cxgbe/t4_tom: restore socket's protosw before entering TIME_WAIT.

This fixes a panic due to stale so->so_proto if t4_tom is unloaded and
one or more connections that were previously offloaded are still around
in TIME_WAIT state.

Reviewed by:	jhb@
MFC after:	1 week
Sponsored by:	Chelsio Communications
Differential Revision:	https://reviews.freebsd.org/D29503
This commit is contained in:
Navdeep Parhar 2021-03-29 21:35:05 -07:00
parent 869880463c
commit 5394893269
3 changed files with 15 additions and 2 deletions

View File

@ -1260,6 +1260,7 @@ do_peer_close(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
break;
case TCPS_FIN_WAIT_2:
restore_so_proto(so, inp->inp_vflag & INP_IPV6);
tcp_twstart(tp);
INP_UNLOCK_ASSERT(inp); /* safe, we have a ref on the inp */
NET_EPOCH_EXIT(et);
@ -1320,6 +1321,7 @@ do_close_con_rpl(struct sge_iq *iq, const struct rss_header *rss,
switch (tp->t_state) {
case TCPS_CLOSING: /* see TCPS_FIN_WAIT_2 in do_peer_close too */
restore_so_proto(so, inp->inp_vflag & INP_IPV6);
tcp_twstart(tp);
release:
INP_UNLOCK_ASSERT(inp); /* safe, we have a ref on the inp */

View File

@ -79,9 +79,11 @@ __FBSDID("$FreeBSD$");
#include "tom/t4_tom.h"
#include "tom/t4_tls.h"
static struct protosw *tcp_protosw;
static struct protosw toe_protosw;
static struct pr_usrreqs toe_usrreqs;
static struct protosw *tcp6_protosw;
static struct protosw toe6_protosw;
static struct pr_usrreqs toe6_usrreqs;
@ -263,6 +265,15 @@ offload_socket(struct socket *so, struct toepcb *toep)
mtx_unlock(&td->toep_list_lock);
}
void
restore_so_proto(struct socket *so, bool v6)
{
if (v6)
so->so_proto = tcp6_protosw;
else
so->so_proto = tcp_protosw;
}
/* This is _not_ the normal way to "unoffload" a socket. */
void
undo_offload_socket(struct socket *so)
@ -282,6 +293,7 @@ undo_offload_socket(struct socket *so)
sb = &so->so_rcv;
SOCKBUF_LOCK(sb);
sb->sb_flags &= ~SB_NOCOALESCE;
restore_so_proto(so, inp->inp_vflag & INP_IPV6);
SOCKBUF_UNLOCK(sb);
tp->tod = NULL;
@ -1837,8 +1849,6 @@ t4_ctloutput_tom(struct socket *so, struct sockopt *sopt)
static int
t4_tom_mod_load(void)
{
struct protosw *tcp_protosw, *tcp6_protosw;
/* CPL handlers */
t4_register_cpl_handler(CPL_GET_TCB_RPL, do_get_tcb_rpl);
t4_register_shared_cpl_handler(CPL_L2T_WRITE_RPL, do_l2t_write_rpl2,

View File

@ -352,6 +352,7 @@ int init_toepcb(struct vi_info *, struct toepcb *);
struct toepcb *hold_toepcb(struct toepcb *);
void free_toepcb(struct toepcb *);
void offload_socket(struct socket *, struct toepcb *);
void restore_so_proto(struct socket *, bool);
void undo_offload_socket(struct socket *);
void final_cpl_received(struct toepcb *);
void insert_tid(struct adapter *, int, void *, int);