mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git
synced 2026-05-02 18:17:50 -04:00
Merge tag 'net-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Pull networking fixes from Jakub Kicinski:
"Including fixes from bpf and netfilter.
Previous releases - regressions:
- Revert "net: rtnetlink: Enslave device before bringing it up",
breaks the case inverse to the one it was trying to fix
- net: dsa: fix oob access in DSA's netdevice event handler
dereference netdev_priv() before check its a DSA port
- sched: track device in tcf_block_get/put_ext() only for clsact
binder types
- net: tls, fix WARNING in __sk_msg_free when record becomes full
during splice and MORE hint set
- sfp-bus: fix SFP mode detect from bitrate
- drv: stmmac: prevent DSA tags from breaking COE
Previous releases - always broken:
- bpf: fix no forward progress in in bpf_iter_udp if output buffer is
too small
- bpf: reject variable offset alu on registers with a type of
PTR_TO_FLOW_KEYS to prevent oob access
- netfilter: tighten input validation
- net: add more sanity check in virtio_net_hdr_to_skb()
- rxrpc: fix use of Don't Fragment flag on RESPONSE packets, avoid
infinite loop
- amt: do not use the portion of skb->cb area which may get clobbered
- mptcp: improve validation of the MPTCPOPT_MP_JOIN MCTCP option
Misc:
- spring cleanup of inactive maintainers"
* tag 'net-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (88 commits)
i40e: Include types.h to some headers
ipv6: mcast: fix data-race in ipv6_mc_down / mld_ifc_work
selftests: mlxsw: qos_pfc: Adjust the test to support 8 lanes
selftests: mlxsw: qos_pfc: Remove wrong description
mlxsw: spectrum_router: Register netdevice notifier before nexthop
mlxsw: spectrum_acl_tcam: Fix stack corruption
mlxsw: spectrum_acl_tcam: Fix NULL pointer dereference in error path
mlxsw: spectrum_acl_erp: Fix error flow of pool allocation failure
ethtool: netlink: Add missing ethnl_ops_begin/complete
selftests: bonding: Add more missing config options
selftests: netdevsim: add a config file
libbpf: warn on unexpected __arg_ctx type when rewriting BTF
selftests/bpf: add tests confirming type logic in kernel for __arg_ctx
bpf: enforce types for __arg_ctx-tagged arguments in global subprogs
bpf: extract bpf_ctx_convert_map logic and make it more reusable
libbpf: feature-detect arg:ctx tag support in kernel
ipvs: avoid stat macros calls from preemptible context
netfilter: nf_tables: reject NFT_SET_CONCAT with not field length description
netfilter: nf_tables: skip dead set elements in netlink dump
netfilter: nf_tables: do not allow mismatch field size and set key length
...
This commit is contained in:
135
tools/testing/selftests/bpf/prog_tests/sock_iter_batch.c
Normal file
135
tools/testing/selftests/bpf/prog_tests/sock_iter_batch.c
Normal file
@@ -0,0 +1,135 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (c) 2024 Meta
|
||||
|
||||
#include <test_progs.h>
|
||||
#include "network_helpers.h"
|
||||
#include "sock_iter_batch.skel.h"
|
||||
|
||||
#define TEST_NS "sock_iter_batch_netns"
|
||||
|
||||
static const int nr_soreuse = 4;
|
||||
|
||||
static void do_test(int sock_type, bool onebyone)
|
||||
{
|
||||
int err, i, nread, to_read, total_read, iter_fd = -1;
|
||||
int first_idx, second_idx, indices[nr_soreuse];
|
||||
struct bpf_link *link = NULL;
|
||||
struct sock_iter_batch *skel;
|
||||
int *fds[2] = {};
|
||||
|
||||
skel = sock_iter_batch__open();
|
||||
if (!ASSERT_OK_PTR(skel, "sock_iter_batch__open"))
|
||||
return;
|
||||
|
||||
/* Prepare 2 buckets of sockets in the kernel hashtable */
|
||||
for (i = 0; i < ARRAY_SIZE(fds); i++) {
|
||||
int local_port;
|
||||
|
||||
fds[i] = start_reuseport_server(AF_INET6, sock_type, "::1", 0, 0,
|
||||
nr_soreuse);
|
||||
if (!ASSERT_OK_PTR(fds[i], "start_reuseport_server"))
|
||||
goto done;
|
||||
local_port = get_socket_local_port(*fds[i]);
|
||||
if (!ASSERT_GE(local_port, 0, "get_socket_local_port"))
|
||||
goto done;
|
||||
skel->rodata->ports[i] = ntohs(local_port);
|
||||
}
|
||||
|
||||
err = sock_iter_batch__load(skel);
|
||||
if (!ASSERT_OK(err, "sock_iter_batch__load"))
|
||||
goto done;
|
||||
|
||||
link = bpf_program__attach_iter(sock_type == SOCK_STREAM ?
|
||||
skel->progs.iter_tcp_soreuse :
|
||||
skel->progs.iter_udp_soreuse,
|
||||
NULL);
|
||||
if (!ASSERT_OK_PTR(link, "bpf_program__attach_iter"))
|
||||
goto done;
|
||||
|
||||
iter_fd = bpf_iter_create(bpf_link__fd(link));
|
||||
if (!ASSERT_GE(iter_fd, 0, "bpf_iter_create"))
|
||||
goto done;
|
||||
|
||||
/* Test reading a bucket (either from fds[0] or fds[1]).
|
||||
* Only read "nr_soreuse - 1" number of sockets
|
||||
* from a bucket and leave one socket out from
|
||||
* that bucket on purpose.
|
||||
*/
|
||||
to_read = (nr_soreuse - 1) * sizeof(*indices);
|
||||
total_read = 0;
|
||||
first_idx = -1;
|
||||
do {
|
||||
nread = read(iter_fd, indices, onebyone ? sizeof(*indices) : to_read);
|
||||
if (nread <= 0 || nread % sizeof(*indices))
|
||||
break;
|
||||
total_read += nread;
|
||||
|
||||
if (first_idx == -1)
|
||||
first_idx = indices[0];
|
||||
for (i = 0; i < nread / sizeof(*indices); i++)
|
||||
ASSERT_EQ(indices[i], first_idx, "first_idx");
|
||||
} while (total_read < to_read);
|
||||
ASSERT_EQ(nread, onebyone ? sizeof(*indices) : to_read, "nread");
|
||||
ASSERT_EQ(total_read, to_read, "total_read");
|
||||
|
||||
free_fds(fds[first_idx], nr_soreuse);
|
||||
fds[first_idx] = NULL;
|
||||
|
||||
/* Read the "whole" second bucket */
|
||||
to_read = nr_soreuse * sizeof(*indices);
|
||||
total_read = 0;
|
||||
second_idx = !first_idx;
|
||||
do {
|
||||
nread = read(iter_fd, indices, onebyone ? sizeof(*indices) : to_read);
|
||||
if (nread <= 0 || nread % sizeof(*indices))
|
||||
break;
|
||||
total_read += nread;
|
||||
|
||||
for (i = 0; i < nread / sizeof(*indices); i++)
|
||||
ASSERT_EQ(indices[i], second_idx, "second_idx");
|
||||
} while (total_read <= to_read);
|
||||
ASSERT_EQ(nread, 0, "nread");
|
||||
/* Both so_reuseport ports should be in different buckets, so
|
||||
* total_read must equal to the expected to_read.
|
||||
*
|
||||
* For a very unlikely case, both ports collide at the same bucket,
|
||||
* the bucket offset (i.e. 3) will be skipped and it cannot
|
||||
* expect the to_read number of bytes.
|
||||
*/
|
||||
if (skel->bss->bucket[0] != skel->bss->bucket[1])
|
||||
ASSERT_EQ(total_read, to_read, "total_read");
|
||||
|
||||
done:
|
||||
for (i = 0; i < ARRAY_SIZE(fds); i++)
|
||||
free_fds(fds[i], nr_soreuse);
|
||||
if (iter_fd < 0)
|
||||
close(iter_fd);
|
||||
bpf_link__destroy(link);
|
||||
sock_iter_batch__destroy(skel);
|
||||
}
|
||||
|
||||
void test_sock_iter_batch(void)
|
||||
{
|
||||
struct nstoken *nstoken = NULL;
|
||||
|
||||
SYS_NOFAIL("ip netns del " TEST_NS " &> /dev/null");
|
||||
SYS(done, "ip netns add %s", TEST_NS);
|
||||
SYS(done, "ip -net %s link set dev lo up", TEST_NS);
|
||||
|
||||
nstoken = open_netns(TEST_NS);
|
||||
if (!ASSERT_OK_PTR(nstoken, "open_netns"))
|
||||
goto done;
|
||||
|
||||
if (test__start_subtest("tcp")) {
|
||||
do_test(SOCK_STREAM, true);
|
||||
do_test(SOCK_STREAM, false);
|
||||
}
|
||||
if (test__start_subtest("udp")) {
|
||||
do_test(SOCK_DGRAM, true);
|
||||
do_test(SOCK_DGRAM, false);
|
||||
}
|
||||
close_netns(nstoken);
|
||||
|
||||
done:
|
||||
SYS_NOFAIL("ip netns del " TEST_NS " &> /dev/null");
|
||||
}
|
||||
@@ -47,6 +47,19 @@ static void subtest_ctx_arg_rewrite(void)
|
||||
struct btf *btf = NULL;
|
||||
__u32 info_len = sizeof(info);
|
||||
int err, fd, i;
|
||||
struct btf *kern_btf = NULL;
|
||||
|
||||
kern_btf = btf__load_vmlinux_btf();
|
||||
if (!ASSERT_OK_PTR(kern_btf, "kern_btf_load"))
|
||||
return;
|
||||
|
||||
/* simple detection of kernel native arg:ctx tag support */
|
||||
if (btf__find_by_name_kind(kern_btf, "bpf_subprog_arg_info", BTF_KIND_STRUCT) > 0) {
|
||||
test__skip();
|
||||
btf__free(kern_btf);
|
||||
return;
|
||||
}
|
||||
btf__free(kern_btf);
|
||||
|
||||
skel = test_global_func_ctx_args__open();
|
||||
if (!ASSERT_OK_PTR(skel, "skel_open"))
|
||||
|
||||
@@ -72,6 +72,8 @@
|
||||
#define inet_rcv_saddr sk.__sk_common.skc_rcv_saddr
|
||||
#define inet_dport sk.__sk_common.skc_dport
|
||||
|
||||
#define udp_portaddr_hash inet.sk.__sk_common.skc_u16hashes[1]
|
||||
|
||||
#define ir_loc_addr req.__req_common.skc_rcv_saddr
|
||||
#define ir_num req.__req_common.skc_num
|
||||
#define ir_rmt_addr req.__req_common.skc_daddr
|
||||
@@ -85,6 +87,7 @@
|
||||
#define sk_rmem_alloc sk_backlog.rmem_alloc
|
||||
#define sk_refcnt __sk_common.skc_refcnt
|
||||
#define sk_state __sk_common.skc_state
|
||||
#define sk_net __sk_common.skc_net
|
||||
#define sk_v6_daddr __sk_common.skc_v6_daddr
|
||||
#define sk_v6_rcv_saddr __sk_common.skc_v6_rcv_saddr
|
||||
#define sk_flags __sk_common.skc_flags
|
||||
|
||||
91
tools/testing/selftests/bpf/progs/sock_iter_batch.c
Normal file
91
tools/testing/selftests/bpf/progs/sock_iter_batch.c
Normal file
@@ -0,0 +1,91 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (c) 2024 Meta
|
||||
|
||||
#include "vmlinux.h"
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_core_read.h>
|
||||
#include <bpf/bpf_endian.h>
|
||||
#include "bpf_tracing_net.h"
|
||||
#include "bpf_kfuncs.h"
|
||||
|
||||
#define ATTR __always_inline
|
||||
#include "test_jhash.h"
|
||||
|
||||
static bool ipv6_addr_loopback(const struct in6_addr *a)
|
||||
{
|
||||
return (a->s6_addr32[0] | a->s6_addr32[1] |
|
||||
a->s6_addr32[2] | (a->s6_addr32[3] ^ bpf_htonl(1))) == 0;
|
||||
}
|
||||
|
||||
volatile const __u16 ports[2];
|
||||
unsigned int bucket[2];
|
||||
|
||||
SEC("iter/tcp")
|
||||
int iter_tcp_soreuse(struct bpf_iter__tcp *ctx)
|
||||
{
|
||||
struct sock *sk = (struct sock *)ctx->sk_common;
|
||||
struct inet_hashinfo *hinfo;
|
||||
unsigned int hash;
|
||||
struct net *net;
|
||||
int idx;
|
||||
|
||||
if (!sk)
|
||||
return 0;
|
||||
|
||||
sk = bpf_rdonly_cast(sk, bpf_core_type_id_kernel(struct sock));
|
||||
if (sk->sk_family != AF_INET6 ||
|
||||
sk->sk_state != TCP_LISTEN ||
|
||||
!ipv6_addr_loopback(&sk->sk_v6_rcv_saddr))
|
||||
return 0;
|
||||
|
||||
if (sk->sk_num == ports[0])
|
||||
idx = 0;
|
||||
else if (sk->sk_num == ports[1])
|
||||
idx = 1;
|
||||
else
|
||||
return 0;
|
||||
|
||||
/* bucket selection as in inet_lhash2_bucket_sk() */
|
||||
net = sk->sk_net.net;
|
||||
hash = jhash2(sk->sk_v6_rcv_saddr.s6_addr32, 4, net->hash_mix);
|
||||
hash ^= sk->sk_num;
|
||||
hinfo = net->ipv4.tcp_death_row.hashinfo;
|
||||
bucket[idx] = hash & hinfo->lhash2_mask;
|
||||
bpf_seq_write(ctx->meta->seq, &idx, sizeof(idx));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define udp_sk(ptr) container_of(ptr, struct udp_sock, inet.sk)
|
||||
|
||||
SEC("iter/udp")
|
||||
int iter_udp_soreuse(struct bpf_iter__udp *ctx)
|
||||
{
|
||||
struct sock *sk = (struct sock *)ctx->udp_sk;
|
||||
struct udp_table *udptable;
|
||||
int idx;
|
||||
|
||||
if (!sk)
|
||||
return 0;
|
||||
|
||||
sk = bpf_rdonly_cast(sk, bpf_core_type_id_kernel(struct sock));
|
||||
if (sk->sk_family != AF_INET6 ||
|
||||
!ipv6_addr_loopback(&sk->sk_v6_rcv_saddr))
|
||||
return 0;
|
||||
|
||||
if (sk->sk_num == ports[0])
|
||||
idx = 0;
|
||||
else if (sk->sk_num == ports[1])
|
||||
idx = 1;
|
||||
else
|
||||
return 0;
|
||||
|
||||
/* bucket selection as in udp_hashslot2() */
|
||||
udptable = sk->sk_net.net->ipv4.udp_table;
|
||||
bucket[idx] = udp_sk(sk)->udp_portaddr_hash & udptable->mask;
|
||||
bpf_seq_write(ctx->meta->seq, &idx, sizeof(idx));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
@@ -69,3 +69,34 @@ u32 jhash(const void *key, u32 length, u32 initval)
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static __always_inline u32 jhash2(const u32 *k, u32 length, u32 initval)
|
||||
{
|
||||
u32 a, b, c;
|
||||
|
||||
/* Set up the internal state */
|
||||
a = b = c = JHASH_INITVAL + (length<<2) + initval;
|
||||
|
||||
/* Handle most of the key */
|
||||
while (length > 3) {
|
||||
a += k[0];
|
||||
b += k[1];
|
||||
c += k[2];
|
||||
__jhash_mix(a, b, c);
|
||||
length -= 3;
|
||||
k += 3;
|
||||
}
|
||||
|
||||
/* Handle the last 3 u32's */
|
||||
switch (length) {
|
||||
case 3: c += k[2];
|
||||
case 2: b += k[1];
|
||||
case 1: a += k[0];
|
||||
__jhash_final(a, b, c);
|
||||
break;
|
||||
case 0: /* Nothing left to add */
|
||||
break;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <vmlinux.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
#include "bpf_misc.h"
|
||||
#include "xdp_metadata.h"
|
||||
#include "bpf_kfuncs.h"
|
||||
@@ -138,25 +139,182 @@ __weak int subprog_ctx_tag(void *ctx __arg_ctx)
|
||||
return bpf_get_stack(ctx, stack, sizeof(stack), 0);
|
||||
}
|
||||
|
||||
__weak int raw_tp_canonical(struct bpf_raw_tracepoint_args *ctx __arg_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
__weak int raw_tp_u64_array(u64 *ctx __arg_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("?raw_tp")
|
||||
__success __log_level(2)
|
||||
int arg_tag_ctx_raw_tp(void *ctx)
|
||||
{
|
||||
return subprog_ctx_tag(ctx);
|
||||
return subprog_ctx_tag(ctx) + raw_tp_canonical(ctx) + raw_tp_u64_array(ctx);
|
||||
}
|
||||
|
||||
SEC("?raw_tp.w")
|
||||
__success __log_level(2)
|
||||
int arg_tag_ctx_raw_tp_writable(void *ctx)
|
||||
{
|
||||
return subprog_ctx_tag(ctx) + raw_tp_canonical(ctx) + raw_tp_u64_array(ctx);
|
||||
}
|
||||
|
||||
SEC("?tp_btf/sys_enter")
|
||||
__success __log_level(2)
|
||||
int arg_tag_ctx_raw_tp_btf(void *ctx)
|
||||
{
|
||||
return subprog_ctx_tag(ctx) + raw_tp_canonical(ctx) + raw_tp_u64_array(ctx);
|
||||
}
|
||||
|
||||
struct whatever { };
|
||||
|
||||
__weak int tp_whatever(struct whatever *ctx __arg_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("?tp")
|
||||
__success __log_level(2)
|
||||
int arg_tag_ctx_tp(void *ctx)
|
||||
{
|
||||
return subprog_ctx_tag(ctx);
|
||||
return subprog_ctx_tag(ctx) + tp_whatever(ctx);
|
||||
}
|
||||
|
||||
__weak int kprobe_subprog_pt_regs(struct pt_regs *ctx __arg_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
__weak int kprobe_subprog_typedef(bpf_user_pt_regs_t *ctx __arg_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("?kprobe")
|
||||
__success __log_level(2)
|
||||
int arg_tag_ctx_kprobe(void *ctx)
|
||||
{
|
||||
return subprog_ctx_tag(ctx);
|
||||
return subprog_ctx_tag(ctx) +
|
||||
kprobe_subprog_pt_regs(ctx) +
|
||||
kprobe_subprog_typedef(ctx);
|
||||
}
|
||||
|
||||
__weak int perf_subprog_regs(
|
||||
#if defined(bpf_target_riscv)
|
||||
struct user_regs_struct *ctx __arg_ctx
|
||||
#elif defined(bpf_target_s390)
|
||||
/* user_pt_regs typedef is anonymous struct, so only `void *` works */
|
||||
void *ctx __arg_ctx
|
||||
#elif defined(bpf_target_loongarch) || defined(bpf_target_arm64) || defined(bpf_target_powerpc)
|
||||
struct user_pt_regs *ctx __arg_ctx
|
||||
#else
|
||||
struct pt_regs *ctx __arg_ctx
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
__weak int perf_subprog_typedef(bpf_user_pt_regs_t *ctx __arg_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
__weak int perf_subprog_canonical(struct bpf_perf_event_data *ctx __arg_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("?perf_event")
|
||||
__success __log_level(2)
|
||||
int arg_tag_ctx_perf(void *ctx)
|
||||
{
|
||||
return subprog_ctx_tag(ctx) +
|
||||
perf_subprog_regs(ctx) +
|
||||
perf_subprog_typedef(ctx) +
|
||||
perf_subprog_canonical(ctx);
|
||||
}
|
||||
|
||||
__weak int iter_subprog_void(void *ctx __arg_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
__weak int iter_subprog_typed(struct bpf_iter__task *ctx __arg_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("?iter/task")
|
||||
__success __log_level(2)
|
||||
int arg_tag_ctx_iter_task(struct bpf_iter__task *ctx)
|
||||
{
|
||||
return (iter_subprog_void(ctx) + iter_subprog_typed(ctx)) & 1;
|
||||
}
|
||||
|
||||
__weak int tracing_subprog_void(void *ctx __arg_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
__weak int tracing_subprog_u64(u64 *ctx __arg_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int acc;
|
||||
|
||||
SEC("?fentry/" SYS_PREFIX "sys_nanosleep")
|
||||
__success __log_level(2)
|
||||
int BPF_PROG(arg_tag_ctx_fentry)
|
||||
{
|
||||
acc += tracing_subprog_void(ctx) + tracing_subprog_u64(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("?fexit/" SYS_PREFIX "sys_nanosleep")
|
||||
__success __log_level(2)
|
||||
int BPF_PROG(arg_tag_ctx_fexit)
|
||||
{
|
||||
acc += tracing_subprog_void(ctx) + tracing_subprog_u64(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("?fmod_ret/" SYS_PREFIX "sys_nanosleep")
|
||||
__success __log_level(2)
|
||||
int BPF_PROG(arg_tag_ctx_fmod_ret)
|
||||
{
|
||||
return tracing_subprog_void(ctx) + tracing_subprog_u64(ctx);
|
||||
}
|
||||
|
||||
SEC("?lsm/bpf")
|
||||
__success __log_level(2)
|
||||
int BPF_PROG(arg_tag_ctx_lsm)
|
||||
{
|
||||
return tracing_subprog_void(ctx) + tracing_subprog_u64(ctx);
|
||||
}
|
||||
|
||||
SEC("?struct_ops/test_1")
|
||||
__success __log_level(2)
|
||||
int BPF_PROG(arg_tag_ctx_struct_ops)
|
||||
{
|
||||
return tracing_subprog_void(ctx) + tracing_subprog_u64(ctx);
|
||||
}
|
||||
|
||||
SEC(".struct_ops")
|
||||
struct bpf_dummy_ops dummy_1 = {
|
||||
.test_1 = (void *)arg_tag_ctx_struct_ops,
|
||||
};
|
||||
|
||||
SEC("?syscall")
|
||||
__success __log_level(2)
|
||||
int arg_tag_ctx_syscall(void *ctx)
|
||||
{
|
||||
return tracing_subprog_void(ctx) + tracing_subprog_u64(ctx) + tp_whatever(ctx);
|
||||
}
|
||||
|
||||
__weak int subprog_dynptr(struct bpf_dynptr *dptr)
|
||||
|
||||
@@ -146,4 +146,23 @@ l0_%=: exit; \
|
||||
: __clobber_all);
|
||||
}
|
||||
|
||||
SEC("flow_dissector")
|
||||
__description("flow_keys illegal alu op with variable offset")
|
||||
__failure __msg("R7 pointer arithmetic on flow_keys prohibited")
|
||||
__naked void flow_keys_illegal_variable_offset_alu(void)
|
||||
{
|
||||
asm volatile(" \
|
||||
r6 = r1; \
|
||||
r7 = *(u64*)(r6 + %[flow_keys_off]); \
|
||||
r8 = 8; \
|
||||
r8 /= 1; \
|
||||
r8 &= 8; \
|
||||
r7 += r8; \
|
||||
r0 = *(u64*)(r7 + 0); \
|
||||
exit; \
|
||||
" :
|
||||
: __imm_const(flow_keys_off, offsetof(struct __sk_buff, flow_keys))
|
||||
: __clobber_all);
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
||||
@@ -1,2 +1,10 @@
|
||||
CONFIG_BONDING=y
|
||||
CONFIG_BRIDGE=y
|
||||
CONFIG_DUMMY=y
|
||||
CONFIG_IPV6=y
|
||||
CONFIG_MACVLAN=y
|
||||
CONFIG_NET_ACT_GACT=y
|
||||
CONFIG_NET_CLS_FLOWER=y
|
||||
CONFIG_NET_SCH_INGRESS=y
|
||||
CONFIG_NLMON=y
|
||||
CONFIG_VETH=y
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
# Regression Test:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
# Regression Test:
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
# | + $swp1 $swp3 + + $swp4 |
|
||||
# | | iPOOL1 iPOOL0 | | iPOOL2 |
|
||||
# | | ePOOL4 ePOOL5 | | ePOOL4 |
|
||||
# | | 1Gbps | | 1Gbps |
|
||||
# | | PFC:enabled=1 | | PFC:enabled=1 |
|
||||
# | +-|----------------------|-+ +-|------------------------+ |
|
||||
# | | + $swp1.111 $swp3.111 + | | + $swp4.111 | |
|
||||
@@ -120,6 +119,9 @@ h2_destroy()
|
||||
|
||||
switch_create()
|
||||
{
|
||||
local lanes_swp4
|
||||
local pg1_size
|
||||
|
||||
# pools
|
||||
# -----
|
||||
|
||||
@@ -229,7 +231,20 @@ switch_create()
|
||||
dcb pfc set dev $swp4 prio-pfc all:off 1:on
|
||||
# PG0 will get autoconfigured to Xoff, give PG1 arbitrarily 100K, which
|
||||
# is (-2*MTU) about 80K of delay provision.
|
||||
dcb buffer set dev $swp4 buffer-size all:0 1:$_100KB
|
||||
pg1_size=$_100KB
|
||||
|
||||
setup_wait_dev_with_timeout $swp4
|
||||
|
||||
lanes_swp4=$(ethtool $swp4 | grep 'Lanes:')
|
||||
lanes_swp4=${lanes_swp4#*"Lanes: "}
|
||||
|
||||
# 8-lane ports use two buffers among which the configured buffer
|
||||
# is split, so double the size to get twice (20K + 80K).
|
||||
if [[ $lanes_swp4 -eq 8 ]]; then
|
||||
pg1_size=$((pg1_size * 2))
|
||||
fi
|
||||
|
||||
dcb buffer set dev $swp4 buffer-size all:0 1:$pg1_size
|
||||
|
||||
# bridges
|
||||
# -------
|
||||
|
||||
@@ -10,7 +10,8 @@ lib_dir=$(dirname $0)/../../../../net/forwarding
|
||||
ALL_TESTS="single_mask_test identical_filters_test two_masks_test \
|
||||
multiple_masks_test ctcam_edge_cases_test delta_simple_test \
|
||||
delta_two_masks_one_key_test delta_simple_rehash_test \
|
||||
bloom_simple_test bloom_complex_test bloom_delta_test"
|
||||
bloom_simple_test bloom_complex_test bloom_delta_test \
|
||||
max_erp_entries_test max_group_size_test"
|
||||
NUM_NETIFS=2
|
||||
source $lib_dir/lib.sh
|
||||
source $lib_dir/tc_common.sh
|
||||
@@ -983,6 +984,109 @@ bloom_delta_test()
|
||||
log_test "bloom delta test ($tcflags)"
|
||||
}
|
||||
|
||||
max_erp_entries_test()
|
||||
{
|
||||
# The number of eRP entries is limited. Once the maximum number of eRPs
|
||||
# has been reached, filters cannot be added. This test verifies that
|
||||
# when this limit is reached, inserstion fails without crashing.
|
||||
|
||||
RET=0
|
||||
|
||||
local num_masks=32
|
||||
local num_regions=15
|
||||
local chain_failed
|
||||
local mask_failed
|
||||
local ret
|
||||
|
||||
if [[ "$tcflags" != "skip_sw" ]]; then
|
||||
return 0;
|
||||
fi
|
||||
|
||||
for ((i=1; i < $num_regions; i++)); do
|
||||
for ((j=$num_masks; j >= 0; j--)); do
|
||||
tc filter add dev $h2 ingress chain $i protocol ip \
|
||||
pref $i handle $j flower $tcflags \
|
||||
dst_ip 192.1.0.0/$j &> /dev/null
|
||||
ret=$?
|
||||
|
||||
if [ $ret -ne 0 ]; then
|
||||
chain_failed=$i
|
||||
mask_failed=$j
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# We expect to exceed the maximum number of eRP entries, so that
|
||||
# insertion eventually fails. Otherwise, the test should be adjusted to
|
||||
# add more filters.
|
||||
check_fail $ret "expected to exceed number of eRP entries"
|
||||
|
||||
for ((; i >= 1; i--)); do
|
||||
for ((j=0; j <= $num_masks; j++)); do
|
||||
tc filter del dev $h2 ingress chain $i protocol ip \
|
||||
pref $i handle $j flower &> /dev/null
|
||||
done
|
||||
done
|
||||
|
||||
log_test "max eRP entries test ($tcflags). " \
|
||||
"max chain $chain_failed, mask $mask_failed"
|
||||
}
|
||||
|
||||
max_group_size_test()
|
||||
{
|
||||
# The number of ACLs in an ACL group is limited. Once the maximum
|
||||
# number of ACLs has been reached, filters cannot be added. This test
|
||||
# verifies that when this limit is reached, insertion fails without
|
||||
# crashing.
|
||||
|
||||
RET=0
|
||||
|
||||
local num_acls=32
|
||||
local max_size
|
||||
local ret
|
||||
|
||||
if [[ "$tcflags" != "skip_sw" ]]; then
|
||||
return 0;
|
||||
fi
|
||||
|
||||
for ((i=1; i < $num_acls; i++)); do
|
||||
if [[ $(( i % 2 )) == 1 ]]; then
|
||||
tc filter add dev $h2 ingress pref $i proto ipv4 \
|
||||
flower $tcflags dst_ip 198.51.100.1/32 \
|
||||
ip_proto tcp tcp_flags 0x01/0x01 \
|
||||
action drop &> /dev/null
|
||||
else
|
||||
tc filter add dev $h2 ingress pref $i proto ipv6 \
|
||||
flower $tcflags dst_ip 2001:db8:1::1/128 \
|
||||
action drop &> /dev/null
|
||||
fi
|
||||
|
||||
ret=$?
|
||||
[[ $ret -ne 0 ]] && max_size=$((i - 1)) && break
|
||||
done
|
||||
|
||||
# We expect to exceed the maximum number of ACLs in a group, so that
|
||||
# insertion eventually fails. Otherwise, the test should be adjusted to
|
||||
# add more filters.
|
||||
check_fail $ret "expected to exceed number of ACLs in a group"
|
||||
|
||||
for ((; i >= 1; i--)); do
|
||||
if [[ $(( i % 2 )) == 1 ]]; then
|
||||
tc filter del dev $h2 ingress pref $i proto ipv4 \
|
||||
flower $tcflags dst_ip 198.51.100.1/32 \
|
||||
ip_proto tcp tcp_flags 0x01/0x01 \
|
||||
action drop &> /dev/null
|
||||
else
|
||||
tc filter del dev $h2 ingress pref $i proto ipv6 \
|
||||
flower $tcflags dst_ip 2001:db8:1::1/128 \
|
||||
action drop &> /dev/null
|
||||
fi
|
||||
done
|
||||
|
||||
log_test "max ACL group size test ($tcflags). max size $max_size"
|
||||
}
|
||||
|
||||
setup_prepare()
|
||||
{
|
||||
h1=${NETIFS[p1]}
|
||||
|
||||
10
tools/testing/selftests/drivers/net/netdevsim/config
Normal file
10
tools/testing/selftests/drivers/net/netdevsim/config
Normal file
@@ -0,0 +1,10 @@
|
||||
CONFIG_DUMMY=y
|
||||
CONFIG_GENEVE=m
|
||||
CONFIG_IPV6=y
|
||||
CONFIG_NETDEVSIM=m
|
||||
CONFIG_NET_SCH_MQPRIO=y
|
||||
CONFIG_NET_SCH_MULTIQ=y
|
||||
CONFIG_NET_SCH_PRIO=y
|
||||
CONFIG_PSAMPLE=y
|
||||
CONFIG_PTP_1588_CLOCK_MOCK=y
|
||||
CONFIG_VXLAN=m
|
||||
@@ -51,6 +51,7 @@ function make_netdev {
|
||||
fi
|
||||
|
||||
echo $NSIM_ID $@ > /sys/bus/netdevsim/new_device
|
||||
udevadm settle
|
||||
# get new device name
|
||||
ls /sys/bus/netdevsim/devices/netdevsim${NSIM_ID}/net/
|
||||
}
|
||||
|
||||
@@ -8,16 +8,20 @@ NSIM_NETDEV=$(make_netdev)
|
||||
|
||||
set -o pipefail
|
||||
|
||||
# Since commit 2b3ddcb35357 ("ethtool: fec: Change the prompt ...")
|
||||
# in ethtool CLI the Configured lines start with Supported/Configured.
|
||||
configured=$($ETHTOOL --show-fec $NSIM_NETDEV | tail -2 | head -1 | cut -d' ' -f1)
|
||||
|
||||
# netdevsim starts out with None/None
|
||||
s=$($ETHTOOL --show-fec $NSIM_NETDEV | tail -2)
|
||||
check $? "$s" "Configured FEC encodings: None
|
||||
check $? "$s" "$configured FEC encodings: None
|
||||
Active FEC encoding: None"
|
||||
|
||||
# Test Auto
|
||||
$ETHTOOL --set-fec $NSIM_NETDEV encoding auto
|
||||
check $?
|
||||
s=$($ETHTOOL --show-fec $NSIM_NETDEV | tail -2)
|
||||
check $? "$s" "Configured FEC encodings: Auto
|
||||
check $? "$s" "$configured FEC encodings: Auto
|
||||
Active FEC encoding: Off"
|
||||
|
||||
# Test case in-sensitivity
|
||||
@@ -25,7 +29,7 @@ for o in off Off OFF; do
|
||||
$ETHTOOL --set-fec $NSIM_NETDEV encoding $o
|
||||
check $?
|
||||
s=$($ETHTOOL --show-fec $NSIM_NETDEV | tail -2)
|
||||
check $? "$s" "Configured FEC encodings: Off
|
||||
check $? "$s" "$configured FEC encodings: Off
|
||||
Active FEC encoding: Off"
|
||||
done
|
||||
|
||||
@@ -33,7 +37,7 @@ for o in BaseR baser BAser; do
|
||||
$ETHTOOL --set-fec $NSIM_NETDEV encoding $o
|
||||
check $?
|
||||
s=$($ETHTOOL --show-fec $NSIM_NETDEV | tail -2)
|
||||
check $? "$s" "Configured FEC encodings: BaseR
|
||||
check $? "$s" "$configured FEC encodings: BaseR
|
||||
Active FEC encoding: BaseR"
|
||||
done
|
||||
|
||||
@@ -41,7 +45,7 @@ for o in llrs rs; do
|
||||
$ETHTOOL --set-fec $NSIM_NETDEV encoding $o
|
||||
check $?
|
||||
s=$($ETHTOOL --show-fec $NSIM_NETDEV | tail -2)
|
||||
check $? "$s" "Configured FEC encodings: ${o^^}
|
||||
check $? "$s" "$configured FEC encodings: ${o^^}
|
||||
Active FEC encoding: ${o^^}"
|
||||
done
|
||||
|
||||
@@ -49,13 +53,13 @@ done
|
||||
$ETHTOOL --set-fec $NSIM_NETDEV encoding rs llrs
|
||||
check $?
|
||||
s=$($ETHTOOL --show-fec $NSIM_NETDEV | tail -2)
|
||||
check $? "$s" "Configured FEC encodings: RS LLRS
|
||||
check $? "$s" "$configured FEC encodings: RS LLRS
|
||||
Active FEC encoding: LLRS"
|
||||
|
||||
$ETHTOOL --set-fec $NSIM_NETDEV encoding rs off auto
|
||||
check $?
|
||||
s=$($ETHTOOL --show-fec $NSIM_NETDEV | tail -2)
|
||||
check $? "$s" "Configured FEC encodings: Auto Off RS
|
||||
check $? "$s" "$configured FEC encodings: Auto Off RS
|
||||
Active FEC encoding: RS"
|
||||
|
||||
# Make sure other link modes are rejected
|
||||
|
||||
@@ -233,6 +233,7 @@ function print_tables {
|
||||
function get_netdev_name {
|
||||
local -n old=$1
|
||||
|
||||
udevadm settle
|
||||
new=$(ls /sys/class/net)
|
||||
|
||||
for netdev in $new; do
|
||||
|
||||
0
tools/testing/selftests/net/forwarding/lib.sh
Executable file → Normal file
0
tools/testing/selftests/net/forwarding/lib.sh
Executable file → Normal file
@@ -28,6 +28,7 @@ ALL_TESTS="
|
||||
kci_test_neigh_get
|
||||
kci_test_bridge_parent_id
|
||||
kci_test_address_proto
|
||||
kci_test_enslave_bonding
|
||||
"
|
||||
|
||||
devdummy="test-dummy0"
|
||||
@@ -1241,6 +1242,31 @@ kci_test_address_proto()
|
||||
return $ret
|
||||
}
|
||||
|
||||
kci_test_enslave_bonding()
|
||||
{
|
||||
local bond="bond123"
|
||||
local ret=0
|
||||
|
||||
setup_ns testns
|
||||
if [ $? -ne 0 ]; then
|
||||
end_test "SKIP bonding tests: cannot add net namespace $testns"
|
||||
return $ksft_skip
|
||||
fi
|
||||
|
||||
run_cmd ip -netns $testns link add dev $bond type bond mode balance-rr
|
||||
run_cmd ip -netns $testns link add dev $devdummy type dummy
|
||||
run_cmd ip -netns $testns link set dev $devdummy up
|
||||
run_cmd ip -netns $testns link set dev $devdummy master $bond down
|
||||
if [ $ret -ne 0 ]; then
|
||||
end_test "FAIL: initially up interface added to a bond and set down"
|
||||
ip netns del "$testns"
|
||||
return 1
|
||||
fi
|
||||
|
||||
end_test "PASS: enslave interface in a bond"
|
||||
ip netns del "$testns"
|
||||
}
|
||||
|
||||
kci_test_rtnl()
|
||||
{
|
||||
local current_test
|
||||
|
||||
@@ -52,5 +52,5 @@ $(OUTPUT)/%_ipv6: %.c
|
||||
|
||||
$(OUTPUT)/icmps-accept_ipv4: CFLAGS+= -DTEST_ICMPS_ACCEPT
|
||||
$(OUTPUT)/icmps-accept_ipv6: CFLAGS+= -DTEST_ICMPS_ACCEPT
|
||||
$(OUTPUT)/bench-lookups_ipv4: LDFLAGS+= -lm
|
||||
$(OUTPUT)/bench-lookups_ipv6: LDFLAGS+= -lm
|
||||
$(OUTPUT)/bench-lookups_ipv4: LDLIBS+= -lm
|
||||
$(OUTPUT)/bench-lookups_ipv6: LDLIBS+= -lm
|
||||
|
||||
@@ -707,6 +707,20 @@ TEST_F(tls, splice_from_pipe)
|
||||
EXPECT_EQ(memcmp(mem_send, mem_recv, send_len), 0);
|
||||
}
|
||||
|
||||
TEST_F(tls, splice_more)
|
||||
{
|
||||
unsigned int f = SPLICE_F_NONBLOCK | SPLICE_F_MORE | SPLICE_F_GIFT;
|
||||
int send_len = TLS_PAYLOAD_MAX_LEN;
|
||||
char mem_send[TLS_PAYLOAD_MAX_LEN];
|
||||
int i, send_pipe = 1;
|
||||
int p[2];
|
||||
|
||||
ASSERT_GE(pipe(p), 0);
|
||||
EXPECT_GE(write(p[1], mem_send, send_len), 0);
|
||||
for (i = 0; i < 32; i++)
|
||||
EXPECT_EQ(splice(p[0], NULL, self->fd, NULL, send_pipe, f), 1);
|
||||
}
|
||||
|
||||
TEST_F(tls, splice_from_pipe2)
|
||||
{
|
||||
int send_len = 16000;
|
||||
|
||||
Reference in New Issue
Block a user