[SRU][F:linux-bluefield][PATCH 19/21] UBUNTU: SAUCE: bpf: Add a helper to query TCP conntrack information in XDP
Bodong Wang
bodong at nvidia.com
Mon Jul 5 15:39:57 UTC 2021
From: Maxim Mikityanskiy <maximmi at nvidia.com>
BugLink: https://bugs.launchpad.net/bugs/1934499
The new bpf_ct_lookup_tcp helper allows to query connection tracking
information of a TCP connection based on source and destination IP
address and port. The helper returns the status flags of the conntrack
entry if found.
Signed-off-by: Maxim Mikityanskiy <maximmi at nvidia.com>
Reviewed-by: Tariq Toukan <tariqt at nvidia.com>
Signed-off-by: Bodong Wang <bodong at nvidia.com>
---
include/uapi/linux/bpf.h | 20 ++++++++-
net/core/filter.c | 71 +++++++++++++++++++++++++++++++
tools/include/uapi/linux/bpf.h | 20 ++++++++-
tools/testing/selftests/bpf/bpf_helpers.h | 3 ++
4 files changed, 112 insertions(+), 2 deletions(-)
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index f182bd7..9128511 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -2750,6 +2750,23 @@ struct bpf_stack_build_id {
* **-EOPNOTSUPP** kernel configuration does not enable SYN cookies
*
* **-EPROTONOSUPPORT** IP packet version is not 4 or 6
+ *
+ * long bpf_ct_lookup_tcp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u64 netns, u64 flags)
+ * Description
+ * Look for conntrack info for a TCP connection matching *tuple*,
+ * optionally in a child network namespace *netns*.
+ *
+ * This helper is available only if the kernel was compiled with
+ * **CONFIG_NF_CONNTRACK** configuration option as built-in.
+ * Return
+ * On success, connection tracking status (see **enum
+ * ip_conntrack_status**).
+ *
+ * On failure, the returned value is one of the following:
+ *
+ * **-EINVAL** input arguments are invalid.
+ *
+ * **-ENOENT** the connection is not known to conntrack.
*/
#define __BPF_FUNC_MAPPER(FN) \
FN(unspec), \
@@ -2862,7 +2879,8 @@ struct bpf_stack_build_id {
FN(sk_storage_get), \
FN(sk_storage_delete), \
FN(send_signal), \
- FN(tcp_gen_syncookie),
+ FN(tcp_gen_syncookie), \
+ FN(ct_lookup_tcp), \
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
* function eBPF program intends to call
diff --git a/net/core/filter.c b/net/core/filter.c
index 609fe9f..7df5971 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -73,6 +73,8 @@
#include <net/lwtunnel.h>
#include <net/ipv6_stubs.h>
#include <net/bpf_sk_storage.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
/**
* sk_filter_trim_cap - run a packet through a socket filter
@@ -5950,6 +5952,71 @@ u32 bpf_xdp_sock_convert_ctx_access(enum bpf_access_type type,
.arg5_type = ARG_CONST_SIZE,
};
+#if IS_BUILTIN(CONFIG_NF_CONNTRACK)
+BPF_CALL_5(bpf_xdp_ct_lookup_tcp, struct xdp_buff *, ctx,
+ struct bpf_sock_tuple *, bpf_tuple, u32, len,
+ u64, netns_id, u64, flags)
+{
+ struct nf_conntrack_tuple_hash *found;
+ const struct nf_conntrack_zone *zone;
+ struct nf_conntrack_tuple tuple = {};
+ unsigned long status;
+ struct nf_conn *ct;
+ struct net *net;
+
+ if (len == sizeof(bpf_tuple->ipv4)) {
+ tuple.src.l3num = AF_INET;
+ tuple.src.u3.ip = bpf_tuple->ipv4.saddr;
+ tuple.src.u.tcp.port = bpf_tuple->ipv4.sport;
+ tuple.dst.u3.ip = bpf_tuple->ipv4.daddr;
+ tuple.dst.u.tcp.port = bpf_tuple->ipv4.dport;
+#if IS_ENABLED(CONFIG_IPV6)
+ } else if (len == sizeof(bpf_tuple->ipv6)) {
+ tuple.src.l3num = AF_INET6;
+ memcpy(tuple.src.u3.ip6, bpf_tuple->ipv6.saddr, sizeof(bpf_tuple->ipv6.saddr));
+ tuple.src.u.tcp.port = bpf_tuple->ipv6.sport;
+ memcpy(tuple.dst.u3.ip6, bpf_tuple->ipv6.daddr, sizeof(bpf_tuple->ipv6.daddr));
+ tuple.dst.u.tcp.port = bpf_tuple->ipv6.dport;
+#endif
+ } else {
+ return -EINVAL;
+ }
+
+ net = dev_net(ctx->rxq->dev);
+ if ((s32)netns_id >= 0) {
+ if (unlikely(netns_id) > S32_MAX)
+ return -EINVAL;
+ net = get_net_ns_by_id(net, netns_id);
+ }
+
+ zone = &nf_ct_zone_dflt;
+
+ tuple.dst.protonum = IPPROTO_TCP;
+ tuple.dst.dir = IP_CT_DIR_ORIGINAL;
+
+ found = nf_conntrack_find_get(net, zone, &tuple);
+ if (!found)
+ return -ENOENT;
+ ct = nf_ct_tuplehash_to_ctrack(found);
+ status = ct->status;
+ nf_ct_put(ct);
+
+ return status;
+}
+
+static const struct bpf_func_proto bpf_xdp_ct_lookup_tcp_proto = {
+ .func = bpf_xdp_ct_lookup_tcp,
+ .gpl_only = true, /* nf_conntrack_find_get is GPL */
+ .pkt_access = true,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_CTX,
+ .arg2_type = ARG_PTR_TO_MEM,
+ .arg3_type = ARG_CONST_SIZE,
+ .arg4_type = ARG_ANYTHING,
+ .arg5_type = ARG_ANYTHING,
+};
+#endif
+
#endif /* CONFIG_INET */
bool bpf_helper_changes_pkt_data(void *func)
@@ -6284,6 +6351,10 @@ bool bpf_helper_changes_pkt_data(void *func)
return &bpf_tcp_check_syncookie_proto;
case BPF_FUNC_tcp_gen_syncookie:
return &bpf_tcp_gen_syncookie_proto;
+#if IS_BUILTIN(CONFIG_NF_CONNTRACK)
+ case BPF_FUNC_ct_lookup_tcp:
+ return &bpf_xdp_ct_lookup_tcp_proto;
+#endif
#endif
default:
return bpf_base_func_proto(func_id);
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 8649422..14ffd42 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -2750,6 +2750,23 @@ struct bpf_stack_build_id {
* **-EOPNOTSUPP** kernel configuration does not enable SYN cookies
*
* **-EPROTONOSUPPORT** IP packet version is not 4 or 6
+ *
+ * long bpf_ct_lookup_tcp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u64 netns, u64 flags)
+ * Description
+ * Look for conntrack info for a TCP connection matching *tuple*,
+ * optionally in a child network namespace *netns*.
+ *
+ * This helper is available only if the kernel was compiled with
+ * **CONFIG_NF_CONNTRACK** configuration option as built-in.
+ * Return
+ * On success, connection tracking status (see **enum
+ * ip_conntrack_status**).
+ *
+ * On failure, the returned value is one of the following:
+ *
+ * **-EINVAL** input arguments are invalid.
+ *
+ * **-ENOENT** the connection is not known to conntrack.
*/
#define __BPF_FUNC_MAPPER(FN) \
FN(unspec), \
@@ -2862,7 +2879,8 @@ struct bpf_stack_build_id {
FN(sk_storage_get), \
FN(sk_storage_delete), \
FN(send_signal), \
- FN(tcp_gen_syncookie),
+ FN(tcp_gen_syncookie), \
+ FN(ct_lookup_tcp), \
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
* function eBPF program intends to call
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h
index 9f77cba..9f1e2ac 100644
--- a/tools/testing/selftests/bpf/bpf_helpers.h
+++ b/tools/testing/selftests/bpf/bpf_helpers.h
@@ -233,6 +233,9 @@ static int (*bpf_sk_storage_delete)(void *map, struct bpf_sock *sk) =
static long long (*bpf_tcp_gen_syncookie)(struct bpf_sock *sk, void *ip,
int ip_len, void *tcp, int tcp_len) =
(void *) BPF_FUNC_tcp_gen_syncookie;
+static long (*bpf_ct_lookup_tcp)(void *ctx, struct bpf_sock_tuple *tuple,
+ __u32 tuple_size, __u64 netns, __u64 flags) =
+ (void *) BPF_FUNC_ct_lookup_tcp;
/* llvm builtin functions that eBPF C program may use to
* emit BPF_LD_ABS and BPF_LD_IND instructions
--
1.8.3.1
More information about the kernel-team
mailing list