diff mbox

[RFC,03/12] mac80211: use all MBSS interfaces for path selection

Message ID 1367548442-8229-4-git-send-email-thomas@cozybit.com (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Thomas Pedersen May 3, 2013, 2:33 a.m. UTC
From: Bob Copeland <me@bobcopeland.com>

Change the HWMP path selection code to establish paths using
all interfaces participating in a shared mbss.  This means that
group-addressed action frames like PREQ will go out on each
interface, while individually addressed frames use whichever
interface has the destination as a peer.

When processing received frames, consider it a match if any
local interface in the mbss matches the target address.

Finally, mesh_path_lookup() now scans the path table on each
interface until a path (if any) is found so that paths can
be shared among the interfaces.

[ PERR/unicast frame handling fixes from Thomas Pedersen ]

Signed-off-by: Bob Copeland <bob@cozybit.com>
---
 net/mac80211/cfg.c          |    8 +--
 net/mac80211/mesh.h         |    6 +--
 net/mac80211/mesh_hwmp.c    |  121 ++++++++++++++++++++++++++++++-------------
 net/mac80211/mesh_pathtbl.c |   47 +++++++++++------
 net/mac80211/rx.c           |    5 +-
 net/mac80211/tx.c           |    5 +-
 6 files changed, 128 insertions(+), 64 deletions(-)

Comments

Johannes Berg May 7, 2013, 1:40 p.m. UTC | #1
On Thu, 2013-05-02 at 19:33 -0700, Thomas Pedersen wrote:

>  /**
> - * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame. Calling
> - * this function is considered "using" the associated mpath, so preempt a path
> - * refresh if this mpath expires soon.
> + * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame and
> + * insert the correct outgoing interface on the skb cb. Calling this function
> + * is considered "using" the associated mpath, so preempt a path refresh if
> + * this mpath expires soon.

This is of course completely bogus kernel-doc :)

johannes

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Bob Copeland May 7, 2013, 2:11 p.m. UTC | #2
On Tue, May 07, 2013 at 03:40:45PM +0200, Johannes Berg wrote:
> >  /**
> > + * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame and
> > + * insert the correct outgoing interface on the skb cb. Calling this function
> > + * is considered "using" the associated mpath, so preempt a path refresh if
> > + * this mpath expires soon.
> 
> This is of course completely bogus kernel-doc :)

Ack, thanks.
diff mbox

Patch

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 1f51bdf..76e9575 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1605,8 +1605,8 @@  static int ieee80211_change_mpath(struct wiphy *wiphy,
 		return -ENOENT;
 	}
 
-	mpath = mesh_path_lookup(sdata, dst);
-	if (!mpath) {
+	mpath = mesh_path_lookup(mbss(sdata), dst);
+	if (!mpath || mpath->sdata != sdata) {
 		rcu_read_unlock();
 		return -ENOENT;
 	}
@@ -1669,8 +1669,8 @@  static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
 	rcu_read_lock();
-	mpath = mesh_path_lookup(sdata, dst);
-	if (!mpath) {
+	mpath = mesh_path_lookup(mbss(sdata), dst);
+	if (!mpath || mpath->sdata != sdata) {
 		rcu_read_unlock();
 		return -ENOENT;
 	}
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 4a1a15e..2f83e8c 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -258,14 +258,14 @@  void ieee80211_mps_frame_release(struct sta_info *sta,
 				 struct ieee802_11_elems *elems);
 
 /* Mesh paths */
-int mesh_nexthop_lookup(struct ieee80211_sub_if_data *sdata,
+int mesh_nexthop_lookup(struct mesh_local_bss *mbss,
 			struct sk_buff *skb);
 int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata,
 			 struct sk_buff *skb);
 void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata);
