Skip to content

Commit a72d00a

Browse files
author
Aritra Basu
committed
fix IPv6 ND proxy gateway address handling
ND proxy FIB lookups occur in the receiving interface's VRF. Gateway addresses must be registered to tap interface so NS lookups in the host-tap VRF succeed. Signed-off-by: Aritra Basu <[email protected]>
1 parent 86f489e commit a72d00a

File tree

2 files changed

+70
-3
lines changed

2 files changed

+70
-3
lines changed

vpp-manager/vpp_runner.go

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -644,16 +644,51 @@ func (v *VppRunner) configureVppUplinkInterface(
644644
return errors.Wrap(err, "Error enabling ARP proxy")
645645
}
646646

647+
// Configure ND proxy for IPv6 - ND proxy allows VPP to respond to Neighbor Solicitations
648+
// ND proxy FIB lookups happen in the receiving interface's VRF, so add both cases to tap:
649+
// 1. Host's own addresses: Add to ND proxy table on tap, so VPP responds to NS for host addresses
650+
// 2. Gateway addresses: Add to ND proxy table on tap, so VPP proxies NS arriving from the host
651+
// (VPP responds with NA using its own MAC, then routes traffic to real gateway via uplink)
652+
// The ND proxy feature must be enabled on tap0 (where NS arrives from the host).
653+
654+
hasIPv6 := false
655+
656+
// Add host's own IPv6 addresses to ND proxy on tap interface
647657
for _, addr := range ifState.Addresses {
648658
if addr.IP.To4() == nil {
649-
log.Infof("Adding ND proxy for address %s", addr.IP)
650-
err = v.vpp.EnableIP6NdProxy(tapSwIfIndex, addr.IP)
659+
hasIPv6 = true
660+
log.Infof("Adding ND proxy for host address %s on tap", addr.IP)
661+
err = v.vpp.AddIP6NdProxyAddress(tapSwIfIndex, addr.IP)
662+
if err != nil {
663+
log.Errorf("Error adding ND proxy address %s on tap: %v", addr.IP.String(), err)
664+
}
665+
}
666+
}
667+
668+
// Add gateway addresses to ND proxy on TAP interface
669+
// The ND proxy FIB lookup happens in the interface's VRF, so we must add gateway
670+
// addresses to the tap interface for VPP to respond to NS from the host
671+
// VPP will respond with NA using its own MAC - acting as a proxy for the gateway
672+
for _, route := range ifState.Routes {
673+
if route.Gw != nil && route.Gw.To4() == nil {
674+
hasIPv6 = true
675+
log.Infof("Adding ND proxy for gateway %s on tap (for host NS)", route.Gw)
676+
err = v.vpp.AddIP6NdProxyAddress(tapSwIfIndex, route.Gw)
651677
if err != nil {
652-
log.Errorf("Error configuring nd proxy for address %s: %v", addr.IP.String(), err)
678+
log.Errorf("Error adding ND proxy for gateway %s on tap: %v", route.Gw.String(), err)
653679
}
654680
}
655681
}
656682

683+
// Enable ND proxy feature on tap if we have any IPv6 addresses to proxy
684+
if hasIPv6 {
685+
log.Infof("Enabling ND proxy feature on tap interface")
686+
err = v.vpp.EnableIP6NdProxyFeature(tapSwIfIndex)
687+
if err != nil {
688+
log.Errorf("Error enabling ND proxy feature on tap: %v", err)
689+
}
690+
}
691+
657692
if *config.GetCalicoVppDebug().GSOEnabled {
658693
err = v.vpp.EnableGSOFeature(tapSwIfIndex)
659694
if err != nil {

vpplink/ip6_nd.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,35 @@ func (v *VppLink) EnableIP6NdProxy(swIfIndex uint32, address net.IP) error {
6060

6161
return nil
6262
}
63+
64+
// AddIP6NdProxyAddress adds an address to the ND proxy table for the specified interface.
65+
// This tells VPP to forward NS for this address out the specified interface.
66+
// Note: This does NOT enable ND proxy on the interface - use EnableIP6NdProxyFeature for that.
67+
func (v *VppLink) AddIP6NdProxyAddress(swIfIndex uint32, address net.IP) error {
68+
client := ip6_nd.NewServiceClient(v.GetConnection())
69+
70+
_, err := client.IP6ndProxyAddDel(v.GetContext(), &ip6_nd.IP6ndProxyAddDel{
71+
IsAdd: true,
72+
IP: types.ToVppIP6Address(address),
73+
SwIfIndex: interface_types.InterfaceIndex(swIfIndex),
74+
})
75+
if err != nil {
76+
return fmt.Errorf("failed to add IP6 ND Proxy address %v (swif %d): %w", address, swIfIndex, err)
77+
}
78+
return nil
79+
}
80+
81+
// EnableIP6NdProxyFeature enables the ND proxy feature on an interface.
82+
// Once enabled, VPP will intercept all NDP traffic on this interface and handle it.
83+
func (v *VppLink) EnableIP6NdProxyFeature(swIfIndex uint32) error {
84+
client := ip6_nd.NewServiceClient(v.GetConnection())
85+
86+
_, err := client.IP6ndProxyEnableDisable(v.GetContext(), &ip6_nd.IP6ndProxyEnableDisable{
87+
IsEnable: true,
88+
SwIfIndex: interface_types.InterfaceIndex(swIfIndex),
89+
})
90+
if err != nil {
91+
return fmt.Errorf("failed to enable IP6 ND Proxy feature (swif %d): %w", swIfIndex, err)
92+
}
93+
return nil
94+
}

0 commit comments

Comments
 (0)