lkml.org 
[lkml]   [2016]   [Apr]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.16 039/217] mac80211: fix unnecessary frame drops in mesh fwding
    3.16.35-rc1 review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Michal Kazior <michal.kazior@tieto.com>

    commit cf44012810ccdd8fd947518e965cb04b7b8498be upstream.

    The ieee80211_queue_stopped() expects hw queue
    number but it was given raw WMM AC number instead.

    This could cause frame drops and problems with
    traffic in some cases - most notably if driver
    doesn't map AC numbers to queue numbers 1:1 and
    uses ieee80211_stop_queues() and
    ieee80211_wake_queue() only without ever calling
    ieee80211_wake_queues().

    On ath10k it was possible to hit this problem in
    the following case:

    1. wlan0 uses queue 0
    (ath10k maps queues per vif)
    2. offchannel uses queue 15
    3. queues 1-14 are unused
    4. ieee80211_stop_queues()
    5. ieee80211_wake_queue(q=0)
    6. ieee80211_wake_queue(q=15)
    (other queues are not woken up because both
    driver and mac80211 know other queues are
    unused)
    7. ieee80211_rx_h_mesh_fwding()
    8. ieee80211_select_queue_80211() returns 2
    9. ieee80211_queue_stopped(q=2) returns true
    10. frame is dropped (oops!)

    Fixes: d3c1597b8d1b ("mac80211: fix forwarded mesh frame queue mapping")
    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    net/mac80211/rx.c | 5 +++--
    1 file changed, 3 insertions(+), 2 deletions(-)

    --- a/net/mac80211/rx.c
    +++ b/net/mac80211/rx.c
    @@ -2058,7 +2058,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
    struct ieee80211_sub_if_data *sdata = rx->sdata;
    struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
    struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
    - u16 q, hdrlen;
    + u16 ac, q, hdrlen;

    hdr = (struct ieee80211_hdr *) skb->data;
    hdrlen = ieee80211_hdrlen(hdr->frame_control);
    @@ -2128,7 +2128,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
    ether_addr_equal(sdata->vif.addr, hdr->addr3))
    return RX_CONTINUE;

    - q = ieee80211_select_queue_80211(sdata, skb, hdr);
    + ac = ieee80211_select_queue_80211(sdata, skb, hdr);
    + q = sdata->vif.hw_queue[ac];
    if (ieee80211_queue_stopped(&local->hw, q)) {
    IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion);
    return RX_DROP_MONITOR;
    \
     
     \ /
      Last update: 2016-04-27 02:01    [W:4.497 / U:0.200 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site