github.com/sagernet/netlink@v0.0.0-20240612041022-b9a21c07ac6a/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 11 "github.com/sagernet/netlink/nl" 12 "golang.org/x/sys/unix" 13 ) 14 15 func TestFilterAddDel(t *testing.T) { 16 tearDown := setUpNetlinkTest(t) 17 defer tearDown() 18 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 19 t.Fatal(err) 20 } 21 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil { 22 t.Fatal(err) 23 } 24 link, err := LinkByName("foo") 25 if err != nil { 26 t.Fatal(err) 27 } 28 if err := LinkSetUp(link); err != nil { 29 t.Fatal(err) 30 } 31 redir, err := LinkByName("bar") 32 if err != nil { 33 t.Fatal(err) 34 } 35 if err := LinkSetUp(redir); err != nil { 36 t.Fatal(err) 37 } 38 qdisc := &Ingress{ 39 QdiscAttrs: QdiscAttrs{ 40 LinkIndex: link.Attrs().Index, 41 Handle: MakeHandle(0xffff, 0), 42 Parent: HANDLE_INGRESS, 43 }, 44 } 45 if err := QdiscAdd(qdisc); err != nil { 46 t.Fatal(err) 47 } 48 qdiscs, err := SafeQdiscList(link) 49 if err != nil { 50 t.Fatal(err) 51 } 52 if len(qdiscs) != 1 { 53 t.Fatal("Failed to add qdisc") 54 } 55 _, ok := qdiscs[0].(*Ingress) 56 if !ok { 57 t.Fatal("Qdisc is the wrong type") 58 } 59 classId := MakeHandle(1, 1) 60 filter := &U32{ 61 FilterAttrs: FilterAttrs{ 62 LinkIndex: link.Attrs().Index, 63 Parent: MakeHandle(0xffff, 0), 64 Priority: 1, 65 Protocol: unix.ETH_P_IP, 66 }, 67 RedirIndex: redir.Attrs().Index, 68 ClassId: classId, 69 } 70 if err := FilterAdd(filter); err != nil { 71 t.Fatal(err) 72 } 73 filters, err := FilterList(link, MakeHandle(0xffff, 0)) 74 if err != nil { 75 t.Fatal(err) 76 } 77 if len(filters) != 1 { 78 t.Fatal("Failed to add filter") 79 } 80 u32, ok := filters[0].(*U32) 81 if !ok { 82 t.Fatal("Filter is the wrong type") 83 } 84 if u32.ClassId != classId { 85 t.Fatalf("ClassId of the filter is the wrong value") 86 } 87 if err := FilterDel(filter); err != nil { 88 t.Fatal(err) 89 } 90 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 91 if err != nil { 92 t.Fatal(err) 93 } 94 if len(filters) != 0 { 95 t.Fatal("Failed to remove filter") 96 } 97 if err := QdiscDel(qdisc); err != nil { 98 t.Fatal(err) 99 } 100 qdiscs, err = SafeQdiscList(link) 101 if err != nil { 102 t.Fatal(err) 103 } 104 if len(qdiscs) != 0 { 105 t.Fatal("Failed to remove qdisc") 106 } 107 } 108 109 func TestFilterReplace(t *testing.T) { 110 tearDown := setUpNetlinkTest(t) 111 defer tearDown() 112 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 113 t.Fatal(err) 114 } 115 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil { 116 t.Fatal(err) 117 } 118 link, err := LinkByName("foo") 119 if err != nil { 120 t.Fatal(err) 121 } 122 if err := LinkSetUp(link); err != nil { 123 t.Fatal(err) 124 } 125 redir, err := LinkByName("bar") 126 if err != nil { 127 t.Fatal(err) 128 } 129 if err := LinkSetUp(redir); err != nil { 130 t.Fatal(err) 131 } 132 qdisc := &Ingress{ 133 QdiscAttrs: QdiscAttrs{ 134 LinkIndex: link.Attrs().Index, 135 Handle: MakeHandle(0xffff, 0), 136 Parent: HANDLE_INGRESS, 137 }, 138 } 139 if err := QdiscAdd(qdisc); err != nil { 140 t.Fatal(err) 141 } 142 143 filter := &U32{ 144 FilterAttrs: FilterAttrs{ 145 LinkIndex: link.Attrs().Index, 146 Parent: MakeHandle(0xffff, 0), 147 Priority: 1, 148 Protocol: unix.ETH_P_IP, 149 }, 150 RedirIndex: redir.Attrs().Index, 151 ClassId: MakeHandle(1, 1), 152 } 153 154 if err := FilterReplace(filter); err != nil { 155 t.Fatal(err) 156 } 157 filters, err := FilterList(link, MakeHandle(0xffff, 0)) 158 if err != nil { 159 t.Fatal(err) 160 } 161 if len(filters) != 1 { 162 t.Fatal("Failed replace filter") 163 } 164 165 if err := FilterReplace(filter); err != nil { 166 t.Fatal(err) 167 } 168 } 169 170 func TestAdvancedFilterAddDel(t *testing.T) { 171 tearDown := setUpNetlinkTest(t) 172 defer tearDown() 173 if err := LinkAdd(&Ifb{LinkAttrs{Name: "baz"}}); err != nil { 174 t.Fatal(err) 175 } 176 link, err := LinkByName("baz") 177 if err != nil { 178 t.Fatal(err) 179 } 180 if err := LinkSetUp(link); err != nil { 181 t.Fatal(err) 182 } 183 index := link.Attrs().Index 184 185 qdiscHandle := MakeHandle(0x1, 0x0) 186 qdiscAttrs := QdiscAttrs{ 187 LinkIndex: index, 188 Handle: qdiscHandle, 189 Parent: HANDLE_ROOT, 190 } 191 192 qdisc := NewHtb(qdiscAttrs) 193 if err := QdiscAdd(qdisc); err != nil { 194 t.Fatal(err) 195 } 196 qdiscs, err := SafeQdiscList(link) 197 if err != nil { 198 t.Fatal(err) 199 } 200 if len(qdiscs) != 1 { 201 t.Fatal("Failed to add qdisc") 202 } 203 _, ok := qdiscs[0].(*Htb) 204 if !ok { 205 t.Fatal("Qdisc is the wrong type") 206 } 207 208 classId := MakeHandle(0x1, 0x46cb) 209 classAttrs := ClassAttrs{ 210 LinkIndex: index, 211 Parent: qdiscHandle, 212 Handle: classId, 213 } 214 htbClassAttrs := HtbClassAttrs{ 215 Rate: 512 * 1024, 216 Buffer: 32 * 1024, 217 } 218 htbClass := NewHtbClass(classAttrs, htbClassAttrs) 219 if err = ClassReplace(htbClass); err != nil { 220 t.Fatalf("Failed to add a HTB class: %v", err) 221 } 222 classes, err := SafeClassList(link, qdiscHandle) 223 if err != nil { 224 t.Fatal(err) 225 } 226 if len(classes) != 1 { 227 t.Fatal("Failed to add class") 228 } 229 _, ok = classes[0].(*HtbClass) 230 if !ok { 231 t.Fatal("Class is the wrong type") 232 } 233 234 htid := MakeHandle(0x0010, 0000) 235 divisor := uint32(1) 236 hashTable := &U32{ 237 FilterAttrs: FilterAttrs{ 238 LinkIndex: index, 239 Handle: htid, 240 Parent: qdiscHandle, 241 Priority: 1, 242 Protocol: unix.ETH_P_ALL, 243 }, 244 Divisor: divisor, 245 } 246 cHashTable := *hashTable 247 if err := FilterAdd(hashTable); err != nil { 248 t.Fatal(err) 249 } 250 // Check if the hash table is identical before and after FilterAdd. 251 if !reflect.DeepEqual(cHashTable, *hashTable) { 252 t.Fatalf("Hash table %v and %v are not equal", cHashTable, *hashTable) 253 } 254 255 u32SelKeys := []TcU32Key{ 256 { 257 Mask: 0xff, 258 Val: 80, 259 Off: 20, 260 OffMask: 0, 261 }, 262 { 263 Mask: 0xffff, 264 Val: 0x146ca, 265 Off: 32, 266 OffMask: 0, 267 }, 268 } 269 270 handle := MakeHandle(0x0000, 0001) 271 filter := &U32{ 272 FilterAttrs: FilterAttrs{ 273 LinkIndex: index, 274 Handle: handle, 275 Parent: qdiscHandle, 276 Priority: 1, 277 Protocol: unix.ETH_P_ALL, 278 }, 279 Sel: &TcU32Sel{ 280 Keys: u32SelKeys, 281 Flags: TC_U32_TERMINAL, 282 }, 283 ClassId: classId, 284 Hash: htid, 285 Actions: []Action{}, 286 } 287 // Copy filter. 288 cFilter := *filter 289 if err := FilterAdd(filter); err != nil { 290 t.Fatal(err) 291 } 292 // Check if the filter is identical before and after FilterAdd. 293 if !reflect.DeepEqual(cFilter, *filter) { 294 t.Fatalf("U32 %v and %v are not equal", cFilter, *filter) 295 } 296 297 filters, err := FilterList(link, qdiscHandle) 298 if err != nil { 299 t.Fatal(err) 300 } 301 if len(filters) != 1 { 302 t.Fatal("Failed to add filter") 303 } 304 305 u32, ok := filters[0].(*U32) 306 if !ok { 307 t.Fatal("Filter is the wrong type") 308 } 309 // Endianness checks 310 if u32.Sel.Offmask != filter.Sel.Offmask { 311 t.Fatal("The endianness of TcU32Key.Sel.Offmask is wrong") 312 } 313 if u32.Sel.Hmask != filter.Sel.Hmask { 314 t.Fatal("The endianness of TcU32Key.Sel.Hmask is wrong") 315 } 316 for i, key := range u32.Sel.Keys { 317 if key.Mask != filter.Sel.Keys[i].Mask { 318 t.Fatal("The endianness of TcU32Key.Mask is wrong") 319 } 320 if key.Val != filter.Sel.Keys[i].Val { 321 t.Fatal("The endianness of TcU32Key.Val is wrong") 322 } 323 } 324 if u32.Handle != (handle | htid) { 325 t.Fatalf("The handle is wrong. expected %v but actually %v", 326 (handle | htid), u32.Handle) 327 } 328 if u32.Hash != htid { 329 t.Fatal("The hash table ID is wrong") 330 } 331 332 if err := FilterDel(u32); err != nil { 333 t.Fatal(err) 334 } 335 filters, err = FilterList(link, qdiscHandle) 336 if err != nil { 337 t.Fatal(err) 338 } 339 if len(filters) != 0 { 340 t.Fatal("Failed to remove filter") 341 } 342 343 if err = ClassDel(htbClass); err != nil { 344 t.Fatalf("Failed to delete a HTP class: %v", err) 345 } 346 classes, err = SafeClassList(link, qdiscHandle) 347 if err != nil { 348 t.Fatal(err) 349 } 350 if len(classes) != 0 { 351 t.Fatal("Failed to remove class") 352 } 353 354 if err := QdiscDel(qdisc); err != nil { 355 t.Fatal(err) 356 } 357 qdiscs, err = SafeQdiscList(link) 358 if err != nil { 359 t.Fatal(err) 360 } 361 if len(qdiscs) != 0 { 362 t.Fatal("Failed to remove qdisc") 363 } 364 } 365 366 func TestFilterFwAddDel(t *testing.T) { 367 tearDown := setUpNetlinkTest(t) 368 defer tearDown() 369 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 370 t.Fatal(err) 371 } 372 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil { 373 t.Fatal(err) 374 } 375 link, err := LinkByName("foo") 376 if err != nil { 377 t.Fatal(err) 378 } 379 if err := LinkSetUp(link); err != nil { 380 t.Fatal(err) 381 } 382 redir, err := LinkByName("bar") 383 if err != nil { 384 t.Fatal(err) 385 } 386 if err := LinkSetUp(redir); err != nil { 387 t.Fatal(err) 388 } 389 attrs := QdiscAttrs{ 390 LinkIndex: link.Attrs().Index, 391 Handle: MakeHandle(0xffff, 0), 392 Parent: HANDLE_ROOT, 393 } 394 qdisc := NewHtb(attrs) 395 if err := QdiscAdd(qdisc); err != nil { 396 t.Fatal(err) 397 } 398 qdiscs, err := SafeQdiscList(link) 399 if err != nil { 400 t.Fatal(err) 401 } 402 if len(qdiscs) != 1 { 403 t.Fatal("Failed to add qdisc") 404 } 405 _, ok := qdiscs[0].(*Htb) 406 if !ok { 407 t.Fatal("Qdisc is the wrong type") 408 } 409 410 classattrs := ClassAttrs{ 411 LinkIndex: link.Attrs().Index, 412 Parent: MakeHandle(0xffff, 0), 413 Handle: MakeHandle(0xffff, 2), 414 } 415 416 htbclassattrs := HtbClassAttrs{ 417 Rate: 1234000, 418 Cbuffer: 1690, 419 } 420 class := NewHtbClass(classattrs, htbclassattrs) 421 if err := ClassAdd(class); err != nil { 422 t.Fatal(err) 423 } 424 classes, err := SafeClassList(link, MakeHandle(0xffff, 2)) 425 if err != nil { 426 t.Fatal(err) 427 } 428 if len(classes) != 1 { 429 t.Fatal("Failed to add class") 430 } 431 432 police := NewPoliceAction() 433 police.Burst = 12345 434 police.Rate = 1234 435 police.PeakRate = 2345 436 police.Action = TcAct(TC_POLICE_SHOT) 437 438 filterattrs := FilterAttrs{ 439 LinkIndex: link.Attrs().Index, 440 Parent: MakeHandle(0xffff, 0), 441 Handle: MakeHandle(0, 0x6), 442 Priority: 1, 443 Protocol: unix.ETH_P_IP, 444 } 445 446 filter := FwFilter{ 447 FilterAttrs: filterattrs, 448 ClassId: MakeHandle(0xffff, 2), 449 Police: police, 450 } 451 452 if err := FilterAdd(&filter); err != nil { 453 t.Fatal(err) 454 } 455 456 filters, err := FilterList(link, MakeHandle(0xffff, 0)) 457 if err != nil { 458 t.Fatal(err) 459 } 460 if len(filters) != 1 { 461 t.Fatal("Failed to add filter") 462 } 463 fw, ok := filters[0].(*FwFilter) 464 if !ok { 465 t.Fatal("Filter is the wrong type") 466 } 467 if fw.Police.Rate != filter.Police.Rate { 468 t.Fatal("Police Rate doesn't match") 469 } 470 if fw.ClassId != filter.ClassId { 471 t.Fatal("ClassId doesn't match") 472 } 473 if fw.InDev != filter.InDev { 474 t.Fatal("InDev doesn't match") 475 } 476 if fw.Police.AvRate != filter.Police.AvRate { 477 t.Fatal("AvRate doesn't match") 478 } 479 480 if err := FilterDel(&filter); err != nil { 481 t.Fatal(err) 482 } 483 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 484 if err != nil { 485 t.Fatal(err) 486 } 487 if len(filters) != 0 { 488 t.Fatal("Failed to remove filter") 489 } 490 if err := ClassDel(class); err != nil { 491 t.Fatal(err) 492 } 493 classes, err = SafeClassList(link, MakeHandle(0xffff, 0)) 494 if err != nil { 495 t.Fatal(err) 496 } 497 if len(classes) != 0 { 498 t.Fatal("Failed to remove class") 499 } 500 501 if err := QdiscDel(qdisc); err != nil { 502 t.Fatal(err) 503 } 504 qdiscs, err = SafeQdiscList(link) 505 if err != nil { 506 t.Fatal(err) 507 } 508 if len(qdiscs) != 0 { 509 t.Fatal("Failed to remove qdisc") 510 } 511 } 512 513 func TestFilterU32BpfAddDel(t *testing.T) { 514 t.Skipf("Fd does not match in ci") 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 fd, err := loadSimpleBpf(BPF_PROG_TYPE_SCHED_ACT, 1) 560 if err != nil { 561 t.Skipf("Loading bpf program failed: %s", err) 562 } 563 classId := MakeHandle(1, 1) 564 filter := &U32{ 565 FilterAttrs: FilterAttrs{ 566 LinkIndex: link.Attrs().Index, 567 Parent: MakeHandle(0xffff, 0), 568 Priority: 1, 569 Protocol: unix.ETH_P_ALL, 570 }, 571 ClassId: classId, 572 Actions: []Action{ 573 &BpfAction{Fd: fd, Name: "simple"}, 574 &MirredAction{ 575 ActionAttrs: ActionAttrs{ 576 Action: TC_ACT_STOLEN, 577 }, 578 MirredAction: TCA_EGRESS_REDIR, 579 Ifindex: redir.Attrs().Index, 580 }, 581 }, 582 } 583 584 if err := FilterAdd(filter); err != nil { 585 t.Fatal(err) 586 } 587 588 filters, err := FilterList(link, MakeHandle(0xffff, 0)) 589 if err != nil { 590 t.Fatal(err) 591 } 592 if len(filters) != 1 { 593 t.Fatal("Failed to add filter") 594 } 595 u32, ok := filters[0].(*U32) 596 if !ok { 597 t.Fatal("Filter is the wrong type") 598 } 599 600 if len(u32.Actions) != 2 { 601 t.Fatalf("Too few Actions in filter") 602 } 603 if u32.ClassId != classId { 604 t.Fatalf("ClassId of the filter is the wrong value") 605 } 606 607 // actions can be returned in reverse order 608 bpfAction, ok := u32.Actions[0].(*BpfAction) 609 if !ok { 610 bpfAction, ok = u32.Actions[1].(*BpfAction) 611 if !ok { 612 t.Fatal("Action is the wrong type") 613 } 614 } 615 if bpfAction.Fd != fd { 616 t.Fatalf("Action Fd does not match %d != %d", bpfAction.Fd, fd) 617 } 618 if _, ok := u32.Actions[0].(*MirredAction); !ok { 619 if _, ok := u32.Actions[1].(*MirredAction); !ok { 620 t.Fatal("Action is the wrong type") 621 } 622 } 623 624 if err := FilterDel(filter); err != nil { 625 t.Fatal(err) 626 } 627 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 628 if err != nil { 629 t.Fatal(err) 630 } 631 if len(filters) != 0 { 632 t.Fatal("Failed to remove filter") 633 } 634 635 if err := QdiscDel(qdisc); err != nil { 636 t.Fatal(err) 637 } 638 qdiscs, err = SafeQdiscList(link) 639 if err != nil { 640 t.Fatal(err) 641 } 642 if len(qdiscs) != 0 { 643 t.Fatal("Failed to remove qdisc") 644 } 645 } 646 647 func TestFilterU32ConnmarkAddDel(t *testing.T) { 648 tearDown := setUpNetlinkTest(t) 649 defer tearDown() 650 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 651 t.Fatal(err) 652 } 653 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil { 654 t.Fatal(err) 655 } 656 link, err := LinkByName("foo") 657 if err != nil { 658 t.Fatal(err) 659 } 660 if err := LinkSetUp(link); err != nil { 661 t.Fatal(err) 662 } 663 redir, err := LinkByName("bar") 664 if err != nil { 665 t.Fatal(err) 666 } 667 if err := LinkSetUp(redir); err != nil { 668 t.Fatal(err) 669 } 670 qdisc := &Ingress{ 671 QdiscAttrs: QdiscAttrs{ 672 LinkIndex: link.Attrs().Index, 673 Handle: MakeHandle(0xffff, 0), 674 Parent: HANDLE_INGRESS, 675 }, 676 } 677 if err := QdiscAdd(qdisc); err != nil { 678 t.Fatal(err) 679 } 680 qdiscs, err := SafeQdiscList(link) 681 if err != nil { 682 t.Fatal(err) 683 } 684 if len(qdiscs) != 1 { 685 t.Fatal("Failed to add qdisc") 686 } 687 _, ok := qdiscs[0].(*Ingress) 688 if !ok { 689 t.Fatal("Qdisc is the wrong type") 690 } 691 692 classId := MakeHandle(1, 1) 693 filter := &U32{ 694 FilterAttrs: FilterAttrs{ 695 LinkIndex: link.Attrs().Index, 696 Parent: MakeHandle(0xffff, 0), 697 Priority: 1, 698 Protocol: unix.ETH_P_ALL, 699 }, 700 ClassId: classId, 701 Actions: []Action{ 702 &ConnmarkAction{ 703 ActionAttrs: ActionAttrs{ 704 Action: TC_ACT_PIPE, 705 }, 706 }, 707 &MirredAction{ 708 ActionAttrs: ActionAttrs{ 709 Action: TC_ACT_STOLEN, 710 }, 711 MirredAction: TCA_EGRESS_REDIR, 712 Ifindex: redir.Attrs().Index, 713 }, 714 }, 715 } 716 717 if err := FilterAdd(filter); err != nil { 718 t.Fatal(err) 719 } 720 721 filters, err := FilterList(link, MakeHandle(0xffff, 0)) 722 if err != nil { 723 t.Fatal(err) 724 } 725 if len(filters) != 1 { 726 t.Fatal("Failed to add filter") 727 } 728 u32, ok := filters[0].(*U32) 729 if !ok { 730 t.Fatal("Filter is the wrong type") 731 } 732 733 if len(u32.Actions) != 2 { 734 t.Fatalf("Too few Actions in filter") 735 } 736 if u32.ClassId != classId { 737 t.Fatalf("ClassId of the filter is the wrong value") 738 } 739 740 // actions can be returned in reverse order 741 cma, ok := u32.Actions[0].(*ConnmarkAction) 742 if !ok { 743 cma, ok = u32.Actions[1].(*ConnmarkAction) 744 if !ok { 745 t.Fatal("Unable to find connmark action") 746 } 747 } 748 749 if cma.Attrs().Action != TC_ACT_PIPE { 750 t.Fatal("Connmark action isn't TC_ACT_PIPE") 751 } 752 753 mia, ok := u32.Actions[0].(*MirredAction) 754 if !ok { 755 mia, ok = u32.Actions[1].(*MirredAction) 756 if !ok { 757 t.Fatal("Unable to find mirred action") 758 } 759 } 760 761 if mia.Attrs().Action != TC_ACT_STOLEN { 762 t.Fatal("Mirred action isn't TC_ACT_STOLEN") 763 } 764 765 if err := FilterDel(filter); err != nil { 766 t.Fatal(err) 767 } 768 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 769 if err != nil { 770 t.Fatal(err) 771 } 772 if len(filters) != 0 { 773 t.Fatal("Failed to remove filter") 774 } 775 776 if err := QdiscDel(qdisc); err != nil { 777 t.Fatal(err) 778 } 779 qdiscs, err = SafeQdiscList(link) 780 if err != nil { 781 t.Fatal(err) 782 } 783 if len(qdiscs) != 0 { 784 t.Fatal("Failed to remove qdisc") 785 } 786 } 787 788 func TestFilterU32CsumAddDel(t *testing.T) { 789 tearDown := setUpNetlinkTest(t) 790 defer tearDown() 791 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 792 t.Fatalf("add link foo error: %v", err) 793 } 794 link, err := LinkByName("foo") 795 if err != nil { 796 t.Fatalf("add link foo error: %v", err) 797 } 798 if err := LinkSetUp(link); err != nil { 799 t.Fatalf("set foo link up error: %v", err) 800 } 801 802 qdisc := &Ingress{ 803 QdiscAttrs: QdiscAttrs{ 804 LinkIndex: link.Attrs().Index, 805 Handle: MakeHandle(0xffff, 0), 806 Parent: HANDLE_INGRESS, 807 }, 808 } 809 if err := QdiscAdd(qdisc); err != nil { 810 t.Fatal(err) 811 } 812 qdiscs, err := SafeQdiscList(link) 813 if err != nil { 814 t.Fatalf("get qdisc error: %v", err) 815 } 816 817 found := false 818 for _, v := range qdiscs { 819 if _, ok := v.(*Ingress); ok { 820 found = true 821 break 822 } 823 } 824 if !found { 825 t.Fatal("Qdisc is the wrong type") 826 } 827 828 classId := MakeHandle(1, 1) 829 filter := &U32{ 830 FilterAttrs: FilterAttrs{ 831 LinkIndex: link.Attrs().Index, 832 Parent: MakeHandle(0xffff, 0), 833 Priority: 1, 834 Protocol: unix.ETH_P_ALL, 835 }, 836 ClassId: classId, 837 Actions: []Action{ 838 &CsumAction{ 839 ActionAttrs: ActionAttrs{ 840 Action: TC_ACT_PIPE, 841 }, 842 UpdateFlags: TCA_CSUM_UPDATE_FLAG_TCP, 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.Fatalf("get filter error: %v", err) 854 } 855 856 if len(filters) != 1 { 857 t.Fatalf("the count filters error, expect: 1, acutal: %d", len(filters)) 858 } 859 860 ft, ok := filters[0].(*U32) 861 if !ok { 862 t.Fatal("Filter is the wrong type") 863 } 864 865 if ft.LinkIndex != link.Attrs().Index { 866 t.Fatal("link index error") 867 } 868 869 if len(ft.Actions) != 1 { 870 t.Fatalf("filter has wrong number of actions, expect: 1, acutal: %d", len(filters)) 871 } 872 873 csum, ok := ft.Actions[0].(*CsumAction) 874 if !ok { 875 t.Fatal("action is the wrong type") 876 } 877 878 if csum.Attrs().Action != TC_ACT_PIPE { 879 t.Fatal("Csum action isn't TC_ACT_PIPE") 880 } 881 882 if csum.UpdateFlags != TCA_CSUM_UPDATE_FLAG_TCP { 883 t.Fatalf("Csum action isn't TCA_CSUM_UPDATE_FLAG_TCP, got %d", csum.UpdateFlags) 884 } 885 886 if err := FilterDel(ft); err != nil { 887 t.Fatal(err) 888 } 889 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 890 if err != nil { 891 t.Fatal(err) 892 } 893 if len(filters) != 0 { 894 t.Fatal("Failed to remove filter") 895 } 896 897 if err := QdiscDel(qdisc); err != nil { 898 t.Fatal(err) 899 } 900 qdiscs, err = SafeQdiscList(link) 901 if err != nil { 902 t.Fatal(err) 903 } 904 905 found = false 906 for _, v := range qdiscs { 907 if _, ok := v.(*Ingress); ok { 908 found = true 909 break 910 } 911 } 912 if found { 913 t.Fatal("Failed to remove qdisc") 914 } 915 } 916 917 func setupLinkForTestWithQdisc(t *testing.T, linkName string) (Qdisc, Link) { 918 if err := LinkAdd(&Ifb{LinkAttrs{Name: linkName}}); err != nil { 919 t.Fatal(err) 920 } 921 link, err := LinkByName(linkName) 922 if err != nil { 923 t.Fatal(err) 924 } 925 if err := LinkSetUp(link); err != nil { 926 t.Fatal(err) 927 } 928 attrs := QdiscAttrs{ 929 LinkIndex: link.Attrs().Index, 930 Handle: MakeHandle(0xffff, 0), 931 Parent: HANDLE_CLSACT, 932 } 933 qdisc := &GenericQdisc{ 934 QdiscAttrs: attrs, 935 QdiscType: "clsact", 936 } 937 938 if err := QdiscAdd(qdisc); err != nil { 939 t.Fatal(err) 940 } 941 qdiscs, err := SafeQdiscList(link) 942 if err != nil { 943 t.Fatal(err) 944 } 945 if len(qdiscs) != 1 { 946 t.Fatal("Failed to add qdisc", len(qdiscs)) 947 } 948 if q, ok := qdiscs[0].(*GenericQdisc); !ok || q.Type() != "clsact" { 949 t.Fatal("qdisc is the wrong type") 950 } 951 return qdiscs[0], link 952 } 953 954 func TestFilterClsActBpfAddDel(t *testing.T) { 955 t.Skipf("Fd does not match in ci") 956 // This feature was added in kernel 4.5 957 minKernelRequired(t, 4, 5) 958 959 tearDown := setUpNetlinkTest(t) 960 defer tearDown() 961 962 qdisc, link := setupLinkForTestWithQdisc(t, "foo") 963 filterattrs := FilterAttrs{ 964 LinkIndex: link.Attrs().Index, 965 Parent: HANDLE_MIN_EGRESS, 966 Handle: MakeHandle(0, 1), 967 Protocol: unix.ETH_P_ALL, 968 Priority: 1, 969 } 970 fd, err := loadSimpleBpf(BPF_PROG_TYPE_SCHED_CLS, 1) 971 if err != nil { 972 t.Skipf("Loading bpf program failed: %s", err) 973 } 974 filter := &BpfFilter{ 975 FilterAttrs: filterattrs, 976 Fd: fd, 977 Name: "simple", 978 DirectAction: true, 979 } 980 if filter.Fd < 0 { 981 t.Skipf("Failed to load bpf program") 982 } 983 984 if err := FilterAdd(filter); err != nil { 985 t.Fatal(err) 986 } 987 988 filters, err := FilterList(link, HANDLE_MIN_EGRESS) 989 if err != nil { 990 t.Fatal(err) 991 } 992 if len(filters) != 1 { 993 t.Fatal("Failed to add filter") 994 } 995 bpf, ok := filters[0].(*BpfFilter) 996 if !ok { 997 t.Fatal("Filter is the wrong type") 998 } 999 1000 if bpf.Fd != filter.Fd { 1001 t.Fatal("Filter Fd does not match") 1002 } 1003 if bpf.DirectAction != filter.DirectAction { 1004 t.Fatal("Filter DirectAction does not match") 1005 } 1006 1007 if err := FilterDel(filter); err != nil { 1008 t.Fatal(err) 1009 } 1010 filters, err = FilterList(link, HANDLE_MIN_EGRESS) 1011 if err != nil { 1012 t.Fatal(err) 1013 } 1014 if len(filters) != 0 { 1015 t.Fatal("Failed to remove filter") 1016 } 1017 1018 if err := QdiscDel(qdisc); err != nil { 1019 t.Fatal(err) 1020 } 1021 qdiscs, err := SafeQdiscList(link) 1022 if err != nil { 1023 t.Fatal(err) 1024 } 1025 if len(qdiscs) != 0 { 1026 t.Fatal("Failed to remove qdisc") 1027 } 1028 } 1029 1030 func TestFilterMatchAllAddDel(t *testing.T) { 1031 // This classifier was added in kernel 4.7 1032 minKernelRequired(t, 4, 7) 1033 1034 tearDown := setUpNetlinkTest(t) 1035 defer tearDown() 1036 _, link := setupLinkForTestWithQdisc(t, "foo") 1037 _, link2 := setupLinkForTestWithQdisc(t, "bar") 1038 filter := &MatchAll{ 1039 FilterAttrs: FilterAttrs{ 1040 LinkIndex: link.Attrs().Index, 1041 Parent: HANDLE_MIN_EGRESS, 1042 Priority: 32000, 1043 Protocol: unix.ETH_P_ALL, 1044 }, 1045 Actions: []Action{ 1046 &MirredAction{ 1047 ActionAttrs: ActionAttrs{ 1048 Action: TC_ACT_STOLEN, 1049 }, 1050 MirredAction: TCA_EGRESS_REDIR, 1051 Ifindex: link2.Attrs().Index, 1052 }, 1053 }, 1054 } 1055 if err := FilterAdd(filter); err != nil { 1056 t.Fatal(err) 1057 } 1058 1059 filters, err := FilterList(link, HANDLE_MIN_EGRESS) 1060 if err != nil { 1061 t.Fatal(err) 1062 } 1063 if len(filters) != 1 { 1064 t.Fatal("Failed to add filter") 1065 } 1066 matchall, ok := filters[0].(*MatchAll) 1067 if !ok { 1068 t.Fatal("Filter is the wrong type") 1069 } 1070 1071 if matchall.Priority != 32000 { 1072 t.Fatal("Filter priority does not match") 1073 } 1074 1075 if len(matchall.Actions) != 1 { 1076 t.Fatal("Filter has no actions") 1077 } 1078 1079 mirredAction, ok := matchall.Actions[0].(*MirredAction) 1080 if !ok { 1081 t.Fatal("Action does not match") 1082 } 1083 1084 if mirredAction.Ifindex != link2.Attrs().Index { 1085 t.Fatal("Action ifindex does not match") 1086 } 1087 1088 if err := FilterDel(filter); err != nil { 1089 t.Fatal(err) 1090 } 1091 filters, err = FilterList(link, HANDLE_MIN_EGRESS) 1092 if err != nil { 1093 t.Fatal(err) 1094 } 1095 if len(filters) != 0 { 1096 t.Fatal("Failed to remove filter") 1097 } 1098 1099 } 1100 1101 func TestFilterU32TunnelKeyAddDel(t *testing.T) { 1102 tearDown := setUpNetlinkTest(t) 1103 defer tearDown() 1104 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 1105 t.Fatal(err) 1106 } 1107 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil { 1108 t.Fatal(err) 1109 } 1110 link, err := LinkByName("foo") 1111 if err != nil { 1112 t.Fatal(err) 1113 } 1114 if err := LinkSetUp(link); err != nil { 1115 t.Fatal(err) 1116 } 1117 redir, err := LinkByName("bar") 1118 if err != nil { 1119 t.Fatal(err) 1120 } 1121 if err := LinkSetUp(redir); err != nil { 1122 t.Fatal(err) 1123 } 1124 1125 qdisc := &Ingress{ 1126 QdiscAttrs: QdiscAttrs{ 1127 LinkIndex: link.Attrs().Index, 1128 Handle: MakeHandle(0xffff, 0), 1129 Parent: HANDLE_INGRESS, 1130 }, 1131 } 1132 if err := QdiscAdd(qdisc); err != nil { 1133 t.Fatal(err) 1134 } 1135 qdiscs, err := SafeQdiscList(link) 1136 if err != nil { 1137 t.Fatal(err) 1138 } 1139 1140 found := false 1141 for _, v := range qdiscs { 1142 if _, ok := v.(*Ingress); ok { 1143 found = true 1144 break 1145 } 1146 } 1147 if !found { 1148 t.Fatal("Qdisc is the wrong type") 1149 } 1150 1151 tunnelAct := NewTunnelKeyAction() 1152 tunnelAct.SrcAddr = net.IPv4(10, 10, 10, 1) 1153 tunnelAct.DstAddr = net.IPv4(10, 10, 10, 2) 1154 tunnelAct.KeyID = 0x01 1155 tunnelAct.Action = TCA_TUNNEL_KEY_SET 1156 tunnelAct.DestPort = 8472 1157 1158 classId := MakeHandle(1, 1) 1159 filter := &U32{ 1160 FilterAttrs: FilterAttrs{ 1161 LinkIndex: link.Attrs().Index, 1162 Parent: MakeHandle(0xffff, 0), 1163 Priority: 1, 1164 Protocol: unix.ETH_P_ALL, 1165 }, 1166 ClassId: classId, 1167 Actions: []Action{ 1168 tunnelAct, 1169 &MirredAction{ 1170 ActionAttrs: ActionAttrs{ 1171 Action: TC_ACT_STOLEN, 1172 }, 1173 MirredAction: TCA_EGRESS_REDIR, 1174 Ifindex: redir.Attrs().Index, 1175 }, 1176 }, 1177 } 1178 1179 if err := FilterAdd(filter); err != nil { 1180 t.Fatal(err) 1181 } 1182 1183 filters, err := FilterList(link, MakeHandle(0xffff, 0)) 1184 if err != nil { 1185 t.Fatal(err) 1186 } 1187 if len(filters) != 1 { 1188 t.Fatal("Failed to add filter") 1189 } 1190 u32, ok := filters[0].(*U32) 1191 if !ok { 1192 t.Fatal("Filter is the wrong type") 1193 } 1194 1195 if len(u32.Actions) != 2 { 1196 t.Fatalf("Too few Actions in filter") 1197 } 1198 if u32.ClassId != classId { 1199 t.Fatalf("ClassId of the filter is the wrong value") 1200 } 1201 1202 // actions can be returned in reverse order 1203 tun, ok := u32.Actions[0].(*TunnelKeyAction) 1204 if !ok { 1205 tun, ok = u32.Actions[1].(*TunnelKeyAction) 1206 if !ok { 1207 t.Fatal("Unable to find tunnel action") 1208 } 1209 } 1210 1211 if tun.Attrs().Action != TC_ACT_PIPE { 1212 t.Fatal("TunnelKey action isn't TC_ACT_PIPE") 1213 } 1214 if !tun.SrcAddr.Equal(tunnelAct.SrcAddr) { 1215 t.Fatal("Action SrcAddr doesn't match") 1216 } 1217 if !tun.DstAddr.Equal(tunnelAct.DstAddr) { 1218 t.Fatal("Action DstAddr doesn't match") 1219 } 1220 if tun.KeyID != tunnelAct.KeyID { 1221 t.Fatal("Action KeyID doesn't match") 1222 } 1223 if tun.DestPort != tunnelAct.DestPort { 1224 t.Fatal("Action DestPort doesn't match") 1225 } 1226 if tun.Action != tunnelAct.Action { 1227 t.Fatal("Action doesn't match") 1228 } 1229 1230 mia, ok := u32.Actions[0].(*MirredAction) 1231 if !ok { 1232 mia, ok = u32.Actions[1].(*MirredAction) 1233 if !ok { 1234 t.Fatal("Unable to find mirred action") 1235 } 1236 } 1237 1238 if mia.Attrs().Action != TC_ACT_STOLEN { 1239 t.Fatal("Mirred action isn't TC_ACT_STOLEN") 1240 } 1241 1242 if err := FilterDel(filter); err != nil { 1243 t.Fatal(err) 1244 } 1245 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 1246 if err != nil { 1247 t.Fatal(err) 1248 } 1249 if len(filters) != 0 { 1250 t.Fatal("Failed to remove filter") 1251 } 1252 1253 if err := QdiscDel(qdisc); err != nil { 1254 t.Fatal(err) 1255 } 1256 qdiscs, err = SafeQdiscList(link) 1257 if err != nil { 1258 t.Fatal(err) 1259 } 1260 1261 found = false 1262 for _, v := range qdiscs { 1263 if _, ok := v.(*Ingress); ok { 1264 found = true 1265 break 1266 } 1267 } 1268 if found { 1269 t.Fatal("Failed to remove qdisc") 1270 } 1271 } 1272 1273 func TestFilterU32SkbEditAddDel(t *testing.T) { 1274 tearDown := setUpNetlinkTest(t) 1275 defer tearDown() 1276 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 1277 t.Fatal(err) 1278 } 1279 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil { 1280 t.Fatal(err) 1281 } 1282 link, err := LinkByName("foo") 1283 if err != nil { 1284 t.Fatal(err) 1285 } 1286 if err := LinkSetUp(link); err != nil { 1287 t.Fatal(err) 1288 } 1289 redir, err := LinkByName("bar") 1290 if err != nil { 1291 t.Fatal(err) 1292 } 1293 if err := LinkSetUp(redir); err != nil { 1294 t.Fatal(err) 1295 } 1296 1297 qdisc := &Ingress{ 1298 QdiscAttrs: QdiscAttrs{ 1299 LinkIndex: link.Attrs().Index, 1300 Handle: MakeHandle(0xffff, 0), 1301 Parent: HANDLE_INGRESS, 1302 }, 1303 } 1304 if err := QdiscAdd(qdisc); err != nil { 1305 t.Fatal(err) 1306 } 1307 qdiscs, err := SafeQdiscList(link) 1308 if err != nil { 1309 t.Fatal(err) 1310 } 1311 1312 found := false 1313 for _, v := range qdiscs { 1314 if _, ok := v.(*Ingress); ok { 1315 found = true 1316 break 1317 } 1318 } 1319 if !found { 1320 t.Fatal("Qdisc is the wrong type") 1321 } 1322 1323 skbedit := NewSkbEditAction() 1324 ptype := uint16(unix.PACKET_HOST) 1325 skbedit.PType = &ptype 1326 priority := uint32(0xff) 1327 skbedit.Priority = &priority 1328 mark := uint32(0xfe) 1329 skbedit.Mark = &mark 1330 mapping := uint16(0xf) 1331 skbedit.QueueMapping = &mapping 1332 1333 classId := MakeHandle(1, 1) 1334 filter := &U32{ 1335 FilterAttrs: FilterAttrs{ 1336 LinkIndex: link.Attrs().Index, 1337 Parent: MakeHandle(0xffff, 0), 1338 Priority: 1, 1339 Protocol: unix.ETH_P_ALL, 1340 }, 1341 ClassId: classId, 1342 Actions: []Action{ 1343 skbedit, 1344 &MirredAction{ 1345 ActionAttrs: ActionAttrs{ 1346 Action: TC_ACT_STOLEN, 1347 }, 1348 MirredAction: TCA_EGRESS_REDIR, 1349 Ifindex: redir.Attrs().Index, 1350 }, 1351 }, 1352 } 1353 1354 if err := FilterAdd(filter); err != nil { 1355 t.Fatal(err) 1356 } 1357 1358 filters, err := FilterList(link, MakeHandle(0xffff, 0)) 1359 if err != nil { 1360 t.Fatal(err) 1361 } 1362 if len(filters) != 1 { 1363 t.Fatal("Failed to add filter") 1364 } 1365 u32, ok := filters[0].(*U32) 1366 if !ok { 1367 t.Fatal("Filter is the wrong type") 1368 } 1369 1370 if len(u32.Actions) != 2 { 1371 t.Fatalf("Too few Actions in filter") 1372 } 1373 if u32.ClassId != classId { 1374 t.Fatalf("ClassId of the filter is the wrong value") 1375 } 1376 1377 // actions can be returned in reverse order 1378 edit, ok := u32.Actions[0].(*SkbEditAction) 1379 if !ok { 1380 edit, ok = u32.Actions[1].(*SkbEditAction) 1381 if !ok { 1382 t.Fatal("Unable to find tunnel action") 1383 } 1384 } 1385 1386 if edit.Attrs().Action != TC_ACT_PIPE { 1387 t.Fatal("SkbEdit action isn't TC_ACT_PIPE") 1388 } 1389 if edit.PType == nil || *edit.PType != *skbedit.PType { 1390 t.Fatal("Action PType doesn't match") 1391 } 1392 if edit.QueueMapping == nil || *edit.QueueMapping != *skbedit.QueueMapping { 1393 t.Fatal("Action QueueMapping doesn't match") 1394 } 1395 if edit.Mark == nil || *edit.Mark != *skbedit.Mark { 1396 t.Fatal("Action Mark doesn't match") 1397 } 1398 if edit.Priority == nil || *edit.Priority != *skbedit.Priority { 1399 t.Fatal("Action Priority doesn't match") 1400 } 1401 1402 mia, ok := u32.Actions[0].(*MirredAction) 1403 if !ok { 1404 mia, ok = u32.Actions[1].(*MirredAction) 1405 if !ok { 1406 t.Fatal("Unable to find mirred action") 1407 } 1408 } 1409 1410 if mia.Attrs().Action != TC_ACT_STOLEN { 1411 t.Fatal("Mirred action isn't TC_ACT_STOLEN") 1412 } 1413 1414 if err := FilterDel(filter); err != nil { 1415 t.Fatal(err) 1416 } 1417 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 1418 if err != nil { 1419 t.Fatal(err) 1420 } 1421 if len(filters) != 0 { 1422 t.Fatal("Failed to remove filter") 1423 } 1424 1425 if err := QdiscDel(qdisc); err != nil { 1426 t.Fatal(err) 1427 } 1428 qdiscs, err = SafeQdiscList(link) 1429 if err != nil { 1430 t.Fatal(err) 1431 } 1432 1433 found = false 1434 for _, v := range qdiscs { 1435 if _, ok := v.(*Ingress); ok { 1436 found = true 1437 break 1438 } 1439 } 1440 if found { 1441 t.Fatal("Failed to remove qdisc") 1442 } 1443 } 1444 1445 func TestFilterU32LinkOption(t *testing.T) { 1446 tearDown := setUpNetlinkTest(t) 1447 defer tearDown() 1448 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 1449 t.Fatalf("add link foo error: %v", err) 1450 } 1451 link, err := LinkByName("foo") 1452 if err != nil { 1453 t.Fatalf("add link foo error: %v", err) 1454 } 1455 if err := LinkSetUp(link); err != nil { 1456 t.Fatalf("set foo link up error: %v", err) 1457 } 1458 1459 qdisc := &Ingress{ 1460 QdiscAttrs: QdiscAttrs{ 1461 LinkIndex: link.Attrs().Index, 1462 Handle: MakeHandle(0xffff, 0), 1463 Parent: HANDLE_INGRESS, 1464 }, 1465 } 1466 if err := QdiscAdd(qdisc); err != nil { 1467 t.Fatal(err) 1468 } 1469 qdiscs, err := SafeQdiscList(link) 1470 if err != nil { 1471 t.Fatalf("get qdisc error: %v", err) 1472 } 1473 1474 found := false 1475 for _, v := range qdiscs { 1476 if _, ok := v.(*Ingress); ok { 1477 found = true 1478 break 1479 } 1480 } 1481 if !found { 1482 t.Fatal("Qdisc is the wrong type") 1483 } 1484 1485 htid := uint32(10) 1486 size := uint32(8) 1487 priority := uint16(200) 1488 u32Table := &U32{ 1489 FilterAttrs: FilterAttrs{ 1490 LinkIndex: link.Attrs().Index, 1491 Handle: htid << 20, 1492 Parent: MakeHandle(0xffff, 0), 1493 Priority: priority, 1494 Protocol: unix.ETH_P_ALL, 1495 }, 1496 Divisor: size, 1497 } 1498 if err := FilterAdd(u32Table); err != nil { 1499 t.Fatal(err) 1500 } 1501 1502 u32 := &U32{ 1503 FilterAttrs: FilterAttrs{ 1504 LinkIndex: link.Attrs().Index, 1505 Parent: MakeHandle(0xffff, 0), 1506 Handle: 1, 1507 Priority: priority, 1508 Protocol: unix.ETH_P_ALL, 1509 }, 1510 Link: uint32(htid << 20), 1511 Sel: &TcU32Sel{ 1512 Nkeys: 1, 1513 Flags: TC_U32_TERMINAL | TC_U32_VAROFFSET, 1514 Hmask: 0x0000ff00, 1515 Hoff: 0, 1516 Offshift: 8, 1517 Keys: []TcU32Key{ 1518 { 1519 Mask: 0, 1520 Val: 0, 1521 Off: 0, 1522 }, 1523 }, 1524 }, 1525 } 1526 if err := FilterAdd(u32); err != nil { 1527 t.Fatal(err) 1528 } 1529 1530 filters, err := FilterList(link, MakeHandle(0xffff, 0)) 1531 if err != nil { 1532 t.Fatalf("get filter error: %v", err) 1533 } 1534 1535 if len(filters) != 1 { 1536 t.Fatalf("the count filters error, expect: 1, acutal: %d", len(filters)) 1537 } 1538 1539 ft, ok := filters[0].(*U32) 1540 if !ok { 1541 t.Fatal("Filter is the wrong type") 1542 } 1543 1544 if ft.LinkIndex != link.Attrs().Index { 1545 t.Fatal("link index error") 1546 } 1547 1548 if ft.Link != htid<<20 { 1549 t.Fatal("hash table id error") 1550 } 1551 1552 if ft.Priority != priority { 1553 t.Fatal("priority error") 1554 } 1555 1556 if err := FilterDel(ft); err != nil { 1557 t.Fatal(err) 1558 } 1559 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 1560 if err != nil { 1561 t.Fatal(err) 1562 } 1563 if len(filters) != 0 { 1564 t.Fatal("Failed to remove filter") 1565 } 1566 1567 if err := QdiscDel(qdisc); err != nil { 1568 t.Fatal(err) 1569 } 1570 qdiscs, err = SafeQdiscList(link) 1571 if err != nil { 1572 t.Fatal(err) 1573 } 1574 1575 found = false 1576 for _, v := range qdiscs { 1577 if _, ok := v.(*Ingress); ok { 1578 found = true 1579 break 1580 } 1581 } 1582 if found { 1583 t.Fatal("Failed to remove qdisc") 1584 } 1585 } 1586 1587 func TestFilterFlowerAddDel(t *testing.T) { 1588 tearDown := setUpNetlinkTest(t) 1589 defer tearDown() 1590 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 1591 t.Fatal(err) 1592 } 1593 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil { 1594 t.Fatal(err) 1595 } 1596 link, err := LinkByName("foo") 1597 if err != nil { 1598 t.Fatal(err) 1599 } 1600 if err := LinkSetUp(link); err != nil { 1601 t.Fatal(err) 1602 } 1603 redir, err := LinkByName("bar") 1604 if err != nil { 1605 t.Fatal(err) 1606 } 1607 if err := LinkSetUp(redir); err != nil { 1608 t.Fatal(err) 1609 } 1610 1611 qdisc := &Ingress{ 1612 QdiscAttrs: QdiscAttrs{ 1613 LinkIndex: link.Attrs().Index, 1614 Handle: MakeHandle(0xffff, 0), 1615 Parent: HANDLE_INGRESS, 1616 }, 1617 } 1618 if err := QdiscAdd(qdisc); err != nil { 1619 t.Fatal(err) 1620 } 1621 qdiscs, err := SafeQdiscList(link) 1622 if err != nil { 1623 t.Fatal(err) 1624 } 1625 1626 found := false 1627 for _, v := range qdiscs { 1628 if _, ok := v.(*Ingress); ok { 1629 found = true 1630 break 1631 } 1632 } 1633 if !found { 1634 t.Fatal("Qdisc is the wrong type") 1635 } 1636 1637 testMask := net.CIDRMask(24, 32) 1638 1639 filter := &Flower{ 1640 FilterAttrs: FilterAttrs{ 1641 LinkIndex: link.Attrs().Index, 1642 Parent: MakeHandle(0xffff, 0), 1643 Priority: 1, 1644 Protocol: unix.ETH_P_ALL, 1645 }, 1646 DestIP: net.ParseIP("1.0.0.1"), 1647 DestIPMask: testMask, 1648 SrcIP: net.ParseIP("2.0.0.1"), 1649 SrcIPMask: testMask, 1650 EthType: unix.ETH_P_IP, 1651 EncDestIP: net.ParseIP("3.0.0.1"), 1652 EncDestIPMask: testMask, 1653 EncSrcIP: net.ParseIP("4.0.0.1"), 1654 EncSrcIPMask: testMask, 1655 EncDestPort: 8472, 1656 EncKeyId: 1234, 1657 Actions: []Action{ 1658 &MirredAction{ 1659 ActionAttrs: ActionAttrs{ 1660 Action: TC_ACT_STOLEN, 1661 }, 1662 MirredAction: TCA_EGRESS_REDIR, 1663 Ifindex: redir.Attrs().Index, 1664 }, 1665 }, 1666 } 1667 1668 if err := FilterAdd(filter); err != nil { 1669 t.Fatal(err) 1670 } 1671 1672 filters, err := FilterList(link, MakeHandle(0xffff, 0)) 1673 if err != nil { 1674 t.Fatal(err) 1675 } 1676 if len(filters) != 1 { 1677 t.Fatal("Failed to add filter") 1678 } 1679 flower, ok := filters[0].(*Flower) 1680 if !ok { 1681 t.Fatal("Filter is the wrong type") 1682 } 1683 1684 if filter.EthType != flower.EthType { 1685 t.Fatalf("Flower EthType doesn't match") 1686 } 1687 if !filter.DestIP.Equal(flower.DestIP) { 1688 t.Fatalf("Flower DestIP doesn't match") 1689 } 1690 if !filter.SrcIP.Equal(flower.SrcIP) { 1691 t.Fatalf("Flower SrcIP doesn't match") 1692 } 1693 1694 if !reflect.DeepEqual(filter.DestIPMask, testMask) { 1695 t.Fatalf("Flower DestIPMask doesn't match") 1696 } 1697 if !reflect.DeepEqual(filter.SrcIPMask, testMask) { 1698 t.Fatalf("Flower SrcIPMask doesn't match") 1699 } 1700 1701 if !filter.EncDestIP.Equal(flower.EncDestIP) { 1702 t.Fatalf("Flower EncDestIP doesn't match") 1703 } 1704 if !filter.EncSrcIP.Equal(flower.EncSrcIP) { 1705 t.Fatalf("Flower EncSrcIP doesn't match") 1706 } 1707 if !reflect.DeepEqual(filter.EncDestIPMask, testMask) { 1708 t.Fatalf("Flower EncDestIPMask doesn't match") 1709 } 1710 if !reflect.DeepEqual(filter.EncSrcIPMask, testMask) { 1711 t.Fatalf("Flower EncSrcIPMask doesn't match") 1712 } 1713 if filter.EncKeyId != flower.EncKeyId { 1714 t.Fatalf("Flower EncKeyId doesn't match") 1715 } 1716 if filter.EncDestPort != flower.EncDestPort { 1717 t.Fatalf("Flower EncDestPort doesn't match") 1718 } 1719 1720 mia, ok := flower.Actions[0].(*MirredAction) 1721 if !ok { 1722 t.Fatal("Unable to find mirred action") 1723 } 1724 1725 if mia.Attrs().Action != TC_ACT_STOLEN { 1726 t.Fatal("Mirred action isn't TC_ACT_STOLEN") 1727 } 1728 1729 if err := FilterDel(filter); err != nil { 1730 t.Fatal(err) 1731 } 1732 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 1733 if err != nil { 1734 t.Fatal(err) 1735 } 1736 if len(filters) != 0 { 1737 t.Fatal("Failed to remove filter") 1738 } 1739 1740 if err := QdiscDel(qdisc); err != nil { 1741 t.Fatal(err) 1742 } 1743 qdiscs, err = SafeQdiscList(link) 1744 if err != nil { 1745 t.Fatal(err) 1746 } 1747 1748 found = false 1749 for _, v := range qdiscs { 1750 if _, ok := v.(*Ingress); ok { 1751 found = true 1752 break 1753 } 1754 } 1755 if found { 1756 t.Fatal("Failed to remove qdisc") 1757 } 1758 } 1759 1760 func TestFilterU32PoliceAddDel(t *testing.T) { 1761 tearDown := setUpNetlinkTest(t) 1762 defer tearDown() 1763 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 1764 t.Fatal(err) 1765 } 1766 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil { 1767 t.Fatal(err) 1768 } 1769 link, err := LinkByName("foo") 1770 if err != nil { 1771 t.Fatal(err) 1772 } 1773 if err := LinkSetUp(link); err != nil { 1774 t.Fatal(err) 1775 } 1776 redir, err := LinkByName("bar") 1777 if err != nil { 1778 t.Fatal(err) 1779 } 1780 if err := LinkSetUp(redir); err != nil { 1781 t.Fatal(err) 1782 } 1783 1784 qdisc := &Ingress{ 1785 QdiscAttrs: QdiscAttrs{ 1786 LinkIndex: link.Attrs().Index, 1787 Handle: MakeHandle(0xffff, 0), 1788 Parent: HANDLE_INGRESS, 1789 }, 1790 } 1791 if err := QdiscAdd(qdisc); err != nil { 1792 t.Fatal(err) 1793 } 1794 qdiscs, err := SafeQdiscList(link) 1795 if err != nil { 1796 t.Fatal(err) 1797 } 1798 1799 found := false 1800 for _, v := range qdiscs { 1801 if _, ok := v.(*Ingress); ok { 1802 found = true 1803 break 1804 } 1805 } 1806 if !found { 1807 t.Fatal("Qdisc is the wrong type") 1808 } 1809 1810 const ( 1811 policeRate = 0x40000000 // 1 Gbps 1812 policeBurst = 0x19000 // 100 KB 1813 policePeakRate = 0x4000 // 16 Kbps 1814 ) 1815 1816 police := NewPoliceAction() 1817 police.Rate = policeRate 1818 police.PeakRate = policePeakRate 1819 police.Burst = policeBurst 1820 police.ExceedAction = TC_POLICE_SHOT 1821 police.NotExceedAction = TC_POLICE_UNSPEC 1822 1823 classId := MakeHandle(1, 1) 1824 filter := &U32{ 1825 FilterAttrs: FilterAttrs{ 1826 LinkIndex: link.Attrs().Index, 1827 Parent: MakeHandle(0xffff, 0), 1828 Priority: 1, 1829 Protocol: unix.ETH_P_ALL, 1830 }, 1831 ClassId: classId, 1832 Actions: []Action{ 1833 police, 1834 &MirredAction{ 1835 ActionAttrs: ActionAttrs{ 1836 Action: TC_ACT_STOLEN, 1837 }, 1838 MirredAction: TCA_EGRESS_REDIR, 1839 Ifindex: redir.Attrs().Index, 1840 }, 1841 }, 1842 } 1843 1844 if err := FilterAdd(filter); err != nil { 1845 t.Fatal(err) 1846 } 1847 1848 filters, err := FilterList(link, MakeHandle(0xffff, 0)) 1849 if err != nil { 1850 t.Fatal(err) 1851 } 1852 if len(filters) != 1 { 1853 t.Fatal("Failed to add filter") 1854 } 1855 u32, ok := filters[0].(*U32) 1856 if !ok { 1857 t.Fatal("Filter is the wrong type") 1858 } 1859 1860 if len(u32.Actions) != 2 { 1861 t.Fatalf("Too few Actions in filter") 1862 } 1863 if u32.ClassId != classId { 1864 t.Fatalf("ClassId of the filter is the wrong value") 1865 } 1866 1867 // actions can be returned in reverse order 1868 p, ok := u32.Actions[0].(*PoliceAction) 1869 if !ok { 1870 p, ok = u32.Actions[1].(*PoliceAction) 1871 if !ok { 1872 t.Fatal("Unable to find police action") 1873 } 1874 } 1875 1876 if p.ExceedAction != TC_POLICE_SHOT { 1877 t.Fatal("Police ExceedAction isn't TC_POLICE_SHOT") 1878 } 1879 1880 if p.NotExceedAction != TC_POLICE_UNSPEC { 1881 t.Fatal("Police NotExceedAction isn't TC_POLICE_UNSPEC") 1882 } 1883 1884 if p.Rate != policeRate { 1885 t.Fatal("Action Rate doesn't match") 1886 } 1887 1888 if p.PeakRate != policePeakRate { 1889 t.Fatal("Action PeakRate doesn't match") 1890 } 1891 1892 if p.LinkLayer != nl.LINKLAYER_ETHERNET { 1893 t.Fatal("Action LinkLayer doesn't match") 1894 } 1895 1896 mia, ok := u32.Actions[0].(*MirredAction) 1897 if !ok { 1898 mia, ok = u32.Actions[1].(*MirredAction) 1899 if !ok { 1900 t.Fatal("Unable to find mirred action") 1901 } 1902 } 1903 1904 if mia.Attrs().Action != TC_ACT_STOLEN { 1905 t.Fatal("Mirred action isn't TC_ACT_STOLEN") 1906 } 1907 1908 if err := FilterDel(filter); err != nil { 1909 t.Fatal(err) 1910 } 1911 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 1912 if err != nil { 1913 t.Fatal(err) 1914 } 1915 if len(filters) != 0 { 1916 t.Fatal("Failed to remove filter") 1917 } 1918 1919 if err := QdiscDel(qdisc); err != nil { 1920 t.Fatal(err) 1921 } 1922 qdiscs, err = SafeQdiscList(link) 1923 if err != nil { 1924 t.Fatal(err) 1925 } 1926 1927 found = false 1928 for _, v := range qdiscs { 1929 if _, ok := v.(*Ingress); ok { 1930 found = true 1931 break 1932 } 1933 } 1934 if found { 1935 t.Fatal("Failed to remove qdisc") 1936 } 1937 }