Skip to content

Commit

Permalink
fix(linux_networking.go): remove dangling IPv6 routes
Browse files Browse the repository at this point in the history
Remove extra routes added by iproute2 when addresses are added to
interfaces which block IPv6 service VIPs from routing from the host.

See: #1698
  • Loading branch information
aauren committed Jul 5, 2024
1 parent 26b539e commit e8962dd
Showing 1 changed file with 31 additions and 0 deletions.
31 changes: 31 additions & 0 deletions pkg/controllers/proxy/linux_networking.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/moby/ipvs"
"github.com/vishvananda/netlink"
"github.com/vishvananda/netns"
"golang.org/x/sys/unix"
"k8s.io/klog/v2"
)

Expand Down Expand Up @@ -129,6 +130,7 @@ func (ln *linuxNetworking) ipAddrDel(iface netlink.Link, ip string, nodeIP strin
func (ln *linuxNetworking) ipAddrAdd(iface netlink.Link, ip string, nodeIP string, addRoute bool) error {
var netMask net.IPMask
var ipRouteCmdArgs []string
var isIPv6 bool
parsedIP := net.ParseIP(ip)
parsedNodeIP := net.ParseIP(nodeIP)
if parsedIP.To4() != nil {
Expand All @@ -139,6 +141,7 @@ func (ln *linuxNetworking) ipAddrAdd(iface netlink.Link, ip string, nodeIP strin

netMask = net.CIDRMask(ipv4NetMaskBits, ipv4NetMaskBits)
ipRouteCmdArgs = make([]string, 0)
isIPv6 = false
} else {
// If we're supposed to add a route and the IP family of the NodeIP and the VIP IP don't match, we can't proceed
if addRoute && parsedNodeIP.To4() != nil {
Expand All @@ -147,6 +150,7 @@ func (ln *linuxNetworking) ipAddrAdd(iface netlink.Link, ip string, nodeIP strin

netMask = net.CIDRMask(ipv6NetMaskBits, ipv6NetMaskBits)
ipRouteCmdArgs = []string{"-6"}
isIPv6 = true
}

naddr := &netlink.Addr{IPNet: &net.IPNet{IP: parsedIP, Mask: netMask}, Scope: syscall.RT_SCOPE_LINK}
Expand Down Expand Up @@ -177,6 +181,33 @@ func (ln *linuxNetworking) ipAddrAdd(iface netlink.Link, ip string, nodeIP strin
return err
}

// IPv6 address adds in iproute2 appear to create some misc routes that will interfere with the source routing that
// we attempt to do below and cuased the issue commented on above. We need to remove those before we attempt to
// create the source route below. See: https://github.com/cloudnativelabs/kube-router/issues/1698
if isIPv6 {
nRoute := &netlink.Route{
Dst: &net.IPNet{IP: parsedIP, Mask: netMask},
Table: unix.RT_TABLE_UNSPEC,
}
routes, err := netlink.RouteListFiltered(netlink.FAMILY_V6, nRoute,
netlink.RT_FILTER_DST|netlink.RT_FILTER_TABLE)
if err != nil {
klog.Errorf("failed to list routes for interface %s: %v", iface.Attrs().Name, err)
return err
}
for idx, route := range routes {
klog.V(1).Infof("Checking route %s for interface %s...", route, iface.Attrs().Name)
// Looking for routes where the destination matches our VIP AND the source is either nil or not the node IP
if route.Src == nil || !route.Src.Equal(parsedNodeIP) {
klog.V(1).Infof("Deleting route %s for interface %s...", route, iface.Attrs().Name)
err = netlink.RouteDel(&routes[idx])
if err != nil {
klog.Errorf("failed to delete route %s for interface %s: %v", route, iface.Attrs().Name, err)
}
}
}
}

return nil
}

Expand Down

0 comments on commit e8962dd

Please sign in to comment.