@@ -394,6 +394,7 @@ struct tcp_sock {
bool is_mptcp;
#endif
#if IS_ENABLED(CONFIG_SMC)
+ bool (*smc_in_limited)(const struct sock *sk);
bool syn_smc; /* SYN includes SMC */
#endif
@@ -6703,7 +6703,8 @@ static void tcp_openreq_init(struct request_sock *req,
ireq->ir_num = ntohs(tcp_hdr(skb)->dest);
ireq->ir_mark = inet_request_mark(sk, skb);
#if IS_ENABLED(CONFIG_SMC)
- ireq->smc_ok = rx_opt->smc_ok;
+ ireq->smc_ok = rx_opt->smc_ok && !(tcp_sk(sk)->smc_in_limited &&
+ tcp_sk(sk)->smc_in_limited(sk));
#endif
}
@@ -101,6 +101,22 @@ static struct sock *smc_tcp_syn_recv_sock(const struct sock *sk, struct sk_buff
return NULL;
}
+static bool smc_is_in_limited(const struct sock *sk)
+{
+ const struct smc_sock *smc;
+
+ smc = (const struct smc_sock *)
+ ((uintptr_t)sk->sk_user_data & ~SK_USER_DATA_NOCOPY);
+
+ if (!smc)
+ return true;
+
+ if (workqueue_congested(WORK_CPU_UNBOUND, smc_hs_wq))
+ return true;
+
+ return false;
+}
+
static struct smc_hashinfo smc_v4_hashinfo = {
.lock = __RW_LOCK_UNLOCKED(smc_v4_hashinfo.lock),
};
@@ -2309,6 +2325,8 @@ static int smc_listen(struct socket *sock, int backlog)
inet_csk(smc->clcsock->sk)->icsk_af_ops = &smc->af_ops;
+ tcp_sk(smc->clcsock->sk)->smc_in_limited = smc_is_in_limited;
+
rc = kernel_listen(smc->clcsock, backlog);
if (rc) {
smc->clcsock->sk->sk_data_ready = smc->clcsk_data_ready;