aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorThomas Pedersen <thomas@cozybit.com>2011-11-24 20:15:23 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-11-28 14:44:05 -0500
commitd3c1597b8d1ba0447ce858c7c385eabcf69f2c8f (patch)
tree8cb77c385088aadf240d270f1c854d72d4193c52 /net
parent3c26f1f68e24d087cd3481aeb68a6274e6e0b30b (diff)
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>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/iface.c15
-rw-r--r--net/mac80211/rx.c15
-rw-r--r--net/mac80211/wme.c24
-rw-r--r--net/mac80211/wme.h3
4 files changed, 36 insertions, 21 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index be1d61e76e93..3d3bb5e9d8fa 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -672,7 +672,6 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev,
672 struct ieee80211_local *local = sdata->local; 672 struct ieee80211_local *local = sdata->local;
673 struct ieee80211_hdr *hdr; 673 struct ieee80211_hdr *hdr;
674 struct ieee80211_radiotap_header *rtap = (void *)skb->data; 674 struct ieee80211_radiotap_header *rtap = (void *)skb->data;
675 u8 *p;
676 675
677 if (local->hw.queues < 4) 676 if (local->hw.queues < 4)
678 return 0; 677 return 0;
@@ -683,19 +682,7 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev,
683 682
684 hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len)); 683 hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len));
685 684
686 if (!ieee80211_is_data(hdr->frame_control)) { 685 return ieee80211_select_queue_80211(local, skb, hdr);
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);
699} 686}
700 687
701static const struct net_device_ops ieee80211_monitorif_ops = { 688static const struct net_device_ops ieee80211_monitorif_ops = {
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 60798d6d53cf..92fa95741761 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1899,6 +1899,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1899 struct ieee80211_local *local = rx->local; 1899 struct ieee80211_local *local = rx->local;
1900 struct ieee80211_sub_if_data *sdata = rx->sdata; 1900 struct ieee80211_sub_if_data *sdata = rx->sdata;
1901 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); 1901 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
1902 u16 q;
1902 1903
1903 hdr = (struct ieee80211_hdr *) skb->data; 1904 hdr = (struct ieee80211_hdr *) skb->data;
1904 hdrlen = ieee80211_hdrlen(hdr->frame_control); 1905 hdrlen = ieee80211_hdrlen(hdr->frame_control);
@@ -1917,12 +1918,6 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1917 /* illegal frame */ 1918 /* illegal frame */
1918 return RX_DROP_MONITOR; 1919 return RX_DROP_MONITOR;
1919 1920
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
1926 if (mesh_hdr->flags & MESH_FLAGS_AE) { 1921 if (mesh_hdr->flags & MESH_FLAGS_AE) {
1927 struct mesh_path *mppath; 1922 struct mesh_path *mppath;
1928 char *proxied_addr; 1923 char *proxied_addr;
@@ -1954,7 +1949,13 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1954 compare_ether_addr(sdata->vif.addr, hdr->addr3) == 0) 1949 compare_ether_addr(sdata->vif.addr, hdr->addr3) == 0)
1955 return RX_CONTINUE; 1950 return RX_CONTINUE;
1956 1951
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);
1958 mesh_hdr->ttl--; 1959 mesh_hdr->ttl--;
1959 1960
1960 if (status->rx_flags & IEEE80211_RX_RA_MATCH) { 1961 if (status->rx_flags & IEEE80211_RX_RA_MATCH) {
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index a98f24ac9369..89511be3111e 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -52,6 +52,30 @@ static int wme_downgrade_ac(struct sk_buff *skb)
52 } 52 }
53} 53}
54 54
55/* Indicate which queue to use for this fully formed 802.11 frame */
56u16 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}
55 79
56/* Indicate which queue to use. */ 80/* Indicate which queue to use. */
57u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, 81u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h
index 34e166fbf4d4..94edceb617ff 100644
--- a/net/mac80211/wme.h
+++ b/net/mac80211/wme.h
@@ -15,6 +15,9 @@
15 15
16extern const int ieee802_1d_to_ac[8]; 16extern const int ieee802_1d_to_ac[8];
17 17
18u16 ieee80211_select_queue_80211(struct ieee80211_local *local,
19 struct sk_buff *skb,
20 struct ieee80211_hdr *hdr);
18u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, 21u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
19 struct sk_buff *skb); 22 struct sk_buff *skb);
20void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, 23void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,