00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <linux/slab.h>
00012 #include <asm/unaligned.h>
00013 #include "ieee80211_i.h"
00014 #include "mesh.h"
00015
00016 #define TMR_RUNNING_HK 0
00017 #define TMR_RUNNING_MP 1
00018 #define TMR_RUNNING_MPR 2
00019
00020 int mesh_allocated;
00021 static struct kmem_cache *rm_cache;
00022
00023 #ifdef CONFIG_MAC80211_MESH
00024 bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt)
00025 {
00026 return (mgmt->u.action.u.mesh_action.action_code ==
00027 WLAN_MESH_ACTION_HWMP_PATH_SELECTION);
00028 }
00029 #else
00030 bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt)
00031 { return false; }
00032 #endif
00033
00034 void ieee80211s_init(void)
00035 {
00036 mesh_pathtbl_init();
00037 mesh_allocated = 1;
00038 rm_cache = kmem_cache_create("mesh_rmc", sizeof(struct rmc_entry),
00039 0, 0, NULL);
00040 }
00041
00042 void ieee80211s_stop(void)
00043 {
00044 mesh_pathtbl_unregister();
00045 kmem_cache_destroy(rm_cache);
00046 }
00047
00048 static void ieee80211_mesh_housekeeping_timer(unsigned long data)
00049 {
00050 struct ieee80211_sub_if_data *sdata = (void *) data;
00051 struct ieee80211_local *local = sdata->local;
00052 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00053
00054 set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags);
00055
00056 if (local->quiescing) {
00057 set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
00058 return;
00059 }
00060
00061 ieee80211_queue_work(&local->hw, &sdata->work);
00062 }
00063
00073 bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
00074 struct ieee802_11_elems *ie)
00075 {
00076 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00077 struct ieee80211_local *local = sdata->local;
00078 u32 basic_rates = 0;
00079 enum nl80211_channel_type sta_channel_type = NL80211_CHAN_NO_HT;
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 if (!(ifmsh->mesh_id_len == ie->mesh_id_len &&
00092 memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 &&
00093 (ifmsh->mesh_pp_id == ie->mesh_config->meshconf_psel) &&
00094 (ifmsh->mesh_pm_id == ie->mesh_config->meshconf_pmetric) &&
00095 (ifmsh->mesh_cc_id == ie->mesh_config->meshconf_congest) &&
00096 (ifmsh->mesh_sp_id == ie->mesh_config->meshconf_synch) &&
00097 (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth)))
00098 goto mismatch;
00099
00100 ieee80211_sta_get_rates(local, ie, local->oper_channel->band,
00101 &basic_rates);
00102
00103 if (sdata->vif.bss_conf.basic_rates != basic_rates)
00104 goto mismatch;
00105
00106 if (ie->ht_operation)
00107 sta_channel_type =
00108 ieee80211_ht_oper_to_channel_type(ie->ht_operation);
00109
00110
00111 if (ie->ht_operation &&
00112 (local->_oper_channel_type == NL80211_CHAN_HT40MINUS ||
00113 local->_oper_channel_type == NL80211_CHAN_HT40PLUS) &&
00114 (sta_channel_type == NL80211_CHAN_HT40MINUS ||
00115 sta_channel_type == NL80211_CHAN_HT40PLUS) &&
00116 local->_oper_channel_type != sta_channel_type)
00117 goto mismatch;
00118
00119 return true;
00120 mismatch:
00121 return false;
00122 }
00123
00129 bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie)
00130 {
00131 return (ie->mesh_config->meshconf_cap &
00132 MESHCONF_CAPAB_ACCEPT_PLINKS) != 0;
00133 }
00134
00140 void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata)
00141 {
00142 bool free_plinks;
00143
00144
00145
00146
00147
00148
00149
00150 free_plinks = mesh_plink_availables(sdata);
00151
00152 if (free_plinks != sdata->u.mesh.accepting_plinks)
00153 ieee80211_mesh_housekeeping_timer((unsigned long) sdata);
00154 }
00155
00156 int mesh_rmc_init(struct ieee80211_sub_if_data *sdata)
00157 {
00158 int i;
00159
00160 sdata->u.mesh.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL);
00161 if (!sdata->u.mesh.rmc)
00162 return -ENOMEM;
00163 sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1;
00164 for (i = 0; i < RMC_BUCKETS; i++)
00165 INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i].list);
00166 return 0;
00167 }
00168
00169 void mesh_rmc_free(struct ieee80211_sub_if_data *sdata)
00170 {
00171 struct mesh_rmc *rmc = sdata->u.mesh.rmc;
00172 struct rmc_entry *p, *n;
00173 int i;
00174
00175 if (!sdata->u.mesh.rmc)
00176 return;
00177
00178 for (i = 0; i < RMC_BUCKETS; i++)
00179 list_for_each_entry_safe(p, n, &rmc->bucket[i].list, list) {
00180 list_del(&p->list);
00181 kmem_cache_free(rm_cache, p);
00182 }
00183
00184 kfree(rmc);
00185 sdata->u.mesh.rmc = NULL;
00186 }
00187
00200 int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr,
00201 struct ieee80211_sub_if_data *sdata)
00202 {
00203 struct mesh_rmc *rmc = sdata->u.mesh.rmc;
00204 u32 seqnum = 0;
00205 int entries = 0;
00206 u8 idx;
00207 struct rmc_entry *p, *n;
00208
00209
00210 memcpy(&seqnum, &mesh_hdr->seqnum, sizeof(mesh_hdr->seqnum));
00211 idx = le32_to_cpu(mesh_hdr->seqnum) & rmc->idx_mask;
00212 list_for_each_entry_safe(p, n, &rmc->bucket[idx].list, list) {
00213 ++entries;
00214 if (time_after(jiffies, p->exp_time) ||
00215 (entries == RMC_QUEUE_MAX_LEN)) {
00216 list_del(&p->list);
00217 kmem_cache_free(rm_cache, p);
00218 --entries;
00219 } else if ((seqnum == p->seqnum) &&
00220 (ether_addr_equal(sa, p->sa)))
00221 return -1;
00222 }
00223
00224 p = kmem_cache_alloc(rm_cache, GFP_ATOMIC);
00225 if (!p)
00226 return 0;
00227
00228 p->seqnum = seqnum;
00229 p->exp_time = jiffies + RMC_TIMEOUT;
00230 memcpy(p->sa, sa, ETH_ALEN);
00231 list_add(&p->list, &rmc->bucket[idx].list);
00232 return 0;
00233 }
00234
00235 int
00236 mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
00237 {
00238 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00239 u8 *pos, neighbors;
00240 u8 meshconf_len = sizeof(struct ieee80211_meshconf_ie);
00241
00242 if (skb_tailroom(skb) < 2 + meshconf_len)
00243 return -ENOMEM;
00244
00245 pos = skb_put(skb, 2 + meshconf_len);
00246 *pos++ = WLAN_EID_MESH_CONFIG;
00247 *pos++ = meshconf_len;
00248
00249
00250 *pos++ = ifmsh->mesh_pp_id;
00251
00252 *pos++ = ifmsh->mesh_pm_id;
00253
00254 *pos++ = ifmsh->mesh_cc_id;
00255
00256 *pos++ = ifmsh->mesh_sp_id;
00257
00258 *pos++ = ifmsh->mesh_auth_id;
00259
00260 neighbors = atomic_read(&ifmsh->mshstats.estab_plinks);
00261
00262 neighbors = (neighbors > 15) ? 15 : neighbors;
00263 *pos++ = neighbors << 1;
00264
00265 ifmsh->accepting_plinks = mesh_plink_availables(sdata);
00266 *pos = MESHCONF_CAPAB_FORWARDING;
00267 *pos |= ifmsh->accepting_plinks ?
00268 MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00;
00269 *pos++ |= ifmsh->adjusting_tbtt ?
00270 MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00;
00271 *pos++ = 0x00;
00272
00273 return 0;
00274 }
00275
00276 int
00277 mesh_add_meshid_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
00278 {
00279 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00280 u8 *pos;
00281
00282 if (skb_tailroom(skb) < 2 + ifmsh->mesh_id_len)
00283 return -ENOMEM;
00284
00285 pos = skb_put(skb, 2 + ifmsh->mesh_id_len);
00286 *pos++ = WLAN_EID_MESH_ID;
00287 *pos++ = ifmsh->mesh_id_len;
00288 if (ifmsh->mesh_id_len)
00289 memcpy(pos, ifmsh->mesh_id, ifmsh->mesh_id_len);
00290
00291 return 0;
00292 }
00293
00294 int
00295 mesh_add_vendor_ies(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
00296 {
00297 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00298 u8 offset, len;
00299 const u8 *data;
00300
00301 if (!ifmsh->ie || !ifmsh->ie_len)
00302 return 0;
00303
00304
00305 offset = ieee80211_ie_split_vendor(ifmsh->ie, ifmsh->ie_len, 0);
00306
00307 if (offset) {
00308 len = ifmsh->ie_len - offset;
00309 data = ifmsh->ie + offset;
00310 if (skb_tailroom(skb) < len)
00311 return -ENOMEM;
00312 memcpy(skb_put(skb, len), data, len);
00313 }
00314
00315 return 0;
00316 }
00317
00318 int
00319 mesh_add_rsn_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
00320 {
00321 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00322 u8 len = 0;
00323 const u8 *data;
00324
00325 if (!ifmsh->ie || !ifmsh->ie_len)
00326 return 0;
00327
00328
00329 data = ifmsh->ie;
00330 while (data < ifmsh->ie + ifmsh->ie_len) {
00331 if (*data == WLAN_EID_RSN) {
00332 len = data[1] + 2;
00333 break;
00334 }
00335 data++;
00336 }
00337
00338 if (len) {
00339 if (skb_tailroom(skb) < len)
00340 return -ENOMEM;
00341 memcpy(skb_put(skb, len), data, len);
00342 }
00343
00344 return 0;
00345 }
00346
00347 int mesh_add_ds_params_ie(struct sk_buff *skb,
00348 struct ieee80211_sub_if_data *sdata)
00349 {
00350 struct ieee80211_local *local = sdata->local;
00351 struct ieee80211_supported_band *sband;
00352 u8 *pos;
00353
00354 if (skb_tailroom(skb) < 3)
00355 return -ENOMEM;
00356
00357 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
00358 if (sband->band == IEEE80211_BAND_2GHZ) {
00359 pos = skb_put(skb, 2 + 1);
00360 *pos++ = WLAN_EID_DS_PARAMS;
00361 *pos++ = 1;
00362 *pos++ = ieee80211_frequency_to_channel(local->hw.conf.channel->center_freq);
00363 }
00364
00365 return 0;
00366 }
00367
00368 int mesh_add_ht_cap_ie(struct sk_buff *skb,
00369 struct ieee80211_sub_if_data *sdata)
00370 {
00371 struct ieee80211_local *local = sdata->local;
00372 struct ieee80211_supported_band *sband;
00373 u8 *pos;
00374
00375 sband = local->hw.wiphy->bands[local->oper_channel->band];
00376 if (!sband->ht_cap.ht_supported ||
00377 local->_oper_channel_type == NL80211_CHAN_NO_HT)
00378 return 0;
00379
00380 if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap))
00381 return -ENOMEM;
00382
00383 pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_cap));
00384 ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, sband->ht_cap.cap);
00385
00386 return 0;
00387 }
00388
00389 int mesh_add_ht_oper_ie(struct sk_buff *skb,
00390 struct ieee80211_sub_if_data *sdata)
00391 {
00392 struct ieee80211_local *local = sdata->local;
00393 struct ieee80211_channel *channel = local->oper_channel;
00394 enum nl80211_channel_type channel_type = local->_oper_channel_type;
00395 struct ieee80211_supported_band *sband =
00396 local->hw.wiphy->bands[channel->band];
00397 struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap;
00398 u8 *pos;
00399
00400 if (!ht_cap->ht_supported || channel_type == NL80211_CHAN_NO_HT)
00401 return 0;
00402
00403 if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_operation))
00404 return -ENOMEM;
00405
00406 pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation));
00407 ieee80211_ie_build_ht_oper(pos, ht_cap, channel, channel_type,
00408 sdata->vif.bss_conf.ht_operation_mode);
00409
00410 return 0;
00411 }
00412 static void ieee80211_mesh_path_timer(unsigned long data)
00413 {
00414 struct ieee80211_sub_if_data *sdata =
00415 (struct ieee80211_sub_if_data *) data;
00416 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00417 struct ieee80211_local *local = sdata->local;
00418
00419 if (local->quiescing) {
00420 set_bit(TMR_RUNNING_MP, &ifmsh->timers_running);
00421 return;
00422 }
00423
00424 ieee80211_queue_work(&local->hw, &sdata->work);
00425 }
00426
00427 static void ieee80211_mesh_path_root_timer(unsigned long data)
00428 {
00429 struct ieee80211_sub_if_data *sdata =
00430 (struct ieee80211_sub_if_data *) data;
00431 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00432 struct ieee80211_local *local = sdata->local;
00433
00434 set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags);
00435
00436 if (local->quiescing) {
00437 set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running);
00438 return;
00439 }
00440
00441 ieee80211_queue_work(&local->hw, &sdata->work);
00442 }
00443
00444 void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh)
00445 {
00446 if (ifmsh->mshcfg.dot11MeshHWMPRootMode)
00447 set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags);
00448 else {
00449 clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags);
00450
00451 del_timer_sync(&ifmsh->mesh_path_root_timer);
00452 }
00453 }
00454
00465 int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc,
00466 const u8 *meshda, const u8 *meshsa)
00467 {
00468 if (is_multicast_ether_addr(meshda)) {
00469 *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
00470
00471 memcpy(hdr->addr1, meshda, ETH_ALEN);
00472 memcpy(hdr->addr2, meshsa, ETH_ALEN);
00473 memcpy(hdr->addr3, meshsa, ETH_ALEN);
00474 return 24;
00475 } else {
00476 *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
00477
00478 memset(hdr->addr1, 0, ETH_ALEN);
00479 memcpy(hdr->addr2, meshsa, ETH_ALEN);
00480 memcpy(hdr->addr3, meshda, ETH_ALEN);
00481 memcpy(hdr->addr4, meshsa, ETH_ALEN);
00482 return 30;
00483 }
00484 }
00485
00498 int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
00499 struct ieee80211_sub_if_data *sdata, char *addr4or5,
00500 char *addr6)
00501 {
00502 int aelen = 0;
00503 BUG_ON(!addr4or5 && addr6);
00504 memset(meshhdr, 0, sizeof(*meshhdr));
00505 meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
00506 put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum);
00507 sdata->u.mesh.mesh_seqnum++;
00508 if (addr4or5 && !addr6) {
00509 meshhdr->flags |= MESH_FLAGS_AE_A4;
00510 aelen += ETH_ALEN;
00511 memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN);
00512 } else if (addr4or5 && addr6) {
00513 meshhdr->flags |= MESH_FLAGS_AE_A5_A6;
00514 aelen += 2 * ETH_ALEN;
00515 memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN);
00516 memcpy(meshhdr->eaddr2, addr6, ETH_ALEN);
00517 }
00518 return 6 + aelen;
00519 }
00520
00521 static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
00522 struct ieee80211_if_mesh *ifmsh)
00523 {
00524 bool free_plinks;
00525
00526 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
00527 printk(KERN_DEBUG "%s: running mesh housekeeping\n",
00528 sdata->name);
00529 #endif
00530
00531 ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT);
00532 mesh_path_expire(sdata);
00533
00534 free_plinks = mesh_plink_availables(sdata);
00535 if (free_plinks != sdata->u.mesh.accepting_plinks)
00536 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
00537
00538 mod_timer(&ifmsh->housekeeping_timer,
00539 round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
00540 }
00541
00542 static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata)
00543 {
00544 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00545
00546 mesh_path_tx_root_frame(sdata);
00547 mod_timer(&ifmsh->mesh_path_root_timer,
00548 round_jiffies(TU_TO_EXP_TIME(
00549 ifmsh->mshcfg.dot11MeshHWMPRannInterval)));
00550 }
00551
00552 #ifdef CONFIG_PM
00553 void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
00554 {
00555 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00556
00557
00558
00559 if (del_timer_sync(&ifmsh->housekeeping_timer))
00560 set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
00561 if (del_timer_sync(&ifmsh->mesh_path_timer))
00562 set_bit(TMR_RUNNING_MP, &ifmsh->timers_running);
00563 if (del_timer_sync(&ifmsh->mesh_path_root_timer))
00564 set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running);
00565 }
00566
00567 void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata)
00568 {
00569 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00570
00571 if (test_and_clear_bit(TMR_RUNNING_HK, &ifmsh->timers_running))
00572 add_timer(&ifmsh->housekeeping_timer);
00573 if (test_and_clear_bit(TMR_RUNNING_MP, &ifmsh->timers_running))
00574 add_timer(&ifmsh->mesh_path_timer);
00575 if (test_and_clear_bit(TMR_RUNNING_MPR, &ifmsh->timers_running))
00576 add_timer(&ifmsh->mesh_path_root_timer);
00577 ieee80211_mesh_root_setup(ifmsh);
00578 }
00579 #endif
00580
00581 void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
00582 {
00583 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00584 struct ieee80211_local *local = sdata->local;
00585
00586 local->fif_other_bss++;
00587
00588 atomic_inc(&local->iff_allmultis);
00589 ieee80211_configure_filter(local);
00590
00591 ifmsh->mesh_cc_id = 0;
00592 ifmsh->mesh_auth_id = 0;
00593
00594 ifmsh->sync_ops = ieee80211_mesh_sync_ops_get(ifmsh->mesh_sp_id);
00595 ifmsh->adjusting_tbtt = false;
00596 ifmsh->sync_offset_clockdrift_max = 0;
00597 set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags);
00598 ieee80211_mesh_root_setup(ifmsh);
00599 ieee80211_queue_work(&local->hw, &sdata->work);
00600 sdata->vif.bss_conf.ht_operation_mode =
00601 ifmsh->mshcfg.ht_opmode;
00602 sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL;
00603 sdata->vif.bss_conf.basic_rates =
00604 ieee80211_mandatory_rates(sdata->local,
00605 sdata->local->hw.conf.channel->band);
00606 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
00607 BSS_CHANGED_BEACON_ENABLED |
00608 BSS_CHANGED_HT |
00609 BSS_CHANGED_BASIC_RATES |
00610 BSS_CHANGED_BEACON_INT);
00611 }
00612
00613 void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
00614 {
00615 struct ieee80211_local *local = sdata->local;
00616 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00617
00618 ifmsh->mesh_id_len = 0;
00619 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
00620 sta_info_flush(local, NULL);
00621
00622 del_timer_sync(&sdata->u.mesh.housekeeping_timer);
00623 del_timer_sync(&sdata->u.mesh.mesh_path_root_timer);
00624 del_timer_sync(&sdata->u.mesh.mesh_path_timer);
00625
00626
00627
00628
00629
00630
00631
00632 cancel_work_sync(&sdata->work);
00633
00634 local->fif_other_bss--;
00635 atomic_dec(&local->iff_allmultis);
00636 ieee80211_configure_filter(local);
00637 }
00638
00639 static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
00640 u16 stype,
00641 struct ieee80211_mgmt *mgmt,
00642 size_t len,
00643 struct ieee80211_rx_status *rx_status)
00644 {
00645 struct ieee80211_local *local = sdata->local;
00646 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00647 struct ieee802_11_elems elems;
00648 struct ieee80211_channel *channel;
00649 size_t baselen;
00650 int freq;
00651 enum ieee80211_band band = rx_status->band;
00652
00653
00654 if (stype == IEEE80211_STYPE_PROBE_RESP &&
00655 !ether_addr_equal(mgmt->da, sdata->vif.addr))
00656 return;
00657
00658 baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
00659 if (baselen > len)
00660 return;
00661
00662 ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
00663 &elems);
00664
00665
00666 if (elems.rsn_len && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE)
00667 return;
00668
00669 if (elems.ds_params && elems.ds_params_len == 1)
00670 freq = ieee80211_channel_to_frequency(elems.ds_params[0], band);
00671 else
00672 freq = rx_status->freq;
00673
00674 channel = ieee80211_get_channel(local->hw.wiphy, freq);
00675
00676 if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
00677 return;
00678
00679 if (elems.mesh_id && elems.mesh_config &&
00680 mesh_matches_local(sdata, &elems))
00681 mesh_neighbour_update(sdata, mgmt->sa, &elems);
00682
00683 if (ifmsh->sync_ops)
00684 ifmsh->sync_ops->rx_bcn_presp(sdata,
00685 stype, mgmt, &elems, rx_status);
00686 }
00687
00688 static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
00689 struct ieee80211_mgmt *mgmt,
00690 size_t len,
00691 struct ieee80211_rx_status *rx_status)
00692 {
00693 switch (mgmt->u.action.category) {
00694 case WLAN_CATEGORY_SELF_PROTECTED:
00695 switch (mgmt->u.action.u.self_prot.action_code) {
00696 case WLAN_SP_MESH_PEERING_OPEN:
00697 case WLAN_SP_MESH_PEERING_CLOSE:
00698 case WLAN_SP_MESH_PEERING_CONFIRM:
00699 mesh_rx_plink_frame(sdata, mgmt, len, rx_status);
00700 break;
00701 }
00702 break;
00703 case WLAN_CATEGORY_MESH_ACTION:
00704 if (mesh_action_is_path_sel(mgmt))
00705 mesh_rx_path_sel_frame(sdata, mgmt, len);
00706 break;
00707 }
00708 }
00709
00710 void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
00711 struct sk_buff *skb)
00712 {
00713 struct ieee80211_rx_status *rx_status;
00714 struct ieee80211_mgmt *mgmt;
00715 u16 stype;
00716
00717 rx_status = IEEE80211_SKB_RXCB(skb);
00718 mgmt = (struct ieee80211_mgmt *) skb->data;
00719 stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
00720
00721 switch (stype) {
00722 case IEEE80211_STYPE_PROBE_RESP:
00723 case IEEE80211_STYPE_BEACON:
00724 ieee80211_mesh_rx_bcn_presp(sdata, stype, mgmt, skb->len,
00725 rx_status);
00726 break;
00727 case IEEE80211_STYPE_ACTION:
00728 ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status);
00729 break;
00730 }
00731 }
00732
00733 void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
00734 {
00735 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00736
00737 if (ifmsh->preq_queue_len &&
00738 time_after(jiffies,
00739 ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval)))
00740 mesh_path_start_discovery(sdata);
00741
00742 if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags))
00743 mesh_mpath_table_grow();
00744
00745 if (test_and_clear_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags))
00746 mesh_mpp_table_grow();
00747
00748 if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags))
00749 ieee80211_mesh_housekeeping(sdata, ifmsh);
00750
00751 if (test_and_clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags))
00752 ieee80211_mesh_rootpath(sdata);
00753
00754 if (test_and_clear_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags))
00755 mesh_sync_adjust_tbtt(sdata);
00756 }
00757
00758 void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
00759 {
00760 struct ieee80211_sub_if_data *sdata;
00761
00762 rcu_read_lock();
00763 list_for_each_entry_rcu(sdata, &local->interfaces, list)
00764 if (ieee80211_vif_is_mesh(&sdata->vif))
00765 ieee80211_queue_work(&local->hw, &sdata->work);
00766 rcu_read_unlock();
00767 }
00768
00769 void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
00770 {
00771 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
00772
00773 setup_timer(&ifmsh->housekeeping_timer,
00774 ieee80211_mesh_housekeeping_timer,
00775 (unsigned long) sdata);
00776
00777 ifmsh->accepting_plinks = true;
00778 ifmsh->preq_id = 0;
00779 ifmsh->sn = 0;
00780 ifmsh->num_gates = 0;
00781 atomic_set(&ifmsh->mpaths, 0);
00782 mesh_rmc_init(sdata);
00783 ifmsh->last_preq = jiffies;
00784 ifmsh->next_perr = jiffies;
00785
00786 if (!mesh_allocated)
00787 ieee80211s_init();
00788 setup_timer(&ifmsh->mesh_path_timer,
00789 ieee80211_mesh_path_timer,
00790 (unsigned long) sdata);
00791 setup_timer(&ifmsh->mesh_path_root_timer,
00792 ieee80211_mesh_path_root_timer,
00793 (unsigned long) sdata);
00794 INIT_LIST_HEAD(&ifmsh->preq_queue.list);
00795 spin_lock_init(&ifmsh->mesh_preq_queue_lock);
00796 spin_lock_init(&ifmsh->sync_offset_lock);
00797 }