diff mbox series

[mptcp-next,v1,4/5] selftests/bpf: Implement mptcp pm helpers in BPF

Message ID 174476b578f6665cc96d03f30ae8b440b84b8b07.1738924875.git.tanggeliang@kylinos.cn (mailing list archive)
State Superseded, archived
Delegated to: Matthieu Baerts
Headers show
Series BPF path manager, part 5 | expand

Checks

Context Check Description
matttbe/build success Build and static analysis OK
matttbe/checkpatch warning total: 0 errors, 4 warnings, 2 checks, 126 lines checked
matttbe/shellcheck success MPTCP selftests files have not been modified
matttbe/KVM_Validation__normal fail Script error! ❓
matttbe/KVM_Validation__debug fail Script error! ❓
matttbe/KVM_Validation__btf-normal__only_bpftest_all_ fail Script error! ❓
matttbe/KVM_Validation__btf-debug__only_bpftest_all_ fail Script error! ❓

Commit Message

Geliang Tang Feb. 7, 2025, 10:49 a.m. UTC
From: Geliang Tang <tanggeliang@kylinos.cn>

This patch implements MPTCP path manager helpers mptcp_pm_copy_addr(),
mptcp_pm_copy_entry(), ipv6_addr_equal(), mptcp_addresses_equal() and
mptcp_pm_find_ssk() in BPF.

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 tools/testing/selftests/bpf/progs/mptcp_bpf.h | 110 ++++++++++++++++++
 1 file changed, 110 insertions(+)
diff mbox series

Patch

diff --git a/tools/testing/selftests/bpf/progs/mptcp_bpf.h b/tools/testing/selftests/bpf/progs/mptcp_bpf.h
index 5e29ac93d823..816917e59995 100644
--- a/tools/testing/selftests/bpf/progs/mptcp_bpf.h
+++ b/tools/testing/selftests/bpf/progs/mptcp_bpf.h
@@ -3,6 +3,7 @@ 
 #define __MPTCP_BPF_H__
 
 #include "bpf_experimental.h"
+#include "bpf_tracing_net.h"
 
 /* mptcp helpers from include/net/mptcp.h */
 #define MPTCP_SUBFLOWS_MAX 8
@@ -36,6 +37,11 @@  static inline int list_is_head(const struct list_head *list,
 #define mptcp_for_each_subflow(__msk, __subflow)			\
 	list_for_each_entry(__subflow, &((__msk)->conn_list), node)
 
+/* errno macros from include/uapi/asm-generic/errno-base.h */
+#define	ESRCH		3	/* No such process */
+#define	ENOMEM		12	/* Out of Memory */
+#define	EINVAL		22	/* Invalid argument */
+
 static __always_inline struct sock *
 mptcp_subflow_tcp_sock(const struct mptcp_subflow_context *subflow)
 {
@@ -62,4 +68,108 @@  extern void mptcp_subflow_set_scheduled(struct mptcp_subflow_context *subflow,
 extern struct mptcp_subflow_context *
 bpf_mptcp_subflow_ctx_by_pos(const struct mptcp_sched_data *data, unsigned int pos) __ksym;
 
+/* reimplemented BPF helpers */
+static __always_inline void
+mptcp_pm_copy_addr(struct mptcp_addr_info *dst,
+		   struct mptcp_addr_info *src)
+{
+	dst->id = src->id;
+	dst->family = src->family;
+	dst->port = src->port;
+
+	if (src->family == AF_INET) {
+		dst->addr.s_addr = src->addr.s_addr;
+	} else if (src->family == AF_INET6) {
+		dst->addr6.s6_addr32[0] = src->addr6.s6_addr32[0];
+		dst->addr6.s6_addr32[1] = src->addr6.s6_addr32[1];
+		dst->addr6.s6_addr32[2] = src->addr6.s6_addr32[2];
+		dst->addr6.s6_addr32[3] = src->addr6.s6_addr32[3];
+	}
+}
+
+static __always_inline void
+mptcp_pm_copy_entry(struct mptcp_pm_addr_entry *dst,
+		    struct mptcp_pm_addr_entry *src)
+{
+	mptcp_pm_copy_addr(&dst->addr, &src->addr);
+
+	dst->flags = src->flags;
+	dst->ifindex = src->ifindex;
+}
+
+#define inet_sk(ptr) container_of(ptr, struct inet_sock, sk)
+
+#define ipv6_addr_equal(a, b)	((a).s6_addr32[0] == (b).s6_addr32[0] &&	\
+				 (a).s6_addr32[1] == (b).s6_addr32[1] &&	\
+				 (a).s6_addr32[2] == (b).s6_addr32[2] &&	\
+				 (a).s6_addr32[3] == (b).s6_addr32[3])
+
+static __always_inline bool
+mptcp_addresses_equal(const struct mptcp_addr_info *a,
+		      const struct mptcp_addr_info *b, bool use_port)
+{
+	bool addr_equals = false;
+
+	if (a->family == b->family) {
+		if (a->family == AF_INET)
+			addr_equals = a->addr.s_addr == b->addr.s_addr;
+		else
+			addr_equals = ipv6_addr_equal(a->addr6, b->addr6);
+	}
+
+	if (!addr_equals)
+		return false;
+	if (!use_port)
+		return true;
+
+	return a->port == b->port;
+}
+
+static __always_inline struct sock *
+mptcp_pm_find_ssk(struct mptcp_sock *msk,
+		  const struct mptcp_addr_info *local,
+		  const struct mptcp_addr_info *remote)
+{
+	struct mptcp_subflow_context *subflow;
+
+	if (local->family != remote->family)
+		return NULL;
+
+	bpf_for_each(mptcp_subflow, subflow, msk) {
+		const struct inet_sock *issk;
+		struct sock *ssk;
+
+		ssk = bpf_mptcp_subflow_tcp_sock(subflow);
+		if (!ssk)
+			continue;
+
+		if (local->family != ssk->sk_family)
+			continue;
+
+		issk = bpf_core_cast(inet_sk(ssk), struct inet_sock);
+
+		switch (ssk->sk_family) {
+		case AF_INET:
+			if (issk->inet_saddr != local->addr.s_addr ||
+			    issk->inet_daddr != remote->addr.s_addr)
+				continue;
+			break;
+		case AF_INET6: {
+			if (!ipv6_addr_equal(local->addr6, issk->pinet6->saddr) ||
+			    !ipv6_addr_equal(remote->addr6, ssk->sk_v6_daddr))
+				continue;
+			break;
+		}
+		default:
+			continue;
+		}
+
+		if (issk->inet_sport == local->port &&
+		    issk->inet_dport == remote->port)
+			return ssk;
+	}
+
+	return NULL;
+}
+
 #endif