From: Bob Copeland <[email protected]>

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 <[email protected]>
---
 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(-)

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);
-- 
1.7.10.4

_______________________________________________
Devel mailing list
[email protected]
http://lists.open80211s.org/cgi-bin/mailman/listinfo/devel

Reply via email to