aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
authorJavier Cardona <javier@cozybit.com>2010-12-16 20:37:49 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-12-20 14:46:57 -0500
commitc80d545da3f7c0e534ccd4a780f322f80a92cff1 (patch)
treeedd5c51676b4677fc1a0b2fc692ffe97df863f25 /net/wireless/nl80211.c
parent24bdd9f4c9af75b33b438d60381a67626de0128d (diff)
mac80211: Let userspace enable and configure vendor specific path selection.
Userspace will now be allowed to toggle between the default path selection algorithm (HWMP, implemented in the kernel), and a vendor specific alternative. Also in the same patch, allow userspace to add information elements to mesh beacons. This is accordance with the Extensible Path Selection Framework specified in version 7.0 of the 802.11s draft. Signed-off-by: Javier Cardona <javier@cozybit.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c63
1 files changed, 58 insertions, 5 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 10be9350752e..eef89d0b558b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2773,6 +2773,14 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A
2773 [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 }, 2773 [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 },
2774}; 2774};
2775 2775
2776static const struct nla_policy
2777 nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = {
2778 [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 },
2779 [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 },
2780 [NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE] = { .type = NLA_BINARY,
2781 .len = IEEE80211_MAX_DATA_LEN },
2782};
2783
2776static int nl80211_parse_mesh_config(struct genl_info *info, 2784static int nl80211_parse_mesh_config(struct genl_info *info,
2777 struct mesh_config *cfg, 2785 struct mesh_config *cfg,
2778 u32 *mask_out) 2786 u32 *mask_out)
@@ -2839,14 +2847,50 @@ do {\
2839 dot11MeshHWMPRootMode, mask, 2847 dot11MeshHWMPRootMode, mask,
2840 NL80211_MESHCONF_HWMP_ROOTMODE, 2848 NL80211_MESHCONF_HWMP_ROOTMODE,
2841 nla_get_u8); 2849 nla_get_u8);
2842
2843 if (mask_out) 2850 if (mask_out)
2844 *mask_out = mask; 2851 *mask_out = mask;
2852
2845 return 0; 2853 return 0;
2846 2854
2847#undef FILL_IN_MESH_PARAM_IF_SET 2855#undef FILL_IN_MESH_PARAM_IF_SET
2848} 2856}
2849 2857
2858static int nl80211_parse_mesh_setup(struct genl_info *info,
2859 struct mesh_setup *setup)
2860{
2861 struct nlattr *tb[NL80211_MESH_SETUP_ATTR_MAX + 1];
2862
2863 if (!info->attrs[NL80211_ATTR_MESH_SETUP])
2864 return -EINVAL;
2865 if (nla_parse_nested(tb, NL80211_MESH_SETUP_ATTR_MAX,
2866 info->attrs[NL80211_ATTR_MESH_SETUP],
2867 nl80211_mesh_setup_params_policy))
2868 return -EINVAL;
2869
2870 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])
2871 setup->path_sel_proto =
2872 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])) ?
2873 IEEE80211_PATH_PROTOCOL_VENDOR :
2874 IEEE80211_PATH_PROTOCOL_HWMP;
2875
2876 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])
2877 setup->path_metric =
2878 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])) ?
2879 IEEE80211_PATH_METRIC_VENDOR :
2880 IEEE80211_PATH_METRIC_AIRTIME;
2881
2882 if (tb[NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE]) {
2883 struct nlattr *ieattr =
2884 tb[NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE];
2885 if (!is_valid_ie_attr(ieattr))
2886 return -EINVAL;
2887 setup->vendor_ie = nla_data(ieattr);
2888 setup->vendor_ie_len = nla_len(ieattr);
2889 }
2890
2891 return 0;
2892}
2893
2850static int nl80211_update_mesh_config(struct sk_buff *skb, 2894static int nl80211_update_mesh_config(struct sk_buff *skb,
2851 struct genl_info *info) 2895 struct genl_info *info)
2852{ 2896{
@@ -4667,10 +4711,12 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
4667 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 4711 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4668 struct net_device *dev = info->user_ptr[1]; 4712 struct net_device *dev = info->user_ptr[1];
4669 struct mesh_config cfg; 4713 struct mesh_config cfg;
4714 struct mesh_setup setup;
4670 int err; 4715 int err;
4671 4716
4672 /* start with default */ 4717 /* start with default */
4673 memcpy(&cfg, &default_mesh_config, sizeof(cfg)); 4718 memcpy(&cfg, &default_mesh_config, sizeof(cfg));
4719 memcpy(&setup, &default_mesh_setup, sizeof(setup));
4674 4720
4675 if (info->attrs[NL80211_ATTR_MESH_CONFIG]) { 4721 if (info->attrs[NL80211_ATTR_MESH_CONFIG]) {
4676 /* and parse parameters if given */ 4722 /* and parse parameters if given */
@@ -4683,10 +4729,17 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
4683 !nla_len(info->attrs[NL80211_ATTR_MESH_ID])) 4729 !nla_len(info->attrs[NL80211_ATTR_MESH_ID]))
4684 return -EINVAL; 4730 return -EINVAL;
4685 4731
4686 return cfg80211_join_mesh(rdev, dev, 4732 setup.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
4687 nla_data(info->attrs[NL80211_ATTR_MESH_ID]), 4733 setup.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
4688 nla_len(info->attrs[NL80211_ATTR_MESH_ID]), 4734
4689 &cfg); 4735 if (info->attrs[NL80211_ATTR_MESH_SETUP]) {
4736 /* parse additional setup parameters if given */
4737 err = nl80211_parse_mesh_setup(info, &setup);
4738 if (err)
4739 return err;
4740 }
4741
4742 return cfg80211_join_mesh(rdev, dev, &setup, &cfg);
4690} 4743}
4691 4744
4692static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info) 4745static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info)