aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-rpcrdma.c
diff options
context:
space:
mode:
authorJorge Mora <jmora1300@gmail.com>2022-03-10 07:22:59 -0700
committerA Wireshark GitLab Utility <gerald+gitlab-utility@wireshark.org>2022-03-16 05:33:46 +0000
commit746b46a16a94956c41ca2db89a25f9407da856f1 (patch)
tree8e395502bedaec81687d9b3b0aa175d6388864e6 /epan/dissectors/packet-rpcrdma.c
parent4cc8e0921363eca99d10f0c240bf85b67a470b78 (diff)
RPCoRDMA: add iWarp send reassembly
Add global variable gp_rdmap_info to point to the data parameter given by parent dissector IWARP_DDP_RDMAP. Add binary tree, msn_list, to add send_info_t struct using the message sequence number of an untagged message as the key. Modify function add_send_fragment() to include iWarp segments. Message numbers are given by the untagged message offset, thus the msgno of send_info_t is not used and it is set to 0. Since message offsets are not consecutive for iWarp, verify there are no missing fragments by checking the number of bytes added to the reassembly table. Also, remove function rpcrdma_initialize() Related to #17963.
Diffstat (limited to 'epan/dissectors/packet-rpcrdma.c')
-rw-r--r--epan/dissectors/packet-rpcrdma.c90
1 files changed, 61 insertions, 29 deletions
diff --git a/epan/dissectors/packet-rpcrdma.c b/epan/dissectors/packet-rpcrdma.c
index 68410db369..cbfe815a69 100644
--- a/epan/dissectors/packet-rpcrdma.c
+++ b/epan/dissectors/packet-rpcrdma.c
@@ -152,11 +152,6 @@ static const value_string rpcordma_err[] = {
{0, NULL}
};
-typedef enum {
- INFINIBAND, /* RPC-over-RDMA on InfiniBand */
- IWARP /* RPC-over-RDMA on iWARP */
-} rpcrdma_type_t;
-
/* RDMA chunk type */
typedef enum {
RDMA_READ_CHUNK,
@@ -223,6 +218,7 @@ typedef struct {
wmem_tree_t *psn_list; /* Binary tree of IB requests searched by PSN */
wmem_tree_t *msgid_list; /* Binary tree of segments with same message id */
wmem_tree_t *send_list; /* Binary tree for mapping PSN -> msgid (IB) */
+ wmem_tree_t *msn_list; /* Binary tree for mapping MSN -> msgid (iWarp) */
segment_info_t *segment_info; /* Current READ/WRITE/REPLY segment info */
guint32 iosize; /* Maximum size of data transferred in a
single packet */
@@ -246,6 +242,9 @@ enum {
*/
static struct infinibandinfo *gp_infiniband_info = NULL;
+/* Global variable set for every iWarp packet */
+static rdmap_info_t *gp_rdmap_info = NULL;
+
/* Call process_reassembled_data just once per frame */
static gboolean g_needs_reassembly = FALSE;
@@ -303,6 +302,7 @@ static rdma_conv_info_t *get_rdma_conv_info(packet_info *pinfo)
p_rdma_conv_info->psn_list = wmem_tree_new(wmem_file_scope());
p_rdma_conv_info->msgid_list = wmem_tree_new(wmem_file_scope());
p_rdma_conv_info->send_list = wmem_tree_new(wmem_file_scope());
+ p_rdma_conv_info->msn_list = wmem_tree_new(wmem_file_scope());
p_rdma_conv_info->segment_info = NULL;
p_rdma_conv_info->iosize = 1;
conversation_add_proto_data(p_conversation, proto_rpcordma, p_rdma_conv_info);
@@ -488,11 +488,16 @@ static tvbuff_t *add_fragment(tvbuff_t *tvb, gint offset, guint32 msgid,
gint32 msg_num, gboolean more_frags, rdma_conv_info_t *p_rdma_conv_info,
packet_info *pinfo, proto_tree *tree)
{
+ guint8 pad_count = 0;
guint32 nbytes, frag_size;
tvbuff_t *new_tvb = NULL;
fragment_head *fd_head = NULL;
guint32 *p_msgid;
+ if (gp_infiniband_info) {
+ pad_count = gp_infiniband_info->pad_count;
+ }
+
/* Get fragment head if reassembly has been completed */
fd_head = get_fragment_head(pinfo);
if (fd_head == NULL) {
@@ -501,14 +506,14 @@ static tvbuff_t *add_fragment(tvbuff_t *tvb, gint offset, guint32 msgid,
nbytes = tvb_captured_length_remaining(tvb, offset);
if (nbytes > 0 || more_frags) {
/* Add message fragment to reassembly table */
- if (gp_infiniband_info->pad_count > 0 && p_rdma_conv_info != NULL && \
+ if (pad_count > 0 && p_rdma_conv_info && \
p_rdma_conv_info->segment_info != NULL && \
p_rdma_conv_info->segment_info->type == RDMA_READ_CHUNK && \
p_rdma_conv_info->segment_info->xdrpos == 0) {
/* Do not include any padding bytes inserted by Infiniband
* layer if this is a PZRC (Position-Zero Read Chunk) since
* payload stream already has any necessary padding bytes */
- frag_size = tvb_reported_length_remaining(tvb, offset) - gp_infiniband_info->pad_count;
+ frag_size = tvb_reported_length_remaining(tvb, offset) - pad_count;
if (frag_size < nbytes) {
nbytes = frag_size;
}
@@ -1271,16 +1276,25 @@ static tvbuff_t *add_send_fragment(rdma_conv_info_t *p_rdma_conv_info,
gint32 msgno = -1;
tvbuff_t *new_tvb = NULL;
gboolean first_frag = FALSE;
+ gboolean middle_frag = FALSE;
gboolean last_frag = FALSE;
send_info_t *p_send_info = NULL;
if (gp_infiniband_info) {
first_frag = gp_infiniband_info->opCode == RC_SEND_FIRST;
+ middle_frag = gp_infiniband_info->opCode == RC_SEND_MIDDLE;
last_frag = (gp_infiniband_info->opCode == RC_SEND_LAST || \
gp_infiniband_info->opCode == RC_SEND_LAST_INVAL);
+ } else if (gp_rdmap_info) {
+ first_frag = !gp_rdmap_info->last_flag && gp_rdmap_info->message_offset == 0;
+ middle_frag = !gp_rdmap_info->last_flag && gp_rdmap_info->message_offset > 0;
+ last_frag = gp_rdmap_info->last_flag && gp_rdmap_info->message_offset > 0;
}
- if (pinfo->fd->visited) {
+ if (!first_frag && !middle_frag && !last_frag) {
+ /* Only one SEND fragment, no need to reassemble */
+ return tvb;
+ } else if (pinfo->fd->visited) {
return get_reassembled_data(tvb, 0, pinfo, tree);
} else if (first_frag) {
/* Start of multi-SEND message */
@@ -1292,11 +1306,17 @@ static tvbuff_t *add_send_fragment(rdma_conv_info_t *p_rdma_conv_info,
/* Message numbers are relative with respect to current PSN */
p_send_info->msgno = gp_infiniband_info->packet_seq_num;
wmem_tree_insert32(p_rdma_conv_info->send_list, gp_infiniband_info->packet_seq_num, p_send_info);
+ } else if (gp_rdmap_info) {
+ /* Message numbers are given by the RDMAP offset -- msgno is not used */
+ p_send_info->msgno = 0;
+ wmem_tree_insert32(p_rdma_conv_info->msn_list, gp_rdmap_info->message_seq_num, p_send_info);
}
} else {
/* SEND fragment, get the send reassembly info structure */
if (gp_infiniband_info) {
p_send_info = wmem_tree_lookup32_le(p_rdma_conv_info->send_list, gp_infiniband_info->packet_seq_num);
+ } else if (gp_rdmap_info) {
+ p_send_info = wmem_tree_lookup32(p_rdma_conv_info->msn_list, gp_rdmap_info->message_seq_num);
}
}
if (p_send_info) {
@@ -1305,10 +1325,21 @@ static tvbuff_t *add_send_fragment(rdma_conv_info_t *p_rdma_conv_info,
if (gp_infiniband_info) {
/* Message numbers are consecutive starting at zero */
msgno = gp_infiniband_info->packet_seq_num - p_send_info->msgno;
+ } else if (gp_rdmap_info) {
+ /* Message numbers are given by the RDMAP offset */
+ msgno = gp_rdmap_info->message_offset;
}
}
if (msgid > 0 && msgno >= 0) {
new_tvb = add_fragment(tvb, 0, msgid, msgno, !last_frag, p_rdma_conv_info, pinfo, tree);
+ if (last_frag && !new_tvb && gp_rdmap_info) {
+ /* Since message numbers are not consecutive for iWarp,
+ * verify there are no missing fragments */
+ if (p_send_info->rsize == msgno + tvb_reported_length(tvb)) {
+ end_reassembly(msgid, NULL, pinfo);
+ new_tvb = get_reassembled_data(tvb, 0, pinfo, tree);
+ }
+ }
}
if (new_tvb) {
/* This is the last fragment, data has been reassembled
@@ -1591,22 +1622,6 @@ dissect_rpcrdma(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data
return offset;
}
-/* Initialize global variables for InfiniBand reassembly */
-static void
-rpcrdma_initialize(rpcrdma_type_t rtype, void *data)
-{
- g_rpcrdma_reduced = FALSE;
-
- if (rtype == INFINIBAND) {
- /* Reassembly is supported only on InifiBand packets */
- gp_infiniband_info = (struct infinibandinfo *)data;
- g_needs_reassembly = TRUE;
- } else {
- gp_infiniband_info = NULL;
- g_needs_reassembly = FALSE;
- }
-}
-
static gboolean
dissect_rpcrdma_ib_heur(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
@@ -1615,7 +1630,11 @@ dissect_rpcrdma_ib_heur(tvbuff_t *tvb, packet_info *pinfo,
gboolean more_frags = FALSE;
rdma_conv_info_t *p_rdma_conv_info;
- rpcrdma_initialize(INFINIBAND, data);
+ /* Initialize global variables for InfiniBand reassembly */
+ g_rpcrdma_reduced = FALSE;
+ g_needs_reassembly = TRUE;
+ gp_rdmap_info = NULL;
+ gp_infiniband_info = (struct infinibandinfo *)data;
if (!gp_infiniband_info)
return FALSE;
@@ -1693,15 +1712,28 @@ static gboolean
dissect_rpcrdma_iwarp_heur(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
{
- struct rdmapinfo *info = (struct rdmapinfo *)data;
- rpcrdma_initialize(IWARP, data);
+ rdma_conv_info_t *p_rdma_conv_info;
+
+ /* Initialize global variables for iWarp reassembly */
+ g_rpcrdma_reduced = FALSE;
+ g_needs_reassembly = TRUE;
+ gp_infiniband_info = NULL;
+ gp_rdmap_info = (rdmap_info_t *)data;
- if (!info)
+ if (!gp_rdmap_info)
return FALSE;
- switch (info->opcode) {
+ /* Get conversation state */
+ p_rdma_conv_info = get_rdma_conv_info(pinfo);
+
+ switch (gp_rdmap_info->opcode) {
case RDMA_SEND:
case RDMA_SEND_INVALIDATE:
+ tvb = add_send_fragment(p_rdma_conv_info, tvb, pinfo, tree);
+ if (!gp_rdmap_info->last_flag) {
+ /* This is a SEND fragment, do not dissect yet */
+ return FALSE;
+ }
break;
default:
return FALSE;