From Kovarththanan Rajaratnam via bug 3548:
[obnox/wireshark/wip.git] / epan / dissectors / packet-iwarp-ddp-rdmap.c
1 /* packet-iwarp-ddp-rdmap.c 
2  * Routines for Direct Data Placement (DDP) and
3  * Remote Direct Memory Access Protocol (RDMAP) dissection
4  * According to IETF RFC 5041 and RFC 5040 
5  * Copyright 2008, Yves Geissbuehler <yves.geissbuehler@gmx.net> 
6  * Copyright 2008, Philip Frey <frey.philip@gmail.com> 
7  * 
8  * $Id$ 
9  * 
10  * Wireshark - Network traffic analyzer 
11  * By Gerald Combs <gerald@wireshark.org> 
12  * Copyright 1998 Gerald Combs 
13  * 
14  * This program is free software; you can redistribute it and/or 
15  * modify it under the terms of the GNU General Public License 
16  * as published by the Free Software Foundation; either version 2 
17  * of the License, or (at your option) any later version. 
18  * 
19  * This program is distributed in the hope that it will be useful, 
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
22  * GNU General Public License for more details. 
23  * 
24  * You should have received a copy of the GNU General Public License 
25  * along with this program; if not, write to the Free Software 
26  * Foundation, Inc.,
27  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. 
28  */
29
30 /* INCLUDES */
31 #ifdef HAVE_CONFIG_H 
32 # include "config.h" 
33 #endif
34 #include <stdio.h> 
35 #include <stdlib.h> 
36 #include <string.h> 
37 #include <glib.h> 
38 #include <epan/packet.h> 
39
40 /* DEFINES */
41
42 /* header field byte lengths */
43 #define DDP_CONTROL_FIELD_LEN 1
44 #define DDP_TAGGED_HEADER_LEN 14
45 #define DDP_TAGGED_RSVDULP_LEN 4
46 #define DDP_STAG_LEN 4
47 #define DDP_TO_LEN 8
48 #define DDP_UNTAGGED_HEADER_LEN 18
49 #define DDP_UNTAGGED_RSVDULP_LEN 5
50 #define DDP_QN_LEN 4
51 #define DDP_MSN_LEN 4
52 #define DDP_MO_LEN 4
53 #define DDP_BUFFER_MODEL_LEN 12
54
55 #define RDMA_CONTROL_FIELD_LEN 1
56 #define RDMA_RESERVED_FIELD_LEN 4
57 #define RDMA_INVAL_STAG_LEN 4
58 #define RDMA_SINKSTAG_LEN 4
59 #define RDMA_SINKTO_LEN 8
60 #define RDMA_RDMARDSZ_LEN 4
61 #define RDMA_SRCSTAG_LEN 4
62 #define RDMA_SRCTO_LEN 8
63 #define RDMA_DDP_SEGLEN_LEN 2
64 #define RDMA_TERMINATED_RDMA_LEN 28
65
66 /* RDMA messages */
67 #define RDMA_WRITE 0x00
68 #define RDMA_READ_REQUEST 0x01
69 #define RDMA_READ_RESPONSE 0x02
70 #define RDMA_SEND 0x03
71 #define RDMA_SEND_INVALIDATE 0x04
72 #define RDMA_SEND_SE 0x05
73 #define RDMA_SEND_SE_INVALIDATE 0x06
74 #define RDMA_TERMINATE 0x07
75
76 /* bitmasks */
77 #define DDP_TAGGED_FLAG 0x80
78 #define DDP_LAST_FLAG 0x40
79 #define DDP_RSVD 0x3C
80 #define DDP_DV 0x03
81 #define RDMA_RV 0xC0
82 #define RDMA_RSV 0x30
83 #define RDMA_OPCODE 0x0F
84
85 #define IWARP_LAYER 0xF0
86 #define IWARP_ETYPE 0x0F
87 #define IWARP_HDRCT 0xE0
88 #define IWARP_HDRCT_M 0x80
89 #define IWARP_HDRCT_D 0x40
90 #define IWARP_HDRCT_R 0x20
91 #define IWARP_TERM_RES 0x1FFF
92
93 #define IWARP_LAYER_RDMA 0x00
94 #define IWARP_LAYER_DDP 0x10
95 #define IWARP_LAYER_LLP 0x20
96 #define IWARP_ETYPE_DDP_TAGGED 0x01
97 #define IWARP_ETYPE_DDP_UNTAGGED 0x02
98
99 /* GLOBALS */
100 static gint proto_iwarp_ddp_rdmap = -1;
101 static gint ett_iwarp_ddp_rdmap = -1;
102
103 static dissector_handle_t data_handle;
104
105 /*
106  * DDP: initialize the protocol and registered fields
107  */
108 static gint hf_iwarp_ddp = -1;
109
110 /* DDP Control Field */
111 static gint hf_iwarp_ddp_control_field = -1;
112 static gint hf_iwarp_ddp_t_flag = -1;
113 static gint hf_iwarp_ddp_l_flag = -1;
114 static gint hf_iwarp_ddp_rsvd = -1;
115 static gint hf_iwarp_ddp_dv = -1;
116
117 /* DDP rsvdULP[8:39] field */
118 static gint hf_iwarp_ddp_rsvdulp = -1;
119
120 /* Tagged Buffer Model Header */
121 static gint hf_iwarp_ddp_tagged_header = -1;
122 static gint hf_iwarp_ddp_stag = -1;
123 static gint hf_iwarp_ddp_to = -1;
124
125 /* Untagged Buffer Model Header */
126 static gint hf_iwarp_ddp_untagged_header = -1;
127 static gint hf_iwarp_ddp_qn= -1;
128 static gint hf_iwarp_ddp_msn = -1;
129 static gint hf_iwarp_ddp_mo = -1;
130
131 /* initialize the subtree pointers */
132 static gint ett_iwarp_ddp = -1;
133
134 static gint ett_iwarp_ddp_control_field = -1;
135 static gint ett_iwarp_ddp_tagged_header = -1;
136 static gint ett_iwarp_ddp_untagged_header = -1;
137
138 /* 
139  * RDMAP: initialize the protocol and registered fields
140  */
141 static gint hf_iwarp_rdma = -1;
142
143 /* Control Field */
144 static gint hf_iwarp_rdma_control_field = -1;
145 static gint hf_iwarp_rdma_version = -1;
146 static gint hf_iwarp_rdma_rsvd = -1;
147 static gint hf_iwarp_rdma_opcode = -1;
148
149 /* DDP rsvdULP[8:39] RDMA interpretations */
150 static gint hf_iwarp_rdma_reserved = -1;
151 static gint hf_iwarp_rdma_inval_stag = -1;
152
153 /* Read Request Header */
154 static gint hf_iwarp_rdma_rr_header = -1;
155 static gint hf_iwarp_rdma_sinkstag = -1;
156 static gint hf_iwarp_rdma_sinkto = -1;
157 static gint hf_iwarp_rdma_rdmardsz = -1;
158 static gint hf_iwarp_rdma_srcstag = -1;
159 static gint hf_iwarp_rdma_srcto = -1;
160
161 /* Terminate Header */
162 static gint hf_iwarp_rdma_terminate_header = -1;
163 static gint hf_iwarp_rdma_term_ctrl = -1;
164 static gint hf_iwarp_rdma_term_layer = -1;
165 static gint hf_iwarp_rdma_term_etype = -1;
166 static gint hf_iwarp_rdma_term_etype_rdma = -1;
167 static gint hf_iwarp_rdma_term_etype_ddp = -1;
168 static gint hf_iwarp_rdma_term_etype_llp = -1;
169 static gint hf_iwarp_rdma_term_errcode = -1;
170 static gint hf_iwarp_rdma_term_errcode_rdma = -1;
171 static gint hf_iwarp_rdma_term_errcode_ddp_untagged = -1;
172 static gint hf_iwarp_rdma_term_errcode_ddp_tagged = -1;
173 static gint hf_iwarp_rdma_term_errcode_llp = -1;
174 static gint hf_iwarp_rdma_term_hdrct = -1;
175 static gint hf_iwarp_rdma_term_hdrct_m = -1;
176 static gint hf_iwarp_rdma_term_hdrct_d = -1;
177 static gint hf_iwarp_rdma_term_hdrct_r = -1;
178 static gint hf_iwarp_rdma_term_rsvd = -1;
179 static gint hf_iwarp_rdma_term_ddp_seg_len = -1;
180 static gint hf_iwarp_rdma_term_ddp_h = -1;
181 static gint hf_iwarp_rdma_term_rdma_h = -1;
182
183 /* initialize the subtree pointers */
184 static gint ett_iwarp_rdma = -1;
185
186 static gint ett_iwarp_rdma_control_field = -1;
187 static gint ett_iwarp_rdma_rr_header = -1;
188 static gint ett_iwarp_rdma_terminate_header = -1;
189 static gint ett_iwarp_rdma_term_ctrl = -1;
190 static gint ett_iwarp_rdma_term_hdrct = -1;
191
192 static const value_string rdmap_messages[] = {
193                 { RDMA_WRITE, "Write" },
194                 { RDMA_READ_REQUEST, "Read Request" },
195                 { RDMA_READ_RESPONSE, "Read Response" },
196                 { RDMA_SEND, "Send" },
197                 { RDMA_SEND_INVALIDATE, "Send with Invalidate" },
198                 { RDMA_SEND_SE, "Send with SE" },
199                 { RDMA_SEND_SE_INVALIDATE, "Send with SE and Invalidate" },
200                 { RDMA_TERMINATE, "Terminate" },
201                 { 0, NULL       }
202 };
203
204 static const value_string layer_names[] = {
205                 { IWARP_LAYER_RDMA, "RDMA" },
206                 { IWARP_LAYER_DDP, "DDP" },
207                 { IWARP_LAYER_LLP, "LLP" },
208                 { 0, NULL }
209 };
210
211
212 static const value_string rdma_etype_names[] = {
213                 { 0x00, "Local Catastrophic Error" },
214                 { 0x01, "Remote Protection Error" },
215                 { 0x02, "Remote Operation Error" },
216                 { 0, NULL }
217 };
218
219 static const value_string rdma_errcode_names[] = {
220                 { 0x00, "Invalid STag" },
221                 { 0x01, "Base or bounds violation" },
222                 { 0x02, "Access rights violation" },
223                 { 0x03, "STag not associated with RDMAP Stream" },
224                 { 0x04, "TO wrap" },
225                 { 0x05, "Invalid RDMAP version" },
226                 { 0x06, "Unexpected OpCode" },
227                 { 0x07, "Catastrophic error, localized to RDMAP Stream" },
228                 { 0x08, "Catastrophic error, global" },
229                 { 0x09, "STag cannot be Invalidated" },
230                 { 0xFF, "Unspecific Error" },
231                 { 0, NULL }
232 };
233
234 static const value_string ddp_etype_names[] = {
235                 { 0x00, "Local Catastrophic Error" },
236                 { 0x01, "Tagged Buffer Error" },
237                 { 0x02, "Untagged Buffer Error" },
238                 { 0x03, "Reserved for the use by the LLP" },
239                 { 0, NULL }
240 };
241
242 static const value_string ddp_errcode_tagged_names[] = {
243                 { 0x00, "Invalid STag" },
244                 { 0x01, "Base or bounds violation" },
245                 { 0x02, "STag not associated with DDP Stream" },
246                 { 0x03, "TO wrap" },
247                 { 0x04, "Invalid DDP version" },
248                 { 0, NULL }
249 };
250
251 static const value_string ddp_errcode_untagged_names[] = {
252                 { 0x01, "Invalid QN" },
253                 { 0x02, "Invalid MSN - no buffer available" },
254                 { 0x03, "Invalid MSN - MSN range is not valid" },
255                 { 0x04, "Invalid MO" },
256                 { 0x05, "DDP Message too long for available buffer" },
257                 { 0x06, "Invalid DDP version" },
258                 { 0, NULL } 
259 };
260
261 /* update packet list pane in the GUI */
262 void
263 ddp_rdma_packetlist(packet_info *pinfo, gboolean ddp_last_flag, 
264                 guint8 rdma_msg_opcode)
265 {
266         const gchar *ddp_fragment_state;
267
268         if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
269                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DDP/RDMA");
270         }
271
272         if (ddp_last_flag) {
273                 ddp_fragment_state = "[last DDP segment]";
274         } else {
275                 ddp_fragment_state = "[more DDP segments]";
276         }
277
278         if (check_col(pinfo->cinfo, COL_INFO)) {
279                 col_add_fstr(pinfo->cinfo, COL_INFO, "%d > %d %s %s", pinfo->srcport,
280                                 pinfo->destport, val_to_str(rdma_msg_opcode, rdmap_messages,
281                                                 "Unknown %d"), ddp_fragment_state);
282         }
283 }
284
285 /* dissects RDMA Read Request and Terminate message header */
286 void
287 dissect_iwarp_rdmap(tvbuff_t *tvb, proto_tree *rdma_tree, guint32 offset,
288                 guint8 rdma_msg_opcode)
289 {
290         proto_tree *rdma_header_tree = NULL;
291         proto_tree *term_ctrl_field_tree = NULL;
292         proto_tree *header_ctrl_field_tree = NULL;
293         
294         proto_item *rdma_header_subitem = NULL;
295         proto_item *term_ctrl_field_subitem = NULL;
296         proto_item *header_ctrl_field_subitem = NULL;
297
298         guint8 layer, etype, hdrct;
299         
300         guint32 rdmardsz;
301
302         if (rdma_tree) {
303                 
304                 if (rdma_msg_opcode == RDMA_READ_REQUEST) {
305                         rdma_header_subitem = proto_tree_add_item(rdma_tree,
306                                         hf_iwarp_rdma_rr_header, tvb, offset, -1, FALSE);
307                         rdma_header_tree = proto_item_add_subtree(rdma_header_subitem,
308                                         ett_iwarp_rdma);
309
310                         proto_tree_add_item(rdma_header_tree, hf_iwarp_rdma_sinkstag, tvb,
311                                         offset, RDMA_SINKSTAG_LEN, FALSE);
312                         offset += RDMA_SINKSTAG_LEN;
313                         proto_tree_add_item(rdma_header_tree, hf_iwarp_rdma_sinkto, tvb,
314                                         offset, RDMA_SINKTO_LEN, FALSE);
315                         offset += RDMA_SINKTO_LEN;
316                         
317                         rdmardsz = (guint32) tvb_get_ntohl(tvb, offset);
318                         proto_tree_add_uint_format_value(rdma_header_tree,
319                                         hf_iwarp_rdma_rdmardsz, tvb, offset,
320                                         RDMA_RDMARDSZ_LEN, rdmardsz, "%u bytes",
321                                         rdmardsz);
322                         
323                         offset += RDMA_RDMARDSZ_LEN;
324                         proto_tree_add_item(rdma_header_tree, hf_iwarp_rdma_srcstag, tvb,
325                                         offset, RDMA_SRCSTAG_LEN, FALSE);
326                         offset += RDMA_SRCSTAG_LEN;
327                         proto_tree_add_item(rdma_header_tree, hf_iwarp_rdma_srcto, tvb,
328                                         offset, RDMA_SRCTO_LEN, FALSE);
329                         offset += RDMA_SRCTO_LEN;
330                 }
331
332                 if (rdma_msg_opcode == RDMA_TERMINATE) {
333                         rdma_header_subitem = proto_tree_add_item(rdma_tree,
334                                         hf_iwarp_rdma_terminate_header, tvb, offset, -1, FALSE);
335                         rdma_header_tree = proto_item_add_subtree(rdma_header_subitem,
336                                         ett_iwarp_rdma);
337
338                         /* Terminate Control Field */
339                         layer = tvb_get_guint8(tvb, offset) & IWARP_LAYER;
340                         etype = tvb_get_guint8(tvb, offset) & IWARP_ETYPE;
341
342                         term_ctrl_field_subitem = proto_tree_add_item(rdma_tree,
343                                         hf_iwarp_rdma_term_ctrl, tvb, offset, 3, FALSE);
344                         term_ctrl_field_tree = proto_item_add_subtree(
345                                         term_ctrl_field_subitem, ett_iwarp_rdma);
346                         proto_tree_add_item(term_ctrl_field_tree, hf_iwarp_rdma_term_layer,
347                                         tvb, offset, 1, FALSE);
348
349                         switch (layer) {
350                                 case IWARP_LAYER_RDMA:
351                                         proto_tree_add_item(term_ctrl_field_tree,
352                                                         hf_iwarp_rdma_term_etype_rdma, tvb, offset, 1,
353                                                         FALSE);
354                                         offset += 1;
355                                         proto_tree_add_item(term_ctrl_field_tree,
356                                                         hf_iwarp_rdma_term_errcode_rdma, tvb, offset, 1,
357                                                         FALSE);
358                                         offset += 1;
359                                         break;
360                                 case IWARP_LAYER_DDP:
361                                         proto_tree_add_item(term_ctrl_field_tree,
362                                                         hf_iwarp_rdma_term_etype_ddp, tvb, offset, 1,
363                                                         FALSE);
364                                         offset += 1;
365                                         switch (etype) {
366                                                 case IWARP_ETYPE_DDP_TAGGED:
367                                                         proto_tree_add_item(term_ctrl_field_tree,
368                                                                         hf_iwarp_rdma_term_errcode_ddp_tagged, tvb,
369                                                                         offset, 1, FALSE);
370                                                         offset += 1;
371                                                         break;
372                                                 case IWARP_ETYPE_DDP_UNTAGGED:
373                                                         proto_tree_add_item(term_ctrl_field_tree,
374                                                                         hf_iwarp_rdma_term_errcode_ddp_untagged, tvb,
375                                                                         offset, 1, FALSE);
376                                                         offset += 1;
377                                                         break;
378                                                 default:
379                                                         proto_tree_add_item(term_ctrl_field_tree,
380                                                                         hf_iwarp_rdma_term_errcode, tvb, offset, 1,
381                                                                         FALSE);
382                                                         offset += 1;
383                                                         break;
384                                         }
385                                         break;
386                                 case IWARP_LAYER_LLP:
387                                         proto_tree_add_item(term_ctrl_field_tree,
388                                                         hf_iwarp_rdma_term_etype_llp, tvb, offset, 1,
389                                                         FALSE);
390                                         offset += 1;
391                                         proto_tree_add_item(term_ctrl_field_tree,
392                                                         hf_iwarp_rdma_term_errcode_llp, tvb, offset, 1,
393                                                         FALSE);
394                                         offset += 1;
395                                         break;
396                                 default:
397                                         proto_tree_add_item(term_ctrl_field_tree,
398                                                         hf_iwarp_rdma_term_etype, tvb, offset, 1, FALSE);
399                                         offset += 1;
400                                         proto_tree_add_item(term_ctrl_field_tree,
401                                                         hf_iwarp_rdma_term_errcode, tvb, offset, 1, FALSE);
402                                         offset += 1;
403                                         break;
404                         }
405
406                         /* header control bits (hdctr), part of Terminate Control Field */
407                         header_ctrl_field_subitem = proto_tree_add_item(
408                                         term_ctrl_field_tree, hf_iwarp_rdma_term_hdrct, tvb,
409                                         offset, 1, FALSE);
410                         header_ctrl_field_tree = proto_item_add_subtree(
411                                         header_ctrl_field_subitem, ett_iwarp_rdma);
412                         
413                         hdrct = tvb_get_guint8(tvb, offset) & IWARP_HDRCT;
414                         
415                         proto_tree_add_item(header_ctrl_field_tree,
416                                         hf_iwarp_rdma_term_hdrct_m, tvb, offset, 1, FALSE);
417                         proto_tree_add_item(header_ctrl_field_tree,
418                                         hf_iwarp_rdma_term_hdrct_d, tvb, offset, 1, FALSE);
419                         proto_tree_add_item(header_ctrl_field_tree,
420                                         hf_iwarp_rdma_term_hdrct_r, tvb, offset, 1, FALSE);
421
422                         proto_tree_add_item(rdma_header_tree, hf_iwarp_rdma_term_rsvd, tvb,
423                                         offset, 2, FALSE);
424                         offset += 2;
425
426                         
427                         if (hdrct & IWARP_HDRCT_D) {
428                                 /* DDP Segment Length (if any) */
429                                 proto_tree_add_item(rdma_header_tree,
430                                                 hf_iwarp_rdma_term_ddp_seg_len, tvb,
431                                                 offset, RDMA_DDP_SEGLEN_LEN, FALSE);
432                                 offset += RDMA_DDP_SEGLEN_LEN;
433                                 
434                                 /* Terminated DDP Header (if any), tagged or untagged */
435                                 if (etype == IWARP_ETYPE_DDP_TAGGED) {
436                                         proto_tree_add_item(rdma_header_tree,
437                                                         hf_iwarp_rdma_term_ddp_h, tvb,
438                                                         offset, DDP_TAGGED_HEADER_LEN, FALSE);
439                                         offset += DDP_TAGGED_HEADER_LEN;
440                                 } else {
441                                         proto_tree_add_item(rdma_header_tree,
442                                                         hf_iwarp_rdma_term_ddp_h, tvb,
443                                                         offset, DDP_UNTAGGED_HEADER_LEN, FALSE);
444                                         offset += DDP_UNTAGGED_HEADER_LEN;
445                                 }
446                         }
447
448                         /* Terminated RDMA Header (if any) */
449                         if (hdrct & IWARP_HDRCT_R) {
450                                 proto_tree_add_item(rdma_header_tree, hf_iwarp_rdma_term_rdma_h,
451                                                 tvb, offset, RDMA_TERMINATED_RDMA_LEN, FALSE);
452                         }
453                 }
454         }
455 }
456
457 /* 
458  * Main dissection routine which dissects a DDP segment and interprets the
459  * header field rsvdULP according to RDMAP.
460  */
461 void
462 dissect_iwarp_ddp_rdmap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
463 {
464         proto_tree *ddp_rdma_tree = NULL;
465         proto_tree *ddp_tree = NULL;
466         proto_tree *ddp_ctrl_field_tree = NULL;
467         proto_tree *ddp_buffer_model_tree = NULL;
468         proto_tree *rdma_tree = NULL;
469         proto_tree *rdma_ctrl_field_tree = NULL;
470
471         proto_item *ddp_rdma_item = NULL;
472         proto_item *ddp_item = NULL;
473         proto_item *ddp_ctrl_field_item = NULL;
474         proto_item *ddp_buffer_model_item = NULL;
475         proto_item *rdma_item = NULL;
476         proto_item *rdma_ctrl_field_item = NULL;
477
478         tvbuff_t *next_tvb = NULL;
479         
480         gboolean is_tagged_buffer_model;
481         guint8 ddp_ctrl_field, rdma_ctrl_field, rdma_msg_opcode;
482         guint32 header_end;
483         guint32 offset = 0;
484
485         ddp_ctrl_field = tvb_get_guint8(tvb, 0);
486         rdma_ctrl_field = tvb_get_guint8(tvb, 1);
487         rdma_msg_opcode = rdma_ctrl_field & RDMA_OPCODE;
488         is_tagged_buffer_model = ddp_ctrl_field & DDP_TAGGED_FLAG;
489
490         ddp_rdma_packetlist(pinfo, ddp_ctrl_field & DDP_LAST_FLAG, rdma_msg_opcode);
491         
492         if (tree) {
493                 
494                 offset = 0;
495                 
496                 /* determine header length */
497                 if (is_tagged_buffer_model) {
498                         header_end = DDP_TAGGED_HEADER_LEN;
499                 } else {
500                         header_end = DDP_UNTAGGED_HEADER_LEN;
501                 }
502                 
503                 if (rdma_msg_opcode == RDMA_READ_REQUEST
504                                 || rdma_msg_opcode == RDMA_TERMINATE) {
505                         header_end = -1;
506                 }
507                 
508                 /* DDP/RDMA protocol tree */
509                 ddp_rdma_item = proto_tree_add_item(tree, proto_iwarp_ddp_rdmap,
510                                 tvb, offset, header_end, FALSE);
511                 ddp_rdma_tree = proto_item_add_subtree(ddp_rdma_item,
512                                 ett_iwarp_ddp_rdmap);
513
514                 /* DDP protocol header subtree */       
515                 ddp_item = proto_tree_add_item(ddp_rdma_tree, hf_iwarp_ddp, tvb,
516                                 offset, header_end, FALSE);
517                 ddp_tree = proto_item_add_subtree(ddp_item, ett_iwarp_ddp);
518
519                 /* DDP control field */
520                 ddp_ctrl_field_item = proto_tree_add_item(ddp_tree,
521                                 hf_iwarp_ddp_control_field, tvb, offset,
522                                 DDP_CONTROL_FIELD_LEN, FALSE);
523                 ddp_ctrl_field_tree = proto_item_add_subtree(ddp_ctrl_field_item,
524                                 ett_iwarp_ddp);
525                 
526                 proto_tree_add_item(ddp_ctrl_field_tree, hf_iwarp_ddp_t_flag, tvb,
527                                 offset, DDP_CONTROL_FIELD_LEN, FALSE);
528                 proto_tree_add_item(ddp_ctrl_field_tree, hf_iwarp_ddp_l_flag, tvb,
529                                 offset, DDP_CONTROL_FIELD_LEN, FALSE);
530                 proto_tree_add_item(ddp_ctrl_field_tree, hf_iwarp_ddp_rsvd, tvb,
531                                 offset, DDP_CONTROL_FIELD_LEN, FALSE);
532                 proto_tree_add_item(ddp_ctrl_field_tree, hf_iwarp_ddp_dv, tvb, offset,
533                                 DDP_CONTROL_FIELD_LEN, FALSE);
534                 offset += DDP_CONTROL_FIELD_LEN;
535                 
536                 
537                 /* DDP header field RsvdULP */
538                 if (!is_tagged_buffer_model) {
539                         proto_tree_add_item(ddp_tree, hf_iwarp_ddp_rsvdulp, tvb,
540                                         offset, DDP_UNTAGGED_RSVDULP_LEN, FALSE);
541                 }
542                 
543                 /* RDMA protocol header subtree */
544                 if (is_tagged_buffer_model) {
545                         header_end = RDMA_CONTROL_FIELD_LEN;
546                 } else {
547                         header_end = RDMA_CONTROL_FIELD_LEN + RDMA_RESERVED_FIELD_LEN;
548                 }
549                 
550                 rdma_item = proto_tree_add_item(ddp_rdma_tree, hf_iwarp_rdma, tvb,
551                                         offset, header_end, FALSE);
552                 rdma_tree = proto_item_add_subtree(rdma_item, ett_iwarp_rdma);
553
554                 /* RDMA Control Field */
555                 rdma_ctrl_field_item = proto_tree_add_item(rdma_tree,
556                                 hf_iwarp_rdma_control_field, tvb, offset,
557                                 RDMA_CONTROL_FIELD_LEN, FALSE);
558                 rdma_ctrl_field_tree = proto_item_add_subtree(rdma_ctrl_field_item,
559                                 ett_iwarp_rdma);
560                 
561                 proto_tree_add_item(rdma_ctrl_field_tree, hf_iwarp_rdma_version, tvb,
562                                 offset, RDMA_CONTROL_FIELD_LEN, FALSE);
563                 proto_tree_add_item(rdma_ctrl_field_tree, hf_iwarp_rdma_rsvd, tvb,
564                                 offset, RDMA_CONTROL_FIELD_LEN, FALSE);
565                 proto_tree_add_item(rdma_ctrl_field_tree, hf_iwarp_rdma_opcode, tvb,
566                                 offset, RDMA_CONTROL_FIELD_LEN, FALSE);
567                 offset += RDMA_CONTROL_FIELD_LEN;
568                 
569                 /* dissection of DDP rsvdULP[8:39] with respect to RDMAP */
570                 if (rdma_msg_opcode == RDMA_READ_REQUEST
571                                 || rdma_msg_opcode == RDMA_SEND
572                                 || rdma_msg_opcode == RDMA_SEND_SE
573                                 || rdma_msg_opcode == RDMA_TERMINATE) {
574                         proto_tree_add_item(rdma_tree, hf_iwarp_rdma_reserved,
575                                  tvb, offset, RDMA_RESERVED_FIELD_LEN, FALSE);
576                 }
577                 
578                 if (rdma_msg_opcode == RDMA_SEND_INVALIDATE
579                                 || rdma_msg_opcode == RDMA_SEND_SE_INVALIDATE) {
580                         proto_tree_add_item(rdma_tree, hf_iwarp_rdma_inval_stag,
581                                 tvb, offset, RDMA_INVAL_STAG_LEN, FALSE);
582                 }
583                 
584                 if (!is_tagged_buffer_model) {
585                         offset += RDMA_RESERVED_FIELD_LEN;
586                 }
587
588                 /* DDP Buffer Model dissection */
589                 if (is_tagged_buffer_model) {
590
591                         /* Tagged Buffer Model Case */
592                         ddp_buffer_model_item = proto_tree_add_item(ddp_tree,
593                                         hf_iwarp_ddp_tagged_header, tvb, offset,
594                                         DDP_BUFFER_MODEL_LEN, FALSE);
595                         ddp_buffer_model_tree = proto_item_add_subtree(ddp_buffer_model_item,
596                                         ett_iwarp_ddp);
597
598                         proto_tree_add_item(ddp_buffer_model_tree, hf_iwarp_ddp_stag, tvb,
599                                         offset, DDP_STAG_LEN, FALSE);
600                         offset += DDP_STAG_LEN;
601                         proto_tree_add_item(ddp_buffer_model_tree, hf_iwarp_ddp_to, tvb,
602                                         offset, DDP_TO_LEN, FALSE);
603                         offset += DDP_TO_LEN;
604                         
605                         if( rdma_msg_opcode == RDMA_READ_RESPONSE
606                                         || rdma_msg_opcode == RDMA_WRITE) {
607                                 
608                                 /* display the payload */
609                                 next_tvb = tvb_new_subset(tvb, DDP_TAGGED_HEADER_LEN, -1, -1);
610                                 call_dissector(data_handle, next_tvb, pinfo, tree);
611                         }
612                         
613                 } else {
614                         
615                         /* Untagged Buffer Model Case */
616                         ddp_buffer_model_item = proto_tree_add_item(ddp_tree,
617                                         hf_iwarp_ddp_untagged_header, tvb, offset,
618                                         DDP_BUFFER_MODEL_LEN, FALSE);
619                         ddp_buffer_model_tree = proto_item_add_subtree(ddp_buffer_model_item,
620                                         ett_iwarp_ddp);
621
622                         proto_tree_add_item(ddp_buffer_model_tree, hf_iwarp_ddp_qn, tvb,
623                                         offset, DDP_QN_LEN, FALSE);
624                         offset += DDP_QN_LEN;
625                         proto_tree_add_item(ddp_buffer_model_tree, hf_iwarp_ddp_msn, tvb,
626                                         offset, DDP_MSN_LEN, FALSE);
627                         offset += DDP_MSN_LEN;
628                         proto_tree_add_item(ddp_buffer_model_tree, hf_iwarp_ddp_mo, tvb,
629                                         offset, DDP_MO_LEN, FALSE);
630                         offset += DDP_MO_LEN;
631                         
632                         if (rdma_msg_opcode == RDMA_SEND
633                                         || rdma_msg_opcode == RDMA_SEND_INVALIDATE
634                                         || rdma_msg_opcode == RDMA_SEND_SE
635                                         || rdma_msg_opcode == RDMA_SEND_SE_INVALIDATE) {
636
637                                 /* display the payload */
638                                 next_tvb = tvb_new_subset(tvb, DDP_UNTAGGED_HEADER_LEN, -1, -1);
639                                 call_dissector(data_handle, next_tvb, pinfo, tree);
640                         }
641                 }
642         }
643
644         /* do further dissection for RDMA messages RDMA Read Request & Terminate */
645         if (rdma_msg_opcode == RDMA_READ_REQUEST
646                         || rdma_msg_opcode == RDMA_TERMINATE) {
647                 dissect_iwarp_rdmap(tvb, rdma_tree, offset, rdma_msg_opcode);
648         }
649 }
650
651 /* register the protocol with Wireshark */
652 void
653 proto_register_iwarp_ddp_rdmap(void)
654 {
655         /* setup list of header fields */
656         static hf_register_info hf[] = {
657
658                 /* DDP */
659                 { &hf_iwarp_ddp, {
660                                 "DDP header", "iwarp_ddp",
661                                 FT_NONE, BASE_NONE, NULL, 0x0,
662                                 NULL, HFILL } },
663                 { &hf_iwarp_ddp_control_field, {
664                                 "DDP control field", "iwarp_ddp.control_field",
665                                 FT_NONE, BASE_NONE, NULL, 0x0,
666                                 "DDP Control Field", HFILL } },
667                 { &hf_iwarp_ddp_tagged_header, {
668                                 "Tagged buffer model", "iwarp_ddp.tagged",
669                                 FT_NONE, BASE_NONE, NULL, 0x0,
670                                 "DDP Tagged Buffer Model Header", HFILL} },
671                 { &hf_iwarp_ddp_untagged_header, {
672                                 "Untagged buffer model", "iwarp_ddp.untagged",
673                                 FT_NONE, BASE_NONE, NULL, 0x0,
674                                 "DDP Untagged Buffer Model Header", HFILL} },
675                 { &hf_iwarp_ddp_t_flag, {
676                                 "Tagged flag", "iwarp_ddp.tagged_flag",
677                                 FT_BOOLEAN, 8, NULL, DDP_TAGGED_FLAG,
678                                 NULL, HFILL} },
679                 { &hf_iwarp_ddp_l_flag, {
680                                 "Last flag", "iwarp_ddp.last_flag",
681                                 FT_BOOLEAN, 8, NULL, DDP_LAST_FLAG,
682                                 NULL, HFILL} },
683                 { &hf_iwarp_ddp_rsvd, {
684                                 "Reserved", "iwarp_ddp.rsvd",
685                                 FT_UINT8, BASE_HEX, NULL, DDP_RSVD,
686                                 NULL, HFILL} },
687                 { &hf_iwarp_ddp_dv, {
688                                 "DDP protocol version", "iwarp_ddp.dv",
689                                 FT_UINT8, BASE_DEC, NULL, DDP_DV,
690                                 NULL, HFILL} },
691                 { &hf_iwarp_ddp_rsvdulp, {
692                                 "Reserved for use by the ULP", "iwarp_ddp.rsvdulp",
693                                 FT_BYTES, BASE_NONE, NULL, 0x0,
694                                 NULL, HFILL} },
695                 { &hf_iwarp_ddp_stag, {
696                                 "(Data Sink) Steering Tag", "iwarp_ddp.stag",
697                                 FT_BYTES, BASE_NONE, NULL, 0x0,
698                                 NULL, HFILL} },
699                 { &hf_iwarp_ddp_to, {
700                                 "(Data Sink) Tagged offset", "iwarp_ddp.tagged_offset",
701                                 FT_BYTES, BASE_NONE, NULL, 0x0,
702                                 NULL, HFILL} },
703                 { &hf_iwarp_ddp_qn, {
704                                 "Queue number", "iwarp_ddp.qn",
705                                 FT_UINT32, BASE_DEC, NULL, 0x0,
706                                 NULL, HFILL} },
707                 { &hf_iwarp_ddp_msn, {
708                                 "Message sequence number", "iwarp_ddp.msn",
709                                 FT_UINT32, BASE_DEC, NULL, 0x0,
710                                 NULL, HFILL} },
711                 { &hf_iwarp_ddp_mo, {
712                                 "Message offset", "iwarp_ddp.mo",
713                                 FT_UINT32, BASE_DEC, NULL, 0x0,
714                                 NULL, HFILL}
715                 },
716
717                 /* RDMAP */
718                 { &hf_iwarp_rdma, {
719                                 "RDMAP header", "iwarp_rdma",
720                                 FT_NONE, BASE_NONE, NULL, 0x0,
721                                 NULL, HFILL} },
722                 { &hf_iwarp_rdma_control_field, {
723                                 "RDMAP control field", "iwarp_rdma.control_field",
724                                 FT_NONE, BASE_NONE, NULL, 0x0,
725                                 "RDMA Control Field", HFILL} },
726                 { &hf_iwarp_rdma_version, {
727                                 "Version", "iwarp_rdma.version",
728                                 FT_UINT8, BASE_DEC, NULL, RDMA_RV,
729                                 "RDMA Version Field", HFILL} },
730                 { &hf_iwarp_rdma_rsvd, {
731                                 "Reserved", "iwarp_rdma.rsv",
732                                 FT_UINT8, BASE_HEX, NULL, RDMA_RSV,
733                                 "RDMA Control Field Reserved", HFILL} },
734                 { &hf_iwarp_rdma_opcode, {
735                                 "OpCode", "iwarp_rdma.opcode",
736                                 FT_UINT8, BASE_HEX, VALS(rdmap_messages), RDMA_OPCODE,
737                                 "RDMA OpCode Field", HFILL} },
738                 { &hf_iwarp_rdma_reserved, {
739                                 "Reserved", "iwarp_rdma.reserved",
740                                 FT_BYTES, BASE_NONE, NULL, 0x0,
741                                 NULL, HFILL} },
742                 { &hf_iwarp_rdma_inval_stag, {
743                                 "Invalidate STag", "iwarp_rdma.inval_stag",
744                                 FT_UINT32, BASE_DEC, NULL, 0x0,
745                                 "RDMA Invalidate STag", HFILL} },
746                 { &hf_iwarp_rdma_rr_header, {
747                                 "Read request", "iwarp_rdma.rr",
748                                 FT_NONE, BASE_NONE, NULL, 0x0,
749                                 "RDMA Read Request Header", HFILL} },
750                 { &hf_iwarp_rdma_terminate_header, {
751                                 "Terminate", "iwarp_rdma.terminate",
752                                 FT_NONE, BASE_NONE, NULL, 0x0,
753                                 "RDMA Terminate Header", HFILL} },
754                 { &hf_iwarp_rdma_sinkstag, {
755                                 "Data Sink STag", "iwarp_rdma.sinkstag",
756                                 FT_UINT32, BASE_DEC, NULL, 0x0,
757                                 NULL, HFILL} },
758                 { &hf_iwarp_rdma_sinkto, {
759                                 "Data Sink Tagged Offset", "iwarp_rdma.sinkto",
760                                 FT_UINT64, BASE_DEC, NULL, 0x0,
761                                 NULL, HFILL} },
762                 { &hf_iwarp_rdma_rdmardsz, {
763                                 "RDMA Read Message Size", "iwarp_rdma.rdmardsz",
764                                 FT_UINT32, BASE_DEC, NULL, 0x0,
765                                 NULL, HFILL} },
766                 { &hf_iwarp_rdma_srcstag, {
767                                 "Data Source STag", "iwarp_rdma.srcstag",
768                                 FT_UINT32, BASE_DEC, NULL, 0x0,
769                                 NULL, HFILL} },
770                 { &hf_iwarp_rdma_srcto, {
771                                 "Data Source Tagged Offset", "iwarp_rdma.srcto",
772                                 FT_BYTES, BASE_NONE, NULL, 0x0,
773                                 NULL, HFILL} },
774                 { &hf_iwarp_rdma_term_ctrl, {
775                                 "Terminate Control", "iwarp_rdma.term_ctrl",
776                                 FT_NONE, BASE_NONE, NULL, 0x0,
777                                 "RDMA Terminate Control Field", HFILL} },
778                 { &hf_iwarp_rdma_term_layer, {
779                                 "Layer", "iwarp_rdma.term_layer",
780                                 FT_UINT8, BASE_HEX, VALS(layer_names), IWARP_LAYER,
781                                 "Terminate Control Field: Layer", HFILL} },
782                 { &hf_iwarp_rdma_term_etype_rdma, {
783                                 "Error Types for RDMA layer", "iwarp_rdma.term_etype_rdma",
784                                 FT_UINT8, BASE_HEX, VALS(rdma_etype_names), IWARP_ETYPE,
785                                 "Terminate Control Field: Error Type", HFILL} },
786                 { &hf_iwarp_rdma_term_etype_ddp, {
787                                 "Error Types for DDP layer", "iwarp_rdma.term_etype_ddp",
788                                 FT_UINT8, BASE_HEX, VALS(ddp_etype_names), IWARP_ETYPE,
789                                 "Terminate Control Field: Error Type", HFILL} },
790                 { &hf_iwarp_rdma_term_etype_llp, {
791                                 "Error Types for LLP layer", "iwarp_rdma.term_etype_llp",
792                                 FT_UINT8, BASE_HEX, NULL, IWARP_ETYPE,
793                                 "Terminate Control Field: Error Type", HFILL} },
794                 { &hf_iwarp_rdma_term_etype, {
795                                 "Error Types", "iwarp_rdma.term_etype",
796                                 FT_UINT8, BASE_HEX, NULL, IWARP_ETYPE,
797                                 "Terminate Control Field: Error Type", HFILL} },
798                 { &hf_iwarp_rdma_term_errcode_rdma, {
799                                 "Error Code for RDMA layer", "iwarp_rdma.term_errcode_rdma",
800                                 FT_UINT8, BASE_HEX, VALS(rdma_errcode_names), 0x0,
801                                 "Terminate Control Field: Error Code", HFILL} },
802                 { &hf_iwarp_rdma_term_errcode_ddp_tagged, {
803                                 "Error Code for DDP Tagged Buffer",
804                                 "iwarp_rdma.term_errcode_ddp_tagged",
805                                 FT_UINT8, BASE_HEX, VALS(ddp_errcode_tagged_names), 0x0,
806                                 "Terminate Control Field: Error Code", HFILL} },
807                 { &hf_iwarp_rdma_term_errcode_ddp_untagged, {
808                                 "Error Code for DDP Untagged Buffer",
809                                 "iwarp_rdma.term_errcode_ddp_untagged",
810                                 FT_UINT8, BASE_HEX, VALS(ddp_errcode_untagged_names), 0x0,
811                                 "Terminate Control Field: Error Code", HFILL} },
812                 { &hf_iwarp_rdma_term_errcode, {
813                                 "Error Code", "iwarp_rdma.term_errcode",
814                                 FT_UINT8, BASE_HEX, NULL, 0x0,
815                                 "Terminate Control Field: Error Code", HFILL} },
816                 { &hf_iwarp_rdma_term_errcode_llp, {
817                                 "Error Code for LLP layer", "iwarp_rdma.term_errcode_llp",
818                                 FT_UINT8, BASE_HEX, NULL, 0x0,
819                                 "Terminate Control Field: Lower Layer Protocol Error Code",
820                                 HFILL} },
821                 { &hf_iwarp_rdma_term_hdrct, {
822                                 "Header control bits", "iwarp_rdma.term_hdrct",
823                                 FT_NONE, BASE_NONE, NULL, IWARP_HDRCT,
824                                 "Terminate Control Field: Header control bits", HFILL} },
825                 { &hf_iwarp_rdma_term_hdrct_m, {
826                                 "M bit", "iwarp_rdma.term_hdrct_m",
827                                 FT_UINT8, BASE_HEX, NULL, IWARP_HDRCT_M,
828                                 "Header control bit m: DDP Segment Length valid", HFILL} },
829                 { &hf_iwarp_rdma_term_hdrct_d, {
830                                 "D bit", "iwarp_rdma.hdrct_d",
831                                 FT_UINT8, BASE_HEX, NULL, IWARP_HDRCT_D,
832                                 "Header control bit d: DDP Header Included", HFILL} },
833                 { &hf_iwarp_rdma_term_hdrct_r, {
834                                 "R bit", "iwarp_rdma.hdrct_r",
835                                 FT_UINT8, BASE_HEX, NULL, IWARP_HDRCT_R,
836                                 "Header control bit r: RDMAP Header Included", HFILL} },
837                 { &hf_iwarp_rdma_term_rsvd, {
838                                 "Reserved", "iwarp_rdma.term_rsvd",
839                                 FT_UINT16, BASE_HEX, NULL, IWARP_TERM_RES,
840                                 NULL, HFILL} },
841                 { &hf_iwarp_rdma_term_ddp_seg_len, {
842                                 "DDP Segment Length", "iwarp_rdma.term_ddp_seg_len",
843                                 FT_BYTES, BASE_NONE, NULL, 0x0,
844                                 NULL, HFILL} },
845                 { &hf_iwarp_rdma_term_ddp_h, {
846                                 "Terminated DDP Header", "iwarp_rdma.term_ddp_h",
847                                 FT_BYTES, BASE_NONE, NULL, 0x0,
848                                 NULL, HFILL} },
849                 { &hf_iwarp_rdma_term_rdma_h, {
850                                 "Terminated RDMA Header", "iwarp_rdma.term_rdma_h",
851                                 FT_BYTES, BASE_NONE, NULL, 0x0,
852                                 NULL, HFILL} }
853         };
854
855         /* setup protocol subtree array */
856         static gint *ett[] = {
857
858                 &ett_iwarp_ddp_rdmap,
859                 
860                 /* DDP */
861                 &ett_iwarp_ddp,
862
863                 &ett_iwarp_ddp_control_field,
864                 &ett_iwarp_ddp_tagged_header,
865                 &ett_iwarp_ddp_untagged_header,
866                 
867                 /* RDMAP */
868                 &ett_iwarp_rdma,
869                 
870                 &ett_iwarp_rdma_control_field,
871                 &ett_iwarp_rdma_rr_header,
872                 &ett_iwarp_rdma_terminate_header,
873                 &ett_iwarp_rdma_term_ctrl,
874                 &ett_iwarp_rdma_term_hdrct
875         };
876
877         /* register the protocol name and description */
878         proto_iwarp_ddp_rdmap = proto_register_protocol(
879                 "iWARP Direct Data Placement and Remote Direct Memory Access Protocol",
880                 "IWARP_DDP_RDMAP",
881                 "iwarp_ddp_rdmap");
882
883         /* required function calls to register the header fields and subtrees */
884         proto_register_field_array(proto_iwarp_ddp_rdmap, hf, array_length(hf));
885         proto_register_subtree_array(ett, array_length(ett));
886
887         register_dissector("iwarp_ddp_rdmap", dissect_iwarp_ddp_rdmap,
888                         proto_iwarp_ddp_rdmap);
889 }
890
891 void
892 proto_reg_handoff_iwarp_ddp_rdmap(void)
893 {
894         data_handle = find_dissector("data");
895 }