2 * Routines for lnet dissection
3 * Copyright (c) 2012, 2013, 2017 Intel Corporation.
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
13 * LNet - Lustre Networking
15 * A network abstraction layer for passing data at near wire-speed.
16 * Supports RDMA where available and run across a variety of network hosts.
18 * http://doc.lustre.org/lustre_manual.xhtml#understandinglustrenetworking
23 #include <epan/packet.h>
24 #include <epan/expert.h>
25 #include <epan/to_str.h>
26 #include <epan/proto_data.h>
29 #include "packet-tcp.h"
30 #include "packet-lnet.h"
31 VALUE_STRING_ARRAY2(portal_index
);
33 void proto_reg_handoff_lnet(void);
34 void proto_register_lnet(void);
36 static dissector_handle_t lnet_handle
;
38 /* Initialize the protocol and registered fields */
39 static int proto_lnet
;
41 static int hf_lnet_ksm_type
;
42 static int hf_lnet_ksm_csum
;
43 static int hf_lnet_ksm_zc_req_cookie
;
44 static int hf_lnet_ksm_zc_ack_cookie
;
46 static int hf_lnet_ib_magic
;
47 static int hf_lnet_ib_version
;
48 static int hf_lnet_ib_type
;
49 static int hf_lnet_ib_credits
;
50 static int hf_lnet_ib_nob
;
51 static int hf_lnet_ib_csum
;
52 static int hf_lnet_ib_srcstamp
;
53 static int hf_lnet_ib_dststamp
;
55 static int hf_lnet_src_nid
;
56 static int hf_lnet_dest_nid
;
58 static int hf_lnet_nid_addr
;
59 static int hf_lnet_nid_lnet_type
;
60 static int hf_lnet_nid_interface
;
62 static int hf_lnet_dest_pid
;
63 static int hf_lnet_src_pid
;
65 static int hf_lnet_msg_type
;
66 static int hf_lnet_payload_length
;
67 static int hf_lnet_payload
;
68 static int hf_lnet_msg_filler
;
70 static int hf_dst_wmd_interface
;
71 static int hf_dst_wmd_object
;
73 static int hf_match_bits
;
74 static int hf_mlength
;
76 static int hf_hdr_data
;
77 static int hf_ptl_index
;
80 static int hf_src_offset
;
81 static int hf_sink_length
;
83 static int hf_hello_incarnation
;
84 static int hf_hello_type
;
86 static int hf_lnet_o2ib_connparam
;
87 static int hf_lnet_o2ib_connparam_qdepth
;
88 static int hf_lnet_o2ib_connparam_max_frags
;
89 static int hf_lnet_o2ib_connparam_max_size
;
90 static int hf_lnet_o2ib_cookie
;
91 static int hf_lnet_o2ib_src_cookie
;
92 static int hf_lnet_o2ib_dest_cookie
;
93 static int hf_lnet_o2ib_status
;
95 static int hf_lnet_rdma_desc
;
96 static int hf_lnet_rdma_desc_key
;
97 static int hf_lnet_rdma_desc_nfrags
;
99 static int hf_lnet_rdma_frag_size
;
100 static int hf_lnet_rdma_frag_addr
;
102 /* Initialize the subtree pointers */
104 static int ett_lnet_nid
;
105 static int ett_lnet_o2ib_connparams
;
106 static int ett_lnet_rdma_desc
;
107 static int ett_lnet_rdma_frag
;
109 static expert_field ei_lnet_buflen
;
110 static expert_field ei_lnet_type
;
112 #define LNET_TCP_PORT 988 /* Not IANA registered */
114 #define LNET_HEADER_LEN 52
115 #define LNET_PTL_INDEX_OFFSET_PUT (88 + extra_bytes)
117 #define EXTRA_IB_HEADER_SIZE 24
119 static dissector_table_t subdissector_table
;
121 /********************************************************************\
125 * NID : Network IDentifiyer
127 * e.g. 192.168.1.1@tcp0 or 10.10.10.1@o2ib4
129 \********************************************************************/
131 #define lndnames_VALUE_STRING_LIST(XXX) \
148 VALUE_STRING_ENUM2(lndnames
);
149 VALUE_STRING_ARRAY2(lndnames
);
151 /* These are the NID protocol names */
152 static const value_string lndprotos
[] = {
153 { QSWLND
, "elan" }, /* removed v2_7_50 */
155 { GMLND
, "gm" }, /* removed v2_0_0-rc1a-16-gc660aac */
156 { PTLLND
, "ptl" }, /* removed v2_7_50 */
158 { CIBLND
, "cib" }, /* removed v2_0_0-rc1a-175-gd2b8a0e */
159 { OPENIBLND
, "openib" }, /* removed v2_0_0-rc1a-175-gd2b8a0e */
160 { IIBLND
, "iib" }, /* removed v2_0_0-rc1a-175-gd2b8a0e */
162 { RALND
, "ra" }, /* removed v2_7_50_0-34-g8be9e41 */
163 { VIBLND
, "vib" }, /* removed v2_0_0-rc1a-175-gd2b8a0e */
164 { MXLND
, "mx" }, /* removed v2_7_50_0-34-g8be9e41 */
179 static const value_string lnet_msg_type
[] = {
180 { LNET_MSG_ACK
, "ACK"},
181 { LNET_MSG_PUT
, "PUT"},
182 { LNET_MSG_GET
, "GET"},
183 { LNET_MSG_REPLY
, "REPLY"},
184 { LNET_MSG_HELLO
, "HELLO"},
188 /* PROTO MAGIC for LNDs */
189 #define LNET_PROTO_IB_MAGIC 0x0be91b91
190 #define LNET_PROTO_MAGIC 0x45726963 /* ! */
191 #define LNET_PROTO_PING_MAGIC 0x70696E67 /* 'ping' */
192 #define LNET_PROTO_ACCEPTOR_MAGIC 0xacce7100
193 #define LNET_PROTO_GNI_MAGIC 0xb00fbabe /* ask Kim */
194 #define LNET_PROTO_TCP_MAGIC 0xeebc0ded
196 static const value_string lnet_magic
[] = {
197 { LNET_PROTO_IB_MAGIC
, "IB_MAGIC" },
198 { LNET_PROTO_MAGIC
, "LNET_MAGIC" }, /* place holder */
199 { LNET_PROTO_PING_MAGIC
, "PING_MAGIC" },
200 { LNET_PROTO_ACCEPTOR_MAGIC
, "ACCEPTOR_MAGIC" },
201 { LNET_PROTO_GNI_MAGIC
, "GNI_MAGIC" },
202 { LNET_PROTO_TCP_MAGIC
, "TCP_MAGIC" },
206 /* SOCKLND constants. */
207 #define ksm_type_VALUE_STRING_LIST(XXX) \
208 XXX(KSOCK_MSG_NOOP, 0xc0) \
209 XXX(KSOCK_MSG_LNET, 0xc1)
211 VALUE_STRING_ENUM2(ksm_type
);
212 VALUE_STRING_ARRAY2(ksm_type
);
214 static const value_string ib_version_t
[] = {
220 #define lnet_ib_type_VALUE_STRING_LIST(XXX) \
221 XXX(IBLND_MSG_CONNREQ, 0xc0) \
222 XXX(IBLND_MSG_CONNACK, 0xc1) \
223 XXX(IBLND_MSG_NOOP, 0xd0) \
224 XXX(IBLND_MSG_IMMEDIATE, 0xd1) \
225 XXX(IBLND_MSG_PUT_REQ, 0xd2) \
226 XXX(IBLND_MSG_PUT_NAK, 0xd3) \
227 XXX(IBLND_MSG_PUT_ACK, 0xd4) \
228 XXX(IBLND_MSG_PUT_DONE, 0xd5) \
229 XXX(IBLND_MSG_GET_REQ, 0xd6) \
230 XXX(IBLND_MSG_GET_DONE, 0xd7)
232 VALUE_STRING_ENUM2(lnet_ib_type
);
233 VALUE_STRING_ARRAY2(lnet_ib_type
);
235 /********************************************************************\
239 \********************************************************************/
241 typedef struct _lnet_conv_info_t
{
245 static struct lnet_trans_info
*
246 get_lnet_conv(packet_info
*pinfo
, uint64_t match_bits
) {
247 conversation_t
*conversation
;
249 struct lnet_trans_info
*info
;
251 lnet_conv_info_t
*conv_info
;
253 // Ignore ports because this is kernel level and there can only be one Lustre instance per server
254 conversation
= find_conversation(pinfo
->num
, &pinfo
->src
, &pinfo
->dst
, conversation_pt_to_conversation_type(pinfo
->ptype
),
256 if (conversation
== NULL
)
257 conversation
= conversation_new(pinfo
->num
, &pinfo
->src
,
258 &pinfo
->dst
, conversation_pt_to_conversation_type(pinfo
->ptype
), 0, 0, 0);
260 conv_info
= (lnet_conv_info_t
*)conversation_get_proto_data(conversation
, proto_lnet
);
262 conv_info
= wmem_new0(wmem_file_scope(), lnet_conv_info_t
);
263 conv_info
->pdus
= wmem_map_new(wmem_file_scope(), g_direct_hash
, g_direct_equal
);
265 conversation_add_proto_data(conversation
, proto_lnet
, conv_info
);
268 info
= (struct lnet_trans_info
*)wmem_map_lookup(conv_info
->pdus
, GUINT_TO_POINTER(match_bits
));
270 info
= wmem_new0(wmem_file_scope(), struct lnet_trans_info
);
271 info
->match_bits
= match_bits
;
272 wmem_map_insert(conv_info
->pdus
, GUINT_TO_POINTER(info
->match_bits
), info
);
278 /********************************************************************\
280 * LND:O2IB Structures
282 \********************************************************************/
285 dissect_struct_o2ib_connparam(tvbuff_t
*tvb
, proto_tree
*parent_tree
, int offset
)
290 item
= proto_tree_add_item(parent_tree
, hf_lnet_o2ib_connparam
, tvb
, offset
, 8, ENC_NA
);
291 tree
= proto_item_add_subtree(item
, ett_lnet_o2ib_connparams
);
293 proto_tree_add_item(tree
, hf_lnet_o2ib_connparam_qdepth
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
295 proto_tree_add_item(tree
, hf_lnet_o2ib_connparam_max_frags
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
297 proto_tree_add_item(tree
, hf_lnet_o2ib_connparam_max_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
302 /* kib_rdma_desc_t */
304 /* __u32 rd_key; /\* local/remote key *\/ */
305 /* __u32 rd_nfrags; /\* # fragments *\/ */
306 /* kib_rdma_frag_t rd_frags[0]; /\* buffer frags *\/ */
310 /* __u32 rf_nob; /\* # bytes this frag *\/ */
311 /* __u64 rf_addr; /\* CAVEAT EMPTOR: misaligned!! *\/ */
314 dissect_struct_rdma_desc(tvbuff_t
*tvb
, proto_tree
*parent_tree
, int offset
)
316 proto_tree
*tree
, *ftree
;
324 item
= proto_tree_add_item(parent_tree
, hf_lnet_rdma_desc
, tvb
, offset
, -1, ENC_NA
);
325 tree
= proto_item_add_subtree(item
, ett_lnet_rdma_desc
);
327 /* @@ SAVE KEY and use to intercept infiniband payload */
328 proto_tree_add_item(tree
, hf_lnet_rdma_desc_key
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
330 proto_tree_add_item_ret_uint(tree
, hf_lnet_rdma_desc_nfrags
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &frags
);
333 for (i
=0; i
< frags
; ++i
) {
334 ftree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, 12, ett_lnet_rdma_frag
, NULL
, "RDMA Fragment [%d]", i
);
335 proto_tree_add_item(ftree
, hf_lnet_rdma_frag_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
337 proto_tree_add_item(ftree
, hf_lnet_rdma_frag_addr
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
341 proto_item_set_len(item
, offset
-old_offset
);
346 /********************************************************************\
348 * NID Dissection & Healper Function
350 \********************************************************************/
354 lnet_dissect_struct_nid(tvbuff_t
* tvb
, proto_tree
*parent_tree
, int offset
, int hf_index
)
358 uint32_t ip
, interface
, proto
;
360 item
= proto_tree_add_item(parent_tree
, hf_index
, tvb
, offset
, 8, ENC_NA
);
361 tree
= proto_item_add_subtree(item
, ett_lnet_nid
);
363 ip
= tvb_get_ipv4(tvb
, offset
);
364 proto_tree_add_item(tree
, hf_lnet_nid_addr
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
366 proto_tree_add_item_ret_uint(tree
, hf_lnet_nid_interface
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
, &interface
);
368 proto_tree_add_item_ret_uint(tree
, hf_lnet_nid_lnet_type
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
, &proto
);
373 set_address(&addr
, AT_IPv4
, 4, &ip
);
374 proto_item_append_text(item
, ": %s@%s%d", address_to_name(&addr
), val_to_str(proto
, lndprotos
, "E(%d)"), interface
);
380 /********************************************************************\
384 \********************************************************************/
387 dissect_csum(tvbuff_t
* tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, unsigned lnd_type
)
392 csum
= tvb_get_letohl(tvb
, offset
);
393 // @@ convert this to proto_tree_add_checksum()
396 ti
= proto_tree_add_item(tree
, hf_lnet_ib_csum
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
400 ti
= proto_tree_add_item(tree
, hf_lnet_ksm_csum
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
404 ti
= proto_tree_add_expert_format(tree
, pinfo
, &ei_lnet_type
, tvb
, offset
, 4,
405 "Checksum for unprocessed type: %s",
406 val_to_str(lnd_type
, lndnames
, "Unknown(%d)"));
411 proto_item_append_text(ti
, " (DISABLED)");
416 /********************************************************************\
418 * Message Type Dissection
420 \********************************************************************/
423 dissect_lnet_put(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, uint64_t *match
)
425 /* typedef struct lnet_put {
426 lnet_handle_wire_t ack_wmd;
431 } WIRE_ATTR lnet_put_t; */
435 proto_tree_add_item(tree
, hf_dst_wmd_interface
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
437 proto_tree_add_item(tree
, hf_dst_wmd_object
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
440 proto_tree_add_item_ret_uint64(tree
, hf_match_bits
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
, match
);
442 proto_tree_add_item(tree
, hf_hdr_data
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
445 /* print ptl_index */
446 proto_tree_add_item_ret_uint(tree
, hf_ptl_index
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &ptl_index
);
449 port
= val_to_str(ptl_index
, portal_index
, "Unknown(%d)");
450 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, ", ", port
);
451 proto_item_append_text(tree
, ", %s" , port
);
453 proto_tree_add_item(tree
, hf_offset
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
459 dissect_lnet_get(tvbuff_t
* tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, uint64_t *match
)
461 /* typedef struct lnet_get {
462 lnet_handle_wire_t return_wmd;
467 } WIRE_ATTR lnet_get_t;
472 proto_tree_add_item(tree
, hf_dst_wmd_interface
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
474 proto_tree_add_item(tree
, hf_dst_wmd_object
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
476 proto_tree_add_item_ret_uint64(tree
, hf_match_bits
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
, match
);
479 proto_tree_add_item_ret_uint(tree
, hf_ptl_index
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &ptl_index
);
482 port
= val_to_str(ptl_index
, portal_index
, "Unknown (%d)");
483 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, ", ", port
);
484 proto_item_append_text(tree
, ", %s", port
);
486 proto_tree_add_item(tree
, hf_src_offset
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
488 proto_tree_add_item(tree
, hf_sink_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
494 dissect_lnet_reply(tvbuff_t
* tvb
, proto_tree
*tree
, int offset
)
496 /* typedef struct lnet_reply {
497 lnet_handle_wire_t dst_wmd;
498 } WIRE_ATTR lnet_reply_t; */
500 proto_tree_add_item(tree
, hf_dst_wmd_interface
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
502 proto_tree_add_item(tree
, hf_dst_wmd_object
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
510 dissect_lnet_hello(tvbuff_t
* tvb
, proto_tree
*tree
, int offset
)
512 /* typedef struct lnet_hello {
515 } WIRE_ATTR lnet_hello_t; */
517 proto_tree_add_item(tree
, hf_hello_incarnation
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
519 proto_tree_add_item(tree
, hf_hello_type
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
525 dissect_lnet_ack(tvbuff_t
* tvb
, proto_tree
*tree
, int offset
, uint64_t *match
)
527 /* typedef struct lnet_ack {
528 lnet_handle_wire_t dst_wmd;
531 } WIRE_ATTR lnet_ack_t; */
533 proto_tree_add_item(tree
, hf_dst_wmd_interface
, tvb
, offset
, 8, ENC_NA
);
535 proto_tree_add_item(tree
, hf_dst_wmd_object
, tvb
, offset
, 8, ENC_NA
);
537 proto_tree_add_item_ret_uint64(tree
, hf_match_bits
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
, match
);
539 proto_tree_add_item(tree
, hf_mlength
, tvb
, offset
,4, ENC_LITTLE_ENDIAN
);
544 /********************************************************************\
546 * Dissect Header Functions
548 \********************************************************************/
551 dissect_ksock_msg(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
556 proto_tree_add_item(tree
, hf_lnet_ksm_type
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
558 offset
= dissect_csum(tvb
, pinfo
, tree
, offset
, SOCKLND
);
559 ti
= proto_tree_add_item_ret_uint64(tree
, hf_lnet_ksm_zc_req_cookie
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
, &val
);
561 proto_item_append_text(ti
, " (NO ACK REQUIRED)");
563 ti
= proto_tree_add_item_ret_uint64(tree
, hf_lnet_ksm_zc_ack_cookie
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
, &val
);
565 proto_item_append_text(ti
, " (NOT ACK)");
570 dissect_ksock_msg_noop(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
572 return dissect_ksock_msg(tvb
, pinfo
, tree
, 0);
576 dissect_ib_msg(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, uint32_t *msg_type
, uint32_t *msg_length
)
580 * __u32 ibm_magic; * I'm an ibnal message *
581 * __u16 ibm_version; * this is my version *
583 * __u8 ibm_type; * msg type *
584 * __u8 ibm_credits; * returned credits *
585 * __u32 ibm_nob; * # bytes in message *
586 * __u32 ibm_cksum; * checksum (0 == no
588 * __u64 ibm_srcnid; * sender's NID *
589 * __u64 ibm_srcstamp; * sender's incarnation *
590 * __u64 ibm_dstnid; * destination's NID *
591 * __u64 ibm_dststamp; * destination's
595 * kib_connparams_t connparams;
596 * kib_immediate_msg_t immediate;
597 * kib_putreq_msg_t putreq;
598 * kib_putack_msg_t putack;
600 * kib_completion_msg_t completion;
602 *} WIRE_ATTR kib_msg_t; */
604 proto_tree_add_item(tree
, hf_lnet_ib_magic
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
606 proto_tree_add_item(tree
, hf_lnet_ib_version
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
608 proto_tree_add_item_ret_uint(tree
, hf_lnet_ib_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
, msg_type
);
610 proto_tree_add_item(tree
, hf_lnet_ib_credits
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
612 proto_tree_add_item_ret_uint(tree
, hf_lnet_ib_nob
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, msg_length
);
614 offset
= dissect_csum(tvb
, pinfo
, tree
, offset
, O2IBLND
);
616 offset
= lnet_dissect_struct_nid(tvb
, tree
, offset
, hf_lnet_src_nid
);
618 proto_tree_add_item(tree
, hf_lnet_ib_srcstamp
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
621 offset
= lnet_dissect_struct_nid(tvb
, tree
, offset
, hf_lnet_dest_nid
);
623 proto_tree_add_item(tree
, hf_lnet_ib_dststamp
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
626 /* LNet payloads only exist when the LND msg type is IMMEDIATE.
627 Return a zero offset for all other types. */
631 /********************************************************************\
633 * Main Packet Dissection
635 \********************************************************************/
637 dissect_lnet_message(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
641 proto_tree
*lnet_tree
;
642 /* Other misc. local variables. */
644 uint32_t msg_length
= 0;
645 uint32_t payload_length
= 0;
646 int32_t msg_filler_length
= 0;
649 uint32_t msg_type
= 0;
650 uint32_t ib_msg_type
= 0;
651 unsigned extra_bytes
= GPOINTER_TO_UINT(data
);
652 bool ib_msg_payload
= false;
654 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "LNET");
655 col_clear(pinfo
->cinfo
, COL_INFO
);
657 ti
= proto_tree_add_item(tree
, proto_lnet
, tvb
, 0, -1, ENC_NA
);
658 lnet_tree
= proto_item_add_subtree(ti
, ett_lnet
);
661 offset
= dissect_ib_msg(tvb
, pinfo
, lnet_tree
, offset
, &ib_msg_type
, &msg_length
);
663 switch (ib_msg_type
) {
664 case IBLND_MSG_CONNREQ
:
665 case IBLND_MSG_CONNACK
:
667 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "LNET %s",
668 val_to_str(ib_msg_type
, lnet_ib_type
, "Unknown(%d)"));
669 offset
= dissect_struct_o2ib_connparam(tvb
, lnet_tree
, offset
);
670 msg_filler_length
= tvb_reported_length_remaining(tvb
, offset
);
671 ib_msg_payload
= true;
676 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "LNET %s",
677 val_to_str(ib_msg_type
, lnet_ib_type
, "Unknown(%d)"));
678 ib_msg_payload
= true;
681 case IBLND_MSG_IMMEDIATE
:
682 // Normal LNET Message
685 case IBLND_MSG_PUT_REQ
:
690 case IBLND_MSG_PUT_ACK
:
692 // src cookie + dest cookie + rdma_desc_t
693 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "LNET %s",
694 val_to_str(ib_msg_type
, lnet_ib_type
, "Unknown(%d)"));
695 proto_tree_add_item(lnet_tree
, hf_lnet_o2ib_src_cookie
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
697 proto_tree_add_item(lnet_tree
, hf_lnet_o2ib_dest_cookie
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
699 offset
= dissect_struct_rdma_desc(tvb
, lnet_tree
, offset
);
700 ib_msg_payload
= true;
703 case IBLND_MSG_GET_REQ
:
705 // lnet_hdr + cookie + rdma_desc_t
708 case IBLND_MSG_PUT_NAK
:
709 case IBLND_MSG_PUT_DONE
:
710 case IBLND_MSG_GET_DONE
:
711 // kib_completion_msg_t;
712 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "LNET %s",
713 val_to_str(ib_msg_type
, lnet_ib_type
, "Unknown(%d)"));
715 proto_tree_add_item(lnet_tree
, hf_lnet_o2ib_cookie
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
717 proto_tree_add_item(lnet_tree
, hf_lnet_o2ib_status
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
719 ib_msg_payload
= true;
724 /* dissect the first 24 bytes (ksock_msg_t in
727 offset
= dissect_ksock_msg(tvb
, pinfo
, lnet_tree
, offset
);
730 if (!ib_msg_payload
) {
732 offset
= lnet_dissect_struct_nid(tvb
, lnet_tree
, offset
, hf_lnet_dest_nid
);
733 offset
= lnet_dissect_struct_nid(tvb
, lnet_tree
, offset
, hf_lnet_src_nid
);
736 proto_tree_add_item(lnet_tree
, hf_lnet_src_pid
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
738 proto_tree_add_item(lnet_tree
, hf_lnet_dest_pid
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
741 /* put some nice info on lnet line */
742 proto_tree_add_item_ret_uint(lnet_tree
, hf_lnet_msg_type
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &msg_type
);
743 proto_item_append_text(ti
, " %s", val_to_str(msg_type
, lnet_msg_type
, "Unknown(%d)"));
744 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "LNET_%s", val_to_str(msg_type
, lnet_msg_type
, "Unknown(%d)"));
747 /* payload data (to follow) length :*/
748 proto_tree_add_item_ret_uint(lnet_tree
, hf_lnet_payload_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &payload_length
);
754 offset
= dissect_lnet_ack(tvb
, lnet_tree
, offset
, &match
);
757 offset
= dissect_lnet_put(tvb
, pinfo
, lnet_tree
, offset
, &match
);
760 offset
= dissect_lnet_get(tvb
, pinfo
, lnet_tree
, offset
, &match
);
763 offset
= dissect_lnet_reply(tvb
, lnet_tree
, offset
);
766 offset
= dissect_lnet_hello(tvb
, lnet_tree
, offset
);
772 switch (ib_msg_type
) {
773 case 0: // not actually an ib_msg
775 case IBLND_MSG_PUT_REQ
:
776 proto_tree_add_item(lnet_tree
, hf_lnet_o2ib_cookie
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
778 /*@@ SAVE payload_length with O2IB cookie for IBLND_MSG_PUT_ACK */
781 case IBLND_MSG_GET_REQ
:
782 proto_tree_add_item(lnet_tree
, hf_lnet_o2ib_cookie
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
784 offset
= dissect_struct_rdma_desc(tvb
, lnet_tree
, offset
);
789 msg_filler_length
= 72 - offset
+ 24 + extra_bytes
;
791 if (msg_filler_length > 72)
794 /* +24 : ksock_message take 24bytes, and already in offset */
797 if (msg_filler_length
> 0) {
798 proto_tree_add_item(lnet_tree
, hf_lnet_msg_filler
, tvb
, offset
, msg_filler_length
, ENC_NA
);
799 offset
+= msg_filler_length
;
802 if (payload_length
> 0) {
804 struct lnet_trans_info
*conv
;
806 next_tvb
= tvb_new_subset_length(tvb
, offset
, payload_length
);
809 conv
= get_lnet_conv(pinfo
, match
);
811 offset
+= dissector_try_uint_new(subdissector_table
, tvb_get_letohl(tvb
, LNET_PTL_INDEX_OFFSET_PUT
),
812 next_tvb
, pinfo
, tree
, true, conv
);
815 /* display of payload */
816 proto_tree_add_item(lnet_tree
, hf_lnet_payload
, tvb
, offset
, payload_length
, ENC_NA
);
817 offset
+= payload_length
;
822 if (tvb_captured_length(tvb
) != offset
) {
823 expert_add_info_format(pinfo
, ti
, &ei_lnet_buflen
,
824 "Capture:%d offset:%d (length:%d) msg_type:%d ib_type:%02x",
825 tvb_captured_length(tvb
), offset
, msg_length
, msg_type
, ib_msg_type
);
830 /********************************************************************\
832 * Length Functions (these are SOCK LND only)
834 \********************************************************************/
837 get_lnet_ib_pdu_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
, int offset
, void *data _U_
)
841 /* Ensure this is an LNET IB segment */
842 if (tvb_get_letohl(tvb
, 0) != LNET_PROTO_IB_MAGIC
)
845 /* Get the IB message length (see dissect_ib_msg() for .ibm_nob)
847 plen
= tvb_get_letohl(tvb
, offset
+ 8);
854 get_lnet_message_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
, int offset
, void *data _U_
)
857 unsigned extra_bytes
= GPOINTER_TO_UINT(data
);
859 /* Get the payload length:
861 * 28 = the rest of the headers
863 plen
= tvb_get_letohl(tvb
, offset
+ 28 + 24 + extra_bytes
);
865 /* That length doesn't include the header; add that in.
866 * +24 == ksock msg header.. :D
868 return plen
+ 72 + 24 + extra_bytes
;
872 get_noop_message_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb _U_
,
873 int offset _U_
, void *data _U_
)
878 /******************************************************************** \
882 \********************************************************************/
885 dissect_lnet(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
887 switch (tvb_get_letohl(tvb
, 0)) {
889 tcp_dissect_pdus(tvb
, pinfo
, tree
, true, 0,
890 get_noop_message_len
,
891 dissect_ksock_msg_noop
, GUINT_TO_POINTER(0));
894 tcp_dissect_pdus(tvb
, pinfo
, tree
, true, LNET_HEADER_LEN
,
895 get_lnet_message_len
,
896 dissect_lnet_message
, GUINT_TO_POINTER(0));
899 return tvb_captured_length(tvb
);
903 dissect_lnet_ib_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
905 /* We can tell if this is an LNet payload by looking at the first
906 * 32-bit word for our magic number. */
907 if (tvb_captured_length(tvb
) < 4 || tvb_get_letohl(tvb
, 0) != LNET_PROTO_IB_MAGIC
)
908 /* Not an LNet payload. */
911 dissect_lnet_message(tvb
, pinfo
, tree
, GUINT_TO_POINTER(EXTRA_IB_HEADER_SIZE
));
916 proto_register_lnet(void)
918 static hf_register_info hf
[] = {
920 { "Type of socklnd message", "lnet.ksm_type", FT_UINT32
, BASE_HEX
, VALS(ksm_type
), 0x0, NULL
, HFILL
}},
922 { "Checksum", "lnet.ksm_csum", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
923 { &hf_lnet_ksm_zc_req_cookie
,
924 { "Ack required", "lnet.ksm_zc_req_cookie", FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
925 { &hf_lnet_ksm_zc_ack_cookie
,
926 { "Ack", "lnet.ksm_zc_ack_cookie", FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
928 /* Infiniband Fields */
930 { "Magic of IB message", "lnet.ib.magic", FT_UINT32
, BASE_HEX
, VALS(lnet_magic
), 0x0, NULL
, HFILL
} },
931 { &hf_lnet_ib_version
,
932 { "Version", "lnet.ib.version", FT_UINT16
, BASE_HEX
, VALS(ib_version_t
), 0x0, NULL
, HFILL
} },
934 { "Type of IB message", "lnet.ib.type", FT_UINT8
, BASE_HEX
, VALS(lnet_ib_type
), 0x0, NULL
, HFILL
} },
935 { &hf_lnet_ib_credits
,
936 { "Returned Credits", "lnet.ib.credits", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
} },
938 { "Number of Bytes", "lnet.ib.nob", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
} },
940 { "Checksum", "lnet.ib_csum", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
} },
941 { &hf_lnet_ib_srcstamp
,
942 { "Sender Timestamp", "lnet.ib.srcstamp", FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
, NULL
, 0x0, NULL
, HFILL
}},
943 { &hf_lnet_ib_dststamp
,
944 { "Destination Timestamp", "lnet.ib.dststamp", FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
, NULL
, 0x0, NULL
, HFILL
}},
947 { "Src nid", "lnet.src_nid", FT_NONE
, BASE_NONE
, NULL
, 0x0, "Source NID", HFILL
}},
949 { "Dest nid", "lnet.dest_nid", FT_NONE
, BASE_NONE
, NULL
, 0x0, "Destination NID", HFILL
}},
952 { "lnd address", "lnet.nid.addr", FT_IPv4
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
953 { &hf_lnet_nid_lnet_type
,
954 { "lnd network type", "lnet.nid.type", FT_UINT16
, BASE_DEC
, VALS(lndnames
), 0x0, NULL
, HFILL
}},
955 { &hf_lnet_nid_interface
,
956 { "lnd network interface", "lnet.nid.net_interface", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
959 { "Dest pid", "lnet.dest_pid", FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0, "Destination pid", HFILL
}},
961 { "Src pid", "lnet.src_pid", FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0, "Source nid", HFILL
}},
964 { "Message type", "lnet.msg_type", FT_UINT32
, BASE_DEC
, VALS(lnet_msg_type
), 0x0, NULL
, HFILL
}},
965 { &hf_lnet_payload_length
,
966 { "Payload length", "lnet.payload_length", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
968 { "Payload", "lnet.payload", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
970 { &hf_dst_wmd_interface
,
971 { "DST MD index interface", "lnet.msg_dst_interface_cookie", FT_UINT64
, BASE_HEX_DEC
, NULL
, 0x0, NULL
, HFILL
}},
972 { &hf_dst_wmd_object
,
973 { "DST MD index object", "lnet.msg_dst_object_cookie", FT_UINT64
, BASE_HEX_DEC
, NULL
, 0x0, NULL
, HFILL
}},
975 { "Match bits", "lnet.msg_dst_match_bits", FT_UINT64
, BASE_HEX_DEC
, NULL
, 0x0, NULL
, HFILL
}},
977 { "Message length", "lnet.msg_length", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
981 { "hdr data", "lnet.msg_hdr_data", FT_UINT64
, BASE_HEX_DEC
, NULL
, 0x0, NULL
, HFILL
}},
983 { "ptl index", "lnet.ptl_index", FT_UINT32
, BASE_DEC
, VALS(portal_index
), 0x0, NULL
, HFILL
}},
985 { "offset", "lnet.offset", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
989 { "src offset", "lnet.src_offset", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
991 { "sink length", "lnet.sink_length", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
994 { &hf_hello_incarnation
,
995 { "hello incarnation", "lnet.hello_incarnation", FT_UINT64
, BASE_HEX_DEC
, NULL
, 0x0, NULL
, HFILL
}},
997 { "hello type", "lnet.hello_type", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
999 { &hf_lnet_msg_filler
,
1000 { "msg filler (padding)", "lnet.ptl_filler", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
1003 { &hf_lnet_o2ib_connparam
,
1004 { "O2IB ConnParam", "lnet.connparam", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
1005 { &hf_lnet_o2ib_connparam_qdepth
,
1006 { "Queue Depth", "lnet.connparam.qdepth", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1007 { &hf_lnet_o2ib_connparam_max_frags
,
1008 { "Max Fragments", "lnet.connparam.max_frags", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1009 { &hf_lnet_o2ib_connparam_max_size
,
1010 { "Max Msg Size", "lnet.connparam.max_size", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1012 { &hf_lnet_o2ib_cookie
,
1013 { "O2IB Cookie", "lnet.o2ib.cookie", FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1014 { &hf_lnet_o2ib_src_cookie
,
1015 { "O2IB Source Cookie", "lnet.o2ib.src_cookie", FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1016 { &hf_lnet_o2ib_dest_cookie
,
1017 { "O2IB Dest Cookie", "lnet.o2ib.dest_cookie", FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1018 { &hf_lnet_o2ib_status
,
1019 { "O2IB Status", "lnet.o2ib.status", FT_INT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1021 { &hf_lnet_rdma_desc
,
1022 { "RDMA Description", "lnet.rdma", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
1023 { &hf_lnet_rdma_desc_key
,
1024 { "RDMA Key", "lnet.rdma.key", FT_UINT32
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1025 { &hf_lnet_rdma_desc_nfrags
,
1026 { "RDMA # of Fragments", "lnet.rdma.nfrags", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1028 { &hf_lnet_rdma_frag_size
,
1029 { "RDMA Frag Size (bytes)", "lnet.rdma_frag.size", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1030 { &hf_lnet_rdma_frag_addr
,
1031 { "RDMA Frag Address", "lnet.rdma_frag.addr", FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1034 static int *ett
[] = {
1037 &ett_lnet_o2ib_connparams
,
1038 &ett_lnet_rdma_desc
,
1039 &ett_lnet_rdma_frag
,
1042 expert_module_t
*expert_lnet
;
1043 static ei_register_info ei
[] = {
1045 { "lnet.bad_buflen", PI_MALFORMED
, PI_ERROR
, "Buffer length mis-match", EXPFILL
} },
1047 { "lnet.bad_type", PI_PROTOCOL
, PI_ERROR
, "LNET Type mis-match", EXPFILL
} }
1050 proto_lnet
= proto_register_protocol("Lustre Network", "LNet", "lnet");
1052 proto_register_field_array(proto_lnet
, hf
, array_length(hf
));
1053 proto_register_subtree_array(ett
, array_length(ett
));
1054 expert_lnet
= expert_register_protocol(proto_lnet
);
1055 expert_register_field_array(expert_lnet
, ei
, array_length(ei
));
1057 lnet_handle
= register_dissector("lnet", dissect_lnet
, proto_lnet
);
1059 subdissector_table
= register_dissector_table("lnet.ptl_index", "lnet portal index",
1061 FT_UINT32
, BASE_DEC
);
1065 proto_reg_handoff_lnet(void)
1067 heur_dissector_add("infiniband.payload", dissect_lnet_ib_heur
, "LNet over IB",
1068 "lnet_ib", proto_lnet
, HEURISTIC_ENABLE
);
1069 heur_dissector_add("infiniband.mad.cm.private", dissect_lnet_ib_heur
, "LNet over IB CM",
1070 "lnet_ib_cm_private", proto_lnet
, HEURISTIC_ENABLE
);
1071 dissector_add_for_decode_as("infiniband", lnet_handle
);
1072 dissector_add_uint_with_preference("tcp.port", LNET_TCP_PORT
, lnet_handle
);
1076 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1081 * indent-tabs-mode: nil
1084 * vi: set shiftwidth=4 tabstop=8 expandtab:
1085 * :indentSize=4:tabSize=8:noTabs=true: