Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Yuyang Huang and committed by
Paolo Abeni
33d97a07 e61e6c41

+48 -4
+3
include/net/addrconf.h
··· 546 546 const struct ifmcaddr6 *ifmca, 547 547 struct inet6_fill_args *args); 548 548 549 + int inet6_fill_ifacaddr(struct sk_buff *skb, 550 + const struct ifacaddr6 *ifaca, 551 + struct inet6_fill_args *args); 549 552 #endif
+7 -1
include/uapi/linux/rtnetlink.h
··· 100 100 RTM_GETMULTICAST, 101 101 #define RTM_GETMULTICAST RTM_GETMULTICAST 102 102 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, 104 108 #define RTM_GETANYCAST RTM_GETANYCAST 105 109 106 110 RTM_NEWNEIGHTBL = 64, ··· 787 783 #define RTNLGRP_IPV4_MCADDR RTNLGRP_IPV4_MCADDR 788 784 RTNLGRP_IPV6_MCADDR, 789 785 #define RTNLGRP_IPV6_MCADDR RTNLGRP_IPV6_MCADDR 786 + RTNLGRP_IPV6_ACADDR, 787 + #define RTNLGRP_IPV6_ACADDR RTNLGRP_IPV6_ACADDR 790 788 __RTNLGRP_MAX 791 789 }; 792 790 #define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
+3 -3
net/ipv6/addrconf.c
··· 5240 5240 return 0; 5241 5241 } 5242 5242 5243 - static int inet6_fill_ifacaddr(struct sk_buff *skb, 5244 - const struct ifacaddr6 *ifaca, 5245 - struct inet6_fill_args *args) 5243 + int inet6_fill_ifacaddr(struct sk_buff *skb, 5244 + const struct ifacaddr6 *ifaca, 5245 + struct inet6_fill_args *args) 5246 5246 { 5247 5247 struct net_device *dev = fib6_info_nh_dev(ifaca->aca_rt); 5248 5248 int ifindex = dev ? dev->ifindex : 1;
+35
net/ipv6/anycast.c
··· 278 278 return aca; 279 279 } 280 280 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 + 281 312 /* 282 313 * device anycast group inc (add if not found) 283 314 */ ··· 364 333 365 334 addrconf_join_solict(idev->dev, &aca->aca_addr); 366 335 336 + inet6_ifacaddr_notify(idev->dev, aca, RTM_NEWANYCAST); 337 + 367 338 aca_put(aca); 368 339 return 0; 369 340 out: ··· 407 374 addrconf_leave_solict(idev, &aca->aca_addr); 408 375 409 376 ip6_del_rt(dev_net(idev->dev), aca->aca_rt, false); 377 + 378 + inet6_ifacaddr_notify(idev->dev, aca, RTM_DELANYCAST); 410 379 411 380 aca_put(aca); 412 381 return 0;