~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/mac80211/mesh_hwmp.c

Version: ~ [ linux-5.6-rc3 ] ~ [ linux-5.5.6 ] ~ [ linux-5.4.22 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.106 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.171 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.214 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.214 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.82 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Copyright (c) 2008, 2009 open80211s Ltd.
  3  * Author:     Luis Carlos Cobo <luisca@cozybit.com>
  4  *
  5  * This program is free software; you can redistribute it and/or modify
  6  * it under the terms of the GNU General Public License version 2 as
  7  * published by the Free Software Foundation.
  8  */
  9 
 10 #include <linux/slab.h>
 11 #include <linux/etherdevice.h>
 12 #include <asm/unaligned.h>
 13 #include "wme.h"
 14 #include "mesh.h"
 15 
 16 #define TEST_FRAME_LEN  8192
 17 #define MAX_METRIC      0xffffffff
 18 #define ARITH_SHIFT     8
 19 
 20 #define MAX_PREQ_QUEUE_LEN      64
 21 
 22 /* Destination only */
 23 #define MP_F_DO 0x1
 24 /* Reply and forward */
 25 #define MP_F_RF 0x2
 26 /* Unknown Sequence Number */
 27 #define MP_F_USN    0x01
 28 /* Reason code Present */
 29 #define MP_F_RCODE  0x02
 30 
 31 static void mesh_queue_preq(struct mesh_path *, u8);
 32 
 33 static inline u32 u32_field_get(const u8 *preq_elem, int offset, bool ae)
 34 {
 35         if (ae)
 36                 offset += 6;
 37         return get_unaligned_le32(preq_elem + offset);
 38 }
 39 
 40 static inline u16 u16_field_get(const u8 *preq_elem, int offset, bool ae)
 41 {
 42         if (ae)
 43                 offset += 6;
 44         return get_unaligned_le16(preq_elem + offset);
 45 }
 46 
 47 /* HWMP IE processing macros */
 48 #define AE_F                    (1<<6)
 49 #define AE_F_SET(x)             (*x & AE_F)
 50 #define PREQ_IE_FLAGS(x)        (*(x))
 51 #define PREQ_IE_HOPCOUNT(x)     (*(x + 1))
 52 #define PREQ_IE_TTL(x)          (*(x + 2))
 53 #define PREQ_IE_PREQ_ID(x)      u32_field_get(x, 3, 0)
 54 #define PREQ_IE_ORIG_ADDR(x)    (x + 7)
 55 #define PREQ_IE_ORIG_SN(x)      u32_field_get(x, 13, 0)
 56 #define PREQ_IE_LIFETIME(x)     u32_field_get(x, 17, AE_F_SET(x))
 57 #define PREQ_IE_METRIC(x)       u32_field_get(x, 21, AE_F_SET(x))
 58 #define PREQ_IE_TARGET_F(x)     (*(AE_F_SET(x) ? x + 32 : x + 26))
 59 #define PREQ_IE_TARGET_ADDR(x)  (AE_F_SET(x) ? x + 33 : x + 27)
 60 #define PREQ_IE_TARGET_SN(x)    u32_field_get(x, 33, AE_F_SET(x))
 61 
 62 
 63 #define PREP_IE_FLAGS(x)        PREQ_IE_FLAGS(x)
 64 #define PREP_IE_HOPCOUNT(x)     PREQ_IE_HOPCOUNT(x)
 65 #define PREP_IE_TTL(x)          PREQ_IE_TTL(x)
 66 #define PREP_IE_ORIG_ADDR(x)    (AE_F_SET(x) ? x + 27 : x + 21)
 67 #define PREP_IE_ORIG_SN(x)      u32_field_get(x, 27, AE_F_SET(x))
 68 #define PREP_IE_LIFETIME(x)     u32_field_get(x, 13, AE_F_SET(x))
 69 #define PREP_IE_METRIC(x)       u32_field_get(x, 17, AE_F_SET(x))
 70 #define PREP_IE_TARGET_ADDR(x)  (x + 3)
 71 #define PREP_IE_TARGET_SN(x)    u32_field_get(x, 9, 0)
 72 
 73 #define PERR_IE_TTL(x)          (*(x))
 74 #define PERR_IE_TARGET_FLAGS(x) (*(x + 2))
 75 #define PERR_IE_TARGET_ADDR(x)  (x + 3)
 76 #define PERR_IE_TARGET_SN(x)    u32_field_get(x, 9, 0)
 77 #define PERR_IE_TARGET_RCODE(x) u16_field_get(x, 13, 0)
 78 
 79 #define MSEC_TO_TU(x) (x*1000/1024)
 80 #define SN_GT(x, y) ((s32)(y - x) < 0)
 81 #define SN_LT(x, y) ((s32)(x - y) < 0)
 82 
 83 #define net_traversal_jiffies(s) \
 84         msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime)
 85 #define default_lifetime(s) \
 86         MSEC_TO_TU(s->u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout)
 87 #define min_preq_int_jiff(s) \
 88         (msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval))
 89 #define max_preq_retries(s) (s->u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries)
 90 #define disc_timeout_jiff(s) \
 91         msecs_to_jiffies(sdata->u.mesh.mshcfg.min_discovery_timeout)
 92 #define root_path_confirmation_jiffies(s) \
 93         msecs_to_jiffies(sdata->u.mesh.mshcfg.dot11MeshHWMPconfirmationInterval)
 94 
 95 enum mpath_frame_type {
 96         MPATH_PREQ = 0,
 97         MPATH_PREP,
 98         MPATH_PERR,
 99         MPATH_RANN
100 };
101 
102 static const u8 broadcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
103 
104 static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
105                                   const u8 *orig_addr, u32 orig_sn,
106                                   u8 target_flags, const u8 *target,
107                                   u32 target_sn, const u8 *da,
108                                   u8 hop_count, u8 ttl,
109                                   u32 lifetime, u32 metric, u32 preq_id,
110                                   struct ieee80211_sub_if_data *sdata)
111 {
112         struct ieee80211_local *local = sdata->local;
113         struct sk_buff *skb;
114         struct ieee80211_mgmt *mgmt;
115         u8 *pos, ie_len;
116         int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) +
117                       sizeof(mgmt->u.action.u.mesh_action);
118 
119         skb = dev_alloc_skb(local->tx_headroom +
120                             hdr_len +
121                             2 + 37); /* max HWMP IE */
122         if (!skb)
123                 return -1;
124         skb_reserve(skb, local->tx_headroom);
125         mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
126         memset(mgmt, 0, hdr_len);
127         mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
128                                           IEEE80211_STYPE_ACTION);
129 
130         memcpy(mgmt->da, da, ETH_ALEN);
131         memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
132         /* BSSID == SA */
133         memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
134         mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION;
135         mgmt->u.action.u.mesh_action.action_code =
136                                         WLAN_MESH_ACTION_HWMP_PATH_SELECTION;
137 
138         switch (action) {
139         case MPATH_PREQ:
140                 mhwmp_dbg(sdata, "sending PREQ to %pM\n", target);
141                 ie_len = 37;
142                 pos = skb_put(skb, 2 + ie_len);
143                 *pos++ = WLAN_EID_PREQ;
144                 break;
145         case MPATH_PREP:
146                 mhwmp_dbg(sdata, "sending PREP to %pM\n", orig_addr);
147                 ie_len = 31;
148                 pos = skb_put(skb, 2 + ie_len);
149                 *pos++ = WLAN_EID_PREP;
150                 break;
151         case MPATH_RANN:
152                 mhwmp_dbg(sdata, "sending RANN from %pM\n", orig_addr);
153                 ie_len = sizeof(struct ieee80211_rann_ie);
154                 pos = skb_put(skb, 2 + ie_len);
155                 *pos++ = WLAN_EID_RANN;
156                 break;
157         default:
158                 kfree_skb(skb);
159                 return -ENOTSUPP;
160         }
161         *pos++ = ie_len;
162         *pos++ = flags;
163         *pos++ = hop_count;
164         *pos++ = ttl;
165         if (action == MPATH_PREP) {
166                 memcpy(pos, target, ETH_ALEN);
167                 pos += ETH_ALEN;
168                 put_unaligned_le32(target_sn, pos);
169                 pos += 4;
170         } else {
171                 if (action == MPATH_PREQ) {
172                         put_unaligned_le32(preq_id, pos);
173                         pos += 4;
174                 }
175                 memcpy(pos, orig_addr, ETH_ALEN);
176                 pos += ETH_ALEN;
177                 put_unaligned_le32(orig_sn, pos);
178                 pos += 4;
179         }
180         put_unaligned_le32(lifetime, pos); /* interval for RANN */
181         pos += 4;
182         put_unaligned_le32(metric, pos);
183         pos += 4;
184         if (action == MPATH_PREQ) {
185                 *pos++ = 1; /* destination count */
186                 *pos++ = target_flags;
187                 memcpy(pos, target, ETH_ALEN);
188                 pos += ETH_ALEN;
189                 put_unaligned_le32(target_sn, pos);
190                 pos += 4;
191         } else if (action == MPATH_PREP) {
192                 memcpy(pos, orig_addr, ETH_ALEN);
193                 pos += ETH_ALEN;
194                 put_unaligned_le32(orig_sn, pos);
195                 pos += 4;
196         }
197 
198         ieee80211_tx_skb(sdata, skb);
199         return 0;
200 }
201 
202 
203 /*  Headroom is not adjusted.  Caller should ensure that skb has sufficient
204  *  headroom in case the frame is encrypted. */
205 static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata,
206                 struct sk_buff *skb)
207 {
208         struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
209         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
210 
211         skb_set_mac_header(skb, 0);
212         skb_set_network_header(skb, 0);
213         skb_set_transport_header(skb, 0);
214 
215         /* Send all internal mgmt frames on VO. Accordingly set TID to 7. */
216         skb_set_queue_mapping(skb, IEEE80211_AC_VO);
217         skb->priority = 7;
218 
219         info->control.vif = &sdata->vif;
220         info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
221         ieee80211_set_qos_hdr(sdata, skb);
222         ieee80211_mps_set_frame_flags(sdata, NULL, hdr);
223 }
224 
225 /**
226  * mesh_path_error_tx - Sends a PERR mesh management frame
227  *
228  * @ttl: allowed remaining hops
229  * @target: broken destination
230  * @target_sn: SN of the broken destination
231  * @target_rcode: reason code for this PERR
232  * @ra: node this frame is addressed to
233  * @sdata: local mesh subif
234  *
235  * Note: This function may be called with driver locks taken that the driver
236  * also acquires in the TX path.  To avoid a deadlock we don't transmit the
237  * frame directly but add it to the pending queue instead.
238  */
239 int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
240                        u8 ttl, const u8 *target, u32 target_sn,
241                        u16 target_rcode, const u8 *ra)
242 {
243         struct ieee80211_local *local = sdata->local;
244         struct sk_buff *skb;
245         struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
246         struct ieee80211_mgmt *mgmt;
247         u8 *pos, ie_len;
248         int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) +
249                       sizeof(mgmt->u.action.u.mesh_action);
250 
251         if (time_before(jiffies, ifmsh->next_perr))
252                 return -EAGAIN;
253 
254         skb = dev_alloc_skb(local->tx_headroom +
255                             sdata->encrypt_headroom +
256                             IEEE80211_ENCRYPT_TAILROOM +
257                             hdr_len +
258                             2 + 15 /* PERR IE */);
259         if (!skb)
260                 return -1;
261         skb_reserve(skb, local->tx_headroom + sdata->encrypt_headroom);
262         mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
263         memset(mgmt, 0, hdr_len);
264         mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
265                                           IEEE80211_STYPE_ACTION);
266 
267         memcpy(mgmt->da, ra, ETH_ALEN);
268         memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
269         /* BSSID == SA */
270         memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
271         mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION;
272         mgmt->u.action.u.mesh_action.action_code =
273                                         WLAN_MESH_ACTION_HWMP_PATH_SELECTION;
274         ie_len = 15;
275         pos = skb_put(skb, 2 + ie_len);
276         *pos++ = WLAN_EID_PERR;
277         *pos++ = ie_len;
278         /* ttl */
279         *pos++ = ttl;
280         /* number of destinations */
281         *pos++ = 1;
282         /*
283          * flags bit, bit 1 is unset if we know the sequence number and
284          * bit 2 is set if we have a reason code
285          */
286         *pos = 0;
287         if (!target_sn)
288                 *pos |= MP_F_USN;
289         if (target_rcode)
290                 *pos |= MP_F_RCODE;
291         pos++;
292         memcpy(pos, target, ETH_ALEN);
293         pos += ETH_ALEN;
294         put_unaligned_le32(target_sn, pos);
295         pos += 4;
296         put_unaligned_le16(target_rcode, pos);
297 
298         /* see note in function header */
299         prepare_frame_for_deferred_tx(sdata, skb);
300         ifmsh->next_perr = TU_TO_EXP_TIME(
301                                    ifmsh->mshcfg.dot11MeshHWMPperrMinInterval);
302         ieee80211_add_pending_skb(local, skb);
303         return 0;
304 }
305 
306 void ieee80211s_update_metric(struct ieee80211_local *local,
307                 struct sta_info *sta, struct sk_buff *skb)
308 {
309         struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
310         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
311         int failed;
312 
313         if (!ieee80211_is_data(hdr->frame_control))
314                 return;
315 
316         failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK);
317 
318         /* moving average, scaled to 100 */
319         sta->fail_avg = ((80 * sta->fail_avg + 5) / 100 + 20 * failed);
320         if (sta->fail_avg > 95)
321                 mesh_plink_broken(sta);
322 }
323 
324 static u32 airtime_link_metric_get(struct ieee80211_local *local,
325                                    struct sta_info *sta)
326 {
327         struct rate_info rinfo;
328         /* This should be adjusted for each device */
329         int device_constant = 1 << ARITH_SHIFT;
330         int test_frame_len = TEST_FRAME_LEN << ARITH_SHIFT;
331         int s_unit = 1 << ARITH_SHIFT;
332         int rate, err;
333         u32 tx_time, estimated_retx;
334         u64 result;
335 
336         if (sta->fail_avg >= 100)
337                 return MAX_METRIC;
338 
339         sta_set_rate_info_tx(sta, &sta->last_tx_rate, &rinfo);
340         rate = cfg80211_calculate_bitrate(&rinfo);
341         if (WARN_ON(!rate))
342                 return MAX_METRIC;
343 
344         err = (sta->fail_avg << ARITH_SHIFT) / 100;
345 
346         /* bitrate is in units of 100 Kbps, while we need rate in units of
347          * 1Mbps. This will be corrected on tx_time computation.
348          */
349         tx_time = (device_constant + 10 * test_frame_len / rate);
350         estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err));
351         result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ;
352         return (u32)result;
353 }
354 
355 /**
356  * hwmp_route_info_get - Update routing info to originator and transmitter
357  *
358  * @sdata: local mesh subif
359  * @mgmt: mesh management frame
360  * @hwmp_ie: hwmp information element (PREP or PREQ)
361  * @action: type of hwmp ie
362  *
363  * This function updates the path routing information to the originator and the
364  * transmitter of a HWMP PREQ or PREP frame.
365  *
366  * Returns: metric to frame originator or 0 if the frame should not be further
367  * processed
368  *
369  * Notes: this function is the only place (besides user-provided info) where
370  * path routing information is updated.
371  */
372 static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
373                                struct ieee80211_mgmt *mgmt,
374                                const u8 *hwmp_ie, enum mpath_frame_type action)
375 {
376         struct ieee80211_local *local = sdata->local;
377         struct mesh_path *mpath;
378         struct sta_info *sta;
379         bool fresh_info;
380         const u8 *orig_addr, *ta;
381         u32 orig_sn, orig_metric;
382         unsigned long orig_lifetime, exp_time;
383         u32 last_hop_metric, new_metric;
384         bool process = true;
385 
386         rcu_read_lock();
387         sta = sta_info_get(sdata, mgmt->sa);
388         if (!sta) {
389                 rcu_read_unlock();
390                 return 0;
391         }
392 
393         last_hop_metric = airtime_link_metric_get(local, sta);
394         /* Update and check originator routing info */
395         fresh_info = true;
396 
397         switch (action) {
398         case MPATH_PREQ:
399                 orig_addr = PREQ_IE_ORIG_ADDR(hwmp_ie);
400                 orig_sn = PREQ_IE_ORIG_SN(hwmp_ie);
401                 orig_lifetime = PREQ_IE_LIFETIME(hwmp_ie);
402                 orig_metric = PREQ_IE_METRIC(hwmp_ie);
403                 break;
404         case MPATH_PREP:
405                 /* Originator here refers to the MP that was the target in the
406                  * Path Request. We divert from the nomenclature in the draft
407                  * so that we can easily use a single function to gather path
408                  * information from both PREQ and PREP frames.
409                  */
410                 orig_addr = PREP_IE_TARGET_ADDR(hwmp_ie);
411                 orig_sn = PREP_IE_TARGET_SN(hwmp_ie);
412                 orig_lifetime = PREP_IE_LIFETIME(hwmp_ie);
413                 orig_metric = PREP_IE_METRIC(hwmp_ie);
414                 break;
415         default:
416                 rcu_read_unlock();
417                 return 0;
418         }
419         new_metric = orig_metric + last_hop_metric;
420         if (new_metric < orig_metric)
421                 new_metric = MAX_METRIC;
422         exp_time = TU_TO_EXP_TIME(orig_lifetime);
423 
424         if (ether_addr_equal(orig_addr, sdata->vif.addr)) {
425                 /* This MP is the originator, we are not interested in this
426                  * frame, except for updating transmitter's path info.
427                  */
428                 process = false;
429                 fresh_info = false;
430         } else {
431                 mpath = mesh_path_lookup(sdata, orig_addr);
432                 if (mpath) {
433                         spin_lock_bh(&mpath->state_lock);
434                         if (mpath->flags & MESH_PATH_FIXED)
435                                 fresh_info = false;
436                         else if ((mpath->flags & MESH_PATH_ACTIVE) &&
437                             (mpath->flags & MESH_PATH_SN_VALID)) {
438                                 if (SN_GT(mpath->sn, orig_sn) ||
439                                     (mpath->sn == orig_sn &&
440                                      new_metric >= mpath->metric)) {
441                                         process = false;
442                                         fresh_info = false;
443                                 }
444                         }
445                 } else {
446                         mpath = mesh_path_add(sdata, orig_addr);
447                         if (IS_ERR(mpath)) {
448                                 rcu_read_unlock();
449                                 return 0;
450                         }
451                         spin_lock_bh(&mpath->state_lock);
452                 }
453 
454                 if (fresh_info) {
455                         mesh_path_assign_nexthop(mpath, sta);
456                         mpath->flags |= MESH_PATH_SN_VALID;
457                         mpath->metric = new_metric;
458                         mpath->sn = orig_sn;
459                         mpath->exp_time = time_after(mpath->exp_time, exp_time)
460                                           ?  mpath->exp_time : exp_time;
461                         mesh_path_activate(mpath);
462                         spin_unlock_bh(&mpath->state_lock);
463                         mesh_path_tx_pending(mpath);
464                         /* draft says preq_id should be saved to, but there does
465                          * not seem to be any use for it, skipping by now
466                          */
467                 } else
468                         spin_unlock_bh(&mpath->state_lock);
469         }
470 
471         /* Update and check transmitter routing info */
472         ta = mgmt->sa;
473         if (ether_addr_equal(orig_addr, ta))
474                 fresh_info = false;
475         else {
476                 fresh_info = true;
477 
478                 mpath = mesh_path_lookup(sdata, ta);
479                 if (mpath) {
480                         spin_lock_bh(&mpath->state_lock);
481                         if ((mpath->flags & MESH_PATH_FIXED) ||
482                                 ((mpath->flags & MESH_PATH_ACTIVE) &&
483                                         (last_hop_metric > mpath->metric)))
484                                 fresh_info = false;
485                 } else {
486                         mpath = mesh_path_add(sdata, ta);
487                         if (IS_ERR(mpath)) {
488                                 rcu_read_unlock();
489                                 return 0;
490                         }
491                         spin_lock_bh(&mpath->state_lock);
492                 }
493 
494                 if (fresh_info) {
495                         mesh_path_assign_nexthop(mpath, sta);
496                         mpath->metric = last_hop_metric;
497                         mpath->exp_time = time_after(mpath->exp_time, exp_time)
498                                           ?  mpath->exp_time : exp_time;
499                         mesh_path_activate(mpath);
500                         spin_unlock_bh(&mpath->state_lock);
501                         mesh_path_tx_pending(mpath);
502                 } else
503                         spin_unlock_bh(&mpath->state_lock);
504         }
505 
506         rcu_read_unlock();
507 
508         return process ? new_metric : 0;
509 }
510 
511 static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
512                                     struct ieee80211_mgmt *mgmt,
513                                     const u8 *preq_elem, u32 metric)
514 {
515         struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
516         struct mesh_path *mpath = NULL;
517         const u8 *target_addr, *orig_addr;
518         const u8 *da;
519         u8 target_flags, ttl, flags;
520         u32 orig_sn, target_sn, lifetime, orig_metric;
521         bool reply = false;
522         bool forward = true;
523         bool root_is_gate;
524 
525         /* Update target SN, if present */
526         target_addr = PREQ_IE_TARGET_ADDR(preq_elem);
527         orig_addr = PREQ_IE_ORIG_ADDR(preq_elem);
528         target_sn = PREQ_IE_TARGET_SN(preq_elem);
529         orig_sn = PREQ_IE_ORIG_SN(preq_elem);
530         target_flags = PREQ_IE_TARGET_F(preq_elem);
531         orig_metric = metric;
532         /* Proactive PREQ gate announcements */
533         flags = PREQ_IE_FLAGS(preq_elem);
534         root_is_gate = !!(flags & RANN_FLAG_IS_GATE);
535 
536         mhwmp_dbg(sdata, "received PREQ from %pM\n", orig_addr);
537 
538         if (ether_addr_equal(target_addr, sdata->vif.addr)) {
539                 mhwmp_dbg(sdata, "PREQ is for us\n");
540                 forward = false;
541                 reply = true;
542                 metric = 0;
543                 if (time_after(jiffies, ifmsh->last_sn_update +
544                                         net_traversal_jiffies(sdata)) ||
545                     time_before(jiffies, ifmsh->last_sn_update)) {
546                         ++ifmsh->sn;
547                         ifmsh->last_sn_update = jiffies;
548                 }
549                 target_sn = ifmsh->sn;
550         } else if (is_broadcast_ether_addr(target_addr) &&
551                    (target_flags & IEEE80211_PREQ_TO_FLAG)) {
552                 rcu_read_lock();
553                 mpath = mesh_path_lookup(sdata, orig_addr);
554                 if (mpath) {
555                         if (flags & IEEE80211_PREQ_PROACTIVE_PREP_FLAG) {
556                                 reply = true;
557                                 target_addr = sdata->vif.addr;
558                                 target_sn = ++ifmsh->sn;
559                                 metric = 0;
560                                 ifmsh->last_sn_update = jiffies;
561                         }
562                         if (root_is_gate)
563                                 mesh_path_add_gate(mpath);
564                 }
565                 rcu_read_unlock();
566         } else {
567                 rcu_read_lock();
568                 mpath = mesh_path_lookup(sdata, target_addr);
569                 if (mpath) {
570                         if ((!(mpath->flags & MESH_PATH_SN_VALID)) ||
571                                         SN_LT(mpath->sn, target_sn)) {
572                                 mpath->sn = target_sn;
573                                 mpath->flags |= MESH_PATH_SN_VALID;
574                         } else if ((!(target_flags & MP_F_DO)) &&
575                                         (mpath->flags & MESH_PATH_ACTIVE)) {
576                                 reply = true;
577                                 metric = mpath->metric;
578                                 target_sn = mpath->sn;
579                                 if (target_flags & MP_F_RF)
580                                         target_flags |= MP_F_DO;
581                                 else
582                                         forward = false;
583                         }
584                 }
585                 rcu_read_unlock();
586         }
587 
588         if (reply) {
589                 lifetime = PREQ_IE_LIFETIME(preq_elem);
590                 ttl = ifmsh->mshcfg.element_ttl;
591                 if (ttl != 0) {
592                         mhwmp_dbg(sdata, "replying to the PREQ\n");
593                         mesh_path_sel_frame_tx(MPATH_PREP, 0, orig_addr,
594                                                orig_sn, 0, target_addr,
595                                                target_sn, mgmt->sa, 0, ttl,
596                                                lifetime, metric, 0, sdata);
597                 } else {
598                         ifmsh->mshstats.dropped_frames_ttl++;
599                 }
600         }
601 
602         if (forward && ifmsh->mshcfg.dot11MeshForwarding) {
603                 u32 preq_id;
604                 u8 hopcount;
605 
606                 ttl = PREQ_IE_TTL(preq_elem);
607                 lifetime = PREQ_IE_LIFETIME(preq_elem);
608                 if (ttl <= 1) {
609                         ifmsh->mshstats.dropped_frames_ttl++;
610                         return;
611                 }
612                 mhwmp_dbg(sdata, "forwarding the PREQ from %pM\n", orig_addr);
613                 --ttl;
614                 preq_id = PREQ_IE_PREQ_ID(preq_elem);
615                 hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1;
616                 da = (mpath && mpath->is_root) ?
617                         mpath->rann_snd_addr : broadcast_addr;
618 
619                 if (flags & IEEE80211_PREQ_PROACTIVE_PREP_FLAG) {
620                         target_addr = PREQ_IE_TARGET_ADDR(preq_elem);
621                         target_sn = PREQ_IE_TARGET_SN(preq_elem);
622                         metric = orig_metric;
623                 }
624 
625                 mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr,
626                                        orig_sn, target_flags, target_addr,
627                                        target_sn, da, hopcount, ttl, lifetime,
628                                        metric, preq_id, sdata);
629                 if (!is_multicast_ether_addr(da))
630                         ifmsh->mshstats.fwded_unicast++;
631                 else
632                         ifmsh->mshstats.fwded_mcast++;
633                 ifmsh->mshstats.fwded_frames++;
634         }
635 }
636 
637 
638 static inline struct sta_info *
639 next_hop_deref_protected(struct mesh_path *mpath)
640 {
641         return rcu_dereference_protected(mpath->next_hop,
642                                          lockdep_is_held(&mpath->state_lock));
643 }
644 
645 
646 static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
647                                     struct ieee80211_mgmt *mgmt,
648                                     const u8 *prep_elem, u32 metric)
649 {
650         struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
651         struct mesh_path *mpath;
652         const u8 *target_addr, *orig_addr;
653         u8 ttl, hopcount, flags;
654         u8 next_hop[ETH_ALEN];
655         u32 target_sn, orig_sn, lifetime;
656 
657         mhwmp_dbg(sdata, "received PREP from %pM\n",
658                   PREP_IE_TARGET_ADDR(prep_elem));
659 
660         orig_addr = PREP_IE_ORIG_ADDR(prep_elem);
661         if (ether_addr_equal(orig_addr, sdata->vif.addr))
662                 /* destination, no forwarding required */
663                 return;
664 
665         if (!ifmsh->mshcfg.dot11MeshForwarding)
666                 return;
667 
668         ttl = PREP_IE_TTL(prep_elem);
669         if (ttl <= 1) {
670                 sdata->u.mesh.mshstats.dropped_frames_ttl++;
671                 return;
672         }
673 
674         rcu_read_lock();
675         mpath = mesh_path_lookup(sdata, orig_addr);
676         if (mpath)
677                 spin_lock_bh(&mpath->state_lock);
678         else
679                 goto fail;
680         if (!(mpath->flags & MESH_PATH_ACTIVE)) {
681                 spin_unlock_bh(&mpath->state_lock);
682                 goto fail;
683         }
684         memcpy(next_hop, next_hop_deref_protected(mpath)->sta.addr, ETH_ALEN);
685         spin_unlock_bh(&mpath->state_lock);
686         --ttl;
687         flags = PREP_IE_FLAGS(prep_elem);
688         lifetime = PREP_IE_LIFETIME(prep_elem);
689         hopcount = PREP_IE_HOPCOUNT(prep_elem) + 1;
690         target_addr = PREP_IE_TARGET_ADDR(prep_elem);
691         target_sn = PREP_IE_TARGET_SN(prep_elem);
692         orig_sn = PREP_IE_ORIG_SN(prep_elem);
693 
694         mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr, orig_sn, 0,
695                                target_addr, target_sn, next_hop, hopcount,
696                                ttl, lifetime, metric, 0, sdata);
697         rcu_read_unlock();
698 
699         sdata->u.mesh.mshstats.fwded_unicast++;
700         sdata->u.mesh.mshstats.fwded_frames++;
701         return;
702 
703 fail:
704         rcu_read_unlock();
705         sdata->u.mesh.mshstats.dropped_frames_no_route++;
706 }
707 
708 static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata,
709                                     struct ieee80211_mgmt *mgmt,
710                                     const u8 *perr_elem)
711 {
712         struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
713         struct mesh_path *mpath;
714         u8 ttl;
715         const u8 *ta, *target_addr;
716         u32 target_sn;
717         u16 target_rcode;
718 
719         ta = mgmt->sa;
720         ttl = PERR_IE_TTL(perr_elem);
721         if (ttl <= 1) {
722                 ifmsh->mshstats.dropped_frames_ttl++;
723                 return;
724         }
725         ttl--;
726         target_addr = PERR_IE_TARGET_ADDR(perr_elem);
727         target_sn = PERR_IE_TARGET_SN(perr_elem);
728         target_rcode = PERR_IE_TARGET_RCODE(perr_elem);
729 
730         rcu_read_lock();
731         mpath = mesh_path_lookup(sdata, target_addr);
732         if (mpath) {
733                 struct sta_info *sta;
734 
735                 spin_lock_bh(&mpath->state_lock);
736                 sta = next_hop_deref_protected(mpath);
737                 if (mpath->flags & MESH_PATH_ACTIVE &&
738                     ether_addr_equal(ta, sta->sta.addr) &&
739                     (!(mpath->flags & MESH_PATH_SN_VALID) ||
740                     SN_GT(target_sn, mpath->sn))) {
741                         mpath->flags &= ~MESH_PATH_ACTIVE;
742                         mpath->sn = target_sn;
743                         spin_unlock_bh(&mpath->state_lock);
744                         if (!ifmsh->mshcfg.dot11MeshForwarding)
745                                 goto endperr;
746                         mesh_path_error_tx(sdata, ttl, target_addr,
747                                            target_sn, target_rcode,
748                                            broadcast_addr);
749                 } else
750                         spin_unlock_bh(&mpath->state_lock);
751         }
752 endperr:
753         rcu_read_unlock();
754 }
755 
756 static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
757                                     struct ieee80211_mgmt *mgmt,
758                                     const struct ieee80211_rann_ie *rann)
759 {
760         struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
761         struct ieee80211_local *local = sdata->local;
762         struct sta_info *sta;
763         struct mesh_path *mpath;
764         u8 ttl, flags, hopcount;
765         const u8 *orig_addr;
766         u32 orig_sn, metric, metric_txsta, interval;
767         bool root_is_gate;
768 
769         ttl = rann->rann_ttl;
770         flags = rann->rann_flags;
771         root_is_gate = !!(flags & RANN_FLAG_IS_GATE);
772         orig_addr = rann->rann_addr;
773         orig_sn = le32_to_cpu(rann->rann_seq);
774         interval = le32_to_cpu(rann->rann_interval);
775         hopcount = rann->rann_hopcount;
776         hopcount++;
777         metric = le32_to_cpu(rann->rann_metric);
778 
779         /*  Ignore our own RANNs */
780         if (ether_addr_equal(orig_addr, sdata->vif.addr))
781                 return;
782 
783         mhwmp_dbg(sdata,
784                   "received RANN from %pM via neighbour %pM (is_gate=%d)\n",
785                   orig_addr, mgmt->sa, root_is_gate);
786 
787         rcu_read_lock();
788         sta = sta_info_get(sdata, mgmt->sa);
789         if (!sta) {
790                 rcu_read_unlock();
791                 return;
792         }
793 
794         metric_txsta = airtime_link_metric_get(local, sta);
795 
796         mpath = mesh_path_lookup(sdata, orig_addr);
797         if (!mpath) {
798                 mpath = mesh_path_add(sdata, orig_addr);
799                 if (IS_ERR(mpath)) {
800                         rcu_read_unlock();
801                         sdata->u.mesh.mshstats.dropped_frames_no_route++;
802                         return;
803                 }
804         }
805 
806         if (!(SN_LT(mpath->sn, orig_sn)) &&
807             !(mpath->sn == orig_sn && metric < mpath->rann_metric)) {
808                 rcu_read_unlock();
809                 return;
810         }
811 
812         if ((!(mpath->flags & (MESH_PATH_ACTIVE | MESH_PATH_RESOLVING)) ||
813              (time_after(jiffies, mpath->last_preq_to_root +
814                                   root_path_confirmation_jiffies(sdata)) ||
815              time_before(jiffies, mpath->last_preq_to_root))) &&
816              !(mpath->flags & MESH_PATH_FIXED) && (ttl != 0)) {
817                 mhwmp_dbg(sdata,
818                           "time to refresh root mpath %pM\n",
819                           orig_addr);
820                 mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
821                 mpath->last_preq_to_root = jiffies;
822         }
823 
824         mpath->sn = orig_sn;
825         mpath->rann_metric = metric + metric_txsta;
826         mpath->is_root = true;
827         /* Recording RANNs sender address to send individually
828          * addressed PREQs destined for root mesh STA */
829         memcpy(mpath->rann_snd_addr, mgmt->sa, ETH_ALEN);
830 
831         if (root_is_gate)
832                 mesh_path_add_gate(mpath);
833 
834         if (ttl <= 1) {
835                 ifmsh->mshstats.dropped_frames_ttl++;
836                 rcu_read_unlock();
837                 return;
838         }
839         ttl--;
840 
841         if (ifmsh->mshcfg.dot11MeshForwarding) {
842                 mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
843                                        orig_sn, 0, NULL, 0, broadcast_addr,
844                                        hopcount, ttl, interval,
845                                        metric + metric_txsta, 0, sdata);
846         }
847 
848         rcu_read_unlock();
849 }
850 
851 
852 void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
853                             struct ieee80211_mgmt *mgmt, size_t len)
854 {
855         struct ieee802_11_elems elems;
856         size_t baselen;
857         u32 last_hop_metric;
858         struct sta_info *sta;
859 
860         /* need action_code */
861         if (len < IEEE80211_MIN_ACTION_SIZE + 1)
862                 return;
863 
864         rcu_read_lock();
865         sta = sta_info_get(sdata, mgmt->sa);
866         if (!sta || sta->plink_state != NL80211_PLINK_ESTAB) {
867                 rcu_read_unlock();
868                 return;
869         }
870         rcu_read_unlock();
871 
872         baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt;
873         ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
874                                len - baselen, false, &elems);
875 
876         if (elems.preq) {
877                 if (elems.preq_len != 37)
878                         /* Right now we support just 1 destination and no AE */
879                         return;
880                 last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.preq,
881                                                       MPATH_PREQ);
882                 if (last_hop_metric)
883                         hwmp_preq_frame_process(sdata, mgmt, elems.preq,
884                                                 last_hop_metric);
885         }
886         if (elems.prep) {
887                 if (elems.prep_len != 31)
888                         /* Right now we support no AE */
889                         return;
890                 last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.prep,
891                                                       MPATH_PREP);
892                 if (last_hop_metric)
893                         hwmp_prep_frame_process(sdata, mgmt, elems.prep,
894                                                 last_hop_metric);
895         }
896         if (elems.perr) {
897                 if (elems.perr_len != 15)
898                         /* Right now we support only one destination per PERR */
899                         return;
900                 hwmp_perr_frame_process(sdata, mgmt, elems.perr);
901         }
902         if (elems.rann)
903                 hwmp_rann_frame_process(sdata, mgmt, elems.rann);
904 }
905 
906 /**
907  * mesh_queue_preq - queue a PREQ to a given destination
908  *
909  * @mpath: mesh path to discover
910  * @flags: special attributes of the PREQ to be sent
911  *
912  * Locking: the function must be called from within a rcu read lock block.
913  *
914  */
915 static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
916 {
917         struct ieee80211_sub_if_data *sdata = mpath->sdata;
918         struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
919         struct mesh_preq_queue *preq_node;
920 
921         preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_ATOMIC);
922         if (!preq_node) {
923                 mhwmp_dbg(sdata, "could not allocate PREQ node\n");
924                 return;
925         }
926 
927         spin_lock_bh(&ifmsh->mesh_preq_queue_lock);
928         if (ifmsh->preq_queue_len == MAX_PREQ_QUEUE_LEN) {
929                 spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
930                 kfree(preq_node);
931                 if (printk_ratelimit())
932                         mhwmp_dbg(sdata, "PREQ node queue full\n");
933                 return;
934         }
935 
936         spin_lock(&mpath->state_lock);
937         if (mpath->flags & MESH_PATH_REQ_QUEUED) {
938                 spin_unlock(&mpath->state_lock);
939                 spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
940                 kfree(preq_node);
941                 return;
942         }
943 
944         memcpy(preq_node->dst, mpath->dst, ETH_ALEN);
945         preq_node->flags = flags;
946 
947         mpath->flags |= MESH_PATH_REQ_QUEUED;
948         spin_unlock(&mpath->state_lock);
949 
950         list_add_tail(&preq_node->list, &ifmsh->preq_queue.list);
951         ++ifmsh->preq_queue_len;
952         spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
953 
954         if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata)))
955                 ieee80211_queue_work(&sdata->local->hw, &sdata->work);
956 
957         else if (time_before(jiffies, ifmsh->last_preq)) {
958                 /* avoid long wait if did not send preqs for a long time
959                  * and jiffies wrapped around
960                  */
961                 ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1;
962                 ieee80211_queue_work(&sdata->local->hw, &sdata->work);
963         } else
964                 mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq +
965                                                 min_preq_int_jiff(sdata));
966 }
967 
968 /**
969  * mesh_path_start_discovery - launch a path discovery from the PREQ queue
970  *
971  * @sdata: local mesh subif
972  */
973 void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
974 {
975         struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
976         struct mesh_preq_queue *preq_node;
977         struct mesh_path *mpath;
978         u8 ttl, target_flags;
979         const u8 *da;
980         u32 lifetime;
981 
982         spin_lock_bh(&ifmsh->mesh_preq_queue_lock);
983         if (!ifmsh->preq_queue_len ||
984                 time_before(jiffies, ifmsh->last_preq +
985                                 min_preq_int_jiff(sdata))) {
986                 spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
987                 return;
988         }
989 
990         preq_node = list_first_entry(&ifmsh->preq_queue.list,
991                         struct mesh_preq_queue, list);
992         list_del(&preq_node->list);
993         --ifmsh->preq_queue_len;
994         spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
995 
996         rcu_read_lock();
997         mpath = mesh_path_lookup(sdata, preq_node->dst);
998         if (!mpath)
999                 goto enddiscovery;
1000 
1001         spin_lock_bh(&mpath->state_lock);
1002         mpath->flags &= ~MESH_PATH_REQ_QUEUED;
1003         if (preq_node->flags & PREQ_Q_F_START) {
1004                 if (mpath->flags & MESH_PATH_RESOLVING) {
1005                         spin_unlock_bh(&mpath->state_lock);
1006                         goto enddiscovery;
1007                 } else {
1008                         mpath->flags &= ~MESH_PATH_RESOLVED;
1009                         mpath->flags |= MESH_PATH_RESOLVING;
1010                         mpath->discovery_retries = 0;
1011                         mpath->discovery_timeout = disc_timeout_jiff(sdata);
1012                 }
1013         } else if (!(mpath->flags & MESH_PATH_RESOLVING) ||
1014                         mpath->flags & MESH_PATH_RESOLVED) {
1015                 mpath->flags &= ~MESH_PATH_RESOLVING;
1016                 spin_unlock_bh(&mpath->state_lock);
1017                 goto enddiscovery;
1018         }
1019 
1020         ifmsh->last_preq = jiffies;
1021 
1022         if (time_after(jiffies, ifmsh->last_sn_update +
1023                                 net_traversal_jiffies(sdata)) ||
1024             time_before(jiffies, ifmsh->last_sn_update)) {
1025                 ++ifmsh->sn;
1026                 sdata->u.mesh.last_sn_update = jiffies;
1027         }
1028         lifetime = default_lifetime(sdata);
1029         ttl = sdata->u.mesh.mshcfg.element_ttl;
1030         if (ttl == 0) {
1031                 sdata->u.mesh.mshstats.dropped_frames_ttl++;
1032                 spin_unlock_bh(&mpath->state_lock);
1033                 goto enddiscovery;
1034         }
1035 
1036         if (preq_node->flags & PREQ_Q_F_REFRESH)
1037                 target_flags = MP_F_DO;
1038         else
1039                 target_flags = MP_F_RF;
1040 
1041         spin_unlock_bh(&mpath->state_lock);
1042         da = (mpath->is_root) ? mpath->rann_snd_addr : broadcast_addr;
1043         mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->vif.addr, ifmsh->sn,
1044                                target_flags, mpath->dst, mpath->sn, da, 0,
1045                                ttl, lifetime, 0, ifmsh->preq_id++, sdata);
1046         mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout);
1047 
1048 enddiscovery:
1049         rcu_read_unlock();
1050         kfree(preq_node);
1051 }
1052 
1053 /**
1054  * mesh_nexthop_resolve - lookup next hop; conditionally start path discovery
1055  *
1056  * @skb: 802.11 frame to be sent
1057  * @sdata: network subif the frame will be sent through
1058  *
1059  * Lookup next hop for given skb and start path discovery if no
1060  * forwarding information is found.
1061  *
1062  * Returns: 0 if the next hop was found and -ENOENT if the frame was queued.
1063  * skb is freeed here if no mpath could be allocated.
1064  */
1065 int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata,
1066                          struct sk_buff *skb)
1067 {
1068         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1069         struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1070         struct mesh_path *mpath;
1071         struct sk_buff *skb_to_free = NULL;
1072         u8 *target_addr = hdr->addr3;
1073         int err = 0;
1074 
1075         /* Nulls are only sent to peers for PS and should be pre-addressed */
1076         if (ieee80211_is_qos_nullfunc(hdr->frame_control))
1077                 return 0;
1078 
1079         rcu_read_lock();
1080         err = mesh_nexthop_lookup(sdata, skb);
1081         if (!err)
1082                 goto endlookup;
1083 
1084         /* no nexthop found, start resolving */
1085         mpath = mesh_path_lookup(sdata, target_addr);
1086         if (!mpath) {
1087                 mpath = mesh_path_add(sdata, target_addr);
1088                 if (IS_ERR(mpath)) {
1089                         mesh_path_discard_frame(sdata, skb);
1090                         err = PTR_ERR(mpath);
1091                         goto endlookup;
1092                 }
1093         }
1094 
1095         if (!(mpath->flags & MESH_PATH_RESOLVING))
1096                 mesh_queue_preq(mpath, PREQ_Q_F_START);
1097 
1098         if (skb_queue_len(&mpath->frame_queue) >= MESH_FRAME_QUEUE_LEN)
1099                 skb_to_free = skb_dequeue(&mpath->frame_queue);
1100 
1101         info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
1102         ieee80211_set_qos_hdr(sdata, skb);
1103         skb_queue_tail(&mpath->frame_queue, skb);
1104         err = -ENOENT;
1105         if (skb_to_free)
1106                 mesh_path_discard_frame(sdata, skb_to_free);
1107 
1108 endlookup:
1109         rcu_read_unlock();
1110         return err;
1111 }
1112 
1113 /**
1114  * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame. Calling
1115  * this function is considered "using" the associated mpath, so preempt a path
1116  * refresh if this mpath expires soon.
1117  *
1118  * @skb: 802.11 frame to be sent
1119  * @sdata: network subif the frame will be sent through
1120  *
1121  * Returns: 0 if the next hop was found. Nonzero otherwise.
1122  */
1123 int mesh_nexthop_lookup(struct ieee80211_sub_if_data *sdata,
1124                         struct sk_buff *skb)
1125 {
1126         struct mesh_path *mpath;
1127         struct sta_info *next_hop;
1128         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1129         u8 *target_addr = hdr->addr3;
1130         int err = -ENOENT;
1131 
1132         rcu_read_lock();
1133         mpath = mesh_path_lookup(sdata, target_addr);
1134 
1135         if (!mpath || !(mpath->flags & MESH_PATH_ACTIVE))
1136                 goto endlookup;
1137 
1138         if (time_after(jiffies,
1139                        mpath->exp_time -
1140                        msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) &&
1141             ether_addr_equal(sdata->vif.addr, hdr->addr4) &&
1142             !(mpath->flags & MESH_PATH_RESOLVING) &&
1143             !(mpath->flags & MESH_PATH_FIXED))
1144                 mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
1145 
1146         next_hop = rcu_dereference(mpath->next_hop);
1147         if (next_hop) {
1148                 memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN);
1149                 memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
1150                 ieee80211_mps_set_frame_flags(sdata, next_hop, hdr);
1151                 err = 0;
1152         }
1153 
1154 endlookup:
1155         rcu_read_unlock();
1156         return err;
1157 }
1158 
1159 void mesh_path_timer(unsigned long data)
1160 {
1161         struct mesh_path *mpath = (void *) data;
1162         struct ieee80211_sub_if_data *sdata = mpath->sdata;
1163         int ret;
1164 
1165         if (sdata->local->quiescing)
1166                 return;
1167 
1168         spin_lock_bh(&mpath->state_lock);
1169         if (mpath->flags & MESH_PATH_RESOLVED ||
1170                         (!(mpath->flags & MESH_PATH_RESOLVING))) {
1171                 mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED);
1172                 spin_unlock_bh(&mpath->state_lock);
1173         } else if (mpath->discovery_retries < max_preq_retries(sdata)) {
1174                 ++mpath->discovery_retries;
1175                 mpath->discovery_timeout *= 2;
1176                 mpath->flags &= ~MESH_PATH_REQ_QUEUED;
1177                 spin_unlock_bh(&mpath->state_lock);
1178                 mesh_queue_preq(mpath, 0);
1179         } else {
1180                 mpath->flags = 0;
1181                 mpath->exp_time = jiffies;
1182                 spin_unlock_bh(&mpath->state_lock);
1183                 if (!mpath->is_gate && mesh_gate_num(sdata) > 0) {
1184                         ret = mesh_path_send_to_gates(mpath);
1185                         if (ret)
1186                                 mhwmp_dbg(sdata, "no gate was reachable\n");
1187                 } else
1188                         mesh_path_flush_pending(mpath);
1189         }
1190 }
1191 
1192 void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
1193 {
1194         struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
1195         u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;
1196         u8 flags, target_flags = 0;
1197 
1198         flags = (ifmsh->mshcfg.dot11MeshGateAnnouncementProtocol)
1199                         ? RANN_FLAG_IS_GATE : 0;
1200 
1201         switch (ifmsh->mshcfg.dot11MeshHWMPRootMode) {
1202         case IEEE80211_PROACTIVE_RANN:
1203                 mesh_path_sel_frame_tx(MPATH_RANN, flags, sdata->vif.addr,
1204                                        ++ifmsh->sn, 0, NULL, 0, broadcast_addr,
1205                                        0, ifmsh->mshcfg.element_ttl,
1206                                        interval, 0, 0, sdata);
1207                 break;
1208         case IEEE80211_PROACTIVE_PREQ_WITH_PREP:
1209                 flags |= IEEE80211_PREQ_PROACTIVE_PREP_FLAG;
1210         case IEEE80211_PROACTIVE_PREQ_NO_PREP:
1211                 interval = ifmsh->mshcfg.dot11MeshHWMPactivePathToRootTimeout;
1212                 target_flags |= IEEE80211_PREQ_TO_FLAG |
1213                                 IEEE80211_PREQ_USN_FLAG;
1214                 mesh_path_sel_frame_tx(MPATH_PREQ, flags, sdata->vif.addr,
1215                                        ++ifmsh->sn, target_flags,
1216                                        (u8 *) broadcast_addr, 0, broadcast_addr,
1217                                        0, ifmsh->mshcfg.element_ttl, interval,
1218                                        0, ifmsh->preq_id++, sdata);
1219                 break;
1220         default:
1221                 mhwmp_dbg(sdata, "Proactive mechanism not supported\n");
1222                 return;
1223         }
1224 }
1225 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp