aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/cfg.c
diff options
context:
space:
mode:
authorLuis Carlos Cobo <luisca@cozybit.com>2008-02-23 09:17:17 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-03-06 15:30:42 -0500
commitc5dd9c2bd0b2422dbcd57fe8158d1d7d36c07dd9 (patch)
treefee281c139ec5c57ced94e8119cb1768b17fa9d8 /net/mac80211/cfg.c
parent9f42f607058a80bfb7b4f687bb84016ae129cfd1 (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.c269
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
19static enum ieee80211_if_types 24static enum ieee80211_if_types
20nl80211_type_to_mac80211_type(enum nl80211_iftype type) 25nl80211_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
318static 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
346static 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
300static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, 363static 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
567static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, 638static 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
737static 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
773static 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
783static 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
816static 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
855static 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
877static 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
659struct cfg80211_ops mac80211_config_ops = { 900struct 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};