Commit 15f295f5 authored by D. Wythe's avatar D. Wythe Committed by Martin KaFai Lau
Browse files

net/smc: bpf: Introduce generic hook for handshake flow



The introduction of IPPROTO_SMC enables eBPF programs to determine
whether to use SMC based on the context of socket creation, such as
network namespaces, PID and comm name, etc.

As a subsequent enhancement, to introduce a new generic hook that
allows decisions on whether to use SMC or not at runtime, including
but not limited to local/remote IP address or ports.

User can write their own implememtion via bpf_struct_ops now to choose
whether to use SMC or not before TCP 3rd handshake to be comleted.

Signed-off-by: default avatarD. Wythe <alibuda@linux.alibaba.com>
Signed-off-by: default avatarMartin KaFai Lau <martin.lau@kernel.org>
Reviewed-by: default avatarDust Li <dust.li@linux.alibaba.com>
Link: https://patch.msgid.link/20251107035632.115950-3-alibuda@linux.alibaba.com
parent 07c428ec
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -17,6 +17,9 @@ struct netns_smc {
#ifdef CONFIG_SYSCTL
	struct ctl_table_header		*smc_hdr;
#endif
#if IS_ENABLED(CONFIG_SMC_HS_CTRL_BPF)
	struct smc_hs_ctrl __rcu	*hs_ctrl;
#endif /* CONFIG_SMC_HS_CTRL_BPF */
	unsigned int			sysctl_autocorking_size;
	unsigned int			sysctl_smcr_buf_type;
	int				sysctl_smcr_testlink_time;
+53 −0
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
#include <linux/wait.h>
#include <linux/dibs.h>

struct tcp_sock;
struct inet_request_sock;
struct sock;

#define SMC_MAX_PNETID_LEN	16	/* Max. length of PNET id */
@@ -50,4 +52,55 @@ struct smcd_dev {
	u8 going_away : 1;
};

#define SMC_HS_CTRL_NAME_MAX 16

enum {
	/* ops can be inherit from init_net */
	SMC_HS_CTRL_FLAG_INHERITABLE = 0x1,

	SMC_HS_CTRL_ALL_FLAGS = SMC_HS_CTRL_FLAG_INHERITABLE,
};

struct smc_hs_ctrl {
	/* private */

	struct list_head list;
	struct module *owner;

	/* public */

	/* unique name */
	char name[SMC_HS_CTRL_NAME_MAX];
	int flags;

	/* Invoked before computing SMC option for SYN packets.
	 * We can control whether to set SMC options by returning various value.
	 * Return 0 to disable SMC, or return any other value to enable it.
	 */
	int (*syn_option)(struct tcp_sock *tp);

	/* Invoked before Set up SMC options for SYN-ACK packets
	 * We can control whether to respond SMC options by returning various
	 * value. Return 0 to disable SMC, or return any other value to enable
	 * it.
	 */
	int (*synack_option)(const struct tcp_sock *tp,
			     struct inet_request_sock *ireq);
};

#if IS_ENABLED(CONFIG_SMC_HS_CTRL_BPF)
#define smc_call_hsbpf(init_val, tp, func, ...) ({				\
	typeof(init_val) __ret = (init_val);					\
	struct smc_hs_ctrl *ctrl;						\
	rcu_read_lock();							\
	ctrl = rcu_dereference(sock_net((struct sock *)(tp))->smc.hs_ctrl);	\
	if (ctrl && ctrl->func)							\
		__ret = ctrl->func(tp, ##__VA_ARGS__);				\
	rcu_read_unlock();							\
	__ret;									\
})
#else
#define smc_call_hsbpf(init_val, tp, ...)  ({ (void)(tp); (init_val); })
#endif /* CONFIG_SMC_HS_CTRL_BPF */

#endif	/* _SMC_H */
+17 −14
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include <net/tcp.h>
#include <net/tcp_ecn.h>
#include <net/mptcp.h>
#include <net/smc.h>
#include <net/proto_memory.h>
#include <net/psp.h>

@@ -802,36 +803,38 @@ static void tcp_options_write(struct tcphdr *th, struct tcp_sock *tp,
	mptcp_options_write(th, ptr, tp, opts);
}

static void smc_set_option(const struct tcp_sock *tp,
static void smc_set_option(struct tcp_sock *tp,
			   struct tcp_out_options *opts,
			   unsigned int *remaining)
{
#if IS_ENABLED(CONFIG_SMC)
	if (static_branch_unlikely(&tcp_have_smc)) {
		if (tp->syn_smc) {
			if (*remaining >= TCPOLEN_EXP_SMC_BASE_ALIGNED) {
	if (static_branch_unlikely(&tcp_have_smc) && tp->syn_smc) {
		tp->syn_smc = !!smc_call_hsbpf(1, tp, syn_option);
		/* re-check syn_smc */
		if (tp->syn_smc &&
		    *remaining >= TCPOLEN_EXP_SMC_BASE_ALIGNED) {
			opts->options |= OPTION_SMC;
			*remaining -= TCPOLEN_EXP_SMC_BASE_ALIGNED;
		}
	}
	}
#endif
}

static void smc_set_option_cond(const struct tcp_sock *tp,
				const struct inet_request_sock *ireq,
				struct inet_request_sock *ireq,
				struct tcp_out_options *opts,
				unsigned int *remaining)
{
#if IS_ENABLED(CONFIG_SMC)
	if (static_branch_unlikely(&tcp_have_smc)) {
		if (tp->syn_smc && ireq->smc_ok) {
			if (*remaining >= TCPOLEN_EXP_SMC_BASE_ALIGNED) {
	if (static_branch_unlikely(&tcp_have_smc) && tp->syn_smc && ireq->smc_ok) {
		ireq->smc_ok = !!smc_call_hsbpf(1, tp, synack_option, ireq);
		/* re-check smc_ok */
		if (ireq->smc_ok &&
		    *remaining >= TCPOLEN_EXP_SMC_BASE_ALIGNED) {
			opts->options |= OPTION_SMC;
			*remaining -= TCPOLEN_EXP_SMC_BASE_ALIGNED;
		}
	}
	}
#endif
}

+10 −0
Original line number Diff line number Diff line
@@ -19,3 +19,13 @@ config SMC_DIAG
	  smcss.

	  if unsure, say Y.

config SMC_HS_CTRL_BPF
	bool "Generic eBPF hook for SMC handshake flow"
	depends on SMC && BPF_SYSCALL
	default y
	help
	  SMC_HS_CTRL_BPF enables support to register generic eBPF hook for SMC
	  handshake flow, which offer much greater flexibility in modifying the behavior
	  of the SMC protocol stack compared to a complete kernel-based approach. Select
	  this option if you want filtring the handshake process via eBPF programs.
 No newline at end of file
+1 −0
Original line number Diff line number Diff line
@@ -6,3 +6,4 @@ smc-y := af_smc.o smc_pnet.o smc_ib.o smc_clc.o smc_core.o smc_wr.o smc_llc.o
smc-y += smc_cdc.o smc_tx.o smc_rx.o smc_close.o smc_ism.o smc_netlink.o smc_stats.o
smc-y += smc_tracepoint.o smc_inet.o
smc-$(CONFIG_SYSCTL) += smc_sysctl.o
smc-$(CONFIG_SMC_HS_CTRL_BPF) += smc_hs_bpf.o
Loading