Treat TVBs as opaque: use the accessor functions instead of accessing the fields
[obnox/wireshark/wip.git] / epan / dissectors / packet-infiniband.c
1 /* packet-infiniband.c
2  * Routines for Infiniband/ERF Dissection
3  * Copyright 2008 Endace Technology Limited
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * Modified 2010 by Mellanox Technologies Ltd.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <glib.h>
33 #include <epan/packet.h>
34 #include <epan/proto.h>
35 #include <epan/emem.h>
36 #include <epan/conversation.h>
37 #include <epan/dissectors/packet-frame.h>
38 #include <epan/prefs.h>
39 #include <epan/etypes.h>
40 #include <string.h>
41 #include "packet-infiniband.h"
42
43 #define PROTO_TAG_INFINIBAND    "Infiniband"
44
45 /* Wireshark ID */
46 static int proto_infiniband = -1;
47 static int proto_infiniband_link = -1;
48
49 /* Variables to hold expansion values between packets */
50 /* static gint ett_infiniband = -1;                */
51 static gint ett_all_headers = -1;
52 static gint ett_lrh = -1;
53 static gint ett_grh = -1;
54 static gint ett_bth = -1;
55 static gint ett_rwh = -1;
56 static gint ett_rdeth = -1;
57 static gint ett_deth = -1;
58 static gint ett_reth = -1;
59 static gint ett_atomiceth = -1;
60 static gint ett_aeth = -1;
61 static gint ett_atomicacketh = -1;
62 static gint ett_immdt = -1;
63 static gint ett_ieth = -1;
64 static gint ett_payload = -1;
65 static gint ett_vendor = -1;
66 static gint ett_subn_lid_routed = -1;
67 static gint ett_subn_directed_route = -1;
68 static gint ett_subnadmin = -1;
69 static gint ett_mad = -1;
70 static gint ett_cm = -1;
71 static gint ett_rmpp = -1;
72 static gint ett_subm_attribute = -1;
73 static gint ett_suba_attribute = -1;
74 static gint ett_datadetails = -1;
75 static gint ett_noticestraps = -1;
76 /* static gint ett_nodedesc = -1;                  */
77 /* static gint ett_nodeinfo = -1;                  */
78 /* static gint ett_switchinfo = -1;                */
79 /* static gint ett_guidinfo = -1;                  */
80 /* static gint ett_portinfo = -1;                  */
81 static gint ett_portinfo_capmask = -1;
82 static gint ett_pkeytable = -1;
83 static gint ett_sltovlmapping = -1;
84 static gint ett_vlarbitrationtable = -1;
85 static gint ett_linearforwardingtable = -1;
86 static gint ett_randomforwardingtable = -1;
87 static gint ett_multicastforwardingtable = -1;
88 static gint ett_sminfo = -1;
89 static gint ett_vendordiag = -1;
90 static gint ett_ledinfo = -1;
91 static gint ett_linkspeedwidthpairs = -1;
92 static gint ett_informinfo = -1;
93 static gint ett_linkrecord = -1;
94 static gint ett_servicerecord = -1;
95 static gint ett_pathrecord = -1;
96 static gint ett_mcmemberrecord = -1;
97 static gint ett_tracerecord = -1;
98 static gint ett_multipathrecord = -1;
99 static gint ett_serviceassocrecord = -1;
100 static gint ett_perfclass = -1;
101 static gint ett_eoib = -1;
102 static gint ett_link = -1;
103
104 /* Global ref to highest level tree should we find other protocols encapsulated in IB */
105 static proto_tree *top_tree = NULL;
106
107 /* Dissector Declarations */
108 static dissector_handle_t ipv6_handle;
109 static dissector_handle_t data_handle;
110 static dissector_handle_t eth_handle;
111 static dissector_table_t ethertype_dissector_table;
112
113 /* MAD_Data
114 * Structure to hold information from the common MAD header.
115 * This is necessary because the MAD header contains information which significantly changes the dissection algorithm. */
116 typedef struct {
117     guint8 managementClass;
118     guint8 classVersion;
119     guint8 method;
120     guint8 status;
121     guint16 classSpecific;
122     guint64 transactionID;
123     guint16 attributeID;
124     guint32 attributeModifier;
125     char data[232];
126 } MAD_Data;
127
128 /* Forward-declarations */
129
130 static void dissect_roce(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
131 static void dissect_infiniband(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
132 static void dissect_infiniband_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean starts_with_grh);
133 static void dissect_infiniband_link(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
134 static gint32 find_next_header_sequence(guint32 OpCode);
135 static gboolean contains(guint32 value, guint32* arr, int length);
136 static void dissect_general_info(tvbuff_t *tvb, gint offset, packet_info *pinfo, gboolean starts_with_grh);
137
138 /* Parsing Methods for specific IB headers. */
139
140 static void parse_VENDOR(proto_tree *, tvbuff_t *, gint *);
141 static void parse_PAYLOAD(proto_tree *, packet_info *, tvbuff_t *, gint *, gint length);
142 static void parse_IETH(proto_tree *, tvbuff_t *, gint *);
143 static void parse_IMMDT(proto_tree *, tvbuff_t *, gint *offset);
144 static void parse_ATOMICACKETH(proto_tree *, tvbuff_t *, gint *offset);
145 static void parse_AETH(proto_tree *, tvbuff_t *, gint *offset);
146 static void parse_ATOMICETH(proto_tree *, tvbuff_t *, gint *offset);
147 static void parse_RETH(proto_tree *, tvbuff_t *, gint *offset);
148 static void parse_DETH(proto_tree *, packet_info *, tvbuff_t *, gint *offset);
149 static void parse_RDETH(proto_tree *, tvbuff_t *, gint *offset);
150 static void parse_IPvSix(proto_tree *, tvbuff_t *, gint *offset, packet_info *);
151 static void parse_RWH(proto_tree *, tvbuff_t *, gint *offset, packet_info *);
152 static gboolean parse_EoIB(proto_tree *, tvbuff_t *, gint offset, packet_info *);
153
154 static void parse_SUBN_LID_ROUTED(proto_tree *, packet_info *, tvbuff_t *, gint *offset);
155 static void parse_SUBN_DIRECTED_ROUTE(proto_tree *, packet_info *, tvbuff_t *, gint *offset);
156 static void parse_SUBNADMN(proto_tree *, packet_info *, tvbuff_t *, gint *offset);
157 static void parse_PERF(proto_tree *, tvbuff_t *, packet_info *, gint *offset);
158 static void parse_BM(proto_tree *, tvbuff_t *, gint *offset);
159 static void parse_DEV_MGT(proto_tree *, tvbuff_t *, gint *offset);
160 static void parse_COM_MGT(proto_tree *parentTree, packet_info *pinfo, tvbuff_t *tvb, gint *offset);
161 static void parse_SNMP(proto_tree *, tvbuff_t *, gint *offset);
162 static void parse_VENDOR_MANAGEMENT(proto_tree *, tvbuff_t *, gint *offset);
163 static void parse_APPLICATION_MANAGEMENT(proto_tree *, tvbuff_t *, gint *offset);
164 static void parse_RESERVED_MANAGEMENT(proto_tree *, tvbuff_t *, gint *offset);
165
166 static gboolean parse_MAD_Common(proto_tree*, tvbuff_t*, gint *offset, MAD_Data*);
167 static gboolean parse_RMPP(proto_tree* , tvbuff_t* , gint *offset);
168 static void label_SUBM_Method(proto_item*, MAD_Data*, packet_info*);
169 static void label_SUBM_Attribute(proto_item*, MAD_Data*, packet_info*);
170 static void label_SUBA_Method(proto_item*, MAD_Data*, packet_info*);
171 static void label_SUBA_Attribute(proto_item*, MAD_Data*, packet_info*);
172
173 /* Class Attribute Parsing Routines */
174 static gboolean parse_SUBM_Attribute(proto_tree*, tvbuff_t*, gint *offset, MAD_Data*);
175 static gboolean parse_SUBA_Attribute(proto_tree*, tvbuff_t*, gint *offset, MAD_Data*);
176
177 /* These methods parse individual attributes
178 * Naming convention FunctionHandle = "parse_" + [Attribute Name];
179 * Where [Attribute Name] is the attribute identifier from chapter 14 of the IB Specification
180 * Subnet Management */
181 static void parse_NoticesAndTraps(proto_tree*, tvbuff_t*, gint *offset);
182 static void parse_NodeDescription(proto_tree*, tvbuff_t*, gint *offset);
183 static void parse_NodeInfo(proto_tree*, tvbuff_t*, gint *offset);
184 static void parse_SwitchInfo(proto_tree*, tvbuff_t*, gint *offset);
185 static void parse_GUIDInfo(proto_tree*, tvbuff_t*, gint *offset);
186 static void parse_PortInfo(proto_tree*, tvbuff_t*, gint *offset);
187 static void parse_P_KeyTable(proto_tree*, tvbuff_t*, gint *offset);
188 static void parse_SLtoVLMappingTable(proto_tree*, tvbuff_t*, gint *offset);
189 static void parse_VLArbitrationTable(proto_tree*, tvbuff_t*, gint *offset);
190 static void parse_LinearForwardingTable(proto_tree*, tvbuff_t*, gint *offset);
191 static void parse_RandomForwardingTable(proto_tree*, tvbuff_t*, gint *offset);
192 static void parse_MulticastForwardingTable(proto_tree*, tvbuff_t*, gint *offset);
193 static void parse_SMInfo(proto_tree*, tvbuff_t*, gint *offset);
194 static void parse_VendorDiag(proto_tree*, tvbuff_t*, gint *offset);
195 static void parse_LedInfo(proto_tree*, tvbuff_t*, gint *offset);
196 static void parse_LinkSpeedWidthPairsTable(proto_tree*, tvbuff_t*, gint *offset);
197
198 /* These methods parse individual attributes for specific MAD management classes.
199 * Naming convention FunctionHandle = "parse_" + [Management Class] + "_" + [Attribute Name];
200 * Where [Management Class] is the shorthand name for the management class as defined
201 * in the MAD Management Classes section below in this file, and [Attribute Name] is the
202 * attribute identifier from the corresponding chapter of the IB Specification */
203 static void parse_PERF_PortCounters(proto_tree* parentTree, tvbuff_t* tvb, packet_info *pinfo, gint *offset);
204 static void parse_PERF_PortCountersExtended(proto_tree* parentTree, tvbuff_t* tvb, packet_info *pinfo, gint *offset);
205
206 /* Subnet Administration */
207 static void parse_InformInfo(proto_tree*, tvbuff_t*, gint *offset);
208 static void parse_LinkRecord(proto_tree*, tvbuff_t*, gint *offset);
209 static void parse_ServiceRecord(proto_tree*, tvbuff_t*, gint *offset);
210 static void parse_PathRecord(proto_tree*, tvbuff_t*, gint *offset);
211 static void parse_MCMemberRecord(proto_tree*, tvbuff_t*, gint *offset);
212 static void parse_TraceRecord(proto_tree*, tvbuff_t*, gint *offset);
213 static void parse_MultiPathRecord(proto_tree*, tvbuff_t*, gint *offset);
214 static void parse_ServiceAssociationRecord(proto_tree*, tvbuff_t*, gint *offset);
215
216 /* Subnet Administration */
217 static void parse_RID(proto_tree*, tvbuff_t*, gint *offset, MAD_Data*);
218
219 /* SM Methods */
220 static const value_string SUBM_Methods[] = {
221     { 0x01, "SubnGet("},
222     { 0x02, "SubnSet("},
223     { 0x81, "SubnGetResp("},
224     { 0x05, "SubnTrap("},
225     { 0x07, "SubnTrapResp("},
226     { 0, NULL}
227 };
228 /* SM Attributes */
229 static const value_string SUBM_Attributes[] = {
230     { 0x0001, "Attribute (ClassPortInfo)"},
231     { 0x0002, "Attribute (Notice)"},
232     { 0x0003, "Attribute (InformInfo)"},
233     { 0x0010, "Attribute (NodeDescription)"},
234     { 0x0011, "Attribute (NodeInfo)"},
235     { 0x0012, "Attribute (SwitchInfo)"},
236     { 0x0014, "Attribute (GUIDInfo)"},
237     { 0x0015, "Attribute (PortInfo)"},
238     { 0x0016, "Attribute (P_KeyTable)"},
239     { 0x0017, "Attribute (SLtoVLMapptingTable)"},
240     { 0x0018, "Attribute (VLArbitrationTable)"},
241     { 0x0019, "Attribute (LinearForwardingTable)"},
242     { 0x001A, "Attribute (RandomForwardingTable)"},
243     { 0x001B, "Attribute (MulticastForwardingTable)"},
244     { 0x001C, "Attribute (LinkSpeedWidthPairsTable)"},
245     { 0x0020, "Attribute (SMInfo)"},
246     { 0x0030, "Attribute (VendorDiag)"},
247     { 0x0031, "Attribute (LedInfo)"},
248     { 0, NULL}
249 };
250
251 /* SA Methods */
252 static const value_string SUBA_Methods[] = {
253     { 0x01, "SubnAdmGet("},
254     { 0x81, "SubnAdmGetResp("},
255     { 0x02, "SubnAdmSet("},
256     { 0x06, "SubnAdmReport("},
257     { 0x86, "SubnAdmReportResp("},
258     { 0x12, "SubnAdmGetTable("},
259     { 0x92, "SubnAdmGetTableResp("},
260     { 0x13, "SubnAdmGetTraceTable("},
261     { 0x14, "SubnAdmGetMulti("},
262     { 0x94, "SubnAdmGetMultiResp("},
263     { 0x15, "SubnAdmDelete("},
264     { 0x95, "SubnAdmDeleteResp("},
265     { 0, NULL}
266 };
267 /* SA Attributes */
268 static const value_string SUBA_Attributes[] = {
269     { 0x0001, "Attribute (ClassPortInfo)"},
270     { 0x0002, "Attribute (Notice)"},
271     { 0x0003, "Attribute (InformInfo)"},
272     { 0x0011, "Attribute (NodeRecord)"},
273     { 0x0012, "Attribute (PortInfoRecord)"},
274     { 0x0013, "Attribute (SLtoVLMappingTableRecord)"},
275     { 0x0014, "Attribute (SwitchInfoRecord)"},
276     { 0x0015, "Attribute (LinearForwardingTableRecord)"},
277     { 0x0016, "Attribute (RandomForwardingTableRecord)"},
278     { 0x0017, "Attribute (MulticastForwardingTableRecord)"},
279     { 0x0018, "Attribute (SMInfoRecord)"},
280     { 0x0019, "Attribute (LinkSpeedWidthPairsTableRecord)"},
281     { 0x00F3, "Attribute (InformInfoRecord)"},
282     { 0x0020, "Attribute (LinkRecord)"},
283     { 0x0030, "Attribute (GuidInfoRecord)"},
284     { 0x0031, "Attribute (ServiceRecord)"},
285     { 0x0033, "Attribute (P_KeyTableRecord)"},
286     { 0x0035, "Attribute (PathRecord)"},
287     { 0x0036, "Attribute (VLArbitrationTableRecord)"},
288     { 0x0038, "Attribute (MCMembersRecord)"},
289     { 0x0039, "Attribute (TraceRecord)"},
290     { 0x003A, "Attribute (MultiPathRecord)"},
291     { 0x003B, "Attribute (ServiceAssociationRecord)"},
292     { 0, NULL}
293 };
294
295 /* CM Attributes */
296 static const value_string CM_Attributes[] = {
297     { 0x0001, "ClassPortInfo"},
298     { 0x0010, "ConnectRequest"},
299     { 0x0011, "MsgRcptAck"},
300     { 0x0012, "ConnectReject"},
301     { 0x0013, "ConnectReply"},
302     { 0x0014, "ReadyToUse"},
303     { 0x0015, "DisconnectRequest"},
304     { 0x0016, "DisconnectReply"},
305     { 0x0017, "ServiceIDResReq"},
306     { 0x0018, "ServiceIDResReqResp"},
307     { 0x0019, "LoadAlternatePath"},
308     { 0x001A, "AlternatePathResponse"},
309     { 0, NULL}
310 };
311
312
313 /* RMPP Types */
314 #define RMPP_ILLEGAL 0
315 #define RMPP_DATA   1
316 #define RMPP_ACK    2
317 #define RMPP_STOP   3
318 #define RMPP_ABORT  4
319
320 static const value_string RMPP_Packet_Types[] = {
321     { RMPP_ILLEGAL, " Illegal RMPP Type (0)! " },
322     { RMPP_DATA, "RMPP (DATA)" },
323     { RMPP_ACK, "RMPP (ACK)" },
324     { RMPP_STOP, "RMPP (STOP)" },
325     { RMPP_ABORT, "RMPP (ABORT)" },
326     { 0, NULL}
327 };
328
329 static const value_string RMPP_Flags[] = {
330     { 3, " (Transmission Sequence - First Packet)"},
331     { 5, " (Transmission Sequence - Last Packet)"},
332     { 1, " (Transmission Sequence) " },
333     { 0, NULL}
334 };
335
336 static const value_string RMPP_Status[]= {
337     { 0, " (Normal)"},
338     { 1, " (Resources Exhausted)"},
339     { 118, " (Total Time Too Long)"},
340     { 119, " (Inconsistent Last and PayloadLength)"},
341     { 120, " (Inconsistent First and Segment Number)"},
342     { 121, " (Bad RMPPType)"},
343     { 122, " (NewWindowLast Too Small)"},
344     { 123, " (SegmentNumber Too Big)"},
345     { 124, " (Illegal Status)"},
346     { 125, " (Unsupported Version)"},
347     { 126, " (Too Many Retries)"},
348     { 127, " (Unspecified - Unknown Error Code on ABORT)"},
349     { 0, NULL}
350 };
351
352 static const value_string DiagCode[]= {
353     {0x0000, "Function Ready"},
354     {0x0001, "Performing Self Test"},
355     {0x0002, "Initializing"},
356     {0x0003, "Soft Error - Function has non-fatal error"},
357     {0x0004, "Hard Error - Function has fatal error"},
358     { 0, NULL}
359 };
360 static const value_string LinkWidthEnabled[]= {
361     {0x0000, "No State Change"},
362     {0x0001, "1x"},
363     {0x0002, "4x"},
364     {0x0003, "1x or 4x"},
365     {0x0004, "8x"},
366     {0x0005, "1x or 8x"},
367     {0x0006, "4x or 8x"},
368     {0x0007, "1x or 4x or 8x"},
369     {0x0008, "12x"},
370     {0x0009, "1x or 12x"},
371     {0x000A, "4x or 12x"},
372     {0x000B, "1x or 4x or 12x"},
373     {0x000C, "8x or 12x"},
374     {0x000D, "1x or 8x or 12x"},
375     {0x000E, "4x or 8x or 12x"},
376     {0x000E, "1x or 4x or 8x or 12x"},
377     {0x00FF, "Set to LinkWidthSupported Value - Response contains actual LinkWidthSupported"},
378     { 0, NULL}
379 };
380
381 static const value_string LinkWidthSupported[]= {
382     {0x0001, "1x"},
383     {0x0003, "1x or 4x"},
384     {0x0007, "1x or 4x or 8x"},
385     {0x000B, "1x or 4x or 12x"},
386     {0x000F, "1x or 4x or 8x or 12x"},
387     { 0, NULL}
388 };
389 static const value_string LinkWidthActive[]= {
390     {0x0001, "1x"},
391     {0x0002, "4x"},
392     {0x0004, "8x"},
393     {0x0008, "12x"},
394     { 0, NULL}
395 };
396 static const value_string LinkSpeedSupported[]= {
397     {0x0001, "2.5 Gbps"},
398     {0x0003, "2.5 or 5.0 Gbps"},
399     {0x0005, "2.5 or 10.0 Gbps"},
400     {0x0007, "2.5 or 5.0 or 10.0 Gbps"},
401     { 0, NULL}
402 };
403 static const value_string PortState[]= {
404     {0x0000, "No State Change"},
405     {0x0001, "Down (includes failed links)"},
406     {0x0002, "Initialized"},
407     {0x0003, "Armed"},
408     {0x0004, "Active"},
409     { 0, NULL}
410 };
411 static const value_string PortPhysicalState[]= {
412     {0x0000, "No State Change"},
413     {0x0001, "Sleep"},
414     {0x0002, "Polling"},
415     {0x0003, "Disabled"},
416     {0x0004, "PortConfigurationTraining"},
417     {0x0005, "LinkUp"},
418     {0x0006, "LinkErrorRecovery"},
419     {0x0007, "Phy Test"},
420     { 0, NULL}
421 };
422 static const value_string LinkDownDefaultState[]= {
423     {0x0000, "No State Change"},
424     {0x0001, "Sleep"},
425     {0x0002, "Polling"},
426     { 0, NULL}
427 };
428 static const value_string LinkSpeedActive[]= {
429     {0x0001, "2.5 Gbps"},
430     {0x0002, "5.0 Gbps"},
431     {0x0004, "10.0 Gbps"},
432     { 0, NULL}
433 };
434 static const value_string LinkSpeedEnabled[]= {
435     {0x0000, "No State Change"},
436     {0x0001, "2.5 Gbps"},
437     {0x0003, "2.5 or 5.0 Gbps"},
438     {0x0005, "2.5 or 10.0 Gbps"},
439     {0x0007, "2.5 or 5.0 or 10.0 Gbps"},
440     {0x000F, "Set to LinkSpeedSupported value - response contains actual LinkSpeedSupported"},
441     { 0, NULL}
442 };
443 static const value_string NeighborMTU[]= {
444     {0x0001, "256"},
445     {0x0002, "512"},
446     {0x0003, "1024"},
447     {0x0004, "2048"},
448     {0x0005, "4096"},
449     { 0, NULL}
450 };
451 static const value_string VLCap[]= {
452     {0x0001, "VL0"},
453     {0x0002, "VL0, VL1"},
454     {0x0003, "VL0 - VL3"},
455     {0x0004, "VL0 - VL7"},
456     {0x0005, "VL0 - VL14"},
457     { 0, NULL}
458 };
459 static const value_string MTUCap[]= {
460     {0x0001, "256"},
461     {0x0002, "512"},
462     {0x0003, "1024"},
463     {0x0004, "2048"},
464     {0x0005, "4096"},
465     { 0, NULL}
466 };
467 static const value_string OperationalVLs[]= {
468     {0x0000, "No State Change"},
469     {0x0001, "VL0"},
470     {0x0002, "VL0, VL1"},
471     {0x0003, "VL0 - VL3"},
472     {0x0004, "VL0 - VL7"},
473     {0x0005, "VL0 - VL14"},
474     { 0, NULL}
475 };
476
477 /* Local Route Header (LRH) */
478 static int hf_infiniband_LRH = -1;
479 static int hf_infiniband_virtual_lane = -1;
480 static int hf_infiniband_link_version = -1;
481 static int hf_infiniband_service_level = -1;
482 static int hf_infiniband_reserved2 = -1;
483 static int hf_infiniband_link_next_header = -1;
484 static int hf_infiniband_destination_local_id = -1;
485 static int hf_infiniband_reserved5 = -1;
486 static int hf_infiniband_packet_length = -1;
487 static int hf_infiniband_source_local_id = -1;
488 /* Global Route Header (GRH) */
489 static int hf_infiniband_GRH = -1;
490 static int hf_infiniband_ip_version = -1;
491 static int hf_infiniband_traffic_class = -1;
492 static int hf_infiniband_flow_label = -1;
493 static int hf_infiniband_payload_length = -1;
494 static int hf_infiniband_next_header = -1;
495 static int hf_infiniband_hop_limit = -1;
496 static int hf_infiniband_source_gid = -1;
497 static int hf_infiniband_destination_gid = -1;
498 /* Base Transport Header (BTH) */
499 static int hf_infiniband_BTH = -1;
500 static int hf_infiniband_opcode = -1;
501 static int hf_infiniband_solicited_event = -1;
502 static int hf_infiniband_migreq = -1;
503 static int hf_infiniband_pad_count = -1;
504 static int hf_infiniband_transport_header_version = -1;
505 static int hf_infiniband_partition_key = -1;
506 static int hf_infiniband_reserved8 = -1;
507 static int hf_infiniband_destination_qp = -1;
508 static int hf_infiniband_acknowledge_request = -1;
509 static int hf_infiniband_reserved7 = -1;
510 static int hf_infiniband_packet_sequence_number = -1;
511 /* Raw Header (RWH) */
512 static int hf_infiniband_RWH = -1;
513 static int hf_infiniband_reserved16_RWH = -1;
514 static int hf_infiniband_etype = -1;
515 /* Reliable Datagram Extended Transport Header (RDETH) */
516 static int hf_infiniband_RDETH = -1;
517 static int hf_infiniband_reserved8_RDETH = -1;
518 static int hf_infiniband_ee_context = -1;
519 /* Datagram Extended Transport Header (DETH) */
520 static int hf_infiniband_DETH = -1;
521 static int hf_infiniband_queue_key = -1;
522 static int hf_infiniband_reserved8_DETH = -1;
523 static int hf_infiniband_source_qp = -1;
524 /* RDMA Extended Transport Header (RETH) */
525 static int hf_infiniband_RETH = -1;
526 static int hf_infiniband_virtual_address = -1;
527 static int hf_infiniband_remote_key = -1;
528 static int hf_infiniband_dma_length = -1;
529 /* Atomic Extended Transport Header (AtomicETH) */
530 static int hf_infiniband_AtomicETH = -1;
531 /* static int hf_infiniband_virtual_address_AtomicETH = -1;                  */
532 /* static int hf_infiniband_remote_key_AtomicETH = -1;                       */
533 static int hf_infiniband_swap_or_add_data = -1;
534 static int hf_infiniband_compare_data = -1;
535 /* ACK Extended Transport Header (AETH) */
536 static int hf_infiniband_AETH = -1;
537 static int hf_infiniband_syndrome = -1;
538 static int hf_infiniband_message_sequence_number = -1;
539 /* Atomic ACK Extended Transport Header (AtomicAckETH) */
540 static int hf_infiniband_AtomicAckETH = -1;
541 static int hf_infiniband_original_remote_data = -1;
542 /* Immediate Extended Transport Header (ImmDt) */
543 static int hf_infiniband_IMMDT = -1;
544 /* Invalidate Extended Transport Header (IETH) */
545 static int hf_infiniband_IETH = -1;
546 /* Payload */
547 static int hf_infiniband_payload = -1;
548 static int hf_infiniband_invariant_crc = -1;
549 static int hf_infiniband_variant_crc = -1;
550 /* Unknown or Vendor Specific */
551 static int hf_infiniband_raw_data = -1;
552 static int hf_infiniband_vendor = -1;
553 /* CM REQ Header */
554 static int hf_cm_req_local_comm_id = -1;
555 static int hf_cm_req_service_id = -1;
556 static int hf_cm_req_local_ca_guid = -1;
557 static int hf_cm_req_local_qkey = -1;
558 static int hf_cm_req_local_qpn = -1;
559 static int hf_cm_req_respo_res = -1;
560 static int hf_cm_req_local_eecn = -1;
561 static int hf_cm_req_init_depth = -1;
562 static int hf_cm_req_remote_eecn = -1;
563 static int hf_cm_req_remote_cm_resp_to = -1;
564 static int hf_cm_req_transp_serv_type = -1;
565 static int hf_cm_req_e2e_flow_ctrl = -1;
566 static int hf_cm_req_start_psn = -1;
567 static int hf_cm_req_local_cm_resp_to = -1;
568 static int hf_cm_req_retry_count = -1;
569 static int hf_cm_req_pkey = -1;
570 static int hf_cm_req_path_pp_mtu = -1;
571 static int hf_cm_req_rdc_exists = -1;
572 static int hf_cm_req_rnr_retry_count = -1;
573 static int hf_cm_req_max_cm_retries = -1;
574 static int hf_cm_req_srq = -1;
575 static int hf_cm_req_primary_local_lid = -1;
576 static int hf_cm_req_primary_remote_lid = -1;
577 static int hf_cm_req_primary_local_gid = -1;
578 static int hf_cm_req_primary_remote_gid = -1;
579 static int hf_cm_req_primary_flow_label = -1;
580 static int hf_cm_req_primary_packet_rate = -1;
581 static int hf_cm_req_primary_traffic_class = -1;
582 static int hf_cm_req_primary_hop_limit = -1;
583 static int hf_cm_req_primary_sl = -1;
584 static int hf_cm_req_primary_subnet_local = -1;
585 static int hf_cm_req_primary_local_ack_to = -1;
586 static int hf_cm_req_alt_local_lid = -1;
587 static int hf_cm_req_alt_remote_lid = -1;
588 static int hf_cm_req_alt_local_gid = -1;
589 static int hf_cm_req_alt_remote_gid = -1;
590 static int hf_cm_req_flow_label = -1;
591 static int hf_cm_req_packet_rate = -1;
592 static int hf_cm_req_alt_traffic_class = -1;
593 static int hf_cm_req_alt_hop_limit = -1;
594 static int hf_cm_req_SL = -1;
595 static int hf_cm_req_subnet_local = -1;
596 static int hf_cm_req_local_ACK_timeout = -1;
597 static int hf_cm_req_private_data = -1;
598 /* CM REP Header */
599 static int hf_cm_rep_localcommid = -1;
600 static int hf_cm_rep_remotecommid = -1;
601 static int hf_cm_rep_localqkey = -1;
602 static int hf_cm_rep_localqpn = -1;
603 static int hf_cm_rep_localeecontnum = -1;
604 static int hf_cm_rep_startingpsn = -1;
605 static int hf_cm_rep_responderres = -1;
606 static int hf_cm_rep_initiatordepth = -1;
607 static int hf_cm_rep_tgtackdelay = -1;
608 static int hf_cm_rep_failoveracc = -1;
609 static int hf_cm_rep_e2eflowctl = -1;
610 static int hf_cm_rep_rnrretrycount = -1;
611 static int hf_cm_rep_srq = -1;
612 static int hf_cm_rep_localcaguid = -1;
613 static int hf_cm_rep_privatedata = -1;
614 /* CM RTU Header */
615 static int hf_cm_rtu_localcommid = -1;
616 static int hf_cm_rtu_remotecommid = -1;
617 static int hf_cm_rtu_privatedata = -1;
618 /* CM REJ Header */
619 static int hf_cm_rej_local_commid = -1;
620 static int hf_cm_rej_remote_commid = -1;
621 static int hf_cm_rej_msg_rej = -1;
622 static int hf_cm_rej_rej_info_len = -1;
623 static int hf_cm_rej_reason = -1;
624 static int hf_cm_rej_add_rej_info = -1;
625 static int hf_cm_rej_private_data = -1;
626 /* MAD Base Header */
627 static int hf_infiniband_MAD = -1;
628 static int hf_infiniband_base_version = -1;
629 static int hf_infiniband_mgmt_class = -1;
630 static int hf_infiniband_class_version = -1;
631 /* static int hf_infiniband_reserved1 = -1;                                  */
632 static int hf_infiniband_method = -1;
633 static int hf_infiniband_status = -1;
634 static int hf_infiniband_class_specific = -1;
635 static int hf_infiniband_transaction_id = -1;
636 static int hf_infiniband_attribute_id = -1;
637 static int hf_infiniband_reserved16 = -1;
638 static int hf_infiniband_attribute_modifier = -1;
639 static int hf_infiniband_data = -1;
640 /* RMPP Header */
641 static int hf_infiniband_RMPP = -1;
642 static int hf_infiniband_rmpp_version = -1;
643 static int hf_infiniband_rmpp_type = -1;
644 static int hf_infiniband_r_resp_time = -1;
645 static int hf_infiniband_rmpp_flags = -1;
646 static int hf_infiniband_rmpp_status = -1;
647 static int hf_infiniband_rmpp_data1 = -1;
648 static int hf_infiniband_rmpp_data2 = -1;
649 /* RMPP Data */
650 /* static int hf_infiniband_RMPP_DATA = -1;                                  */
651 static int hf_infiniband_segment_number = -1;
652 static int hf_infiniband_payload_length32 = -1;
653 static int hf_infiniband_transferred_data = -1;
654 /* RMPP ACK */
655 static int hf_infiniband_new_window_last = -1;
656 static int hf_infiniband_reserved220 = -1;
657 /* RMPP ABORT and STOP */
658 static int hf_infiniband_reserved32 = -1;
659 static int hf_infiniband_optional_extended_error_data = -1;
660 /* SMP Data LID Routed */
661 static int hf_infiniband_SMP_LID = -1;
662 static int hf_infiniband_m_key = -1;
663 static int hf_infiniband_smp_data = -1;
664 static int hf_infiniband_reserved1024 = -1;
665 static int hf_infiniband_reserved256 = -1;
666 /* SMP Data Directed Route */
667 static int hf_infiniband_SMP_DIRECTED = -1;
668 static int hf_infiniband_smp_status = -1;
669 static int hf_infiniband_hop_pointer = -1;
670 static int hf_infiniband_hop_count = -1;
671 static int hf_infiniband_dr_slid = -1;
672 static int hf_infiniband_dr_dlid = -1;
673 static int hf_infiniband_reserved28 = -1;
674 static int hf_infiniband_d = -1;
675 static int hf_infiniband_initial_path = -1;
676 static int hf_infiniband_return_path = -1;
677 /* SA MAD Header */
678 static int hf_infiniband_SA = -1;
679 static int hf_infiniband_sm_key = -1;
680 static int hf_infiniband_attribute_offset = -1;
681 static int hf_infiniband_component_mask = -1;
682 static int hf_infiniband_subnet_admin_data = -1;
683 /* Mellanox EoIB encapsulation header */
684 static int hf_infiniband_EOIB = -1;
685 static int hf_infiniband_ver = -1;
686 static int hf_infiniband_tcp_chk = -1;
687 static int hf_infiniband_ip_chk = -1;
688 static int hf_infiniband_fcs = -1;
689 static int hf_infiniband_ms = -1;
690 static int hf_infiniband_seg_off = -1;
691 static int hf_infiniband_seg_id = -1;
692
693 /* Attributes
694 * Additional Structures for individuala attribute decoding.
695 * Since they are not headers the naming convention is slightly modified
696 * Convention: hf_infiniband_[attribute name]_[field]
697 * This was not entirely necessary but I felt the previous convention
698 * did not provide adequate readability for the granularity of attribute/attribute fields. */
699
700 /* NodeDescription */
701 static int hf_infiniband_NodeDescription_NodeString = -1;
702 /* NodeInfo */
703 static int hf_infiniband_NodeInfo_BaseVersion = -1;
704 static int hf_infiniband_NodeInfo_ClassVersion = -1;
705 static int hf_infiniband_NodeInfo_NodeType = -1;
706 static int hf_infiniband_NodeInfo_NumPorts = -1;
707 static int hf_infiniband_NodeInfo_SystemImageGUID = -1;
708 static int hf_infiniband_NodeInfo_NodeGUID = -1;
709 static int hf_infiniband_NodeInfo_PortGUID = -1;
710 static int hf_infiniband_NodeInfo_PartitionCap = -1;
711 static int hf_infiniband_NodeInfo_DeviceID = -1;
712 static int hf_infiniband_NodeInfo_Revision = -1;
713 static int hf_infiniband_NodeInfo_LocalPortNum = -1;
714 static int hf_infiniband_NodeInfo_VendorID = -1;
715 /* SwitchInfo */
716 static int hf_infiniband_SwitchInfo_LinearFDBCap = -1;
717 static int hf_infiniband_SwitchInfo_RandomFDBCap = -1;
718 static int hf_infiniband_SwitchInfo_MulticastFDBCap = -1;
719 static int hf_infiniband_SwitchInfo_LinearFDBTop = -1;
720 static int hf_infiniband_SwitchInfo_DefaultPort = -1;
721 static int hf_infiniband_SwitchInfo_DefaultMulticastPrimaryPort = -1;
722 static int hf_infiniband_SwitchInfo_DefaultMulticastNotPrimaryPort = -1;
723 static int hf_infiniband_SwitchInfo_LifeTimeValue = -1;
724 static int hf_infiniband_SwitchInfo_PortStateChange = -1;
725 static int hf_infiniband_SwitchInfo_OptimizedSLtoVLMappingProgramming = -1;
726 static int hf_infiniband_SwitchInfo_LIDsPerPort = -1;
727 static int hf_infiniband_SwitchInfo_PartitionEnforcementCap = -1;
728 static int hf_infiniband_SwitchInfo_InboundEnforcementCap = -1;
729 static int hf_infiniband_SwitchInfo_OutboundEnforcementCap = -1;
730 static int hf_infiniband_SwitchInfo_FilterRawInboundCap = -1;
731 static int hf_infiniband_SwitchInfo_FilterRawOutboundCap = -1;
732 static int hf_infiniband_SwitchInfo_EnhancedPortZero = -1;
733 /* GUIDInfo */
734 /* static int hf_infiniband_GUIDInfo_GUIDBlock = -1;                         */
735 static int hf_infiniband_GUIDInfo_GUID = -1;
736 /* PortInfo */
737 static int hf_infiniband_PortInfo_GidPrefix = -1;
738 static int hf_infiniband_PortInfo_LID = -1;
739 static int hf_infiniband_PortInfo_MasterSMLID = -1;
740 static int hf_infiniband_PortInfo_CapabilityMask = -1;
741
742 /* Capability Mask Flags */
743 static int hf_infiniband_PortInfo_CapabilityMask_SM = -1;
744 static int hf_infiniband_PortInfo_CapabilityMask_NoticeSupported = -1;
745 static int hf_infiniband_PortInfo_CapabilityMask_TrapSupported = -1;
746 static int hf_infiniband_PortInfo_CapabilityMask_OptionalPDSupported = -1;
747 static int hf_infiniband_PortInfo_CapabilityMask_AutomaticMigrationSupported = -1;
748 static int hf_infiniband_PortInfo_CapabilityMask_SLMappingSupported = -1;
749 static int hf_infiniband_PortInfo_CapabilityMask_MKeyNVRAM = -1;
750 static int hf_infiniband_PortInfo_CapabilityMask_PKeyNVRAM = -1;
751 static int hf_infiniband_PortInfo_CapabilityMask_LEDInfoSupported = -1;
752 static int hf_infiniband_PortInfo_CapabilityMask_SMdisabled = -1;
753 static int hf_infiniband_PortInfo_CapabilityMask_SystemImageGUIDSupported = -1;
754 static int hf_infiniband_PortInfo_CapabilityMask_PKeySwitchExternalPortTrapSupported = -1;
755 static int hf_infiniband_PortInfo_CapabilityMask_CommunicationsManagementSupported = -1;
756 static int hf_infiniband_PortInfo_CapabilityMask_SNMPTunnelingSupported = -1;
757 static int hf_infiniband_PortInfo_CapabilityMask_ReinitSupported = -1;
758 static int hf_infiniband_PortInfo_CapabilityMask_DeviceManagementSupported = -1;
759 static int hf_infiniband_PortInfo_CapabilityMask_VendorClassSupported = -1;
760 static int hf_infiniband_PortInfo_CapabilityMask_DRNoticeSupported = -1;
761 static int hf_infiniband_PortInfo_CapabilityMask_CapabilityMaskNoticeSupported = -1;
762 static int hf_infiniband_PortInfo_CapabilityMask_BootManagementSupported = -1;
763 static int hf_infiniband_PortInfo_CapabilityMask_LinkRoundTripLatencySupported = -1;
764 static int hf_infiniband_PortInfo_CapabilityMask_ClientRegistrationSupported = -1;
765 static int hf_infiniband_PortInfo_CapabilityMask_OtherLocalChangesNoticeSupported = -1;
766 static int hf_infiniband_PortInfo_CapabilityMask_LinkSpeedWIdthPairsTableSupported = -1;
767 /* End Capability Mask Flags */
768
769
770 static int hf_infiniband_PortInfo_DiagCode = -1;
771 static int hf_infiniband_PortInfo_M_KeyLeasePeriod = -1;
772 static int hf_infiniband_PortInfo_LocalPortNum = -1;
773 static int hf_infiniband_PortInfo_LinkWidthEnabled = -1;
774 static int hf_infiniband_PortInfo_LinkWidthSupported = -1;
775 static int hf_infiniband_PortInfo_LinkWidthActive = -1;
776 static int hf_infiniband_PortInfo_LinkSpeedSupported = -1;
777 static int hf_infiniband_PortInfo_PortState = -1;
778 static int hf_infiniband_PortInfo_PortPhysicalState = -1;
779 static int hf_infiniband_PortInfo_LinkDownDefaultState = -1;
780 static int hf_infiniband_PortInfo_M_KeyProtectBits = -1;
781 static int hf_infiniband_PortInfo_LMC = -1;
782 static int hf_infiniband_PortInfo_LinkSpeedActive = -1;
783 static int hf_infiniband_PortInfo_LinkSpeedEnabled = -1;
784 static int hf_infiniband_PortInfo_NeighborMTU = -1;
785 static int hf_infiniband_PortInfo_MasterSMSL = -1;
786 static int hf_infiniband_PortInfo_VLCap = -1;
787 static int hf_infiniband_PortInfo_M_Key = -1;
788 static int hf_infiniband_PortInfo_InitType = -1;
789 static int hf_infiniband_PortInfo_VLHighLimit = -1;
790 static int hf_infiniband_PortInfo_VLArbitrationHighCap = -1;
791 static int hf_infiniband_PortInfo_VLArbitrationLowCap = -1;
792 static int hf_infiniband_PortInfo_InitTypeReply = -1;
793 static int hf_infiniband_PortInfo_MTUCap = -1;
794 static int hf_infiniband_PortInfo_VLStallCount = -1;
795 static int hf_infiniband_PortInfo_HOQLife = -1;
796 static int hf_infiniband_PortInfo_OperationalVLs = -1;
797 static int hf_infiniband_PortInfo_PartitionEnforcementInbound = -1;
798 static int hf_infiniband_PortInfo_PartitionEnforcementOutbound = -1;
799 static int hf_infiniband_PortInfo_FilterRawInbound = -1;
800 static int hf_infiniband_PortInfo_FilterRawOutbound = -1;
801 static int hf_infiniband_PortInfo_M_KeyViolations = -1;
802 static int hf_infiniband_PortInfo_P_KeyViolations = -1;
803 static int hf_infiniband_PortInfo_Q_KeyViolations = -1;
804 static int hf_infiniband_PortInfo_GUIDCap = -1;
805 static int hf_infiniband_PortInfo_ClientReregister = -1;
806 static int hf_infiniband_PortInfo_SubnetTimeOut = -1;
807 static int hf_infiniband_PortInfo_RespTimeValue = -1;
808 static int hf_infiniband_PortInfo_LocalPhyErrors = -1;
809 static int hf_infiniband_PortInfo_OverrunErrors = -1;
810 static int hf_infiniband_PortInfo_MaxCreditHint = -1;
811 static int hf_infiniband_PortInfo_LinkRoundTripLatency = -1;
812
813 /* P_KeyTable */
814 static int hf_infiniband_P_KeyTable_P_KeyTableBlock = -1;
815 static int hf_infiniband_P_KeyTable_MembershipType = -1;
816 static int hf_infiniband_P_KeyTable_P_KeyBase = -1;
817
818 /* SLtoVLMappingTable */
819 static int hf_infiniband_SLtoVLMappingTable_SLtoVL_HighBits = -1;
820 static int hf_infiniband_SLtoVLMappingTable_SLtoVL_LowBits = -1;
821
822 /* VLArbitrationTable */
823 /* static int hf_infiniband_VLArbitrationTable_VLWeightPairs = -1;           */
824 static int hf_infiniband_VLArbitrationTable_VL = -1;
825 static int hf_infiniband_VLArbitrationTable_Weight = -1;
826
827 /* LinearForwardingTable */
828 /* static int hf_infiniband_LinearForwardingTable_LinearForwardingTableBlock = -1;  */
829 static int hf_infiniband_LinearForwardingTable_Port = -1;
830
831 /* RandomForwardingTable */
832 /* static int hf_infiniband_RandomForwardingTable_RandomForwardingTableBlock = -1;  */
833 static int hf_infiniband_RandomForwardingTable_LID = -1;
834 static int hf_infiniband_RandomForwardingTable_Valid = -1;
835 static int hf_infiniband_RandomForwardingTable_LMC = -1;
836 static int hf_infiniband_RandomForwardingTable_Port = -1;
837
838 /* MulticastForwardingTable */
839 /* static int hf_infiniband_MulticastForwardingTable_MulticastForwardingTableBlock = -1;    */
840 static int hf_infiniband_MulticastForwardingTable_PortMask = -1;
841
842 /* SMInfo */
843 static int hf_infiniband_SMInfo_GUID = -1;
844 static int hf_infiniband_SMInfo_SM_Key = -1;
845 static int hf_infiniband_SMInfo_ActCount = -1;
846 static int hf_infiniband_SMInfo_Priority = -1;
847 static int hf_infiniband_SMInfo_SMState = -1;
848
849 /* VendorDiag */
850 static int hf_infiniband_VendorDiag_NextIndex = -1;
851 static int hf_infiniband_VendorDiag_DiagData = -1;
852
853 /* LedInfo */
854 static int hf_infiniband_LedInfo_LedMask = -1;
855
856 /* LinkSpeedWidthPairsTable */
857 static int hf_infiniband_LinkSpeedWidthPairsTable_NumTables = -1;
858 static int hf_infiniband_LinkSpeedWidthPairsTable_PortMask = -1;
859 static int hf_infiniband_LinkSpeedWidthPairsTable_SpeedTwoFive = -1;
860 static int hf_infiniband_LinkSpeedWidthPairsTable_SpeedFive = -1;
861 static int hf_infiniband_LinkSpeedWidthPairsTable_SpeedTen = -1;
862
863 /* Attributes for Subnet Administration.
864 * Mostly we have "Records" here which are just structures of SM attributes.
865 * There are some unique attributes though that we will want to have a structure for. */
866
867 /* NodeRecord */
868 /* PortInfoRecord */
869 /* SLtoVLMappingTableRecord */
870 /* SwitchInfoRecord */
871 /* LinearForwardingTableRecord */
872 /* RandomForwardingTableRecord */
873 /* MulticastForwardingTableRecord */
874 /* VLArbitrationTableRecord */
875
876 static int hf_infiniband_SA_LID = -1;
877 static int hf_infiniband_SA_EndportLID = -1;
878 static int hf_infiniband_SA_PortNum = -1;
879 static int hf_infiniband_SA_InputPortNum = -1;
880 static int hf_infiniband_SA_OutputPortNum = -1;
881 static int hf_infiniband_SA_BlockNum_EightBit = -1;
882 static int hf_infiniband_SA_BlockNum_NineBit = -1;
883 static int hf_infiniband_SA_BlockNum_SixteenBit = -1;
884 static int hf_infiniband_SA_Position = -1;
885 /* static int hf_infiniband_SA_Index = -1;                                   */
886
887 /* InformInfoRecord */
888 static int hf_infiniband_InformInfoRecord_SubscriberGID = -1;
889 static int hf_infiniband_InformInfoRecord_Enum = -1;
890
891 /* InformInfo */
892 static int hf_infiniband_InformInfo_GID = -1;
893 static int hf_infiniband_InformInfo_LIDRangeBegin = -1;
894 static int hf_infiniband_InformInfo_LIDRangeEnd = -1;
895 static int hf_infiniband_InformInfo_IsGeneric = -1;
896 static int hf_infiniband_InformInfo_Subscribe = -1;
897 static int hf_infiniband_InformInfo_Type = -1;
898 static int hf_infiniband_InformInfo_TrapNumberDeviceID = -1;
899 static int hf_infiniband_InformInfo_QPN = -1;
900 static int hf_infiniband_InformInfo_RespTimeValue = -1;
901 static int hf_infiniband_InformInfo_ProducerTypeVendorID = -1;
902
903 /* LinkRecord */
904 static int hf_infiniband_LinkRecord_FromLID = -1;
905 static int hf_infiniband_LinkRecord_FromPort = -1;
906 static int hf_infiniband_LinkRecord_ToPort = -1;
907 static int hf_infiniband_LinkRecord_ToLID = -1;
908
909 /* ServiceRecord */
910 static int hf_infiniband_ServiceRecord_ServiceID = -1;
911 static int hf_infiniband_ServiceRecord_ServiceGID = -1;
912 static int hf_infiniband_ServiceRecord_ServiceP_Key = -1;
913 static int hf_infiniband_ServiceRecord_ServiceLease = -1;
914 static int hf_infiniband_ServiceRecord_ServiceKey = -1;
915 static int hf_infiniband_ServiceRecord_ServiceName = -1;
916 static int hf_infiniband_ServiceRecord_ServiceData = -1;
917
918 /* ServiceAssociationRecord */
919 static int hf_infiniband_ServiceAssociationRecord_ServiceKey = -1;
920 static int hf_infiniband_ServiceAssociationRecord_ServiceName = -1;
921
922 /* PathRecord */
923 static int hf_infiniband_PathRecord_DGID = -1;
924 static int hf_infiniband_PathRecord_SGID = -1;
925 static int hf_infiniband_PathRecord_DLID = -1;
926 static int hf_infiniband_PathRecord_SLID = -1;
927 static int hf_infiniband_PathRecord_RawTraffic = -1;
928 static int hf_infiniband_PathRecord_FlowLabel = -1;
929 static int hf_infiniband_PathRecord_HopLimit = -1;
930 static int hf_infiniband_PathRecord_TClass = -1;
931 static int hf_infiniband_PathRecord_Reversible = -1;
932 static int hf_infiniband_PathRecord_NumbPath = -1;
933 static int hf_infiniband_PathRecord_P_Key = -1;
934 static int hf_infiniband_PathRecord_SL = -1;
935 static int hf_infiniband_PathRecord_MTUSelector = -1;
936 static int hf_infiniband_PathRecord_MTU = -1;
937 static int hf_infiniband_PathRecord_RateSelector = -1;
938 static int hf_infiniband_PathRecord_Rate = -1;
939 static int hf_infiniband_PathRecord_PacketLifeTimeSelector = -1;
940 static int hf_infiniband_PathRecord_PacketLifeTime = -1;
941 static int hf_infiniband_PathRecord_Preference = -1;
942
943 /* MCMemberRecord */
944 static int hf_infiniband_MCMemberRecord_MGID = -1;
945 static int hf_infiniband_MCMemberRecord_PortGID = -1;
946 static int hf_infiniband_MCMemberRecord_Q_Key = -1;
947 static int hf_infiniband_MCMemberRecord_MLID = -1;
948 static int hf_infiniband_MCMemberRecord_MTUSelector = -1;
949 static int hf_infiniband_MCMemberRecord_MTU = -1;
950 static int hf_infiniband_MCMemberRecord_TClass = -1;
951 static int hf_infiniband_MCMemberRecord_P_Key = -1;
952 static int hf_infiniband_MCMemberRecord_RateSelector = -1;
953 static int hf_infiniband_MCMemberRecord_Rate = -1;
954 static int hf_infiniband_MCMemberRecord_PacketLifeTimeSelector = -1;
955 static int hf_infiniband_MCMemberRecord_PacketLifeTime = -1;
956 static int hf_infiniband_MCMemberRecord_SL = -1;
957 static int hf_infiniband_MCMemberRecord_FlowLabel = -1;
958 static int hf_infiniband_MCMemberRecord_HopLimit = -1;
959 static int hf_infiniband_MCMemberRecord_Scope = -1;
960 static int hf_infiniband_MCMemberRecord_JoinState = -1;
961 static int hf_infiniband_MCMemberRecord_ProxyJoin = -1;
962
963 /* TraceRecord */
964 static int hf_infiniband_TraceRecord_GIDPrefix = -1;
965 static int hf_infiniband_TraceRecord_IDGeneration = -1;
966 static int hf_infiniband_TraceRecord_NodeType = -1;
967 static int hf_infiniband_TraceRecord_NodeID = -1;
968 static int hf_infiniband_TraceRecord_ChassisID = -1;
969 static int hf_infiniband_TraceRecord_EntryPortID = -1;
970 static int hf_infiniband_TraceRecord_ExitPortID = -1;
971 static int hf_infiniband_TraceRecord_EntryPort = -1;
972 static int hf_infiniband_TraceRecord_ExitPort = -1;
973
974 /* MultiPathRecord */
975 static int hf_infiniband_MultiPathRecord_RawTraffic = -1;
976 static int hf_infiniband_MultiPathRecord_FlowLabel = -1;
977 static int hf_infiniband_MultiPathRecord_HopLimit = -1;
978 static int hf_infiniband_MultiPathRecord_TClass = -1;
979 static int hf_infiniband_MultiPathRecord_Reversible = -1;
980 static int hf_infiniband_MultiPathRecord_NumbPath = -1;
981 static int hf_infiniband_MultiPathRecord_P_Key = -1;
982 static int hf_infiniband_MultiPathRecord_SL = -1;
983 static int hf_infiniband_MultiPathRecord_MTUSelector = -1;
984 static int hf_infiniband_MultiPathRecord_MTU = -1;
985 static int hf_infiniband_MultiPathRecord_RateSelector = -1;
986 static int hf_infiniband_MultiPathRecord_Rate = -1;
987 static int hf_infiniband_MultiPathRecord_PacketLifeTimeSelector = -1;
988 static int hf_infiniband_MultiPathRecord_PacketLifeTime = -1;
989 static int hf_infiniband_MultiPathRecord_IndependenceSelector = -1;
990 static int hf_infiniband_MultiPathRecord_GIDScope = -1;
991 static int hf_infiniband_MultiPathRecord_SGIDCount = -1;
992 static int hf_infiniband_MultiPathRecord_DGIDCount = -1;
993 static int hf_infiniband_MultiPathRecord_SDGID = -1;
994
995 /* Notice */
996 static int hf_infiniband_Notice_IsGeneric = -1;
997 static int hf_infiniband_Notice_Type = -1;
998 static int hf_infiniband_Notice_ProducerTypeVendorID = -1;
999 static int hf_infiniband_Notice_TrapNumberDeviceID = -1;
1000 static int hf_infiniband_Notice_IssuerLID = -1;
1001 static int hf_infiniband_Notice_NoticeToggle = -1;
1002 static int hf_infiniband_Notice_NoticeCount = -1;
1003 static int hf_infiniband_Notice_DataDetails = -1;
1004 /* static int hf_infiniband_Notice_IssuerGID = -1;             */
1005 /* static int hf_infiniband_Notice_ClassTrapSpecificData = -1; */
1006
1007 /* PortCounters attribute in Performance class */
1008 static int hf_infiniband_PortCounters = -1;
1009 static int hf_infiniband_PortCounters_PortSelect = -1;
1010 static int hf_infiniband_PortCounters_CounterSelect = -1;
1011 static int hf_infiniband_PortCounters_SymbolErrorCounter = -1;
1012 static int hf_infiniband_PortCounters_LinkErrorRecoveryCounter = -1;
1013 static int hf_infiniband_PortCounters_LinkDownedCounter = -1;
1014 static int hf_infiniband_PortCounters_PortRcvErrors = -1;
1015 static int hf_infiniband_PortCounters_PortRcvRemotePhysicalErrors = -1;
1016 static int hf_infiniband_PortCounters_PortRcvSwitchRelayErrors = -1;
1017 static int hf_infiniband_PortCounters_PortXmitDiscards = -1;
1018 static int hf_infiniband_PortCounters_PortXmitConstraintErrors = -1;
1019 static int hf_infiniband_PortCounters_PortRcvConstraintErrors = -1;
1020 static int hf_infiniband_PortCounters_LocalLinkIntegrityErrors = -1;
1021 static int hf_infiniband_PortCounters_ExcessiveBufferOverrunErrors = -1;
1022 static int hf_infiniband_PortCounters_VL15Dropped = -1;
1023 static int hf_infiniband_PortCounters_PortXmitData = -1;
1024 static int hf_infiniband_PortCounters_PortRcvData = -1;
1025 static int hf_infiniband_PortCounters_PortXmitPkts = -1;
1026 static int hf_infiniband_PortCounters_PortRcvPkts = -1;
1027
1028 /* Extended PortCounters attribute in Performance class */
1029 static int hf_infiniband_PortCountersExt = -1;
1030 static int hf_infiniband_PortCountersExt_PortSelect = -1;
1031 static int hf_infiniband_PortCountersExt_CounterSelect = -1;
1032 static int hf_infiniband_PortCountersExt_PortXmitData = -1;
1033 static int hf_infiniband_PortCountersExt_PortRcvData = -1;
1034 static int hf_infiniband_PortCountersExt_PortXmitPkts = -1;
1035 static int hf_infiniband_PortCountersExt_PortRcvPkts = -1;
1036 static int hf_infiniband_PortCountersExt_PortUnicastXmitPkts = -1;
1037 static int hf_infiniband_PortCountersExt_PortUnicastRcvPkts = -1;
1038 static int hf_infiniband_PortCountersExt_PortMulticastXmitPkts = -1;
1039 static int hf_infiniband_PortCountersExt_PortMulticastRcvPkts = -1;
1040
1041 /* Notice DataDetails and ClassTrapSpecific Data for certain traps
1042 * Note that traps reuse many fields, so they are only declared once under the first trap that they appear.
1043 * There is no need to redeclare them for specific Traps (as with other SA Attributes) because they are uniform between Traps. */
1044
1045 /* Parse DataDetails for a given Trap */
1046 static void parse_NoticeDataDetails(proto_tree*, tvbuff_t*, gint *offset, guint16 trapNumber);
1047
1048 /* Traps 64,65,66,67 */
1049 static int hf_infiniband_Trap_GIDADDR = -1;
1050
1051 /* Traps 68,69 */
1052 /* DataDetails */
1053 static int hf_infiniband_Trap_COMP_MASK = -1;
1054 static int hf_infiniband_Trap_WAIT_FOR_REPATH = -1;
1055 /* ClassTrapSpecificData */
1056 /* static int hf_infiniband_Trap_PATH_REC = -1;                              */
1057
1058 /* Trap 128 */
1059 static int hf_infiniband_Trap_LIDADDR = -1;
1060
1061 /* Trap 129, 130, 131 */
1062 static int hf_infiniband_Trap_PORTNO = -1;
1063
1064 /* Trap 144 */
1065 static int hf_infiniband_Trap_OtherLocalChanges = -1;
1066 static int hf_infiniband_Trap_CAPABILITYMASK = -1;
1067 static int hf_infiniband_Trap_LinkSpeecEnabledChange = -1;
1068 static int hf_infiniband_Trap_LinkWidthEnabledChange = -1;
1069 static int hf_infiniband_Trap_NodeDescriptionChange = -1;
1070
1071 /* Trap 145 */
1072 static int hf_infiniband_Trap_SYSTEMIMAGEGUID = -1;
1073
1074 /* Trap 256 */
1075 static int hf_infiniband_Trap_DRSLID = -1;
1076 static int hf_infiniband_Trap_METHOD = -1;
1077 static int hf_infiniband_Trap_ATTRIBUTEID = -1;
1078 static int hf_infiniband_Trap_ATTRIBUTEMODIFIER = -1;
1079 static int hf_infiniband_Trap_MKEY = -1;
1080 static int hf_infiniband_Trap_DRNotice = -1;
1081 static int hf_infiniband_Trap_DRPathTruncated = -1;
1082 static int hf_infiniband_Trap_DRHopCount = -1;
1083 static int hf_infiniband_Trap_DRNoticeReturnPath = -1;
1084
1085 /* Trap 257, 258 */
1086 static int hf_infiniband_Trap_LIDADDR1 = -1;
1087 static int hf_infiniband_Trap_LIDADDR2 = -1;
1088 static int hf_infiniband_Trap_KEY = -1;
1089 static int hf_infiniband_Trap_SL = -1;
1090 static int hf_infiniband_Trap_QP1 = -1;
1091 static int hf_infiniband_Trap_QP2 = -1;
1092 static int hf_infiniband_Trap_GIDADDR1 = -1;
1093 static int hf_infiniband_Trap_GIDADDR2 = -1;
1094
1095 /* Trap 259 */
1096 static int hf_infiniband_Trap_DataValid = -1;
1097 static int hf_infiniband_Trap_PKEY = -1;
1098 static int hf_infiniband_Trap_SWLIDADDR = -1;
1099
1100 /* Infiniband Link */
1101 static int hf_infiniband_link_op = -1;
1102 static int hf_infiniband_link_fctbs = -1;
1103 static int hf_infiniband_link_vl = -1;
1104 static int hf_infiniband_link_fccl = -1;
1105 static int hf_infiniband_link_lpcrc = -1;
1106
1107 /* Trap Type/Descriptions for dissection */
1108 static const value_string Operand_Description[]= {
1109     { 0, " Normal Flow Control"},
1110     { 1, " Flow Control Init"},
1111     { 0, NULL}
1112 };
1113
1114 /* Trap Type/Descriptions for dissection */
1115 static const value_string Trap_Description[]= {
1116     { 64, " (Informational) <GIDADDR> is now in service"},
1117     { 65, " (Informational) <GIDADDR> is out of service"},
1118     { 66, " (Informational) New Multicast Group with multicast address <GIDADDR> is now created"},
1119     { 67, " (Informational) Multicast Group with multicast address <GIDADDR> is now deleted"},
1120     { 68, " (Informational) Paths indicated by <PATH_REC> and <COMP_MASK> are no longer valid"},
1121     { 69, " (Informational) Paths indicated by <PATH_REC> and <COMP_MASK> have been recomputed"},
1122     { 128, " (Urgent) Link State of at least one port of switch at <LIDADDR> has changed"},
1123     { 129, " (Urgent) Local Link Integrity threshold reached at <LIDADDR><PORTNO>"},
1124     { 130, " (Urgent) Excessive Buffer OVerrun threshold reached at <LIDADDR><PORTNO>"},
1125     { 131, " (Urgent) Flow Control Update watchdog timer expired at <LIDADDR><PORTNO>"},
1126     { 144, " (Informational) CapMask, NodeDesc, LinkWidthEnabled or LinkSpeedEnabled at <LIDADDR> has been modified"},
1127     { 145, " (Informational) SystemImageGUID at <LIDADDR> has been modified.  New value is <SYSTEMIMAGEGUID>"},
1128     { 256, " (Security) Bad M_Key, <M_KEY> from <LIDADDR> attempted <METHOD> with <ATTRIBUTEID> and <ATTRIBUTEMODIFIER>"},
1129     { 257, " (Security) Bad P_Key, <KEY> from <LIDADDR1><GIDADDR1><QP1> to <LIDADDR2><GIDADDR2><QP2> on <SL>"},
1130     { 258, " (Security) Bad Q_Key, <KEY> from <LIDADDR1><GIDADDR1><QP1> to <LIDADDR2><GIDADDR2><QP2> on <SL>"},
1131     { 259, " (Security) Bad P_Key, <KEY> from <LIDADDR1><GIDADDR1><QP1> to <LIDADDR2><GIDADDR2><QP2> on <SL> at switch <LIDADDR><PORTNO>"},
1132     { 0, NULL}
1133 };
1134
1135
1136
1137
1138 /* MAD Management Classes
1139 * Classes from the Common MAD Header
1140 *
1141 *      Management Class Name        Class Description
1142 * ------------------------------------------------------------------------------------------------------------ */
1143 #define SUBN_LID_ROUTED 0x01        /* Subnet Management LID Route */
1144 #define SUBN_DIRECTED_ROUTE 0x81    /* Subnet Management Directed Route */
1145 #define SUBNADMN 0x03               /* Subnet Administration */
1146 #define PERF 0x04                   /* Performance Management */
1147 #define BM 0x05                     /* Baseboard Management (Tunneling of IB-ML commands through the IBA subnet) */
1148 #define DEV_MGT 0x06                /* Device Management */
1149 #define COM_MGT 0x07                /* Communications Management */
1150 #define SNMP 0x08                   /* SNMP Tunneling (tunneling of the SNMP protocol through the IBA fabric) */
1151 #define VENDOR_1_START 0x09         /* Start of first Vendor Specific Range */
1152 #define VENDOR_1_END 0x0F           /* End of first Vendor Specific Range */
1153 #define VENDOR_2_START 0x30         /* Start of second Vendor Specific Range */
1154 #define VENDOR_2_END 0x4F           /* End of the second Vendor Specific Range */
1155 #define APPLICATION_START 0x10      /* Start of Application Specific Range */
1156 #define APPLICATION_END 0x2F        /* End of Application Specific Range */
1157
1158 /* Performance class Attributes */
1159 #define ATTR_PORT_COUNTERS      0x0012
1160 #define ATTR_PORT_COUNTERS_EXT  0x001D
1161
1162 /* ComMgt class Attributes*/
1163 #define ATTR_CM_REQ             0x0010
1164 #define ATTR_CM_REP             0x0013
1165 #define ATTR_CM_RTU             0x0014
1166 #define ATTR_CM_REJ             0x0012
1167
1168 /* Link Next Header Values */
1169 #define IBA_GLOBAL 3
1170 #define IBA_LOCAL  2
1171 #define IP_NON_IBA 1
1172 #define RAW        0
1173
1174 /* OpCodeValues
1175 * Code Bits [7-5] Connection Type
1176 *           [4-0] Message Type
1177
1178 * Reliable Connection (RC)
1179 * [7-5] = 000 */
1180 #define RC_SEND_FIRST                   0 /*0x00000000 */
1181 #define RC_SEND_MIDDLE                  1 /*0x00000001 */
1182 #define RC_SEND_LAST                    2 /*0x00000010 */
1183 #define RC_SEND_LAST_IMM                3 /*0x00000011 */
1184 #define RC_SEND_ONLY                    4 /*0x00000100 */
1185 #define RC_SEND_ONLY_IMM                5 /*0x00000101 */
1186 #define RC_RDMA_WRITE_FIRST             6 /*0x00000110 */
1187 #define RC_RDMA_WRITE_MIDDLE            7 /*0x00000111 */
1188 #define RC_RDMA_WRITE_LAST              8 /*0x00001000 */
1189 #define RC_RDMA_WRITE_LAST_IMM          9 /*0x00001001 */
1190 #define RC_RDMA_WRITE_ONLY              10 /*0x00001010 */
1191 #define RC_RDMA_WRITE_ONLY_IMM          11 /*0x00001011 */
1192 #define RC_RDMA_READ_REQUEST            12 /*0x00001100 */
1193 #define RC_RDMA_READ_RESPONSE_FIRST     13 /*0x00001101 */
1194 #define RC_RDMA_READ_RESPONSE_MIDDLE    14 /*0x00001110 */
1195 #define RC_RDMA_READ_RESPONSE_LAST      15 /*0x00001111 */
1196 #define RC_RDMA_READ_RESPONSE_ONLY      16 /*0x00010000 */
1197 #define RC_ACKNOWLEDGE                  17 /*0x00010001 */
1198 #define RC_ATOMIC_ACKNOWLEDGE           18 /*0x00010010 */
1199 #define RC_CMP_SWAP                     19 /*0x00010011 */
1200 #define RC_FETCH_ADD                    20 /*0x00010100 */
1201 #define RC_SEND_LAST_INVAL              22 /*0x00010110 */
1202 #define RC_SEND_ONLY_INVAL              23 /*0x00010111 */
1203
1204 /* Reliable Datagram (RD)
1205 * [7-5] = 010 */
1206 #define RD_SEND_FIRST                   64 /*0x01000000 */
1207 #define RD_SEND_MIDDLE                  65 /*0x01000001 */
1208 #define RD_SEND_LAST                    66 /*0x01000010 */
1209 #define RD_SEND_LAST_IMM                67 /*0x01000011 */
1210 #define RD_SEND_ONLY                    68 /*0x01000100 */
1211 #define RD_SEND_ONLY_IMM                69 /*0x01000101 */
1212 #define RD_RDMA_WRITE_FIRST             70 /*0x01000110 */
1213 #define RD_RDMA_WRITE_MIDDLE            71 /*0x01000111 */
1214 #define RD_RDMA_WRITE_LAST              72 /*0x01001000 */
1215 #define RD_RDMA_WRITE_LAST_IMM          73 /*0x01001001 */
1216 #define RD_RDMA_WRITE_ONLY              74 /*0x01001010 */
1217 #define RD_RDMA_WRITE_ONLY_IMM          75 /*0x01001011 */
1218 #define RD_RDMA_READ_REQUEST            76 /*0x01001100 */
1219 #define RD_RDMA_READ_RESPONSE_FIRST     77 /*0x01001101 */
1220 #define RD_RDMA_READ_RESPONSE_MIDDLE    78 /*0x01001110 */
1221 #define RD_RDMA_READ_RESPONSE_LAST      79 /*0x01001111 */
1222 #define RD_RDMA_READ_RESPONSE_ONLY      80 /*0x01010000 */
1223 #define RD_ACKNOWLEDGE                  81 /*0x01010001 */
1224 #define RD_ATOMIC_ACKNOWLEDGE           82 /*0x01010010 */
1225 #define RD_CMP_SWAP                     83 /*0x01010011 */
1226 #define RD_FETCH_ADD                    84 /*0x01010100 */
1227 #define RD_RESYNC                       85 /*0x01010101 */
1228
1229 /* Unreliable Datagram (UD)
1230 * [7-5] = 011 */
1231 #define UD_SEND_ONLY                    100 /*0x01100100 */
1232 #define UD_SEND_ONLY_IMM                101 /*0x01100101 */
1233
1234 /* Unreliable Connection (UC)
1235 * [7-5] = 001 */
1236 #define UC_SEND_FIRST                   32 /*0x00100000 */
1237 #define UC_SEND_MIDDLE                  33 /*0x00100001 */
1238 #define UC_SEND_LAST                    34 /*0x00100010 */
1239 #define UC_SEND_LAST_IMM                35 /*0x00100011 */
1240 #define UC_SEND_ONLY                    36 /*0x00100100 */
1241 #define UC_SEND_ONLY_IMM                37 /*0x00100101 */
1242 #define UC_RDMA_WRITE_FIRST             38 /*0x00100110 */
1243 #define UC_RDMA_WRITE_MIDDLE            39 /*0x00100111 */
1244 #define UC_RDMA_WRITE_LAST              40 /*0x00101000 */
1245 #define UC_RDMA_WRITE_LAST_IMM          41 /*0x00101001 */
1246 #define UC_RDMA_WRITE_ONLY              42 /*0x00101010 */
1247 #define UC_RDMA_WRITE_ONLY_IMM          43 /*0x00101011 */
1248
1249 static const value_string OpCodeMap[] =
1250 {
1251     { RC_SEND_FIRST, "RC Send First " },
1252     { RC_SEND_MIDDLE, "RC Send Middle "},
1253     { RC_SEND_LAST, "RC Send Last " },
1254     { RC_SEND_LAST_IMM, "RC Send Last Immediate "},
1255     { RC_SEND_ONLY, "RC Send Only "},
1256     { RC_SEND_ONLY_IMM, "RC Send Only Immediate "},
1257     { RC_RDMA_WRITE_FIRST, "RC RDMA Write First " },
1258     { RC_RDMA_WRITE_MIDDLE, "RC RDMA Write Middle "},
1259     { RC_RDMA_WRITE_LAST, "RC RDMA Write Last "},
1260     { RC_RDMA_WRITE_LAST_IMM, "RC RDMA Write Last Immediate " },
1261     { RC_RDMA_WRITE_ONLY, "RC RDMA Write Only " },
1262     { RC_RDMA_WRITE_ONLY_IMM, "RC RDMA Write Only Immediate "},
1263     { RC_RDMA_READ_REQUEST,  "RC RDMA Read Request " },
1264     { RC_RDMA_READ_RESPONSE_FIRST, "RC RDMA Read Response First " },
1265     { RC_RDMA_READ_RESPONSE_MIDDLE, "RC RDMA Read Response Middle "},
1266     { RC_RDMA_READ_RESPONSE_LAST, "RC RDMA Read Response Last " },
1267     { RC_RDMA_READ_RESPONSE_ONLY, "RC RDMA Read Response Only "},
1268     { RC_ACKNOWLEDGE, "RC Acknowledge " },
1269     { RC_ATOMIC_ACKNOWLEDGE, "RC Atomic Acknowledge " },
1270     { RC_CMP_SWAP, "RC Compare Swap " },
1271     { RC_FETCH_ADD, "RC Fetch Add "},
1272     { RC_SEND_LAST_INVAL, "RC Send Last Invalidate "},
1273     { RC_SEND_ONLY_INVAL, "RC Send Only Invalidate " },
1274
1275
1276     { RD_SEND_FIRST, "RD Send First "},
1277     { RD_SEND_MIDDLE,"RD Send Middle " },
1278     { RD_SEND_LAST, "RD Send Last "},
1279     { RD_SEND_LAST_IMM, "RD Last Immediate " },
1280     { RD_SEND_ONLY,"RD Send Only "},
1281     { RD_SEND_ONLY_IMM,"RD Send Only Immediate "},
1282     { RD_RDMA_WRITE_FIRST,"RD RDMA Write First "},
1283     { RD_RDMA_WRITE_MIDDLE, "RD RDMA Write Middle "},
1284     { RD_RDMA_WRITE_LAST,"RD RDMA Write Last "},
1285     { RD_RDMA_WRITE_LAST_IMM,"RD RDMA Write Last Immediate "},
1286     { RD_RDMA_WRITE_ONLY,"RD RDMA Write Only "},
1287     { RD_RDMA_WRITE_ONLY_IMM,"RD RDMA Write Only Immediate "},
1288     { RD_RDMA_READ_REQUEST,"RD RDMA Read Request "},
1289     { RD_RDMA_READ_RESPONSE_FIRST,"RD RDMA Read Response First "},
1290     { RD_RDMA_READ_RESPONSE_MIDDLE,"RD RDMA Read Response Middle "},
1291     { RD_RDMA_READ_RESPONSE_LAST,"RD RDMA Read Response Last "},
1292     { RD_RDMA_READ_RESPONSE_ONLY,"RD RDMA Read Response Only "},
1293     { RD_ACKNOWLEDGE,"RD Acknowledge "},
1294     { RD_ATOMIC_ACKNOWLEDGE,"RD Atomic Acknowledge "},
1295     { RD_CMP_SWAP,"RD Compare Swap "},
1296     { RD_FETCH_ADD, "RD Fetch Add "},
1297     { RD_RESYNC,"RD RESYNC "},
1298
1299
1300     { UD_SEND_ONLY, "UD Send Only "},
1301     { UD_SEND_ONLY_IMM, "UD Send Only Immediate "},
1302
1303
1304     { UC_SEND_FIRST,"UC Send First "},
1305     { UC_SEND_MIDDLE,"UC Send Middle "},
1306     { UC_SEND_LAST,"UC Send Last "},
1307     { UC_SEND_LAST_IMM,"UC Send Last Immediate "},
1308     { UC_SEND_ONLY,"UC Send Only "},
1309     { UC_SEND_ONLY_IMM,"UC Send Only Immediate "},
1310     { UC_RDMA_WRITE_FIRST,"UC RDMA Write First"},
1311     { UC_RDMA_WRITE_MIDDLE,"Unreliable Connection RDMA Write Middle "},
1312     { UC_RDMA_WRITE_LAST,"UC RDMA Write Last "},
1313     { UC_RDMA_WRITE_LAST_IMM,"UC RDMA Write Last Immediate "},
1314     { UC_RDMA_WRITE_ONLY,"UC RDMA Write Only "},
1315     { UC_RDMA_WRITE_ONLY_IMM,"UC RDMA Write Only Immediate "},
1316     { 0, NULL}
1317
1318 };
1319
1320
1321
1322 /* Header Ordering Based on OPCODES
1323 * These are simply an enumeration of the possible header combinations defined by the IB Spec.
1324 * These enumerations
1325 * #DEFINE [HEADER_ORDER]         [ENUM]
1326 * __________________________________ */
1327 #define RDETH_DETH_PAYLD            0
1328 /* __________________________________ */
1329 #define RDETH_DETH_RETH_PAYLD       1
1330 /* __________________________________ */
1331 #define RDETH_DETH_IMMDT_PAYLD      2
1332 /* __________________________________ */
1333 #define RDETH_DETH_RETH_IMMDT_PAYLD 3
1334 /* __________________________________ */
1335 #define RDETH_DETH_RETH             4
1336 /* __________________________________ */
1337 #define RDETH_AETH_PAYLD            5
1338 /* __________________________________ */
1339 #define RDETH_PAYLD                 6
1340 /* __________________________________ */
1341 #define RDETH_AETH                  7
1342 /* __________________________________ */
1343 #define RDETH_AETH_ATOMICACKETH     8
1344 /* __________________________________ */
1345 #define RDETH_DETH_ATOMICETH        9
1346 /* ___________________________________ */
1347 #define RDETH_DETH                  10
1348 /* ___________________________________ */
1349 #define DETH_PAYLD                  11
1350 /* ___________________________________ */
1351 #define DETH_IMMDT_PAYLD            12
1352 /* ___________________________________ */
1353 #define PAYLD                       13
1354 /* ___________________________________ */
1355 #define IMMDT_PAYLD                 14
1356 /* ___________________________________ */
1357 #define RETH_PAYLD                  15
1358 /* ___________________________________ */
1359 #define RETH_IMMDT_PAYLD            16
1360 /* ___________________________________ */
1361 #define RETH                        17
1362 /* ___________________________________ */
1363 #define AETH_PAYLD                  18
1364 /* ___________________________________ */
1365 #define AETH                        19
1366 /* ___________________________________ */
1367 #define AETH_ATOMICACKETH           20
1368 /* ___________________________________ */
1369 #define ATOMICETH                   21
1370 /* ___________________________________ */
1371 #define IETH_PAYLD                  22
1372 /* ___________________________________ */
1373
1374
1375 /* Infiniband transport services
1376    These are an enumeration of the transport services over which an IB packet
1377    might be sent. The values match the corresponding 3 bits of the opCode field
1378    in the BTH  */
1379 #define TRANSPORT_RC    0
1380 #define TRANSPORT_UC    1
1381 #define TRANSPORT_RD    2
1382 #define TRANSPORT_UD    3
1383
1384
1385 /* Array of all availavle OpCodes to make matching a bit easier.
1386 * The OpCodes dictate the header sequence following in the packet.
1387 * These arrays tell the dissector which headers must be decoded for the given OpCode. */
1388 static guint32 opCode_RDETH_DETH_ATOMICETH[] = {
1389  RD_CMP_SWAP,
1390  RD_FETCH_ADD
1391 };
1392 static guint32 opCode_IETH_PAYLD[] = {
1393  RC_SEND_LAST_INVAL,
1394  RC_SEND_ONLY_INVAL
1395 };
1396 static guint32 opCode_ATOMICETH[] = {
1397  RC_CMP_SWAP,
1398  RC_FETCH_ADD
1399 };
1400 static guint32 opCode_RDETH_DETH_RETH_PAYLD[] = {
1401  RD_RDMA_WRITE_FIRST,
1402  RD_RDMA_WRITE_ONLY
1403 };
1404 static guint32 opCode_RETH_IMMDT_PAYLD[] = {
1405  RC_RDMA_WRITE_ONLY_IMM,
1406  UC_RDMA_WRITE_ONLY_IMM
1407 };
1408 static guint32 opCode_RDETH_DETH_IMMDT_PAYLD[] = {
1409  RD_SEND_LAST_IMM,
1410  RD_SEND_ONLY_IMM,
1411  RD_RDMA_WRITE_LAST_IMM
1412 };
1413
1414 static guint32 opCode_RDETH_AETH_PAYLD[] = {
1415  RD_RDMA_READ_RESPONSE_FIRST,
1416  RD_RDMA_READ_RESPONSE_LAST,
1417  RD_RDMA_READ_RESPONSE_ONLY
1418 };
1419 static guint32 opCode_AETH_PAYLD[] = {
1420  RC_RDMA_READ_RESPONSE_FIRST,
1421  RC_RDMA_READ_RESPONSE_LAST,
1422  RC_RDMA_READ_RESPONSE_ONLY
1423 };
1424 static guint32 opCode_RETH_PAYLD[] = {
1425  RC_RDMA_WRITE_FIRST,
1426  RC_RDMA_WRITE_ONLY,
1427  UC_RDMA_WRITE_FIRST,
1428  UC_RDMA_WRITE_ONLY
1429 };
1430
1431 static guint32 opCode_RDETH_DETH_PAYLD[] = {
1432  RD_SEND_FIRST,
1433  RD_SEND_MIDDLE,
1434  RD_SEND_LAST,
1435  RD_SEND_ONLY,
1436  RD_RDMA_WRITE_MIDDLE,
1437  RD_RDMA_WRITE_LAST
1438 };
1439
1440 static guint32 opCode_IMMDT_PAYLD[] = {
1441  RC_SEND_LAST_IMM,
1442  RC_SEND_ONLY_IMM,
1443  RC_RDMA_WRITE_LAST_IMM,
1444  UC_SEND_LAST_IMM,
1445  UC_SEND_ONLY_IMM,
1446  UC_RDMA_WRITE_LAST_IMM
1447 };
1448
1449 static guint32 opCode_PAYLD[] = {
1450  RC_SEND_FIRST,
1451  RC_SEND_MIDDLE,
1452  RC_SEND_LAST,
1453  RC_SEND_ONLY,
1454  RC_RDMA_WRITE_MIDDLE,
1455  RC_RDMA_WRITE_LAST,
1456  RC_RDMA_READ_RESPONSE_MIDDLE,
1457  UC_SEND_FIRST,
1458  UC_SEND_MIDDLE,
1459  UC_SEND_LAST,
1460  UC_SEND_ONLY,
1461  UC_RDMA_WRITE_MIDDLE,
1462  UC_RDMA_WRITE_LAST
1463 };
1464
1465 /* It is not necessary to create arrays for these OpCodes since they indicate only one further header.
1466 *  We can just decode it directly
1467
1468 * static guint32 opCode_DETH_IMMDT_PAYLD[] = {
1469 * UD_SEND_ONLY_IMM
1470 * };
1471 * static guint32 opCode_DETH_PAYLD[] = {
1472 * UD_SEND_ONLY
1473 * };
1474 * static guint32 opCode_RDETH_DETH[] = {
1475 * RD_RESYNC
1476 * };
1477 * static guint32 opCode_RDETH_DETH_RETH[] = {
1478 * RD_RDMA_READ_REQUEST
1479 * };
1480 * static guint32 opCode_RDETH_DETH_RETH_IMMDT_PAYLD[] = {
1481 * RD_RDMA_WRITE_ONLY_IMM
1482 * };
1483 * static guint32 opCode_RDETH_AETH_ATOMICACKETH[] = {
1484 * RD_ATOMIC_ACKNOWLEDGE
1485 * };
1486 * static guint32 opCode_RDETH_AETH[] = {
1487 * RD_ACKNOWLEDGE
1488 * };
1489 * static guint32 opCode_RDETH_PAYLD[] = {
1490 * RD_RDMA_READ_RESPONSE_MIDDLE
1491 * };
1492 * static guint32 opCode_AETH_ATOMICACKETH[] = {
1493 * RC_ATOMIC_ACKNOWLEDGE
1494 * };
1495 * static guint32 opCode_RETH[] = {
1496 * RC_RDMA_READ_REQUEST
1497 * };
1498 * static guint32 opCode_AETH[] = {
1499 * RC_ACKNOWLEDGE
1500 * }; */
1501
1502 static void *src_addr = NULL,     /* the address to be displayed in the source/destination columns */
1503             *dst_addr = NULL;     /* (lid/gid number) will be stored here */
1504
1505 #define ADDR_MAX_LEN  sizeof("IPv6 over IB Packet")      /* maximum length of src_addr and dst_addr is for IPoIB
1506                                                             where we print an explanation string */
1507
1508 static gint8 transport_type = -1;      /* reflects the transport type of the packet being parsed.
1509                                           only use one of the TRANSPORT_* values for this field */
1510
1511 /* settings to be set by the user via the preferences dialog */
1512 static gboolean pref_dissect_eoib = TRUE;
1513 static gboolean pref_identify_iba_payload = TRUE;
1514
1515 /* saves information about connections that have been/are in the process of being
1516    negotiated via ConnectionManagement packets */
1517 typedef struct {
1518     guint8 req_gid[GID_SIZE],
1519            resp_gid[GID_SIZE];  /* GID of requester/responder, respectively */
1520     guint16 req_lid,
1521             resp_lid;   /* LID of requester/responder, respectively */
1522     guint32 req_qp,
1523             resp_qp;            /* QP number of requester/responder, respectively */
1524     guint64 service_id;         /* service id for this connection */
1525 } connection_context;
1526
1527 /* holds a table of connection contexts being negotiated by CM. the key is a obtained
1528    using ADD_ADDRESS_TO_HASH(initiator address, TransactionID) [remember that the 1st
1529    argument to ADD_ADDRESS_TO_HASH must be an lvalue. */
1530 static GHashTable *CM_context_table = NULL;
1531
1532 /* heuristics sub-dissectors list for dissecting the data payload of IB packets */
1533 static heur_dissector_list_t heur_dissectors_payload;
1534 /* heuristics sub-dissectors list for dissecting the PrivateData of CM packets */
1535 static heur_dissector_list_t heur_dissectors_cm_private;
1536
1537 /* ----- This sections contains various utility functions indirectly related to Infiniband dissection ---- */
1538
1539 /* g_int64_hash, g_int64_equal are defined starting glib 2.22 - otherwise, we'll have to
1540    provide them ourselves! */
1541 #if !GLIB_CHECK_VERSION(2,22,0)
1542 guint
1543 g_int64_hash (gconstpointer v)
1544 {
1545   return (guint) *(const gint64*) v;
1546 }
1547
1548 gboolean
1549 g_int64_equal (gconstpointer v1,
1550                gconstpointer v2)
1551 {
1552   return *((const gint64*) v1) == *((const gint64*) v2);
1553 }
1554 #endif
1555
1556 void table_destroy_notify(gpointer data) {
1557     g_free(data);
1558 }
1559
1560 /* --------------------------------------------------------------------------------------------------------*/
1561
1562 /* Helper dissector for correctly dissecting RoCE packets (encapsulated within an Ethernet */
1563 /* frame). The only difference from regular IB packets is that RoCE packets do not contain */
1564 /* a LRH, and always start with a GRH.                                                      */
1565 static void
1566 dissect_roce(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1567 {
1568     /* this is a RoCE packet, so signal the IB dissector not to look for LRH */
1569     dissect_infiniband_common(tvb, pinfo, tree, TRUE);
1570 }
1571
1572 static void
1573 dissect_infiniband(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1574 {
1575     dissect_infiniband_common(tvb, pinfo, tree, FALSE);
1576 }
1577
1578 /* Common Dissector for both InfiniBand and RoCE packets
1579  * IN:
1580  *       tvb - The tvbbuff of packet data
1581  *       pinfo - The packet info structure with column information
1582  *       tree - The tree structure under which field nodes are to be added
1583  *       starts_with_grh - If true this packets start with a GRH header (RoCE), otherwise with LRH as usual
1584  * Notes:
1585  * 1.) Floating "offset+=" statements should probably be "functionized" but they are inline
1586  * Offset is only passed by reference in specific places, so do not be confused when following code
1587  * In any code path, adding up "offset+=" statements will tell you what byte you are at */
1588 static void
1589 dissect_infiniband_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean starts_with_grh)
1590 {
1591     /* Top Level Item */
1592     proto_item *infiniband_packet = NULL;
1593
1594     /* The Headers Subtree */
1595     proto_tree *all_headers_tree = NULL;
1596
1597     /* LRH - Local Route Header */
1598     proto_tree *local_route_header_tree = NULL;
1599     proto_item *local_route_header_item = NULL;
1600
1601     /* GRH - Global Route Header */
1602     proto_tree *global_route_header_tree = NULL;
1603     proto_item *global_route_header_item = NULL;
1604
1605     /* BTH - Base Transport header */
1606     proto_tree *base_transport_header_tree = NULL;
1607     proto_item *base_transport_header_item = NULL;
1608
1609     /* Raw Data */
1610     proto_item *RAWDATA_header_item;
1611     guint8 lnh_val = 0;             /* Link Next Header Value */
1612     gint offset = 0;                /* Current Offset */
1613
1614     /* General Variables */
1615     gboolean bthFollows = 0;        /* Tracks if we are parsing a BTH.  This is a significant decision point */
1616     guint8 virtualLane = 0;         /* IB VirtualLane.  Keyed off of for detecting subnet admin/management */
1617     guint8 opCode = 0;              /* OpCode from BTH header. */
1618     gint32 nextHeaderSequence = -1; /* defined by this dissector. #define which indicates the upcoming header sequence from OpCode */
1619     guint16 payloadLength = 0;      /* Payload Length should it exist */
1620     guint8 nxtHdr = 0;              /* Keyed off for header dissection order */
1621     guint16 packetLength = 0;       /* Packet Length.  We track this as tvb_length - offset.   */
1622                                     /*  It provides the parsing methods a known size            */
1623                                     /*   that must be available for that header.                */
1624     struct e_in6_addr SRCgid;       /* Structures to hold GIDs should we need them */
1625     struct e_in6_addr DSTgid;
1626     gint crc_length = 0;
1627
1628     /* allocate space for source/destination addresses. we will fill them in later */
1629     src_addr = ep_alloc(ADDR_MAX_LEN);
1630     dst_addr = ep_alloc(ADDR_MAX_LEN);
1631
1632     pinfo->srcport = pinfo->destport = 0xffffffff;  /* set the src/dest QPN to something impossible instead of the default 0,
1633                                                        so we don't mistake it for a MAD. (QP is only 24bit, so can't be 0xffffffff)*/
1634
1635     /* add any code that should only run the first time the packet is dissected here: */
1636     if (!pinfo->fd->flags.visited)
1637     {
1638         pinfo->ptype = PT_IBQP;     /* set the port-type for this packet to be Infiniband QP number */
1639     }
1640
1641     /* Mark the Packet type as Infiniband in the wireshark UI */
1642     /* Clear other columns */
1643     col_set_str(pinfo->cinfo, COL_PROTOCOL, "InfiniBand");
1644     col_clear(pinfo->cinfo, COL_INFO);
1645
1646     /* Get the parent tree from the ERF dissector.  We don't want to nest under ERF */
1647     if(tree && tree->parent)
1648     {
1649         /* Set the normal tree outside of ERF */
1650         tree = tree->parent;
1651         /* Set a global reference for nested protocols */
1652         top_tree = tree;
1653     }
1654
1655     /* The "quick-dissection" code in dissect_general_info skips lots of the recently-added code
1656        for saving context etc. It is no longer viable to maintain two code branches, so we have
1657        (temporarily?) disabled the second one. All dissection now goes through the full branch,
1658        using a NULL tree pointer if this is not a full dissection call. Take care not to dereference
1659        the tree pointer or any subtree pointers you create using it and you'll be fine. */
1660     if(0 && !tree)
1661     {
1662         /* If no packet details are being dissected, extract some high level info for the packet view */
1663         /* Assigns column values rather than full tree population */
1664         dissect_general_info(tvb, offset, pinfo, starts_with_grh);
1665         return;
1666     }
1667
1668     /* Top Level Packet */
1669     infiniband_packet = proto_tree_add_item(tree, proto_infiniband, tvb, offset, -1, FALSE);
1670
1671     /* Headers Level Tree */
1672     all_headers_tree = proto_item_add_subtree(infiniband_packet, ett_all_headers);
1673
1674     if (starts_with_grh) {
1675         /* this is a RoCE packet, skip LRH parsing */
1676         lnh_val = IBA_GLOBAL;
1677         packetLength = tvb_get_ntohs(tvb, 4);   /* since we have no LRH to get PktLen from, use that of the GRH */
1678         goto skip_lrh;
1679     }
1680
1681     /* Local Route Header Subtree */
1682     local_route_header_item = proto_tree_add_item(all_headers_tree, hf_infiniband_LRH, tvb, offset, 8, FALSE);
1683     proto_item_set_text(local_route_header_item, "%s", "Local Route Header");
1684     local_route_header_tree = proto_item_add_subtree(local_route_header_item, ett_lrh);
1685
1686     proto_tree_add_item(local_route_header_tree, hf_infiniband_virtual_lane,            tvb, offset, 1, FALSE);
1687
1688
1689     /* Get the Virtual Lane.  We'll use this to identify Subnet Management and Subnet Administration Packets. */
1690     virtualLane =  tvb_get_guint8(tvb, offset);
1691     virtualLane = virtualLane & 0xF0;
1692
1693
1694     proto_tree_add_item(local_route_header_tree, hf_infiniband_link_version,            tvb, offset, 1, FALSE); offset+=1;
1695     proto_tree_add_item(local_route_header_tree, hf_infiniband_service_level,           tvb, offset, 1, FALSE);
1696
1697     proto_tree_add_item(local_route_header_tree, hf_infiniband_reserved2,               tvb, offset, 1, FALSE);
1698     proto_tree_add_item(local_route_header_tree, hf_infiniband_link_next_header,        tvb, offset, 1, FALSE);
1699
1700
1701     /* Save Link Next Header... This tells us what the next header is. */
1702     lnh_val =  tvb_get_guint8(tvb, offset);
1703     lnh_val = lnh_val & 0x03;
1704     offset+=1;
1705
1706
1707     proto_tree_add_item(local_route_header_tree, hf_infiniband_destination_local_id,    tvb, offset, 2, FALSE);
1708
1709
1710     /* Set destination in packet view. */
1711     *((guint16*) dst_addr) = tvb_get_ntohs(tvb, offset);
1712     SET_ADDRESS(&pinfo->dst, AT_IB, sizeof(guint16), dst_addr);
1713
1714     offset+=2;
1715
1716     proto_tree_add_item(local_route_header_tree, hf_infiniband_reserved5,               tvb, offset, 2, FALSE);
1717
1718     packetLength = tvb_get_ntohs(tvb, offset); /* Get the Packet Length. This will determine payload size later on. */
1719     packetLength = packetLength & 0x07FF;      /* Mask off top 5 bits, they are reserved */
1720     packetLength = packetLength * 4;           /* Multiply by 4 to get true byte length. This is by specification.  */
1721                                                /*   PktLen is size in 4 byte words (byteSize /4). */
1722
1723     proto_tree_add_item(local_route_header_tree, hf_infiniband_packet_length,           tvb, offset, 2, FALSE); offset+=2;
1724     proto_tree_add_item(local_route_header_tree, hf_infiniband_source_local_id,         tvb, offset, 2, FALSE);
1725
1726     /* Set Source in packet view. */
1727     *((guint16*) src_addr) = tvb_get_ntohs(tvb, offset);
1728     SET_ADDRESS(&pinfo->src, AT_IB, sizeof(guint16), src_addr);
1729
1730     offset+=2;
1731     packetLength -= 8; /* Shave 8 bytes for the LRH. */
1732
1733 skip_lrh:
1734
1735     /* Key off Link Next Header.  This tells us what High Level Data Format we have */
1736     switch(lnh_val)
1737     {
1738         case IBA_GLOBAL:
1739             global_route_header_item = proto_tree_add_item(all_headers_tree, hf_infiniband_GRH, tvb, offset, 40, FALSE);
1740             proto_item_set_text(global_route_header_item, "%s", "Global Route Header");
1741             global_route_header_tree = proto_item_add_subtree(global_route_header_item, ett_grh);
1742
1743             proto_tree_add_item(global_route_header_tree, hf_infiniband_ip_version,         tvb, offset, 1, FALSE);
1744             proto_tree_add_item(global_route_header_tree, hf_infiniband_traffic_class,      tvb, offset, 2, FALSE);
1745             proto_tree_add_item(global_route_header_tree, hf_infiniband_flow_label,         tvb, offset, 4, FALSE); offset += 4;
1746
1747             payloadLength = tvb_get_ntohs(tvb, offset);
1748
1749             proto_tree_add_item(global_route_header_tree, hf_infiniband_payload_length,     tvb, offset, 2, FALSE); offset += 2;
1750
1751             nxtHdr = tvb_get_guint8(tvb, offset);
1752
1753             proto_tree_add_item(global_route_header_tree, hf_infiniband_next_header,        tvb, offset, 1, FALSE); offset +=1;
1754             proto_tree_add_item(global_route_header_tree, hf_infiniband_hop_limit,          tvb, offset, 1, FALSE); offset +=1;
1755             proto_tree_add_item(global_route_header_tree, hf_infiniband_source_gid,         tvb, offset, 16, FALSE);
1756
1757             tvb_get_ipv6(tvb, offset, &SRCgid);
1758
1759             /* set source GID in packet view*/
1760             memcpy(src_addr, &SRCgid, GID_SIZE);
1761             SET_ADDRESS(&pinfo->src, AT_IB, GID_SIZE, src_addr);
1762
1763             offset += 16;
1764
1765             proto_tree_add_item(global_route_header_tree, hf_infiniband_destination_gid,    tvb, offset, 16, FALSE);
1766
1767             tvb_get_ipv6(tvb, offset, &DSTgid);
1768
1769             /* set destination GID in packet view*/
1770             memcpy(dst_addr, &DSTgid, GID_SIZE);
1771             SET_ADDRESS(&pinfo->dst, AT_IB, GID_SIZE, dst_addr);
1772
1773             offset += 16;
1774             packetLength -= 40; /* Shave 40 bytes for GRH */
1775
1776             if(nxtHdr != 0x1B)
1777             {
1778                 /* Some kind of packet being transported globally with IBA, but locally it is not IBA - no BTH following. */
1779                 break;
1780             }
1781             /* otherwise fall through and start parsing BTH */
1782         case IBA_LOCAL:
1783             bthFollows = TRUE;
1784             base_transport_header_item = proto_tree_add_item(all_headers_tree, hf_infiniband_BTH, tvb, offset, 12, FALSE);
1785             proto_item_set_text(base_transport_header_item, "%s", "Base Transport Header");
1786             base_transport_header_tree = proto_item_add_subtree(base_transport_header_item, ett_bth);
1787             proto_tree_add_item(base_transport_header_tree, hf_infiniband_opcode,                       tvb, offset, 1, FALSE);
1788
1789             /* Get the OpCode - this tells us what headers are following */
1790             opCode = tvb_get_guint8(tvb, offset);
1791             col_append_str(pinfo->cinfo, COL_INFO, val_to_str((guint32)opCode, OpCodeMap, "Unknown OpCode"));
1792             offset +=1;
1793
1794             proto_tree_add_item(base_transport_header_tree, hf_infiniband_solicited_event,              tvb, offset, 1, FALSE);
1795             proto_tree_add_item(base_transport_header_tree, hf_infiniband_migreq,                       tvb, offset, 1, FALSE);
1796             proto_tree_add_item(base_transport_header_tree, hf_infiniband_pad_count,                    tvb, offset, 1, FALSE);
1797             proto_tree_add_item(base_transport_header_tree, hf_infiniband_transport_header_version,     tvb, offset, 1, FALSE); offset +=1;
1798             proto_tree_add_item(base_transport_header_tree, hf_infiniband_partition_key,                tvb, offset, 2, FALSE); offset +=2;
1799             proto_tree_add_item(base_transport_header_tree, hf_infiniband_reserved8,                    tvb, offset, 1, FALSE); offset +=1;
1800             proto_tree_add_item(base_transport_header_tree, hf_infiniband_destination_qp,               tvb, offset, 3, FALSE);
1801             pinfo->destport = tvb_get_ntoh24(tvb, offset); offset +=3;
1802             proto_tree_add_item(base_transport_header_tree, hf_infiniband_acknowledge_request,          tvb, offset, 1, FALSE);
1803             proto_tree_add_item(base_transport_header_tree, hf_infiniband_reserved7,                    tvb, offset, 1, FALSE); offset +=1;
1804             proto_tree_add_item(base_transport_header_tree, hf_infiniband_packet_sequence_number,       tvb, offset, 3, FALSE); offset +=3;
1805
1806
1807             packetLength -= 12; /* Shave 12 for Base Transport Header */
1808
1809         break;
1810         case IP_NON_IBA:
1811             /* Raw IPv6 Packet */
1812             g_snprintf(dst_addr,  ADDR_MAX_LEN, "IPv6 over IB Packet");
1813             SET_ADDRESS(&pinfo->dst,  AT_STRINGZ, (int)strlen(dst_addr)+1, dst_addr);
1814
1815             parse_IPvSix(all_headers_tree, tvb, &offset, pinfo);
1816             break;
1817         case RAW:
1818             parse_RWH(all_headers_tree, tvb, &offset, pinfo);
1819             break;
1820         default:
1821             /* Unknown Packet */
1822             RAWDATA_header_item = proto_tree_add_item(all_headers_tree, hf_infiniband_raw_data, tvb, offset, -1, FALSE);
1823             proto_item_set_text(RAWDATA_header_item, "%s", "Unknown Raw Data - IB Encapsulated");
1824             break;
1825     }
1826
1827     /* Base Transport header is hit quite often, however it is alone since it is the exception not the rule */
1828     /* Only IBA Local packets use it */
1829     if(bthFollows)
1830     {
1831         /* Find our next header sequence based on the Opcode
1832         * Each case decrements the packetLength by the amount of bytes consumed by each header.
1833         * The find_next_header_sequence method could be used to automate this.
1834         * We need to keep track of this so we know much data to mark as payload/ICRC/VCRC values. */
1835
1836         transport_type = (opCode & 0xE0) >> 5;   /* save transport type for identifying EoIB payloads later... */
1837         nextHeaderSequence = find_next_header_sequence((guint32) opCode);
1838
1839         /* find_next_header_sequence gives us the DEFINE value corresponding to the header order following */
1840         /* Enumerations are named intuitively, e.g. RDETH DETH PAYLOAD means there is an RDETH Header, DETH Header, and a packet payload */
1841         switch(nextHeaderSequence)
1842         {
1843             case RDETH_DETH_PAYLD:
1844                 parse_RDETH(all_headers_tree, tvb, &offset);
1845                 parse_DETH(all_headers_tree, pinfo, tvb, &offset);
1846
1847                 packetLength -= 4; /* RDETH */
1848                 packetLength -= 8; /* DETH */
1849
1850                 parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength);
1851                 break;
1852             case RDETH_DETH_RETH_PAYLD:
1853                 parse_RDETH(all_headers_tree, tvb, &offset);
1854                 parse_DETH(all_headers_tree, pinfo, tvb, &offset);
1855                 parse_RETH(all_headers_tree, tvb, &offset);
1856
1857                 packetLength -= 4; /* RDETH */
1858                 packetLength -= 8; /* DETH */
1859                 packetLength -= 16; /* RETH */
1860
1861                 parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength);
1862                 break;
1863             case RDETH_DETH_IMMDT_PAYLD:
1864                 parse_RDETH(all_headers_tree, tvb, &offset);
1865                 parse_DETH(all_headers_tree, pinfo, tvb, &offset);
1866                 parse_IMMDT(all_headers_tree, tvb, &offset);
1867
1868                 packetLength -= 4; /* RDETH */
1869                 packetLength -= 8; /* DETH */
1870                 packetLength -= 4; /* IMMDT */
1871
1872                 parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength);
1873                 break;
1874             case RDETH_DETH_RETH_IMMDT_PAYLD:
1875                 parse_RDETH(all_headers_tree, tvb, &offset);
1876                 parse_DETH(all_headers_tree, pinfo, tvb, &offset);
1877                 parse_RETH(all_headers_tree, tvb, &offset);
1878                 parse_IMMDT(all_headers_tree, tvb, &offset);
1879
1880                 packetLength -= 4; /* RDETH */
1881                 packetLength -= 8; /* DETH */
1882                 packetLength -= 16; /* RETH */
1883                 packetLength -= 4; /* IMMDT */
1884
1885                 parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength);
1886                 break;
1887             case RDETH_DETH_RETH:
1888                 parse_RDETH(all_headers_tree, tvb, &offset);
1889                 parse_DETH(all_headers_tree, pinfo, tvb, &offset);
1890                 parse_RETH(all_headers_tree, tvb, &offset);
1891
1892                 packetLength -= 4; /* RDETH */
1893                 packetLength -= 8; /* DETH */
1894                 packetLength -= 16; /* RETH */
1895
1896                 break;
1897             case RDETH_AETH_PAYLD:
1898                 parse_RDETH(all_headers_tree, tvb, &offset);
1899                 parse_AETH(all_headers_tree, tvb, &offset);
1900
1901                 packetLength -= 4; /* RDETH */
1902                 packetLength -= 4; /* AETH */
1903
1904                 parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength);
1905                 break;
1906             case RDETH_PAYLD:
1907                 parse_RDETH(all_headers_tree, tvb, &offset);
1908
1909                 packetLength -= 4; /* RDETH */
1910
1911                 parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength);
1912                 break;
1913             case RDETH_AETH:
1914                 parse_AETH(all_headers_tree, tvb, &offset);
1915
1916                 packetLength -= 4; /* RDETH */
1917                 packetLength -= 4; /* AETH */
1918
1919
1920                 break;
1921             case RDETH_AETH_ATOMICACKETH:
1922                 parse_RDETH(all_headers_tree, tvb, &offset);
1923                 parse_AETH(all_headers_tree, tvb, &offset);
1924                 parse_ATOMICACKETH(all_headers_tree, tvb, &offset);
1925
1926                 packetLength -= 4; /* RDETH */
1927                 packetLength -= 4; /* AETH */
1928                 packetLength -= 8; /* AtomicAckETH */
1929
1930
1931                 break;
1932             case RDETH_DETH_ATOMICETH:
1933                 parse_RDETH(all_headers_tree, tvb, &offset);
1934                 parse_DETH(all_headers_tree, pinfo, tvb, &offset);
1935                 parse_ATOMICETH(all_headers_tree, tvb, &offset);
1936
1937                 packetLength -= 4; /* RDETH */
1938                 packetLength -= 8; /* DETH */
1939                 packetLength -= 28; /* AtomicETH */
1940
1941                 break;
1942             case RDETH_DETH:
1943                 parse_RDETH(all_headers_tree, tvb, &offset);
1944                 parse_DETH(all_headers_tree, pinfo, tvb, &offset);
1945
1946                 packetLength -= 4; /* RDETH */
1947                 packetLength -= 8; /* DETH */
1948
1949                 break;
1950             case DETH_PAYLD:
1951                 parse_DETH(all_headers_tree, pinfo, tvb, &offset);
1952
1953                 packetLength -= 8; /* DETH */
1954
1955                 parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength);
1956                 break;
1957             case PAYLD:
1958
1959                 parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength);
1960                 break;
1961             case IMMDT_PAYLD:
1962                 parse_IMMDT(all_headers_tree, tvb, &offset);
1963
1964                 packetLength -= 4; /* IMMDT */
1965
1966                 parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength);
1967                 break;
1968             case RETH_PAYLD:
1969                 parse_RETH(all_headers_tree, tvb, &offset);
1970
1971                 packetLength -= 16; /* RETH */
1972
1973                 parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength);
1974                 break;
1975             case RETH:
1976                 parse_RETH(all_headers_tree, tvb, &offset);
1977
1978                 packetLength -= 16; /* RETH */
1979
1980                 break;
1981             case AETH_PAYLD:
1982                 parse_AETH(all_headers_tree, tvb, &offset);
1983
1984                 packetLength -= 4; /* AETH */
1985
1986                 parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength);
1987                 break;
1988             case AETH:
1989                 parse_AETH(all_headers_tree, tvb, &offset);
1990
1991                 packetLength -= 4; /* AETH */
1992
1993                 break;
1994             case AETH_ATOMICACKETH:
1995                 parse_AETH(all_headers_tree, tvb, &offset);
1996                 parse_ATOMICACKETH(all_headers_tree, tvb, &offset);
1997
1998                 packetLength -= 4; /* AETH */
1999                 packetLength -= 8; /* AtomicAckETH */
2000
2001                 break;
2002             case ATOMICETH:
2003                 parse_ATOMICETH(all_headers_tree, tvb, &offset);
2004
2005                 packetLength -= 28; /* AtomicETH */
2006
2007                 break;
2008             case IETH_PAYLD:
2009                 parse_IETH(all_headers_tree, tvb, &offset);
2010
2011                 packetLength -= 4; /* IETH */
2012
2013                 parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength);
2014                 break;
2015             case DETH_IMMDT_PAYLD:
2016                 parse_DETH(all_headers_tree, pinfo, tvb, &offset);
2017                 parse_IMMDT(all_headers_tree, tvb, &offset);
2018
2019                 packetLength -= 8; /* DETH */
2020                 packetLength -= 4; /* IMMDT */
2021
2022                 parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength);
2023                 break;
2024             default:
2025                 parse_VENDOR(all_headers_tree, tvb, &offset);
2026                 break;
2027
2028         }
2029
2030     }
2031     /* Display the ICRC/VCRC */
2032     /* Doing it this way rather than in a variety of places according to the specific packet */
2033     /* If we've already displayed it crc_length comes out 0 */
2034     crc_length = tvb_reported_length_remaining(tvb, offset);
2035     if(crc_length == 6)
2036     {
2037         proto_tree_add_item(all_headers_tree, hf_infiniband_invariant_crc, tvb, offset, 4, FALSE); offset +=4;
2038         proto_tree_add_item(all_headers_tree, hf_infiniband_variant_crc,   tvb, offset, 2, FALSE); offset+=2;
2039     }
2040     else if(crc_length == 4)
2041     {
2042         proto_tree_add_item(all_headers_tree, hf_infiniband_invariant_crc, tvb, offset, 4, FALSE); offset +=4;
2043     }
2044     else if(crc_length == 2)
2045     {
2046         proto_tree_add_item(all_headers_tree, hf_infiniband_variant_crc,   tvb, offset, 2, FALSE); offset+=2;
2047     }
2048
2049 }
2050
2051 static void
2052 dissect_infiniband_link(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2053 {
2054     /* Top Level Item */
2055     proto_item *infiniband_link_packet = NULL;
2056
2057     /* The Link Subtree */
2058     proto_tree *link_tree = NULL;
2059
2060     proto_item *operand_item = NULL;
2061     gint offset = 0;                /* Current Offset */
2062     guint8 operand;                 /* Link packet Operand */
2063
2064     operand =  tvb_get_guint8(tvb, offset);
2065     operand = (operand & 0xF0) >> 4;
2066
2067     /* Mark the Packet type as Infiniband in the wireshark UI */
2068     /* Clear other columns */
2069     col_set_str(pinfo->cinfo, COL_PROTOCOL, "InfiniBand Link");
2070     col_clear(pinfo->cinfo, COL_INFO);
2071     col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
2072              val_to_str(operand, Operand_Description, "Unknown (0x%1x)"));
2073
2074     /* Get the parent tree from the ERF dissector.  We don't want to nest under ERF */
2075     if(tree && tree->parent)
2076     {
2077         /* Set the normal tree outside of ERF */
2078         tree = tree->parent;
2079         /* Set a global reference for nested protocols */
2080         top_tree = tree;
2081     }
2082
2083     if(!tree)
2084     {
2085         /* If no packet details are being dissected, extract some high level info for the packet view */
2086         /* Assigns column values rather than full tree population */
2087         dissect_general_info(tvb, offset, pinfo, FALSE);
2088         return;
2089     }
2090
2091     /* Top Level Packet */
2092     infiniband_link_packet = proto_tree_add_item(tree, proto_infiniband_link, tvb, offset, -1, FALSE);
2093
2094     /* Headers Level Tree */
2095     link_tree = proto_item_add_subtree(infiniband_link_packet, ett_link);
2096
2097     operand_item = proto_tree_add_item(link_tree, hf_infiniband_link_op, tvb, offset, 2, FALSE);
2098
2099     if (operand > 1) {
2100         proto_item_set_text(operand_item, "%s", "Reserved");
2101         call_dissector(data_handle, tvb, pinfo, link_tree);
2102     } else {
2103         proto_tree_add_item(link_tree, hf_infiniband_link_fctbs, tvb, offset, 2, FALSE);
2104         offset += 2;
2105
2106         proto_tree_add_item(link_tree, hf_infiniband_link_vl, tvb, offset, 2, FALSE);
2107         proto_tree_add_item(link_tree, hf_infiniband_link_fccl, tvb, offset, 2, FALSE);
2108         offset += 2;
2109
2110         proto_tree_add_item(link_tree, hf_infiniband_link_lpcrc, tvb, offset, 2, FALSE);
2111         offset += 2;
2112     }
2113
2114 }
2115
2116
2117 /* Description: Finds the header sequence that follows the Base Transport Header.
2118 * Somwhat inefficient (should be using a single key,value pair data structure)
2119 * But uses pure probablity to take a stab at better efficiency.
2120 * Searches largest header sequence groups first, and then finally resorts to single matches for unique header sequences
2121 * IN: OpCode: The OpCode from the Base Transport Header.
2122 * OUT: The Header Sequence enumeration.  See Declarations for #defines from (0-22) */
2123 static gint32
2124 find_next_header_sequence(guint32 OpCode)
2125 {
2126     if(contains(OpCode, &opCode_PAYLD[0], (gint32)sizeof(opCode_PAYLD)))
2127         return PAYLD;
2128
2129     if(contains(OpCode, &opCode_IMMDT_PAYLD[0], (gint32)sizeof(opCode_IMMDT_PAYLD)))
2130         return IMMDT_PAYLD;
2131
2132     if(contains(OpCode, &opCode_RDETH_DETH_PAYLD[0], (gint32)sizeof(opCode_RDETH_DETH_PAYLD)))
2133         return RDETH_DETH_PAYLD;
2134
2135     if(contains(OpCode, &opCode_RETH_PAYLD[0], (gint32)sizeof(opCode_RETH_PAYLD)))
2136         return RETH_PAYLD;
2137
2138     if(contains(OpCode, &opCode_RDETH_AETH_PAYLD[0], (gint32)sizeof(opCode_RDETH_AETH_PAYLD)))
2139         return RDETH_AETH_PAYLD;
2140
2141     if(contains(OpCode, &opCode_AETH_PAYLD[0], (gint32)sizeof(opCode_AETH_PAYLD)))
2142         return AETH_PAYLD;
2143
2144     if(contains(OpCode, &opCode_RDETH_DETH_IMMDT_PAYLD[0], (gint32)sizeof(opCode_RDETH_DETH_IMMDT_PAYLD)))
2145         return RDETH_DETH_IMMDT_PAYLD;
2146
2147     if(contains(OpCode, &opCode_RETH_IMMDT_PAYLD[0], (gint32)sizeof(opCode_RETH_IMMDT_PAYLD)))
2148         return RETH_IMMDT_PAYLD;
2149
2150     if(contains(OpCode, &opCode_RDETH_DETH_RETH_PAYLD[0], (gint32)sizeof(opCode_RDETH_DETH_RETH_PAYLD)))
2151         return RDETH_DETH_RETH_PAYLD;
2152
2153     if(contains(OpCode, &opCode_ATOMICETH[0], (gint32)sizeof(opCode_ATOMICETH)))
2154         return ATOMICETH;
2155
2156     if(contains(OpCode, &opCode_IETH_PAYLD[0], (gint32)sizeof(opCode_IETH_PAYLD)))
2157         return IETH_PAYLD;
2158
2159     if(contains(OpCode, &opCode_RDETH_DETH_ATOMICETH[0], (gint32)sizeof(opCode_RDETH_DETH_ATOMICETH)))
2160         return RDETH_DETH_ATOMICETH;
2161
2162     if((OpCode ^ RC_ACKNOWLEDGE) == 0)
2163         return AETH;
2164
2165     if((OpCode ^ RC_RDMA_READ_REQUEST) == 0)
2166         return RETH;
2167
2168     if((OpCode ^ RC_ATOMIC_ACKNOWLEDGE) == 0)
2169         return AETH_ATOMICACKETH;
2170
2171     if((OpCode ^ RD_RDMA_READ_RESPONSE_MIDDLE) == 0)
2172         return RDETH_PAYLD;
2173
2174     if((OpCode ^ RD_ACKNOWLEDGE) == 0)
2175         return RDETH_AETH;
2176
2177     if((OpCode ^ RD_ATOMIC_ACKNOWLEDGE) == 0)
2178         return RDETH_AETH_ATOMICACKETH;
2179
2180     if((OpCode ^ RD_RDMA_WRITE_ONLY_IMM) == 0)
2181         return RDETH_DETH_RETH_IMMDT_PAYLD;
2182
2183     if((OpCode ^ RD_RDMA_READ_REQUEST) == 0)
2184         return RDETH_DETH_RETH;
2185
2186     if((OpCode ^ RD_RESYNC) == 0)
2187         return RDETH_DETH;
2188
2189     if((OpCode ^ UD_SEND_ONLY) == 0)
2190         return DETH_PAYLD;
2191
2192     if((OpCode ^ UD_SEND_ONLY_IMM) == 0)
2193         return DETH_IMMDT_PAYLD;
2194
2195     return -1;
2196 }
2197
2198 /* Description: Finds if a given value is present in an array. This is probably in a standard library somewhere,
2199 * But I'd rather define my own.
2200 * IN: OpCode: The OpCode you are looking for
2201 * IN: Codes: The organized array of OpCodes to look through
2202 * IN: Array length, because we're in C++...
2203 * OUT: Boolean indicating if that OpCode was found in OpCodes */
2204 static gboolean
2205 contains(guint32 OpCode, guint32* Codes, gint32 length)
2206 {
2207     gint32 i;
2208     for(i = 0; i < length; i++)
2209     {
2210         if((OpCode ^ Codes[i]) == 0)
2211             return TRUE;
2212     }
2213     return FALSE;
2214 }
2215
2216 /* Parse RDETH - Reliable Datagram Extended Transport Header
2217 * IN: parentTree to add the dissection to - in this code the all_headers_tree
2218 * IN: tvb - the data buffer from wireshark
2219 * IN/OUT: The current and updated offset */
2220 static void
2221 parse_RDETH(proto_tree * parentTree, tvbuff_t *tvb, gint *offset)
2222 {
2223     gint local_offset = *offset;
2224     /* RDETH - Reliable Datagram Extended Transport Header */
2225     proto_tree *RDETH_header_tree = NULL;
2226     proto_item *RDETH_header_item = NULL;
2227
2228     RDETH_header_item = proto_tree_add_item(parentTree, hf_infiniband_RDETH, tvb, local_offset, 4, FALSE);
2229     proto_item_set_text(RDETH_header_item, "%s", "RDETH - Reliable Datagram Extended Transport Header");
2230     RDETH_header_tree = proto_item_add_subtree(RDETH_header_item, ett_rdeth);
2231
2232     proto_tree_add_item(RDETH_header_tree, hf_infiniband_reserved8_RDETH,   tvb, local_offset, 1, FALSE); local_offset+=1;
2233     proto_tree_add_item(RDETH_header_tree, hf_infiniband_ee_context,        tvb, local_offset, 3, FALSE); local_offset+=3;
2234     *offset = local_offset;
2235 }
2236
2237 /* Parse DETH - Datagram Extended Transport Header
2238 * IN: parentTree to add the dissection to - in this code the all_headers_tree
2239 * IN: tvb - the data buffer from wireshark
2240 * IN/OUT: The current and updated offset  */
2241 static void
2242 parse_DETH(proto_tree *parentTree, packet_info *pinfo, tvbuff_t *tvb, gint *offset)
2243 {
2244     gint local_offset = *offset;
2245     /* DETH - Datagram Extended Transport Header */
2246     proto_tree *DETH_header_tree = NULL;
2247     proto_item *DETH_header_item = NULL;
2248
2249     DETH_header_item = proto_tree_add_item(parentTree, hf_infiniband_DETH, tvb, local_offset, 8, FALSE);
2250     proto_item_set_text(DETH_header_item, "%s", "DETH - Datagram Extended Transport Header");
2251     DETH_header_tree = proto_item_add_subtree(DETH_header_item, ett_deth);
2252
2253     proto_tree_add_item(DETH_header_tree, hf_infiniband_queue_key,                  tvb, local_offset, 4, FALSE); local_offset+=4;
2254     proto_tree_add_item(DETH_header_tree, hf_infiniband_reserved8_DETH,             tvb, local_offset, 1, FALSE); local_offset+=1;
2255     proto_tree_add_item(DETH_header_tree, hf_infiniband_source_qp,                  tvb, local_offset, 3, FALSE);
2256     pinfo->srcport = tvb_get_ntoh24(tvb, local_offset); local_offset+=3;
2257
2258     *offset = local_offset;
2259 }
2260
2261 /* Parse RETH - RDMA Extended Transport Header
2262 * IN: parentTree to add the dissection to - in this code the all_headers_tree
2263 * IN: tvb - the data buffer from wireshark
2264 * IN/OUT: The current and updated offset */
2265 static void
2266 parse_RETH(proto_tree * parentTree, tvbuff_t *tvb, gint *offset)
2267 {
2268     gint local_offset = *offset;
2269     /* RETH - RDMA Extended Transport Header */
2270     proto_tree *RETH_header_tree = NULL;
2271     proto_item *RETH_header_item = NULL;
2272
2273     RETH_header_item = proto_tree_add_item(parentTree, hf_infiniband_RETH, tvb, local_offset, 16, FALSE);
2274     proto_item_set_text(RETH_header_item, "%s", "RETH - RDMA Extended Transport Header");
2275     RETH_header_tree = proto_item_add_subtree(RETH_header_item, ett_reth);
2276
2277     proto_tree_add_item(RETH_header_tree, hf_infiniband_virtual_address,                tvb, local_offset, 8, FALSE); local_offset+=8;
2278     proto_tree_add_item(RETH_header_tree, hf_infiniband_remote_key,                     tvb, local_offset, 4, FALSE); local_offset+=4;
2279     proto_tree_add_item(RETH_header_tree, hf_infiniband_dma_length,                     tvb, local_offset, 4, FALSE); local_offset+=4;
2280
2281     *offset = local_offset;
2282 }
2283
2284 /* Parse AtomicETH - Atomic Extended Transport Header
2285 * IN: parentTree to add the dissection to - in this code the all_headers_tree
2286 * IN: tvb - the data buffer from wireshark
2287 * IN/OUT: The current and updated offset */
2288 static void
2289 parse_ATOMICETH(proto_tree * parentTree, tvbuff_t *tvb, gint *offset)
2290 {
2291     gint local_offset = *offset;
2292     /* AtomicETH - Atomic Extended Transport Header */
2293     proto_tree *ATOMICETH_header_tree = NULL;
2294     proto_item *ATOMICETH_header_item = NULL;
2295
2296     ATOMICETH_header_item = proto_tree_add_item(parentTree, hf_infiniband_AtomicETH, tvb, local_offset, 28, FALSE);
2297     proto_item_set_text(ATOMICETH_header_item, "%s", "AtomicETH - Atomic Extended Transport Header");
2298     ATOMICETH_header_tree = proto_item_add_subtree(ATOMICETH_header_item, ett_atomiceth);
2299
2300     proto_tree_add_item(ATOMICETH_header_tree, hf_infiniband_virtual_address,               tvb, local_offset, 8, FALSE); local_offset+=8;
2301     proto_tree_add_item(ATOMICETH_header_tree, hf_infiniband_remote_key,                    tvb, local_offset, 4, FALSE); local_offset+=4;
2302     proto_tree_add_item(ATOMICETH_header_tree, hf_infiniband_swap_or_add_data,              tvb, local_offset, 8, FALSE); local_offset+=8;
2303     proto_tree_add_item(ATOMICETH_header_tree, hf_infiniband_compare_data,                  tvb, local_offset, 8, FALSE); local_offset+=8;
2304     *offset = local_offset;
2305 }
2306
2307 /* Parse AETH - ACK Extended Transport Header
2308 * IN: parentTree to add the dissection to - in this code the all_headers_tree
2309 * IN: tvb - the data buffer from wireshark
2310 * IN/OUT: The current and updated offset */
2311 static void
2312 parse_AETH(proto_tree * parentTree, tvbuff_t *tvb, gint *offset)
2313 {
2314     gint local_offset = *offset;
2315     /* AETH - ACK Extended Transport Header */
2316     proto_tree *AETH_header_tree = NULL;
2317     proto_item *AETH_header_item = NULL;
2318
2319     AETH_header_item = proto_tree_add_item(parentTree, hf_infiniband_AETH, tvb, local_offset, 4, FALSE);
2320     proto_item_set_text(AETH_header_item, "%s", "AETH - ACK Extended Transport Header");
2321     AETH_header_tree = proto_item_add_subtree(AETH_header_item, ett_aeth);
2322
2323     proto_tree_add_item(AETH_header_tree, hf_infiniband_syndrome,                       tvb, local_offset, 1, FALSE); local_offset+=1;
2324     proto_tree_add_item(AETH_header_tree, hf_infiniband_message_sequence_number,        tvb, local_offset, 3, FALSE); local_offset+=3;
2325
2326     *offset = local_offset;
2327 }
2328
2329 /* Parse AtomicAckEth - Atomic ACK Extended Transport Header
2330 * IN: parentTree to add the dissection to - in this code the all_headers_tree
2331 * IN: tvb - the data buffer from wireshark
2332 * IN/OUT: The current and updated offset */
2333 static void
2334 parse_ATOMICACKETH(proto_tree * parentTree, tvbuff_t *tvb, gint *offset)
2335 {
2336     gint local_offset = *offset;
2337     /* AtomicAckEth - Atomic ACK Extended Transport Header */
2338     proto_tree *ATOMICACKETH_header_tree = NULL;
2339     proto_item *ATOMICACKETH_header_item = NULL;
2340
2341     ATOMICACKETH_header_item = proto_tree_add_item(parentTree, hf_infiniband_AtomicAckETH, tvb, local_offset, 8, FALSE);
2342     proto_item_set_text(ATOMICACKETH_header_item, "%s", "ATOMICACKETH - Atomic ACK Extended Transport Header");
2343     ATOMICACKETH_header_tree = proto_item_add_subtree(ATOMICACKETH_header_item, ett_atomicacketh);
2344     proto_tree_add_item(ATOMICACKETH_header_tree, hf_infiniband_original_remote_data,   tvb, local_offset, 8, FALSE); local_offset+=8;
2345     *offset = local_offset;
2346 }
2347
2348 /* Parse IMMDT - Immediate Data Extended Transport Header
2349 * IN: parentTree to add the dissection to - in this code the all_headers_tree
2350 * IN: tvb - the data buffer from wireshark
2351 * IN/OUT: The current and updated offset */
2352 static void
2353 parse_IMMDT(proto_tree * parentTree, tvbuff_t *tvb, gint *offset)
2354 {
2355     gint local_offset = *offset;
2356     /* IMMDT - Immediate Data Extended Transport Header */
2357     proto_tree *IMMDT_header_tree = NULL;
2358     proto_item *IMMDT_header_item = NULL;
2359
2360     IMMDT_header_item = proto_tree_add_item(parentTree, hf_infiniband_IMMDT, tvb, local_offset, 4, FALSE);
2361     proto_item_set_text(IMMDT_header_item, "%s", "IMMDT - Immediate Data Extended Transport Header");
2362     IMMDT_header_tree = proto_item_add_subtree(IMMDT_header_item, ett_immdt);
2363     proto_tree_add_item(IMMDT_header_tree, hf_infiniband_IMMDT, tvb, local_offset, 4, FALSE); local_offset+=4;
2364     *offset = local_offset;
2365 }
2366
2367 /* Parse IETH - Invalidate Extended Transport Header
2368 * IN: parentTree to add the dissection to - in this code the all_headers_tree
2369 * IN: tvb - the data buffer from wireshark
2370 * IN/OUT: The current and updated offset */
2371 static void
2372 parse_IETH(proto_tree * parentTree, tvbuff_t *tvb, gint *offset)
2373 {
2374     gint local_offset = *offset;
2375     /* IETH - Invalidate Extended Transport Header */
2376     proto_tree *IETH_header_tree = NULL;
2377     proto_item *IETH_header_item = NULL;
2378
2379     IETH_header_item = proto_tree_add_item(parentTree, hf_infiniband_IETH, tvb, local_offset, 4, FALSE);
2380     proto_item_set_text(IETH_header_item, "%s", "IETH - Invalidate Extended Transport Header");
2381     IETH_header_tree = proto_item_add_subtree(IETH_header_item, ett_ieth);
2382
2383     proto_tree_add_item(IETH_header_tree, hf_infiniband_IETH,   tvb, local_offset, 4, FALSE); local_offset+=4;
2384
2385     *offset = local_offset;
2386 }
2387
2388 /* Parse Payload - Packet Payload / Invariant CRC / Variant CRC
2389 * IN: parentTree to add the dissection to - in this code the all_headers_tree
2390 * IN: pinfo - packet info from wireshark
2391 * IN: tvb - the data buffer from wireshark
2392 * IN/OUT: offset - The current and updated offset
2393 * IN: length - Length of Payload */
2394 static void parse_PAYLOAD(proto_tree *parentTree, packet_info *pinfo, tvbuff_t *tvb, gint *offset, gint length)
2395 {
2396     gint local_offset = *offset;
2397     /* Payload - Packet Payload */
2398     proto_tree *PAYLOAD_header_tree = NULL;
2399     proto_item *PAYLOAD_header_item = NULL;
2400     guint8 management_class;
2401     tvbuff_t *volatile next_tvb;
2402     gint            captured_length, reported_length;
2403     guint16 etype, reserved;
2404     const char      *saved_proto;
2405     volatile gboolean   dissector_found = FALSE;
2406
2407     if(!tvb_bytes_exist(tvb, *offset, length)) /* previously consumed bytes + offset was all the data - none or corrupt payload */
2408     {
2409         col_set_str(pinfo->cinfo, COL_INFO, "Invalid Packet Length from LRH! [Malformed Packet]");
2410         col_set_fence(pinfo->cinfo, COL_INFO);
2411         return;
2412     }
2413
2414     /* management datagrams are determined by the source/destination QPs */
2415     if (pinfo->srcport == 0 || pinfo->srcport == 1 || pinfo->destport == 0 || pinfo->destport == 1)    /* management datagram */
2416     {
2417         management_class =  tvb_get_guint8(tvb, (*offset) + 1);
2418
2419         if(((management_class >= (guint8)VENDOR_1_START) && (management_class <= (guint8)VENDOR_1_END))
2420             || ((management_class >= (guint8)VENDOR_2_START) && (management_class <= (guint8)VENDOR_2_END)))
2421         {
2422             /* parse vendor specific */
2423             parse_VENDOR_MANAGEMENT(parentTree, tvb, offset);
2424         }
2425         else if((management_class >= (guint8)APPLICATION_START) && (management_class <= (guint8)APPLICATION_END))
2426         {
2427             /* parse application specific */
2428             parse_APPLICATION_MANAGEMENT(parentTree, tvb, offset);
2429         }
2430         else if(((management_class == (guint8)0x00) || (management_class == (guint8)0x02))
2431             || ((management_class >= (guint8)0x50) && (management_class <= (guint8)0x80))
2432             || ((management_class >= (guint8)0x82)))
2433         {
2434             /* parse reserved classes */
2435             parse_RESERVED_MANAGEMENT(parentTree, tvb, offset);
2436         }
2437         else /* we have a normal management_class */
2438         {
2439             switch(management_class)
2440             {
2441                 case SUBN_LID_ROUTED:
2442                     /* parse subn man lid routed */
2443                     parse_SUBN_LID_ROUTED(parentTree, pinfo, tvb, &local_offset);
2444                 break;
2445                 case SUBN_DIRECTED_ROUTE:
2446                     /* parse subn directed route */
2447                     parse_SUBN_DIRECTED_ROUTE(parentTree, pinfo, tvb, &local_offset);
2448                 break;
2449                 case SUBNADMN:
2450                     /* parse sub admin */
2451                     parse_SUBNADMN(parentTree, pinfo, tvb, &local_offset);
2452                 break;
2453                 case PERF:
2454                     /* parse performance */
2455                     parse_PERF(parentTree, tvb, pinfo, &local_offset);
2456                 break;
2457                 case BM:
2458                     /* parse baseboard mgmt */
2459                     parse_BM(parentTree, tvb, &local_offset);
2460                 break;
2461                 case DEV_MGT:
2462                     /* parse device management */
2463                     parse_DEV_MGT(parentTree, tvb, &local_offset);
2464                 break;
2465                 case COM_MGT:
2466                     /* parse communication management */
2467                     parse_COM_MGT(parentTree, pinfo, tvb, &local_offset);
2468                 break;
2469                 case SNMP:
2470                     /* parse snmp tunneling */
2471                     parse_SNMP(parentTree, tvb, &local_offset);
2472                 break;
2473                 default:
2474                     break;
2475             }
2476         }
2477     }
2478     else /* Normal Data Packet - Parse as such */
2479     {
2480
2481         /* Calculation for Payload:
2482         * (tvb_length) Length of entire packet - (local_offset) Starting byte of Payload Data
2483         * offset addition is more complex for the payload.
2484         * We need the total length of the packet, - length of previous headers, + offset where payload started.
2485         * We also need  to reserve 6 bytes for the CRCs which are not actually part of the payload.  */
2486
2487         etype = tvb_get_ntohs(tvb, local_offset);
2488         reserved =  tvb_get_ntohs(tvb, local_offset + 2);
2489
2490         /* try to recognize whether or not this is a Mellanox EoIB packet by the
2491            transport type and the 4 first bits of the payload */
2492         if      (pref_dissect_eoib &&
2493                  transport_type == TRANSPORT_UD &&
2494                  tvb_get_bits8(tvb, local_offset*8, 4) == 0xC) {
2495             dissector_found = parse_EoIB(parentTree, tvb, local_offset, pinfo);
2496         }
2497
2498         /* IBA packet data could be anything in principle, however it is common
2499          * practice to carry non-IBA data encapsulated with an EtherType header,
2500          * similar to the RWH header. There is no way to identify these frames
2501          * positively.
2502          *
2503          * If the appropriate option is set in protocol preferences,
2504          * We see if the first few bytes look like an EtherType header, and if so
2505          * call the appropriate dissector. If not we call the "data" dissector.
2506          */
2507         if (!dissector_found && pref_identify_iba_payload && reserved == 0) {
2508             void *pd_save;
2509
2510             /* Get the captured length and reported length of the data
2511                after the Ethernet type. */
2512             captured_length = tvb_length_remaining(tvb, local_offset+4);
2513             reported_length = tvb_reported_length_remaining(tvb,
2514                                     local_offset+4);
2515
2516             next_tvb = tvb_new_subset(tvb, local_offset+4, captured_length,
2517                           reported_length);
2518
2519             pinfo->ethertype = etype;
2520
2521             /* Look for sub-dissector, and call it if found.
2522                Catch exceptions, so that if the reported length of "next_tvb"
2523                was reduced by some dissector before an exception was thrown,
2524                we can still put in an item for the trailer. */
2525             saved_proto = pinfo->current_proto;
2526             pd_save = pinfo->private_data;
2527
2528             TRY {
2529                 dissector_found = dissector_try_uint(ethertype_dissector_table,
2530                                      etype, next_tvb, pinfo, top_tree);
2531             }
2532             CATCH(BoundsError) {
2533                 /* Somebody threw BoundsError, which means that:
2534
2535                 1) a dissector was found, so we don't need to
2536                 dissect the payload as data or update the
2537                 protocol or info columns;
2538
2539                 2) dissecting the payload found that the packet was
2540                 cut off by a snapshot length before the end of
2541                 the payload.  The trailer comes after the payload,
2542                 so *all* of the trailer is cut off, and we'll
2543                 just get another BoundsError if we add the trailer.
2544
2545                 Therefore, we just rethrow the exception so it gets
2546                 reported; we don't dissect the trailer or do anything
2547                 else. */
2548                 RETHROW;
2549             }
2550             CATCH(OutOfMemoryError) {
2551                 RETHROW;
2552             }
2553             CATCH_ALL {
2554                 /* Somebody threw an exception other than BoundsError, which
2555                    means that a dissector was found, so we don't need to
2556                    dissect the payload as data or update the protocol or info
2557                    columns.  We just show the exception and then drive on
2558                    to show the trailer, after noting that a dissector was
2559                    found and restoring the protocol value that was in effect
2560                    before we called the subdissector. */
2561
2562                 /*  Restore the private_data structure in case one of the
2563                  *  called dissectors modified it (and, due to the exception,
2564                  *  was unable to restore it).
2565                  */
2566                 pinfo->private_data = pd_save;
2567
2568                 show_exception(next_tvb, pinfo, top_tree, EXCEPT_CODE, GET_MESSAGE);
2569                 dissector_found = TRUE;
2570                 pinfo->current_proto = saved_proto;
2571             }
2572             ENDTRY;
2573
2574             if (dissector_found) {
2575                 /* now create payload entry to show Ethertype */
2576                 PAYLOAD_header_item = proto_tree_add_item(parentTree, hf_infiniband_payload, tvb, local_offset, tvb_reported_length_remaining(tvb, local_offset)-6, FALSE);
2577                 proto_item_set_text(PAYLOAD_header_item, "%s", "IBA Payload - appears to be EtherType encapsulated");
2578                 PAYLOAD_header_tree = proto_item_add_subtree(PAYLOAD_header_item, ett_payload);
2579                 proto_tree_add_uint(PAYLOAD_header_tree, hf_infiniband_etype, tvb,
2580                             local_offset, 2,  tvb_get_ntohs(tvb, local_offset));
2581
2582                 local_offset += 2;
2583
2584                 proto_tree_add_uint(PAYLOAD_header_tree, hf_infiniband_reserved16_RWH, tvb,
2585                             local_offset, 2, tvb_get_ntohs(tvb, local_offset));
2586
2587             }
2588
2589         }
2590
2591         captured_length = tvb_length_remaining(tvb, local_offset);
2592         reported_length = tvb_reported_length_remaining(tvb,
2593                                 local_offset);
2594
2595         if (reported_length >= 6)
2596             reported_length -= 6;
2597         if (captured_length > reported_length)
2598             captured_length = reported_length;
2599
2600         next_tvb = tvb_new_subset(tvb, local_offset,
2601                       captured_length,
2602                       reported_length);
2603
2604         /* Try any heuristic dissectors that requested a chance to try and dissect IB payloads */
2605         if (!dissector_found) {
2606             dissector_found = dissector_try_heuristic(heur_dissectors_payload, next_tvb, pinfo, parentTree);
2607         }
2608
2609         if (!dissector_found) {
2610             /* No sub-dissector found.
2611                Label rest of packet as "Data" */
2612             call_dissector(data_handle, next_tvb, pinfo, top_tree);
2613
2614         }
2615
2616
2617         /*parse_RWH(parentTree, tvb, &local_offset, pinfo);*/
2618
2619         /* Will contain ICRC and VCRC = 4+2 */
2620         local_offset = tvb_reported_length(tvb) - 6;
2621     }
2622
2623     *offset = local_offset;
2624 }
2625
2626 /* Parse VENDOR - Parse a vendor specific or unknown header sequence
2627 * IN: parentTree to add the dissection to - in this code the all_headers_tree
2628 * IN: tvb - the data buffer from wireshark
2629 * IN/OUT: The current and updated offset */
2630 static void parse_VENDOR(proto_tree * parentTree, tvbuff_t *tvb, gint *offset)
2631 {
2632     gint local_offset = *offset;
2633     proto_tree *VENDOR_header_tree = NULL;
2634     proto_item *VENDOR_header_item = NULL;
2635
2636     VENDOR_header_item = proto_tree_add_item(parentTree, hf_infiniband_vendor, tvb, local_offset, 4, FALSE);
2637     proto_item_set_text(VENDOR_header_item, "%s", "Vendor Specific or Unknown Header Sequence");
2638     VENDOR_header_tree = proto_item_add_subtree(VENDOR_header_item, ett_vendor);
2639     proto_tree_add_item(VENDOR_header_tree, hf_infiniband_vendor,   tvb, local_offset, -1, FALSE);
2640     *offset = local_offset;
2641 }
2642
2643 /* Parse IPv6 - Parse an IPv6 Packet
2644 * IN: parentTree to add the dissection to - in this code the all_headers_tree
2645 * IN: tvb - the data buffer from wireshark
2646 * IN/OUT: The current and updated offset
2647 * IN: pinfo - packet info from wireshark */
2648 static void parse_IPvSix(proto_tree *parentTree, tvbuff_t *tvb, gint *offset, packet_info *pinfo)
2649 {
2650     tvbuff_t *ipv6_tvb;
2651
2652     /* (- 2) for VCRC which lives at the end of the packet   */
2653     ipv6_tvb = tvb_new_subset(tvb, *offset,
2654                   tvb_length_remaining(tvb, *offset) - 2,
2655                   tvb_reported_length_remaining(tvb, *offset) - 2);
2656     call_dissector(ipv6_handle, ipv6_tvb, pinfo, parentTree);
2657     *offset = tvb_reported_length(tvb) - 2;
2658
2659     /* Display the VCRC */
2660     proto_tree_add_item(parentTree, hf_infiniband_variant_crc,  tvb, *offset, 2, FALSE);
2661 }
2662
2663 /* Parse EtherType - Parse a generic IP packaet with an EtherType of IP or ARP
2664 * IN: parentTree to add the dissection to - in this code the all_headers_tree
2665 * IN: tvb - the data buffer from wireshark
2666 * IN/OUT: The current and updated offset
2667 * IN: pinfo - packet info from wireshark */
2668 static void parse_RWH(proto_tree *ah_tree, tvbuff_t *tvb, gint *offset, packet_info *pinfo)
2669 {
2670     guint16 ether_type;
2671     tvbuff_t *next_tvb;
2672
2673     /* RWH - Raw Header */
2674     proto_tree *RWH_header_tree = NULL;
2675     proto_item *RWH_header_item = NULL;
2676
2677     gint captured_length, reported_length;
2678
2679     RWH_header_item = proto_tree_add_item(ah_tree, hf_infiniband_RWH, tvb, *offset, 4, FALSE);
2680     proto_item_set_text(RWH_header_item, "%s", "RWH - Raw Header");
2681     RWH_header_tree = proto_item_add_subtree(RWH_header_item, ett_rwh);
2682
2683     proto_tree_add_item(RWH_header_tree, hf_infiniband_reserved16_RWH, tvb,
2684             *offset, 2, FALSE);
2685
2686     *offset += 2;
2687
2688     ether_type = tvb_get_ntohs(tvb, *offset);
2689     proto_tree_add_uint(RWH_header_tree, hf_infiniband_etype, tvb, *offset, 2,
2690                         ether_type);
2691     *offset += 2;
2692
2693     /* Get the captured length and reported length of the data
2694      * after the Ethernet type. */
2695     captured_length = tvb_length_remaining(tvb, *offset);
2696     reported_length = tvb_reported_length_remaining(tvb, *offset);
2697
2698     /* Construct a tvbuff for the payload after the Ethernet type,
2699      * not including the FCS. */
2700     if (captured_length >= 0 && reported_length >= 0) {
2701         if (reported_length >= 2)
2702             reported_length -= 2;
2703         if (captured_length > reported_length)
2704             captured_length = reported_length;
2705     }
2706
2707     next_tvb = tvb_new_subset(tvb, *offset, captured_length, reported_length);
2708     if (!dissector_try_uint(ethertype_dissector_table, ether_type,
2709             next_tvb, pinfo, top_tree))
2710        call_dissector(data_handle, next_tvb, pinfo, top_tree);
2711
2712     *offset = tvb_reported_length(tvb) - 2;
2713     /* Display the VCRC */
2714     proto_tree_add_item(ah_tree, hf_infiniband_variant_crc, tvb, *offset, 2, FALSE);
2715 }
2716
2717
2718 /* Parse a Mellanox EoIB Encapsulation Header and the associated Ethernet frame
2719 * IN: parentTree to add the dissection to - in this code the all_headers_tree
2720 * IN: tvb - the data buffer from wireshark
2721 * IN: The current offset
2722 * IN: pinfo - packet info from wireshark */
2723 static gboolean parse_EoIB(proto_tree *tree, tvbuff_t *tvb, gint offset, packet_info *pinfo)
2724 {
2725     proto_item *header_item;
2726     proto_tree *header_subtree;
2727     gboolean ms;
2728     gint8 seg_offset;
2729     tvbuff_t *encap_tvb;
2730     /* the encapsulated eoib size (including the header!) is remaining length-6 bytes of CRC */
2731     int encap_size = tvb_reported_length_remaining(tvb, offset) - 6;
2732
2733     if (encap_size < 4) {
2734         /* not even large enough to contain the eoib encap header. error! */
2735         return FALSE;
2736     }
2737
2738     encap_tvb = tvb_new_subset(tvb, offset + 4, tvb_length_remaining(tvb, offset + 4), encap_size - 4);
2739
2740     header_item = proto_tree_add_item(tree, hf_infiniband_EOIB, tvb, offset, 4, FALSE);
2741     header_subtree = proto_item_add_subtree(header_item, ett_eoib);
2742
2743     proto_tree_add_item(header_subtree, hf_infiniband_ver, tvb, offset, 2, FALSE);
2744     proto_tree_add_item(header_subtree, hf_infiniband_tcp_chk, tvb, offset, 2, FALSE);
2745     proto_tree_add_item(header_subtree, hf_infiniband_ip_chk, tvb, offset, 2, FALSE);
2746     proto_tree_add_item(header_subtree, hf_infiniband_fcs, tvb, offset, 2, FALSE);
2747
2748     ms = tvb_get_bits8(tvb, (offset + 1)*8 + 2, 1);
2749     seg_offset = tvb_get_bits8(tvb, (offset + 1)*8 + 3, 5);
2750
2751     proto_tree_add_item(header_subtree, hf_infiniband_ms, tvb, offset, 2, FALSE);
2752     proto_tree_add_item(header_subtree, hf_infiniband_seg_off, tvb, offset, 2, FALSE); offset += 2;
2753     proto_tree_add_item(header_subtree, hf_infiniband_seg_id, tvb, offset, 2, FALSE); offset += 2;
2754
2755     if (seg_offset || ms) {
2756         /* this is a fragment of an encapsulated Ethernet jumbo frame, parse as data */
2757         call_dissector(data_handle, encap_tvb, pinfo, top_tree);
2758     } else {
2759         /* non-fragmented frames can be fully parsed */
2760         call_dissector(eth_handle, encap_tvb, pinfo, top_tree);
2761     }
2762
2763     return TRUE;
2764 }
2765
2766
2767 /* Parse Subnet Management (LID Routed)
2768 * IN: parentTree to add the dissection to
2769 * IN: pinfo - packet info from wireshark
2770 * IN: tvb - the data buffer from wireshark
2771 * IN/OUT: The current and updated offset */
2772 static void parse_SUBN_LID_ROUTED(proto_tree *parentTree, packet_info *pinfo, tvbuff_t *tvb, gint *offset)
2773 {
2774     /* Parse the Common MAD Header */
2775     MAD_Data MadData;
2776     gint local_offset;
2777     proto_tree *SUBN_LID_ROUTED_header_tree = NULL;
2778     proto_item *SUBN_LID_ROUTED_header_item = NULL;
2779
2780     if(!parse_MAD_Common(parentTree, tvb, offset, &MadData))
2781     {
2782         /* TODO: Mark Corrupt Packet - Not enough bytes exist for at least the Common MAD header which is present in all MAD packets */
2783         return;
2784     }
2785
2786     local_offset = *offset;
2787
2788     /* local_offset - 24 here because when we come out of parse_MAD_Common, the offset it sitting at the data section. */
2789     SUBN_LID_ROUTED_header_item = proto_tree_add_item(parentTree, hf_infiniband_SMP_LID, tvb, local_offset - 24, 256, FALSE);
2790     proto_item_set_text(SUBN_LID_ROUTED_header_item, "%s", "SMP (LID Routed) ");
2791     SUBN_LID_ROUTED_header_tree = proto_item_add_subtree(SUBN_LID_ROUTED_header_item, ett_subn_lid_routed);
2792     proto_tree_add_item(SUBN_LID_ROUTED_header_tree, hf_infiniband_m_key,           tvb, local_offset, 8, FALSE); local_offset +=8;
2793     proto_tree_add_item(SUBN_LID_ROUTED_header_tree, hf_infiniband_reserved256,     tvb, local_offset, 32, FALSE); local_offset +=32;
2794
2795     label_SUBM_Method(SUBN_LID_ROUTED_header_item, &MadData, pinfo);
2796     label_SUBM_Attribute(SUBN_LID_ROUTED_header_item, &MadData, pinfo);
2797
2798     /* Try to do the detail parse of the attribute.  If there is an error, or the attribute is unknown, we'll just highlight the generic data. */
2799     if(!parse_SUBM_Attribute(SUBN_LID_ROUTED_header_tree, tvb, &local_offset, &MadData))
2800     {
2801         proto_tree_add_item(SUBN_LID_ROUTED_header_tree, hf_infiniband_smp_data,    tvb, local_offset, 64, FALSE); local_offset +=64;
2802     }
2803
2804     proto_tree_add_item(SUBN_LID_ROUTED_header_tree, hf_infiniband_reserved1024,    tvb, local_offset, 128, FALSE); local_offset +=128;
2805     *offset = local_offset;
2806 }
2807
2808 /* Parse Subnet Management (Directed Route)
2809 * IN: parentTree to add the dissection to
2810 * IN: tvb - the data buffer from wireshark
2811 * IN/OUT: The current and updated offset */
2812 static void parse_SUBN_DIRECTED_ROUTE(proto_tree *parentTree, packet_info *pinfo, tvbuff_t *tvb, gint *offset)
2813 {
2814     /* Parse the Common MAD Header */
2815     MAD_Data MadData;
2816     gint local_offset;
2817     proto_tree *SUBN_DIRECTED_ROUTE_header_tree = NULL;
2818     proto_item *SUBN_DIRECTED_ROUTE_header_item = NULL;
2819
2820     if(!parse_MAD_Common(parentTree, tvb, offset, &MadData))
2821     {
2822         /* TODO: Mark Corrupt Packet - Not enough bytes exist for at least the Common MAD header which is present in all MAD packets */
2823         return;
2824     }
2825
2826     local_offset = *offset;
2827
2828     /* local_offset - 24 here because when we come out of parse_MAD_Common, the offset it sitting at the data section.
2829     * We need to go backwards because this particular SMP uses the class specific portion of the Common MAD Header */
2830     SUBN_DIRECTED_ROUTE_header_item = proto_tree_add_item(parentTree, hf_infiniband_SMP_DIRECTED, tvb, local_offset - 24, 256, FALSE);
2831     proto_item_set_text(SUBN_DIRECTED_ROUTE_header_item, "%s", "SMP (Directed Route) ");
2832     SUBN_DIRECTED_ROUTE_header_tree = proto_item_add_subtree(SUBN_DIRECTED_ROUTE_header_item, ett_subn_directed_route);
2833
2834     label_SUBM_Method(SUBN_DIRECTED_ROUTE_header_item, &MadData, pinfo);
2835     label_SUBM_Attribute(SUBN_DIRECTED_ROUTE_header_item, &MadData, pinfo);
2836
2837     /* Place us at offset 4, the "D" Bit (Direction bit for Directed Route SMPs) */
2838     local_offset -= 20;
2839     proto_tree_add_item(SUBN_DIRECTED_ROUTE_header_tree, hf_infiniband_d,               tvb, local_offset, 1, FALSE);
2840     proto_tree_add_item(SUBN_DIRECTED_ROUTE_header_tree, hf_infiniband_smp_status,      tvb, local_offset, 2, FALSE); local_offset +=2;
2841     proto_tree_add_item(SUBN_DIRECTED_ROUTE_header_tree, hf_infiniband_hop_pointer,     tvb, local_offset, 1, FALSE); local_offset +=1;
2842     proto_tree_add_item(SUBN_DIRECTED_ROUTE_header_tree, hf_infiniband_hop_count,       tvb, local_offset, 1, FALSE); local_offset +=1;
2843     local_offset += 16; /* Skip over the rest of the Common MAD Header... It's already dissected by parse_MAD_Common */
2844     proto_tree_add_item(SUBN_DIRECTED_ROUTE_header_tree, hf_infiniband_m_key,           tvb, local_offset, 8, FALSE); local_offset +=8;
2845     proto_tree_add_item(SUBN_DIRECTED_ROUTE_header_tree, hf_infiniband_dr_slid,         tvb, local_offset, 2, FALSE); local_offset +=2;
2846     proto_tree_add_item(SUBN_DIRECTED_ROUTE_header_tree, hf_infiniband_dr_dlid,         tvb, local_offset, 2, FALSE); local_offset +=2;
2847     proto_tree_add_item(SUBN_DIRECTED_ROUTE_header_tree, hf_infiniband_reserved28,      tvb, local_offset, 28, FALSE); local_offset +=28;
2848
2849     /* Try to do the detail parse of the attribute.  If there is an error, or the attribute is unknown, we'll just highlight the generic data. */
2850     if(!parse_SUBM_Attribute(SUBN_DIRECTED_ROUTE_header_tree, tvb, &local_offset, &MadData))
2851     {
2852         proto_tree_add_item(SUBN_DIRECTED_ROUTE_header_tree, hf_infiniband_smp_data,    tvb, local_offset, 64, FALSE); local_offset +=64;
2853     }
2854
2855     proto_tree_add_item(SUBN_DIRECTED_ROUTE_header_tree, hf_infiniband_initial_path,        tvb, local_offset, 64, FALSE); local_offset +=64;
2856     proto_tree_add_item(SUBN_DIRECTED_ROUTE_header_tree, hf_infiniband_return_path,     tvb, local_offset, 64, FALSE); local_offset +=64;
2857     *offset = local_offset;
2858 }
2859
2860 /* Parse Subnet Administration
2861 * IN: parentTree to add the dissection to
2862 * IN: pinfo - packet info from wireshark
2863 * IN: tvb - the data buffer from wireshark
2864 * IN/OUT: The current and updated offset */
2865 static void parse_SUBNADMN(proto_tree *parentTree, packet_info *pinfo, tvbuff_t *tvb, gint *offset)
2866 {
2867     /* Parse the Common MAD Header */
2868     MAD_Data MadData;
2869     gint local_offset;
2870     proto_tree *SUBNADMN_header_tree = NULL;
2871     proto_item *SUBNADMN_header_item = NULL;
2872
2873     if(!parse_MAD_Common(parentTree, tvb, offset, &MadData))
2874     {
2875         /* TODO: Mark Corrupt Packet - Not enough bytes exist for at least the Common MAD header which is present in all MAD packets */
2876         return;
2877     }
2878     if(!parse_RMPP(parentTree, tvb, offset))
2879     {
2880         /* TODO: Mark Corrupt Packet */
2881         return;
2882     }
2883     local_offset = *offset;
2884
2885     SUBNADMN_header_item = proto_tree_add_item(parentTree, hf_infiniband_SA, tvb, local_offset - 36, 256, FALSE);
2886     proto_item_set_text(SUBNADMN_header_item, "%s", "SMA");
2887     SUBNADMN_header_tree = proto_item_add_subtree(SUBNADMN_header_item, ett_subnadmin);
2888
2889     proto_tree_add_item(SUBNADMN_header_tree, hf_infiniband_sm_key,             tvb, local_offset, 8, FALSE); local_offset+=8;
2890     proto_tree_add_item(SUBNADMN_header_tree, hf_infiniband_attribute_offset,   tvb, local_offset, 2, FALSE); local_offset+=4;
2891     proto_tree_add_item(SUBNADMN_header_tree, hf_infiniband_reserved16,         tvb, local_offset, 2, FALSE); local_offset+=4;
2892     proto_tree_add_item(SUBNADMN_header_tree, hf_infiniband_component_mask,     tvb, local_offset, 8, FALSE); local_offset+=8;
2893
2894     label_SUBA_Method(SUBNADMN_header_item, &MadData, pinfo);
2895     label_SUBA_Attribute(SUBNADMN_header_item, &MadData, pinfo);
2896
2897     if(!parse_SUBA_Attribute(SUBNADMN_header_tree, tvb, &local_offset, &MadData))
2898     {
2899         proto_tree_add_item(SUBNADMN_header_tree, hf_infiniband_subnet_admin_data,  tvb, local_offset, 200, FALSE); local_offset+=200;
2900     }
2901     *offset = local_offset;
2902 }
2903
2904 /* Parse Performance Management
2905 * IN: parentTree to add the dissection to
2906 * IN: tvb - the data buffer from wireshark
2907 * IN: pinfo - the pinfo struct from wireshark
2908 * IN/OUT: The current and updated offset */
2909 static void parse_PERF(proto_tree *parentTree, tvbuff_t *tvb, packet_info *pinfo, gint *offset)
2910 {
2911     /* Parse the Common MAD Header */
2912     MAD_Data MadData;
2913     gint local_offset;
2914     proto_item *PERF_header_item = NULL;
2915
2916     if(!parse_MAD_Common(parentTree, tvb, offset, &MadData))
2917     {
2918         /* TODO: Mark Corrupt Packet - Not enough bytes exist for at least the Common MAD header which is present in all MAD packets */
2919         return;
2920     }
2921
2922     local_offset = *offset; /* offset now points to the start of the MAD data field */
2923
2924     switch (MadData.attributeID) {
2925         case ATTR_PORT_COUNTERS:
2926             parse_PERF_PortCounters(parentTree, tvb, pinfo, &local_offset);
2927             break;
2928         case ATTR_PORT_COUNTERS_EXT:
2929             parse_PERF_PortCountersExtended(parentTree, tvb, pinfo, &local_offset);
2930             break;
2931         default:
2932             PERF_header_item = proto_tree_add_item(parentTree, hf_infiniband_smp_data, tvb, local_offset, MAD_DATA_SIZE, FALSE); local_offset += MAD_DATA_SIZE;
2933             proto_item_set_text(PERF_header_item, "%s", "PERF - Performance Management MAD (Dissector Not Implemented)");
2934             break;
2935     }
2936
2937     *offset = local_offset;
2938 }
2939
2940 /* Parse Baseboard Management
2941 * IN: parentTree to add the dissection to
2942 * IN: tvb - the data buffer from wireshark
2943 * IN/OUT: The current and updated offset */
2944 static void parse_BM(proto_tree *parentTree, tvbuff_t *tvb, gint *offset)
2945 {
2946     /* Parse the Common MAD Header */
2947     MAD_Data MadData;
2948     gint local_offset;
2949     proto_item *PERF_header_item = NULL;
2950
2951     if(!parse_MAD_Common(parentTree, tvb, offset, &MadData))
2952     {
2953         /* TODO: Mark Corrupt Packet - Not enough bytes exist for at least the Common MAD header which is present in all MAD packets */
2954         return;
2955     }
2956     local_offset = *offset;
2957
2958     PERF_header_item = proto_tree_add_item(parentTree, hf_infiniband_smp_data, tvb, local_offset, MAD_DATA_SIZE, FALSE); local_offset += MAD_DATA_SIZE;
2959     proto_item_set_text(PERF_header_item, "%s", "BM - Baseboard Management MAD (Dissector Not Implemented)");
2960     *offset = local_offset;
2961 }
2962
2963 /* Parse Device Management
2964 * IN: parentTree to add the dissection to
2965 * IN: tvb - the data buffer from wireshark
2966 * IN/OUT: The current and updated offset */
2967 static void parse_DEV_MGT(proto_tree *parentTree, tvbuff_t *tvb, gint *offset)
2968 {
2969     /* Parse the Common MAD Header */
2970     MAD_Data MadData;
2971     gint local_offset;
2972     proto_item *PERF_header_item = NULL;
2973
2974     if(!parse_MAD_Common(parentTree, tvb, offset, &MadData))
2975     {
2976         /* TODO: Mark Corrupt Packet - Not enough bytes exist for at least the Common MAD header which is present in all MAD packets */
2977         return;
2978     }
2979     local_offset = *offset;
2980     PERF_header_item = proto_tree_add_item(parentTree, hf_infiniband_smp_data, tvb, local_offset, MAD_DATA_SIZE, FALSE); local_offset += MAD_DATA_SIZE;
2981     proto_item_set_text(PERF_header_item, "%s", "DEV_MGT - Device Management MAD (Dissector Not Implemented)");
2982     *offset = local_offset;
2983 }
2984
2985 /* Parse Communications Management
2986 * IN: parentTree to add the dissection to
2987 * IN: tvb - the data buffer from wireshark
2988 * IN/OUT: The current and updated offset */
2989 static void parse_COM_MGT(proto_tree *parentTree, packet_info *pinfo, tvbuff_t *tvb, gint *offset)
2990 {
2991     MAD_Data MadData;
2992     gint local_offset;
2993     guint32 local_qpn = 0, remote_qpn = 0;
2994     guint8 *local_gid, *remote_gid;
2995     guint32 local_lid, remote_lid;
2996     guint64 serviceid;
2997     const char *label = NULL;
2998     proto_item *CM_header_item = NULL;
2999     proto_tree *CM_header_tree = NULL;
3000     connection_context *connection = NULL; /* we'll use this to store new connections this CM packet is establishing*/
3001     tvbuff_t *next_tvb;
3002
3003     local_gid = ep_alloc(GID_SIZE);
3004     remote_gid = ep_alloc(GID_SIZE);
3005
3006     if(!parse_MAD_Common(parentTree, tvb, offset, &MadData))
3007     {
3008         /* TODO: Mark Corrupt Packet - Not enough bytes exist for at least the Common MAD header which is present in all MAD packets */
3009         return;
3010     }
3011     local_offset = *offset;
3012
3013     CM_header_item = proto_tree_add_item(parentTree, hf_infiniband_smp_data, tvb, local_offset, 140, FALSE);
3014
3015     label = val_to_str(MadData.attributeID, CM_Attributes, "(Unknown CM Attribute)");
3016
3017     proto_item_set_text(CM_header_item, "CM %s", label);
3018     col_clear(pinfo->cinfo, COL_INFO);
3019     col_append_fstr(pinfo->cinfo, COL_INFO, "CM: %s", label);
3020
3021     CM_header_tree = proto_item_add_subtree(CM_header_item, ett_cm);
3022
3023     switch (MadData.attributeID) {
3024         case ATTR_CM_REQ:
3025             proto_tree_add_item(CM_header_tree, hf_cm_req_local_comm_id, tvb, local_offset, 4, FALSE); local_offset += 4;
3026             local_offset += 4;  /* skip reserved */
3027             proto_tree_add_item(CM_header_tree, hf_cm_req_service_id, tvb, local_offset, 8, FALSE);
3028             serviceid = tvb_get_ntoh64(tvb, local_offset); local_offset += 8;
3029             proto_tree_add_item(CM_header_tree, hf_cm_req_local_ca_guid, tvb, local_offset, 8, FALSE); local_offset += 8;
3030             local_offset += 4;  /* skip reserved */
3031             proto_tree_add_item(CM_header_tree, hf_cm_req_local_qkey, tvb, local_offset, 4, FALSE); local_offset += 4;
3032             proto_tree_add_item(CM_header_tree, hf_cm_req_local_qpn, tvb, local_offset, 3, FALSE);
3033             local_qpn = tvb_get_ntoh24(tvb, local_offset); local_offset += 3;
3034             proto_tree_add_item(CM_header_tree, hf_cm_req_respo_res, tvb, local_offset, 1, FALSE); local_offset += 1;
3035             proto_tree_add_item(CM_header_tree, hf_cm_req_local_eecn, tvb, local_offset, 3, FALSE); local_offset += 3;
3036             proto_tree_add_item(CM_header_tree, hf_cm_req_init_depth, tvb, local_offset, 1, FALSE); local_offset += 1;
3037             proto_tree_add_item(CM_header_tree, hf_cm_req_remote_eecn, tvb, local_offset, 3, FALSE); local_offset += 3;
3038             proto_tree_add_item(CM_header_tree, hf_cm_req_remote_cm_resp_to, tvb, local_offset, 1, FALSE);
3039             proto_tree_add_item(CM_header_tree, hf_cm_req_transp_serv_type, tvb, local_offset, 1, FALSE);
3040             proto_tree_add_item(CM_header_tree, hf_cm_req_e2e_flow_ctrl, tvb, local_offset, 1, FALSE); local_offset += 1;
3041             proto_tree_add_item(CM_header_tree, hf_cm_req_start_psn, tvb, local_offset, 3, FALSE); local_offset += 3;
3042             proto_tree_add_item(CM_header_tree, hf_cm_req_local_cm_resp_to, tvb, local_offset, 1, FALSE);
3043             proto_tree_add_item(CM_header_tree, hf_cm_req_retry_count, tvb, local_offset, 1, FALSE); local_offset += 1;
3044             proto_tree_add_item(CM_header_tree, hf_cm_req_pkey, tvb, local_offset, 2, FALSE); local_offset += 2;
3045             proto_tree_add_item(CM_header_tree, hf_cm_req_path_pp_mtu, tvb, local_offset, 1, FALSE);
3046             proto_tree_add_item(CM_header_tree, hf_cm_req_rdc_exists, tvb, local_offset, 1, FALSE);
3047             proto_tree_add_item(CM_header_tree, hf_cm_req_rnr_retry_count, tvb, local_offset, 1, FALSE); local_offset += 1;
3048             proto_tree_add_item(CM_header_tree, hf_cm_req_max_cm_retries, tvb, local_offset, 1, FALSE);
3049             proto_tree_add_item(CM_header_tree, hf_cm_req_srq, tvb, local_offset, 1, FALSE);
3050             local_offset += 1;  /* skip reserved */
3051             proto_tree_add_item(CM_header_tree, hf_cm_req_primary_local_lid, tvb, local_offset, 2, FALSE);
3052             local_lid = tvb_get_ntohs(tvb, local_offset); local_offset += 2;
3053             proto_tree_add_item(CM_header_tree, hf_cm_req_primary_remote_lid, tvb, local_offset, 2, FALSE);
3054             remote_lid = tvb_get_ntohs(tvb, local_offset); local_offset += 2;
3055             proto_tree_add_item(CM_header_tree, hf_cm_req_primary_local_gid, tvb, local_offset, 16, FALSE);
3056             tvb_get_ipv6(tvb, local_offset, (struct e_in6_addr*)local_gid); local_offset += 16;
3057             proto_tree_add_item(CM_header_tree, hf_cm_req_primary_remote_gid, tvb, local_offset, 16, FALSE);
3058             tvb_get_ipv6(tvb, local_offset, (struct e_in6_addr*)remote_gid); local_offset += 16;
3059             proto_tree_add_item(CM_header_tree, hf_cm_req_primary_flow_label, tvb, local_offset, 2, FALSE); local_offset += 2;
3060             local_offset += 1;  /* skip reserved */
3061             proto_tree_add_item(CM_header_tree, hf_cm_req_primary_packet_rate, tvb, local_offset, 1, FALSE); local_offset += 1;
3062             proto_tree_add_item(CM_header_tree, hf_cm_req_primary_traffic_class, tvb, local_offset, 1, FALSE); local_offset += 1;
3063             proto_tree_add_item(CM_header_tree, hf_cm_req_primary_hop_limit, tvb, local_offset, 1, FALSE); local_offset += 1;
3064             proto_tree_add_item(CM_header_tree, hf_cm_req_primary_sl, tvb, local_offset, 1, FALSE);
3065             proto_tree_add_item(CM_header_tree, hf_cm_req_primary_subnet_local, tvb, local_offset, 1, FALSE);
3066             local_offset += 1;  /* skip reserved */
3067             proto_tree_add_item(CM_header_tree, hf_cm_req_primary_local_ack_to, tvb, local_offset, 1, FALSE);
3068             local_offset += 1;  /* skip reserved */
3069             proto_tree_add_item(CM_header_tree, hf_cm_req_alt_local_lid, tvb, local_offset, 2, FALSE); local_offset += 2;
3070             proto_tree_add_item(CM_header_tree, hf_cm_req_alt_remote_lid, tvb, local_offset, 2, FALSE); local_offset += 2;
3071             proto_tree_add_item(CM_header_tree, hf_cm_req_alt_local_gid, tvb, local_offset, 16, FALSE); local_offset += 16;
3072             proto_tree_add_item(CM_header_tree, hf_cm_req_alt_remote_gid, tvb, local_offset, 16, FALSE); local_offset += 16;
3073             proto_tree_add_item(CM_header_tree, hf_cm_req_flow_label, tvb, local_offset, 2, FALSE); local_offset += 2;
3074             local_offset += 1;  /* skip reserved */
3075             proto_tree_add_item(CM_header_tree, hf_cm_req_packet_rate, tvb, local_offset, 1, FALSE); local_offset += 1;
3076             proto_tree_add_item(CM_header_tree, hf_cm_req_alt_traffic_class, tvb, local_offset, 1, FALSE); local_offset += 1;
3077             proto_tree_add_item(CM_header_tree, hf_cm_req_alt_hop_limit, tvb, local_offset, 1, FALSE); local_offset += 1;
3078             proto_tree_add_item(CM_header_tree, hf_cm_req_SL, tvb, local_offset, 1, FALSE);
3079             proto_tree_add_item(CM_header_tree, hf_cm_req_subnet_local, tvb, local_offset, 1, FALSE);
3080             local_offset += 1;  /* skip reserved */
3081             proto_tree_add_item(CM_header_tree, hf_cm_req_local_ACK_timeout, tvb, local_offset, 1, FALSE);
3082             local_offset += 1;  /* skip reserved */
3083
3084             /* the following saves information about the conversation this packet defines,
3085                so there's no point in doing it more than once per packet */
3086             if(!pinfo->fd->flags.visited)
3087             {
3088                 conversation_t *conv;
3089                 conversation_infiniband_data *proto_data = NULL;
3090                 guint64 *hash_key = g_malloc(sizeof(guint64));
3091
3092                 /* create a new connection context and store it in the hash table */
3093                 connection = g_malloc(sizeof(connection_context));
3094                 memcpy(&(connection->req_gid), local_gid, GID_SIZE);
3095                 memcpy(&(connection->resp_gid), remote_gid, GID_SIZE);
3096                 connection->req_lid = local_lid;
3097                 connection->resp_lid = remote_lid;
3098                 connection->req_qp = local_qpn;
3099                 connection->resp_qp = 0;   /* not currently known. we'll fill this in later */
3100                 connection->service_id = serviceid;
3101
3102                 /* save the context to the context hash table, for retrieval when the corresponding
3103                    CM REP message arrives*/
3104                 *hash_key = MadData.transactionID;
3105                 ADD_ADDRESS_TO_HASH(*hash_key, &pinfo->src);
3106                 g_hash_table_replace(CM_context_table, hash_key, connection);
3107
3108                 /* Now we create a conversation for the CM exchange. This uses both
3109                    sides of the conversation since CM packets also include the source
3110                    QPN */
3111                 proto_data = se_alloc(sizeof(conversation_infiniband_data));
3112                 proto_data->service_id = connection->service_id;
3113
3114                 conv = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst,
3115                                         PT_IBQP, pinfo->srcport, pinfo->destport, 0);
3116                 conversation_add_proto_data(conv, proto_infiniband, proto_data);
3117             }
3118
3119             /* give a chance for subdissectors to analyze the private data */
3120             next_tvb = tvb_new_subset(tvb, local_offset, 92, -1);
3121             if (! dissector_try_heuristic(heur_dissectors_cm_private, next_tvb, pinfo, parentTree) )
3122                 /* if none reported success, add this as raw "data" */
3123                 proto_tree_add_item(CM_header_tree, hf_cm_req_private_data, tvb, local_offset, 92, FALSE);
3124
3125             local_offset += 92;
3126             break;
3127         case ATTR_CM_REP:
3128             proto_tree_add_item(CM_header_tree, hf_cm_rep_localcommid, tvb, local_offset, 4, FALSE); local_offset += 4;
3129             proto_tree_add_item(CM_header_tree, hf_cm_rep_remotecommid, tvb, local_offset, 4, FALSE); local_offset += 4;
3130             proto_tree_add_item(CM_header_tree, hf_cm_rep_localqkey, tvb, local_offset, 4, FALSE); local_offset += 4;
3131             proto_tree_add_item(CM_header_tree, hf_cm_rep_localqpn, tvb, local_offset, 3, FALSE);
3132             remote_qpn = tvb_get_ntoh24(tvb, local_offset); local_offset += 3;
3133             local_offset += 1;  /* skip reserved */
3134             proto_tree_add_item(CM_header_tree, hf_cm_rep_localeecontnum, tvb, local_offset, 3, FALSE); local_offset += 3;
3135             local_offset += 1;  /* skip reserved */
3136             proto_tree_add_item(CM_header_tree, hf_cm_rep_startingpsn, tvb, local_offset, 3, FALSE); local_offset += 3;
3137             local_offset += 1;  /* skip reserved */
3138             proto_tree_add_item(CM_header_tree, hf_cm_rep_responderres, tvb, local_offset, 1, FALSE); local_offset += 1;
3139             proto_tree_add_item(CM_header_tree, hf_cm_rep_initiatordepth, tvb, local_offset, 1, FALSE); local_offset += 1;
3140             proto_tree_add_item(CM_header_tree, hf_cm_rep_tgtackdelay, tvb, local_offset, 1, FALSE);
3141             proto_tree_add_item(CM_header_tree, hf_cm_rep_failoveracc, tvb, local_offset, 1, FALSE);
3142             proto_tree_add_item(CM_header_tree, hf_cm_rep_e2eflowctl, tvb, local_offset, 1, FALSE); local_offset += 1;
3143             proto_tree_add_item(CM_header_tree, hf_cm_rep_rnrretrycount, tvb, local_offset, 1, FALSE);
3144             proto_tree_add_item(CM_header_tree, hf_cm_rep_srq, tvb, local_offset, 1, FALSE);
3145             local_offset += 1;  /* skip reserved */
3146             proto_tree_add_item(CM_header_tree, hf_cm_rep_localcaguid, tvb, local_offset, 8, FALSE); local_offset += 8;
3147
3148             /* the following saves information about the conversation this packet defines,
3149                so there's no point in doing it more than once per packet */
3150             if(!pinfo->fd->flags.visited)
3151             {
3152                 /* get the previously saved context for this connection */
3153                 guint64 hash_key;
3154                 hash_key = MadData.transactionID;
3155                 ADD_ADDRESS_TO_HASH(hash_key, &pinfo->dst);
3156                 connection = g_hash_table_lookup(CM_context_table, &hash_key);
3157
3158                 /* if an appropriate connection was not found there's something wrong, but nothing we can