Index: epan/dissectors/packet-infiniband.c
===================================================================
--- epan/dissectors/packet-infiniband.c	(revision 32537)
+++ epan/dissectors/packet-infiniband.c	(working copy)
@@ -8,6 +8,8 @@
  * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
  *
+ * Modified 2010 by Mellanox Technologies Ltd.
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
@@ -30,7 +32,9 @@
 #include <glib.h>
 #include <epan/packet.h>
 #include <epan/proto.h>
+#include <epan/emem.h>
 #include <epan/dissectors/packet-frame.h>
+#include <string.h>
 #include "packet-infiniband.h"
 
 /* Main Dissector */
@@ -78,7 +82,13 @@
     struct e_in6_addr SRCgid;       /* Structures to hold GIDs should we need them */
     struct e_in6_addr DSTgid;
     gint crc_length = 0;
+    gint32 src_qp = -1, dst_qp = -1;    /* Tracks source and destination QPs. This is important
+                                           for deciding whether or not the packet is a MAD      */
 
+    /* initialize source/destination address strings. we will fill them in later */
+    src_addr_str = ep_alloc(ADDR_STR_MAX_LEN+1);
+    dst_addr_str = ep_alloc(ADDR_STR_MAX_LEN+1);
+                                                                   
     /* Mark the Packet type as Infiniband in the wireshark UI */
     /* Clear other columns */
     if(pinfo->cinfo)
@@ -119,7 +129,7 @@
 
 
     /* Get the Virtual Lane.  We'll use this to identify Subnet Management and Subnet Administration Packets. */
-    virtualLane =  tvb_get_guint8(tvb, offset);
+    virtualLane = tvb_get_guint8(tvb, offset);
     virtualLane = virtualLane & 0xF0;
 
 
@@ -140,13 +150,11 @@
 
 
     /* Set destination in packet view. */
-    if (check_col(pinfo->cinfo, COL_DEF_DST))
-    {
-        col_add_fstr(pinfo->cinfo, COL_DEF_DST, "DLID: %s", tvb_bytes_to_str(tvb, offset, 2));
-    }
+    g_snprintf(dst_addr_str, ADDR_STR_MAX_LEN, "DLID: %d", tvb_get_ntohs(tvb, offset));
+    SET_ADDRESS(&pinfo->dst, AT_STRINGZ, (int)strlen(dst_addr_str)+1, dst_addr_str);
+
     offset+=2;
 
-
     proto_tree_add_item(local_route_header_tree, hf_infiniband_reserved5,               tvb, offset, 2, FALSE);
 
     packetLength = tvb_get_ntohs(tvb, offset); /* Get the Packet Length. This will determine payload size later on. */
@@ -158,10 +166,8 @@
     proto_tree_add_item(local_route_header_tree, hf_infiniband_source_local_id,         tvb, offset, 2, FALSE);
 
     /* Set Source in packet view. */
-    if (check_col(pinfo->cinfo, COL_DEF_SRC))
-    {
-        col_add_fstr(pinfo->cinfo, COL_DEF_SRC, "SLID: %s", tvb_bytes_to_str(tvb, offset, 2));
-    }
+    g_snprintf(src_addr_str, ADDR_STR_MAX_LEN, "SLID: %d", tvb_get_ntohs(tvb, offset));
+    SET_ADDRESS(&pinfo->src, AT_STRINGZ, (int)strlen(src_addr_str)+1, src_addr_str);
 
     offset+=2;
     packetLength -= 8; /* Shave 8 bytes for the LRH. */
@@ -189,19 +195,21 @@
             proto_tree_add_item(global_route_header_tree, hf_infiniband_source_gid,         tvb, offset, 16, FALSE);
 
             tvb_get_ipv6(tvb, offset, &SRCgid);
-            if (check_col(pinfo->cinfo, COL_DEF_SRC))
-            {
-                col_add_fstr(pinfo->cinfo, COL_DEF_SRC, "SGID: %s", ip6_to_str(&SRCgid));
-            }
+
+            /* set source GID in packet view*/
+            g_snprintf(src_addr_str,  ADDR_STR_MAX_LEN, "SGID: %s", ip6_to_str(&SRCgid));
+            SET_ADDRESS(&pinfo->src,  AT_STRINGZ, (int)strlen(src_addr_str)+1, src_addr_str);
+
             offset += 16;
 
             proto_tree_add_item(global_route_header_tree, hf_infiniband_destination_gid,    tvb, offset, 16, FALSE);
 
             tvb_get_ipv6(tvb, offset, &DSTgid);
-            if (check_col(pinfo->cinfo, COL_DEF_DST))
-            {
-                col_add_fstr(pinfo->cinfo, COL_DEF_DST, "DGID: %s", ip6_to_str(&DSTgid));
-            }
+
+            /* set destination GID in packet view*/
+            g_snprintf(dst_addr_str,  ADDR_STR_MAX_LEN, "DGID: %s", ip6_to_str(&DSTgid));
+            SET_ADDRESS(&pinfo->dst,  AT_STRINGZ, (int)strlen(dst_addr_str)+1, dst_addr_str);
+
             offset += 16;
             packetLength -= 40; /* Shave 40 bytes for GRH */
 
@@ -232,7 +240,8 @@
             proto_tree_add_item(base_transport_header_tree, hf_infiniband_transport_header_version,     tvb, offset, 1, FALSE); offset +=1;
             proto_tree_add_item(base_transport_header_tree, hf_infiniband_partition_key,                tvb, offset, 2, FALSE); offset +=2;
             proto_tree_add_item(base_transport_header_tree, hf_infiniband_reserved8,                    tvb, offset, 1, FALSE); offset +=1;
-            proto_tree_add_item(base_transport_header_tree, hf_infiniband_destination_qp,               tvb, offset, 3, FALSE); offset +=3;
+            proto_tree_add_item(base_transport_header_tree, hf_infiniband_destination_qp,               tvb, offset, 3, FALSE);
+            dst_qp = tvb_get_ntoh24(tvb, offset); offset +=3;
             proto_tree_add_item(base_transport_header_tree, hf_infiniband_acknowledge_request,          tvb, offset, 1, FALSE);
             proto_tree_add_item(base_transport_header_tree, hf_infiniband_reserved7,                    tvb, offset, 1, FALSE); offset +=1;
             proto_tree_add_item(base_transport_header_tree, hf_infiniband_packet_sequence_number,       tvb, offset, 3, FALSE); offset +=3;
@@ -243,11 +252,9 @@
         break;
         case IP_NON_IBA:
             /* Raw IPv6 Packet */
