Index: sys/netinet/tcp_lro.c =================================================================== --- sys/netinet/tcp_lro.c +++ sys/netinet/tcp_lro.c @@ -725,7 +725,7 @@ struct mbuf *m; struct tcphdr *th; uint16_t tcp_data_len, csum_upd; - int l; + int l, have_tstmp_opt; /* * First we must check the lead (m_head) @@ -799,9 +799,13 @@ tcp_push_and_replace(tp, lc, le, m); goto again; } - if (l != 0 && (__predict_false(l != TCPOLEN_TSTAMP_APPA) || - (*ts_ptr != ntohl(TCPOPT_NOP<<24|TCPOPT_NOP<<16| - TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)))) { + if (l && (__predict_true(l == TCPOLEN_TSTAMP_APPA) && + (*ts_ptr == ntohl(TCPOPT_NOP<<24|TCPOPT_NOP<<16| + TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)))) + have_tstmp_opt = 1; + else + have_tstmp_opt = 0; + if (l != 0 && (__predict_false(have_tstmp_opt == 0))) { /* * Maybe a sack in the new one? We need to * start all over after flushing the @@ -816,7 +820,7 @@ tcp_push_and_replace(tp, lc, le, m); goto again; } - if (l != 0) { + if (have_tstmp_opt) { uint32_t tsval = ntohl(*(ts_ptr + 1)); /* Make sure timestamp values are increasing. */ if (TSTMP_GT(le->tsval, tsval)) { @@ -996,32 +1000,7 @@ if ((tcplro_stacks_wanting_mbufq == 0) || (le->m_head->m_flags & M_VLANTAG)) goto skip_lookup; - if (le->inp == NULL) { - le->inp = inp = tcp_lro_lookup(lc, le); - if (inp && ((inp->inp_flags & (INP_DROPPED|INP_TIMEWAIT)) || - (inp->inp_flags2 & INP_FREED))) { - /* - * We can't present these to the inp since - * it will not support the stripped ethernet - * header that these have nor if a compressed - * ack is presnet. - */ - INP_WUNLOCK(inp); - lro_free_mbuf_chain(le->m_head); - goto done; - } - if ((le->flags & HAS_COMP_ENTRIES) && - ((inp->inp_flags2 & INP_MBUF_ACKCMP) == 0)) { - /* - * It swapped to off, must be a stack - * switch. We need to ditch all the packets - * and the peer will just have to retransmit. - */ - INP_WUNLOCK(inp); - lro_free_mbuf_chain(le->m_head); - goto done; - } - } else { + if (le->inp != NULL) { /* We have a reference on the inp lets lock and release it */ inp = le->inp; INP_WLOCK(inp); @@ -1510,7 +1489,7 @@ uint32_t *ts_ptr; tcp_seq seq; int error, ip_len, hdr_len, locked = 0; - uint16_t eh_type, tcp_data_len, need_flush; + uint16_t eh_type, tcp_data_len, need_flush, have_tstmp_opt; #ifdef TCPHPTS uint16_t iptos; #endif @@ -1521,12 +1500,12 @@ m->m_flags &= ~(M_ACKCMP|M_LRO_EHDRSTRP); /* We expect a contiguous header [eh, ip, tcp]. */ + nanouptime(&arrv); if ((m->m_flags & (M_TSTMP_LRO|M_TSTMP)) == 0) { /* If no hardware or arrival stamp on the packet add arrival */ - nanouptime(&arrv); m->m_pkthdr.rcv_tstmp = (arrv.tv_sec * 1000000000) + arrv.tv_nsec; m->m_flags |= M_TSTMP_LRO; - } + } eh = mtod(m, struct ether_header *); eh_type = ntohs(eh->ether_type); switch (eh_type) { @@ -1598,15 +1577,19 @@ ts_ptr = (uint32_t *)(th + 1); tcp_data_len -= hdr_len; hdr_len -= sizeof(*th); + if (hdr_len && (__predict_true(hdr_len == TCPOLEN_TSTAMP_APPA) && + (*ts_ptr == ntohl(TCPOPT_NOP<<24|TCPOPT_NOP<<16| + TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)))) + have_tstmp_opt = 1; + else + have_tstmp_opt = 0; if (th->th_flags & TH_SYN) return (TCP_LRO_CANNOT); if ((th->th_flags & ~(TH_ACK | TH_PUSH)) != 0) { need_flush = 1; } else need_flush = 0; - if (hdr_len != 0 && (__predict_false(hdr_len != TCPOLEN_TSTAMP_APPA) || - (*ts_ptr != ntohl(TCPOPT_NOP<<24|TCPOPT_NOP<<16| - TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)))) { + if (hdr_len != 0 && (__predict_false(have_tstmp_opt == 0))) { /* * We have an option besides Timestamps, maybe * it is a sack (most likely) which means we @@ -1832,7 +1815,8 @@ nm = m_getcl(M_NOWAIT, MT_DATA, (M_ACKCMP|M_PKTHDR)); else { nm = m_gethdr(M_NOWAIT, MT_DATA); - nm->m_flags |= M_ACKCMP; + if (nm) + nm->m_flags |= M_ACKCMP; } if (nm) { nm->m_pkthdr.rcvif = lc->ifp; @@ -1918,7 +1902,7 @@ le->next_seq = seq + tcp_data_len; le->ack_seq = th->th_ack; le->window = th->th_win; - if (hdr_len != 0) { + if (have_tstmp_opt) { le->timestamp = 1; le->tsval = ntohl(*(ts_ptr + 1)); le->tsecr = *(ts_ptr + 2); @@ -2013,7 +1997,8 @@ nm = m_getcl(M_NOWAIT, MT_DATA, (M_ACKCMP|M_PKTHDR)); else { nm = m_gethdr(M_NOWAIT, MT_DATA); - nm->m_flags |= M_ACKCMP; + if (nm) + nm->m_flags |= M_ACKCMP; } if (nm) { nm->m_pkthdr.rcvif = lc->ifp;