github.com/vishvananda/netlink@v1.3.1/filter_test.go (about) 1 //go:build linux 2 // +build linux 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 // Check if the hash table is identical before and after FilterAdd. 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 // Copy filter. 289 cFilter := *filter 290 if err := FilterAdd(filter); err != nil { 291 t.Fatal(err) 292 } 293 // Check if the filter is identical before and after FilterAdd. 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 // Endianness checks 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 // actions can be returned in reverse order 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 // actions can be returned in reverse order 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 // This feature was added in kernel 4.5 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 // This classifier was added in kernel 4.7 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 // actions can be returned in reverse order 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 // actions can be returned in reverse order 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 srcMac, err := net.ParseMAC("2C:54:91:88:C9:E3") 1772 if err != nil { 1773 t.Fatal(err) 1774 } 1775 destMac, err := net.ParseMAC("2C:54:91:88:C9:E5") 1776 if err != nil { 1777 t.Fatal(err) 1778 } 1779 1780 ipproto := new(nl.IPProto) 1781 *ipproto = nl.IPPROTO_TCP 1782 1783 filter := &Flower{ 1784 FilterAttrs: FilterAttrs{ 1785 LinkIndex: link.Attrs().Index, 1786 Parent: MakeHandle(0xffff, 0), 1787 Priority: 1, 1788 Protocol: unix.ETH_P_ALL, 1789 }, 1790 DestIP: net.ParseIP("1.0.0.1"), 1791 DestIPMask: testMask, 1792 SrcIP: net.ParseIP("2.0.0.1"), 1793 SrcIPMask: testMask, 1794 EthType: unix.ETH_P_IP, 1795 EncDestIP: net.ParseIP("3.0.0.1"), 1796 EncDestIPMask: testMask, 1797 EncSrcIP: net.ParseIP("4.0.0.1"), 1798 EncSrcIPMask: testMask, 1799 EncDestPort: 8472, 1800 EncKeyId: 1234, 1801 SrcMac: srcMac, 1802 DestMac: destMac, 1803 IPProto: ipproto, 1804 DestPort: 1111, 1805 SrcPort: 1111, 1806 Actions: []Action{ 1807 &VlanAction{ 1808 ActionAttrs: ActionAttrs{ 1809 Action: TC_ACT_PIPE, 1810 }, 1811 Action: TCA_VLAN_ACT_PUSH, 1812 VlanID: 1234, 1813 }, 1814 &MirredAction{ 1815 ActionAttrs: ActionAttrs{ 1816 Action: TC_ACT_STOLEN, 1817 }, 1818 MirredAction: TCA_EGRESS_REDIR, 1819 Ifindex: redir.Attrs().Index, 1820 }, 1821 &GenericAction{ 1822 ActionAttrs: ActionAttrs{ 1823 Action: getTcActGotoChain(), 1824 }, 1825 Chain: 20, 1826 }, 1827 }, 1828 } 1829 1830 if err := FilterAdd(filter); err != nil { 1831 t.Fatal(err) 1832 } 1833 1834 time.Sleep(time.Second) 1835 filters, err := FilterList(link, MakeHandle(0xffff, 0)) 1836 if err != nil { 1837 t.Fatal(err) 1838 } 1839 if len(filters) != 1 { 1840 t.Fatal("Failed to add filter") 1841 } 1842 flower, ok := filters[0].(*Flower) 1843 if !ok { 1844 t.Fatal("Filter is the wrong type") 1845 } 1846 1847 if filter.EthType != flower.EthType { 1848 t.Fatalf("Flower EthType doesn't match") 1849 } 1850 if !filter.DestIP.Equal(flower.DestIP) { 1851 t.Fatalf("Flower DestIP doesn't match") 1852 } 1853 if !filter.SrcIP.Equal(flower.SrcIP) { 1854 t.Fatalf("Flower SrcIP doesn't match") 1855 } 1856 1857 if !reflect.DeepEqual(filter.DestIPMask, testMask) { 1858 t.Fatalf("Flower DestIPMask doesn't match") 1859 } 1860 if !reflect.DeepEqual(filter.SrcIPMask, testMask) { 1861 t.Fatalf("Flower SrcIPMask doesn't match") 1862 } 1863 1864 if !filter.EncDestIP.Equal(flower.EncDestIP) { 1865 t.Fatalf("Flower EncDestIP doesn't match") 1866 } 1867 if !filter.EncSrcIP.Equal(flower.EncSrcIP) { 1868 t.Fatalf("Flower EncSrcIP doesn't match") 1869 } 1870 if !reflect.DeepEqual(filter.EncDestIPMask, testMask) { 1871 t.Fatalf("Flower EncDestIPMask doesn't match") 1872 } 1873 if !reflect.DeepEqual(filter.EncSrcIPMask, testMask) { 1874 t.Fatalf("Flower EncSrcIPMask doesn't match") 1875 } 1876 if filter.EncKeyId != flower.EncKeyId { 1877 t.Fatalf("Flower EncKeyId doesn't match") 1878 } 1879 if filter.EncDestPort != flower.EncDestPort { 1880 t.Fatalf("Flower EncDestPort doesn't match") 1881 } 1882 if flower.IPProto == nil || *filter.IPProto != *flower.IPProto { 1883 t.Fatalf("Flower IPProto doesn't match") 1884 } 1885 if filter.DestPort != flower.DestPort { 1886 t.Fatalf("Flower DestPort doesn't match") 1887 } 1888 if filter.SrcPort != flower.SrcPort { 1889 t.Fatalf("Flower SrcPort doesn't match") 1890 } 1891 if !(filter.SrcMac.String() == flower.SrcMac.String()) { 1892 t.Fatalf("Flower SrcMac doesn't match") 1893 } 1894 if !(filter.DestMac.String() == flower.DestMac.String()) { 1895 t.Fatalf("Flower DestMac doesn't match") 1896 } 1897 1898 vla, ok := flower.Actions[0].(*VlanAction) 1899 if !ok { 1900 t.Fatal("Unable to find vlan action") 1901 } 1902 1903 if vla.Attrs().Action != TC_ACT_PIPE { 1904 t.Fatal("Vlan action isn't TC_ACT_PIPE") 1905 } 1906 1907 if vla.Action != TCA_VLAN_ACT_PUSH { 1908 t.Fatal("Second Vlan action isn't push") 1909 } 1910 1911 if vla.VlanID != 1234 { 1912 t.Fatal("Second Vlan action vlanId isn't correct") 1913 } 1914 1915 mia, ok := flower.Actions[1].(*MirredAction) 1916 if !ok { 1917 t.Fatal("Unable to find mirred action") 1918 } 1919 1920 if mia.Attrs().Action != TC_ACT_STOLEN { 1921 t.Fatal("Mirred action isn't TC_ACT_STOLEN") 1922 } 1923 1924 if mia.Timestamp == nil || mia.Timestamp.Installed == 0 { 1925 t.Fatal("Incorrect mirred action timestamp") 1926 } 1927 1928 if mia.Statistics == nil { 1929 t.Fatal("Incorrect mirred action stats") 1930 } 1931 1932 ga, ok := flower.Actions[2].(*GenericAction) 1933 if !ok { 1934 t.Fatal("Unable to find generic action") 1935 } 1936 1937 if ga.Attrs().Action != getTcActGotoChain() { 1938 t.Fatal("Generic action isn't TC_ACT_GOTO_CHAIN") 1939 } 1940 1941 if ga.Timestamp == nil || ga.Timestamp.Installed == 0 { 1942 t.Fatal("Incorrect generic action timestamp") 1943 } 1944 1945 if ga.Statistics == nil { 1946 t.Fatal("Incorrect generic action stats") 1947 } 1948 1949 if err := FilterDel(filter); err != nil { 1950 t.Fatal(err) 1951 } 1952 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 1953 if err != nil { 1954 t.Fatal(err) 1955 } 1956 if len(filters) != 0 { 1957 t.Fatal("Failed to remove filter") 1958 } 1959 1960 filter = &Flower{ 1961 FilterAttrs: FilterAttrs{ 1962 LinkIndex: link.Attrs().Index, 1963 Parent: MakeHandle(0xffff, 0), 1964 Priority: 1, 1965 Protocol: unix.ETH_P_8021Q, 1966 }, 1967 EthType: unix.ETH_P_8021Q, 1968 VlanId: 2046, 1969 Actions: []Action{ 1970 &VlanAction{ 1971 ActionAttrs: ActionAttrs{ 1972 Action: TC_ACT_PIPE, 1973 }, 1974 Action: TCA_VLAN_ACT_POP, 1975 }, 1976 &MirredAction{ 1977 ActionAttrs: ActionAttrs{ 1978 Action: TC_ACT_STOLEN, 1979 }, 1980 MirredAction: TCA_EGRESS_REDIR, 1981 Ifindex: redir.Attrs().Index, 1982 }, 1983 }, 1984 } 1985 1986 if err := FilterAdd(filter); err != nil { 1987 t.Fatal(err) 1988 } 1989 1990 time.Sleep(time.Second) 1991 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 1992 if err != nil { 1993 t.Fatal(err) 1994 } 1995 if len(filters) != 1 { 1996 t.Fatal("Failed to add filter") 1997 } 1998 flower, ok = filters[0].(*Flower) 1999 if !ok { 2000 t.Fatal("Filter is the wrong type") 2001 } 2002 2003 if filter.VlanId != flower.VlanId { 2004 t.Fatalf("Flower VlanId doesn't match") 2005 } 2006 2007 vla, ok = flower.Actions[0].(*VlanAction) 2008 if !ok { 2009 t.Fatal("Unable to find vlan action") 2010 } 2011 2012 if vla.Attrs().Action != TC_ACT_PIPE { 2013 t.Fatal("Vlan action isn't TC_ACT_PIPE") 2014 } 2015 2016 if vla.Action != TCA_VLAN_ACT_POP { 2017 t.Fatal("First Vlan action isn't pop") 2018 } 2019 2020 mia, ok = flower.Actions[1].(*MirredAction) 2021 if !ok { 2022 t.Fatal("Unable to find mirred action") 2023 } 2024 2025 if mia.Attrs().Action != TC_ACT_STOLEN { 2026 t.Fatal("Mirred action isn't TC_ACT_STOLEN") 2027 } 2028 2029 if mia.Timestamp == nil || mia.Timestamp.Installed == 0 { 2030 t.Fatal("Incorrect mirred action timestamp") 2031 } 2032 2033 if mia.Statistics == nil { 2034 t.Fatal("Incorrect mirred action stats") 2035 } 2036 2037 if err := FilterDel(filter); err != nil { 2038 t.Fatal(err) 2039 } 2040 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 2041 if err != nil { 2042 t.Fatal(err) 2043 } 2044 if len(filters) != 0 { 2045 t.Fatal("Failed to remove filter") 2046 } 2047 2048 classId := MakeHandle(1, 101) 2049 2050 filter = &Flower{ 2051 FilterAttrs: FilterAttrs{ 2052 LinkIndex: link.Attrs().Index, 2053 Parent: MakeHandle(0xffff, 0), 2054 Priority: 1, 2055 Protocol: unix.ETH_P_ALL, 2056 }, 2057 2058 EthType: unix.ETH_P_IP, 2059 IPProto: ipproto, 2060 ClassId: classId, 2061 SrcPortRangeMin: 1000, 2062 SrcPortRangeMax: 2000, 2063 } 2064 if err := FilterAdd(filter); err != nil { 2065 t.Fatal(err) 2066 } 2067 2068 time.Sleep(time.Second) 2069 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 2070 if err != nil { 2071 t.Fatal(err) 2072 } 2073 if len(filters) != 1 { 2074 t.Fatal("Failed to add filter") 2075 } 2076 flower, ok = filters[0].(*Flower) 2077 if !ok { 2078 t.Fatal("Filter is the wrong type") 2079 } 2080 if filter.ClassId != flower.ClassId { 2081 t.Fatalf("Flower ClassId doesn't match") 2082 } 2083 if filter.SrcPortRangeMin != flower.SrcPortRangeMin { 2084 t.Fatalf("Flower SrcPortRangeMin doesn't match") 2085 } 2086 if filter.SrcPortRangeMax != flower.SrcPortRangeMax { 2087 t.Fatalf("Flower SrcPortRangeMax doesn't match") 2088 } 2089 if err := FilterDel(filter); err != nil { 2090 t.Fatal(err) 2091 } 2092 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 2093 if err != nil { 2094 t.Fatal(err) 2095 } 2096 if len(filters) != 0 { 2097 t.Fatal("Failed to remove filter") 2098 } 2099 2100 if err := QdiscDel(qdisc); err != nil { 2101 t.Fatal(err) 2102 } 2103 qdiscs, err = SafeQdiscList(link) 2104 if err != nil { 2105 t.Fatal(err) 2106 } 2107 2108 found = false 2109 for _, v := range qdiscs { 2110 if _, ok := v.(*Ingress); ok { 2111 found = true 2112 break 2113 } 2114 } 2115 if found { 2116 t.Fatal("Failed to remove qdisc") 2117 } 2118 } 2119 2120 func TestFilterIPv6FlowerPedit(t *testing.T) { 2121 tearDown := setUpNetlinkTest(t) 2122 defer tearDown() 2123 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 2124 t.Fatal(err) 2125 } 2126 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil { 2127 t.Fatal(err) 2128 } 2129 link, err := LinkByName("foo") 2130 if err != nil { 2131 t.Fatal(err) 2132 } 2133 if err := LinkSetUp(link); err != nil { 2134 t.Fatal(err) 2135 } 2136 redir, err := LinkByName("bar") 2137 if err != nil { 2138 t.Fatal(err) 2139 } 2140 if err := LinkSetUp(redir); err != nil { 2141 t.Fatal(err) 2142 } 2143 2144 qdisc := &Ingress{ 2145 QdiscAttrs: QdiscAttrs{ 2146 LinkIndex: link.Attrs().Index, 2147 Handle: MakeHandle(0xffff, 0), 2148 Parent: HANDLE_INGRESS, 2149 }, 2150 } 2151 if err := QdiscAdd(qdisc); err != nil { 2152 t.Fatal(err) 2153 } 2154 qdiscs, err := SafeQdiscList(link) 2155 if err != nil { 2156 t.Fatal(err) 2157 } 2158 2159 found := false 2160 for _, v := range qdiscs { 2161 if _, ok := v.(*Ingress); ok { 2162 found = true 2163 break 2164 } 2165 } 2166 if !found { 2167 t.Fatal("Qdisc is the wrong type") 2168 } 2169 2170 testMask := net.CIDRMask(64, 128) 2171 2172 ipproto := new(nl.IPProto) 2173 *ipproto = nl.IPPROTO_TCP 2174 2175 filter := &Flower{ 2176 FilterAttrs: FilterAttrs{ 2177 LinkIndex: link.Attrs().Index, 2178 Parent: MakeHandle(0xffff, 0), 2179 Priority: 1, 2180 Protocol: unix.ETH_P_ALL, 2181 }, 2182 DestIP: net.ParseIP("ffff::fff1"), 2183 DestIPMask: testMask, 2184 EthType: unix.ETH_P_IPV6, 2185 IPProto: ipproto, 2186 DestPort: 6666, 2187 Actions: []Action{}, 2188 } 2189 2190 peditAction := NewPeditAction() 2191 peditAction.Proto = uint8(nl.IPPROTO_TCP) 2192 peditAction.SrcPort = 7777 2193 peditAction.SrcIP = net.ParseIP("ffff::fff2") 2194 filter.Actions = append(filter.Actions, peditAction) 2195 2196 miaAction := &MirredAction{ 2197 ActionAttrs: ActionAttrs{ 2198 Action: TC_ACT_REDIRECT, 2199 }, 2200 MirredAction: TCA_EGRESS_REDIR, 2201 Ifindex: redir.Attrs().Index, 2202 } 2203 filter.Actions = append(filter.Actions, miaAction) 2204 2205 if err := FilterAdd(filter); err != nil { 2206 t.Fatal(err) 2207 } 2208 2209 filters, err := FilterList(link, MakeHandle(0xffff, 0)) 2210 if err != nil { 2211 t.Fatal(err) 2212 } 2213 if len(filters) != 1 { 2214 t.Fatal("Failed to add filter") 2215 } 2216 flower, ok := filters[0].(*Flower) 2217 if !ok { 2218 t.Fatal("Filter is the wrong type") 2219 } 2220 2221 if filter.EthType != flower.EthType { 2222 t.Fatalf("Flower EthType doesn't match") 2223 } 2224 if !filter.DestIP.Equal(flower.DestIP) { 2225 t.Fatalf("Flower DestIP doesn't match") 2226 } 2227 2228 if !reflect.DeepEqual(filter.DestIPMask, testMask) { 2229 t.Fatalf("Flower DestIPMask doesn't match") 2230 } 2231 2232 if flower.IPProto == nil || *filter.IPProto != *flower.IPProto { 2233 t.Fatalf("Flower IPProto doesn't match") 2234 } 2235 if filter.DestPort != flower.DestPort { 2236 t.Fatalf("Flower DestPort doesn't match") 2237 } 2238 2239 _, ok = flower.Actions[0].(*PeditAction) 2240 if !ok { 2241 t.Fatal("Unable to find pedit action") 2242 } 2243 2244 _, ok = flower.Actions[1].(*MirredAction) 2245 if !ok { 2246 t.Fatal("Unable to find mirred action") 2247 } 2248 2249 if err := FilterDel(filter); err != nil { 2250 t.Fatal(err) 2251 } 2252 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 2253 if err != nil { 2254 t.Fatal(err) 2255 } 2256 if len(filters) != 0 { 2257 t.Fatal("Failed to remove filter") 2258 } 2259 2260 if err := QdiscDel(qdisc); err != nil { 2261 t.Fatal(err) 2262 } 2263 qdiscs, err = SafeQdiscList(link) 2264 if err != nil { 2265 t.Fatal(err) 2266 } 2267 2268 found = false 2269 for _, v := range qdiscs { 2270 if _, ok := v.(*Ingress); ok { 2271 found = true 2272 break 2273 } 2274 } 2275 if found { 2276 t.Fatal("Failed to remove qdisc") 2277 } 2278 } 2279 2280 func TestFilterU32PoliceAddDel(t *testing.T) { 2281 tearDown := setUpNetlinkTest(t) 2282 defer tearDown() 2283 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 2284 t.Fatal(err) 2285 } 2286 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil { 2287 t.Fatal(err) 2288 } 2289 link, err := LinkByName("foo") 2290 if err != nil { 2291 t.Fatal(err) 2292 } 2293 if err := LinkSetUp(link); err != nil { 2294 t.Fatal(err) 2295 } 2296 redir, err := LinkByName("bar") 2297 if err != nil { 2298 t.Fatal(err) 2299 } 2300 if err := LinkSetUp(redir); err != nil { 2301 t.Fatal(err) 2302 } 2303 2304 qdisc := &Ingress{ 2305 QdiscAttrs: QdiscAttrs{ 2306 LinkIndex: link.Attrs().Index, 2307 Handle: MakeHandle(0xffff, 0), 2308 Parent: HANDLE_INGRESS, 2309 }, 2310 } 2311 if err := QdiscAdd(qdisc); err != nil { 2312 t.Fatal(err) 2313 } 2314 qdiscs, err := SafeQdiscList(link) 2315 if err != nil { 2316 t.Fatal(err) 2317 } 2318 2319 found := false 2320 for _, v := range qdiscs { 2321 if _, ok := v.(*Ingress); ok { 2322 found = true 2323 break 2324 } 2325 } 2326 if !found { 2327 t.Fatal("Qdisc is the wrong type") 2328 } 2329 2330 const ( 2331 policeRate = 0x40000000 // 1 Gbps 2332 policeBurst = 0x19000 // 100 KB 2333 policePeakRate = 0x4000 // 16 Kbps 2334 ) 2335 2336 police := NewPoliceAction() 2337 police.Rate = policeRate 2338 police.PeakRate = policePeakRate 2339 police.Burst = policeBurst 2340 police.ExceedAction = TC_POLICE_SHOT 2341 police.NotExceedAction = TC_POLICE_UNSPEC 2342 2343 classId := MakeHandle(1, 1) 2344 filter := &U32{ 2345 FilterAttrs: FilterAttrs{ 2346 LinkIndex: link.Attrs().Index, 2347 Parent: MakeHandle(0xffff, 0), 2348 Priority: 1, 2349 Protocol: unix.ETH_P_ALL, 2350 }, 2351 ClassId: classId, 2352 Actions: []Action{ 2353 police, 2354 &MirredAction{ 2355 ActionAttrs: ActionAttrs{ 2356 Action: TC_ACT_STOLEN, 2357 }, 2358 MirredAction: TCA_EGRESS_REDIR, 2359 Ifindex: redir.Attrs().Index, 2360 }, 2361 }, 2362 } 2363 2364 if err := FilterAdd(filter); err != nil { 2365 t.Fatal(err) 2366 } 2367 2368 filters, err := FilterList(link, MakeHandle(0xffff, 0)) 2369 if err != nil { 2370 t.Fatal(err) 2371 } 2372 if len(filters) != 1 { 2373 t.Fatal("Failed to add filter") 2374 } 2375 u32, ok := filters[0].(*U32) 2376 if !ok { 2377 t.Fatal("Filter is the wrong type") 2378 } 2379 2380 if len(u32.Actions) != 2 { 2381 t.Fatalf("Too few Actions in filter") 2382 } 2383 if u32.ClassId != classId { 2384 t.Fatalf("ClassId of the filter is the wrong value") 2385 } 2386 2387 // actions can be returned in reverse order 2388 p, ok := u32.Actions[0].(*PoliceAction) 2389 if !ok { 2390 p, ok = u32.Actions[1].(*PoliceAction) 2391 if !ok { 2392 t.Fatal("Unable to find police action") 2393 } 2394 } 2395 2396 if p.ExceedAction != TC_POLICE_SHOT { 2397 t.Fatal("Police ExceedAction isn't TC_POLICE_SHOT") 2398 } 2399 2400 if p.NotExceedAction != TC_POLICE_UNSPEC { 2401 t.Fatal("Police NotExceedAction isn't TC_POLICE_UNSPEC") 2402 } 2403 2404 if p.Rate != policeRate { 2405 t.Fatal("Action Rate doesn't match") 2406 } 2407 2408 if p.PeakRate != policePeakRate { 2409 t.Fatal("Action PeakRate doesn't match") 2410 } 2411 2412 if p.LinkLayer != nl.LINKLAYER_ETHERNET { 2413 t.Fatal("Action LinkLayer doesn't match") 2414 } 2415 2416 mia, ok := u32.Actions[0].(*MirredAction) 2417 if !ok { 2418 mia, ok = u32.Actions[1].(*MirredAction) 2419 if !ok { 2420 t.Fatal("Unable to find mirred action") 2421 } 2422 } 2423 2424 if mia.Attrs().Action != TC_ACT_STOLEN { 2425 t.Fatal("Mirred action isn't TC_ACT_STOLEN") 2426 } 2427 2428 if err := FilterDel(filter); err != nil { 2429 t.Fatal(err) 2430 } 2431 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 2432 if err != nil { 2433 t.Fatal(err) 2434 } 2435 if len(filters) != 0 { 2436 t.Fatal("Failed to remove filter") 2437 } 2438 2439 if err := QdiscDel(qdisc); err != nil { 2440 t.Fatal(err) 2441 } 2442 qdiscs, err = SafeQdiscList(link) 2443 if err != nil { 2444 t.Fatal(err) 2445 } 2446 2447 found = false 2448 for _, v := range qdiscs { 2449 if _, ok := v.(*Ingress); ok { 2450 found = true 2451 break 2452 } 2453 } 2454 if found { 2455 t.Fatal("Failed to remove qdisc") 2456 } 2457 } 2458 2459 func TestFilterU32DirectPoliceAddDel(t *testing.T) { 2460 tearDown := setUpNetlinkTest(t) 2461 defer tearDown() 2462 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 2463 t.Fatal(err) 2464 } 2465 link, err := LinkByName("foo") 2466 if err != nil { 2467 t.Fatal(err) 2468 } 2469 if err := LinkSetUp(link); err != nil { 2470 t.Fatal(err) 2471 } 2472 2473 qdisc := &Ingress{ 2474 QdiscAttrs: QdiscAttrs{ 2475 LinkIndex: link.Attrs().Index, 2476 Handle: MakeHandle(0xffff, 0), 2477 Parent: HANDLE_INGRESS, 2478 }, 2479 } 2480 if err := QdiscAdd(qdisc); err != nil { 2481 t.Fatal(err) 2482 } 2483 2484 const ( 2485 policeRate = 0x40000000 // 1 Gbps 2486 policeBurst = 0x19000 // 100 KB 2487 policePeakRate = 0x4000 // 16 Kbps 2488 ) 2489 2490 police := NewPoliceAction() 2491 police.Rate = policeRate 2492 police.PeakRate = policePeakRate 2493 police.Burst = policeBurst 2494 police.ExceedAction = TC_POLICE_SHOT 2495 police.NotExceedAction = TC_POLICE_UNSPEC 2496 2497 classId := MakeHandle(1, 1) 2498 filter := &U32{ 2499 FilterAttrs: FilterAttrs{ 2500 LinkIndex: link.Attrs().Index, 2501 Parent: MakeHandle(0xffff, 0), 2502 Priority: 1, 2503 Protocol: unix.ETH_P_ALL, 2504 }, 2505 ClassId: classId, 2506 Police: police, 2507 } 2508 2509 if err := FilterAdd(filter); err != nil { 2510 t.Fatal(err) 2511 } 2512 2513 filters, err := FilterList(link, MakeHandle(0xffff, 0)) 2514 if err != nil { 2515 t.Fatal(err) 2516 } 2517 if len(filters) != 1 { 2518 t.Fatal("Failed to add filter") 2519 } 2520 u32, ok := filters[0].(*U32) 2521 if !ok { 2522 t.Fatal("Filter is the wrong type") 2523 } 2524 2525 if u32.Police == nil { 2526 t.Fatalf("No police in filter") 2527 } 2528 2529 if u32.Police.Rate != policeRate { 2530 t.Fatal("Filter Rate doesn't match") 2531 } 2532 2533 if u32.Police.PeakRate != policePeakRate { 2534 t.Fatal("Filter PeakRate doesn't match") 2535 } 2536 2537 if u32.Police.LinkLayer != nl.LINKLAYER_ETHERNET { 2538 t.Fatal("Filter LinkLayer doesn't match") 2539 } 2540 2541 if err := QdiscDel(qdisc); err != nil { 2542 t.Fatal(err) 2543 } 2544 qdiscs, err := SafeQdiscList(link) 2545 if err != nil { 2546 t.Fatal(err) 2547 } 2548 2549 found := false 2550 for _, v := range qdiscs { 2551 if _, ok := v.(*Ingress); ok { 2552 found = true 2553 break 2554 } 2555 } 2556 if found { 2557 t.Fatal("Failed to remove qdisc") 2558 } 2559 } 2560 2561 func TestFilterChainAddDel(t *testing.T) { 2562 tearDown := setUpNetlinkTest(t) 2563 defer tearDown() 2564 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 2565 t.Fatal(err) 2566 } 2567 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil { 2568 t.Fatal(err) 2569 } 2570 link, err := LinkByName("foo") 2571 if err != nil { 2572 t.Fatal(err) 2573 } 2574 if err := LinkSetUp(link); err != nil { 2575 t.Fatal(err) 2576 } 2577 redir, err := LinkByName("bar") 2578 if err != nil { 2579 t.Fatal(err) 2580 } 2581 if err := LinkSetUp(redir); err != nil { 2582 t.Fatal(err) 2583 } 2584 qdisc := &Ingress{ 2585 QdiscAttrs: QdiscAttrs{ 2586 LinkIndex: link.Attrs().Index, 2587 Handle: MakeHandle(0xffff, 0), 2588 Parent: HANDLE_INGRESS, 2589 }, 2590 } 2591 if err := QdiscAdd(qdisc); err != nil { 2592 t.Fatal(err) 2593 } 2594 qdiscs, err := SafeQdiscList(link) 2595 if err != nil { 2596 t.Fatal(err) 2597 } 2598 if len(qdiscs) != 1 { 2599 t.Fatal("Failed to add qdisc") 2600 } 2601 _, ok := qdiscs[0].(*Ingress) 2602 if !ok { 2603 t.Fatal("Qdisc is the wrong type") 2604 } 2605 classId := MakeHandle(1, 1) 2606 chainVal := new(uint32) 2607 *chainVal = 20 2608 filter := &U32{ 2609 FilterAttrs: FilterAttrs{ 2610 LinkIndex: link.Attrs().Index, 2611 Parent: MakeHandle(0xffff, 0), 2612 Priority: 1, 2613 Protocol: unix.ETH_P_IP, 2614 Chain: chainVal, 2615 }, 2616 RedirIndex: redir.Attrs().Index, 2617 ClassId: classId, 2618 } 2619 if err := FilterAdd(filter); err != nil { 2620 t.Fatal(err) 2621 } 2622 filters, err := FilterList(link, MakeHandle(0xffff, 0)) 2623 if err != nil { 2624 t.Fatal(err) 2625 } 2626 if len(filters) != 1 { 2627 t.Fatal("Failed to add filter") 2628 } 2629 filterChain := filters[0].Attrs().Chain 2630 if filterChain != nil && *filterChain != *chainVal { 2631 t.Fatalf("Chain of the filter is the wrong value") 2632 } 2633 if err := FilterDel(filter); err != nil { 2634 t.Fatal(err) 2635 } 2636 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 2637 if err != nil { 2638 t.Fatal(err) 2639 } 2640 if len(filters) != 0 { 2641 t.Fatal("Failed to remove filter") 2642 } 2643 if err := QdiscDel(qdisc); err != nil { 2644 t.Fatal(err) 2645 } 2646 qdiscs, err = SafeQdiscList(link) 2647 if err != nil { 2648 t.Fatal(err) 2649 } 2650 if len(qdiscs) != 0 { 2651 t.Fatal("Failed to remove qdisc") 2652 } 2653 } 2654 2655 func TestFilterSampleAddDel(t *testing.T) { 2656 minKernelRequired(t, 4, 11) 2657 if _, err := GenlFamilyGet("psample"); err != nil { 2658 t.Skip("psample genetlink family unavailable - is CONFIG_PSAMPLE enabled?") 2659 } 2660 2661 tearDown := setUpNetlinkTest(t) 2662 defer tearDown() 2663 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 2664 t.Fatal(err) 2665 } 2666 link, err := LinkByName("foo") 2667 if err != nil { 2668 t.Fatal(err) 2669 } 2670 if err := LinkSetUp(link); err != nil { 2671 t.Fatal(err) 2672 } 2673 2674 qdisc := &Ingress{ 2675 QdiscAttrs: QdiscAttrs{ 2676 LinkIndex: link.Attrs().Index, 2677 Handle: MakeHandle(0xffff, 0), 2678 Parent: HANDLE_INGRESS, 2679 }, 2680 } 2681 if err := QdiscAdd(qdisc); err != nil { 2682 t.Fatal(err) 2683 } 2684 qdiscs, err := SafeQdiscList(link) 2685 if err != nil { 2686 t.Fatal(err) 2687 } 2688 2689 found := false 2690 for _, v := range qdiscs { 2691 if _, ok := v.(*Ingress); ok { 2692 found = true 2693 break 2694 } 2695 } 2696 if !found { 2697 t.Fatal("Qdisc is the wrong type") 2698 } 2699 2700 sample := NewSampleAction() 2701 sample.Group = 7 2702 sample.Rate = 12 2703 sample.TruncSize = 200 2704 2705 classId := MakeHandle(1, 1) 2706 filter := &MatchAll{ 2707 FilterAttrs: FilterAttrs{ 2708 LinkIndex: link.Attrs().Index, 2709 Parent: MakeHandle(0xffff, 0), 2710 Priority: 1, 2711 Protocol: unix.ETH_P_ALL, 2712 }, 2713 ClassId: classId, 2714 Actions: []Action{ 2715 sample, 2716 }, 2717 } 2718 2719 if err := FilterAdd(filter); err != nil { 2720 t.Fatal(err) 2721 } 2722 2723 filters, err := FilterList(link, MakeHandle(0xffff, 0)) 2724 if err != nil { 2725 t.Fatal(err) 2726 } 2727 if len(filters) != 1 { 2728 t.Fatal("Failed to add filter") 2729 } 2730 mf, ok := filters[0].(*MatchAll) 2731 if !ok { 2732 t.Fatal("Filter is the wrong type") 2733 } 2734 2735 if len(mf.Actions) < 1 { 2736 t.Fatalf("Too few Actions in filter") 2737 } 2738 if mf.ClassId != classId { 2739 t.Fatalf("ClassId of the filter is the wrong value") 2740 } 2741 2742 lsample, ok := mf.Actions[0].(*SampleAction) 2743 if !ok { 2744 t.Fatal("Unable to find sample action") 2745 } 2746 if lsample.Group != sample.Group { 2747 t.Fatalf("Inconsistent sample action group") 2748 } 2749 if lsample.Rate != sample.Rate { 2750 t.Fatalf("Inconsistent sample action rate") 2751 } 2752 if lsample.TruncSize != sample.TruncSize { 2753 t.Fatalf("Inconsistent sample truncation size") 2754 } 2755 2756 if err := FilterDel(filter); err != nil { 2757 t.Fatal(err) 2758 } 2759 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 2760 if err != nil { 2761 t.Fatal(err) 2762 } 2763 if len(filters) != 0 { 2764 t.Fatal("Failed to remove filter") 2765 } 2766 2767 if err := QdiscDel(qdisc); err != nil { 2768 t.Fatal(err) 2769 } 2770 qdiscs, err = SafeQdiscList(link) 2771 if err != nil { 2772 t.Fatal(err) 2773 } 2774 2775 found = false 2776 for _, v := range qdiscs { 2777 if _, ok := v.(*Ingress); ok { 2778 found = true 2779 break 2780 } 2781 } 2782 if found { 2783 t.Fatal("Failed to remove qdisc") 2784 } 2785 }