1
2
3
4 package netlink
5
6 import (
7 "net"
8 "os"
9 "runtime"
10 "strconv"
11 "testing"
12 "time"
13
14 "github.com/vishvananda/netlink/nl"
15 "github.com/vishvananda/netns"
16 "golang.org/x/sys/unix"
17 )
18
19 func TestRouteAddDel(t *testing.T) {
20 tearDown := setUpNetlinkTest(t)
21 defer tearDown()
22
23
24 link, err := LinkByName("lo")
25 if err != nil {
26 t.Fatal(err)
27 }
28
29
30 if err := LinkSetUp(link); err != nil {
31 t.Fatal(err)
32 }
33
34
35 dst := &net.IPNet{
36 IP: net.IPv4(192, 168, 0, 0),
37 Mask: net.CIDRMask(24, 32),
38 }
39
40 ip := net.IPv4(127, 1, 1, 1)
41 route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
42 if err := RouteAdd(&route); err != nil {
43 t.Fatal(err)
44 }
45 routes, err := RouteList(link, FAMILY_V4)
46 if err != nil {
47 t.Fatal(err)
48 }
49 if len(routes) != 1 {
50 t.Fatal("Route not added properly")
51 }
52
53 routes, err = RouteList(nil, FAMILY_V4)
54 if err != nil {
55 t.Fatal(err)
56 }
57 if len(routes) != 1 {
58 t.Fatal("Route not listed properly")
59 }
60
61 dstIP := net.IPv4(192, 168, 0, 42)
62 routeToDstIP, err := RouteGet(dstIP)
63 if err != nil {
64 t.Fatal(err)
65 }
66
67 if len(routeToDstIP) == 0 {
68 t.Fatal("Default route not present")
69 }
70 if err := RouteDel(&route); err != nil {
71 t.Fatal(err)
72 }
73 routes, err = RouteList(link, FAMILY_V4)
74 if err != nil {
75 t.Fatal(err)
76 }
77 if len(routes) != 0 {
78 t.Fatal("Route not removed properly")
79 }
80
81
82
83 _, defaultDst, _ := net.ParseCIDR("0.0.0.0/0")
84 route = Route{Dst: defaultDst, LinkIndex: link.Attrs().Index}
85 if err := RouteAdd(&route); err != nil {
86 t.Fatal(err)
87 }
88 routes, err = RouteList(link, FAMILY_V4)
89 if err != nil {
90 t.Fatal(err)
91 }
92 if len(routes) != 1 {
93 t.Fatal("Dev default route not listed properly")
94 }
95 if err := RouteDel(&routes[0]); err != nil {
96 t.Fatal(err)
97 }
98 routes, err = RouteList(link, FAMILY_V4)
99 if err != nil {
100 t.Fatal(err)
101 }
102 if len(routes) != 0 {
103 t.Fatal("Dev default route not removed properly")
104 }
105
106
107 route = Route{Dst: defaultDst, Type: unix.RTN_BLACKHOLE, Family: FAMILY_V4}
108 if err := RouteAdd(&route); err != nil {
109 t.Fatal(err)
110 }
111 routes, err = RouteList(nil, FAMILY_V4)
112 if err != nil {
113 t.Fatal(err)
114 }
115 t.Logf("%+v", routes)
116
117 if len(routes) != 1 {
118 t.Fatal("Blackhole default route not listed properly")
119 }
120
121 if err := RouteDel(&routes[0]); err != nil {
122 t.Fatal(err)
123 }
124 routes, err = RouteList(nil, FAMILY_V4)
125 if err != nil {
126 t.Fatal(err)
127 }
128 if len(routes) != 0 {
129 t.Fatal("Blackhole default route not removed properly")
130 }
131
132
133 route = Route{Dst: defaultDst, Type: unix.RTN_PROHIBIT}
134 if err := RouteAdd(&route); err != nil {
135 t.Fatal(err)
136 }
137 routes, err = RouteList(nil, FAMILY_V4)
138 if err != nil {
139 t.Fatal(err)
140 }
141 if len(routes) != 1 {
142 t.Fatal("Prohibit default route not listed properly")
143 }
144
145 if err := RouteDel(&routes[0]); err != nil {
146 t.Fatal(err)
147 }
148 routes, err = RouteList(nil, FAMILY_V4)
149 if err != nil {
150 t.Fatal(err)
151 }
152 if len(routes) != 0 {
153 t.Fatal("Prohibit default route not removed properly")
154 }
155 }
156
157 func TestRoute6AddDel(t *testing.T) {
158 tearDown := setUpNetlinkTest(t)
159 defer tearDown()
160
161
162
163 la := NewLinkAttrs()
164 la.Name = "dummy_route6"
165 la.TxQLen = 1500
166 dummy := &Dummy{LinkAttrs: la}
167 if err := LinkAdd(dummy); err != nil {
168 t.Fatal(err)
169 }
170
171
172 link, err := LinkByName("dummy_route6")
173 if err != nil {
174 t.Fatal(err)
175 }
176
177
178 if err := LinkSetUp(link); err != nil {
179 t.Fatal(err)
180 }
181
182
183
184 routes, err := RouteList(link, FAMILY_V6)
185 if err != nil {
186 t.Fatal(err)
187 }
188 nroutes := len(routes)
189
190
191 dst := &net.IPNet{
192 IP: net.ParseIP("2001:db8::0"),
193 Mask: net.CIDRMask(64, 128),
194 }
195 route := Route{LinkIndex: link.Attrs().Index, Dst: dst}
196 if err := RouteAdd(&route); err != nil {
197 t.Fatal(err)
198 }
199 routes, err = RouteList(link, FAMILY_V6)
200 if err != nil {
201 t.Fatal(err)
202 }
203 if len(routes) != nroutes+1 {
204 t.Fatal("Route not added properly")
205 }
206
207 dstIP := net.ParseIP("2001:db8::1")
208 routeToDstIP, err := RouteGet(dstIP)
209 if err != nil {
210 t.Fatal(err)
211 }
212
213
214 if len(routeToDstIP) == 0 {
215 t.Fatal("Route not present")
216 }
217 if err := RouteDel(&route); err != nil {
218 t.Fatal(err)
219 }
220 routes, err = RouteList(link, FAMILY_V6)
221 if err != nil {
222 t.Fatal(err)
223 }
224 if len(routes) != nroutes {
225 t.Fatal("Route not removed properly")
226 }
227
228
229 _, defaultDst, _ := net.ParseCIDR("::/0")
230 route = Route{LinkIndex: link.Attrs().Index, Dst: defaultDst}
231 if err := RouteAdd(&route); err != nil {
232 t.Fatal(err)
233 }
234 routes, err = RouteList(link, FAMILY_V6)
235 if err != nil {
236 t.Fatal(err)
237 }
238 if len(routes) != nroutes+1 {
239 t.Fatal("Default route not added properly")
240 }
241
242
243 for _, route := range routes {
244 if route.Dst.String() == defaultDst.String() {
245 if err := RouteDel(&route); err != nil {
246 t.Fatal(err)
247 }
248 }
249 }
250 routes, err = RouteList(link, FAMILY_V6)
251 if err != nil {
252 t.Fatal(err)
253 }
254 if len(routes) != nroutes {
255 t.Fatal("Default route not removed properly")
256 }
257
258
259 routes, err = RouteList(nil, FAMILY_V6)
260 if err != nil {
261 t.Fatal(err)
262 }
263 nroutes = len(routes)
264
265 route = Route{Type: unix.RTN_BLACKHOLE, Dst: defaultDst}
266 if err := RouteAdd(&route); err != nil {
267 t.Fatal(err)
268 }
269 routes, err = RouteList(nil, FAMILY_V6)
270 if err != nil {
271 t.Fatal(err)
272 }
273 if len(routes) != nroutes+1 {
274 t.Fatal("Blackhole default route not added properly")
275 }
276
277
278 for _, route := range routes {
279 if ipNetEqual(route.Dst, defaultDst) {
280 if err := RouteDel(&route); err != nil {
281 t.Fatal(err)
282 }
283 }
284 }
285 routes, err = RouteList(nil, FAMILY_V6)
286 if err != nil {
287 t.Fatal(err)
288 }
289 if len(routes) != nroutes {
290 t.Fatal("Blackhole default route not removed properly")
291 }
292
293
294 routes, err = RouteList(nil, FAMILY_V6)
295 if err != nil {
296 t.Fatal(err)
297 }
298 nroutes = len(routes)
299
300 route = Route{Type: unix.RTN_BLACKHOLE, Dst: defaultDst}
301 if err := RouteAdd(&route); err != nil {
302 t.Fatal(err)
303 }
304 routes, err = RouteList(nil, FAMILY_V6)
305 if err != nil {
306 t.Fatal(err)
307 }
308 if len(routes) != nroutes+1 {
309 t.Fatal("Prohibit default route not added properly")
310 }
311
312
313 for _, route := range routes {
314 if ipNetEqual(route.Dst, defaultDst) {
315 if err := RouteDel(&route); err != nil {
316 t.Fatal(err)
317 }
318 }
319 }
320 routes, err = RouteList(nil, FAMILY_V6)
321 if err != nil {
322 t.Fatal(err)
323 }
324 if len(routes) != nroutes {
325 t.Fatal("Prohibit default route not removed properly")
326 }
327
328
329 if err := LinkDel(link); err != nil {
330 t.Fatal(err)
331 }
332 }
333
334 func TestRouteChange(t *testing.T) {
335 tearDown := setUpNetlinkTest(t)
336 defer tearDown()
337
338
339 link, err := LinkByName("lo")
340 if err != nil {
341 t.Fatal(err)
342 }
343
344
345 if err := LinkSetUp(link); err != nil {
346 t.Fatal(err)
347 }
348
349
350 dst := &net.IPNet{
351 IP: net.IPv4(192, 168, 0, 0),
352 Mask: net.CIDRMask(24, 32),
353 }
354
355 ip := net.IPv4(127, 1, 1, 1)
356 route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
357
358 if err := RouteChange(&route); err == nil {
359 t.Fatal("Route added while it should fail")
360 }
361
362 if err := RouteAdd(&route); err != nil {
363 t.Fatal(err)
364 }
365 routes, err := RouteList(link, FAMILY_V4)
366 if err != nil {
367 t.Fatal(err)
368 }
369 if len(routes) != 1 {
370 t.Fatal("Route not added properly")
371 }
372
373 ip = net.IPv4(127, 1, 1, 2)
374 route = Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
375 if err := RouteChange(&route); err != nil {
376 t.Fatal(err)
377 }
378
379 routes, err = RouteList(link, FAMILY_V4)
380 if err != nil {
381 t.Fatal(err)
382 }
383
384 if len(routes) != 1 || !routes[0].Src.Equal(ip) {
385 t.Fatal("Route not changed properly")
386 }
387
388 if err := RouteDel(&route); err != nil {
389 t.Fatal(err)
390 }
391 routes, err = RouteList(link, FAMILY_V4)
392 if err != nil {
393 t.Fatal(err)
394 }
395 if len(routes) != 0 {
396 t.Fatal("Route not removed properly")
397 }
398 }
399
400 func TestRouteReplace(t *testing.T) {
401 tearDown := setUpNetlinkTest(t)
402 defer tearDown()
403
404
405 link, err := LinkByName("lo")
406 if err != nil {
407 t.Fatal(err)
408 }
409
410
411 if err := LinkSetUp(link); err != nil {
412 t.Fatal(err)
413 }
414
415
416 dst := &net.IPNet{
417 IP: net.IPv4(192, 168, 0, 0),
418 Mask: net.CIDRMask(24, 32),
419 }
420
421 ip := net.IPv4(127, 1, 1, 1)
422 route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
423 if err := RouteAdd(&route); err != nil {
424 t.Fatal(err)
425 }
426 routes, err := RouteList(link, FAMILY_V4)
427 if err != nil {
428 t.Fatal(err)
429 }
430 if len(routes) != 1 {
431 t.Fatal("Route not added properly")
432 }
433
434 ip = net.IPv4(127, 1, 1, 2)
435 route = Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
436 if err := RouteReplace(&route); err != nil {
437 t.Fatal(err)
438 }
439
440 routes, err = RouteList(link, FAMILY_V4)
441 if err != nil {
442 t.Fatal(err)
443 }
444
445 if len(routes) != 1 || !routes[0].Src.Equal(ip) {
446 t.Fatal("Route not replaced properly")
447 }
448
449 if err := RouteDel(&route); err != nil {
450 t.Fatal(err)
451 }
452 routes, err = RouteList(link, FAMILY_V4)
453 if err != nil {
454 t.Fatal(err)
455 }
456 if len(routes) != 0 {
457 t.Fatal("Route not removed properly")
458 }
459 }
460
461 func TestRouteAppend(t *testing.T) {
462 tearDown := setUpNetlinkTest(t)
463 defer tearDown()
464
465
466 link, err := LinkByName("lo")
467 if err != nil {
468 t.Fatal(err)
469 }
470
471
472 if err := LinkSetUp(link); err != nil {
473 t.Fatal(err)
474 }
475
476
477 dst := &net.IPNet{
478 IP: net.IPv4(192, 168, 0, 0),
479 Mask: net.CIDRMask(24, 32),
480 }
481
482 ip := net.IPv4(127, 1, 1, 1)
483 route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
484 if err := RouteAdd(&route); err != nil {
485 t.Fatal(err)
486 }
487 routes, err := RouteList(link, FAMILY_V4)
488 if err != nil {
489 t.Fatal(err)
490 }
491 if len(routes) != 1 {
492 t.Fatal("Route not added properly")
493 }
494
495 ip = net.IPv4(127, 1, 1, 2)
496 route = Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
497 if err := RouteAppend(&route); err != nil {
498 t.Fatal(err)
499 }
500
501 routes, err = RouteList(link, FAMILY_V4)
502 if err != nil {
503 t.Fatal(err)
504 }
505
506 if len(routes) != 2 || !routes[1].Src.Equal(ip) {
507 t.Fatal("Route not append properly")
508 }
509
510 if err := RouteDel(&routes[0]); err != nil {
511 t.Fatal(err)
512 }
513 if err := RouteDel(&routes[1]); err != nil {
514 t.Fatal(err)
515 }
516 routes, err = RouteList(link, FAMILY_V4)
517 if err != nil {
518 t.Fatal(err)
519 }
520 if len(routes) != 0 {
521 t.Fatal("Route not removed properly")
522 }
523 }
524
525 func TestRouteAddIncomplete(t *testing.T) {
526 tearDown := setUpNetlinkTest(t)
527 defer tearDown()
528
529
530 link, err := LinkByName("lo")
531 if err != nil {
532 t.Fatal(err)
533 }
534
535
536 if err = LinkSetUp(link); err != nil {
537 t.Fatal(err)
538 }
539
540 route := Route{LinkIndex: link.Attrs().Index}
541 if err := RouteAdd(&route); err == nil {
542 t.Fatal("Adding incomplete route should fail")
543 }
544 }
545
546
547 func expectRouteUpdate(ch <-chan RouteUpdate, t, f uint16, dst net.IP) bool {
548 for {
549 timeout := time.After(time.Minute)
550 select {
551 case update := <-ch:
552 if update.Type == t &&
553 update.NlFlags == f &&
554 update.Route.Dst != nil &&
555 update.Route.Dst.IP.Equal(dst) {
556 return true
557 }
558 case <-timeout:
559 return false
560 }
561 }
562 }
563
564 func TestRouteSubscribe(t *testing.T) {
565 tearDown := setUpNetlinkTest(t)
566 defer tearDown()
567
568 ch := make(chan RouteUpdate)
569 done := make(chan struct{})
570 defer close(done)
571 if err := RouteSubscribe(ch, done); err != nil {
572 t.Fatal(err)
573 }
574
575
576 link, err := LinkByName("lo")
577 if err != nil {
578 t.Fatal(err)
579 }
580
581
582 if err = LinkSetUp(link); err != nil {
583 t.Fatal(err)
584 }
585
586
587 dst := &net.IPNet{
588 IP: net.IPv4(192, 168, 0, 0),
589 Mask: net.CIDRMask(24, 32),
590 }
591
592 ip := net.IPv4(127, 1, 1, 1)
593 route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
594 if err := RouteAdd(&route); err != nil {
595 t.Fatal(err)
596 }
597
598 if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, unix.NLM_F_EXCL|unix.NLM_F_CREATE, dst.IP) {
599 t.Fatal("Add update not received as expected")
600 }
601 if err := RouteDel(&route); err != nil {
602 t.Fatal(err)
603 }
604 if !expectRouteUpdate(ch, unix.RTM_DELROUTE, 0, dst.IP) {
605 t.Fatal("Del update not received as expected")
606 }
607 }
608
609 func TestRouteSubscribeWithOptions(t *testing.T) {
610 tearDown := setUpNetlinkTest(t)
611 defer tearDown()
612
613 ch := make(chan RouteUpdate)
614 done := make(chan struct{})
615 defer close(done)
616 var lastError error
617 defer func() {
618 if lastError != nil {
619 t.Fatalf("Fatal error received during subscription: %v", lastError)
620 }
621 }()
622 if err := RouteSubscribeWithOptions(ch, done, RouteSubscribeOptions{
623 ErrorCallback: func(err error) {
624 lastError = err
625 },
626 }); err != nil {
627 t.Fatal(err)
628 }
629
630
631 link, err := LinkByName("lo")
632 if err != nil {
633 t.Fatal(err)
634 }
635
636
637 if err = LinkSetUp(link); err != nil {
638 t.Fatal(err)
639 }
640
641
642 dst := &net.IPNet{
643 IP: net.IPv4(192, 168, 0, 0),
644 Mask: net.CIDRMask(24, 32),
645 }
646
647 ip := net.IPv4(127, 1, 1, 1)
648 route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
649 if err := RouteAdd(&route); err != nil {
650 t.Fatal(err)
651 }
652
653 if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, unix.NLM_F_EXCL|unix.NLM_F_CREATE, dst.IP) {
654 t.Fatal("Add update not received as expected")
655 }
656 }
657
658 func TestRouteSubscribeAt(t *testing.T) {
659 skipUnlessRoot(t)
660
661
662 newNs, err := netns.New()
663 if err != nil {
664 t.Fatal(err)
665 }
666 defer newNs.Close()
667
668 nh, err := NewHandleAt(newNs)
669 if err != nil {
670 t.Fatal(err)
671 }
672 defer nh.Close()
673
674
675 ch := make(chan RouteUpdate)
676 done := make(chan struct{})
677 defer close(done)
678 if err := RouteSubscribeAt(newNs, ch, done); err != nil {
679 t.Fatal(err)
680 }
681
682
683 link, err := nh.LinkByName("lo")
684 if err != nil {
685 t.Fatal(err)
686 }
687
688
689 if err = nh.LinkSetUp(link); err != nil {
690 t.Fatal(err)
691 }
692
693
694 dst := &net.IPNet{
695 IP: net.IPv4(192, 169, 0, 0),
696 Mask: net.CIDRMask(24, 32),
697 }
698
699 ip := net.IPv4(127, 100, 1, 1)
700 route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
701 if err := nh.RouteAdd(&route); err != nil {
702 t.Fatal(err)
703 }
704
705 if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, unix.NLM_F_EXCL|unix.NLM_F_CREATE, dst.IP) {
706 t.Fatal("Add update not received as expected")
707 }
708 if err := nh.RouteDel(&route); err != nil {
709 t.Fatal(err)
710 }
711 if !expectRouteUpdate(ch, unix.RTM_DELROUTE, 0, dst.IP) {
712 t.Fatal("Del update not received as expected")
713 }
714 }
715
716 func TestRouteSubscribeListExisting(t *testing.T) {
717 skipUnlessRoot(t)
718
719
720 newNs, err := netns.New()
721 if err != nil {
722 t.Fatal(err)
723 }
724 defer newNs.Close()
725
726 nh, err := NewHandleAt(newNs)
727 if err != nil {
728 t.Fatal(err)
729 }
730 defer nh.Close()
731
732
733 link, err := nh.LinkByName("lo")
734 if err != nil {
735 t.Fatal(err)
736 }
737
738
739 if err = nh.LinkSetUp(link); err != nil {
740 t.Fatal(err)
741 }
742
743
744 dst10 := &net.IPNet{
745 IP: net.IPv4(10, 10, 10, 0),
746 Mask: net.CIDRMask(24, 32),
747 }
748
749 ip := net.IPv4(127, 100, 1, 1)
750 route10 := Route{LinkIndex: link.Attrs().Index, Dst: dst10, Src: ip}
751 if err := nh.RouteAdd(&route10); err != nil {
752 t.Fatal(err)
753 }
754
755
756 ch := make(chan RouteUpdate)
757 done := make(chan struct{})
758 defer close(done)
759 if err := RouteSubscribeWithOptions(ch, done, RouteSubscribeOptions{
760 Namespace: &newNs,
761 ListExisting: true},
762 ); err != nil {
763 t.Fatal(err)
764 }
765
766 if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, 0, dst10.IP) {
767 t.Fatal("Existing add update not received as expected")
768 }
769
770
771 dst := &net.IPNet{
772 IP: net.IPv4(192, 169, 0, 0),
773 Mask: net.CIDRMask(24, 32),
774 }
775
776 route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
777 if err := nh.RouteAdd(&route); err != nil {
778 t.Fatal(err)
779 }
780
781 if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, unix.NLM_F_EXCL|unix.NLM_F_CREATE, dst.IP) {
782 t.Fatal("Add update not received as expected")
783 }
784 if err := nh.RouteDel(&route); err != nil {
785 t.Fatal(err)
786 }
787 if !expectRouteUpdate(ch, unix.RTM_DELROUTE, 0, dst.IP) {
788 t.Fatal("Del update not received as expected")
789 }
790 if err := nh.RouteDel(&route10); err != nil {
791 t.Fatal(err)
792 }
793 if !expectRouteUpdate(ch, unix.RTM_DELROUTE, 0, dst10.IP) {
794 t.Fatal("Del update not received as expected")
795 }
796 }
797
798 func TestRouteFilterAllTables(t *testing.T) {
799 tearDown := setUpNetlinkTest(t)
800 defer tearDown()
801
802
803 link, err := LinkByName("lo")
804 if err != nil {
805 t.Fatal(err)
806 }
807
808 if err = LinkSetUp(link); err != nil {
809 t.Fatal(err)
810 }
811
812
813 dst := &net.IPNet{
814 IP: net.IPv4(1, 1, 1, 1),
815 Mask: net.CIDRMask(32, 32),
816 }
817
818 tables := []int{1000, 1001, 1002}
819 src := net.IPv4(127, 3, 3, 3)
820 for _, table := range tables {
821 route := Route{
822 LinkIndex: link.Attrs().Index,
823 Dst: dst,
824 Src: src,
825 Scope: unix.RT_SCOPE_LINK,
826 Priority: 13,
827 Table: table,
828 Type: unix.RTN_UNICAST,
829 Tos: 12,
830 Hoplimit: 100,
831 Realm: 328,
832 }
833 if err := RouteAdd(&route); err != nil {
834 t.Fatal(err)
835 }
836 }
837 routes, err := RouteListFiltered(FAMILY_V4, &Route{
838 Dst: dst,
839 Src: src,
840 Scope: unix.RT_SCOPE_LINK,
841 Table: unix.RT_TABLE_UNSPEC,
842 Type: unix.RTN_UNICAST,
843 Tos: 12,
844 Hoplimit: 100,
845 Realm: 328,
846 }, RT_FILTER_DST|RT_FILTER_SRC|RT_FILTER_SCOPE|RT_FILTER_TABLE|RT_FILTER_TYPE|RT_FILTER_TOS|RT_FILTER_HOPLIMIT|RT_FILTER_REALM)
847 if err != nil {
848 t.Fatal(err)
849 }
850 if len(routes) != 3 {
851 t.Fatal("Routes not added properly")
852 }
853
854 for _, route := range routes {
855 if route.Scope != unix.RT_SCOPE_LINK {
856 t.Fatal("Invalid Scope. Route not added properly")
857 }
858 if route.Priority != 13 {
859 t.Fatal("Invalid Priority. Route not added properly")
860 }
861 if !tableIDIn(tables, route.Table) {
862 t.Fatalf("Invalid Table %d. Route not added properly", route.Table)
863 }
864 if route.Type != unix.RTN_UNICAST {
865 t.Fatal("Invalid Type. Route not added properly")
866 }
867 if route.Tos != 12 {
868 t.Fatal("Invalid Tos. Route not added properly")
869 }
870 if route.Hoplimit != 100 {
871 t.Fatal("Invalid Hoplimit. Route not added properly")
872 }
873 if route.Realm != 328 {
874 t.Fatal("Invalid Realm. Route not added properly")
875 }
876 }
877 }
878
879 func TestRouteFilterByFamily(t *testing.T) {
880 tearDown := setUpNetlinkTest(t)
881 defer tearDown()
882
883 const table int = 999
884
885
886 link, err := LinkByName("lo")
887 if err != nil {
888 t.Fatal(err)
889 }
890
891 if err = LinkSetUp(link); err != nil {
892 t.Fatal(err)
893 }
894
895
896 dst4 := &net.IPNet{
897 IP: net.IPv4(2, 2, 0, 0),
898 Mask: net.CIDRMask(24, 32),
899 }
900 route4 := Route{LinkIndex: link.Attrs().Index, Dst: dst4, Table: table}
901 if err := RouteAdd(&route4); err != nil {
902 t.Fatal(err)
903 }
904
905
906 dst6 := &net.IPNet{
907 IP: net.ParseIP("2001:db9::0"),
908 Mask: net.CIDRMask(64, 128),
909 }
910 route6 := Route{LinkIndex: link.Attrs().Index, Dst: dst6, Table: table}
911 if err := RouteAdd(&route6); err != nil {
912 t.Fatal(err)
913 }
914
915
916 routes_all, err := RouteListFiltered(FAMILY_ALL, &Route{Table: table}, RT_FILTER_TABLE)
917 if err != nil {
918 t.Fatal(err)
919 }
920 if len(routes_all) != 2 {
921 t.Fatal("Filtering by FAMILY_ALL doesn't find two routes")
922 }
923
924
925 routes_v4, err := RouteListFiltered(FAMILY_V4, &Route{Table: table}, RT_FILTER_TABLE)
926 if err != nil {
927 t.Fatal(err)
928 }
929 if len(routes_v4) != 1 {
930 t.Fatal("Filtering by FAMILY_V4 doesn't find one route")
931 }
932
933
934 routes_v6, err := RouteListFiltered(FAMILY_V6, &Route{Table: table}, RT_FILTER_TABLE)
935 if err != nil {
936 t.Fatal(err)
937 }
938 if len(routes_v6) != 1 {
939 t.Fatal("Filtering by FAMILY_V6 doesn't find one route")
940 }
941
942
943 routes_non_existent, err := RouteListFiltered(99, &Route{Table: table}, RT_FILTER_TABLE)
944 if err != nil {
945 t.Fatal(err)
946 }
947 if len(routes_non_existent) != 0 {
948 t.Fatal("Filtering by non-existent family find some route")
949 }
950 }
951
952 func TestRouteFilterIterCanStop(t *testing.T) {
953 tearDown := setUpNetlinkTest(t)
954 defer tearDown()
955
956
957 link, err := LinkByName("lo")
958 if err != nil {
959 t.Fatal(err)
960 }
961
962 if err = LinkSetUp(link); err != nil {
963 t.Fatal(err)
964 }
965
966
967 dst := &net.IPNet{
968 IP: net.IPv4(1, 1, 1, 1),
969 Mask: net.CIDRMask(32, 32),
970 }
971
972 for i := 0; i < 3; i++ {
973 route := Route{
974 LinkIndex: link.Attrs().Index,
975 Dst: dst,
976 Scope: unix.RT_SCOPE_LINK,
977 Priority: 1 + i,
978 Table: 1000,
979 Type: unix.RTN_UNICAST,
980 }
981 if err := RouteAdd(&route); err != nil {
982 t.Fatal(err)
983 }
984 }
985
986 var routes []Route
987 err = RouteListFilteredIter(FAMILY_V4, &Route{
988 Dst: dst,
989 Scope: unix.RT_SCOPE_LINK,
990 Table: 1000,
991 Type: unix.RTN_UNICAST,
992 }, RT_FILTER_TABLE, func(route Route) (cont bool) {
993 routes = append(routes, route)
994 return len(routes) < 2
995 })
996 if err != nil {
997 t.Fatal(err)
998 }
999 if len(routes) != 2 {
1000 t.Fatal("Unexpected number of iterations")
1001 }
1002 for _, route := range routes {
1003 if route.Scope != unix.RT_SCOPE_LINK {
1004 t.Fatal("Invalid Scope. Route not added properly")
1005 }
1006 if route.Priority < 1 || route.Priority > 3 {
1007 t.Fatal("Priority outside expected range. Route not added properly")
1008 }
1009 if route.Table != 1000 {
1010 t.Fatalf("Invalid Table %d. Route not added properly", route.Table)
1011 }
1012 if route.Type != unix.RTN_UNICAST {
1013 t.Fatal("Invalid Type. Route not added properly")
1014 }
1015 }
1016 }
1017
1018 func BenchmarkRouteListFilteredNew(b *testing.B) {
1019 tearDown := setUpNetlinkTest(b)
1020 defer tearDown()
1021
1022 link, err := setUpRoutesBench(b)
1023
1024 b.ResetTimer()
1025 b.ReportAllocs()
1026 var routes []Route
1027 for i := 0; i < b.N; i++ {
1028 routes, err = pkgHandle.RouteListFiltered(FAMILY_V4, &Route{
1029 LinkIndex: link.Attrs().Index,
1030 }, RT_FILTER_OIF)
1031 if err != nil {
1032 b.Fatal(err)
1033 }
1034 if len(routes) != 65535 {
1035 b.Fatal("Incorrect number of routes.", len(routes))
1036 }
1037 }
1038 runtime.KeepAlive(routes)
1039 }
1040
1041 func BenchmarkRouteListIter(b *testing.B) {
1042 tearDown := setUpNetlinkTest(b)
1043 defer tearDown()
1044
1045 link, err := setUpRoutesBench(b)
1046
1047 b.ResetTimer()
1048 b.ReportAllocs()
1049 for i := 0; i < b.N; i++ {
1050 var routes int
1051 err = RouteListFilteredIter(FAMILY_V4, &Route{
1052 LinkIndex: link.Attrs().Index,
1053 }, RT_FILTER_OIF, func(route Route) (cont bool) {
1054 routes++
1055 return true
1056 })
1057 if err != nil {
1058 b.Fatal(err)
1059 }
1060 if routes != 65535 {
1061 b.Fatal("Incorrect number of routes.", routes)
1062 }
1063 }
1064 }
1065
1066 func setUpRoutesBench(b *testing.B) (Link, error) {
1067
1068 link, err := LinkByName("lo")
1069 if err != nil {
1070 b.Fatal(err)
1071 }
1072
1073 if err = LinkSetUp(link); err != nil {
1074 b.Fatal(err)
1075 }
1076
1077
1078 for i := 0; i < 65535; i++ {
1079 dst := &net.IPNet{
1080 IP: net.IPv4(1, 1, byte(i>>8), byte(i&0xff)),
1081 Mask: net.CIDRMask(32, 32),
1082 }
1083 route := Route{
1084 LinkIndex: link.Attrs().Index,
1085 Dst: dst,
1086 Scope: unix.RT_SCOPE_LINK,
1087 Priority: 10,
1088 Type: unix.RTN_UNICAST,
1089 }
1090 if err := RouteAdd(&route); err != nil {
1091 b.Fatal(err)
1092 }
1093 }
1094 return link, err
1095 }
1096
1097 func tableIDIn(ids []int, id int) bool {
1098 for _, v := range ids {
1099 if v == id {
1100 return true
1101 }
1102 }
1103 return false
1104 }
1105
1106 func TestRouteExtraFields(t *testing.T) {
1107 tearDown := setUpNetlinkTest(t)
1108 defer tearDown()
1109
1110
1111 link, err := LinkByName("lo")
1112 if err != nil {
1113 t.Fatal(err)
1114 }
1115
1116 if err = LinkSetUp(link); err != nil {
1117 t.Fatal(err)
1118 }
1119
1120
1121 dst := &net.IPNet{
1122 IP: net.IPv4(1, 1, 1, 1),
1123 Mask: net.CIDRMask(32, 32),
1124 }
1125
1126 src := net.IPv4(127, 3, 3, 3)
1127 route := Route{
1128 LinkIndex: link.Attrs().Index,
1129 Dst: dst,
1130 Src: src,
1131 Scope: unix.RT_SCOPE_LINK,
1132 Priority: 13,
1133 Table: unix.RT_TABLE_MAIN,
1134 Type: unix.RTN_UNICAST,
1135 Tos: 12,
1136 Hoplimit: 100,
1137 Realm: 239,
1138 }
1139 if err := RouteAdd(&route); err != nil {
1140 t.Fatal(err)
1141 }
1142 routes, err := RouteListFiltered(FAMILY_V4, &Route{
1143 Dst: dst,
1144 Src: src,
1145 Scope: unix.RT_SCOPE_LINK,
1146 Table: unix.RT_TABLE_MAIN,
1147 Type: unix.RTN_UNICAST,
1148 Tos: 12,
1149 Hoplimit: 100,
1150 Realm: 239,
1151 }, RT_FILTER_DST|RT_FILTER_SRC|RT_FILTER_SCOPE|RT_FILTER_TABLE|RT_FILTER_TYPE|RT_FILTER_TOS|RT_FILTER_HOPLIMIT|RT_FILTER_REALM)
1152 if err != nil {
1153 t.Fatal(err)
1154 }
1155 if len(routes) != 1 {
1156 t.Fatal("Route not added properly")
1157 }
1158
1159 if routes[0].Scope != unix.RT_SCOPE_LINK {
1160 t.Fatal("Invalid Scope. Route not added properly")
1161 }
1162 if routes[0].Priority != 13 {
1163 t.Fatal("Invalid Priority. Route not added properly")
1164 }
1165 if routes[0].Table != unix.RT_TABLE_MAIN {
1166 t.Fatal("Invalid Scope. Route not added properly")
1167 }
1168 if routes[0].Type != unix.RTN_UNICAST {
1169 t.Fatal("Invalid Type. Route not added properly")
1170 }
1171 if routes[0].Tos != 12 {
1172 t.Fatal("Invalid Tos. Route not added properly")
1173 }
1174 if routes[0].Hoplimit != 100 {
1175 t.Fatal("Invalid Hoplimit. Route not added properly")
1176 }
1177 if routes[0].Realm != 239 {
1178 t.Fatal("Invalid Realm. Route not added properly")
1179 }
1180 }
1181
1182 func TestRouteMultiPath(t *testing.T) {
1183 tearDown := setUpNetlinkTest(t)
1184 defer tearDown()
1185
1186
1187 link, err := LinkByName("lo")
1188 if err != nil {
1189 t.Fatal(err)
1190 }
1191
1192 if err = LinkSetUp(link); err != nil {
1193 t.Fatal(err)
1194 }
1195
1196
1197 dst := &net.IPNet{
1198 IP: net.IPv4(192, 168, 0, 0),
1199 Mask: net.CIDRMask(24, 32),
1200 }
1201
1202 idx := link.Attrs().Index
1203 route := Route{Dst: dst, MultiPath: []*NexthopInfo{{LinkIndex: idx}, {LinkIndex: idx}}}
1204 if err := RouteAdd(&route); err != nil {
1205 t.Fatal(err)
1206 }
1207 routes, err := RouteList(nil, FAMILY_V4)
1208 if err != nil {
1209 t.Fatal(err)
1210 }
1211 if len(routes) != 1 {
1212 t.Fatal("MultiPath Route not added properly")
1213 }
1214 if len(routes[0].MultiPath) != 2 {
1215 t.Fatal("MultiPath Route not added properly")
1216 }
1217 }
1218
1219 func TestRouteIifOption(t *testing.T) {
1220 skipUnlessRoot(t)
1221
1222 runtime.LockOSThread()
1223 t.Cleanup(runtime.UnlockOSThread)
1224
1225 rootNs, err := netns.GetFromPid(1)
1226 if err != nil {
1227 t.Fatalf("could not get root ns: %s", err)
1228 }
1229 t.Cleanup(func() { rootNs.Close() })
1230
1231 rootHdl, err := NewHandleAt(rootNs)
1232 if err != nil {
1233 t.Fatalf("could not create handle for root ns: %s", err)
1234 }
1235 t.Cleanup(func() { rootHdl.Close() })
1236
1237
1238
1239
1240
1241 ns, err := netns.New()
1242 if err != nil {
1243 t.Fatalf("could not create new ns: %s", err)
1244 }
1245 t.Cleanup(func() { ns.Close() })
1246
1247 l := &Veth{
1248 LinkAttrs: LinkAttrs{Name: "veth1"},
1249 PeerName: "veth2",
1250 PeerNamespace: NsFd(ns),
1251 }
1252 if err = rootHdl.LinkAdd(l); err != nil {
1253 t.Fatalf("could not add veth interface: %s", err)
1254 }
1255 t.Cleanup(func() { rootHdl.LinkDel(l) })
1256
1257 ve1, err := rootHdl.LinkByName("veth1")
1258 if err != nil {
1259 t.Fatalf("could not get link veth1: %s", err)
1260 }
1261
1262 err = rootHdl.AddrAdd(ve1, &Addr{IPNet: &net.IPNet{IP: net.ParseIP("2.2.2.3"), Mask: net.CIDRMask(24, 32)}})
1263 if err != nil {
1264 t.Fatalf("could not set address for veth1: %s", err)
1265 }
1266
1267 nh, err := NewHandleAt(ns)
1268 if err != nil {
1269 t.Fatalf("could not get handle for ns %+v: %s", ns, err)
1270 }
1271 t.Cleanup(func() { nh.Close() })
1272
1273 ve2, err := nh.LinkByName("veth2")
1274 if err != nil {
1275 t.Fatalf("could not get link veth2: %s", err)
1276 }
1277
1278 err = nh.AddrAdd(ve2, &Addr{IPNet: &net.IPNet{IP: net.ParseIP("2.2.2.4"), Mask: net.CIDRMask(24, 32)}})
1279 if err != nil {
1280 t.Fatalf("could set address for veth2: %s", err)
1281 }
1282
1283 if err = rootHdl.LinkSetUp(ve1); err != nil {
1284 t.Fatalf("could not set veth1 up: %s", err)
1285 }
1286
1287 if err = nh.LinkSetUp(ve2); err != nil {
1288 t.Fatalf("could not set veth2 up: %s", err)
1289 }
1290
1291 err = nh.RouteAdd(&Route{
1292 Dst: &net.IPNet{
1293 IP: net.IPv4zero,
1294 Mask: net.CIDRMask(0, 32),
1295 },
1296 Gw: net.ParseIP("2.2.2.3"),
1297 })
1298 if err != nil {
1299 t.Fatalf("could not add default route to ns: %s", err)
1300 }
1301
1302
1303
1304 _, err = rootHdl.RouteGetWithOptions(net.ParseIP("8.8.8.8"), &RouteGetOptions{
1305 SrcAddr: net.ParseIP("2.2.2.4"),
1306 })
1307 if err == nil {
1308 t.Fatal("route get should have resulted in error but did not")
1309 }
1310
1311 testWithOptions := func(opts *RouteGetOptions) {
1312 routes, err := rootHdl.RouteGetWithOptions(net.ParseIP("8.8.8.8"), opts)
1313 if err != nil {
1314 t.Fatalf("could not get route: %s", err)
1315 }
1316 if len(routes) != 1 {
1317 t.Fatalf("did not get exactly one route, routes: %+v", routes)
1318 }
1319
1320
1321 r, err := rootHdl.RouteGet(net.ParseIP("8.8.8.8"))
1322 if err != nil {
1323 t.Fatalf("could not get default route for 8.8.8.8: %s", err)
1324 }
1325 if len(r) != 1 {
1326 t.Fatalf("did not get exactly one route, routes: %+v", routes)
1327 }
1328 if !routes[0].Gw.Equal(r[0].Gw) {
1329 t.Fatalf("wrong gateway in route: expected: %s, got: %s", r[0].Gw, routes[0].Gw)
1330 }
1331 if routes[0].LinkIndex != r[0].LinkIndex {
1332 t.Fatalf("wrong link in route: expected: %d, got: %d", r[0].LinkIndex, routes[0].LinkIndex)
1333 }
1334 }
1335
1336 t.Run("with iif", func(t *testing.T) {
1337 testWithOptions(&RouteGetOptions{
1338 SrcAddr: net.ParseIP("2.2.2.4"),
1339 Iif: "veth1",
1340 })
1341 })
1342
1343 t.Run("with iifIndex", func(t *testing.T) {
1344 testWithOptions(&RouteGetOptions{
1345 SrcAddr: net.ParseIP("2.2.2.4"),
1346 IifIndex: ve1.Attrs().Index,
1347 })
1348 })
1349
1350 t.Run("with iif and iifIndex", func(t *testing.T) {
1351 testWithOptions(&RouteGetOptions{
1352 SrcAddr: net.ParseIP("2.2.2.4"),
1353 Iif: "veth1",
1354 IifIndex: ve2.Attrs().Index,
1355 })
1356 })
1357 }
1358
1359 func TestRouteOifOption(t *testing.T) {
1360 tearDown := setUpNetlinkTest(t)
1361 defer tearDown()
1362
1363
1364 err := LinkAdd(&Dummy{LinkAttrs{Name: "eth0"}})
1365 if err != nil {
1366 t.Fatal(err)
1367 }
1368
1369 link1, err := LinkByName("eth0")
1370 if err != nil {
1371 t.Fatal(err)
1372 }
1373
1374 if err = LinkSetUp(link1); err != nil {
1375 t.Fatal(err)
1376 }
1377
1378 if err = LinkAdd(&Dummy{LinkAttrs{Name: "eth1"}}); err != nil {
1379 t.Fatal(err)
1380 }
1381
1382 link2, err := LinkByName("eth1")
1383 if err != nil {
1384 t.Fatal(err)
1385 }
1386
1387 if err = LinkSetUp(link2); err != nil {
1388 t.Fatal(err)
1389 }
1390
1391
1392 addr1 := &Addr{
1393 IPNet: &net.IPNet{
1394 IP: net.IPv4(192, 168, 1, 1),
1395 Mask: net.CIDRMask(24, 32),
1396 },
1397 }
1398
1399 if err = AddrAdd(link1, addr1); err != nil {
1400 t.Fatal(err)
1401 }
1402
1403 addr2 := &Addr{
1404 IPNet: &net.IPNet{
1405 IP: net.IPv4(192, 168, 2, 1),
1406 Mask: net.CIDRMask(24, 32),
1407 },
1408 }
1409
1410 if err = AddrAdd(link2, addr2); err != nil {
1411 t.Fatal(err)
1412 }
1413
1414
1415 dst := &net.IPNet{
1416 IP: net.IPv4(0, 0, 0, 0),
1417 Mask: net.CIDRMask(0, 32),
1418 }
1419 gw1 := net.IPv4(192, 168, 1, 254)
1420 gw2 := net.IPv4(192, 168, 2, 254)
1421 route := Route{Dst: dst, MultiPath: []*NexthopInfo{{LinkIndex: link1.Attrs().Index,
1422 Gw: gw1}, {LinkIndex: link2.Attrs().Index, Gw: gw2}}}
1423 if err := RouteAdd(&route); err != nil {
1424 t.Fatal(err)
1425 }
1426
1427
1428 dstIP := net.IPv4(10, 1, 1, 1)
1429 routes, err := RouteGetWithOptions(dstIP, &RouteGetOptions{Oif: "eth0"})
1430 if err != nil {
1431 t.Fatal(err)
1432 }
1433
1434 if len(routes) != 1 || routes[0].LinkIndex != link1.Attrs().Index ||
1435 !routes[0].Gw.Equal(gw1) {
1436 t.Fatal("Get route from unmatched interface")
1437 }
1438
1439 routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{Oif: "eth1"})
1440 if err != nil {
1441 t.Fatal(err)
1442 }
1443
1444 if len(routes) != 1 || routes[0].LinkIndex != link2.Attrs().Index ||
1445 !routes[0].Gw.Equal(gw2) {
1446 t.Fatal("Get route from unmatched interface")
1447 }
1448
1449 }
1450
1451 func TestFilterDefaultRoute(t *testing.T) {
1452 tearDown := setUpNetlinkTest(t)
1453 defer tearDown()
1454
1455
1456 link, err := LinkByName("lo")
1457 if err != nil {
1458 t.Fatal(err)
1459 }
1460
1461 if err = LinkSetUp(link); err != nil {
1462 t.Fatal(err)
1463 }
1464
1465 address := &Addr{
1466 IPNet: &net.IPNet{
1467 IP: net.IPv4(127, 0, 0, 2),
1468 Mask: net.CIDRMask(24, 32),
1469 },
1470 }
1471 if err = AddrAdd(link, address); err != nil {
1472 t.Fatal(err)
1473 }
1474
1475
1476 gw := net.IPv4(127, 0, 0, 2)
1477
1478 defaultRoute := Route{
1479 Dst: nil,
1480 Gw: gw,
1481 }
1482
1483 if err := RouteAdd(&defaultRoute); err != nil {
1484 t.Fatal(err)
1485 }
1486
1487
1488 dst := &net.IPNet{
1489 IP: net.IPv4(192, 168, 0, 0),
1490 Mask: net.CIDRMask(24, 32),
1491 }
1492
1493 extraRoute := Route{
1494 Dst: dst,
1495 Gw: gw,
1496 }
1497
1498 if err := RouteAdd(&extraRoute); err != nil {
1499 t.Fatal(err)
1500 }
1501 var filterTests = []struct {
1502 filter *Route
1503 mask uint64
1504 expected net.IP
1505 }{
1506 {
1507 &Route{Dst: nil},
1508 RT_FILTER_DST,
1509 gw,
1510 },
1511 {
1512 &Route{Dst: dst},
1513 RT_FILTER_DST,
1514 gw,
1515 },
1516 }
1517
1518 for _, f := range filterTests {
1519 routes, err := RouteListFiltered(FAMILY_V4, f.filter, f.mask)
1520 if err != nil {
1521 t.Fatal(err)
1522 }
1523 if len(routes) != 1 {
1524 t.Fatal("Route not filtered properly")
1525 }
1526 if !routes[0].Gw.Equal(gw) {
1527 t.Fatal("Unexpected Gateway")
1528 }
1529 }
1530
1531 }
1532
1533 func TestMPLSRouteAddDel(t *testing.T) {
1534 tearDown := setUpMPLSNetlinkTest(t)
1535 defer tearDown()
1536
1537
1538 link, err := LinkByName("lo")
1539 if err != nil {
1540 t.Fatal(err)
1541 }
1542
1543
1544 if err := LinkSetUp(link); err != nil {
1545 t.Fatal(err)
1546 }
1547
1548 mplsDst := 100
1549 route := Route{
1550 LinkIndex: link.Attrs().Index,
1551 MPLSDst: &mplsDst,
1552 NewDst: &MPLSDestination{
1553 Labels: []int{200, 300},
1554 },
1555 }
1556 if err := RouteAdd(&route); err != nil {
1557 t.Fatal(err)
1558 }
1559 routes, err := RouteList(link, FAMILY_MPLS)
1560 if err != nil {
1561 t.Fatal(err)
1562 }
1563 if len(routes) != 1 {
1564 t.Fatal("Route not added properly")
1565 }
1566
1567 if err := RouteDel(&route); err != nil {
1568 t.Fatal(err)
1569 }
1570 routes, err = RouteList(link, FAMILY_MPLS)
1571 if err != nil {
1572 t.Fatal(err)
1573 }
1574 if len(routes) != 0 {
1575 t.Fatal("Route not removed properly")
1576 }
1577
1578 }
1579
1580 func TestIP6tnlRouteAddDel(t *testing.T) {
1581 _, err := RouteList(nil, FAMILY_V4)
1582 if err != nil {
1583 t.Fatal(err)
1584 }
1585
1586 tearDown := setUpNetlinkTest(t)
1587 defer tearDown()
1588
1589
1590 link, err := LinkByName("lo")
1591 if err != nil {
1592 t.Fatal(err)
1593 }
1594
1595
1596 if err := LinkSetUp(link); err != nil {
1597 t.Fatal(err)
1598 }
1599
1600 _, dst, err := net.ParseCIDR("192.168.99.0/24")
1601 if err != nil {
1602 t.Fatalf("cannot parse destination prefix: %v", err)
1603 }
1604
1605 encap := IP6tnlEncap{
1606 Dst: net.ParseIP("2001:db8::"),
1607 Src: net.ParseIP("::"),
1608 }
1609
1610 route := &Route{
1611 LinkIndex: link.Attrs().Index,
1612 Dst: dst,
1613 Encap: &encap,
1614 }
1615
1616 if err := RouteAdd(route); err != nil {
1617 t.Fatalf("Cannot add route: %v", err)
1618 }
1619 routes, err := RouteList(link, FAMILY_V4)
1620 if err != nil {
1621 t.Fatal(err)
1622 }
1623 if len(routes) != 1 {
1624 t.Fatal("Route not added properly")
1625 }
1626
1627 if err := RouteDel(route); err != nil {
1628 t.Fatal(err)
1629 }
1630 routes, err = RouteList(link, FAMILY_V4)
1631 if err != nil {
1632 t.Fatal(err)
1633 }
1634 if len(routes) != 0 {
1635 t.Fatal("Route not removed properly")
1636 }
1637
1638 }
1639
1640 func TestRouteEqual(t *testing.T) {
1641 mplsDst := 100
1642 seg6encap := &SEG6Encap{Mode: nl.SEG6_IPTUN_MODE_ENCAP}
1643 seg6encap.Segments = []net.IP{net.ParseIP("fc00:a000::11")}
1644 cases := []Route{
1645 {
1646 Dst: nil,
1647 Gw: net.IPv4(1, 1, 1, 1),
1648 },
1649 {
1650 LinkIndex: 20,
1651 Dst: nil,
1652 Gw: net.IPv4(1, 1, 1, 1),
1653 },
1654 {
1655 ILinkIndex: 21,
1656 LinkIndex: 20,
1657 Dst: nil,
1658 Gw: net.IPv4(1, 1, 1, 1),
1659 },
1660 {
1661 LinkIndex: 20,
1662 Dst: nil,
1663 Protocol: 20,
1664 Gw: net.IPv4(1, 1, 1, 1),
1665 },
1666 {
1667 LinkIndex: 20,
1668 Dst: nil,
1669 Priority: 20,
1670 Gw: net.IPv4(1, 1, 1, 1),
1671 },
1672 {
1673 LinkIndex: 20,
1674 Dst: nil,
1675 Type: 20,
1676 Gw: net.IPv4(1, 1, 1, 1),
1677 },
1678 {
1679 LinkIndex: 20,
1680 Dst: nil,
1681 Table: 200,
1682 Gw: net.IPv4(1, 1, 1, 1),
1683 },
1684 {
1685 LinkIndex: 20,
1686 Dst: nil,
1687 Tos: 1,
1688 Gw: net.IPv4(1, 1, 1, 1),
1689 },
1690 {
1691 LinkIndex: 20,
1692 Dst: nil,
1693 Hoplimit: 1,
1694 Gw: net.IPv4(1, 1, 1, 1),
1695 },
1696 {
1697 LinkIndex: 20,
1698 Dst: nil,
1699 Realm: 29,
1700 Gw: net.IPv4(1, 1, 1, 1),
1701 },
1702 {
1703 LinkIndex: 20,
1704 Dst: nil,
1705 Flags: int(FLAG_ONLINK),
1706 Gw: net.IPv4(1, 1, 1, 1),
1707 },
1708 {
1709 LinkIndex: 10,
1710 Dst: &net.IPNet{
1711 IP: net.IPv4(192, 168, 0, 0),
1712 Mask: net.CIDRMask(24, 32),
1713 },
1714 Src: net.IPv4(127, 1, 1, 1),
1715 },
1716 {
1717 LinkIndex: 10,
1718 Scope: unix.RT_SCOPE_LINK,
1719 Dst: &net.IPNet{
1720 IP: net.IPv4(192, 168, 0, 0),
1721 Mask: net.CIDRMask(24, 32),
1722 },
1723 Src: net.IPv4(127, 1, 1, 1),
1724 },
1725 {
1726 LinkIndex: 3,
1727 Dst: &net.IPNet{
1728 IP: net.IPv4(1, 1, 1, 1),
1729 Mask: net.CIDRMask(32, 32),
1730 },
1731 Src: net.IPv4(127, 3, 3, 3),
1732 Scope: unix.RT_SCOPE_LINK,
1733 Priority: 13,
1734 Table: unix.RT_TABLE_MAIN,
1735 Type: unix.RTN_UNICAST,
1736 Tos: 12,
1737 },
1738 {
1739 LinkIndex: 3,
1740 Dst: &net.IPNet{
1741 IP: net.IPv4(1, 1, 1, 1),
1742 Mask: net.CIDRMask(32, 32),
1743 },
1744 Src: net.IPv4(127, 3, 3, 3),
1745 Scope: unix.RT_SCOPE_LINK,
1746 Priority: 13,
1747 Table: unix.RT_TABLE_MAIN,
1748 Type: unix.RTN_UNICAST,
1749 Hoplimit: 100,
1750 },
1751 {
1752 LinkIndex: 3,
1753 Dst: &net.IPNet{
1754 IP: net.IPv4(1, 1, 1, 1),
1755 Mask: net.CIDRMask(32, 32),
1756 },
1757 Src: net.IPv4(127, 3, 3, 3),
1758 Scope: unix.RT_SCOPE_LINK,
1759 Priority: 13,
1760 Table: unix.RT_TABLE_MAIN,
1761 Type: unix.RTN_UNICAST,
1762 Realm: 129,
1763 },
1764 {
1765 LinkIndex: 10,
1766 MPLSDst: &mplsDst,
1767 NewDst: &MPLSDestination{
1768 Labels: []int{200, 300},
1769 },
1770 },
1771 {
1772 Dst: nil,
1773 Gw: net.IPv4(1, 1, 1, 1),
1774 Encap: &MPLSEncap{
1775 Labels: []int{100},
1776 },
1777 },
1778 {
1779 LinkIndex: 10,
1780 Dst: &net.IPNet{
1781 IP: net.IPv4(10, 0, 0, 102),
1782 Mask: net.CIDRMask(32, 32),
1783 },
1784 Encap: seg6encap,
1785 },
1786 {
1787 Dst: nil,
1788 MultiPath: []*NexthopInfo{{LinkIndex: 10}, {LinkIndex: 20}},
1789 },
1790 {
1791 Dst: nil,
1792 MultiPath: []*NexthopInfo{{
1793 LinkIndex: 10,
1794 Gw: net.IPv4(1, 1, 1, 1),
1795 }, {LinkIndex: 20}},
1796 },
1797 {
1798 Dst: nil,
1799 MultiPath: []*NexthopInfo{{
1800 LinkIndex: 10,
1801 Gw: net.IPv4(1, 1, 1, 1),
1802 Encap: &MPLSEncap{
1803 Labels: []int{100},
1804 },
1805 }, {LinkIndex: 20}},
1806 },
1807 {
1808 Dst: nil,
1809 MultiPath: []*NexthopInfo{{
1810 LinkIndex: 10,
1811 NewDst: &MPLSDestination{
1812 Labels: []int{200, 300},
1813 },
1814 }, {LinkIndex: 20}},
1815 },
1816 {
1817 Dst: nil,
1818 MultiPath: []*NexthopInfo{{
1819 LinkIndex: 10,
1820 Encap: seg6encap,
1821 }, {LinkIndex: 20}},
1822 },
1823 }
1824 for i1 := range cases {
1825 for i2 := range cases {
1826 got := cases[i1].Equal(cases[i2])
1827 expected := i1 == i2
1828 if got != expected {
1829 t.Errorf("Equal(%q,%q) == %s but expected %s",
1830 cases[i1], cases[i2],
1831 strconv.FormatBool(got),
1832 strconv.FormatBool(expected))
1833 }
1834 }
1835 }
1836 }
1837
1838 func TestIPNetEqual(t *testing.T) {
1839 cases := []string{
1840 "1.1.1.1/24", "1.1.1.0/24", "1.1.1.1/32",
1841 "0.0.0.0/0", "0.0.0.0/14",
1842 "2001:db8::/32", "2001:db8::/128",
1843 "2001:db8::caff/32", "2001:db8::caff/128",
1844 "",
1845 }
1846 for _, c1 := range cases {
1847 var n1 *net.IPNet
1848 if c1 != "" {
1849 var i1 net.IP
1850 var err1 error
1851 i1, n1, err1 = net.ParseCIDR(c1)
1852 if err1 != nil {
1853 panic(err1)
1854 }
1855 n1.IP = i1
1856 }
1857 for _, c2 := range cases {
1858 var n2 *net.IPNet
1859 if c2 != "" {
1860 var i2 net.IP
1861 var err2 error
1862 i2, n2, err2 = net.ParseCIDR(c2)
1863 if err2 != nil {
1864 panic(err2)
1865 }
1866 n2.IP = i2
1867 }
1868
1869 got := ipNetEqual(n1, n2)
1870 expected := c1 == c2
1871 if got != expected {
1872 t.Errorf("IPNetEqual(%q,%q) == %s but expected %s",
1873 c1, c2,
1874 strconv.FormatBool(got),
1875 strconv.FormatBool(expected))
1876 }
1877 }
1878 }
1879 }
1880
1881 func TestSEG6LocalEqual(t *testing.T) {
1882
1883
1884 segs := []net.IP{net.ParseIP("fc00:a000::11")}
1885
1886 var flags_end [nl.SEG6_LOCAL_MAX]bool
1887 flags_end[nl.SEG6_LOCAL_ACTION] = true
1888 var flags_end_x [nl.SEG6_LOCAL_MAX]bool
1889 flags_end_x[nl.SEG6_LOCAL_ACTION] = true
1890 flags_end_x[nl.SEG6_LOCAL_NH6] = true
1891 var flags_end_t [nl.SEG6_LOCAL_MAX]bool
1892 flags_end_t[nl.SEG6_LOCAL_ACTION] = true
1893 flags_end_t[nl.SEG6_LOCAL_TABLE] = true
1894 var flags_end_dx2 [nl.SEG6_LOCAL_MAX]bool
1895 flags_end_dx2[nl.SEG6_LOCAL_ACTION] = true
1896 flags_end_dx2[nl.SEG6_LOCAL_OIF] = true
1897 var flags_end_dx6 [nl.SEG6_LOCAL_MAX]bool
1898 flags_end_dx6[nl.SEG6_LOCAL_ACTION] = true
1899 flags_end_dx6[nl.SEG6_LOCAL_NH6] = true
1900 var flags_end_dx4 [nl.SEG6_LOCAL_MAX]bool
1901 flags_end_dx4[nl.SEG6_LOCAL_ACTION] = true
1902 flags_end_dx4[nl.SEG6_LOCAL_NH4] = true
1903 var flags_end_dt6 [nl.SEG6_LOCAL_MAX]bool
1904 flags_end_dt6[nl.SEG6_LOCAL_ACTION] = true
1905 flags_end_dt6[nl.SEG6_LOCAL_TABLE] = true
1906 var flags_end_dt4 [nl.SEG6_LOCAL_MAX]bool
1907 flags_end_dt4[nl.SEG6_LOCAL_ACTION] = true
1908 flags_end_dt4[nl.SEG6_LOCAL_TABLE] = true
1909 var flags_end_b6 [nl.SEG6_LOCAL_MAX]bool
1910 flags_end_b6[nl.SEG6_LOCAL_ACTION] = true
1911 flags_end_b6[nl.SEG6_LOCAL_SRH] = true
1912 var flags_end_b6_encaps [nl.SEG6_LOCAL_MAX]bool
1913 flags_end_b6_encaps[nl.SEG6_LOCAL_ACTION] = true
1914 flags_end_b6_encaps[nl.SEG6_LOCAL_SRH] = true
1915 var flags_end_bpf [nl.SEG6_LOCAL_MAX]bool
1916 flags_end_bpf[nl.SEG6_LOCAL_ACTION] = true
1917 flags_end_bpf[nl.SEG6_LOCAL_BPF] = true
1918
1919 cases := []SEG6LocalEncap{
1920 {
1921 Flags: flags_end,
1922 Action: nl.SEG6_LOCAL_ACTION_END,
1923 },
1924 {
1925 Flags: flags_end_x,
1926 Action: nl.SEG6_LOCAL_ACTION_END_X,
1927 In6Addr: net.ParseIP("2001:db8::1"),
1928 },
1929 {
1930 Flags: flags_end_t,
1931 Action: nl.SEG6_LOCAL_ACTION_END_T,
1932 Table: 10,
1933 },
1934 {
1935 Flags: flags_end_dx2,
1936 Action: nl.SEG6_LOCAL_ACTION_END_DX2,
1937 Oif: 20,
1938 },
1939 {
1940 Flags: flags_end_dx6,
1941 Action: nl.SEG6_LOCAL_ACTION_END_DX6,
1942 In6Addr: net.ParseIP("2001:db8::1"),
1943 },
1944 {
1945 Flags: flags_end_dx4,
1946 Action: nl.SEG6_LOCAL_ACTION_END_DX4,
1947 InAddr: net.IPv4(192, 168, 10, 10),
1948 },
1949 {
1950 Flags: flags_end_dt6,
1951 Action: nl.SEG6_LOCAL_ACTION_END_DT6,
1952 Table: 30,
1953 },
1954 {
1955 Flags: flags_end_dt4,
1956 Action: nl.SEG6_LOCAL_ACTION_END_DT4,
1957 Table: 40,
1958 },
1959 {
1960 Flags: flags_end_b6,
1961 Action: nl.SEG6_LOCAL_ACTION_END_B6,
1962 Segments: segs,
1963 },
1964 {
1965 Flags: flags_end_b6_encaps,
1966 Action: nl.SEG6_LOCAL_ACTION_END_B6_ENCAPS,
1967 Segments: segs,
1968 },
1969 }
1970
1971
1972 endBpf := SEG6LocalEncap{
1973 Flags: flags_end_bpf,
1974 Action: nl.SEG6_LOCAL_ACTION_END_BPF,
1975 }
1976 _ = endBpf.SetProg(1, "firewall")
1977 cases = append(cases, endBpf)
1978
1979 for i1 := range cases {
1980 for i2 := range cases {
1981 got := cases[i1].Equal(&cases[i2])
1982 expected := i1 == i2
1983 if got != expected {
1984 t.Errorf("Equal(%v,%v) == %s but expected %s",
1985 cases[i1], cases[i2],
1986 strconv.FormatBool(got),
1987 strconv.FormatBool(expected))
1988 }
1989 }
1990 }
1991 }
1992 func TestSEG6RouteAddDel(t *testing.T) {
1993 if os.Getenv("CI") == "true" {
1994 t.Skipf("Fails in CI with: route_test.go:*: Invalid Type. SEG6_IPTUN_MODE_INLINE routes not added properly")
1995 }
1996
1997
1998 tearDown := setUpSEG6NetlinkTest(t)
1999 defer tearDown()
2000
2001
2002 link, err := LinkByName("lo")
2003 if err != nil {
2004 t.Fatal(err)
2005 }
2006 if err := LinkSetUp(link); err != nil {
2007 t.Fatal(err)
2008 }
2009
2010 dst1 := &net.IPNet{
2011 IP: net.ParseIP("2001:db8::1"),
2012 Mask: net.CIDRMask(128, 128),
2013 }
2014 dst2 := &net.IPNet{
2015 IP: net.IPv4(10, 0, 0, 102),
2016 Mask: net.CIDRMask(32, 32),
2017 }
2018 var s1, s2 []net.IP
2019 s1 = append(s1, net.ParseIP("::"))
2020 s1 = append(s1, net.ParseIP("fc00:a000::12"))
2021 s1 = append(s1, net.ParseIP("fc00:a000::11"))
2022 s2 = append(s2, net.ParseIP("fc00:a000::22"))
2023 s2 = append(s2, net.ParseIP("fc00:a000::21"))
2024 e1 := &SEG6Encap{Mode: nl.SEG6_IPTUN_MODE_INLINE}
2025 e2 := &SEG6Encap{Mode: nl.SEG6_IPTUN_MODE_ENCAP}
2026 e1.Segments = s1
2027 e2.Segments = s2
2028 route1 := Route{LinkIndex: link.Attrs().Index, Dst: dst1, Encap: e1}
2029 route2 := Route{LinkIndex: link.Attrs().Index, Dst: dst2, Encap: e2}
2030
2031
2032 if err := RouteAdd(&route1); err != nil {
2033 t.Fatal(err)
2034 }
2035 if err := RouteAdd(&route2); err != nil {
2036 t.Fatal(err)
2037 }
2038
2039 routes, err := RouteList(link, FAMILY_V6)
2040 if err != nil {
2041 t.Fatal(err)
2042 }
2043 if len(routes) != 1 {
2044 t.Fatal("SEG6 routes not added properly")
2045 }
2046 for _, route := range routes {
2047 if route.Encap == nil || route.Encap.Type() != nl.LWTUNNEL_ENCAP_SEG6 {
2048 t.Fatal("Invalid Type. SEG6_IPTUN_MODE_INLINE routes not added properly")
2049 }
2050 }
2051
2052 routes, err = RouteList(link, FAMILY_V4)
2053 if err != nil {
2054 t.Fatal(err)
2055 }
2056 if len(routes) != 1 {
2057 t.Fatal("SEG6 routes not added properly")
2058 }
2059 for _, route := range routes {
2060 if route.Encap.Type() != nl.LWTUNNEL_ENCAP_SEG6 {
2061 t.Fatal("Invalid Type. SEG6_IPTUN_MODE_ENCAP routes not added properly")
2062 }
2063 }
2064
2065
2066 if err := RouteDel(&route1); err != nil {
2067 t.Fatal(err)
2068 }
2069 if err := RouteDel(&route2); err != nil {
2070 t.Fatal(err)
2071 }
2072 routes, err = RouteList(link, FAMILY_V4)
2073 if err != nil {
2074 t.Fatal(err)
2075 }
2076 if len(routes) != 0 {
2077 t.Fatal("SEG6 routes not removed properly")
2078 }
2079 }
2080
2081
2082 func TestSEG6LocalRoute6AddDel(t *testing.T) {
2083 minKernelRequired(t, 4, 14)
2084 tearDown := setUpSEG6NetlinkTest(t)
2085 defer tearDown()
2086
2087
2088
2089 la := NewLinkAttrs()
2090 la.Name = "dummy_route6"
2091 la.TxQLen = 1500
2092 dummy := &Dummy{LinkAttrs: la}
2093 if err := LinkAdd(dummy); err != nil {
2094 t.Fatal(err)
2095 }
2096
2097 link, err := LinkByName("dummy_route6")
2098 if err != nil {
2099 t.Fatal(err)
2100 }
2101 if err := LinkSetUp(link); err != nil {
2102 t.Fatal(err)
2103 }
2104
2105 dst1 := &net.IPNet{
2106 IP: net.ParseIP("2001:db8::1"),
2107 Mask: net.CIDRMask(128, 128),
2108 }
2109
2110
2111
2112 var s1 []net.IP
2113 s1 = append(s1, net.ParseIP("fc00:a000::12"))
2114 s1 = append(s1, net.ParseIP("fc00:a000::11"))
2115 var flags_end_b6_encaps [nl.SEG6_LOCAL_MAX]bool
2116 flags_end_b6_encaps[nl.SEG6_LOCAL_ACTION] = true
2117 flags_end_b6_encaps[nl.SEG6_LOCAL_SRH] = true
2118 e1 := &SEG6LocalEncap{
2119 Flags: flags_end_b6_encaps,
2120 Action: nl.SEG6_LOCAL_ACTION_END_B6,
2121 Segments: s1,
2122 }
2123 route1 := Route{LinkIndex: link.Attrs().Index, Dst: dst1, Encap: e1}
2124
2125
2126 if err := RouteAdd(&route1); err != nil {
2127 t.Fatal(err)
2128 }
2129
2130
2131
2132
2133 routesFound, err := RouteGet(dst1.IP)
2134 if err != nil {
2135 t.Fatal(err)
2136 }
2137 if len(routesFound) != 1 {
2138 t.Fatal("SEG6Local route not added correctly")
2139 }
2140 if !e1.Equal(routesFound[0].Encap) {
2141 t.Fatal("Encap does not match the original SEG6LocalEncap")
2142 }
2143
2144
2145 if err := RouteDel(&route1); err != nil {
2146 t.Fatal(err)
2147 }
2148
2149 if _, err = RouteGet(dst1.IP); err == nil {
2150 t.Fatal("SEG6Local route still exists.")
2151 }
2152
2153
2154 if err := LinkDel(link); err != nil {
2155 t.Fatal(err)
2156 }
2157 }
2158
2159 func TestBpfEncap(t *testing.T) {
2160 tCase := &BpfEncap{}
2161 if err := tCase.SetProg(nl.LWT_BPF_IN, 0, "test_in"); err == nil {
2162 t.Fatal("BpfEncap: inserting invalid FD did not return error")
2163 }
2164 if err := tCase.SetProg(nl.LWT_BPF_XMIT_HEADROOM, 23, "test_nout"); err == nil {
2165 t.Fatal("BpfEncap: inserting invalid mode did not return error")
2166 }
2167 if err := tCase.SetProg(nl.LWT_BPF_XMIT, 12, "test_xmit"); err != nil {
2168 t.Fatal("BpfEncap: inserting valid program option returned error")
2169 }
2170 if err := tCase.SetXmitHeadroom(12); err != nil {
2171 t.Fatal("BpfEncap: inserting valid headroom returned error")
2172 }
2173 if err := tCase.SetXmitHeadroom(nl.LWT_BPF_MAX_HEADROOM + 1); err == nil {
2174 t.Fatal("BpfEncap: inserting invalid headroom did not return error")
2175 }
2176 tCase = &BpfEncap{}
2177
2178 expected := &BpfEncap{
2179 progs: [nl.LWT_BPF_MAX]bpfObj{
2180 1: {
2181 progName: "test_in[fd:10]",
2182 progFd: 10,
2183 },
2184 2: {
2185 progName: "test_out[fd:11]",
2186 progFd: 11,
2187 },
2188 3: {
2189 progName: "test_xmit[fd:21]",
2190 progFd: 21,
2191 },
2192 },
2193 headroom: 128,
2194 }
2195
2196 _ = tCase.SetProg(1, 10, "test_in")
2197 _ = tCase.SetProg(2, 11, "test_out")
2198 _ = tCase.SetProg(3, 21, "test_xmit")
2199 _ = tCase.SetXmitHeadroom(128)
2200 if !tCase.Equal(expected) {
2201 t.Fatal("BpfEncap: equal comparison failed")
2202 }
2203 _ = tCase.SetProg(3, 21, "test2_xmit")
2204 if tCase.Equal(expected) {
2205 t.Fatal("BpfEncap: equal comparison succeeded when attributes differ")
2206 }
2207 }
2208
2209 func TestMTURouteAddDel(t *testing.T) {
2210 _, err := RouteList(nil, FAMILY_V4)
2211 if err != nil {
2212 t.Fatal(err)
2213 }
2214
2215 tearDown := setUpNetlinkTest(t)
2216 defer tearDown()
2217
2218
2219 link, err := LinkByName("lo")
2220 if err != nil {
2221 t.Fatal(err)
2222 }
2223
2224
2225 if err := LinkSetUp(link); err != nil {
2226 t.Fatal(err)
2227 }
2228
2229
2230 dst := &net.IPNet{
2231 IP: net.IPv4(192, 168, 0, 0),
2232 Mask: net.CIDRMask(24, 32),
2233 }
2234
2235 route := Route{LinkIndex: link.Attrs().Index, Dst: dst, MTU: 500}
2236 if err := RouteAdd(&route); err != nil {
2237 t.Fatal(err)
2238 }
2239 routes, err := RouteList(link, FAMILY_V4)
2240 if err != nil {
2241 t.Fatal(err)
2242 }
2243 if len(routes) != 1 {
2244 t.Fatal("Route not added properly")
2245 }
2246
2247 if route.MTU != routes[0].MTU {
2248 t.Fatal("Route mtu not set properly")
2249 }
2250
2251 if err := RouteDel(&route); err != nil {
2252 t.Fatal(err)
2253 }
2254 routes, err = RouteList(link, FAMILY_V4)
2255 if err != nil {
2256 t.Fatal(err)
2257 }
2258 if len(routes) != 0 {
2259 t.Fatal("Route not removed properly")
2260 }
2261 }
2262
2263 func TestRouteViaAddDel(t *testing.T) {
2264 minKernelRequired(t, 5, 4)
2265 tearDown := setUpNetlinkTest(t)
2266 defer tearDown()
2267
2268 _, err := RouteList(nil, FAMILY_V4)
2269 if err != nil {
2270 t.Fatal(err)
2271 }
2272
2273 link, err := LinkByName("lo")
2274 if err != nil {
2275 t.Fatal(err)
2276 }
2277
2278 if err := LinkSetUp(link); err != nil {
2279 t.Fatal(err)
2280 }
2281
2282 route := &Route{
2283 LinkIndex: link.Attrs().Index,
2284 Dst: &net.IPNet{
2285 IP: net.IPv4(192, 168, 0, 0),
2286 Mask: net.CIDRMask(24, 32),
2287 },
2288 MultiPath: []*NexthopInfo{
2289 {
2290 LinkIndex: link.Attrs().Index,
2291 Via: &Via{
2292 AddrFamily: FAMILY_V6,
2293 Addr: net.ParseIP("2001::1"),
2294 },
2295 },
2296 },
2297 }
2298
2299 if err := RouteAdd(route); err != nil {
2300 t.Fatalf("route: %v, err: %v", route, err)
2301 }
2302
2303 routes, err := RouteList(link, FAMILY_V4)
2304 if err != nil {
2305 t.Fatal(err)
2306 }
2307 if len(routes) != 1 {
2308 t.Fatal("Route not added properly")
2309 }
2310
2311 got := routes[0].Via
2312 want := route.MultiPath[0].Via
2313 if !want.Equal(got) {
2314 t.Fatalf("Route Via attribute does not match; got: %s, want: %s", got, want)
2315 }
2316
2317 if err := RouteDel(route); err != nil {
2318 t.Fatal(err)
2319 }
2320 routes, err = RouteList(link, FAMILY_V4)
2321 if err != nil {
2322 t.Fatal(err)
2323 }
2324 if len(routes) != 0 {
2325 t.Fatal("Route not removed properly")
2326 }
2327 }
2328
2329 func TestRouteUIDOption(t *testing.T) {
2330 tearDown := setUpNetlinkTest(t)
2331 defer tearDown()
2332
2333
2334 err := LinkAdd(&Dummy{LinkAttrs{Name: "eth0"}})
2335 if err != nil {
2336 t.Fatal(err)
2337 }
2338 link, err := LinkByName("eth0")
2339 if err != nil {
2340 t.Fatal(err)
2341 }
2342 if err = LinkSetUp(link); err != nil {
2343 t.Fatal(err)
2344 }
2345 addr := &Addr{
2346 IPNet: &net.IPNet{
2347 IP: net.IPv4(192, 168, 1, 1),
2348 Mask: net.CIDRMask(16, 32),
2349 },
2350 }
2351 if err = AddrAdd(link, addr); err != nil {
2352 t.Fatal(err)
2353 }
2354
2355
2356 testtable := 1000
2357
2358 gw1 := net.IPv4(192, 168, 1, 254)
2359 gw2 := net.IPv4(192, 168, 2, 254)
2360
2361
2362 defaultRouteMain := Route{
2363 Dst: nil,
2364 Gw: gw1,
2365 }
2366 if err := RouteAdd(&defaultRouteMain); err != nil {
2367 t.Fatal(err)
2368 }
2369
2370
2371 defaultRouteTest := Route{
2372 Dst: nil,
2373 Gw: gw2,
2374 Table: testtable,
2375 }
2376 if err := RouteAdd(&defaultRouteTest); err != nil {
2377 t.Fatal(err)
2378 }
2379
2380
2381 routes, err := RouteListFiltered(FAMILY_V4, &Route{
2382 Dst: nil,
2383 Table: unix.RT_TABLE_UNSPEC,
2384 }, RT_FILTER_DST|RT_FILTER_TABLE)
2385 if err != nil {
2386 t.Fatal(err)
2387 }
2388 if len(routes) != 2 || routes[0].Table == routes[1].Table {
2389 t.Fatal("Routes not added properly")
2390 }
2391
2392
2393
2394 var uid uint32 = 1000
2395 rule := NewRule()
2396 rule.UIDRange = NewRuleUIDRange(uid, uid)
2397 rule.Table = testtable
2398 if err := RuleAdd(rule); err != nil {
2399 t.Fatal(err)
2400 }
2401
2402 dstIP := net.IPv4(10, 1, 1, 1)
2403
2404
2405 routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{UID: nil})
2406 if err != nil {
2407 t.Fatal(err)
2408 }
2409
2410 if len(routes) != 1 || !routes[0].Gw.Equal(gw1) {
2411 t.Fatal(routes)
2412 }
2413
2414
2415 routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{UID: &uid})
2416 if err != nil {
2417 t.Fatal(err)
2418 }
2419
2420 if len(routes) != 1 || !routes[0].Gw.Equal(gw2) {
2421 t.Fatal(routes)
2422 }
2423 }
2424
2425 func TestRouteFWMarkOption(t *testing.T) {
2426 tearDown := setUpNetlinkTest(t)
2427 defer tearDown()
2428
2429
2430 err := LinkAdd(&Dummy{LinkAttrs{Name: "eth0"}})
2431 if err != nil {
2432 t.Fatal(err)
2433 }
2434 link, err := LinkByName("eth0")
2435 if err != nil {
2436 t.Fatal(err)
2437 }
2438 if err = LinkSetUp(link); err != nil {
2439 t.Fatal(err)
2440 }
2441 addr := &Addr{
2442 IPNet: &net.IPNet{
2443 IP: net.IPv4(192, 168, 1, 1),
2444 Mask: net.CIDRMask(16, 32),
2445 },
2446 }
2447 if err = AddrAdd(link, addr); err != nil {
2448 t.Fatal(err)
2449 }
2450
2451
2452 testTable0 := 254
2453 testTable1 := 1000
2454 testTable2 := 1001
2455
2456 gw0 := net.IPv4(192, 168, 1, 254)
2457 gw1 := net.IPv4(192, 168, 2, 254)
2458 gw2 := net.IPv4(192, 168, 3, 254)
2459
2460
2461 defaultRouteMain := Route{
2462 Dst: nil,
2463 Gw: gw0,
2464 Table: testTable0,
2465 }
2466 if err := RouteAdd(&defaultRouteMain); err != nil {
2467 t.Fatal(err)
2468 }
2469
2470
2471 defaultRouteTest1 := Route{
2472 Dst: nil,
2473 Gw: gw1,
2474 Table: testTable1,
2475 }
2476 if err := RouteAdd(&defaultRouteTest1); err != nil {
2477 t.Fatal(err)
2478 }
2479
2480
2481 defaultRouteTest2 := Route{
2482 Dst: nil,
2483 Gw: gw2,
2484 Table: testTable2,
2485 }
2486 if err := RouteAdd(&defaultRouteTest2); err != nil {
2487 t.Fatal(err)
2488 }
2489
2490
2491 routes, err := RouteListFiltered(FAMILY_V4, &Route{
2492 Dst: nil,
2493 Table: unix.RT_TABLE_UNSPEC,
2494 }, RT_FILTER_DST|RT_FILTER_TABLE)
2495 if err != nil {
2496 t.Fatal(err)
2497 }
2498 if len(routes) != 3 || routes[0].Table == routes[1].Table || routes[1].Table == routes[2].Table ||
2499 routes[0].Table == routes[2].Table {
2500 t.Fatal("Routes not added properly")
2501 }
2502
2503
2504 fwmark1 := uint32(0xAFFFFFFF)
2505 fwmark2 := uint32(0xBFFFFFFF)
2506
2507 rule := NewRule()
2508 rule.Mark = fwmark1
2509 rule.Mask = &[]uint32{0xFFFFFFFF}[0]
2510
2511 rule.Table = testTable1
2512 if err := RuleAdd(rule); err != nil {
2513 t.Fatal(err)
2514 }
2515
2516 rule = NewRule()
2517 rule.Mark = fwmark2
2518 rule.Mask = &[]uint32{0xFFFFFFFF}[0]
2519 rule.Table = testTable2
2520 if err := RuleAdd(rule); err != nil {
2521 t.Fatal(err)
2522 }
2523
2524 rules, err := RuleListFiltered(FAMILY_V4, &Rule{Mark: fwmark1}, RT_FILTER_MARK)
2525 if err != nil {
2526 t.Fatal(err)
2527 }
2528 if len(rules) != 1 || rules[0].Table != testTable1 || rules[0].Mark != fwmark1 {
2529 t.Fatal("Rules not added properly")
2530 }
2531
2532 rules, err = RuleListFiltered(FAMILY_V4, &Rule{Mark: fwmark2}, RT_FILTER_MARK)
2533 if err != nil {
2534 t.Fatal(err)
2535 }
2536 if len(rules) != 1 || rules[0].Table != testTable2 || rules[0].Mark != fwmark2 {
2537 t.Fatal("Rules not added properly")
2538 }
2539
2540 dstIP := net.IPv4(10, 1, 1, 1)
2541
2542
2543 routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{})
2544 if err != nil {
2545 t.Fatal(err)
2546 }
2547 if len(routes) != 1 || !routes[0].Gw.Equal(gw0) {
2548 t.Fatal(routes)
2549 }
2550
2551
2552 routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{Mark: fwmark1})
2553 if err != nil {
2554 t.Fatal(err)
2555 }
2556 if len(routes) != 1 || !routes[0].Gw.Equal(gw1) {
2557 t.Fatal(routes)
2558 }
2559
2560
2561 routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{Mark: fwmark2})
2562 if err != nil {
2563 t.Fatal(err)
2564 }
2565 if len(routes) != 1 || !routes[0].Gw.Equal(gw2) {
2566 t.Fatal(routes)
2567 }
2568 }
2569
2570 func TestRouteGetFIBMatchOption(t *testing.T) {
2571 tearDown := setUpNetlinkTest(t)
2572 defer tearDown()
2573
2574 err := LinkAdd(&Dummy{LinkAttrs{Name: "eth0"}})
2575 if err != nil {
2576 t.Fatal(err)
2577 }
2578 link, err := LinkByName("eth0")
2579 if err != nil {
2580 t.Fatal(err)
2581 }
2582 if err = LinkSetUp(link); err != nil {
2583 t.Fatal(err)
2584 }
2585 addr := &Addr{
2586 IPNet: &net.IPNet{
2587 IP: net.IPv4(192, 168, 0, 2),
2588 Mask: net.CIDRMask(24, 32),
2589 },
2590 }
2591 if err = AddrAdd(link, addr); err != nil {
2592 t.Fatal(err)
2593 }
2594
2595 route := &Route{
2596 LinkIndex: link.Attrs().Index,
2597 Gw: net.IPv4(192, 168, 1, 1),
2598 Dst: &net.IPNet{
2599 IP: net.IPv4(192, 168, 2, 0),
2600 Mask: net.CIDRMask(24, 32),
2601 },
2602 Flags: int(FLAG_ONLINK),
2603 }
2604
2605 err = RouteAdd(route)
2606 if err != nil {
2607 t.Fatal(err)
2608 }
2609
2610 routes, err := RouteGetWithOptions(net.IPv4(192, 168, 2, 1), &RouteGetOptions{FIBMatch: true})
2611 if err != nil {
2612 t.Fatal(err)
2613 }
2614
2615 if len(routes) != 1 {
2616 t.Fatalf("More than one route matched %v", routes)
2617 }
2618
2619 if len(routes[0].ListFlags()) != 1 {
2620 t.Fatalf("More than one route flag returned %v", routes[0].ListFlags())
2621 }
2622
2623 flag := routes[0].ListFlags()[0]
2624 if flag != "onlink" {
2625 t.Fatalf("Unexpected flag %s returned", flag)
2626 }
2627 }
2628
View as plain text