@@ -575,6 +575,13 @@ extern int bpf_iter_css_new(struct bpf_iter_css *it,
extern struct cgroup_subsys_state *bpf_iter_css_next(struct bpf_iter_css *it) __weak __ksym;
extern void bpf_iter_css_destroy(struct bpf_iter_css *it) __weak __ksym;
+struct bpf_iter_mptcp_subflow;
+extern int bpf_iter_mptcp_subflow_new(struct bpf_iter_mptcp_subflow *it,
+ struct mptcp_sock *msk) __weak __ksym;
+extern struct mptcp_subflow_context *
+bpf_iter_mptcp_subflow_next(struct bpf_iter_mptcp_subflow *it) __weak __ksym;
+extern void bpf_iter_mptcp_subflow_destroy(struct bpf_iter_mptcp_subflow *it) __weak __ksym;
+
extern int bpf_wq_init(struct bpf_wq *wq, void *p__map, unsigned int flags) __weak __ksym;
extern int bpf_wq_start(struct bpf_wq *wq, unsigned int flags) __weak __ksym;
extern int bpf_wq_set_callback_impl(struct bpf_wq *wq,
@@ -43,6 +43,15 @@ mptcp_subflow_tcp_sock(const struct mptcp_subflow_context *subflow)
}
/* ksym */
+extern struct mptcp_sock *bpf_mptcp_sock_acquire(struct mptcp_sock *msk) __ksym;
+extern void bpf_mptcp_sock_release(struct mptcp_sock *msk) __ksym;
+
+extern struct mptcp_sock *bpf_mptcp_sk(struct sock *sk) __ksym;
+extern struct mptcp_subflow_context *
+bpf_mptcp_subflow_ctx(const struct sock *sk) __ksym;
+extern struct sock *
+bpf_mptcp_subflow_tcp_sock(const struct mptcp_subflow_context *subflow) __ksym;
+
extern void mptcp_subflow_set_scheduled(struct mptcp_subflow_context *subflow,
bool scheduled) __ksym;
new file mode 100644
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024, Kylin Software */
+
+/* vmlinux.h, bpf_helpers.h and other 'define' */
+#include "bpf_tracing_net.h"
+#include "mptcp_bpf.h"
+
+char _license[] SEC("license") = "GPL";
+int ids;
+
+SEC("cgroup/getsockopt")
+int iters_subflow(struct bpf_sockopt *ctx)
+{
+ struct mptcp_subflow_context *subflow;
+ struct bpf_sock *sk = ctx->sk;
+ struct sock *ssk = NULL;
+ struct mptcp_sock *msk;
+ int local_ids = 0;
+
+ if (!sk || sk->protocol != IPPROTO_MPTCP ||
+ ctx->level != SOL_TCP || ctx->optname != TCP_CONGESTION)
+ return 1;
+
+ msk = bpf_mptcp_sk((struct sock *)sk);
+ if (msk->pm.server_side || !msk->pm.subflows)
+ return 1;
+
+ msk = bpf_mptcp_sock_acquire(msk);
+ if (!msk)
+ return 1;
+ bpf_for_each(mptcp_subflow, subflow, msk) {
+ /* Here MPTCP-specific packet scheduler kfunc can be called:
+ * this test is not doing anything really useful, only to
+ * verify the iteration works.
+ */
+
+ local_ids += subflow->subflow_id;
+
+ /* only to check the following kfunc works */
+ ssk = bpf_mptcp_subflow_tcp_sock(subflow);
+ }
+
+ if (!ssk)
+ goto out;
+
+ /* assert: if not OK, something wrong on the kernel side */
+ if (ssk->sk_dport != ((struct sock *)msk)->sk_dport)
+ goto out;
+
+ /* only to check the following kfunc works */
+ subflow = bpf_mptcp_subflow_ctx(ssk);
+ if (subflow->token != msk->token)
+ goto out;
+
+ ids = local_ids;
+
+out:
+ bpf_mptcp_sock_release(msk);
+ return 1;
+}