Browse code

Update netlink library (required for libnetwork)

Signed-off-by: Tom Denham <tom@tomdee.co.uk>

Tom Denham authored on 2016/11/20 09:09:06
Showing 13 changed files
... ...
@@ -33,7 +33,7 @@ github.com/hashicorp/go-multierror fcdddc395df1ddf4247c69bd436e84cfa0733f7e
33 33
 github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e8c0ea0959870
34 34
 github.com/docker/libkv v0.2.1
35 35
 github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25
36
-github.com/vishvananda/netlink e73bad418fd727ed3a02830b1af1ad0283a1de6c
36
+github.com/vishvananda/netlink 482f7a52b758233521878cb6c5904b6bd63f3457
37 37
 github.com/BurntSushi/toml f706d00e3de6abe700c994cdd545a1a4915af060
38 38
 github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374
39 39
 github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d
... ...
@@ -8,11 +8,11 @@ package netlink
8 8
 #include <stdint.h>
9 9
 #include <unistd.h>
10 10
 
11
-static int load_simple_bpf(int prog_type) {
11
+static int load_simple_bpf(int prog_type, int ret) {
12 12
 #ifdef __NR_bpf
13
-	// { return 1; }
13
+	// { return ret; }
14 14
 	__u64 __attribute__((aligned(8))) insns[] = {
15
-		0x00000001000000b7ull,
15
+		0x00000000000000b7ull | ((__u64)ret<<32),
16 16
 		0x0000000000000095ull,
17 17
 	};
18 18
 	__u8 __attribute__((aligned(8))) license[] = "ASL2";
... ...
@@ -51,10 +51,12 @@ const (
51 51
 	BPF_PROG_TYPE_KPROBE
52 52
 	BPF_PROG_TYPE_SCHED_CLS
53 53
 	BPF_PROG_TYPE_SCHED_ACT
54
+	BPF_PROG_TYPE_TRACEPOINT
55
+	BPF_PROG_TYPE_XDP
54 56
 )
55 57
 
56 58
 // loadSimpleBpf loads a trivial bpf program for testing purposes
57
-func loadSimpleBpf(progType BpfProgType) (int, error) {
58
-	fd, err := C.load_simple_bpf(C.int(progType))
59
+func loadSimpleBpf(progType BpfProgType, ret int) (int, error) {
60
+	fd, err := C.load_simple_bpf(C.int(progType), C.int(ret))
59 61
 	return int(fd), err
60 62
 }
... ...
@@ -60,7 +60,7 @@ func (a TcAct) String() string {
60 60
 	case TC_ACT_JUMP:
61 61
 		return "jump"
62 62
 	}
63
-	return fmt.Sprintf("0x%x", a)
63
+	return fmt.Sprintf("0x%x", int32(a))
64 64
 }
65 65
 
66 66
 type TcPolAct int32
... ...
@@ -86,7 +86,7 @@ func (a TcPolAct) String() string {
86 86
 	case TC_POLICE_PIPE:
87 87
 		return "pipe"
88 88
 	}
89
-	return fmt.Sprintf("0x%x", a)
89
+	return fmt.Sprintf("0x%x", int32(a))
90 90
 }
91 91
 
92 92
 type ActionAttrs struct {
... ...
@@ -1,7 +1,9 @@
1 1
 package netlink
2 2
 
3 3
 import (
4
+	"fmt"
4 5
 	"syscall"
6
+	"time"
5 7
 
6 8
 	"github.com/vishvananda/netlink/nl"
7 9
 	"github.com/vishvananda/netns"
... ...
@@ -33,6 +35,29 @@ func NewHandle(nlFamilies ...int) (*Handle, error) {
33 33
 	return newHandle(netns.None(), netns.None(), nlFamilies...)
34 34
 }
35 35
 
36
+// SetSocketTimeout sets the send and receive timeout for each socket in the
37
+// netlink handle. Although the socket timeout has granularity of one
38
+// microsecond, the effective granularity is floored by the kernel timer tick,
39
+// which default value is four milliseconds.
40
+func (h *Handle) SetSocketTimeout(to time.Duration) error {
41
+	if to < time.Microsecond {
42
+		return fmt.Errorf("invalid timeout, minimul value is %s", time.Microsecond)
43
+	}
44
+	tv := syscall.NsecToTimeval(to.Nanoseconds())
45
+	for _, sh := range h.sockets {
46
+		fd := sh.Socket.GetFd()
47
+		err := syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &tv)
48
+		if err != nil {
49
+			return err
50
+		}
51
+		err = syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, &tv)
52
+		if err != nil {
53
+			return err
54
+		}
55
+	}
56
+	return nil
57
+}
58
+
36 59
 // NewHandle returns a netlink handle on the network namespace
37 60
 // specified by ns. If ns=netns.None(), current network namespace
38 61
 // will be assumed
... ...
@@ -26,11 +26,15 @@ type LinkAttrs struct {
26 26
 	Name         string
27 27
 	HardwareAddr net.HardwareAddr
28 28
 	Flags        net.Flags
29
+	RawFlags     uint32
29 30
 	ParentIndex  int         // index of the parent link device
30 31
 	MasterIndex  int         // must be the index of a bridge
31 32
 	Namespace    interface{} // nil | NsPid | NsFd
32 33
 	Alias        string
33 34
 	Statistics   *LinkStatistics
35
+	Promisc      int
36
+	Xdp          *LinkXdp
37
+	EncapType    string
34 38
 }
35 39
 
36 40
 // NewLinkAttrs returns LinkAttrs structure filled with default values
... ...
@@ -69,6 +73,11 @@ type LinkStatistics struct {
69 69
 	TxCompressed      uint32
70 70
 }
71 71
 
72
+type LinkXdp struct {
73
+	Fd       int
74
+	Attached bool
75
+}
76
+
72 77
 // Device links cannot be created via netlink. These links
73 78
 // are links created by udev like 'lo' and 'etho0'
74 79
 type Device struct {
... ...
@@ -171,11 +180,13 @@ func (macvtap Macvtap) Type() string {
171 171
 }
172 172
 
173 173
 type TuntapMode uint16
174
+type TuntapFlag uint16
174 175
 
175 176
 // Tuntap links created via /dev/tun/tap, but can be destroyed via netlink
176 177
 type Tuntap struct {
177 178
 	LinkAttrs
178
-	Mode TuntapMode
179
+	Mode  TuntapMode
180
+	Flags TuntapFlag
179 181
 }
180 182
 
181 183
 func (tuntap *Tuntap) Attrs() *LinkAttrs {
... ...
@@ -251,6 +262,7 @@ type IPVlanMode uint16
251 251
 const (
252 252
 	IPVLAN_MODE_L2 IPVlanMode = iota
253 253
 	IPVLAN_MODE_L3
254
+	IPVLAN_MODE_L3S
254 255
 	IPVLAN_MODE_MAX
255 256
 )
256 257
 
... ...
@@ -16,8 +16,13 @@ import (
16 16
 const SizeofLinkStats = 0x5c
17 17
 
18 18
 const (
19
-	TUNTAP_MODE_TUN TuntapMode = syscall.IFF_TUN
20
-	TUNTAP_MODE_TAP TuntapMode = syscall.IFF_TAP
19
+	TUNTAP_MODE_TUN  TuntapMode = syscall.IFF_TUN
20
+	TUNTAP_MODE_TAP  TuntapMode = syscall.IFF_TAP
21
+	TUNTAP_DEFAULTS  TuntapFlag = syscall.IFF_TUN_EXCL | syscall.IFF_ONE_QUEUE
22
+	TUNTAP_VNET_HDR  TuntapFlag = syscall.IFF_VNET_HDR
23
+	TUNTAP_TUN_EXCL  TuntapFlag = syscall.IFF_TUN_EXCL
24
+	TUNTAP_NO_PI     TuntapFlag = syscall.IFF_NO_PI
25
+	TUNTAP_ONE_QUEUE TuntapFlag = syscall.IFF_ONE_QUEUE
21 26
 )
22 27
 
23 28
 var native = nl.NativeEndian()
... ...
@@ -50,6 +55,44 @@ func (h *Handle) ensureIndex(link *LinkAttrs) {
50 50
 	}
51 51
 }
52 52
 
53
+func (h *Handle) SetPromiscOn(link Link) error {
54
+	base := link.Attrs()
55
+	h.ensureIndex(base)
56
+	req := h.newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
57
+
58
+	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
59
+	msg.Change = syscall.IFF_PROMISC
60
+	msg.Flags = syscall.IFF_UP
61
+	msg.Index = int32(base.Index)
62
+	req.AddData(msg)
63
+
64
+	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
65
+	return err
66
+}
67
+
68
+func SetPromiscOn(link Link) error {
69
+	return pkgHandle.SetPromiscOn(link)
70
+}
71
+
72
+func (h *Handle) SetPromiscOff(link Link) error {
73
+	base := link.Attrs()
74
+	h.ensureIndex(base)
75
+	req := h.newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
76
+
77
+	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
78
+	msg.Change = syscall.IFF_PROMISC
79
+	msg.Flags = 0 & ^syscall.IFF_UP
80
+	msg.Index = int32(base.Index)
81
+	req.AddData(msg)
82
+
83
+	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
84
+	return err
85
+}
86
+
87
+func SetPromiscOff(link Link) error {
88
+	return pkgHandle.SetPromiscOff(link)
89
+}
90
+
53 91
 // LinkSetUp enables the link device.
54 92
 // Equivalent to: `ip link set $link up`
55 93
 func LinkSetUp(link Link) error {
... ...
@@ -255,6 +298,36 @@ func (h *Handle) LinkSetVfVlan(link Link, vf, vlan int) error {
255 255
 	return err
256 256
 }
257 257
 
258
+// LinkSetVfTxRate sets the tx rate of a vf for the link.
259
+// Equivalent to: `ip link set $link vf $vf rate $rate`
260
+func LinkSetVfTxRate(link Link, vf, rate int) error {
261
+	return pkgHandle.LinkSetVfTxRate(link, vf, rate)
262
+}
263
+
264
+// LinkSetVfTxRate sets the tx rate of a vf for the link.
265
+// Equivalent to: `ip link set $link vf $vf rate $rate`
266
+func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error {
267
+	base := link.Attrs()
268
+	h.ensureIndex(base)
269
+	req := h.newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
270
+
271
+	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
272
+	msg.Index = int32(base.Index)
273
+	req.AddData(msg)
274
+
275
+	data := nl.NewRtAttr(nl.IFLA_VFINFO_LIST, nil)
276
+	info := nl.NewRtAttrChild(data, nl.IFLA_VF_INFO, nil)
277
+	vfmsg := nl.VfTxRate{
278
+		Vf:   uint32(vf),
279
+		Rate: uint32(rate),
280
+	}
281
+	nl.NewRtAttrChild(info, nl.IFLA_VF_TX_RATE, vfmsg.Serialize())
282
+	req.AddData(data)
283
+
284
+	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
285
+	return err
286
+}
287
+
258 288
 // LinkSetMaster sets the master of the link device.
259 289
 // Equivalent to: `ip link set $link master $master`
260 290
 func LinkSetMaster(link Link, master *Bridge) error {
... ...
@@ -373,6 +446,23 @@ func (h *Handle) LinkSetNsFd(link Link, fd int) error {
373 373
 	return err
374 374
 }
375 375
 
376
+// LinkSetXdpFd adds a bpf function to the driver. The fd must be a bpf
377
+// program loaded with bpf(type=BPF_PROG_TYPE_XDP)
378
+func LinkSetXdpFd(link Link, fd int) error {
379
+	base := link.Attrs()
380
+	ensureIndex(base)
381
+	req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
382
+
383
+	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
384
+	msg.Index = int32(base.Index)
385
+	req.AddData(msg)
386
+
387
+	addXdpAttrs(&LinkXdp{Fd: fd}, req)
388
+
389
+	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
390
+	return err
391
+}
392
+
376 393
 func boolAttr(val bool) []byte {
377 394
 	var v uint8
378 395
 	if val {
... ...
@@ -552,9 +642,7 @@ func (h *Handle) LinkAdd(link Link) error {
552 552
 	if tuntap, ok := link.(*Tuntap); ok {
553 553
 		// TODO: support user
554 554
 		// TODO: support group
555
-		// TODO: support non- one_queue
556
-		// TODO: support pi | vnet_hdr | multi_queue
557
-		// TODO: support non- exclusive
555
+		// TODO: multi_queue
558 556
 		// TODO: support non- persistent
559 557
 		if tuntap.Mode < syscall.IFF_TUN || tuntap.Mode > syscall.IFF_TAP {
560 558
 			return fmt.Errorf("Tuntap.Mode %v unknown!", tuntap.Mode)
... ...
@@ -565,10 +653,13 @@ func (h *Handle) LinkAdd(link Link) error {
565 565
 		}
566 566
 		defer file.Close()
567 567
 		var req ifReq
568
-		req.Flags |= syscall.IFF_ONE_QUEUE
569
-		req.Flags |= syscall.IFF_TUN_EXCL
570
-		copy(req.Name[:15], base.Name)
568
+		if tuntap.Flags == 0 {
569
+			req.Flags = uint16(TUNTAP_DEFAULTS)
570
+		} else {
571
+			req.Flags = uint16(tuntap.Flags)
572
+		}
571 573
 		req.Flags |= uint16(tuntap.Mode)
574
+		copy(req.Name[:15], base.Name)
572 575
 		_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, file.Fd(), uintptr(syscall.TUNSETIFF), uintptr(unsafe.Pointer(&req)))
573 576
 		if errno != 0 {
574 577
 			return fmt.Errorf("Tuntap IOCTL TUNSETIFF failed, errno %v", errno)
... ...
@@ -649,6 +740,10 @@ func (h *Handle) LinkAdd(link Link) error {
649 649
 		req.AddData(attr)
650 650
 	}
651 651
 
652
+	if base.Xdp != nil {
653
+		addXdpAttrs(base.Xdp, req)
654
+	}
655
+
652 656
 	linkInfo := nl.NewRtAttr(syscall.IFLA_LINKINFO, nil)
653 657
 	nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type()))
654 658
 
... ...
@@ -871,7 +966,10 @@ func linkDeserialize(m []byte) (Link, error) {
871 871
 		return nil, err
872 872
 	}
873 873
 
874
-	base := LinkAttrs{Index: int(msg.Index), Flags: linkFlags(msg.Flags)}
874
+	base := LinkAttrs{Index: int(msg.Index), RawFlags: msg.Flags, Flags: linkFlags(msg.Flags), EncapType: msg.EncapType()}
875
+	if msg.Flags&syscall.IFF_PROMISC != 0 {
876
+		base.Promisc = 1
877
+	}
875 878
 	var link Link
876 879
 	linkType := ""
877 880
 	for _, attr := range attrs {
... ...
@@ -958,6 +1056,12 @@ func linkDeserialize(m []byte) (Link, error) {
958 958
 			base.Alias = string(attr.Value[:len(attr.Value)-1])
959 959
 		case syscall.IFLA_STATS:
960 960
 			base.Statistics = parseLinkStats(attr.Value[:])
961
+		case nl.IFLA_XDP:
962
+			xdp, err := parseLinkXdp(attr.Value[:])
963
+			if err != nil {
964
+				return nil, err
965
+			}
966
+			base.Xdp = xdp
961 967
 		}
962 968
 	}
963 969
 	// Links that don't have IFLA_INFO_KIND are hardware devices
... ...
@@ -1389,3 +1493,28 @@ func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) {
1389 1389
 func parseLinkStats(data []byte) *LinkStatistics {
1390 1390
 	return (*LinkStatistics)(unsafe.Pointer(&data[0:SizeofLinkStats][0]))
1391 1391
 }
1392
+
1393
+func addXdpAttrs(xdp *LinkXdp, req *nl.NetlinkRequest) {
1394
+	attrs := nl.NewRtAttr(nl.IFLA_XDP|syscall.NLA_F_NESTED, nil)
1395
+	b := make([]byte, 4)
1396
+	native.PutUint32(b, uint32(xdp.Fd))
1397
+	nl.NewRtAttrChild(attrs, nl.IFLA_XDP_FD, b)
1398
+	req.AddData(attrs)
1399
+}
1400
+
1401
+func parseLinkXdp(data []byte) (*LinkXdp, error) {
1402
+	attrs, err := nl.ParseRouteAttr(data)
1403
+	if err != nil {
1404
+		return nil, err
1405
+	}
1406
+	xdp := &LinkXdp{}
1407
+	for _, attr := range attrs {
1408
+		switch attr.Attr.Type {
1409
+		case nl.IFLA_XDP_FD:
1410
+			xdp.Fd = int(native.Uint32(attr.Value[0:4]))
1411
+		case nl.IFLA_XDP_ATTACHED:
1412
+			xdp.Attached = attr.Value[0] != 0
1413
+		}
1414
+	}
1415
+	return xdp, nil
1416
+}
... ...
@@ -151,8 +151,10 @@ func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error {
151 151
 	dstData := nl.NewRtAttr(NDA_DST, ipData)
152 152
 	req.AddData(dstData)
153 153
 
154
-	hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr))
155
-	req.AddData(hwData)
154
+	if neigh.Flags != NTF_PROXY || neigh.HardwareAddr != nil {
155
+		hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr))
156
+		req.AddData(hwData)
157
+	}
156 158
 
157 159
 	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
158 160
 	return err
... ...
@@ -165,14 +167,33 @@ func NeighList(linkIndex, family int) ([]Neigh, error) {
165 165
 	return pkgHandle.NeighList(linkIndex, family)
166 166
 }
167 167
 
168
+// NeighProxyList gets a list of neighbor proxies in the system.
169
+// Equivalent to: `ip neighbor show proxy`.
170
+// The list can be filtered by link and ip family.
171
+func NeighProxyList(linkIndex, family int) ([]Neigh, error) {
172
+	return pkgHandle.NeighProxyList(linkIndex, family)
173
+}
174
+
168 175
 // NeighList gets a list of IP-MAC mappings in the system (ARP table).
169 176
 // Equivalent to: `ip neighbor show`.
170 177
 // The list can be filtered by link and ip family.
171 178
 func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) {
179
+	return h.neighList(linkIndex, family, 0)
180
+}
181
+
182
+// NeighProxyList gets a list of neighbor proxies in the system.
183
+// Equivalent to: `ip neighbor show proxy`.
184
+// The list can be filtered by link, ip family.
185
+func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) {
186
+	return h.neighList(linkIndex, family, NTF_PROXY)
187
+}
188
+
189
+func (h *Handle) neighList(linkIndex, family, flags int) ([]Neigh, error) {
172 190
 	req := h.newNetlinkRequest(syscall.RTM_GETNEIGH, syscall.NLM_F_DUMP)
173 191
 	msg := Ndmsg{
174 192
 		Family: uint8(family),
175 193
 		Index:  uint32(linkIndex),
194
+		Flags:  uint8(flags),
176 195
 	}
177 196
 	req.AddData(&msg)
178 197
 
... ...
@@ -78,7 +78,7 @@ func AddrDel(link *Link, addr *Addr) error {
78 78
 	return ErrNotImplemented
79 79
 }
80 80
 
81
-func AddrList(link *Link, family int) ([]Addr, error) {
81
+func AddrList(link Link, family int) ([]Addr, error) {
82 82
 	return nil, ErrNotImplemented
83 83
 }
84 84
 
... ...
@@ -1,13 +1,35 @@
1 1
 package nl
2 2
 
3 3
 import (
4
+	"syscall"
4 5
 	"unsafe"
5 6
 )
6 7
 
7 8
 const (
8 9
 	DEFAULT_CHANGE = 0xFFFFFFFF
9 10
 	// doesn't exist in syscall
10
-	IFLA_VFINFO_LIST = 0x16
11
+	IFLA_VFINFO_LIST = syscall.IFLA_IFALIAS + 1 + iota
12
+	IFLA_STATS64
13
+	IFLA_VF_PORTS
14
+	IFLA_PORT_SELF
15
+	IFLA_AF_SPEC
16
+	IFLA_GROUP
17
+	IFLA_NET_NS_FD
18
+	IFLA_EXT_MASK
19
+	IFLA_PROMISCUITY
20
+	IFLA_NUM_TX_QUEUES
21
+	IFLA_NUM_RX_QUEUES
22
+	IFLA_CARRIER
23
+	IFLA_PHYS_PORT_ID
24
+	IFLA_CARRIER_CHANGES
25
+	IFLA_PHYS_SWITCH_ID
26
+	IFLA_LINK_NETNSID
27
+	IFLA_PHYS_PORT_NAME
28
+	IFLA_PROTO_DOWN
29
+	IFLA_GSO_MAX_SEGS
30
+	IFLA_GSO_MAX_SIZE
31
+	IFLA_PAD
32
+	IFLA_XDP
11 33
 )
12 34
 
13 35
 const (
... ...
@@ -90,11 +112,6 @@ const (
90 90
 )
91 91
 
92 92
 const (
93
-	// not defined in syscall
94
-	IFLA_NET_NS_FD = 28
95
-)
96
-
97
-const (
98 93
 	IFLA_MACVLAN_UNSPEC = iota
99 94
 	IFLA_MACVLAN_MODE
100 95
 	IFLA_MACVLAN_FLAGS
... ...
@@ -394,3 +411,10 @@ func DeserializeVfRssQueryEn(b []byte) *VfRssQueryEn {
394 394
 func (msg *VfRssQueryEn) Serialize() []byte {
395 395
 	return (*(*[SizeofVfRssQueryEn]byte)(unsafe.Pointer(msg)))[:]
396 396
 }
397
+
398
+const (
399
+	IFLA_XDP_UNSPEC   = iota
400
+	IFLA_XDP_FD       /* fd of xdp program to attach, or -1 to remove */
401
+	IFLA_XDP_ATTACHED /* read-only bool indicating if prog is attached */
402
+	IFLA_XDP_MAX      = IFLA_XDP_ATTACHED
403
+)
... ...
@@ -100,6 +100,147 @@ func (msg *IfInfomsg) Len() int {
100 100
 	return syscall.SizeofIfInfomsg
101 101
 }
102 102
 
103
+func (msg *IfInfomsg) EncapType() string {
104
+	switch msg.Type {
105
+	case 0:
106
+		return "generic"
107
+	case syscall.ARPHRD_ETHER:
108
+		return "ether"
109
+	case syscall.ARPHRD_EETHER:
110
+		return "eether"
111
+	case syscall.ARPHRD_AX25:
112
+		return "ax25"
113
+	case syscall.ARPHRD_PRONET:
114
+		return "pronet"
115
+	case syscall.ARPHRD_CHAOS:
116
+		return "chaos"
117
+	case syscall.ARPHRD_IEEE802:
118
+		return "ieee802"
119
+	case syscall.ARPHRD_ARCNET:
120
+		return "arcnet"
121
+	case syscall.ARPHRD_APPLETLK:
122
+		return "atalk"
123
+	case syscall.ARPHRD_DLCI:
124
+		return "dlci"
125
+	case syscall.ARPHRD_ATM:
126
+		return "atm"
127
+	case syscall.ARPHRD_METRICOM:
128
+		return "metricom"
129
+	case syscall.ARPHRD_IEEE1394:
130
+		return "ieee1394"
131
+	case syscall.ARPHRD_INFINIBAND:
132
+		return "infiniband"
133
+	case syscall.ARPHRD_SLIP:
134
+		return "slip"
135
+	case syscall.ARPHRD_CSLIP:
136
+		return "cslip"
137
+	case syscall.ARPHRD_SLIP6:
138
+		return "slip6"
139
+	case syscall.ARPHRD_CSLIP6:
140
+		return "cslip6"
141
+	case syscall.ARPHRD_RSRVD:
142
+		return "rsrvd"
143
+	case syscall.ARPHRD_ADAPT:
144
+		return "adapt"
145
+	case syscall.ARPHRD_ROSE:
146
+		return "rose"
147
+	case syscall.ARPHRD_X25:
148
+		return "x25"
149
+	case syscall.ARPHRD_HWX25:
150
+		return "hwx25"
151
+	case syscall.ARPHRD_PPP:
152
+		return "ppp"
153
+	case syscall.ARPHRD_HDLC:
154
+		return "hdlc"
155
+	case syscall.ARPHRD_LAPB:
156
+		return "lapb"
157
+	case syscall.ARPHRD_DDCMP:
158
+		return "ddcmp"
159
+	case syscall.ARPHRD_RAWHDLC:
160
+		return "rawhdlc"
161
+	case syscall.ARPHRD_TUNNEL:
162
+		return "ipip"
163
+	case syscall.ARPHRD_TUNNEL6:
164
+		return "tunnel6"
165
+	case syscall.ARPHRD_FRAD:
166
+		return "frad"
167
+	case syscall.ARPHRD_SKIP:
168
+		return "skip"
169
+	case syscall.ARPHRD_LOOPBACK:
170
+		return "loopback"
171
+	case syscall.ARPHRD_LOCALTLK:
172
+		return "ltalk"
173
+	case syscall.ARPHRD_FDDI:
174
+		return "fddi"
175
+	case syscall.ARPHRD_BIF:
176
+		return "bif"
177
+	case syscall.ARPHRD_SIT:
178
+		return "sit"
179
+	case syscall.ARPHRD_IPDDP:
180
+		return "ip/ddp"
181
+	case syscall.ARPHRD_IPGRE:
182
+		return "gre"
183
+	case syscall.ARPHRD_PIMREG:
184
+		return "pimreg"
185
+	case syscall.ARPHRD_HIPPI:
186
+		return "hippi"
187
+	case syscall.ARPHRD_ASH:
188
+		return "ash"
189
+	case syscall.ARPHRD_ECONET:
190
+		return "econet"
191
+	case syscall.ARPHRD_IRDA:
192
+		return "irda"
193
+	case syscall.ARPHRD_FCPP:
194
+		return "fcpp"
195
+	case syscall.ARPHRD_FCAL:
196
+		return "fcal"
197
+	case syscall.ARPHRD_FCPL:
198
+		return "fcpl"
199
+	case syscall.ARPHRD_FCFABRIC:
200
+		return "fcfb0"
201
+	case syscall.ARPHRD_FCFABRIC + 1:
202
+		return "fcfb1"
203
+	case syscall.ARPHRD_FCFABRIC + 2:
204
+		return "fcfb2"
205
+	case syscall.ARPHRD_FCFABRIC + 3:
206
+		return "fcfb3"
207
+	case syscall.ARPHRD_FCFABRIC + 4:
208
+		return "fcfb4"
209
+	case syscall.ARPHRD_FCFABRIC + 5:
210
+		return "fcfb5"
211
+	case syscall.ARPHRD_FCFABRIC + 6:
212
+		return "fcfb6"
213
+	case syscall.ARPHRD_FCFABRIC + 7:
214
+		return "fcfb7"
215
+	case syscall.ARPHRD_FCFABRIC + 8:
216
+		return "fcfb8"
217
+	case syscall.ARPHRD_FCFABRIC + 9:
218
+		return "fcfb9"
219
+	case syscall.ARPHRD_FCFABRIC + 10:
220
+		return "fcfb10"
221
+	case syscall.ARPHRD_FCFABRIC + 11:
222
+		return "fcfb11"
223
+	case syscall.ARPHRD_FCFABRIC + 12:
224
+		return "fcfb12"
225
+	case syscall.ARPHRD_IEEE802_TR:
226
+		return "tr"
227
+	case syscall.ARPHRD_IEEE80211:
228
+		return "ieee802.11"
229
+	case syscall.ARPHRD_IEEE80211_PRISM:
230
+		return "ieee802.11/prism"
231
+	case syscall.ARPHRD_IEEE80211_RADIOTAP:
232
+		return "ieee802.11/radiotap"
233
+	case syscall.ARPHRD_IEEE802154:
234
+		return "ieee802.15.4"
235
+
236
+	case 65534:
237
+		return "none"
238
+	case 65535:
239
+		return "void"
240
+	}
241
+	return fmt.Sprintf("unknown%d", msg.Type)
242
+}
243
+
103 244
 func rtaAlignOf(attrlen int) int {
104 245
 	return (attrlen + syscall.RTA_ALIGNTO - 1) & ^(syscall.RTA_ALIGNTO - 1)
105 246
 }
... ...
@@ -153,7 +153,7 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
153 153
 				} else {
154 154
 					gw = nl.NewRtAttr(syscall.RTA_GATEWAY, []byte(nh.Gw.To16()))
155 155
 				}
156
-				gwData := gw.Serialize()
156
+				gwData = gw.Serialize()
157 157
 				rtnh.Len += uint16(len(gwData))
158 158
 			}
159 159
 			buf = append(buf, rtnh.Serialize()...)
... ...
@@ -82,41 +82,46 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
82 82
 		req.AddData(rtAttrs[i])
83 83
 	}
84 84
 
85
-	var (
86
-		b      = make([]byte, 4)
87
-		native = nl.NativeEndian()
88
-	)
85
+	native := nl.NativeEndian()
89 86
 
90 87
 	if rule.Priority >= 0 {
88
+		b := make([]byte, 4)
91 89
 		native.PutUint32(b, uint32(rule.Priority))
92 90
 		req.AddData(nl.NewRtAttr(nl.FRA_PRIORITY, b))
93 91
 	}
94 92
 	if rule.Mark >= 0 {
93
+		b := make([]byte, 4)
95 94
 		native.PutUint32(b, uint32(rule.Mark))
96 95
 		req.AddData(nl.NewRtAttr(nl.FRA_FWMARK, b))
97 96
 	}
98 97
 	if rule.Mask >= 0 {
98
+		b := make([]byte, 4)
99 99
 		native.PutUint32(b, uint32(rule.Mask))
100 100
 		req.AddData(nl.NewRtAttr(nl.FRA_FWMASK, b))
101 101
 	}
102 102
 	if rule.Flow >= 0 {
103
+		b := make([]byte, 4)
103 104
 		native.PutUint32(b, uint32(rule.Flow))
104 105
 		req.AddData(nl.NewRtAttr(nl.FRA_FLOW, b))
105 106
 	}
106 107
 	if rule.TunID > 0 {
108
+		b := make([]byte, 4)
107 109
 		native.PutUint32(b, uint32(rule.TunID))
108 110
 		req.AddData(nl.NewRtAttr(nl.FRA_TUN_ID, b))
109 111
 	}
110 112
 	if rule.Table >= 256 {
113
+		b := make([]byte, 4)
111 114
 		native.PutUint32(b, uint32(rule.Table))
112 115
 		req.AddData(nl.NewRtAttr(nl.FRA_TABLE, b))
113 116
 	}
114 117
 	if msg.Table > 0 {
115 118
 		if rule.SuppressPrefixlen >= 0 {
119
+			b := make([]byte, 4)
116 120
 			native.PutUint32(b, uint32(rule.SuppressPrefixlen))
117 121
 			req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_PREFIXLEN, b))
118 122
 		}
119 123
 		if rule.SuppressIfgroup >= 0 {
124
+			b := make([]byte, 4)
120 125
 			native.PutUint32(b, uint32(rule.SuppressIfgroup))
121 126
 			req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_IFGROUP, b))
122 127
 		}
... ...
@@ -129,6 +134,7 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
129 129
 	}
130 130
 	if rule.Goto >= 0 {
131 131
 		msg.Type = nl.FR_ACT_NOP
132
+		b := make([]byte, 4)
132 133
 		native.PutUint32(b, uint32(rule.Goto))
133 134
 		req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b))
134 135
 	}
... ...
@@ -213,7 +213,7 @@ func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState
213 213
 		req.AddData(out)
214 214
 	}
215 215
 	if state.Src != nil {
216
-		out := nl.NewRtAttr(nl.XFRMA_SRCADDR, state.Src)
216
+		out := nl.NewRtAttr(nl.XFRMA_SRCADDR, state.Src.To16())
217 217
 		req.AddData(out)
218 218
 	}
219 219