Commit 784d5dc0 authored by Maxim Mikityanskiy's avatar Maxim Mikityanskiy Committed by Alexei Starovoitov

selftests/bpf: Add selftests for raw syncookie helpers in TC mode

This commit extends selftests for the new BPF helpers
bpf_tcp_raw_{gen,check}_syncookie_ipv{4,6} to also test the TC BPF
functionality added in the previous commit.
Signed-off-by: default avatarMaxim Mikityanskiy <maximmi@nvidia.com>
Reviewed-by: default avatarTariq Toukan <tariqt@nvidia.com>
Link: https://lore.kernel.org/r/20220615134847.3753567-7-maximmi@nvidia.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 9a4cf073
// SPDX-License-Identifier: LGPL-2.1 OR BSD-2-Clause // SPDX-License-Identifier: LGPL-2.1 OR BSD-2-Clause
/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ /* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
#define _GNU_SOURCE
#include <test_progs.h> #include <test_progs.h>
#include <network_helpers.h> #include <network_helpers.h>
#include <ctype.h> #include <ctype.h>
...@@ -12,9 +13,11 @@ ...@@ -12,9 +13,11 @@
goto out; \ goto out; \
}) })
#define SYS_OUT(cmd) ({ \ #define SYS_OUT(cmd, ...) ({ \
FILE *f = popen((cmd), "r"); \ char buf[1024]; \
if (!ASSERT_OK_PTR(f, (cmd))) \ snprintf(buf, sizeof(buf), (cmd), ##__VA_ARGS__); \
FILE *f = popen(buf, "r"); \
if (!ASSERT_OK_PTR(f, buf)) \
goto out; \ goto out; \
f; \ f; \
}) })
...@@ -57,9 +60,10 @@ static bool expect_str(char *buf, size_t size, const char *str, const char *name ...@@ -57,9 +60,10 @@ static bool expect_str(char *buf, size_t size, const char *str, const char *name
return ok; return ok;
} }
void test_xdp_synproxy(void) static void test_synproxy(bool xdp)
{ {
int server_fd = -1, client_fd = -1, accept_fd = -1; int server_fd = -1, client_fd = -1, accept_fd = -1;
char *prog_id, *prog_id_end;
struct nstoken *ns = NULL; struct nstoken *ns = NULL;
FILE *ctrl_file = NULL; FILE *ctrl_file = NULL;
char buf[CMD_OUT_BUF_SIZE]; char buf[CMD_OUT_BUF_SIZE];
...@@ -76,8 +80,9 @@ void test_xdp_synproxy(void) ...@@ -76,8 +80,9 @@ void test_xdp_synproxy(void)
* checksums and drops packets. * checksums and drops packets.
*/ */
SYS("ethtool -K tmp0 tx off"); SYS("ethtool -K tmp0 tx off");
/* Workaround required for veth. */ if (xdp)
SYS("ip link set tmp0 xdp object xdp_dummy.o section xdp 2> /dev/null"); /* Workaround required for veth. */
SYS("ip link set tmp0 xdp object xdp_dummy.o section xdp 2> /dev/null");
ns = open_netns("synproxy"); ns = open_netns("synproxy");
if (!ASSERT_OK_PTR(ns, "setns")) if (!ASSERT_OK_PTR(ns, "setns"))
...@@ -97,14 +102,34 @@ void test_xdp_synproxy(void) ...@@ -97,14 +102,34 @@ void test_xdp_synproxy(void)
SYS("iptables -t filter -A INPUT \ SYS("iptables -t filter -A INPUT \
-i tmp1 -m state --state INVALID -j DROP"); -i tmp1 -m state --state INVALID -j DROP");
ctrl_file = SYS_OUT("./xdp_synproxy --iface tmp1 --ports 8080 --single \ ctrl_file = SYS_OUT("./xdp_synproxy --iface tmp1 --ports 8080 \
--mss4 1460 --mss6 1440 --wscale 7 --ttl 64"); --single --mss4 1460 --mss6 1440 \
--wscale 7 --ttl 64%s", xdp ? "" : " --tc");
size = fread(buf, 1, sizeof(buf), ctrl_file); size = fread(buf, 1, sizeof(buf), ctrl_file);
pclose(ctrl_file); pclose(ctrl_file);
if (!expect_str(buf, size, "Total SYNACKs generated: 0\n", if (!expect_str(buf, size, "Total SYNACKs generated: 0\n",
"initial SYNACKs")) "initial SYNACKs"))
goto out; goto out;
if (!xdp) {
ctrl_file = SYS_OUT("tc filter show dev tmp1 ingress");
size = fread(buf, 1, sizeof(buf), ctrl_file);
pclose(ctrl_file);
prog_id = memmem(buf, size, " id ", 4);
if (!ASSERT_OK_PTR(prog_id, "find prog id"))
goto out;
prog_id += 4;
if (!ASSERT_LT(prog_id, buf + size, "find prog id begin"))
goto out;
prog_id_end = prog_id;
while (prog_id_end < buf + size && *prog_id_end >= '0' &&
*prog_id_end <= '9')
prog_id_end++;
if (!ASSERT_LT(prog_id_end, buf + size, "find prog id end"))
goto out;
*prog_id_end = '\0';
}
server_fd = start_server(AF_INET, SOCK_STREAM, "198.18.0.2", 8080, 0); server_fd = start_server(AF_INET, SOCK_STREAM, "198.18.0.2", 8080, 0);
if (!ASSERT_GE(server_fd, 0, "start_server")) if (!ASSERT_GE(server_fd, 0, "start_server"))
goto out; goto out;
...@@ -124,7 +149,11 @@ void test_xdp_synproxy(void) ...@@ -124,7 +149,11 @@ void test_xdp_synproxy(void)
if (!ASSERT_OK_PTR(ns, "setns")) if (!ASSERT_OK_PTR(ns, "setns"))
goto out; goto out;
ctrl_file = SYS_OUT("./xdp_synproxy --iface tmp1 --single"); if (xdp)
ctrl_file = SYS_OUT("./xdp_synproxy --iface tmp1 --single");
else
ctrl_file = SYS_OUT("./xdp_synproxy --prog %s --single",
prog_id);
size = fread(buf, 1, sizeof(buf), ctrl_file); size = fread(buf, 1, sizeof(buf), ctrl_file);
pclose(ctrl_file); pclose(ctrl_file);
if (!expect_str(buf, size, "Total SYNACKs generated: 1\n", if (!expect_str(buf, size, "Total SYNACKs generated: 1\n",
...@@ -144,3 +173,11 @@ void test_xdp_synproxy(void) ...@@ -144,3 +173,11 @@ void test_xdp_synproxy(void)
system("ip link del tmp0"); system("ip link del tmp0");
system("ip netns del synproxy"); system("ip netns del synproxy");
} }
void test_xdp_synproxy(void)
{
if (test__start_subtest("xdp"))
test_synproxy(true);
if (test__start_subtest("tc"))
test_synproxy(false);
}
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
#include <bpf/bpf_endian.h> #include <bpf/bpf_endian.h>
#include <asm/errno.h> #include <asm/errno.h>
#define TC_ACT_OK 0
#define TC_ACT_SHOT 2
#define NSEC_PER_SEC 1000000000L #define NSEC_PER_SEC 1000000000L
#define ETH_ALEN 6 #define ETH_ALEN 6
...@@ -80,6 +83,12 @@ extern struct nf_conn *bpf_xdp_ct_lookup(struct xdp_md *xdp_ctx, ...@@ -80,6 +83,12 @@ extern struct nf_conn *bpf_xdp_ct_lookup(struct xdp_md *xdp_ctx,
struct bpf_ct_opts *opts, struct bpf_ct_opts *opts,
__u32 len_opts) __ksym; __u32 len_opts) __ksym;
extern struct nf_conn *bpf_skb_ct_lookup(struct __sk_buff *skb_ctx,
struct bpf_sock_tuple *bpf_tuple,
u32 len_tuple,
struct bpf_ct_opts *opts,
u32 len_opts) __ksym;
extern void bpf_ct_release(struct nf_conn *ct) __ksym; extern void bpf_ct_release(struct nf_conn *ct) __ksym;
static __always_inline void swap_eth_addr(__u8 *a, __u8 *b) static __always_inline void swap_eth_addr(__u8 *a, __u8 *b)
...@@ -382,7 +391,7 @@ static __always_inline int tcp_dissect(void *data, void *data_end, ...@@ -382,7 +391,7 @@ static __always_inline int tcp_dissect(void *data, void *data_end,
return XDP_TX; return XDP_TX;
} }
static __always_inline int tcp_lookup(struct xdp_md *ctx, struct header_pointers *hdr) static __always_inline int tcp_lookup(void *ctx, struct header_pointers *hdr, bool xdp)
{ {
struct bpf_ct_opts ct_lookup_opts = { struct bpf_ct_opts ct_lookup_opts = {
.netns_id = BPF_F_CURRENT_NETNS, .netns_id = BPF_F_CURRENT_NETNS,
...@@ -416,7 +425,10 @@ static __always_inline int tcp_lookup(struct xdp_md *ctx, struct header_pointers ...@@ -416,7 +425,10 @@ static __always_inline int tcp_lookup(struct xdp_md *ctx, struct header_pointers
*/ */
return XDP_ABORTED; return XDP_ABORTED;
} }
ct = bpf_xdp_ct_lookup(ctx, &tup, tup_size, &ct_lookup_opts, sizeof(ct_lookup_opts)); if (xdp)
ct = bpf_xdp_ct_lookup(ctx, &tup, tup_size, &ct_lookup_opts, sizeof(ct_lookup_opts));
else
ct = bpf_skb_ct_lookup(ctx, &tup, tup_size, &ct_lookup_opts, sizeof(ct_lookup_opts));
if (ct) { if (ct) {
unsigned long status = ct->status; unsigned long status = ct->status;
...@@ -529,8 +541,9 @@ static __always_inline void tcpv6_gen_synack(struct header_pointers *hdr, ...@@ -529,8 +541,9 @@ static __always_inline void tcpv6_gen_synack(struct header_pointers *hdr,
} }
static __always_inline int syncookie_handle_syn(struct header_pointers *hdr, static __always_inline int syncookie_handle_syn(struct header_pointers *hdr,
struct xdp_md *ctx, void *ctx,
void *data, void *data_end) void *data, void *data_end,
bool xdp)
{ {
__u32 old_pkt_size, new_pkt_size; __u32 old_pkt_size, new_pkt_size;
/* Unlike clang 10, clang 11 and 12 generate code that doesn't pass the /* Unlike clang 10, clang 11 and 12 generate code that doesn't pass the
...@@ -666,8 +679,13 @@ static __always_inline int syncookie_handle_syn(struct header_pointers *hdr, ...@@ -666,8 +679,13 @@ static __always_inline int syncookie_handle_syn(struct header_pointers *hdr,
/* Set the new packet size. */ /* Set the new packet size. */
old_pkt_size = data_end - data; old_pkt_size = data_end - data;
new_pkt_size = sizeof(*hdr->eth) + ip_len + hdr->tcp->doff * 4; new_pkt_size = sizeof(*hdr->eth) + ip_len + hdr->tcp->doff * 4;
if (bpf_xdp_adjust_tail(ctx, new_pkt_size - old_pkt_size)) if (xdp) {
return XDP_ABORTED; if (bpf_xdp_adjust_tail(ctx, new_pkt_size - old_pkt_size))
return XDP_ABORTED;
} else {
if (bpf_skb_change_tail(ctx, new_pkt_size, 0))
return XDP_ABORTED;
}
values_inc_synacks(); values_inc_synacks();
...@@ -693,71 +711,123 @@ static __always_inline int syncookie_handle_ack(struct header_pointers *hdr) ...@@ -693,71 +711,123 @@ static __always_inline int syncookie_handle_ack(struct header_pointers *hdr)
return XDP_PASS; return XDP_PASS;
} }
SEC("xdp") static __always_inline int syncookie_part1(void *ctx, void *data, void *data_end,
int syncookie_xdp(struct xdp_md *ctx) struct header_pointers *hdr, bool xdp)
{ {
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
struct header_pointers hdr;
__s64 value;
int ret;
struct bpf_ct_opts ct_lookup_opts = { struct bpf_ct_opts ct_lookup_opts = {
.netns_id = BPF_F_CURRENT_NETNS, .netns_id = BPF_F_CURRENT_NETNS,
.l4proto = IPPROTO_TCP, .l4proto = IPPROTO_TCP,
}; };
int ret;
ret = tcp_dissect(data, data_end, &hdr); ret = tcp_dissect(data, data_end, hdr);
if (ret != XDP_TX) if (ret != XDP_TX)
return ret; return ret;
ret = tcp_lookup(ctx, &hdr); ret = tcp_lookup(ctx, hdr, xdp);
if (ret != XDP_TX) if (ret != XDP_TX)
return ret; return ret;
/* Packet is TCP and doesn't belong to an established connection. */ /* Packet is TCP and doesn't belong to an established connection. */
if ((hdr.tcp->syn ^ hdr.tcp->ack) != 1) if ((hdr->tcp->syn ^ hdr->tcp->ack) != 1)
return XDP_DROP; return XDP_DROP;
/* Grow the TCP header to TCP_MAXLEN to be able to pass any hdr.tcp_len /* Grow the TCP header to TCP_MAXLEN to be able to pass any hdr->tcp_len
* to bpf_tcp_raw_gen_syncookie_ipv{4,6} and pass the verifier. * to bpf_tcp_raw_gen_syncookie_ipv{4,6} and pass the verifier.
*/ */
if (bpf_xdp_adjust_tail(ctx, TCP_MAXLEN - hdr.tcp_len)) if (xdp) {
return XDP_ABORTED; if (bpf_xdp_adjust_tail(ctx, TCP_MAXLEN - hdr->tcp_len))
return XDP_ABORTED;
} else {
/* Without volatile the verifier throws this error:
* R9 32-bit pointer arithmetic prohibited
*/
volatile u64 old_len = data_end - data;
data_end = (void *)(long)ctx->data_end; if (bpf_skb_change_tail(ctx, old_len + TCP_MAXLEN - hdr->tcp_len, 0))
data = (void *)(long)ctx->data; return XDP_ABORTED;
}
return XDP_TX;
}
if (hdr.ipv4) { static __always_inline int syncookie_part2(void *ctx, void *data, void *data_end,
hdr.eth = data; struct header_pointers *hdr, bool xdp)
hdr.ipv4 = (void *)hdr.eth + sizeof(*hdr.eth); {
if (hdr->ipv4) {
hdr->eth = data;
hdr->ipv4 = (void *)hdr->eth + sizeof(*hdr->eth);
/* IPV4_MAXLEN is needed when calculating checksum. /* IPV4_MAXLEN is needed when calculating checksum.
* At least sizeof(struct iphdr) is needed here to access ihl. * At least sizeof(struct iphdr) is needed here to access ihl.
*/ */
if ((void *)hdr.ipv4 + IPV4_MAXLEN > data_end) if ((void *)hdr->ipv4 + IPV4_MAXLEN > data_end)
return XDP_ABORTED; return XDP_ABORTED;
hdr.tcp = (void *)hdr.ipv4 + hdr.ipv4->ihl * 4; hdr->tcp = (void *)hdr->ipv4 + hdr->ipv4->ihl * 4;
} else if (hdr.ipv6) { } else if (hdr->ipv6) {
hdr.eth = data; hdr->eth = data;
hdr.ipv6 = (void *)hdr.eth + sizeof(*hdr.eth); hdr->ipv6 = (void *)hdr->eth + sizeof(*hdr->eth);
hdr.tcp = (void *)hdr.ipv6 + sizeof(*hdr.ipv6); hdr->tcp = (void *)hdr->ipv6 + sizeof(*hdr->ipv6);
} else { } else {
return XDP_ABORTED; return XDP_ABORTED;
} }
if ((void *)hdr.tcp + TCP_MAXLEN > data_end) if ((void *)hdr->tcp + TCP_MAXLEN > data_end)
return XDP_ABORTED; return XDP_ABORTED;
/* We run out of registers, tcp_len gets spilled to the stack, and the /* We run out of registers, tcp_len gets spilled to the stack, and the
* verifier forgets its min and max values checked above in tcp_dissect. * verifier forgets its min and max values checked above in tcp_dissect.
*/ */
hdr.tcp_len = hdr.tcp->doff * 4; hdr->tcp_len = hdr->tcp->doff * 4;
if (hdr.tcp_len < sizeof(*hdr.tcp)) if (hdr->tcp_len < sizeof(*hdr->tcp))
return XDP_ABORTED; return XDP_ABORTED;
return hdr.tcp->syn ? syncookie_handle_syn(&hdr, ctx, data, data_end) : return hdr->tcp->syn ? syncookie_handle_syn(hdr, ctx, data, data_end, xdp) :
syncookie_handle_ack(&hdr); syncookie_handle_ack(hdr);
}
SEC("xdp")
int syncookie_xdp(struct xdp_md *ctx)
{
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
struct header_pointers hdr;
int ret;
ret = syncookie_part1(ctx, data, data_end, &hdr, true);
if (ret != XDP_TX)
return ret;
data_end = (void *)(long)ctx->data_end;
data = (void *)(long)ctx->data;
return syncookie_part2(ctx, data, data_end, &hdr, true);
}
SEC("tc")
int syncookie_tc(struct __sk_buff *skb)
{
void *data_end = (void *)(long)skb->data_end;
void *data = (void *)(long)skb->data;
struct header_pointers hdr;
int ret;
ret = syncookie_part1(skb, data, data_end, &hdr, false);
if (ret != XDP_TX)
return ret == XDP_PASS ? TC_ACT_OK : TC_ACT_SHOT;
data_end = (void *)(long)skb->data_end;
data = (void *)(long)skb->data;
ret = syncookie_part2(skb, data, data_end, &hdr, false);
switch (ret) {
case XDP_PASS:
return TC_ACT_OK;
case XDP_TX:
return bpf_redirect(skb->ifindex, 0);
default:
return TC_ACT_SHOT;
}
} }
char _license[] SEC("license") = "GPL"; char _license[] SEC("license") = "GPL";
...@@ -18,16 +18,31 @@ ...@@ -18,16 +18,31 @@
static unsigned int ifindex; static unsigned int ifindex;
static __u32 attached_prog_id; static __u32 attached_prog_id;
static bool attached_tc;
static void noreturn cleanup(int sig) static void noreturn cleanup(int sig)
{ {
DECLARE_LIBBPF_OPTS(bpf_xdp_attach_opts, opts); LIBBPF_OPTS(bpf_xdp_attach_opts, opts);
int prog_fd; int prog_fd;
int err; int err;
if (attached_prog_id == 0) if (attached_prog_id == 0)
exit(0); exit(0);
if (attached_tc) {
LIBBPF_OPTS(bpf_tc_hook, hook,
.ifindex = ifindex,
.attach_point = BPF_TC_INGRESS);
err = bpf_tc_hook_destroy(&hook);
if (err < 0) {
fprintf(stderr, "Error: bpf_tc_hook_destroy: %s\n", strerror(-err));
fprintf(stderr, "Failed to destroy the TC hook\n");
exit(1);
}
exit(0);
}
prog_fd = bpf_prog_get_fd_by_id(attached_prog_id); prog_fd = bpf_prog_get_fd_by_id(attached_prog_id);
if (prog_fd < 0) { if (prog_fd < 0) {
fprintf(stderr, "Error: bpf_prog_get_fd_by_id: %s\n", strerror(-prog_fd)); fprintf(stderr, "Error: bpf_prog_get_fd_by_id: %s\n", strerror(-prog_fd));
...@@ -55,7 +70,7 @@ static void noreturn cleanup(int sig) ...@@ -55,7 +70,7 @@ static void noreturn cleanup(int sig)
static noreturn void usage(const char *progname) static noreturn void usage(const char *progname)
{ {
fprintf(stderr, "Usage: %s [--iface <iface>|--prog <prog_id>] [--mss4 <mss ipv4> --mss6 <mss ipv6> --wscale <wscale> --ttl <ttl>] [--ports <port1>,<port2>,...] [--single]\n", fprintf(stderr, "Usage: %s [--iface <iface>|--prog <prog_id>] [--mss4 <mss ipv4> --mss6 <mss ipv6> --wscale <wscale> --ttl <ttl>] [--ports <port1>,<port2>,...] [--single] [--tc]\n",
progname); progname);
exit(1); exit(1);
} }
...@@ -74,7 +89,7 @@ static unsigned long parse_arg_ul(const char *progname, const char *arg, unsigne ...@@ -74,7 +89,7 @@ static unsigned long parse_arg_ul(const char *progname, const char *arg, unsigne
} }
static void parse_options(int argc, char *argv[], unsigned int *ifindex, __u32 *prog_id, static void parse_options(int argc, char *argv[], unsigned int *ifindex, __u32 *prog_id,
__u64 *tcpipopts, char **ports, bool *single) __u64 *tcpipopts, char **ports, bool *single, bool *tc)
{ {
static struct option long_options[] = { static struct option long_options[] = {
{ "help", no_argument, NULL, 'h' }, { "help", no_argument, NULL, 'h' },
...@@ -86,6 +101,7 @@ static void parse_options(int argc, char *argv[], unsigned int *ifindex, __u32 * ...@@ -86,6 +101,7 @@ static void parse_options(int argc, char *argv[], unsigned int *ifindex, __u32 *
{ "ttl", required_argument, NULL, 't' }, { "ttl", required_argument, NULL, 't' },
{ "ports", required_argument, NULL, 'p' }, { "ports", required_argument, NULL, 'p' },
{ "single", no_argument, NULL, 's' }, { "single", no_argument, NULL, 's' },
{ "tc", no_argument, NULL, 'c' },
{ NULL, 0, NULL, 0 }, { NULL, 0, NULL, 0 },
}; };
unsigned long mss4, mss6, wscale, ttl; unsigned long mss4, mss6, wscale, ttl;
...@@ -143,6 +159,9 @@ static void parse_options(int argc, char *argv[], unsigned int *ifindex, __u32 * ...@@ -143,6 +159,9 @@ static void parse_options(int argc, char *argv[], unsigned int *ifindex, __u32 *
case 's': case 's':
*single = true; *single = true;
break; break;
case 'c':
*tc = true;
break;
default: default:
usage(argv[0]); usage(argv[0]);
} }
...@@ -164,7 +183,7 @@ static void parse_options(int argc, char *argv[], unsigned int *ifindex, __u32 * ...@@ -164,7 +183,7 @@ static void parse_options(int argc, char *argv[], unsigned int *ifindex, __u32 *
usage(argv[0]); usage(argv[0]);
} }
static int syncookie_attach(const char *argv0, unsigned int ifindex) static int syncookie_attach(const char *argv0, unsigned int ifindex, bool tc)
{ {
struct bpf_prog_info info = {}; struct bpf_prog_info info = {};
__u32 info_len = sizeof(info); __u32 info_len = sizeof(info);
...@@ -188,9 +207,9 @@ static int syncookie_attach(const char *argv0, unsigned int ifindex) ...@@ -188,9 +207,9 @@ static int syncookie_attach(const char *argv0, unsigned int ifindex)
return err; return err;
} }
prog = bpf_object__find_program_by_name(obj, "syncookie_xdp"); prog = bpf_object__find_program_by_name(obj, tc ? "syncookie_tc" : "syncookie_xdp");
if (!prog) { if (!prog) {
fprintf(stderr, "Error: bpf_object__find_program_by_name: program syncookie_xdp was not found\n"); fprintf(stderr, "Error: bpf_object__find_program_by_name: program was not found\n");
return -ENOENT; return -ENOENT;
} }
...@@ -201,21 +220,50 @@ static int syncookie_attach(const char *argv0, unsigned int ifindex) ...@@ -201,21 +220,50 @@ static int syncookie_attach(const char *argv0, unsigned int ifindex)
fprintf(stderr, "Error: bpf_obj_get_info_by_fd: %s\n", strerror(-err)); fprintf(stderr, "Error: bpf_obj_get_info_by_fd: %s\n", strerror(-err));
goto out; goto out;
} }
attached_tc = tc;
attached_prog_id = info.id; attached_prog_id = info.id;
signal(SIGINT, cleanup); signal(SIGINT, cleanup);
signal(SIGTERM, cleanup); signal(SIGTERM, cleanup);
err = bpf_xdp_attach(ifindex, prog_fd, XDP_FLAGS_UPDATE_IF_NOEXIST, NULL); if (tc) {
if (err < 0) { LIBBPF_OPTS(bpf_tc_hook, hook,
fprintf(stderr, "Error: bpf_set_link_xdp_fd: %s\n", strerror(-err)); .ifindex = ifindex,
signal(SIGINT, SIG_DFL); .attach_point = BPF_TC_INGRESS);
signal(SIGTERM, SIG_DFL); LIBBPF_OPTS(bpf_tc_opts, opts,
attached_prog_id = 0; .handle = 1,
goto out; .priority = 1,
.prog_fd = prog_fd);
err = bpf_tc_hook_create(&hook);
if (err < 0) {
fprintf(stderr, "Error: bpf_tc_hook_create: %s\n",
strerror(-err));
goto fail;
}
err = bpf_tc_attach(&hook, &opts);
if (err < 0) {
fprintf(stderr, "Error: bpf_tc_attach: %s\n",
strerror(-err));
goto fail;
}
} else {
err = bpf_xdp_attach(ifindex, prog_fd,
XDP_FLAGS_UPDATE_IF_NOEXIST, NULL);
if (err < 0) {
fprintf(stderr, "Error: bpf_set_link_xdp_fd: %s\n",
strerror(-err));
goto fail;
}
} }
err = 0; err = 0;
out: out:
bpf_object__close(obj); bpf_object__close(obj);
return err; return err;
fail:
signal(SIGINT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
attached_prog_id = 0;
goto out;
} }
static int syncookie_open_bpf_maps(__u32 prog_id, int *values_map_fd, int *ports_map_fd) static int syncookie_open_bpf_maps(__u32 prog_id, int *values_map_fd, int *ports_map_fd)
...@@ -248,11 +296,6 @@ static int syncookie_open_bpf_maps(__u32 prog_id, int *values_map_fd, int *ports ...@@ -248,11 +296,6 @@ static int syncookie_open_bpf_maps(__u32 prog_id, int *values_map_fd, int *ports
goto out; goto out;
} }
if (prog_info.type != BPF_PROG_TYPE_XDP) {
fprintf(stderr, "Error: BPF prog type is not BPF_PROG_TYPE_XDP\n");
err = -ENOENT;
goto out;
}
if (prog_info.nr_map_ids < 2) { if (prog_info.nr_map_ids < 2) {
fprintf(stderr, "Error: Found %u BPF maps, expected at least 2\n", fprintf(stderr, "Error: Found %u BPF maps, expected at least 2\n",
prog_info.nr_map_ids); prog_info.nr_map_ids);
...@@ -319,17 +362,22 @@ int main(int argc, char *argv[]) ...@@ -319,17 +362,22 @@ int main(int argc, char *argv[])
char *ports; char *ports;
bool single; bool single;
int err = 0; int err = 0;
bool tc;
parse_options(argc, argv, &ifindex, &prog_id, &tcpipopts, &ports, &single); parse_options(argc, argv, &ifindex, &prog_id, &tcpipopts, &ports,
&single, &tc);
if (prog_id == 0) { if (prog_id == 0) {
err = bpf_xdp_query_id(ifindex, 0, &prog_id); if (!tc) {
if (err < 0) { err = bpf_xdp_query_id(ifindex, 0, &prog_id);
fprintf(stderr, "Error: bpf_get_link_xdp_id: %s\n", strerror(-err)); if (err < 0) {
goto out; fprintf(stderr, "Error: bpf_get_link_xdp_id: %s\n",
strerror(-err));
goto out;
}
} }
if (prog_id == 0) { if (prog_id == 0) {
err = syncookie_attach(argv[0], ifindex); err = syncookie_attach(argv[0], ifindex, tc);
if (err < 0) if (err < 0)
goto out; goto out;
prog_id = attached_prog_id; prog_id = attached_prog_id;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment