Vendor netlink @ebdfb74

Signed-off-by: Alessandro Boch <aboch@docker.com>
This commit is contained in:
Alessandro Boch 2017-01-23 22:47:37 -08:00
parent 929ae4a0b6
commit ed758b604a
13 changed files with 711 additions and 63 deletions

View File

@ -32,7 +32,7 @@ github.com/hashicorp/go-multierror fcdddc395df1ddf4247c69bd436e84cfa0733f7e
github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e8c0ea0959870 github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e8c0ea0959870
github.com/docker/libkv 1d8431073ae03cdaedb198a89722f3aab6d418ef github.com/docker/libkv 1d8431073ae03cdaedb198a89722f3aab6d418ef
github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25 github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25
github.com/vishvananda/netlink 482f7a52b758233521878cb6c5904b6bd63f3457 github.com/vishvananda/netlink ebdfb7402004b397e6573c71132160d8e23cc12a
github.com/BurntSushi/toml f706d00e3de6abe700c994cdd545a1a4915af060 github.com/BurntSushi/toml f706d00e3de6abe700c994cdd545a1a4915af060
github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374 github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374
github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d

View File

@ -13,6 +13,7 @@ type Addr struct {
Label string Label string
Flags int Flags int
Scope int Scope int
Peer *net.IPNet
} }
// String returns $ip/$netmask $label // String returns $ip/$netmask $label
@ -43,3 +44,10 @@ func (a Addr) Equal(x Addr) bool {
// ignore label for comparison // ignore label for comparison
return a.IP.Equal(x.IP) && sizea == sizeb return a.IP.Equal(x.IP) && sizea == sizeb
} }
func (a Addr) PeerEqual(x Addr) bool {
sizea, _ := a.Peer.Mask.Size()
sizeb, _ := x.Peer.Mask.Size()
// ignore label for comparison
return a.Peer.IP.Equal(x.Peer.IP) && sizea == sizeb
}

View File

@ -56,17 +56,27 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
msg.Prefixlen = uint8(prefixlen) msg.Prefixlen = uint8(prefixlen)
req.AddData(msg) req.AddData(msg)
var addrData []byte var localAddrData []byte
if family == FAMILY_V4 { if family == FAMILY_V4 {
addrData = addr.IP.To4() localAddrData = addr.IP.To4()
} else { } else {
addrData = addr.IP.To16() localAddrData = addr.IP.To16()
} }
localData := nl.NewRtAttr(syscall.IFA_LOCAL, addrData) localData := nl.NewRtAttr(syscall.IFA_LOCAL, localAddrData)
req.AddData(localData) req.AddData(localData)
var peerAddrData []byte
if addr.Peer != nil {
if family == FAMILY_V4 {
peerAddrData = addr.Peer.IP.To4()
} else {
peerAddrData = addr.Peer.IP.To16()
}
} else {
peerAddrData = localAddrData
}
addressData := nl.NewRtAttr(syscall.IFA_ADDRESS, addrData) addressData := nl.NewRtAttr(syscall.IFA_ADDRESS, peerAddrData)
req.AddData(addressData) req.AddData(addressData)
if addr.Flags != 0 { if addr.Flags != 0 {
@ -161,11 +171,13 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) {
IP: attr.Value, IP: attr.Value,
Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)), Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
} }
addr.Peer = dst
case syscall.IFA_LOCAL: case syscall.IFA_LOCAL:
local = &net.IPNet{ local = &net.IPNet{
IP: attr.Value, IP: attr.Value,
Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)), Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
} }
addr.IPNet = local
case syscall.IFA_LABEL: case syscall.IFA_LABEL:
addr.Label = string(attr.Value[:len(attr.Value)-1]) addr.Label = string(attr.Value[:len(attr.Value)-1])
case IFA_FLAGS: case IFA_FLAGS:

View File

@ -0,0 +1,218 @@
// +build !linux
package netlink
import (
"net"
"time"
"github.com/vishvananda/netns"
)
type Handle struct{}
func NewHandle(nlFamilies ...int) (*Handle, error) {
return nil, ErrNotImplemented
}
func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error) {
return nil, ErrNotImplemented
}
func NewHandleAtFrom(newNs, curNs netns.NsHandle) (*Handle, error) {
return nil, ErrNotImplemented
}
func (h *Handle) Delete() {}
func (h *Handle) SupportsNetlinkFamily(nlFamily int) bool {
return false
}
func (h *Handle) SetSocketTimeout(to time.Duration) error {
return ErrNotImplemented
}
func (h *Handle) SetPromiscOn(link Link) error {
return ErrNotImplemented
}
func (h *Handle) SetPromiscOff(link Link) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetUp(link Link) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetDown(link Link) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetMTU(link Link, mtu int) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetName(link Link, name string) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetAlias(link Link, name string) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetVfVlan(link Link, vf, vlan int) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetMaster(link Link, master *Bridge) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetNoMaster(link Link) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetMasterByIndex(link Link, masterIndex int) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetNsPid(link Link, nspid int) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetNsFd(link Link, fd int) error {
return ErrNotImplemented
}
func (h *Handle) LinkAdd(link Link) error {
return ErrNotImplemented
}
func (h *Handle) LinkDel(link Link) error {
return ErrNotImplemented
}
func (h *Handle) LinkByName(name string) (Link, error) {
return nil, ErrNotImplemented
}
func (h *Handle) LinkByAlias(alias string) (Link, error) {
return nil, ErrNotImplemented
}
func (h *Handle) LinkByIndex(index int) (Link, error) {
return nil, ErrNotImplemented
}
func (h *Handle) LinkList() ([]Link, error) {
return nil, ErrNotImplemented
}
func (h *Handle) LinkSetHairpin(link Link, mode bool) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetGuard(link Link, mode bool) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetFastLeave(link Link, mode bool) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetLearning(link Link, mode bool) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetRootBlock(link Link, mode bool) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetFlood(link Link, mode bool) error {
return ErrNotImplemented
}
func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
return ErrNotImplemented
}
func (h *Handle) AddrAdd(link Link, addr *Addr) error {
return ErrNotImplemented
}
func (h *Handle) AddrDel(link Link, addr *Addr) error {
return ErrNotImplemented
}
func (h *Handle) AddrList(link Link, family int) ([]Addr, error) {
return nil, ErrNotImplemented
}
func (h *Handle) ClassDel(class Class) error {
return ErrNotImplemented
}
func (h *Handle) ClassChange(class Class) error {
return ErrNotImplemented
}
func (h *Handle) ClassReplace(class Class) error {
return ErrNotImplemented
}
func (h *Handle) ClassAdd(class Class) error {
return ErrNotImplemented
}
func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) {
return nil, ErrNotImplemented
}
func (h *Handle) FilterDel(filter Filter) error {
return ErrNotImplemented
}
func (h *Handle) FilterAdd(filter Filter) error {
return ErrNotImplemented
}
func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
return nil, ErrNotImplemented
}
func (h *Handle) NeighAdd(neigh *Neigh) error {
return ErrNotImplemented
}
func (h *Handle) NeighSet(neigh *Neigh) error {
return ErrNotImplemented
}
func (h *Handle) NeighAppend(neigh *Neigh) error {
return ErrNotImplemented
}
func (h *Handle) NeighDel(neigh *Neigh) error {
return ErrNotImplemented
}
func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) {
return nil, ErrNotImplemented
}
func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) {
return nil, ErrNotImplemented
}

View File

@ -35,6 +35,41 @@ type LinkAttrs struct {
Promisc int Promisc int
Xdp *LinkXdp Xdp *LinkXdp
EncapType string EncapType string
Protinfo *Protinfo
OperState LinkOperState
}
// LinkOperState represents the values of the IFLA_OPERSTATE link
// attribute, which contains the RFC2863 state of the interface.
type LinkOperState uint8
const (
OperUnknown = iota // Status can't be determined.
OperNotPresent // Some component is missing.
OperDown // Down.
OperLowerLayerDown // Down due to state of lower layer.
OperTesting // In some test mode.
OperDormant // Not up but pending an external event.
OperUp // Up, ready to send packets.
)
func (s LinkOperState) String() string {
switch s {
case OperNotPresent:
return "not-present"
case OperDown:
return "down"
case OperLowerLayerDown:
return "lower-layer-down"
case OperTesting:
return "testing"
case OperDormant:
return "dormant"
case OperUp:
return "up"
default:
return "unknown"
}
} }
// NewLinkAttrs returns LinkAttrs structure filled with default values // NewLinkAttrs returns LinkAttrs structure filled with default values
@ -44,10 +79,12 @@ func NewLinkAttrs() LinkAttrs {
} }
} }
type LinkStatistics LinkStatistics64
/* /*
Ref: struct rtnl_link_stats {...} Ref: struct rtnl_link_stats {...}
*/ */
type LinkStatistics struct { type LinkStatistics32 struct {
RxPackets uint32 RxPackets uint32
TxPackets uint32 TxPackets uint32
RxBytes uint32 RxBytes uint32
@ -73,6 +110,63 @@ type LinkStatistics struct {
TxCompressed uint32 TxCompressed uint32
} }
func (s32 LinkStatistics32) to64() *LinkStatistics64 {
return &LinkStatistics64{
RxPackets: uint64(s32.RxPackets),
TxPackets: uint64(s32.TxPackets),
RxBytes: uint64(s32.RxBytes),
TxBytes: uint64(s32.TxBytes),
RxErrors: uint64(s32.RxErrors),
TxErrors: uint64(s32.TxErrors),
RxDropped: uint64(s32.RxDropped),
TxDropped: uint64(s32.TxDropped),
Multicast: uint64(s32.Multicast),
Collisions: uint64(s32.Collisions),
RxLengthErrors: uint64(s32.RxLengthErrors),
RxOverErrors: uint64(s32.RxOverErrors),
RxCrcErrors: uint64(s32.RxCrcErrors),
RxFrameErrors: uint64(s32.RxFrameErrors),
RxFifoErrors: uint64(s32.RxFifoErrors),
RxMissedErrors: uint64(s32.RxMissedErrors),
TxAbortedErrors: uint64(s32.TxAbortedErrors),
TxCarrierErrors: uint64(s32.TxCarrierErrors),
TxFifoErrors: uint64(s32.TxFifoErrors),
TxHeartbeatErrors: uint64(s32.TxHeartbeatErrors),
TxWindowErrors: uint64(s32.TxWindowErrors),
RxCompressed: uint64(s32.RxCompressed),
TxCompressed: uint64(s32.TxCompressed),
}
}
/*
Ref: struct rtnl_link_stats64 {...}
*/
type LinkStatistics64 struct {
RxPackets uint64
TxPackets uint64
RxBytes uint64
TxBytes uint64
RxErrors uint64
TxErrors uint64
RxDropped uint64
TxDropped uint64
Multicast uint64
Collisions uint64
RxLengthErrors uint64
RxOverErrors uint64
RxCrcErrors uint64
RxFrameErrors uint64
RxFifoErrors uint64
RxMissedErrors uint64
TxAbortedErrors uint64
TxCarrierErrors uint64
TxFifoErrors uint64
TxHeartbeatErrors uint64
TxWindowErrors uint64
RxCompressed uint64
TxCompressed uint64
}
type LinkXdp struct { type LinkXdp struct {
Fd int Fd int
Attached bool Attached bool
@ -301,31 +395,31 @@ func StringToBondMode(s string) BondMode {
// Possible BondMode // Possible BondMode
const ( const (
BOND_MODE_802_3AD BondMode = iota BOND_MODE_BALANCE_RR BondMode = iota
BOND_MODE_BALANCE_RR
BOND_MODE_ACTIVE_BACKUP BOND_MODE_ACTIVE_BACKUP
BOND_MODE_BALANCE_XOR BOND_MODE_BALANCE_XOR
BOND_MODE_BROADCAST BOND_MODE_BROADCAST
BOND_MODE_802_3AD
BOND_MODE_BALANCE_TLB BOND_MODE_BALANCE_TLB
BOND_MODE_BALANCE_ALB BOND_MODE_BALANCE_ALB
BOND_MODE_UNKNOWN BOND_MODE_UNKNOWN
) )
var bondModeToString = map[BondMode]string{ var bondModeToString = map[BondMode]string{
BOND_MODE_802_3AD: "802.3ad",
BOND_MODE_BALANCE_RR: "balance-rr", BOND_MODE_BALANCE_RR: "balance-rr",
BOND_MODE_ACTIVE_BACKUP: "active-backup", BOND_MODE_ACTIVE_BACKUP: "active-backup",
BOND_MODE_BALANCE_XOR: "balance-xor", BOND_MODE_BALANCE_XOR: "balance-xor",
BOND_MODE_BROADCAST: "broadcast", BOND_MODE_BROADCAST: "broadcast",
BOND_MODE_802_3AD: "802.3ad",
BOND_MODE_BALANCE_TLB: "balance-tlb", BOND_MODE_BALANCE_TLB: "balance-tlb",
BOND_MODE_BALANCE_ALB: "balance-alb", BOND_MODE_BALANCE_ALB: "balance-alb",
} }
var StringToBondModeMap = map[string]BondMode{ var StringToBondModeMap = map[string]BondMode{
"802.3ad": BOND_MODE_802_3AD,
"balance-rr": BOND_MODE_BALANCE_RR, "balance-rr": BOND_MODE_BALANCE_RR,
"active-backup": BOND_MODE_ACTIVE_BACKUP, "active-backup": BOND_MODE_ACTIVE_BACKUP,
"balance-xor": BOND_MODE_BALANCE_XOR, "balance-xor": BOND_MODE_BALANCE_XOR,
"broadcast": BOND_MODE_BROADCAST, "broadcast": BOND_MODE_BROADCAST,
"802.3ad": BOND_MODE_802_3AD,
"balance-tlb": BOND_MODE_BALANCE_TLB, "balance-tlb": BOND_MODE_BALANCE_TLB,
"balance-alb": BOND_MODE_BALANCE_ALB, "balance-alb": BOND_MODE_BALANCE_ALB,
} }
@ -589,6 +683,54 @@ func (gretap *Gretap) Type() string {
return "gretap" return "gretap"
} }
type Iptun struct {
LinkAttrs
Ttl uint8
Tos uint8
PMtuDisc uint8
Link uint32
Local net.IP
Remote net.IP
}
func (iptun *Iptun) Attrs() *LinkAttrs {
return &iptun.LinkAttrs
}
func (iptun *Iptun) Type() string {
return "ipip"
}
type Vti struct {
LinkAttrs
IKey uint32
OKey uint32
Link uint32
Local net.IP
Remote net.IP
}
func (vti *Vti) Attrs() *LinkAttrs {
return &vti.LinkAttrs
}
func (iptun *Vti) Type() string {
return "vti"
}
type Vrf struct {
LinkAttrs
Table uint32
}
func (vrf *Vrf) Attrs() *LinkAttrs {
return &vrf.LinkAttrs
}
func (vrf *Vrf) Type() string {
return "vrf"
}
// iproute2 supported devices; // iproute2 supported devices;
// vlan | veth | vcan | dummy | ifb | macvlan | macvtap | // vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
// bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan | // bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |

View File

@ -13,7 +13,11 @@ import (
"github.com/vishvananda/netns" "github.com/vishvananda/netns"
) )
const SizeofLinkStats = 0x5c const (
SizeofLinkStats32 = 0x5c
SizeofLinkStats64 = 0xd8
IFLA_STATS64 = 0x17 // syscall pkg does not contain this one
)
const ( const (
TUNTAP_MODE_TUN TuntapMode = syscall.IFF_TUN TUNTAP_MODE_TUN TuntapMode = syscall.IFF_TUN
@ -783,6 +787,12 @@ func (h *Handle) LinkAdd(link Link) error {
} }
} else if gretap, ok := link.(*Gretap); ok { } else if gretap, ok := link.(*Gretap); ok {
addGretapAttrs(gretap, linkInfo) 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)
} }
req.AddData(linkInfo) req.AddData(linkInfo)
@ -949,7 +959,7 @@ func execGetLink(req *nl.NetlinkRequest) (Link, error) {
return nil, fmt.Errorf("Link not found") return nil, fmt.Errorf("Link not found")
case len(msgs) == 1: case len(msgs) == 1:
return linkDeserialize(msgs[0]) return LinkDeserialize(nil, msgs[0])
default: default:
return nil, fmt.Errorf("More than one link found") return nil, fmt.Errorf("More than one link found")
@ -958,7 +968,7 @@ func execGetLink(req *nl.NetlinkRequest) (Link, error) {
// linkDeserialize deserializes a raw message received from netlink into // linkDeserialize deserializes a raw message received from netlink into
// a link object. // a link object.
func linkDeserialize(m []byte) (Link, error) { func LinkDeserialize(hdr *syscall.NlMsghdr, m []byte) (Link, error) {
msg := nl.DeserializeIfInfomsg(m) msg := nl.DeserializeIfInfomsg(m)
attrs, err := nl.ParseRouteAttr(m[msg.Len():]) attrs, err := nl.ParseRouteAttr(m[msg.Len():])
@ -970,8 +980,12 @@ func linkDeserialize(m []byte) (Link, error) {
if msg.Flags&syscall.IFF_PROMISC != 0 { if msg.Flags&syscall.IFF_PROMISC != 0 {
base.Promisc = 1 base.Promisc = 1
} }
var link Link var (
linkType := "" link Link
stats32 []byte
stats64 []byte
linkType string
)
for _, attr := range attrs { for _, attr := range attrs {
switch attr.Attr.Type { switch attr.Attr.Type {
case syscall.IFLA_LINKINFO: case syscall.IFLA_LINKINFO:
@ -1006,6 +1020,12 @@ func linkDeserialize(m []byte) (Link, error) {
link = &Macvtap{} link = &Macvtap{}
case "gretap": case "gretap":
link = &Gretap{} link = &Gretap{}
case "ipip":
link = &Iptun{}
case "vti":
link = &Vti{}
case "vrf":
link = &Vrf{}
default: default:
link = &GenericLink{LinkType: linkType} link = &GenericLink{LinkType: linkType}
} }
@ -1029,6 +1049,12 @@ func linkDeserialize(m []byte) (Link, error) {
parseMacvtapData(link, data) parseMacvtapData(link, data)
case "gretap": case "gretap":
parseGretapData(link, data) parseGretapData(link, data)
case "ipip":
parseIptunData(link, data)
case "vti":
parseVtiData(link, data)
case "vrf":
parseVrfData(link, data)
} }
} }
} }
@ -1055,15 +1081,35 @@ func linkDeserialize(m []byte) (Link, error) {
case syscall.IFLA_IFALIAS: case syscall.IFLA_IFALIAS:
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[:]) stats32 = attr.Value[:]
case IFLA_STATS64:
stats64 = attr.Value[:]
case nl.IFLA_XDP: case nl.IFLA_XDP:
xdp, err := parseLinkXdp(attr.Value[:]) xdp, err := parseLinkXdp(attr.Value[:])
if err != nil { if err != nil {
return nil, err return nil, err
} }
base.Xdp = xdp base.Xdp = xdp
case syscall.IFLA_PROTINFO | syscall.NLA_F_NESTED:
if hdr != nil && hdr.Type == syscall.RTM_NEWLINK &&
msg.Family == syscall.AF_BRIDGE {
attrs, err := nl.ParseRouteAttr(attr.Value[:])
if err != nil {
return nil, err
}
base.Protinfo = parseProtinfo(attrs)
}
case syscall.IFLA_OPERSTATE:
base.OperState = LinkOperState(uint8(attr.Value[0]))
} }
} }
if stats64 != nil {
base.Statistics = parseLinkStats64(stats64)
} else if stats32 != nil {
base.Statistics = parseLinkStats32(stats32)
}
// Links that don't have IFLA_INFO_KIND are hardware devices // Links that don't have IFLA_INFO_KIND are hardware devices
if link == nil { if link == nil {
link = &Device{} link = &Device{}
@ -1096,7 +1142,7 @@ func (h *Handle) LinkList() ([]Link, error) {
var res []Link var res []Link
for _, m := range msgs { for _, m := range msgs {
link, err := linkDeserialize(m) link, err := LinkDeserialize(nil, m)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1145,7 +1191,7 @@ func linkSubscribe(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-cha
} }
for _, m := range msgs { for _, m := range msgs {
ifmsg := nl.DeserializeIfInfomsg(m.Data) ifmsg := nl.DeserializeIfInfomsg(m.Data)
link, err := linkDeserialize(m.Data) link, err := LinkDeserialize(&m.Header, m.Data)
if err != nil { if err != nil {
return return
} }
@ -1490,8 +1536,12 @@ func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) {
} }
} }
func parseLinkStats(data []byte) *LinkStatistics { func parseLinkStats32(data []byte) *LinkStatistics {
return (*LinkStatistics)(unsafe.Pointer(&data[0:SizeofLinkStats][0])) return (*LinkStatistics)((*LinkStatistics32)(unsafe.Pointer(&data[0:SizeofLinkStats32][0])).to64())
}
func parseLinkStats64(data []byte) *LinkStatistics {
return (*LinkStatistics)((*LinkStatistics64)(unsafe.Pointer(&data[0:SizeofLinkStats64][0])))
} }
func addXdpAttrs(xdp *LinkXdp, req *nl.NetlinkRequest) { func addXdpAttrs(xdp *LinkXdp, req *nl.NetlinkRequest) {
@ -1518,3 +1568,96 @@ func parseLinkXdp(data []byte) (*LinkXdp, error) {
} }
return xdp, nil return xdp, nil
} }
func addIptunAttrs(iptun *Iptun, linkInfo *nl.RtAttr) {
data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
ip := iptun.Local.To4()
if ip != nil {
nl.NewRtAttrChild(data, nl.IFLA_IPTUN_LOCAL, []byte(ip))
}
ip = iptun.Remote.To4()
if ip != nil {
nl.NewRtAttrChild(data, nl.IFLA_IPTUN_REMOTE, []byte(ip))
}
if iptun.Link != 0 {
nl.NewRtAttrChild(data, nl.IFLA_IPTUN_LINK, nl.Uint32Attr(iptun.Link))
}
nl.NewRtAttrChild(data, nl.IFLA_IPTUN_PMTUDISC, nl.Uint8Attr(iptun.PMtuDisc))
nl.NewRtAttrChild(data, nl.IFLA_IPTUN_TTL, nl.Uint8Attr(iptun.Ttl))
nl.NewRtAttrChild(data, nl.IFLA_IPTUN_TOS, nl.Uint8Attr(iptun.Tos))
}
func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) {
iptun := link.(*Iptun)
for _, datum := range data {
switch datum.Attr.Type {
case nl.IFLA_IPTUN_LOCAL:
iptun.Local = net.IP(datum.Value[0:4])
case nl.IFLA_IPTUN_REMOTE:
iptun.Remote = net.IP(datum.Value[0:4])
case nl.IFLA_IPTUN_TTL:
iptun.Ttl = uint8(datum.Value[0])
case nl.IFLA_IPTUN_TOS:
iptun.Tos = uint8(datum.Value[0])
case nl.IFLA_IPTUN_PMTUDISC:
iptun.PMtuDisc = uint8(datum.Value[0])
}
}
}
func addVtiAttrs(vti *Vti, linkInfo *nl.RtAttr) {
data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
ip := vti.Local.To4()
if ip != nil {
nl.NewRtAttrChild(data, nl.IFLA_VTI_LOCAL, []byte(ip))
}
ip = vti.Remote.To4()
if ip != nil {
nl.NewRtAttrChild(data, nl.IFLA_VTI_REMOTE, []byte(ip))
}
if vti.Link != 0 {
nl.NewRtAttrChild(data, nl.IFLA_VTI_LINK, nl.Uint32Attr(vti.Link))
}
nl.NewRtAttrChild(data, nl.IFLA_VTI_IKEY, htonl(vti.IKey))
nl.NewRtAttrChild(data, nl.IFLA_VTI_OKEY, htonl(vti.OKey))
}
func parseVtiData(link Link, data []syscall.NetlinkRouteAttr) {
vti := link.(*Vti)
for _, datum := range data {
switch datum.Attr.Type {
case nl.IFLA_VTI_LOCAL:
vti.Local = net.IP(datum.Value[0:4])
case nl.IFLA_VTI_REMOTE:
vti.Remote = net.IP(datum.Value[0:4])
case nl.IFLA_VTI_IKEY:
vti.IKey = ntohl(datum.Value[0:4])
case nl.IFLA_VTI_OKEY:
vti.OKey = ntohl(datum.Value[0:4])
}
}
}
func addVrfAttrs(vrf *Vrf, linkInfo *nl.RtAttr) {
data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
b := make([]byte, 4)
native.PutUint32(b, uint32(vrf.Table))
nl.NewRtAttrChild(data, nl.IFLA_VRF_TABLE, b)
}
func parseVrfData(link Link, data []syscall.NetlinkRouteAttr) {
vrf := link.(*Vrf)
for _, datum := range data {
switch datum.Attr.Type {
case nl.IFLA_VRF_TABLE:
vrf.Table = native.Uint32(datum.Value[0:4])
}
}
}

