in cni/internal/netlink.go [198:245]
func (defaultNetlinkOps) CreateTap(name string, mtu int, ownerUID, ownerGID int) (netlink.Link, error) {
tapLinkAttrs := netlink.NewLinkAttrs()
tapLinkAttrs.Name = name
tapLink := &netlink.Tuntap{
LinkAttrs: tapLinkAttrs,
// We want a tap device (L2) as opposed to a tun (L3)
Mode: netlink.TUNTAP_MODE_TAP,
// Firecracker does not support multiqueue tap devices at this time:
// https://github.com/firecracker-microvm/firecracker/issues/750
Queues: 1,
Flags: netlink.TUNTAP_ONE_QUEUE | // single queue tap device
netlink.TUNTAP_VNET_HDR, // parse vnet headers added by the vm's virtio_net implementation
}
err := netlink.LinkAdd(tapLink)
if err != nil {
return nil, errors.Wrap(err, "failed to create tap device")
}
for _, tapFd := range tapLink.Fds {
err = unix.IoctlSetInt(int(tapFd.Fd()), unix.TUNSETOWNER, ownerUID)
if err != nil {
return nil, errors.Wrapf(err, "failed to set tap %s owner to uid %d",
name, ownerUID)
}
err = unix.IoctlSetInt(int(tapFd.Fd()), unix.TUNSETGROUP, ownerGID)
if err != nil {
return nil, errors.Wrapf(err, "failed to set tap %s group to gid %d",
name, ownerGID)
}
}
err = netlink.LinkSetMTU(tapLink, mtu)
if err != nil {
return nil, errors.Wrapf(err, "failed to set tap device MTU to %d", mtu)
}
err = netlink.LinkSetUp(tapLink)
if err != nil {
return nil, errors.Wrap(err, "failed to set tap up")
}
return tapLink, nil
}