connectivity: fix CrossSubnet defaulting to Always with host-prefix#959
Open
connectivity: fix CrossSubnet defaulting to Always with host-prefix#959
Conversation
When the local node's BGP address has a host prefix (/128 for IPv6, /32 for IPv4), GetNodeIPNet() returned a subnet containing only the node itself. This made nodeIPNet.Contains(peer) false for every peer, causing CrossSubnet to behave identically to Always — tunnels were formed to all peers including same-subnet ones. Fixed by querying VPP for the actual subnet mask configured on the main uplink interface. vpp-manager already widens /128 to /64 via getUplinkAddressWithMask() for IPv6 host prefixes. When a host prefix is detected, GetNodeIPNet() calls getUplinkIPNetFromVPP() to retrieve the uplink's configured prefix via AddrList(), using that for the CrossSubnet Contains() check to honor CrossSubnet for host prefix. Signed-off-by: Aritra Basu <aritrbas@cisco.com>
sknat
reviewed
Mar 20, 2026
Collaborator
sknat
left a comment
There was a problem hiding this comment.
Oh, good catch ! I think this could be solved by tweaking a bit vpp_runner.
More details inline
| // "CrossSubnet" to behave like "Always". Fall back to the VPP uplink | ||
| // interface's configured subnet, which vpp-manager already widens from | ||
| // /128 to /64 via getUplinkAddressWithMask() for IPv6 host prefixes. | ||
| ones, bits := ipNet.Mask.Size() |
Collaborator
There was a problem hiding this comment.
Can't this be solved by moving the call to getUplinkAddressWithMask()
to be in GetAddressesAsIPNet() and GetAddresses() ?
If we do this, updateCalicoNode() will advertise the updated /64 in v6 mode,
which we should then receive through felix in nodeBGPSpec
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
CrossSubnetmode for VXLAN and IPIP is not honored when the local node's BGP address has a host prefix (/128for IPv6 or/32for IPv4). Instead, it falls back toAlwaysmode, forming tunnels to all peers including those within the same subnet.RCA
GetNodeIPNet()returns the BGP spec'sIPNetdirectly from Felix'sHostMetadataV4V6Update. When DHCPv6 assigns/128addresses,net.IPNet.Contains()with a/128mask only matches the exact node IP. So, no peer can ever be "same subnet", and every peer gets a tunnel.Fix
Query VPP for the actual subnet mask on the main uplink interface.
vpp-manageralready appliesgetUplinkAddressWithMask()(controlled byTranslateUplinkAddrMaskTo64) which widens/128to/64when configuring the VPP uplink. WhenGetNodeIPNet()detects a host prefix (/128or/32), it callsgetUplinkIPNetFromVPP()which usesvpplink.AddrList()on the main uplink interface to find the matching address and retrieve its actual subnet mask. This ensures we use the real subnet mask from VPP data plane and gracefully degrade to/128BGP net if the VPP query fails.