[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1708412505-34470-19-git-send-email-alibuda@linux.alibaba.com>
Date: Tue, 20 Feb 2024 15:01:43 +0800
From: "D. Wythe" <alibuda@...ux.alibaba.com>
To: kgraul@...ux.ibm.com,
wenjia@...ux.ibm.com,
jaka@...ux.ibm.com,
wintera@...ux.ibm.com,
guwen@...ux.alibaba.com
Cc: kuba@...nel.org,
davem@...emloft.net,
netdev@...r.kernel.org,
linux-s390@...r.kernel.org,
linux-rdma@...r.kernel.org,
tonylu@...ux.alibaba.com,
pabeni@...hat.com,
edumazet@...gle.com
Subject: [RFC net-next 18/20] net/smc: add define and macro for smc_negotiation
From: "D. Wythe" <alibuda@...ux.alibaba.com>
smc_negotiation is a new way to describe the state of the SMC
protocol, note that it will only be used by inet sock. It mainly
describes the following states of SMC sock:
TBD: Before TCP handshake is completed.
PREPARE: TCP is established, and smc is establishing.
SMC: smc handshake is established.
NO_SMC: sock should act as TCP.
Before this patch, it is determined that these conditions must be
applied simultaneously to syn_smc/use_fallback/sk_state,
synchronization of fields needs to be handled with care,
while syn_smc field cannot be modified at any time. Based on these
considerations, inet sock uses smc_negotiation to control the
protocol state.
Signed-off-by: D. Wythe <alibuda@...ux.alibaba.com>
---
net/smc/smc.h | 1 +
net/smc/smc_inet.h | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 97 insertions(+)
diff --git a/net/smc/smc.h b/net/smc/smc.h
index 1675193..538920f 100644
--- a/net/smc/smc.h
+++ b/net/smc/smc.h
@@ -252,6 +252,7 @@ struct smc_sock { /* smc sock container */
};
struct socket *clcsock; /* internal tcp socket */
unsigned char smc_state; /* smc state used in smc via inet_sk */
+ unsigned int isck_smc_negotiation;
unsigned long smc_sk_flags; /* smc sock flags used for inet sock */
void (*clcsk_state_change)(struct sock *sk);
/* original stat_change fct. */
diff --git a/net/smc/smc_inet.h b/net/smc/smc_inet.h
index 68ecfa0..1f182c0 100644
--- a/net/smc/smc_inet.h
+++ b/net/smc/smc_inet.h
@@ -18,6 +18,9 @@
/* MUST after net/tcp.h or warning */
#include <net/transp_v6.h>
+#include <net/smc.h>
+#include "smc.h"
+
extern struct proto smc_inet_prot;
extern struct proto smc_inet6_prot;
@@ -27,6 +30,99 @@
extern struct inet_protosw smc_inet_protosw;
extern struct inet_protosw smc_inet6_protosw;
+enum smc_inet_sock_negotiation_state {
+ /* When creating an AF_SMC sock, the state field will be initialized to 0 by default,
+ * which is only for logical compatibility with that situation
+ * and will never be used.
+ */
+ SMC_NEGOTIATION_COMPATIBLE_WITH_AF_SMC = 0,
+
+ /* This connection is still uncertain whether it is an SMC connection or not,
+ * It always appears when actively open SMC connection, because it's unclear
+ * whether the server supports the SMC protocol and has willing to use SMC.
+ */
+ SMC_NEGOTIATION_TBD = 0x10,
+
+ /* This state indicates that this connection is definitely not an SMC connection.
+ * and it is absolutely impossible to become an SMC connection again. A fina
+ * state.
+ */
+ SMC_NEGOTIATION_NO_SMC = 0x20,
+
+ /* This state indicates that this connection is an SMC connection. and it is
+ * absolutely impossible to become an not-SMC connection again. A final state.
+ */
+ SMC_NEGOTIATION_SMC = 0x40,
+
+ /* This state indicates that this connection is in the process of SMC handshake.
+ * It is mainly used to eliminate the ambiguity of syn_smc, because when syn_smc is 1,
+ * It may represent remote has support for SMC, or it may just indicate that itself has
+ * supports for SMC.
+ */
+ SMC_NEGOTIATION_PREPARE_SMC = 0x80,
+
+ /* flags */
+ SMC_NEGOTIATION_LISTEN_FLAG = 0x01,
+ SMC_NEGOTIATION_ABORT_FLAG = 0x02,
+};
+
+static __always_inline void isck_smc_negotiation_store(struct smc_sock *smc,
+ enum smc_inet_sock_negotiation_state state)
+{
+ WRITE_ONCE(smc->isck_smc_negotiation,
+ state | (READ_ONCE(smc->isck_smc_negotiation) & 0x0f));
+}
+
+static __always_inline int isck_smc_negotiation_load(struct smc_sock *smc)
+{
+ return READ_ONCE(smc->isck_smc_negotiation) & 0xf0;
+}
+
+static __always_inline void isck_smc_negotiation_set_flags(struct smc_sock *smc, int flags)
+{
+ smc->isck_smc_negotiation = (smc->isck_smc_negotiation | (flags & 0x0f));
+}
+
+static __always_inline int isck_smc_negotiation_get_flags(struct smc_sock *smc)
+{
+ return smc->isck_smc_negotiation & 0x0f;
+}
+
+static __always_inline bool smc_inet_sock_check_fallback_fast(struct sock *sk)
+{
+ return !tcp_sk(sk)->syn_smc;
+}
+
+static __always_inline bool smc_inet_sock_check_fallback(struct sock *sk)
+{
+ return isck_smc_negotiation_load(smc_sk(sk)) == SMC_NEGOTIATION_NO_SMC;
+}
+
+static __always_inline bool smc_inet_sock_check_smc(struct sock *sk)
+{
+ if (smc_inet_sock_check_fallback_fast(sk))
+ return false;
+
+ return isck_smc_negotiation_load(smc_sk(sk)) == SMC_NEGOTIATION_SMC;
+}
+
+static __always_inline bool smc_inet_sock_is_active_open(struct sock *sk)
+{
+ return !(isck_smc_negotiation_get_flags(smc_sk(sk)) & SMC_NEGOTIATION_LISTEN_FLAG);
+}
+
+static inline void smc_inet_sock_abort(struct sock *sk)
+{
+ write_lock_bh(&sk->sk_callback_lock);
+ if (isck_smc_negotiation_get_flags(smc_sk(sk)) & SMC_NEGOTIATION_ABORT_FLAG) {
+ write_unlock_bh(&sk->sk_callback_lock);
+ return;
+ }
+ isck_smc_negotiation_set_flags(smc_sk(sk), SMC_NEGOTIATION_ABORT_FLAG);
+ write_unlock_bh(&sk->sk_callback_lock);
+ sk->sk_error_report(sk);
+}
+
/* obtain TCP proto via sock family */
static __always_inline struct proto *smc_inet_get_tcp_prot(int family)
{
--
1.8.3.1
Powered by blists - more mailing lists