Merge remote-tracking branch 'origin/master' into loci-split
Conflicts:
c_gen/codegen.py
diff --git a/c_gen/codegen.py b/c_gen/codegen.py
index 2bc62ca..3249747 100644
--- a/c_gen/codegen.py
+++ b/c_gen/codegen.py
@@ -62,7 +62,7 @@
# Special case for version
pwtms.append(PushWireTypesMember(m.name, m.offset, m.length, "obj->version"))
else:
- pwtms.append(PushWireTypesMember(m.name, m.offset, m.length, m.value))
+ pwtms.append(PushWireTypesMember(m.name, m.offset, m.length, hex(m.value)))
type_members_by_version[version] = pwtms
# Merge versions with identical type members
diff --git a/c_gen/templates/loci_show.h b/c_gen/templates/loci_show.h
index 3d55da8..a66c321 100644
--- a/c_gen/templates/loci_show.h
+++ b/c_gen/templates/loci_show.h
@@ -371,5 +371,7 @@
#define LOCI_SHOW_u16_partner_port_num(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
#define LOCI_SHOW_u16_partner_key(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
#define LOCI_SHOW_u64_time_ms(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
+#define LOCI_SHOW_desc_str_uri(writer, cookie, val) LOCI_SHOW_desc_str(writer, cookie, val)
+#define LOCI_SHOW_u8_state(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
#endif /* _LOCI_SHOW_H_ */
diff --git a/loxi_ir/ir.py b/loxi_ir/ir.py
index 6fae92b..6a053c6 100644
--- a/loxi_ir/ir.py
+++ b/loxi_ir/ir.py
@@ -176,6 +176,10 @@
raise Exception("Not a fixed length class: {}".format(self.name))
@property
+ def length_member(self):
+ return find(lambda m: type(m) == OFLengthMember, self.members)
+
+ @property
def has_internal_alignment(self):
return self.params.get('length_includes_align') == 'True'
diff --git a/openflow_input/bsn_controller_connections b/openflow_input/bsn_controller_connections
new file mode 100644
index 0000000..eae315e
--- /dev/null
+++ b/openflow_input/bsn_controller_connections
@@ -0,0 +1,71 @@
+// Copyright 2013, Big Switch Networks, Inc.
+//
+// LoxiGen is licensed under the Eclipse Public License,
+// version 1.0 (EPL), with the following special exception:
+//
+// LOXI Exception
+//
+// As a special exception to the terms of the EPL, you may
+// distribute libraries generated by LoxiGen (LoxiGen Libraries)
+// under the terms of your choice, provided that copyright and
+// licensing notices generated by LoxiGen are not altered or removed
+// from the LoxiGen Libraries and the notice provided below is (i)
+// included in the LoxiGen Libraries, if distributed in source code
+// form and (ii) included in any documentation for the LoxiGen
+// Libraries, if distributed in binary form.
+//
+// Notice: "Copyright 2013, Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler."
+//
+// You may not use this file except in compliance with the EPL or
+// LOXI Exception. You may obtain a copy of the EPL at:
+//
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an "AS
+// IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+// express or implied. See the EPL for the specific language
+// governing permissions and limitations under the EPL.
+
+// Retrieve a list of configured controller connections and their status.
+// When auxiliary connections are used there may be multiple connections
+// to the same controller. All connections to a given controller will
+// share the same role (so there may be multiple master connections in
+// the list).
+
+// The URIs are of the form tcp://1.2.3.4:6553
+
+#version 4
+
+enum ofp_bsn_controller_connection_state(wire_type=uint8_t) {
+ OFP_BSN_CONTROLLER_CONNECTION_STATE_DISCONNECTED = 0,
+ OFP_BSN_CONTROLLER_CONNECTION_STATE_CONNECTED = 1,
+};
+
+struct of_bsn_controller_connections_request : of_bsn_header {
+ uint8_t version;
+ uint8_t type == 4;
+ uint16_t length;
+ uint32_t xid;
+ uint32_t experimenter == 0x5c16c7;
+ uint32_t subtype == 56;
+};
+
+struct of_bsn_controller_connection {
+ enum ofp_bsn_controller_connection_state state;
+ uint8_t auxiliary_id;
+ pad(2);
+ enum ofp_controller_role role;
+ of_desc_str_t uri;
+};
+
+struct of_bsn_controller_connections_reply : of_bsn_header {
+ uint8_t version;
+ uint8_t type == 4;
+ uint16_t length;
+ uint32_t xid;
+ uint32_t experimenter == 0x5c16c7;
+ uint32_t subtype == 57;
+ list(of_bsn_controller_connection_t) connections;
+};
diff --git a/openflow_input/bsn_role_status b/openflow_input/bsn_role_status
new file mode 100644
index 0000000..f53ff23
--- /dev/null
+++ b/openflow_input/bsn_role_status
@@ -0,0 +1,55 @@
+// Copyright 2013, Big Switch Networks, Inc.
+//
+// LoxiGen is licensed under the Eclipse Public License,
+// version 1.0 (EPL), with the following special exception:
+//
+// LOXI Exception
+//
+// As a special exception to the terms of the EPL, you may
+// distribute libraries generated by LoxiGen (LoxiGen Libraries)
+// under the terms of your choice, provided that copyright and
+// licensing notices generated by LoxiGen are not altered or removed
+// from the LoxiGen Libraries and the notice provided below is (i)
+// included in the LoxiGen Libraries, if distributed in source code
+// form and (ii) included in any documentation for the LoxiGen
+// Libraries, if distributed in binary form.
+//
+// Notice: "Copyright 2013, Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler."
+//
+// You may not use this file except in compliance with the EPL or
+// LOXI Exception. You may obtain a copy of the EPL at:
+//
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an "AS
+// IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+// express or implied. See the EPL for the specific language
+// governing permissions and limitations under the EPL.
+
+// Backport the OpenFlow 1.4 role status message
+//
+// This message will be sent when a controller's role changes for any reason
+// other than it using OFPT_ROLE_REQUEST.
+
+#version 4
+
+enum ofp_bsn_controller_role_reason(wire_type=uint8_t) {
+ OFP_BSN_CONTROLLER_ROLE_REASON_MASTER_REQUEST = 0,
+ OFP_BSN_CONTROLLER_ROLE_REASON_CONFIG = 1,
+ OFP_BSN_CONTROLLER_ROLE_REASON_EXPERIMENTER = 2,
+};
+
+struct of_bsn_role_status : of_bsn_header {
+ uint8_t version;
+ uint8_t type == 4;
+ uint16_t length;
+ uint32_t xid;
+ uint32_t experimenter == 0x5c16c7;
+ uint32_t subtype == 55;
+ enum ofp_controller_role role;
+ enum ofp_bsn_controller_role_reason reason;
+ pad(3);
+ uint64_t generation_id;
+};
diff --git a/test_data/of10/packet_in.data b/test_data/of10/packet_in.data
index a8de82c..d5ccf32 100644
--- a/test_data/of10/packet_in.data
+++ b/test_data/of10/packet_in.data
@@ -18,7 +18,7 @@
data='abc')
-- c
obj = of_packet_in_new(OF_VERSION_1_0);
-of_packet_in_buffer_id_set(obj, 2882400001);
+of_packet_in_buffer_id_set(obj, 0xabcdef01);
{
of_octets_t data = { .bytes=3, .data=(uint8_t *)"\x61\x62\x63" };
of_packet_in_data_set(obj, &data);
diff --git a/test_data/of10/packet_out.data b/test_data/of10/packet_out.data
index fdd1c3d..a3c642b 100644
--- a/test_data/of10/packet_out.data
+++ b/test_data/of10/packet_out.data
@@ -25,7 +25,7 @@
data='abc')
-- c
obj = of_packet_out_new(OF_VERSION_1_0);
-of_packet_out_buffer_id_set(obj, 2882400001);
+of_packet_out_buffer_id_set(obj, 0xabcdef01);
of_packet_out_in_port_set(obj, 65534);
of_packet_out_xid_set(obj, 305419896);
{
diff --git a/test_data/of10/port_mod.data b/test_data/of10/port_mod.data
index 53e09ce..754e139 100644
--- a/test_data/of10/port_mod.data
+++ b/test_data/of10/port_mod.data
@@ -18,12 +18,12 @@
advertise=0xCAFE6789)
-- c
obj = of_port_mod_new(OF_VERSION_1_0);
-of_port_mod_advertise_set(obj, 3405670281);
-of_port_mod_config_set(obj, 2427178479);
+of_port_mod_advertise_set(obj, 0xCAFE6789);
+of_port_mod_config_set(obj, 0x90ABCDEF);
{
of_mac_addr_t hw_addr = { { 1, 2, 3, 4, 5, 6 } };
of_port_mod_hw_addr_set(obj, hw_addr);
}
-of_port_mod_mask_set(obj, 4279369489);
+of_port_mod_mask_set(obj, 0xFF11FF11);
of_port_mod_port_no_set(obj, 65533);
of_port_mod_xid_set(obj, 2);
diff --git a/wireshark_gen/field_info.py b/wireshark_gen/field_info.py
index cf3192c..94e5243 100644
--- a/wireshark_gen/field_info.py
+++ b/wireshark_gen/field_info.py
@@ -104,6 +104,9 @@
('of_barrier_reply', 'type'): 'ofp_type',
('of_echo_request', 'type'): 'ofp_type',
('of_echo_reply', 'type'): 'ofp_type',
+ ('of_flow_delete', 'type'): 'ofp_type',
+ ('of_flow_add', 'type'): 'ofp_type',
+ ('of_port_status', 'type'): 'ofp_type',
('of_match_v3', 'type'): 'ofp_match_type',
('of_action_set_nw_ttl', 'type'): 'ofp_action_type',
('of_action_set_field', 'type'): 'ofp_action_type',
diff --git a/wireshark_gen/templates/_ofclass_dissector.lua b/wireshark_gen/templates/_ofclass_dissector.lua
index 1e1520f..d327b49 100644
--- a/wireshark_gen/templates/_ofclass_dissector.lua
+++ b/wireshark_gen/templates/_ofclass_dissector.lua
@@ -39,17 +39,39 @@
-- Discriminator is ${ofclass.discriminator.name}
:: #endif
function ${name}(reader, subtree)
+:: field_length_members = []
:: if ofclass.virtual:
return ${ofclass.name}_v${version.wire_version}_dissectors[reader.peek(${ofclass.discriminator.offset},${ofclass.discriminator.length}):uint()](reader, subtree)
:: else:
+:: if not ofclass.is_fixed_length:
+ local _length = reader.peek(${ofclass.length_member.offset}, ${ofclass.length_member.base_length}):uint()
+ local orig_reader = reader
+ reader = orig_reader.slice(_length)
+:: #endif
:: for m in ofclass.members:
:: if isinstance(m, OFPadMember):
reader.skip(${m.length})
:: continue
:: #endif
+:: if isinstance(m, OFFieldLengthMember):
+ local _${m.field_name}_length = reader.peek(0, ${m.base_length}):uint()
+:: field_length_members.append(m.field_name)
+:: #endif
+:: if m.oftype.startswith("list"):
+:: class_name = m.oftype.replace('_t)', '').replace('(', '').replace('list', '')
+:: if m.name in field_length_members:
+ read_list(reader.slice(_${m.name}_length), dissect_${class_name}_v${version.wire_version}, subtree, '${class_name}')
+:: else:
+ read_list(reader, dissect_${class_name}_v${version.wire_version}, subtree, '${class_name}')
+:: #endif
+:: if ofclass.has_external_alignment:
+ orig_reader.skip_align()
+:: #endif
+:: else:
:: field_name = make_field_name(version, ofclass.name, m.name)
:: reader_name = get_reader(version, ofclass, m)
${reader_name}(reader, ${version.wire_version}, subtree, '${field_name}')
+:: #endif
:: #endfor
return '${ofclass.name}'
:: #endif
diff --git a/wireshark_gen/templates/_oftype_readers.lua b/wireshark_gen/templates/_oftype_readers.lua
index 10f13ca..6c7fb5c 100644
--- a/wireshark_gen/templates/_oftype_readers.lua
+++ b/wireshark_gen/templates/_oftype_readers.lua
@@ -57,11 +57,11 @@
function read_of_match_t(reader, version, subtree, field_name)
if version == 1 then
- dissect_of_match_v1_v1(reader, subtree:add(fields[field_name]))
+ dissect_of_match_v1_v1(reader, subtree:add("of_match"))
elseif version == 2 then
- dissect_of_match_v2_v2(reader, subtree:add(fields[field_name]))
+ dissect_of_match_v2_v2(reader, subtree:add("of_match"))
elseif version >= 3 then
- dissect_of_match_v3_v3(reader, subtree:add(fields[field_name]))
+ dissect_of_match_v3_v3(reader, subtree:add("of_match"))
end
end
@@ -105,122 +105,6 @@
end
end
-function read_list_of_action_t(reader, version, subtree, field_name)
- if reader.is_empty() then
- return
- end
-
- local list_len = 0
-
- if string.find(field_name,'packet_out') then
- if version == 1 then
- list_len = reader.peek(-2,2):uint()
- else
- list_len = reader.peek(-8,2):uint()
- end
- end
-
- local list = nil
- local reader2 = nil
-
- if list_len == 0 then
- list = subtree:add(fields[field_name], reader.peek_all(0))
- reader2 = reader
- else
- list = subtree:add(fields[field_name], reader.peek(0, list_len))
- reader2 = reader.slice(list_len)
- end
-
- while not reader2.is_empty() do
- local action_len = reader2.peek(2, 2):uint()
- local child_reader = reader2.slice(action_len)
- local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
- local info = of_action_dissectors[version](child_reader, child_subtree)
- 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)
- if reader.is_empty() then
- return
- end
- local list = subtree:add(fields[field_name], reader.peek_all(0))
- list:set_text("List of port descriptions")
- while not reader.is_empty() do
- local port_desc_len = 64
- local child_reader = reader.slice(port_desc_len)
- local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
- local info = of_port_desc_dissectors[version](child_reader, child_subtree)
- child_subtree:set_text(info)
- end
-end
-
-function read_list_of_flow_stats_entry_t(reader, version, subtree, field_name)
- if reader.is_empty() then
- return
- end
- local list = subtree:add(fields[field_name], reader.peek_all(0))
- list:set_text("List of flow stats entries")
- while not reader.is_empty() do
- local stats_len = reader.peek(0,2):uint()
- local child_reader = reader.slice(stats_len)
- local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
- local info = of_flow_stats_entry_dissectors[version](child_reader, child_subtree)
- child_subtree:set_text(info)
- end
-end
-
-function read_list_of_port_stats_entry_t(reader, version, subtree, field_name)
- if reader.is_empty() then
- return
- end
- local list = subtree:add(fields[field_name], reader.peek_all(0))
- list:set_text("List of port stats entries")
- while not reader.is_empty() do
- local stats_len = 112
- local child_reader = reader.slice(stats_len)
- local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
- local info = of_port_stats_entry_dissectors[version](child_reader, child_subtree)
- child_subtree:set_text(info)
- end
-end
-
-function read_list_of_table_stats_entry_t(reader, version, subtree, field_name)
- if reader.is_empty() then
- return
- end
- local list = subtree:add(fields[field_name], reader.peek_all(0))
- list:set_text("List of table stats entries")
- while not reader.is_empty() do
- local stats_len = 24
- local child_reader = reader.slice(stats_len)
- local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
- local info = of_table_stats_entry_dissectors[version](child_reader, child_subtree)
- child_subtree:set_text(info)
- end
-end
-
-function read_list_of_queue_stats_entry_t(reader, version, subtree, field_name)
- if reader.is_empty() then
- return
- end
- local list = subtree:add(fields[field_name], reader.peek_all(0))
- list:set_text("List of flow stats entries")
- while not reader.is_empty() do
- local stats_len = 40
- local child_reader = reader.slice(stats_len)
- local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
- local info = of_queue_stats_entry_dissectors[version](child_reader, child_subtree)
- child_subtree:set_text(info)
- end
-end
-
-function read_list_of_packet_queue_t(reader, version, subtree, field_name)
- -- TODO
- read_of_octets_t()
-end
-
function read_of_desc_str_t(reader, version, subtree, field_name)
read_scalar(reader, subtree, field_name, 256)
end
@@ -229,50 +113,13 @@
read_scalar(reader, subtree, field_name, 32)
end
-function read_list_of_oxm_t(reader, version, subtree, field_name)
- if reader.is_empty() then
- return
- end
- local list_len = reader.peek(-2,2):uint()
- local reader2 = reader.slice(list_len - 4)
- local list = nil
- if not reader2.is_empty() then
- list = subtree:add(fields[field_name], reader2.peek_all(0))
- list:set_text("List of matches")
- 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 = of_oxm_dissectors[version](child_reader, child_subtree)
- child_subtree:set_text(info)
- end
- subtree:set_text("OXM")
- reader.skip_align()
-end
-
-function read_list_of_instruction_t(reader, version, subtree, field_name)
+function read_of_port_desc_t(reader, version, subtree, field_name)
if reader.is_empty() then
return
end
local child_subtree = subtree:add(fields[field_name], reader.peek_all(0))
- local info = of_instruction_dissectors[version](reader, child_subtree)
- child_subtree:set_text("Instructions")
-end
-
-function read_list_of_bucket_t(reader, version, subtree, field_name)
- if reader.is_empty() then
- return
- end
- local bucket_list_subtree = subtree:add(fields[field_name], reader.peek_all(0))
- bucket_list_subtree:set_text("List of buckets")
- while not reader.is_empty() do
- local bucket_len = reader.peek(0,2):uint()
- local child_reader = reader.slice(bucket_len)
- local child_subtree = bucket_list_subtree:add(fields[field_name], child_reader.peek_all(0))
- local info = of_bucket_dissectors[version](child_reader, child_subtree)
- child_subtree:set_text(info)
- end
+ local info = of_port_desc_dissectors[version](reader, child_subtree)
+ child_subtree:set_text(info)
end
function read_of_oxm_t(reader, version, subtree, field_name)
@@ -283,3 +130,16 @@
local info = of_oxm_dissectors[version](reader, child_subtree)
child_subtree:set_text(info)
end
+
+function read_list(reader, dissector, subtree, field_name)
+ if not reader.is_empty() then
+ local list_subtree = subtree:add(field_name .. " list", reader.peek_all(0))
+ while not reader.is_empty() do
+ local atom_subtree = list_subtree:add(field_name, reader.peek_all(0))
+ local info = dissector(reader, atom_subtree)
+ atom_subtree:set_text(info)
+ end
+ else
+ return
+ end
+end
diff --git a/wireshark_gen/templates/openflow.lua b/wireshark_gen/templates/openflow.lua
index bdbe2ec..cad61a5 100644
--- a/wireshark_gen/templates/openflow.lua
+++ b/wireshark_gen/templates/openflow.lua
@@ -106,69 +106,15 @@
:: #endfor
}
-local of_oxm_dissectors = {
-:: for version in ir:
- [${version.wire_version}] = dissect_of_oxm_v${version.wire_version},
-:: #endfor
-}
-
-local of_action_dissectors = {
-:: for version in ir:
- [${version.wire_version}] = dissect_of_action_v${version.wire_version},
-:: #endfor
-}
-
-local of_instruction_dissectors = {
-:: for version in ir:
- [${version.wire_version}] = dissect_of_instruction_v${version.wire_version},
-:: #endfor
-}
-
-local of_bucket_dissectors = {
-:: for version in ir:
- [${version.wire_version}] = dissect_of_bucket_v${version.wire_version},
-:: #endfor
-}
-
local of_port_desc_dissectors = {
:: for version in ir:
[${version.wire_version}] = dissect_of_port_desc_v${version.wire_version},
:: #endfor
}
-local of_stats_reply_dissectors = {
+local of_oxm_dissectors = {
:: for version in ir:
- [${version.wire_version}] = dissect_of_stats_reply_v${version.wire_version},
-:: #endfor
-}
-
-local of_stats_request_dissectors = {
-:: for version in ir:
- [${version.wire_version}] = dissect_of_stats_request_v${version.wire_version},
-:: #endfor
-}
-
-local of_flow_stats_entry_dissectors = {
-:: for version in ir:
- [${version.wire_version}] = dissect_of_flow_stats_entry_v${version.wire_version},
-:: #endfor
-}
-
-local of_port_stats_entry_dissectors = {
-:: for version in ir:
- [${version.wire_version}] = dissect_of_port_stats_entry_v${version.wire_version},
-:: #endfor
-}
-
-local of_table_stats_entry_dissectors = {
-:: for version in ir:
- [${version.wire_version}] = dissect_of_table_stats_entry_v${version.wire_version},
-:: #endfor
-}
-
-local of_queue_stats_entry_dissectors = {
-:: for version in ir:
- [${version.wire_version}] = dissect_of_queue_stats_entry_v${version.wire_version},
+ [${version.wire_version}] = dissect_of_oxm_v${version.wire_version},
:: #endfor
}