diff options
author | Nicolas Dichtel <nicolas.dichtel@6wind.com> | 2015-04-07 05:51:53 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-04-07 17:29:41 -0400 |
commit | 9a9634545c7051f567096117d417e9c3be24706d (patch) | |
tree | d3238d41a1c5aa27c4b53e476d9892c4dcc99e23 | |
parent | b111e4e1112316e800dd1f1debdf017d2cf940b2 (diff) |
netns: notify netns id events
With this patch, netns ids that are created and deleted are advertised into the
group RTNLGRP_NSID.
Because callers of rtnl_net_notifyid() already know the id of the peer, there is
no need to call __peernet2id() in rtnl_net_fill().
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/uapi/linux/rtnetlink.h | 4 | ||||
-rw-r--r-- | net/core/net_namespace.c | 52 |
2 files changed, 48 insertions, 8 deletions
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h index bea910f924dd..974db03f7b1a 100644 --- a/include/uapi/linux/rtnetlink.h +++ b/include/uapi/linux/rtnetlink.h | |||
@@ -134,6 +134,8 @@ enum { | |||
134 | 134 | ||
135 | RTM_NEWNSID = 88, | 135 | RTM_NEWNSID = 88, |
136 | #define RTM_NEWNSID RTM_NEWNSID | 136 | #define RTM_NEWNSID RTM_NEWNSID |
137 | RTM_DELNSID = 89, | ||
138 | #define RTM_DELNSID RTM_DELNSID | ||
137 | RTM_GETNSID = 90, | 139 | RTM_GETNSID = 90, |
138 | #define RTM_GETNSID RTM_GETNSID | 140 | #define RTM_GETNSID RTM_GETNSID |
139 | 141 | ||
@@ -635,6 +637,8 @@ enum rtnetlink_groups { | |||
635 | #define RTNLGRP_MDB RTNLGRP_MDB | 637 | #define RTNLGRP_MDB RTNLGRP_MDB |
636 | RTNLGRP_MPLS_ROUTE, | 638 | RTNLGRP_MPLS_ROUTE, |
637 | #define RTNLGRP_MPLS_ROUTE RTNLGRP_MPLS_ROUTE | 639 | #define RTNLGRP_MPLS_ROUTE RTNLGRP_MPLS_ROUTE |
640 | RTNLGRP_NSID, | ||
641 | #define RTNLGRP_NSID RTNLGRP_NSID | ||
638 | __RTNLGRP_MAX | 642 | __RTNLGRP_MAX |
639 | }; | 643 | }; |
640 | #define RTNLGRP_MAX (__RTNLGRP_MAX - 1) | 644 | #define RTNLGRP_MAX (__RTNLGRP_MAX - 1) |
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index be28afccfbbb..b3b5f22f0e90 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
@@ -148,9 +148,11 @@ static void ops_free_list(const struct pernet_operations *ops, | |||
148 | } | 148 | } |
149 | } | 149 | } |
150 | 150 | ||
151 | static void rtnl_net_notifyid(struct net *net, struct net *peer, int cmd, | ||
152 | int id); | ||
151 | static int alloc_netid(struct net *net, struct net *peer, int reqid) | 153 | static int alloc_netid(struct net *net, struct net *peer, int reqid) |
152 | { | 154 | { |
153 | int min = 0, max = 0; | 155 | int min = 0, max = 0, id; |
154 | 156 | ||
155 | ASSERT_RTNL(); | 157 | ASSERT_RTNL(); |
156 | 158 | ||
@@ -159,7 +161,11 @@ static int alloc_netid(struct net *net, struct net *peer, int reqid) | |||
159 | max = reqid + 1; | 161 | max = reqid + 1; |
160 | } | 162 | } |
161 | 163 | ||
162 | return idr_alloc(&net->netns_ids, peer, min, max, GFP_KERNEL); | 164 | id = idr_alloc(&net->netns_ids, peer, min, max, GFP_KERNEL); |
165 | if (id >= 0) | ||
166 | rtnl_net_notifyid(net, peer, RTM_NEWNSID, id); | ||
167 | |||
168 | return id; | ||
163 | } | 169 | } |
164 | 170 | ||
165 | /* This function is used by idr_for_each(). If net is equal to peer, the | 171 | /* This function is used by idr_for_each(). If net is equal to peer, the |
@@ -359,8 +365,10 @@ static void cleanup_net(struct work_struct *work) | |||
359 | for_each_net(tmp) { | 365 | for_each_net(tmp) { |
360 | int id = __peernet2id(tmp, net, false); | 366 | int id = __peernet2id(tmp, net, false); |
361 | 367 | ||
362 | if (id >= 0) | 368 | if (id >= 0) { |
369 | rtnl_net_notifyid(tmp, net, RTM_DELNSID, id); | ||
363 | idr_remove(&tmp->netns_ids, id); | 370 | idr_remove(&tmp->netns_ids, id); |
371 | } | ||
364 | } | 372 | } |
365 | idr_destroy(&net->netns_ids); | 373 | idr_destroy(&net->netns_ids); |
366 | 374 | ||
@@ -531,7 +539,8 @@ static int rtnl_net_get_size(void) | |||
531 | } | 539 | } |
532 | 540 | ||
533 | static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags, | 541 | static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags, |
534 | int cmd, struct net *net, struct net *peer) | 542 | int cmd, struct net *net, struct net *peer, |
543 | int nsid) | ||
535 | { | 544 | { |
536 | struct nlmsghdr *nlh; | 545 | struct nlmsghdr *nlh; |
537 | struct rtgenmsg *rth; | 546 | struct rtgenmsg *rth; |
@@ -546,9 +555,13 @@ static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags, | |||
546 | rth = nlmsg_data(nlh); | 555 | rth = nlmsg_data(nlh); |
547 | rth->rtgen_family = AF_UNSPEC; | 556 | rth->rtgen_family = AF_UNSPEC; |
548 | 557 | ||
549 | id = __peernet2id(net, peer, false); | 558 | if (nsid >= 0) { |
550 | if (id < 0) | 559 | id = nsid; |
551 | id = NETNSA_NSID_NOT_ASSIGNED; | 560 | } else { |
561 | id = __peernet2id(net, peer, false); | ||
562 | if (id < 0) | ||
563 | id = NETNSA_NSID_NOT_ASSIGNED; | ||
564 | } | ||
552 | if (nla_put_s32(skb, NETNSA_NSID, id)) | 565 | if (nla_put_s32(skb, NETNSA_NSID, id)) |
553 | goto nla_put_failure; | 566 | goto nla_put_failure; |
554 | 567 | ||
@@ -589,7 +602,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
589 | } | 602 | } |
590 | 603 | ||
591 | err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0, | 604 | err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0, |
592 | RTM_GETNSID, net, peer); | 605 | RTM_GETNSID, net, peer, -1); |
593 | if (err < 0) | 606 | if (err < 0) |
594 | goto err_out; | 607 | goto err_out; |
595 | 608 | ||
@@ -603,6 +616,29 @@ out: | |||
603 | return err; | 616 | return err; |
604 | } | 617 | } |
605 | 618 | ||
619 | static void rtnl_net_notifyid(struct net *net, struct net *peer, int cmd, | ||
620 | int id) | ||
621 | { | ||
622 | struct sk_buff *msg; | ||
623 | int err = -ENOMEM; | ||
624 | |||
625 | msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL); | ||
626 | if (!msg) | ||
627 | goto out; | ||
628 | |||
629 | err = rtnl_net_fill(msg, 0, 0, 0, cmd, net, peer, id); | ||
630 | if (err < 0) | ||
631 | goto err_out; | ||
632 | |||
633 | rtnl_notify(msg, net, 0, RTNLGRP_NSID, NULL, 0); | ||
634 | return; | ||
635 | |||
636 | err_out: | ||
637 | nlmsg_free(msg); | ||
638 | out: | ||
639 | rtnl_set_sk_err(net, RTNLGRP_NSID, err); | ||
640 | } | ||
641 | |||
606 | static int __init net_ns_init(void) | 642 | static int __init net_ns_init(void) |
607 | { | 643 | { |
608 | struct net_generic *ng; | 644 | struct net_generic *ng; |