Skip to content

Commit

Permalink
mac80211: Mesh Fast xmit support
Browse files Browse the repository at this point in the history
Support Fast xmit for mesh device types by caching the
header corresponding to the ethernet DA and reusing
the cached header (mac, mesh, llc) everytime the packet
is intended for that DA.

This will avoid multiple path table lookups during header
generation for a mesh packet tx.

Freshness of the header is verified by identifying change
in mesh paths before using the header and corresponding
changes to the header and cache entry is done on the fly.

Mutable fields of the header such as eth SA, tid, mesh SN,
PN are updated for each xmit.

Each cache entry is about 100Bytes, least used/expired entries
are periodically removed when cache gets almost full.
Currently the size is set to 50 entries.

Driver needs to advertise NL80211_EXT_FEATURE_MESH_FAST_XMIT
to enable this support and setup this cache.

Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
  • Loading branch information
Sriram R authored and intel-lab-lkp committed Dec 4, 2021
1 parent 75c5bd6 commit 14d9dd6
Show file tree
Hide file tree
Showing 9 changed files with 554 additions and 6 deletions.
3 changes: 3 additions & 0 deletions include/net/mac80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,8 @@ enum mac80211_tx_info_flags {
* @IEEE80211_TX_CTRL_DONT_REORDER: This frame should not be reordered
* relative to other frames that have this flag set, independent
* of their QoS TID or other priority field values.
* @IEEE80211_TX_CTRL_CHECK_FAST_MESH: During Mesh xmit, the header of this
* frame can be cached for faster lookup later.
*
* These flags are used in tx_info->control.flags.
*/
Expand All @@ -881,6 +883,7 @@ enum mac80211_tx_control_flags {
IEEE80211_TX_INTCFL_NEED_TXPROCESSING = BIT(6),
IEEE80211_TX_CTRL_NO_SEQNO = BIT(7),
IEEE80211_TX_CTRL_DONT_REORDER = BIT(8),
IEEE80211_TX_CTRL_CHECK_FAST_MESH = BIT(9),
};

/*
Expand Down
4 changes: 4 additions & 0 deletions include/uapi/linux/nl80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -6063,6 +6063,9 @@ enum nl80211_feature_flags {
* @NL80211_EXT_FEATURE_RADAR_OFFCHAN: Device supports offchannel radar/CAC
* detection.
*
* @NL80211_EXT_FEATURE_MESH_FAST_XMIT: Driver supports enabling of MESH FAST XMIT
* in mac80211
*
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
*/
Expand Down Expand Up @@ -6130,6 +6133,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_BSS_COLOR,
NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD,
NL80211_EXT_FEATURE_RADAR_OFFCHAN,
NL80211_EXT_FEATURE_MESH_FAST_XMIT,

/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
Expand Down
1 change: 1 addition & 0 deletions net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,7 @@ struct ieee80211_if_mesh {
struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */
int mesh_paths_generation;
int mpp_paths_generation;
struct mesh_hdr_cache *hdr_cache;
};

#ifdef CONFIG_MAC80211_MESH
Expand Down
2 changes: 2 additions & 0 deletions net/mac80211/mesh.c
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,8 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata)
changed = mesh_accept_plinks_update(sdata);
ieee80211_mbss_info_change_notify(sdata, changed);

mesh_hdr_cache_manage(sdata);

mod_timer(&ifmsh->housekeeping_timer,
round_jiffies(jiffies +
IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
Expand Down
63 changes: 63 additions & 0 deletions net/mac80211/mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,61 @@ struct mesh_table {
atomic_t entries; /* Up to MAX_MESH_NEIGHBOURS */
};

/**
* struct mesh_hdr_cache
* @rhead: the rhashtable containing header cache entries
* @walk_head: linked list containing all cached header entries
* @walk_lock: lock protecting walk_head
* @size: number of entries in the header cache
*/
struct mesh_hdr_cache {
struct rhashtable rhead;
struct hlist_head walk_head;
/* protects header hlist */
spinlock_t walk_lock;
atomic_t size;
};

#define MESH_HDR_CACHE_SIZE 50
#define MESH_HDR_CACHE_HIGH_THRESHOLD ((MESH_HDR_CACHE_SIZE * 2) / 3)
#define MESH_HDR_CACHE_TIMEOUT 8000 /* msecs */

#define MESH_HDR_MAX_LEN 56 /* mac+mesh+rfc1042 hdr */

/**
* struct mhdr_cache_entry - Cached Mesh header entry
* @addr_key: The Ethernet DA which is the key for this entry
* @hdr: The cached header
* @machdr_len: Total length of the mac header
* @hdrlen: Length of this header entry
* @key: Key corresponding to the nexthop stored in the header
* @pn_offs: Offset to PN which is updated for every xmit
* @band: band used for tx
* @walk_list: list containing all the cached header entries
* @rhash: rhashtable pointer
* @mpath: The Mesh path corresponding to the Mesh DA
* @mppath: The MPP entry corresponding to this DA
* @timestamp: Last used time of this entry
* @rcu: rcu to free this entry
* @path_change_count: Stored path change value corresponding to the mpath
*/
struct mhdr_cache_entry {
u8 addr_key[ETH_ALEN];
u8 hdr[MESH_HDR_MAX_LEN];
u16 machdr_len;
u16 hdrlen;
struct ieee80211_key *key;
u8 pn_offs;
u8 band;
struct hlist_node walk_list;
struct rhash_head rhash;
struct mesh_path *mpath;
struct mesh_path *mppath;
unsigned long timestamp;
struct rcu_head rcu;
u32 path_change_count;
};

/* Recent multicast cache */
/* RMC_BUCKETS must be a power of 2, maximum 256 */
#define RMC_BUCKETS 256
Expand Down Expand Up @@ -319,6 +374,14 @@ void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata);

bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);

struct mhdr_cache_entry *mesh_fill_cached_hdr(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb);
void mesh_cache_hdr(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, struct mesh_path *mpath);
void mesh_hdr_cache_manage(struct ieee80211_sub_if_data *sdata);
void mesh_hdr_cache_flush(struct mesh_path *mpath, bool is_mpp);
void mesh_queue_preq(struct mesh_path *mpath, u8 flags);

#ifdef CONFIG_MAC80211_MESH
static inline
u32 mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
Expand Down
8 changes: 5 additions & 3 deletions net/mac80211/mesh_hwmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@

#define MAX_PREQ_QUEUE_LEN 64

static void mesh_queue_preq(struct mesh_path *, u8);

static inline u32 u32_field_get(const u8 *preq_elem, int offset, bool ae)
{
if (ae)
Expand Down Expand Up @@ -972,7 +970,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
* Locking: the function must be called from within a rcu read lock block.
*
*/
static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
{
struct ieee80211_sub_if_data *sdata = mpath->sdata;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
Expand Down Expand Up @@ -1250,6 +1248,10 @@ int mesh_nexthop_lookup(struct ieee80211_sub_if_data *sdata,
memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN);
memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
ieee80211_mps_set_frame_flags(sdata, next_hop, hdr);
/* Cache the whole header so as to use next time rather than resolving
* and building it every time
*/
mesh_cache_hdr(sdata, skb, mpath);
return 0;
}

Expand Down

0 comments on commit 14d9dd6

Please sign in to comment.