2 * Lnet packet dissection
3 * Author: Laurent George <george@ocre.cea.fr>
4 * based on packet-agentx.c and packet-afs.c
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1999 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 * Copyright (c) 2012, 2013, Intel Corporation.
39 #include <epan/packet.h>
40 #include <epan/conversation.h>
41 #include <epan/prefs.h>
42 #include <epan/emem.h>
44 #include <epan/dissectors/packet-tcp.h>
45 #include <epan/dissectors/packet-infiniband.h>
47 /* This value inidcates whether we are processing an Infiniband packet, or
48 TCP. It gets set to the extra bytes the IB header requires if IB,
50 static guint ib_lnd_extra_bytes;
52 /* How much data has at least to be available to be able to determine the
53 * length of the lnet message.
54 * Note: This is only used for TCP-based LNet packets. Not used for Infiniband.
56 #define LNET_HEADER_LEN 52
57 #define LNET_NID_DEST_OFFSET (24 + ib_lnd_extra_bytes)
58 #define LNET_NID_SRC_OFFSET (32 + ib_lnd_extra_bytes)
59 #define LNET_MSG_TYPE_OFFSET (48 + ib_lnd_extra_bytes)
60 #define LNET_PTL_INDEX_OFFSET_PUT (88 + ib_lnd_extra_bytes)
62 #define EXTRA_IB_HEADER_SIZE 24
64 /* TCP ports used for LNet. */
65 static guint global_lnet_tcp_port = 988;
66 static guint lnet_tcp_port = 988;
68 void proto_reg_handoff_lnet(void);
70 /* Define the lnet proto */
71 static int proto_lnet = -1;
73 static int hf_lnet_src_nid = -1 ;
74 static int hf_lnet_src_nid_addr = -1 ;
75 static int hf_lnet_src_nid_lnet_type = -1;
76 static int hf_lnet_src_nid_interface = -1 ;
78 static int hf_lnet_ksm_type = -1;
79 static int hf_lnet_ksm_csum = -1;
80 static int hf_lnet_ksm_zc_req_cookie = -1;
81 static int hf_lnet_ksm_zc_ack_cookie = -1;
83 static int hf_lnet_ib_magic = -1;
84 static int hf_lnet_ib_version = -1;
85 static int hf_lnet_ib_type = -1;
86 static int hf_lnet_ib_credits = -1;
87 static int hf_lnet_ib_nob = -1;
88 static int hf_lnet_ib_csum = -1;
89 static int hf_lnet_ib_srcstamp = -1;
90 static int hf_lnet_ib_dststamp = -1;
92 static int hf_lnet_dest_nid = -1 ;
93 static int hf_lnet_dest_nid_addr = -1 ;
94 static int hf_lnet_dest_nid_lnet_type = -1 ;
95 static int hf_lnet_dest_nid_interface = -1 ;
97 static int hf_lnet_dest_pid = -1 ;
98 static int hf_lnet_src_pid = -1 ;
100 static int hf_lnet_msg_type = -1 ;
101 static int hf_lnet_payload_length = -1;
102 static int hf_lnet_payload = -1 ;
103 static int hf_lnet_msg_header = -1 ;
104 static int hf_lnet_msg_filler = -1 ;
106 static int hf_dst_wmd = -1 ;
107 static int hf_dst_wmd_interface = -1 ;
108 static int hf_dst_wmd_object = -1 ;
110 static int hf_match_bits = -1 ;
111 static int hf_mlength = -1 ;
113 static int hf_hdr_data = -1 ;
114 static int hf_ptl_index = -1 ;
115 static int hf_offset = -1 ;
116 static gint ett_lnet = -1;
118 static int hf_src_offset = -1;
119 static int hf_sink_length = -1;
121 static int hf_hello_incarnation = -1 ;
122 static int hf_hello_type = -1 ;
124 static gint ett_lnet_dest_nid= -1;
125 static gint ett_lnet_src_nid= -1;
129 /* Breakdown of a NID. */
130 typedef struct t_nid {
136 /*static heur_dissector_list_t heur_subdissector_list; */
137 static dissector_table_t subdissector_table;
139 static const value_string lndnames[] = {
162 static const value_string lnet_msg_type_t[] = {
163 { LNET_MSG_ACK , "ACK"},
164 { LNET_MSG_PUT , "PUT"},
165 { LNET_MSG_GET , "GET"},
166 { LNET_MSG_REPLY, "REPLY"},
167 { LNET_MSG_HELLO, "HELLO"}
170 /* Port Index numbers. Defined in lustre/include/lustre/lustre_idl.h */
171 static const value_string portal_indices[] = {
172 { 0 , "LNET_RESERVED_PORTAL"},
173 { 1 , "CONNMGR_REQUEST_PORTAL"},
174 { 2 , "CONNMGR_REPLY_PORTAL"},
175 { 3 , "OSC_REQUEST_PORTAL(obsolete)"},
176 { 4 , "OSC_REPLY_PORTAL"},
177 { 5 , "OSC_BULK_PORTAL(obsolete)"},
178 { 6 , "OST_IO_PORTAL"},
179 { 7 , "OST_CREATE_PORTAL"},
180 { 8 , "OST_BULK_PORTAL"},
181 { 9 , "MDC_REQUEST_PORTAL(obsolete)"},
182 { 10 , "MDC_REPLY_PORTAL"},
183 { 11 , "MDC_BULK_PORTAL(obsolete)"},
184 { 12 , "MDS_REQUEST_PORTAL"},
185 { 13 , "MDS_REPLY_PORTAL(obsolete)"},
186 { 14 , "MDS_BULK_PORTAL"},
187 { 15 , "LDLM_CB_REQUEST_PORTAL"},
188 { 16 , "LDLM_CB_REPLY_PORTAL"},
189 { 17 , "LDLM_CANCEL_REQUEST_PORTAL"},
190 { 18 , "LDLM_CANCEL_REPLY_PORTAL"},
191 { 19 , "PTLBD_REQUEST_PORTAL(obsolete)"},
192 { 20 , "PTLBD_REPLY_PORTAL(obsolete)"},
193 { 21 , "PTLBD_BULK_PORTAL(obsolete)"},
194 { 22 , "MDS_SETATTR_PORTAL"},
195 { 23 , "MDS_READPAGE_PORTAL"},
196 { 24 , "MDS_MDS_PORTAL"},
197 { 25 , "MGC_REPLY_PORTAL"},
198 { 26 , "MGS_REQUEST_PORTAL"},
199 { 27 , "MGS_REPLY_PORTAL"},
200 { 28 , "OST_REQUEST_PORTAL"},
201 { 29 , "FLD_REQUEST_PORTAL"},
202 { 30 , "SEQ_METADATA_PORTAL"},
203 { 31 , "SEQ_DATA_PORTAL"},
204 { 32 , "SEQ_CONTROLLER_PORTAL"},
205 { 33 , "MGS_BULK_PORTAL"},
206 { 50 , "SRPC_REQUEST_PORTAL"},
207 { 51 , "SRPC_FRAMEWORK_REQUEST_PORTAL"},
208 { 52 , "SRPC_RDMA_PORTAL"}
211 /* SOCKLND constants. */
212 #define KSOCK_MSG_NOOP 0xc0 /* ksm_u empty */
213 #define KSOCK_MSG_LNET 0xc1 /* lnet msg */
215 static const value_string ksm_type_t[] = {
216 {0xc0, "KSOCK_MSG_NOOP"},/* ksm_u empty */
217 {0xc1, "KSOCK_MSG_LNET"} /* lnet msg */
220 /* O2IBLND constants. */
221 #define LNET_PROTO_IB_MAGIC 0x0be91b91
223 static const value_string ib_version_t[] = {
228 #define IBLND_MSG_CONNREQ 0xc0 /* connection request */
229 #define IBLND_MSG_CONNACK 0xc1 /* connection acknowledge */
230 #define IBLND_MSG_NOOP 0xd0 /* nothing (just credits) */
231 #define IBLND_MSG_IMMEDIATE 0xd1 /* immediate */
232 #define IBLND_MSG_PUT_REQ 0xd2 /* putreq (src->sink) */
233 #define IBLND_MSG_PUT_NAK 0xd3 /* completion (sink->src) */
234 #define IBLND_MSG_PUT_ACK 0xd4 /* putack (sink->src) */
235 #define IBLND_MSG_PUT_DONE 0xd5 /* completion (src->sink) */
236 #define IBLND_MSG_GET_REQ 0xd6 /* getreq (sink->src) */
237 #define IBLND_MSG_GET_DONE 0xd7 /* completion (src->sink: all OK) */
239 static const value_string ib_type_t[] = {
240 {0xc0, "IBLND_MSG_CONNREQ"},
241 {0xc1, "IBLND_MSG_CONNACK"},
242 {0xd0, "IBLND_MSG_NOOP"},
243 {0xd1, "IBLND_MSG_IMMEDIATE"},
244 {0xd2, "IBLND_MSG_PUT_REQ"},
245 {0xd3, "IBLND_MSG_PUT_NAK"},
246 {0xd4, "IBLND_MSG_PUT_ACK"},
247 {0xd5, "IBLND_MSG_PUT_DONE"},
248 {0xd6, "IBLND_MSG_GET_REQ"},
249 {0xd7, "IBLND_MSG_GET_DONE"}
252 static gboolean little_endian = TRUE;
254 #ifndef ENABLE_STATIC
255 const gchar version[] = VERSION;
257 /* Start the functions we need for the plugin stuff */
260 plugin_register(void)
262 extern void proto_register_lnet(void);
264 proto_register_lnet();
268 plugin_reg_handoff(void)
270 extern void proto_reg_handoff_lnet(void);
272 proto_reg_handoff_lnet();
277 get_nid(tvbuff_t *tvb, gint offset)
281 nid.addr = g_htonl(tvb_get_ipv4(tvb, offset));
282 nid.interface = tvb_get_letohs(tvb, offset + 4);
283 nid.proto = tvb_get_letohs(tvb, offset + 6);
287 static int dissect_csum(tvbuff_t * tvb, proto_tree *tree, int offset)
290 csum = tvb_get_letohl(tvb, offset);
292 proto_tree_add_text(tree, tvb, offset, 4, "Checksum Disabled");
294 if (ib_lnd_extra_bytes)
295 proto_tree_add_item(tree, hf_lnet_ib_csum, tvb, offset,
298 proto_tree_add_item(tree, hf_lnet_ksm_csum, tvb, offset,
306 static int dissect_req_cookie(tvbuff_t * tvb, proto_tree *tree, int offset)
309 req= tvb_get_letoh64(tvb, offset);
311 proto_tree_add_text(tree, tvb, offset, 8, "Ack not required");
313 proto_tree_add_item(tree, hf_lnet_ksm_zc_req_cookie, tvb, offset, 8, little_endian);
317 static int dissect_ack_cookie(tvbuff_t * tvb, proto_tree *tree, int offset)
320 ack= tvb_get_letoh64(tvb, offset);
322 proto_tree_add_text(tree, tvb, offset, 8, "Not ack");
324 proto_tree_add_item(tree, hf_lnet_ksm_zc_ack_cookie, tvb, offset, 8, little_endian);
329 dissect_ksock_msg_noop( tvbuff_t * tvb, packet_info *pinfo, proto_tree *tree)
333 proto_tree_add_item(tree, hf_lnet_ksm_type, tvb, offset, 4, TRUE);offset+=4;
334 offset=dissect_csum(tvb,tree,offset);
335 offset=dissect_req_cookie(tvb, tree, offset);
336 offset=dissect_ack_cookie(tvb,tree,offset);
340 static int dissect_ksock_msg(tvbuff_t * tvb, proto_tree *tree, int offset)
342 proto_tree_add_item(tree, hf_lnet_ksm_type, tvb, offset, 4, TRUE);offset+=4;
343 offset=dissect_csum(tvb,tree,offset);
344 offset=dissect_req_cookie(tvb, tree, offset);
345 offset=dissect_ack_cookie(tvb,tree,offset);
350 dissect_ib_msg(tvbuff_t *tvb, proto_tree *tree, int offset)
354 * __u32 ibm_magic; * I'm an ibnal message *
355 * __u16 ibm_version; * this is my version *
357 * __u8 ibm_type; * msg type *
358 * __u8 ibm_credits; * returned credits *
359 * __u32 ibm_nob; * # bytes in message *
360 * __u32 ibm_cksum; * checksum (0 == no
362 * __u64 ibm_srcnid; * sender's NID *
363 * __u64 ibm_srcstamp; * sender's incarnation *
364 * __u64 ibm_dstnid; * destination's NID *
365 * __u64 ibm_dststamp; * destination's
369 * kib_connparams_t connparams;
370 * kib_immediate_msg_t immediate;
371 * kib_putreq_msg_t putreq;
372 * kib_putack_msg_t putack;
374 * kib_completion_msg_t completion;
376 *} WIRE_ATTR kib_msg_t; */
382 proto_tree_add_item(tree, hf_lnet_ib_magic, tvb, offset, 4,
385 proto_tree_add_item(tree, hf_lnet_ib_version, tvb, offset, 2,
388 msg_type = tvb_get_guint8(tvb, offset);
389 proto_tree_add_item(tree, hf_lnet_ib_type, tvb, offset, 1,
392 proto_tree_add_item(tree, hf_lnet_ib_credits, tvb, offset, 1,
395 proto_tree_add_item(tree, hf_lnet_ib_nob, tvb, offset, 4,
398 offset = dissect_csum(tvb, tree, offset);
400 src_nid = get_nid(tvb, offset);
401 proto_tree_add_text(tree, tvb, offset, 8, "src_nid = %s@tcp%d",
402 ip_to_str((guint8 *) &src_nid.addr),
405 proto_tree_add_item(tree, hf_lnet_ib_srcstamp, tvb, offset, 8,
409 dst_nid = get_nid(tvb, offset);
410 proto_tree_add_text(tree, tvb, offset, 8, "dst_nid = %s@tcp%d",
411 ip_to_str((guint8 *) &dst_nid.addr),
414 proto_tree_add_item(tree, hf_lnet_ib_dststamp, tvb,offset, 8,
418 /* LNet payloads only exist when the LND msg type is IMMEDIATE.
419 Return a zero offset for all other types. */
420 return (msg_type == IBLND_MSG_IMMEDIATE) ? offset : 0;
423 static int dissect_dest_nid(tvbuff_t * tvb, proto_tree *tree, int offset)
425 proto_tree_add_item(tree, hf_lnet_dest_nid_addr, tvb, offset, 4, TRUE);offset+=4;
426 proto_tree_add_item(tree, hf_lnet_dest_nid_interface, tvb, offset, 2, TRUE);offset+=2;
427 proto_tree_add_item(tree, hf_lnet_dest_nid_lnet_type, tvb, offset, 2, TRUE);offset+=2;
432 static int dissect_src_nid(tvbuff_t * tvb, proto_tree *tree, int offset)
434 proto_tree_add_item(tree, hf_lnet_src_nid_addr, tvb, offset, 4, TRUE);offset+=4;
435 proto_tree_add_item(tree, hf_lnet_src_nid_interface, tvb, offset, 2, TRUE);offset+=2;
436 proto_tree_add_item(tree, hf_lnet_src_nid_lnet_type, tvb, offset, 2, TRUE);offset+=2;
440 static int dissect_lnet_put(tvbuff_t * tvb, proto_tree *tree, int offset, packet_info *pinfo _U_)
442 /* typedef struct lnet_put {
443 lnet_handle_wire_t ack_wmd;
448 } WIRE_ATTR lnet_put_t; */
450 proto_tree_add_item(tree,hf_dst_wmd_interface,tvb,offset,8,little_endian); offset+=8;
451 proto_tree_add_item(tree,hf_dst_wmd_object,tvb,offset,8,little_endian);offset+=8;
453 proto_tree_add_item(tree,hf_match_bits,tvb,offset,8,little_endian);offset+=8;
454 proto_tree_add_item(tree,hf_hdr_data,tvb,offset,8,little_endian);offset+=8;
455 if (check_col(pinfo->cinfo, COL_INFO))
456 col_append_sep_str(pinfo->cinfo, COL_INFO, ", ",
457 val_to_str(tvb_get_letohl(tvb, offset), portal_indices,
458 "Unknown")); /* add some nice value */
459 proto_item_append_text(tree, ", %s" , val_to_str(tvb_get_letohl(tvb,
463 /* print ptl_index */
464 proto_tree_add_item(tree,hf_ptl_index,tvb,offset,4,little_endian);offset+=4;
465 proto_tree_add_item(tree,hf_offset,tvb,offset,4,little_endian);offset+=4;
469 static int dissect_lnet_get(tvbuff_t * tvb, proto_tree *tree, int offset, packet_info *pinfo _U_)
471 /* typedef struct lnet_get {
472 lnet_handle_wire_t return_wmd;
477 } WIRE_ATTR lnet_get_t; */
479 proto_tree_add_item(tree,hf_dst_wmd_interface,tvb,offset,8,little_endian);offset+=8;
480 proto_tree_add_item(tree,hf_dst_wmd_object,tvb,offset,8,little_endian);offset+=8;
481 /*if (check_col(pinfo->cinfo, COL_INFO))*/
482 /* col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, " %" G_GINT64_MODIFIER "u ", tvb_get_letoh64(tvb,offset) );*/
484 proto_tree_add_item(tree,hf_match_bits,tvb,offset,8,little_endian);offset+=8;
485 if (check_col(pinfo->cinfo, COL_INFO))
486 col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", val_to_str(tvb_get_letohl(tvb,offset), portal_indices, "Unknown"));
487 proto_item_append_text(tree, ", %s" , val_to_str(tvb_get_letohl(tvb,offset), portal_indices, "Unknown"));
488 proto_tree_add_item(tree,hf_ptl_index,tvb,offset,4,little_endian);offset+=4;
489 proto_tree_add_item(tree,hf_src_offset,tvb,offset,4,little_endian);offset+=4;
490 proto_tree_add_item(tree,hf_sink_length,tvb,offset,4,little_endian);offset+=4;
494 static int 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,little_endian);offset+=8;
501 proto_tree_add_item(tree,hf_dst_wmd_object,tvb,offset,8,little_endian);offset+=8;
507 static int dissect_lnet_hello(tvbuff_t * tvb, proto_tree *tree, int offset)
509 /* typedef struct lnet_hello {
512 } WIRE_ATTR lnet_hello_t; */
514 proto_tree_add_item(tree,hf_hello_incarnation,tvb,offset,8,little_endian); offset+=8;
515 proto_tree_add_item(tree,hf_hello_type,tvb,offset,4,little_endian); offset+=4;
519 static int dissect_lnet_ack(tvbuff_t * tvb, proto_tree *tree, int offset, packet_info *pinfo _U_)
521 /* typedef struct lnet_ack {
522 lnet_handle_wire_t dst_wmd;
525 } WIRE_ATTR lnet_ack_t; */
527 proto_tree_add_item(tree,hf_dst_wmd_interface,tvb,offset,8,TRUE); offset+=8;
528 proto_tree_add_item(tree,hf_dst_wmd_object,tvb,offset,8,TRUE);offset+=8;
529 proto_tree_add_item(tree,hf_match_bits,tvb,offset,8, little_endian);offset+=8;
530 proto_tree_add_item(tree,hf_mlength, tvb,offset,4, little_endian); offset+=4;
534 static void dissect_lnet_message(tvbuff_t * tvb, packet_info *pinfo, proto_tree *tree);
536 /* The next two length getting routines are only used for KSOCK LNK messages. */
538 get_lnet_message_len(packet_info __attribute__((__unused__))*pinfo, tvbuff_t *tvb, int offset)
542 /* Get the payload length */
543 plen = tvb_get_letohl(tvb, offset + 28 + 24 + ib_lnd_extra_bytes);
548 /* That length doesn't include the header; add that in. */
549 return plen + 72 + 24 + ib_lnd_extra_bytes; /* +24 == ksock msg
555 get_noop_message_len(packet_info __attribute__((__unused__))*pinfo, tvbuff_t *tvb, int offset)
561 dissect_lnet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
563 /* TODO : correct this, now we do a difference between packet with
564 NOOP and others .. but I don't find how to use pdu_dissect with
565 a variable length<=LNET_HEADER_LEN */
566 ib_lnd_extra_bytes = 0;
567 switch(tvb_get_letohl(tvb,0)){
569 tcp_dissect_pdus(tvb,pinfo,tree,TRUE,0, get_noop_message_len,dissect_ksock_msg_noop);
572 tcp_dissect_pdus(tvb,pinfo,tree,TRUE,LNET_HEADER_LEN, get_lnet_message_len,dissect_lnet_message);
579 dissect_ib_lnet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
581 /* We can tell if this is an LNet payload by looking at the first
582 * 32-bit word for our magic number. */
583 if (tvb_get_letohl(tvb, 0) != LNET_PROTO_IB_MAGIC) {
584 /* Not an LNet payload. */
588 ib_lnd_extra_bytes = EXTRA_IB_HEADER_SIZE;
589 tcp_dissect_pdus(tvb, pinfo, tree, TRUE, LNET_HEADER_LEN,
590 get_lnet_message_len, dissect_lnet_message);
591 return tvb_length(tvb);
594 /*----------------------------------------------------------- */
595 /* For the conversation */
602 typedef struct lnet_request_key {
604 guint32 conversation;
605 } lnet_request_key_t;
607 typedef struct lnet_request_val {
609 guint32 packet_num_parent;
610 } lnet_request_val_t;
613 static GHashTable *lnet_request_hash;
619 lnet_equal(gconstpointer v, gconstpointer w)
621 const struct lnet_request_key *v1 = (const struct lnet_request_key *)v;
622 const struct lnet_request_key *v2 = (const struct lnet_request_key *)w;
624 if (v1 -> conversation == v2 -> conversation &&
625 v1 -> match_bits == v2 -> match_bits)
635 lnet_hash (gconstpointer v)
637 const struct lnet_request_key *key = (const struct lnet_request_key *)v;
638 return key -> conversation + key -> match_bits;
643 lnet_init_protocol(void)
645 if (lnet_request_hash)
646 g_hash_table_destroy(lnet_request_hash);
648 lnet_request_hash = g_hash_table_new(lnet_hash, lnet_equal);
652 static lnet_request_val_t*
653 get_lnet_conv(packet_info * pinfo , GHashTable * lnet_hash_table, guint64 match_bits )
655 conversation_t * conversation ;
656 lnet_request_key_t request_key, *new_request_key;
657 lnet_request_val_t *request_val=NULL ;
659 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
662 if (NULL == conversation)
663 /* It's not part of any conversation - create a new one. */
664 conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, proto_lnet,
665 pinfo->srcport, pinfo->destport, 0);
667 request_key.conversation = conversation->index;
668 request_key.match_bits = match_bits;
670 request_val = (struct lnet_request_val * ) g_hash_table_lookup(lnet_hash_table, &request_key);
672 new_request_key = se_alloc(sizeof(struct lnet_request_key));
673 *new_request_key = request_key;
674 request_val = se_alloc(sizeof(struct lnet_request_val));
675 request_val -> match_bits = match_bits;
676 request_val -> packet_num_parent = pinfo->fd->num ;
677 /*request_val -> filename = "test" ; */
678 g_hash_table_insert(lnet_hash_table, new_request_key, request_val);
688 /*----------------------------------------------------------- */
690 dissect_lnet_message(tvbuff_t * tvb, packet_info *pinfo, proto_tree *tree)
696 lnet_request_val_t* conversation_val ;
699 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
700 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Lnet");
703 if (check_col(pinfo->cinfo, COL_INFO)) {
704 /* t_nid dest_nid ; */
706 /*guint32 msg_type;*/
707 /*[> col_clear(pinfo->cinfo, COL_INFO); <]*/
708 /*dest_nid = get_nid(tvb, LNET_NID_DEST_OFFSET);*/
709 /*src_nid = get_nid(tvb, LNET_NID_SRC_OFFSET);*/
711 /*[> col_add_fstr(pinfo->cinfo, COL_INFO, "%s@tcp%d > %s@tcp%d",
712 ip_to_str((guint8 *) &src_nid.addr), src_nid.interface,
713 ip_to_str((guint8 *) & dest_nid.addr), dest_nid.interface); */
715 msg_type = tvb_get_letohl(tvb, LNET_MSG_TYPE_OFFSET );
716 /* We delete the entire line and add LNET + msg_type */
717 col_add_fstr(pinfo->cinfo, COL_INFO, "LNET_%s", (msg_type < sizeof(lnet_msg_type_t)/sizeof(value_string)) ? lnet_msg_type_t[msg_type].strptr : "Unknown");
721 t_nid dest_nid ; /* nid value */
725 proto_item *ti = NULL; /* principal node */
726 proto_tree *lnet_tree = NULL ; /* principal tree */
727 proto_tree *lnet_nid_src_tree= NULL ; /*subtree for the nids*/
728 proto_tree *lnet_nid_dest_tree= NULL ;
729 proto_item *ti_src_nid ; /* node for the nids */
730 proto_item *ti_dest_nid ;
735 guint32 payload_length;
736 guint32 msg_filler_length;
739 ti = proto_tree_add_item(tree,proto_lnet,tvb,0,-1,FALSE); /* principal node */
740 /* ti=proto_tree_add_protocol_format(tree, proto_lnet, tvb, 0, -1, "Lnet"); */
742 lnet_tree = proto_item_add_subtree(ti,ett_lnet); /* add the subtree*/
744 if (ib_lnd_extra_bytes) {
745 offset = dissect_ib_msg(tvb, lnet_tree, offset);
747 /* There was no LNet payload, only ob2lnd. */
751 /* dissect the first 24 bytes (ksock_msg_t in
753 offset=dissect_ksock_msg(tvb,lnet_tree,offset);
757 dest_nid = get_nid(tvb, offset);
758 ti_dest_nid = proto_tree_add_text(lnet_tree, tvb, offset, 8, "dest_nid = %s@tcp%d", ip_to_str((guint8 *) &dest_nid.addr), dest_nid.interface);
759 lnet_nid_dest_tree = proto_item_add_subtree(ti_dest_nid,ett_lnet_dest_nid) ;
760 offset=dissect_dest_nid(tvb,lnet_nid_dest_tree,offset);
762 /* Same for src_nid */
763 src_nid = get_nid(tvb, offset);
764 ti_src_nid = proto_tree_add_text(lnet_tree, tvb, offset, 8, "src_nid = %s@tcp%d", ip_to_str((guint8 *) &src_nid.addr), src_nid.interface);
765 lnet_nid_src_tree = proto_item_add_subtree(ti_src_nid,ett_lnet_src_nid) ;
766 offset=dissect_src_nid(tvb,lnet_nid_src_tree,offset);
769 proto_tree_add_item(lnet_tree, hf_lnet_src_pid, tvb, offset, 4, TRUE); offset+=4;
770 proto_tree_add_item(lnet_tree, hf_lnet_dest_pid, tvb, offset, 4, TRUE); offset+=4;
772 /* message_type (32 bits) */
773 msg_type = tvb_get_letohl(tvb, offset+0);
774 /* put some nice info on lnet line */
775 proto_item_append_text(ti," %s", (msg_type < sizeof(lnet_msg_type_t)/sizeof(value_string)) ? lnet_msg_type_t[msg_type].strptr : "Unknow") ; /* rajout de l'info dans l'arbre */
776 proto_tree_add_item(lnet_tree, hf_lnet_msg_type, tvb, offset, 4, TRUE); offset+=4;
778 /* payload data (to follow) length :*/
779 payload_length = tvb_get_letohl(tvb,offset+0);
780 proto_tree_add_item(lnet_tree, hf_lnet_payload_length, tvb, offset, 4, TRUE); offset+=4;
782 /* here offset = 24+8+8+4+4+4+4 = 56 */
786 offset=dissect_lnet_ack(tvb,lnet_tree,offset,pinfo);
787 match = tvb_get_letoh64(tvb,72 );
790 offset=dissect_lnet_put(tvb,lnet_tree,offset,pinfo);
791 match = tvb_get_letoh64(tvb, 72);
794 offset=dissect_lnet_get(tvb,lnet_tree,offset,pinfo);
795 match = tvb_get_letoh64(tvb, 72);
798 offset=dissect_lnet_reply(tvb,lnet_tree,offset);
801 offset=dissect_lnet_hello(tvb,lnet_tree,offset);
808 conversation_val = get_lnet_conv(pinfo , lnet_request_hash, match );
809 /* proto_tree_add_text(tree, tvb, 0 , 0, "match = %" G_GINT64_MODIFIER "u parent = %d", conversation_val -> match_bits , conversation_val -> packet_num_parent); */
813 msg_filler_length = 72 - offset + 24 + ib_lnd_extra_bytes;
814 if ( msg_filler_length > 72)
816 /* +24 : ksosck_message take 24bytes, and allready in offset */
818 proto_tree_add_item(lnet_tree, hf_lnet_msg_filler, tvb, offset,
819 msg_filler_length, little_endian);
820 offset+=msg_filler_length;
822 if (payload_length>0)
825 /* display of payload */
826 proto_tree_add_item(lnet_tree, hf_lnet_payload, tvb,
827 offset, payload_length,
830 next_tvb = tvb_new_subset (tvb, offset, payload_length, payload_length);
831 if(msg_type==LNET_MSG_PUT)
832 dissector_try_port(subdissector_table, tvb_get_letohl(tvb,LNET_PTL_INDEX_OFFSET_PUT), next_tvb, pinfo, tree);
836 offset+=payload_length;
841 proto_register_lnet(void)
843 static hf_register_info hf[] = {
844 { &hf_lnet_ksm_type ,
845 { "Type of socklnd message" , "lnet.ksm_type" , FT_UINT32 , BASE_HEX , VALS(ksm_type_t) , 0x0 , "" , HFILL }} ,
846 { &hf_lnet_ksm_csum ,
847 { "Checksum" , "lnet.ksm_csum" , FT_UINT32 , BASE_DEC , NULL , 0x0 , "" , HFILL }} ,
848 { &hf_lnet_ksm_zc_req_cookie ,
849 { "Ack required" , "lnet.ksm_zc_req_cookie" , FT_UINT64 , BASE_HEX , NULL , 0x0 , "" , HFILL }} ,
850 { &hf_lnet_ksm_zc_ack_cookie ,
851 { "Ack" , "lnet.ksm_zc_ack_cookie" , FT_UINT64 , BASE_HEX , NULL , 0x0 , "" , HFILL }} ,
853 { "Magic of IB message", "lnet.ib.magic", FT_UINT32,
854 BASE_HEX, NULL, 0x0, "", HFILL} },
855 { &hf_lnet_ib_version,
856 { "Version", "lnet.ib.version", FT_UINT16, BASE_HEX,
857 VALS(ib_version_t), 0x0, "", HFILL} },
859 { "Type of IB message", "lnet.ib.type", FT_UINT8,
860 BASE_HEX, VALS(ib_type_t), 0x0, "", HFILL} },
861 { &hf_lnet_ib_credits,
862 { "Returned Credits", "lnet.ib.credits", FT_UINT8,
863 BASE_DEC, NULL, 0x0, "", HFILL} },
865 { "Number of Bytes", "lnet.ib.nob", FT_UINT32,
866 BASE_DEC, NULL, 0x0, "", HFILL} },
868 { "Checksum", "lnet.ib_csum", FT_UINT32, BASE_DEC,
869 NULL, 0x0, "", HFILL} },
870 { &hf_lnet_ib_srcstamp,
871 { "Sender Timestamp", "lnet.ib.srcstamp",
872 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
874 { &hf_lnet_ib_dststamp,
875 { "Destination Timestamp", "lnet.ib.dststamp",
876 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
880 { "Src nid" , "lnet.src_nid" , FT_UINT64 , BASE_HEX , NULL , 0x0 , "src nid" , HFILL }} ,
881 { &hf_lnet_src_nid_addr ,
882 { "Src nid" , "lnet.src_nid_addr" , FT_IPv4 , BASE_NONE , NULL , 0x0 , "" , HFILL }} ,
883 { &hf_lnet_src_nid_lnet_type ,
884 { "lnd network type" , "lnet.src_nid_type" , FT_UINT16 , BASE_DEC , VALS(lndnames) , 0x0 , "" , HFILL} },
885 { &hf_lnet_src_nid_interface ,
886 { "lnd network interface" , "lnet.src_nid_net_interface" , FT_UINT16 , BASE_DEC , NULL , 0x0 , NULL , HFILL }} ,
888 { &hf_lnet_dest_nid ,
889 { "Dest nid" , "lnet.dest_nid" , FT_UINT64 , BASE_HEX , NULL , 0x0 , "" , HFILL }} ,
891 { &hf_lnet_dest_nid_addr ,
892 { "Destination nid" , "lnet.dest_nid_addr" , FT_IPv4 , BASE_NONE , NULL , 0x0 , "" , HFILL }} ,
893 { &hf_lnet_dest_nid_lnet_type ,
894 { "lnd network type" , "lnet.dest_nid_type" , FT_UINT16 , BASE_DEC , VALS(lndnames) , 0x0 , "" , HFILL} },
895 { &hf_lnet_dest_nid_interface ,
896 { "lnd network interface" , "lnet.dest_nid_net_interface" , FT_UINT16 , BASE_DEC , NULL , 0x0 , NULL , HFILL }} ,
898 { &hf_lnet_dest_pid ,
899 { "Dest pid" , "lnet.dest_pid" , FT_UINT32 , BASE_DEC_HEX , NULL , 0x0 , "dest pid" , HFILL }} ,
901 { "Src pid" , "lnet.src_pid" , FT_UINT32 , BASE_DEC_HEX , NULL , 0x0 , "src nid" , HFILL }} ,
903 { &hf_lnet_msg_type ,
904 { "Message type" , "lnet.msg_type" , FT_UINT32 , BASE_DEC , VALS(lnet_msg_type_t) , 0x0 , "msg type" , HFILL }} ,
905 { &hf_lnet_payload_length ,
906 { "Payload length" , "lnet.payload_length" , FT_UINT32 , BASE_DEC , NULL , 0x0 , "" , HFILL }} ,
908 { "Payload" , "lnet.payload" , FT_NONE , BASE_NONE , NULL , 0x0 , "" , HFILL }} ,
911 { "DST MD index " , "lnet.msg_dst_cookie" , FT_BYTES , BASE_NONE , NULL , 0x0 , "" , HFILL }} ,
912 { &hf_dst_wmd_interface ,
913 { "DST MD index interface" , "lnet.msg_dst_inteface_cookie" , FT_UINT64 , BASE_HEX_DEC , NULL , 0x0 , "" , HFILL }} ,
914 { &hf_dst_wmd_object ,
915 { "DST MD index object" , "lnet.msg_dst_object_cookie" , FT_UINT64 , BASE_HEX_DEC , NULL , 0x0 , "" , HFILL }} ,
917 { "Match bits" , "lnet.msg_dst_match_bits" , FT_UINT64 , BASE_HEX_DEC , NULL , 0x0 , "" , HFILL}} ,
919 { "Message length" , "lnet.msg_length" , FT_UINT32 , BASE_DEC , NULL , 0x0 , "" , HFILL}} ,
924 { "hdr data" , "lnet.msg_hdr_data" , FT_UINT64 , BASE_HEX_DEC , NULL , 0x0 , "" , HFILL}} ,
926 { "ptl index" , "lnet.ptl_index" , FT_UINT32 , BASE_DEC , VALS(portal_indices) , 0x0 , "" , HFILL}} ,
928 { "offset" , "lnet.offset" , FT_UINT32 , BASE_DEC , NULL , 0x0 , "" , HFILL}} ,
932 { "src offset" , "lnet.src_offset" , FT_UINT32 , BASE_DEC , NULL , 0x0 , "" , HFILL}} ,
934 { "sink length" , "lnet.sink_length" , FT_UINT32 , BASE_DEC , NULL , 0x0 , "" , HFILL}} ,
937 { &hf_hello_incarnation ,
938 { "hello incarnation " , "lnet.hello_incarnation" , FT_UINT64 , BASE_HEX_DEC , NULL , 0x0 , "" , HFILL}} ,
940 { "hello type" , "lnet.hello_type" , FT_UINT32 , BASE_DEC , NULL , 0x0 , "" , HFILL}} ,
942 { &hf_lnet_msg_header ,
943 { "ptl header" , "lnet.ptl_header" , FT_NONE , BASE_NONE , NULL , 0x0 , "" , HFILL}} ,
945 { &hf_lnet_msg_filler ,
946 { "msg filler (padding)" , "lnet.ptl_filler" , FT_NONE , BASE_NONE , NULL , 0x0 , "" , HFILL}} ,
948 /* Add more fields here */
951 static gint *ett[] = {
958 module_t *lnet_module;
960 proto_lnet = proto_register_protocol("Lnet", /*name*/
961 "Lnet", /*short name*/
964 proto_register_field_array(proto_lnet, hf, array_length(hf));
965 proto_register_subtree_array(ett, array_length(ett));
967 lnet_module = prefs_register_protocol(proto_lnet, proto_reg_handoff_lnet);
969 prefs_register_uint_preference(lnet_module, "tcp.lnet_port",
970 "Lnet listener TCP Port",
971 "Set the TCP port for Lnet"
972 "(if other than the default of 988)",
973 10, &global_lnet_tcp_port);
975 subdissector_table = register_dissector_table("lnet.ptl_index", "lnet portal index", FT_UINT32 , BASE_DEC);
977 register_init_routine(&lnet_init_protocol);
982 /* The registration hand-off routine */
984 proto_reg_handoff_lnet(void)
986 static int lnet_prefs_initialized = FALSE;
987 static dissector_handle_t lnet_handle;
989 if(!lnet_prefs_initialized) {
990 heur_dissector_add("infiniband.payload", dissect_ib_lnet,
992 heur_dissector_add("infiniband.mad.cm.private",
993 dissect_ib_lnet, proto_lnet);
994 lnet_handle = create_dissector_handle(dissect_lnet, proto_lnet);
995 lnet_prefs_initialized = TRUE;
998 dissector_delete("tcp.port",global_lnet_tcp_port, lnet_handle);
1000 lnet_tcp_port = global_lnet_tcp_port;
1002 dissector_add("tcp.port", lnet_tcp_port, lnet_handle);