1
2
3
4 package netlink
5
6 import (
7 "bytes"
8 "errors"
9 "fmt"
10 "net"
11 "os"
12 "os/exec"
13 "sort"
14 "strings"
15 "syscall"
16 "testing"
17 "time"
18
19 "github.com/vishvananda/netlink/nl"
20 "github.com/vishvananda/netns"
21 "golang.org/x/sys/unix"
22 )
23
24 const (
25 testTxQLen int = 100
26 defaultTxQLen int = 1000
27 testTxQueues int = 4
28 testRxQueues int = 8
29 )
30
31 func testLinkAddDel(t *testing.T, link Link) {
32 _, err := LinkList()
33 if err != nil {
34 t.Fatal(err)
35 }
36
37 if err := LinkAdd(link); err != nil {
38 t.Fatal(err)
39 }
40
41 base := link.Attrs()
42
43 result, err := LinkByName(base.Name)
44 if err != nil {
45 t.Fatal(err)
46 }
47
48 rBase := result.Attrs()
49
50 if base.Index != 0 {
51 if base.Index != rBase.Index {
52 t.Fatalf("index is %d, should be %d", rBase.Index, base.Index)
53 }
54 }
55
56 if base.Group > 0 {
57 if base.Group != rBase.Group {
58 t.Fatalf("group is %d, should be %d", rBase.Group, base.Group)
59 }
60 }
61
62 if vlan, ok := link.(*Vlan); ok {
63 other, ok := result.(*Vlan)
64 if !ok {
65 t.Fatal("Result of create is not a vlan")
66 }
67 if vlan.VlanId != other.VlanId {
68 t.Fatal("Link.VlanId id doesn't match")
69 }
70 }
71
72 if resultPrimary, ok := result.(*Netkit); ok {
73 if inputPrimary, ok := link.(*Netkit); ok {
74 if resultPrimary.Policy != inputPrimary.Policy {
75 t.Fatalf("Policy is %d, should be %d", int(resultPrimary.Policy), int(inputPrimary.Policy))
76 }
77 if resultPrimary.PeerPolicy != inputPrimary.PeerPolicy {
78 t.Fatalf("Peer Policy is %d, should be %d", int(resultPrimary.PeerPolicy), int(inputPrimary.PeerPolicy))
79 }
80 if resultPrimary.Mode != inputPrimary.Mode {
81 t.Fatalf("Mode is %d, should be %d", int(resultPrimary.Mode), int(inputPrimary.Mode))
82 }
83
84 if inputPrimary.peerLinkAttrs.Name != "" {
85 var resultPeer *Netkit
86 pLink, err := LinkByName(inputPrimary.peerLinkAttrs.Name)
87 if err != nil {
88 t.Fatalf("Failed to get Peer netkit %s", inputPrimary.peerLinkAttrs.Name)
89 }
90 if resultPeer, ok = pLink.(*Netkit); !ok {
91 t.Fatalf("Peer %s is incorrect type", inputPrimary.peerLinkAttrs.Name)
92 }
93 if resultPrimary.PeerPolicy != resultPeer.Policy {
94 t.Fatalf("Peer Policy from primary is %d, should be %d", int(resultPrimary.PeerPolicy), int(resultPeer.Policy))
95 }
96 if resultPeer.PeerPolicy != resultPrimary.Policy {
97 t.Fatalf("PeerPolicy from peer is %d, should be %d", int(resultPeer.PeerPolicy), int(resultPrimary.Policy))
98 }
99 if resultPrimary.Mode != resultPeer.Mode {
100 t.Fatalf("Peer Mode from primary is %d, should be %d", int(resultPrimary.Mode), int(resultPeer.Mode))
101 }
102 if resultPrimary.IsPrimary() == resultPeer.IsPrimary() {
103 t.Fatalf("Both primary and peer device has the same value in IsPrimary() %t", resultPrimary.IsPrimary())
104 }
105 }
106 }
107
108 }
109
110 if veth, ok := result.(*Veth); ok {
111 if rBase.TxQLen != base.TxQLen {
112 t.Fatalf("qlen is %d, should be %d", rBase.TxQLen, base.TxQLen)
113 }
114
115 if rBase.NumTxQueues != base.NumTxQueues {
116 t.Fatalf("txQueues is %d, should be %d", rBase.NumTxQueues, base.NumTxQueues)
117 }
118
119 if rBase.NumRxQueues != base.NumRxQueues {
120 t.Fatalf("rxQueues is %d, should be %d", rBase.NumRxQueues, base.NumRxQueues)
121 }
122
123 if rBase.MTU != base.MTU {
124 t.Fatalf("MTU is %d, should be %d", rBase.MTU, base.MTU)
125 }
126
127 if original, ok := link.(*Veth); ok {
128 if original.PeerName != "" {
129 var peer *Veth
130 other, err := LinkByName(original.PeerName)
131 if err != nil {
132 t.Fatalf("Peer %s not created", veth.PeerName)
133 }
134 if peer, ok = other.(*Veth); !ok {
135 t.Fatalf("Peer %s is incorrect type", veth.PeerName)
136 }
137 if peer.TxQLen != testTxQLen {
138 t.Fatalf("TxQLen of peer is %d, should be %d", peer.TxQLen, testTxQLen)
139 }
140 if peer.NumTxQueues != testTxQueues {
141 t.Fatalf("NumTxQueues of peer is %d, should be %d", peer.NumTxQueues, testTxQueues)
142 }
143 if peer.NumRxQueues != testRxQueues {
144 t.Fatalf("NumRxQueues of peer is %d, should be %d", peer.NumRxQueues, testRxQueues)
145 }
146 if !bytes.Equal(peer.Attrs().HardwareAddr, original.PeerHardwareAddr) {
147 t.Fatalf("Peer MAC addr is %s, should be %s", peer.Attrs().HardwareAddr, original.PeerHardwareAddr)
148 }
149 }
150 }
151 }
152
153 if _, ok := result.(*Veth); !ok {
154 if _, ok := result.(*Netkit); !ok {
155
156 if rBase.ParentIndex == 0 && base.ParentIndex != 0 {
157 t.Fatalf("Created link doesn't have parent %d but it should", base.ParentIndex)
158 } else if rBase.ParentIndex != 0 && base.ParentIndex == 0 {
159 t.Fatalf("Created link has parent %d but it shouldn't", rBase.ParentIndex)
160 } else if rBase.ParentIndex != 0 && base.ParentIndex != 0 {
161 if rBase.ParentIndex != base.ParentIndex {
162 t.Fatalf("Link.ParentIndex doesn't match %d != %d", rBase.ParentIndex, base.ParentIndex)
163 }
164 }
165 }
166 }
167
168 if _, ok := link.(*Wireguard); ok {
169 _, ok := result.(*Wireguard)
170 if !ok {
171 t.Fatal("Result of create is not a wireguard")
172 }
173 }
174
175 if vxlan, ok := link.(*Vxlan); ok {
176 other, ok := result.(*Vxlan)
177 if !ok {
178 t.Fatal("Result of create is not a vxlan")
179 }
180 compareVxlan(t, vxlan, other)
181 }
182
183 if ipv, ok := link.(*IPVlan); ok {
184 other, ok := result.(*IPVlan)
185 if !ok {
186 t.Fatal("Result of create is not a ipvlan")
187 }
188 if ipv.Mode != other.Mode {
189 t.Fatalf("Got unexpected mode: %d, expected: %d", other.Mode, ipv.Mode)
190 }
191 if ipv.Flag != other.Flag {
192 t.Fatalf("Got unexpected flag: %d, expected: %d", other.Flag, ipv.Flag)
193 }
194 }
195
196 if macv, ok := link.(*Macvlan); ok {
197 other, ok := result.(*Macvlan)
198 if !ok {
199 t.Fatal("Result of create is not a macvlan")
200 }
201 if macv.Mode != other.Mode {
202 t.Fatalf("Got unexpected mode: %d, expected: %d", other.Mode, macv.Mode)
203 }
204 if other.BCQueueLen > 0 || other.UsedBCQueueLen > 0 {
205 if other.UsedBCQueueLen < other.BCQueueLen {
206 t.Fatalf("UsedBCQueueLen (%d) is smaller than BCQueueLen (%d)", other.UsedBCQueueLen, other.BCQueueLen)
207 }
208 }
209 if macv.BCQueueLen > 0 {
210 if macv.BCQueueLen != other.BCQueueLen {
211 t.Fatalf("BCQueueLen not set correctly: %d, expected: %d", other.BCQueueLen, macv.BCQueueLen)
212 }
213 }
214 }
215
216 if macv, ok := link.(*Macvtap); ok {
217 other, ok := result.(*Macvtap)
218 if !ok {
219 t.Fatal("Result of create is not a macvtap")
220 }
221 if macv.Mode != other.Mode {
222 t.Fatalf("Got unexpected mode: %d, expected: %d", other.Mode, macv.Mode)
223 }
224 if other.BCQueueLen > 0 || other.UsedBCQueueLen > 0 {
225 if other.UsedBCQueueLen < other.BCQueueLen {
226 t.Fatalf("UsedBCQueueLen (%d) is smaller than BCQueueLen (%d)", other.UsedBCQueueLen, other.BCQueueLen)
227 }
228 }
229 if macv.BCQueueLen > 0 {
230 if macv.BCQueueLen != other.BCQueueLen {
231 t.Fatalf("BCQueueLen not set correctly: %d, expected: %d", other.BCQueueLen, macv.BCQueueLen)
232 }
233 }
234 }
235
236 if _, ok := link.(*Vti); ok {
237 _, ok := result.(*Vti)
238 if !ok {
239 t.Fatal("Result of create is not a vti")
240 }
241 }
242
243 if bond, ok := link.(*Bond); ok {
244 other, ok := result.(*Bond)
245 if !ok {
246 t.Fatal("Result of create is not a bond")
247 }
248 if bond.Mode != other.Mode {
249 t.Fatalf("Got unexpected mode: %d, expected: %d", other.Mode, bond.Mode)
250 }
251 if bond.ArpIpTargets != nil {
252 if other.ArpIpTargets == nil {
253 t.Fatalf("Got unexpected ArpIpTargets: nil")
254 }
255
256 if len(bond.ArpIpTargets) != len(other.ArpIpTargets) {
257 t.Fatalf("Got unexpected ArpIpTargets len: %d, expected: %d",
258 len(other.ArpIpTargets), len(bond.ArpIpTargets))
259 }
260
261 for i := range bond.ArpIpTargets {
262 if !bond.ArpIpTargets[i].Equal(other.ArpIpTargets[i]) {
263 t.Fatalf("Got unexpected ArpIpTargets: %s, expected: %s",
264 other.ArpIpTargets[i], bond.ArpIpTargets[i])
265 }
266 }
267 }
268
269 switch mode := bondModeToString[bond.Mode]; mode {
270 case "802.3ad":
271 if bond.AdSelect != other.AdSelect {
272 t.Fatalf("Got unexpected AdSelect: %d, expected: %d", other.AdSelect, bond.AdSelect)
273 }
274 if bond.AdActorSysPrio != other.AdActorSysPrio {
275 t.Fatalf("Got unexpected AdActorSysPrio: %d, expected: %d", other.AdActorSysPrio, bond.AdActorSysPrio)
276 }
277 if bond.AdUserPortKey != other.AdUserPortKey {
278 t.Fatalf("Got unexpected AdUserPortKey: %d, expected: %d", other.AdUserPortKey, bond.AdUserPortKey)
279 }
280 if !bytes.Equal(bond.AdActorSystem, other.AdActorSystem) {
281 t.Fatalf("Got unexpected AdActorSystem: %d, expected: %d", other.AdActorSystem, bond.AdActorSystem)
282 }
283 case "balance-tlb":
284 if bond.TlbDynamicLb != other.TlbDynamicLb {
285 t.Fatalf("Got unexpected TlbDynamicLb: %d, expected: %d", other.TlbDynamicLb, bond.TlbDynamicLb)
286 }
287 }
288 }
289
290 if iptun, ok := link.(*Iptun); ok {
291 other, ok := result.(*Iptun)
292 if !ok {
293 t.Fatal("Result of create is not a iptun")
294 }
295 if iptun.FlowBased != other.FlowBased {
296 t.Fatal("Iptun.FlowBased doesn't match")
297 }
298 }
299
300 if ip6tnl, ok := link.(*Ip6tnl); ok {
301 other, ok := result.(*Ip6tnl)
302 if !ok {
303 t.Fatal("Result of create is not a ip6tnl")
304 }
305 if ip6tnl.FlowBased != other.FlowBased {
306 t.Fatal("Ip6tnl.FlowBased doesn't match")
307 }
308
309 }
310
311 if _, ok := link.(*Sittun); ok {
312 _, ok := result.(*Sittun)
313 if !ok {
314 t.Fatal("Result of create is not a sittun")
315 }
316 }
317
318 if geneve, ok := link.(*Geneve); ok {
319 other, ok := result.(*Geneve)
320 if !ok {
321 t.Fatal("Result of create is not a Geneve")
322 }
323 compareGeneve(t, geneve, other)
324 }
325
326 if gretap, ok := link.(*Gretap); ok {
327 other, ok := result.(*Gretap)
328 if !ok {
329 t.Fatal("Result of create is not a Gretap")
330 }
331 compareGretap(t, gretap, other)
332 }
333
334 if gretun, ok := link.(*Gretun); ok {
335 other, ok := result.(*Gretun)
336 if !ok {
337 t.Fatal("Result of create is not a Gretun")
338 }
339 compareGretun(t, gretun, other)
340 }
341
342 if xfrmi, ok := link.(*Xfrmi); ok {
343 other, ok := result.(*Xfrmi)
344 if !ok {
345 t.Fatal("Result of create is not a xfrmi")
346 }
347 compareXfrmi(t, xfrmi, other)
348 }
349
350 if tuntap, ok := link.(*Tuntap); ok {
351 other, ok := result.(*Tuntap)
352 if !ok {
353 t.Fatal("Result of create is not a tuntap")
354 }
355 compareTuntap(t, tuntap, other)
356 }
357
358 if bareudp, ok := link.(*BareUDP); ok {
359 other, ok := result.(*BareUDP)
360 if !ok {
361 t.Fatal("Result of create is not a BareUDP")
362 }
363 compareBareUDP(t, bareudp, other)
364 }
365
366 if err = LinkDel(link); err != nil {
367 t.Fatal(err)
368 }
369
370 links, err := LinkList()
371 if err != nil {
372 t.Fatal(err)
373 }
374
375 for _, l := range links {
376 if l.Attrs().Name == link.Attrs().Name {
377 t.Fatal("Link not removed properly")
378 }
379 }
380 }
381
382 func compareGeneve(t *testing.T, expected, actual *Geneve) {
383 if actual.ID != expected.ID {
384 t.Fatalf("Geneve.ID doesn't match: %d %d", actual.ID, expected.ID)
385 }
386
387
388 if expected.Dport == 0 {
389 expected.Dport = 6081
390 }
391
392 if actual.Dport != expected.Dport {
393 t.Fatal("Geneve.Dport doesn't match")
394 }
395
396 if actual.Ttl != expected.Ttl {
397 t.Fatal("Geneve.Ttl doesn't match")
398 }
399
400 if actual.Tos != expected.Tos {
401 t.Fatal("Geneve.Tos doesn't match")
402 }
403
404 if !actual.Remote.Equal(expected.Remote) {
405 t.Fatalf("Geneve.Remote is not equal: %s!=%s", actual.Remote, expected.Remote)
406 }
407
408 if actual.FlowBased != expected.FlowBased {
409 t.Fatal("Geneve.FlowBased doesn't match")
410 }
411
412 if actual.InnerProtoInherit != expected.InnerProtoInherit {
413 t.Fatal("Geneve.InnerProtoInherit doesn't match")
414 }
415
416
417 }
418
419 func compareGretap(t *testing.T, expected, actual *Gretap) {
420 if actual.IKey != expected.IKey {
421 t.Fatal("Gretap.IKey doesn't match")
422 }
423
424 if actual.OKey != expected.OKey {
425 t.Fatal("Gretap.OKey doesn't match")
426 }
427
428 if actual.EncapSport != expected.EncapSport {
429 t.Fatal("Gretap.EncapSport doesn't match")
430 }
431
432 if actual.EncapDport != expected.EncapDport {
433 t.Fatal("Gretap.EncapDport doesn't match")
434 }
435
436 if expected.Local != nil && !actual.Local.Equal(expected.Local) {
437 t.Fatal("Gretap.Local doesn't match")
438 }
439
440 if expected.Remote != nil && !actual.Remote.Equal(expected.Remote) {
441 t.Fatal("Gretap.Remote doesn't match")
442 }
443
444 if actual.IFlags != expected.IFlags {
445 t.Fatal("Gretap.IFlags doesn't match")
446 }
447
448 if actual.OFlags != expected.OFlags {
449 t.Fatal("Gretap.OFlags doesn't match")
450 }
451
452 if actual.PMtuDisc != expected.PMtuDisc {
453 t.Fatal("Gretap.PMtuDisc doesn't match")
454 }
455
456 if actual.Ttl != expected.Ttl {
457 t.Fatal("Gretap.Ttl doesn't match")
458 }
459
460 if actual.Tos != expected.Tos {
461 t.Fatal("Gretap.Tos doesn't match")
462 }
463
464 if actual.EncapType != expected.EncapType {
465 t.Fatal("Gretap.EncapType doesn't match")
466 }
467
468 if actual.EncapFlags != expected.EncapFlags {
469 t.Fatal("Gretap.EncapFlags doesn't match")
470 }
471
472 if actual.Link != expected.Link {
473 t.Fatal("Gretap.Link doesn't match")
474 }
475
476 if actual.FlowBased != expected.FlowBased {
477 t.Fatal("Gretap.FlowBased doesn't match")
478 }
479 }
480
481 func compareGretun(t *testing.T, expected, actual *Gretun) {
482 if actual.Link != expected.Link {
483 t.Fatal("Gretun.Link doesn't match")
484 }
485
486 if actual.IFlags != expected.IFlags {
487 t.Fatal("Gretun.IFlags doesn't match")
488 }
489
490 if actual.OFlags != expected.OFlags {
491 t.Fatal("Gretun.OFlags doesn't match")
492 }
493
494 if actual.IKey != expected.IKey {
495 t.Fatal("Gretun.IKey doesn't match")
496 }
497
498 if actual.OKey != expected.OKey {
499 t.Fatal("Gretun.OKey doesn't match")
500 }
501
502 if expected.Local != nil && !actual.Local.Equal(expected.Local) {
503 t.Fatal("Gretun.Local doesn't match")
504 }
505
506 if expected.Remote != nil && !actual.Remote.Equal(expected.Remote) {
507 t.Fatal("Gretun.Remote doesn't match")
508 }
509
510 if actual.Ttl != expected.Ttl {
511 t.Fatal("Gretun.Ttl doesn't match")
512 }
513
514 if actual.Tos != expected.Tos {
515 t.Fatal("Gretun.Tos doesn't match")
516 }
517
518 if actual.PMtuDisc != expected.PMtuDisc {
519 t.Fatal("Gretun.PMtuDisc doesn't match")
520 }
521
522 if actual.EncapType != expected.EncapType {
523 t.Fatal("Gretun.EncapType doesn't match")
524 }
525
526 if actual.EncapFlags != expected.EncapFlags {
527 t.Fatal("Gretun.EncapFlags doesn't match")
528 }
529
530 if actual.EncapSport != expected.EncapSport {
531 t.Fatal("Gretun.EncapSport doesn't match")
532 }
533
534 if actual.EncapDport != expected.EncapDport {
535 t.Fatal("Gretun.EncapDport doesn't match")
536 }
537 if actual.FlowBased != expected.FlowBased {
538 t.Fatal("Gretun.FlowBased doesn't match")
539 }
540 }
541
542 func compareVxlan(t *testing.T, expected, actual *Vxlan) {
543
544 if actual.VxlanId != expected.VxlanId {
545 t.Fatal("Vxlan.VxlanId doesn't match")
546 }
547 if expected.SrcAddr != nil && !actual.SrcAddr.Equal(expected.SrcAddr) {
548 t.Fatal("Vxlan.SrcAddr doesn't match")
549 }
550 if expected.Group != nil && !actual.Group.Equal(expected.Group) {
551 t.Fatal("Vxlan.Group doesn't match")
552 }
553 if expected.TTL != -1 && actual.TTL != expected.TTL {
554 t.Fatal("Vxlan.TTL doesn't match")
555 }
556 if expected.TOS != -1 && actual.TOS != expected.TOS {
557 t.Fatal("Vxlan.TOS doesn't match")
558 }
559 if actual.Learning != expected.Learning {
560 t.Fatal("Vxlan.Learning doesn't match")
561 }
562 if actual.Proxy != expected.Proxy {
563 t.Fatal("Vxlan.Proxy doesn't match")
564 }
565 if actual.RSC != expected.RSC {
566 t.Fatal("Vxlan.RSC doesn't match")
567 }
568 if actual.L2miss != expected.L2miss {
569 t.Fatal("Vxlan.L2miss doesn't match")
570 }
571 if actual.L3miss != expected.L3miss {
572 t.Fatal("Vxlan.L3miss doesn't match")
573 }
574 if actual.GBP != expected.GBP {
575 t.Fatal("Vxlan.GBP doesn't match")
576 }
577 if actual.FlowBased != expected.FlowBased {
578 t.Fatal("Vxlan.FlowBased doesn't match")
579 }
580 if actual.UDP6ZeroCSumTx != expected.UDP6ZeroCSumTx {
581 t.Fatal("Vxlan.UDP6ZeroCSumTx doesn't match")
582 }
583 if actual.UDP6ZeroCSumRx != expected.UDP6ZeroCSumRx {
584 t.Fatal("Vxlan.UDP6ZeroCSumRx doesn't match")
585 }
586 if expected.NoAge {
587 if !actual.NoAge {
588 t.Fatal("Vxlan.NoAge doesn't match")
589 }
590 } else if expected.Age > 0 && actual.Age != expected.Age {
591 t.Fatal("Vxlan.Age doesn't match")
592 }
593 if expected.Limit > 0 && actual.Limit != expected.Limit {
594 t.Fatal("Vxlan.Limit doesn't match")
595 }
596 if expected.Port > 0 && actual.Port != expected.Port {
597 t.Fatal("Vxlan.Port doesn't match")
598 }
599 if expected.PortLow > 0 || expected.PortHigh > 0 {
600 if actual.PortLow != expected.PortLow {
601 t.Fatal("Vxlan.PortLow doesn't match")
602 }
603 if actual.PortHigh != expected.PortHigh {
604 t.Fatal("Vxlan.PortHigh doesn't match")
605 }
606 }
607 }
608
609 func compareXfrmi(t *testing.T, expected, actual *Xfrmi) {
610 if expected.Ifid != actual.Ifid {
611 t.Fatal("Xfrmi.Ifid doesn't match")
612 }
613 }
614
615 func compareTuntap(t *testing.T, expected, actual *Tuntap) {
616 if expected.Mode != actual.Mode {
617 t.Fatalf("Tuntap.Mode doesn't match: expected : %+v, got %+v", expected.Mode, actual.Mode)
618 }
619
620 if expected.Owner != actual.Owner {
621 t.Fatal("Tuntap.Owner doesn't match")
622 }
623
624 if expected.Group != actual.Group {
625 t.Fatal("Tuntap.Group doesn't match")
626 }
627
628 if expected.NonPersist != actual.NonPersist {
629 t.Fatal("Tuntap.Group doesn't match")
630 }
631 }
632
633 func compareBareUDP(t *testing.T, expected, actual *BareUDP) {
634
635 if expected.Port == 0 {
636 expected.Port = 6635
637 }
638 if actual.Port != expected.Port {
639 t.Fatalf("BareUDP.Port doesn't match: %d %d", actual.Port, expected.Port)
640 }
641
642 if actual.EtherType != expected.EtherType {
643 t.Fatalf("BareUDP.EtherType doesn't match: %x %x", actual.EtherType, expected.EtherType)
644 }
645
646 if actual.SrcPortMin != expected.SrcPortMin {
647 t.Fatalf("BareUDP.SrcPortMin doesn't match: %d %d", actual.SrcPortMin, expected.SrcPortMin)
648 }
649
650 if actual.MultiProto != expected.MultiProto {
651 t.Fatal("BareUDP.MultiProto doesn't match")
652 }
653 }
654
655 func TestLinkAddDelWithIndex(t *testing.T) {
656 tearDown := setUpNetlinkTest(t)
657 defer tearDown()
658
659 testLinkAddDel(t, &Dummy{LinkAttrs{Index: 1000, Name: "foo"}})
660 }
661
662 func TestLinkAddDelDummy(t *testing.T) {
663 tearDown := setUpNetlinkTest(t)
664 defer tearDown()
665
666 testLinkAddDel(t, &Dummy{LinkAttrs{Name: "foo"}})
667 }
668
669 func TestLinkAddDelDummyWithGroup(t *testing.T) {
670 tearDown := setUpNetlinkTest(t)
671 defer tearDown()
672
673 testLinkAddDel(t, &Dummy{LinkAttrs{Name: "foo", Group: 42}})
674 }
675
676 func TestLinkModify(t *testing.T) {
677 tearDown := setUpNetlinkTest(t)
678 defer tearDown()
679
680 linkName := "foo"
681 originalMTU := 1500
682 updatedMTU := 1442
683
684 link := &Dummy{LinkAttrs{Name: linkName, MTU: originalMTU}}
685 base := link.Attrs()
686
687 if err := LinkAdd(link); err != nil {
688 t.Fatal(err)
689 }
690
691 link.MTU = updatedMTU
692 if err := LinkModify(link); err != nil {
693 t.Fatal(err)
694 }
695
696 result, err := LinkByName(linkName)
697 if err != nil {
698 t.Fatal(err)
699 }
700
701 rBase := result.Attrs()
702 if rBase.MTU != updatedMTU {
703 t.Fatalf("MTU is %d, should be %d", rBase.MTU, base.MTU)
704 }
705 }
706
707 func TestLinkAddDelIfb(t *testing.T) {
708 tearDown := setUpNetlinkTest(t)
709 defer tearDown()
710
711 testLinkAddDel(t, &Ifb{LinkAttrs{Name: "foo"}})
712 }
713
714 func TestLinkAddDelBridge(t *testing.T) {
715 tearDown := setUpNetlinkTest(t)
716 defer tearDown()
717
718 testLinkAddDel(t, &Bridge{LinkAttrs: LinkAttrs{Name: "foo", MTU: 1400}})
719 }
720
721 func TestLinkAddDelGeneve(t *testing.T) {
722 tearDown := setUpNetlinkTest(t)
723 defer tearDown()
724
725 testLinkAddDel(t, &Geneve{
726 LinkAttrs: LinkAttrs{Name: "foo4", EncapType: "geneve"},
727 ID: 0x1000,
728 Remote: net.IPv4(127, 0, 0, 1)})
729
730 testLinkAddDel(t, &Geneve{
731 LinkAttrs: LinkAttrs{Name: "foo6", EncapType: "geneve"},
732 ID: 0x1000,
733 Remote: net.ParseIP("2001:db8:ef33::2")})
734 }
735
736 func TestLinkAddDelGeneveFlowBased(t *testing.T) {
737 tearDown := setUpNetlinkTest(t)
738 defer tearDown()
739
740 testLinkAddDel(t, &Geneve{
741 LinkAttrs: LinkAttrs{Name: "foo"},
742 Dport: 1234,
743 FlowBased: true})
744 }
745
746 func TestGeneveCompareToIP(t *testing.T) {
747 ns, tearDown := setUpNamedNetlinkTest(t)
748 defer tearDown()
749
750 expected := &Geneve{
751 ID: 0x764332,
752 Remote: net.ParseIP("1.2.3.4"),
753 Dport: 6081,
754 }
755
756
757 cmd := exec.Command("ip", "netns", "exec", ns,
758 "ip", "link", "add", "gen0",
759 "type", "geneve",
760 "vni", fmt.Sprint(expected.ID),
761 "remote", expected.Remote.String(),
762
763
764
765 )
766 out := &bytes.Buffer{}
767 cmd.Stdout = out
768 cmd.Stderr = out
769
770 if rc := cmd.Run(); rc != nil {
771 t.Fatal("failed creating link:", rc, out.String())
772 }
773
774 link, err := LinkByName("gen0")
775 if err != nil {
776 t.Fatal("Failed getting link: ", err)
777 }
778 actual, ok := link.(*Geneve)
779 if !ok {
780 t.Fatalf("resulted interface is not geneve: %T", link)
781 }
782 compareGeneve(t, expected, actual)
783 }
784
785 func TestLinkAddDelGretap(t *testing.T) {
786 tearDown := setUpNetlinkTest(t)
787 defer tearDown()
788
789 testLinkAddDel(t, &Gretap{
790 LinkAttrs: LinkAttrs{Name: "foo4"},
791 IKey: 0x101,
792 OKey: 0x101,
793 PMtuDisc: 1,
794 Local: net.IPv4(127, 0, 0, 1),
795 Remote: net.IPv4(127, 0, 0, 1)})
796
797 testLinkAddDel(t, &Gretap{
798 LinkAttrs: LinkAttrs{Name: "foo6"},
799 IKey: 0x101,
800 OKey: 0x101,
801 Local: net.ParseIP("2001:db8:abcd::1"),
802 Remote: net.ParseIP("2001:db8:ef33::2")})
803 }
804
805 func TestLinkAddDelGretun(t *testing.T) {
806 tearDown := setUpNetlinkTest(t)
807 defer tearDown()
808
809 testLinkAddDel(t, &Gretun{
810 LinkAttrs: LinkAttrs{Name: "foo4"},
811 Local: net.IPv4(127, 0, 0, 1),
812 Remote: net.IPv4(127, 0, 0, 1)})
813
814 testLinkAddDel(t, &Gretun{
815 LinkAttrs: LinkAttrs{Name: "foo6"},
816 Local: net.ParseIP("2001:db8:abcd::1"),
817 Remote: net.ParseIP("2001:db8:ef33::2")})
818 }
819
820 func TestLinkAddDelGretunPointToMultiPoint(t *testing.T) {
821 tearDown := setUpNetlinkTest(t)
822 defer tearDown()
823
824 testLinkAddDel(t, &Gretun{
825 LinkAttrs: LinkAttrs{Name: "foo"},
826 Local: net.IPv4(127, 0, 0, 1),
827 IKey: 1234,
828 OKey: 1234})
829
830 testLinkAddDel(t, &Gretun{
831 LinkAttrs: LinkAttrs{Name: "foo6"},
832 Local: net.ParseIP("2001:db8:1234::4"),
833 IKey: 5678,
834 OKey: 7890})
835 }
836
837 func TestLinkAddDelGretunFlowBased(t *testing.T) {
838 minKernelRequired(t, 4, 3)
839
840 tearDown := setUpNetlinkTest(t)
841 defer tearDown()
842
843 testLinkAddDel(t, &Gretun{
844 LinkAttrs: LinkAttrs{Name: "foo"},
845 FlowBased: true})
846 }
847
848 func TestLinkAddDelGretapFlowBased(t *testing.T) {
849 minKernelRequired(t, 4, 3)
850
851 tearDown := setUpNetlinkTest(t)
852 defer tearDown()
853
854 testLinkAddDel(t, &Gretap{
855 LinkAttrs: LinkAttrs{Name: "foo"},
856 FlowBased: true})
857 }
858
859 func TestLinkAddDelVlan(t *testing.T) {
860 tearDown := setUpNetlinkTest(t)
861 defer tearDown()
862
863 parent := &Dummy{LinkAttrs{Name: "foo"}}
864 if err := LinkAdd(parent); err != nil {
865 t.Fatal(err)
866 }
867
868 testLinkAddDel(t, &Vlan{LinkAttrs{Name: "bar", ParentIndex: parent.Attrs().Index}, 900, VLAN_PROTOCOL_8021Q})
869
870 if err := LinkDel(parent); err != nil {
871 t.Fatal(err)
872 }
873 }
874
875 func TestLinkAddDelMacvlan(t *testing.T) {
876 tearDown := setUpNetlinkTest(t)
877 defer tearDown()
878
879 parent := &Dummy{LinkAttrs{Name: "foo"}}
880 if err := LinkAdd(parent); err != nil {
881 t.Fatal(err)
882 }
883
884 testLinkAddDel(t, &Macvlan{
885 LinkAttrs: LinkAttrs{Name: "bar", ParentIndex: parent.Attrs().Index},
886 Mode: MACVLAN_MODE_PRIVATE,
887 })
888
889 testLinkAddDel(t, &Macvlan{
890 LinkAttrs: LinkAttrs{Name: "bar", ParentIndex: parent.Attrs().Index},
891 Mode: MACVLAN_MODE_BRIDGE,
892 })
893
894 testLinkAddDel(t, &Macvlan{
895 LinkAttrs: LinkAttrs{Name: "bar", ParentIndex: parent.Attrs().Index},
896 Mode: MACVLAN_MODE_VEPA,
897 })
898
899 if err := LinkDel(parent); err != nil {
900 t.Fatal(err)
901 }
902 }
903
904 func TestLinkAddDelMacvtap(t *testing.T) {
905 tearDown := setUpNetlinkTest(t)
906 defer tearDown()
907
908 parent := &Dummy{LinkAttrs{Name: "foo"}}
909 if err := LinkAdd(parent); err != nil {
910 t.Fatal(err)
911 }
912
913 testLinkAddDel(t, &Macvtap{
914 Macvlan: Macvlan{
915 LinkAttrs: LinkAttrs{Name: "bar", ParentIndex: parent.Attrs().Index},
916 Mode: MACVLAN_MODE_PRIVATE,
917 },
918 })
919
920 testLinkAddDel(t, &Macvtap{
921 Macvlan: Macvlan{
922 LinkAttrs: LinkAttrs{Name: "bar", ParentIndex: parent.Attrs().Index},
923 Mode: MACVLAN_MODE_BRIDGE,
924 },
925 })
926
927 testLinkAddDel(t, &Macvtap{
928 Macvlan: Macvlan{
929 LinkAttrs: LinkAttrs{Name: "bar", ParentIndex: parent.Attrs().Index},
930 Mode: MACVLAN_MODE_VEPA,
931 },
932 })
933
934 if err := LinkDel(parent); err != nil {
935 t.Fatal(err)
936 }
937 }
938
939 func TestLinkMacvBCQueueLen(t *testing.T) {
940 minKernelRequired(t, 5, 11)
941
942 tearDown := setUpNetlinkTest(t)
943 defer tearDown()
944
945 parent := &Dummy{LinkAttrs{Name: "foo"}}
946 if err := LinkAdd(parent); err != nil {
947 t.Fatal(err)
948 }
949
950 testLinkAddDel(t, &Macvlan{
951 LinkAttrs: LinkAttrs{Name: "bar", ParentIndex: parent.Attrs().Index},
952 Mode: MACVLAN_MODE_PRIVATE,
953 BCQueueLen: 10000,
954 })
955
956 testLinkAddDel(t, &Macvtap{
957 Macvlan: Macvlan{
958 LinkAttrs: LinkAttrs{Name: "bar", ParentIndex: parent.Attrs().Index},
959 Mode: MACVLAN_MODE_PRIVATE,
960 BCQueueLen: 10000,
961 },
962 })
963
964 if err := LinkDel(parent); err != nil {
965 t.Fatal(err)
966 }
967 }
968
969 func TestNetkitPeerNs(t *testing.T) {
970 minKernelRequired(t, 6, 7)
971 tearDown := setUpNetlinkTest(t)
972 defer tearDown()
973
974 basens, err := netns.Get()
975 if err != nil {
976 t.Fatal("Failed to get basens")
977 }
978 defer basens.Close()
979
980 nsOne, err := netns.New()
981 if err != nil {
982 t.Fatal("Failed to create nsOne")
983 }
984 defer nsOne.Close()
985
986 nsTwo, err := netns.New()
987 if err != nil {
988 t.Fatal("Failed to create nsTwo")
989 }
990 defer nsTwo.Close()
991
992 netkit := &Netkit{
993 LinkAttrs: LinkAttrs{
994 Name: "foo",
995 Namespace: NsFd(basens),
996 },
997 Mode: NETKIT_MODE_L2,
998 Policy: NETKIT_POLICY_FORWARD,
999 PeerPolicy: NETKIT_POLICY_BLACKHOLE,
1000 }
1001 peerAttr := &LinkAttrs{
1002 Name: "bar",
1003 Namespace: NsFd(nsOne),
1004 }
1005 netkit.SetPeerAttrs(peerAttr)
1006
1007 if err := LinkAdd(netkit); err != nil {
1008 t.Fatal(err)
1009 }
1010
1011 _, err = LinkByName("bar")
1012 if err == nil {
1013 t.Fatal("netkit link bar is in nsTwo")
1014 }
1015
1016 _, err = LinkByName("foo")
1017 if err == nil {
1018 t.Fatal("netkit link foo is in nsTwo")
1019 }
1020
1021 err = netns.Set(basens)
1022 if err != nil {
1023 t.Fatal("Failed to set basens")
1024 }
1025
1026 _, err = LinkByName("foo")
1027 if err != nil {
1028 t.Fatal("netkit link foo is not in basens")
1029 }
1030
1031 err = netns.Set(nsOne)
1032 if err != nil {
1033 t.Fatal("Failed to set nsOne")
1034 }
1035
1036 _, err = LinkByName("bar")
1037 if err != nil {
1038 t.Fatal("netkit link bar is not in nsOne")
1039 }
1040 }
1041
1042 func TestLinkAddDelNetkit(t *testing.T) {
1043 minKernelRequired(t, 6, 7)
1044 tearDown := setUpNetlinkTest(t)
1045 defer tearDown()
1046
1047 netkit := &Netkit{
1048 LinkAttrs: LinkAttrs{
1049 Name: "foo",
1050 },
1051 Mode: NETKIT_MODE_L2,
1052 Policy: NETKIT_POLICY_FORWARD,
1053 PeerPolicy: NETKIT_POLICY_BLACKHOLE,
1054 }
1055 peerAttr := &LinkAttrs{
1056 Name: "bar",
1057 }
1058 netkit.SetPeerAttrs(peerAttr)
1059 testLinkAddDel(t, netkit)
1060 }
1061
1062 func TestLinkAddDelVeth(t *testing.T) {
1063 tearDown := setUpNetlinkTest(t)
1064 defer tearDown()
1065
1066 peerMAC, _ := net.ParseMAC("00:12:34:56:78:02")
1067
1068 veth := &Veth{
1069 LinkAttrs: LinkAttrs{
1070 Name: "foo",
1071 TxQLen: testTxQLen,
1072 MTU: 1400,
1073 NumTxQueues: testTxQueues,
1074 NumRxQueues: testRxQueues,
1075 },
1076 PeerName: "bar",
1077 PeerHardwareAddr: peerMAC,
1078 }
1079 testLinkAddDel(t, veth)
1080 }
1081
1082 func TestLinkAddDelBond(t *testing.T) {
1083 minKernelRequired(t, 3, 13)
1084
1085 tearDown := setUpNetlinkTest(t)
1086 defer tearDown()
1087
1088 modes := []string{"802.3ad", "balance-tlb"}
1089 for _, mode := range modes {
1090 bond := NewLinkBond(LinkAttrs{Name: "foo"})
1091 bond.Mode = StringToBondModeMap[mode]
1092 switch mode {
1093 case "802.3ad":
1094 bond.AdSelect = BondAdSelect(BOND_AD_SELECT_BANDWIDTH)
1095 bond.AdActorSysPrio = 1
1096 bond.AdUserPortKey = 1
1097 bond.AdActorSystem, _ = net.ParseMAC("06:aa:bb:cc:dd:ee")
1098 bond.ArpIpTargets = []net.IP{net.ParseIP("1.1.1.1"), net.ParseIP("1.1.1.2")}
1099 case "balance-tlb":
1100 bond.TlbDynamicLb = 1
1101 bond.ArpIpTargets = []net.IP{net.ParseIP("1.1.1.2"), net.ParseIP("1.1.1.1")}
1102 }
1103 testLinkAddDel(t, bond)
1104 }
1105 }
1106
1107 func TestLinkAddVethWithDefaultTxQLen(t *testing.T) {
1108 tearDown := setUpNetlinkTest(t)
1109 defer tearDown()
1110 la := NewLinkAttrs()
1111 la.Name = "foo"
1112
1113 veth := &Veth{LinkAttrs: la, PeerName: "bar"}
1114 if err := LinkAdd(veth); err != nil {
1115 t.Fatal(err)
1116 }
1117 link, err := LinkByName("foo")
1118 if err != nil {
1119 t.Fatal(err)
1120 }
1121 if veth, ok := link.(*Veth); !ok {
1122 t.Fatalf("unexpected link type: %T", link)
1123 } else {
1124 if veth.TxQLen != defaultTxQLen {
1125 t.Fatalf("TxQLen is %d, should be %d", veth.TxQLen, defaultTxQLen)
1126 }
1127 }
1128 peer, err := LinkByName("bar")
1129 if err != nil {
1130 t.Fatal(err)
1131 }
1132 if veth, ok := peer.(*Veth); !ok {
1133 t.Fatalf("unexpected link type: %T", link)
1134 } else {
1135 if veth.TxQLen != defaultTxQLen {
1136 t.Fatalf("TxQLen is %d, should be %d", veth.TxQLen, defaultTxQLen)
1137 }
1138 }
1139 }
1140
1141 func TestLinkAddVethWithZeroTxQLen(t *testing.T) {
1142 tearDown := setUpNetlinkTest(t)
1143 defer tearDown()
1144 la := NewLinkAttrs()
1145 la.Name = "foo"
1146 la.TxQLen = 0
1147
1148 veth := &Veth{LinkAttrs: la, PeerName: "bar"}
1149 if err := LinkAdd(veth); err != nil {
1150 t.Fatal(err)
1151 }
1152 link, err := LinkByName("foo")
1153 if err != nil {
1154 t.Fatal(err)
1155 }
1156 if veth, ok := link.(*Veth); !ok {
1157 t.Fatalf("unexpected link type: %T", link)
1158 } else {
1159 if veth.TxQLen != 0 {
1160 t.Fatalf("TxQLen is %d, should be %d", veth.TxQLen, 0)
1161 }
1162 }
1163 peer, err := LinkByName("bar")
1164 if err != nil {
1165 t.Fatal(err)
1166 }
1167 if veth, ok := peer.(*Veth); !ok {
1168 t.Fatalf("unexpected link type: %T", link)
1169 } else {
1170 if veth.TxQLen != 0 {
1171 t.Fatalf("TxQLen is %d, should be %d", veth.TxQLen, 0)
1172 }
1173 }
1174 }
1175
1176 func TestLinkAddDelDummyWithGSO(t *testing.T) {
1177 const (
1178 gsoMaxSegs = 16
1179 gsoMaxSize = 1 << 14
1180 )
1181 minKernelRequired(t, 4, 16)
1182 tearDown := setUpNetlinkTest(t)
1183 defer tearDown()
1184
1185 dummy := &Dummy{LinkAttrs: LinkAttrs{Name: "foo", GSOMaxSize: gsoMaxSize, GSOMaxSegs: gsoMaxSegs}}
1186 if err := LinkAdd(dummy); err != nil {
1187 t.Fatal(err)
1188 }
1189 link, err := LinkByName("foo")
1190 if err != nil {
1191 t.Fatal(err)
1192 }
1193 dummy, ok := link.(*Dummy)
1194 if !ok {
1195 t.Fatalf("unexpected link type: %T", link)
1196 }
1197
1198 if dummy.GSOMaxSize != gsoMaxSize {
1199 t.Fatalf("GSOMaxSize is %d, should be %d", dummy.GSOMaxSize, gsoMaxSize)
1200 }
1201 if dummy.GSOMaxSegs != gsoMaxSegs {
1202 t.Fatalf("GSOMaxSeg is %d, should be %d", dummy.GSOMaxSegs, gsoMaxSegs)
1203 }
1204 }
1205
1206 func TestLinkAddDelDummyWithGRO(t *testing.T) {
1207 const (
1208 groMaxSize = 1 << 14
1209 )
1210 minKernelRequired(t, 5, 19)
1211 tearDown := setUpNetlinkTest(t)
1212 defer tearDown()
1213
1214 dummy := &Dummy{LinkAttrs: LinkAttrs{Name: "foo", GROMaxSize: groMaxSize}}
1215 if err := LinkAdd(dummy); err != nil {
1216 t.Fatal(err)
1217 }
1218 link, err := LinkByName("foo")
1219 if err != nil {
1220 t.Fatal(err)
1221 }
1222 dummy, ok := link.(*Dummy)
1223 if !ok {
1224 t.Fatalf("unexpected link type: %T", link)
1225 }
1226
1227 if dummy.GROMaxSize != groMaxSize {
1228 t.Fatalf("GROMaxSize is %d, should be %d", dummy.GROMaxSize, groMaxSize)
1229 }
1230 }
1231
1232 func TestLinkAddDummyWithTxQLen(t *testing.T) {
1233 tearDown := setUpNetlinkTest(t)
1234 defer tearDown()
1235 la := NewLinkAttrs()
1236 la.Name = "foo"
1237 la.TxQLen = 1500
1238
1239 dummy := &Dummy{LinkAttrs: la}
1240 if err := LinkAdd(dummy); err != nil {
1241 t.Fatal(err)
1242 }
1243 link, err := LinkByName("foo")
1244 if err != nil {
1245 t.Fatal(err)
1246 }
1247 if dummy, ok := link.(*Dummy); !ok {
1248 t.Fatalf("unexpected link type: %T", link)
1249 } else {
1250 if dummy.TxQLen != 1500 {
1251 t.Fatalf("TxQLen is %d, should be %d", dummy.TxQLen, 1500)
1252 }
1253 }
1254 }
1255
1256 func TestLinkAddDelBridgeMaster(t *testing.T) {
1257 tearDown := setUpNetlinkTest(t)
1258 defer tearDown()
1259
1260 master := &Bridge{LinkAttrs: LinkAttrs{Name: "foo"}}
1261 if err := LinkAdd(master); err != nil {
1262 t.Fatal(err)
1263 }
1264 testLinkAddDel(t, &Dummy{LinkAttrs{Name: "bar", MasterIndex: master.Attrs().Index}})
1265
1266 if err := LinkDel(master); err != nil {
1267 t.Fatal(err)
1268 }
1269 }
1270
1271 func testLinkSetUnsetResetMaster(t *testing.T, master, newmaster Link) {
1272 slave := &Dummy{LinkAttrs{Name: "baz"}}
1273 if err := LinkAdd(slave); err != nil {
1274 t.Fatal(err)
1275 }
1276
1277 nonexistsmaster := &Bridge{LinkAttrs: LinkAttrs{Name: "foobar"}}
1278
1279 if err := LinkSetMaster(slave, nonexistsmaster); err == nil {
1280 t.Fatal("error expected")
1281 }
1282
1283 if err := LinkSetMaster(slave, master); err != nil {
1284 t.Fatal(err)
1285 }
1286
1287 link, err := LinkByName("baz")
1288 if err != nil {
1289 t.Fatal(err)
1290 }
1291
1292 if link.Attrs().MasterIndex != master.Attrs().Index {
1293 t.Fatal("Master not set properly")
1294 }
1295
1296 if err := LinkSetMaster(slave, newmaster); err != nil {
1297 t.Fatal(err)
1298 }
1299
1300 link, err = LinkByName("baz")
1301 if err != nil {
1302 t.Fatal(err)
1303 }
1304
1305 if link.Attrs().MasterIndex != newmaster.Attrs().Index {
1306 t.Fatal("Master not reset properly")
1307 }
1308
1309 if err := LinkSetNoMaster(slave); err != nil {
1310 t.Fatal(err)
1311 }
1312
1313 link, err = LinkByName("baz")
1314 if err != nil {
1315 t.Fatal(err)
1316 }
1317
1318 if link.Attrs().MasterIndex != 0 {
1319 t.Fatal("Master not unset properly")
1320 }
1321 if err := LinkDel(slave); err != nil {
1322 t.Fatal(err)
1323 }
1324 }
1325
1326 func TestLinkSetUnsetResetMaster(t *testing.T) {
1327 tearDown := setUpNetlinkTest(t)
1328 defer tearDown()
1329
1330 master := &Bridge{LinkAttrs: LinkAttrs{Name: "foo"}}
1331 if err := LinkAdd(master); err != nil {
1332 t.Fatal(err)
1333 }
1334
1335 newmaster := &Bridge{LinkAttrs: LinkAttrs{Name: "bar"}}
1336 if err := LinkAdd(newmaster); err != nil {
1337 t.Fatal(err)
1338 }
1339
1340 testLinkSetUnsetResetMaster(t, master, newmaster)
1341
1342 if err := LinkDel(newmaster); err != nil {
1343 t.Fatal(err)
1344 }
1345
1346 if err := LinkDel(master); err != nil {
1347 t.Fatal(err)
1348 }
1349 }
1350
1351 func TestLinkSetUnsetResetMasterBond(t *testing.T) {
1352 tearDown := setUpNetlinkTest(t)
1353 defer tearDown()
1354
1355 master := NewLinkBond(LinkAttrs{Name: "foo"})
1356 master.Mode = BOND_MODE_BALANCE_RR
1357 if err := LinkAdd(master); err != nil {
1358 t.Fatal(err)
1359 }
1360
1361 newmaster := NewLinkBond(LinkAttrs{Name: "bar"})
1362 newmaster.Mode = BOND_MODE_BALANCE_RR
1363 if err := LinkAdd(newmaster); err != nil {
1364 t.Fatal(err)
1365 }
1366
1367 testLinkSetUnsetResetMaster(t, master, newmaster)
1368
1369 if err := LinkDel(newmaster); err != nil {
1370 t.Fatal(err)
1371 }
1372
1373 if err := LinkDel(master); err != nil {
1374 t.Fatal(err)
1375 }
1376 }
1377
1378 func TestLinkSetNs(t *testing.T) {
1379 tearDown := setUpNetlinkTest(t)
1380 defer tearDown()
1381
1382 basens, err := netns.Get()
1383 if err != nil {
1384 t.Fatal("Failed to get basens")
1385 }
1386 defer basens.Close()
1387
1388 newns, err := netns.New()
1389 if err != nil {
1390 t.Fatal("Failed to create newns")
1391 }
1392 defer newns.Close()
1393
1394 link := &Veth{LinkAttrs{Name: "foo"}, "bar", nil, nil}
1395 if err := LinkAdd(link); err != nil {
1396 t.Fatal(err)
1397 }
1398
1399 peer, err := LinkByName("bar")
1400 if err != nil {
1401 t.Fatal(err)
1402 }
1403
1404 LinkSetNsFd(peer, int(basens))
1405 if err != nil {
1406 t.Fatal("Failed to set newns for link")
1407 }
1408
1409 _, err = LinkByName("bar")
1410 if err == nil {
1411 t.Fatal("Link bar is still in newns")
1412 }
1413
1414 err = netns.Set(basens)
1415 if err != nil {
1416 t.Fatal("Failed to set basens")
1417 }
1418
1419 peer, err = LinkByName("bar")
1420 if err != nil {
1421 t.Fatal("Link is not in basens")
1422 }
1423
1424 if err := LinkDel(peer); err != nil {
1425 t.Fatal(err)
1426 }
1427
1428 err = netns.Set(newns)
1429 if err != nil {
1430 t.Fatal("Failed to set newns")
1431 }
1432
1433 _, err = LinkByName("foo")
1434 if err == nil {
1435 t.Fatal("Other half of veth pair not deleted")
1436 }
1437
1438 }
1439
1440 func TestLinkAddDelWireguard(t *testing.T) {
1441 minKernelRequired(t, 5, 6)
1442
1443 tearDown := setUpNetlinkTest(t)
1444 defer tearDown()
1445
1446 testLinkAddDel(t, &Wireguard{LinkAttrs: LinkAttrs{Name: "wg0"}})
1447 }
1448
1449 func TestVethPeerNs(t *testing.T) {
1450 tearDown := setUpNetlinkTest(t)
1451 defer tearDown()
1452
1453 basens, err := netns.Get()
1454 if err != nil {
1455 t.Fatal("Failed to get basens")
1456 }
1457 defer basens.Close()
1458
1459 newns, err := netns.New()
1460 if err != nil {
1461 t.Fatal("Failed to create newns")
1462 }
1463 defer newns.Close()
1464
1465 link := &Veth{LinkAttrs{Name: "foo"}, "bar", nil, NsFd(basens)}
1466 if err := LinkAdd(link); err != nil {
1467 t.Fatal(err)
1468 }
1469
1470 _, err = LinkByName("bar")
1471 if err == nil {
1472 t.Fatal("Link bar is in newns")
1473 }
1474
1475 err = netns.Set(basens)
1476 if err != nil {
1477 t.Fatal("Failed to set basens")
1478 }
1479
1480 _, err = LinkByName("bar")
1481 if err != nil {
1482 t.Fatal("Link bar is not in basens")
1483 }
1484
1485 err = netns.Set(newns)
1486 if err != nil {
1487 t.Fatal("Failed to set newns")
1488 }
1489
1490 _, err = LinkByName("foo")
1491 if err != nil {
1492 t.Fatal("Link foo is not in newns")
1493 }
1494 }
1495
1496 func TestVethPeerNs2(t *testing.T) {
1497 tearDown := setUpNetlinkTest(t)
1498 defer tearDown()
1499
1500 basens, err := netns.Get()
1501 if err != nil {
1502 t.Fatal("Failed to get basens")
1503 }
1504 defer basens.Close()
1505
1506 onens, err := netns.New()
1507 if err != nil {
1508 t.Fatal("Failed to create newns")
1509 }
1510 defer onens.Close()
1511
1512 twons, err := netns.New()
1513 if err != nil {
1514 t.Fatal("Failed to create twons")
1515 }
1516 defer twons.Close()
1517
1518 link := &Veth{LinkAttrs{Name: "foo", Namespace: NsFd(onens)}, "bar", nil, NsFd(basens)}
1519 if err := LinkAdd(link); err != nil {
1520 t.Fatal(err)
1521 }
1522
1523 _, err = LinkByName("foo")
1524 if err == nil {
1525 t.Fatal("Link foo is in twons")
1526 }
1527
1528 _, err = LinkByName("bar")
1529 if err == nil {
1530 t.Fatal("Link bar is in twons")
1531 }
1532
1533 err = netns.Set(basens)
1534 if err != nil {
1535 t.Fatal("Failed to set basens")
1536 }
1537
1538 _, err = LinkByName("bar")
1539 if err != nil {
1540 t.Fatal("Link bar is not in basens")
1541 }
1542
1543 err = netns.Set(onens)
1544 if err != nil {
1545 t.Fatal("Failed to set onens")
1546 }
1547
1548 _, err = LinkByName("foo")
1549 if err != nil {
1550 t.Fatal("Link foo is not in onens")
1551 }
1552 }
1553
1554 func TestLinkAddDelVxlan(t *testing.T) {
1555 tearDown := setUpNetlinkTest(t)
1556 defer tearDown()
1557
1558 parent := &Dummy{
1559 LinkAttrs{Name: "foo"},
1560 }
1561 if err := LinkAdd(parent); err != nil {
1562 t.Fatal(err)
1563 }
1564
1565 vxlan := Vxlan{
1566 LinkAttrs: LinkAttrs{
1567 Name: "bar",
1568 },
1569 VxlanId: 10,
1570 VtepDevIndex: parent.Index,
1571 Learning: true,
1572 L2miss: true,
1573 L3miss: true,
1574 }
1575
1576 testLinkAddDel(t, &vxlan)
1577 if err := LinkDel(parent); err != nil {
1578 t.Fatal(err)
1579 }
1580 }
1581
1582 func TestLinkAddDelVxlanUdpCSum6(t *testing.T) {
1583 minKernelRequired(t, 3, 16)
1584 tearDown := setUpNetlinkTest(t)
1585 defer tearDown()
1586
1587 parent := &Dummy{
1588 LinkAttrs{Name: "foo"},
1589 }
1590 if err := LinkAdd(parent); err != nil {
1591 t.Fatal(err)
1592 }
1593
1594 vxlan := Vxlan{
1595 LinkAttrs: LinkAttrs{
1596 Name: "bar",
1597 },
1598 VxlanId: 10,
1599 VtepDevIndex: parent.Index,
1600 Learning: true,
1601 L2miss: true,
1602 L3miss: true,
1603 UDP6ZeroCSumTx: true,
1604 UDP6ZeroCSumRx: true,
1605 }
1606
1607 testLinkAddDel(t, &vxlan)
1608 if err := LinkDel(parent); err != nil {
1609 t.Fatal(err)
1610 }
1611 }
1612
1613 func TestLinkAddDelVxlanGbp(t *testing.T) {
1614 minKernelRequired(t, 4, 0)
1615
1616 tearDown := setUpNetlinkTest(t)
1617 defer tearDown()
1618
1619 parent := &Dummy{
1620 LinkAttrs{Name: "foo"},
1621 }
1622 if err := LinkAdd(parent); err != nil {
1623 t.Fatal(err)
1624 }
1625
1626 vxlan := Vxlan{
1627 LinkAttrs: LinkAttrs{
1628 Name: "bar",
1629 },
1630 VxlanId: 10,
1631 VtepDevIndex: parent.Index,
1632 Learning: true,
1633 L2miss: true,
1634 L3miss: true,
1635 UDP6ZeroCSumTx: true,
1636 UDP6ZeroCSumRx: true,
1637 GBP: true,
1638 }
1639
1640 testLinkAddDel(t, &vxlan)
1641 if err := LinkDel(parent); err != nil {
1642 t.Fatal(err)
1643 }
1644 }
1645
1646 func TestLinkAddDelVxlanFlowBased(t *testing.T) {
1647 minKernelRequired(t, 4, 3)
1648
1649 tearDown := setUpNetlinkTest(t)
1650 defer tearDown()
1651
1652 vxlan := Vxlan{
1653 LinkAttrs: LinkAttrs{
1654 Name: "foo",
1655 },
1656 Learning: false,
1657 FlowBased: true,
1658 }
1659
1660 testLinkAddDel(t, &vxlan)
1661 }
1662
1663 func TestLinkAddDelBareUDP(t *testing.T) {
1664 minKernelRequired(t, 5, 1)
1665 setUpNetlinkTestWithKModule(t, "bareudp")
1666 tearDown := setUpNetlinkTest(t)
1667 defer tearDown()
1668
1669 testLinkAddDel(t, &BareUDP{
1670 LinkAttrs: LinkAttrs{Name: "foo99"},
1671 Port: 6635,
1672 EtherType: syscall.ETH_P_MPLS_UC,
1673 SrcPortMin: 12345,
1674 MultiProto: true,
1675 })
1676
1677 testLinkAddDel(t, &BareUDP{
1678 LinkAttrs: LinkAttrs{Name: "foo100"},
1679 Port: 6635,
1680 EtherType: syscall.ETH_P_IP,
1681 SrcPortMin: 12345,
1682 MultiProto: true,
1683 })
1684 }
1685
1686 func TestBareUDPCompareToIP(t *testing.T) {
1687 if os.Getenv("CI") == "true" {
1688 t.Skipf("Fails in CI due to old iproute2")
1689 }
1690
1691 minKernelRequired(t, 5, 9)
1692 setUpNetlinkTestWithKModule(t, "bareudp")
1693 ns, tearDown := setUpNamedNetlinkTest(t)
1694 defer tearDown()
1695
1696 expected := &BareUDP{
1697 Port: uint16(6635),
1698 EtherType: syscall.ETH_P_MPLS_UC,
1699 SrcPortMin: 12345,
1700 MultiProto: true,
1701 }
1702
1703
1704 cmd := exec.Command("ip", "netns", "exec", ns,
1705 "ip", "link", "add", "b0",
1706 "type", "bareudp",
1707 "dstport", fmt.Sprint(expected.Port),
1708 "ethertype", "mpls_uc",
1709 "srcportmin", fmt.Sprint(expected.SrcPortMin),
1710 "multiproto",
1711 )
1712 out := &bytes.Buffer{}
1713 cmd.Stdout = out
1714 cmd.Stderr = out
1715
1716 if rc := cmd.Run(); rc != nil {
1717 t.Fatal("failed creating link:", rc, out.String())
1718 }
1719
1720 link, err := LinkByName("b0")
1721 if err != nil {
1722 t.Fatal("Failed getting link: ", err)
1723 }
1724 actual, ok := link.(*BareUDP)
1725 if !ok {
1726 t.Fatalf("resulted interface is not BareUDP: %T", link)
1727 }
1728 compareBareUDP(t, expected, actual)
1729 }
1730
1731 func TestLinkAddDelIPVlanL2(t *testing.T) {
1732 minKernelRequired(t, 4, 2)
1733 tearDown := setUpNetlinkTest(t)
1734 defer tearDown()
1735 parent := &Dummy{LinkAttrs{Name: "foo"}}
1736 if err := LinkAdd(parent); err != nil {
1737 t.Fatal(err)
1738 }
1739
1740 ipv := IPVlan{
1741 LinkAttrs: LinkAttrs{
1742 Name: "bar",
1743 ParentIndex: parent.Index,
1744 },
1745 Mode: IPVLAN_MODE_L2,
1746 }
1747
1748 testLinkAddDel(t, &ipv)
1749 }
1750
1751 func TestLinkAddDelIPVlanL3(t *testing.T) {
1752 minKernelRequired(t, 4, 2)
1753 tearDown := setUpNetlinkTest(t)
1754 defer tearDown()
1755 parent := &Dummy{LinkAttrs{Name: "foo"}}
1756 if err := LinkAdd(parent); err != nil {
1757 t.Fatal(err)
1758 }
1759
1760 ipv := IPVlan{
1761 LinkAttrs: LinkAttrs{
1762 Name: "bar",
1763 ParentIndex: parent.Index,
1764 },
1765 Mode: IPVLAN_MODE_L3,
1766 }
1767
1768 testLinkAddDel(t, &ipv)
1769 }
1770
1771 func TestLinkAddDelIPVlanVepa(t *testing.T) {
1772 minKernelRequired(t, 4, 15)
1773 tearDown := setUpNetlinkTest(t)
1774 defer tearDown()
1775 parent := &Dummy{LinkAttrs{Name: "foo"}}
1776 if err := LinkAdd(parent); err != nil {
1777 t.Fatal(err)
1778 }
1779
1780 ipv := IPVlan{
1781 LinkAttrs: LinkAttrs{
1782 Name: "bar",
1783 ParentIndex: parent.Index,
1784 },
1785 Mode: IPVLAN_MODE_L3,
1786 Flag: IPVLAN_FLAG_VEPA,
1787 }
1788
1789 testLinkAddDel(t, &ipv)
1790 }
1791
1792 func TestLinkAddDelIPVlanNoParent(t *testing.T) {
1793 tearDown := setUpNetlinkTest(t)
1794 defer tearDown()
1795
1796 ipv := IPVlan{
1797 LinkAttrs: LinkAttrs{
1798 Name: "bar",
1799 },
1800 Mode: IPVLAN_MODE_L3,
1801 }
1802 err := LinkAdd(&ipv)
1803 if err == nil {
1804 t.Fatal("Add should fail if ipvlan creating without ParentIndex")
1805 }
1806 if err.Error() != "Can't create ipvlan link without ParentIndex" {
1807 t.Fatalf("Error should be about missing ParentIndex, got %q", err)
1808 }
1809 }
1810
1811 func TestLinkByIndex(t *testing.T) {
1812 tearDown := setUpNetlinkTest(t)
1813 defer tearDown()
1814
1815 dummy := &Dummy{LinkAttrs{Name: "dummy"}}
1816 if err := LinkAdd(dummy); err != nil {
1817 t.Fatal(err)
1818 }
1819
1820 found, err := LinkByIndex(dummy.Index)
1821 if err != nil {
1822 t.Fatal(err)
1823 }
1824
1825 if found.Attrs().Index != dummy.Attrs().Index {
1826 t.Fatalf("Indices don't match: %v != %v", found.Attrs().Index, dummy.Attrs().Index)
1827 }
1828
1829 LinkDel(dummy)
1830
1831
1832 _, err = LinkByIndex(dummy.Attrs().Index)
1833 if err == nil {
1834 t.Fatalf("LinkByIndex(%v) found deleted link", err)
1835 }
1836 }
1837
1838 func TestLinkSet(t *testing.T) {
1839 tearDown := setUpNetlinkTest(t)
1840 defer tearDown()
1841
1842 iface := &Dummy{LinkAttrs{Name: "foo"}}
1843 if err := LinkAdd(iface); err != nil {
1844 t.Fatal(err)
1845 }
1846
1847 link, err := LinkByName("foo")
1848 if err != nil {
1849 t.Fatal(err)
1850 }
1851
1852 err = LinkSetName(link, "bar")
1853 if err != nil {
1854 t.Fatalf("Could not change interface name: %v", err)
1855 }
1856
1857 link, err = LinkByName("bar")
1858 if err != nil {
1859 t.Fatalf("Interface name not changed: %v", err)
1860 }
1861
1862 err = LinkSetMTU(link, 1400)
1863 if err != nil {
1864 t.Fatalf("Could not set MTU: %v", err)
1865 }
1866
1867 link, err = LinkByName("bar")
1868 if err != nil {
1869 t.Fatal(err)
1870 }
1871
1872 if link.Attrs().MTU != 1400 {
1873 t.Fatal("MTU not changed")
1874 }
1875
1876 err = LinkSetTxQLen(link, 500)
1877 if err != nil {
1878 t.Fatalf("Could not set txqlen: %v", err)
1879 }
1880
1881 link, err = LinkByName("bar")
1882 if err != nil {
1883 t.Fatal(err)
1884 }
1885
1886 if link.Attrs().TxQLen != 500 {
1887 t.Fatal("txqlen not changed")
1888 }
1889
1890 addr, err := net.ParseMAC("00:12:34:56:78:AB")
1891 if err != nil {
1892 t.Fatal(err)
1893 }
1894
1895 err = LinkSetHardwareAddr(link, addr)
1896 if err != nil {
1897 t.Fatal(err)
1898 }
1899
1900 link, err = LinkByName("bar")
1901 if err != nil {
1902 t.Fatal(err)
1903 }
1904
1905 if !bytes.Equal(link.Attrs().HardwareAddr, addr) {
1906 t.Fatalf("hardware address not changed")
1907 }
1908
1909 err = LinkSetAlias(link, "barAlias")
1910 if err != nil {
1911 t.Fatalf("Could not set alias: %v", err)
1912 }
1913
1914 link, err = LinkByName("bar")
1915 if err != nil {
1916 t.Fatal(err)
1917 }
1918
1919 if link.Attrs().Alias != "barAlias" {
1920 t.Fatalf("alias not changed")
1921 }
1922
1923 link, err = LinkByAlias("barAlias")
1924 if err != nil {
1925 t.Fatal(err)
1926 }
1927
1928 err = LinkSetGroup(link, 42)
1929 if err != nil {
1930 t.Fatalf("Could not set group: %v", err)
1931 }
1932
1933 link, err = LinkByName("bar")
1934 if err != nil {
1935 t.Fatal(err)
1936 }
1937
1938 if link.Attrs().Group != 42 {
1939 t.Fatal("Link group not changed")
1940 }
1941 }
1942
1943 func TestLinkAltName(t *testing.T) {
1944 tearDown := setUpNetlinkTest(t)
1945 defer tearDown()
1946
1947 iface := &Dummy{LinkAttrs{Name: "bar"}}
1948 if err := LinkAdd(iface); err != nil {
1949 t.Fatal(err)
1950 }
1951
1952 link, err := LinkByName("bar")
1953 if err != nil {
1954 t.Fatal(err)
1955 }
1956
1957 altNames := []string{"altname", "altname2", "some_longer_altname"}
1958 sort.Strings(altNames)
1959 altNamesStr := strings.Join(altNames, ",")
1960
1961 for _, altname := range altNames {
1962 err = LinkAddAltName(link, altname)
1963 if err != nil {
1964 t.Fatalf("Could not add %s: %v", altname, err)
1965 }
1966 }
1967
1968 link, err = LinkByName("bar")
1969 if err != nil {
1970 t.Fatal(err)
1971 }
1972
1973 sort.Strings(link.Attrs().AltNames)
1974 linkAltNamesStr := strings.Join(link.Attrs().AltNames, ",")
1975
1976 if altNamesStr != linkAltNamesStr {
1977 t.Fatalf("Expected %s AltNames, got %s", altNamesStr, linkAltNamesStr)
1978 }
1979
1980 for _, altname := range altNames {
1981 link, err = LinkByName(altname)
1982 if err != nil {
1983 t.Fatal(err)
1984 }
1985 }
1986
1987 for idx, altName := range altNames {
1988 err = LinkDelAltName(link, altName)
1989 if err != nil {
1990 t.Fatalf("Could not delete %s: %v", altName, err)
1991 }
1992
1993 link, err = LinkByName("bar")
1994 if err != nil {
1995 t.Fatal(err)
1996 }
1997
1998 sort.Strings(link.Attrs().AltNames)
1999 linkAltNamesStr := strings.Join(link.Attrs().AltNames, ",")
2000 altNamesStr := strings.Join(altNames[idx+1:], ",")
2001
2002 if linkAltNamesStr != altNamesStr {
2003 t.Fatalf("Expected %s AltNames, got %s", altNamesStr, linkAltNamesStr)
2004 }
2005 }
2006
2007 }
2008
2009 func TestLinkSetARP(t *testing.T) {
2010 tearDown := setUpNetlinkTest(t)
2011 defer tearDown()
2012
2013 iface := &Veth{LinkAttrs: LinkAttrs{Name: "foo", TxQLen: testTxQLen, MTU: 1500}, PeerName: "banana"}
2014 if err := LinkAdd(iface); err != nil {
2015 t.Fatal(err)
2016 }
2017
2018 link, err := LinkByName("foo")
2019 if err != nil {
2020 t.Fatal(err)
2021 }
2022
2023 err = LinkSetARPOff(link)
2024 if err != nil {
2025 t.Fatal(err)
2026 }
2027
2028 link, err = LinkByName("foo")
2029 if err != nil {
2030 t.Fatal(err)
2031 }
2032
2033 if link.Attrs().RawFlags&unix.IFF_NOARP != uint32(unix.IFF_NOARP) {
2034 t.Fatalf("NOARP was not set")
2035 }
2036
2037 err = LinkSetARPOn(link)
2038 if err != nil {
2039 t.Fatal(err)
2040 }
2041
2042 link, err = LinkByName("foo")
2043 if err != nil {
2044 t.Fatal(err)
2045 }
2046
2047 if link.Attrs().RawFlags&unix.IFF_NOARP != 0 {
2048 t.Fatalf("NOARP is still set")
2049 }
2050 }
2051
2052 func expectLinkUpdate(ch <-chan LinkUpdate, ifaceName string, up bool) bool {
2053 for {
2054 timeout := time.After(time.Minute)
2055 select {
2056 case update := <-ch:
2057 if ifaceName == update.Link.Attrs().Name && (update.IfInfomsg.Flags&unix.IFF_UP != 0) == up {
2058 return true
2059 }
2060 case <-timeout:
2061 return false
2062 }
2063 }
2064 }
2065
2066 func TestLinkSubscribe(t *testing.T) {
2067 tearDown := setUpNetlinkTest(t)
2068 defer tearDown()
2069
2070 ch := make(chan LinkUpdate)
2071 done := make(chan struct{})
2072 defer close(done)
2073 if err := LinkSubscribe(ch, done); err != nil {
2074 t.Fatal(err)
2075 }
2076
2077 link := &Veth{LinkAttrs{Name: "foo", TxQLen: testTxQLen, MTU: 1400}, "bar", nil, nil}
2078 if err := LinkAdd(link); err != nil {
2079 t.Fatal(err)
2080 }
2081
2082 if !expectLinkUpdate(ch, "foo", false) {
2083 t.Fatal("Add update not received as expected")
2084 }
2085
2086 if err := LinkSetUp(link); err != nil {
2087 t.Fatal(err)
2088 }
2089
2090 if !expectLinkUpdate(ch, "foo", true) {
2091 t.Fatal("Link Up update not received as expected")
2092 }
2093
2094 if err := LinkDel(link); err != nil {
2095 t.Fatal(err)
2096 }
2097
2098 if !expectLinkUpdate(ch, "foo", false) {
2099 t.Fatal("Del update not received as expected")
2100 }
2101 }
2102
2103 func TestLinkSubscribeWithOptions(t *testing.T) {
2104 tearDown := setUpNetlinkTest(t)
2105 defer tearDown()
2106
2107 ch := make(chan LinkUpdate)
2108 done := make(chan struct{})
2109 defer close(done)
2110 var lastError error
2111 defer func() {
2112 if lastError != nil {
2113 t.Fatalf("Fatal error received during subscription: %v", lastError)
2114 }
2115 }()
2116 if err := LinkSubscribeWithOptions(ch, done, LinkSubscribeOptions{
2117 ErrorCallback: func(err error) {
2118 lastError = err
2119 },
2120 }); err != nil {
2121 t.Fatal(err)
2122 }
2123
2124 link := &Veth{LinkAttrs{Name: "foo", TxQLen: testTxQLen, MTU: 1400}, "bar", nil, nil}
2125 if err := LinkAdd(link); err != nil {
2126 t.Fatal(err)
2127 }
2128
2129 if !expectLinkUpdate(ch, "foo", false) {
2130 t.Fatal("Add update not received as expected")
2131 }
2132 }
2133
2134 func TestLinkSubscribeAt(t *testing.T) {
2135 skipUnlessRoot(t)
2136
2137
2138 newNs, err := netns.New()
2139 if err != nil {
2140 t.Fatal(err)
2141 }
2142 defer newNs.Close()
2143
2144 nh, err := NewHandleAt(newNs)
2145 if err != nil {
2146 t.Fatal(err)
2147 }
2148 defer nh.Close()
2149
2150
2151 ch := make(chan LinkUpdate)
2152 done := make(chan struct{})
2153 defer close(done)
2154 if err := LinkSubscribeAt(newNs, ch, done); err != nil {
2155 t.Fatal(err)
2156 }
2157
2158 link := &Veth{LinkAttrs{Name: "test", TxQLen: testTxQLen, MTU: 1400}, "bar", nil, nil}
2159 if err := nh.LinkAdd(link); err != nil {
2160 t.Fatal(err)
2161 }
2162
2163 if !expectLinkUpdate(ch, "test", false) {
2164 t.Fatal("Add update not received as expected")
2165 }
2166
2167 if err := nh.LinkSetUp(link); err != nil {
2168 t.Fatal(err)
2169 }
2170
2171 if !expectLinkUpdate(ch, "test", true) {
2172 t.Fatal("Link Up update not received as expected")
2173 }
2174
2175 if err := nh.LinkDel(link); err != nil {
2176 t.Fatal(err)
2177 }
2178
2179 if !expectLinkUpdate(ch, "test", false) {
2180 t.Fatal("Del update not received as expected")
2181 }
2182 }
2183
2184 func TestLinkSubscribeListExisting(t *testing.T) {
2185 skipUnlessRoot(t)
2186
2187
2188 newNs, err := netns.New()
2189 if err != nil {
2190 t.Fatal(err)
2191 }
2192 defer newNs.Close()
2193
2194 nh, err := NewHandleAt(newNs)
2195 if err != nil {
2196 t.Fatal(err)
2197 }
2198 defer nh.Close()
2199
2200 link := &Veth{LinkAttrs{Name: "test", TxQLen: testTxQLen, MTU: 1400}, "bar", nil, nil}
2201 if err := nh.LinkAdd(link); err != nil {
2202 t.Fatal(err)
2203 }
2204
2205
2206 ch := make(chan LinkUpdate)
2207 done := make(chan struct{})
2208 defer close(done)
2209 if err := LinkSubscribeWithOptions(ch, done, LinkSubscribeOptions{
2210 Namespace: &newNs,
2211 ListExisting: true},
2212 ); err != nil {
2213 t.Fatal(err)
2214 }
2215
2216 if !expectLinkUpdate(ch, "test", false) {
2217 t.Fatal("Add update not received as expected")
2218 }
2219
2220 if err := nh.LinkSetUp(link); err != nil {
2221 t.Fatal(err)
2222 }
2223
2224 if !expectLinkUpdate(ch, "test", true) {
2225 t.Fatal("Link Up update not received as expected")
2226 }
2227
2228 if err := nh.LinkDel(link); err != nil {
2229 t.Fatal(err)
2230 }
2231
2232 if !expectLinkUpdate(ch, "test", false) {
2233 t.Fatal("Del update not received as expected")
2234 }
2235 }
2236
2237 func TestLinkStats(t *testing.T) {
2238 defer setUpNetlinkTest(t)()
2239
2240
2241
2242 v0 := "v0"
2243 v1 := "v1"
2244
2245 vethLink := &Veth{LinkAttrs: LinkAttrs{Name: v0}, PeerName: v1}
2246 if err := LinkAdd(vethLink); err != nil {
2247 t.Fatal(err)
2248 }
2249
2250 veth0, err := LinkByName(v0)
2251 if err != nil {
2252 t.Fatal(err)
2253 }
2254 if err := LinkSetUp(veth0); err != nil {
2255 t.Fatal(err)
2256 }
2257
2258 veth1, err := LinkByName(v1)
2259 if err != nil {
2260 t.Fatal(err)
2261 }
2262 if err := LinkSetUp(veth1); err != nil {
2263 t.Fatal(err)
2264 }
2265
2266 time.Sleep(2 * time.Second)
2267
2268
2269 veth0, err = LinkByName(v0)
2270 if err != nil {
2271 t.Fatal(err)
2272 }
2273 veth1, err = LinkByName(v1)
2274 if err != nil {
2275 t.Fatal(err)
2276 }
2277 v0Stats := veth0.Attrs().Statistics
2278 v1Stats := veth1.Attrs().Statistics
2279 if v0Stats.RxPackets != v1Stats.TxPackets || v0Stats.TxPackets != v1Stats.RxPackets ||
2280 v0Stats.RxBytes != v1Stats.TxBytes || v0Stats.TxBytes != v1Stats.RxBytes {
2281 t.Fatalf("veth ends counters differ:\n%v\n%v", v0Stats, v1Stats)
2282 }
2283 }
2284
2285 func TestLinkXdp(t *testing.T) {
2286 links, err := LinkList()
2287 if err != nil {
2288 t.Fatal(err)
2289 }
2290 var testXdpLink Link
2291 for _, link := range links {
2292 if link.Attrs().Xdp != nil && !link.Attrs().Xdp.Attached {
2293 testXdpLink = link
2294 break
2295 }
2296 }
2297 if testXdpLink == nil {
2298 t.Skipf("No link supporting XDP found")
2299 }
2300 fd, err := loadSimpleBpf(BPF_PROG_TYPE_XDP, 2 )
2301 if err != nil {
2302 t.Skipf("Loading bpf program failed: %s", err)
2303 }
2304 if err := LinkSetXdpFd(testXdpLink, fd); err != nil {
2305 t.Fatal(err)
2306 }
2307 if err := LinkSetXdpFdWithFlags(testXdpLink, fd, nl.XDP_FLAGS_UPDATE_IF_NOEXIST); !errors.Is(err, unix.EBUSY) {
2308 t.Fatal(err)
2309 }
2310 if err := LinkSetXdpFd(testXdpLink, -1); err != nil {
2311 t.Fatal(err)
2312 }
2313 }
2314
2315 func TestLinkAddDelIptun(t *testing.T) {
2316 minKernelRequired(t, 4, 9)
2317 tearDown := setUpNetlinkTest(t)
2318 defer tearDown()
2319
2320 testLinkAddDel(t, &Iptun{
2321 LinkAttrs: LinkAttrs{Name: "iptunfoo"},
2322 PMtuDisc: 1,
2323 Local: net.IPv4(127, 0, 0, 1),
2324 Remote: net.IPv4(127, 0, 0, 1)})
2325 }
2326
2327 func TestLinkAddDelIptunFlowBased(t *testing.T) {
2328 minKernelRequired(t, 4, 9)
2329 tearDown := setUpNetlinkTest(t)
2330 defer tearDown()
2331
2332 testLinkAddDel(t, &Iptun{
2333 LinkAttrs: LinkAttrs{Name: "iptunflowfoo"},
2334 FlowBased: true,
2335 })
2336 }
2337
2338 func TestLinkAddDelIp6tnl(t *testing.T) {
2339 tearDown := setUpNetlinkTest(t)
2340 defer tearDown()
2341
2342 testLinkAddDel(t, &Ip6tnl{
2343 LinkAttrs: LinkAttrs{Name: "ip6tnltest"},
2344 Local: net.ParseIP("2001:db8::100"),
2345 Remote: net.ParseIP("2001:db8::200"),
2346 })
2347 }
2348
2349 func TestLinkAddDelIp6tnlFlowbased(t *testing.T) {
2350 tearDown := setUpNetlinkTest(t)
2351 defer tearDown()
2352
2353 testLinkAddDel(t, &Ip6tnl{
2354 LinkAttrs: LinkAttrs{Name: "ip6tnltest"},
2355 FlowBased: true,
2356 })
2357 }
2358
2359 func TestLinkAddDelSittun(t *testing.T) {
2360 tearDown := setUpNetlinkTest(t)
2361 defer tearDown()
2362
2363 testLinkAddDel(t, &Sittun{
2364 LinkAttrs: LinkAttrs{Name: "sittunfoo"},
2365 PMtuDisc: 1,
2366 Local: net.IPv4(127, 0, 0, 1),
2367 Remote: net.IPv4(127, 0, 0, 1)})
2368 }
2369
2370 func TestLinkAddDelVti(t *testing.T) {
2371 tearDown := setUpNetlinkTest(t)
2372 defer tearDown()
2373
2374 testLinkAddDel(t, &Vti{
2375 LinkAttrs: LinkAttrs{Name: "vtifoo"},
2376 IKey: 0x101,
2377 OKey: 0x101,
2378 Local: net.IPv4(127, 0, 0, 1),
2379 Remote: net.IPv4(127, 0, 0, 1)})
2380
2381 testLinkAddDel(t, &Vti{
2382 LinkAttrs: LinkAttrs{Name: "vtibar"},
2383 IKey: 0x101,
2384 OKey: 0x101,
2385 Local: net.IPv6loopback,
2386 Remote: net.IPv6loopback})
2387 }
2388
2389 func TestLinkSetGSOMaxSize(t *testing.T) {
2390 minKernelRequired(t, 5, 19)
2391 tearDown := setUpNetlinkTest(t)
2392 defer tearDown()
2393
2394 iface := &Veth{LinkAttrs: LinkAttrs{Name: "foo", TxQLen: testTxQLen, MTU: 1500}, PeerName: "bar"}
2395 if err := LinkAdd(iface); err != nil {
2396 t.Fatal(err)
2397 }
2398
2399 link, err := LinkByName("foo")
2400 if err != nil {
2401 t.Fatal(err)
2402 }
2403
2404 err = LinkSetGSOMaxSize(link, 32768)
2405 if err != nil {
2406 t.Fatal(err)
2407 }
2408
2409 link, err = LinkByName("foo")
2410 if err != nil {
2411 t.Fatal(err)
2412 }
2413
2414 if link.Attrs().GSOMaxSize != 32768 {
2415 t.Fatalf("GSO max size was not modified")
2416 }
2417 }
2418
2419 func TestLinkSetGSOMaxSegs(t *testing.T) {
2420 minKernelRequired(t, 5, 19)
2421 tearDown := setUpNetlinkTest(t)
2422 defer tearDown()
2423
2424 iface := &Veth{LinkAttrs: LinkAttrs{Name: "foo", TxQLen: testTxQLen, MTU: 1500}, PeerName: "bar"}
2425 if err := LinkAdd(iface); err != nil {
2426 t.Fatal(err)
2427 }
2428
2429 link, err := LinkByName("foo")
2430 if err != nil {
2431 t.Fatal(err)
2432 }
2433
2434 err = LinkSetGSOMaxSegs(link, 16)
2435 if err != nil {
2436 t.Fatal(err)
2437 }
2438
2439 link, err = LinkByName("foo")
2440 if err != nil {
2441 t.Fatal(err)
2442 }
2443
2444 if link.Attrs().GSOMaxSegs != 16 {
2445 t.Fatalf("GSO max segments was not modified")
2446 }
2447 }
2448
2449 func TestLinkSetGROMaxSize(t *testing.T) {
2450 minKernelRequired(t, 5, 19)
2451 tearDown := setUpNetlinkTest(t)
2452 defer tearDown()
2453
2454 iface := &Veth{LinkAttrs: LinkAttrs{Name: "foo", TxQLen: testTxQLen, MTU: 1500}, PeerName: "bar"}
2455 if err := LinkAdd(iface); err != nil {
2456 t.Fatal(err)
2457 }
2458
2459 link, err := LinkByName("foo")
2460 if err != nil {
2461 t.Fatal(err)
2462 }
2463
2464 err = LinkSetGROMaxSize(link, 32768)
2465 if err != nil {
2466 t.Fatal(err)
2467 }
2468
2469 link, err = LinkByName("foo")
2470 if err != nil {
2471 t.Fatal(err)
2472 }
2473
2474 if link.Attrs().GROMaxSize != 32768 {
2475 t.Fatalf("GRO max size was not modified")
2476 }
2477 }
2478
2479 func TestLinkGetTSOMax(t *testing.T) {
2480 minKernelRequired(t, 5, 19)
2481 tearDown := setUpNetlinkTest(t)
2482 defer tearDown()
2483
2484 iface := &Veth{LinkAttrs: LinkAttrs{Name: "foo", TxQLen: testTxQLen, MTU: 1500}, PeerName: "bar"}
2485 if err := LinkAdd(iface); err != nil {
2486 t.Fatal(err)
2487 }
2488
2489 link, err := LinkByName("foo")
2490 if err != nil {
2491 t.Fatal(err)
2492 }
2493
2494 if link.Attrs().TSOMaxSize != 524280 || link.Attrs().TSOMaxSegs != 65535 {
2495 t.Fatalf("TSO max size and segments could not be retrieved")
2496 }
2497 }
2498
2499 func TestLinkSetGSOIPv4MaxSize(t *testing.T) {
2500 minKernelRequired(t, 6, 3)
2501 tearDown := setUpNetlinkTest(t)
2502 defer tearDown()
2503
2504 iface := &Veth{LinkAttrs: LinkAttrs{Name: "foo", TxQLen: testTxQLen, MTU: 1500}, PeerName: "bar"}
2505 if err := LinkAdd(iface); err != nil {
2506 t.Fatal(err)
2507 }
2508
2509 link, err := LinkByName("foo")
2510 if err != nil {
2511 t.Fatal(err)
2512 }
2513
2514 err = LinkSetGSOIPv4MaxSize(link, 32768)
2515 if err != nil {
2516 t.Fatal(err)
2517 }
2518
2519 link, err = LinkByName("foo")
2520 if err != nil {
2521 t.Fatal(err)
2522 }
2523
2524 if link.Attrs().GSOIPv4MaxSize != 32768 {
2525 t.Fatalf("GSO max size was not modified")
2526 }
2527 }
2528
2529 func TestLinkSetGROIPv4MaxSize(t *testing.T) {
2530 minKernelRequired(t, 6, 3)
2531 tearDown := setUpNetlinkTest(t)
2532 defer tearDown()
2533
2534 iface := &Veth{LinkAttrs: LinkAttrs{Name: "foo", TxQLen: testTxQLen, MTU: 1500}, PeerName: "bar"}
2535 if err := LinkAdd(iface); err != nil {
2536 t.Fatal(err)
2537 }
2538
2539 link, err := LinkByName("foo")
2540 if err != nil {
2541 t.Fatal(err)
2542 }
2543
2544 err = LinkSetGROIPv4MaxSize(link, 32768)
2545 if err != nil {
2546 t.Fatal(err)
2547 }
2548
2549 link, err = LinkByName("foo")
2550 if err != nil {
2551 t.Fatal(err)
2552 }
2553
2554 if link.Attrs().GROIPv4MaxSize != 32768 {
2555 t.Fatalf("GRO max size was not modified")
2556 }
2557 }
2558
2559 func TestBridgeCreationWithMulticastSnooping(t *testing.T) {
2560 minKernelRequired(t, 4, 4)
2561
2562 tearDown := setUpNetlinkTest(t)
2563 defer tearDown()
2564
2565 bridgeWithDefaultMcastSnoopName := "foo"
2566 bridgeWithDefaultMcastSnoop := &Bridge{LinkAttrs: LinkAttrs{Name: bridgeWithDefaultMcastSnoopName}}
2567 if err := LinkAdd(bridgeWithDefaultMcastSnoop); err != nil {
2568 t.Fatal(err)
2569 }
2570 expectMcastSnooping(t, bridgeWithDefaultMcastSnoopName, true)
2571 if err := LinkDel(bridgeWithDefaultMcastSnoop); err != nil {
2572 t.Fatal(err)
2573 }
2574
2575 mcastSnoop := true
2576 bridgeWithMcastSnoopOnName := "bar"
2577 bridgeWithMcastSnoopOn := &Bridge{LinkAttrs: LinkAttrs{Name: bridgeWithMcastSnoopOnName}, MulticastSnooping: &mcastSnoop}
2578 if err := LinkAdd(bridgeWithMcastSnoopOn); err != nil {
2579 t.Fatal(err)
2580 }
2581 expectMcastSnooping(t, bridgeWithMcastSnoopOnName, true)
2582 if err := LinkDel(bridgeWithMcastSnoopOn); err != nil {
2583 t.Fatal(err)
2584 }
2585
2586 mcastSnoop = false
2587 bridgeWithMcastSnoopOffName := "foobar"
2588 bridgeWithMcastSnoopOff := &Bridge{LinkAttrs: LinkAttrs{Name: bridgeWithMcastSnoopOffName}, MulticastSnooping: &mcastSnoop}
2589 if err := LinkAdd(bridgeWithMcastSnoopOff); err != nil {
2590 t.Fatal(err)
2591 }
2592 expectMcastSnooping(t, bridgeWithMcastSnoopOffName, false)
2593 if err := LinkDel(bridgeWithMcastSnoopOff); err != nil {
2594 t.Fatal(err)
2595 }
2596 }
2597
2598 func TestBridgeSetMcastSnoop(t *testing.T) {
2599 minKernelRequired(t, 4, 4)
2600
2601 tearDown := setUpNetlinkTest(t)
2602 defer tearDown()
2603
2604 bridgeName := "foo"
2605 bridge := &Bridge{LinkAttrs: LinkAttrs{Name: bridgeName}}
2606 if err := LinkAdd(bridge); err != nil {
2607 t.Fatal(err)
2608 }
2609 expectMcastSnooping(t, bridgeName, true)
2610
2611 if err := BridgeSetMcastSnoop(bridge, false); err != nil {
2612 t.Fatal(err)
2613 }
2614 expectMcastSnooping(t, bridgeName, false)
2615
2616 if err := BridgeSetMcastSnoop(bridge, true); err != nil {
2617 t.Fatal(err)
2618 }
2619 expectMcastSnooping(t, bridgeName, true)
2620
2621 if err := LinkDel(bridge); err != nil {
2622 t.Fatal(err)
2623 }
2624 }
2625
2626 func expectMcastSnooping(t *testing.T, linkName string, expected bool) {
2627 bridge, err := LinkByName(linkName)
2628 if err != nil {
2629 t.Fatal(err)
2630 }
2631
2632 if actual := *bridge.(*Bridge).MulticastSnooping; actual != expected {
2633 t.Fatalf("expected %t got %t", expected, actual)
2634 }
2635 }
2636
2637 func TestBridgeSetVlanFiltering(t *testing.T) {
2638 minKernelRequired(t, 4, 4)
2639
2640 tearDown := setUpNetlinkTest(t)
2641 defer tearDown()
2642
2643 bridgeName := "foo"
2644 bridge := &Bridge{LinkAttrs: LinkAttrs{Name: bridgeName}}
2645 if err := LinkAdd(bridge); err != nil {
2646 t.Fatal(err)
2647 }
2648 expectVlanFiltering(t, bridgeName, false)
2649
2650 if err := BridgeSetVlanFiltering(bridge, true); err != nil {
2651 t.Fatal(err)
2652 }
2653 expectVlanFiltering(t, bridgeName, true)
2654
2655 if err := BridgeSetVlanFiltering(bridge, false); err != nil {
2656 t.Fatal(err)
2657 }
2658 expectVlanFiltering(t, bridgeName, false)
2659
2660 if err := LinkDel(bridge); err != nil {
2661 t.Fatal(err)
2662 }
2663 }
2664
2665 func TestBridgeDefaultPVID(t *testing.T) {
2666 minKernelRequired(t, 4, 4)
2667
2668 tearDown := setUpNetlinkTest(t)
2669 defer tearDown()
2670
2671 bridgeName := "foo"
2672 bridge := &Bridge{LinkAttrs: LinkAttrs{Name: bridgeName}}
2673 if err := LinkAdd(bridge); err != nil {
2674 t.Fatal(err)
2675 }
2676 expectVlanDefaultPVID(t, bridgeName, 1)
2677
2678 if err := BridgeSetVlanDefaultPVID(bridge, 100); err != nil {
2679 t.Fatal(err)
2680 }
2681 expectVlanDefaultPVID(t, bridgeName, 100)
2682
2683 if err := BridgeSetVlanDefaultPVID(bridge, 0); err != nil {
2684 t.Fatal(err)
2685 }
2686 expectVlanDefaultPVID(t, bridgeName, 0)
2687
2688 if err := LinkDel(bridge); err != nil {
2689 t.Fatal(err)
2690 }
2691 }
2692
2693 func expectVlanFiltering(t *testing.T, linkName string, expected bool) {
2694 bridge, err := LinkByName(linkName)
2695 if err != nil {
2696 t.Fatal(err)
2697 }
2698
2699 if actual := *bridge.(*Bridge).VlanFiltering; actual != expected {
2700 t.Fatalf("expected %t got %t", expected, actual)
2701 }
2702 }
2703
2704 func expectVlanDefaultPVID(t *testing.T, linkName string, expected uint16) {
2705 bridge, err := LinkByName(linkName)
2706 if err != nil {
2707 t.Fatal(err)
2708 }
2709
2710 if actual := *bridge.(*Bridge).VlanDefaultPVID; actual != expected {
2711 t.Fatalf("expected %d got %d", expected, actual)
2712 }
2713 }
2714
2715 func TestBridgeCreationWithAgeingTime(t *testing.T) {
2716 minKernelRequired(t, 3, 18)
2717
2718 tearDown := setUpNetlinkTest(t)
2719 defer tearDown()
2720
2721 bridgeWithSpecifiedAgeingTimeName := "foo"
2722 ageingTime := uint32(20000)
2723 bridgeWithSpecifiedAgeingTime := &Bridge{LinkAttrs: LinkAttrs{Name: bridgeWithSpecifiedAgeingTimeName}, AgeingTime: &ageingTime}
2724 if err := LinkAdd(bridgeWithSpecifiedAgeingTime); err != nil {
2725 t.Fatal(err)
2726 }
2727
2728 retrievedBridge, err := LinkByName(bridgeWithSpecifiedAgeingTimeName)
2729 if err != nil {
2730 t.Fatal(err)
2731 }
2732
2733 actualAgeingTime := *retrievedBridge.(*Bridge).AgeingTime
2734 if actualAgeingTime != ageingTime {
2735 t.Fatalf("expected %d got %d", ageingTime, actualAgeingTime)
2736 }
2737 if err := LinkDel(bridgeWithSpecifiedAgeingTime); err != nil {
2738 t.Fatal(err)
2739 }
2740
2741 bridgeWithDefaultAgeingTimeName := "bar"
2742 bridgeWithDefaultAgeingTime := &Bridge{LinkAttrs: LinkAttrs{Name: bridgeWithDefaultAgeingTimeName}}
2743 if err := LinkAdd(bridgeWithDefaultAgeingTime); err != nil {
2744 t.Fatal(err)
2745 }
2746
2747 retrievedBridge, err = LinkByName(bridgeWithDefaultAgeingTimeName)
2748 if err != nil {
2749 t.Fatal(err)
2750 }
2751
2752 actualAgeingTime = *retrievedBridge.(*Bridge).AgeingTime
2753 if actualAgeingTime != 30000 {
2754 t.Fatalf("expected %d got %d", 30000, actualAgeingTime)
2755 }
2756 if err := LinkDel(bridgeWithDefaultAgeingTime); err != nil {
2757 t.Fatal(err)
2758 }
2759 }
2760
2761 func TestBridgeCreationWithHelloTime(t *testing.T) {
2762 minKernelRequired(t, 3, 18)
2763
2764 tearDown := setUpNetlinkTest(t)
2765 defer tearDown()
2766
2767 bridgeWithSpecifiedHelloTimeName := "foo"
2768 helloTime := uint32(300)
2769 bridgeWithSpecifiedHelloTime := &Bridge{LinkAttrs: LinkAttrs{Name: bridgeWithSpecifiedHelloTimeName}, HelloTime: &helloTime}
2770 if err := LinkAdd(bridgeWithSpecifiedHelloTime); err != nil {
2771 t.Fatal(err)
2772 }
2773
2774 retrievedBridge, err := LinkByName(bridgeWithSpecifiedHelloTimeName)
2775 if err != nil {
2776 t.Fatal(err)
2777 }
2778
2779 actualHelloTime := *retrievedBridge.(*Bridge).HelloTime
2780 if actualHelloTime != helloTime {
2781 t.Fatalf("expected %d got %d", helloTime, actualHelloTime)
2782 }
2783 if err := LinkDel(bridgeWithSpecifiedHelloTime); err != nil {
2784 t.Fatal(err)
2785 }
2786
2787 bridgeWithDefaultHelloTimeName := "bar"
2788 bridgeWithDefaultHelloTime := &Bridge{LinkAttrs: LinkAttrs{Name: bridgeWithDefaultHelloTimeName}}
2789 if err := LinkAdd(bridgeWithDefaultHelloTime); err != nil {
2790 t.Fatal(err)
2791 }
2792
2793 retrievedBridge, err = LinkByName(bridgeWithDefaultHelloTimeName)
2794 if err != nil {
2795 t.Fatal(err)
2796 }
2797
2798 actualHelloTime = *retrievedBridge.(*Bridge).HelloTime
2799 if actualHelloTime != 200 {
2800 t.Fatalf("expected %d got %d", 200, actualHelloTime)
2801 }
2802 if err := LinkDel(bridgeWithDefaultHelloTime); err != nil {
2803 t.Fatal(err)
2804 }
2805 }
2806
2807 func TestBridgeCreationWithVlanFiltering(t *testing.T) {
2808 minKernelRequired(t, 3, 18)
2809
2810 tearDown := setUpNetlinkTest(t)
2811 defer tearDown()
2812
2813 bridgeWithVlanFilteringEnabledName := "foo"
2814 vlanFiltering := true
2815 bridgeWithVlanFilteringEnabled := &Bridge{LinkAttrs: LinkAttrs{Name: bridgeWithVlanFilteringEnabledName}, VlanFiltering: &vlanFiltering}
2816 if err := LinkAdd(bridgeWithVlanFilteringEnabled); err != nil {
2817 t.Fatal(err)
2818 }
2819
2820 retrievedBridge, err := LinkByName(bridgeWithVlanFilteringEnabledName)
2821 if err != nil {
2822 t.Fatal(err)
2823 }
2824
2825 retrievedVlanFilteringState := *retrievedBridge.(*Bridge).VlanFiltering
2826 if retrievedVlanFilteringState != vlanFiltering {
2827 t.Fatalf("expected %t got %t", vlanFiltering, retrievedVlanFilteringState)
2828 }
2829 if err := LinkDel(bridgeWithVlanFilteringEnabled); err != nil {
2830 t.Fatal(err)
2831 }
2832
2833 bridgeWithDefaultVlanFilteringName := "bar"
2834 bridgeWIthDefaultVlanFiltering := &Bridge{LinkAttrs: LinkAttrs{Name: bridgeWithDefaultVlanFilteringName}}
2835 if err := LinkAdd(bridgeWIthDefaultVlanFiltering); err != nil {
2836 t.Fatal(err)
2837 }
2838
2839 retrievedBridge, err = LinkByName(bridgeWithDefaultVlanFilteringName)
2840 if err != nil {
2841 t.Fatal(err)
2842 }
2843
2844 retrievedVlanFilteringState = *retrievedBridge.(*Bridge).VlanFiltering
2845 if retrievedVlanFilteringState != false {
2846 t.Fatalf("expected %t got %t", false, retrievedVlanFilteringState)
2847 }
2848 if err := LinkDel(bridgeWIthDefaultVlanFiltering); err != nil {
2849 t.Fatal(err)
2850 }
2851 }
2852
2853 func TestLinkSubscribeWithProtinfo(t *testing.T) {
2854 tearDown := setUpNetlinkTest(t)
2855 defer tearDown()
2856
2857 master := &Bridge{LinkAttrs: LinkAttrs{Name: "foo"}}
2858 if err := LinkAdd(master); err != nil {
2859 t.Fatal(err)
2860 }
2861
2862 slave := &Veth{
2863 LinkAttrs: LinkAttrs{
2864 Name: "bar",
2865 TxQLen: testTxQLen,
2866 MTU: 1400,
2867 MasterIndex: master.Attrs().Index,
2868 },
2869 PeerName: "bar-peer",
2870 }
2871 if err := LinkAdd(slave); err != nil {
2872 t.Fatal(err)
2873 }
2874
2875 ch := make(chan LinkUpdate)
2876 done := make(chan struct{})
2877 defer close(done)
2878 if err := LinkSubscribe(ch, done); err != nil {
2879 t.Fatal(err)
2880 }
2881
2882 if err := LinkSetHairpin(slave, true); err != nil {
2883 t.Fatal(err)
2884 }
2885
2886 select {
2887 case update := <-ch:
2888 if !(update.Attrs().Name == "bar" && update.Attrs().Protinfo != nil &&
2889 update.Attrs().Protinfo.Hairpin) {
2890 t.Fatal("Hairpin update not received as expected")
2891 }
2892 case <-time.After(time.Minute):
2893 t.Fatal("Hairpin update timed out")
2894 }
2895
2896 if err := LinkDel(slave); err != nil {
2897 t.Fatal(err)
2898 }
2899
2900 if err := LinkDel(master); err != nil {
2901 t.Fatal(err)
2902 }
2903 }
2904
2905 func testGTPLink(t *testing.T) *GTP {
2906 conn1, err := net.ListenUDP("udp", &net.UDPAddr{
2907 IP: net.ParseIP("0.0.0.0"),
2908 Port: 3386,
2909 })
2910 if err != nil {
2911 t.Fatal(err)
2912 }
2913 conn2, err := net.ListenUDP("udp", &net.UDPAddr{
2914 IP: net.ParseIP("0.0.0.0"),
2915 Port: 2152,
2916 })
2917 if err != nil {
2918 t.Fatal(err)
2919 }
2920 fd1, _ := conn1.File()
2921 fd2, _ := conn2.File()
2922 return >P{
2923 LinkAttrs: LinkAttrs{
2924 Name: "gtp0",
2925 },
2926 FD0: int(fd1.Fd()),
2927 FD1: int(fd2.Fd()),
2928 }
2929 }
2930
2931 func TestLinkAddDelGTP(t *testing.T) {
2932 tearDown := setUpNetlinkTestWithKModule(t, "gtp")
2933 defer tearDown()
2934 gtp := testGTPLink(t)
2935 testLinkAddDel(t, gtp)
2936 }
2937
2938 func TestLinkAddDelXfrmi(t *testing.T) {
2939 minKernelRequired(t, 4, 19)
2940 defer setUpNetlinkTest(t)()
2941
2942 lo, _ := LinkByName("lo")
2943
2944 testLinkAddDel(t, &Xfrmi{
2945 LinkAttrs: LinkAttrs{Name: "xfrm123", ParentIndex: lo.Attrs().Index},
2946 Ifid: 123})
2947 }
2948
2949 func TestLinkAddDelXfrmiNoId(t *testing.T) {
2950 minKernelRequired(t, 4, 19)
2951 defer setUpNetlinkTest(t)()
2952
2953 lo, _ := LinkByName("lo")
2954
2955 err := LinkAdd(&Xfrmi{
2956 LinkAttrs: LinkAttrs{Name: "xfrm0", ParentIndex: lo.Attrs().Index}})
2957 if !errors.Is(err, unix.EINVAL) {
2958 t.Errorf("Error returned expected to be EINVAL")
2959 }
2960
2961 }
2962
2963 func TestLinkByNameWhenLinkIsNotFound(t *testing.T) {
2964 _, err := LinkByName("iammissing")
2965 if err == nil {
2966 t.Fatal("Link not expected to found")
2967 }
2968
2969 _, ok := err.(LinkNotFoundError)
2970 if !ok {
2971 t.Errorf("Error returned expected to of LinkNotFoundError type: %v", err)
2972 }
2973 }
2974
2975 func TestLinkByAliasWhenLinkIsNotFound(t *testing.T) {
2976 _, err := LinkByAlias("iammissing")
2977 if err == nil {
2978 t.Fatal("Link not expected to found")
2979 }
2980
2981 _, ok := err.(LinkNotFoundError)
2982 if !ok {
2983 t.Errorf("Error returned expected to of LinkNotFoundError type: %v", err)
2984 }
2985 }
2986
2987 func TestLinkAddDelTuntap(t *testing.T) {
2988 tearDown := setUpNetlinkTest(t)
2989 defer tearDown()
2990
2991
2992
2993 if err := syscall.Mount("sysfs", "/sys", "sysfs", syscall.MS_RDONLY, ""); err != nil {
2994 t.Fatal("Cannot mount sysfs")
2995 }
2996
2997 defer func() {
2998 if err := syscall.Unmount("/sys", 0); err != nil {
2999 t.Fatal("Cannot umount /sys")
3000 }
3001 }()
3002
3003 testLinkAddDel(t, &Tuntap{
3004 LinkAttrs: LinkAttrs{Name: "foo"},
3005 Mode: TUNTAP_MODE_TAP})
3006 }
3007
3008 func TestLinkAddDelTuntapMq(t *testing.T) {
3009 tearDown := setUpNetlinkTest(t)
3010 defer tearDown()
3011
3012 if err := syscall.Mount("sysfs", "/sys", "sysfs", syscall.MS_RDONLY, ""); err != nil {
3013 t.Fatal("Cannot mount sysfs")
3014 }
3015
3016 defer func() {
3017 if err := syscall.Unmount("/sys", 0); err != nil {
3018 t.Fatal("Cannot umount /sys")
3019 }
3020 }()
3021
3022 testLinkAddDel(t, &Tuntap{
3023 LinkAttrs: LinkAttrs{Name: "foo"},
3024 Mode: TUNTAP_MODE_TAP,
3025 Queues: 4})
3026
3027 testLinkAddDel(t, &Tuntap{
3028 LinkAttrs: LinkAttrs{Name: "foo"},
3029 Mode: TUNTAP_MODE_TAP,
3030 Queues: 4,
3031 Flags: TUNTAP_MULTI_QUEUE_DEFAULTS | TUNTAP_VNET_HDR})
3032 }
3033
3034 func TestLinkAddDelTuntapOwnerGroup(t *testing.T) {
3035 tearDown := setUpNetlinkTest(t)
3036 defer tearDown()
3037
3038 if err := syscall.Mount("sysfs", "/sys", "sysfs", syscall.MS_RDONLY, ""); err != nil {
3039 t.Fatal("Cannot mount sysfs")
3040 }
3041
3042 defer func() {
3043 if err := syscall.Unmount("/sys", 0); err != nil {
3044 t.Fatal("Cannot umount /sys")
3045 }
3046 }()
3047
3048 testLinkAddDel(t, &Tuntap{
3049 LinkAttrs: LinkAttrs{Name: "foo"},
3050 Mode: TUNTAP_MODE_TAP,
3051 Owner: 0,
3052 Group: 0,
3053 })
3054 }
3055
3056 func TestVethPeerIndex(t *testing.T) {
3057 tearDown := setUpNetlinkTest(t)
3058 defer tearDown()
3059
3060 const (
3061 vethPeer1 = "vethOne"
3062 vethPeer2 = "vethTwo"
3063 )
3064
3065 link := &Veth{
3066 LinkAttrs: LinkAttrs{
3067 Name: vethPeer1,
3068 MTU: 1500,
3069 Flags: net.FlagUp,
3070 },
3071 PeerName: vethPeer2,
3072 }
3073
3074 if err := LinkAdd(link); err != nil {
3075 t.Fatal(err)
3076 }
3077
3078 linkOne, err := LinkByName("vethOne")
3079 if err != nil {
3080 t.Fatal(err)
3081 }
3082
3083 linkTwo, err := LinkByName("vethTwo")
3084 if err != nil {
3085 t.Fatal(err)
3086 }
3087
3088 peerIndexOne, err := VethPeerIndex(&Veth{LinkAttrs: *linkOne.Attrs()})
3089 if err != nil {
3090 t.Fatal(err)
3091 }
3092
3093 peerIndexTwo, err := VethPeerIndex(&Veth{LinkAttrs: *linkTwo.Attrs()})
3094 if err != nil {
3095 t.Fatal(err)
3096 }
3097
3098 if peerIndexOne != linkTwo.Attrs().Index {
3099 t.Errorf("VethPeerIndex(%s) mismatch %d != %d", linkOne.Attrs().Name, peerIndexOne, linkTwo.Attrs().Index)
3100 }
3101
3102 if peerIndexTwo != linkOne.Attrs().Index {
3103 t.Errorf("VethPeerIndex(%s) mismatch %d != %d", linkTwo.Attrs().Name, peerIndexTwo, linkOne.Attrs().Index)
3104 }
3105 }
3106
3107 func TestLinkSlaveBond(t *testing.T) {
3108 minKernelRequired(t, 3, 13)
3109
3110 tearDown := setUpNetlinkTest(t)
3111 defer tearDown()
3112
3113 const (
3114 bondName = "foo"
3115 slaveName = "fooFoo"
3116 )
3117
3118 bond := NewLinkBond(LinkAttrs{Name: bondName})
3119 bond.Mode = BOND_MODE_BALANCE_RR
3120 if err := LinkAdd(bond); err != nil {
3121 t.Fatal(err)
3122 }
3123 defer LinkDel(bond)
3124
3125 slaveDummy := &Dummy{LinkAttrs{Name: slaveName}}
3126 if err := LinkAdd(slaveDummy); err != nil {
3127 t.Fatal(err)
3128 }
3129 defer LinkDel(slaveDummy)
3130
3131 if err := LinkSetBondSlave(slaveDummy, bond); err != nil {
3132 t.Fatal(err)
3133 }
3134
3135 slaveLink, err := LinkByName(slaveName)
3136 if err != nil {
3137 t.Fatal(err)
3138 }
3139
3140 slave := slaveLink.Attrs().Slave
3141 if slave == nil {
3142 t.Errorf("for %s expected slave is not nil.", slaveName)
3143 }
3144
3145 if slaveType := slave.SlaveType(); slaveType != "bond" {
3146 t.Errorf("for %s expected slave type is 'bond', but '%s'", slaveName, slaveType)
3147 }
3148 }
3149
3150 func TestLinkSetBondSlaveQueueId(t *testing.T) {
3151 minKernelRequired(t, 3, 13)
3152
3153 tearDown := setUpNetlinkTest(t)
3154 defer tearDown()
3155
3156 const (
3157 bondName = "foo"
3158 slave1Name = "fooFoo"
3159 )
3160
3161 bond := NewLinkBond(LinkAttrs{Name: bondName})
3162 if err := LinkAdd(bond); err != nil {
3163 t.Fatal(err)
3164 }
3165 defer LinkDel(bond)
3166
3167 slave := &Dummy{LinkAttrs{Name: slave1Name}}
3168 if err := LinkAdd(slave); err != nil {
3169 t.Fatal(err)
3170 }
3171 defer LinkDel(slave)
3172
3173 if err := LinkSetBondSlave(slave, bond); err != nil {
3174 t.Fatal(err)
3175 }
3176
3177 if err := pkgHandle.LinkSetBondSlaveQueueId(slave, 1); err != nil {
3178 t.Fatal(err)
3179 }
3180 }
3181
3182 func TestLinkSetBondSlave(t *testing.T) {
3183 minKernelRequired(t, 3, 13)
3184
3185 tearDown := setUpNetlinkTest(t)
3186 defer tearDown()
3187
3188 const (
3189 bondName = "foo"
3190 slaveOneName = "fooFoo"
3191 slaveTwoName = "fooBar"
3192 )
3193
3194 bond := NewLinkBond(LinkAttrs{Name: bondName})
3195 bond.Mode = StringToBondModeMap["802.3ad"]
3196 bond.AdSelect = BondAdSelect(BOND_AD_SELECT_BANDWIDTH)
3197 bond.AdActorSysPrio = 1
3198 bond.AdUserPortKey = 1
3199 bond.AdActorSystem, _ = net.ParseMAC("06:aa:bb:cc:dd:ee")
3200
3201 if err := LinkAdd(bond); err != nil {
3202 t.Fatal(err)
3203 }
3204
3205 bondLink, err := LinkByName(bondName)
3206 if err != nil {
3207 t.Fatal(err)
3208 }
3209 defer LinkDel(bondLink)
3210
3211 if err := LinkAdd(&Dummy{LinkAttrs{Name: slaveOneName}}); err != nil {
3212 t.Fatal(err)
3213 }
3214
3215 slaveOneLink, err := LinkByName(slaveOneName)
3216 if err != nil {
3217 t.Fatal(err)
3218 }
3219 defer LinkDel(slaveOneLink)
3220
3221 if err := LinkAdd(&Dummy{LinkAttrs{Name: slaveTwoName}}); err != nil {
3222 t.Fatal(err)
3223 }
3224 slaveTwoLink, err := LinkByName(slaveTwoName)
3225 if err != nil {
3226 t.Fatal(err)
3227 }
3228 defer LinkDel(slaveTwoLink)
3229
3230 if err := LinkSetBondSlave(slaveOneLink, &Bond{LinkAttrs: *bondLink.Attrs()}); err != nil {
3231 t.Fatal(err)
3232 }
3233
3234 if err := LinkSetBondSlave(slaveTwoLink, &Bond{LinkAttrs: *bondLink.Attrs()}); err != nil {
3235 t.Fatal(err)
3236 }
3237
3238
3239 slaveOneLink, err = LinkByName(slaveOneName)
3240 if err != nil {
3241 t.Fatal(err)
3242 }
3243
3244 slaveTwoLink, err = LinkByName(slaveTwoName)
3245 if err != nil {
3246 t.Fatal(err)
3247 }
3248
3249 if slaveOneLink.Attrs().MasterIndex != bondLink.Attrs().Index {
3250 t.Errorf("For %s expected %s to be master", slaveOneLink.Attrs().Name, bondLink.Attrs().Name)
3251 }
3252
3253 if slaveTwoLink.Attrs().MasterIndex != bondLink.Attrs().Index {
3254 t.Errorf("For %s expected %s to be master", slaveTwoLink.Attrs().Name, bondLink.Attrs().Name)
3255 }
3256 }
3257
3258 func testFailover(t *testing.T, slaveName, bondName string) {
3259 slaveLink, err := LinkByName(slaveName)
3260 if err != nil {
3261 t.Fatal(err)
3262 }
3263
3264 bondLink, err := LinkByName(bondName)
3265 if err != nil {
3266 t.Fatal(err)
3267 }
3268
3269 err = LinkSetBondSlaveActive(slaveLink, &Bond{LinkAttrs: *bondLink.Attrs()})
3270 if err != nil {
3271 t.Errorf("set slave link active failed: %v", err)
3272 return
3273 }
3274
3275 bondLink, err = LinkByName(bondName)
3276 if err != nil {
3277 t.Fatal(err)
3278 }
3279 bond := bondLink.(*Bond)
3280 if bond.ActiveSlave != slaveLink.Attrs().Index {
3281 t.Errorf("the current active slave %d is not expected as %d", bond.ActiveSlave, slaveLink.Attrs().Index)
3282 }
3283 }
3284
3285 func TestLinkFailover(t *testing.T) {
3286 minKernelRequired(t, 3, 13)
3287
3288 tearDown := setUpNetlinkTest(t)
3289 defer tearDown()
3290
3291 const (
3292 bondName = "foo"
3293 slaveOneName = "fooFoo"
3294 slaveTwoName = "fooBar"
3295 )
3296
3297 bond := NewLinkBond(LinkAttrs{Name: bondName})
3298 bond.Mode = StringToBondModeMap["active-backup"]
3299 bond.Miimon = 100
3300
3301 if err := LinkAdd(bond); err != nil {
3302 t.Fatal(err)
3303 }
3304
3305 bondLink, err := LinkByName(bondName)
3306 if err != nil {
3307 t.Fatal(err)
3308 }
3309 defer LinkDel(bondLink)
3310
3311 if err := LinkAdd(&Dummy{LinkAttrs{Name: slaveOneName}}); err != nil {
3312 t.Fatal(err)
3313 }
3314
3315 slaveOneLink, err := LinkByName(slaveOneName)
3316 if err != nil {
3317 t.Fatal(err)
3318 }
3319 defer LinkDel(slaveOneLink)
3320
3321 if err := LinkAdd(&Dummy{LinkAttrs{Name: slaveTwoName}}); err != nil {
3322 t.Fatal(err)
3323 }
3324 slaveTwoLink, err := LinkByName(slaveTwoName)
3325 if err != nil {
3326 t.Fatal(err)
3327 }
3328 defer LinkDel(slaveTwoLink)
3329
3330 if err := LinkSetBondSlave(slaveOneLink, &Bond{LinkAttrs: *bondLink.Attrs()}); err != nil {
3331 t.Fatal(err)
3332 }
3333
3334 if err := LinkSetBondSlave(slaveTwoLink, &Bond{LinkAttrs: *bondLink.Attrs()}); err != nil {
3335 t.Fatal(err)
3336 }
3337
3338 testFailover(t, slaveOneName, bondName)
3339 testFailover(t, slaveTwoName, bondName)
3340 testFailover(t, slaveTwoName, bondName)
3341
3342
3343 slaveOneLink, err = LinkByName(slaveOneName)
3344 if err != nil {
3345 t.Fatal(err)
3346 }
3347 err = LinkDelBondSlave(slaveOneLink, &Bond{LinkAttrs: *bondLink.Attrs()})
3348 if err != nil {
3349 t.Errorf("Remove slave %s from bond failed: %v", slaveOneName, err)
3350 }
3351 slaveOneLink, err = LinkByName(slaveOneName)
3352 if err != nil {
3353 t.Fatal(err)
3354 }
3355 if slaveOneLink.Attrs().MasterIndex > 0 {
3356 t.Errorf("The nic %s is still a slave of %d", slaveOneName, slaveOneLink.Attrs().MasterIndex)
3357 }
3358 }
3359
3360 func TestLinkSetAllmulticast(t *testing.T) {
3361 tearDown := setUpNetlinkTest(t)
3362 defer tearDown()
3363
3364 iface := &Veth{LinkAttrs: LinkAttrs{Name: "foo"}, PeerName: "bar"}
3365 if err := LinkAdd(iface); err != nil {
3366 t.Fatal(err)
3367 }
3368
3369 link, err := LinkByName("foo")
3370 if err != nil {
3371 t.Fatal(err)
3372 }
3373
3374 if err := LinkSetUp(link); err != nil {
3375 t.Fatal(err)
3376 }
3377
3378 link, err = LinkByName("foo")
3379 if err != nil {
3380 t.Fatal(err)
3381 }
3382
3383 if err := LinkSetAllmulticastOn(link); err != nil {
3384 t.Fatal(err)
3385 }
3386
3387 link, err = LinkByName("foo")
3388 if err != nil {
3389 t.Fatal(err)
3390 }
3391
3392 if link.Attrs().Allmulti != 1 {
3393 t.Fatal("IFF_ALLMULTI was not set")
3394 }
3395
3396 if err := LinkSetAllmulticastOff(link); err != nil {
3397 t.Fatal(err)
3398 }
3399
3400 link, err = LinkByName("foo")
3401 if err != nil {
3402 t.Fatal(err)
3403 }
3404
3405 if link.Attrs().Allmulti != 0 {
3406 t.Fatal("IFF_ALLMULTI is still set")
3407 }
3408 }
3409
3410 func TestLinkSetMulticast(t *testing.T) {
3411 tearDown := setUpNetlinkTest(t)
3412 defer tearDown()
3413
3414 iface := &Veth{LinkAttrs: LinkAttrs{Name: "foo"}, PeerName: "bar"}
3415 if err := LinkAdd(iface); err != nil {
3416 t.Fatal(err)
3417 }
3418
3419 link, err := LinkByName("foo")
3420 if err != nil {
3421 t.Fatal(err)
3422 }
3423
3424 if err := LinkSetUp(link); err != nil {
3425 t.Fatal(err)
3426 }
3427
3428 link, err = LinkByName("foo")
3429 if err != nil {
3430 t.Fatal(err)
3431 }
3432
3433 if err := LinkSetMulticastOn(link); err != nil {
3434 t.Fatal(err)
3435 }
3436
3437 link, err = LinkByName("foo")
3438 if err != nil {
3439 t.Fatal(err)
3440 }
3441
3442 if link.Attrs().Multi != 1 {
3443 t.Fatal("IFF_MULTICAST was not set")
3444 }
3445
3446 if err := LinkSetMulticastOff(link); err != nil {
3447 t.Fatal(err)
3448 }
3449
3450 link, err = LinkByName("foo")
3451 if err != nil {
3452 t.Fatal(err)
3453 }
3454
3455 if link.Attrs().Multi != 0 {
3456 t.Fatal("IFF_MULTICAST is still set")
3457 }
3458 }
3459
3460 func TestLinkSetMacvlanMode(t *testing.T) {
3461 tearDown := setUpNetlinkTest(t)
3462 defer tearDown()
3463
3464 const (
3465 parentName = "foo"
3466 macvlanName = "fooFoo"
3467 macvtapName = "fooBar"
3468 )
3469
3470 parent := &Dummy{LinkAttrs{Name: parentName}}
3471 if err := LinkAdd(parent); err != nil {
3472 t.Fatal(err)
3473 }
3474 defer LinkDel(parent)
3475
3476 testMacvlanMode := func(link Link, mode MacvlanMode) {
3477 if err := LinkSetMacvlanMode(link, mode); err != nil {
3478 t.Fatal(err)
3479 }
3480
3481 name := link.Attrs().Name
3482 result, err := LinkByName(name)
3483 if err != nil {
3484 t.Fatal(err)
3485 }
3486
3487 var actual MacvlanMode
3488 switch l := result.(type) {
3489 case *Macvlan:
3490 actual = l.Mode
3491 case *Macvtap:
3492 actual = l.Macvlan.Mode
3493 }
3494
3495 if actual != mode {
3496 t.Fatalf("expected %v got %v for %+v", mode, actual, link)
3497 }
3498 }
3499
3500 macvlan := &Macvlan{
3501 LinkAttrs: LinkAttrs{Name: macvlanName, ParentIndex: parent.Attrs().Index},
3502 Mode: MACVLAN_MODE_BRIDGE,
3503 }
3504 if err := LinkAdd(macvlan); err != nil {
3505 t.Fatal(err)
3506 }
3507 defer LinkDel(macvlan)
3508
3509 testMacvlanMode(macvlan, MACVLAN_MODE_VEPA)
3510 testMacvlanMode(macvlan, MACVLAN_MODE_PRIVATE)
3511 testMacvlanMode(macvlan, MACVLAN_MODE_SOURCE)
3512 testMacvlanMode(macvlan, MACVLAN_MODE_BRIDGE)
3513
3514 macvtap := &Macvtap{
3515 Macvlan: Macvlan{
3516 LinkAttrs: LinkAttrs{Name: macvtapName, ParentIndex: parent.Attrs().Index},
3517 Mode: MACVLAN_MODE_BRIDGE,
3518 },
3519 }
3520 if err := LinkAdd(macvtap); err != nil {
3521 t.Fatal(err)
3522 }
3523 defer LinkDel(macvtap)
3524
3525 testMacvlanMode(macvtap, MACVLAN_MODE_VEPA)
3526 testMacvlanMode(macvtap, MACVLAN_MODE_PRIVATE)
3527 testMacvlanMode(macvtap, MACVLAN_MODE_SOURCE)
3528 testMacvlanMode(macvtap, MACVLAN_MODE_BRIDGE)
3529 }
3530
View as plain text