1
2
3
4 package netlink
5
6 import (
7 "reflect"
8 "testing"
9 )
10
11 func SafeQdiscList(link Link) ([]Qdisc, error) {
12 qdiscs, err := QdiscList(link)
13 if err != nil {
14 return nil, err
15 }
16 result := []Qdisc{}
17 for _, qdisc := range qdiscs {
18
19
20 attrs := qdisc.Attrs()
21 if attrs.Handle == HANDLE_NONE && attrs.Parent == HANDLE_ROOT {
22 continue
23 }
24 result = append(result, qdisc)
25 }
26 return result, nil
27 }
28
29 func SafeClassList(link Link, handle uint32) ([]Class, error) {
30 classes, err := ClassList(link, handle)
31 if err != nil {
32 return nil, err
33 }
34 result := []Class{}
35 for ind := range classes {
36 double := false
37 for _, class2 := range classes[ind+1:] {
38 if classes[ind].Attrs().Handle == class2.Attrs().Handle {
39 double = true
40 }
41 }
42 if !double {
43 result = append(result, classes[ind])
44 }
45 }
46 return result, nil
47 }
48
49 func testClassStats(this, that *ClassStatistics, t *testing.T) {
50 ok := reflect.DeepEqual(this, that)
51 if !ok {
52 t.Fatalf("%#v is expected but it actually was %#v", that, this)
53 }
54 }
55
56 func TestClassAddDel(t *testing.T) {
57 tearDown := setUpNetlinkTest(t)
58 defer tearDown()
59 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
60 t.Fatal(err)
61 }
62 if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
63 t.Fatal(err)
64 }
65 link, err := LinkByName("foo")
66 if err != nil {
67 t.Fatal(err)
68 }
69 if err := LinkSetUp(link); err != nil {
70 t.Fatal(err)
71 }
72 attrs := QdiscAttrs{
73 LinkIndex: link.Attrs().Index,
74 Handle: MakeHandle(0xffff, 0),
75 Parent: HANDLE_ROOT,
76 }
77 qdisc := NewHtb(attrs)
78 if err := QdiscAdd(qdisc); err != nil {
79 t.Fatal(err)
80 }
81 qdiscs, err := SafeQdiscList(link)
82 if err != nil {
83 t.Fatal(err)
84 }
85 if len(qdiscs) != 1 {
86 t.Fatal("Failed to add qdisc")
87 }
88 _, ok := qdiscs[0].(*Htb)
89 if !ok {
90 t.Fatal("Qdisc is the wrong type")
91 }
92
93 classattrs := ClassAttrs{
94 LinkIndex: link.Attrs().Index,
95 Parent: MakeHandle(0xffff, 0),
96 Handle: MakeHandle(0xffff, 2),
97 }
98
99 htbclassattrs := HtbClassAttrs{
100 Rate: 1234000,
101 Cbuffer: 1690,
102 Prio: 2,
103 Quantum: 1000,
104 }
105 class := NewHtbClass(classattrs, htbclassattrs)
106 if err := ClassAdd(class); err != nil {
107 t.Fatal(err)
108 }
109 classes, err := SafeClassList(link, MakeHandle(0xffff, 0))
110 if err != nil {
111 t.Fatal(err)
112 }
113 if len(classes) != 1 {
114 t.Fatal("Failed to add class")
115 }
116
117 htb, ok := classes[0].(*HtbClass)
118 if !ok {
119 t.Fatal("Class is the wrong type")
120 }
121 if htb.Rate != class.Rate {
122 t.Fatal("Rate doesn't match")
123 }
124 if htb.Ceil != class.Ceil {
125 t.Fatal("Ceil doesn't match")
126 }
127 if htb.Buffer != class.Buffer {
128 t.Fatal("Buffer doesn't match")
129 }
130 if htb.Cbuffer != class.Cbuffer {
131 t.Fatal("Cbuffer doesn't match")
132 }
133 if htb.Prio != class.Prio {
134 t.Fatal("Prio doesn't match")
135 }
136 if htb.Quantum != class.Quantum {
137 t.Fatal("Quantum doesn't match")
138 }
139
140 testClassStats(htb.ClassAttrs.Statistics, NewClassStatistics(), t)
141
142 qattrs := QdiscAttrs{
143 LinkIndex: link.Attrs().Index,
144 Handle: MakeHandle(0x2, 0),
145 Parent: MakeHandle(0xffff, 2),
146 }
147 nattrs := NetemQdiscAttrs{
148 Latency: 20000,
149 Loss: 23.4,
150 Duplicate: 14.3,
151 LossCorr: 8.34,
152 Jitter: 1000,
153 DelayCorr: 12.3,
154 ReorderProb: 23.4,
155 CorruptProb: 10.0,
156 CorruptCorr: 10,
157 Rate64: 10 * 1024 * 1024,
158 }
159 qdiscnetem := NewNetem(qattrs, nattrs)
160 if err := QdiscAdd(qdiscnetem); err != nil {
161 t.Fatal(err)
162 }
163
164 qdiscs, err = SafeQdiscList(link)
165 if err != nil {
166 t.Fatal(err)
167 }
168 if len(qdiscs) != 2 {
169 t.Fatal("Failed to add qdisc")
170 }
171 _, ok = qdiscs[0].(*Htb)
172 if !ok {
173 t.Fatal("Qdisc is the wrong type")
174 }
175
176 netem, ok := qdiscs[1].(*Netem)
177 if !ok {
178 t.Fatal("Qdisc is the wrong type")
179 }
180
181 if netem.Loss != qdiscnetem.Loss {
182 t.Fatal("Loss does not match")
183 }
184 if netem.Latency != qdiscnetem.Latency {
185 t.Fatal("Latency does not match")
186 }
187 if netem.CorruptProb != qdiscnetem.CorruptProb {
188 t.Fatal("CorruptProb does not match")
189 }
190 if netem.Jitter != qdiscnetem.Jitter {
191 t.Fatal("Jitter does not match")
192 }
193 if netem.LossCorr != qdiscnetem.LossCorr {
194 t.Fatal("Loss does not match")
195 }
196 if netem.DuplicateCorr != qdiscnetem.DuplicateCorr {
197 t.Fatal("DuplicateCorr does not match")
198 }
199 if netem.Rate64 != qdiscnetem.Rate64 {
200 t.Fatalf("Rate64 does not match. Expected %d, got %d", netem.Rate64, qdiscnetem.Rate64)
201 }
202
203
204
205 if err := ClassDel(class); err != nil {
206 t.Fatal(err)
207 }
208 classes, err = SafeClassList(link, MakeHandle(0xffff, 0))
209 if err != nil {
210 t.Fatal(err)
211 }
212 if len(classes) != 0 {
213 t.Fatal("Failed to remove class")
214 }
215 if err := QdiscDel(qdisc); err != nil {
216 t.Fatal(err)
217 }
218 qdiscs, err = SafeQdiscList(link)
219 if err != nil {
220 t.Fatal(err)
221 }
222 if len(qdiscs) != 0 {
223 t.Fatal("Failed to remove qdisc")
224 }
225 }
226
227 func TestHtbClassAddHtbClassChangeDel(t *testing.T) {
228
238 tearDown := setUpNetlinkTest(t)
239 defer tearDown()
240 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
241 t.Fatal(err)
242 }
243 link, err := LinkByName("foo")
244 if err != nil {
245 t.Fatal(err)
246 }
247 if err := LinkSetUp(link); err != nil {
248 t.Fatal(err)
249 }
250 attrs := QdiscAttrs{
251 LinkIndex: link.Attrs().Index,
252 Handle: MakeHandle(0xffff, 0),
253 Parent: HANDLE_ROOT,
254 }
255 qdisc := NewHtb(attrs)
256 if err := QdiscAdd(qdisc); err != nil {
257 t.Fatal(err)
258 }
259 qdiscs, err := SafeQdiscList(link)
260 if err != nil {
261 t.Fatal(err)
262 }
263 if len(qdiscs) != 1 {
264 t.Fatal("Failed to add qdisc")
265 }
266 _, ok := qdiscs[0].(*Htb)
267 if !ok {
268 t.Fatal("Qdisc is the wrong type")
269 }
270
271 classattrs := ClassAttrs{
272 LinkIndex: link.Attrs().Index,
273 Parent: MakeHandle(0xffff, 0),
274 Handle: MakeHandle(0xffff, 2),
275 }
276
277 htbclassattrs := HtbClassAttrs{
278 Rate: uint64(1<<32) + 10,
279 Ceil: uint64(1<<32) + 20,
280 Cbuffer: 1690,
281 }
282 class := NewHtbClass(classattrs, htbclassattrs)
283 if err := ClassAdd(class); err != nil {
284 t.Fatal(err)
285 }
286 classes, err := SafeClassList(link, 0)
287 if err != nil {
288 t.Fatal(err)
289 }
290 if len(classes) != 1 {
291 t.Fatal("Failed to add class")
292 }
293
294 htb, ok := classes[0].(*HtbClass)
295 if !ok {
296 t.Fatal("Class is the wrong type")
297 }
298
299 testClassStats(htb.ClassAttrs.Statistics, NewClassStatistics(), t)
300
301 qattrs := QdiscAttrs{
302 LinkIndex: link.Attrs().Index,
303 Handle: MakeHandle(0x2, 0),
304 Parent: MakeHandle(0xffff, 2),
305 }
306 nattrs := NetemQdiscAttrs{
307 Latency: 20000,
308 Loss: 23.4,
309 Duplicate: 14.3,
310 LossCorr: 8.34,
311 Jitter: 1000,
312 DelayCorr: 12.3,
313 ReorderProb: 23.4,
314 CorruptProb: 10.0,
315 CorruptCorr: 10,
316 }
317 qdiscnetem := NewNetem(qattrs, nattrs)
318 if err := QdiscAdd(qdiscnetem); err != nil {
319 t.Fatal(err)
320 }
321
322 qdiscs, err = SafeQdiscList(link)
323 if err != nil {
324 t.Fatal(err)
325 }
326 if len(qdiscs) != 2 {
327 t.Fatal("Failed to add qdisc")
328 }
329
330 _, ok = qdiscs[1].(*Netem)
331 if !ok {
332 t.Fatal("Qdisc is the wrong type")
333 }
334
335
336
337
338
339 oldHandle := classattrs.Handle
340 classattrs.Handle = MakeHandle(0xffff, 3)
341 class = NewHtbClass(classattrs, htbclassattrs)
342 if err := ClassChange(class); err == nil {
343 t.Fatal("ClassChange should not work when using a different handle.")
344 }
345
346 classattrs.Handle = oldHandle
347 htbclassattrs.Rate = 4321000
348 class = NewHtbClass(classattrs, htbclassattrs)
349 if err := ClassChange(class); err != nil {
350 t.Fatal(err)
351 }
352
353 classes, err = SafeClassList(link, MakeHandle(0xffff, 0))
354 if err != nil {
355 t.Fatal(err)
356 }
357 if len(classes) != 1 {
358 t.Fatalf(
359 "1 class expected, %d found",
360 len(classes),
361 )
362 }
363
364 htb, ok = classes[0].(*HtbClass)
365 if !ok {
366 t.Fatal("Class is the wrong type")
367 }
368
369 if htb.Rate != class.Rate {
370 t.Fatal("Rate did not get changed while changing the class.")
371 }
372
373
374 qdiscs, err = SafeQdiscList(link)
375 if err != nil {
376 t.Fatal(err)
377 }
378
379 if len(qdiscs) != 2 {
380 t.Fatalf("2 qdisc expected, %d found", len(qdiscs))
381 }
382 _, ok = qdiscs[0].(*Htb)
383 if !ok {
384 t.Fatal("Qdisc is the wrong type")
385 }
386
387 _, ok = qdiscs[1].(*Netem)
388 if !ok {
389 t.Fatal("Qdisc is the wrong type")
390 }
391
392
393
394
395
396
397 class = NewHtbClass(classattrs, htbclassattrs)
398 if err := ClassReplace(class); err != nil {
399 t.Fatal("Failed to replace class that is existing.")
400 }
401
402 classes, err = SafeClassList(link, MakeHandle(0xffff, 0))
403 if err != nil {
404 t.Fatal(err)
405 }
406 if len(classes) != 1 {
407 t.Fatalf(
408 "1 class expected, %d found",
409 len(classes),
410 )
411 }
412
413 htb, ok = classes[0].(*HtbClass)
414 if !ok {
415 t.Fatal("Class is the wrong type")
416 }
417
418 if htb.Rate != class.Rate {
419 t.Fatal("Rate did not get changed while changing the class.")
420 }
421
422
423 classattrs.Handle = MakeHandle(0xffff, 3)
424 class = NewHtbClass(classattrs, htbclassattrs)
425 if err := ClassReplace(class); err != nil {
426 t.Fatal(err)
427 }
428
429 classes, err = SafeClassList(link, MakeHandle(0xffff, 0))
430 if err != nil {
431 t.Fatal(err)
432 }
433 if len(classes) != 2 {
434 t.Fatalf(
435 "2 classes expected, %d found",
436 len(classes),
437 )
438 }
439
440 htb, ok = classes[1].(*HtbClass)
441 if !ok {
442 t.Fatal("Class is the wrong type")
443 }
444
445 if htb.Rate != class.Rate {
446 t.Fatal("Rate did not get changed while changing the class.")
447 }
448
449
450 for _, class := range classes {
451 if err := ClassDel(class); err != nil {
452 t.Fatal(err)
453 }
454 }
455
456 classes, err = SafeClassList(link, MakeHandle(0xffff, 0))
457 if err != nil {
458 t.Fatal(err)
459 }
460 if len(classes) != 0 {
461 t.Fatal("Failed to remove class")
462 }
463 if err := QdiscDel(qdisc); err != nil {
464 t.Fatal(err)
465 }
466 qdiscs, err = SafeQdiscList(link)
467 if err != nil {
468 t.Fatal(err)
469 }
470 if len(qdiscs) != 0 {
471 t.Fatal("Failed to remove qdisc")
472 }
473 }
474
475 func TestClassHfsc(t *testing.T) {
476
477 tearDown := setUpNetlinkTestWithKModule(t, "sch_hfsc")
478 defer tearDown()
479
480
481 if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
482 t.Fatal(err)
483 }
484 link, err := LinkByName("foo")
485 if err != nil {
486 t.Fatal(err)
487 }
488 if err := LinkSetUp(link); err != nil {
489 t.Fatal(err)
490 }
491
492
493 qdiscAttrs := QdiscAttrs{
494 LinkIndex: link.Attrs().Index,
495 Handle: MakeHandle(1, 0),
496 Parent: HANDLE_ROOT,
497 }
498 hfscQdisc := NewHfsc(qdiscAttrs)
499 hfscQdisc.Defcls = 2
500
501 err = QdiscAdd(hfscQdisc)
502 if 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) != 1 {
510 t.Fatal("Failed to add qdisc")
511 }
512 _, ok := qdiscs[0].(*Hfsc)
513 if !ok {
514 t.Fatal("Qdisc is the wrong type")
515 }
516
517
518 classAttrs := ClassAttrs{
519 LinkIndex: link.Attrs().Index,
520 Parent: MakeHandle(1, 0),
521 Handle: MakeHandle(1, 1),
522 }
523 hfscClass := NewHfscClass(classAttrs)
524 hfscClass.SetLS(5e6, 10, 5e6)
525
526 err = ClassAdd(hfscClass)
527 if err != nil {
528 t.Fatal(err)
529 }
530
531 hfscClass2 := hfscClass
532 hfscClass2.SetLS(0, 0, 0)
533 hfscClass2.Attrs().Parent = MakeHandle(1, 1)
534 hfscClass2.Attrs().Handle = MakeHandle(1, 2)
535 hfscClass2.SetRsc(0, 0, 2e6)
536
537 err = ClassAdd(hfscClass2)
538 if err != nil {
539 t.Fatal(err)
540 }
541
542 hfscClass3 := hfscClass
543 hfscClass3.SetLS(0, 0, 0)
544 hfscClass3.Attrs().Parent = MakeHandle(1, 1)
545 hfscClass3.Attrs().Handle = MakeHandle(1, 3)
546
547 err = ClassAdd(hfscClass3)
548 if err != nil {
549 t.Fatal(err)
550 }
551
552
553 classes, err := SafeClassList(link, MakeHandle(1, 0))
554 if err != nil {
555 t.Fatal(err)
556 }
557 if len(classes) != 4 {
558 t.Fatal("Failed to add classes")
559 }
560 for _, c := range classes {
561 class, ok := c.(*HfscClass)
562 if !ok {
563 t.Fatal("Wrong type of class")
564 }
565 if class.ClassAttrs.Handle == hfscClass.ClassAttrs.Handle {
566 if class.Fsc != hfscClass.Fsc {
567 t.Fatal("HfscClass FSC don't match")
568 }
569 if class.Usc != hfscClass.Usc {
570 t.Fatal("HfscClass USC don't match")
571 }
572 if class.Rsc != hfscClass.Rsc {
573 t.Fatal("HfscClass RSC don't match")
574 }
575 }
576 if class.ClassAttrs.Handle == hfscClass2.ClassAttrs.Handle {
577 if class.Fsc != hfscClass2.Fsc {
578 t.Fatal("HfscClass2 FSC don't match")
579 }
580 if class.Usc != hfscClass2.Usc {
581 t.Fatal("HfscClass2 USC don't match")
582 }
583 if class.Rsc != hfscClass2.Rsc {
584 t.Fatal("HfscClass2 RSC don't match")
585 }
586 }
587 if class.ClassAttrs.Handle == hfscClass3.ClassAttrs.Handle {
588 if class.Fsc != hfscClass3.Fsc {
589 t.Fatal("HfscClass3 FSC don't match")
590 }
591 if class.Usc != hfscClass3.Usc {
592 t.Fatal("HfscClass3 USC don't match")
593 }
594 if class.Rsc != hfscClass3.Rsc {
595 t.Fatal("HfscClass3 RSC don't match")
596 }
597 }
598 }
599
600
601 fqcodelAttrs := QdiscAttrs{
602 LinkIndex: link.Attrs().Index,
603 Parent: MakeHandle(1, 2),
604 Handle: MakeHandle(2, 0),
605 }
606 fqcodel1 := NewFqCodel(fqcodelAttrs)
607 fqcodel1.ECN = 0
608 fqcodel1.Limit = 1200
609 fqcodel1.Flows = 65535
610 fqcodel1.Target = 5
611
612 err = QdiscAdd(fqcodel1)
613 if err != nil {
614 t.Fatal(err)
615 }
616
617 fqcodel2 := fqcodel1
618 fqcodel2.Attrs().Handle = MakeHandle(3, 0)
619 fqcodel2.Attrs().Parent = MakeHandle(1, 3)
620
621 err = QdiscAdd(fqcodel2)
622 if err != nil {
623 t.Fatal(err)
624 }
625
626
627 qdiscs, _ = SafeQdiscList(link)
628 if len(qdiscs) != 3 {
629 t.Fatal("Failed to add qdisc")
630 }
631 for _, q := range qdiscs[1:] {
632 _, ok = q.(*FqCodel)
633 if !ok {
634 t.Fatal("Qdisc is the wrong type")
635 }
636 }
637
638
639 if err := ClassDel(hfscClass3); err != nil {
640 t.Fatal(err)
641 }
642
643 classes, err = SafeClassList(link, MakeHandle(1, 0))
644 if err != nil {
645 t.Fatal(err)
646 }
647 if len(classes) != 3 {
648 t.Fatal("Failed to delete classes")
649 }
650
651 qdiscs, _ = SafeQdiscList(link)
652 if len(qdiscs) != 2 {
653 t.Fatal("Failed to delete qdisc")
654 }
655
656
657 hfscClass2.SetRsc(0, 0, 0)
658 hfscClass2.SetSC(5e6, 100, 1e6)
659 hfscClass2.SetUL(6e6, 50, 2e6)
660 hfscClass2.Attrs().Handle = MakeHandle(1, 8)
661 if err := ClassChange(hfscClass2); err == nil {
662 t.Fatal("Class change shouldn't work with a different handle")
663 }
664 hfscClass2.Attrs().Handle = MakeHandle(1, 2)
665 if err := ClassChange(hfscClass2); err != nil {
666 t.Fatal(err)
667 }
668
669
670
671 hfscClass2.SetSC(6e6, 100, 2e6)
672 hfscClass2.SetUL(8e6, 500, 4e6)
673 hfscClass2.Attrs().Handle = MakeHandle(1, 8)
674 if err := ClassReplace(hfscClass2); err != nil {
675 t.Fatal(err)
676 }
677
678 hfscClass.SetLS(5e6, 200, 1e6)
679 if err := ClassChange(hfscClass); err != nil {
680 t.Fatal(err)
681 }
682
683 }
684
View as plain text