diff options
Diffstat (limited to 'net/mac80211/mesh_hwmp.c')
-rw-r--r-- | net/mac80211/mesh_hwmp.c | 51 |
1 files changed, 25 insertions, 26 deletions
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 829e08a657d0..2b18053070c1 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -232,7 +232,7 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, | |||
232 | *pos++ = WLAN_EID_PERR; | 232 | *pos++ = WLAN_EID_PERR; |
233 | *pos++ = ie_len; | 233 | *pos++ = ie_len; |
234 | /* ttl */ | 234 | /* ttl */ |
235 | *pos++ = MESH_TTL; | 235 | *pos++ = ttl; |
236 | /* number of destinations */ | 236 | /* number of destinations */ |
237 | *pos++ = 1; | 237 | *pos++ = 1; |
238 | /* | 238 | /* |
@@ -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; |
@@ -522,7 +521,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
522 | 521 | ||
523 | if (reply) { | 522 | if (reply) { |
524 | lifetime = PREQ_IE_LIFETIME(preq_elem); | 523 | lifetime = PREQ_IE_LIFETIME(preq_elem); |
525 | ttl = ifmsh->mshcfg.dot11MeshTTL; | 524 | ttl = ifmsh->mshcfg.element_ttl; |
526 | if (ttl != 0) { | 525 | if (ttl != 0) { |
527 | mhwmp_dbg("replying to the PREQ\n"); | 526 | mhwmp_dbg("replying to the PREQ\n"); |
528 | mesh_path_sel_frame_tx(MPATH_PREP, 0, target_addr, | 527 | mesh_path_sel_frame_tx(MPATH_PREP, 0, target_addr, |
@@ -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++; |
@@ -877,7 +881,7 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) | |||
877 | sdata->u.mesh.last_sn_update = jiffies; | 881 | sdata->u.mesh.last_sn_update = jiffies; |
878 | } | 882 | } |
879 | lifetime = default_lifetime(sdata); | 883 | lifetime = default_lifetime(sdata); |
880 | ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; | 884 | ttl = sdata->u.mesh.mshcfg.element_ttl; |
881 | if (ttl == 0) { | 885 | if (ttl == 0) { |
882 | sdata->u.mesh.mshstats.dropped_frames_ttl++; | 886 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
883 | spin_unlock_bh(&mpath->state_lock); | 887 | spin_unlock_bh(&mpath->state_lock); |
@@ -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 |
@@ -1013,5 +1011,6 @@ mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) | |||
1013 | mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr, | 1011 | mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr, |
1014 | cpu_to_le32(++ifmsh->sn), | 1012 | cpu_to_le32(++ifmsh->sn), |
1015 | 0, NULL, 0, broadcast_addr, | 1013 | 0, NULL, 0, broadcast_addr, |
1016 | 0, MESH_TTL, 0, 0, 0, sdata); | 1014 | 0, sdata->u.mesh.mshcfg.element_ttl, |
1015 | 0, 0, 0, sdata); | ||
1017 | } | 1016 | } |