summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Barber <simon.barber@meraki.net>2016-01-06 17:23:00 -0800
committerMichael Mann <mmann78@netscape.net>2017-04-30 13:22:50 +0000
commitbb83fe45519eb280e6545ad69868e4e7f5fbef93 (patch)
tree997f88afebd94c1cd60ea22b28b1341e324b2c52
parent7f2c6e13001bed11ae113b0aca47e562735d6e26 (diff)
downloadwireshark-bb83fe45519eb280e6545ad69868e4e7f5fbef93.tar.gz
packet-ieee80211-radio.c: Minor refactor and whitespace cleanup
Change-Id: Idad8f7eeed968eeed9f553fef98d58453f328afb Reviewed-on: https://code.wireshark.org/review/21421 Petri-Dish: Michael Mann <mmann78@netscape.net> Reviewed-by: Michael Mann <mmann78@netscape.net> Tested-by: Michael Mann <mmann78@netscape.net>
-rw-r--r--epan/dissectors/packet-ieee80211-radio.c622
-rw-r--r--wiretap/wtap.h20
2 files changed, 317 insertions, 325 deletions
diff --git a/epan/dissectors/packet-ieee80211-radio.c b/epan/dissectors/packet-ieee80211-radio.c
index 5b847b38e5..ebe72fea5b 100644
--- a/epan/dissectors/packet-ieee80211-radio.c
+++ b/epan/dissectors/packet-ieee80211-radio.c
@@ -175,30 +175,30 @@ static const value_string fec_vals[] = {
* Note: MCS 32 is special - only valid for 40Mhz channel.
*/
WS_DLL_PUBLIC_DEF const guint16 ieee80211_ht_Dbps[MAX_MCS_INDEX+1] = {
- /* MCS 0 - 1 stream */
- 26, 52, 78, 104, 156, 208, 234, 260,
+ /* MCS 0 - 1 stream */
+ 26, 52, 78, 104, 156, 208, 234, 260,
- /* MCS 8 - 2 stream */
- 52, 104, 156, 208, 312, 416, 468, 520,
+ /* MCS 8 - 2 stream */
+ 52, 104, 156, 208, 312, 416, 468, 520,
- /* MCS 16 - 3 stream */
- 78, 156, 234, 312, 468, 624, 702, 780,
+ /* MCS 16 - 3 stream */
+ 78, 156, 234, 312, 468, 624, 702, 780,
- /* MCS 24 - 4 stream */
- 104, 208, 312, 416, 624, 832, 936, 1040,
+ /* MCS 24 - 4 stream */
+ 104, 208, 312, 416, 624, 832, 936, 1040,
- /* MCS 32 - 1 stream */
- 12, /* only valid for 40Mhz - 11a/g DUP mode */
+ /* MCS 32 - 1 stream */
+ 12, /* only valid for 40Mhz - 11a/g DUP mode */
- /* MCS 33 - 2 stream */
- 156, 208, 260, 234, 312, 390,
+ /* MCS 33 - 2 stream */
+ 156, 208, 260, 234, 312, 390,
- /* MCS 39 - 3 stream */
- 208, 260, 260, 312, 364, 364, 416, 312, 390, 390, 468, 546, 546, 624,
+ /* MCS 39 - 3 stream */
+ 208, 260, 260, 312, 364, 364, 416, 312, 390, 390, 468, 546, 546, 624,
- /* MCS 53 - 4 stream */
- 260, 312, 364, 312, 364, 416, 468, 416, 468, 520, 520, 572,
- 390, 468, 546, 468, 546, 624, 702, 624, 702, 780, 780, 858
+ /* MCS 53 - 4 stream */
+ 260, 312, 364, 312, 364, 416, 468, 416, 468, 520, 520, 572,
+ 390, 468, 546, 468, 546, 624, 702, 624, 702, 780, 780, 858
};
/*
@@ -379,12 +379,15 @@ static void
dissect_wlan_radio_phdr (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void *data)
{
struct ieee_802_11_phdr *phdr = (struct ieee_802_11_phdr *)data;
- proto_item *ti = NULL;
- proto_tree *radio_tree = NULL;
+ proto_item *ti;
+ proto_tree *radio_tree;
float data_rate = 0.0f;
gboolean have_data_rate = FALSE;
gboolean has_short_preamble = FALSE;
gboolean short_preamble = 1;
+ guint bandwidth = 0;
+ gboolean can_calculate_rate = FALSE;
+ proto_item *p_item;
guint frame_length = tvb_reported_length(tvb); /* length of 802.11 frame data */
@@ -392,6 +395,9 @@ dissect_wlan_radio_phdr (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
guint preamble = 0; /* duration of plcp */
guint duration = 0; /* duration of whole frame (plcp + mac data + any trailing parts) */
+ int phy = phdr->phy;
+ union ieee_802_11_phy_info *phy_info = &phdr->phy_info;
+
col_set_str(pinfo->cinfo, COL_PROTOCOL, "Radio");
col_clear(pinfo->cinfo, COL_INFO);
@@ -407,19 +413,17 @@ dissect_wlan_radio_phdr (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
col_add_fstr(pinfo->cinfo, COL_RSSI, "%u%%", phdr->signal_percent);
}
- if (tree) {
- ti = proto_tree_add_item(tree, proto_wlan_radio, tvb, 0, 0, ENC_NA);
- radio_tree = proto_item_add_subtree (ti, ett_wlan_radio);
+ ti = proto_tree_add_item(tree, proto_wlan_radio, tvb, 0, 0, ENC_NA);
+ radio_tree = proto_item_add_subtree (ti, ett_wlan_radio);
- if (phdr->phy != PHDR_802_11_PHY_UNKNOWN) {
- proto_tree_add_uint(radio_tree, hf_wlan_radio_phy, tvb, 0, 0,
- phdr->phy);
+ if (phy != PHDR_802_11_PHY_UNKNOWN) {
+ proto_tree_add_uint(radio_tree, hf_wlan_radio_phy, tvb, 0, 0, phy);
- switch (phdr->phy) {
+ switch (phy) {
case PHDR_802_11_PHY_11_FHSS:
{
- struct ieee_802_11_fhss *info_fhss = &phdr->phy_info.info_11_fhss;
+ struct ieee_802_11_fhss *info_fhss = &phy_info->info_11_fhss;
if (info_fhss->has_hop_set) {
proto_tree_add_uint(radio_tree, hf_wlan_radio_11_fhss_hop_set, tvb, 0, 0,
@@ -438,7 +442,7 @@ dissect_wlan_radio_phdr (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
case PHDR_802_11_PHY_11B:
{
- struct ieee_802_11b *info_b = &phdr->phy_info.info_11b;
+ struct ieee_802_11b *info_b = &phy_info->info_11b;
has_short_preamble = info_b->has_short_preamble;
short_preamble = info_b->short_preamble;
@@ -452,7 +456,7 @@ dissect_wlan_radio_phdr (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
case PHDR_802_11_PHY_11A:
{
- struct ieee_802_11a *info_a = &phdr->phy_info.info_11a;
+ struct ieee_802_11a *info_a = &phy_info->info_11a;
if (info_a->has_channel_type) {
proto_tree_add_uint(radio_tree, hf_wlan_radio_11a_channel_type, tvb, 0, 0,
@@ -467,7 +471,7 @@ dissect_wlan_radio_phdr (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
case PHDR_802_11_PHY_11G:
{
- struct ieee_802_11g *info_g = &phdr->phy_info.info_11g;
+ struct ieee_802_11g *info_g = &phy_info->info_11g;
has_short_preamble = info_g->has_short_preamble;
short_preamble = info_g->short_preamble;
@@ -485,9 +489,23 @@ dissect_wlan_radio_phdr (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
case PHDR_802_11_PHY_11N:
{
- struct ieee_802_11n *info_n = &phdr->phy_info.info_11n;
+ struct ieee_802_11n *info_n = &phy_info->info_11n;
guint bandwidth_40;
+ /*
+ * If we have all the fields needed to look up the data rate,
+ * do so.
+ */
+ if (info_n->has_mcs_index &&
+ info_n->has_bandwidth &&
+ info_n->has_short_gi) {
+ bandwidth_40 = (info_n->bandwidth == PHDR_802_11_BANDWIDTH_40_MHZ) ? 1 : 0;
+ if (info_n->mcs_index < MAX_MCS_INDEX) {
+ data_rate = ieee80211_htrate(info_n->mcs_index, bandwidth_40, info_n->short_gi);
+ have_data_rate = TRUE;
+ }
+ }
+
if (info_n->has_mcs_index) {
proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_mcs_index, tvb, 0, 0,
info_n->mcs_index);
@@ -522,32 +540,44 @@ dissect_wlan_radio_phdr (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_ness, tvb, 0, 0,
info_n->ness);
}
-
- /*
- * If we have all the fields needed to look up the data rate,
- * do so.
- */
- if (info_n->has_mcs_index &&
- info_n->has_bandwidth &&
- info_n->has_short_gi) {
- bandwidth_40 =
- (info_n->bandwidth == PHDR_802_11_BANDWIDTH_40_MHZ) ?
- 1 : 0;
- if (info_n->mcs_index <= MAX_MCS_INDEX) {
- data_rate = ieee80211_htrate(info_n->mcs_index, bandwidth_40, info_n->short_gi);
- have_data_rate = TRUE;
- }
- }
}
break;
case PHDR_802_11_PHY_11AC:
{
- struct ieee_802_11ac *info_ac = &phdr->phy_info.info_11ac;
- gboolean can_calculate_rate;
- guint bandwidth = 0;
+ struct ieee_802_11ac *info_ac = &phy_info->info_11ac;
guint i;
+ if (info_ac->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, info_ac->short_gi);
+ } else {
+ can_calculate_rate = FALSE; /* unknown GI length */
+ }
+
+ if (info_ac->has_bandwidth) {
+ proto_tree_add_uint(radio_tree, hf_wlan_radio_11ac_bandwidth, tvb, 0, 0, info_ac->bandwidth);
+ if (info_ac->bandwidth < G_N_ELEMENTS(ieee80211_vht_bw2rate_index))
+ bandwidth = ieee80211_vht_bw2rate_index[info_ac->bandwidth];
+ else
+ can_calculate_rate = FALSE; /* unknown bandwidth */
+ } else {
+ can_calculate_rate = FALSE; /* no bandwidth */
+ }
+
+ for (i = 0; i < 4; i++) {
+
+ if (info_ac->nss[i] != 0) {
+ /*
+ * If we can calculate the data rate for this user, do so.
+ */
+ if (can_calculate_rate && info_ac->mcs[i] <= MAX_MCS_VHT_INDEX) {
+ data_rate = ieee80211_vhtrate(info_ac->mcs[i], bandwidth, info_ac->short_gi) * info_ac->nss[i];
+ have_data_rate = TRUE;
+ }
+ }
+ }
+
if (info_ac->has_stbc) {
proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_stbc, tvb, 0, 0,
info_ac->stbc);
@@ -558,14 +588,6 @@ dissect_wlan_radio_phdr (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
info_ac->txop_ps_not_allowed);
}
- if (info_ac->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,
- info_ac->short_gi);
- } else {
- can_calculate_rate = FALSE; /* unknown GI length */
- }
-
if (info_ac->has_short_gi_nsym_disambig) {
proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_short_gi_nsym_disambig, tvb, 0, 0,
info_ac->short_gi_nsym_disambig);
@@ -581,17 +603,6 @@ dissect_wlan_radio_phdr (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
info_ac->beamformed);
}
- if (info_ac->has_bandwidth) {
- if (info_ac->bandwidth < G_N_ELEMENTS(ieee80211_vht_bw2rate_index))
- bandwidth = ieee80211_vht_bw2rate_index[info_ac->bandwidth];
- else
- can_calculate_rate = FALSE; /* unknown bandwidth */
- proto_tree_add_uint(radio_tree, hf_wlan_radio_11ac_bandwidth, tvb, 0, 0,
- info_ac->bandwidth);
- } else {
- can_calculate_rate = FALSE; /* no bandwidth */
- }
-
for (i = 0; i < 4; i++) {
if (info_ac->nss[i] != 0) {
@@ -661,267 +672,249 @@ dissect_wlan_radio_phdr (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
}
}
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,
+ 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",
data_rate);
- }
+ }
- if (phdr->has_channel) {
- col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%u", phdr->channel);
- proto_tree_add_uint(radio_tree, hf_wlan_radio_channel, tvb, 0, 0,
- phdr->channel);
- }
+ if (phdr->has_channel) {
+ col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%u", phdr->channel);
+ proto_tree_add_uint(radio_tree, hf_wlan_radio_channel, tvb, 0, 0, phdr->channel);
+ }
- if (phdr->has_frequency) {
- col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%u MHz", phdr->frequency);
- proto_tree_add_uint_format_value(radio_tree, hf_wlan_radio_frequency, tvb, 0, 0,
- phdr->frequency,
- "%u MHz",
- phdr->frequency);
- }
+ if (phdr->has_frequency) {
+ col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%u MHz", phdr->frequency);
+ proto_tree_add_uint(radio_tree, hf_wlan_radio_frequency, tvb, 0, 0, phdr->frequency);
+ }
- if (phdr->has_signal_percent) {
- col_add_fstr(pinfo->cinfo, COL_RSSI, "%u%%", phdr->signal_percent);
- proto_tree_add_uint(radio_tree, hf_wlan_radio_signal_percent, tvb, 0, 0, phdr->signal_percent);
- }
+ if (phdr->has_signal_percent) {
+ col_add_fstr(pinfo->cinfo, COL_RSSI, "%u%%", phdr->signal_percent);
+ proto_tree_add_uint(radio_tree, hf_wlan_radio_signal_percent, tvb, 0, 0, phdr->signal_percent);
+ }
- if (phdr->has_signal_dbm) {
- col_add_fstr(pinfo->cinfo, COL_RSSI, "%d dBm", phdr->signal_dbm);
- proto_tree_add_int(radio_tree, hf_wlan_radio_signal_dbm, tvb, 0, 0, phdr->signal_dbm);
- }
+ if (phdr->has_signal_dbm) {
+ col_add_fstr(pinfo->cinfo, COL_RSSI, "%d dBm", phdr->signal_dbm);
+ proto_tree_add_int(radio_tree, hf_wlan_radio_signal_dbm, tvb, 0, 0, phdr->signal_dbm);
+ }
- if (phdr->has_noise_percent) {
- proto_tree_add_uint(radio_tree, hf_wlan_radio_noise_percent, tvb, 0, 0, phdr->noise_percent);
- }
+ if (phdr->has_noise_percent) {
+ proto_tree_add_uint(radio_tree, hf_wlan_radio_noise_percent, tvb, 0, 0, phdr->noise_percent);
+ }
- if (phdr->has_noise_dbm) {
- proto_tree_add_int(radio_tree, hf_wlan_radio_noise_dbm, tvb, 0, 0, phdr->noise_dbm);
- }
+ if (phdr->has_noise_dbm) {
+ proto_tree_add_int(radio_tree, hf_wlan_radio_noise_dbm, tvb, 0, 0, phdr->noise_dbm);
+ }
- if (phdr->has_tsf_timestamp) {
- proto_tree_add_uint64(radio_tree, hf_wlan_radio_timestamp, tvb, 0, 0,
- phdr->tsf_timestamp);
- }
- if (phdr->has_aggregate_info) {
- proto_tree_add_boolean(radio_tree, hf_wlan_last_part_of_a_mpdu, tvb, 0, 0,
- (phdr->aggregate_flags & PHDR_802_11_LAST_PART_OF_A_MPDU) ?
- TRUE : FALSE);
- proto_tree_add_boolean(radio_tree, hf_wlan_a_mpdu_delim_crc_error, tvb, 0, 0,
- (phdr->aggregate_flags & PHDR_802_11_A_MPDU_DELIM_CRC_ERROR) ?
- TRUE : FALSE);
- proto_tree_add_uint(radio_tree, hf_wlan_a_mpdu_aggregate_id, tvb, 0, 0,
- phdr->aggregate_id);
+ if (phdr->has_tsf_timestamp) {
+ proto_tree_add_uint64(radio_tree, hf_wlan_radio_timestamp, tvb, 0, 0, phdr->tsf_timestamp);
+ }
+ if (phdr->has_aggregate_info) {
+ proto_tree_add_boolean(radio_tree, hf_wlan_last_part_of_a_mpdu, tvb, 0, 0, phdr->aggregate_flags);
+ proto_tree_add_boolean(radio_tree, hf_wlan_a_mpdu_delim_crc_error, tvb, 0, 0, phdr->aggregate_flags);
+ proto_tree_add_uint(radio_tree, hf_wlan_a_mpdu_aggregate_id, tvb, 0, 0, phdr->aggregate_id);
+ }
+
+ if (have_data_rate) {
+ /* duration calculations */
+ gboolean assumed_short_preamble = FALSE;
+ gboolean assumed_non_greenfield = FALSE;
+ gboolean assumed_no_stbc = FALSE;
+ gboolean assumed_no_extension_streams = FALSE;
+ gboolean assumed_bcc_fec = FALSE;
+
+ /* some generators report CCK frames as 'dynamic-cck-ofdm', which are converted
+ * into the 11g PHY type, so we need to be smart and recognize which ones are
+ * DSSS/CCK and which are OFDM. Use the data_rate to do this. */
+ if (phy == PHDR_802_11_PHY_11G &&
+ (data_rate == 1.0f || data_rate == 2.0f ||
+ data_rate == 5.5f || data_rate == 11.0f ||
+ data_rate == 22.0f || data_rate == 33.0f)) {
+ phy = PHDR_802_11_PHY_11B;
}
- if (have_data_rate) {
- gboolean assumed_short_preamble = FALSE;
- gboolean assumed_non_greenfield = FALSE;
- gboolean assumed_no_stbc = FALSE;
- gboolean assumed_no_extension_streams = FALSE;
- gboolean assumed_bcc_fec = FALSE;
-
- /* some generators report CCK frames as 'dynamic-cck-ofdm', which are converted
- * into the 11g PHY type, so we need to be smart and recognize which ones are
- * DSSS/CCK and which are OFDM. Use the data_rate to do this. */
- int phy = phdr->phy;
- if (phy == PHDR_802_11_PHY_11G &&
- (data_rate == 1.0f || data_rate == 2.0f ||
- data_rate == 5.5f || data_rate == 11.0f ||
- data_rate == 22.0f || data_rate == 33.0f)) {
- phy = PHDR_802_11_PHY_11B;
- }
+ switch (phy) {
- switch (phy) {
+ case PHDR_802_11_PHY_11_FHSS:
+ /* TODO: preamble/duration calc for FHSS */
+ break;
- case PHDR_802_11_PHY_11_FHSS:
- break;
-
- case PHDR_802_11_PHY_11B:
- if (!has_short_preamble || wlan_radio_always_short_preamble) {
- assumed_short_preamble = TRUE;
- short_preamble = TRUE;
- }
- preamble = short_preamble ? 72 + 24 : 144 + 48;
+ case PHDR_802_11_PHY_11B:
+ if (!has_short_preamble || wlan_radio_always_short_preamble) {
+ assumed_short_preamble = TRUE;
+ short_preamble = TRUE;
+ }
+ preamble = short_preamble ? 72 + 24 : 144 + 48;
+
+ /* calculation of frame duration
+ * Things we need to know to calculate accurate duration
+ * 802.11 / 802.11b (DSSS or CCK modulation)
+ * - length of preamble
+ * - rate
+ */
+ /* round up to whole microseconds */
+ duration = (guint) ceil(preamble + frame_length * 8 / data_rate);
+ break;
+
+ case PHDR_802_11_PHY_11A:
+ case PHDR_802_11_PHY_11G:
+ {
+ /* OFDM rate */
+ /* calculation of frame duration
+ * Things we need to know to calculate accurate duration
+ * 802.11a / 802.11g (OFDM modulation)
+ * - rate
+ */
+
+ /* preamble + signal */
+ preamble = 16 + 4;
+
+ /* 16 service bits, data and 6 tail bits */
+ guint bits = 16 + 8 * frame_length + 6;
+ guint symbols = (guint) ceil(bits / (data_rate * 4));
+
+ duration = preamble + symbols * 4;
+ break;
+ }
- /* calculation of frame duration
- * Things we need to know to calculate accurate duration
- * 802.11 / 802.11b (DSSS or CCK modulation)
- * - length of preamble
- * - rate
- */
- /* round up to whole microseconds */
- duration = (guint) ceil(preamble + frame_length * 8 / data_rate);
+ case PHDR_802_11_PHY_11N:
+ {
+ struct ieee_802_11n *info_n = &phdr->phy_info.info_11n;
+
+ /* We have all the fields required to calculate the duration */
+ static const guint Nhtdltf[4] = {1, 2, 4, 4};
+ static const guint Nhteltf[4] = {0, 1, 2, 4};
+ guint Nsts;
+ guint stbc_streams;
+ guint ness;
+
+ /*
+ * If we don't have necessary fields, or if we have them but
+ * they have invalid values, then bail.
+ */
+ if (!info_n->has_mcs_index ||
+ info_n->mcs_index > MAX_MCS_INDEX ||
+ !info_n->has_bandwidth ||
+ !info_n->has_short_gi)
break;
- case PHDR_802_11_PHY_11A:
- case PHDR_802_11_PHY_11G:
- {
- /* OFDM rate */
- /* calculation of frame duration
- * Things we need to know to calculate accurate duration
- * 802.11a / 802.11g (OFDM modulation)
- * - rate
- */
-
- /* 16 service bits, data and 6 tail bits */
- guint bits = 16 + 8 * frame_length + 6;
- guint symbols = (guint) ceil(bits / (data_rate * 4));
+ /* calculation of frame duration
+ * Things we need to know to calculate accurate duration
+ * 802.11n / HT
+ * - whether frame preamble is mixed or greenfield, (assume mixed)
+ * - guard interval, 800ns or 400ns
+ * - bandwidth, 20Mhz or 40Mhz
+ * - MCS index - used with previous 2 to calculate rate
+ * - how many additional STBC streams are used (assume 0)
+ * - how many optional extension spatial streams are used (assume 0)
+ * - whether BCC or LDCP coding is used (assume BCC)
+ */
+
+ /* preamble duration
+ * see ieee802.11n-2009 Figure 20-1 - PPDU format
+ * for HT-mixed format
+ * L-STF 8us, L-LTF 8us, L-SIG 4us, HT-SIG 8us, HT_STF 4us
+ * for HT-greenfield
+ * HT-GF-STF 8us, HT-LTF1 8us, HT_SIG 8us
+ */
+ if (info_n->has_greenfield) {
+ preamble = info_n->greenfield ? 24 : 32;
+ } else {
+ preamble = 32;
+ assumed_non_greenfield = TRUE;
+ }
- /* preamble + signal */
- preamble = 16 + 4;
+ if (info_n->has_stbc_streams) {
+ stbc_streams = info_n->stbc_streams;
+ } else {
+ stbc_streams = 0;
+ assumed_no_stbc = TRUE;
+ }
- duration = preamble + symbols * 4;
- break;
+ if (info_n->has_ness) {
+ ness = info_n->ness;
+ if (ness >= G_N_ELEMENTS(Nhteltf)) {
+ /* Not valid */
+ break;
}
+ } else {
+ ness = 0;
+ assumed_no_extension_streams = TRUE;
+ }
- case PHDR_802_11_PHY_11N:
- {
- struct ieee_802_11n *info_n = &phdr->phy_info.info_11n;
- guint bandwidth_40;
-
- /* We have all the fields required to calculate the duration */
- static const guint Nhtdltf[4] = {1, 2, 4, 4};
- static const guint Nhteltf[4] = {0, 1, 2, 4};
- guint Nsts, bits, Mstbc, bits_per_symbol, symbols;
- guint stbc_streams;
- guint ness;
-
- /*
- * If we don't have necessary fields, or if we have them but
- * they have invalid values, then bail.
- */
- if (!info_n->has_mcs_index ||
- info_n->mcs_index > MAX_MCS_INDEX ||
- !info_n->has_bandwidth ||
- !info_n->has_short_gi)
- break;
-
- bandwidth_40 = info_n->bandwidth == PHDR_802_11_BANDWIDTH_40_MHZ;
-
- /* calculation of frame duration
- * Things we need to know to calculate accurate duration
- * 802.11n / HT
- * - whether frame preamble is mixed or greenfield, (assume mixed)
- * - guard interval, 800ns or 400ns
- * - bandwidth, 20Mhz or 40Mhz
- * - MCS index - used with previous 2 to calculate rate
- * - how many additional STBC streams are used (assume 0)
- * - how many optional extension spatial streams are used (assume 0)
- * - whether BCC or LDCP coding is used (assume BCC)
- */
-
- /* preamble duration
- * see ieee802.11n-2009 Figure 20-1 - PPDU format
- * for HT-mixed format
- * L-STF 8us, L-LTF 8us, L-SIG 4us, HT-SIG 8us, HT_STF 4us
- * for HT-greenfield
- * HT-GF-STF 8us, HT-LTF1 8us, HT_SIG 8us
- */
- if (info_n->has_greenfield) {
- preamble = info_n->greenfield ? 24 : 32;
- } else {
- preamble = 32;
- assumed_non_greenfield = TRUE;
- }
-
- if (info_n->has_stbc_streams) {
- stbc_streams = info_n->stbc_streams;
- } else {
- stbc_streams = 0;
- assumed_no_stbc = TRUE;
- }
-
- if (info_n->has_ness) {
- ness = info_n->ness;
- if (ness >= G_N_ELEMENTS(Nhteltf)) {
- /* Not valid */
- break;
- }
- } else {
- ness = 0;
- assumed_no_extension_streams = TRUE;
- }
+ /* calculate number of HT-LTF training symbols.
+ * see ieee80211n-2009 20.3.9.4.6 table 20-11 */
+ Nsts = ieee80211_ht_streams[info_n->mcs_index] + stbc_streams;
+ if (Nsts == 0 || Nsts - 1 >= G_N_ELEMENTS(Nhtdltf)) {
+ /* Not usable */
+ break;
+ }
+ preamble += 4 * (Nhtdltf[Nsts-1] + Nhteltf[ness]);
- /* calculate number of HT-LTF training symbols.
- * see ieee80211n-2009 20.3.9.4.6 table 20-11 */
- Nsts = ieee80211_ht_streams[info_n->mcs_index] + stbc_streams;
- if (Nsts == 0 || Nsts - 1 >= G_N_ELEMENTS(Nhtdltf)) {
- /* Not usable */
- break;
- }
- preamble += 4 * (Nhtdltf[Nsts-1] + Nhteltf[ness]);
+ if (info_n->has_stbc_streams) {
+ stbc_streams = info_n->stbc_streams;
+ } else {
+ stbc_streams = 0;
+ assumed_no_stbc = TRUE;
+ }
- if (!info_n->has_fec) {
- assumed_bcc_fec = TRUE;
- }
+ if (info_n->has_ness) {
+ ness = info_n->ness;
+ } else {
+ ness = 0;
+ assumed_no_extension_streams = TRUE;
+ }
- /* data field calculation */
- /* see ieee80211n-2009 20.3.11 (20-32) - for BCC FEC */
- /* TODO: handle LDPC FEC (info_n->fec == 1), it changes the rounding
- * Currently this is the same logic as BCC */
- bits = 8 * frame_length + 16 + ieee80211_ht_Nes[info_n->mcs_index] * 6;
- Mstbc = stbc_streams ? 2 : 1;
- bits_per_symbol = ieee80211_ht_Dbps[info_n->mcs_index] * (bandwidth_40 ? 2 : 1);
- symbols = bits / (bits_per_symbol * Mstbc);
-
- /* round up to whole symbols */
- if((bits % (bits_per_symbol * Mstbc)) > 0)
- symbols++;
-
- symbols *= Mstbc;
- duration = preamble + (symbols * (info_n->short_gi ? 36 : 40) + 5) / 10;
- break;
- }
+ /* calculate number of HT-LTF training symbols.
+ * see ieee80211n-2009 20.3.9.4.6 table 20-11 */
+ Nsts = ieee80211_ht_streams[info_n->mcs_index] + stbc_streams;
+ preamble += 4 * (Nhtdltf[Nsts-1] + Nhteltf[ness]);
- case PHDR_802_11_PHY_11AC:
- {
- struct ieee_802_11ac *info_ac = &phdr->phy_info.info_11ac;
- int bits, stbc;
+ if (!info_n->has_fec) {
+ assumed_bcc_fec = TRUE;
+ }
+ break;
+ }
- /* TODO: this is a crude quick hack, need proper calculation of bits/symbols/FEC/rounding/etc */
- if (info_ac->has_stbc) {
- stbc = info_ac->stbc;
- } else {
- stbc = 0;
- assumed_no_stbc = TRUE;
- }
+ case PHDR_802_11_PHY_11AC:
+ {
+ struct ieee_802_11ac *info_ac = &phy_info->info_11ac;
- preamble = 32 + 4 * info_ac->nss[0] * (stbc+1);
- bits = 8 * frame_length + 16;
- duration = (guint) (preamble + bits / data_rate);
- break;
- }
+ if (!info_ac->has_stbc) {
+ assumed_no_stbc = TRUE;
}
+ preamble = 32 + 4 * info_ac->nss[0] * (info_ac->has_stbc ? info_ac->stbc+1 : 1);
+ break;
+ }
+ }
if (duration) {
- proto_item *item = proto_tree_add_uint(radio_tree, hf_wlan_radio_duration, tvb, 0, 0, duration);
- PROTO_ITEM_SET_GENERATED(item);
-
- if (assumed_short_preamble)
- expert_add_info(pinfo, item, &ei_wlan_radio_assumed_short_preamble);
- if (assumed_non_greenfield)
- expert_add_info(pinfo, item, &ei_wlan_radio_assumed_non_greenfield);
- if (assumed_no_stbc)
- expert_add_info(pinfo, item, &ei_wlan_radio_assumed_no_stbc);
- if (assumed_no_extension_streams)
- expert_add_info(pinfo, item, &ei_wlan_radio_assumed_no_extension_streams);
- if (assumed_bcc_fec)
- expert_add_info(pinfo, item, &ei_wlan_radio_assumed_bcc_fec);
-
- if (preamble) {
- proto_tree *d_tree = proto_item_add_subtree(item, ett_wlan_radio_duration);
- proto_item *p_item = proto_tree_add_uint(d_tree, hf_wlan_radio_preamble, tvb, 0, 0, preamble);
- PROTO_ITEM_SET_GENERATED(p_item);
- }
+ proto_item *item = proto_tree_add_uint(radio_tree, hf_wlan_radio_duration, tvb, 0, 0, duration);
+ proto_tree *d_tree = proto_item_add_subtree(item, ett_wlan_radio_duration);
+ PROTO_ITEM_SET_GENERATED(item);
+
+ if (assumed_short_preamble)
+ expert_add_info(pinfo, item, &ei_wlan_radio_assumed_short_preamble);
+ if (assumed_non_greenfield)
+ expert_add_info(pinfo, item, &ei_wlan_radio_assumed_non_greenfield);
+ if (assumed_no_stbc)
+ expert_add_info(pinfo, item, &ei_wlan_radio_assumed_no_stbc);
+ if (assumed_no_extension_streams)
+ expert_add_info(pinfo, item, &ei_wlan_radio_assumed_no_extension_streams);
+ if (assumed_bcc_fec)
+ expert_add_info(pinfo, item, &ei_wlan_radio_assumed_bcc_fec);
+
+ if (preamble) {
+ p_item = proto_tree_add_uint(d_tree, hf_wlan_radio_preamble, tvb, 0, 0, preamble);
+ PROTO_ITEM_SET_GENERATED(p_item);
}
}
- } /* if (tree) */
+ } /* if (have_data_rate) */
}
/*
@@ -950,7 +943,9 @@ dissect_wlan_noqos_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree
return call_dissector_with_data(ieee80211_noqos_handle, tvb, pinfo, tree, data);
}
-static hf_register_info hf_wlan_radio[] = {
+void proto_register_ieee80211_radio(void)
+{
+ static hf_register_info hf_wlan_radio[] = {
{&hf_wlan_radio_phy,
{"PHY type", "wlan_radio.phy", FT_UINT32, BASE_DEC, VALS(phy_vals), 0,
NULL, HFILL }},
@@ -1100,11 +1095,11 @@ static hf_register_info hf_wlan_radio[] = {
NULL, HFILL }},
{&hf_wlan_last_part_of_a_mpdu,
- {"Last part of an A-MPDU", "wlan_radio.last_part_of_an_ampdu", FT_BOOLEAN, 0, NULL, 0,
+ {"Last part of an A-MPDU", "wlan_radio.last_part_of_an_ampdu", FT_BOOLEAN, 32, NULL, PHDR_802_11_LAST_PART_OF_A_MPDU,
"This is the last part of an A-MPDU", HFILL }},
{&hf_wlan_a_mpdu_delim_crc_error,
- {"A-MPDU delimiter CRC error", "wlan_radio.a_mpdu_delim_crc_error", FT_BOOLEAN, 0, NULL, 0,
+ {"A-MPDU delimiter CRC error", "wlan_radio.a_mpdu_delim_crc_error", FT_BOOLEAN, 32, NULL, PHDR_802_11_A_MPDU_DELIM_CRC_ERROR,
NULL, HFILL }},
{&hf_wlan_a_mpdu_aggregate_id,
@@ -1119,10 +1114,15 @@ static hf_register_info hf_wlan_radio[] = {
{&hf_wlan_radio_preamble,
{"Preamble", "wlan_radio.preamble", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, &units_microseconds, 0,
"Duration of the PLCP or preamble in microseconds, calculated from PHY data", HFILL }},
+ };
-};
+ static gint *ett[] = {
+ &ett_wlan_radio,
+ &ett_wlan_radio_11ac_user,
+ &ett_wlan_radio_duration,
+ };
-static ei_register_info ei[] = {
+ static ei_register_info ei[] = {
{ &ei_wlan_radio_assumed_short_preamble,
{ "wlan_radio.assumed.short_preamble", PI_ASSUMPTION, PI_WARN,
"No preamble length information was available, assuming short preamble.", EXPFILL }},
@@ -1142,23 +1142,14 @@ static ei_register_info ei[] = {
{ &ei_wlan_radio_assumed_bcc_fec,
{ "wlan_radio.assumed.bcc_fec", PI_ASSUMPTION, PI_WARN,
"No fec type information was available, assuming bcc fec.", EXPFILL }},
-};
+ };
-module_t *wlan_radio_module;
-expert_module_t* expert_wlan_radio;
+ module_t *wlan_radio_module;
+ expert_module_t* expert_wlan_radio;
-static gint *tree_array[] = {
- &ett_wlan_radio,
- &ett_wlan_radio_11ac_user,
- &ett_wlan_radio_duration
-};
-
-void proto_register_ieee80211_radio(void)
-{
- proto_wlan_radio = proto_register_protocol("802.11 radio information", "802.11 Radio",
- "wlan_radio");
+ proto_wlan_radio = proto_register_protocol("802.11 radio information", "802.11 Radio", "wlan_radio");
proto_register_field_array(proto_wlan_radio, hf_wlan_radio, array_length(hf_wlan_radio));
- proto_register_subtree_array(tree_array, array_length(tree_array));
+ proto_register_subtree_array(ett, array_length(ett));
expert_wlan_radio = expert_register_protocol(proto_wlan_radio);
expert_register_field_array(expert_wlan_radio, ei, array_length(ei));
@@ -1172,7 +1163,6 @@ void proto_register_ieee80211_radio(void)
"Some generators incorrectly indicate long preamble when the preamble was actually"
"short. Always assume short preamble when calculating duration.",
&wlan_radio_always_short_preamble);
-
}
void proto_reg_handoff_ieee80211_radio(void)
diff --git a/wiretap/wtap.h b/wiretap/wtap.h
index c5d9db4c5c..957dc76c6b 100644
--- a/wiretap/wtap.h
+++ b/wiretap/wtap.h
@@ -760,20 +760,22 @@ struct ieee_802_11ad {
guint8 mcs; /* MCS index */
};
+union ieee_802_11_phy_info {
+ struct ieee_802_11_fhss info_11_fhss;
+ struct ieee_802_11b info_11b;
+ struct ieee_802_11a info_11a;
+ struct ieee_802_11g info_11g;
+ struct ieee_802_11n info_11n;
+ struct ieee_802_11ac info_11ac;
+ struct ieee_802_11ad info_11ad;
+};
+
struct ieee_802_11_phdr {
gint fcs_len; /* Number of bytes of FCS - -1 means "unknown" */
gboolean decrypted; /* TRUE if frame is decrypted even if "protected" bit is set */
gboolean datapad; /* TRUE if frame has padding between 802.11 header and payload */
guint phy; /* PHY type */
- union {
- struct ieee_802_11_fhss info_11_fhss;
- struct ieee_802_11b info_11b;
- struct ieee_802_11a info_11a;
- struct ieee_802_11g info_11g;
- struct ieee_802_11n info_11n;
- struct ieee_802_11ac info_11ac;
- struct ieee_802_11ad info_11ad;
- } phy_info;
+ union ieee_802_11_phy_info phy_info;
/* Which of this information is present? */
guint has_channel:1;