diff options
Diffstat (limited to 'net/mac80211/mesh_hwmp.c')
-rw-r--r-- | net/mac80211/mesh_hwmp.c | 38 |
1 files changed, 20 insertions, 18 deletions
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index e57f2e728cfe..2b18053070c1 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -391,7 +391,6 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, (mpath->flags & MESH_PATH_SN_VALID)) { if (SN_GT(mpath->sn, orig_sn) || (mpath->sn == orig_sn && - action == MPATH_PREQ && new_metric >= mpath->metric)) { process = false; fresh_info = false; @@ -561,6 +560,14 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, } +static inline struct sta_info * +next_hop_deref_protected(struct mesh_path *mpath) +{ + return rcu_dereference_protected(mpath->next_hop, + lockdep_is_held(&mpath->state_lock)); +} + + static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, u8 *prep_elem, u32 metric) @@ -600,7 +607,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, spin_unlock_bh(&mpath->state_lock); goto fail; } - memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN); + memcpy(next_hop, next_hop_deref_protected(mpath)->sta.addr, ETH_ALEN); spin_unlock_bh(&mpath->state_lock); --ttl; flags = PREP_IE_FLAGS(prep_elem); @@ -652,7 +659,8 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, if (mpath) { spin_lock_bh(&mpath->state_lock); if (mpath->flags & MESH_PATH_ACTIVE && - memcmp(ta, mpath->next_hop->sta.addr, ETH_ALEN) == 0 && + memcmp(ta, next_hop_deref_protected(mpath)->sta.addr, + ETH_ALEN) == 0 && (!(mpath->flags & MESH_PATH_SN_VALID) || SN_GT(target_sn, mpath->sn))) { mpath->flags &= ~MESH_PATH_ACTIVE; @@ -914,6 +922,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, { struct sk_buff *skb_to_free = NULL; struct mesh_path *mpath; + struct sta_info *next_hop; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; u8 *target_addr = hdr->addr3; int err = 0; @@ -941,7 +950,11 @@ int mesh_nexthop_lookup(struct sk_buff *skb, mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); } - memcpy(hdr->addr1, mpath->next_hop->sta.addr, ETH_ALEN); + next_hop = rcu_dereference(mpath->next_hop); + if (next_hop) + memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN); + else + err = -ENOENT; } else { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); if (!(mpath->flags & MESH_PATH_RESOLVING)) { @@ -967,20 +980,11 @@ endlookup: void mesh_path_timer(unsigned long data) { - struct ieee80211_sub_if_data *sdata; - struct mesh_path *mpath; - - rcu_read_lock(); - mpath = (struct mesh_path *) data; - mpath = rcu_dereference(mpath); - if (!mpath) - goto endmpathtimer; - sdata = mpath->sdata; + struct mesh_path *mpath = (void *) data; + struct ieee80211_sub_if_data *sdata = mpath->sdata; - if (sdata->local->quiescing) { - rcu_read_unlock(); + if (sdata->local->quiescing) return; - } spin_lock_bh(&mpath->state_lock); if (mpath->flags & MESH_PATH_RESOLVED || @@ -997,8 +1001,6 @@ void mesh_path_timer(unsigned long data) } spin_unlock_bh(&mpath->state_lock); -endmpathtimer: - rcu_read_unlock(); } void |