netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jiri Pirko <jiri@resnulli.us>
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, jakub.kicinski@netronome.com,
	sthemmin@microsoft.com, dsahern@gmail.com, dcbw@redhat.com,
	mkubecek@suse.cz, andrew@lunn.ch, parav@mellanox.com,
	saeedm@mellanox.com, mlxsw@mellanox.com
Subject: [patch net-next rfc 3/7] net: rtnetlink: add commands to add and delete alternative ifnames
Date: Fri, 19 Jul 2019 13:00:25 +0200	[thread overview]
Message-ID: <20190719110029.29466-4-jiri@resnulli.us> (raw)
In-Reply-To: <20190719110029.29466-1-jiri@resnulli.us>

From: Jiri Pirko <jiri@mellanox.com>

Add two commands to add and delete alternative ifnames for net device.
Each net device can have multiple alternative names.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 include/linux/netdevice.h      |   4 ++
 include/uapi/linux/if.h        |   1 +
 include/uapi/linux/if_link.h   |   1 +
 include/uapi/linux/rtnetlink.h |   7 +++
 net/core/dev.c                 |  58 ++++++++++++++++++-
 net/core/rtnetlink.c           | 102 +++++++++++++++++++++++++++++++++
 security/selinux/nlmsgtab.c    |   4 +-
 7 files changed, 175 insertions(+), 2 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 74f99f127b0e..6922fdb483ca 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -920,10 +920,14 @@ struct tlsdev_ops;
 
 struct netdev_name_node {
 	struct hlist_node hlist;
+	struct list_head list;
 	struct net_device *dev;
 	char *name;
 };
 
+int netdev_name_node_alt_create(struct net_device *dev, char *name);
+int netdev_name_node_alt_destroy(struct net_device *dev, char *name);
+
 /*
  * This structure defines the management hooks for network devices.
  * The following hooks can be defined; unless noted otherwise, they are
diff --git a/include/uapi/linux/if.h b/include/uapi/linux/if.h
index 7fea0fd7d6f5..4bf33344aab1 100644
--- a/include/uapi/linux/if.h
+++ b/include/uapi/linux/if.h
@@ -33,6 +33,7 @@
 #define	IFNAMSIZ	16
 #endif /* __UAPI_DEF_IF_IFNAMSIZ */
 #define	IFALIASZ	256
+#define	ALTIFNAMSIZ	128
 #include <linux/hdlc/ioctl.h>
 
 /* For glibc compatibility. An empty enum does not compile. */
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 4a8c02cafa9a..92268946e04a 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -167,6 +167,7 @@ enum {
 	IFLA_NEW_IFINDEX,
 	IFLA_MIN_MTU,
 	IFLA_MAX_MTU,
+	IFLA_ALT_IFNAME_MOD, /* Alternative ifname to add/delete */
 	__IFLA_MAX
 };
 
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index ce2a623abb75..b36cfd83eb76 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -164,6 +164,13 @@ enum {
 	RTM_GETNEXTHOP,
 #define RTM_GETNEXTHOP	RTM_GETNEXTHOP
 
+	RTM_NEWALTIFNAME = 108,
+#define RTM_NEWALTIFNAME	RTM_NEWALTIFNAME
+	RTM_DELALTIFNAME,
+#define RTM_DELALTIFNAME	RTM_DELALTIFNAME
+	RTM_GETALTIFNAME,
+#define RTM_GETALTIFNAME	RTM_GETALTIFNAME
+
 	__RTM_MAX,
 #define RTM_MAX		(((__RTM_MAX + 3) & ~3) - 1)
 };
