Fri, Aug 09, 2019 at 06:11:30AM CEST, ro...@cumulusnetworks.com wrote: >On Fri, Jul 19, 2019 at 4:00 AM Jiri Pirko <j...@resnulli.us> wrote: >> >> From: Jiri Pirko <j...@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 <j...@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 >> + > >I might have missed the prior discussion, why do we need new commands >?. can't this simply be part of RTM_*LINK and we use RTM_SETLINK to >set alternate names ?
How? This is to add/remove. How do you suggest to to add/remove by setlink? > > > >> __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 >>