mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 19:13:47 +02:00
Merge branch 'selftests-net-add-netkit-container-env-and-test'
David Wei says:
====================
selftests/net: add netkit container env and test
Add a new Python selftest env NetDrvContEnv that sets up a pair of
netkit netdevs, with one inside of a netns, and a bpf prog that forwards
skbs from NETIF to the netkit inside the netns.
NETIF = "eth0"
LOCAL_V6 = "2001:db8:1::1"
REMOTE_V6 = "2001:db8:1::2"
LOCAL_PREFIX_V6 = "2001:db8:2::0/64"
+-----------------------------+ +------------------------------+
dst | INIT NS | | TEST NS |
2001: | +---------------+ | | |
db8:2::2| | NETIF | | bpf | |
+---|>| 2001:db8:1::1 | |redirect| +-------------------------+ |
| | | |-----------|--------|>| Netkit | |
| | +---------------+ | _peer | | nk_guest | |
| | +-------------+ Netkit pair | | | fe80::2/64 | |
| | | Netkit |.............|........|>| 2001:db8:2::2/64 | |
| | | nk_host | | | +-------------------------+ |
| | | fe80::1/64 | | | |
| | +-------------+ | | route: |
| | | | default |
| | route: | | via fe80::1 dev nk_guest |
| | 2001:db8:2::2/128 | +------------------------------+
| | via fe80::2 dev nk_host |
| +-----------------------------+
|
| +---------------+
| | REMOTE |
+---| 2001:db8:1::2 |
+---------------+
I will use this series for queue leasing selftests. Include a basic ping
test in this series as demonstration.
====================
Link: https://patch.msgid.link/20260305181803.2912736-1-dw@davidwei.uk
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
13f0dd7ed1
|
|
@ -66,6 +66,44 @@ LOCAL_V4, LOCAL_V6, REMOTE_V4, REMOTE_V6
|
|||
|
||||
Local and remote endpoint IP addresses.
|
||||
|
||||
LOCAL_PREFIX_V6
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Local IP prefix/subnet which can be used to allocate extra IP addresses (for
|
||||
network name spaces behind macvlan, veth, netkit devices). DUT must be
|
||||
reachable using these addresses from the endpoint.
|
||||
|
||||
LOCAL_PREFIX_V6 must NOT match LOCAL_V6.
|
||||
|
||||
Example:
|
||||
NETIF = "eth0"
|
||||
LOCAL_V6 = "2001:db8:1::1"
|
||||
REMOTE_V6 = "2001:db8:1::2"
|
||||
LOCAL_PREFIX_V6 = "2001:db8:2::0/64"
|
||||
|
||||
+-----------------------------+ +------------------------------+
|
||||
dst | INIT NS | | TEST NS |
|
||||
2001: | +---------------+ | | |
|
||||
db8:2::2| | NETIF | | bpf | |
|
||||
+---|>| 2001:db8:1::1 | |redirect| +-------------------------+ |
|
||||
| | | |-----------|--------|>| Netkit | |
|
||||
| | +---------------+ | _peer | | nk_guest | |
|
||||
| | +-------------+ Netkit pair | | | fe80::2/64 | |
|
||||
| | | Netkit |.............|........|>| 2001:db8:2::2/64 | |
|
||||
| | | nk_host | | | +-------------------------+ |
|
||||
| | | fe80::1/64 | | | |
|
||||
| | +-------------+ | | route: |
|
||||
| | | | default |
|
||||
| | route: | | via fe80::1 dev nk_guest |
|
||||
| | 2001:db8:2::2/128 | +------------------------------+
|
||||
| | via fe80::2 dev nk_host |
|
||||
| +-----------------------------+
|
||||
|
|
||||
| +---------------+
|
||||
| | REMOTE |
|
||||
+---| 2001:db8:1::2 |
|
||||
+---------------+
|
||||
|
||||
REMOTE_TYPE
|
||||
~~~~~~~~~~~
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ TEST_PROGS = \
|
|||
irq.py \
|
||||
loopback.sh \
|
||||
nic_timestamp.py \
|
||||
nk_netns.py \
|
||||
pp_alloc_fail.py \
|
||||
rss_api.py \
|
||||
rss_ctx.py \
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
CONFIG_BPF_SYSCALL=y
|
||||
CONFIG_FAIL_FUNCTION=y
|
||||
CONFIG_FAULT_INJECTION=y
|
||||
CONFIG_FAULT_INJECTION_DEBUG_FS=y
|
||||
|
|
@ -5,7 +6,9 @@ CONFIG_FUNCTION_ERROR_INJECTION=y
|
|||
CONFIG_IO_URING=y
|
||||
CONFIG_IPV6=y
|
||||
CONFIG_IPV6_GRE=y
|
||||
CONFIG_NET_CLS_BPF=y
|
||||
CONFIG_NET_IPGRE=y
|
||||
CONFIG_NET_IPGRE_DEMUX=y
|
||||
CONFIG_NETKIT=y
|
||||
CONFIG_UDMABUF=y
|
||||
CONFIG_VXLAN=y
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
"""
|
||||
Driver test environment (hardware-only tests).
|
||||
NetDrvEnv and NetDrvEpEnv are the main environment classes.
|
||||
NetDrvContEnv extends NetDrvEpEnv with netkit container support.
|
||||
Former is for local host only tests, latter creates / connects
|
||||
to a remote endpoint. See NIPA wiki for more information about
|
||||
running and writing driver tests.
|
||||
|
|
@ -30,7 +31,7 @@ try:
|
|||
from net.lib.py import ksft_eq, ksft_ge, ksft_in, ksft_is, ksft_lt, \
|
||||
ksft_ne, ksft_not_in, ksft_raises, ksft_true, ksft_gt, ksft_not_none
|
||||
from drivers.net.lib.py import GenerateTraffic, Remote, Iperf3Runner
|
||||
from drivers.net.lib.py import NetDrvEnv, NetDrvEpEnv
|
||||
from drivers.net.lib.py import NetDrvEnv, NetDrvEpEnv, NetDrvContEnv
|
||||
|
||||
__all__ = ["NetNS", "NetNSEnter", "NetdevSimDev",
|
||||
"EthtoolFamily", "NetdevFamily", "NetshaperFamily",
|
||||
|
|
@ -45,8 +46,8 @@ try:
|
|||
"ksft_eq", "ksft_ge", "ksft_in", "ksft_is", "ksft_lt",
|
||||
"ksft_ne", "ksft_not_in", "ksft_raises", "ksft_true", "ksft_gt",
|
||||
"ksft_not_none", "ksft_not_none",
|
||||
"NetDrvEnv", "NetDrvEpEnv", "GenerateTraffic", "Remote",
|
||||
"Iperf3Runner"]
|
||||
"NetDrvEnv", "NetDrvEpEnv", "NetDrvContEnv", "GenerateTraffic",
|
||||
"Remote", "Iperf3Runner"]
|
||||
except ModuleNotFoundError as e:
|
||||
print("Failed importing `net` library from kernel sources")
|
||||
print(str(e))
|
||||
|
|
|
|||
49
tools/testing/selftests/drivers/net/hw/nk_forward.bpf.c
Normal file
49
tools/testing/selftests/drivers/net/hw/nk_forward.bpf.c
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/pkt_cls.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/in6.h>
|
||||
#include <bpf/bpf_endian.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
#define TC_ACT_OK 0
|
||||
#define ETH_P_IPV6 0x86DD
|
||||
|
||||
#define ctx_ptr(field) ((void *)(long)(field))
|
||||
|
||||
#define v6_p64_equal(a, b) (a.s6_addr32[0] == b.s6_addr32[0] && \
|
||||
a.s6_addr32[1] == b.s6_addr32[1])
|
||||
|
||||
volatile __u32 netkit_ifindex;
|
||||
volatile __u8 ipv6_prefix[16];
|
||||
|
||||
SEC("tc/ingress")
|
||||
int tc_redirect_peer(struct __sk_buff *skb)
|
||||
{
|
||||
void *data_end = ctx_ptr(skb->data_end);
|
||||
void *data = ctx_ptr(skb->data);
|
||||
struct in6_addr *peer_addr;
|
||||
struct ipv6hdr *ip6h;
|
||||
struct ethhdr *eth;
|
||||
|
||||
peer_addr = (struct in6_addr *)ipv6_prefix;
|
||||
|
||||
if (skb->protocol != bpf_htons(ETH_P_IPV6))
|
||||
return TC_ACT_OK;
|
||||
|
||||
eth = data;
|
||||
if ((void *)(eth + 1) > data_end)
|
||||
return TC_ACT_OK;
|
||||
|
||||
ip6h = data + sizeof(struct ethhdr);
|
||||
if ((void *)(ip6h + 1) > data_end)
|
||||
return TC_ACT_OK;
|
||||
|
||||
if (!v6_p64_equal(ip6h->daddr, (*peer_addr)))
|
||||
return TC_ACT_OK;
|
||||
|
||||
return bpf_redirect_peer(netkit_ifindex, 0);
|
||||
}
|
||||
|
||||
char __license[] SEC("license") = "GPL";
|
||||
29
tools/testing/selftests/drivers/net/hw/nk_netns.py
Executable file
29
tools/testing/selftests/drivers/net/hw/nk_netns.py
Executable file
|
|
@ -0,0 +1,29 @@
|
|||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
"""
|
||||
Test exercising NetDrvContEnv() itself, a NetDrvContEnv() selftest.
|
||||
"""
|
||||
|
||||
from lib.py import ksft_run, ksft_exit
|
||||
from lib.py import NetDrvContEnv
|
||||
from lib.py import cmd
|
||||
|
||||
|
||||
def test_ping(cfg) -> None:
|
||||
""" Run ping between the container and the remote system. """
|
||||
cfg.require_ipver("6")
|
||||
|
||||
cmd(f"ping -c 1 -W5 {cfg.nk_guest_ipv6}", host=cfg.remote)
|
||||
cmd(f"ping -c 1 -W5 {cfg.remote_addr_v['6']}", ns=cfg.netns)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
""" Ksft boiler plate main """
|
||||
with NetDrvContEnv(__file__) as cfg:
|
||||
ksft_run([test_ping], args=(cfg,))
|
||||
ksft_exit()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
"""
|
||||
Driver test environment.
|
||||
NetDrvEnv and NetDrvEpEnv are the main environment classes.
|
||||
NetDrvContEnv extends NetDrvEpEnv with netkit container support.
|
||||
Former is for local host only tests, latter creates / connects
|
||||
to a remote endpoint. See NIPA wiki for more information about
|
||||
running and writing driver tests.
|
||||
|
|
@ -19,7 +20,7 @@ try:
|
|||
# Import one by one to avoid pylint false positives
|
||||
from net.lib.py import NetNS, NetNSEnter, NetdevSimDev
|
||||
from net.lib.py import EthtoolFamily, NetdevFamily, NetshaperFamily, \
|
||||
NlError, RtnlFamily, DevlinkFamily, PSPFamily
|
||||
NlError, RtnlFamily, DevlinkFamily, PSPFamily, Netlink
|
||||
from net.lib.py import CmdExitFailure
|
||||
from net.lib.py import bkg, cmd, bpftool, bpftrace, defer, ethtool, \
|
||||
fd_read_timeout, ip, rand_port, rand_ports, wait_port_listen, wait_file
|
||||
|
|
@ -31,7 +32,7 @@ try:
|
|||
|
||||
__all__ = ["NetNS", "NetNSEnter", "NetdevSimDev",
|
||||
"EthtoolFamily", "NetdevFamily", "NetshaperFamily",
|
||||
"NlError", "RtnlFamily", "DevlinkFamily", "PSPFamily",
|
||||
"NlError", "RtnlFamily", "DevlinkFamily", "PSPFamily", "Netlink",
|
||||
"CmdExitFailure",
|
||||
"bkg", "cmd", "bpftool", "bpftrace", "defer", "ethtool",
|
||||
"fd_read_timeout", "ip", "rand_port", "rand_ports",
|
||||
|
|
@ -43,12 +44,12 @@ try:
|
|||
"ksft_ne", "ksft_not_in", "ksft_raises", "ksft_true", "ksft_gt",
|
||||
"ksft_not_none", "ksft_not_none"]
|
||||
|
||||
from .env import NetDrvEnv, NetDrvEpEnv
|
||||
from .env import NetDrvEnv, NetDrvEpEnv, NetDrvContEnv
|
||||
from .load import GenerateTraffic, Iperf3Runner
|
||||
from .remote import Remote
|
||||
|
||||
__all__ += ["NetDrvEnv", "NetDrvEpEnv", "GenerateTraffic", "Remote",
|
||||
"Iperf3Runner"]
|
||||
__all__ += ["NetDrvEnv", "NetDrvEpEnv", "NetDrvContEnv", "GenerateTraffic",
|
||||
"Remote", "Iperf3Runner"]
|
||||
except ModuleNotFoundError as e:
|
||||
print("Failed importing `net` library from kernel sources")
|
||||
print(str(e))
|
||||
|
|
|
|||
|
|
@ -1,13 +1,16 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
import ipaddress
|
||||
import os
|
||||
import time
|
||||
import json
|
||||
from pathlib import Path
|
||||
from lib.py import KsftSkipEx, KsftXfailEx
|
||||
from lib.py import ksft_setup, wait_file
|
||||
from lib.py import cmd, ethtool, ip, CmdExitFailure
|
||||
from lib.py import NetNS, NetdevSimDev
|
||||
from .remote import Remote
|
||||
from . import bpftool, RtnlFamily, Netlink
|
||||
|
||||
|
||||
class NetDrvEnvBase:
|
||||
|
|
@ -289,3 +292,207 @@ class NetDrvEpEnv(NetDrvEnvBase):
|
|||
data.get('stats-block-usecs', 0) / 1000 / 1000
|
||||
|
||||
time.sleep(self._stats_settle_time)
|
||||
|
||||
|
||||
class NetDrvContEnv(NetDrvEpEnv):
|
||||
"""
|
||||
Class for an environment with a netkit pair setup for forwarding traffic
|
||||
between the physical interface and a network namespace.
|
||||
NETIF = "eth0"
|
||||
LOCAL_V6 = "2001:db8:1::1"
|
||||
REMOTE_V6 = "2001:db8:1::2"
|
||||
LOCAL_PREFIX_V6 = "2001:db8:2::0/64"
|
||||
|
||||
+-----------------------------+ +------------------------------+
|
||||
dst | INIT NS | | TEST NS |
|
||||
2001: | +---------------+ | | |
|
||||
db8:2::2| | NETIF | | bpf | |
|
||||
+---|>| 2001:db8:1::1 | |redirect| +-------------------------+ |
|
||||
| | | |-----------|--------|>| Netkit | |
|
||||
| | +---------------+ | _peer | | nk_guest | |
|
||||
| | +-------------+ Netkit pair | | | fe80::2/64 | |
|
||||
| | | Netkit |.............|........|>| 2001:db8:2::2/64 | |
|
||||
| | | nk_host | | | +-------------------------+ |
|
||||
| | | fe80::1/64 | | | |
|
||||
| | +-------------+ | | route: |
|
||||
| | | | default |
|
||||
| | route: | | via fe80::1 dev nk_guest |
|
||||
| | 2001:db8:2::2/128 | +------------------------------+
|
||||
| | via fe80::2 dev nk_host |
|
||||
| +-----------------------------+
|
||||
|
|
||||
| +---------------+
|
||||
| | REMOTE |
|
||||
+---| 2001:db8:1::2 |
|
||||
+---------------+
|
||||
"""
|
||||
|
||||
def __init__(self, src_path, rxqueues=1, **kwargs):
|
||||
self.netns = None
|
||||
self._nk_host_ifname = None
|
||||
self._nk_guest_ifname = None
|
||||
self._tc_clsact_added = False
|
||||
self._tc_attached = False
|
||||
self._bpf_prog_pref = None
|
||||
self._bpf_prog_id = None
|
||||
self._init_ns_attached = False
|
||||
self._old_fwd = None
|
||||
self._old_accept_ra = None
|
||||
|
||||
super().__init__(src_path, **kwargs)
|
||||
|
||||
self.require_ipver("6")
|
||||
local_prefix = self.env.get("LOCAL_PREFIX_V6")
|
||||
if not local_prefix:
|
||||
raise KsftSkipEx("LOCAL_PREFIX_V6 required")
|
||||
|
||||
net = ipaddress.IPv6Network(local_prefix, strict=False)
|
||||
self.ipv6_prefix = str(net.network_address)
|
||||
self.nk_host_ipv6 = f"{self.ipv6_prefix}2:1"
|
||||
self.nk_guest_ipv6 = f"{self.ipv6_prefix}2:2"
|
||||
|
||||
local_v6 = ipaddress.IPv6Address(self.addr_v["6"])
|
||||
if local_v6 in net:
|
||||
raise KsftSkipEx("LOCAL_V6 must not fall within LOCAL_PREFIX_V6")
|
||||
|
||||
rtnl = RtnlFamily()
|
||||
rtnl.newlink(
|
||||
{
|
||||
"linkinfo": {
|
||||
"kind": "netkit",
|
||||
"data": {
|
||||
"mode": "l2",
|
||||
"policy": "forward",
|
||||
"peer-policy": "forward",
|
||||
},
|
||||
},
|
||||
"num-rx-queues": rxqueues,
|
||||
},
|
||||
flags=[Netlink.NLM_F_CREATE, Netlink.NLM_F_EXCL],
|
||||
)
|
||||
|
||||
all_links = ip("-d link show", json=True)
|
||||
netkit_links = [link for link in all_links
|
||||
if link.get('linkinfo', {}).get('info_kind') == 'netkit'
|
||||
and 'UP' not in link.get('flags', [])]
|
||||
|
||||
if len(netkit_links) != 2:
|
||||
raise KsftSkipEx("Failed to create netkit pair")
|
||||
|
||||
netkit_links.sort(key=lambda x: x['ifindex'])
|
||||
self._nk_host_ifname = netkit_links[1]['ifname']
|
||||
self._nk_guest_ifname = netkit_links[0]['ifname']
|
||||
self.nk_host_ifindex = netkit_links[1]['ifindex']
|
||||
self.nk_guest_ifindex = netkit_links[0]['ifindex']
|
||||
|
||||
self._setup_ns()
|
||||
self._attach_bpf()
|
||||
|
||||
def __del__(self):
|
||||
if self._tc_attached:
|
||||
cmd(f"tc filter del dev {self.ifname} ingress pref {self._bpf_prog_pref}")
|
||||
self._tc_attached = False
|
||||
|
||||
if self._tc_clsact_added:
|
||||
cmd(f"tc qdisc del dev {self.ifname} clsact")
|
||||
self._tc_clsact_added = False
|
||||
|
||||
if self._nk_host_ifname:
|
||||
cmd(f"ip link del dev {self._nk_host_ifname}")
|
||||
self._nk_host_ifname = None
|
||||
self._nk_guest_ifname = None
|
||||
|
||||
if self._init_ns_attached:
|
||||
cmd("ip netns del init", fail=False)
|
||||
self._init_ns_attached = False
|
||||
|
||||
if self.netns:
|
||||
del self.netns
|
||||
self.netns = None
|
||||
|
||||
if self._old_fwd is not None:
|
||||
with open("/proc/sys/net/ipv6/conf/all/forwarding", "w",
|
||||
encoding="utf-8") as f:
|
||||
f.write(self._old_fwd)
|
||||
self._old_fwd = None
|
||||
if self._old_accept_ra is not None:
|
||||
with open("/proc/sys/net/ipv6/conf/all/accept_ra", "w",
|
||||
encoding="utf-8") as f:
|
||||
f.write(self._old_accept_ra)
|
||||
self._old_accept_ra = None
|
||||
|
||||
super().__del__()
|
||||
|
||||
def _setup_ns(self):
|
||||
fwd_path = "/proc/sys/net/ipv6/conf/all/forwarding"
|
||||
ra_path = "/proc/sys/net/ipv6/conf/all/accept_ra"
|
||||
with open(fwd_path, encoding="utf-8") as f:
|
||||
self._old_fwd = f.read().strip()
|
||||
with open(ra_path, encoding="utf-8") as f:
|
||||
self._old_accept_ra = f.read().strip()
|
||||
with open(fwd_path, "w", encoding="utf-8") as f:
|
||||
f.write("1")
|
||||
with open(ra_path, "w", encoding="utf-8") as f:
|
||||
f.write("2")
|
||||
|
||||
self.netns = NetNS()
|
||||
cmd("ip netns attach init 1")
|
||||
self._init_ns_attached = True
|
||||
ip("netns set init 0", ns=self.netns)
|
||||
ip(f"link set dev {self._nk_guest_ifname} netns {self.netns.name}")
|
||||
ip(f"link set dev {self._nk_host_ifname} up")
|
||||
ip(f"-6 addr add fe80::1/64 dev {self._nk_host_ifname} nodad")
|
||||
ip(f"-6 route add {self.nk_guest_ipv6}/128 via fe80::2 dev {self._nk_host_ifname}")
|
||||
|
||||
ip("link set lo up", ns=self.netns)
|
||||
ip(f"link set dev {self._nk_guest_ifname} up", ns=self.netns)
|
||||
ip(f"-6 addr add fe80::2/64 dev {self._nk_guest_ifname}", ns=self.netns)
|
||||
ip(f"-6 addr add {self.nk_guest_ipv6}/64 dev {self._nk_guest_ifname} nodad", ns=self.netns)
|
||||
ip(f"-6 route add default via fe80::1 dev {self._nk_guest_ifname}", ns=self.netns)
|
||||
|
||||
def _tc_ensure_clsact(self):
|
||||
qdisc = json.loads(cmd(f"tc -j qdisc show dev {self.ifname}").stdout)
|
||||
for q in qdisc:
|
||||
if q['kind'] == 'clsact':
|
||||
return
|
||||
cmd(f"tc qdisc add dev {self.ifname} clsact")
|
||||
self._tc_clsact_added = True
|
||||
|
||||
def _get_bpf_prog_ids(self):
|
||||
filters = json.loads(cmd(f"tc -j filter show dev {self.ifname} ingress").stdout)
|
||||
for bpf in filters:
|
||||
if 'options' not in bpf:
|
||||
continue
|
||||
if bpf['options']['bpf_name'].startswith('nk_forward.bpf'):
|
||||
return (bpf['pref'], bpf['options']['prog']['id'])
|
||||
raise Exception("Failed to get BPF prog ID")
|
||||
|
||||
def _attach_bpf(self):
|
||||
bpf_obj = self.test_dir / "nk_forward.bpf.o"
|
||||
if not bpf_obj.exists():
|
||||
raise KsftSkipEx("BPF prog not found")
|
||||
|
||||
self._tc_ensure_clsact()
|
||||
cmd(f"tc filter add dev {self.ifname} ingress bpf obj {bpf_obj}"
|
||||
" sec tc/ingress direct-action")
|
||||
self._tc_attached = True
|
||||
|
||||
(self._bpf_prog_pref, self._bpf_prog_id) = self._get_bpf_prog_ids()
|
||||
prog_info = bpftool(f"prog show id {self._bpf_prog_id}", json=True)
|
||||
map_ids = prog_info.get("map_ids", [])
|
||||
|
||||
bss_map_id = None
|
||||
for map_id in map_ids:
|
||||
map_info = bpftool(f"map show id {map_id}", json=True)
|
||||
if map_info.get("name").endswith("bss"):
|
||||
bss_map_id = map_id
|
||||
|
||||
if bss_map_id is None:
|
||||
raise Exception("Failed to find .bss map")
|
||||
|
||||
ipv6_addr = ipaddress.IPv6Address(self.ipv6_prefix)
|
||||
ipv6_bytes = ipv6_addr.packed
|
||||
ifindex_bytes = self.nk_host_ifindex.to_bytes(4, byteorder='little')
|
||||
value = ipv6_bytes + ifindex_bytes
|
||||
value_hex = ' '.join(f'{b:02x}' for b in value)
|
||||
bpftool(f"map update id {bss_map_id} key hex 00 00 00 00 value hex {value_hex}")
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ from .utils import CmdExitFailure, fd_read_timeout, cmd, bkg, defer, \
|
|||
bpftool, ip, ethtool, bpftrace, rand_port, rand_ports, wait_port_listen, \
|
||||
wait_file, tool
|
||||
from .ynl import NlError, YnlFamily, EthtoolFamily, NetdevFamily, RtnlFamily, RtnlAddrFamily
|
||||
from .ynl import NetshaperFamily, DevlinkFamily, PSPFamily
|
||||
from .ynl import NetshaperFamily, DevlinkFamily, PSPFamily, Netlink
|
||||
|
||||
__all__ = ["KSRC",
|
||||
"KsftFailEx", "KsftSkipEx", "KsftXfailEx", "ksft_pr", "ksft_eq",
|
||||
|
|
@ -31,4 +31,4 @@ __all__ = ["KSRC",
|
|||
"NetdevSim", "NetdevSimDev",
|
||||
"NetshaperFamily", "DevlinkFamily", "PSPFamily", "NlError",
|
||||
"YnlFamily", "EthtoolFamily", "NetdevFamily", "RtnlFamily",
|
||||
"RtnlAddrFamily"]
|
||||
"RtnlAddrFamily", "Netlink"]
|
||||
|
|
|
|||
|
|
@ -13,20 +13,26 @@ try:
|
|||
SPEC_PATH = KSFT_DIR / "net/lib/specs"
|
||||
|
||||
sys.path.append(tools_full_path.as_posix())
|
||||
from net.lib.ynl.pyynl.lib import YnlFamily, NlError
|
||||
from net.lib.ynl.pyynl.lib import YnlFamily, NlError, Netlink
|
||||
else:
|
||||
# Running in tree
|
||||
tools_full_path = KSRC / "tools"
|
||||
SPEC_PATH = KSRC / "Documentation/netlink/specs"
|
||||
|
||||
sys.path.append(tools_full_path.as_posix())
|
||||
from net.ynl.pyynl.lib import YnlFamily, NlError
|
||||
from net.ynl.pyynl.lib import YnlFamily, NlError, Netlink
|
||||
except ModuleNotFoundError as e:
|
||||
ksft_pr("Failed importing `ynl` library from kernel sources")
|
||||
ksft_pr(str(e))
|
||||
ktap_result(True, comment="SKIP")
|
||||
sys.exit(4)
|
||||
|
||||
__all__ = [
|
||||
"NlError", "Netlink", "YnlFamily", "SPEC_PATH",
|
||||
"EthtoolFamily", "RtnlFamily", "RtnlAddrFamily",
|
||||
"NetdevFamily", "NetshaperFamily", "DevlinkFamily", "PSPFamily",
|
||||
]
|
||||
|
||||
#
|
||||
# Wrapper classes, loading the right specs
|
||||
# Set schema='' to avoid jsonschema validation, it's slow
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user