Merge into master from pull request #151:
automatically generate action/instruction ID classes (https://github.com/floodlight/loxigen/pull/151)
diff --git a/c_gen/build_of_g.py b/c_gen/build_of_g.py
index 2a272ce..f117bfd 100755
--- a/c_gen/build_of_g.py
+++ b/c_gen/build_of_g.py
@@ -443,28 +443,6 @@
of_g.ordered_classes[wire_version].append(new_cls)
classes[new_cls] = classes[cls]
- # Generate action_id classes for OF 1.3
- for wire_version, ordered_classes in of_g.ordered_classes.items():
- if not wire_version in [of_g.VERSION_1_3]:
- continue
- classes = versions[of_g.of_version_wire2name[wire_version]]['classes']
- for cls in ordered_classes:
- if not loxi_utils.class_is_action(cls):
- continue
- action = cls[10:]
- if action == '' or action == 'header':
- continue
- name = "of_action_id_" + action
- members = classes["of_action"][:]
- of_g.ordered_classes[wire_version].append(name)
- if type_maps.action_id_is_extension(name, wire_version):
- # Copy the base action classes thru subtype
- members = classes["of_action_" + action][:4]
- classes[name] = members
-
- # @fixme If we support extended actions in OF 1.3, need to add IDs
- # for them here
-
for wire_version in of_g.wire_ver_map.keys():
version_name = of_g.of_version_wire2name[wire_version]
calculate_offsets_and_lengths(
diff --git a/c_gen/loxi_utils_legacy.py b/c_gen/loxi_utils_legacy.py
index e20155d..9abca52 100644
--- a/c_gen/loxi_utils_legacy.py
+++ b/c_gen/loxi_utils_legacy.py
@@ -180,6 +180,8 @@
"""
Return True if cls_name is an instruction object
"""
+ if cls.find("of_instruction_id") == 0:
+ return False
if cls.find("of_instruction") == 0:
return True
diff --git a/c_gen/type_maps.py b/c_gen/type_maps.py
index ae5f481..e709b70 100644
--- a/c_gen/type_maps.py
+++ b/c_gen/type_maps.py
@@ -60,21 +60,25 @@
of_g.VERSION_1_3:dict()
}
-# HACK shared between actions and action_ids
-of_1_3_action_types = dict()
+instruction_id_types = {
+ of_g.VERSION_1_0:dict(),
+ of_g.VERSION_1_1:dict(),
+ of_g.VERSION_1_2:dict(),
+ of_g.VERSION_1_3:dict()
+ }
action_types = {
of_g.VERSION_1_0:dict(),
of_g.VERSION_1_1:dict(),
of_g.VERSION_1_2:dict(),
- of_g.VERSION_1_3:of_1_3_action_types
+ of_g.VERSION_1_3:dict(),
}
action_id_types = {
of_g.VERSION_1_0:dict(),
of_g.VERSION_1_1:dict(),
of_g.VERSION_1_2:dict(),
- of_g.VERSION_1_3:of_1_3_action_types
+ of_g.VERSION_1_3:dict(),
}
queue_prop_types = {
@@ -134,6 +138,7 @@
# All inheritance data for non-messages
inheritance_data = dict(
of_instruction = instruction_types,
+ of_instruction_id = instruction_id_types,
of_action = action_types,
of_action_id = action_id_types,
of_oxm = oxm_types,
diff --git a/java_gen/java_model.py b/java_gen/java_model.py
index 8f5434e..7aa4857 100644
--- a/java_gen/java_model.py
+++ b/java_gen/java_model.py
@@ -470,6 +470,15 @@
return ("action", "OFActionExperimenter", None)
else:
return ("action", "OFAction", None)
+ elif self.ir_class.is_instanceof("of_action_id"):
+ if self.ir_class.is_subclassof('of_action_id_bsn'):
+ return ("actionid", "OFActionIdBsn", None)
+ elif self.ir_class.is_subclassof('of_action_id_nicira'):
+ return ("actionid", "OFActionIdNicira", None)
+ elif self.ir_class.is_subclassof('of_action_id_experimenter'):
+ return ("actionid", "OFActionIdExperimenter", None)
+ else:
+ return ("actionid", "OFActionId", None)
elif self.ir_class.is_instruction:
if self.ir_class.is_subclassof('of_instruction_bsn'):
return ("instruction", "OFInstructionBsn", None)
@@ -477,6 +486,13 @@
return ("instruction", "OFInstructionExperimenter", None)
else:
return ("instruction", "OFInstruction", None)
+ elif self.ir_class.is_instanceof('of_instruction_id'):
+ if self.ir_class.is_subclassof('of_instruction_id_bsn'):
+ return ("instructionid", "OFInstructionIdBsn", None)
+ elif self.ir_class.is_subclassof('of_instruction_id_experimenter'):
+ return ("instructionid", "OFInstructionIdExperimenter", None)
+ else:
+ return ("instructionid", "OFInstructionId", None)
elif re.match(r'OFBsnVport.+$', self.name):
return ("", "OFBsnVport", None)
elif self.name == "OFOxm":
diff --git a/java_gen/templates/_imports.java b/java_gen/templates/_imports.java
index cf7334d..af529bc 100644
--- a/java_gen/templates/_imports.java
+++ b/java_gen/templates/_imports.java
@@ -7,8 +7,10 @@
import java.util.Map;
import org.projectfloodlight.openflow.protocol.*;
import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
import org.projectfloodlight.openflow.protocol.meterband.*;
import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
import org.projectfloodlight.openflow.protocol.match.*;
import org.projectfloodlight.openflow.protocol.oxm.*;
import org.projectfloodlight.openflow.protocol.queueprop.*;
diff --git a/lang_python.py b/lang_python.py
index f40cecc..9087b43 100644
--- a/lang_python.py
+++ b/lang_python.py
@@ -50,6 +50,8 @@
of12: ... # (code generation incomplete)
oxm.py # OXM classes
of13: ... # (code generation incomplete)
+ action_id.py # Action ID classes
+ instruction_id.py # Instruction ID classes
meter_band.py # Meter band classes
The user will add the pyloxi directory to PYTHONPATH. Then they can
@@ -83,7 +85,7 @@
1: ["action", "common", "const", "message", "util"],
2: ["action", "common", "const", "instruction", "message", "util"],
3: ["action", "common", "const", "instruction", "message", "oxm", "util"],
- 4: ["action", "common", "const", "instruction", "message", "meter_band", "oxm", "util"],
+ 4: ["action", "action_id", "common", "const", "instruction", "instruction_id", "message", "meter_band", "oxm", "util"],
}
def make_gen(name, version):
diff --git a/loxi_ir/ir.py b/loxi_ir/ir.py
index df1c77d..ebd4f85 100644
--- a/loxi_ir/ir.py
+++ b/loxi_ir/ir.py
@@ -419,9 +419,52 @@
build_touch_classes.remove(name)
return c
+ def build_id_class(orig_name, base_name):
+ name = base_name + '_id' + orig_name[len(base_name):]
+ if name in name_classes:
+ return name_classes[name]
+ orig_fe, _ = name_frontend_classes[orig_name]
+
+ if orig_fe.superclass:
+ superclass_name = base_name + '_id' + orig_fe.superclass[len(base_name):]
+ superclass = build_id_class(orig_fe.superclass, base_name)
+ else:
+ superclass_name = None
+ superclass = None
+
+ fe = frontend_ir.OFClass(
+ name=name,
+ superclass=superclass_name,
+ members=[m for m in orig_fe.members if not isinstance(m, frontend_ir.OFDataMember)],
+ virtual=orig_fe.virtual,
+ params={})
+
+ base_length, is_fixed_length, member_lengths = \
+ ir_offset.calc_lengths(version, fe, name_classes, name_enums)
+ assert fe.virtual or is_fixed_length
+
+ members = []
+ c = OFClass(name=fe.name, superclass=superclass,
+ members=members, virtual=fe.virtual, params=fe.params,
+ is_fixed_length=is_fixed_length, base_length=base_length)
+
+ members.extend( build_member(c, fe_member, member_lengths[fe_member])
+ for fe_member in fe.members)
+
+ name_classes[name] = c
+ return c
+
+ id_class_roots = ["of_action", "of_instruction"]
+
for name in sorted(name_frontend_classes.keys()):
c = build_class(name)
+ # Build ID classes for OF 1.3+
+ if version.wire_version >= 4:
+ for root in id_class_roots:
+ if c.is_instanceof(root):
+ build_id_class(name, root)
+
protocol = OFProtocol(version=version, classes=tuple(name_classes.values()), enums=tuple(name_enums.values()))
for e in chain(protocol.classes, protocol.enums):
e.protocol = protocol
diff --git a/py_gen/codegen.py b/py_gen/codegen.py
index 2c4a135..de3fdba 100644
--- a/py_gen/codegen.py
+++ b/py_gen/codegen.py
@@ -40,8 +40,10 @@
roots = {
'of_header': 'message',
'of_action': 'action',
+ 'of_action_id': 'action_id',
'of_oxm': 'oxm',
'of_instruction': 'instruction',
+ 'of_instruction_id': 'instruction_id',
'of_meter_band': 'meter_band',
}
@@ -74,6 +76,11 @@
ofclasses=modules_by_version[version]['action'],
version=version)
+def generate_action_id(out, name, version):
+ util.render_template(out, 'module.py',
+ ofclasses=modules_by_version[version]['action_id'],
+ version=version)
+
def generate_oxm(out, name, version):
util.render_template(out, 'module.py',
ofclasses=modules_by_version[version]['oxm'],
@@ -94,6 +101,11 @@
ofclasses=modules_by_version[version]['instruction'],
version=version)
+def generate_instruction_id(out, name, version):
+ util.render_template(out, 'module.py',
+ ofclasses=modules_by_version[version]['instruction_id'],
+ version=version)
+
def generate_message(out, name, version):
util.render_template(out, 'module.py',
ofclasses=modules_by_version[version]['message'],
diff --git a/py_gen/templates/module.py b/py_gen/templates/module.py
index 252bf0d..30c45ad 100644
--- a/py_gen/templates/module.py
+++ b/py_gen/templates/module.py
@@ -43,6 +43,8 @@
import oxm
:: #endif
:: if version >= OFVersions.VERSION_1_3:
+import action_id
+import instruction_id
import meter_band
:: #endif
import util
diff --git a/py_gen/templates/util.py b/py_gen/templates/util.py
index 8ad246a..ed2698a 100644
--- a/py_gen/templates/util.py
+++ b/py_gen/templates/util.py
@@ -41,6 +41,8 @@
import oxm
:: #endif
:: if version >= OFVersions.VERSION_1_3:
+import action_id
+import instruction_id
import meter_band
:: #endif