From e3ecb9310c9973f85f7d0bd06ef8cf7dc7ecf3c2 Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Mon, 24 Oct 2016 11:43:25 -0400 Subject: [PATCH] packet-infiniband: Added support to dissect ip cm request private data This patch adds support to dissect 36 bytes of private data of Table 560 of spec 1.3.1 whenever CM request message is of IP CM type. Change-Id: I66b65b066a0034cf95c4c4f38549882c265b7ef5 Tested-by: paravpandit@yahoo.com Reviewed-on: https://code.wireshark.org/review/18434 Reviewed-by: Alexis La Goutte Petri-Dish: Alexis La Goutte Tested-by: Petri Dish Buildbot Reviewed-by: Roland Knall --- epan/dissectors/packet-infiniband.c | 119 ++++++++++++++++++++++++++-- 1 file changed, 114 insertions(+), 5 deletions(-) diff --git a/epan/dissectors/packet-infiniband.c b/epan/dissectors/packet-infiniband.c index 304e73ab8c..0dbb91699e 100644 --- a/epan/dissectors/packet-infiniband.c +++ b/epan/dissectors/packet-infiniband.c @@ -74,6 +74,7 @@ static gint ett_subnadmin = -1; static gint ett_mad = -1; static gint ett_cm = -1; static gint ett_cm_sid = -1; +static gint ett_cm_ipcm = -1; static gint ett_rmpp = -1; static gint ett_subm_attribute = -1; static gint ett_suba_attribute = -1; @@ -625,6 +626,18 @@ static int hf_cm_req_alt_reserved1 = -1; static int hf_cm_req_local_ACK_timeout = -1; static int hf_cm_req_alt_reserved2 = -1; static int hf_cm_req_private_data = -1; +static int hf_cm_req_ip_cm_req_msg = -1; +static int hf_cm_req_ip_cm_majv = -1; +static int hf_cm_req_ip_cm_minv = -1; +static int hf_cm_req_ip_cm_ipv = -1; +static int hf_cm_req_ip_cm_res = -1; +static int hf_cm_req_ip_cm_sport = -1; +static int hf_cm_req_ip_cm_dip6 = -1; +static int hf_cm_req_ip_cm_sip6 = -1; +static int hf_cm_req_ip_cm_dip4 = -1; +static int hf_cm_req_ip_cm_sip4 = -1; +static int hf_ip_cm_req_consumer_private_data = -1; + /* CM REP Header */ static int hf_cm_rep_localcommid = -1; static int hf_cm_rep_remotecommid = -1; @@ -2922,11 +2935,12 @@ static void parse_DEV_MGT(proto_tree *parentTree, tvbuff_t *tvb, gint *offset) *offset = local_offset; } -static void parse_CM_Req_ServiceID(proto_tree *parent_tree, tvbuff_t *tvb, gint *offset, guint64 serviceid) +static gboolean parse_CM_Req_ServiceID(proto_tree *parent_tree, tvbuff_t *tvb, gint *offset, guint64 serviceid) { proto_item *service_id_item; proto_tree *service_id_tree; gint local_offset = *offset; + gboolean ip_cm_sid; if ((serviceid & RDMA_IP_CM_SID_PREFIX_MASK) == RDMA_IP_CM_SID_PREFIX) { service_id_item = proto_tree_add_item(parent_tree, hf_cm_req_service_id, tvb, local_offset, 8, ENC_NA); @@ -2939,11 +2953,14 @@ static void parse_CM_Req_ServiceID(proto_tree *parent_tree, tvbuff_t *tvb, gint local_offset += 1; proto_tree_add_item(service_id_tree, hf_cm_req_service_id_dport, tvb, local_offset, 2, ENC_BIG_ENDIAN); local_offset += 2; + ip_cm_sid = TRUE; } else { proto_tree_add_item(parent_tree, hf_cm_req_service_id, tvb, local_offset, 8, ENC_BIG_ENDIAN); local_offset += 8; + ip_cm_sid = FALSE; } *offset = local_offset; + return ip_cm_sid; } static void save_conversation_info(packet_info *pinfo, guint8 *local_gid, guint8 *remote_gid, @@ -2987,6 +3004,45 @@ static void save_conversation_info(packet_info *pinfo, guint8 *local_gid, guint8 } } +static void parse_IP_CM_Req_Msg(proto_tree *parent_tree, tvbuff_t *tvb, gint local_offset) +{ + proto_item *private_data_item; + proto_tree *private_data_tree; + guint8 ipv; + + private_data_item = proto_tree_add_item(parent_tree, hf_cm_req_ip_cm_req_msg, tvb, local_offset, 36, ENC_NA); + proto_item_set_text(private_data_item, "%s", "IP CM Private Data"); + private_data_tree = proto_item_add_subtree(private_data_item, ett_cm_ipcm); + + proto_tree_add_item(private_data_tree, hf_cm_req_ip_cm_majv, tvb, local_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(private_data_tree, hf_cm_req_ip_cm_minv, tvb, local_offset, 1, ENC_BIG_ENDIAN); + local_offset += 1; + ipv = tvb_get_guint8(tvb, local_offset) & 0xf0 >> 4; + + proto_tree_add_item(private_data_tree, hf_cm_req_ip_cm_ipv, tvb, local_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(private_data_tree, hf_cm_req_ip_cm_res, tvb, local_offset, 1, ENC_BIG_ENDIAN); + local_offset += 1; + proto_tree_add_item(private_data_tree, hf_cm_req_ip_cm_sport, tvb, local_offset, 2, ENC_BIG_ENDIAN); + local_offset += 2; + + if (ipv == 4) { + /* skip first 12 bytes of zero for dip */ + proto_tree_add_item(private_data_tree, hf_cm_req_ip_cm_dip4, tvb, local_offset + 12, 4, ENC_NA); + local_offset += 16; + /* skip first 12 bytes of zero for sip */ + proto_tree_add_item(private_data_tree, hf_cm_req_ip_cm_sip4, tvb, local_offset + 12, 4, ENC_NA); + } else { + proto_tree_add_item(private_data_tree, hf_cm_req_ip_cm_dip6, tvb, local_offset, 16, ENC_NA); + local_offset += 16; + proto_tree_add_item(private_data_tree, hf_cm_req_ip_cm_sip6, tvb, local_offset, 16, ENC_NA); + } + local_offset += 16; + + /* finally add the consumer specific private data as undecoded data */ + proto_tree_add_item(private_data_tree, hf_ip_cm_req_consumer_private_data, + tvb, local_offset, 56, ENC_NA); +} + static void parse_CM_Req(proto_tree *parentTree, packet_info *pinfo, tvbuff_t *tvb, gint *offset, MAD_Data *MadData, proto_tree *CM_header_tree) { @@ -2998,6 +3054,7 @@ static void parse_CM_Req(proto_tree *parentTree, packet_info *pinfo, tvbuff_t *t guint32 local_qpn; guint32 local_lid; guint32 remote_lid; + gboolean ip_cm_sid; local_gid = (guint8 *)wmem_alloc(wmem_packet_scope(), GID_SIZE); remote_gid = (guint8 *)wmem_alloc(wmem_packet_scope(), GID_SIZE); @@ -3008,7 +3065,7 @@ static void parse_CM_Req(proto_tree *parentTree, packet_info *pinfo, tvbuff_t *t proto_tree_add_item(CM_header_tree, hf_infiniband_reserved4, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; serviceid = tvb_get_ntoh64(tvb, local_offset); - parse_CM_Req_ServiceID(CM_header_tree, tvb, &local_offset, serviceid); + ip_cm_sid = parse_CM_Req_ServiceID(CM_header_tree, tvb, &local_offset, serviceid); proto_tree_add_item(CM_header_tree, hf_cm_req_local_ca_guid, tvb, local_offset, 8, ENC_BIG_ENDIAN); local_offset += 8; proto_tree_add_item(CM_header_tree, hf_infiniband_reserved4, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; @@ -3067,11 +3124,17 @@ static void parse_CM_Req(proto_tree *parentTree, packet_info *pinfo, tvbuff_t *t save_conversation_info(pinfo, local_gid, remote_gid, local_qpn, local_lid, remote_lid, serviceid, MadData); + if (ip_cm_sid) { + /* decode IP CM service specific private data */ + parse_IP_CM_Req_Msg(CM_header_tree, tvb, local_offset); + } else { + /* Add the undecoded private data anyway as RDMA CM private data */ + proto_tree_add_item(CM_header_tree, hf_cm_req_private_data, tvb, local_offset, 92, ENC_NA); + } + /* give a chance for subdissectors to analyze the private data */ next_tvb = tvb_new_subset_length(tvb, local_offset, 92); - if (! dissector_try_heuristic(heur_dissectors_cm_private, next_tvb, pinfo, parentTree, &hdtbl_entry, NULL) ) - /* if none reported success, add this as raw "data" */ - proto_tree_add_item(CM_header_tree, hf_cm_req_private_data, tvb, local_offset, 92, ENC_NA); + dissector_try_heuristic(heur_dissectors_cm_private, next_tvb, pinfo, parentTree, &hdtbl_entry, NULL); local_offset += 92; *offset = local_offset; @@ -5756,6 +5819,51 @@ void proto_register_infiniband(void) "PrivateData", "infiniband.cm.req.private", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} }, + {&hf_cm_req_ip_cm_req_msg, { + "IP CM Request Msg", "infiniband.cm.req.ip_cm", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + {&hf_cm_req_ip_cm_majv, { + "IP CM Major Version", "infiniband.cm.req.ip_cm.majv", + FT_UINT8, BASE_HEX, NULL, 0xf0, NULL, HFILL} + }, + {&hf_cm_req_ip_cm_minv, { + "IP CM Minor Version", "infiniband.cm.req.ip_cm.minv", + FT_UINT8, BASE_HEX, NULL, 0x0f, NULL, HFILL} + }, + {&hf_cm_req_ip_cm_ipv, { + "IP CM IP Version", "infiniband.cm.req.ip_cm.ipv", + FT_UINT8, BASE_HEX, NULL, 0xf0, NULL, HFILL} + }, + {&hf_cm_req_ip_cm_res, { + "IP CM Reserved", "infiniband.cm.req.ip_cm.reserved", + FT_UINT8, BASE_HEX, NULL, 0x0f, NULL, HFILL} + }, + {&hf_cm_req_ip_cm_sport, { + "IP CM Source Port", "infiniband.cm.req.ip_cm.sport", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + {&hf_cm_req_ip_cm_dip6, { + "IP CM Destination IP", "infiniband.cm.req.ip_cm.dip6", + FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + {&hf_cm_req_ip_cm_sip6, { + "IP CM Source IP", "infiniband.cm.req.ip_cm.sip6", + FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + {&hf_cm_req_ip_cm_dip4, { + "IP CM Destination IP", "infiniband.cm.req.ip_cm.dip4", + FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + {&hf_cm_req_ip_cm_sip4, { + "IP CM Source IP", "infiniband.cm.req.ip_cm.sip4", + FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + + {&hf_ip_cm_req_consumer_private_data, { + "IP CM Consumer PrivateData", "infiniband.cm.req.ip_cm.private", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, /* CM REP Header */ {&hf_cm_rep_localcommid, { "Local Communication ID", "infiniband.cm.rep", @@ -7519,6 +7627,7 @@ void proto_register_infiniband(void) &ett_subnadmin, &ett_cm, &ett_cm_sid, + &ett_cm_ipcm, &ett_mad, &ett_rmpp, &ett_subm_attribute,