aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJorge Mora <jmora1300@gmail.com>2022-03-09 19:19:42 -0700
committerA Wireshark GitLab Utility <gerald+gitlab-utility@wireshark.org>2022-03-16 05:33:45 +0000
commit2523f6781d311d6aaa4aa8755fbda369a8931a79 (patch)
tree8304fe35d48fa83a3f9ed85d8485dc068dd49566
parentbf9a82d24498202005b0e71ea9107bbc9e6ad95c (diff)
RPCoRDMA: correctly cache Infiniband send fragments
On the second pass, make sure to get the correct reassembly info from the packet proto cache. This avoids having add_fragment() being called again in the second pass since the message id will be different. Also, do all of the work on add_send_fragment() and get it ready for iWarp send reassembly. Related to #17963.
-rw-r--r--epan/dissectors/packet-rpcrdma.c113
1 files changed, 51 insertions, 62 deletions
diff --git a/epan/dissectors/packet-rpcrdma.c b/epan/dissectors/packet-rpcrdma.c
index 81bceb3dec..68410db369 100644
--- a/epan/dissectors/packet-rpcrdma.c
+++ b/epan/dissectors/packet-rpcrdma.c
@@ -212,17 +212,17 @@ typedef struct {
/* Send reassembly info structure */
typedef struct {
- guint32 destqp; /* Destination queue pair */
- guint32 msgid; /* ID for fragments belonging together */
- guint32 msgno; /* Message number base */
-} send_msg_t;
+ guint32 msgid; /* ID for fragments belonging together */
+ guint32 msgno; /* Message number base */
+ guint32 rsize; /* Number of bytes added to reassembly table */
+} send_info_t;
/* State structure per conversation */
typedef struct {
- wmem_list_t *sendmsg_list; /* List of RDMA send reassembly struct info */
wmem_tree_t *segment_list; /* Binary tree of segments searched by handle */
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) */
segment_info_t *segment_info; /* Current READ/WRITE/REPLY segment info */
guint32 iosize; /* Maximum size of data transferred in a
single packet */
@@ -299,10 +299,10 @@ static rdma_conv_info_t *get_rdma_conv_info(packet_info *pinfo)
if (p_rdma_conv_info == NULL) {
/* Add state structure for this conversation */
p_rdma_conv_info = wmem_new(wmem_file_scope(), rdma_conv_info_t);
- p_rdma_conv_info->sendmsg_list = wmem_list_new(wmem_file_scope());
p_rdma_conv_info->segment_list = wmem_tree_new(wmem_file_scope());
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->segment_info = NULL;
p_rdma_conv_info->iosize = 1;
conversation_add_proto_data(p_conversation, proto_rpcordma, p_rdma_conv_info);
@@ -1264,62 +1264,58 @@ process_rdma_lists(tvbuff_t *tvb, guint offset, rdma_lists_t *rdma_lists,
* Add a fragment to the SEND reassembly table and return the reassembled data
* if all fragments have been added
*/
-static tvbuff_t *add_send_fragment(tvbuff_t *tvb, packet_info *pinfo,
- proto_tree *tree, gboolean more_frags, gboolean init)
+static tvbuff_t *add_send_fragment(rdma_conv_info_t *p_rdma_conv_info,
+ tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- guint32 msg_num;
+ guint32 msgid = 0;
+ gint32 msgno = -1;
tvbuff_t *new_tvb = NULL;
- wmem_list_frame_t *item;
- send_msg_t *p_send_item;
- send_msg_t *p_send_msg = NULL;
- rdma_conv_info_t *p_rdma_conv_info;
-
- /* Get conversation state */
- p_rdma_conv_info = get_rdma_conv_info(pinfo);
-
- /* Find the correct send_msg_t info struct */
- for (item = wmem_list_head(p_rdma_conv_info->sendmsg_list); item != NULL; item = wmem_list_frame_next(item)) {
- p_send_item = (send_msg_t *)wmem_list_frame_data(item);
- if (pinfo->destport == p_send_item->destqp) {
- p_send_msg = p_send_item;
- break;
- }
+ gboolean first_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;
+ last_frag = (gp_infiniband_info->opCode == RC_SEND_LAST || \
+ gp_infiniband_info->opCode == RC_SEND_LAST_INVAL);
}
- if (p_send_msg == NULL) {
- /* Create new send_msg_t info */
- p_send_msg = wmem_new(wmem_file_scope(), send_msg_t);
- p_send_msg->destqp = pinfo->destport;
- p_send_msg->msgid = get_msg_id();
- p_send_msg->msgno = gp_infiniband_info->packet_seq_num;
+ if (pinfo->fd->visited) {
+ return get_reassembled_data(tvb, 0, pinfo, tree);
+ } else if (first_frag) {
+ /* Start of multi-SEND message */
+ p_send_info = wmem_new(wmem_file_scope(), send_info_t);
+ p_send_info->msgid = get_msg_id();
+ p_send_info->rsize = 0;
- /* Add info to the list */
- wmem_list_append(p_rdma_conv_info->sendmsg_list, p_send_msg);
+ if (gp_infiniband_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 {
+ /* 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);
+ }
}
-
- if (init) {
- /* Make sure to set the base message number on SEND First */
- p_send_msg->msgno = gp_infiniband_info->packet_seq_num;
- /* Make sure to throw away the current reassembly fragments
- * if last reassembly was incomplete and not terminated */
- new_tvb = fragment_delete(&rpcordma_reassembly_table, pinfo, p_send_msg->msgid, NULL);
- if (new_tvb) {
- tvb_free(new_tvb);
+ if (p_send_info) {
+ p_send_info->rsize += tvb_reported_length(tvb);
+ msgid = p_send_info->msgid;
+ if (gp_infiniband_info) {
+ /* Message numbers are consecutive starting at zero */
+ msgno = gp_infiniband_info->packet_seq_num - p_send_info->msgno;
}
}
-
- /* Message number of current fragment */
- msg_num = gp_infiniband_info->packet_seq_num - p_send_msg->msgno;
-
- /* Add fragment to send reassembly table */
- new_tvb = add_fragment(tvb, 0, p_send_msg->msgid, msg_num, more_frags, NULL, pinfo, tree);
-
- if (!more_frags) {
- /* Set base message number to the next expected value */
- p_send_msg->msgno = gp_infiniband_info->packet_seq_num + 1;
+ if (msgid > 0 && msgno >= 0) {
+ new_tvb = add_fragment(tvb, 0, msgid, msgno, !last_frag, p_rdma_conv_info, pinfo, tree);
}
-
- return new_tvb;
+ if (new_tvb) {
+ /* This is the last fragment, data has been reassembled
+ * and ready to be dissected */
+ return new_tvb;
+ }
+ return tvb;
}
/*
@@ -1632,19 +1628,12 @@ dissect_rpcrdma_ib_heur(tvbuff_t *tvb, packet_info *pinfo,
case RC_SEND_ONLY_INVAL:
break;
case RC_SEND_FIRST:
- add_send_fragment(tvb, pinfo, tree, TRUE, TRUE);
- return FALSE;
case RC_SEND_MIDDLE:
- add_send_fragment(tvb, pinfo, tree, TRUE, FALSE);
+ add_send_fragment(p_rdma_conv_info, tvb, pinfo, tree);
return FALSE;
case RC_SEND_LAST:
case RC_SEND_LAST_INVAL:
- new_tvb = add_send_fragment(tvb, pinfo, tree, FALSE, FALSE);
- if (new_tvb) {
- /* This is the last fragment, data has been reassembled
- * and ready to be dissected */
- tvb = new_tvb;
- }
+ tvb = add_send_fragment(p_rdma_conv_info, tvb, pinfo, tree);
break;
case RC_RDMA_WRITE_ONLY:
case RC_RDMA_WRITE_ONLY_IMM: