diff options
Diffstat (limited to 'net/mac80211/mesh_hwmp.c')
-rw-r--r-- | net/mac80211/mesh_hwmp.c | 42 |
1 files changed, 20 insertions, 22 deletions
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 5bf64d7112b3..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, | |||
391 | (mpath->flags & MESH_PATH_SN_VALID)) { | 391 | (mpath->flags & MESH_PATH_SN_VALID)) { |
392 | if (SN_GT(mpath->sn, orig_sn) || | 392 | if (SN_GT(mpath->sn, orig_sn) || |
393 | (mpath->sn == orig_sn && | 393 | (mpath->sn == orig_sn && |
394 | action == MPATH_PREQ && | ||
395 | new_metric >= mpath->metric)) { | 394 | new_metric >= mpath->metric)) { |
396 | process = false; | 395 | process = false; |
397 | fresh_info = false; | 396 | fresh_info = false; |
@@ -561,6 +560,14 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
561 | } | 560 | } |
562 | 561 | ||
563 | 562 | ||
563 | static inline struct sta_info * | ||
564 | next_hop_deref_protected(struct mesh_path *mpath) | ||
565 | { | ||
566 | return rcu_dereference_protected(mpath->next_hop, | ||
567 | lockdep_is_held(&mpath->state_lock)); | ||
568 | } | ||
569 | |||
570 | |||
564 | static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, | 571 | static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, |
565 | struct ieee80211_mgmt *mgmt, | 572 | struct ieee80211_mgmt *mgmt, |
566 | u8 *prep_elem, u32 metric) | 573 | u8 *prep_elem, u32 metric) |
@@ -600,7 +607,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, | |||
600 | spin_unlock_bh(&mpath->state_lock); | 607 | spin_unlock_bh(&mpath->state_lock); |
601 | goto fail; | 608 | goto fail; |
602 | } | 609 | } |
603 | memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN); | 610 | memcpy(next_hop, next_hop_deref_protected(mpath)->sta.addr, ETH_ALEN); |
604 | spin_unlock_bh(&mpath->state_lock); | 611 | spin_unlock_bh(&mpath->state_lock); |
605 | --ttl; | 612 | --ttl; |
606 | flags = PREP_IE_FLAGS(prep_elem); | 613 | flags = PREP_IE_FLAGS(prep_elem); |
@@ -633,7 +640,6 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, | |||
633 | struct mesh_path *mpath; | 640 | struct mesh_path *mpath; |
634 | u8 ttl; | 641 | u8 ttl; |
635 | u8 *ta, *target_addr; | 642 | u8 *ta, *target_addr; |
636 | u8 target_flags; | ||
637 | u32 target_sn; | 643 | u32 target_sn; |
638 | u16 target_rcode; | 644 | u16 target_rcode; |
639 | 645 | ||
@@ -644,7 +650,6 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, | |||
644 | return; | 650 | return; |
645 | } | 651 | } |
646 | ttl--; | 652 | ttl--; |
647 | target_flags = PERR_IE_TARGET_FLAGS(perr_elem); | ||
648 | target_addr = PERR_IE_TARGET_ADDR(perr_elem); | 653 | target_addr = PERR_IE_TARGET_ADDR(perr_elem); |
649 | target_sn = PERR_IE_TARGET_SN(perr_elem); | 654 | target_sn = PERR_IE_TARGET_SN(perr_elem); |
650 | target_rcode = PERR_IE_TARGET_RCODE(perr_elem); | 655 | target_rcode = PERR_IE_TARGET_RCODE(perr_elem); |
@@ -654,7 +659,8 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, | |||
654 | if (mpath) { | 659 | if (mpath) { |
655 | spin_lock_bh(&mpath->state_lock); | 660 | spin_lock_bh(&mpath->state_lock); |
656 | if (mpath->flags & MESH_PATH_ACTIVE && | 661 | if (mpath->flags & MESH_PATH_ACTIVE && |
657 | memcmp(ta, mpath->next_hop->sta.addr, ETH_ALEN) == 0 && | 662 | memcmp(ta, next_hop_deref_protected(mpath)->sta.addr, |
663 | ETH_ALEN) == 0 && | ||
658 | (!(mpath->flags & MESH_PATH_SN_VALID) || | 664 | (!(mpath->flags & MESH_PATH_SN_VALID) || |
659 | SN_GT(target_sn, mpath->sn))) { | 665 | SN_GT(target_sn, mpath->sn))) { |
660 | mpath->flags &= ~MESH_PATH_ACTIVE; | 666 | mpath->flags &= ~MESH_PATH_ACTIVE; |
@@ -675,12 +681,10 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
675 | { | 681 | { |
676 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 682 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
677 | struct mesh_path *mpath; | 683 | struct mesh_path *mpath; |
678 | u8 *ta; | ||
679 | u8 ttl, flags, hopcount; | 684 | u8 ttl, flags, hopcount; |
680 | u8 *orig_addr; | 685 | u8 *orig_addr; |
681 | u32 orig_sn, metric; | 686 | u32 orig_sn, metric; |
682 | 687 | ||
683 | ta = mgmt->sa; | ||
684 | ttl = rann->rann_ttl; | 688 | ttl = rann->rann_ttl; |
685 | if (ttl <= 1) { | 689 | if (ttl <= 1) { |
686 | ifmsh->mshstats.dropped_frames_ttl++; | 690 | ifmsh->mshstats.dropped_frames_ttl++; |
@@ -918,6 +922,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, | |||
918 | { | 922 | { |
919 | struct sk_buff *skb_to_free = NULL; | 923 | struct sk_buff *skb_to_free = NULL; |
920 | struct mesh_path *mpath; | 924 | struct mesh_path *mpath; |
925 | struct sta_info *next_hop; | ||
921 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 926 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
922 | u8 *target_addr = hdr->addr3; | 927 | u8 *target_addr = hdr->addr3; |
923 | int err = 0; | 928 | int err = 0; |
@@ -945,7 +950,11 @@ int mesh_nexthop_lookup(struct sk_buff *skb, | |||
945 | mesh_queue_preq(mpath, | 950 | mesh_queue_preq(mpath, |
946 | PREQ_Q_F_START | PREQ_Q_F_REFRESH); | 951 | PREQ_Q_F_START | PREQ_Q_F_REFRESH); |
947 | } | 952 | } |
948 | memcpy(hdr->addr1, mpath->next_hop->sta.addr, ETH_ALEN); | 953 | next_hop = rcu_dereference(mpath->next_hop); |
954 | if (next_hop) | ||
955 | memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN); | ||
956 | else | ||
957 | err = -ENOENT; | ||
949 | } else { | 958 | } else { |
950 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 959 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
951 | if (!(mpath->flags & MESH_PATH_RESOLVING)) { | 960 | if (!(mpath->flags & MESH_PATH_RESOLVING)) { |
@@ -971,20 +980,11 @@ endlookup: | |||
971 | 980 | ||
972 | void mesh_path_timer(unsigned long data) | 981 | void mesh_path_timer(unsigned long data) |
973 | { | 982 | { |
974 | struct ieee80211_sub_if_data *sdata; | 983 | struct mesh_path *mpath = (void *) data; |
975 | struct mesh_path *mpath; | 984 | struct ieee80211_sub_if_data *sdata = mpath->sdata; |
976 | |||
977 | rcu_read_lock(); | ||
978 | mpath = (struct mesh_path *) data; | ||
979 | mpath = rcu_dereference(mpath); | ||
980 | if (!mpath) | ||
981 | goto endmpathtimer; | ||
982 | sdata = mpath->sdata; | ||
983 | 985 | ||
984 | if (sdata->local->quiescing) { | 986 | if (sdata->local->quiescing) |
985 | rcu_read_unlock(); | ||
986 | return; | 987 | return; |
987 | } | ||
988 | 988 | ||
989 | spin_lock_bh(&mpath->state_lock); | 989 | spin_lock_bh(&mpath->state_lock); |
990 | if (mpath->flags & MESH_PATH_RESOLVED || | 990 | if (mpath->flags & MESH_PATH_RESOLVED || |
@@ -1001,8 +1001,6 @@ void mesh_path_timer(unsigned long data) | |||
1001 | } | 1001 | } |
1002 | 1002 | ||
1003 | spin_unlock_bh(&mpath->state_lock); | 1003 | spin_unlock_bh(&mpath->state_lock); |
1004 | endmpathtimer: | ||
1005 | rcu_read_unlock(); | ||
1006 | } | 1004 | } |
1007 | 1005 | ||
1008 | void | 1006 | void |