Index: head/sys/dev/cxgbe/offload.h =================================================================== --- head/sys/dev/cxgbe/offload.h +++ head/sys/dev/cxgbe/offload.h @@ -225,6 +225,7 @@ int ddp; int rx_coalesce; int tls; + int tls_rx_timeout; int *tls_rx_ports; int num_tls_rx_ports; int tx_align; Index: head/sys/dev/cxgbe/t4_main.c =================================================================== --- head/sys/dev/cxgbe/t4_main.c +++ head/sys/dev/cxgbe/t4_main.c @@ -403,6 +403,11 @@ &t4_toe_rexmt_backoff[14], 0, ""); SYSCTL_INT(_hw_cxgbe_toe_rexmt_backoff, OID_AUTO, 15, CTLFLAG_RDTUN, &t4_toe_rexmt_backoff[15], 0, ""); + +static int t4_toe_tls_rx_timeout = 5; +SYSCTL_INT(_hw_cxgbe_toe, OID_AUTO, tls_rx_timeout, CTLFLAG_RDTUN, + &t4_toe_tls_rx_timeout, 0, + "Timeout in seconds to downgrade TLS sockets to plain TOE"); #endif #ifdef DEV_NETMAP @@ -786,6 +791,7 @@ #ifdef TCP_OFFLOAD static int sysctl_tls(SYSCTL_HANDLER_ARGS); static int sysctl_tls_rx_ports(SYSCTL_HANDLER_ARGS); +static int sysctl_tls_rx_timeout(SYSCTL_HANDLER_ARGS); static int sysctl_tp_tick(SYSCTL_HANDLER_ARGS); static int sysctl_tp_dack_timer(SYSCTL_HANDLER_ARGS); static int sysctl_tp_timer(SYSCTL_HANDLER_ARGS); @@ -6789,6 +6795,12 @@ sysctl_tls_rx_ports, "I", "TCP ports that use inline TLS+TOE RX"); + sc->tt.tls_rx_timeout = t4_toe_tls_rx_timeout; + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tls_rx_timeout", + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, 0, + sysctl_tls_rx_timeout, "I", + "Timeout in seconds to downgrade TLS sockets to plain TOE"); + sc->tt.tx_align = -1; SYSCTL_ADD_INT(ctx, children, OID_AUTO, "tx_align", CTLFLAG_RW, &sc->tt.tx_align, 0, "chop and align payload"); @@ -10046,6 +10058,29 @@ return (rc); } +static int +sysctl_tls_rx_timeout(SYSCTL_HANDLER_ARGS) +{ + struct adapter *sc = arg1; + int v, rc; + + v = sc->tt.tls_rx_timeout; + rc = sysctl_handle_int(oidp, &v, 0, req); + if (rc != 0 || req->newptr == NULL) + return (rc); + + if (v < 0) + return (EINVAL); + + if (v != 0 && !(sc->cryptocaps & FW_CAPS_CONFIG_TLSKEYS)) + return (ENOTSUP); + + sc->tt.tls_rx_timeout = v; + + return (0); + +} + static void unit_conv(char *buf, size_t len, u_int val, u_int factor) { @@ -11287,6 +11322,9 @@ if (t4_pktc_idx_ofld < -1 || t4_pktc_idx_ofld >= SGE_NCOUNTERS) t4_pktc_idx_ofld = PKTC_IDX_OFLD; + + if (t4_toe_tls_rx_timeout < 0) + t4_toe_tls_rx_timeout = 0; #else if (t4_rdmacaps_allowed == -1) t4_rdmacaps_allowed = 0; Index: head/sys/dev/cxgbe/tom/t4_connect.c =================================================================== --- head/sys/dev/cxgbe/tom/t4_connect.c +++ head/sys/dev/cxgbe/tom/t4_connect.c @@ -105,9 +105,6 @@ inp->inp_flowtype = M_HASHTYPE_OPAQUE; inp->inp_flowid = tid; - if (ulp_mode(toep) == ULP_MODE_TLS) - tls_establish(toep); - done: INP_WUNLOCK(inp); CURVNET_RESTORE(); Index: head/sys/dev/cxgbe/tom/t4_cpl_io.c =================================================================== --- head/sys/dev/cxgbe/tom/t4_cpl_io.c +++ head/sys/dev/cxgbe/tom/t4_cpl_io.c @@ -392,6 +392,9 @@ send_flowc_wr(toep, tp); soisconnected(so); + + if (ulp_mode(toep) == ULP_MODE_TLS) + tls_establish(toep); } int Index: head/sys/dev/cxgbe/tom/t4_tls.c =================================================================== --- head/sys/dev/cxgbe/tom/t4_tls.c +++ head/sys/dev/cxgbe/tom/t4_tls.c @@ -64,14 +64,6 @@ */ #define tls_tcp_seq PH_loc.thirtytwo[0] -/* - * Handshake lock used for the handshake timer. Having a global lock - * is perhaps not ideal, but it avoids having to use callout_drain() - * in tls_uninit_toep() which can't block. Also, the timer shouldn't - * actually fire for most connections. - */ -static struct mtx tls_handshake_lock; - static void t4_set_tls_tcb_field(struct toepcb *toep, uint16_t word, uint64_t mask, uint64_t val) @@ -149,7 +141,7 @@ V_TCB_ULP_TYPE(M_TCB_ULP_TYPE), V_TCB_ULP_TYPE(ULP_MODE_NONE)); t4_clear_rx_quiesce(toep); - toep->flags &= ~TPF_FORCE_CREDITS; + toep->flags &= ~(TPF_FORCE_CREDITS | TPF_TLS_ESTABLISHED); toep->params.ulp_mode = ULP_MODE_NONE; } @@ -748,6 +740,25 @@ struct adapter *sc = td_adapter(toep->td); /* + * If this connection has timed out without receiving more + * data, downgrade to plain TOE mode and don't re-arm the + * timer. + */ + if (sc->tt.tls_rx_timeout != 0) { + struct inpcb *inp; + struct tcpcb *tp; + + inp = toep->inp; + tp = intotcpcb(inp); + if ((ticks - tp->t_rcvtime) >= sc->tt.tls_rx_timeout) { + CTR2(KTR_CXGBE, "%s: tid %d clr_ofld_mode", __func__, + toep->tid); + tls_clr_ofld_mode(toep); + return; + } + } + + /* * XXX: Does not have the t4_get_tcb() checks to refine the * workaround. */ @@ -762,10 +773,9 @@ { struct tls_ofld_info *tls_ofld = &toep->tls; - mtx_lock(&tls_handshake_lock); + INP_WLOCK_ASSERT(toep->inp); callout_reset(&tls_ofld->handshake_timer, TLS_SRV_HELLO_BKOFF_TM * hz, tls_send_handshake_ack, toep); - mtx_unlock(&tls_handshake_lock); } void @@ -773,9 +783,8 @@ { struct tls_ofld_info *tls_ofld = &toep->tls; - mtx_lock(&tls_handshake_lock); + INP_WLOCK_ASSERT(toep->inp); callout_stop(&tls_ofld->handshake_timer); - mtx_unlock(&tls_handshake_lock); } int @@ -1129,9 +1138,6 @@ tls_ofld->key_location = TLS_SFO_WR_CONTEXTLOC_DDR; tls_ofld->rx_key_addr = -1; tls_ofld->tx_key_addr = -1; - if (ulp_mode(toep) == ULP_MODE_TLS) - callout_init_mtx(&tls_ofld->handshake_timer, - &tls_handshake_lock, 0); } void @@ -1149,17 +1155,27 @@ t4_set_tls_tcb_field(toep, W_TCB_ULP_RAW, V_TCB_ULP_RAW(M_TCB_ULP_RAW), V_TCB_ULP_RAW(V_TF_TLS_ENABLE(1))); - toep->flags |= TPF_FORCE_CREDITS; + toep->flags |= TPF_FORCE_CREDITS | TPF_TLS_ESTABLISHED; + callout_init_rw(&toep->tls.handshake_timer, &toep->inp->inp_lock, 0); tls_start_handshake_timer(toep); } void -tls_uninit_toep(struct toepcb *toep) +tls_detach(struct toepcb *toep) { - if (ulp_mode(toep) == ULP_MODE_TLS) + if (toep->flags & TPF_TLS_ESTABLISHED) { tls_stop_handshake_timer(toep); + toep->flags &= ~TPF_TLS_ESTABLISHED; + } +} + +void +tls_uninit_toep(struct toepcb *toep) +{ + + MPASS((toep->flags & TPF_TLS_ESTABLISHED) == 0); clear_tls_keyid(toep); } @@ -2383,7 +2399,6 @@ t4_tls_mod_load(void) { - mtx_init(&tls_handshake_lock, "t4tls handshake", NULL, MTX_DEF); t4_register_cpl_handler(CPL_TLS_DATA, do_tls_data); t4_register_cpl_handler(CPL_RX_TLS_CMP, do_rx_tls_cmp); } @@ -2394,6 +2409,5 @@ t4_register_cpl_handler(CPL_TLS_DATA, NULL); t4_register_cpl_handler(CPL_RX_TLS_CMP, NULL); - mtx_destroy(&tls_handshake_lock); } #endif /* TCP_OFFLOAD */ Index: head/sys/dev/cxgbe/tom/t4_tom.h =================================================================== --- head/sys/dev/cxgbe/tom/t4_tom.h +++ head/sys/dev/cxgbe/tom/t4_tom.h @@ -75,6 +75,7 @@ TPF_KTLS = (1 << 11), /* send TLS records from KTLS */ TPF_INITIALIZED = (1 << 12), /* init_toepcb has been called */ TPF_TLS_RECEIVE = (1 << 13), /* should receive TLS records */ + TPF_TLS_ESTABLISHED = (1 << 14), /* TLS handshake timer initialized */ }; enum { @@ -448,6 +449,7 @@ void t4_push_ktls(struct adapter *, struct toepcb *, int); void t4_tls_mod_load(void); void t4_tls_mod_unload(void); +void tls_detach(struct toepcb *); void tls_establish(struct toepcb *); void tls_init_toep(struct toepcb *); int tls_rx_key(struct toepcb *); Index: head/sys/dev/cxgbe/tom/t4_tom.c =================================================================== --- head/sys/dev/cxgbe/tom/t4_tom.c +++ head/sys/dev/cxgbe/tom/t4_tom.c @@ -382,6 +382,9 @@ } #endif + if (ulp_mode(toep) == ULP_MODE_TLS) + tls_detach(toep); + tp->tod = NULL; tp->t_toe = NULL; tp->t_flags &= ~TF_TOE; @@ -845,6 +848,8 @@ if (ulp_mode(toep) == ULP_MODE_TCPDDP) release_ddp_resources(toep); + else if (ulp_mode(toep) == ULP_MODE_TLS) + tls_detach(toep); toep->inp = NULL; toep->flags &= ~TPF_CPL_PENDING; mbufq_drain(&toep->ulp_pdu_reclaimq);