in pkg/networkutils/network.go [907:1020]
func setupENINetwork(eniIP string, eniMAC string, deviceNumber int, eniSubnetCIDR string, netLink netlinkwrapper.NetLink,
retryLinkByMacInterval time.Duration, retryRouteAddInterval time.Duration, mtu int) error {
if deviceNumber == 0 {
return errors.New("setupENINetwork should never be called on the primary ENI")
}
tableNumber := deviceNumber + 1
log.Infof("Setting up network for an ENI with IP address %s, MAC address %s, CIDR %s and route table %d",
eniIP, eniMAC, eniSubnetCIDR, tableNumber)
link, err := linkByMac(eniMAC, netLink, retryLinkByMacInterval)
if err != nil {
return errors.Wrapf(err, "setupENINetwork: failed to find the link which uses MAC address %s", eniMAC)
}
if err = netLink.LinkSetMTU(link, mtu); err != nil {
return errors.Wrapf(err, "setupENINetwork: failed to set MTU to %d for %s", mtu, eniIP)
}
if err = netLink.LinkSetUp(link); err != nil {
return errors.Wrapf(err, "setupENINetwork: failed to bring up ENI %s", eniIP)
}
_, ipnet, err := net.ParseCIDR(eniSubnetCIDR)
if err != nil {
return errors.Wrapf(err, "setupENINetwork: invalid IPv4 CIDR block %s", eniSubnetCIDR)
}
gw, err := IncrementIPv4Addr(ipnet.IP)
if err != nil {
return errors.Wrapf(err, "setupENINetwork: failed to define gateway address from %v", ipnet.IP)
}
// Explicitly set the IP on the device if not already set.
// Required for older kernels.
// ip addr show
// ip add del <eniIP> dev <link> (if necessary)
// ip add add <eniIP> dev <link>
log.Debugf("Setting up ENI's primary IP %s", eniIP)
addrs, err := netLink.AddrList(link, unix.AF_INET)
if err != nil {
return errors.Wrap(err, "setupENINetwork: failed to list IP address for ENI")
}
for _, addr := range addrs {
log.Debugf("Deleting existing IP address %s", addr.String())
if err = netLink.AddrDel(link, &addr); err != nil {
return errors.Wrap(err, "setupENINetwork: failed to delete IP addr from ENI")
}
}
eniAddr := &net.IPNet{
IP: net.ParseIP(eniIP),
Mask: ipnet.Mask,
}
log.Debugf("Adding IP address %s", eniAddr.String())
if err = netLink.AddrAdd(link, &netlink.Addr{IPNet: eniAddr}); err != nil {
return errors.Wrap(err, "setupENINetwork: failed to add IP addr to ENI")
}
linkIndex := link.Attrs().Index
log.Debugf("Setting up ENI's default gateway %v, table %d, linkIndex %d", gw, tableNumber, linkIndex)
routes := []netlink.Route{
// Add a direct link route for the host's ENI IP only
{
LinkIndex: linkIndex,
Dst: &net.IPNet{IP: gw, Mask: net.CIDRMask(32, 32)},
Scope: netlink.SCOPE_LINK,
Table: tableNumber,
},
// Route all other traffic via the host's ENI IP
{
LinkIndex: linkIndex,
Dst: &net.IPNet{IP: net.IPv4zero, Mask: net.CIDRMask(0, 32)},
Scope: netlink.SCOPE_UNIVERSE,
Gw: gw,
Table: tableNumber,
},
}
for _, r := range routes {
err := netLink.RouteDel(&r)
if err != nil && !netlinkwrapper.IsNotExistsError(err) {
return errors.Wrap(err, "setupENINetwork: failed to clean up old routes")
}
err = retry.NWithBackoff(retry.NewSimpleBackoff(500*time.Millisecond, retryRouteAddInterval, 0.15, 2.0), maxRetryRouteAdd, func() error {
if err := netLink.RouteReplace(&r); err != nil {
log.Debugf("Not able to set route %s/0 via %s table %d", r.Dst.IP.String(), gw.String(), tableNumber)
return errors.Wrapf(err, "setupENINetwork: unable to replace route entry %s", r.Dst.IP.String())
}
log.Debugf("Successfully added/replaced route to be %s/0", r.Dst.IP.String())
return nil
})
if err != nil {
return err
}
}
// Remove the route that default out to ENI-x out of main route table
_, cidr, err := net.ParseCIDR(eniSubnetCIDR)
if err != nil {
return errors.Wrapf(err, "setupENINetwork: invalid IPv4 CIDR block %s", eniSubnetCIDR)
}
defaultRoute := netlink.Route{
Dst: cidr,
Src: net.ParseIP(eniIP),
Table: mainRoutingTable,
Scope: netlink.SCOPE_LINK,
}
if err := netLink.RouteDel(&defaultRoute); err != nil {
if !netlinkwrapper.IsNotExistsError(err) {
return errors.Wrapf(err, "setupENINetwork: unable to delete default route %s for source IP %s", cidr.String(), eniIP)
}
}
return nil
}