Re: [PATCH v4] mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue.

2016-09-01 Thread Toke Høiland-Jørgensen
Johannes Berg  writes:

>> Yeah, was going to do that anyway. But since I'm touching the code
>> anyway, this might be an opportunity to avoid constructs like this:
>> 
>> if (!invoke_tx_handlers(tx))
>>   /* continue sending the packet */
>> 
>> Most other succeed/fail functions seem to be of type bool, so it
>> would help consistency as well. Unless there is some particular
>> reason why this function happens to be using 0 to indicate success?
>> 
>
> It's just convention in the kernel, really.
>
> IMHO if a function has a bool return value it should be have a more
> expressive name that indicates better what's going on, like e.g.
>
> bool ieee80211_is_radar_required(...);
>
> but of course that's not always done.

Well, it's applied somewhat inconsistently across mac80211, it seems
(e.g. ieee80211_tx() and ieee80211_tx_prepare_skb() are bool, while
invoke_tx_handlers() and ieee80211_skb_resize() are int). But okay,
don't have that strong an opinion about the colour of this particular
bikeshed so I'll keep it the way it is ;)

-Toke


Re: [PATCH v4] mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue.

2016-09-01 Thread Johannes Berg

> Yeah, was going to do that anyway. But since I'm touching the code
> anyway, this might be an opportunity to avoid constructs like this:
> 
> if (!invoke_tx_handlers(tx))
>   /* continue sending the packet */
> 
> Most other succeed/fail functions seem to be of type bool, so it
> would help consistency as well. Unless there is some particular
> reason why this function happens to be using 0 to indicate success?
> 

It's just convention in the kernel, really.

IMHO if a function has a bool return value it should be have a more
expressive name that indicates better what's going on, like e.g.

bool ieee80211_is_radar_required(...);

but of course that's not always done.

johannes


Re: [PATCH v4] mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue.

2016-09-01 Thread Toke Høiland-Jørgensen
Johannes Berg  writes:

>> > They have three possible values ... :)
>> 
>> Ah, no, not the handlers themselves. Meant the invoke_tx_handlers()
>> function (or all three of them after my patch; hence the plural). To
>> avoid the "0 means true" confusion you alluded to :)
>> 
>
> Ah. Actually, even I got confused and thought the return value *was*
> the same as the handler.
>
> I think it doesn't matter to be tricky, gcc is probably going to (have
> to) generate exactly the same code like when you explicitly put an if
> statement in there, it seems?

Yeah, was going to do that anyway. But since I'm touching the code
anyway, this might be an opportunity to avoid constructs like this:

if (!invoke_tx_handlers(tx))
  /* continue sending the packet */

Most other succeed/fail functions seem to be of type bool, so it would
help consistency as well. Unless there is some particular reason why
this function happens to be using 0 to indicate success?

-Toke


Re: [PATCH v4] mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue.

2016-09-01 Thread Johannes Berg

> > They have three possible values ... :)
> 
> Ah, no, not the handlers themselves. Meant the invoke_tx_handlers()
> function (or all three of them after my patch; hence the plural). To
> avoid the "0 means true" confusion you alluded to :)
> 

Ah. Actually, even I got confused and thought the return value *was*
the same as the handler.

I think it doesn't matter to be tricky, gcc is probably going to (have
to) generate exactly the same code like when you explicitly put an if
statement in there, it seems?

johannes


Re: [PATCH v4] mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue.

2016-09-01 Thread Toke Høiland-Jørgensen
Johannes Berg  writes:

>> > > +static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
>> > > +{
>> > > +return invoke_tx_handlers_early(tx) ||
>> > > invoke_tx_handlers_late(tx);
>> > > +}
>> > 
>> > Ugh, please, no, don't be tricky where it's not necessary. Now
>> > every
>> > person reading this has to first look up the return type, and then
>> > the
>> > return value, and make sure they understand that success is
>> > actually
>> > the value 0 ... that's way too much to ask.
>> 
>> Noted. Any objections to turning these into bool return types?
>
> They have three possible values ... :)

Ah, no, not the handlers themselves. Meant the invoke_tx_handlers()
function (or all three of them after my patch; hence the plural). To
avoid the "0 means true" confusion you alluded to :)

-Toke


Re: [PATCH v4] mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue.

2016-09-01 Thread Johannes Berg

> > > +static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
> > > +{
> > > + return invoke_tx_handlers_early(tx) ||
> > > invoke_tx_handlers_late(tx);
> > > +}
> > 
> > Ugh, please, no, don't be tricky where it's not necessary. Now
> > every
> > person reading this has to first look up the return type, and then
> > the
> > return value, and make sure they understand that success is
> > actually
> > the value 0 ... that's way too much to ask.
> 
> Noted. Any objections to turning these into bool return types?

They have three possible values ... :)

johannes



Re: [PATCH v4] mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue.

2016-09-01 Thread Toke Høiland-Jørgensen
Johannes Berg  writes:

>> +static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
>> +{
>> +return invoke_tx_handlers_early(tx) ||
>> invoke_tx_handlers_late(tx);
>> +}
>
> Ugh, please, no, don't be tricky where it's not necessary. Now every
> person reading this has to first look up the return type, and then the
> return value, and make sure they understand that success is actually
> the value 0 ... that's way too much to ask.

Noted. Any objections to turning these into bool return types?


I'll go through and fix your other comments and send a new version.
Thanks for the feedback :)

-Toke


Re: [PATCH v4] mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue.

2016-08-31 Thread Johannes Berg
On Tue, 2016-08-30 at 15:15 +0200, Toke Høiland-Jørgensen wrote:

> @@ -829,10 +844,16 @@ ieee80211_tx_h_sequence(struct
> ieee80211_tx_data *tx)
>    */
>   if (!ieee80211_is_data_qos(hdr->frame_control) ||
>   is_multicast_ether_addr(hdr->addr1)) {
> - /* driver should assign sequence number */
> - info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
> - /* for pure STA mode without beacons, we can do it
> */
> - hdr->seq_ctrl = cpu_to_le16(tx->sdata-
> >sequence_number);
> + fragnum = 0;
> + seq = cpu_to_le16(tx->sdata->sequence_number);
> + skb_queue_walk(>skbs, skb) {
> + info = IEEE80211_SKB_CB(skb);
> + hdr = (struct ieee80211_hdr *)skb->data;
> + /* driver should assign sequence number */
> + info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
> + /* for pure STA mode without beacons, we can
> do it */
> + hdr->seq_ctrl = seq | fragnum++;

I would very much prefer you kept fragnum assignment in the
fragmentation handler.

Also, you just broke this on big endian, please run sparse on your
patches if you don't see these things directly.

> + if (!fast_tx ||
> + !ieee80211_xmit_fast_finish(sta->sdata, sta,
> fast_tx, skb,
> + false)) {
> + /* fast xmit was started, but fails to
> finish */
> + ieee80211_free_txskb(hw, skb);
> + goto begin;
> + }

That obviously cannot happen, it can't fail to finish. See the comments
in xmit_fast() and the return values ...

> +static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
> +{
> + return invoke_tx_handlers_early(tx) ||
> invoke_tx_handlers_late(tx);
> +}

Ugh, please, no, don't be tricky where it's not necessary. Now every
person reading this has to first look up the return type, and then the
return value, and make sure they understand that success is actually
the value 0 ... that's way too much to ask.
 
> +ieee80211_tx_result
> +ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
> +{
> + struct sk_buff *skb;
> + ieee80211_tx_result r;
> +
> + skb_queue_walk(>skbs, skb) {
> + r = ieee80211_tx_h_michael_mic_add_skb(tx, skb);
> + if (r != TX_CONTINUE)
> + return r;
> + }
> + return TX_CONTINUE;
> +}

You just broke TKIP completely again. Adding the MMIC and fragmentation
are not commutative operations.

johannes


[PATCH v4] mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue.

2016-08-30 Thread Toke Høiland-Jørgensen
The TXQ intermediate queues can cause packet reordering when more than
one flow is active to a single station. Since some of the wifi-specific
packet handling (notably sequence number and encryption handling) is
sensitive to re-ordering, things break if they are applied before the
TXQ.

This splits up the TX handlers and fast_xmit logic into two parts: An
early part and a late part. The former is applied before TXQ enqueue,
and the latter after dequeue. The non-TXQ path just applies both parts
at once.

To avoid having to deal with fragmentation on dequeue, the split is set
to be after the fragmentation handler. This means that some reordering
of TX handlers is necessary, and some handlers had to be made aware of
fragmentation due to this reordering.

This approach avoids having to scatter special cases for when TXQ is
enabled, at the cost of making the fast_xmit and TX handler code
slightly more complex.

Signed-off-by: Toke Høiland-Jørgensen 
---
Changes since v3:
  - Fix sequence number assignment in the fast path.
  - Code cleanup.

 include/net/mac80211.h |   2 +
 net/mac80211/tx.c  | 269 ++---
 net/mac80211/wpa.c |  18 +++-
 3 files changed, 227 insertions(+), 62 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index cca510a..9a6a3e9 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -715,6 +715,7 @@ enum mac80211_tx_info_flags {
  * frame (PS-Poll or uAPSD).
  * @IEEE80211_TX_CTRL_RATE_INJECT: This frame is injected with rate information
  * @IEEE80211_TX_CTRL_AMSDU: This frame is an A-MSDU frame
+ * @IEEE80211_TX_CTRL_FAST_XMIT: This frame is going through the fast_xmit path
  *
  * These flags are used in tx_info->control.flags.
  */
@@ -723,6 +724,7 @@ enum mac80211_tx_control_flags {
IEEE80211_TX_CTRL_PS_RESPONSE   = BIT(1),
IEEE80211_TX_CTRL_RATE_INJECT   = BIT(2),
IEEE80211_TX_CTRL_AMSDU = BIT(3),
+   IEEE80211_TX_CTRL_FAST_XMIT = BIT(4),
 };
 
 /*
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 1d0746d..56dca2d 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -38,6 +38,12 @@
 #include "wme.h"
 #include "rate.h"
 
+static int invoke_tx_handlers_late(struct ieee80211_tx_data *tx);
+static bool ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sdata,
+  struct sta_info *sta,
+  struct ieee80211_fast_tx *fast_tx,
+  struct sk_buff *skb, bool xmit);
+
 /* misc utils */
 
 static inline void ieee80211_tx_stats(struct net_device *dev, u32 len)
@@ -585,20 +591,27 @@ static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
 {
struct ieee80211_key *key;
-   struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
-   struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
+   struct ieee80211_tx_info *info;
+   struct ieee80211_hdr *hdr;
+   struct sk_buff *skb = tx->skb;
+
+   if (!skb)
+   skb = skb_peek(>skbs);
+
+   info = IEEE80211_SKB_CB(skb);
+   hdr = (struct ieee80211_hdr *)skb->data;
 
if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT))
tx->key = NULL;
else if (tx->sta &&
 (key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx])))
tx->key = key;
-   else if (ieee80211_is_group_privacy_action(tx->skb) &&
+   else if (ieee80211_is_group_privacy_action(skb) &&
(key = rcu_dereference(tx->sdata->default_multicast_key)))
tx->key = key;
else if (ieee80211_is_mgmt(hdr->frame_control) &&
 is_multicast_ether_addr(hdr->addr1) &&
-ieee80211_is_robust_mgmt_frame(tx->skb) &&
+ieee80211_is_robust_mgmt_frame(skb) &&
 (key = rcu_dereference(tx->sdata->default_mgmt_key)))
tx->key = key;
else if (is_multicast_ether_addr(hdr->addr1) &&
@@ -628,8 +641,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
case WLAN_CIPHER_SUITE_GCMP_256:
if (!ieee80211_is_data_present(hdr->frame_control) &&
!ieee80211_use_mfp(hdr->frame_control, tx->sta,
-  tx->skb) &&
-   !ieee80211_is_group_privacy_action(tx->skb))
+  skb) &&
+   !ieee80211_is_group_privacy_action(skb))
tx->key = NULL;
else
skip_hw = (tx->key->conf.flags &
@@ -799,10 +812,12 @@ static __le16 ieee80211_tx_next_seq(struct sta_info *sta, 
int tid)
 static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
 {
-