Skip to content

Commit 3d589f9

Browse files
author
CKI Backport Bot
committed
netlink: add IPv6 anycast join/leave notifications
JIRA: https://issues.redhat.com/browse/RHEL-84540 commit 33d97a0 Author: Yuyang Huang <yuyanghuang@google.com> Date: Tue Jan 7 20:43:55 2025 +0900 netlink: add IPv6 anycast join/leave notifications This change introduces a mechanism for notifying userspace applications about changes to IPv6 anycast addresses via netlink. It includes: * Addition and deletion of IPv6 anycast addresses are reported using RTM_NEWANYCAST and RTM_DELANYCAST. * A new netlink group (RTNLGRP_IPV6_ACADDR) for subscribing to these notifications. This enables user space applications(e.g. ip monitor) to efficiently track anycast addresses through netlink messages, improving metrics collection and system monitoring. It also unlocks the potential for advanced anycast management in user space, such as hardware offload control and fine grained network control. Cc: Maciej Żenczykowski <maze@google.com> Cc: Lorenzo Colitti <lorenzo@google.com> Signed-off-by: Yuyang Huang <yuyanghuang@google.com> Reviewed-by: David Ahern <dsahern@kernel.org> Link: https://patch.msgid.link/20250107114355.1766086-1-yuyanghuang@google.com Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com>
1 parent 277aa23 commit 3d589f9

File tree

4 files changed

+48
-4
lines changed

4 files changed

+48
-4
lines changed

include/net/addrconf.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,4 +546,7 @@ int inet6_fill_ifmcaddr(struct sk_buff *skb,
546546
const struct ifmcaddr6 *ifmca,
547547
struct inet6_fill_args *args);
548548

549+
int inet6_fill_ifacaddr(struct sk_buff *skb,
550+
const struct ifacaddr6 *ifaca,
551+
struct inet6_fill_args *args);
549552
#endif

include/uapi/linux/rtnetlink.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,11 @@ enum {
100100
RTM_GETMULTICAST,
101101
#define RTM_GETMULTICAST RTM_GETMULTICAST
102102

103-
RTM_GETANYCAST = 62,
103+
RTM_NEWANYCAST = 60,
104+
#define RTM_NEWANYCAST RTM_NEWANYCAST
105+
RTM_DELANYCAST,
106+
#define RTM_DELANYCAST RTM_DELANYCAST
107+
RTM_GETANYCAST,
104108
#define RTM_GETANYCAST RTM_GETANYCAST
105109

106110
RTM_NEWNEIGHTBL = 64,
@@ -782,6 +786,8 @@ enum rtnetlink_groups {
782786
#define RTNLGRP_IPV4_MCADDR RTNLGRP_IPV4_MCADDR
783787
RTNLGRP_IPV6_MCADDR,
784788
#define RTNLGRP_IPV6_MCADDR RTNLGRP_IPV6_MCADDR
789+
RTNLGRP_IPV6_ACADDR,
790+
#define RTNLGRP_IPV6_ACADDR RTNLGRP_IPV6_ACADDR
785791
__RTNLGRP_MAX
786792
};
787793
#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)

net/ipv6/addrconf.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5243,9 +5243,9 @@ int inet6_fill_ifmcaddr(struct sk_buff *skb,
52435243
return 0;
52445244
}
52455245

5246-
static int inet6_fill_ifacaddr(struct sk_buff *skb,
5247-
const struct ifacaddr6 *ifaca,
5248-
struct inet6_fill_args *args)
5246+
int inet6_fill_ifacaddr(struct sk_buff *skb,
5247+
const struct ifacaddr6 *ifaca,
5248+
struct inet6_fill_args *args)
52495249
{
52505250
struct net_device *dev = fib6_info_nh_dev(ifaca->aca_rt);
52515251
int ifindex = dev ? dev->ifindex : 1;

net/ipv6/anycast.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,37 @@ static struct ifacaddr6 *aca_alloc(struct fib6_info *f6i,
278278
return aca;
279279
}
280280

281+
static void inet6_ifacaddr_notify(struct net_device *dev,
282+
const struct ifacaddr6 *ifaca, int event)
283+
{
284+
struct inet6_fill_args fillargs = {
285+
.event = event,
286+
.netnsid = -1,
287+
};
288+
struct net *net = dev_net(dev);
289+
struct sk_buff *skb;
290+
int err = -ENOMEM;
291+
292+
skb = nlmsg_new(NLMSG_ALIGN(sizeof(struct ifaddrmsg)) +
293+
nla_total_size(sizeof(struct in6_addr)) +
294+
nla_total_size(sizeof(struct ifa_cacheinfo)),
295+
GFP_KERNEL);
296+
if (!skb)
297+
goto error;
298+
299+
err = inet6_fill_ifacaddr(skb, ifaca, &fillargs);
300+
if (err < 0) {
301+
pr_err("Failed to fill in anycast addresses (err %d)\n", err);
302+
nlmsg_free(skb);
303+
goto error;
304+
}
305+
306+
rtnl_notify(skb, net, 0, RTNLGRP_IPV6_ACADDR, NULL, GFP_KERNEL);
307+
return;
308+
error:
309+
rtnl_set_sk_err(net, RTNLGRP_IPV6_ACADDR, err);
310+
}
311+
281312
/*
282313
* device anycast group inc (add if not found)
283314
*/
@@ -333,6 +364,8 @@ int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr)
333364

334365
addrconf_join_solict(idev->dev, &aca->aca_addr);
335366

367+
inet6_ifacaddr_notify(idev->dev, aca, RTM_NEWANYCAST);
368+
336369
aca_put(aca);
337370
return 0;
338371
out:
@@ -375,6 +408,8 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr)
375408

376409
ip6_del_rt(dev_net(idev->dev), aca->aca_rt, false);
377410

411+
inet6_ifacaddr_notify(idev->dev, aca, RTM_DELANYCAST);
412+
378413
aca_put(aca);
379414
return 0;
380415
}

0 commit comments

Comments
 (0)