cxgb4/chtls: Fix tid stuck due to wrong update of qid
TID stuck is seen when there is a race in
CPL_PASS_ACCEPT_RPL/CPL_ABORT_REQ and abort is arriving
before the accept reply, which sets the queue number.
In this case HW ends up sending CPL_ABORT_RPL_RSS to an
incorrect ingress queue.
V1->V2:
- Removed the unused variable len in chtls_set_quiesce_ctrl().
V2->V3:
- As kfree_skb() has a check for null skb, so removed this
check before calling kfree_skb() in func chtls_send_reset().
Fixes: cc35c88ae4
("crypto : chtls - CPL handler definition")
Signed-off-by: Rohit Maheshwari <rohitm@chelsio.com>
Signed-off-by: Ayush Sawal <ayush.sawal@chelsio.com>
Link: https://lore.kernel.org/r/20210112053600.24590-1-ayush.sawal@chelsio.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Родитель
7128c834d3
Коммит
8ad2a970d2
|
@ -40,6 +40,13 @@
|
|||
#define TCB_L2T_IX_M 0xfffULL
|
||||
#define TCB_L2T_IX_V(x) ((x) << TCB_L2T_IX_S)
|
||||
|
||||
#define TCB_T_FLAGS_W 1
|
||||
#define TCB_T_FLAGS_S 0
|
||||
#define TCB_T_FLAGS_M 0xffffffffffffffffULL
|
||||
#define TCB_T_FLAGS_V(x) ((__u64)(x) << TCB_T_FLAGS_S)
|
||||
|
||||
#define TCB_FIELD_COOKIE_TFLAG 1
|
||||
|
||||
#define TCB_SMAC_SEL_W 0
|
||||
#define TCB_SMAC_SEL_S 24
|
||||
#define TCB_SMAC_SEL_M 0xffULL
|
||||
|
|
|
@ -575,7 +575,11 @@ int send_tx_flowc_wr(struct sock *sk, int compl,
|
|||
void chtls_tcp_push(struct sock *sk, int flags);
|
||||
int chtls_push_frames(struct chtls_sock *csk, int comp);
|
||||
int chtls_set_tcb_tflag(struct sock *sk, unsigned int bit_pos, int val);
|
||||
void chtls_set_tcb_field_rpl_skb(struct sock *sk, u16 word,
|
||||
u64 mask, u64 val, u8 cookie,
|
||||
int through_l2t);
|
||||
int chtls_setkey(struct chtls_sock *csk, u32 keylen, u32 mode, int cipher_type);
|
||||
void chtls_set_quiesce_ctrl(struct sock *sk, int val);
|
||||
void skb_entail(struct sock *sk, struct sk_buff *skb, int flags);
|
||||
unsigned int keyid_to_addr(int start_addr, int keyid);
|
||||
void free_tls_keyid(struct sock *sk);
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "chtls.h"
|
||||
#include "chtls_cm.h"
|
||||
#include "clip_tbl.h"
|
||||
#include "t4_tcb.h"
|
||||
|
||||
/*
|
||||
* State transitions and actions for close. Note that if we are in SYN_SENT
|
||||
|
@ -267,7 +268,9 @@ static void chtls_send_reset(struct sock *sk, int mode, struct sk_buff *skb)
|
|||
if (sk->sk_state != TCP_SYN_RECV)
|
||||
chtls_send_abort(sk, mode, skb);
|
||||
else
|
||||
goto out;
|
||||
chtls_set_tcb_field_rpl_skb(sk, TCB_T_FLAGS_W,
|
||||
TCB_T_FLAGS_V(TCB_T_FLAGS_M), 0,
|
||||
TCB_FIELD_COOKIE_TFLAG, 1);
|
||||
|
||||
return;
|
||||
out:
|
||||
|
@ -1949,6 +1952,8 @@ static void chtls_close_con_rpl(struct sock *sk, struct sk_buff *skb)
|
|||
else if (tcp_sk(sk)->linger2 < 0 &&
|
||||
!csk_flag_nochk(csk, CSK_ABORT_SHUTDOWN))
|
||||
chtls_abort_conn(sk, skb);
|
||||
else if (csk_flag_nochk(csk, CSK_TX_DATA_SENT))
|
||||
chtls_set_quiesce_ctrl(sk, 0);
|
||||
break;
|
||||
default:
|
||||
pr_info("close_con_rpl in bad state %d\n", sk->sk_state);
|
||||
|
@ -2292,6 +2297,28 @@ static int chtls_wr_ack(struct chtls_dev *cdev, struct sk_buff *skb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int chtls_set_tcb_rpl(struct chtls_dev *cdev, struct sk_buff *skb)
|
||||
{
|
||||
struct cpl_set_tcb_rpl *rpl = cplhdr(skb) + RSS_HDR;
|
||||
unsigned int hwtid = GET_TID(rpl);
|
||||
struct sock *sk;
|
||||
|
||||
sk = lookup_tid(cdev->tids, hwtid);
|
||||
|
||||
/* return EINVAL if socket doesn't exist */
|
||||
if (!sk)
|
||||
return -EINVAL;
|
||||
|
||||
/* Reusing the skb as size of cpl_set_tcb_field structure
|
||||
* is greater than cpl_abort_req
|
||||
*/
|
||||
if (TCB_COOKIE_G(rpl->cookie) == TCB_FIELD_COOKIE_TFLAG)
|
||||
chtls_send_abort(sk, CPL_ABORT_SEND_RST, NULL);
|
||||
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
chtls_handler_func chtls_handlers[NUM_CPL_CMDS] = {
|
||||
[CPL_PASS_OPEN_RPL] = chtls_pass_open_rpl,
|
||||
[CPL_CLOSE_LISTSRV_RPL] = chtls_close_listsrv_rpl,
|
||||
|
@ -2304,5 +2331,6 @@ chtls_handler_func chtls_handlers[NUM_CPL_CMDS] = {
|
|||
[CPL_CLOSE_CON_RPL] = chtls_conn_cpl,
|
||||
[CPL_ABORT_REQ_RSS] = chtls_conn_cpl,
|
||||
[CPL_ABORT_RPL_RSS] = chtls_conn_cpl,
|
||||
[CPL_FW4_ACK] = chtls_wr_ack,
|
||||
[CPL_FW4_ACK] = chtls_wr_ack,
|
||||
[CPL_SET_TCB_RPL] = chtls_set_tcb_rpl,
|
||||
};
|
||||
|
|
|
@ -88,6 +88,24 @@ static int chtls_set_tcb_field(struct sock *sk, u16 word, u64 mask, u64 val)
|
|||
return ret < 0 ? ret : 0;
|
||||
}
|
||||
|
||||
void chtls_set_tcb_field_rpl_skb(struct sock *sk, u16 word,
|
||||
u64 mask, u64 val, u8 cookie,
|
||||
int through_l2t)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
unsigned int wrlen;
|
||||
|
||||
wrlen = sizeof(struct cpl_set_tcb_field) + sizeof(struct ulptx_idata);
|
||||
wrlen = roundup(wrlen, 16);
|
||||
|
||||
skb = alloc_skb(wrlen, GFP_KERNEL | __GFP_NOFAIL);
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
__set_tcb_field(sk, skb, word, mask, val, cookie, 0);
|
||||
send_or_defer(sk, tcp_sk(sk), skb, through_l2t);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set one of the t_flags bits in the TCB.
|
||||
*/
|
||||
|
@ -113,6 +131,29 @@ static int chtls_set_tcb_quiesce(struct sock *sk, int val)
|
|||
TF_RX_QUIESCE_V(val));
|
||||
}
|
||||
|
||||
void chtls_set_quiesce_ctrl(struct sock *sk, int val)
|
||||
{
|
||||
struct chtls_sock *csk;
|
||||
struct sk_buff *skb;
|
||||
unsigned int wrlen;
|
||||
int ret;
|
||||
|
||||
wrlen = sizeof(struct cpl_set_tcb_field) + sizeof(struct ulptx_idata);
|
||||
wrlen = roundup(wrlen, 16);
|
||||
|
||||
skb = alloc_skb(wrlen, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
csk = rcu_dereference_sk_user_data(sk);
|
||||
|
||||
__set_tcb_field(sk, skb, 1, TF_RX_QUIESCE_V(1), 0, 0, 1);
|
||||
set_wr_txq(skb, CPL_PRIORITY_CONTROL, csk->port_id);
|
||||
ret = cxgb4_ofld_send(csk->egress_dev, skb);
|
||||
if (ret < 0)
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
/* TLS Key bitmap processing */
|
||||
int chtls_init_kmap(struct chtls_dev *cdev, struct cxgb4_lld_info *lldi)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче