* [PATCH] ipv6: add `do_forwarding` sysctl to enable per-interface forwarding
@ 2025-06-25 14:26 Gabriel Goller
2025-06-26 14:51 ` Nicolas Dichtel
0 siblings, 1 reply; 5+ messages in thread
From: Gabriel Goller @ 2025-06-25 14:26 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Jonathan Corbet, David Ahern
Cc: Nicolas Dichtel, netdev, linux-doc, linux-kernel
It is currently impossible to enable ipv6 forwarding on a per-interface
basis like in ipv4. To enable forwarding on an ipv6 interface we need to
enable it on all interfaces and disable it on the other interfaces using
a netfilter rule. This is especially cumbersome if you have lots of
interface and only want to enable forwarding on a few. According to the
sysctl docs [0] the `net.ipv6.conf.all.forwarding` enables forwarding
for all interfaces, while the interface-specific
`net.ipv6.conf.<interface>.forwarding` configures the interface
Host/Router configuration.
Introduce a new sysctl flag `do_forwarding`, which can be set on every
interface. The ip6_forwarding function will then check if the global
forwarding flag OR the do_forwarding flag is active and forward the
packet. To preserver backwards-compatibility also reset the flag on all
interfaces when setting the global forwarding flag to 0.
[0]: https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
---
* I don't have any hard feelings about the naming, Nicolas Dichtel
proposed `fwd_per_iface` but I think `do_forwarding` is a better fit.
* I'm also not sure about the reset when setting the global forwarding
flag; don't know if I did that right. Feedback is welcome!
* Thanks for the help!
Documentation/networking/ip-sysctl.rst | 5 +++++
include/linux/ipv6.h | 1 +
include/uapi/linux/ipv6.h | 1 +
include/uapi/linux/sysctl.h | 1 +
net/ipv6/addrconf.c | 21 +++++++++++++++++++++
net/ipv6/ip6_output.c | 3 ++-
6 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/Documentation/networking/ip-sysctl.rst b/Documentation/networking/ip-sysctl.rst
index 0f1251cce314..fa966a710e21 100644
--- a/Documentation/networking/ip-sysctl.rst
+++ b/Documentation/networking/ip-sysctl.rst
@@ -2292,6 +2292,11 @@ conf/all/forwarding - BOOLEAN
proxy_ndp - BOOLEAN
Do proxy ndp.
+do_forwarding - BOOLEAN
+ Enable forwarding on this interface only -- regardless of the setting on
+ ``conf/all/forwarding``. When setting ``conf.all.forwarding`` to 0,
+ the `do_forwarding` flag will be reset on all interfaces.
+
fwmark_reflect - BOOLEAN
Controls the fwmark of kernel-generated IPv6 reply packets that are not
associated with a socket for example, TCP RSTs or ICMPv6 echo replies).
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 5aeeed22f35b..74d7cfbb8f83 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -19,6 +19,7 @@ struct ipv6_devconf {
__s32 forwarding;
__s32 disable_policy;
__s32 proxy_ndp;
+ __u8 do_forwarding;
__cacheline_group_end(ipv6_devconf_read_txrx);
__s32 accept_ra;
diff --git a/include/uapi/linux/ipv6.h b/include/uapi/linux/ipv6.h
index cf592d7b630f..66147838bb83 100644
--- a/include/uapi/linux/ipv6.h
+++ b/include/uapi/linux/ipv6.h
@@ -199,6 +199,7 @@ enum {
DEVCONF_NDISC_EVICT_NOCARRIER,
DEVCONF_ACCEPT_UNTRACKED_NA,
DEVCONF_ACCEPT_RA_MIN_LFT,
+ DEVCONF_DO_FORWARDING,
DEVCONF_MAX
};
diff --git a/include/uapi/linux/sysctl.h b/include/uapi/linux/sysctl.h
index 8981f00204db..d540689910ec 100644
--- a/include/uapi/linux/sysctl.h
+++ b/include/uapi/linux/sysctl.h
@@ -573,6 +573,7 @@ enum {
NET_IPV6_ACCEPT_RA_FROM_LOCAL=26,
NET_IPV6_ACCEPT_RA_RT_INFO_MIN_PLEN=27,
NET_IPV6_RA_DEFRTR_METRIC=28,
+ NET_IPV6_DO_FORWARDING=29,
__NET_IPV6_MAX
};
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index ba2ec7c870cc..2f0c68428f63 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -239,6 +239,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
.ndisc_evict_nocarrier = 1,
.ra_honor_pio_life = 0,
.ra_honor_pio_pflag = 0,
+ .do_forwarding = 0,
};
static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
@@ -303,6 +304,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
.ndisc_evict_nocarrier = 1,
.ra_honor_pio_life = 0,
.ra_honor_pio_pflag = 0,
+ .do_forwarding = 0,
};
/* Check if link is ready: is it up and is a valid qdisc available */
@@ -857,6 +859,15 @@ static void addrconf_forward_change(struct net *net, __s32 newf)
idev = __in6_dev_get_rtnl_net(dev);
if (idev) {
int changed = (!idev->cnf.forwarding) ^ (!newf);
+ /*
+ * With the introduction of do_forwarding, we need to be backwards
+ * compatible, so that means we need to set the do_forwarding flag
+ * on every interface to 0 if net.ipv6.conf.all.forwarding is set to 0.
+ * This allows the global forwarding flag to disable forwarding for
+ * all interfaces.
+ */
+ if (newf == 0)
+ WRITE_ONCE(idev->cnf.do_forwarding, newf);
WRITE_ONCE(idev->cnf.forwarding, newf);
if (changed)
@@ -5719,6 +5730,7 @@ static void ipv6_store_devconf(const struct ipv6_devconf *cnf,
array[DEVCONF_ACCEPT_UNTRACKED_NA] =
READ_ONCE(cnf->accept_untracked_na);
array[DEVCONF_ACCEPT_RA_MIN_LFT] = READ_ONCE(cnf->accept_ra_min_lft);
+ array[DEVCONF_DO_FORWARDING] = READ_ONCE(cnf->do_forwarding);
}
static inline size_t inet6_ifla6_size(void)
@@ -7217,6 +7229,15 @@ static const struct ctl_table addrconf_sysctl[] = {
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_TWO,
},
+ {
+ .procname = "do_forwarding",
+ .data = &ipv6_devconf.do_forwarding,
+ .maxlen = sizeof(u8),
+ .mode = 0644,
+ .proc_handler = proc_dou8vec_minmax,
+ .extra1 = SYSCTL_ZERO,
+ .extra2 = SYSCTL_ONE,
+ },
};
static int __addrconf_sysctl_register(struct net *net, char *dev_name,
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 7bd29a9ff0db..a75bbf54157e 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -509,7 +509,8 @@ int ip6_forward(struct sk_buff *skb)
u32 mtu;
idev = __in6_dev_get_safely(dev_get_by_index_rcu(net, IP6CB(skb)->iif));
- if (READ_ONCE(net->ipv6.devconf_all->forwarding) == 0)
+ if ((idev && READ_ONCE(idev->cnf.do_forwarding) == 0) &&
+ READ_ONCE(net->ipv6.devconf_all->forwarding) == 0)
goto error;
if (skb->pkt_type != PACKET_HOST)
--
2.39.5
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] ipv6: add `do_forwarding` sysctl to enable per-interface forwarding
2025-06-25 14:26 [PATCH] ipv6: add `do_forwarding` sysctl to enable per-interface forwarding Gabriel Goller
@ 2025-06-26 14:51 ` Nicolas Dichtel
2025-06-27 14:47 ` Gabriel Goller
0 siblings, 1 reply; 5+ messages in thread
From: Nicolas Dichtel @ 2025-06-26 14:51 UTC (permalink / raw)
To: Gabriel Goller, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Jonathan Corbet, David Ahern
Cc: netdev, linux-doc, linux-kernel
Le 25/06/2025 à 16:26, Gabriel Goller a écrit :
> It is currently impossible to enable ipv6 forwarding on a per-interface
> basis like in ipv4. To enable forwarding on an ipv6 interface we need to
> enable it on all interfaces and disable it on the other interfaces using
> a netfilter rule. This is especially cumbersome if you have lots of
> interface and only want to enable forwarding on a few. According to the
> sysctl docs [0] the `net.ipv6.conf.all.forwarding` enables forwarding
> for all interfaces, while the interface-specific
> `net.ipv6.conf.<interface>.forwarding` configures the interface
> Host/Router configuration.
>
> Introduce a new sysctl flag `do_forwarding`, which can be set on every
> interface. The ip6_forwarding function will then check if the global
> forwarding flag OR the do_forwarding flag is active and forward the
> packet. To preserver backwards-compatibility also reset the flag on all
> interfaces when setting the global forwarding flag to 0.
>
> [0]: https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
>
> Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
Please, export this sysctl via a NETCONFA_DO_FORWARDING attribute also.
> ---
>
> * I don't have any hard feelings about the naming, Nicolas Dichtel
> proposed `fwd_per_iface` but I think `do_forwarding` is a better fit.
What about force_forwarding?
> * I'm also not sure about the reset when setting the global forwarding
> flag; don't know if I did that right. Feedback is welcome!
It seems correct to me.
> * Thanks for the help!
Maybe you could align ipv6.all.do_forwarding on ipv4.all.forwarding, ie setting
all existing ipv6.*.do_forwarding.
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/devinet.c#n2423
Regards,
Nicolas
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] ipv6: add `do_forwarding` sysctl to enable per-interface forwarding
2025-06-26 14:51 ` Nicolas Dichtel
@ 2025-06-27 14:47 ` Gabriel Goller
2025-06-30 14:53 ` Nicolas Dichtel
0 siblings, 1 reply; 5+ messages in thread
From: Gabriel Goller @ 2025-06-27 14:47 UTC (permalink / raw)
To: Nicolas Dichtel
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Jonathan Corbet, David Ahern, netdev, linux-doc,
linux-kernel
On 26.06.2025 16:51, Nicolas Dichtel wrote:
>Le 25/06/2025 à 16:26, Gabriel Goller a écrit :
>> It is currently impossible to enable ipv6 forwarding on a per-interface
>> basis like in ipv4. To enable forwarding on an ipv6 interface we need to
>> enable it on all interfaces and disable it on the other interfaces using
>> a netfilter rule. This is especially cumbersome if you have lots of
>> interface and only want to enable forwarding on a few. According to the
>> sysctl docs [0] the `net.ipv6.conf.all.forwarding` enables forwarding
>> for all interfaces, while the interface-specific
>> `net.ipv6.conf.<interface>.forwarding` configures the interface
>> Host/Router configuration.
>>
>> Introduce a new sysctl flag `do_forwarding`, which can be set on every
>> interface. The ip6_forwarding function will then check if the global
>> forwarding flag OR the do_forwarding flag is active and forward the
>> packet. To preserver backwards-compatibility also reset the flag on all
>> interfaces when setting the global forwarding flag to 0.
>>
>> [0]: https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
>>
>> Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
>Please, export this sysctl via a NETCONFA_DO_FORWARDING attribute also.
Yep, will do.
>> ---
>>
>> * I don't have any hard feelings about the naming, Nicolas Dichtel
>> proposed `fwd_per_iface` but I think `do_forwarding` is a better fit.
>What about force_forwarding?
I Agree!
>> * I'm also not sure about the reset when setting the global forwarding
>> flag; don't know if I did that right. Feedback is welcome!
>It seems correct to me.
>
>> * Thanks for the help!
>Maybe you could align ipv6.all.do_forwarding on ipv4.all.forwarding, ie setting
>all existing ipv6.*.do_forwarding.
>https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/devinet.c#n2423
Also done!
>Regards,
>Nicolas
Sent a new patch just now, thanks for reviewing!
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] ipv6: add `do_forwarding` sysctl to enable per-interface forwarding
2025-06-27 14:47 ` Gabriel Goller
@ 2025-06-30 14:53 ` Nicolas Dichtel
2025-07-01 14:05 ` Gabriel Goller
0 siblings, 1 reply; 5+ messages in thread
From: Nicolas Dichtel @ 2025-06-30 14:53 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Jonathan Corbet, David Ahern, netdev, linux-doc,
linux-kernel
Le 27/06/2025 à 16:47, Gabriel Goller a écrit :
[snip]
>
> Sent a new patch just now, thanks for reviewing!
>
FWIW, I didn't see any new patch from you.
Regards,
Nicolas
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] ipv6: add `do_forwarding` sysctl to enable per-interface forwarding
2025-06-30 14:53 ` Nicolas Dichtel
@ 2025-07-01 14:05 ` Gabriel Goller
0 siblings, 0 replies; 5+ messages in thread
From: Gabriel Goller @ 2025-07-01 14:05 UTC (permalink / raw)
To: Nicolas Dichtel
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Jonathan Corbet, David Ahern, netdev, linux-doc,
linux-kernel
On 30.06.2025 16:53, Nicolas Dichtel wrote:
>Le 27/06/2025 à 16:47, Gabriel Goller a écrit :
>[snip]
>>
>> Sent a new patch just now, thanks for reviewing!
>>
>FWIW, I didn't see any new patch from you.
It's out now, forgot to actually send it -_-
>Regards,
>Nicolas
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-07-01 14:05 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-06-25 14:26 [PATCH] ipv6: add `do_forwarding` sysctl to enable per-interface forwarding Gabriel Goller
2025-06-26 14:51 ` Nicolas Dichtel
2025-06-27 14:47 ` Gabriel Goller
2025-06-30 14:53 ` Nicolas Dichtel
2025-07-01 14:05 ` Gabriel Goller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®