View File

@ -4,41 +4,114 @@ package netlink
import ( import (
"errors" "errors"
"net"
) )
var ( var (
ErrNotImplemented = errors.New("not implemented") ErrNotImplemented = errors.New("not implemented")
) )
func LinkSetUp(link *Link) error { func LinkSetUp(link Link) error {
return ErrNotImplemented return ErrNotImplemented
} }
func LinkSetDown(link *Link) error { func LinkSetDown(link Link) error {
return ErrNotImplemented return ErrNotImplemented
} }
func LinkSetMTU(link *Link, mtu int) error { func LinkSetMTU(link Link, mtu int) error {
return ErrNotImplemented return ErrNotImplemented
} }
func LinkSetMaster(link *Link, master *Link) error { func LinkSetMaster(link Link, master *Link) error {
return ErrNotImplemented return ErrNotImplemented
} }
func LinkSetNsPid(link *Link, nspid int) error { func LinkSetNsPid(link Link, nspid int) error {
return ErrNotImplemented return ErrNotImplemented
} }
func LinkSetNsFd(link *Link, fd int) error { func LinkSetNsFd(link Link, fd int) error {
return ErrNotImplemented return ErrNotImplemented
} }
func LinkAdd(link *Link) error { func LinkSetName(link Link, name string) error {
return ErrNotImplemented return ErrNotImplemented
} }
func LinkDel(link *Link) error { func LinkSetAlias(link Link, name string) error {
return ErrNotImplemented
}
func LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error {
return ErrNotImplemented
}
func LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error {
return ErrNotImplemented
}
func LinkSetVfVlan(link Link, vf, vlan int) error {
return ErrNotImplemented
}
func LinkSetVfTxRate(link Link, vf, rate int) error {
return ErrNotImplemented
}
func LinkSetNoMaster(link Link) error {
return ErrNotImplemented
}
func LinkSetMasterByIndex(link Link, masterIndex int) error {
return ErrNotImplemented
}
func LinkSetXdpFd(link Link, fd int) error {
return ErrNotImplemented
}
func LinkByName(name string) (Link, error) {
return nil, ErrNotImplemented
}
func LinkByAlias(alias string) (Link, error) {
return nil, ErrNotImplemented
}
func LinkByIndex(index int) (Link, error) {
return nil, ErrNotImplemented
}
func LinkSetHairpin(link Link, mode bool) error {
return ErrNotImplemented
}
func LinkSetGuard(link Link, mode bool) error {
return ErrNotImplemented
}
func LinkSetFastLeave(link Link, mode bool) error {
return ErrNotImplemented
}
func LinkSetLearning(link Link, mode bool) error {
return ErrNotImplemented
}
func LinkSetRootBlock(link Link, mode bool) error {
return ErrNotImplemented
}
func LinkSetFlood(link Link, mode bool) error {
return ErrNotImplemented
}
func LinkAdd(link Link) error {
return ErrNotImplemented
}
func LinkDel(link Link) error {
return ErrNotImplemented return ErrNotImplemented
} }
@ -70,11 +143,11 @@ func LinkList() ([]Link, error) {
return nil, ErrNotImplemented return nil, ErrNotImplemented
} }
func AddrAdd(link *Link, addr *Addr) error { func AddrAdd(link Link, addr *Addr) error {
return ErrNotImplemented return ErrNotImplemented
} }
func AddrDel(link *Link, addr *Addr) error { func AddrDel(link Link, addr *Addr) error {
return ErrNotImplemented return ErrNotImplemented
} }
@ -90,7 +163,7 @@ func RouteDel(route *Route) error {
return ErrNotImplemented return ErrNotImplemented
} }
func RouteList(link *Link, family int) ([]Route, error) { func RouteList(link Link, family int) ([]Route, error) {
return nil, ErrNotImplemented return nil, ErrNotImplemented
} }

