d80211: Add software sequence support
Subsystems (2)
PATCH v2 1/1 d80211: Add software sequence support
Most hardware can keep track of sequence numbers themselves, unfortunately *most* doesn't cover all devices. ;) This patch will keep track of the (per-bss) sequence number if the flag IEEE80211_HW_SOFTWARE_SEQUENCE has been set.
---
include/net/d80211.h +3 -0
@@ -534,6 +534,9 @@ struct ieee80211_hw {* per-packet RC4 key with each TX frame when doing hwcrypto */ #define IEEE80211_HW_TKIP_REQ_PHASE2_KEY (1<<14) +/* Does the HOST need to insert the frame sequence counter */ +#define IEEE80211_HW_SOFTWARE_SEQUENCE (1<<15) +u32 flags;/* hardware flags defined above */ /* Set to the size of a needed device specific skb headroom for TX skbs. */
net/d80211/ieee80211.c +42 -1
85 lines not on this page · raw message
net/d80211/ieee80211_i.h +5 -0
@@ -80,6 +80,7 @@ struct ieee80211_sta_bss {u8 ssid[IEEE80211_MAX_SSID_LEN ];size_t ssid_len;u16 capability;/* host byte order */ +u16 sequence;int hw_mode;int channel;int freq;
@@ -682,6 +683,10 @@ struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev, u8 *addr);int ieee80211_sta_deauthenticate (struct net_device *dev,u16 reason);int ieee80211_sta_disassociate (struct net_device *dev,u16 reason); +struct ieee80211_sta_bss * +ieee80211_rx_bss_get (struct net_device *dev,u8 *bssid); +void ieee80211_rx_bss_put (struct net_device *dev, +struct ieee80211_sta_bss *bss);/* ieee80211_dev.c */ int ieee80211_dev_alloc_index (struct ieee80211_local *local);
net/d80211/ieee80211_sta.c +3 -7
@@ -57,10 +57,6 @@static void ieee80211_send_probe_req (struct net_device *dev,u8 *dst,u8 *ssid,size_t ssid_len); -static struct ieee80211_sta_bss * -ieee80211_rx_bss_get (struct net_device *dev,u8 *bssid); -static void ieee80211_rx_bss_put (struct net_device *dev, -struct ieee80211_sta_bss *bss);static int ieee80211_sta_find_ibss (struct net_device *dev,struct ieee80211_if_sta *ifsta);static int ieee80211_sta_wep_configured (struct net_device *dev);
@@ -1274,7 +1270,7 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid) } -static struct ieee80211_sta_bss * +struct ieee80211_sta_bss *ieee80211_rx_bss_get (struct net_device *dev,u8 *bssid) {struct ieee80211_local *local = dev->ieee80211_ptr;
@@ -1303,8 +1299,8 @@ static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss) } -static void ieee80211_rx_bss_put (struct net_device *dev, -struct ieee80211_sta_bss *bss) +void ieee80211_rx_bss_put (struct net_device *dev, +struct ieee80211_sta_bss *bss) {struct ieee80211_local *local = dev->ieee80211_ptr;if (!atomic_dec_and_test (&bss->users))
Johannes Berg
maintainerQuoted 4 lines · Ivo van Doorn
Most hardware can keep track of sequence numbers themselves, unfortunately *most* doesn't cover all devices. ;) This patch will keep track of the (per-bss) sequence number if the flag
IEEE80211_HW_SOFTWARE_SEQUENCEhas been set.
Can this be a library function instead? Our TX path is already cluttered enough...
Quoted 12 lines
net/d80211/ieee80211.c +12
-0+static void ieee80211_include_sequence (struct net_device *dev, +struct ieee80211_hdr *hdr) +{ +struct ieee80211_sta_bss *bss; +u8 *bssid =ieee80211_get_bssid (hdr,sizeof (*hdr)); + + bss =ieee80211_rx_bss_get (dev, bssid); +if (!bss) +return ; + +/* +* Set the sequence number for this frame.
net/d80211/ieee80211.c static u8 * ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len); · line 74
Quoted 10 lines
net/d80211/ieee80211.c +10
-0+*/ + hdr->seq_ctrl =cpu_to_le16 (bss->sequence &IEEE80211_SCTL_SEQ ); + +/* +* Increase the sequence number. +*/ + bss->sequence = (bss->sequence +0x10 ) &IEEE80211_SCTL_SEQ ; + +ieee80211_rx_bss_put (dev, bss); +}
This could be exported getting an skb instead of the ieee80211_hdr.
Then the driver can just call it whenever it needs the sequence number for a frame. It'll need to be a bit smart about fragmentation but I think that's ok.
I may be radical, but I think that a lot of things hardware can do belong into library functions the driver can use instead of cluttering the stack with it.
johannes
Quoted 7 lines · Johannes Berg
Then the driver can just call it whenever it needs the sequence number for a frame. It'll need to be a bit smart about fragmentation but I think that's ok.
I may be radical, but I think that a lot of things hardware can do belong into library functions the driver can use instead of cluttering the stack with it.
I'm inclined to agree, FWIW...
Signature · 2 lines
John W. Linville [email protected]
Hi,
Quoted 9 lines
Quoted 7 lines
Then the driver can just call it whenever it needs the sequence number for a frame. It'll need to be a bit smart about fragmentation but I think that's ok.
I may be radical, but I think that a lot of things hardware can do belong into library functions the driver can use instead of cluttering the stack with it.
I'm inclined to agree, FWIW...
Ok, I'll change it. New patch will arrive in a few days.
Ivo
Quoted 9 lines · Johannes Berg
Quoted 4 lines · Ivo van Doorn
Most hardware can keep track of sequence numbers themselves, unfortunately *most* doesn't cover all devices. ;) This patch will keep track of the (per-bss) sequence number if the flag
IEEE80211_HW_SOFTWARE_SEQUENCEhas been set.Can this be a library function instead? Our TX path is already cluttered enough...
If we're going to switch to a library approach, let's do it all at once. I don't want some features requiring flags to toggle and others requiring a function to call.
-Michael Wu
Quoted 3 lines · Michael Wu
If we're going to switch to a library approach, let's do it all at once. I don't want some features requiring flags to toggle and others requiring a function to call.
Entirely library approach is not possible. So we're going to end up with mixed environment in any case.
Jiri
Signature · 2 lines
Jiri Benc SUSE Labs
Quoted 4 lines · Michael Wu
If we're going to switch to a library approach, let's do it all at once. I don't want some features requiring flags to toggle and others requiring a function to call.
To be specific, I don't like the library approach when we can simply set a flag and let the stack handle it. It may clutter the TX path, but it reduces complexity on the driver end. Also, this particular test can be moved from the TX path to device registration with some changes to the way the TX handlers are handled. I will need to check if there are other TX handlers that would benefit from this to make it worthwhile. For things like encryption, I think library functions or callbacks will really be needed to do things right, but for software sequence numbers, I'd rather stick with a simple flag to enable/disable it. It also allows us to report if a particular device supports software sequence numbers which the use of a library function would not specify so directly.
-Michael Wu
Quoted 2 lines · Michael Wu
To be specific, I don't like the library approach when we can simply set a flag and let the stack handle it.
In general, I would prefer not to use library approach for things like this sequence number support. In this case, there may not even be need for that flag if the operation itself is fast enough. In other words, I don't think it would cause problems for other drivers if the seq# were set regardless of whether it is neede or not. Just doing this without the flag may be the cleanest way and not likely to use much more CPU than verification of a flag before doing this..
Signature · 1 line
Jouni Malinen PGP id EFC895FA
Quoted 2 lines · Johannes Berg
Can this be a library function instead? Our TX path is already cluttered enough...
The advantage of non-library approach in this case is that you don't need to search for a BSS the frame belongs to. Ivo's patch searches for it but I think it's possible to remember it from the past.
If this feature is implemented as a library function you need to search for a BSS in any case. That's way more overhead than one condition in the tx path.
Jiri
Signature · 2 lines
Jiri Benc SUSE Labs
net/d80211/ieee80211_i.h struct ieee80211_sta_bss { · line 86
Quoted 12 lines · Ivo van Doorn
net/d80211/ieee80211_i.h +1
-0@@ -80,6 +80,7 @@ struct ieee80211_sta_bss {u8 ssid[IEEE80211_MAX_SSID_LEN ];size_t ssid_len;u16 capability;/* host byte order */ +u16 sequence;int hw_mode;int channel;int freq;
I am not so sure that storing this information in struct ieee80211_sta_bss is correct. As far as I can tell, that is strictly for storing information scan results and beacon information. Nothing outside of ieee80211_sta.c uses it. struct sta_info or struct ieee80211_if_ap (sta interfaces have a pointer to the struct ieee80211_if_ap on the master device) may be a better choice. I think struct sta_info is the right one though there is a problem - it isn't allocated until a successful association.
-Michael Wu
Quoted 7 lines · Michael Wu
I am not so sure that storing this information in struct
ieee80211_sta_bssis correct. As far as I can tell, that is strictly for storing information scan results and beacon information. Nothing outside ofieee80211_sta.cuses it. structsta_infoor structieee80211_if_ap(sta interfaces have a pointer to the structieee80211_if_apon the master device) may be a better choice. I think structsta_infois the right one though there is a problem - it isn't allocated until a successful association.
Thinking about it more, sdata should be the correct place. It's more per-interface thing than per-BSS (although the difference is small in this particular case).
Thanks,
Jiri
Signature · 2 lines
Jiri Benc SUSE Labs
Quoted 8 lines
Quoted 1 line
I am not so sure that storing this information in struct
ieee80211_sta_bssis
Quoted 1 line
correct. As far as I can tell, that is strictly for storing information
scan
Quoted 1 line
results and beacon information. Nothing outside of
ieee80211_sta.cusesit.
Quoted 1 line
struct
sta_infoor structieee80211_if_ap(sta interfaces have a pointerto
Quoted 8 lines
Quoted 2 lines
the struct
ieee80211_if_apon the master device) may be a better choice. I think structsta_infois the right one though there is a problem - itisn't
Quoted 1 line
allocated until a successful association.
Thinking about it more, sdata should be the correct place. It's more per-interface thing than per-BSS (although the difference is small in this particular case).
That would also optimize the sequence handler since the BSS
does not have to be looked up anymore. I'll create the patch to do this asap.
Ivo
Quoted 3 lines · Jiri Benc
Thinking about it more, sdata should be the correct place. It's more per-interface thing than per-BSS (although the difference is small in this particular case).
...and thinking about it even more, that won't work with WDS.
Jiri
Signature · 2 lines
Jiri Benc SUSE Labs
Quoted 6 lines · Jiri Benc
Quoted 3 lines · Jiri Benc
Thinking about it more, sdata should be the correct place. It's more per-interface thing than per-BSS (although the difference is small in this particular case).
...and thinking about it even more, that won't work with WDS.
You mean storing the sequence counter per-interface won't work, or per-bss?
Ivo
Quoted 10 lines · Ivo van Doorn
Quoted 6 lines · Jiri Benc
Quoted 3 lines · Jiri Benc
Thinking about it more, sdata should be the correct place. It's more per-interface thing than per-BSS (although the difference is small in this particular case).
...and thinking about it even more, that won't work with WDS.
You mean storing the sequence counter per-interface won't work, or per-bss?
Both.
When you have a WDS link and some other wireless interface at the same time, their source addresses are (in most cases) the same. You want to have the sequence control counter shared by them. Actually, it will probably work most of time even when they have different counters. The situation where it won't work is if you have two virtual interfaces, one in STA and second in WDS mode, both connected to the same AP. I can't figure out how this particular setup could be useful but it's generally not disallowed.
Anyway, using different counter for a WDS interface probably violates 802.11 (although it's not much specific in this case). I believe it will work in most cases, though.
Any ideas how to solve that?
Thanks,
Jiri
Signature · 2 lines
Jiri Benc SUSE Labs
Quoted 23 lines · Jiri Benc
Quoted 10 lines · Ivo van Doorn
Quoted 6 lines · Jiri Benc
Quoted 3 lines · Jiri Benc
Thinking about it more, sdata should be the correct place. It's more per-interface thing than per-BSS (although the difference is small in this particular case).
...and thinking about it even more, that won't work with WDS.
You mean storing the sequence counter per-interface won't work, or per-bss?
Both.
When you have a WDS link and some other wireless interface at the same time, their source addresses are (in most cases) the same. You want to have the sequence control counter shared by them. Actually, it will probably work most of time even when they have different counters. The situation where it won't work is if you have two virtual interfaces, one in STA and second in WDS mode, both connected to the same AP. I can't figure out how this particular setup could be useful but it's generally not disallowed.
Quoted 5 lines
Anyway, using different counter for a WDS interface probably violates 802.11 (although it's not much specific in this case). I believe it will work in most cases, though.
Any ideas how to solve that?
Are there more situations where it might be important to know
if the WDS interface has to keep in mind that there is a virtual STA interface on the same network? Because it might be worthwhile to make a check for that in the creation of the WDS interface (and in the STA interface).
Ivo
Johannes Berg
maintainerQuoted 11 lines · Jiri Benc
Both.
When you have a WDS link and some other wireless interface at the same time, their source addresses are (in most cases) the same. You want to have the sequence control counter shared by them. Actually, it will probably work most of time even when they have different counters. The situation where it won't work is if you have two virtual interfaces, one in STA and second in WDS mode, both connected to the same AP. I can't figure out how this particular setup could be useful but it's generally not disallowed.
Quoted 5 lines
Anyway, using different counter for a WDS interface probably violates 802.11 (although it's not much specific in this case). I believe it will work in most cases, though.
Any ideas how to solve that?
Make the counter per-mac address?
johannes
Quoted 13 lines · Johannes Berg
Quoted 11 lines · Jiri Benc
Both.
When you have a WDS link and some other wireless interface at the same time, their source addresses are (in most cases) the same. You want to have the sequence control counter shared by them. Actually, it will probably work most of time even when they have different counters. The situation where it won't work is if you have two virtual interfaces, one in STA and second in WDS mode, both connected to the same AP. I can't figure out how this particular setup could be useful but it's generally not disallowed.
Quoted 7 lines
Quoted 5 lines
Anyway, using different counter for a WDS interface probably violates 802.11 (although it's not much specific in this case). I believe it will work in most cases, though.
Any ideas how to solve that?
Make the counter per-mac address?
Wouldn't that be the same as per-interface?
Ivo
Johannes Berg
maintainerQuoted 18 lines · Ivo van Doorn
Quoted 17 lines · Johannes Berg
Quoted 15 lines · Jiri Benc
Both.
When you have a WDS link and some other wireless interface at the same time, their source addresses are (in most cases) the same. You want to have the sequence control counter shared by them. Actually, it will probably work most of time even when they have different counters. The situation where it won't work is if you have two virtual interfaces, one in STA and second in WDS mode, both connected to the same AP. I can't figure out how this particular setup could be useful but it's generally not disallowed.
Anyway, using different counter for a WDS interface probably violates 802.11 (although it's not much specific in this case). I believe it will work in most cases, though.
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
Any ideas how to solve that?
Make the counter per-mac address?
Wouldn't that be the same as per-interface?
Don't WDS interfaces have the same MAC as the corresponding AP interface?
johannes
Quoted 8 lines · Johannes Berg
Quoted 4 lines · Ivo van Doorn
Quoted 1 line · Johannes Berg
Make the counter per-mac address?
Wouldn't that be the same as per-interface?
Don't WDS interfaces have the same MAC as the corresponding AP interface?
They do.
Per-MAC address counters would work but it's another overhead we need to add (allocate a new reference-counted structure, put a pointer to it into sdata, correctly deal with it when MAC address changes).
I think we can live with the counter in sdata. It's not perfect but it should work for all useful cases. The only situation where it won't work I have been able to imagine is the case I described (STA and WDS with the same address) and this particular setup is currently being denied by d80211 (and it's not allowed by 802.11, btw).
If we consider this as a problem later, we can always change to per-MAC address counters or something as it's completely internal to the stack and no driver changes would be required.
Jiri
Signature · 2 lines
Jiri Benc SUSE Labs
Johannes Berg
maintainerQuoted 3 lines · Jiri Benc
Per-MAC address counters would work but it's another overhead we need to add (allocate a new reference-counted structure, put a pointer to it into sdata, correctly deal with it when MAC address changes).
Yup, I agree. Put it into drivers :P
Quoted 9 lines
I think we can live with the counter in sdata. It's not perfect but it should work for all useful cases. The only situation where it won't work I have been able to imagine is the case I described (STA and WDS with the same address) and this particular setup is currently being denied by d80211 (and it's not allowed by 802.11, btw).
If we consider this as a problem later, we can always change to per-MAC address counters or something as it's completely internal to the stack and no driver changes would be required.
Ok. I'm fine with putting it into the stack. I'll take Michael by the word though that he'll do dynamically registered tx handlers later ;)
johannes
Quoted 6 lines
Quoted 3 lines
If we consider this as a problem later, we can always change to per-MAC address counters or something as it's completely internal to the stack and no driver changes would be required.
Ok. I'm fine with putting it into the stack. I'll take Michael by the word though that he'll do dynamically registered tx handlers later ;)
So just to be clear, this patch does not need any tweaking anymore right? Latest patch series for rt2x00 accidently had software sequence handling removed out of rt2400pci and rt2500pci so it is actually broken and at the moment. So I need to either restore it back into the rt2x00 drivers or the mac80211 stack needs to get the support so rt2x00 can use it. :)
Ivo
Quoted 1 line · Ivo van Doorn
So just to be clear, this patch does not need any tweaking anymore right?
Just stick the counter in sdata if you haven't done so already. Should be fine once that's done.
Thanks,
-Michael Wu
Quoted 4 lines · Michael Wu
Quoted 1 line · Ivo van Doorn
So just to be clear, this patch does not need any tweaking anymore right?
Just stick the counter in sdata if you haven't done so already. Should be fine once that's done.
Ah ok. I had it in ieee80211_sta_bss.
I'll create a new patch with the sequence number in the right location.
Thanks.
Ivo
PATCH v3 1/1 d80211: Add software sequence support
Most hardware can keep track of sequence numbers themselves, unfortunately *most* doesn't cover all devices. ;) This patch will keep track of the (per-bss) sequence number if the flag IEEE80211_HW_SOFTWARE_SEQUENCE has been set.
This 3rd version of the patch has the sequence number stored in the ieee80211_sub_if_data structure.
---
include/net/mac80211.h +3 -0
@@ -515,6 +515,9 @@ struct ieee80211_hw {* normal operation. */ #define IEEE80211_HW_MONITOR_DURING_OPER (1<<9) +/* Does the HOST need to insert the frame sequence counter */ +#define IEEE80211_HW_SOFTWARE_SEQUENCE (1<<10) +/* please fill this gap when adding new flags */ /* calculate Michael MIC for an MSDU when doing hwcrypto */
net/mac80211/ieee80211.c +33 -1
@@ -54,6 +54,20 @@ static u8 * ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len);static int ieee80211_mgmt_start_xmit (struct sk_buff *skb,struct net_device *dev); +static void ieee80211_include_sequence (struct ieee80211_sub_if_data *sdata, +struct ieee80211_hdr *hdr) +{ +/* +* Set the sequence number for this frame. +*/ + hdr->seq_ctrl =cpu_to_le16 (sdata->sequence &IEEE80211_SCTL_SEQ ); + +/* +* Increase the sequence number. +*/ + sdata->sequence = (sdata->sequence +0x10 ) &IEEE80211_SCTL_SEQ ; +} +struct ieee80211_key_conf *ieee80211_key_data2conf (struct ieee80211_local *local,const struct ieee80211_key *data)
@@ -445,6 +459,7 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)size_t hdrlen, per_fragm, num_fragm, payload_len, left;struct sk_buff **frags, *first, *frag;int i; +u16 seq;u8 *pos;int frag_threshold = tx->local->fragmentation_threshold;
@@ -463,6 +478,7 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx) goto fail; hdr->frame_control |=cpu_to_le16 (IEEE80211_FCTL_MOREFRAGS ); + seq =le16_to_cpu (hdr->seq_ctrl) &IEEE80211_SCTL_SEQ ; pos = first->data + hdrlen + per_fragm; left = payload_len - per_fragm;for (i =0 ; i < num_fragm -1 ; i++) {
@@ -490,7 +506,7 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)memcpy (fhdr, first->data, hdrlen);if (i == num_fragm -2 ) fhdr->frame_control &=cpu_to_le16 (~IEEE80211_FCTL_MOREFRAGS ); - fhdr->seq_ctrl =cpu_to_le16 (i +1 ); + fhdr->seq_ctrl =cpu_to_le16 (seq + ((i +1 ) &IEEE80211_SCTL_FRAG )); copylen = left > per_fragm ? per_fragm : left;memcpy (skb_put (frag, copylen), pos, copylen);
@@ -900,6 +916,17 @@ ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx)return TXRX_CONTINUE ; } +static ieee80211_txrx_result +ieee80211_tx_h_sequence (struct ieee80211_txrx_data *tx) +{ +struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; + +if ((tx->local->hw.flags &IEEE80211_HW_SOFTWARE_SEQUENCE ) && +ieee80211_get_hdrlen (le16_to_cpu (hdr->frame_control)) >=24 ) +ieee80211_include_sequence (tx->sdata, hdr); + +return TXRX_CONTINUE ; +}/* This function is called whenever the AP is about to exceed the maximum limit * of buffered frames for power saving STAs. This situation should not really
@@ -1770,6 +1797,10 @@ struct sk_buff * ieee80211_beacon_get(struct ieee80211_hw *hw, int if_id,skb_reserve (skb, local->hw.extra_tx_headroom);memcpy (skb_put (skb, bh_len), b_head, bh_len); +if (hw->flags &IEEE80211_HW_SOFTWARE_SEQUENCE ) +ieee80211_include_sequence (sdata, + (struct ieee80211_hdr *)skb->data); +ieee80211_beacon_add_tim (local, ap, skb);if (b_tail) {
@@ -4381,6 +4412,7 @@ static ieee80211_rx_handler ieee80211_rx_handlers[] =static ieee80211_tx_handler ieee80211_tx_handlers[] = { ieee80211_tx_h_check_assoc, + ieee80211_tx_h_sequence, ieee80211_tx_h_ps_buf, ieee80211_tx_h_select_key, ieee80211_tx_h_michael_mic_add,
net/mac80211/ieee80211_i.h +2 -0
@@ -317,6 +317,8 @@ struct ieee80211_sub_if_data {int ieee802_1x;/* IEEE 802.1X PAE - drop packet to/from unauthorized * port */ +u16 sequence; +/* Fragment table for host-based reassembly */ struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX ];unsigned int fragment_next;
Quoted 4 lines · Ivo van Doorn
Most hardware can keep track of sequence numbers themselves, unfortunately *most* doesn't cover all devices. ;) This patch will keep track of the (per-bss) sequence number if the flag
IEEE80211_HW_SOFTWARE_SEQUENCEhas been set.
The question has been asked (by Jouni), but I didn't see a good answer (maybe I missed it).
Why is this a flag at all? The sequence counter is such a trivial thing that having an extra conditional is just _more_ overhead. Why not simply calculate the seq all the time and let hardware override it, if it has the capability to do so? Calculation of the seq is cheap. No need to bloat code.
Quoted 127 lines
This 3rd version of the patch has the sequence number stored in the
ieee80211_sub_if_datastructure.Signed-off-by Ivo van Doorn <[email protected]>---
include/net/mac80211.h +3
-0@@ -515,6 +515,9 @@ struct ieee80211_hw {* normal operation. */ #define IEEE80211_HW_MONITOR_DURING_OPER (1<<9) +/* Does the HOST need to insert the frame sequence counter */ +#define IEEE80211_HW_SOFTWARE_SEQUENCE (1<<10) +/* please fill this gap when adding new flags */ /* calculate Michael MIC for an MSDU when doing hwcrypto */ net/mac80211/ieee80211.c +33
-1@@ -54,6 +54,20 @@ static u8 * ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len);static int ieee80211_mgmt_start_xmit (struct sk_buff *skb,struct net_device *dev); +static void ieee80211_include_sequence (struct ieee80211_sub_if_data *sdata, +struct ieee80211_hdr *hdr) +{ +/* +* Set the sequence number for this frame. +*/ + hdr->seq_ctrl =cpu_to_le16 (sdata->sequence &IEEE80211_SCTL_SEQ ); + +/* +* Increase the sequence number. +*/ + sdata->sequence = (sdata->sequence +0x10 ) &IEEE80211_SCTL_SEQ ; +} +struct ieee80211_key_conf *ieee80211_key_data2conf (struct ieee80211_local *local,const struct ieee80211_key *data)@@ -445,6 +459,7 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)size_t hdrlen, per_fragm, num_fragm, payload_len, left;struct sk_buff **frags, *first, *frag;int i; +u16 seq;u8 *pos;int frag_threshold = tx->local->fragmentation_threshold;@@ -463,6 +478,7 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx) goto fail; hdr->frame_control |=cpu_to_le16 (IEEE80211_FCTL_MOREFRAGS ); + seq =le16_to_cpu (hdr->seq_ctrl) &IEEE80211_SCTL_SEQ ; pos = first->data + hdrlen + per_fragm; left = payload_len - per_fragm;for (i =0 ; i < num_fragm -1 ; i++) {@@ -490,7 +506,7 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)memcpy (fhdr, first->data, hdrlen);if (i == num_fragm -2 ) fhdr->frame_control &=cpu_to_le16 (~IEEE80211_FCTL_MOREFRAGS ); - fhdr->seq_ctrl =cpu_to_le16 (i +1 ); + fhdr->seq_ctrl =cpu_to_le16 (seq + ((i +1 ) &IEEE80211_SCTL_FRAG )); copylen = left > per_fragm ? per_fragm : left;memcpy (skb_put (frag, copylen), pos, copylen);@@ -900,6 +916,17 @@ ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx)return TXRX_CONTINUE ; } +static ieee80211_txrx_result +ieee80211_tx_h_sequence (struct ieee80211_txrx_data *tx) +{ +struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; + +if ((tx->local->hw.flags &IEEE80211_HW_SOFTWARE_SEQUENCE ) && +ieee80211_get_hdrlen (le16_to_cpu (hdr->frame_control)) >=24 ) +ieee80211_include_sequence (tx->sdata, hdr); + +return TXRX_CONTINUE ; +}/* This function is called whenever the AP is about to exceed the maximum limit * of buffered frames for power saving STAs. This situation should not really @@ -1770,6 +1797,10 @@ struct sk_buff * ieee80211_beacon_get(struct ieee80211_hw *hw, int if_id,skb_reserve (skb, local->hw.extra_tx_headroom);memcpy (skb_put (skb, bh_len), b_head, bh_len); +if (hw->flags &IEEE80211_HW_SOFTWARE_SEQUENCE ) +ieee80211_include_sequence (sdata, + (struct ieee80211_hdr *)skb->data); +ieee80211_beacon_add_tim (local, ap, skb);if (b_tail) {@@ -4381,6 +4412,7 @@ static ieee80211_rx_handler ieee80211_rx_handlers[] =static ieee80211_tx_handler ieee80211_tx_handlers[] = { ieee80211_tx_h_check_assoc, + ieee80211_tx_h_sequence, ieee80211_tx_h_ps_buf, ieee80211_tx_h_select_key, ieee80211_tx_h_michael_mic_add,net/mac80211/ieee80211_i.h +2
-1@@ -317,6 +317,8 @@ struct ieee80211_sub_if_data {int ieee802_1x;/* IEEE 802.1X PAE - drop packet to/from unauthorized * port */ +u16 sequence; +/* Fragment table for host-based reassembly */ struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX ];unsigned int fragment_next; -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 1 line
Greetings Michael.
Quoted 6 lines · Michael Buesch
Quoted 4 lines · Ivo van Doorn
Most hardware can keep track of sequence numbers themselves, unfortunately *most* doesn't cover all devices. ;) This patch will keep track of the (per-bss) sequence number if the flag
IEEE80211_HW_SOFTWARE_SEQUENCEhas been set.
Quoted 7 lines
The question has been asked (by Jouni), but I didn't see a good answer (maybe I missed it).
Why is this a flag at all? The sequence counter is such a trivial thing that having an extra conditional is just _more_ overhead. Why not simply calculate the seq all the time and let hardware override it, if it has the capability to do so? Calculation of the seq is cheap. No need to bloat code.
It would also safe me a patch for rt2400pci and rt2500pci as well. ;)
Well if nobody objects against setting the sequence number always, then below patch would be sufficient. :)
---
net/mac80211/ieee80211.c +30 -1
@@ -54,6 +54,20 @@ static u8 * ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len);static int ieee80211_mgmt_start_xmit (struct sk_buff *skb,struct net_device *dev); +static void ieee80211_include_sequence (struct ieee80211_sub_if_data *sdata, +struct ieee80211_hdr *hdr) +{ +/* +* Set the sequence number for this frame. +*/ + hdr->seq_ctrl =cpu_to_le16 (sdata->sequence &IEEE80211_SCTL_SEQ ); + +/* +* Increase the sequence number. +*/ + sdata->sequence = (sdata->sequence +0x10 ) &IEEE80211_SCTL_SEQ ; +} +struct ieee80211_key_conf *ieee80211_key_data2conf (struct ieee80211_local *local,const struct ieee80211_key *data)
@@ -445,6 +459,7 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)size_t hdrlen, per_fragm, num_fragm, payload_len, left;struct sk_buff **frags, *first, *frag;int i; +u16 seq;u8 *pos;int frag_threshold = tx->local->fragmentation_threshold;
@@ -463,6 +478,7 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx) goto fail; hdr->frame_control |=cpu_to_le16 (IEEE80211_FCTL_MOREFRAGS ); + seq =le16_to_cpu (hdr->seq_ctrl) &IEEE80211_SCTL_SEQ ; pos = first->data + hdrlen + per_fragm; left = payload_len - per_fragm;for (i =0 ; i < num_fragm -1 ; i++) {
@@ -490,7 +506,7 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)memcpy (fhdr, first->data, hdrlen);if (i == num_fragm -2 ) fhdr->frame_control &=cpu_to_le16 (~IEEE80211_FCTL_MOREFRAGS ); - fhdr->seq_ctrl =cpu_to_le16 (i +1 ); + fhdr->seq_ctrl =cpu_to_le16 (seq + ((i +1 ) &IEEE80211_SCTL_FRAG )); copylen = left > per_fragm ? per_fragm : left;memcpy (skb_put (frag, copylen), pos, copylen);
@@ -900,6 +916,16 @@ ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx)return TXRX_CONTINUE ; } +static ieee80211_txrx_result +ieee80211_tx_h_sequence (struct ieee80211_txrx_data *tx) +{ +struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; + +if (ieee80211_get_hdrlen (le16_to_cpu (hdr->frame_control)) >=24 ) +ieee80211_include_sequence (tx->sdata, hdr); + +return TXRX_CONTINUE ; +}/* This function is called whenever the AP is about to exceed the maximum limit * of buffered frames for power saving STAs. This situation should not really
@@ -1770,6 +1796,8 @@ struct sk_buff * ieee80211_beacon_get(struct ieee80211_hw *hw, int if_id,skb_reserve (skb, local->hw.extra_tx_headroom);memcpy (skb_put (skb, bh_len), b_head, bh_len); +ieee80211_include_sequence (sdata, (struct ieee80211_hdr *)skb->data); +ieee80211_beacon_add_tim (local, ap, skb);if (b_tail) {
@@ -4381,6 +4409,7 @@ static ieee80211_rx_handler ieee80211_rx_handlers[] =static ieee80211_tx_handler ieee80211_tx_handlers[] = { ieee80211_tx_h_check_assoc, + ieee80211_tx_h_sequence, ieee80211_tx_h_ps_buf, ieee80211_tx_h_select_key, ieee80211_tx_h_michael_mic_add,
net/mac80211/ieee80211_i.h +2 -0
@@ -317,6 +317,8 @@ struct ieee80211_sub_if_data {int ieee802_1x;/* IEEE 802.1X PAE - drop packet to/from unauthorized * port */ +u16 sequence; +/* Fragment table for host-based reassembly */ struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX ];unsigned int fragment_next;
net/mac80211/ieee80211.c static u8 * ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len); · line 58
Quoted 2 lines · Ivo van Doorn
net/mac80211/ieee80211.c +2
-0+static void ieee80211_include_sequence (struct ieee80211_sub_if_data *sdata, +struct ieee80211_hdr *hdr)
I'd prefer specifying this as inline function.
net/mac80211/ieee80211.c static u8 * ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len); · line 63
Quoted 5 lines
net/mac80211/ieee80211.c +5
-0+{ +/* +* Set the sequence number for this frame. +*/ + hdr->seq_ctrl =cpu_to_le16 (sdata->sequence &IEEE80211_SCTL_SEQ );
No need to do "& IEEE80211_SCTL_SEQ" here.
net/mac80211/ieee80211.c static u8 * ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len); · line 67
Quoted 4 lines
net/mac80211/ieee80211.c +4
-0+ +/* +* Increase the sequence number. +*/
Please reduce this and previous comment to one line each.
Quoted 23 lines
net/mac80211/ieee80211.c +5
-0+ sdata->sequence = (sdata->sequence +0x10 ) &IEEE80211_SCTL_SEQ ; +} +struct ieee80211_key_conf *ieee80211_key_data2conf (struct ieee80211_local *local,const struct ieee80211_key *data)@@ -445,6 +459,7 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)size_t hdrlen, per_fragm, num_fragm, payload_len, left;struct sk_buff **frags, *first, *frag;int i; +u16 seq;u8 *pos;int frag_threshold = tx->local->fragmentation_threshold;@@ -463,6 +478,7 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx) goto fail; hdr->frame_control |=cpu_to_le16 (IEEE80211_FCTL_MOREFRAGS ); + seq =le16_to_cpu (hdr->seq_ctrl) &IEEE80211_SCTL_SEQ ; pos = first->data + hdrlen + per_fragm; left = payload_len - per_fragm;for (i =0 ; i < num_fragm -1 ; i++) {
net/mac80211/ieee80211.c ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx) · line 509
Quoted 5 lines
net/mac80211/ieee80211.c +1
-1@@ -490,7 +506,7 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)memcpy (fhdr, first->data, hdrlen);if (i == num_fragm -2 ) fhdr->frame_control &=cpu_to_le16 (~IEEE80211_FCTL_MOREFRAGS ); - fhdr->seq_ctrl =cpu_to_le16 (i +1 ); + fhdr->seq_ctrl =cpu_to_le16 (seq + ((i +1 ) &IEEE80211_SCTL_FRAG ));
I'd prefer | instead of + here.
Thanks,
Jiri
Signature · 2 lines
Jiri Benc SUSE Labs