diff options
author | Christophe GUERBER <christophe.guerber@gmail.com> | 2019-01-17 09:51:31 +0100 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2019-01-20 07:49:46 +0000 |
commit | 77c9b211249c6ac4caa0f5ce41869f568495e756 (patch) | |
tree | d39831e1a98b5db3ff4b85b9f987fdf75a5dd39f /epan/dissectors/packet-openflow_v6.c | |
parent | 7c1d99cb895a31e9b6d6263a16cad569737ec30f (diff) |
OpenFlow 1.5: implement version specific parts
B.18.1 Egress Tables (EXT-306):
B.18.2 Packet Type aware pipeline (EXT-112)
B.18.3 Extensible Flow Entry Statistics (EXT-334)
B.18.4 Flow Entry Statistics Trigger (EXT-335)
B.18.6 Packet Register pipeline fields (EXT-244)
B.18.11 Scheduled Bundles (EXT-340)
B.18.12 Controller connection status (EXT-454)
B.18.14 Enable setting all pipeline fields in packet-out (EXT-427)
B.18.15 Port properties for pipeline fields (EXT-388)
B.18.16 Port property for recirculation (EXT-399)
B.18.21 Rename some type for consistency (EXT-302)
Change-Id: I02d2370f6cf661e400bb8b690213589cd030a541
Reviewed-on: https://code.wireshark.org/review/31566
Reviewed-by: Jaap Keuter <jaap.keuter@xs4all.nl>
Petri-Dish: Jaap Keuter <jaap.keuter@xs4all.nl>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan/dissectors/packet-openflow_v6.c')
-rw-r--r-- | epan/dissectors/packet-openflow_v6.c | 1716 |
1 files changed, 1237 insertions, 479 deletions
diff --git a/epan/dissectors/packet-openflow_v6.c b/epan/dissectors/packet-openflow_v6.c index 3ea3a408fe..70e84b081a 100644 --- a/epan/dissectors/packet-openflow_v6.c +++ b/epan/dissectors/packet-openflow_v6.c @@ -60,6 +60,7 @@ static int hf_openflow_v6_action_type = -1; static int hf_openflow_v6_action_length = -1; static int hf_openflow_v6_action_experimenter_experimenter = -1; static int hf_openflow_v6_oxm_experimenter_value = -1; +static int hf_openflow_v6_oxm_register = -1; static int hf_openflow_v6_action_output_port = -1; static int hf_openflow_v6_action_output_max_len = -1; static int hf_openflow_v6_action_output_pad = -1; @@ -98,7 +99,6 @@ static int hf_openflow_v6_instruction_write_metadata_pad = -1; static int hf_openflow_v6_instruction_write_metadata_value = -1; static int hf_openflow_v6_instruction_write_metadata_mask = -1; static int hf_openflow_v6_instruction_actions_pad = -1; -static int hf_openflow_v6_instruction_meter_meter_id = -1; static int hf_openflow_v6_port_desc_prop_type = -1; static int hf_openflow_v6_port_desc_prop_length = -1; static int hf_openflow_v6_port_desc_prop_ethernet_pad = -1; @@ -285,6 +285,8 @@ static int hf_openflow_v6_switch_features_capabilities_group_stats = -1; static int hf_openflow_v6_switch_features_capabilities_ip_reasm = -1; static int hf_openflow_v6_switch_features_capabilities_queue_stats = -1; static int hf_openflow_v6_switch_features_capabilities_port_blocked = -1; +static int hf_openflow_v6_switch_features_capabilities_bundles = -1; +static int hf_openflow_v6_switch_features_capabilities_flow_monitoring = -1; static int hf_openflow_v6_switch_features_reserved = -1; static int hf_openflow_v6_switch_config_flags = -1; static int hf_openflow_v6_switch_config_flags_fragments = -1; @@ -299,16 +301,11 @@ static int hf_openflow_v6_flow_removed_cookie = -1; static int hf_openflow_v6_flow_removed_priority = -1; static int hf_openflow_v6_flow_removed_reason = -1; static int hf_openflow_v6_flow_removed_table_id = -1; -static int hf_openflow_v6_flow_removed_duration_sec = -1; -static int hf_openflow_v6_flow_removed_duration_nsec = -1; static int hf_openflow_v6_flow_removed_idle_timeout = -1; static int hf_openflow_v6_flow_removed_hard_timeout = -1; -static int hf_openflow_v6_flow_removed_packet_count = -1; -static int hf_openflow_v6_flow_removed_byte_count = -1; static int hf_openflow_v6_port_status_reason = -1; static int hf_openflow_v6_port_status_pad = -1; static int hf_openflow_v6_packet_out_buffer_id = -1; -static int hf_openflow_v6_packet_out_in_port = -1; static int hf_openflow_v6_packet_out_acts_len = -1; static int hf_openflow_v6_packet_out_pad = -1; static int hf_openflow_v6_flowmod_cookie = -1; @@ -469,27 +466,10 @@ static int hf_openflow_v6_switch_description_serial_num = -1; static int hf_openflow_v6_switch_description_dp_desc = -1; static int hf_openflow_v6_flow_stats_length = -1; static int hf_openflow_v6_flow_stats_table_id = -1; -static int hf_openflow_v6_flow_stats_pad = -1; static int hf_openflow_v6_flow_stats_duration_sec = -1; static int hf_openflow_v6_flow_stats_duration_nsec = -1; static int hf_openflow_v6_flow_stats_priority = -1; -static int hf_openflow_v6_flow_stats_idle_timeout = -1; -static int hf_openflow_v6_flow_stats_hard_timeout = -1; -static int hf_openflow_v6_flow_stats_flags = -1; -static int hf_openflow_v6_flow_stats_flags_send_flow_rem = -1; -static int hf_openflow_v6_flow_stats_flags_check_overlap = -1; -static int hf_openflow_v6_flow_stats_flags_reset_counts = -1; -static int hf_openflow_v6_flow_stats_flags_no_packet_counts = -1; -static int hf_openflow_v6_flow_stats_flags_no_byte_counts = -1; -static int hf_openflow_v6_flow_stats_importance = -1; static int hf_openflow_v6_flow_stats_pad2 = -1; -static int hf_openflow_v6_flow_stats_cookie = -1; -static int hf_openflow_v6_flow_stats_packet_count = -1; -static int hf_openflow_v6_flow_stats_byte_count = -1; -static int hf_openflow_v6_aggregate_stats_packet_count = -1; -static int hf_openflow_v6_aggregate_stats_byte_count = -1; -static int hf_openflow_v6_aggregate_stats_flow_count = -1; -static int hf_openflow_v6_aggregate_stats_pad = -1; static int hf_openflow_v6_table_stats_table_id = -1; static int hf_openflow_v6_table_stats_pad = -1; static int hf_openflow_v6_table_stats_active_count = -1; @@ -755,6 +735,66 @@ static int hf_openflow_v6_bundle_add_pad = -1; static int hf_openflow_v6_bundle_add_flags = -1; static int hf_openflow_v6_bundle_add_flags_atomic = -1; static int hf_openflow_v6_bundle_add_flags_ordered = -1; +static int hf_openflow_v6_oxs_class = -1; +static int hf_openflow_v6_oxs_field = -1; +static int hf_openflow_v6_oxs_reserved = -1; +static int hf_openflow_v6_oxs_length = -1; +static int hf_openflow_v6_oxs_basic_duration_sec = -1; +static int hf_openflow_v6_oxs_basic_duration_nsec = -1; +static int hf_openflow_v6_oxs_basic_idle_sec = -1; +static int hf_openflow_v6_oxs_basic_idle_nsec = -1; +static int hf_openflow_v6_oxs_basic_flow_count = -1; +static int hf_openflow_v6_oxs_basic_packet_count = -1; +static int hf_openflow_v6_oxs_basic_byte_count = -1; +static int hf_openflow_v6_oxs_experimenter_experimenter = -1; +static int hf_openflow_v6_oxs_experimenter_value = -1; +static int hf_openflow_v6_instruction_stat_trigger_flags = -1; +static int hf_openflow_v6_instruction_stat_triffer_flags_periodic = -1; +static int hf_openflow_v6_instruction_stat_triffer_flags_only_first = -1; +static int hf_openflow_v6_instruction_stat_triffer_flags_reserved = -1; +static int hf_openflow_v6_port_desc_prop_recirculate_port_no = -1; +static int hf_openflow_v6_bundle_features_request_flags = -1; +static int hf_openflow_v6_bundle_features_request_pad = -1; +static int hf_openflow_v6_stats_reserved = -1; +static int hf_openflow_v6_stats_length = -1; +static int hf_openflow_v6_stats_pad = -1; +static int hf_openflow_v6_flow_desc_length = -1; +static int hf_openflow_v6_flow_desc_pad2 = -1; +static int hf_openflow_v6_flow_desc_table_id = -1; +static int hf_openflow_v6_flow_desc_pad = -1; +static int hf_openflow_v6_flow_desc_priority = -1; +static int hf_openflow_v6_flow_desc_idle_timeout = -1; +static int hf_openflow_v6_flow_desc_hard_timeout = -1; +static int hf_openflow_v6_flow_desc_flags = -1; +static int hf_openflow_v6_flow_desc_flags_send_flow_rem = -1; +static int hf_openflow_v6_flow_desc_flags_check_overlap = -1; +static int hf_openflow_v6_flow_desc_flags_reset_counts = -1; +static int hf_openflow_v6_flow_desc_flags_no_packet_counts = -1; +static int hf_openflow_v6_flow_desc_flags_no_byte_counts = -1; +static int hf_openflow_v6_flow_desc_importance = -1; +static int hf_openflow_v6_flow_desc_cookie = -1; +static int hf_openflow_v6_controller_status_length = -1; +static int hf_openflow_v6_controller_status_short_id = -1; +static int hf_openflow_v6_controller_status_role = -1; +static int hf_openflow_v6_controller_status_reason = -1; +static int hf_openflow_v6_controller_status_channel_status = -1; +static int hf_openflow_v6_controller_status_pad = -1; +static int hf_openflow_v6_time_seconds = -1; +static int hf_openflow_v6_time_nanoseconds = -1; +static int hf_openflow_v6_time_pad = -1; +static int hf_openflow_v6_bundle_feature_prop_type = -1; +static int hf_openflow_v6_bundle_feature_prop_length = -1; +static int hf_openflow_v6_bundle_feature_prop_time_pad = -1; +static int hf_openflow_v6_bundle_feature_prop_experimenter_experimenter = -1; +static int hf_openflow_v6_bundle_feature_prop_experimenter_exp_type = -1; +static int hf_openflow_v6_bundle_feature_prop_pad = -1; +static int hf_openflow_v6_controller_status_prop_type = -1; +static int hf_openflow_v6_controller_status_prop_length = -1; +static int hf_openflow_v6_controller_status_prop_experimenter_experimenter = -1; +static int hf_openflow_v6_controller_status_prop_experimenter_exp_type = -1; +static int hf_openflow_v6_controller_status_prop_pad = -1; +static int hf_openflow_v6_flow_stats_reason = -1; +static int hf_openflow_v6_controller_status_prop_uri = -1; static gint ett_openflow_v6 = -1; static gint ett_openflow_v6_flowmod_flags = -1; @@ -798,7 +838,6 @@ static gint ett_openflow_v6_table_feature_prop_oxm_id = -1; static gint ett_openflow_v6_flow_monitor_request_flags = -1; static gint ett_openflow_v6_multipart_request_flags = -1; static gint ett_openflow_v6_flow_stats = -1; -static gint ett_openflow_v6_flow_stats_flags = -1; static gint ett_openflow_v6_table_stats = -1; static gint ett_openflow_v6_port_stats = -1; static gint ett_openflow_v6_queue_stats = -1; @@ -837,6 +876,11 @@ static gint ett_openflow_v6_bundle_control_flags = -1; static gint ett_openflow_v6_bundle_prop = -1; static gint ett_openflow_v6_bundle_add_flags = -1; static gint ett_openflow_v6_bundle_add_message = -1; +static gint ett_openflow_v6_instruction_stat_trigger_flags = -1; +static gint ett_openflow_v6_flow_desc = -1; +static gint ett_openflow_v6_flow_desc_flags = -1; +static gint ett_openflow_v6_bundle_feature_prop = -1; +static gint ett_openflow_v6_controller_status_prop = -1; static expert_field ei_openflow_v6_match_undecoded = EI_INIT; static expert_field ei_openflow_v6_oxm_undecoded = EI_INIT; @@ -860,6 +904,8 @@ static expert_field ei_openflow_v6_async_config_prop_undecoded = EI_INIT; static expert_field ei_openflow_v6_bundle_prop_undecoded = EI_INIT; static expert_field ei_openflow_v6_message_undecoded = EI_INIT; static expert_field ei_openflow_v6_length_too_short = EI_INIT; +static expert_field ei_openflow_v6_bundle_feature_prop_undecoded = EI_INIT; +static expert_field ei_openflow_v6_controller_status_prop_undecoded = EI_INIT; static const value_string openflow_v6_version_values[] = { { 0x06, "1.5" }, @@ -899,6 +945,7 @@ static const value_string openflow_v6_version_values[] = { #define OFPT_REQUESTFORWARD 32 #define OFPT_BUNDLE_CONTROL 33 #define OFPT_BUNDLE_ADD_MESSAGE 34 +#define OFPT_CONTROLLER_STATUS 35 static const value_string openflow_v6_type_values[] = { { OFPT_HELLO, "OFPT_HELLO" }, { OFPT_ERROR, "OFPT_ERROR" }, @@ -933,6 +980,7 @@ static const value_string openflow_v6_type_values[] = { { OFPT_REQUESTFORWARD, "OFPT_REQUESTFORWARD" }, { OFPT_BUNDLE_CONTROL, "OFPT_BUNDLE_CONTROL" }, { OFPT_BUNDLE_ADD_MESSAGE, "OFPT_BUNDLE_ADD_MESSAGE" }, + { OFPT_CONTROLLER_STATUS, "OFPT_CONTROLLER_STATUS" }, { 0, NULL } }; static value_string_ext openflow_v6_type_values_ext = VALUE_STRING_EXT_INIT(openflow_v6_type_values); @@ -992,14 +1040,126 @@ static const value_string openflow_v6_buffer_reserved_values[] = { { 0, NULL} }; +/* + * OXS + */ +#define OFPXSC_OPENFLOW_BASIC 0x8002 +#define OFPXSC_EXPERIMENTER 0xFFFF +static const value_string openflow_v6_oxs_class_values[] = { + { OFPXSC_OPENFLOW_BASIC, "OFPXSC_OPENFLOW_BASIC" }, + { OFPXSC_EXPERIMENTER, "OFPXSC_EXPERIMENTER" }, + { 0, NULL } +}; + +#define OFPXST_OFB_DURATION 0 /* Time flow entry has been alive. */ +#define OFPXST_OFB_IDLE_TIME 1 /* Time flow entry has been idle. */ +#define OFPXST_OFB_FLOW_COUNT 3 /* Number of aggregated flow entries. */ +#define OFPXST_OFB_PACKET_COUNT 4 /* Number of packets in flow entry. */ +#define OFPXST_OFB_BYTE_COUNT 5 /* Number of bytes in flow entry. */ +static const value_string openflow_v6_oxs_basic_field_values[] = { + { OFPXST_OFB_DURATION, "OFPXST_OFB_DURATION" }, + { OFPXST_OFB_IDLE_TIME, "OFPXST_OFB_IDLE_TIME" }, + { OFPXST_OFB_FLOW_COUNT, "OFPXST_OFB_FLOW_COUNT" }, + { OFPXST_OFB_PACKET_COUNT, "OFPXST_OFB_PACKET_COUNT" }, + { OFPXST_OFB_BYTE_COUNT, "OFPXST_OFB_BYTE_COUNT" }, + { 0, NULL } +}; + +#define OXS_FIELD_MASK 0xfe +#define OXS_RESERVED_MASK 0x01 + +static int +dissect_openflow_v6_oxs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) +{ + guint32 oxs_class; + guint32 oxs_field; + guint32 oxs_payload_length; + + proto_tree_add_item_ret_uint(tree, hf_openflow_v6_oxs_class, tvb, offset, 2, ENC_BIG_ENDIAN, &oxs_class); + offset+=2; + + proto_tree_add_item_ret_uint(tree, hf_openflow_v6_oxs_field, tvb, offset, 1, ENC_BIG_ENDIAN, &oxs_field); + proto_tree_add_item(tree, hf_openflow_v6_oxs_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + offset+=1; + + proto_tree_add_item_ret_uint(tree, hf_openflow_v6_oxs_length, tvb, offset, 1, ENC_BIG_ENDIAN, &oxs_payload_length); + offset+=1; + + if (oxs_class == OFPXSC_OPENFLOW_BASIC) { + switch (oxs_field) { + case OFPXST_OFB_DURATION: + proto_tree_add_item(tree, hf_openflow_v6_oxs_basic_duration_sec, tvb, offset, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_openflow_v6_oxs_basic_duration_nsec, tvb, offset+4, 4, ENC_BIG_ENDIAN); + break; + case OFPXST_OFB_IDLE_TIME: + proto_tree_add_item(tree, hf_openflow_v6_oxs_basic_idle_sec, tvb, offset, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_openflow_v6_oxs_basic_idle_nsec, tvb, offset+4, 4, ENC_BIG_ENDIAN); + break; + case OFPXST_OFB_FLOW_COUNT: + proto_tree_add_item(tree, hf_openflow_v6_oxs_basic_flow_count, tvb, offset, 4, ENC_BIG_ENDIAN); + break; + case OFPXST_OFB_PACKET_COUNT: + proto_tree_add_item(tree, hf_openflow_v6_oxs_basic_packet_count, tvb, offset, 8, ENC_BIG_ENDIAN); + break; + case OFPXST_OFB_BYTE_COUNT: + proto_tree_add_item(tree, hf_openflow_v6_oxs_basic_byte_count, tvb, offset, 8, ENC_BIG_ENDIAN); + break; + } + } else if (oxs_class == OFPXSC_EXPERIMENTER) { + proto_tree_add_item(tree, hf_openflow_v6_oxs_experimenter_experimenter, tvb, offset, 4, ENC_BIG_ENDIAN); + + proto_tree_add_item(tree, hf_openflow_v6_oxs_experimenter_value, tvb, offset+4, oxs_payload_length - 4, ENC_NA); + } + offset+=oxs_payload_length; + + return offset; +} + +static int +dissect_openflow_stats_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) +{ + guint32 stats_length; + int oxs_end; + guint32 padding; + + proto_tree_add_item(tree, hf_openflow_v6_stats_reserved, tvb, offset, 2, ENC_NA); + + proto_tree_add_item_ret_uint(tree, hf_openflow_v6_stats_length, tvb, offset+2, 2, ENC_BIG_ENDIAN, &stats_length); + + oxs_end = offset + stats_length; + offset+=4; + + while (offset < oxs_end) { + offset = dissect_openflow_v6_oxs(tvb, pinfo, tree, offset, oxs_end - offset); + } + + if (offset > oxs_end) { + // XXX EI if offset > oxs_end? + offset = oxs_end; + } + + padding = ((stats_length + 7) & ~7) - stats_length; + if (padding) { + proto_tree_add_item(tree, hf_openflow_v6_stats_pad, tvb, oxs_end, padding, ENC_NA); + offset += padding; + } + + return offset; +} + +/* + * OXM + */ #define OFPXMC_NXM_0 0x0000 /* Backward compatibility with NXM */ #define OFPXMC_NXM_1 0x0001 /* Backward compatibility with NXM */ #define OFPXMC_OPENFLOW_BASIC 0x8000 /* Basic class for OpenFlow */ +#define OFPXMC_PACKET_REGS 0x8001 /* Packet registers (pipeline fields). */ #define OFPXMC_EXPERIMENTER 0xFFFF /* Experimenter class */ static const value_string openflow_v6_oxm_class_values[] = { { 0x0000, "OFPXMC_NMX_0" }, { 0x0001, "OFPXMC_NXM_1" }, { 0x8000, "OFPXMC_OPENFLOW_BASIC" }, + { 0x8001, "OFPXMC_PACKET_REGS" }, { 0xFFFF, "OFPXMC_EXPERIMENTER" }, { 0, NULL} }; @@ -1097,34 +1257,69 @@ static const value_string openflow_v6_oxm_basic_field_values[] = { }; static value_string_ext openflow_v6_oxm_basic_field_values_ext = VALUE_STRING_EXT_INIT(openflow_v6_oxm_basic_field_values); +#define OFPHTN_ONF 0 +#define OFPHTN_ETHERTYPE 1 +#define OFPHTN_IP_PROTO 2 +#define OFPHTN_UDP_TCP_PORT 3 +#define OFPHTN_IPV4_OPTION 4 +static const value_string openflow_v6_header_type_namespace_values[] = { + { OFPHTN_ONF, "OFPHTN_ONF" }, + { OFPHTN_ETHERTYPE, "OFPHTN_ETHERTYPE" }, + { OFPHTN_IP_PROTO, "OFPHTN_IP_PROTO" }, + { OFPHTN_UDP_TCP_PORT, "OFPHTN_UDP_TCP_PORT" }, + { OFPHTN_IPV4_OPTION, "OFPHTN_IPV4_OPTION" }, + { 0, NULL } +}; + #define OXM_FIELD_MASK 0xfe -#define OXM_FIELD_OFFSET 1 #define OXM_HM_MASK 0x01 + +typedef struct oxm_header { + guint32 oxm_class; + guint32 oxm_hm; + guint32 oxm_field; + guint32 oxm_length; +} oxm_header; static int -dissect_openflow_oxm_header_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) +dissect_openflow_oxm_header_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_, oxm_header *retval) { - guint16 oxm_class; + guint32 oxm_class; + guint32 oxm_hm; + guint32 oxm_field; + guint32 oxm_length; /* oxm_class */ - oxm_class = tvb_get_ntohs(tvb, offset); - proto_tree_add_item(tree, hf_openflow_v6_oxm_class, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(tree, hf_openflow_v6_oxm_class, tvb, offset, 2, ENC_BIG_ENDIAN, &oxm_class); offset+=2; /* oxm_field */ - if (oxm_class == OFPXMC_OPENFLOW_BASIC) { - proto_tree_add_bits_item(tree, hf_openflow_v6_oxm_field_basic, tvb, (offset * 8), 7, ENC_NA); - } else { - proto_tree_add_bits_item(tree, hf_openflow_v6_oxm_field, tvb, (offset * 8), 7, ENC_NA); + switch (oxm_class) { + case OFPXMC_OPENFLOW_BASIC: + proto_tree_add_item_ret_uint(tree, hf_openflow_v6_oxm_field_basic, tvb, (offset * 8), 7, ENC_NA, &oxm_field); + break; + case OFPXMC_PACKET_REGS: + proto_tree_add_item_ret_uint(tree, hf_openflow_v6_oxm_register, tvb, offset, 1, ENC_BIG_ENDIAN, &oxm_field); + break; + default: + proto_tree_add_item_ret_uint(tree, hf_openflow_v6_oxm_field, tvb, offset, 1, ENC_BIG_ENDIAN, &oxm_field); + break; } /* oxm_hm */ - proto_tree_add_bits_item(tree, hf_openflow_v6_oxm_hm, tvb, (offset * 8) + 7, 1, ENC_NA); + proto_tree_add_item_ret_uint(tree, hf_openflow_v6_oxm_hm, tvb, offset, 1, ENC_BIG_ENDIAN, &oxm_hm); offset+=1; /* oxm_length */ - proto_tree_add_item(tree, hf_openflow_v6_oxm_length, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(tree, hf_openflow_v6_oxm_length, tvb, offset, 1, ENC_BIG_ENDIAN, &oxm_length); offset+=1; + if (retval) { + retval->oxm_class = oxm_class; + retval->oxm_hm = oxm_hm; + retval->oxm_field = oxm_field; + retval->oxm_length = oxm_length; + } + return offset; } @@ -1134,31 +1329,26 @@ static int dissect_openflow_oxm_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) { proto_tree *oxm_tree; - guint16 oxm_class; guint16 oxm_end; - guint8 oxm_field_hm; - guint8 oxm_hm; - guint8 oxm_field; - guint8 oxm_length; + oxm_header header; guint8 field_length; + guint32 packet_type_namespace; + proto_item *ti; - oxm_class = tvb_get_ntohs(tvb, offset); - oxm_field_hm = tvb_get_guint8(tvb, offset + 2); - oxm_length = tvb_get_guint8(tvb, offset + 3); - oxm_end = offset + 4 + oxm_length; + header.oxm_length = tvb_get_guint8(tvb, offset + 3); - oxm_field = (oxm_field_hm & OXM_FIELD_MASK) >> OXM_FIELD_OFFSET; - oxm_hm = oxm_field_hm & OXM_HM_MASK; - field_length = (oxm_hm == 0) ? oxm_length : (oxm_length / 2); + oxm_tree = proto_tree_add_subtree(tree, tvb, offset, header.oxm_length + 4, ett_openflow_v6_oxm, NULL, "OXM field"); - oxm_tree = proto_tree_add_subtree(tree, tvb, offset, oxm_length + 4, ett_openflow_v6_oxm, NULL, "OXM field"); + offset = dissect_openflow_oxm_header_v6(tvb, pinfo, oxm_tree, offset, length, &header); - offset = dissect_openflow_oxm_header_v6(tvb, pinfo, oxm_tree, offset, length); + oxm_end = offset + 4 + header.oxm_length; + field_length = (header.oxm_hm == 0) ? header.oxm_length : (header.oxm_length / 2); - if (oxm_class == OFPXMC_OPENFLOW_BASIC) { - switch(oxm_field) { + if (header.oxm_class == OFPXMC_OPENFLOW_BASIC) { + switch(header.oxm_field) { case OFPXMT_OFB_IN_PORT: case OFPXMT_OFB_IN_PHY_PORT: + case OFPXMT_OFB_ACTSET_OUTPUT: proto_tree_add_item(oxm_tree, hf_openflow_v6_oxm_value_uint32, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; break; @@ -1171,7 +1361,7 @@ dissect_openflow_oxm_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, case OFPXMT_OFB_IPV6_ND_TLL: /*The target link-layer address option in an IPv6 Neighbor Discovery message */ proto_tree_add_item(oxm_tree, hf_openflow_v6_oxm_value_etheraddr, tvb, offset, 6, ENC_NA); offset+=6; - if (oxm_hm) { + if (header.oxm_hm) { proto_tree_add_item(oxm_tree, hf_openflow_v6_oxm_mask_etheraddr, tvb, offset, 6, ENC_NA); offset+=6; } @@ -1186,7 +1376,7 @@ dissect_openflow_oxm_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, proto_tree_add_item(oxm_tree, hf_openflow_v6_oxm_value_vlan_present, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(oxm_tree, hf_openflow_v6_oxm_value_vlan_vid, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; - if (oxm_hm) { + if (header.oxm_hm) { proto_tree_add_item(oxm_tree, hf_openflow_v6_oxm_mask_vlan, tvb, offset, 2, ENC_NA); offset+=2; } @@ -1203,7 +1393,7 @@ dissect_openflow_oxm_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, case OFPXMT_OFB_ARP_TPA: proto_tree_add_item(oxm_tree, hf_openflow_v6_oxm_value_ipv4addr, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; - if (oxm_hm) { + if (header.oxm_hm) { proto_tree_add_item(oxm_tree, hf_openflow_v6_oxm_mask_ipv4addr, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; } @@ -1223,7 +1413,7 @@ dissect_openflow_oxm_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, case OFPXMT_OFB_IPV6_DST: proto_tree_add_item(oxm_tree, hf_openflow_v6_oxm_value_ipv6addr, tvb, offset, 16, ENC_NA); offset+=16; - if (oxm_hm) { + if (header.oxm_hm) { proto_tree_add_item(oxm_tree, hf_openflow_v6_oxm_mask_ipv6addr, tvb, offset, 16, ENC_NA); offset+=16; } @@ -1240,6 +1430,15 @@ dissect_openflow_oxm_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, } break; + case OFPXMT_OFB_PACKET_TYPE: + ti = proto_tree_add_item_ret_uint(oxm_tree, hf_openflow_v6_oxm_value_uint16, tvb, offset, 2, ENC_BIG_ENDIAN, &packet_type_namespace); + proto_item_append_text(ti, " (%s)", val_to_str_const(packet_type_namespace, openflow_v6_header_type_namespace_values, "Unknown")); + offset+=2; + + proto_tree_add_item(oxm_tree, hf_openflow_v6_oxm_value_uint16, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + break; + default: /* value */ if (field_length > 0) { @@ -1248,7 +1447,7 @@ dissect_openflow_oxm_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, } /* mask */ - if (field_length > 0 && oxm_hm != 0) { + if (field_length > 0 && header.oxm_hm != 0) { proto_tree_add_item(oxm_tree, hf_openflow_v6_oxm_mask, tvb, offset, field_length, ENC_NA); offset += field_length; } @@ -1261,16 +1460,23 @@ dissect_openflow_oxm_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, offset = oxm_end; } - } else if (oxm_class == OFPXMC_EXPERIMENTER) { + } else if (header.oxm_class == OFPXMC_PACKET_REGS) { + proto_tree_add_item(oxm_tree, hf_openflow_v6_oxm_value, tvb, offset, 8, ENC_NA); + offset+=8; + if (header.oxm_hm) { + proto_tree_add_item(oxm_tree, hf_openflow_v6_oxm_mask, tvb, offset, 8, ENC_NA); + offset+=8; + } + } else if (header.oxm_class == OFPXMC_EXPERIMENTER) { /* uint32_t experimenter; */ proto_tree_add_item(oxm_tree, hf_openflow_v6_oxm_experimenter_experimenter, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; - proto_tree_add_item(oxm_tree, hf_openflow_v6_oxm_experimenter_value, tvb, offset, oxm_length - 4, ENC_NA); - offset+=(oxm_length - 4); + proto_tree_add_item(oxm_tree, hf_openflow_v6_oxm_experimenter_value, tvb, offset, header.oxm_length - 4, ENC_NA); + offset+=(header.oxm_length - 4); } else { proto_tree_add_expert_format(oxm_tree, pinfo, &ei_openflow_v6_oxm_undecoded, - tvb, offset, oxm_length, "Unknown OXM body."); - offset+=oxm_length; + tvb, offset, header.oxm_length, "Unknown OXM body."); + offset+=header.oxm_length; } return offset; @@ -1289,7 +1495,7 @@ dissect_openflow_match_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tre { proto_item *ti; proto_tree *match_tree; - guint16 match_type; + guint32 match_type; guint16 match_length; gint32 fields_end; guint16 pad_length; @@ -1297,8 +1503,7 @@ dissect_openflow_match_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tre match_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_openflow_v6_match, &ti, "Match"); /* uint16_t type; */ - match_type = tvb_get_ntohs(tvb, offset); - proto_tree_add_item(match_tree, hf_openflow_v6_match_type, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(match_tree, hf_openflow_v6_match_type, tvb, offset, 2, ENC_BIG_ENDIAN, &match_type); offset+=2; /* uint16_t length; (excluding padding) */ @@ -1372,14 +1577,13 @@ dissect_openflow_meter_band_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree { proto_item *ti; proto_tree *band_tree; - guint16 band_type; + guint32 band_type; guint16 band_len; band_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_openflow_v6_meter_band, &ti, "Meter band"); /* uint16_t type; */ - band_type = tvb_get_ntohs(tvb, offset); - proto_tree_add_item(band_tree, hf_openflow_v6_meter_band_type, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(band_tree, hf_openflow_v6_meter_band_type, tvb, offset, 2, ENC_BIG_ENDIAN, &band_type); offset+=2; /* uint16_t len; */ @@ -1450,15 +1654,14 @@ static int dissect_openflow_hello_element_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length) { proto_tree *elem_tree; - guint16 elem_type; + guint32 elem_type; guint16 elem_length; guint16 pad_length; elem_tree = proto_tree_add_subtree(tree, tvb, offset, length - offset, ett_openflow_v6_hello_element, NULL, "Element"); /* uint16_t type; */ - elem_type = tvb_get_ntohs(tvb, offset); - proto_tree_add_item(elem_tree, hf_openflow_v6_hello_element_type, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(elem_tree, hf_openflow_v6_hello_element_type, tvb, offset, 2, ENC_BIG_ENDIAN, &elem_type); offset+=2; /* uint16_t length; */ @@ -1774,11 +1977,10 @@ dissect_openflow_error_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tre { proto_tree *data_tree; proto_item *data_ti; - guint16 error_type; + guint32 error_type; /* uint16_t type; */ - error_type = tvb_get_ntohs(tvb, offset); - proto_tree_add_item(tree, hf_openflow_v6_error_type, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(tree, hf_openflow_v6_error_type, tvb, offset, 2, ENC_BIG_ENDIAN, &error_type); offset +=2; /* uint16_t code; */ @@ -1937,13 +2139,16 @@ dissect_openflow_experimenter_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tr } } -#define OFPC_FLOW_STATS 1<<0 -#define OFPC_TABLE_STATS 1<<1 -#define OFPC_PORT_STATS 1<<2 -#define OFPC_GROUP_STATS 1<<3 -#define OFPC_IP_REASM 1<<5 -#define OFPC_QUEUE_STATS 1<<6 -#define OFPC_PORT_BLOCKED 1<<8 +#define OFPC_FLOW_STATS 1<<0 /* Flow statistics. */ +#define OFPC_TABLE_STATS 1<<1 /* Table statistics. */ +#define OFPC_PORT_STATS 1<<2 /* Port statistics. */ +#define OFPC_GROUP_STATS 1<<3 /* Group statistics. */ +#define OFPC_IP_REASM 1<<5 /* Can reassemble IP fragments. */ +#define OFPC_QUEUE_STATS 1<<6 /* Queue statistics. */ +#define OFPC_PORT_BLOCKED 1<<8 /* Switch will block looping ports. */ +#define OFPC_BUNDLES 1<<9 /* Switch supports bundles. */ +#define OFPC_FLOW_MONITORING 1<<10 /* Switch supports flow monitoring. */ + static void dissect_openflow_switch_features_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) { @@ -1981,6 +2186,8 @@ dissect_openflow_switch_features_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto proto_tree_add_item(cap_tree, hf_openflow_v6_switch_features_capabilities_ip_reasm, tvb, offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(cap_tree, hf_openflow_v6_switch_features_capabilities_queue_stats, tvb, offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(cap_tree, hf_openflow_v6_switch_features_capabilities_port_blocked, tvb, offset, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(cap_tree, hf_openflow_v6_switch_features_capabilities_bundles, tvb, offset, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(cap_tree, hf_openflow_v6_switch_features_capabilities_flow_monitoring, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; /* uint32_t reserved; */ @@ -2123,29 +2330,17 @@ static const value_string openflow_v6_flow_removed_reason_values[] = { static void dissect_openflow_flow_removed_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) { - /* uint64_t cookie; */ - proto_tree_add_item(tree, hf_openflow_v6_flow_removed_cookie, tvb, offset, 8, ENC_BIG_ENDIAN); - offset+=8; - - /* uint16_t priority; */ - proto_tree_add_item(tree, hf_openflow_v6_flow_removed_priority, tvb, offset, 2, ENC_BIG_ENDIAN); - offset+=2; - - /* uint8_t reason; */ - proto_tree_add_item(tree, hf_openflow_v6_flow_removed_reason, tvb, offset, 1, ENC_BIG_ENDIAN); - offset+=1; - /* uint8_t table_id; */ proto_tree_add_item(tree, hf_openflow_v6_flow_removed_table_id, tvb, offset, 1, ENC_BIG_ENDIAN); offset+=1; - /* uint32_t duration_sec; */ - proto_tree_add_item(tree, hf_openflow_v6_flow_removed_duration_sec, tvb, offset, 4, ENC_BIG_ENDIAN); - offset+=4; + /* uint8_t reason; */ + proto_tree_add_item(tree, hf_openflow_v6_flow_removed_reason, tvb, offset, 1, ENC_BIG_ENDIAN); + offset+=1; - /* uint32_t duration_nsec; */ - proto_tree_add_item(tree, hf_openflow_v6_flow_removed_duration_nsec, tvb, offset, 4, ENC_BIG_ENDIAN); - offset+=4; + /* uint16_t priority; */ + proto_tree_add_item(tree, hf_openflow_v6_flow_removed_priority, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; /* uint16_t idle_timeout; */ proto_tree_add_item(tree, hf_openflow_v6_flow_removed_idle_timeout, tvb, offset, 2, ENC_BIG_ENDIAN); @@ -2155,16 +2350,15 @@ dissect_openflow_flow_removed_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tr proto_tree_add_item(tree, hf_openflow_v6_flow_removed_hard_timeout, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; - /* uint64_t packet_count; */ - proto_tree_add_item(tree, hf_openflow_v6_flow_removed_packet_count, tvb, offset, 8, ENC_BIG_ENDIAN); - offset+=8; - - /* uint64_t byte_count; */ - proto_tree_add_item(tree, hf_openflow_v6_flow_removed_byte_count, tvb, offset, 8, ENC_BIG_ENDIAN); + /* uint64_t cookie; */ + proto_tree_add_item(tree, hf_openflow_v6_flow_removed_cookie, tvb, offset, 8, ENC_BIG_ENDIAN); offset+=8; /* struct ofp_match match; */ - dissect_openflow_match_v6(tvb, pinfo, tree, offset, length); + offset = dissect_openflow_match_v6(tvb, pinfo, tree, offset, length); + + /* struct ofp_stats */ + dissect_openflow_stats_v6(tvb, pinfo, tree, offset, length); } #define OFPAT_OUTPUT 0 /* Output to switch port. */ @@ -2215,11 +2409,10 @@ static const value_string openflow_v6_action_type_values[] = { static int dissect_openflow_action_header_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) { - guint16 act_type; + guint32 act_type; /* uint16_t type; */ - act_type = tvb_get_ntohs(tvb, offset); - proto_tree_add_item(tree, hf_openflow_v6_action_type, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(tree, hf_openflow_v6_action_type, tvb, offset, 2, ENC_BIG_ENDIAN, &act_type); offset+=2; /* uint16_t length; */ @@ -2620,14 +2813,20 @@ dissect_openflow_port_desc_prop_optical_v6(tvbuff_t *tvb, packet_info *pinfo _U_ -#define OFPPDPT_ETHERNET 0 -#define OFPPDPT_OPTICAL 1 +#define OFPPDPT_ETHERNET 0 +#define OFPPDPT_OPTICAL 1 +#define OFPPDPT_PIPELINE_INPUT 2 +#define OFPPDPT_PIPELINE_OUTPUT 3 +#define OFPPDPT_RECIRCULATE 4 #define OFPPDPT_EXPERIMENTER 0xFFFF static const value_string openflow_v6_port_desc_prop_type_values[] = { - { OFPPDPT_ETHERNET, "OFPPDPT_ETHERNET" }, - { OFPPDPT_OPTICAL, "OFPPDPT_OPTICAL" }, - { OFPPDPT_EXPERIMENTER, "OFPPDPT_EXPERIMENTER" }, - { 0, NULL } + { OFPPDPT_ETHERNET, "OFPPDPT_ETHERNET" }, + { OFPPDPT_OPTICAL, "OFPPDPT_OPTICAL" }, + { OFPPDPT_PIPELINE_INPUT, "OFPPDPT_PIPELINE_INPUT" }, + { OFPPDPT_PIPELINE_OUTPUT, "OFPPDPT_PIPELINE_OUTPUT" }, + { OFPPDPT_RECIRCULATE, "OFPPDPT_RECIRCULATE" }, + { OFPPDPT_EXPERIMENTER, "OFPPDPT_EXPERIMENTER" }, + { 0, NULL } }; static int @@ -2635,20 +2834,18 @@ dissect_openflow_port_desc_prop_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_ { proto_tree *prop_tree; proto_item *prop_item; - guint16 prop_type; - guint16 prop_length; - - prop_type = tvb_get_ntohs(tvb, offset); - prop_length = tvb_get_ntohs(tvb, offset); + guint32 prop_type; + guint32 prop_length; + int fields_end; - prop_tree = proto_tree_add_subtree(tree, tvb, offset, prop_length, ett_openflow_v6_port_desc_prop, NULL, "Port desc. property"); + prop_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_openflow_v6_port_desc_prop, NULL, "Port desc. property"); /* uint16_t type; */ - proto_tree_add_item(prop_tree, hf_openflow_v6_port_desc_prop_type, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(prop_tree, hf_openflow_v6_port_desc_prop_type, tvb, offset, 2, ENC_BIG_ENDIAN, &prop_type); offset+=2; /* uint16_t len; */ - prop_item = proto_tree_add_item(prop_tree, hf_openflow_v6_port_desc_prop_length, tvb, offset, 2, ENC_BIG_ENDIAN); + prop_item = proto_tree_add_item_ret_uint(prop_tree, hf_openflow_v6_port_desc_prop_length, tvb, offset, 2, ENC_BIG_ENDIAN, &prop_length); offset+=2; switch (prop_type) { @@ -2660,6 +2857,24 @@ dissect_openflow_port_desc_prop_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_ offset = dissect_openflow_port_desc_prop_optical_v6(tvb, pinfo, prop_tree, offset, length); break; + case OFPPDPT_PIPELINE_INPUT: + case OFPPDPT_PIPELINE_OUTPUT: + fields_end = offset + prop_length - 4; + while(offset < fields_end) { + offset = dissect_openflow_oxm_v6(tvb, pinfo, prop_tree, offset, length); + } + offset+=((prop_length + 7) & ~7) - prop_length; + break; + + case OFPPDPT_RECIRCULATE: + fields_end = offset + prop_length - 4; + while(offset < fields_end) { + proto_tree_add_item(tree, hf_openflow_v6_port_desc_prop_recirculate_port_no, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + offset+=((prop_length + 7) & ~7) - prop_length; + break; + case OFPPDPT_EXPERIMENTER: if (prop_length <= 12) { expert_add_info(pinfo, prop_item, &ei_openflow_v6_length_too_short); @@ -2712,6 +2927,7 @@ dissect_openflow_port_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree { proto_item *ti; proto_tree *port_tree, *conf_tree, *state_tree; + guint32 port_length; guint16 port_end; port_tree = proto_tree_add_subtree(tree, tvb, offset, 64, ett_openflow_v6_port, NULL, "Port"); @@ -2721,8 +2937,8 @@ dissect_openflow_port_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree offset+=4; /* uint16_t length; */ - port_end = tvb_get_ntohs(tvb, offset) + offset - 4; - proto_tree_add_item(port_tree, hf_openflow_v6_port_length, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(port_tree, hf_openflow_v6_port_length, tvb, offset, 2, ENC_BIG_ENDIAN, &port_length); + port_end = port_length + offset - 4; offset+=2; /* uint8_t pad[2]; */ @@ -2803,7 +3019,7 @@ static void dissect_openflow_packet_out_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) { proto_tree *data_tree; - guint16 acts_len; + guint32 acts_len; gint32 acts_end; tvbuff_t *next_tvb; gboolean save_writable; @@ -2814,18 +3030,16 @@ dissect_openflow_packet_out_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree proto_tree_add_item(tree, hf_openflow_v6_packet_out_buffer_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; - /* uint32_t in_port; */ - proto_tree_add_item(tree, hf_openflow_v6_packet_out_in_port, tvb, offset, 4, ENC_BIG_ENDIAN); - offset+=4; - /* uint16_t actions_len; */ - acts_len = tvb_get_ntohs(tvb, offset); - proto_tree_add_item(tree, hf_openflow_v6_packet_out_acts_len, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(tree, hf_openflow_v6_packet_out_acts_len, tvb, offset, 2, ENC_BIG_ENDIAN, &acts_len); offset+=2; - /* uint8_t pad[6]; */ - proto_tree_add_item(tree, hf_openflow_v6_packet_out_pad, tvb, offset, 6, ENC_NA); - offset+=6; + /* uint8_t pad[2]; */ + proto_tree_add_item(tree, hf_openflow_v6_packet_out_pad, tvb, offset, 2, ENC_NA); + offset+=2; + + /* struct ofp_match match; */ + offset = dissect_openflow_match_v6(tvb, pinfo, tree, offset, length); /* struct ofp_action_header actions[0]; */ acts_end = offset + acts_len; @@ -2887,19 +3101,22 @@ static const value_string openflow_v6_instruction_type_values[] = { }; - +typedef struct inst_header { + guint32 type; + guint32 length; +} inst_header; static int -dissect_openflow_instruction_header_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) +dissect_openflow_instruction_header_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_, inst_header *retval) { - guint16 inst_type; + guint32 inst_type; + guint32 inst_length; /* uint16_t type; */ - inst_type = tvb_get_ntohs(tvb, offset); - proto_tree_add_item(tree, hf_openflow_v6_instruction_type, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(tree, hf_openflow_v6_instruction_type, tvb, offset, 2, ENC_BIG_ENDIAN, &inst_type); offset+=2; /* uint16_t length; */ - proto_tree_add_item(tree, hf_openflow_v6_instruction_length, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(tree, hf_openflow_v6_instruction_length, tvb, offset, 2, ENC_BIG_ENDIAN, &inst_length); offset+=2; if (inst_type == OFPIT_EXPERIMENTER) { @@ -2908,30 +3125,37 @@ dissect_openflow_instruction_header_v6(tvbuff_t *tvb, packet_info *pinfo _U_, pr offset+=4; } + if (retval) { + retval->type = inst_type; + retval->length = inst_length; + } + return offset; } - +#define OFPSTF_PERIODIC 1 << 0 +#define OFPSTF_ONLY_FIRST 1 << 1 static int dissect_openflow_instruction_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) { - proto_tree *inst_tree; - guint16 inst_type; - guint16 inst_length; - gint32 acts_end; - - inst_type = tvb_get_ntohs(tvb, offset); - inst_length = tvb_get_ntohs(tvb, offset + 2); + proto_item *ti; + proto_tree *inst_tree, *flags_tree; + inst_header header; + gint32 inst_end; - inst_tree = proto_tree_add_subtree(tree, tvb, offset, inst_length, ett_openflow_v6_instruction, NULL, "Instruction"); + inst_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_openflow_v6_instruction, &ti, "Instruction"); - offset = dissect_openflow_instruction_header_v6(tvb, pinfo, inst_tree, offset, length); + offset = dissect_openflow_instruction_header_v6(tvb, pinfo, inst_tree, offset, length, &header); + proto_item_set_len(ti, header.length); - if (inst_length < 8) { - inst_length = 8; + if (header.length < 8) { + // XXX Shouldn't it be reported with an expert info? + header.length = 8; } - switch (inst_type) { + inst_end = offset + header.length - 4; + + switch (header.type) { case OFPIT_GOTO_TABLE: /* uint8_t table_id; */ proto_tree_add_item(inst_tree, hf_openflow_v6_instruction_goto_table_table_id, tvb, offset, 1, ENC_BIG_ENDIAN); @@ -2962,28 +3186,34 @@ dissect_openflow_instruction_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tre proto_tree_add_item(inst_tree, hf_openflow_v6_instruction_actions_pad, tvb, offset, 4, ENC_NA); offset+=4; - acts_end = offset + inst_length - 8; - while (offset < acts_end) { + while (offset < inst_end) { offset = dissect_openflow_action_v6(tvb, pinfo, inst_tree, offset, length); } break; - case OFPIT_METER: - /* uint32_t meter_id; */ - proto_tree_add_item(inst_tree, hf_openflow_v6_instruction_meter_meter_id, tvb, offset, 4, ENC_BIG_ENDIAN); + case OFPIT_STAT_TRIGGER: + ti = proto_tree_add_item(inst_tree, hf_openflow_v6_instruction_stat_trigger_flags, tvb, offset, 4, ENC_BIG_ENDIAN); + flags_tree = proto_item_add_subtree(ti, ett_openflow_v6_instruction_stat_trigger_flags); + proto_tree_add_item(flags_tree, hf_openflow_v6_instruction_stat_triffer_flags_periodic, tvb, offset, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(flags_tree, hf_openflow_v6_instruction_stat_triffer_flags_only_first, tvb, offset, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(flags_tree, hf_openflow_v6_instruction_stat_triffer_flags_reserved, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; + + while (offset < inst_end) { + offset = dissect_openflow_stats_v6(tvb, pinfo, inst_tree, offset, length); + } break; case OFPIT_EXPERIMENTER: proto_tree_add_expert_format(inst_tree, pinfo, &ei_openflow_v6_instruction_undecoded, - tvb, offset, inst_length - 8, "Experimenter instruction body."); - offset += inst_length - 8; + tvb, offset, header.length - 8, "Experimenter instruction body."); + offset += header.length - 8; break; default: proto_tree_add_expert_format(inst_tree, pinfo, &ei_openflow_v6_instruction_undecoded, - tvb, offset, inst_length - 4, "Unknown instruction body."); - offset += inst_length - 4; + tvb, offset, header.length - 4, "Unknown instruction body."); + offset += header.length - 4; break; } @@ -3264,21 +3494,19 @@ static int dissect_openflow_portmod_prop_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) { proto_tree *prop_tree; - proto_item *prop_item; - guint16 prop_type; - guint16 prop_length; + proto_item *prop_item, *ti; + guint32 prop_type; + guint32 prop_length; - prop_type = tvb_get_ntohs(tvb, offset); - prop_length = tvb_get_ntohs(tvb, offset + 2); - - prop_tree = proto_tree_add_subtree(tree, tvb, offset, prop_length, ett_openflow_v6_portmod_prop, NULL, "Portmod property"); + prop_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_openflow_v6_portmod_prop, &ti, "Portmod property"); /* uint16_t type; */ - proto_tree_add_item(prop_tree, hf_openflow_v6_portmod_prop_type, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(prop_tree, hf_openflow_v6_portmod_prop_type, tvb, offset, 2, ENC_BIG_ENDIAN, &prop_type); offset+=2; /* uint16_t len; */ - prop_item = proto_tree_add_item(prop_tree, hf_openflow_v6_portmod_prop_length, tvb, offset, 2, ENC_BIG_ENDIAN); + prop_item = proto_tree_add_item_ret_uint(prop_tree, hf_openflow_v6_portmod_prop_length, tvb, offset, 2, ENC_BIG_ENDIAN, &prop_length); + proto_item_set_len(ti, prop_length); offset+=2; switch (prop_type) { @@ -3394,20 +3622,20 @@ dissect_openflow_tablemod_prop_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_t proto_item *ti, *prop_item; proto_tree *prop_tree, *flags_tree; - guint16 prop_type; - guint16 prop_length; + guint32 prop_type; + guint32 prop_length; - prop_type = tvb_get_ntohs(tvb, offset); prop_length = tvb_get_ntohs(tvb, offset + 2); - prop_tree = proto_tree_add_subtree(tree, tvb, offset, prop_length, ett_openflow_v6_tablemod_prop, NULL, "Tablemod property"); + prop_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_openflow_v6_tablemod_prop, &ti, "Tablemod property"); /* uint16_t type; */ - proto_tree_add_item(prop_tree, hf_openflow_v6_tablemod_prop_type, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(prop_tree, hf_openflow_v6_tablemod_prop_type, tvb, offset, 2, ENC_BIG_ENDIAN, &prop_type); offset+=2; /* uint16_t len; */ - prop_item = proto_tree_add_item(prop_tree, hf_openflow_v6_tablemod_prop_length, tvb, offset, 2, ENC_BIG_ENDIAN); + prop_item = proto_tree_add_item_ret_uint(prop_tree, hf_openflow_v6_tablemod_prop_length, tvb, offset, 2, ENC_BIG_ENDIAN, &prop_length); + proto_item_set_len(ti, prop_length); offset+=2; switch (prop_type) { @@ -3583,23 +3811,28 @@ dissect_openflow_aggregate_stats_request_v6(tvbuff_t *tvb, packet_info *pinfo _U } -#define OFPTFPT_INSTRUCTIONS 0 -#define OFPTFPT_INSTRUCTIONS_MISS 1 -#define OFPTFPT_NEXT_TABLES 2 -#define OFPTFPT_NEXT_TABLES_MISS 3 -#define OFPTFPT_WRITE_ACTIONS 4 -#define OFPTFPT_WRITE_ACTIONS_MISS 5 -#define OFPTFPT_APPLY_ACTIONS 6 -#define OFPTFPT_APPLY_ACTIONS_MISS 7 -#define OFPTFPT_MATCH 8 -#define OFPTFPT_WILDCARDS 10 -#define OFPTFPT_WRITE_SETFIELD 12 -#define OFPTFPT_WRITE_SETFIELD_MISS 13 -#define OFPTFPT_APPLY_SETFIELD 14 -#define OFPTFPT_APPLY_SETFIELD_MISS 15 -#define OFPTFPT_TABLE_SYNC_FROM 16 -#define OFPTFPT_EXPERIMENTER 0xFFFE -#define OFPTFPT_EXPERIMENTER_MISS 0xFFFF +#define OFPTFPT_INSTRUCTIONS 0 +#define OFPTFPT_INSTRUCTIONS_MISS 1 +#define OFPTFPT_NEXT_TABLES 2 +#define OFPTFPT_NEXT_TABLES_MISS 3 +#define OFPTFPT_WRITE_ACTIONS 4 +#define OFPTFPT_WRITE_ACTIONS_MISS 5 +#define OFPTFPT_APPLY_ACTIONS 6 +#define OFPTFPT_APPLY_ACTIONS_MISS 7 +#define OFPTFPT_MATCH 8 +#define OFPTFPT_WILDCARDS 10 +#define OFPTFPT_WRITE_SETFIELD 12 +#define OFPTFPT_WRITE_SETFIELD_MISS 13 +#define OFPTFPT_APPLY_SETFIELD 14 +#define OFPTFPT_APPLY_SETFIELD_MISS 15 +#define OFPTFPT_TABLE_SYNC_FROM 16 +#define OFPTFPT_WRITE_COPYFIELD 18 +#define OFPTFPT_WRITE_COPYFIELD_MISS 19 +#define OFPTFPT_APPLY_COPYFIELD 20 +#define OFPTFPT_APPLY_COPYFIELD_MISS 21 +#define OFPTFPT_PACKET_TYPES 22 +#define OFPTFPT_EXPERIMENTER 0xFFFE +#define OFPTFPT_EXPERIMENTER_MISS 0xFFFF static const value_string openflow_v6_table_feature_prop_type_values[] = { { OFPTFPT_INSTRUCTIONS, "OFPTFPT_INSTRUCTIONS" }, { OFPTFPT_INSTRUCTIONS_MISS, "OFPTFPT_INSTRUCTIONS_MISS" }, @@ -3618,7 +3851,14 @@ static const value_string openflow_v6_table_feature_prop_type_values[] = { { OFPTFPT_EXPERIMENTER, "OFPTFPT_EXPERIMENTER" }, { OFPTFPT_EXPERIMENTER_MISS, "OFPTFPT_EXPERIMENTER_MISS" }, { OFPTFPT_TABLE_SYNC_FROM, "OFPTFPT_TABLE_SYNC_FROM" }, - { 0, NULL } + { OFPTFPT_WRITE_COPYFIELD, "OFPTFPT_WRITE_COPYFIELD" }, + { OFPTFPT_WRITE_COPYFIELD_MISS,"OFPTFPT_WRITE_COPYFIELD_MISS" }, + { OFPTFPT_APPLY_COPYFIELD, "OFPTFPT_APPLY_COPYFIELD" }, + { OFPTFPT_APPLY_COPYFIELD_MISS,"OFPTFPT_APPLY_COPYFIELD_MISS" }, + { OFPTFPT_PACKET_TYPES, "OFPTFPT_PACKET_TYPES" }, + { OFPTFPT_EXPERIMENTER, "OFPTFPT_EXPERIMENTER" }, + { OFPTFPT_EXPERIMENTER_MISS, "OFPTFPT_EXPERIMENTER_MISS" }, + { 0, NULL } }; @@ -3627,8 +3867,8 @@ dissect_openflow_table_feature_prop_v6(tvbuff_t *tvb, packet_info *pinfo _U_, pr { proto_item *ti; proto_tree *prop_tree, *elem_tree; - guint16 prop_type; - guint16 prop_length; + guint32 prop_type; + guint32 prop_length; guint16 elem_begin; gint32 body_end; guint16 pad_length; @@ -3636,14 +3876,12 @@ dissect_openflow_table_feature_prop_v6(tvbuff_t *tvb, packet_info *pinfo _U_, pr prop_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_openflow_v6_table_feature_prop, &ti, "Table feature property"); /* uint16_t type; */ - prop_type = tvb_get_ntohs(tvb, offset); - proto_tree_add_item(prop_tree, hf_openflow_v6_table_feature_prop_type, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(prop_tree, hf_openflow_v6_table_feature_prop_type, tvb, offset, 2, ENC_BIG_ENDIAN, &prop_type); offset+=2; /* uint16_t length; */ - prop_length = tvb_get_ntohs(tvb, offset); + proto_tree_add_item_ret_uint(prop_tree, hf_openflow_v6_table_feature_prop_length, tvb, offset, 2, ENC_BIG_ENDIAN, &prop_length); proto_item_set_len(ti, prop_length); - proto_tree_add_item(prop_tree, hf_openflow_v6_table_feature_prop_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; if (prop_length < 4) { @@ -3660,7 +3898,7 @@ dissect_openflow_table_feature_prop_v6(tvbuff_t *tvb, packet_info *pinfo _U_, pr elem_begin = offset; elem_tree = proto_tree_add_subtree(prop_tree, tvb, offset, -1, ett_openflow_v6_table_feature_prop_instruction_id, &ti, "Instruction ID"); - offset = dissect_openflow_instruction_header_v6(tvb, pinfo, elem_tree, offset, length); + offset = dissect_openflow_instruction_header_v6(tvb, pinfo, elem_tree, offset, length, NULL); proto_item_set_len(ti, offset - elem_begin); } break; @@ -3692,11 +3930,15 @@ dissect_openflow_table_feature_prop_v6(tvbuff_t *tvb, packet_info *pinfo _U_, pr case OFPTFPT_WRITE_SETFIELD_MISS: case OFPTFPT_APPLY_SETFIELD: case OFPTFPT_APPLY_SETFIELD_MISS: + case OFPTFPT_WRITE_COPYFIELD: + case OFPTFPT_WRITE_COPYFIELD_MISS: + case OFPTFPT_APPLY_COPYFIELD: + case OFPTFPT_APPLY_COPYFIELD_MISS: while (offset < body_end) { elem_begin = offset; elem_tree = proto_tree_add_subtree(prop_tree, tvb, offset, -1, ett_openflow_v6_table_feature_prop_oxm_id, &ti, "OXM ID"); - offset = dissect_openflow_oxm_header_v6(tvb, pinfo, elem_tree, offset, length); + offset = dissect_openflow_oxm_header_v6(tvb, pinfo, elem_tree, offset, length, NULL); proto_item_set_len(ti, offset - elem_begin); } break; @@ -3708,6 +3950,16 @@ dissect_openflow_table_feature_prop_v6(tvbuff_t *tvb, packet_info *pinfo _U_, pr } break; + case OFPTFPT_PACKET_TYPES: + while (offset < body_end) { + elem_begin = offset; + elem_tree = proto_tree_add_subtree(prop_tree, tvb, offset, -1, ett_openflow_v6_table_feature_prop_oxm_id, &ti, "OXM ID"); + + offset = dissect_openflow_oxm_v6(tvb, pinfo, elem_tree, offset, length); + proto_item_set_len(ti, offset - elem_begin); + } + break; + case OFPTFPT_EXPERIMENTER: case OFPTFPT_EXPERIMENTER_MISS: /* uint32_t experimenter; */ @@ -3747,16 +3999,15 @@ dissect_openflow_table_features_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_ { proto_item *ti; proto_tree *feat_tree, *caps_tree; - guint16 feat_length; + guint32 feat_length; gint32 feat_end; feat_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_openflow_v6_table_features, &ti, "Table features"); /* uint16_t length; */ - feat_length = tvb_get_ntohs(tvb, offset); + proto_tree_add_item_ret_uint(feat_tree, hf_openflow_v6_table_features_length, tvb, offset, 2, ENC_BIG_ENDIAN, &feat_length); feat_end = offset + feat_length; proto_item_set_len(ti, feat_length); - proto_tree_add_item(feat_tree, hf_openflow_v6_table_features_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; /* uint8_t table_id; */ @@ -3946,43 +4197,170 @@ dissect_openflow_flow_monitor_request_v6(tvbuff_t *tvb, packet_info *pinfo _U_, dissect_openflow_match_v6(tvb, pinfo, tree, offset, length); } -#define OFPMP_DESC 0 -#define OFPMP_FLOW 1 -#define OFPMP_AGGREGATE 2 -#define OFPMP_TABLE 3 -#define OFPMP_PORT_STATS 4 -#define OFPMP_QUEUE_STATS 5 -#define OFPMP_GROUP 6 -#define OFPMP_GROUP_DESC 7 -#define OFPMP_GROUP_FEATURES 8 -#define OFPMP_METER 9 -#define OFPMP_METER_DESC 10 -#define OFPMP_METER_FEATURES 11 -#define OFPMP_TABLE_FEATURES 12 -#define OFPMP_PORT_DESC 13 -#define OFPMP_TABLE_DESC 14 -#define OFPMP_QUEUE_DESC 15 -#define OFPMP_FLOW_MONITOR 16 +static int +dissect_openflow_time_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) +{ + /* uint64_t seconds; */ + proto_tree_add_item(tree, hf_openflow_v6_time_seconds, tvb, offset, 8, ENC_BIG_ENDIAN); + offset+=8; + + /* uint32_t nanoseconds; */ + proto_tree_add_item(tree, hf_openflow_v6_time_nanoseconds, tvb, offset, 4, ENC_BIG_ENDIAN); + offset+=4; + + /* uint8_t pad[4]; */ + proto_tree_add_item(tree, hf_openflow_v6_time_pad, tvb, offset, 4, ENC_NA); + offset+=4; + + return offset; +} + +#define OFPTMPBF_TIME_CAPABILITY 1 +#define OFPTMPBF_EXPERIMENTER 0xFFFF +static const value_string openflow_v6_bundle_feature_prop_type_values[] = { + { OFPTMPBF_TIME_CAPABILITY, "OFPTMPBF_TIME_CAPABILITY" }, + { OFPTMPBF_EXPERIMENTER, "OFPTMPBF_EXPERIMENTER" }, + { 0, NULL } +}; + + +static int +dissect_openflow_bundle_feature_prop_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length) +{ + proto_item *ti; + proto_tree *prop_tree; + guint32 prop_type; + guint32 prop_length; + gint32 body_end; + guint16 pad_length; + + prop_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_openflow_v6_bundle_feature_prop, &ti, "Bundle feature property"); + + /* uint16_t type; */ + proto_tree_add_item_ret_uint(prop_tree, hf_openflow_v6_bundle_feature_prop_type, tvb, offset, 2, ENC_BIG_ENDIAN, &prop_type); + offset+=2; + + /* uint16_t length; */ + proto_tree_add_item_ret_uint(prop_tree, hf_openflow_v6_bundle_feature_prop_length, tvb, offset, 2, ENC_BIG_ENDIAN, &prop_length); + proto_item_set_len(ti, prop_length); + offset+=2; + + if (prop_length < 4) { + prop_length = 4; + } + + body_end = offset + prop_length - 4; + + /* body */ + switch (prop_type) { + case OFPTMPBF_TIME_CAPABILITY: + /* uint8_t pad[4]; */ + proto_tree_add_item(prop_tree, hf_openflow_v6_bundle_feature_prop_time_pad, tvb, offset, 4, ENC_NA); + offset+=4; + + /* struct ofp_time sched_accuracy; */ + offset = dissect_openflow_time_v6(tvb, pinfo, tree, offset, length); + + /* struct ofp_time sched_max_future; */ + offset = dissect_openflow_time_v6(tvb, pinfo, tree, offset, length); + + /* struct ofp_time sched_max_past; */ + offset = dissect_openflow_time_v6(tvb, pinfo, tree, offset, length); + + /* struct ofp_time timestamp; */ + offset = dissect_openflow_time_v6(tvb, pinfo, tree, offset, length); + break; + case OFPTMPBF_EXPERIMENTER: + /* uint32_t experimenter; */ + proto_tree_add_item(prop_tree, hf_openflow_v6_bundle_feature_prop_experimenter_experimenter, tvb, offset, 4, ENC_BIG_ENDIAN); + offset+=4; + + /* uint32_t exp_type; */ + proto_tree_add_item(prop_tree, hf_openflow_v6_bundle_feature_prop_experimenter_exp_type, tvb, offset, 4, ENC_BIG_ENDIAN); + offset+=4; + + /* uint32_t experimenter_data[0]; */ + proto_tree_add_expert_format(prop_tree, pinfo, &ei_openflow_v6_bundle_feature_prop_undecoded, + tvb, offset, body_end - offset, "Experimenter bundle property body."); + offset = body_end; + break; + + default: + proto_tree_add_expert_format(prop_tree, pinfo, &ei_openflow_v6_bundle_feature_prop_undecoded, + tvb, offset, body_end - offset, "Unknown bundle property body."); + offset = body_end; + break; + }; + + pad_length = (prop_length + 7)/8*8 - prop_length; + if (pad_length > 0) { + proto_tree_add_item(prop_tree, hf_openflow_v6_bundle_feature_prop_pad, tvb, offset, pad_length, ENC_NA); + offset+=pad_length; + } + + return offset; +} + +static void +dissect_openflow_bundle_features_request_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) +{ + /* uint32_t feature_request_flags; */ + proto_tree_add_item(tree, hf_openflow_v6_bundle_features_request_flags, tvb, offset, 4, ENC_BIG_ENDIAN); + offset+=4; + + /* uint8_t pad[4]; */ + proto_tree_add_item(tree, hf_openflow_v6_bundle_features_request_pad, tvb, offset, 4, ENC_NA); + offset+=4; + + /* struct ofp_bundle_features_prop_header properties[0]; */ + while (offset < length) { + offset = dissect_openflow_bundle_feature_prop_v6(tvb, pinfo, tree, offset, length); + } +} + +#define OFPMP_DESC 0 +#define OFPMP_FLOW_DESC 1 +#define OFPMP_AGGREGATE_STATS 2 +#define OFPMP_TABLE_STATS 3 +#define OFPMP_PORT_STATS 4 +#define OFPMP_QUEUE_STATS 5 +#define OFPMP_GROUP_STATS 6 +#define OFPMP_GROUP_DESC 7 +#define OFPMP_GROUP_FEATURES 8 +#define OFPMP_METER_STATS 9 +#define OFPMP_METER_DESC 10 +#define OFPMP_METER_FEATURES 11 +#define OFPMP_TABLE_FEATURES 12 +#define OFPMP_PORT_DESC 13 +#define OFPMP_TABLE_DESC 14 +#define OFPMP_QUEUE_DESC 15 +#define OFPMP_FLOW_MONITOR 16 +#define OFPMP_FLOW_STATS 17 +#define OFPMP_CONTROLLER_STATUS 18 +#define OFPMP_BUNDLE_FEATURES 19 #define OFPMP_EXPERIMENTER 0xffff static const value_string openflow_v6_multipart_type_values[] = { - { OFPMP_DESC, "OFPMP_DESC" }, - { OFPMP_FLOW, "OFPMP_FLOW" }, - { OFPMP_AGGREGATE, "OFPMP_AGGREGATE" }, - { OFPMP_TABLE, "OFPMP_TABLE" }, - { OFPMP_PORT_STATS, "OFPMP_PORT_STATS" }, - { OFPMP_QUEUE_STATS, "OFPMP_QUEUE_STATS" }, - { OFPMP_GROUP, "OFPMP_GROUP" }, - { OFPMP_GROUP_DESC, "OFPMP_GROUP_DESC" }, - { OFPMP_GROUP_FEATURES, "OFPMP_GROUP_FEATURES" }, - { OFPMP_METER, "OFPMP_METER" }, - { OFPMP_METER_DESC, "OFPMP_METER_DESC" }, - { OFPMP_METER_FEATURES, "OFPMP_METER_FEATURES" }, - { OFPMP_TABLE_FEATURES, "OFPMP_TABLE_FEATURES" }, - { OFPMP_PORT_DESC, "OFPMP_PORT_DESC" }, - { OFPMP_TABLE_DESC, "OFPMP_TABLE_DESC" }, - { OFPMP_QUEUE_DESC, "OFPMP_QUEUE_DESC" }, - { OFPMP_FLOW_MONITOR, "OFPMP_FLOW_MONITOR" }, - { OFPMP_EXPERIMENTER, "OFPMP_EXPERIMENTER" }, + { OFPMP_DESC, "OFPMP_DESC" }, + { OFPMP_FLOW_DESC, "OFPMP_FLOW_DESC" }, + { OFPMP_AGGREGATE_STATS, "OFPMP_AGGREGATE_STATS" }, + { OFPMP_TABLE_STATS, "OFPMP_TABLE_STATS" }, + { OFPMP_PORT_STATS, "OFPMP_PORT_STATS" }, + { OFPMP_QUEUE_STATS, "OFPMP_QUEUE_STATS" }, + { OFPMP_GROUP_STATS, "OFPMP_GROUP_STATS" }, + { OFPMP_GROUP_DESC, "OFPMP_GROUP_DESC" }, + { OFPMP_GROUP_FEATURES, "OFPMP_GROUP_FEATURES" }, + { OFPMP_METER_STATS, "OFPMP_METER_STATS" }, + { OFPMP_METER_DESC, "OFPMP_METER_DESC" }, + { OFPMP_METER_FEATURES, "OFPMP_METER_FEATURES" }, + { OFPMP_TABLE_FEATURES, "OFPMP_TABLE_FEATURES" }, + { OFPMP_PORT_DESC, "OFPMP_PORT_DESC" }, + { OFPMP_TABLE_DESC, "OFPMP_TABLE_DESC" }, + { OFPMP_QUEUE_DESC, "OFPMP_QUEUE_DESC" }, + { OFPMP_FLOW_MONITOR, "OFPMP_FLOW_MONITOR" }, + { OFPMP_FLOW_STATS, "OFPMP_FLOW_STATS" }, + { OFPMP_CONTROLLER_STATUS, "OFPMP_CONTROLLER_STATUS" }, + { OFPMP_BUNDLE_FEATURES, "OFPMP_BUNDLE_FEATURES" }, + { OFPMP_EXPERIMENTER, "OFPMP_EXPERIMENTER" }, { 0, NULL } }; @@ -3992,11 +4370,10 @@ dissect_openflow_multipart_request_v6(tvbuff_t *tvb, packet_info *pinfo _U_, pro { proto_item *ti; proto_tree *flags_tree; - guint16 type; + guint32 type; /* uint16_t type; */ - type = tvb_get_ntohs(tvb, offset); - proto_tree_add_item(tree, hf_openflow_v6_multipart_request_type , tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(tree, hf_openflow_v6_multipart_request_type , tvb, offset, 2, ENC_BIG_ENDIAN, &type); offset+=2; /* uint16_t flags; */ @@ -4011,18 +4388,18 @@ dissect_openflow_multipart_request_v6(tvbuff_t *tvb, packet_info *pinfo _U_, pro offset+=4; /* uint8_t body[0]; */ - switch(type){ + switch (type) { case OFPMP_DESC: /* The request body is empty. */ break; - case OFPMP_FLOW: + case OFPMP_FLOW_DESC: dissect_openflow_flow_stats_request_v6(tvb, pinfo, tree, offset, length); break; - case OFPMP_AGGREGATE: + case OFPMP_AGGREGATE_STATS: dissect_openflow_aggregate_stats_request_v6(tvb, pinfo, tree, offset, length); break; - case OFPMP_TABLE: - /* The request body is empty. */ + case OFPMP_TABLE_STATS: + /* The request body is empty. */ break; case OFPMP_PORT_STATS: dissect_openflow_port_stats_request_v6(tvb, pinfo, tree, offset, length); @@ -4030,7 +4407,7 @@ dissect_openflow_multipart_request_v6(tvbuff_t *tvb, packet_info *pinfo _U_, pro case OFPMP_QUEUE_STATS: dissect_openflow_queue_stats_request_v6(tvb, pinfo, tree, offset, length); break; - case OFPMP_GROUP: + case OFPMP_GROUP_STATS: dissect_openflow_group_stats_request_v6(tvb, pinfo, tree, offset, length); break; case OFPMP_GROUP_DESC: @@ -4039,7 +4416,7 @@ dissect_openflow_multipart_request_v6(tvbuff_t *tvb, packet_info *pinfo _U_, pro case OFPMP_GROUP_FEATURES: /* The request body is empty. */ break; - case OFPMP_METER: + case OFPMP_METER_STATS: dissect_openflow_meter_stats_request_v6(tvb, pinfo, tree, offset, length); break; case OFPMP_METER_DESC: @@ -4065,6 +4442,15 @@ dissect_openflow_multipart_request_v6(tvbuff_t *tvb, packet_info *pinfo _U_, pro case OFPMP_FLOW_MONITOR: dissect_openflow_flow_monitor_request_v6(tvb, pinfo, tree, offset, length); break; + case OFPMP_FLOW_STATS: + dissect_openflow_flow_stats_request_v6(tvb, pinfo, tree, offset, length); + break; + case OFPMP_CONTROLLER_STATUS: + /* The request body is empty. */ + break; + case OFPMP_BUNDLE_FEATURES: + dissect_openflow_bundle_features_request_v6(tvb, pinfo, tree, offset, length); + break; case OFPMP_EXPERIMENTER: /* uint32_t experimenter; */ proto_tree_add_item(tree, hf_openflow_v6_multipart_request_experimenter_experimenter, tvb, offset, 4, ENC_BIG_ENDIAN); @@ -4116,111 +4502,131 @@ dissect_openflow_switch_description_v6(tvbuff_t *tvb, packet_info *pinfo _U_, pr static int -dissect_openflow_flow_stats_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) +dissect_openflow_flow_desc_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) { proto_item *ti; - proto_tree *stats_tree, *flags_tree; - guint16 stats_len; - gint32 stats_end; + proto_tree *desc_tree, *flags_tree; + guint32 desc_len; + gint32 desc_end; - stats_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_openflow_v6_flow_stats, &ti, "Flow stats"); + desc_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_openflow_v6_flow_desc, &ti, "Flow desc"); /* uint16_t length; */ - stats_len = tvb_get_ntohs(tvb, offset); - stats_end = offset + stats_len; - proto_item_set_len(ti, stats_len); - proto_tree_add_item(stats_tree, hf_openflow_v6_flow_stats_length, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(desc_tree, hf_openflow_v6_flow_desc_length, tvb, offset, 2, ENC_BIG_ENDIAN, &desc_len); + desc_end = offset + desc_len; + proto_item_set_len(ti, desc_len); + offset+=2; + + /* uint8_t pad2[2]; */ + proto_tree_add_item(desc_tree, hf_openflow_v6_flow_desc_pad2, tvb, offset, 2, ENC_NA); offset+=2; /* uint8_t table_id; */ - proto_tree_add_item(stats_tree, hf_openflow_v6_flow_stats_table_id, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(desc_tree, hf_openflow_v6_flow_desc_table_id, tvb, offset, 1, ENC_BIG_ENDIAN); offset+=1; /* uint8_t pad; */ - proto_tree_add_item(stats_tree, hf_openflow_v6_flow_stats_pad, tvb, offset, 1, ENC_NA); + proto_tree_add_item(desc_tree, hf_openflow_v6_flow_desc_pad, tvb, offset, 1, ENC_NA); offset+=1; - /* uint32_t duration_sec; */ - proto_tree_add_item(stats_tree, hf_openflow_v6_flow_stats_duration_sec, tvb, offset, 4, ENC_BIG_ENDIAN); - offset+=4; - - /* uint32_t duration_nsec; */ - proto_tree_add_item(stats_tree, hf_openflow_v6_flow_stats_duration_nsec, tvb, offset, 4, ENC_BIG_ENDIAN); - offset+=4; - /* uint16_t priority; */ - proto_tree_add_item(stats_tree, hf_openflow_v6_flow_stats_priority, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(desc_tree, hf_openflow_v6_flow_desc_priority, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; /* uint16_t idle_timeout; */ - proto_tree_add_item(stats_tree, hf_openflow_v6_flow_stats_idle_timeout, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(desc_tree, hf_openflow_v6_flow_desc_idle_timeout, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; /* uint16_t hard_timeout; */ - proto_tree_add_item(stats_tree, hf_openflow_v6_flow_stats_hard_timeout, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(desc_tree, hf_openflow_v6_flow_desc_hard_timeout, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; /* uint16_t flags; */ - ti = proto_tree_add_item(stats_tree, hf_openflow_v6_flow_stats_flags, tvb, offset, 2, ENC_BIG_ENDIAN); - flags_tree = proto_item_add_subtree(ti, ett_openflow_v6_flow_stats_flags); - - proto_tree_add_item(flags_tree, hf_openflow_v6_flow_stats_flags_send_flow_rem, tvb, offset, 2, ENC_BIG_ENDIAN); - proto_tree_add_item(flags_tree, hf_openflow_v6_flow_stats_flags_check_overlap, tvb, offset, 2, ENC_BIG_ENDIAN); - proto_tree_add_item(flags_tree, hf_openflow_v6_flow_stats_flags_reset_counts, tvb, offset, 2, ENC_BIG_ENDIAN); - proto_tree_add_item(flags_tree, hf_openflow_v6_flow_stats_flags_no_packet_counts, tvb, offset, 2, ENC_BIG_ENDIAN); - proto_tree_add_item(flags_tree, hf_openflow_v6_flow_stats_flags_no_byte_counts, tvb, offset, 2, ENC_BIG_ENDIAN); + ti = proto_tree_add_item(desc_tree, hf_openflow_v6_flow_desc_flags, tvb, offset, 2, ENC_BIG_ENDIAN); + flags_tree = proto_item_add_subtree(ti, ett_openflow_v6_flow_desc_flags); + + proto_tree_add_item(flags_tree, hf_openflow_v6_flow_desc_flags_send_flow_rem, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(flags_tree, hf_openflow_v6_flow_desc_flags_check_overlap, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(flags_tree, hf_openflow_v6_flow_desc_flags_reset_counts, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(flags_tree, hf_openflow_v6_flow_desc_flags_no_packet_counts, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(flags_tree, hf_openflow_v6_flow_desc_flags_no_byte_counts, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; /* uint16_t importance; */ - proto_tree_add_item(stats_tree, hf_openflow_v6_flow_stats_importance, tvb, offset, 4, ENC_BIG_ENDIAN); - offset+=2; - - /* uint8_t pad2[2]; */ - proto_tree_add_item(stats_tree, hf_openflow_v6_flow_stats_pad2, tvb, offset, 4, ENC_NA); + proto_tree_add_item(desc_tree, hf_openflow_v6_flow_desc_importance, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=2; /* uint64_t cookie; */ - proto_tree_add_item(stats_tree, hf_openflow_v6_flow_stats_cookie, tvb, offset, 8, ENC_BIG_ENDIAN); - offset+=8; - - /* uint64_t packet_count; */ - proto_tree_add_item(stats_tree, hf_openflow_v6_flow_stats_packet_count, tvb, offset, 8, ENC_BIG_ENDIAN); - offset+=8; - - /* uint64_t byte_count; */ - proto_tree_add_item(stats_tree, hf_openflow_v6_flow_stats_byte_count, tvb, offset, 8, ENC_BIG_ENDIAN); + proto_tree_add_item(desc_tree, hf_openflow_v6_flow_desc_cookie, tvb, offset, 8, ENC_BIG_ENDIAN); offset+=8; /* struct ofp_match match; */ - offset = dissect_openflow_match_v6(tvb, pinfo, stats_tree, offset, length); + offset = dissect_openflow_match_v6(tvb, pinfo, desc_tree, offset, length); + + /* struct ofp_stats stats; */ + offset = dissect_openflow_stats_v6(tvb, pinfo, desc_tree, offset, length); /* struct ofp_instruction instructions[0]; */ - while (offset < stats_end) { - offset = dissect_openflow_instruction_v6(tvb, pinfo, stats_tree, offset, length); + while (offset < desc_end) { + offset = dissect_openflow_instruction_v6(tvb, pinfo, desc_tree, offset, length); } return offset; } -static void -dissect_openflow_aggregate_stats_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) +#define OFPFSR_STATS_REQUEST 0 +#define OFPFSR_STAT_TRIGGER 1 +static const value_string openflow_v6_flow_stats_reason_values[] = { + { OFPFSR_STATS_REQUEST, "OFPFSR_STATS_REQUEST" }, + { OFPFSR_STAT_TRIGGER, "OFPFSR_STAT_TRIGGER" }, + { 0, NULL } +}; + +static int +dissect_openflow_flow_stats_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) { - /* uint64_t packet_count; */ - proto_tree_add_item(tree, hf_openflow_v6_aggregate_stats_packet_count, tvb, offset, 8, ENC_BIG_ENDIAN); - offset+=8; + proto_item *ti; + proto_tree *stats_tree; + guint32 stats_len; - /* uint64_t byte_count; */ - proto_tree_add_item(tree, hf_openflow_v6_aggregate_stats_byte_count, tvb, offset, 8, ENC_BIG_ENDIAN); - offset+=8; + stats_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_openflow_v6_flow_stats, &ti, "Flow stats"); - /* uint32_t flow_count; */ - proto_tree_add_item(tree, hf_openflow_v6_aggregate_stats_flow_count, tvb, offset, 4, ENC_BIG_ENDIAN); - offset+=4; + /* uint16_t length; */ + proto_tree_add_item_ret_uint(stats_tree, hf_openflow_v6_flow_stats_length, tvb, offset, 2, ENC_BIG_ENDIAN, &stats_len); + proto_item_set_len(ti, stats_len); + offset+=2; - /* uint8_t pad[4]; */ - proto_tree_add_item(tree, hf_openflow_v6_aggregate_stats_pad, tvb, offset, 4, ENC_NA); - /*offset+=4;*/ + /* uint8_t pad2[2]; */ + proto_tree_add_item(stats_tree, hf_openflow_v6_flow_stats_pad2, tvb, offset, 2, ENC_NA); + offset+=1; + + /* uint8_t table_id; */ + proto_tree_add_item(stats_tree, hf_openflow_v6_flow_stats_table_id, tvb, offset, 1, ENC_BIG_ENDIAN); + offset+=1; + + /* uint8_t reason; */ + proto_tree_add_item(stats_tree, hf_openflow_v6_flow_stats_reason, tvb, offset, 1, ENC_BIG_ENDIAN); + offset+=1; + + /* uint16_t priority; */ + proto_tree_add_item(stats_tree, hf_openflow_v6_flow_stats_priority, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + + /* struct ofp_match match; */ + offset = dissect_openflow_match_v6(tvb, pinfo, stats_tree, offset, length); + + /* struct ofp_stats stats; */ + offset = dissect_openflow_stats_v6(tvb, pinfo, stats_tree, offset, length); + + return offset; +} + + +static void +dissect_openflow_aggregate_stats_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) +{ + dissect_openflow_stats_v6(tvb, pinfo, tree, offset, length); } @@ -4369,21 +4775,19 @@ static int dissect_openflow_port_stats_prop_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) { proto_tree *prop_tree; - proto_item *prop_item; - guint16 prop_type; - guint16 prop_length; - - prop_type = tvb_get_ntohs(tvb, offset); - prop_length = tvb_get_ntohs(tvb, offset); + proto_item *ti, *prop_item; + guint32 prop_type; + guint32 prop_length; - prop_tree = proto_tree_add_subtree(tree, tvb, offset, prop_length, ett_openflow_v6_port_stats_prop, NULL, "Port stats. property"); + prop_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_openflow_v6_port_stats_prop, &ti, "Port stats. property"); /* uint16_t type; */ - proto_tree_add_item(prop_tree, hf_openflow_v6_port_stats_prop_type, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(prop_tree, hf_openflow_v6_port_stats_prop_type, tvb, offset, 2, ENC_BIG_ENDIAN, &prop_type); offset+=2; /* uint16_t len; */ - prop_item = proto_tree_add_item(prop_tree, hf_openflow_v6_port_stats_prop_length, tvb, offset, 2, ENC_BIG_ENDIAN); + prop_item = proto_tree_add_item_ret_uint(prop_tree, hf_openflow_v6_port_stats_prop_length, tvb, offset, 2, ENC_BIG_ENDIAN, &prop_length); + proto_item_set_len(ti, prop_length); offset+=2; switch (prop_type) { @@ -4434,13 +4838,14 @@ static int dissect_openflow_port_stats_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) { proto_tree *stats_tree; + guint32 stats_length; guint16 stats_end; stats_tree = proto_tree_add_subtree(tree, tvb, offset, 112, ett_openflow_v6_port_stats, NULL, "Port stats"); /* uint16_t length; */ - stats_end = tvb_get_ntohs(tvb, offset) + offset - 4; - proto_tree_add_item(stats_tree, hf_openflow_v6_port_stats_length, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(stats_tree, hf_openflow_v6_port_stats_length, tvb, offset, 2, ENC_BIG_ENDIAN, &stats_length); + stats_end = stats_length + offset - 4; offset+=2; /* uint8_t pad[2]; */ @@ -4506,16 +4911,15 @@ dissect_openflow_table_desc_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree { proto_item *ti; proto_tree *desc_tree, *conf_tree; - guint16 desc_length; + guint32 desc_length; gint32 desc_end; - desc_length = tvb_get_ntohs(tvb, offset); - desc_end = offset + desc_length; - - desc_tree = proto_tree_add_subtree(tree, tvb, offset, desc_length, ett_openflow_v6_table_desc, NULL, "Table desc"); + desc_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_openflow_v6_table_desc, &ti, "Table desc"); /* uint16_t length; */ - proto_tree_add_item(desc_tree, hf_openflow_v6_table_desc_length, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(desc_tree, hf_openflow_v6_table_desc_length, tvb, offset, 2, ENC_BIG_ENDIAN, &desc_length); + proto_item_set_len(ti, desc_length); + desc_end = offset + desc_length; offset+=2; /* uint8_t table_id; */ @@ -4555,16 +4959,15 @@ dissect_openflow_queue_stats_prop_v6(tvbuff_t *tvb, packet_info *pinfo _U_, prot { proto_tree *prop_tree; proto_item *prop_item; - guint16 prop_type; + guint32 prop_type; guint16 prop_length; - prop_type = tvb_get_ntohs(tvb, offset); prop_length = tvb_get_ntohs(tvb, offset + 2); prop_tree = proto_tree_add_subtree(tree, tvb, offset, prop_length, ett_openflow_v6_queue_stats_prop, NULL, "Queue stats property"); /* uint16_t type; */ - proto_tree_add_item(prop_tree, hf_openflow_v6_queue_stats_prop_type, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(prop_tree, hf_openflow_v6_queue_stats_prop_type, tvb, offset, 2, ENC_BIG_ENDIAN, &prop_type); offset+=2; /* uint16_t len; */ @@ -5104,14 +5507,13 @@ dissect_openflow_queue_desc_prop_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto { proto_item *ti; proto_tree *prop_tree; - guint16 prop_type; + guint32 prop_type; guint16 prop_len; prop_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_openflow_v6_queue_desc_prop, &ti, "Queue property"); /* uint16_t property; */ - prop_type = tvb_get_ntohs(tvb, offset); - proto_tree_add_item(prop_tree, hf_openflow_v6_queue_desc_prop_property, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(prop_tree, hf_openflow_v6_queue_desc_prop_property, tvb, offset, 2, ENC_BIG_ENDIAN, &prop_type); offset+=2; /* uint16_t len; */ @@ -5221,6 +5623,140 @@ dissect_openflow_queue_desc_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree } +#define OFPCSPT_URI 0 +#define OFPCSPT_EXPERIMENTER 0xFFFF +static const value_string openflow_v6_controller_status_prop_type_values[] = { + { OFPCSPT_URI, "OFPCSPT_URI" }, + { OFPCSPT_EXPERIMENTER, "OFPCSPT_EXPERIMENTER" }, + { 0, NULL } +}; + + +static int +dissect_openflow_controller_status_prop_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) +{ + proto_item *ti; + proto_tree *prop_tree; + guint32 prop_type; + guint32 prop_length; + gint32 body_end; + guint16 pad_length; + + prop_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_openflow_v6_controller_status_prop, &ti, "Controller status property"); + + /* uint16_t type; */ + proto_tree_add_item_ret_uint(prop_tree, hf_openflow_v6_controller_status_prop_type, tvb, offset, 2, ENC_BIG_ENDIAN, &prop_type); + offset+=2; + + /* uint16_t length; */ + proto_tree_add_item_ret_uint(prop_tree, hf_openflow_v6_controller_status_prop_length, tvb, offset, 2, ENC_BIG_ENDIAN, &prop_length); + proto_item_set_len(ti, prop_length); + offset+=2; + + if (prop_length < 4) { + prop_length = 4; + } + + body_end = offset + prop_length - 4; + + /* body */ + switch (prop_type) { + case OFPCSPT_URI: + /* uint8_t uri[0]; */ + proto_tree_add_item(tree, hf_openflow_v6_controller_status_prop_uri, tvb, offset, prop_length - 4, ENC_ASCII|ENC_NA); + offset += body_end; + break; + case OFPCSPT_EXPERIMENTER: + /* uint32_t experimenter; */ + proto_tree_add_item(prop_tree, hf_openflow_v6_controller_status_prop_experimenter_experimenter, tvb, offset, 4, ENC_BIG_ENDIAN); + offset+=4; + + /* uint32_t exp_type; */ + proto_tree_add_item(prop_tree, hf_openflow_v6_controller_status_prop_experimenter_exp_type, tvb, offset, 4, ENC_BIG_ENDIAN); + offset+=4; + + /* uint32_t experimenter_data[0]; */ + proto_tree_add_expert_format(prop_tree, pinfo, &ei_openflow_v6_controller_status_prop_undecoded, + tvb, offset, body_end - offset, "Experimenter controller property body."); + offset = body_end; + break; + + default: + proto_tree_add_expert_format(prop_tree, pinfo, &ei_openflow_v6_controller_status_prop_undecoded, + tvb, offset, body_end - offset, "Unknown controller property body."); + offset = body_end; + break; + }; + + pad_length = (prop_length + 7)/8*8 - prop_length; + if (pad_length > 0) { + proto_tree_add_item(prop_tree, hf_openflow_v6_controller_status_prop_pad, tvb, offset, pad_length, ENC_NA); + offset+=pad_length; + } + + return offset; +} + +#define OFPCSR_REQUEST 0 +#define OFPCSR_CHANNEL_STATUS 1 +#define OFPCSR_ROLE 2 +#define OFPCSR_CONTROLLER_ADDED 3 +#define OFPCSR_CONTROLLER_REMOVED 4 +#define OFPCSR_SHORT_ID 5 +#define OFPCSR_EXPERIMENTER 6 +static const value_string openflow_v6_controller_status_reason_values[] = { + { OFPCSR_REQUEST, "OFPCSR_REQUEST" }, + { OFPCSR_CHANNEL_STATUS, "OFPCSR_CHANNEL_STATUS" }, + { OFPCSR_ROLE, "OFPCSR_ROLE" }, + { OFPCSR_CONTROLLER_ADDED, "OFPCSR_CONTROLLER_ADDED" }, + { OFPCSR_CONTROLLER_REMOVED, "OFPCSR_CONTROLLER_REMOVED" }, + { OFPCSR_SHORT_ID, "OFPCSR_SHORT_ID" }, + { OFPCSR_EXPERIMENTER, "OFPCSR_EXPERIMENTER" }, + { 0, NULL } +}; + +#define OFPCT_STATUS_UP 0 +#define OFPCT_STATUS_DOWN 1 +static const value_string openflow_v6_controller_status_channel_status_values[] = { + { OFPCT_STATUS_UP, "OFPCT_STATUS_UP" }, + { OFPCT_STATUS_DOWN, "OFPCT_STATUS_DOWN" }, + { 0, NULL } +}; + +static int +dissect_openflow_controller_status_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) +{ + /* uint16_t length; */ + proto_tree_add_item(tree, hf_openflow_v6_controller_status_length, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + + /* uint16_t short_id; */ + proto_tree_add_item(tree, hf_openflow_v6_controller_status_short_id, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + + /* uint32_t role; */ + proto_tree_add_item(tree, hf_openflow_v6_controller_status_role, tvb, offset, 4, ENC_BIG_ENDIAN); + offset+=4; + + /* uint8_t reason; */ + proto_tree_add_item(tree, hf_openflow_v6_controller_status_reason, tvb, offset, 1, ENC_BIG_ENDIAN); + offset+=1; + + /* uint8_t channel_status; */ + proto_tree_add_item(tree, hf_openflow_v6_controller_status_channel_status, tvb, offset, 1, ENC_BIG_ENDIAN); + offset+=1; + + /* uint8_t pad[6]; */ + proto_tree_add_item(tree, hf_openflow_v6_controller_status_pad, tvb, offset, 6, ENC_NA); + offset+=6; + + /* struct ofp_controller_status_prop_header properties[0]; */ + // XXX Should it be a while loop? + dissect_openflow_controller_status_prop_v6(tvb, pinfo, tree, offset, length); + + return offset; +} + #define OFPFME_INITIAL 0 #define OFPFME_ADDED 1 #define OFPFME_REMOVED 2 @@ -5243,23 +5779,21 @@ static int dissect_openflow_flow_update_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) { proto_tree *update_tree; - guint16 update_len; - guint16 update_event; + guint32 update_len; + guint32 update_event; gint32 update_end; proto_item *ti; - update_len = tvb_get_ntohs(tvb, offset); - update_end = offset + update_len; - update_event = tvb_get_ntohs(tvb, offset + 2); - - update_tree = proto_tree_add_subtree(tree, tvb, offset, update_len, ett_openflow_v6_flow_update, NULL, "Flow update"); + update_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_openflow_v6_flow_update, &ti, "Flow update"); /* uint16_t length; */ - proto_tree_add_item(update_tree, hf_openflow_v6_flow_update_length, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(update_tree, hf_openflow_v6_flow_update_length, tvb, offset, 2, ENC_BIG_ENDIAN, &update_len); + update_end = offset + update_len; + proto_item_set_len(ti, update_len); offset+=2; /* uint16_t event; */ - ti = proto_tree_add_item(update_tree, hf_openflow_v6_flow_update_event, tvb, offset, 2, ENC_BIG_ENDIAN); + ti = proto_tree_add_item_ret_uint(update_tree, hf_openflow_v6_flow_update_event, tvb, offset, 2, ENC_BIG_ENDIAN, &update_event); offset+=2; if (update_len < 4) { @@ -5345,11 +5879,10 @@ dissect_openflow_multipart_reply_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto { proto_item *ti; proto_tree *flags_tree; - guint16 type; + guint32 type; /* uint16_t type; */ - type = tvb_get_ntohs(tvb, offset); - proto_tree_add_item(tree, hf_openflow_v6_multipart_reply_type, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(tree, hf_openflow_v6_multipart_reply_type, tvb, offset, 2, ENC_BIG_ENDIAN, &type); offset+=2; /* uint16_t flags; */ @@ -5367,15 +5900,13 @@ dissect_openflow_multipart_reply_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto case OFPMP_DESC: dissect_openflow_switch_description_v6(tvb, pinfo, tree, offset, length); break; - case OFPMP_FLOW: - while (offset < length) { - offset = dissect_openflow_flow_stats_v6(tvb, pinfo, tree, offset, length); - } + case OFPMP_FLOW_DESC: + dissect_openflow_flow_desc_v6(tvb, pinfo, tree, offset, length); break; - case OFPMP_AGGREGATE: + case OFPMP_AGGREGATE_STATS: dissect_openflow_aggregate_stats_v6(tvb, pinfo, tree, offset, length); break; - case OFPMP_TABLE: + case OFPMP_TABLE_STATS: while (offset < length) { offset = dissect_openflow_table_stats_v6(tvb, pinfo, tree, offset, length); } @@ -5390,7 +5921,7 @@ dissect_openflow_multipart_reply_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto offset = dissect_openflow_queue_stats_v6(tvb, pinfo, tree, offset, length); } break; - case OFPMP_GROUP: + case OFPMP_GROUP_STATS: while (offset < length) { offset = dissect_openflow_group_stats_v6(tvb, pinfo, tree, offset, length); } @@ -5403,7 +5934,7 @@ dissect_openflow_multipart_reply_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto case OFPMP_GROUP_FEATURES: dissect_openflow_group_features_v6(tvb, pinfo, tree, offset, length); break; - case OFPMP_METER: + case OFPMP_METER_STATS: while (offset < length) { offset = dissect_openflow_meter_stats_v6(tvb, pinfo, tree, offset, length); } @@ -5441,6 +5972,14 @@ dissect_openflow_multipart_reply_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto offset = dissect_openflow_flow_update_v6(tvb, pinfo, tree, offset, length); } break; + case OFPMP_FLOW_STATS: + while (offset < length) { + offset = dissect_openflow_flow_stats_v6(tvb, pinfo, tree, offset, length); + } + break; + case OFPMP_CONTROLLER_STATUS: + dissect_openflow_controller_status_v6(tvb, pinfo, tree, offset, length); + break; case OFPMP_EXPERIMENTER: /* uint32_t experimenter; */ @@ -5562,20 +6101,18 @@ dissect_openflow_async_config_prop_v6(tvbuff_t *tvb, packet_info *pinfo _U_, pro { proto_item *ti, *prop_item; proto_tree *prop_tree, *pi_tree, *ps_tree, *fr_tree, *rs_tree, *ts_tree, *rf_tree; - guint16 prop_type; - guint16 prop_len; + guint32 prop_type; + guint32 prop_len; - prop_type = tvb_get_ntohs(tvb, offset); - prop_len = tvb_get_ntohs(tvb, offset + 2); - - prop_tree = proto_tree_add_subtree(tree, tvb, offset, prop_len, ett_openflow_v6_async_config_prop, NULL, "Async config prop"); + prop_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_openflow_v6_async_config_prop, &ti, "Async config prop"); /* uint16_t type; */ - proto_tree_add_item(prop_tree, hf_openflow_v6_async_config_prop_type, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(prop_tree, hf_openflow_v6_async_config_prop_type, tvb, offset, 2, ENC_BIG_ENDIAN, &prop_type); offset += 2; /* uint16_t length; */ - prop_item = proto_tree_add_item(prop_tree, hf_openflow_v6_async_config_prop_length, tvb, offset, 2, ENC_BIG_ENDIAN); + prop_item = proto_tree_add_item_ret_uint(prop_tree, hf_openflow_v6_async_config_prop_length, tvb, offset, 2, ENC_BIG_ENDIAN, &prop_len); + proto_item_set_len(ti, prop_len); offset += 2; switch (prop_type) { @@ -5812,8 +6349,10 @@ dissect_openflow_requestforward_v6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_ } +#define OFPBPT_TIME 0x0001 #define OFPBPT_EXPERIMENTER 0xFFFF static const value_string openflow_v6_bundle_prop_type_values[] = { + { OFPBPT_TIME, "OFPBPT_TIME" }, { OFPBPT_EXPERIMENTER, "OFPBPT_EXPERIMENTER" }, { 0, NULL } }; @@ -5822,22 +6361,26 @@ static int dissect_openflow_bundle_prop_v6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint16 length) { proto_tree *prop_tree; - proto_item *prop_item; - guint16 prop_type; - guint16 prop_len; - - prop_type = tvb_get_ntohs(tvb, offset); - prop_len = tvb_get_ntohs(tvb, offset + 2); + proto_item *prop_item, *ti; + guint32 prop_type; + guint32 prop_len; - prop_tree = proto_tree_add_subtree(tree, tvb, offset, prop_len, ett_openflow_v6_bundle_prop, NULL, "Bundle prop"); + prop_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_openflow_v6_bundle_prop, &ti, "Bundle prop"); /* uint16_t type; */ - proto_tree_add_item(prop_tree, hf_openflow_v6_bundle_prop_type, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(prop_tree, hf_openflow_v6_bundle_prop_type, tvb, offset, 2, ENC_BIG_ENDIAN, &prop_type); + offset+=2; /* uint16_t length; */ - prop_item = proto_tree_add_item(prop_tree, hf_openflow_v6_bundle_prop_length, tvb, offset, 2, ENC_BIG_ENDIAN); + prop_item = proto_tree_add_item_ret_uint(prop_tree, hf_openflow_v6_bundle_prop_length, tvb, offset, 2, ENC_BIG_ENDIAN, &prop_len); + proto_item_set_len(ti, prop_len); + offset+=2; switch (prop_type) { + case OFPBPT_TIME: + dissect_openflow_time_v6(tvb, pinfo, tree, offset, length); + offset += prop_len - 4; + break; case OFPBPT_EXPERIMENTER: if (prop_len <= 12) { expert_add_info(pinfo, prop_item, &ei_openflow_v6_length_too_short); @@ -6071,6 +6614,9 @@ dissect_openflow_message_v6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, case OFPT_BUNDLE_ADD_MESSAGE: dissect_openflow_bundle_add_v6(tvb, pinfo, tree, offset, length); break; + case OFPT_CONTROLLER_STATUS: + dissect_openflow_controller_status_v6(tvb, pinfo, tree, offset, length); + break; default: if (length > 8) { @@ -6141,17 +6687,17 @@ proto_register_openflow_v6(void) }, { &hf_openflow_v6_oxm_field, { "Field", "openflow_v6.oxm.field", - FT_UINT8, BASE_DEC, NULL, 0x0, + FT_UINT8, BASE_DEC, NULL, OXM_FIELD_MASK, NULL, HFILL } }, { &hf_openflow_v6_oxm_field_basic, { "Field", "openflow_v6.oxm.field", - FT_UINT8, BASE_DEC | BASE_EXT_STRING, &openflow_v6_oxm_basic_field_values_ext, 0x0, + FT_UINT8, BASE_DEC | BASE_EXT_STRING, &openflow_v6_oxm_basic_field_values_ext, OXM_FIELD_MASK, NULL, HFILL } }, { &hf_openflow_v6_oxm_hm, { "Has mask", "openflow_v6.oxm.hm", - FT_BOOLEAN, BASE_NONE, NULL, 0x0, + FT_BOOLEAN, 8, NULL, OXM_HM_MASK, NULL, HFILL } }, { &hf_openflow_v6_oxm_length, @@ -6469,11 +7015,6 @@ proto_register_openflow_v6(void) FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, - { &hf_openflow_v6_instruction_meter_meter_id, - { "Meter ID", "openflow_v6.instruction.meter.meter_id", - FT_UINT32, BASE_DEC|BASE_SPECIAL_VALS, VALS(openflow_v6_meter_id_reserved_values), 0x0, - NULL, HFILL } - }, { &hf_openflow_v6_port_desc_prop_type, { "Type", "openflow_v6.port.desc_prop.type", FT_UINT16, BASE_DEC, VALS(openflow_v6_port_desc_prop_type_values), 0x0, @@ -7404,6 +7945,16 @@ proto_register_openflow_v6(void) FT_BOOLEAN, 32, NULL, OFPC_PORT_BLOCKED, NULL, HFILL } }, + { &hf_openflow_v6_switch_features_capabilities_bundles, + { "OFPC_BUNDLES", "openflow_v6.switch_features.capabilities.bundles", + FT_BOOLEAN, 32, NULL, OFPC_BUNDLES, + NULL, HFILL } + }, + { &hf_openflow_v6_switch_features_capabilities_flow_monitoring, + { "OFPC_FLOW_MONITORING", "openflow_v6.switch_features.capabilities.flow_monitoring", + FT_BOOLEAN, 32, NULL, OFPC_FLOW_MONITORING, + NULL, HFILL } + }, { &hf_openflow_v6_switch_features_reserved, { "Reserved", "openflow_v6.switch_features_reserved", FT_UINT32, BASE_HEX, NULL, 0x0, @@ -7474,16 +8025,6 @@ proto_register_openflow_v6(void) FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, - { &hf_openflow_v6_flow_removed_duration_sec, - { "Duration sec", "openflow_v6.flow_removed.duration_sec", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_openflow_v6_flow_removed_duration_nsec, - { "Duration nsec", "openflow_v6.flow_removed.duration_nsec", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, { &hf_openflow_v6_flow_removed_idle_timeout, { "Idle timeout", "openflow_v6.flow_removed.idle_timeout", FT_UINT16, BASE_DEC, NULL, 0x0, @@ -7494,16 +8035,6 @@ proto_register_openflow_v6(void) FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, - { &hf_openflow_v6_flow_removed_packet_count, - { "Packet count", "openflow_v6.flow_removed.packet_count", - FT_UINT64, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_openflow_v6_flow_removed_byte_count, - { "Byte count", "openflow_v6.flow_removed.byte_count", - FT_UINT64, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, { &hf_openflow_v6_port_status_reason, { "Reason", "openflow_v6.port_status.reason", FT_UINT8, BASE_DEC, VALS(openflow_v6_port_status_reason_values), 0x0, @@ -7519,11 +8050,6 @@ proto_register_openflow_v6(void) FT_UINT32, BASE_DEC|BASE_SPECIAL_VALS, VALS(openflow_v6_buffer_reserved_values), 0x0, NULL, HFILL } }, - { &hf_openflow_v6_packet_out_in_port, - { "In port", "openflow_v6.packet_out.in_port", - FT_UINT32, BASE_DEC|BASE_SPECIAL_VALS, VALS(openflow_v6_port_reserved_values), 0x0, - NULL, HFILL } - }, { &hf_openflow_v6_packet_out_acts_len, { "Actions length", "openflow_v6.packet_out.acts_len", FT_UINT16, BASE_DEC, NULL, 0x0, @@ -8314,121 +8840,81 @@ proto_register_openflow_v6(void) FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, - { &hf_openflow_v6_flow_stats_length, - { "Length", "openflow_v6.flow_stats.length", + { &hf_openflow_v6_flow_desc_length, + { "Length", "openflow_v6.flow_desc.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, - { &hf_openflow_v6_flow_stats_table_id, - { "Table ID", "openflow_v6.flow_stats.table_id", + { &hf_openflow_v6_flow_desc_table_id, + { "Table ID", "openflow_v6.flow_desc.table_id", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, - { &hf_openflow_v6_flow_stats_pad, - { "Pad", "openflow_v6.flow_stats.pad", + { &hf_openflow_v6_flow_desc_pad, + { "Pad", "openflow_v6.flow_desc.pad", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, - { &hf_openflow_v6_flow_stats_duration_sec, - { "Duration sec", "openflow_v6.flow_stats.duration_sec", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_openflow_v6_flow_stats_duration_nsec, - { "Duration nsec", "openflow_v6.flow_stats.duration_nsec", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_openflow_v6_flow_stats_priority, - { "Priority", "openflow_v6.flow_stats.priority", + { &hf_openflow_v6_flow_desc_priority, + { "Priority", "openflow_v6.flow_desc.priority", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, - { &hf_openflow_v6_flow_stats_idle_timeout, - { "Idle timeout", "openflow_v6.flow_stats.idle_timeout", + { &hf_openflow_v6_flow_desc_idle_timeout, + { "Idle timeout", "openflow_v6.flow_desc.idle_timeout", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, - { &hf_openflow_v6_flow_stats_hard_timeout, - { "Hard timeout", "openflow_v6.flow_stats.hard_timeout", + { &hf_openflow_v6_flow_desc_hard_timeout, + { "Hard timeout", "openflow_v6.flow_desc.hard_timeout", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, - { &hf_openflow_v6_flow_stats_flags, - { "Flags", "openflow_v6.flow_stats.flags", + { &hf_openflow_v6_flow_desc_flags, + { "Flags", "openflow_v6.flow_desc.flags", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } }, - { &hf_openflow_v6_flow_stats_flags_send_flow_rem, - { "Send flow removed", "openflow_v6.flow_stats.flags.send_flow_rem", + { &hf_openflow_v6_flow_desc_flags_send_flow_rem, + { "Send flow removed", "openflow_v6.flow_desc.flags.send_flow_rem", FT_BOOLEAN, 16, NULL, OFPFF_SEND_FLOW_REM, NULL, HFILL } }, - { &hf_openflow_v6_flow_stats_flags_check_overlap, - { "Check overlap", "openflow_v6.flow_stats.flags.check_overlap", + { &hf_openflow_v6_flow_desc_flags_check_overlap, + { "Check overlap", "openflow_v6.flow_desc.flags.check_overlap", FT_BOOLEAN, 16, NULL, OFPFF_CHECK_OVERLAP, NULL, HFILL } }, - { &hf_openflow_v6_flow_stats_flags_reset_counts, - { "Reset counts", "openflow_v6.flow_stats.flags.reset_counts", + { &hf_openflow_v6_flow_desc_flags_reset_counts, + { "Reset counts", "openflow_v6.flow_desc.flags.reset_counts", FT_BOOLEAN, 16, NULL, OFPFF_RESET_COUNTS, NULL, HFILL } }, - { &hf_openflow_v6_flow_stats_flags_no_packet_counts, - { "Don't count packets", "openflow_v6.flow_stats.flags.no_packet_counts", + { &hf_openflow_v6_flow_desc_flags_no_packet_counts, + { "Don't count packets", "openflow_v6.flow_desc.flags.no_packet_counts", FT_BOOLEAN, 16, NULL, OFPFF_NO_PKT_COUNTS, NULL, HFILL } }, - { &hf_openflow_v6_flow_stats_flags_no_byte_counts, - { "Don't count bytes", "openflow_v6.flow_stats.flags.no_byte_counts", + { &hf_openflow_v6_flow_desc_flags_no_byte_counts, + { "Don't count bytes", "openflow_v6.flow_desc.flags.no_byte_counts", FT_BOOLEAN, 16, NULL, OFPFF_NO_BYT_COUNTS, NULL, HFILL } }, - { &hf_openflow_v6_flow_stats_importance, - { "Importance", "openflow_v6.flow_stats.importance", + { &hf_openflow_v6_flow_desc_importance, + { "Importance", "openflow_v6.flow_desc.importance", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, - { &hf_openflow_v6_flow_stats_pad2, - { "Pad", "openflow_v6.flow_stats.pad2", + { &hf_openflow_v6_flow_desc_pad2, + { "Pad", "openflow_v6.flow_desc.pad2", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, - { &hf_openflow_v6_flow_stats_cookie, - { "Cookie", "openflow_v6.flow_stats.cookie", + { &hf_openflow_v6_flow_desc_cookie, + { "Cookie", "openflow_v6.flow_desc.cookie", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, - { &hf_openflow_v6_flow_stats_packet_count, - { "Packet count", "openflow_v6.flow_stats.packet_count", - FT_UINT64, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_openflow_v6_flow_stats_byte_count, - { "Byte count", "openflow_v6.flow_stats.byte_count", - FT_UINT64, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_openflow_v6_aggregate_stats_packet_count, - { "Packet count", "openflow_v6.aggregate_stats.packet_count", - FT_UINT64, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_openflow_v6_aggregate_stats_byte_count, - { "Byte count", "openflow_v6.aggregate_stats.byte_count", - FT_UINT64, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_openflow_v6_aggregate_stats_flow_count, - { "Flow count", "openflow_v6.aggregate_stats.flow_count", - FT_UINT64, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_openflow_v6_aggregate_stats_pad, - { "Pad", "openflow_v6.aggregate_stats.pad", - FT_BYTES, BASE_NONE, NULL, 0x0, - NULL, HFILL } - }, { &hf_openflow_v6_table_stats_table_id, { "Table ID", "openflow_v6.table_stats.table_id", FT_UINT8, BASE_DEC|BASE_SPECIAL_VALS, VALS(openflow_v6_table_reserved_values), 0x0, @@ -9754,7 +10240,267 @@ proto_register_openflow_v6(void) { "OFPBF_ORDERED", "openflow_v6.bundle_add.flags.ordered", FT_BOOLEAN, 16, NULL, OFPBF_ORDERED, NULL, HFILL } - } + }, + { &hf_openflow_v6_oxs_class, + { "Class", "openflow_v6.oxs.class", + FT_UINT16, BASE_HEX, VALS(openflow_v6_oxs_class_values), 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_oxs_field, + { "Field", "openflow_v6.oxs.field", + FT_UINT8, BASE_DEC, VALS(openflow_v6_oxs_basic_field_values), OXS_FIELD_MASK, + NULL, HFILL } + }, + { &hf_openflow_v6_oxs_reserved, + { "Reserved", "openflow_v6.oxs.reserved", + FT_UINT8, BASE_HEX, NULL, OXS_RESERVED_MASK, + NULL, HFILL } + }, + { &hf_openflow_v6_oxs_length, + { "Length", "openflow_v6.oxs.length", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_oxs_basic_duration_sec, + { "Duration", "openflow_v6.oxs.duration_sec", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_oxs_basic_duration_nsec, + { "Duration", "openflow_v6.oxs.duration_nsec", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_oxs_basic_idle_sec, + { "Idle", "openflow_v6.oxs.idle_sec", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_oxs_basic_idle_nsec, + { "Idle", "openflow_v6.oxs.idle_nsec", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_oxs_basic_flow_count, + { "Flow count", "openflow_v6.oxs.flow_count", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_oxs_basic_packet_count, + { "Packet count", "openflow_v6.oxs.packet_count", + FT_UINT64, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_oxs_basic_byte_count, + { "Byte count", "openflow_v6.oxs.byte_count", + FT_UINT64, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_oxs_experimenter_experimenter, + { "Experimenter ID", "openflow_v6.oxs.experimenter.experimenter", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_oxs_experimenter_value, + { "Experimenter ID", "openflow_v6.oxs.experimenter.value", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_stats_reserved, + { "Reserved", "openflow_v6.stats.reserved", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_stats_length, + { "Length", "openflow_v6.stats.length", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_stats_pad, + { "Pad", "openflow_v6.stats.pad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_oxm_register, + { "Register", "openflow_v6.oxm.register", + FT_UINT8, BASE_DEC, NULL, OXM_FIELD_MASK, + NULL, HFILL } + }, + { &hf_openflow_v6_instruction_stat_trigger_flags, + { "Flags", "openflow_v6.instruction.stat_trigger.flags", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_instruction_stat_triffer_flags_periodic, + { "Flags", "openflow_v6.instruction.stat_trigger.flags.periodic", + FT_UINT32, BASE_HEX, NULL, OFPSTF_PERIODIC, + NULL, HFILL } + }, + { &hf_openflow_v6_instruction_stat_triffer_flags_only_first, + { "Flags", "openflow_v6.instruction.stat_trigger.flags.only_first", + FT_UINT32, BASE_HEX, NULL, OFPSTF_ONLY_FIRST, + NULL, HFILL } + }, + { &hf_openflow_v6_instruction_stat_triffer_flags_reserved, + { "Flags", "openflow_v6.instruction.stat_trigger.flags.reserved", + FT_UINT32, BASE_HEX, NULL, 0xfffffffc, + NULL, HFILL } + }, + { &hf_openflow_v6_controller_status_length, + { "Length", "openflow_v6.controller_status.length", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_controller_status_short_id, + { "Short ID", "openflow_v6.controller_status.short_id", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_controller_status_role, + { "Role", "openflow_v6.controller_status.role", + FT_UINT32, BASE_HEX, VALS(openflow_v6_controller_role_values), 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_controller_status_reason, + { "Reason", "openflow_v6.controller_status.reason", + FT_UINT8, BASE_DEC, VALS(openflow_v6_controller_status_reason_values), 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_controller_status_channel_status, + { "Reason", "openflow_v6.controller_status.channel_status", + FT_UINT8, BASE_DEC, VALS(openflow_v6_controller_status_channel_status_values), 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_controller_status_pad, + { "Reason", "openflow_v6.controller_status.pad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_time_seconds, + { "Seconds", "openflow_v6.time.seconds", + FT_UINT64, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_time_nanoseconds, + { "Nanoseconds", "openflow_v6.time.nanoseconds", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_time_pad, + { "Pad", "openflow_v6.time.pad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_bundle_feature_prop_type, + { "Type", "openflow_v6.bundle_feature.prop.type", + FT_UINT16, BASE_HEX, VALS(openflow_v6_bundle_feature_prop_type_values), 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_bundle_feature_prop_length, + { "Length", "openflow_v6.bundle_feature.prop.length", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_bundle_feature_prop_time_pad, + { "Pad", "openflow_v6.bundle_feature.prop.pad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_bundle_feature_prop_experimenter_experimenter, + { "Experimenter", "openflow_v6.bundle_feature.prop.experimenter.experimenter", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_bundle_feature_prop_experimenter_exp_type, + { "Type", "openflow_v6.bundle_feature.prop.experimenter.type", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_bundle_feature_prop_pad, + { "Pad", "openflow_v6.bundle_feature.prop.pad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_controller_status_prop_type, + { "Type", "openflow_v6.controller_status.prop.type", + FT_UINT16, BASE_DEC, VALS(openflow_v6_controller_status_prop_type_values), 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_controller_status_prop_length, + { "Length", "openflow_v6.controller_status.prop.length", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_controller_status_prop_experimenter_experimenter, + { "Experimenter", "openflow_v6.controller_status.prop.experimenter.experimenter", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_controller_status_prop_experimenter_exp_type, + { "Type", "openflow_v6.controller_status.prop.experimenter.type", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_controller_status_prop_pad, + { "Pad", "openflow_v6.controller_status.prop.pad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_port_desc_prop_recirculate_port_no, + { "Port No", "openflow_v6.port.stats_prop.recirculate.port_no", + FT_UINT32, BASE_DEC|BASE_SPECIAL_VALS, VALS(openflow_v6_port_reserved_values), 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_bundle_features_request_flags, + { "Flags", "openflow_v6.bundle_features_request.flags", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_bundle_features_request_pad, + { "Pad", "openflow_v6.bundle_features_request.pad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_flow_stats_pad2, + { "Pad", "openflow_v6.flow_stats.pad2", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_flow_stats_reason, + { "Reason", "openflow_v6.flow_stats.reason", + FT_UINT8, BASE_DEC, VALS(openflow_v6_flow_stats_reason_values), 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_flow_stats_length, + { "Length", "openflow_v6.flow_stats.length", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_flow_stats_table_id, + { "Table ID", "openflow_v6.flow_stats.table_id", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_flow_stats_duration_sec, + { "Duration sec", "openflow_v6.flow_stats.duration_sec", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_flow_stats_duration_nsec, + { "Duration nsec", "openflow_v6.flow_stats.duration_nsec", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_flow_stats_priority, + { "Priority", "openflow_v6.flow_stats.priority", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v6_controller_status_prop_uri, + { "URI", "openflow_v6.controller_status.prop.uri", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, }; static gint *ett[] = { @@ -9800,7 +10546,6 @@ proto_register_openflow_v6(void) &ett_openflow_v6_flow_monitor_request_flags, &ett_openflow_v6_multipart_request_flags, &ett_openflow_v6_flow_stats, - &ett_openflow_v6_flow_stats_flags, &ett_openflow_v6_table_stats, &ett_openflow_v6_port_stats, &ett_openflow_v6_queue_stats, @@ -9838,7 +10583,12 @@ proto_register_openflow_v6(void) &ett_openflow_v6_bundle_control_flags, &ett_openflow_v6_bundle_prop, &ett_openflow_v6_bundle_add_flags, - &ett_openflow_v6_bundle_add_message + &ett_openflow_v6_bundle_add_message, + &ett_openflow_v6_instruction_stat_trigger_flags, + &ett_openflow_v6_flow_desc, + &ett_openflow_v6_flow_desc_flags, + &ett_openflow_v6_bundle_feature_prop, + &ett_openflow_v6_controller_status_prop, }; static ei_register_info ei[] = { @@ -9929,7 +10679,15 @@ proto_register_openflow_v6(void) {&ei_openflow_v6_length_too_short, { "openflow_v6.message.length_too_short", PI_MALFORMED, PI_ERROR, "Length is too short.", EXPFILL } - } + }, + {&ei_openflow_v6_bundle_feature_prop_undecoded, + { "openflow_v6.bundle_feature.prop.undecoded", PI_UNDECODED, PI_NOTE, + "Unknown bundle feature prop body.", EXPFILL } + }, + {&ei_openflow_v6_controller_status_prop_undecoded, + { "openflow_v6.controller_status.prop.undecoded", PI_UNDECODED, PI_NOTE, + "Unknown controller status prop body.", EXPFILL } + }, }; |