diff options
author | Anders Broman <anders.broman@ericsson.com> | 2013-10-20 21:12:32 +0000 |
---|---|---|
committer | Anders Broman <anders.broman@ericsson.com> | 2013-10-20 21:12:32 +0000 |
commit | 98dec2f09b9a0e63ee382c2b357b7165121a5760 (patch) | |
tree | b57c598fb43b55048395d436bfd589b526105d7c /epan | |
parent | b552143a5cc71cebd2e1d256c2cd06e28d4814d2 (diff) | |
download | wireshark-98dec2f09b9a0e63ee382c2b357b7165121a5760.tar.gz |
Adds dissecting for actions, and proper display for OXM values.
https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9283
svn path=/trunk/; revision=52725
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dissectors/packet-openflow_v4.c | 693 |
1 files changed, 648 insertions, 45 deletions
diff --git a/epan/dissectors/packet-openflow_v4.c b/epan/dissectors/packet-openflow_v4.c index b4fdd34b53..3d0445f99a 100644 --- a/epan/dissectors/packet-openflow_v4.c +++ b/epan/dissectors/packet-openflow_v4.c @@ -28,9 +28,10 @@ #include "config.h" #include <glib.h> - -#include <epan/packet.h> +#include <epan/etypes.h> #include <epan/expert.h> +#include <epan/ipproto.h> +#include <epan/packet.h> void proto_reg_handoff_openflow_v4(void); static int proto_openflow_v4 = -1; @@ -44,10 +45,50 @@ static int hf_openflow_v4_oxm_field_basic = -1; static int hf_openflow_v4_oxm_hm = -1; static int hf_openflow_v4_oxm_length = -1; static int hf_openflow_v4_oxm_value = -1; +static int hf_openflow_v4_oxm_value_etheraddr = -1; +static int hf_openflow_v4_oxm_value_ethertype = -1; +static int hf_openflow_v4_oxm_value_ipv4addr = -1; +static int hf_openflow_v4_oxm_value_ipv6addr = -1; +static int hf_openflow_v4_oxm_value_ipproto = -1; +static int hf_openflow_v4_oxm_value_uint16 = -1; +static int hf_openflow_v4_oxm_value_uint24 = -1; +static int hf_openflow_v4_oxm_value_uint32 = -1; static int hf_openflow_v4_oxm_mask = -1; +static int hf_openflow_v4_oxm_mask_etheraddr = -1; +static int hf_openflow_v4_oxm_mask_ipv4addr = -1; +static int hf_openflow_v4_oxm_mask_ipv6addr = -1; static int hf_openflow_v4_match_type = -1; static int hf_openflow_v4_match_length = -1; static int hf_openflow_v4_match_pad = -1; +static int hf_openflow_v4_action_type = -1; +static int hf_openflow_v4_action_length = -1; +static int hf_openflow_v4_action_output_port = -1; +static int hf_openflow_v4_action_output_port_reserved = -1; +static int hf_openflow_v4_action_output_max_len = -1; +static int hf_openflow_v4_action_output_max_len_reserved = -1; +static int hf_openflow_v4_action_output_pad = -1; +static int hf_openflow_v4_action_copy_ttl_out_pad = -1; +static int hf_openflow_v4_action_copy_ttl_in_pad = -1; +static int hf_openflow_v4_action_set_mpls_ttl_ttl = -1; +static int hf_openflow_v4_action_set_mpls_ttl_pad = -1; +static int hf_openflow_v4_action_dec_mpls_ttl_pad = -1; +static int hf_openflow_v4_action_push_vlan_ethertype = -1; +static int hf_openflow_v4_action_push_vlan_pad = -1; +static int hf_openflow_v4_action_pop_vlan_pad = -1; +static int hf_openflow_v4_action_push_mpls_ethertype = -1; +static int hf_openflow_v4_action_push_mpls_pad = -1; +static int hf_openflow_v4_action_pop_mpls_ethertype = -1; +static int hf_openflow_v4_action_pop_mpls_pad = -1; +static int hf_openflow_v4_action_set_queue_queue_id = -1; +static int hf_openflow_v4_action_group_group_id = -1; +static int hf_openflow_v4_action_group_group_id_reserved = -1; +static int hf_openflow_v4_action_set_nw_ttl_ttl = -1; +static int hf_openflow_v4_action_set_nw_ttl_pad = -1; +static int hf_openflow_v4_action_dec_nw_ttl_pad = -1; +static int hf_openflow_v4_action_set_field_pad = -1; +static int hf_openflow_v4_action_push_pbb_ethertype = -1; +static int hf_openflow_v4_action_push_pbb_pad = -1; +static int hf_openflow_v4_action_pop_pbb_pad = -1; static int hf_openflow_v4_instruction_type = -1; static int hf_openflow_v4_instruction_length = -1; static int hf_openflow_v4_instruction_goto_table_table_id = -1; @@ -107,10 +148,13 @@ static gint ett_openflow_v4_flowmod_instructions = -1; static gint ett_openflow_v4_oxm = -1; static gint ett_openflow_v4_match = -1; static gint ett_openflow_v4_match_oxm_fields = -1; +static gint ett_openflow_v4_action = -1; static gint ett_openflow_v4_instruction = -1; static gint ett_openflow_v4_instruction_actions_actions = -1; static expert_field ei_openflow_v4_match_undecoded = EI_INIT; +static expert_field ei_openflow_v4_oxm_undecoded = EI_INIT; +static expert_field ei_openflow_v4_action_undecoded = EI_INIT; static expert_field ei_openflow_v4_instruction_undecoded = EI_INIT; static const value_string openflow_v4_version_values[] = { @@ -251,6 +295,46 @@ static const value_string openflow_v4_oxm_class_values[] = { { 0, NULL} }; +#define OFPXMT_OFB_IN_PORT 0 +#define OFPXMT_OFB_IN_PHY_PORT 1 +#define OFPXMT_OFB_METADATA 2 +#define OFPXMT_OFB_ETH_DST 3 +#define OFPXMT_OFB_ETH_SRC 4 +#define OFPXMT_OFB_ETH_TYPE 5 +#define OFPXMT_OFB_VLAN_VID 6 +#define OFPXMT_OFB_VLAN_PCP 7 +#define OFPXMT_OFB_IP_DSCP 8 +#define OFPXMT_OFB_IP_ECN 9 +#define OFPXMT_OFB_IP_PROTO 10 +#define OFPXMT_OFB_IPV4_SRC 11 +#define OFPXMT_OFB_IPV4_DST 12 +#define OFPXMT_OFB_TCP_SRC 13 +#define OFPXMT_OFB_TCP_DST 14 +#define OFPXMT_OFB_UDP_SRC 15 +#define OFPXMT_OFB_UDP_DST 16 +#define OFPXMT_OFB_SCTP_SRC 17 +#define OFPXMT_OFB_SCTP_DST 18 +#define OFPXMT_OFB_ICMPV4_TYPE 19 +#define OFPXMT_OFB_ICMPV4_CODE 20 +#define OFPXMT_OFB_ARP_OP 21 +#define OFPXMT_OFB_ARP_SPA 22 +#define OFPXMT_OFB_ARP_TPA 23 +#define OFPXMT_OFB_ARP_SHA 24 +#define OFPXMT_OFB_ARP_THA 25 +#define OFPXMT_OFB_IPV6_SRC 26 +#define OFPXMT_OFB_IPV6_DST 27 +#define OFPXMT_OFB_IPV6_FLABEL 28 +#define OFPXMT_OFB_ICMPV6_TYPE 29 +#define OFPXMT_OFB_ICMPV6_CODE 30 +#define OFPXMT_OFB_IPV6_ND_TARGET 31 +#define OFPXMT_OFB_IPV6_ND_SLL 32 +#define OFPXMT_OFB_IPV6_ND_TLL 33 +#define OFPXMT_OFB_MPLS_LABEL 34 +#define OFPXMT_OFB_MPLS_TC 35 +#define OFPXMT_OFP_MPLS_BOS 36 +#define OFPXMT_OFB_PBB_ISID 37 +#define OFPXMT_OFB_TUNNEL_ID 38 +#define OFPXMT_OFB_IPV6_EXTHDR 39 static const value_string openflow_v4_oxm_basic_field_values[] = { { 0, "OFPXMT_OFB_IN_PORT" }, { 1, "OFPXMT_OFB_IN_PHY_PORT" }, @@ -331,33 +415,120 @@ dissect_openflow_oxm_v4(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, { proto_item *ti; proto_tree *oxm_tree; + guint16 oxm_class; guint8 oxm_field_hm; guint8 oxm_hm; + guint8 oxm_field; guint8 oxm_length; + guint8 field_length; + 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_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); + ti = proto_tree_add_text(tree, tvb, offset, oxm_length + 4, "OXM"); oxm_tree = proto_item_add_subtree(ti, ett_openflow_v4_oxm); offset = dissect_openflow_oxm_header_v4(tvb, pinfo, oxm_tree, offset, length); - oxm_hm = oxm_field_hm & OXM_HM_MASK; - if (oxm_hm != 0) { - oxm_length /= 2; - } - - /* value */ - if (oxm_length > 0) { - proto_tree_add_item(oxm_tree, hf_openflow_v4_oxm_value, tvb, offset, oxm_length, ENC_BIG_ENDIAN); - offset += oxm_length; - } + if (oxm_class == OFPXMC_OPENFLOW_BASIC) { + switch(oxm_field) { + case OFPXMT_OFB_IN_PORT: + case OFPXMT_OFB_IN_PHY_PORT: + proto_tree_add_item(oxm_tree, hf_openflow_v4_oxm_value_uint32, tvb, offset, 4, ENC_BIG_ENDIAN); + offset+=4; + break; + + case OFPXMT_OFB_ETH_DST: + case OFPXMT_OFB_ETH_SRC: + case OFPXMT_OFB_ARP_SHA: + case OFPXMT_OFB_ARP_THA: + proto_tree_add_item(oxm_tree, hf_openflow_v4_oxm_value_etheraddr, tvb, offset, 6, ENC_BIG_ENDIAN); + offset+=6; + if (oxm_hm) { + proto_tree_add_item(oxm_tree, hf_openflow_v4_oxm_mask_etheraddr, tvb, offset, 6, ENC_BIG_ENDIAN); + offset+=6; + } + break; + + case OFPXMT_OFB_ETH_TYPE: + proto_tree_add_item(oxm_tree, hf_openflow_v4_oxm_value_ethertype, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + break; + + case OFPXMT_OFB_IP_PROTO: + proto_tree_add_item(oxm_tree, hf_openflow_v4_oxm_value_ipproto, tvb, offset, 1, ENC_BIG_ENDIAN); + offset+=1; + break; + + case OFPXMT_OFB_IPV4_SRC: + case OFPXMT_OFB_IPV4_DST: + case OFPXMT_OFB_ARP_SPA: + case OFPXMT_OFB_ARP_TPA: + proto_tree_add_item(oxm_tree, hf_openflow_v4_oxm_value_ipv4addr, tvb, offset, 4, ENC_BIG_ENDIAN); + offset+=4; + if (oxm_hm) { + proto_tree_add_item(oxm_tree, hf_openflow_v4_oxm_mask_ipv4addr, tvb, offset, 4, ENC_BIG_ENDIAN); + offset+=4; + } + break; + + case OFPXMT_OFB_TCP_SRC: + case OFPXMT_OFB_TCP_DST: + case OFPXMT_OFB_UDP_SRC: + case OFPXMT_OFB_UDP_DST: + case OFPXMT_OFB_SCTP_SRC: + case OFPXMT_OFB_SCTP_DST: + proto_tree_add_item(oxm_tree, hf_openflow_v4_oxm_value_uint16, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + break; + + case OFPXMT_OFB_IPV6_SRC: + case OFPXMT_OFB_IPV6_DST: + case OFPXMT_OFB_IPV6_ND_SLL: + case OFPXMT_OFB_IPV6_ND_TLL: + proto_tree_add_item(oxm_tree, hf_openflow_v4_oxm_value_ipv6addr, tvb, offset, 16, ENC_BIG_ENDIAN); + offset+=16; + if (oxm_hm) { + proto_tree_add_item(oxm_tree, hf_openflow_v4_oxm_mask_ipv6addr, tvb, offset, 16, ENC_BIG_ENDIAN); + offset+=16; + } + break; + + case OFPXMT_OFB_MPLS_LABEL: + /* size differs in specification and header file */ + if (field_length == 3) { + proto_tree_add_item(oxm_tree, hf_openflow_v4_oxm_value_uint24, tvb, offset, 3, ENC_BIG_ENDIAN); + offset+=3; + } else if (field_length == 4) { + proto_tree_add_item(oxm_tree, hf_openflow_v4_oxm_value_uint32, tvb, offset, 4, ENC_BIG_ENDIAN); + offset+=4; + } + break; + + default: + /* value */ + if (field_length > 0) { + proto_tree_add_item(oxm_tree, hf_openflow_v4_oxm_value, tvb, offset, field_length, ENC_BIG_ENDIAN); + offset += field_length; + } + + /* mask */ + if (field_length > 0 && oxm_hm != 0) { + proto_tree_add_item(oxm_tree, hf_openflow_v4_oxm_mask, tvb, offset, field_length, ENC_BIG_ENDIAN); + offset += field_length; + } + break; + } - /* mask */ - if (oxm_length > 0 && oxm_hm != 0) { - proto_tree_add_item(oxm_tree, hf_openflow_v4_oxm_mask, tvb, offset, oxm_length, ENC_BIG_ENDIAN); - offset += oxm_length; + } else { + proto_tree_add_expert_format(oxm_tree, pinfo, &ei_openflow_v4_oxm_undecoded, + tvb, offset, oxm_length, "Unknown OXM body."); + offset+=oxm_length; } return offset; @@ -400,21 +571,25 @@ dissect_openflow_match_v4(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tre switch (match_type) { case OFPMT_STANDARD: proto_tree_add_expert_format(match_tree, pinfo, &ei_openflow_v4_match_undecoded, - tvb, offset, match_length - 4, "Standard match (deprecated)."); + tvb, offset, match_length - 4, "Standard match body (deprecated)."); offset+=match_length-4; break; - case OFPMT_OXM: - ti = proto_tree_add_text(match_tree, tvb, offset, match_length - 4, "Fields"); - fields_tree = proto_item_add_subtree(ti, ett_openflow_v4_match_oxm_fields); + case OFPMT_OXM: fields_end = offset + match_length - 4; - while(offset < fields_end) { - offset = dissect_openflow_oxm_v4(tvb, pinfo, fields_tree, offset, length); + + if (offset < fields_end) { + ti = proto_tree_add_text(match_tree, tvb, offset, match_length - 4, "Fields"); + fields_tree = proto_item_add_subtree(ti, ett_openflow_v4_match_oxm_fields); + while(offset < fields_end) { + offset = dissect_openflow_oxm_v4(tvb, pinfo, fields_tree, offset, length); + } } break; + default: proto_tree_add_expert_format(match_tree, pinfo, &ei_openflow_v4_match_undecoded, - tvb, offset, match_length - 4, "Unknown match."); + tvb, offset, match_length - 4, "Unknown match body."); offset+=match_length-4; break; } @@ -500,6 +675,238 @@ dissect_openflow_features_reply_v4(tvbuff_t *tvb, packet_info *pinfo _U_, proto_ } +#define OFPAT_OUTPUT 0 /* Output to switch port. */ +#define OFPAT_COPY_TTL_OUT 11 /* Copy TTL "outwards" */ +#define OFPAT_COPY_TTL_IN 12 /* Copy TTL "inwards" */ +#define OFPAT_SET_MPLS_TTL 15 /* MPLS TTL */ +#define OFPAT_DEC_MPLS_TTL 16 /* Decrement MPLS TTL */ +#define OFPAT_PUSH_VLAN 17 /* Push a new VLAN tag */ +#define OFPAT_POP_VLAN 18 /* Pop the outer VLAN tag */ +#define OFPAT_PUSH_MPLS 19 /* Push a new MPLS tag */ +#define OFPAT_POP_MPLS 20 /* Pop the outer MPLS tag */ +#define OFPAT_SET_QUEUE 21 /* Set queue id when outputting to a port */ +#define OFPAT_GROUP 22 /* Apply group. */ +#define OFPAT_SET_NW_TTL 23 /* IP TTL. */ +#define OFPAT_DEC_NW_TTL 24 /* Decrement IP TTL. */ +#define OFPAT_SET_FIELD 25 /* Set a header field using OXM TLV format. */ +#define OFPAT_PUSH_PBB 26 /* Push a new PBB service tag (I-TAG) */ +#define OFPAT_POP_PBB 27 /* Pop the outer PBB service tag (I-TAG) */ +#define OFPAT_EXPERIMENTER 0xffff + +static const value_string openflow_v4_action_type_values[] = { + { 0, "OFPAT_OUTPUT" }, + { 11, "OFPAT_COPY_TTL_OUT" }, + { 12, "OFPAT_COPY_TTL_IN" }, + { 15, "OFPAT_SET_MPLS_TTL" }, + { 16, "OFPAT_DEC_MPLS_TTL" }, + { 17, "OFPAT_PUSH_VLAN" }, + { 18, "OFPAT_POP_VLAN" }, + { 19, "OFPAT_PUSH_MPLS" }, + { 20, "OFPAT_POP_MPLS" }, + { 21, "OFPAT_SET_QUEUE" }, + { 22, "OFPAT_GROUP" }, + { 23, "OFPAT_SET_NW_TTL" }, + { 24, "OFPAT_DEC_NW_TTL" }, + { 25, "OFPAT_SET_FIELD" }, + { 26, "OFPAT_PUSH_PBB" }, + { 27, "OFPAT_POP_PBB" }, + { 0xffff, "OFPAT_EXPERIMENTER" }, + { 0, NULL} +}; + +#define OFPCML_MAX 0xffe5 /* Maximum max_len value. */ +static const value_string openflow_v4_action_output_max_len_reserved_values[] = { + { 0xffff, "OFPCML_NO_BUFFER" }, + { 0, NULL } +}; + +static int +dissect_openflow_action_v4(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_) +{ + proto_item *ti; + proto_tree *act_tree; + guint16 act_type; + guint16 act_length; + guint16 act_end; + + ti = proto_tree_add_text(tree, tvb, offset, -1, "Action"); + act_tree = proto_item_add_subtree(ti, ett_openflow_v4_action); + + /* uint16_t type; */ + act_type = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(act_tree, hf_openflow_v4_action_type, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + + /* uint16_t length; */ + act_length = tvb_get_ntohs(tvb, offset); + proto_item_set_len(ti, act_length); + proto_tree_add_item(act_tree, hf_openflow_v4_action_length, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + + switch (act_type) { + case OFPAT_OUTPUT: + /* uint32_t port; */ + if (tvb_get_ntohl(tvb, offset) <= OFPP_MAX) { + proto_tree_add_item(act_tree, hf_openflow_v4_action_output_port, tvb, offset, 4, ENC_BIG_ENDIAN); + } else { + proto_tree_add_item(act_tree, hf_openflow_v4_action_output_port_reserved, tvb, offset, 4, ENC_BIG_ENDIAN); + } + offset+=4; + + /* uint16_t max_len; */ + if (tvb_get_ntohs(tvb, offset) <= OFPCML_MAX) { + proto_tree_add_item(act_tree, hf_openflow_v4_action_output_max_len, tvb, offset, 2, ENC_BIG_ENDIAN); + } else { + proto_tree_add_item(act_tree, hf_openflow_v4_action_output_max_len_reserved, tvb, offset, 2, ENC_BIG_ENDIAN); + } + offset+=2; + + /* uint8_t pad[6]; */ + proto_tree_add_item(act_tree, hf_openflow_v4_action_output_pad, tvb, offset, 6, ENC_BIG_ENDIAN); + offset+=6; + + break; + + case OFPAT_COPY_TTL_OUT: + /* uint8_t pad[4]; */ + proto_tree_add_item(act_tree, hf_openflow_v4_action_copy_ttl_out_pad, tvb, offset, 4, ENC_BIG_ENDIAN); + offset+=4; + break; + + case OFPAT_COPY_TTL_IN: + /* uint8_t pad[4]; */ + proto_tree_add_item(act_tree, hf_openflow_v4_action_copy_ttl_in_pad, tvb, offset, 4, ENC_BIG_ENDIAN); + offset+=4; + break; + + case OFPAT_SET_MPLS_TTL: + /* uint8_t mpls_ttl; */ + proto_tree_add_item(act_tree, hf_openflow_v4_action_set_mpls_ttl_ttl, tvb, offset, 1, ENC_BIG_ENDIAN); + offset+=1; + + /* uint8_t pad[3]; */ + proto_tree_add_item(act_tree, hf_openflow_v4_action_set_mpls_ttl_pad, tvb, offset, 3, ENC_BIG_ENDIAN); + offset+=3; + break; + + case OFPAT_DEC_MPLS_TTL: + /* uint8_t pad[4]; */ + proto_tree_add_item(act_tree, hf_openflow_v4_action_dec_mpls_ttl_pad, tvb, offset, 4, ENC_BIG_ENDIAN); + offset+=4; + break; + + case OFPAT_PUSH_VLAN: + /* uint16_t ethertype; */ + proto_tree_add_item(act_tree, hf_openflow_v4_action_push_vlan_ethertype, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + + /* uint8_t pad[2]; */ + proto_tree_add_item(act_tree, hf_openflow_v4_action_push_vlan_pad, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + break; + + case OFPAT_POP_VLAN: + /* uint8_t pad[4]; */ + proto_tree_add_item(act_tree, hf_openflow_v4_action_pop_vlan_pad, tvb, offset, 4, ENC_BIG_ENDIAN); + offset+=4; + break; + + case OFPAT_PUSH_MPLS: + /* uint16_t ethertype; */ + proto_tree_add_item(act_tree, hf_openflow_v4_action_push_mpls_ethertype, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + + /* uint8_t pad[2]; */ + proto_tree_add_item(act_tree, hf_openflow_v4_action_push_mpls_pad, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + break; + + case OFPAT_POP_MPLS: + /* uint16_t ethertype; */ + proto_tree_add_item(act_tree, hf_openflow_v4_action_pop_mpls_ethertype, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + + /* uint8_t pad[2]; */ + proto_tree_add_item(act_tree, hf_openflow_v4_action_pop_mpls_pad, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + break; + + case OFPAT_SET_QUEUE: + /* uint32_t queue_id; */ + proto_tree_add_item(act_tree, hf_openflow_v4_action_set_queue_queue_id, tvb, offset, 4, ENC_BIG_ENDIAN); + offset+=4; + break; + + case OFPAT_GROUP: + /* uint32_t group_id; */ + if (tvb_get_ntohl(tvb, offset) <= OFPG_MAX) { + proto_tree_add_item(act_tree, hf_openflow_v4_action_group_group_id, tvb, offset, 4, ENC_BIG_ENDIAN); + } else { + proto_tree_add_item(act_tree, hf_openflow_v4_action_group_group_id_reserved, tvb, offset, 4, ENC_BIG_ENDIAN); + } + offset+=4; + break; + + case OFPAT_SET_NW_TTL: + /* uint8_t nw_ttl; */ + proto_tree_add_item(act_tree, hf_openflow_v4_action_set_nw_ttl_ttl, tvb, offset, 1, ENC_BIG_ENDIAN); + offset+=1; + + /* uint8_t pad[3]; */ + proto_tree_add_item(act_tree, hf_openflow_v4_action_set_nw_ttl_pad, tvb, offset, 3, ENC_BIG_ENDIAN); + offset+=3; + break; + + case OFPAT_DEC_NW_TTL: + /* uint8_t pad[4]; */ + proto_tree_add_item(act_tree, hf_openflow_v4_action_dec_nw_ttl_pad, tvb, offset, 4, ENC_BIG_ENDIAN); + offset+=4; + break; + + case OFPAT_SET_FIELD: + act_end = offset + act_length - 4; + offset = dissect_openflow_oxm_v4(tvb, pinfo, act_tree, offset, length); + + /* padded to 64 bits */ + if (offset < act_end) { + proto_tree_add_item(act_tree, hf_openflow_v4_action_set_field_pad, tvb, offset, act_end - offset, ENC_BIG_ENDIAN); + offset = act_end; + } + break; + + case OFPAT_PUSH_PBB: + /* uint16_t ethertype; */ + proto_tree_add_item(act_tree, hf_openflow_v4_action_push_pbb_ethertype, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + + /* uint8_t pad[2]; */ + proto_tree_add_item(act_tree, hf_openflow_v4_action_push_pbb_pad, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + break; + + case OFPAT_POP_PBB: + /* uint8_t pad[4]; */ + proto_tree_add_item(act_tree, hf_openflow_v4_action_pop_pbb_pad, tvb, offset, 4, ENC_BIG_ENDIAN); + offset+=4; + break; + + case OFPAT_EXPERIMENTER: + proto_tree_add_expert_format(act_tree, pinfo, &ei_openflow_v4_action_undecoded, + tvb, offset, act_length - 4, "Experimenter action body."); + offset += act_length - 4; + break; + + default: + proto_tree_add_expert_format(act_tree, pinfo, &ei_openflow_v4_action_undecoded, + tvb, offset, act_length - 4, "Unknown action body."); + offset += act_length - 4; + break; + } + + return offset; +} + + #define OFPIT_GOTO_TABLE 1 /* Setup the next table in the lookup */ #define OFPIT_WRITE_METADATA 2 /* Setup the metadata field for use later in */ #define OFPIT_WRITE_ACTIONS 3 /* Write the action(s) onto the datapath action */ @@ -533,6 +940,7 @@ dissect_openflow_instruction_v4(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tre proto_tree *inst_tree, *actions_tree; guint16 inst_type; guint16 inst_length; + guint16 acts_end; ti = proto_tree_add_text(tree, tvb, offset, -1, "Instruction"); inst_tree = proto_item_add_subtree(ti, ett_openflow_v4_instruction); @@ -574,30 +982,21 @@ dissect_openflow_instruction_v4(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tre break; case OFPIT_WRITE_ACTIONS: - proto_tree_add_item(inst_tree, hf_openflow_v4_instruction_actions_pad, tvb, offset, 4, ENC_BIG_ENDIAN); - offset+=4; - - ti = proto_tree_add_text(inst_tree, tvb, offset, inst_length - 8, "Actions"); - actions_tree = proto_item_add_subtree(ti, ett_openflow_v4_instruction_actions_actions); - - proto_tree_add_text(actions_tree, tvb, offset, 0, "Actions not dissected yet"); - offset += inst_length - 8; - break; - case OFPIT_APPLY_ACTIONS: + case OFPIT_CLEAR_ACTIONS: proto_tree_add_item(inst_tree, hf_openflow_v4_instruction_actions_pad, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; - ti = proto_tree_add_text(inst_tree, tvb, offset, inst_length - 8, "Actions"); - actions_tree = proto_item_add_subtree(ti, ett_openflow_v4_instruction_actions_actions); + acts_end = offset + inst_length - 8; - proto_tree_add_text(actions_tree, tvb, offset, 0, "Actions not dissected yet"); - offset += inst_length - 8; - break; + if (offset < acts_end) { + ti = proto_tree_add_text(inst_tree, tvb, offset, inst_length - 8, "Actions"); + actions_tree = proto_item_add_subtree(ti, ett_openflow_v4_instruction_actions_actions); - case OFPIT_CLEAR_ACTIONS: - proto_tree_add_item(inst_tree, hf_openflow_v4_instruction_actions_pad, tvb, offset, 4, ENC_BIG_ENDIAN); - offset+=4; + while (offset < acts_end) { + offset = dissect_openflow_action_v4(tvb, pinfo, actions_tree, offset, length); + } + } break; case OFPIT_METER: @@ -612,13 +1011,13 @@ dissect_openflow_instruction_v4(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tre case OFPIT_EXPERIMENTER: proto_tree_add_expert_format(inst_tree, pinfo, &ei_openflow_v4_instruction_undecoded, - tvb, offset, inst_length - 4, "Experimenter instruction."); + tvb, offset, inst_length - 4, "Experimenter instruction body."); offset += inst_length - 4; break; default: proto_tree_add_expert_format(inst_tree, pinfo, &ei_openflow_v4_instruction_undecoded, - tvb, offset, inst_length - 4, "Unknown instruction."); + tvb, offset, inst_length - 4, "Unknown instruction body."); offset += inst_length - 4; break; } @@ -1033,11 +1432,61 @@ proto_register_openflow_v4(void) FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_openflow_v4_oxm_value_etheraddr, + { "Value", "openflow_v4.oxm.value", + FT_ETHER, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_oxm_value_ethertype, + { "Value", "openflow_v4.oxm.value", + FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_oxm_value_ipv4addr, + { "Value", "openflow_v4.oxm.value", + FT_IPv4, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_oxm_value_ipv6addr, + { "Value", "openflow_v4.oxm.value", + FT_IPv6, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_oxm_value_ipproto, + { "Value", "openflow_v4.oxm.value", + FT_UINT8, BASE_DEC|BASE_EXT_STRING, (&ipproto_val_ext), 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_oxm_value_uint16, + { "Value", "openflow_v4.oxm.value", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_oxm_value_uint24, + { "Value", "openflow_v4.oxm.value", + FT_UINT24, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_oxm_value_uint32, + { "Value", "openflow_v4.oxm.value", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, { &hf_openflow_v4_oxm_mask, { "Mask", "openflow_v4.oxm.mask", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_openflow_v4_oxm_mask_etheraddr, + { "Mask", "openflow_v4.oxm.value", + FT_ETHER, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_oxm_mask_ipv4addr, + { "Mask", "openflow_v4.oxm.value", + FT_IPv4, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, { &hf_openflow_v4_match_type, { "Type", "openflow_v4.match.type", FT_UINT16, BASE_DEC, VALS(openflow_v4_match_type_values), 0x0, @@ -1053,6 +1502,151 @@ proto_register_openflow_v4(void) FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_openflow_v4_action_type, + { "Type", "openflow_v4.action.type", + FT_UINT16, BASE_DEC, VALS(openflow_v4_action_type_values), 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_length, + { "Length", "openflow_v4.action.length", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_output_port, + { "Port", "openflow_v4.action.output.port", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_output_port_reserved, + { "Port", "openflow_v4.action.output.port", + FT_UINT32, BASE_HEX, VALS(openflow_v4_port_reserved_values), 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_output_max_len, + { "Max length", "openflow_v4.action.output.max_len", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_output_max_len_reserved, + { "Max length", "openflow_v4.action.output.max_len", + FT_UINT16, BASE_HEX, VALS(openflow_v4_action_output_max_len_reserved_values), 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_output_pad, + { "Padding", "openflow_v4.action.output.pad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_copy_ttl_out_pad, + { "Padding", "openflow_v4.action.copy_ttl_out.pad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_copy_ttl_in_pad, + { "Padding", "openflow_v4.action.copy_ttl_in.pad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_set_mpls_ttl_ttl, + { "TTL", "openflow_v4.action.set_mpls_ttl.ttl", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_set_mpls_ttl_pad, + { "Padding", "openflow_v4.action.set_mpls_ttl.pad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_dec_mpls_ttl_pad, + { "Padding", "openflow_v4.action.dec_mpls_ttl.pad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_push_vlan_ethertype, + { "Ethertype", "openflow_v4.action.push_vlan.ethertype", + FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_push_vlan_pad, + { "Padding", "openflow_v4.action.push_vlan.pad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_pop_vlan_pad, + { "Padding", "openflow_v4.action.pop_vlan.pad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_push_mpls_ethertype, + { "Ethertype", "openflow_v4.action.push_mpls.ethertype", + FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_push_mpls_pad, + { "Padding", "openflow_v4.action.push_mpls.pad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_pop_mpls_ethertype, + { "Ethertype", "openflow_v4.action.pop_mpls.ethertype", + FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_pop_mpls_pad, + { "Padding", "openflow_v4.action.pop_mpls.pad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_set_queue_queue_id, + { "Queue ID", "openflow_v4.action.set_queue.queue_id", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_group_group_id, + { "Group ID", "openflow_v4.action.group.group_id", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_group_group_id_reserved, + { "Group ID", "openflow_v4.action.group.group_id", + FT_UINT32, BASE_HEX, VALS(openflow_v4_port_reserved_values), 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_set_nw_ttl_ttl, + { "TTL", "openflow_v4.action.set_nw_ttl.ttl", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_set_nw_ttl_pad, + { "Padding", "openflow_v4.action.set_nw_ttl.pad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_dec_nw_ttl_pad, + { "Padding", "openflow_v4.action.dec_nw_ttl.pad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_set_field_pad, + { "Padding", "openflow_v4.action.set_field.pad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_push_pbb_ethertype, + { "Ethertype", "openflow_v4.action.push_pbb.ethertype", + FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_push_pbb_pad, + { "Padding", "openflow_v4.action.push_pbb.pad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_openflow_v4_action_pop_pbb_pad, + { "Padding", "openflow_v4.action.pop_pbb.pad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, { &hf_openflow_v4_instruction_type, { "Type", "openflow_v4.instruction.type", FT_UINT16, BASE_DEC, VALS(openflow_v4_instruction_type_values), 0x0, @@ -1314,18 +1908,27 @@ proto_register_openflow_v4(void) &ett_openflow_v4_oxm, &ett_openflow_v4_match, &ett_openflow_v4_match_oxm_fields, + &ett_openflow_v4_action, &ett_openflow_v4_instruction, &ett_openflow_v4_instruction_actions_actions }; static ei_register_info ei[] = { + { &ei_openflow_v4_oxm_undecoded, + { "openflow_v4.oxm.undecoded", PI_UNDECODED, PI_NOTE, + "Unknown OMX body.", EXPFILL } + }, { &ei_openflow_v4_match_undecoded, { "openflow_v4.match.undecoded", PI_UNDECODED, PI_NOTE, - "Unknown match.", EXPFILL } + "Unknown match body.", EXPFILL } + }, + { &ei_openflow_v4_action_undecoded, + { "openflow_v4.action.undecoded", PI_UNDECODED, PI_NOTE, + "Unknown action body.", EXPFILL } }, { &ei_openflow_v4_instruction_undecoded, { "openflow_v4.instruction.undecoded", PI_UNDECODED, PI_NOTE, - "Unknown instruction.", EXPFILL } + "Unknown instruction body.", EXPFILL } } }; |