|
@@ -379,6 +379,74 @@ func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error {
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
+// LinkSetVfSpoofchk enables/disables spoof check on a vf for the link.
|
|
|
+// Equivalent to: `ip link set $link vf $vf spoofchk $check`
|
|
|
+func LinkSetVfSpoofchk(link Link, vf int, check bool) error {
|
|
|
+ return pkgHandle.LinkSetVfSpoofchk(link, vf, check)
|
|
|
+}
|
|
|
+
|
|
|
+// LinkSetVfSpookfchk enables/disables spoof check on a vf for the link.
|
|
|
+// Equivalent to: `ip link set $link vf $vf spoofchk $check`
|
|
|
+func (h *Handle) LinkSetVfSpoofchk(link Link, vf int, check bool) error {
|
|
|
+ var setting uint32
|
|
|
+ base := link.Attrs()
|
|
|
+ h.ensureIndex(base)
|
|
|
+ req := h.newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
|
|
|
+
|
|
|
+ msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
|
|
|
+ msg.Index = int32(base.Index)
|
|
|
+ req.AddData(msg)
|
|
|
+
|
|
|
+ data := nl.NewRtAttr(nl.IFLA_VFINFO_LIST, nil)
|
|
|
+ info := nl.NewRtAttrChild(data, nl.IFLA_VF_INFO, nil)
|
|
|
+ if check {
|
|
|
+ setting = 1
|
|
|
+ }
|
|
|
+ vfmsg := nl.VfSpoofchk{
|
|
|
+ Vf: uint32(vf),
|
|
|
+ Setting: setting,
|
|
|
+ }
|
|
|
+ nl.NewRtAttrChild(info, nl.IFLA_VF_SPOOFCHK, vfmsg.Serialize())
|
|
|
+ req.AddData(data)
|
|
|
+
|
|
|
+ _, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
|
|
+ return err
|
|
|
+}
|
|
|
+
|
|
|
+// LinkSetVfTrust enables/disables trust state on a vf for the link.
|
|
|
+// Equivalent to: `ip link set $link vf $vf trust $state`
|
|
|
+func LinkSetVfTrust(link Link, vf int, state bool) error {
|
|
|
+ return pkgHandle.LinkSetVfTrust(link, vf, state)
|
|
|
+}
|
|
|
+
|
|
|
+// LinkSetVfTrust enables/disables trust state on a vf for the link.
|
|
|
+// Equivalent to: `ip link set $link vf $vf trust $state`
|
|
|
+func (h *Handle) LinkSetVfTrust(link Link, vf int, state bool) error {
|
|
|
+ var setting uint32
|
|
|
+ base := link.Attrs()
|
|
|
+ h.ensureIndex(base)
|
|
|
+ req := h.newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
|
|
|
+
|
|
|
+ msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
|
|
|
+ msg.Index = int32(base.Index)
|
|
|
+ req.AddData(msg)
|
|
|
+
|
|
|
+ data := nl.NewRtAttr(nl.IFLA_VFINFO_LIST, nil)
|
|
|
+ info := nl.NewRtAttrChild(data, nl.IFLA_VF_INFO, nil)
|
|
|
+ if state {
|
|
|
+ setting = 1
|
|
|
+ }
|
|
|
+ vfmsg := nl.VfTrust{
|
|
|
+ Vf: uint32(vf),
|
|
|
+ Setting: setting,
|
|
|
+ }
|
|
|
+ nl.NewRtAttrChild(info, nl.IFLA_VF_TRUST, vfmsg.Serialize())
|
|
|
+ req.AddData(data)
|
|
|
+
|
|
|
+ _, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
|
|
+ return err
|
|
|
+}
|
|
|
+
|
|
|
// LinkSetMaster sets the master of the link device.
|
|
|
// Equivalent to: `ip link set $link master $master`
|
|
|
func LinkSetMaster(link Link, master *Bridge) error {
|
|
@@ -500,6 +568,12 @@ func (h *Handle) LinkSetNsFd(link Link, fd int) error {
|
|
|
// LinkSetXdpFd adds a bpf function to the driver. The fd must be a bpf
|
|
|
// program loaded with bpf(type=BPF_PROG_TYPE_XDP)
|
|
|
func LinkSetXdpFd(link Link, fd int) error {
|
|
|
+ return LinkSetXdpFdWithFlags(link, fd, 0)
|
|
|
+}
|
|
|
+
|
|
|
+// LinkSetXdpFdWithFlags adds a bpf function to the driver with the given
|
|
|
+// options. The fd must be a bpf program loaded with bpf(type=BPF_PROG_TYPE_XDP)
|
|
|
+func LinkSetXdpFdWithFlags(link Link, fd, flags int) error {
|
|
|
base := link.Attrs()
|
|
|
ensureIndex(base)
|
|
|
req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
|
|
@@ -508,7 +582,7 @@ func LinkSetXdpFd(link Link, fd int) error {
|
|
|
msg.Index = int32(base.Index)
|
|
|
req.AddData(msg)
|
|
|
|
|
|
- addXdpAttrs(&LinkXdp{Fd: fd}, req)
|
|
|
+ addXdpAttrs(&LinkXdp{Fd: fd, Flags: uint32(flags)}, req)
|
|
|
|
|
|
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
|
|
return err
|
|
@@ -528,7 +602,13 @@ type vxlanPortRange struct {
|
|
|
|
|
|
func addVxlanAttrs(vxlan *Vxlan, linkInfo *nl.RtAttr) {
|
|
|
data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
|
|
|
+
|
|
|
+ if vxlan.FlowBased {
|
|
|
+ vxlan.VxlanId = 0
|
|
|
+ }
|
|
|
+
|
|
|
nl.NewRtAttrChild(data, nl.IFLA_VXLAN_ID, nl.Uint32Attr(uint32(vxlan.VxlanId)))
|
|
|
+
|
|
|
if vxlan.VtepDevIndex != 0 {
|
|
|
nl.NewRtAttrChild(data, nl.IFLA_VXLAN_LINK, nl.Uint32Attr(uint32(vxlan.VtepDevIndex)))
|
|
|
}
|
|
@@ -569,6 +649,9 @@ func addVxlanAttrs(vxlan *Vxlan, linkInfo *nl.RtAttr) {
|
|
|
if vxlan.GBP {
|
|
|
nl.NewRtAttrChild(data, nl.IFLA_VXLAN_GBP, []byte{})
|
|
|
}
|
|
|
+ if vxlan.FlowBased {
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_VXLAN_FLOWBASED, boolAttr(vxlan.FlowBased))
|
|
|
+ }
|
|
|
if vxlan.NoAge {
|
|
|
nl.NewRtAttrChild(data, nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(0))
|
|
|
} else if vxlan.Age > 0 {
|
|
@@ -818,16 +901,17 @@ func (h *Handle) linkModify(link Link, flags int) error {
|
|
|
linkInfo := nl.NewRtAttr(syscall.IFLA_LINKINFO, nil)
|
|
|
nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type()))
|
|
|
|
|
|
- if vlan, ok := link.(*Vlan); ok {
|
|
|
+ switch link := link.(type) {
|
|
|
+ case *Vlan:
|
|
|
b := make([]byte, 2)
|
|
|
- native.PutUint16(b, uint16(vlan.VlanId))
|
|
|
+ native.PutUint16(b, uint16(link.VlanId))
|
|
|
data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
|
|
|
nl.NewRtAttrChild(data, nl.IFLA_VLAN_ID, b)
|
|
|
- } else if veth, ok := link.(*Veth); ok {
|
|
|
+ case *Veth:
|
|
|
data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
|
|
|
peer := nl.NewRtAttrChild(data, nl.VETH_INFO_PEER, nil)
|
|
|
nl.NewIfInfomsgChild(peer, syscall.AF_UNSPEC)
|
|
|
- nl.NewRtAttrChild(peer, syscall.IFLA_IFNAME, nl.ZeroTerminated(veth.PeerName))
|
|
|
+ nl.NewRtAttrChild(peer, syscall.IFLA_IFNAME, nl.ZeroTerminated(link.PeerName))
|
|
|
if base.TxQLen >= 0 {
|
|
|
nl.NewRtAttrChild(peer, syscall.IFLA_TXQLEN, nl.Uint32Attr(uint32(base.TxQLen)))
|
|
|
}
|
|
@@ -835,35 +919,37 @@ func (h *Handle) linkModify(link Link, flags int) error {
|
|
|
nl.NewRtAttrChild(peer, syscall.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU)))
|
|
|
}
|
|
|
|
|
|
- } else if vxlan, ok := link.(*Vxlan); ok {
|
|
|
- addVxlanAttrs(vxlan, linkInfo)
|
|
|
- } else if bond, ok := link.(*Bond); ok {
|
|
|
- addBondAttrs(bond, linkInfo)
|
|
|
- } else if ipv, ok := link.(*IPVlan); ok {
|
|
|
+ case *Vxlan:
|
|
|
+ addVxlanAttrs(link, linkInfo)
|
|
|
+ case *Bond:
|
|
|
+ addBondAttrs(link, linkInfo)
|
|
|
+ case *IPVlan:
|
|
|
data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
|
|
|
- nl.NewRtAttrChild(data, nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(ipv.Mode)))
|
|
|
- } else if macv, ok := link.(*Macvlan); ok {
|
|
|
- if macv.Mode != MACVLAN_MODE_DEFAULT {
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode)))
|
|
|
+ case *Macvlan:
|
|
|
+ if link.Mode != MACVLAN_MODE_DEFAULT {
|
|
|
data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
|
|
|
- nl.NewRtAttrChild(data, nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[macv.Mode]))
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode]))
|
|
|
}
|
|
|
- } else if macv, ok := link.(*Macvtap); ok {
|
|
|
- if macv.Mode != MACVLAN_MODE_DEFAULT {
|
|
|
+ case *Macvtap:
|
|
|
+ if link.Mode != MACVLAN_MODE_DEFAULT {
|
|
|
data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
|
|
|
- nl.NewRtAttrChild(data, nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[macv.Mode]))
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode]))
|
|
|
}
|
|
|
- } else if gretap, ok := link.(*Gretap); ok {
|
|
|
- addGretapAttrs(gretap, linkInfo)
|
|
|
- } else if iptun, ok := link.(*Iptun); ok {
|
|
|
- addIptunAttrs(iptun, linkInfo)
|
|
|
- } else if vti, ok := link.(*Vti); ok {
|
|
|
- addVtiAttrs(vti, linkInfo)
|
|
|
- } else if vrf, ok := link.(*Vrf); ok {
|
|
|
- addVrfAttrs(vrf, linkInfo)
|
|
|
- } else if bridge, ok := link.(*Bridge); ok {
|
|
|
- addBridgeAttrs(bridge, linkInfo)
|
|
|
- } else if gtp, ok := link.(*GTP); ok {
|
|
|
- addGTPAttrs(gtp, linkInfo)
|
|
|
+ case *Gretap:
|
|
|
+ addGretapAttrs(link, linkInfo)
|
|
|
+ case *Iptun:
|
|
|
+ addIptunAttrs(link, linkInfo)
|
|
|
+ case *Gretun:
|
|
|
+ addGretunAttrs(link, linkInfo)
|
|
|
+ case *Vti:
|
|
|
+ addVtiAttrs(link, linkInfo)
|
|
|
+ case *Vrf:
|
|
|
+ addVrfAttrs(link, linkInfo)
|
|
|
+ case *Bridge:
|
|
|
+ addBridgeAttrs(link, linkInfo)
|
|
|
+ case *GTP:
|
|
|
+ addGTPAttrs(link, linkInfo)
|
|
|
}
|
|
|
|
|
|
req.AddData(linkInfo)
|
|
@@ -1093,6 +1179,8 @@ func LinkDeserialize(hdr *syscall.NlMsghdr, m []byte) (Link, error) {
|
|
|
link = &Gretap{}
|
|
|
case "ipip":
|
|
|
link = &Iptun{}
|
|
|
+ case "gre":
|
|
|
+ link = &Gretun{}
|
|
|
case "vti":
|
|
|
link = &Vti{}
|
|
|
case "vrf":
|
|
@@ -1124,6 +1212,8 @@ func LinkDeserialize(hdr *syscall.NlMsghdr, m []byte) (Link, error) {
|
|
|
parseGretapData(link, data)
|
|
|
case "ipip":
|
|
|
parseIptunData(link, data)
|
|
|
+ case "gre":
|
|
|
+ parseGretunData(link, data)
|
|
|
case "vti":
|
|
|
parseVtiData(link, data)
|
|
|
case "vrf":
|
|
@@ -1178,6 +1268,8 @@ func LinkDeserialize(hdr *syscall.NlMsghdr, m []byte) (Link, error) {
|
|
|
}
|
|
|
case syscall.IFLA_OPERSTATE:
|
|
|
base.OperState = LinkOperState(uint8(attr.Value[0]))
|
|
|
+ case nl.IFLA_LINK_NETNSID:
|
|
|
+ base.NetNsID = int(native.Uint32(attr.Value[0:4]))
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1239,16 +1331,34 @@ type LinkUpdate struct {
|
|
|
// LinkSubscribe takes a chan down which notifications will be sent
|
|
|
// when links change. Close the 'done' chan to stop subscription.
|
|
|
func LinkSubscribe(ch chan<- LinkUpdate, done <-chan struct{}) error {
|
|
|
- return linkSubscribe(netns.None(), netns.None(), ch, done)
|
|
|
+ return linkSubscribeAt(netns.None(), netns.None(), ch, done, nil)
|
|
|
}
|
|
|
|
|
|
// LinkSubscribeAt works like LinkSubscribe plus it allows the caller
|
|
|
// to choose the network namespace in which to subscribe (ns).
|
|
|
func LinkSubscribeAt(ns netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}) error {
|
|
|
- return linkSubscribe(ns, netns.None(), ch, done)
|
|
|
+ return linkSubscribeAt(ns, netns.None(), ch, done, nil)
|
|
|
+}
|
|
|
+
|
|
|
+// LinkSubscribeOptions contains a set of options to use with
|
|
|
+// LinkSubscribeWithOptions.
|
|
|
+type LinkSubscribeOptions struct {
|
|
|
+ Namespace *netns.NsHandle
|
|
|
+ ErrorCallback func(error)
|
|
|
+}
|
|
|
+
|
|
|
+// LinkSubscribeWithOptions work like LinkSubscribe but enable to
|
|
|
+// provide additional options to modify the behavior. Currently, the
|
|
|
+// namespace can be provided as well as an error callback.
|
|
|
+func LinkSubscribeWithOptions(ch chan<- LinkUpdate, done <-chan struct{}, options LinkSubscribeOptions) error {
|
|
|
+ if options.Namespace == nil {
|
|
|
+ none := netns.None()
|
|
|
+ options.Namespace = &none
|
|
|
+ }
|
|
|
+ return linkSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback)
|
|
|
}
|
|
|
|
|
|
-func linkSubscribe(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}) error {
|
|
|
+func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}, cberr func(error)) error {
|
|
|
s, err := nl.SubscribeAt(newNs, curNs, syscall.NETLINK_ROUTE, syscall.RTNLGRP_LINK)
|
|
|
if err != nil {
|
|
|
return err
|
|
@@ -1264,12 +1374,18 @@ func linkSubscribe(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-cha
|
|
|
for {
|
|
|
msgs, err := s.Receive()
|
|
|
if err != nil {
|
|
|
+ if cberr != nil {
|
|
|
+ cberr(err)
|
|
|
+ }
|
|
|
return
|
|
|
}
|
|
|
for _, m := range msgs {
|
|
|
ifmsg := nl.DeserializeIfInfomsg(m.Data)
|
|
|
link, err := LinkDeserialize(&m.Header, m.Data)
|
|
|
if err != nil {
|
|
|
+ if cberr != nil {
|
|
|
+ cberr(err)
|
|
|
+ }
|
|
|
return
|
|
|
}
|
|
|
ch <- LinkUpdate{IfInfomsg: *ifmsg, Header: m.Header, Link: link}
|
|
@@ -1363,6 +1479,33 @@ func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// LinkSetTxQLen sets the transaction queue length for the link.
|
|
|
+// Equivalent to: `ip link set $link txqlen $qlen`
|
|
|
+func LinkSetTxQLen(link Link, qlen int) error {
|
|
|
+ return pkgHandle.LinkSetTxQLen(link, qlen)
|
|
|
+}
|
|
|
+
|
|
|
+// LinkSetTxQLen sets the transaction queue length for the link.
|
|
|
+// Equivalent to: `ip link set $link txqlen $qlen`
|
|
|
+func (h *Handle) LinkSetTxQLen(link Link, qlen int) error {
|
|
|
+ base := link.Attrs()
|
|
|
+ h.ensureIndex(base)
|
|
|
+ req := h.newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
|
|
|
+
|
|
|
+ msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
|
|
|
+ msg.Index = int32(base.Index)
|
|
|
+ req.AddData(msg)
|
|
|
+
|
|
|
+ b := make([]byte, 4)
|
|
|
+ native.PutUint32(b, uint32(qlen))
|
|
|
+
|
|
|
+ data := nl.NewRtAttr(syscall.IFLA_TXQLEN, b)
|
|
|
+ req.AddData(data)
|
|
|
+
|
|
|
+ _, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
|
|
+ return err
|
|
|
+}
|
|
|
+
|
|
|
func parseVlanData(link Link, data []syscall.NetlinkRouteAttr) {
|
|
|
vlan := link.(*Vlan)
|
|
|
for _, datum := range data {
|
|
@@ -1407,6 +1550,8 @@ func parseVxlanData(link Link, data []syscall.NetlinkRouteAttr) {
|
|
|
vxlan.UDPCSum = int8(datum.Value[0]) != 0
|
|
|
case nl.IFLA_VXLAN_GBP:
|
|
|
vxlan.GBP = true
|
|
|
+ case nl.IFLA_VXLAN_FLOWBASED:
|
|
|
+ vxlan.FlowBased = int8(datum.Value[0]) != 0
|
|
|
case nl.IFLA_VXLAN_AGEING:
|
|
|
vxlan.Age = int(native.Uint32(datum.Value[0:4]))
|
|
|
vxlan.NoAge = vxlan.Age == 0
|
|
@@ -1547,6 +1692,12 @@ func linkFlags(rawFlags uint32) net.Flags {
|
|
|
func addGretapAttrs(gretap *Gretap, linkInfo *nl.RtAttr) {
|
|
|
data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
|
|
|
|
|
|
+ if gretap.FlowBased {
|
|
|
+ // In flow based mode, no other attributes need to be configured
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_GRE_COLLECT_METADATA, boolAttr(gretap.FlowBased))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
ip := gretap.Local.To4()
|
|
|
if ip != nil {
|
|
|
nl.NewRtAttrChild(data, nl.IFLA_GRE_LOCAL, []byte(ip))
|
|
@@ -1613,6 +1764,69 @@ func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) {
|
|
|
gre.EncapType = native.Uint16(datum.Value[0:2])
|
|
|
case nl.IFLA_GRE_ENCAP_FLAGS:
|
|
|
gre.EncapFlags = native.Uint16(datum.Value[0:2])
|
|
|
+ case nl.IFLA_GRE_COLLECT_METADATA:
|
|
|
+ gre.FlowBased = int8(datum.Value[0]) != 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func addGretunAttrs(gre *Gretun, linkInfo *nl.RtAttr) {
|
|
|
+ data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
|
|
|
+
|
|
|
+ ip := gre.Local.To4()
|
|
|
+ if ip != nil {
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_GRE_LOCAL, []byte(ip))
|
|
|
+ }
|
|
|
+ ip = gre.Remote.To4()
|
|
|
+ if ip != nil {
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_GRE_REMOTE, []byte(ip))
|
|
|
+ }
|
|
|
+
|
|
|
+ if gre.IKey != 0 {
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_GRE_IKEY, htonl(gre.IKey))
|
|
|
+ gre.IFlags |= uint16(nl.GRE_KEY)
|
|
|
+ }
|
|
|
+
|
|
|
+ if gre.OKey != 0 {
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_GRE_OKEY, htonl(gre.OKey))
|
|
|
+ gre.OFlags |= uint16(nl.GRE_KEY)
|
|
|
+ }
|
|
|
+
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_GRE_IFLAGS, htons(gre.IFlags))
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_GRE_OFLAGS, htons(gre.OFlags))
|
|
|
+
|
|
|
+ if gre.Link != 0 {
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_GRE_LINK, nl.Uint32Attr(gre.Link))
|
|
|
+ }
|
|
|
+
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_GRE_PMTUDISC, nl.Uint8Attr(gre.PMtuDisc))
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_GRE_TTL, nl.Uint8Attr(gre.Ttl))
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_GRE_TOS, nl.Uint8Attr(gre.Tos))
|
|
|
+}
|
|
|
+
|
|
|
+func parseGretunData(link Link, data []syscall.NetlinkRouteAttr) {
|
|
|
+ gre := link.(*Gretun)
|
|
|
+ for _, datum := range data {
|
|
|
+ switch datum.Attr.Type {
|
|
|
+ case nl.IFLA_GRE_OKEY:
|
|
|
+ gre.IKey = ntohl(datum.Value[0:4])
|
|
|
+ case nl.IFLA_GRE_IKEY:
|
|
|
+ gre.OKey = ntohl(datum.Value[0:4])
|
|
|
+ case nl.IFLA_GRE_LOCAL:
|
|
|
+ gre.Local = net.IP(datum.Value[0:4])
|
|
|
+ case nl.IFLA_GRE_REMOTE:
|
|
|
+ gre.Remote = net.IP(datum.Value[0:4])
|
|
|
+ case nl.IFLA_GRE_IFLAGS:
|
|
|
+ gre.IFlags = ntohs(datum.Value[0:2])
|
|
|
+ case nl.IFLA_GRE_OFLAGS:
|
|
|
+ gre.OFlags = ntohs(datum.Value[0:2])
|
|
|
+
|
|
|
+ case nl.IFLA_GRE_TTL:
|
|
|
+ gre.Ttl = uint8(datum.Value[0])
|
|
|
+ case nl.IFLA_GRE_TOS:
|
|
|
+ gre.Tos = uint8(datum.Value[0])
|
|
|
+ case nl.IFLA_GRE_PMTUDISC:
|
|
|
+ gre.PMtuDisc = uint8(datum.Value[0])
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -1630,8 +1844,10 @@ func addXdpAttrs(xdp *LinkXdp, req *nl.NetlinkRequest) {
|
|
|
b := make([]byte, 4)
|
|
|
native.PutUint32(b, uint32(xdp.Fd))
|
|
|
nl.NewRtAttrChild(attrs, nl.IFLA_XDP_FD, b)
|
|
|
- native.PutUint32(b, xdp.Flags)
|
|
|
- nl.NewRtAttrChild(attrs, nl.IFLA_XDP_FLAGS, b)
|
|
|
+ if xdp.Flags != 0 {
|
|
|
+ native.PutUint32(b, xdp.Flags)
|
|
|
+ nl.NewRtAttrChild(attrs, nl.IFLA_XDP_FLAGS, b)
|
|
|
+ }
|
|
|
req.AddData(attrs)
|
|
|
}
|
|
|
|
|
@@ -1649,6 +1865,8 @@ func parseLinkXdp(data []byte) (*LinkXdp, error) {
|
|
|
xdp.Attached = attr.Value[0] != 0
|
|
|
case nl.IFLA_XDP_FLAGS:
|
|
|
xdp.Flags = native.Uint32(attr.Value[0:4])
|
|
|
+ case nl.IFLA_XDP_PROG_ID:
|
|
|
+ xdp.ProgId = native.Uint32(attr.Value[0:4])
|
|
|
}
|
|
|
}
|
|
|
return xdp, nil
|