in cmd/routed-eni-cni-plugin/driver/driver.go [104:228]
func (createVethContext *createVethPairContext) run(hostNS ns.NetNS) error {
veth := &netlink.Veth{
LinkAttrs: netlink.LinkAttrs{
Name: createVethContext.contVethName,
Flags: net.FlagUp,
MTU: createVethContext.mtu,
},
PeerName: createVethContext.hostVethName,
}
if err := createVethContext.netLink.LinkAdd(veth); err != nil {
return err
}
hostVeth, err := createVethContext.netLink.LinkByName(createVethContext.hostVethName)
if err != nil {
return errors.Wrapf(err, "setup NS network: failed to find link %q", createVethContext.hostVethName)
}
// Explicitly set the veth to UP state, because netlink doesn't always do that on all the platforms with net.FlagUp.
// veth won't get a link local address unless it's set to UP state.
if err = createVethContext.netLink.LinkSetUp(hostVeth); err != nil {
return errors.Wrapf(err, "setup NS network: failed to set link %q up", createVethContext.hostVethName)
}
contVeth, err := createVethContext.netLink.LinkByName(createVethContext.contVethName)
if err != nil {
return errors.Wrapf(err, "setup NS network: failed to find link %q", createVethContext.contVethName)
}
// Explicitly set the veth to UP state, because netlink doesn't always do that on all the platforms with net.FlagUp.
// veth won't get a link local address unless it's set to UP state.
if err = createVethContext.netLink.LinkSetUp(contVeth); err != nil {
return errors.Wrapf(err, "setup NS network: failed to set link %q up", createVethContext.contVethName)
}
if createVethContext.v6Addr != nil && createVethContext.v6Addr.IP.To16() != nil {
// Enable v6 support on Container's veth interface.
if err = createVethContext.procSys.Set(fmt.Sprintf("net/ipv6/conf/%s/disable_ipv6", createVethContext.contVethName), "0"); err != nil {
if !os.IsNotExist(err) {
return errors.Wrapf(err, "setupVeth network: failed to enable IPv6 on container veth interface")
}
}
// Enable v6 support on Container's lo interface inside the Pod networking namespace.
if err = createVethContext.procSys.Set(fmt.Sprintf("net/ipv6/conf/lo/disable_ipv6"), "0"); err != nil {
if !os.IsNotExist(err) {
return errors.Wrapf(err, "setupVeth network: failed to enable IPv6 on container's lo interface")
}
}
}
// Add a connected route to a dummy next hop (169.254.1.1 or fe80::1)
// # ip route show
// default via 169.254.1.1 dev eth0
// 169.254.1.1 dev eth0
var gw net.IP
var maskLen int
var addr *netlink.Addr
var defNet *net.IPNet
if createVethContext.v4Addr != nil {
gw = net.IPv4(169, 254, 1, 1)
maskLen = 32
addr = &netlink.Addr{IPNet: createVethContext.v4Addr}
defNet = &net.IPNet{IP: net.IPv4zero, Mask: net.CIDRMask(0, maskLen)}
} else if createVethContext.v6Addr != nil {
gw = net.IP{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
maskLen = 128
addr = &netlink.Addr{IPNet: createVethContext.v6Addr}
defNet = &net.IPNet{IP: net.IPv6zero, Mask: net.CIDRMask(0, maskLen)}
}
gwNet := &net.IPNet{IP: gw, Mask: net.CIDRMask(maskLen, maskLen)}
if err = createVethContext.netLink.RouteReplace(&netlink.Route{
LinkIndex: contVeth.Attrs().Index,
Scope: netlink.SCOPE_LINK,
Dst: gwNet}); err != nil {
return errors.Wrap(err, "setup NS network: failed to add default gateway")
}
// Add a default route via dummy next hop(169.254.1.1 or fe80::1). Then all outgoing traffic will be routed by this
// default route via dummy next hop (169.254.1.1 or fe80::1)
if err = createVethContext.netLink.RouteAdd(&netlink.Route{
LinkIndex: contVeth.Attrs().Index,
Scope: netlink.SCOPE_UNIVERSE,
Dst: defNet,
Gw: gw,
}); err != nil {
return errors.Wrap(err, "setup NS network: failed to add default route")
}
if err = createVethContext.netLink.AddrAdd(contVeth, addr); err != nil {
return errors.Wrapf(err, "setup NS network: failed to add IP addr to %q", createVethContext.contVethName)
}
// add static ARP entry for default gateway
// we are using routed mode on the host and container need this static ARP entry to resolve its default gateway.
// IP address family is derived from the IP address passed to the function (v4 or v6)
neigh := &netlink.Neigh{
LinkIndex: contVeth.Attrs().Index,
State: netlink.NUD_PERMANENT,
IP: gwNet.IP,
HardwareAddr: hostVeth.Attrs().HardwareAddr,
}
if err = createVethContext.netLink.NeighAdd(neigh); err != nil {
return errors.Wrap(err, "setup NS network: failed to add static ARP")
}
if createVethContext.v6Addr != nil && createVethContext.v6Addr.IP.To16() != nil {
if err := cniutils.WaitForAddressesToBeStable(createVethContext.netLink, createVethContext.contVethName, v6DADTimeout, WAIT_INTERVAL); err != nil {
return errors.Wrap(err, "setup NS network: failed while waiting for v6 addresses to be stable")
}
}
// Now that the everything has been successfully set up in the container, move the "host" end of the
// veth into the host namespace.
if err = createVethContext.netLink.LinkSetNsFd(hostVeth, int(hostNS.Fd())); err != nil {
return errors.Wrap(err, "setup NS network: failed to move veth to host netns")
}
return nil
}