View File

@ -418,3 +418,37 @@ const (
IFLA_XDP_ATTACHED /* read-only bool indicating if prog is attached */ IFLA_XDP_ATTACHED /* read-only bool indicating if prog is attached */
IFLA_XDP_MAX = IFLA_XDP_ATTACHED IFLA_XDP_MAX = IFLA_XDP_ATTACHED
) )
const (
IFLA_IPTUN_UNSPEC = iota
IFLA_IPTUN_LINK
IFLA_IPTUN_LOCAL
IFLA_IPTUN_REMOTE
IFLA_IPTUN_TTL
IFLA_IPTUN_TOS
IFLA_IPTUN_ENCAP_LIMIT
IFLA_IPTUN_FLOWINFO
IFLA_IPTUN_FLAGS
IFLA_IPTUN_PROTO
IFLA_IPTUN_PMTUDISC
IFLA_IPTUN_6RD_PREFIX
IFLA_IPTUN_6RD_RELAY_PREFIX
IFLA_IPTUN_6RD_PREFIXLEN
IFLA_IPTUN_6RD_RELAY_PREFIXLEN
IFLA_IPTUN_MAX = IFLA_IPTUN_6RD_RELAY_PREFIXLEN
)
const (
IFLA_VTI_UNSPEC = iota
IFLA_VTI_LINK
IFLA_VTI_IKEY
IFLA_VTI_OKEY
IFLA_VTI_LOCAL
IFLA_VTI_REMOTE
IFLA_VTI_MAX = IFLA_VTI_REMOTE
)
const (
IFLA_VRF_UNSPEC = iota
IFLA_VRF_TABLE
)

