mac80211: Mesh data frames must have the QoS header
authorJavier Cardona <javier@cozybit.com>
Thu, 8 Sep 2011 00:49:53 +0000 (17:49 -0700)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 14 Sep 2011 17:56:50 +0000 (13:56 -0400)
Per sec 7.1.3.5 of draft 12.0 of 802.11s, mesh frames indicate the
presence of the mesh control header in their QoS header.

Signed-off-by: Javier Cardona <javier@cozybit.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
include/linux/ieee80211.h
net/mac80211/mesh.c
net/mac80211/mesh_hwmp.c
net/mac80211/mesh_pathtbl.c
net/mac80211/rx.c
net/mac80211/tx.c
net/mac80211/wme.c
net/mac80211/wme.h

index 37f95f2e10f9606164b441fd0e4622bd01879183..72f3933938c0e850982c90c69b48a851ccd4086f 100644 (file)
 #define IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK  0x0060
 /* A-MSDU 802.11n */
 #define IEEE80211_QOS_CTL_A_MSDU_PRESENT       0x0080
+/* Mesh Control 802.11s */
+#define IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT  0x0100
 
 /* U-APSD queue for WMM IEs sent by AP */
 #define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD      (1<<7)
index 65acbf5eed2da885293020fd012f501515cf0708..a4225ae69681dbac88d9e664f747526f55c5fb70 100644 (file)
@@ -463,8 +463,7 @@ int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc,
                memcpy(hdr->addr3, meshsa, ETH_ALEN);
                return 24;
        } else {
-               *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
-                               IEEE80211_FCTL_TODS);
+               *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
                /* RA TA DA SA */
                memset(hdr->addr1, 0, ETH_ALEN);   /* RA is resolved later */
                memcpy(hdr->addr2, meshsa, ETH_ALEN);
index 63df0bc3dba4c97218b767a0f59797c9d331b822..6df7913d7ca4baeadc784695aae2ebd311426809 100644 (file)
@@ -209,7 +209,6 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
 static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata,
                struct sk_buff *skb)
 {
-       struct ieee80211_local *local = sdata->local;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
        skb_set_mac_header(skb, 0);
@@ -221,7 +220,7 @@ static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata,
        skb->priority = 7;
 
        info->control.vif = &sdata->vif;
-       ieee80211_set_qos_hdr(local, skb);
+       ieee80211_set_qos_hdr(sdata, skb);
 }
 
 /**
index 4fc8c7a5d4dd010f934f5ddecf01f2d07224f9fe..332b5ff1e885e2f3cac6568a35b87782a727335b 100644 (file)
@@ -225,7 +225,7 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta)
                hdr = (struct ieee80211_hdr *) skb->data;
                memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN);
                skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, skb));
-               ieee80211_set_qos_hdr(sdata->local, skb);
+               ieee80211_set_qos_hdr(sdata, skb);
                __skb_queue_tail(&tmpq, skb);
        }
 
index b1ea4444065eb983f4042ae178d0844f155dd6b9..db46601e50bfaa4b88b82fa475ed6351beb9014d 100644 (file)
@@ -1910,7 +1910,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
                                                                fwded_mcast);
                                skb_set_queue_mapping(fwd_skb,
                                        ieee80211_select_queue(sdata, fwd_skb));
-                               ieee80211_set_qos_hdr(local, fwd_skb);
+                               ieee80211_set_qos_hdr(sdata, fwd_skb);
                        } else {
                                int err;
                                /*
@@ -2572,12 +2572,12 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx)
                CALL_RXH(ieee80211_rx_h_ps_poll)
                CALL_RXH(ieee80211_rx_h_michael_mic_verify)
                /* must be after MMIC verify so header is counted in MPDU mic */
-               CALL_RXH(ieee80211_rx_h_remove_qos_control)
-               CALL_RXH(ieee80211_rx_h_amsdu)
 #ifdef CONFIG_MAC80211_MESH
                if (ieee80211_vif_is_mesh(&rx->sdata->vif))
                        CALL_RXH(ieee80211_rx_h_mesh_fwding);
 #endif
+               CALL_RXH(ieee80211_rx_h_remove_qos_control)
+               CALL_RXH(ieee80211_rx_h_amsdu)
                CALL_RXH(ieee80211_rx_h_data)
                CALL_RXH(ieee80211_rx_h_ctrl);
                CALL_RXH(ieee80211_rx_h_mgmt_check)
index 2a8e437165fb92d1c24e7e17169a03d8ad0640c3..7cd6c28968b282763fa4739fd13296ed3ad99550 100644 (file)
@@ -1596,7 +1596,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
                                return;
                        }
 
-       ieee80211_set_qos_hdr(local, skb);
+       ieee80211_set_qos_hdr(sdata, skb);
        ieee80211_tx(sdata, skb, false);
        rcu_read_unlock();
 }
index a9fee2bc63001ffb2e863fc16581fedf3816d77c..971004c9b04f62b6c59557966b2985591e6d63e6 100644 (file)
@@ -135,7 +135,8 @@ u16 ieee80211_downgrade_queue(struct ieee80211_local *local,
        return ieee802_1d_to_ac[skb->priority];
 }
 
-void ieee80211_set_qos_hdr(struct ieee80211_local *local, struct sk_buff *skb)
+void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,
+                          struct sk_buff *skb)
 {
        struct ieee80211_hdr *hdr = (void *)skb->data;
 
@@ -146,10 +147,11 @@ void ieee80211_set_qos_hdr(struct ieee80211_local *local, struct sk_buff *skb)
 
                tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
 
-               if (unlikely(local->wifi_wme_noack_test))
+               if (unlikely(sdata->local->wifi_wme_noack_test))
                        ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
-               /* qos header is 2 bytes, second reserved */
+               /* qos header is 2 bytes */
                *p++ = ack_policy | tid;
-               *p = 0;
+               *p = ieee80211_vif_is_mesh(&sdata->vif) ?
+                       (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8) : 0;
        }
 }
index faead6d0202659877f8b86c427805b5becb54999..34e166fbf4d4cbd595cc148ac53d6c81ded60d73 100644 (file)
@@ -17,7 +17,8 @@ extern const int ieee802_1d_to_ac[8];
 
 u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
                           struct sk_buff *skb);
-void ieee80211_set_qos_hdr(struct ieee80211_local *local, struct sk_buff *skb);
+void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,
+                          struct sk_buff *skb);
 u16 ieee80211_downgrade_queue(struct ieee80211_local *local,
                               struct sk_buff *skb);