diff options
author | Alexis La Goutte <alexis.lagoutte@gmail.com> | 2012-09-18 20:46:05 +0000 |
---|---|---|
committer | Alexis La Goutte <alexis.lagoutte@gmail.com> | 2012-09-18 20:46:05 +0000 |
commit | b6e0cc28a56a0547c13d4547328bf827d8a66895 (patch) | |
tree | a6ba0515090be8f9bcfb45af1ea199f69ab48ddd /epan | |
parent | 90e68a72b9cca80f064710fe9f68c6ac59c85faf (diff) |
From Daniel via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=7716
Adding VHT Radiotap fields support
Parsing and UI representation for recently adopted VHT Radiotap fields for
802.11ac specification
http://www.radiotap.org/defined-fields/VHT
From me :
* Make checkAPIs happy
* Fix wrong last argument for some proto_tree_add_item
* Use proto_tree_add_item when it is possible
svn path=/trunk/; revision=44985
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dissectors/packet-ieee80211-radiotap-defs.h | 54 | ||||
-rw-r--r-- | epan/dissectors/packet-ieee80211-radiotap-iter.c | 4 | ||||
-rw-r--r-- | epan/dissectors/packet-ieee80211-radiotap.c | 503 |
3 files changed, 556 insertions, 5 deletions
diff --git a/epan/dissectors/packet-ieee80211-radiotap-defs.h b/epan/dissectors/packet-ieee80211-radiotap-defs.h index 08f5ccd6e3..e0b9a6a009 100644 --- a/epan/dissectors/packet-ieee80211-radiotap-defs.h +++ b/epan/dissectors/packet-ieee80211-radiotap-defs.h @@ -208,6 +208,7 @@ enum ieee80211_radiotap_type { IEEE80211_RADIOTAP_XCHANNEL = 18, /* Unofficial, used by FreeBSD */ IEEE80211_RADIOTAP_MCS = 19, IEEE80211_RADIOTAP_AMPDU_STATUS = 20, + IEEE80211_RADIOTAP_VHT = 21, /* valid in every it_present bitmap, even vendor namespaces */ IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, @@ -216,8 +217,8 @@ enum ieee80211_radiotap_type { }; /* not (yet) defined Radiotap present flag */ -/* Bit 21 to 28 are not defined (in binary : 0001 1111 1110 0000 0000 0000 0000 0000 */ -#define IEEE80211_RADIOTAP_NOTDEFINED 0x1FE00000 +/* Bit 22 to 28 are not defined (in binary : 0001 1111 1100 0000 0000 0000 0000 0000 */ +#define IEEE80211_RADIOTAP_NOTDEFINED 0x1FC00000 /* Channel flags. */ #define IEEE80211_CHAN_TURBO 0x0010 /* Turbo channel */ @@ -287,4 +288,53 @@ enum ieee80211_radiotap_type { #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010 #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020 + +/* For IEEE80211_RADIOTAP_VHT */ +#define IEEE80211_RADIOTAP_VHT_HAVE_STBC 0x0001 +#define IEEE80211_RADIOTAP_VHT_HAVE_TXOP_PS 0x0002 +#define IEEE80211_RADIOTAP_VHT_HAVE_GI 0x0004 +#define IEEE80211_RADIOTAP_VHT_HAVE_SGI_NSYM_DA 0x0008 +#define IEEE80211_RADIOTAP_VHT_HAVE_LDPC_EXTRA 0x0010 +#define IEEE80211_RADIOTAP_VHT_HAVE_BF 0x0020 +#define IEEE80211_RADIOTAP_VHT_HAVE_BW 0x0040 +#define IEEE80211_RADIOTAP_VHT_HAVE_GID 0x0080 +#define IEEE80211_RADIOTAP_VHT_HAVE_PAID 0x0100 +#define IEEE80211_RADIOTAP_VHT_STBC 0x01 +#define IEEE80211_RADIOTAP_VHT_TXOP_PS 0x02 +#define IEEE80211_RADIOTAP_VHT_SGI 0x04 +#define IEEE80211_RADIOTAP_VHT_SGI_NSYM_DA 0x08 +#define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA 0x10 +#define IEEE80211_RADIOTAP_VHT_BF 0x20 +#define IEEE80211_RADIOTAP_VHT_NSS 0x0f +#define IEEE80211_RADIOTAP_VHT_MCS 0xf0 +#define IEEE80211_RADIOTAP_VHT_CODING_LDPC 0x01 + +#define IEEE80211_RADIOTAP_VHT_BW_20 IEEE80211_RADIOTAP_MCS_BW_20 +#define IEEE80211_RADIOTAP_VHT_BW_40 IEEE80211_RADIOTAP_MCS_BW_40 +#define IEEE80211_RADIOTAP_VHT_BW_20L IEEE80211_RADIOTAP_MCS_BW_20L +#define IEEE80211_RADIOTAP_VHT_BW_20U IEEE80211_RADIOTAP_MCS_BW_20U +#define IEEE80211_RADIOTAP_VHT_BW_80 4 +#define IEEE80211_RADIOTAP_VHT_BW_40L 5 +#define IEEE80211_RADIOTAP_VHT_BW_40U 6 +#define IEEE80211_RADIOTAP_VHT_BW_20LL 7 +#define IEEE80211_RADIOTAP_VHT_BW_20LU 8 +#define IEEE80211_RADIOTAP_VHT_BW_20UL 9 +#define IEEE80211_RADIOTAP_VHT_BW_20UU 10 +#define IEEE80211_RADIOTAP_VHT_BW_160 11 +#define IEEE80211_RADIOTAP_VHT_BW_80L 12 +#define IEEE80211_RADIOTAP_VHT_BW_80U 13 +#define IEEE80211_RADIOTAP_VHT_BW_40LL 14 +#define IEEE80211_RADIOTAP_VHT_BW_40LU 15 +#define IEEE80211_RADIOTAP_VHT_BW_40UL 16 +#define IEEE80211_RADIOTAP_VHT_BW_40UU 17 +#define IEEE80211_RADIOTAP_VHT_BW_20LLL 18 +#define IEEE80211_RADIOTAP_VHT_BW_20LLU 19 +#define IEEE80211_RADIOTAP_VHT_BW_20LUL 20 +#define IEEE80211_RADIOTAP_VHT_BW_20LUU 21 +#define IEEE80211_RADIOTAP_VHT_BW_20ULL 22 +#define IEEE80211_RADIOTAP_VHT_BW_20ULU 23 +#define IEEE80211_RADIOTAP_VHT_BW_20UUL 24 +#define IEEE80211_RADIOTAP_VHT_BW_20UUU 25 + + #endif /* IEEE80211_RADIOTAP_H */ diff --git a/epan/dissectors/packet-ieee80211-radiotap-iter.c b/epan/dissectors/packet-ieee80211-radiotap-iter.c index b54e88affa..ff1e4bacb2 100644 --- a/epan/dissectors/packet-ieee80211-radiotap-iter.c +++ b/epan/dissectors/packet-ieee80211-radiotap-iter.c @@ -51,7 +51,9 @@ static const struct radiotap_align_size rtap_namespace_sizes[] = { /* [IEEE80211_RADIOTAP_DATA_RETRIES] = 17 */ { 1, 1 }, /* [IEEE80211_RADIOTAP_XCHANNEL] = 18 */ { 0, 0 }, /* Unofficial, used by FreeBSD */ /* [IEEE80211_RADIOTAP_MCS] = 19 */ { 1, 3 }, - /* [IEEE80211_RADIOTAP_AMPDU_STATUS] = 20 */ { 4, 8 } + /* [IEEE80211_RADIOTAP_AMPDU_STATUS] = 20 */ { 4, 8 }, + /* [IEEE80211_RADIOTAP_VHT] = 21 */ { 2, 12 } + /* * add more here as they are defined in * include/net/ieee80211_radiotap.h diff --git a/epan/dissectors/packet-ieee80211-radiotap.c b/epan/dissectors/packet-ieee80211-radiotap.c index ee61bbae9d..fdc7b604ad 100644 --- a/epan/dissectors/packet-ieee80211-radiotap.c +++ b/epan/dissectors/packet-ieee80211-radiotap.c @@ -130,6 +130,32 @@ static int hf_radiotap_ampdu_flags_last_known = -1; static int hf_radiotap_ampdu_flags_is_last = -1; static int hf_radiotap_ampdu_flags_delim_crc_error = -1; static int hf_radiotap_ampdu_delim_crc = -1; +static int hf_radiotap_vht = -1; +static int hf_radiotap_vht_known = -1; +static int hf_radiotap_vht_have_stbc = -1; +static int hf_radiotap_vht_have_txop_ps = -1; +static int hf_radiotap_vht_have_gi = -1; +static int hf_radiotap_vht_have_sgi_nsym_da = -1; +static int hf_radiotap_vht_have_ldpc_extra = -1; +static int hf_radiotap_vht_have_bf = -1; +static int hf_radiotap_vht_have_bw = -1; +static int hf_radiotap_vht_have_gid = -1; +static int hf_radiotap_vht_have_p_aid = -1; +static int hf_radiotap_vht_stbc = -1; +static int hf_radiotap_vht_txop_ps = -1; +static int hf_radiotap_vht_gi = -1; +static int hf_radiotap_vht_sgi_nsym_da = -1; +static int hf_radiotap_vht_ldpc_extra = -1; +static int hf_radiotap_vht_bf = -1; +static int hf_radiotap_vht_bw = -1; +static int hf_radiotap_vht_nsts[4] = { -1, -1, -1, -1 }; +static int hf_radiotap_vht_mcs[4] = { -1, -1, -1, -1 }; +static int hf_radiotap_vht_nss[4] = { -1, -1, -1, -1 }; +static int hf_radiotap_vht_coding[4] = { -1, -1, -1, -1 }; +static int hf_radiotap_vht_datarate[4] = { -1, -1, -1, -1 }; +static int hf_radiotap_vht_gid = -1; +static int hf_radiotap_vht_p_aid = -1; +static int hf_radiotap_vht_user = -1; /* "Present" flags */ static int hf_radiotap_present_tsft = -1; @@ -151,6 +177,7 @@ static int hf_radiotap_present_rxflags = -1; static int hf_radiotap_present_xchannel = -1; static int hf_radiotap_present_mcs = -1; static int hf_radiotap_present_ampdu = -1; +static int hf_radiotap_present_vht = -1; static int hf_radiotap_present_reserved = -1; static int hf_radiotap_present_rtap_ns = -1; static int hf_radiotap_present_vendor_ns = -1; @@ -182,6 +209,9 @@ static gint ett_radiotap_mcs = -1; static gint ett_radiotap_mcs_known = -1; static gint ett_radiotap_ampdu = -1; static gint ett_radiotap_ampdu_flags = -1; +static gint ett_radiotap_vht = -1; +static gint ett_radiotap_vht_known = -1; +static gint ett_radiotap_vht_user = -1; static dissector_handle_t ieee80211_handle; static dissector_handle_t ieee80211_datapad_handle; @@ -237,6 +267,137 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree); #define IEEE80211_CHAN_108PUREG \ (IEEE80211_CHAN_PUREG | IEEE80211_CHAN_TURBO) +#define MAX_MCS_VHT_INDEX 9 + +/* + * Maps a VHT bandwidth index to ieee80211_vhtinfo.rates index. + */ +static const int ieee80211_vht_bw2rate_index[] = { + /* 20Mhz total */ 0, + /* 40Mhz total */ 1, 0, 0, + /* 80Mhz total */ 2, 1, 1, 0, 0, 0, 0, + /* 160Mhz total */ 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +struct mcs_vht_info { + char *modulation; + char *coding_rate; + float rates[4][2]; +}; + +static const struct mcs_vht_info ieee80211_vhtinfo[MAX_MCS_VHT_INDEX+1] = { + /* MCS 0 */ + { "BPSK", "1/2", + { /* 20 Mhz */ { 6.5f, /* SGI */ 7.2f, }, + /* 40 Mhz */ { 13.5f, /* SGI */ 15.0f, }, + /* 80 Mhz */ { 29.3f, /* SGI */ 32.5f, }, + /* 160 Mhz */ { 58.5f, /* SGI */ 65.0f, } + } + }, + /* MCS 1 */ + { "QPSK", "1/2", + { /* 20 Mhz */ { 13.0f, /* SGI */ 14.4f, }, + /* 40 Mhz */ { 27.0f, /* SGI */ 30.0f, }, + /* 80 Mhz */ { 58.5f, /* SGI */ 65.0f, }, + /* 160 Mhz */ { 117.0f, /* SGI */ 130.0f, } + } + }, + /* MCS 2 */ + { "QPSK", "3/4", + { /* 20 Mhz */ { 19.5f, /* SGI */ 21.7f, }, + /* 40 Mhz */ { 40.5f, /* SGI */ 45.0f, }, + /* 80 Mhz */ { 87.8f, /* SGI */ 97.5f, }, + /* 160 Mhz */ { 175.5f, /* SGI */ 195.0f, } + } + }, + /* MCS 3 */ + { "16-QAM", "1/2", + { /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, }, + /* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, }, + /* 80 Mhz */ { 117.0f, /* SGI */ 130.0f, }, + /* 160 Mhz */ { 234.0f, /* SGI */ 260.0f, } + } + }, + /* MCS 4 */ + { "16-QAM", "3/4", + { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, }, + /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, }, + /* 80 Mhz */ { 175.5f, /* SGI */ 195.0f, }, + /* 160 Mhz */ { 351.0f, /* SGI */ 390.0f, } + } + }, + /* MCS 5 */ + { "64-QAM", "2/3", + { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, }, + /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, }, + /* 80 Mhz */ { 234.0f, /* SGI */ 260.0f, }, + /* 160 Mhz */ { 468.0f, /* SGI */ 520.0f, } + } + }, + /* MCS 6 */ + { "64-QAM", "3/4", + { /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, }, + /* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, }, + /* 80 Mhz */ { 263.3f, /* SGI */ 292.5f, }, + /* 160 Mhz */ { 526.5f, /* SGI */ 585.0f, } + } + }, + /* MCS 7 */ + { "64-QAM", "5/6", + { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, }, + /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, }, + /* 80 Mhz */ { 292.5f, /* SGI */ 325.0f, }, + /* 160 Mhz */ { 585.0f, /* SGI */ 650.0f, } + } + }, + /* MCS 8 */ + { "256-QAM", "3/4", + { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, + /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, + /* 80 Mhz */ { 351.0f, /* SGI */ 390.0f, }, + /* 160 Mhz */ { 702.0f, /* SGI */ 780.0f, } + } + }, + /* MCS 9 */ + { "256-QAM", "5/6", + { /* 20 Mhz */ { 0.0f, /* SGI */ 0.0f, }, + /* 40 Mhz */ { 180.0f, /* SGI */ 200.0f, }, + /* 80 Mhz */ { 390.0f, /* SGI */ 433.3f, }, + /* 160 Mhz */ { 780.0f, /* SGI */ 866.7f, } + } + } +}; + +static const value_string vht_bandwidth[] = { + { IEEE80211_RADIOTAP_VHT_BW_20, "20 MHz" }, + { IEEE80211_RADIOTAP_VHT_BW_20L, "20 MHz lower" }, + { IEEE80211_RADIOTAP_VHT_BW_20U, "20 MHz upper" }, + { IEEE80211_RADIOTAP_VHT_BW_40, "40 MHz" }, + { IEEE80211_RADIOTAP_VHT_BW_20LL, "20 MHz, channel 1/4" }, + { IEEE80211_RADIOTAP_VHT_BW_20LU, "20 MHz, channel 2/4" }, + { IEEE80211_RADIOTAP_VHT_BW_20UL, "20 MHz, channel 3/4" }, + { IEEE80211_RADIOTAP_VHT_BW_20UU, "20 MHz, channel 4/4" }, + { IEEE80211_RADIOTAP_VHT_BW_40L, "40 MHz lower" }, + { IEEE80211_RADIOTAP_VHT_BW_40U, "40 MHz upper" }, + { IEEE80211_RADIOTAP_VHT_BW_80, "80 MHz" }, + { IEEE80211_RADIOTAP_VHT_BW_20LLL, "20 MHz, channel 1/8" }, + { IEEE80211_RADIOTAP_VHT_BW_20LLU, "20 MHz, channel 2/8" }, + { IEEE80211_RADIOTAP_VHT_BW_20LUL, "20 MHz, channel 3/8" }, + { IEEE80211_RADIOTAP_VHT_BW_20LUU, "20 MHz, channel 4/8" }, + { IEEE80211_RADIOTAP_VHT_BW_20ULL, "20 MHz, channel 5/8" }, + { IEEE80211_RADIOTAP_VHT_BW_20ULU, "20 MHz, channel 6/8" }, + { IEEE80211_RADIOTAP_VHT_BW_20UUL, "20 MHz, channel 7/8" }, + { IEEE80211_RADIOTAP_VHT_BW_20UUU, "20 MHz, channel 8/8" }, + { IEEE80211_RADIOTAP_VHT_BW_40LL, "40 MHz, channel 1/4" }, + { IEEE80211_RADIOTAP_VHT_BW_40LU, "40 MHz, channel 2/4" }, + { IEEE80211_RADIOTAP_VHT_BW_40UL, "40 MHz, channel 3/4" }, + { IEEE80211_RADIOTAP_VHT_BW_40UU, "40 MHz, channel 4/4" }, + { IEEE80211_RADIOTAP_VHT_BW_80L, "80 MHz lower" }, + { IEEE80211_RADIOTAP_VHT_BW_80U, "80 MHz upper" }, + { IEEE80211_RADIOTAP_VHT_BW_160, "160 MHz" }, + { 0, NULL } +}; + #define MAX_MCS_INDEX 76 /* @@ -815,7 +976,7 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) int hdr_fcs_offset = 0; guint32 sent_fcs = 0; guint32 calc_fcs; - gint err; + gint err = -ENOENT; struct ieee80211_radiotap_iterator iter; void *data; struct _radiotap_info *radiotap_info; @@ -981,6 +1142,9 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) proto_tree_add_item(present_tree, hf_radiotap_present_ampdu, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN); + proto_tree_add_item(present_tree, + hf_radiotap_present_vht, tvb, + offset + 4, 4, ENC_LITTLE_ENDIAN); ti = proto_tree_add_item(present_tree, hf_radiotap_present_reserved, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN); @@ -1532,7 +1696,6 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) proto_item *it; proto_tree *ampdu_tree = NULL, *ampdu_flags_tree; guint16 flags; - flags = tvb_get_letohs(tvb, offset + 4); if (tree) { @@ -1564,6 +1727,171 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) } break; } + case IEEE80211_RADIOTAP_VHT: { + proto_item *it, *it_root = NULL; + proto_tree *vht_tree = NULL, *vht_known_tree = NULL, *user_tree = NULL; + guint16 known, nsts; + guint8 flags, bw, mcs_nss; + guint bandwidth = 0; + guint gi_length = 0; + guint nss = 0; + guint mcs = 0; + gboolean can_calculate_rate; + guint i; + + /* + * Start out assuming that we can calculate the rate; + * if we are missing any of the MCS index, channel + * width, or guard interval length, we can't. + */ + can_calculate_rate = TRUE; + + known = tvb_get_letohs(tvb, offset); + flags = tvb_get_guint8(tvb, offset + 2); + bw = tvb_get_guint8(tvb, offset + 3); + + if (tree) { + it_root = proto_tree_add_item(radiotap_tree, hf_radiotap_vht, + tvb, offset, 12, ENC_NA); + vht_tree = proto_item_add_subtree(it_root, ett_radiotap_vht); + it = proto_tree_add_item(vht_tree, hf_radiotap_vht_known, + tvb, offset, 2, known); + vht_known_tree = proto_item_add_subtree(it, ett_radiotap_vht_known); + + proto_tree_add_item(vht_known_tree, hf_radiotap_vht_have_stbc, + tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(vht_known_tree, hf_radiotap_vht_have_txop_ps, + tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(vht_known_tree, hf_radiotap_vht_have_gi, + tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(vht_known_tree, hf_radiotap_vht_have_sgi_nsym_da, + tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(vht_known_tree, hf_radiotap_vht_have_ldpc_extra, + tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(vht_known_tree, hf_radiotap_vht_have_bf, + tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(vht_known_tree, hf_radiotap_vht_have_bw, + tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(vht_known_tree, hf_radiotap_vht_have_gid, + tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(vht_known_tree, hf_radiotap_vht_have_p_aid, + tvb, offset, 2, ENC_LITTLE_ENDIAN); + } + + if (known & IEEE80211_RADIOTAP_VHT_HAVE_STBC) { + if (vht_tree) + proto_tree_add_item(vht_tree, hf_radiotap_vht_stbc, + tvb, offset + 2, 1, ENC_LITTLE_ENDIAN); + } + + if (known & IEEE80211_RADIOTAP_VHT_HAVE_TXOP_PS) { + if (vht_tree) + proto_tree_add_item(vht_tree, hf_radiotap_vht_txop_ps, + tvb, offset + 2, 1, ENC_LITTLE_ENDIAN); + } + + if (known & IEEE80211_RADIOTAP_VHT_HAVE_GI) { + gi_length = (flags & IEEE80211_RADIOTAP_VHT_SGI) ? 1 : 0; + if (vht_tree) { + proto_tree_add_item(vht_tree, hf_radiotap_vht_gi, + tvb, offset + 2, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(vht_tree, hf_radiotap_vht_sgi_nsym_da, + tvb, offset + 2, 1, ENC_LITTLE_ENDIAN); + } + } else { + can_calculate_rate = FALSE; /* no GI width */ + } + + if (known & IEEE80211_RADIOTAP_VHT_HAVE_LDPC_EXTRA) { + if (vht_tree) { + proto_tree_add_item(vht_tree, hf_radiotap_vht_ldpc_extra, + tvb, offset + 2, 1, ENC_LITTLE_ENDIAN); + } + } + + if (known & IEEE80211_RADIOTAP_VHT_HAVE_BF) { + if (vht_tree) + proto_tree_add_item(vht_tree, hf_radiotap_vht_bf, + tvb, offset + 2, 1, ENC_LITTLE_ENDIAN); + } + + if (known & IEEE80211_RADIOTAP_VHT_HAVE_BW) { + if (bw <= sizeof(ieee80211_vht_bw2rate_index)/sizeof(ieee80211_vht_bw2rate_index[0])) + bandwidth = ieee80211_vht_bw2rate_index[bw]; + else + can_calculate_rate = FALSE; /* unknown bandwidth */ + + if (vht_tree) + proto_tree_add_item(vht_tree, hf_radiotap_vht_bw, + tvb, offset + 3, 1, ENC_LITTLE_ENDIAN); + } else { + can_calculate_rate = FALSE; /* no bandwidth */ + } + + for(i=0; i<4; i++) { + mcs_nss = tvb_get_guint8(tvb, offset + 4 + i); + nss = (mcs_nss & IEEE80211_RADIOTAP_VHT_NSS); + mcs = (mcs_nss & IEEE80211_RADIOTAP_VHT_MCS) >> 4; + + if ((known & IEEE80211_RADIOTAP_VHT_HAVE_STBC) && (flags & IEEE80211_RADIOTAP_VHT_STBC)) + nsts = 2 * nss; + else + nsts = nss; + + if (nss) { + if (vht_tree) { + it = proto_tree_add_item(vht_tree, hf_radiotap_vht_user, + tvb, offset + 4, 5, ENC_NA); + proto_item_append_text(it, " %d: MCS %u", i, mcs); + user_tree = proto_item_add_subtree(it, ett_radiotap_vht_user); + + it = proto_tree_add_item(user_tree, hf_radiotap_vht_mcs[i], + tvb, offset + 4 + i, 1, + ENC_LITTLE_ENDIAN); + if (mcs > MAX_MCS_VHT_INDEX) { + proto_item_append_text(it, " (invalid)"); + } else { + proto_item_append_text(it, " (%s %s)", + ieee80211_vhtinfo[mcs].modulation, + ieee80211_vhtinfo[mcs].coding_rate); + } + + proto_tree_add_item(user_tree, hf_radiotap_vht_nss[i], + tvb, offset + 4 + i, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_uint(user_tree, hf_radiotap_vht_nsts[i], + tvb, offset + 4 + i, 1, nsts); + proto_tree_add_item(user_tree, hf_radiotap_vht_coding[i], + tvb, offset + 8, 1,ENC_LITTLE_ENDIAN); + } + + if (can_calculate_rate) { + float rate = ieee80211_vhtinfo[mcs].rates[bandwidth][gi_length] * nss; + if (rate != 0.0f && user_tree) { + rate_ti = proto_tree_add_float_format(user_tree, + hf_radiotap_vht_datarate[i], + tvb, offset, 12, rate, + "Data Rate: %.1f Mb/s", rate); + PROTO_ITEM_SET_GENERATED(rate_ti); + } + } + } + } + + if (known & IEEE80211_RADIOTAP_VHT_HAVE_GID) { + if (vht_tree) + proto_tree_add_item(vht_tree, hf_radiotap_vht_gid, + tvb, offset+9, 1, ENC_LITTLE_ENDIAN); + } + + if (known & IEEE80211_RADIOTAP_VHT_HAVE_PAID) { + if (vht_tree) { + proto_tree_add_item(vht_tree, hf_radiotap_vht_p_aid, + tvb, offset+10, 2, ENC_LITTLE_ENDIAN); + } + } + + break; + } } } @@ -1761,6 +2089,11 @@ void proto_register_radiotap(void) FT_BOOLEAN, 32, NULL, RADIOTAP_MASK(AMPDU_STATUS), "Specifies if the A-MPDU status field is present", HFILL}}, + {&hf_radiotap_present_vht, + {"VHT information", "radiotap.present.vht", + FT_BOOLEAN, 32, NULL, RADIOTAP_MASK(VHT), + "Specifies if the VHT field is present", HFILL}}, + {&hf_radiotap_present_reserved, {"Reserved", "radiotap.present.reserved", FT_UINT32, BASE_HEX, NULL, IEEE80211_RADIOTAP_NOTDEFINED, @@ -2155,6 +2488,169 @@ void proto_register_radiotap(void) {"A-MPDU subframe delimiter CRC", "radiotap.ampdu.delim_crc", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}}, + {&hf_radiotap_vht, + {"VHT information", "radiotap.vht", + FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, + {&hf_radiotap_vht_known, + {"Known VHT information", "radiotap.vht.known", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Bit mask indicating what VHT information is present", HFILL}}, + {&hf_radiotap_vht_user, + {"User", "radiotap.vht.user", + FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, + {&hf_radiotap_vht_have_stbc, + {"STBC", "radiotap.vht.have_stbc", + FT_BOOLEAN, 16, NULL, IEEE80211_RADIOTAP_VHT_HAVE_STBC, + "Space Time Block Coding information present", HFILL}}, + {&hf_radiotap_vht_have_txop_ps, + {"TXOP_PS_NOT_ALLOWED", "radiotap.vht.have_txop_ps", + FT_BOOLEAN, 16, NULL, IEEE80211_RADIOTAP_VHT_HAVE_TXOP_PS, + "TXOP_PS_NOT_ALLOWED information present", HFILL}}, + {&hf_radiotap_vht_have_gi, + {"Guard interval", "radiotap.vht.have_gi", + FT_BOOLEAN, 16, NULL, IEEE80211_RADIOTAP_VHT_HAVE_GI, + "Short/Long guard interval information present", HFILL}}, + {&hf_radiotap_vht_have_sgi_nsym_da, + {"SGI Nsym disambiguation", "radiotap.vht.have_sgi_nsym_da", + FT_BOOLEAN, 16, NULL, IEEE80211_RADIOTAP_VHT_HAVE_SGI_NSYM_DA, + "Short guard interval Nsym disambiguation information present", HFILL}}, + {&hf_radiotap_vht_have_ldpc_extra, + {"LDPC extra OFDM symbol", "radiotap.vht.ldpc_extra", + FT_BOOLEAN, 16, NULL, IEEE80211_RADIOTAP_VHT_HAVE_LDPC_EXTRA, + NULL, HFILL}}, + {&hf_radiotap_vht_have_bf, + {"Beamformed", "radiotap.vht.have_beamformed", + FT_BOOLEAN, 16, NULL, IEEE80211_RADIOTAP_VHT_HAVE_BF, + NULL, HFILL}}, + {&hf_radiotap_vht_have_bw, + {"Bandwidth", "radiotap.mcs.have_bw", + FT_BOOLEAN, 16, NULL, IEEE80211_RADIOTAP_VHT_HAVE_BW, + NULL, HFILL}}, + {&hf_radiotap_vht_have_gid, + {"Group ID", "radiotap.mcs.have_gid", + FT_BOOLEAN, 16, NULL, IEEE80211_RADIOTAP_VHT_HAVE_GID, + NULL, HFILL}}, + {&hf_radiotap_vht_have_p_aid, + {"Partial AID", "radiotap.mcs.have_paid", + FT_BOOLEAN, 16, NULL, IEEE80211_RADIOTAP_VHT_HAVE_PAID, + NULL, HFILL}}, + {&hf_radiotap_vht_stbc, + {"STBC", "radiotap.vht.stbc", + FT_BOOLEAN, 8, TFS(&tfs_on_off), IEEE80211_RADIOTAP_VHT_STBC, + "Space Time Block Coding flag", HFILL}}, + {&hf_radiotap_vht_txop_ps, + {"TXOP_PS_NOT_ALLOWED", "radiotap.vht.txop_ps", + FT_BOOLEAN, 8, NULL, IEEE80211_RADIOTAP_VHT_TXOP_PS, + "Flag indicating whether STAs may doze during TXOP", HFILL}}, + {&hf_radiotap_vht_gi, + {"Guard interval", "radiotap.vht.gi", + FT_UINT8, BASE_DEC, VALS(mcs_gi), IEEE80211_RADIOTAP_VHT_SGI, + "Short/Long guard interval", HFILL}}, + {&hf_radiotap_vht_sgi_nsym_da, + {"SGI Nsym disambiguation", "radiotap.vht.sgi_nsym_da", + FT_BOOLEAN, 8, NULL, IEEE80211_RADIOTAP_VHT_SGI_NSYM_DA, + "Short Guard Interval Nsym disambiguation", HFILL}}, + {&hf_radiotap_vht_ldpc_extra, + {"LDPC extra OFDM symbol", "radiotap.vht.ldpc_extra", + FT_BOOLEAN, 8, NULL, IEEE80211_RADIOTAP_VHT_LDPC_EXTRA, + NULL, HFILL}}, + {&hf_radiotap_vht_bf, + {"Beamformed", "radiotap.vht.beamformed", + FT_BOOLEAN, 8, NULL, IEEE80211_RADIOTAP_VHT_BF, + NULL, HFILL}}, + {&hf_radiotap_vht_bw, + {"Bandwidth", "radiotap.vht.bw", + FT_UINT8, BASE_DEC, VALS(vht_bandwidth), 0x0, + NULL, HFILL}}, + {&hf_radiotap_vht_nsts[0], + {"Space-time streams 0", "radiotap.vht.nsts.0", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Number of Space-time streams", HFILL}}, + {&hf_radiotap_vht_nsts[1], + {"Space-time streams 1", "radiotap.vht.nsts.1", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Number of Space-time streams", HFILL}}, + {&hf_radiotap_vht_nsts[2], + {"Space-time streams 2", "radiotap.vht.nsts.2", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Number of Space-time streams", HFILL}}, + {&hf_radiotap_vht_nsts[3], + {"Space-time streams 3", "radiotap.vht.nsts.3", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Number of Space-time streams", HFILL}}, + {&hf_radiotap_vht_mcs[0], + {"MCS index 0", "radiotap.vht.mcs.0", + FT_UINT8, BASE_DEC, NULL, IEEE80211_RADIOTAP_VHT_MCS, + "MCS index", HFILL}}, + {&hf_radiotap_vht_mcs[1], + {"MCS index 1", "radiotap.vht.mcs.1", + FT_UINT8, BASE_DEC, NULL, IEEE80211_RADIOTAP_VHT_MCS, + "MCS index", HFILL}}, + {&hf_radiotap_vht_mcs[2], + {"MCS index 2", "radiotap.vht.mcs.2", + FT_UINT8, BASE_DEC, NULL, IEEE80211_RADIOTAP_VHT_MCS, + "MCS index", HFILL}}, + {&hf_radiotap_vht_mcs[3], + {"MCS index 3", "radiotap.vht.mcs.3", + FT_UINT8, BASE_DEC, NULL, IEEE80211_RADIOTAP_VHT_MCS, + "MCS index", HFILL}}, + {&hf_radiotap_vht_nss[0], + {"Spatial streams 0", "radiotap.vht.nss.0", + FT_UINT8, BASE_DEC, NULL, IEEE80211_RADIOTAP_VHT_NSS, + "Number of spatial streams", HFILL}}, + {&hf_radiotap_vht_nss[1], + {"Spatial streams 1", "radiotap.vht.nss.1", + FT_UINT8, BASE_DEC, NULL, IEEE80211_RADIOTAP_VHT_NSS, + "Number of spatial streams", HFILL}}, + {&hf_radiotap_vht_nss[2], + {"Spatial streams 2", "radiotap.vht.nss.2", + FT_UINT8, BASE_DEC, NULL, IEEE80211_RADIOTAP_VHT_NSS, + "Number of spatial streams", HFILL}}, + {&hf_radiotap_vht_nss[3], + {"Spatial streams 3", "radiotap.vht.nss.3", + FT_UINT8, BASE_DEC, NULL, IEEE80211_RADIOTAP_VHT_NSS, + "Number of spatial streams", HFILL}}, + {&hf_radiotap_vht_coding[0], + {"Coding 0", "radiotap.vht.coding.0", + FT_UINT8, BASE_DEC, VALS(mcs_fec), 0x0, + "Coding", HFILL}}, + {&hf_radiotap_vht_coding[1], + {"Coding 1", "radiotap.vht.coding.1", + FT_UINT8, BASE_DEC, VALS(mcs_fec), 0x0, + "Coding", HFILL}}, + {&hf_radiotap_vht_coding[2], + {"Coding 2", "radiotap.vht.coding.2", + FT_UINT8, BASE_DEC, VALS(mcs_fec), 0x0, + "Coding", HFILL}}, + {&hf_radiotap_vht_coding[3], + {"Coding 3", "radiotap.vht.coding.3", + FT_UINT8, BASE_DEC, VALS(mcs_fec), 0x0, + "Coding", HFILL}}, + {&hf_radiotap_vht_datarate[0], + {"Data rate (Mb/s) 0", "radiotap.vht.datarate.0", + FT_FLOAT, BASE_NONE, NULL, 0x0, + "Speed this frame was sent/received at", HFILL}}, + {&hf_radiotap_vht_datarate[1], + {"Data rate (Mb/s) 1", "radiotap.vht.datarate.1", + FT_FLOAT, BASE_NONE, NULL, 0x0, + "Speed this frame was sent/received at", HFILL}}, + {&hf_radiotap_vht_datarate[2], + {"Data rate (Mb/s) 2", "radiotap.vht.datarate.2", + FT_FLOAT, BASE_NONE, NULL, 0x0, + "Speed this frame was sent/received at", HFILL}}, + {&hf_radiotap_vht_datarate[3], + {"Data rate (Mb/s) 3", "radiotap.vht.datarate.3", + FT_FLOAT, BASE_NONE, NULL, 0x0, + "Speed this frame was sent/received at", HFILL}}, + {&hf_radiotap_vht_gid, + {"Group Id", "radiotap.vht.gid", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_radiotap_vht_p_aid, + {"Partial AID", "radiotap.vht.paid", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_radiotap_vendor_ns, {"Vendor namespace", "radiotap.vendor_namespace", FT_BYTES, BASE_NONE, NULL, 0x0, @@ -2200,6 +2696,9 @@ void proto_register_radiotap(void) &ett_radiotap_mcs_known, &ett_radiotap_ampdu, &ett_radiotap_ampdu_flags, + &ett_radiotap_vht, + &ett_radiotap_vht_known, + &ett_radiotap_vht_user }; module_t *radiotap_module; |