github.com/elfadel/cilium@v1.6.12/pkg/datapath/linux/node.go (about) 1 // Copyright 2018-2019 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package linux 16 17 import ( 18 "fmt" 19 "net" 20 "os" 21 "syscall" 22 23 "github.com/cilium/cilium/pkg/cidr" 24 "github.com/cilium/cilium/pkg/datapath" 25 "github.com/cilium/cilium/pkg/datapath/linux/ipsec" 26 "github.com/cilium/cilium/pkg/datapath/linux/linux_defaults" 27 "github.com/cilium/cilium/pkg/datapath/linux/route" 28 "github.com/cilium/cilium/pkg/lock" 29 "github.com/cilium/cilium/pkg/logging/logfields" 30 "github.com/cilium/cilium/pkg/maps/tunnel" 31 "github.com/cilium/cilium/pkg/node" 32 "github.com/cilium/cilium/pkg/option" 33 34 "github.com/cilium/arping" 35 "github.com/sirupsen/logrus" 36 "github.com/vishvananda/netlink" 37 ) 38 39 var ( 40 wildcardIPv4 = "0.0.0.0" 41 wildcardIPv6 = "0::0" 42 ) 43 44 type linuxNodeHandler struct { 45 mutex lock.Mutex 46 isInitialized bool 47 nodeConfig datapath.LocalNodeConfiguration 48 nodeAddressing datapath.NodeAddressing 49 datapathConfig DatapathConfiguration 50 nodes map[node.Identity]*node.Node 51 enableNeighDiscovery bool 52 neighByNode map[node.Identity]*netlink.Neigh 53 } 54 55 // NewNodeHandler returns a new node handler to handle node events and 56 // implement the implications in the Linux datapath 57 func NewNodeHandler(datapathConfig DatapathConfiguration, nodeAddressing datapath.NodeAddressing) datapath.NodeHandler { 58 return &linuxNodeHandler{ 59 nodeAddressing: nodeAddressing, 60 datapathConfig: datapathConfig, 61 nodes: map[node.Identity]*node.Node{}, 62 neighByNode: map[node.Identity]*netlink.Neigh{}, 63 } 64 } 65 66 // updateTunnelMapping is called when a node update is received while running 67 // with encapsulation mode enabled. The CIDR and IP of both the old and new 68 // node are provided as context. The caller expects the tunnel mapping in the 69 // datapath to be updated. 70 func updateTunnelMapping(oldCIDR, newCIDR *cidr.CIDR, oldIP, newIP net.IP, firstAddition, encapEnabled bool, oldEncryptKey, newEncryptKey uint8) { 71 if !encapEnabled { 72 // When the protocol family is disabled, the initial node addition will 73 // trigger a deletion to clean up leftover entries. The deletion happens 74 // in quiet mode as we don't know whether it exists or not 75 if newCIDR != nil && firstAddition { 76 deleteTunnelMapping(newCIDR, true) 77 } 78 79 return 80 } 81 82 if cidrNodeMappingUpdateRequired(oldCIDR, newCIDR, oldIP, newIP, oldEncryptKey, newEncryptKey) { 83 log.WithFields(logrus.Fields{ 84 logfields.IPAddr: newIP, 85 "allocCIDR": newCIDR, 86 }).Debug("Updating tunnel map entry") 87 88 if err := tunnel.TunnelMap.SetTunnelEndpoint(newEncryptKey, newCIDR.IP, newIP); err != nil { 89 log.WithError(err).WithFields(logrus.Fields{ 90 "allocCIDR": newCIDR, 91 }).Error("bpf: Unable to update in tunnel endpoint map") 92 } 93 } 94 95 // Determine whether an old tunnel mapping must be cleaned up. The 96 // below switch lists all conditions in which case the oldCIDR must be 97 // removed from the tunnel mapping 98 switch { 99 // CIDR no longer announced 100 case newCIDR == nil && oldCIDR != nil: 101 fallthrough 102 // Node allocation CIDR has changed 103 case oldCIDR != nil && newCIDR != nil && !oldCIDR.IP.Equal(newCIDR.IP): 104 deleteTunnelMapping(oldCIDR, false) 105 } 106 } 107 108 // cidrNodeMappingUpdateRequired returns true if the change from an old node 109 // CIDR and node IP to a new node CIDR and node IP requires to insert/update 110 // the new node CIDR. 111 func cidrNodeMappingUpdateRequired(oldCIDR, newCIDR *cidr.CIDR, oldIP, newIP net.IP, oldKey, newKey uint8) bool { 112 // No CIDR provided 113 if newCIDR == nil { 114 return false 115 } 116 // Newly announced CIDR 117 if oldCIDR == nil { 118 return true 119 } 120 121 // Change in node IP 122 if !oldIP.Equal(newIP) { 123 return true 124 } 125 126 if newKey != oldKey { 127 return true 128 } 129 130 // CIDR changed 131 return !oldCIDR.IP.Equal(newCIDR.IP) 132 } 133 134 func deleteTunnelMapping(oldCIDR *cidr.CIDR, quietMode bool) { 135 if oldCIDR == nil { 136 return 137 } 138 139 log.WithField("allocCIDR", oldCIDR).Debug("Deleting tunnel map entry") 140 141 if err := tunnel.TunnelMap.DeleteTunnelEndpoint(oldCIDR.IP); err != nil { 142 if !quietMode { 143 log.WithError(err).WithFields(logrus.Fields{ 144 "allocCIDR": oldCIDR, 145 }).Error("Unable to delete in tunnel endpoint map") 146 } 147 } 148 } 149 150 func createDirectRouteSpec(CIDR *cidr.CIDR, nodeIP net.IP) (routeSpec *netlink.Route, err error) { 151 var routes []netlink.Route 152 153 routeSpec = &netlink.Route{ 154 Dst: CIDR.IPNet, 155 Gw: nodeIP, 156 } 157 158 routes, err = netlink.RouteGet(nodeIP) 159 if err != nil { 160 err = fmt.Errorf("unable to lookup route for node %s: %s", nodeIP, err) 161 return 162 } 163 164 if len(routes) == 0 { 165 err = fmt.Errorf("no route found to destination %s", nodeIP.String()) 166 return 167 } 168 169 if routes[0].Gw != nil && !routes[0].Gw.IsUnspecified() && !routes[0].Gw.Equal(nodeIP) { 170 err = fmt.Errorf("route to destination %s contains gateway %s, must be directly reachable", 171 nodeIP, routes[0].Gw.String()) 172 return 173 } 174 175 linkIndex := routes[0].LinkIndex 176 177 // Special treatment if the route points to the loopback, lookup the 178 // local route and use that ifindex 179 if linkIndex == 1 { 180 family := netlink.FAMILY_V4 181 dst := &net.IPNet{IP: nodeIP, Mask: net.CIDRMask(32, 32)} 182 if nodeIP.To4() == nil { 183 family = netlink.FAMILY_V6 184 dst.Mask = net.CIDRMask(128, 128) 185 } 186 187 filter := &netlink.Route{ 188 Table: 255, // local table 189 Dst: dst, 190 } 191 192 routes, err = netlink.RouteListFiltered(family, filter, netlink.RT_FILTER_DST|netlink.RT_FILTER_TABLE) 193 if err != nil { 194 err = fmt.Errorf("unable to find local route for destination %s: %s", nodeIP, err) 195 return 196 } 197 198 if len(routes) == 0 { 199 err = fmt.Errorf("unable to find local route for destination %s which is routed over loopback", nodeIP) 200 return 201 } 202 203 linkIndex = routes[0].LinkIndex 204 } 205 206 routeSpec.LinkIndex = linkIndex 207 208 return 209 } 210 211 func installDirectRoute(CIDR *cidr.CIDR, nodeIP net.IP) (routeSpec *netlink.Route, err error) { 212 routeSpec, err = createDirectRouteSpec(CIDR, nodeIP) 213 if err != nil { 214 return 215 } 216 217 err = netlink.RouteReplace(routeSpec) 218 return 219 } 220 221 func (n *linuxNodeHandler) lookupDirectRoute(CIDR *cidr.CIDR, nodeIP net.IP) ([]netlink.Route, error) { 222 routeSpec, err := createDirectRouteSpec(CIDR, nodeIP) 223 if err != nil { 224 return nil, err 225 } 226 227 family := netlink.FAMILY_V4 228 if nodeIP.To4() == nil { 229 family = netlink.FAMILY_V6 230 } 231 return netlink.RouteListFiltered(family, routeSpec, netlink.RT_FILTER_DST|netlink.RT_FILTER_GW|netlink.RT_FILTER_OIF) 232 } 233 234 func (n *linuxNodeHandler) updateDirectRoute(oldCIDR, newCIDR *cidr.CIDR, oldIP, newIP net.IP, firstAddition, directRouteEnabled bool) error { 235 if !directRouteEnabled { 236 // When the protocol family is disabled, the initial node addition will 237 // trigger a deletion to clean up leftover entries. The deletion happens 238 // in quiet mode as we don't know whether it exists or not 239 if newCIDR != nil && firstAddition { 240 n.deleteDirectRoute(newCIDR, newIP) 241 } 242 return nil 243 } 244 245 if cidrNodeMappingUpdateRequired(oldCIDR, newCIDR, oldIP, newIP, 0, 0) { 246 log.WithFields(logrus.Fields{ 247 logfields.IPAddr: newIP, 248 "allocCIDR": newCIDR, 249 }).Debug("Updating direct route") 250 251 if routeSpec, err := installDirectRoute(newCIDR, newIP); err != nil { 252 log.WithError(err).Warningf("Unable to install direct node route %s", routeSpec.String()) 253 return err 254 } 255 } 256 257 // Determine whether an old route must be deleted. The below switch 258 // lists all conditions in which case the route derived from oldCIDR 259 // and oldIP must be deleted. 260 switch { 261 // CIDR no longer announced 262 case newCIDR == nil && oldCIDR != nil: 263 fallthrough 264 // node IP has changed 265 case !oldIP.Equal(newIP): 266 fallthrough 267 // Node allocation CIDR has changed 268 case oldCIDR != nil && newCIDR != nil && !oldCIDR.IP.Equal(newCIDR.IP): 269 n.deleteDirectRoute(oldCIDR, oldIP) 270 } 271 272 return nil 273 } 274 275 func (n *linuxNodeHandler) deleteDirectRoute(CIDR *cidr.CIDR, nodeIP net.IP) { 276 if CIDR == nil { 277 return 278 } 279 280 family := netlink.FAMILY_V4 281 if CIDR.IP.To4() == nil { 282 family = netlink.FAMILY_V6 283 } 284 285 filter := &netlink.Route{ 286 Dst: CIDR.IPNet, 287 Gw: nodeIP, 288 } 289 290 routes, err := netlink.RouteListFiltered(family, filter, netlink.RT_FILTER_DST|netlink.RT_FILTER_GW) 291 if err != nil { 292 log.WithError(err).Error("Unable to list direct routes") 293 return 294 } 295 296 for _, rt := range routes { 297 if err := netlink.RouteDel(&rt); err != nil { 298 log.WithError(err).Warningf("Unable to delete direct node route %s", rt.String()) 299 } 300 } 301 } 302 303 // createNodeRoute creates a route that points the specified prefix to the host 304 // device via the router IP 305 // 306 // Example: 307 // 10.10.0.0/24 via 10.10.0.1 dev cilium_host src 10.10.0.1 308 // f00d::a0a:0:0:0/112 via f00d::a0a:0:0:1 dev cilium_host src fd04::11 metric 1024 pref medium 309 // 310 func (n *linuxNodeHandler) createNodeRoute(prefix *cidr.CIDR) (route.Route, error) { 311 var local, nexthop net.IP 312 if prefix.IP.To4() != nil { 313 if n.nodeAddressing.IPv4() == nil { 314 return route.Route{}, fmt.Errorf("IPv4 addressing unavailable") 315 } 316 317 if n.nodeAddressing.IPv4().Router() == nil { 318 return route.Route{}, fmt.Errorf("IPv4 router address unavailable") 319 } 320 321 nexthop = n.nodeAddressing.IPv4().Router() 322 local = nexthop 323 } else { 324 if n.nodeAddressing.IPv6() == nil { 325 return route.Route{}, fmt.Errorf("IPv6 addressing unavailable") 326 } 327 328 if n.nodeAddressing.IPv6().Router() == nil { 329 return route.Route{}, fmt.Errorf("IPv6 router address unavailable") 330 } 331 332 if n.nodeAddressing.IPv6().PrimaryExternal() == nil { 333 return route.Route{}, fmt.Errorf("External IPv6 address unavailable") 334 } 335 336 nexthop = n.nodeAddressing.IPv6().Router() 337 local = n.nodeAddressing.IPv6().PrimaryExternal() 338 } 339 340 // The default routing table accounts for encryption overhead for encrypt-node traffic 341 return route.Route{ 342 Nexthop: &nexthop, 343 Local: local, 344 Device: n.datapathConfig.HostDevice, 345 Prefix: *prefix.IPNet, 346 MTU: n.nodeConfig.MtuConfig.GetRouteMTU(), 347 }, nil 348 } 349 350 func (n *linuxNodeHandler) lookupNodeRoute(prefix *cidr.CIDR) (*route.Route, error) { 351 if prefix == nil { 352 return nil, nil 353 } 354 355 routeSpec, err := n.createNodeRoute(prefix) 356 if err != nil { 357 return nil, err 358 } 359 360 return route.Lookup(routeSpec) 361 } 362 363 func (n *linuxNodeHandler) updateNodeRoute(prefix *cidr.CIDR, addressFamilyEnabled bool) error { 364 if prefix == nil || !addressFamilyEnabled { 365 return nil 366 } 367 368 nodeRoute, err := n.createNodeRoute(prefix) 369 if err != nil { 370 return err 371 } 372 if _, err := route.Upsert(nodeRoute); err != nil { 373 log.WithError(err).WithFields(nodeRoute.LogFields()).Warning("Unable to update route") 374 return err 375 } 376 377 return nil 378 } 379 380 func (n *linuxNodeHandler) deleteNodeRoute(prefix *cidr.CIDR) error { 381 if prefix == nil { 382 return nil 383 } 384 385 nodeRoute, err := n.createNodeRoute(prefix) 386 if err != nil { 387 return err 388 } 389 if err := route.Delete(nodeRoute); err != nil { 390 log.WithError(err).WithFields(nodeRoute.LogFields()).Warning("Unable to delete route") 391 return err 392 } 393 394 return nil 395 } 396 397 func (n *linuxNodeHandler) familyEnabled(c *cidr.CIDR) bool { 398 return (c.IP.To4() != nil && n.nodeConfig.EnableIPv4) || (c.IP.To4() == nil && n.nodeConfig.EnableIPv6) 399 } 400 401 func (n *linuxNodeHandler) updateOrRemoveNodeRoutes(old, new []*cidr.CIDR) { 402 addedAuxRoutes, removedAuxRoutes := cidr.DiffCIDRLists(old, new) 403 for _, prefix := range addedAuxRoutes { 404 if prefix != nil { 405 n.updateNodeRoute(prefix, n.familyEnabled(prefix)) 406 } 407 } 408 for _, prefix := range removedAuxRoutes { 409 if rt, _ := n.lookupNodeRoute(prefix); rt != nil { 410 n.deleteNodeRoute(prefix) 411 } 412 } 413 } 414 415 func (n *linuxNodeHandler) NodeAdd(newNode node.Node) error { 416 n.mutex.Lock() 417 defer n.mutex.Unlock() 418 419 n.nodes[newNode.Identity()] = &newNode 420 421 if n.isInitialized { 422 return n.nodeUpdate(nil, &newNode, true) 423 } 424 425 return nil 426 } 427 428 func (n *linuxNodeHandler) NodeUpdate(oldNode, newNode node.Node) error { 429 n.mutex.Lock() 430 defer n.mutex.Unlock() 431 432 n.nodes[newNode.Identity()] = &newNode 433 434 if n.isInitialized { 435 return n.nodeUpdate(&oldNode, &newNode, false) 436 } 437 438 return nil 439 } 440 441 func upsertIPsecLog(err error, spec string, loc, rem *net.IPNet, spi uint8) { 442 scopedLog := log.WithFields(logrus.Fields{ 443 logfields.Reason: spec, 444 "local-ip": loc, 445 "remote-ip": rem, 446 "spi": spi, 447 }) 448 if err != nil { 449 scopedLog.WithError(err).Error("IPsec enable failed") 450 } else { 451 scopedLog.Debug("IPsec enable succeeded") 452 } 453 } 454 455 func (n *linuxNodeHandler) enableSubnetIPsec(v4CIDR, v6CIDR []*net.IPNet) { 456 var spi uint8 457 var err error 458 459 n.replaceHostRules() 460 461 for _, cidr := range v4CIDR { 462 ipsecIPv4Wildcard := &net.IPNet{IP: net.ParseIP(wildcardIPv4), Mask: net.IPv4Mask(0, 0, 0, 0)} 463 464 n.replaceNodeIPSecInRoute(cidr) 465 466 n.replaceNodeIPSecOutRoute(cidr) 467 spi, err = ipsec.UpsertIPsecEndpoint(ipsecIPv4Wildcard, cidr, ipsec.IPSecDirOut, true) 468 upsertIPsecLog(err, "CNI Out IPv4", ipsecIPv4Wildcard, cidr, spi) 469 470 n.replaceNodeExternalIPSecOutRoute(cidr) 471 } 472 473 for _, cidr := range v6CIDR { 474 ipsecIPv6Wildcard := &net.IPNet{IP: net.ParseIP(wildcardIPv6), Mask: net.CIDRMask(0, 0)} 475 476 n.replaceNodeIPSecInRoute(cidr) 477 478 n.replaceNodeIPSecOutRoute(cidr) 479 spi, err := ipsec.UpsertIPsecEndpoint(ipsecIPv6Wildcard, cidr, ipsec.IPSecDirOut, true) 480 upsertIPsecLog(err, "CNI Out IPv6", cidr, ipsecIPv6Wildcard, spi) 481 482 n.replaceNodeExternalIPSecOutRoute(cidr) 483 } 484 } 485 486 func (n *linuxNodeHandler) encryptNode(newNode *node.Node) { 487 var spi uint8 488 var err error 489 490 if n.nodeConfig.EnableIPv4 && n.nodeConfig.EncryptNode { 491 internalIPv4 := n.nodeAddressing.IPv4().PrimaryExternal() 492 exactMask := net.IPv4Mask(255, 255, 255, 255) 493 ipsecLocal := &net.IPNet{IP: internalIPv4, Mask: exactMask} 494 if newNode.IsLocal() { 495 ipsecIPv4Wildcard := &net.IPNet{IP: net.ParseIP(wildcardIPv4), Mask: net.IPv4Mask(0, 0, 0, 0)} 496 n.replaceNodeIPSecInRoute(ipsecLocal) 497 spi, err = ipsec.UpsertIPsecEndpoint(ipsecLocal, ipsecIPv4Wildcard, ipsec.IPSecDirIn, true) 498 upsertIPsecLog(err, "EncryptNode local IPv4", ipsecLocal, ipsecIPv4Wildcard, spi) 499 } else { 500 if remoteIPv4 := newNode.GetNodeIP(false); remoteIPv4 != nil { 501 ipsecRemote := &net.IPNet{IP: remoteIPv4, Mask: exactMask} 502 n.replaceNodeExternalIPSecOutRoute(ipsecRemote) 503 spi, err = ipsec.UpsertIPsecEndpoint(ipsecLocal, ipsecRemote, ipsec.IPSecDirOutNode, true) 504 upsertIPsecLog(err, "EncryptNode IPv4", ipsecLocal, ipsecRemote, spi) 505 } 506 remoteIPv4 := newNode.GetCiliumInternalIP(false) 507 if remoteIPv4 != nil && !n.subnetEncryption() { 508 mask := newNode.IPv4AllocCIDR.Mask 509 ipsecRemoteRoute := &net.IPNet{IP: remoteIPv4.Mask(mask), Mask: mask} 510 ipsecRemote := &net.IPNet{IP: remoteIPv4, Mask: mask} 511 ipsecWildcard := &net.IPNet{IP: net.ParseIP(wildcardIPv4), Mask: net.IPv4Mask(0, 0, 0, 0)} 512 513 n.replaceNodeExternalIPSecOutRoute(ipsecRemoteRoute) 514 if remoteIPv4T := newNode.GetNodeIP(false); remoteIPv4T != nil { 515 ipsecRemoteT := &net.IPNet{IP: remoteIPv4T, Mask: exactMask} 516 err = ipsec.UpsertIPsecEndpointPolicy(ipsecWildcard, ipsecRemote, ipsecLocal, ipsecRemoteT, ipsec.IPSecDirOutNode) 517 } 518 upsertIPsecLog(err, "EncryptNode Cilium IPv4", ipsecWildcard, ipsecRemote, spi) 519 } 520 } 521 } 522 523 if n.nodeConfig.EnableIPv6 && n.nodeConfig.EncryptNode { 524 internalIPv6 := n.nodeAddressing.IPv6().PrimaryExternal() 525 exactMask := net.CIDRMask(128, 128) 526 ipsecLocal := &net.IPNet{IP: internalIPv6, Mask: exactMask} 527 if newNode.IsLocal() { 528 ipsecIPv6Wildcard := &net.IPNet{IP: net.ParseIP(wildcardIPv6), Mask: net.CIDRMask(0, 0)} 529 n.replaceNodeIPSecInRoute(ipsecLocal) 530 spi, err = ipsec.UpsertIPsecEndpoint(ipsecLocal, ipsecIPv6Wildcard, ipsec.IPSecDirIn, true) 531 upsertIPsecLog(err, "EncryptNode local IPv6", ipsecLocal, ipsecIPv6Wildcard, spi) 532 } else { 533 if remoteIPv6 := newNode.GetNodeIP(true); remoteIPv6 != nil { 534 ipsecRemote := &net.IPNet{IP: remoteIPv6, Mask: exactMask} 535 n.replaceNodeExternalIPSecOutRoute(ipsecRemote) 536 spi, err = ipsec.UpsertIPsecEndpoint(ipsecLocal, ipsecRemote, ipsec.IPSecDirOut, true) 537 upsertIPsecLog(err, "EncryptNode IPv6", ipsecLocal, ipsecRemote, spi) 538 } 539 remoteIPv6 := newNode.GetCiliumInternalIP(true) 540 if remoteIPv6 != nil && !n.subnetEncryption() { 541 mask := newNode.IPv6AllocCIDR.Mask 542 ipsecRemoteRoute := &net.IPNet{IP: remoteIPv6.Mask(mask), Mask: mask} 543 ipsecRemote := &net.IPNet{IP: remoteIPv6, Mask: mask} 544 ipsecWildcard := &net.IPNet{IP: net.ParseIP(wildcardIPv6), Mask: net.CIDRMask(0, 0)} 545 546 n.replaceNodeExternalIPSecOutRoute(ipsecRemoteRoute) 547 if remoteIPv6T := newNode.GetNodeIP(true); remoteIPv6T != nil { 548 ipsecRemoteT := &net.IPNet{IP: remoteIPv6T, Mask: exactMask} 549 err = ipsec.UpsertIPsecEndpointPolicy(ipsecWildcard, ipsecRemote, ipsecLocal, ipsecRemoteT, ipsec.IPSecDirOutNode) 550 } 551 upsertIPsecLog(err, "EncryptNode Cilium IPv6", ipsecWildcard, ipsecRemote, spi) 552 } 553 } 554 } 555 556 } 557 558 func neighborLog(spec, iface string, err error, ip *net.IP, hwAddr *net.HardwareAddr, link int) { 559 scopedLog := log.WithFields(logrus.Fields{ 560 logfields.Reason: spec, 561 "Interface": iface, 562 logfields.IPAddr: ip, 563 "HardwareAddr": hwAddr, 564 "LinkIndex": link, 565 }) 566 567 if err != nil { 568 scopedLog.WithError(err).Error("insertNeighbor failed") 569 } else { 570 scopedLog.Debug("insertNeighbor") 571 } 572 } 573 574 func (n *linuxNodeHandler) insertNeighbor(newNode *node.Node, ifaceName string) { 575 if newNode.IsLocal() { 576 return 577 } 578 579 ciliumIPv4 := newNode.GetNodeIP(false) 580 var hwAddr net.HardwareAddr 581 link := 0 582 583 iface, err := net.InterfaceByName(ifaceName) 584 if err != nil { 585 neighborLog("insertNeightbor InterfaceByName", ifaceName, err, &ciliumIPv4, &hwAddr, link) 586 return 587 } 588 589 _, err = arping.FindIPInNetworkFromIface(ciliumIPv4, *iface) 590 if err != nil { 591 neighborLog("insertNeightbor IP not L2 reachable", ifaceName, nil, &ciliumIPv4, &hwAddr, link) 592 return 593 } 594 595 linkAttr, err := netlink.LinkByName(ifaceName) 596 if err != nil { 597 neighborLog("insertNeightbor LinkByName", ifaceName, err, &ciliumIPv4, &hwAddr, link) 598 return 599 } 600 link = linkAttr.Attrs().Index 601 602 if hwAddr, _, err := arping.PingOverIface(ciliumIPv4, *iface); err == nil { 603 neigh := netlink.Neigh{ 604 LinkIndex: link, 605 IP: ciliumIPv4, 606 HardwareAddr: hwAddr, 607 State: netlink.NUD_PERMANENT, 608 } 609 err := netlink.NeighSet(&neigh) 610 neighborLog("insertNeighbor NeighSet", ifaceName, err, &ciliumIPv4, &hwAddr, link) 611 if err == nil { 612 n.neighByNode[newNode.Identity()] = &neigh 613 } 614 } else { 615 neighborLog("insertNeighbor arping failed", ifaceName, err, &ciliumIPv4, &hwAddr, link) 616 } 617 } 618 619 func (n *linuxNodeHandler) deleteNeighbor(oldNode *node.Node) { 620 neigh, ok := n.neighByNode[oldNode.Identity()] 621 if !ok { 622 return 623 } 624 625 if err := netlink.NeighDel(neigh); err != nil { 626 log.WithFields(logrus.Fields{ 627 logfields.IPAddr: neigh.IP, 628 "HardwareAddr": neigh.HardwareAddr, 629 "LinkIndex": neigh.LinkIndex, 630 }).WithError(err).Warn("Failed to remove neighbor entry") 631 } 632 } 633 634 func (n *linuxNodeHandler) enableIPsec(newNode *node.Node) { 635 var spi uint8 636 var err error 637 638 if newNode.IsLocal() { 639 n.replaceHostRules() 640 } 641 642 if n.nodeConfig.EnableIPv4 && newNode.IPv4AllocCIDR != nil { 643 new4Net := &net.IPNet{IP: newNode.IPv4AllocCIDR.IP, Mask: newNode.IPv4AllocCIDR.Mask} 644 if newNode.IsLocal() { 645 n.replaceNodeIPSecInRoute(new4Net) 646 ciliumInternalIPv4 := newNode.GetCiliumInternalIP(false) 647 if ciliumInternalIPv4 != nil { 648 ipsecLocal := &net.IPNet{IP: ciliumInternalIPv4, Mask: n.nodeAddressing.IPv4().AllocationCIDR().Mask} 649 ipsecIPv4Wildcard := &net.IPNet{IP: net.ParseIP(wildcardIPv4), Mask: net.IPv4Mask(0, 0, 0, 0)} 650 spi, err = ipsec.UpsertIPsecEndpoint(ipsecLocal, ipsecIPv4Wildcard, ipsec.IPSecDirIn, n.nodeConfig.EncryptNode) 651 upsertIPsecLog(err, "local IPv4", ipsecLocal, ipsecIPv4Wildcard, spi) 652 } 653 } else { 654 if ciliumInternalIPv4 := newNode.GetCiliumInternalIP(false); ciliumInternalIPv4 != nil { 655 ipsecLocal := &net.IPNet{IP: n.nodeAddressing.IPv4().Router(), Mask: n.nodeAddressing.IPv4().AllocationCIDR().Mask} 656 ipsecRemote := &net.IPNet{IP: ciliumInternalIPv4, Mask: newNode.IPv4AllocCIDR.Mask} 657 n.replaceNodeIPSecOutRoute(new4Net) 658 spi, err = ipsec.UpsertIPsecEndpoint(ipsecLocal, ipsecRemote, ipsec.IPSecDirOut, n.nodeConfig.EncryptNode) 659 upsertIPsecLog(err, "IPv4", ipsecLocal, ipsecRemote, spi) 660 } 661 } 662 } 663 664 if n.nodeConfig.EnableIPv6 && newNode.IPv6AllocCIDR != nil { 665 new6Net := &net.IPNet{IP: newNode.IPv6AllocCIDR.IP, Mask: newNode.IPv6AllocCIDR.Mask} 666 if newNode.IsLocal() { 667 n.replaceNodeIPSecInRoute(new6Net) 668 ciliumInternalIPv6 := newNode.GetCiliumInternalIP(true) 669 if ciliumInternalIPv6 != nil { 670 ipsecLocal := &net.IPNet{IP: ciliumInternalIPv6, Mask: n.nodeAddressing.IPv6().AllocationCIDR().Mask} 671 ipsecIPv6Wildcard := &net.IPNet{IP: net.ParseIP(wildcardIPv6), Mask: net.CIDRMask(0, 0)} 672 spi, err = ipsec.UpsertIPsecEndpoint(ipsecLocal, ipsecIPv6Wildcard, ipsec.IPSecDirIn, n.nodeConfig.EncryptNode) 673 upsertIPsecLog(err, "local IPv6", ipsecLocal, ipsecIPv6Wildcard, spi) 674 } 675 } else { 676 if ciliumInternalIPv6 := newNode.GetCiliumInternalIP(true); ciliumInternalIPv6 != nil { 677 ipsecLocalWildcard := &net.IPNet{IP: net.ParseIP(wildcardIPv6), Mask: net.CIDRMask(0, 0)} 678 ipsecRemote := &net.IPNet{IP: ciliumInternalIPv6, Mask: newNode.IPv6AllocCIDR.Mask} 679 n.replaceNodeIPSecOutRoute(new6Net) 680 spi, err := ipsec.UpsertIPsecEndpoint(ipsecLocalWildcard, ipsecRemote, ipsec.IPSecDirOut, n.nodeConfig.EncryptNode) 681 upsertIPsecLog(err, "IPv6", ipsecLocalWildcard, ipsecRemote, spi) 682 } 683 } 684 } 685 } 686 687 func (n *linuxNodeHandler) subnetEncryption() bool { 688 return len(n.nodeConfig.IPv4PodSubnets) > 0 || len(n.nodeConfig.IPv6PodSubnets) > 0 689 } 690 691 func (n *linuxNodeHandler) nodeUpdate(oldNode, newNode *node.Node, firstAddition bool) error { 692 var ( 693 oldIP4Cidr, oldIP6Cidr *cidr.CIDR 694 oldIP4, oldIP6 net.IP 695 newIP4 = newNode.GetNodeIP(false) 696 newIP6 = newNode.GetNodeIP(true) 697 oldKey, newKey uint8 698 ) 699 700 if oldNode != nil { 701 oldIP4Cidr = oldNode.IPv4AllocCIDR 702 oldIP6Cidr = oldNode.IPv6AllocCIDR 703 oldIP4 = oldNode.GetNodeIP(false) 704 oldIP6 = oldNode.GetNodeIP(true) 705 oldKey = oldNode.EncryptionKey 706 } 707 708 if n.nodeConfig.EnableIPSec && !n.subnetEncryption() { 709 n.enableIPsec(newNode) 710 newKey = newNode.EncryptionKey 711 } 712 713 if n.enableNeighDiscovery { 714 var ifaceName string 715 if option.Config.EnableNodePort { 716 ifaceName = option.Config.Device 717 } else { 718 ifaceName = option.Config.EncryptInterface 719 } 720 n.insertNeighbor(newNode, ifaceName) 721 } 722 723 if n.nodeConfig.EnableIPSec { 724 n.encryptNode(newNode) 725 } 726 727 if newNode.IsLocal() { 728 if n.nodeConfig.EnableLocalNodeRoute { 729 n.updateOrRemoveNodeRoutes([]*cidr.CIDR{oldIP4Cidr}, []*cidr.CIDR{newNode.IPv4AllocCIDR}) 730 n.updateOrRemoveNodeRoutes([]*cidr.CIDR{oldIP6Cidr}, []*cidr.CIDR{newNode.IPv6AllocCIDR}) 731 } 732 if n.subnetEncryption() { 733 n.enableSubnetIPsec(n.nodeConfig.IPv4PodSubnets, n.nodeConfig.IPv6PodSubnets) 734 } 735 return nil 736 } 737 738 if n.nodeConfig.EnableAutoDirectRouting { 739 n.updateDirectRoute(oldIP4Cidr, newNode.IPv4AllocCIDR, oldIP4, newIP4, firstAddition, n.nodeConfig.EnableIPv4) 740 n.updateDirectRoute(oldIP6Cidr, newNode.IPv6AllocCIDR, oldIP6, newIP6, firstAddition, n.nodeConfig.EnableIPv6) 741 return nil 742 } 743 744 if n.nodeConfig.EnableEncapsulation { 745 // Update the tunnel mapping of the node. In case the 746 // node has changed its CIDR range, a new entry in the 747 // map is created and the old entry is removed. 748 updateTunnelMapping(oldIP4Cidr, newNode.IPv4AllocCIDR, oldIP4, newIP4, firstAddition, n.nodeConfig.EnableIPv4, oldKey, newKey) 749 // Not a typo, the IPv4 host IP is used to build the IPv6 overlay 750 updateTunnelMapping(oldIP6Cidr, newNode.IPv6AllocCIDR, oldIP4, newIP4, firstAddition, n.nodeConfig.EnableIPv6, oldKey, newKey) 751 752 if !n.nodeConfig.UseSingleClusterRoute { 753 n.updateOrRemoveNodeRoutes([]*cidr.CIDR{oldIP4Cidr}, []*cidr.CIDR{newNode.IPv4AllocCIDR}) 754 n.updateOrRemoveNodeRoutes([]*cidr.CIDR{oldIP6Cidr}, []*cidr.CIDR{newNode.IPv6AllocCIDR}) 755 } 756 757 return nil 758 } else if firstAddition { 759 // When encapsulation is disabled, then the initial node addition 760 // triggers a removal of eventual old tunnel map entries. 761 deleteTunnelMapping(newNode.IPv4AllocCIDR, true) 762 deleteTunnelMapping(newNode.IPv6AllocCIDR, true) 763 764 if rt, _ := n.lookupNodeRoute(newNode.IPv4AllocCIDR); rt != nil { 765 n.deleteNodeRoute(newNode.IPv4AllocCIDR) 766 } 767 if rt, _ := n.lookupNodeRoute(newNode.IPv6AllocCIDR); rt != nil { 768 n.deleteNodeRoute(newNode.IPv6AllocCIDR) 769 } 770 } 771 772 return nil 773 } 774 775 func (n *linuxNodeHandler) NodeDelete(oldNode node.Node) error { 776 n.mutex.Lock() 777 defer n.mutex.Unlock() 778 779 nodeIdentity := oldNode.Identity() 780 if oldCachedNode, nodeExists := n.nodes[nodeIdentity]; nodeExists { 781 delete(n.nodes, nodeIdentity) 782 783 if n.isInitialized { 784 return n.nodeDelete(oldCachedNode) 785 } 786 } 787 788 return nil 789 } 790 791 func (n *linuxNodeHandler) nodeDelete(oldNode *node.Node) error { 792 if oldNode.IsLocal() { 793 return nil 794 } 795 796 oldIP4 := oldNode.GetNodeIP(false) 797 oldIP6 := oldNode.GetNodeIP(true) 798 799 if n.nodeConfig.EnableAutoDirectRouting { 800 n.deleteDirectRoute(oldNode.IPv4AllocCIDR, oldIP4) 801 n.deleteDirectRoute(oldNode.IPv6AllocCIDR, oldIP6) 802 } 803 804 if n.nodeConfig.EnableEncapsulation { 805 deleteTunnelMapping(oldNode.IPv4AllocCIDR, false) 806 deleteTunnelMapping(oldNode.IPv6AllocCIDR, false) 807 808 if !n.nodeConfig.UseSingleClusterRoute { 809 n.deleteNodeRoute(oldNode.IPv4AllocCIDR) 810 n.deleteNodeRoute(oldNode.IPv6AllocCIDR) 811 } 812 } 813 814 if n.enableNeighDiscovery { 815 n.deleteNeighbor(oldNode) 816 } 817 818 if n.nodeConfig.EnableIPSec { 819 n.deleteIPsec(oldNode) 820 } 821 822 return nil 823 } 824 825 func (n *linuxNodeHandler) updateOrRemoveClusterRoute(addressing datapath.NodeAddressingFamily, addressFamilyEnabled bool) { 826 allocCIDR := addressing.AllocationCIDR() 827 if addressFamilyEnabled { 828 n.updateNodeRoute(allocCIDR, addressFamilyEnabled) 829 } else if rt, _ := n.lookupNodeRoute(allocCIDR); rt != nil { 830 n.deleteNodeRoute(allocCIDR) 831 } 832 } 833 834 func (n *linuxNodeHandler) replaceHostRules() error { 835 rule := route.Rule{ 836 Priority: 1, 837 Mask: linux_defaults.RouteMarkMask, 838 Table: linux_defaults.RouteTableIPSec, 839 } 840 841 if n.nodeConfig.EnableIPv4 { 842 rule.Mark = linux_defaults.RouteMarkDecrypt 843 if err := route.ReplaceRule(rule); err != nil { 844 log.WithError(err).Error("Replace IPv4 route decrypt rule failed") 845 return err 846 } 847 rule.Mark = linux_defaults.RouteMarkEncrypt 848 if err := route.ReplaceRule(rule); err != nil { 849 log.WithError(err).Error("Replace IPv4 route encrypt rule failed") 850 return err 851 } 852 } 853 854 if n.nodeConfig.EnableIPv6 { 855 rule.Mark = linux_defaults.RouteMarkDecrypt 856 if err := route.ReplaceRuleIPv6(rule); err != nil { 857 log.WithError(err).Error("Replace IPv6 route decrypt rule failed") 858 return err 859 } 860 rule.Mark = linux_defaults.RouteMarkEncrypt 861 if err := route.ReplaceRuleIPv6(rule); err != nil { 862 log.WithError(err).Error("Replace IPv6 route ecrypt rule failed") 863 return err 864 } 865 } 866 867 return nil 868 } 869 870 func (n *linuxNodeHandler) removeEncryptRules() error { 871 rule := route.Rule{ 872 Priority: 1, 873 Mask: linux_defaults.RouteMarkMask, 874 Table: linux_defaults.RouteTableIPSec, 875 } 876 877 rule.Mark = linux_defaults.RouteMarkDecrypt 878 if err := route.DeleteRule(rule); err != nil { 879 if !os.IsNotExist(err) { 880 return fmt.Errorf("Delete previous IPv4 decrypt rule failed: %s", err) 881 } 882 } 883 884 rule.Mark = linux_defaults.RouteMarkEncrypt 885 if err := route.DeleteRule(rule); err != nil { 886 if !os.IsNotExist(err) { 887 return fmt.Errorf("Delete previousa IPv4 encrypt rule failed: %s", err) 888 } 889 } 890 891 rule.Mark = linux_defaults.RouteMarkDecrypt 892 if err := route.DeleteRuleIPv6(rule); err != nil { 893 if !os.IsNotExist(err) && err != syscall.EAFNOSUPPORT { 894 return fmt.Errorf("Delete previous IPv6 decrypt rule failed: %s", err) 895 } 896 } 897 898 rule.Mark = linux_defaults.RouteMarkEncrypt 899 if err := route.DeleteRuleIPv6(rule); err != nil { 900 if !os.IsNotExist(err) && err != syscall.EAFNOSUPPORT { 901 return fmt.Errorf("Delete previous IPv6 encrypt rule failed: %s", err) 902 } 903 } 904 return nil 905 } 906 907 func (n *linuxNodeHandler) createNodeIPSecInRoute(ip *net.IPNet) route.Route { 908 var device string 909 910 if option.Config.Tunnel == option.TunnelDisabled { 911 device = n.datapathConfig.EncryptInterface 912 } else { 913 device = linux_defaults.TunnelDeviceName 914 } 915 return route.Route{ 916 Nexthop: nil, 917 Device: device, 918 Prefix: *ip, 919 Table: linux_defaults.RouteTableIPSec, 920 Proto: linux_defaults.RouteProtocolIPSec, 921 Type: route.RTN_LOCAL, 922 } 923 } 924 925 func (n *linuxNodeHandler) createNodeIPSecOutRoute(ip *net.IPNet) route.Route { 926 return route.Route{ 927 Nexthop: nil, 928 Device: n.datapathConfig.HostDevice, 929 Prefix: *ip, 930 Table: linux_defaults.RouteTableIPSec, 931 } 932 } 933 934 func (n *linuxNodeHandler) createNodeExternalIPSecOutRoute(ip *net.IPNet, dflt bool) route.Route { 935 var tbl int 936 var dev string 937 var mtu int 938 939 if dflt { 940 dev = n.datapathConfig.HostDevice 941 mtu = n.nodeConfig.MtuConfig.GetRouteMTU() 942 } else { 943 tbl = linux_defaults.RouteTableIPSec 944 dev = n.datapathConfig.HostDevice 945 } 946 947 // The default routing table accounts for encryption overhead for encrypt-node traffic 948 return route.Route{ 949 Device: dev, 950 Prefix: *ip, 951 Table: tbl, 952 Proto: route.EncryptRouteProtocol, 953 MTU: mtu, 954 } 955 } 956 957 // replaceNodeIPSecOutRoute replace the out IPSec route in the host routing table 958 // with the new route. If no route exists the route is installed on the host. 959 func (n *linuxNodeHandler) replaceNodeIPSecOutRoute(ip *net.IPNet) { 960 if ip == nil { 961 return 962 } 963 964 if ip.IP.To4() != nil { 965 if !n.nodeConfig.EnableIPv4 { 966 return 967 } 968 } else { 969 if !n.nodeConfig.EnableIPv6 { 970 return 971 } 972 } 973 974 _, err := route.Upsert(n.createNodeIPSecOutRoute(ip)) 975 if err != nil { 976 log.WithError(err).Error("Unable to replace the IPSec route OUT the host routing table") 977 } 978 } 979 980 // replaceNodeExternalIPSecOutRoute replace the out IPSec route in the host routing table 981 // with the new route. If no route exists the route is installed on the host. 982 func (n *linuxNodeHandler) replaceNodeExternalIPSecOutRoute(ip *net.IPNet) { 983 if ip == nil { 984 return 985 } 986 987 if ip.IP.To4() != nil { 988 if !n.nodeConfig.EnableIPv4 { 989 return 990 } 991 } else { 992 if !n.nodeConfig.EnableIPv6 { 993 return 994 } 995 } 996 997 _, err := route.Upsert(n.createNodeExternalIPSecOutRoute(ip, true)) 998 if err != nil { 999 log.WithError(err).Error("Unable to replace the IPSec route OUT the default routing table") 1000 } 1001 _, err = route.Upsert(n.createNodeExternalIPSecOutRoute(ip, false)) 1002 if err != nil { 1003 log.WithError(err).Error("Unable to replace the IPSec route OUT the host routing table") 1004 } 1005 } 1006 1007 func (n *linuxNodeHandler) deleteNodeIPSecOutRoute(ip *net.IPNet) { 1008 if ip == nil { 1009 return 1010 } 1011 1012 if ip.IP.To4() != nil { 1013 if !n.nodeConfig.EnableIPv4 { 1014 return 1015 } 1016 } else { 1017 if !n.nodeConfig.EnableIPv6 { 1018 return 1019 } 1020 } 1021 1022 if err := route.Delete(n.createNodeIPSecOutRoute(ip)); err != nil { 1023 log.WithError(err).Error("Unable to delete the IPsec route OUT from the host routing table") 1024 } 1025 } 1026 1027 func (n *linuxNodeHandler) deleteNodeExternalIPSecOutRoute(ip *net.IPNet) { 1028 if ip == nil { 1029 return 1030 } 1031 1032 if ip.IP.To4() != nil { 1033 if !n.nodeConfig.EnableIPv4 { 1034 return 1035 } 1036 } else { 1037 if !n.nodeConfig.EnableIPv6 { 1038 return 1039 } 1040 } 1041 1042 if err := route.Delete(n.createNodeExternalIPSecOutRoute(ip, true)); err != nil { 1043 log.WithError(err).Error("Unable to delete the IPsec route External OUT from the ipsec routing table") 1044 } 1045 1046 if err := route.Delete(n.createNodeExternalIPSecOutRoute(ip, false)); err != nil { 1047 log.WithError(err).Error("Unable to delete the IPsec route External OUT from the host routing table") 1048 } 1049 } 1050 1051 // replaceNodeIPSecoInRoute replace the in IPSec routes in the host routing table 1052 // with the new route. If no route exists the route is installed on the host. 1053 func (n *linuxNodeHandler) replaceNodeIPSecInRoute(ip *net.IPNet) { 1054 if ip == nil { 1055 return 1056 } 1057 1058 if ip.IP.To4() != nil { 1059 if !n.nodeConfig.EnableIPv4 { 1060 return 1061 } 1062 } else { 1063 if !n.nodeConfig.EnableIPv6 { 1064 return 1065 } 1066 } 1067 1068 _, err := route.Upsert(n.createNodeIPSecInRoute(ip)) 1069 if err != nil { 1070 log.WithError(err).Error("Unable to replace the IPSec route IN the host routing table") 1071 } 1072 } 1073 1074 func (n *linuxNodeHandler) deleteIPsec(oldNode *node.Node) { 1075 if n.nodeConfig.EnableIPv4 && oldNode.IPv4AllocCIDR != nil { 1076 ciliumInternalIPv4 := oldNode.GetCiliumInternalIP(false) 1077 old4Net := &net.IPNet{IP: ciliumInternalIPv4, Mask: oldNode.IPv4AllocCIDR.Mask} 1078 old4RouteNet := &net.IPNet{IP: oldNode.IPv4AllocCIDR.IP, Mask: oldNode.IPv4AllocCIDR.Mask} 1079 n.deleteNodeIPSecOutRoute(old4RouteNet) 1080 ipsec.DeleteIPsecEndpoint(old4Net) 1081 if n.nodeConfig.EncryptNode { 1082 if remoteIPv4 := oldNode.GetNodeIP(false); remoteIPv4 != nil { 1083 exactMask := net.IPv4Mask(255, 255, 255, 255) 1084 ipsecRemote := &net.IPNet{IP: remoteIPv4, Mask: exactMask} 1085 n.deleteNodeExternalIPSecOutRoute(ipsecRemote) 1086 } 1087 } 1088 } 1089 1090 if n.nodeConfig.EnableIPv6 && oldNode.IPv6AllocCIDR != nil { 1091 ciliumInternalIPv6 := oldNode.GetCiliumInternalIP(true) 1092 old6Net := &net.IPNet{IP: ciliumInternalIPv6, Mask: oldNode.IPv6AllocCIDR.Mask} 1093 old6RouteNet := &net.IPNet{IP: oldNode.IPv6AllocCIDR.IP, Mask: oldNode.IPv6AllocCIDR.Mask} 1094 n.deleteNodeIPSecOutRoute(old6RouteNet) 1095 ipsec.DeleteIPsecEndpoint(old6Net) 1096 if n.nodeConfig.EncryptNode { 1097 if remoteIPv6 := oldNode.GetNodeIP(true); remoteIPv6 != nil { 1098 exactMask := net.CIDRMask(128, 128) 1099 ipsecRemote := &net.IPNet{IP: remoteIPv6, Mask: exactMask} 1100 n.deleteNodeExternalIPSecOutRoute(ipsecRemote) 1101 } 1102 } 1103 } 1104 } 1105 1106 // NodeConfigurationChanged is called when the LocalNodeConfiguration has changed 1107 func (n *linuxNodeHandler) NodeConfigurationChanged(newConfig datapath.LocalNodeConfiguration) error { 1108 n.mutex.Lock() 1109 defer n.mutex.Unlock() 1110 1111 prevConfig := n.nodeConfig 1112 n.nodeConfig = newConfig 1113 1114 n.enableNeighDiscovery = n.nodeConfig.EnableIPv4 && 1115 (option.Config.EnableNodePort || 1116 (n.nodeConfig.EnableIPSec && option.Config.Tunnel == option.TunnelDisabled)) 1117 1118 n.updateOrRemoveNodeRoutes(prevConfig.AuxiliaryPrefixes, newConfig.AuxiliaryPrefixes) 1119 1120 if newConfig.EnableIPSec { 1121 if err := n.replaceHostRules(); err != nil { 1122 log.WithError(err).Warning("Cannot replace Host rules") 1123 } 1124 } else { 1125 err := n.removeEncryptRules() 1126 if err != nil { 1127 log.WithError(err).Warning("Cannot cleanup previous encryption rule state.") 1128 } 1129 } 1130 1131 if newConfig.UseSingleClusterRoute { 1132 n.updateOrRemoveClusterRoute(n.nodeAddressing.IPv4(), newConfig.EnableIPv4) 1133 n.updateOrRemoveClusterRoute(n.nodeAddressing.IPv6(), newConfig.EnableIPv6) 1134 } else if prevConfig.UseSingleClusterRoute { 1135 // single cluster route has been disabled, remove route 1136 n.deleteNodeRoute(n.nodeAddressing.IPv4().AllocationCIDR()) 1137 n.deleteNodeRoute(n.nodeAddressing.IPv6().AllocationCIDR()) 1138 } 1139 1140 if !n.isInitialized { 1141 n.isInitialized = true 1142 if !n.nodeConfig.UseSingleClusterRoute { 1143 for _, unlinkedNode := range n.nodes { 1144 n.nodeUpdate(nil, unlinkedNode, true) 1145 } 1146 } 1147 } 1148 1149 return nil 1150 } 1151 1152 // NodeValidateImplementation is called to validate the implementation of the 1153 // node in the datapath 1154 func (n *linuxNodeHandler) NodeValidateImplementation(nodeToValidate node.Node) error { 1155 return n.nodeUpdate(nil, &nodeToValidate, false) 1156 } 1157 1158 // NodeDeviceNameWithDefaultRoute returns the node's device name which 1159 // handles the default route in the current namespace 1160 func NodeDeviceNameWithDefaultRoute() (string, error) { 1161 link, err := route.NodeDeviceWithDefaultRoute() 1162 if err != nil { 1163 return "", err 1164 } 1165 return link.Attrs().Name, nil 1166 }