Whamcloud - gitweb
32feb9553a71d3078791b657c6f7cd8de8317407
[fs/lustre-release.git] / lustre / contrib / 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
44 /* how much data has at least to be available to be able to determine the
45  * length of the lnet message */
46 #define LNET_HEADER_LEN 52
47 #define LNET_NID_DEST_OFFSET 24
48 #define LNET_NID_SRC_OFFSET 32
49 #define LNET_MSG_TYPE_OFFSET 48
50
51 static guint global_lnet_tcp_port = 988;
52 static guint lnet_tcp_port = 988;
53
54 void proto_reg_handoff_lnet(void);
55
56 #define LNET_PTL_INDEX_OFFSET_PUT 88
57
58 /* Define the lnet proto */
59 static int proto_lnet = -1;
60
61 static int hf_lnet_src_nid = -1 ;
62 static int hf_lnet_src_nid_addr = -1 ;
63 static int hf_lnet_src_nid_lnet_type = -1 ; 
64 static int hf_lnet_src_nid_interface = -1  ;
65
66 static int hf_lnet_ksm_type = -1 ;
67 static int hf_lnet_ksm_csum= -1;       
68 static int hf_lnet_ksm_zc_req_cookie=-1;
69 static int hf_lnet_ksm_zc_ack_cookie=-1; 
70
71 static int hf_lnet_dest_nid = -1 ;
72 static int hf_lnet_dest_nid_addr = -1 ;
73 static int hf_lnet_dest_nid_lnet_type = -1 ; 
74 static int hf_lnet_dest_nid_interface = -1 ;
75
76 static int hf_lnet_dest_pid = -1 ; 
77 static int hf_lnet_src_pid = -1 ;
78
79 static int hf_lnet_msg_type = -1 ;
80 static int hf_lnet_payload_length = -1;
81 static int hf_lnet_payload = -1 ;
82 static int hf_lnet_msg_header = -1 ; 
83 static int hf_lnet_msg_filler = -1 ;
84
85 static int hf_dst_wmd = -1 ;   
86 static int hf_dst_wmd_interface = -1 ;   
87 static int hf_dst_wmd_object = -1 ;   
88
89 static int hf_match_bits = -1 ; 
90 static int hf_mlength = -1 ; 
91
92 static int hf_hdr_data = -1 ;
93 static int hf_ptl_index = -1 ;
94 static int hf_offset = -1 ;
95 static gint ett_lnet = -1;
96
97 static int hf_src_offset = -1;
98 static int hf_sink_length = -1;
99
100 static int hf_hello_incarnation = -1 ;
101 static int hf_hello_type = -1 ; 
102
103 static gint ett_lnet_dest_nid= -1;
104 static gint ett_lnet_src_nid= -1;
105
106 tvbuff_t *next_tvb;
107
108 /*static heur_dissector_list_t heur_subdissector_list; */
109 static dissector_table_t subdissector_table;
110
111 static const value_string lnetnames[] = {
112         { 1, "QSWLND   "},
113         { 2, "SOCKLND  "},
114         { 3, "GMLND    "},
115         { 4, "PTLLND   "},
116         { 5, "O2IBLND  "},
117         { 6, "CIBLND   "},
118         { 7, "OPENIBLND"}, 
119         { 8, "IIBLND   "},
120         { 9, "LOLND    "},
121         { 10,"RALND    "},
122         { 11,"VIBLND   "},
123         { 12,"MXLND    "} 
124 };
125
126 enum MSG_type{
127         LNET_MSG_ACK = 0,
128         LNET_MSG_PUT,
129         LNET_MSG_GET,
130         LNET_MSG_REPLY,
131         LNET_MSG_HELLO,
132 } ;
133
134 static const value_string lnet_msg_type_t[] = {
135         { LNET_MSG_ACK  , "ACK"},  
136         { LNET_MSG_PUT  , "PUT"},  
137         { LNET_MSG_GET  , "GET"},  
138         { LNET_MSG_REPLY, "REPLY"},  
139         { LNET_MSG_HELLO, "HELLO"} 
140 };
141
142 /* defined in lustre/include/lustre/lustre_idl.h */
143 static const value_string portal_indices[] = {
144         { 1 , "CONNMGR_REQUEST_PORTAL"},
145         { 2 , "CONNMGR_REPLY_PORTAL"},
146         { 3 , "OSC_REQUEST_PORTAL(obsolete)"},
147         { 4 , "OSC_REPLY_PORTAL"},
148         { 5 , "OSC_BULK_PORTAL(obsolete)"},
149         { 6 , "OST_IO_PORTAL"},
150         { 7 , "OST_CREATE_PORTAL"},
151         { 8 , "OST_BULK_PORTAL"},
152         { 9 , "MDC_REQUEST_PORTAL(obsolete)"},
153         { 10 , "MDC_REPLY_PORTAL"},
154         { 11 , "MDC_BULK_PORTAL(obsolete)"},
155         { 12 , "MDS_REQUEST_PORTAL"},
156         { 13 , "MDS_REPLY_PORTAL(obsolete)"},
157         { 14 , "MDS_BULK_PORTAL"},
158         { 15 , "LDLM_CB_REQUEST_PORTAL"},
159         { 16 , "LDLM_CB_REPLY_PORTAL"},
160         { 17 , "LDLM_CANCEL_REQUEST_PORTAL"},
161         { 18 , "LDLM_CANCEL_REPLY_PORTAL"},
162         { 19 , "PTLBD_REQUEST_PORTAL(obsolete)"},
163         { 20 , "PTLBD_REPLY_PORTAL(obsolete)"},
164         { 21 , "PTLBD_BULK_PORTAL(obsolete)"},
165         { 22 , "MDS_SETATTR_PORTAL"},
166         { 23 , "MDS_READPAGE_PORTAL"},
167         { 25 , "MGC_REPLY_PORTAL"},
168         { 26 , "MGS_REQUEST_PORTAL"},
169         { 27 , "MGS_REPLY_PORTAL"},
170         { 28 , "OST_REQUEST_PORTAL"}
171 };
172
173 #define KSOCK_MSG_NOOP          0xc0            /* ksm_u empty */ 
174 #define KSOCK_MSG_LNET          0xc1            /* lnet msg */
175
176 static const value_string ksm_type_t[] = {
177         {0xc0, "KSOCK_MSG_NOOP"},/* ksm_u empty */ 
178         {0xc1, "KSOCK_MSG_LNET"} /* lnet msg */
179 };
180
181
182 static int dissect_csum(tvbuff_t * tvb, proto_tree *tree, int offset)
183 {
184         guint32 csum;
185         csum = tvb_get_letohl(tvb, offset);
186         if (!csum)
187                 proto_tree_add_text(tree, tvb, offset, 4, "checksum disabled");
188         else
189                 proto_tree_add_item(tree, hf_lnet_ksm_csum, tvb, offset, 4, TRUE);
190
191         offset+=4;
192         return offset;
193 }
194
195
196 static int dissect_req_cookie(tvbuff_t * tvb, proto_tree *tree, int offset)
197 {
198         guint32 req;
199         req= tvb_get_letoh64(tvb, offset);
200         if (!req)
201                 proto_tree_add_text(tree, tvb, offset, 8, "ack not required");
202         else
203                 proto_tree_add_item(tree, hf_lnet_ksm_zc_req_cookie, tvb, offset, 8, TRUE);
204         offset+=8;
205         return offset;
206 }
207
208 static int dissect_ack_cookie(tvbuff_t * tvb, proto_tree *tree, int offset)
209 {
210         guint32 ack;
211         ack= tvb_get_letoh64(tvb, offset);
212         if (!ack)
213                 proto_tree_add_text(tree, tvb, offset, 8, "not ack");
214         else
215                 proto_tree_add_item(tree, hf_lnet_ksm_zc_ack_cookie, tvb, offset, 8, TRUE);
216         offset+=8;
217         return offset;
218 }
219
220 static void 
221 dissect_ksock_msg_noop( tvbuff_t * tvb, packet_info *pinfo _U_ , proto_tree *tree)
222 {
223         guint32 offset;
224         offset=0;
225         proto_tree_add_item(tree, hf_lnet_ksm_type, tvb, offset, 4, TRUE);offset+=4;
226         offset=dissect_csum(tvb,tree,offset);
227         offset=dissect_req_cookie(tvb, tree, offset);
228         offset=dissect_ack_cookie(tvb,tree,offset);
229 }
230
231
232 static int dissect_ksock_msg(tvbuff_t * tvb, proto_tree *tree, int offset)
233 {
234         proto_tree_add_item(tree, hf_lnet_ksm_type, tvb, offset, 4, TRUE);offset+=4;
235         offset=dissect_csum(tvb,tree,offset);
236         offset=dissect_req_cookie(tvb, tree, offset);
237         offset=dissect_ack_cookie(tvb,tree,offset);
238         return offset;
239 }
240
241 static int dissect_dest_nid(tvbuff_t * tvb, proto_tree *tree, int offset)
242 {
243         proto_tree_add_item(tree, hf_lnet_dest_nid_addr, tvb, offset, 4, TRUE);offset+=4;
244         proto_tree_add_item(tree, hf_lnet_dest_nid_interface, tvb, offset, 2, TRUE);offset+=2;
245         proto_tree_add_item(tree, hf_lnet_dest_nid_lnet_type, tvb, offset, 2, TRUE);offset+=2;
246         return offset;
247 }
248
249
250 static int dissect_src_nid(tvbuff_t * tvb, proto_tree *tree, int offset)
251 {
252         proto_tree_add_item(tree, hf_lnet_src_nid_addr, tvb, offset, 4, TRUE);offset+=4;
253         proto_tree_add_item(tree, hf_lnet_src_nid_interface, tvb, offset, 2, TRUE);offset+=2;
254         proto_tree_add_item(tree, hf_lnet_src_nid_lnet_type, tvb, offset, 2, TRUE);offset+=2;
255         return offset;
256 }
257
258 static int dissect_lnet_put(tvbuff_t * tvb, proto_tree *tree, int offset, packet_info *pinfo _U_)
259 {
260         /* typedef struct lnet_put {
261                  lnet_handle_wire_t  ack_wmd;
262                  __u64               match_bits;
263                  __u64               hdr_data;
264                  __u32               ptl_index;
265                  __u32               offset;
266                  } WIRE_ATTR lnet_put_t; */
267
268         gboolean little_endian=TRUE ;
269
270         proto_tree_add_item(tree,hf_dst_wmd_interface,tvb,offset,8,little_endian); offset+=8;
271         proto_tree_add_item(tree,hf_dst_wmd_object,tvb,offset,8,little_endian);offset+=8;
272
273         proto_tree_add_item(tree,hf_match_bits,tvb,offset,8,little_endian);offset+=8;
274         proto_tree_add_item(tree,hf_hdr_data,tvb,offset,8,little_endian);offset+=8;
275         if (check_col(pinfo->cinfo, COL_INFO)) 
276                 col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", val_to_str(tvb_get_letohl(tvb,offset), portal_indices, "Unknow")); /* add some nice value  */
277         proto_item_append_text(tree, ", %s" , val_to_str(tvb_get_letohl(tvb,offset), portal_indices, "Unknow")); /* print ptl_index */
278         proto_tree_add_item(tree,hf_ptl_index,tvb,offset,4,little_endian);offset+=4;
279         proto_tree_add_item(tree,hf_offset,tvb,offset,4,little_endian);offset+=4;
280         return offset ; 
281 }
282
283 static int dissect_lnet_get(tvbuff_t * tvb, proto_tree *tree, int offset, packet_info *pinfo _U_)
284 {
285         /* typedef struct lnet_get {
286                  lnet_handle_wire_t  return_wmd;
287                  __u64               match_bits;
288                  __u32               ptl_index;
289                  __u32               src_offset;
290                  __u32               sink_length;
291                  } WIRE_ATTR lnet_get_t; */
292
293         gboolean little_endian=TRUE ;
294         proto_tree_add_item(tree,hf_dst_wmd_interface,tvb,offset,8,little_endian);offset+=8;
295         proto_tree_add_item(tree,hf_dst_wmd_object,tvb,offset,8,little_endian);offset+=8;
296         /*if (check_col(pinfo->cinfo, COL_INFO))*/
297         /*        col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, " %" G_GINT64_MODIFIER "u ", tvb_get_letoh64(tvb,offset) );*/
298
299         proto_tree_add_item(tree,hf_match_bits,tvb,offset,8,little_endian);offset+=8;
300         if (check_col(pinfo->cinfo, COL_INFO)) 
301                 col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", val_to_str(tvb_get_letohl(tvb,offset), portal_indices, "Unknow")); 
302         proto_item_append_text(tree, ", %s" , val_to_str(tvb_get_letohl(tvb,offset), portal_indices, "Unknow")); /* print ptl_index */
303         proto_tree_add_item(tree,hf_ptl_index,tvb,offset,4,little_endian);offset+=4;
304         proto_tree_add_item(tree,hf_src_offset,tvb,offset,4,little_endian);offset+=4;
305         proto_tree_add_item(tree,hf_sink_length,tvb,offset,4,little_endian);offset+=4;
306         return offset; 
307 }
308
309 static int dissect_lnet_reply(tvbuff_t * tvb, proto_tree *tree, int offset)
310 {
311         /* typedef struct lnet_reply {
312                  lnet_handle_wire_t  dst_wmd;
313                  } WIRE_ATTR lnet_reply_t; */
314
315         gboolean little_endian=TRUE ;
316         proto_tree_add_item(tree,hf_dst_wmd_interface,tvb,offset,8,little_endian);offset+=8; 
317         proto_tree_add_item(tree,hf_dst_wmd_object,tvb,offset,8,little_endian);offset+=8;
318
319         return offset;
320 }
321
322
323 static int dissect_lnet_hello(tvbuff_t * tvb, proto_tree *tree, int offset)
324 {
325         /* typedef struct lnet_hello {
326                  __u64              incarnation;
327                  __u32              type;
328                  } WIRE_ATTR lnet_hello_t; */
329
330         gboolean little_endian=TRUE ;
331         proto_tree_add_item(tree,hf_hello_incarnation,tvb,offset,8,little_endian); offset+=8;
332         proto_tree_add_item(tree,hf_hello_type,tvb,offset,4,little_endian); offset+=4;
333         return offset; 
334 }
335
336 static int dissect_lnet_ack(tvbuff_t * tvb, proto_tree *tree, int offset, packet_info *pinfo _U_)
337 {
338         /* typedef struct lnet_ack {
339                  lnet_handle_wire_t  dst_wmd;
340                  __u64               match_bits;
341                  __u32               mlength;
342                  } WIRE_ATTR lnet_ack_t; */
343
344         proto_tree_add_item(tree,hf_dst_wmd_interface,tvb,offset,8,TRUE); offset+=8;
345         proto_tree_add_item(tree,hf_dst_wmd_object,tvb,offset,8,TRUE);offset+=8;
346         proto_tree_add_item(tree,hf_match_bits,tvb,offset,8,TRUE);offset+=8;
347         proto_tree_add_item(tree,hf_mlength, tvb,offset,4,TRUE); offset+=4;
348         return offset ; 
349
350
351 static void dissect_lnet_message(tvbuff_t * tvb, packet_info *pinfo, proto_tree *tree); 
352 /* return the pdu length */ 
353 static guint 
354 get_lnet_message_len(packet_info  __attribute__((__unused__))*pinfo, tvbuff_t *tvb, int offset) 
355
356         /*
357          * Get the payload length
358          */
359         guint32 plen;
360         plen = tvb_get_letohl(tvb,offset+28+24); /*24 = ksm header, 28 = le reste des headers*/
361
362         /*
363          * That length doesn't include the header; add that in.
364          */
365         return plen + 72 +24 ; /*  +24 == ksock msg header.. :D */
366
367 }
368
369 static guint
370 get_noop_message_len(packet_info  __attribute__((__unused__))*pinfo, tvbuff_t *tvb _U_ , int offset _U_) 
371 {
372         return 24;
373 }
374
375 static void 
376 dissect_lnet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)  
377 {
378         /* TODO : correct this, now we do a difference between packet with NOOP and others ..
379                  but I don't find how to use pdu_dissect with a variable length<=LNET_HEADER_LEN */
380         switch(tvb_get_letohl(tvb,0)){
381                 case KSOCK_MSG_NOOP:
382                         /*g_print("ksock noop %d \n", pinfo->fd->num);*/
383                         tcp_dissect_pdus(tvb,pinfo,tree,TRUE,0, get_noop_message_len,dissect_ksock_msg_noop);
384                         break;
385                 case KSOCK_MSG_LNET:
386                         tcp_dissect_pdus(tvb,pinfo,tree,TRUE,LNET_HEADER_LEN, get_lnet_message_len,dissect_lnet_message);
387                         break;
388         }
389
390 }
391
392 typedef struct t_nid {
393         guint32 addr;
394         guint16 interface;
395         guint16 proto;
396 } t_nid ;
397
398 static t_nid get_nid(tvbuff_t *tvb, gint offset)
399 {
400         t_nid nid ;
401         nid.addr = g_htonl(tvb_get_ipv4(tvb,offset));
402         nid.interface = tvb_get_letohs(tvb,offset+4);
403         nid.proto = tvb_get_letohs(tvb,offset+6);
404         return nid ;
405         /* example : 
406          * get_nid(tvb, LNET_NID_DEST_OFFSET);
407          * get_nid(tvb, LNET_NID_SRC_OFFSET); 
408          * */
409 }
410
411 /*----------------------------------------------------------- */
412 /* For the conversation */
413
414 typedef struct {
415         guint64 match_bits;
416 } my_entry_t;
417
418
419 typedef struct lnet_request_key {
420         guint64 match_bits ;
421         guint32 conversation;
422 } lnet_request_key_t;
423
424 typedef struct lnet_request_val {
425         guint64 match_bits;
426         guint32 packet_num_parent;
427 } lnet_request_val_t;
428
429
430 static GHashTable *lnet_request_hash = NULL;
431
432 /*
433  * Hash Functions
434  */
435 static gint
436 lnet_equal(gconstpointer v, gconstpointer w)
437 {
438         const struct lnet_request_key *v1 = (const struct lnet_request_key *)v;
439         const struct lnet_request_key *v2 = (const struct lnet_request_key *)w;
440
441         if (v1 -> conversation == v2 -> conversation &&
442                         v1 -> match_bits == v2 -> match_bits)
443         {
444
445                 return 1;
446         }
447
448         return 0;
449 }
450
451 static guint
452 lnet_hash (gconstpointer v)
453 {
454         const struct lnet_request_key *key = (const struct lnet_request_key *)v;
455         guint val;
456
457         val = key -> conversation + key -> match_bits ;
458
459         return val;
460 }
461
462
463 static void
464 lnet_init_protocol(void)
465 {
466         if (lnet_request_hash)
467                 g_hash_table_destroy(lnet_request_hash);
468
469         lnet_request_hash = g_hash_table_new(lnet_hash, lnet_equal);
470 }
471
472
473 static lnet_request_val_t*
474 get_lnet_conv(packet_info * pinfo , GHashTable * lnet_hash_table,  guint64 match_bits )
475 {
476         conversation_t *  conversation ; 
477         lnet_request_key_t request_key, *new_request_key;
478         lnet_request_val_t *request_val=NULL ;
479
480         conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
481
482
483         if (NULL == conversation)
484                 /* It's not part of any conversation - create a new one. */
485                 conversation = conversation_new(pinfo->fd->num,  &pinfo->src, &pinfo->dst, proto_lnet,
486                                 pinfo->srcport, pinfo->destport, 0);
487
488         request_key.conversation = conversation->index;
489         request_key.match_bits = match_bits;
490
491         request_val = (struct lnet_request_val * ) g_hash_table_lookup(lnet_hash_table, &request_key);
492         if(!request_val){
493                 new_request_key = se_alloc(sizeof(struct lnet_request_key));
494                 *new_request_key = request_key;
495                 request_val = se_alloc(sizeof(struct lnet_request_val));
496                 request_val -> match_bits = match_bits;
497                 request_val -> packet_num_parent = pinfo->fd->num ;
498                 /*request_val -> filename = "test" ; */
499                 g_hash_table_insert(lnet_hash_table, new_request_key, request_val);
500
501         }
502
503         return request_val ;
504
505 }
506
507
508
509 /*----------------------------------------------------------- */
510 static void
511 dissect_lnet_message(tvbuff_t * tvb, packet_info *pinfo, proto_tree *tree)
512 {
513
514         guint64 match;
515         guint32 msg_type;
516
517         lnet_request_val_t* conversation_val ;
518
519
520         if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
521                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Lnet");
522         }
523
524         if (check_col(pinfo->cinfo, COL_INFO)) {
525                 /* t_nid dest_nid ; */
526                 /*t_nid src_nid ; */
527                 /*guint32 msg_type;*/
528                 /*[> col_clear(pinfo->cinfo, COL_INFO); <]*/
529                 /*dest_nid = get_nid(tvb, LNET_NID_DEST_OFFSET);*/
530                 /*src_nid = get_nid(tvb, LNET_NID_SRC_OFFSET);*/
531
532                 /*[> col_add_fstr(pinfo->cinfo, COL_INFO, "%s@tcp%d > %s@tcp%d",
533                         ip_to_str((guint8 *) &src_nid.addr), src_nid.interface,
534                         ip_to_str((guint8 *) & dest_nid.addr), dest_nid.interface); */
535
536                 msg_type = tvb_get_letohl(tvb, LNET_MSG_TYPE_OFFSET );
537                 /* We delete the entire line and add LNET  + msg_type */
538                 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 : "Unknow") ; 
539         }
540
541         if (tree) {
542                 t_nid dest_nid ; /* nid value */
543                 t_nid src_nid ; 
544
545
546                 proto_item *ti = NULL; /* principal  node */
547                 proto_tree *lnet_tree = NULL ; /* principal tree */
548                 proto_tree *lnet_nid_src_tree= NULL ; /*subtree for the nids*/
549                 proto_tree *lnet_nid_dest_tree= NULL ; 
550                 proto_item *ti_src_nid ; /* node for the nids */
551                 proto_item *ti_dest_nid ; 
552
553                 gint offset = 0 ; 
554
555                 guint32 msg_type ;
556                 guint32 payload_length; 
557                 guint32 msg_filler_length;
558
559
560                 ti = proto_tree_add_item(tree,proto_lnet,tvb,0,-1,FALSE); /* principal node */ 
561                 /*      ti=proto_tree_add_protocol_format(tree, proto_lnet, tvb, 0, -1, "Lnet"); */
562
563                 lnet_tree = proto_item_add_subtree(ti,ett_lnet); /* add the subtree*/
564
565                 /* dissect the 24first bytes (ksock_msg_t in lnet/socklnd.h */
566                 offset=dissect_ksock_msg(tvb,lnet_tree,offset);
567
568                 /* dest nid */
569                 dest_nid = get_nid(tvb, LNET_NID_DEST_OFFSET);
570                 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);
571                 lnet_nid_dest_tree = proto_item_add_subtree(ti_dest_nid,ett_lnet_dest_nid) ; 
572                 offset=dissect_dest_nid(tvb,lnet_nid_dest_tree,offset); 
573
574                 /* same for src_nid */
575                 src_nid = get_nid(tvb, LNET_NID_SRC_OFFSET);
576                 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);
577                 lnet_nid_src_tree = proto_item_add_subtree(ti_src_nid,ett_lnet_src_nid) ; 
578                 offset=dissect_src_nid(tvb,lnet_nid_src_tree,offset);
579
580                 /* pid */
581                 proto_tree_add_item(lnet_tree, hf_lnet_src_pid, tvb, offset, 4, TRUE); offset+=4;
582                 proto_tree_add_item(lnet_tree, hf_lnet_dest_pid, tvb, offset, 4, TRUE); offset+=4;
583
584                 /* message_type (32 bits) */
585                 msg_type = tvb_get_letohl(tvb, offset+0);
586                 /* put some nice info on lnet line */ 
587                 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 */
588                 proto_tree_add_item(lnet_tree, hf_lnet_msg_type, tvb, offset, 4, TRUE); offset+=4;
589
590                 /* payload data (to follow) length :*/
591                 payload_length = tvb_get_letohl(tvb,offset+0);  
592                 proto_tree_add_item(lnet_tree, hf_lnet_payload_length, tvb, offset, 4, TRUE); offset+=4;
593
594                 /* here offset = 24+8+8+4+4+4+4 = 56 */
595                 match = 0 ;
596                 switch(msg_type) {
597                         case LNET_MSG_ACK:
598                                 offset=dissect_lnet_ack(tvb,lnet_tree,offset,pinfo);
599                                 match = tvb_get_letoh64(tvb,72 );
600                                 break;
601                         case LNET_MSG_PUT:
602                                 offset=dissect_lnet_put(tvb,lnet_tree,offset,pinfo);
603                                 match = tvb_get_letoh64(tvb, 72);
604                                 break;
605                         case LNET_MSG_GET:
606                                 offset=dissect_lnet_get(tvb,lnet_tree,offset,pinfo);
607                                 match = tvb_get_letoh64(tvb, 72);
608                                 break;
609                         case LNET_MSG_REPLY:
610                                 offset=dissect_lnet_reply(tvb,lnet_tree,offset);
611                                 break;
612                         case LNET_MSG_HELLO:
613                                 offset=dissect_lnet_hello(tvb,lnet_tree,offset);
614                                 break;
615                         default:
616                                 break;
617                 }
618
619
620                 conversation_val = get_lnet_conv(pinfo , lnet_request_hash, match );
621                 /*      proto_tree_add_text(tree, tvb, 0 , 0, "match = %" G_GINT64_MODIFIER "u parent = %d", conversation_val -> match_bits , conversation_val -> packet_num_parent); */
622
623
624                 /* padding */
625                 msg_filler_length = 72 - offset + 24 ; 
626                 if ( msg_filler_length > 72)
627                         return ;
628                 /*  +24 : ksosck_message take 24bytes, and allready in offset  */
629
630                 proto_tree_add_item(lnet_tree, hf_lnet_msg_filler, tvb, offset, msg_filler_length, TRUE);
631                 offset+=msg_filler_length;
632
633                 if (payload_length>0)
634                 {
635
636                         /* display of payload */ 
637                         proto_tree_add_item(lnet_tree,hf_lnet_payload, tvb, offset, payload_length, TRUE); 
638
639                         next_tvb = tvb_new_subset (tvb, offset, payload_length, payload_length);
640                         if(msg_type==LNET_MSG_PUT)
641                                 dissector_try_port(subdissector_table, tvb_get_letohl(tvb,LNET_PTL_INDEX_OFFSET_PUT), next_tvb, pinfo, tree);
642
643                 }
644
645                 offset+=payload_length;
646         } 
647 }
648
649 void
650 proto_register_lnet(void)
651 {
652         static hf_register_info hf[] = {
653                 { &hf_lnet_ksm_type           , 
654                         { "Type of socklnd message"   , "lnet.ksm_type"                , FT_UINT32 , BASE_HEX     , VALS(ksm_type_t)      , 0x0 , ""         , HFILL }} , 
655                 { &hf_lnet_ksm_csum           , 
656                         { "Checksum"                  , "lnet.ksm_csum"                , FT_UINT32 , BASE_DEC     , NULL                  , 0x0 , ""         , HFILL }} , 
657                 { &hf_lnet_ksm_zc_req_cookie  , 
658                         { "Ack required"              , "lnet.ksm_zc_req_cookie"       , FT_UINT64 , BASE_HEX     , NULL                  , 0x0 , ""         , HFILL }} , 
659                 { &hf_lnet_ksm_zc_ack_cookie  , 
660                         { "Ack"                       , "lnet.ksm_zc_ack_cookie"       , FT_UINT64 , BASE_HEX     , NULL                  , 0x0 , ""         , HFILL }} , 
661
662                 { &hf_lnet_src_nid            , 
663                         { "Src nid"                   , "lnet.src_nid"                 , FT_UINT64 , BASE_HEX     , NULL                  , 0x0 , "src nid"  , HFILL }} , 
664                 { &hf_lnet_src_nid_addr       , 
665                         { "Src nid"                   , "lnet.src_nid_addr"            , FT_IPv4   , BASE_NONE    , NULL                  , 0x0 , ""         , HFILL }} , 
666                 { &hf_lnet_src_nid_lnet_type  , 
667                         { "lnd network type"          , "lnet.src_nid_type"            , FT_UINT16 , BASE_DEC     , VALS(lnetnames)       , 0x0 , ""         , HFILL }} , 
668                 { &hf_lnet_src_nid_interface  , 
669                         { "lnd network interface"     , "lnet.src_nid_net_interface"   , FT_UINT16 , BASE_DEC     , NULL                  , 0x0 , NULL       , HFILL }} , 
670
671                 { &hf_lnet_dest_nid           , 
672                         { "Dest nid"                  , "lnet.dest_nid"                , FT_UINT64 , BASE_HEX     , NULL                  , 0x0 , ""         , HFILL }} , 
673
674                 { &hf_lnet_dest_nid_addr      , 
675                         { "Destination nid"           , "lnet.dest_nid_addr"           , FT_IPv4   , BASE_NONE    , NULL                  , 0x0 , ""         , HFILL }} , 
676                 { &hf_lnet_dest_nid_lnet_type , 
677                         { "lnd network type"          , "lnet.dest_nid_type"           , FT_UINT16 , BASE_DEC     , VALS(lnetnames)       , 0x0 , ""         , HFILL }} , 
678                 { &hf_lnet_dest_nid_interface , 
679                         { "lnd network interface"     , "lnet.dest_nid_net_interface"  , FT_UINT16 , BASE_DEC     , NULL                  , 0x0 , NULL       , HFILL }} , 
680
681                 { &hf_lnet_dest_pid           , 
682                         { "Dest pid"                  , "lnet.dest_pid"                , FT_UINT32 , BASE_DEC_HEX , NULL                  , 0x0 , "dest pid" , HFILL }} , 
683                 { &hf_lnet_src_pid            , 
684                         { "Src pid"                   , "lnet.src_pid"                 , FT_UINT32 , BASE_DEC_HEX , NULL                  , 0x0 , "src nid"  , HFILL }} , 
685
686                 { &hf_lnet_msg_type           , 
687                         { "Message type"              , "lnet.msg_type"                , FT_UINT32 , BASE_DEC     , VALS(lnet_msg_type_t) , 0x0 , "msg type" , HFILL }} , 
688                 { &hf_lnet_payload_length     , 
689                         { "Payload length"            , "lnet.payload_length"          , FT_UINT32 , BASE_DEC     , NULL                  , 0x0 , ""         , HFILL }} , 
690                 { &hf_lnet_payload            , 
691                         { "Payload"                   , "lnet.payload"                 , FT_NONE   , BASE_NONE    , NULL                  , 0x0 , ""         , HFILL }} , 
692
693                 {&hf_dst_wmd                  , 
694                         { "DST MD index "             , "lnet.msg_dst_cookie"          , FT_BYTES  , BASE_NONE    , NULL                  , 0x0 , ""         , HFILL }} , 
695                 { &hf_dst_wmd_interface       , 
696                         { "DST MD index interface"    , "lnet.msg_dst_inteface_cookie" , FT_UINT64 , BASE_HEX_DEC , NULL                  , 0x0 , ""         , HFILL }} , 
697                 { &hf_dst_wmd_object          , 
698                         { "DST MD index object"       , "lnet.msg_dst_object_cookie"   , FT_UINT64 , BASE_HEX_DEC , NULL                  , 0x0 , ""         , HFILL }} , 
699                 { &hf_match_bits              , 
700                         { "Match bits"                , "lnet.msg_dst_match_bits"      , FT_UINT64 , BASE_HEX_DEC , NULL                  , 0x0 , ""         , HFILL}}  , 
701                 { &hf_mlength                 , 
702                         { "Message length"            , "lnet.msg_length"              , FT_UINT32 , BASE_DEC     , NULL                  , 0x0 , ""         , HFILL}}  , 
703
704
705                 /* Put */
706                 { &hf_hdr_data                , 
707                         { "hdr data"                  , "lnet.msg_hdr_data"            , FT_UINT64 , BASE_HEX_DEC , NULL                  , 0x0 , ""         , HFILL}}  , 
708                 { &hf_ptl_index               , 
709                         { "ptl index"                 , "lnet.ptl_index"               , FT_UINT32 , BASE_DEC     , VALS(portal_indices)  , 0x0 , ""         , HFILL}}  , 
710                 { &hf_offset                  , 
711                         { "offset"                    , "lnet.offset"                  , FT_UINT32 , BASE_DEC     , NULL                  , 0x0 , ""         , HFILL}}  , 
712
713                 /* Get*/
714                 { &hf_src_offset              , 
715                         { "src offset"                , "lnet.src_offset"              , FT_UINT32 , BASE_DEC     , NULL                  , 0x0 , ""         , HFILL}}  , 
716                 { &hf_sink_length             , 
717                         { "sink length"               , "lnet.sink_length"             , FT_UINT32 , BASE_DEC     , NULL                  , 0x0 , ""         , HFILL}}  , 
718
719                 /* Hello*/
720                 { &hf_hello_incarnation       , 
721                         { "hello incarnation "        , "lnet.hello_incarnation"       , FT_UINT64 , BASE_HEX_DEC , NULL                  , 0x0 , ""         , HFILL}}  , 
722                 { &hf_hello_type              , 
723                         { "hello type"                , "lnet.hello_type"              , FT_UINT32 , BASE_DEC     , NULL                  , 0x0 , ""         , HFILL}}  , 
724
725                 { &hf_lnet_msg_header         , 
726                         { "ptl header"                , "lnet.ptl_header"              , FT_NONE   , BASE_NONE    , NULL                  , 0x0 , ""         , HFILL}}  , 
727
728                 { &hf_lnet_msg_filler         , 
729                         { "msg filler (padding)"      , "lnet.ptl_filler"              , FT_NONE   , BASE_NONE    , NULL                  , 0x0 , ""         , HFILL}}  , 
730
731                 /* Add more fields here */
732         };
733
734         static gint *ett[] = {
735                 &ett_lnet,
736                 &ett_lnet_dest_nid,
737                 &ett_lnet_src_nid
738         };
739
740
741         module_t *lnet_module;
742
743         proto_lnet = proto_register_protocol("Lnet", /*name*/
744                         "Lnet",  /*short name*/
745                         "lnet"); /*abbrev*/
746
747         proto_register_field_array(proto_lnet, hf, array_length(hf));
748         proto_register_subtree_array(ett, array_length(ett));
749
750         lnet_module = prefs_register_protocol(proto_lnet, proto_reg_handoff_lnet);
751
752         prefs_register_uint_preference(lnet_module, "tcp.lnet_port",
753                         "Lnet listener TCP Port",
754                         "Set the TCP port for Lnet"
755                         "(if other than the default of 988)",
756                         10, &global_lnet_tcp_port);
757
758         subdissector_table = register_dissector_table("lnet.ptl_index", "lnet portal index", FT_UINT32 , BASE_DEC);
759
760         register_init_routine(&lnet_init_protocol);
761
762 }
763
764
765 /* The registration hand-off routine */
766 void
767 proto_reg_handoff_lnet(void)
768 {
769         static int lnet_prefs_initialized = FALSE;
770         static dissector_handle_t lnet_handle;
771
772         if(!lnet_prefs_initialized) {
773                 lnet_handle = create_dissector_handle(dissect_lnet, proto_lnet);
774                 lnet_prefs_initialized = TRUE;
775         }
776         else {
777                 dissector_delete("tcp.port",global_lnet_tcp_port, lnet_handle);
778         }
779
780         lnet_tcp_port = global_lnet_tcp_port;
781
782         dissector_add("tcp.port", lnet_tcp_port, lnet_handle);
783 }