-            if (check_col(pinfo->cinfo, COL_DEF_DST))
-            {
-                col_set_str(pinfo->cinfo, COL_DEF_DST, "IPv6 over IB Packet");
-                col_set_fence(pinfo->cinfo, COL_DEF_DST);
-            }
+            g_snprintf(dst_addr_str,  ADDR_STR_MAX_LEN, "IPv6 over IB Packet");
+            SET_ADDRESS(&pinfo->src,  AT_STRINGZ, (int)strlen(dst_addr_str)+1, dst_addr_str);
+
             parse_IPvSix(all_headers_tree, tvb, &offset, pinfo);
             break;
         case RAW:
@@ -278,38 +285,38 @@
         {
             case RDETH_DETH_PAYLD:
                 parse_RDETH(all_headers_tree, tvb, &offset);
-                parse_DETH(all_headers_tree, tvb, &offset);
+                parse_DETH(all_headers_tree, tvb, &offset, &src_qp);
 
                 packetLength -= 4; /* RDETH */
                 packetLength -= 8; /* DETH */
 
-                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, virtualLane);
+                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, src_qp, dst_qp);
                 break;
             case RDETH_DETH_RETH_PAYLD:
                 parse_RDETH(all_headers_tree, tvb, &offset);
-                parse_DETH(all_headers_tree, tvb, &offset);
+                parse_DETH(all_headers_tree, tvb, &offset, &src_qp);
                 parse_RETH(all_headers_tree, tvb, &offset);
 
                 packetLength -= 4; /* RDETH */
                 packetLength -= 8; /* DETH */
                 packetLength -= 16; /* RETH */
 
-                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, virtualLane);
+                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, src_qp, dst_qp);
                 break;
             case RDETH_DETH_IMMDT_PAYLD:
                 parse_RDETH(all_headers_tree, tvb, &offset);
-                parse_DETH(all_headers_tree, tvb, &offset);
+                parse_DETH(all_headers_tree, tvb, &offset, &src_qp);
                 parse_IMMDT(all_headers_tree, tvb, &offset);
 
                 packetLength -= 4; /* RDETH */
                 packetLength -= 8; /* DETH */
                 packetLength -= 4; /* IMMDT */
 
-                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, virtualLane);
+                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, src_qp, dst_qp);
                 break;
             case RDETH_DETH_RETH_IMMDT_PAYLD:
                 parse_RDETH(all_headers_tree, tvb, &offset);
-                parse_DETH(all_headers_tree, tvb, &offset);
+                parse_DETH(all_headers_tree, tvb, &offset, &src_qp);
                 parse_RETH(all_headers_tree, tvb, &offset);
                 parse_IMMDT(all_headers_tree, tvb, &offset);
 
@@ -318,11 +325,11 @@
                 packetLength -= 16; /* RETH */
                 packetLength -= 4; /* IMMDT */
 
-                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, virtualLane);
+                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, src_qp, dst_qp);
                 break;
             case RDETH_DETH_RETH:
                 parse_RDETH(all_headers_tree, tvb, &offset);
-                parse_DETH(all_headers_tree, tvb, &offset);
+                parse_DETH(all_headers_tree, tvb, &offset, &src_qp);
                 parse_RETH(all_headers_tree, tvb, &offset);
 
                 packetLength -= 4; /* RDETH */
@@ -337,14 +344,14 @@
                 packetLength -= 4; /* RDETH */
                 packetLength -= 4; /* AETH */
 
-                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, virtualLane);
+                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, src_qp, dst_qp);
                 break;
             case RDETH_PAYLD:
                 parse_RDETH(all_headers_tree, tvb, &offset);
 
                 packetLength -= 4; /* RDETH */
 
-                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, virtualLane);
+                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, src_qp, dst_qp);
                 break;
             case RDETH_AETH:
                 parse_AETH(all_headers_tree, tvb, &offset);
@@ -367,7 +374,7 @@
                 break;
             case RDETH_DETH_ATOMICETH:
                 parse_RDETH(all_headers_tree, tvb, &offset);
-                parse_DETH(all_headers_tree, tvb, &offset);
+                parse_DETH(all_headers_tree, tvb, &offset, &src_qp);
                 parse_ATOMICETH(all_headers_tree, tvb, &offset);
 
                 packetLength -= 4; /* RDETH */
@@ -377,36 +384,36 @@
                 break;
             case RDETH_DETH:
                 parse_RDETH(all_headers_tree, tvb, &offset);
-                parse_DETH(all_headers_tree, tvb, &offset);
+                parse_DETH(all_headers_tree, tvb, &offset, &src_qp);
 
                 packetLength -= 4; /* RDETH */
                 packetLength -= 8; /* DETH */
 
                 break;
             case DETH_PAYLD:
-                parse_DETH(all_headers_tree, tvb, &offset);
+                parse_DETH(all_headers_tree, tvb, &offset, &src_qp);
 
                 packetLength -= 8; /* DETH */
 
-                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, virtualLane);
+                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, src_qp, dst_qp);
                 break;
             case PAYLD:
 
-                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, virtualLane);
+                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, src_qp, dst_qp);
                 break;
             case IMMDT_PAYLD:
                 parse_IMMDT(all_headers_tree, tvb, &offset);
 
                 packetLength -= 4; /* IMMDT */
 
-                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, virtualLane);
+                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, src_qp, dst_qp);
                 break;
             case RETH_PAYLD:
                 parse_RETH(all_headers_tree, tvb, &offset);
 
                 packetLength -= 16; /* RETH */
 
-                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, virtualLane);
+                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, src_qp, dst_qp);
                 break;
             case RETH:
                 parse_RETH(all_headers_tree, tvb, &offset);
@@ -419,7 +426,7 @@
 
                 packetLength -= 4; /* AETH */
 
-                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, virtualLane);
+                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, src_qp, dst_qp);
                 break;
             case AETH:
                 parse_AETH(all_headers_tree, tvb, &offset);
@@ -446,16 +453,16 @@
 
                 packetLength -= 4; /* IETH */
 
-                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, virtualLane);
+                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, src_qp, dst_qp);
                 break;
             case DETH_IMMDT_PAYLD:
-                parse_DETH(all_headers_tree, tvb, &offset);
+                parse_DETH(all_headers_tree, tvb, &offset, &src_qp);
                 parse_IMMDT(all_headers_tree, tvb, &offset);
 
                 packetLength -= 8; /* DETH */
                 packetLength -= 4; /* IMMDT */
 
-                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, virtualLane);
+                parse_PAYLOAD(all_headers_tree, pinfo, tvb, &offset, packetLength, src_qp, dst_qp);
                 break;
             default:
                 parse_VENDOR(all_headers_tree, tvb, &offset);
@@ -680,7 +687,7 @@
 * IN: tvb - the data buffer from wireshark
 * IN/OUT: The current and updated offset */
 static void
-parse_DETH(proto_tree * parentTree, tvbuff_t *tvb, gint *offset)
+parse_DETH(proto_tree * parentTree, tvbuff_t *tvb, gint *offset, gint *src_qp)
 {
     gint local_offset = *offset;
     /* DETH - Datagram Extended Transport Header */
@@ -693,7 +700,8 @@
 
     proto_tree_add_item(DETH_header_tree, hf_infiniband_queue_key,                  tvb, local_offset, 4, FALSE); local_offset+=4;
     proto_tree_add_item(DETH_header_tree, hf_infiniband_reserved8_DETH,             tvb, local_offset, 1, FALSE); local_offset+=1;
-    proto_tree_add_item(DETH_header_tree, hf_infiniband_source_qp,                  tvb, local_offset, 3, FALSE); local_offset+=3;
+    proto_tree_add_item(DETH_header_tree, hf_infiniband_source_qp,                  tvb, local_offset, 3, FALSE);
+    *src_qp = tvb_get_ntoh24(tvb, local_offset); local_offset+=3;
 
     *offset = local_offset;
 }
@@ -831,7 +839,7 @@
 * IN: tvb - the data buffer from wireshark
 * IN/OUT: The current and updated offset
 * IN: Length of Payload */
-static void parse_PAYLOAD(proto_tree *parentTree, packet_info *pinfo, tvbuff_t *tvb, gint *offset, gint length, guint8 virtualLane)
+static void parse_PAYLOAD(proto_tree *parentTree, packet_info *pinfo, tvbuff_t *tvb, gint *offset, gint length, gint src_qp, gint dst_qp)
 {
     gint local_offset = *offset;
     /* Payload - Packet Payload */
@@ -853,7 +861,7 @@
         }
         return;
     }
-    if(virtualLane == 0xF0)
+    if(src_qp == 0 || src_qp == 1 || dst_qp == 0 || dst_qp == 1)    /* management datagram */
     {
         management_class =  tvb_get_guint8(tvb, (*offset) + 1);
 
@@ -893,7 +901,7 @@
                 break;
                 case PERF:
                     /* parse performance */
-                    parse_PERF(parentTree, tvb, &local_offset);
+                    parse_PERF(parentTree, tvb, pinfo, &local_offset);
                 break;
                 case BM:
                     /* parse baseboard mgmt */
@@ -1277,7 +1285,7 @@
 * IN: parentTree to add the dissection to
 * IN: tvb - the data buffer from wireshark
 * IN/OUT: The current and updated offset */
-static void parse_PERF(proto_tree *parentTree, tvbuff_t *tvb, gint *offset)
+static void parse_PERF(proto_tree *parentTree, tvbuff_t *tvb, packet_info *pinfo, gint *offset)
 {
     /* Parse the Common MAD Header */
     MAD_Data MadData;
@@ -1289,9 +1297,22 @@
         /* TODO: Mark Corrupt Packet - Not enough bytes exist for at least the Common MAD header which is present in all MAD packets */
         return;
     }
-    local_offset = *offset;
-    PERF_header_item = proto_tree_add_item(parentTree, hf_infiniband_smp_data, tvb, local_offset, 256, FALSE); local_offset += 256;
-    proto_item_set_text(PERF_header_item, "%s", "PERF - Performance Management MAD (Dissector Not Implemented)");
+
+    local_offset = *offset; /* offset now points to the start of the MAD data field */
+
+    switch (MadData.attributeID) {
+        case ATTR_PORT_COUNTERS:
+            parse_PERF_PortCounters(parentTree, tvb, pinfo, &local_offset);
+            break;
+        case ATTR_PORT_COUNTERS_EXT:
+            parse_PERF_PortCountersExtended(parentTree, tvb, pinfo, &local_offset);
+            break;
+        default:
+            PERF_header_item = proto_tree_add_item(parentTree, hf_infiniband_smp_data, tvb, local_offset, MAD_DATA_SIZE, FALSE); local_offset += MAD_DATA_SIZE;
+            proto_item_set_text(PERF_header_item, "%s", "PERF - Performance Management MAD (Dissector Not Implemented)");
+            break;
+    }
+
     *offset = local_offset;
 }
 
@@ -1313,7 +1334,7 @@
     }
     local_offset = *offset;
 
-    PERF_header_item = proto_tree_add_item(parentTree, hf_infiniband_smp_data, tvb, local_offset, 256, FALSE); local_offset += 256;
+    PERF_header_item = proto_tree_add_item(parentTree, hf_infiniband_smp_data, tvb, local_offset, MAD_DATA_SIZE, FALSE); local_offset += MAD_DATA_SIZE;
     proto_item_set_text(PERF_header_item, "%s", "BM - Baseboard Management MAD (Dissector Not Implemented)");
     *offset = local_offset;
 }
@@ -1335,7 +1356,7 @@
         return;
     }
     local_offset = *offset;
-    PERF_header_item = proto_tree_add_item(parentTree, hf_infiniband_smp_data, tvb, local_offset, 256, FALSE); local_offset += 256;
+    PERF_header_item = proto_tree_add_item(parentTree, hf_infiniband_smp_data, tvb, local_offset, MAD_DATA_SIZE, FALSE); local_offset += MAD_DATA_SIZE;
     proto_item_set_text(PERF_header_item, "%s", "DEV_MGT - Device Management MAD (Dissector Not Implemented)");
     *offset = local_offset;
 }
@@ -1357,7 +1378,7 @@
         return;
     }
     local_offset = *offset;
-    PERF_header_item = proto_tree_add_item(parentTree, hf_infiniband_smp_data, tvb, local_offset, 256, FALSE); local_offset += 256;
+    PERF_header_item = proto_tree_add_item(parentTree, hf_infiniband_smp_data, tvb, local_offset, MAD_DATA_SIZE, FALSE); local_offset += MAD_DATA_SIZE;
     proto_item_set_text(PERF_header_item, "%s", "COMM - Communication Management MAD (Dissector Not Implemented)");
     *offset = local_offset;
 }
@@ -1380,7 +1401,7 @@
     }
     local_offset = *offset;
 
-    PERF_header_item = proto_tree_add_item(parentTree, hf_infiniband_smp_data, tvb, local_offset, 256, FALSE); local_offset += 256;
+    PERF_header_item = proto_tree_add_item(parentTree, hf_infiniband_smp_data, tvb, local_offset, MAD_DATA_SIZE, FALSE); local_offset += MAD_DATA_SIZE;
     proto_item_set_text(PERF_header_item, "%s", "SNMP - SNMP Tunneling MAD (Dissector Not Implemented)");
     *offset = local_offset;
 }
@@ -1403,8 +1424,9 @@
     }
     local_offset = *offset;
 
