From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id 1882E1FF0B7 for ; Fri, 16 Oct 2026 18:33:41 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id A8A1921481; Fri, 16 Oct 2026 18:33:39 +0200 (CEST) Mime-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=UTF-8 Date: Fri, 16 Oct 2026 18:33:32 +0200 Message-Id: Subject: Re: [PATCH network v4 1/6] sdn: evpn: enable force_forwarding for ipv6 forwarding to subnets From: "Lukas Sichert" To: "Hannes Laimer" , "Lukas Sichert" References: <20260727135509.14588-1-l.sichert@proxmox.com> <20260727135509.14588-2-l.sichert@proxmox.com> In-Reply-To: X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1792168412675 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.626 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: JHCIHZGVTCD7Q73JEHF3ANHK4XTFECFT X-Message-ID-Hash: JHCIHZGVTCD7Q73JEHF3ANHK4XTFECFT X-MailFrom: l.sichert@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: pve-devel@lists.proxmox.com X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Thanks for the response, comments inline: On 2026-08-24 09:23, Hannes Laimer wrote: > On 2026-07-27 15:55, Lukas Sichert wrote: >> + if ($is_evpn_gateway) { >> + #find outgoing ipv6 interface >> + my ($outip, $outiface); >> + eval { >> + ($outip, $outiface) =3D >> + PVE::Network::SDN::Zones::Plugin::get_local_route_i= p('2001:4860:4860::8888'); >> + }; >> + if ($@) { >> + my $msg =3D "interface for IPv6 forwarding could not be= resolved: $@"; >> + log_warn($msg); >> + } elsif ($outiface) { >> + push @iface_config, >> + "post-up echo 1 > /proc/sys/net/ipv6/conf/$outiface= /force_forwarding"; >> + push @iface_config, >> + "post-down echo 0 > /proc/sys/net/ipv6/conf/$outifa= ce/force_forwarding"; > > our `ifupdown2` is shippes with `ifreload-down-changed=3D0`, so > `post-down`s never run on changes (except for vxlan and vlan), so just > deleting the subnet, will leave the `force_forwarding=3D1` on the > `outiface` > > sdn apply does run the `post-down` for removed infterfaces, but it also > runs all the `post-up`s again, so this works not because the `post-down` > is not executed on delete, but because the `post-up` re-write the `1` > > and with a manual `ifdown`, this can actually break things > > we should probably drop the `post-down` here, this is at best a no-op, > and can potentially break things. so this might generally not be the > place to manage a shared uplinks sysctl.. > > something like we do in pve-common with `disable_ipv6` could be an > alternative, on apply we'd have to check if we still need it on the > uplink interface, then either `=3D0` or `=3D1` it Agreed, a post-up/post-down pair is not the right place to manage a shared uplink's sysctl. As discussed off-list, the better approach is to enable it in ifupdown2, mimicking how IPv4 forwarding is handled: enable it when a gateway is configured or a flag is set. > >> + } >> + } >> + } >> + >> push @iface_config, "arp-accept on" if $ipv4 || $ipv6; >> push @iface_config, "vrf $vrf_iface" if $vrf_iface; >> push(@{ $config->{$vnetid} }, @iface_config) if !$config->{$vnetid}= ; >> @@ -342,6 +367,13 @@ sub generate_sdn_config { >> push @iface_config, "bridge_fd 0"; >> push @iface_config, "mtu $mtu" if $mtu; >> push @iface_config, "vrf $vrf_iface"; >> + >> + if ($enable_forward_v6) { >> + push @iface_config, >> + "post-up echo 1 > /proc/sys/net/ipv6/conf/$brvrf/fo= rce_forwarding"; >> + push @iface_config, >> + "post-down echo 0 > /proc/sys/net/ipv6/conf/$brvrf/= force_forwarding"; >> + } >> push(@{ $config->{$brvrf} }, @iface_config) if !$config->{$= brvrf}; > > emitting `force_forwarding` for the zone `vrfbr_` interfaces is bound to > the first subnet defined on the vnet, if this first one happens to not be > IPv6, `force_forwarding` is missing there Thanks for pointing it out, I overlooked this. The 'vrfbr_' creation happens outside of the subnet loop, but multiple vnets inside a zone share one 'vrfbr_'. This means if the first vnet in the loop contains no ipv6 subnet, the 'vrfbr_' does not recieve the 'force_forwarding' flag.