Merge into master from pull request #105:
add of_oxm_bsn_lag_id (https://github.com/floodlight/loxigen/pull/105)
diff --git a/wireshark_gen/__init__.py b/wireshark_gen/__init__.py
index b4135ea..c4ff7f4 100644
--- a/wireshark_gen/__init__.py
+++ b/wireshark_gen/__init__.py
@@ -35,7 +35,7 @@
templates_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'templates')
-DissectorField = namedtuple("DissectorField", ["fullname", "name", "type", "base"])
+DissectorField = namedtuple("DissectorField", ["fullname", "name", "type", "base", "enum_table"])
proto_names = { 1: 'of10', 2: 'of11', 3: 'of12', 4: 'of13' }
def make_field_name(wire_version, ofclass_name, member_name):
@@ -43,6 +43,17 @@
ofclass_name[3:],
member_name)
+def get_reader(version, cls, m):
+ """
+ Decide on a reader function to use for the given field
+ """
+ ofproto = of_g.ir[version]
+ enum = ofproto.enum_by_name(m.oftype)
+ if enum and 'wire_type' in enum.params:
+ return "read_" + enum.params['wire_type']
+ else:
+ return "read_" + m.oftype.replace(')', '').replace('(', '_')
+
def get_field_info(version, cls, name, oftype):
"""
Decide on a Wireshark type and base for a given field.
@@ -50,10 +61,14 @@
Returns (type, base)
"""
if oftype.startswith("list"):
- return "bytes", "NONE"
+ return "bytes", "NONE", "nil"
ofproto = of_g.ir[version]
+
enum = ofproto.enum_by_name(oftype)
+ if not enum and (cls, name) in field_info.class_field_to_enum:
+ enum_name = field_info.class_field_to_enum[(cls, name)]
+ enum = ofproto.enum_by_name(enum_name)
if enum:
field_type = "uint32"
@@ -76,7 +91,12 @@
print "WARN missing oftype_to_base for", oftype
field_base = "NONE"
- return field_type, field_base
+ if enum:
+ enum_table = 'enum_v%d_%s' % (version, enum.name)
+ else:
+ enum_table = 'nil'
+
+ return field_type, field_base, enum_table
def create_fields():
r = []
@@ -86,8 +106,8 @@
if isinstance(m, OFPadMember):
continue
fullname = make_field_name(wire_version, ofclass.name, m.name)
- field_type, field_base = get_field_info(wire_version, ofclass.name, m.name, m.oftype)
- r.append(DissectorField(fullname, m.name, field_type, field_base))
+ field_type, field_base, enum_table = get_field_info(wire_version, ofclass.name, m.name, m.oftype)
+ r.append(DissectorField(fullname, m.name, field_type, field_base, enum_table))
return r
diff --git a/wireshark_gen/field_info.py b/wireshark_gen/field_info.py
index 167ff32..28f4cdb 100644
--- a/wireshark_gen/field_info.py
+++ b/wireshark_gen/field_info.py
@@ -81,6 +81,38 @@
"of_bitmap_128_t": "NONE",
}
+# Use enums for certain fields where it isn't specified in the LOXI input
+class_field_to_enum = {
+ ('of_flow_mod', 'type'): 'ofp_type',
+ ('of_error_msg', 'type'): 'ofp_type',
+ ('of_stats_request', 'type'): 'ofp_type',
+ ('of_stats_request', 'stats_type'): 'ofp_stats_type',
+ ('of_stats_request', 'flags'): 'ofp_stats_request_flags',
+ ('of_stats_reply', 'type'): 'ofp_type',
+ ('of_stats_reply', 'stats_type'): 'ofp_stats_type',
+ ('of_stats_reply', 'flags'): 'ofp_stats_reply_flags',
+ ('of_flow_mod', 'table_id'): 'ofp_table',
+ ('of_flow_mod', '_command'): 'ofp_flow_mod_command',
+ ('of_flow_mod', 'out_port'): 'ofp_port',
+ ('of_flow_mod', 'out_group'): 'ofp_group',
+ ('of_error_msg', 'err_type'): 'ofp_error_type',
+ ('of_port_mod', 'type'): 'ofp_type',
+ ('of_hello', 'type'): 'ofp_type',
+ ('of_features_request', 'type'): 'ofp_type',
+ ('of_features_reply', 'type'): 'ofp_type',
+ ('of_barrier_request', 'type'): 'ofp_type',
+ ('of_barrier_reply', 'type'): 'ofp_type',
+ ('of_echo_request', 'type'): 'ofp_type',
+ ('of_echo_reply', 'type'): 'ofp_type',
+ ('of_match_v3', 'type'): 'ofp_match_type',
+ ('of_action_set_nw_ttl', 'type'): 'ofp_action_type',
+ ('of_action_output', 'type'): 'ofp_action_type',
+ ('of_action_group', 'type'): 'ofp_action_type',
+ ('of_action_id', 'type'): 'ofp_action_type',
+ ('of_instruction_apply_actions', 'type'): 'ofp_instruction_type',
+ ('of_instruction_write_actions', 'type'): 'ofp_instruction_type',
+}
+
# Override oftype_to_base for certain field names
field_to_base = {
"eth_type": "HEX",
diff --git a/wireshark_gen/templates/_ofclass_dissector.lua b/wireshark_gen/templates/_ofclass_dissector.lua
index f1c81b0..4aef886 100644
--- a/wireshark_gen/templates/_ofclass_dissector.lua
+++ b/wireshark_gen/templates/_ofclass_dissector.lua
@@ -26,7 +26,7 @@
:: # under the EPL.
::
:: from loxi_ir import *
-:: from wireshark_gen import make_field_name
+:: from wireshark_gen import make_field_name, get_reader
:: attrs = []
:: if ofclass.virtual: attrs.append("virtual")
:: if ofclass.superclass: attrs.append("child")
@@ -45,7 +45,7 @@
:: continue
:: #endif
:: field_name = make_field_name(version, ofclass.name, m.name)
-:: reader_name = "read_" + m.oftype.replace(')', '').replace('(', '_')
+:: reader_name = get_reader(version, ofclass, m)
${reader_name}(reader, ${version}, subtree, '${field_name}')
:: #endfor
return '${ofclass.name}'
diff --git a/wireshark_gen/templates/_oftype_readers.lua b/wireshark_gen/templates/_oftype_readers.lua
index 1db9f1f..c258953 100644
--- a/wireshark_gen/templates/_oftype_readers.lua
+++ b/wireshark_gen/templates/_oftype_readers.lua
@@ -89,6 +89,10 @@
read_scalar(reader, subtree, field_name, 4)
end
+function read_of_ipv6_t(reader, version, subtree, field_name)
+ read_scalar(reader, subtree, field_name, 16)
+end
+
function read_of_fm_cmd_t(reader, version, subtree, field_name)
if version == 1 then
read_scalar(reader, subtree, field_name, 2)
@@ -97,10 +101,6 @@
end
end
-function read_ofp_flow_mod_flags(reader, version, subtree, field_name)
- read_scalar(reader, subtree, field_name, 2)
-end
-
function read_list_of_action_t(reader, version, subtree, field_name)
if reader.is_empty() then
return
@@ -111,9 +111,10 @@
local action_len = reader.peek(2, 2):uint()
local child_reader = reader.slice(action_len)
local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
- local info = dissect_of_action_v1(child_reader, child_subtree)
+ local info = dissect_of_action(child_reader, child_subtree, version)
child_subtree:set_text(info)
end
+ list:set_text("List of actions")
end
function read_list_of_port_desc_t(reader, version, subtree, field_name)
@@ -130,14 +131,19 @@
end
local list_len = reader.peek(-2,2):uint()
local reader2 = reader.slice(list_len - 4)
- local list = subtree:add(fields[field_name], reader2.peek_all(0))
+ local list = nil
+ if not reader2.is_empty() then
+ list = subtree:add(fields[field_name], reader2.peek_all(0))
+ end
while not reader2.is_empty() do
local match_len = 4 + reader2.peek(3,1):uint()
local child_reader = reader2.slice(match_len)
local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
- local info = dissect_of_oxm_v3(child_reader, child_subtree)
+ local info = dissect_of_oxm(child_reader, child_subtree, version)
child_subtree:set_text(info)
end
+ subtree:set_text("OXM")
+ list:set_text("List of matches")
reader.skip_align()
end
@@ -145,7 +151,7 @@
if reader.is_empty() then
return
end
- if not reader.is_empty() then
- subtree:add(fields[field_name], reader.read_all())
- end
+ local child_subtree = subtree:add(fields[field_name], reader.peek_all(0))
+ local info = dissect_of_instruction(reader, child_subtree, version)
+ child_subtree:set_text("Instructions")
end
diff --git a/wireshark_gen/templates/openflow.lua b/wireshark_gen/templates/openflow.lua
index bf1cdf5..067dbdd 100644
--- a/wireshark_gen/templates/openflow.lua
+++ b/wireshark_gen/templates/openflow.lua
@@ -54,40 +54,10 @@
:: #endfor
-:: values = {
-:: 'of13.flow_mod.type': 'enum_v4_ofp_type',
-:: 'of13.error_msg.type': 'enum_v4_ofp_type',
-:: 'of13.stats_request.type': 'enum_v4_ofp_type',
-:: 'of13.stats_request.stats_type': 'enum_v4_ofp_stats_type',
-:: 'of13.stats_request.flags': 'enum_v4_ofp_stats_request_flags',
-:: 'of13.stats_reply.type': 'enum_v4_ofp_type',
-:: 'of13.stats_reply.stats_type': 'enum_v4_ofp_stats_type',
-:: 'of13.stats_reply.flags': 'enum_v4_ofp_stats_reply_flags',
-:: 'of13.flow_mod.table_id': 'enum_v4_ofp_table',
-:: 'of13.flow_mod._command': 'enum_v4_ofp_flow_mod_command',
-:: 'of13.flow_mod.out_port': 'enum_v4_ofp_port',
-:: 'of13.flow_mod.out_group': 'enum_v4_ofp_group',
-:: 'of13.error_msg.err_type': 'enum_v4_ofp_error_type',
-:: 'of13.port_mod.type': 'enum_v4_ofp_type',
-:: 'of13.hello.type': 'enum_v4_ofp_type',
-:: 'of13.features_request.type': 'enum_v4_ofp_type',
-:: 'of13.features_reply.type': 'enum_v4_ofp_type',
-:: 'of13.barrier_request.type': 'enum_v4_ofp_type',
-:: 'of13.barrier_reply.type': 'enum_v4_ofp_type',
-:: 'of13.echo_request.type': 'enum_v4_ofp_type',
-:: 'of13.echo_reply.type': 'enum_v4_ofp_type',
-:: 'of13.match_t.type': 'enum_v4_ofp_match_type'
-:: }
-
-
fields = {}
:: for field in fields:
:: if field.type in ["uint8", "uint16", "uint32", "uint64"]:
-:: if field.fullname in values:
-fields[${repr(field.fullname)}] = ProtoField.${field.type}("${field.fullname}", "${field.name}", base.${field.base}, ${values[field.fullname]})
-:: else:
-fields[${repr(field.fullname)}] = ProtoField.${field.type}("${field.fullname}", "${field.name}", base.${field.base})
-:: #endif
+fields[${repr(field.fullname)}] = ProtoField.${field.type}("${field.fullname}", "${field.name}", base.${field.base}, ${field.enum_table})
:: elif field.type in ["ipv4", "ipv6", "ether", "bytes", "stringz"]:
fields[${repr(field.fullname)}] = ProtoField.${field.type}("${field.fullname}", "${field.name}")
:: else:
@@ -131,6 +101,24 @@
:: #endfor
}
+local of_oxm_dissectors = {
+:: for version in ir:
+ [${version}] = of_oxm_v${version}_dissectors,
+:: #endfor
+}
+
+local of_action_dissectors = {
+:: for version in ir:
+ [${version}] = of_action_v${version}_dissectors,
+:: #endfor
+}
+
+local of_instruction_dissectors = {
+:: for version in ir:
+ [${version}] = of_instruction_v${version}_dissectors,
+:: #endfor
+}
+
function dissect_of_message(buf, root)
local reader = OFReader.new(buf)
local subtree = root:add(p_of, buf(0))
@@ -150,16 +138,36 @@
return protocol, info
end
-function dissect_of_oxm_v3(reader, subtree)
+function dissect_of_oxm(reader, subtree, version_val)
local type_val = reader.peek(0,4):uint()
-
local info = "unknown"
- if of_oxm_v3_dissectors[type_val] then
- info = of_oxm_v3_dissectors[type_val](reader, subtree)
+ if of_oxm_dissectors[version_val] and of_oxm_dissectors[version_val][type_val] then
+ info = of_oxm_dissectors[version_val][type_val](reader, subtree)
end
return info
end
+
+function dissect_of_action(reader, subtree, version_val)
+ local type_val = reader.peek(0,2):uint()
+ local info = "unknown"
+ if of_action_dissectors[version_val] and of_action_dissectors[version_val][type_val] then
+ info = of_action_dissectors[version_val][type_val](reader, subtree)
+ end
+
+ return info
+end
+
+function dissect_of_instruction(reader, subtree, version_val)
+ local type_val = reader.peek(0,2):uint()
+ local info = "unknown"
+ if of_instruction_dissectors[version_val] and of_instruction_dissectors[version_val][type_val] then
+ info = of_instruction_dissectors[version_val][type_val](reader, subtree)
+ end
+
+ return info
+end
+
-- of dissector function
function p_of.dissector (buf, pkt, root)
local offset = 0