aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Aring <aar@pengutronix.de>2016-06-18 04:45:34 -0400
committerMarcel Holtmann <marcel@holtmann.org>2016-07-08 06:20:57 -0400
commit66e5c2672cd11b9310008099faf6a4ffb9dfb6d0 (patch)
tree44fa2118c4570d457a5f4cafd33ec9fdd4bc28f3
parentaece0c3fe1f06962a591268b8c236df0ae5d9e4e (diff)
ieee802154: add netns support
This patch adds netns support for 802.15.4 subsystem. Most parts are copy&pasted from wireless subsystem, it has the identically userspace API. Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com> Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com> Signed-off-by: Alexander Aring <aar@pengutronix.de> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--include/net/cfg802154.h13
-rw-r--r--include/net/nl802154.h5
-rw-r--r--net/ieee802154/core.c70
-rw-r--r--net/ieee802154/core.h2
-rw-r--r--net/ieee802154/nl802154.c54
5 files changed, 138 insertions, 6 deletions
diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index 171cd76558fb..795ca4008f72 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -219,9 +219,22 @@ struct wpan_phy {
219 219
220 struct device dev; 220 struct device dev;
221 221
222 /* the network namespace this phy lives in currently */
223 possible_net_t _net;
224
222 char priv[0] __aligned(NETDEV_ALIGN); 225 char priv[0] __aligned(NETDEV_ALIGN);
223}; 226};
224 227
228static inline struct net *wpan_phy_net(struct wpan_phy *wpan_phy)
229{
230 return read_pnet(&wpan_phy->_net);
231}
232
233static inline void wpan_phy_net_set(struct wpan_phy *wpan_phy, struct net *net)
234{
235 write_pnet(&wpan_phy->_net, net);
236}
237
225struct ieee802154_addr { 238struct ieee802154_addr {
226 u8 mode; 239 u8 mode;
227 __le16 pan_id; 240 __le16 pan_id;
diff --git a/include/net/nl802154.h b/include/net/nl802154.h
index 7aad2fdfd16a..ddcee128f5d9 100644
--- a/include/net/nl802154.h
+++ b/include/net/nl802154.h
@@ -54,6 +54,8 @@ enum nl802154_commands {
54 54
55 NL802154_CMD_SET_ACKREQ_DEFAULT, 55 NL802154_CMD_SET_ACKREQ_DEFAULT,
56 56
57 NL802154_CMD_SET_WPAN_PHY_NETNS,
58
57 /* add new commands above here */ 59 /* add new commands above here */
58 60
59#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL 61#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
@@ -126,6 +128,9 @@ enum nl802154_attrs {
126 128
127 NL802154_ATTR_PAD, 129 NL802154_ATTR_PAD,
128 130
131 NL802154_ATTR_PID,
132 NL802154_ATTR_NETNS_FD,
133
129 /* add attributes here, update the policy in nl802154.c */ 134 /* add attributes here, update the policy in nl802154.c */
130 135
131#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL 136#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c
index c35fdfa6d04e..cb7176cd4cd6 100644
--- a/net/ieee802154/core.c
+++ b/net/ieee802154/core.c
@@ -140,6 +140,8 @@ wpan_phy_new(const struct cfg802154_ops *ops, size_t priv_size)
140 rdev->wpan_phy.dev.class = &wpan_phy_class; 140 rdev->wpan_phy.dev.class = &wpan_phy_class;
141 rdev->wpan_phy.dev.platform_data = rdev; 141 rdev->wpan_phy.dev.platform_data = rdev;
142 142
143 wpan_phy_net_set(&rdev->wpan_phy, &init_net);
144
143 init_waitqueue_head(&rdev->dev_wait); 145 init_waitqueue_head(&rdev->dev_wait);
144 146
145 return &rdev->wpan_phy; 147 return &rdev->wpan_phy;
@@ -207,6 +209,49 @@ void wpan_phy_free(struct wpan_phy *phy)
207} 209}
208EXPORT_SYMBOL(wpan_phy_free); 210EXPORT_SYMBOL(wpan_phy_free);
209 211
212int cfg802154_switch_netns(struct cfg802154_registered_device *rdev,
213 struct net *net)
214{
215 struct wpan_dev *wpan_dev;
216 int err = 0;
217
218 list_for_each_entry(wpan_dev, &rdev->wpan_dev_list, list) {
219 if (!wpan_dev->netdev)
220 continue;
221 wpan_dev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
222 err = dev_change_net_namespace(wpan_dev->netdev, net, "wpan%d");
223 if (err)
224 break;
225 wpan_dev->netdev->features |= NETIF_F_NETNS_LOCAL;
226 }
227
228 if (err) {
229 /* failed -- clean up to old netns */
230 net = wpan_phy_net(&rdev->wpan_phy);
231
232 list_for_each_entry_continue_reverse(wpan_dev,
233 &rdev->wpan_dev_list,
234 list) {
235 if (!wpan_dev->netdev)
236 continue;
237 wpan_dev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
238 err = dev_change_net_namespace(wpan_dev->netdev, net,
239 "wpan%d");
240 WARN_ON(err);
241 wpan_dev->netdev->features |= NETIF_F_NETNS_LOCAL;
242 }
243
244 return err;
245 }
246
247 wpan_phy_net_set(&rdev->wpan_phy, net);
248
249 err = device_rename(&rdev->wpan_phy.dev, dev_name(&rdev->wpan_phy.dev));
250 WARN_ON(err);
251
252 return 0;
253}
254
210void cfg802154_dev_free(struct cfg802154_registered_device *rdev) 255void cfg802154_dev_free(struct cfg802154_registered_device *rdev)
211{ 256{
212 kfree(rdev); 257 kfree(rdev);
@@ -286,14 +331,34 @@ static struct notifier_block cfg802154_netdev_notifier = {
286 .notifier_call = cfg802154_netdev_notifier_call, 331 .notifier_call = cfg802154_netdev_notifier_call,
287}; 332};
288 333
334static void __net_exit cfg802154_pernet_exit(struct net *net)
335{
336 struct cfg802154_registered_device *rdev;
337
338 rtnl_lock();
339 list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
340 if (net_eq(wpan_phy_net(&rdev->wpan_phy), net))
341 WARN_ON(cfg802154_switch_netns(rdev, &init_net));
342 }
343 rtnl_unlock();
344}
345
346static struct pernet_operations cfg802154_pernet_ops = {
347 .exit = cfg802154_pernet_exit,
348};
349
289static int __init wpan_phy_class_init(void) 350static int __init wpan_phy_class_init(void)
290{ 351{
291 int rc; 352 int rc;
292 353
293 rc = wpan_phy_sysfs_init(); 354 rc = register_pernet_device(&cfg802154_pernet_ops);
294 if (rc) 355 if (rc)
295 goto err; 356 goto err;
296 357
358 rc = wpan_phy_sysfs_init();
359 if (rc)
360 goto err_sysfs;
361
297 rc = register_netdevice_notifier(&cfg802154_netdev_notifier); 362 rc = register_netdevice_notifier(&cfg802154_netdev_notifier);
298 if (rc) 363 if (rc)
299 goto err_nl; 364 goto err_nl;
@@ -315,6 +380,8 @@ err_notifier:
315 unregister_netdevice_notifier(&cfg802154_netdev_notifier); 380 unregister_netdevice_notifier(&cfg802154_netdev_notifier);
316err_nl: 381err_nl:
317 wpan_phy_sysfs_exit(); 382 wpan_phy_sysfs_exit();
383err_sysfs:
384 unregister_pernet_device(&cfg802154_pernet_ops);
318err: 385err:
319 return rc; 386 return rc;
320} 387}
@@ -326,6 +393,7 @@ static void __exit wpan_phy_class_exit(void)
326 ieee802154_nl_exit(); 393 ieee802154_nl_exit();
327 unregister_netdevice_notifier(&cfg802154_netdev_notifier); 394 unregister_netdevice_notifier(&cfg802154_netdev_notifier);
328 wpan_phy_sysfs_exit(); 395 wpan_phy_sysfs_exit();
396 unregister_pernet_device(&cfg802154_pernet_ops);
329} 397}
330module_exit(wpan_phy_class_exit); 398module_exit(wpan_phy_class_exit);
331 399
diff --git a/net/ieee802154/core.h b/net/ieee802154/core.h
index 231fade959f3..81141f58d079 100644
--- a/net/ieee802154/core.h
+++ b/net/ieee802154/core.h
@@ -38,6 +38,8 @@ wpan_phy_to_rdev(struct wpan_phy *wpan_phy)
38extern struct list_head cfg802154_rdev_list; 38extern struct list_head cfg802154_rdev_list;
39extern int cfg802154_rdev_list_generation; 39extern int cfg802154_rdev_list_generation;
40 40
41int cfg802154_switch_netns(struct cfg802154_registered_device *rdev,
42 struct net *net);
41/* free object */ 43/* free object */
42void cfg802154_dev_free(struct cfg802154_registered_device *rdev); 44void cfg802154_dev_free(struct cfg802154_registered_device *rdev);
43struct cfg802154_registered_device * 45struct cfg802154_registered_device *
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c
index 116187b5c267..d90a4ed5b8a0 100644
--- a/net/ieee802154/nl802154.c
+++ b/net/ieee802154/nl802154.c
@@ -80,7 +80,8 @@ __cfg802154_wpan_dev_from_attrs(struct net *netns, struct nlattr **attrs)
80 list_for_each_entry(rdev, &cfg802154_rdev_list, list) { 80 list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
81 struct wpan_dev *wpan_dev; 81 struct wpan_dev *wpan_dev;
82 82
83 /* TODO netns compare */ 83 if (wpan_phy_net(&rdev->wpan_phy) != netns)
84 continue;
84 85
85 if (have_wpan_dev_id && rdev->wpan_phy_idx != wpan_phy_idx) 86 if (have_wpan_dev_id && rdev->wpan_phy_idx != wpan_phy_idx)
86 continue; 87 continue;
@@ -175,7 +176,8 @@ __cfg802154_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
175 if (!rdev) 176 if (!rdev)
176 return ERR_PTR(-ENODEV); 177 return ERR_PTR(-ENODEV);
177 178
178 /* TODO netns compare */ 179 if (netns != wpan_phy_net(&rdev->wpan_phy))
180 return ERR_PTR(-ENODEV);
179 181
180 return rdev; 182 return rdev;
181} 183}
@@ -233,6 +235,8 @@ static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = {
233 235
234 [NL802154_ATTR_ACKREQ_DEFAULT] = { .type = NLA_U8 }, 236 [NL802154_ATTR_ACKREQ_DEFAULT] = { .type = NLA_U8 },
235 237
238 [NL802154_ATTR_PID] = { .type = NLA_U32 },
239 [NL802154_ATTR_NETNS_FD] = { .type = NLA_U32 },
236#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL 240#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
237 [NL802154_ATTR_SEC_ENABLED] = { .type = NLA_U8, }, 241 [NL802154_ATTR_SEC_ENABLED] = { .type = NLA_U8, },
238 [NL802154_ATTR_SEC_OUT_LEVEL] = { .type = NLA_U32, }, 242 [NL802154_ATTR_SEC_OUT_LEVEL] = { .type = NLA_U32, },
@@ -590,7 +594,6 @@ static int nl802154_dump_wpan_phy_parse(struct sk_buff *skb,
590 struct cfg802154_registered_device *rdev; 594 struct cfg802154_registered_device *rdev;
591 int ifidx = nla_get_u32(tb[NL802154_ATTR_IFINDEX]); 595 int ifidx = nla_get_u32(tb[NL802154_ATTR_IFINDEX]);
592 596
593 /* TODO netns */
594 netdev = __dev_get_by_index(&init_net, ifidx); 597 netdev = __dev_get_by_index(&init_net, ifidx);
595 if (!netdev) 598 if (!netdev)
596 return -ENODEV; 599 return -ENODEV;
@@ -629,7 +632,8 @@ nl802154_dump_wpan_phy(struct sk_buff *skb, struct netlink_callback *cb)
629 } 632 }
630 633
631 list_for_each_entry(rdev, &cfg802154_rdev_list, list) { 634 list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
632 /* TODO net ns compare */ 635 if (!net_eq(wpan_phy_net(&rdev->wpan_phy), sock_net(skb->sk)))
636 continue;
633 if (++idx <= state->start) 637 if (++idx <= state->start)
634 continue; 638 continue;
635 if (state->filter_wpan_phy != -1 && 639 if (state->filter_wpan_phy != -1 &&
@@ -871,7 +875,8 @@ nl802154_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
871 875
872 rtnl_lock(); 876 rtnl_lock();
873 list_for_each_entry(rdev, &cfg802154_rdev_list, list) { 877 list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
874 /* TODO netns compare */ 878 if (!net_eq(wpan_phy_net(&rdev->wpan_phy), sock_net(skb->sk)))
879 continue;
875 if (wp_idx < wp_start) { 880 if (wp_idx < wp_start) {
876 wp_idx++; 881 wp_idx++;
877 continue; 882 continue;
@@ -1271,6 +1276,37 @@ nl802154_set_ackreq_default(struct sk_buff *skb, struct genl_info *info)
1271 return rdev_set_ackreq_default(rdev, wpan_dev, ackreq); 1276 return rdev_set_ackreq_default(rdev, wpan_dev, ackreq);
1272} 1277}
1273 1278
1279static int nl802154_wpan_phy_netns(struct sk_buff *skb, struct genl_info *info)
1280{
1281 struct cfg802154_registered_device *rdev = info->user_ptr[0];
1282 struct net *net;
1283 int err;
1284
1285 if (info->attrs[NL802154_ATTR_PID]) {
1286 u32 pid = nla_get_u32(info->attrs[NL802154_ATTR_PID]);
1287
1288 net = get_net_ns_by_pid(pid);
1289 } else if (info->attrs[NL802154_ATTR_NETNS_FD]) {
1290 u32 fd = nla_get_u32(info->attrs[NL802154_ATTR_NETNS_FD]);
1291
1292 net = get_net_ns_by_fd(fd);
1293 } else {
1294 return -EINVAL;
1295 }
1296
1297 if (IS_ERR(net))
1298 return PTR_ERR(net);
1299
1300 err = 0;
1301
1302 /* check if anything to do */
1303 if (!net_eq(wpan_phy_net(&rdev->wpan_phy), net))
1304 err = cfg802154_switch_netns(rdev, net);
1305
1306 put_net(net);
1307 return err;
1308}
1309
1274#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL 1310#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
1275static const struct nla_policy nl802154_dev_addr_policy[NL802154_DEV_ADDR_ATTR_MAX + 1] = { 1311static const struct nla_policy nl802154_dev_addr_policy[NL802154_DEV_ADDR_ATTR_MAX + 1] = {
1276 [NL802154_DEV_ADDR_ATTR_PAN_ID] = { .type = NLA_U16 }, 1312 [NL802154_DEV_ADDR_ATTR_PAN_ID] = { .type = NLA_U16 },
@@ -2262,6 +2298,14 @@ static const struct genl_ops nl802154_ops[] = {
2262 NL802154_FLAG_NEED_RTNL, 2298 NL802154_FLAG_NEED_RTNL,
2263 }, 2299 },
2264 { 2300 {
2301 .cmd = NL802154_CMD_SET_WPAN_PHY_NETNS,
2302 .doit = nl802154_wpan_phy_netns,
2303 .policy = nl802154_policy,
2304 .flags = GENL_ADMIN_PERM,
2305 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2306 NL802154_FLAG_NEED_RTNL,
2307 },
2308 {
2265 .cmd = NL802154_CMD_SET_PAN_ID, 2309 .cmd = NL802154_CMD_SET_PAN_ID,
2266 .doit = nl802154_set_pan_id, 2310 .doit = nl802154_set_pan_id,
2267 .policy = nl802154_policy, 2311 .policy = nl802154_policy,