* [PATCH net-next 0/4] Ease to interpret net-nsid
@ 2018-11-21 11:01 Nicolas Dichtel
2018-11-21 11:01 ` [PATCH net-next 1/4] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel
` (4 more replies)
0 siblings, 5 replies; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-21 11:01 UTC (permalink / raw)
To: davem; +Cc: netdev
The goal of this series is to ease the interpretation of nsid received in
netlink messages from other netns (when the user uses
NETLINK_F_LISTEN_ALL_NSID).
After this series, with a patched iproute2:
$ ip netns add foo
$ ip netns add bar
$ touch /var/run/netns/init_net
$ mount --bind /proc/1/ns/net /var/run/netns/init_net
$ ip netns set init_net 11
$ ip netns set foo 12
$ ip netns set bar 13
$ ip netns
init_net (id: 11)
bar (id: 13)
foo (id: 12)
$ ip -n foo netns set init_net 21
$ ip -n foo netns set foo 22
$ ip -n foo netns set bar 23
$ ip -n foo netns
init_net (id: 21)
bar (id: 23)
foo (id: 22)
$ ip -n bar netns set init_net 31
$ ip -n bar netns set foo 32
$ ip -n bar netns set bar 33
$ ip -n bar netns
init_net (id: 31)
bar (id: 33)
foo (id: 32)
$ ip netns list-id target-nsid 12
nsid 21 current-nsid 11 (iproute2 netns name: init_net)
nsid 22 current-nsid 12 (iproute2 netns name: foo)
nsid 23 current-nsid 13 (iproute2 netns name: bar)
$ ip -n bar netns list-id target-nsid 32 nsid 31
nsid 21 current-nsid 31 (iproute2 netns name: init_net)
include/uapi/linux/net_namespace.h | 2 +
net/core/net_namespace.c | 132 ++++++++++++++++++++++++++++++-------
2 files changed, 110 insertions(+), 24 deletions(-)
Comments are welcomed,
Regards,
Nicolas
^ permalink raw reply [flat|nested] 39+ messages in thread
* [PATCH net-next 1/4] netns: remove net arg from rtnl_net_fill()
2018-11-21 11:01 [PATCH net-next 0/4] Ease to interpret net-nsid Nicolas Dichtel
@ 2018-11-21 11:01 ` Nicolas Dichtel
2018-11-21 11:01 ` [PATCH net-next 2/4] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel
` (3 subsequent siblings)
4 siblings, 0 replies; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-21 11:01 UTC (permalink / raw)
To: davem; +Cc: netdev, Nicolas Dichtel
This argument is not used anymore.
Fixes: cab3c8ec8d57 ("netns: always provide the id to rtnl_net_fill()")
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
net/core/net_namespace.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index fefe72774aeb..3e6af99bbe53 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -739,7 +739,7 @@ static int rtnl_net_get_size(void)
}
static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
- int cmd, struct net *net, int nsid)
+ int cmd, int nsid)
{
struct nlmsghdr *nlh;
struct rtgenmsg *rth;
@@ -801,7 +801,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
id = peernet2id(net, peer);
err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
- RTM_NEWNSID, net, id);
+ RTM_NEWNSID, id);
if (err < 0)
goto err_out;
@@ -833,7 +833,7 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data)
ret = rtnl_net_fill(net_cb->skb, NETLINK_CB(net_cb->cb->skb).portid,
net_cb->cb->nlh->nlmsg_seq, NLM_F_MULTI,
- RTM_NEWNSID, net_cb->net, id);
+ RTM_NEWNSID, id);
if (ret < 0)
return ret;
@@ -876,7 +876,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id)
if (!msg)
goto out;
- err = rtnl_net_fill(msg, 0, 0, 0, cmd, net, id);
+ err = rtnl_net_fill(msg, 0, 0, 0, cmd, id);
if (err < 0)
goto err_out;
--
2.18.0
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next 2/4] netns: add support of NETNSA_TARGET_NSID
2018-11-21 11:01 [PATCH net-next 0/4] Ease to interpret net-nsid Nicolas Dichtel
2018-11-21 11:01 ` [PATCH net-next 1/4] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel
@ 2018-11-21 11:01 ` Nicolas Dichtel
2018-11-21 18:05 ` David Ahern
2018-11-21 11:01 ` [PATCH net-next 3/4] netns: enable to specify a nsid for a get request Nicolas Dichtel
` (2 subsequent siblings)
4 siblings, 1 reply; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-21 11:01 UTC (permalink / raw)
To: davem; +Cc: netdev, Nicolas Dichtel
Like it was done for link and address, add the ability to perform get/dump
in another netns by specifying a target nsid attribute.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
include/uapi/linux/net_namespace.h | 1 +
net/core/net_namespace.c | 97 ++++++++++++++++++++++++------
2 files changed, 80 insertions(+), 18 deletions(-)
diff --git a/include/uapi/linux/net_namespace.h b/include/uapi/linux/net_namespace.h
index 0187c74d8889..0ed9dd61d32a 100644
--- a/include/uapi/linux/net_namespace.h
+++ b/include/uapi/linux/net_namespace.h
@@ -16,6 +16,7 @@ enum {
NETNSA_NSID,
NETNSA_PID,
NETNSA_FD,
+ NETNSA_TARGET_NSID,
__NETNSA_MAX,
};
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 3e6af99bbe53..3d02a742155f 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -669,6 +669,7 @@ static const struct nla_policy rtnl_net_policy[NETNSA_MAX + 1] = {
[NETNSA_NSID] = { .type = NLA_S32 },
[NETNSA_PID] = { .type = NLA_U32 },
[NETNSA_FD] = { .type = NLA_U32 },
+ [NETNSA_TARGET_NSID] = { .type = NLA_S32 },
};
static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -767,9 +768,9 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
{
struct net *net = sock_net(skb->sk);
struct nlattr *tb[NETNSA_MAX + 1];
+ struct net *peer, *target = net;
struct nlattr *nla;
struct sk_buff *msg;
- struct net *peer;
int err, id;
err = nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX,
@@ -793,30 +794,47 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
return PTR_ERR(peer);
}
+ if (tb[NETNSA_TARGET_NSID]) {
+ id = nla_get_s32(tb[NETNSA_TARGET_NSID]);
+ target = rtnl_get_net_ns_capable(NETLINK_CB(skb).sk, id);
+ if (IS_ERR(target)) {
+ NL_SET_BAD_ATTR(extack, tb[NETNSA_TARGET_NSID]);
+ NL_SET_ERR_MSG(extack,
+ "Target netns reference is invalid");
+ err = PTR_ERR(target);
+ goto put_peer;
+ }
+ } else {
+ get_net(target);
+ }
+
msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL);
if (!msg) {
err = -ENOMEM;
- goto out;
+ goto put_target;
}
- id = peernet2id(net, peer);
+ id = peernet2id(target, peer);
err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
RTM_NEWNSID, id);
if (err < 0)
- goto err_out;
+ goto free_nlmsg;
err = rtnl_unicast(msg, net, NETLINK_CB(skb).portid);
- goto out;
+ goto put_target;
-err_out:
+free_nlmsg:
nlmsg_free(msg);
-out:
+put_target:
+ put_net(target);
+put_peer:
put_net(peer);
return err;
}
struct rtnl_net_dump_cb {
- struct net *net;
+ struct net *tgt_net;
+ struct net *ref_net;
struct sk_buff *skb;
struct netlink_callback *cb;
int idx;
@@ -842,29 +860,72 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data)
return 0;
}
+static int rtnl_valid_dump_net_req(const struct nlmsghdr *nlh, struct sock *sk,
+ struct rtnl_net_dump_cb *net_cb,
+ struct netlink_callback *cb)
+{
+ struct netlink_ext_ack *extack = cb->extack;
+ struct nlattr *tb[NETNSA_MAX + 1];
+ int err, i;
+
+ err = nlmsg_parse_strict(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX,
+ rtnl_net_policy, extack);
+ if (err < 0)
+ return err;
+
+ for (i = 0; i <= NETNSA_MAX; i++) {
+ if (!tb[i])
+ continue;
+
+ if (i == NETNSA_TARGET_NSID) {
+ struct net *net;
+
+ net = rtnl_get_net_ns_capable(sk, nla_get_s32(tb[i]));
+ if (IS_ERR(net)) {
+ NL_SET_BAD_ATTR(extack, tb[i]);
+ NL_SET_ERR_MSG(extack,
+ "Invalid target network namespace id");
+ return PTR_ERR(net);
+ }
+ net_cb->ref_net = net_cb->tgt_net;
+ net_cb->tgt_net = net;
+ } else {
+ NL_SET_BAD_ATTR(extack, tb[i]);
+ NL_SET_ERR_MSG(extack,
+ "Unsupported attribute in dump request");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
{
- struct net *net = sock_net(skb->sk);
struct rtnl_net_dump_cb net_cb = {
- .net = net,
+ .tgt_net = sock_net(skb->sk),
.skb = skb,
.cb = cb,
.idx = 0,
.s_idx = cb->args[0],
};
+ int err = 0;
- if (cb->strict_check &&
- nlmsg_attrlen(cb->nlh, sizeof(struct rtgenmsg))) {
- NL_SET_ERR_MSG(cb->extack, "Unknown data in network namespace id dump request");
- return -EINVAL;
+ if (cb->strict_check) {
+ err = rtnl_valid_dump_net_req(cb->nlh, skb->sk, &net_cb, cb);
+ if (err < 0)
+ goto end;
}
- spin_lock_bh(&net->nsid_lock);
- idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb);
- spin_unlock_bh(&net->nsid_lock);
+ spin_lock_bh(&net_cb.tgt_net->nsid_lock);
+ idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb);
+ spin_unlock_bh(&net_cb.tgt_net->nsid_lock);
cb->args[0] = net_cb.idx;
- return skb->len;
+end:
+ if (net_cb.ref_net)
+ put_net(net_cb.tgt_net);
+ return err < 0 ? err : skb->len;
}
static void rtnl_net_notifyid(struct net *net, int cmd, int id)
--
2.18.0
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next 3/4] netns: enable to specify a nsid for a get request
2018-11-21 11:01 [PATCH net-next 0/4] Ease to interpret net-nsid Nicolas Dichtel
2018-11-21 11:01 ` [PATCH net-next 1/4] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel
2018-11-21 11:01 ` [PATCH net-next 2/4] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel
@ 2018-11-21 11:01 ` Nicolas Dichtel
2018-11-21 11:01 ` [PATCH net-next 4/4] netns: enable to dump full nsid translation table Nicolas Dichtel
2018-11-22 15:50 ` [PATCH net-next v2 0/5] Ease to interpret net-nsid Nicolas Dichtel
4 siblings, 0 replies; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-21 11:01 UTC (permalink / raw)
To: davem; +Cc: netdev, Nicolas Dichtel
Combined with NETNSA_TARGET_NSID, it enables to "translate" a nsid from one
netns to a nsid of another netns.
This is useful when using NETLINK_F_LISTEN_ALL_NSID because it helps the
user to interpret a nsid received from an other netns.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
net/core/net_namespace.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 3d02a742155f..92730905886c 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -783,6 +783,11 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
} else if (tb[NETNSA_FD]) {
peer = get_net_ns_by_fd(nla_get_u32(tb[NETNSA_FD]));
nla = tb[NETNSA_FD];
+ } else if (tb[NETNSA_NSID]) {
+ peer = get_net_ns_by_id(net, nla_get_u32(tb[NETNSA_NSID]));
+ if (!peer)
+ peer = ERR_PTR(-ENOENT);
+ nla = tb[NETNSA_NSID];
} else {
NL_SET_ERR_MSG(extack, "Peer netns reference is missing");
return -EINVAL;
--
2.18.0
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next 4/4] netns: enable to dump full nsid translation table
2018-11-21 11:01 [PATCH net-next 0/4] Ease to interpret net-nsid Nicolas Dichtel
` (2 preceding siblings ...)
2018-11-21 11:01 ` [PATCH net-next 3/4] netns: enable to specify a nsid for a get request Nicolas Dichtel
@ 2018-11-21 11:01 ` Nicolas Dichtel
2018-11-21 18:09 ` David Ahern
2018-11-22 15:50 ` [PATCH net-next v2 0/5] Ease to interpret net-nsid Nicolas Dichtel
4 siblings, 1 reply; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-21 11:01 UTC (permalink / raw)
To: davem; +Cc: netdev, Nicolas Dichtel
Like the previous patch, the goal is to ease to convert nsids from one
netns to another netns.
A new attribute (NETNSA_CURRENT_NSID) is added to the kernel answer when
NETNSA_TARGET_NSID is provided, thus the user can easily convert nsids.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
include/uapi/linux/net_namespace.h | 1 +
net/core/net_namespace.c | 30 ++++++++++++++++++++++++------
2 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/include/uapi/linux/net_namespace.h b/include/uapi/linux/net_namespace.h
index 0ed9dd61d32a..9f9956809565 100644
--- a/include/uapi/linux/net_namespace.h
+++ b/include/uapi/linux/net_namespace.h
@@ -17,6 +17,7 @@ enum {
NETNSA_PID,
NETNSA_FD,
NETNSA_TARGET_NSID,
+ NETNSA_CURRENT_NSID,
__NETNSA_MAX,
};
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 92730905886c..fc568cd0b560 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -740,7 +740,7 @@ static int rtnl_net_get_size(void)
}
static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
- int cmd, int nsid)
+ int cmd, int nsid, bool add_ref, int ref_nsid)
{
struct nlmsghdr *nlh;
struct rtgenmsg *rth;
@@ -755,6 +755,9 @@ static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
if (nla_put_s32(skb, NETNSA_NSID, nsid))
goto nla_put_failure;
+ if (add_ref && nla_put_s32(skb, NETNSA_CURRENT_NSID, ref_nsid))
+ goto nla_put_failure;
+
nlmsg_end(skb, nlh);
return 0;
@@ -769,9 +772,10 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
struct net *net = sock_net(skb->sk);
struct nlattr *tb[NETNSA_MAX + 1];
struct net *peer, *target = net;
+ bool add_ref = false;
struct nlattr *nla;
struct sk_buff *msg;
- int err, id;
+ int err, id, ref_id;
err = nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX,
rtnl_net_policy, extack);
@@ -809,6 +813,8 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
err = PTR_ERR(target);
goto put_peer;
}
+ ref_id = peernet2id(net, peer);
+ add_ref = true;
} else {
get_net(target);
}
@@ -821,7 +827,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
id = peernet2id(target, peer);
err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
- RTM_NEWNSID, id);
+ RTM_NEWNSID, id, add_ref, ref_id);
if (err < 0)
goto free_nlmsg;
@@ -849,14 +855,17 @@ struct rtnl_net_dump_cb {
static int rtnl_net_dumpid_one(int id, void *peer, void *data)
{
struct rtnl_net_dump_cb *net_cb = (struct rtnl_net_dump_cb *)data;
- int ret;
+ int ref_id = 0, ret;
if (net_cb->idx < net_cb->s_idx)
goto cont;
+ if (net_cb->ref_net)
+ ref_id = __peernet2id(net_cb->ref_net, peer);
+
ret = rtnl_net_fill(net_cb->skb, NETLINK_CB(net_cb->cb->skb).portid,
net_cb->cb->nlh->nlmsg_seq, NLM_F_MULTI,
- RTM_NEWNSID, id);
+ RTM_NEWNSID, id, net_cb->ref_net, ref_id);
if (ret < 0)
return ret;
@@ -923,7 +932,16 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
}
spin_lock_bh(&net_cb.tgt_net->nsid_lock);
+ if (net_cb.ref_net &&
+ !net_eq(net_cb.ref_net, net_cb.tgt_net) &&
+ !spin_trylock_bh(&net_cb.ref_net->nsid_lock)) {
+ err = -EAGAIN;
+ goto end;
+ }
idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb);
+ if (net_cb.ref_net &&
+ !net_eq(net_cb.ref_net, net_cb.tgt_net))
+ spin_unlock_bh(&net_cb.ref_net->nsid_lock);
spin_unlock_bh(&net_cb.tgt_net->nsid_lock);
cb->args[0] = net_cb.idx;
@@ -942,7 +960,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id)
if (!msg)
goto out;
- err = rtnl_net_fill(msg, 0, 0, 0, cmd, id);
+ err = rtnl_net_fill(msg, 0, 0, 0, cmd, id, false, 0);
if (err < 0)
goto err_out;
--
2.18.0
^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [PATCH net-next 2/4] netns: add support of NETNSA_TARGET_NSID
2018-11-21 11:01 ` [PATCH net-next 2/4] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel
@ 2018-11-21 18:05 ` David Ahern
2018-11-21 20:58 ` Nicolas Dichtel
0 siblings, 1 reply; 39+ messages in thread
From: David Ahern @ 2018-11-21 18:05 UTC (permalink / raw)
To: Nicolas Dichtel, davem; +Cc: netdev
On 11/21/18 4:01 AM, Nicolas Dichtel wrote:
> static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
> {
> - struct net *net = sock_net(skb->sk);
> struct rtnl_net_dump_cb net_cb = {
> - .net = net,
> + .tgt_net = sock_net(skb->sk),
> .skb = skb,
> .cb = cb,
> .idx = 0,
> .s_idx = cb->args[0],
> };
> + int err = 0;
>
> - if (cb->strict_check &&
> - nlmsg_attrlen(cb->nlh, sizeof(struct rtgenmsg))) {
> - NL_SET_ERR_MSG(cb->extack, "Unknown data in network namespace id dump request");
> - return -EINVAL;
> + if (cb->strict_check) {
> + err = rtnl_valid_dump_net_req(cb->nlh, skb->sk, &net_cb, cb);
> + if (err < 0)
> + goto end;
> }
>
> - spin_lock_bh(&net->nsid_lock);
> - idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb);
> - spin_unlock_bh(&net->nsid_lock);
> + spin_lock_bh(&net_cb.tgt_net->nsid_lock);
> + idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb);
> + spin_unlock_bh(&net_cb.tgt_net->nsid_lock);
>
> cb->args[0] = net_cb.idx;
> - return skb->len;
> +end:
> + if (net_cb.ref_net)
> + put_net(net_cb.tgt_net);
That is going to lead to confusion -- you check that ref_net is set put
do a put on tgt_net. Other places using a target namespace use the nsid
as the key to whether a put_net is needed.
> + return err < 0 ? err : skb->len;
> }
>
> static void rtnl_net_notifyid(struct net *net, int cmd, int id)
>
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH net-next 4/4] netns: enable to dump full nsid translation table
2018-11-21 11:01 ` [PATCH net-next 4/4] netns: enable to dump full nsid translation table Nicolas Dichtel
@ 2018-11-21 18:09 ` David Ahern
2018-11-21 21:01 ` Nicolas Dichtel
0 siblings, 1 reply; 39+ messages in thread
From: David Ahern @ 2018-11-21 18:09 UTC (permalink / raw)
To: Nicolas Dichtel, davem; +Cc: netdev
On 11/21/18 4:01 AM, Nicolas Dichtel wrote:
> diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
> index 92730905886c..fc568cd0b560 100644
> --- a/net/core/net_namespace.c
> +++ b/net/core/net_namespace.c
> @@ -740,7 +740,7 @@ static int rtnl_net_get_size(void)
> }
>
> static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
> - int cmd, int nsid)
> + int cmd, int nsid, bool add_ref, int ref_nsid)
> {
> struct nlmsghdr *nlh;
> struct rtgenmsg *rth;
> @@ -755,6 +755,9 @@ static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
> if (nla_put_s32(skb, NETNSA_NSID, nsid))
> goto nla_put_failure;
>
> + if (add_ref && nla_put_s32(skb, NETNSA_CURRENT_NSID, ref_nsid))
> + goto nla_put_failure;
Why not use ref_nsid >= 0 and drop the add_ref argument?
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH net-next 2/4] netns: add support of NETNSA_TARGET_NSID
2018-11-21 18:05 ` David Ahern
@ 2018-11-21 20:58 ` Nicolas Dichtel
2018-11-21 21:07 ` David Ahern
0 siblings, 1 reply; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-21 20:58 UTC (permalink / raw)
To: David Ahern, davem; +Cc: netdev
Le 21/11/2018 à 19:05, David Ahern a écrit :
> On 11/21/18 4:01 AM, Nicolas Dichtel wrote:
>> static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
>> {
>> - struct net *net = sock_net(skb->sk);
>> struct rtnl_net_dump_cb net_cb = {
>> - .net = net,
>> + .tgt_net = sock_net(skb->sk),
>> .skb = skb,
>> .cb = cb,
>> .idx = 0,
>> .s_idx = cb->args[0],
>> };
>> + int err = 0;
>>
>> - if (cb->strict_check &&
>> - nlmsg_attrlen(cb->nlh, sizeof(struct rtgenmsg))) {
>> - NL_SET_ERR_MSG(cb->extack, "Unknown data in network namespace id dump request");
>> - return -EINVAL;
>> + if (cb->strict_check) {
>> + err = rtnl_valid_dump_net_req(cb->nlh, skb->sk, &net_cb, cb);
>> + if (err < 0)
>> + goto end;
>> }
>>
>> - spin_lock_bh(&net->nsid_lock);
>> - idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb);
>> - spin_unlock_bh(&net->nsid_lock);
>> + spin_lock_bh(&net_cb.tgt_net->nsid_lock);
>> + idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb);
>> + spin_unlock_bh(&net_cb.tgt_net->nsid_lock);
>>
>> cb->args[0] = net_cb.idx;
>> - return skb->len;
>> +end:
>> + if (net_cb.ref_net)
>> + put_net(net_cb.tgt_net);
>
> That is going to lead to confusion -- you check that ref_net is set put
> do a put on tgt_net. Other places using a target namespace use the nsid
> as the key to whether a put_net is needed.
The target-nsid is not stored in net_cb (not needed). ref_net is set only if
tgt_net comes from TARGET_NSID. I can add a comment.
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH net-next 4/4] netns: enable to dump full nsid translation table
2018-11-21 18:09 ` David Ahern
@ 2018-11-21 21:01 ` Nicolas Dichtel
2018-11-21 21:08 ` David Ahern
0 siblings, 1 reply; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-21 21:01 UTC (permalink / raw)
To: David Ahern, davem; +Cc: netdev
Le 21/11/2018 à 19:09, David Ahern a écrit :
> On 11/21/18 4:01 AM, Nicolas Dichtel wrote:
>> diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
>> index 92730905886c..fc568cd0b560 100644
>> --- a/net/core/net_namespace.c
>> +++ b/net/core/net_namespace.c
>> @@ -740,7 +740,7 @@ static int rtnl_net_get_size(void)
>> }
>>
>> static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
>> - int cmd, int nsid)
>> + int cmd, int nsid, bool add_ref, int ref_nsid)
>> {
>> struct nlmsghdr *nlh;
>> struct rtgenmsg *rth;
>> @@ -755,6 +755,9 @@ static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
>> if (nla_put_s32(skb, NETNSA_NSID, nsid))
>> goto nla_put_failure;
>>
>> + if (add_ref && nla_put_s32(skb, NETNSA_CURRENT_NSID, ref_nsid))
>> + goto nla_put_failure;
>
> Why not use ref_nsid >= 0 and drop the add_ref argument?
Because ref_nsid can be -1 (NETNSA_NSID_NOT_ASSIGNED) and I didn't want to add
another magic, I think it's clearer with an explicit bool.
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH net-next 2/4] netns: add support of NETNSA_TARGET_NSID
2018-11-21 20:58 ` Nicolas Dichtel
@ 2018-11-21 21:07 ` David Ahern
2018-11-22 8:06 ` Nicolas Dichtel
0 siblings, 1 reply; 39+ messages in thread
From: David Ahern @ 2018-11-21 21:07 UTC (permalink / raw)
To: nicolas.dichtel, davem; +Cc: netdev
On 11/21/18 1:58 PM, Nicolas Dichtel wrote:
> The target-nsid is not stored in net_cb (not needed). ref_net is set only if
> tgt_net comes from TARGET_NSID. I can add a comment.
ref_net is added by this patch and it is only used (unless I missed
something) to know if the put_net is needed. ie/, drop ref_net in place
of nsid
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH net-next 4/4] netns: enable to dump full nsid translation table
2018-11-21 21:01 ` Nicolas Dichtel
@ 2018-11-21 21:08 ` David Ahern
0 siblings, 0 replies; 39+ messages in thread
From: David Ahern @ 2018-11-21 21:08 UTC (permalink / raw)
To: nicolas.dichtel, davem; +Cc: netdev
On 11/21/18 2:01 PM, Nicolas Dichtel wrote:
> Le 21/11/2018 à 19:09, David Ahern a écrit :
>> On 11/21/18 4:01 AM, Nicolas Dichtel wrote:
>>> diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
>>> index 92730905886c..fc568cd0b560 100644
>>> --- a/net/core/net_namespace.c
>>> +++ b/net/core/net_namespace.c
>>> @@ -740,7 +740,7 @@ static int rtnl_net_get_size(void)
>>> }
>>>
>>> static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
>>> - int cmd, int nsid)
>>> + int cmd, int nsid, bool add_ref, int ref_nsid)
>>> {
>>> struct nlmsghdr *nlh;
>>> struct rtgenmsg *rth;
>>> @@ -755,6 +755,9 @@ static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
>>> if (nla_put_s32(skb, NETNSA_NSID, nsid))
>>> goto nla_put_failure;
>>>
>>> + if (add_ref && nla_put_s32(skb, NETNSA_CURRENT_NSID, ref_nsid))
>>> + goto nla_put_failure;
>>
>> Why not use ref_nsid >= 0 and drop the add_ref argument?
> Because ref_nsid can be -1 (NETNSA_NSID_NOT_ASSIGNED) and I didn't want to add
> another magic, I think it's clearer with an explicit bool.
>
it pushes the input args to 8.
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH net-next 2/4] netns: add support of NETNSA_TARGET_NSID
2018-11-21 21:07 ` David Ahern
@ 2018-11-22 8:06 ` Nicolas Dichtel
0 siblings, 0 replies; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-22 8:06 UTC (permalink / raw)
To: David Ahern, davem; +Cc: netdev
Le 21/11/2018 à 22:07, David Ahern a écrit :
> On 11/21/18 1:58 PM, Nicolas Dichtel wrote:
>> The target-nsid is not stored in net_cb (not needed). ref_net is set only if
>> tgt_net comes from TARGET_NSID. I can add a comment.
>
> ref_net is added by this patch and it is only used (unless I missed
> something) to know if the put_net is needed. ie/, drop ref_net in place
> of nsid
It is used by a following patch (4/4) to get NETNSA_CURRENT_NSID.
^ permalink raw reply [flat|nested] 39+ messages in thread
* [PATCH net-next v2 0/5] Ease to interpret net-nsid
2018-11-21 11:01 [PATCH net-next 0/4] Ease to interpret net-nsid Nicolas Dichtel
` (3 preceding siblings ...)
2018-11-21 11:01 ` [PATCH net-next 4/4] netns: enable to dump full nsid translation table Nicolas Dichtel
@ 2018-11-22 15:50 ` Nicolas Dichtel
2018-11-22 15:50 ` [PATCH net-next v2 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel
` (5 more replies)
4 siblings, 6 replies; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-22 15:50 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem
The goal of this series is to ease the interpretation of nsid received in
netlink messages from other netns (when the user uses
NETLINK_F_LISTEN_ALL_NSID).
After this series, with a patched iproute2:
$ ip netns add foo
$ ip netns add bar
$ touch /var/run/netns/init_net
$ mount --bind /proc/1/ns/net /var/run/netns/init_net
$ ip netns set init_net 11
$ ip netns set foo 12
$ ip netns set bar 13
$ ip netns
init_net (id: 11)
bar (id: 13)
foo (id: 12)
$ ip -n foo netns set init_net 21
$ ip -n foo netns set foo 22
$ ip -n foo netns set bar 23
$ ip -n foo netns
init_net (id: 21)
bar (id: 23)
foo (id: 22)
$ ip -n bar netns set init_net 31
$ ip -n bar netns set foo 32
$ ip -n bar netns set bar 33
$ ip -n bar netns
init_net (id: 31)
bar (id: 33)
foo (id: 32)
$ ip netns list-id target-nsid 12
nsid 21 current-nsid 11 (iproute2 netns name: init_net)
nsid 22 current-nsid 12 (iproute2 netns name: foo)
nsid 23 current-nsid 13 (iproute2 netns name: bar)
$ ip -n bar netns list-id target-nsid 32 nsid 31
nsid 21 current-nsid 31 (iproute2 netns name: init_net)
v1 -> v2:
- patch 1/5: remove net from struct rtnl_net_dump_cb
- patch 2/5: new in this version
- patch 3/5: use a bool to know if rtnl_get_net_ns_capable() was called
- patch 5/5: use struct net_fill_args
include/uapi/linux/net_namespace.h | 2 +
net/core/net_namespace.c | 157 +++++++++++++++++++++++++++++++------
2 files changed, 133 insertions(+), 26 deletions(-)
Comments are welcomed,
Regards,
Nicolas
^ permalink raw reply [flat|nested] 39+ messages in thread
* [PATCH net-next v2 1/5] netns: remove net arg from rtnl_net_fill()
2018-11-22 15:50 ` [PATCH net-next v2 0/5] Ease to interpret net-nsid Nicolas Dichtel
@ 2018-11-22 15:50 ` Nicolas Dichtel
2018-11-22 16:18 ` David Ahern
2018-11-22 15:50 ` [PATCH net-next v2 2/5] netns: introduce 'struct net_fill_args' Nicolas Dichtel
` (4 subsequent siblings)
5 siblings, 1 reply; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-22 15:50 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem, Nicolas Dichtel
This argument is not used anymore.
Fixes: cab3c8ec8d57 ("netns: always provide the id to rtnl_net_fill()")
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
net/core/net_namespace.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index fefe72774aeb..52b9620e3457 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -739,7 +739,7 @@ static int rtnl_net_get_size(void)
}
static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
- int cmd, struct net *net, int nsid)
+ int cmd, int nsid)
{
struct nlmsghdr *nlh;
struct rtgenmsg *rth;
@@ -801,7 +801,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
id = peernet2id(net, peer);
err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
- RTM_NEWNSID, net, id);
+ RTM_NEWNSID, id);
if (err < 0)
goto err_out;
@@ -816,7 +816,6 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
}
struct rtnl_net_dump_cb {
- struct net *net;
struct sk_buff *skb;
struct netlink_callback *cb;
int idx;
@@ -833,7 +832,7 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data)
ret = rtnl_net_fill(net_cb->skb, NETLINK_CB(net_cb->cb->skb).portid,
net_cb->cb->nlh->nlmsg_seq, NLM_F_MULTI,
- RTM_NEWNSID, net_cb->net, id);
+ RTM_NEWNSID, id);
if (ret < 0)
return ret;
@@ -846,7 +845,6 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
{
struct net *net = sock_net(skb->sk);
struct rtnl_net_dump_cb net_cb = {
- .net = net,
.skb = skb,
.cb = cb,
.idx = 0,
@@ -876,7 +874,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id)
if (!msg)
goto out;
- err = rtnl_net_fill(msg, 0, 0, 0, cmd, net, id);
+ err = rtnl_net_fill(msg, 0, 0, 0, cmd, id);
if (err < 0)
goto err_out;
--
2.18.0
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next v2 2/5] netns: introduce 'struct net_fill_args'
2018-11-22 15:50 ` [PATCH net-next v2 0/5] Ease to interpret net-nsid Nicolas Dichtel
2018-11-22 15:50 ` [PATCH net-next v2 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel
@ 2018-11-22 15:50 ` Nicolas Dichtel
2018-11-22 16:23 ` David Ahern
2018-11-22 15:50 ` [PATCH net-next v2 3/5] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel
` (3 subsequent siblings)
5 siblings, 1 reply; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-22 15:50 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem, Nicolas Dichtel
This is a preparatory work. To avoid having to much arguments for the
function rtnl_net_fill(), a new structure is defined.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
net/core/net_namespace.c | 48 ++++++++++++++++++++++++++++------------
1 file changed, 34 insertions(+), 14 deletions(-)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 52b9620e3457..f8a5966b086c 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -738,20 +738,28 @@ static int rtnl_net_get_size(void)
;
}
-static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
- int cmd, int nsid)
+struct net_fill_args {
+ u32 portid;
+ u32 seq;
+ int flags;
+ int cmd;
+ int nsid;
+};
+
+static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args)
{
struct nlmsghdr *nlh;
struct rtgenmsg *rth;
- nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rth), flags);
+ nlh = nlmsg_put(skb, args->portid, args->seq, args->cmd, sizeof(*rth),
+ args->flags);
if (!nlh)
return -EMSGSIZE;
rth = nlmsg_data(nlh);
rth->rtgen_family = AF_UNSPEC;
- if (nla_put_s32(skb, NETNSA_NSID, nsid))
+ if (nla_put_s32(skb, NETNSA_NSID, args->nsid))
goto nla_put_failure;
nlmsg_end(skb, nlh);
@@ -767,10 +775,15 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
{
struct net *net = sock_net(skb->sk);
struct nlattr *tb[NETNSA_MAX + 1];
+ struct net_fill_args fillargs = {
+ .portid = NETLINK_CB(skb).portid,
+ .seq = nlh->nlmsg_seq,
+ .cmd = RTM_NEWNSID,
+ };
struct nlattr *nla;
struct sk_buff *msg;
struct net *peer;
- int err, id;
+ int err;
err = nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX,
rtnl_net_policy, extack);
@@ -799,9 +812,8 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
goto out;
}
- id = peernet2id(net, peer);
- err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
- RTM_NEWNSID, id);
+ fillargs.nsid = peernet2id(net, peer);
+ err = rtnl_net_fill(msg, &fillargs);
if (err < 0)
goto err_out;
@@ -817,7 +829,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
struct rtnl_net_dump_cb {
struct sk_buff *skb;
- struct netlink_callback *cb;
+ struct net_fill_args fillargs;
int idx;
int s_idx;
};
@@ -830,9 +842,8 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data)
if (net_cb->idx < net_cb->s_idx)
goto cont;
- ret = rtnl_net_fill(net_cb->skb, NETLINK_CB(net_cb->cb->skb).portid,
- net_cb->cb->nlh->nlmsg_seq, NLM_F_MULTI,
- RTM_NEWNSID, id);
+ net_cb->fillargs.nsid = id;
+ ret = rtnl_net_fill(net_cb->skb, &net_cb->fillargs);
if (ret < 0)
return ret;
@@ -846,7 +857,12 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
struct net *net = sock_net(skb->sk);
struct rtnl_net_dump_cb net_cb = {
.skb = skb,
- .cb = cb,
+ .fillargs = {
+ .portid = NETLINK_CB(cb->skb).portid,
+ .seq = cb->nlh->nlmsg_seq,
+ .flags = NLM_F_MULTI,
+ .cmd = RTM_NEWNSID,
+ },
.idx = 0,
.s_idx = cb->args[0],
};
@@ -867,6 +883,10 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
static void rtnl_net_notifyid(struct net *net, int cmd, int id)
{
+ struct net_fill_args fillargs = {
+ .cmd = cmd,
+ .nsid = id,
+ };
struct sk_buff *msg;
int err = -ENOMEM;
@@ -874,7 +894,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id)
if (!msg)
goto out;
- err = rtnl_net_fill(msg, 0, 0, 0, cmd, id);
+ err = rtnl_net_fill(msg, &fillargs);
if (err < 0)
goto err_out;
--
2.18.0
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next v2 3/5] netns: add support of NETNSA_TARGET_NSID
2018-11-22 15:50 ` [PATCH net-next v2 0/5] Ease to interpret net-nsid Nicolas Dichtel
2018-11-22 15:50 ` [PATCH net-next v2 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel
2018-11-22 15:50 ` [PATCH net-next v2 2/5] netns: introduce 'struct net_fill_args' Nicolas Dichtel
@ 2018-11-22 15:50 ` Nicolas Dichtel
2018-11-22 16:32 ` David Ahern
2018-11-22 15:50 ` [PATCH net-next v2 4/5] netns: enable to specify a nsid for a get request Nicolas Dichtel
` (2 subsequent siblings)
5 siblings, 1 reply; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-22 15:50 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem, Nicolas Dichtel
Like it was done for link and address, add the ability to perform get/dump
in another netns by specifying a target nsid attribute.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
include/uapi/linux/net_namespace.h | 1 +
net/core/net_namespace.c | 86 ++++++++++++++++++++++++++----
2 files changed, 76 insertions(+), 11 deletions(-)
diff --git a/include/uapi/linux/net_namespace.h b/include/uapi/linux/net_namespace.h
index 0187c74d8889..0ed9dd61d32a 100644
--- a/include/uapi/linux/net_namespace.h
+++ b/include/uapi/linux/net_namespace.h
@@ -16,6 +16,7 @@ enum {
NETNSA_NSID,
NETNSA_PID,
NETNSA_FD,
+ NETNSA_TARGET_NSID,
__NETNSA_MAX,
};
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index f8a5966b086c..885c54197e31 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -669,6 +669,7 @@ static const struct nla_policy rtnl_net_policy[NETNSA_MAX + 1] = {
[NETNSA_NSID] = { .type = NLA_S32 },
[NETNSA_PID] = { .type = NLA_U32 },
[NETNSA_FD] = { .type = NLA_U32 },
+ [NETNSA_TARGET_NSID] = { .type = NLA_S32 },
};
static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -780,9 +781,10 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
.seq = nlh->nlmsg_seq,
.cmd = RTM_NEWNSID,
};
+ struct net *peer, *target = net;
+ bool put_target = false;
struct nlattr *nla;
struct sk_buff *msg;
- struct net *peer;
int err;
err = nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX,
@@ -806,13 +808,27 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
return PTR_ERR(peer);
}
+ if (tb[NETNSA_TARGET_NSID]) {
+ int id = nla_get_s32(tb[NETNSA_TARGET_NSID]);
+
+ target = rtnl_get_net_ns_capable(NETLINK_CB(skb).sk, id);
+ if (IS_ERR(target)) {
+ NL_SET_BAD_ATTR(extack, tb[NETNSA_TARGET_NSID]);
+ NL_SET_ERR_MSG(extack,
+ "Target netns reference is invalid");
+ err = PTR_ERR(target);
+ goto out;
+ }
+ put_target = true;
+ }
+
msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL);
if (!msg) {
err = -ENOMEM;
goto out;
}
- fillargs.nsid = peernet2id(net, peer);
+ fillargs.nsid = peernet2id(target, peer);
err = rtnl_net_fill(msg, &fillargs);
if (err < 0)
goto err_out;
@@ -823,15 +839,19 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
err_out:
nlmsg_free(msg);
out:
+ if (put_target)
+ put_net(target);
put_net(peer);
return err;
}
struct rtnl_net_dump_cb {
+ struct net *tgt_net;
struct sk_buff *skb;
struct net_fill_args fillargs;
int idx;
int s_idx;
+ bool put_tgt_net;
};
static int rtnl_net_dumpid_one(int id, void *peer, void *data)
@@ -852,10 +872,50 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data)
return 0;
}
+static int rtnl_valid_dump_net_req(const struct nlmsghdr *nlh, struct sock *sk,
+ struct rtnl_net_dump_cb *net_cb,
+ struct netlink_callback *cb)
+{
+ struct netlink_ext_ack *extack = cb->extack;
+ struct nlattr *tb[NETNSA_MAX + 1];
+ int err, i;
+
+ err = nlmsg_parse_strict(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX,
+ rtnl_net_policy, extack);
+ if (err < 0)
+ return err;
+
+ for (i = 0; i <= NETNSA_MAX; i++) {
+ if (!tb[i])
+ continue;
+
+ if (i == NETNSA_TARGET_NSID) {
+ struct net *net;
+
+ net = rtnl_get_net_ns_capable(sk, nla_get_s32(tb[i]));
+ if (IS_ERR(net)) {
+ NL_SET_BAD_ATTR(extack, tb[i]);
+ NL_SET_ERR_MSG(extack,
+ "Invalid target network namespace id");
+ return PTR_ERR(net);
+ }
+ net_cb->tgt_net = net;
+ net_cb->put_tgt_net = true;
+ } else {
+ NL_SET_BAD_ATTR(extack, tb[i]);
+ NL_SET_ERR_MSG(extack,
+ "Unsupported attribute in dump request");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
{
- struct net *net = sock_net(skb->sk);
struct rtnl_net_dump_cb net_cb = {
+ .tgt_net = sock_net(skb->sk),
.skb = skb,
.fillargs = {
.portid = NETLINK_CB(cb->skb).portid,
@@ -866,19 +926,23 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
.idx = 0,
.s_idx = cb->args[0],
};
+ int err = 0;
- if (cb->strict_check &&
- nlmsg_attrlen(cb->nlh, sizeof(struct rtgenmsg))) {
- NL_SET_ERR_MSG(cb->extack, "Unknown data in network namespace id dump request");
- return -EINVAL;
+ if (cb->strict_check) {
+ err = rtnl_valid_dump_net_req(cb->nlh, skb->sk, &net_cb, cb);
+ if (err < 0)
+ goto end;
}
- spin_lock_bh(&net->nsid_lock);
- idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb);
- spin_unlock_bh(&net->nsid_lock);
+ spin_lock_bh(&net_cb.tgt_net->nsid_lock);
+ idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb);
+ spin_unlock_bh(&net_cb.tgt_net->nsid_lock);
cb->args[0] = net_cb.idx;
- return skb->len;
+end:
+ if (net_cb.put_tgt_net)
+ put_net(net_cb.tgt_net);
+ return err < 0 ? err : skb->len;
}
static void rtnl_net_notifyid(struct net *net, int cmd, int id)
--
2.18.0
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next v2 4/5] netns: enable to specify a nsid for a get request
2018-11-22 15:50 ` [PATCH net-next v2 0/5] Ease to interpret net-nsid Nicolas Dichtel
` (2 preceding siblings ...)
2018-11-22 15:50 ` [PATCH net-next v2 3/5] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel
@ 2018-11-22 15:50 ` Nicolas Dichtel
2018-11-22 16:32 ` David Ahern
2018-11-22 15:50 ` [PATCH net-next v2 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel
2018-11-22 22:22 ` [PATCH net-next v3 0/5] Ease to interpret net-nsid Nicolas Dichtel
5 siblings, 1 reply; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-22 15:50 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem, Nicolas Dichtel
Combined with NETNSA_TARGET_NSID, it enables to "translate" a nsid from one
netns to a nsid of another netns.
This is useful when using NETLINK_F_LISTEN_ALL_NSID because it helps the
user to interpret a nsid received from an other netns.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
net/core/net_namespace.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 885c54197e31..dd25fb22ad45 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -797,6 +797,11 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
} else if (tb[NETNSA_FD]) {
peer = get_net_ns_by_fd(nla_get_u32(tb[NETNSA_FD]));
nla = tb[NETNSA_FD];
+ } else if (tb[NETNSA_NSID]) {
+ peer = get_net_ns_by_id(net, nla_get_u32(tb[NETNSA_NSID]));
+ if (!peer)
+ peer = ERR_PTR(-ENOENT);
+ nla = tb[NETNSA_NSID];
} else {
NL_SET_ERR_MSG(extack, "Peer netns reference is missing");
return -EINVAL;
--
2.18.0
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next v2 5/5] netns: enable to dump full nsid translation table
2018-11-22 15:50 ` [PATCH net-next v2 0/5] Ease to interpret net-nsid Nicolas Dichtel
` (3 preceding siblings ...)
2018-11-22 15:50 ` [PATCH net-next v2 4/5] netns: enable to specify a nsid for a get request Nicolas Dichtel
@ 2018-11-22 15:50 ` Nicolas Dichtel
2018-11-22 16:40 ` David Ahern
2018-11-22 22:22 ` [PATCH net-next v3 0/5] Ease to interpret net-nsid Nicolas Dichtel
5 siblings, 1 reply; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-22 15:50 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem, Nicolas Dichtel
Like the previous patch, the goal is to ease to convert nsids from one
netns to another netns.
A new attribute (NETNSA_CURRENT_NSID) is added to the kernel answer when
NETNSA_TARGET_NSID is provided, thus the user can easily convert nsids.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
include/uapi/linux/net_namespace.h | 1 +
net/core/net_namespace.c | 30 ++++++++++++++++++++++++------
2 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/include/uapi/linux/net_namespace.h b/include/uapi/linux/net_namespace.h
index 0ed9dd61d32a..9f9956809565 100644
--- a/include/uapi/linux/net_namespace.h
+++ b/include/uapi/linux/net_namespace.h
@@ -17,6 +17,7 @@ enum {
NETNSA_PID,
NETNSA_FD,
NETNSA_TARGET_NSID,
+ NETNSA_CURRENT_NSID,
__NETNSA_MAX,
};
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index dd25fb22ad45..25030e0317a2 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -745,6 +745,8 @@ struct net_fill_args {
int flags;
int cmd;
int nsid;
+ bool add_ref;
+ int ref_nsid;
};
static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args)
@@ -763,6 +765,10 @@ static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args)
if (nla_put_s32(skb, NETNSA_NSID, args->nsid))
goto nla_put_failure;
+ if (args->add_ref &&
+ nla_put_s32(skb, NETNSA_CURRENT_NSID, args->ref_nsid))
+ goto nla_put_failure;
+
nlmsg_end(skb, nlh);
return 0;
@@ -782,7 +788,6 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
.cmd = RTM_NEWNSID,
};
struct net *peer, *target = net;
- bool put_target = false;
struct nlattr *nla;
struct sk_buff *msg;
int err;
@@ -824,7 +829,8 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
err = PTR_ERR(target);
goto out;
}
- put_target = true;
+ fillargs.add_ref = true;
+ fillargs.ref_nsid = peernet2id(net, peer);
}
msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL);
@@ -844,7 +850,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
err_out:
nlmsg_free(msg);
out:
- if (put_target)
+ if (fillargs.add_ref)
put_net(target);
put_net(peer);
return err;
@@ -852,11 +858,11 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
struct rtnl_net_dump_cb {
struct net *tgt_net;
+ struct net *ref_net;
struct sk_buff *skb;
struct net_fill_args fillargs;
int idx;
int s_idx;
- bool put_tgt_net;
};
static int rtnl_net_dumpid_one(int id, void *peer, void *data)
@@ -868,6 +874,8 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data)
goto cont;
net_cb->fillargs.nsid = id;
+ if (net_cb->fillargs.add_ref)
+ net_cb->fillargs.ref_nsid = __peernet2id(net_cb->ref_net, peer);
ret = rtnl_net_fill(net_cb->skb, &net_cb->fillargs);
if (ret < 0)
return ret;
@@ -904,8 +912,9 @@ static int rtnl_valid_dump_net_req(const struct nlmsghdr *nlh, struct sock *sk,
"Invalid target network namespace id");
return PTR_ERR(net);
}
+ net_cb->fillargs.add_ref = true;
+ net_cb->ref_net = net_cb->tgt_net;
net_cb->tgt_net = net;
- net_cb->put_tgt_net = true;
} else {
NL_SET_BAD_ATTR(extack, tb[i]);
NL_SET_ERR_MSG(extack,
@@ -940,12 +949,21 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
}
spin_lock_bh(&net_cb.tgt_net->nsid_lock);
+ if (net_cb.fillargs.add_ref &&
+ !net_eq(net_cb.ref_net, net_cb.tgt_net) &&
+ !spin_trylock_bh(&net_cb.ref_net->nsid_lock)) {
+ err = -EAGAIN;
+ goto end;
+ }
idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb);
+ if (net_cb.fillargs.add_ref &&
+ !net_eq(net_cb.ref_net, net_cb.tgt_net))
+ spin_unlock_bh(&net_cb.ref_net->nsid_lock);
spin_unlock_bh(&net_cb.tgt_net->nsid_lock);
cb->args[0] = net_cb.idx;
end:
- if (net_cb.put_tgt_net)
+ if (net_cb.fillargs.add_ref)
put_net(net_cb.tgt_net);
return err < 0 ? err : skb->len;
}
--
2.18.0
^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [PATCH net-next v2 1/5] netns: remove net arg from rtnl_net_fill()
2018-11-22 15:50 ` [PATCH net-next v2 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel
@ 2018-11-22 16:18 ` David Ahern
0 siblings, 0 replies; 39+ messages in thread
From: David Ahern @ 2018-11-22 16:18 UTC (permalink / raw)
To: Nicolas Dichtel; +Cc: netdev, davem
On 11/22/18 8:50 AM, Nicolas Dichtel wrote:
> This argument is not used anymore.
>
> Fixes: cab3c8ec8d57 ("netns: always provide the id to rtnl_net_fill()")
> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> ---
> net/core/net_namespace.c | 10 ++++------
> 1 file changed, 4 insertions(+), 6 deletions(-)
>
Reviewed-by: David Ahern <dsahern@gmail.com>
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH net-next v2 2/5] netns: introduce 'struct net_fill_args'
2018-11-22 15:50 ` [PATCH net-next v2 2/5] netns: introduce 'struct net_fill_args' Nicolas Dichtel
@ 2018-11-22 16:23 ` David Ahern
0 siblings, 0 replies; 39+ messages in thread
From: David Ahern @ 2018-11-22 16:23 UTC (permalink / raw)
To: Nicolas Dichtel; +Cc: netdev, davem
On 11/22/18 8:50 AM, Nicolas Dichtel wrote:
> This is a preparatory work. To avoid having to much arguments for the
> function rtnl_net_fill(), a new structure is defined.
>
> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> ---
> net/core/net_namespace.c | 48 ++++++++++++++++++++++++++++------------
> 1 file changed, 34 insertions(+), 14 deletions(-)
>
Reviewed-by: David Ahern <dsahern@gmail.com>
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH net-next v2 3/5] netns: add support of NETNSA_TARGET_NSID
2018-11-22 15:50 ` [PATCH net-next v2 3/5] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel
@ 2018-11-22 16:32 ` David Ahern
0 siblings, 0 replies; 39+ messages in thread
From: David Ahern @ 2018-11-22 16:32 UTC (permalink / raw)
To: Nicolas Dichtel; +Cc: netdev, davem
On 11/22/18 8:50 AM, Nicolas Dichtel wrote:
> Like it was done for link and address, add the ability to perform get/dump
> in another netns by specifying a target nsid attribute.
>
> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> ---
> include/uapi/linux/net_namespace.h | 1 +
> net/core/net_namespace.c | 86 ++++++++++++++++++++++++++----
> 2 files changed, 76 insertions(+), 11 deletions(-)
Reviewed-by: David Ahern <dsahern@gmail.com>
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH net-next v2 4/5] netns: enable to specify a nsid for a get request
2018-11-22 15:50 ` [PATCH net-next v2 4/5] netns: enable to specify a nsid for a get request Nicolas Dichtel
@ 2018-11-22 16:32 ` David Ahern
0 siblings, 0 replies; 39+ messages in thread
From: David Ahern @ 2018-11-22 16:32 UTC (permalink / raw)
To: Nicolas Dichtel; +Cc: netdev, davem
On 11/22/18 8:50 AM, Nicolas Dichtel wrote:
> Combined with NETNSA_TARGET_NSID, it enables to "translate" a nsid from one
> netns to a nsid of another netns.
> This is useful when using NETLINK_F_LISTEN_ALL_NSID because it helps the
> user to interpret a nsid received from an other netns.
>
> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> ---
> net/core/net_namespace.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
Reviewed-by: David Ahern <dsahern@gmail.com>
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH net-next v2 5/5] netns: enable to dump full nsid translation table
2018-11-22 15:50 ` [PATCH net-next v2 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel
@ 2018-11-22 16:40 ` David Ahern
2018-11-22 16:42 ` Nicolas Dichtel
0 siblings, 1 reply; 39+ messages in thread
From: David Ahern @ 2018-11-22 16:40 UTC (permalink / raw)
To: Nicolas Dichtel; +Cc: netdev, davem
On 11/22/18 8:50 AM, Nicolas Dichtel wrote:
> diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
> index dd25fb22ad45..25030e0317a2 100644
> --- a/net/core/net_namespace.c
> +++ b/net/core/net_namespace.c
> @@ -745,6 +745,8 @@ struct net_fill_args {
> int flags;
> int cmd;
> int nsid;
> + bool add_ref;
> + int ref_nsid;
> };
>
> static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args)
> @@ -763,6 +765,10 @@ static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args)
> if (nla_put_s32(skb, NETNSA_NSID, args->nsid))
> goto nla_put_failure;
>
> + if (args->add_ref &&
> + nla_put_s32(skb, NETNSA_CURRENT_NSID, args->ref_nsid))
> + goto nla_put_failure;
> +
you need to add NETNSA_CURRENT_NSID to rtnl_net_get_size.
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH net-next v2 5/5] netns: enable to dump full nsid translation table
2018-11-22 16:40 ` David Ahern
@ 2018-11-22 16:42 ` Nicolas Dichtel
0 siblings, 0 replies; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-22 16:42 UTC (permalink / raw)
To: David Ahern; +Cc: netdev, davem
Le 22/11/2018 à 17:40, David Ahern a écrit :
> On 11/22/18 8:50 AM, Nicolas Dichtel wrote:
>> diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
>> index dd25fb22ad45..25030e0317a2 100644
>> --- a/net/core/net_namespace.c
>> +++ b/net/core/net_namespace.c
>> @@ -745,6 +745,8 @@ struct net_fill_args {
>> int flags;
>> int cmd;
>> int nsid;
>> + bool add_ref;
>> + int ref_nsid;
>> };
>>
>> static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args)
>> @@ -763,6 +765,10 @@ static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args)
>> if (nla_put_s32(skb, NETNSA_NSID, args->nsid))
>> goto nla_put_failure;
>>
>> + if (args->add_ref &&
>> + nla_put_s32(skb, NETNSA_CURRENT_NSID, args->ref_nsid))
>> + goto nla_put_failure;
>> +
>
> you need to add NETNSA_CURRENT_NSID to rtnl_net_get_size.
>
Good catch.
I thought to this and I forgot at the end :/
^ permalink raw reply [flat|nested] 39+ messages in thread
* [PATCH net-next v3 0/5] Ease to interpret net-nsid
2018-11-22 15:50 ` [PATCH net-next v2 0/5] Ease to interpret net-nsid Nicolas Dichtel
` (4 preceding siblings ...)
2018-11-22 15:50 ` [PATCH net-next v2 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel
@ 2018-11-22 22:22 ` Nicolas Dichtel
2018-11-22 22:22 ` [PATCH net-next v3 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel
` (5 more replies)
5 siblings, 6 replies; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-22 22:22 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem
The goal of this series is to ease the interpretation of nsid received in
netlink messages from other netns (when the user uses
NETLINK_F_LISTEN_ALL_NSID).
After this series, with a patched iproute2:
$ ip netns add foo
$ ip netns add bar
$ touch /var/run/netns/init_net
$ mount --bind /proc/1/ns/net /var/run/netns/init_net
$ ip netns set init_net 11
$ ip netns set foo 12
$ ip netns set bar 13
$ ip netns
init_net (id: 11)
bar (id: 13)
foo (id: 12)
$ ip -n foo netns set init_net 21
$ ip -n foo netns set foo 22
$ ip -n foo netns set bar 23
$ ip -n foo netns
init_net (id: 21)
bar (id: 23)
foo (id: 22)
$ ip -n bar netns set init_net 31
$ ip -n bar netns set foo 32
$ ip -n bar netns set bar 33
$ ip -n bar netns
init_net (id: 31)
bar (id: 33)
foo (id: 32)
$ ip netns list-id target-nsid 12
nsid 21 current-nsid 11 (iproute2 netns name: init_net)
nsid 22 current-nsid 12 (iproute2 netns name: foo)
nsid 23 current-nsid 13 (iproute2 netns name: bar)
$ ip -n bar netns list-id target-nsid 32 nsid 31
nsid 21 current-nsid 31 (iproute2 netns name: init_net)
v2 -> v3:
- patch 5/5: account NETNSA_CURRENT_NSID in rtnl_net_get_size()
v1 -> v2:
- patch 1/5: remove net from struct rtnl_net_dump_cb
- patch 2/5: new in this version
- patch 3/5: use a bool to know if rtnl_get_net_ns_capable() was called
- patch 5/5: use struct net_fill_args
include/uapi/linux/net_namespace.h | 2 +
net/core/net_namespace.c | 158 +++++++++++++++++++++++++++++++------
2 files changed, 134 insertions(+), 26 deletions(-)
Comments are welcomed,
Regards,
Nicolas
^ permalink raw reply [flat|nested] 39+ messages in thread
* [PATCH net-next v3 1/5] netns: remove net arg from rtnl_net_fill()
2018-11-22 22:22 ` [PATCH net-next v3 0/5] Ease to interpret net-nsid Nicolas Dichtel
@ 2018-11-22 22:22 ` Nicolas Dichtel
2018-11-22 22:22 ` [PATCH net-next v3 2/5] netns: introduce 'struct net_fill_args' Nicolas Dichtel
` (4 subsequent siblings)
5 siblings, 0 replies; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-22 22:22 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem, Nicolas Dichtel
This argument is not used anymore.
Fixes: cab3c8ec8d57 ("netns: always provide the id to rtnl_net_fill()")
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Reviewed-by: David Ahern <dsahern@gmail.com>
---
net/core/net_namespace.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index fefe72774aeb..52b9620e3457 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -739,7 +739,7 @@ static int rtnl_net_get_size(void)
}
static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
- int cmd, struct net *net, int nsid)
+ int cmd, int nsid)
{
struct nlmsghdr *nlh;
struct rtgenmsg *rth;
@@ -801,7 +801,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
id = peernet2id(net, peer);
err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
- RTM_NEWNSID, net, id);
+ RTM_NEWNSID, id);
if (err < 0)
goto err_out;
@@ -816,7 +816,6 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
}
struct rtnl_net_dump_cb {
- struct net *net;
struct sk_buff *skb;
struct netlink_callback *cb;
int idx;
@@ -833,7 +832,7 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data)
ret = rtnl_net_fill(net_cb->skb, NETLINK_CB(net_cb->cb->skb).portid,
net_cb->cb->nlh->nlmsg_seq, NLM_F_MULTI,
- RTM_NEWNSID, net_cb->net, id);
+ RTM_NEWNSID, id);
if (ret < 0)
return ret;
@@ -846,7 +845,6 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
{
struct net *net = sock_net(skb->sk);
struct rtnl_net_dump_cb net_cb = {
- .net = net,
.skb = skb,
.cb = cb,
.idx = 0,
@@ -876,7 +874,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id)
if (!msg)
goto out;
- err = rtnl_net_fill(msg, 0, 0, 0, cmd, net, id);
+ err = rtnl_net_fill(msg, 0, 0, 0, cmd, id);
if (err < 0)
goto err_out;
--
2.18.0
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next v3 2/5] netns: introduce 'struct net_fill_args'
2018-11-22 22:22 ` [PATCH net-next v3 0/5] Ease to interpret net-nsid Nicolas Dichtel
2018-11-22 22:22 ` [PATCH net-next v3 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel
@ 2018-11-22 22:22 ` Nicolas Dichtel
2018-11-22 22:22 ` [PATCH net-next v3 3/5] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel
` (3 subsequent siblings)
5 siblings, 0 replies; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-22 22:22 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem, Nicolas Dichtel
This is a preparatory work. To avoid having to much arguments for the
function rtnl_net_fill(), a new structure is defined.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Reviewed-by: David Ahern <dsahern@gmail.com>
---
net/core/net_namespace.c | 48 ++++++++++++++++++++++++++++------------
1 file changed, 34 insertions(+), 14 deletions(-)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 52b9620e3457..f8a5966b086c 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -738,20 +738,28 @@ static int rtnl_net_get_size(void)
;
}
-static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
- int cmd, int nsid)
+struct net_fill_args {
+ u32 portid;
+ u32 seq;
+ int flags;
+ int cmd;
+ int nsid;
+};
+
+static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args)
{
struct nlmsghdr *nlh;
struct rtgenmsg *rth;
- nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rth), flags);
+ nlh = nlmsg_put(skb, args->portid, args->seq, args->cmd, sizeof(*rth),
+ args->flags);
if (!nlh)
return -EMSGSIZE;
rth = nlmsg_data(nlh);
rth->rtgen_family = AF_UNSPEC;
- if (nla_put_s32(skb, NETNSA_NSID, nsid))
+ if (nla_put_s32(skb, NETNSA_NSID, args->nsid))
goto nla_put_failure;
nlmsg_end(skb, nlh);
@@ -767,10 +775,15 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
{
struct net *net = sock_net(skb->sk);
struct nlattr *tb[NETNSA_MAX + 1];
+ struct net_fill_args fillargs = {
+ .portid = NETLINK_CB(skb).portid,
+ .seq = nlh->nlmsg_seq,
+ .cmd = RTM_NEWNSID,
+ };
struct nlattr *nla;
struct sk_buff *msg;
struct net *peer;
- int err, id;
+ int err;
err = nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX,
rtnl_net_policy, extack);
@@ -799,9 +812,8 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
goto out;
}
- id = peernet2id(net, peer);
- err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
- RTM_NEWNSID, id);
+ fillargs.nsid = peernet2id(net, peer);
+ err = rtnl_net_fill(msg, &fillargs);
if (err < 0)
goto err_out;
@@ -817,7 +829,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
struct rtnl_net_dump_cb {
struct sk_buff *skb;
- struct netlink_callback *cb;
+ struct net_fill_args fillargs;
int idx;
int s_idx;
};
@@ -830,9 +842,8 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data)
if (net_cb->idx < net_cb->s_idx)
goto cont;
- ret = rtnl_net_fill(net_cb->skb, NETLINK_CB(net_cb->cb->skb).portid,
- net_cb->cb->nlh->nlmsg_seq, NLM_F_MULTI,
- RTM_NEWNSID, id);
+ net_cb->fillargs.nsid = id;
+ ret = rtnl_net_fill(net_cb->skb, &net_cb->fillargs);
if (ret < 0)
return ret;
@@ -846,7 +857,12 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
struct net *net = sock_net(skb->sk);
struct rtnl_net_dump_cb net_cb = {
.skb = skb,
- .cb = cb,
+ .fillargs = {
+ .portid = NETLINK_CB(cb->skb).portid,
+ .seq = cb->nlh->nlmsg_seq,
+ .flags = NLM_F_MULTI,
+ .cmd = RTM_NEWNSID,
+ },
.idx = 0,
.s_idx = cb->args[0],
};
@@ -867,6 +883,10 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
static void rtnl_net_notifyid(struct net *net, int cmd, int id)
{
+ struct net_fill_args fillargs = {
+ .cmd = cmd,
+ .nsid = id,
+ };
struct sk_buff *msg;
int err = -ENOMEM;
@@ -874,7 +894,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id)
if (!msg)
goto out;
- err = rtnl_net_fill(msg, 0, 0, 0, cmd, id);
+ err = rtnl_net_fill(msg, &fillargs);
if (err < 0)
goto err_out;
--
2.18.0
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next v3 3/5] netns: add support of NETNSA_TARGET_NSID
2018-11-22 22:22 ` [PATCH net-next v3 0/5] Ease to interpret net-nsid Nicolas Dichtel
2018-11-22 22:22 ` [PATCH net-next v3 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel
2018-11-22 22:22 ` [PATCH net-next v3 2/5] netns: introduce 'struct net_fill_args' Nicolas Dichtel
@ 2018-11-22 22:22 ` Nicolas Dichtel
2018-11-22 22:22 ` [PATCH net-next v3 4/5] netns: enable to specify a nsid for a get request Nicolas Dichtel
` (2 subsequent siblings)
5 siblings, 0 replies; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-22 22:22 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem, Nicolas Dichtel
Like it was done for link and address, add the ability to perform get/dump
in another netns by specifying a target nsid attribute.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Reviewed-by: David Ahern <dsahern@gmail.com>
---
include/uapi/linux/net_namespace.h | 1 +
net/core/net_namespace.c | 86 ++++++++++++++++++++++++++----
2 files changed, 76 insertions(+), 11 deletions(-)
diff --git a/include/uapi/linux/net_namespace.h b/include/uapi/linux/net_namespace.h
index 0187c74d8889..0ed9dd61d32a 100644
--- a/include/uapi/linux/net_namespace.h
+++ b/include/uapi/linux/net_namespace.h
@@ -16,6 +16,7 @@ enum {
NETNSA_NSID,
NETNSA_PID,
NETNSA_FD,
+ NETNSA_TARGET_NSID,
__NETNSA_MAX,
};
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index f8a5966b086c..885c54197e31 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -669,6 +669,7 @@ static const struct nla_policy rtnl_net_policy[NETNSA_MAX + 1] = {
[NETNSA_NSID] = { .type = NLA_S32 },
[NETNSA_PID] = { .type = NLA_U32 },
[NETNSA_FD] = { .type = NLA_U32 },
+ [NETNSA_TARGET_NSID] = { .type = NLA_S32 },
};
static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -780,9 +781,10 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
.seq = nlh->nlmsg_seq,
.cmd = RTM_NEWNSID,
};
+ struct net *peer, *target = net;
+ bool put_target = false;
struct nlattr *nla;
struct sk_buff *msg;
- struct net *peer;
int err;
err = nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX,
@@ -806,13 +808,27 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
return PTR_ERR(peer);
}
+ if (tb[NETNSA_TARGET_NSID]) {
+ int id = nla_get_s32(tb[NETNSA_TARGET_NSID]);
+
+ target = rtnl_get_net_ns_capable(NETLINK_CB(skb).sk, id);
+ if (IS_ERR(target)) {
+ NL_SET_BAD_ATTR(extack, tb[NETNSA_TARGET_NSID]);
+ NL_SET_ERR_MSG(extack,
+ "Target netns reference is invalid");
+ err = PTR_ERR(target);
+ goto out;
+ }
+ put_target = true;
+ }
+
msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL);
if (!msg) {
err = -ENOMEM;
goto out;
}
- fillargs.nsid = peernet2id(net, peer);
+ fillargs.nsid = peernet2id(target, peer);
err = rtnl_net_fill(msg, &fillargs);
if (err < 0)
goto err_out;
@@ -823,15 +839,19 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
err_out:
nlmsg_free(msg);
out:
+ if (put_target)
+ put_net(target);
put_net(peer);
return err;
}
struct rtnl_net_dump_cb {
+ struct net *tgt_net;
struct sk_buff *skb;
struct net_fill_args fillargs;
int idx;
int s_idx;
+ bool put_tgt_net;
};
static int rtnl_net_dumpid_one(int id, void *peer, void *data)
@@ -852,10 +872,50 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data)
return 0;
}
+static int rtnl_valid_dump_net_req(const struct nlmsghdr *nlh, struct sock *sk,
+ struct rtnl_net_dump_cb *net_cb,
+ struct netlink_callback *cb)
+{
+ struct netlink_ext_ack *extack = cb->extack;
+ struct nlattr *tb[NETNSA_MAX + 1];
+ int err, i;
+
+ err = nlmsg_parse_strict(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX,
+ rtnl_net_policy, extack);
+ if (err < 0)
+ return err;
+
+ for (i = 0; i <= NETNSA_MAX; i++) {
+ if (!tb[i])
+ continue;
+
+ if (i == NETNSA_TARGET_NSID) {
+ struct net *net;
+
+ net = rtnl_get_net_ns_capable(sk, nla_get_s32(tb[i]));
+ if (IS_ERR(net)) {
+ NL_SET_BAD_ATTR(extack, tb[i]);
+ NL_SET_ERR_MSG(extack,
+ "Invalid target network namespace id");
+ return PTR_ERR(net);
+ }
+ net_cb->tgt_net = net;
+ net_cb->put_tgt_net = true;
+ } else {
+ NL_SET_BAD_ATTR(extack, tb[i]);
+ NL_SET_ERR_MSG(extack,
+ "Unsupported attribute in dump request");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
{
- struct net *net = sock_net(skb->sk);
struct rtnl_net_dump_cb net_cb = {
+ .tgt_net = sock_net(skb->sk),
.skb = skb,
.fillargs = {
.portid = NETLINK_CB(cb->skb).portid,
@@ -866,19 +926,23 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
.idx = 0,
.s_idx = cb->args[0],
};
+ int err = 0;
- if (cb->strict_check &&
- nlmsg_attrlen(cb->nlh, sizeof(struct rtgenmsg))) {
- NL_SET_ERR_MSG(cb->extack, "Unknown data in network namespace id dump request");
- return -EINVAL;
+ if (cb->strict_check) {
+ err = rtnl_valid_dump_net_req(cb->nlh, skb->sk, &net_cb, cb);
+ if (err < 0)
+ goto end;
}
- spin_lock_bh(&net->nsid_lock);
- idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb);
- spin_unlock_bh(&net->nsid_lock);
+ spin_lock_bh(&net_cb.tgt_net->nsid_lock);
+ idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb);
+ spin_unlock_bh(&net_cb.tgt_net->nsid_lock);
cb->args[0] = net_cb.idx;
- return skb->len;
+end:
+ if (net_cb.put_tgt_net)
+ put_net(net_cb.tgt_net);
+ return err < 0 ? err : skb->len;
}
static void rtnl_net_notifyid(struct net *net, int cmd, int id)
--
2.18.0
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next v3 4/5] netns: enable to specify a nsid for a get request
2018-11-22 22:22 ` [PATCH net-next v3 0/5] Ease to interpret net-nsid Nicolas Dichtel
` (2 preceding siblings ...)
2018-11-22 22:22 ` [PATCH net-next v3 3/5] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel
@ 2018-11-22 22:22 ` Nicolas Dichtel
2018-11-22 22:22 ` [PATCH net-next v3 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel
2018-11-26 14:42 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid Nicolas Dichtel
5 siblings, 0 replies; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-22 22:22 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem, Nicolas Dichtel
Combined with NETNSA_TARGET_NSID, it enables to "translate" a nsid from one
netns to a nsid of another netns.
This is useful when using NETLINK_F_LISTEN_ALL_NSID because it helps the
user to interpret a nsid received from an other netns.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Reviewed-by: David Ahern <dsahern@gmail.com>
---
net/core/net_namespace.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 885c54197e31..dd25fb22ad45 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -797,6 +797,11 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
} else if (tb[NETNSA_FD]) {
peer = get_net_ns_by_fd(nla_get_u32(tb[NETNSA_FD]));
nla = tb[NETNSA_FD];
+ } else if (tb[NETNSA_NSID]) {
+ peer = get_net_ns_by_id(net, nla_get_u32(tb[NETNSA_NSID]));
+ if (!peer)
+ peer = ERR_PTR(-ENOENT);
+ nla = tb[NETNSA_NSID];
} else {
NL_SET_ERR_MSG(extack, "Peer netns reference is missing");
return -EINVAL;
--
2.18.0
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next v3 5/5] netns: enable to dump full nsid translation table
2018-11-22 22:22 ` [PATCH net-next v3 0/5] Ease to interpret net-nsid Nicolas Dichtel
` (3 preceding siblings ...)
2018-11-22 22:22 ` [PATCH net-next v3 4/5] netns: enable to specify a nsid for a get request Nicolas Dichtel
@ 2018-11-22 22:22 ` Nicolas Dichtel
2018-11-24 15:47 ` David Ahern
2018-11-26 10:06 ` kbuild test robot
2018-11-26 14:42 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid Nicolas Dichtel
5 siblings, 2 replies; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-22 22:22 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem, Nicolas Dichtel
Like the previous patch, the goal is to ease to convert nsids from one
netns to another netns.
A new attribute (NETNSA_CURRENT_NSID) is added to the kernel answer when
NETNSA_TARGET_NSID is provided, thus the user can easily convert nsids.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
include/uapi/linux/net_namespace.h | 1 +
net/core/net_namespace.c | 31 ++++++++++++++++++++++++------
2 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/include/uapi/linux/net_namespace.h b/include/uapi/linux/net_namespace.h
index 0ed9dd61d32a..9f9956809565 100644
--- a/include/uapi/linux/net_namespace.h
+++ b/include/uapi/linux/net_namespace.h
@@ -17,6 +17,7 @@ enum {
NETNSA_PID,
NETNSA_FD,
NETNSA_TARGET_NSID,
+ NETNSA_CURRENT_NSID,
__NETNSA_MAX,
};
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index dd25fb22ad45..2f25d7f2a43b 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -736,6 +736,7 @@ static int rtnl_net_get_size(void)
{
return NLMSG_ALIGN(sizeof(struct rtgenmsg))
+ nla_total_size(sizeof(s32)) /* NETNSA_NSID */
+ + nla_total_size(sizeof(s32)) /* NETNSA_CURRENT_NSID */
;
}
@@ -745,6 +746,8 @@ struct net_fill_args {
int flags;
int cmd;
int nsid;
+ bool add_ref;
+ int ref_nsid;
};
static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args)
@@ -763,6 +766,10 @@ static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args)
if (nla_put_s32(skb, NETNSA_NSID, args->nsid))
goto nla_put_failure;
+ if (args->add_ref &&
+ nla_put_s32(skb, NETNSA_CURRENT_NSID, args->ref_nsid))
+ goto nla_put_failure;
+
nlmsg_end(skb, nlh);
return 0;
@@ -782,7 +789,6 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
.cmd = RTM_NEWNSID,
};
struct net *peer, *target = net;
- bool put_target = false;
struct nlattr *nla;
struct sk_buff *msg;
int err;
@@ -824,7 +830,8 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
err = PTR_ERR(target);
goto out;
}
- put_target = true;
+ fillargs.add_ref = true;
+ fillargs.ref_nsid = peernet2id(net, peer);
}
msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL);
@@ -844,7 +851,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
err_out:
nlmsg_free(msg);
out:
- if (put_target)
+ if (fillargs.add_ref)
put_net(target);
put_net(peer);
return err;
@@ -852,11 +859,11 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
struct rtnl_net_dump_cb {
struct net *tgt_net;
+ struct net *ref_net;
struct sk_buff *skb;
struct net_fill_args fillargs;
int idx;
int s_idx;
- bool put_tgt_net;
};
static int rtnl_net_dumpid_one(int id, void *peer, void *data)
@@ -868,6 +875,8 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data)
goto cont;
net_cb->fillargs.nsid = id;
+ if (net_cb->fillargs.add_ref)
+ net_cb->fillargs.ref_nsid = __peernet2id(net_cb->ref_net, peer);
ret = rtnl_net_fill(net_cb->skb, &net_cb->fillargs);
if (ret < 0)
return ret;
@@ -904,8 +913,9 @@ static int rtnl_valid_dump_net_req(const struct nlmsghdr *nlh, struct sock *sk,
"Invalid target network namespace id");
return PTR_ERR(net);
}
+ net_cb->fillargs.add_ref = true;
+ net_cb->ref_net = net_cb->tgt_net;
net_cb->tgt_net = net;
- net_cb->put_tgt_net = true;
} else {
NL_SET_BAD_ATTR(extack, tb[i]);
NL_SET_ERR_MSG(extack,
@@ -940,12 +950,21 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
}
spin_lock_bh(&net_cb.tgt_net->nsid_lock);
+ if (net_cb.fillargs.add_ref &&
+ !net_eq(net_cb.ref_net, net_cb.tgt_net) &&
+ !spin_trylock_bh(&net_cb.ref_net->nsid_lock)) {
+ err = -EAGAIN;
+ goto end;
+ }
idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb);
+ if (net_cb.fillargs.add_ref &&
+ !net_eq(net_cb.ref_net, net_cb.tgt_net))
+ spin_unlock_bh(&net_cb.ref_net->nsid_lock);
spin_unlock_bh(&net_cb.tgt_net->nsid_lock);
cb->args[0] = net_cb.idx;
end:
- if (net_cb.put_tgt_net)
+ if (net_cb.fillargs.add_ref)
put_net(net_cb.tgt_net);
return err < 0 ? err : skb->len;
}
--
2.18.0
^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [PATCH net-next v3 5/5] netns: enable to dump full nsid translation table
2018-11-22 22:22 ` [PATCH net-next v3 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel
@ 2018-11-24 15:47 ` David Ahern
2018-11-26 10:06 ` kbuild test robot
1 sibling, 0 replies; 39+ messages in thread
From: David Ahern @ 2018-11-24 15:47 UTC (permalink / raw)
To: Nicolas Dichtel; +Cc: netdev, davem
On 11/22/18 3:22 PM, Nicolas Dichtel wrote:
> Like the previous patch, the goal is to ease to convert nsids from one
> netns to another netns.
> A new attribute (NETNSA_CURRENT_NSID) is added to the kernel answer when
> NETNSA_TARGET_NSID is provided, thus the user can easily convert nsids.
>
> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> ---
> include/uapi/linux/net_namespace.h | 1 +
> net/core/net_namespace.c | 31 ++++++++++++++++++++++++------
> 2 files changed, 26 insertions(+), 6 deletions(-)
>
Reviewed-by: David Ahern <dsahern@gmail.com>
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH net-next v3 5/5] netns: enable to dump full nsid translation table
2018-11-22 22:22 ` [PATCH net-next v3 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel
2018-11-24 15:47 ` David Ahern
@ 2018-11-26 10:06 ` kbuild test robot
1 sibling, 0 replies; 39+ messages in thread
From: kbuild test robot @ 2018-11-26 10:06 UTC (permalink / raw)
To: Nicolas Dichtel; +Cc: kbuild-all, dsahern, netdev, davem, Nicolas Dichtel
[-- Attachment #1: Type: text/plain, Size: 4062 bytes --]
Hi Nicolas,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on net-next/master]
url: https://github.com/0day-ci/linux/commits/Nicolas-Dichtel/netns-remove-net-arg-from-rtnl_net_fill/20181126-035032
config: x86_64-allmodconfig (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All warnings (new ones prefixed by >>):
include/linux/slab.h:332:43: warning: dubious: x & !y
include/linux/slab.h:332:43: warning: dubious: x & !y
>> net/core/net_namespace.c:963:23: warning: context imbalance in 'rtnl_net_dumpid' - different lock contexts for basic block
vim +/rtnl_net_dumpid +963 net/core/net_namespace.c
5589651eb Nicolas Dichtel 2018-11-22 929
a143c40c3 Nicolas Dichtel 2015-04-07 930 static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
a143c40c3 Nicolas Dichtel 2015-04-07 931 {
a143c40c3 Nicolas Dichtel 2015-04-07 932 struct rtnl_net_dump_cb net_cb = {
5589651eb Nicolas Dichtel 2018-11-22 933 .tgt_net = sock_net(skb->sk),
a143c40c3 Nicolas Dichtel 2015-04-07 934 .skb = skb,
70955fc94 Nicolas Dichtel 2018-11-22 935 .fillargs = {
70955fc94 Nicolas Dichtel 2018-11-22 936 .portid = NETLINK_CB(cb->skb).portid,
70955fc94 Nicolas Dichtel 2018-11-22 937 .seq = cb->nlh->nlmsg_seq,
70955fc94 Nicolas Dichtel 2018-11-22 938 .flags = NLM_F_MULTI,
70955fc94 Nicolas Dichtel 2018-11-22 939 .cmd = RTM_NEWNSID,
70955fc94 Nicolas Dichtel 2018-11-22 940 },
a143c40c3 Nicolas Dichtel 2015-04-07 941 .idx = 0,
a143c40c3 Nicolas Dichtel 2015-04-07 942 .s_idx = cb->args[0],
a143c40c3 Nicolas Dichtel 2015-04-07 943 };
5589651eb Nicolas Dichtel 2018-11-22 944 int err = 0;
a143c40c3 Nicolas Dichtel 2015-04-07 945
5589651eb Nicolas Dichtel 2018-11-22 946 if (cb->strict_check) {
5589651eb Nicolas Dichtel 2018-11-22 947 err = rtnl_valid_dump_net_req(cb->nlh, skb->sk, &net_cb, cb);
5589651eb Nicolas Dichtel 2018-11-22 948 if (err < 0)
5589651eb Nicolas Dichtel 2018-11-22 949 goto end;
f80f14c36 David Ahern 2018-10-07 950 }
f80f14c36 David Ahern 2018-10-07 951
5589651eb Nicolas Dichtel 2018-11-22 952 spin_lock_bh(&net_cb.tgt_net->nsid_lock);
8a46e1ccc Nicolas Dichtel 2018-11-22 953 if (net_cb.fillargs.add_ref &&
8a46e1ccc Nicolas Dichtel 2018-11-22 954 !net_eq(net_cb.ref_net, net_cb.tgt_net) &&
8a46e1ccc Nicolas Dichtel 2018-11-22 955 !spin_trylock_bh(&net_cb.ref_net->nsid_lock)) {
8a46e1ccc Nicolas Dichtel 2018-11-22 956 err = -EAGAIN;
8a46e1ccc Nicolas Dichtel 2018-11-22 957 goto end;
8a46e1ccc Nicolas Dichtel 2018-11-22 958 }
5589651eb Nicolas Dichtel 2018-11-22 959 idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb);
8a46e1ccc Nicolas Dichtel 2018-11-22 960 if (net_cb.fillargs.add_ref &&
8a46e1ccc Nicolas Dichtel 2018-11-22 961 !net_eq(net_cb.ref_net, net_cb.tgt_net))
8a46e1ccc Nicolas Dichtel 2018-11-22 962 spin_unlock_bh(&net_cb.ref_net->nsid_lock);
5589651eb Nicolas Dichtel 2018-11-22 @963 spin_unlock_bh(&net_cb.tgt_net->nsid_lock);
a143c40c3 Nicolas Dichtel 2015-04-07 964
a143c40c3 Nicolas Dichtel 2015-04-07 965 cb->args[0] = net_cb.idx;
5589651eb Nicolas Dichtel 2018-11-22 966 end:
8a46e1ccc Nicolas Dichtel 2018-11-22 967 if (net_cb.fillargs.add_ref)
5589651eb Nicolas Dichtel 2018-11-22 968 put_net(net_cb.tgt_net);
5589651eb Nicolas Dichtel 2018-11-22 969 return err < 0 ? err : skb->len;
a143c40c3 Nicolas Dichtel 2015-04-07 970 }
a143c40c3 Nicolas Dichtel 2015-04-07 971
:::::: The code at line 963 was first introduced by commit
:::::: 5589651eb5e06b32107a1d8830af4be67aa58b85 netns: add support of NETNSA_TARGET_NSID
:::::: TO: Nicolas Dichtel <nicolas.dichtel@6wind.com>
:::::: CC: 0day robot <lkp@intel.com>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 66610 bytes --]
^ permalink raw reply [flat|nested] 39+ messages in thread
* [PATCH net-next v4 0/5] Ease to interpret net-nsid
2018-11-22 22:22 ` [PATCH net-next v3 0/5] Ease to interpret net-nsid Nicolas Dichtel
` (4 preceding siblings ...)
2018-11-22 22:22 ` [PATCH net-next v3 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel
@ 2018-11-26 14:42 ` Nicolas Dichtel
2018-11-26 14:42 ` [PATCH net-next v4 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel
` (5 more replies)
5 siblings, 6 replies; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-26 14:42 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem
The goal of this series is to ease the interpretation of nsid received in
netlink messages from other netns (when the user uses
NETLINK_F_LISTEN_ALL_NSID).
After this series, with a patched iproute2:
$ ip netns add foo
$ ip netns add bar
$ touch /var/run/netns/init_net
$ mount --bind /proc/1/ns/net /var/run/netns/init_net
$ ip netns set init_net 11
$ ip netns set foo 12
$ ip netns set bar 13
$ ip netns
init_net (id: 11)
bar (id: 13)
foo (id: 12)
$ ip -n foo netns set init_net 21
$ ip -n foo netns set foo 22
$ ip -n foo netns set bar 23
$ ip -n foo netns
init_net (id: 21)
bar (id: 23)
foo (id: 22)
$ ip -n bar netns set init_net 31
$ ip -n bar netns set foo 32
$ ip -n bar netns set bar 33
$ ip -n bar netns
init_net (id: 31)
bar (id: 33)
foo (id: 32)
$ ip netns list-id target-nsid 12
nsid 21 current-nsid 11 (iproute2 netns name: init_net)
nsid 22 current-nsid 12 (iproute2 netns name: foo)
nsid 23 current-nsid 13 (iproute2 netns name: bar)
$ ip -n bar netns list-id target-nsid 32 nsid 31
nsid 21 current-nsid 31 (iproute2 netns name: init_net)
v3 -> v4:
- patch 5/5: fix imbalance lock in error path
v2 -> v3:
- patch 5/5: account NETNSA_CURRENT_NSID in rtnl_net_get_size()
v1 -> v2:
- patch 1/5: remove net from struct rtnl_net_dump_cb
- patch 2/5: new in this version
- patch 3/5: use a bool to know if rtnl_get_net_ns_capable() was called
- patch 5/5: use struct net_fill_args
include/uapi/linux/net_namespace.h | 2 +
net/core/net_namespace.c | 159 +++++++++++++++++++++++++++++++------
2 files changed, 135 insertions(+), 26 deletions(-)
Comments are welcomed,
Regards,
Nicolas
^ permalink raw reply [flat|nested] 39+ messages in thread
* [PATCH net-next v4 1/5] netns: remove net arg from rtnl_net_fill()
2018-11-26 14:42 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid Nicolas Dichtel
@ 2018-11-26 14:42 ` Nicolas Dichtel
2018-11-26 14:42 ` [PATCH net-next v4 2/5] netns: introduce 'struct net_fill_args' Nicolas Dichtel
` (4 subsequent siblings)
5 siblings, 0 replies; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-26 14:42 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem, Nicolas Dichtel
This argument is not used anymore.
Fixes: cab3c8ec8d57 ("netns: always provide the id to rtnl_net_fill()")
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Reviewed-by: David Ahern <dsahern@gmail.com>
---
net/core/net_namespace.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index fefe72774aeb..52b9620e3457 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -739,7 +739,7 @@ static int rtnl_net_get_size(void)
}
static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
- int cmd, struct net *net, int nsid)
+ int cmd, int nsid)
{
struct nlmsghdr *nlh;
struct rtgenmsg *rth;
@@ -801,7 +801,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
id = peernet2id(net, peer);
err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
- RTM_NEWNSID, net, id);
+ RTM_NEWNSID, id);
if (err < 0)
goto err_out;
@@ -816,7 +816,6 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
}
struct rtnl_net_dump_cb {
- struct net *net;
struct sk_buff *skb;
struct netlink_callback *cb;
int idx;
@@ -833,7 +832,7 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data)
ret = rtnl_net_fill(net_cb->skb, NETLINK_CB(net_cb->cb->skb).portid,
net_cb->cb->nlh->nlmsg_seq, NLM_F_MULTI,
- RTM_NEWNSID, net_cb->net, id);
+ RTM_NEWNSID, id);
if (ret < 0)
return ret;
@@ -846,7 +845,6 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
{
struct net *net = sock_net(skb->sk);
struct rtnl_net_dump_cb net_cb = {
- .net = net,
.skb = skb,
.cb = cb,
.idx = 0,
@@ -876,7 +874,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id)
if (!msg)
goto out;
- err = rtnl_net_fill(msg, 0, 0, 0, cmd, net, id);
+ err = rtnl_net_fill(msg, 0, 0, 0, cmd, id);
if (err < 0)
goto err_out;
--
2.18.0
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next v4 2/5] netns: introduce 'struct net_fill_args'
2018-11-26 14:42 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid Nicolas Dichtel
2018-11-26 14:42 ` [PATCH net-next v4 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel
@ 2018-11-26 14:42 ` Nicolas Dichtel
2018-11-26 14:42 ` [PATCH net-next v4 3/5] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel
` (3 subsequent siblings)
5 siblings, 0 replies; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-26 14:42 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem, Nicolas Dichtel
This is a preparatory work. To avoid having to much arguments for the
function rtnl_net_fill(), a new structure is defined.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Reviewed-by: David Ahern <dsahern@gmail.com>
---
net/core/net_namespace.c | 48 ++++++++++++++++++++++++++++------------
1 file changed, 34 insertions(+), 14 deletions(-)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 52b9620e3457..f8a5966b086c 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -738,20 +738,28 @@ static int rtnl_net_get_size(void)
;
}
-static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
- int cmd, int nsid)
+struct net_fill_args {
+ u32 portid;
+ u32 seq;
+ int flags;
+ int cmd;
+ int nsid;
+};
+
+static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args)
{
struct nlmsghdr *nlh;
struct rtgenmsg *rth;
- nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rth), flags);
+ nlh = nlmsg_put(skb, args->portid, args->seq, args->cmd, sizeof(*rth),
+ args->flags);
if (!nlh)
return -EMSGSIZE;
rth = nlmsg_data(nlh);
rth->rtgen_family = AF_UNSPEC;
- if (nla_put_s32(skb, NETNSA_NSID, nsid))
+ if (nla_put_s32(skb, NETNSA_NSID, args->nsid))
goto nla_put_failure;
nlmsg_end(skb, nlh);
@@ -767,10 +775,15 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
{
struct net *net = sock_net(skb->sk);
struct nlattr *tb[NETNSA_MAX + 1];
+ struct net_fill_args fillargs = {
+ .portid = NETLINK_CB(skb).portid,
+ .seq = nlh->nlmsg_seq,
+ .cmd = RTM_NEWNSID,
+ };
struct nlattr *nla;
struct sk_buff *msg;
struct net *peer;
- int err, id;
+ int err;
err = nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX,
rtnl_net_policy, extack);
@@ -799,9 +812,8 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
goto out;
}
- id = peernet2id(net, peer);
- err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
- RTM_NEWNSID, id);
+ fillargs.nsid = peernet2id(net, peer);
+ err = rtnl_net_fill(msg, &fillargs);
if (err < 0)
goto err_out;
@@ -817,7 +829,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
struct rtnl_net_dump_cb {
struct sk_buff *skb;
- struct netlink_callback *cb;
+ struct net_fill_args fillargs;
int idx;
int s_idx;
};
@@ -830,9 +842,8 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data)
if (net_cb->idx < net_cb->s_idx)
goto cont;
- ret = rtnl_net_fill(net_cb->skb, NETLINK_CB(net_cb->cb->skb).portid,
- net_cb->cb->nlh->nlmsg_seq, NLM_F_MULTI,
- RTM_NEWNSID, id);
+ net_cb->fillargs.nsid = id;
+ ret = rtnl_net_fill(net_cb->skb, &net_cb->fillargs);
if (ret < 0)
return ret;
@@ -846,7 +857,12 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
struct net *net = sock_net(skb->sk);
struct rtnl_net_dump_cb net_cb = {
.skb = skb,
- .cb = cb,
+ .fillargs = {
+ .portid = NETLINK_CB(cb->skb).portid,
+ .seq = cb->nlh->nlmsg_seq,
+ .flags = NLM_F_MULTI,
+ .cmd = RTM_NEWNSID,
+ },
.idx = 0,
.s_idx = cb->args[0],
};
@@ -867,6 +883,10 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
static void rtnl_net_notifyid(struct net *net, int cmd, int id)
{
+ struct net_fill_args fillargs = {
+ .cmd = cmd,
+ .nsid = id,
+ };
struct sk_buff *msg;
int err = -ENOMEM;
@@ -874,7 +894,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id)
if (!msg)
goto out;
- err = rtnl_net_fill(msg, 0, 0, 0, cmd, id);
+ err = rtnl_net_fill(msg, &fillargs);
if (err < 0)
goto err_out;
--
2.18.0
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next v4 3/5] netns: add support of NETNSA_TARGET_NSID
2018-11-26 14:42 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid Nicolas Dichtel
2018-11-26 14:42 ` [PATCH net-next v4 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel
2018-11-26 14:42 ` [PATCH net-next v4 2/5] netns: introduce 'struct net_fill_args' Nicolas Dichtel
@ 2018-11-26 14:42 ` Nicolas Dichtel
2018-11-26 14:42 ` [PATCH net-next v4 4/5] netns: enable to specify a nsid for a get request Nicolas Dichtel
` (2 subsequent siblings)
5 siblings, 0 replies; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-26 14:42 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem, Nicolas Dichtel
Like it was done for link and address, add the ability to perform get/dump
in another netns by specifying a target nsid attribute.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Reviewed-by: David Ahern <dsahern@gmail.com>
---
include/uapi/linux/net_namespace.h | 1 +
net/core/net_namespace.c | 86 ++++++++++++++++++++++++++----
2 files changed, 76 insertions(+), 11 deletions(-)
diff --git a/include/uapi/linux/net_namespace.h b/include/uapi/linux/net_namespace.h
index 0187c74d8889..0ed9dd61d32a 100644
--- a/include/uapi/linux/net_namespace.h
+++ b/include/uapi/linux/net_namespace.h
@@ -16,6 +16,7 @@ enum {
NETNSA_NSID,
NETNSA_PID,
NETNSA_FD,
+ NETNSA_TARGET_NSID,
__NETNSA_MAX,
};
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index f8a5966b086c..885c54197e31 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -669,6 +669,7 @@ static const struct nla_policy rtnl_net_policy[NETNSA_MAX + 1] = {
[NETNSA_NSID] = { .type = NLA_S32 },
[NETNSA_PID] = { .type = NLA_U32 },
[NETNSA_FD] = { .type = NLA_U32 },
+ [NETNSA_TARGET_NSID] = { .type = NLA_S32 },
};
static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -780,9 +781,10 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
.seq = nlh->nlmsg_seq,
.cmd = RTM_NEWNSID,
};
+ struct net *peer, *target = net;
+ bool put_target = false;
struct nlattr *nla;
struct sk_buff *msg;
- struct net *peer;
int err;
err = nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX,
@@ -806,13 +808,27 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
return PTR_ERR(peer);
}
+ if (tb[NETNSA_TARGET_NSID]) {
+ int id = nla_get_s32(tb[NETNSA_TARGET_NSID]);
+
+ target = rtnl_get_net_ns_capable(NETLINK_CB(skb).sk, id);
+ if (IS_ERR(target)) {
+ NL_SET_BAD_ATTR(extack, tb[NETNSA_TARGET_NSID]);
+ NL_SET_ERR_MSG(extack,
+ "Target netns reference is invalid");
+ err = PTR_ERR(target);
+ goto out;
+ }
+ put_target = true;
+ }
+
msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL);
if (!msg) {
err = -ENOMEM;
goto out;
}
- fillargs.nsid = peernet2id(net, peer);
+ fillargs.nsid = peernet2id(target, peer);
err = rtnl_net_fill(msg, &fillargs);
if (err < 0)
goto err_out;
@@ -823,15 +839,19 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
err_out:
nlmsg_free(msg);
out:
+ if (put_target)
+ put_net(target);
put_net(peer);
return err;
}
struct rtnl_net_dump_cb {
+ struct net *tgt_net;
struct sk_buff *skb;
struct net_fill_args fillargs;
int idx;
int s_idx;
+ bool put_tgt_net;
};
static int rtnl_net_dumpid_one(int id, void *peer, void *data)
@@ -852,10 +872,50 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data)
return 0;
}
+static int rtnl_valid_dump_net_req(const struct nlmsghdr *nlh, struct sock *sk,
+ struct rtnl_net_dump_cb *net_cb,
+ struct netlink_callback *cb)
+{
+ struct netlink_ext_ack *extack = cb->extack;
+ struct nlattr *tb[NETNSA_MAX + 1];
+ int err, i;
+
+ err = nlmsg_parse_strict(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX,
+ rtnl_net_policy, extack);
+ if (err < 0)
+ return err;
+
+ for (i = 0; i <= NETNSA_MAX; i++) {
+ if (!tb[i])
+ continue;
+
+ if (i == NETNSA_TARGET_NSID) {
+ struct net *net;
+
+ net = rtnl_get_net_ns_capable(sk, nla_get_s32(tb[i]));
+ if (IS_ERR(net)) {
+ NL_SET_BAD_ATTR(extack, tb[i]);
+ NL_SET_ERR_MSG(extack,
+ "Invalid target network namespace id");
+ return PTR_ERR(net);
+ }
+ net_cb->tgt_net = net;
+ net_cb->put_tgt_net = true;
+ } else {
+ NL_SET_BAD_ATTR(extack, tb[i]);
+ NL_SET_ERR_MSG(extack,
+ "Unsupported attribute in dump request");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
{
- struct net *net = sock_net(skb->sk);
struct rtnl_net_dump_cb net_cb = {
+ .tgt_net = sock_net(skb->sk),
.skb = skb,
.fillargs = {
.portid = NETLINK_CB(cb->skb).portid,
@@ -866,19 +926,23 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
.idx = 0,
.s_idx = cb->args[0],
};
+ int err = 0;
- if (cb->strict_check &&
- nlmsg_attrlen(cb->nlh, sizeof(struct rtgenmsg))) {
- NL_SET_ERR_MSG(cb->extack, "Unknown data in network namespace id dump request");
- return -EINVAL;
+ if (cb->strict_check) {
+ err = rtnl_valid_dump_net_req(cb->nlh, skb->sk, &net_cb, cb);
+ if (err < 0)
+ goto end;
}
- spin_lock_bh(&net->nsid_lock);
- idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb);
- spin_unlock_bh(&net->nsid_lock);
+ spin_lock_bh(&net_cb.tgt_net->nsid_lock);
+ idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb);
+ spin_unlock_bh(&net_cb.tgt_net->nsid_lock);
cb->args[0] = net_cb.idx;
- return skb->len;
+end:
+ if (net_cb.put_tgt_net)
+ put_net(net_cb.tgt_net);
+ return err < 0 ? err : skb->len;
}
static void rtnl_net_notifyid(struct net *net, int cmd, int id)
--
2.18.0
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next v4 4/5] netns: enable to specify a nsid for a get request
2018-11-26 14:42 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid Nicolas Dichtel
` (2 preceding siblings ...)
2018-11-26 14:42 ` [PATCH net-next v4 3/5] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel
@ 2018-11-26 14:42 ` Nicolas Dichtel
2018-11-26 14:42 ` [PATCH net-next v4 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel
2018-11-28 0:20 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid David Miller
5 siblings, 0 replies; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-26 14:42 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem, Nicolas Dichtel
Combined with NETNSA_TARGET_NSID, it enables to "translate" a nsid from one
netns to a nsid of another netns.
This is useful when using NETLINK_F_LISTEN_ALL_NSID because it helps the
user to interpret a nsid received from an other netns.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Reviewed-by: David Ahern <dsahern@gmail.com>
---
net/core/net_namespace.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 885c54197e31..dd25fb22ad45 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -797,6 +797,11 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
} else if (tb[NETNSA_FD]) {
peer = get_net_ns_by_fd(nla_get_u32(tb[NETNSA_FD]));
nla = tb[NETNSA_FD];
+ } else if (tb[NETNSA_NSID]) {
+ peer = get_net_ns_by_id(net, nla_get_u32(tb[NETNSA_NSID]));
+ if (!peer)
+ peer = ERR_PTR(-ENOENT);
+ nla = tb[NETNSA_NSID];
} else {
NL_SET_ERR_MSG(extack, "Peer netns reference is missing");
return -EINVAL;
--
2.18.0
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next v4 5/5] netns: enable to dump full nsid translation table
2018-11-26 14:42 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid Nicolas Dichtel
` (3 preceding siblings ...)
2018-11-26 14:42 ` [PATCH net-next v4 4/5] netns: enable to specify a nsid for a get request Nicolas Dichtel
@ 2018-11-26 14:42 ` Nicolas Dichtel
2018-11-28 0:20 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid David Miller
5 siblings, 0 replies; 39+ messages in thread
From: Nicolas Dichtel @ 2018-11-26 14:42 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem, Nicolas Dichtel
Like the previous patch, the goal is to ease to convert nsids from one
netns to another netns.
A new attribute (NETNSA_CURRENT_NSID) is added to the kernel answer when
NETNSA_TARGET_NSID is provided, thus the user can easily convert nsids.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Reviewed-by: David Ahern <dsahern@gmail.com>
---
include/uapi/linux/net_namespace.h | 1 +
net/core/net_namespace.c | 32 ++++++++++++++++++++++++------
2 files changed, 27 insertions(+), 6 deletions(-)
diff --git a/include/uapi/linux/net_namespace.h b/include/uapi/linux/net_namespace.h
index 0ed9dd61d32a..9f9956809565 100644
--- a/include/uapi/linux/net_namespace.h
+++ b/include/uapi/linux/net_namespace.h
@@ -17,6 +17,7 @@ enum {
NETNSA_PID,
NETNSA_FD,
NETNSA_TARGET_NSID,
+ NETNSA_CURRENT_NSID,
__NETNSA_MAX,
};
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index dd25fb22ad45..05b23b285058 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -736,6 +736,7 @@ static int rtnl_net_get_size(void)
{
return NLMSG_ALIGN(sizeof(struct rtgenmsg))
+ nla_total_size(sizeof(s32)) /* NETNSA_NSID */
+ + nla_total_size(sizeof(s32)) /* NETNSA_CURRENT_NSID */
;
}
@@ -745,6 +746,8 @@ struct net_fill_args {
int flags;
int cmd;
int nsid;
+ bool add_ref;
+ int ref_nsid;
};
static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args)
@@ -763,6 +766,10 @@ static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args)
if (nla_put_s32(skb, NETNSA_NSID, args->nsid))
goto nla_put_failure;
+ if (args->add_ref &&
+ nla_put_s32(skb, NETNSA_CURRENT_NSID, args->ref_nsid))
+ goto nla_put_failure;
+
nlmsg_end(skb, nlh);
return 0;
@@ -782,7 +789,6 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
.cmd = RTM_NEWNSID,
};
struct net *peer, *target = net;
- bool put_target = false;
struct nlattr *nla;
struct sk_buff *msg;
int err;
@@ -824,7 +830,8 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
err = PTR_ERR(target);
goto out;
}
- put_target = true;
+ fillargs.add_ref = true;
+ fillargs.ref_nsid = peernet2id(net, peer);
}
msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL);
@@ -844,7 +851,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
err_out:
nlmsg_free(msg);
out:
- if (put_target)
+ if (fillargs.add_ref)
put_net(target);
put_net(peer);
return err;
@@ -852,11 +859,11 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
struct rtnl_net_dump_cb {
struct net *tgt_net;
+ struct net *ref_net;
struct sk_buff *skb;
struct net_fill_args fillargs;
int idx;
int s_idx;
- bool put_tgt_net;
};
static int rtnl_net_dumpid_one(int id, void *peer, void *data)
@@ -868,6 +875,8 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data)
goto cont;
net_cb->fillargs.nsid = id;
+ if (net_cb->fillargs.add_ref)
+ net_cb->fillargs.ref_nsid = __peernet2id(net_cb->ref_net, peer);
ret = rtnl_net_fill(net_cb->skb, &net_cb->fillargs);
if (ret < 0)
return ret;
@@ -904,8 +913,9 @@ static int rtnl_valid_dump_net_req(const struct nlmsghdr *nlh, struct sock *sk,
"Invalid target network namespace id");
return PTR_ERR(net);
}
+ net_cb->fillargs.add_ref = true;
+ net_cb->ref_net = net_cb->tgt_net;
net_cb->tgt_net = net;
- net_cb->put_tgt_net = true;
} else {
NL_SET_BAD_ATTR(extack, tb[i]);
NL_SET_ERR_MSG(extack,
@@ -940,12 +950,22 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
}
spin_lock_bh(&net_cb.tgt_net->nsid_lock);
+ if (net_cb.fillargs.add_ref &&
+ !net_eq(net_cb.ref_net, net_cb.tgt_net) &&
+ !spin_trylock_bh(&net_cb.ref_net->nsid_lock)) {
+ spin_unlock_bh(&net_cb.tgt_net->nsid_lock);
+ err = -EAGAIN;
+ goto end;
+ }
idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb);
+ if (net_cb.fillargs.add_ref &&
+ !net_eq(net_cb.ref_net, net_cb.tgt_net))
+ spin_unlock_bh(&net_cb.ref_net->nsid_lock);
spin_unlock_bh(&net_cb.tgt_net->nsid_lock);
cb->args[0] = net_cb.idx;
end:
- if (net_cb.put_tgt_net)
+ if (net_cb.fillargs.add_ref)
put_net(net_cb.tgt_net);
return err < 0 ? err : skb->len;
}
--
2.18.0
^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [PATCH net-next v4 0/5] Ease to interpret net-nsid
2018-11-26 14:42 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid Nicolas Dichtel
` (4 preceding siblings ...)
2018-11-26 14:42 ` [PATCH net-next v4 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel
@ 2018-11-28 0:20 ` David Miller
5 siblings, 0 replies; 39+ messages in thread
From: David Miller @ 2018-11-28 0:20 UTC (permalink / raw)
To: nicolas.dichtel; +Cc: dsahern, netdev
From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Date: Mon, 26 Nov 2018 15:42:01 +0100
>
> The goal of this series is to ease the interpretation of nsid received in
> netlink messages from other netns (when the user uses
> NETLINK_F_LISTEN_ALL_NSID).
>
> After this series, with a patched iproute2:
...
> v3 -> v4:
> - patch 5/5: fix imbalance lock in error path
>
> v2 -> v3:
> - patch 5/5: account NETNSA_CURRENT_NSID in rtnl_net_get_size()
>
> v1 -> v2:
> - patch 1/5: remove net from struct rtnl_net_dump_cb
> - patch 2/5: new in this version
> - patch 3/5: use a bool to know if rtnl_get_net_ns_capable() was called
> - patch 5/5: use struct net_fill_args
Series applied.
^ permalink raw reply [flat|nested] 39+ messages in thread
end of thread, other threads:[~2018-11-28 11:20 UTC | newest]
Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-21 11:01 [PATCH net-next 0/4] Ease to interpret net-nsid Nicolas Dichtel
2018-11-21 11:01 ` [PATCH net-next 1/4] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel
2018-11-21 11:01 ` [PATCH net-next 2/4] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel
2018-11-21 18:05 ` David Ahern
2018-11-21 20:58 ` Nicolas Dichtel
2018-11-21 21:07 ` David Ahern
2018-11-22 8:06 ` Nicolas Dichtel
2018-11-21 11:01 ` [PATCH net-next 3/4] netns: enable to specify a nsid for a get request Nicolas Dichtel
2018-11-21 11:01 ` [PATCH net-next 4/4] netns: enable to dump full nsid translation table Nicolas Dichtel
2018-11-21 18:09 ` David Ahern
2018-11-21 21:01 ` Nicolas Dichtel
2018-11-21 21:08 ` David Ahern
2018-11-22 15:50 ` [PATCH net-next v2 0/5] Ease to interpret net-nsid Nicolas Dichtel
2018-11-22 15:50 ` [PATCH net-next v2 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel
2018-11-22 16:18 ` David Ahern
2018-11-22 15:50 ` [PATCH net-next v2 2/5] netns: introduce 'struct net_fill_args' Nicolas Dichtel
2018-11-22 16:23 ` David Ahern
2018-11-22 15:50 ` [PATCH net-next v2 3/5] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel
2018-11-22 16:32 ` David Ahern
2018-11-22 15:50 ` [PATCH net-next v2 4/5] netns: enable to specify a nsid for a get request Nicolas Dichtel
2018-11-22 16:32 ` David Ahern
2018-11-22 15:50 ` [PATCH net-next v2 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel
2018-11-22 16:40 ` David Ahern
2018-11-22 16:42 ` Nicolas Dichtel
2018-11-22 22:22 ` [PATCH net-next v3 0/5] Ease to interpret net-nsid Nicolas Dichtel
2018-11-22 22:22 ` [PATCH net-next v3 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel
2018-11-22 22:22 ` [PATCH net-next v3 2/5] netns: introduce 'struct net_fill_args' Nicolas Dichtel
2018-11-22 22:22 ` [PATCH net-next v3 3/5] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel
2018-11-22 22:22 ` [PATCH net-next v3 4/5] netns: enable to specify a nsid for a get request Nicolas Dichtel
2018-11-22 22:22 ` [PATCH net-next v3 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel
2018-11-24 15:47 ` David Ahern
2018-11-26 10:06 ` kbuild test robot
2018-11-26 14:42 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid Nicolas Dichtel
2018-11-26 14:42 ` [PATCH net-next v4 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel
2018-11-26 14:42 ` [PATCH net-next v4 2/5] netns: introduce 'struct net_fill_args' Nicolas Dichtel
2018-11-26 14:42 ` [PATCH net-next v4 3/5] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel
2018-11-26 14:42 ` [PATCH net-next v4 4/5] netns: enable to specify a nsid for a get request Nicolas Dichtel
2018-11-26 14:42 ` [PATCH net-next v4 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel
2018-11-28 0:20 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid David Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).