github.com/vishvananda/netlink@v1.3.0/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 1772 ipproto := new(nl.IPProto) 1773 *ipproto = nl.IPPROTO_TCP 1774 1775 filter := &Flower{ 1776 FilterAttrs: FilterAttrs{ 1777 LinkIndex: link.Attrs().Index, 1778 Parent: MakeHandle(0xffff, 0), 1779 Priority: 1, 1780 Protocol: unix.ETH_P_ALL, 1781 }, 1782 DestIP: net.ParseIP("1.0.0.1"), 1783 DestIPMask: testMask, 1784 SrcIP: net.ParseIP("2.0.0.1"), 1785 SrcIPMask: testMask, 1786 EthType: unix.ETH_P_IP, 1787 EncDestIP: net.ParseIP("3.0.0.1"), 1788 EncDestIPMask: testMask, 1789 EncSrcIP: net.ParseIP("4.0.0.1"), 1790 EncSrcIPMask: testMask, 1791 EncDestPort: 8472, 1792 EncKeyId: 1234, 1793 IPProto: ipproto, 1794 DestPort: 1111, 1795 SrcPort: 1111, 1796 Actions: []Action{ 1797 &MirredAction{ 1798 ActionAttrs: ActionAttrs{ 1799 Action: TC_ACT_STOLEN, 1800 }, 1801 MirredAction: TCA_EGRESS_REDIR, 1802 Ifindex: redir.Attrs().Index, 1803 }, 1804 &GenericAction{ 1805 ActionAttrs: ActionAttrs{ 1806 Action: getTcActGotoChain(), 1807 }, 1808 Chain: 20, 1809 }, 1810 }, 1811 } 1812 1813 if err := FilterAdd(filter); err != nil { 1814 t.Fatal(err) 1815 } 1816 1817 time.Sleep(time.Second) 1818 filters, err := FilterList(link, MakeHandle(0xffff, 0)) 1819 if err != nil { 1820 t.Fatal(err) 1821 } 1822 if len(filters) != 1 { 1823 t.Fatal("Failed to add filter") 1824 } 1825 flower, ok := filters[0].(*Flower) 1826 if !ok { 1827 t.Fatal("Filter is the wrong type") 1828 } 1829 1830 if filter.EthType != flower.EthType { 1831 t.Fatalf("Flower EthType doesn't match") 1832 } 1833 if !filter.DestIP.Equal(flower.DestIP) { 1834 t.Fatalf("Flower DestIP doesn't match") 1835 } 1836 if !filter.SrcIP.Equal(flower.SrcIP) { 1837 t.Fatalf("Flower SrcIP doesn't match") 1838 } 1839 1840 if !reflect.DeepEqual(filter.DestIPMask, testMask) { 1841 t.Fatalf("Flower DestIPMask doesn't match") 1842 } 1843 if !reflect.DeepEqual(filter.SrcIPMask, testMask) { 1844 t.Fatalf("Flower SrcIPMask doesn't match") 1845 } 1846 1847 if !filter.EncDestIP.Equal(flower.EncDestIP) { 1848 t.Fatalf("Flower EncDestIP doesn't match") 1849 } 1850 if !filter.EncSrcIP.Equal(flower.EncSrcIP) { 1851 t.Fatalf("Flower EncSrcIP doesn't match") 1852 } 1853 if !reflect.DeepEqual(filter.EncDestIPMask, testMask) { 1854 t.Fatalf("Flower EncDestIPMask doesn't match") 1855 } 1856 if !reflect.DeepEqual(filter.EncSrcIPMask, testMask) { 1857 t.Fatalf("Flower EncSrcIPMask doesn't match") 1858 } 1859 if filter.EncKeyId != flower.EncKeyId { 1860 t.Fatalf("Flower EncKeyId doesn't match") 1861 } 1862 if filter.EncDestPort != flower.EncDestPort { 1863 t.Fatalf("Flower EncDestPort doesn't match") 1864 } 1865 if flower.IPProto == nil || *filter.IPProto != *flower.IPProto { 1866 t.Fatalf("Flower IPProto doesn't match") 1867 } 1868 if filter.DestPort != flower.DestPort { 1869 t.Fatalf("Flower DestPort doesn't match") 1870 } 1871 if filter.SrcPort != flower.SrcPort { 1872 t.Fatalf("Flower SrcPort doesn't match") 1873 } 1874 1875 mia, ok := flower.Actions[0].(*MirredAction) 1876 if !ok { 1877 t.Fatal("Unable to find mirred action") 1878 } 1879 1880 if mia.Attrs().Action != TC_ACT_STOLEN { 1881 t.Fatal("Mirred action isn't TC_ACT_STOLEN") 1882 } 1883 1884 if mia.Timestamp == nil || mia.Timestamp.Installed == 0 { 1885 t.Fatal("Incorrect mirred action timestamp") 1886 } 1887 1888 if mia.Statistics == nil { 1889 t.Fatal("Incorrect mirred action stats") 1890 } 1891 1892 ga, ok := flower.Actions[1].(*GenericAction) 1893 if !ok { 1894 t.Fatal("Unable to find generic action") 1895 } 1896 1897 if ga.Attrs().Action != getTcActGotoChain() { 1898 t.Fatal("Generic action isn't TC_ACT_GOTO_CHAIN") 1899 } 1900 1901 if ga.Timestamp == nil || ga.Timestamp.Installed == 0 { 1902 t.Fatal("Incorrect generic action timestamp") 1903 } 1904 1905 if ga.Statistics == nil { 1906 t.Fatal("Incorrect generic action stats") 1907 } 1908 1909 if err := FilterDel(filter); err != nil { 1910 t.Fatal(err) 1911 } 1912 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 1913 if err != nil { 1914 t.Fatal(err) 1915 } 1916 if len(filters) != 0 { 1917 t.Fatal("Failed to remove filter") 1918 } 1919 1920 if err := QdiscDel(qdisc); err != nil { 1921 t.Fatal(err) 1922 } 1923 qdiscs, err = SafeQdiscList(link) 1924 if err != nil { 1925 t.Fatal(err) 1926 } 1927 1928 found = false 1929 for _, v := range qdiscs { 1930 if _, ok := v.(*Ingress); ok { 1931 found = true 1932 break 1933 } 1934 } 1935 if found { 1936 t.Fatal("Failed to remove qdisc") 1937 } 1938 } 1939 1940 func TestFilterIPv6FlowerPedit(t *testing.T) { 1941 tearDown := setUpNetlinkTest(t) 1942 defer tearDown() 1943 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 1944 t.Fatal(err) 1945 } 1946 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil { 1947 t.Fatal(err) 1948 } 1949 link, err := LinkByName("foo") 1950 if err != nil { 1951 t.Fatal(err) 1952 } 1953 if err := LinkSetUp(link); err != nil { 1954 t.Fatal(err) 1955 } 1956 redir, err := LinkByName("bar") 1957 if err != nil { 1958 t.Fatal(err) 1959 } 1960 if err := LinkSetUp(redir); err != nil { 1961 t.Fatal(err) 1962 } 1963 1964 qdisc := &Ingress{ 1965 QdiscAttrs: QdiscAttrs{ 1966 LinkIndex: link.Attrs().Index, 1967 Handle: MakeHandle(0xffff, 0), 1968 Parent: HANDLE_INGRESS, 1969 }, 1970 } 1971 if err := QdiscAdd(qdisc); err != nil { 1972 t.Fatal(err) 1973 } 1974 qdiscs, err := SafeQdiscList(link) 1975 if err != nil { 1976 t.Fatal(err) 1977 } 1978 1979 found := false 1980 for _, v := range qdiscs { 1981 if _, ok := v.(*Ingress); ok { 1982 found = true 1983 break 1984 } 1985 } 1986 if !found { 1987 t.Fatal("Qdisc is the wrong type") 1988 } 1989 1990 testMask := net.CIDRMask(64, 128) 1991 1992 ipproto := new(nl.IPProto) 1993 *ipproto = nl.IPPROTO_TCP 1994 1995 filter := &Flower{ 1996 FilterAttrs: FilterAttrs{ 1997 LinkIndex: link.Attrs().Index, 1998 Parent: MakeHandle(0xffff, 0), 1999 Priority: 1, 2000 Protocol: unix.ETH_P_ALL, 2001 }, 2002 DestIP: net.ParseIP("ffff::fff1"), 2003 DestIPMask: testMask, 2004 EthType: unix.ETH_P_IPV6, 2005 IPProto: ipproto, 2006 DestPort: 6666, 2007 Actions: []Action{}, 2008 } 2009 2010 peditAction := NewPeditAction() 2011 peditAction.Proto = uint8(nl.IPPROTO_TCP) 2012 peditAction.SrcPort = 7777 2013 peditAction.SrcIP = net.ParseIP("ffff::fff2") 2014 filter.Actions = append(filter.Actions, peditAction) 2015 2016 miaAction := &MirredAction{ 2017 ActionAttrs: ActionAttrs{ 2018 Action: TC_ACT_REDIRECT, 2019 }, 2020 MirredAction: TCA_EGRESS_REDIR, 2021 Ifindex: redir.Attrs().Index, 2022 } 2023 filter.Actions = append(filter.Actions, miaAction) 2024 2025 if err := FilterAdd(filter); err != nil { 2026 t.Fatal(err) 2027 } 2028 2029 filters, err := FilterList(link, MakeHandle(0xffff, 0)) 2030 if err != nil { 2031 t.Fatal(err) 2032 } 2033 if len(filters) != 1 { 2034 t.Fatal("Failed to add filter") 2035 } 2036 flower, ok := filters[0].(*Flower) 2037 if !ok { 2038 t.Fatal("Filter is the wrong type") 2039 } 2040 2041 if filter.EthType != flower.EthType { 2042 t.Fatalf("Flower EthType doesn't match") 2043 } 2044 if !filter.DestIP.Equal(flower.DestIP) { 2045 t.Fatalf("Flower DestIP doesn't match") 2046 } 2047 2048 if !reflect.DeepEqual(filter.DestIPMask, testMask) { 2049 t.Fatalf("Flower DestIPMask doesn't match") 2050 } 2051 2052 if flower.IPProto == nil || *filter.IPProto != *flower.IPProto { 2053 t.Fatalf("Flower IPProto doesn't match") 2054 } 2055 if filter.DestPort != flower.DestPort { 2056 t.Fatalf("Flower DestPort doesn't match") 2057 } 2058 2059 _, ok = flower.Actions[0].(*PeditAction) 2060 if !ok { 2061 t.Fatal("Unable to find pedit action") 2062 } 2063 2064 _, ok = flower.Actions[1].(*MirredAction) 2065 if !ok { 2066 t.Fatal("Unable to find mirred action") 2067 } 2068 2069 if err := FilterDel(filter); err != nil { 2070 t.Fatal(err) 2071 } 2072 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 2073 if err != nil { 2074 t.Fatal(err) 2075 } 2076 if len(filters) != 0 { 2077 t.Fatal("Failed to remove filter") 2078 } 2079 2080 if err := QdiscDel(qdisc); err != nil { 2081 t.Fatal(err) 2082 } 2083 qdiscs, err = SafeQdiscList(link) 2084 if err != nil { 2085 t.Fatal(err) 2086 } 2087 2088 found = false 2089 for _, v := range qdiscs { 2090 if _, ok := v.(*Ingress); ok { 2091 found = true 2092 break 2093 } 2094 } 2095 if found { 2096 t.Fatal("Failed to remove qdisc") 2097 } 2098 } 2099 2100 func TestFilterU32PoliceAddDel(t *testing.T) { 2101 tearDown := setUpNetlinkTest(t) 2102 defer tearDown() 2103 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 2104 t.Fatal(err) 2105 } 2106 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil { 2107 t.Fatal(err) 2108 } 2109 link, err := LinkByName("foo") 2110 if err != nil { 2111 t.Fatal(err) 2112 } 2113 if err := LinkSetUp(link); err != nil { 2114 t.Fatal(err) 2115 } 2116 redir, err := LinkByName("bar") 2117 if err != nil { 2118 t.Fatal(err) 2119 } 2120 if err := LinkSetUp(redir); err != nil { 2121 t.Fatal(err) 2122 } 2123 2124 qdisc := &Ingress{ 2125 QdiscAttrs: QdiscAttrs{ 2126 LinkIndex: link.Attrs().Index, 2127 Handle: MakeHandle(0xffff, 0), 2128 Parent: HANDLE_INGRESS, 2129 }, 2130 } 2131 if err := QdiscAdd(qdisc); err != nil { 2132 t.Fatal(err) 2133 } 2134 qdiscs, err := SafeQdiscList(link) 2135 if err != nil { 2136 t.Fatal(err) 2137 } 2138 2139 found := false 2140 for _, v := range qdiscs { 2141 if _, ok := v.(*Ingress); ok { 2142 found = true 2143 break 2144 } 2145 } 2146 if !found { 2147 t.Fatal("Qdisc is the wrong type") 2148 } 2149 2150 const ( 2151 policeRate = 0x40000000 // 1 Gbps 2152 policeBurst = 0x19000 // 100 KB 2153 policePeakRate = 0x4000 // 16 Kbps 2154 ) 2155 2156 police := NewPoliceAction() 2157 police.Rate = policeRate 2158 police.PeakRate = policePeakRate 2159 police.Burst = policeBurst 2160 police.ExceedAction = TC_POLICE_SHOT 2161 police.NotExceedAction = TC_POLICE_UNSPEC 2162 2163 classId := MakeHandle(1, 1) 2164 filter := &U32{ 2165 FilterAttrs: FilterAttrs{ 2166 LinkIndex: link.Attrs().Index, 2167 Parent: MakeHandle(0xffff, 0), 2168 Priority: 1, 2169 Protocol: unix.ETH_P_ALL, 2170 }, 2171 ClassId: classId, 2172 Actions: []Action{ 2173 police, 2174 &MirredAction{ 2175 ActionAttrs: ActionAttrs{ 2176 Action: TC_ACT_STOLEN, 2177 }, 2178 MirredAction: TCA_EGRESS_REDIR, 2179 Ifindex: redir.Attrs().Index, 2180 }, 2181 }, 2182 } 2183 2184 if err := FilterAdd(filter); err != nil { 2185 t.Fatal(err) 2186 } 2187 2188 filters, err := FilterList(link, MakeHandle(0xffff, 0)) 2189 if err != nil { 2190 t.Fatal(err) 2191 } 2192 if len(filters) != 1 { 2193 t.Fatal("Failed to add filter") 2194 } 2195 u32, ok := filters[0].(*U32) 2196 if !ok { 2197 t.Fatal("Filter is the wrong type") 2198 } 2199 2200 if len(u32.Actions) != 2 { 2201 t.Fatalf("Too few Actions in filter") 2202 } 2203 if u32.ClassId != classId { 2204 t.Fatalf("ClassId of the filter is the wrong value") 2205 } 2206 2207 // actions can be returned in reverse order 2208 p, ok := u32.Actions[0].(*PoliceAction) 2209 if !ok { 2210 p, ok = u32.Actions[1].(*PoliceAction) 2211 if !ok { 2212 t.Fatal("Unable to find police action") 2213 } 2214 } 2215 2216 if p.ExceedAction != TC_POLICE_SHOT { 2217 t.Fatal("Police ExceedAction isn't TC_POLICE_SHOT") 2218 } 2219 2220 if p.NotExceedAction != TC_POLICE_UNSPEC { 2221 t.Fatal("Police NotExceedAction isn't TC_POLICE_UNSPEC") 2222 } 2223 2224 if p.Rate != policeRate { 2225 t.Fatal("Action Rate doesn't match") 2226 } 2227 2228 if p.PeakRate != policePeakRate { 2229 t.Fatal("Action PeakRate doesn't match") 2230 } 2231 2232 if p.LinkLayer != nl.LINKLAYER_ETHERNET { 2233 t.Fatal("Action LinkLayer doesn't match") 2234 } 2235 2236 mia, ok := u32.Actions[0].(*MirredAction) 2237 if !ok { 2238 mia, ok = u32.Actions[1].(*MirredAction) 2239 if !ok { 2240 t.Fatal("Unable to find mirred action") 2241 } 2242 } 2243 2244 if mia.Attrs().Action != TC_ACT_STOLEN { 2245 t.Fatal("Mirred action isn't TC_ACT_STOLEN") 2246 } 2247 2248 if err := FilterDel(filter); err != nil { 2249 t.Fatal(err) 2250 } 2251 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 2252 if err != nil { 2253 t.Fatal(err) 2254 } 2255 if len(filters) != 0 { 2256 t.Fatal("Failed to remove filter") 2257 } 2258 2259 if err := QdiscDel(qdisc); err != nil { 2260 t.Fatal(err) 2261 } 2262 qdiscs, err = SafeQdiscList(link) 2263 if err != nil { 2264 t.Fatal(err) 2265 } 2266 2267 found = false 2268 for _, v := range qdiscs { 2269 if _, ok := v.(*Ingress); ok { 2270 found = true 2271 break 2272 } 2273 } 2274 if found { 2275 t.Fatal("Failed to remove qdisc") 2276 } 2277 } 2278 2279 func TestFilterU32DirectPoliceAddDel(t *testing.T) { 2280 tearDown := setUpNetlinkTest(t) 2281 defer tearDown() 2282 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 2283 t.Fatal(err) 2284 } 2285 link, err := LinkByName("foo") 2286 if err != nil { 2287 t.Fatal(err) 2288 } 2289 if err := LinkSetUp(link); err != nil { 2290 t.Fatal(err) 2291 } 2292 2293 qdisc := &Ingress{ 2294 QdiscAttrs: QdiscAttrs{ 2295 LinkIndex: link.Attrs().Index, 2296 Handle: MakeHandle(0xffff, 0), 2297 Parent: HANDLE_INGRESS, 2298 }, 2299 } 2300 if err := QdiscAdd(qdisc); err != nil { 2301 t.Fatal(err) 2302 } 2303 2304 const ( 2305 policeRate = 0x40000000 // 1 Gbps 2306 policeBurst = 0x19000 // 100 KB 2307 policePeakRate = 0x4000 // 16 Kbps 2308 ) 2309 2310 police := NewPoliceAction() 2311 police.Rate = policeRate 2312 police.PeakRate = policePeakRate 2313 police.Burst = policeBurst 2314 police.ExceedAction = TC_POLICE_SHOT 2315 police.NotExceedAction = TC_POLICE_UNSPEC 2316 2317 classId := MakeHandle(1, 1) 2318 filter := &U32{ 2319 FilterAttrs: FilterAttrs{ 2320 LinkIndex: link.Attrs().Index, 2321 Parent: MakeHandle(0xffff, 0), 2322 Priority: 1, 2323 Protocol: unix.ETH_P_ALL, 2324 }, 2325 ClassId: classId, 2326 Police: police, 2327 } 2328 2329 if err := FilterAdd(filter); err != nil { 2330 t.Fatal(err) 2331 } 2332 2333 filters, err := FilterList(link, MakeHandle(0xffff, 0)) 2334 if err != nil { 2335 t.Fatal(err) 2336 } 2337 if len(filters) != 1 { 2338 t.Fatal("Failed to add filter") 2339 } 2340 u32, ok := filters[0].(*U32) 2341 if !ok { 2342 t.Fatal("Filter is the wrong type") 2343 } 2344 2345 if u32.Police == nil { 2346 t.Fatalf("No police in filter") 2347 } 2348 2349 if u32.Police.Rate != policeRate { 2350 t.Fatal("Filter Rate doesn't match") 2351 } 2352 2353 if u32.Police.PeakRate != policePeakRate { 2354 t.Fatal("Filter PeakRate doesn't match") 2355 } 2356 2357 if u32.Police.LinkLayer != nl.LINKLAYER_ETHERNET { 2358 t.Fatal("Filter LinkLayer doesn't match") 2359 } 2360 2361 if err := QdiscDel(qdisc); err != nil { 2362 t.Fatal(err) 2363 } 2364 qdiscs, err := SafeQdiscList(link) 2365 if err != nil { 2366 t.Fatal(err) 2367 } 2368 2369 found := false 2370 for _, v := range qdiscs { 2371 if _, ok := v.(*Ingress); ok { 2372 found = true 2373 break 2374 } 2375 } 2376 if found { 2377 t.Fatal("Failed to remove qdisc") 2378 } 2379 } 2380 2381 func TestFilterChainAddDel(t *testing.T) { 2382 tearDown := setUpNetlinkTest(t) 2383 defer tearDown() 2384 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 2385 t.Fatal(err) 2386 } 2387 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil { 2388 t.Fatal(err) 2389 } 2390 link, err := LinkByName("foo") 2391 if err != nil { 2392 t.Fatal(err) 2393 } 2394 if err := LinkSetUp(link); err != nil { 2395 t.Fatal(err) 2396 } 2397 redir, err := LinkByName("bar") 2398 if err != nil { 2399 t.Fatal(err) 2400 } 2401 if err := LinkSetUp(redir); err != nil { 2402 t.Fatal(err) 2403 } 2404 qdisc := &Ingress{ 2405 QdiscAttrs: QdiscAttrs{ 2406 LinkIndex: link.Attrs().Index, 2407 Handle: MakeHandle(0xffff, 0), 2408 Parent: HANDLE_INGRESS, 2409 }, 2410 } 2411 if err := QdiscAdd(qdisc); err != nil { 2412 t.Fatal(err) 2413 } 2414 qdiscs, err := SafeQdiscList(link) 2415 if err != nil { 2416 t.Fatal(err) 2417 } 2418 if len(qdiscs) != 1 { 2419 t.Fatal("Failed to add qdisc") 2420 } 2421 _, ok := qdiscs[0].(*Ingress) 2422 if !ok { 2423 t.Fatal("Qdisc is the wrong type") 2424 } 2425 classId := MakeHandle(1, 1) 2426 chainVal := new(uint32) 2427 *chainVal = 20 2428 filter := &U32{ 2429 FilterAttrs: FilterAttrs{ 2430 LinkIndex: link.Attrs().Index, 2431 Parent: MakeHandle(0xffff, 0), 2432 Priority: 1, 2433 Protocol: unix.ETH_P_IP, 2434 Chain: chainVal, 2435 }, 2436 RedirIndex: redir.Attrs().Index, 2437 ClassId: classId, 2438 } 2439 if err := FilterAdd(filter); err != nil { 2440 t.Fatal(err) 2441 } 2442 filters, err := FilterList(link, MakeHandle(0xffff, 0)) 2443 if err != nil { 2444 t.Fatal(err) 2445 } 2446 if len(filters) != 1 { 2447 t.Fatal("Failed to add filter") 2448 } 2449 filterChain := filters[0].Attrs().Chain 2450 if filterChain != nil && *filterChain != *chainVal { 2451 t.Fatalf("Chain of the filter is the wrong value") 2452 } 2453 if err := FilterDel(filter); err != nil { 2454 t.Fatal(err) 2455 } 2456 filters, err = FilterList(link, MakeHandle(0xffff, 0)) 2457 if err != nil { 2458 t.Fatal(err) 2459 } 2460 if len(filters) != 0 { 2461 t.Fatal("Failed to remove filter") 2462 } 2463 if err := QdiscDel(qdisc); err != nil { 2464 t.Fatal(err) 2465 } 2466 qdiscs, err = SafeQdiscList(link) 2467 if err != nil { 2468 t.Fatal(err) 2469 } 2470 if len(qdiscs) != 0 { 2471 t.Fatal("Failed to remove qdisc") 2472 } 2473 }