-struct mesh_path *mesh_path_lookup(struct ieee80211_sub_if_data *sdata,
+struct mesh_path *mesh_path_lookup(struct mesh_local_bss *mbss,
 				   const u8 *dst);
-struct mesh_path *mpp_path_lookup(struct ieee80211_sub_if_data *sdata,
+struct mesh_path *mpp_path_lookup(struct mesh_local_bss *mbss,
 				  const u8 *dst);
 int mpp_path_add(struct ieee80211_sub_if_data *sdata,
 		 const u8 *dst, const u8 *mpp);
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 486819c..d8eaccc 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -101,14 +101,14 @@  enum mpath_frame_type {
 
 static const u8 broadcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
-static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
-				  const u8 *orig_addr, __le32 orig_sn,
-				  u8 target_flags, const u8 *target,
-				  __le32 target_sn, const u8 *da,
-				  u8 hop_count, u8 ttl,
-				  __le32 lifetime, __le32 metric,
-				  __le32 preq_id,
-				  struct ieee80211_sub_if_data *sdata)
+static int __mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
+				    const u8 *orig_addr, __le32 orig_sn,
+				    u8 target_flags, const u8 *target,
+				    __le32 target_sn, const u8 *da,
+				    u8 hop_count, u8 ttl,
+				    __le32 lifetime, __le32 metric,
+				    __le32 preq_id,
+				    struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_local *local = sdata->local;
 	struct sk_buff *skb;
@@ -201,6 +201,38 @@  static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
 	return 0;
 }
 
+static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
+				    const u8 *orig_addr, __le32 orig_sn,
+				    u8 target_flags, const u8 *target,
+				    __le32 target_sn, const u8 *da,
+				    u8 hop_count, u8 ttl,
+				    __le32 lifetime, __le32 metric,
+				    __le32 preq_id,
+				    struct ieee80211_sub_if_data *sdata)
+{
+	struct mesh_local_bss *mbss = mbss(sdata);
+	struct ieee80211_sub_if_data *tmp_sdata;
+	bool broadcast = is_broadcast_ether_addr(da);
+	struct sta_info *sta;
+	int ret = 0;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(tmp_sdata, &mbss->if_list, u.mesh.if_list) {
+		if (!broadcast) {
+			/* find right outgoing interface */
+			sta = sta_info_get(tmp_sdata, da);
+			if (!sta)
+				continue;
+		}
+		ret = __mesh_path_sel_frame_tx(action, flags, orig_addr,
+				orig_sn, target_flags, target, target_sn,
+				da, hop_count, ttl, lifetime, metric,
+				preq_id, tmp_sdata);
+	}
+	rcu_read_unlock();
+	return ret;
+}
+
 
 /*  Headroom is not adjusted.  Caller should ensure that skb has sufficient
  *  headroom in case the frame is encrypted. */
@@ -302,6 +334,8 @@  int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
 	ifmsh->next_perr = TU_TO_EXP_TIME(
 				   ifmsh->mshcfg.dot11MeshHWMPperrMinInterval);
 	ieee80211_add_pending_skb(local, skb);
+	if (is_multicast_ether_addr(mgmt->da))
+		mesh_bss_forward_tx(sdata, skb);
 	return 0;
 }
 
