/* packet-opa.c * Routines for Omni-Path 9B L2, L4, and extended L4 header dissection * Copyright (c) 2016, Intel Corporation. * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "config.h" #include #include void proto_reg_handoff_opa_9b(void); void proto_register_opa_9b(void); /* OpCodeValues * Code Bits [7-5] Connection Type * [4-0] Message Type * Reliable Connection (RC) [7-5] = 000 */ #define RC_SEND_FIRST 0 /*0x00000000 */ #define RC_SEND_MIDDLE 1 /*0x00000001 */ #define RC_SEND_LAST 2 /*0x00000010 */ #define RC_SEND_LAST_IMM 3 /*0x00000011 */ #define RC_SEND_ONLY 4 /*0x00000100 */ #define RC_SEND_ONLY_IMM 5 /*0x00000101 */ #define RC_RDMA_WRITE_FIRST 6 /*0x00000110 */ #define RC_RDMA_WRITE_MIDDLE 7 /*0x00000111 */ #define RC_RDMA_WRITE_LAST 8 /*0x00001000 */ #define RC_RDMA_WRITE_LAST_IMM 9 /*0x00001001 */ #define RC_RDMA_WRITE_ONLY 10 /*0x00001010 */ #define RC_RDMA_WRITE_ONLY_IMM 11 /*0x00001011 */ #define RC_RDMA_READ_REQUEST 12 /*0x00001100 */ #define RC_RDMA_READ_RESPONSE_FIRST 13 /*0x00001101 */ #define RC_RDMA_READ_RESPONSE_MIDDLE 14 /*0x00001110 */ #define RC_RDMA_READ_RESPONSE_LAST 15 /*0x00001111 */ #define RC_RDMA_READ_RESPONSE_ONLY 16 /*0x00010000 */ #define RC_ACKNOWLEDGE 17 /*0x00010001 */ #define RC_ATOMIC_ACKNOWLEDGE 18 /*0x00010010 */ #define RC_CMP_SWAP 19 /*0x00010011 */ #define RC_FETCH_ADD 20 /*0x00010100 */ #define RC_SEND_LAST_INVAL 22 /*0x00010110 */ #define RC_SEND_ONLY_INVAL 23 /*0x00010111 */ /* Reliable Datagram (RD) [7-5] = 010 */ #define RD_SEND_FIRST 64 /*0x01000000 */ #define RD_SEND_MIDDLE 65 /*0x01000001 */ #define RD_SEND_LAST 66 /*0x01000010 */ #define RD_SEND_LAST_IMM 67 /*0x01000011 */ #define RD_SEND_ONLY 68 /*0x01000100 */ #define RD_SEND_ONLY_IMM 69 /*0x01000101 */ #define RD_RDMA_WRITE_FIRST 70 /*0x01000110 */ #define RD_RDMA_WRITE_MIDDLE 71 /*0x01000111 */ #define RD_RDMA_WRITE_LAST 72 /*0x01001000 */ #define RD_RDMA_WRITE_LAST_IMM 73 /*0x01001001 */ #define RD_RDMA_WRITE_ONLY 74 /*0x01001010 */ #define RD_RDMA_WRITE_ONLY_IMM 75 /*0x01001011 */ #define RD_RDMA_READ_REQUEST 76 /*0x01001100 */ #define RD_RDMA_READ_RESPONSE_FIRST 77 /*0x01001101 */ #define RD_RDMA_READ_RESPONSE_MIDDLE 78 /*0x01001110 */ #define RD_RDMA_READ_RESPONSE_LAST 79 /*0x01001111 */ #define RD_RDMA_READ_RESPONSE_ONLY 80 /*0x01010000 */ #define RD_ACKNOWLEDGE 81 /*0x01010001 */ #define RD_ATOMIC_ACKNOWLEDGE 82 /*0x01010010 */ #define RD_CMP_SWAP 83 /*0x01010011 */ #define RD_FETCH_ADD 84 /*0x01010100 */ #define RD_RESYNC 85 /*0x01010101 */ /* Unreliable Datagram (UD) [7-5] = 011 */ #define UD_SEND_ONLY 100 /*0x01100100 */ #define UD_SEND_ONLY_IMM 101 /*0x01100101 */ /* Unreliable Connection (UC) [7-5] = 001 */ #define UC_SEND_FIRST 32 /*0x00100000 */ #define UC_SEND_MIDDLE 33 /*0x00100001 */ #define UC_SEND_LAST 34 /*0x00100010 */ #define UC_SEND_LAST_IMM 35 /*0x00100011 */ #define UC_SEND_ONLY 36 /*0x00100100 */ #define UC_SEND_ONLY_IMM 37 /*0x00100101 */ #define UC_RDMA_WRITE_FIRST 38 /*0x00100110 */ #define UC_RDMA_WRITE_MIDDLE 39 /*0x00100111 */ #define UC_RDMA_WRITE_LAST 40 /*0x00101000 */ #define UC_RDMA_WRITE_LAST_IMM 41 /*0x00101001 */ #define UC_RDMA_WRITE_ONLY 42 /*0x00101010 */ #define UC_RDMA_WRITE_ONLY_IMM 43 /*0x00101011 */ /* Header Ordering Based on OPCODES */ #define RDETH_DETH_PAYLD 0 #define RDETH_DETH_RETH_PAYLD 1 #define RDETH_DETH_IMMDT_PAYLD 2 #define RDETH_DETH_RETH_IMMDT_PAYLD 3 #define RDETH_DETH_RETH 4 #define RDETH_AETH_PAYLD 5 #define RDETH_PAYLD 6 #define RDETH_AETH 7 #define RDETH_AETH_ATOMICACKETH 8 #define RDETH_DETH_ATOMICETH 9 #define RDETH_DETH 10 #define DETH_PAYLD 11 #define DETH_IMMDT_PAYLD 12 #define PAYLD 13 #define IMMDT_PAYLD 14 #define RETH_PAYLD 15 #define RETH_IMMDT_PAYLD 16 #define RETH 17 #define AETH_PAYLD 18 #define AETH 19 #define AETH_ATOMICACKETH 20 #define ATOMICETH 21 #define IETH_PAYLD 22 #define KDETH_PSM 23 #define KDETH_TIDRDMA 24 /* PSM */ #define PSM_RESERVED 0xC0 #define PSM_TINY 0xC1 #define PSM_SHORT 0xC2 #define PSM_MEDIUM 0xC3 #define PSM_MEDIUM_DATA 0xC4 #define PSM_LONG_RTS 0xC5 #define PSM_LONG_CTS 0xC6 #define PSM_LONG_DATA 0xC7 #define PSM_TIDS_GRANT 0xC8 #define PSM_TIDS_GRANT_ACK 0xC9 #define PSM_TIDS_RELEASE 0xCA #define PSM_TIDS_RELEASE_CONFIRM 0xCB #define PSM_EXPTID_UNALIGNED 0xCC #define PSM_EXPTID 0xCD #define PSM_ACK 0xCE #define PSM_NAK 0xCF #define PSM_ERR_CHK 0xD0 #define PSM_ERR_CHK_BAD 0xD1 #define PSM_ERR_CHK_GEN 0xD2 #define PSM_FLOW_CCA_BECN 0xD3 #define PSM_CONNECT_REQUEST 0xD4 #define PSM_CONNECT_REPLY 0xD5 #define PSM_DISCONNECT_REQUEST 0xD6 #define PSM_DISCONNECT_REPLY 0xD7 #define PSM_AM_REQUEST_NOREPLY 0xD8 #define PSM_AM_REQUEST 0xD9 #define PSM_AM_REPLY 0xDA /* TID RDMA */ #define TID_RDMA_WRITE_REQUEST 0xE0 #define TID_RDMA_WRITE_RESPONSE 0xE1 #define TID_RDMA_WRITE_DATA 0xE2 #define TID_RDMA_WRITE_DATA_LAST 0xE3 #define TID_RDMA_READ_REQUEST 0xE4 #define TID_RDMA_READ_RESPONSE 0xE5 #define TID_RDMA_RESYNC 0xE6 #define TID_RDMA_ACK 0xE7 /* Array of all availavle OpCodes to make matching a bit easier. The OpCodes * dictate the header sequence following in the packet. These arrays tell the * dissector which headers must be decoded for the given OpCode. */ static guint32 opCode_RDETH_DETH_ATOMICETH[] = { RD_CMP_SWAP, RD_FETCH_ADD }; static guint32 opCode_IETH_PAYLD[] = { RC_SEND_LAST_INVAL, RC_SEND_ONLY_INVAL }; static guint32 opCode_ATOMICETH[] = { RC_CMP_SWAP, RC_FETCH_ADD }; static guint32 opCode_RDETH_DETH_RETH_PAYLD[] = { RD_RDMA_WRITE_FIRST, RD_RDMA_WRITE_ONLY }; static guint32 opCode_RETH_IMMDT_PAYLD[] = { RC_RDMA_WRITE_ONLY_IMM, UC_RDMA_WRITE_ONLY_IMM }; static guint32 opCode_RDETH_DETH_IMMDT_PAYLD[] = { RD_SEND_LAST_IMM, RD_SEND_ONLY_IMM, RD_RDMA_WRITE_LAST_IMM }; static guint32 opCode_RDETH_AETH_PAYLD[] = { RD_RDMA_READ_RESPONSE_FIRST, RD_RDMA_READ_RESPONSE_LAST, RD_RDMA_READ_RESPONSE_ONLY }; static guint32 opCode_AETH_PAYLD[] = { RC_RDMA_READ_RESPONSE_FIRST, RC_RDMA_READ_RESPONSE_LAST, RC_RDMA_READ_RESPONSE_ONLY }; static guint32 opCode_RETH_PAYLD[] = { RC_RDMA_WRITE_FIRST, RC_RDMA_WRITE_ONLY, UC_RDMA_WRITE_FIRST, UC_RDMA_WRITE_ONLY }; static guint32 opCode_RDETH_DETH_PAYLD[] = { RD_SEND_FIRST, RD_SEND_MIDDLE, RD_SEND_LAST, RD_SEND_ONLY, RD_RDMA_WRITE_MIDDLE, RD_RDMA_WRITE_LAST }; static guint32 opCode_IMMDT_PAYLD[] = { RC_SEND_LAST_IMM, RC_SEND_ONLY_IMM, RC_RDMA_WRITE_LAST_IMM, UC_SEND_LAST_IMM, UC_SEND_ONLY_IMM, UC_RDMA_WRITE_LAST_IMM }; static guint32 opCode_PAYLD[] = { RC_SEND_FIRST, RC_SEND_MIDDLE, RC_SEND_LAST, RC_SEND_ONLY, RC_RDMA_WRITE_MIDDLE, RC_RDMA_WRITE_LAST, RC_RDMA_READ_RESPONSE_MIDDLE, UC_SEND_FIRST, UC_SEND_MIDDLE, UC_SEND_LAST, UC_SEND_ONLY, UC_RDMA_WRITE_MIDDLE, UC_RDMA_WRITE_LAST }; static guint32 opCode_PSM[] = { PSM_RESERVED, PSM_TINY, PSM_SHORT, PSM_MEDIUM, PSM_MEDIUM_DATA, PSM_LONG_RTS, PSM_LONG_CTS, PSM_LONG_DATA, PSM_TIDS_GRANT, PSM_TIDS_GRANT_ACK, PSM_TIDS_RELEASE, PSM_TIDS_RELEASE_CONFIRM, PSM_EXPTID_UNALIGNED, PSM_EXPTID, PSM_ACK, PSM_NAK, PSM_ERR_CHK, PSM_ERR_CHK_BAD, PSM_ERR_CHK_GEN, PSM_FLOW_CCA_BECN, PSM_CONNECT_REQUEST, PSM_CONNECT_REPLY, PSM_DISCONNECT_REQUEST, PSM_DISCONNECT_REPLY, PSM_AM_REQUEST_NOREPLY, PSM_AM_REQUEST, PSM_AM_REPLY }; static guint opCode_TIDRDMA[] = { TID_RDMA_WRITE_REQUEST, TID_RDMA_WRITE_RESPONSE, TID_RDMA_WRITE_DATA, TID_RDMA_WRITE_DATA_LAST, TID_RDMA_READ_REQUEST, TID_RDMA_READ_RESPONSE, TID_RDMA_RESYNC, TID_RDMA_ACK }; /* OP Codes */ static const value_string vals_opa_bth_opcode[] = { { RC_SEND_FIRST, "RC Send First" }, { RC_SEND_MIDDLE, "RC Send Middle" }, { RC_SEND_LAST, "RC Send Last" }, { RC_SEND_LAST_IMM, "RC Send Last Immediate" }, { RC_SEND_ONLY, "RC Send Only" }, { RC_SEND_ONLY_IMM, "RC Send Only Immediate" }, { RC_RDMA_WRITE_FIRST, "RC RDMA Write First" }, { RC_RDMA_WRITE_MIDDLE, "RC RDMA Write Middle" }, { RC_RDMA_WRITE_LAST, "RC RDMA Write Last" }, { RC_RDMA_WRITE_LAST_IMM, "RC RDMA Write Last Immediate" }, { RC_RDMA_WRITE_ONLY, "RC RDMA Write Only" }, { RC_RDMA_WRITE_ONLY_IMM, "RC RDMA Write Only Immediate" }, { RC_RDMA_READ_REQUEST, "RC RDMA Read Request" }, { RC_RDMA_READ_RESPONSE_FIRST, "RC RDMA Read Response First" }, { RC_RDMA_READ_RESPONSE_MIDDLE, "RC RDMA Read Response Middle" }, { RC_RDMA_READ_RESPONSE_LAST, "RC RDMA Read Response Last" }, { RC_RDMA_READ_RESPONSE_ONLY, "RC RDMA Read Response Only" }, { RC_ACKNOWLEDGE, "RC Acknowledge" }, { RC_ATOMIC_ACKNOWLEDGE, "RC Atomic Acknowledge" }, { RC_CMP_SWAP, "RC Compare Swap" }, { RC_FETCH_ADD, "RC Fetch Add" }, { RC_SEND_LAST_INVAL, "RC Send Last Invalidate" }, { RC_SEND_ONLY_INVAL, "RC Send Only Invalidate" }, { RD_SEND_FIRST, "RD Send First" }, { RD_SEND_MIDDLE, "RD Send Middle" }, { RD_SEND_LAST, "RD Send Last" }, { RD_SEND_LAST_IMM, "RD Last Immediate" }, { RD_SEND_ONLY, "RD Send Only" }, { RD_SEND_ONLY_IMM, "RD Send Only Immediate" }, { RD_RDMA_WRITE_FIRST, "RD RDMA Write First" }, { RD_RDMA_WRITE_MIDDLE, "RD RDMA Write Middle" }, { RD_RDMA_WRITE_LAST, "RD RDMA Write Last" }, { RD_RDMA_WRITE_LAST_IMM, "RD RDMA Write Last Immediate" }, { RD_RDMA_WRITE_ONLY, "RD RDMA Write Only" }, { RD_RDMA_WRITE_ONLY_IMM, "RD RDMA Write Only Immediate" }, { RD_RDMA_READ_REQUEST, "RD RDMA Read Request" }, { RD_RDMA_READ_RESPONSE_FIRST, "RD RDMA Read Response First" }, { RD_RDMA_READ_RESPONSE_MIDDLE, "RD RDMA Read Response Middle" }, { RD_RDMA_READ_RESPONSE_LAST, "RD RDMA Read Response Last" }, { RD_RDMA_READ_RESPONSE_ONLY, "RD RDMA Read Response Only" }, { RD_ACKNOWLEDGE, "RD Acknowledge" }, { RD_ATOMIC_ACKNOWLEDGE, "RD Atomic Acknowledge" }, { RD_CMP_SWAP, "RD Compare Swap" }, { RD_FETCH_ADD, "RD Fetch Add" }, { RD_RESYNC, "RD RESYNC" }, { UD_SEND_ONLY, "UD Send Only" }, { UD_SEND_ONLY_IMM, "UD Send Only Immediate" }, { UC_SEND_FIRST, "UC Send First" }, { UC_SEND_MIDDLE, "UC Send Middle" }, { UC_SEND_LAST, "UC Send Last" }, { UC_SEND_LAST_IMM, "UC Send Last Immediate" }, { UC_SEND_ONLY, "UC Send Only" }, { UC_SEND_ONLY_IMM, "UC Send Only Immediate" }, { UC_RDMA_WRITE_FIRST, "UC RDMA Write First" }, { UC_RDMA_WRITE_MIDDLE, "Unreliable Connection RDMA Write Middle" }, { UC_RDMA_WRITE_LAST, "UC RDMA Write Last" }, { UC_RDMA_WRITE_LAST_IMM, "UC RDMA Write Last Immediate" }, { UC_RDMA_WRITE_ONLY, "UC RDMA Write Only" }, { UC_RDMA_WRITE_ONLY_IMM, "UC RDMA Write Only Immediate" }, { PSM_RESERVED, "PSM Reserved" }, { PSM_TINY, "PSM TINY" }, { PSM_SHORT, "PSM SHORT" }, { PSM_MEDIUM, "PSM MEDIUM" }, { PSM_MEDIUM_DATA, "PSM MEDIUM_DATA" }, { PSM_LONG_RTS, "PSM LONG RTS" }, { PSM_LONG_CTS, "PSM LONG CTS" }, { PSM_LONG_DATA, "PSM LONG DATA" }, { PSM_TIDS_GRANT, "PSM TIDS GRANT" }, { PSM_TIDS_GRANT_ACK, "PSM TIDS GRANT ACK" }, { PSM_TIDS_RELEASE, "PSM TIDS RELEASE" }, { PSM_TIDS_RELEASE_CONFIRM, "PSM TIDS RELEASE CONFIRM" }, { PSM_EXPTID_UNALIGNED, "PSM EXPTID UNALIGNED" }, { PSM_EXPTID, "PSM EXPTID" }, { PSM_ACK, "PSM ACK" }, { PSM_NAK, "PSM NAK" }, { PSM_ERR_CHK, "PSM ERR CHK" }, { PSM_ERR_CHK_BAD, "PSM ERR CHK BAD" }, { PSM_ERR_CHK_GEN, "PSM ERR CHK GEN" }, { PSM_FLOW_CCA_BECN, "PSM FLOW CCA BECN" }, { PSM_CONNECT_REQUEST, "PSM CONNECT REQUEST" }, { PSM_CONNECT_REPLY, "PSM CONNECT REPLY" }, { PSM_DISCONNECT_REQUEST, "PSM DISCONNECT REQUEST" }, { PSM_DISCONNECT_REPLY, "PSM DISCONNECT REPLY" }, { PSM_AM_REQUEST_NOREPLY, "PSM AM REQUEST NOREPLY" }, { PSM_AM_REQUEST, "PSM AM REQUEST" }, { PSM_AM_REPLY, "PSM AM REPLY" }, { TID_RDMA_WRITE_REQUEST, "TID RDMA Write Request" }, { TID_RDMA_WRITE_RESPONSE, "TID RDMA Write Response" }, { TID_RDMA_WRITE_DATA, "TID RDMA Write Data" }, { TID_RDMA_WRITE_DATA_LAST, "TID RDMA Write Data Last" }, { TID_RDMA_READ_REQUEST, "TID RDMA Read Request" }, { TID_RDMA_READ_RESPONSE, "TID RDMA Read Response" }, { TID_RDMA_RESYNC, "TID RDMA ReSync" }, { TID_RDMA_ACK, "TID RDMA Ack" }, { 0, NULL } }; static const value_string vals_opa_9b_lnh[] = { { 0, "RAW" }, { 3, "GRH" }, { 2, "BTH" }, { 1, "Ipv6" }, { 0, NULL } }; static const value_string vals_opa_9b_grh_ipver[] = { { 4, "IPv4" }, { 6, "IPv6" }, { 0, NULL }, }; static const value_string vals_opa_9b_grh_next_hdr[] = { { 0x1B, "BTH Follows" }, { 0, NULL } }; static const true_false_string tfs_opa_bth_migrated_notmigrated = { "Migrated", "Not Migrated" }; static const true_false_string tfs_opa_kdeth_offset_32_64 = { "32 Byte Words", "64 Byte Words" }; /* Wireshark ID */ static gint proto_opa_9b; /* Variables to hold expansion values between packets */ static gint ett_all_headers; static gint ett_9b; static gint ett_grh; static gint ett_bth; static gint ett_rdeth; static gint ett_deth; static gint ett_reth; static gint ett_atomiceth; static gint ett_aeth; static gint ett_atomicacketh; static gint ett_immdt; static gint ett_ieth; static gint ett_kdeth; static gint ett_psm; static gint ett_tidrdma; /* 9B Header Fields */ static gint hf_opa_9B; static gint hf_opa_9B_service_channel; static gint hf_opa_9B_link_version; static gint hf_opa_9B_service_level; static gint hf_opa_9B_reserved2; static gint hf_opa_9B_lnh; static gint hf_opa_9B_dlid; static gint hf_opa_9B_reserved3; static gint hf_opa_9B_packet_length; static gint hf_opa_9B_slid; /* ICRC */ static gint hf_opa_9b_ICRC; /* GRH */ static gint hf_opa_grh; static gint hf_opa_grh_ip_version; static gint hf_opa_grh_traffic_class; static gint hf_opa_grh_flow_label; static gint hf_opa_grh_payload_length; static gint hf_opa_grh_next_header; static gint hf_opa_grh_hop_limit; static gint hf_opa_grh_source_gid; static gint hf_opa_grh_destination_gid; /* BTH */ static gint hf_opa_bth; static gint hf_opa_bth_opcode; static gint hf_opa_bth_solicited_event; static gint hf_opa_bth_migreq; static gint hf_opa_bth_pad_count; static gint hf_opa_bth_transport_header_version; static gint hf_opa_bth_partition_key; static gint hf_opa_bth_fcn; static gint hf_opa_bth_bcn; static gint hf_opa_bth_Reserved8a; static gint hf_opa_bth_destination_qp; static gint hf_opa_bth_acknowledge_request; static gint hf_opa_bth_packet_sequence_number; /* XXETH */ static gint hf_opa_RDETH; static gint hf_opa_RDETH_reserved8; static gint hf_opa_RDETH_ee_context; static gint hf_opa_DETH; static gint hf_opa_DETH_queue_key; static gint hf_opa_DETH_reserved8; static gint hf_opa_DETH_source_qp; static gint hf_opa_RETH; static gint hf_opa_RETH_virtual_address; static gint hf_opa_RETH_remote_key; static gint hf_opa_RETH_dma_length; static gint hf_opa_AtomicETH; static gint hf_opa_AtomicETH_virtual_address; static gint hf_opa_AtomicETH_remote_key; static gint hf_opa_AtomicETH_swap_or_add_data; static gint hf_opa_AtomicETH_compare_data; static gint hf_opa_AETH; static gint hf_opa_AETH_syndrome; static gint hf_opa_AETH_message_sequence_number; static gint hf_opa_AtomicAckETH; static gint hf_opa_AtomicAckETH_original_remote_data; static gint hf_opa_IMMDT; static gint hf_opa_IMMDT_data; static gint hf_opa_IETH; static gint hf_opa_IETH_r_key; static gint hf_opa_KDETH; static gint hf_opa_KDETH_kver; static gint hf_opa_KDETH_sh; static gint hf_opa_KDETH_intr; static gint hf_opa_KDETH_tidctrl; static gint hf_opa_KDETH_tid; static gint hf_opa_KDETH_offset_mode; static gint hf_opa_KDETH_offset; static int * const _opa_KDETH_word1[] = { &hf_opa_KDETH_kver, &hf_opa_KDETH_sh, &hf_opa_KDETH_intr, &hf_opa_KDETH_tidctrl, &hf_opa_KDETH_tid, &hf_opa_KDETH_offset_mode, &hf_opa_KDETH_offset, NULL }; static gint hf_opa_KDETH_hcrc; static gint hf_opa_KDETH_j_key; static int * const _opa_KDETH_word2[] = { &hf_opa_KDETH_hcrc, &hf_opa_KDETH_j_key, NULL }; /* PSM */ static gint hf_opa_psm; static gint hf_opa_psm_a; static gint hf_opa_psm_ackpsn; static gint hf_opa_psm_flags; static gint hf_opa_psm_commidx; static gint hf_opa_psm_flowid; static gint hf_opa_psm_msglen; static gint hf_opa_psm_msgseq; static gint hf_opa_psm_tag; static gint hf_opa_psm_msgdata; static gint hf_opa_psm_short_msglen; static gint hf_opa_psm_paylen; static gint hf_opa_psm_offset; static gint hf_opa_psm_sreqidx; static gint hf_opa_psm_rreqidx; static gint hf_opa_psm_rdescid; static gint hf_opa_psm_sdescid; static gint hf_opa_psm_psn; static gint hf_opa_psm_hostipv4; static gint hf_opa_psm_hostpid; static gint hf_opa_psm_dlen; static gint hf_opa_psm_nargs; static gint hf_opa_psm_hidx; static gint hf_opa_psm_arg; static gint hf_opa_psm_payload; /* TID RDMA */ static gint hf_opa_TIDRDMA; static gint hf_opa_TIDRDMA_reserved; static gint hf_opa_TIDRDMA_TIDFlowPSN_reserved; static gint hf_opa_TIDRDMA_TIDFlowPSN; static gint hf_opa_TIDRDMA_TIDFlowQP_reserved; static gint hf_opa_TIDRDMA_TIDFlowQP; static gint hf_opa_TIDRDMA_VerbsPSN_reserved; static gint hf_opa_TIDRDMA_VerbsPSN; static gint hf_opa_TIDRDMA_VerbsQP_reserved; static gint hf_opa_TIDRDMA_VerbsQP; /* Custom Functions */ static void cf_opa_dw_to_b(gchar *buf, guint32 value) { snprintf(buf, ITEM_LABEL_LENGTH, "%u DWORDS (%u Bytes)", value, value * 4); } /* Dissector Declarations */ static dissector_handle_t opa_9b_handle; static dissector_handle_t opa_mad_handle; static dissector_handle_t infiniband_handle; static dissector_handle_t ipv6_handle; static void parse_opa_9B_Header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset, guint8 *lnh_val) { /* 16B - L2 Header */ proto_item *L2_9B_header_item; proto_tree *L2_9B_header_tree; void *src_addr, *dst_addr; gint local_offset = *offset; col_prepend_fstr(pinfo->cinfo, COL_INFO, "9B: "); L2_9B_header_item = proto_tree_add_item(tree, hf_opa_9B, tvb, local_offset, 8, ENC_NA); L2_9B_header_tree = proto_item_add_subtree(L2_9B_header_item, ett_9b); proto_tree_add_item(L2_9B_header_tree, hf_opa_9B_service_channel, tvb, local_offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(L2_9B_header_tree, hf_opa_9B_link_version, tvb, local_offset, 1, ENC_BIG_ENDIAN); local_offset += 1; proto_tree_add_item(L2_9B_header_tree, hf_opa_9B_service_level, tvb, local_offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(L2_9B_header_tree, hf_opa_9B_reserved2, tvb, local_offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(L2_9B_header_tree, hf_opa_9B_lnh, tvb, local_offset, 1, ENC_BIG_ENDIAN); /* Save Link Next Header... This tells us what the next header is. */ *lnh_val = tvb_get_guint8(tvb, local_offset); *lnh_val &= 0x03; local_offset += 1; proto_tree_add_item(L2_9B_header_tree, hf_opa_9B_dlid, tvb, local_offset, 2, ENC_BIG_ENDIAN); /* Set destination in packet view. */ dst_addr = wmem_alloc(pinfo->pool, sizeof(guint16)); *((guint16 *)dst_addr) = tvb_get_ntohs(tvb, local_offset); set_address(&pinfo->dst, AT_IB, sizeof(guint16), dst_addr); local_offset += 2; proto_tree_add_item(L2_9B_header_tree, hf_opa_9B_reserved3, tvb, local_offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(L2_9B_header_tree, hf_opa_9B_packet_length, tvb, local_offset, 2, ENC_BIG_ENDIAN); local_offset += 2; proto_tree_add_item(L2_9B_header_tree, hf_opa_9B_slid, tvb, local_offset, 2, ENC_BIG_ENDIAN); /* Set Source in packet view. */ src_addr = wmem_alloc(pinfo->pool, sizeof(guint16)); *((guint16 *)src_addr) = tvb_get_ntohs(tvb, local_offset); set_address(&pinfo->src, AT_IB, sizeof(guint16), src_addr); local_offset += 2; *offset = local_offset; } static void parse_opa_grh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset, guint8 *nextHdr) { proto_item *global_route_header_item; proto_tree *global_route_header_tree; gint local_offset = *offset; col_append_fstr(pinfo->cinfo, COL_INFO, "GRH: "); global_route_header_item = proto_tree_add_item(tree, hf_opa_grh, tvb, local_offset, 40, ENC_NA); global_route_header_tree = proto_item_add_subtree(global_route_header_item, ett_grh); proto_tree_add_item(global_route_header_tree, hf_opa_grh_ip_version, tvb, local_offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(global_route_header_tree, hf_opa_grh_traffic_class, tvb, local_offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(global_route_header_tree, hf_opa_grh_flow_label, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; proto_tree_add_item(global_route_header_tree, hf_opa_grh_payload_length, tvb, local_offset, 2, ENC_BIG_ENDIAN); local_offset += 2; *nextHdr = tvb_get_guint8(tvb, local_offset); proto_tree_add_item(global_route_header_tree, hf_opa_grh_next_header, tvb, local_offset, 1, ENC_BIG_ENDIAN); local_offset += 1; proto_tree_add_item(global_route_header_tree, hf_opa_grh_hop_limit, tvb, local_offset, 1, ENC_BIG_ENDIAN); local_offset += 1; proto_tree_add_item(global_route_header_tree, hf_opa_grh_source_gid, tvb, local_offset, 16, ENC_NA); /* set source GID in packet view*/ set_address_tvb(&pinfo->src, AT_IB, 16, tvb, local_offset); local_offset += 16; proto_tree_add_item(global_route_header_tree, hf_opa_grh_destination_gid, tvb, local_offset, 16, ENC_NA); /* set destination GID in packet view*/ set_address_tvb(&pinfo->dst, AT_IB, 16, tvb, local_offset); local_offset += 16; *offset = local_offset; } static void parse_opa_bth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset, guint8 *opCode) { proto_item *base_transport_header_item; proto_tree *base_transport_header_tree; gint local_offset = *offset; col_append_fstr(pinfo->cinfo, COL_INFO, "BTH: "); base_transport_header_item = proto_tree_add_item(tree, hf_opa_bth, tvb, local_offset, 12, ENC_NA); base_transport_header_tree = proto_item_add_subtree(base_transport_header_item, ett_bth); proto_tree_add_item(base_transport_header_tree, hf_opa_bth_opcode, tvb, local_offset, 1, ENC_LITTLE_ENDIAN); *opCode = tvb_get_guint8(tvb, local_offset); col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str((guint32)(*opCode), vals_opa_bth_opcode, "Unknown OpCode (0x%0x)")); local_offset += 1; proto_tree_add_item(base_transport_header_tree, hf_opa_bth_solicited_event, tvb, local_offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(base_transport_header_tree, hf_opa_bth_migreq, tvb, local_offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(base_transport_header_tree, hf_opa_bth_pad_count, tvb, local_offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(base_transport_header_tree, hf_opa_bth_transport_header_version, tvb, local_offset, 1, ENC_BIG_ENDIAN); local_offset += 1; proto_tree_add_item(base_transport_header_tree, hf_opa_bth_partition_key, tvb, local_offset, 2, ENC_BIG_ENDIAN); local_offset += 2; proto_tree_add_item(base_transport_header_tree, hf_opa_bth_fcn, tvb, local_offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(base_transport_header_tree, hf_opa_bth_bcn, tvb, local_offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(base_transport_header_tree, hf_opa_bth_Reserved8a, tvb, local_offset, 1, ENC_BIG_ENDIAN); local_offset += 1; proto_tree_add_item(base_transport_header_tree, hf_opa_bth_destination_qp, tvb, local_offset, 3, ENC_BIG_ENDIAN); pinfo->destport = tvb_get_ntoh24(tvb, local_offset); local_offset += 3; proto_tree_add_item(base_transport_header_tree, hf_opa_bth_acknowledge_request, tvb, local_offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(base_transport_header_tree, hf_opa_bth_packet_sequence_number, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; *offset = local_offset; } static gboolean contains(guint32 OpCode, guint32 *Codes, gint32 length) { gint32 i; for (i = 0; i < length; i++) { if ((OpCode ^ Codes[i]) == 0) return TRUE; } return FALSE; } static gint32 find_next_header_sequence(guint32 OpCode) { if (contains(OpCode, &opCode_PAYLD[0], (gint32)array_length(opCode_PAYLD))) return PAYLD; if (contains(OpCode, &opCode_IMMDT_PAYLD[0], (gint32)array_length(opCode_IMMDT_PAYLD))) return IMMDT_PAYLD; if (contains(OpCode, &opCode_RDETH_DETH_PAYLD[0], (gint32)array_length(opCode_RDETH_DETH_PAYLD))) return RDETH_DETH_PAYLD; if (contains(OpCode, &opCode_RETH_PAYLD[0], (gint32)array_length(opCode_RETH_PAYLD))) return RETH_PAYLD; if (contains(OpCode, &opCode_RDETH_AETH_PAYLD[0], (gint32)array_length(opCode_RDETH_AETH_PAYLD))) return RDETH_AETH_PAYLD; if (contains(OpCode, &opCode_AETH_PAYLD[0], (gint32)array_length(opCode_AETH_PAYLD))) return AETH_PAYLD; if (contains(OpCode, &opCode_RDETH_DETH_IMMDT_PAYLD[0], (gint32)array_length(opCode_RDETH_DETH_IMMDT_PAYLD))) return RDETH_DETH_IMMDT_PAYLD; if (contains(OpCode, &opCode_RETH_IMMDT_PAYLD[0], (gint32)array_length(opCode_RETH_IMMDT_PAYLD))) return RETH_IMMDT_PAYLD; if (contains(OpCode, &opCode_RDETH_DETH_RETH_PAYLD[0], (gint32)array_length(opCode_RDETH_DETH_RETH_PAYLD))) return RDETH_DETH_RETH_PAYLD; if (contains(OpCode, &opCode_ATOMICETH[0], (gint32)array_length(opCode_ATOMICETH))) return ATOMICETH; if (contains(OpCode, &opCode_IETH_PAYLD[0], (gint32)array_length(opCode_IETH_PAYLD))) return IETH_PAYLD; if (contains(OpCode, &opCode_RDETH_DETH_ATOMICETH[0], (gint32)array_length(opCode_RDETH_DETH_ATOMICETH))) return RDETH_DETH_ATOMICETH; if (contains(OpCode, &opCode_PSM[0], (gint32)array_length(opCode_PSM))) return KDETH_PSM; if (contains(OpCode, &opCode_TIDRDMA[0], (gint32)array_length(opCode_TIDRDMA))) return KDETH_TIDRDMA; if ((OpCode ^ RC_ACKNOWLEDGE) == 0) return AETH; if ((OpCode ^ RC_RDMA_READ_REQUEST) == 0) return RETH; if ((OpCode ^ RC_ATOMIC_ACKNOWLEDGE) == 0) return AETH_ATOMICACKETH; if ((OpCode ^ RD_RDMA_READ_RESPONSE_MIDDLE) == 0) return RDETH_PAYLD; if ((OpCode ^ RD_ACKNOWLEDGE) == 0) return RDETH_AETH; if ((OpCode ^ RD_ATOMIC_ACKNOWLEDGE) == 0) return RDETH_AETH_ATOMICACKETH; if ((OpCode ^ RD_RDMA_WRITE_ONLY_IMM) == 0) return RDETH_DETH_RETH_IMMDT_PAYLD; if ((OpCode ^ RD_RDMA_READ_REQUEST) == 0) return RDETH_DETH_RETH; if ((OpCode ^ RD_RESYNC) == 0) return RDETH_DETH; if ((OpCode ^ UD_SEND_ONLY) == 0) return DETH_PAYLD; if ((OpCode ^ UD_SEND_ONLY_IMM) == 0) return DETH_IMMDT_PAYLD; return -1; } /* Parse RDETH - Reliable Datagram Extended Transport Header */ static void parse_RDETH(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset) { gint local_offset = *offset; /* RDETH - Reliable Datagram Extended Transport Header */ proto_item *RDETH_header_item; proto_tree *RDETH_header_tree; col_append_fstr(pinfo->cinfo, COL_INFO, "RDETH: "); RDETH_header_item = proto_tree_add_item(tree, hf_opa_RDETH, tvb, local_offset, 4, ENC_NA); RDETH_header_tree = proto_item_add_subtree(RDETH_header_item, ett_rdeth); proto_tree_add_item(RDETH_header_tree, hf_opa_RDETH_reserved8, tvb, local_offset, 1, ENC_BIG_ENDIAN); local_offset += 1; proto_tree_add_item(RDETH_header_tree, hf_opa_RDETH_ee_context, tvb, local_offset, 3, ENC_BIG_ENDIAN); local_offset += 3; *offset = local_offset; } /* Parse DETH - Datagram Extended Transport Header */ static void parse_DETH(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset) { gint local_offset = *offset; /* DETH - Datagram Extended Transport Header */ proto_item *DETH_header_item; proto_tree *DETH_header_tree; col_append_fstr(pinfo->cinfo, COL_INFO, "DETH: "); DETH_header_item = proto_tree_add_item(tree, hf_opa_DETH, tvb, local_offset, 8, ENC_NA); DETH_header_tree = proto_item_add_subtree(DETH_header_item, ett_deth); proto_tree_add_item(DETH_header_tree, hf_opa_DETH_queue_key, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; proto_tree_add_item(DETH_header_tree, hf_opa_DETH_reserved8, tvb, local_offset, 1, ENC_BIG_ENDIAN); local_offset += 1; proto_tree_add_item(DETH_header_tree, hf_opa_DETH_source_qp, tvb, local_offset, 3, ENC_BIG_ENDIAN); pinfo->srcport = tvb_get_ntoh24(tvb, local_offset); local_offset += 3; *offset = local_offset; } /* Parse RETH - RDMA Extended Transport Header */ static void parse_RETH(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset) { gint local_offset = *offset; /* RETH - RDMA Extended Transport Header */ proto_item *RETH_header_item; proto_tree *RETH_header_tree; col_append_fstr(pinfo->cinfo, COL_INFO, "RETH: "); RETH_header_item = proto_tree_add_item(tree, hf_opa_RETH, tvb, local_offset, 16, ENC_NA); RETH_header_tree = proto_item_add_subtree(RETH_header_item, ett_reth); proto_tree_add_item(RETH_header_tree, hf_opa_RETH_virtual_address, tvb, local_offset, 8, ENC_BIG_ENDIAN); local_offset += 8; proto_tree_add_item(RETH_header_tree, hf_opa_RETH_remote_key, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; proto_tree_add_item(RETH_header_tree, hf_opa_RETH_dma_length, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; *offset = local_offset; } /* Parse AtomicETH - Atomic Extended Transport Header */ static void parse_ATOMICETH(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset) { gint local_offset = *offset; /* AtomicETH - Atomic Extended Transport Header */ proto_item *ATOMICETH_header_item; proto_tree *ATOMICETH_header_tree; col_append_fstr(pinfo->cinfo, COL_INFO, "AtomicETH: "); ATOMICETH_header_item = proto_tree_add_item(tree, hf_opa_AtomicETH, tvb, local_offset, 28, ENC_NA); ATOMICETH_header_tree = proto_item_add_subtree(ATOMICETH_header_item, ett_atomiceth); proto_tree_add_item(ATOMICETH_header_tree, hf_opa_AtomicETH_virtual_address, tvb, local_offset, 8, ENC_BIG_ENDIAN); local_offset += 8; proto_tree_add_item(ATOMICETH_header_tree, hf_opa_AtomicETH_remote_key, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; proto_tree_add_item(ATOMICETH_header_tree, hf_opa_AtomicETH_swap_or_add_data, tvb, local_offset, 8, ENC_BIG_ENDIAN); local_offset += 8; proto_tree_add_item(ATOMICETH_header_tree, hf_opa_AtomicETH_compare_data, tvb, local_offset, 8, ENC_BIG_ENDIAN); local_offset += 8; *offset = local_offset; } /* Parse AETH - ACK Extended Transport Header */ static void parse_AETH(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset) { gint local_offset = *offset; /* AETH - ACK Extended Transport Header */ proto_item *AETH_header_item; proto_tree *AETH_header_tree; col_append_fstr(pinfo->cinfo, COL_INFO, "AETH: "); AETH_header_item = proto_tree_add_item(tree, hf_opa_AETH, tvb, local_offset, 4, ENC_NA); AETH_header_tree = proto_item_add_subtree(AETH_header_item, ett_aeth); proto_tree_add_item(AETH_header_tree, hf_opa_AETH_syndrome, tvb, local_offset, 1, ENC_BIG_ENDIAN); local_offset += 1; proto_tree_add_item(AETH_header_tree, hf_opa_AETH_message_sequence_number, tvb, local_offset, 3, ENC_BIG_ENDIAN); local_offset += 3; *offset = local_offset; } /* Parse AtomicAckEth - Atomic ACK Extended Transport Header */ static void parse_ATOMICACKETH(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset) { gint local_offset = *offset; /* AtomicAckEth - Atomic ACK Extended Transport Header */ proto_item *ATOMICACKETH_header_item; proto_tree *ATOMICACKETH_header_tree; col_append_fstr(pinfo->cinfo, COL_INFO, "AtomicACKETH: "); ATOMICACKETH_header_item = proto_tree_add_item(tree, hf_opa_AtomicAckETH, tvb, local_offset, 8, ENC_NA); ATOMICACKETH_header_tree = proto_item_add_subtree(ATOMICACKETH_header_item, ett_atomicacketh); proto_tree_add_item(ATOMICACKETH_header_tree, hf_opa_AtomicAckETH_original_remote_data, tvb, local_offset, 8, ENC_BIG_ENDIAN); local_offset += 8; *offset = local_offset; } /* Parse IMMDT - Immediate Data Extended Transport Header */ static void parse_IMMDT(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset) { gint local_offset = *offset; /* IMMDT - Immediate Data Extended Transport Header */ proto_item *IMMDT_header_item; proto_tree *IMMDT_header_tree; col_append_fstr(pinfo->cinfo, COL_INFO, "IMMDT: "); IMMDT_header_item = proto_tree_add_item(tree, hf_opa_IMMDT, tvb, local_offset, 4, ENC_NA); IMMDT_header_tree = proto_item_add_subtree(IMMDT_header_item, ett_immdt); proto_tree_add_item(IMMDT_header_tree, hf_opa_IMMDT_data, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; *offset = local_offset; } /* Parse IETH - Invalidate Extended Transport Header */ static void parse_IETH(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset) { gint local_offset = *offset; /* IETH - Invalidate Extended Transport Header */ proto_item *IETH_header_item; proto_tree *IETH_header_tree; col_append_fstr(pinfo->cinfo, COL_INFO, "IETH: "); IETH_header_item = proto_tree_add_item(tree, hf_opa_IETH, tvb, local_offset, 4, ENC_NA); IETH_header_tree = proto_item_add_subtree(IETH_header_item, ett_ieth); proto_tree_add_item(IETH_header_tree, hf_opa_IETH_r_key, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; *offset = local_offset; } /* Parse KDETH - Key Datagram Extended Transport Header */ static void parse_KDETH(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset) { gint local_offset = *offset; /* KDETH - Key Datagram Extended Transport Header */ proto_item *KDETH_header_item; proto_tree *KDETH_header_tree; col_append_fstr(pinfo->cinfo, COL_INFO, "KDETH: "); KDETH_header_item = proto_tree_add_item(tree, hf_opa_KDETH, tvb, local_offset, 8, ENC_NA); KDETH_header_tree = proto_item_add_subtree(KDETH_header_item, ett_kdeth); proto_tree_add_bitmask_list(KDETH_header_tree, tvb, local_offset, 4, _opa_KDETH_word1, ENC_LITTLE_ENDIAN); local_offset += 4; proto_tree_add_bitmask_list(KDETH_header_tree, tvb, local_offset, 4, _opa_KDETH_word2, ENC_LITTLE_ENDIAN); local_offset += 4; *offset = local_offset; } /* Parse PSM header */ static void parse_PSM(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset, gint opCode) { gint local_offset = *offset; /* PSM Header */ proto_item *PSM_header_item; proto_tree *PSM_header_tree; guint32 payLength; col_append_fstr(pinfo->cinfo, COL_INFO, "PSM: "); PSM_header_item = proto_tree_add_item(tree, hf_opa_psm, tvb, local_offset, 28, ENC_NA); PSM_header_tree = proto_item_add_subtree(PSM_header_item, ett_psm); proto_tree_add_item(PSM_header_tree, hf_opa_psm_a, tvb, local_offset + 3, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(PSM_header_tree, hf_opa_psm_ackpsn, tvb, local_offset, 4, ENC_LITTLE_ENDIAN); local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_flags, tvb, local_offset + 3, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(PSM_header_tree, hf_opa_psm_commidx, tvb, local_offset, 3, ENC_LITTLE_ENDIAN); local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_flowid, tvb, local_offset + 3, 1, ENC_LITTLE_ENDIAN); switch (opCode) { case PSM_TINY: proto_tree_add_item(PSM_header_tree, hf_opa_psm_msglen, tvb, local_offset + 2, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(PSM_header_tree, hf_opa_psm_msgseq, tvb, local_offset, 2, ENC_LITTLE_ENDIAN); local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_tag, tvb, local_offset, 8, ENC_LITTLE_ENDIAN); local_offset += 8; proto_tree_add_item(PSM_header_tree, hf_opa_psm_msgdata, tvb, local_offset, 8, ENC_LITTLE_ENDIAN); local_offset += 8; break; case PSM_SHORT: proto_tree_add_item(PSM_header_tree, hf_opa_psm_msgseq, tvb, local_offset, 2, ENC_LITTLE_ENDIAN); local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_tag, tvb, local_offset, 8, ENC_LITTLE_ENDIAN); local_offset += 8; proto_tree_add_item(PSM_header_tree, hf_opa_psm_msglen, tvb, local_offset, 4, ENC_LITTLE_ENDIAN); payLength = tvb_get_letohl(tvb, local_offset); local_offset += 8; proto_tree_add_item(PSM_header_tree, hf_opa_psm_payload, tvb, local_offset, payLength, ENC_NA); local_offset += payLength; break; case PSM_MEDIUM: proto_tree_add_item(PSM_header_tree, hf_opa_psm_msgseq, tvb, local_offset, 2, ENC_LITTLE_ENDIAN); local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_tag, tvb, local_offset, 8, ENC_LITTLE_ENDIAN); local_offset += 8; proto_tree_add_item(PSM_header_tree, hf_opa_psm_msglen, tvb, local_offset, 4, ENC_LITTLE_ENDIAN); local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_paylen, tvb, local_offset, 4, ENC_LITTLE_ENDIAN); local_offset += 4; break; case PSM_MEDIUM_DATA: proto_tree_add_item(PSM_header_tree, hf_opa_psm_msgseq, tvb, local_offset, 2, ENC_LITTLE_ENDIAN); local_offset += 4; local_offset += 8; proto_tree_add_item(PSM_header_tree, hf_opa_psm_offset, tvb, local_offset, 4, ENC_LITTLE_ENDIAN); local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_paylen, tvb, local_offset, 4, ENC_LITTLE_ENDIAN); local_offset += 4; break; case PSM_LONG_RTS: proto_tree_add_item(PSM_header_tree, hf_opa_psm_msgseq, tvb, local_offset, 2, ENC_LITTLE_ENDIAN); local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_tag, tvb, local_offset, 8, ENC_LITTLE_ENDIAN); local_offset += 8; proto_tree_add_item(PSM_header_tree, hf_opa_psm_msglen, tvb, local_offset, 4, ENC_LITTLE_ENDIAN); local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_sreqidx, tvb, local_offset, 4, ENC_LITTLE_ENDIAN); local_offset += 4; break; case PSM_LONG_CTS: local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_sreqidx, tvb, local_offset, 4, ENC_LITTLE_ENDIAN); local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_rreqidx, tvb, local_offset, 4, ENC_LITTLE_ENDIAN); local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_msglen, tvb, local_offset, 4, ENC_LITTLE_ENDIAN); local_offset += 8; break; case PSM_LONG_DATA: local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_rreqidx, tvb, local_offset, 4, ENC_LITTLE_ENDIAN); local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_offset, tvb, local_offset, 4, ENC_LITTLE_ENDIAN); local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_paylen, tvb, local_offset, 4, ENC_LITTLE_ENDIAN); local_offset += 8; break; case PSM_TIDS_GRANT: local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_sreqidx, tvb, local_offset, 4, ENC_LITTLE_ENDIAN); local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_short_msglen, tvb, local_offset, 4, ENC_LITTLE_ENDIAN); local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_paylen, tvb, local_offset, 4, ENC_LITTLE_ENDIAN); local_offset += 8; break; case PSM_TIDS_GRANT_ACK: local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_rdescid, tvb, local_offset, 8, ENC_LITTLE_ENDIAN); local_offset += 8; local_offset += 8; break; case PSM_TIDS_RELEASE: local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_rdescid, tvb, local_offset, 8, ENC_LITTLE_ENDIAN); local_offset += 8; proto_tree_add_item(PSM_header_tree, hf_opa_psm_sdescid, tvb, local_offset, 8, ENC_LITTLE_ENDIAN); local_offset += 8; break; case PSM_TIDS_RELEASE_CONFIRM: local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_sdescid, tvb, local_offset, 8, ENC_LITTLE_ENDIAN); local_offset += 8; local_offset += 8; break; case PSM_EXPTID_UNALIGNED: local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_rdescid, tvb, local_offset, 8, ENC_LITTLE_ENDIAN); local_offset += 8; local_offset += 8; break; case PSM_EXPTID: local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_rdescid, tvb, local_offset, 8, ENC_LITTLE_ENDIAN); local_offset += 8; proto_tree_add_item(PSM_header_tree, hf_opa_psm_sdescid, tvb, local_offset, 8, ENC_LITTLE_ENDIAN); local_offset += 8; break; case PSM_ACK: local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_sdescid, tvb, local_offset, 8, ENC_LITTLE_ENDIAN); local_offset += 8; local_offset += 8; break; case PSM_NAK: local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_sdescid, tvb, local_offset, 8, ENC_LITTLE_ENDIAN); local_offset += 8; proto_tree_add_item(PSM_header_tree, hf_opa_psm_psn, tvb, local_offset, 4, ENC_LITTLE_ENDIAN); local_offset += 8; break; case PSM_ERR_CHK: case PSM_ERR_CHK_BAD: local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_hostipv4, tvb, local_offset, 4, ENC_LITTLE_ENDIAN); local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_hostpid, tvb, local_offset, 4, ENC_LITTLE_ENDIAN); local_offset += 12; break; case PSM_ERR_CHK_GEN: local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_rdescid, tvb, local_offset, 8, ENC_LITTLE_ENDIAN); local_offset += 8; proto_tree_add_item(PSM_header_tree, hf_opa_psm_sdescid, tvb, local_offset, 8, ENC_LITTLE_ENDIAN); local_offset += 8; break; case PSM_FLOW_CCA_BECN: break; case PSM_CONNECT_REQUEST: case PSM_CONNECT_REPLY: case PSM_DISCONNECT_REQUEST: case PSM_DISCONNECT_REPLY: local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_paylen, tvb, local_offset, 4, ENC_LITTLE_ENDIAN); local_offset += 16; break; case PSM_AM_REQUEST_NOREPLY: case PSM_AM_REQUEST: case PSM_AM_REPLY: proto_tree_add_item(PSM_header_tree, hf_opa_psm_dlen, tvb, local_offset + 3, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(PSM_header_tree, hf_opa_psm_nargs, tvb, local_offset + 3, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(PSM_header_tree, hf_opa_psm_hidx, tvb, local_offset + 2, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(PSM_header_tree, hf_opa_psm_msgseq, tvb, local_offset, 2, ENC_LITTLE_ENDIAN); local_offset += 4; proto_tree_add_item(PSM_header_tree, hf_opa_psm_arg, tvb, local_offset, 8, ENC_LITTLE_ENDIAN); local_offset += 8; proto_tree_add_item(PSM_header_tree, hf_opa_psm_arg, tvb, local_offset, 8, ENC_LITTLE_ENDIAN); local_offset += 8; break; } *offset = local_offset; } static void parse_TIDRDMA(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset, gint opCode, gboolean *parsePayload) { gint local_offset = *offset; proto_item *TIDRDMA_header_item; proto_tree *TIDRDMA_header_tree; switch (opCode) { case TID_RDMA_WRITE_REQUEST: parse_RETH(tvb, pinfo, tree, &local_offset); col_append_fstr(pinfo->cinfo, COL_INFO, "TID RDMA Write Request: "); TIDRDMA_header_item = proto_tree_add_item(tree, hf_opa_TIDRDMA, tvb, local_offset, 12, ENC_NA); proto_item_set_text(TIDRDMA_header_item, "TID RDMA Write Request Header"); TIDRDMA_header_tree = proto_item_add_subtree(TIDRDMA_header_item, ett_tidrdma); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_reserved, tvb, local_offset, 8, ENC_NA); local_offset += 8; proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_VerbsQP_reserved, tvb, local_offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_VerbsQP, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; *parsePayload = FALSE; break; case TID_RDMA_WRITE_RESPONSE: parse_AETH(tvb, pinfo, tree, &local_offset); col_append_fstr(pinfo->cinfo, COL_INFO, "TID RDMA Write Response: "); TIDRDMA_header_item = proto_tree_add_item(tree, hf_opa_TIDRDMA, tvb, local_offset, 24, ENC_NA); proto_item_set_text(TIDRDMA_header_item, "TID RDMA Write Response Header"); TIDRDMA_header_tree = proto_item_add_subtree(TIDRDMA_header_item, ett_tidrdma); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_reserved, tvb, local_offset, 12, ENC_NA); local_offset += 12; proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_TIDFlowPSN_reserved, tvb, local_offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_TIDFlowPSN, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_TIDFlowQP_reserved, tvb, local_offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_TIDFlowQP, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_VerbsQP_reserved, tvb, local_offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_VerbsQP, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; *parsePayload = FALSE; break; case TID_RDMA_WRITE_DATA: col_append_fstr(pinfo->cinfo, COL_INFO, "TID RDMA Write Data: "); TIDRDMA_header_item = proto_tree_add_item(tree, hf_opa_TIDRDMA, tvb, local_offset, 28, ENC_NA); proto_item_set_text(TIDRDMA_header_item, "TID RDMA Write Data Header"); TIDRDMA_header_tree = proto_item_add_subtree(TIDRDMA_header_item, ett_tidrdma); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_reserved, tvb, local_offset, 24, ENC_NA); local_offset += 24; proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_VerbsQP_reserved, tvb, local_offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_VerbsQP, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; *parsePayload = TRUE; break; case TID_RDMA_WRITE_DATA_LAST: col_append_fstr(pinfo->cinfo, COL_INFO, "TID RDMA Write Data Last: "); TIDRDMA_header_item = proto_tree_add_item(tree, hf_opa_TIDRDMA, tvb, local_offset, 28, ENC_NA); proto_item_set_text(TIDRDMA_header_item, "TID RDMA Write Data Last Header"); TIDRDMA_header_tree = proto_item_add_subtree(TIDRDMA_header_item, ett_tidrdma); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_reserved, tvb, local_offset, 24, ENC_NA); local_offset += 24; proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_VerbsQP_reserved, tvb, local_offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_VerbsQP, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; *parsePayload = TRUE; break; case TID_RDMA_READ_REQUEST: parse_RETH(tvb, pinfo, tree, &local_offset); col_append_fstr(pinfo->cinfo, COL_INFO, "TID RDMA Read Request: "); TIDRDMA_header_item = proto_tree_add_item(tree, hf_opa_TIDRDMA, tvb, local_offset, 12, ENC_NA); proto_item_set_text(TIDRDMA_header_item, "TID RDMA Read Request Header"); TIDRDMA_header_tree = proto_item_add_subtree(TIDRDMA_header_item, ett_tidrdma); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_TIDFlowPSN_reserved, tvb, local_offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_TIDFlowPSN, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_TIDFlowQP_reserved, tvb, local_offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_TIDFlowQP, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_VerbsQP_reserved, tvb, local_offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_VerbsQP, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; *parsePayload = FALSE; break; case TID_RDMA_READ_RESPONSE: parse_AETH(tvb, pinfo, tree, &local_offset); col_append_fstr(pinfo->cinfo, COL_INFO, "TID RDMA Read Response: "); TIDRDMA_header_item = proto_tree_add_item(tree, hf_opa_TIDRDMA, tvb, local_offset, 24, ENC_NA); proto_item_set_text(TIDRDMA_header_item, "TID RDMA Read Response Header"); TIDRDMA_header_tree = proto_item_add_subtree(TIDRDMA_header_item, ett_tidrdma); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_reserved, tvb, local_offset, 16, ENC_NA); local_offset += 16; proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_VerbsPSN_reserved, tvb, local_offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_VerbsPSN, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_VerbsQP_reserved, tvb, local_offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_VerbsQP, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; *parsePayload = TRUE; break; case TID_RDMA_RESYNC: col_append_fstr(pinfo->cinfo, COL_INFO, "TID RDMA Read ReSync: "); TIDRDMA_header_item = proto_tree_add_item(tree, hf_opa_TIDRDMA, tvb, local_offset, 28, ENC_NA); proto_item_set_text(TIDRDMA_header_item, "TID RDMA Read ReSync Header"); TIDRDMA_header_tree = proto_item_add_subtree(TIDRDMA_header_item, ett_tidrdma); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_reserved, tvb, local_offset, 24, ENC_NA); local_offset += 24; proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_VerbsQP_reserved, tvb, local_offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_VerbsQP, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; *parsePayload = FALSE; break; case TID_RDMA_ACK: parse_AETH(tvb, pinfo, tree, &local_offset); col_append_fstr(pinfo->cinfo, COL_INFO, "TID RDMA ACK: "); TIDRDMA_header_item = proto_tree_add_item(tree, hf_opa_TIDRDMA, tvb, local_offset, 24, ENC_NA); proto_item_set_text(TIDRDMA_header_item, "TID RDMA ACK Header"); TIDRDMA_header_tree = proto_item_add_subtree(TIDRDMA_header_item, ett_tidrdma); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_reserved, tvb, local_offset, 8, ENC_NA); local_offset += 8; proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_TIDFlowPSN_reserved, tvb, local_offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_TIDFlowPSN, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_VerbsPSN_reserved, tvb, local_offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_VerbsPSN, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_TIDFlowQP_reserved, tvb, local_offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_TIDFlowQP, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_VerbsQP_reserved, tvb, local_offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(TIDRDMA_header_tree, hf_opa_TIDRDMA_VerbsQP, tvb, local_offset, 4, ENC_BIG_ENDIAN); local_offset += 4; *parsePayload = FALSE; break; default: *parsePayload = FALSE; } *offset = local_offset; } static void parse_IPvSix(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset) { call_dissector(ipv6_handle, tvb_new_subset_remaining(tvb, *offset), pinfo, tree); *offset = tvb_reported_length(tvb); } static int dissect_opa_9b(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { proto_item *opa_packet; /* TVB to pass to opa header */ tvbuff_t *opa_tvb; /* TVB to pass to infiniband header */ tvbuff_t *infiniband_tvb; gint offset = 0; /* Current Offset */ gint ib_offset = 0; /* Offset to track if IB packet */ gint captured_length, reported_length; guint8 lnh_val = 0; gboolean bthFollows = FALSE; gboolean parsePayload = FALSE; gint32 nextHeaderSequence = -1; guint8 nextHdr = 0, opCode = 0; guint8 baseVersion = 0; /* Infiniband Check */ lnh_val = tvb_get_guint8(tvb, ib_offset + 1) & 0x3; if (lnh_val == 3) { nextHdr = tvb_get_guint8(tvb, ib_offset + 6); ib_offset += 40; } if (lnh_val == 2 || nextHdr == 0x1B) { opCode = tvb_get_guint8(tvb, ib_offset + 8); if (opCode == 0x64) { baseVersion = tvb_get_guint8(tvb, ib_offset + 28); if (baseVersion == 0x01) { infiniband_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(infiniband_handle, infiniband_tvb, pinfo, tree); return tvb_captured_length(tvb); } } } tree = proto_tree_get_parent_tree(tree); col_set_str(pinfo->cinfo, COL_PROTOCOL, "Omni-Path"); col_clear(pinfo->cinfo, COL_INFO); pinfo->srcport = pinfo->destport = 0xffffffff; opa_packet = proto_tree_add_item(tree, proto_opa_9b, tvb, offset, -1, ENC_NA); /* Headers Level Tree */ tree = proto_item_add_subtree(opa_packet, ett_all_headers); parse_opa_9B_Header(tvb, pinfo, tree, &offset, &lnh_val); switch (lnh_val) { case 3: /* GLOBAL - GRH - Global Route Header */ parse_opa_grh(tvb, pinfo, tree, &offset, &nextHdr); if (nextHdr != 0x1B) { /* no BTH following. */ break; } /* FALL THROUGH */ case 2: /* LOCAL - BTH - Base Transport Header */ parse_opa_bth(tvb, pinfo, tree, &offset, &opCode); bthFollows = TRUE; break; case 1: /* NON OPA - IPv6 Packet */ set_address(&pinfo->dst, AT_STRINGZ, (int)strlen("IPv6 over OPA Packet") + 1, wmem_strdup(pinfo->pool, "IPv6 over OPA Packet")); parse_IPvSix(tvb, pinfo, tree, &offset); break; case 0: /* RAW */ break; default: break; } if (bthFollows) { /* Save transport type for identifying EoOPA payloads later */ nextHeaderSequence = find_next_header_sequence((guint32)opCode); switch (nextHeaderSequence) { case RDETH_DETH_PAYLD: parse_RDETH(tvb, pinfo, tree, &offset); parse_DETH(tvb, pinfo, tree, &offset); parsePayload = TRUE; break; case RDETH_DETH_RETH_PAYLD: parse_RDETH(tvb, pinfo, tree, &offset); parse_DETH(tvb, pinfo, tree, &offset); parse_RETH(tvb, pinfo, tree, &offset); parsePayload = TRUE; break; case RDETH_DETH_IMMDT_PAYLD: parse_RDETH(tvb, pinfo, tree, &offset); parse_DETH(tvb, pinfo, tree, &offset); parse_IMMDT(tvb, pinfo, tree, &offset); parsePayload = TRUE; break; case RDETH_DETH_RETH_IMMDT_PAYLD: parse_RDETH(tvb, pinfo, tree, &offset); parse_DETH(tvb, pinfo, tree, &offset); parse_RETH(tvb, pinfo, tree, &offset); parse_IMMDT(tvb, pinfo, tree, &offset); parsePayload = TRUE; break; case RDETH_DETH_RETH: parse_RDETH(tvb, pinfo, tree, &offset); parse_DETH(tvb, pinfo, tree, &offset); parse_RETH(tvb, pinfo, tree, &offset); break; case RDETH_AETH_PAYLD: parse_RDETH(tvb, pinfo, tree, &offset); parse_AETH(tvb, pinfo, tree, &offset); parsePayload = TRUE; break; case RDETH_PAYLD: parse_RDETH(tvb, pinfo, tree, &offset); parsePayload = TRUE; break; case RDETH_AETH: parse_AETH(tvb, pinfo, tree, &offset); break; case RDETH_AETH_ATOMICACKETH: parse_RDETH(tvb, pinfo, tree, &offset); parse_AETH(tvb, pinfo, tree, &offset); parse_ATOMICACKETH(tvb, pinfo, tree, &offset); break; case RDETH_DETH_ATOMICETH: parse_RDETH(tvb, pinfo, tree, &offset); parse_DETH(tvb, pinfo, tree, &offset); parse_ATOMICETH(tvb, pinfo, tree, &offset); break; case RDETH_DETH: parse_RDETH(tvb, pinfo, tree, &offset); parse_DETH(tvb, pinfo, tree, &offset); break; case DETH_PAYLD: parse_DETH(tvb, pinfo, tree, &offset); parsePayload = TRUE; break; case PAYLD: parsePayload = TRUE; break; case IMMDT_PAYLD: parse_IMMDT(tvb, pinfo, tree, &offset); parsePayload = TRUE; break; case RETH_PAYLD: parse_RETH(tvb, pinfo, tree, &offset); parsePayload = TRUE; break; case RETH: parse_RETH(tvb, pinfo, tree, &offset); break; case AETH_PAYLD: parse_AETH(tvb, pinfo, tree, &offset); parsePayload = TRUE; break; case AETH: parse_AETH(tvb, pinfo, tree, &offset); break; case AETH_ATOMICACKETH: parse_AETH(tvb, pinfo, tree, &offset); parse_ATOMICACKETH(tvb, pinfo, tree, &offset); break; case ATOMICETH: parse_ATOMICETH(tvb, pinfo, tree, &offset); break; case IETH_PAYLD: parse_IETH(tvb, pinfo, tree, &offset); parsePayload = TRUE; break; case DETH_IMMDT_PAYLD: parse_DETH(tvb, pinfo, tree, &offset); parse_IMMDT(tvb, pinfo, tree, &offset); parsePayload = TRUE; break; case KDETH_PSM: parse_KDETH(tvb, pinfo, tree, &offset); parse_PSM(tvb, pinfo, tree, &offset, opCode); break; case KDETH_TIDRDMA: parse_KDETH(tvb, pinfo, tree, &offset); parse_TIDRDMA(tvb, pinfo, tree, &offset, opCode, &parsePayload); break; default: break; } /* END: switch (nextHeaderSequence) */ if (parsePayload) { /* Pass to OPA MAD dissector */ captured_length = tvb_captured_length_remaining(tvb, offset); reported_length = tvb_reported_length_remaining(tvb, offset); if (reported_length >= 4) reported_length -= 4; if (captured_length > reported_length) captured_length = reported_length; if (captured_length > 0) { opa_tvb = tvb_new_subset_length_caplen(tvb, offset, captured_length, reported_length); call_dissector(opa_mad_handle, opa_tvb, pinfo, tree); offset += captured_length; } } } /* END: if(bthFollows) */ /* Display the ICRC */ reported_length = tvb_reported_length_remaining(tvb, offset); if (reported_length != 4) { offset += reported_length - 4; } proto_tree_add_item(tree, hf_opa_9b_ICRC, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; return offset; } void proto_register_opa_9b(void) { static hf_register_info hf[] = { /* L2Header(9B) */ { &hf_opa_9B, { "Omni-Path 9B Header", "opa.9b", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_opa_9B_service_channel, { "Service Channel", "opa.9b.sc", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL } }, { &hf_opa_9B_link_version, { "Link Version", "opa.9b.linkversion", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL } }, { &hf_opa_9B_service_level, { "Service Level", "opa.9b.sl", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL } }, { &hf_opa_9B_reserved2, { "Reserved (2 bits)", "opa.9b.reserved2", FT_UINT8, BASE_HEX, NULL, 0x0C, NULL, HFILL } }, { &hf_opa_9B_lnh, { "Link Next Header", "opa.9b.lnh", FT_UINT8, BASE_DEC, VALS(vals_opa_9b_lnh), 0x03, NULL, HFILL } }, { &hf_opa_9B_dlid, { "Dest LID", "opa.9b.dlid", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_opa_9B_reserved3, { "Reserved (4 bits)", "opa.9b.reserved3", FT_UINT16, BASE_HEX, NULL, 0xF000, NULL, HFILL } }, { &hf_opa_9B_packet_length, { "Packet Length", "opa.length", FT_UINT16, BASE_CUSTOM, CF_FUNC(cf_opa_dw_to_b), 0x0FFF, NULL, HFILL } }, { &hf_opa_9B_slid, { "Source LID", "opa.9b.slid", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_opa_9b_ICRC, { "Invariant CRC", "opa.9b.icrc", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, /* Global Route Header */ { &hf_opa_grh, { "GRH - Global Route Header", "opa.grh", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_opa_grh_ip_version, { "IP Version", "opa.grh.ipver", FT_UINT8, BASE_DEC, VALS(vals_opa_9b_grh_ipver), 0xF0, NULL, HFILL } }, { &hf_opa_grh_traffic_class, { "Traffic Class", "opa.grh.tclass", FT_UINT16, BASE_DEC, NULL, 0x0FF0, NULL, HFILL } }, { &hf_opa_grh_flow_label, { "Flow Label", "opa.grh.flowlabel", FT_UINT32, BASE_DEC, NULL, 0x000FFFFF, NULL, HFILL } }, { &hf_opa_grh_payload_length, { "Payload Length", "opa.grh.paylen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_opa_grh_next_header, { "Next Header", "opa.grh.nxthdr", FT_UINT8, BASE_DEC, VALS(vals_opa_9b_grh_next_hdr), 0x0, NULL, HFILL } }, { &hf_opa_grh_hop_limit, { "Hop Limit", "opa.grh.hoplmt", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_opa_grh_source_gid, { "Source GID", "opa.grh.sgid", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_opa_grh_destination_gid, { "Destination GID", "opa.grh.dgid", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL } }, /* Base Transport Header */ { &hf_opa_bth, { "BTH - Base Transport Header", "opa.bth", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_opa_bth_opcode, { "Opcode", "opa.bth.opcode", FT_UINT8, BASE_HEX, VALS(vals_opa_bth_opcode), 0x0, NULL, HFILL } }, { &hf_opa_bth_solicited_event, { "Solicited Event", "opa.bth.se", FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x80, NULL, HFILL } }, { &hf_opa_bth_migreq, { "MigReq", "opa.bth.m", FT_BOOLEAN, 8, TFS(&tfs_opa_bth_migrated_notmigrated), 0x40, NULL, HFILL } }, { &hf_opa_bth_pad_count, { "Pad Count", "opa.bth.padcnt", FT_UINT8, BASE_DEC, NULL, 0x30, NULL, HFILL } }, { &hf_opa_bth_transport_header_version, { "Header Version", "opa.bth.tver", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL } }, { &hf_opa_bth_partition_key, { "Partition Key", "opa.bth.p_key", FT_UINT16, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_opa_bth_fcn, { "FCN", "opa.bth.fcn", FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x80, NULL, HFILL } }, { &hf_opa_bth_bcn, { "BCN", "opa.bth.bcn", FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x40, NULL, HFILL } }, { &hf_opa_bth_Reserved8a, { "Reserved (6 bits)", "opa.bth.reserved8a", FT_UINT8, BASE_HEX, NULL, 0x3F, NULL, HFILL } }, { &hf_opa_bth_destination_qp, { "Destination Queue Pair", "opa.bth.destqp", FT_UINT24, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_opa_bth_acknowledge_request, { "Acknowledge Request", "opa.bth.a", FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x80, NULL, HFILL } }, { &hf_opa_bth_packet_sequence_number, { "Packet Sequence Number", "opa.bth.psn", FT_UINT32, BASE_DEC, NULL, 0x7FFFFFFF, NULL, HFILL } }, /* Reliable Datagram Extended Transport Header (RDETH) */ { &hf_opa_RDETH, { "RDETH - Reliable Datagram Extended Transport Header", "opa.rdeth", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_opa_RDETH_reserved8, { "Reserved (8 bits)", "opa.rdeth.reserved", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_opa_RDETH_ee_context, { "EE Context", "opa.rdeth.eecnxt", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL } }, /* Datagram Extended Transport Header (DETH) */ { &hf_opa_DETH, { "DETH - Datagram Extended Transport Header", "opa.deth", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_opa_DETH_queue_key, { "Queue Key", "opa.deth.q_key", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_opa_DETH_reserved8, { "Reserved (8 bits)", "opa.deth.reserved", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_opa_DETH_source_qp, { "Source Queue Pair", "opa.deth.srcqp", FT_UINT24, BASE_HEX, NULL, 0x0, NULL, HFILL } }, /* RDMA Extended Transport Header (RETH) */ { &hf_opa_RETH, { "RETH - RDMA Extended Transport Header", "opa.reth", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_opa_RETH_virtual_address, { "Virtual Address", "opa.reth.va", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_opa_RETH_remote_key, { "Remote Key", "opa.reth.r_key", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_opa_RETH_dma_length, { "DMA Length", "opa.reth.dmalen", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, /* Atomic Extended Transport Header (AtomicETH) */ { &hf_opa_AtomicETH, { "AtomicETH - Atomic Extended Transport Header", "opa.atomiceth", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_opa_AtomicETH_virtual_address, { "Virtual Address", "opa.atomiceth.va", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_opa_AtomicETH_remote_key, { "Remote Key", "opa.atomiceth.r_key", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_opa_AtomicETH_swap_or_add_data, { "Swap (Or Add) Data", "opa.atomiceth.swapdt", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_opa_AtomicETH_compare_data, { "Compare Data", "opa.atomiceth.cmpdt", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, /* ACK Extended Transport Header (AETH) */ { &hf_opa_AETH, { "AETH - ACK Extended Transport Header", "opa.aeth", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_opa_AETH_syndrome, { "Syndrome", "opa.aeth.syndrome", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_opa_AETH_message_sequence_number, { "Message Sequence Number", "opa.aeth.msn", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL } }, /* Atomic ACK Extended Transport Header (AtomicAckETH) */ { &hf_opa_AtomicAckETH, { "AtomicAckETH - Atomic ACK Extended Transport Header", "opa.atomicacketh", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_opa_AtomicAckETH_original_remote_data, { "Original Remote Data", "opa.atomicacketh.origremdt", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, /* Immediate Extended Transport Header (ImmDT) */ { &hf_opa_IMMDT, { "IMMDT - Immediate Extended Transport Header", "opa.immdt", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_opa_IMMDT_data, { "Immediate Data", "opa.immdt.data", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, /* Invalidate Extended Transport Header (IETH) */ { &hf_opa_IETH, { "IETH - Invalidate Extended Transport Header", "opa.ieth", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_opa_IETH_r_key, { "RKey", "opa.ieth.r_key", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, /* Key Datagram Extended Transport Header (KDETH) */ { &hf_opa_KDETH, { "KDETH - Key Datagram Extended Transport Header", "opa.kdeth", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_opa_KDETH_kver, { "KDETH Version Field", "opa.kdeth.kver", FT_UINT32, BASE_HEX, NULL, 0xC0000000, NULL, HFILL } }, { &hf_opa_KDETH_sh, { "SuppressHeader", "opa.kdeth.sh", FT_BOOLEAN, 32, NULL, 0x20000000, NULL, HFILL } }, { &hf_opa_KDETH_intr, { "InterruptBit", "opa.kdeth.intr", FT_BOOLEAN, 32, NULL, 0x10000000, NULL, HFILL } }, { &hf_opa_KDETH_tidctrl, { "TokenIDCtrl", "opa.kdeth.tidctrl", FT_UINT32, BASE_HEX, NULL, 0x0C000000, NULL, HFILL } }, { &hf_opa_KDETH_tid, { "TokenID", "opa.kdeth.tid", FT_UINT32, BASE_HEX, NULL, 0x03FF0000, NULL, HFILL } }, { &hf_opa_KDETH_offset_mode, { "Offset Mode", "opa.kdeth.offsetmode", FT_BOOLEAN, 32, TFS(&tfs_opa_kdeth_offset_32_64), 0x00008000, NULL, HFILL } }, { &hf_opa_KDETH_offset, { "Offset", "opa.kdeth.offset", FT_UINT32, BASE_HEX, NULL, 0x00007FFF, NULL, HFILL } }, { &hf_opa_KDETH_hcrc, { "HCRC", "opa.kdeth.hcrc", FT_UINT32, BASE_HEX, NULL, 0xFFFF0000, NULL, HFILL } }, { &hf_opa_KDETH_j_key, { "J_Key", "opa.kdeth.j_key", FT_UINT32, BASE_HEX, NULL, 0x0000FFFF, NULL, HFILL } }, /* PSM */ { &hf_opa_psm, { "PSM Header", "opa.psm", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_opa_psm_a, { "ACKFlag", "opa.psm.a", FT_UINT8, BASE_HEX, NULL, 0x80, NULL, HFILL } }, { &hf_opa_psm_ackpsn, { "ACKPSN", "opa.psm.ackpsn", FT_UINT32, BASE_DEC, NULL, 0x7FFF, NULL, HFILL } }, { &hf_opa_psm_flags, { "Flags", "opa.psm.flags", FT_UINT8, BASE_DEC, NULL, 0xFC, NULL, HFILL } }, { &hf_opa_psm_commidx, { "CommIdx", "opa.psm.commidx", FT_UINT32, BASE_HEX, NULL, 0x3FFF, NULL, HFILL } }, { &hf_opa_psm_flowid, { "FlowId", "opa.psm.flowid", FT_UINT8, BASE_HEX, NULL, 0x80, NULL, HFILL } }, /* PSM opcode specific */ { &hf_opa_psm_msglen, { "MsgLen", "opa.psm.msglen", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_opa_psm_msgseq, { "MsqSeq", "opa.psm.msgseq", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_opa_psm_tag, { "Tag", "opa.psm.tag", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_opa_psm_msgdata, { "MsqData", "opa.psm.msgdata", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_opa_psm_short_msglen, { "MsgLen", "opa.psm.short.msglen", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_opa_psm_paylen, { "PayLen", "opa.psm.paylen", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_opa_psm_offset, { "Offset", "opa.psm.offset", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_opa_psm_sreqidx, { "SreqIdx", "opa.psm.sreqidx", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_opa_psm_rreqidx, { "RreqIdx", "opa.psm.rreqidx", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_opa_psm_rdescid, { "RdescId", "opa.psm.rdescid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_opa_psm_sdescid, { "SdescId", "opa.psm.sdescid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_opa_psm_psn, { "PSN", "opa.psm.psn", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_opa_psm_hostipv4, { "HostIPv4Addr", "opa.psm.hostipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_opa_psm_hostpid, { "HostPid", "opa.psm.hostpid", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_opa_psm_dlen, { "Datalength", "opa.psm.dlen", FT_UINT8, BASE_DEC, NULL, 0x38, NULL, HFILL } }, { &hf_opa_psm_nargs, { "NumberArgs", "opa.psm.nargs", FT_UINT32, BASE_DEC, NULL, 0x07, NULL, HFILL } }, { &hf_opa_psm_hidx, { "HandlerIndex", "opa.psm.hidx", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_opa_psm_arg, { "Argument", "opa.psm.arg", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_opa_psm_payload, { "Payload", "opa.psm.payload", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_opa_TIDRDMA, { "TID RDMA Header", "opa.tidrdma", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_opa_TIDRDMA_reserved, { "Reserved", "opa.tidrdma.reserved", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_opa_TIDRDMA_TIDFlowPSN_reserved, { "Reserved (1 bit)", "opa.tidrdma.tidflowpsn.reserved", FT_UINT32, BASE_HEX, NULL, 0x80000000, NULL, HFILL } }, { &hf_opa_TIDRDMA_TIDFlowPSN, { "TID Flow PSN", "opa.tidrdma.tidflowpsn", FT_UINT32, BASE_HEX, NULL, 0x7FFFFFFF, NULL, HFILL } }, { &hf_opa_TIDRDMA_TIDFlowQP_reserved, { "Reserved (8 bits)", "opa.tidrdma.tidflowqp.reserved", FT_UINT32, BASE_HEX, NULL, 0xFF000000, NULL, HFILL } }, { &hf_opa_TIDRDMA_TIDFlowQP, { "TID Flow QP", "opa.tidrdma.tidflowqp", FT_UINT32, BASE_HEX, NULL, 0x00FFFFFF, NULL, HFILL } }, { &hf_opa_TIDRDMA_VerbsPSN_reserved, { "Reserved (1 bit)", "opa.tidrdma.verbspsn.reserved", FT_UINT32, BASE_HEX, NULL, 0x80000000, NULL, HFILL } }, { &hf_opa_TIDRDMA_VerbsPSN, { "Verbs PSN", "opa.tidrdma.verbspsn", FT_UINT32, BASE_HEX, NULL, 0x7FFFFFFF, NULL, HFILL } }, { &hf_opa_TIDRDMA_VerbsQP_reserved, { "Reserved (8 bits)", "opa.tidrdma.verbsqp.reserved", FT_UINT32, BASE_HEX, NULL, 0xFF000000, NULL, HFILL } }, { &hf_opa_TIDRDMA_VerbsQP, { "Verbs QP", "opa.tidrdma.verbsqp", FT_UINT32, BASE_HEX, NULL, 0x00FFFFFF, NULL, HFILL } } }; static gint *ett[] = { &ett_all_headers, &ett_9b, &ett_grh, &ett_bth, &ett_rdeth, &ett_deth, &ett_reth, &ett_atomiceth, &ett_aeth, &ett_atomicacketh, &ett_immdt, &ett_ieth, &ett_kdeth, &ett_psm, &ett_tidrdma }; proto_opa_9b = proto_register_protocol("Intel Omni-Path", "OPA", "opa"); opa_9b_handle = register_dissector("opa", dissect_opa_9b, proto_opa_9b); proto_register_field_array(proto_opa_9b, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); } void proto_reg_handoff_opa_9b(void) { ipv6_handle = find_dissector("ipv6"); opa_mad_handle = find_dissector("opa.mad"); infiniband_handle = find_dissector("infiniband"); /* announce an anonymous Omni-Path 9B dissector */ dissector_add_uint("erf.types.type", ERF_TYPE_OPA_9B, opa_9b_handle); } /* * Editor modelines - https://www.wireshark.org/tools/modelines.html * * Local variables: * c-basic-offset: 4 * tab-width: 8 * indent-tabs-mode: nil * End: * * vi: set shiftwidth=4 tabstop=8 expandtab: * :indentSize=4:tabSize=8:noTabs=true: */