1
2
3
4 package netlink
5
6 import (
7 "net"
8 "reflect"
9 "testing"
10 "time"
11
12 "github.com/vishvananda/netlink/nl"
13 "golang.org/x/sys/unix"
14 )
15
16 func TestFilterAddDel(t *testing.T) {
17 tearDown := setUpNetlinkTest(t)
18 defer tearDown()
19 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
20 t.Fatal(err)
21 }
22 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
23 t.Fatal(err)
24 }
25 link, err := LinkByName("foo")
26 if err != nil {
27 t.Fatal(err)
28 }
29 if err := LinkSetUp(link); err != nil {
30 t.Fatal(err)
31 }
32 redir, err := LinkByName("bar")
33 if err != nil {
34 t.Fatal(err)
35 }
36 if err := LinkSetUp(redir); err != nil {
37 t.Fatal(err)
38 }
39 qdisc := &Ingress{
40 QdiscAttrs: QdiscAttrs{
41 LinkIndex: link.Attrs().Index,
42 Handle: MakeHandle(0xffff, 0),
43 Parent: HANDLE_INGRESS,
44 },
45 }
46 if err := QdiscAdd(qdisc); err != nil {
47 t.Fatal(err)
48 }
49 qdiscs, err := SafeQdiscList(link)
50 if err != nil {
51 t.Fatal(err)
52 }
53 if len(qdiscs) != 1 {
54 t.Fatal("Failed to add qdisc")
55 }
56 _, ok := qdiscs[0].(*Ingress)
57 if !ok {
58 t.Fatal("Qdisc is the wrong type")
59 }
60 classId := MakeHandle(1, 1)
61 filter := &U32{
62 FilterAttrs: FilterAttrs{
63 LinkIndex: link.Attrs().Index,
64 Parent: MakeHandle(0xffff, 0),
65 Priority: 1,
66 Protocol: unix.ETH_P_IP,
67 },
68 RedirIndex: redir.Attrs().Index,
69 ClassId: classId,
70 }
71 if err := FilterAdd(filter); err != nil {
72 t.Fatal(err)
73 }
74 filters, err := FilterList(link, MakeHandle(0xffff, 0))
75 if err != nil {
76 t.Fatal(err)
77 }
78 if len(filters) != 1 {
79 t.Fatal("Failed to add filter")
80 }
81 u32, ok := filters[0].(*U32)
82 if !ok {
83 t.Fatal("Filter is the wrong type")
84 }
85 if u32.ClassId != classId {
86 t.Fatalf("ClassId of the filter is the wrong value")
87 }
88 if err := FilterDel(filter); err != nil {
89 t.Fatal(err)
90 }
91 filters, err = FilterList(link, MakeHandle(0xffff, 0))
92 if err != nil {
93 t.Fatal(err)
94 }
95 if len(filters) != 0 {
96 t.Fatal("Failed to remove filter")
97 }
98 if err := QdiscDel(qdisc); err != nil {
99 t.Fatal(err)
100 }
101 qdiscs, err = SafeQdiscList(link)
102 if err != nil {
103 t.Fatal(err)
104 }
105 if len(qdiscs) != 0 {
106 t.Fatal("Failed to remove qdisc")
107 }
108 }
109
110 func TestFilterReplace(t *testing.T) {
111 tearDown := setUpNetlinkTest(t)
112 defer tearDown()
113 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
114 t.Fatal(err)
115 }
116 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
117 t.Fatal(err)
118 }
119 link, err := LinkByName("foo")
120 if err != nil {
121 t.Fatal(err)
122 }
123 if err := LinkSetUp(link); err != nil {
124 t.Fatal(err)
125 }
126 redir, err := LinkByName("bar")
127 if err != nil {
128 t.Fatal(err)
129 }
130 if err := LinkSetUp(redir); err != nil {
131 t.Fatal(err)
132 }
133 qdisc := &Ingress{
134 QdiscAttrs: QdiscAttrs{
135 LinkIndex: link.Attrs().Index,
136 Handle: MakeHandle(0xffff, 0),
137 Parent: HANDLE_INGRESS,
138 },
139 }
140 if err := QdiscAdd(qdisc); err != nil {
141 t.Fatal(err)
142 }
143
144 filter := &U32{
145 FilterAttrs: FilterAttrs{
146 LinkIndex: link.Attrs().Index,
147 Parent: MakeHandle(0xffff, 0),
148 Priority: 1,
149 Protocol: unix.ETH_P_IP,
150 },
151 RedirIndex: redir.Attrs().Index,
152 ClassId: MakeHandle(1, 1),
153 }
154
155 if err := FilterReplace(filter); err != nil {
156 t.Fatal(err)
157 }
158 filters, err := FilterList(link, MakeHandle(0xffff, 0))
159 if err != nil {
160 t.Fatal(err)
161 }
162 if len(filters) != 1 {
163 t.Fatal("Failed replace filter")
164 }
165
166 if err := FilterReplace(filter); err != nil {
167 t.Fatal(err)
168 }
169 }
170
171 func TestAdvancedFilterAddDel(t *testing.T) {
172 tearDown := setUpNetlinkTest(t)
173 defer tearDown()
174 if err := LinkAdd(&Ifb{LinkAttrs{Name: "baz"}}); err != nil {
175 t.Fatal(err)
176 }
177 link, err := LinkByName("baz")
178 if err != nil {
179 t.Fatal(err)
180 }
181 if err := LinkSetUp(link); err != nil {
182 t.Fatal(err)
183 }
184 index := link.Attrs().Index
185
186 qdiscHandle := MakeHandle(0x1, 0x0)
187 qdiscAttrs := QdiscAttrs{
188 LinkIndex: index,
189 Handle: qdiscHandle,
190 Parent: HANDLE_ROOT,
191 }
192
193 qdisc := NewHtb(qdiscAttrs)
194 if err := QdiscAdd(qdisc); err != nil {
195 t.Fatal(err)
196 }
197 qdiscs, err := SafeQdiscList(link)
198 if err != nil {
199 t.Fatal(err)
200 }
201 if len(qdiscs) != 1 {
202 t.Fatal("Failed to add qdisc")
203 }
204 _, ok := qdiscs[0].(*Htb)
205 if !ok {
206 t.Fatal("Qdisc is the wrong type")
207 }
208
209 classId := MakeHandle(0x1, 0x46cb)
210 classAttrs := ClassAttrs{
211 LinkIndex: index,
212 Parent: qdiscHandle,
213 Handle: classId,
214 }
215 htbClassAttrs := HtbClassAttrs{
216 Rate: 512 * 1024,
217 Buffer: 32 * 1024,
218 }
219 htbClass := NewHtbClass(classAttrs, htbClassAttrs)
220 if err = ClassReplace(htbClass); err != nil {
221 t.Fatalf("Failed to add a HTB class: %v", err)
222 }
223 classes, err := SafeClassList(link, qdiscHandle)
224 if err != nil {
225 t.Fatal(err)
226 }
227 if len(classes) != 1 {
228 t.Fatal("Failed to add class")
229 }
230 _, ok = classes[0].(*HtbClass)
231 if !ok {
232 t.Fatal("Class is the wrong type")
233 }
234
235 htid := MakeHandle(0x0010, 0000)
236 divisor := uint32(1)
237 hashTable := &U32{
238 FilterAttrs: FilterAttrs{
239 LinkIndex: index,
240 Handle: htid,
241 Parent: qdiscHandle,
242 Priority: 1,
243 Protocol: unix.ETH_P_ALL,
244 },
245 Divisor: divisor,
246 }
247 cHashTable := *hashTable
248 if err := FilterAdd(hashTable); err != nil {
249 t.Fatal(err)
250 }
251
252 if !reflect.DeepEqual(cHashTable, *hashTable) {
253 t.Fatalf("Hash table %v and %v are not equal", cHashTable, *hashTable)
254 }
255
256 u32SelKeys := []TcU32Key{
257 {
258 Mask: 0xff,
259 Val: 80,
260 Off: 20,
261 OffMask: 0,
262 },
263 {
264 Mask: 0xffff,
265 Val: 0x146ca,
266 Off: 32,
267 OffMask: 0,
268 },
269 }
270
271 handle := MakeHandle(0x0000, 0001)
272 filter := &U32{
273 FilterAttrs: FilterAttrs{
274 LinkIndex: index,
275 Handle: handle,
276 Parent: qdiscHandle,
277 Priority: 1,
278 Protocol: unix.ETH_P_ALL,
279 },
280 Sel: &TcU32Sel{
281 Keys: u32SelKeys,
282 Flags: TC_U32_TERMINAL,
283 },
284 ClassId: classId,
285 Hash: htid,
286 Actions: []Action{},
287 }
288
289 cFilter := *filter
290 if err := FilterAdd(filter); err != nil {
291 t.Fatal(err)
292 }
293
294 if !reflect.DeepEqual(cFilter, *filter) {
295 t.Fatalf("U32 %v and %v are not equal", cFilter, *filter)
296 }
297
298 filters, err := FilterList(link, qdiscHandle)
299 if err != nil {
300 t.Fatal(err)
301 }
302 if len(filters) != 1 {
303 t.Fatal("Failed to add filter")
304 }
305
306 u32, ok := filters[0].(*U32)
307 if !ok {
308 t.Fatal("Filter is the wrong type")
309 }
310
311 if u32.Sel.Offmask != filter.Sel.Offmask {
312 t.Fatal("The endianness of TcU32Key.Sel.Offmask is wrong")
313 }
314 if u32.Sel.Hmask != filter.Sel.Hmask {
315 t.Fatal("The endianness of TcU32Key.Sel.Hmask is wrong")
316 }
317 for i, key := range u32.Sel.Keys {
318 if key.Mask != filter.Sel.Keys[i].Mask {
319 t.Fatal("The endianness of TcU32Key.Mask is wrong")
320 }
321 if key.Val != filter.Sel.Keys[i].Val {
322 t.Fatal("The endianness of TcU32Key.Val is wrong")
323 }
324 }
325 if u32.Handle != (handle | htid) {
326 t.Fatalf("The handle is wrong. expected %v but actually %v",
327 (handle | htid), u32.Handle)
328 }
329 if u32.Hash != htid {
330 t.Fatal("The hash table ID is wrong")
331 }
332
333 if err := FilterDel(u32); err != nil {
334 t.Fatal(err)
335 }
336 filters, err = FilterList(link, qdiscHandle)
337 if err != nil {
338 t.Fatal(err)
339 }
340 if len(filters) != 0 {
341 t.Fatal("Failed to remove filter")
342 }
343
344 if err = ClassDel(htbClass); err != nil {
345 t.Fatalf("Failed to delete a HTP class: %v", err)
346 }
347 classes, err = SafeClassList(link, qdiscHandle)
348 if err != nil {
349 t.Fatal(err)
350 }
351 if len(classes) != 0 {
352 t.Fatal("Failed to remove class")
353 }
354
355 if err := QdiscDel(qdisc); err != nil {
356 t.Fatal(err)
357 }
358 qdiscs, err = SafeQdiscList(link)
359 if err != nil {
360 t.Fatal(err)
361 }
362 if len(qdiscs) != 0 {
363 t.Fatal("Failed to remove qdisc")
364 }
365 }
366
367 func TestFilterFwAddDel(t *testing.T) {
368 tearDown := setUpNetlinkTest(t)
369 defer tearDown()
370 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
371 t.Fatal(err)
372 }
373 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
374 t.Fatal(err)
375 }
376 link, err := LinkByName("foo")
377 if err != nil {
378 t.Fatal(err)
379 }
380 if err := LinkSetUp(link); err != nil {
381 t.Fatal(err)
382 }
383 redir, err := LinkByName("bar")
384 if err != nil {
385 t.Fatal(err)
386 }
387 if err := LinkSetUp(redir); err != nil {
388 t.Fatal(err)
389 }
390 attrs := QdiscAttrs{
391 LinkIndex: link.Attrs().Index,
392 Handle: MakeHandle(0xffff, 0),
393 Parent: HANDLE_ROOT,
394 }
395 qdisc := NewHtb(attrs)
396 if err := QdiscAdd(qdisc); err != nil {
397 t.Fatal(err)
398 }
399 qdiscs, err := SafeQdiscList(link)
400 if err != nil {
401 t.Fatal(err)
402 }
403 if len(qdiscs) != 1 {
404 t.Fatal("Failed to add qdisc")
405 }
406 _, ok := qdiscs[0].(*Htb)
407 if !ok {
408 t.Fatal("Qdisc is the wrong type")
409 }
410
411 classattrs := ClassAttrs{
412 LinkIndex: link.Attrs().Index,
413 Parent: MakeHandle(0xffff, 0),
414 Handle: MakeHandle(0xffff, 2),
415 }
416
417 htbclassattrs := HtbClassAttrs{
418 Rate: 1234000,
419 Cbuffer: 1690,
420 }
421 class := NewHtbClass(classattrs, htbclassattrs)
422 if err := ClassAdd(class); err != nil {
423 t.Fatal(err)
424 }
425 classes, err := SafeClassList(link, MakeHandle(0xffff, 2))
426 if err != nil {
427 t.Fatal(err)
428 }
429 if len(classes) != 1 {
430 t.Fatal("Failed to add class")
431 }
432
433 police := NewPoliceAction()
434 police.Burst = 12345
435 police.Rate = 1234
436 police.PeakRate = 2345
437 police.Action = TcAct(TC_POLICE_SHOT)
438
439 filterattrs := FilterAttrs{
440 LinkIndex: link.Attrs().Index,
441 Parent: MakeHandle(0xffff, 0),
442 Handle: MakeHandle(0, 0x6),
443 Priority: 1,
444 Protocol: unix.ETH_P_IP,
445 }
446
447 filter := FwFilter{
448 FilterAttrs: filterattrs,
449 ClassId: MakeHandle(0xffff, 2),
450 Police: police,
451 }
452
453 if err := FilterAdd(&filter); err != nil {
454 t.Fatal(err)
455 }
456
457 filters, err := FilterList(link, MakeHandle(0xffff, 0))
458 if err != nil {
459 t.Fatal(err)
460 }
461 if len(filters) != 1 {
462 t.Fatal("Failed to add filter")
463 }
464 fw, ok := filters[0].(*FwFilter)
465 if !ok {
466 t.Fatal("Filter is the wrong type")
467 }
468 if fw.Police.Rate != filter.Police.Rate {
469 t.Fatal("Police Rate doesn't match")
470 }
471 if fw.ClassId != filter.ClassId {
472 t.Fatal("ClassId doesn't match")
473 }
474 if fw.InDev != filter.InDev {
475 t.Fatal("InDev doesn't match")
476 }
477 if fw.Police.AvRate != filter.Police.AvRate {
478 t.Fatal("AvRate doesn't match")
479 }
480
481 if err := FilterDel(&filter); err != nil {
482 t.Fatal(err)
483 }
484 filters, err = FilterList(link, MakeHandle(0xffff, 0))
485 if err != nil {
486 t.Fatal(err)
487 }
488 if len(filters) != 0 {
489 t.Fatal("Failed to remove filter")
490 }
491 if err := ClassDel(class); err != nil {
492 t.Fatal(err)
493 }
494 classes, err = SafeClassList(link, MakeHandle(0xffff, 0))
495 if err != nil {
496 t.Fatal(err)
497 }
498 if len(classes) != 0 {
499 t.Fatal("Failed to remove class")
500 }
501
502 if err := QdiscDel(qdisc); err != nil {
503 t.Fatal(err)
504 }
505 qdiscs, err = SafeQdiscList(link)
506 if err != nil {
507 t.Fatal(err)
508 }
509 if len(qdiscs) != 0 {
510 t.Fatal("Failed to remove qdisc")
511 }
512 }
513
514 func TestFilterFwActAddDel(t *testing.T) {
515 tearDown := setUpNetlinkTest(t)
516 defer tearDown()
517 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
518 t.Fatal(err)
519 }
520 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
521 t.Fatal(err)
522 }
523 link, err := LinkByName("foo")
524 if err != nil {
525 t.Fatal(err)
526 }
527 if err := LinkSetUp(link); err != nil {
528 t.Fatal(err)
529 }
530 redir, err := LinkByName("bar")
531 if err != nil {
532 t.Fatal(err)
533 }
534 if err := LinkSetUp(redir); err != nil {
535 t.Fatal(err)
536 }
537 qdisc := &Ingress{
538 QdiscAttrs: QdiscAttrs{
539 LinkIndex: link.Attrs().Index,
540 Handle: MakeHandle(0xffff, 0),
541 Parent: HANDLE_INGRESS,
542 },
543 }
544 if err := QdiscAdd(qdisc); err != nil {
545 t.Fatal(err)
546 }
547 qdiscs, err := SafeQdiscList(link)
548 if err != nil {
549 t.Fatal(err)
550 }
551 if len(qdiscs) != 1 {
552 t.Fatal("Failed to add qdisc")
553 }
554 _, ok := qdiscs[0].(*Ingress)
555 if !ok {
556 t.Fatal("Qdisc is the wrong type")
557 }
558
559 classId := MakeHandle(1, 1)
560 filter := &FwFilter{
561 FilterAttrs: FilterAttrs{
562 LinkIndex: link.Attrs().Index,
563 Parent: MakeHandle(0xffff, 0),
564 Priority: 1,
565 Protocol: unix.ETH_P_ALL,
566 Handle: MakeHandle(0, 0x6),
567 },
568 ClassId: classId,
569 Actions: []Action{
570 &MirredAction{
571 ActionAttrs: ActionAttrs{
572 Action: TC_ACT_STOLEN,
573 },
574 MirredAction: TCA_EGRESS_REDIR,
575 Ifindex: redir.Attrs().Index,
576 },
577 },
578 }
579
580 if err := FilterAdd(filter); err != nil {
581 t.Fatal(err)
582 }
583
584 filters, err := FilterList(link, MakeHandle(0xffff, 0))
585 if err != nil {
586 t.Fatal(err)
587 }
588 if len(filters) != 1 {
589 t.Fatal("Failed to add filter")
590 }
591 fw, ok := filters[0].(*FwFilter)
592 if !ok {
593 t.Fatal("Filter is the wrong type")
594 }
595
596 if len(fw.Actions) != 1 {
597 t.Fatalf("Too few Actions in filter")
598 }
599 if fw.ClassId != classId {
600 t.Fatalf("ClassId of the filter is the wrong value")
601 }
602
603 mia, ok := fw.Actions[0].(*MirredAction)
604 if !ok {
605 t.Fatal("Unable to find mirred action")
606 }
607
608 if mia.Attrs().Action != TC_ACT_STOLEN {
609 t.Fatal("Mirred action isn't TC_ACT_STOLEN")
610 }
611
612 if mia.MirredAction != TCA_EGRESS_REDIR {
613 t.Fatal("MirredAction isn't TCA_EGRESS_REDIR")
614 }
615
616 if mia.Ifindex != redir.Attrs().Index {
617 t.Fatal("Unmatched redirect index")
618 }
619
620 if err := FilterDel(filter); err != nil {
621 t.Fatal(err)
622 }
623 filters, err = FilterList(link, MakeHandle(0xffff, 0))
624 if err != nil {
625 t.Fatal(err)
626 }
627 if len(filters) != 0 {
628 t.Fatal("Failed to remove filter")
629 }
630
631 if err := QdiscDel(qdisc); err != nil {
632 t.Fatal(err)
633 }
634 qdiscs, err = SafeQdiscList(link)
635 if err != nil {
636 t.Fatal(err)
637 }
638 if len(qdiscs) != 0 {
639 t.Fatal("Failed to remove qdisc")
640 }
641 }
642
643 func TestFilterU32BpfAddDel(t *testing.T) {
644 t.Skipf("Fd does not match in ci")
645 tearDown := setUpNetlinkTest(t)
646 defer tearDown()
647 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
648 t.Fatal(err)
649 }
650 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
651 t.Fatal(err)
652 }
653 link, err := LinkByName("foo")
654 if err != nil {
655 t.Fatal(err)
656 }
657 if err := LinkSetUp(link); err != nil {
658 t.Fatal(err)
659 }
660 redir, err := LinkByName("bar")
661 if err != nil {
662 t.Fatal(err)
663 }
664 if err := LinkSetUp(redir); err != nil {
665 t.Fatal(err)
666 }
667 qdisc := &Ingress{
668 QdiscAttrs: QdiscAttrs{
669 LinkIndex: link.Attrs().Index,
670 Handle: MakeHandle(0xffff, 0),
671 Parent: HANDLE_INGRESS,
672 },
673 }
674 if err := QdiscAdd(qdisc); err != nil {
675 t.Fatal(err)
676 }
677 qdiscs, err := SafeQdiscList(link)
678 if err != nil {
679 t.Fatal(err)
680 }
681 if len(qdiscs) != 1 {
682 t.Fatal("Failed to add qdisc")
683 }
684 _, ok := qdiscs[0].(*Ingress)
685 if !ok {
686 t.Fatal("Qdisc is the wrong type")
687 }
688
689 fd, err := loadSimpleBpf(BPF_PROG_TYPE_SCHED_ACT, 1)
690 if err != nil {
691 t.Skipf("Loading bpf program failed: %s", err)
692 }
693 classId := MakeHandle(1, 1)
694 filter := &U32{
695 FilterAttrs: FilterAttrs{
696 LinkIndex: link.Attrs().Index,
697 Parent: MakeHandle(0xffff, 0),
698 Priority: 1,
699 Protocol: unix.ETH_P_ALL,
700 },
701 ClassId: classId,
702 Actions: []Action{
703 &BpfAction{Fd: fd, Name: "simple"},
704 &MirredAction{
705 ActionAttrs: ActionAttrs{
706 Action: TC_ACT_STOLEN,
707 },
708 MirredAction: TCA_EGRESS_REDIR,
709 Ifindex: redir.Attrs().Index,
710 },
711 },
712 }
713
714 if err := FilterAdd(filter); err != nil {
715 t.Fatal(err)
716 }
717
718 filters, err := FilterList(link, MakeHandle(0xffff, 0))
719 if err != nil {
720 t.Fatal(err)
721 }
722 if len(filters) != 1 {
723 t.Fatal("Failed to add filter")
724 }
725 u32, ok := filters[0].(*U32)
726 if !ok {
727 t.Fatal("Filter is the wrong type")
728 }
729
730 if len(u32.Actions) != 2 {
731 t.Fatalf("Too few Actions in filter")
732 }
733 if u32.ClassId != classId {
734 t.Fatalf("ClassId of the filter is the wrong value")
735 }
736
737
738 bpfAction, ok := u32.Actions[0].(*BpfAction)
739 if !ok {
740 bpfAction, ok = u32.Actions[1].(*BpfAction)
741 if !ok {
742 t.Fatal("Action is the wrong type")
743 }
744 }
745 if bpfAction.Fd != fd {
746 t.Fatalf("Action Fd does not match %d != %d", bpfAction.Fd, fd)
747 }
748 if _, ok := u32.Actions[0].(*MirredAction); !ok {
749 if _, ok := u32.Actions[1].(*MirredAction); !ok {
750 t.Fatal("Action is the wrong type")
751 }
752 }
753
754 if err := FilterDel(filter); err != nil {
755 t.Fatal(err)
756 }
757 filters, err = FilterList(link, MakeHandle(0xffff, 0))
758 if err != nil {
759 t.Fatal(err)
760 }
761 if len(filters) != 0 {
762 t.Fatal("Failed to remove filter")
763 }
764
765 if err := QdiscDel(qdisc); err != nil {
766 t.Fatal(err)
767 }
768 qdiscs, err = SafeQdiscList(link)
769 if err != nil {
770 t.Fatal(err)
771 }
772 if len(qdiscs) != 0 {
773 t.Fatal("Failed to remove qdisc")
774 }
775 }
776
777 func TestFilterU32ConnmarkAddDel(t *testing.T) {
778 tearDown := setUpNetlinkTest(t)
779 defer tearDown()
780 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
781 t.Fatal(err)
782 }
783 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
784 t.Fatal(err)
785 }
786 link, err := LinkByName("foo")
787 if err != nil {
788 t.Fatal(err)
789 }
790 if err := LinkSetUp(link); err != nil {
791 t.Fatal(err)
792 }
793 redir, err := LinkByName("bar")
794 if err != nil {
795 t.Fatal(err)
796 }
797 if err := LinkSetUp(redir); err != nil {
798 t.Fatal(err)
799 }
800 qdisc := &Ingress{
801 QdiscAttrs: QdiscAttrs{
802 LinkIndex: link.Attrs().Index,
803 Handle: MakeHandle(0xffff, 0),
804 Parent: HANDLE_INGRESS,
805 },
806 }
807 if err := QdiscAdd(qdisc); err != nil {
808 t.Fatal(err)
809 }
810 qdiscs, err := SafeQdiscList(link)
811 if err != nil {
812 t.Fatal(err)
813 }
814 if len(qdiscs) != 1 {
815 t.Fatal("Failed to add qdisc")
816 }
817 _, ok := qdiscs[0].(*Ingress)
818 if !ok {
819 t.Fatal("Qdisc is the wrong type")
820 }
821
822 classId := MakeHandle(1, 1)
823 filter := &U32{
824 FilterAttrs: FilterAttrs{
825 LinkIndex: link.Attrs().Index,
826 Parent: MakeHandle(0xffff, 0),
827 Priority: 1,
828 Protocol: unix.ETH_P_ALL,
829 },
830 ClassId: classId,
831 Actions: []Action{
832 &ConnmarkAction{
833 ActionAttrs: ActionAttrs{
834 Action: TC_ACT_PIPE,
835 },
836 },
837 &MirredAction{
838 ActionAttrs: ActionAttrs{
839 Action: TC_ACT_STOLEN,
840 },
841 MirredAction: TCA_EGRESS_REDIR,
842 Ifindex: redir.Attrs().Index,
843 },
844 },
845 }
846
847 if err := FilterAdd(filter); err != nil {
848 t.Fatal(err)
849 }
850
851 filters, err := FilterList(link, MakeHandle(0xffff, 0))
852 if err != nil {
853 t.Fatal(err)
854 }
855 if len(filters) != 1 {
856 t.Fatal("Failed to add filter")
857 }
858 u32, ok := filters[0].(*U32)
859 if !ok {
860 t.Fatal("Filter is the wrong type")
861 }
862
863 if len(u32.Actions) != 2 {
864 t.Fatalf("Too few Actions in filter")
865 }
866 if u32.ClassId != classId {
867 t.Fatalf("ClassId of the filter is the wrong value")
868 }
869
870
871 cma, ok := u32.Actions[0].(*ConnmarkAction)
872 if !ok {
873 cma, ok = u32.Actions[1].(*ConnmarkAction)
874 if !ok {
875 t.Fatal("Unable to find connmark action")
876 }
877 }
878
879 if cma.Attrs().Action != TC_ACT_PIPE {
880 t.Fatal("Connmark action isn't TC_ACT_PIPE")
881 }
882
883 mia, ok := u32.Actions[0].(*MirredAction)
884 if !ok {
885 mia, ok = u32.Actions[1].(*MirredAction)
886 if !ok {
887 t.Fatal("Unable to find mirred action")
888 }
889 }
890
891 if mia.Attrs().Action != TC_ACT_STOLEN {
892 t.Fatal("Mirred action isn't TC_ACT_STOLEN")
893 }
894
895 if err := FilterDel(filter); err != nil {
896 t.Fatal(err)
897 }
898 filters, err = FilterList(link, MakeHandle(0xffff, 0))
899 if err != nil {
900 t.Fatal(err)
901 }
902 if len(filters) != 0 {
903 t.Fatal("Failed to remove filter")
904 }
905
906 if err := QdiscDel(qdisc); err != nil {
907 t.Fatal(err)
908 }
909 qdiscs, err = SafeQdiscList(link)
910 if err != nil {
911 t.Fatal(err)
912 }
913 if len(qdiscs) != 0 {
914 t.Fatal("Failed to remove qdisc")
915 }
916 }
917
918 func TestFilterU32CsumAddDel(t *testing.T) {
919 tearDown := setUpNetlinkTest(t)
920 defer tearDown()
921 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
922 t.Fatalf("add link foo error: %v", err)
923 }
924 link, err := LinkByName("foo")
925 if err != nil {
926 t.Fatalf("add link foo error: %v", err)
927 }
928 if err := LinkSetUp(link); err != nil {
929 t.Fatalf("set foo link up error: %v", err)
930 }
931
932 qdisc := &Ingress{
933 QdiscAttrs: QdiscAttrs{
934 LinkIndex: link.Attrs().Index,
935 Handle: MakeHandle(0xffff, 0),
936 Parent: HANDLE_INGRESS,
937 },
938 }
939 if err := QdiscAdd(qdisc); err != nil {
940 t.Fatal(err)
941 }
942 qdiscs, err := SafeQdiscList(link)
943 if err != nil {
944 t.Fatalf("get qdisc error: %v", err)
945 }
946
947 found := false
948 for _, v := range qdiscs {
949 if _, ok := v.(*Ingress); ok {
950 found = true
951 break
952 }
953 }
954 if !found {
955 t.Fatal("Qdisc is the wrong type")
956 }
957
958 classId := MakeHandle(1, 1)
959 filter := &U32{
960 FilterAttrs: FilterAttrs{
961 LinkIndex: link.Attrs().Index,
962 Parent: MakeHandle(0xffff, 0),
963 Priority: 1,
964 Protocol: unix.ETH_P_ALL,
965 },
966 ClassId: classId,
967 Actions: []Action{
968 &CsumAction{
969 ActionAttrs: ActionAttrs{
970 Action: TC_ACT_PIPE,
971 },
972 UpdateFlags: TCA_CSUM_UPDATE_FLAG_TCP,
973 },
974 },
975 }
976
977 if err := FilterAdd(filter); err != nil {
978 t.Fatal(err)
979 }
980
981 filters, err := FilterList(link, MakeHandle(0xffff, 0))
982 if err != nil {
983 t.Fatalf("get filter error: %v", err)
984 }
985
986 if len(filters) != 1 {
987 t.Fatalf("the count filters error, expect: 1, acutal: %d", len(filters))
988 }
989
990 ft, ok := filters[0].(*U32)
991 if !ok {
992 t.Fatal("Filter is the wrong type")
993 }
994
995 if ft.LinkIndex != link.Attrs().Index {
996 t.Fatal("link index error")
997 }
998
999 if len(ft.Actions) != 1 {
1000 t.Fatalf("filter has wrong number of actions, expect: 1, acutal: %d", len(filters))
1001 }
1002
1003 csum, ok := ft.Actions[0].(*CsumAction)
1004 if !ok {
1005 t.Fatal("action is the wrong type")
1006 }
1007
1008 if csum.Attrs().Action != TC_ACT_PIPE {
1009 t.Fatal("Csum action isn't TC_ACT_PIPE")
1010 }
1011
1012 if csum.UpdateFlags != TCA_CSUM_UPDATE_FLAG_TCP {
1013 t.Fatalf("Csum action isn't TCA_CSUM_UPDATE_FLAG_TCP, got %d", csum.UpdateFlags)
1014 }
1015
1016 if err := FilterDel(ft); err != nil {
1017 t.Fatal(err)
1018 }
1019 filters, err = FilterList(link, MakeHandle(0xffff, 0))
1020 if err != nil {
1021 t.Fatal(err)
1022 }
1023 if len(filters) != 0 {
1024 t.Fatal("Failed to remove filter")
1025 }
1026
1027 if err := QdiscDel(qdisc); err != nil {
1028 t.Fatal(err)
1029 }
1030 qdiscs, err = SafeQdiscList(link)
1031 if err != nil {
1032 t.Fatal(err)
1033 }
1034
1035 found = false
1036 for _, v := range qdiscs {
1037 if _, ok := v.(*Ingress); ok {
1038 found = true
1039 break
1040 }
1041 }
1042 if found {
1043 t.Fatal("Failed to remove qdisc")
1044 }
1045 }
1046
1047 func setupLinkForTestWithQdisc(t *testing.T, linkName string) (Qdisc, Link) {
1048 if err := LinkAdd(&Ifb{LinkAttrs{Name: linkName}}); err != nil {
1049 t.Fatal(err)
1050 }
1051 link, err := LinkByName(linkName)
1052 if err != nil {
1053 t.Fatal(err)
1054 }
1055 if err := LinkSetUp(link); err != nil {
1056 t.Fatal(err)
1057 }
1058 qdisc := &Clsact{
1059 QdiscAttrs: QdiscAttrs{
1060 LinkIndex: link.Attrs().Index,
1061 Handle: MakeHandle(0xffff, 0),
1062 Parent: HANDLE_CLSACT,
1063 },
1064 }
1065
1066 if err := QdiscAdd(qdisc); err != nil {
1067 t.Fatal(err)
1068 }
1069 qdiscs, err := SafeQdiscList(link)
1070 if err != nil {
1071 t.Fatal(err)
1072 }
1073 if len(qdiscs) != 1 {
1074 t.Fatal("Failed to add qdisc", len(qdiscs))
1075 }
1076 if q, ok := qdiscs[0].(*Clsact); !ok || q.Type() != "clsact" {
1077 t.Fatal("qdisc is the wrong type")
1078 }
1079 return qdiscs[0], link
1080 }
1081
1082 func TestFilterClsActBpfAddDel(t *testing.T) {
1083 t.Skipf("Fd does not match in ci")
1084
1085 minKernelRequired(t, 4, 5)
1086
1087 tearDown := setUpNetlinkTest(t)
1088 defer tearDown()
1089
1090 qdisc, link := setupLinkForTestWithQdisc(t, "foo")
1091 filterattrs := FilterAttrs{
1092 LinkIndex: link.Attrs().Index,
1093 Parent: HANDLE_MIN_EGRESS,
1094 Handle: MakeHandle(0, 1),
1095 Protocol: unix.ETH_P_ALL,
1096 Priority: 1,
1097 }
1098 fd, err := loadSimpleBpf(BPF_PROG_TYPE_SCHED_CLS, 1)
1099 if err != nil {
1100 t.Skipf("Loading bpf program failed: %s", err)
1101 }
1102 filter := &BpfFilter{
1103 FilterAttrs: filterattrs,
1104 Fd: fd,
1105 Name: "simple",
1106 DirectAction: true,
1107 }
1108 if filter.Fd < 0 {
1109 t.Skipf("Failed to load bpf program")
1110 }
1111
1112 if err := FilterAdd(filter); err != nil {
1113 t.Fatal(err)
1114 }
1115
1116 filters, err := FilterList(link, HANDLE_MIN_EGRESS)
1117 if err != nil {
1118 t.Fatal(err)
1119 }
1120 if len(filters) != 1 {
1121 t.Fatal("Failed to add filter")
1122 }
1123 bpf, ok := filters[0].(*BpfFilter)
1124 if !ok {
1125 t.Fatal("Filter is the wrong type")
1126 }
1127
1128 if bpf.Fd != filter.Fd {
1129 t.Fatal("Filter Fd does not match")
1130 }
1131 if bpf.DirectAction != filter.DirectAction {
1132 t.Fatal("Filter DirectAction does not match")
1133 }
1134
1135 if err := FilterDel(filter); err != nil {
1136 t.Fatal(err)
1137 }
1138 filters, err = FilterList(link, HANDLE_MIN_EGRESS)
1139 if err != nil {
1140 t.Fatal(err)
1141 }
1142 if len(filters) != 0 {
1143 t.Fatal("Failed to remove filter")
1144 }
1145
1146 if err := QdiscDel(qdisc); err != nil {
1147 t.Fatal(err)
1148 }
1149 qdiscs, err := SafeQdiscList(link)
1150 if err != nil {
1151 t.Fatal(err)
1152 }
1153 if len(qdiscs) != 0 {
1154 t.Fatal("Failed to remove qdisc")
1155 }
1156 }
1157
1158 func TestFilterMatchAllAddDel(t *testing.T) {
1159
1160 minKernelRequired(t, 4, 7)
1161
1162 tearDown := setUpNetlinkTest(t)
1163 defer tearDown()
1164 _, link := setupLinkForTestWithQdisc(t, "foo")
1165 _, link2 := setupLinkForTestWithQdisc(t, "bar")
1166 filter := &MatchAll{
1167 FilterAttrs: FilterAttrs{
1168 LinkIndex: link.Attrs().Index,
1169 Parent: HANDLE_MIN_EGRESS,
1170 Priority: 32000,
1171 Protocol: unix.ETH_P_ALL,
1172 },
1173 Actions: []Action{
1174 &MirredAction{
1175 ActionAttrs: ActionAttrs{
1176 Action: TC_ACT_STOLEN,
1177 },
1178 MirredAction: TCA_EGRESS_REDIR,
1179 Ifindex: link2.Attrs().Index,
1180 },
1181 },
1182 }
1183 if err := FilterAdd(filter); err != nil {
1184 t.Fatal(err)
1185 }
1186
1187 filters, err := FilterList(link, HANDLE_MIN_EGRESS)
1188 if err != nil {
1189 t.Fatal(err)
1190 }
1191 if len(filters) != 1 {
1192 t.Fatal("Failed to add filter")
1193 }
1194 matchall, ok := filters[0].(*MatchAll)
1195 if !ok {
1196 t.Fatal("Filter is the wrong type")
1197 }
1198
1199 if matchall.Priority != 32000 {
1200 t.Fatal("Filter priority does not match")
1201 }
1202
1203 if len(matchall.Actions) != 1 {
1204 t.Fatal("Filter has no actions")
1205 }
1206
1207 mirredAction, ok := matchall.Actions[0].(*MirredAction)
1208 if !ok {
1209 t.Fatal("Action does not match")
1210 }
1211
1212 if mirredAction.Ifindex != link2.Attrs().Index {
1213 t.Fatal("Action ifindex does not match")
1214 }
1215
1216 if err := FilterDel(filter); err != nil {
1217 t.Fatal(err)
1218 }
1219 filters, err = FilterList(link, HANDLE_MIN_EGRESS)
1220 if err != nil {
1221 t.Fatal(err)
1222 }
1223 if len(filters) != 0 {
1224 t.Fatal("Failed to remove filter")
1225 }
1226
1227 }
1228
1229 func TestFilterU32TunnelKeyAddDel(t *testing.T) {
1230 tearDown := setUpNetlinkTest(t)
1231 defer tearDown()
1232 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
1233 t.Fatal(err)
1234 }
1235 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
1236 t.Fatal(err)
1237 }
1238 link, err := LinkByName("foo")
1239 if err != nil {
1240 t.Fatal(err)
1241 }
1242 if err := LinkSetUp(link); err != nil {
1243 t.Fatal(err)
1244 }
1245 redir, err := LinkByName("bar")
1246 if err != nil {
1247 t.Fatal(err)
1248 }
1249 if err := LinkSetUp(redir); err != nil {
1250 t.Fatal(err)
1251 }
1252
1253 qdisc := &Ingress{
1254 QdiscAttrs: QdiscAttrs{
1255 LinkIndex: link.Attrs().Index,
1256 Handle: MakeHandle(0xffff, 0),
1257 Parent: HANDLE_INGRESS,
1258 },
1259 }
1260 if err := QdiscAdd(qdisc); err != nil {
1261 t.Fatal(err)
1262 }
1263 qdiscs, err := SafeQdiscList(link)
1264 if err != nil {
1265 t.Fatal(err)
1266 }
1267
1268 found := false
1269 for _, v := range qdiscs {
1270 if _, ok := v.(*Ingress); ok {
1271 found = true
1272 break
1273 }
1274 }
1275 if !found {
1276 t.Fatal("Qdisc is the wrong type")
1277 }
1278
1279 tunnelAct := NewTunnelKeyAction()
1280 tunnelAct.SrcAddr = net.IPv4(10, 10, 10, 1)
1281 tunnelAct.DstAddr = net.IPv4(10, 10, 10, 2)
1282 tunnelAct.KeyID = 0x01
1283 tunnelAct.Action = TCA_TUNNEL_KEY_SET
1284 tunnelAct.DestPort = 8472
1285
1286 classId := MakeHandle(1, 1)
1287 filter := &U32{
1288 FilterAttrs: FilterAttrs{
1289 LinkIndex: link.Attrs().Index,
1290 Parent: MakeHandle(0xffff, 0),
1291 Priority: 1,
1292 Protocol: unix.ETH_P_ALL,
1293 },
1294 ClassId: classId,
1295 Actions: []Action{
1296 tunnelAct,
1297 &MirredAction{
1298 ActionAttrs: ActionAttrs{
1299 Action: TC_ACT_STOLEN,
1300 },
1301 MirredAction: TCA_EGRESS_REDIR,
1302 Ifindex: redir.Attrs().Index,
1303 },
1304 },
1305 }
1306
1307 if err := FilterAdd(filter); err != nil {
1308 t.Fatal(err)
1309 }
1310
1311 filters, err := FilterList(link, MakeHandle(0xffff, 0))
1312 if err != nil {
1313 t.Fatal(err)
1314 }
1315 if len(filters) != 1 {
1316 t.Fatal("Failed to add filter")
1317 }
1318 u32, ok := filters[0].(*U32)
1319 if !ok {
1320 t.Fatal("Filter is the wrong type")
1321 }
1322
1323 if len(u32.Actions) != 2 {
1324 t.Fatalf("Too few Actions in filter")
1325 }
1326 if u32.ClassId != classId {
1327 t.Fatalf("ClassId of the filter is the wrong value")
1328 }
1329
1330
1331 tun, ok := u32.Actions[0].(*TunnelKeyAction)
1332 if !ok {
1333 tun, ok = u32.Actions[1].(*TunnelKeyAction)
1334 if !ok {
1335 t.Fatal("Unable to find tunnel action")
1336 }
1337 }
1338
1339 if tun.Attrs().Action != TC_ACT_PIPE {
1340 t.Fatal("TunnelKey action isn't TC_ACT_PIPE")
1341 }
1342 if !tun.SrcAddr.Equal(tunnelAct.SrcAddr) {
1343 t.Fatal("Action SrcAddr doesn't match")
1344 }
1345 if !tun.DstAddr.Equal(tunnelAct.DstAddr) {
1346 t.Fatal("Action DstAddr doesn't match")
1347 }
1348 if tun.KeyID != tunnelAct.KeyID {
1349 t.Fatal("Action KeyID doesn't match")
1350 }
1351 if tun.DestPort != tunnelAct.DestPort {
1352 t.Fatal("Action DestPort doesn't match")
1353 }
1354 if tun.Action != tunnelAct.Action {
1355 t.Fatal("Action doesn't match")
1356 }
1357
1358 mia, ok := u32.Actions[0].(*MirredAction)
1359 if !ok {
1360 mia, ok = u32.Actions[1].(*MirredAction)
1361 if !ok {
1362 t.Fatal("Unable to find mirred action")
1363 }
1364 }
1365
1366 if mia.Attrs().Action != TC_ACT_STOLEN {
1367 t.Fatal("Mirred action isn't TC_ACT_STOLEN")
1368 }
1369
1370 if err := FilterDel(filter); err != nil {
1371 t.Fatal(err)
1372 }
1373 filters, err = FilterList(link, MakeHandle(0xffff, 0))
1374 if err != nil {
1375 t.Fatal(err)
1376 }
1377 if len(filters) != 0 {
1378 t.Fatal("Failed to remove filter")
1379 }
1380
1381 if err := QdiscDel(qdisc); err != nil {
1382 t.Fatal(err)
1383 }
1384 qdiscs, err = SafeQdiscList(link)
1385 if err != nil {
1386 t.Fatal(err)
1387 }
1388
1389 found = false
1390 for _, v := range qdiscs {
1391 if _, ok := v.(*Ingress); ok {
1392 found = true
1393 break
1394 }
1395 }
1396 if found {
1397 t.Fatal("Failed to remove qdisc")
1398 }
1399 }
1400
1401 func TestFilterU32SkbEditAddDel(t *testing.T) {
1402 tearDown := setUpNetlinkTest(t)
1403 defer tearDown()
1404 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
1405 t.Fatal(err)
1406 }
1407 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
1408 t.Fatal(err)
1409 }
1410 link, err := LinkByName("foo")
1411 if err != nil {
1412 t.Fatal(err)
1413 }
1414 if err := LinkSetUp(link); err != nil {
1415 t.Fatal(err)
1416 }
1417 redir, err := LinkByName("bar")
1418 if err != nil {
1419 t.Fatal(err)
1420 }
1421 if err := LinkSetUp(redir); err != nil {
1422 t.Fatal(err)
1423 }
1424
1425 qdisc := &Ingress{
1426 QdiscAttrs: QdiscAttrs{
1427 LinkIndex: link.Attrs().Index,
1428 Handle: MakeHandle(0xffff, 0),
1429 Parent: HANDLE_INGRESS,
1430 },
1431 }
1432 if err := QdiscAdd(qdisc); err != nil {
1433 t.Fatal(err)
1434 }
1435 qdiscs, err := SafeQdiscList(link)
1436 if err != nil {
1437 t.Fatal(err)
1438 }
1439
1440 found := false
1441 for _, v := range qdiscs {
1442 if _, ok := v.(*Ingress); ok {
1443 found = true
1444 break
1445 }
1446 }
1447 if !found {
1448 t.Fatal("Qdisc is the wrong type")
1449 }
1450
1451 skbedit := NewSkbEditAction()
1452 ptype := uint16(unix.PACKET_HOST)
1453 skbedit.PType = &ptype
1454 priority := uint32(0xff)
1455 skbedit.Priority = &priority
1456 mark := uint32(0xfe)
1457 skbedit.Mark = &mark
1458 mask := uint32(0xff)
1459 skbedit.Mask = &mask
1460 mapping := uint16(0xf)
1461 skbedit.QueueMapping = &mapping
1462
1463 classId := MakeHandle(1, 1)
1464 filter := &U32{
1465 FilterAttrs: FilterAttrs{
1466 LinkIndex: link.Attrs().Index,
1467 Parent: MakeHandle(0xffff, 0),
1468 Priority: 1,
1469 Protocol: unix.ETH_P_ALL,
1470 },
1471 ClassId: classId,
1472 Actions: []Action{
1473 skbedit,
1474 &MirredAction{
1475 ActionAttrs: ActionAttrs{
1476 Action: TC_ACT_STOLEN,
1477 },
1478 MirredAction: TCA_EGRESS_REDIR,
1479 Ifindex: redir.Attrs().Index,
1480 },
1481 },
1482 }
1483
1484 if err := FilterAdd(filter); err != nil {
1485 t.Fatal(err)
1486 }
1487
1488 filters, err := FilterList(link, MakeHandle(0xffff, 0))
1489 if err != nil {
1490 t.Fatal(err)
1491 }
1492 if len(filters) != 1 {
1493 t.Fatal("Failed to add filter")
1494 }
1495 u32, ok := filters[0].(*U32)
1496 if !ok {
1497 t.Fatal("Filter is the wrong type")
1498 }
1499
1500 if len(u32.Actions) != 2 {
1501 t.Fatalf("Too few Actions in filter")
1502 }
1503 if u32.ClassId != classId {
1504 t.Fatalf("ClassId of the filter is the wrong value")
1505 }
1506
1507
1508 edit, ok := u32.Actions[0].(*SkbEditAction)
1509 if !ok {
1510 edit, ok = u32.Actions[1].(*SkbEditAction)
1511 if !ok {
1512 t.Fatal("Unable to find tunnel action")
1513 }
1514 }
1515
1516 if edit.Attrs().Action != TC_ACT_PIPE {
1517 t.Fatal("SkbEdit action isn't TC_ACT_PIPE")
1518 }
1519 if edit.PType == nil || *edit.PType != *skbedit.PType {
1520 t.Fatal("Action PType doesn't match")
1521 }
1522 if edit.QueueMapping == nil || *edit.QueueMapping != *skbedit.QueueMapping {
1523 t.Fatal("Action QueueMapping doesn't match")
1524 }
1525 if edit.Mark == nil || *edit.Mark != *skbedit.Mark {
1526 t.Fatal("Action Mark doesn't match")
1527 }
1528 if edit.Mask == nil || *edit.Mask != *skbedit.Mask {
1529 t.Fatal("Action Mask doesn't match")
1530 }
1531 if edit.Priority == nil || *edit.Priority != *skbedit.Priority {
1532 t.Fatal("Action Priority doesn't match")
1533 }
1534
1535 mia, ok := u32.Actions[0].(*MirredAction)
1536 if !ok {
1537 mia, ok = u32.Actions[1].(*MirredAction)
1538 if !ok {
1539 t.Fatal("Unable to find mirred action")
1540 }
1541 }
1542
1543 if mia.Attrs().Action != TC_ACT_STOLEN {
1544 t.Fatal("Mirred action isn't TC_ACT_STOLEN")
1545 }
1546
1547 if err := FilterDel(filter); err != nil {
1548 t.Fatal(err)
1549 }
1550 filters, err = FilterList(link, MakeHandle(0xffff, 0))
1551 if err != nil {
1552 t.Fatal(err)
1553 }
1554 if len(filters) != 0 {
1555 t.Fatal("Failed to remove filter")
1556 }
1557
1558 if err := QdiscDel(qdisc); err != nil {
1559 t.Fatal(err)
1560 }
1561 qdiscs, err = SafeQdiscList(link)
1562 if err != nil {
1563 t.Fatal(err)
1564 }
1565
1566 found = false
1567 for _, v := range qdiscs {
1568 if _, ok := v.(*Ingress); ok {
1569 found = true
1570 break
1571 }
1572 }
1573 if found {
1574 t.Fatal("Failed to remove qdisc")
1575 }
1576 }
1577
1578 func TestFilterU32LinkOption(t *testing.T) {
1579 tearDown := setUpNetlinkTest(t)
1580 defer tearDown()
1581 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
1582 t.Fatalf("add link foo error: %v", err)
1583 }
1584 link, err := LinkByName("foo")
1585 if err != nil {
1586 t.Fatalf("add link foo error: %v", err)
1587 }
1588 if err := LinkSetUp(link); err != nil {
1589 t.Fatalf("set foo link up error: %v", err)
1590 }
1591
1592 qdisc := &Ingress{
1593 QdiscAttrs: QdiscAttrs{
1594 LinkIndex: link.Attrs().Index,
1595 Handle: MakeHandle(0xffff, 0),
1596 Parent: HANDLE_INGRESS,
1597 },
1598 }
1599 if err := QdiscAdd(qdisc); err != nil {
1600 t.Fatal(err)
1601 }
1602 qdiscs, err := SafeQdiscList(link)
1603 if err != nil {
1604 t.Fatalf("get qdisc error: %v", err)
1605 }
1606
1607 found := false
1608 for _, v := range qdiscs {
1609 if _, ok := v.(*Ingress); ok {
1610 found = true
1611 break
1612 }
1613 }
1614 if !found {
1615 t.Fatal("Qdisc is the wrong type")
1616 }
1617
1618 htid := uint32(10)
1619 size := uint32(8)
1620 priority := uint16(200)
1621 u32Table := &U32{
1622 FilterAttrs: FilterAttrs{
1623 LinkIndex: link.Attrs().Index,
1624 Handle: htid << 20,
1625 Parent: MakeHandle(0xffff, 0),
1626 Priority: priority,
1627 Protocol: unix.ETH_P_ALL,
1628 },
1629 Divisor: size,
1630 }
1631 if err := FilterAdd(u32Table); err != nil {
1632 t.Fatal(err)
1633 }
1634
1635 u32 := &U32{
1636 FilterAttrs: FilterAttrs{
1637 LinkIndex: link.Attrs().Index,
1638 Parent: MakeHandle(0xffff, 0),
1639 Handle: 1,
1640 Priority: priority,
1641 Protocol: unix.ETH_P_ALL,
1642 },
1643 Link: uint32(htid << 20),
1644 Sel: &TcU32Sel{
1645 Nkeys: 1,
1646 Flags: TC_U32_TERMINAL | TC_U32_VAROFFSET,
1647 Hmask: 0x0000ff00,
1648 Hoff: 0,
1649 Offshift: 8,
1650 Keys: []TcU32Key{
1651 {
1652 Mask: 0,
1653 Val: 0,
1654 Off: 0,
1655 },
1656 },
1657 },
1658 }
1659 if err := FilterAdd(u32); err != nil {
1660 t.Fatal(err)
1661 }
1662
1663 filters, err := FilterList(link, MakeHandle(0xffff, 0))
1664 if err != nil {
1665 t.Fatalf("get filter error: %v", err)
1666 }
1667
1668 if len(filters) != 1 {
1669 t.Fatalf("the count filters error, expect: 1, acutal: %d", len(filters))
1670 }
1671
1672 ft, ok := filters[0].(*U32)
1673 if !ok {
1674 t.Fatal("Filter is the wrong type")
1675 }
1676
1677 if ft.LinkIndex != link.Attrs().Index {
1678 t.Fatal("link index error")
1679 }
1680
1681 if ft.Link != htid<<20 {
1682 t.Fatal("hash table id error")
1683 }
1684
1685 if ft.Priority != priority {
1686 t.Fatal("priority error")
1687 }
1688
1689 if err := FilterDel(ft); err != nil {
1690 t.Fatal(err)
1691 }
1692 filters, err = FilterList(link, MakeHandle(0xffff, 0))
1693 if err != nil {
1694 t.Fatal(err)
1695 }
1696 if len(filters) != 0 {
1697 t.Fatal("Failed to remove filter")
1698 }
1699
1700 if err := QdiscDel(qdisc); err != nil {
1701 t.Fatal(err)
1702 }
1703 qdiscs, err = SafeQdiscList(link)
1704 if err != nil {
1705 t.Fatal(err)
1706 }
1707
1708 found = false
1709 for _, v := range qdiscs {
1710 if _, ok := v.(*Ingress); ok {
1711 found = true
1712 break
1713 }
1714 }
1715 if found {
1716 t.Fatal("Failed to remove qdisc")
1717 }
1718 }
1719
1720 func TestFilterFlowerAddDel(t *testing.T) {
1721 tearDown := setUpNetlinkTest(t)
1722 defer tearDown()
1723 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
1724 t.Fatal(err)
1725 }
1726 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
1727 t.Fatal(err)
1728 }
1729 link, err := LinkByName("foo")
1730 if err != nil {
1731 t.Fatal(err)
1732 }
1733 if err := LinkSetUp(link); err != nil {
1734 t.Fatal(err)
1735 }
1736 redir, err := LinkByName("bar")
1737 if err != nil {
1738 t.Fatal(err)
1739 }
1740 if err := LinkSetUp(redir); err != nil {
1741 t.Fatal(err)
1742 }
1743
1744 qdisc := &Ingress{
1745 QdiscAttrs: QdiscAttrs{
1746 LinkIndex: link.Attrs().Index,
1747 Handle: MakeHandle(0xffff, 0),
1748 Parent: HANDLE_INGRESS,
1749 },
1750 }
1751 if err := QdiscAdd(qdisc); err != nil {
1752 t.Fatal(err)
1753 }
1754 qdiscs, err := SafeQdiscList(link)
1755 if err != nil {
1756 t.Fatal(err)
1757 }
1758
1759 found := false
1760 for _, v := range qdiscs {
1761 if _, ok := v.(*Ingress); ok {
1762 found = true
1763 break
1764 }
1765 }
1766 if !found {
1767 t.Fatal("Qdisc is the wrong type")
1768 }
1769
1770 testMask := net.CIDRMask(24, 32)
1771
1772 ipproto := new(nl.IPProto)
1773 *ipproto = nl.IPPROTO_TCP
1774
1775 filter := &Flower{
1776 FilterAttrs: FilterAttrs{
1777 LinkIndex: link.Attrs().Index,
1778 Parent: MakeHandle(0xffff, 0),
1779 Priority: 1,
1780 Protocol: unix.ETH_P_ALL,
1781 },
1782 DestIP: net.ParseIP("1.0.0.1"),
1783 DestIPMask: testMask,
1784 SrcIP: net.ParseIP("2.0.0.1"),
1785 SrcIPMask: testMask,
1786 EthType: unix.ETH_P_IP,
1787 EncDestIP: net.ParseIP("3.0.0.1"),
1788 EncDestIPMask: testMask,
1789 EncSrcIP: net.ParseIP("4.0.0.1"),
1790 EncSrcIPMask: testMask,
1791 EncDestPort: 8472,
1792 EncKeyId: 1234,
1793 IPProto: ipproto,
1794 DestPort: 1111,
1795 SrcPort: 1111,
1796 Actions: []Action{
1797 &MirredAction{
1798 ActionAttrs: ActionAttrs{
1799 Action: TC_ACT_STOLEN,
1800 },
1801 MirredAction: TCA_EGRESS_REDIR,
1802 Ifindex: redir.Attrs().Index,
1803 },
1804 &GenericAction{
1805 ActionAttrs: ActionAttrs{
1806 Action: getTcActGotoChain(),
1807 },
1808 Chain: 20,
1809 },
1810 },
1811 }
1812
1813 if err := FilterAdd(filter); err != nil {
1814 t.Fatal(err)
1815 }
1816
1817 time.Sleep(time.Second)
1818 filters, err := FilterList(link, MakeHandle(0xffff, 0))
1819 if err != nil {
1820 t.Fatal(err)
1821 }
1822 if len(filters) != 1 {
1823 t.Fatal("Failed to add filter")
1824 }
1825 flower, ok := filters[0].(*Flower)
1826 if !ok {
1827 t.Fatal("Filter is the wrong type")
1828 }
1829
1830 if filter.EthType != flower.EthType {
1831 t.Fatalf("Flower EthType doesn't match")
1832 }
1833 if !filter.DestIP.Equal(flower.DestIP) {
1834 t.Fatalf("Flower DestIP doesn't match")
1835 }
1836 if !filter.SrcIP.Equal(flower.SrcIP) {
1837 t.Fatalf("Flower SrcIP doesn't match")
1838 }
1839
1840 if !reflect.DeepEqual(filter.DestIPMask, testMask) {
1841 t.Fatalf("Flower DestIPMask doesn't match")
1842 }
1843 if !reflect.DeepEqual(filter.SrcIPMask, testMask) {
1844 t.Fatalf("Flower SrcIPMask doesn't match")
1845 }
1846
1847 if !filter.EncDestIP.Equal(flower.EncDestIP) {
1848 t.Fatalf("Flower EncDestIP doesn't match")
1849 }
1850 if !filter.EncSrcIP.Equal(flower.EncSrcIP) {
1851 t.Fatalf("Flower EncSrcIP doesn't match")
1852 }
1853 if !reflect.DeepEqual(filter.EncDestIPMask, testMask) {
1854 t.Fatalf("Flower EncDestIPMask doesn't match")
1855 }
1856 if !reflect.DeepEqual(filter.EncSrcIPMask, testMask) {
1857 t.Fatalf("Flower EncSrcIPMask doesn't match")
1858 }
1859 if filter.EncKeyId != flower.EncKeyId {
1860 t.Fatalf("Flower EncKeyId doesn't match")
1861 }
1862 if filter.EncDestPort != flower.EncDestPort {
1863 t.Fatalf("Flower EncDestPort doesn't match")
1864 }
1865 if flower.IPProto == nil || *filter.IPProto != *flower.IPProto {
1866 t.Fatalf("Flower IPProto doesn't match")
1867 }
1868 if filter.DestPort != flower.DestPort {
1869 t.Fatalf("Flower DestPort doesn't match")
1870 }
1871 if filter.SrcPort != flower.SrcPort {
1872 t.Fatalf("Flower SrcPort doesn't match")
1873 }
1874
1875 mia, ok := flower.Actions[0].(*MirredAction)
1876 if !ok {
1877 t.Fatal("Unable to find mirred action")
1878 }
1879
1880 if mia.Attrs().Action != TC_ACT_STOLEN {
1881 t.Fatal("Mirred action isn't TC_ACT_STOLEN")
1882 }
1883
1884 if mia.Timestamp == nil || mia.Timestamp.Installed == 0 {
1885 t.Fatal("Incorrect mirred action timestamp")
1886 }
1887
1888 if mia.Statistics == nil {
1889 t.Fatal("Incorrect mirred action stats")
1890 }
1891
1892 ga, ok := flower.Actions[1].(*GenericAction)
1893 if !ok {
1894 t.Fatal("Unable to find generic action")
1895 }
1896
1897 if ga.Attrs().Action != getTcActGotoChain() {
1898 t.Fatal("Generic action isn't TC_ACT_GOTO_CHAIN")
1899 }
1900
1901 if ga.Timestamp == nil || ga.Timestamp.Installed == 0 {
1902 t.Fatal("Incorrect generic action timestamp")
1903 }
1904
1905 if ga.Statistics == nil {
1906 t.Fatal("Incorrect generic action stats")
1907 }
1908
1909 if err := FilterDel(filter); err != nil {
1910 t.Fatal(err)
1911 }
1912 filters, err = FilterList(link, MakeHandle(0xffff, 0))
1913 if err != nil {
1914 t.Fatal(err)
1915 }
1916 if len(filters) != 0 {
1917 t.Fatal("Failed to remove filter")
1918 }
1919
1920 if err := QdiscDel(qdisc); err != nil {
1921 t.Fatal(err)
1922 }
1923 qdiscs, err = SafeQdiscList(link)
1924 if err != nil {
1925 t.Fatal(err)
1926 }
1927
1928 found = false
1929 for _, v := range qdiscs {
1930 if _, ok := v.(*Ingress); ok {
1931 found = true
1932 break
1933 }
1934 }
1935 if found {
1936 t.Fatal("Failed to remove qdisc")
1937 }
1938 }
1939
1940 func TestFilterIPv6FlowerPedit(t *testing.T) {
1941 tearDown := setUpNetlinkTest(t)
1942 defer tearDown()
1943 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
1944 t.Fatal(err)
1945 }
1946 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
1947 t.Fatal(err)
1948 }
1949 link, err := LinkByName("foo")
1950 if err != nil {
1951 t.Fatal(err)
1952 }
1953 if err := LinkSetUp(link); err != nil {
1954 t.Fatal(err)
1955 }
1956 redir, err := LinkByName("bar")
1957 if err != nil {
1958 t.Fatal(err)
1959 }
1960 if err := LinkSetUp(redir); err != nil {
1961 t.Fatal(err)
1962 }
1963
1964 qdisc := &Ingress{
1965 QdiscAttrs: QdiscAttrs{
1966 LinkIndex: link.Attrs().Index,
1967 Handle: MakeHandle(0xffff, 0),
1968 Parent: HANDLE_INGRESS,
1969 },
1970 }
1971 if err := QdiscAdd(qdisc); err != nil {
1972 t.Fatal(err)
1973 }
1974 qdiscs, err := SafeQdiscList(link)
1975 if err != nil {
1976 t.Fatal(err)
1977 }
1978
1979 found := false
1980 for _, v := range qdiscs {
1981 if _, ok := v.(*Ingress); ok {
1982 found = true
1983 break
1984 }
1985 }
1986 if !found {
1987 t.Fatal("Qdisc is the wrong type")
1988 }
1989
1990 testMask := net.CIDRMask(64, 128)
1991
1992 ipproto := new(nl.IPProto)
1993 *ipproto = nl.IPPROTO_TCP
1994
1995 filter := &Flower{
1996 FilterAttrs: FilterAttrs{
1997 LinkIndex: link.Attrs().Index,
1998 Parent: MakeHandle(0xffff, 0),
1999 Priority: 1,
2000 Protocol: unix.ETH_P_ALL,
2001 },
2002 DestIP: net.ParseIP("ffff::fff1"),
2003 DestIPMask: testMask,
2004 EthType: unix.ETH_P_IPV6,
2005 IPProto: ipproto,
2006 DestPort: 6666,
2007 Actions: []Action{},
2008 }
2009
2010 peditAction := NewPeditAction()
2011 peditAction.Proto = uint8(nl.IPPROTO_TCP)
2012 peditAction.SrcPort = 7777
2013 peditAction.SrcIP = net.ParseIP("ffff::fff2")
2014 filter.Actions = append(filter.Actions, peditAction)
2015
2016 miaAction := &MirredAction{
2017 ActionAttrs: ActionAttrs{
2018 Action: TC_ACT_REDIRECT,
2019 },
2020 MirredAction: TCA_EGRESS_REDIR,
2021 Ifindex: redir.Attrs().Index,
2022 }
2023 filter.Actions = append(filter.Actions, miaAction)
2024
2025 if err := FilterAdd(filter); err != nil {
2026 t.Fatal(err)
2027 }
2028
2029 filters, err := FilterList(link, MakeHandle(0xffff, 0))
2030 if err != nil {
2031 t.Fatal(err)
2032 }
2033 if len(filters) != 1 {
2034 t.Fatal("Failed to add filter")
2035 }
2036 flower, ok := filters[0].(*Flower)
2037 if !ok {
2038 t.Fatal("Filter is the wrong type")
2039 }
2040
2041 if filter.EthType != flower.EthType {
2042 t.Fatalf("Flower EthType doesn't match")
2043 }
2044 if !filter.DestIP.Equal(flower.DestIP) {
2045 t.Fatalf("Flower DestIP doesn't match")
2046 }
2047
2048 if !reflect.DeepEqual(filter.DestIPMask, testMask) {
2049 t.Fatalf("Flower DestIPMask doesn't match")
2050 }
2051
2052 if flower.IPProto == nil || *filter.IPProto != *flower.IPProto {
2053 t.Fatalf("Flower IPProto doesn't match")
2054 }
2055 if filter.DestPort != flower.DestPort {
2056 t.Fatalf("Flower DestPort doesn't match")
2057 }
2058
2059 _, ok = flower.Actions[0].(*PeditAction)
2060 if !ok {
2061 t.Fatal("Unable to find pedit action")
2062 }
2063
2064 _, ok = flower.Actions[1].(*MirredAction)
2065 if !ok {
2066 t.Fatal("Unable to find mirred action")
2067 }
2068
2069 if err := FilterDel(filter); err != nil {
2070 t.Fatal(err)
2071 }
2072 filters, err = FilterList(link, MakeHandle(0xffff, 0))
2073 if err != nil {
2074 t.Fatal(err)
2075 }
2076 if len(filters) != 0 {
2077 t.Fatal("Failed to remove filter")
2078 }
2079
2080 if err := QdiscDel(qdisc); err != nil {
2081 t.Fatal(err)
2082 }
2083 qdiscs, err = SafeQdiscList(link)
2084 if err != nil {
2085 t.Fatal(err)
2086 }
2087
2088 found = false
2089 for _, v := range qdiscs {
2090 if _, ok := v.(*Ingress); ok {
2091 found = true
2092 break
2093 }
2094 }
2095 if found {
2096 t.Fatal("Failed to remove qdisc")
2097 }
2098 }
2099
2100 func TestFilterU32PoliceAddDel(t *testing.T) {
2101 tearDown := setUpNetlinkTest(t)
2102 defer tearDown()
2103 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
2104 t.Fatal(err)
2105 }
2106 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
2107 t.Fatal(err)
2108 }
2109 link, err := LinkByName("foo")
2110 if err != nil {
2111 t.Fatal(err)
2112 }
2113 if err := LinkSetUp(link); err != nil {
2114 t.Fatal(err)
2115 }
2116 redir, err := LinkByName("bar")
2117 if err != nil {
2118 t.Fatal(err)
2119 }
2120 if err := LinkSetUp(redir); err != nil {
2121 t.Fatal(err)
2122 }
2123
2124 qdisc := &Ingress{
2125 QdiscAttrs: QdiscAttrs{
2126 LinkIndex: link.Attrs().Index,
2127 Handle: MakeHandle(0xffff, 0),
2128 Parent: HANDLE_INGRESS,
2129 },
2130 }
2131 if err := QdiscAdd(qdisc); err != nil {
2132 t.Fatal(err)
2133 }
2134 qdiscs, err := SafeQdiscList(link)
2135 if err != nil {
2136 t.Fatal(err)
2137 }
2138
2139 found := false
2140 for _, v := range qdiscs {
2141 if _, ok := v.(*Ingress); ok {
2142 found = true
2143 break
2144 }
2145 }
2146 if !found {
2147 t.Fatal("Qdisc is the wrong type")
2148 }
2149
2150 const (
2151 policeRate = 0x40000000
2152 policeBurst = 0x19000
2153 policePeakRate = 0x4000
2154 )
2155
2156 police := NewPoliceAction()
2157 police.Rate = policeRate
2158 police.PeakRate = policePeakRate
2159 police.Burst = policeBurst
2160 police.ExceedAction = TC_POLICE_SHOT
2161 police.NotExceedAction = TC_POLICE_UNSPEC
2162
2163 classId := MakeHandle(1, 1)
2164 filter := &U32{
2165 FilterAttrs: FilterAttrs{
2166 LinkIndex: link.Attrs().Index,
2167 Parent: MakeHandle(0xffff, 0),
2168 Priority: 1,
2169 Protocol: unix.ETH_P_ALL,
2170 },
2171 ClassId: classId,
2172 Actions: []Action{
2173 police,
2174 &MirredAction{
2175 ActionAttrs: ActionAttrs{
2176 Action: TC_ACT_STOLEN,
2177 },
2178 MirredAction: TCA_EGRESS_REDIR,
2179 Ifindex: redir.Attrs().Index,
2180 },
2181 },
2182 }
2183
2184 if err := FilterAdd(filter); err != nil {
2185 t.Fatal(err)
2186 }
2187
2188 filters, err := FilterList(link, MakeHandle(0xffff, 0))
2189 if err != nil {
2190 t.Fatal(err)
2191 }
2192 if len(filters) != 1 {
2193 t.Fatal("Failed to add filter")
2194 }
2195 u32, ok := filters[0].(*U32)
2196 if !ok {
2197 t.Fatal("Filter is the wrong type")
2198 }
2199
2200 if len(u32.Actions) != 2 {
2201 t.Fatalf("Too few Actions in filter")
2202 }
2203 if u32.ClassId != classId {
2204 t.Fatalf("ClassId of the filter is the wrong value")
2205 }
2206
2207
2208 p, ok := u32.Actions[0].(*PoliceAction)
2209 if !ok {
2210 p, ok = u32.Actions[1].(*PoliceAction)
2211 if !ok {
2212 t.Fatal("Unable to find police action")
2213 }
2214 }
2215
2216 if p.ExceedAction != TC_POLICE_SHOT {
2217 t.Fatal("Police ExceedAction isn't TC_POLICE_SHOT")
2218 }
2219
2220 if p.NotExceedAction != TC_POLICE_UNSPEC {
2221 t.Fatal("Police NotExceedAction isn't TC_POLICE_UNSPEC")
2222 }
2223
2224 if p.Rate != policeRate {
2225 t.Fatal("Action Rate doesn't match")
2226 }
2227
2228 if p.PeakRate != policePeakRate {
2229 t.Fatal("Action PeakRate doesn't match")
2230 }
2231
2232 if p.LinkLayer != nl.LINKLAYER_ETHERNET {
2233 t.Fatal("Action LinkLayer doesn't match")
2234 }
2235
2236 mia, ok := u32.Actions[0].(*MirredAction)
2237 if !ok {
2238 mia, ok = u32.Actions[1].(*MirredAction)
2239 if !ok {
2240 t.Fatal("Unable to find mirred action")
2241 }
2242 }
2243
2244 if mia.Attrs().Action != TC_ACT_STOLEN {
2245 t.Fatal("Mirred action isn't TC_ACT_STOLEN")
2246 }
2247
2248 if err := FilterDel(filter); err != nil {
2249 t.Fatal(err)
2250 }
2251 filters, err = FilterList(link, MakeHandle(0xffff, 0))
2252 if err != nil {
2253 t.Fatal(err)
2254 }
2255 if len(filters) != 0 {
2256 t.Fatal("Failed to remove filter")
2257 }
2258
2259 if err := QdiscDel(qdisc); err != nil {
2260 t.Fatal(err)
2261 }
2262 qdiscs, err = SafeQdiscList(link)
2263 if err != nil {
2264 t.Fatal(err)
2265 }
2266
2267 found = false
2268 for _, v := range qdiscs {
2269 if _, ok := v.(*Ingress); ok {
2270 found = true
2271 break
2272 }
2273 }
2274 if found {
2275 t.Fatal("Failed to remove qdisc")
2276 }
2277 }
2278
2279 func TestFilterU32DirectPoliceAddDel(t *testing.T) {
2280 tearDown := setUpNetlinkTest(t)
2281 defer tearDown()
2282 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
2283 t.Fatal(err)
2284 }
2285 link, err := LinkByName("foo")
2286 if err != nil {
2287 t.Fatal(err)
2288 }
2289 if err := LinkSetUp(link); err != nil {
2290 t.Fatal(err)
2291 }
2292
2293 qdisc := &Ingress{
2294 QdiscAttrs: QdiscAttrs{
2295 LinkIndex: link.Attrs().Index,
2296 Handle: MakeHandle(0xffff, 0),
2297 Parent: HANDLE_INGRESS,
2298 },
2299 }
2300 if err := QdiscAdd(qdisc); err != nil {
2301 t.Fatal(err)
2302 }
2303
2304 const (
2305 policeRate = 0x40000000
2306 policeBurst = 0x19000
2307 policePeakRate = 0x4000
2308 )
2309
2310 police := NewPoliceAction()
2311 police.Rate = policeRate
2312 police.PeakRate = policePeakRate
2313 police.Burst = policeBurst
2314 police.ExceedAction = TC_POLICE_SHOT
2315 police.NotExceedAction = TC_POLICE_UNSPEC
2316
2317 classId := MakeHandle(1, 1)
2318 filter := &U32{
2319 FilterAttrs: FilterAttrs{
2320 LinkIndex: link.Attrs().Index,
2321 Parent: MakeHandle(0xffff, 0),
2322 Priority: 1,
2323 Protocol: unix.ETH_P_ALL,
2324 },
2325 ClassId: classId,
2326 Police: police,
2327 }
2328
2329 if err := FilterAdd(filter); err != nil {
2330 t.Fatal(err)
2331 }
2332
2333 filters, err := FilterList(link, MakeHandle(0xffff, 0))
2334 if err != nil {
2335 t.Fatal(err)
2336 }
2337 if len(filters) != 1 {
2338 t.Fatal("Failed to add filter")
2339 }
2340 u32, ok := filters[0].(*U32)
2341 if !ok {
2342 t.Fatal("Filter is the wrong type")
2343 }
2344
2345 if u32.Police == nil {
2346 t.Fatalf("No police in filter")
2347 }
2348
2349 if u32.Police.Rate != policeRate {
2350 t.Fatal("Filter Rate doesn't match")
2351 }
2352
2353 if u32.Police.PeakRate != policePeakRate {
2354 t.Fatal("Filter PeakRate doesn't match")
2355 }
2356
2357 if u32.Police.LinkLayer != nl.LINKLAYER_ETHERNET {
2358 t.Fatal("Filter LinkLayer doesn't match")
2359 }
2360
2361 if err := QdiscDel(qdisc); err != nil {
2362 t.Fatal(err)
2363 }
2364 qdiscs, err := SafeQdiscList(link)
2365 if err != nil {
2366 t.Fatal(err)
2367 }
2368
2369 found := false
2370 for _, v := range qdiscs {
2371 if _, ok := v.(*Ingress); ok {
2372 found = true
2373 break
2374 }
2375 }
2376 if found {
2377 t.Fatal("Failed to remove qdisc")
2378 }
2379 }
2380
2381 func TestFilterChainAddDel(t *testing.T) {
2382 tearDown := setUpNetlinkTest(t)
2383 defer tearDown()
2384 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
2385 t.Fatal(err)
2386 }
2387 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
2388 t.Fatal(err)
2389 }
2390 link, err := LinkByName("foo")
2391 if err != nil {
2392 t.Fatal(err)
2393 }
2394 if err := LinkSetUp(link); err != nil {
2395 t.Fatal(err)
2396 }
2397 redir, err := LinkByName("bar")
2398 if err != nil {
2399 t.Fatal(err)
2400 }
2401 if err := LinkSetUp(redir); err != nil {
2402 t.Fatal(err)
2403 }
2404 qdisc := &Ingress{
2405 QdiscAttrs: QdiscAttrs{
2406 LinkIndex: link.Attrs().Index,
2407 Handle: MakeHandle(0xffff, 0),
2408 Parent: HANDLE_INGRESS,
2409 },
2410 }
2411 if err := QdiscAdd(qdisc); err != nil {
2412 t.Fatal(err)
2413 }
2414 qdiscs, err := SafeQdiscList(link)
2415 if err != nil {
2416 t.Fatal(err)
2417 }
2418 if len(qdiscs) != 1 {
2419 t.Fatal("Failed to add qdisc")
2420 }
2421 _, ok := qdiscs[0].(*Ingress)
2422 if !ok {
2423 t.Fatal("Qdisc is the wrong type")
2424 }
2425 classId := MakeHandle(1, 1)
2426 chainVal := new(uint32)
2427 *chainVal = 20
2428 filter := &U32{
2429 FilterAttrs: FilterAttrs{
2430 LinkIndex: link.Attrs().Index,
2431 Parent: MakeHandle(0xffff, 0),
2432 Priority: 1,
2433 Protocol: unix.ETH_P_IP,
2434 Chain: chainVal,
2435 },
2436 RedirIndex: redir.Attrs().Index,
2437 ClassId: classId,
2438 }
2439 if err := FilterAdd(filter); err != nil {
2440 t.Fatal(err)
2441 }
2442 filters, err := FilterList(link, MakeHandle(0xffff, 0))
2443 if err != nil {
2444 t.Fatal(err)
2445 }
2446 if len(filters) != 1 {
2447 t.Fatal("Failed to add filter")
2448 }
2449 filterChain := filters[0].Attrs().Chain
2450 if filterChain != nil && *filterChain != *chainVal {
2451 t.Fatalf("Chain of the filter is the wrong value")
2452 }
2453 if err := FilterDel(filter); err != nil {
2454 t.Fatal(err)
2455 }
2456 filters, err = FilterList(link, MakeHandle(0xffff, 0))
2457 if err != nil {
2458 t.Fatal(err)
2459 }
2460 if len(filters) != 0 {
2461 t.Fatal("Failed to remove filter")
2462 }
2463 if err := QdiscDel(qdisc); err != nil {
2464 t.Fatal(err)
2465 }
2466 qdiscs, err = SafeQdiscList(link)
2467 if err != nil {
2468 t.Fatal(err)
2469 }
2470 if len(qdiscs) != 0 {
2471 t.Fatal("Failed to remove qdisc")
2472 }
2473 }
2474
View as plain text