Skip to content

F #-: VRouter: IPv6 support (forwarding and virtual IPs via VRRP) - #406

Closed
netaviator wants to merge 2 commits into
OpenNebula:masterfrom
netaviator:pr/ipv6-support
Closed

netaviator wants to merge 2 commits into
OpenNebula:masterfrom
netaviator:pr/ipv6-support

Conversation

@netaviator

Copy link
Copy Markdown

Two parts that belong together: a router that holds IPv6 VIPs has to forward IPv6 as well.

IPv6 forwarding: new Router6 module
Router4 enables IPv4 forwarding on the routed NICs; nothing does it for IPv6. Add the counterpart as an opt-in service (ONEAPP_VNF_ROUTER6_ENABLED, default NO), modelled on Router4: an OpenRC service that writes /etc/sysctl.d/98-Router6.conf on start and switches everything off on stop. Unlike IPv4, Linux forwards IPv6 only when net.ipv6.conf.all.forwarding is 1: writing the per-interface switches does not turn the router on, and once the global switch is on the router forwards between ALL interfaces. So the global switch is set and only the management NICs are kept from being routers themselves. accept_ra=2 is written first on every NIC, because setting all.forwarding=1 turns router advertisement acceptance off on the interfaces that have accept_ra=1 (a NIC configured by SLAAC would lose its address). There is no IPv6 filtering or NAT66 in the appliance; that is why the default is NO.

IPv6 virtual IPs via VRRP
Allow IPv6 VIPs next to the IPv4 ones. They come from the OpenNebula floating IPv6 (ETH_VROUTER_IP6) and from ONEAPP_VROUTER_ETH_VIP; an address given by both is listed once and the explicit value wins.

  • An IPv6 VIP without a prefix length gets /64 (ETH_MASK and the IPv4 range guesses do not apply). A prefix length of 0 becomes /128, like /32 for IPv4. When the prefix length of an IPv4 VIP has to be guessed, a warning is logged once per NIC and address.
  • A malformed IPv6 VIP is skipped with an error that names the attribute (at most 40 characters of the value are logged) instead of breaking keepalived.conf or the rest of the VIPs.
  • VRRP: keepalived needs one instance per address family, so a second instance _6 joins the same vrrp_sync_group as the IPv4 one (no authentication on it: it is not allowed for IPv6). A NIC group with IPv6 VIPs only gets just that instance. The Failover module reacts to the group event only, so nothing changes there.
  • IPv6 VIPs are installed with preferred_lft 0. Otherwise the kernel picks the VIP as the source address of the router's own IPv6 traffic (measured on the VRRP master), and sessions to a peer that only knows the node address never came up. The VIP stays on the NIC and is still answered for.
  • Addresses are compared in the form "ip -j addr" prints (compressed, lower case), so the readiness check does not fail on notation.

Tests: the Router6 module, the VIP detection and the generated keepalived.conf, and IPv6 examples for the HAProxy and LVS configuration (both are address family generic; frontends bind to the VIPs).

Two parts that belong together: a router that holds IPv6 VIPs has to
forward IPv6 as well.

IPv6 forwarding: new Router6 module
Router4 enables IPv4 forwarding on the routed NICs; nothing does it for
IPv6. Add the counterpart as an opt-in service (ONEAPP_VNF_ROUTER6_ENABLED,
default NO), modelled on Router4: an OpenRC service that writes
/etc/sysctl.d/98-Router6.conf on start and switches everything off on stop.
Unlike IPv4, Linux forwards IPv6 only when net.ipv6.conf.all.forwarding is
1: writing the per-interface switches does not turn the router on, and
once the global switch is on the router forwards between ALL interfaces.
So the global switch is set and only the management NICs are kept from
being routers themselves. accept_ra=2 is written first on every NIC,
because setting all.forwarding=1 turns router advertisement acceptance off
on the interfaces that have accept_ra=1 (a NIC configured by SLAAC would
lose its address). There is no IPv6 filtering or NAT66 in the appliance;
that is why the default is NO.

IPv6 virtual IPs via VRRP
Allow IPv6 VIPs next to the IPv4 ones. They come from the OpenNebula
floating IPv6 (ETH<n>_VROUTER_IP6) and from ONEAPP_VROUTER_ETH<n>_VIP<m>;
an address given by both is listed once and the explicit value wins.

* An IPv6 VIP without a prefix length gets /64 (ETH<n>_MASK and the IPv4
  range guesses do not apply). A prefix length of 0 becomes /128, like /32
  for IPv4. When the prefix length of an IPv4 VIP has to be guessed, a
  warning is logged once per NIC and address.
* A malformed IPv6 VIP is skipped with an error that names the attribute
  (at most 40 characters of the value are logged) instead of breaking
  keepalived.conf or the rest of the VIPs.
* VRRP: keepalived needs one instance per address family, so a second
  instance <NIC>_6 joins the same vrrp_sync_group as the IPv4 one (no
  authentication on it: it is not allowed for IPv6). A NIC group with
  IPv6 VIPs only gets just that instance. The Failover module reacts to
  the group event only, so nothing changes there.
* IPv6 VIPs are installed with preferred_lft 0. Otherwise the kernel picks
  the VIP as the source address of the router's own IPv6 traffic (measured
  on the VRRP master), and sessions to a peer that only knows the node
  address never came up. The VIP stays on the NIC and is still answered for.
* Addresses are compared in the form "ip -j addr" prints (compressed,
  lower case), so the readiness check does not fail on notation.

Tests: the Router6 module, the VIP detection and the generated
keepalived.conf, and IPv6 examples for the HAProxy and LVS configuration
(both are address family generic; frontends bind to the VIPs).

Signed-off-by: Jan Gilla <jgilla@level66.network>
The failover service starts the routing services on the VRRP master from
its SERVICES table, which had no entry for one-router6. With
ONEAPP_VNF_ROUTER6_ENABLED=YES the service was installed but never
started, so the IPv6 forwarding settings were never written.
@netaviator netaviator closed this by deleting the head repository Oct 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant