in plugins/vpc-branch-eni/plugin/commands.go [321:437]
func (plugin *Plugin) createTAPLink(
branch *eni.Branch,
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 link %+v.", bridge)
err := netlink.LinkAdd(bridge)
if err != nil {
log.Errorf("Failed to create bridge link: %v", err)
return err
}
// Set bridge link MTU.
err = netlink.LinkSetMTU(bridge, vpc.JumboFrameMTU)
if err != nil {
log.Errorf("Failed to set bridge link MTU: %v", err)
return err
}
// In TAP mode, the branch 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 branch link itself. However, this
// can happen if the branch link is being reused between successive invocations of the plugin.
// Overriding the branch link'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 link: %v", err)
return err
}
err = branch.SetMACAddress(bridgeLink.Attrs().HardwareAddr)
if err != nil {
log.Errorf("Failed to set branch link MAC address: %v.", err)
return err
}
// Set bridge link operational state up.
err = netlink.LinkSetUp(bridge)
if err != nil {
log.Errorf("Failed to set bridge link state: %v", err)
return err
}
// Connect branch link to the bridge.
la = netlink.NewLinkAttrs()
la.Name = branch.GetLinkName()
branchLink := &netlink.Dummy{LinkAttrs: la}
err = netlink.LinkSetMaster(branchLink, bridge)
if err != nil {
log.Errorf("Failed to set branch link master: %v", err)
return err
}
// Create the TAP link.
// 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 link %+v.", tapLink)
err = netlink.LinkAdd(tapLink)
if err != nil {
log.Errorf("Failed to add TAP link: %v", err)
return err
}
// Set TAP link MTU.
err = netlink.LinkSetMTU(tapLink, vpc.JumboFrameMTU)
if err != nil {
log.Errorf("Failed to set TAP link MTU: %v", err)
return err
}
// Set TAP link ownership.
log.Infof("Setting TAP link 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 link UID: %v", err)
return err
}
err = unix.IoctlSetInt(fd, unix.TUNSETGROUP, tapCfg.Gid)
if err != nil {
log.Errorf("Failed to set TAP link 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 link state: %v", err)
return err
}
return nil
}