Add the radiotap field IEEE80211_RADIOTAP_RATE and IEEE80211_RADIOTAP_MCS radiotap parser. These additions are compatible with the radiotap definition (http://www.radiotap.org/Radiotap) Previous attempts were made on this mailing list using a new flag in ieee80211_tx_info. But since this field is now full, I choose to use a bit field in the rate control part of the ieee80211_tx_info. signed-off-by: Cédric Debarge <cedric.debarge@xxxxxxxxx> --- include/net/mac80211.h | 1 + net/mac80211/tx.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 421b6ec..3ed63d8 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -721,6 +721,7 @@ struct ieee80211_tx_info { u8 use_cts_prot:1; u8 short_preamble:1; u8 skip_table:1; + u8 tx_ctl_rc_bypass:1; /* 2 bytes free */ }; /* only needed before rate control */ diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 5214686..7aff9b5 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -657,6 +657,9 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) struct ieee80211_sta_rates *ratetbl = NULL; bool assoc = false; + if (info->control.tx_ctl_rc_bypass) + return TX_CONTINUE; + memset(&txrc, 0, sizeof(txrc)); sband = tx->local->hw.wiphy->bands[info->band]; @@ -1530,19 +1533,30 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, ieee80211_tx(sdata, skb, false, band); } -static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb) +static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb, + struct ieee80211_local *local) { struct ieee80211_radiotap_iterator iterator; struct ieee80211_radiotap_header *rthdr = (struct ieee80211_radiotap_header *) skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_channel *chan = local->monitor_chandef.chan; + struct ieee80211_supported_band *sband = + local->hw.wiphy->bands[chan->band]; + u16 txflags; + s8 rate_idx; + u16 bit_rate; + int i; + unsigned char known; + unsigned char flags; int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len, NULL); - u16 txflags; info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT | IEEE80211_TX_CTL_DONTFRAG; + info->control.tx_ctl_rc_bypass = 0; + /* * for every radiotap entry that is present * (ieee80211_radiotap_iterator_next returns -ENOENT when no more @@ -1589,6 +1603,58 @@ static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb) info->flags |= IEEE80211_TX_CTL_NO_ACK; break; + case IEEE80211_RADIOTAP_RATE: + rate_idx = -1; + /* convert legacy rate; NB: .5 Mb/s -> 100 kb/s */ + bit_rate = *iterator.this_arg * 5; + for (i = 0; i < sband->n_bitrates; i++){ + if (sband->bitrates[i].bitrate == bit_rate) { + rate_idx = i; + break; + } + } + /* Rate not available - rejecting */ + if (rate_idx < 0) + return false; + + info->control.tx_ctl_rc_bypass = 1; + info->control.rates[0].idx = rate_idx; + info->control.rates[0].count = 1; + break; + + case IEEE80211_RADIOTAP_MCS: + known = iterator.this_arg[0]; + flags = iterator.this_arg[1]; + rate_idx = iterator.this_arg[2]; + + /* 11n not supported - rejecting */ + if(!sband->ht_cap.ht_supported) { + return false; + } + + /* set mcs */ + if(known & IEEE80211_RADIOTAP_MCS_HAVE_MCS) { + info->control.rates[0].idx = rate_idx; + info->control.rates[0].flags |= + IEEE80211_TX_RC_MCS; + } + + /* set GI */ + if ((known & IEEE80211_RADIOTAP_MCS_HAVE_GI) && + (flags & IEEE80211_RADIOTAP_MCS_SGI)) + info->control.rates[0].flags |= + IEEE80211_TX_RC_SHORT_GI; + + /* set bandwith */ + if ((known & IEEE80211_RADIOTAP_MCS_HAVE_BW) && + (flags & IEEE80211_RADIOTAP_MCS_BW_40)) + info->control.rates[0].flags |= + IEEE80211_TX_RC_40_MHZ_WIDTH; + + info->control.rates[0].count = 1; + info->control.tx_ctl_rc_bypass = 1; + break; + /* * Please update the file * Documentation/networking/mac80211-injection.txt @@ -1684,7 +1750,7 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, IEEE80211_TX_CTL_INJECTED; /* process and remove the injection radiotap header */ - if (!ieee80211_parse_tx_radiotap(skb)) + if (!ieee80211_parse_tx_radiotap(skb, local)) goto fail; rcu_read_lock(); -- 1.7.9.5 Cédric DEBARGE -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html