|
@@ -16,8 +16,13 @@ import (
|
|
const SizeofLinkStats = 0x5c
|
|
const SizeofLinkStats = 0x5c
|
|
|
|
|
|
const (
|
|
const (
|
|
- TUNTAP_MODE_TUN TuntapMode = syscall.IFF_TUN
|
|
|
|
- TUNTAP_MODE_TAP TuntapMode = syscall.IFF_TAP
|
|
|
|
|
|
+ TUNTAP_MODE_TUN TuntapMode = syscall.IFF_TUN
|
|
|
|
+ TUNTAP_MODE_TAP TuntapMode = syscall.IFF_TAP
|
|
|
|
+ TUNTAP_DEFAULTS TuntapFlag = syscall.IFF_TUN_EXCL | syscall.IFF_ONE_QUEUE
|
|
|
|
+ TUNTAP_VNET_HDR TuntapFlag = syscall.IFF_VNET_HDR
|
|
|
|
+ TUNTAP_TUN_EXCL TuntapFlag = syscall.IFF_TUN_EXCL
|
|
|
|
+ TUNTAP_NO_PI TuntapFlag = syscall.IFF_NO_PI
|
|
|
|
+ TUNTAP_ONE_QUEUE TuntapFlag = syscall.IFF_ONE_QUEUE
|
|
)
|
|
)
|
|
|
|
|
|
var native = nl.NativeEndian()
|
|
var native = nl.NativeEndian()
|
|
@@ -50,6 +55,44 @@ func (h *Handle) ensureIndex(link *LinkAttrs) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+func (h *Handle) SetPromiscOn(link Link) error {
|
|
|
|
+ base := link.Attrs()
|
|
|
|
+ h.ensureIndex(base)
|
|
|
|
+ req := h.newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
|
|
|
|
+
|
|
|
|
+ msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
|
|
|
|
+ msg.Change = syscall.IFF_PROMISC
|
|
|
|
+ msg.Flags = syscall.IFF_UP
|
|
|
|
+ msg.Index = int32(base.Index)
|
|
|
|
+ req.AddData(msg)
|
|
|
|
+
|
|
|
|
+ _, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
|
|
|
+ return err
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func SetPromiscOn(link Link) error {
|
|
|
|
+ return pkgHandle.SetPromiscOn(link)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *Handle) SetPromiscOff(link Link) error {
|
|
|
|
+ base := link.Attrs()
|
|
|
|
+ h.ensureIndex(base)
|
|
|
|
+ req := h.newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
|
|
|
|
+
|
|
|
|
+ msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
|
|
|
|
+ msg.Change = syscall.IFF_PROMISC
|
|
|
|
+ msg.Flags = 0 & ^syscall.IFF_UP
|
|
|
|
+ msg.Index = int32(base.Index)
|
|
|
|
+ req.AddData(msg)
|
|
|
|
+
|
|
|
|
+ _, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
|
|
|
+ return err
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func SetPromiscOff(link Link) error {
|
|
|
|
+ return pkgHandle.SetPromiscOff(link)
|
|
|
|
+}
|
|
|
|
+
|
|
// LinkSetUp enables the link device.
|
|
// LinkSetUp enables the link device.
|
|
// Equivalent to: `ip link set $link up`
|
|
// Equivalent to: `ip link set $link up`
|
|
func LinkSetUp(link Link) error {
|
|
func LinkSetUp(link Link) error {
|
|
@@ -255,6 +298,36 @@ func (h *Handle) LinkSetVfVlan(link Link, vf, vlan int) error {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// LinkSetVfTxRate sets the tx rate of a vf for the link.
|
|
|
|
+// Equivalent to: `ip link set $link vf $vf rate $rate`
|
|
|
|
+func LinkSetVfTxRate(link Link, vf, rate int) error {
|
|
|
|
+ return pkgHandle.LinkSetVfTxRate(link, vf, rate)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// LinkSetVfTxRate sets the tx rate of a vf for the link.
|
|
|
|
+// Equivalent to: `ip link set $link vf $vf rate $rate`
|
|
|
|
+func (h *Handle) LinkSetVfTxRate(link Link, vf, rate 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)
|
|
|
|
+
|
|
|
|
+ data := nl.NewRtAttr(nl.IFLA_VFINFO_LIST, nil)
|
|
|
|
+ info := nl.NewRtAttrChild(data, nl.IFLA_VF_INFO, nil)
|
|
|
|
+ vfmsg := nl.VfTxRate{
|
|
|
|
+ Vf: uint32(vf),
|
|
|
|
+ Rate: uint32(rate),
|
|
|
|
+ }
|
|
|
|
+ nl.NewRtAttrChild(info, nl.IFLA_VF_TX_RATE, vfmsg.Serialize())
|
|
|
|
+ req.AddData(data)
|
|
|
|
+
|
|
|
|
+ _, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
|
|
|
+ return err
|
|
|
|
+}
|
|
|
|
+
|
|
// LinkSetMaster sets the master of the link device.
|
|
// LinkSetMaster sets the master of the link device.
|
|
// Equivalent to: `ip link set $link master $master`
|
|
// Equivalent to: `ip link set $link master $master`
|
|
func LinkSetMaster(link Link, master *Bridge) error {
|
|
func LinkSetMaster(link Link, master *Bridge) error {
|
|
@@ -373,6 +446,23 @@ func (h *Handle) LinkSetNsFd(link Link, fd int) error {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// 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 {
|
|
|
|
+ base := link.Attrs()
|
|
|
|
+ ensureIndex(base)
|
|
|
|
+ req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
|
|
|
|
+
|
|
|
|
+ msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
|
|
|
|
+ msg.Index = int32(base.Index)
|
|
|
|
+ req.AddData(msg)
|
|
|
|
+
|
|
|
|
+ addXdpAttrs(&LinkXdp{Fd: fd}, req)
|
|
|
|
+
|
|
|
|
+ _, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
|
|
|
+ return err
|
|
|
|
+}
|
|
|
|
+
|
|
func boolAttr(val bool) []byte {
|
|
func boolAttr(val bool) []byte {
|
|
var v uint8
|
|
var v uint8
|
|
if val {
|
|
if val {
|
|
@@ -552,9 +642,7 @@ func (h *Handle) LinkAdd(link Link) error {
|
|
if tuntap, ok := link.(*Tuntap); ok {
|
|
if tuntap, ok := link.(*Tuntap); ok {
|
|
// TODO: support user
|
|
// TODO: support user
|
|
// TODO: support group
|
|
// TODO: support group
|
|
- // TODO: support non- one_queue
|
|
|
|
- // TODO: support pi | vnet_hdr | multi_queue
|
|
|
|
- // TODO: support non- exclusive
|
|
|
|
|
|
+ // TODO: multi_queue
|
|
// TODO: support non- persistent
|
|
// TODO: support non- persistent
|
|
if tuntap.Mode < syscall.IFF_TUN || tuntap.Mode > syscall.IFF_TAP {
|
|
if tuntap.Mode < syscall.IFF_TUN || tuntap.Mode > syscall.IFF_TAP {
|
|
return fmt.Errorf("Tuntap.Mode %v unknown!", tuntap.Mode)
|
|
return fmt.Errorf("Tuntap.Mode %v unknown!", tuntap.Mode)
|
|
@@ -565,10 +653,13 @@ func (h *Handle) LinkAdd(link Link) error {
|
|
}
|
|
}
|
|
defer file.Close()
|
|
defer file.Close()
|
|
var req ifReq
|
|
var req ifReq
|
|
- req.Flags |= syscall.IFF_ONE_QUEUE
|
|
|
|
- req.Flags |= syscall.IFF_TUN_EXCL
|
|
|
|
- copy(req.Name[:15], base.Name)
|
|
|
|
|
|
+ if tuntap.Flags == 0 {
|
|
|
|
+ req.Flags = uint16(TUNTAP_DEFAULTS)
|
|
|
|
+ } else {
|
|
|
|
+ req.Flags = uint16(tuntap.Flags)
|
|
|
|
+ }
|
|
req.Flags |= uint16(tuntap.Mode)
|
|
req.Flags |= uint16(tuntap.Mode)
|
|
|
|
+ copy(req.Name[:15], base.Name)
|
|
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, file.Fd(), uintptr(syscall.TUNSETIFF), uintptr(unsafe.Pointer(&req)))
|
|
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, file.Fd(), uintptr(syscall.TUNSETIFF), uintptr(unsafe.Pointer(&req)))
|
|
if errno != 0 {
|
|
if errno != 0 {
|
|
return fmt.Errorf("Tuntap IOCTL TUNSETIFF failed, errno %v", errno)
|
|
return fmt.Errorf("Tuntap IOCTL TUNSETIFF failed, errno %v", errno)
|
|
@@ -649,6 +740,10 @@ func (h *Handle) LinkAdd(link Link) error {
|
|
req.AddData(attr)
|
|
req.AddData(attr)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if base.Xdp != nil {
|
|
|
|
+ addXdpAttrs(base.Xdp, req)
|
|
|
|
+ }
|
|
|
|
+
|
|
linkInfo := nl.NewRtAttr(syscall.IFLA_LINKINFO, nil)
|
|
linkInfo := nl.NewRtAttr(syscall.IFLA_LINKINFO, nil)
|
|
nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type()))
|
|
nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type()))
|
|
|
|
|
|
@@ -871,7 +966,10 @@ func linkDeserialize(m []byte) (Link, error) {
|
|
return nil, err
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
|
|
- base := LinkAttrs{Index: int(msg.Index), Flags: linkFlags(msg.Flags)}
|
|
|
|
|
|
+ base := LinkAttrs{Index: int(msg.Index), RawFlags: msg.Flags, Flags: linkFlags(msg.Flags), EncapType: msg.EncapType()}
|
|
|
|
+ if msg.Flags&syscall.IFF_PROMISC != 0 {
|
|
|
|
+ base.Promisc = 1
|
|
|
|
+ }
|
|
var link Link
|
|
var link Link
|
|
linkType := ""
|
|
linkType := ""
|
|
for _, attr := range attrs {
|
|
for _, attr := range attrs {
|
|
@@ -958,6 +1056,12 @@ func linkDeserialize(m []byte) (Link, error) {
|
|
base.Alias = string(attr.Value[:len(attr.Value)-1])
|
|
base.Alias = string(attr.Value[:len(attr.Value)-1])
|
|
case syscall.IFLA_STATS:
|
|
case syscall.IFLA_STATS:
|
|
base.Statistics = parseLinkStats(attr.Value[:])
|
|
base.Statistics = parseLinkStats(attr.Value[:])
|
|
|
|
+ case nl.IFLA_XDP:
|
|
|
|
+ xdp, err := parseLinkXdp(attr.Value[:])
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+ base.Xdp = xdp
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Links that don't have IFLA_INFO_KIND are hardware devices
|
|
// Links that don't have IFLA_INFO_KIND are hardware devices
|
|
@@ -1389,3 +1493,28 @@ func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) {
|
|
func parseLinkStats(data []byte) *LinkStatistics {
|
|
func parseLinkStats(data []byte) *LinkStatistics {
|
|
return (*LinkStatistics)(unsafe.Pointer(&data[0:SizeofLinkStats][0]))
|
|
return (*LinkStatistics)(unsafe.Pointer(&data[0:SizeofLinkStats][0]))
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+func addXdpAttrs(xdp *LinkXdp, req *nl.NetlinkRequest) {
|
|
|
|
+ attrs := nl.NewRtAttr(nl.IFLA_XDP|syscall.NLA_F_NESTED, nil)
|
|
|
|
+ b := make([]byte, 4)
|
|
|
|
+ native.PutUint32(b, uint32(xdp.Fd))
|
|
|
|
+ nl.NewRtAttrChild(attrs, nl.IFLA_XDP_FD, b)
|
|
|
|
+ req.AddData(attrs)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func parseLinkXdp(data []byte) (*LinkXdp, error) {
|
|
|
|
+ attrs, err := nl.ParseRouteAttr(data)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+ xdp := &LinkXdp{}
|
|
|
|
+ for _, attr := range attrs {
|
|
|
|
+ switch attr.Attr.Type {
|
|
|
|
+ case nl.IFLA_XDP_FD:
|
|
|
|
+ xdp.Fd = int(native.Uint32(attr.Value[0:4]))
|
|
|
|
+ case nl.IFLA_XDP_ATTACHED:
|
|
|
|
+ xdp.Attached = attr.Value[0] != 0
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return xdp, nil
|
|
|
|
+}
|