3 * Routines for IBM i RDMA dissection
4 * Copyright 2018, 2024 IBM Corporation
5 * Brian Jongekryg (bej@us.ibm.com, bej@arbin.net)
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
15 * Dissector for IBM i base RDMA frame traffic
16 * captured via TRCCNN TYPE(*RDMA) command
18 * Subdissectors for IBM i RDMA endoint traffic can be registered
20 * dissector_add_uint("irdma.ep.port", port, handle);
27 #include <epan/packet.h> /* Should be first Wireshark include (other than config.h) */
28 #include <epan/conversation.h>
29 #include <epan/proto_data.h>
30 #include <epan/expert.h>
31 #include <epan/prefs.h>
32 #include <epan/addr_resolv.h>
33 #include <wsutil/utf8_entities.h>
35 #include <packet-irdma.h>
37 /* irdmaep conversation and packet analysis data */
38 typedef struct irdmaep_buffer
43 /* Offset of first byte available for use */
46 /* Last data sequence number in buffer */
49 /* Contents of buffer unknown */
54 #define IRDMAEP_MAX_DATA_BUFID 2
55 typedef struct irdmaep_flow
57 /* Last sent DATA sequence */
61 /* Last sent USER_RDMA data (RECVACK) ID, offset */
64 uint32_t recvack_offset
;
66 /* Receive buffer status */
67 /* Number of receive buffers */
68 uint32_t recv_buffer_count
;
70 /* Most recent buffer used by sender */
73 /* Calculated buffer size estimate */
74 uint32_t recv_min_size
;
76 /* Track up to two remote receive buffers */
77 irdmaep_buffer_t recv_buffer
[IRDMAEP_MAX_DATA_BUFID
];
81 typedef struct irdmaep_analysis
83 /* Trace status for both directions of the flow.
84 Info for sends with smaller src port is recorded in flow1,
85 larger src port in flow2. */
89 /* Forward or reverse flow info based on current packet ports */
90 irdmaep_flow_t
*fwd_flow
, *rev_flow
;
92 /* Server port number from CONNREQ or CONNACK to help determine
93 which payload dissector to call. */
96 /* Keep track of RDMA endpoint stream numbers */
99 /* Track whether conversation was closed, so we know to start
100 new conversation if CONNREQ/ACK seen. */
103 /* Current link sequence number */
106 /* Link switch timestamps */
107 nstime_t movereq_time
;
109 /* Conversation timestamps */
113 } irdmaep_analysis_t
;
115 typedef struct irdmaep_packet_analysis
117 /* Retransmitted packet? */
120 /* Out-of-order sequence (should never occur) */
123 /* Bytes remaining available for sending/receiving */
124 uint32_t rbuf_available
;
126 /* Bytes remaining in current/active receive buffer */
129 /* Max bytes available for next send */
132 /* Is rbuf_available estimated or true value */
135 /* Does packet sequence indicate this is stale (prior link) */
138 /* First packet on new link */
141 /* Time to move link */
142 nstime_t movelink_time
;
144 /* Delta time from previous packet */
147 } irdmaep_packet_analysis_t
;
150 void proto_reg_handoff_irdma(void);
151 void proto_register_irdma(void);
153 static int dissect_irdma(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
);
154 static int dissect_irdmaqp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
);
155 static int dissect_irdmalink(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
);
156 static int dissect_irdmaep(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
);
157 static void dissect_data_msg(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
158 irdmaep_analysis_t
*epd
, proto_tree
*ep_tree
);
159 static void irdmaep_add_rbuf_tree(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
160 irdmaep_packet_analysis_t
*eppd
);
161 static void dissect_reuse_msg(tvbuff_t
*tvb
, packet_info
*pinfo
,
162 irdmaep_analysis_t
*epd
, proto_tree
*ep_tree
);
163 static void dissect_user_recv_msg(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
164 irdmaep_analysis_t
*epd
, proto_tree
*ep_tree
);
165 static void dissect_user_send_msg(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
166 irdmaep_analysis_t
*epd
, proto_tree
*ep_tree
);
167 static void dissect_connect_msg(tvbuff_t
*tvb
, packet_info
*pinfo
,
168 irdmaep_analysis_t
*epd
, proto_tree
*ep_tree
);
169 static void dissect_close_msg(tvbuff_t
*tvb
, packet_info
*pinfo
,
170 irdmaep_analysis_t
*epd
, proto_tree
*ep_tree
);
171 static void dissect_buffer_msg_mkeyaddr(tvbuff_t
*tvb
, packet_info
*pinfo
,
172 irdmaep_analysis_t
*epd
, proto_tree
*ep_tree
);
173 static void dissect_buffer_msg(tvbuff_t
*tvb
, packet_info
*pinfo
,
174 irdmaep_analysis_t
*epd
, proto_tree
*ep_tree
);
175 static void dissect_move_link_msg(tvbuff_t
*tvb
, packet_info
*pinfo
,
176 irdmaep_analysis_t
*epd
, proto_tree
*ep_tree
);
177 static void dissect_move_link_ack_msg(tvbuff_t
*tvb
, packet_info
*pinfo
,
178 irdmaep_analysis_t
*epd
, proto_tree
*ep_tree
);
179 static void dissect_move_link_cmp_msg(tvbuff_t
*tvb
, packet_info
*pinfo
,
180 irdmaep_analysis_t
*epd
, proto_tree
*ep_tree
);
181 static void dissect_irdmaep_data(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
182 irdmaep_pdata_t
*data
);
183 static irdmaep_analysis_t
*init_irdmaep_conversation_data(packet_info
*pinfo
);
184 static void analyze_irdmaep_rbuffer(irdmaep_flow_t
*flow
,
185 irdmaep_packet_analysis_t
*eppd
);
186 static void *add_eppd(packet_info
*pinfo
);
187 static void *get_eppd(packet_info
*pinfo
);
188 static void *get_or_add_eppd(packet_info
*pinfo
);
190 /* Initialize the protocol and registered fields */
191 static int proto_irdma
;
192 static int proto_irdmaqp
;
193 static int proto_irdmalink
;
194 static int proto_irdmaep
;
196 static int hf_irdma_hwdst
;
197 static int hf_irdma_hwsrc
;
198 static int hf_irdma_qpindex
;
199 static int hf_irdma_ip6src
;
200 static int hf_irdma_ip6dst
;
201 static int hf_irdma_ip4src
;
202 static int hf_irdma_ip4dst
;
203 static int hf_irdma_hwaddr
;
204 static int hf_irdma_ip6addr
;
205 static int hf_irdma_ip4addr
;
207 static int hf_irdmaqp_type
;
208 static int hf_irdmaqp_id
;
210 static int hf_irdmalink_type
;
211 static int hf_irdmalink_groups
;
213 static int hf_irdmaep_type
;
214 static int hf_irdmaep_len
;
215 static int hf_irdmaep_grpid
;
216 static int hf_irdmaep_grpid_ctr
;
217 static int hf_irdmaep_grpid_time
;
218 static int hf_irdmaep_grpid_hwaddr
;
219 static int hf_irdmaep_srcport
;
220 static int hf_irdmaep_dstport
;
221 static int hf_irdmaep_port
;
222 static int hf_irdmaep_stream
;
223 static int hf_irdmaep_linkseq
;
224 static int hf_irdmaep_sndbufsize
;
225 static int hf_irdmaep_usrblksize
;
226 static int hf_irdmaep_reason
;
227 static int hf_irdmaep_rbuf
;
228 static int hf_irdmaep_rkey
;
229 static int hf_irdmaep_raddr
;
230 static int hf_irdmaep_flags
;
231 static int hf_irdmaep_flag_buf0_free
;
232 static int hf_irdmaep_flag_buf1_free
;
233 static int hf_irdmaep_rcvbufsize
;
234 static int hf_irdmaep_sendseq
;
235 static int hf_irdmaep_recvseq0
;
236 static int hf_irdmaep_recvseq1
;
237 static int hf_irdmaep_usndsent
;
238 static int hf_irdmaep_usndid
;
239 static int hf_irdmaep_urcvid
;
240 static int hf_irdmaep_seqnum
;
241 static int hf_irdmaep_bufid
;
242 static int hf_irdmaep_offset
;
243 static int hf_irdmaep_datalen
;
244 static int hf_irdmaep_ulength
;
245 static int hf_irdmaep_blength
;
246 static int hf_irdmaep_recvid
;
247 static int hf_irdmaep_rbufavail
;
248 static int hf_irdmaep_rbufactive
;
249 static int hf_irdmaep_rbufmax
;
250 static int hf_irdmaep_move1
;
251 static int hf_irdmaep_move2
;
252 static int hf_irdmaep_ts_relative
;
253 static int hf_irdmaep_ts_delta
;
255 static expert_field ei_irdmaep_analysis_stale
;
256 static expert_field ei_irdmaep_analysis_dup
;
257 static expert_field ei_irdmaep_analysis_oos
;
258 static expert_field ei_irdmaep_connection_req
;
259 static expert_field ei_irdmaep_connection_ack
;
260 static expert_field ei_irdmaep_connection_lswt
;
262 /* Initialize the subtree pointers */
263 static int ett_irdma
;
264 static int ett_irdmaqp
;
265 static int ett_irdmalink
;
266 static int ett_irdmaep
;
267 static int ett_irdmaep_grpid
;
268 static int ett_irdmaep_rbuf
;
269 static int ett_irdmaep_bufflags
;
270 static int ett_irdmaep_rcvbuf_analyze
;
271 static int ett_irdmaep_timestamps
;
273 static dissector_table_t irdmaep_dissector_table
= NULL
;
275 static dissector_handle_t irdmaqp_handle
;
276 static dissector_handle_t irdmalink_handle
;
277 static dissector_handle_t irdmaep_handle
;
279 static uint32_t irdmaep_stream_count
;
281 /* Data passed from iRDMA dissector to QP, Link, Endpoint dissectors */
287 /* Miscellaneous utility functions */
289 seq16_lt(uint16_t a
, uint16_t b
)
291 return (int16_t) (a
- b
) < 0;
295 seq16_gt(uint16_t a
, uint16_t b
)
297 return (int16_t) (a
- b
) > 0;
301 is_v4mapped(ws_in6_addr
*addr
)
303 static uint8_t mapped
[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF};
304 return memcmp(addr
, mapped
, 12) == 0;
308 is_v4compat(ws_in6_addr
*addr
)
310 static uint8_t zeroes
[12] = {0};
311 return memcmp(addr
, zeroes
, 12) == 0
312 && memcmp(&addr
->bytes
[12], zeroes
, 4) != 0;
315 static const value_string irdma_serv_names
[] = {
316 {930, "mrdb-engine"},
317 {931, "mrdb-objrep"},
318 {932, "mrdb-objrepr"},
323 static inline const char *
324 irdma_serv_name_lookup(unsigned port
)
326 return try_val_to_str(port
, irdma_serv_names
);
330 irdma_col_snprint_port(char *buf
, unsigned long buf_siz
, uint16_t val
)
334 if (gbl_resolv_flags
.transport_name
&&
335 (str
= irdma_serv_name_lookup(val
)) != NULL
) {
336 snprintf(buf
, buf_siz
, "%s(%" PRIu16
")", str
, val
);
338 snprintf(buf
, buf_siz
, "%" PRIu16
, val
);
343 irdma_col_append_ports(column_info
*cinfo
, const int col
, uint16_t src
, uint16_t dst
)
345 char buf_src
[32], buf_dst
[32];
347 irdma_col_snprint_port(buf_src
, 32, src
);
348 irdma_col_snprint_port(buf_dst
, 32, dst
);
349 col_append_lstr(cinfo
, col
, buf_src
, " " UTF8_RIGHTWARDS_ARROW
" ", buf_dst
, COL_ADD_LSTR_TERMINATOR
);
353 irdma_custom_format_port(char *str
, uint32_t port
)
355 irdma_col_snprint_port(str
, ITEM_LABEL_LENGTH
, port
);
359 irdma_custom_format_rbufsize(char *str
, uint32_t bufsize
)
362 uint32_t kb_bufsize
= bufsize
* 4;
363 snprintf(str
, ITEM_LABEL_LENGTH
, "%" PRIu32
" (%" PRIu32
" KB)", bufsize
, kb_bufsize
);
369 irdmaep_stream_count
= 0;
372 /*********************************************************************/
373 /*********************************************************************/
374 /* RDMA pseudo-header data and functions */
375 /*********************************************************************/
376 /*********************************************************************/
378 /* IBM i RDMA pseudo-header from TRCCNN offsets */
379 #define IRDMA_HDR_DST 0
380 #define IRDMA_HDR_SRC 6
381 #define IRDMA_HDR_QPINDEX 12
382 #define IRDMA_HDR_SRCIP 14
383 #define IRDMA_HDR_SRCIP4 26
384 #define IRDMA_HDR_DSTIP 30
385 #define IRDMA_HDR_DSTIP4 42
386 #define IRDMA_HDR_LENGTH 46
388 /* Payload types for IBM i RDMA frames */
389 #define IRDMA_PROTO_ENDPOINT 0 /* 0b */
390 #define IRDMA_PROTO_QP 4 /* 100b */
391 #define IRDMA_PROTO_LINK 5 /* 101b */
393 /* Dissect IBM i RDMA pseudo-header */
395 dissect_irdma(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
397 /* Set up structures needed to add the protocol subtree and manage it */
399 proto_item
*irdma_item
;
400 proto_tree
*irdma_tree
;
401 /* Other misc. local variables. */
404 char *src_str
, *dst_str
;
405 irdma_data_t irdma_data
= {0};
406 dissector_handle_t subdissector_handle
= NULL
;
410 /* First, if at all possible, do some heuristics to check if the packet
411 * cannot possibly belong to your protocol. This is especially important
412 * for protocols directly on top of TCP or UDP where port collisions are
413 * common place (e.g., even though your protocol uses a well known port,
414 * someone else may set up, for example, a web server on that port which,
415 * if someone analyzed that web server's traffic in Wireshark, would result
416 * in Wireshark handing an HTTP packet to your dissector).
421 /* Check that the packet is long enough for it to belong to us. */
422 if (tvb_reported_length(tvb
) < IRDMA_HDR_LENGTH
)
425 /* Check that the packet has a recognizable frame type. This probably
426 won't eliminate many bad packets. */
427 uint8_t ftype
= tvb_get_bits8(tvb
, IRDMA_HDR_LENGTH
* 8, 3);
431 /*** COLUMN DATA ***/
433 /* There are two normal columns to fill in: the 'Protocol' column which
434 * is narrow and generally just contains the constant string 'irdma',
435 * and the 'Info' column which can be much wider and contain misc. summary
436 * information (for example, the port number for TCP packets).
438 * If you are setting the column to a constant string, use "col_set_str()",
439 * as it's more efficient than the other "col_set_XXX()" calls.
442 * - you may be appending to the column later OR
443 * - you have constructed the string locally OR
444 * - the string was returned from a call to val_to_str()
445 * then use "col_add_str()" instead, as that takes a copy of the string.
447 * The function "col_add_fstr()" can be used instead of "col_add_str()"; it
448 * takes "printf()"-like arguments. Don't use "col_add_fstr()" with a format
449 * string of "%s" - just use "col_add_str()" or "col_set_str()", as it's
450 * more efficient than "col_add_fstr()".
452 * For full details see section 1.4 of README.dissector.
455 /* Set the Protocol column to the constant string of irdma */
456 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "RDMA");
458 /* Use first 3 bits beyond header to determine what type of frame this is
459 (QP management, Link Management, Endpoint) */
460 if (ftype
== IRDMA_PROTO_QP
)
462 col_set_str(pinfo
->cinfo
, COL_INFO
, "QP Management");
463 subdissector_handle
= irdmaqp_handle
;
466 if (ftype
== IRDMA_PROTO_LINK
)
468 col_set_str(pinfo
->cinfo
, COL_INFO
, "Link Management");
469 subdissector_handle
= irdmalink_handle
;
473 col_set_str(pinfo
->cinfo
, COL_INFO
, "RDMA Endpoint");
474 subdissector_handle
= irdmaep_handle
;
477 /*** PROTOCOL TREE ***/
479 /* Now we will create a sub-tree for our protocol and start adding fields
480 * to display under that sub-tree. Most of the time the only functions you
481 * will need are proto_tree_add_item() and proto_item_add_subtree().
483 * NOTE: The offset and length values in the call to proto_tree_add_item()
484 * define what data bytes to highlight in the hex display window when the
485 * line in the protocol tree display corresponding to that item is selected.
487 * Supplying a length of -1 tells Wireshark to highlight all data from the
488 * offset to the end of the packet.
491 /* create display subtree for the protocol */
492 irdma_item
= proto_tree_add_item(tree
, proto_irdma
, tvb
, 0, IRDMA_HDR_LENGTH
, ENC_NA
);
493 irdma_tree
= proto_item_add_subtree(irdma_item
, ett_irdma
);
495 set_address_tvb(&pinfo
->dl_dst
, AT_ETHER
, 6, tvb
, IRDMA_HDR_DST
);
496 set_address_tvb(&pinfo
->dl_src
, AT_ETHER
, 6, tvb
, IRDMA_HDR_SRC
);
498 proto_tree_add_item(irdma_tree
, hf_irdma_hwdst
, tvb
, IRDMA_HDR_DST
, 6, ENC_NA
);
499 ti
= proto_tree_add_item(irdma_tree
, hf_irdma_hwaddr
, tvb
, IRDMA_HDR_DST
, 6, ENC_NA
);
500 PROTO_ITEM_SET_HIDDEN(ti
);
502 proto_tree_add_item(irdma_tree
, hf_irdma_hwsrc
, tvb
, IRDMA_HDR_SRC
, 6, ENC_NA
);
503 ti
= proto_tree_add_item(irdma_tree
, hf_irdma_hwaddr
, tvb
, IRDMA_HDR_SRC
, 6, ENC_NA
);
504 PROTO_ITEM_SET_HIDDEN(ti
);
506 proto_tree_add_item_ret_uint(irdma_tree
, hf_irdma_qpindex
, tvb
,
507 IRDMA_HDR_QPINDEX
, 2, ENC_BIG_ENDIAN
,
508 &irdma_data
.qpindex
);
510 /* Get source IP address and determine if we've got an IPv4 or IPv6 address */
511 tvb_get_ipv6(tvb
, IRDMA_HDR_SRCIP
, &ipsrc
);
512 ipv4
= is_v4mapped(&ipsrc
) || is_v4compat(&ipsrc
);
516 set_address_tvb(&pinfo
->net_dst
, AT_IPv4
, 4, tvb
, IRDMA_HDR_DSTIP4
);
517 copy_address_shallow(&pinfo
->dst
, &pinfo
->net_dst
);
519 set_address_tvb(&pinfo
->net_src
, AT_IPv4
, 4, tvb
, IRDMA_HDR_SRCIP4
);
520 copy_address_shallow(&pinfo
->src
, &pinfo
->net_src
);
522 src_str
= tvb_address_with_resolution_to_str(wmem_packet_scope(), tvb
, AT_IPv4
, IRDMA_HDR_SRCIP4
);
523 dst_str
= tvb_address_with_resolution_to_str(wmem_packet_scope(), tvb
, AT_IPv4
, IRDMA_HDR_DSTIP4
);
525 proto_tree_add_item(irdma_tree
, hf_irdma_ip4src
, tvb
, IRDMA_HDR_SRCIP4
, 4, ENC_BIG_ENDIAN
);
526 ti
= proto_tree_add_item(irdma_tree
, hf_irdma_ip4addr
, tvb
, IRDMA_HDR_SRCIP4
, 4, ENC_BIG_ENDIAN
);
527 PROTO_ITEM_SET_HIDDEN(ti
);
529 proto_tree_add_item(irdma_tree
, hf_irdma_ip4dst
, tvb
, IRDMA_HDR_DSTIP4
, 4, ENC_BIG_ENDIAN
);
530 ti
= proto_tree_add_item(irdma_tree
, hf_irdma_ip4addr
, tvb
, IRDMA_HDR_DSTIP4
, 4, ENC_BIG_ENDIAN
);
531 PROTO_ITEM_SET_HIDDEN(ti
);
535 set_address_tvb(&pinfo
->net_dst
, AT_IPv6
, 16, tvb
, IRDMA_HDR_DSTIP
);
536 copy_address_shallow(&pinfo
->dst
, &pinfo
->net_dst
);
538 set_address_tvb(&pinfo
->net_src
, AT_IPv6
, 16, tvb
, IRDMA_HDR_SRCIP
);
539 copy_address_shallow(&pinfo
->src
, &pinfo
->net_src
);
541 src_str
= tvb_address_with_resolution_to_str(wmem_packet_scope(), tvb
, AT_IPv6
, IRDMA_HDR_SRCIP
);
542 dst_str
= tvb_address_with_resolution_to_str(wmem_packet_scope(), tvb
, AT_IPv6
, IRDMA_HDR_DSTIP
);
544 proto_tree_add_item(irdma_tree
, hf_irdma_ip6src
, tvb
, IRDMA_HDR_SRCIP
, 16, ENC_NA
);
545 ti
= proto_tree_add_item(irdma_tree
, hf_irdma_ip6addr
, tvb
, IRDMA_HDR_SRCIP
, 16, ENC_NA
);
546 PROTO_ITEM_SET_HIDDEN(ti
);
548 proto_tree_add_item(irdma_tree
, hf_irdma_ip6dst
, tvb
, IRDMA_HDR_DSTIP
, 16, ENC_NA
);
549 ti
= proto_tree_add_item(irdma_tree
, hf_irdma_ip6addr
, tvb
, IRDMA_HDR_DSTIP
, 16, ENC_NA
);
550 PROTO_ITEM_SET_HIDDEN(ti
);
553 proto_item_append_text(irdma_item
, ", Src: %s", src_str
);
554 proto_item_append_text(irdma_item
, ", Dst: %s", dst_str
);
556 call_dissector_with_data(subdissector_handle
,
557 tvb_new_subset_remaining(tvb
, IRDMA_HDR_LENGTH
),
558 pinfo
, tree
, &irdma_data
);
560 /* Return the amount of data this dissector was able to dissect (which may
561 * or may not be the total captured packet as we return here). */
562 return tvb_captured_length(tvb
);
565 /*********************************************************************/
566 /*********************************************************************/
567 /* RDMA QP data and functions */
568 /*********************************************************************/
569 /*********************************************************************/
570 /* IBM i RDMA QP message types */
571 #define IRDMA_QP_ECHOREQ 0x8000
572 #define IRDMA_QP_ECHORSP 0x8001
574 /* IBM i RDMA QP message offsets */
575 #define IRDMA_QP_TYPE 0 /* 16-bit message type */
576 #define IRDMA_QP_ECHO_ID 2 /* 16-bit Echo req/rsp ID */
578 static const value_string irdmaqp_type_str
[] = {
579 {IRDMA_QP_ECHOREQ
, "Echo request"},
580 {IRDMA_QP_ECHORSP
, "Echo response"},
583 /* Dissect RDMA QP packets */
585 dissect_irdmaqp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
590 irdma_data_t
*irdma_data
= (irdma_data_t
*) data
;
592 if (tvb_reported_length(tvb
) < 2)
595 /* Set the Protocol column */
596 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "RDMA-QP");
598 uint16_t msg_type
= tvb_get_ntohs(tvb
, IRDMA_QP_TYPE
);
599 const char *msg_type_str
= val_to_str(msg_type
, irdmaqp_type_str
,
600 "Unknown message (0x%04X)");
602 col_add_fstr(pinfo
->cinfo
, COL_INFO
,
603 "%-16s qp=%2" PRIu32
, msg_type_str
, irdma_data
->qpindex
);
605 /* Create display subtree for the QP message */
606 ti
= proto_tree_add_item(tree
, proto_irdmaqp
, tvb
, 0, -1, ENC_NA
);
607 qp_tree
= proto_item_add_subtree(ti
, ett_irdmaqp
);
609 proto_tree_add_item(qp_tree
, hf_irdmaqp_type
, tvb
, IRDMA_QP_TYPE
, 2,
614 case IRDMA_QP_ECHOREQ
:
615 case IRDMA_QP_ECHORSP
:
618 proto_tree_add_item_ret_uint(qp_tree
, hf_irdmaqp_id
, tvb
,
620 ENC_BIG_ENDIAN
, &echo_id
);
621 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", id=%" PRIu32
, echo_id
);
626 return tvb_captured_length(tvb
);
629 /*********************************************************************/
630 /*********************************************************************/
631 /* RDMA Link data and functions */
632 /*********************************************************************/
633 /*********************************************************************/
634 /* IBM i RDMA Link message types */
635 #define IRDMA_LINK_STATUS 0xA000
637 /* IBM i RDMA Link message offsets */
638 #define IRDMA_LINK_TYPE 0 /* 16-bit message type */
639 #define IRDMA_LINK_STATUS_GROUPS 2 /* 16-bit count of active groups */
641 static const value_string irdmalink_type_str
[] = {
642 {IRDMA_LINK_STATUS
, "Link Status"},
645 /* Dissect RDMA Link packets */
647 dissect_irdmalink(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
650 proto_tree
*link_tree
;
652 if (tvb_reported_length(tvb
) < 2)
655 /* Set the Protocol column */
656 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "RDMA-Link");
658 uint16_t msg_type
= tvb_get_ntohs(tvb
, IRDMA_LINK_TYPE
);
659 const char *msg_type_str
= val_to_str(msg_type
, irdmalink_type_str
,
660 "Unknown message (0x%04X)");
662 col_add_str(pinfo
->cinfo
, COL_INFO
, msg_type_str
);
664 /* Create display subtree for the Link message */
665 ti
= proto_tree_add_item(tree
, proto_irdmalink
, tvb
, 0, -1, ENC_NA
);
666 link_tree
= proto_item_add_subtree(ti
, ett_irdmalink
);
668 proto_tree_add_item(link_tree
, hf_irdmalink_type
, tvb
, IRDMA_LINK_TYPE
, 2,
673 case IRDMA_LINK_STATUS
:
676 proto_tree_add_item_ret_uint(link_tree
, hf_irdmalink_groups
, tvb
,
677 IRDMA_LINK_STATUS_GROUPS
, 2,
678 ENC_BIG_ENDIAN
, &groups
);
679 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", groups=%" PRIu32
, groups
);
684 return tvb_captured_length(tvb
);
687 /*********************************************************************/
688 /*********************************************************************/
689 /* RDMA Endpoint data and functions */
690 /*********************************************************************/
691 /*********************************************************************/
692 /* IBM i RDMA Endpoint preferences */
693 static bool irdmaep_calculate_ts
= true;
694 static bool irdmaep_no_subdissector_on_error
= true;
696 /* IBM i RDMA Endpoint message types */
697 #define IRDMA_EP_CONNREQ 0x01
698 #define IRDMA_EP_CONNACK 0x02
699 #define IRDMA_EP_CONNBUF 0x03
700 #define IRDMA_EP_RNEGREQ 0x04
701 #define IRDMA_EP_RNEGACK 0x05
702 #define IRDMA_EP_CLOSE 0x06
703 #define IRDMA_EP_RESET 0x09
704 #define IRDMA_EP_MOVEREQ 0x11
705 #define IRDMA_EP_MOVEACK 0x12
706 #define IRDMA_EP_MOVECMP 0x13
707 #define IRDMA_EP_DATA 0x21
708 #define IRDMA_EP_REUSEBUF 0x22
709 #define IRDMA_EP_RECVREQ 0x23
710 #define IRDMA_EP_RECVACK 0x24
711 #define IRDMA_EP_RECVNAK 0x25
713 /* IBM i RDMA Endpoint message offsets */
714 #define IRDMA_EP_TYPE 0 /* ( 1) Message type */
715 #define IRDMA_EP_LEN 1 /* ( 1) Message length */
716 #define IRDMA_EP_GRPID 2 /* (12) Group ID */
717 #define IRDMA_EP_GRPID_CTR 2 /* ( 1) Uniqueness counter */
718 #define IRDMA_EP_GRPID_TIME 3 /* ( 5) Bits 4-43 of TOD */
719 #define IRDMA_EP_GRPID_MAC 8 /* ( 6) MAC address */
720 #define IRDMA_EP_SPORT 14 /* ( 2) Source port */
721 #define IRDMA_EP_DPORT 16 /* ( 2) Destination port */
722 #define IRDMA_EP_LINKSEQ 18 /* ( 2) Link sequence number */
723 #define IRDMA_EP_MIN_LENGTH 20
725 #define IRDMA_EP_CONNECT_BUFSIZE 20 /* ( 2) Send buffer size (* 4KB) */
726 #define IRDMA_EP_CONNECT_USRBLKSIZE 22 /* ( 2) USER_RDMA receive block size (* 4KB) */
727 #define IRDMA_EP_CONNECT_MIN_LENGTH 24
729 #define IRDMA_EP_CLOSE_REASON 20 /* ( 4) Close reason */
730 #define IRDMA_EP_CLOSE_MIN_LENGTH 24
732 #define IRDMA_EP_BUFFER_RKEY 20 /* ( 4) x2 Receive buffer MKeys */
733 #define IRDMA_EP_BUFFER_RADDR 28 /* ( 8) x2 Receive buffer addresses */
734 #define IRDMA_EP_BUFFER_FLAGS 44 /* ( 4 bits) Flags */
735 #define IRDMA_EP_BUFFER_RBUFSIZE 44 /* (12 bits) Size of each receive buffer (* 4KB) */
736 #define IRDMA_EP_MOVELINK_SENDSEQ 46 /* ( 2) Last sent sequence number */
737 #define IRDMA_EP_MOVELINK_RBUFSEQ 48 /* ( 2) x2 Last received sequence number */
738 #define IRDMA_EP_MOVELINK_USNDSENT 52 /* ( 4) Number of bytes sent from current USER_RDMA */
739 #define IRDMA_EP_MOVELINK_USNDID 56 /* ( 2) Current USER_RDMA recv ID being sent */
740 #define IRDMA_EP_MOVELINKACK_URCVID 58 /* ( 2) Last USER_RDMA recv ID complete */
742 #define IRDMA_EP_MOVELINKCMP_URCVID 20 /* ( 2) Last USER_RDMA recv ID complete */
744 #define IRDMA_EP_DATA_SEQNUM 20 /* ( 2) Sequence number */
745 #define IRDMA_EP_DATA_BUFID 22 /* ( 2) Buffer index */
746 #define IRDMA_EP_DATA_OFFSET 24 /* ( 4) Buffer offset */
747 #define IRDMA_EP_DATA_DATALEN 28 /* ( 4) Data length */
748 #define IRDMA_EP_DATA_MSG_LEN 32
750 #define IRDMA_EP_REUSE_SEQNUM 20 /* ( 2) Sequence number */
751 #define IRDMA_EP_REUSE_BUFID 22 /* ( 2) Buffer index */
753 #define IRDMA_EP_USERRECV_ULENGTH 20 /* ( 4) Total user receive length */
754 #define IRDMA_EP_USERRECV_OFFSET 24 /* ( 4) Offset within full buffer */
755 #define IRDMA_EP_USERRECV_RLENGTH 28 /* ( 4) Buffer length */
756 #define IRDMA_EP_USERRECV_RECVID 32 /* ( 2) Receive identifier */
757 #define IRDMA_EP_USERRECV_RKEY 34 /* ( 4) Buffer MKey */
758 #define IRDMA_EP_USERRECV_RADDR 38 /* ( 8) Buffer address */
759 #define IRDMA_EP_USERRECV_MSG_LEN 46
761 #define IRDMA_EP_USERSEND_ULENGTH 20 /* ( 4) Total user send length */
762 #define IRDMA_EP_USERSEND_OFFSET 24 /* ( 4) Offset within full buffer */
763 #define IRDMA_EP_USERSEND_SLENGTH 28 /* ( 4) Length sent */
764 #define IRDMA_EP_USERSEND_RECVID 32 /* ( 2) Receive identifier */
765 #define IRDMA_EP_USERSEND_MSG_LEN 34
767 static const value_string irdmaep_type_str
[] = {
768 {IRDMA_EP_CONNREQ
, "CONNREQ"},
769 {IRDMA_EP_CONNACK
, "CONNACK"},
770 {IRDMA_EP_CONNBUF
, "CONNBUF"},
771 {IRDMA_EP_RNEGREQ
, "RNEGREQ"},
772 {IRDMA_EP_RNEGACK
, "RNEGACK"},
773 {IRDMA_EP_CLOSE
, "CLOSE"},
774 {IRDMA_EP_RESET
, "RESET"},
775 {IRDMA_EP_MOVEREQ
, "MOVEREQ"},
776 {IRDMA_EP_MOVEACK
, "MOVEACK"},
777 {IRDMA_EP_MOVECMP
, "MOVECMP"},
778 {IRDMA_EP_DATA
, "DATA"},
779 {IRDMA_EP_REUSEBUF
, "REUSEBUF"},
780 {IRDMA_EP_RECVREQ
, "RECVREQ"},
781 {IRDMA_EP_RECVACK
, "RECVACK"},
782 {IRDMA_EP_RECVNAK
, "RECVNAK"},
785 static const value_string vals_free_inuse
[] = {
790 /* Dissect RDMA Endpoint packets */
792 dissect_irdmaep(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
794 proto_item
*ti
, *ti_seq
, *ti_type
;
795 proto_tree
*ep_tree
, *ts_tree
;
796 proto_tree
*grpid_tree
;
798 conversation_t
*conv
= NULL
;
799 irdmaep_analysis_t
*epd
= NULL
;
800 irdmaep_packet_analysis_t
*eppd
= NULL
;
804 if (tvb_reported_length(tvb
) < IRDMA_EP_MIN_LENGTH
)
807 /* Set the Protocol column */
808 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "RDMA-EP");
810 col_clear(pinfo
->cinfo
, COL_INFO
);
812 pinfo
->srcport
= tvb_get_ntohs(tvb
, IRDMA_EP_SPORT
);
813 pinfo
->destport
= tvb_get_ntohs(tvb
, IRDMA_EP_DPORT
);
814 pinfo
->ptype
= PT_TCP
; /* Not really TCP, but nothing else better */
815 irdma_col_append_ports(pinfo
->cinfo
, COL_INFO
,
816 pinfo
->srcport
, pinfo
->destport
);
818 set_address(&group_addr
, AT_STRINGZ
, 25,
819 tvb_bytes_to_str(wmem_packet_scope(), tvb
, IRDMA_EP_GRPID
, 12));
821 uint8_t msg_type
= tvb_get_uint8(tvb
, IRDMA_EP_TYPE
);
822 uint8_t msg_length
= tvb_get_uint8(tvb
, IRDMA_EP_LEN
);
823 const char *msg_type_str
= val_to_str(msg_type
, irdmaep_type_str
,
825 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " [%s]", msg_type_str
);
827 /* Find or create conversation for this packet */
828 conv
= find_conversation(pinfo
->num
, &group_addr
, &group_addr
,
829 CONVERSATION_NONE
, pinfo
->srcport
, pinfo
->destport
, 0);
831 /* If first time through the packets and conversation exists but message
832 is a CONNREQ, check if we really should be starting a new conversation
834 if (!PINFO_FD_VISITED(pinfo
)
836 && msg_type
== IRDMA_EP_CONNREQ
)
838 epd
= (irdmaep_analysis_t
*) conversation_get_proto_data(conv
, proto_irdmaep
);
839 if (epd
&& epd
->closed
)
843 /* If this is a new conversation, allocate conversation data */
846 conv
= conversation_new(pinfo
->num
, &group_addr
, &group_addr
,
847 CONVERSATION_NONE
, pinfo
->srcport
, pinfo
->destport
, 0);
848 epd
= init_irdmaep_conversation_data(pinfo
);
849 conversation_add_proto_data(conv
, proto_irdmaep
, epd
);
852 epd
= (irdmaep_analysis_t
*) conversation_get_proto_data(conv
, proto_irdmaep
);
854 DISSECTOR_ASSERT(epd
!= NULL
);
856 if (pinfo
->num
> conv
->last_frame
)
857 conv
->last_frame
= pinfo
->num
;
859 epd
->fwd_flow
= &epd
->flow1
;
860 epd
->rev_flow
= &epd
->flow2
;
861 if (pinfo
->srcport
< pinfo
->destport
)
863 epd
->fwd_flow
= &epd
->flow2
;
864 epd
->rev_flow
= &epd
->flow1
;
867 /* Create display subtree for the Endpoint message */
868 ti
= proto_tree_add_item(tree
, proto_irdmaep
, tvb
, 0, msg_length
, ENC_NA
);
869 ep_tree
= proto_item_add_subtree(ti
, ett_irdmaep
);
871 ti_type
= proto_tree_add_item(ep_tree
, hf_irdmaep_type
, tvb
,
872 IRDMA_EP_TYPE
, 1, ENC_NA
);
873 proto_tree_add_item(ep_tree
, hf_irdmaep_len
, tvb
,
874 IRDMA_EP_LEN
, 1, ENC_NA
);
876 ti
= proto_tree_add_item(ep_tree
, hf_irdmaep_grpid
, tvb
,
877 IRDMA_EP_GRPID
, 12, ENC_NA
);
878 grpid_tree
= proto_item_add_subtree(ti
, ett_irdmaep_grpid
);
880 proto_tree_add_item(grpid_tree
, hf_irdmaep_grpid_ctr
, tvb
,
881 IRDMA_EP_GRPID_CTR
, 1, ENC_NA
);
882 proto_tree_add_item(grpid_tree
, hf_irdmaep_grpid_time
, tvb
,
883 IRDMA_EP_GRPID_TIME
, 5, ENC_BIG_ENDIAN
);
884 proto_tree_add_item(grpid_tree
, hf_irdmaep_grpid_hwaddr
, tvb
,
885 IRDMA_EP_GRPID_MAC
, 6, ENC_NA
);
888 proto_tree_add_item_ret_uint(ep_tree
, hf_irdmaep_srcport
, tvb
,
889 IRDMA_EP_SPORT
, 2, ENC_BIG_ENDIAN
,
891 ti
= proto_tree_add_item(ep_tree
, hf_irdmaep_port
, tvb
,
892 IRDMA_EP_SPORT
, 2, ENC_BIG_ENDIAN
);
893 PROTO_ITEM_SET_HIDDEN(ti
);
895 proto_tree_add_item_ret_uint(ep_tree
, hf_irdmaep_dstport
, tvb
,
896 IRDMA_EP_DPORT
, 2, ENC_BIG_ENDIAN
,
898 ti
= proto_tree_add_item(ep_tree
, hf_irdmaep_port
, tvb
,
899 IRDMA_EP_DPORT
, 2, ENC_BIG_ENDIAN
);
900 PROTO_ITEM_SET_HIDDEN(ti
);
901 ti
= proto_tree_add_uint(ep_tree
, hf_irdmaep_stream
, tvb
, 0, 0,
903 PROTO_ITEM_SET_GENERATED(ti
);
904 ti_seq
= proto_tree_add_item_ret_uint(ep_tree
, hf_irdmaep_linkseq
, tvb
,
905 IRDMA_EP_LINKSEQ
, 2, ENC_BIG_ENDIAN
,
908 /* Record conversation info that should only be done on first pass
909 (when packets are seen in order) */
910 if (!PINFO_FD_VISITED(pinfo
))
912 if (irdmaep_calculate_ts
)
915 eppd
= (irdmaep_packet_analysis_t
*) get_or_add_eppd(pinfo
);
916 nstime_delta(&eppd
->delta_time
, &pinfo
->abs_ts
, &epd
->ts_prev
);
918 nstime_copy(&epd
->ts_prev
, &pinfo
->abs_ts
);
921 /* If this is a CLOSE or RESET request, remember so that if we see a
922 later CONNREQ with the same ports, we'll create a new conversation. */
923 if (msg_type
== IRDMA_EP_CLOSE
924 || msg_type
== IRDMA_EP_RESET
)
927 /* If link seq not yet known, save current link seq */
928 if (epd
->link
== 0xFFFFFFFF)
931 /* Update current link seq if it has increased */
932 if (seq16_gt(linkseq
, epd
->link
))
936 eppd
= (irdmaep_packet_analysis_t
*) get_or_add_eppd(pinfo
);
940 /* If packet is from prior link, set stale flag */
941 if (seq16_lt(linkseq
, epd
->link
))
944 eppd
= (irdmaep_packet_analysis_t
*) get_or_add_eppd(pinfo
);
949 eppd
= (irdmaep_packet_analysis_t
*) get_eppd(pinfo
);
954 expert_add_info(pinfo
, ti_seq
, &ei_irdmaep_connection_lswt
);
957 expert_add_info(pinfo
, ti_seq
, &ei_irdmaep_analysis_stale
);
963 dissect_data_msg(tvb
, pinfo
, tree
, epd
, ep_tree
);
966 case IRDMA_EP_REUSEBUF
:
967 dissect_reuse_msg(tvb
, pinfo
, epd
, ep_tree
);
970 case IRDMA_EP_RECVREQ
:
971 dissect_user_recv_msg(tvb
, pinfo
, tree
, epd
, ep_tree
);
974 case IRDMA_EP_RECVACK
:
975 case IRDMA_EP_RECVNAK
:
976 dissect_user_send_msg(tvb
, pinfo
, tree
, epd
, ep_tree
);
979 case IRDMA_EP_CONNREQ
:
980 expert_add_info_format(pinfo
, ti_type
, &ei_irdmaep_connection_req
,
981 "Connection request (CONNREQ): server port %u",
983 dissect_connect_msg(tvb
, pinfo
, epd
, ep_tree
);
986 case IRDMA_EP_CONNACK
:
987 expert_add_info_format(pinfo
, ti_type
, &ei_irdmaep_connection_ack
,
988 "Connection acknowledgement (CONNACK): server port %u",
990 dissect_connect_msg(tvb
, pinfo
, epd
, ep_tree
);
993 case IRDMA_EP_RNEGREQ
:
994 dissect_connect_msg(tvb
, pinfo
, epd
, ep_tree
);
998 dissect_close_msg(tvb
, pinfo
, epd
, ep_tree
);
1001 case IRDMA_EP_CONNBUF
:
1002 case IRDMA_EP_RNEGACK
:
1003 dissect_buffer_msg(tvb
, pinfo
, epd
, ep_tree
);
1006 case IRDMA_EP_MOVEREQ
:
1007 if (!PINFO_FD_VISITED(pinfo
))
1009 /* Save time of MOVEREQ so we can report link switch delay */
1010 epd
->movereq_time
= pinfo
->abs_ts
;
1013 dissect_move_link_msg(tvb
, pinfo
, epd
, ep_tree
);
1016 case IRDMA_EP_MOVEACK
:
1017 dissect_move_link_ack_msg(tvb
, pinfo
, epd
, ep_tree
);
1020 case IRDMA_EP_MOVECMP
:
1021 dissect_move_link_cmp_msg(tvb
, pinfo
, epd
, ep_tree
);
1025 ts_tree
= proto_tree_add_subtree(ep_tree
, tvb
, 0, 0, ett_irdmaep_timestamps
,
1027 PROTO_ITEM_SET_GENERATED(ti
);
1028 nstime_delta(&ts
, &pinfo
->abs_ts
, &epd
->ts_first
);
1029 ti
= proto_tree_add_time(ts_tree
, hf_irdmaep_ts_relative
, tvb
, 0, 0, &ts
);
1030 PROTO_ITEM_SET_GENERATED(ti
);
1031 if (eppd
&& !nstime_is_unset(&eppd
->delta_time
))
1033 ti
= proto_tree_add_time(ts_tree
, hf_irdmaep_ts_delta
, tvb
, 0, 0,
1035 PROTO_ITEM_SET_GENERATED(ti
);
1038 return tvb_captured_length(tvb
);
1042 dissect_data_msg(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
1043 irdmaep_analysis_t
*epd
, proto_tree
*ep_tree
)
1046 irdmaep_packet_analysis_t
*eppd
= NULL
;
1047 irdmaep_pdata_t pdata
= {IRDMAEP_DATA_TYPE
};
1048 uint32_t bufid
, seqnum
, offset
, datalen
;
1050 ti_seq
= proto_tree_add_item_ret_uint(ep_tree
, hf_irdmaep_seqnum
, tvb
,
1051 IRDMA_EP_DATA_SEQNUM
, 2, ENC_BIG_ENDIAN
,
1053 proto_tree_add_item_ret_uint(ep_tree
, hf_irdmaep_bufid
, tvb
,
1054 IRDMA_EP_DATA_BUFID
, 2, ENC_BIG_ENDIAN
,
1056 proto_tree_add_item_ret_uint(ep_tree
, hf_irdmaep_offset
, tvb
,
1057 IRDMA_EP_DATA_OFFSET
, 4, ENC_BIG_ENDIAN
,
1059 proto_tree_add_item_ret_uint(ep_tree
, hf_irdmaep_datalen
, tvb
,
1060 IRDMA_EP_DATA_DATALEN
, 4, ENC_BIG_ENDIAN
,
1063 /* Update flow analysis only on first (in-order) pass */
1064 if (!PINFO_FD_VISITED(pinfo
)
1065 && bufid
< IRDMAEP_MAX_DATA_BUFID
)
1067 /* Only validate sequence number if we know previous seq# */
1068 if (epd
->fwd_flow
->data_seq_valid
)
1070 uint16_t expected
= epd
->fwd_flow
->data_seq
+ 1;
1071 if (seqnum
!= expected
)
1073 /* Unexpected sequence number -- update packet data */
1074 eppd
= (irdmaep_packet_analysis_t
*) get_or_add_eppd(pinfo
);
1075 if (seq16_lt(seqnum
, expected
))
1076 eppd
->retransmission
= 1;
1078 eppd
->out_of_order
= 1; /* Should never occur! */
1082 epd
->fwd_flow
->data_seq_valid
= 1;
1083 epd
->fwd_flow
->data_seq
= seqnum
;
1085 /* Update remote receive buffer status */
1086 /* First, if this gives info on receive buffer we didn't yet know about,
1087 bump buffer count but set those buffers to indeterminate state */
1088 for (; epd
->fwd_flow
->recv_buffer_count
<= bufid
; ++epd
->fwd_flow
->recv_buffer_count
)
1089 epd
->fwd_flow
->recv_buffer
[epd
->fwd_flow
->recv_buffer_count
].indeterminate
= 1;
1091 epd
->fwd_flow
->recv_mrb
= bufid
;
1092 epd
->fwd_flow
->recv_buffer
[bufid
].seq_num
= seqnum
;
1093 epd
->fwd_flow
->recv_buffer
[bufid
].offset
= (offset
+ datalen
+ 0xF) & ~0xF;
1094 epd
->fwd_flow
->recv_buffer
[bufid
].indeterminate
= 0;
1096 /* Adjust discovered size of buffer (in case initial buffer info msg
1097 wasn't captured for this flow) */
1098 if (epd
->fwd_flow
->recv_buffer
[bufid
].offset
> epd
->fwd_flow
->recv_min_size
)
1099 epd
->fwd_flow
->recv_min_size
= (epd
->fwd_flow
->recv_buffer
[bufid
].offset
+ 0xFFF) & ~0xFFF;
1102 eppd
= (irdmaep_packet_analysis_t
*) get_or_add_eppd(pinfo
);
1103 analyze_irdmaep_rbuffer(epd
->fwd_flow
, eppd
);
1106 eppd
= (irdmaep_packet_analysis_t
*) get_eppd(pinfo
);
1110 if (eppd
->retransmission
)
1112 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
, "[Retransmission] ");
1113 expert_add_info(pinfo
, ti_seq
, &ei_irdmaep_analysis_dup
);
1116 if (eppd
->out_of_order
)
1118 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
, "[Out-of-order] ");
1119 expert_add_info(pinfo
, ti_seq
, &ei_irdmaep_analysis_oos
);
1122 irdmaep_add_rbuf_tree(tvb
, pinfo
, ep_tree
, eppd
);
1125 dissect_irdmaep_data(tvb_new_subset_remaining(tvb
, IRDMA_EP_DATA_MSG_LEN
),
1126 pinfo
, tree
, &pdata
);
1130 irdmaep_add_rbuf_tree(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
,
1131 irdmaep_packet_analysis_t
*eppd
)
1134 proto_tree
*rcvbuf_tree
;
1136 ti
= proto_tree_add_uint(tree
, hf_irdmaep_rbufavail
, tvb
, 0, 0,
1137 eppd
->rbuf_available
);
1138 if (eppd
->rbuf_estimated
)
1139 proto_item_append_text(ti
, " (min)");
1140 PROTO_ITEM_SET_GENERATED(ti
);
1142 rcvbuf_tree
= proto_item_add_subtree(ti
, ett_irdmaep_rcvbuf_analyze
);
1144 ti
= proto_tree_add_uint(rcvbuf_tree
, hf_irdmaep_rbufactive
, tvb
, 0, 0,
1146 if (eppd
->rbuf_estimated
)
1147 proto_item_append_text(ti
, " (min)");
1148 PROTO_ITEM_SET_GENERATED(ti
);
1150 ti
= proto_tree_add_uint(rcvbuf_tree
, hf_irdmaep_rbufmax
, tvb
, 0, 0,
1152 if (eppd
->rbuf_estimated
)
1153 proto_item_append_text(ti
, " (min)");
1154 PROTO_ITEM_SET_GENERATED(ti
);
1158 dissect_reuse_msg(tvbuff_t
*tvb
, packet_info
*pinfo
,
1159 irdmaep_analysis_t
*epd
, proto_tree
*ep_tree
)
1161 irdmaep_packet_analysis_t
*eppd
= NULL
;
1162 uint32_t bufid
, seqnum
;
1164 proto_tree_add_item_ret_uint(ep_tree
, hf_irdmaep_seqnum
, tvb
,
1165 IRDMA_EP_REUSE_SEQNUM
, 2, ENC_BIG_ENDIAN
,
1167 proto_tree_add_item_ret_uint(ep_tree
, hf_irdmaep_bufid
, tvb
,
1168 IRDMA_EP_REUSE_BUFID
, 2, ENC_BIG_ENDIAN
,
1171 /* Update receive buffer analysis only on first (in-order) pass */
1172 if (!PINFO_FD_VISITED(pinfo
)
1173 && bufid
< IRDMAEP_MAX_DATA_BUFID
)
1175 /* Reuse msg reflects local receive buffer status, so update lcl_rbuf */
1177 /* First, if this gives info on receive buffer we didn't yet know about,
1178 bump buffer count but set those buffers to indeterminate state */
1179 for (; epd
->rev_flow
->recv_buffer_count
<= bufid
; ++epd
->rev_flow
->recv_buffer_count
)
1180 epd
->rev_flow
->recv_buffer
[epd
->rev_flow
->recv_buffer_count
].indeterminate
= 1;
1182 if (epd
->rev_flow
->recv_buffer_count
> 1
1183 || epd
->rev_flow
->recv_buffer
[bufid
].seq_num
== seqnum
1184 || epd
->rev_flow
->recv_buffer
[bufid
].indeterminate
)
1186 epd
->rev_flow
->recv_buffer
[bufid
].offset
= 0;
1187 epd
->rev_flow
->recv_buffer
[bufid
].indeterminate
= 0;
1190 eppd
= (irdmaep_packet_analysis_t
*) add_eppd(pinfo
);
1191 analyze_irdmaep_rbuffer(epd
->rev_flow
, eppd
);
1194 eppd
= (irdmaep_packet_analysis_t
*) get_eppd(pinfo
);
1197 irdmaep_add_rbuf_tree(tvb
, pinfo
, ep_tree
, eppd
);
1201 dissect_user_recv_msg(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
1202 irdmaep_analysis_t
*epd _U_
, proto_tree
*ep_tree
)
1205 proto_tree
*rbuf_tree
;
1207 irdmaep_pdata_t pdata
= {IRDMAEP_USERRDMA_TYPE
, 0};
1209 proto_tree_add_item(ep_tree
, hf_irdmaep_ulength
, tvb
,
1210 IRDMA_EP_USERRECV_ULENGTH
, 4, ENC_BIG_ENDIAN
);
1211 proto_tree_add_item_ret_uint(ep_tree
, hf_irdmaep_offset
, tvb
,
1212 IRDMA_EP_USERRECV_OFFSET
, 4, ENC_BIG_ENDIAN
,
1213 &pdata
.userrdma_offset
);
1214 proto_tree_add_item(ep_tree
, hf_irdmaep_blength
, tvb
,
1215 IRDMA_EP_USERRECV_RLENGTH
, 4, ENC_BIG_ENDIAN
);
1216 proto_tree_add_item(ep_tree
, hf_irdmaep_recvid
, tvb
,
1217 IRDMA_EP_USERRECV_RECVID
, 2, ENC_BIG_ENDIAN
);
1218 ti
= proto_tree_add_item(ep_tree
, hf_irdmaep_rbuf
, tvb
,
1219 IRDMA_EP_USERRECV_RKEY
, 12, ENC_NA
);
1220 rbuf_tree
= proto_item_add_subtree(ti
, ett_irdmaep_rbuf
);
1221 proto_tree_add_item(rbuf_tree
, hf_irdmaep_rkey
, tvb
,
1222 IRDMA_EP_USERRECV_RKEY
, 4, ENC_BIG_ENDIAN
);
1223 proto_tree_add_item(rbuf_tree
, hf_irdmaep_raddr
, tvb
,
1224 IRDMA_EP_USERRECV_RADDR
, 8, ENC_BIG_ENDIAN
);
1226 dissect_irdmaep_data(tvb_new_subset_remaining(tvb
, IRDMA_EP_USERRECV_MSG_LEN
),
1227 pinfo
, tree
, &pdata
);
1231 dissect_user_send_msg(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
1232 irdmaep_analysis_t
*epd
, proto_tree
*ep_tree
)
1235 irdmaep_packet_analysis_t
*eppd
= NULL
;
1236 uint32_t recvid
, offset
, block_length
, total_length
;
1238 proto_tree_add_item_ret_uint(ep_tree
, hf_irdmaep_ulength
, tvb
,
1239 IRDMA_EP_USERSEND_ULENGTH
, 4, ENC_BIG_ENDIAN
,
1241 ti_ofs
= proto_tree_add_item_ret_uint(ep_tree
, hf_irdmaep_offset
, tvb
,
1242 IRDMA_EP_USERSEND_OFFSET
, 4, ENC_BIG_ENDIAN
,
1244 proto_tree_add_item_ret_uint(ep_tree
, hf_irdmaep_blength
, tvb
,
1245 IRDMA_EP_USERSEND_SLENGTH
, 4, ENC_BIG_ENDIAN
,
1247 proto_tree_add_item_ret_uint(ep_tree
, hf_irdmaep_recvid
, tvb
,
1248 IRDMA_EP_USERSEND_RECVID
, 2, ENC_BIG_ENDIAN
,
1251 /* Update flow analysis only on first (in-order) pass */
1252 if (!PINFO_FD_VISITED(pinfo
))
1254 if (epd
->fwd_flow
->recvack_valid
)
1256 uint16_t nextid
= epd
->fwd_flow
->recvack_id
+ 1;
1258 if ((recvid
== epd
->fwd_flow
->recvack_id
&& offset
== epd
->fwd_flow
->recvack_offset
)
1259 || (recvid
== nextid
&& offset
== 0))
1261 /* Expected ID, offset */
1265 /* Unexpected offset */
1266 eppd
= (irdmaep_packet_analysis_t
*) get_or_add_eppd(pinfo
);
1267 if (recvid
== epd
->fwd_flow
->recvack_id
1268 && offset
< epd
->fwd_flow
->recvack_offset
)
1269 eppd
->retransmission
= 1;
1271 eppd
->out_of_order
= 1; /* Should never occur! */
1275 epd
->fwd_flow
->recvack_valid
= 1;
1276 epd
->fwd_flow
->recvack_id
= recvid
;
1277 epd
->fwd_flow
->recvack_offset
= offset
+ block_length
;
1280 eppd
= (irdmaep_packet_analysis_t
*) get_eppd(pinfo
);
1284 if (eppd
->retransmission
)
1286 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
, "[Retransmission] ");
1287 expert_add_info(pinfo
, ti_ofs
, &ei_irdmaep_analysis_dup
);
1290 if (eppd
->out_of_order
)
1292 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
, "[Out-of-order] ");
1293 expert_add_info(pinfo
, ti_ofs
, &ei_irdmaep_analysis_oos
);
1297 irdmaep_pdata_t pdata
= {IRDMAEP_USERRDMA_TYPE
, offset
};
1298 dissect_irdmaep_data(tvb_new_subset_remaining(tvb
, IRDMA_EP_USERSEND_MSG_LEN
),
1299 pinfo
, tree
, &pdata
);
1303 dissect_connect_msg(tvbuff_t
*tvb
, packet_info
*pinfo _U_
,
1304 irdmaep_analysis_t
*epd _U_
, proto_tree
*ep_tree
)
1309 ti
= proto_tree_add_item_ret_uint(ep_tree
, hf_irdmaep_sndbufsize
, tvb
,
1310 IRDMA_EP_CONNECT_BUFSIZE
, 2,
1311 ENC_BIG_ENDIAN
, &bufsize
);
1312 proto_item_append_text(ti
, " (%u KB)", bufsize
* 4);
1314 uint8_t msg_type
= tvb_get_uint8(tvb
, IRDMA_EP_TYPE
);
1315 if (msg_type
== IRDMA_EP_CONNREQ
1316 || msg_type
== IRDMA_EP_CONNACK
)
1318 ti
= proto_tree_add_item_ret_uint(ep_tree
, hf_irdmaep_usrblksize
, tvb
,
1319 IRDMA_EP_CONNECT_USRBLKSIZE
, 2,
1320 ENC_BIG_ENDIAN
, &bufsize
);
1321 proto_item_append_text(ti
, " (%u KB)", bufsize
* 4);
1326 dissect_close_msg(tvbuff_t
*tvb
, packet_info
*pinfo _U_
,
1327 irdmaep_analysis_t
*epd _U_
, proto_tree
*ep_tree
)
1329 proto_tree_add_item(ep_tree
, hf_irdmaep_reason
, tvb
,
1330 IRDMA_EP_CLOSE_REASON
, 4, ENC_BIG_ENDIAN
);
1334 dissect_buffer_msg_mkeyaddr(tvbuff_t
*tvb
, packet_info
*pinfo _U_
,
1335 irdmaep_analysis_t
*epd _U_
, proto_tree
*ep_tree
)
1338 proto_tree
*rbuf_tree
;
1340 ti
= proto_tree_add_item(ep_tree
, hf_irdmaep_rbuf
, tvb
,
1341 IRDMA_EP_BUFFER_RKEY
, 24, ENC_NA
);
1342 rbuf_tree
= proto_item_add_subtree(ti
, ett_irdmaep_rbuf
);
1343 proto_tree_add_item(rbuf_tree
, hf_irdmaep_rkey
, tvb
,
1344 IRDMA_EP_BUFFER_RKEY
, 4, ENC_BIG_ENDIAN
);
1345 proto_tree_add_item(rbuf_tree
, hf_irdmaep_raddr
, tvb
,
1346 IRDMA_EP_BUFFER_RADDR
, 8, ENC_BIG_ENDIAN
);
1347 proto_tree_add_item(rbuf_tree
, hf_irdmaep_rkey
, tvb
,
1348 IRDMA_EP_BUFFER_RKEY
+ 4, 4, ENC_BIG_ENDIAN
);
1349 proto_tree_add_item(rbuf_tree
, hf_irdmaep_raddr
, tvb
,
1350 IRDMA_EP_BUFFER_RADDR
+ 8, 8, ENC_BIG_ENDIAN
);
1354 dissect_buffer_msg(tvbuff_t
*tvb
, packet_info
*pinfo
,
1355 irdmaep_analysis_t
*epd
, proto_tree
*ep_tree
)
1359 dissect_buffer_msg_mkeyaddr(tvb
, pinfo
, epd
, ep_tree
);
1361 proto_tree_add_item_ret_uint(ep_tree
, hf_irdmaep_rcvbufsize
, tvb
,
1362 IRDMA_EP_BUFFER_RBUFSIZE
, 2, ENC_BIG_ENDIAN
,
1366 /* Update receive buffer analysis only on first (in-order) pass */
1367 if (!PINFO_FD_VISITED(pinfo
))
1369 if (tvb_get_uint32(tvb
, IRDMA_EP_BUFFER_RKEY
, ENC_BIG_ENDIAN
))
1371 memset(&epd
->rev_flow
->recv_buffer
[0], 0,
1372 sizeof epd
->rev_flow
->recv_buffer
[0]);
1373 epd
->rev_flow
->recv_buffer
[0].size
= rbufsize
;
1374 if (epd
->rev_flow
->recv_buffer_count
< 1)
1375 epd
->rev_flow
->recv_buffer_count
= 1;
1378 if (tvb_get_uint32(tvb
, IRDMA_EP_BUFFER_RKEY
+ 4, ENC_BIG_ENDIAN
))
1380 memset(&epd
->rev_flow
->recv_buffer
[1], 0,
1381 sizeof epd
->rev_flow
->recv_buffer
[1]);
1382 epd
->rev_flow
->recv_buffer
[1].size
= rbufsize
;
1383 if (epd
->rev_flow
->recv_buffer_count
< 2)
1384 epd
->rev_flow
->recv_buffer_count
= 2;
1390 dissect_move_link_msg(tvbuff_t
*tvb
, packet_info
*pinfo
,
1391 irdmaep_analysis_t
*epd
, proto_tree
*ep_tree
)
1393 dissect_buffer_msg_mkeyaddr(tvb
, pinfo
, epd
, ep_tree
);
1396 proto_tree
*flags_tree
;
1399 ti
= proto_tree_add_item(ep_tree
, hf_irdmaep_flags
, tvb
,
1400 IRDMA_EP_BUFFER_FLAGS
, 1, ENC_NA
);
1401 flags_tree
= proto_item_add_subtree(ti
, ett_irdmaep_bufflags
);
1402 proto_tree_add_item(flags_tree
, hf_irdmaep_flag_buf0_free
, tvb
,
1403 IRDMA_EP_BUFFER_FLAGS
, 1, ENC_NA
);
1404 proto_tree_add_item(flags_tree
, hf_irdmaep_flag_buf1_free
, tvb
,
1405 IRDMA_EP_BUFFER_FLAGS
, 1, ENC_NA
);
1406 proto_tree_add_item_ret_uint(ep_tree
, hf_irdmaep_rcvbufsize
, tvb
,
1407 IRDMA_EP_BUFFER_RBUFSIZE
, 2, ENC_BIG_ENDIAN
,
1410 proto_tree_add_item(ep_tree
, hf_irdmaep_sendseq
, tvb
,
1411 IRDMA_EP_MOVELINK_SENDSEQ
, 2, ENC_BIG_ENDIAN
);
1412 proto_tree_add_item(ep_tree
, hf_irdmaep_recvseq0
, tvb
,
1413 IRDMA_EP_MOVELINK_RBUFSEQ
, 2, ENC_BIG_ENDIAN
);
1414 proto_tree_add_item(ep_tree
, hf_irdmaep_recvseq1
, tvb
,
1415 IRDMA_EP_MOVELINK_RBUFSEQ
+ 2, 2, ENC_BIG_ENDIAN
);
1416 proto_tree_add_item(ep_tree
, hf_irdmaep_usndsent
, tvb
,
1417 IRDMA_EP_MOVELINK_USNDSENT
, 4, ENC_BIG_ENDIAN
);
1418 proto_tree_add_item(ep_tree
, hf_irdmaep_usndid
, tvb
,
1419 IRDMA_EP_MOVELINK_USNDID
, 2, ENC_BIG_ENDIAN
);
1421 /* Update receive buffer analysis only on first (in-order) pass */
1422 if (!PINFO_FD_VISITED(pinfo
))
1424 if (tvb_get_uint32(tvb
, IRDMA_EP_BUFFER_RKEY
, ENC_BIG_ENDIAN
)
1425 && (rbufsize
& 0x8000))
1427 memset(&epd
->rev_flow
->recv_buffer
[0], 0,
1428 sizeof epd
->rev_flow
->recv_buffer
[0]);
1429 epd
->rev_flow
->recv_buffer
[0].size
= (rbufsize
& 0xFFF) * 4096;
1432 if (tvb_get_uint32(tvb
, IRDMA_EP_BUFFER_RKEY
+ 4, ENC_BIG_ENDIAN
)
1433 && (rbufsize
& 0x4000))
1435 memset(&epd
->rev_flow
->recv_buffer
[1], 0,
1436 sizeof epd
->rev_flow
->recv_buffer
[1]);
1437 epd
->rev_flow
->recv_buffer
[1].size
= (rbufsize
& 0xFFF) * 4096;
1443 dissect_move_link_ack_msg(tvbuff_t
*tvb
, packet_info
*pinfo
,
1444 irdmaep_analysis_t
*epd
, proto_tree
*ep_tree
)
1447 irdmaep_packet_analysis_t
*eppd
= NULL
;
1449 if (!PINFO_FD_VISITED(pinfo
))
1451 eppd
= (irdmaep_packet_analysis_t
*) get_or_add_eppd(pinfo
);
1453 nstime_delta(&eppd
->movelink_time
, &pinfo
->abs_ts
, &epd
->movereq_time
);
1456 eppd
= (irdmaep_packet_analysis_t
*) get_eppd(pinfo
);
1458 dissect_move_link_msg(tvb
, pinfo
, epd
, ep_tree
);
1460 proto_tree_add_item(ep_tree
, hf_irdmaep_urcvid
, tvb
,
1461 IRDMA_EP_MOVELINKACK_URCVID
, 2, ENC_BIG_ENDIAN
);
1463 ti
= proto_tree_add_time(ep_tree
, hf_irdmaep_move1
, tvb
,
1464 IRDMA_EP_TYPE
, 0, &eppd
->movelink_time
);
1465 PROTO_ITEM_SET_GENERATED(ti
);
1469 dissect_move_link_cmp_msg(tvbuff_t
*tvb
, packet_info
*pinfo
,
1470 irdmaep_analysis_t
*epd
, proto_tree
*ep_tree
)
1473 irdmaep_packet_analysis_t
*eppd
= NULL
;
1475 if (!PINFO_FD_VISITED(pinfo
))
1477 eppd
= (irdmaep_packet_analysis_t
*) get_or_add_eppd(pinfo
);
1479 nstime_delta(&eppd
->movelink_time
, &pinfo
->abs_ts
, &epd
->movereq_time
);
1482 eppd
= (irdmaep_packet_analysis_t
*) get_eppd(pinfo
);
1484 proto_tree_add_item(ep_tree
, hf_irdmaep_urcvid
, tvb
,
1485 IRDMA_EP_MOVELINKCMP_URCVID
, 2, ENC_BIG_ENDIAN
);
1487 ti
= proto_tree_add_time(ep_tree
, hf_irdmaep_move2
, tvb
,
1488 IRDMA_EP_TYPE
, 0, &eppd
->movelink_time
);
1489 PROTO_ITEM_SET_GENERATED(ti
);
1493 dissect_irdmaep_data(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
1494 irdmaep_pdata_t
*pdata
)
1496 irdmaep_packet_analysis_t
*eppd
= NULL
;
1498 /* Should we try to call subdissector based on port? */
1499 if (!irdmaep_no_subdissector_on_error
1500 || !(eppd
= (irdmaep_packet_analysis_t
*) get_eppd(pinfo
))
1501 || !eppd
->retransmission
)
1503 uint32_t low_port
, high_port
;
1505 if (pinfo
->srcport
< pinfo
->destport
)
1507 low_port
= pinfo
->srcport
;
1508 high_port
= pinfo
->destport
;
1512 low_port
= pinfo
->destport
;
1513 high_port
= pinfo
->srcport
;
1516 if (dissector_try_uint_with_data(irdmaep_dissector_table
, low_port
,
1517 tvb
, pinfo
, tree
, true, pdata
))
1520 if (dissector_try_uint_with_data(irdmaep_dissector_table
, high_port
,
1521 tvb
, pinfo
, tree
, true, pdata
))
1525 /* If no subdissector (or error and skipped calling), just dissect as data */
1526 call_data_dissector(tvb
, pinfo
, tree
);
1529 static irdmaep_analysis_t
*
1530 init_irdmaep_conversation_data(packet_info
*pinfo
)
1532 irdmaep_analysis_t
*epd
1533 = wmem_new0(wmem_file_scope(), irdmaep_analysis_t
);
1535 epd
->stream
= irdmaep_stream_count
++;
1538 nstime_copy(&epd
->ts_first
, &pinfo
->abs_ts
);
1539 nstime_copy(&epd
->ts_prev
, &pinfo
->abs_ts
);
1545 get_eppd(packet_info
*pinfo
)
1547 return p_get_proto_data(wmem_file_scope(), pinfo
, proto_irdmaep
,
1548 pinfo
->curr_layer_num
);
1552 add_eppd(packet_info
*pinfo
)
1554 irdmaep_packet_analysis_t
*eppd
1555 = wmem_new0(wmem_file_scope(), irdmaep_packet_analysis_t
);
1556 p_add_proto_data(wmem_file_scope(), pinfo
, proto_irdmaep
,
1557 pinfo
->curr_layer_num
, eppd
);
1559 nstime_set_unset(&eppd
->delta_time
);
1564 get_or_add_eppd(packet_info
*pinfo
)
1566 irdmaep_packet_analysis_t
*eppd
= (irdmaep_packet_analysis_t
*) get_eppd(pinfo
);
1568 eppd
= (irdmaep_packet_analysis_t
*) add_eppd(pinfo
);
1574 analyze_irdmaep_rbuffer(irdmaep_flow_t
*flow
,
1575 irdmaep_packet_analysis_t
*eppd
)
1577 uint32_t bufid
= flow
->recv_mrb
;
1579 /* Start by getting available space in the current receive
1581 if (flow
->recv_buffer
[bufid
].size
)
1582 eppd
->rbuf_available
1585 = flow
->recv_buffer
[bufid
].size
1586 - flow
->recv_buffer
[bufid
].offset
;
1589 eppd
->rbuf_available
1592 = flow
->recv_min_size
1593 - flow
->recv_buffer
[bufid
].offset
;
1594 eppd
->rbuf_estimated
= 1;
1597 /* If there's a second receive buffer and it's empty, include
1598 it in receive buffer analysis */
1599 if (++bufid
== IRDMAEP_MAX_DATA_BUFID
)
1601 if (flow
->recv_buffer_count
> 1
1602 && !flow
->recv_buffer
[bufid
].indeterminate
1603 && flow
->recv_buffer
[bufid
].offset
== 0)
1605 uint32_t size
= flow
->recv_buffer
[bufid
].size
1606 ? flow
->recv_buffer
[bufid
].size
1607 : flow
->recv_min_size
;
1608 eppd
->rbuf_available
+= size
;
1609 if (size
> eppd
->rbuf_max
)
1610 eppd
->rbuf_max
= size
;
1614 /*********************************************************************/
1615 /*********************************************************************/
1616 /* Dissector registration functions */
1617 /*********************************************************************/
1618 /*********************************************************************/
1620 /* Register the protocol with Wireshark */
1622 proto_register_irdma(void)
1624 module_t
*irdmaep_module
;
1625 expert_module_t
*expert_irdmaep
;
1627 /*****************************************************************/
1628 /* RDMA pseudo-header field definitions */
1629 /*****************************************************************/
1630 static hf_register_info hf
[] = {
1632 { "Destination", "irdma.dst",
1633 FT_ETHER
, BASE_NONE
, NULL
, 0x0,
1634 "Destination Hardware Address", HFILL
}},
1636 { "Source", "irdma.src",
1637 FT_ETHER
, BASE_NONE
, NULL
, 0x0,
1638 "Source Hardware Address", HFILL
}},
1639 { &hf_irdma_qpindex
,
1640 { "QP#", "irdma.qpidx",
1641 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1642 "QP Index", HFILL
}},
1644 { "Source IP", "irdma.ipv6.src",
1645 FT_IPv6
, BASE_NONE
, NULL
, 0x0,
1646 "Source IP Address", HFILL
}},
1648 { "Destination IP", "irdma.ipv6.dst",
1649 FT_IPv6
, BASE_NONE
, NULL
, 0x0,
1650 "Destination IP Address", HFILL
}},
1652 { "Source IP", "irdma.ipv4.src",
1653 FT_IPv4
, BASE_NONE
, NULL
, 0x0,
1654 "Source IP Address", HFILL
}},
1656 { "Destination IP", "irdma.ipv4.dst",
1657 FT_IPv4
, BASE_NONE
, NULL
, 0x0,
1658 "Destination IP Address", HFILL
}},
1660 { "Address", "irdma.addr",
1661 FT_ETHER
, BASE_NONE
, NULL
, 0x0,
1662 "Source or Destination Hardware Address", HFILL
}},
1663 { &hf_irdma_ip6addr
,
1664 { "IP Address", "irdma.ipv6.addr",
1665 FT_IPv6
, BASE_NONE
, NULL
, 0x0,
1666 "Source or Destination IPv6 Address", HFILL
}},
1667 { &hf_irdma_ip4addr
,
1668 { "IP Address", "irdma.ipv4.addr",
1669 FT_IPv4
, BASE_NONE
, NULL
, 0x0,
1670 "Source or Destination IPv4 Address", HFILL
}}
1673 /*****************************************************************/
1674 /* RDMA QP field definitions */
1675 /*****************************************************************/
1676 static hf_register_info hfqp
[] = {
1678 { "Type", "irdma.qp.type",
1679 FT_UINT16
, BASE_HEX
, VALS(irdmaqp_type_str
), 0x0,
1680 "RDMA QP Message Type", HFILL
}},
1682 { "Identifier", "irdma.qp.echo.id",
1683 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1684 "RDMA QP Echo Identifier", HFILL
}}
1687 /*****************************************************************/
1688 /* RDMA Link field definitions */
1689 /*****************************************************************/
1690 static hf_register_info hflink
[] = {
1691 { &hf_irdmalink_type
,
1692 { "Type", "irdma.link.type",
1693 FT_UINT16
, BASE_HEX
, VALS(irdmalink_type_str
), 0x0,
1694 "RDMA Link Message Type", HFILL
}},
1695 { &hf_irdmalink_groups
,
1696 { "Groups", "irdma.link.status.groups",
1697 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1698 "RDMA Link Status Active Group Count", HFILL
}}
1701 /*****************************************************************/
1702 /* RDMA Endpoint field definitions */
1703 /*****************************************************************/
1704 static hf_register_info hfep
[] = {
1706 { "Type", "irdma.ep.type",
1707 FT_UINT8
, BASE_DEC_HEX
, VALS(irdmaep_type_str
), 0x0,
1708 "RDMA Endpoint Message Type", HFILL
}},
1710 { "Length", "irdma.ep.len",
1711 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1712 "RDMA Endpoint Message Length", HFILL
}},
1713 { &hf_irdmaep_grpid
,
1714 { "Group ID", "irdma.ep.grpid",
1715 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1716 "RDMA Endpoint Group Identifier", HFILL
}},
1717 { &hf_irdmaep_grpid_ctr
,
1718 { "Counter", "irdma.ep.grpid.counter",
1719 FT_UINT8
, BASE_HEX_DEC
, NULL
, 0x0,
1720 "RDMA Endpoint Group Identifier Uniqueness Counter", HFILL
}},
1721 { &hf_irdmaep_grpid_time
,
1722 { "Time Generated", "irdma.ep.grpid.time",
1723 FT_UINT48
, BASE_HEX_DEC
, NULL
, 0x0,
1724 "RDMA Endpoint Group Identifier Timestamp", HFILL
}},
1725 { &hf_irdmaep_grpid_hwaddr
,
1726 { "Hardware Address", "irdma.ep.grpid.hwaddr",
1727 FT_ETHER
, BASE_NONE
, NULL
, 0x0,
1728 "RDMA Endpoint Group Identifier Hardware Address", HFILL
}},
1729 { &hf_irdmaep_srcport
,
1730 { "Source Port", "irdma.ep.srcport",
1731 FT_UINT16
, BASE_CUSTOM
, CF_FUNC(irdma_custom_format_port
), 0x0,
1732 "RDMA Endpoint Source Port", HFILL
}},
1733 { &hf_irdmaep_dstport
,
1734 { "Destination Port", "irdma.ep.dstport",
1735 FT_UINT16
, BASE_CUSTOM
, CF_FUNC(irdma_custom_format_port
), 0x0,
1736 "RDMA Endpoint Destination Port", HFILL
}},
1738 { "Source or Destination Port", "irdma.ep.port",
1739 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1740 "RDMA Endpoint Source or Destination Port", HFILL
}},
1741 { &hf_irdmaep_stream
,
1742 { "Stream index", "irdma.ep.stream",
1743 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1744 "RDMA Endpoint Stream Index", HFILL
}},
1745 { &hf_irdmaep_linkseq
,
1746 { "Link Sequence", "irdma.ep.linkseq",
1747 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1748 "RDMA Endpoint Link Switch Sequence", HFILL
}},
1749 { &hf_irdmaep_sndbufsize
,
1750 { "Send Buffer Size", "irdma.ep.sndbufsize",
1751 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1752 "RDMA Endpoint Send Buffer Size", HFILL
}},
1753 { &hf_irdmaep_usrblksize
,
1754 { "User Block Size", "irdma.ep.usrblksize",
1755 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1756 "RDMA Endpoint USER_RDMA Block Size", HFILL
}},
1757 { &hf_irdmaep_reason
,
1758 { "Reason", "irdma.ep.reason",
1759 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0, /* TODO - Add Strings for reason? */
1760 "RDMA Endpoint Close Reason", HFILL
}},
1762 { "Remote Memory", "irdma.ep.rbuf",
1763 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1764 "RDMA Endpoint Remote Memory Key/Address", HFILL
}},
1766 { "Remote Memory Key", "irdma.ep.rbuf.key",
1767 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
1768 "RDMA Endpoint Remote Memory Key", HFILL
}},
1769 { &hf_irdmaep_raddr
,
1770 { "Remote Memory Address", "irdma.ep.rbuf.addr",
1771 FT_UINT64
, BASE_HEX
, NULL
, 0x0,
1772 "RDMA Endpoint Remote Memory Address", HFILL
}},
1773 { &hf_irdmaep_flags
,
1774 { "Flags", "irdma.ep.buffer.flags",
1775 FT_UINT8
, BASE_HEX
, NULL
, 0xF0,
1776 "RDMA Endpoint Buffer Flags", HFILL
}},
1777 { &hf_irdmaep_flag_buf0_free
,
1778 { "Buffer #0", "irdma.ep.buffer.flags.buf0",
1779 FT_UINT8
, 1, VALS(vals_free_inuse
), 0x80,
1780 "RDMA Endpoint Buffer 0 Free Flag", HFILL
}},
1781 { &hf_irdmaep_flag_buf1_free
,
1782 { "Buffer #1", "irdma.ep.buffer.flags.buf1",
1783 FT_UINT8
, 1, VALS(vals_free_inuse
), 0x40,
1784 "RDMA Endpoint Buffer 1 Free Flag", HFILL
}},
1785 { &hf_irdmaep_rcvbufsize
,
1786 { "Receive Buffer Size", "irdma.ep.rcvbufsize",
1787 FT_UINT16
, BASE_CUSTOM
, CF_FUNC(irdma_custom_format_rbufsize
), 0x0,
1788 "RDMA Endpoint Receive Buffer Size", HFILL
}},
1789 { &hf_irdmaep_sendseq
,
1790 { "Last Send Sequence", "irdma.ep.sendseq",
1791 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
1792 "RDMA Endpoint Last Successful Data Sequence Number", HFILL
}},
1793 { &hf_irdmaep_recvseq0
,
1794 { "Last Received Sequence (Buffer #0)", "irdma.ep.recvseq0",
1795 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
1796 "RDMA Endpoint Last Received Data Sequence Number", HFILL
}},
1797 { &hf_irdmaep_recvseq1
,
1798 { "Last Received Sequence (Buffer #1)", "irdma.ep.recvseq1",
1799 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
1800 "RDMA Endpoint Last Received Data Sequence Number", HFILL
}},
1801 { &hf_irdmaep_usndsent
,
1802 { "USER_RDMA Bytes Sent", "irdma.ep.usndsent",
1803 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0,
1804 "RDMA Endpoint Bytes Sent From Current USER_RDMA Transfer", HFILL
}},
1805 { &hf_irdmaep_usndid
,
1806 { "USER_RDMA Send Identifier", "irdma.ep.usndid",
1807 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
1808 "RDMA Endpoint Current USER_RDMA Send Identifier", HFILL
}},
1809 { &hf_irdmaep_urcvid
,
1810 { "USER_RDMA Receive Identifier Complete", "irdma.ep.urcvid",
1811 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
1812 "RDMA Endpoint Last USER_RDMA Receive Identifier Completed", HFILL
}},
1813 { &hf_irdmaep_seqnum
,
1814 { "Send Sequence", "irdma.ep.seqnum",
1815 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
1816 "RDMA Endpoint Data Sequence Number", HFILL
}},
1817 { &hf_irdmaep_bufid
,
1818 { "Buffer Identifier", "irdma.ep.bufid",
1819 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1820 "RDMA Endpoint Buffer Identifier", HFILL
}},
1821 { &hf_irdmaep_offset
,
1822 { "Buffer Offset", "irdma.ep.offset",
1823 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0,
1824 "RDMA Endpoint Buffer Offset", HFILL
}},
1825 { &hf_irdmaep_datalen
,
1826 { "Length", "irdma.ep.length",
1827 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0,
1828 "RDMA Endpoint Data Length", HFILL
}},
1829 { &hf_irdmaep_ulength
,
1830 { "USER_RDMA Length", "irdma.ep.ulength",
1831 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0,
1832 "RDMA Endpoint USER_RDMA Total Length", HFILL
}},
1833 { &hf_irdmaep_blength
,
1834 { "USER_RDMA Block Length", "irdma.ep.blength",
1835 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0,
1836 "RDMA Endpoint USER_RDMA Block Length", HFILL
}},
1837 { &hf_irdmaep_recvid
,
1838 { "USER_RDMA Receive Identifier", "irdma.ep.recvid",
1839 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
1840 "RDMA Endpoint USER_RDMA Receive Identifier", HFILL
}},
1841 { &hf_irdmaep_rbufavail
,
1842 { "Receive Buffer Available", "irdma.ep.analysis.rcvbuf",
1843 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0,
1844 "RDMA Receive Buffer Bytes Available", HFILL
}},
1845 { &hf_irdmaep_rbufactive
,
1846 { "Active Receive Buffer Available", "irdma.ep.analysis.rcvbuf.active",
1847 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0,
1848 "RDMA Active Receive Buffer Bytes Available", HFILL
}},
1849 { &hf_irdmaep_rbufmax
,
1850 { "Maximum Receive Buffer Available", "irdma.ep.analysis.rcvbuf.max",
1851 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0,
1852 "RDMA Maximum Receive Buffer Bytes Available", HFILL
}},
1853 { &hf_irdmaep_move1
,
1854 { "Server link switch time", "irdma.ep.analysis.linkswt.server",
1855 FT_RELATIVE_TIME
, BASE_NONE
, NULL
, 0x0,
1856 "RDMA server link switch time", HFILL
}},
1857 { &hf_irdmaep_move2
,
1858 { "Link switch time", "irdma.ep.analysis.linkswt",
1859 FT_RELATIVE_TIME
, BASE_NONE
, NULL
, 0x0,
1860 "RDMA link switch time", HFILL
}},
1861 { &hf_irdmaep_ts_relative
,
1862 { "Time since first frame in this RDMA stream", "irdma.ep.time_relative",
1863 FT_RELATIVE_TIME
, BASE_NONE
, NULL
, 0x0,
1864 "Time relative to first frame in this RDMA stream", HFILL
}},
1865 { &hf_irdmaep_ts_delta
,
1866 { "Time since previous frame in this RDMA stream", "irdma.ep.time_delta",
1867 FT_RELATIVE_TIME
, BASE_NONE
, NULL
, 0x0,
1868 "Time delta from previous frame in this RDMA stream", HFILL
}}
1871 /*****************************************************************/
1872 /* Protocol subtree array */
1873 /*****************************************************************/
1874 static int *ett
[] = {
1881 &ett_irdmaep_bufflags
,
1882 &ett_irdmaep_rcvbuf_analyze
,
1883 &ett_irdmaep_timestamps
1886 /* Setup protocol expert items */
1887 static ei_register_info ei
[] = {
1888 { &ei_irdmaep_analysis_stale
,
1889 { "irdma.ep.analysis.stale", PI_SEQUENCE
, PI_NOTE
,
1890 "Packet received from prior link", EXPFILL
}},
1891 { &ei_irdmaep_analysis_dup
,
1892 { "irdma.ep.analysis.dup", PI_SEQUENCE
, PI_CHAT
,
1893 "Duplicate data packet (retransmission)", EXPFILL
}},
1894 { &ei_irdmaep_analysis_oos
,
1895 { "irdma.ep.analysis.oos", PI_SEQUENCE
, PI_ERROR
,
1896 "Out of order data packet", EXPFILL
}},
1897 { &ei_irdmaep_connection_req
,
1898 { "irdma.ep.connection.req", PI_SEQUENCE
, PI_CHAT
,
1899 "Connection request (CONNREQ)", EXPFILL
}},
1900 { &ei_irdmaep_connection_ack
,
1901 { "irdma.ep.connection.ack", PI_SEQUENCE
, PI_CHAT
,
1902 "Connection acknowledgement (CONNACK)", EXPFILL
}},
1903 { &ei_irdmaep_connection_lswt
,
1904 { "irdma.ep.connection.linkswt", PI_SEQUENCE
, PI_NOTE
,
1905 "Link switch", EXPFILL
}}
1908 /*****************************************************************/
1909 /* Register the protocols */
1910 /*****************************************************************/
1911 proto_irdma
= proto_register_protocol("IBM i RDMA", "iRDMA", "irdma");
1912 proto_irdmaqp
= proto_register_protocol("IBM i RDMA QP", "iRDMA-QP", "irdma.qp");
1913 proto_irdmalink
= proto_register_protocol("IBM i RDMA Link", "iRDMA-Link", "irdma.link");
1914 proto_irdmaep
= proto_register_protocol("IBM i RDMA Endpoint", "iRDMA-EP", "irdma.ep");
1916 register_init_routine(irdma_init
);
1918 /* Required function calls to register the header fields and subtrees */
1919 proto_register_field_array(proto_irdma
, hf
, array_length(hf
));
1920 proto_register_field_array(proto_irdmaqp
, hfqp
, array_length(hfqp
));
1921 proto_register_field_array(proto_irdmalink
, hflink
, array_length(hflink
));
1922 proto_register_field_array(proto_irdmaep
, hfep
, array_length(hfep
));
1924 proto_register_subtree_array(ett
, array_length(ett
));
1926 // Register a dissector table to allow sub-dissectors to register based on EP port
1927 irdmaep_dissector_table
1928 = register_dissector_table("irdma.ep.port", "RDMA EP Port", proto_irdmaep
, FT_UINT16
, BASE_DEC
);
1930 /* Required function calls to register expert items */
1931 expert_irdmaep
= expert_register_protocol(proto_irdmaep
);
1932 expert_register_field_array(expert_irdmaep
, ei
, array_length(ei
));
1934 /* Register a preferences module (see section 2.6 of README.dissector
1935 * for more details). Registration of a prefs callback is not required
1936 * if there are no preferences that affect protocol registration (an example
1937 * of a preference that would affect registration is a port preference).
1938 * If the prefs callback is not needed, use NULL instead of
1939 * proto_reg_handoff_irdma in the following.
1941 prefs_register_protocol(proto_irdma
, proto_reg_handoff_irdma
);
1942 irdmaep_module
= prefs_register_protocol(proto_irdmaep
, NULL
);
1943 prefs_register_bool_preference(irdmaep_module
, "calculate_timestamps",
1944 "Calculate conversation timestamps",
1945 "Calculate timestamps relative to the first frame and the previous frame in the RDMA conversation",
1946 &irdmaep_calculate_ts
);
1947 prefs_register_bool_preference(irdmaep_module
, "no_subdissector_on_error",
1948 "Do not call subdissectors for error packets",
1949 "Do not call any subdissectors for retransmitted segments",
1950 &irdmaep_no_subdissector_on_error
);
1952 register_dissector("irdma", dissect_irdma
, proto_irdma
);
1955 /* Simpler form of proto_reg_handoff_irdma which can be used if there are
1956 * no prefs-dependent registration function calls. */
1958 proto_reg_handoff_irdma(void)
1960 /* Use create_dissector_handle() to get the handles to IBM i RDMA
1963 irdmaqp_handle
= create_dissector_handle(dissect_irdmaqp
, proto_irdmaqp
);
1964 irdmalink_handle
= create_dissector_handle(dissect_irdmalink
, proto_irdmalink
);
1965 irdmaep_handle
= create_dissector_handle(dissect_irdmaep
, proto_irdmaep
);
1969 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1974 * indent-tabs-mode: nil
1977 * vi: set shiftwidth=4 tabstop=8 expandtab:
1978 * :indentSize=4:tabSize=8:noTabs=true: