mac80211: Mesh data frames must have the QoS header
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>
This commit is contained in:
parent
4777be4163
commit
2154c81c32
|
@ -130,6 +130,8 @@
|
||||||
#define IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK 0x0060
|
#define IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK 0x0060
|
||||||
/* A-MSDU 802.11n */
|
/* A-MSDU 802.11n */
|
||||||
#define IEEE80211_QOS_CTL_A_MSDU_PRESENT 0x0080
|
#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 */
|
/* U-APSD queue for WMM IEs sent by AP */
|
||||||
#define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD (1<<7)
|
#define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD (1<<7)
|
||||||
|
|
|
@ -463,8 +463,7 @@ int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc,
|
||||||
memcpy(hdr->addr3, meshsa, ETH_ALEN);
|
memcpy(hdr->addr3, meshsa, ETH_ALEN);
|
||||||
return 24;
|
return 24;
|
||||||
} else {
|
} else {
|
||||||
*fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
|
*fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
|
||||||
IEEE80211_FCTL_TODS);
|
|
||||||
/* RA TA DA SA */
|
/* RA TA DA SA */
|
||||||
memset(hdr->addr1, 0, ETH_ALEN); /* RA is resolved later */
|
memset(hdr->addr1, 0, ETH_ALEN); /* RA is resolved later */
|
||||||
memcpy(hdr->addr2, meshsa, ETH_ALEN);
|
memcpy(hdr->addr2, meshsa, ETH_ALEN);
|
||||||
|
|
|
@ -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,
|
static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata,
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct ieee80211_local *local = sdata->local;
|
|
||||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||||
|
|
||||||
skb_set_mac_header(skb, 0);
|
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;
|
skb->priority = 7;
|
||||||
|
|
||||||
info->control.vif = &sdata->vif;
|
info->control.vif = &sdata->vif;
|
||||||
ieee80211_set_qos_hdr(local, skb);
|
ieee80211_set_qos_hdr(sdata, skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -225,7 +225,7 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta)
|
||||||
hdr = (struct ieee80211_hdr *) skb->data;
|
hdr = (struct ieee80211_hdr *) skb->data;
|
||||||
memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN);
|
memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN);
|
||||||
skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, skb));
|
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);
|
__skb_queue_tail(&tmpq, skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1910,7 +1910,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
|
||||||
fwded_mcast);
|
fwded_mcast);
|
||||||
skb_set_queue_mapping(fwd_skb,
|
skb_set_queue_mapping(fwd_skb,
|
||||||
ieee80211_select_queue(sdata, fwd_skb));
|
ieee80211_select_queue(sdata, fwd_skb));
|
||||||
ieee80211_set_qos_hdr(local, fwd_skb);
|
ieee80211_set_qos_hdr(sdata, fwd_skb);
|
||||||
} else {
|
} else {
|
||||||
int err;
|
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_ps_poll)
|
||||||
CALL_RXH(ieee80211_rx_h_michael_mic_verify)
|
CALL_RXH(ieee80211_rx_h_michael_mic_verify)
|
||||||
/* must be after MMIC verify so header is counted in MPDU mic */
|
/* 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
|
#ifdef CONFIG_MAC80211_MESH
|
||||||
if (ieee80211_vif_is_mesh(&rx->sdata->vif))
|
if (ieee80211_vif_is_mesh(&rx->sdata->vif))
|
||||||
CALL_RXH(ieee80211_rx_h_mesh_fwding);
|
CALL_RXH(ieee80211_rx_h_mesh_fwding);
|
||||||
#endif
|
#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_data)
|
||||||
CALL_RXH(ieee80211_rx_h_ctrl);
|
CALL_RXH(ieee80211_rx_h_ctrl);
|
||||||
CALL_RXH(ieee80211_rx_h_mgmt_check)
|
CALL_RXH(ieee80211_rx_h_mgmt_check)
|
||||||
|
|
|
@ -1596,7 +1596,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ieee80211_set_qos_hdr(local, skb);
|
ieee80211_set_qos_hdr(sdata, skb);
|
||||||
ieee80211_tx(sdata, skb, false);
|
ieee80211_tx(sdata, skb, false);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,7 +135,8 @@ u16 ieee80211_downgrade_queue(struct ieee80211_local *local,
|
||||||
return ieee802_1d_to_ac[skb->priority];
|
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;
|
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;
|
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;
|
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++ = ack_policy | tid;
|
||||||
*p = 0;
|
*p = ieee80211_vif_is_mesh(&sdata->vif) ?
|
||||||
|
(IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8) : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,8 @@ extern const int ieee802_1d_to_ac[8];
|
||||||
|
|
||||||
u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
|
u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
|
||||||
struct sk_buff *skb);
|
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,
|
u16 ieee80211_downgrade_queue(struct ieee80211_local *local,
|
||||||
struct sk_buff *skb);
|
struct sk_buff *skb);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue