Whamcloud - gitweb
LU-1994 llite: don't release nd->path in ll_follow_link
[fs/lustre-release.git] / lustre / contrib / wireshark / packet-lnet.c
1 /* packet-lnet.c 
2  * Lnet packet dissection 
3  * Author: Laurent George <george@ocre.cea.fr>
4  * based on packet-agentx.c and packet-afs.c
5  * 20080903
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1999 Gerald Combs
10  *
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.
15  *
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.
20  *
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.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <ctype.h>
33 #include <time.h>
34 #include <string.h>
35 #include <glib.h>
36
37 #include <epan/packet.h>
38 #include <epan/conversation.h>
39 #include <epan/prefs.h>
40 #include <epan/emem.h>
41
42 #include <epan/dissectors/packet-tcp.h>
43 #include <epan/dissectors/packet-infiniband.h>
44
45 /* How much data has at least to be available to be able to determine the
46  * length of the lnet message.
47  * Note: This is only used for TCP-based LNet packets.  Not used for Infiniband.
48  */
49 #define LNET_HEADER_LEN 52
50 #define LNET_NID_DEST_OFFSET 24
51 #define LNET_NID_SRC_OFFSET 32
52 #define LNET_MSG_TYPE_OFFSET 48
53 #define LNET_PTL_INDEX_OFFSET_PUT 88
54
55 /* TCP ports used for LNet. */
56 static guint global_lnet_tcp_port = 988;
57 static guint lnet_tcp_port = 988;
58
59 /* This boolean inidcates whether we are processing an Infiniband packet, or
60    TCP. */
61 static guint ib_packet;
62
63 void proto_reg_handoff_lnet(void);
64
65 /* Define the lnet proto */
66 static int proto_lnet = -1;
67
68 static int hf_lnet_src_nid = -1 ;
69 static int hf_lnet_src_nid_addr = -1 ;
70 static int hf_lnet_src_nid_lnet_type = -1;
71 static int hf_lnet_src_nid_interface = -1  ;
72
73 static int hf_lnet_ksm_type = -1;
74 static int hf_lnet_ksm_csum = -1;
75 static int hf_lnet_ksm_zc_req_cookie = -1;
76 static int hf_lnet_ksm_zc_ack_cookie = -1;
77
78 static int hf_lnet_ib_magic = -1;
79 static int hf_lnet_ib_version = -1;
80 static int hf_lnet_ib_type = -1;
81 static int hf_lnet_ib_credits = -1;
82 static int hf_lnet_ib_nob = -1;
83 static int hf_lnet_ib_csum = -1;
84 static int hf_lnet_ib_srcstamp = -1;
85 static int hf_lnet_ib_dststamp = -1;
86
87 static int hf_lnet_dest_nid = -1 ;
88 static int hf_lnet_dest_nid_addr = -1 ;
89 static int hf_lnet_dest_nid_lnet_type = -1 ; 
90 static int hf_lnet_dest_nid_interface = -1 ;
91
92 static int hf_lnet_dest_pid = -1 ; 
93 static int hf_lnet_src_pid = -1 ;
94
95 static int hf_lnet_msg_type = -1 ;
96 static int hf_lnet_payload_length = -1;
97 static int hf_lnet_payload = -1 ;
98 static int hf_lnet_msg_header = -1 ; 
99 static int hf_lnet_msg_filler = -1 ;
100
101 static int hf_dst_wmd = -1 ;   
102 static int hf_dst_wmd_interface = -1 ;   
103 static int hf_dst_wmd_object = -1 ;   
104
105 static int hf_match_bits = -1 ; 
106 static int hf_mlength = -1 ; 
107
108 static int hf_hdr_data = -1 ;
109 static int hf_ptl_index = -1 ;
110 static int hf_offset = -1 ;
111 static gint ett_lnet = -1;
112
113 static int hf_src_offset = -1;
114 static int hf_sink_length = -1;
115
116 static int hf_hello_incarnation = -1 ;
117 static int hf_hello_type = -1 ; 
118
119 static gint ett_lnet_dest_nid= -1;
120 static gint ett_lnet_src_nid= -1;
121
122 tvbuff_t *next_tvb;
123
124 /* Breakdown of a NID. */
125 typedef struct t_nid {
126         guint32 addr;
127         guint16 interface;
128         guint16 proto;
129 } t_nid ;
130
131 /*static heur_dissector_list_t heur_subdissector_list; */
132 static dissector_table_t subdissector_table;
133
134 static const value_string lndnames[] = {
135         { 1, "QSWLND   "},
136         { 2, "SOCKLND  "},
137         { 3, "GMLND    "},
138         { 4, "PTLLND   "},
139         { 5, "O2IBLND  "},
140         { 6, "CIBLND   "},
141         { 7, "OPENIBLND"}, 
142         { 8, "IIBLND   "},
143         { 9, "LOLND    "},
144         { 10,"RALND    "},
145         { 11,"VIBLND   "},
146         { 12,"MXLND    "} 
147 };
148
149 enum MSG_type{
150         LNET_MSG_ACK = 0,
151         LNET_MSG_PUT,
152         LNET_MSG_GET,
153         LNET_MSG_REPLY,
154         LNET_MSG_HELLO,
155 } ;
156
157 static const value_string lnet_msg_type_t[] = {
158         { LNET_MSG_ACK  , "ACK"},  
159         { LNET_MSG_PUT  , "PUT"},  
160         { LNET_MSG_GET  , "GET"},  
161         { LNET_MSG_REPLY, "REPLY"},  
162         { LNET_MSG_HELLO, "HELLO"} 
163 };
164
165 /* Port Index numbers.  Defined in lustre/include/lustre/lustre_idl.h */
166 static const value_string portal_indices[] = {
167         { 0 , "LNET_RESERVED_PORTAL"},
168         { 1 , "CONNMGR_REQUEST_PORTAL"},
169         { 2 , "CONNMGR_REPLY_PORTAL"},
170         { 3 , "OSC_REQUEST_PORTAL(obsolete)"},
171         { 4 , "OSC_REPLY_PORTAL"},
172         { 5 , "OSC_BULK_PORTAL(obsolete)"},
173         { 6 , "OST_IO_PORTAL"},
174         { 7 , "OST_CREATE_PORTAL"},
175         { 8 , "OST_BULK_PORTAL"},
176         { 9 , "MDC_REQUEST_PORTAL(obsolete)"},
177         { 10 , "MDC_REPLY_PORTAL"},
178         { 11 , "MDC_BULK_PORTAL(obsolete)"},
179         { 12 , "MDS_REQUEST_PORTAL"},
180         { 13 , "MDS_REPLY_PORTAL(obsolete)"},
181         { 14 , "MDS_BULK_PORTAL"},
182         { 15 , "LDLM_CB_REQUEST_PORTAL"},
183         { 16 , "LDLM_CB_REPLY_PORTAL"},
184         { 17 , "LDLM_CANCEL_REQUEST_PORTAL"},
185         { 18 , "LDLM_CANCEL_REPLY_PORTAL"},
186         { 19 , "PTLBD_REQUEST_PORTAL(obsolete)"},
187         { 20 , "PTLBD_REPLY_PORTAL(obsolete)"},
188         { 21 , "PTLBD_BULK_PORTAL(obsolete)"},
189         { 22 , "MDS_SETATTR_PORTAL"},
190         { 23 , "MDS_READPAGE_PORTAL"},
191         { 24 , "MDS_MDS_PORTAL"},
192         { 25 , "MGC_REPLY_PORTAL"},
193         { 26 , "MGS_REQUEST_PORTAL"},
194         { 27 , "MGS_REPLY_PORTAL"},
195         { 28 , "OST_REQUEST_PORTAL"},
196         { 29 , "FLD_REQUEST_PORTAL"},
197         { 30 , "SEQ_METADATA_PORTAL"},
198         { 31 , "SEQ_DATA_PORTAL"},
199         { 32 , "SEQ_CONTROLLER_PORTAL"},
200         { 33 , "MGS_BULK_PORTAL"},
201         { 50 , "SRPC_REQUEST_PORTAL"},
202         { 51 , "SRPC_FRAMEWORK_REQUEST_PORTAL"},
203         { 52 , "SRPC_RDMA_PORTAL"}
204 };
205
206 /* SOCKLND constants. */
207 #define KSOCK_MSG_NOOP          0xc0            /* ksm_u empty */ 
208 #define KSOCK_MSG_LNET          0xc1            /* lnet msg */
209
210 static const value_string ksm_type_t[] = {
211         {0xc0, "KSOCK_MSG_NOOP"},/* ksm_u empty */ 
212         {0xc1, "KSOCK_MSG_LNET"} /* lnet msg */
213 };
214
215 /* O2IBLND constants. */
216 #define LNET_PROTO_IB_MAGIC     0x0be91b91
217
218 static const value_string ib_version_t[] = {
219         {0x11, "1"},
220         {0x12, "2"}
221 };
222
223 #define IBLND_MSG_CONNREQ       0xc0    /* connection request */
224 #define IBLND_MSG_CONNACK       0xc1    /* connection acknowledge */
225 #define IBLND_MSG_NOOP          0xd0    /* nothing (just credits) */
226 #define IBLND_MSG_IMMEDIATE     0xd1    /* immediate */
227 #define IBLND_MSG_PUT_REQ       0xd2    /* putreq (src->sink) */
228 #define IBLND_MSG_PUT_NAK       0xd3    /* completion (sink->src) */
229 #define IBLND_MSG_PUT_ACK       0xd4    /* putack (sink->src) */
230 #define IBLND_MSG_PUT_DONE      0xd5    /* completion (src->sink) */
231 #define IBLND_MSG_GET_REQ       0xd6    /* getreq (sink->src) */
232 #define IBLND_MSG_GET_DONE      0xd7    /* completion (src->sink: all OK) */
233
234 static const value_string ib_type_t[] = {
235         {0xc0, "IBLND_MSG_CONNREQ"},
236         {0xc1, "IBLND_MSG_CONNACK"},
237         {0xd0, "IBLND_MSG_NOOP"},
238         {0xd1, "IBLND_MSG_IMMEDIATE"},
239         {0xd2, "IBLND_MSG_PUT_REQ"},
240         {0xd3, "IBLND_MSG_PUT_NAK"},
241         {0xd4, "IBLND_MSG_PUT_ACK"},
242         {0xd5, "IBLND_MSG_PUT_DONE"},
243         {0xd6, "IBLND_MSG_GET_REQ"},
244         {0xd7, "IBLND_MSG_GET_DONE"}
245 };
246
247 static gboolean little_endian = TRUE;
248
249 #ifndef ENABLE_STATIC
250 const gchar version[] = VERSION;
251
252 /* Start the functions we need for the plugin stuff */
253
254 void
255 plugin_register(void)
256 {
257         extern void proto_register_lnet(void);
258
259         proto_register_lnet();
260 }
261
262 void
263 plugin_reg_handoff(void)
264 {
265         extern void proto_reg_handoff_lnet(void);
266
267         proto_reg_handoff_lnet();
268 }
269 #endif
270
271 static t_nid
272 get_nid(tvbuff_t *tvb, gint offset)
273 {
274         t_nid nid ;
275
276         nid.addr = g_htonl(tvb_get_ipv4(tvb, offset));
277         nid.interface = tvb_get_letohs(tvb, offset + 4);
278         nid.proto = tvb_get_letohs(tvb, offset + 6);
279         return nid ;
280 }
281
282 static int dissect_csum(tvbuff_t * tvb, proto_tree *tree, int offset)
283 {
284         guint32 csum;
285         csum = tvb_get_letohl(tvb, offset);
286         if (!csum)
287                 proto_tree_add_text(tree, tvb, offset, 4, "Checksum Disabled");
288         else {
289                 if (ib_packet)
290                         proto_tree_add_item(tree, hf_lnet_ib_csum, tvb, offset,
291                                             4, little_endian);
292                 else
293                         proto_tree_add_item(tree, hf_lnet_ksm_csum, tvb, offset,
294                                             4, little_endian);
295         }
296
297         return offset + 4;
298 }
299
300
301 static int dissect_req_cookie(tvbuff_t * tvb, proto_tree *tree, int offset)
302 {
303         guint32 req;
304         req= tvb_get_letoh64(tvb, offset);
305         if (!req)
306                 proto_tree_add_text(tree, tvb, offset, 8, "Ack not required");
307         else
308                 proto_tree_add_item(tree, hf_lnet_ksm_zc_req_cookie, tvb, offset, 8, little_endian);
309         return offset + 8;
310 }
311
312 static int dissect_ack_cookie(tvbuff_t * tvb, proto_tree *tree, int offset)
313 {
314         guint32 ack;
315         ack= tvb_get_letoh64(tvb, offset);
316         if (!ack)
317                 proto_tree_add_text(tree, tvb, offset, 8, "Not ack");
318         else
319                 proto_tree_add_item(tree, hf_lnet_ksm_zc_ack_cookie, tvb, offset, 8, little_endian);
320         return offset + 8;
321 }
322
323 static void 
324 dissect_ksock_msg_noop( tvbuff_t * tvb, packet_info *pinfo, proto_tree *tree)
325 {
326         guint32 offset;
327         offset=0;
328         proto_tree_add_item(tree, hf_lnet_ksm_type, tvb, offset, 4, TRUE);offset+=4;
329         offset=dissect_csum(tvb,tree,offset);
330         offset=dissect_req_cookie(tvb, tree, offset);
331         offset=dissect_ack_cookie(tvb,tree,offset);
332 }
333
334
335 static int dissect_ksock_msg(tvbuff_t * tvb, proto_tree *tree, int offset)
336 {
337         proto_tree_add_item(tree, hf_lnet_ksm_type, tvb, offset, 4, TRUE);offset+=4;
338         offset=dissect_csum(tvb,tree,offset);
339         offset=dissect_req_cookie(tvb, tree, offset);
340         offset=dissect_ack_cookie(tvb,tree,offset);
341         return offset;
342 }
343
344 static int
345 dissect_ib_msg(tvbuff_t *tvb, proto_tree *tree, int offset)
346 {
347         /* typedef struct
348          * {
349          *      __u32             ibm_magic;            * I'm an ibnal message *
350          *      __u16             ibm_version;          * this is my version *
351
352          *      __u8              ibm_type;             * msg type *
353          *      __u8              ibm_credits;          * returned credits *
354          *      __u32             ibm_nob;              * # bytes in message *
355          *      __u32             ibm_cksum;            * checksum (0 == no
356          *                                                checksum) *
357          *      __u64             ibm_srcnid;           * sender's NID *
358          *      __u64             ibm_srcstamp;         * sender's incarnation *
359          *      __u64             ibm_dstnid;           * destination's NID *
360          *      __u64             ibm_dststamp;         * destination's
361          *                                                incarnation *
362
363          *      union {
364          *              kib_connparams_t      connparams;
365          *              kib_immediate_msg_t   immediate;
366          *              kib_putreq_msg_t      putreq;
367          *              kib_putack_msg_t      putack;
368          *              kib_get_msg_t         get;
369          *              kib_completion_msg_t  completion;
370          *      } WIRE_ATTR ibm_u;
371          *} WIRE_ATTR kib_msg_t;   */
372
373         t_nid src_nid;
374         t_nid dst_nid;
375         guint8 msg_type;
376
377         proto_tree_add_item(tree, hf_lnet_ib_magic, tvb, offset, 4,
378                             little_endian);
379         offset += 4;
380         proto_tree_add_item(tree, hf_lnet_ib_version, tvb, offset, 2,
381                             little_endian);
382         offset += 2;
383         msg_type = tvb_get_guint8(tvb, offset);
384         proto_tree_add_item(tree, hf_lnet_ib_type, tvb, offset, 1,
385                             little_endian);
386         offset += 1;
387         proto_tree_add_item(tree, hf_lnet_ib_credits, tvb, offset, 1,
388                             little_endian);
389         offset += 1;
390         proto_tree_add_item(tree, hf_lnet_ib_nob, tvb, offset, 4,
391                             little_endian);
392         offset += 4;
393         offset = dissect_csum(tvb, tree, offset);
394
395         src_nid = get_nid(tvb, offset);
396         proto_tree_add_text(tree, tvb, offset, 8, "src_nid = %s@tcp%d",
397                             ip_to_str((guint8 *) &src_nid.addr),
398                             src_nid.interface);
399         offset += 8;
400         proto_tree_add_item(tree, hf_lnet_ib_srcstamp, tvb, offset, 8,
401                             little_endian);
402         offset += 8;
403
404         dst_nid = get_nid(tvb, offset);
405         proto_tree_add_text(tree, tvb, offset, 8, "dst_nid = %s@tcp%d",
406                             ip_to_str((guint8 *) &dst_nid.addr),
407                             dst_nid.interface);
408         offset += 8;
409         proto_tree_add_item(tree, hf_lnet_ib_dststamp, tvb,offset, 8,
410                             little_endian);
411         offset += 8;
412
413         /* LNet payloads only exist when the LND msg type is IMMEDIATE.
414            Return a zero offset for all other types. */
415         return (msg_type == IBLND_MSG_IMMEDIATE) ? offset : 0;
416 }
417
418 static int dissect_dest_nid(tvbuff_t * tvb, proto_tree *tree, int offset)
419 {
420         proto_tree_add_item(tree, hf_lnet_dest_nid_addr, tvb, offset, 4, TRUE);offset+=4;
421         proto_tree_add_item(tree, hf_lnet_dest_nid_interface, tvb, offset, 2, TRUE);offset+=2;
422         proto_tree_add_item(tree, hf_lnet_dest_nid_lnet_type, tvb, offset, 2, TRUE);offset+=2;
423         return offset;
424 }
425
426
427 static int dissect_src_nid(tvbuff_t * tvb, proto_tree *tree, int offset)
428 {
429         proto_tree_add_item(tree, hf_lnet_src_nid_addr, tvb, offset, 4, TRUE);offset+=4;
430         proto_tree_add_item(tree, hf_lnet_src_nid_interface, tvb, offset, 2, TRUE);offset+=2;
431         proto_tree_add_item(tree, hf_lnet_src_nid_lnet_type, tvb, offset, 2, TRUE);offset+=2;
432         return offset;
433 }
434
435 static int dissect_lnet_put(tvbuff_t * tvb, proto_tree *tree, int offset, packet_info *pinfo _U_)
436 {
437         /* typedef struct lnet_put {
438                  lnet_handle_wire_t  ack_wmd;
439                  __u64               match_bits;
440                  __u64               hdr_data;
441                  __u32               ptl_index;
442                  __u32               offset;
443                  } WIRE_ATTR lnet_put_t; */
444
445         proto_tree_add_item(tree,hf_dst_wmd_interface,tvb,offset,8,little_endian); offset+=8;
446         proto_tree_add_item(tree,hf_dst_wmd_object,tvb,offset,8,little_endian);offset+=8;
447
448         proto_tree_add_item(tree,hf_match_bits,tvb,offset,8,little_endian);offset+=8;
449         proto_tree_add_item(tree,hf_hdr_data,tvb,offset,8,little_endian);offset+=8;
450         if (check_col(pinfo->cinfo, COL_INFO)) 
451                 col_append_sep_str(pinfo->cinfo, COL_INFO, ", ",
452                 val_to_str(tvb_get_letohl(tvb, offset), portal_indices,
453                            "Unknown")); /* add some nice value  */
454         proto_item_append_text(tree, ", %s" , val_to_str(tvb_get_letohl(tvb,
455                                                                         offset),
456                                                          portal_indices,
457                                                          "Unknown"));
458                                                          /* print ptl_index */
459         proto_tree_add_item(tree,hf_ptl_index,tvb,offset,4,little_endian);offset+=4;
460         proto_tree_add_item(tree,hf_offset,tvb,offset,4,little_endian);offset+=4;
461         return offset ; 
462 }
463
464 static int dissect_lnet_get(tvbuff_t * tvb, proto_tree *tree, int offset, packet_info *pinfo _U_)
465 {
466         /* typedef struct lnet_get {
467                  lnet_handle_wire_t  return_wmd;
468                  __u64               match_bits;
469                  __u32               ptl_index;
470                  __u32               src_offset;
471                  __u32               sink_length;
472                  } WIRE_ATTR lnet_get_t; */
473
474         proto_tree_add_item(tree,hf_dst_wmd_interface,tvb,offset,8,little_endian);offset+=8;
475         proto_tree_add_item(tree,hf_dst_wmd_object,tvb,offset,8,little_endian);offset+=8;
476         /*if (check_col(pinfo->cinfo, COL_INFO))*/
477         /*        col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, " %" G_GINT64_MODIFIER "u ", tvb_get_letoh64(tvb,offset) );*/
478
479         proto_tree_add_item(tree,hf_match_bits,tvb,offset,8,little_endian);offset+=8;
480         if (check_col(pinfo->cinfo, COL_INFO)) 
481                 col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", val_to_str(tvb_get_letohl(tvb,offset), portal_indices, "Unknown"));
482         proto_item_append_text(tree, ", %s" , val_to_str(tvb_get_letohl(tvb,offset), portal_indices, "Unknown"));
483         proto_tree_add_item(tree,hf_ptl_index,tvb,offset,4,little_endian);offset+=4;
484         proto_tree_add_item(tree,hf_src_offset,tvb,offset,4,little_endian);offset+=4;
485         proto_tree_add_item(tree,hf_sink_length,tvb,offset,4,little_endian);offset+=4;
486         return offset; 
487 }
488
489 static int dissect_lnet_reply(tvbuff_t * tvb, proto_tree *tree, int offset)
490 {
491         /* typedef struct lnet_reply {
492                  lnet_handle_wire_t  dst_wmd;
493                  } WIRE_ATTR lnet_reply_t; */
494
495         proto_tree_add_item(tree,hf_dst_wmd_interface,tvb,offset,8,little_endian);offset+=8; 
496         proto_tree_add_item(tree,hf_dst_wmd_object,tvb,offset,8,little_endian);offset+=8;
497
498         return offset;
499 }
500
501
502 static int dissect_lnet_hello(tvbuff_t * tvb, proto_tree *tree, int offset)
503 {
504         /* typedef struct lnet_hello {
505                  __u64              incarnation;
506                  __u32              type;
507                  } WIRE_ATTR lnet_hello_t; */
508
509         proto_tree_add_item(tree,hf_hello_incarnation,tvb,offset,8,little_endian); offset+=8;
510         proto_tree_add_item(tree,hf_hello_type,tvb,offset,4,little_endian); offset+=4;
511         return offset; 
512 }
513
514 static int dissect_lnet_ack(tvbuff_t * tvb, proto_tree *tree, int offset, packet_info *pinfo _U_)
515 {
516         /* typedef struct lnet_ack {
517                  lnet_handle_wire_t  dst_wmd;
518                  __u64               match_bits;
519                  __u32               mlength;
520                  } WIRE_ATTR lnet_ack_t; */
521
522         proto_tree_add_item(tree,hf_dst_wmd_interface,tvb,offset,8,TRUE); offset+=8;
523         proto_tree_add_item(tree,hf_dst_wmd_object,tvb,offset,8,TRUE);offset+=8;
524         proto_tree_add_item(tree,hf_match_bits,tvb,offset,8, little_endian);offset+=8;
525         proto_tree_add_item(tree,hf_mlength, tvb,offset,4, little_endian); offset+=4;
526         return offset ; 
527
528
529 static void dissect_lnet_message(tvbuff_t * tvb, packet_info *pinfo, proto_tree *tree); 
530
531 /* The next two length getting routines are only used for KSOCK LNK messages. */
532 static guint 
533 get_lnet_message_len(packet_info  __attribute__((__unused__))*pinfo, tvbuff_t *tvb, int offset) 
534
535         guint32 plen;
536
537         /* Get the payload length */
538         plen = tvb_get_letohl(tvb,offset+28+24); /* 24 = ksm header,
539                                                      28 = the rest of the
540                                                           headers */
541
542         /* That length doesn't include the header; add that in. */
543         return plen + 72 +24 ; /*  +24 == ksock msg header.. :D */
544
545 }
546
547 static guint
548 get_noop_message_len(packet_info  __attribute__((__unused__))*pinfo, tvbuff_t *tvb, int offset)
549 {
550         return 24;
551 }
552
553 static void 
554 dissect_lnet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)  
555 {
556         /* TODO : correct this, now we do a difference between packet with
557            NOOP and others ..  but I don't find how to use pdu_dissect with
558            a variable length<=LNET_HEADER_LEN */
559         ib_packet = 0;
560         switch(tvb_get_letohl(tvb,0)){
561                 case KSOCK_MSG_NOOP:
562                         /*g_print("ksock noop %d \n", pinfo->fd->num);*/
563                         tcp_dissect_pdus(tvb,pinfo,tree,TRUE,0, get_noop_message_len,dissect_ksock_msg_noop);
564                         break;
565                 case KSOCK_MSG_LNET:
566                         tcp_dissect_pdus(tvb,pinfo,tree,TRUE,LNET_HEADER_LEN, get_lnet_message_len,dissect_lnet_message);
567                         break;
568         }
569
570 }
571
572 static int
573 dissect_ib_lnet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
574 {
575         /* We can tell if this is an LNet payload by looking at the first
576          * 32-bit word for our magic number. */
577         if (tvb_get_letohl(tvb, 0) != LNET_PROTO_IB_MAGIC) {
578                 /* Not an LNet payload. */
579                 return 0;
580         }
581
582         ib_packet = 1;
583         dissect_lnet_message(tvb, pinfo, tree);
584         return tvb_length(tvb);
585 }
586
587 /*----------------------------------------------------------- */
588 /* For the conversation */
589
590 typedef struct {
591         guint64 match_bits;
592 } my_entry_t;
593
594
595 typedef struct lnet_request_key {
596         guint64 match_bits ;
597         guint32 conversation;
598 } lnet_request_key_t;
599
600 typedef struct lnet_request_val {
601         guint64 match_bits;
602         guint32 packet_num_parent;
603 } lnet_request_val_t;
604
605
606 static GHashTable *lnet_request_hash;
607
608 /*
609  * Hash Functions
610  */
611 static gint
612 lnet_equal(gconstpointer v, gconstpointer w)
613 {
614         const struct lnet_request_key *v1 = (const struct lnet_request_key *)v;
615         const struct lnet_request_key *v2 = (const struct lnet_request_key *)w;
616
617         if (v1 -> conversation == v2 -> conversation &&
618                         v1 -> match_bits == v2 -> match_bits)
619         {
620
621                 return 1;
622         }
623
624         return 0;
625 }
626
627 static guint
628 lnet_hash (gconstpointer v)
629 {
630         const struct lnet_request_key *key = (const struct lnet_request_key *)v;
631         return key -> conversation + key -> match_bits;
632 }
633
634
635 static void
636 lnet_init_protocol(void)
637 {
638         if (lnet_request_hash)
639                 g_hash_table_destroy(lnet_request_hash);
640
641         lnet_request_hash = g_hash_table_new(lnet_hash, lnet_equal);
642 }
643
644
645 static lnet_request_val_t*
646 get_lnet_conv(packet_info * pinfo , GHashTable * lnet_hash_table,  guint64 match_bits )
647 {
648         conversation_t *  conversation ; 
649         lnet_request_key_t request_key, *new_request_key;
650         lnet_request_val_t *request_val=NULL ;
651
652         conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
653
654
655         if (NULL == conversation)
656                 /* It's not part of any conversation - create a new one. */
657                 conversation = conversation_new(pinfo->fd->num,  &pinfo->src, &pinfo->dst, proto_lnet,
658                                 pinfo->srcport, pinfo->destport, 0);
659
660         request_key.conversation = conversation->index;
661         request_key.match_bits = match_bits;
662
663         request_val = (struct lnet_request_val * ) g_hash_table_lookup(lnet_hash_table, &request_key);
664         if(!request_val){
665                 new_request_key = se_alloc(sizeof(struct lnet_request_key));
666                 *new_request_key = request_key;
667                 request_val = se_alloc(sizeof(struct lnet_request_val));
668                 request_val -> match_bits = match_bits;
669                 request_val -> packet_num_parent = pinfo->fd->num ;
670                 /*request_val -> filename = "test" ; */
671                 g_hash_table_insert(lnet_hash_table, new_request_key, request_val);
672
673         }
674
675         return request_val ;
676
677 }
678
679
680
681 /*----------------------------------------------------------- */
682 static void
683 dissect_lnet_message(tvbuff_t * tvb, packet_info *pinfo, proto_tree *tree)
684 {
685
686         guint64 match;
687         guint32 msg_type;
688
689         lnet_request_val_t* conversation_val ;
690
691
692         if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
693                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Lnet");
694         }
695
696         if (check_col(pinfo->cinfo, COL_INFO)) {
697                 /* t_nid dest_nid ; */
698                 /*t_nid src_nid ; */
699                 /*guint32 msg_type;*/
700                 /*[> col_clear(pinfo->cinfo, COL_INFO); <]*/
701                 /*dest_nid = get_nid(tvb, LNET_NID_DEST_OFFSET);*/
702                 /*src_nid = get_nid(tvb, LNET_NID_SRC_OFFSET);*/
703
704                 /*[> col_add_fstr(pinfo->cinfo, COL_INFO, "%s@tcp%d > %s@tcp%d",
705                         ip_to_str((guint8 *) &src_nid.addr), src_nid.interface,
706                         ip_to_str((guint8 *) & dest_nid.addr), dest_nid.interface); */
707
708                 msg_type = tvb_get_letohl(tvb, LNET_MSG_TYPE_OFFSET );
709                 /* We delete the entire line and add LNET  + msg_type */
710                 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");
711         }
712
713         if (tree) {
714                 t_nid dest_nid ; /* nid value */
715                 t_nid src_nid ; 
716
717
718                 proto_item *ti = NULL; /* principal  node */
719                 proto_tree *lnet_tree = NULL ; /* principal tree */
720                 proto_tree *lnet_nid_src_tree= NULL ; /*subtree for the nids*/
721                 proto_tree *lnet_nid_dest_tree= NULL ; 
722                 proto_item *ti_src_nid ; /* node for the nids */
723                 proto_item *ti_dest_nid ; 
724
725                 gint offset = 0 ; 
726
727                 guint32 msg_type ;
728                 guint32 payload_length; 
729                 guint32 msg_filler_length;
730
731
732                 ti = proto_tree_add_item(tree,proto_lnet,tvb,0,-1,FALSE); /* principal node */ 
733                 /*      ti=proto_tree_add_protocol_format(tree, proto_lnet, tvb, 0, -1, "Lnet"); */
734
735                 lnet_tree = proto_item_add_subtree(ti,ett_lnet); /* add the subtree*/
736
737                 if (ib_packet) {
738                         offset = dissect_ib_msg(tvb, lnet_tree, offset);
739                         if (offset == 0) {
740                                 /*  There was no LNet payload, only ob2lnd. */
741                                 return;
742                         }
743                 } else {
744                         /* dissect the first 24 bytes (ksock_msg_t in
745                            lnet/socklnd.h */
746                         offset=dissect_ksock_msg(tvb,lnet_tree,offset);
747                 }
748
749                 /* Dest nid */
750                 dest_nid = get_nid(tvb, offset);
751                 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);
752                 lnet_nid_dest_tree = proto_item_add_subtree(ti_dest_nid,ett_lnet_dest_nid) ; 
753                 offset=dissect_dest_nid(tvb,lnet_nid_dest_tree,offset); 
754
755                 /* Same for src_nid */
756                 src_nid = get_nid(tvb, offset);
757                 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);
758                 lnet_nid_src_tree = proto_item_add_subtree(ti_src_nid,ett_lnet_src_nid) ; 
759                 offset=dissect_src_nid(tvb,lnet_nid_src_tree,offset);
760
761                 /* pid */
762                 proto_tree_add_item(lnet_tree, hf_lnet_src_pid, tvb, offset, 4, TRUE); offset+=4;
763                 proto_tree_add_item(lnet_tree, hf_lnet_dest_pid, tvb, offset, 4, TRUE); offset+=4;
764
765                 /* message_type (32 bits) */
766                 msg_type = tvb_get_letohl(tvb, offset+0);
767                 /* put some nice info on lnet line */ 
768                 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 */
769                 proto_tree_add_item(lnet_tree, hf_lnet_msg_type, tvb, offset, 4, TRUE); offset+=4;
770
771                 /* payload data (to follow) length :*/
772                 payload_length = tvb_get_letohl(tvb,offset+0);  
773                 proto_tree_add_item(lnet_tree, hf_lnet_payload_length, tvb, offset, 4, TRUE); offset+=4;
774
775                 /* here offset = 24+8+8+4+4+4+4 = 56 */
776                 match = 0 ;
777                 switch(msg_type) {
778                         case LNET_MSG_ACK:
779                                 offset=dissect_lnet_ack(tvb,lnet_tree,offset,pinfo);
780                                 match = tvb_get_letoh64(tvb,72 );
781                                 break;
782                         case LNET_MSG_PUT:
783                                 offset=dissect_lnet_put(tvb,lnet_tree,offset,pinfo);
784                                 match = tvb_get_letoh64(tvb, 72);
785                                 break;
786                         case LNET_MSG_GET:
787                                 offset=dissect_lnet_get(tvb,lnet_tree,offset,pinfo);
788                                 match = tvb_get_letoh64(tvb, 72);
789                                 break;
790                         case LNET_MSG_REPLY:
791                                 offset=dissect_lnet_reply(tvb,lnet_tree,offset);
792                                 break;
793                         case LNET_MSG_HELLO:
794                                 offset=dissect_lnet_hello(tvb,lnet_tree,offset);
795                                 break;
796                         default:
797                                 break;
798                 }
799
800
801                 conversation_val = get_lnet_conv(pinfo , lnet_request_hash, match );
802                 /*      proto_tree_add_text(tree, tvb, 0 , 0, "match = %" G_GINT64_MODIFIER "u parent = %d", conversation_val -> match_bits , conversation_val -> packet_num_parent); */
803
804
805                 /* padding */
806                 msg_filler_length = 72 - offset + 24 ; 
807                 if ( msg_filler_length > 72)
808                         return ;
809                 /*  +24 : ksosck_message take 24bytes, and allready in offset  */
810
811                 proto_tree_add_item(lnet_tree, hf_lnet_msg_filler, tvb, offset,
812                                     msg_filler_length, little_endian);
813                 offset+=msg_filler_length;
814
815                 if (payload_length>0)
816                 {
817
818                         /* display of payload */ 
819                         proto_tree_add_item(lnet_tree, hf_lnet_payload, tvb,
820                                             offset, payload_length,
821                                             little_endian);
822
823                         next_tvb = tvb_new_subset (tvb, offset, payload_length, payload_length);
824                         if(msg_type==LNET_MSG_PUT)
825                                 dissector_try_port(subdissector_table, tvb_get_letohl(tvb,LNET_PTL_INDEX_OFFSET_PUT), next_tvb, pinfo, tree);
826
827                 }
828
829                 offset+=payload_length;
830         } 
831 }
832
833 void
834 proto_register_lnet(void)
835 {
836         static hf_register_info hf[] = {
837                 { &hf_lnet_ksm_type           , 
838                         { "Type of socklnd message"   , "lnet.ksm_type"                , FT_UINT32 , BASE_HEX     , VALS(ksm_type_t)      , 0x0 , ""         , HFILL }} , 
839                 { &hf_lnet_ksm_csum           , 
840                         { "Checksum"                  , "lnet.ksm_csum"                , FT_UINT32 , BASE_DEC     , NULL                  , 0x0 , ""         , HFILL }} , 
841                 { &hf_lnet_ksm_zc_req_cookie  , 
842                         { "Ack required"              , "lnet.ksm_zc_req_cookie"       , FT_UINT64 , BASE_HEX     , NULL                  , 0x0 , ""         , HFILL }} , 
843                 { &hf_lnet_ksm_zc_ack_cookie  , 
844                         { "Ack"                       , "lnet.ksm_zc_ack_cookie"       , FT_UINT64 , BASE_HEX     , NULL                  , 0x0 , ""         , HFILL }} , 
845                 { &hf_lnet_ib_magic,
846                         { "Magic of IB message", "lnet.ib.magic", FT_UINT32,
847                           BASE_HEX, NULL, 0x0, "", HFILL} },
848                 { &hf_lnet_ib_version,
849                         { "Version", "lnet.ib.version", FT_UINT16, BASE_HEX,
850                           VALS(ib_version_t), 0x0, "", HFILL} },
851                 { &hf_lnet_ib_type,
852                         { "Type of IB message", "lnet.ib.type", FT_UINT8,
853                           BASE_HEX, VALS(ib_type_t), 0x0, "", HFILL} },
854                 { &hf_lnet_ib_credits,
855                         { "Returned Credits", "lnet.ib.credits", FT_UINT8,
856                           BASE_DEC, NULL, 0x0, "", HFILL} },
857                 { &hf_lnet_ib_nob,
858                         { "Number of Bytes", "lnet.ib.nob", FT_UINT32,
859                           BASE_DEC, NULL, 0x0, "", HFILL} },
860                 { &hf_lnet_ib_csum,
861                         { "Checksum", "lnet.ib_csum", FT_UINT32, BASE_DEC,
862                           NULL, 0x0, "", HFILL} },
863                 { &hf_lnet_ib_srcstamp,
864                         { "Sender Timestamp", "lnet.ib.srcstamp",
865                           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
866                           "", HFILL} },
867                 { &hf_lnet_ib_dststamp,
868                         { "Destination Timestamp", "lnet.ib.dststamp",
869                           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
870                           "", HFILL} },
871
872                 { &hf_lnet_src_nid            , 
873                         { "Src nid"                   , "lnet.src_nid"                 , FT_UINT64 , BASE_HEX     , NULL                  , 0x0 , "src nid"  , HFILL }} , 
874                 { &hf_lnet_src_nid_addr       , 
875                         { "Src nid"                   , "lnet.src_nid_addr"            , FT_IPv4   , BASE_NONE    , NULL                  , 0x0 , ""         , HFILL }} , 
876                 { &hf_lnet_src_nid_lnet_type  , 
877                         { "lnd network type"          , "lnet.src_nid_type"            , FT_UINT16 , BASE_DEC     , VALS(lndnames)       , 0x0 , ""         , HFILL} },
878                 { &hf_lnet_src_nid_interface  , 
879                         { "lnd network interface"     , "lnet.src_nid_net_interface"   , FT_UINT16 , BASE_DEC     , NULL                  , 0x0 , NULL       , HFILL }} , 
880
881                 { &hf_lnet_dest_nid           , 
882                         { "Dest nid"                  , "lnet.dest_nid"                , FT_UINT64 , BASE_HEX     , NULL                  , 0x0 , ""         , HFILL }} , 
883
884                 { &hf_lnet_dest_nid_addr      , 
885                         { "Destination nid"           , "lnet.dest_nid_addr"           , FT_IPv4   , BASE_NONE    , NULL                  , 0x0 , ""         , HFILL }} , 
886                 { &hf_lnet_dest_nid_lnet_type , 
887                         { "lnd network type"          , "lnet.dest_nid_type"           , FT_UINT16 , BASE_DEC     , VALS(lndnames)       , 0x0 , ""         , HFILL} },
888                 { &hf_lnet_dest_nid_interface , 
889                         { "lnd network interface"     , "lnet.dest_nid_net_interface"  , FT_UINT16 , BASE_DEC     , NULL                  , 0x0 , NULL       , HFILL }} , 
890
891                 { &hf_lnet_dest_pid           , 
892                         { "Dest pid"                  , "lnet.dest_pid"                , FT_UINT32 , BASE_DEC_HEX , NULL                  , 0x0 , "dest pid" , HFILL }} , 
893                 { &hf_lnet_src_pid            , 
894                         { "Src pid"                   , "lnet.src_pid"                 , FT_UINT32 , BASE_DEC_HEX , NULL                  , 0x0 , "src nid"  , HFILL }} , 
895
896                 { &hf_lnet_msg_type           , 
897                         { "Message type"              , "lnet.msg_type"                , FT_UINT32 , BASE_DEC     , VALS(lnet_msg_type_t) , 0x0 , "msg type" , HFILL }} , 
898                 { &hf_lnet_payload_length     , 
899                         { "Payload length"            , "lnet.payload_length"          , FT_UINT32 , BASE_DEC     , NULL                  , 0x0 , ""         , HFILL }} , 
900                 { &hf_lnet_payload            , 
901                         { "Payload"                   , "lnet.payload"                 , FT_NONE   , BASE_NONE    , NULL                  , 0x0 , ""         , HFILL }} , 
902
903                 {&hf_dst_wmd                  , 
904                         { "DST MD index "             , "lnet.msg_dst_cookie"          , FT_BYTES  , BASE_NONE    , NULL                  , 0x0 , ""         , HFILL }} , 
905                 { &hf_dst_wmd_interface       , 
906                         { "DST MD index interface"    , "lnet.msg_dst_inteface_cookie" , FT_UINT64 , BASE_HEX_DEC , NULL                  , 0x0 , ""         , HFILL }} , 
907                 { &hf_dst_wmd_object          , 
908                         { "DST MD index object"       , "lnet.msg_dst_object_cookie"   , FT_UINT64 , BASE_HEX_DEC , NULL                  , 0x0 , ""         , HFILL }} , 
909                 { &hf_match_bits              , 
910                         { "Match bits"                , "lnet.msg_dst_match_bits"      , FT_UINT64 , BASE_HEX_DEC , NULL                  , 0x0 , ""         , HFILL}}  , 
911                 { &hf_mlength                 , 
912                         { "Message length"            , "lnet.msg_length"              , FT_UINT32 , BASE_DEC     , NULL                  , 0x0 , ""         , HFILL}}  , 
913
914
915                 /* Put */
916                 { &hf_hdr_data                , 
917                         { "hdr data"                  , "lnet.msg_hdr_data"            , FT_UINT64 , BASE_HEX_DEC , NULL                  , 0x0 , ""         , HFILL}}  , 
918                 { &hf_ptl_index               , 
919                         { "ptl index"                 , "lnet.ptl_index"               , FT_UINT32 , BASE_DEC     , VALS(portal_indices)  , 0x0 , ""         , HFILL}}  , 
920                 { &hf_offset                  , 
921                         { "offset"                    , "lnet.offset"                  , FT_UINT32 , BASE_DEC     , NULL                  , 0x0 , ""         , HFILL}}  , 
922
923                 /* Get*/
924                 { &hf_src_offset              , 
925                         { "src offset"                , "lnet.src_offset"              , FT_UINT32 , BASE_DEC     , NULL                  , 0x0 , ""         , HFILL}}  , 
926                 { &hf_sink_length             , 
927                         { "sink length"               , "lnet.sink_length"             , FT_UINT32 , BASE_DEC     , NULL                  , 0x0 , ""         , HFILL}}  , 
928
929                 /* Hello*/
930                 { &hf_hello_incarnation       , 
931                         { "hello incarnation "        , "lnet.hello_incarnation"       , FT_UINT64 , BASE_HEX_DEC , NULL                  , 0x0 , ""         , HFILL}}  , 
932                 { &hf_hello_type              , 
933                         { "hello type"                , "lnet.hello_type"              , FT_UINT32 , BASE_DEC     , NULL                  , 0x0 , ""         , HFILL}}  , 
934
935                 { &hf_lnet_msg_header         , 
936                         { "ptl header"                , "lnet.ptl_header"              , FT_NONE   , BASE_NONE    , NULL                  , 0x0 , ""         , HFILL}}  , 
937
938                 { &hf_lnet_msg_filler         , 
939                         { "msg filler (padding)"      , "lnet.ptl_filler"              , FT_NONE   , BASE_NONE    , NULL                  , 0x0 , ""         , HFILL}}  , 
940
941                 /* Add more fields here */
942         };
943
944         static gint *ett[] = {
945                 &ett_lnet,
946                 &ett_lnet_dest_nid,
947                 &ett_lnet_src_nid
948         };
949
950
951         module_t *lnet_module;
952
953         proto_lnet = proto_register_protocol("Lnet", /*name*/
954                         "Lnet",  /*short name*/
955                         "lnet"); /*abbrev*/
956
957         proto_register_field_array(proto_lnet, hf, array_length(hf));
958         proto_register_subtree_array(ett, array_length(ett));
959
960         lnet_module = prefs_register_protocol(proto_lnet, proto_reg_handoff_lnet);
961
962         prefs_register_uint_preference(lnet_module, "tcp.lnet_port",
963                         "Lnet listener TCP Port",
964                         "Set the TCP port for Lnet"
965                         "(if other than the default of 988)",
966                         10, &global_lnet_tcp_port);
967
968         subdissector_table = register_dissector_table("lnet.ptl_index", "lnet portal index", FT_UINT32 , BASE_DEC);
969
970         register_init_routine(&lnet_init_protocol);
971
972 }
973
974
975 /* The registration hand-off routine */
976 void
977 proto_reg_handoff_lnet(void)
978 {
979         static int lnet_prefs_initialized = FALSE;
980         static dissector_handle_t lnet_handle;
981
982         if(!lnet_prefs_initialized) {
983                 heur_dissector_add("infiniband.payload", dissect_ib_lnet,
984                                    proto_lnet);
985                 heur_dissector_add("infiniband.mad.cm.private",
986                                    dissect_ib_lnet, proto_lnet);
987                 lnet_handle = create_dissector_handle(dissect_lnet, proto_lnet);
988                 lnet_prefs_initialized = TRUE;
989         }
990         else
991                 dissector_delete("tcp.port",global_lnet_tcp_port, lnet_handle);
992
993         lnet_tcp_port = global_lnet_tcp_port;
994
995         dissector_add("tcp.port", lnet_tcp_port, lnet_handle);
996 }