From fbe1ea0c5d88b1b60c0fce1c5b3b4eddd2a1c62c Mon Sep 17 00:00:00 2001 From: Gengbiao-Shen Date: Tue, 23 May 2023 09:35:01 +0800 Subject: [PATCH] net/smc: Introduce high performance mode for boosting SMC sangfor inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I73B5W ------------------------------------------ Introduce a slightly micro polling mechanism into SMC's rx/tx paths, so rx/tx interfaces can obtain faster performance due to lower possibility of entering sk_wait. The mode can be configured when probing the SMC module. Signed-off-by: Gengbiao Shen --- net/smc/af_smc.c | 15 +++++++++++++++ net/smc/smc_hp.h | 27 +++++++++++++++++++++++++++ net/smc/smc_rx.c | 33 +++++++++++++++++++++++++++++++-- net/smc/smc_tx.c | 28 +++++++++++++++++++++++++++- 4 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 net/smc/smc_hp.h diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index 41cbc7c89c9d..bb5a4d040362 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c @@ -48,6 +48,7 @@ #include "smc_tx.h" #include "smc_rx.h" #include "smc_close.h" +#include "smc_hp.h" static DEFINE_MUTEX(smc_server_lgr_pending); /* serialize link group * creation on server @@ -59,6 +60,20 @@ static DEFINE_MUTEX(smc_client_lgr_pending); /* serialize link group struct workqueue_struct *smc_hs_wq; /* wq for handshake work */ struct workqueue_struct *smc_close_wq; /* wq for close work */ +bool smc_hp_mode = SMC_HP_MODE; /* flag for smc high performance mode */ +ushort smc_rx_micro_loop_us = SMC_RX_MICRO_LOOP_US; /* rx micro loop time in us */ +ushort smc_tx_micro_loop_us = SMC_TX_MICRO_LOOP_US; /* tx micro loop time in us */ + +module_param_named(hp_mode, smc_hp_mode, bool, 0644); +MODULE_PARM_DESC(hp_mode, + "SMC high performance mode. [Default=" __stringify(SMC_HP_MODE) "]"); +module_param_named(rx_micro_loop, smc_rx_micro_loop_us, ushort, 0644); +MODULE_PARM_DESC(rx_micro_loop, + "SMC rx micro loop time in us. [Default=" __stringify(SMC_RX_MICRO_LOOP_US) "]"); +module_param_named(tx_micro_loop, smc_tx_micro_loop_us, ushort, 0644); +MODULE_PARM_DESC(tx_micro_loop, + "SMC tx micro loop time in us. [Default=" __stringify(SMC_TX_MICRO_LOOP_US) "]"); + static void smc_tcp_listen_work(struct work_struct *); static void smc_connect_work(struct work_struct *); diff --git a/net/smc/smc_hp.h b/net/smc/smc_hp.h new file mode 100644 index 000000000000..da5041537614 --- /dev/null +++ b/net/smc/smc_hp.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Shared Memory Communications over RDMA (SMC-R) and RoCE + * + * smc_hp.h: smc high performance interface of SMC subsystem. + * + * Copyright (c) 2023, Sangfor Technologies Inc. + * + * Author: Gengbiao Shen + * + */ + +#ifndef SMC_HP_H +#define SMC_HP_H + +#include + +/* params for smc high performance mode */ +#define SMC_HP_MODE true +#define SMC_RX_MICRO_LOOP_US 100 +#define SMC_TX_MICRO_LOOP_US 0 + +extern bool smc_hp_mode; +extern ushort smc_rx_micro_loop_us; +extern ushort smc_tx_micro_loop_us; + +#endif /* SMC_HP_H */ diff --git a/net/smc/smc_rx.c b/net/smc/smc_rx.c index 7f7e983e42b1..5a0a7412eaa6 100644 --- a/net/smc/smc_rx.c +++ b/net/smc/smc_rx.c @@ -21,6 +21,7 @@ #include "smc_cdc.h" #include "smc_tx.h" /* smc_tx_consumer_update() */ #include "smc_rx.h" +#include "smc_hp.h" /* callback implementation to wakeup consumers blocked with smc_rx_wait(). * indirectly called by smc_cdc_msg_recv_action(). @@ -214,6 +215,24 @@ int smc_rx_wait(struct smc_sock *smc, long *timeo, return rc; } +/* enter real rx wait process until rx micro polling timeout */ +int smc_hp_rx_wait(struct smc_sock *smc, long *timeo, + int (*fcrit)(struct smc_connection *conn), ktime_t *end_time) +{ + int rc = 0; + + if (unlikely(!smc_rx_micro_loop_us)) { + rc = smc_rx_wait(smc, timeo, fcrit); + } else if (unlikely(!(*end_time))) { + *end_time = ktime_add_us(ktime_get(), (u64)smc_rx_micro_loop_us); + } else if (unlikely(ktime_after(ktime_get(), *end_time))) { + *end_time = 0; + rc = smc_rx_wait(smc, timeo, fcrit); + } + + return rc; +} + static int smc_rx_recv_urg(struct smc_sock *smc, struct msghdr *msg, int len, int flags) { @@ -291,6 +310,7 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg, long timeo; int target; /* Read at least these many bytes */ int rc; + ktime_t end_time = 0; if (unlikely(flags & MSG_ERRQUEUE)) return -EINVAL; /* future work for sk.sk_family == AF_SMC */ @@ -355,7 +375,10 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg, } if (!smc_rx_data_available(conn)) { - smc_rx_wait(smc, &timeo, smc_rx_data_available); + if (likely(smc_hp_mode)) + smc_hp_rx_wait(smc, &timeo, smc_rx_data_available, &end_time); + else + smc_rx_wait(smc, &timeo, smc_rx_data_available); continue; } @@ -369,10 +392,16 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg, func = smc_rx_data_available_and_no_splice_pend; else func = smc_rx_data_available; - smc_rx_wait(smc, &timeo, func); + if (likely(smc_hp_mode)) + smc_hp_rx_wait(smc, &timeo, func, &end_time); + else + smc_rx_wait(smc, &timeo, func); continue; } + if (end_time) + end_time = 0; + smc_curs_copy(&cons, &conn->local_tx_ctrl.cons, conn); /* subsequent splice() calls pick up where previous left */ if (splbytes) diff --git a/net/smc/smc_tx.c b/net/smc/smc_tx.c index 52ef1fca0b60..39426f507ca8 100644 --- a/net/smc/smc_tx.c +++ b/net/smc/smc_tx.c @@ -27,6 +27,7 @@ #include "smc_close.h" #include "smc_ism.h" #include "smc_tx.h" +#include "smc_hp.h" #define SMC_TX_WORK_DELAY 0 #define SMC_TX_CORK_DELAY (HZ >> 2) /* 250 ms */ @@ -121,6 +122,24 @@ static int smc_tx_wait(struct smc_sock *smc, int flags) return rc; } +/* enter real tx wait process until tx micro polling timeout */ +static int smc_hp_tx_wait(struct smc_sock *smc, int flags, + ktime_t *end_time) +{ + int rc = 0; + + if (flags & MSG_DONTWAIT || !smc_tx_micro_loop_us) { + rc = smc_tx_wait(smc, flags); + } else if (unlikely(!(*end_time))) { + *end_time = ktime_add_us(ktime_get(), (u64)smc_tx_micro_loop_us); + } else if (unlikely(ktime_after(ktime_get(), *end_time))) { + *end_time = 0; + rc = smc_tx_wait(smc, flags); + } + + return rc; +} + static bool smc_tx_is_corked(struct smc_sock *smc) { struct tcp_sock *tp = tcp_sk(smc->clcsock->sk); @@ -142,6 +161,7 @@ int smc_tx_sendmsg(struct smc_sock *smc, struct msghdr *msg, size_t len) int tx_cnt_prep; int writespace; int rc, chunk; + ktime_t end_time = 0; /* This should be in poll */ sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk); @@ -167,12 +187,18 @@ int smc_tx_sendmsg(struct smc_sock *smc, struct msghdr *msg, size_t len) if (!atomic_read(&conn->sndbuf_space) || conn->urg_tx_pend) { if (send_done) return send_done; - rc = smc_tx_wait(smc, msg->msg_flags); + if (likely(smc_hp_mode)) + rc = smc_hp_tx_wait(smc, msg->msg_flags, &end_time); + else + rc = smc_tx_wait(smc, msg->msg_flags); if (rc) goto out_err; continue; } + if (end_time) + end_time = 0; + /* initialize variables for 1st iteration of subsequent loop */ /* could be just 1 byte, even after smc_tx_wait above */ writespace = atomic_read(&conn->sndbuf_space); -- Gitee