View File

@ -656,6 +656,13 @@ func Uint32Attr(v uint32) []byte {
return bytes return bytes
} }
func Uint64Attr(v uint64) []byte {
native := NativeEndian()
bytes := make([]byte, 8)
native.PutUint64(bytes, v)
return bytes
}
func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) { func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) {
var attrs []syscall.NetlinkRouteAttr var attrs []syscall.NetlinkRouteAttr
for len(b) >= syscall.SizeofRtAttr { for len(b) >= syscall.SizeofRtAttr {

View File

@ -46,8 +46,5 @@ func boolToByte(x bool) []byte {
} }
func byteToBool(x byte) bool { func byteToBool(x byte) bool {
if uint8(x) != 0 { return uint8(x) != 0
return true
}
return false
} }

View File

@ -40,25 +40,31 @@ func (h *Handle) LinkGetProtinfo(link Link) (Protinfo, error) {
if err != nil { if err != nil {
return pi, err return pi, err
} }
var pi Protinfo pi = *parseProtinfo(infos)
for _, info := range infos {
switch info.Attr.Type {
case nl.IFLA_BRPORT_MODE:
pi.Hairpin = byteToBool(info.Value[0])
case nl.IFLA_BRPORT_GUARD:
pi.Guard = byteToBool(info.Value[0])
case nl.IFLA_BRPORT_FAST_LEAVE:
pi.FastLeave = byteToBool(info.Value[0])
case nl.IFLA_BRPORT_PROTECT:
pi.RootBlock = byteToBool(info.Value[0])
case nl.IFLA_BRPORT_LEARNING:
pi.Learning = byteToBool(info.Value[0])
case nl.IFLA_BRPORT_UNICAST_FLOOD:
pi.Flood = byteToBool(info.Value[0])
}
}
return pi, nil return pi, nil
} }
} }
return pi, fmt.Errorf("Device with index %d not found", base.Index) return pi, fmt.Errorf("Device with index %d not found", base.Index)
} }
func parseProtinfo(infos []syscall.NetlinkRouteAttr) *Protinfo {
var pi Protinfo
for _, info := range infos {
switch info.Attr.Type {
case nl.IFLA_BRPORT_MODE:
pi.Hairpin = byteToBool(info.Value[0])
case nl.IFLA_BRPORT_GUARD:
pi.Guard = byteToBool(info.Value[0])
case nl.IFLA_BRPORT_FAST_LEAVE:
pi.FastLeave = byteToBool(info.Value[0])
case nl.IFLA_BRPORT_PROTECT:
pi.RootBlock = byteToBool(info.Value[0])
case nl.IFLA_BRPORT_LEARNING:
pi.Learning = byteToBool(info.Value[0])
case nl.IFLA_BRPORT_UNICAST_FLOOD:
pi.Flood = byteToBool(info.Value[0])
}
}
return &pi
}