-    PERF_header_item = proto_tree_add_item(parentTree, hf_infiniband_smp_data, tvb, local_offset, 256, FALSE); local_offset += 256;
+    PERF_header_item = proto_tree_add_item(parentTree, hf_infiniband_smp_data, tvb, local_offset, MAD_DATA_SIZE, FALSE); local_offset += MAD_DATA_SIZE;
     proto_item_set_text(PERF_header_item, "%s", "VENDOR - Vendor Specific Management MAD (Dissector Not Implemented)");
+
     *offset = local_offset;
 }
 
@@ -1425,7 +1447,7 @@
         return;
     }
     local_offset = *offset;
-    PERF_header_item = proto_tree_add_item(parentTree, hf_infiniband_smp_data, tvb, local_offset, 256, FALSE); local_offset += 256;
+    PERF_header_item = proto_tree_add_item(parentTree, hf_infiniband_smp_data, tvb, local_offset, MAD_DATA_SIZE, FALSE); local_offset += MAD_DATA_SIZE;
     proto_item_set_text(PERF_header_item, "%s", "APP - Application Specific MAD (Dissector Not Implemented)");
     *offset = local_offset;
 }
@@ -1482,7 +1504,7 @@
     MadData->transactionID =        tvb_get_ntoh64(tvb, local_offset + 8);
     MadData->attributeID =          tvb_get_ntohs(tvb, local_offset + 16);
     MadData->attributeModifier =    tvb_get_ntohl(tvb, local_offset + 20);
-    tvb_memcpy(tvb, MadData->data, local_offset + 24, 232);
+    tvb_memcpy(tvb, MadData->data, local_offset + 24, MAD_DATA_SIZE);
 
     /* Populate the Dissector Tree */
 
@@ -1500,8 +1522,8 @@
     proto_tree_add_item(MAD_header_tree, hf_infiniband_attribute_id,        tvb, local_offset, 2, FALSE); local_offset+=2;
     proto_tree_add_item(MAD_header_tree, hf_infiniband_reserved16,          tvb, local_offset, 2, FALSE); local_offset+=2;
     proto_tree_add_item(MAD_header_tree, hf_infiniband_attribute_modifier,  tvb, local_offset, 4, FALSE); local_offset+=4;
-    proto_tree_add_item(MAD_header_tree, hf_infiniband_data,                tvb, local_offset, 232, FALSE); local_offset+=232;
-    *offset = (local_offset - 232); /* Move the offset back to the start of the Data field - this will be where the other parsers start. */
+    proto_tree_add_item(MAD_header_tree, hf_infiniband_data,                tvb, local_offset, MAD_DATA_SIZE, FALSE);
+    *offset = local_offset; /* Move the offset to the start of the Data field - this will be where the other parsers start. */
 
     return TRUE;
 }
@@ -1529,8 +1551,8 @@
     switch(RMPP_Type)
     {
         case RMPP_ILLEGAL:
-            proto_tree_add_item(RMPP_header_tree, hf_infiniband_rmpp_data1,     tvb, local_offset, 32, FALSE); local_offset+=32;
-            proto_tree_add_item(RMPP_header_tree, hf_infiniband_rmpp_data2,     tvb, local_offset, 32, FALSE); local_offset+=32;
+            proto_tree_add_item(RMPP_header_tree, hf_infiniband_rmpp_data1,     tvb, local_offset, 4, FALSE); local_offset+=4;
+            proto_tree_add_item(RMPP_header_tree, hf_infiniband_rmpp_data2,     tvb, local_offset, 4, FALSE); local_offset+=4;
             break;
         case RMPP_DATA:
             proto_tree_add_item(RMPP_header_tree, hf_infiniband_segment_number,     tvb, local_offset, 4, FALSE); local_offset+=4;
@@ -2988,6 +3010,83 @@
     proto_tree_add_item(ServiceAssociationRecord_header_tree, hf_infiniband_ServiceAssociationRecord_ServiceName,       tvb, local_offset, 64, FALSE); local_offset +=64;
 }
 
+/* Parse PortCounters MAD from the Performance management class.
+* IN:   parentTree - The tree to add the dissection to
+*       tvb - The tvbbuff of packet data
+*       offset - The offset in TVB where the attribute begins
+*       pinfo - The packet info structure with column information  */
+static void parse_PERF_PortCounters(proto_tree* parentTree, tvbuff_t* tvb, packet_info *pinfo, gint *offset)
+{
+    proto_item *perf_item = NULL;
+    proto_tree *perf_tree = NULL;
+    gint local_offset = *offset;
+
+    col_set_str(pinfo->cinfo, COL_INFO, "PERF (PortCounters)");
+
+    perf_item = proto_tree_add_item(parentTree, hf_infiniband_PortCounters, tvb, local_offset, 40, FALSE);
+    perf_tree = proto_item_add_subtree(perf_item, ett_perfclass);
+
+    local_offset += 40; /* skip reserved field */
+    local_offset += 1;  /* skip reserved field */
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCounters_PortSelect,  tvb, local_offset, 1, FALSE); local_offset += 1;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCounters_CounterSelect, tvb, local_offset, 2, FALSE); local_offset += 2;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCounters_SymbolErrorCounter, tvb, local_offset, 2, FALSE); local_offset += 2;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCounters_LinkErrorRecoveryCounter, tvb, local_offset, 1, FALSE); local_offset += 1;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCounters_LinkDownedCounter, tvb, local_offset, 1, FALSE); local_offset += 1;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCounters_PortRcvErrors, tvb, local_offset, 2, FALSE); local_offset += 2;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCounters_PortRcvRemotePhysicalErrors, tvb, local_offset, 2, FALSE); local_offset += 2;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCounters_PortRcvSwitchRelayErrors, tvb, local_offset, 2, FALSE); local_offset += 2;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCounters_PortXmitDiscards, tvb, local_offset, 2, FALSE); local_offset += 2;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCounters_PortXmitConstraintErrors, tvb, local_offset, 1, FALSE); local_offset += 1;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCounters_PortRcvConstraintErrors, tvb, local_offset, 1, FALSE); local_offset += 1;
+    local_offset += 1;  /* skip reserved field */
+    proto_tree_add_bits_item(perf_tree, hf_infiniband_PortCounters_LocalLinkIntegrityErrors, tvb, local_offset*8, 4, FALSE);
+    proto_tree_add_bits_item(perf_tree, hf_infiniband_PortCounters_ExcessiveBufferOverrunErrors, tvb, local_offset*8 + 4, 4, FALSE); local_offset += 1;
+    local_offset += 2;  /* skip reserved field */
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCounters_VL15Dropped, tvb, local_offset, 2, FALSE); local_offset += 2;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCounters_PortXmitData, tvb, local_offset, 4, FALSE); local_offset += 4;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCounters_PortRcvData, tvb, local_offset, 4, FALSE); local_offset += 4;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCounters_PortXmitPkts, tvb, local_offset, 4, FALSE); local_offset += 4;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCounters_PortRcvPkts, tvb, local_offset, 4, FALSE); local_offset += 4;
+
+    *offset = local_offset; /* update caller's offset to point to end of the PortCounters payload */
+    return;
+}
+
+/* Parse PortCountersExtended MAD from the Performance management class.
+* IN:   parentTree - The tree to add the dissection to
+*       tvb - The tvbbuff of packet data
+*       offset - The offset in TVB where the attribute begins
+*       pinfo - The packet info structure with column information  */
+static void parse_PERF_PortCountersExtended(proto_tree* parentTree, tvbuff_t* tvb, packet_info *pinfo, gint *offset)
+{
+    proto_item *perf_item = NULL;
+    proto_tree *perf_tree = NULL;
+    gint local_offset = *offset;
+
+    col_set_str(pinfo->cinfo, COL_INFO, "PERF (PortCountersExtended)");
+
+    perf_item = proto_tree_add_item(parentTree, hf_infiniband_PortCountersExt, tvb, local_offset, 72, FALSE);
+    perf_tree = proto_item_add_subtree(perf_item, ett_perfclass);
+
+    local_offset += 40; /* skip reserved field */
+    local_offset += 1;  /* skip reserved field */
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCountersExt_PortSelect,  tvb, local_offset, 1, FALSE); local_offset += 1;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCountersExt_CounterSelect, tvb, local_offset, 2, FALSE); local_offset += 2;
+    local_offset += 4;  /* skip reserved field */
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCountersExt_PortXmitData, tvb, local_offset, 8, FALSE); local_offset += 8;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCountersExt_PortRcvData, tvb, local_offset, 8, FALSE); local_offset += 8;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCountersExt_PortXmitPkts, tvb, local_offset, 8, FALSE); local_offset += 8;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCountersExt_PortRcvPkts, tvb, local_offset, 8, FALSE); local_offset += 8;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCountersExt_PortUnicastXmitPkts, tvb, local_offset, 8, FALSE); local_offset += 8;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCountersExt_PortUnicastRcvPkts, tvb, local_offset, 8, FALSE); local_offset += 8;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCountersExt_PortMulticastXmitPkts, tvb, local_offset, 8, FALSE); local_offset += 8;
+    proto_tree_add_item(perf_tree, hf_infiniband_PortCountersExt_PortMulticastRcvPkts, tvb, local_offset, 8, FALSE); local_offset += 8;
+
+    *offset = local_offset; /* update caller's offset to point to end of the PortCountersExt payload */
+    return;
+}
+
 /* dissect_general_info
 * Used to extract very few values from the packet in the case that full dissection is disabled by the user.
 * IN:
@@ -3007,7 +3106,6 @@
     guint8 management_class = 0;
     MAD_Data MadData;
 
-
     virtualLane =  tvb_get_guint8(tvb, offset);
     virtualLane = virtualLane & 0xF0;
     offset+=1;
@@ -3018,17 +3116,13 @@
     offset+=1;
 
     /* Set destination in packet view. */
-    if (check_col(pinfo->cinfo, COL_DEF_DST))
-    {
-        col_add_fstr(pinfo->cinfo, COL_DEF_DST, "DLID: %s", tvb_bytes_to_str(tvb, offset, 2));
-    }
+    g_snprintf(dst_addr_str, ADDR_STR_MAX_LEN, "DLID: %d", tvb_get_ntohs(tvb, offset));
+    SET_ADDRESS(&pinfo->dst, AT_STRINGZ, (int)strlen(dst_addr_str)+1, dst_addr_str);
     offset+=4;
 
     /* Set Source in packet view. */
-    if (check_col(pinfo->cinfo, COL_DEF_SRC))
-    {
-        col_add_fstr(pinfo->cinfo, COL_DEF_SRC, "SLID: %s", tvb_bytes_to_str(tvb, offset, 2));
-    }
+    g_snprintf(src_addr_str, ADDR_STR_MAX_LEN, "SLID: %d", tvb_get_ntohs(tvb, offset));
+    SET_ADDRESS(&pinfo->src, AT_STRINGZ, (int)strlen(src_addr_str)+1, src_addr_str);
     offset+=2;
 
     switch(lnh_val)
@@ -3039,17 +3133,19 @@
             offset += 2;
 
             tvb_get_ipv6(tvb, offset, &SRCgid);
-            if (check_col(pinfo->cinfo, COL_DEF_SRC))
-            {
-                col_add_fstr(pinfo->cinfo, COL_DEF_SRC, "SGID: %s", ip6_to_str(&SRCgid));
-            }
+
+            /* Set source GID in packet view. */
+            g_snprintf(src_addr_str, ADDR_STR_MAX_LEN, "SGID: %s", ip6_to_str(&SRCgid));
+            SET_ADDRESS(&pinfo->src, AT_STRINGZ, (int)strlen(src_addr_str)+1, src_addr_str);
+
             offset += 16;
 
             tvb_get_ipv6(tvb, offset, &DSTgid);
-            if (check_col(pinfo->cinfo, COL_DEF_DST))
-            {
-                col_add_fstr(pinfo->cinfo, COL_DEF_DST, "DGID: %s", ip6_to_str(&DSTgid));
-            }
+            
+            /* Set destination GID in packet view. */
+            g_snprintf(dst_addr_str, ADDR_STR_MAX_LEN, "DGID: %s", ip6_to_str(&DSTgid));
+            SET_ADDRESS(&pinfo->dst, AT_STRINGZ, (int)strlen(dst_addr_str)+1, dst_addr_str);
+
             offset += 16;
 
             if(nxtHdr != 0x1B)
@@ -3075,11 +3171,8 @@
             break;
         case IP_NON_IBA:
             /* Raw IPv6 Packet */
-            if (check_col(pinfo->cinfo, COL_DEF_DST))
-            {
-                col_set_str(pinfo->cinfo, COL_DEF_DST, "IPv6 over IB Packet");
-                col_set_fence(pinfo->cinfo, COL_DEF_DST);
-            }
+            g_snprintf(dst_addr_str, ADDR_STR_MAX_LEN, "IPv6 over IB Packet");
+            SET_ADDRESS(&pinfo->dst, AT_STRINGZ, (int)strlen(dst_addr_str)+1, dst_addr_str);
             break;
         case RAW:
             break;
@@ -3225,6 +3318,19 @@
     /* XXX: ToDo: Verify against Infiniband 1.2.1 Specification                           */
     /*            Fields verified/corrected: Those after comment "XX: All following ..."  */
 
