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 | } |
