diff options
author | Luis Carlos Cobo <luisca@cozybit.com> | 2008-02-23 09:17:17 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-03-06 15:30:42 -0500 |
commit | c5dd9c2bd0b2422dbcd57fe8158d1d7d36c07dd9 (patch) | |
tree | fee281c139ec5c57ced94e8119cb1768b17fa9d8 /net/mac80211/cfg.c | |
parent | 9f42f607058a80bfb7b4f687bb84016ae129cfd1 (diff) |
mac80211: mesh path and mesh peer configuration
This adds code to allow adding mesh interfaces and configuring
mesh peers etc. Also, it adds code for station dumping.
Signed-off-by: Luis Carlos Cobo <luisca@cozybit.com>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r-- | net/mac80211/cfg.c | 269 |
1 files changed, 259 insertions, 10 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 0e97ceee640c..b1befac1736a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -15,6 +15,11 @@ | |||
15 | #include "ieee80211_i.h" | 15 | #include "ieee80211_i.h" |
16 | #include "cfg.h" | 16 | #include "cfg.h" |
17 | #include "ieee80211_rate.h" | 17 | #include "ieee80211_rate.h" |
18 | #ifdef CONFIG_MAC80211_MESH | ||
19 | #include "mesh.h" | ||
20 | #endif | ||
21 | |||
22 | #define DEFAULT_RATES 0 | ||
18 | 23 | ||
19 | static enum ieee80211_if_types | 24 | static enum ieee80211_if_types |
20 | nl80211_type_to_mac80211_type(enum nl80211_iftype type) | 25 | nl80211_type_to_mac80211_type(enum nl80211_iftype type) |
@@ -28,6 +33,10 @@ nl80211_type_to_mac80211_type(enum nl80211_iftype type) | |||
28 | return IEEE80211_IF_TYPE_STA; | 33 | return IEEE80211_IF_TYPE_STA; |
29 | case NL80211_IFTYPE_MONITOR: | 34 | case NL80211_IFTYPE_MONITOR: |
30 | return IEEE80211_IF_TYPE_MNTR; | 35 | return IEEE80211_IF_TYPE_MNTR; |
36 | #ifdef CONFIG_MAC80211_MESH | ||
37 | case NL80211_IFTYPE_MESH_POINT: | ||
38 | return IEEE80211_IF_TYPE_MESH_POINT; | ||
39 | #endif | ||
31 | default: | 40 | default: |
32 | return IEEE80211_IF_TYPE_INVALID; | 41 | return IEEE80211_IF_TYPE_INVALID; |
33 | } | 42 | } |
@@ -110,6 +119,15 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, | |||
110 | ieee80211_if_reinit(dev); | 119 | ieee80211_if_reinit(dev); |
111 | ieee80211_if_set_type(dev, itype); | 120 | ieee80211_if_set_type(dev, itype); |
112 | 121 | ||
122 | #ifdef CONFIG_MAC80211_MESH | ||
123 | if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT && | ||
124 | params->mesh_id_len) { | ||
125 | sdata->u.sta.mesh_id_len = params->mesh_id_len; | ||
126 | memcpy(sdata->u.sta.mesh_id, params->mesh_id, | ||
127 | params->mesh_id_len); | ||
128 | } | ||
129 | #endif | ||
130 | |||
113 | if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR || !flags) | 131 | if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR || !flags) |
114 | return 0; | 132 | return 0; |
115 | 133 | ||
@@ -297,6 +315,51 @@ static int ieee80211_config_default_key(struct wiphy *wiphy, | |||
297 | return 0; | 315 | return 0; |
298 | } | 316 | } |
299 | 317 | ||
318 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | ||
319 | { | ||
320 | #ifdef CONFIG_MAC80211_MESH | ||
321 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); | ||
322 | #endif | ||
323 | |||
324 | sinfo->filled = STATION_INFO_INACTIVE_TIME | | ||
325 | STATION_INFO_RX_BYTES | | ||
326 | STATION_INFO_TX_BYTES; | ||
327 | |||
328 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); | ||
329 | sinfo->rx_bytes = sta->rx_bytes; | ||
330 | sinfo->tx_bytes = sta->tx_bytes; | ||
331 | |||
332 | #ifdef CONFIG_MAC80211_MESH | ||
333 | if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) { | ||
334 | sinfo->filled |= STATION_INFO_LLID | | ||
335 | STATION_INFO_PLID | | ||
336 | STATION_INFO_PLINK_STATE; | ||
337 | |||
338 | sinfo->llid = le16_to_cpu(sta->llid); | ||
339 | sinfo->plid = le16_to_cpu(sta->plid); | ||
340 | sinfo->plink_state = sta->plink_state; | ||
341 | } | ||
342 | #endif | ||
343 | } | ||
344 | |||
345 | |||
346 | static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | ||
347 | int idx, u8 *mac, struct station_info *sinfo) | ||
348 | { | ||
349 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
350 | struct sta_info *sta; | ||
351 | |||
352 | sta = sta_info_get_by_idx(local, idx, dev); | ||
353 | if (!sta) | ||
354 | return -ENOENT; | ||
355 | |||
356 | memcpy(mac, sta->addr, ETH_ALEN); | ||
357 | sta_set_sinfo(sta, sinfo); | ||
358 | sta_info_put(sta); | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | |||
300 | static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, | 363 | static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, |
301 | u8 *mac, struct station_info *sinfo) | 364 | u8 *mac, struct station_info *sinfo) |
302 | { | 365 | { |
@@ -308,15 +371,7 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
308 | return -ENOENT; | 371 | return -ENOENT; |
309 | 372 | ||
310 | /* XXX: verify sta->dev == dev */ | 373 | /* XXX: verify sta->dev == dev */ |
311 | 374 | sta_set_sinfo(sta, sinfo); | |
312 | sinfo->filled = STATION_INFO_INACTIVE_TIME | | ||
313 | STATION_INFO_RX_BYTES | | ||
314 | STATION_INFO_TX_BYTES; | ||
315 | |||
316 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); | ||
317 | sinfo->rx_bytes = sta->rx_bytes; | ||
318 | sinfo->tx_bytes = sta->tx_bytes; | ||
319 | |||
320 | sta_info_put(sta); | 375 | sta_info_put(sta); |
321 | 376 | ||
322 | return 0; | 377 | return 0; |
@@ -525,6 +580,9 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
525 | u32 rates; | 580 | u32 rates; |
526 | int i, j; | 581 | int i, j; |
527 | struct ieee80211_supported_band *sband; | 582 | struct ieee80211_supported_band *sband; |
583 | #ifdef CONFIG_MAC80211_MESH | ||
584 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); | ||
585 | #endif | ||
528 | 586 | ||
529 | if (params->station_flags & STATION_FLAG_CHANGED) { | 587 | if (params->station_flags & STATION_FLAG_CHANGED) { |
530 | sta->flags &= ~WLAN_STA_AUTHORIZED; | 588 | sta->flags &= ~WLAN_STA_AUTHORIZED; |
@@ -562,6 +620,19 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
562 | } | 620 | } |
563 | sta->supp_rates[local->oper_channel->band] = rates; | 621 | sta->supp_rates[local->oper_channel->band] = rates; |
564 | } | 622 | } |
623 | |||
624 | #ifdef CONFIG_MAC80211_MESH | ||
625 | if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT && | ||
626 | params->plink_action) | ||
627 | switch (params->plink_action) { | ||
628 | case PLINK_ACTION_OPEN: | ||
629 | mesh_plink_open(sta); | ||
630 | break; | ||
631 | case PLINK_ACTION_BLOCK: | ||
632 | mesh_plink_block(sta); | ||
633 | break; | ||
634 | } | ||
635 | #endif | ||
565 | } | 636 | } |
566 | 637 | ||
567 | static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | 638 | static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, |
@@ -584,7 +655,13 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
584 | } else | 655 | } else |
585 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 656 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
586 | 657 | ||
587 | sta = sta_info_add(local, dev, mac, GFP_KERNEL); | 658 | #ifdef CONFIG_MAC80211_MESH |
659 | if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) | ||
660 | sta = mesh_plink_add(mac, DEFAULT_RATES, dev); | ||
661 | else | ||
662 | #endif | ||
663 | sta = sta_info_add(local, dev, mac, GFP_KERNEL); | ||
664 | |||
588 | if (IS_ERR(sta)) | 665 | if (IS_ERR(sta)) |
589 | return PTR_ERR(sta); | 666 | return PTR_ERR(sta); |
590 | 667 | ||
@@ -656,6 +733,170 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
656 | return 0; | 733 | return 0; |
657 | } | 734 | } |
658 | 735 | ||
736 | #ifdef CONFIG_MAC80211_MESH | ||
737 | static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | ||
738 | u8 *dst, u8 *next_hop) | ||
739 | { | ||
740 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
741 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
742 | struct mesh_path *mpath; | ||
743 | struct sta_info *sta; | ||
744 | int err; | ||
745 | |||
746 | if (!netif_running(dev)) | ||
747 | return -ENETDOWN; | ||
748 | |||
749 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) | ||
750 | return -ENOTSUPP; | ||
751 | |||
752 | sta = sta_info_get(local, next_hop); | ||
753 | if (!sta) | ||
754 | return -ENOENT; | ||
755 | |||
756 | err = mesh_path_add(dst, dev); | ||
757 | if (err) | ||
758 | return err; | ||
759 | |||
760 | rcu_read_lock(); | ||
761 | mpath = mesh_path_lookup(dst, dev); | ||
762 | if (!mpath) { | ||
763 | rcu_read_unlock(); | ||
764 | sta_info_put(sta); | ||
765 | return -ENXIO; | ||
766 | } | ||
767 | mesh_path_fix_nexthop(mpath, sta); | ||
768 | sta_info_put(sta); | ||
769 | rcu_read_unlock(); | ||
770 | return 0; | ||
771 | } | ||
772 | |||
773 | static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, | ||
774 | u8 *dst) | ||
775 | { | ||
776 | if (dst) | ||
777 | return mesh_path_del(dst, dev); | ||
778 | |||
779 | mesh_path_flush(dev); | ||
780 | return 0; | ||
781 | } | ||
782 | |||
783 | static int ieee80211_change_mpath(struct wiphy *wiphy, | ||
784 | struct net_device *dev, | ||
785 | u8 *dst, u8 *next_hop) | ||
786 | { | ||
787 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
788 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
789 | struct mesh_path *mpath; | ||
790 | struct sta_info *sta; | ||
791 | |||
792 | if (!netif_running(dev)) | ||
793 | return -ENETDOWN; | ||
794 | |||
795 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) | ||
796 | return -ENOTSUPP; | ||
797 | |||
798 | sta = sta_info_get(local, next_hop); | ||
799 | if (!sta) | ||
800 | return -ENOENT; | ||
801 | |||
802 | rcu_read_lock(); | ||
803 | mpath = mesh_path_lookup(dst, dev); | ||
804 | if (!mpath) { | ||
805 | rcu_read_unlock(); | ||
806 | sta_info_put(sta); | ||
807 | return -ENOENT; | ||
808 | } | ||
809 | |||
810 | mesh_path_fix_nexthop(mpath, sta); | ||
811 | sta_info_put(sta); | ||
812 | rcu_read_unlock(); | ||
813 | return 0; | ||
814 | } | ||
815 | |||
816 | static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, | ||
817 | struct mpath_info *pinfo) | ||
818 | { | ||
819 | if (mpath->next_hop) | ||
820 | memcpy(next_hop, mpath->next_hop->addr, ETH_ALEN); | ||
821 | else | ||
822 | memset(next_hop, 0, ETH_ALEN); | ||
823 | |||
824 | pinfo->filled = MPATH_INFO_FRAME_QLEN | | ||
825 | MPATH_INFO_DSN | | ||
826 | MPATH_INFO_METRIC | | ||
827 | MPATH_INFO_EXPTIME | | ||
828 | MPATH_INFO_DISCOVERY_TIMEOUT | | ||
829 | MPATH_INFO_DISCOVERY_RETRIES | | ||
830 | MPATH_INFO_FLAGS; | ||
831 | |||
832 | pinfo->frame_qlen = mpath->frame_queue.qlen; | ||
833 | pinfo->dsn = mpath->dsn; | ||
834 | pinfo->metric = mpath->metric; | ||
835 | if (time_before(jiffies, mpath->exp_time)) | ||
836 | pinfo->exptime = jiffies_to_msecs(mpath->exp_time - jiffies); | ||
837 | pinfo->discovery_timeout = | ||
838 | jiffies_to_msecs(mpath->discovery_timeout); | ||
839 | pinfo->discovery_retries = mpath->discovery_retries; | ||
840 | pinfo->flags = 0; | ||
841 | if (mpath->flags & MESH_PATH_ACTIVE) | ||
842 | pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE; | ||
843 | if (mpath->flags & MESH_PATH_RESOLVING) | ||
844 | pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING; | ||
845 | if (mpath->flags & MESH_PATH_DSN_VALID) | ||
846 | pinfo->flags |= NL80211_MPATH_FLAG_DSN_VALID; | ||
847 | if (mpath->flags & MESH_PATH_FIXED) | ||
848 | pinfo->flags |= NL80211_MPATH_FLAG_FIXED; | ||
849 | if (mpath->flags & MESH_PATH_RESOLVING) | ||
850 | pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING; | ||
851 | |||
852 | pinfo->flags = mpath->flags; | ||
853 | } | ||
854 | |||
855 | static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, | ||
856 | u8 *dst, u8 *next_hop, struct mpath_info *pinfo) | ||
857 | |||
858 | { | ||
859 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
860 | struct mesh_path *mpath; | ||
861 | |||
862 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) | ||
863 | return -ENOTSUPP; | ||
864 | |||
865 | rcu_read_lock(); | ||
866 | mpath = mesh_path_lookup(dst, dev); | ||
867 | if (!mpath) { | ||
868 | rcu_read_unlock(); | ||
869 | return -ENOENT; | ||
870 | } | ||
871 | memcpy(dst, mpath->dst, ETH_ALEN); | ||
872 | mpath_set_pinfo(mpath, next_hop, pinfo); | ||
873 | rcu_read_unlock(); | ||
874 | return 0; | ||
875 | } | ||
876 | |||
877 | static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, | ||
878 | int idx, u8 *dst, u8 *next_hop, | ||
879 | struct mpath_info *pinfo) | ||
880 | { | ||
881 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
882 | struct mesh_path *mpath; | ||
883 | |||
884 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) | ||
885 | return -ENOTSUPP; | ||
886 | |||
887 | rcu_read_lock(); | ||
888 | mpath = mesh_path_lookup_by_idx(idx, dev); | ||
889 | if (!mpath) { | ||
890 | rcu_read_unlock(); | ||
891 | return -ENOENT; | ||
892 | } | ||
893 | memcpy(dst, mpath->dst, ETH_ALEN); | ||
894 | mpath_set_pinfo(mpath, next_hop, pinfo); | ||
895 | rcu_read_unlock(); | ||
896 | return 0; | ||
897 | } | ||
898 | #endif | ||
899 | |||
659 | struct cfg80211_ops mac80211_config_ops = { | 900 | struct cfg80211_ops mac80211_config_ops = { |
660 | .add_virtual_intf = ieee80211_add_iface, | 901 | .add_virtual_intf = ieee80211_add_iface, |
661 | .del_virtual_intf = ieee80211_del_iface, | 902 | .del_virtual_intf = ieee80211_del_iface, |
@@ -671,4 +912,12 @@ struct cfg80211_ops mac80211_config_ops = { | |||
671 | .del_station = ieee80211_del_station, | 912 | .del_station = ieee80211_del_station, |
672 | .change_station = ieee80211_change_station, | 913 | .change_station = ieee80211_change_station, |
673 | .get_station = ieee80211_get_station, | 914 | .get_station = ieee80211_get_station, |
915 | .dump_station = ieee80211_dump_station, | ||
916 | #ifdef CONFIG_MAC80211_MESH | ||
917 | .add_mpath = ieee80211_add_mpath, | ||
918 | .del_mpath = ieee80211_del_mpath, | ||
919 | .change_mpath = ieee80211_change_mpath, | ||
920 | .get_mpath = ieee80211_get_mpath, | ||
921 | .dump_mpath = ieee80211_dump_mpath, | ||
922 | #endif | ||
674 | }; | 923 | }; |