+    /* meanings for MAD method field */
+    static const value_string mad_method_str[] = {
+        { 0x01, "Get()" },
+        { 0x02, "Set()" },
+        { 0x81, "GetResp()" },
+        { 0x03, "Send()" },
+        { 0x05, "Trap()" },
+        { 0x06, "Report()" },
+        { 0x86, "ReportResp()" },
+        { 0x07, "TrapRepress()" },
+        { 0,    NULL }
+    };
+
     static hf_register_info hf[] = {    
         /* Local Route Header (LRH) */
         { &hf_infiniband_LRH, {
@@ -3528,7 +3634,7 @@
 #endif
         { &hf_infiniband_method, {
                 "Method", "infiniband.mad.method",
-                FT_UINT8, BASE_HEX, NULL, 0x7F, NULL, HFILL}
+                FT_UINT8, BASE_HEX, VALS(mad_method_str), 0x0, NULL, HFILL}
         },
         { &hf_infiniband_status, {
                 "Status", "infiniband.mad.status",
@@ -3715,7 +3821,6 @@
                 "Subnet Admin Data", "infiniband.sa.subnetadmindata",
                 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}
         },
-
         /* NodeDescription */
         { &hf_infiniband_NodeDescription_NodeString, {
                 "NodeString", "infiniband.nodedescription.nodestring",
@@ -4869,6 +4974,161 @@
         { &hf_infiniband_Trap_SWLIDADDR, {
                 "SWLIDADDR", "infiniband.trap.swlidaddr",
                 FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}
+        },
+        /* PortCounters in Performance class */
+        { &hf_infiniband_PortCounters, {
+                "Port Counters (Performance Management MAD)", "infiniband.portcounters",
+                FT_NONE, BASE_NONE, NULL, 0x0,
+                "Performance class PortCounters packet", HFILL}
+        },
+        { &hf_infiniband_PortCounters_PortSelect, {
+                "PortSelect", "infiniband.portcounters.portselect",
+                FT_UINT8, BASE_HEX, NULL, 0x0,
+                "Selects the port that will be accessed", HFILL}
+        },
+        { &hf_infiniband_PortCounters_CounterSelect, {
+                "CounterSelect", "infiniband.portcounters.counterselect",
+                FT_UINT16, BASE_HEX, NULL, 0x0,
+                "When writing, selects which counters are affected by the operation", HFILL}
+        },
+        { &hf_infiniband_PortCounters_SymbolErrorCounter, {
+                "SymbolErrorCounter", "infiniband.portcounters.symbolerrorcounter",
+                FT_UINT16, BASE_DEC, NULL, 0x0,
+                "Total number of minor link errors", HFILL}
+        },
+        { &hf_infiniband_PortCounters_LinkErrorRecoveryCounter, {
+                "LinkErrorRecoveryCounter", "infiniband.portcounters.linkerrorrecoverycounter",
+                FT_UINT8, BASE_DEC, NULL, 0x0,
+                "Total number of times successfully completed link error recovery process", HFILL}
+        },
+        { &hf_infiniband_PortCounters_LinkDownedCounter, {
+                "LinkDownedCounter", "infiniband.portcounters.linkdownedcounter",
+                FT_UINT8, BASE_DEC, NULL, 0x0,
+                "Total number of times failed link error recovery process", HFILL}
+        },
+        { &hf_infiniband_PortCounters_PortRcvErrors, {
+                "PortRcvErrors", "infiniband.portcounters.portrcverrors",
+                FT_UINT16, BASE_DEC, NULL, 0x0,
+                "Total number of packets containing an error received", HFILL}
+        },
+        { &hf_infiniband_PortCounters_PortRcvRemotePhysicalErrors, {
+                "PortRcvRemotePhysicalErrors", "infiniband.portcounters.portrcvremotephysicalerrors",
+                FT_UINT16, BASE_DEC, NULL, 0x0,
+                "Total number of packets marked with EBP delimiter received", HFILL}
+        },
+        { &hf_infiniband_PortCounters_PortRcvSwitchRelayErrors, {
+                "PortRcvSwitchRelayErrors", "infiniband.portcounters.portrcvswitchrelayerrors",
+                FT_UINT16, BASE_DEC, NULL, 0x0,
+                "Total number of packets number of packets discarded because they could not be forwarded by switch relay", 
+                HFILL}
+        },
+        { &hf_infiniband_PortCounters_PortXmitDiscards, {
+                "PortXmitDiscards", "infiniband.portcounters.portxmitdiscards",
+                FT_UINT16, BASE_DEC, NULL, 0x0,
+                "Total number of outbound packets discarded", HFILL}
+        },
+        { &hf_infiniband_PortCounters_PortXmitConstraintErrors, {
+                "PortXmitConstraintErrors", "infiniband.portcounters.portxmitconstrainterrors",
+                FT_UINT8, BASE_DEC, NULL, 0x0,
+                "Total number of packets not transmitted from the switch physical port", HFILL}
+        },
+        { &hf_infiniband_PortCounters_PortRcvConstraintErrors, {
+                "PortRcvConstraintErrors", "infiniband.portcounters.portrcvconstrainterrors",
+                FT_UINT8, BASE_DEC, NULL, 0x0,
+                "Total number of packets received on the switch physical port that are discarded", HFILL}
+        },
+        { &hf_infiniband_PortCounters_LocalLinkIntegrityErrors, {
+                "LocalLinkIntegrityErrors", "infiniband.portcounters.locallinkintegrityerrors",
+                FT_UINT8, BASE_DEC, NULL, 0x0,
+                "The number of times the count of local physical errors exceeded the threshold specified by LocalPhyErrors",
+                HFILL}
+        },
+        { &hf_infiniband_PortCounters_ExcessiveBufferOverrunErrors, {
+                "ExcessiveBufferOverrunErrors", "infiniband.portcounters.excessivebufferoverrunerrors",
+                FT_UINT8, BASE_DEC, NULL, 0x0,
+                "The number of times that OverrunErrors consecutive flow control update periods occured",
+                HFILL}
+        },
+        { &hf_infiniband_PortCounters_VL15Dropped, {
+                "VL15Dropped", "infiniband.portcounters.vl15dropped",
+                FT_UINT16, BASE_DEC, NULL, 0x0,
+                "Number of incoming VL15 packets dropped", HFILL}
+        },
+        { &hf_infiniband_PortCounters_PortXmitData, {
+                "PortXmitData", "infiniband.portcounters.portxmitdata",
+                FT_UINT32, BASE_DEC, NULL, 0x0,
+                "Total number of data octets, divided by 4, transmitted on all VLs from the port", HFILL}
+        },
+        { &hf_infiniband_PortCounters_PortRcvData, {
+                "PortRcvData", "infiniband.portcounters.portrcvdata",
+                FT_UINT32, BASE_DEC, NULL, 0x0,
+                "Total number of data octets, divided by 4, received on all VLs at the port", HFILL}
+        },
+        { &hf_infiniband_PortCounters_PortXmitPkts, {
+                "PortXmitPkts", "infiniband.portcounters.portxmitpkts",
+                FT_UINT32, BASE_DEC, NULL, 0x0,
+                "Total number of packets transmitted on all VLs from the port", HFILL}
+        },
+        { &hf_infiniband_PortCounters_PortRcvPkts, {
+                "PortRcvPkts", "infiniband.portcounters.portrcvpkts",
+                FT_UINT32, BASE_DEC, NULL, 0x0,
+                "Total number of packets received from all VLs on the port", HFILL}
+        },
+        /* PortCountersExtended in Performance class */
+        { &hf_infiniband_PortCountersExt, {
+                "Port Counters Extended (Performance Management MAD)", "infiniband.portcounters_ext",
+                FT_NONE, BASE_NONE, NULL, 0x0,
+                "Performance class PortCountersExtended packet", HFILL}
+        },
+        { &hf_infiniband_PortCountersExt_PortSelect, {
+                "PortSelect", "infiniband.portcounters_ext.portselect",
+                FT_UINT8, BASE_HEX, NULL, 0x0,
+                "Selects the port that will be accessed", HFILL}
+        },
+        { &hf_infiniband_PortCountersExt_CounterSelect, {
+                "CounterSelect", "infiniband.portcounters_ext.counterselect",
+                FT_UINT16, BASE_HEX, NULL, 0x0,
+                "When writing, selects which counters are affected by the operation", HFILL}
+        },
+        { &hf_infiniband_PortCountersExt_PortXmitData, {
+                "PortXmitData", "infiniband.portcounters_ext.portxmitdata",
+                FT_UINT64, BASE_DEC, NULL, 0x0,
+                "Total number of data octets, divided by 4, transmitted on all VLs from the port", HFILL}
+        },
+        { &hf_infiniband_PortCountersExt_PortRcvData, {
+                "PortRcvData", "infiniband.portcounters_ext.portrcvdata",
+                FT_UINT64, BASE_DEC, NULL, 0x0,
+                "Total number of data octets, divided by 4, received on all VLs at the port", HFILL}
+        },
+        { &hf_infiniband_PortCountersExt_PortXmitPkts, {
+                "PortXmitPkts", "infiniband.portcounters_ext.portxmitpkts",
+                FT_UINT64, BASE_DEC, NULL, 0x0,
+                "Total number of packets transmitted on all VLs from the port", HFILL}
+        },
+        { &hf_infiniband_PortCountersExt_PortRcvPkts, {
+                "PortRcvPkts", "infiniband.portcounters_ext.portrcvpkts",
+                FT_UINT64, BASE_DEC, NULL, 0x0,
+                "Total number of packets received from all VLs on the port", HFILL}
+        },
+        { &hf_infiniband_PortCountersExt_PortUnicastXmitPkts, {
+                "PortUnicastXmitPkts", "infiniband.portcounters_ext.portunicastxmitpkts",
+                FT_UINT64, BASE_DEC, NULL, 0x0,
+                "Total number of unicast packets transmitted on all VLs from the port", HFILL}
+        },
+        { &hf_infiniband_PortCountersExt_PortUnicastRcvPkts, {
+                "PortUnicastRcvPkts", "infiniband.portcounters_ext.portunicastrcvpkts",
+                FT_UINT64, BASE_DEC, NULL, 0x0,
+                "Total number of unicast packets received from all VLs on the port", HFILL}
+        },
+        { &hf_infiniband_PortCountersExt_PortMulticastXmitPkts, {
+                "PortMulticastXmitPkts", "infiniband.portcounters_ext.portmulticastxmitpkts",
+                FT_UINT64, BASE_DEC, NULL, 0x0,
+                "Total number of multicast packets transmitted on all VLs from the port", HFILL}
+        },
+        { &hf_infiniband_PortCountersExt_PortMulticastRcvPkts, {
+                "PortMulticastRcvPkts", "infiniband.portcounters_ext.portmulticastrcvpkts",
+                FT_UINT64, BASE_DEC, NULL, 0x0,
+                "Total number of multicast packets received from all VLs on the port", HFILL}
         }
     };
 
@@ -4924,6 +5184,7 @@
         &ett_tracerecord,
         &ett_multipathrecord,
         &ett_serviceassocrecord,
+        &ett_perfclass,
     };
 
     static hf_register_info hf_link[] = {    
@@ -4960,13 +5221,11 @@
     proto_register_field_array(proto_infiniband, hf, array_length(hf));
     proto_register_subtree_array(ett, array_length(ett));
 
-
     proto_infiniband_link = proto_register_protocol("InfiniBand Link", "InfiniBand Link", "infiniband_link");
     register_dissector("infiniband_link", dissect_infiniband_link, proto_infiniband_link);
 
     proto_register_field_array(proto_infiniband_link, hf_link, array_length(hf_link));
     proto_register_subtree_array(ett_link_array, array_length(ett_link_array));
-
 }
 
 /* Reg Handoff.  Register dissectors we'll need for IPoIB */
Index: epan/dissectors/packet-infiniband.h
===================================================================
--- epan/dissectors/packet-infiniband.h	(revision 32537)
+++ epan/dissectors/packet-infiniband.h	(working copy)
@@ -8,6 +8,8 @@
  * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
  *
+ * Modified 2010 by Mellanox Technologies Ltd.
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
@@ -27,7 +29,6 @@
 
 #define PROTO_TAG_INFINIBAND    "Infiniband"
 
-#include <epan/etypes.h>
 
 /* Wireshark ID */
 static int proto_infiniband = -1;
@@ -84,6 +85,7 @@
 static gint ett_tracerecord = -1;
 static gint ett_multipathrecord = -1;
 static gint ett_serviceassocrecord = -1;
+static gint ett_perfclass = -1;
 
 static gint ett_link = -1;
 
@@ -119,14 +121,14 @@
 /* Parsing Methods for specific IB headers. */
 
 static void parse_VENDOR(proto_tree *, tvbuff_t *, gint *);
-static void parse_PAYLOAD(proto_tree *, packet_info *, tvbuff_t *, gint *, gint length, guint8 virtualLane);
+static void parse_PAYLOAD(proto_tree *, packet_info *, tvbuff_t *, gint *, gint length, gint src_qp, gint dst_qp);
 static void parse_IETH(proto_tree *, tvbuff_t *, gint *);
 static void parse_IMMDT(proto_tree *, tvbuff_t *, gint *offset);
 static void parse_ATOMICACKETH(proto_tree *, tvbuff_t *, gint *offset);
 static void parse_AETH(proto_tree *, tvbuff_t *, gint *offset);
 static void parse_ATOMICETH(proto_tree *, tvbuff_t *, gint *offset);
 static void parse_RETH(proto_tree *, tvbuff_t *, gint *offset);
-static void parse_DETH(proto_tree *, tvbuff_t *, gint *offset);
+static void parse_DETH(proto_tree *, tvbuff_t *, gint *offset, gint* src_qp);
 static void parse_RDETH(proto_tree *, tvbuff_t *, gint *offset);
 static void parse_IPvSix(proto_tree *, tvbuff_t *, gint *offset, packet_info *);
 static void parse_RWH(proto_tree *, tvbuff_t *, gint *offset, packet_info *);
@@ -134,7 +136,7 @@
 static void parse_SUBN_LID_ROUTED(proto_tree *, packet_info *, tvbuff_t *, gint *offset);
 static void parse_SUBN_DIRECTED_ROUTE(proto_tree *, packet_info *, tvbuff_t *, gint *offset);
 static void parse_SUBNADMN(proto_tree *, packet_info *, tvbuff_t *, gint *offset);
-static void parse_PERF(proto_tree *, tvbuff_t *, gint *offset);
+static void parse_PERF(proto_tree *, tvbuff_t *, packet_info *, gint *offset);
 static void parse_BM(proto_tree *, tvbuff_t *, gint *offset);
 static void parse_DEV_MGT(proto_tree *, tvbuff_t *, gint *offset);
 static void parse_COM_MGT(proto_tree *, tvbuff_t *, gint *offset);
@@ -175,6 +177,14 @@
 static void parse_LedInfo(proto_tree*, tvbuff_t*, gint *offset);
 static void parse_LinkSpeedWidthPairsTable(proto_tree*, tvbuff_t*, gint *offset);
 
+/* These methods parse individual attributes for specific MAD management classes.
+* Naming convention FunctionHandle = "parse_" + [Management Class] + "_" + [Attribute Name]; 
+* Where [Management Class] is the shorthand name for the management class as defined
+* in the MAD Management Classes section below in this file, and [Attribute Name] is the
+* attribute identifier from the corresponding chapter of the IB Specification */
+static void parse_PERF_PortCounters(proto_tree* parentTree, tvbuff_t* tvb, packet_info *pinfo, gint *offset);
+static void parse_PERF_PortCountersExtended(proto_tree* parentTree, tvbuff_t* tvb, packet_info *pinfo, gint *offset);
+
 /* Subnet Administration */
 static void parse_InformInfo(proto_tree*, tvbuff_t*, gint *offset);
 static void parse_LinkRecord(proto_tree*, tvbuff_t*, gint *offset);
@@ -877,6 +887,40 @@
 /* static int hf_infiniband_Notice_IssuerGID = -1;             */
 /* static int hf_infiniband_Notice_ClassTrapSpecificData = -1; */
 
+/* PortCounters attribute in Performance class */
+static int hf_infiniband_PortCounters = -1;
+static int hf_infiniband_PortCounters_PortSelect = -1;
+static int hf_infiniband_PortCounters_CounterSelect = -1;
+static int hf_infiniband_PortCounters_SymbolErrorCounter = -1;
+static int hf_infiniband_PortCounters_LinkErrorRecoveryCounter = -1;
+static int hf_infiniband_PortCounters_LinkDownedCounter = -1;
+static int hf_infiniband_PortCounters_PortRcvErrors = -1;
+static int hf_infiniband_PortCounters_PortRcvRemotePhysicalErrors = -1;
+static int hf_infiniband_PortCounters_PortRcvSwitchRelayErrors = -1;
+static int hf_infiniband_PortCounters_PortXmitDiscards = -1;
+static int hf_infiniband_PortCounters_PortXmitConstraintErrors = -1;
+static int hf_infiniband_PortCounters_PortRcvConstraintErrors = -1;
+static int hf_infiniband_PortCounters_LocalLinkIntegrityErrors = -1;
+static int hf_infiniband_PortCounters_ExcessiveBufferOverrunErrors = -1;
+static int hf_infiniband_PortCounters_VL15Dropped = -1;
+static int hf_infiniband_PortCounters_PortXmitData = -1;
+static int hf_infiniband_PortCounters_PortRcvData = -1;
+static int hf_infiniband_PortCounters_PortXmitPkts = -1;
+static int hf_infiniband_PortCounters_PortRcvPkts = -1;
+
+/* Extended PortCounters attribute in Performance class */
+static int hf_infiniband_PortCountersExt = -1;
+static int hf_infiniband_PortCountersExt_PortSelect = -1;
+static int hf_infiniband_PortCountersExt_CounterSelect = -1;
+static int hf_infiniband_PortCountersExt_PortXmitData = -1;
+static int hf_infiniband_PortCountersExt_PortRcvData = -1;
+static int hf_infiniband_PortCountersExt_PortXmitPkts = -1;
+static int hf_infiniband_PortCountersExt_PortRcvPkts = -1;
+static int hf_infiniband_PortCountersExt_PortUnicastXmitPkts = -1;
+static int hf_infiniband_PortCountersExt_PortUnicastRcvPkts = -1;
+static int hf_infiniband_PortCountersExt_PortMulticastXmitPkts = -1;
+static int hf_infiniband_PortCountersExt_PortMulticastRcvPkts = -1;
+
 /* Notice DataDetails and ClassTrapSpecific Data for certain traps 
 * Note that traps reuse many fields, so they are only declared once under the first trap that they appear.
 * There is no need to redeclare them for specific Traps (as with other SA Attributes) because they are uniform between Traps. */
@@ -994,6 +1038,10 @@
 #define APPLICATION_START 0x10      /* Start of Application Specific Range */
 #define APPLICATION_END 0x2F        /* End of Application Specific Range */
 
+/* Performance class Attributes */
+#define ATTR_PORT_COUNTERS      0x0012
+#define ATTR_PORT_COUNTERS_EXT  0x001D
+
 /* Link Next Header Values */
 #define IBA_GLOBAL 3
 #define IBA_LOCAL  2
@@ -1318,4 +1366,10 @@
 * RC_ACKNOWLEDGE
 * }; */
 
+static gchar *src_addr_str = NULL,     /* the string to be displayed in the source/destination columns */
+             *dst_addr_str = NULL;     /* will be stored here */
+
+#define MAD_DATA_SIZE     232     /* size of data field a MAD payload carries */
+#define ADDR_STR_MAX_LEN  33      /* maximum length of src_addr_str and dst_addr_str */
+
 #endif
