github.com/sagernet/netlink@v0.0.0-20240612041022-b9a21c07ac6a/qdisc_test.go (about) 1 //go:build linux 2 // +build linux 3 4 package netlink 5 6 import ( 7 "testing" 8 ) 9 10 func TestTbfAddDel(t *testing.T) { 11 tearDown := setUpNetlinkTest(t) 12 defer tearDown() 13 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 14 t.Fatal(err) 15 } 16 link, err := LinkByName("foo") 17 if err != nil { 18 t.Fatal(err) 19 } 20 if err := LinkSetUp(link); err != nil { 21 t.Fatal(err) 22 } 23 qdisc := &Tbf{ 24 QdiscAttrs: QdiscAttrs{ 25 LinkIndex: link.Attrs().Index, 26 Handle: MakeHandle(1, 0), 27 Parent: HANDLE_ROOT, 28 }, 29 Rate: 131072, 30 Limit: 1220703, 31 Buffer: 16793, 32 } 33 if err := QdiscAdd(qdisc); err != nil { 34 t.Fatal(err) 35 } 36 qdiscs, err := SafeQdiscList(link) 37 if err != nil { 38 t.Fatal(err) 39 } 40 if len(qdiscs) != 1 { 41 t.Fatal("Failed to add qdisc") 42 } 43 tbf, ok := qdiscs[0].(*Tbf) 44 if !ok { 45 t.Fatal("Qdisc is the wrong type") 46 } 47 if tbf.Rate != qdisc.Rate { 48 t.Fatal("Rate doesn't match") 49 } 50 if tbf.Limit != qdisc.Limit { 51 t.Fatal("Limit doesn't match") 52 } 53 if tbf.Buffer != qdisc.Buffer { 54 t.Fatal("Buffer doesn't match") 55 } 56 if err := QdiscDel(qdisc); err != nil { 57 t.Fatal(err) 58 } 59 qdiscs, err = SafeQdiscList(link) 60 if err != nil { 61 t.Fatal(err) 62 } 63 if len(qdiscs) != 0 { 64 t.Fatal("Failed to remove qdisc") 65 } 66 } 67 68 func TestHtbAddDel(t *testing.T) { 69 tearDown := setUpNetlinkTest(t) 70 defer tearDown() 71 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 72 t.Fatal(err) 73 } 74 link, err := LinkByName("foo") 75 if err != nil { 76 t.Fatal(err) 77 } 78 if err := LinkSetUp(link); err != nil { 79 t.Fatal(err) 80 } 81 82 attrs := QdiscAttrs{ 83 LinkIndex: link.Attrs().Index, 84 Handle: MakeHandle(1, 0), 85 Parent: HANDLE_ROOT, 86 } 87 88 qdisc := NewHtb(attrs) 89 qdisc.Rate2Quantum = 5 90 if err := QdiscAdd(qdisc); err != nil { 91 t.Fatal(err) 92 } 93 94 qdiscs, err := SafeQdiscList(link) 95 if err != nil { 96 t.Fatal(err) 97 } 98 if len(qdiscs) != 1 { 99 t.Fatal("Failed to add qdisc") 100 } 101 htb, ok := qdiscs[0].(*Htb) 102 if !ok { 103 t.Fatal("Qdisc is the wrong type") 104 } 105 if htb.Defcls != qdisc.Defcls { 106 t.Fatal("Defcls doesn't match") 107 } 108 if htb.Rate2Quantum != qdisc.Rate2Quantum { 109 t.Fatal("Rate2Quantum doesn't match") 110 } 111 if htb.Debug != qdisc.Debug { 112 t.Fatal("Debug doesn't match") 113 } 114 if err := QdiscDel(qdisc); err != nil { 115 t.Fatal(err) 116 } 117 qdiscs, err = SafeQdiscList(link) 118 if err != nil { 119 t.Fatal(err) 120 } 121 if len(qdiscs) != 0 { 122 t.Fatal("Failed to remove qdisc") 123 } 124 } 125 126 func TestSfqAddDel(t *testing.T) { 127 tearDown := setUpNetlinkTestWithKModule(t, "sch_sfq") 128 defer tearDown() 129 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 130 t.Fatal(err) 131 } 132 link, err := LinkByName("foo") 133 if err != nil { 134 t.Fatal(err) 135 } 136 if err := LinkSetUp(link); err != nil { 137 t.Fatal(err) 138 } 139 140 attrs := QdiscAttrs{ 141 LinkIndex: link.Attrs().Index, 142 Handle: MakeHandle(1, 0), 143 Parent: HANDLE_ROOT, 144 } 145 146 qdisc := Sfq{ 147 QdiscAttrs: attrs, 148 Quantum: 2, 149 Perturb: 11, 150 Limit: 123, 151 Divisor: 4, 152 } 153 if err := QdiscAdd(&qdisc); err != nil { 154 t.Fatal(err) 155 } 156 157 qdiscs, err := SafeQdiscList(link) 158 if err != nil { 159 t.Fatal(err) 160 } 161 if len(qdiscs) != 1 { 162 t.Fatal("Failed to add qdisc") 163 } 164 sfq, ok := qdiscs[0].(*Sfq) 165 if !ok { 166 t.Fatal("Qdisc is the wrong type") 167 } 168 if sfq.Quantum != qdisc.Quantum { 169 t.Fatal("Quantum doesn't match") 170 } 171 if sfq.Perturb != qdisc.Perturb { 172 t.Fatal("Perturb doesn't match") 173 } 174 if sfq.Limit != qdisc.Limit { 175 t.Fatal("Limit doesn't match") 176 } 177 if sfq.Divisor != qdisc.Divisor { 178 t.Fatal("Divisor doesn't match") 179 } 180 if err := QdiscDel(&qdisc); err != nil { 181 t.Fatal(err) 182 } 183 qdiscs, err = SafeQdiscList(link) 184 if err != nil { 185 t.Fatal(err) 186 } 187 if len(qdiscs) != 0 { 188 t.Fatal("Failed to remove qdisc") 189 } 190 } 191 192 func TestPrioAddDel(t *testing.T) { 193 tearDown := setUpNetlinkTest(t) 194 defer tearDown() 195 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 196 t.Fatal(err) 197 } 198 link, err := LinkByName("foo") 199 if err != nil { 200 t.Fatal(err) 201 } 202 if err := LinkSetUp(link); err != nil { 203 t.Fatal(err) 204 } 205 qdisc := NewPrio(QdiscAttrs{ 206 LinkIndex: link.Attrs().Index, 207 Handle: MakeHandle(1, 0), 208 Parent: HANDLE_ROOT, 209 }) 210 if err := QdiscAdd(qdisc); err != nil { 211 t.Fatal(err) 212 } 213 qdiscs, err := SafeQdiscList(link) 214 if err != nil { 215 t.Fatal(err) 216 } 217 if len(qdiscs) != 1 { 218 t.Fatal("Failed to add qdisc") 219 } 220 _, ok := qdiscs[0].(*Prio) 221 if !ok { 222 t.Fatal("Qdisc is the wrong type") 223 } 224 if err := QdiscDel(qdisc); err != nil { 225 t.Fatal(err) 226 } 227 qdiscs, err = SafeQdiscList(link) 228 if err != nil { 229 t.Fatal(err) 230 } 231 if len(qdiscs) != 0 { 232 t.Fatal("Failed to remove qdisc") 233 } 234 } 235 236 func TestTbfAddHtbReplaceDel(t *testing.T) { 237 tearDown := setUpNetlinkTest(t) 238 defer tearDown() 239 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 240 t.Fatal(err) 241 } 242 link, err := LinkByName("foo") 243 if err != nil { 244 t.Fatal(err) 245 } 246 if err := LinkSetUp(link); err != nil { 247 t.Fatal(err) 248 } 249 250 // Add 251 attrs := QdiscAttrs{ 252 LinkIndex: link.Attrs().Index, 253 Handle: MakeHandle(1, 0), 254 Parent: HANDLE_ROOT, 255 } 256 qdisc := &Tbf{ 257 QdiscAttrs: attrs, 258 Rate: 131072, 259 Limit: 1220703, 260 Buffer: 16793, 261 } 262 if err := QdiscAdd(qdisc); err != nil { 263 t.Fatal(err) 264 } 265 qdiscs, err := SafeQdiscList(link) 266 if err != nil { 267 t.Fatal(err) 268 } 269 if len(qdiscs) != 1 { 270 t.Fatal("Failed to add qdisc") 271 } 272 tbf, ok := qdiscs[0].(*Tbf) 273 if !ok { 274 t.Fatal("Qdisc is the wrong type") 275 } 276 if tbf.Rate != qdisc.Rate { 277 t.Fatal("Rate doesn't match") 278 } 279 if tbf.Limit != qdisc.Limit { 280 t.Fatal("Limit doesn't match") 281 } 282 if tbf.Buffer != qdisc.Buffer { 283 t.Fatal("Buffer doesn't match") 284 } 285 // Replace 286 // For replace to work, the handle MUST be different that the running one 287 attrs.Handle = MakeHandle(2, 0) 288 qdisc2 := NewHtb(attrs) 289 qdisc2.Rate2Quantum = 5 290 if err := QdiscReplace(qdisc2); err != nil { 291 t.Fatal(err) 292 } 293 294 qdiscs, err = SafeQdiscList(link) 295 if err != nil { 296 t.Fatal(err) 297 } 298 if len(qdiscs) != 1 { 299 t.Fatal("Failed to add qdisc") 300 } 301 htb, ok := qdiscs[0].(*Htb) 302 if !ok { 303 t.Fatal("Qdisc is the wrong type") 304 } 305 if htb.Defcls != qdisc2.Defcls { 306 t.Fatal("Defcls doesn't match") 307 } 308 if htb.Rate2Quantum != qdisc2.Rate2Quantum { 309 t.Fatal("Rate2Quantum doesn't match") 310 } 311 if htb.Debug != qdisc2.Debug { 312 t.Fatal("Debug doesn't match") 313 } 314 315 if err := QdiscDel(qdisc2); err != nil { 316 t.Fatal(err) 317 } 318 qdiscs, err = SafeQdiscList(link) 319 if err != nil { 320 t.Fatal(err) 321 } 322 if len(qdiscs) != 0 { 323 t.Fatal("Failed to remove qdisc") 324 } 325 } 326 327 func TestTbfAddTbfChangeDel(t *testing.T) { 328 tearDown := setUpNetlinkTest(t) 329 defer tearDown() 330 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 331 t.Fatal(err) 332 } 333 link, err := LinkByName("foo") 334 if err != nil { 335 t.Fatal(err) 336 } 337 if err := LinkSetUp(link); err != nil { 338 t.Fatal(err) 339 } 340 341 // Add 342 attrs := QdiscAttrs{ 343 LinkIndex: link.Attrs().Index, 344 Handle: MakeHandle(1, 0), 345 Parent: HANDLE_ROOT, 346 } 347 qdisc := &Tbf{ 348 QdiscAttrs: attrs, 349 Rate: 131072, 350 Limit: 1220703, 351 Buffer: 16793, 352 } 353 if err := QdiscAdd(qdisc); err != nil { 354 t.Fatal(err) 355 } 356 qdiscs, err := SafeQdiscList(link) 357 if err != nil { 358 t.Fatal(err) 359 } 360 if len(qdiscs) != 1 { 361 t.Fatal("Failed to add qdisc") 362 } 363 tbf, ok := qdiscs[0].(*Tbf) 364 if !ok { 365 t.Fatal("Qdisc is the wrong type") 366 } 367 if tbf.Rate != qdisc.Rate { 368 t.Fatal("Rate doesn't match") 369 } 370 if tbf.Limit != qdisc.Limit { 371 t.Fatal("Limit doesn't match") 372 } 373 if tbf.Buffer != qdisc.Buffer { 374 t.Fatal("Buffer doesn't match") 375 } 376 // Change 377 // For change to work, the handle MUST not change 378 qdisc.Rate = 23456 379 if err := QdiscChange(qdisc); err != nil { 380 t.Fatal(err) 381 } 382 383 qdiscs, err = SafeQdiscList(link) 384 if err != nil { 385 t.Fatal(err) 386 } 387 if len(qdiscs) != 1 { 388 t.Fatal("Failed to add qdisc") 389 } 390 tbf, ok = qdiscs[0].(*Tbf) 391 if !ok { 392 t.Fatal("Qdisc is the wrong type") 393 } 394 if tbf.Rate != qdisc.Rate { 395 t.Fatal("Rate doesn't match") 396 } 397 if tbf.Limit != qdisc.Limit { 398 t.Fatal("Limit doesn't match") 399 } 400 if tbf.Buffer != qdisc.Buffer { 401 t.Fatal("Buffer doesn't match") 402 } 403 404 if err := QdiscDel(qdisc); err != nil { 405 t.Fatal(err) 406 } 407 qdiscs, err = SafeQdiscList(link) 408 if err != nil { 409 t.Fatal(err) 410 } 411 if len(qdiscs) != 0 { 412 t.Fatal("Failed to remove qdisc") 413 } 414 } 415 416 func TestFqAddChangeDel(t *testing.T) { 417 minKernelRequired(t, 3, 11) 418 419 tearDown := setUpNetlinkTest(t) 420 defer tearDown() 421 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 422 t.Fatal(err) 423 } 424 link, err := LinkByName("foo") 425 if err != nil { 426 t.Fatal(err) 427 } 428 if err := LinkSetUp(link); err != nil { 429 t.Fatal(err) 430 } 431 qdisc := &Fq{ 432 QdiscAttrs: QdiscAttrs{ 433 LinkIndex: link.Attrs().Index, 434 Handle: MakeHandle(1, 0), 435 Parent: HANDLE_ROOT, 436 }, 437 FlowPacketLimit: 123, 438 Pacing: 0, 439 } 440 if err := QdiscAdd(qdisc); err != nil { 441 t.Fatal(err) 442 } 443 qdiscs, err := SafeQdiscList(link) 444 if err != nil { 445 t.Fatal(err) 446 } 447 if len(qdiscs) != 1 { 448 t.Fatal("Failed to add qdisc") 449 } 450 fq, ok := qdiscs[0].(*Fq) 451 if !ok { 452 t.Fatal("Qdisc is the wrong type") 453 } 454 if fq.FlowPacketLimit != qdisc.FlowPacketLimit { 455 t.Fatal("Flow Packet Limit does not match") 456 } 457 if fq.Pacing != qdisc.Pacing { 458 t.Fatal("Pacing does not match") 459 } 460 461 if err := QdiscDel(qdisc); err != nil { 462 t.Fatal(err) 463 } 464 qdiscs, err = SafeQdiscList(link) 465 if err != nil { 466 t.Fatal(err) 467 } 468 if len(qdiscs) != 0 { 469 t.Fatal("Failed to remove qdisc") 470 } 471 } 472 473 func TestFqHorizon(t *testing.T) { 474 minKernelRequired(t, 5, 7) 475 476 tearDown := setUpNetlinkTest(t) 477 defer tearDown() 478 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 479 t.Fatal(err) 480 } 481 link, err := LinkByName("foo") 482 if err != nil { 483 t.Fatal(err) 484 } 485 if err := LinkSetUp(link); err != nil { 486 t.Fatal(err) 487 } 488 qdisc := &Fq{ 489 QdiscAttrs: QdiscAttrs{ 490 LinkIndex: link.Attrs().Index, 491 Handle: MakeHandle(1, 0), 492 Parent: HANDLE_ROOT, 493 }, 494 Horizon: 1000, 495 HorizonDropPolicy: HORIZON_DROP_POLICY_CAP, 496 } 497 if err := QdiscAdd(qdisc); err != nil { 498 t.Fatal(err) 499 } 500 qdiscs, err := SafeQdiscList(link) 501 if err != nil { 502 t.Fatal(err) 503 } 504 if len(qdiscs) != 1 { 505 t.Fatal("Failed to add qdisc") 506 } 507 fq, ok := qdiscs[0].(*Fq) 508 if !ok { 509 t.Fatal("Qdisc is the wrong type") 510 } 511 if fq.Horizon != qdisc.Horizon { 512 t.Fatal("Horizon does not match") 513 } 514 if fq.HorizonDropPolicy != qdisc.HorizonDropPolicy { 515 t.Fatal("HorizonDropPolicy does not match") 516 } 517 518 if err := QdiscDel(qdisc); err != nil { 519 t.Fatal(err) 520 } 521 qdiscs, err = SafeQdiscList(link) 522 if err != nil { 523 t.Fatal(err) 524 } 525 if len(qdiscs) != 0 { 526 t.Fatal("Failed to remove qdisc") 527 } 528 } 529 530 func TestFqCodelAddChangeDel(t *testing.T) { 531 minKernelRequired(t, 3, 4) 532 533 tearDown := setUpNetlinkTest(t) 534 defer tearDown() 535 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 536 t.Fatal(err) 537 } 538 link, err := LinkByName("foo") 539 if err != nil { 540 t.Fatal(err) 541 } 542 if err := LinkSetUp(link); err != nil { 543 t.Fatal(err) 544 } 545 qdisc := &FqCodel{ 546 QdiscAttrs: QdiscAttrs{ 547 LinkIndex: link.Attrs().Index, 548 Handle: MakeHandle(1, 0), 549 Parent: HANDLE_ROOT, 550 }, 551 ECN: 1, 552 Quantum: 9000, 553 } 554 if err := QdiscAdd(qdisc); err != nil { 555 t.Fatal(err) 556 } 557 qdiscs, err := SafeQdiscList(link) 558 if err != nil { 559 t.Fatal(err) 560 } 561 if len(qdiscs) != 1 { 562 t.Fatal("Failed to add qdisc") 563 } 564 fqcodel, ok := qdiscs[0].(*FqCodel) 565 if !ok { 566 t.Fatal("Qdisc is the wrong type") 567 } 568 if fqcodel.Quantum != qdisc.Quantum { 569 t.Fatal("Quantum does not match") 570 } 571 572 if err := QdiscDel(qdisc); err != nil { 573 t.Fatal(err) 574 } 575 qdiscs, err = SafeQdiscList(link) 576 if err != nil { 577 t.Fatal(err) 578 } 579 if len(qdiscs) != 0 { 580 t.Fatal("Failed to remove qdisc") 581 } 582 } 583 584 func TestIngressAddDel(t *testing.T) { 585 tearDown := setUpNetlinkTest(t) 586 defer tearDown() 587 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil { 588 t.Fatal(err) 589 } 590 link, err := LinkByName("foo") 591 if err != nil { 592 t.Fatal(err) 593 } 594 qdisc := &Ingress{ 595 QdiscAttrs: QdiscAttrs{ 596 LinkIndex: link.Attrs().Index, 597 Parent: HANDLE_INGRESS, 598 }, 599 } 600 err = QdiscAdd(qdisc) 601 if err != nil { 602 t.Fatal("Failed to add qdisc") 603 } 604 qdiscs, err := SafeQdiscList(link) 605 if err != nil { 606 t.Fatal("Failed to list qdisc") 607 } 608 if len(qdiscs) != 1 { 609 t.Fatal("Failed to add qdisc") 610 } 611 if err = QdiscDel(qdisc); err != nil { 612 t.Fatal(err) 613 } 614 qdiscs, err = SafeQdiscList(link) 615 if err != nil { 616 t.Fatal(err) 617 } 618 if len(qdiscs) != 0 { 619 t.Fatal("Failed to remove qdisc") 620 } 621 }