opa-mad: Fix PortSelectMask parsing to common function

Added Common function to convert 256-bit Port Select Mask into a range
string (e.g. "1-3,5-8,10").

Used wmem_strbuf API to allocate range string.

Change-Id: I70d737d1a33e84c7961eaf0bf83a1bc0689380a1
Signed-off-by: Adam Goldman <adam.goldman@intel.com>
Reviewed-on: https://code.wireshark.org/review/28506
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
sylvain/gmr1
Goldman, Adam 2019-01-15 09:12:59 -05:00 committed by Anders Broman
parent 9d5ab21163
commit 5d38999b57
1 changed files with 77 additions and 65 deletions

View File

@ -2516,6 +2516,72 @@ static const fragment_items opa_rmpp_frag_items = {
"RMPP Fragments"
};
/**
* Builds a range string from a PortSelectMask
*
* @param[in] tvb pointer to packet buffer
* @param[in] offset offset into packet buffer where port select mask begins
* @param[out] port_list optional: pointer to an arrray of ports, allocated by
* wmem_alloc(wmem_packet_scope(), 256)
* @param[out] num_ports optional: pointer to a number of ports in set in port
* select mask and portlist if provided.
* @return gchar* pointer to range string allocated using
* wmem_strbuf_sized_new(wmem_packet_scope(),...)
*/
static gchar *opa_format_port_select_mask(tvbuff_t *tvb, gint offset, guint8 **port_list, guint8 *num_ports)
{
gint i, j, port, last = -1, first = 0, ports = 0;
guint64 mask, psm[4];
wmem_strbuf_t *buf = NULL;
guint8 *portlist = NULL;
if (!tvb_bytes_exist(tvb, offset, 32)) {
return (gchar *)"Invalid Length: Requires 32 bytes";
}
psm[0] = tvb_get_ntoh64(tvb, offset);
psm[1] = tvb_get_ntoh64(tvb, offset + 8);
psm[2] = tvb_get_ntoh64(tvb, offset + 16);
psm[3] = tvb_get_ntoh64(tvb, offset + 24);
buf = wmem_strbuf_sized_new(wmem_packet_scope(), 0, ITEM_LABEL_LENGTH);
if (port_list) {
/* Allocate list of ports; max = 256 = 64 * 4 */
portlist = (guint8 *)wmem_alloc(wmem_packet_scope(), 256);
memset(portlist, 0xFF, 256);
}
for (i = 0; i < 4; i++) {
mask = psm[3 - i];
for (j = 0; mask && j < 64; j++, mask >>= 1) {
if ((mask & (guint64)0x1) == 0) continue;
port = (i * 64) + j;
if (portlist) portlist[ports] = port;
if (last == -1) {
wmem_strbuf_append_printf(buf, "%d", port);
last = first = port;
} else if ((port - last) > 1) {
if (first == last)
wmem_strbuf_append_printf(buf, ",%d", port);
else
wmem_strbuf_append_printf(buf, "-%d,%d", last, port);
last = first = port;
} else {
last = port;
}
ports++;
}
}
if (first != last && last != -1) {
wmem_strbuf_append_printf(buf, "-%d", last);
}
if (wmem_strbuf_get_len(buf) == 0) {
wmem_strbuf_append(buf, "<Empty>");
}
if (num_ports) *num_ports = ports;
if (port_list) *port_list = portlist;
return (gchar *)wmem_strbuf_finalize(buf);
}
/* Custom Functions */
static void cf_opa_mad_swinfo_ar_frequency(gchar *buf, guint16 value)
{
@ -6154,10 +6220,6 @@ static gint parse_ClearPortStatus(proto_tree *parentTree, tvbuff_t *tvb, gint *o
proto_tree *ClearPortStatus_header_tree;
proto_item *ClearPortStatus_PortSelectMask_item;
gint local_offset = *offset;
guint64 PortSelectMask[4];
guint64 PortSelectMaskTemp;
guint i, j;
guint PortsOffset = 0;
if (!parentTree)
return *offset;
@ -6168,20 +6230,10 @@ static gint parse_ClearPortStatus(proto_tree *parentTree, tvbuff_t *tvb, gint *o
return *offset;
ClearPortStatus_header_tree = proto_item_add_subtree(ClearPortStatus_header_item, ett_clearportstatus);
PortSelectMask[0] = tvb_get_ntoh64(tvb, local_offset);
PortSelectMask[1] = tvb_get_ntoh64(tvb, local_offset + 8);
PortSelectMask[2] = tvb_get_ntoh64(tvb, local_offset + 16);
PortSelectMask[3] = tvb_get_ntoh64(tvb, local_offset + 24);
ClearPortStatus_PortSelectMask_item = proto_tree_add_item(ClearPortStatus_header_tree, hf_opa_ClearPortStatus_PortSelectMask, tvb, local_offset, 32, ENC_NA);
for (j = 0; j < 4; j++) {
for (i = 0, PortSelectMaskTemp = PortSelectMask[3 - j]; i < 64 && (PortSelectMaskTemp); i++, PortSelectMaskTemp >>= (guint64)1) {
if (PortSelectMaskTemp & (guint64)0x1) {
proto_item_append_text(ClearPortStatus_PortSelectMask_item, "%s%u", (PortsOffset ? ", " : " "), (i)+(j * 64));
PortsOffset++;
}
}
}
proto_item_append_text(ClearPortStatus_PortSelectMask_item, ": %s",
opa_format_port_select_mask(tvb, local_offset, NULL, NULL));
local_offset += 32;
proto_tree_add_bitmask(ClearPortStatus_header_tree, tvb, local_offset,
@ -6203,10 +6255,7 @@ static gint parse_DataPortCounters(proto_tree *parentTree, tvbuff_t *tvb, gint *
gint local_offset = *offset;
guint32 VLSelectMask, vlSelMskTmp;
guint64 PortSelectMask[4];
guint64 PortSelectMaskTemp;
guint VLs, i, j, p;
guint PortsOffset = 0;
guint VLs, i, p;
guint Num_Ports = (MAD->AttributeModifier >> 24) & 0xFF;
if (!parentTree)
@ -6226,20 +6275,9 @@ static gint parse_DataPortCounters(proto_tree *parentTree, tvbuff_t *tvb, gint *
}
DataPortCounters_header_tree = proto_item_add_subtree(DataPortCounters_header_item, ett_dataportcounters);
PortSelectMask[0] = tvb_get_ntoh64(tvb, local_offset);
PortSelectMask[1] = tvb_get_ntoh64(tvb, local_offset + 8);
PortSelectMask[2] = tvb_get_ntoh64(tvb, local_offset + 16);
PortSelectMask[3] = tvb_get_ntoh64(tvb, local_offset + 24);
DataPortCounters_PortSelectMask_item = proto_tree_add_item(DataPortCounters_header_tree, hf_opa_DataPortCounters_PortSelectMask, tvb, local_offset, 32, ENC_NA);
for (j = 0; j < 4; j++) {
for (i = 0, PortSelectMaskTemp = PortSelectMask[3 - j]; i < 64 && (PortSelectMaskTemp); i++, PortSelectMaskTemp >>= (guint64)1) {
if (PortSelectMaskTemp & (guint64)0x1) {
proto_item_append_text(DataPortCounters_PortSelectMask_item, "%s%u", (PortsOffset ? ", " : " "), (i)+(j * 64));
PortsOffset++;
}
}
}
proto_item_append_text(DataPortCounters_PortSelectMask_item, ": %s",
opa_format_port_select_mask(tvb, local_offset, NULL, NULL));
local_offset += 32;
proto_tree_add_item(DataPortCounters_header_tree, hf_opa_DataPortCounters_VLSelectMask, tvb, local_offset, 4, ENC_BIG_ENDIAN);
@ -6351,10 +6389,7 @@ static gint parse_ErrorPortCounters(proto_tree *parentTree, tvbuff_t *tvb, gint
gint local_offset = *offset;
guint32 VLSelectMask, vlSelMskTmp;
guint64 PortSelectMask[4];
guint64 PortSelectMaskTemp;
guint VLs, i, j, p;
guint PortsOffset = 0;
guint VLs, i, p;
guint Num_Ports = (MAD->AttributeModifier & 0xFF000000) >> 24;
if (!parentTree)
@ -6374,19 +6409,9 @@ static gint parse_ErrorPortCounters(proto_tree *parentTree, tvbuff_t *tvb, gint
}
ErrorPortCounters_header_tree = proto_item_add_subtree(ErrorPortCounters_header_item, ett_errorportcounters);
PortSelectMask[0] = tvb_get_ntoh64(tvb, local_offset);
PortSelectMask[1] = tvb_get_ntoh64(tvb, local_offset + 8);
PortSelectMask[2] = tvb_get_ntoh64(tvb, local_offset + 16);
PortSelectMask[3] = tvb_get_ntoh64(tvb, local_offset + 24);
ErrorPortCounters_PortSelectMask_item = proto_tree_add_item(ErrorPortCounters_header_tree, hf_opa_ErrorPortCounters_PortSelectMask, tvb, local_offset, 32, ENC_NA);
for (j = 0; j < 4; j++) {
for (i = 0, PortSelectMaskTemp = PortSelectMask[3 - j]; i < 64 && (PortSelectMaskTemp); i++, PortSelectMaskTemp >>= (guint64)1) {
if (PortSelectMaskTemp & (guint64)0x1) {
proto_item_append_text(ErrorPortCounters_PortSelectMask_item, "%s%u", (PortsOffset ? ", " : " "), (i)+(j * 64));
PortsOffset++;
}
}
}
proto_item_append_text(ErrorPortCounters_PortSelectMask_item, ": %s",
opa_format_port_select_mask(tvb, local_offset, NULL, NULL));
local_offset += 32;
proto_tree_add_item(ErrorPortCounters_header_tree, hf_opa_ErrorPortCounters_VLSelectMask, tvb, local_offset, 4, ENC_BIG_ENDIAN);
@ -6469,10 +6494,7 @@ static gint parse_ErrorPortInfo(proto_tree *parentTree, tvbuff_t *tvb, gint *off
*FMConfigErrorInfo_tree;
gint local_offset = *offset;
guint64 PortSelectMask[4];
guint64 PortSelectMaskTemp;
guint i, j, p, ErrorCode;
guint PortsOffset = 0;
guint p, ErrorCode;
guint Num_Ports = (MAD->AttributeModifier & 0xFF000000) >> 24;
if (!parentTree)
@ -6487,19 +6509,9 @@ static gint parse_ErrorPortInfo(proto_tree *parentTree, tvbuff_t *tvb, gint *off
}
ErrorPortInfo_header_tree = proto_item_add_subtree(ErrorPortInfo_header_item, ett_errorportinfo);
PortSelectMask[0] = tvb_get_ntoh64(tvb, local_offset);
PortSelectMask[1] = tvb_get_ntoh64(tvb, local_offset + 8);
PortSelectMask[2] = tvb_get_ntoh64(tvb, local_offset + 16);
PortSelectMask[3] = tvb_get_ntoh64(tvb, local_offset + 24);
ErrorPortInfo_PortSelectMask_item = proto_tree_add_item(ErrorPortInfo_header_tree, hf_opa_ErrorPortInfo_PortSelectMask, tvb, local_offset, 32, ENC_NA);
for (j = 0; j < 4; j++) {
for (i = 0, PortSelectMaskTemp = PortSelectMask[3 - j]; i < 64 && (PortSelectMaskTemp); i++, PortSelectMaskTemp >>= (guint64)1) {
if (PortSelectMaskTemp & (guint64)0x1) {
proto_item_append_text(ErrorPortInfo_PortSelectMask_item, "%s%u", (PortsOffset ? ", " : " "), (i)+(j * 64));
PortsOffset++;
}
}
}
proto_item_append_text(ErrorPortInfo_PortSelectMask_item, ": %s",
opa_format_port_select_mask(tvb, local_offset, NULL, NULL));
local_offset += 32;
if (MAD->Method == METHOD_GET)