[PATCH] network: allow accept_ra == 0 when enabling ipv6 forwarding
Cedric Bosdonnat
CBosdonnat at suse.com
Tue Sep 1 08:27:47 UTC 2020
On Wed, 2020-08-12 at 19:21 -0400, Laine Stump wrote:
> Yay! A user who follows up their conversation on the libvirt-users list
> with a patch! :-)
>
> On 8/11/20 8:14 PM, Ian Wienand wrote:
> > The checks modified here were added with
> > 00d28a78b5d1f6eaf79f06ac59e31c568af9da37 to avoid losing routes on
> > hosts.
>
> I'm Cc'ing the author of that patch, Cédric Bosdonnat, to make sure that
> whatever we end up doing doesn't upset his use case.
Ouch! that is old... even reading my bugzilla log I have troubles
explaining that thing properly. I'll try it though.
So the hypervisor has at least one (Router Advertised) RA route.
After defining a network like the following, the RA route is removed if
accept_ra isn't set to 2.
<network ipv6="yes">
<name>test5</name>
<forward mode="nat"/>
<bridge name="708837c1d27-br0" stp="off"/>
<mac address="52:54:00:45:5f:27"/>
<ip
family="ipv6"
address="fc00:0000:0000:000f:0000:0000:0000:0001"
prefix="64"/>
</network>
The RA route was removed in networkEnableIPForwarding() when
setting /proc/sys/net/ipv6/conf/all/forwarding to 1.
Me not being a network expert (and even less on ipv6) doesn't help.
I hope this explanation will help you better see the use case I had.
--
Cedric
> > However, tools such as systemd-networking and NetworkManager manage
> > RA's in userspace and thus IPv6 may be up and working on an interface
> > even with accept_ra == 0.
> >
> > This modifies the check to only error if an interface's accept_ra is
> > already set to "1"; as noted inline this seems to when it is likely
> > that enabling forwarding may change the RA acceptance behaviour of the
> > interface.
>
> Unfortunately, on my Fedora 32 machine that has NetworkManager enabled,
> not all the interfaces have accept_ra=0 by default. One of the bridge
> devices (created by NetworkManager in response to an ifcfg file in
> /etc/sysconfig/network-scripts) has accept_ra = 1. (there are several
> other interfaces that have accept_ra=1, but those interfaces are either
> not online, or they don't have an IPv6 address.
>
>
> So this doesn't work for all cases. I think we need to get more
> information on how to most easily, generically, and reliably determine
> if the kernel accept_ra setting can be ignored. Possibly the
> NetworkManager people can help us out here.
>
>
> (or alternately we could punt and just make a configuration setting,
> although that is taking the easy road, and not a good precedent to set)
>
>
> > I have noticed this because I am using the IPv6 NAT features enabled
> > with 927acaedec7effbe67a154d8bfa0e67f7d08e6c7. I am using this on my
> > laptop which switches between wired and wireless connections; both of
> > which are configured in an unremarkable way by Fedora's NetworkManager
> > and get configured for IPv6 via SLAAC and whatever NetworkManager
> > magic it does. With this I can define and start a libvirt network
> > with <nat ipv6="yes"> and <ip family='ipv6'
> > address='fc00:abcd:ef12:34::' prefix='64'> and it seems to "just work"
> > for guests.
> >
> > Signed-off-by: Ian Wienand <iwienand at redhat.com>
> > ---
> > src/util/virnetdevip.c | 41 +++++++++++++++++++++++++++--------------
> > 1 file changed, 27 insertions(+), 14 deletions(-)
> >
> > diff --git a/src/util/virnetdevip.c b/src/util/virnetdevip.c
> > index 409f062c5c..de27cacfc9 100644
> > --- a/src/util/virnetdevip.c
> > +++ b/src/util/virnetdevip.c
> > @@ -496,7 +496,7 @@ virNetDevIPGetAcceptRA(const char *ifname)
> > }
> >
> > struct virNetDevIPCheckIPv6ForwardingData {
> > - bool hasRARoutes;
> > + bool hasKernelRARoutes;
> >
> > /* Devices with conflicting accept_ra */
> > char **devices;
> > @@ -552,15 +552,26 @@ virNetDevIPCheckIPv6ForwardingCallback(struct nlmsghdr *resp,
> > if (!ifname)
> > return -1;
> >
> > - accept_ra = virNetDevIPGetAcceptRA(ifname);
> > -
> > VIR_DEBUG("Checking route for device %s (%d), accept_ra: %d",
> > ifname, ifindex, accept_ra);
> >
> > - if (accept_ra != 2 && virNetDevIPCheckIPv6ForwardingAddIF(data, &ifname) < 0)
> > + accept_ra = virNetDevIPGetAcceptRA(ifname);
> > + /* 0 = do no accept RA
> > + * 1 = accept if forwarding disabled
> > + * 2 = ovveride and accept RA when forwarding enabled
> > + *
> > + * When RA is managed by userspace (systemd-networkd or
> > + * NetworkManager) accept_ra is unset and we don't need to
> > + * worry about it. If it is 1, enabling forwarding might
> > + * change the behaviour so the user needs to be warned.
> > + */
> > + if (accept_ra == 0)
> > + return 0;
> > +
> > + if (accept_ra == 1 && virNetDevIPCheckIPv6ForwardingAddIF(data, &ifname) < 0)
> > return -1;
> >
> > - data->hasRARoutes = true;
> > + data->hasKernelRARoutes = true;
> > return 0;
> > }
> >
> > @@ -590,11 +601,13 @@ virNetDevIPCheckIPv6ForwardingCallback(struct nlmsghdr *resp,
> > VIR_DEBUG("Checking multipath route nexthop device %s (%d), accept_ra: %d",
> > ifname, nh->rtnh_ifindex, accept_ra);
> >
> > - if (accept_ra != 2 && virNetDevIPCheckIPv6ForwardingAddIF(data, &ifname) < 0)
> > - return -1;
> > + if (accept_ra == 1) {
> > + if (virNetDevIPCheckIPv6ForwardingAddIF(data, &ifname) < 0)
> > + return -1;
> > + data->hasKernelRARoutes = true;
> > + }
> >
> > VIR_FREE(ifname);
> > - data->hasRARoutes = true;
> >
> > len -= NLMSG_ALIGN(nh->rtnh_len);
> > VIR_WARNINGS_NO_CAST_ALIGN
> > @@ -613,7 +626,7 @@ virNetDevIPCheckIPv6Forwarding(void)
> > struct rtgenmsg genmsg;
> > size_t i;
> > struct virNetDevIPCheckIPv6ForwardingData data = {
> > - .hasRARoutes = false,
> > + .hasKernelRARoutes = false,
> > .devices = NULL,
> > .ndevices = 0
> > };
> > @@ -644,11 +657,11 @@ virNetDevIPCheckIPv6Forwarding(void)
> > goto cleanup;
> > }
> >
> > - valid = !data.hasRARoutes || data.ndevices == 0;
> > + valid = !data.hasKernelRARoutes || data.ndevices == 0;
> >
> > /* Check the global accept_ra if at least one isn't set on a
> > per-device basis */
> > - if (!valid && data.hasRARoutes) {
> > + if (!valid && data.hasKernelRARoutes) {
> > int accept_ra = virNetDevIPGetAcceptRA(NULL);
> > valid = accept_ra == 2;
> > VIR_DEBUG("Checked global accept_ra: %d", accept_ra);
> > @@ -663,9 +676,9 @@ virNetDevIPCheckIPv6Forwarding(void)
> > }
> >
> > virReportError(VIR_ERR_INTERNAL_ERROR,
> > - _("Check the host setup: enabling IPv6 forwarding with "
> > - "RA routes without accept_ra set to 2 is likely to cause "
> > - "routes loss. Interfaces to look at: %s"),
> > + _("Check the host setup: interface has accept_ra set to 1 "
> > + "and enabling forwarding without accept_ra set to 2 is "
> > + "likely to cause routes loss. Interfaces to look at: %s"),
> > virBufferCurrentContent(&buf));
> > }
> >
>
>
More information about the libvir-list
mailing list