View File

@ -168,11 +168,13 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
options = nl.NewRtAttr(nl.TCA_OPTIONS, tcmap.Serialize()) options = nl.NewRtAttr(nl.TCA_OPTIONS, tcmap.Serialize())
} else if tbf, ok := qdisc.(*Tbf); ok { } else if tbf, ok := qdisc.(*Tbf); ok {
opt := nl.TcTbfQopt{} opt := nl.TcTbfQopt{}
// TODO: handle rate > uint32
opt.Rate.Rate = uint32(tbf.Rate) opt.Rate.Rate = uint32(tbf.Rate)
opt.Limit = tbf.Limit opt.Limit = tbf.Limit
opt.Buffer = tbf.Buffer opt.Buffer = tbf.Buffer
nl.NewRtAttrChild(options, nl.TCA_TBF_PARMS, opt.Serialize()) nl.NewRtAttrChild(options, nl.TCA_TBF_PARMS, opt.Serialize())
if tbf.Rate >= uint64(1<<32) {
nl.NewRtAttrChild(options, nl.TCA_TBF_RATE64, nl.Uint64Attr(tbf.Rate))
}
} else if htb, ok := qdisc.(*Htb); ok { } else if htb, ok := qdisc.(*Htb); ok {
opt := nl.TcHtbGlob{} opt := nl.TcHtbGlob{}
opt.Version = htb.Version opt.Version = htb.Version
@ -421,7 +423,7 @@ func parseTbfData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
tbf.Limit = opt.Limit tbf.Limit = opt.Limit
tbf.Buffer = opt.Buffer tbf.Buffer = opt.Buffer
case nl.TCA_TBF_RATE64: case nl.TCA_TBF_RATE64:
tbf.Rate = native.Uint64(datum.Value[0:4]) tbf.Rate = native.Uint64(datum.Value[0:8])
} }
} }
return nil return nil

View File

@ -283,14 +283,20 @@ func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64)
continue continue
case filterMask&RT_FILTER_SRC != 0 && !route.Src.Equal(filter.Src): case filterMask&RT_FILTER_SRC != 0 && !route.Src.Equal(filter.Src):
continue continue
case filterMask&RT_FILTER_DST != 0 && filter.Dst != nil: case filterMask&RT_FILTER_DST != 0:
if route.Dst == nil { if filter.Dst == nil {
continue if route.Dst != nil {
} continue
aMaskLen, aMaskBits := route.Dst.Mask.Size() }
bMaskLen, bMaskBits := filter.Dst.Mask.Size() } else {
if !(route.Dst.IP.Equal(filter.Dst.IP) && aMaskLen == bMaskLen && aMaskBits == bMaskBits) { if route.Dst == nil {
continue continue
}
aMaskLen, aMaskBits := route.Dst.Mask.Size()
bMaskLen, bMaskBits := filter.Dst.Mask.Size()
if !(route.Dst.IP.Equal(filter.Dst.IP) && aMaskLen == bMaskLen && aMaskBits == bMaskBits) {
continue
}
} }
} }
} }