Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Overlapping header include additions in macsec.c A bug fix in 'net' overlapping with the removal of 'version' string in ena_netdev.c Overlapping test additions in selftests Makefile Overlapping PCI ID table adjustments in iwlwifi driver. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -33,6 +33,7 @@ TARGETS += memory-hotplug
|
||||
TARGETS += mount
|
||||
TARGETS += mqueue
|
||||
TARGETS += net
|
||||
TARGETS += net/forwarding
|
||||
TARGETS += net/mptcp
|
||||
TARGETS += netfilter
|
||||
TARGETS += networking/timestamping
|
||||
|
@@ -0,0 +1,60 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <test_progs.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include "test_send_signal_kern.skel.h"
|
||||
|
||||
static void sigusr1_handler(int signum)
|
||||
{
|
||||
}
|
||||
|
||||
#define THREAD_COUNT 100
|
||||
|
||||
static void *worker(void *p)
|
||||
{
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < 1000; i++)
|
||||
usleep(1);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void test_send_signal_sched_switch(void)
|
||||
{
|
||||
struct test_send_signal_kern *skel;
|
||||
pthread_t threads[THREAD_COUNT];
|
||||
u32 duration = 0;
|
||||
int i, err;
|
||||
|
||||
signal(SIGUSR1, sigusr1_handler);
|
||||
|
||||
skel = test_send_signal_kern__open_and_load();
|
||||
if (CHECK(!skel, "skel_open_and_load", "skeleton open_and_load failed\n"))
|
||||
return;
|
||||
|
||||
skel->bss->pid = getpid();
|
||||
skel->bss->sig = SIGUSR1;
|
||||
|
||||
err = test_send_signal_kern__attach(skel);
|
||||
if (CHECK(err, "skel_attach", "skeleton attach failed\n"))
|
||||
goto destroy_skel;
|
||||
|
||||
for (i = 0; i < THREAD_COUNT; i++) {
|
||||
err = pthread_create(threads + i, NULL, worker, NULL);
|
||||
if (CHECK(err, "pthread_create", "Error creating thread, %s\n",
|
||||
strerror(errno)))
|
||||
goto destroy_skel;
|
||||
}
|
||||
|
||||
for (i = 0; i < THREAD_COUNT; i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
|
||||
destroy_skel:
|
||||
test_send_signal_kern__destroy(skel);
|
||||
}
|
@@ -31,6 +31,12 @@ int send_signal_tp(void *ctx)
|
||||
return bpf_send_signal_test(ctx);
|
||||
}
|
||||
|
||||
SEC("tracepoint/sched/sched_switch")
|
||||
int send_signal_tp_sched(void *ctx)
|
||||
{
|
||||
return bpf_send_signal_test(ctx);
|
||||
}
|
||||
|
||||
SEC("perf_event")
|
||||
int send_signal_perf(void *ctx)
|
||||
{
|
||||
|
@@ -1062,6 +1062,48 @@ static struct btf_raw_test raw_tests[] = {
|
||||
.err_str = "Member exceeds struct_size",
|
||||
},
|
||||
|
||||
/* Test member unexceeds the size of struct
|
||||
*
|
||||
* enum E {
|
||||
* E0,
|
||||
* E1,
|
||||
* };
|
||||
*
|
||||
* struct A {
|
||||
* char m;
|
||||
* enum E __attribute__((packed)) n;
|
||||
* };
|
||||
*/
|
||||
{
|
||||
.descr = "size check test #5",
|
||||
.raw_types = {
|
||||
/* int */ /* [1] */
|
||||
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, sizeof(int)),
|
||||
/* char */ /* [2] */
|
||||
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1),
|
||||
/* enum E { */ /* [3] */
|
||||
BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 2), 1),
|
||||
BTF_ENUM_ENC(NAME_TBD, 0),
|
||||
BTF_ENUM_ENC(NAME_TBD, 1),
|
||||
/* } */
|
||||
/* struct A { */ /* [4] */
|
||||
BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 2),
|
||||
BTF_MEMBER_ENC(NAME_TBD, 2, 0), /* char m; */
|
||||
BTF_MEMBER_ENC(NAME_TBD, 3, 8),/* enum E __attribute__((packed)) n; */
|
||||
/* } */
|
||||
BTF_END_RAW,
|
||||
},
|
||||
.str_sec = "\0E\0E0\0E1\0A\0m\0n",
|
||||
.str_sec_size = sizeof("\0E\0E0\0E1\0A\0m\0n"),
|
||||
.map_type = BPF_MAP_TYPE_ARRAY,
|
||||
.map_name = "size_check5_map",
|
||||
.key_size = sizeof(int),
|
||||
.value_size = 2,
|
||||
.key_type_id = 1,
|
||||
.value_type_id = 4,
|
||||
.max_entries = 4,
|
||||
},
|
||||
|
||||
/* typedef const void * const_void_ptr;
|
||||
* struct A {
|
||||
* const_void_ptr m;
|
||||
|
@@ -61,6 +61,21 @@
|
||||
},
|
||||
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
|
||||
},
|
||||
{
|
||||
"jset32: ignores upper bits",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
BPF_LD_IMM64(BPF_REG_7, 0x8000000000000000),
|
||||
BPF_LD_IMM64(BPF_REG_8, 0x8000000000000000),
|
||||
BPF_JMP_REG(BPF_JSET, BPF_REG_7, BPF_REG_8, 1),
|
||||
BPF_EXIT_INSN(),
|
||||
BPF_JMP32_REG(BPF_JSET, BPF_REG_7, BPF_REG_8, 1),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 2),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.result = ACCEPT,
|
||||
.retval = 2,
|
||||
},
|
||||
{
|
||||
"jset32: min/max deduction",
|
||||
.insns = {
|
||||
|
@@ -11,7 +11,9 @@ TEST_PROGS += udpgso_bench.sh fib_rule_tests.sh msg_zerocopy.sh psock_snd.sh
|
||||
TEST_PROGS += udpgro_bench.sh udpgro.sh test_vxlan_under_vrf.sh reuseport_addr_any.sh
|
||||
TEST_PROGS += test_vxlan_fdb_changelink.sh so_txtime.sh ipv6_flowlabel.sh
|
||||
TEST_PROGS += tcp_fastopen_backup_key.sh fcnal-test.sh l2tp.sh traceroute.sh
|
||||
TEST_PROGS += fin_ack_lat.sh
|
||||
TEST_PROGS += fin_ack_lat.sh fib_nexthop_multiprefix.sh fib_nexthops.sh
|
||||
TEST_PROGS += altnames.sh icmp_redirect.sh ip6_gre_headroom.sh
|
||||
TEST_PROGS += route_localnet.sh
|
||||
TEST_PROGS += reuseaddr_ports_exhausted.sh
|
||||
TEST_PROGS_EXTENDED := in_netns.sh
|
||||
TEST_GEN_FILES = socket nettest
|
||||
|
76
tools/testing/selftests/net/forwarding/Makefile
Normal file
76
tools/testing/selftests/net/forwarding/Makefile
Normal file
@@ -0,0 +1,76 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+ OR MIT
|
||||
|
||||
TEST_PROGS = bridge_igmp.sh \
|
||||
bridge_port_isolation.sh \
|
||||
bridge_sticky_fdb.sh \
|
||||
bridge_vlan_aware.sh \
|
||||
bridge_vlan_unaware.sh \
|
||||
ethtool.sh \
|
||||
gre_inner_v4_multipath.sh \
|
||||
gre_inner_v6_multipath.sh \
|
||||
gre_multipath.sh \
|
||||
ip6gre_inner_v4_multipath.sh \
|
||||
ip6gre_inner_v6_multipath.sh \
|
||||
ipip_flat_gre_key.sh \
|
||||
ipip_flat_gre_keys.sh \
|
||||
ipip_flat_gre.sh \
|
||||
ipip_hier_gre_key.sh \
|
||||
ipip_hier_gre_keys.sh \
|
||||
ipip_hier_gre.sh \
|
||||
loopback.sh \
|
||||
mirror_gre_bound.sh \
|
||||
mirror_gre_bridge_1d.sh \
|
||||
mirror_gre_bridge_1d_vlan.sh \
|
||||
mirror_gre_bridge_1q_lag.sh \
|
||||
mirror_gre_bridge_1q.sh \
|
||||
mirror_gre_changes.sh \
|
||||
mirror_gre_flower.sh \
|
||||
mirror_gre_lag_lacp.sh \
|
||||
mirror_gre_neigh.sh \
|
||||
mirror_gre_nh.sh \
|
||||
mirror_gre.sh \
|
||||
mirror_gre_vlan_bridge_1q.sh \
|
||||
mirror_gre_vlan.sh \
|
||||
mirror_vlan.sh \
|
||||
router_bridge.sh \
|
||||
router_bridge_vlan.sh \
|
||||
router_broadcast.sh \
|
||||
router_mpath_nh.sh \
|
||||
router_multicast.sh \
|
||||
router_multipath.sh \
|
||||
router.sh \
|
||||
router_vid_1.sh \
|
||||
sch_ets.sh \
|
||||
sch_tbf_ets.sh \
|
||||
sch_tbf_prio.sh \
|
||||
sch_tbf_root.sh \
|
||||
tc_actions.sh \
|
||||
tc_chains.sh \
|
||||
tc_flower_router.sh \
|
||||
tc_flower.sh \
|
||||
tc_shblocks.sh \
|
||||
tc_vlan_modify.sh \
|
||||
vxlan_asymmetric.sh \
|
||||
vxlan_bridge_1d_port_8472.sh \
|
||||
vxlan_bridge_1d.sh \
|
||||
vxlan_bridge_1q_port_8472.sh \
|
||||
vxlan_bridge_1q.sh \
|
||||
vxlan_symmetric.sh
|
||||
|
||||
TEST_PROGS_EXTENDED := devlink_lib.sh \
|
||||
ethtool_lib.sh \
|
||||
fib_offload_lib.sh \
|
||||
forwarding.config.sample \
|
||||
ipip_lib.sh \
|
||||
lib.sh \
|
||||
mirror_gre_lib.sh \
|
||||
mirror_gre_topo_lib.sh \
|
||||
mirror_lib.sh \
|
||||
mirror_topo_lib.sh \
|
||||
sch_ets_core.sh \
|
||||
sch_ets_tests.sh \
|
||||
sch_tbf_core.sh \
|
||||
sch_tbf_etsprio.sh \
|
||||
tc_common.sh
|
||||
|
||||
include ../../lib.mk
|
0
tools/testing/selftests/net/forwarding/ethtool_lib.sh
Executable file → Normal file
0
tools/testing/selftests/net/forwarding/ethtool_lib.sh
Executable file → Normal file
@@ -21,6 +21,10 @@
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef SOL_DCCP
|
||||
#define SOL_DCCP 269
|
||||
#endif
|
||||
|
||||
static const char *IP4_ADDR = "127.0.0.1";
|
||||
static const char *IP6_ADDR = "::1";
|
||||
static const char *IP4_MAPPED6 = "::ffff:127.0.0.1";
|
||||
|
@@ -3,6 +3,10 @@
|
||||
|
||||
TEST_PROGS := nft_trans_stress.sh nft_nat.sh bridge_brouter.sh \
|
||||
conntrack_icmp_related.sh nft_flowtable.sh ipvs.sh \
|
||||
nft_concat_range.sh
|
||||
nft_concat_range.sh \
|
||||
nft_queue.sh
|
||||
|
||||
LDLIBS = -lmnl
|
||||
TEST_GEN_FILES = nf-queue
|
||||
|
||||
include ../lib.mk
|
||||
|
@@ -1,2 +1,8 @@
|
||||
CONFIG_NET_NS=y
|
||||
CONFIG_NF_TABLES_INET=y
|
||||
CONFIG_NFT_QUEUE=m
|
||||
CONFIG_NFT_NAT=m
|
||||
CONFIG_NFT_REDIR=m
|
||||
CONFIG_NFT_MASQ=m
|
||||
CONFIG_NFT_FLOW_OFFLOAD=m
|
||||
CONFIG_NF_CT_NETLINK=m
|
||||
|
352
tools/testing/selftests/netfilter/nf-queue.c
Normal file
352
tools/testing/selftests/netfilter/nf-queue.c
Normal file
@@ -0,0 +1,352 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <libmnl/libmnl.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
#include <linux/netfilter/nfnetlink_queue.h>
|
||||
|
||||
struct options {
|
||||
bool count_packets;
|
||||
int verbose;
|
||||
unsigned int queue_num;
|
||||
unsigned int timeout;
|
||||
};
|
||||
|
||||
static unsigned int queue_stats[5];
|
||||
static struct options opts;
|
||||
|
||||
static void help(const char *p)
|
||||
{
|
||||
printf("Usage: %s [-c|-v [-vv] ] [-t timeout] [-q queue_num]\n", p);
|
||||
}
|
||||
|
||||
static int parse_attr_cb(const struct nlattr *attr, void *data)
|
||||
{
|
||||
const struct nlattr **tb = data;
|
||||
int type = mnl_attr_get_type(attr);
|
||||
|
||||
/* skip unsupported attribute in user-space */
|
||||
if (mnl_attr_type_valid(attr, NFQA_MAX) < 0)
|
||||
return MNL_CB_OK;
|
||||
|
||||
switch (type) {
|
||||
case NFQA_MARK:
|
||||
case NFQA_IFINDEX_INDEV:
|
||||
case NFQA_IFINDEX_OUTDEV:
|
||||
case NFQA_IFINDEX_PHYSINDEV:
|
||||
case NFQA_IFINDEX_PHYSOUTDEV:
|
||||
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
|
||||
perror("mnl_attr_validate");
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
break;
|
||||
case NFQA_TIMESTAMP:
|
||||
if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC,
|
||||
sizeof(struct nfqnl_msg_packet_timestamp)) < 0) {
|
||||
perror("mnl_attr_validate2");
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
break;
|
||||
case NFQA_HWADDR:
|
||||
if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC,
|
||||
sizeof(struct nfqnl_msg_packet_hw)) < 0) {
|
||||
perror("mnl_attr_validate2");
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
break;
|
||||
case NFQA_PAYLOAD:
|
||||
break;
|
||||
}
|
||||
tb[type] = attr;
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
static int queue_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[NFQA_MAX+1] = { 0 };
|
||||
struct nfqnl_msg_packet_hdr *ph = NULL;
|
||||
uint32_t id = 0;
|
||||
|
||||
(void)data;
|
||||
|
||||
mnl_attr_parse(nlh, sizeof(struct nfgenmsg), parse_attr_cb, tb);
|
||||
if (tb[NFQA_PACKET_HDR]) {
|
||||
ph = mnl_attr_get_payload(tb[NFQA_PACKET_HDR]);
|
||||
id = ntohl(ph->packet_id);
|
||||
|
||||
if (opts.verbose > 0)
|
||||
printf("packet hook=%u, hwproto 0x%x",
|
||||
ntohs(ph->hw_protocol), ph->hook);
|
||||
|
||||
if (ph->hook >= 5) {
|
||||
fprintf(stderr, "Unknown hook %d\n", ph->hook);
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
|
||||
if (opts.verbose > 0) {
|
||||
uint32_t skbinfo = 0;
|
||||
|
||||
if (tb[NFQA_SKB_INFO])
|
||||
skbinfo = ntohl(mnl_attr_get_u32(tb[NFQA_SKB_INFO]));
|
||||
if (skbinfo & NFQA_SKB_CSUMNOTREADY)
|
||||
printf(" csumnotready");
|
||||
if (skbinfo & NFQA_SKB_GSO)
|
||||
printf(" gso");
|
||||
if (skbinfo & NFQA_SKB_CSUM_NOTVERIFIED)
|
||||
printf(" csumnotverified");
|
||||
puts("");
|
||||
}
|
||||
|
||||
if (opts.count_packets)
|
||||
queue_stats[ph->hook]++;
|
||||
}
|
||||
|
||||
return MNL_CB_OK + id;
|
||||
}
|
||||
|
||||
static struct nlmsghdr *
|
||||
nfq_build_cfg_request(char *buf, uint8_t command, int queue_num)
|
||||
{
|
||||
struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
|
||||
struct nfqnl_msg_config_cmd cmd = {
|
||||
.command = command,
|
||||
.pf = htons(AF_INET),
|
||||
};
|
||||
struct nfgenmsg *nfg;
|
||||
|
||||
nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG;
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST;
|
||||
|
||||
nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
|
||||
|
||||
nfg->nfgen_family = AF_UNSPEC;
|
||||
nfg->version = NFNETLINK_V0;
|
||||
nfg->res_id = htons(queue_num);
|
||||
|
||||
mnl_attr_put(nlh, NFQA_CFG_CMD, sizeof(cmd), &cmd);
|
||||
|
||||
return nlh;
|
||||
}
|
||||
|
||||
static struct nlmsghdr *
|
||||
nfq_build_cfg_params(char *buf, uint8_t mode, int range, int queue_num)
|
||||
{
|
||||
struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
|
||||
struct nfqnl_msg_config_params params = {
|
||||
.copy_range = htonl(range),
|
||||
.copy_mode = mode,
|
||||
};
|
||||
struct nfgenmsg *nfg;
|
||||
|
||||
nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG;
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST;
|
||||
|
||||
nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
|
||||
nfg->nfgen_family = AF_UNSPEC;
|
||||
nfg->version = NFNETLINK_V0;
|
||||
nfg->res_id = htons(queue_num);
|
||||
|
||||
mnl_attr_put(nlh, NFQA_CFG_PARAMS, sizeof(params), ¶ms);
|
||||
|
||||
return nlh;
|
||||
}
|
||||
|
||||
static struct nlmsghdr *
|
||||
nfq_build_verdict(char *buf, int id, int queue_num, int verd)
|
||||
{
|
||||
struct nfqnl_msg_verdict_hdr vh = {
|
||||
.verdict = htonl(verd),
|
||||
.id = htonl(id),
|
||||
};
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfg;
|
||||
|
||||
nlh = mnl_nlmsg_put_header(buf);
|
||||
nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_VERDICT;
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST;
|
||||
nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
|
||||
nfg->nfgen_family = AF_UNSPEC;
|
||||
nfg->version = NFNETLINK_V0;
|
||||
nfg->res_id = htons(queue_num);
|
||||
|
||||
mnl_attr_put(nlh, NFQA_VERDICT_HDR, sizeof(vh), &vh);
|
||||
|
||||
return nlh;
|
||||
}
|
||||
|
||||
static void print_stats(void)
|
||||
{
|
||||
unsigned int last, total;
|
||||
int i;
|
||||
|
||||
if (!opts.count_packets)
|
||||
return;
|
||||
|
||||
total = 0;
|
||||
last = queue_stats[0];
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
printf("hook %d packets %08u\n", i, queue_stats[i]);
|
||||
last = queue_stats[i];
|
||||
total += last;
|
||||
}
|
||||
|
||||
printf("%u packets total\n", total);
|
||||
}
|
||||
|
||||
struct mnl_socket *open_queue(void)
|
||||
{
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
unsigned int queue_num;
|
||||
struct mnl_socket *nl;
|
||||
struct nlmsghdr *nlh;
|
||||
struct timeval tv;
|
||||
uint32_t flags;
|
||||
|
||||
nl = mnl_socket_open(NETLINK_NETFILTER);
|
||||
if (nl == NULL) {
|
||||
perror("mnl_socket_open");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||
perror("mnl_socket_bind");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
queue_num = opts.queue_num;
|
||||
nlh = nfq_build_cfg_request(buf, NFQNL_CFG_CMD_BIND, queue_num);
|
||||
|
||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||
perror("mnl_socket_sendto");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
nlh = nfq_build_cfg_params(buf, NFQNL_COPY_PACKET, 0xFFFF, queue_num);
|
||||
|
||||
flags = NFQA_CFG_F_GSO | NFQA_CFG_F_UID_GID;
|
||||
mnl_attr_put_u32(nlh, NFQA_CFG_FLAGS, htonl(flags));
|
||||
mnl_attr_put_u32(nlh, NFQA_CFG_MASK, htonl(flags));
|
||||
|
||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||
perror("mnl_socket_sendto");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
memset(&tv, 0, sizeof(tv));
|
||||
tv.tv_sec = opts.timeout;
|
||||
if (opts.timeout && setsockopt(mnl_socket_get_fd(nl),
|
||||
SOL_SOCKET, SO_RCVTIMEO,
|
||||
&tv, sizeof(tv))) {
|
||||
perror("setsockopt(SO_RCVTIMEO)");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return nl;
|
||||
}
|
||||
|
||||
static int mainloop(void)
|
||||
{
|
||||
unsigned int buflen = 64 * 1024 + MNL_SOCKET_BUFFER_SIZE;
|
||||
struct mnl_socket *nl;
|
||||
struct nlmsghdr *nlh;
|
||||
unsigned int portid;
|
||||
char *buf;
|
||||
int ret;
|
||||
|
||||
buf = malloc(buflen);
|
||||
if (!buf) {
|
||||
perror("malloc");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
nl = open_queue();
|
||||
portid = mnl_socket_get_portid(nl);
|
||||
|
||||
for (;;) {
|
||||
uint32_t id;
|
||||
|
||||
ret = mnl_socket_recvfrom(nl, buf, buflen);
|
||||
if (ret == -1) {
|
||||
if (errno == ENOBUFS)
|
||||
continue;
|
||||
|
||||
if (errno == EAGAIN) {
|
||||
errno = 0;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
perror("mnl_socket_recvfrom");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = mnl_cb_run(buf, ret, 0, portid, queue_cb, NULL);
|
||||
if (ret < 0) {
|
||||
perror("mnl_cb_run");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
id = ret - MNL_CB_OK;
|
||||
nlh = nfq_build_verdict(buf, id, opts.queue_num, NF_ACCEPT);
|
||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||
perror("mnl_socket_sendto");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
mnl_socket_close(nl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void parse_opts(int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
|
||||
while ((c = getopt(argc, argv, "chvt:q:")) != -1) {
|
||||
switch (c) {
|
||||
case 'c':
|
||||
opts.count_packets = true;
|
||||
break;
|
||||
case 'h':
|
||||
help(argv[0]);
|
||||
exit(0);
|
||||
break;
|
||||
case 'q':
|
||||
opts.queue_num = atoi(optarg);
|
||||
if (opts.queue_num > 0xffff)
|
||||
opts.queue_num = 0;
|
||||
break;
|
||||
case 't':
|
||||
opts.timeout = atoi(optarg);
|
||||
break;
|
||||
case 'v':
|
||||
opts.verbose++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ret;
|
||||
|
||||
parse_opts(argc, argv);
|
||||
|
||||
ret = mainloop();
|
||||
if (opts.count_packets)
|
||||
print_stats();
|
||||
|
||||
return ret;
|
||||
}
|
332
tools/testing/selftests/netfilter/nft_queue.sh
Executable file
332
tools/testing/selftests/netfilter/nft_queue.sh
Executable file
@@ -0,0 +1,332 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# This tests nf_queue:
|
||||
# 1. can process packets from all hooks
|
||||
# 2. support running nfqueue from more than one base chain
|
||||
#
|
||||
# Kselftest framework requirement - SKIP code is 4.
|
||||
ksft_skip=4
|
||||
ret=0
|
||||
|
||||
sfx=$(mktemp -u "XXXXXXXX")
|
||||
ns1="ns1-$sfx"
|
||||
ns2="ns2-$sfx"
|
||||
nsrouter="nsrouter-$sfx"
|
||||
|
||||
cleanup()
|
||||
{
|
||||
ip netns del ${ns1}
|
||||
ip netns del ${ns2}
|
||||
ip netns del ${nsrouter}
|
||||
rm -f "$TMPFILE0"
|
||||
rm -f "$TMPFILE1"
|
||||
}
|
||||
|
||||
nft --version > /dev/null 2>&1
|
||||
if [ $? -ne 0 ];then
|
||||
echo "SKIP: Could not run test without nft tool"
|
||||
exit $ksft_skip
|
||||
fi
|
||||
|
||||
ip -Version > /dev/null 2>&1
|
||||
if [ $? -ne 0 ];then
|
||||
echo "SKIP: Could not run test without ip tool"
|
||||
exit $ksft_skip
|
||||
fi
|
||||
|
||||
ip netns add ${nsrouter}
|
||||
if [ $? -ne 0 ];then
|
||||
echo "SKIP: Could not create net namespace"
|
||||
exit $ksft_skip
|
||||
fi
|
||||
|
||||
TMPFILE0=$(mktemp)
|
||||
TMPFILE1=$(mktemp)
|
||||
trap cleanup EXIT
|
||||
|
||||
ip netns add ${ns1}
|
||||
ip netns add ${ns2}
|
||||
|
||||
ip link add veth0 netns ${nsrouter} type veth peer name eth0 netns ${ns1} > /dev/null 2>&1
|
||||
if [ $? -ne 0 ];then
|
||||
echo "SKIP: No virtual ethernet pair device support in kernel"
|
||||
exit $ksft_skip
|
||||
fi
|
||||
ip link add veth1 netns ${nsrouter} type veth peer name eth0 netns ${ns2}
|
||||
|
||||
ip -net ${nsrouter} link set lo up
|
||||
ip -net ${nsrouter} link set veth0 up
|
||||
ip -net ${nsrouter} addr add 10.0.1.1/24 dev veth0
|
||||
ip -net ${nsrouter} addr add dead:1::1/64 dev veth0
|
||||
|
||||
ip -net ${nsrouter} link set veth1 up
|
||||
ip -net ${nsrouter} addr add 10.0.2.1/24 dev veth1
|
||||
ip -net ${nsrouter} addr add dead:2::1/64 dev veth1
|
||||
|
||||
ip -net ${ns1} link set lo up
|
||||
ip -net ${ns1} link set eth0 up
|
||||
|
||||
ip -net ${ns2} link set lo up
|
||||
ip -net ${ns2} link set eth0 up
|
||||
|
||||
ip -net ${ns1} addr add 10.0.1.99/24 dev eth0
|
||||
ip -net ${ns1} addr add dead:1::99/64 dev eth0
|
||||
ip -net ${ns1} route add default via 10.0.1.1
|
||||
ip -net ${ns1} route add default via dead:1::1
|
||||
|
||||
ip -net ${ns2} addr add 10.0.2.99/24 dev eth0
|
||||
ip -net ${ns2} addr add dead:2::99/64 dev eth0
|
||||
ip -net ${ns2} route add default via 10.0.2.1
|
||||
ip -net ${ns2} route add default via dead:2::1
|
||||
|
||||
load_ruleset() {
|
||||
local name=$1
|
||||
local prio=$2
|
||||
|
||||
ip netns exec ${nsrouter} nft -f - <<EOF
|
||||
table inet $name {
|
||||
chain nfq {
|
||||
ip protocol icmp queue bypass
|
||||
icmpv6 type { "echo-request", "echo-reply" } queue num 1 bypass
|
||||
}
|
||||
chain pre {
|
||||
type filter hook prerouting priority $prio; policy accept;
|
||||
jump nfq
|
||||
}
|
||||
chain input {
|
||||
type filter hook input priority $prio; policy accept;
|
||||
jump nfq
|
||||
}
|
||||
chain forward {
|
||||
type filter hook forward priority $prio; policy accept;
|
||||
tcp dport 12345 queue num 2
|
||||
jump nfq
|
||||
}
|
||||
chain output {
|
||||
type filter hook output priority $prio; policy accept;
|
||||
tcp dport 12345 queue num 3
|
||||
jump nfq
|
||||
}
|
||||
chain post {
|
||||
type filter hook postrouting priority $prio; policy accept;
|
||||
jump nfq
|
||||
}
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
load_counter_ruleset() {
|
||||
local prio=$1
|
||||
|
||||
ip netns exec ${nsrouter} nft -f - <<EOF
|
||||
table inet countrules {
|
||||
chain pre {
|
||||
type filter hook prerouting priority $prio; policy accept;
|
||||
counter
|
||||
}
|
||||
chain input {
|
||||
type filter hook input priority $prio; policy accept;
|
||||
counter
|
||||
}
|
||||
chain forward {
|
||||
type filter hook forward priority $prio; policy accept;
|
||||
counter
|
||||
}
|
||||
chain output {
|
||||
type filter hook output priority $prio; policy accept;
|
||||
counter
|
||||
}
|
||||
chain post {
|
||||
type filter hook postrouting priority $prio; policy accept;
|
||||
counter
|
||||
}
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
test_ping() {
|
||||
ip netns exec ${ns1} ping -c 1 -q 10.0.2.99 > /dev/null
|
||||
if [ $? -ne 0 ];then
|
||||
return 1
|
||||
fi
|
||||
|
||||
ip netns exec ${ns1} ping -c 1 -q dead:2::99 > /dev/null
|
||||
if [ $? -ne 0 ];then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
test_ping_router() {
|
||||
ip netns exec ${ns1} ping -c 1 -q 10.0.2.1 > /dev/null
|
||||
if [ $? -ne 0 ];then
|
||||
return 1
|
||||
fi
|
||||
|
||||
ip netns exec ${ns1} ping -c 1 -q dead:2::1 > /dev/null
|
||||
if [ $? -ne 0 ];then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
test_queue_blackhole() {
|
||||
local proto=$1
|
||||
|
||||
ip netns exec ${nsrouter} nft -f - <<EOF
|
||||
table $proto blackh {
|
||||
chain forward {
|
||||
type filter hook forward priority 0; policy accept;
|
||||
queue num 600
|
||||
}
|
||||
}
|
||||
EOF
|
||||
if [ $proto = "ip" ] ;then
|
||||
ip netns exec ${ns1} ping -c 1 -q 10.0.2.99 > /dev/null
|
||||
lret=$?
|
||||
elif [ $proto = "ip6" ]; then
|
||||
ip netns exec ${ns1} ping -c 1 -q dead:2::99 > /dev/null
|
||||
lret=$?
|
||||
else
|
||||
lret=111
|
||||
fi
|
||||
|
||||
# queue without bypass keyword should drop traffic if no listener exists.
|
||||
if [ $lret -eq 0 ];then
|
||||
echo "FAIL: $proto expected failure, got $lret" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ip netns exec ${nsrouter} nft delete table $proto blackh
|
||||
if [ $? -ne 0 ] ;then
|
||||
echo "FAIL: $proto: Could not delete blackh table"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "PASS: $proto: statement with no listener results in packet drop"
|
||||
}
|
||||
|
||||
test_queue()
|
||||
{
|
||||
local expected=$1
|
||||
local last=""
|
||||
|
||||
# spawn nf-queue listeners
|
||||
ip netns exec ${nsrouter} ./nf-queue -c -q 0 -t 3 > "$TMPFILE0" &
|
||||
ip netns exec ${nsrouter} ./nf-queue -c -q 1 -t 3 > "$TMPFILE1" &
|
||||
sleep 1
|
||||
test_ping
|
||||
ret=$?
|
||||
if [ $ret -ne 0 ];then
|
||||
echo "FAIL: netns routing/connectivity with active listener on queue $queue: $ret" 1>&2
|
||||
exit $ret
|
||||
fi
|
||||
|
||||
test_ping_router
|
||||
ret=$?
|
||||
if [ $ret -ne 0 ];then
|
||||
echo "FAIL: netns router unreachable listener on queue $queue: $ret" 1>&2
|
||||
exit $ret
|
||||
fi
|
||||
|
||||
wait
|
||||
ret=$?
|
||||
|
||||
for file in $TMPFILE0 $TMPFILE1; do
|
||||
last=$(tail -n1 "$file")
|
||||
if [ x"$last" != x"$expected packets total" ]; then
|
||||
echo "FAIL: Expected $expected packets total, but got $last" 1>&2
|
||||
cat "$file" 1>&2
|
||||
|
||||
ip netns exec ${nsrouter} nft list ruleset
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
echo "PASS: Expected and received $last"
|
||||
}
|
||||
|
||||
test_tcp_forward()
|
||||
{
|
||||
ip netns exec ${nsrouter} ./nf-queue -q 2 -t 10 &
|
||||
local nfqpid=$!
|
||||
|
||||
tmpfile=$(mktemp) || exit 1
|
||||
dd conv=sparse status=none if=/dev/zero bs=1M count=100 of=$tmpfile
|
||||
ip netns exec ${ns2} nc -w 5 -l -p 12345 <"$tmpfile" >/dev/null &
|
||||
local rpid=$!
|
||||
|
||||
sleep 1
|
||||
ip netns exec ${ns1} nc -w 5 10.0.2.99 12345 <"$tmpfile" >/dev/null &
|
||||
|
||||
rm -f "$tmpfile"
|
||||
|
||||
wait $rpid
|
||||
wait $lpid
|
||||
[ $? -eq 0 ] && echo "PASS: tcp and nfqueue in forward chain"
|
||||
}
|
||||
|
||||
test_tcp_localhost()
|
||||
{
|
||||
tc -net "${nsrouter}" qdisc add dev lo root netem loss random 1%
|
||||
|
||||
tmpfile=$(mktemp) || exit 1
|
||||
|
||||
dd conv=sparse status=none if=/dev/zero bs=1M count=900 of=$tmpfile
|
||||
ip netns exec ${nsrouter} nc -w 5 -l -p 12345 <"$tmpfile" >/dev/null &
|
||||
local rpid=$!
|
||||
|
||||
ip netns exec ${nsrouter} ./nf-queue -q 3 -t 30 &
|
||||
local nfqpid=$!
|
||||
|
||||
sleep 1
|
||||
ip netns exec ${nsrouter} nc -w 5 127.0.0.1 12345 <"$tmpfile" > /dev/null
|
||||
rm -f "$tmpfile"
|
||||
|
||||
wait $rpid
|
||||
[ $? -eq 0 ] && echo "PASS: tcp via loopback"
|
||||
}
|
||||
|
||||
ip netns exec ${nsrouter} sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
|
||||
ip netns exec ${nsrouter} sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
|
||||
ip netns exec ${nsrouter} sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
|
||||
|
||||
load_ruleset "filter" 0
|
||||
|
||||
sleep 3
|
||||
|
||||
test_ping
|
||||
ret=$?
|
||||
if [ $ret -eq 0 ];then
|
||||
# queue bypass works (rules were skipped, no listener)
|
||||
echo "PASS: ${ns1} can reach ${ns2}"
|
||||
else
|
||||
echo "FAIL: ${ns1} cannot reach ${ns2}: $ret" 1>&2
|
||||
exit $ret
|
||||
fi
|
||||
|
||||
test_queue_blackhole ip
|
||||
test_queue_blackhole ip6
|
||||
|
||||
# dummy ruleset to add base chains between the
|
||||
# queueing rules. We don't want the second reinject
|
||||
# to re-execute the old hooks.
|
||||
load_counter_ruleset 10
|
||||
|
||||
# we are hooking all: prerouting/input/forward/output/postrouting.
|
||||
# we ping ${ns2} from ${ns1} via ${nsrouter} using ipv4 and ipv6, so:
|
||||
# 1x icmp prerouting,forward,postrouting -> 3 queue events (6 incl. reply).
|
||||
# 1x icmp prerouting,input,output postrouting -> 4 queue events incl. reply.
|
||||
# so we expect that userspace program receives 10 packets.
|
||||
test_queue 10
|
||||
|
||||
# same. We queue to a second program as well.
|
||||
load_ruleset "filter2" 20
|
||||
test_queue 20
|
||||
|
||||
test_tcp_forward
|
||||
test_tcp_localhost
|
||||
|
||||
exit $ret
|
@@ -527,11 +527,16 @@ n0 wg set wg0 peer "$pub2" allowed-ips 0.0.0.0/0
|
||||
n0 wg set wg0 peer "$pub2" allowed-ips ::/0,1700::/111,5000::/4,e000::/37,9000::/75
|
||||
n0 wg set wg0 peer "$pub2" allowed-ips ::/0
|
||||
n0 wg set wg0 peer "$pub2" remove
|
||||
low_order_points=( AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= 4Ot6fDtBuK4WVuP68Z/EatoJjeucMrH9hmIFFl9JuAA= X5yVvKNQjCSx0LFVnIPvWwREXMRYHI6G2CJO3dCfEVc= 7P///////////////////////////////////////38= 7f///////////////////////////////////////38= 7v///////////////////////////////////////38= )
|
||||
n0 wg set wg0 private-key /dev/null ${low_order_points[@]/#/peer }
|
||||
[[ -z $(n0 wg show wg0 peers) ]]
|
||||
n0 wg set wg0 private-key <(echo "$key1") ${low_order_points[@]/#/peer }
|
||||
[[ -z $(n0 wg show wg0 peers) ]]
|
||||
for low_order_point in AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= 4Ot6fDtBuK4WVuP68Z/EatoJjeucMrH9hmIFFl9JuAA= X5yVvKNQjCSx0LFVnIPvWwREXMRYHI6G2CJO3dCfEVc= 7P///////////////////////////////////////38= 7f///////////////////////////////////////38= 7v///////////////////////////////////////38=; do
|
||||
n0 wg set wg0 peer "$low_order_point" persistent-keepalive 1 endpoint 127.0.0.1:1111
|
||||
done
|
||||
[[ -n $(n0 wg show wg0 peers) ]]
|
||||
exec 4< <(n0 ncat -l -u -p 1111)
|
||||
ncat_pid=$!
|
||||
waitncatudp $netns0 $ncat_pid
|
||||
ip0 link set wg0 up
|
||||
! read -r -n 1 -t 2 <&4 || false
|
||||
kill $ncat_pid
|
||||
ip0 link del wg0
|
||||
|
||||
declare -A objects
|
||||
|
@@ -41,7 +41,7 @@ $(DISTFILES_PATH)/$(1):
|
||||
flock -x $$@.lock -c '[ -f $$@ ] && exit 0; wget -O $$@.tmp $(MIRROR)$(1) || wget -O $$@.tmp $(2)$(1) || rm -f $$@.tmp; [ -f $$@.tmp ] || exit 1; if echo "$(3) $$@.tmp" | sha256sum -c -; then mv $$@.tmp $$@; else rm -f $$@.tmp; exit 71; fi'
|
||||
endef
|
||||
|
||||
$(eval $(call tar_download,MUSL,musl,1.1.24,.tar.gz,https://www.musl-libc.org/releases/,1370c9a812b2cf2a7d92802510cca0058cc37e66a7bedd70051f0a34015022a3))
|
||||
$(eval $(call tar_download,MUSL,musl,1.2.0,.tar.gz,https://musl.libc.org/releases/,c6de7b191139142d3f9a7b5b702c9cae1b5ee6e7f57e582da9328629408fd4e8))
|
||||
$(eval $(call tar_download,IPERF,iperf,3.7,.tar.gz,https://downloads.es.net/pub/iperf/,d846040224317caf2f75c843d309a950a7db23f9b44b94688ccbe557d6d1710c))
|
||||
$(eval $(call tar_download,BASH,bash,5.0,.tar.gz,https://ftp.gnu.org/gnu/bash/,b4a80f2ac66170b2913efbfb9f2594f1f76c7b1afd11f799e22035d63077fb4d))
|
||||
$(eval $(call tar_download,IPROUTE2,iproute2,5.4.0,.tar.xz,https://www.kernel.org/pub/linux/utils/net/iproute2/,fe97aa60a0d4c5ac830be18937e18dc3400ca713a33a89ad896ff1e3d46086ae))
|
||||
|
@@ -13,7 +13,6 @@
|
||||
#include <fcntl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/io.h>
|
||||
|
@@ -56,7 +56,6 @@ CONFIG_NO_HZ_IDLE=y
|
||||
CONFIG_NO_HZ_FULL=n
|
||||
CONFIG_HZ_PERIODIC=n
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
CONFIG_COMPAT_32BIT_TIME=y
|
||||
CONFIG_ARCH_RANDOM=y
|
||||
CONFIG_FILE_LOCKING=y
|
||||
CONFIG_POSIX_TIMERS=y
|
||||
|
Reference in New Issue
Block a user