00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <linux/slab.h>
00011 #include <linux/etherdevice.h>
00012 #include <asm/unaligned.h>
00013 #include "wme.h"
00014 #include "mesh.h"
00015
00016 #ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG
00017 #define mhwmp_dbg(fmt, args...) \
00018 printk(KERN_DEBUG "Mesh HWMP (%s): " fmt "\n", sdata->name, ##args)
00019 #else
00020 #define mhwmp_dbg(fmt, args...) do { (void)(0); } while (0)
00021 #endif
00022
00023 #define TEST_FRAME_LEN 8192
00024 #define MAX_METRIC 0xffffffff
00025 #define ARITH_SHIFT 8
00026
00027
00028 #define MESH_FRAME_QUEUE_LEN 10
00029 #define MAX_PREQ_QUEUE_LEN 64
00030
00031
00032 #define MP_F_DO 0x1
00033
00034 #define MP_F_RF 0x2
00035
00036 #define MP_F_USN 0x01
00037
00038 #define MP_F_RCODE 0x02
00039
00040 static void mesh_queue_preq(struct mesh_path *, u8);
00041
00042 static inline u32 u32_field_get(u8 *preq_elem, int offset, bool ae)
00043 {
00044 if (ae)
00045 offset += 6;
00046 return get_unaligned_le32(preq_elem + offset);
00047 }
00048
00049 static inline u32 u16_field_get(u8 *preq_elem, int offset, bool ae)
00050 {
00051 if (ae)
00052 offset += 6;
00053 return get_unaligned_le16(preq_elem + offset);
00054 }
00055
00056
00057 #define AE_F (1<<6)
00058 #define AE_F_SET(x) (*x & AE_F)
00059 #define PREQ_IE_FLAGS(x) (*(x))
00060 #define PREQ_IE_HOPCOUNT(x) (*(x + 1))
00061 #define PREQ_IE_TTL(x) (*(x + 2))
00062 #define PREQ_IE_PREQ_ID(x) u32_field_get(x, 3, 0)
00063 #define PREQ_IE_ORIG_ADDR(x) (x + 7)
00064 #define PREQ_IE_ORIG_SN(x) u32_field_get(x, 13, 0)
00065 #define PREQ_IE_LIFETIME(x) u32_field_get(x, 17, AE_F_SET(x))
00066 #define PREQ_IE_METRIC(x) u32_field_get(x, 21, AE_F_SET(x))
00067 #define PREQ_IE_TARGET_F(x) (*(AE_F_SET(x) ? x + 32 : x + 26))
00068 #define PREQ_IE_TARGET_ADDR(x) (AE_F_SET(x) ? x + 33 : x + 27)
00069 #define PREQ_IE_TARGET_SN(x) u32_field_get(x, 33, AE_F_SET(x))
00070
00071
00072 #define PREP_IE_FLAGS(x) PREQ_IE_FLAGS(x)
00073 #define PREP_IE_HOPCOUNT(x) PREQ_IE_HOPCOUNT(x)
00074 #define PREP_IE_TTL(x) PREQ_IE_TTL(x)
00075 #define PREP_IE_ORIG_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21)
00076 #define PREP_IE_ORIG_SN(x) u32_field_get(x, 27, AE_F_SET(x))
00077 #define PREP_IE_LIFETIME(x) u32_field_get(x, 13, AE_F_SET(x))
00078 #define PREP_IE_METRIC(x) u32_field_get(x, 17, AE_F_SET(x))
00079 #define PREP_IE_TARGET_ADDR(x) (x + 3)
00080 #define PREP_IE_TARGET_SN(x) u32_field_get(x, 9, 0)
00081
00082 #define PERR_IE_TTL(x) (*(x))
00083 #define PERR_IE_TARGET_FLAGS(x) (*(x + 2))
00084 #define PERR_IE_TARGET_ADDR(x) (x + 3)
00085 #define PERR_IE_TARGET_SN(x) u32_field_get(x, 9, 0)
00086 #define PERR_IE_TARGET_RCODE(x) u16_field_get(x, 13, 0)
00087
00088 #define MSEC_TO_TU(x) (x*1000/1024)
00089 #define SN_GT(x, y) ((s32)(y - x) < 0)
00090 #define SN_LT(x, y) ((s32)(x - y) < 0)
00091
00092 #define net_traversal_jiffies(s) \
00093 msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime)
00094 #define default_lifetime(s) \
00095 MSEC_TO_TU(s->u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout)
00096 #define min_preq_int_jiff(s) \
00097 (msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval))
00098 #define max_preq_retries(s) (s->u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries)
00099 #define disc_timeout_jiff(s) \
00100 msecs_to_jiffies(sdata->u.mesh.mshcfg.min_discovery_timeout)
00101
00102 enum mpath_frame_type {
00103 MPATH_PREQ = 0,
00104 MPATH_PREP,
00105 MPATH_PERR,
00106 MPATH_RANN
00107 };
00108
00109 static const u8 broadcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
00110
00111 static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
00112 u8 *orig_addr, __le32 orig_sn, u8 target_flags, u8 *target,
00113 __le32 target_sn, const u8 *da, u8 hop_count, u8 ttl,
00114 __le32 lifetime, __le32 metric, __le32 preq_id,
00115 struct ieee80211_sub_if_data *sdata)
00116 {
00117 struct ieee80211_local *local = sdata->local;
00118 struct sk_buff *skb;
00119 struct ieee80211_mgmt *mgmt;
00120 u8 *pos, ie_len;
00121 int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) +
00122 sizeof(mgmt->u.action.u.mesh_action);
00123
00124 skb = dev_alloc_skb(local->tx_headroom +
00125 hdr_len +
00126 2 + 37);
00127 if (!skb)
00128 return -1;
00129 skb_reserve(skb, local->tx_headroom);
00130 mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
00131 memset(mgmt, 0, hdr_len);
00132 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
00133 IEEE80211_STYPE_ACTION);
00134
00135 memcpy(mgmt->da, da, ETH_ALEN);
00136 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
00137
00138 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
00139 mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION;
00140 mgmt->u.action.u.mesh_action.action_code =
00141 WLAN_MESH_ACTION_HWMP_PATH_SELECTION;
00142
00143 switch (action) {
00144 case MPATH_PREQ:
00145 mhwmp_dbg("sending PREQ to %pM", target);
00146 ie_len = 37;
00147 pos = skb_put(skb, 2 + ie_len);
00148 *pos++ = WLAN_EID_PREQ;
00149 break;
00150 case MPATH_PREP:
00151 mhwmp_dbg("sending PREP to %pM", target);
00152 ie_len = 31;
00153 pos = skb_put(skb, 2 + ie_len);
00154 *pos++ = WLAN_EID_PREP;
00155 break;
00156 case MPATH_RANN:
00157 mhwmp_dbg("sending RANN from %pM", orig_addr);
00158 ie_len = sizeof(struct ieee80211_rann_ie);
00159 pos = skb_put(skb, 2 + ie_len);
00160 *pos++ = WLAN_EID_RANN;
00161 break;
00162 default:
00163 kfree_skb(skb);
00164 return -ENOTSUPP;
00165 break;
00166 }
00167 *pos++ = ie_len;
00168 *pos++ = flags;
00169 *pos++ = hop_count;
00170 *pos++ = ttl;
00171 if (action == MPATH_PREP) {
00172 memcpy(pos, target, ETH_ALEN);
00173 pos += ETH_ALEN;
00174 memcpy(pos, &target_sn, 4);
00175 pos += 4;
00176 } else {
00177 if (action == MPATH_PREQ) {
00178 memcpy(pos, &preq_id, 4);
00179 pos += 4;
00180 }
00181 memcpy(pos, orig_addr, ETH_ALEN);
00182 pos += ETH_ALEN;
00183 memcpy(pos, &orig_sn, 4);
00184 pos += 4;
00185 }
00186 memcpy(pos, &lifetime, 4);
00187 pos += 4;
00188 memcpy(pos, &metric, 4);
00189 pos += 4;
00190 if (action == MPATH_PREQ) {
00191 *pos++ = 1;
00192 *pos++ = target_flags;
00193 memcpy(pos, target, ETH_ALEN);
00194 pos += ETH_ALEN;
00195 memcpy(pos, &target_sn, 4);
00196 pos += 4;
00197 } else if (action == MPATH_PREP) {
00198 memcpy(pos, orig_addr, ETH_ALEN);
00199 pos += ETH_ALEN;
00200 memcpy(pos, &orig_sn, 4);
00201 pos += 4;
00202 }
00203
00204 ieee80211_tx_skb(sdata, skb);
00205 return 0;
00206 }
00207
00208
00209
00210
00211 static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata,
00212 struct sk_buff *skb)
00213 {
00214 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
00215
00216 skb_set_mac_header(skb, 0);
00217 skb_set_network_header(skb, 0);
00218 skb_set_transport_header(skb, 0);
00219
00220
00221 skb_set_queue_mapping(skb, IEEE80211_AC_VO);
00222 skb->priority = 7;
00223
00224 info->control.vif = &sdata->vif;
00225 ieee80211_set_qos_hdr(sdata, skb);
00226 }
00227
00240 int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
00241 __le16 target_rcode, const u8 *ra,
00242 struct ieee80211_sub_if_data *sdata)
00243 {
00244 struct ieee80211_local *local = sdata->local;
00245 struct sk_buff *skb;
00246 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00247 struct ieee80211_mgmt *mgmt;
00248 u8 *pos, ie_len;
00249 int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) +
00250 sizeof(mgmt->u.action.u.mesh_action);
00251
00252 if (time_before(jiffies, ifmsh->next_perr))
00253 return -EAGAIN;
00254
00255 skb = dev_alloc_skb(local->tx_headroom +
00256 hdr_len +
00257 2 + 15 );
00258 if (!skb)
00259 return -1;
00260 skb_reserve(skb, local->tx_headroom);
00261 mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
00262 memset(mgmt, 0, hdr_len);
00263 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
00264 IEEE80211_STYPE_ACTION);
00265
00266 memcpy(mgmt->da, ra, ETH_ALEN);
00267 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
00268
00269 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
00270 mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION;
00271 mgmt->u.action.u.mesh_action.action_code =
00272 WLAN_MESH_ACTION_HWMP_PATH_SELECTION;
00273 ie_len = 15;
00274 pos = skb_put(skb, 2 + ie_len);
00275 *pos++ = WLAN_EID_PERR;
00276 *pos++ = ie_len;
00277
00278 *pos++ = ttl;
00279
00280 *pos++ = 1;
00281
00282
00283
00284
00285 *pos = 0;
00286 if (!target_sn)
00287 *pos |= MP_F_USN;
00288 if (target_rcode)
00289 *pos |= MP_F_RCODE;
00290 pos++;
00291 memcpy(pos, target, ETH_ALEN);
00292 pos += ETH_ALEN;
00293 memcpy(pos, &target_sn, 4);
00294 pos += 4;
00295 memcpy(pos, &target_rcode, 2);
00296
00297
00298 prepare_frame_for_deferred_tx(sdata, skb);
00299 ifmsh->next_perr = TU_TO_EXP_TIME(
00300 ifmsh->mshcfg.dot11MeshHWMPperrMinInterval);
00301 ieee80211_add_pending_skb(local, skb);
00302 return 0;
00303 }
00304
00305 void ieee80211s_update_metric(struct ieee80211_local *local,
00306 struct sta_info *stainfo, struct sk_buff *skb)
00307 {
00308 struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
00309 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
00310 int failed;
00311
00312 if (!ieee80211_is_data(hdr->frame_control))
00313 return;
00314
00315 failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK);
00316
00317
00318 stainfo->fail_avg = ((80 * stainfo->fail_avg + 5) / 100 + 20 * failed);
00319 if (stainfo->fail_avg > 95)
00320 mesh_plink_broken(stainfo);
00321 }
00322
00323 static u32 airtime_link_metric_get(struct ieee80211_local *local,
00324 struct sta_info *sta)
00325 {
00326 struct ieee80211_supported_band *sband;
00327 struct rate_info rinfo;
00328
00329 int device_constant = 1 << ARITH_SHIFT;
00330 int test_frame_len = TEST_FRAME_LEN << ARITH_SHIFT;
00331 int s_unit = 1 << ARITH_SHIFT;
00332 int rate, err;
00333 u32 tx_time, estimated_retx;
00334 u64 result;
00335
00336 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
00337
00338 if (sta->fail_avg >= 100)
00339 return MAX_METRIC;
00340
00341 sta_set_rate_info_tx(sta, &sta->last_tx_rate, &rinfo);
00342 rate = cfg80211_calculate_bitrate(&rinfo);
00343 if (WARN_ON(!rate))
00344 return MAX_METRIC;
00345
00346 err = (sta->fail_avg << ARITH_SHIFT) / 100;
00347
00348
00349
00350
00351 tx_time = (device_constant + 10 * test_frame_len / rate);
00352 estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err));
00353 result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ;
00354 return (u32)result;
00355 }
00356
00373 static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
00374 struct ieee80211_mgmt *mgmt,
00375 u8 *hwmp_ie, enum mpath_frame_type action)
00376 {
00377 struct ieee80211_local *local = sdata->local;
00378 struct mesh_path *mpath;
00379 struct sta_info *sta;
00380 bool fresh_info;
00381 u8 *orig_addr, *ta;
00382 u32 orig_sn, orig_metric;
00383 unsigned long orig_lifetime, exp_time;
00384 u32 last_hop_metric, new_metric;
00385 bool process = true;
00386
00387 rcu_read_lock();
00388 sta = sta_info_get(sdata, mgmt->sa);
00389 if (!sta) {
00390 rcu_read_unlock();
00391 return 0;
00392 }
00393
00394 last_hop_metric = airtime_link_metric_get(local, sta);
00395
00396 fresh_info = true;
00397
00398 switch (action) {
00399 case MPATH_PREQ:
00400 orig_addr = PREQ_IE_ORIG_ADDR(hwmp_ie);
00401 orig_sn = PREQ_IE_ORIG_SN(hwmp_ie);
00402 orig_lifetime = PREQ_IE_LIFETIME(hwmp_ie);
00403 orig_metric = PREQ_IE_METRIC(hwmp_ie);
00404 break;
00405 case MPATH_PREP:
00406
00407
00408
00409
00410
00411 orig_addr = PREP_IE_TARGET_ADDR(hwmp_ie);
00412 orig_sn = PREP_IE_TARGET_SN(hwmp_ie);
00413 orig_lifetime = PREP_IE_LIFETIME(hwmp_ie);
00414 orig_metric = PREP_IE_METRIC(hwmp_ie);
00415 break;
00416 default:
00417 rcu_read_unlock();
00418 return 0;
00419 }
00420 new_metric = orig_metric + last_hop_metric;
00421 if (new_metric < orig_metric)
00422 new_metric = MAX_METRIC;
00423 exp_time = TU_TO_EXP_TIME(orig_lifetime);
00424
00425 if (ether_addr_equal(orig_addr, sdata->vif.addr)) {
00426
00427
00428
00429 process = false;
00430 fresh_info = false;
00431 } else {
00432 mpath = mesh_path_lookup(orig_addr, sdata);
00433 if (mpath) {
00434 spin_lock_bh(&mpath->state_lock);
00435 if (mpath->flags & MESH_PATH_FIXED)
00436 fresh_info = false;
00437 else if ((mpath->flags & MESH_PATH_ACTIVE) &&
00438 (mpath->flags & MESH_PATH_SN_VALID)) {
00439 if (SN_GT(mpath->sn, orig_sn) ||
00440 (mpath->sn == orig_sn &&
00441 new_metric >= mpath->metric)) {
00442 process = false;
00443 fresh_info = false;
00444 }
00445 }
00446 } else {
00447 mesh_path_add(orig_addr, sdata);
00448 mpath = mesh_path_lookup(orig_addr, sdata);
00449 if (!mpath) {
00450 rcu_read_unlock();
00451 return 0;
00452 }
00453 spin_lock_bh(&mpath->state_lock);
00454 }
00455
00456 if (fresh_info) {
00457 mesh_path_assign_nexthop(mpath, sta);
00458 mpath->flags |= MESH_PATH_SN_VALID;
00459 mpath->metric = new_metric;
00460 mpath->sn = orig_sn;
00461 mpath->exp_time = time_after(mpath->exp_time, exp_time)
00462 ? mpath->exp_time : exp_time;
00463 mesh_path_activate(mpath);
00464 spin_unlock_bh(&mpath->state_lock);
00465 mesh_path_tx_pending(mpath);
00466
00467
00468
00469 } else
00470 spin_unlock_bh(&mpath->state_lock);
00471 }
00472
00473
00474 ta = mgmt->sa;
00475 if (ether_addr_equal(orig_addr, ta))
00476 fresh_info = false;
00477 else {
00478 fresh_info = true;
00479
00480 mpath = mesh_path_lookup(ta, sdata);
00481 if (mpath) {
00482 spin_lock_bh(&mpath->state_lock);
00483 if ((mpath->flags & MESH_PATH_FIXED) ||
00484 ((mpath->flags & MESH_PATH_ACTIVE) &&
00485 (last_hop_metric > mpath->metric)))
00486 fresh_info = false;
00487 } else {
00488 mesh_path_add(ta, sdata);
00489 mpath = mesh_path_lookup(ta, sdata);
00490 if (!mpath) {
00491 rcu_read_unlock();
00492 return 0;
00493 }
00494 spin_lock_bh(&mpath->state_lock);
00495 }
00496
00497 if (fresh_info) {
00498 mesh_path_assign_nexthop(mpath, sta);
00499 mpath->metric = last_hop_metric;
00500 mpath->exp_time = time_after(mpath->exp_time, exp_time)
00501 ? mpath->exp_time : exp_time;
00502 mesh_path_activate(mpath);
00503 spin_unlock_bh(&mpath->state_lock);
00504 mesh_path_tx_pending(mpath);
00505 } else
00506 spin_unlock_bh(&mpath->state_lock);
00507 }
00508
00509 rcu_read_unlock();
00510
00511 return process ? new_metric : 0;
00512 }
00513
00514 static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
00515 struct ieee80211_mgmt *mgmt,
00516 u8 *preq_elem, u32 metric)
00517 {
00518 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00519 struct mesh_path *mpath = NULL;
00520 u8 *target_addr, *orig_addr;
00521 const u8 *da;
00522 u8 target_flags, ttl;
00523 u32 orig_sn, target_sn, lifetime;
00524 bool reply = false;
00525 bool forward = true;
00526
00527
00528 target_addr = PREQ_IE_TARGET_ADDR(preq_elem);
00529 orig_addr = PREQ_IE_ORIG_ADDR(preq_elem);
00530 target_sn = PREQ_IE_TARGET_SN(preq_elem);
00531 orig_sn = PREQ_IE_ORIG_SN(preq_elem);
00532 target_flags = PREQ_IE_TARGET_F(preq_elem);
00533
00534 mhwmp_dbg("received PREQ from %pM", orig_addr);
00535
00536 if (ether_addr_equal(target_addr, sdata->vif.addr)) {
00537 mhwmp_dbg("PREQ is for us");
00538 forward = false;
00539 reply = true;
00540 metric = 0;
00541 if (time_after(jiffies, ifmsh->last_sn_update +
00542 net_traversal_jiffies(sdata)) ||
00543 time_before(jiffies, ifmsh->last_sn_update)) {
00544 target_sn = ++ifmsh->sn;
00545 ifmsh->last_sn_update = jiffies;
00546 }
00547 } else {
00548 rcu_read_lock();
00549 mpath = mesh_path_lookup(target_addr, sdata);
00550 if (mpath) {
00551 if ((!(mpath->flags & MESH_PATH_SN_VALID)) ||
00552 SN_LT(mpath->sn, target_sn)) {
00553 mpath->sn = target_sn;
00554 mpath->flags |= MESH_PATH_SN_VALID;
00555 } else if ((!(target_flags & MP_F_DO)) &&
00556 (mpath->flags & MESH_PATH_ACTIVE)) {
00557 reply = true;
00558 metric = mpath->metric;
00559 target_sn = mpath->sn;
00560 if (target_flags & MP_F_RF)
00561 target_flags |= MP_F_DO;
00562 else
00563 forward = false;
00564 }
00565 }
00566 rcu_read_unlock();
00567 }
00568
00569 if (reply) {
00570 lifetime = PREQ_IE_LIFETIME(preq_elem);
00571 ttl = ifmsh->mshcfg.element_ttl;
00572 if (ttl != 0) {
00573 mhwmp_dbg("replying to the PREQ");
00574 mesh_path_sel_frame_tx(MPATH_PREP, 0, orig_addr,
00575 cpu_to_le32(orig_sn), 0, target_addr,
00576 cpu_to_le32(target_sn), mgmt->sa, 0, ttl,
00577 cpu_to_le32(lifetime), cpu_to_le32(metric),
00578 0, sdata);
00579 } else
00580 ifmsh->mshstats.dropped_frames_ttl++;
00581 }
00582
00583 if (forward && ifmsh->mshcfg.dot11MeshForwarding) {
00584 u32 preq_id;
00585 u8 hopcount, flags;
00586
00587 ttl = PREQ_IE_TTL(preq_elem);
00588 lifetime = PREQ_IE_LIFETIME(preq_elem);
00589 if (ttl <= 1) {
00590 ifmsh->mshstats.dropped_frames_ttl++;
00591 return;
00592 }
00593 mhwmp_dbg("forwarding the PREQ from %pM", orig_addr);
00594 --ttl;
00595 flags = PREQ_IE_FLAGS(preq_elem);
00596 preq_id = PREQ_IE_PREQ_ID(preq_elem);
00597 hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1;
00598 da = (mpath && mpath->is_root) ?
00599 mpath->rann_snd_addr : broadcast_addr;
00600 mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr,
00601 cpu_to_le32(orig_sn), target_flags, target_addr,
00602 cpu_to_le32(target_sn), da,
00603 hopcount, ttl, cpu_to_le32(lifetime),
00604 cpu_to_le32(metric), cpu_to_le32(preq_id),
00605 sdata);
00606 if (!is_multicast_ether_addr(da))
00607 ifmsh->mshstats.fwded_unicast++;
00608 else
00609 ifmsh->mshstats.fwded_mcast++;
00610 ifmsh->mshstats.fwded_frames++;
00611 }
00612 }
00613
00614
00615 static inline struct sta_info *
00616 next_hop_deref_protected(struct mesh_path *mpath)
00617 {
00618 return rcu_dereference_protected(mpath->next_hop,
00619 lockdep_is_held(&mpath->state_lock));
00620 }
00621
00622
00623 static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
00624 struct ieee80211_mgmt *mgmt,
00625 u8 *prep_elem, u32 metric)
00626 {
00627 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00628 struct mesh_path *mpath;
00629 u8 *target_addr, *orig_addr;
00630 u8 ttl, hopcount, flags;
00631 u8 next_hop[ETH_ALEN];
00632 u32 target_sn, orig_sn, lifetime;
00633
00634 mhwmp_dbg("received PREP from %pM", PREP_IE_ORIG_ADDR(prep_elem));
00635
00636 orig_addr = PREP_IE_ORIG_ADDR(prep_elem);
00637 if (ether_addr_equal(orig_addr, sdata->vif.addr))
00638
00639 return;
00640
00641 if (!ifmsh->mshcfg.dot11MeshForwarding)
00642 return;
00643
00644 ttl = PREP_IE_TTL(prep_elem);
00645 if (ttl <= 1) {
00646 sdata->u.mesh.mshstats.dropped_frames_ttl++;
00647 return;
00648 }
00649
00650 rcu_read_lock();
00651 mpath = mesh_path_lookup(orig_addr, sdata);
00652 if (mpath)
00653 spin_lock_bh(&mpath->state_lock);
00654 else
00655 goto fail;
00656 if (!(mpath->flags & MESH_PATH_ACTIVE)) {
00657 spin_unlock_bh(&mpath->state_lock);
00658 goto fail;
00659 }
00660 memcpy(next_hop, next_hop_deref_protected(mpath)->sta.addr, ETH_ALEN);
00661 spin_unlock_bh(&mpath->state_lock);
00662 --ttl;
00663 flags = PREP_IE_FLAGS(prep_elem);
00664 lifetime = PREP_IE_LIFETIME(prep_elem);
00665 hopcount = PREP_IE_HOPCOUNT(prep_elem) + 1;
00666 target_addr = PREP_IE_TARGET_ADDR(prep_elem);
00667 target_sn = PREP_IE_TARGET_SN(prep_elem);
00668 orig_sn = PREP_IE_ORIG_SN(prep_elem);
00669
00670 mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr,
00671 cpu_to_le32(orig_sn), 0, target_addr,
00672 cpu_to_le32(target_sn), next_hop, hopcount,
00673 ttl, cpu_to_le32(lifetime), cpu_to_le32(metric),
00674 0, sdata);
00675 rcu_read_unlock();
00676
00677 sdata->u.mesh.mshstats.fwded_unicast++;
00678 sdata->u.mesh.mshstats.fwded_frames++;
00679 return;
00680
00681 fail:
00682 rcu_read_unlock();
00683 sdata->u.mesh.mshstats.dropped_frames_no_route++;
00684 }
00685
00686 static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata,
00687 struct ieee80211_mgmt *mgmt, u8 *perr_elem)
00688 {
00689 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00690 struct mesh_path *mpath;
00691 u8 ttl;
00692 u8 *ta, *target_addr;
00693 u32 target_sn;
00694 u16 target_rcode;
00695
00696 ta = mgmt->sa;
00697 ttl = PERR_IE_TTL(perr_elem);
00698 if (ttl <= 1) {
00699 ifmsh->mshstats.dropped_frames_ttl++;
00700 return;
00701 }
00702 ttl--;
00703 target_addr = PERR_IE_TARGET_ADDR(perr_elem);
00704 target_sn = PERR_IE_TARGET_SN(perr_elem);
00705 target_rcode = PERR_IE_TARGET_RCODE(perr_elem);
00706
00707 rcu_read_lock();
00708 mpath = mesh_path_lookup(target_addr, sdata);
00709 if (mpath) {
00710 struct sta_info *sta;
00711
00712 spin_lock_bh(&mpath->state_lock);
00713 sta = next_hop_deref_protected(mpath);
00714 if (mpath->flags & MESH_PATH_ACTIVE &&
00715 ether_addr_equal(ta, sta->sta.addr) &&
00716 (!(mpath->flags & MESH_PATH_SN_VALID) ||
00717 SN_GT(target_sn, mpath->sn))) {
00718 mpath->flags &= ~MESH_PATH_ACTIVE;
00719 mpath->sn = target_sn;
00720 spin_unlock_bh(&mpath->state_lock);
00721 if (!ifmsh->mshcfg.dot11MeshForwarding)
00722 goto endperr;
00723 mesh_path_error_tx(ttl, target_addr, cpu_to_le32(target_sn),
00724 cpu_to_le16(target_rcode),
00725 broadcast_addr, sdata);
00726 } else
00727 spin_unlock_bh(&mpath->state_lock);
00728 }
00729 endperr:
00730 rcu_read_unlock();
00731 }
00732
00733 static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
00734 struct ieee80211_mgmt *mgmt,
00735 struct ieee80211_rann_ie *rann)
00736 {
00737 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00738 struct ieee80211_local *local = sdata->local;
00739 struct sta_info *sta;
00740 struct mesh_path *mpath;
00741 u8 ttl, flags, hopcount;
00742 u8 *orig_addr;
00743 u32 orig_sn, metric, metric_txsta, interval;
00744 bool root_is_gate;
00745
00746 ttl = rann->rann_ttl;
00747 if (ttl <= 1) {
00748 ifmsh->mshstats.dropped_frames_ttl++;
00749 return;
00750 }
00751 ttl--;
00752 flags = rann->rann_flags;
00753 root_is_gate = !!(flags & RANN_FLAG_IS_GATE);
00754 orig_addr = rann->rann_addr;
00755 orig_sn = le32_to_cpu(rann->rann_seq);
00756 interval = le32_to_cpu(rann->rann_interval);
00757 hopcount = rann->rann_hopcount;
00758 hopcount++;
00759 metric = le32_to_cpu(rann->rann_metric);
00760
00761
00762 if (ether_addr_equal(orig_addr, sdata->vif.addr))
00763 return;
00764
00765 mhwmp_dbg("received RANN from %pM via neighbour %pM (is_gate=%d)",
00766 orig_addr, mgmt->sa, root_is_gate);
00767
00768 rcu_read_lock();
00769 sta = sta_info_get(sdata, mgmt->sa);
00770 if (!sta) {
00771 rcu_read_unlock();
00772 return;
00773 }
00774
00775 metric_txsta = airtime_link_metric_get(local, sta);
00776
00777 mpath = mesh_path_lookup(orig_addr, sdata);
00778 if (!mpath) {
00779 mesh_path_add(orig_addr, sdata);
00780 mpath = mesh_path_lookup(orig_addr, sdata);
00781 if (!mpath) {
00782 rcu_read_unlock();
00783 sdata->u.mesh.mshstats.dropped_frames_no_route++;
00784 return;
00785 }
00786 }
00787
00788 if ((!(mpath->flags & (MESH_PATH_ACTIVE | MESH_PATH_RESOLVING)) ||
00789 time_after(jiffies, mpath->exp_time - 1*HZ)) &&
00790 !(mpath->flags & MESH_PATH_FIXED)) {
00791 mhwmp_dbg("%s time to refresh root mpath %pM", sdata->name,
00792 orig_addr);
00793 mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
00794 }
00795
00796 if ((SN_LT(mpath->sn, orig_sn) || (mpath->sn == orig_sn &&
00797 metric < mpath->rann_metric)) && ifmsh->mshcfg.dot11MeshForwarding) {
00798 mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
00799 cpu_to_le32(orig_sn),
00800 0, NULL, 0, broadcast_addr,
00801 hopcount, ttl, cpu_to_le32(interval),
00802 cpu_to_le32(metric + metric_txsta),
00803 0, sdata);
00804 mpath->sn = orig_sn;
00805 mpath->rann_metric = metric + metric_txsta;
00806
00807
00808 memcpy(mpath->rann_snd_addr, mgmt->sa, ETH_ALEN);
00809 }
00810
00811 mpath->is_root = true;
00812
00813 if (root_is_gate)
00814 mesh_path_add_gate(mpath);
00815
00816 rcu_read_unlock();
00817 }
00818
00819
00820 void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
00821 struct ieee80211_mgmt *mgmt,
00822 size_t len)
00823 {
00824 struct ieee802_11_elems elems;
00825 size_t baselen;
00826 u32 last_hop_metric;
00827 struct sta_info *sta;
00828
00829
00830 if (len < IEEE80211_MIN_ACTION_SIZE + 1)
00831 return;
00832
00833 rcu_read_lock();
00834 sta = sta_info_get(sdata, mgmt->sa);
00835 if (!sta || sta->plink_state != NL80211_PLINK_ESTAB) {
00836 rcu_read_unlock();
00837 return;
00838 }
00839 rcu_read_unlock();
00840
00841 baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt;
00842 ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
00843 len - baselen, &elems);
00844
00845 if (elems.preq) {
00846 if (elems.preq_len != 37)
00847
00848 return;
00849 last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.preq,
00850 MPATH_PREQ);
00851 if (last_hop_metric)
00852 hwmp_preq_frame_process(sdata, mgmt, elems.preq,
00853 last_hop_metric);
00854 }
00855 if (elems.prep) {
00856 if (elems.prep_len != 31)
00857
00858 return;
00859 last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.prep,
00860 MPATH_PREP);
00861 if (last_hop_metric)
00862 hwmp_prep_frame_process(sdata, mgmt, elems.prep,
00863 last_hop_metric);
00864 }
00865 if (elems.perr) {
00866 if (elems.perr_len != 15)
00867
00868 return;
00869 hwmp_perr_frame_process(sdata, mgmt, elems.perr);
00870 }
00871 if (elems.rann)
00872 hwmp_rann_frame_process(sdata, mgmt, elems.rann);
00873 }
00874
00884 static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
00885 {
00886 struct ieee80211_sub_if_data *sdata = mpath->sdata;
00887 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00888 struct mesh_preq_queue *preq_node;
00889
00890 preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_ATOMIC);
00891 if (!preq_node) {
00892 mhwmp_dbg("could not allocate PREQ node");
00893 return;
00894 }
00895
00896 spin_lock_bh(&ifmsh->mesh_preq_queue_lock);
00897 if (ifmsh->preq_queue_len == MAX_PREQ_QUEUE_LEN) {
00898 spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
00899 kfree(preq_node);
00900 if (printk_ratelimit())
00901 mhwmp_dbg("PREQ node queue full");
00902 return;
00903 }
00904
00905 spin_lock(&mpath->state_lock);
00906 if (mpath->flags & MESH_PATH_REQ_QUEUED) {
00907 spin_unlock(&mpath->state_lock);
00908 spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
00909 kfree(preq_node);
00910 return;
00911 }
00912
00913 memcpy(preq_node->dst, mpath->dst, ETH_ALEN);
00914 preq_node->flags = flags;
00915
00916 mpath->flags |= MESH_PATH_REQ_QUEUED;
00917 spin_unlock(&mpath->state_lock);
00918
00919 list_add_tail(&preq_node->list, &ifmsh->preq_queue.list);
00920 ++ifmsh->preq_queue_len;
00921 spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
00922
00923 if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata)))
00924 ieee80211_queue_work(&sdata->local->hw, &sdata->work);
00925
00926 else if (time_before(jiffies, ifmsh->last_preq)) {
00927
00928
00929
00930 ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1;
00931 ieee80211_queue_work(&sdata->local->hw, &sdata->work);
00932 } else
00933 mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq +
00934 min_preq_int_jiff(sdata));
00935 }
00936
00942 void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
00943 {
00944 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00945 struct mesh_preq_queue *preq_node;
00946 struct mesh_path *mpath;
00947 u8 ttl, target_flags;
00948 const u8 *da;
00949 u32 lifetime;
00950
00951 spin_lock_bh(&ifmsh->mesh_preq_queue_lock);
00952 if (!ifmsh->preq_queue_len ||
00953 time_before(jiffies, ifmsh->last_preq +
00954 min_preq_int_jiff(sdata))) {
00955 spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
00956 return;
00957 }
00958
00959 preq_node = list_first_entry(&ifmsh->preq_queue.list,
00960 struct mesh_preq_queue, list);
00961 list_del(&preq_node->list);
00962 --ifmsh->preq_queue_len;
00963 spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
00964
00965 rcu_read_lock();
00966 mpath = mesh_path_lookup(preq_node->dst, sdata);
00967 if (!mpath)
00968 goto enddiscovery;
00969
00970 spin_lock_bh(&mpath->state_lock);
00971 mpath->flags &= ~MESH_PATH_REQ_QUEUED;
00972 if (preq_node->flags & PREQ_Q_F_START) {
00973 if (mpath->flags & MESH_PATH_RESOLVING) {
00974 spin_unlock_bh(&mpath->state_lock);
00975 goto enddiscovery;
00976 } else {
00977 mpath->flags &= ~MESH_PATH_RESOLVED;
00978 mpath->flags |= MESH_PATH_RESOLVING;
00979 mpath->discovery_retries = 0;
00980 mpath->discovery_timeout = disc_timeout_jiff(sdata);
00981 }
00982 } else if (!(mpath->flags & MESH_PATH_RESOLVING) ||
00983 mpath->flags & MESH_PATH_RESOLVED) {
00984 mpath->flags &= ~MESH_PATH_RESOLVING;
00985 spin_unlock_bh(&mpath->state_lock);
00986 goto enddiscovery;
00987 }
00988
00989 ifmsh->last_preq = jiffies;
00990
00991 if (time_after(jiffies, ifmsh->last_sn_update +
00992 net_traversal_jiffies(sdata)) ||
00993 time_before(jiffies, ifmsh->last_sn_update)) {
00994 ++ifmsh->sn;
00995 sdata->u.mesh.last_sn_update = jiffies;
00996 }
00997 lifetime = default_lifetime(sdata);
00998 ttl = sdata->u.mesh.mshcfg.element_ttl;
00999 if (ttl == 0) {
01000 sdata->u.mesh.mshstats.dropped_frames_ttl++;
01001 spin_unlock_bh(&mpath->state_lock);
01002 goto enddiscovery;
01003 }
01004
01005 if (preq_node->flags & PREQ_Q_F_REFRESH)
01006 target_flags = MP_F_DO;
01007 else
01008 target_flags = MP_F_RF;
01009
01010 spin_unlock_bh(&mpath->state_lock);
01011 da = (mpath->is_root) ? mpath->rann_snd_addr : broadcast_addr;
01012 mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->vif.addr,
01013 cpu_to_le32(ifmsh->sn), target_flags, mpath->dst,
01014 cpu_to_le32(mpath->sn), da, 0,
01015 ttl, cpu_to_le32(lifetime), 0,
01016 cpu_to_le32(ifmsh->preq_id++), sdata);
01017 mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout);
01018
01019 enddiscovery:
01020 rcu_read_unlock();
01021 kfree(preq_node);
01022 }
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033 int mesh_nexthop_resolve(struct sk_buff *skb,
01034 struct ieee80211_sub_if_data *sdata)
01035 {
01036 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
01037 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
01038 struct mesh_path *mpath;
01039 struct sk_buff *skb_to_free = NULL;
01040 u8 *target_addr = hdr->addr3;
01041 int err = 0;
01042
01043 rcu_read_lock();
01044 err = mesh_nexthop_lookup(skb, sdata);
01045 if (!err)
01046 goto endlookup;
01047
01048
01049 mpath = mesh_path_lookup(target_addr, sdata);
01050 if (!mpath) {
01051 mesh_path_add(target_addr, sdata);
01052 mpath = mesh_path_lookup(target_addr, sdata);
01053 if (!mpath) {
01054 mesh_path_discard_frame(skb, sdata);
01055 err = -ENOSPC;
01056 goto endlookup;
01057 }
01058 }
01059
01060 if (!(mpath->flags & MESH_PATH_RESOLVING))
01061 mesh_queue_preq(mpath, PREQ_Q_F_START);
01062
01063 if (skb_queue_len(&mpath->frame_queue) >= MESH_FRAME_QUEUE_LEN)
01064 skb_to_free = skb_dequeue(&mpath->frame_queue);
01065
01066 info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
01067 ieee80211_set_qos_hdr(sdata, skb);
01068 skb_queue_tail(&mpath->frame_queue, skb);
01069 err = -ENOENT;
01070 if (skb_to_free)
01071 mesh_path_discard_frame(skb_to_free, sdata);
01072
01073 endlookup:
01074 rcu_read_unlock();
01075 return err;
01076 }
01087 int mesh_nexthop_lookup(struct sk_buff *skb,
01088 struct ieee80211_sub_if_data *sdata)
01089 {
01090 struct mesh_path *mpath;
01091 struct sta_info *next_hop;
01092 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
01093 u8 *target_addr = hdr->addr3;
01094 int err = -ENOENT;
01095
01096 rcu_read_lock();
01097 mpath = mesh_path_lookup(target_addr, sdata);
01098
01099 if (!mpath || !(mpath->flags & MESH_PATH_ACTIVE))
01100 goto endlookup;
01101
01102 if (time_after(jiffies,
01103 mpath->exp_time -
01104 msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) &&
01105 ether_addr_equal(sdata->vif.addr, hdr->addr4) &&
01106 !(mpath->flags & MESH_PATH_RESOLVING) &&
01107 !(mpath->flags & MESH_PATH_FIXED))
01108 mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
01109
01110 next_hop = rcu_dereference(mpath->next_hop);
01111 if (next_hop) {
01112 memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN);
01113 memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
01114 err = 0;
01115 }
01116
01117 endlookup:
01118 rcu_read_unlock();
01119 return err;
01120 }
01121
01122 void mesh_path_timer(unsigned long data)
01123 {
01124 struct mesh_path *mpath = (void *) data;
01125 struct ieee80211_sub_if_data *sdata = mpath->sdata;
01126 int ret;
01127
01128 if (sdata->local->quiescing)
01129 return;
01130
01131 spin_lock_bh(&mpath->state_lock);
01132 if (mpath->flags & MESH_PATH_RESOLVED ||
01133 (!(mpath->flags & MESH_PATH_RESOLVING))) {
01134 mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED);
01135 spin_unlock_bh(&mpath->state_lock);
01136 } else if (mpath->discovery_retries < max_preq_retries(sdata)) {
01137 ++mpath->discovery_retries;
01138 mpath->discovery_timeout *= 2;
01139 mpath->flags &= ~MESH_PATH_REQ_QUEUED;
01140 spin_unlock_bh(&mpath->state_lock);
01141 mesh_queue_preq(mpath, 0);
01142 } else {
01143 mpath->flags = 0;
01144 mpath->exp_time = jiffies;
01145 spin_unlock_bh(&mpath->state_lock);
01146 if (!mpath->is_gate && mesh_gate_num(sdata) > 0) {
01147 ret = mesh_path_send_to_gates(mpath);
01148 if (ret)
01149 mhwmp_dbg("no gate was reachable");
01150 } else
01151 mesh_path_flush_pending(mpath);
01152 }
01153 }
01154
01155 void
01156 mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
01157 {
01158 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
01159 u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;
01160 u8 flags;
01161
01162 flags = (ifmsh->mshcfg.dot11MeshGateAnnouncementProtocol)
01163 ? RANN_FLAG_IS_GATE : 0;
01164 mesh_path_sel_frame_tx(MPATH_RANN, flags, sdata->vif.addr,
01165 cpu_to_le32(++ifmsh->sn),
01166 0, NULL, 0, broadcast_addr,
01167 0, sdata->u.mesh.mshcfg.element_ttl,
01168 cpu_to_le32(interval), 0, 0, sdata);
01169 }