Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/drivers/net/xdp.py
26288 views
1
#!/usr/bin/env python3
2
# SPDX-License-Identifier: GPL-2.0
3
4
"""
5
This file contains tests to verify native XDP support in network drivers.
6
The tests utilize the BPF program `xdp_native.bpf.o` from the `selftests.net.lib`
7
directory, with each test focusing on a specific aspect of XDP functionality.
8
"""
9
import random
10
import string
11
from dataclasses import dataclass
12
from enum import Enum
13
14
from lib.py import ksft_run, ksft_exit, ksft_eq, ksft_ne, ksft_pr
15
from lib.py import KsftFailEx, NetDrvEpEnv, EthtoolFamily, NlError
16
from lib.py import bkg, cmd, rand_port, wait_port_listen
17
from lib.py import ip, bpftool, defer
18
19
20
class TestConfig(Enum):
21
"""Enum for XDP configuration options."""
22
MODE = 0 # Configures the BPF program for a specific test
23
PORT = 1 # Port configuration to communicate with the remote host
24
ADJST_OFFSET = 2 # Tail/Head adjustment offset for extension/shrinking
25
ADJST_TAG = 3 # Adjustment tag to annotate the start and end of extension
26
27
28
class XDPAction(Enum):
29
"""Enum for XDP actions."""
30
PASS = 0 # Pass the packet up to the stack
31
DROP = 1 # Drop the packet
32
TX = 2 # Route the packet to the remote host
33
TAIL_ADJST = 3 # Adjust the tail of the packet
34
HEAD_ADJST = 4 # Adjust the head of the packet
35
36
37
class XDPStats(Enum):
38
"""Enum for XDP statistics."""
39
RX = 0 # Count of valid packets received for testing
40
PASS = 1 # Count of packets passed up to the stack
41
DROP = 2 # Count of packets dropped
42
TX = 3 # Count of incoming packets routed to the remote host
43
ABORT = 4 # Count of packets that were aborted
44
45
46
@dataclass
47
class BPFProgInfo:
48
"""Data class to store information about a BPF program."""
49
name: str # Name of the BPF program
50
file: str # BPF program object file
51
xdp_sec: str = "xdp" # XDP section name (e.g., "xdp" or "xdp.frags")
52
mtu: int = 1500 # Maximum Transmission Unit, default is 1500
53
54
55
def _exchg_udp(cfg, port, test_string):
56
"""
57
Exchanges UDP packets between a local and remote host using the socat tool.
58
59
Args:
60
cfg: Configuration object containing network settings.
61
port: Port number to use for the UDP communication.
62
test_string: String that the remote host will send.
63
64
Returns:
65
The string received by the test host.
66
"""
67
cfg.require_cmd("socat", remote=True)
68
69
rx_udp_cmd = f"socat -{cfg.addr_ipver} -T 2 -u UDP-RECV:{port},reuseport STDOUT"
70
tx_udp_cmd = f"echo -n {test_string} | socat -t 2 -u STDIN UDP:{cfg.baddr}:{port}"
71
72
with bkg(rx_udp_cmd, exit_wait=True) as nc:
73
wait_port_listen(port, proto="udp")
74
cmd(tx_udp_cmd, host=cfg.remote, shell=True)
75
76
return nc.stdout.strip()
77
78
79
def _test_udp(cfg, port, size=256):
80
"""
81
Tests UDP packet exchange between a local and remote host.
82
83
Args:
84
cfg: Configuration object containing network settings.
85
port: Port number to use for the UDP communication.
86
size: The length of the test string to be exchanged, default is 256 characters.
87
88
Returns:
89
bool: True if the received string matches the sent string, False otherwise.
90
"""
91
test_str = "".join(random.choice(string.ascii_lowercase) for _ in range(size))
92
recvd_str = _exchg_udp(cfg, port, test_str)
93
94
return recvd_str == test_str
95
96
97
def _load_xdp_prog(cfg, bpf_info):
98
"""
99
Loads an XDP program onto a network interface.
100
101
Args:
102
cfg: Configuration object containing network settings.
103
bpf_info: BPFProgInfo object containing information about the BPF program.
104
105
Returns:
106
dict: A dictionary containing the XDP program ID, name, and associated map IDs.
107
"""
108
abs_path = cfg.net_lib_dir / bpf_info.file
109
prog_info = {}
110
111
cmd(f"ip link set dev {cfg.remote_ifname} mtu {bpf_info.mtu}", shell=True, host=cfg.remote)
112
defer(ip, f"link set dev {cfg.remote_ifname} mtu 1500", host=cfg.remote)
113
114
cmd(
115
f"ip link set dev {cfg.ifname} mtu {bpf_info.mtu} xdp obj {abs_path} sec {bpf_info.xdp_sec}",
116
shell=True
117
)
118
defer(ip, f"link set dev {cfg.ifname} mtu 1500 xdp off")
119
120
xdp_info = ip(f"-d link show dev {cfg.ifname}", json=True)[0]
121
prog_info["id"] = xdp_info["xdp"]["prog"]["id"]
122
prog_info["name"] = xdp_info["xdp"]["prog"]["name"]
123
prog_id = prog_info["id"]
124
125
map_ids = bpftool(f"prog show id {prog_id}", json=True)["map_ids"]
126
prog_info["maps"] = {}
127
for map_id in map_ids:
128
name = bpftool(f"map show id {map_id}", json=True)["name"]
129
prog_info["maps"][name] = map_id
130
131
return prog_info
132
133
134
def format_hex_bytes(value):
135
"""
136
Helper function that converts an integer into a formatted hexadecimal byte string.
137
138
Args:
139
value: An integer representing the number to be converted.
140
141
Returns:
142
A string representing hexadecimal equivalent of value, with bytes separated by spaces.
143
"""
144
hex_str = value.to_bytes(4, byteorder='little', signed=True)
145
return ' '.join(f'{byte:02x}' for byte in hex_str)
146
147
148
def _set_xdp_map(map_name, key, value):
149
"""
150
Updates an XDP map with a given key-value pair using bpftool.
151
152
Args:
153
map_name: The name of the XDP map to update.
154
key: The key to update in the map, formatted as a hexadecimal string.
155
value: The value to associate with the key, formatted as a hexadecimal string.
156
"""
157
key_formatted = format_hex_bytes(key)
158
value_formatted = format_hex_bytes(value)
159
bpftool(
160
f"map update name {map_name} key hex {key_formatted} value hex {value_formatted}"
161
)
162
163
164
def _get_stats(xdp_map_id):
165
"""
166
Retrieves and formats statistics from an XDP map.
167
168
Args:
169
xdp_map_id: The ID of the XDP map from which to retrieve statistics.
170
171
Returns:
172
A dictionary containing formatted packet statistics for various XDP actions.
173
The keys are based on the XDPStats Enum values.
174
175
Raises:
176
KsftFailEx: If the stats retrieval fails.
177
"""
178
stats_dump = bpftool(f"map dump id {xdp_map_id}", json=True)
179
if not stats_dump:
180
raise KsftFailEx(f"Failed to get stats for map {xdp_map_id}")
181
182
stats_formatted = {}
183
for key in range(0, 5):
184
val = stats_dump[key]["formatted"]["value"]
185
if stats_dump[key]["formatted"]["key"] == XDPStats.RX.value:
186
stats_formatted[XDPStats.RX.value] = val
187
elif stats_dump[key]["formatted"]["key"] == XDPStats.PASS.value:
188
stats_formatted[XDPStats.PASS.value] = val
189
elif stats_dump[key]["formatted"]["key"] == XDPStats.DROP.value:
190
stats_formatted[XDPStats.DROP.value] = val
191
elif stats_dump[key]["formatted"]["key"] == XDPStats.TX.value:
192
stats_formatted[XDPStats.TX.value] = val
193
elif stats_dump[key]["formatted"]["key"] == XDPStats.ABORT.value:
194
stats_formatted[XDPStats.ABORT.value] = val
195
196
return stats_formatted
197
198
199
def _test_pass(cfg, bpf_info, msg_sz):
200
"""
201
Tests the XDP_PASS action by exchanging UDP packets.
202
203
Args:
204
cfg: Configuration object containing network settings.
205
bpf_info: BPFProgInfo object containing information about the BPF program.
206
msg_sz: Size of the test message to send.
207
"""
208
209
prog_info = _load_xdp_prog(cfg, bpf_info)
210
port = rand_port()
211
212
_set_xdp_map("map_xdp_setup", TestConfig.MODE.value, XDPAction.PASS.value)
213
_set_xdp_map("map_xdp_setup", TestConfig.PORT.value, port)
214
215
ksft_eq(_test_udp(cfg, port, msg_sz), True, "UDP packet exchange failed")
216
stats = _get_stats(prog_info["maps"]["map_xdp_stats"])
217
218
ksft_ne(stats[XDPStats.RX.value], 0, "RX stats should not be zero")
219
ksft_eq(stats[XDPStats.RX.value], stats[XDPStats.PASS.value], "RX and PASS stats mismatch")
220
221
222
def test_xdp_native_pass_sb(cfg):
223
"""
224
Tests the XDP_PASS action for single buffer case.
225
226
Args:
227
cfg: Configuration object containing network settings.
228
"""
229
bpf_info = BPFProgInfo("xdp_prog", "xdp_native.bpf.o", "xdp", 1500)
230
231
_test_pass(cfg, bpf_info, 256)
232
233
234
def test_xdp_native_pass_mb(cfg):
235
"""
236
Tests the XDP_PASS action for a multi-buff size.
237
238
Args:
239
cfg: Configuration object containing network settings.
240
"""
241
bpf_info = BPFProgInfo("xdp_prog_frags", "xdp_native.bpf.o", "xdp.frags", 9000)
242
243
_test_pass(cfg, bpf_info, 8000)
244
245
246
def _test_drop(cfg, bpf_info, msg_sz):
247
"""
248
Tests the XDP_DROP action by exchanging UDP packets.
249
250
Args:
251
cfg: Configuration object containing network settings.
252
bpf_info: BPFProgInfo object containing information about the BPF program.
253
msg_sz: Size of the test message to send.
254
"""
255
256
prog_info = _load_xdp_prog(cfg, bpf_info)
257
port = rand_port()
258
259
_set_xdp_map("map_xdp_setup", TestConfig.MODE.value, XDPAction.DROP.value)
260
_set_xdp_map("map_xdp_setup", TestConfig.PORT.value, port)
261
262
ksft_eq(_test_udp(cfg, port, msg_sz), False, "UDP packet exchange should fail")
263
stats = _get_stats(prog_info["maps"]["map_xdp_stats"])
264
265
ksft_ne(stats[XDPStats.RX.value], 0, "RX stats should be zero")
266
ksft_eq(stats[XDPStats.RX.value], stats[XDPStats.DROP.value], "RX and DROP stats mismatch")
267
268
269
def test_xdp_native_drop_sb(cfg):
270
"""
271
Tests the XDP_DROP action for a signle-buff case.
272
273
Args:
274
cfg: Configuration object containing network settings.
275
"""
276
bpf_info = BPFProgInfo("xdp_prog", "xdp_native.bpf.o", "xdp", 1500)
277
278
_test_drop(cfg, bpf_info, 256)
279
280
281
def test_xdp_native_drop_mb(cfg):
282
"""
283
Tests the XDP_DROP action for a multi-buff case.
284
285
Args:
286
cfg: Configuration object containing network settings.
287
"""
288
bpf_info = BPFProgInfo("xdp_prog_frags", "xdp_native.bpf.o", "xdp.frags", 9000)
289
290
_test_drop(cfg, bpf_info, 8000)
291
292
293
def test_xdp_native_tx_mb(cfg):
294
"""
295
Tests the XDP_TX action for a multi-buff case.
296
297
Args:
298
cfg: Configuration object containing network settings.
299
"""
300
cfg.require_cmd("socat", remote=True)
301
302
bpf_info = BPFProgInfo("xdp_prog_frags", "xdp_native.bpf.o", "xdp.frags", 9000)
303
prog_info = _load_xdp_prog(cfg, bpf_info)
304
port = rand_port()
305
306
_set_xdp_map("map_xdp_setup", TestConfig.MODE.value, XDPAction.TX.value)
307
_set_xdp_map("map_xdp_setup", TestConfig.PORT.value, port)
308
309
test_string = ''.join(random.choice(string.ascii_lowercase) for _ in range(8000))
310
rx_udp = f"socat -{cfg.addr_ipver} -T 2 -u UDP-RECV:{port},reuseport STDOUT"
311
tx_udp = f"echo {test_string} | socat -t 2 -u STDIN UDP:{cfg.baddr}:{port}"
312
313
with bkg(rx_udp, host=cfg.remote, exit_wait=True) as rnc:
314
wait_port_listen(port, proto="udp", host=cfg.remote)
315
cmd(tx_udp, host=cfg.remote, shell=True)
316
317
stats = _get_stats(prog_info['maps']['map_xdp_stats'])
318
319
ksft_eq(rnc.stdout.strip(), test_string, "UDP packet exchange failed")
320
ksft_eq(stats[XDPStats.TX.value], 1, "TX stats mismatch")
321
322
323
def _validate_res(res, offset_lst, pkt_sz_lst):
324
"""
325
Validates the result of a test.
326
327
Args:
328
res: The result of the test, which should be a dictionary with a "status" key.
329
330
Raises:
331
KsftFailEx: If the test fails to pass any combination of offset and packet size.
332
"""
333
if "status" not in res:
334
raise KsftFailEx("Missing 'status' key in result dictionary")
335
336
# Validate that not a single case was successful
337
if res["status"] == "fail":
338
if res["offset"] == offset_lst[0] and res["pkt_sz"] == pkt_sz_lst[0]:
339
raise KsftFailEx(f"{res['reason']}")
340
341
# Get the previous offset and packet size to report the successful run
342
tmp_idx = offset_lst.index(res["offset"])
343
prev_offset = offset_lst[tmp_idx - 1]
344
if tmp_idx == 0:
345
tmp_idx = pkt_sz_lst.index(res["pkt_sz"])
346
prev_pkt_sz = pkt_sz_lst[tmp_idx - 1]
347
else:
348
prev_pkt_sz = res["pkt_sz"]
349
350
# Use these values for error reporting
351
ksft_pr(
352
f"Failed run: pkt_sz {res['pkt_sz']}, offset {res['offset']}. "
353
f"Last successful run: pkt_sz {prev_pkt_sz}, offset {prev_offset}. "
354
f"Reason: {res['reason']}"
355
)
356
357
358
def _check_for_failures(recvd_str, stats):
359
"""
360
Checks for common failures while adjusting headroom or tailroom.
361
362
Args:
363
recvd_str: The string received from the remote host after sending a test string.
364
stats: A dictionary containing formatted packet statistics for various XDP actions.
365
366
Returns:
367
str: A string describing the failure reason if a failure is detected, otherwise None.
368
"""
369
370
# Any adjustment failure result in an abort hence, we track this counter
371
if stats[XDPStats.ABORT.value] != 0:
372
return "Adjustment failed"
373
374
# Since we are using aggregate stats for a single test across all offsets and packet sizes
375
# we can't use RX stats only to track data exchange failure without taking a previous
376
# snapshot. An easier way is to simply check for non-zero length of received string.
377
if len(recvd_str) == 0:
378
return "Data exchange failed"
379
380
# Check for RX and PASS stats mismatch. Ideally, they should be equal for a successful run
381
if stats[XDPStats.RX.value] != stats[XDPStats.PASS.value]:
382
return "RX stats mismatch"
383
384
return None
385
386
387
def _test_xdp_native_tail_adjst(cfg, pkt_sz_lst, offset_lst):
388
"""
389
Tests the XDP tail adjustment functionality.
390
391
This function loads the appropriate XDP program based on the provided
392
program name and configures the XDP map for tail adjustment. It then
393
validates the tail adjustment by sending and receiving UDP packets
394
with specified packet sizes and offsets.
395
396
Args:
397
cfg: Configuration object containing network settings.
398
prog: Name of the XDP program to load.
399
pkt_sz_lst: List of packet sizes to test.
400
offset_lst: List of offsets to validate support for tail adjustment.
401
402
Returns:
403
dict: A dictionary with test status and failure details if applicable.
404
"""
405
port = rand_port()
406
bpf_info = BPFProgInfo("xdp_prog_frags", "xdp_native.bpf.o", "xdp.frags", 9000)
407
408
prog_info = _load_xdp_prog(cfg, bpf_info)
409
410
# Configure the XDP map for tail adjustment
411
_set_xdp_map("map_xdp_setup", TestConfig.MODE.value, XDPAction.TAIL_ADJST.value)
412
_set_xdp_map("map_xdp_setup", TestConfig.PORT.value, port)
413
414
for offset in offset_lst:
415
tag = format(random.randint(65, 90), "02x")
416
417
_set_xdp_map("map_xdp_setup", TestConfig.ADJST_OFFSET.value, offset)
418
if offset > 0:
419
_set_xdp_map("map_xdp_setup", TestConfig.ADJST_TAG.value, int(tag, 16))
420
421
for pkt_sz in pkt_sz_lst:
422
test_str = "".join(random.choice(string.ascii_lowercase) for _ in range(pkt_sz))
423
recvd_str = _exchg_udp(cfg, port, test_str)
424
stats = _get_stats(prog_info["maps"]["map_xdp_stats"])
425
426
failure = _check_for_failures(recvd_str, stats)
427
if failure is not None:
428
return {
429
"status": "fail",
430
"reason": failure,
431
"offset": offset,
432
"pkt_sz": pkt_sz,
433
}
434
435
# Validate data content based on offset direction
436
expected_data = None
437
if offset > 0:
438
expected_data = test_str + (offset * chr(int(tag, 16)))
439
else:
440
expected_data = test_str[0:pkt_sz + offset]
441
442
if recvd_str != expected_data:
443
return {
444
"status": "fail",
445
"reason": "Data mismatch",
446
"offset": offset,
447
"pkt_sz": pkt_sz,
448
}
449
450
return {"status": "pass"}
451
452
453
def test_xdp_native_adjst_tail_grow_data(cfg):
454
"""
455
Tests the XDP tail adjustment by growing packet data.
456
457
Args:
458
cfg: Configuration object containing network settings.
459
"""
460
pkt_sz_lst = [512, 1024, 2048]
461
offset_lst = [1, 16, 32, 64, 128, 256]
462
res = _test_xdp_native_tail_adjst(
463
cfg,
464
pkt_sz_lst,
465
offset_lst,
466
)
467
468
_validate_res(res, offset_lst, pkt_sz_lst)
469
470
471
def test_xdp_native_adjst_tail_shrnk_data(cfg):
472
"""
473
Tests the XDP tail adjustment by shrinking packet data.
474
475
Args:
476
cfg: Configuration object containing network settings.
477
"""
478
pkt_sz_lst = [512, 1024, 2048]
479
offset_lst = [-16, -32, -64, -128, -256]
480
res = _test_xdp_native_tail_adjst(
481
cfg,
482
pkt_sz_lst,
483
offset_lst,
484
)
485
486
_validate_res(res, offset_lst, pkt_sz_lst)
487
488
489
def get_hds_thresh(cfg):
490
"""
491
Retrieves the header data split (HDS) threshold for a network interface.
492
493
Args:
494
cfg: Configuration object containing network settings.
495
496
Returns:
497
The HDS threshold value. If the threshold is not supported or an error occurs,
498
a default value of 1500 is returned.
499
"""
500
netnl = cfg.netnl
501
hds_thresh = 1500
502
503
try:
504
rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})
505
if 'hds-thresh' not in rings:
506
ksft_pr(f'hds-thresh not supported. Using default: {hds_thresh}')
507
return hds_thresh
508
hds_thresh = rings['hds-thresh']
509
except NlError as e:
510
ksft_pr(f"Failed to get rings: {e}. Using default: {hds_thresh}")
511
512
return hds_thresh
513
514
515
def _test_xdp_native_head_adjst(cfg, prog, pkt_sz_lst, offset_lst):
516
"""
517
Tests the XDP head adjustment action for a multi-buffer case.
518
519
Args:
520
cfg: Configuration object containing network settings.
521
netnl: Network namespace or link object (not used in this function).
522
523
This function sets up the packet size and offset lists, then performs
524
the head adjustment test by sending and receiving UDP packets.
525
"""
526
cfg.require_cmd("socat", remote=True)
527
528
prog_info = _load_xdp_prog(cfg, BPFProgInfo(prog, "xdp_native.bpf.o", "xdp.frags", 9000))
529
port = rand_port()
530
531
_set_xdp_map("map_xdp_setup", TestConfig.MODE.value, XDPAction.HEAD_ADJST.value)
532
_set_xdp_map("map_xdp_setup", TestConfig.PORT.value, port)
533
534
hds_thresh = get_hds_thresh(cfg)
535
for offset in offset_lst:
536
for pkt_sz in pkt_sz_lst:
537
# The "head" buffer must contain at least the Ethernet header
538
# after we eat into it. We send large-enough packets, but if HDS
539
# is enabled head will only contain headers. Don't try to eat
540
# more than 28 bytes (UDPv4 + eth hdr left: (14 + 20 + 8) - 14)
541
l2_cut_off = 28 if cfg.addr_ipver == 4 else 48
542
if pkt_sz > hds_thresh and offset > l2_cut_off:
543
ksft_pr(
544
f"Failed run: pkt_sz ({pkt_sz}) > HDS threshold ({hds_thresh}) and "
545
f"offset {offset} > {l2_cut_off}"
546
)
547
return {"status": "pass"}
548
549
test_str = ''.join(random.choice(string.ascii_lowercase) for _ in range(pkt_sz))
550
tag = format(random.randint(65, 90), '02x')
551
552
_set_xdp_map("map_xdp_setup",
553
TestConfig.ADJST_OFFSET.value,
554
offset)
555
_set_xdp_map("map_xdp_setup", TestConfig.ADJST_TAG.value, int(tag, 16))
556
_set_xdp_map("map_xdp_setup", TestConfig.ADJST_OFFSET.value, offset)
557
558
recvd_str = _exchg_udp(cfg, port, test_str)
559
560
# Check for failures around adjustment and data exchange
561
failure = _check_for_failures(recvd_str, _get_stats(prog_info['maps']['map_xdp_stats']))
562
if failure is not None:
563
return {
564
"status": "fail",
565
"reason": failure,
566
"offset": offset,
567
"pkt_sz": pkt_sz
568
}
569
570
# Validate data content based on offset direction
571
expected_data = None
572
if offset < 0:
573
expected_data = chr(int(tag, 16)) * (0 - offset) + test_str
574
else:
575
expected_data = test_str[offset:]
576
577
if recvd_str != expected_data:
578
return {
579
"status": "fail",
580
"reason": "Data mismatch",
581
"offset": offset,
582
"pkt_sz": pkt_sz
583
}
584
585
return {"status": "pass"}
586
587
588
def test_xdp_native_adjst_head_grow_data(cfg):
589
"""
590
Tests the XDP headroom growth support.
591
592
Args:
593
cfg: Configuration object containing network settings.
594
595
This function sets up the packet size and offset lists, then calls the
596
_test_xdp_native_head_adjst_mb function to perform the actual test. The
597
test is passed if the headroom is successfully extended for given packet
598
sizes and offsets.
599
"""
600
pkt_sz_lst = [512, 1024, 2048]
601
602
# Negative values result in headroom shrinking, resulting in growing of payload
603
offset_lst = [-16, -32, -64, -128, -256]
604
res = _test_xdp_native_head_adjst(cfg, "xdp_prog_frags", pkt_sz_lst, offset_lst)
605
606
_validate_res(res, offset_lst, pkt_sz_lst)
607
608
609
def test_xdp_native_adjst_head_shrnk_data(cfg):
610
"""
611
Tests the XDP headroom shrinking support.
612
613
Args:
614
cfg: Configuration object containing network settings.
615
616
This function sets up the packet size and offset lists, then calls the
617
_test_xdp_native_head_adjst_mb function to perform the actual test. The
618
test is passed if the headroom is successfully shrunk for given packet
619
sizes and offsets.
620
"""
621
pkt_sz_lst = [512, 1024, 2048]
622
623
# Positive values result in headroom growing, resulting in shrinking of payload
624
offset_lst = [16, 32, 64, 128, 256]
625
res = _test_xdp_native_head_adjst(cfg, "xdp_prog_frags", pkt_sz_lst, offset_lst)
626
627
_validate_res(res, offset_lst, pkt_sz_lst)
628
629
630
def main():
631
"""
632
Main function to execute the XDP tests.
633
634
This function runs a series of tests to validate the XDP support for
635
both the single and multi-buffer. It uses the NetDrvEpEnv context
636
manager to manage the network driver environment and the ksft_run
637
function to execute the tests.
638
"""
639
with NetDrvEpEnv(__file__) as cfg:
640
cfg.netnl = EthtoolFamily()
641
ksft_run(
642
[
643
test_xdp_native_pass_sb,
644
test_xdp_native_pass_mb,
645
test_xdp_native_drop_sb,
646
test_xdp_native_drop_mb,
647
test_xdp_native_tx_mb,
648
test_xdp_native_adjst_tail_grow_data,
649
test_xdp_native_adjst_tail_shrnk_data,
650
test_xdp_native_adjst_head_grow_data,
651
test_xdp_native_adjst_head_shrnk_data,
652
],
653
args=(cfg,))
654
ksft_exit()
655
656
657
if __name__ == "__main__":
658
main()
659
660