aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mesh.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mesh.c')
-rw-r--r--net/mac80211/mesh.c87
1 files changed, 14 insertions, 73 deletions
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 6a4331429598..c8a4f19ed13b 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -8,6 +8,7 @@
8 * published by the Free Software Foundation. 8 * published by the Free Software Foundation.
9 */ 9 */
10 10
11#include <linux/slab.h>
11#include <asm/unaligned.h> 12#include <asm/unaligned.h>
12#include "ieee80211_i.h" 13#include "ieee80211_i.h"
13#include "mesh.h" 14#include "mesh.h"
@@ -53,7 +54,7 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
53 return; 54 return;
54 } 55 }
55 56
56 ieee80211_queue_work(&local->hw, &ifmsh->work); 57 ieee80211_queue_work(&local->hw, &sdata->work);
57} 58}
58 59
59/** 60/**
@@ -286,8 +287,6 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
286 *pos++ |= sdata->u.mesh.accepting_plinks ? 287 *pos++ |= sdata->u.mesh.accepting_plinks ?
287 MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; 288 MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00;
288 *pos++ = 0x00; 289 *pos++ = 0x00;
289
290 return;
291} 290}
292 291
293u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_table *tbl) 292u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_table *tbl)
@@ -346,7 +345,7 @@ static void ieee80211_mesh_path_timer(unsigned long data)
346 return; 345 return;
347 } 346 }
348 347
349 ieee80211_queue_work(&local->hw, &ifmsh->work); 348 ieee80211_queue_work(&local->hw, &sdata->work);
350} 349}
351 350
352static void ieee80211_mesh_path_root_timer(unsigned long data) 351static void ieee80211_mesh_path_root_timer(unsigned long data)
@@ -363,7 +362,7 @@ static void ieee80211_mesh_path_root_timer(unsigned long data)
363 return; 362 return;
364 } 363 }
365 364
366 ieee80211_queue_work(&local->hw, &ifmsh->work); 365 ieee80211_queue_work(&local->hw, &sdata->work);
367} 366}
368 367
369void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh) 368void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh)
@@ -457,7 +456,7 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
457 456
458#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 457#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
459 printk(KERN_DEBUG "%s: running mesh housekeeping\n", 458 printk(KERN_DEBUG "%s: running mesh housekeeping\n",
460 sdata->dev->name); 459 sdata->name);
461#endif 460#endif
462 461
463 ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); 462 ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT);
@@ -485,9 +484,6 @@ void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
485{ 484{
486 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 485 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
487 486
488 /* might restart the timer but that doesn't matter */
489 cancel_work_sync(&ifmsh->work);
490
491 /* use atomic bitops in case both timers fire at the same time */ 487 /* use atomic bitops in case both timers fire at the same time */
492 488
493 if (del_timer_sync(&ifmsh->housekeeping_timer)) 489 if (del_timer_sync(&ifmsh->housekeeping_timer))
@@ -519,7 +515,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
519 515
520 set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); 516 set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags);
521 ieee80211_mesh_root_setup(ifmsh); 517 ieee80211_mesh_root_setup(ifmsh);
522 ieee80211_queue_work(&local->hw, &ifmsh->work); 518 ieee80211_queue_work(&local->hw, &sdata->work);
523 sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; 519 sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL;
524 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | 520 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
525 BSS_CHANGED_BEACON_ENABLED | 521 BSS_CHANGED_BEACON_ENABLED |
@@ -537,16 +533,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
537 * whether the interface is running, which, at this point, 533 * whether the interface is running, which, at this point,
538 * it no longer is. 534 * it no longer is.
539 */ 535 */
540 cancel_work_sync(&sdata->u.mesh.work); 536 cancel_work_sync(&sdata->work);
541
542 /*
543 * When we get here, the interface is marked down.
544 * Call synchronize_rcu() to wait for the RX path
545 * should it be using the interface and enqueuing
546 * frames at this very time on another CPU.
547 */
548 rcu_barrier(); /* Wait for RX path and call_rcu()'s */
549 skb_queue_purge(&sdata->u.mesh.skb_queue);
550} 537}
551 538
552static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, 539static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
@@ -565,7 +552,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
565 552
566 /* ignore ProbeResp to foreign address */ 553 /* ignore ProbeResp to foreign address */
567 if (stype == IEEE80211_STYPE_PROBE_RESP && 554 if (stype == IEEE80211_STYPE_PROBE_RESP &&
568 compare_ether_addr(mgmt->da, sdata->dev->dev_addr)) 555 compare_ether_addr(mgmt->da, sdata->vif.addr))
569 return; 556 return;
570 557
571 baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; 558 baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
@@ -600,17 +587,17 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
600 struct ieee80211_rx_status *rx_status) 587 struct ieee80211_rx_status *rx_status)
601{ 588{
602 switch (mgmt->u.action.category) { 589 switch (mgmt->u.action.category) {
603 case MESH_PLINK_CATEGORY: 590 case WLAN_CATEGORY_MESH_PLINK:
604 mesh_rx_plink_frame(sdata, mgmt, len, rx_status); 591 mesh_rx_plink_frame(sdata, mgmt, len, rx_status);
605 break; 592 break;
606 case MESH_PATH_SEL_CATEGORY: 593 case WLAN_CATEGORY_MESH_PATH_SEL:
607 mesh_rx_path_sel_frame(sdata, mgmt, len); 594 mesh_rx_path_sel_frame(sdata, mgmt, len);
608 break; 595 break;
609 } 596 }
610} 597}
611 598
612static void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, 599void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
613 struct sk_buff *skb) 600 struct sk_buff *skb)
614{ 601{
615 struct ieee80211_rx_status *rx_status; 602 struct ieee80211_rx_status *rx_status;
616 struct ieee80211_if_mesh *ifmsh; 603 struct ieee80211_if_mesh *ifmsh;
@@ -633,26 +620,11 @@ static void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
633 ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status); 620 ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status);
634 break; 621 break;
635 } 622 }
636
637 kfree_skb(skb);
638} 623}
639 624
640static void ieee80211_mesh_work(struct work_struct *work) 625void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
641{ 626{
642 struct ieee80211_sub_if_data *sdata =
643 container_of(work, struct ieee80211_sub_if_data, u.mesh.work);
644 struct ieee80211_local *local = sdata->local;
645 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 627 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
646 struct sk_buff *skb;
647
648 if (!netif_running(sdata->dev))
649 return;
650
651 if (local->scanning)
652 return;
653
654 while ((skb = skb_dequeue(&ifmsh->skb_queue)))
655 ieee80211_mesh_rx_queued_mgmt(sdata, skb);
656 628
657 if (ifmsh->preq_queue_len && 629 if (ifmsh->preq_queue_len &&
658 time_after(jiffies, 630 time_after(jiffies,
@@ -679,7 +651,7 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
679 rcu_read_lock(); 651 rcu_read_lock();
680 list_for_each_entry_rcu(sdata, &local->interfaces, list) 652 list_for_each_entry_rcu(sdata, &local->interfaces, list)
681 if (ieee80211_vif_is_mesh(&sdata->vif)) 653 if (ieee80211_vif_is_mesh(&sdata->vif))
682 ieee80211_queue_work(&local->hw, &sdata->u.mesh.work); 654 ieee80211_queue_work(&local->hw, &sdata->work);
683 rcu_read_unlock(); 655 rcu_read_unlock();
684} 656}
685 657
@@ -687,11 +659,9 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
687{ 659{
688 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 660 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
689 661
690 INIT_WORK(&ifmsh->work, ieee80211_mesh_work);
691 setup_timer(&ifmsh->housekeeping_timer, 662 setup_timer(&ifmsh->housekeeping_timer,
692 ieee80211_mesh_housekeeping_timer, 663 ieee80211_mesh_housekeeping_timer,
693 (unsigned long) sdata); 664 (unsigned long) sdata);
694 skb_queue_head_init(&sdata->u.mesh.skb_queue);
695 665
696 ifmsh->mshcfg.dot11MeshRetryTimeout = MESH_RET_T; 666 ifmsh->mshcfg.dot11MeshRetryTimeout = MESH_RET_T;
697 ifmsh->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T; 667 ifmsh->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T;
@@ -732,32 +702,3 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
732 INIT_LIST_HEAD(&ifmsh->preq_queue.list); 702 INIT_LIST_HEAD(&ifmsh->preq_queue.list);
733 spin_lock_init(&ifmsh->mesh_preq_queue_lock); 703 spin_lock_init(&ifmsh->mesh_preq_queue_lock);
734} 704}
735
736ieee80211_rx_result
737ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
738{
739 struct ieee80211_local *local = sdata->local;
740 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
741 struct ieee80211_mgmt *mgmt;
742 u16 fc;
743
744 if (skb->len < 24)
745 return RX_DROP_MONITOR;
746
747 mgmt = (struct ieee80211_mgmt *) skb->data;
748 fc = le16_to_cpu(mgmt->frame_control);
749
750 switch (fc & IEEE80211_FCTL_STYPE) {
751 case IEEE80211_STYPE_ACTION:
752 if (skb->len < IEEE80211_MIN_ACTION_SIZE)
753 return RX_DROP_MONITOR;
754 /* fall through */
755 case IEEE80211_STYPE_PROBE_RESP:
756 case IEEE80211_STYPE_BEACON:
757 skb_queue_tail(&ifmsh->skb_queue, skb);
758 ieee80211_queue_work(&local->hw, &ifmsh->work);
759 return RX_QUEUED;
760 }
761
762 return RX_CONTINUE;
763}