diff options
Diffstat (limited to 'epan/dissectors/packet-infiniband.c')
-rw-r--r-- | epan/dissectors/packet-infiniband.c | 318 |
1 files changed, 161 insertions, 157 deletions
diff --git a/epan/dissectors/packet-infiniband.c b/epan/dissectors/packet-infiniband.c index a007d6a231..f775864638 100644 --- a/epan/dissectors/packet-infiniband.c +++ b/epan/dissectors/packet-infiniband.c @@ -105,7 +105,6 @@ static gint ett_tracerecord = -1; static gint ett_multipathrecord = -1; static gint ett_serviceassocrecord = -1; static gint ett_perfclass = -1; -static gint ett_eoib = -1; static gint ett_link = -1; /* Dissector Declaration */ @@ -160,7 +159,6 @@ static void parse_RDETH(proto_tree *, tvbuff_t *, gint *offset); static void parse_IPvSix(proto_tree *, tvbuff_t *, gint *offset, packet_info *); static void parse_RWH(proto_tree *, tvbuff_t *, gint *offset, packet_info *, proto_tree *); static void parse_DCCETH(proto_tree *parentTree, tvbuff_t *tvb, gint *offset); -static gboolean parse_EoIB(proto_tree *, tvbuff_t *, gint offset, packet_info *, proto_tree *); static void parse_SUBN_LID_ROUTED(proto_tree *, packet_info *, tvbuff_t *, gint *offset); static void parse_SUBN_DIRECTED_ROUTE(proto_tree *, packet_info *, tvbuff_t *, gint *offset); @@ -728,8 +726,9 @@ static int hf_infiniband_sm_key = -1; static int hf_infiniband_attribute_offset = -1; static int hf_infiniband_component_mask = -1; static int hf_infiniband_subnet_admin_data = -1; + /* Mellanox EoIB encapsulation header */ -static int hf_infiniband_EOIB = -1; +static int proto_mellanox_eoib = -1; static int hf_infiniband_ver = -1; static int hf_infiniband_tcp_chk = -1; static int hf_infiniband_ip_chk = -1; @@ -738,6 +737,15 @@ static int hf_infiniband_ms = -1; static int hf_infiniband_seg_off = -1; static int hf_infiniband_seg_id = -1; +static gint ett_eoib = -1; + +#define MELLANOX_VERSION_FLAG 0x3000 +#define MELLANOX_TCP_CHECKSUM_FLAG 0x0C00 +#define MELLANOX_IP_CHECKSUM_FLAG 0x0300 +#define MELLANOX_FCS_PRESENT_FLAG 0x0040 +#define MELLANOX_MORE_SEGMENT_FLAG 0x0020 +#define MELLANOX_SEGMENT_FLAG 0x001F + /* Attributes * Additional Structures for individuala attribute decoding. * Since they are not headers the naming convention is slightly modified @@ -1495,8 +1503,6 @@ static guint32 opCode_PAYLD[] = { * }; */ /* settings to be set by the user via the preferences dialog */ -static gboolean pref_dissect_eoib = TRUE; -static gboolean pref_identify_iba_payload = TRUE; static guint pref_rroce_udp_port = DEFAULT_RROCE_UDP_PORT; /* saves information about connections that have been/are in the process of being @@ -1591,7 +1597,7 @@ dissect_infiniband_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, i /* General Variables */ gboolean bthFollows = FALSE; /* Tracks if we are parsing a BTH. This is a significant decision point */ - struct infinibandinfo info = { 0, FALSE, 0}; + struct infinibandinfo info = { 0, FALSE, 0, NULL}; gint32 nextHeaderSequence = -1; /* defined by this dissector. #define which indicates the upcoming header sequence from OpCode */ guint8 nxtHdr = 0; /* Keyed off for header dissection order */ guint16 packetLength = 0; /* Packet Length. We track this as tvb_length - offset. */ @@ -2403,9 +2409,6 @@ static void parse_PAYLOAD(proto_tree *parentTree, guint8 management_class; tvbuff_t *volatile next_tvb; gint reported_length; - guint16 etype, reserved; - const char *saved_proto; - volatile gboolean dissector_found = FALSE; heur_dtbl_entry_t *hdtbl_entry; if (!tvb_bytes_exist(tvb, *offset, length)) /* previously consumed bytes + offset was all the data - none or corrupt payload */ @@ -2486,104 +2489,25 @@ static void parse_PAYLOAD(proto_tree *parentTree, */ update_sport(pinfo); + info->payload_tree = parentTree; + /* Calculation for Payload: * (tvb_length) Length of entire packet - (local_offset) Starting byte of Payload Data * offset addition is more complex for the payload. * We need the total length of the packet, - length of previous headers, + offset where payload started. * We also need to reserve 6 bytes for the CRCs which are not actually part of the payload. */ - - etype = tvb_get_ntohs(tvb, local_offset); - reserved = tvb_get_ntohs(tvb, local_offset + 2); - - /* try to recognize whether or not this is a Mellanox EoIB packet by the - transport type and the 4 first bits of the payload */ - if (pref_dissect_eoib && - (((info->opCode & 0xE0) >> 5) == TRANSPORT_UD) && - (tvb_get_bits8(tvb, local_offset*8, 4) == 0xC)) { - dissector_found = parse_EoIB(parentTree, tvb, local_offset, pinfo, top_tree); - } - - /* IBA packet data could be anything in principle, however it is common - * practice to carry non-IBA data encapsulated with an EtherType header, - * similar to the RWH header. There is no way to identify these frames - * positively. - * - * If the appropriate option is set in protocol preferences, - * We see if the first few bytes look like an EtherType header, and if so - * call the appropriate dissector. If not we call the "data" dissector. - */ - if (!dissector_found && pref_identify_iba_payload && (reserved == 0)) { - next_tvb = tvb_new_subset_remaining(tvb, local_offset+4); - - /* Look for sub-dissector, and call it if found. - Catch exceptions, so that if the reported length of "next_tvb" - was reduced by some dissector before an exception was thrown, - we can still put in an item for the trailer. */ - saved_proto = pinfo->current_proto; - - TRY { - dissector_found = dissector_try_uint(ethertype_dissector_table, - etype, next_tvb, pinfo, top_tree); - } - CATCH_NONFATAL_ERRORS { - /* Somebody threw an exception that means that there - was a problem dissecting the payload; that means - that a dissector was found, so we don't need to - dissect the payload as data or update the protocol - or info columns. - - Just show the exception and then drive on to show - the trailer, after noting that a dissector was found - and restoring the protocol value that was in effect - before we called the subdissector. - */ - - show_exception(next_tvb, pinfo, top_tree, EXCEPT_CODE, GET_MESSAGE); - dissector_found = TRUE; - pinfo->current_proto = saved_proto; - } - ENDTRY; - - if (dissector_found) { - proto_item *PAYLOAD_header_item; - proto_tree *PAYLOAD_header_tree; - /* now create payload entry to show Ethertype */ - PAYLOAD_header_item = proto_tree_add_item(parentTree, hf_infiniband_payload, tvb, local_offset, tvb_reported_length_remaining(tvb, local_offset)-6, ENC_NA); - proto_item_set_text(PAYLOAD_header_item, "%s", "IBA Payload - appears to be EtherType encapsulated"); - PAYLOAD_header_tree = proto_item_add_subtree(PAYLOAD_header_item, ett_payload); - proto_tree_add_uint(PAYLOAD_header_tree, hf_infiniband_etype, tvb, - local_offset, 2, tvb_get_ntohs(tvb, local_offset)); - - local_offset += 2; - - proto_tree_add_uint(PAYLOAD_header_tree, hf_infiniband_reserved16_RWH, tvb, - local_offset, 2, tvb_get_ntohs(tvb, local_offset)); - - } - - } - - reported_length = tvb_reported_length_remaining(tvb, - local_offset); - + reported_length = tvb_reported_length_remaining(tvb, local_offset); if (reported_length >= crclen) reported_length -= crclen; next_tvb = tvb_new_subset_length(tvb, local_offset, reported_length); /* Try any heuristic dissectors that requested a chance to try and dissect IB payloads */ - if (!dissector_found) { - dissector_found = dissector_try_heuristic(heur_dissectors_payload, next_tvb, pinfo, parentTree, &hdtbl_entry, info); - } - - if (!dissector_found) { + if (!dissector_try_heuristic(heur_dissectors_payload, next_tvb, pinfo, top_tree, &hdtbl_entry, info)) { /* No sub-dissector found. Label rest of packet as "Data" */ call_data_dissector(next_tvb, pinfo, top_tree); - } - /*parse_RWH(parentTree, tvb, &local_offset, pinfo, top_tree);*/ - /* Will contain ICRC <and maybe VCRC> = 4 or 4+2 (crclen) */ local_offset = tvb_reported_length(tvb) - crclen; } @@ -2687,49 +2611,126 @@ static void parse_RWH(proto_tree *ah_tree, tvbuff_t *tvb, gint *offset, packet_i * IN: The current offset * IN: pinfo - packet info from wireshark * IN: top_tree - parent tree of Infiniband dissector */ -static gboolean parse_EoIB(proto_tree *tree, tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *top_tree) +static gboolean dissect_mellanox_eoib(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_item *header_item; proto_tree *header_subtree; - gboolean ms; - gint8 seg_offset; tvbuff_t *encap_tvb; - /* the encapsulated eoib size (including the header!) is remaining length-6 bytes of CRC */ - int encap_size = tvb_reported_length_remaining(tvb, offset) - 6; + int offset = 0; + gboolean more_segments; + struct infinibandinfo *info = (struct infinibandinfo *)data; - if (encap_size < 4) { + if (((info->opCode & 0xE0) >> 5) != TRANSPORT_UD) + return FALSE; + + if ((tvb_get_guint8(tvb, offset) & 0xF0) != 0xC0) + return FALSE; + + if (tvb_reported_length(tvb) < 4) { /* not even large enough to contain the eoib encap header. error! */ return FALSE; } - encap_tvb = tvb_new_subset_length(tvb, offset + 4, encap_size - 4); - - header_item = proto_tree_add_item(tree, hf_infiniband_EOIB, tvb, offset, 4, ENC_NA); + header_item = proto_tree_add_item(tree, proto_mellanox_eoib, tvb, offset, 4, ENC_NA); header_subtree = proto_item_add_subtree(header_item, ett_eoib); proto_tree_add_item(header_subtree, hf_infiniband_ver, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(header_subtree, hf_infiniband_tcp_chk, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(header_subtree, hf_infiniband_ip_chk, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(header_subtree, hf_infiniband_fcs, tvb, offset, 2, ENC_BIG_ENDIAN); - - ms = tvb_get_bits8(tvb, (offset + 1)*8 + 2, 1); - seg_offset = tvb_get_bits8(tvb, (offset + 1)*8 + 3, 5); - proto_tree_add_item(header_subtree, hf_infiniband_ms, tvb, offset, 2, ENC_BIG_ENDIAN); - proto_tree_add_item(header_subtree, hf_infiniband_seg_off, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; + proto_tree_add_item(header_subtree, hf_infiniband_seg_off, tvb, offset, 2, ENC_BIG_ENDIAN); + more_segments = tvb_get_ntohs(tvb, offset) & (MELLANOX_MORE_SEGMENT_FLAG | MELLANOX_SEGMENT_FLAG); + offset += 2; proto_tree_add_item(header_subtree, hf_infiniband_seg_id, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; - if (seg_offset || ms) { + encap_tvb = tvb_new_subset_remaining(tvb, offset); + + if (more_segments) { /* this is a fragment of an encapsulated Ethernet jumbo frame, parse as data */ - call_data_dissector(encap_tvb, pinfo, top_tree); + call_data_dissector(encap_tvb, pinfo, tree); } else { /* non-fragmented frames can be fully parsed */ - call_dissector(eth_handle, encap_tvb, pinfo, top_tree); + call_dissector(eth_handle, encap_tvb, pinfo, tree); } return TRUE; } +/* IBA packet data could be anything in principle, however it is common + * practice to carry non-IBA data encapsulated with an EtherType header, + * similar to the RWH header. There is no way to identify these frames + * positively. + */ +static gboolean dissect_eth_over_ib(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) +{ + guint16 etype, reserved; + const char *saved_proto; + int offset = 0; + tvbuff_t *next_tvb; + struct infinibandinfo *info = (struct infinibandinfo *)data; + volatile gboolean dissector_found = FALSE; + + if (tvb_reported_length(tvb) < 4) { + /* not even large enough to contain the eoib encap header. error! */ + return FALSE; + } + + etype = tvb_get_ntohs(tvb, offset); + reserved = tvb_get_ntohs(tvb, offset + 2); + + if (reserved != 0) + return FALSE; + + next_tvb = tvb_new_subset_remaining(tvb, offset+4); + + /* Look for sub-dissector, and call it if found. + Catch exceptions, so that if the reported length of "next_tvb" + was reduced by some dissector before an exception was thrown, + we can still put in an item for the trailer. */ + saved_proto = pinfo->current_proto; + + TRY { + dissector_found = dissector_try_uint(ethertype_dissector_table, + etype, next_tvb, pinfo, tree); + } + CATCH_NONFATAL_ERRORS { + /* Somebody threw an exception that means that there + was a problem dissecting the payload; that means + that a dissector was found, so we don't need to + dissect the payload as data or update the protocol + or info columns. + + Just show the exception and then drive on to show + the trailer, after noting that a dissector was found + and restoring the protocol value that was in effect + before we called the subdissector. + */ + + show_exception(next_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE); + dissector_found = TRUE; + pinfo->current_proto = saved_proto; + } + ENDTRY; + + if (dissector_found) { + proto_item *PAYLOAD_header_item; + proto_tree *PAYLOAD_header_tree; + + /* now create payload entry to show Ethertype */ + PAYLOAD_header_item = proto_tree_add_item(info->payload_tree, hf_infiniband_payload, tvb, offset, tvb_reported_length_remaining(tvb, offset)-6, ENC_NA); + proto_item_set_text(PAYLOAD_header_item, "%s", "IBA Payload - appears to be EtherType encapsulated"); + PAYLOAD_header_tree = proto_item_add_subtree(PAYLOAD_header_item, ett_payload); + + proto_tree_add_item(PAYLOAD_header_tree, hf_infiniband_etype, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + proto_tree_add_item(PAYLOAD_header_tree, hf_infiniband_reserved16_RWH, tvb, offset, 2, ENC_BIG_ENDIAN); + + } + + return dissector_found; +} /* Parse Subnet Management (LID Routed) * IN: parentTree to add the dissection to @@ -3473,7 +3474,7 @@ static void parse_CM_DRsp(proto_tree *parentTree, packet_info *pinfo, tvbuff_t * static void parse_COM_MGT(proto_tree *parentTree, packet_info *pinfo, tvbuff_t *tvb, gint *offset) { MAD_Data MadData; - struct infinibandinfo info = { 0, FALSE, 0}; + struct infinibandinfo info = { 0, FALSE, 0, NULL}; gint local_offset; const char *label; proto_item *CM_header_item; @@ -5280,7 +5281,7 @@ static void dissect_general_info(tvbuff_t *tvb, gint offset, packet_info *pinfo, MAD_Data MadData; /* BTH - Base Trasport Header */ - struct infinibandinfo info = { 0, FALSE, 0}; + struct infinibandinfo info = { 0, FALSE, 0, NULL}; gint bthSize = 12; void *src_addr, /* the address to be displayed in the source/destination columns */ *dst_addr; /* (lid/gid number) will be stored here */ @@ -6443,40 +6444,6 @@ void proto_register_infiniband(void) FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} }, - /* Mellanox EoIB encapsulation header */ - { &hf_infiniband_EOIB, { - "Mellanox EoIB Encapsulation Header", "infiniband.eoib", - FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL} - }, - { &hf_infiniband_ver, { - "Version", "infiniband.eoib.version", - FT_UINT16, BASE_HEX, NULL, 0x3000, NULL, HFILL} - }, - { &hf_infiniband_tcp_chk, { - "TCP Checksum", "infiniband.eoib.tcp_chk", - FT_UINT16, BASE_HEX, NULL, 0x0c00, NULL, HFILL} - }, - { &hf_infiniband_ip_chk, { - "IP Checksum", "infiniband.eoib.ip_chk", - FT_UINT16, BASE_HEX, NULL, 0x0300, NULL, HFILL} - }, - { &hf_infiniband_fcs, { - "FCS Field Present", "infiniband.eoib.fcs", - FT_BOOLEAN, 16, NULL, 0x0040, NULL, HFILL} - }, - { &hf_infiniband_ms, { - "More Segments to Follow", "infiniband.eoib.ms", - FT_BOOLEAN, 16, NULL, 0x0020, NULL, HFILL} - }, - { &hf_infiniband_seg_off, { - "Segment Offset", "infiniband.eoib.ip_seg_offset", - FT_UINT16, BASE_DEC, NULL, 0x001f, NULL, HFILL} - }, - { &hf_infiniband_seg_id, { - "Segment ID", "infiniband.eoib.ip_seg_id", - FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} - }, - /* NodeDescription */ { &hf_infiniband_NodeDescription_NodeString, { "NodeString", "infiniband.nodedescription.nodestring", @@ -7881,7 +7848,6 @@ void proto_register_infiniband(void) &ett_multipathrecord, &ett_serviceassocrecord, &ett_perfclass, - &ett_eoib }; static hf_register_info hf_link[] = { @@ -7907,11 +7873,46 @@ void proto_register_infiniband(void) } }; - static gint *ett_link_array[] = { &ett_link }; + static hf_register_info hf_eoib[] = { + /* Mellanox EoIB encapsulation header */ + { &hf_infiniband_ver, { + "Version", "infiniband.eoib.version", + FT_UINT16, BASE_HEX, NULL, MELLANOX_VERSION_FLAG, NULL, HFILL} + }, + { &hf_infiniband_tcp_chk, { + "TCP Checksum", "infiniband.eoib.tcp_chk", + FT_UINT16, BASE_HEX, NULL, MELLANOX_TCP_CHECKSUM_FLAG, NULL, HFILL} + }, + { &hf_infiniband_ip_chk, { + "IP Checksum", "infiniband.eoib.ip_chk", + FT_UINT16, BASE_HEX, NULL, MELLANOX_IP_CHECKSUM_FLAG, NULL, HFILL} + }, + { &hf_infiniband_fcs, { + "FCS Field Present", "infiniband.eoib.fcs", + FT_BOOLEAN, 16, NULL, MELLANOX_FCS_PRESENT_FLAG, NULL, HFILL} + }, + { &hf_infiniband_ms, { + "More Segments to Follow", "infiniband.eoib.ms", + FT_BOOLEAN, 16, NULL, MELLANOX_MORE_SEGMENT_FLAG, NULL, HFILL} + }, + { &hf_infiniband_seg_off, { + "Segment Offset", "infiniband.eoib.ip_seg_offset", + FT_UINT16, BASE_DEC, NULL, MELLANOX_SEGMENT_FLAG, NULL, HFILL} + }, + { &hf_infiniband_seg_id, { + "Segment ID", "infiniband.eoib.ip_seg_id", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + }; + + static gint *ett_eoib_array[] = { + &ett_eoib + }; + proto_infiniband = proto_register_protocol("InfiniBand", "IB", "infiniband"); ib_handle = register_dissector("infiniband", dissect_infiniband, proto_infiniband); @@ -7925,16 +7926,8 @@ void proto_register_infiniband(void) /* register dissection preferences */ infiniband_module = prefs_register_protocol(proto_infiniband, proto_reg_handoff_infiniband); - prefs_register_bool_preference(infiniband_module, "identify_payload", - "Attempt to identify and parse encapsulated IBA payloads", - "When set, dissector will attempt to identify unknown IBA payloads " - "as containing an encapsulated ethertype, and parse them accordingly", - &pref_identify_iba_payload); - prefs_register_bool_preference(infiniband_module, "dissect_eoib", - "Attempt to identify and parse Mellanox EoIB packets", - "When set, dissector will attempt to identify and parse " - "Mellanox Ethernet-over-InfiniBand packets", - &pref_dissect_eoib); + prefs_register_obsolete_preference(infiniband_module, "identify_payload"); + prefs_register_obsolete_preference(infiniband_module, "dissect_eoib"); prefs_register_uint_preference(infiniband_module, "rroce.port", "RRoce UDP Port(Default 1021)", "when set " "the Analyser will consider this as RRoce UDP Port and parse it accordingly", 10, &pref_rroce_udp_port); @@ -7945,6 +7938,10 @@ void proto_register_infiniband(void) proto_register_field_array(proto_infiniband_link, hf_link, array_length(hf_link)); proto_register_subtree_array(ett_link_array, array_length(ett_link_array)); + proto_mellanox_eoib = proto_register_protocol("Mellanox EoIB Encapsulation Header", "Mellanox EoIB", "infiniband.eoib"); + proto_register_field_array(proto_infiniband, hf_eoib, array_length(hf_eoib)); + proto_register_subtree_array(ett_eoib_array, array_length(ett_eoib_array)); + /* initialize the hash table */ CM_context_table = g_hash_table_new_full(g_int64_hash, g_int64_equal, table_destroy_notify, table_destroy_notify); @@ -7956,6 +7953,7 @@ void proto_reg_handoff_infiniband(void) static gboolean initialized = FALSE; static guint prev_rroce_udp_port; dissector_handle_t roce_handle, rroce_handle; + int proto_ethertype; ipv6_handle = find_dissector_add_dependency("ipv6", proto_infiniband); @@ -8006,6 +8004,12 @@ void proto_reg_handoff_infiniband(void) dissector_add_uint("udp.port", pref_rroce_udp_port, rroce_handle); dissector_add_uint("wtap_encap", WTAP_ENCAP_INFINIBAND, ib_handle); + heur_dissector_add("infiniband.payload", dissect_mellanox_eoib, "Mellanox EoIB", "mellanox_eoib", proto_mellanox_eoib, HEURISTIC_ENABLE); + + /* This could be put in the ethernet dissector file, but since there are a few Infiniband fields in the encapsulation, + keep the dissector here, but associate it with ethernet */ + proto_ethertype = proto_get_id_by_filter_name( "ethertype" ); + heur_dissector_add("infiniband.payload", dissect_eth_over_ib, "Ethernet over IB", "eth_over_ib", proto_ethertype, HEURISTIC_ENABLE); } /* |