netlink/netlink_linux.go
func NetworkLinkAddVlan(masterDev, vlanDev string, vlanId uint16) error {
	s, err := getNetlinkSocket()
	if err != nil {
		return err
	}
	defer s.Close()

	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)

	masterDevIfc, err := net.InterfaceByName(masterDev)
	if err != nil {
		return err
	}

	msg := newIfInfomsg(syscall.AF_UNSPEC)
	wb.AddData(msg)

	nest1 := newRtAttr(syscall.IFLA_LINKINFO, nil)
	newRtAttrChild(nest1, IFLA_INFO_KIND, nonZeroTerminated("vlan"))

	nest2 := newRtAttrChild(nest1, IFLA_INFO_DATA, nil)
	vlanData := make([]byte, 2)
	native.PutUint16(vlanData, vlanId)
	newRtAttrChild(nest2, IFLA_VLAN_ID, vlanData)
	wb.AddData(nest1)

	wb.AddData(uint32Attr(syscall.IFLA_LINK, uint32(masterDevIfc.Index)))
	wb.AddData(newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(vlanDev)))

	if err := s.Send(wb); err != nil {
		return err
	}
	return s.HandleAck(wb.Seq)
}
func NetworkLinkAddVlan(masterDev, vlanDev string, vlanId uint16) error {
	s, err := getNetlinkSocket()
	if err != nil {
		return err
	}
	defer s.Close()

	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)

	masterDevIfc, err := net.InterfaceByName(masterDev)
	if err != nil {
		return err
	}

	msg := newIfInfomsg(syscall.AF_UNSPEC)
	wb.AddData(msg)

	nest1 := newRtAttr(syscall.IFLA_LINKINFO, nil)
	newRtAttrChild(nest1, IFLA_INFO_KIND, nonZeroTerminated("vlan"))

	nest2 := newRtAttrChild(nest1, IFLA_INFO_DATA, nil)
	vlanData := make([]byte, 2)
	native.PutUint16(vlanData, vlanId)
	newRtAttrChild(nest2, IFLA_VLAN_ID, vlanData)
	wb.AddData(nest1)

	wb.AddData(uint32Attr(syscall.IFLA_LINK, uint32(masterDevIfc.Index)))
	wb.AddData(newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(vlanDev)))

	if err := s.Send(wb); err != nil {
		return err
	}
	return s.HandleAck(wb.Seq)
}
// Add a new VLAN interface with masterDev as its upper device
// This is identical to running:
// ip link add name $name link $masterdev type vlan id $id