tcp_hpts: use queue(9) STAILQ for the input queue
Reviewed by: rrs Differential Revision: https://reviews.freebsd.org/D39574
This commit is contained in:
parent
e7e621f94d
commit
a540cdca31
@ -92,9 +92,8 @@ __FBSDID("$FreeBSD$");
|
|||||||
*
|
*
|
||||||
* There is a common functions within the rack_bbr_common code
|
* There is a common functions within the rack_bbr_common code
|
||||||
* version i.e. ctf_do_queued_segments(). This function
|
* version i.e. ctf_do_queued_segments(). This function
|
||||||
* knows how to take the input queue of packets from
|
* knows how to take the input queue of packets from tp->t_inqueue
|
||||||
* tp->t_in_pkts and process them digging out
|
* and process them digging out all the arguments, calling any bpf tap and
|
||||||
* all the arguments, calling any bpf tap and
|
|
||||||
* calling into tfb_do_segment_nounlock(). The common
|
* calling into tfb_do_segment_nounlock(). The common
|
||||||
* function (ctf_do_queued_segments()) requires that
|
* function (ctf_do_queued_segments()) requires that
|
||||||
* you have defined the tfb_do_segment_nounlock() as
|
* you have defined the tfb_do_segment_nounlock() as
|
||||||
@ -1331,7 +1330,8 @@ tcp_hptsi(struct tcp_hpts_entry *hpts, int from_callout)
|
|||||||
kern_prefetch(tp->t_fb_ptr, &did_prefetch);
|
kern_prefetch(tp->t_fb_ptr, &did_prefetch);
|
||||||
did_prefetch = 1;
|
did_prefetch = 1;
|
||||||
}
|
}
|
||||||
if ((inp->inp_flags2 & INP_SUPPORTS_MBUFQ) && tp->t_in_pkt) {
|
if ((inp->inp_flags2 & INP_SUPPORTS_MBUFQ) &&
|
||||||
|
!STAILQ_EMPTY(&tp->t_inqueue)) {
|
||||||
error = (*tp->t_fb->tfb_do_queued_segments)(tp, 0);
|
error = (*tp->t_fb->tfb_do_queued_segments)(tp, 0);
|
||||||
if (error) {
|
if (error) {
|
||||||
/* The input killed the connection */
|
/* The input killed the connection */
|
||||||
|
@ -1179,18 +1179,14 @@ tcp_lro_condense(struct lro_ctrl *lc, struct lro_entry *le)
|
|||||||
|
|
||||||
#ifdef TCPHPTS
|
#ifdef TCPHPTS
|
||||||
static void
|
static void
|
||||||
tcp_queue_pkts(struct inpcb *inp, struct tcpcb *tp, struct lro_entry *le)
|
tcp_queue_pkts(struct tcpcb *tp, struct lro_entry *le)
|
||||||
{
|
{
|
||||||
INP_WLOCK_ASSERT(inp);
|
|
||||||
if (tp->t_in_pkt == NULL) {
|
INP_WLOCK_ASSERT(tptoinpcb(tp));
|
||||||
/* Nothing yet there */
|
|
||||||
tp->t_in_pkt = le->m_head;
|
STAILQ_HEAD(, mbuf) q = { le->m_head,
|
||||||
tp->t_tail_pkt = le->m_last_mbuf;
|
&STAILQ_NEXT(le->m_last_mbuf, m_stailqpkt) };
|
||||||
} else {
|
STAILQ_CONCAT(&tp->t_inqueue, &q);
|
||||||
/* Already some there */
|
|
||||||
tp->t_tail_pkt->m_nextpkt = le->m_head;
|
|
||||||
tp->t_tail_pkt = le->m_last_mbuf;
|
|
||||||
}
|
|
||||||
le->m_head = NULL;
|
le->m_head = NULL;
|
||||||
le->m_last_mbuf = NULL;
|
le->m_last_mbuf = NULL;
|
||||||
}
|
}
|
||||||
@ -1221,7 +1217,7 @@ tcp_lro_get_last_if_ackcmp(struct lro_ctrl *lc, struct lro_entry *le,
|
|||||||
|
|
||||||
/* Look at the last mbuf if any in queue */
|
/* Look at the last mbuf if any in queue */
|
||||||
if (can_append_old_cmp) {
|
if (can_append_old_cmp) {
|
||||||
m = tp->t_tail_pkt;
|
m = STAILQ_LAST(&tp->t_inqueue, mbuf, m_stailqpkt);
|
||||||
if (m != NULL && (m->m_flags & M_ACKCMP) != 0) {
|
if (m != NULL && (m->m_flags & M_ACKCMP) != 0) {
|
||||||
if (M_TRAILINGSPACE(m) >= sizeof(struct tcp_ackent)) {
|
if (M_TRAILINGSPACE(m) >= sizeof(struct tcp_ackent)) {
|
||||||
tcp_lro_log(tp, lc, le, NULL, 23, 0, 0, 0, 0);
|
tcp_lro_log(tp, lc, le, NULL, 23, 0, 0, 0, 0);
|
||||||
@ -1451,7 +1447,7 @@ tcp_lro_flush_tcphpts(struct lro_ctrl *lc, struct lro_entry *le)
|
|||||||
if (le->m_head != NULL) {
|
if (le->m_head != NULL) {
|
||||||
counter_u64_add(tcp_inp_lro_direct_queue, 1);
|
counter_u64_add(tcp_inp_lro_direct_queue, 1);
|
||||||
tcp_lro_log(tp, lc, le, NULL, 22, 1, inp->inp_flags2, 0, 1);
|
tcp_lro_log(tp, lc, le, NULL, 22, 1, inp->inp_flags2, 0, 1);
|
||||||
tcp_queue_pkts(inp, tp, le);
|
tcp_queue_pkts(tp, le);
|
||||||
}
|
}
|
||||||
if (should_wake) {
|
if (should_wake) {
|
||||||
/* Wakeup */
|
/* Wakeup */
|
||||||
|
@ -11600,7 +11600,7 @@ bbr_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
|
|||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
/* First lets see if we have old packets */
|
/* First lets see if we have old packets */
|
||||||
if (tp->t_in_pkt) {
|
if (!STAILQ_EMPTY(&tp->t_inqueue)) {
|
||||||
if (ctf_do_queued_segments(tp, 1)) {
|
if (ctf_do_queued_segments(tp, 1)) {
|
||||||
m_freem(m);
|
m_freem(m);
|
||||||
return;
|
return;
|
||||||
|
@ -17069,7 +17069,7 @@ rack_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
|
|||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
|
||||||
/* First lets see if we have old packets */
|
/* First lets see if we have old packets */
|
||||||
if (tp->t_in_pkt) {
|
if (!STAILQ_EMPTY(&tp->t_inqueue)) {
|
||||||
if (ctf_do_queued_segments(tp, 1)) {
|
if (ctf_do_queued_segments(tp, 1)) {
|
||||||
m_freem(m);
|
m_freem(m);
|
||||||
return;
|
return;
|
||||||
|
@ -493,10 +493,8 @@ ctf_do_queued_segments(struct tcpcb *tp, int have_pkt)
|
|||||||
struct mbuf *m;
|
struct mbuf *m;
|
||||||
|
|
||||||
/* First lets see if we have old packets */
|
/* First lets see if we have old packets */
|
||||||
if (tp->t_in_pkt) {
|
if ((m = STAILQ_FIRST(&tp->t_inqueue)) != NULL) {
|
||||||
m = tp->t_in_pkt;
|
STAILQ_INIT(&tp->t_inqueue);
|
||||||
tp->t_in_pkt = NULL;
|
|
||||||
tp->t_tail_pkt = NULL;
|
|
||||||
if (ctf_process_inbound_raw(tp, m, have_pkt)) {
|
if (ctf_process_inbound_raw(tp, m, have_pkt)) {
|
||||||
/* We lost the tcpcb (maybe a RST came in)? */
|
/* We lost the tcpcb (maybe a RST came in)? */
|
||||||
return(1);
|
return(1);
|
||||||
|
@ -2262,6 +2262,7 @@ tcp_newtcpcb(struct inpcb *inp)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
TAILQ_INIT(&tp->t_segq);
|
TAILQ_INIT(&tp->t_segq);
|
||||||
|
STAILQ_INIT(&tp->t_inqueue);
|
||||||
tp->t_maxseg =
|
tp->t_maxseg =
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
isipv6 ? V_tcp_v6mssdflt :
|
isipv6 ? V_tcp_v6mssdflt :
|
||||||
@ -2437,8 +2438,10 @@ tcp_discardcb(struct tcpcb *tp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TCPSTATES_DEC(tp->t_state);
|
TCPSTATES_DEC(tp->t_state);
|
||||||
|
|
||||||
if (tp->t_fb->tfb_tcp_fb_fini)
|
if (tp->t_fb->tfb_tcp_fb_fini)
|
||||||
(*tp->t_fb->tfb_tcp_fb_fini)(tp, 1);
|
(*tp->t_fb->tfb_tcp_fb_fini)(tp, 1);
|
||||||
|
MPASS(STAILQ_EMPTY(&tp->t_inqueue));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we got enough samples through the srtt filter,
|
* If we got enough samples through the srtt filter,
|
||||||
@ -4242,7 +4245,8 @@ tcp_handle_orphaned_packets(struct tcpcb *tp)
|
|||||||
|
|
||||||
if (tptoinpcb(tp)->inp_flags2 & INP_MBUF_L_ACKS)
|
if (tptoinpcb(tp)->inp_flags2 & INP_MBUF_L_ACKS)
|
||||||
return;
|
return;
|
||||||
if ((tptoinpcb(tp)->inp_flags2 & INP_SUPPORTS_MBUFQ) == 0) {
|
if ((tptoinpcb(tp)->inp_flags2 & INP_SUPPORTS_MBUFQ) == 0 &&
|
||||||
|
!STAILQ_EMPTY(&tp->t_inqueue)) {
|
||||||
/*
|
/*
|
||||||
* It is unsafe to process the packets since a
|
* It is unsafe to process the packets since a
|
||||||
* reset may be lurking in them (its rare but it
|
* reset may be lurking in them (its rare but it
|
||||||
@ -4253,44 +4257,27 @@ tcp_handle_orphaned_packets(struct tcpcb *tp)
|
|||||||
* This new stack does not do any fancy LRO features
|
* This new stack does not do any fancy LRO features
|
||||||
* so all we can do is toss the packets.
|
* so all we can do is toss the packets.
|
||||||
*/
|
*/
|
||||||
m = tp->t_in_pkt;
|
m = STAILQ_FIRST(&tp->t_inqueue);
|
||||||
tp->t_in_pkt = NULL;
|
STAILQ_INIT(&tp->t_inqueue);
|
||||||
tp->t_tail_pkt = NULL;
|
STAILQ_FOREACH_FROM_SAFE(m, &tp->t_inqueue, m_stailqpkt, save)
|
||||||
while (m) {
|
|
||||||
save = m->m_nextpkt;
|
|
||||||
m->m_nextpkt = NULL;
|
|
||||||
m_freem(m);
|
m_freem(m);
|
||||||
m = save;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Here we have a stack that does mbuf queuing but
|
* Here we have a stack that does mbuf queuing but
|
||||||
* does not support compressed ack's. We must
|
* does not support compressed ack's. We must
|
||||||
* walk all the mbufs and discard any compressed acks.
|
* walk all the mbufs and discard any compressed acks.
|
||||||
*/
|
*/
|
||||||
m = tp->t_in_pkt;
|
STAILQ_FOREACH_SAFE(m, &tp->t_inqueue, m_stailqpkt, save) {
|
||||||
prev = NULL;
|
|
||||||
while (m) {
|
|
||||||
if (m->m_flags & M_ACKCMP) {
|
if (m->m_flags & M_ACKCMP) {
|
||||||
/* We must toss this packet */
|
if (m == STAILQ_FIRST(&tp->t_inqueue))
|
||||||
if (tp->t_tail_pkt == m)
|
STAILQ_REMOVE_HEAD(&tp->t_inqueue,
|
||||||
tp->t_tail_pkt = prev;
|
m_stailqpkt);
|
||||||
if (prev)
|
|
||||||
prev->m_nextpkt = m->m_nextpkt;
|
|
||||||
else
|
else
|
||||||
tp->t_in_pkt = m->m_nextpkt;
|
STAILQ_REMOVE_AFTER(&tp->t_inqueue,
|
||||||
m->m_nextpkt = NULL;
|
prev, m_stailqpkt);
|
||||||
m_freem(m);
|
m_freem(m);
|
||||||
/* move forward */
|
} else
|
||||||
if (prev)
|
|
||||||
m = prev->m_nextpkt;
|
|
||||||
else
|
|
||||||
m = tp->t_in_pkt;
|
|
||||||
} else {
|
|
||||||
/* this one is ok */
|
|
||||||
prev = m;
|
prev = m;
|
||||||
m = m->m_nextpkt;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -355,8 +355,7 @@ struct tcpcb {
|
|||||||
int t_segqlen; /* segment reassembly queue length */
|
int t_segqlen; /* segment reassembly queue length */
|
||||||
uint32_t t_segqmbuflen; /* total reassembly queue byte length */
|
uint32_t t_segqmbuflen; /* total reassembly queue byte length */
|
||||||
struct tsegqe_head t_segq; /* segment reassembly queue */
|
struct tsegqe_head t_segq; /* segment reassembly queue */
|
||||||
struct mbuf *t_in_pkt;
|
STAILQ_HEAD(, mbuf) t_inqueue; /* HPTS input queue */
|
||||||
struct mbuf *t_tail_pkt;
|
|
||||||
uint32_t snd_ssthresh; /* snd_cwnd size threshold for
|
uint32_t snd_ssthresh; /* snd_cwnd size threshold for
|
||||||
* for slow start exponential to
|
* for slow start exponential to
|
||||||
* linear switch
|
* linear switch
|
||||||
|
Loading…
Reference in New Issue
Block a user