func()

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)
}