diff options
Diffstat (limited to 'plugins/wimax/mac_hd_generic_decoder.c')
-rw-r--r-- | plugins/wimax/mac_hd_generic_decoder.c | 2298 |
1 files changed, 2298 insertions, 0 deletions
diff --git a/plugins/wimax/mac_hd_generic_decoder.c b/plugins/wimax/mac_hd_generic_decoder.c new file mode 100644 index 0000000000..3f0b0bcc1c --- /dev/null +++ b/plugins/wimax/mac_hd_generic_decoder.c @@ -0,0 +1,2298 @@ +/* mac_hd_generic_decoder.c + * WiMax Generic MAC Header decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan <lu.pan@intel.com> + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1999 Gerald Combs + * + * 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 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* TODO: Add FT_UINT24 and FT_INT24 cases to gtk_widget_get_toplevel() + * to prevent having to make all the changes from BASE_DEC to BASE_HEX + * made to this file today: 10/20/06. + */ + +/* Include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* +#define DEBUG +*/ + +#include "moduleinfo.h" + +#include <string.h> +#include <glib.h> +#include <epan/packet.h> +#include <epan/prefs.h> +#include <epan/address.h> +#include <epan/reassemble.h> +#include "crc.h" + +extern gint proto_wimax; + +extern gint seen_a_service_type; +extern gboolean first_gmh; /* defined in wimax_pdu_decoder.c */ +guint get_service_type( void ); /* defined in wimax_utils.c */ + +extern gint8 arq_enabled; /* declared in packet-wmx.c */ +extern gint scheduling_service_type; /* declared in packet-wmx.c */ +extern gint mac_sdu_length; /* declared in packet-wmx.c */ + +extern address bs_address; /* declared in packet-wmx.c */ +extern guint max_logical_bands; /* declared in wimax_compact_dlmap_ie_decoder.c */ +extern gboolean is_down_link(address *src_address);/* declared in packet-wmx.c */ +extern void proto_register_mac_mgmt_msg(void); /* defined in macmgmtmsgdecoder.c */ +extern void init_wimax_globals(); /* defined in msg_ulmap.c */ + +extern void dissect_mac_mgmt_msg_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); + +/* global variables */ +gboolean include_cor2_changes = FALSE; + +/* Well-known CIDs */ +guint cid_initial_ranging = 0x0000; +guint global_cid_max_basic = 320; +guint cid_max_primary = 640; +guint cid_aas_ranging = 0xFeFF; +guint cid_normal_multicast = 0xFFFa; +guint cid_sleep_multicast = 0xFFFb; +guint cid_idle_multicast = 0xFFFc; +guint cid_frag_broadcast = 0xFFFd; +guint cid_padding = 0xFFFe; +guint cid_broadcast = 0xFFFF; + +/* Maximum number of CID's */ +#define MAX_CID 64 + +/* forward reference */ +void dissect_mac_header_generic_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); +static gint extended_subheader_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); +static gint arq_feedback_payload_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *parent_item); + +/* Static variables */ +static GHashTable *payload_frag_table = NULL; + +gint proto_mac_header_generic_decoder = -1; +static gint ett_mac_header_generic_decoder = -1; +static gint ett_mac_subheader_decoder = -1; +static gint ett_mac_mesh_subheader_decoder = -1; +static gint ett_mac_frag_subheader_decoder = -1; +static gint ett_mac_grant_mgmt_subheader_decoder = -1; +static gint ett_mac_pkt_subheader_decoder = -1; +static gint ett_mac_fast_fb_subheader_decoder = -1; +static gint ett_mac_ext_subheader_decoder = -1; +static gint ett_mac_ext_subheader_dl_decoder = -1; +static gint ett_mac_ext_subheader_ul_decoder = -1; +static gint ett_mac_arq_fb_payload_decoder = -1; +static gint ett_mac_data_pdu_decoder = -1; +static gint hf_mac_header_generic_value_bytes = -1; + +static guint frag_type, frag_len; +static guint extended_type, arq_fb_payload, seq_number; + +static guint cid_adjust[MAX_CID]; /* Must not start with 0 */ +static guint cid_vernier[MAX_CID]; +static guint cid_adj_array_size = 0; +static guint *cid_adj_array = NULL; +static guint8 *frag_num_array = NULL; + +static address save_src; +static address save_dst; + +/* Setup protocol subtree array */ +static gint *ett[] = +{ + &ett_mac_header_generic_decoder, + &ett_mac_subheader_decoder, + &ett_mac_mesh_subheader_decoder, + &ett_mac_frag_subheader_decoder, + &ett_mac_grant_mgmt_subheader_decoder, + &ett_mac_pkt_subheader_decoder, + &ett_mac_fast_fb_subheader_decoder, + &ett_mac_ext_subheader_decoder, + &ett_mac_ext_subheader_dl_decoder, + &ett_mac_ext_subheader_ul_decoder, + &ett_mac_arq_fb_payload_decoder, + &ett_mac_data_pdu_decoder, +}; + +#define WIMAX_MAC_HEADER_SIZE 6 +#define IP_HEADER_BYTE 0x45 + +#define EXTENDED_SUB_HEADER_RSV_MASK 0x80 +#define EXTENDED_SUB_HEADER_TYPE_MASK 0x7F + +/* WIMAX GENERIC MAC HEADER FIELDS (figure 19) */ +/* 1st to 3rd bytes */ +#define WIMAX_MAC_HEADER_GENERIC_HT 0x800000 +#define WIMAX_MAC_HEADER_GENERIC_EC 0x400000 +#define WIMAX_MAC_HEADER_GENERIC_TYPE_5 0x200000 +#define WIMAX_MAC_HEADER_GENERIC_TYPE_4 0x100000 +#define WIMAX_MAC_HEADER_GENERIC_TYPE_3 0x080000 +#define WIMAX_MAC_HEADER_GENERIC_TYPE_2 0x040000 +#define WIMAX_MAC_HEADER_GENERIC_TYPE_1 0x020000 +#define WIMAX_MAC_HEADER_GENERIC_TYPE_0 0x010000 +#define WIMAX_MAC_HEADER_GENERIC_ESF 0x008000 +#define WIMAX_MAC_HEADER_GENERIC_CI 0x004000 +#define WIMAX_MAC_HEADER_GENERIC_EKS 0x003000 +#define WIMAX_MAC_HEADER_GENERIC_RSV 0x000800 +#define WIMAX_MAC_HEADER_GENERIC_LEN 0x0007FF + +/* WIMAX GENERIC MAC HEADER 1st byte masks */ +#define WIMAX_MAC_HEADER_GENERIC_HT_MASK 0x80 +#define WIMAX_MAC_HEADER_GENERIC_EC_MASK 0x40 +#define WIMAX_MAC_HEADER_GENERIC_TYPE_MASK 0x3F +/* WiMax Generic MAC Header Sub Type Masks */ +#define GENERIC_SUB_TYPE_0 0x01 +#define GENERIC_SUB_TYPE_1 0x02 +#define GENERIC_SUB_TYPE_2 0x04 +#define GENERIC_SUB_TYPE_3 0x08 +#define GENERIC_SUB_TYPE_4 0x10 +#define GENERIC_SUB_TYPE_5 0x20 + +/* WIMAX GENERIC MAC HEADER 2nd byte masks */ +#define WIMAX_MAC_HEADER_GENERIC_ESF_MASK 0x80 +#define WIMAX_MAC_HEADER_GENERIC_CI_MASK 0x40 +#define WIMAX_MAC_HEADER_GENERIC_EKS_MASK 0x30 +#define WIMAX_MAC_HEADER_GENERIC_LEN_MASK 0x07 + +static int hf_mac_header_generic_ht = -1; +static int hf_mac_header_generic_ec = -1; +static int hf_mac_header_generic_type_0 = -1; +static int hf_mac_header_generic_type_1 = -1; +static int hf_mac_header_generic_type_2 = -1; +static int hf_mac_header_generic_type_3 = -1; +static int hf_mac_header_generic_type_4 = -1; +static int hf_mac_header_generic_type_5 = -1; +static int hf_mac_header_generic_esf = -1; +static int hf_mac_header_generic_ci = -1; +static int hf_mac_header_generic_eks = -1; +static int hf_mac_header_generic_rsv = -1; +static int hf_mac_header_generic_len = -1; +static int hf_mac_header_generic_cid = -1; +static int hf_mac_header_generic_hcs = -1; +static int hf_mac_header_generic_crc = -1; + +/* MAC Header types */ +static const value_string ht_msgs[] = +{ + { 0, "Generic" }, + { 1, "Signaling" }, + { 0, NULL} +}; + +/* Encryption Controls */ +static const value_string ec_msgs[] = +{ + { 0, "Not encrypted" }, + { 1, "Encrypted" }, + { 0, NULL} +}; + +/* ESF messages */ +static const value_string esf_msgs[] = +{ + { 0, "Extended subheader is absent" }, + { 1, "Extended subheader is present" }, + { 0, NULL} +}; + +/* CRC Indicator messages */ +static const value_string ci_msgs[] = +{ + { 0, "No CRC is included" }, + { 1, "CRC is included" }, + { 0, NULL} +}; + +/* Sub-Type message 0 */ +static const value_string type_msg0[] = +{ + { 0, "Fast-feedback allocation subheader(DL)/Grant management subheader(UL) is absent" }, + { 1, "Fast-feedback allocation subheader(DL)/Grant management subheader(UL) is present" }, + { 0, NULL} +}; + +/* Sub-Type message 1 */ +static const value_string type_msg1[] = +{ + { 0, "Packing subheader is absent" }, + { 1, "Packing Subheader is present" }, + { 0, NULL} +}; + +/* Sub-Type message 2 */ +static const value_string type_msg2[] = +{ + { 0, "Fragmentation subheader is absent" }, + { 1, "Fragmentation subheader is present" }, + { 0, NULL} +}; + +/* Sub-Type message 3 */ +static const value_string type_msg3[] = +{ + { 0, "The subheader is not extended" }, + { 1, "The subheader is extended" }, + { 0, NULL} +}; + +/* Sub-Type message 4 */ +static const value_string type_msg4[] = +{ + { 0, "ARQ feedback payload is absent" }, + { 1, "ARQ feedback payload is present" }, + { 0, NULL} +}; + +/* Sub-Type message 5 */ +static const value_string type_msg5[] = +{ + { 0, "Mesh subheader is absent" }, + { 1, "Mesh subheader is present" }, + { 0, NULL} +}; + +/* Fast-Feedback Feedback Types */ +static const value_string fast_fb_types[] = +{ + { 0, "Fast DL measurement" }, + { 1, "Fast MIMO Feedback, Antenna #0" }, + { 2, "Fast MIMO Feedback, Antenna #1" }, + { 3, "MIMO Mode and Permutation Mode Feedback" }, + { 0, NULL} +}; + +/* Generic MAC header display */ +static hf_register_info hf[] = +{ + { + &hf_mac_header_generic_value_bytes, + { + "Values", "wimax.genericValueBytes", + FT_BYTES, BASE_HEX, NULL, 0x0, + "", HFILL + } + }, + { + &hf_mac_header_generic_ht, + { + "MAC Header Type", "wimax.genericHt", + FT_UINT24, BASE_HEX, VALS(ht_msgs), WIMAX_MAC_HEADER_GENERIC_HT, + "", HFILL + } + }, + { + &hf_mac_header_generic_ec, + { + "MAC Encryption Control", "wimax.genericEc", + FT_UINT24, BASE_HEX, VALS(ec_msgs), WIMAX_MAC_HEADER_GENERIC_EC, + "", HFILL + } + }, + { + &hf_mac_header_generic_type_0, + { + "MAC Sub-type Bit 0", "wimax.genericType0", + FT_UINT24, BASE_HEX, VALS(type_msg0), WIMAX_MAC_HEADER_GENERIC_TYPE_0, + "", HFILL + } + }, + { + &hf_mac_header_generic_type_1, + { + "MAC Sub-type Bit 1", "wimax.genericType1", + FT_UINT24, BASE_HEX, VALS(type_msg1), WIMAX_MAC_HEADER_GENERIC_TYPE_1, + "", HFILL + } + }, + { + &hf_mac_header_generic_type_2, + { + "MAC Sub-type Bit 2", "wimax.genericType2", + FT_UINT24, BASE_HEX, VALS(type_msg2), WIMAX_MAC_HEADER_GENERIC_TYPE_2, + "", HFILL + } + }, + { + &hf_mac_header_generic_type_3, + { + "MAC Sub-type Bit 3", "wimax.genericType3", + FT_UINT24, BASE_HEX, VALS(type_msg3), WIMAX_MAC_HEADER_GENERIC_TYPE_3, + "", HFILL + } + }, + { + &hf_mac_header_generic_type_4, + { + "MAC Sub-type Bit 4", "wimax.genericType4", + FT_UINT24, BASE_HEX, VALS(type_msg4), WIMAX_MAC_HEADER_GENERIC_TYPE_4, + "", HFILL + } + }, + { + &hf_mac_header_generic_type_5, + { + "MAC Sub-type Bit 5", "wimax.genericType5", + FT_UINT24, BASE_HEX, VALS(type_msg5), WIMAX_MAC_HEADER_GENERIC_TYPE_5, + "", HFILL + } + }, + { + &hf_mac_header_generic_esf, + { + "Extended Sub-header Field", "wimax.genericEsf", + FT_UINT24, BASE_HEX, VALS(esf_msgs), WIMAX_MAC_HEADER_GENERIC_ESF, + "", HFILL + } + }, + { + &hf_mac_header_generic_ci, + { + "CRC Indicator", "wimax.genericCi", + FT_UINT24, BASE_HEX, VALS(ci_msgs), WIMAX_MAC_HEADER_GENERIC_CI, + "", HFILL + } + }, + { + &hf_mac_header_generic_eks, + { + "Encryption Key Sequence", "wimax.genericEks", + FT_UINT24, BASE_HEX, NULL, WIMAX_MAC_HEADER_GENERIC_EKS, + "", HFILL + } + }, + { + &hf_mac_header_generic_rsv, + { + "Reserved", "wimax.genericRsv", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_GENERIC_RSV, + "", HFILL + } + }, + { + &hf_mac_header_generic_len, + { + "Length", "wimax.genericLen", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_GENERIC_LEN, + "", HFILL + } + }, + { + &hf_mac_header_generic_cid, + { + "Connection ID", "wimax.genericCid", + FT_UINT16, BASE_DEC, NULL, 0x0, + "", HFILL + } + }, + { + &hf_mac_header_generic_hcs, + { + "Header Check Sequence", "wimax.genericHcs", + FT_UINT8, BASE_HEX, NULL, 0x0, + "", HFILL + } + }, + { + &hf_mac_header_generic_crc, + { + "CRC", "wimax.genericCrc", + FT_UINT32, BASE_HEX, NULL, 0x0, + "", HFILL + } + } +}; + +/* Extended sub-headers */ +/* DL sub-header types */ +enum +{ +SDU_SN, +DL_SLEEP_CONTROL, +FEEDBACK_REQ, +SN_REQ, +PDU_SN_SHORT_DL, +PDU_SN_LONG_DL +} DL_EXT_SUBHEADER; + +static const value_string dl_ext_sub_header_type[] = +{ + {0, "SDU_SN"}, + {1, "DL Sleep Control"}, + {2, "Feedback Request"}, + {3, "SN Request"}, + {4, "PDU SN (short)"}, + {5, "PDU SN (long)"}, + {0, NULL} +}; + +/* DL Sleep Control Extended Subheader field masks (table 13e) */ +#define DL_SLEEP_CONTROL_POWER_SAVING_CLASS_ID_MASK 0xFC0000 /*0x00003F*/ +#define DL_SLEEP_CONTROL_OPERATION_MASK 0x020000 /*0x000040*/ +#define DL_SLEEP_CONTROL_FINAL_SLEEP_WINDOW_EXPONENT_MASK 0x01C000 /*0x000380*/ +#define DL_SLEEP_CONTROL_FINAL_SLEEP_WINDOW_BASE_MASK 0x003FF0 /*0x0FFC00*/ +#define DL_SLEEP_CONTROL_RESERVED_MASK 0x00000F /*0xF00000*/ + +/* Feedback Request Extended Subheader field masks (table 13f) */ +#define FEEDBACK_REQUEST_UIUC_MASK 0xF00000 /*0x00000F*/ +#define FEEDBACK_REQUEST_FEEDBACK_TYPE_MASK 0x0F0000 /*0x0000F0*/ +#define FEEDBACK_REQUEST_OFDMA_SYMBOL_OFFSET_MASK 0x00FC00 /*0x003F00*/ +#define FEEDBACK_REQUEST_SUBCHANNEL_OFFSET_MASK 0x0003F0 /*0x0FC000*/ +#define FEEDBACK_REQUEST_NUMBER_OF_SLOTS_MASK 0x00000E /*0x700000*/ +#define FEEDBACK_REQUEST_FRAME_OFFSET_MASK 0x000001 /*0x800000*/ + +/* OFDMA UIUC Values ??? */ +static const value_string uiuc_values[] = +{ + { 0, "Fast-Feedback Channel" }, + { 1, "Burst Profile 1" }, + { 2, "Burst Profile 2" }, + { 3, "Burst Profile 3" }, + { 4, "Burst Profile 4" }, + { 5, "Burst Profile 5" }, + { 6, "Burst Profile 6" }, + { 7, "Burst Profile 7" }, + { 8, "Burst Profile 8" }, + { 9, "Burst Profile 9" }, + { 10, "Burst Profile 10" }, + { 11, "Extended UIUC 2 IE" }, + { 12, "CDMA Bandwidth Request, CDMA Ranging" }, + { 13, "PAPR Reduction Allocation, Safety Zone" }, + { 14, "CDMA Allocation IE" }, + { 15, "Extended UIUC" }, + { 0, NULL} +}; + +/* UL sub-header types */ +enum +{ +MIMO_MODE_FEEDBACK, +UL_TX_POWER_REPORT, +MINI_FEEDBACK, +PDU_SN_SHORT_UL, +PDU_SN_LONG_UL +} UL_EXT_SUBHEADER; + +static const value_string ul_ext_sub_header_type[] = +{ + {0, "MIMO Mode Feedback"}, + {1, "UL TX Power Report"}, + {2, "Mini-feedback"}, + {3, "PDU SN (short)"}, + {4, "PDU SN (long)"}, + {0, NULL} +}; + +/* MIMO Mode Feedback Extended Subheader field masks (table 13g) */ +#define MIMO_FEEDBACK_TYPE_MASK 0xC0 /*0x03*/ +#define MIMO_FEEDBACK_CONTENT_MASK 0x3F /*0xFC*/ +/* Mimo Feedback Types ??? */ +static const value_string mimo_fb_types[] = +{ + { 0, "Fast DL measurement" }, + { 1, "Default Feedback with Antenna Grouping" }, + { 2, "Antenna Selection and Reduced Codebook" }, + { 3, "Quantized Precoding Weight Feedback" }, + { 0, NULL} +}; + +/* MNI-Feedback Extended Subheader field masks (table 13i) */ +#define MINI_FEEDBACK_TYPE_MASK 0xF000 /*0x000F*/ +#define MINI_FEEDBACK_CONTENT_MASK 0x0FFF /*0xFFF0*/ +/* Feedback Types */ +static const value_string fb_types[] = +{ + { 0, "CQI and MIMO Feedback" }, + { 1, "DL average CINR" }, + { 2, "MIMO Coefficients Feedback" }, + { 3, "Preferred DL Channel DIUC Feedback" }, + { 4, "UL Transmission Power" }, + { 5, "PHY Channel Feedback" }, + { 6, "AMC Band Indication Bitmap" }, + { 7, "Life Span of Short-term Precoding Feedback" }, + { 8, "Multiple Types of Feedback" }, + { 9, "Long-term Precoding Feedback" }, + { 10, "Combined DL Average CINR of Active BSs" }, + { 11, "MIMO Channel Feedback" }, + { 12, "CINR Feedback" }, + { 13, "Close-loop MIMO Feedback" }, + { 14, "Reserved" }, + { 15, "Reserved" }, + { 0, NULL} +}; + +/* common fields */ +static gint hf_mac_header_generic_ext_subheader_rsv = -1; +/* DL sub-header */ +static gint hf_mac_header_generic_ext_subheader_type_dl = -1; +static gint hf_mac_header_generic_ext_subheader_sdu_sn = -1; +static gint hf_mac_header_generic_ext_subheader_dl_sleep_control_pscid = -1; +static gint hf_mac_header_generic_ext_subheader_dl_sleep_control_op = -1; +static gint hf_mac_header_generic_ext_subheader_dl_sleep_control_fswe = -1; +static gint hf_mac_header_generic_ext_subheader_dl_sleep_control_fswb = -1; +static gint hf_mac_header_generic_ext_subheader_dl_sleep_control_rsv = -1; +static gint hf_mac_header_generic_ext_subheader_fb_req_uiuc = -1; +static gint hf_mac_header_generic_ext_subheader_fb_req_fb_type = -1; +static gint hf_mac_header_generic_ext_subheader_fb_req_ofdma_symbol_offset = -1; +static gint hf_mac_header_generic_ext_subheader_fb_req_subchannel_offset = -1; +static gint hf_mac_header_generic_ext_subheader_fb_req_slots = -1; +static gint hf_mac_header_generic_ext_subheader_fb_req_frame_offset = -1; + +/* DL Sleep Control Operations */ +static const value_string dl_sleep_control_ops[] = +{ + { 0, "De-activate Power Saving Class" }, + { 1, "Activate Power Saving Class" }, + { 0, NULL} +}; + +/* UL sub-header */ +static gint hf_mac_header_generic_ext_subheader_type_ul = -1; +static gint hf_mac_header_generic_ext_subheader_mimo_mode_fb_type = -1; +static gint hf_mac_header_generic_ext_subheader_mimo_fb_content = -1; +static gint hf_mac_header_generic_ext_subheader_ul_tx_pwr_rep = -1; +static gint hf_mac_header_generic_ext_subheader_mini_fb_type = -1; +static gint hf_mac_header_generic_ext_subheader_mini_fb_content = -1; +/* common fields */ +static gint hf_mac_header_generic_ext_subheader_pdu_sn_short = -1; +static gint hf_mac_header_generic_ext_subheader_pdu_sn_long = -1; + +/* SN Request subheader */ +#define SN_REQUEST_SUBHEADER_SN_REPORT_INDICATION_1_MASK 0x01 +#define SN_REQUEST_SUBHEADER_SN_REPORT_INDICATION_2_MASK 0x02 +#define SN_REQUEST_SUBHEADER_RESERVED_MASK 0xFC + +static gint hf_mac_header_generic_ext_subheader_sn_req_rep_ind_1 = -1; +static gint hf_mac_header_generic_ext_subheader_sn_req_rep_ind_2 = -1; +static gint hf_mac_header_generic_ext_subheader_sn_req_rsv = -1; +/* SN Report Indication message */ +static const value_string sn_rep_msg[] = +{ + { 0, "" }, + { 1, "request transmission" }, + { 0, NULL} +}; + +/* Extended Subheader display */ +static hf_register_info hf_ext[] = +{ + { + &hf_mac_header_generic_ext_subheader_rsv, + { + "Reserved", "wimax.genericExtSubhd.Rsv", + FT_UINT8, BASE_DEC, NULL, EXTENDED_SUB_HEADER_RSV_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_type_dl, + { + "DL Extended Subheader Type", "wimax.genericExtSubhd.Dl", + FT_UINT8, BASE_DEC, VALS(dl_ext_sub_header_type), EXTENDED_SUB_HEADER_TYPE_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_type_ul, + { + "UL Extended Subheader Type", "wimax.genericExtSubhd.Ul", + FT_UINT8, BASE_DEC, VALS(ul_ext_sub_header_type), EXTENDED_SUB_HEADER_TYPE_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_sdu_sn, + { + "SDU Sequence Number", "wimax.genericExtSubhd.SduSn", + FT_UINT8, BASE_DEC, NULL, 0x0, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_dl_sleep_control_pscid, + { + "Power Saving Class ID", "wimax.genericExtSubhd.DlSleepCtrlPSCID", + FT_UINT24, BASE_DEC, NULL, DL_SLEEP_CONTROL_POWER_SAVING_CLASS_ID_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_dl_sleep_control_op, + { + "Operation", "wimax.genericExtSubhd.DlSleepCtrlOP", + FT_UINT24, BASE_HEX, VALS(dl_sleep_control_ops), DL_SLEEP_CONTROL_OPERATION_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_dl_sleep_control_fswe, + { + "Final Sleep Window Exponent", "wimax.genericExtSubhd.DlSleepCtrlFSWE", + FT_UINT24, BASE_DEC, NULL, DL_SLEEP_CONTROL_FINAL_SLEEP_WINDOW_EXPONENT_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_dl_sleep_control_fswb, + { + "Final Sleep Window Base", "wimax.genericExtSubhd.DlSleepCtrlFSWB", + FT_UINT24, BASE_DEC, NULL, DL_SLEEP_CONTROL_FINAL_SLEEP_WINDOW_BASE_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_dl_sleep_control_rsv, + { + "Reserved", "wimax.genericExtSubhd.DlSleepCtrlRsv", + FT_UINT24, BASE_DEC, NULL, DL_SLEEP_CONTROL_RESERVED_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_fb_req_uiuc, + { + "UIUC", "wimax.genericExtSubhd.FbReqUIUC", + FT_UINT24, BASE_HEX, VALS(uiuc_values), FEEDBACK_REQUEST_UIUC_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_fb_req_fb_type, + { + "Feedback Type", "wimax.genericExtSubhd.FbReqFbType", + FT_UINT24, BASE_HEX, VALS(fb_types), FEEDBACK_REQUEST_FEEDBACK_TYPE_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_fb_req_ofdma_symbol_offset, + { + "OFDMA Symbol Offset", "wimax.genericExtSubhd.FbReqOfdmaSymbolOffset", + FT_UINT24, BASE_HEX, NULL, FEEDBACK_REQUEST_OFDMA_SYMBOL_OFFSET_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_fb_req_subchannel_offset, + { + "Subchannel Offset", "wimax.genericExtSubhd.FbReqSubchannelOffset", + FT_UINT24, BASE_HEX, NULL, FEEDBACK_REQUEST_SUBCHANNEL_OFFSET_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_fb_req_slots, + { + "Number of Slots", "wimax.genericExtSubhd.FbReqSlots", + FT_UINT24, BASE_HEX, NULL, FEEDBACK_REQUEST_NUMBER_OF_SLOTS_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_fb_req_frame_offset, + { + "Frame Offset", "wimax.genericExtSubhd.FbReqFrameOffset", + FT_UINT24, BASE_HEX, NULL, FEEDBACK_REQUEST_FRAME_OFFSET_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_sn_req_rep_ind_1, + { + "First SN Report Indication", "wimax.genericExtSubhd.SnReqRepInd1", + FT_UINT8, BASE_DEC, VALS(sn_rep_msg), SN_REQUEST_SUBHEADER_SN_REPORT_INDICATION_1_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_sn_req_rep_ind_2, + { + "Second SN Report Indication", "wimax.genericExtSubhd.SnReqRepInd2", + FT_UINT8, BASE_DEC, VALS(sn_rep_msg), SN_REQUEST_SUBHEADER_SN_REPORT_INDICATION_2_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_sn_req_rsv, + { + "Reserved", "wimax.genericExtSubhd.SnReqRsv", + FT_UINT8, BASE_DEC, NULL, SN_REQUEST_SUBHEADER_RESERVED_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_mimo_mode_fb_type, + { + "Feedback Type", "wimax.genericExtSubhd.MimoFbType", + FT_UINT8, BASE_DEC, VALS(mimo_fb_types), MIMO_FEEDBACK_TYPE_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_mimo_fb_content, + { + "Feedback Content", "wimax.genericExtSubhd.MimoFbContent", + FT_UINT8, BASE_DEC, NULL, MIMO_FEEDBACK_CONTENT_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_ul_tx_pwr_rep, + { + "UL TX Power", "wimax.genericExtSubhd.UlTxPwr", + FT_UINT8, BASE_DEC, NULL, 0x0, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_mini_fb_type, + { + "Feedback Type", "wimax.genericExtSubhd.MiniFbType", + FT_UINT16, BASE_DEC, VALS(fb_types), MINI_FEEDBACK_TYPE_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_mini_fb_content, + { + "Feedback Content", "wimax.genericExtSubhd.MiniFbContent", + FT_UINT16, BASE_DEC, NULL, MINI_FEEDBACK_CONTENT_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_pdu_sn_short, + { + "PDU Sequence Number", "wimax.genericExtSubhd.PduSnShort", + FT_UINT8, BASE_DEC, NULL, 0x0, + "", HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_pdu_sn_long, + { + "PDU Sequence Number", "wimax.genericExtSubhd.PduSnLong", + FT_UINT16, BASE_DEC, NULL, 0x0, + "", HFILL + } + } +}; + +/* Mesh Subheader */ +static gint hf_mac_header_generic_mesh_subheader = -1; + +/* Mesh Subheader display */ +static hf_register_info hf_mesh[] = +{ + { + &hf_mac_header_generic_mesh_subheader, + { + "Xmt Node Id", "wimax.genericMeshSubhd", + FT_UINT16, BASE_DEC, NULL, 0x0, + "", HFILL + } + } +}; + +/* Fragmentation Subheader (table 8) */ +#define FRAGMENTATION_SUBHEADER_FC_MASK 0xC000 /*0x0003*/ +#define FRAGMENTATION_SUBHEADER_BSN_MASK 0x3FF8 /*0x1FFC*/ +#define FRAGMENTATION_SUBHEADER_RSV_EXT_MASK 0x0007 /*0xE000*/ +#define FRAGMENTATION_SUBHEADER_FSN_MASK 0x38 /*0x1C*/ +#define FRAGMENTATION_SUBHEADER_RSV_MASK 0x07 /*0xE0*/ +#define FRAGMENT_TYPE_MASK 0xC0 +#define SEQ_NUMBER_MASK 0x38 +#define SEQ_NUMBER_MASK_11 0x3FF8 + +#define NO_FRAG 0 +#define LAST_FRAG 1 +#define FIRST_FRAG 2 +#define MIDDLE_FRAG 3 + +static gint hf_mac_header_generic_frag_subhd_fc = -1; +static gint hf_mac_header_generic_frag_subhd_fc_ext = -1; +static gint hf_mac_header_generic_frag_subhd_bsn = -1; +static gint hf_mac_header_generic_frag_subhd_fsn = -1; +static gint hf_mac_header_generic_frag_subhd_fsn_ext = -1; +static gint hf_mac_header_generic_frag_subhd_rsv = -1; +static gint hf_mac_header_generic_frag_subhd_rsv_ext = -1; + +/* Fragment Types */ +static const value_string frag_types[] = +{ + { 0, "No fragmentation" }, + { 1, "Last fragment" }, + { 2, "First fragment" }, + { 3, "Continuing (middle) fragment" }, + { 0, NULL} +}; + +/* Fragmentation Subheader display */ +static hf_register_info hf_frag[] = +{ + { + &hf_mac_header_generic_frag_subhd_fc, + { + "Fragment Type", "wimax.genericFragSubhd.Fc", + FT_UINT8, BASE_DEC, VALS(frag_types), FRAGMENTATION_SUBHEADER_FC_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_frag_subhd_fc_ext, + { + "Fragment Type", "wimax.genericFragSubhd.FcExt", + FT_UINT16, BASE_DEC, VALS(frag_types), FRAGMENTATION_SUBHEADER_FC_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_frag_subhd_bsn, + { + "Block Sequence Number (BSN)", "wimax.genericFragSubhd.Bsn", + FT_UINT16, BASE_DEC, NULL, FRAGMENTATION_SUBHEADER_BSN_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_frag_subhd_fsn, + { + "Fragment Sequence Number (FSN)", "wimax.genericFragSubhd.Fsn", + FT_UINT8, BASE_DEC, NULL, FRAGMENTATION_SUBHEADER_FSN_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_frag_subhd_fsn_ext, + { + "Fragment Sequence Number (FSN)", "wimax.genericFragSubhd.FsnExt", + FT_UINT16, BASE_DEC, NULL, FRAGMENTATION_SUBHEADER_BSN_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_frag_subhd_rsv, + { + "Reserved", "wimax.genericFragSubhd.Rsv", + FT_UINT8, BASE_DEC, NULL, FRAGMENTATION_SUBHEADER_RSV_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_frag_subhd_rsv_ext, + { + "Reserved", "wimax.genericFragSubhd.RsvExt", + FT_UINT16, BASE_DEC, NULL, FRAGMENTATION_SUBHEADER_RSV_EXT_MASK, + "", HFILL + } + } +}; + +/* Packing Subheader (table 11) */ +#define PACKING_SUBHEADER_FC_MASK 0xC00000 +#define PACKING_SUBHEADER_BSN_MASK 0x3FF800 +#define PACKING_SUBHEADER_FSN_MASK 0x38 +#define PACKING_SUBHEADER_LENGTH_MASK 0x07FF +#define PACKING_SUBHEADER_LENGTH_EXT_MASK 0x0007FF + +#define FRAG_LENGTH_MASK 0x0007FF00 + +static gint hf_mac_header_generic_packing_subhd_fc = -1; +static gint hf_mac_header_generic_packing_subhd_fc_ext = -1; +static gint hf_mac_header_generic_packing_subhd_bsn = -1; +static gint hf_mac_header_generic_packing_subhd_fsn = -1; +static gint hf_mac_header_generic_packing_subhd_fsn_ext = -1; +static gint hf_mac_header_generic_packing_subhd_len = -1; +static gint hf_mac_header_generic_packing_subhd_len_ext = -1; + +/* Packing Subheader display */ +static hf_register_info hf_pack[] = +{ + { + &hf_mac_header_generic_packing_subhd_fc, + { + "Fragment Type", "wimax.genericPackSubhd.Fc", + FT_UINT16, BASE_DEC, VALS(frag_types), PACKING_SUBHEADER_FC_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_packing_subhd_fc_ext, + { + "Fragment Type", "wimax.genericPackSubhd.FcExt", + FT_UINT24, BASE_HEX, VALS(frag_types), PACKING_SUBHEADER_FC_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_packing_subhd_bsn, + { + "First Block Sequence Number", "wimax.genericPackSubhd.Bsn", + FT_UINT24, BASE_DEC, NULL, PACKING_SUBHEADER_BSN_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_packing_subhd_fsn, + { + "Fragment Number", "wimax.genericPackSubhd.Fsn", + FT_UINT16, BASE_DEC, NULL, PACKING_SUBHEADER_FSN_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_packing_subhd_fsn_ext, + { + "Fragment Number", "wimax.genericPackSubhd.FsnExt", + FT_UINT24, BASE_DEC, NULL, PACKING_SUBHEADER_BSN_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_packing_subhd_len, + { + "Length", "wimax.genericPackSubhd.Len", + FT_UINT16, BASE_DEC, NULL, PACKING_SUBHEADER_LENGTH_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_packing_subhd_len_ext, + { + "Length", "wimax.genericPackSubhd.LenExt", + FT_UINT24, BASE_DEC, NULL, PACKING_SUBHEADER_LENGTH_EXT_MASK, + "", HFILL + } + } +}; + +/* Fast-feedback Allocation Subheader (table 13) */ +#define FAST_FEEDBACK_ALLOCATION_OFFSET_MASK 0xFC /*0x3F*/ +#define FAST_FEEDBACK_FEEDBACK_TYPE_MASK 0x03 /*0xC0*/ + +static gint hf_mac_header_generic_fast_fb_subhd_alloc_offset = -1; +static gint hf_mac_header_generic_fast_fb_subhd_fb_type = -1; + +/* Fast-feedback Allocation Subheader display */ +static hf_register_info hf_fast[] = +{ + { + &hf_mac_header_generic_fast_fb_subhd_alloc_offset, + { + "Allocation Offset", "wimax.genericFastFbSubhd.AllocOffset", + FT_UINT8, BASE_DEC, NULL, FAST_FEEDBACK_ALLOCATION_OFFSET_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_fast_fb_subhd_fb_type, + { + "Feedback Type", "wimax.genericFastFbSubhd.FbType", + FT_UINT8, BASE_DEC, VALS(fast_fb_types), FAST_FEEDBACK_FEEDBACK_TYPE_MASK, + "", HFILL + } + } +}; + +/* Grant Management Subheader (table 9 & 10) */ +#define GRANT_MGMT_SUBHEADER_UGS_SI_MASK 0x8000 /*0x0001*/ +#define GRANT_MGMT_SUBHEADER_UGS_PM_MASK 0x4000 /*0x0002*/ +#define GRANT_MGMT_SUBHEADER_UGS_FLI_MASK 0x2000 /*0x0004*/ +#define GRANT_MGMT_SUBHEADER_UGS_FL_MASK 0x1E00 /*0x0078*/ +#define GRANT_MGMT_SUBHEADER_UGS_RSV_MASK 0x01FF /*0xFF80*/ +#define GRANT_MGMT_SUBHEADER_EXT_PBR_MASK 0xFFE0 /*0x07FF*/ +#define GRANT_MGMT_SUBHEADER_EXT_FLI_MASK 0x0010 /*0x0800*/ +#define GRANT_MGMT_SUBHEADER_EXT_FL_MASK 0x000F /*0xF000*/ + +enum +{ + SCHEDULE_SERVICE_TYPE_RSVD, + SCHEDULE_SERVICE_TYPE_UNDEFINED, + SCHEDULE_SERVICE_TYPE_BE, + SCHEDULE_SERVICE_TYPE_NRTPS, + SCHEDULE_SERVICE_TYPE_RTPS, + SCHEDULE_SERVICE_TYPE_EXT_RTPS, + SCHEDULE_SERVICE_TYPE_UGS +} SCHEDULE_SERVICE_TYPE; + +static gint hf_mac_header_generic_grant_mgmt_ugs_tree = -1; +static gint hf_mac_header_generic_grant_mgmt_subhd_ugs_si = -1; +static gint hf_mac_header_generic_grant_mgmt_subhd_ugs_pm = -1; +static gint hf_mac_header_generic_grant_mgmt_subhd_ugs_fli = -1; +static gint hf_mac_header_generic_grant_mgmt_subhd_ugs_fl = -1; +static gint hf_mac_header_generic_grant_mgmt_subhd_ugs_rsv = -1; +static gint hf_mac_header_generic_grant_mgmt_ext_rtps_tree = -1; +static gint hf_mac_header_generic_grant_mgmt_subhd_ext_pbr = -1; +static gint hf_mac_header_generic_grant_mgmt_subhd_ext_fli = -1; +static gint hf_mac_header_generic_grant_mgmt_subhd_ext_fl = -1; +static gint hf_mac_header_generic_grant_mgmt_ext_pbr_tree = -1; +static gint hf_mac_header_generic_grant_mgmt_subhd_pbr = -1; + +/* Slip Indicators */ +static const value_string si_msgs[] = +{ + { 0, "No action" }, + { 1, "A slip of UL grants relative to the UL queue depth" }, + { 0, NULL} +}; + +/* Poll-Me Messages */ +static const value_string pm_msgs[] = +{ + { 0, "No action" }, + { 1, "Request a bandwidth poll" }, + { 0, NULL} +}; + +/* Frame Latency Indications */ +static const value_string fli_msgs[] = +{ + { 0, "Frame latency field disabled" }, + { 1, "Frame latency field enabled" }, + { 0, NULL} +}; + +/* Grant Management Subheader display */ +static hf_register_info hf_grant[] = +{ + { + &hf_mac_header_generic_grant_mgmt_ext_pbr_tree, + { + "Scheduling Service Type (Default)", + "wimax.genericGrantSubhd.Default", + FT_UINT16, BASE_DEC, NULL, 0x0, + "", HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_subhd_pbr, + { + "PiggyBack Request", "wimax.genericGrantSubhd.Pbr", + FT_UINT16, BASE_DEC, NULL, 0x0, + "", HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_ugs_tree, + { + "Scheduling Service Type (UGS)", "wimax.genericGrantSubhd.UGS", + FT_UINT16, BASE_DEC, NULL, 0x0, + "", HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_subhd_ugs_si, + { + "Slip Indicator", "wimax.genericGrantSubhd.Si", + FT_UINT16, BASE_DEC, VALS(si_msgs), GRANT_MGMT_SUBHEADER_UGS_SI_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_subhd_ugs_pm, + { + "Poll-Me", "wimax.genericGrantSubhd.Pm", + FT_UINT16, BASE_DEC, VALS(pm_msgs), GRANT_MGMT_SUBHEADER_UGS_PM_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_subhd_ugs_fli, + { + "Frame Latency Indication", "wimax.genericGrantSubhd.Fli", + FT_UINT16, BASE_DEC, VALS(fli_msgs), GRANT_MGMT_SUBHEADER_UGS_FLI_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_subhd_ugs_fl, + { + "Frame Latency", "wimax.genericGrantSubhd.Fl", + FT_UINT16, BASE_DEC, NULL, GRANT_MGMT_SUBHEADER_UGS_FL_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_subhd_ugs_rsv, + { + "Reserved", "wimax.genericGrantSubhd.Rsv", + FT_UINT16, BASE_DEC, NULL, GRANT_MGMT_SUBHEADER_UGS_RSV_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_ext_rtps_tree, + { + "Scheduling Service Type (Extended rtPS)", + "wimax.genericGrantSubhd.ExtendedRTPS", + FT_UINT16, BASE_DEC, NULL, 0x0, + "", HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_subhd_ext_pbr, + { + "Extended PiggyBack Request", "wimax.genericGrantSubhd.ExtPbr", + FT_UINT16, BASE_DEC, NULL, GRANT_MGMT_SUBHEADER_EXT_PBR_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_subhd_ext_fli, + { + "Frame Latency Indication", "wimax.genericGrantSubhd.ExtFli", + FT_UINT16, BASE_DEC, VALS(fli_msgs), GRANT_MGMT_SUBHEADER_EXT_FLI_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_subhd_ext_fl, + { + "Frame Latency", "wimax.genericGrantSubhd.ExtFl", + FT_UINT16, BASE_DEC, NULL, GRANT_MGMT_SUBHEADER_EXT_FL_MASK, + "", HFILL + } + } +}; + +/* ARQ Feedback Payload */ + +/* ARQ Feedback IE bit masks (table 111) */ +#define ARQ_FB_IE_LAST_BIT_MASK 0x8000 /*0x0001*/ +#define ARQ_FB_IE_ACK_TYPE_MASK 0x6000 /*0x0006*/ +#define ARQ_FB_IE_BSN_MASK 0x1FFC /*0x3FF8*/ +#define ARQ_FB_IE_NUM_MAPS_MASK 0x0003 /*0xC000*/ +#define ARQ_FB_IE_SEQ_FORMAT_MASK 0x8000 /*0x0001*/ +#define ARQ_FB_IE_SEQ_ACK_MAP_MASK 0x7000 /*0x000E*/ +#define ARQ_FB_IE_SEQ1_LENGTH_MASK 0x0F00 /*0x00F0*/ +#define ARQ_FB_IE_SEQ2_LENGTH_MASK 0x00F0 /*0x0F00*/ +#define ARQ_FB_IE_SEQ3_LENGTH_MASK 0x000F /*0xF000*/ +#define ARQ_FB_IE_SEQ_ACK_MAP_2_MASK 0x6000 /*0x0006*/ +#define ARQ_FB_IE_SEQ1_LENGTH_6_MASK 0x1F80 /*0x01F8*/ +#define ARQ_FB_IE_SEQ2_LENGTH_6_MASK 0x007E /*0x7E00*/ +#define ARQ_FB_IE_RSV_MASK 0x0001 /*0x8000*/ + +static gint hf_mac_header_generic_arq_fb_ie_cid = -1; +static gint hf_mac_header_generic_arq_fb_ie_last = -1; +static gint hf_mac_header_generic_arq_fb_ie_ack_type = -1; +static gint hf_mac_header_generic_arq_fb_ie_bsn = -1; +static gint hf_mac_header_generic_arq_fb_ie_num_maps = -1; +static gint hf_ack_type_reserved = -1; +static gint hf_mac_header_generic_arq_fb_ie_sel_ack_map = -1; +static gint hf_mac_header_generic_arq_fb_ie_seq_format = -1; +static gint hf_mac_header_generic_arq_fb_ie_seq_ack_map = -1; +static gint hf_mac_header_generic_arq_fb_ie_seq1_length = -1; +static gint hf_mac_header_generic_arq_fb_ie_seq2_length = -1; +static gint hf_mac_header_generic_arq_fb_ie_seq3_length = -1; +static gint hf_mac_header_generic_arq_fb_ie_seq_ack_map_2 = -1; +static gint hf_mac_header_generic_arq_fb_ie_seq1_length_6 = -1; +static gint hf_mac_header_generic_arq_fb_ie_seq2_length_6 = -1; +static gint hf_mac_header_generic_arq_fb_ie_rsv = -1; + +/* Last IE Indicators */ +static const value_string last_ie_msgs[] = +{ + { 0, "No" }, + { 1, "Yes" }, + { 0, NULL} +}; + +/* ARQ Feedback Payload display */ +static hf_register_info hf_arq[] = +{ + { + &hf_mac_header_generic_arq_fb_ie_cid, + { + "CID", "wimax.genericArq.FbIeCid", + FT_UINT16, BASE_DEC, NULL, 0x0, + "", HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_last, + { + "Last IE", "wimax.genericArq.FbIeLast", + FT_UINT16, BASE_DEC, VALS(last_ie_msgs), ARQ_FB_IE_LAST_BIT_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_ack_type, + { + "ACK Type", "wimax.genericArq.FbIeAckType", + FT_UINT16, BASE_DEC, NULL, ARQ_FB_IE_ACK_TYPE_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_bsn, + { + "BSN", "wimax.genericArq.FbIeBsn", + FT_UINT16, BASE_DEC, NULL, ARQ_FB_IE_BSN_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_num_maps, + { + "Number of ACK Maps", "wimax.genericArq.FbIeMaps", + FT_UINT16, BASE_DEC, NULL, ARQ_FB_IE_NUM_MAPS_MASK, + "", HFILL + } + }, + { + &hf_ack_type_reserved, + { + "Reserved", "wimax.genericArq.FbIeRsvd", FT_UINT16, BASE_DEC, NULL, 0x03, "", HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_sel_ack_map, + { + "Selective ACK Map", "wimax.genericArq.FbIeSelAckMap", + FT_UINT16, BASE_HEX, NULL, 0x0, + "", HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_seq_format, + { + "Sequence Format", "wimax.genericArq.FbIeSeqFmt", + FT_UINT16, BASE_DEC, NULL, ARQ_FB_IE_SEQ_FORMAT_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_seq_ack_map, + { + "Sequence ACK Map", "wimax.genericArq.FbIeSeqAckMap", + FT_UINT16, BASE_HEX, NULL, ARQ_FB_IE_SEQ_ACK_MAP_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_seq1_length, + { + "Sequence 1 Length", "wimax.genericArq.FbIeSeq1Len", + FT_UINT16, BASE_DEC, NULL, ARQ_FB_IE_SEQ1_LENGTH_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_seq2_length, + { + "Sequence 2 Length", "wimax.genericArq.FbIeSeq2Len", + FT_UINT16, BASE_DEC, NULL, ARQ_FB_IE_SEQ2_LENGTH_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_seq3_length, + { + "Sequence 3 Length", "wimax.genericArq.FbIeSeq3Len", + FT_UINT16, BASE_DEC, NULL, ARQ_FB_IE_SEQ3_LENGTH_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_seq_ack_map_2, + { + "Sequence ACK Map", "wimax.genericArq.FbIeSeqAckMap2", + FT_UINT16, BASE_HEX, NULL, ARQ_FB_IE_SEQ_ACK_MAP_2_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_seq1_length_6, + { + "Sequence 1 Length", "wimax.genericArq.FbIeSeq1Len", + FT_UINT16, BASE_DEC, NULL, ARQ_FB_IE_SEQ1_LENGTH_6_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_seq2_length_6, + { + "Sequence 2 Length", "wimax.genericArq.FbIeSeq2Len", + FT_UINT16, BASE_DEC, NULL, ARQ_FB_IE_SEQ2_LENGTH_6_MASK, + "", HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_rsv, + { + "Reserved", "wimax.genericArq.FbIeRsv", + FT_UINT16, BASE_DEC, NULL, ARQ_FB_IE_RSV_MASK, + "", HFILL + } + } +}; + +/* Register Wimax defrag table init routine. */ +void wimax_defragment_init(void) +{ + gint i; + + fragment_table_init(&payload_frag_table); + + /* Init fragmentation variables. */ + for (i = 0; i < MAX_CID; i++) + { + cid_adjust[i] = 1; /* Must not start with 0 */ + cid_vernier[i] = 0; + } + cid_adj_array_size = 0; + /* Free the array memory. */ + if (cid_adj_array) { + free(cid_adj_array); + } + cid_adj_array = NULL; + if (frag_num_array) { + free(frag_num_array); + } + frag_num_array = NULL; + + /* Initialize to make sure bs_address gets set in FCH decoder. */ + bs_address.len = 0; + + /* Initialize the Scheduling Service Type flag */ + seen_a_service_type = 0; + + max_logical_bands = 12; + + /* Initialize UL_MAP globals. */ + init_wimax_globals(); +} + +static guint decode_packing_subheader(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree, guint payload_length, guint payload_offset, proto_item *parent_item) +{ + proto_item *generic_item = NULL; + proto_tree *generic_tree = NULL; + guint starting_offset = payload_offset; + + /* update the info column */ + if (check_col(pinfo->cinfo, COL_INFO)) + { + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Packing subhdr"); + } + /* add the Packing subheader info */ + proto_item_append_text(parent_item, ", Packing Subheader"); + /* display Packing subheader type */ + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, payload_tvb, payload_offset, ((arq_enabled|extended_type)?3:2), "Packing subheader (%u bytes)", ((arq_enabled|extended_type)?3:2)); + /* add Packing subheader subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_pkt_subheader_decoder); + /* decode and display the Packing subheader */ + /* Get the fragment type */ + frag_type = (tvb_get_guint8(payload_tvb, payload_offset) & FRAGMENT_TYPE_MASK) >> 6; + /* if ARQ Feedback payload is present */ + if (arq_fb_payload) + { /* get the frag length */ + frag_len = ((tvb_get_ntohl(payload_tvb, payload_offset) & FRAG_LENGTH_MASK) >> 8); + /* get the sequence number */ + seq_number = (tvb_get_ntohs(payload_tvb, payload_offset) & SEQ_NUMBER_MASK_11) >> 3; + proto_tree_add_item(generic_tree, hf_mac_header_generic_packing_subhd_fc_ext, payload_tvb, payload_offset, 3, FALSE); + proto_tree_add_item(generic_tree, hf_mac_header_generic_packing_subhd_bsn, payload_tvb, payload_offset, 3, FALSE); + proto_tree_add_item(generic_tree, hf_mac_header_generic_packing_subhd_len_ext, payload_tvb, payload_offset, 3, FALSE); + /* update the length and offset */ + payload_length -= 3; + payload_offset += 3; + frag_len -= 3; + } + else + { + if (extended_type) + { /* get the frag length */ + frag_len = ((tvb_get_ntohl(payload_tvb, payload_offset) & FRAG_LENGTH_MASK) >> 8); + /* get the sequence number */ + seq_number = (tvb_get_ntohs(payload_tvb, payload_offset) & SEQ_NUMBER_MASK_11) >> 3; + proto_tree_add_item(generic_tree, hf_mac_header_generic_packing_subhd_fc_ext, payload_tvb, payload_offset, 3, FALSE); + proto_tree_add_item(generic_tree, hf_mac_header_generic_packing_subhd_fsn_ext, payload_tvb, payload_offset, 3, FALSE); + proto_tree_add_item(generic_tree, hf_mac_header_generic_packing_subhd_len_ext, payload_tvb, payload_offset, 3, FALSE); + /* update the length and offset */ + payload_length -= 3; + payload_offset += 3; + frag_len -= 3; + } + else + { /* get the frag length */ + frag_len = (tvb_get_ntohs(payload_tvb, payload_offset) & PACKING_SUBHEADER_LENGTH_MASK); + /* get the sequence number */ + seq_number = (tvb_get_guint8(payload_tvb, payload_offset) & SEQ_NUMBER_MASK) >> 3; + proto_tree_add_item(generic_tree, hf_mac_header_generic_packing_subhd_fc, payload_tvb, payload_offset, 2, FALSE); + proto_tree_add_item(generic_tree, hf_mac_header_generic_packing_subhd_fsn, payload_tvb, payload_offset, 2, FALSE); + proto_tree_add_item(generic_tree, hf_mac_header_generic_packing_subhd_len, payload_tvb, payload_offset, 2, FALSE); + /* update the length and offset */ + payload_length -= 2; + payload_offset += 2; + frag_len -= 2; + } + } + /* Prevent a crash! */ + if ((gint)frag_len < 0) + frag_len = 0; + /* Return the number of bytes decoded. */ + return payload_offset - starting_offset; +} + +/* Register Wimax Generic Mac Header Protocol and Dissector */ +void proto_register_mac_header_generic(void) +{ + if (proto_mac_header_generic_decoder == -1) + { + proto_mac_header_generic_decoder = proto_register_protocol ( + "WiMax Generic/Type1/Type2 MAC Header Messages", /* name */ + "WiMax Generic/Type1/Type2 MAC Header (hdr)", /* short name */ + "hdr" /* abbrev */ + ); + /* register the field display messages */ + proto_register_field_array(proto_mac_header_generic_decoder, hf, array_length(hf)); + proto_register_field_array(proto_mac_header_generic_decoder, hf_ext, array_length(hf_ext)); + proto_register_field_array(proto_mac_header_generic_decoder, hf_mesh, array_length(hf_mesh)); + proto_register_field_array(proto_mac_header_generic_decoder, hf_frag, array_length(hf_frag)); + proto_register_field_array(proto_mac_header_generic_decoder, hf_pack, array_length(hf_pack)); + proto_register_field_array(proto_mac_header_generic_decoder, hf_fast, array_length(hf_fast)); + proto_register_field_array(proto_mac_header_generic_decoder, hf_grant, array_length(hf_grant)); + proto_register_field_array(proto_mac_header_generic_decoder, hf_arq, array_length(hf_arq)); + proto_register_subtree_array(ett, array_length(ett)); + } + /* register the generic mac header dissector */ + register_dissector("mac_header_generic_handler", dissect_mac_header_generic_decoder, proto_mac_header_generic_decoder); + /* register the mac payload dissector */ + proto_register_mac_mgmt_msg(); + /* Register the payload fragment table init routine */ + register_init_routine(wimax_defragment_init); +} + +void dissect_mac_header_generic_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint offset = 0; + guint payload_offset, payload_length; + + static guint8 frag_number[MAX_CID]; + static guint cid_list[MAX_CID]; + static guint cid_base; + static char *reassem_str = "Reassembled Data transport PDU (%u bytes)"; + static char *data_str = "Data transport PDU (%u bytes)"; + char *str_ptr; + gint length, i, cid_index; + guint tvb_len, ret_length, ubyte, new_tvb_len, new_payload_len; + guint mac_ht, mac_ec, mac_esf, mac_ci, mac_eks, mac_len, mac_cid, cid; + guint ffb_grant_mgmt_subheader, packing_subheader, fragment_subheader; + guint mesh_subheader; + guint packing_length; + guint32 mac_crc, calculated_crc; + proto_item *parent_item = NULL; + proto_item *generic_item = NULL; + proto_tree *generic_tree = NULL; + proto_item *child_item = NULL; + proto_tree *child_tree = NULL; + tvbuff_t *payload_tvb; + tvbuff_t *data_pdu_tvb; + fragment_data *payload_frag; + gboolean first_arq_fb_payload = TRUE; + + dissector_handle_t mac_payload_handle; + + proto_mac_header_generic_decoder = proto_wimax; + if (tree) + { /* we are being asked for details */ +#ifdef DEBUG + /* update the info column */ + if (check_col(pinfo->cinfo, COL_INFO)) + { + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "GMH"); + } +#endif + /* Get the frame length */ + tvb_len = tvb_length(tvb); + if (tvb_len < WIMAX_MAC_HEADER_SIZE) + { /* display the error message */ + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, tvb_len, "Error: the size of Generic MAC Header tvb is too small! (%u bytes)", tvb_len); + /* add subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_header_generic_decoder); + /* display the Generic MAC Header in Hex */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_value_bytes, tvb, offset, tvb_len, FALSE); + return; + } + /* get the parent */ + parent_item = proto_tree_get_parent(tree); + /* add the MAC header info */ + proto_item_append_text(parent_item, " - Generic MAC Header"); + /* display MAC header message */ + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, WIMAX_MAC_HEADER_SIZE, "Generic MAC Header (%u bytes)", WIMAX_MAC_HEADER_SIZE); + /* add MAC header subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_header_generic_decoder); + /* Decode and display the MAC header */ + /* Get the first byte */ + ubyte = tvb_get_guint8(tvb, offset); + /* get the Header Type (HT) */ + mac_ht = ((ubyte & WIMAX_MAC_HEADER_GENERIC_HT_MASK)?1:0); + /* get the Encryption Control (EC) */ + mac_ec = ((ubyte & WIMAX_MAC_HEADER_GENERIC_EC_MASK)?1:0); + /* get the sub types */ + ffb_grant_mgmt_subheader = ((ubyte & GENERIC_SUB_TYPE_0)?1:0); + packing_subheader = ((ubyte & GENERIC_SUB_TYPE_1)?1:0); + fragment_subheader = ((ubyte & GENERIC_SUB_TYPE_2)?1:0); + extended_type = ((ubyte & GENERIC_SUB_TYPE_3)?1:0); + arq_fb_payload = ((ubyte & GENERIC_SUB_TYPE_4)?1:0); + mesh_subheader = ((ubyte & GENERIC_SUB_TYPE_5)?1:0); + /* Get the 2nd byte */ + ubyte = tvb_get_guint8(tvb, (offset+1)); + /* get the Extended subheader field (ESF) */ + mac_esf = ((ubyte & WIMAX_MAC_HEADER_GENERIC_ESF_MASK)?1:0); + /* get the CRC indicator (CI) */ + mac_ci = ((ubyte & WIMAX_MAC_HEADER_GENERIC_CI_MASK)?1:0); + /* get the Encryption key sequence (EKS) */ + mac_eks = ((ubyte & WIMAX_MAC_HEADER_GENERIC_EKS_MASK)>>4); + /* get the MAC length */ + mac_len = (tvb_get_ntohs(tvb, (offset+1)) & WIMAX_MAC_HEADER_GENERIC_LEN); + /* get the CID */ + mac_cid = tvb_get_ntohs(tvb, (offset+3)); + /* display the Header Type (HT) */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_ht, tvb, offset, 3, FALSE); + /* display the Encryption Control (EC) */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_ec, tvb, offset, 3, FALSE); + /* display the sub-types (Type) */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_type_5, tvb, offset, 3, FALSE); + proto_tree_add_item(generic_tree, hf_mac_header_generic_type_4, tvb, offset, 3, FALSE); + proto_tree_add_item(generic_tree, hf_mac_header_generic_type_3, tvb, offset, 3, FALSE); + proto_tree_add_item(generic_tree, hf_mac_header_generic_type_2, tvb, offset, 3, FALSE); + proto_tree_add_item(generic_tree, hf_mac_header_generic_type_1, tvb, offset, 3, FALSE); + proto_tree_add_item(generic_tree, hf_mac_header_generic_type_0, tvb, offset, 3, FALSE); + /* display the Extended sub-header Field (ESF) */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_esf, tvb, offset, 3, FALSE); + /* display the CRC Indicator (CI) */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_ci, tvb, offset, 3, FALSE); + /* display the Encryption Key Sequence (EKS) */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_eks, tvb, offset, 3, FALSE); + /* display the reserved field */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_rsv, tvb, offset, 3, FALSE); + /* display the length */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_len, tvb, offset, 3, FALSE); + /* Decode and display the CID */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_cid, tvb, (offset+3), 2, FALSE); + /* Decode and display the HCS */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_hcs, tvb, (offset+5), 1, FALSE); + /* get the frame length without MAC header */ + length = mac_len - WIMAX_MAC_HEADER_SIZE; +#ifdef DEBUG + proto_item_append_text(parent_item, "tvb length=%u, mac length=%u, frame length=%u,", tvb_len, mac_len, length); +#endif + /* set the offset for the frame */ + offset += WIMAX_MAC_HEADER_SIZE; + /* the processing of the subheaders is order sensitive */ + /* do not change the order */ + + if (mac_ec) + { + if (mac_ci) + { + if (length >= (gint)sizeof(mac_crc)) + { + length -= sizeof(mac_crc); + } + } + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, length, "Encrypted PDU (%u bytes)", length); + /* add payload subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_data_pdu_decoder); + proto_tree_add_item(generic_tree, hf_mac_header_generic_value_bytes, tvb, offset, length, FALSE); + goto check_crc; + } + + /* if Extended subheader is present */ + if (mac_esf) + { /* add the Extended subheader info */ + proto_item_append_text(parent_item, ", Extended Subheader(s)"); + ret_length = extended_subheader_decoder(tvb_new_subset(tvb, offset, length, length), pinfo, tree); + /* update the length and offset */ + length -= ret_length; + offset += ret_length; + } + /* if Mesh subheader is present */ + if (mesh_subheader) + { /* update the info column */ + if (check_col(pinfo->cinfo, COL_INFO)) + { + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Mesh subhdr"); + } + /* add the Mesh subheader info */ + proto_item_append_text(parent_item, ", Mesh Subheader"); + /* display Mesh subheader type */ + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, length, "Mesh subheader (2 bytes)"); + /* add Mesh subheader subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_mesh_subheader_decoder); + /* decode and display the Mesh subheader */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_mesh_subheader, tvb, offset, 2, FALSE); + /* update the length and offset */ + length -= 2; + offset += 2; + } + /* if Fast-feedback allocation (DL) subheader or Grant management (UL) subheader is present */ + if (ffb_grant_mgmt_subheader) + { /* check if it is downlink packet */ + if (is_down_link(&(pinfo->src))) + { /* Fast-feedback allocation (DL) subheader is present */ + /* update the info column */ + if (check_col(pinfo->cinfo, COL_INFO)) + { + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Fast-fb subhdr"); + } + /* add the Fast-feedback subheader info */ + proto_item_append_text(parent_item, ", Fast-feedback Subheader"); + /* display Fast-feedback allocation subheader type */ + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, length, "Fast-feedback allocation (DL) subheader (%u bytes)", length); + /* add Fast-feedback allocation subheader subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_fast_fb_subheader_decoder); + proto_tree_add_item(generic_tree, hf_mac_header_generic_fast_fb_subhd_alloc_offset, tvb, offset, 1, FALSE); + proto_tree_add_item(generic_tree, hf_mac_header_generic_fast_fb_subhd_fb_type, tvb, offset, 1, FALSE); + /* update the length and offset */ + length -= 1; + offset += 1; + } + else /* Grant management (UL) subheader is present */ + { /* update the info column */ + if (check_col(pinfo->cinfo, COL_INFO)) + { + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Grant mgmt subhdr"); + } + /* add the Grant management subheader info */ + proto_item_append_text(parent_item, ", Grant Management Subheader"); + /* display Grant management subheader type */ + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, 2, "Grant management (UL) subheader (2 bytes)"); + /* add Grant management subheader subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_grant_mgmt_subheader_decoder); + scheduling_service_type = get_service_type(); + switch (scheduling_service_type) + { + case SCHEDULE_SERVICE_TYPE_UGS: + proto_item_append_text(generic_item, ": It looks like UGS is the correct Scheduling Service Type"); + break; + case SCHEDULE_SERVICE_TYPE_EXT_RTPS: + proto_item_append_text(generic_item, ": It looks like Extended rtPS is the correct Scheduling Service Type"); + break; + case -1: + proto_item_append_text(generic_item, ": Cannot determine the correct Scheduling Service Type"); + break; + default: + proto_item_append_text(generic_item, ": It looks like Piggyback Request is the correct Scheduling Service Type"); + break; + } + /* Create tree for Scheduling Service Type (UGS) */ + child_item = proto_tree_add_item(generic_tree, hf_mac_header_generic_grant_mgmt_ugs_tree, tvb, offset, 2, FALSE); + child_tree = proto_item_add_subtree(child_item, ett_mac_grant_mgmt_subheader_decoder); + proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ugs_si, tvb, offset, 2, FALSE); + proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ugs_pm, tvb, offset, 2, FALSE); + proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ugs_fli, tvb, offset, 2, FALSE); + proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ugs_fl, tvb, offset, 2, FALSE); + proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ugs_rsv, tvb, offset, 2, FALSE); + + /* Create tree for Scheduling Service Type (Extended RTPS) */ + child_item = proto_tree_add_item(generic_tree, hf_mac_header_generic_grant_mgmt_ext_rtps_tree, tvb, offset, 2, FALSE); + child_tree = proto_item_add_subtree(child_item, ett_mac_grant_mgmt_subheader_decoder); + proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ext_pbr, tvb, offset, 2, FALSE); + proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ext_fli, tvb, offset, 2, FALSE); + proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ext_fl, tvb, offset, 2, FALSE); + + /* Create tree for Scheduling Service Type (Piggyback Request) */ + child_item = proto_tree_add_item(generic_tree, hf_mac_header_generic_grant_mgmt_ext_pbr_tree, tvb, offset, 2, FALSE); + child_tree = proto_item_add_subtree(child_item, ett_mac_grant_mgmt_subheader_decoder); + proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_pbr, tvb, offset, 2, FALSE); + + /* update the length and offset */ + length -= 2; + offset += 2; + } + } + /* if Fragmentation subheader is present */ + if (fragment_subheader) + { /* update the info column */ + if (check_col(pinfo->cinfo, COL_INFO)) + { + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Frag subhdr"); + } + /* add the Fragmentation subheader info */ + proto_item_append_text(parent_item, ", Frag Subheader"); + /* display Fragmentation subheader type */ + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, ((arq_enabled|extended_type)?2:1), "Fragmentation subheader (%u bytes)", ((arq_enabled|extended_type)?2:1)); + /* add Fragmentation subheader subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_frag_subheader_decoder); + /* Get the fragment type */ + frag_type = (tvb_get_guint8(tvb, offset) & FRAGMENT_TYPE_MASK) >> 6; + if (arq_fb_payload) + { /* get the sequence number */ + seq_number = (tvb_get_ntohs(tvb, offset) & SEQ_NUMBER_MASK_11) >> 3; + /* decode and display the header */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_fc_ext, tvb, offset, 2, FALSE); + proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_bsn, tvb, offset, 2, FALSE); + proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_rsv_ext, tvb, offset, 2, FALSE); + /* update the length and offset */ + length -= 2; + offset += 2; + } + else + { + if (extended_type) + { /* get the sequence number */ + seq_number = (tvb_get_ntohs(tvb, offset) & SEQ_NUMBER_MASK_11) >> 3; + /* decode and display the header */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_fc_ext, tvb, offset, 2, FALSE); + proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_fsn_ext, tvb, offset, 2, FALSE); + proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_rsv_ext, tvb, offset, 2, FALSE); + /* update the length and offset */ + length -= 2; + offset += 2; + } + else + { /* get the sequence number */ + seq_number = (tvb_get_guint8(tvb, offset) & SEQ_NUMBER_MASK) >> 3; + /* decode and display the header */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_fc, tvb, offset, 1, FALSE); + proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_fsn, tvb, offset, 1, FALSE); + proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_rsv, tvb, offset, 1, FALSE); + /* update the length and offset */ + length -= 1; + offset += 1; + } + } + frag_len = length; + } + else /* ??? default fragment type: no fragment */ + { + frag_type = NO_FRAG; + } + /* Decode the MAC payload if there is any */ + if (mac_ci) + { + if (length < (gint)sizeof(mac_crc)) + { /* display error message */ + proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, length, "Error - the frame is too short (%u bytes)", length); + return; + } + length -= sizeof(mac_crc); + } + while (length > 0) + { + frag_len = length; /* Can be changed by Packing subhdr */ + if (packing_subheader) + { + packing_length = decode_packing_subheader(tvb, pinfo, tree, length, offset, parent_item); + length -= packing_length; + offset += packing_length; + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, frag_len, "Data transport PDU (%u bytes)", frag_len); + /* add payload subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_data_pdu_decoder); + proto_tree_add_item(generic_tree, hf_mac_header_generic_value_bytes, tvb, offset, frag_len, FALSE); + } + /* defragment first if it is fragmented */ + if (frag_type == NO_FRAG) + { /* not fragmented payload */ + payload_tvb = tvb_new_subset(tvb, offset, length, length); + payload_length = length; + new_payload_len = length; + } + else /* fragmented payload */ + { /* add the frag */ + /* Make sure cid will not match a previous packet with different data */ + for (i = 0; i < MAX_CID; i++) + { + if (cid_list[i] == mac_cid) + { + cid_base = i * (0xFFFFFFFF / MAX_CID); + break; + } + if (cid_list[i] == 0) + { + cid_list[i] = mac_cid; + cid_base = i * (0xFFFFFFFF / MAX_CID); + break; + } + } + cid_index = i; + while (pinfo->fd->num > cid_adj_array_size) + { + cid_adj_array_size += 1024; + cid_adj_array = g_realloc(cid_adj_array, sizeof(guint) * cid_adj_array_size); + frag_num_array = g_realloc(frag_num_array, sizeof(guint8) * cid_adj_array_size); + /* Clear the added memory */ + memset(&cid_adj_array[cid_adj_array_size - 1024], 0, sizeof(guint) * 1024); + } + if (first_gmh) + { + /* New cid_adjust for each packet with fragment(s) */ + cid_adjust[cid_index] += cid_vernier[cid_index]; + /* cid_vernier must always be 0 at start of packet. */ + cid_vernier[cid_index] = 0; + } + /* Create artificial sequence numbers. */ + frag_number[cid_index]++; + if (frag_type == FIRST_FRAG) + { + frag_number[cid_index] = 0; + } + if (cid_adj_array[pinfo->fd->num]) + { + /* We apparently just clicked on the packet again. */ + cid_adjust[cid_index] = cid_adj_array[pinfo->fd->num]; + /* Set the frag_number at start of packet. */ + if (first_gmh) + { + frag_number[cid_index] = frag_num_array[pinfo->fd->num]; + } + } else { + /* Save for next time we click on this packet. */ + cid_adj_array[pinfo->fd->num] = cid_adjust[cid_index]; + if (first_gmh) + { + frag_num_array[pinfo->fd->num] = frag_number[cid_index]; + } + } + /* Reset in case we stay in this while() loop to finish the packet. */ + first_gmh = FALSE; + cid = cid_base + cid_adjust[cid_index] + cid_vernier[cid_index]; + /* Save address pointers. */ + save_src = pinfo->src; + save_dst = pinfo->dst; + /* Use dl_src and dl_dst in defrag. */ + pinfo->src = pinfo->dl_src; + pinfo->dst = pinfo->dl_dst; + payload_frag = fragment_add_seq(tvb, offset, pinfo, cid, payload_frag_table, frag_number[cid_index], frag_len, ((frag_type==LAST_FRAG)?0:1)); + /* Restore address pointers. */ + pinfo->src = save_src; + pinfo->dst = save_dst; + if (frag_type == LAST_FRAG) + { + /* Make sure fragment_add_seq() sees next one as a new frame. */ + cid_vernier[cid_index]++; + } + /* Don't show reassem packet until last frag. */ + proto_tree_add_text(tree, tvb, offset, frag_len, "Payload Fragment (%d bytes)", frag_len); + + if (payload_frag && frag_type == LAST_FRAG) + { /* defragmented completely */ + payload_length = payload_frag->len; + /* create the new tvb for defragmented frame */ + payload_tvb = tvb_new_real_data(payload_frag->data, payload_length, payload_length); + /* attach the payload_tvb to tvb so that it will be cleaned up when tvb is cleaned up */ + tvb_set_child_real_data_tvbuff(tvb, payload_tvb); + /* add the defragmented data to the data source list */ + add_new_data_source(pinfo, payload_tvb, "Reassembled WiMax MAC payload"); + /* save the tvb langth */ + new_payload_len = payload_length; + } + else /* error or defragment is not complete */ + { + payload_tvb = NULL; +#ifdef DEBUG /* for debug only */ +/* if (frag_type == LAST_FRAG)*/ + { /* error */ + /* update the info column */ + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Dropped the incomplete frame"); + } +#endif +#if 0 + if (frag_type == FIRST_FRAG) + { /* Set up to decode the first fragment (even though next fragment not read yet) */ + payload_tvb = tvb_new_subset(tvb, offset, length, length); + payload_length = length; + frag_len = length; + } +#endif + } + } + /* process the defragmented payload */ + if (payload_tvb) + { /* reset the payload_offset */ + payload_offset = 0; + /* process the payload */ + if (payload_length > 0) + { + if (!new_payload_len) + continue; + /* if ARQ Feedback payload is present, it should be the first SDU */ + if (first_arq_fb_payload && arq_fb_payload) + { /* decode and display the ARQ feedback payload */ + first_arq_fb_payload = FALSE; + ret_length = arq_feedback_payload_decoder(tvb_new_subset(payload_tvb, payload_offset, new_payload_len, new_payload_len), pinfo, generic_tree, parent_item); +#ifdef DEBUG /* for debug only */ + if (ret_length != new_payload_len) + { /* error */ + /* update the info column */ + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "incorrect ARQ fb payload size"); + } +#endif + } + else /* decode SDUs */ + { /* check the payload type */ + if (mac_cid == cid_padding) + { /* update the info column */ + if (check_col(pinfo->cinfo, COL_INFO)) + { + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Padding CID"); + } + /* get the parent */ + generic_item = proto_tree_get_parent(tree); + /* add the MAC header info */ + proto_item_append_text(generic_item, ", Padding CID"); + /* display padding CID */ + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, payload_tvb, payload_offset, new_payload_len, "Padding CID (%u bytes)", new_payload_len); + /* add payload subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_header_generic_decoder); + /* display the Padding CID payload in Hex */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_value_bytes, payload_tvb, payload_offset, new_payload_len, FALSE); + } + else if ((mac_cid <= (2 * global_cid_max_basic)) || (mac_cid == cid_aas_ranging) + || (mac_cid >= cid_normal_multicast)) + { /* MAC management message */ + dissect_mac_mgmt_msg_decoder(tvb_new_subset(payload_tvb, payload_offset, new_payload_len, new_payload_len), pinfo, tree); + } + else /* data transport PDU */ + { /* update the info column */ + if (check_col(pinfo->cinfo, COL_INFO)) + { + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Data"); + } + /* add the MAC payload info */ + proto_item_append_text(parent_item, ", Data"); + /* display payload info */ + if ((new_payload_len + payload_offset) > payload_length) + { + new_tvb_len = new_payload_len - payload_offset; + } + else + { + new_tvb_len = new_payload_len; + } + if (frag_type == LAST_FRAG || frag_type == NO_FRAG) + { + if (frag_type == NO_FRAG) + { + str_ptr = data_str; + new_payload_len = frag_len; + } + else + { + str_ptr = reassem_str; + } + { + data_pdu_tvb = tvb_new_subset(payload_tvb, payload_offset, new_tvb_len, new_tvb_len); + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, data_pdu_tvb, payload_offset, new_payload_len, str_ptr, new_payload_len); + /* add payload subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_data_pdu_decoder); + /* check the data type */ + if (tvb_get_guint8(payload_tvb, payload_offset) == IP_HEADER_BYTE) + { + mac_payload_handle = find_dissector("ip"); + if (mac_payload_handle) + call_dissector(mac_payload_handle, tvb_new_subset(payload_tvb, payload_offset, new_tvb_len, new_tvb_len), pinfo, generic_tree); + else /* display the Generic MAC Header in Hex */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_value_bytes, payload_tvb, payload_offset, new_tvb_len, FALSE); + } + else /* display the Generic MAC Header in Hex */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_value_bytes, payload_tvb, payload_offset, new_tvb_len, FALSE); + } + } + } + } + payload_length -= new_payload_len; + payload_offset += new_payload_len; + } /* end of while loop */ + } /* end of payload processing */ + length -= frag_len; + offset += frag_len; + } /* end of payload decoding */ +check_crc: + /* Decode and display the CRC if it is present */ + if (mac_ci) + { + /* add the CRC info */ + proto_item_append_text(parent_item, ", CRC"); + /* check the length */ + if (MIN(tvb_len, tvb_reported_length(tvb)) >= mac_len) + { /* get the CRC */ + mac_crc = tvb_get_ntohl(tvb, mac_len - sizeof(mac_crc)); + /* calculate the CRC */ + calculated_crc = wimax_mac_calc_crc32((guint8 *)tvb_get_ptr(tvb, 0, mac_len - sizeof(mac_crc)), mac_len - sizeof(mac_crc)); + /* display the CRC */ + generic_item = proto_tree_add_item(tree, hf_mac_header_generic_crc, tvb, mac_len - sizeof(mac_crc), sizeof(mac_crc), FALSE); + if (mac_crc != calculated_crc) + { + proto_item_append_text(generic_item, " - incorrect! (should be: 0x%x)", calculated_crc); + } + } + else + { /* display error message */ + proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, 0, tvb_len, "CRC missing - the frame is too short (%u bytes)", tvb_len); + } + } + else /* CRC is not included */ + { /* add the CRC info */ + proto_item_append_text(parent_item, ", No CRC"); + /* display message */ + proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, 0, tvb_len, "CRC is not included in this frame!"); + } + } +} + +static gint extended_subheader_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + gint offset = 0; + gint length, ext_length, ubyte, i; + proto_item *ti = NULL; + proto_tree *sub_tree = NULL; + proto_tree *ti_tree = NULL; + + /* update the info column */ + if (check_col(pinfo->cinfo, COL_INFO)) + { + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Ext subhdrs"); + } + + /* Get the tvb length */ + length = tvb_length(tvb); + if (!length) + { /* display the error message */ + proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, length, "Error: extended subheader tvb is empty ! (%u bytes)", length); + return length; + } + + /* Get the length of the extended subheader group */ + ext_length = tvb_get_guint8(tvb, offset); + /* display subheader type */ + ti = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, length, "Extended subheader group (%u bytes)", ext_length); + /* add extended subheader subtree */ + sub_tree = proto_item_add_subtree(ti, ett_mac_ext_subheader_decoder); + /* decode and display the extended subheaders */ + for (i=1; i<ext_length;) + { /* Get the extended subheader type */ + ubyte = (tvb_get_guint8(tvb, (offset+i)) & EXTENDED_SUB_HEADER_TYPE_MASK); + /* decode and display the extended subheader type (MSB) */ + proto_tree_add_item(sub_tree, hf_mac_header_generic_ext_subheader_rsv, tvb, (offset+i), 1, FALSE); + /* for downlink */ + if (is_down_link(&(pinfo->src))) /* for downlink */ + { /* decode and display the extended subheader type */ + ti = proto_tree_add_item(sub_tree, hf_mac_header_generic_ext_subheader_type_dl, tvb, (offset+i), 1, FALSE); + /* add subtree */ + ti_tree = proto_item_add_subtree(ti, ett_mac_ext_subheader_dl_decoder); + i++; + switch (ubyte) + { + case SDU_SN: + /* decode and display the extended sdu sn subheader */ + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_sdu_sn, tvb, (offset+i), 1, FALSE); + i++; + break; + case DL_SLEEP_CONTROL: + /* decode and display the extended dl sleep control subheader */ + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_dl_sleep_control_pscid, tvb, (offset+i), 3, FALSE); + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_dl_sleep_control_op, tvb, (offset+i), 3, FALSE); + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_dl_sleep_control_fswe, tvb, (offset+i), 3, FALSE); + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_dl_sleep_control_fswb, tvb, (offset+i), 3, FALSE); + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_dl_sleep_control_rsv, tvb, (offset+i), 3, FALSE); + i += 3; + break; + case FEEDBACK_REQ: + /* decode and display the extended feedback request subheader */ + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_fb_req_uiuc, tvb, (offset+i), 3, FALSE); + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_fb_req_fb_type, tvb, (offset+i), 3, FALSE); + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_fb_req_ofdma_symbol_offset, tvb, (offset+i), 3, FALSE); + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_fb_req_subchannel_offset, tvb, (offset+i), 3, FALSE); + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_fb_req_slots, tvb, (offset+i), 3, FALSE); + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_fb_req_frame_offset, tvb, (offset+i), 3, FALSE); + i += 3; + break; + case SN_REQ: + /* decode and display the extended SN request subheader */ + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_sn_req_rep_ind_1, tvb, (offset+i), 1, FALSE); + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_sn_req_rep_ind_2, tvb, (offset+i), 1, FALSE); + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_sn_req_rsv, tvb, (offset+i), 1, FALSE); + i++; + break; + case PDU_SN_SHORT_DL: + /* decode and display the extended pdu sn (short) subheader */ + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_pdu_sn_short, tvb, (offset+i), 1, FALSE); + i++; + break; + case PDU_SN_LONG_DL: + /* decode and display the extended pdu sn (long) subheader */ + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_pdu_sn_long, tvb, (offset+i), 2, FALSE); + i += 2; + break; + default: /* reserved */ + break; + } + } + else /* for uplink */ + { /* decode and display the extended subheader type */ + ti = proto_tree_add_item(sub_tree, hf_mac_header_generic_ext_subheader_type_ul, tvb, (offset+i), 1, FALSE); + /* add subtree */ + ti_tree = proto_item_add_subtree(ti, ett_mac_ext_subheader_ul_decoder); + i++; + switch (ubyte) + { + case MIMO_MODE_FEEDBACK: + /* decode and display the extended MIMO Mode Feedback subheader */ + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_mimo_mode_fb_type, tvb, (offset+i), 1, FALSE); + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_mimo_fb_content, tvb, (offset+i), 1, FALSE); + i++; + break; + case UL_TX_POWER_REPORT: + /* decode and display the extended ul tx power report subheader */ + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_ul_tx_pwr_rep, tvb, (offset+i), 1, FALSE); + i++; + break; + case MINI_FEEDBACK: + /* decode and display the extended MINI Feedback subheader */ + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_mini_fb_type, tvb, (offset+i), 2, FALSE); + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_mini_fb_content, tvb, (offset+i), 2, FALSE); + i += 2; + break; + case PDU_SN_SHORT_UL: + /* decode and display the extended pdu sn (short) subheader */ + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_pdu_sn_short, tvb, (offset+i), 1, FALSE); + i++; + break; + case PDU_SN_LONG_UL: + /* decode and display the extended pdu sn (long) subheader */ + proto_tree_add_item(ti_tree, hf_mac_header_generic_ext_subheader_pdu_sn_long, tvb, (offset+i), 2, FALSE); + i += 2; + break; + default: /* reserved */ + break; + } + } + } + /* return the extended subheader length */ + return ext_length; +} + +static gint arq_feedback_payload_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *parent_item) +{ + gint length, i; + gint offset; + gint last_ie = 0; + gint ack_type, num_maps, seq_format; + gint word2, word3; + proto_item *ti = NULL; + proto_item *sub_ti = NULL; + proto_tree *sub_tree = NULL; + + /* update the info column */ + if (check_col(pinfo->cinfo, COL_INFO)) + { + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "ARQ feedback payld"); + } + + /* add the MAC header info */ + proto_item_append_text(parent_item, ", ARQ feedback payload"); + + /* reset the offset */ + offset = 0; + + /* Get the tvb length */ + length = tvb_length(tvb); + if (!length) + { /* display the error message */ + proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, length, "Error: ARQ feedback payload tvb is empty ! (%u bytes)", length); + return length; + } + + /* display subheader type */ + ti = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, length, "ARQ feedback payload "); + /* add extended subheader subtree */ + sub_tree = proto_item_add_subtree(ti, ett_mac_arq_fb_payload_decoder); + /* decode and display the ARQ Feedback IEs */ + while (!last_ie) + { /* decode and display CID */ + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_cid, tvb, offset, 2, FALSE); + /* move to next 16-bit word */ + offset += 2; + /* Get the 2nd 16-bit */ + word2 = tvb_get_ntohs(tvb, offset); + /* get the last bit */ + last_ie = (word2 & ARQ_FB_IE_LAST_BIT_MASK); + /* get the ACK type */ + ack_type = ((word2 & ARQ_FB_IE_ACK_TYPE_MASK) >> 13); + /* get the number of ACK maps */ + num_maps = (word2 & ARQ_FB_IE_NUM_MAPS_MASK) + 1; + /* decode and display the 2nd word */ + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_last, tvb, offset, 2, FALSE); + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_ack_type, tvb, offset, 2, FALSE); + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_bsn, tvb, offset, 2, FALSE); + /* decode and display the 3rd word */ + if (ack_type != 1) + { + sub_ti = proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_num_maps, tvb, offset, 2, FALSE); + /* move to next 16-bit word */ + offset += 2; + proto_item_append_text(sub_ti, " (%d map(s))", num_maps); + for (i = 0; i < num_maps; i++) + { + if (ack_type != 3) + { + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_sel_ack_map, tvb, offset, 2, FALSE); + } + else + { /* Get the next 16-bit */ + word3 = tvb_get_ntohs(tvb, offset); + /* get the sequence format */ + seq_format = (word3 & ARQ_FB_IE_SEQ_FORMAT_MASK); + /* decode and display the sequence format */ + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_seq_format, tvb, offset, 2, FALSE); + if (!seq_format) + { + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_seq_ack_map_2, tvb, offset, 2, FALSE); + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_seq1_length_6, tvb, offset, 2, FALSE); + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_seq2_length_6, tvb, offset, 2, FALSE); + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_rsv, tvb, offset, 2, FALSE); + } + else + { + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_seq_ack_map, tvb, offset, 2, FALSE); + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_seq1_length, tvb, offset, 2, FALSE); + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_seq2_length, tvb, offset, 2, FALSE); + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_seq3_length, tvb, offset, 2, FALSE); + } + } + /* move to next 16-bit word */ + offset += 2; + } + } + else + { + /* Number of ACK Maps bits are reserved when ACK TYPE == 1 */ + proto_tree_add_item(sub_tree, hf_ack_type_reserved, tvb, offset, 2, FALSE); + /* move to next 16-bit word */ + offset += 2; + } + } + /* append text */ + proto_item_append_text(ti,"(%u bytes)", offset); + /* return the offset */ + return offset; +} |