26
26
27
27
logfile = None
28
28
log_level = 1
29
+ skip_extack = False
29
30
bpf_test_dir = os .path .dirname (os .path .realpath (__file__ ))
30
31
pp = pprint .PrettyPrinter ()
31
32
devs = [] # devices we created for clean up
@@ -132,17 +133,28 @@ def rm(f):
132
133
if f in files :
133
134
files .remove (f )
134
135
135
- def tool (name , args , flags , JSON = True , ns = "" , fail = True ):
136
+ def tool (name , args , flags , JSON = True , ns = "" , fail = True , include_stderr = False ):
136
137
params = ""
137
138
if JSON :
138
139
params += "%s " % (flags ["json" ])
139
140
140
141
if ns != "" :
141
142
ns = "ip netns exec %s " % (ns )
142
143
143
- ret , out = cmd (ns + name + " " + params + args , fail = fail )
144
- if JSON and len (out .strip ()) != 0 :
145
- return ret , json .loads (out )
144
+ if include_stderr :
145
+ ret , stdout , stderr = cmd (ns + name + " " + params + args ,
146
+ fail = fail , include_stderr = True )
147
+ else :
148
+ ret , stdout = cmd (ns + name + " " + params + args ,
149
+ fail = fail , include_stderr = False )
150
+
151
+ if JSON and len (stdout .strip ()) != 0 :
152
+ out = json .loads (stdout )
153
+ else :
154
+ out = stdout
155
+
156
+ if include_stderr :
157
+ return ret , out , stderr
146
158
else :
147
159
return ret , out
148
160
@@ -181,13 +193,15 @@ def bpftool_map_list_wait(expected=0, n_retry=20):
181
193
time .sleep (0.05 )
182
194
raise Exception ("Time out waiting for map counts to stabilize want %d, have %d" % (expected , nmaps ))
183
195
184
- def ip (args , force = False , JSON = True , ns = "" , fail = True ):
196
+ def ip (args , force = False , JSON = True , ns = "" , fail = True , include_stderr = False ):
185
197
if force :
186
198
args = "-force " + args
187
- return tool ("ip" , args , {"json" :"-j" }, JSON = JSON , ns = ns , fail = fail )
199
+ return tool ("ip" , args , {"json" :"-j" }, JSON = JSON , ns = ns ,
200
+ fail = fail , include_stderr = include_stderr )
188
201
189
- def tc (args , JSON = True , ns = "" , fail = True ):
190
- return tool ("tc" , args , {"json" :"-p" }, JSON = JSON , ns = ns , fail = fail )
202
+ def tc (args , JSON = True , ns = "" , fail = True , include_stderr = False ):
203
+ return tool ("tc" , args , {"json" :"-p" }, JSON = JSON , ns = ns ,
204
+ fail = fail , include_stderr = include_stderr )
191
205
192
206
def ethtool (dev , opt , args , fail = True ):
193
207
return cmd ("ethtool %s %s %s" % (opt , dev ["ifname" ], args ), fail = fail )
@@ -348,13 +362,17 @@ def set_mtu(self, mtu, fail=True):
348
362
return ip ("link set dev %s mtu %d" % (self .dev ["ifname" ], mtu ),
349
363
fail = fail )
350
364
351
- def set_xdp (self , bpf , mode , force = False , JSON = True , fail = True ):
365
+ def set_xdp (self , bpf , mode , force = False , JSON = True ,
366
+ fail = True , include_stderr = False ):
352
367
return ip ("link set dev %s xdp%s %s" % (self .dev ["ifname" ], mode , bpf ),
353
- force = force , JSON = JSON , fail = fail )
368
+ force = force , JSON = JSON ,
369
+ fail = fail , include_stderr = include_stderr )
354
370
355
- def unset_xdp (self , mode , force = False , JSON = True , fail = True ):
371
+ def unset_xdp (self , mode , force = False , JSON = True ,
372
+ fail = True , include_stderr = False ):
356
373
return ip ("link set dev %s xdp%s off" % (self .dev ["ifname" ], mode ),
357
- force = force , JSON = JSON , fail = fail )
374
+ force = force , JSON = JSON ,
375
+ fail = fail , include_stderr = include_stderr )
358
376
359
377
def ip_link_show (self , xdp ):
360
378
_ , link = ip ("link show dev %s" % (self ['ifname' ]))
@@ -410,7 +428,7 @@ def tc_show_ingress(self, expected=None):
410
428
return filters
411
429
412
430
def cls_bpf_add_filter (self , bpf , da = False , skip_sw = False , skip_hw = False ,
413
- fail = True ):
431
+ fail = True , include_stderr = False ):
414
432
params = ""
415
433
if da :
416
434
params += " da"
@@ -419,7 +437,8 @@ def cls_bpf_add_filter(self, bpf, da=False, skip_sw=False, skip_hw=False,
419
437
if skip_hw :
420
438
params += " skip_hw"
421
439
return tc ("filter add dev %s ingress bpf %s %s" %
422
- (self ['ifname' ], bpf , params ), fail = fail )
440
+ (self ['ifname' ], bpf , params ),
441
+ fail = fail , include_stderr = include_stderr )
423
442
424
443
def set_ethtool_tc_offloads (self , enable , fail = True ):
425
444
args = "hw-tc-offload %s" % ("on" if enable else "off" )
@@ -491,6 +510,16 @@ def check_dev_info(other_ns, ns, prog_file=None, map_file=None, removed=False):
491
510
fail ("dev" not in m .keys (), "Device parameters not reported" )
492
511
fail (dev != m ["dev" ], "Map's device different than program's" )
493
512
513
+ def check_extack (output , reference , args ):
514
+ if skip_extack :
515
+ return
516
+ lines = output .split ("\n " )
517
+ comp = len (lines ) >= 2 and lines [1 ] == reference
518
+ fail (not comp , "Missing or incorrect netlink extack message" )
519
+
520
+ def check_extack_nsim (output , reference , args ):
521
+ check_extack (output , "Error: netdevsim: " + reference , args )
522
+
494
523
# Parse command line
495
524
parser = argparse .ArgumentParser ()
496
525
parser .add_argument ("--log" , help = "output verbose log to given file" )
@@ -527,6 +556,14 @@ def check_dev_info(other_ns, ns, prog_file=None, map_file=None, removed=False):
527
556
skip (ret != 0 , "sample %s/%s not found, please compile it" %
528
557
(bpf_test_dir , s ))
529
558
559
+ # Check if iproute2 is built with libmnl (needed by extack support)
560
+ _ , _ , err = cmd ("tc qdisc delete dev lo handle 0" ,
561
+ fail = False , include_stderr = True )
562
+ if err .find ("Error: Failed to find qdisc with specified handle." ) == - 1 :
563
+ print ("Warning: no extack message in iproute2 output, libmnl missing?" )
564
+ log ("Warning: no extack message in iproute2 output, libmnl missing?" , "" )
565
+ skip_extack = True
566
+
530
567
# Check if net namespaces seem to work
531
568
ns = mknetns ()
532
569
skip (ns is None , "Could not create a net namespace" )
@@ -558,8 +595,10 @@ def check_dev_info(other_ns, ns, prog_file=None, map_file=None, removed=False):
558
595
sim .tc_flush_filters ()
559
596
560
597
start_test ("Test TC offloads are off by default..." )
561
- ret , _ = sim .cls_bpf_add_filter (obj , skip_sw = True , fail = False )
598
+ ret , _ , err = sim .cls_bpf_add_filter (obj , skip_sw = True ,
599
+ fail = False , include_stderr = True )
562
600
fail (ret == 0 , "TC filter loaded without enabling TC offloads" )
601
+ check_extack (err , "Error: TC offload is disabled on net device." , args )
563
602
sim .wait_for_flush ()
564
603
565
604
sim .set_ethtool_tc_offloads (True )
@@ -587,8 +626,11 @@ def check_dev_info(other_ns, ns, prog_file=None, map_file=None, removed=False):
587
626
sim .dfs ["bpf_tc_non_bound_accept" ] = "N"
588
627
589
628
start_test ("Test TC cBPF unbound bytecode doesn't offload..." )
590
- ret , _ = sim .cls_bpf_add_filter (bytecode , skip_sw = True , fail = False )
629
+ ret , _ , err = sim .cls_bpf_add_filter (bytecode , skip_sw = True ,
630
+ fail = False , include_stderr = True )
591
631
fail (ret == 0 , "TC bytecode loaded for offload" )
632
+ check_extack_nsim (err , "netdevsim configured to reject unbound programs." ,
633
+ args )
592
634
sim .wait_for_flush ()
593
635
594
636
start_test ("Test TC offloads work..." )
@@ -669,16 +711,24 @@ def check_dev_info(other_ns, ns, prog_file=None, map_file=None, removed=False):
669
711
"Device parameters reported for non-offloaded program" )
670
712
671
713
start_test ("Test XDP prog replace with bad flags..." )
672
- ret , _ = sim .set_xdp (obj , "offload" , force = True , fail = False )
714
+ ret , _ , err = sim .set_xdp (obj , "offload" , force = True ,
715
+ fail = False , include_stderr = True )
673
716
fail (ret == 0 , "Replaced XDP program with a program in different mode" )
674
- ret , _ = sim .set_xdp (obj , "" , force = True , fail = False )
717
+ check_extack_nsim (err , "program loaded with different flags." , args )
718
+ ret , _ , err = sim .set_xdp (obj , "" , force = True ,
719
+ fail = False , include_stderr = True )
675
720
fail (ret == 0 , "Replaced XDP program with a program in different mode" )
721
+ check_extack_nsim (err , "program loaded with different flags." , args )
676
722
677
723
start_test ("Test XDP prog remove with bad flags..." )
678
- ret , _ = sim .unset_xdp ("offload" , force = True , fail = False )
724
+ ret , _ , err = sim .unset_xdp ("offload" , force = True ,
725
+ fail = False , include_stderr = True )
679
726
fail (ret == 0 , "Removed program with a bad mode mode" )
680
- ret , _ = sim .unset_xdp ("" , force = True , fail = False )
727
+ check_extack_nsim (err , "program loaded with different flags." , args )
728
+ ret , _ , err = sim .unset_xdp ("" , force = True ,
729
+ fail = False , include_stderr = True )
681
730
fail (ret == 0 , "Removed program with a bad mode mode" )
731
+ check_extack_nsim (err , "program loaded with different flags." , args )
682
732
683
733
start_test ("Test MTU restrictions..." )
684
734
ret , _ = sim .set_mtu (9000 , fail = False )
@@ -687,8 +737,9 @@ def check_dev_info(other_ns, ns, prog_file=None, map_file=None, removed=False):
687
737
sim .unset_xdp ("drv" )
688
738
bpftool_prog_list_wait (expected = 0 )
689
739
sim .set_mtu (9000 )
690
- ret , _ = sim .set_xdp (obj , "drv" , fail = False )
740
+ ret , _ , err = sim .set_xdp (obj , "drv" , fail = False , include_stderr = True )
691
741
fail (ret == 0 , "Driver should refuse to load program with MTU of 9000..." )
742
+ check_extack_nsim (err , "MTU too large w/ XDP enabled." , args )
692
743
sim .set_mtu (1500 )
693
744
694
745
sim .wait_for_flush ()
@@ -724,25 +775,32 @@ def check_dev_info(other_ns, ns, prog_file=None, map_file=None, removed=False):
724
775
sim2 .set_xdp (obj , "offload" )
725
776
pin_file , pinned = pin_prog ("/sys/fs/bpf/tmp" )
726
777
727
- ret , _ = sim .set_xdp (pinned , "offload" , fail = False )
778
+ ret , _ , err = sim .set_xdp (pinned , "offload" ,
779
+ fail = False , include_stderr = True )
728
780
fail (ret == 0 , "Pinned program loaded for a different device accepted" )
781
+ check_extack_nsim (err , "program bound to different dev." , args )
729
782
sim2 .remove ()
730
- ret , _ = sim .set_xdp (pinned , "offload" , fail = False )
783
+ ret , _ , err = sim .set_xdp (pinned , "offload" ,
784
+ fail = False , include_stderr = True )
731
785
fail (ret == 0 , "Pinned program loaded for a removed device accepted" )
786
+ check_extack_nsim (err , "xdpoffload of non-bound program." , args )
732
787
rm (pin_file )
733
788
bpftool_prog_list_wait (expected = 0 )
734
789
735
790
start_test ("Test mixing of TC and XDP..." )
736
791
sim .tc_add_ingress ()
737
792
sim .set_xdp (obj , "offload" )
738
- ret , _ = sim .cls_bpf_add_filter (obj , skip_sw = True , fail = False )
793
+ ret , _ , err = sim .cls_bpf_add_filter (obj , skip_sw = True ,
794
+ fail = False , include_stderr = True )
739
795
fail (ret == 0 , "Loading TC when XDP active should fail" )
796
+ check_extack_nsim (err , "driver and netdev offload states mismatch." , args )
740
797
sim .unset_xdp ("offload" )
741
798
sim .wait_for_flush ()
742
799
743
800
sim .cls_bpf_add_filter (obj , skip_sw = True )
744
- ret , _ = sim .set_xdp (obj , "offload" , fail = False )
801
+ ret , _ , err = sim .set_xdp (obj , "offload" , fail = False , include_stderr = True )
745
802
fail (ret == 0 , "Loading XDP when TC active should fail" )
803
+ check_extack_nsim (err , "TC program is already loaded." , args )
746
804
747
805
start_test ("Test binding TC from pinned..." )
748
806
pin_file , pinned = pin_prog ("/sys/fs/bpf/tmp" )
@@ -765,8 +823,10 @@ def check_dev_info(other_ns, ns, prog_file=None, map_file=None, removed=False):
765
823
766
824
start_test ("Test asking for TC offload of two filters..." )
767
825
sim .cls_bpf_add_filter (obj , da = True , skip_sw = True )
768
- ret , _ = sim .cls_bpf_add_filter (obj , da = True , skip_sw = True , fail = False )
826
+ ret , _ , err = sim .cls_bpf_add_filter (obj , da = True , skip_sw = True ,
827
+ fail = False , include_stderr = True )
769
828
fail (ret == 0 , "Managed to offload two TC filters at the same time" )
829
+ check_extack_nsim (err , "driver and netdev offload states mismatch." , args )
770
830
771
831
sim .tc_flush_filters (bound = 2 , total = 2 )
772
832
0 commit comments