[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <274d34670c9cc79cb387b4fae2bd1ca70561a9c1.1678448186.git.petrm@nvidia.com>
Date: Fri, 10 Mar 2023 12:44:55 +0100
From: Petr Machata <petrm@...dia.com>
To: "David S. Miller" <davem@...emloft.net>,
Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>,
Paolo Abeni <pabeni@...hat.com>, <netdev@...r.kernel.org>
CC: David Ahern <dsahern@...nel.org>, Shuah Khan <shuah@...nel.org>,
"Ido Schimmel" <idosch@...dia.com>,
Petr Machata <petrm@...dia.com>, <mlxsw@...dia.com>
Subject: [PATCH net-next 2/5] net: ipv6: addrconf: Support IPv6 address labels
IPv4 addresses can be tagged with label strings. Unlike IPv6 addrlabels,
which are used for prioritization of IPv6 addresses, these "ip address
labels" are simply tags that the userspace can assign to IP addresses
arbitrarily.
In this patch, add to IPv6 support for address labels. This adds the
necessary fields, but does not expose them through UAPI yet -- that will
happen in the next patch.
When not given, the default address label is the same as the netdevice
name. In IPv4, this behavior is due to Linux 2.0 compatibility. While this
is probably not a concern anymore, having the same behavior in IPv6 as we
have in IPv4 will make the feature easier to understand.
Also similarly to IPv4, when address label is part of a request to remove
an address, the label given has to match the label at the address, or else
the address is not removed.
Signed-off-by: Petr Machata <petrm@...dia.com>
Reviewed-by: Ido Schimmel <idosch@...dia.com>
---
include/net/addrconf.h | 2 ++
include/net/if_inet6.h | 1 +
net/ipv6/addrconf.c | 14 ++++++++++++--
3 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index c04f359655b8..52214a46cc7e 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -73,6 +73,8 @@ struct ifa6_config {
u32 preferred_lft;
u32 valid_lft;
u16 scope;
+ char ifa_label[IFNAMSIZ];
+ bool has_ifa_label;
};
int addrconf_init(void);
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index c8490729b4ae..2cfb2ac1d1f7 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -83,6 +83,7 @@ struct inet6_ifaddr {
struct rcu_head rcu;
struct in6_addr peer_addr;
+ char ifa_label[IFNAMSIZ];
};
struct ip6_sf_socklist {
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index faa47f9ea73a..5f4f16bb6ef0 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1134,6 +1134,11 @@ ipv6_add_addr(struct inet6_dev *idev, struct ifa6_config *cfg,
ifa->rt = f6i;
ifa->idev = idev;
+ if (cfg->has_ifa_label)
+ memcpy(ifa->ifa_label, cfg->ifa_label, sizeof(cfg->ifa_label));
+ else
+ memcpy(ifa->ifa_label, idev->dev->name, IFNAMSIZ);
+
in6_dev_hold(idev);
/* For caller */
@@ -3000,6 +3005,7 @@ static int inet6_addr_add(struct net *net, int ifindex,
}
static int inet6_addr_del(struct net *net, int ifindex, u32 ifa_flags,
+ const char *ifa_label,
const struct in6_addr *pfx, unsigned int plen)
{
struct inet6_ifaddr *ifp;
@@ -3019,6 +3025,8 @@ static int inet6_addr_del(struct net *net, int ifindex, u32 ifa_flags,
read_lock_bh(&idev->lock);
list_for_each_entry(ifp, &idev->addr_list, if_list) {
+ if (ifa_label && strcmp(ifp->ifa_label, ifa_label))
+ continue;
if (ifp->prefix_len == plen &&
ipv6_addr_equal(pfx, &ifp->addr)) {
in6_ifa_hold(ifp);
@@ -3079,7 +3087,7 @@ int addrconf_del_ifaddr(struct net *net, void __user *arg)
return -EFAULT;
rtnl_lock();
- err = inet6_addr_del(net, ireq.ifr6_ifindex, 0, &ireq.ifr6_addr,
+ err = inet6_addr_del(net, ireq.ifr6_ifindex, 0, NULL, &ireq.ifr6_addr,
ireq.ifr6_prefixlen);
rtnl_unlock();
return err;
@@ -4691,7 +4699,7 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh,
/* We ignore other flags so far. */
ifa_flags &= IFA_F_MANAGETEMPADDR;
- return inet6_addr_del(net, ifm->ifa_index, ifa_flags, pfx,
+ return inet6_addr_del(net, ifm->ifa_index, ifa_flags, NULL, pfx,
ifm->ifa_prefixlen);
}
@@ -4792,6 +4800,8 @@ static int inet6_addr_modify(struct net *net, struct inet6_ifaddr *ifp,
if (cfg->rt_priority && cfg->rt_priority != ifp->rt_priority)
ifp->rt_priority = cfg->rt_priority;
+ if (cfg->has_ifa_label)
+ memcpy(ifp->ifa_label, cfg->ifa_label, IFNAMSIZ);
if (new_peer)
ifp->peer_addr = *cfg->peer_pfx;
--
2.39.0
Powered by blists - more mailing lists