From 67d4f460d18ff27cfd002583f7149276912f909f Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Sat, 12 Oct 2024 11:19:44 +0800 Subject: [PATCH] ipv6 Signed-off-by: Geliang Tang --- net/mptcp/bpf.c | 13 ++++++ .../testing/selftests/bpf/prog_tests/mptcp.c | 17 ++++--- tools/testing/selftests/bpf/progs/mptcp_bpf.h | 14 ++++++ .../bpf/progs/mptcp_bpf_userspace_pm.c | 45 +++++++++++++++++++ .../selftests/bpf/progs/test_fill_link_info.c | 1 + 5 files changed, 83 insertions(+), 7 deletions(-) diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c index fd794a4f4fbed..22eea0bd95d0e 100644 --- a/net/mptcp/bpf.c +++ b/net/mptcp/bpf.c @@ -624,6 +624,17 @@ __bpf_kfunc __u8 bpf_next_bit(struct mptcp_id_bitmap *bitmap) return find_next_zero_bit(bitmap->map, MPTCP_PM_MAX_ADDR_ID + 1, 1); } +__bpf_kfunc bool bpf_ipv6_addr_v4mapped(const struct mptcp_addr_info *a) +{ + return ipv6_addr_v4mapped(&a->addr6); +} + +__bpf_kfunc void bpf_ipv6_addr_set_v4mapped(const __be32 addr, + struct mptcp_addr_info *v4mapped) +{ + ipv6_addr_set_v4mapped(addr, &v4mapped->addr6); +} + __bpf_kfunc bool bpf_mptcp_subflow_queues_empty(struct sock *sk) { return tcp_rtx_queue_empty(sk); @@ -666,6 +677,8 @@ BTF_ID_FLAGS(func, bpf_bitmap_zero) BTF_ID_FLAGS(func, bpf_test_bit) BTF_ID_FLAGS(func, bpf_set_bit) BTF_ID_FLAGS(func, bpf_next_bit) +BTF_ID_FLAGS(func, bpf_ipv6_addr_v4mapped) +BTF_ID_FLAGS(func, bpf_ipv6_addr_set_v4mapped) BTF_ID_FLAGS(func, mptcp_pm_remove_addr) BTF_ID_FLAGS(func, mptcp_pm_remove_addr_entry, KF_SLEEPABLE) BTF_ID_FLAGS(func, __mptcp_subflow_connect, KF_SLEEPABLE) diff --git a/tools/testing/selftests/bpf/prog_tests/mptcp.c b/tools/testing/selftests/bpf/prog_tests/mptcp.c index 69e25c674cddc..f473d2ee38e7e 100644 --- a/tools/testing/selftests/bpf/prog_tests/mptcp.c +++ b/tools/testing/selftests/bpf/prog_tests/mptcp.c @@ -827,6 +827,7 @@ static int userspace_pm_dump_addr(char *output) if (!ASSERT_STRNEQ(buf, output, sizeof(buf), "dump_addr")) return -1; + printf("\n\n\n\ndump: %s\n\n", buf); return 0; } @@ -893,7 +894,7 @@ static int userspace_pm_rm_addr(__u8 id) return 0; } -static void run_userspace_pm(void) +static void run_userspace_pm(bool ipv6) { int server_fd, client_fd, accept_fd; int err; @@ -950,14 +951,15 @@ static void run_userspace_pm(void) send_byte(accept_fd); recv_byte(client_fd); - err = userspace_pm_add_addr(ADDR_3, 200); + err = userspace_pm_add_addr(ipv6 ? ADDR6_3 : ADDR_3, 200); if (!ASSERT_OK(err, "userspace_pm_add_addr")) goto close_accept; send_byte(accept_fd); recv_byte(client_fd); - err = userspace_pm_dump_addr("id 200 flags signal 10.0.1.3\n"); + err = userspace_pm_dump_addr(ipv6 ? "id 200 flags signal dead:beef:1::3\n" : + "id 200 flags signal 10.0.1.3\n"); if (!ASSERT_OK(err, "userspace_pm_dump_addr")) goto close_accept; @@ -995,14 +997,14 @@ static void test_userspace_pm(void) if (!ASSERT_OK(err, "userspace_pm_init: userspace pm")) goto fail; - run_userspace_pm(); + run_userspace_pm(false); userspace_pm_cleanup(); fail: cleanup_netns(nstoken); } -static void test_bpf_pm(struct bpf_object *obj, char *pm) +static void test_bpf_pm(struct bpf_object *obj, char *pm, bool ipv6) { struct nstoken *nstoken; struct bpf_link *link; @@ -1022,7 +1024,7 @@ static void test_bpf_pm(struct bpf_object *obj, char *pm) if (!ASSERT_OK(err, "userspace_pm_init: bpf pm")) goto close_netns; - run_userspace_pm(); + run_userspace_pm(ipv6); userspace_pm_cleanup(); close_netns: @@ -1062,7 +1064,8 @@ static void test_userspace_bpf(void) if (!ASSERT_OK(mptcp_bpf_userspace_pm__load(skel), "load: userspace_pm")) goto fail; - test_bpf_pm(skel->obj, "userspace_pm"); + //test_bpf_pm(skel->obj, "userspace_pm", skel->kconfig->CONFIG_MPTCP_IPV6); + test_bpf_pm(skel->obj, "userspace_pm", 1); fail: mptcp_bpf_userspace_pm__destroy(skel); diff --git a/tools/testing/selftests/bpf/progs/mptcp_bpf.h b/tools/testing/selftests/bpf/progs/mptcp_bpf.h index d2dd1800ed4fc..1ac3d7f568fa5 100644 --- a/tools/testing/selftests/bpf/progs/mptcp_bpf.h +++ b/tools/testing/selftests/bpf/progs/mptcp_bpf.h @@ -2,6 +2,7 @@ #ifndef __MPTCP_BPF_H__ #define __MPTCP_BPF_H__ +#include #include "bpf_experimental.h" /* mptcp helpers from include/net/mptcp.h */ @@ -23,6 +24,9 @@ #define ENOMEM 12 /* Out of Memory */ #define EINVAL 22 /* Invalid argument */ +#define sk_ipv6only __sk_common.skc_ipv6only +#define ipv6_only_sock(sk) (sk->sk_ipv6only) + /* list helpers from include/linux/list.h */ static inline int list_is_head(const struct list_head *list, const struct list_head *head) @@ -55,6 +59,12 @@ static inline int list_is_head(const struct list_head *list, #define mptcp_for_each_address(__msk, __entry) \ list_for_each_entry(__entry, &((__msk)->pm.userspace_pm_local_addr_list), list) +#define ipv6_addr_equal(a1, a2) ((a1).s6_addr32[0] == (a2).s6_addr32[0] && \ + (a1).s6_addr32[1] == (a2).s6_addr32[1] && \ + (a1).s6_addr32[2] == (a2).s6_addr32[2] && \ + (a1).s6_addr32[3] == (a2).s6_addr32[3]) +#define ipv6_addr_cmp(a1, a2) memcmp((a1), (a2), sizeof(struct in6_addr)); + static __always_inline struct sock * mptcp_subflow_tcp_sock(const struct mptcp_subflow_context *subflow) { @@ -99,6 +109,10 @@ extern bool bpf_test_bit(u8 nr, struct mptcp_id_bitmap *bitmap) __ksym; extern void bpf_set_bit(u8 nr, struct mptcp_id_bitmap *bitmap) __ksym; extern u8 bpf_next_bit(struct mptcp_id_bitmap *bitmap) __ksym; +extern bool bpf_ipv6_addr_v4mapped(const struct mptcp_addr_info *a) __ksym; +extern void bpf_ipv6_addr_set_v4mapped(const __be32 addr, + struct mptcp_addr_info *v4mapped) __ksym; + extern int mptcp_pm_remove_addr(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list) __ksym; extern void mptcp_pm_remove_addr_entry(struct mptcp_sock *msk, diff --git a/tools/testing/selftests/bpf/progs/mptcp_bpf_userspace_pm.c b/tools/testing/selftests/bpf/progs/mptcp_bpf_userspace_pm.c index 93bf42a868348..1d62e78f64583 100644 --- a/tools/testing/selftests/bpf/progs/mptcp_bpf_userspace_pm.c +++ b/tools/testing/selftests/bpf/progs/mptcp_bpf_userspace_pm.c @@ -4,6 +4,7 @@ #include "bpf_tracing_net.h" #include "mptcp_bpf.h" +extern bool CONFIG_MPTCP_IPV6 __kconfig __weak; char _license[] SEC("license") = "GPL"; SEC("struct_ops") @@ -24,6 +25,16 @@ static bool mptcp_addresses_equal(const struct mptcp_addr_info *a, if (a->family == b->family) { if (a->family == AF_INET) addr_equals = a->addr.s_addr == b->addr.s_addr; +#if CONFIG_MPTCP_IPV6 + else + addr_equals = !ipv6_addr_cmp(&a->addr6, &b->addr6); + } else if (a->family == AF_INET) { + if (bpf_ipv6_addr_v4mapped(b)) + addr_equals = a->addr.s_addr == b->addr6.s6_addr32[3]; + } else if (b->family == AF_INET) { + if (bpf_ipv6_addr_v4mapped(a)) + addr_equals = a->addr6.s6_addr32[3] == b->addr.s_addr; +#endif } if (!addr_equals) @@ -179,7 +190,20 @@ static bool mptcp_pm_addr_families_match(const struct sock *sk, { bool mptcp_is_v4 = sk->sk_family == AF_INET; +#if CONFIG_MPTCP_IPV6 + bool loc_is_v4 = loc->family == AF_INET || bpf_ipv6_addr_v4mapped(loc); + bool rem_is_v4 = rem->family == AF_INET || bpf_ipv6_addr_v4mapped(rem); + + if (mptcp_is_v4) + return loc_is_v4 && rem_is_v4; + + if (ipv6_only_sock(sk)) + return !loc_is_v4 && !rem_is_v4; + + return loc_is_v4 == rem_is_v4; +#else return mptcp_is_v4 && loc->family == AF_INET && rem->family == AF_INET; +#endif } static struct mptcp_pm_addr_entry * @@ -267,6 +291,16 @@ static struct sock *mptcp_pm_find_ssk(struct mptcp_sock *msk, issk->inet_daddr != remote->addr.s_addr) continue; break; +#if CONFIG_MPTCP_IPV6 + case AF_INET6: { + const struct ipv6_pinfo *pinfo = bpf_core_cast(ssk, struct ipv6_pinfo); + + if (!ipv6_addr_equal(local->addr6, pinfo->saddr) || + !ipv6_addr_equal(remote->addr6, ssk->sk_v6_daddr)) + continue; + break; + } +#endif default: continue; } @@ -287,6 +321,17 @@ int BPF_PROG(mptcp_pm_subflow_destroy, struct mptcp_sock *msk, int err = -EINVAL; struct sock *ssk; +#if CONFIG_MPTCP_IPV6 + if (local->addr.family == AF_INET && bpf_ipv6_addr_v4mapped(remote)) { + bpf_ipv6_addr_set_v4mapped(local->addr.addr.s_addr, remote); + local->addr.family = AF_INET6; + } + if (remote->family == AF_INET && bpf_ipv6_addr_v4mapped(&local->addr)) { + bpf_ipv6_addr_set_v4mapped(remote->addr.s_addr, &local->addr); + remote->family = AF_INET6; + } +#endif + if (local->addr.family != remote->family) return err; diff --git a/tools/testing/selftests/bpf/progs/test_fill_link_info.c b/tools/testing/selftests/bpf/progs/test_fill_link_info.c index 6afa834756e9f..339909ec21f24 100644 --- a/tools/testing/selftests/bpf/progs/test_fill_link_info.c +++ b/tools/testing/selftests/bpf/progs/test_fill_link_info.c @@ -6,6 +6,7 @@ #include extern bool CONFIG_X86_KERNEL_IBT __kconfig __weak; +extern bool CONFIG_MPTCP_IPV6 __kconfig __weak; /* This function is here to have CONFIG_X86_KERNEL_IBT * used and added to object BTF.