@@ -376,6 +410,7 @@  static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
 			       const u8 *hwmp_ie, enum mpath_frame_type action)
 {
 	struct ieee80211_local *local = sdata->local;
+	struct mesh_local_bss *mbss = mbss(sdata);
 	struct mesh_path *mpath;
 	struct sta_info *sta;
 	bool fresh_info;
@@ -423,14 +458,14 @@  static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
 		new_metric = MAX_METRIC;
 	exp_time = TU_TO_EXP_TIME(orig_lifetime);
 
-	if (ether_addr_equal(orig_addr, sdata->vif.addr)) {
+	if (mesh_bss_matches_addr(mbss, orig_addr)) {
 		/* This MP is the originator, we are not interested in this
 		 * frame, except for updating transmitter's path info.
 		 */
 		process = false;
 		fresh_info = false;
 	} else {
-		mpath = mesh_path_lookup(sdata, orig_addr);
+		mpath = mesh_path_lookup(mbss, orig_addr);
 		if (mpath) {
 			spin_lock_bh(&mpath->state_lock);
 			if (mpath->flags & MESH_PATH_FIXED)
@@ -477,7 +512,7 @@  static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
 	else {
 		fresh_info = true;
 
-		mpath = mesh_path_lookup(sdata, ta);
+		mpath = mesh_path_lookup(mbss, ta);
 		if (mpath) {
 			spin_lock_bh(&mpath->state_lock);
 			if ((mpath->flags & MESH_PATH_FIXED) ||
@@ -515,6 +550,7 @@  static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
 				    const u8 *preq_elem, u32 metric)
 {
 	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+	struct mesh_local_bss *mbss = mbss(sdata);
 	struct mesh_path *mpath = NULL;
 	const u8 *target_addr, *orig_addr;
 	const u8 *da;
@@ -537,7 +573,7 @@  static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
 
 	mhwmp_dbg(sdata, "received PREQ from %pM\n", orig_addr);
 
-	if (ether_addr_equal(target_addr, sdata->vif.addr)) {
+	if (mesh_bss_matches_addr(mbss, target_addr)) {
 		mhwmp_dbg(sdata, "PREQ is for us\n");
 		forward = false;
 		reply = true;
@@ -551,7 +587,7 @@  static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
 	} else if (is_broadcast_ether_addr(target_addr) &&
 		   (target_flags & IEEE80211_PREQ_TO_FLAG)) {
 		rcu_read_lock();
-		mpath = mesh_path_lookup(sdata, orig_addr);
+		mpath = mesh_path_lookup(mbss, orig_addr);
 		if (mpath) {
 			if (flags & IEEE80211_PREQ_PROACTIVE_PREP_FLAG) {
 				reply = true;
@@ -566,7 +602,7 @@  static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
 		rcu_read_unlock();
 	} else {
 		rcu_read_lock();
-		mpath = mesh_path_lookup(sdata, target_addr);
+		mpath = mesh_path_lookup(mbss, target_addr);
 		if (mpath) {
 			if ((!(mpath->flags & MESH_PATH_SN_VALID)) ||
 					SN_LT(mpath->sn, target_sn)) {
@@ -646,12 +682,12 @@  next_hop_deref_protected(struct mesh_path *mpath)
 					 lockdep_is_held(&mpath->state_lock));
 }
 
-
 static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
 				    struct ieee80211_mgmt *mgmt,
 				    const u8 *prep_elem, u32 metric)
 {
 	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+	struct mesh_local_bss *mbss = mbss(sdata);
 	struct mesh_path *mpath;
 	const u8 *target_addr, *orig_addr;
 	u8 ttl, hopcount, flags;
@@ -662,7 +698,7 @@  static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
 		  PREP_IE_TARGET_ADDR(prep_elem));
 
 	orig_addr = PREP_IE_ORIG_ADDR(prep_elem);
-	if (ether_addr_equal(orig_addr, sdata->vif.addr))
+	if (mesh_bss_matches_addr(mbss, orig_addr))
 		/* destination, no forwarding required */
 		return;
 
@@ -676,7 +712,7 @@  static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
 	}
 
 	rcu_read_lock();
-	mpath = mesh_path_lookup(sdata, orig_addr);
+	mpath = mesh_path_lookup(mbss, orig_addr);
 	if (mpath)
 		spin_lock_bh(&mpath->state_lock);
 	else
@@ -734,7 +770,7 @@  static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata,
 	target_rcode = PERR_IE_TARGET_RCODE(perr_elem);
 
 	rcu_read_lock();
-	mpath = mesh_path_lookup(sdata, target_addr);
+	mpath = mesh_path_lookup(mbss(sdata), target_addr);
 	if (mpath) {
 		struct sta_info *sta;
 
@@ -766,6 +802,7 @@  static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
 {
 	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
 	struct ieee80211_local *local = sdata->local;
+	struct mesh_local_bss *mbss = mbss(sdata);
 	struct sta_info *sta;
 	struct mesh_path *mpath;
 	u8 ttl, flags, hopcount;
@@ -784,7 +821,7 @@  static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
 	metric = le32_to_cpu(rann->rann_metric);
 
 	/*  Ignore our own RANNs */
-	if (ether_addr_equal(orig_addr, sdata->vif.addr))
+	if (mesh_bss_matches_addr(mbss, orig_addr))
 		return;
 
 	mhwmp_dbg(sdata,
@@ -800,7 +837,7 @@  static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
 
 	metric_txsta = airtime_link_metric_get(local, sta);
 
-	mpath = mesh_path_lookup(sdata, orig_addr);
+	mpath = mesh_path_lookup(mbss, orig_addr);
 	if (!mpath) {
 		mpath = mesh_path_add(sdata, orig_addr);
 		if (IS_ERR(mpath)) {
@@ -982,6 +1019,7 @@  static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
 void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+	struct mesh_local_bss *mbss = mbss(sdata);
 	struct mesh_preq_queue *preq_node;
 	struct mesh_path *mpath;
 	u8 ttl, target_flags;
@@ -1003,7 +1041,7 @@  void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
 	spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
 
 	rcu_read_lock();
-	mpath = mesh_path_lookup(sdata, preq_node->dst);
+	mpath = mesh_path_lookup(mbss, preq_node->dst);
 	if (!mpath)
 		goto enddiscovery;
 
@@ -1078,6 +1116,7 @@  int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata,
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct mesh_local_bss *mbss = mbss(sdata);
 	struct mesh_path *mpath;
 	struct sk_buff *skb_to_free = NULL;
 	u8 *target_addr = hdr->addr3;
@@ -1088,12 +1127,12 @@  int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata,
 		return 0;
 
 	rcu_read_lock();
-	err = mesh_nexthop_lookup(sdata, skb);
+	err = mesh_nexthop_lookup(mbss, skb);
 	if (!err)
 		goto endlookup;
 
 	/* no nexthop found, start resolving */
-	mpath = mesh_path_lookup(sdata, target_addr);
+	mpath = mesh_path_lookup(mbss, target_addr);
 	if (!mpath) {
 		mpath = mesh_path_add(sdata, target_addr);
 		if (IS_ERR(mpath)) {
@@ -1122,46 +1161,54 @@  endlookup:
 }
 
 /**
- * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame. Calling
- * this function is considered "using" the associated mpath, so preempt a path
- * refresh if this mpath expires soon.
+ * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame and
+ * insert the correct outgoing interface on the skb cb. Calling this function
+ * is considered "using" the associated mpath, so preempt a path refresh if
+ * this mpath expires soon.
  *
  * @skb: 802.11 frame to be sent
- * @sdata: network subif the frame will be sent through
+ * @mbss: MBSS in which to find a path
  *
  * Returns: 0 if the next hop was found. Nonzero otherwise.
  */
-int mesh_nexthop_lookup(struct ieee80211_sub_if_data *sdata,
+int mesh_nexthop_lookup(struct mesh_local_bss *mbss,
 			struct sk_buff *skb)
 {
+	struct ieee80211_sub_if_data *sdata = NULL;
 	struct mesh_path *mpath;
 	struct sta_info *next_hop;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct ieee80211_tx_info *info;
 	u8 *target_addr = hdr->addr3;
 	int err = -ENOENT;
 
 	rcu_read_lock();
-	mpath = mesh_path_lookup(sdata, target_addr);
+	mpath = mesh_path_lookup(mbss, target_addr);
 
 	if (!mpath || !(mpath->flags & MESH_PATH_ACTIVE))
 		goto endlookup;
 
-	if (time_after(jiffies,
-		       mpath->exp_time -
-		       msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) &&
-	    ether_addr_equal(sdata->vif.addr, hdr->addr4) &&
-	    !(mpath->flags & MESH_PATH_RESOLVING) &&
-	    !(mpath->flags & MESH_PATH_FIXED))
-		mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
-
 	next_hop = rcu_dereference(mpath->next_hop);
 	if (next_hop) {
+		info = IEEE80211_SKB_CB(skb);
+		sdata = mpath->sdata;
+		info->control.vif = &sdata->vif;
 		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);
 		err = 0;
 	}
 
+	if (sdata &&
+	    time_after(jiffies,
+		       mpath->exp_time -
+		       msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) &&
+	    ether_addr_equal(sdata->vif.addr, hdr->addr4) &&
+	    !(mpath->flags & MESH_PATH_RESOLVING) &&
+	    !(mpath->flags & MESH_PATH_FIXED))
+		mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
+
+
 endlookup:
 	rcu_read_unlock();
 	return err;
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 89aacfd..993a270 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -184,11 +184,11 @@  errcopy:
 	return -ENOMEM;
 }
 
-static u32 mesh_table_hash(const u8 *addr, struct ieee80211_sub_if_data *sdata,
+static u32 mesh_table_hash(struct mesh_local_bss *mbss, const u8 *addr,
 			   struct mesh_table *tbl)
 {
-	/* Use last four bytes of hw addr and interface index as hash index */
-	return jhash_2words(*(u32 *)(addr+2), sdata->dev->ifindex,
+	/* Use last four bytes of hw addr and first four of meshid */
+	return jhash_2words(*(u32 *)(addr+2), *(u32 *) mbss->mesh_id,
 			    tbl->hash_rnd) & tbl->hash_mask;
 }
 
@@ -328,15 +328,14 @@  static void mesh_path_move_to_queue(struct mesh_path *gate_mpath,
 	spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags);
 }
 
-
-static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst,
-				      struct ieee80211_sub_if_data *sdata)
+static struct mesh_path *__mpath_lookup(struct mesh_table *tbl, const u8 *dst,
+					struct ieee80211_sub_if_data *sdata)
 {
 	struct mesh_path *mpath;
 	struct hlist_head *bucket;
 	struct mpath_node *node;
 
-	bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)];
+	bucket = &tbl->hash_buckets[mesh_table_hash(mbss(sdata), dst, tbl)];
 	hlist_for_each_entry_rcu(node, bucket, list) {
 		mpath = node->mpath;
 		if (mpath->sdata == sdata &&
@@ -352,9 +351,25 @@  static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst,
 	return NULL;
 }
 
+static struct mesh_path *mpath_lookup(struct mesh_table *tbl,
+				      struct mesh_local_bss *mbss,
+				      const u8 *dst)
+{
+	struct ieee80211_sub_if_data *sdata;
+	struct mesh_path *mpath;
+
+	list_for_each_entry_rcu(sdata, &mbss->if_list, u.mesh.if_list) {
+		mpath = __mpath_lookup(tbl, dst, sdata);
+		if (mpath)
+			return mpath;
+	}
+	return NULL;
+}
+
 /**
  * mesh_path_lookup - look up a path in the mesh path table
- * @sdata: local subif
+ *
+ * @mbss: MBSS where this destination might be found
  * @dst: hardware address (ETH_ALEN length) of destination
  *
  * Returns: pointer to the mesh path structure, or NULL if not found
@@ -362,15 +377,15 @@  static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst,
  * Locking: must be called within a read rcu section.
  */
 struct mesh_path *
-mesh_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst)
+mesh_path_lookup(struct mesh_local_bss *mbss, const u8 *dst)
 {
-	return mpath_lookup(rcu_dereference(mesh_paths), dst, sdata);
+	return mpath_lookup(rcu_dereference(mesh_paths), mbss, dst);
 }
 
 struct mesh_path *
-mpp_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst)
+mpp_path_lookup(struct mesh_local_bss *mbss, const u8 *dst)
 {
-	return mpath_lookup(rcu_dereference(mpp_paths), dst, sdata);
+	return mpath_lookup(rcu_dereference(mpp_paths), mbss, dst);
 }
 
 
@@ -519,7 +534,7 @@  struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
 	read_lock_bh(&pathtbl_resize_lock);
 	tbl = resize_dereference_mesh_paths();
 
-	hash_idx = mesh_table_hash(dst, sdata, tbl);
+	hash_idx = mesh_table_hash(mbss(sdata), dst, tbl);
 	bucket = &tbl->hash_buckets[hash_idx];
 
 	spin_lock(&tbl->hashwlock[hash_idx]);
@@ -669,7 +684,7 @@  int mpp_path_add(struct ieee80211_sub_if_data *sdata,
 
 	tbl = resize_dereference_mpp_paths();
 
-	hash_idx = mesh_table_hash(dst, sdata, tbl);
+	hash_idx = mesh_table_hash(mbss(sdata), dst, tbl);
 	bucket = &tbl->hash_buckets[hash_idx];
 
 	spin_lock(&tbl->hashwlock[hash_idx]);
@@ -862,7 +877,7 @@  int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)
 
 	read_lock_bh(&pathtbl_resize_lock);
 	tbl = resize_dereference_mesh_paths();
-	hash_idx = mesh_table_hash(addr, sdata, tbl);
+	hash_idx = mesh_table_hash(mbss(sdata), addr, tbl);
 	bucket = &tbl->hash_buckets[hash_idx];
 
 	spin_lock(&tbl->hashwlock[hash_idx]);
@@ -1028,7 +1043,7 @@  static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl)
 	node = hlist_entry(p, struct mpath_node, list);
 	mpath = node->mpath;
 	new_node->mpath = mpath;
-	hash_idx = mesh_table_hash(mpath->dst, mpath->sdata, newtbl);
+	hash_idx = mesh_table_hash(mbss(mpath->sdata), mpath->dst, newtbl);
 	hlist_add_head(&new_node->list,
 			&newtbl->hash_buckets[hash_idx]);
 	return 0;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 22e412b..4e7886d 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2006,6 +2006,7 @@  ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
 	struct sk_buff *skb = rx->skb, *fwd_skb;
 	struct ieee80211_local *local = rx->local;
 	struct ieee80211_sub_if_data *sdata = rx->sdata;
+	struct mesh_local_bss *mbss = mbss(sdata);
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
 	__le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_NOFORWARD);
@@ -2059,7 +2060,7 @@  ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
 		}
 
 		rcu_read_lock();
-		mppath = mpp_path_lookup(sdata, proxied_addr);
+		mppath = mpp_path_lookup(mbss, proxied_addr);
 		if (!mppath) {
 			mpp_path_add(sdata, proxied_addr, mpp_addr);
 		} else {
@@ -2110,7 +2111,7 @@  ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
 		memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN);
 		/* update power mode indication when forwarding */
 		ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr);
-	} else if (!mesh_nexthop_lookup(sdata, fwd_skb)) {
+	} else if (!mesh_nexthop_lookup(mbss, fwd_skb)) {
 		/* mesh power mode flags updated in mesh_nexthop_lookup */
 		IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast);
 	} else {
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 4a5fbf8..c132c76 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1799,7 +1799,7 @@  netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 			struct sta_info *next_hop;
 			bool mpp_lookup = true;
 
-			mpath = mesh_path_lookup(sdata, skb->data);
+			mpath = mesh_path_lookup(mbss(sdata), skb->data);
 			if (mpath) {
 				mpp_lookup = false;
 				next_hop = rcu_dereference(mpath->next_hop);
@@ -1810,7 +1810,8 @@  netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 			}
 
 			if (mpp_lookup)
-				mppath = mpp_path_lookup(sdata, skb->data);
+				mppath = mpp_path_lookup(mbss(sdata),
+							 skb->data);
 
 			if (mppath && mpath)
 				mesh_path_del(mpath->sdata, mpath->dst);