Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_lro.c
Show First 20 Lines • Show All 915 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->flags = (th->th_x2 << 8) | th->th_flags; | le->flags = tcp_get_flags(th); | ||||
le->needs_merge = 0; | 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 | ||||
▲ Show 20 Lines • Show All 95 Lines • ▼ Show 20 Lines | if (tcp_opt_len != 0 && __predict_false(tcp_opt_len != TCPOLEN_TSTAMP_APPA || | ||||
/* | /* | ||||
* Its not the timestamp. We can't | * Its not the timestamp. We can't | ||||
* use this guy as the head. | * use this guy as the head. | ||||
*/ | */ | ||||
le->m_head->m_nextpkt = m->m_nextpkt; | le->m_head->m_nextpkt = m->m_nextpkt; | ||||
tcp_push_and_replace(lc, le, m); | tcp_push_and_replace(lc, le, m); | ||||
goto again; | goto again; | ||||
} | } | ||||
if ((((th->th_x2 << 8) | th->th_flags) & ~(TH_ACK | TH_PUSH)) != 0) { | if ((tcp_get_flags(th) & ~(TH_ACK | TH_PUSH)) != 0) { | ||||
/* | /* | ||||
* Make sure that previously seen segments/ACKs are delivered | * Make sure that previously seen segments/ACKs are delivered | ||||
* before this segment, e.g. FIN. | * before this segment, e.g. FIN. | ||||
*/ | */ | ||||
le->m_head->m_nextpkt = m->m_nextpkt; | le->m_head->m_nextpkt = m->m_nextpkt; | ||||
tcp_push_and_replace(lc, le, m); | tcp_push_and_replace(lc, le, m); | ||||
goto again; | goto again; | ||||
} | } | ||||
Show All 27 Lines | if (tcp_opt_len != 0 && | ||||
* start all over after flushing the | * start all over after flushing the | ||||
* current le. We will go up to the beginning | * current le. We will go up to the beginning | ||||
* and flush it (calling the replace again possibly | * and flush it (calling the replace again possibly | ||||
* or just returning). | * or just returning). | ||||
*/ | */ | ||||
tcp_push_and_replace(lc, le, m); | tcp_push_and_replace(lc, le, m); | ||||
goto again; | goto again; | ||||
} | } | ||||
if ((((th->th_x2 << 8) | th->th_flags) & ~(TH_ACK | TH_PUSH)) != 0) { | if ((tcp_get_flags(th) & ~(TH_ACK | TH_PUSH)) != 0) { | ||||
tcp_push_and_replace(lc, le, m); | tcp_push_and_replace(lc, le, m); | ||||
goto again; | goto again; | ||||
} | } | ||||
if (tcp_opt_len != 0) { | if (tcp_opt_len != 0) { | ||||
uint32_t tsval = ntohl(*(ts_ptr + 1)); | uint32_t tsval = ntohl(*(ts_ptr + 1)); | ||||
/* Make sure timestamp values are increasing. */ | /* Make sure timestamp values are increasing. */ | ||||
if (TSTMP_GT(le->tsval, tsval)) { | if (TSTMP_GT(le->tsval, tsval)) { | ||||
tcp_push_and_replace(lc, le, m); | tcp_push_and_replace(lc, le, m); | ||||
goto again; | goto again; | ||||
} | } | ||||
le->tsval = tsval; | le->tsval = tsval; | ||||
le->tsecr = *(ts_ptr + 2); | le->tsecr = *(ts_ptr + 2); | ||||
} | } | ||||
/* Try to append the new segment. */ | /* Try to append the new segment. */ | ||||
if (__predict_false(ntohl(th->th_seq) != le->next_seq || | if (__predict_false(ntohl(th->th_seq) != le->next_seq || | ||||
((th->th_flags & TH_ACK) != | ((tcp_get_flags(th) & TH_ACK) != | ||||
(le->flags & TH_ACK)) || | (le->flags & TH_ACK)) || | ||||
(tcp_data_len == 0 && | (tcp_data_len == 0 && | ||||
le->ack_seq == th->th_ack && | le->ack_seq == th->th_ack && | ||||
le->window == th->th_win))) { | le->window == th->th_win))) { | ||||
/* Out of order packet, non-ACK + ACK or dup ACK. */ | /* Out of order packet, non-ACK + ACK or dup ACK. */ | ||||
tcp_push_and_replace(lc, le, m); | tcp_push_and_replace(lc, le, m); | ||||
goto again; | goto again; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 155 Lines • ▼ Show 20 Lines | case (sizeof(*th)): | ||||
break; | break; | ||||
default: | default: | ||||
*ppts = NULL; | *ppts = NULL; | ||||
*other_opts = true; | *other_opts = true; | ||||
ret = false; | ret = false; | ||||
break; | break; | ||||
} | } | ||||
/* For ACKCMP we only accept ACK, PUSH, ECE and CWR. */ | /* For ACKCMP we only accept ACK, PUSH, ECE and CWR. */ | ||||
if ((((th->th_x2 << 8) | th->th_flags) & ~(TH_ACK | TH_PUSH | TH_ECE | TH_CWR)) != 0) | if ((tcp_get_flags(th) & ~(TH_ACK | TH_PUSH | TH_ECE | TH_CWR)) != 0) | ||||
ret = false; | ret = false; | ||||
/* If it has data on it we cannot compress it */ | /* If it has data on it we cannot compress it */ | ||||
if (m->m_pkthdr.lro_tcp_d_len) | if (m->m_pkthdr.lro_tcp_d_len) | ||||
ret = false; | ret = false; | ||||
/* ACK flag must be set. */ | /* ACK flag must be set. */ | ||||
if (!(th->th_flags & TH_ACK)) | if (!(tcp_get_flags(th) & TH_ACK)) | ||||
ret = false; | ret = false; | ||||
return (ret); | return (ret); | ||||
} | } | ||||
static int | static int | ||||
tcp_lro_flush_tcphpts(struct lro_ctrl *lc, struct lro_entry *le) | tcp_lro_flush_tcphpts(struct lro_ctrl *lc, struct lro_entry *le) | ||||
{ | { | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
▲ Show 20 Lines • Show All 287 Lines • ▼ Show 20 Lines | build_ack_entry(struct tcp_ackent *ae, struct tcphdr *th, struct mbuf *m, | ||||
*/ | */ | ||||
ae->timestamp = m->m_pkthdr.rcv_tstmp; | ae->timestamp = m->m_pkthdr.rcv_tstmp; | ||||
if (m->m_flags & M_TSTMP_LRO) | if (m->m_flags & M_TSTMP_LRO) | ||||
ae->flags = TSTMP_LRO; | ae->flags = TSTMP_LRO; | ||||
else if (m->m_flags & M_TSTMP) | else if (m->m_flags & M_TSTMP) | ||||
ae->flags = TSTMP_HDWR; | ae->flags = TSTMP_HDWR; | ||||
ae->seq = ntohl(th->th_seq); | ae->seq = ntohl(th->th_seq); | ||||
ae->ack = ntohl(th->th_ack); | ae->ack = ntohl(th->th_ack); | ||||
ae->flags |= (th->th_x2 << 8) | th->th_flags; | ae->flags |= tcp_get_flags(th); | ||||
if (ts_ptr != NULL) { | if (ts_ptr != NULL) { | ||||
ae->ts_value = ntohl(ts_ptr[1]); | ae->ts_value = ntohl(ts_ptr[1]); | ||||
ae->ts_echo = ntohl(ts_ptr[2]); | ae->ts_echo = ntohl(ts_ptr[2]); | ||||
ae->flags |= HAS_TSTMP; | ae->flags |= HAS_TSTMP; | ||||
} | } | ||||
ae->win = ntohs(th->th_win); | ae->win = ntohs(th->th_win); | ||||
ae->codepoint = iptos; | ae->codepoint = iptos; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 238 Lines • ▼ Show 20 Lines | if ((m->m_flags & (M_TSTMP_LRO | M_TSTMP)) == 0) { | ||||
m->m_pkthdr.rcv_tstmp = bintime2ns(&lc->lro_last_queue_time); | m->m_pkthdr.rcv_tstmp = bintime2ns(&lc->lro_last_queue_time); | ||||
m->m_flags |= M_TSTMP_LRO; | m->m_flags |= M_TSTMP_LRO; | ||||
} | } | ||||
/* Get pointer to TCP header. */ | /* Get pointer to TCP header. */ | ||||
th = pa->tcp; | th = pa->tcp; | ||||
/* Don't process SYN packets. */ | /* Don't process SYN packets. */ | ||||
if (__predict_false(th->th_flags & TH_SYN)) | if (__predict_false(tcp_get_flags(th) & TH_SYN)) | ||||
return (TCP_LRO_CANNOT); | return (TCP_LRO_CANNOT); | ||||
/* Get total TCP header length and compute payload length. */ | /* Get total TCP header length and compute payload length. */ | ||||
tcp_opt_len = (th->th_off << 2); | tcp_opt_len = (th->th_off << 2); | ||||
tcp_data_len = m->m_pkthdr.len - ((uint8_t *)th - | tcp_data_len = m->m_pkthdr.len - ((uint8_t *)th - | ||||
(uint8_t *)m->m_data) - tcp_opt_len; | (uint8_t *)m->m_data) - tcp_opt_len; | ||||
tcp_opt_len -= sizeof(*th); | tcp_opt_len -= sizeof(*th); | ||||
▲ Show 20 Lines • Show All 131 Lines • Show Last 20 Lines |