Fix handling of 11ac radio metadata.

Add more fields to the metadata to handle everything radiotap has, and
show them.

Call the FEC type field just "FEC", and have it be an integer field with
0 meaning BCC and 1 meaning LDPC, rather than a Boolean.

11ac doesn't have *an* MCS, it can have up to 4, one per user.

Label the 11ac bandwidth values the same way we do in the radiotap
dissector.

Change-Id: I2c2415baff3e5d68d49dda497980e8271d26b1f6
Reviewed-on: https://code.wireshark.org/review/9176
Reviewed-by: Guy Harris <guy@alum.mit.edu>
This commit is contained in:
Guy Harris 2015-06-26 11:28:25 -07:00
parent 51d2eefc95
commit 78adf17850
6 changed files with 399 additions and 119 deletions

View File

@ -51,12 +51,23 @@ static int hf_wlan_radio_11n_mcs_index = -1;
static int hf_wlan_radio_11n_bandwidth = -1;
static int hf_wlan_radio_11n_short_gi = -1;
static int hf_wlan_radio_11n_greenfield = -1;
static int hf_wlan_radio_11n_ldpc = -1;
static int hf_wlan_radio_11n_fec = -1;
static int hf_wlan_radio_11n_stbc_streams = -1;
static int hf_wlan_radio_11n_ness = -1;
static int hf_wlan_radio_11ac_mcs_index = -1;
static int hf_wlan_radio_11ac_bandwidth = -1;
static int hf_wlan_radio_11ac_stbc = -1;
static int hf_wlan_radio_11ac_txop_ps_not_allowed = -1;
static int hf_wlan_radio_11ac_short_gi = -1;
static int hf_wlan_radio_11ac_short_gi_nsym_disambig = -1;
static int hf_wlan_radio_11ac_ldpc_extra_ofdm_symbol = -1;
static int hf_wlan_radio_11ac_beamformed = -1;
static int hf_wlan_radio_11ac_bandwidth = -1;
static int hf_wlan_radio_11ac_user = -1;
static int hf_wlan_radio_11ac_nsts = -1;
static int hf_wlan_radio_11ac_mcs = -1;
static int hf_wlan_radio_11ac_nss = -1;
static int hf_wlan_radio_11ac_fec = -1;
static int hf_wlan_radio_11ac_gid = -1;
static int hf_wlan_radio_11ac_p_aid = -1;
static int hf_wlan_radio_data_rate = -1;
static int hf_wlan_radio_channel = -1;
static int hf_wlan_radio_frequency = -1;
@ -108,25 +119,31 @@ static const value_string bandwidth_vals[] = {
{ PHDR_802_11_BANDWIDTH_80_MHZ, "80 MHz" },
{ PHDR_802_11_BANDWIDTH_40_40L, "40 MHz + 40 MHz lower" },
{ PHDR_802_11_BANDWIDTH_40_40U, "40 MHz + 40 MHz upper" },
{ PHDR_802_11_BANDWIDTH_20LL, "20LL" },
{ PHDR_802_11_BANDWIDTH_20LU, "20LU" },
{ PHDR_802_11_BANDWIDTH_20UL, "20UL" },
{ PHDR_802_11_BANDWIDTH_20UU, "20UU" },
{ PHDR_802_11_BANDWIDTH_20LL, "20 MHz, channel 1/4" },
{ PHDR_802_11_BANDWIDTH_20LU, "20 MHz, channel 2/4" },
{ PHDR_802_11_BANDWIDTH_20UL, "20 MHz, channel 3/4" },
{ PHDR_802_11_BANDWIDTH_20UU, "20 MHz, channel 4/4" },
{ PHDR_802_11_BANDWIDTH_160_MHZ, "160 MHz" },
{ PHDR_802_11_BANDWIDTH_80_80L, "80 MHz + 80 MHz lower" },
{ PHDR_802_11_BANDWIDTH_80_80U, "80 MHz + 80 MHz upper" },
{ PHDR_802_11_BANDWIDTH_40LL, "40LL" },
{ PHDR_802_11_BANDWIDTH_40LU, "40LU" },
{ PHDR_802_11_BANDWIDTH_40UL, "40UL" },
{ PHDR_802_11_BANDWIDTH_40UU, "40UU" },
{ PHDR_802_11_BANDWIDTH_20LLL, "20LLL" },
{ PHDR_802_11_BANDWIDTH_20LLU, "20LLU" },
{ PHDR_802_11_BANDWIDTH_20LUL, "20LUL" },
{ PHDR_802_11_BANDWIDTH_20LUU, "20LUU" },
{ PHDR_802_11_BANDWIDTH_20ULL, "20ULL" },
{ PHDR_802_11_BANDWIDTH_20ULU, "20ULU" },
{ PHDR_802_11_BANDWIDTH_20UUL, "20UUL" },
{ PHDR_802_11_BANDWIDTH_20UUU, "20UUU" },
{ PHDR_802_11_BANDWIDTH_40LL, "40 MHz, channel 1/4" },
{ PHDR_802_11_BANDWIDTH_40LU, "40 MHz, channel 2/4" },
{ PHDR_802_11_BANDWIDTH_40UL, "40 MHz, channel 3/4" },
{ PHDR_802_11_BANDWIDTH_40UU, "40 MHz, channel 4/4" },
{ PHDR_802_11_BANDWIDTH_20LLL, "20 MHz, channel 1/8" },
{ PHDR_802_11_BANDWIDTH_20LLU, "20 MHz, channel 2/8" },
{ PHDR_802_11_BANDWIDTH_20LUL, "20 MHz, channel 3/8" },
{ PHDR_802_11_BANDWIDTH_20LUU, "20 MHz, channel 4/8" },
{ PHDR_802_11_BANDWIDTH_20ULL, "20 MHz, channel 5/8" },
{ PHDR_802_11_BANDWIDTH_20ULU, "20 MHz, channel 6/8" },
{ PHDR_802_11_BANDWIDTH_20UUL, "20 MHz, channel 7/8" },
{ PHDR_802_11_BANDWIDTH_20UUU, "20 MHz, channel 8/8" },
{ 0, NULL }
};
static const value_string fec_vals[] = {
{ 0, "BEC" },
{ 1, "LDPC" },
{ 0, NULL }
};
@ -530,7 +547,109 @@ const float ieee80211_float_htrates[MAX_MCS_INDEX+1][2][2] = {
},
};
#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 {
const char *modulation;
const 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 gint ett_wlan_radio = -1;
static gint ett_wlan_radio_11ac_user = -1;
/*
* Dissect 802.11 with a variable-length link-layer header and a pseudo-
@ -552,38 +671,8 @@ dissect_wlan_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void
if (phdr->presence_flags & PHDR_802_11_HAS_DATA_RATE) {
data_rate = phdr->data_rate * 0.5f;
have_data_rate = TRUE;
} else {
/* This applies only to 802.11n and 802.11ac */
switch (phdr->phy) {
case PHDR_802_11_PHY_11N:
/* Do we have all the fields we need to look it up? */
{
#define PHDR_802_11N_ALL_MCS_FIELDS \
(PHDR_802_11N_HAS_MCS_INDEX | \
PHDR_802_11N_HAS_BANDWIDTH | \
PHDR_802_11N_HAS_SHORT_GI)
guint bandwidth_40;
if ((phdr->phy_info.info_11n.presence_flags & PHDR_802_11N_ALL_MCS_FIELDS) == PHDR_802_11N_ALL_MCS_FIELDS) {
bandwidth_40 =
(phdr->phy_info.info_11n.bandwidth == PHDR_802_11_BANDWIDTH_40_MHZ) ?
1 : 0;
if (phdr->phy_info.info_11n.mcs_index < MAX_MCS_INDEX) {
data_rate = ieee80211_float_htrates[phdr->phy_info.info_11n.mcs_index][bandwidth_40][phdr->phy_info.info_11n.short_gi];
have_data_rate = TRUE;
}
}
}
break;
}
}
/* Add the radio information to the column information */
if (have_data_rate)
col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%.1f", data_rate);
if (phdr->presence_flags & PHDR_802_11_HAS_SIGNAL_DBM) {
col_add_fstr(pinfo->cinfo, COL_RSSI, "%u dBm", phdr->signal_dbm);
} else if (phdr->presence_flags & PHDR_802_11_HAS_SIGNAL_PERCENT) {
@ -634,62 +723,180 @@ dissect_wlan_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void
break;
case PHDR_802_11_PHY_11N:
if (phdr->phy_info.info_11n.presence_flags & PHDR_802_11N_HAS_MCS_INDEX) {
proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_mcs_index, tvb, 0, 0,
phdr->phy_info.info_11n.mcs_index);
}
{
guint bandwidth_40;
if (phdr->phy_info.info_11n.presence_flags & PHDR_802_11N_HAS_BANDWIDTH) {
proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_bandwidth, tvb, 0, 0,
phdr->phy_info.info_11n.bandwidth);
}
if (phdr->phy_info.info_11n.presence_flags & PHDR_802_11N_HAS_MCS_INDEX) {
proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_mcs_index, tvb, 0, 0,
phdr->phy_info.info_11n.mcs_index);
}
if (phdr->phy_info.info_11n.presence_flags & PHDR_802_11N_HAS_SHORT_GI) {
proto_tree_add_boolean(radio_tree, hf_wlan_radio_11n_short_gi, tvb, 0, 0,
phdr->phy_info.info_11n.short_gi);
}
if (phdr->phy_info.info_11n.presence_flags & PHDR_802_11N_HAS_BANDWIDTH) {
proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_bandwidth, tvb, 0, 0,
phdr->phy_info.info_11n.bandwidth);
}
if (phdr->phy_info.info_11n.presence_flags & PHDR_802_11N_HAS_GREENFIELD) {
proto_tree_add_boolean(radio_tree, hf_wlan_radio_11n_greenfield, tvb, 0, 0,
phdr->phy_info.info_11n.greenfield);
}
if (phdr->phy_info.info_11n.presence_flags & PHDR_802_11N_HAS_SHORT_GI) {
proto_tree_add_boolean(radio_tree, hf_wlan_radio_11n_short_gi, tvb, 0, 0,
phdr->phy_info.info_11n.short_gi);
}
if (phdr->phy_info.info_11n.presence_flags & PHDR_802_11N_HAS_LDPC) {
proto_tree_add_boolean(radio_tree, hf_wlan_radio_11n_ldpc, tvb, 0, 0,
phdr->phy_info.info_11n.ldpc);
}
if (phdr->phy_info.info_11n.presence_flags & PHDR_802_11N_HAS_GREENFIELD) {
proto_tree_add_boolean(radio_tree, hf_wlan_radio_11n_greenfield, tvb, 0, 0,
phdr->phy_info.info_11n.greenfield);
}
if (phdr->phy_info.info_11n.presence_flags & PHDR_802_11N_HAS_STBC_STREAMS) {
proto_tree_add_boolean(radio_tree, hf_wlan_radio_11n_stbc_streams, tvb, 0, 0,
phdr->phy_info.info_11n.stbc_streams);
}
if (phdr->phy_info.info_11n.presence_flags & PHDR_802_11N_HAS_FEC) {
proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_fec, tvb, 0, 0,
phdr->phy_info.info_11n.fec);
}
if (phdr->phy_info.info_11n.presence_flags & PHDR_802_11N_HAS_NESS) {
proto_tree_add_boolean(radio_tree, hf_wlan_radio_11n_ness, tvb, 0, 0,
phdr->phy_info.info_11n.ness);
if (phdr->phy_info.info_11n.presence_flags & PHDR_802_11N_HAS_STBC_STREAMS) {
proto_tree_add_boolean(radio_tree, hf_wlan_radio_11n_stbc_streams, tvb, 0, 0,
phdr->phy_info.info_11n.stbc_streams);
}
if (phdr->phy_info.info_11n.presence_flags & PHDR_802_11N_HAS_NESS) {
proto_tree_add_boolean(radio_tree, hf_wlan_radio_11n_ness, tvb, 0, 0,
phdr->phy_info.info_11n.ness);
}
/*
* If we have all the fields needed to look up the data rate,
* do so.
*/
#define PHDR_802_11N_ALL_FIELDS_FOR_DATARATE \
(PHDR_802_11N_HAS_MCS_INDEX | \
PHDR_802_11N_HAS_BANDWIDTH | \
PHDR_802_11N_HAS_SHORT_GI)
if ((phdr->phy_info.info_11n.presence_flags & PHDR_802_11N_ALL_FIELDS_FOR_DATARATE) == PHDR_802_11N_ALL_FIELDS_FOR_DATARATE) {
bandwidth_40 =
(phdr->phy_info.info_11n.bandwidth == PHDR_802_11_BANDWIDTH_40_MHZ) ?
1 : 0;
if (phdr->phy_info.info_11n.mcs_index < MAX_MCS_INDEX) {
data_rate = ieee80211_float_htrates[phdr->phy_info.info_11n.mcs_index][bandwidth_40][phdr->phy_info.info_11n.short_gi];
have_data_rate = TRUE;
}
}
}
break;
case PHDR_802_11_PHY_11AC:
if (phdr->phy_info.info_11ac.presence_flags & PHDR_802_11AC_HAS_MCS_INDEX) {
proto_tree_add_uint(radio_tree, hf_wlan_radio_11ac_mcs_index, tvb, 0, 0,
phdr->phy_info.info_11ac.mcs_index);
}
{
gboolean can_calculate_rate;
guint bandwidth;
guint i;
if (phdr->phy_info.info_11ac.presence_flags & PHDR_802_11AC_HAS_BANDWIDTH) {
proto_tree_add_uint(radio_tree, hf_wlan_radio_11ac_bandwidth, tvb, 0, 0,
phdr->phy_info.info_11ac.bandwidth);
}
if (phdr->phy_info.info_11ac.presence_flags & PHDR_802_11AC_HAS_STBC) {
proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_stbc, tvb, 0, 0,
phdr->phy_info.info_11ac.stbc);
}
if (phdr->phy_info.info_11ac.presence_flags & PHDR_802_11AC_HAS_SHORT_GI) {
proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_short_gi, tvb, 0, 0,
phdr->phy_info.info_11ac.short_gi);
}
if (phdr->phy_info.info_11ac.presence_flags & PHDR_802_11AC_HAS_TXOP_PS_NOT_ALLOWED) {
proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_txop_ps_not_allowed, tvb, 0, 0,
phdr->phy_info.info_11ac.txop_ps_not_allowed);
}
if (phdr->phy_info.info_11ac.presence_flags & PHDR_802_11AC_HAS_SHORT_GI) {
can_calculate_rate = TRUE; /* well, if we also have the bandwidth */
proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_short_gi, tvb, 0, 0,
phdr->phy_info.info_11ac.short_gi);
} else {
can_calculate_rate = FALSE; /* unknown GI length */
}
if (phdr->phy_info.info_11ac.presence_flags & PHDR_802_11AC_HAS_SHORT_GI_NSYM_DISAMBIG) {
proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_short_gi_nsym_disambig, tvb, 0, 0,
phdr->phy_info.info_11ac.short_gi_nsym_disambig);
}
if (phdr->phy_info.info_11ac.presence_flags & PHDR_802_11AC_HAS_LDPC_EXTRA_OFDM_SYMBOL) {
proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_ldpc_extra_ofdm_symbol, tvb, 0, 0,
phdr->phy_info.info_11ac.ldpc_extra_ofdm_symbol);
}
if (phdr->phy_info.info_11ac.presence_flags & PHDR_802_11AC_HAS_BEAMFORMED) {
proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_beamformed, tvb, 0, 0,
phdr->phy_info.info_11ac.beamformed);
}
if (phdr->phy_info.info_11ac.presence_flags & PHDR_802_11AC_HAS_BANDWIDTH) {
if (phdr->phy_info.info_11ac.bandwidth < G_N_ELEMENTS(ieee80211_vht_bw2rate_index))
bandwidth = ieee80211_vht_bw2rate_index[phdr->phy_info.info_11ac.bandwidth];
else
can_calculate_rate = FALSE; /* unknown bandwidth */
proto_tree_add_uint(radio_tree, hf_wlan_radio_11ac_bandwidth, tvb, 0, 0,
phdr->phy_info.info_11ac.bandwidth);
} else {
can_calculate_rate = FALSE; /* no bandwidth */
}
for (i = 0; i < 4; i++) {
guint nsts;
if ((phdr->phy_info.info_11ac.presence_flags & PHDR_802_11AC_HAS_STBC) &&
phdr->phy_info.info_11ac.stbc)
nsts = 2 * phdr->phy_info.info_11ac.nss[i];
else
nsts = phdr->phy_info.info_11ac.nss[i];
if (phdr->phy_info.info_11ac.nss[i] != 0) {
proto_item *it;
proto_tree *user_tree;
it = proto_tree_add_item(radio_tree, hf_wlan_radio_11ac_user, tvb, 0, 0, ENC_NA);
proto_item_append_text(it, " %d: MCS %u", i, phdr->phy_info.info_11ac.mcs[i]);
user_tree = proto_item_add_subtree(it, ett_wlan_radio_11ac_user);
it = proto_tree_add_uint(user_tree, hf_wlan_radio_11ac_mcs, tvb, 0, 0,
phdr->phy_info.info_11ac.mcs[i]);
if (phdr->phy_info.info_11ac.mcs[i] > MAX_MCS_VHT_INDEX) {
proto_item_append_text(it, " (invalid)");
} else {
proto_item_append_text(it, " (%s %s)",
ieee80211_vhtinfo[phdr->phy_info.info_11ac.mcs[i]].modulation,
ieee80211_vhtinfo[phdr->phy_info.info_11ac.mcs[i]].coding_rate);
}
proto_tree_add_uint(user_tree, hf_wlan_radio_11ac_nss, tvb, 0, 0,
phdr->phy_info.info_11ac.nss[i]);
proto_tree_add_uint(user_tree, hf_wlan_radio_11ac_nsts, tvb, 0, 0,
nsts);
proto_tree_add_uint(user_tree, hf_wlan_radio_11ac_fec, tvb, 0, 0,
(phdr->phy_info.info_11ac.fec >> i) & 0x01);
/*
* If we can calculate the data rate for this user, do so.
*/
if (can_calculate_rate && phdr->phy_info.info_11ac.mcs[i] <= MAX_MCS_VHT_INDEX) {
data_rate = ieee80211_vhtinfo[phdr->phy_info.info_11ac.mcs[i]].rates[bandwidth][phdr->phy_info.info_11ac.short_gi] * phdr->phy_info.info_11ac.nss[i];
if (data_rate != 0.0f) {
proto_tree_add_float_format_value(user_tree, hf_wlan_radio_data_rate, tvb, 0, 0,
data_rate,
"%.1f Mb/s",
data_rate);
}
}
}
}
if (phdr->phy_info.info_11ac.presence_flags & PHDR_802_11AC_HAS_GROUP_ID) {
proto_tree_add_uint(radio_tree, hf_wlan_radio_11ac_gid, tvb, 0, 0,
phdr->phy_info.info_11ac.group_id);
}
if (phdr->phy_info.info_11ac.presence_flags & PHDR_802_11AC_HAS_PARTIAL_AID) {
proto_tree_add_uint(radio_tree, hf_wlan_radio_11ac_p_aid, tvb, 0, 0,
phdr->phy_info.info_11ac.partial_aid);
}
}
break;
}
}
if (have_data_rate) {
col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%.1f", data_rate);
proto_tree_add_float_format_value(radio_tree, hf_wlan_radio_data_rate, tvb, 0, 0,
data_rate,
"%.1f Mb/s",
@ -801,8 +1008,8 @@ static hf_register_info hf_wlan_radio[] = {
{"Greenfield", "wlan_radio.11n.greenfield", FT_BOOLEAN, BASE_NONE, NULL, 0,
NULL, HFILL }},
{&hf_wlan_radio_11n_ldpc,
{"FEC is LDPC", "wlan_radio.11n.ldpc", FT_BOOLEAN, BASE_NONE, NULL, 0,
{&hf_wlan_radio_11n_fec,
{"FEC", "wlan_radio.11n.fec", FT_UINT32, BASE_DEC, VALS(fec_vals), 0,
NULL, HFILL }},
{&hf_wlan_radio_11n_stbc_streams,
@ -813,24 +1020,68 @@ static hf_register_info hf_wlan_radio[] = {
{"Number of extension spatial streams", "wlan_radio.11n.ness", FT_UINT32, BASE_DEC, NULL, 0,
NULL, HFILL }},
{&hf_wlan_radio_11ac_mcs_index,
{"MCS index", "wlan_radio.11ac.mcs_index", FT_UINT32, BASE_DEC, NULL, 0,
{&hf_wlan_radio_11ac_stbc,
{"STBC", "wlan_radio.11ac.stbc", FT_BOOLEAN, 0, TFS(&tfs_on_off), 0x0,
"Space Time Block Coding flag", HFILL }},
{&hf_wlan_radio_11ac_txop_ps_not_allowed,
{"TXOP_PS_NOT_ALLOWED", "wlan_radio_11ac.txop_ps_not_allowed", FT_BOOLEAN, 0, NULL, 0x0,
"Flag indicating whether STAs may doze during TXOP", HFILL }},
{&hf_wlan_radio_11ac_short_gi,
{"Short GI", "wlan_radio.11ac.short_gi", FT_BOOLEAN, 0, NULL, 0,
NULL, HFILL }},
{&hf_wlan_radio_11ac_short_gi_nsym_disambig,
{"Short GI Nsym disambiguation", "wlan_radio.11ac.short_gi_nsym_disambig", FT_BOOLEAN, 0, NULL, 0x0,
"Short Guard Interval Nsym disambiguation", HFILL }},
{&hf_wlan_radio_11ac_ldpc_extra_ofdm_symbol,
{"LDPC extra OFDM symbol", "wlan_radio.11ac.ldpc_extra_ofdm_symbol", FT_BOOLEAN, 0, NULL, 0x0,
NULL, HFILL }},
{&hf_wlan_radio_11ac_beamformed,
{"Beamformed", "wlan_radio.11ac.beamformed", FT_BOOLEAN, 0, NULL, 0x0,
NULL, HFILL }},
{&hf_wlan_radio_11ac_bandwidth,
{"Bandwidth", "wlan_radio.11ac.bandwidth", FT_UINT32, BASE_DEC, VALS(bandwidth_vals), 0,
NULL, HFILL }},
{&hf_wlan_radio_11ac_short_gi,
{"Short GI", "wlan_radio.11ac.short_gi", FT_BOOLEAN, 0, NULL, 0,
{&hf_wlan_radio_11ac_user,
{"User", "wlan_radio.11ac.user", FT_NONE, BASE_NONE, NULL, 0x0,
NULL, HFILL }},
{&hf_wlan_radio_11ac_nsts,
{"Space-time streams", "wlan_radio.11ac.nsts", FT_UINT32, BASE_DEC, NULL, 0x0,
"Number of Space-time streams", HFILL }},
{&hf_wlan_radio_11ac_mcs,
{"MCS index", "wlan_radio.11ac.mcs", FT_UINT32, BASE_DEC, NULL, 0x0,
"MCS index", HFILL }},
{&hf_wlan_radio_11ac_nss,
{"Spatial streams", "wlan_radio.11ac.nss", FT_UINT32, BASE_DEC, NULL, 0x0,
"Number of spatial streams", HFILL }},
{&hf_wlan_radio_11ac_fec,
{"FEC", "wlan_radio.11ac.fec", FT_UINT32, BASE_DEC, VALS(fec_vals), 0x0,
"Type of FEC", HFILL }},
{&hf_wlan_radio_11ac_gid,
{"Group Id", "wlan_radio.11ac.gid", FT_UINT32, BASE_DEC, NULL, 0x0,
NULL, HFILL }},
{&hf_wlan_radio_11ac_p_aid,
{"Partial AID", "wlan_radio.11ac.paid", FT_UINT16, BASE_DEC, NULL, 0x0,
NULL, HFILL }},
{&hf_wlan_radio_data_rate,
{"Data rate", "wlan_radio.data_rate", FT_FLOAT, BASE_NONE, NULL, 0,
"Data rate (bits/s)", HFILL }},
"Speed at which this frame was sent/received", HFILL }},
{&hf_wlan_radio_channel,
{"Channel", "wlan_radio.channel", FT_UINT8, BASE_DEC, NULL, 0,
{"Channel", "wlan_radio.channel", FT_UINT32, BASE_DEC, NULL, 0,
"802.11 channel number that this frame was sent/received on", HFILL }},
{&hf_wlan_radio_frequency,
@ -842,7 +1093,7 @@ static hf_register_info hf_wlan_radio[] = {
NULL, HFILL }},
{&hf_wlan_radio_signal_percent,
{"Signal strength (percentage)", "wlan_radio.signal_dbm", FT_UINT8, BASE_DEC, NULL, 0,
{"Signal strength (percentage)", "wlan_radio.signal_dbm", FT_UINT32, BASE_DEC, NULL, 0,
"Signal strength, as percentage of maximum RSSI", HFILL }},
{&hf_wlan_radio_signal_dbm,
@ -850,7 +1101,7 @@ static hf_register_info hf_wlan_radio[] = {
NULL, HFILL }},
{&hf_wlan_radio_noise_percent,
{"Noise level (percentage)", "wlan_radio.noise_percentage", FT_UINT8, BASE_DEC, NULL, 0,
{"Noise level (percentage)", "wlan_radio.noise_percentage", FT_UINT32, BASE_DEC, NULL, 0,
NULL, HFILL }},
{&hf_wlan_radio_noise_dbm,
@ -863,7 +1114,8 @@ static hf_register_info hf_wlan_radio[] = {
};
static gint *tree_array[] = {
&ett_wlan_radio
&ett_wlan_radio,
&ett_wlan_radio_11ac_user
};
void proto_register_ieee80211_radio(void)

View File

@ -1357,8 +1357,8 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
phdr.phy_info.info_11n.greenfield = (mcs_flags & IEEE80211_RADIOTAP_MCS_FMT_GF) != 0;
}
if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_FEC) {
phdr.phy_info.info_11n.presence_flags |= PHDR_802_11N_HAS_LDPC;
phdr.phy_info.info_11n.ldpc = (mcs_flags & IEEE80211_RADIOTAP_MCS_FEC_LDPC) != 0;
phdr.phy_info.info_11n.presence_flags |= PHDR_802_11N_HAS_FEC;
phdr.phy_info.info_11n.fec = (mcs_flags & IEEE80211_RADIOTAP_MCS_FEC_LDPC) ? 1 : 0;
}
if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_STBC) {
phdr.phy_info.info_11n.presence_flags |= PHDR_802_11N_HAS_STBC_STREAMS;
@ -1529,7 +1529,6 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
phdr.phy_info.info_11ac.presence_flags = 0;
}
vht_flags = tvb_get_guint8(tvb, offset + 2);
if (tree) {
it_root = proto_tree_add_item(radiotap_tree, hf_radiotap_vht,
tvb, offset, 12, ENC_NA);
@ -1559,12 +1558,16 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
}
if (known & IEEE80211_RADIOTAP_VHT_HAVE_STBC) {
phdr.phy_info.info_11ac.presence_flags |= PHDR_802_11AC_HAS_STBC;
phdr.phy_info.info_11ac.stbc = (vht_flags & IEEE80211_RADIOTAP_VHT_STBC) != 0;
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) {
phdr.phy_info.info_11ac.presence_flags |= PHDR_802_11AC_HAS_TXOP_PS_NOT_ALLOWED;
phdr.phy_info.info_11ac.txop_ps_not_allowed = (vht_flags & IEEE80211_RADIOTAP_VHT_TXOP_PS) != 0;
if (vht_tree)
proto_tree_add_item(vht_tree, hf_radiotap_vht_txop_ps,
tvb, offset + 2, 1, ENC_LITTLE_ENDIAN);
@ -1573,7 +1576,7 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
if (known & IEEE80211_RADIOTAP_VHT_HAVE_GI) {
gi_length = (vht_flags & IEEE80211_RADIOTAP_VHT_SGI) ? 1 : 0;
phdr.phy_info.info_11ac.presence_flags |= PHDR_802_11AC_HAS_SHORT_GI;
phdr.phy_info.info_11ac.short_gi = (gi_length == 0);
phdr.phy_info.info_11ac.short_gi = gi_length;
if (vht_tree) {
proto_tree_add_item(vht_tree, hf_radiotap_vht_gi,
tvb, offset + 2, 1, ENC_LITTLE_ENDIAN);
@ -1583,6 +1586,8 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
}
if (known & IEEE80211_RADIOTAP_VHT_HAVE_SGI_NSYM_DA) {
phdr.phy_info.info_11ac.presence_flags |= PHDR_802_11AC_HAS_SHORT_GI_NSYM_DISAMBIG;
phdr.phy_info.info_11ac.short_gi_nsym_disambig = (vht_flags & IEEE80211_RADIOTAP_VHT_SGI_NSYM_DA) != 0;
if (vht_tree) {
it = proto_tree_add_item(vht_tree, hf_radiotap_vht_sgi_nsym_da,
tvb, offset + 2, 1, ENC_LITTLE_ENDIAN);
@ -1594,6 +1599,8 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
}
if (known & IEEE80211_RADIOTAP_VHT_HAVE_LDPC_EXTRA) {
phdr.phy_info.info_11ac.presence_flags |= PHDR_802_11AC_HAS_LDPC_EXTRA_OFDM_SYMBOL;
phdr.phy_info.info_11ac.ldpc_extra_ofdm_symbol = (vht_flags & IEEE80211_RADIOTAP_VHT_LDPC_EXTRA) != 0;
if (vht_tree) {
proto_tree_add_item(vht_tree, hf_radiotap_vht_ldpc_extra,
tvb, offset + 2, 1, ENC_LITTLE_ENDIAN);
@ -1601,6 +1608,8 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
}
if (known & IEEE80211_RADIOTAP_VHT_HAVE_BF) {
phdr.phy_info.info_11ac.presence_flags |= PHDR_802_11AC_HAS_BEAMFORMED;
phdr.phy_info.info_11ac.beamformed = (vht_flags & IEEE80211_RADIOTAP_VHT_BF) != 0;
if (vht_tree)
proto_tree_add_item(vht_tree, hf_radiotap_vht_bf,
tvb, offset + 2, 1, ENC_LITTLE_ENDIAN);
@ -1626,6 +1635,8 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
mcs_nss = tvb_get_guint8(tvb, offset + 4 + i);
nss = (mcs_nss & IEEE80211_RADIOTAP_VHT_NSS);
mcs = (mcs_nss & IEEE80211_RADIOTAP_VHT_MCS) >> 4;
phdr.phy_info.info_11ac.mcs[i] = mcs;
phdr.phy_info.info_11ac.nss[i] = nss;
if ((known & IEEE80211_RADIOTAP_VHT_HAVE_STBC) && (vht_flags & IEEE80211_RADIOTAP_VHT_STBC))
nsts = 2 * nss;
@ -1670,14 +1681,19 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
}
}
}
phdr.phy_info.info_11ac.fec = tvb_get_guint8(tvb, offset + 8);
if (known & IEEE80211_RADIOTAP_VHT_HAVE_GID) {
phdr.phy_info.info_11ac.presence_flags |= PHDR_802_11AC_HAS_GROUP_ID;
phdr.phy_info.info_11ac.group_id = tvb_get_guint8(tvb, offset + 9);
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) {
phdr.phy_info.info_11ac.presence_flags |= PHDR_802_11AC_HAS_PARTIAL_AID;
phdr.phy_info.info_11ac.partial_aid = tvb_get_letohs(tvb, offset + 10);
if (vht_tree) {
proto_tree_add_item(vht_tree, hf_radiotap_vht_p_aid,
tvb, offset+10, 2, ENC_LITTLE_ENDIAN);

View File

@ -728,9 +728,7 @@ wlantap_dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree
if (vw_rflags & FLAGS_CHAN_VHT) {
phdr.phy = PHDR_802_11_PHY_11AC;
phdr.phy_info.info_11ac.presence_flags =
PHDR_802_11AC_HAS_MCS_INDEX |
PHDR_802_11AC_HAS_SHORT_GI;
phdr.phy_info.info_11ac.mcs_index = mcs_index;
phdr.phy_info.info_11ac.short_gi = ((vw_rflags & FLAGS_CHAN_SHORTGI) != 0);
} else {
phdr.phy = PHDR_802_11_PHY_11N;

View File

@ -473,8 +473,6 @@ dissect_peekremote_new(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void
extflags = tvb_get_ntohl(tvb, offset);
if (extflags & EXT_FLAG_802_11ac) {
phdr.phy = PHDR_802_11_PHY_11AC;
phdr.phy_info.info_11ac.presence_flags = PHDR_802_11AC_HAS_MCS_INDEX;
phdr.phy_info.info_11ac.mcs_index = mcs_index;
} else {
phdr.phy = PHDR_802_11_PHY_11N;
phdr.phy_info.info_11n.presence_flags = PHDR_802_11N_HAS_MCS_INDEX;

View File

@ -739,11 +739,12 @@ peektagged_read_packet(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
case WTAP_ENCAP_IEEE_802_11_WITH_RADIO:
if (saw_data_rate_or_mcs_index) {
if (ext_flags & EXT_FLAG_MCS_INDEX_USED) {
/* It's an MCS index. */
if (ext_flags & EXT_FLAG_802_11ac) {
ieee_802_11.phy_info.info_11ac.presence_flags |= PHDR_802_11AC_HAS_MCS_INDEX;
ieee_802_11.phy_info.info_11ac.mcs_index = data_rate_or_mcs_index;
} else {
/*
* It's an MCS index.
*
* XXX - what about 11ac?
*/
if (!(ext_flags & EXT_FLAG_802_11ac)) {
ieee_802_11.phy_info.info_11n.presence_flags |= PHDR_802_11N_HAS_MCS_INDEX;
ieee_802_11.phy_info.info_11n.mcs_index = data_rate_or_mcs_index;
}

View File

@ -633,7 +633,7 @@ struct ieee_802_11n { /* 802.11n */
guint bandwidth; /* Bandwidth = 20 MHz, 40 MHz, etc. */
guint short_gi:1; /* True for short guard interval */
guint greenfield:1; /* True for greenfield, short for mixed */
guint ldpc:1; /* True for LDPC FEC */
guint fec:1; /* FEC: 0 = BCC, 1 = LDPC */
guint stbc_streams:2; /* Number of STBC streams */
guint ness; /* Number of extension spatial streams */
};
@ -645,7 +645,7 @@ struct ieee_802_11n { /* 802.11n */
#define PHDR_802_11N_HAS_BANDWIDTH 0x00000002 /* bandwidth */
#define PHDR_802_11N_HAS_SHORT_GI 0x00000004 /* short_gi */
#define PHDR_802_11N_HAS_GREENFIELD 0x00000008 /* greenfield */
#define PHDR_802_11N_HAS_LDPC 0x00000010 /* ldpc */
#define PHDR_802_11N_HAS_FEC 0x00000010 /* fec */
#define PHDR_802_11N_HAS_STBC_STREAMS 0x00000020 /* stbc_streams */
#define PHDR_802_11N_HAS_NESS 0x00000040 /* ness */
@ -679,17 +679,32 @@ struct ieee_802_11n { /* 802.11n */
struct ieee_802_11ac { /* 802.11ac */
guint32 presence_flags; /* Which of this information is present? */
guint16 mcs_index; /* MCS index */
guint bandwidth; /* Bandwidth = 20 MHz, 40 MHz, etc. */
guint stbc:1; /* 1 if all spatial streams have STBC */
guint txop_ps_not_allowed:1;
guint short_gi:1; /* True for short guard interval */
guint short_gi_nsym_disambig:1;
guint ldpc_extra_ofdm_symbol:1;
guint beamformed:1;
guint8 bandwidth; /* Bandwidth = 20 MHz, 40 MHz, etc. */
guint8 mcs[4]; /* MCS index per user */
guint8 nss[4]; /* NSS per user */
guint8 fec; /* Bit array of FEC per user: 0 = BCC, 1 = LDPC */
guint8 group_id;
guint8 partial_aid;
};
/*
* Presence flags for 802.11ac.
*/
#define PHDR_802_11AC_HAS_MCS_INDEX 0x00000001 /* mcs */
#define PHDR_802_11AC_HAS_BANDWIDTH 0x00000002 /* bandwidth */
#define PHDR_802_11AC_HAS_SHORT_GI 0x00000004 /* short_gi */
#define PHDR_802_11AC_HAS_STBC 0x00000001 /* stbc */
#define PHDR_802_11AC_HAS_TXOP_PS_NOT_ALLOWED 0x00000002 /* txop_ps_not_allowed */
#define PHDR_802_11AC_HAS_SHORT_GI 0x00000004 /* short_gi */
#define PHDR_802_11AC_HAS_SHORT_GI_NSYM_DISAMBIG 0x00000008 /* short_gi_nsym_disambig */
#define PHDR_802_11AC_HAS_LDPC_EXTRA_OFDM_SYMBOL 0x00000010 /* ldpc_extra_ofdm_symbol */
#define PHDR_802_11AC_HAS_BEAMFORMED 0x00000020 /* beamformed */
#define PHDR_802_11AC_HAS_BANDWIDTH 0x00000040 /* bandwidth */
#define PHDR_802_11AC_HAS_GROUP_ID 0x00000080 /* group_id */
#define PHDR_802_11AC_HAS_PARTIAL_AID 0x00000100 /* partial_aid */
struct ieee_802_11_phdr {
gint fcs_len; /* Number of bytes of FCS - -1 means "unknown" */