From: Eric Dumazet <edumazet@google.com>
To: "David S . Miller" <davem@davemloft.net>,
Jakub Kicinski <kuba@kernel.org>,
Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>,
Kuniyuki Iwashima <kuniyu@google.com>,
netdev@vger.kernel.org, eric.dumazet@gmail.com,
Eric Dumazet <edumazet@google.com>,
Ido Schimmel <idosch@nvidia.com>
Subject: [PATCH net-next] ipv6: add IPV6_CALL() helper
Date: Mon, 2 Mar 2026 15:42:01 +0000 [thread overview]
Message-ID: <20260302154201.1621117-1-edumazet@google.com> (raw)
ipv6_stub use is racy, we should add READ_ONCE() and WRITE_ONCE(),
even if this pointer can only change once.
Add IPV6_CALL() macro to factorize the READ_ONCE(), and perform
direct calls when CONFIG_IPV6=y.
ipv6_stub->nd_tbl will need a separate patch.
$ size vmlinux.old vmlinux.new
text data bss dec hex filename
37705007 23152761 4747540 65605308 3e90ebc vmlinux.0
37702861 23152665 4747540 65603066 3e905fa vmlinux
$ scripts/bloat-o-meter -t vmlinux.old vmlinux.new
add/remove: 0/22 grow/shrink: 0/25 up/down: 0/-1025 (-1025)
Function old new delta
nexthop_select_path 832 828 -4
ipv4_confirm_neigh 426 422 -4
fib_detect_death 348 344 -4
br_do_suppress_nd 671 667 -4
udp_lib_setsockopt 893 888 -5
set_xfrm_gro_udp_encap_rcv 117 112 -5
__ipv6_neigh_lookup_noref_stub 336 328 -8
udp_tunnel_encap_enable 57 45 -12
udp_tunnel6_dst_lookup 465 453 -12
setup_udp_tunnel_sock 251 239 -12
nexthop_free_rcu 254 242 -12
bpf_xmit 1203 1191 -12
bpf_input 500 488 -12
__remove_nexthop 1705 1693 -12
xfrm6_tunnel_check_size 631 616 -15
sch_frag_xmit_hook 1233 1218 -15
icmp_build_probe 922 907 -15
eafnosupport_fib6_select_path 15 - -15
ip_neigh_gw6 708 692 -16
__pfx_eafnosupport_ipv6_route_input 16 - -16
__pfx_eafnosupport_ipv6_fragment 16 - -16
__pfx_eafnosupport_ipv6_dst_lookup_flow 16 - -16
__pfx_eafnosupport_ipv6_dev_find 16 - -16
__pfx_eafnosupport_ip6_mtu_from_fib6 16 - -16
__pfx_eafnosupport_ip6_del_rt 16 - -16
__pfx_eafnosupport_fib6_table_lookup 16 - -16
__pfx_eafnosupport_fib6_select_path 16 - -16
__pfx_eafnosupport_fib6_nh_init 16 - -16
__pfx_eafnosupport_fib6_lookup 16 - -16
__pfx_eafnosupport_fib6_get_table 16 - -16
eafnosupport_ip6_mtu_from_fib6 17 - -17
eafnosupport_fib6_get_table 17 - -17
skb_do_redirect 2878 2858 -20
eafnosupport_ipv6_route_input 20 - -20
eafnosupport_ip6_del_rt 20 - -20
eafnosupport_fib6_table_lookup 20 - -20
eafnosupport_fib6_lookup 20 - -20
eafnosupport_ipv6_dst_lookup_flow 22 - -22
eafnosupport_ipv6_dev_find 22 - -22
nh_rt_cache_flush 191 167 -24
fib_check_nh 1580 1556 -24
nat_keepalive_work_single 1319 1292 -27
eafnosupport_ipv6_fragment 35 - -35
eafnosupport_fib6_nh_init 49 - -49
rtm_new_nexthop 8495 8441 -54
bpf_ipv6_fib_lookup 1107 1043 -64
.compoundliteral 5792 5592 -200
Total: Before=25219423, After=25218398, chg -0.00%
Signed-off-by: Eric Dumazet <edumazet@google.com>
CC: Ido Schimmel <idosch@nvidia.com>
---
v2: rename fib6_update_sernum to fib6_update_sernum_stub (Jakub feedback)
v1: https://lore.kernel.org/netdev/20260301162514.3347319-1-edumazet@google.com/
drivers/infiniband/core/addr.c | 2 +-
drivers/infiniband/sw/rxe/rxe_net.c | 6 ++---
.../ethernet/mellanox/mlx5/core/en/tc_tun.c | 4 +--
.../ethernet/netronome/nfp/flower/action.c | 2 +-
.../netronome/nfp/flower/tunnel_conf.c | 6 ++---
drivers/net/ethernet/sfc/tc_encap_actions.c | 4 +--
drivers/net/gtp.c | 2 +-
drivers/net/ovpn/peer.c | 4 +--
drivers/net/ovpn/udp.c | 2 +-
drivers/net/usb/cdc_mbim.c | 2 +-
drivers/net/vxlan/vxlan_multicast.c | 4 +--
drivers/net/wireguard/socket.c | 4 +--
include/net/ipv6_stubs.h | 26 +++++++++++++------
include/net/udp_tunnel.h | 2 +-
net/core/filter.c | 12 ++++-----
net/core/lwt_bpf.c | 4 +--
net/ipv4/fib_semantics.c | 4 +--
net/ipv4/icmp.c | 5 +++-
net/ipv4/nexthop.c | 15 ++++++-----
net/ipv4/udp.c | 4 +--
net/ipv6/addrconf_core.c | 10 ++++---
net/ipv6/af_inet6.c | 14 +++++-----
net/ipv6/ip6_fib.c | 2 +-
net/ipv6/ip6_output.c | 1 +
net/ipv6/ip6_udp_tunnel.c | 3 +--
net/ipv6/ndisc.c | 1 +
net/mpls/af_mpls.c | 2 +-
net/openvswitch/actions.c | 2 +-
net/sched/sch_frag.c | 5 ++--
net/tipc/udp_media.c | 8 +++---
net/xfrm/espintcp.c | 2 +-
net/xfrm/xfrm_nat_keepalive.c | 4 +--
net/xfrm/xfrm_output.c | 2 +-
33 files changed, 96 insertions(+), 74 deletions(-)
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 866746695712aeae425100eefb231e44d52d52d4..5de8fd283ac9b0dbc07d5851f05d15e84c3645e3 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -411,7 +411,7 @@ static int addr6_resolve(struct sockaddr *src_sock,
fl6.saddr = src_in->sin6_addr;
fl6.flowi6_oif = addr->bound_dev_if;
- dst = ipv6_stub->ipv6_dst_lookup_flow(addr->net, NULL, &fl6, NULL);
+ dst = IPV6_CALL(ip6_dst_lookup_flow)(addr->net, NULL, &fl6, NULL);
if (IS_ERR(dst))
return PTR_ERR(dst);
diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c
index 0bd0902b11f734acbbb9fa521bf117bbf6a7710d..d5c81705c801bcd618520d143bff023b65b7132a 100644
--- a/drivers/infiniband/sw/rxe/rxe_net.c
+++ b/drivers/infiniband/sw/rxe/rxe_net.c
@@ -138,9 +138,9 @@ static struct dst_entry *rxe_find_route6(struct rxe_qp *qp,
memcpy(&fl6.daddr, daddr, sizeof(*daddr));
fl6.flowi6_proto = IPPROTO_UDP;
- ndst = ipv6_stub->ipv6_dst_lookup_flow(sock_net(recv_sockets.sk6->sk),
- recv_sockets.sk6->sk, &fl6,
- NULL);
+ ndst = IPV6_CALL(ip6_dst_lookup_flow)(sock_net(recv_sockets.sk6->sk),
+ recv_sockets.sk6->sk, &fl6,
+ NULL);
if (IS_ERR(ndst)) {
rxe_dbg_qp(qp, "no route to %pI6\n", daddr);
return NULL;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
index a14f216048cd2dbe37d0f905c55138ab2c744a42..45462aa0960b9fb23885b0bd6b8b398880369299 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
@@ -453,8 +453,8 @@ static int mlx5e_route_lookup_ipv6_get(struct mlx5e_priv *priv,
if (tunnel && tunnel->get_remote_ifindex)
attr->fl.fl6.flowi6_oif = tunnel->get_remote_ifindex(dev);
- dst = ipv6_stub->ipv6_dst_lookup_flow(dev_net(dev), NULL, &attr->fl.fl6,
- NULL);
+ dst = IPV6_CALL(ip6_dst_lookup_flow)(dev_net(dev), NULL, &attr->fl.fl6,
+ NULL);
if (IS_ERR(dst))
return PTR_ERR(dst);
diff --git a/drivers/net/ethernet/netronome/nfp/flower/action.c b/drivers/net/ethernet/netronome/nfp/flower/action.c
index aca2a7417af37c52fd26278139263760a781e72b..71da2f6fdfa5364d704ac140967b41bf0dfc39e9 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/action.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/action.c
@@ -470,7 +470,7 @@ nfp_fl_set_tun(struct nfp_app *app, struct nfp_fl_set_tun *set_tun,
flow.daddr = ip_tun->key.u.ipv6.dst;
flow.flowi4_proto = IPPROTO_UDP;
- dst = ipv6_stub->ipv6_dst_lookup_flow(net, NULL, &flow, NULL);
+ dst = IPV6_CALL(ip6_dst_lookup_flow)(net, NULL, &flow, NULL);
if (!IS_ERR(dst)) {
set_tun->ttl = ip6_dst_hoplimit(dst);
dst_release(dst);
diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
index 0cef0e2b85d09de991d242dce9f6a174bc6d4457..a6dab3fc00bf355be2b32ab7c2ccef2950924677 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
@@ -650,7 +650,7 @@ static void nfp_tun_neigh_update(struct work_struct *work)
flow6.daddr = *(struct in6_addr *)n->primary_key;
if (!neigh_invalid) {
struct dst_entry *dst;
- /* Use ipv6_dst_lookup_flow to populate flow6->saddr
+ /* Use ip6_dst_lookup_flow to populate flow6->saddr
* and other fields. This information is only needed
* for new entries, lookup can be skipped when an entry
* gets invalidated - as only the daddr is needed for
@@ -815,8 +815,8 @@ void nfp_tunnel_request_route_v6(struct nfp_app *app, struct sk_buff *skb)
flow.flowi6_proto = IPPROTO_UDP;
#if IS_ENABLED(CONFIG_INET) && IS_ENABLED(CONFIG_IPV6)
- dst = ipv6_stub->ipv6_dst_lookup_flow(dev_net(netdev), NULL, &flow,
- NULL);
+ dst = IPV6_CALL(ip6_dst_lookup_flow)(dev_net(netdev), NULL, &flow,
+ NULL);
if (IS_ERR(dst))
goto fail_rcu_unlock;
#else
diff --git a/drivers/net/ethernet/sfc/tc_encap_actions.c b/drivers/net/ethernet/sfc/tc_encap_actions.c
index da35705cc5e19d0e2435407bdd2cf8e273e22b59..be5dea4441d47a72590785cbdd7b604334926ef9 100644
--- a/drivers/net/ethernet/sfc/tc_encap_actions.c
+++ b/drivers/net/ethernet/sfc/tc_encap_actions.c
@@ -149,8 +149,8 @@ static int efx_bind_neigh(struct efx_nic *efx,
#if IS_ENABLED(CONFIG_IPV6)
struct dst_entry *dst;
- dst = ipv6_stub->ipv6_dst_lookup_flow(net, NULL, &flow6,
- NULL);
+ dst = IPV6_CALL(ip6_dst_lookup_flow)(net, NULL, &flow6,
+ NULL);
rc = PTR_ERR_OR_ZERO(dst);
if (rc) {
NL_SET_ERR_MSG_MOD(extack, "Failed to lookup route for IPv6 encap");
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index e8949f5562090513e2d95ea01f3d463356e58cfb..e42cedaf413261eedd9dc9982be6423bbbfa51b6 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -374,7 +374,7 @@ static struct rt6_info *ip6_route_output_gtp(struct net *net,
fl6->saddr = *saddr;
fl6->flowi6_proto = sk->sk_protocol;
- dst = ipv6_stub->ipv6_dst_lookup_flow(net, sk, fl6, NULL);
+ dst = IPV6_CALL(ip6_dst_lookup_flow)(net, sk, fl6, NULL);
if (IS_ERR(dst))
return ERR_PTR(-ENETUNREACH);
diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
index 3716a1d828015e2f6cdfa75d1a81c89d1f32b4ce..2f9dec27bdeee38a6c021d495a717a2803e08966 100644
--- a/drivers/net/ovpn/peer.c
+++ b/drivers/net/ovpn/peer.c
@@ -821,8 +821,8 @@ static struct in6_addr ovpn_nexthop_from_rt6(struct ovpn_priv *ovpn,
.daddr = dest,
};
- entry = ipv6_stub->ipv6_dst_lookup_flow(dev_net(ovpn->dev), NULL, &fl,
- NULL);
+ entry = IPV6_CALL(ip6_dst_lookup_flow)(dev_net(ovpn->dev), NULL, &fl,
+ NULL);
if (IS_ERR(entry)) {
net_dbg_ratelimited("%s: no route to host %pI6c\n",
netdev_name(ovpn->dev), &dest);
diff --git a/drivers/net/ovpn/udp.c b/drivers/net/ovpn/udp.c
index 272b535ecaad4c75ff2aa9d4589b4cfa36a0dea9..20db16a37777e82d7c5c6ac2b0400863bff8b7d9 100644
--- a/drivers/net/ovpn/udp.c
+++ b/drivers/net/ovpn/udp.c
@@ -251,7 +251,7 @@ static int ovpn_udp6_output(struct ovpn_peer *peer, struct ovpn_bind *bind,
dst_cache_reset(cache);
}
- dst = ipv6_stub->ipv6_dst_lookup_flow(sock_net(sk), sk, &fl, NULL);
+ dst = IPV6_CALL(ip6_dst_lookup_flow)(sock_net(sk), sk, &fl, NULL);
if (IS_ERR(dst)) {
ret = PTR_ERR(dst);
net_dbg_ratelimited("%s: no route to host %pISpc: %d\n",
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index dbf01210b0e783ddc3c6961663ebf8d4574b6bf0..e645c9c33ee781eae975d7d4be3d14050d2851a5 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -343,7 +343,7 @@ static void do_neigh_solicit(struct usbnet *dev, u8 *buf, u16 tci)
in6_dev_put(in6_dev);
/* ipv6_stub != NULL if in6_dev_get returned an inet6_dev */
- ipv6_stub->ndisc_send_na(netdev, &iph->saddr, &msg->target,
+ IPV6_CALL(ndisc_send_na)(netdev, &iph->saddr, &msg->target,
is_router /* router */,
true /* solicited */,
false /* override */,
diff --git a/drivers/net/vxlan/vxlan_multicast.c b/drivers/net/vxlan/vxlan_multicast.c
index a7f2d67dc61b80197f1f2c9ec978e1b7d984e4e2..54e1b275b81263ca7b815a4b95c4ecd56b161358 100644
--- a/drivers/net/vxlan/vxlan_multicast.c
+++ b/drivers/net/vxlan/vxlan_multicast.c
@@ -39,7 +39,7 @@ int vxlan_igmp_join(struct vxlan_dev *vxlan, union vxlan_addr *rip,
sk = sock6->sock->sk;
lock_sock(sk);
- ret = ipv6_stub->ipv6_sock_mc_join(sk, ifindex,
+ ret = IPV6_CALL(ipv6_sock_mc_join)(sk, ifindex,
&ip->sin6.sin6_addr);
release_sock(sk);
#endif
@@ -73,7 +73,7 @@ int vxlan_igmp_leave(struct vxlan_dev *vxlan, union vxlan_addr *rip,
sk = sock6->sock->sk;
lock_sock(sk);
- ret = ipv6_stub->ipv6_sock_mc_drop(sk, ifindex,
+ ret = IPV6_CALL(ipv6_sock_mc_drop)(sk, ifindex,
&ip->sin6.sin6_addr);
release_sock(sk);
#endif
diff --git a/drivers/net/wireguard/socket.c b/drivers/net/wireguard/socket.c
index 253488f8c00f887d68b5c592e9f09e1a1777d9cc..66901b0e76c8b628faaf73104fc44ef6b96ab2f2 100644
--- a/drivers/net/wireguard/socket.c
+++ b/drivers/net/wireguard/socket.c
@@ -136,8 +136,8 @@ static int send6(struct wg_device *wg, struct sk_buff *skb,
if (cache)
dst_cache_reset(cache);
}
- dst = ipv6_stub->ipv6_dst_lookup_flow(sock_net(sock), sock, &fl,
- NULL);
+ dst = IPV6_CALL(ip6_dst_lookup_flow)(sock_net(sock), sock, &fl,
+ NULL);
if (IS_ERR(dst)) {
ret = PTR_ERR(dst);
net_dbg_ratelimited("%s: No route to %pISpfsc, error %d\n",
diff --git a/include/net/ipv6_stubs.h b/include/net/ipv6_stubs.h
index d3013e721b1441158e732b04d94078c0a7e9aa6a..285eb6b7ab1163aee6017f12f0bedb0dff42fe82 100644
--- a/include/net/ipv6_stubs.h
+++ b/include/net/ipv6_stubs.h
@@ -17,18 +17,22 @@ struct fib6_nh;
struct fib6_config;
struct fib6_result;
+int ipv6_route_input(struct sk_buff *skb);
+
/* This is ugly, ideally these symbols should be built
* into the core kernel.
*/
struct ipv6_stub {
+ struct neigh_table *nd_tbl;
+#if !defined(CONFIG_IPV6)
int (*ipv6_sock_mc_join)(struct sock *sk, int ifindex,
const struct in6_addr *addr);
int (*ipv6_sock_mc_drop)(struct sock *sk, int ifindex,
const struct in6_addr *addr);
- struct dst_entry *(*ipv6_dst_lookup_flow)(struct net *net,
- const struct sock *sk,
- struct flowi6 *fl6,
- const struct in6_addr *final_dst);
+ struct dst_entry *(*ip6_dst_lookup_flow)(struct net *net,
+ const struct sock *sk,
+ struct flowi6 *fl6,
+ const struct in6_addr *final_dst);
int (*ipv6_route_input)(struct sk_buff *skb);
struct fib6_table *(*fib6_get_table)(struct net *net, u32 id);
@@ -49,7 +53,7 @@ struct ipv6_stub {
struct netlink_ext_ack *extack);
void (*fib6_nh_release)(struct fib6_nh *fib6_nh);
void (*fib6_nh_release_dsts)(struct fib6_nh *fib6_nh);
- void (*fib6_update_sernum)(struct net *net, struct fib6_info *rt);
+ void (*fib6_update_sernum_stub)(struct net *net, struct fib6_info *rt);
int (*ip6_del_rt)(struct net *net, struct fib6_info *rt, bool skip_notify);
void (*fib6_rt_update)(struct net *net, struct fib6_info *rt,
struct nl_info *info);
@@ -67,14 +71,14 @@ struct ipv6_stub {
int (*xfrm6_rcv_encap)(struct sk_buff *skb, int nexthdr, __be32 spi,
int encap_type);
#endif
- struct neigh_table *nd_tbl;
- int (*ipv6_fragment)(struct net *net, struct sock *sk, struct sk_buff *skb,
- int (*output)(struct net *, struct sock *, struct sk_buff *));
+ int (*ip6_fragment)(struct net *net, struct sock *sk, struct sk_buff *skb,
+ int (*output)(struct net *, struct sock *, struct sk_buff *));
struct net_device *(*ipv6_dev_find)(struct net *net, const struct in6_addr *addr,
struct net_device *dev);
int (*ip6_xmit)(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
__u32 mark, struct ipv6_txoptions *opt, int tclass, u32 priority);
+#endif
};
extern const struct ipv6_stub *ipv6_stub __read_mostly;
@@ -99,4 +103,10 @@ struct ipv6_bpf_stub {
};
extern const struct ipv6_bpf_stub *ipv6_bpf_stub __read_mostly;
+#if defined(CONFIG_IPV6)
+#define IPV6_CALL(X) (X)
+#else
+#define IPV6_CALL(X) (READ_ONCE(ipv6_stub)->X)
+#endif
+
#endif
diff --git a/include/net/udp_tunnel.h b/include/net/udp_tunnel.h
index d9c6d04bb3b587d50397e83df087b39963ba5121..fade8bd88e87d8b994d8496c39209e565be4e587 100644
--- a/include/net/udp_tunnel.h
+++ b/include/net/udp_tunnel.h
@@ -230,7 +230,7 @@ static inline void udp_tunnel_encap_enable(struct sock *sk)
#if IS_ENABLED(CONFIG_IPV6)
if (READ_ONCE(sk->sk_family) == PF_INET6)
- ipv6_stub->udpv6_encap_enable();
+ IPV6_CALL(udpv6_encap_enable)();
#endif
udp_encap_enable();
}
diff --git a/net/core/filter.c b/net/core/filter.c
index 0d5d5a17acb2d62a171075d83ca302a52a5e4887..c9db6c70992af7a399d6c5ab3296244f46eadd72 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -2276,7 +2276,7 @@ static int __bpf_redirect_neigh_v6(struct sk_buff *skb, struct net_device *dev,
.saddr = ip6h->saddr,
};
- dst = ipv6_stub->ipv6_dst_lookup_flow(net, NULL, &fl6, NULL);
+ dst = IPV6_CALL(ip6_dst_lookup_flow)(net, NULL, &fl6, NULL);
if (IS_ERR(dst))
goto out_drop;
@@ -6281,11 +6281,11 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
params->tbid = 0;
}
- tb = ipv6_stub->fib6_get_table(net, tbid);
+ tb = IPV6_CALL(fib6_get_table)(net, tbid);
if (unlikely(!tb))
return BPF_FIB_LKUP_RET_NOT_FWDED;
- err = ipv6_stub->fib6_table_lookup(net, tb, oif, &fl6, &res,
+ err = IPV6_CALL(fib6_table_lookup)(net, tb, oif, &fl6, &res,
strict);
} else {
if (flags & BPF_FIB_LOOKUP_MARK)
@@ -6296,7 +6296,7 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
fl6.flowi6_tun_key.tun_id = 0;
fl6.flowi6_uid = sock_net_uid(net, NULL);
- err = ipv6_stub->fib6_lookup(net, oif, &fl6, &res, strict);
+ err = IPV6_CALL(fib6_lookup)(net, oif, &fl6, &res, strict);
}
if (unlikely(err || IS_ERR_OR_NULL(res.f6i) ||
@@ -6317,11 +6317,11 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
return BPF_FIB_LKUP_RET_NOT_FWDED;
}
- ipv6_stub->fib6_select_path(net, &res, &fl6, fl6.flowi6_oif,
+ IPV6_CALL(fib6_select_path)(net, &res, &fl6, fl6.flowi6_oif,
fl6.flowi6_oif != 0, NULL, strict);
if (check_mtu) {
- mtu = ipv6_stub->ip6_mtu_from_fib6(&res, dst, src);
+ mtu = IPV6_CALL(ip6_mtu_from_fib6)(&res, dst, src);
if (params->tot_len > mtu) {
params->mtu_result = mtu; /* union with tot_len */
return BPF_FIB_LKUP_RET_FRAG_NEEDED;
diff --git a/net/core/lwt_bpf.c b/net/core/lwt_bpf.c
index 9f40be0c3e71dd893b9eb86daa039aa42d81fffe..f0e97e086ea39df1bb01ff361a4080089550746b 100644
--- a/net/core/lwt_bpf.c
+++ b/net/core/lwt_bpf.c
@@ -103,7 +103,7 @@ static int bpf_lwt_input_reroute(struct sk_buff *skb)
dev_put(dev);
} else if (skb->protocol == htons(ETH_P_IPV6)) {
skb_dst_drop(skb);
- err = ipv6_stub->ipv6_route_input(skb);
+ err = IPV6_CALL(ipv6_route_input)(skb);
} else {
err = -EAFNOSUPPORT;
}
@@ -233,7 +233,7 @@ static int bpf_lwt_xmit_reroute(struct sk_buff *skb)
fl6.daddr = iph6->daddr;
fl6.saddr = iph6->saddr;
- dst = ipv6_stub->ipv6_dst_lookup_flow(net, skb->sk, &fl6, NULL);
+ dst = IPV6_CALL(ip6_dst_lookup_flow)(net, skb->sk, &fl6, NULL);
if (IS_ERR(dst)) {
err = PTR_ERR(dst);
goto err;
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 01cb587866d8f8d02c6bacce565c6e9f46afebeb..4dfd0c4526fc1fb374befc305270608833f32bba 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -1083,7 +1083,7 @@ static int fib_check_nh_v6_gw(struct net *net, struct fib_nh *nh,
struct fib6_nh fib6_nh = {};
int err;
- err = ipv6_stub->fib6_nh_init(net, &fib6_nh, &cfg, GFP_KERNEL, extack);
+ err = IPV6_CALL(fib6_nh_init)(net, &fib6_nh, &cfg, GFP_KERNEL, extack);
if (!err) {
nh->fib_nh_dev = fib6_nh.fib_nh_dev;
netdev_hold(nh->fib_nh_dev, &nh->fib_nh_dev_tracker,
@@ -1091,7 +1091,7 @@ static int fib_check_nh_v6_gw(struct net *net, struct fib_nh *nh,
nh->fib_nh_oif = nh->fib_nh_dev->ifindex;
nh->fib_nh_scope = RT_SCOPE_LINK;
- ipv6_stub->fib6_nh_release(&fib6_nh);
+ IPV6_CALL(fib6_nh_release)(&fib6_nh);
}
return err;
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index ac6d2ffc1963f1a7650faee8f054a51c05071d4a..98e962347ca03f500448541009173000d6be5a85 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -1342,7 +1342,10 @@ bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr)
case ICMP_AFI_IP6:
if (iio->ident.addr.ctype3_hdr.addrlen != sizeof(struct in6_addr))
goto send_mal_query;
- dev = ipv6_stub->ipv6_dev_find(net, &iio->ident.addr.ip_addr.ipv6_addr, dev);
+ dev = IPV6_CALL(ipv6_dev_find)(
+ net,
+ &iio->ident.addr.ip_addr.ipv6_addr,
+ dev);
dev_hold(dev);
break;
#endif
diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c
index 1aa2b05ee8de856d187b198beb9af699921caa49..2c157679394ab2cbc55f1b11a5559a1436c1508b 100644
--- a/net/ipv4/nexthop.c
+++ b/net/ipv4/nexthop.c
@@ -16,6 +16,7 @@
#include <net/nexthop.h>
#include <net/route.h>
#include <net/sock.h>
+#include <net/ip6_route.h>
#define NH_RES_DEFAULT_IDLE_TIMER (120 * HZ)
#define NH_RES_DEFAULT_UNBALANCED_TIMER 0 /* No forced rebalancing. */
@@ -510,7 +511,7 @@ static void nexthop_free_single(struct nexthop *nh)
fib_nh_release(nh->net, &nhi->fib_nh);
break;
case AF_INET6:
- ipv6_stub->fib6_nh_release(&nhi->fib6_nh);
+ IPV6_CALL(fib6_nh_release)(&nhi->fib6_nh);
break;
}
kfree(nhi);
@@ -2143,7 +2144,7 @@ static void __remove_nexthop_fib(struct net *net, struct nexthop *nh)
fib6_info_hold(f6i);
spin_unlock_bh(&nh->lock);
- ipv6_stub->ip6_del_rt(net, f6i,
+ IPV6_CALL(ip6_del_rt)(net, f6i,
!READ_ONCE(net->ipv4.sysctl_nexthop_compat_mode));
spin_lock_bh(&nh->lock);
@@ -2201,7 +2202,7 @@ static void nh_rt_cache_flush(struct net *net, struct nexthop *nh,
rt_cache_flush(net);
list_for_each_entry(f6i, &nh->f6i_list, nh_list)
- ipv6_stub->fib6_update_sernum(net, f6i);
+ IPV6_CALL(fib6_update_sernum_stub)(net, f6i);
/* if an IPv6 group was replaced, we have to release all old
* dsts to make sure all refcounts are released
@@ -2215,7 +2216,7 @@ static void nh_rt_cache_flush(struct net *net, struct nexthop *nh,
struct nh_info *nhi = rtnl_dereference(nhge->nh->nh_info);
if (nhi->family == AF_INET6)
- ipv6_stub->fib6_nh_release_dsts(&nhi->fib6_nh);
+ IPV6_CALL(fib6_nh_release_dsts)(&nhi->fib6_nh);
}
}
@@ -2496,7 +2497,7 @@ static void __nexthop_replace_notify(struct net *net, struct nexthop *nh,
}
list_for_each_entry(f6i, &nh->f6i_list, nh_list)
- ipv6_stub->fib6_rt_update(net, f6i, info);
+ IPV6_CALL(fib6_rt_update)(net, f6i, info);
}
/* send RTM_NEWROUTE with REPLACE flag set for all FIB entries
@@ -2869,13 +2870,13 @@ static int nh_create_ipv6(struct net *net, struct nexthop *nh,
fib6_cfg.fc_flags |= RTF_GATEWAY;
/* sets nh_dev if successful */
- err = ipv6_stub->fib6_nh_init(net, fib6_nh, &fib6_cfg, GFP_KERNEL,
+ err = IPV6_CALL(fib6_nh_init)(net, fib6_nh, &fib6_cfg, GFP_KERNEL,
extack);
if (err) {
/* IPv6 is not enabled, don't call fib6_nh_release */
if (err == -EAFNOSUPPORT)
goto out;
- ipv6_stub->fib6_nh_release(fib6_nh);
+ IPV6_CALL(fib6_nh_release)(fib6_nh);
} else {
nh->nh_flags = fib6_nh->fib_nh_flags;
}
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 6c6b68a66dcd3b3d8f1747fead868c195e04a0a9..d808742d5994bd3d27780e43186d4cf43466745d 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -2966,7 +2966,7 @@ static void set_xfrm_gro_udp_encap_rcv(__u16 encap_type, unsigned short family,
if (udp_test_bit(GRO_ENABLED, sk) && encap_type == UDP_ENCAP_ESPINUDP) {
if (IS_ENABLED(CONFIG_IPV6) && family == AF_INET6)
- new_gro_receive = ipv6_stub->xfrm6_gro_udp_encap_rcv;
+ new_gro_receive = IPV6_CALL(xfrm6_gro_udp_encap_rcv);
else
new_gro_receive = xfrm4_gro_udp_encap_rcv;
@@ -3039,7 +3039,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
#if IS_ENABLED(CONFIG_IPV6)
if (sk->sk_family == AF_INET6)
WRITE_ONCE(up->encap_rcv,
- ipv6_stub->xfrm6_udp_encap_rcv);
+ IPV6_CALL(xfrm6_udp_encap_rcv));
else
#endif
WRITE_ONCE(up->encap_rcv,
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c
index c008d21925d7f4afa31cc55deec0ccc321cdab04..5171bc29397b240505af29c08b8d0176a871c2d5 100644
--- a/net/ipv6/addrconf_core.c
+++ b/net/ipv6/addrconf_core.c
@@ -129,7 +129,8 @@ int inet6addr_validator_notifier_call_chain(unsigned long val, void *v)
}
EXPORT_SYMBOL(inet6addr_validator_notifier_call_chain);
-static struct dst_entry *eafnosupport_ipv6_dst_lookup_flow(struct net *net,
+#if !defined(CONFIG_IPV6)
+static struct dst_entry *eafnosupport_ip6_dst_lookup_flow(struct net *net,
const struct sock *sk,
struct flowi6 *fl6,
const struct in6_addr *final_dst)
@@ -203,9 +204,11 @@ static struct net_device *eafnosupport_ipv6_dev_find(struct net *net, const stru
{
return ERR_PTR(-EAFNOSUPPORT);
}
+#endif
const struct ipv6_stub *ipv6_stub __read_mostly = &(struct ipv6_stub) {
- .ipv6_dst_lookup_flow = eafnosupport_ipv6_dst_lookup_flow,
+#if !defined(CONFIG_IPV6)
+ .ip6_dst_lookup_flow = eafnosupport_ip6_dst_lookup_flow,
.ipv6_route_input = eafnosupport_ipv6_route_input,
.fib6_get_table = eafnosupport_fib6_get_table,
.fib6_table_lookup = eafnosupport_fib6_table_lookup,
@@ -214,8 +217,9 @@ const struct ipv6_stub *ipv6_stub __read_mostly = &(struct ipv6_stub) {
.ip6_mtu_from_fib6 = eafnosupport_ip6_mtu_from_fib6,
.fib6_nh_init = eafnosupport_fib6_nh_init,
.ip6_del_rt = eafnosupport_ip6_del_rt,
- .ipv6_fragment = eafnosupport_ipv6_fragment,
+ .ip6_fragment = eafnosupport_ipv6_fragment,
.ipv6_dev_find = eafnosupport_ipv6_dev_find,
+#endif
};
EXPORT_SYMBOL_GPL(ipv6_stub);
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 23cc9b4cb2f122975e8601f83b36c168784b9041..d80c85c3215786deffe9e57d35522eadc8032d05 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -1023,16 +1023,18 @@ static struct pernet_operations inet6_net_ops = {
.exit = inet6_net_exit,
};
-static int ipv6_route_input(struct sk_buff *skb)
+int ipv6_route_input(struct sk_buff *skb)
{
ip6_route_input(skb);
return skb_dst(skb)->error;
}
static const struct ipv6_stub ipv6_stub_impl = {
+ .nd_tbl = &nd_tbl,
+#if !defined(CONFIG_IPV6)
.ipv6_sock_mc_join = ipv6_sock_mc_join,
.ipv6_sock_mc_drop = ipv6_sock_mc_drop,
- .ipv6_dst_lookup_flow = ip6_dst_lookup_flow,
+ .ip6_dst_lookup_flow = ip6_dst_lookup_flow,
.ipv6_route_input = ipv6_route_input,
.fib6_get_table = fib6_get_table,
.fib6_table_lookup = fib6_table_lookup,
@@ -1042,7 +1044,7 @@ static const struct ipv6_stub ipv6_stub_impl = {
.fib6_nh_init = fib6_nh_init,
.fib6_nh_release = fib6_nh_release,
.fib6_nh_release_dsts = fib6_nh_release_dsts,
- .fib6_update_sernum = fib6_update_sernum_stub,
+ .fib6_update_sernum_stub = fib6_update_sernum_stub,
.fib6_rt_update = fib6_rt_update,
.ip6_del_rt = ip6_del_rt,
.udpv6_encap_enable = udpv6_encap_enable,
@@ -1053,10 +1055,10 @@ static const struct ipv6_stub ipv6_stub_impl = {
.xfrm6_gro_udp_encap_rcv = xfrm6_gro_udp_encap_rcv,
.xfrm6_rcv_encap = xfrm6_rcv_encap,
#endif
- .nd_tbl = &nd_tbl,
- .ipv6_fragment = ip6_fragment,
+ .ip6_fragment = ip6_fragment,
.ipv6_dev_find = ipv6_dev_find,
.ip6_xmit = ip6_xmit,
+#endif
};
static const struct ipv6_bpf_stub ipv6_bpf_stub_impl = {
@@ -1235,7 +1237,7 @@ static int __init inet6_init(void)
/* ensure that ipv6 stubs are visible only after ipv6 is ready */
wmb();
- ipv6_stub = &ipv6_stub_impl;
+ WRITE_ONCE(ipv6_stub, &ipv6_stub_impl);
ipv6_bpf_stub = &ipv6_bpf_stub_impl;
out:
return err;
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 9058e71241dc376ebff2581ba882357c61d6adb8..e4c71fa1d5083ff38a233a07c660ac5e67849f0b 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -1405,7 +1405,7 @@ void fib6_update_sernum_upto_root(struct net *net, struct fib6_info *rt)
__fib6_update_sernum_upto_root(rt, fib6_new_sernum(net));
}
-/* allow ipv4 to update sernum via ipv6_stub */
+/* allow ipv4 (from nh_rt_cache_flush()) to update sernum via ipv6_stub */
void fib6_update_sernum_stub(struct net *net, struct fib6_info *f6i)
{
spin_lock_bh(&f6i->fib6_table->tb6_lock);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 8e2a6b28cea7ae69099859b337c9044caf99e631..315808dc2a07a2cb724cab72fd7878b5c5063a33 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1045,6 +1045,7 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
kfree_skb(skb);
return err;
}
+EXPORT_SYMBOL_GPL(ip6_fragment);
static inline int ip6_rt_check(const struct rt6key *rt_key,
const struct in6_addr *fl_addr,
diff --git a/net/ipv6/ip6_udp_tunnel.c b/net/ipv6/ip6_udp_tunnel.c
index cef3e021074440adc5c284719fc45f79dffd7dd8..5e2d00efac4aa9050d7d94f1a02a66ebf3ff7244 100644
--- a/net/ipv6/ip6_udp_tunnel.c
+++ b/net/ipv6/ip6_udp_tunnel.c
@@ -162,8 +162,7 @@ struct dst_entry *udp_tunnel6_dst_lookup(struct sk_buff *skb,
fl6.fl6_dport = dport;
fl6.flowlabel = ip6_make_flowinfo(dsfield, key->label);
- dst = ipv6_stub->ipv6_dst_lookup_flow(net, sock->sk, &fl6,
- NULL);
+ dst = IPV6_CALL(ip6_dst_lookup_flow)(net, sock->sk, &fl6, NULL);
if (IS_ERR(dst)) {
netdev_dbg(dev, "no route to %pI6\n", &fl6.daddr);
return ERR_PTR(-ENETUNREACH);
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index f6a5d8c73af9721741c11b543e5abeecdbf2079f..dbe41a1fcef1c1d4dfc0cb2ac09e1f4af8a8a3c5 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -576,6 +576,7 @@ void ndisc_send_na(struct net_device *dev, const struct in6_addr *daddr,
ndisc_send_skb(skb, daddr, src_addr);
}
+EXPORT_SYMBOL(ndisc_send_na);
static void ndisc_send_unsol_na(struct net_device *dev)
{
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index ae85a7654b1f6d2871c29e936f582a6faa5d0656..a4e58968af66b8861238b9c7bcf26304088e5261 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -642,7 +642,7 @@ static struct net_device *inet6_fib_lookup_dev(struct net *net,
memset(&fl6, 0, sizeof(fl6));
memcpy(&fl6.daddr, addr, sizeof(struct in6_addr));
- dst = ipv6_stub->ipv6_dst_lookup_flow(net, NULL, &fl6, NULL);
+ dst = IPV6_CALL(ip6_dst_lookup_flow)(net, NULL, &fl6, NULL);
if (IS_ERR(dst))
return ERR_CAST(dst);
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 792ca44a461da0bb98d49bfe9f233214fb57a61e..e9c9117cd07f2b182de165607f2e008c98bdcad1 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -810,7 +810,7 @@ static void ovs_fragment(struct net *net, struct vport *vport,
skb_dst_set_noref(skb, &ovs_rt.dst);
IP6CB(skb)->frag_max_size = mru;
- ipv6_stub->ipv6_fragment(net, skb->sk, skb, ovs_vport_output);
+ IPV6_CALL(ip6_fragment)(net, skb->sk, skb, ovs_vport_output);
refdst_drop(orig_dst);
} else {
WARN_ONCE(1, "Failed fragment ->%s: eth=%04x, MRU=%d, MTU=%d.",
diff --git a/net/sched/sch_frag.c b/net/sched/sch_frag.c
index d1d87dce7f3f72e33e3c8ec0c0eb35bdd9b5c9f1..f490c0a5829cbaaea3940d267154002c4879e237 100644
--- a/net/sched/sch_frag.c
+++ b/net/sched/sch_frag.c
@@ -6,6 +6,7 @@
#include <net/dst.h>
#include <net/ip.h>
#include <net/ip6_fib.h>
+#include <net/ip6_route.h>
struct sch_frag_data {
unsigned long dst;
@@ -127,8 +128,8 @@ static int sch_fragment(struct net *net, struct sk_buff *skb,
skb_dst_set_noref(skb, &sch_frag_rt.dst);
IP6CB(skb)->frag_max_size = mru;
- ret = ipv6_stub->ipv6_fragment(net, skb->sk, skb,
- sch_frag_xmit);
+ ret = IPV6_CALL(ip6_fragment)(net, skb->sk, skb,
+ sch_frag_xmit);
local_unlock_nested_bh(&sch_frag_data_storage.bh_lock);
refdst_drop(orig_dst);
} else {
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c
index 2b8e385d1e5141a880e312d4a07963e4b7b3b0a7..10d2ff0ad85071863dff1bef2603eac7e0bdb797 100644
--- a/net/tipc/udp_media.c
+++ b/net/tipc/udp_media.c
@@ -207,9 +207,9 @@ static int tipc_udp_xmit(struct net *net, struct sk_buff *skb,
.saddr = src->ipv6,
.flowi6_proto = IPPROTO_UDP
};
- ndst = ipv6_stub->ipv6_dst_lookup_flow(net,
- ub->ubsock->sk,
- &fl6, NULL);
+ ndst = IPV6_CALL(ip6_dst_lookup_flow)(net,
+ ub->ubsock->sk,
+ &fl6, NULL);
if (IS_ERR(ndst)) {
err = PTR_ERR(ndst);
goto tx_error;
@@ -418,7 +418,7 @@ static int enable_mcast(struct udp_bearer *ub, struct udp_media_addr *remote)
#if IS_ENABLED(CONFIG_IPV6)
} else {
lock_sock(sk);
- err = ipv6_stub->ipv6_sock_mc_join(sk, ub->ifindex,
+ err = IPV6_CALL(ipv6_sock_mc_join)(sk, ub->ifindex,
&remote->ipv6);
release_sock(sk);
#endif
diff --git a/net/xfrm/espintcp.c b/net/xfrm/espintcp.c
index e1b11ab59f6ee834bee093e2011f48be6757fde7..714687e39602dd3b891ba72305de14a748f17229 100644
--- a/net/xfrm/espintcp.c
+++ b/net/xfrm/espintcp.c
@@ -43,7 +43,7 @@ static void handle_esp(struct sk_buff *skb, struct sock *sk)
local_bh_disable();
#if IS_ENABLED(CONFIG_IPV6)
if (sk->sk_family == AF_INET6)
- ipv6_stub->xfrm6_rcv_encap(skb, IPPROTO_ESP, 0, TCP_ENCAP_ESPINTCP);
+ IPV6_CALL(xfrm6_rcv_encap)(skb, IPPROTO_ESP, 0, TCP_ENCAP_ESPINTCP);
else
#endif
xfrm4_rcv_encap(skb, IPPROTO_ESP, 0, TCP_ENCAP_ESPINTCP);
diff --git a/net/xfrm/xfrm_nat_keepalive.c b/net/xfrm/xfrm_nat_keepalive.c
index ebf95d48e86c149ceabd6e059d85d39660df5b8c..7b8f2b23c6b9daf5696659856435189565f51842 100644
--- a/net/xfrm/xfrm_nat_keepalive.c
+++ b/net/xfrm/xfrm_nat_keepalive.c
@@ -98,14 +98,14 @@ static int nat_keepalive_send_ipv6(struct sk_buff *skb,
local_lock_nested_bh(&nat_keepalive_sk_ipv6.bh_lock);
sk = this_cpu_read(nat_keepalive_sk_ipv6.sock);
sock_net_set(sk, net);
- dst = ipv6_stub->ipv6_dst_lookup_flow(net, sk, &fl6, NULL);
+ dst = IPV6_CALL(ip6_dst_lookup_flow)(net, sk, &fl6, NULL);
if (IS_ERR(dst)) {
local_unlock_nested_bh(&nat_keepalive_sk_ipv6.bh_lock);
return PTR_ERR(dst);
}
skb_dst_set(skb, dst);
- err = ipv6_stub->ip6_xmit(sk, skb, &fl6, skb->mark, NULL, 0, 0);
+ err = IPV6_CALL(ip6_xmit)(sk, skb, &fl6, skb->mark, NULL, 0, 0);
sock_net_set(sk, &init_net);
local_unlock_nested_bh(&nat_keepalive_sk_ipv6.bh_lock);
return err;
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 54222fcbd7fd81d3b90fbf82749285b33d897990..82a68a530a875c9e7031117a7ea69862989bd8f4 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -900,7 +900,7 @@ int xfrm6_tunnel_check_size(struct sk_buff *skb)
skb->protocol = htons(ETH_P_IPV6);
if (xfrm6_local_dontfrag(sk))
- ipv6_stub->xfrm6_local_rxpmtu(skb, mtu);
+ IPV6_CALL(xfrm6_local_rxpmtu)(skb, mtu);
else if (sk)
xfrm_local_error(skb, mtu);
else
--
2.53.0.473.g4a7958ca14-goog
next reply other threads:[~2026-03-02 15:42 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-02 15:42 Eric Dumazet [this message]
2026-03-03 19:15 ` [PATCH net-next] ipv6: add IPV6_CALL() helper Kuniyuki Iwashima
2026-03-04 1:08 ` Jakub Kicinski
2026-03-04 2:13 ` Eric Dumazet
2026-03-04 2:24 ` Jakub Kicinski
2026-03-04 2:32 ` Eric Dumazet
2026-03-04 2:33 ` Eric Dumazet
2026-03-04 2:45 ` Jakub Kicinski
-- strict thread matches above, loose matches on Subject: below --
2026-03-01 16:25 Eric Dumazet
2026-03-01 19:24 ` Jakub Kicinski
2026-03-01 19:36 ` Jakub Kicinski
2026-03-01 19:37 ` Eric Dumazet
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=20260302154201.1621117-1-edumazet@google.com \
--to=edumazet@google.com \
--cc=davem@davemloft.net \
--cc=eric.dumazet@gmail.com \
--cc=horms@kernel.org \
--cc=idosch@nvidia.com \
--cc=kuba@kernel.org \
--cc=kuniyu@google.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.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