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:
Linus Torvalds
2024-01-18 17:33:50 -08:00
90 changed files with 1366 additions and 235 deletions

View 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");
}

View File

@@ -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"))

View File

@@ -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

View 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";

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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";

View File

@@ -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

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
# Regression Test:

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
# Regression Test:

View File

@@ -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
# -------

View File

@@ -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]}

View 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

View File

@@ -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/
}

View File

@@ -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

View File

@@ -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
View File

View 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

View File

@@ -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

View File

@@ -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;