From mboxrd@z Thu Jan 1 00:00:00 1970 From: Johannes Berg Subject: [RFA] A-MPDU extension Date: Thu, 05 Jul 2012 14:46:40 +0200 Message-ID: <1341492400.4455.42.camel@jlt3.sipsolutions.net> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-IUlwk0s+8VRCDkQM1isY" Return-path: Sender: radiotap-owner-sUITvd46vNxg9hUCZPvPmw@public.gmane.org To: "radiotap-sUITvd46vNxg9hUCZPvPmw@public.gmane.org" List-Id: radiotap@radiotap.org --=-IUlwk0s+8VRCDkQM1isY Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit This is a request for adoption of the long-discussed A-MPDU status extension. I finally got around to implementing it for testing. This proposal adds the following field, as also documented on http://www.radiotap.org/suggested-fields/A-MPDU%20status Bit Number: 20 Structure: u32 reference number, u16 flags, u8 delimiter CRC value, u8 reserved Required Alignment: 4 bytes The presence of this field indicates that the frame was received as part of an a-MPDU. The reference number is generated by the capture device and is the same across each subframe of an A-MPDU. Since the capture device might be capable of capturing multiple channels or data from multiple (concurrent) captures could be merged, the reference number is not guaranteed to be unique across different channels. As a result, applications should use the channel information together with the reference number to identify the subframes belonging to the same A-MPDU. The following flags are defined: 0x0001: driver reports 0-length subframes 0x0002: frame is 0-length subframe (valid only if 0x0001 is set) 0x0004: last subframe is known (should be set for all subframes in an A-MPDU) 0x0008: this frame is the last subframe 0x0010: delimiter CRC error 0x0020: delimiter CRC value known: the delimiter CRC value field is valid 0xffc0: reserved Within an A-MPDU, the subframe index can be determined by the application so it is not included, but depending on the driver reporting this may miss 0-length subframes. --- end of description --- I've attached patches against wireshark to parse and the Linux kernel (the stack and the iwlwifi driver) to report this field. Barring any objections, I will repost at the end of the month for and make the wiki updates to adopt this proposal. At that time, I'll also file a bug against wireshark to update, with this patch. johannes --=-IUlwk0s+8VRCDkQM1isY Content-Disposition: attachment; filename="0001-wireless-add-radiotap-A-MPDU-status-field.patch" Content-Type: text/x-patch; name="0001-wireless-add-radiotap-A-MPDU-status-field.patch"; charset="UTF-8" Content-Transfer-Encoding: 7bit >>From 15827701e153a2ff57a1857b54c86a4d3da1e61d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 5 Jul 2012 11:32:16 +0200 Subject: [PATCH 1/4] wireless: add radiotap A-MPDU status field Define the A-MPDU status field in radiotap, also update the radiotap parser for it and the MCS field that was apparently missed last time. Signed-off-by: Johannes Berg --- include/net/ieee80211_radiotap.h | 11 +++++++++++ net/wireless/radiotap.c | 2 ++ 2 files changed, 13 insertions(+) diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h index 7139254..b273c5b 100644 --- a/include/net/ieee80211_radiotap.h +++ b/include/net/ieee80211_radiotap.h @@ -183,6 +183,9 @@ struct ieee80211_radiotap_header { * Contains a bitmap of known fields/flags, the flags, and * the MCS index. * + * IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitlesss + * + * Contains the AMPDU information for the subframe. */ enum ieee80211_radiotap_type { IEEE80211_RADIOTAP_TSFT = 0, @@ -205,6 +208,7 @@ enum ieee80211_radiotap_type { IEEE80211_RADIOTAP_DATA_RETRIES = 17, IEEE80211_RADIOTAP_MCS = 19, + IEEE80211_RADIOTAP_AMPDU_STATUS = 20, /* valid in every it_present bitmap, even vendor namespaces */ IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, @@ -270,6 +274,13 @@ enum ieee80211_radiotap_type { #define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08 #define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10 +/* For IEEE80211_RADIOTAP_AMPDU_STATUS */ +#define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001 +#define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002 +#define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004 +#define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008 +#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010 +#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020 /* helpers */ static inline int ieee80211_get_radiotap_len(unsigned char *data) diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c index c4ad795..7d604c0 100644 --- a/net/wireless/radiotap.c +++ b/net/wireless/radiotap.c @@ -41,6 +41,8 @@ static const struct radiotap_align_size rtap_namespace_sizes[] = { [IEEE80211_RADIOTAP_TX_FLAGS] = { .align = 2, .size = 2, }, [IEEE80211_RADIOTAP_RTS_RETRIES] = { .align = 1, .size = 1, }, [IEEE80211_RADIOTAP_DATA_RETRIES] = { .align = 1, .size = 1, }, + [IEEE80211_RADIOTAP_MCS] = { .align = 1, .size = 3, }, + [IEEE80211_RADIOTAP_AMPDU_STATUS] = { .align = 4, .size = 8, }, /* * add more here as they are defined in radiotap.h */ -- 1.7.10 --=-IUlwk0s+8VRCDkQM1isY Content-Disposition: attachment; filename*0=0002-mac80211-optimize-ieee80211_rx_status-struct-layout.patc; filename*1=h Content-Type: text/x-patch; name="0002-mac80211-optimize-ieee80211_rx_status-struct-layout.patch"; charset="UTF-8" Content-Transfer-Encoding: 7bit >>From 94aabbebe7ea4bb2b297576d2219f28dda914036 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 5 Jul 2012 13:14:18 +0200 Subject: [PATCH 2/4] mac80211: optimize ieee80211_rx_status struct layout We waste a lot of space in this struct because it uses int values where smaller ones would be sufficient. The upcoming A-MPDU information needs some space, optimize the struct now. Signed-off-by: Johannes Berg --- include/net/mac80211.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 11d72c0..7ce259b 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -709,13 +709,13 @@ enum mac80211_rx_flags { */ struct ieee80211_rx_status { u64 mactime; - enum ieee80211_band band; - int freq; - int signal; - int antenna; - int rate_idx; - int flag; - unsigned int rx_flags; + u16 flag; + u16 freq; + u8 rate_idx; + u8 rx_flags; + u8 band; + u8 antenna; + s8 signal; }; /** -- 1.7.10 --=-IUlwk0s+8VRCDkQM1isY Content-Disposition: attachment; filename="0003-mac80211-support-A-MPDU-status-reporting.patch" Content-Type: text/x-patch; name="0003-mac80211-support-A-MPDU-status-reporting.patch"; charset="UTF-8" Content-Transfer-Encoding: 7bit >>From 1a0f020c98d5d67085272d83f28890fdddd26494 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 5 Jul 2012 11:34:31 +0200 Subject: [PATCH 3/4] mac80211: support A-MPDU status reporting Support getting A-MPDU status information from the drivers and reporting it to userspace via radiotap in the standard fields. Signed-off-by: Johannes Berg --- include/net/mac80211.h | 53 +++++++++++++++++++++++++++++++++++------------- net/mac80211/rx.c | 42 +++++++++++++++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 15 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 7ce259b..ae7888a 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -670,21 +670,41 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) * @RX_FLAG_HT_GF: This frame was received in a HT-greenfield transmission, if * the driver fills this value it should add %IEEE80211_RADIOTAP_MCS_HAVE_FMT * to hw.radiotap_mcs_details to advertise that fact + * @RX_FLAG_AMPDU_DETAILS: A-MPDU details are known, in particular the reference + * number (@ampdu_reference) must be populated and be a distinct number for + * each A-MPDU + * @RX_FLAG_AMPDU_REPORT_ZEROLEN: driver reports 0-length subframes + * @RX_FLAG_AMPDU_IS_ZEROLEN: This is a zero-length subframe, for + * monitoring purposes only + * @RX_FLAG_AMPDU_LAST_KNOWN: last subframe is known, should be set on all + * subframes of a single A-MPDU + * @RX_FLAG_AMPDU_IS_LAST: this subframe is the last subframe of the A-MPDU + * @RX_FLAG_AMPDU_DELIM_CRC_ERROR: A delimiter CRC error has been detected + * on this subframe + * @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC + * is stored in the @ampdu_delimiter_crc field) */ enum mac80211_rx_flags { - RX_FLAG_MMIC_ERROR = 1<<0, - RX_FLAG_DECRYPTED = 1<<1, - RX_FLAG_MMIC_STRIPPED = 1<<3, - RX_FLAG_IV_STRIPPED = 1<<4, - RX_FLAG_FAILED_FCS_CRC = 1<<5, - RX_FLAG_FAILED_PLCP_CRC = 1<<6, - RX_FLAG_MACTIME_MPDU = 1<<7, - RX_FLAG_SHORTPRE = 1<<8, - RX_FLAG_HT = 1<<9, - RX_FLAG_40MHZ = 1<<10, - RX_FLAG_SHORT_GI = 1<<11, - RX_FLAG_NO_SIGNAL_VAL = 1<<12, - RX_FLAG_HT_GF = 1<<13, + RX_FLAG_MMIC_ERROR = BIT(0), + RX_FLAG_DECRYPTED = BIT(1), + RX_FLAG_MMIC_STRIPPED = BIT(3), + RX_FLAG_IV_STRIPPED = BIT(4), + RX_FLAG_FAILED_FCS_CRC = BIT(5), + RX_FLAG_FAILED_PLCP_CRC = BIT(6), + RX_FLAG_MACTIME_MPDU = BIT(7), + RX_FLAG_SHORTPRE = BIT(8), + RX_FLAG_HT = BIT(9), + RX_FLAG_40MHZ = BIT(10), + RX_FLAG_SHORT_GI = BIT(11), + RX_FLAG_NO_SIGNAL_VAL = BIT(12), + RX_FLAG_HT_GF = BIT(13), + RX_FLAG_AMPDU_DETAILS = BIT(14), + RX_FLAG_AMPDU_REPORT_ZEROLEN = BIT(15), + RX_FLAG_AMPDU_IS_ZEROLEN = BIT(16), + RX_FLAG_AMPDU_LAST_KNOWN = BIT(17), + RX_FLAG_AMPDU_IS_LAST = BIT(18), + RX_FLAG_AMPDU_DELIM_CRC_ERROR = BIT(19), + RX_FLAG_AMPDU_DELIM_CRC_KNOWN = BIT(20), }; /** @@ -706,16 +726,21 @@ enum mac80211_rx_flags { * HT rates are use (RX_FLAG_HT) * @flag: %RX_FLAG_* * @rx_flags: internal RX flags for mac80211 + * @ampdu_reference: A-MPDU reference number, must be a different value for + * each A-MPDU but the same for each subframe within one A-MPDU + * @ampdu_delimiter_crc: A-MPDU delimiter CRC */ struct ieee80211_rx_status { u64 mactime; - u16 flag; + u32 ampdu_reference; + u32 flag; u16 freq; u8 rate_idx; u8 rx_flags; u8 band; u8 antenna; s8 signal; + u8 ampdu_delimiter_crc; }; /** diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index d4d82c7..14b5fb4 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -60,7 +60,9 @@ static inline int should_drop_frame(struct sk_buff *skb, struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) + if (status->flag & (RX_FLAG_FAILED_FCS_CRC | + RX_FLAG_FAILED_PLCP_CRC | + RX_FLAG_AMPDU_IS_ZEROLEN)) return 1; if (unlikely(skb->len < 16 + present_fcs_len)) return 1; @@ -91,6 +93,13 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local, if (status->flag & RX_FLAG_HT) /* HT info */ len += 3; + if (status->flag & RX_FLAG_AMPDU_DETAILS) { + /* padding */ + while (len & 3) + len++; + len += 8; + } + return len; } @@ -215,6 +224,37 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, pos++; *pos++ = status->rate_idx; } + + if (status->flag & RX_FLAG_AMPDU_DETAILS) { + u16 flags = 0; + + /* ensure 4 byte alignment */ + while ((pos - (u8 *)rthdr) & 3) + pos++; + rthdr->it_present |= + cpu_to_le32(1 << IEEE80211_RADIOTAP_AMPDU_STATUS); + put_unaligned_le32(status->ampdu_reference, pos); + pos += 4; + if (status->flag & RX_FLAG_AMPDU_REPORT_ZEROLEN) + flags |= IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN; + if (status->flag & RX_FLAG_AMPDU_IS_ZEROLEN) + flags |= IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN; + if (status->flag & RX_FLAG_AMPDU_LAST_KNOWN) + flags |= IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN; + if (status->flag & RX_FLAG_AMPDU_IS_LAST) + flags |= IEEE80211_RADIOTAP_AMPDU_IS_LAST; + if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_ERROR) + flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR; + if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN) + flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN; + put_unaligned_le16(flags, pos); + pos += 2; + if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN) + *pos++ = status->ampdu_delimiter_crc; + else + *pos++ = 0; + *pos++ = 0; + } } /* -- 1.7.10 --=-IUlwk0s+8VRCDkQM1isY Content-Disposition: attachment; filename="0004-iwlwifi-report-A-MPDU-status.patch" Content-Type: text/x-patch; name="0004-iwlwifi-report-A-MPDU-status.patch"; charset="UTF-8" Content-Transfer-Encoding: 7bit >>From cf0ca5d45dd2008602ecc37495206ae44b748e71 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 5 Jul 2012 13:05:08 +0200 Subject: [PATCH 4/4] iwlwifi: report A-MPDU status Since the firmware will give us an A-MPDU bit and only a single PHY information packet for all the subframes in an A-MPDU, we can easily report the minimal A-MPDU information for radiotap. Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/dvm/commands.h | 1 + drivers/net/wireless/iwlwifi/dvm/dev.h | 1 + drivers/net/wireless/iwlwifi/dvm/rx.c | 14 +++++++++++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/dvm/commands.h b/drivers/net/wireless/iwlwifi/dvm/commands.h index 64811cd..7d84fb54 100644 --- a/drivers/net/wireless/iwlwifi/dvm/commands.h +++ b/drivers/net/wireless/iwlwifi/dvm/commands.h @@ -1019,6 +1019,7 @@ struct iwl_wep_cmd { #define RX_RES_PHY_FLAGS_MOD_CCK_MSK cpu_to_le16(1 << 1) #define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK cpu_to_le16(1 << 2) #define RX_RES_PHY_FLAGS_NARROW_BAND_MSK cpu_to_le16(1 << 3) +#define RX_RES_PHY_FLAGS_AGG_MSK cpu_to_le16(1 << 7) #define RX_RES_PHY_FLAGS_ANTENNA_MSK 0xf0 #define RX_RES_PHY_FLAGS_ANTENNA_POS 4 diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h index 54cf085..fee63a7 100644 --- a/drivers/net/wireless/iwlwifi/dvm/dev.h +++ b/drivers/net/wireless/iwlwifi/dvm/dev.h @@ -787,6 +787,7 @@ struct iwl_priv { u8 agg_tids_count; struct iwl_rx_phy_res last_phy_res; + u32 ampdu_ref; bool last_phy_res_valid; /* diff --git a/drivers/net/wireless/iwlwifi/dvm/rx.c b/drivers/net/wireless/iwlwifi/dvm/rx.c index c1f7a18..66415e4 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rx.c +++ b/drivers/net/wireless/iwlwifi/dvm/rx.c @@ -668,6 +668,7 @@ static int iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, struct iwl_rx_packet *pkt = rxb_addr(rxb); priv->last_phy_res_valid = true; + priv->ampdu_ref++; memcpy(&priv->last_phy_res, pkt->data, sizeof(struct iwl_rx_phy_res)); return 0; @@ -911,6 +912,8 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv, u32 ampdu_status; u32 rate_n_flags; + rx_status.flag = 0; + /** * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently. * REPLY_RX: physical layer info is in this buffer @@ -941,6 +944,16 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv, rx_pkt_status = *(__le32 *)(pkt->data + sizeof(*amsdu) + len); ampdu_status = iwlagn_translate_rx_status(priv, le32_to_cpu(rx_pkt_status)); + + if (phy_res->phy_flags & RX_RES_PHY_FLAGS_AGG_MSK) { + /* + * We know which subframes of an A-MPDU belong + * together since we get a single PHY response + * from the firmware for all of them + */ + rx_status.flag |= RX_FLAG_AMPDU_DETAILS; + rx_status.ampdu_reference = priv->ampdu_ref; + } } if ((unlikely(phy_res->cfg_phy_cnt > 20))) { @@ -968,7 +981,6 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv, rx_status.band); rx_status.rate_idx = iwlagn_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band); - rx_status.flag = 0; /* TSF isn't reliable. In order to allow smooth user experience, * this W/A doesn't propagate it to the mac80211 */ -- 1.7.10 --=-IUlwk0s+8VRCDkQM1isY Content-Disposition: attachment; filename="wireshark-ampdu-status.patch" Content-Type: text/x-patch; name="wireshark-ampdu-status.patch"; charset="UTF-8" Content-Transfer-Encoding: 7bit Index: epan/dissectors/packet-ieee80211-radiotap-defs.h =================================================================== --- epan/dissectors/packet-ieee80211-radiotap-defs.h (revision 43572) +++ epan/dissectors/packet-ieee80211-radiotap-defs.h (working copy) @@ -182,6 +182,9 @@ * Contains a bitmap of known fields/flags, the flags, and * the MCS index. * + * IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitlesss + * + * Contains the AMPDU information for the subframe. */ enum ieee80211_radiotap_type { IEEE80211_RADIOTAP_TSFT = 0, @@ -204,6 +207,7 @@ IEEE80211_RADIOTAP_DATA_RETRIES = 17, IEEE80211_RADIOTAP_XCHANNEL = 18, /* Unofficial, used by FreeBSD */ IEEE80211_RADIOTAP_MCS = 19, + IEEE80211_RADIOTAP_AMPDU_STATUS = 20, /* valid in every it_present bitmap, even vendor namespaces */ IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, @@ -270,4 +274,13 @@ #define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10 #define IEEE80211_RADIOTAP_MCS_STBC 0x20 + +/* For IEEE80211_RADIOTAP_AMPDU_STATUS */ +#define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001 +#define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002 +#define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004 +#define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008 +#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010 +#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020 + #endif /* IEEE80211_RADIOTAP_H */ Index: epan/dissectors/packet-ieee80211-radiotap.c =================================================================== --- epan/dissectors/packet-ieee80211-radiotap.c (revision 43572) +++ epan/dissectors/packet-ieee80211-radiotap.c (working copy) @@ -553,6 +553,15 @@ static int hf_radiotap_mcs_format = -1; static int hf_radiotap_mcs_fec = -1; static int hf_radiotap_mcs_stbc = -1; +static int hf_radiotap_ampdu = -1; +static int hf_radiotap_ampdu_ref = -1; +static int hf_radiotap_ampdu_flags = -1; +static int hf_radiotap_ampdu_flags_report_zerolen = -1; +static int hf_radiotap_ampdu_flags_is_zerolen = -1; +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; /* "Present" flags */ static int hf_radiotap_present_tsft = -1; @@ -601,6 +610,8 @@ static gint ett_radiotap_vendor = -1; 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 dissector_handle_t ieee80211_handle; static dissector_handle_t ieee80211_datapad_handle; @@ -1256,11 +1267,44 @@ {"STBC", "radiotap.mcs.stbc", FT_BOOLEAN, 8, TFS(&tfs_on_off), IEEE80211_RADIOTAP_MCS_STBC, "Space Time Block Code", HFILL}}, - {&hf_radiotap_mcs_index, {"MCS index", "radiotap.mcs.index", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_radiotap_ampdu, + {"A-MPDU status", "radiotap.ampdu", + FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, + {&hf_radiotap_ampdu_ref, + {"A-MPDU reference number", "radiotap.ampdu.reference", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_radiotap_ampdu_flags, + {"A-MPDU flags", "radiotap.ampdu.flags", + FT_UINT16, BASE_HEX, NULL, 0x0, + "A-MPDU status flags", HFILL}}, + {&hf_radiotap_ampdu_flags_report_zerolen, + {"Driver reports 0-length subframes in this A-MPDU", "radiotap.ampdu.flags.report_zerolen", + FT_BOOLEAN, 16, NULL, + IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN, NULL, HFILL}}, + {&hf_radiotap_ampdu_flags_is_zerolen, + {"This is a 0-length subframe", "radiotap.ampdu.flags.is_zerolen", + FT_BOOLEAN, 16, NULL, + IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN, NULL, HFILL}}, + {&hf_radiotap_ampdu_flags_last_known, + {"Last subframe of this A-MPDU is known", "radiotap.ampdu.flags.lastknown", + FT_BOOLEAN, 16, NULL, + IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN, NULL, HFILL}}, + {&hf_radiotap_ampdu_flags_is_last, + {"This is the last subframe of this A-MPDU", "radiotap.ampdu.flags.last", + FT_BOOLEAN, 16, NULL, + IEEE80211_RADIOTAP_AMPDU_IS_LAST, NULL, HFILL}}, + {&hf_radiotap_ampdu_flags_delim_crc_error, + {"Delimiter CRC error on this subframe", "radiotap.ampdu.flags.delim_crc_error", + FT_BOOLEAN, 16, NULL, + IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR, NULL, HFILL}}, + {&hf_radiotap_ampdu_delim_crc, + {"A-MPDU subframe delimiter CRC", "radiotap.ampdu.delim_crc", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}}, + {&hf_radiotap_vendor_ns, {"Vendor namespace", "radiotap.vendor_namespace", FT_BYTES, BASE_NONE, NULL, 0x0, @@ -1304,6 +1348,8 @@ &ett_radiotap_vendor, &ett_radiotap_mcs, &ett_radiotap_mcs_known, + &ett_radiotap_ampdu, + &ett_radiotap_ampdu_flags, }; module_t *radiotap_module; @@ -2045,7 +2091,47 @@ } break; } + case IEEE80211_RADIOTAP_AMPDU_STATUS: { + proto_item *it; + proto_tree *ampdu_tree = NULL, *ampdu_flags_tree; + guint32 ref; + guint16 flags; + guint8 delim_crc; + + ref = tvb_get_letohl(tvb, offset); + flags = tvb_get_letohs(tvb, offset + 4); + delim_crc = tvb_get_guint8(tvb, offset + 6); + + if (tree) { + it = proto_tree_add_item(radiotap_tree, hf_radiotap_ampdu, + tvb, offset, 8, ENC_NA); + ampdu_tree = proto_item_add_subtree(it, ett_radiotap_ampdu); + + proto_tree_add_uint(ampdu_tree, hf_radiotap_ampdu_ref, + tvb, offset, 4, ref); + + it = proto_tree_add_uint(ampdu_tree, hf_radiotap_ampdu_flags, + tvb, offset + 4, 2, flags); + ampdu_flags_tree = proto_item_add_subtree(it, ett_radiotap_ampdu_flags); + proto_tree_add_item(ampdu_flags_tree, hf_radiotap_ampdu_flags_report_zerolen, + tvb, offset + 4, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ampdu_flags_tree, hf_radiotap_ampdu_flags_is_zerolen, + tvb, offset + 4, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ampdu_flags_tree, hf_radiotap_ampdu_flags_last_known, + tvb, offset + 4, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ampdu_flags_tree, hf_radiotap_ampdu_flags_is_last, + tvb, offset + 4, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ampdu_flags_tree, hf_radiotap_ampdu_flags_delim_crc_error, + tvb, offset + 4, 2, ENC_LITTLE_ENDIAN); + } + if (flags & IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN) { + if (ampdu_tree) + proto_tree_add_uint(ampdu_tree, hf_radiotap_ampdu_delim_crc, + tvb, offset + 6, 1, delim_crc); + } + break; } + } } if (err != -ENOENT && tree) { Index: epan/dissectors/packet-ieee80211-radiotap-iter.c =================================================================== --- epan/dissectors/packet-ieee80211-radiotap-iter.c (revision 43572) +++ epan/dissectors/packet-ieee80211-radiotap-iter.c (working copy) @@ -50,7 +50,8 @@ /* [IEEE80211_RADIOTAP_RTS_RETRIES] = 16 */ { 1, 1 }, /* [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_MCS] = 19 */ { 1, 3 }, + /* [IEEE80211_RADIOTAP_AMPDU_STATUS] = 20 */ { 4, 8 } /* * add more here as they are defined in * include/net/ieee80211_radiotap.h --=-IUlwk0s+8VRCDkQM1isY--