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
139
140 func LinkSetAllmulticastOn(link Link) error {
141 return pkgHandle.LinkSetAllmulticastOn(link)
142 }
143
144
145
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
162
163 func LinkSetAllmulticastOff(link Link) error {
164 return pkgHandle.LinkSetAllmulticastOff(link)
165 }
166
167
168
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
184
185 func LinkSetMulticastOn(link Link) error {
186 return pkgHandle.LinkSetMulticastOn(link)
187 }
188
189
190
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
207
208 func LinkSetMulticastOff(link Link) error {
209 return pkgHandle.LinkSetMulticastOff(link)
210 }
211
212
213
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
274 b := make([]byte, 4)
275 native.PutUint32(b, mode)
276 inner.AddRtAttr(nl.IFLA_MACVLAN_MACADDR_MODE, b)
277
278
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
298
299
300 func LinkSetMacvlanMode(link Link, mode MacvlanMode) error {
301 return pkgHandle.LinkSetMacvlanMode(link, mode)
302 }
303
304
305
306
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
381
382 func LinkSetUp(link Link) error {
383 return pkgHandle.LinkSetUp(link)
384 }
385
386
387
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
404
405 func LinkSetDown(link Link) error {
406 return pkgHandle.LinkSetDown(link)
407 }
408
409
410
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
426
427 func LinkSetMTU(link Link, mtu int) error {
428 return pkgHandle.LinkSetMTU(link, mtu)
429 }
430
431
432
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
453
454 func LinkSetName(link Link, name string) error {
455 return pkgHandle.LinkSetName(link, name)
456 }
457
458
459
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
477
478 func LinkSetAlias(link Link, name string) error {
479 return pkgHandle.LinkSetAlias(link, name)
480 }
481
482
483
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
501
502 func LinkAddAltName(link Link, name string) error {
503 return pkgHandle.LinkAddAltName(link, name)
504 }
505
506
507
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
527
528 func LinkDelAltName(link Link, name string) error {
529 return pkgHandle.LinkDelAltName(link, name)
530 }
531
532
533
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
553
554 func LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error {
555 return pkgHandle.LinkSetHardwareAddr(link, hwaddr)
556 }
557
558
559
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
577
578 func LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error {
579 return pkgHandle.LinkSetVfHardwareAddr(link, vf, hwaddr)
580 }
581
582
583
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
607
608 func LinkSetVfVlan(link Link, vf, vlan int) error {
609 return pkgHandle.LinkSetVfVlan(link, vf, vlan)
610 }
611
612
613
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
637
638 func LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
639 return pkgHandle.LinkSetVfVlanQos(link, vf, vlan, qos)
640 }
641
642
643
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
668
669 func LinkSetVfVlanQosProto(link Link, vf, vlan, qos, proto int) error {
670 return pkgHandle.LinkSetVfVlanQosProto(link, vf, vlan, qos, proto)
671 }
672
673
674
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
705
706 func LinkSetVfTxRate(link Link, vf, rate int) error {
707 return pkgHandle.LinkSetVfTxRate(link, vf, rate)
708 }
709
710
711
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
735
736 func LinkSetVfRate(link Link, vf, minRate, maxRate int) error {
737 return pkgHandle.LinkSetVfRate(link, vf, minRate, maxRate)
738 }
739
740
741
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
766
767 func LinkSetVfState(link Link, vf int, state uint32) error {
768 return pkgHandle.LinkSetVfState(link, vf, state)
769 }
770
771
772
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
796
797 func LinkSetVfSpoofchk(link Link, vf int, check bool) error {
798 return pkgHandle.LinkSetVfSpoofchk(link, vf, check)
799 }
800
801
802
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
830
831 func LinkSetVfTrust(link Link, vf int, state bool) error {
832 return pkgHandle.LinkSetVfTrust(link, vf, state)
833 }
834
835
836
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
864
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
870
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
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
908
909 func LinkSetMaster(link Link, master Link) error {
910 return pkgHandle.LinkSetMaster(link, master)
911 }
912
913
914
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
929
930 func LinkSetNoMaster(link Link) error {
931 return pkgHandle.LinkSetNoMaster(link)
932 }
933
934
935
936 func (h *Handle) LinkSetNoMaster(link Link) error {
937 return h.LinkSetMasterByIndex(link, 0)
938 }
939
940
941
942 func LinkSetMasterByIndex(link Link, masterIndex int) error {
943 return pkgHandle.LinkSetMasterByIndex(link, masterIndex)
944 }
945
946
947
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
968
969
970 func LinkSetNsPid(link Link, nspid int) error {
971 return pkgHandle.LinkSetNsPid(link, nspid)
972 }
973
974
975
976
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
997
998
999 func LinkSetNsFd(link Link, fd int) error {
1000 return pkgHandle.LinkSetNsFd(link, fd)
1001 }
1002
1003
1004
1005
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
1026
1027 func LinkSetXdpFd(link Link, fd int) error {
1028 return LinkSetXdpFdWithFlags(link, fd, 0)
1029 }
1030
1031
1032
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
1049
1050 func LinkSetGSOMaxSegs(link Link, maxSegs int) error {
1051 return pkgHandle.LinkSetGSOMaxSegs(link, maxSegs)
1052 }
1053
1054
1055
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
1076
1077 func LinkSetGSOMaxSize(link Link, maxSize int) error {
1078 return pkgHandle.LinkSetGSOMaxSize(link, maxSize)
1079 }
1080
1081
1082
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
1103
1104 func LinkSetGROMaxSize(link Link, maxSize int) error {
1105 return pkgHandle.LinkSetGROMaxSize(link, maxSize)
1106 }
1107
1108
1109
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
1130
1131 func LinkSetGSOIPv4MaxSize(link Link, maxSize int) error {
1132 return pkgHandle.LinkSetGSOIPv4MaxSize(link, maxSize)
1133 }
1134
1135
1136
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
1157
1158 func LinkSetGROIPv4MaxSize(link Link, maxSize int) error {
1159 return pkgHandle.LinkSetGROIPv4MaxSize(link, maxSize)
1160 }
1161
1162
1163
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
1370
1371
1372 func LinkAdd(link Link) error {
1373 return pkgHandle.LinkAdd(link)
1374 }
1375
1376
1377
1378
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
1393 base := link.Attrs()
1394
1395
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 {
1416 queues = 1
1417 if tuntap.Flags == 0 {
1418 req.Flags = uint16(TUNTAP_DEFAULTS)
1419 }
1420 } else {
1421
1422
1423
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
1442 unix.Close(fd)
1443
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
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
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
1485 file := os.NewFile(uintptr(fd), TUN)
1486 fds = append(fds, file)
1487
1488
1489
1490
1491
1492
1493
1494
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
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
1530 if base.MasterIndex != 0 {
1531
1532 err := h.LinkSetMasterByIndex(link, base.MasterIndex)
1533 if err != nil {
1534
1535
1536 if !tuntap.NonPersist {
1537
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
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
1777 if base.MasterIndex != 0 {
1778
1779 return h.LinkSetMasterByIndex(link, base.MasterIndex)
1780 }
1781 return nil
1782 }
1783
1784
1785
1786
1787 func LinkDel(link Link) error {
1788 return pkgHandle.LinkDel(link)
1789 }
1790
1791
1792
1793
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
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
1845 func LinkByName(name string) (Link, error) {
1846 return pkgHandle.LinkByName(name)
1847 }
1848
1849
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
1872
1873 h.lookupByDump = true
1874 return h.linkByNameDump(name)
1875 }
1876
1877 return link, err
1878 }
1879
1880
1881
1882 func LinkByAlias(alias string) (Link, error) {
1883 return pkgHandle.LinkByAlias(alias)
1884 }
1885
1886
1887
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
1907
1908 h.lookupByDump = true
1909 return h.linkByAliasDump(alias)
1910 }
1911
1912 return link, err
1913 }
1914
1915
1916 func LinkByIndex(index int) (Link, error) {
1917 return pkgHandle.LinkByIndex(index)
1918 }
1919
1920
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
1957
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 = >P{}
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
2259 if link == nil {
2260 link = &Device{}
2261 }
2262 *link.Attrs() = base
2263 link.Attrs().Slave = linkSlave
2264
2265
2266
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
2287
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
2317
2318 func LinkList() ([]Link, error) {
2319 return pkgHandle.LinkList()
2320 }
2321
2322
2323
2324 func (h *Handle) LinkList() ([]Link, error) {
2325
2326
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
2352 type LinkUpdate struct {
2353 nl.IfInfomsg
2354 Header unix.NlMsghdr
2355 Link
2356 }
2357
2358
2359
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
2365
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
2371
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
2382
2383
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
2491 func LinkSetBRSlaveGroupFwdMask(link Link, mask uint16) error {
2492 return pkgHandle.LinkSetBRSlaveGroupFwdMask(link, mask)
2493 }
2494
2495
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
2587
2588 func LinkSetTxQLen(link Link, qlen int) error {
2589 return pkgHandle.LinkSetTxQLen(link, qlen)
2590 }
2591
2592
2593
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
2614
2615
2616 func LinkSetGroup(link Link, group int) error {
2617 return pkgHandle.LinkSetGroup(link, group)
2618 }
2619
2620
2621
2622
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
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
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
2732
2733
2734
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
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
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
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
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
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
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
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
3740
3741
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
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
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
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
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
3805
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
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 }
3968
View as plain text