func()

in plugins/vpc-tunnel/plugin/commands.go [365:482]


func (plugin *Plugin) createTapLink(
	geneve *eni.Geneve,
	bridgeName string,
	tapLinkName string,
	tapCfg *config.TAPConfig) error {

	// Create the bridge link.
	la := netlink.NewLinkAttrs()
	la.Name = bridgeName
	la.MTU = vpc.JumboFrameMTU
	bridge := &netlink.Bridge{LinkAttrs: la}
	log.Infof("Creating bridge geneve %+v.", bridge)
	err := netlink.LinkAdd(bridge)
	if err != nil {
		log.Errorf("Failed to create bridge geneve: %v", err)
		return err
	}

	// Set bridge link MTU.
	err = netlink.LinkSetMTU(bridge, vpc.JumboFrameMTU)
	if err != nil {
		log.Errorf("Failed to set bridge geneve MTU: %v", err)
		return err
	}

	// In TAP mode, the geneve ENI's MAC address is used exclusively by the consumer of the TAP
	// interface (e.g. a VM), so it shouldn't be assigned to the geneve itself. However, this
	// can happen if the geneve is being reused between successive invocations of the plugin.
	// Overriding the geneve's MAC address with that of the bridge prevents that.
	bridgeLink, err := netlink.LinkByIndex(bridge.Index)
	if err != nil {
		log.Errorf("Failed to find bridge geneve: %v", err)
		return err
	}

	err = geneve.SetMACAddress(bridgeLink.Attrs().HardwareAddr)
	if err != nil {
		log.Errorf("Failed to set interface MAC address: %v.", err)
		return err
	}
	log.Infof("Interface mac address set %v", bridgeLink.Attrs().HardwareAddr)

	// Set bridge operational state up.
	err = netlink.LinkSetUp(bridge)
	if err != nil {
		log.Errorf("Failed to set bridge geneve state: %v", err)
		return err
	}

	// Connect geneve link to the bridge.
	la = netlink.NewLinkAttrs()
	la.Name = geneve.GetLinkName()
	geneveLink := &netlink.Dummy{LinkAttrs: la}
	err = netlink.LinkSetMaster(geneveLink, bridge)
	if err != nil {
		log.Errorf("Failed to set geneve master: %v", err)
		return err
	}

	// Create the TAP geneve.
	// Parse headers added by virtio_net implementation.
	la = netlink.NewLinkAttrs()
	la.Name = tapLinkName
	la.MasterIndex = bridge.Index
	la.MTU = vpc.JumboFrameMTU
	tapLink := &netlink.Tuntap{
		LinkAttrs: la,
		Mode:      netlink.TUNTAP_MODE_TAP,
		Flags:     netlink.TUNTAP_VNET_HDR,
		Queues:    tapCfg.Queues,
	}

	if tapCfg.Queues == 1 {
		tapLink.Flags |= netlink.TUNTAP_ONE_QUEUE
	}

	log.Infof("Creating TAP geneve %+v.", tapLink)
	err = netlink.LinkAdd(tapLink)
	if err != nil {
		log.Errorf("Failed to add TAP geneve: %v", err)
		return err
	}

	// Set TAP link MTU.
	err = netlink.LinkSetMTU(tapLink, vpc.JumboFrameMTU)
	if err != nil {
		log.Errorf("Failed to set TAP geneve MTU: %v", err)
		return err
	}

	// Set TAP link ownership.
	log.Infof("Setting TAP geneve owner to UID %d and GID %d.", tapCfg.Uid, tapCfg.Gid)
	for _, tapFd := range tapLink.Fds {
		fd := int(tapFd.Fd())

		err = unix.IoctlSetInt(fd, unix.TUNSETOWNER, tapCfg.Uid)
		if err != nil {
			log.Errorf("Failed to set TAP geneve UID: %v", err)
			return err
		}
		err = unix.IoctlSetInt(fd, unix.TUNSETGROUP, tapCfg.Gid)
		if err != nil {
			log.Errorf("Failed to set TAP geneve GID: %v", err)
			return err
		}

		tapFd.Close()
	}

	// Set TAP link operational state up.
	err = netlink.LinkSetUp(tapLink)
	if err != nil {
		log.Errorf("Failed to set TAP geneve state: %v", err)
		return err
	}

	return nil
}