Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_lro.c
| Show First 20 Lines • Show All 814 Lines • ▼ Show 20 Lines | update_udp_header: | ||||
| /* Return delta checksum to next stage, if any. */ | /* Return delta checksum to next stage, if any. */ | ||||
| return (csum); | return (csum); | ||||
| } | } | ||||
| static void | static void | ||||
| tcp_flush_out_entry(struct lro_ctrl *lc, struct lro_entry *le) | tcp_flush_out_entry(struct lro_ctrl *lc, struct lro_entry *le) | ||||
| { | { | ||||
| /* Check if we need to recompute any checksums. */ | /* Check if we need to recompute any checksums. */ | ||||
| if (le->m_head->m_pkthdr.lro_nsegs > 1) { | if (le->needs_merge) { | ||||
| uint16_t csum; | uint16_t csum; | ||||
| switch (le->inner.data.lro_type) { | switch (le->inner.data.lro_type) { | ||||
| case LRO_TYPE_IPV4_TCP: | case LRO_TYPE_IPV4_TCP: | ||||
| csum = tcp_lro_update_checksum(&le->inner, le, | csum = tcp_lro_update_checksum(&le->inner, le, | ||||
| le->m_head->m_pkthdr.lro_tcp_d_len, | le->m_head->m_pkthdr.lro_tcp_d_len, | ||||
| le->m_head->m_pkthdr.lro_tcp_d_csum); | le->m_head->m_pkthdr.lro_tcp_d_csum); | ||||
| csum = tcp_lro_update_checksum(&le->outer, NULL, | csum = tcp_lro_update_checksum(&le->outer, NULL, | ||||
| ▲ Show 20 Lines • Show All 84 Lines • ▼ Show 20 Lines | tcp_set_entry_to_mbuf(struct lro_ctrl *lc, struct lro_entry *le, | ||||
| } | } | ||||
| tcp_data_len = m->m_pkthdr.lro_tcp_d_len; | tcp_data_len = m->m_pkthdr.lro_tcp_d_len; | ||||
| /* Pull out TCP sequence numbers and window size. */ | /* Pull out TCP sequence numbers and window size. */ | ||||
| le->next_seq = ntohl(th->th_seq) + tcp_data_len; | le->next_seq = ntohl(th->th_seq) + tcp_data_len; | ||||
| le->ack_seq = th->th_ack; | le->ack_seq = th->th_ack; | ||||
| le->window = th->th_win; | le->window = th->th_win; | ||||
| le->needs_merge = 0; | |||||
| /* Setup new data pointers. */ | /* Setup new data pointers. */ | ||||
| le->m_head = m; | le->m_head = m; | ||||
| le->m_tail = m_last(m); | le->m_tail = m_last(m); | ||||
| } | } | ||||
| static void | static void | ||||
| tcp_push_and_replace(struct lro_ctrl *lc, struct lro_entry *le, struct mbuf *m) | tcp_push_and_replace(struct lro_ctrl *lc, struct lro_entry *le, struct mbuf *m) | ||||
| Show All 25 Lines | tcp_push_and_replace(struct lro_ctrl *lc, struct lro_entry *le, struct mbuf *m) | ||||
| */ | */ | ||||
| tcp_set_entry_to_mbuf(lc, le, m, pa->tcp); | tcp_set_entry_to_mbuf(lc, le, m, pa->tcp); | ||||
| /* Restore the next list */ | /* Restore the next list */ | ||||
| m->m_nextpkt = msave; | m->m_nextpkt = msave; | ||||
| } | } | ||||
| static void | static void | ||||
| tcp_lro_mbuf_append_pkthdr(struct mbuf *m, const struct mbuf *p) | tcp_lro_mbuf_append_pkthdr(struct lro_entry *le, const struct mbuf *p) | ||||
| { | { | ||||
| struct mbuf *m; | |||||
| uint32_t csum; | uint32_t csum; | ||||
| m = le->m_head; | |||||
| if (m->m_pkthdr.lro_nsegs == 1) { | if (m->m_pkthdr.lro_nsegs == 1) { | ||||
| /* Compute relative checksum. */ | /* Compute relative checksum. */ | ||||
| csum = p->m_pkthdr.lro_tcp_d_csum; | csum = p->m_pkthdr.lro_tcp_d_csum; | ||||
| } else { | } else { | ||||
| /* Merge TCP data checksums. */ | /* Merge TCP data checksums. */ | ||||
| csum = (uint32_t)m->m_pkthdr.lro_tcp_d_csum + | csum = (uint32_t)m->m_pkthdr.lro_tcp_d_csum + | ||||
| (uint32_t)p->m_pkthdr.lro_tcp_d_csum; | (uint32_t)p->m_pkthdr.lro_tcp_d_csum; | ||||
| while (csum > 0xffff) | while (csum > 0xffff) | ||||
| csum = (csum >> 16) + (csum & 0xffff); | csum = (csum >> 16) + (csum & 0xffff); | ||||
| } | } | ||||
| /* Update various counters. */ | /* Update various counters. */ | ||||
| m->m_pkthdr.len += p->m_pkthdr.lro_tcp_d_len; | m->m_pkthdr.len += p->m_pkthdr.lro_tcp_d_len; | ||||
| m->m_pkthdr.lro_tcp_d_csum = csum; | m->m_pkthdr.lro_tcp_d_csum = csum; | ||||
| m->m_pkthdr.lro_tcp_d_len += p->m_pkthdr.lro_tcp_d_len; | m->m_pkthdr.lro_tcp_d_len += p->m_pkthdr.lro_tcp_d_len; | ||||
| m->m_pkthdr.lro_nsegs += p->m_pkthdr.lro_nsegs; | m->m_pkthdr.lro_nsegs += p->m_pkthdr.lro_nsegs; | ||||
| le->needs_merge = 1; | |||||
| } | } | ||||
| static void | static void | ||||
| tcp_lro_condense(struct lro_ctrl *lc, struct lro_entry *le) | tcp_lro_condense(struct lro_ctrl *lc, struct lro_entry *le) | ||||
| { | { | ||||
| /* | /* | ||||
| * Walk through the mbuf chain we | * Walk through the mbuf chain we | ||||
| * have on tap and compress/condense | * have on tap and compress/condense | ||||
| ▲ Show 20 Lines • Show All 102 Lines • ▼ Show 20 Lines | if (__predict_false(ntohl(th->th_seq) != le->next_seq || | ||||
| tcp_push_and_replace(lc, le, m); | tcp_push_and_replace(lc, le, m); | ||||
| goto again; | goto again; | ||||
| } | } | ||||
| if (tcp_data_len != 0 || | if (tcp_data_len != 0 || | ||||
| SEQ_GT(ntohl(th->th_ack), ntohl(le->ack_seq))) { | SEQ_GT(ntohl(th->th_ack), ntohl(le->ack_seq))) { | ||||
| le->next_seq += tcp_data_len; | le->next_seq += tcp_data_len; | ||||
| le->ack_seq = th->th_ack; | le->ack_seq = th->th_ack; | ||||
| le->window = th->th_win; | le->window = th->th_win; | ||||
| le->needs_merge = 1; | |||||
| } else if (th->th_ack == le->ack_seq) { | } else if (th->th_ack == le->ack_seq) { | ||||
| le->window = WIN_MAX(le->window, th->th_win); | if (WIN_GT(th->th_win, le->window)) { | ||||
| le->window = th->th_win; | |||||
| le->needs_merge = 1; | |||||
| } | } | ||||
| } | |||||
| if (tcp_data_len == 0) { | if (tcp_data_len == 0) { | ||||
| m_freem(m); | m_freem(m); | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* Merge TCP data checksum and length to head mbuf. */ | /* Merge TCP data checksum and length to head mbuf. */ | ||||
| tcp_lro_mbuf_append_pkthdr(le->m_head, m); | tcp_lro_mbuf_append_pkthdr(le, m); | ||||
| /* | /* | ||||
| * Adjust the mbuf so that m_data points to the first byte of | * Adjust the mbuf so that m_data points to the first byte of | ||||
| * the ULP payload. Adjust the mbuf to avoid complications and | * the ULP payload. Adjust the mbuf to avoid complications and | ||||
| * append new segment to existing mbuf chain. | * append new segment to existing mbuf chain. | ||||
| */ | */ | ||||
| m_adj(m, m->m_pkthdr.len - tcp_data_len); | m_adj(m, m->m_pkthdr.len - tcp_data_len); | ||||
| m_demote_pkthdr(m); | m_demote_pkthdr(m); | ||||
| ▲ Show 20 Lines • Show All 841 Lines • Show Last 20 Lines | |||||