Skip to content

Commit e8962dd

Browse files
committed
fix(linux_networking.go): remove dangling IPv6 routes
Remove extra routes added by iproute2 when addresses are added to interfaces which block IPv6 service VIPs from routing from the host. See: #1698
1 parent 26b539e commit e8962dd

File tree

1 file changed

+31
-0
lines changed

1 file changed

+31
-0
lines changed

pkg/controllers/proxy/linux_networking.go

+31
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/moby/ipvs"
1919
"github.com/vishvananda/netlink"
2020
"github.com/vishvananda/netns"
21+
"golang.org/x/sys/unix"
2122
"k8s.io/klog/v2"
2223
)
2324

@@ -129,6 +130,7 @@ func (ln *linuxNetworking) ipAddrDel(iface netlink.Link, ip string, nodeIP strin
129130
func (ln *linuxNetworking) ipAddrAdd(iface netlink.Link, ip string, nodeIP string, addRoute bool) error {
130131
var netMask net.IPMask
131132
var ipRouteCmdArgs []string
133+
var isIPv6 bool
132134
parsedIP := net.ParseIP(ip)
133135
parsedNodeIP := net.ParseIP(nodeIP)
134136
if parsedIP.To4() != nil {
@@ -139,6 +141,7 @@ func (ln *linuxNetworking) ipAddrAdd(iface netlink.Link, ip string, nodeIP strin
139141

140142
netMask = net.CIDRMask(ipv4NetMaskBits, ipv4NetMaskBits)
141143
ipRouteCmdArgs = make([]string, 0)
144+
isIPv6 = false
142145
} else {
143146
// 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
144147
if addRoute && parsedNodeIP.To4() != nil {
@@ -147,6 +150,7 @@ func (ln *linuxNetworking) ipAddrAdd(iface netlink.Link, ip string, nodeIP strin
147150

148151
netMask = net.CIDRMask(ipv6NetMaskBits, ipv6NetMaskBits)
149152
ipRouteCmdArgs = []string{"-6"}
153+
isIPv6 = true
150154
}
151155

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

184+
// IPv6 address adds in iproute2 appear to create some misc routes that will interfere with the source routing that
185+
// we attempt to do below and cuased the issue commented on above. We need to remove those before we attempt to
186+
// create the source route below. See: https://github.com/cloudnativelabs/kube-router/issues/1698
187+
if isIPv6 {
188+
nRoute := &netlink.Route{
189+
Dst: &net.IPNet{IP: parsedIP, Mask: netMask},
190+
Table: unix.RT_TABLE_UNSPEC,
191+
}
192+
routes, err := netlink.RouteListFiltered(netlink.FAMILY_V6, nRoute,
193+
netlink.RT_FILTER_DST|netlink.RT_FILTER_TABLE)
194+
if err != nil {
195+
klog.Errorf("failed to list routes for interface %s: %v", iface.Attrs().Name, err)
196+
return err
197+
}
198+
for idx, route := range routes {
199+
klog.V(1).Infof("Checking route %s for interface %s...", route, iface.Attrs().Name)
200+
// Looking for routes where the destination matches our VIP AND the source is either nil or not the node IP
201+
if route.Src == nil || !route.Src.Equal(parsedNodeIP) {
202+
klog.V(1).Infof("Deleting route %s for interface %s...", route, iface.Attrs().Name)
203+
err = netlink.RouteDel(&routes[idx])
204+
if err != nil {
205+
klog.Errorf("failed to delete route %s for interface %s: %v", route, iface.Attrs().Name, err)
206+
}
207+
}
208+
}
209+
}
210+
180211
return nil
181212
}
182213

0 commit comments

Comments
 (0)