github.com/vishvananda/netlink@v1.3.0/link_linux.go (about)

     1  package netlink
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"net"
     9  	"os"
    10  	"strconv"
    11  	"strings"
    12  	"syscall"
    13  	"unsafe"
    14  
    15  	"github.com/vishvananda/netlink/nl"
    16  	"github.com/vishvananda/netns"
    17  	"golang.org/x/sys/unix"
    18  )
    19  
    20  const (
    21  	SizeofLinkStats32 = 0x5c
    22  	SizeofLinkStats64 = 0xb8
    23  )
    24  
    25  const (
    26  	TUNTAP_MODE_TUN             TuntapMode = unix.IFF_TUN
    27  	TUNTAP_MODE_TAP             TuntapMode = unix.IFF_TAP
    28  	TUNTAP_DEFAULTS             TuntapFlag = unix.IFF_TUN_EXCL | unix.IFF_ONE_QUEUE
    29  	TUNTAP_VNET_HDR             TuntapFlag = unix.IFF_VNET_HDR
    30  	TUNTAP_TUN_EXCL             TuntapFlag = unix.IFF_TUN_EXCL
    31  	TUNTAP_NO_PI                TuntapFlag = unix.IFF_NO_PI
    32  	TUNTAP_ONE_QUEUE            TuntapFlag = unix.IFF_ONE_QUEUE
    33  	TUNTAP_MULTI_QUEUE          TuntapFlag = unix.IFF_MULTI_QUEUE
    34  	TUNTAP_MULTI_QUEUE_DEFAULTS TuntapFlag = TUNTAP_MULTI_QUEUE | TUNTAP_NO_PI
    35  )
    36  
    37  var StringToTuntapModeMap = map[string]TuntapMode{
    38  	"tun": TUNTAP_MODE_TUN,
    39  	"tap": TUNTAP_MODE_TAP,
    40  }
    41  
    42  func (ttm TuntapMode) String() string {
    43  	switch ttm {
    44  	case TUNTAP_MODE_TUN:
    45  		return "tun"
    46  	case TUNTAP_MODE_TAP:
    47  		return "tap"
    48  	}
    49  	return "unknown"
    50  }
    51  
    52  const (
    53  	VF_LINK_STATE_AUTO    uint32 = 0
    54  	VF_LINK_STATE_ENABLE  uint32 = 1
    55  	VF_LINK_STATE_DISABLE uint32 = 2
    56  )
    57  
    58  var macvlanModes = [...]uint32{
    59  	0,
    60  	nl.MACVLAN_MODE_PRIVATE,
    61  	nl.MACVLAN_MODE_VEPA,
    62  	nl.MACVLAN_MODE_BRIDGE,
    63  	nl.MACVLAN_MODE_PASSTHRU,
    64  	nl.MACVLAN_MODE_SOURCE,
    65  }
    66  
    67  func ensureIndex(link *LinkAttrs) {
    68  	if link != nil && link.Index == 0 {
    69  		newlink, _ := LinkByName(link.Name)
    70  		if newlink != nil {
    71  			link.Index = newlink.Attrs().Index
    72  		}
    73  	}
    74  }
    75  
    76  func (h *Handle) ensureIndex(link *LinkAttrs) {
    77  	if link != nil && link.Index == 0 {
    78  		newlink, _ := h.LinkByName(link.Name)
    79  		if newlink != nil {
    80  			link.Index = newlink.Attrs().Index
    81  		}
    82  	}
    83  }
    84  
    85  func (h *Handle) LinkSetARPOff(link Link) error {
    86  	base := link.Attrs()
    87  	h.ensureIndex(base)
    88  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
    89  
    90  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
    91  	msg.Change |= unix.IFF_NOARP
    92  	msg.Flags |= unix.IFF_NOARP
    93  	msg.Index = int32(base.Index)
    94  	req.AddData(msg)
    95  
    96  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
    97  	return err
    98  }
    99  
   100  func LinkSetARPOff(link Link) error {
   101  	return pkgHandle.LinkSetARPOff(link)
   102  }
   103  
   104  func (h *Handle) LinkSetARPOn(link Link) error {
   105  	base := link.Attrs()
   106  	h.ensureIndex(base)
   107  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
   108  
   109  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   110  	msg.Change |= unix.IFF_NOARP
   111  	msg.Flags &= ^uint32(unix.IFF_NOARP)
   112  	msg.Index = int32(base.Index)
   113  	req.AddData(msg)
   114  
   115  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   116  	return err
   117  }
   118  
   119  func LinkSetARPOn(link Link) error {
   120  	return pkgHandle.LinkSetARPOn(link)
   121  }
   122  
   123  func (h *Handle) SetPromiscOn(link Link) error {
   124  	base := link.Attrs()
   125  	h.ensureIndex(base)
   126  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
   127  
   128  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   129  	msg.Change = unix.IFF_PROMISC
   130  	msg.Flags = unix.IFF_PROMISC
   131  	msg.Index = int32(base.Index)
   132  	req.AddData(msg)
   133  
   134  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   135  	return err
   136  }
   137  
   138  // LinkSetAllmulticastOn enables the reception of all hardware multicast packets for the link device.
   139  // Equivalent to: `ip link set $link allmulticast on`
   140  func LinkSetAllmulticastOn(link Link) error {
   141  	return pkgHandle.LinkSetAllmulticastOn(link)
   142  }
   143  
   144  // LinkSetAllmulticastOn enables the reception of all hardware multicast packets for the link device.
   145  // Equivalent to: `ip link set $link allmulticast on`
   146  func (h *Handle) LinkSetAllmulticastOn(link Link) error {
   147  	base := link.Attrs()
   148  	h.ensureIndex(base)
   149  	req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
   150  
   151  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   152  	msg.Change = unix.IFF_ALLMULTI
   153  	msg.Flags = unix.IFF_ALLMULTI
   154  	msg.Index = int32(base.Index)
   155  	req.AddData(msg)
   156  
   157  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   158  	return err
   159  }
   160  
   161  // LinkSetAllmulticastOff disables the reception of all hardware multicast packets for the link device.
   162  // Equivalent to: `ip link set $link allmulticast off`
   163  func LinkSetAllmulticastOff(link Link) error {
   164  	return pkgHandle.LinkSetAllmulticastOff(link)
   165  }
   166  
   167  // LinkSetAllmulticastOff disables the reception of all hardware multicast packets for the link device.
   168  // Equivalent to: `ip link set $link allmulticast off`
   169  func (h *Handle) LinkSetAllmulticastOff(link Link) error {
   170  	base := link.Attrs()
   171  	h.ensureIndex(base)
   172  	req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
   173  
   174  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   175  	msg.Change = unix.IFF_ALLMULTI
   176  	msg.Index = int32(base.Index)
   177  	req.AddData(msg)
   178  
   179  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   180  	return err
   181  }
   182  
   183  // LinkSetMulticastOn enables the reception of multicast packets for the link device.
   184  // Equivalent to: `ip link set $link multicast on`
   185  func LinkSetMulticastOn(link Link) error {
   186  	return pkgHandle.LinkSetMulticastOn(link)
   187  }
   188  
   189  // LinkSetMulticastOn enables the reception of multicast packets for the link device.
   190  // Equivalent to: `ip link set $link multicast on`
   191  func (h *Handle) LinkSetMulticastOn(link Link) error {
   192  	base := link.Attrs()
   193  	h.ensureIndex(base)
   194  	req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
   195  
   196  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   197  	msg.Change = unix.IFF_MULTICAST
   198  	msg.Flags = unix.IFF_MULTICAST
   199  	msg.Index = int32(base.Index)
   200  	req.AddData(msg)
   201  
   202  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   203  	return err
   204  }
   205  
   206  // LinkSetAllmulticastOff disables the reception of multicast packets for the link device.
   207  // Equivalent to: `ip link set $link multicast off`
   208  func LinkSetMulticastOff(link Link) error {
   209  	return pkgHandle.LinkSetMulticastOff(link)
   210  }
   211  
   212  // LinkSetAllmulticastOff disables the reception of multicast packets for the link device.
   213  // Equivalent to: `ip link set $link multicast off`
   214  func (h *Handle) LinkSetMulticastOff(link Link) error {
   215  	base := link.Attrs()
   216  	h.ensureIndex(base)
   217  	req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
   218  
   219  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   220  	msg.Change = unix.IFF_MULTICAST
   221  	msg.Index = int32(base.Index)
   222  	req.AddData(msg)
   223  
   224  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   225  	return err
   226  }
   227  
   228  func MacvlanMACAddrAdd(link Link, addr net.HardwareAddr) error {
   229  	return pkgHandle.MacvlanMACAddrAdd(link, addr)
   230  }
   231  
   232  func (h *Handle) MacvlanMACAddrAdd(link Link, addr net.HardwareAddr) error {
   233  	return h.macvlanMACAddrChange(link, []net.HardwareAddr{addr}, nl.MACVLAN_MACADDR_ADD)
   234  }
   235  
   236  func MacvlanMACAddrDel(link Link, addr net.HardwareAddr) error {
   237  	return pkgHandle.MacvlanMACAddrDel(link, addr)
   238  }
   239  
   240  func (h *Handle) MacvlanMACAddrDel(link Link, addr net.HardwareAddr) error {
   241  	return h.macvlanMACAddrChange(link, []net.HardwareAddr{addr}, nl.MACVLAN_MACADDR_DEL)
   242  }
   243  
   244  func MacvlanMACAddrFlush(link Link) error {
   245  	return pkgHandle.MacvlanMACAddrFlush(link)
   246  }
   247  
   248  func (h *Handle) MacvlanMACAddrFlush(link Link) error {
   249  	return h.macvlanMACAddrChange(link, nil, nl.MACVLAN_MACADDR_FLUSH)
   250  }
   251  
   252  func MacvlanMACAddrSet(link Link, addrs []net.HardwareAddr) error {
   253  	return pkgHandle.MacvlanMACAddrSet(link, addrs)
   254  }
   255  
   256  func (h *Handle) MacvlanMACAddrSet(link Link, addrs []net.HardwareAddr) error {
   257  	return h.macvlanMACAddrChange(link, addrs, nl.MACVLAN_MACADDR_SET)
   258  }
   259  
   260  func (h *Handle) macvlanMACAddrChange(link Link, addrs []net.HardwareAddr, mode uint32) error {
   261  	base := link.Attrs()
   262  	h.ensureIndex(base)
   263  	req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
   264  
   265  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   266  	msg.Index = int32(base.Index)
   267  	req.AddData(msg)
   268  
   269  	linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil)
   270  	linkInfo.AddRtAttr(nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type()))
   271  	inner := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
   272  
   273  	// IFLA_MACVLAN_MACADDR_MODE = mode
   274  	b := make([]byte, 4)
   275  	native.PutUint32(b, mode)
   276  	inner.AddRtAttr(nl.IFLA_MACVLAN_MACADDR_MODE, b)
   277  
   278  	// populate message with MAC addrs, if necessary
   279  	switch mode {
   280  	case nl.MACVLAN_MACADDR_ADD, nl.MACVLAN_MACADDR_DEL:
   281  		if len(addrs) == 1 {
   282  			inner.AddRtAttr(nl.IFLA_MACVLAN_MACADDR, []byte(addrs[0]))
   283  		}
   284  	case nl.MACVLAN_MACADDR_SET:
   285  		mad := inner.AddRtAttr(nl.IFLA_MACVLAN_MACADDR_DATA, nil)
   286  		for _, addr := range addrs {
   287  			mad.AddRtAttr(nl.IFLA_MACVLAN_MACADDR, []byte(addr))
   288  		}
   289  	}
   290  
   291  	req.AddData(linkInfo)
   292  
   293  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   294  	return err
   295  }
   296  
   297  // LinkSetMacvlanMode sets the mode of a macvlan or macvtap link device.
   298  // Note that passthrough mode cannot be set to and from and will fail.
   299  // Equivalent to: `ip link set $link type (macvlan|macvtap) mode $mode
   300  func LinkSetMacvlanMode(link Link, mode MacvlanMode) error {
   301  	return pkgHandle.LinkSetMacvlanMode(link, mode)
   302  }
   303  
   304  // LinkSetMacvlanMode sets the mode of the macvlan or macvtap link device.
   305  // Note that passthrough mode cannot be set to and from and will fail.
   306  // Equivalent to: `ip link set $link type (macvlan|macvtap) mode $mode
   307  func (h *Handle) LinkSetMacvlanMode(link Link, mode MacvlanMode) error {
   308  	base := link.Attrs()
   309  	h.ensureIndex(base)
   310  	req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
   311  
   312  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   313  	msg.Index = int32(base.Index)
   314  	req.AddData(msg)
   315  
   316  	linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil)
   317  	linkInfo.AddRtAttr(nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type()))
   318  
   319  	data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
   320  	data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[mode]))
   321  
   322  	req.AddData(linkInfo)
   323  
   324  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   325  	return err
   326  }
   327  
   328  func BridgeSetMcastSnoop(link Link, on bool) error {
   329  	return pkgHandle.BridgeSetMcastSnoop(link, on)
   330  }
   331  
   332  func (h *Handle) BridgeSetMcastSnoop(link Link, on bool) error {
   333  	bridge := link.(*Bridge)
   334  	bridge.MulticastSnooping = &on
   335  	return h.linkModify(bridge, unix.NLM_F_ACK)
   336  }
   337  
   338  func BridgeSetVlanFiltering(link Link, on bool) error {
   339  	return pkgHandle.BridgeSetVlanFiltering(link, on)
   340  }
   341  
   342  func (h *Handle) BridgeSetVlanFiltering(link Link, on bool) error {
   343  	bridge := link.(*Bridge)
   344  	bridge.VlanFiltering = &on
   345  	return h.linkModify(bridge, unix.NLM_F_ACK)
   346  }
   347  
   348  func BridgeSetVlanDefaultPVID(link Link, pvid uint16) error {
   349  	return pkgHandle.BridgeSetVlanDefaultPVID(link, pvid)
   350  }
   351  
   352  func (h *Handle) BridgeSetVlanDefaultPVID(link Link, pvid uint16) error {
   353  	bridge := link.(*Bridge)
   354  	bridge.VlanDefaultPVID = &pvid
   355  	return h.linkModify(bridge, unix.NLM_F_ACK)
   356  }
   357  
   358  func SetPromiscOn(link Link) error {
   359  	return pkgHandle.SetPromiscOn(link)
   360  }
   361  
   362  func (h *Handle) SetPromiscOff(link Link) error {
   363  	base := link.Attrs()
   364  	h.ensureIndex(base)
   365  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
   366  
   367  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   368  	msg.Change = unix.IFF_PROMISC
   369  	msg.Index = int32(base.Index)
   370  	req.AddData(msg)
   371  
   372  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   373  	return err
   374  }
   375  
   376  func SetPromiscOff(link Link) error {
   377  	return pkgHandle.SetPromiscOff(link)
   378  }
   379  
   380  // LinkSetUp enables the link device.
   381  // Equivalent to: `ip link set $link up`
   382  func LinkSetUp(link Link) error {
   383  	return pkgHandle.LinkSetUp(link)
   384  }
   385  
   386  // LinkSetUp enables the link device.
   387  // Equivalent to: `ip link set $link up`
   388  func (h *Handle) LinkSetUp(link Link) error {
   389  	base := link.Attrs()
   390  	h.ensureIndex(base)
   391  	req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
   392  
   393  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   394  	msg.Change = unix.IFF_UP
   395  	msg.Flags = unix.IFF_UP
   396  	msg.Index = int32(base.Index)
   397  	req.AddData(msg)
   398  
   399  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   400  	return err
   401  }
   402  
   403  // LinkSetDown disables link device.
   404  // Equivalent to: `ip link set $link down`
   405  func LinkSetDown(link Link) error {
   406  	return pkgHandle.LinkSetDown(link)
   407  }
   408  
   409  // LinkSetDown disables link device.
   410  // Equivalent to: `ip link set $link down`
   411  func (h *Handle) LinkSetDown(link Link) error {
   412  	base := link.Attrs()
   413  	h.ensureIndex(base)
   414  	req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
   415  
   416  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   417  	msg.Change = unix.IFF_UP
   418  	msg.Index = int32(base.Index)
   419  	req.AddData(msg)
   420  
   421  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   422  	return err
   423  }
   424  
   425  // LinkSetMTU sets the mtu of the link device.
   426  // Equivalent to: `ip link set $link mtu $mtu`
   427  func LinkSetMTU(link Link, mtu int) error {
   428  	return pkgHandle.LinkSetMTU(link, mtu)
   429  }
   430  
   431  // LinkSetMTU sets the mtu of the link device.
   432  // Equivalent to: `ip link set $link mtu $mtu`
   433  func (h *Handle) LinkSetMTU(link Link, mtu int) error {
   434  	base := link.Attrs()
   435  	h.ensureIndex(base)
   436  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
   437  
   438  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   439  	msg.Index = int32(base.Index)
   440  	req.AddData(msg)
   441  
   442  	b := make([]byte, 4)
   443  	native.PutUint32(b, uint32(mtu))
   444  
   445  	data := nl.NewRtAttr(unix.IFLA_MTU, b)
   446  	req.AddData(data)
   447  
   448  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   449  	return err
   450  }
   451  
   452  // LinkSetName sets the name of the link device.
   453  // Equivalent to: `ip link set $link name $name`
   454  func LinkSetName(link Link, name string) error {
   455  	return pkgHandle.LinkSetName(link, name)
   456  }
   457  
   458  // LinkSetName sets the name of the link device.
   459  // Equivalent to: `ip link set $link name $name`
   460  func (h *Handle) LinkSetName(link Link, name string) error {
   461  	base := link.Attrs()
   462  	h.ensureIndex(base)
   463  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
   464  
   465  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   466  	msg.Index = int32(base.Index)
   467  	req.AddData(msg)
   468  
   469  	data := nl.NewRtAttr(unix.IFLA_IFNAME, []byte(name))
   470  	req.AddData(data)
   471  
   472  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   473  	return err
   474  }
   475  
   476  // LinkSetAlias sets the alias of the link device.
   477  // Equivalent to: `ip link set dev $link alias $name`
   478  func LinkSetAlias(link Link, name string) error {
   479  	return pkgHandle.LinkSetAlias(link, name)
   480  }
   481  
   482  // LinkSetAlias sets the alias of the link device.
   483  // Equivalent to: `ip link set dev $link alias $name`
   484  func (h *Handle) LinkSetAlias(link Link, name string) error {
   485  	base := link.Attrs()
   486  	h.ensureIndex(base)
   487  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
   488  
   489  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   490  	msg.Index = int32(base.Index)
   491  	req.AddData(msg)
   492  
   493  	data := nl.NewRtAttr(unix.IFLA_IFALIAS, []byte(name))
   494  	req.AddData(data)
   495  
   496  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   497  	return err
   498  }
   499  
   500  // LinkAddAltName adds a new alternative name for the link device.
   501  // Equivalent to: `ip link property add $link altname $name`
   502  func LinkAddAltName(link Link, name string) error {
   503  	return pkgHandle.LinkAddAltName(link, name)
   504  }
   505  
   506  // LinkAddAltName adds a new alternative name for the link device.
   507  // Equivalent to: `ip link property add $link altname $name`
   508  func (h *Handle) LinkAddAltName(link Link, name string) error {
   509  	base := link.Attrs()
   510  	h.ensureIndex(base)
   511  	req := h.newNetlinkRequest(unix.RTM_NEWLINKPROP, unix.NLM_F_ACK)
   512  
   513  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   514  	msg.Index = int32(base.Index)
   515  	req.AddData(msg)
   516  
   517  	data := nl.NewRtAttr(unix.IFLA_PROP_LIST|unix.NLA_F_NESTED, nil)
   518  	data.AddRtAttr(unix.IFLA_ALT_IFNAME, []byte(name))
   519  
   520  	req.AddData(data)
   521  
   522  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   523  	return err
   524  }
   525  
   526  // LinkDelAltName delete an alternative name for the link device.
   527  // Equivalent to: `ip link property del $link altname $name`
   528  func LinkDelAltName(link Link, name string) error {
   529  	return pkgHandle.LinkDelAltName(link, name)
   530  }
   531  
   532  // LinkDelAltName delete an alternative name for the link device.
   533  // Equivalent to: `ip link property del $link altname $name`
   534  func (h *Handle) LinkDelAltName(link Link, name string) error {
   535  	base := link.Attrs()
   536  	h.ensureIndex(base)
   537  	req := h.newNetlinkRequest(unix.RTM_DELLINKPROP, unix.NLM_F_ACK)
   538  
   539  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   540  	msg.Index = int32(base.Index)
   541  	req.AddData(msg)
   542  
   543  	data := nl.NewRtAttr(unix.IFLA_PROP_LIST|unix.NLA_F_NESTED, nil)
   544  	data.AddRtAttr(unix.IFLA_ALT_IFNAME, []byte(name))
   545  
   546  	req.AddData(data)
   547  
   548  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   549  	return err
   550  }
   551  
   552  // LinkSetHardwareAddr sets the hardware address of the link device.
   553  // Equivalent to: `ip link set $link address $hwaddr`
   554  func LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error {
   555  	return pkgHandle.LinkSetHardwareAddr(link, hwaddr)
   556  }
   557  
   558  // LinkSetHardwareAddr sets the hardware address of the link device.
   559  // Equivalent to: `ip link set $link address $hwaddr`
   560  func (h *Handle) LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error {
   561  	base := link.Attrs()
   562  	h.ensureIndex(base)
   563  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
   564  
   565  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   566  	msg.Index = int32(base.Index)
   567  	req.AddData(msg)
   568  
   569  	data := nl.NewRtAttr(unix.IFLA_ADDRESS, []byte(hwaddr))
   570  	req.AddData(data)
   571  
   572  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   573  	return err
   574  }
   575  
   576  // LinkSetVfHardwareAddr sets the hardware address of a vf for the link.
   577  // Equivalent to: `ip link set $link vf $vf mac $hwaddr`
   578  func LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error {
   579  	return pkgHandle.LinkSetVfHardwareAddr(link, vf, hwaddr)
   580  }
   581  
   582  // LinkSetVfHardwareAddr sets the hardware address of a vf for the link.
   583  // Equivalent to: `ip link set $link vf $vf mac $hwaddr`
   584  func (h *Handle) LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error {
   585  	base := link.Attrs()
   586  	h.ensureIndex(base)
   587  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
   588  
   589  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   590  	msg.Index = int32(base.Index)
   591  	req.AddData(msg)
   592  
   593  	data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
   594  	info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
   595  	vfmsg := nl.VfMac{
   596  		Vf: uint32(vf),
   597  	}
   598  	copy(vfmsg.Mac[:], []byte(hwaddr))
   599  	info.AddRtAttr(nl.IFLA_VF_MAC, vfmsg.Serialize())
   600  	req.AddData(data)
   601  
   602  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   603  	return err
   604  }
   605  
   606  // LinkSetVfVlan sets the vlan of a vf for the link.
   607  // Equivalent to: `ip link set $link vf $vf vlan $vlan`
   608  func LinkSetVfVlan(link Link, vf, vlan int) error {
   609  	return pkgHandle.LinkSetVfVlan(link, vf, vlan)
   610  }
   611  
   612  // LinkSetVfVlan sets the vlan of a vf for the link.
   613  // Equivalent to: `ip link set $link vf $vf vlan $vlan`
   614  func (h *Handle) LinkSetVfVlan(link Link, vf, vlan int) error {
   615  	base := link.Attrs()
   616  	h.ensureIndex(base)
   617  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
   618  
   619  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   620  	msg.Index = int32(base.Index)
   621  	req.AddData(msg)
   622  
   623  	data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
   624  	info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
   625  	vfmsg := nl.VfVlan{
   626  		Vf:   uint32(vf),
   627  		Vlan: uint32(vlan),
   628  	}
   629  	info.AddRtAttr(nl.IFLA_VF_VLAN, vfmsg.Serialize())
   630  	req.AddData(data)
   631  
   632  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   633  	return err
   634  }
   635  
   636  // LinkSetVfVlanQos sets the vlan and qos priority of a vf for the link.
   637  // Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos`
   638  func LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
   639  	return pkgHandle.LinkSetVfVlanQos(link, vf, vlan, qos)
   640  }
   641  
   642  // LinkSetVfVlanQos sets the vlan and qos priority of a vf for the link.
   643  // Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos`
   644  func (h *Handle) LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
   645  	base := link.Attrs()
   646  	h.ensureIndex(base)
   647  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
   648  
   649  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   650  	msg.Index = int32(base.Index)
   651  	req.AddData(msg)
   652  
   653  	data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
   654  	info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
   655  	vfmsg := nl.VfVlan{
   656  		Vf:   uint32(vf),
   657  		Vlan: uint32(vlan),
   658  		Qos:  uint32(qos),
   659  	}
   660  	info.AddRtAttr(nl.IFLA_VF_VLAN, vfmsg.Serialize())
   661  	req.AddData(data)
   662  
   663  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   664  	return err
   665  }
   666  
   667  // LinkSetVfVlanQosProto sets the vlan, qos and protocol of a vf for the link.
   668  // Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos proto $proto`
   669  func LinkSetVfVlanQosProto(link Link, vf, vlan, qos, proto int) error {
   670  	return pkgHandle.LinkSetVfVlanQosProto(link, vf, vlan, qos, proto)
   671  }
   672  
   673  // LinkSetVfVlanQosProto sets the vlan, qos and protocol of a vf for the link.
   674  // Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos proto $proto`
   675  func (h *Handle) LinkSetVfVlanQosProto(link Link, vf, vlan, qos, proto int) error {
   676  	base := link.Attrs()
   677  	h.ensureIndex(base)
   678  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
   679  
   680  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   681  	msg.Index = int32(base.Index)
   682  	req.AddData(msg)
   683  
   684  	data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
   685  	vfInfo := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
   686  	vfVlanList := vfInfo.AddRtAttr(nl.IFLA_VF_VLAN_LIST, nil)
   687  
   688  	vfmsg := nl.VfVlanInfo{
   689  		VfVlan: nl.VfVlan{
   690  			Vf:   uint32(vf),
   691  			Vlan: uint32(vlan),
   692  			Qos:  uint32(qos),
   693  		},
   694  		VlanProto: (uint16(proto)>>8)&0xFF | (uint16(proto)&0xFF)<<8,
   695  	}
   696  
   697  	vfVlanList.AddRtAttr(nl.IFLA_VF_VLAN_INFO, vfmsg.Serialize())
   698  	req.AddData(data)
   699  
   700  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   701  	return err
   702  }
   703  
   704  // LinkSetVfTxRate sets the tx rate of a vf for the link.
   705  // Equivalent to: `ip link set $link vf $vf rate $rate`
   706  func LinkSetVfTxRate(link Link, vf, rate int) error {
   707  	return pkgHandle.LinkSetVfTxRate(link, vf, rate)
   708  }
   709  
   710  // LinkSetVfTxRate sets the tx rate of a vf for the link.
   711  // Equivalent to: `ip link set $link vf $vf rate $rate`
   712  func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error {
   713  	base := link.Attrs()
   714  	h.ensureIndex(base)
   715  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
   716  
   717  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   718  	msg.Index = int32(base.Index)
   719  	req.AddData(msg)
   720  
   721  	data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
   722  	info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
   723  	vfmsg := nl.VfTxRate{
   724  		Vf:   uint32(vf),
   725  		Rate: uint32(rate),
   726  	}
   727  	info.AddRtAttr(nl.IFLA_VF_TX_RATE, vfmsg.Serialize())
   728  	req.AddData(data)
   729  
   730  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   731  	return err
   732  }
   733  
   734  // LinkSetVfRate sets the min and max tx rate of a vf for the link.
   735  // Equivalent to: `ip link set $link vf $vf min_tx_rate $min_rate max_tx_rate $max_rate`
   736  func LinkSetVfRate(link Link, vf, minRate, maxRate int) error {
   737  	return pkgHandle.LinkSetVfRate(link, vf, minRate, maxRate)
   738  }
   739  
   740  // LinkSetVfRate sets the min and max tx rate of a vf for the link.
   741  // Equivalent to: `ip link set $link vf $vf min_tx_rate $min_rate max_tx_rate $max_rate`
   742  func (h *Handle) LinkSetVfRate(link Link, vf, minRate, maxRate int) error {
   743  	base := link.Attrs()
   744  	h.ensureIndex(base)
   745  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
   746  
   747  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   748  	msg.Index = int32(base.Index)
   749  	req.AddData(msg)
   750  
   751  	data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
   752  	info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
   753  	vfmsg := nl.VfRate{
   754  		Vf:        uint32(vf),
   755  		MinTxRate: uint32(minRate),
   756  		MaxTxRate: uint32(maxRate),
   757  	}
   758  	info.AddRtAttr(nl.IFLA_VF_RATE, vfmsg.Serialize())
   759  	req.AddData(data)
   760  
   761  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   762  	return err
   763  }
   764  
   765  // LinkSetVfState enables/disables virtual link state on a vf.
   766  // Equivalent to: `ip link set $link vf $vf state $state`
   767  func LinkSetVfState(link Link, vf int, state uint32) error {
   768  	return pkgHandle.LinkSetVfState(link, vf, state)
   769  }
   770  
   771  // LinkSetVfState enables/disables virtual link state on a vf.
   772  // Equivalent to: `ip link set $link vf $vf state $state`
   773  func (h *Handle) LinkSetVfState(link Link, vf int, state uint32) error {
   774  	base := link.Attrs()
   775  	h.ensureIndex(base)
   776  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
   777  
   778  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   779  	msg.Index = int32(base.Index)
   780  	req.AddData(msg)
   781  
   782  	data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
   783  	info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
   784  	vfmsg := nl.VfLinkState{
   785  		Vf:        uint32(vf),
   786  		LinkState: state,
   787  	}
   788  	info.AddRtAttr(nl.IFLA_VF_LINK_STATE, vfmsg.Serialize())
   789  	req.AddData(data)
   790  
   791  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   792  	return err
   793  }
   794  
   795  // LinkSetVfSpoofchk enables/disables spoof check on a vf for the link.
   796  // Equivalent to: `ip link set $link vf $vf spoofchk $check`
   797  func LinkSetVfSpoofchk(link Link, vf int, check bool) error {
   798  	return pkgHandle.LinkSetVfSpoofchk(link, vf, check)
   799  }
   800  
   801  // LinkSetVfSpoofchk enables/disables spoof check on a vf for the link.
   802  // Equivalent to: `ip link set $link vf $vf spoofchk $check`
   803  func (h *Handle) LinkSetVfSpoofchk(link Link, vf int, check bool) error {
   804  	var setting uint32
   805  	base := link.Attrs()
   806  	h.ensureIndex(base)
   807  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
   808  
   809  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   810  	msg.Index = int32(base.Index)
   811  	req.AddData(msg)
   812  
   813  	data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
   814  	info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
   815  	if check {
   816  		setting = 1
   817  	}
   818  	vfmsg := nl.VfSpoofchk{
   819  		Vf:      uint32(vf),
   820  		Setting: setting,
   821  	}
   822  	info.AddRtAttr(nl.IFLA_VF_SPOOFCHK, vfmsg.Serialize())
   823  	req.AddData(data)
   824  
   825  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   826  	return err
   827  }
   828  
   829  // LinkSetVfTrust enables/disables trust state on a vf for the link.
   830  // Equivalent to: `ip link set $link vf $vf trust $state`
   831  func LinkSetVfTrust(link Link, vf int, state bool) error {
   832  	return pkgHandle.LinkSetVfTrust(link, vf, state)
   833  }
   834  
   835  // LinkSetVfTrust enables/disables trust state on a vf for the link.
   836  // Equivalent to: `ip link set $link vf $vf trust $state`
   837  func (h *Handle) LinkSetVfTrust(link Link, vf int, state bool) error {
   838  	var setting uint32
   839  	base := link.Attrs()
   840  	h.ensureIndex(base)
   841  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
   842  
   843  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   844  	msg.Index = int32(base.Index)
   845  	req.AddData(msg)
   846  
   847  	data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
   848  	info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
   849  	if state {
   850  		setting = 1
   851  	}
   852  	vfmsg := nl.VfTrust{
   853  		Vf:      uint32(vf),
   854  		Setting: setting,
   855  	}
   856  	info.AddRtAttr(nl.IFLA_VF_TRUST, vfmsg.Serialize())
   857  	req.AddData(data)
   858  
   859  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   860  	return err
   861  }
   862  
   863  // LinkSetVfNodeGUID sets the node GUID of a vf for the link.
   864  // Equivalent to: `ip link set dev $link vf $vf node_guid $nodeguid`
   865  func LinkSetVfNodeGUID(link Link, vf int, nodeguid net.HardwareAddr) error {
   866  	return pkgHandle.LinkSetVfGUID(link, vf, nodeguid, nl.IFLA_VF_IB_NODE_GUID)
   867  }
   868  
   869  // LinkSetVfPortGUID sets the port GUID of a vf for the link.
   870  // Equivalent to: `ip link set dev $link vf $vf port_guid $portguid`
   871  func LinkSetVfPortGUID(link Link, vf int, portguid net.HardwareAddr) error {
   872  	return pkgHandle.LinkSetVfGUID(link, vf, portguid, nl.IFLA_VF_IB_PORT_GUID)
   873  }
   874  
   875  // LinkSetVfGUID sets the node or port GUID of a vf for the link.
   876  func (h *Handle) LinkSetVfGUID(link Link, vf int, vfGuid net.HardwareAddr, guidType int) error {
   877  	var err error
   878  	var guid uint64
   879  
   880  	buf := bytes.NewBuffer(vfGuid)
   881  	err = binary.Read(buf, binary.BigEndian, &guid)
   882  	if err != nil {
   883  		return err
   884  	}
   885  
   886  	base := link.Attrs()
   887  	h.ensureIndex(base)
   888  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
   889  
   890  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   891  	msg.Index = int32(base.Index)
   892  	req.AddData(msg)
   893  
   894  	data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
   895  	info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
   896  	vfmsg := nl.VfGUID{
   897  		Vf:   uint32(vf),
   898  		GUID: guid,
   899  	}
   900  	info.AddRtAttr(guidType, vfmsg.Serialize())
   901  	req.AddData(data)
   902  
   903  	_, err = req.Execute(unix.NETLINK_ROUTE, 0)
   904  	return err
   905  }
   906  
   907  // LinkSetMaster sets the master of the link device.
   908  // Equivalent to: `ip link set $link master $master`
   909  func LinkSetMaster(link Link, master Link) error {
   910  	return pkgHandle.LinkSetMaster(link, master)
   911  }
   912  
   913  // LinkSetMaster sets the master of the link device.
   914  // Equivalent to: `ip link set $link master $master`
   915  func (h *Handle) LinkSetMaster(link Link, master Link) error {
   916  	index := 0
   917  	if master != nil {
   918  		masterBase := master.Attrs()
   919  		h.ensureIndex(masterBase)
   920  		index = masterBase.Index
   921  	}
   922  	if index <= 0 {
   923  		return fmt.Errorf("Device does not exist")
   924  	}
   925  	return h.LinkSetMasterByIndex(link, index)
   926  }
   927  
   928  // LinkSetNoMaster removes the master of the link device.
   929  // Equivalent to: `ip link set $link nomaster`
   930  func LinkSetNoMaster(link Link) error {
   931  	return pkgHandle.LinkSetNoMaster(link)
   932  }
   933  
   934  // LinkSetNoMaster removes the master of the link device.
   935  // Equivalent to: `ip link set $link nomaster`
   936  func (h *Handle) LinkSetNoMaster(link Link) error {
   937  	return h.LinkSetMasterByIndex(link, 0)
   938  }
   939  
   940  // LinkSetMasterByIndex sets the master of the link device.
   941  // Equivalent to: `ip link set $link master $master`
   942  func LinkSetMasterByIndex(link Link, masterIndex int) error {
   943  	return pkgHandle.LinkSetMasterByIndex(link, masterIndex)
   944  }
   945  
   946  // LinkSetMasterByIndex sets the master of the link device.
   947  // Equivalent to: `ip link set $link master $master`
   948  func (h *Handle) LinkSetMasterByIndex(link Link, masterIndex int) error {
   949  	base := link.Attrs()
   950  	h.ensureIndex(base)
   951  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
   952  
   953  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   954  	msg.Index = int32(base.Index)
   955  	req.AddData(msg)
   956  
   957  	b := make([]byte, 4)
   958  	native.PutUint32(b, uint32(masterIndex))
   959  
   960  	data := nl.NewRtAttr(unix.IFLA_MASTER, b)
   961  	req.AddData(data)
   962  
   963  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   964  	return err
   965  }
   966  
   967  // LinkSetNsPid puts the device into a new network namespace. The
   968  // pid must be a pid of a running process.
   969  // Equivalent to: `ip link set $link netns $pid`
   970  func LinkSetNsPid(link Link, nspid int) error {
   971  	return pkgHandle.LinkSetNsPid(link, nspid)
   972  }
   973  
   974  // LinkSetNsPid puts the device into a new network namespace. The
   975  // pid must be a pid of a running process.
   976  // Equivalent to: `ip link set $link netns $pid`
   977  func (h *Handle) LinkSetNsPid(link Link, nspid int) error {
   978  	base := link.Attrs()
   979  	h.ensureIndex(base)
   980  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
   981  
   982  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
   983  	msg.Index = int32(base.Index)
   984  	req.AddData(msg)
   985  
   986  	b := make([]byte, 4)
   987  	native.PutUint32(b, uint32(nspid))
   988  
   989  	data := nl.NewRtAttr(unix.IFLA_NET_NS_PID, b)
   990  	req.AddData(data)
   991  
   992  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   993  	return err
   994  }
   995  
   996  // LinkSetNsFd puts the device into a new network namespace. The
   997  // fd must be an open file descriptor to a network namespace.
   998  // Similar to: `ip link set $link netns $ns`
   999  func LinkSetNsFd(link Link, fd int) error {
  1000  	return pkgHandle.LinkSetNsFd(link, fd)
  1001  }
  1002  
  1003  // LinkSetNsFd puts the device into a new network namespace. The
  1004  // fd must be an open file descriptor to a network namespace.
  1005  // Similar to: `ip link set $link netns $ns`
  1006  func (h *Handle) LinkSetNsFd(link Link, fd int) error {
  1007  	base := link.Attrs()
  1008  	h.ensureIndex(base)
  1009  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
  1010  
  1011  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
  1012  	msg.Index = int32(base.Index)
  1013  	req.AddData(msg)
  1014  
  1015  	b := make([]byte, 4)
  1016  	native.PutUint32(b, uint32(fd))
  1017  
  1018  	data := nl.NewRtAttr(unix.IFLA_NET_NS_FD, b)
  1019  	req.AddData(data)
  1020  
  1021  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
  1022  	return err
  1023  }
  1024  
  1025  // LinkSetXdpFd adds a bpf function to the driver. The fd must be a bpf
  1026  // program loaded with bpf(type=BPF_PROG_TYPE_XDP)
  1027  func LinkSetXdpFd(link Link, fd int) error {
  1028  	return LinkSetXdpFdWithFlags(link, fd, 0)
  1029  }
  1030  
  1031  // LinkSetXdpFdWithFlags adds a bpf function to the driver with the given
  1032  // options. The fd must be a bpf program loaded with bpf(type=BPF_PROG_TYPE_XDP)
  1033  func LinkSetXdpFdWithFlags(link Link, fd, flags int) error {
  1034  	base := link.Attrs()
  1035  	ensureIndex(base)
  1036  	req := nl.NewNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
  1037  
  1038  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
  1039  	msg.Index = int32(base.Index)
  1040  	req.AddData(msg)
  1041  
  1042  	addXdpAttrs(&LinkXdp{Fd: fd, Flags: uint32(flags)}, req)
  1043  
  1044  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
  1045  	return err
  1046  }
  1047  
  1048  // LinkSetGSOMaxSegs sets the GSO maximum segment count of the link device.
  1049  // Equivalent to: `ip link set $link gso_max_segs $maxSegs`
  1050  func LinkSetGSOMaxSegs(link Link, maxSegs int) error {
  1051  	return pkgHandle.LinkSetGSOMaxSegs(link, maxSegs)
  1052  }
  1053  
  1054  // LinkSetGSOMaxSegs sets the GSO maximum segment count of the link device.
  1055  // Equivalent to: `ip link set $link gso_max_segs $maxSegs`
  1056  func (h *Handle) LinkSetGSOMaxSegs(link Link, maxSize int) error {
  1057  	base := link.Attrs()
  1058  	h.ensureIndex(base)
  1059  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
  1060  
  1061  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
  1062  	msg.Index = int32(base.Index)
  1063  	req.AddData(msg)
  1064  
  1065  	b := make([]byte, 4)
  1066  	native.PutUint32(b, uint32(maxSize))
  1067  
  1068  	data := nl.NewRtAttr(unix.IFLA_GSO_MAX_SEGS, b)
  1069  	req.AddData(data)
  1070  
  1071  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
  1072  	return err
  1073  }
  1074  
  1075  // LinkSetGSOMaxSize sets the IPv6 GSO maximum size of the link device.
  1076  // Equivalent to: `ip link set $link gso_max_size $maxSize`
  1077  func LinkSetGSOMaxSize(link Link, maxSize int) error {
  1078  	return pkgHandle.LinkSetGSOMaxSize(link, maxSize)
  1079  }
  1080  
  1081  // LinkSetGSOMaxSize sets the IPv6 GSO maximum size of the link device.
  1082  // Equivalent to: `ip link set $link gso_max_size $maxSize`
  1083  func (h *Handle) LinkSetGSOMaxSize(link Link, maxSize int) error {
  1084  	base := link.Attrs()
  1085  	h.ensureIndex(base)
  1086  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
  1087  
  1088  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
  1089  	msg.Index = int32(base.Index)
  1090  	req.AddData(msg)
  1091  
  1092  	b := make([]byte, 4)
  1093  	native.PutUint32(b, uint32(maxSize))
  1094  
  1095  	data := nl.NewRtAttr(unix.IFLA_GSO_MAX_SIZE, b)
  1096  	req.AddData(data)
  1097  
  1098  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
  1099  	return err
  1100  }
  1101  
  1102  // LinkSetGROMaxSize sets the IPv6 GRO maximum size of the link device.
  1103  // Equivalent to: `ip link set $link gro_max_size $maxSize`
  1104  func LinkSetGROMaxSize(link Link, maxSize int) error {
  1105  	return pkgHandle.LinkSetGROMaxSize(link, maxSize)
  1106  }
  1107  
  1108  // LinkSetGROMaxSize sets the IPv6 GRO maximum size of the link device.
  1109  // Equivalent to: `ip link set $link gro_max_size $maxSize`
  1110  func (h *Handle) LinkSetGROMaxSize(link Link, maxSize int) error {
  1111  	base := link.Attrs()
  1112  	h.ensureIndex(base)
  1113  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
  1114  
  1115  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
  1116  	msg.Index = int32(base.Index)
  1117  	req.AddData(msg)
  1118  
  1119  	b := make([]byte, 4)
  1120  	native.PutUint32(b, uint32(maxSize))
  1121  
  1122  	data := nl.NewRtAttr(unix.IFLA_GRO_MAX_SIZE, b)
  1123  	req.AddData(data)
  1124  
  1125  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
  1126  	return err
  1127  }
  1128  
  1129  // LinkSetGSOIPv4MaxSize sets the IPv4 GSO maximum size of the link device.
  1130  // Equivalent to: `ip link set $link gso_ipv4_max_size $maxSize`
  1131  func LinkSetGSOIPv4MaxSize(link Link, maxSize int) error {
  1132  	return pkgHandle.LinkSetGSOIPv4MaxSize(link, maxSize)
  1133  }
  1134  
  1135  // LinkSetGSOIPv4MaxSize sets the IPv4 GSO maximum size of the link device.
  1136  // Equivalent to: `ip link set $link gso_ipv4_max_size $maxSize`
  1137  func (h *Handle) LinkSetGSOIPv4MaxSize(link Link, maxSize int) error {
  1138  	base := link.Attrs()
  1139  	h.ensureIndex(base)
  1140  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
  1141  
  1142  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
  1143  	msg.Index = int32(base.Index)
  1144  	req.AddData(msg)
  1145  
  1146  	b := make([]byte, 4)
  1147  	native.PutUint32(b, uint32(maxSize))
  1148  
  1149  	data := nl.NewRtAttr(unix.IFLA_GSO_IPV4_MAX_SIZE, b)
  1150  	req.AddData(data)
  1151  
  1152  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
  1153  	return err
  1154  }
  1155  
  1156  // LinkSetGROIPv4MaxSize sets the IPv4 GRO maximum size of the link device.
  1157  // Equivalent to: `ip link set $link gro_ipv4_max_size $maxSize`
  1158  func LinkSetGROIPv4MaxSize(link Link, maxSize int) error {
  1159  	return pkgHandle.LinkSetGROIPv4MaxSize(link, maxSize)
  1160  }
  1161  
  1162  // LinkSetGROIPv4MaxSize sets the IPv4 GRO maximum size of the link device.
  1163  // Equivalent to: `ip link set $link gro_ipv4_max_size $maxSize`
  1164  func (h *Handle) LinkSetGROIPv4MaxSize(link Link, maxSize int) error {
  1165  	base := link.Attrs()
  1166  	h.ensureIndex(base)
  1167  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
  1168  
  1169  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
  1170  	msg.Index = int32(base.Index)
  1171  	req.AddData(msg)
  1172  
  1173  	b := make([]byte, 4)
  1174  	native.PutUint32(b, uint32(maxSize))
  1175  
  1176  	data := nl.NewRtAttr(unix.IFLA_GRO_IPV4_MAX_SIZE, b)
  1177  	req.AddData(data)
  1178  
  1179  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
  1180  	return err
  1181  }
  1182  
  1183  func boolAttr(val bool) []byte {
  1184  	var v uint8
  1185  	if val {
  1186  		v = 1
  1187  	}
  1188  	return nl.Uint8Attr(v)
  1189  }
  1190  
  1191  type vxlanPortRange struct {
  1192  	Lo, Hi uint16
  1193  }
  1194  
  1195  func addVxlanAttrs(vxlan *Vxlan, linkInfo *nl.RtAttr) {
  1196  	data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
  1197  
  1198  	if vxlan.FlowBased {
  1199  		vxlan.VxlanId = 0
  1200  	}
  1201  
  1202  	data.AddRtAttr(nl.IFLA_VXLAN_ID, nl.Uint32Attr(uint32(vxlan.VxlanId)))
  1203  
  1204  	if vxlan.VtepDevIndex != 0 {
  1205  		data.AddRtAttr(nl.IFLA_VXLAN_LINK, nl.Uint32Attr(uint32(vxlan.VtepDevIndex)))
  1206  	}
  1207  	if vxlan.SrcAddr != nil {
  1208  		ip := vxlan.SrcAddr.To4()
  1209  		if ip != nil {
  1210  			data.AddRtAttr(nl.IFLA_VXLAN_LOCAL, []byte(ip))
  1211  		} else {
  1212  			ip = vxlan.SrcAddr.To16()
  1213  			if ip != nil {
  1214  				data.AddRtAttr(nl.IFLA_VXLAN_LOCAL6, []byte(ip))
  1215  			}
  1216  		}
  1217  	}
  1218  	if vxlan.Group != nil {
  1219  		group := vxlan.Group.To4()
  1220  		if group != nil {
  1221  			data.AddRtAttr(nl.IFLA_VXLAN_GROUP, []byte(group))
  1222  		} else {
  1223  			group = vxlan.Group.To16()
  1224  			if group != nil {
  1225  				data.AddRtAttr(nl.IFLA_VXLAN_GROUP6, []byte(group))
  1226  			}
  1227  		}
  1228  	}
  1229  
  1230  	data.AddRtAttr(nl.IFLA_VXLAN_TTL, nl.Uint8Attr(uint8(vxlan.TTL)))
  1231  	data.AddRtAttr(nl.IFLA_VXLAN_TOS, nl.Uint8Attr(uint8(vxlan.TOS)))
  1232  	data.AddRtAttr(nl.IFLA_VXLAN_LEARNING, boolAttr(vxlan.Learning))
  1233  	data.AddRtAttr(nl.IFLA_VXLAN_PROXY, boolAttr(vxlan.Proxy))
  1234  	data.AddRtAttr(nl.IFLA_VXLAN_RSC, boolAttr(vxlan.RSC))
  1235  	data.AddRtAttr(nl.IFLA_VXLAN_L2MISS, boolAttr(vxlan.L2miss))
  1236  	data.AddRtAttr(nl.IFLA_VXLAN_L3MISS, boolAttr(vxlan.L3miss))
  1237  	data.AddRtAttr(nl.IFLA_VXLAN_UDP_ZERO_CSUM6_TX, boolAttr(vxlan.UDP6ZeroCSumTx))
  1238  	data.AddRtAttr(nl.IFLA_VXLAN_UDP_ZERO_CSUM6_RX, boolAttr(vxlan.UDP6ZeroCSumRx))
  1239  
  1240  	if vxlan.UDPCSum {
  1241  		data.AddRtAttr(nl.IFLA_VXLAN_UDP_CSUM, boolAttr(vxlan.UDPCSum))
  1242  	}
  1243  	if vxlan.GBP {
  1244  		data.AddRtAttr(nl.IFLA_VXLAN_GBP, []byte{})
  1245  	}
  1246  	if vxlan.FlowBased {
  1247  		data.AddRtAttr(nl.IFLA_VXLAN_FLOWBASED, boolAttr(vxlan.FlowBased))
  1248  	}
  1249  	if vxlan.NoAge {
  1250  		data.AddRtAttr(nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(0))
  1251  	} else if vxlan.Age > 0 {
  1252  		data.AddRtAttr(nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(uint32(vxlan.Age)))
  1253  	}
  1254  	if vxlan.Limit > 0 {
  1255  		data.AddRtAttr(nl.IFLA_VXLAN_LIMIT, nl.Uint32Attr(uint32(vxlan.Limit)))
  1256  	}
  1257  	if vxlan.Port > 0 {
  1258  		data.AddRtAttr(nl.IFLA_VXLAN_PORT, htons(uint16(vxlan.Port)))
  1259  	}
  1260  	if vxlan.PortLow > 0 || vxlan.PortHigh > 0 {
  1261  		pr := vxlanPortRange{uint16(vxlan.PortLow), uint16(vxlan.PortHigh)}
  1262  
  1263  		buf := new(bytes.Buffer)
  1264  		binary.Write(buf, binary.BigEndian, &pr)
  1265  
  1266  		data.AddRtAttr(nl.IFLA_VXLAN_PORT_RANGE, buf.Bytes())
  1267  	}
  1268  }
  1269  
  1270  func addBondAttrs(bond *Bond, linkInfo *nl.RtAttr) {
  1271  	data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
  1272  	if bond.Mode >= 0 {
  1273  		data.AddRtAttr(nl.IFLA_BOND_MODE, nl.Uint8Attr(uint8(bond.Mode)))
  1274  	}
  1275  	if bond.ActiveSlave >= 0 {
  1276  		data.AddRtAttr(nl.IFLA_BOND_ACTIVE_SLAVE, nl.Uint32Attr(uint32(bond.ActiveSlave)))
  1277  	}
  1278  	if bond.Miimon >= 0 {
  1279  		data.AddRtAttr(nl.IFLA_BOND_MIIMON, nl.Uint32Attr(uint32(bond.Miimon)))
  1280  	}
  1281  	if bond.UpDelay >= 0 {
  1282  		data.AddRtAttr(nl.IFLA_BOND_UPDELAY, nl.Uint32Attr(uint32(bond.UpDelay)))
  1283  	}
  1284  	if bond.DownDelay >= 0 {
  1285  		data.AddRtAttr(nl.IFLA_BOND_DOWNDELAY, nl.Uint32Attr(uint32(bond.DownDelay)))
  1286  	}
  1287  	if bond.UseCarrier >= 0 {
  1288  		data.AddRtAttr(nl.IFLA_BOND_USE_CARRIER, nl.Uint8Attr(uint8(bond.UseCarrier)))
  1289  	}
  1290  	if bond.ArpInterval >= 0 {
  1291  		data.AddRtAttr(nl.IFLA_BOND_ARP_INTERVAL, nl.Uint32Attr(uint32(bond.ArpInterval)))
  1292  	}
  1293  	if bond.ArpIpTargets != nil {
  1294  		msg := data.AddRtAttr(nl.IFLA_BOND_ARP_IP_TARGET, nil)
  1295  		for i := range bond.ArpIpTargets {
  1296  			ip := bond.ArpIpTargets[i].To4()
  1297  			if ip != nil {
  1298  				msg.AddRtAttr(i, []byte(ip))
  1299  				continue
  1300  			}
  1301  			ip = bond.ArpIpTargets[i].To16()
  1302  			if ip != nil {
  1303  				msg.AddRtAttr(i, []byte(ip))
  1304  			}
  1305  		}
  1306  	}
  1307  	if bond.ArpValidate >= 0 {
  1308  		data.AddRtAttr(nl.IFLA_BOND_ARP_VALIDATE, nl.Uint32Attr(uint32(bond.ArpValidate)))
  1309  	}
  1310  	if bond.ArpAllTargets >= 0 {
  1311  		data.AddRtAttr(nl.IFLA_BOND_ARP_ALL_TARGETS, nl.Uint32Attr(uint32(bond.ArpAllTargets)))
  1312  	}
  1313  	if bond.Primary >= 0 {
  1314  		data.AddRtAttr(nl.IFLA_BOND_PRIMARY, nl.Uint32Attr(uint32(bond.Primary)))
  1315  	}
  1316  	if bond.PrimaryReselect >= 0 {
  1317  		data.AddRtAttr(nl.IFLA_BOND_PRIMARY_RESELECT, nl.Uint8Attr(uint8(bond.PrimaryReselect)))
  1318  	}
  1319  	if bond.FailOverMac >= 0 {
  1320  		data.AddRtAttr(nl.IFLA_BOND_FAIL_OVER_MAC, nl.Uint8Attr(uint8(bond.FailOverMac)))
  1321  	}
  1322  	if bond.XmitHashPolicy >= 0 {
  1323  		data.AddRtAttr(nl.IFLA_BOND_XMIT_HASH_POLICY, nl.Uint8Attr(uint8(bond.XmitHashPolicy)))
  1324  	}
  1325  	if bond.ResendIgmp >= 0 {
  1326  		data.AddRtAttr(nl.IFLA_BOND_RESEND_IGMP, nl.Uint32Attr(uint32(bond.ResendIgmp)))
  1327  	}
  1328  	if bond.NumPeerNotif >= 0 {
  1329  		data.AddRtAttr(nl.IFLA_BOND_NUM_PEER_NOTIF, nl.Uint8Attr(uint8(bond.NumPeerNotif)))
  1330  	}
  1331  	if bond.AllSlavesActive >= 0 {
  1332  		data.AddRtAttr(nl.IFLA_BOND_ALL_SLAVES_ACTIVE, nl.Uint8Attr(uint8(bond.AllSlavesActive)))
  1333  	}
  1334  	if bond.MinLinks >= 0 {
  1335  		data.AddRtAttr(nl.IFLA_BOND_MIN_LINKS, nl.Uint32Attr(uint32(bond.MinLinks)))
  1336  	}
  1337  	if bond.LpInterval >= 0 {
  1338  		data.AddRtAttr(nl.IFLA_BOND_LP_INTERVAL, nl.Uint32Attr(uint32(bond.LpInterval)))
  1339  	}
  1340  	if bond.PacketsPerSlave >= 0 {
  1341  		data.AddRtAttr(nl.IFLA_BOND_PACKETS_PER_SLAVE, nl.Uint32Attr(uint32(bond.PacketsPerSlave)))
  1342  	}
  1343  	if bond.LacpRate >= 0 {
  1344  		data.AddRtAttr(nl.IFLA_BOND_AD_LACP_RATE, nl.Uint8Attr(uint8(bond.LacpRate)))
  1345  	}
  1346  	if bond.AdSelect >= 0 {
  1347  		data.AddRtAttr(nl.IFLA_BOND_AD_SELECT, nl.Uint8Attr(uint8(bond.AdSelect)))
  1348  	}
  1349  	if bond.AdActorSysPrio >= 0 {
  1350  		data.AddRtAttr(nl.IFLA_BOND_AD_ACTOR_SYS_PRIO, nl.Uint16Attr(uint16(bond.AdActorSysPrio)))
  1351  	}
  1352  	if bond.AdUserPortKey >= 0 {
  1353  		data.AddRtAttr(nl.IFLA_BOND_AD_USER_PORT_KEY, nl.Uint16Attr(uint16(bond.AdUserPortKey)))
  1354  	}
  1355  	if bond.AdActorSystem != nil {
  1356  		data.AddRtAttr(nl.IFLA_BOND_AD_ACTOR_SYSTEM, []byte(bond.AdActorSystem))
  1357  	}
  1358  	if bond.TlbDynamicLb >= 0 {
  1359  		data.AddRtAttr(nl.IFLA_BOND_TLB_DYNAMIC_LB, nl.Uint8Attr(uint8(bond.TlbDynamicLb)))
  1360  	}
  1361  }
  1362  
  1363  func cleanupFds(fds []*os.File) {
  1364  	for _, f := range fds {
  1365  		f.Close()
  1366  	}
  1367  }
  1368  
  1369  // LinkAdd adds a new link device. The type and features of the device
  1370  // are taken from the parameters in the link object.
  1371  // Equivalent to: `ip link add $link`
  1372  func LinkAdd(link Link) error {
  1373  	return pkgHandle.LinkAdd(link)
  1374  }
  1375  
  1376  // LinkAdd adds a new link device. The type and features of the device
  1377  // are taken from the parameters in the link object.
  1378  // Equivalent to: `ip link add $link`
  1379  func (h *Handle) LinkAdd(link Link) error {
  1380  	return h.linkModify(link, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
  1381  }
  1382  
  1383  func LinkModify(link Link) error {
  1384  	return pkgHandle.LinkModify(link)
  1385  }
  1386  
  1387  func (h *Handle) LinkModify(link Link) error {
  1388  	return h.linkModify(link, unix.NLM_F_REQUEST|unix.NLM_F_ACK)
  1389  }
  1390  
  1391  func (h *Handle) linkModify(link Link, flags int) error {
  1392  	// TODO: support extra data for macvlan
  1393  	base := link.Attrs()
  1394  
  1395  	// if tuntap, then the name can be empty, OS will provide a name
  1396  	tuntap, isTuntap := link.(*Tuntap)
  1397  
  1398  	if base.Name == "" && !isTuntap {
  1399  		return fmt.Errorf("LinkAttrs.Name cannot be empty")
  1400  	}
  1401  
  1402  	if isTuntap {
  1403  		if tuntap.Mode < unix.IFF_TUN || tuntap.Mode > unix.IFF_TAP {
  1404  			return fmt.Errorf("Tuntap.Mode %v unknown", tuntap.Mode)
  1405  		}
  1406  
  1407  		queues := tuntap.Queues
  1408  
  1409  		var fds []*os.File
  1410  		var req ifReq
  1411  		copy(req.Name[:15], base.Name)
  1412  
  1413  		req.Flags = uint16(tuntap.Flags)
  1414  
  1415  		if queues == 0 { //Legacy compatibility
  1416  			queues = 1
  1417  			if tuntap.Flags == 0 {
  1418  				req.Flags = uint16(TUNTAP_DEFAULTS)
  1419  			}
  1420  		} else {
  1421  			// For best peformance set Flags to TUNTAP_MULTI_QUEUE_DEFAULTS | TUNTAP_VNET_HDR
  1422  			// when a) KVM has support for this ABI and
  1423  			//      b) the value of the flag is queryable using the TUNGETIFF ioctl
  1424  			if tuntap.Flags == 0 {
  1425  				req.Flags = uint16(TUNTAP_MULTI_QUEUE_DEFAULTS)
  1426  			}
  1427  		}
  1428  
  1429  		req.Flags |= uint16(tuntap.Mode)
  1430  		const TUN = "/dev/net/tun"
  1431  		for i := 0; i < queues; i++ {
  1432  			localReq := req
  1433  			fd, err := unix.Open(TUN, os.O_RDWR|syscall.O_CLOEXEC, 0)
  1434  			if err != nil {
  1435  				cleanupFds(fds)
  1436  				return err
  1437  			}
  1438  
  1439  			_, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), uintptr(unix.TUNSETIFF), uintptr(unsafe.Pointer(&localReq)))
  1440  			if errno != 0 {
  1441  				// close the new fd
  1442  				unix.Close(fd)
  1443  				// and the already opened ones
  1444  				cleanupFds(fds)
  1445  				return fmt.Errorf("Tuntap IOCTL TUNSETIFF failed [%d], errno %v", i, errno)
  1446  			}
  1447  
  1448  			_, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.TUNSETOWNER, uintptr(tuntap.Owner))
  1449  			if errno != 0 {
  1450  				cleanupFds(fds)
  1451  				return fmt.Errorf("Tuntap IOCTL TUNSETOWNER failed [%d], errno %v", i, errno)
  1452  			}
  1453  
  1454  			_, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.TUNSETGROUP, uintptr(tuntap.Group))
  1455  			if errno != 0 {
  1456  				cleanupFds(fds)
  1457  				return fmt.Errorf("Tuntap IOCTL TUNSETGROUP failed [%d], errno %v", i, errno)
  1458  			}
  1459  
  1460  			// Set the tun device to non-blocking before use. The below comment
  1461  			// taken from:
  1462  			//
  1463  			// https://github.com/mistsys/tuntap/commit/161418c25003bbee77d085a34af64d189df62bea
  1464  			//
  1465  			// Note there is a complication because in go, if a device node is
  1466  			// opened, go sets it to use nonblocking I/O. However a /dev/net/tun
  1467  			// doesn't work with epoll until after the TUNSETIFF ioctl has been
  1468  			// done. So we open the unix fd directly, do the ioctl, then put the
  1469  			// fd in nonblocking mode, an then finally wrap it in a os.File,
  1470  			// which will see the nonblocking mode and add the fd to the
  1471  			// pollable set, so later on when we Read() from it blocked the
  1472  			// calling thread in the kernel.
  1473  			//
  1474  			// See
  1475  			//   https://github.com/golang/go/issues/30426
  1476  			// which got exposed in go 1.13 by the fix to
  1477  			//   https://github.com/golang/go/issues/30624
  1478  			err = unix.SetNonblock(fd, true)
  1479  			if err != nil {
  1480  				cleanupFds(fds)
  1481  				return fmt.Errorf("Tuntap set to non-blocking failed [%d], err %v", i, err)
  1482  			}
  1483  
  1484  			// create the file from the file descriptor and store it
  1485  			file := os.NewFile(uintptr(fd), TUN)
  1486  			fds = append(fds, file)
  1487  
  1488  			// 1) we only care for the name of the first tap in the multi queue set
  1489  			// 2) if the original name was empty, the localReq has now the actual name
  1490  			//
  1491  			// In addition:
  1492  			// This ensures that the link name is always identical to what the kernel returns.
  1493  			// Not only in case of an empty name, but also when using name templates.
  1494  			// e.g. when the provided name is "tap%d", the kernel replaces %d with the next available number.
  1495  			if i == 0 {
  1496  				link.Attrs().Name = strings.Trim(string(localReq.Name[:]), "\x00")
  1497  			}
  1498  
  1499  		}
  1500  
  1501  		control := func(file *os.File, f func(fd uintptr)) error {
  1502  			name := file.Name()
  1503  			conn, err := file.SyscallConn()
  1504  			if err != nil {
  1505  				return fmt.Errorf("SyscallConn() failed on %s: %v", name, err)
  1506  			}
  1507  			if err := conn.Control(f); err != nil {
  1508  				return fmt.Errorf("Failed to get file descriptor for %s: %v", name, err)
  1509  			}
  1510  			return nil
  1511  		}
  1512  
  1513  		// only persist interface if NonPersist is NOT set
  1514  		if !tuntap.NonPersist {
  1515  			var errno syscall.Errno
  1516  			if err := control(fds[0], func(fd uintptr) {
  1517  				_, _, errno = unix.Syscall(unix.SYS_IOCTL, fd, uintptr(unix.TUNSETPERSIST), 1)
  1518  			}); err != nil {
  1519  				return err
  1520  			}
  1521  			if errno != 0 {
  1522  				cleanupFds(fds)
  1523  				return fmt.Errorf("Tuntap IOCTL TUNSETPERSIST failed, errno %v", errno)
  1524  			}
  1525  		}
  1526  
  1527  		h.ensureIndex(base)
  1528  
  1529  		// can't set master during create, so set it afterwards
  1530  		if base.MasterIndex != 0 {
  1531  			// TODO: verify MasterIndex is actually a bridge?
  1532  			err := h.LinkSetMasterByIndex(link, base.MasterIndex)
  1533  			if err != nil {
  1534  				// un-persist (e.g. allow the interface to be removed) the tuntap
  1535  				// should not hurt if not set prior, condition might be not needed
  1536  				if !tuntap.NonPersist {
  1537  					// ignore error
  1538  					_ = control(fds[0], func(fd uintptr) {
  1539  						_, _, _ = unix.Syscall(unix.SYS_IOCTL, fd, uintptr(unix.TUNSETPERSIST), 0)
  1540  					})
  1541  				}
  1542  				cleanupFds(fds)
  1543  				return err
  1544  			}
  1545  		}
  1546  
  1547  		if tuntap.Queues == 0 {
  1548  			cleanupFds(fds)
  1549  		} else {
  1550  			tuntap.Fds = fds
  1551  		}
  1552  
  1553  		return nil
  1554  	}
  1555  
  1556  	req := h.newNetlinkRequest(unix.RTM_NEWLINK, flags)
  1557  
  1558  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
  1559  	// TODO: make it shorter
  1560  	if base.Flags&net.FlagUp != 0 {
  1561  		msg.Change = unix.IFF_UP
  1562  		msg.Flags = unix.IFF_UP
  1563  	}
  1564  	if base.Flags&net.FlagBroadcast != 0 {
  1565  		msg.Change |= unix.IFF_BROADCAST
  1566  		msg.Flags |= unix.IFF_BROADCAST
  1567  	}
  1568  	if base.Flags&net.FlagLoopback != 0 {
  1569  		msg.Change |= unix.IFF_LOOPBACK
  1570  		msg.Flags |= unix.IFF_LOOPBACK
  1571  	}
  1572  	if base.Flags&net.FlagPointToPoint != 0 {
  1573  		msg.Change |= unix.IFF_POINTOPOINT
  1574  		msg.Flags |= unix.IFF_POINTOPOINT
  1575  	}
  1576  	if base.Flags&net.FlagMulticast != 0 {
  1577  		msg.Change |= unix.IFF_MULTICAST
  1578  		msg.Flags |= unix.IFF_MULTICAST
  1579  	}
  1580  	if base.Index != 0 {
  1581  		msg.Index = int32(base.Index)
  1582  	}
  1583  
  1584  	req.AddData(msg)
  1585  
  1586  	if base.ParentIndex != 0 {
  1587  		b := make([]byte, 4)
  1588  		native.PutUint32(b, uint32(base.ParentIndex))
  1589  		data := nl.NewRtAttr(unix.IFLA_LINK, b)
  1590  		req.AddData(data)
  1591  	} else if link.Type() == "ipvlan" || link.Type() == "ipoib" {
  1592  		return fmt.Errorf("Can't create %s link without ParentIndex", link.Type())
  1593  	}
  1594  
  1595  	nameData := nl.NewRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(base.Name))
  1596  	req.AddData(nameData)
  1597  
  1598  	if base.Alias != "" {
  1599  		alias := nl.NewRtAttr(unix.IFLA_IFALIAS, []byte(base.Alias))
  1600  		req.AddData(alias)
  1601  	}
  1602  
  1603  	if base.MTU > 0 {
  1604  		mtu := nl.NewRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU)))
  1605  		req.AddData(mtu)
  1606  	}
  1607  
  1608  	if base.TxQLen >= 0 {
  1609  		qlen := nl.NewRtAttr(unix.IFLA_TXQLEN, nl.Uint32Attr(uint32(base.TxQLen)))
  1610  		req.AddData(qlen)
  1611  	}
  1612  
  1613  	if base.HardwareAddr != nil {
  1614  		hwaddr := nl.NewRtAttr(unix.IFLA_ADDRESS, []byte(base.HardwareAddr))
  1615  		req.AddData(hwaddr)
  1616  	}
  1617  
  1618  	if base.NumTxQueues > 0 {
  1619  		txqueues := nl.NewRtAttr(unix.IFLA_NUM_TX_QUEUES, nl.Uint32Attr(uint32(base.NumTxQueues)))
  1620  		req.AddData(txqueues)
  1621  	}
  1622  
  1623  	if base.NumRxQueues > 0 {
  1624  		rxqueues := nl.NewRtAttr(unix.IFLA_NUM_RX_QUEUES, nl.Uint32Attr(uint32(base.NumRxQueues)))
  1625  		req.AddData(rxqueues)
  1626  	}
  1627  
  1628  	if base.GSOMaxSegs > 0 {
  1629  		gsoAttr := nl.NewRtAttr(unix.IFLA_GSO_MAX_SEGS, nl.Uint32Attr(base.GSOMaxSegs))
  1630  		req.AddData(gsoAttr)
  1631  	}
  1632  
  1633  	if base.GSOMaxSize > 0 {
  1634  		gsoAttr := nl.NewRtAttr(unix.IFLA_GSO_MAX_SIZE, nl.Uint32Attr(base.GSOMaxSize))
  1635  		req.AddData(gsoAttr)
  1636  	}
  1637  
  1638  	if base.GROMaxSize > 0 {
  1639  		groAttr := nl.NewRtAttr(unix.IFLA_GRO_MAX_SIZE, nl.Uint32Attr(base.GROMaxSize))
  1640  		req.AddData(groAttr)
  1641  	}
  1642  
  1643  	if base.GSOIPv4MaxSize > 0 {
  1644  		gsoAttr := nl.NewRtAttr(unix.IFLA_GSO_IPV4_MAX_SIZE, nl.Uint32Attr(base.GSOIPv4MaxSize))
  1645  		req.AddData(gsoAttr)
  1646  	}
  1647  
  1648  	if base.GROIPv4MaxSize > 0 {
  1649  		groAttr := nl.NewRtAttr(unix.IFLA_GRO_IPV4_MAX_SIZE, nl.Uint32Attr(base.GROIPv4MaxSize))
  1650  		req.AddData(groAttr)
  1651  	}
  1652  
  1653  	if base.Group > 0 {
  1654  		groupAttr := nl.NewRtAttr(unix.IFLA_GROUP, nl.Uint32Attr(base.Group))
  1655  		req.AddData(groupAttr)
  1656  	}
  1657  
  1658  	if base.Namespace != nil {
  1659  		var attr *nl.RtAttr
  1660  		switch ns := base.Namespace.(type) {
  1661  		case NsPid:
  1662  			val := nl.Uint32Attr(uint32(ns))
  1663  			attr = nl.NewRtAttr(unix.IFLA_NET_NS_PID, val)
  1664  		case NsFd:
  1665  			val := nl.Uint32Attr(uint32(ns))
  1666  			attr = nl.NewRtAttr(unix.IFLA_NET_NS_FD, val)
  1667  		}
  1668  
  1669  		req.AddData(attr)
  1670  	}
  1671  
  1672  	if base.Xdp != nil {
  1673  		addXdpAttrs(base.Xdp, req)
  1674  	}
  1675  
  1676  	linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil)
  1677  	linkInfo.AddRtAttr(nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type()))
  1678  
  1679  	switch link := link.(type) {
  1680  	case *Vlan:
  1681  		b := make([]byte, 2)
  1682  		native.PutUint16(b, uint16(link.VlanId))
  1683  		data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
  1684  		data.AddRtAttr(nl.IFLA_VLAN_ID, b)
  1685  
  1686  		if link.VlanProtocol != VLAN_PROTOCOL_UNKNOWN {
  1687  			data.AddRtAttr(nl.IFLA_VLAN_PROTOCOL, htons(uint16(link.VlanProtocol)))
  1688  		}
  1689  	case *Netkit:
  1690  		if err := addNetkitAttrs(link, linkInfo, flags); err != nil {
  1691  			return err
  1692  		}
  1693  	case *Veth:
  1694  		data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
  1695  		peer := data.AddRtAttr(nl.VETH_INFO_PEER, nil)
  1696  		nl.NewIfInfomsgChild(peer, unix.AF_UNSPEC)
  1697  		peer.AddRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(link.PeerName))
  1698  		if base.TxQLen >= 0 {
  1699  			peer.AddRtAttr(unix.IFLA_TXQLEN, nl.Uint32Attr(uint32(base.TxQLen)))
  1700  		}
  1701  		if base.NumTxQueues > 0 {
  1702  			peer.AddRtAttr(unix.IFLA_NUM_TX_QUEUES, nl.Uint32Attr(uint32(base.NumTxQueues)))
  1703  		}
  1704  		if base.NumRxQueues > 0 {
  1705  			peer.AddRtAttr(unix.IFLA_NUM_RX_QUEUES, nl.Uint32Attr(uint32(base.NumRxQueues)))
  1706  		}
  1707  		if base.MTU > 0 {
  1708  			peer.AddRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU)))
  1709  		}
  1710  		if link.PeerHardwareAddr != nil {
  1711  			peer.AddRtAttr(unix.IFLA_ADDRESS, []byte(link.PeerHardwareAddr))
  1712  		}
  1713  		if link.PeerNamespace != nil {
  1714  			switch ns := link.PeerNamespace.(type) {
  1715  			case NsPid:
  1716  				val := nl.Uint32Attr(uint32(ns))
  1717  				peer.AddRtAttr(unix.IFLA_NET_NS_PID, val)
  1718  			case NsFd:
  1719  				val := nl.Uint32Attr(uint32(ns))
  1720  				peer.AddRtAttr(unix.IFLA_NET_NS_FD, val)
  1721  			}
  1722  		}
  1723  	case *Vxlan:
  1724  		addVxlanAttrs(link, linkInfo)
  1725  	case *Bond:
  1726  		addBondAttrs(link, linkInfo)
  1727  	case *IPVlan:
  1728  		data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
  1729  		data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode)))
  1730  		data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag)))
  1731  	case *IPVtap:
  1732  		data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
  1733  		data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode)))
  1734  		data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag)))
  1735  	case *Macvlan:
  1736  		addMacvlanAttrs(link, linkInfo)
  1737  	case *Macvtap:
  1738  		addMacvtapAttrs(link, linkInfo)
  1739  	case *Geneve:
  1740  		addGeneveAttrs(link, linkInfo)
  1741  	case *Gretap:
  1742  		addGretapAttrs(link, linkInfo)
  1743  	case *Iptun:
  1744  		addIptunAttrs(link, linkInfo)
  1745  	case *Ip6tnl:
  1746  		addIp6tnlAttrs(link, linkInfo)
  1747  	case *Sittun:
  1748  		addSittunAttrs(link, linkInfo)
  1749  	case *Gretun:
  1750  		addGretunAttrs(link, linkInfo)
  1751  	case *Vti:
  1752  		addVtiAttrs(link, linkInfo)
  1753  	case *Vrf:
  1754  		addVrfAttrs(link, linkInfo)
  1755  	case *Bridge:
  1756  		addBridgeAttrs(link, linkInfo)
  1757  	case *GTP:
  1758  		addGTPAttrs(link, linkInfo)
  1759  	case *Xfrmi:
  1760  		addXfrmiAttrs(link, linkInfo)
  1761  	case *IPoIB:
  1762  		addIPoIBAttrs(link, linkInfo)
  1763  	case *BareUDP:
  1764  		addBareUDPAttrs(link, linkInfo)
  1765  	}
  1766  
  1767  	req.AddData(linkInfo)
  1768  
  1769  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
  1770  	if err != nil {
  1771  		return err
  1772  	}
  1773  
  1774  	h.ensureIndex(base)
  1775  
  1776  	// can't set master during create, so set it afterwards
  1777  	if base.MasterIndex != 0 {
  1778  		// TODO: verify MasterIndex is actually a bridge?
  1779  		return h.LinkSetMasterByIndex(link, base.MasterIndex)
  1780  	}
  1781  	return nil
  1782  }
  1783  
  1784  // LinkDel deletes link device. Either Index or Name must be set in
  1785  // the link object for it to be deleted. The other values are ignored.
  1786  // Equivalent to: `ip link del $link`
  1787  func LinkDel(link Link) error {
  1788  	return pkgHandle.LinkDel(link)
  1789  }
  1790  
  1791  // LinkDel deletes link device. Either Index or Name must be set in
  1792  // the link object for it to be deleted. The other values are ignored.
  1793  // Equivalent to: `ip link del $link`
  1794  func (h *Handle) LinkDel(link Link) error {
  1795  	base := link.Attrs()
  1796  
  1797  	h.ensureIndex(base)
  1798  
  1799  	req := h.newNetlinkRequest(unix.RTM_DELLINK, unix.NLM_F_ACK)
  1800  
  1801  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
  1802  	msg.Index = int32(base.Index)
  1803  	req.AddData(msg)
  1804  
  1805  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
  1806  	return err
  1807  }
  1808  
  1809  func (h *Handle) linkByNameDump(name string) (Link, error) {
  1810  	links, err := h.LinkList()
  1811  	if err != nil {
  1812  		return nil, err
  1813  	}
  1814  
  1815  	for _, link := range links {
  1816  		if link.Attrs().Name == name {
  1817  			return link, nil
  1818  		}
  1819  
  1820  		// support finding interfaces also via altnames
  1821  		for _, altName := range link.Attrs().AltNames {
  1822  			if altName == name {
  1823  				return link, nil
  1824  			}
  1825  		}
  1826  	}
  1827  	return nil, LinkNotFoundError{fmt.Errorf("Link %s not found", name)}
  1828  }
  1829  
  1830  func (h *Handle) linkByAliasDump(alias string) (Link, error) {
  1831  	links, err := h.LinkList()
  1832  	if err != nil {
  1833  		return nil, err
  1834  	}
  1835  
  1836  	for _, link := range links {
  1837  		if link.Attrs().Alias == alias {
  1838  			return link, nil
  1839  		}
  1840  	}
  1841  	return nil, LinkNotFoundError{fmt.Errorf("Link alias %s not found", alias)}
  1842  }
  1843  
  1844  // LinkByName finds a link by name and returns a pointer to the object.
  1845  func LinkByName(name string) (Link, error) {
  1846  	return pkgHandle.LinkByName(name)
  1847  }
  1848  
  1849  // LinkByName finds a link by name and returns a pointer to the object.
  1850  func (h *Handle) LinkByName(name string) (Link, error) {
  1851  	if h.lookupByDump {
  1852  		return h.linkByNameDump(name)
  1853  	}
  1854  
  1855  	req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_ACK)
  1856  
  1857  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
  1858  	req.AddData(msg)
  1859  
  1860  	attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF))
  1861  	req.AddData(attr)
  1862  
  1863  	nameData := nl.NewRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(name))
  1864  	if len(name) > 15 {
  1865  		nameData = nl.NewRtAttr(unix.IFLA_ALT_IFNAME, nl.ZeroTerminated(name))
  1866  	}
  1867  	req.AddData(nameData)
  1868  
  1869  	link, err := execGetLink(req)
  1870  	if err == unix.EINVAL {
  1871  		// older kernels don't support looking up via IFLA_IFNAME
  1872  		// so fall back to dumping all links
  1873  		h.lookupByDump = true
  1874  		return h.linkByNameDump(name)
  1875  	}
  1876  
  1877  	return link, err
  1878  }
  1879  
  1880  // LinkByAlias finds a link by its alias and returns a pointer to the object.
  1881  // If there are multiple links with the alias it returns the first one
  1882  func LinkByAlias(alias string) (Link, error) {
  1883  	return pkgHandle.LinkByAlias(alias)
  1884  }
  1885  
  1886  // LinkByAlias finds a link by its alias and returns a pointer to the object.
  1887  // If there are multiple links with the alias it returns the first one
  1888  func (h *Handle) LinkByAlias(alias string) (Link, error) {
  1889  	if h.lookupByDump {
  1890  		return h.linkByAliasDump(alias)
  1891  	}
  1892  
  1893  	req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_ACK)
  1894  
  1895  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
  1896  	req.AddData(msg)
  1897  
  1898  	attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF))
  1899  	req.AddData(attr)
  1900  
  1901  	nameData := nl.NewRtAttr(unix.IFLA_IFALIAS, nl.ZeroTerminated(alias))
  1902  	req.AddData(nameData)
  1903  
  1904  	link, err := execGetLink(req)
  1905  	if err == unix.EINVAL {
  1906  		// older kernels don't support looking up via IFLA_IFALIAS
  1907  		// so fall back to dumping all links
  1908  		h.lookupByDump = true
  1909  		return h.linkByAliasDump(alias)
  1910  	}
  1911  
  1912  	return link, err
  1913  }
  1914  
  1915  // LinkByIndex finds a link by index and returns a pointer to the object.
  1916  func LinkByIndex(index int) (Link, error) {
  1917  	return pkgHandle.LinkByIndex(index)
  1918  }
  1919  
  1920  // LinkByIndex finds a link by index and returns a pointer to the object.
  1921  func (h *Handle) LinkByIndex(index int) (Link, error) {
  1922  	req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_ACK)
  1923  
  1924  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
  1925  	msg.Index = int32(index)
  1926  	req.AddData(msg)
  1927  	attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF))
  1928  	req.AddData(attr)
  1929  
  1930  	return execGetLink(req)
  1931  }
  1932  
  1933  func execGetLink(req *nl.NetlinkRequest) (Link, error) {
  1934  	msgs, err := req.Execute(unix.NETLINK_ROUTE, 0)
  1935  	if err != nil {
  1936  		if errno, ok := err.(syscall.Errno); ok {
  1937  			if errno == unix.ENODEV {
  1938  				return nil, LinkNotFoundError{fmt.Errorf("Link not found")}
  1939  			}
  1940  		}
  1941  		return nil, err
  1942  	}
  1943  
  1944  	switch {
  1945  	case len(msgs) == 0:
  1946  		return nil, LinkNotFoundError{fmt.Errorf("Link not found")}
  1947  
  1948  	case len(msgs) == 1:
  1949  		return LinkDeserialize(nil, msgs[0])
  1950  
  1951  	default:
  1952  		return nil, fmt.Errorf("More than one link found")
  1953  	}
  1954  }
  1955  
  1956  // LinkDeserialize deserializes a raw message received from netlink into
  1957  // a link object.
  1958  func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
  1959  	msg := nl.DeserializeIfInfomsg(m)
  1960  
  1961  	attrs, err := nl.ParseRouteAttr(m[msg.Len():])
  1962  	if err != nil {
  1963  		return nil, err
  1964  	}
  1965  
  1966  	base := NewLinkAttrs()
  1967  	base.Index = int(msg.Index)
  1968  	base.RawFlags = msg.Flags
  1969  	base.Flags = linkFlags(msg.Flags)
  1970  	base.EncapType = msg.EncapType()
  1971  	base.NetNsID = -1
  1972  	if msg.Flags&unix.IFF_ALLMULTI != 0 {
  1973  		base.Allmulti = 1
  1974  	}
  1975  	if msg.Flags&unix.IFF_MULTICAST != 0 {
  1976  		base.Multi = 1
  1977  	}
  1978  
  1979  	var (
  1980  		link      Link
  1981  		stats32   *LinkStatistics32
  1982  		stats64   *LinkStatistics64
  1983  		linkType  string
  1984  		linkSlave LinkSlave
  1985  		slaveType string
  1986  	)
  1987  	for _, attr := range attrs {
  1988  		switch attr.Attr.Type {
  1989  		case unix.IFLA_LINKINFO:
  1990  			infos, err := nl.ParseRouteAttr(attr.Value)
  1991  			if err != nil {
  1992  				return nil, err
  1993  			}
  1994  			for _, info := range infos {
  1995  				switch info.Attr.Type {
  1996  				case nl.IFLA_INFO_KIND:
  1997  					linkType = string(info.Value[:len(info.Value)-1])
  1998  					switch linkType {
  1999  					case "dummy":
  2000  						link = &Dummy{}
  2001  					case "ifb":
  2002  						link = &Ifb{}
  2003  					case "bridge":
  2004  						link = &Bridge{}
  2005  					case "vlan":
  2006  						link = &Vlan{}
  2007  					case "netkit":
  2008  						link = &Netkit{}
  2009  					case "veth":
  2010  						link = &Veth{}
  2011  					case "wireguard":
  2012  						link = &Wireguard{}
  2013  					case "vxlan":
  2014  						link = &Vxlan{}
  2015  					case "bond":
  2016  						link = &Bond{}
  2017  					case "ipvlan":
  2018  						link = &IPVlan{}
  2019  					case "ipvtap":
  2020  						link = &IPVtap{}
  2021  					case "macvlan":
  2022  						link = &Macvlan{}
  2023  					case "macvtap":
  2024  						link = &Macvtap{}
  2025  					case "geneve":
  2026  						link = &Geneve{}
  2027  					case "gretap":
  2028  						link = &Gretap{}
  2029  					case "ip6gretap":
  2030  						link = &Gretap{}
  2031  					case "ipip":
  2032  						link = &Iptun{}
  2033  					case "ip6tnl":
  2034  						link = &Ip6tnl{}
  2035  					case "sit":
  2036  						link = &Sittun{}
  2037  					case "gre":
  2038  						link = &Gretun{}
  2039  					case "ip6gre":
  2040  						link = &Gretun{}
  2041  					case "vti", "vti6":
  2042  						link = &Vti{}
  2043  					case "vrf":
  2044  						link = &Vrf{}
  2045  					case "gtp":
  2046  						link = &GTP{}
  2047  					case "xfrm":
  2048  						link = &Xfrmi{}
  2049  					case "tun":
  2050  						link = &Tuntap{}
  2051  					case "ipoib":
  2052  						link = &IPoIB{}
  2053  					case "can":
  2054  						link = &Can{}
  2055  					case "bareudp":
  2056  						link = &BareUDP{}
  2057  					default:
  2058  						link = &GenericLink{LinkType: linkType}
  2059  					}
  2060  				case nl.IFLA_INFO_DATA:
  2061  					data, err := nl.ParseRouteAttr(info.Value)
  2062  					if err != nil {
  2063  						return nil, err
  2064  					}
  2065  					switch linkType {
  2066  					case "netkit":
  2067  						parseNetkitData(link, data)
  2068  					case "vlan":
  2069  						parseVlanData(link, data)
  2070  					case "vxlan":
  2071  						parseVxlanData(link, data)
  2072  					case "bond":
  2073  						parseBondData(link, data)
  2074  					case "ipvlan":
  2075  						parseIPVlanData(link, data)
  2076  					case "ipvtap":
  2077  						parseIPVtapData(link, data)
  2078  					case "macvlan":
  2079  						parseMacvlanData(link, data)
  2080  					case "macvtap":
  2081  						parseMacvtapData(link, data)
  2082  					case "geneve":
  2083  						parseGeneveData(link, data)
  2084  					case "gretap":
  2085  						parseGretapData(link, data)
  2086  					case "ip6gretap":
  2087  						parseGretapData(link, data)
  2088  					case "ipip":
  2089  						parseIptunData(link, data)
  2090  					case "ip6tnl":
  2091  						parseIp6tnlData(link, data)
  2092  					case "sit":
  2093  						parseSittunData(link, data)
  2094  					case "gre":
  2095  						parseGretunData(link, data)
  2096  					case "ip6gre":
  2097  						parseGretunData(link, data)
  2098  					case "vti", "vti6":
  2099  						parseVtiData(link, data)
  2100  					case "vrf":
  2101  						parseVrfData(link, data)
  2102  					case "bridge":
  2103  						parseBridgeData(link, data)
  2104  					case "gtp":
  2105  						parseGTPData(link, data)
  2106  					case "xfrm":
  2107  						parseXfrmiData(link, data)
  2108  					case "tun":
  2109  						parseTuntapData(link, data)
  2110  					case "ipoib":
  2111  						parseIPoIBData(link, data)
  2112  					case "can":
  2113  						parseCanData(link, data)
  2114  					case "bareudp":
  2115  						parseBareUDPData(link, data)
  2116  					}
  2117  
  2118  				case nl.IFLA_INFO_SLAVE_KIND:
  2119  					slaveType = string(info.Value[:len(info.Value)-1])
  2120  					switch slaveType {
  2121  					case "bond":
  2122  						linkSlave = &BondSlave{}
  2123  					case "vrf":
  2124  						linkSlave = &VrfSlave{}
  2125  					}
  2126  
  2127  				case nl.IFLA_INFO_SLAVE_DATA:
  2128  					switch slaveType {
  2129  					case "bond":
  2130  						data, err := nl.ParseRouteAttr(info.Value)
  2131  						if err != nil {
  2132  							return nil, err
  2133  						}
  2134  						parseBondSlaveData(linkSlave, data)
  2135  					case "vrf":
  2136  						data, err := nl.ParseRouteAttr(info.Value)
  2137  						if err != nil {
  2138  							return nil, err
  2139  						}
  2140  						parseVrfSlaveData(linkSlave, data)
  2141  					}
  2142  				}
  2143  			}
  2144  		case unix.IFLA_ADDRESS:
  2145  			var nonzero bool
  2146  			for _, b := range attr.Value {
  2147  				if b != 0 {
  2148  					nonzero = true
  2149  				}
  2150  			}
  2151  			if nonzero {
  2152  				base.HardwareAddr = attr.Value[:]
  2153  			}
  2154  		case unix.IFLA_IFNAME:
  2155  			base.Name = string(attr.Value[:len(attr.Value)-1])
  2156  		case unix.IFLA_MTU:
  2157  			base.MTU = int(native.Uint32(attr.Value[0:4]))
  2158  		case unix.IFLA_PROMISCUITY:
  2159  			base.Promisc = int(native.Uint32(attr.Value[0:4]))
  2160  		case unix.IFLA_LINK:
  2161  			base.ParentIndex = int(native.Uint32(attr.Value[0:4]))
  2162  		case unix.IFLA_MASTER:
  2163  			base.MasterIndex = int(native.Uint32(attr.Value[0:4]))
  2164  		case unix.IFLA_TXQLEN:
  2165  			base.TxQLen = int(native.Uint32(attr.Value[0:4]))
  2166  		case unix.IFLA_IFALIAS:
  2167  			base.Alias = string(attr.Value[:len(attr.Value)-1])
  2168  		case unix.IFLA_STATS:
  2169  			stats32 = new(LinkStatistics32)
  2170  			if err := binary.Read(bytes.NewBuffer(attr.Value[:]), nl.NativeEndian(), stats32); err != nil {
  2171  				return nil, err
  2172  			}
  2173  		case unix.IFLA_STATS64:
  2174  			stats64 = new(LinkStatistics64)
  2175  			if err := binary.Read(bytes.NewBuffer(attr.Value[:]), nl.NativeEndian(), stats64); err != nil {
  2176  				return nil, err
  2177  			}
  2178  		case unix.IFLA_XDP:
  2179  			xdp, err := parseLinkXdp(attr.Value[:])
  2180  			if err != nil {
  2181  				return nil, err
  2182  			}
  2183  			base.Xdp = xdp
  2184  		case unix.IFLA_PROTINFO | unix.NLA_F_NESTED:
  2185  			if hdr != nil && hdr.Type == unix.RTM_NEWLINK &&
  2186  				msg.Family == unix.AF_BRIDGE {
  2187  				attrs, err := nl.ParseRouteAttr(attr.Value[:])
  2188  				if err != nil {
  2189  					return nil, err
  2190  				}
  2191  				protinfo := parseProtinfo(attrs)
  2192  				base.Protinfo = &protinfo
  2193  			}
  2194  		case unix.IFLA_PROP_LIST | unix.NLA_F_NESTED:
  2195  			attrs, err := nl.ParseRouteAttr(attr.Value[:])
  2196  			if err != nil {
  2197  				return nil, err
  2198  			}
  2199  
  2200  			base.AltNames = []string{}
  2201  			for _, attr := range attrs {
  2202  				if attr.Attr.Type == unix.IFLA_ALT_IFNAME {
  2203  					base.AltNames = append(base.AltNames, nl.BytesToString(attr.Value))
  2204  				}
  2205  			}
  2206  		case unix.IFLA_OPERSTATE:
  2207  			base.OperState = LinkOperState(uint8(attr.Value[0]))
  2208  		case unix.IFLA_PHYS_SWITCH_ID:
  2209  			base.PhysSwitchID = int(native.Uint32(attr.Value[0:4]))
  2210  		case unix.IFLA_LINK_NETNSID:
  2211  			base.NetNsID = int(native.Uint32(attr.Value[0:4]))
  2212  		case unix.IFLA_TSO_MAX_SEGS:
  2213  			base.TSOMaxSegs = native.Uint32(attr.Value[0:4])
  2214  		case unix.IFLA_TSO_MAX_SIZE:
  2215  			base.TSOMaxSize = native.Uint32(attr.Value[0:4])
  2216  		case unix.IFLA_GSO_MAX_SEGS:
  2217  			base.GSOMaxSegs = native.Uint32(attr.Value[0:4])
  2218  		case unix.IFLA_GSO_MAX_SIZE:
  2219  			base.GSOMaxSize = native.Uint32(attr.Value[0:4])
  2220  		case unix.IFLA_GRO_MAX_SIZE:
  2221  			base.GROMaxSize = native.Uint32(attr.Value[0:4])
  2222  		case unix.IFLA_GSO_IPV4_MAX_SIZE:
  2223  			base.GSOIPv4MaxSize = native.Uint32(attr.Value[0:4])
  2224  		case unix.IFLA_GRO_IPV4_MAX_SIZE:
  2225  			base.GROIPv4MaxSize = native.Uint32(attr.Value[0:4])
  2226  		case unix.IFLA_VFINFO_LIST:
  2227  			data, err := nl.ParseRouteAttr(attr.Value)
  2228  			if err != nil {
  2229  				return nil, err
  2230  			}
  2231  			vfs, err := parseVfInfoList(data)
  2232  			if err != nil {
  2233  				return nil, err
  2234  			}
  2235  			base.Vfs = vfs
  2236  		case unix.IFLA_NUM_TX_QUEUES:
  2237  			base.NumTxQueues = int(native.Uint32(attr.Value[0:4]))
  2238  		case unix.IFLA_NUM_RX_QUEUES:
  2239  			base.NumRxQueues = int(native.Uint32(attr.Value[0:4]))
  2240  		case unix.IFLA_GROUP:
  2241  			base.Group = native.Uint32(attr.Value[0:4])
  2242  		case unix.IFLA_PERM_ADDRESS:
  2243  			for _, b := range attr.Value {
  2244  				if b != 0 {
  2245  					base.PermHWAddr = attr.Value[:]
  2246  					break
  2247  				}
  2248  			}
  2249  		}
  2250  	}
  2251  
  2252  	if stats64 != nil {
  2253  		base.Statistics = (*LinkStatistics)(stats64)
  2254  	} else if stats32 != nil {
  2255  		base.Statistics = (*LinkStatistics)(stats32.to64())
  2256  	}
  2257  
  2258  	// Links that don't have IFLA_INFO_KIND are hardware devices
  2259  	if link == nil {
  2260  		link = &Device{}
  2261  	}
  2262  	*link.Attrs() = base
  2263  	link.Attrs().Slave = linkSlave
  2264  
  2265  	// If the tuntap attributes are not updated by netlink due to
  2266  	// an older driver, use sysfs
  2267  	if link != nil && linkType == "tun" {
  2268  		tuntap := link.(*Tuntap)
  2269  
  2270  		if tuntap.Mode == 0 {
  2271  			ifname := tuntap.Attrs().Name
  2272  			if flags, err := readSysPropAsInt64(ifname, "tun_flags"); err == nil {
  2273  
  2274  				if flags&unix.IFF_TUN != 0 {
  2275  					tuntap.Mode = unix.IFF_TUN
  2276  				} else if flags&unix.IFF_TAP != 0 {
  2277  					tuntap.Mode = unix.IFF_TAP
  2278  				}
  2279  
  2280  				tuntap.NonPersist = false
  2281  				if flags&unix.IFF_PERSIST == 0 {
  2282  					tuntap.NonPersist = true
  2283  				}
  2284  			}
  2285  
  2286  			// The sysfs interface for owner/group returns -1 for root user, instead of returning 0.
  2287  			// So explicitly check for negative value, before assigning the owner uid/gid.
  2288  			if owner, err := readSysPropAsInt64(ifname, "owner"); err == nil && owner > 0 {
  2289  				tuntap.Owner = uint32(owner)
  2290  			}
  2291  
  2292  			if group, err := readSysPropAsInt64(ifname, "group"); err == nil && group > 0 {
  2293  				tuntap.Group = uint32(group)
  2294  			}
  2295  		}
  2296  	}
  2297  
  2298  	return link, nil
  2299  }
  2300  
  2301  func readSysPropAsInt64(ifname, prop string) (int64, error) {
  2302  	fname := fmt.Sprintf("/sys/class/net/%s/%s", ifname, prop)
  2303  	contents, err := ioutil.ReadFile(fname)
  2304  	if err != nil {
  2305  		return 0, err
  2306  	}
  2307  
  2308  	num, err := strconv.ParseInt(strings.TrimSpace(string(contents)), 0, 64)
  2309  	if err == nil {
  2310  		return num, nil
  2311  	}
  2312  
  2313  	return 0, err
  2314  }
  2315  
  2316  // LinkList gets a list of link devices.
  2317  // Equivalent to: `ip link show`
  2318  func LinkList() ([]Link, error) {
  2319  	return pkgHandle.LinkList()
  2320  }
  2321  
  2322  // LinkList gets a list of link devices.
  2323  // Equivalent to: `ip link show`
  2324  func (h *Handle) LinkList() ([]Link, error) {
  2325  	// NOTE(vish): This duplicates functionality in net/iface_linux.go, but we need
  2326  	//             to get the message ourselves to parse link type.
  2327  	req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP)
  2328  
  2329  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
  2330  	req.AddData(msg)
  2331  	attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF))
  2332  	req.AddData(attr)
  2333  
  2334  	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWLINK)
  2335  	if err != nil {
  2336  		return nil, err
  2337  	}
  2338  
  2339  	var res []Link
  2340  	for _, m := range msgs {
  2341  		link, err := LinkDeserialize(nil, m)
  2342  		if err != nil {
  2343  			return nil, err
  2344  		}
  2345  		res = append(res, link)
  2346  	}
  2347  
  2348  	return res, nil
  2349  }
  2350  
  2351  // LinkUpdate is used to pass information back from LinkSubscribe()
  2352  type LinkUpdate struct {
  2353  	nl.IfInfomsg
  2354  	Header unix.NlMsghdr
  2355  	Link
  2356  }
  2357  
  2358  // LinkSubscribe takes a chan down which notifications will be sent
  2359  // when links change.  Close the 'done' chan to stop subscription.
  2360  func LinkSubscribe(ch chan<- LinkUpdate, done <-chan struct{}) error {
  2361  	return linkSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0, nil, false)
  2362  }
  2363  
  2364  // LinkSubscribeAt works like LinkSubscribe plus it allows the caller
  2365  // to choose the network namespace in which to subscribe (ns).
  2366  func LinkSubscribeAt(ns netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}) error {
  2367  	return linkSubscribeAt(ns, netns.None(), ch, done, nil, false, 0, nil, false)
  2368  }
  2369  
  2370  // LinkSubscribeOptions contains a set of options to use with
  2371  // LinkSubscribeWithOptions.
  2372  type LinkSubscribeOptions struct {
  2373  	Namespace              *netns.NsHandle
  2374  	ErrorCallback          func(error)
  2375  	ListExisting           bool
  2376  	ReceiveBufferSize      int
  2377  	ReceiveBufferForceSize bool
  2378  	ReceiveTimeout         *unix.Timeval
  2379  }
  2380  
  2381  // LinkSubscribeWithOptions work like LinkSubscribe but enable to
  2382  // provide additional options to modify the behavior. Currently, the
  2383  // namespace can be provided as well as an error callback.
  2384  func LinkSubscribeWithOptions(ch chan<- LinkUpdate, done <-chan struct{}, options LinkSubscribeOptions) error {
  2385  	if options.Namespace == nil {
  2386  		none := netns.None()
  2387  		options.Namespace = &none
  2388  	}
  2389  	return linkSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting,
  2390  		options.ReceiveBufferSize, options.ReceiveTimeout, options.ReceiveBufferForceSize)
  2391  }
  2392  
  2393  func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}, cberr func(error), listExisting bool,
  2394  	rcvbuf int, rcvTimeout *unix.Timeval, rcvbufForce bool) error {
  2395  	s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_LINK)
  2396  	if err != nil {
  2397  		return err
  2398  	}
  2399  	if rcvTimeout != nil {
  2400  		if err := s.SetReceiveTimeout(rcvTimeout); err != nil {
  2401  			return err
  2402  		}
  2403  	}
  2404  	if rcvbuf != 0 {
  2405  		err = s.SetReceiveBufferSize(rcvbuf, rcvbufForce)
  2406  		if err != nil {
  2407  			return err
  2408  		}
  2409  	}
  2410  	if done != nil {
  2411  		go func() {
  2412  			<-done
  2413  			s.Close()
  2414  		}()
  2415  	}
  2416  	if listExisting {
  2417  		req := pkgHandle.newNetlinkRequest(unix.RTM_GETLINK,
  2418  			unix.NLM_F_DUMP)
  2419  		msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
  2420  		req.AddData(msg)
  2421  		if err := s.Send(req); err != nil {
  2422  			return err
  2423  		}
  2424  	}
  2425  	go func() {
  2426  		defer close(ch)
  2427  		for {
  2428  			msgs, from, err := s.Receive()
  2429  			if err != nil {
  2430  				if cberr != nil {
  2431  					cberr(fmt.Errorf("Receive failed: %v",
  2432  						err))
  2433  				}
  2434  				return
  2435  			}
  2436  			if from.Pid != nl.PidKernel {
  2437  				if cberr != nil {
  2438  					cberr(fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel))
  2439  				}
  2440  				continue
  2441  			}
  2442  			for _, m := range msgs {
  2443  				if m.Header.Type == unix.NLMSG_DONE {
  2444  					continue
  2445  				}
  2446  				if m.Header.Type == unix.NLMSG_ERROR {
  2447  					error := int32(native.Uint32(m.Data[0:4]))
  2448  					if error == 0 {
  2449  						continue
  2450  					}
  2451  					if cberr != nil {
  2452  						cberr(fmt.Errorf("error message: %v",
  2453  							syscall.Errno(-error)))
  2454  					}
  2455  					continue
  2456  				}
  2457  				ifmsg := nl.DeserializeIfInfomsg(m.Data)
  2458  				header := unix.NlMsghdr(m.Header)
  2459  				link, err := LinkDeserialize(&header, m.Data)
  2460  				if err != nil {
  2461  					if cberr != nil {
  2462  						cberr(err)
  2463  					}
  2464  					continue
  2465  				}
  2466  				ch <- LinkUpdate{IfInfomsg: *ifmsg, Header: header, Link: link}
  2467  			}
  2468  		}
  2469  	}()
  2470  
  2471  	return nil
  2472  }
  2473  
  2474  func LinkSetHairpin(link Link, mode bool) error {
  2475  	return pkgHandle.LinkSetHairpin(link, mode)
  2476  }
  2477  
  2478  func (h *Handle) LinkSetHairpin(link Link, mode bool) error {
  2479  	return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_MODE)
  2480  }
  2481  
  2482  func LinkSetGuard(link Link, mode bool) error {
  2483  	return pkgHandle.LinkSetGuard(link, mode)
  2484  }
  2485  
  2486  func (h *Handle) LinkSetGuard(link Link, mode bool) error {
  2487  	return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_GUARD)
  2488  }
  2489  
  2490  // LinkSetBRSlaveGroupFwdMask set the group_fwd_mask of a bridge slave interface
  2491  func LinkSetBRSlaveGroupFwdMask(link Link, mask uint16) error {
  2492  	return pkgHandle.LinkSetBRSlaveGroupFwdMask(link, mask)
  2493  }
  2494  
  2495  // LinkSetBRSlaveGroupFwdMask set the group_fwd_mask of a bridge slave interface
  2496  func (h *Handle) LinkSetBRSlaveGroupFwdMask(link Link, mask uint16) error {
  2497  	return h.setProtinfoAttrRawVal(link, nl.Uint16Attr(mask), nl.IFLA_BRPORT_GROUP_FWD_MASK)
  2498  }
  2499  
  2500  func LinkSetFastLeave(link Link, mode bool) error {
  2501  	return pkgHandle.LinkSetFastLeave(link, mode)
  2502  }
  2503  
  2504  func (h *Handle) LinkSetFastLeave(link Link, mode bool) error {
  2505  	return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_FAST_LEAVE)
  2506  }
  2507  
  2508  func LinkSetLearning(link Link, mode bool) error {
  2509  	return pkgHandle.LinkSetLearning(link, mode)
  2510  }
  2511  
  2512  func (h *Handle) LinkSetLearning(link Link, mode bool) error {
  2513  	return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_LEARNING)
  2514  }
  2515  
  2516  func LinkSetRootBlock(link Link, mode bool) error {
  2517  	return pkgHandle.LinkSetRootBlock(link, mode)
  2518  }
  2519  
  2520  func (h *Handle) LinkSetRootBlock(link Link, mode bool) error {
  2521  	return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROTECT)
  2522  }
  2523  
  2524  func LinkSetFlood(link Link, mode bool) error {
  2525  	return pkgHandle.LinkSetFlood(link, mode)
  2526  }
  2527  
  2528  func (h *Handle) LinkSetFlood(link Link, mode bool) error {
  2529  	return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_UNICAST_FLOOD)
  2530  }
  2531  
  2532  func LinkSetIsolated(link Link, mode bool) error {
  2533  	return pkgHandle.LinkSetIsolated(link, mode)
  2534  }
  2535  
  2536  func (h *Handle) LinkSetIsolated(link Link, mode bool) error {
  2537  	return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_ISOLATED)
  2538  }
  2539  
  2540  func LinkSetBrProxyArp(link Link, mode bool) error {
  2541  	return pkgHandle.LinkSetBrProxyArp(link, mode)
  2542  }
  2543  
  2544  func (h *Handle) LinkSetBrProxyArp(link Link, mode bool) error {
  2545  	return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROXYARP)
  2546  }
  2547  
  2548  func LinkSetBrProxyArpWiFi(link Link, mode bool) error {
  2549  	return pkgHandle.LinkSetBrProxyArpWiFi(link, mode)
  2550  }
  2551  
  2552  func (h *Handle) LinkSetBrProxyArpWiFi(link Link, mode bool) error {
  2553  	return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROXYARP_WIFI)
  2554  }
  2555  
  2556  func LinkSetBrNeighSuppress(link Link, mode bool) error {
  2557  	return pkgHandle.LinkSetBrNeighSuppress(link, mode)
  2558  }
  2559  
  2560  func (h *Handle) LinkSetBrNeighSuppress(link Link, mode bool) error {
  2561  	return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_NEIGH_SUPPRESS)
  2562  }
  2563  
  2564  func (h *Handle) setProtinfoAttrRawVal(link Link, val []byte, attr int) error {
  2565  	base := link.Attrs()
  2566  	h.ensureIndex(base)
  2567  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
  2568  
  2569  	msg := nl.NewIfInfomsg(unix.AF_BRIDGE)
  2570  	msg.Index = int32(base.Index)
  2571  	req.AddData(msg)
  2572  
  2573  	br := nl.NewRtAttr(unix.IFLA_PROTINFO|unix.NLA_F_NESTED, nil)
  2574  	br.AddRtAttr(attr, val)
  2575  	req.AddData(br)
  2576  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
  2577  	if err != nil {
  2578  		return err
  2579  	}
  2580  	return nil
  2581  }
  2582  func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
  2583  	return h.setProtinfoAttrRawVal(link, boolToByte(mode), attr)
  2584  }
  2585  
  2586  // LinkSetTxQLen sets the transaction queue length for the link.
  2587  // Equivalent to: `ip link set $link txqlen $qlen`
  2588  func LinkSetTxQLen(link Link, qlen int) error {
  2589  	return pkgHandle.LinkSetTxQLen(link, qlen)
  2590  }
  2591  
  2592  // LinkSetTxQLen sets the transaction queue length for the link.
  2593  // Equivalent to: `ip link set $link txqlen $qlen`
  2594  func (h *Handle) LinkSetTxQLen(link Link, qlen int) error {
  2595  	base := link.Attrs()
  2596  	h.ensureIndex(base)
  2597  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
  2598  
  2599  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
  2600  	msg.Index = int32(base.Index)
  2601  	req.AddData(msg)
  2602  
  2603  	b := make([]byte, 4)
  2604  	native.PutUint32(b, uint32(qlen))
  2605  
  2606  	data := nl.NewRtAttr(unix.IFLA_TXQLEN, b)
  2607  	req.AddData(data)
  2608  
  2609  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
  2610  	return err
  2611  }
  2612  
  2613  // LinkSetGroup sets the link group id which can be used to perform mass actions
  2614  // with iproute2 as well use it as a reference in nft filters.
  2615  // Equivalent to: `ip link set $link group $id`
  2616  func LinkSetGroup(link Link, group int) error {
  2617  	return pkgHandle.LinkSetGroup(link, group)
  2618  }
  2619  
  2620  // LinkSetGroup sets the link group id which can be used to perform mass actions
  2621  // with iproute2 as well use it as a reference in nft filters.
  2622  // Equivalent to: `ip link set $link group $id`
  2623  func (h *Handle) LinkSetGroup(link Link, group int) error {
  2624  	base := link.Attrs()
  2625  	h.ensureIndex(base)
  2626  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
  2627  
  2628  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
  2629  	msg.Index = int32(base.Index)
  2630  	req.AddData(msg)
  2631  
  2632  	b := make([]byte, 4)
  2633  	native.PutUint32(b, uint32(group))
  2634  
  2635  	data := nl.NewRtAttr(unix.IFLA_GROUP, b)
  2636  	req.AddData(data)
  2637  
  2638  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
  2639  	return err
  2640  }
  2641  
  2642  func addNetkitAttrs(nk *Netkit, linkInfo *nl.RtAttr, flag int) error {
  2643  	if nk.peerLinkAttrs.HardwareAddr != nil || nk.HardwareAddr != nil {
  2644  		return fmt.Errorf("netkit doesn't support setting Ethernet")
  2645  	}
  2646  
  2647  	data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
  2648  	// Kernel will return error if trying to change the mode of an existing netkit device
  2649  	data.AddRtAttr(nl.IFLA_NETKIT_MODE, nl.Uint32Attr(uint32(nk.Mode)))
  2650  	data.AddRtAttr(nl.IFLA_NETKIT_POLICY, nl.Uint32Attr(uint32(nk.Policy)))
  2651  	data.AddRtAttr(nl.IFLA_NETKIT_PEER_POLICY, nl.Uint32Attr(uint32(nk.PeerPolicy)))
  2652  
  2653  	if (flag & unix.NLM_F_EXCL) == 0 {
  2654  		// Modifying peer link attributes will not take effect
  2655  		return nil
  2656  	}
  2657  
  2658  	peer := data.AddRtAttr(nl.IFLA_NETKIT_PEER_INFO, nil)
  2659  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
  2660  	if nk.peerLinkAttrs.Flags&net.FlagUp != 0 {
  2661  		msg.Change = unix.IFF_UP
  2662  		msg.Flags = unix.IFF_UP
  2663  	}
  2664  	if nk.peerLinkAttrs.Index != 0 {
  2665  		msg.Index = int32(nk.peerLinkAttrs.Index)
  2666  	}
  2667  	peer.AddChild(msg)
  2668  	if nk.peerLinkAttrs.Name != "" {
  2669  		peer.AddRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(nk.peerLinkAttrs.Name))
  2670  	}
  2671  	if nk.peerLinkAttrs.MTU > 0 {
  2672  		peer.AddRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(nk.peerLinkAttrs.MTU)))
  2673  	}
  2674  	if nk.peerLinkAttrs.GSOMaxSegs > 0 {
  2675  		peer.AddRtAttr(unix.IFLA_GSO_MAX_SEGS, nl.Uint32Attr(nk.peerLinkAttrs.GSOMaxSegs))
  2676  	}
  2677  	if nk.peerLinkAttrs.GSOMaxSize > 0 {
  2678  		peer.AddRtAttr(unix.IFLA_GSO_MAX_SIZE, nl.Uint32Attr(nk.peerLinkAttrs.GSOMaxSize))
  2679  	}
  2680  	if nk.peerLinkAttrs.GSOIPv4MaxSize > 0 {
  2681  		peer.AddRtAttr(unix.IFLA_GSO_IPV4_MAX_SIZE, nl.Uint32Attr(nk.peerLinkAttrs.GSOIPv4MaxSize))
  2682  	}
  2683  	if nk.peerLinkAttrs.GROIPv4MaxSize > 0 {
  2684  		peer.AddRtAttr(unix.IFLA_GRO_IPV4_MAX_SIZE, nl.Uint32Attr(nk.peerLinkAttrs.GROIPv4MaxSize))
  2685  	}
  2686  	if nk.peerLinkAttrs.Namespace != nil {
  2687  		switch ns := nk.peerLinkAttrs.Namespace.(type) {
  2688  		case NsPid:
  2689  			peer.AddRtAttr(unix.IFLA_NET_NS_PID, nl.Uint32Attr(uint32(ns)))
  2690  		case NsFd:
  2691  			peer.AddRtAttr(unix.IFLA_NET_NS_FD, nl.Uint32Attr(uint32(ns)))
  2692  		}
  2693  	}
  2694  	return nil
  2695  }
  2696  
  2697  func parseNetkitData(link Link, data []syscall.NetlinkRouteAttr) {
  2698  	netkit := link.(*Netkit)
  2699  	for _, datum := range data {
  2700  		switch datum.Attr.Type {
  2701  		case nl.IFLA_NETKIT_PRIMARY:
  2702  			isPrimary := datum.Value[0:1][0]
  2703  			if isPrimary != 0 {
  2704  				netkit.isPrimary = true
  2705  			}
  2706  		case nl.IFLA_NETKIT_MODE:
  2707  			netkit.Mode = NetkitMode(native.Uint32(datum.Value[0:4]))
  2708  		case nl.IFLA_NETKIT_POLICY:
  2709  			netkit.Policy = NetkitPolicy(native.Uint32(datum.Value[0:4]))
  2710  		case nl.IFLA_NETKIT_PEER_POLICY:
  2711  			netkit.PeerPolicy = NetkitPolicy(native.Uint32(datum.Value[0:4]))
  2712  		}
  2713  	}
  2714  }
  2715  
  2716  func parseVlanData(link Link, data []syscall.NetlinkRouteAttr) {
  2717  	vlan := link.(*Vlan)
  2718  	for _, datum := range data {
  2719  		switch datum.Attr.Type {
  2720  		case nl.IFLA_VLAN_ID:
  2721  			vlan.VlanId = int(native.Uint16(datum.Value[0:2]))
  2722  		case nl.IFLA_VLAN_PROTOCOL:
  2723  			vlan.VlanProtocol = VlanProtocol(int(ntohs(datum.Value[0:2])))
  2724  		}
  2725  	}
  2726  }
  2727  
  2728  func parseVxlanData(link Link, data []syscall.NetlinkRouteAttr) {
  2729  	vxlan := link.(*Vxlan)
  2730  	for _, datum := range data {
  2731  		// NOTE(vish): Apparently some messages can be sent with no value.
  2732  		//             We special case GBP here to not change existing
  2733  		//             functionality. It appears that GBP sends a datum.Value
  2734  		//             of null.
  2735  		if len(datum.Value) == 0 && datum.Attr.Type != nl.IFLA_VXLAN_GBP {
  2736  			continue
  2737  		}
  2738  		switch datum.Attr.Type {
  2739  		case nl.IFLA_VXLAN_ID:
  2740  			vxlan.VxlanId = int(native.Uint32(datum.Value[0:4]))
  2741  		case nl.IFLA_VXLAN_LINK:
  2742  			vxlan.VtepDevIndex = int(native.Uint32(datum.Value[0:4]))
  2743  		case nl.IFLA_VXLAN_LOCAL:
  2744  			vxlan.SrcAddr = net.IP(datum.Value[0:4])
  2745  		case nl.IFLA_VXLAN_LOCAL6:
  2746  			vxlan.SrcAddr = net.IP(datum.Value[0:16])
  2747  		case nl.IFLA_VXLAN_GROUP:
  2748  			vxlan.Group = net.IP(datum.Value[0:4])
  2749  		case nl.IFLA_VXLAN_GROUP6:
  2750  			vxlan.Group = net.IP(datum.Value[0:16])
  2751  		case nl.IFLA_VXLAN_TTL:
  2752  			vxlan.TTL = int(datum.Value[0])
  2753  		case nl.IFLA_VXLAN_TOS:
  2754  			vxlan.TOS = int(datum.Value[0])
  2755  		case nl.IFLA_VXLAN_LEARNING:
  2756  			vxlan.Learning = int8(datum.Value[0]) != 0
  2757  		case nl.IFLA_VXLAN_PROXY:
  2758  			vxlan.Proxy = int8(datum.Value[0]) != 0
  2759  		case nl.IFLA_VXLAN_RSC:
  2760  			vxlan.RSC = int8(datum.Value[0]) != 0
  2761  		case nl.IFLA_VXLAN_L2MISS:
  2762  			vxlan.L2miss = int8(datum.Value[0]) != 0
  2763  		case nl.IFLA_VXLAN_L3MISS:
  2764  			vxlan.L3miss = int8(datum.Value[0]) != 0
  2765  		case nl.IFLA_VXLAN_UDP_CSUM:
  2766  			vxlan.UDPCSum = int8(datum.Value[0]) != 0
  2767  		case nl.IFLA_VXLAN_UDP_ZERO_CSUM6_TX:
  2768  			vxlan.UDP6ZeroCSumTx = int8(datum.Value[0]) != 0
  2769  		case nl.IFLA_VXLAN_UDP_ZERO_CSUM6_RX:
  2770  			vxlan.UDP6ZeroCSumRx = int8(datum.Value[0]) != 0
  2771  		case nl.IFLA_VXLAN_GBP:
  2772  			vxlan.GBP = true
  2773  		case nl.IFLA_VXLAN_FLOWBASED:
  2774  			vxlan.FlowBased = int8(datum.Value[0]) != 0
  2775  		case nl.IFLA_VXLAN_AGEING:
  2776  			vxlan.Age = int(native.Uint32(datum.Value[0:4]))
  2777  			vxlan.NoAge = vxlan.Age == 0
  2778  		case nl.IFLA_VXLAN_LIMIT:
  2779  			vxlan.Limit = int(native.Uint32(datum.Value[0:4]))
  2780  		case nl.IFLA_VXLAN_PORT:
  2781  			vxlan.Port = int(ntohs(datum.Value[0:2]))
  2782  		case nl.IFLA_VXLAN_PORT_RANGE:
  2783  			buf := bytes.NewBuffer(datum.Value[0:4])
  2784  			var pr vxlanPortRange
  2785  			if binary.Read(buf, binary.BigEndian, &pr) != nil {
  2786  				vxlan.PortLow = int(pr.Lo)
  2787  				vxlan.PortHigh = int(pr.Hi)
  2788  			}
  2789  		}
  2790  	}
  2791  }
  2792  
  2793  func parseBondData(link Link, data []syscall.NetlinkRouteAttr) {
  2794  	bond := link.(*Bond)
  2795  	for i := range data {
  2796  		switch data[i].Attr.Type {
  2797  		case nl.IFLA_BOND_MODE:
  2798  			bond.Mode = BondMode(data[i].Value[0])
  2799  		case nl.IFLA_BOND_ACTIVE_SLAVE:
  2800  			bond.ActiveSlave = int(native.Uint32(data[i].Value[0:4]))
  2801  		case nl.IFLA_BOND_MIIMON:
  2802  			bond.Miimon = int(native.Uint32(data[i].Value[0:4]))
  2803  		case nl.IFLA_BOND_UPDELAY:
  2804  			bond.UpDelay = int(native.Uint32(data[i].Value[0:4]))
  2805  		case nl.IFLA_BOND_DOWNDELAY:
  2806  			bond.DownDelay = int(native.Uint32(data[i].Value[0:4]))
  2807  		case nl.IFLA_BOND_USE_CARRIER:
  2808  			bond.UseCarrier = int(data[i].Value[0])
  2809  		case nl.IFLA_BOND_ARP_INTERVAL:
  2810  			bond.ArpInterval = int(native.Uint32(data[i].Value[0:4]))
  2811  		case nl.IFLA_BOND_ARP_IP_TARGET:
  2812  			bond.ArpIpTargets = parseBondArpIpTargets(data[i].Value)
  2813  		case nl.IFLA_BOND_ARP_VALIDATE:
  2814  			bond.ArpValidate = BondArpValidate(native.Uint32(data[i].Value[0:4]))
  2815  		case nl.IFLA_BOND_ARP_ALL_TARGETS:
  2816  			bond.ArpAllTargets = BondArpAllTargets(native.Uint32(data[i].Value[0:4]))
  2817  		case nl.IFLA_BOND_PRIMARY:
  2818  			bond.Primary = int(native.Uint32(data[i].Value[0:4]))
  2819  		case nl.IFLA_BOND_PRIMARY_RESELECT:
  2820  			bond.PrimaryReselect = BondPrimaryReselect(data[i].Value[0])
  2821  		case nl.IFLA_BOND_FAIL_OVER_MAC:
  2822  			bond.FailOverMac = BondFailOverMac(data[i].Value[0])
  2823  		case nl.IFLA_BOND_XMIT_HASH_POLICY:
  2824  			bond.XmitHashPolicy = BondXmitHashPolicy(data[i].Value[0])
  2825  		case nl.IFLA_BOND_RESEND_IGMP:
  2826  			bond.ResendIgmp = int(native.Uint32(data[i].Value[0:4]))
  2827  		case nl.IFLA_BOND_NUM_PEER_NOTIF:
  2828  			bond.NumPeerNotif = int(data[i].Value[0])
  2829  		case nl.IFLA_BOND_ALL_SLAVES_ACTIVE:
  2830  			bond.AllSlavesActive = int(data[i].Value[0])
  2831  		case nl.IFLA_BOND_MIN_LINKS:
  2832  			bond.MinLinks = int(native.Uint32(data[i].Value[0:4]))
  2833  		case nl.IFLA_BOND_LP_INTERVAL:
  2834  			bond.LpInterval = int(native.Uint32(data[i].Value[0:4]))
  2835  		case nl.IFLA_BOND_PACKETS_PER_SLAVE:
  2836  			bond.PacketsPerSlave = int(native.Uint32(data[i].Value[0:4]))
  2837  		case nl.IFLA_BOND_AD_LACP_RATE:
  2838  			bond.LacpRate = BondLacpRate(data[i].Value[0])
  2839  		case nl.IFLA_BOND_AD_SELECT:
  2840  			bond.AdSelect = BondAdSelect(data[i].Value[0])
  2841  		case nl.IFLA_BOND_AD_INFO:
  2842  			// TODO: implement
  2843  		case nl.IFLA_BOND_AD_ACTOR_SYS_PRIO:
  2844  			bond.AdActorSysPrio = int(native.Uint16(data[i].Value[0:2]))
  2845  		case nl.IFLA_BOND_AD_USER_PORT_KEY:
  2846  			bond.AdUserPortKey = int(native.Uint16(data[i].Value[0:2]))
  2847  		case nl.IFLA_BOND_AD_ACTOR_SYSTEM:
  2848  			bond.AdActorSystem = net.HardwareAddr(data[i].Value[0:6])
  2849  		case nl.IFLA_BOND_TLB_DYNAMIC_LB:
  2850  			bond.TlbDynamicLb = int(data[i].Value[0])
  2851  		}
  2852  	}
  2853  }
  2854  
  2855  func parseBondArpIpTargets(value []byte) []net.IP {
  2856  	data, err := nl.ParseRouteAttr(value)
  2857  	if err != nil {
  2858  		return nil
  2859  	}
  2860  
  2861  	targets := []net.IP{}
  2862  	for i := range data {
  2863  		target := net.IP(data[i].Value)
  2864  		if ip := target.To4(); ip != nil {
  2865  			targets = append(targets, ip)
  2866  			continue
  2867  		}
  2868  		if ip := target.To16(); ip != nil {
  2869  			targets = append(targets, ip)
  2870  		}
  2871  	}
  2872  
  2873  	return targets
  2874  }
  2875  
  2876  func addBondSlaveAttrs(bondSlave *BondSlave, linkInfo *nl.RtAttr) {
  2877  	data := linkInfo.AddRtAttr(nl.IFLA_INFO_SLAVE_DATA, nil)
  2878  
  2879  	data.AddRtAttr(nl.IFLA_BOND_SLAVE_STATE, nl.Uint8Attr(uint8(bondSlave.State)))
  2880  	data.AddRtAttr(nl.IFLA_BOND_SLAVE_MII_STATUS, nl.Uint8Attr(uint8(bondSlave.MiiStatus)))
  2881  	data.AddRtAttr(nl.IFLA_BOND_SLAVE_LINK_FAILURE_COUNT, nl.Uint32Attr(bondSlave.LinkFailureCount))
  2882  	data.AddRtAttr(nl.IFLA_BOND_SLAVE_QUEUE_ID, nl.Uint16Attr(bondSlave.QueueId))
  2883  	data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_AGGREGATOR_ID, nl.Uint16Attr(bondSlave.AggregatorId))
  2884  	data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE, nl.Uint8Attr(bondSlave.AdActorOperPortState))
  2885  	data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE, nl.Uint16Attr(bondSlave.AdPartnerOperPortState))
  2886  
  2887  	if mac := bondSlave.PermHardwareAddr; mac != nil {
  2888  		data.AddRtAttr(nl.IFLA_BOND_SLAVE_PERM_HWADDR, []byte(mac))
  2889  	}
  2890  }
  2891  
  2892  func parseBondSlaveData(slave LinkSlave, data []syscall.NetlinkRouteAttr) {
  2893  	bondSlave := slave.(*BondSlave)
  2894  	for i := range data {
  2895  		switch data[i].Attr.Type {
  2896  		case nl.IFLA_BOND_SLAVE_STATE:
  2897  			bondSlave.State = BondSlaveState(data[i].Value[0])
  2898  		case nl.IFLA_BOND_SLAVE_MII_STATUS:
  2899  			bondSlave.MiiStatus = BondSlaveMiiStatus(data[i].Value[0])
  2900  		case nl.IFLA_BOND_SLAVE_LINK_FAILURE_COUNT:
  2901  			bondSlave.LinkFailureCount = native.Uint32(data[i].Value[0:4])
  2902  		case nl.IFLA_BOND_SLAVE_PERM_HWADDR:
  2903  			bondSlave.PermHardwareAddr = net.HardwareAddr(data[i].Value[0:6])
  2904  		case nl.IFLA_BOND_SLAVE_QUEUE_ID:
  2905  			bondSlave.QueueId = native.Uint16(data[i].Value[0:2])
  2906  		case nl.IFLA_BOND_SLAVE_AD_AGGREGATOR_ID:
  2907  			bondSlave.AggregatorId = native.Uint16(data[i].Value[0:2])
  2908  		case nl.IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE:
  2909  			bondSlave.AdActorOperPortState = uint8(data[i].Value[0])
  2910  		case nl.IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE:
  2911  			bondSlave.AdPartnerOperPortState = native.Uint16(data[i].Value[0:2])
  2912  		}
  2913  	}
  2914  }
  2915  
  2916  func parseVrfSlaveData(slave LinkSlave, data []syscall.NetlinkRouteAttr) {
  2917  	vrfSlave := slave.(*VrfSlave)
  2918  	for i := range data {
  2919  		switch data[i].Attr.Type {
  2920  		case nl.IFLA_BOND_SLAVE_STATE:
  2921  			vrfSlave.Table = native.Uint32(data[i].Value[0:4])
  2922  		}
  2923  	}
  2924  }
  2925  
  2926  func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) {
  2927  	ipv := link.(*IPVlan)
  2928  	for _, datum := range data {
  2929  		switch datum.Attr.Type {
  2930  		case nl.IFLA_IPVLAN_MODE:
  2931  			ipv.Mode = IPVlanMode(native.Uint32(datum.Value[0:4]))
  2932  		case nl.IFLA_IPVLAN_FLAG:
  2933  			ipv.Flag = IPVlanFlag(native.Uint32(datum.Value[0:4]))
  2934  		}
  2935  	}
  2936  }
  2937  
  2938  func parseIPVtapData(link Link, data []syscall.NetlinkRouteAttr) {
  2939  	ipv := link.(*IPVtap)
  2940  	for _, datum := range data {
  2941  		switch datum.Attr.Type {
  2942  		case nl.IFLA_IPVLAN_MODE:
  2943  			ipv.Mode = IPVlanMode(native.Uint32(datum.Value[0:4]))
  2944  		case nl.IFLA_IPVLAN_FLAG:
  2945  			ipv.Flag = IPVlanFlag(native.Uint32(datum.Value[0:4]))
  2946  		}
  2947  	}
  2948  }
  2949  
  2950  func addMacvtapAttrs(macvtap *Macvtap, linkInfo *nl.RtAttr) {
  2951  	addMacvlanAttrs(&macvtap.Macvlan, linkInfo)
  2952  }
  2953  
  2954  func parseMacvtapData(link Link, data []syscall.NetlinkRouteAttr) {
  2955  	macv := link.(*Macvtap)
  2956  	parseMacvlanData(&macv.Macvlan, data)
  2957  }
  2958  
  2959  func addMacvlanAttrs(macvlan *Macvlan, linkInfo *nl.RtAttr) {
  2960  	var data *nl.RtAttr
  2961  
  2962  	if macvlan.Mode != MACVLAN_MODE_DEFAULT || macvlan.BCQueueLen > 0 {
  2963  		data = linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
  2964  	}
  2965  
  2966  	if macvlan.Mode != MACVLAN_MODE_DEFAULT {
  2967  		data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[macvlan.Mode]))
  2968  	}
  2969  	if macvlan.BCQueueLen > 0 {
  2970  		data.AddRtAttr(nl.IFLA_MACVLAN_BC_QUEUE_LEN, nl.Uint32Attr(macvlan.BCQueueLen))
  2971  	}
  2972  }
  2973  
  2974  func parseMacvlanData(link Link, data []syscall.NetlinkRouteAttr) {
  2975  	macv := link.(*Macvlan)
  2976  	for _, datum := range data {
  2977  		switch datum.Attr.Type {
  2978  		case nl.IFLA_MACVLAN_MODE:
  2979  			switch native.Uint32(datum.Value[0:4]) {
  2980  			case nl.MACVLAN_MODE_PRIVATE:
  2981  				macv.Mode = MACVLAN_MODE_PRIVATE
  2982  			case nl.MACVLAN_MODE_VEPA:
  2983  				macv.Mode = MACVLAN_MODE_VEPA
  2984  			case nl.MACVLAN_MODE_BRIDGE:
  2985  				macv.Mode = MACVLAN_MODE_BRIDGE
  2986  			case nl.MACVLAN_MODE_PASSTHRU:
  2987  				macv.Mode = MACVLAN_MODE_PASSTHRU
  2988  			case nl.MACVLAN_MODE_SOURCE:
  2989  				macv.Mode = MACVLAN_MODE_SOURCE
  2990  			}
  2991  		case nl.IFLA_MACVLAN_MACADDR_COUNT:
  2992  			macv.MACAddrs = make([]net.HardwareAddr, 0, int(native.Uint32(datum.Value[0:4])))
  2993  		case nl.IFLA_MACVLAN_MACADDR_DATA:
  2994  			macs, err := nl.ParseRouteAttr(datum.Value[:])
  2995  			if err != nil {
  2996  				panic(fmt.Sprintf("failed to ParseRouteAttr for IFLA_MACVLAN_MACADDR_DATA: %v", err))
  2997  			}
  2998  			for _, macDatum := range macs {
  2999  				macv.MACAddrs = append(macv.MACAddrs, net.HardwareAddr(macDatum.Value[0:6]))
  3000  			}
  3001  		case nl.IFLA_MACVLAN_BC_QUEUE_LEN:
  3002  			macv.BCQueueLen = native.Uint32(datum.Value[0:4])
  3003  		case nl.IFLA_MACVLAN_BC_QUEUE_LEN_USED:
  3004  			macv.UsedBCQueueLen = native.Uint32(datum.Value[0:4])
  3005  		}
  3006  	}
  3007  }
  3008  
  3009  // copied from pkg/net_linux.go
  3010  func linkFlags(rawFlags uint32) net.Flags {
  3011  	var f net.Flags
  3012  	if rawFlags&unix.IFF_UP != 0 {
  3013  		f |= net.FlagUp
  3014  	}
  3015  	if rawFlags&unix.IFF_BROADCAST != 0 {
  3016  		f |= net.FlagBroadcast
  3017  	}
  3018  	if rawFlags&unix.IFF_LOOPBACK != 0 {
  3019  		f |= net.FlagLoopback
  3020  	}
  3021  	if rawFlags&unix.IFF_POINTOPOINT != 0 {
  3022  		f |= net.FlagPointToPoint
  3023  	}
  3024  	if rawFlags&unix.IFF_MULTICAST != 0 {
  3025  		f |= net.FlagMulticast
  3026  	}
  3027  	return f
  3028  }
  3029  
  3030  func addGeneveAttrs(geneve *Geneve, linkInfo *nl.RtAttr) {
  3031  	data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
  3032  
  3033  	if geneve.InnerProtoInherit {
  3034  		data.AddRtAttr(nl.IFLA_GENEVE_INNER_PROTO_INHERIT, []byte{})
  3035  	}
  3036  
  3037  	if geneve.FlowBased {
  3038  		geneve.ID = 0
  3039  		data.AddRtAttr(nl.IFLA_GENEVE_COLLECT_METADATA, []byte{})
  3040  	}
  3041  
  3042  	if ip := geneve.Remote; ip != nil {
  3043  		if ip4 := ip.To4(); ip4 != nil {
  3044  			data.AddRtAttr(nl.IFLA_GENEVE_REMOTE, ip.To4())
  3045  		} else {
  3046  			data.AddRtAttr(nl.IFLA_GENEVE_REMOTE6, []byte(ip))
  3047  		}
  3048  	}
  3049  
  3050  	if geneve.ID != 0 {
  3051  		data.AddRtAttr(nl.IFLA_GENEVE_ID, nl.Uint32Attr(geneve.ID))
  3052  	}
  3053  
  3054  	if geneve.Dport != 0 {
  3055  		data.AddRtAttr(nl.IFLA_GENEVE_PORT, htons(geneve.Dport))
  3056  	}
  3057  
  3058  	if geneve.Ttl != 0 {
  3059  		data.AddRtAttr(nl.IFLA_GENEVE_TTL, nl.Uint8Attr(geneve.Ttl))
  3060  	}
  3061  
  3062  	if geneve.Tos != 0 {
  3063  		data.AddRtAttr(nl.IFLA_GENEVE_TOS, nl.Uint8Attr(geneve.Tos))
  3064  	}
  3065  
  3066  	data.AddRtAttr(nl.IFLA_GENEVE_DF, nl.Uint8Attr(uint8(geneve.Df)))
  3067  }
  3068  
  3069  func parseGeneveData(link Link, data []syscall.NetlinkRouteAttr) {
  3070  	geneve := link.(*Geneve)
  3071  	for _, datum := range data {
  3072  		switch datum.Attr.Type {
  3073  		case nl.IFLA_GENEVE_ID:
  3074  			geneve.ID = native.Uint32(datum.Value[0:4])
  3075  		case nl.IFLA_GENEVE_REMOTE, nl.IFLA_GENEVE_REMOTE6:
  3076  			geneve.Remote = datum.Value
  3077  		case nl.IFLA_GENEVE_PORT:
  3078  			geneve.Dport = ntohs(datum.Value[0:2])
  3079  		case nl.IFLA_GENEVE_TTL:
  3080  			geneve.Ttl = uint8(datum.Value[0])
  3081  		case nl.IFLA_GENEVE_TOS:
  3082  			geneve.Tos = uint8(datum.Value[0])
  3083  		case nl.IFLA_GENEVE_COLLECT_METADATA:
  3084  			geneve.FlowBased = true
  3085  		case nl.IFLA_GENEVE_INNER_PROTO_INHERIT:
  3086  			geneve.InnerProtoInherit = true
  3087  		}
  3088  	}
  3089  }
  3090  
  3091  func addGretapAttrs(gretap *Gretap, linkInfo *nl.RtAttr) {
  3092  	data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
  3093  
  3094  	if gretap.FlowBased {
  3095  		// In flow based mode, no other attributes need to be configured
  3096  		data.AddRtAttr(nl.IFLA_GRE_COLLECT_METADATA, []byte{})
  3097  		return
  3098  	}
  3099  
  3100  	if ip := gretap.Local; ip != nil {
  3101  		if ip.To4() != nil {
  3102  			ip = ip.To4()
  3103  		}
  3104  		data.AddRtAttr(nl.IFLA_GRE_LOCAL, []byte(ip))
  3105  	}
  3106  
  3107  	if ip := gretap.Remote; ip != nil {
  3108  		if ip.To4() != nil {
  3109  			ip = ip.To4()
  3110  		}
  3111  		data.AddRtAttr(nl.IFLA_GRE_REMOTE, []byte(ip))
  3112  	}
  3113  
  3114  	if gretap.IKey != 0 {
  3115  		data.AddRtAttr(nl.IFLA_GRE_IKEY, htonl(gretap.IKey))
  3116  		gretap.IFlags |= uint16(nl.GRE_KEY)
  3117  	}
  3118  
  3119  	if gretap.OKey != 0 {
  3120  		data.AddRtAttr(nl.IFLA_GRE_OKEY, htonl(gretap.OKey))
  3121  		gretap.OFlags |= uint16(nl.GRE_KEY)
  3122  	}
  3123  
  3124  	data.AddRtAttr(nl.IFLA_GRE_IFLAGS, htons(gretap.IFlags))
  3125  	data.AddRtAttr(nl.IFLA_GRE_OFLAGS, htons(gretap.OFlags))
  3126  
  3127  	if gretap.Link != 0 {
  3128  		data.AddRtAttr(nl.IFLA_GRE_LINK, nl.Uint32Attr(gretap.Link))
  3129  	}
  3130  
  3131  	data.AddRtAttr(nl.IFLA_GRE_PMTUDISC, nl.Uint8Attr(gretap.PMtuDisc))
  3132  	data.AddRtAttr(nl.IFLA_GRE_TTL, nl.Uint8Attr(gretap.Ttl))
  3133  	data.AddRtAttr(nl.IFLA_GRE_TOS, nl.Uint8Attr(gretap.Tos))
  3134  	data.AddRtAttr(nl.IFLA_GRE_ENCAP_TYPE, nl.Uint16Attr(gretap.EncapType))
  3135  	data.AddRtAttr(nl.IFLA_GRE_ENCAP_FLAGS, nl.Uint16Attr(gretap.EncapFlags))
  3136  	data.AddRtAttr(nl.IFLA_GRE_ENCAP_SPORT, htons(gretap.EncapSport))
  3137  	data.AddRtAttr(nl.IFLA_GRE_ENCAP_DPORT, htons(gretap.EncapDport))
  3138  }
  3139  
  3140  func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) {
  3141  	gre := link.(*Gretap)
  3142  	for _, datum := range data {
  3143  		switch datum.Attr.Type {
  3144  		case nl.IFLA_GRE_OKEY:
  3145  			gre.IKey = ntohl(datum.Value[0:4])
  3146  		case nl.IFLA_GRE_IKEY:
  3147  			gre.OKey = ntohl(datum.Value[0:4])
  3148  		case nl.IFLA_GRE_LOCAL:
  3149  			gre.Local = net.IP(datum.Value)
  3150  		case nl.IFLA_GRE_REMOTE:
  3151  			gre.Remote = net.IP(datum.Value)
  3152  		case nl.IFLA_GRE_ENCAP_SPORT:
  3153  			gre.EncapSport = ntohs(datum.Value[0:2])
  3154  		case nl.IFLA_GRE_ENCAP_DPORT:
  3155  			gre.EncapDport = ntohs(datum.Value[0:2])
  3156  		case nl.IFLA_GRE_IFLAGS:
  3157  			gre.IFlags = ntohs(datum.Value[0:2])
  3158  		case nl.IFLA_GRE_OFLAGS:
  3159  			gre.OFlags = ntohs(datum.Value[0:2])
  3160  		case nl.IFLA_GRE_TTL:
  3161  			gre.Ttl = uint8(datum.Value[0])
  3162  		case nl.IFLA_GRE_TOS:
  3163  			gre.Tos = uint8(datum.Value[0])
  3164  		case nl.IFLA_GRE_PMTUDISC:
  3165  			gre.PMtuDisc = uint8(datum.Value[0])
  3166  		case nl.IFLA_GRE_ENCAP_TYPE:
  3167  			gre.EncapType = native.Uint16(datum.Value[0:2])
  3168  		case nl.IFLA_GRE_ENCAP_FLAGS:
  3169  			gre.EncapFlags = native.Uint16(datum.Value[0:2])
  3170  		case nl.IFLA_GRE_COLLECT_METADATA:
  3171  			gre.FlowBased = true
  3172  		}
  3173  	}
  3174  }
  3175  
  3176  func addGretunAttrs(gre *Gretun, linkInfo *nl.RtAttr) {
  3177  	data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
  3178  
  3179  	if gre.FlowBased {
  3180  		// In flow based mode, no other attributes need to be configured
  3181  		data.AddRtAttr(nl.IFLA_GRE_COLLECT_METADATA, []byte{})
  3182  		return
  3183  	}
  3184  
  3185  	if ip := gre.Local; ip != nil {
  3186  		if ip.To4() != nil {
  3187  			ip = ip.To4()
  3188  		}
  3189  		data.AddRtAttr(nl.IFLA_GRE_LOCAL, []byte(ip))
  3190  	}
  3191  
  3192  	if ip := gre.Remote; ip != nil {
  3193  		if ip.To4() != nil {
  3194  			ip = ip.To4()
  3195  		}
  3196  		data.AddRtAttr(nl.IFLA_GRE_REMOTE, []byte(ip))
  3197  	}
  3198  
  3199  	if gre.IKey != 0 {
  3200  		data.AddRtAttr(nl.IFLA_GRE_IKEY, htonl(gre.IKey))
  3201  		gre.IFlags |= uint16(nl.GRE_KEY)
  3202  	}
  3203  
  3204  	if gre.OKey != 0 {
  3205  		data.AddRtAttr(nl.IFLA_GRE_OKEY, htonl(gre.OKey))
  3206  		gre.OFlags |= uint16(nl.GRE_KEY)
  3207  	}
  3208  
  3209  	data.AddRtAttr(nl.IFLA_GRE_IFLAGS, htons(gre.IFlags))
  3210  	data.AddRtAttr(nl.IFLA_GRE_OFLAGS, htons(gre.OFlags))
  3211  
  3212  	if gre.Link != 0 {
  3213  		data.AddRtAttr(nl.IFLA_GRE_LINK, nl.Uint32Attr(gre.Link))
  3214  	}
  3215  
  3216  	data.AddRtAttr(nl.IFLA_GRE_PMTUDISC, nl.Uint8Attr(gre.PMtuDisc))
  3217  	data.AddRtAttr(nl.IFLA_GRE_TTL, nl.Uint8Attr(gre.Ttl))
  3218  	data.AddRtAttr(nl.IFLA_GRE_TOS, nl.Uint8Attr(gre.Tos))
  3219  	data.AddRtAttr(nl.IFLA_GRE_ENCAP_TYPE, nl.Uint16Attr(gre.EncapType))
  3220  	data.AddRtAttr(nl.IFLA_GRE_ENCAP_FLAGS, nl.Uint16Attr(gre.EncapFlags))
  3221  	data.AddRtAttr(nl.IFLA_GRE_ENCAP_SPORT, htons(gre.EncapSport))
  3222  	data.AddRtAttr(nl.IFLA_GRE_ENCAP_DPORT, htons(gre.EncapDport))
  3223  }
  3224  
  3225  func parseGretunData(link Link, data []syscall.NetlinkRouteAttr) {
  3226  	gre := link.(*Gretun)
  3227  	for _, datum := range data {
  3228  		switch datum.Attr.Type {
  3229  		case nl.IFLA_GRE_IKEY:
  3230  			gre.IKey = ntohl(datum.Value[0:4])
  3231  		case nl.IFLA_GRE_OKEY:
  3232  			gre.OKey = ntohl(datum.Value[0:4])
  3233  		case nl.IFLA_GRE_LOCAL:
  3234  			gre.Local = net.IP(datum.Value)
  3235  		case nl.IFLA_GRE_REMOTE:
  3236  			gre.Remote = net.IP(datum.Value)
  3237  		case nl.IFLA_GRE_IFLAGS:
  3238  			gre.IFlags = ntohs(datum.Value[0:2])
  3239  		case nl.IFLA_GRE_OFLAGS:
  3240  			gre.OFlags = ntohs(datum.Value[0:2])
  3241  		case nl.IFLA_GRE_TTL:
  3242  			gre.Ttl = uint8(datum.Value[0])
  3243  		case nl.IFLA_GRE_TOS:
  3244  			gre.Tos = uint8(datum.Value[0])
  3245  		case nl.IFLA_GRE_PMTUDISC:
  3246  			gre.PMtuDisc = uint8(datum.Value[0])
  3247  		case nl.IFLA_GRE_ENCAP_TYPE:
  3248  			gre.EncapType = native.Uint16(datum.Value[0:2])
  3249  		case nl.IFLA_GRE_ENCAP_FLAGS:
  3250  			gre.EncapFlags = native.Uint16(datum.Value[0:2])
  3251  		case nl.IFLA_GRE_ENCAP_SPORT:
  3252  			gre.EncapSport = ntohs(datum.Value[0:2])
  3253  		case nl.IFLA_GRE_ENCAP_DPORT:
  3254  			gre.EncapDport = ntohs(datum.Value[0:2])
  3255  		case nl.IFLA_GRE_COLLECT_METADATA:
  3256  			gre.FlowBased = true
  3257  		}
  3258  	}
  3259  }
  3260  
  3261  func addXdpAttrs(xdp *LinkXdp, req *nl.NetlinkRequest) {
  3262  	attrs := nl.NewRtAttr(unix.IFLA_XDP|unix.NLA_F_NESTED, nil)
  3263  	b := make([]byte, 4)
  3264  	native.PutUint32(b, uint32(xdp.Fd))
  3265  	attrs.AddRtAttr(nl.IFLA_XDP_FD, b)
  3266  	if xdp.Flags != 0 {
  3267  		b := make([]byte, 4)
  3268  		native.PutUint32(b, xdp.Flags)
  3269  		attrs.AddRtAttr(nl.IFLA_XDP_FLAGS, b)
  3270  	}
  3271  	req.AddData(attrs)
  3272  }
  3273  
  3274  func parseLinkXdp(data []byte) (*LinkXdp, error) {
  3275  	attrs, err := nl.ParseRouteAttr(data)
  3276  	if err != nil {
  3277  		return nil, err
  3278  	}
  3279  	xdp := &LinkXdp{}
  3280  	for _, attr := range attrs {
  3281  		switch attr.Attr.Type {
  3282  		case nl.IFLA_XDP_FD:
  3283  			xdp.Fd = int(native.Uint32(attr.Value[0:4]))
  3284  		case nl.IFLA_XDP_ATTACHED:
  3285  			xdp.AttachMode = uint32(attr.Value[0])
  3286  			xdp.Attached = xdp.AttachMode != 0
  3287  		case nl.IFLA_XDP_FLAGS:
  3288  			xdp.Flags = native.Uint32(attr.Value[0:4])
  3289  		case nl.IFLA_XDP_PROG_ID:
  3290  			xdp.ProgId = native.Uint32(attr.Value[0:4])
  3291  		}
  3292  	}
  3293  	return xdp, nil
  3294  }
  3295  
  3296  func addIptunAttrs(iptun *Iptun, linkInfo *nl.RtAttr) {
  3297  	data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
  3298  
  3299  	if iptun.FlowBased {
  3300  		// In flow based mode, no other attributes need to be configured
  3301  		data.AddRtAttr(nl.IFLA_IPTUN_COLLECT_METADATA, []byte{})
  3302  		return
  3303  	}
  3304  
  3305  	ip := iptun.Local.To4()
  3306  	if ip != nil {
  3307  		data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip))
  3308  	}
  3309  
  3310  	ip = iptun.Remote.To4()
  3311  	if ip != nil {
  3312  		data.AddRtAttr(nl.IFLA_IPTUN_REMOTE, []byte(ip))
  3313  	}
  3314  
  3315  	if iptun.Link != 0 {
  3316  		data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(iptun.Link))
  3317  	}
  3318  	data.AddRtAttr(nl.IFLA_IPTUN_PMTUDISC, nl.Uint8Attr(iptun.PMtuDisc))
  3319  	data.AddRtAttr(nl.IFLA_IPTUN_TTL, nl.Uint8Attr(iptun.Ttl))
  3320  	data.AddRtAttr(nl.IFLA_IPTUN_TOS, nl.Uint8Attr(iptun.Tos))
  3321  	data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_TYPE, nl.Uint16Attr(iptun.EncapType))
  3322  	data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_FLAGS, nl.Uint16Attr(iptun.EncapFlags))
  3323  	data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_SPORT, htons(iptun.EncapSport))
  3324  	data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_DPORT, htons(iptun.EncapDport))
  3325  	data.AddRtAttr(nl.IFLA_IPTUN_PROTO, nl.Uint8Attr(iptun.Proto))
  3326  }
  3327  
  3328  func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) {
  3329  	iptun := link.(*Iptun)
  3330  	for _, datum := range data {
  3331  		switch datum.Attr.Type {
  3332  		case nl.IFLA_IPTUN_LOCAL:
  3333  			iptun.Local = net.IP(datum.Value[0:4])
  3334  		case nl.IFLA_IPTUN_REMOTE:
  3335  			iptun.Remote = net.IP(datum.Value[0:4])
  3336  		case nl.IFLA_IPTUN_TTL:
  3337  			iptun.Ttl = uint8(datum.Value[0])
  3338  		case nl.IFLA_IPTUN_TOS:
  3339  			iptun.Tos = uint8(datum.Value[0])
  3340  		case nl.IFLA_IPTUN_PMTUDISC:
  3341  			iptun.PMtuDisc = uint8(datum.Value[0])
  3342  		case nl.IFLA_IPTUN_ENCAP_SPORT:
  3343  			iptun.EncapSport = ntohs(datum.Value[0:2])
  3344  		case nl.IFLA_IPTUN_ENCAP_DPORT:
  3345  			iptun.EncapDport = ntohs(datum.Value[0:2])
  3346  		case nl.IFLA_IPTUN_ENCAP_TYPE:
  3347  			iptun.EncapType = native.Uint16(datum.Value[0:2])
  3348  		case nl.IFLA_IPTUN_ENCAP_FLAGS:
  3349  			iptun.EncapFlags = native.Uint16(datum.Value[0:2])
  3350  		case nl.IFLA_IPTUN_COLLECT_METADATA:
  3351  			iptun.FlowBased = true
  3352  		case nl.IFLA_IPTUN_PROTO:
  3353  			iptun.Proto = datum.Value[0]
  3354  		}
  3355  	}
  3356  }
  3357  
  3358  func addIp6tnlAttrs(ip6tnl *Ip6tnl, linkInfo *nl.RtAttr) {
  3359  	data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
  3360  
  3361  	if ip6tnl.FlowBased {
  3362  		// In flow based mode, no other attributes need to be configured
  3363  		data.AddRtAttr(nl.IFLA_IPTUN_COLLECT_METADATA, []byte{})
  3364  		return
  3365  	}
  3366  
  3367  	if ip6tnl.Link != 0 {
  3368  		data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(ip6tnl.Link))
  3369  	}
  3370  
  3371  	ip := ip6tnl.Local.To16()
  3372  	if ip != nil {
  3373  		data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip))
  3374  	}
  3375  
  3376  	ip = ip6tnl.Remote.To16()
  3377  	if ip != nil {
  3378  		data.AddRtAttr(nl.IFLA_IPTUN_REMOTE, []byte(ip))
  3379  	}
  3380  
  3381  	data.AddRtAttr(nl.IFLA_IPTUN_TTL, nl.Uint8Attr(ip6tnl.Ttl))
  3382  	data.AddRtAttr(nl.IFLA_IPTUN_TOS, nl.Uint8Attr(ip6tnl.Tos))
  3383  	data.AddRtAttr(nl.IFLA_IPTUN_FLAGS, nl.Uint32Attr(ip6tnl.Flags))
  3384  	data.AddRtAttr(nl.IFLA_IPTUN_PROTO, nl.Uint8Attr(ip6tnl.Proto))
  3385  	data.AddRtAttr(nl.IFLA_IPTUN_FLOWINFO, nl.Uint32Attr(ip6tnl.FlowInfo))
  3386  	data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_LIMIT, nl.Uint8Attr(ip6tnl.EncapLimit))
  3387  	data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_TYPE, nl.Uint16Attr(ip6tnl.EncapType))
  3388  	data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_FLAGS, nl.Uint16Attr(ip6tnl.EncapFlags))
  3389  	data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_SPORT, htons(ip6tnl.EncapSport))
  3390  	data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_DPORT, htons(ip6tnl.EncapDport))
  3391  }
  3392  
  3393  func parseIp6tnlData(link Link, data []syscall.NetlinkRouteAttr) {
  3394  	ip6tnl := link.(*Ip6tnl)
  3395  	for _, datum := range data {
  3396  		switch datum.Attr.Type {
  3397  		case nl.IFLA_IPTUN_LOCAL:
  3398  			ip6tnl.Local = net.IP(datum.Value[:16])
  3399  		case nl.IFLA_IPTUN_REMOTE:
  3400  			ip6tnl.Remote = net.IP(datum.Value[:16])
  3401  		case nl.IFLA_IPTUN_TTL:
  3402  			ip6tnl.Ttl = datum.Value[0]
  3403  		case nl.IFLA_IPTUN_TOS:
  3404  			ip6tnl.Tos = datum.Value[0]
  3405  		case nl.IFLA_IPTUN_FLAGS:
  3406  			ip6tnl.Flags = native.Uint32(datum.Value[:4])
  3407  		case nl.IFLA_IPTUN_PROTO:
  3408  			ip6tnl.Proto = datum.Value[0]
  3409  		case nl.IFLA_IPTUN_FLOWINFO:
  3410  			ip6tnl.FlowInfo = native.Uint32(datum.Value[:4])
  3411  		case nl.IFLA_IPTUN_ENCAP_LIMIT:
  3412  			ip6tnl.EncapLimit = datum.Value[0]
  3413  		case nl.IFLA_IPTUN_ENCAP_TYPE:
  3414  			ip6tnl.EncapType = native.Uint16(datum.Value[0:2])
  3415  		case nl.IFLA_IPTUN_ENCAP_FLAGS:
  3416  			ip6tnl.EncapFlags = native.Uint16(datum.Value[0:2])
  3417  		case nl.IFLA_IPTUN_ENCAP_SPORT:
  3418  			ip6tnl.EncapSport = ntohs(datum.Value[0:2])
  3419  		case nl.IFLA_IPTUN_ENCAP_DPORT:
  3420  			ip6tnl.EncapDport = ntohs(datum.Value[0:2])
  3421  		case nl.IFLA_IPTUN_COLLECT_METADATA:
  3422  			ip6tnl.FlowBased = true
  3423  		}
  3424  	}
  3425  }
  3426  
  3427  func addSittunAttrs(sittun *Sittun, linkInfo *nl.RtAttr) {
  3428  	data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
  3429  
  3430  	if sittun.Link != 0 {
  3431  		data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(sittun.Link))
  3432  	}
  3433  
  3434  	ip := sittun.Local.To4()
  3435  	if ip != nil {
  3436  		data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip))
  3437  	}
  3438  
  3439  	ip = sittun.Remote.To4()
  3440  	if ip != nil {
  3441  		data.AddRtAttr(nl.IFLA_IPTUN_REMOTE, []byte(ip))
  3442  	}
  3443  
  3444  	if sittun.Ttl > 0 {
  3445  		// Would otherwise fail on 3.10 kernel
  3446  		data.AddRtAttr(nl.IFLA_IPTUN_TTL, nl.Uint8Attr(sittun.Ttl))
  3447  	}
  3448  
  3449  	data.AddRtAttr(nl.IFLA_IPTUN_PROTO, nl.Uint8Attr(sittun.Proto))
  3450  	data.AddRtAttr(nl.IFLA_IPTUN_TOS, nl.Uint8Attr(sittun.Tos))
  3451  	data.AddRtAttr(nl.IFLA_IPTUN_PMTUDISC, nl.Uint8Attr(sittun.PMtuDisc))
  3452  	data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_LIMIT, nl.Uint8Attr(sittun.EncapLimit))
  3453  	data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_TYPE, nl.Uint16Attr(sittun.EncapType))
  3454  	data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_FLAGS, nl.Uint16Attr(sittun.EncapFlags))
  3455  	data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_SPORT, htons(sittun.EncapSport))
  3456  	data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_DPORT, htons(sittun.EncapDport))
  3457  }
  3458  
  3459  func parseSittunData(link Link, data []syscall.NetlinkRouteAttr) {
  3460  	sittun := link.(*Sittun)
  3461  	for _, datum := range data {
  3462  		switch datum.Attr.Type {
  3463  		case nl.IFLA_IPTUN_LOCAL:
  3464  			sittun.Local = net.IP(datum.Value[0:4])
  3465  		case nl.IFLA_IPTUN_REMOTE:
  3466  			sittun.Remote = net.IP(datum.Value[0:4])
  3467  		case nl.IFLA_IPTUN_TTL:
  3468  			sittun.Ttl = datum.Value[0]
  3469  		case nl.IFLA_IPTUN_TOS:
  3470  			sittun.Tos = datum.Value[0]
  3471  		case nl.IFLA_IPTUN_PMTUDISC:
  3472  			sittun.PMtuDisc = datum.Value[0]
  3473  		case nl.IFLA_IPTUN_PROTO:
  3474  			sittun.Proto = datum.Value[0]
  3475  		case nl.IFLA_IPTUN_ENCAP_TYPE:
  3476  			sittun.EncapType = native.Uint16(datum.Value[0:2])
  3477  		case nl.IFLA_IPTUN_ENCAP_FLAGS:
  3478  			sittun.EncapFlags = native.Uint16(datum.Value[0:2])
  3479  		case nl.IFLA_IPTUN_ENCAP_SPORT:
  3480  			sittun.EncapSport = ntohs(datum.Value[0:2])
  3481  		case nl.IFLA_IPTUN_ENCAP_DPORT:
  3482  			sittun.EncapDport = ntohs(datum.Value[0:2])
  3483  		}
  3484  	}
  3485  }
  3486  
  3487  func addVtiAttrs(vti *Vti, linkInfo *nl.RtAttr) {
  3488  	data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
  3489  
  3490  	family := FAMILY_V4
  3491  	if vti.Local.To4() == nil {
  3492  		family = FAMILY_V6
  3493  	}
  3494  
  3495  	var ip net.IP
  3496  
  3497  	if family == FAMILY_V4 {
  3498  		ip = vti.Local.To4()
  3499  	} else {
  3500  		ip = vti.Local
  3501  	}
  3502  	if ip != nil {
  3503  		data.AddRtAttr(nl.IFLA_VTI_LOCAL, []byte(ip))
  3504  	}
  3505  
  3506  	if family == FAMILY_V4 {
  3507  		ip = vti.Remote.To4()
  3508  	} else {
  3509  		ip = vti.Remote
  3510  	}
  3511  	if ip != nil {
  3512  		data.AddRtAttr(nl.IFLA_VTI_REMOTE, []byte(ip))
  3513  	}
  3514  
  3515  	if vti.Link != 0 {
  3516  		data.AddRtAttr(nl.IFLA_VTI_LINK, nl.Uint32Attr(vti.Link))
  3517  	}
  3518  
  3519  	data.AddRtAttr(nl.IFLA_VTI_IKEY, htonl(vti.IKey))
  3520  	data.AddRtAttr(nl.IFLA_VTI_OKEY, htonl(vti.OKey))
  3521  }
  3522  
  3523  func parseVtiData(link Link, data []syscall.NetlinkRouteAttr) {
  3524  	vti := link.(*Vti)
  3525  	for _, datum := range data {
  3526  		switch datum.Attr.Type {
  3527  		case nl.IFLA_VTI_LOCAL:
  3528  			vti.Local = net.IP(datum.Value)
  3529  		case nl.IFLA_VTI_REMOTE:
  3530  			vti.Remote = net.IP(datum.Value)
  3531  		case nl.IFLA_VTI_IKEY:
  3532  			vti.IKey = ntohl(datum.Value[0:4])
  3533  		case nl.IFLA_VTI_OKEY:
  3534  			vti.OKey = ntohl(datum.Value[0:4])
  3535  		}
  3536  	}
  3537  }
  3538  
  3539  func addVrfAttrs(vrf *Vrf, linkInfo *nl.RtAttr) {
  3540  	data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
  3541  	b := make([]byte, 4)
  3542  	native.PutUint32(b, uint32(vrf.Table))
  3543  	data.AddRtAttr(nl.IFLA_VRF_TABLE, b)
  3544  }
  3545  
  3546  func parseVrfData(link Link, data []syscall.NetlinkRouteAttr) {
  3547  	vrf := link.(*Vrf)
  3548  	for _, datum := range data {
  3549  		switch datum.Attr.Type {
  3550  		case nl.IFLA_VRF_TABLE:
  3551  			vrf.Table = native.Uint32(datum.Value[0:4])
  3552  		}
  3553  	}
  3554  }
  3555  
  3556  func addBridgeAttrs(bridge *Bridge, linkInfo *nl.RtAttr) {
  3557  	data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
  3558  	if bridge.MulticastSnooping != nil {
  3559  		data.AddRtAttr(nl.IFLA_BR_MCAST_SNOOPING, boolToByte(*bridge.MulticastSnooping))
  3560  	}
  3561  	if bridge.AgeingTime != nil {
  3562  		data.AddRtAttr(nl.IFLA_BR_AGEING_TIME, nl.Uint32Attr(*bridge.AgeingTime))
  3563  	}
  3564  	if bridge.HelloTime != nil {
  3565  		data.AddRtAttr(nl.IFLA_BR_HELLO_TIME, nl.Uint32Attr(*bridge.HelloTime))
  3566  	}
  3567  	if bridge.VlanFiltering != nil {
  3568  		data.AddRtAttr(nl.IFLA_BR_VLAN_FILTERING, boolToByte(*bridge.VlanFiltering))
  3569  	}
  3570  	if bridge.VlanDefaultPVID != nil {
  3571  		data.AddRtAttr(nl.IFLA_BR_VLAN_DEFAULT_PVID, nl.Uint16Attr(*bridge.VlanDefaultPVID))
  3572  	}
  3573  	if bridge.GroupFwdMask != nil {
  3574  		data.AddRtAttr(nl.IFLA_BR_GROUP_FWD_MASK, nl.Uint16Attr(*bridge.GroupFwdMask))
  3575  	}
  3576  }
  3577  
  3578  func parseBridgeData(bridge Link, data []syscall.NetlinkRouteAttr) {
  3579  	br := bridge.(*Bridge)
  3580  	for _, datum := range data {
  3581  		switch datum.Attr.Type {
  3582  		case nl.IFLA_BR_AGEING_TIME:
  3583  			ageingTime := native.Uint32(datum.Value[0:4])
  3584  			br.AgeingTime = &ageingTime
  3585  		case nl.IFLA_BR_HELLO_TIME:
  3586  			helloTime := native.Uint32(datum.Value[0:4])
  3587  			br.HelloTime = &helloTime
  3588  		case nl.IFLA_BR_MCAST_SNOOPING:
  3589  			mcastSnooping := datum.Value[0] == 1
  3590  			br.MulticastSnooping = &mcastSnooping
  3591  		case nl.IFLA_BR_VLAN_FILTERING:
  3592  			vlanFiltering := datum.Value[0] == 1
  3593  			br.VlanFiltering = &vlanFiltering
  3594  		case nl.IFLA_BR_VLAN_DEFAULT_PVID:
  3595  			vlanDefaultPVID := native.Uint16(datum.Value[0:2])
  3596  			br.VlanDefaultPVID = &vlanDefaultPVID
  3597  		case nl.IFLA_BR_GROUP_FWD_MASK:
  3598  			mask := native.Uint16(datum.Value[0:2])
  3599  			br.GroupFwdMask = &mask
  3600  		}
  3601  	}
  3602  }
  3603  
  3604  func addGTPAttrs(gtp *GTP, linkInfo *nl.RtAttr) {
  3605  	data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
  3606  	data.AddRtAttr(nl.IFLA_GTP_FD0, nl.Uint32Attr(uint32(gtp.FD0)))
  3607  	data.AddRtAttr(nl.IFLA_GTP_FD1, nl.Uint32Attr(uint32(gtp.FD1)))
  3608  	data.AddRtAttr(nl.IFLA_GTP_PDP_HASHSIZE, nl.Uint32Attr(131072))
  3609  	if gtp.Role != nl.GTP_ROLE_GGSN {
  3610  		data.AddRtAttr(nl.IFLA_GTP_ROLE, nl.Uint32Attr(uint32(gtp.Role)))
  3611  	}
  3612  }
  3613  
  3614  func parseGTPData(link Link, data []syscall.NetlinkRouteAttr) {
  3615  	gtp := link.(*GTP)
  3616  	for _, datum := range data {
  3617  		switch datum.Attr.Type {
  3618  		case nl.IFLA_GTP_FD0:
  3619  			gtp.FD0 = int(native.Uint32(datum.Value))
  3620  		case nl.IFLA_GTP_FD1:
  3621  			gtp.FD1 = int(native.Uint32(datum.Value))
  3622  		case nl.IFLA_GTP_PDP_HASHSIZE:
  3623  			gtp.PDPHashsize = int(native.Uint32(datum.Value))
  3624  		case nl.IFLA_GTP_ROLE:
  3625  			gtp.Role = int(native.Uint32(datum.Value))
  3626  		}
  3627  	}
  3628  }
  3629  
  3630  func parseVfInfoList(data []syscall.NetlinkRouteAttr) ([]VfInfo, error) {
  3631  	var vfs []VfInfo
  3632  
  3633  	for i, element := range data {
  3634  		if element.Attr.Type != nl.IFLA_VF_INFO {
  3635  			return nil, fmt.Errorf("Incorrect element type in vf info list: %d", element.Attr.Type)
  3636  		}
  3637  		vfAttrs, err := nl.ParseRouteAttr(element.Value)
  3638  		if err != nil {
  3639  			return nil, err
  3640  		}
  3641  
  3642  		vf, err := parseVfInfo(vfAttrs, i)
  3643  		if err != nil {
  3644  			return nil, err
  3645  		}
  3646  		vfs = append(vfs, vf)
  3647  	}
  3648  	return vfs, nil
  3649  }
  3650  
  3651  func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) (VfInfo, error) {
  3652  	vf := VfInfo{ID: id}
  3653  	for _, element := range data {
  3654  		switch element.Attr.Type {
  3655  		case nl.IFLA_VF_MAC:
  3656  			mac := nl.DeserializeVfMac(element.Value[:])
  3657  			vf.Mac = mac.Mac[:6]
  3658  		case nl.IFLA_VF_VLAN:
  3659  			vl := nl.DeserializeVfVlan(element.Value[:])
  3660  			vf.Vlan = int(vl.Vlan)
  3661  			vf.Qos = int(vl.Qos)
  3662  		case nl.IFLA_VF_VLAN_LIST:
  3663  			vfVlanInfoList, err := nl.DeserializeVfVlanList(element.Value[:])
  3664  			if err != nil {
  3665  				return vf, err
  3666  			}
  3667  			vf.VlanProto = int(vfVlanInfoList[0].VlanProto)
  3668  		case nl.IFLA_VF_TX_RATE:
  3669  			txr := nl.DeserializeVfTxRate(element.Value[:])
  3670  			vf.TxRate = int(txr.Rate)
  3671  		case nl.IFLA_VF_SPOOFCHK:
  3672  			sp := nl.DeserializeVfSpoofchk(element.Value[:])
  3673  			vf.Spoofchk = sp.Setting != 0
  3674  		case nl.IFLA_VF_LINK_STATE:
  3675  			ls := nl.DeserializeVfLinkState(element.Value[:])
  3676  			vf.LinkState = ls.LinkState
  3677  		case nl.IFLA_VF_RATE:
  3678  			vfr := nl.DeserializeVfRate(element.Value[:])
  3679  			vf.MaxTxRate = vfr.MaxTxRate
  3680  			vf.MinTxRate = vfr.MinTxRate
  3681  		case nl.IFLA_VF_STATS:
  3682  			vfstats := nl.DeserializeVfStats(element.Value[:])
  3683  			vf.RxPackets = vfstats.RxPackets
  3684  			vf.TxPackets = vfstats.TxPackets
  3685  			vf.RxBytes = vfstats.RxBytes
  3686  			vf.TxBytes = vfstats.TxBytes
  3687  			vf.Multicast = vfstats.Multicast
  3688  			vf.Broadcast = vfstats.Broadcast
  3689  			vf.RxDropped = vfstats.RxDropped
  3690  			vf.TxDropped = vfstats.TxDropped
  3691  
  3692  		case nl.IFLA_VF_RSS_QUERY_EN:
  3693  			result := nl.DeserializeVfRssQueryEn(element.Value)
  3694  			vf.RssQuery = result.Setting
  3695  
  3696  		case nl.IFLA_VF_TRUST:
  3697  			result := nl.DeserializeVfTrust(element.Value)
  3698  			vf.Trust = result.Setting
  3699  		}
  3700  	}
  3701  	return vf, nil
  3702  }
  3703  
  3704  func addXfrmiAttrs(xfrmi *Xfrmi, linkInfo *nl.RtAttr) {
  3705  	data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
  3706  	data.AddRtAttr(nl.IFLA_XFRM_LINK, nl.Uint32Attr(uint32(xfrmi.ParentIndex)))
  3707  	if xfrmi.Ifid != 0 {
  3708  		data.AddRtAttr(nl.IFLA_XFRM_IF_ID, nl.Uint32Attr(xfrmi.Ifid))
  3709  	}
  3710  }
  3711  
  3712  func parseXfrmiData(link Link, data []syscall.NetlinkRouteAttr) {
  3713  	xfrmi := link.(*Xfrmi)
  3714  	for _, datum := range data {
  3715  		switch datum.Attr.Type {
  3716  		case nl.IFLA_XFRM_LINK:
  3717  			xfrmi.ParentIndex = int(native.Uint32(datum.Value))
  3718  		case nl.IFLA_XFRM_IF_ID:
  3719  			xfrmi.Ifid = native.Uint32(datum.Value)
  3720  		}
  3721  	}
  3722  }
  3723  
  3724  func ioctlBondSlave(cmd uintptr, link Link, master *Bond) error {
  3725  	fd, err := getSocketUDP()
  3726  	if err != nil {
  3727  		return err
  3728  	}
  3729  	defer syscall.Close(fd)
  3730  
  3731  	ifreq := newIocltSlaveReq(link.Attrs().Name, master.Attrs().Name)
  3732  	_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), cmd, uintptr(unsafe.Pointer(ifreq)))
  3733  	if errno != 0 {
  3734  		return fmt.Errorf("errno=%v", errno)
  3735  	}
  3736  	return nil
  3737  }
  3738  
  3739  // LinkSetBondSlaveActive sets specified slave to ACTIVE in an `active-backup` bond link via ioctl interface.
  3740  //
  3741  //	Multiple calls keeps the status unchanged(shown in the unit test).
  3742  func LinkSetBondSlaveActive(link Link, master *Bond) error {
  3743  	err := ioctlBondSlave(unix.SIOCBONDCHANGEACTIVE, link, master)
  3744  	if err != nil {
  3745  		return fmt.Errorf("Failed to set slave %q active in %q, %v", link.Attrs().Name, master.Attrs().Name, err)
  3746  	}
  3747  	return nil
  3748  }
  3749  
  3750  // LinkSetBondSlave add slave to bond link via ioctl interface.
  3751  func LinkSetBondSlave(link Link, master *Bond) error {
  3752  	err := ioctlBondSlave(unix.SIOCBONDENSLAVE, link, master)
  3753  	if err != nil {
  3754  		return fmt.Errorf("Failed to enslave %q to %q, %v", link.Attrs().Name, master.Attrs().Name, err)
  3755  	}
  3756  	return nil
  3757  }
  3758  
  3759  // LinkSetBondSlave removes specified slave from bond link via ioctl interface.
  3760  func LinkDelBondSlave(link Link, master *Bond) error {
  3761  	err := ioctlBondSlave(unix.SIOCBONDRELEASE, link, master)
  3762  	if err != nil {
  3763  		return fmt.Errorf("Failed to del slave %q from %q, %v", link.Attrs().Name, master.Attrs().Name, err)
  3764  	}
  3765  	return nil
  3766  }
  3767  
  3768  // LinkSetBondSlaveQueueId modify bond slave queue-id.
  3769  func (h *Handle) LinkSetBondSlaveQueueId(link Link, queueId uint16) error {
  3770  	base := link.Attrs()
  3771  	h.ensureIndex(base)
  3772  	req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
  3773  
  3774  	msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
  3775  	msg.Index = int32(base.Index)
  3776  	req.AddData(msg)
  3777  
  3778  	linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil)
  3779  	data := linkInfo.AddRtAttr(nl.IFLA_INFO_SLAVE_DATA, nil)
  3780  	data.AddRtAttr(nl.IFLA_BOND_SLAVE_QUEUE_ID, nl.Uint16Attr(queueId))
  3781  
  3782  	req.AddData(linkInfo)
  3783  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
  3784  	return err
  3785  }
  3786  
  3787  // LinkSetBondSlaveQueueId modify bond slave queue-id.
  3788  func LinkSetBondSlaveQueueId(link Link, queueId uint16) error {
  3789  	return pkgHandle.LinkSetBondSlaveQueueId(link, queueId)
  3790  }
  3791  
  3792  func vethStatsSerialize(stats ethtoolStats) ([]byte, error) {
  3793  	statsSize := int(unsafe.Sizeof(stats)) + int(stats.nStats)*int(unsafe.Sizeof(uint64(0)))
  3794  	b := make([]byte, 0, statsSize)
  3795  	buf := bytes.NewBuffer(b)
  3796  	err := binary.Write(buf, nl.NativeEndian(), stats)
  3797  	return buf.Bytes()[:statsSize], err
  3798  }
  3799  
  3800  type vethEthtoolStats struct {
  3801  	Cmd    uint32
  3802  	NStats uint32
  3803  	Peer   uint64
  3804  	// Newer kernels have XDP stats in here, but we only care
  3805  	// to extract the peer ifindex here.
  3806  }
  3807  
  3808  func vethStatsDeserialize(b []byte) (vethEthtoolStats, error) {
  3809  	var stats = vethEthtoolStats{}
  3810  	err := binary.Read(bytes.NewReader(b), nl.NativeEndian(), &stats)
  3811  	return stats, err
  3812  }
  3813  
  3814  // VethPeerIndex get veth peer index.
  3815  func VethPeerIndex(link *Veth) (int, error) {
  3816  	fd, err := getSocketUDP()
  3817  	if err != nil {
  3818  		return -1, err
  3819  	}
  3820  	defer syscall.Close(fd)
  3821  
  3822  	ifreq, sSet := newIocltStringSetReq(link.Name)
  3823  	_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), SIOCETHTOOL, uintptr(unsafe.Pointer(ifreq)))
  3824  	if errno != 0 {
  3825  		return -1, fmt.Errorf("SIOCETHTOOL request for %q failed, errno=%v", link.Attrs().Name, errno)
  3826  	}
  3827  
  3828  	stats := ethtoolStats{
  3829  		cmd:    ETHTOOL_GSTATS,
  3830  		nStats: sSet.data[0],
  3831  	}
  3832  
  3833  	buffer, err := vethStatsSerialize(stats)
  3834  	if err != nil {
  3835  		return -1, err
  3836  	}
  3837  
  3838  	ifreq.Data = uintptr(unsafe.Pointer(&buffer[0]))
  3839  	_, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), SIOCETHTOOL, uintptr(unsafe.Pointer(ifreq)))
  3840  	if errno != 0 {
  3841  		return -1, fmt.Errorf("SIOCETHTOOL request for %q failed, errno=%v", link.Attrs().Name, errno)
  3842  	}
  3843  
  3844  	vstats, err := vethStatsDeserialize(buffer)
  3845  	if err != nil {
  3846  		return -1, err
  3847  	}
  3848  
  3849  	return int(vstats.Peer), nil
  3850  }
  3851  
  3852  func parseTuntapData(link Link, data []syscall.NetlinkRouteAttr) {
  3853  	tuntap := link.(*Tuntap)
  3854  	for _, datum := range data {
  3855  		switch datum.Attr.Type {
  3856  		case nl.IFLA_TUN_OWNER:
  3857  			tuntap.Owner = native.Uint32(datum.Value)
  3858  		case nl.IFLA_TUN_GROUP:
  3859  			tuntap.Group = native.Uint32(datum.Value)
  3860  		case nl.IFLA_TUN_TYPE:
  3861  			tuntap.Mode = TuntapMode(uint8(datum.Value[0]))
  3862  		case nl.IFLA_TUN_PERSIST:
  3863  			tuntap.NonPersist = false
  3864  			if uint8(datum.Value[0]) == 0 {
  3865  				tuntap.NonPersist = true
  3866  			}
  3867  		}
  3868  	}
  3869  }
  3870  
  3871  func parseIPoIBData(link Link, data []syscall.NetlinkRouteAttr) {
  3872  	ipoib := link.(*IPoIB)
  3873  	for _, datum := range data {
  3874  		switch datum.Attr.Type {
  3875  		case nl.IFLA_IPOIB_PKEY:
  3876  			ipoib.Pkey = uint16(native.Uint16(datum.Value))
  3877  		case nl.IFLA_IPOIB_MODE:
  3878  			ipoib.Mode = IPoIBMode(native.Uint16(datum.Value))
  3879  		case nl.IFLA_IPOIB_UMCAST:
  3880  			ipoib.Umcast = uint16(native.Uint16(datum.Value))
  3881  		}
  3882  	}
  3883  }
  3884  
  3885  func parseCanData(link Link, data []syscall.NetlinkRouteAttr) {
  3886  	can := link.(*Can)
  3887  	for _, datum := range data {
  3888  
  3889  		switch datum.Attr.Type {
  3890  		case nl.IFLA_CAN_BITTIMING:
  3891  			can.BitRate = native.Uint32(datum.Value)
  3892  			can.SamplePoint = native.Uint32(datum.Value[4:])
  3893  			can.TimeQuanta = native.Uint32(datum.Value[8:])
  3894  			can.PropagationSegment = native.Uint32(datum.Value[12:])
  3895  			can.PhaseSegment1 = native.Uint32(datum.Value[16:])
  3896  			can.PhaseSegment2 = native.Uint32(datum.Value[20:])
  3897  			can.SyncJumpWidth = native.Uint32(datum.Value[24:])
  3898  			can.BitRatePreScaler = native.Uint32(datum.Value[28:])
  3899  		case nl.IFLA_CAN_BITTIMING_CONST:
  3900  			can.Name = string(datum.Value[:16])
  3901  			can.TimeSegment1Min = native.Uint32(datum.Value[16:])
  3902  			can.TimeSegment1Max = native.Uint32(datum.Value[20:])
  3903  			can.TimeSegment2Min = native.Uint32(datum.Value[24:])
  3904  			can.TimeSegment2Max = native.Uint32(datum.Value[28:])
  3905  			can.SyncJumpWidthMax = native.Uint32(datum.Value[32:])
  3906  			can.BitRatePreScalerMin = native.Uint32(datum.Value[36:])
  3907  			can.BitRatePreScalerMax = native.Uint32(datum.Value[40:])
  3908  			can.BitRatePreScalerInc = native.Uint32(datum.Value[44:])
  3909  		case nl.IFLA_CAN_CLOCK:
  3910  			can.ClockFrequency = native.Uint32(datum.Value)
  3911  		case nl.IFLA_CAN_STATE:
  3912  			can.State = native.Uint32(datum.Value)
  3913  		case nl.IFLA_CAN_CTRLMODE:
  3914  			can.Mask = native.Uint32(datum.Value)
  3915  			can.Flags = native.Uint32(datum.Value[4:])
  3916  		case nl.IFLA_CAN_BERR_COUNTER:
  3917  			can.TxError = native.Uint16(datum.Value)
  3918  			can.RxError = native.Uint16(datum.Value[2:])
  3919  		case nl.IFLA_CAN_RESTART_MS:
  3920  			can.RestartMs = native.Uint32(datum.Value)
  3921  		case nl.IFLA_CAN_DATA_BITTIMING_CONST:
  3922  		case nl.IFLA_CAN_RESTART:
  3923  		case nl.IFLA_CAN_DATA_BITTIMING:
  3924  		case nl.IFLA_CAN_TERMINATION:
  3925  		case nl.IFLA_CAN_TERMINATION_CONST:
  3926  		case nl.IFLA_CAN_BITRATE_CONST:
  3927  		case nl.IFLA_CAN_DATA_BITRATE_CONST:
  3928  		case nl.IFLA_CAN_BITRATE_MAX:
  3929  		}
  3930  	}
  3931  }
  3932  
  3933  func addIPoIBAttrs(ipoib *IPoIB, linkInfo *nl.RtAttr) {
  3934  	data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
  3935  	data.AddRtAttr(nl.IFLA_IPOIB_PKEY, nl.Uint16Attr(uint16(ipoib.Pkey)))
  3936  	data.AddRtAttr(nl.IFLA_IPOIB_MODE, nl.Uint16Attr(uint16(ipoib.Mode)))
  3937  	data.AddRtAttr(nl.IFLA_IPOIB_UMCAST, nl.Uint16Attr(uint16(ipoib.Umcast)))
  3938  }
  3939  
  3940  func addBareUDPAttrs(bareudp *BareUDP, linkInfo *nl.RtAttr) {
  3941  	data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
  3942  
  3943  	data.AddRtAttr(nl.IFLA_BAREUDP_PORT, nl.Uint16Attr(nl.Swap16(bareudp.Port)))
  3944  	data.AddRtAttr(nl.IFLA_BAREUDP_ETHERTYPE, nl.Uint16Attr(nl.Swap16(bareudp.EtherType)))
  3945  	if bareudp.SrcPortMin != 0 {
  3946  		data.AddRtAttr(nl.IFLA_BAREUDP_SRCPORT_MIN, nl.Uint16Attr(bareudp.SrcPortMin))
  3947  	}
  3948  	if bareudp.MultiProto {
  3949  		data.AddRtAttr(nl.IFLA_BAREUDP_MULTIPROTO_MODE, []byte{})
  3950  	}
  3951  }
  3952  
  3953  func parseBareUDPData(link Link, data []syscall.NetlinkRouteAttr) {
  3954  	bareudp := link.(*BareUDP)
  3955  	for _, attr := range data {
  3956  		switch attr.Attr.Type {
  3957  		case nl.IFLA_BAREUDP_PORT:
  3958  			bareudp.Port = binary.BigEndian.Uint16(attr.Value)
  3959  		case nl.IFLA_BAREUDP_ETHERTYPE:
  3960  			bareudp.EtherType = binary.BigEndian.Uint16(attr.Value)
  3961  		case nl.IFLA_BAREUDP_SRCPORT_MIN:
  3962  			bareudp.SrcPortMin = native.Uint16(attr.Value)
  3963  		case nl.IFLA_BAREUDP_MULTIPROTO_MODE:
  3964  			bareudp.MultiProto = true
  3965  		}
  3966  	}
  3967  }