mac80211: rework mesh fast xmit implementation

Refactor in order to make use of generic fast xmit functions
Fix issues with mesh SA/DA addressing

Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
Felix Fietkau 2023-02-26 13:36:58 +01:00
parent 026004d530
commit 2f96580c52
4 changed files with 510 additions and 435 deletions

View File

@ -3,40 +3,92 @@ Date: Thu, 16 Feb 2023 11:07:30 +0100
Subject: [PATCH] wifi: mac80211: use mesh header cache to speed up mesh Subject: [PATCH] wifi: mac80211: use mesh header cache to speed up mesh
forwarding forwarding
Use it to look up the next hop address + sta pointer + key and call
__ieee80211_mesh_xmit_fast to queue the tx frame.
Significantly reduces mesh forwarding path CPU usage and enables the Significantly reduces mesh forwarding path CPU usage and enables the
use of iTXQ. direct use of iTXQ.
Signed-off-by: Felix Fietkau <nbd@nbd.name> Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- ---
--- a/net/mac80211/rx.c --- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c +++ b/net/mac80211/rx.c
@@ -2731,6 +2731,7 @@ ieee80211_rx_mesh_data(struct ieee80211_ @@ -2720,6 +2720,65 @@ ieee80211_deliver_skb(struct ieee80211_r
struct ieee80211_hdr hdr = {
.frame_control = cpu_to_le16(fc)
};
+ struct mhdr_cache_entry *entry = NULL;
struct ieee80211_hdr *fwd_hdr;
struct ieee80211s_hdr *mesh_hdr;
struct ieee80211_tx_info *info;
@@ -2788,7 +2789,12 @@ ieee80211_rx_mesh_data(struct ieee80211_
return RX_DROP_MONITOR;
} }
}
- if (mesh_hdr->flags & MESH_FLAGS_AE) { +#ifdef CPTCFG_MAC80211_MESH
+ if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) +static bool
+ entry = mesh_get_cached_hdr(sdata, mesh_hdr->eaddr1); +ieee80211_rx_mesh_fast_forward(struct ieee80211_sub_if_data *sdata,
+ else if (!(mesh_hdr->flags & MESH_FLAGS_AE)) + struct sk_buff *skb, int hdrlen)
+ entry = mesh_get_cached_hdr(sdata, eth->h_dest); +{
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ struct ieee80211_mesh_fast_tx *entry = NULL;
+ struct ieee80211s_hdr *mesh_hdr;
+ struct tid_ampdu_tx *tid_tx;
+ struct sta_info *sta;
+ struct ethhdr eth;
+ u8 tid;
+ +
+ if (!entry && (mesh_hdr->flags & MESH_FLAGS_AE)) { + mesh_hdr = (struct ieee80211s_hdr *)(skb->data + sizeof(eth));
struct mesh_path *mppath; + if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6)
char *proxied_addr; + entry = mesh_fast_tx_get(sdata, mesh_hdr->eaddr1);
bool update = false; + else if (!(mesh_hdr->flags & MESH_FLAGS_AE))
@@ -2862,11 +2868,23 @@ ieee80211_rx_mesh_data(struct ieee80211_ + entry = mesh_fast_tx_get(sdata, skb->data);
+ if (!entry)
+ return false;
+
+ sta = rcu_dereference(entry->mpath->next_hop);
+ if (!sta)
+ return false;
+
+ if (skb_linearize(skb))
+ return false;
+
+ tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
+ tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
+ if (tid_tx) {
+ if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state))
+ return false;
+
+ if (tid_tx->timeout)
+ tid_tx->last_tx = jiffies;
+ }
+
+ ieee80211_aggr_check(sdata, sta, skb);
+
+ if (ieee80211_get_8023_tunnel_proto(skb->data + hdrlen,
+ &skb->protocol))
+ hdrlen += ETH_ALEN;
+ else
+ skb->protocol = htons(skb->len - hdrlen);
+ skb_set_network_header(skb, hdrlen + 2);
+
+ skb->dev = sdata->dev;
+ memcpy(&eth, skb->data, ETH_HLEN - 2);
+ skb_pull(skb, sizeof(eth));
+ __ieee80211_xmit_fast(sdata, sta, &entry->fast_tx, skb, tid_tx,
+ eth.h_dest, eth.h_source);
+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast);
+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames);
+
+ return true;
+}
+#endif
+
static ieee80211_rx_result
ieee80211_rx_mesh_data(struct ieee80211_sub_if_data *sdata, struct sta_info *sta,
struct sk_buff *skb)
@@ -2824,6 +2883,10 @@ ieee80211_rx_mesh_data(struct ieee80211_
skb_set_queue_mapping(skb, ieee802_1d_to_ac[skb->priority]);
+ if (!multicast &&
+ ieee80211_rx_mesh_fast_forward(sdata, skb, mesh_hdrlen))
+ return RX_QUEUED;
+
ieee80211_fill_mesh_addresses(&hdr, &hdr.frame_control,
eth->h_dest, eth->h_source);
hdrlen = ieee80211_hdrlen(hdr.frame_control);
@@ -2862,6 +2925,7 @@ ieee80211_rx_mesh_data(struct ieee80211_
info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING; info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
info->control.vif = &sdata->vif; info->control.vif = &sdata->vif;
info->control.jiffies = jiffies; info->control.jiffies = jiffies;
@ -44,23 +96,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
if (multicast) { if (multicast) {
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast); IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast);
memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN);
/* update power mode indication when forwarding */ @@ -2883,7 +2947,6 @@ ieee80211_rx_mesh_data(struct ieee80211_
ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr);
+ } else if (entry) {
+ struct ieee80211_hdr *ehdr = (struct ieee80211_hdr *)entry->hdr;
+
+ ether_addr_copy(fwd_hdr->addr1, ehdr->addr1);
+ ether_addr_copy(fwd_hdr->addr2, sdata->vif.addr);
+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast);
+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames);
+ qos[0] = fwd_skb->priority;
+ qos[1] = ieee80211_get_qos_ctl(ehdr)[1];
+ __ieee80211_mesh_xmit_fast(sdata, entry, fwd_skb);
+ return RX_QUEUED;
} else if (!mesh_nexthop_lookup(sdata, fwd_skb)) {
/* mesh power mode flags updated in mesh_nexthop_lookup */
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast);
@@ -2883,7 +2901,6 @@ ieee80211_rx_mesh_data(struct ieee80211_
} }
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames); IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames);
@ -68,3 +104,29 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
ieee80211_add_pending_skb(local, fwd_skb); ieee80211_add_pending_skb(local, fwd_skb);
rx_accept: rx_accept:
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2018,6 +2018,8 @@ void __ieee80211_xmit_fast(struct ieee80
struct ieee80211_fast_tx *fast_tx,
struct sk_buff *skb, bool ampdu,
const u8 *da, const u8 *sa);
+void ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata,
+ struct sta_info *sta, struct sk_buff *skb);
/* HT */
void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1191,10 +1191,8 @@ static bool ieee80211_tx_prep_agg(struct
return queued;
}
-static void
-ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata,
- struct sta_info *sta,
- struct sk_buff *skb)
+void ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata,
+ struct sta_info *sta, struct sk_buff *skb)
{
struct rate_control_ref *ref = sdata->local->rate_ctrl;
u16 tid;

View File

@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/net/mac80211/rx.c --- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c +++ b/net/mac80211/rx.c
@@ -2847,6 +2847,9 @@ ieee80211_rx_mesh_data(struct ieee80211_ @@ -2904,6 +2904,9 @@ ieee80211_rx_mesh_data(struct ieee80211_
if (skb_cow_head(fwd_skb, hdrlen - sizeof(struct ethhdr))) if (skb_cow_head(fwd_skb, hdrlen - sizeof(struct ethhdr)))
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
@ -21,7 +21,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
} }
fwd_hdr = skb_push(fwd_skb, hdrlen - sizeof(struct ethhdr)); fwd_hdr = skb_push(fwd_skb, hdrlen - sizeof(struct ethhdr));
@@ -2861,7 +2864,7 @@ ieee80211_rx_mesh_data(struct ieee80211_ @@ -2918,7 +2921,7 @@ ieee80211_rx_mesh_data(struct ieee80211_
hdrlen += ETH_ALEN; hdrlen += ETH_ALEN;
else else
fwd_skb->protocol = htons(fwd_skb->len - hdrlen); fwd_skb->protocol = htons(fwd_skb->len - hdrlen);

View File

@ -87,7 +87,7 @@
CFG80211_TESTMODE_DUMP(ieee80211_testmode_dump) CFG80211_TESTMODE_DUMP(ieee80211_testmode_dump)
--- a/net/mac80211/ieee80211_i.h --- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h
@@ -1536,6 +1536,7 @@ struct ieee80211_local { @@ -1535,6 +1535,7 @@ struct ieee80211_local {
int dynamic_ps_forced_timeout; int dynamic_ps_forced_timeout;
int user_power_level; /* in dBm, for all interfaces */ int user_power_level; /* in dBm, for all interfaces */