diff --git a/net/core/dev.c b/net/core/dev.c
index ad0d42fbdeee..2a3be2b279d3 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -244,7 +244,13 @@ static struct netdev_name_node *netdev_name_node_alloc(struct net_device *dev,
 static struct netdev_name_node *
 netdev_name_node_head_alloc(struct net_device *dev)
 {
-	return netdev_name_node_alloc(dev, dev->name);
+	struct netdev_name_node *name_node;
+
+	name_node = netdev_name_node_alloc(dev, dev->name);
+	if (!name_node)
+		return NULL;
+	INIT_LIST_HEAD(&name_node->list);
+	return name_node;
 }
 
 static void netdev_name_node_free(struct netdev_name_node *name_node)
@@ -288,6 +294,55 @@ static struct netdev_name_node *netdev_name_node_lookup_rcu(struct net *net,
 	return NULL;
 }
 
+int netdev_name_node_alt_create(struct net_device *dev, char *name)
+{
+	struct netdev_name_node *name_node;
+	struct net *net = dev_net(dev);
+
+	name_node = netdev_name_node_lookup(net, name);
+	if (name_node)
+		return -EEXIST;
+	name_node = netdev_name_node_alloc(dev, name);
+	if (!name_node)
+		return -ENOMEM;
+	netdev_name_node_add(net, name_node);
+	/* The node that holds dev->name acts as a head of per-device list. */
+	list_add_tail(&name_node->list, &dev->name_node->list);
+
+	return 0;
+}
+EXPORT_SYMBOL(netdev_name_node_alt_create);
+
+static void __netdev_name_node_alt_destroy(struct netdev_name_node *name_node)
+{
+	list_del(&name_node->list);
+	netdev_name_node_del(name_node);
+	kfree(name_node->name);
+	netdev_name_node_free(name_node);
+}
+
+int netdev_name_node_alt_destroy(struct net_device *dev, char *name)
+{
+	struct netdev_name_node *name_node;
+	struct net *net = dev_net(dev);
+
+	name_node = netdev_name_node_lookup(net, name);
+	if (!name_node)
+		return -ENOENT;
+	__netdev_name_node_alt_destroy(name_node);
+
+	return 0;
+}
+EXPORT_SYMBOL(netdev_name_node_alt_destroy);
+
+static void netdev_name_node_alt_flush(struct net_device *dev)
+{
+	struct netdev_name_node *name_node, *tmp;
+
+	list_for_each_entry_safe(name_node, tmp, &dev->name_node->list, list)
+		__netdev_name_node_alt_destroy(name_node);
+}
+
 /* Device list insertion */
 static void list_netdevice(struct net_device *dev)
 {
@@ -8258,6 +8313,7 @@ static void rollback_registered_many(struct list_head *head)
 		dev_uc_flush(dev);
 		dev_mc_flush(dev);
 
+		netdev_name_node_alt_flush(dev);
 		netdev_name_node_free(dev->name_node);
 
 		if (dev->netdev_ops->ndo_uninit)
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 1ee6460f8275..7a2010b16e10 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1750,6 +1750,8 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
 	[IFLA_CARRIER_DOWN_COUNT] = { .type = NLA_U32 },
 	[IFLA_MIN_MTU]		= { .type = NLA_U32 },
 	[IFLA_MAX_MTU]		= { .type = NLA_U32 },
+	[IFLA_ALT_IFNAME_MOD]	= { .type = NLA_STRING,
+				    .len = ALTIFNAMSIZ - 1 },
 };
 
 static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
@@ -3373,6 +3375,103 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr *nlh,
 	return err;
 }
 
+static int rtnl_newaltifname(struct sk_buff *skb, struct nlmsghdr *nlh,
+			     struct netlink_ext_ack *extack)
+{
+	struct net *net = sock_net(skb->sk);
+	struct nlattr *tb[IFLA_MAX + 1];
+	struct net_device *dev;
+	struct ifinfomsg *ifm;
+	char *new_alt_ifname;
+	int err;
+
+	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy, extack);
+	if (err)
+		return err;
+
+	err = rtnl_ensure_unique_netns(tb, extack, true);
+	if (err)
+		return err;
+
+	ifm = nlmsg_data(nlh);
+	if (ifm->ifi_index > 0) {
+		dev = __dev_get_by_index(net, ifm->ifi_index);
+	} else if (tb[IFLA_IFNAME]) {
+		char ifname[IFNAMSIZ];
+
+		nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
+		dev = __dev_get_by_name(net, ifname);
+	} else {
+		return -EINVAL;
+	}
+
+	if (!dev)
+		return -ENODEV;
+
+	if (!tb[IFLA_ALT_IFNAME_MOD])
+		return -EINVAL;
+
+	new_alt_ifname = nla_strdup(tb[IFLA_ALT_IFNAME_MOD], GFP_KERNEL);
+	if (!new_alt_ifname)
+		return -ENOMEM;
+
+	err = netdev_name_node_alt_create(dev, new_alt_ifname);
+	if (err)
+		goto out_free_new_alt_ifname;
+
+	return 0;
+
+out_free_new_alt_ifname:
+	kfree(new_alt_ifname);
+	return err;
+}
+
+static int rtnl_delaltifname(struct sk_buff *skb, struct nlmsghdr *nlh,
+			     struct netlink_ext_ack *extack)
+{
+	struct net *net = sock_net(skb->sk);
+	struct nlattr *tb[IFLA_MAX + 1];
+	struct net_device *dev;
+	struct ifinfomsg *ifm;
+	char *del_alt_ifname;
+	int err;
+
+	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy, extack);
+	if (err)
+		return err;
+
+	err = rtnl_ensure_unique_netns(tb, extack, true);
+	if (err)
+		return err;
+
+	ifm = nlmsg_data(nlh);
+	if (ifm->ifi_index > 0) {
+		dev = __dev_get_by_index(net, ifm->ifi_index);
+	} else if (tb[IFLA_IFNAME]) {
+		char ifname[IFNAMSIZ];
+
+		nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
+		dev = __dev_get_by_name(net, ifname);
+	} else {
+		return -EINVAL;
+	}
+
+	if (!dev)
+		return -ENODEV;
+
+	if (!tb[IFLA_ALT_IFNAME_MOD])
+		return -EINVAL;
+
+	del_alt_ifname = nla_strdup(tb[IFLA_ALT_IFNAME_MOD], GFP_KERNEL);
+	if (!del_alt_ifname)
+		return -ENOMEM;
+
+	err = netdev_name_node_alt_destroy(dev, del_alt_ifname);
+	kfree(del_alt_ifname);
+
+	return err;
+}
+
 static u16 rtnl_calcit(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
@@ -5331,6 +5430,9 @@ void __init rtnetlink_init(void)
 	rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all, 0);
 	rtnl_register(PF_UNSPEC, RTM_GETNETCONF, NULL, rtnl_dump_all, 0);
 
+	rtnl_register(PF_UNSPEC, RTM_NEWALTIFNAME, rtnl_newaltifname, NULL, 0);
+	rtnl_register(PF_UNSPEC, RTM_DELALTIFNAME, rtnl_delaltifname, NULL, 0);
+
 	rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, rtnl_fdb_add, NULL, 0);
 	rtnl_register(PF_BRIDGE, RTM_DELNEIGH, rtnl_fdb_del, NULL, 0);
 	rtnl_register(PF_BRIDGE, RTM_GETNEIGH, rtnl_fdb_get, rtnl_fdb_dump, 0);
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index 58345ba0528e..a712b54c666c 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -83,6 +83,8 @@ static const struct nlmsg_perm nlmsg_route_perms[] =
 	{ RTM_NEWNEXTHOP,	NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
 	{ RTM_DELNEXTHOP,	NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
 	{ RTM_GETNEXTHOP,	NETLINK_ROUTE_SOCKET__NLMSG_READ  },
+	{ RTM_NEWALTIFNAME,	NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+	{ RTM_DELALTIFNAME,	NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
 };
 
 static const struct nlmsg_perm nlmsg_tcpdiag_perms[] =
@@ -166,7 +168,7 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
 		 * structures at the top of this file with the new mappings
 		 * before updating the BUILD_BUG_ON() macro!
 		 */
-		BUILD_BUG_ON(RTM_MAX != (RTM_NEWNEXTHOP + 3));
+		BUILD_BUG_ON(RTM_MAX != (RTM_NEWALTIFNAME + 3));
 		err = nlmsg_perm(nlmsg_type, perm, nlmsg_route_perms,
 				 sizeof(nlmsg_route_perms));
 		break;
-- 
2.21.0


  parent reply	other threads:[~2019-07-19 11:00 UTC|newest]

Thread overview: 76+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-19 11:00 [patch net-next rfc 0/7] net: introduce alternative names for network interfaces Jiri Pirko
2019-07-19 11:00 ` [patch net-next rfc 1/7] net: procfs: use index hashlist instead of name hashlist Jiri Pirko
2019-07-19 11:00 ` [patch net-next rfc 2/7] net: introduce name_node struct to be used in hashlist Jiri Pirko
2019-07-19 16:29   ` Stephen Hemminger
2019-07-19 19:17     ` Jiri Pirko
2019-07-19 20:26       ` Stephen Hemminger
2019-07-20  7:15         ` Jiri Pirko
2019-09-13  9:52         ` Jiri Pirko
2019-08-08  4:34   ` kbuild test robot
2019-07-19 11:00 ` Jiri Pirko [this message]
2019-07-20  3:58   ` [patch net-next rfc 3/7] net: rtnetlink: add commands to add and delete alternative ifnames Jakub Kicinski
2019-07-20  7:20     ` Jiri Pirko
2019-08-09  4:11   ` Roopa Prabhu
2019-08-09  6:25     ` Jiri Pirko
2019-08-09 15:40       ` Roopa Prabhu
2019-08-09 15:46         ` Michal Kubecek
2019-08-10 13:46           ` Roopa Prabhu
2019-08-10 15:50             ` Michal Kubecek
2019-08-10 19:39               ` Roopa Prabhu
2019-08-11 22:10                 ` Michal Kubecek
2019-08-12 15:21                   ` Roopa Prabhu
2019-08-12 15:43                     ` Michal Kubecek
2019-08-09 16:14         ` David Ahern
2019-08-10  6:30           ` Jiri Pirko
2019-08-12  1:34             ` David Ahern
2019-08-12  1:37               ` David Ahern
2019-08-12  8:31                 ` Jiri Pirko
2019-08-12 15:13                   ` Roopa Prabhu
2019-08-12 21:43                     ` Jakub Kicinski
2019-08-13  0:29                       ` David Ahern
2019-08-13  6:53                         ` Jiri Pirko
2019-08-13  6:51                     ` Jiri Pirko
2019-08-12 15:40                   ` Stephen Hemminger
2019-08-12 16:23                     ` Roopa Prabhu
2019-08-13  6:55                     ` Jiri Pirko
2019-08-12 16:01                   ` David Ahern
2019-08-13  6:56                     ` Jiri Pirko
2019-08-26 16:09                       ` Jiri Pirko
2019-08-26 16:55                         ` Jakub Kicinski
2019-08-26 21:46                           ` David Ahern
2019-08-26 22:15                             ` Jakub Kicinski
2019-08-26 22:18                               ` David Miller
2019-08-26 22:24                                 ` David Ahern
2019-08-26 22:25                                   ` David Miller
2019-08-27  0:17                                     ` David Ahern
2019-08-27  5:09                                       ` Michal Kubecek
2019-08-27  7:08                                 ` Jiri Pirko
2019-08-27  8:22                                   ` David Miller
2019-08-27  9:35                                     ` Jiri Pirko
2019-08-27 15:14                                       ` Roopa Prabhu
2019-08-28  7:07                                         ` Jiri Pirko
2019-08-29  4:36                                           ` Roopa Prabhu
2019-08-29  5:26                                             ` Michal Kubecek
2019-08-30 14:35                                               ` Roopa Prabhu
2019-08-30 14:47                                                 ` David Ahern
2019-08-30 17:04                                                   ` Jiri Pirko
2019-08-30 14:49                                                 ` Michal Kubecek
2019-08-30 17:03                                                 ` Jiri Pirko
2019-09-12 11:59                                                   ` Jiri Pirko
2019-09-13  8:21                                                     ` Jiri Pirko
2019-09-13 14:50                                                     ` Jiri Pirko
2019-08-27  4:55                             ` Michal Kubecek
2019-08-27 13:43                               ` David Ahern
2019-08-10  6:32         ` Jiri Pirko
2019-07-19 11:00 ` [patch net-next rfc 4/7] net: rtnetlink: put alternative names to getlink message Jiri Pirko
2019-07-20  3:59   ` Jakub Kicinski
2019-07-20  7:17     ` Jiri Pirko
2019-07-19 11:00 ` [patch net-next rfc 5/7] net: rtnetlink: unify the code in __rtnl_newlink get dev with the rest Jiri Pirko
2019-07-19 11:00 ` [patch net-next rfc 6/7] net: rtnetlink: introduce helper to get net_device instance by ifname Jiri Pirko
2019-07-19 11:00 ` [patch net-next rfc 7/7] net: rtnetlink: add possibility to use alternative names as message handle Jiri Pirko
2019-07-20  3:59   ` Jakub Kicinski
2019-07-20  7:22     ` Jiri Pirko
2019-07-19 11:03 ` [patch iproute2 rfc 1/2] ip: add support for alternative name addition/deletion/list Jiri Pirko
2019-07-19 11:03 ` [patch iproute2 rfc 2/2] ip: allow to use alternative names as handle Jiri Pirko
2019-07-19 16:31 ` [patch net-next rfc 0/7] net: introduce alternative names for network interfaces Stephen Hemminger
2019-07-19 19:16   ` Jiri Pirko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190719110029.29466-4-jiri@resnulli.us \
    --to=jiri@resnulli.us \
    --cc=andrew@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=dcbw@redhat.com \
    --cc=dsahern@gmail.com \
    --cc=jakub.kicinski@netronome.com \
    --cc=mkubecek@suse.cz \
    --cc=mlxsw@mellanox.com \
    --cc=netdev@vger.kernel.org \
    --cc=parav@mellanox.com \
    --cc=saeedm@mellanox.com \
    --cc=sthemmin@microsoft.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).