aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mesh_hwmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mesh_hwmp.c')
-rw-r--r--net/mac80211/mesh_hwmp.c177
1 files changed, 127 insertions, 50 deletions
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 3460108810d..174040a4288 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -8,10 +8,12 @@
8 */ 8 */
9 9
10#include <linux/slab.h> 10#include <linux/slab.h>
11#include "wme.h"
11#include "mesh.h" 12#include "mesh.h"
12 13
13#ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG 14#ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG
14#define mhwmp_dbg(fmt, args...) printk(KERN_DEBUG "Mesh HWMP: " fmt, ##args) 15#define mhwmp_dbg(fmt, args...) \
16 printk(KERN_DEBUG "Mesh HWMP (%s): " fmt "\n", sdata->name, ##args)
15#else 17#else
16#define mhwmp_dbg(fmt, args...) do { (void)(0); } while (0) 18#define mhwmp_dbg(fmt, args...) do { (void)(0); } while (0)
17#endif 19#endif
@@ -68,12 +70,12 @@ static inline u32 u16_field_get(u8 *preq_elem, int offset, bool ae)
68#define PREP_IE_FLAGS(x) PREQ_IE_FLAGS(x) 70#define PREP_IE_FLAGS(x) PREQ_IE_FLAGS(x)
69#define PREP_IE_HOPCOUNT(x) PREQ_IE_HOPCOUNT(x) 71#define PREP_IE_HOPCOUNT(x) PREQ_IE_HOPCOUNT(x)
70#define PREP_IE_TTL(x) PREQ_IE_TTL(x) 72#define PREP_IE_TTL(x) PREQ_IE_TTL(x)
71#define PREP_IE_ORIG_ADDR(x) (x + 3) 73#define PREP_IE_ORIG_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21)
72#define PREP_IE_ORIG_SN(x) u32_field_get(x, 9, 0) 74#define PREP_IE_ORIG_SN(x) u32_field_get(x, 27, AE_F_SET(x))
73#define PREP_IE_LIFETIME(x) u32_field_get(x, 13, AE_F_SET(x)) 75#define PREP_IE_LIFETIME(x) u32_field_get(x, 13, AE_F_SET(x))
74#define PREP_IE_METRIC(x) u32_field_get(x, 17, AE_F_SET(x)) 76#define PREP_IE_METRIC(x) u32_field_get(x, 17, AE_F_SET(x))
75#define PREP_IE_TARGET_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21) 77#define PREP_IE_TARGET_ADDR(x) (x + 3)
76#define PREP_IE_TARGET_SN(x) u32_field_get(x, 27, AE_F_SET(x)) 78#define PREP_IE_TARGET_SN(x) u32_field_get(x, 9, 0)
77 79
78#define PERR_IE_TTL(x) (*(x)) 80#define PERR_IE_TTL(x) (*(x))
79#define PERR_IE_TARGET_FLAGS(x) (*(x + 2)) 81#define PERR_IE_TARGET_FLAGS(x) (*(x + 2))
@@ -132,24 +134,25 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
132 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); 134 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
133 /* BSSID == SA */ 135 /* BSSID == SA */
134 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); 136 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
135 mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL; 137 mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION;
136 mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; 138 mgmt->u.action.u.mesh_action.action_code =
139 WLAN_MESH_ACTION_HWMP_PATH_SELECTION;
137 140
138 switch (action) { 141 switch (action) {
139 case MPATH_PREQ: 142 case MPATH_PREQ:
140 mhwmp_dbg("sending PREQ to %pM\n", target); 143 mhwmp_dbg("sending PREQ to %pM", target);
141 ie_len = 37; 144 ie_len = 37;
142 pos = skb_put(skb, 2 + ie_len); 145 pos = skb_put(skb, 2 + ie_len);
143 *pos++ = WLAN_EID_PREQ; 146 *pos++ = WLAN_EID_PREQ;
144 break; 147 break;
145 case MPATH_PREP: 148 case MPATH_PREP:
146 mhwmp_dbg("sending PREP to %pM\n", target); 149 mhwmp_dbg("sending PREP to %pM", target);
147 ie_len = 31; 150 ie_len = 31;
148 pos = skb_put(skb, 2 + ie_len); 151 pos = skb_put(skb, 2 + ie_len);
149 *pos++ = WLAN_EID_PREP; 152 *pos++ = WLAN_EID_PREP;
150 break; 153 break;
151 case MPATH_RANN: 154 case MPATH_RANN:
152 mhwmp_dbg("sending RANN from %pM\n", orig_addr); 155 mhwmp_dbg("sending RANN from %pM", orig_addr);
153 ie_len = sizeof(struct ieee80211_rann_ie); 156 ie_len = sizeof(struct ieee80211_rann_ie);
154 pos = skb_put(skb, 2 + ie_len); 157 pos = skb_put(skb, 2 + ie_len);
155 *pos++ = WLAN_EID_RANN; 158 *pos++ = WLAN_EID_RANN;
@@ -163,35 +166,63 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
163 *pos++ = flags; 166 *pos++ = flags;
164 *pos++ = hop_count; 167 *pos++ = hop_count;
165 *pos++ = ttl; 168 *pos++ = ttl;
166 if (action == MPATH_PREQ) { 169 if (action == MPATH_PREP) {
167 memcpy(pos, &preq_id, 4); 170 memcpy(pos, target, ETH_ALEN);
171 pos += ETH_ALEN;
172 memcpy(pos, &target_sn, 4);
168 pos += 4; 173 pos += 4;
169 } 174 } else {
170 memcpy(pos, orig_addr, ETH_ALEN); 175 if (action == MPATH_PREQ) {
171 pos += ETH_ALEN; 176 memcpy(pos, &preq_id, 4);
172 memcpy(pos, &orig_sn, 4); 177 pos += 4;
173 pos += 4; 178 }
174 if (action != MPATH_RANN) { 179 memcpy(pos, orig_addr, ETH_ALEN);
175 memcpy(pos, &lifetime, 4); 180 pos += ETH_ALEN;
181 memcpy(pos, &orig_sn, 4);
176 pos += 4; 182 pos += 4;
177 } 183 }
184 memcpy(pos, &lifetime, 4); /* interval for RANN */
185 pos += 4;
178 memcpy(pos, &metric, 4); 186 memcpy(pos, &metric, 4);
179 pos += 4; 187 pos += 4;
180 if (action == MPATH_PREQ) { 188 if (action == MPATH_PREQ) {
181 /* destination count */ 189 *pos++ = 1; /* destination count */
182 *pos++ = 1;
183 *pos++ = target_flags; 190 *pos++ = target_flags;
184 }
185 if (action != MPATH_RANN) {
186 memcpy(pos, target, ETH_ALEN); 191 memcpy(pos, target, ETH_ALEN);
187 pos += ETH_ALEN; 192 pos += ETH_ALEN;
188 memcpy(pos, &target_sn, 4); 193 memcpy(pos, &target_sn, 4);
194 pos += 4;
195 } else if (action == MPATH_PREP) {
196 memcpy(pos, orig_addr, ETH_ALEN);
197 pos += ETH_ALEN;
198 memcpy(pos, &orig_sn, 4);
199 pos += 4;
189 } 200 }
190 201
191 ieee80211_tx_skb(sdata, skb); 202 ieee80211_tx_skb(sdata, skb);
192 return 0; 203 return 0;
193} 204}
194 205
206
207/* Headroom is not adjusted. Caller should ensure that skb has sufficient
208 * headroom in case the frame is encrypted. */
209static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata,
210 struct sk_buff *skb)
211{
212 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
213
214 skb_set_mac_header(skb, 0);
215 skb_set_network_header(skb, 0);
216 skb_set_transport_header(skb, 0);
217
218 /* Send all internal mgmt frames on VO. Accordingly set TID to 7. */
219 skb_set_queue_mapping(skb, IEEE80211_AC_VO);
220 skb->priority = 7;
221
222 info->control.vif = &sdata->vif;
223 ieee80211_set_qos_hdr(sdata, skb);
224}
225
195/** 226/**
196 * mesh_send_path error - Sends a PERR mesh management frame 227 * mesh_send_path error - Sends a PERR mesh management frame
197 * 228 *
@@ -199,6 +230,10 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
199 * @target_sn: SN of the broken destination 230 * @target_sn: SN of the broken destination
200 * @target_rcode: reason code for this PERR 231 * @target_rcode: reason code for this PERR
201 * @ra: node this frame is addressed to 232 * @ra: node this frame is addressed to
233 *
234 * Note: This function may be called with driver locks taken that the driver
235 * also acquires in the TX path. To avoid a deadlock we don't transmit the
236 * frame directly but add it to the pending queue instead.
202 */ 237 */
203int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, 238int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
204 __le16 target_rcode, const u8 *ra, 239 __le16 target_rcode, const u8 *ra,
@@ -212,7 +247,7 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
212 247
213 if (!skb) 248 if (!skb)
214 return -1; 249 return -1;
215 skb_reserve(skb, local->hw.extra_tx_headroom); 250 skb_reserve(skb, local->tx_headroom + local->hw.extra_tx_headroom);
216 /* 25 is the size of the common mgmt part (24) plus the size of the 251 /* 25 is the size of the common mgmt part (24) plus the size of the
217 * common action part (1) 252 * common action part (1)
218 */ 253 */
@@ -224,9 +259,11 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
224 259
225 memcpy(mgmt->da, ra, ETH_ALEN); 260 memcpy(mgmt->da, ra, ETH_ALEN);
226 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); 261 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
227 /* BSSID is left zeroed, wildcard value */ 262 /* BSSID == SA */
228 mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL; 263 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
229 mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; 264 mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION;
265 mgmt->u.action.u.mesh_action.action_code =
266 WLAN_MESH_ACTION_HWMP_PATH_SELECTION;
230 ie_len = 15; 267 ie_len = 15;
231 pos = skb_put(skb, 2 + ie_len); 268 pos = skb_put(skb, 2 + ie_len);
232 *pos++ = WLAN_EID_PERR; 269 *pos++ = WLAN_EID_PERR;
@@ -251,7 +288,9 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
251 pos += 4; 288 pos += 4;
252 memcpy(pos, &target_rcode, 2); 289 memcpy(pos, &target_rcode, 2);
253 290
254 ieee80211_tx_skb(sdata, skb); 291 /* see note in function header */
292 prepare_frame_for_deferred_tx(sdata, skb);
293 ieee80211_add_pending_skb(local, skb);
255 return 0; 294 return 0;
256} 295}
257 296
@@ -449,7 +488,6 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
449 488
450 if (fresh_info) { 489 if (fresh_info) {
451 mesh_path_assign_nexthop(mpath, sta); 490 mesh_path_assign_nexthop(mpath, sta);
452 mpath->flags &= ~MESH_PATH_SN_VALID;
453 mpath->metric = last_hop_metric; 491 mpath->metric = last_hop_metric;
454 mpath->exp_time = time_after(mpath->exp_time, exp_time) 492 mpath->exp_time = time_after(mpath->exp_time, exp_time)
455 ? mpath->exp_time : exp_time; 493 ? mpath->exp_time : exp_time;
@@ -484,10 +522,10 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
484 orig_sn = PREQ_IE_ORIG_SN(preq_elem); 522 orig_sn = PREQ_IE_ORIG_SN(preq_elem);
485 target_flags = PREQ_IE_TARGET_F(preq_elem); 523 target_flags = PREQ_IE_TARGET_F(preq_elem);
486 524
487 mhwmp_dbg("received PREQ from %pM\n", orig_addr); 525 mhwmp_dbg("received PREQ from %pM", orig_addr);
488 526
489 if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) { 527 if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) {
490 mhwmp_dbg("PREQ is for us\n"); 528 mhwmp_dbg("PREQ is for us");
491 forward = false; 529 forward = false;
492 reply = true; 530 reply = true;
493 metric = 0; 531 metric = 0;
@@ -523,7 +561,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
523 lifetime = PREQ_IE_LIFETIME(preq_elem); 561 lifetime = PREQ_IE_LIFETIME(preq_elem);
524 ttl = ifmsh->mshcfg.element_ttl; 562 ttl = ifmsh->mshcfg.element_ttl;
525 if (ttl != 0) { 563 if (ttl != 0) {
526 mhwmp_dbg("replying to the PREQ\n"); 564 mhwmp_dbg("replying to the PREQ");
527 mesh_path_sel_frame_tx(MPATH_PREP, 0, target_addr, 565 mesh_path_sel_frame_tx(MPATH_PREP, 0, target_addr,
528 cpu_to_le32(target_sn), 0, orig_addr, 566 cpu_to_le32(target_sn), 0, orig_addr,
529 cpu_to_le32(orig_sn), mgmt->sa, 0, ttl, 567 cpu_to_le32(orig_sn), mgmt->sa, 0, ttl,
@@ -543,7 +581,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
543 ifmsh->mshstats.dropped_frames_ttl++; 581 ifmsh->mshstats.dropped_frames_ttl++;
544 return; 582 return;
545 } 583 }
546 mhwmp_dbg("forwarding the PREQ from %pM\n", orig_addr); 584 mhwmp_dbg("forwarding the PREQ from %pM", orig_addr);
547 --ttl; 585 --ttl;
548 flags = PREQ_IE_FLAGS(preq_elem); 586 flags = PREQ_IE_FLAGS(preq_elem);
549 preq_id = PREQ_IE_PREQ_ID(preq_elem); 587 preq_id = PREQ_IE_PREQ_ID(preq_elem);
@@ -578,7 +616,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
578 u8 next_hop[ETH_ALEN]; 616 u8 next_hop[ETH_ALEN];
579 u32 target_sn, orig_sn, lifetime; 617 u32 target_sn, orig_sn, lifetime;
580 618
581 mhwmp_dbg("received PREP from %pM\n", PREP_IE_ORIG_ADDR(prep_elem)); 619 mhwmp_dbg("received PREP from %pM", PREP_IE_ORIG_ADDR(prep_elem));
582 620
583 /* Note that we divert from the draft nomenclature and denominate 621 /* Note that we divert from the draft nomenclature and denominate
584 * destination to what the draft refers to as origininator. So in this 622 * destination to what the draft refers to as origininator. So in this
@@ -684,6 +722,8 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
684 u8 ttl, flags, hopcount; 722 u8 ttl, flags, hopcount;
685 u8 *orig_addr; 723 u8 *orig_addr;
686 u32 orig_sn, metric; 724 u32 orig_sn, metric;
725 u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;
726 bool root_is_gate;
687 727
688 ttl = rann->rann_ttl; 728 ttl = rann->rann_ttl;
689 if (ttl <= 1) { 729 if (ttl <= 1) {
@@ -692,12 +732,19 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
692 } 732 }
693 ttl--; 733 ttl--;
694 flags = rann->rann_flags; 734 flags = rann->rann_flags;
735 root_is_gate = !!(flags & RANN_FLAG_IS_GATE);
695 orig_addr = rann->rann_addr; 736 orig_addr = rann->rann_addr;
696 orig_sn = rann->rann_seq; 737 orig_sn = rann->rann_seq;
697 hopcount = rann->rann_hopcount; 738 hopcount = rann->rann_hopcount;
698 hopcount++; 739 hopcount++;
699 metric = rann->rann_metric; 740 metric = rann->rann_metric;
700 mhwmp_dbg("received RANN from %pM\n", orig_addr); 741
742 /* Ignore our own RANNs */
743 if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0)
744 return;
745
746 mhwmp_dbg("received RANN from %pM (is_gate=%d)", orig_addr,
747 root_is_gate);
701 748
702 rcu_read_lock(); 749 rcu_read_lock();
703 mpath = mesh_path_lookup(orig_addr, sdata); 750 mpath = mesh_path_lookup(orig_addr, sdata);
@@ -709,18 +756,28 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
709 sdata->u.mesh.mshstats.dropped_frames_no_route++; 756 sdata->u.mesh.mshstats.dropped_frames_no_route++;
710 return; 757 return;
711 } 758 }
712 mesh_queue_preq(mpath,
713 PREQ_Q_F_START | PREQ_Q_F_REFRESH);
714 } 759 }
760
761 if ((!(mpath->flags & (MESH_PATH_ACTIVE | MESH_PATH_RESOLVING)) ||
762 time_after(jiffies, mpath->exp_time - 1*HZ)) &&
763 !(mpath->flags & MESH_PATH_FIXED)) {
764 mhwmp_dbg("%s time to refresh root mpath %pM", sdata->name,
765 orig_addr);
766 mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
767 }
768
715 if (mpath->sn < orig_sn) { 769 if (mpath->sn < orig_sn) {
716 mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, 770 mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
717 cpu_to_le32(orig_sn), 771 cpu_to_le32(orig_sn),
718 0, NULL, 0, broadcast_addr, 772 0, NULL, 0, broadcast_addr,
719 hopcount, ttl, 0, 773 hopcount, ttl, cpu_to_le32(interval),
720 cpu_to_le32(metric + mpath->metric), 774 cpu_to_le32(metric + mpath->metric),
721 0, sdata); 775 0, sdata);
722 mpath->sn = orig_sn; 776 mpath->sn = orig_sn;
723 } 777 }
778 if (root_is_gate)
779 mesh_path_add_gate(mpath);
780
724 rcu_read_unlock(); 781 rcu_read_unlock();
725} 782}
726 783
@@ -732,11 +789,20 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
732 struct ieee802_11_elems elems; 789 struct ieee802_11_elems elems;
733 size_t baselen; 790 size_t baselen;
734 u32 last_hop_metric; 791 u32 last_hop_metric;
792 struct sta_info *sta;
735 793
736 /* need action_code */ 794 /* need action_code */
737 if (len < IEEE80211_MIN_ACTION_SIZE + 1) 795 if (len < IEEE80211_MIN_ACTION_SIZE + 1)
738 return; 796 return;
739 797
798 rcu_read_lock();
799 sta = sta_info_get(sdata, mgmt->sa);
800 if (!sta || sta->plink_state != NL80211_PLINK_ESTAB) {
801 rcu_read_unlock();
802 return;
803 }
804 rcu_read_unlock();
805
740 baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt; 806 baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt;
741 ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable, 807 ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
742 len - baselen, &elems); 808 len - baselen, &elems);
@@ -788,16 +854,16 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
788 854
789 preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_ATOMIC); 855 preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_ATOMIC);
790 if (!preq_node) { 856 if (!preq_node) {
791 mhwmp_dbg("could not allocate PREQ node\n"); 857 mhwmp_dbg("could not allocate PREQ node");
792 return; 858 return;
793 } 859 }
794 860
795 spin_lock(&ifmsh->mesh_preq_queue_lock); 861 spin_lock_bh(&ifmsh->mesh_preq_queue_lock);
796 if (ifmsh->preq_queue_len == MAX_PREQ_QUEUE_LEN) { 862 if (ifmsh->preq_queue_len == MAX_PREQ_QUEUE_LEN) {
797 spin_unlock(&ifmsh->mesh_preq_queue_lock); 863 spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
798 kfree(preq_node); 864 kfree(preq_node);
799 if (printk_ratelimit()) 865 if (printk_ratelimit())
800 mhwmp_dbg("PREQ node queue full\n"); 866 mhwmp_dbg("PREQ node queue full");
801 return; 867 return;
802 } 868 }
803 869
@@ -806,7 +872,7 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
806 872
807 list_add_tail(&preq_node->list, &ifmsh->preq_queue.list); 873 list_add_tail(&preq_node->list, &ifmsh->preq_queue.list);
808 ++ifmsh->preq_queue_len; 874 ++ifmsh->preq_queue_len;
809 spin_unlock(&ifmsh->mesh_preq_queue_lock); 875 spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
810 876
811 if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata))) 877 if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata)))
812 ieee80211_queue_work(&sdata->local->hw, &sdata->work); 878 ieee80211_queue_work(&sdata->local->hw, &sdata->work);
@@ -982,35 +1048,46 @@ void mesh_path_timer(unsigned long data)
982{ 1048{
983 struct mesh_path *mpath = (void *) data; 1049 struct mesh_path *mpath = (void *) data;
984 struct ieee80211_sub_if_data *sdata = mpath->sdata; 1050 struct ieee80211_sub_if_data *sdata = mpath->sdata;
1051 int ret;
985 1052
986 if (sdata->local->quiescing) 1053 if (sdata->local->quiescing)
987 return; 1054 return;
988 1055
989 spin_lock_bh(&mpath->state_lock); 1056 spin_lock_bh(&mpath->state_lock);
990 if (mpath->flags & MESH_PATH_RESOLVED || 1057 if (mpath->flags & MESH_PATH_RESOLVED ||
991 (!(mpath->flags & MESH_PATH_RESOLVING))) 1058 (!(mpath->flags & MESH_PATH_RESOLVING))) {
992 mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED); 1059 mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED);
993 else if (mpath->discovery_retries < max_preq_retries(sdata)) { 1060 spin_unlock_bh(&mpath->state_lock);
1061 } else if (mpath->discovery_retries < max_preq_retries(sdata)) {
994 ++mpath->discovery_retries; 1062 ++mpath->discovery_retries;
995 mpath->discovery_timeout *= 2; 1063 mpath->discovery_timeout *= 2;
1064 spin_unlock_bh(&mpath->state_lock);
996 mesh_queue_preq(mpath, 0); 1065 mesh_queue_preq(mpath, 0);
997 } else { 1066 } else {
998 mpath->flags = 0; 1067 mpath->flags = 0;
999 mpath->exp_time = jiffies; 1068 mpath->exp_time = jiffies;
1000 mesh_path_flush_pending(mpath); 1069 spin_unlock_bh(&mpath->state_lock);
1070 if (!mpath->is_gate && mesh_gate_num(sdata) > 0) {
1071 ret = mesh_path_send_to_gates(mpath);
1072 if (ret)
1073 mhwmp_dbg("no gate was reachable");
1074 } else
1075 mesh_path_flush_pending(mpath);
1001 } 1076 }
1002
1003 spin_unlock_bh(&mpath->state_lock);
1004} 1077}
1005 1078
1006void 1079void
1007mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) 1080mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
1008{ 1081{
1009 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 1082 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
1083 u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;
1084 u8 flags;
1010 1085
1011 mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr, 1086 flags = (ifmsh->mshcfg.dot11MeshGateAnnouncementProtocol)
1087 ? RANN_FLAG_IS_GATE : 0;
1088 mesh_path_sel_frame_tx(MPATH_RANN, flags, sdata->vif.addr,
1012 cpu_to_le32(++ifmsh->sn), 1089 cpu_to_le32(++ifmsh->sn),
1013 0, NULL, 0, broadcast_addr, 1090 0, NULL, 0, broadcast_addr,
1014 0, sdata->u.mesh.mshcfg.element_ttl, 1091 0, sdata->u.mesh.mshcfg.element_ttl,
1015 0, 0, 0, sdata); 1092 cpu_to_le32(interval), 0, 0, sdata);
1016} 1093}