in cmd/egress-cni-plugin/egressContext.go [345:407]
func (ec *egressContext) cmdAddEgressV6() (err error) {
// Per best practice, a new veth pair is created between container ns and node ns
// this newly created veth pair is used for container's egress IPv6 traffic
// NOTE:
// 1. link-local IPv6 addresses are automatically assigned to veth's both ends.
// 2. unique-local IPv6 address allocated from host-local IPAM plugin is assigned to veth's container end only
// 3. veth node end has no unique-local IPv6 address assigned, only link-local IPv6 address
// 4. container IPv6 egress traffic go through node primary interface (eth0) which has an IPv6 global unicast address
// 5. IPv6 egress traffic of all containers in a node shares node primary interface (eth0) through SNAT
if ec.IPTablesIface == nil {
if ec.IPTablesIface, err = ec.IptCreator(iptables.ProtocolIPv6); err != nil {
ec.Log.Error("command ip6tables not found")
return err
}
}
// first disable IPv6 on container's primary interface (eth0)
err = ec.disableContainerInterfaceIPv6(ec.ArgsIfName)
if err != nil {
ec.Log.Errorf("failed to disable IPv6 on container interface %s", ec.ArgsIfName)
return err
}
hostInterface, containerInterface, err := ec.setupContainerVethV6()
if err != nil {
ec.Log.Errorf("veth created failed, ns: %s name: %s, mtu: %d, ipam-result: %+v err: %v",
ec.NsPath, ec.NetConf.IfName, ec.Mtu, *ec.TmpResult, err)
return err
}
ec.Log.Debugf("veth pair created for container IPv6 egress traffic, container interface: %s ,host interface: %s",
containerInterface.Name, hostInterface.Name)
containerIPv6 := ec.TmpResult.IPs[0].Address.IP
err = ec.setupContainerIPv6Route(hostInterface, containerInterface)
if err != nil {
ec.Log.Errorf("setupContainerIPv6Route failed: %v", err)
return err
}
ec.Log.Debugf("container route set up successfully")
err = ec.setupHostIPv6Route(hostInterface, containerIPv6)
if err != nil {
ec.Log.Errorf("setupHostIPv6Route failed: %v", err)
return err
}
ec.Log.Debugf("host IPv6 route set up successfully")
// set up SNAT in host for container IPv6 egress traffic
// following line adds an ip6tables entries to NAT for IPv6 traffic between container v6if0 and node primary ENI (eth0)
err = snat.Add(ec.IPTablesIface, ec.NetConf.NodeIP, containerIPv6, ipv6MulticastRange, ec.SnatChain, ec.SnatComment, ec.NetConf.RandomizeSNAT)
if err != nil {
ec.Log.Errorf("setup host snat failed: %v", err)
return err
}
ec.Log.Debugf("host IPv6 SNAT set up successfully")
// Copy interfaces over to result, but not IPs.
ec.Result.Interfaces = append(ec.Result.Interfaces, ec.TmpResult.Interfaces...)
// Pass through the previous result
return types.PrintResult(ec.Result, ec.NetConf.CNIVersion)
}