aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-07-10 05:21:26 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-07-14 14:52:57 -0400
commitf591fa5dbbbeaebd95c9c019b3a536a327fb79de (patch)
treefdede2804a4d962b072a88dbee870ba41eeb8964 /net/mac80211
parent22bb1be4d271961846cd0889b0f8d671db773080 (diff)
mac80211: fix TX sequence numbers
This patch makes mac80211 assign proper sequence numbers to QoS-data frames. It also removes the old sequence number code because we noticed that only the driver or hardware can assign sequence numbers to non-QoS-data and especially management frames in a race-free manner because beacons aren't passed through mac80211's TX path. This patch also adds temporary code to the rt2x00 drivers to not break them completely, that code will have to be reworked for proper sequence numbers on beacons. It also moves sequence number assignment down in the TX path so no sequence numbers are assigned to frames that are dropped. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/iface.c1
-rw-r--r--net/mac80211/sta_info.h1
-rw-r--r--net/mac80211/tx.c79
4 files changed, 52 insertions, 31 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 934c3ef4f0b..cbea0154ee3 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -419,8 +419,6 @@ struct ieee80211_sub_if_data {
419 */ 419 */
420 u64 basic_rates; 420 u64 basic_rates;
421 421
422 u16 sequence;
423
424 /* Fragment table for host-based reassembly */ 422 /* Fragment table for host-based reassembly */
425 struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; 423 struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX];
426 unsigned int fragment_next; 424 unsigned int fragment_next;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 2e3adcb3ce2..610ed1d9893 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -162,7 +162,6 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
162 /* reset some values that shouldn't be kept across type changes */ 162 /* reset some values that shouldn't be kept across type changes */
163 sdata->basic_rates = 0; 163 sdata->basic_rates = 0;
164 sdata->drop_unencrypted = 0; 164 sdata->drop_unencrypted = 0;
165 sdata->sequence = 0;
166 165
167 return 0; 166 return 0;
168} 167}
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 94311dcfe04..109db787ccb 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -285,6 +285,7 @@ struct sta_info {
285 unsigned long tx_fragments; 285 unsigned long tx_fragments;
286 int txrate_idx; 286 int txrate_idx;
287 int last_txrate_idx; 287 int last_txrate_idx;
288 u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
288#ifdef CONFIG_MAC80211_DEBUG_COUNTERS 289#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
289 unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES]; 290 unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES];
290#endif 291#endif
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 8843416e146..0fbadd8b983 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -38,16 +38,6 @@
38 38
39/* misc utils */ 39/* misc utils */
40 40
41static inline void ieee80211_include_sequence(struct ieee80211_sub_if_data *sdata,
42 struct ieee80211_hdr *hdr)
43{
44 /* Set the sequence number for this frame. */
45 hdr->seq_ctrl = cpu_to_le16(sdata->sequence);
46
47 /* Increase the sequence number. */
48 sdata->sequence = (sdata->sequence + 0x10) & IEEE80211_SCTL_SEQ;
49}
50
51#ifdef CONFIG_MAC80211_LOWTX_FRAME_DUMP 41#ifdef CONFIG_MAC80211_LOWTX_FRAME_DUMP
52static void ieee80211_dump_frame(const char *ifname, const char *title, 42static void ieee80211_dump_frame(const char *ifname, const char *title,
53 const struct sk_buff *skb) 43 const struct sk_buff *skb)
@@ -274,17 +264,6 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
274 return TX_CONTINUE; 264 return TX_CONTINUE;
275} 265}
276 266
277static ieee80211_tx_result debug_noinline
278ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
279{
280 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
281
282 if (ieee80211_hdrlen(hdr->frame_control) >= 24)
283 ieee80211_include_sequence(tx->sdata, hdr);
284
285 return TX_CONTINUE;
286}
287
288/* This function is called whenever the AP is about to exceed the maximum limit 267/* This function is called whenever the AP is about to exceed the maximum limit
289 * of buffered frames for power saving STAs. This situation should not really 268 * of buffered frames for power saving STAs. This situation should not really
290 * happen often during normal operation, so dropping the oldest buffered packet 269 * happen often during normal operation, so dropping the oldest buffered packet
@@ -642,6 +621,49 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
642} 621}
643 622
644static ieee80211_tx_result debug_noinline 623static ieee80211_tx_result debug_noinline
624ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
625{
626 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
627 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
628 u16 *seq;
629 u8 *qc;
630 int tid;
631
632 /* only for injected frames */
633 if (unlikely(ieee80211_is_ctl(hdr->frame_control)))
634 return TX_CONTINUE;
635
636 if (ieee80211_hdrlen(hdr->frame_control) < 24)
637 return TX_CONTINUE;
638
639 if (!ieee80211_is_data_qos(hdr->frame_control)) {
640 info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
641 return TX_CONTINUE;
642 }
643
644 /*
645 * This should be true for injected/management frames only, for
646 * management frames we have set the IEEE80211_TX_CTL_ASSIGN_SEQ
647 * above since they are not QoS-data frames.
648 */
649 if (!tx->sta)
650 return TX_CONTINUE;
651
652 /* include per-STA, per-TID sequence counter */
653
654 qc = ieee80211_get_qos_ctl(hdr);
655 tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
656 seq = &tx->sta->tid_seq[tid];
657
658 hdr->seq_ctrl = cpu_to_le16(*seq);
659
660 /* Increase the sequence number. */
661 *seq = (*seq + 0x10) & IEEE80211_SCTL_SEQ;
662
663 return TX_CONTINUE;
664}
665
666static ieee80211_tx_result debug_noinline
645ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) 667ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
646{ 668{
647 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; 669 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
@@ -1110,12 +1132,12 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
1110 goto txh_done; 1132 goto txh_done;
1111 1133
1112 CALL_TXH(ieee80211_tx_h_check_assoc) 1134 CALL_TXH(ieee80211_tx_h_check_assoc)
1113 CALL_TXH(ieee80211_tx_h_sequence)
1114 CALL_TXH(ieee80211_tx_h_ps_buf) 1135 CALL_TXH(ieee80211_tx_h_ps_buf)
1115 CALL_TXH(ieee80211_tx_h_select_key) 1136 CALL_TXH(ieee80211_tx_h_select_key)
1116 CALL_TXH(ieee80211_tx_h_michael_mic_add) 1137 CALL_TXH(ieee80211_tx_h_michael_mic_add)
1117 CALL_TXH(ieee80211_tx_h_rate_ctrl) 1138 CALL_TXH(ieee80211_tx_h_rate_ctrl)
1118 CALL_TXH(ieee80211_tx_h_misc) 1139 CALL_TXH(ieee80211_tx_h_misc)
1140 CALL_TXH(ieee80211_tx_h_sequence)
1119 CALL_TXH(ieee80211_tx_h_fragment) 1141 CALL_TXH(ieee80211_tx_h_fragment)
1120 /* handlers after fragment must be aware of tx info fragmentation! */ 1142 /* handlers after fragment must be aware of tx info fragmentation! */
1121 CALL_TXH(ieee80211_tx_h_encrypt) 1143 CALL_TXH(ieee80211_tx_h_encrypt)
@@ -1827,9 +1849,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
1827 memcpy(skb_put(skb, beacon->head_len), beacon->head, 1849 memcpy(skb_put(skb, beacon->head_len), beacon->head,
1828 beacon->head_len); 1850 beacon->head_len);
1829 1851
1830 ieee80211_include_sequence(sdata,
1831 (struct ieee80211_hdr *)skb->data);
1832
1833 /* 1852 /*
1834 * Not very nice, but we want to allow the driver to call 1853 * Not very nice, but we want to allow the driver to call
1835 * ieee80211_beacon_get() as a response to the set_tim() 1854 * ieee80211_beacon_get() as a response to the set_tim()
@@ -1919,14 +1938,18 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
1919 1938
1920 info->control.vif = vif; 1939 info->control.vif = vif;
1921 info->tx_rate_idx = rsel.rate_idx; 1940 info->tx_rate_idx = rsel.rate_idx;
1941
1942 info->flags |= IEEE80211_TX_CTL_NO_ACK;
1943 info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
1944 info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
1945 info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
1922 if (sdata->bss_conf.use_short_preamble && 1946 if (sdata->bss_conf.use_short_preamble &&
1923 sband->bitrates[rsel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) 1947 sband->bitrates[rsel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE)
1924 info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; 1948 info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE;
1949
1925 info->antenna_sel_tx = local->hw.conf.antenna_sel_tx; 1950 info->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
1926 info->flags |= IEEE80211_TX_CTL_NO_ACK;
1927 info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
1928 info->control.retry_limit = 1; 1951 info->control.retry_limit = 1;
1929 info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; 1952
1930 (*num_beacons)++; 1953 (*num_beacons)++;
1931out: 1954out:
1932 rcu_read_unlock(); 1955 rcu_read_unlock();