From patchwork Wed Nov 21 11:01:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolas Dichtel X-Patchwork-Id: 1001080 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=6wind.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 430KQT65N0z9s4s for ; Wed, 21 Nov 2018 22:01:53 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729679AbeKUVfs (ORCPT ); Wed, 21 Nov 2018 16:35:48 -0500 Received: from host.76.145.23.62.rev.coltfrance.com ([62.23.145.76]:55073 "EHLO proxy.6wind.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729608AbeKUVfr (ORCPT ); Wed, 21 Nov 2018 16:35:47 -0500 Received: from bretzel.dev.6wind.com (unknown [10.16.0.19]) by proxy.6wind.com (Postfix) with ESMTPS id F0A452218E3; Wed, 21 Nov 2018 11:59:28 +0100 (CET) Received: from dichtel by bretzel.dev.6wind.com with local (Exim 4.89) (envelope-from ) id 1gPQGB-0001SG-Iy; Wed, 21 Nov 2018 12:01:31 +0100 From: Nicolas Dichtel To: davem@davemloft.net Cc: netdev@vger.kernel.org, Nicolas Dichtel Subject: [PATCH net-next 4/4] netns: enable to dump full nsid translation table Date: Wed, 21 Nov 2018 12:01:24 +0100 Message-Id: <20181121110124.5501-5-nicolas.dichtel@6wind.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20181121110124.5501-1-nicolas.dichtel@6wind.com> References: <20181121110124.5501-1-nicolas.dichtel@6wind.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org 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 --- 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;