func()

in cmd/routed-eni-cni-plugin/driver/driver.go [382:470]


func (os *linuxNetwork) SetupPodENINetwork(hostVethName string, contVethName string, netnsPath string, v4Addr *net.IPNet,
	v6Addr *net.IPNet, vlanID int, eniMAC string, subnetGW string, parentIfIndex int, mtu int, log logger.Logger) error {

	hostVeth, err := setupVeth(hostVethName, contVethName, netnsPath, v4Addr, v6Addr, os.netLink, os.ns, mtu, os.procSys, log)
	if err != nil {
		return errors.Wrapf(err, "SetupPodENINetwork failed to setup veth pair.")
	}

	vlanTableID := vlanID + 100
	vlanLink := buildVlanLink(vlanID, parentIfIndex, eniMAC)

	// 1a. clean up if vlan already exists (necessary when trunk ENI changes).
	if oldVlan, err := os.netLink.LinkByName(vlanLink.Name); err == nil {
		if err = os.netLink.LinkDel(oldVlan); err != nil {
			return errors.Wrapf(err, "SetupPodENINetwork: failed to delete old vlan %s", vlanLink.Name)
		}
		log.Debugf("Cleaned up old vlan: %s", vlanLink.Name)
	}

	// 1b. clean up any previous hostVeth ip rule
	oldVlanRule := os.netLink.NewRule()
	oldVlanRule.IifName = hostVethName
	oldVlanRule.Priority = vlanRulePriority
	// loop is required to clean up all existing rules created on the host (when pod with same name are recreated multiple times)
	for {
		if err := os.netLink.RuleDel(oldVlanRule); err != nil {
			if !containsNoSuchRule(err) {
				return errors.Wrapf(err, "SetupPodENINetwork: failed to delete hostveth rule for %s", hostVeth.Attrs().Name)
			}
			break
		}
	}

	// 2. add new vlan link
	err = os.netLink.LinkAdd(vlanLink)
	if err != nil {
		return errors.Wrapf(err, "SetupPodENINetwork: failed to add vlan link.")
	}

	// 3. bring up the vlan
	if err = os.netLink.LinkSetUp(vlanLink); err != nil {
		return errors.Wrapf(err, "SetupPodENINetwork: failed to set link %q up", vlanLink.Name)
	}

	// 4. create default routes for vlan
	routes := buildRoutesForVlan(vlanTableID, vlanLink.Index, net.ParseIP(subnetGW))
	for _, r := range routes {
		if err := os.netLink.RouteReplace(&r); err != nil {
			return errors.Wrapf(err, "SetupPodENINetwork: unable to replace route entry %s via %s", r.Dst.IP.String(), subnetGW)
		}
	}

	var addr *net.IPNet
	if v4Addr != nil {
		addr = v4Addr
	} else if v6Addr != nil {
		addr = v6Addr
	}

	// 5. create route entry for hostveth.
	route := netlink.Route{
		LinkIndex: hostVeth.Attrs().Index,
		Scope:     netlink.SCOPE_LINK,
		Dst:       addr,
		Table:     vlanTableID,
	}
	if err := os.netLink.RouteReplace(&route); err != nil {
		return errors.Wrapf(err, "SetupPodENINetwork: unable to add or replace route entry for %s", route.Dst.IP.String())
	}

	log.Debugf("Successfully set host route to be %s/0", route.Dst.IP.String())

	// 6. Add ip rules for the pod.
	vlanRule := os.netLink.NewRule()
	vlanRule.Table = vlanTableID
	vlanRule.Priority = vlanRulePriority
	vlanRule.IifName = vlanLink.Name
	err = os.netLink.RuleAdd(vlanRule)
	if err != nil && !isRuleExistsError(err) {
		return errors.Wrapf(err, "SetupPodENINetwork: unable to add ip rule for vlan link %s ", vlanLink.Name)
	}

	vlanRule.IifName = hostVeth.Attrs().Name
	err = os.netLink.RuleAdd(vlanRule)
	if err != nil && !isRuleExistsError(err) {
		return errors.Wrapf(err, "SetupPodENINetwork: unable to add ip rule for host veth %s", hostVethName)
	}
	return nil
}