Skip to content

Commit d3c1597

Browse files
twpedersenlinvjw
authored andcommitted
mac80211: fix forwarded mesh frame queue mapping
We can't rely on ieee80211_select_queue() to do its job at this point since the skb->protocol is not yet known. Instead, factor out and reuse the queue mapping logic for injected frames. Also, to mitigate congestion, forwarded frames should be dropped if the outgoing queue was stopped. This was not correctly implemented as we were not checking the right queue. Furthermore, we were dropping frames that had arrived to their destination if that queue was stopped. Signed-off-by: Thomas Pedersen <thomas@cozybit.com> Signed-off-by: Javier Cardona <javier@cozybit.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
1 parent 3c26f1f commit d3c1597

File tree

4 files changed

+36
-21
lines changed

4 files changed

+36
-21
lines changed

net/mac80211/iface.c

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,6 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev,
672672
struct ieee80211_local *local = sdata->local;
673673
struct ieee80211_hdr *hdr;
674674
struct ieee80211_radiotap_header *rtap = (void *)skb->data;
675-
u8 *p;
676675

677676
if (local->hw.queues < 4)
678677
return 0;
@@ -683,19 +682,7 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev,
683682

684683
hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len));
685684

686-
if (!ieee80211_is_data(hdr->frame_control)) {
687-
skb->priority = 7;
688-
return ieee802_1d_to_ac[skb->priority];
689-
}
690-
if (!ieee80211_is_data_qos(hdr->frame_control)) {
691-
skb->priority = 0;
692-
return ieee802_1d_to_ac[skb->priority];
693-
}
694-
695-
p = ieee80211_get_qos_ctl(hdr);
696-
skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK;
697-
698-
return ieee80211_downgrade_queue(local, skb);
685+
return ieee80211_select_queue_80211(local, skb, hdr);
699686
}
700687

701688
static const struct net_device_ops ieee80211_monitorif_ops = {

net/mac80211/rx.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1899,6 +1899,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
18991899
struct ieee80211_local *local = rx->local;
19001900
struct ieee80211_sub_if_data *sdata = rx->sdata;
19011901
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
1902+
u16 q;
19021903

19031904
hdr = (struct ieee80211_hdr *) skb->data;
19041905
hdrlen = ieee80211_hdrlen(hdr->frame_control);
@@ -1917,12 +1918,6 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
19171918
/* illegal frame */
19181919
return RX_DROP_MONITOR;
19191920

1920-
if (ieee80211_queue_stopped(&local->hw, skb_get_queue_mapping(skb))) {
1921-
IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh,
1922-
dropped_frames_congestion);
1923-
return RX_DROP_MONITOR;
1924-
}
1925-
19261921
if (mesh_hdr->flags & MESH_FLAGS_AE) {
19271922
struct mesh_path *mppath;
19281923
char *proxied_addr;
@@ -1954,7 +1949,13 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
19541949
compare_ether_addr(sdata->vif.addr, hdr->addr3) == 0)
19551950
return RX_CONTINUE;
19561951

1957-
skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, skb));
1952+
q = ieee80211_select_queue_80211(local, skb, hdr);
1953+
if (ieee80211_queue_stopped(&local->hw, q)) {
1954+
IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh,
1955+
dropped_frames_congestion);
1956+
return RX_DROP_MONITOR;
1957+
}
1958+
skb_set_queue_mapping(skb, q);
19581959
mesh_hdr->ttl--;
19591960

19601961
if (status->rx_flags & IEEE80211_RX_RA_MATCH) {

net/mac80211/wme.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,30 @@ static int wme_downgrade_ac(struct sk_buff *skb)
5252
}
5353
}
5454

55+
/* Indicate which queue to use for this fully formed 802.11 frame */
56+
u16 ieee80211_select_queue_80211(struct ieee80211_local *local,
57+
struct sk_buff *skb,
58+
struct ieee80211_hdr *hdr)
59+
{
60+
u8 *p;
61+
62+
if (local->hw.queues < 4)
63+
return 0;
64+
65+
if (!ieee80211_is_data(hdr->frame_control)) {
66+
skb->priority = 7;
67+
return ieee802_1d_to_ac[skb->priority];
68+
}
69+
if (!ieee80211_is_data_qos(hdr->frame_control)) {
70+
skb->priority = 0;
71+
return ieee802_1d_to_ac[skb->priority];
72+
}
73+
74+
p = ieee80211_get_qos_ctl(hdr);
75+
skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK;
76+
77+
return ieee80211_downgrade_queue(local, skb);
78+
}
5579

5680
/* Indicate which queue to use. */
5781
u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,

net/mac80211/wme.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515

1616
extern const int ieee802_1d_to_ac[8];
1717

18+
u16 ieee80211_select_queue_80211(struct ieee80211_local *local,
19+
struct sk_buff *skb,
20+
struct ieee80211_hdr *hdr);
1821
u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
1922
struct sk_buff *skb);
2023
void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,

0 commit comments

Comments
 (0)