diff options
author | etxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7> | 2010-08-16 05:48:40 +0000 |
---|---|---|
committer | etxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7> | 2010-08-16 05:48:40 +0000 |
commit | 9d86c75240bd8a4756294dde2c0bd82dcf304ba4 (patch) | |
tree | 5ca76674dcd910b2c764139b4a9f6273ec8d93ec /epan/dissectors | |
parent | e01bcaed81403b7e1614bbf9b944930da5a8d8b2 (diff) |
From Slava:
This patch adds to the Infiniband dissector the ability to dissect EoIB
(Ethernet-over-Infiniband) traffic which uses Mellanox Technologies Ltd's
standard for encapsulating Ethernet traffic inside Infiniband packets.
This patch is submitted on behalf of Mellanox Technologies Ltd.
https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5061
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@33808 f5534014-38df-0310-8fa8-9805f1628bb7
Diffstat (limited to 'epan/dissectors')
-rw-r--r-- | epan/dissectors/packet-infiniband.c | 99 | ||||
-rw-r--r-- | epan/dissectors/packet-infiniband.h | 28 |
2 files changed, 126 insertions, 1 deletions
diff --git a/epan/dissectors/packet-infiniband.c b/epan/dissectors/packet-infiniband.c index 3daf8dcbf5..660db0d9c4 100644 --- a/epan/dissectors/packet-infiniband.c +++ b/epan/dissectors/packet-infiniband.c @@ -303,6 +303,7 @@ skip_lrh: * The find_next_header_sequence method could be used to automate this. * We need to keep track of this so we know much data to mark as payload/ICRC/VCRC values. */ + transport_type = (opCode & 0xE0) >> 5; /* save transport type for identifying EoIB payloads later... */ nextHeaderSequence = find_next_header_sequence((guint32) opCode); /* find_next_header_sequence gives us the DEFINE value corresponding to the header order following */ @@ -968,7 +969,14 @@ static void parse_PAYLOAD(proto_tree *parentTree, packet_info *pinfo, tvbuff_t * etype = tvb_get_ntohs(tvb, local_offset); reserved = tvb_get_ntohs(tvb, local_offset + 2); - if (pref_identify_iba_payload && reserved == 0) { + /* 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 && + transport_type == TRANSPORT_UD && + tvb_get_bits8(tvb, local_offset*8, 4) == 0xC) { + dissector_found = parse_EoIB(parentTree, tvb, local_offset, pinfo); + } + else if (pref_identify_iba_payload && reserved == 0) { /* Get the captured length and reported length of the data after the Ethernet type. */ @@ -1167,6 +1175,54 @@ static void parse_RWH(proto_tree *ah_tree, tvbuff_t *tvb, gint *offset, packet_i proto_tree_add_item(ah_tree, hf_infiniband_variant_crc, tvb, *offset, 2, FALSE); } +/* Parse a Mellanox EoIB Encapsulation Header and the associated Ethernet frame +* IN: parentTree to add the dissection to - in this code the all_headers_tree +* IN: tvb - the data buffer from wireshark +* IN: The current offset +* IN: pinfo - packet info from wireshark */ +static gboolean parse_EoIB(proto_tree *tree, tvbuff_t *tvb, gint offset, packet_info *pinfo) +{ + 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; + + if (encap_size < 4) { + /* not even large enough to contain the eoib encap header. error! */ + return FALSE; + } + + encap_tvb = tvb_new_subset(tvb, offset + 4, tvb_length_remaining(tvb, offset + 4), encap_size - 4); + + header_item = proto_tree_add_item(tree, hf_infiniband_EOIB, tvb, offset, 4, FALSE); + header_subtree = proto_item_add_subtree(header_item, ett_eoib); + + proto_tree_add_item(header_subtree, hf_infiniband_ver, tvb, offset, 2, FALSE); + proto_tree_add_item(header_subtree, hf_infiniband_tcp_chk, tvb, offset, 2, FALSE); + proto_tree_add_item(header_subtree, hf_infiniband_ip_chk, tvb, offset, 2, FALSE); + proto_tree_add_item(header_subtree, hf_infiniband_fcs, tvb, offset, 2, FALSE); + + 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, FALSE); + proto_tree_add_item(header_subtree, hf_infiniband_seg_off, tvb, offset, 2, FALSE); offset += 2; + proto_tree_add_item(header_subtree, hf_infiniband_seg_id, tvb, offset, 2, FALSE); offset += 2; + + if (seg_offset || ms) { + /* this is a fragment of an encapsulated Ethernet jumbo frame, parse as data */ + call_dissector(data_handle, encap_tvb, pinfo, top_tree); + } else { + /* non-fragmented frames can be fully parsed */ + call_dissector(eth_handle, encap_tvb, pinfo, top_tree); + } + + return TRUE; +} + /* Parse Subnet Management (LID Routed) * IN: parentTree to add the dissection to * IN: pinfo - packet info from wireshark @@ -3853,6 +3909,40 @@ 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", @@ -5217,6 +5307,7 @@ void proto_register_infiniband(void) &ett_multipathrecord, &ett_serviceassocrecord, &ett_perfclass, + &ett_eoib }; static hf_register_info hf_link[] = { @@ -5261,6 +5352,11 @@ void proto_register_infiniband(void) "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); proto_infiniband_link = proto_register_protocol("InfiniBand Link", "InfiniBand Link", "infiniband_link"); register_dissector("infiniband_link", dissect_infiniband_link, proto_infiniband_link); @@ -5277,6 +5373,7 @@ void proto_reg_handoff_infiniband(void) ipv6_handle = find_dissector("ipv6"); data_handle = find_dissector("data"); + eth_handle = find_dissector("eth"); ethertype_dissector_table = find_dissector_table("ethertype"); /* create and announce an anonymous RoCE dissector */ diff --git a/epan/dissectors/packet-infiniband.h b/epan/dissectors/packet-infiniband.h index 817b3130f0..22770cdfdc 100644 --- a/epan/dissectors/packet-infiniband.h +++ b/epan/dissectors/packet-infiniband.h @@ -87,6 +87,7 @@ 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; @@ -111,6 +112,7 @@ typedef struct { /* Dissector Declarations */ static dissector_handle_t ipv6_handle; static dissector_handle_t data_handle; +static dissector_handle_t eth_handle; static dissector_table_t ethertype_dissector_table; static void dissect_roce(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); @@ -135,6 +137,7 @@ static void parse_DETH(proto_tree *, tvbuff_t *, gint *offset, gint* src_qp); 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 *); +static gboolean parse_EoIB(proto_tree *, tvbuff_t *, gint offset, packet_info *); 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); @@ -575,6 +578,15 @@ 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 hf_infiniband_ver = -1; +static int hf_infiniband_tcp_chk = -1; +static int hf_infiniband_ip_chk = -1; +static int hf_infiniband_fcs = -1; +static int hf_infiniband_ms = -1; +static int hf_infiniband_seg_off = -1; +static int hf_infiniband_seg_id = -1; /* Attributes * Additional Structures for individuala attribute decoding. @@ -1252,6 +1264,16 @@ static const value_string OpCodeMap[] = /* ___________________________________ */ +/* Infiniband transport services + These are an enumeration of the transport services over which an IB packet + might be sent. The values match the corresponding 3 bits of the opCode field + in the BTH */ +#define TRANSPORT_RC 0 +#define TRANSPORT_UC 1 +#define TRANSPORT_RD 2 +#define TRANSPORT_UD 3 + + /* Array of all availavle OpCodes to make matching a bit easier. * The OpCodes dictate the header sequence following in the packet. * These arrays tell the dissector which headers must be decoded for the given OpCode. */ @@ -1381,4 +1403,10 @@ static gchar *src_addr_str = NULL, /* the string to be displayed in the sour /* settings to be set by the user via the preferences dialog */ static gboolean pref_identify_iba_payload = TRUE; +static gint8 transport_type = -1; /* reflects the transport type of the packet being parsed. + only use one of the TRANSPORT_* values for this field */ + +/* settings to be set by the user via the preferences dialog */ +static gboolean pref_dissect_eoib = TRUE; + #endif |