Changeset View
Changeset View
Standalone View
Standalone View
head/sys/netinet/tcp_output.c
Show First 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | |||||
#include <netinet/in_pcb.h> | #include <netinet/in_pcb.h> | ||||
#include <netinet/ip_var.h> | #include <netinet/ip_var.h> | ||||
#include <netinet/ip_options.h> | #include <netinet/ip_options.h> | ||||
#ifdef INET6 | #ifdef INET6 | ||||
#include <netinet6/in6_pcb.h> | #include <netinet6/in6_pcb.h> | ||||
#include <netinet/ip6.h> | #include <netinet/ip6.h> | ||||
#include <netinet6/ip6_var.h> | #include <netinet6/ip6_var.h> | ||||
#endif | #endif | ||||
#ifdef TCP_RFC7413 | |||||
#include <netinet/tcp_fastopen.h> | |||||
#endif | |||||
#include <netinet/tcp.h> | #include <netinet/tcp.h> | ||||
#define TCPOUTFLAGS | #define TCPOUTFLAGS | ||||
#include <netinet/tcp_fsm.h> | #include <netinet/tcp_fsm.h> | ||||
#include <netinet/tcp_seq.h> | #include <netinet/tcp_seq.h> | ||||
#include <netinet/tcp_timer.h> | #include <netinet/tcp_timer.h> | ||||
#include <netinet/tcp_var.h> | #include <netinet/tcp_var.h> | ||||
#include <netinet/tcpip.h> | #include <netinet/tcpip.h> | ||||
#include <netinet/cc/cc.h> | #include <netinet/cc/cc.h> | ||||
#ifdef TCP_RFC7413 | |||||
#include <netinet/tcp_fastopen.h> | |||||
#endif | |||||
#ifdef TCPPCAP | #ifdef TCPPCAP | ||||
#include <netinet/tcp_pcap.h> | #include <netinet/tcp_pcap.h> | ||||
#endif | #endif | ||||
#ifdef TCPDEBUG | #ifdef TCPDEBUG | ||||
#include <netinet/tcp_debug.h> | #include <netinet/tcp_debug.h> | ||||
#endif | #endif | ||||
#ifdef TCP_OFFLOAD | #ifdef TCP_OFFLOAD | ||||
#include <netinet/tcp_offload.h> | #include <netinet/tcp_offload.h> | ||||
▲ Show 20 Lines • Show All 114 Lines • ▼ Show 20 Lines | |||||
#if defined(IPSEC) || defined(IPSEC_SUPPORT) | #if defined(IPSEC) || defined(IPSEC_SUPPORT) | ||||
unsigned ipsec_optlen = 0; | unsigned ipsec_optlen = 0; | ||||
#endif | #endif | ||||
int idle, sendalot; | int idle, sendalot; | ||||
int sack_rxmit, sack_bytes_rxmt; | int sack_rxmit, sack_bytes_rxmt; | ||||
struct sackhole *p; | struct sackhole *p; | ||||
int tso, mtu; | int tso, mtu; | ||||
struct tcpopt to; | struct tcpopt to; | ||||
#ifdef TCP_RFC7413 | |||||
unsigned int wanted_cookie = 0; | |||||
unsigned int dont_sendalot = 0; | |||||
#endif | |||||
#if 0 | #if 0 | ||||
int maxburst = TCP_MAXBURST; | int maxburst = TCP_MAXBURST; | ||||
#endif | #endif | ||||
#ifdef INET6 | #ifdef INET6 | ||||
struct ip6_hdr *ip6 = NULL; | struct ip6_hdr *ip6 = NULL; | ||||
int isipv6; | int isipv6; | ||||
isipv6 = (tp->t_inpcb->inp_vflag & INP_IPV6) != 0; | isipv6 = (tp->t_inpcb->inp_vflag & INP_IPV6) != 0; | ||||
Show All 9 Lines | |||||
#ifdef TCP_RFC7413 | #ifdef TCP_RFC7413 | ||||
/* | /* | ||||
* For TFO connections in SYN_RECEIVED, only allow the initial | * For TFO connections in SYN_RECEIVED, only allow the initial | ||||
* SYN|ACK and those sent by the retransmit timer. | * SYN|ACK and those sent by the retransmit timer. | ||||
*/ | */ | ||||
if (IS_FASTOPEN(tp->t_flags) && | if (IS_FASTOPEN(tp->t_flags) && | ||||
(tp->t_state == TCPS_SYN_RECEIVED) && | (tp->t_state == TCPS_SYN_RECEIVED) && | ||||
SEQ_GT(tp->snd_max, tp->snd_una) && /* initial SYN|ACK sent */ | SEQ_GT(tp->snd_max, tp->snd_una) && /* initial SYN|ACK sent */ | ||||
(tp->snd_nxt != tp->snd_una)) /* not a retransmit */ | (tp->snd_nxt != tp->snd_una)) /* not a retransmit */ | ||||
return (0); | return (0); | ||||
#endif | #endif | ||||
/* | /* | ||||
* Determine length of data that should be transmitted, | * Determine length of data that should be transmitted, | ||||
* and flags that will be used. | * and flags that will be used. | ||||
* If there is some data or critical controls (SYN, RST) | * If there is some data or critical controls (SYN, RST) | ||||
* to send, then transmit; otherwise, investigate further. | * to send, then transmit; otherwise, investigate further. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 195 Lines • ▼ Show 20 Lines | #endif | ||||
*/ | */ | ||||
if ((flags & TH_SYN) && (tp->t_flags & TF_NOOPT)) { | if ((flags & TH_SYN) && (tp->t_flags & TF_NOOPT)) { | ||||
len = 0; | len = 0; | ||||
flags &= ~TH_FIN; | flags &= ~TH_FIN; | ||||
} | } | ||||
#ifdef TCP_RFC7413 | #ifdef TCP_RFC7413 | ||||
/* | /* | ||||
* When retransmitting SYN|ACK on a passively-created TFO socket, | * On TFO sockets, ensure no data is sent in the following cases: | ||||
* don't include data, as the presence of data may have caused the | * | ||||
* original SYN|ACK to have been dropped by a middlebox. | * - When retransmitting SYN|ACK on a passively-created socket | ||||
* | |||||
* - When retransmitting SYN on an actively created socket | |||||
* | |||||
* - When sending a zero-length cookie (cookie request) on an | |||||
* actively created socket | |||||
* | |||||
* - When the socket is in the CLOSED state (RST is being sent) | |||||
*/ | */ | ||||
if (IS_FASTOPEN(tp->t_flags) && | if (IS_FASTOPEN(tp->t_flags) && | ||||
(((tp->t_state == TCPS_SYN_RECEIVED) && (tp->t_rxtshift > 0)) || | (((flags & TH_SYN) && (tp->t_rxtshift > 0)) || | ||||
((tp->t_state == TCPS_SYN_SENT) && | |||||
(tp->t_tfo_client_cookie_len == 0)) || | |||||
(flags & TH_RST))) | (flags & TH_RST))) | ||||
len = 0; | len = 0; | ||||
#endif | #endif | ||||
if (len <= 0) { | if (len <= 0) { | ||||
/* | /* | ||||
* If FIN has been sent but not acked, | * If FIN has been sent but not acked, | ||||
* but we haven't been called to retransmit, | * but we haven't been called to retransmit, | ||||
* len will be < 0. Otherwise, window shrank | * len will be < 0. Otherwise, window shrank | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | else | ||||
ipoptlen = 0; | ipoptlen = 0; | ||||
#if defined(IPSEC) || defined(IPSEC_SUPPORT) | #if defined(IPSEC) || defined(IPSEC_SUPPORT) | ||||
ipoptlen += ipsec_optlen; | ipoptlen += ipsec_optlen; | ||||
#endif | #endif | ||||
if ((tp->t_flags & TF_TSO) && V_tcp_do_tso && len > tp->t_maxseg && | if ((tp->t_flags & TF_TSO) && V_tcp_do_tso && len > tp->t_maxseg && | ||||
((tp->t_flags & TF_SIGNATURE) == 0) && | ((tp->t_flags & TF_SIGNATURE) == 0) && | ||||
tp->rcv_numsacks == 0 && sack_rxmit == 0 && | tp->rcv_numsacks == 0 && sack_rxmit == 0 && | ||||
ipoptlen == 0) | ipoptlen == 0 && !(flags & TH_SYN)) | ||||
tso = 1; | tso = 1; | ||||
if (sack_rxmit) { | if (sack_rxmit) { | ||||
if (SEQ_LT(p->rxmit + len, tp->snd_una + sbused(&so->so_snd))) | if (SEQ_LT(p->rxmit + len, tp->snd_una + sbused(&so->so_snd))) | ||||
flags &= ~TH_FIN; | flags &= ~TH_FIN; | ||||
} else { | } else { | ||||
if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + | if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + | ||||
sbused(&so->so_snd))) | sbused(&so->so_snd))) | ||||
▲ Show 20 Lines • Show All 205 Lines • ▼ Show 20 Lines | #endif | ||||
if ((tp->t_flags & TF_NOOPT) == 0) { | if ((tp->t_flags & TF_NOOPT) == 0) { | ||||
/* Maximum segment size. */ | /* Maximum segment size. */ | ||||
if (flags & TH_SYN) { | if (flags & TH_SYN) { | ||||
tp->snd_nxt = tp->iss; | tp->snd_nxt = tp->iss; | ||||
to.to_mss = tcp_mssopt(&tp->t_inpcb->inp_inc); | to.to_mss = tcp_mssopt(&tp->t_inpcb->inp_inc); | ||||
to.to_flags |= TOF_MSS; | to.to_flags |= TOF_MSS; | ||||
#ifdef TCP_RFC7413 | #ifdef TCP_RFC7413 | ||||
/* | /* | ||||
* Only include the TFO option on the first | * On SYN or SYN|ACK transmits on TFO connections, | ||||
* transmission of the SYN|ACK on a | * only include the TFO option if it is not a | ||||
* passively-created TFO socket, as the presence of | * retransmit, as the presence of the TFO option may | ||||
* the TFO option may have caused the original | * have caused the original SYN or SYN|ACK to have | ||||
* SYN|ACK to have been dropped by a middlebox. | * been dropped by a middlebox. | ||||
*/ | */ | ||||
if (IS_FASTOPEN(tp->t_flags) && | if (IS_FASTOPEN(tp->t_flags) && | ||||
(tp->t_state == TCPS_SYN_RECEIVED) && | |||||
(tp->t_rxtshift == 0)) { | (tp->t_rxtshift == 0)) { | ||||
if (tp->t_state == TCPS_SYN_RECEIVED) { | |||||
to.to_tfo_len = TCP_FASTOPEN_COOKIE_LEN; | to.to_tfo_len = TCP_FASTOPEN_COOKIE_LEN; | ||||
to.to_tfo_cookie = (u_char *)&tp->t_tfo_cookie; | to.to_tfo_cookie = | ||||
(u_int8_t *)&tp->t_tfo_cookie.server; | |||||
to.to_flags |= TOF_FASTOPEN; | to.to_flags |= TOF_FASTOPEN; | ||||
wanted_cookie = 1; | |||||
} else if (tp->t_state == TCPS_SYN_SENT) { | |||||
to.to_tfo_len = | |||||
tp->t_tfo_client_cookie_len; | |||||
to.to_tfo_cookie = | |||||
tp->t_tfo_cookie.client; | |||||
to.to_flags |= TOF_FASTOPEN; | |||||
wanted_cookie = 1; | |||||
/* | |||||
* If we wind up having more data to | |||||
* send with the SYN than can fit in | |||||
* one segment, don't send any more | |||||
* until the SYN|ACK comes back from | |||||
* the other end. | |||||
*/ | |||||
dont_sendalot = 1; | |||||
} | } | ||||
} | |||||
#endif | #endif | ||||
} | } | ||||
/* Window scaling. */ | /* Window scaling. */ | ||||
if ((flags & TH_SYN) && (tp->t_flags & TF_REQ_SCALE)) { | if ((flags & TH_SYN) && (tp->t_flags & TF_REQ_SCALE)) { | ||||
to.to_wscale = tp->request_r_scale; | to.to_wscale = tp->request_r_scale; | ||||
to.to_flags |= TOF_SCALE; | to.to_flags |= TOF_SCALE; | ||||
} | } | ||||
/* Timestamps. */ | /* Timestamps. */ | ||||
Show All 28 Lines | #if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) | ||||
* account the size needed to set this TCP option. | * account the size needed to set this TCP option. | ||||
*/ | */ | ||||
if (tp->t_flags & TF_SIGNATURE) | if (tp->t_flags & TF_SIGNATURE) | ||||
to.to_flags |= TOF_SIGNATURE; | to.to_flags |= TOF_SIGNATURE; | ||||
#endif /* TCP_SIGNATURE */ | #endif /* TCP_SIGNATURE */ | ||||
/* Processing the options. */ | /* Processing the options. */ | ||||
hdrlen += optlen = tcp_addoptions(&to, opt); | hdrlen += optlen = tcp_addoptions(&to, opt); | ||||
#ifdef TCP_RFC7413 | |||||
/* | |||||
* If we wanted a TFO option to be added, but it was unable | |||||
* to fit, ensure no data is sent. | |||||
*/ | |||||
if (IS_FASTOPEN(tp->t_flags) && wanted_cookie && | |||||
!(to.to_flags & TOF_FASTOPEN)) | |||||
len = 0; | |||||
#endif | |||||
} | } | ||||
/* | /* | ||||
* Adjust data length if insertion of options will | * Adjust data length if insertion of options will | ||||
* bump the packet length beyond the t_maxseg length. | * bump the packet length beyond the t_maxseg length. | ||||
* Clear the FIN bit because we cut off the tail of | * Clear the FIN bit because we cut off the tail of | ||||
* the segment. | * the segment. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 128 Lines • ▼ Show 20 Lines | if (tso) { | ||||
* last segment. | * last segment. | ||||
*/ | */ | ||||
if (tp->t_flags & TF_NEEDFIN) | if (tp->t_flags & TF_NEEDFIN) | ||||
sendalot = 1; | sendalot = 1; | ||||
} else { | } else { | ||||
len = tp->t_maxseg - optlen - ipoptlen; | len = tp->t_maxseg - optlen - ipoptlen; | ||||
sendalot = 1; | sendalot = 1; | ||||
#ifdef TCP_RFC7413 | |||||
if (dont_sendalot) | |||||
sendalot = 0; | |||||
#endif | |||||
} | } | ||||
} else | } else | ||||
tso = 0; | tso = 0; | ||||
KASSERT(len + hdrlen + ipoptlen <= IP_MAXPACKET, | KASSERT(len + hdrlen + ipoptlen <= IP_MAXPACKET, | ||||
("%s: len > IP_MAXPACKET", __func__)); | ("%s: len > IP_MAXPACKET", __func__)); | ||||
/*#ifdef DIAGNOSTIC*/ | /*#ifdef DIAGNOSTIC*/ | ||||
▲ Show 20 Lines • Show All 794 Lines • ▼ Show 20 Lines | case TOF_SACK: | ||||
} | } | ||||
#ifdef TCP_RFC7413 | #ifdef TCP_RFC7413 | ||||
case TOF_FASTOPEN: | case TOF_FASTOPEN: | ||||
{ | { | ||||
int total_len; | int total_len; | ||||
/* XXX is there any point to aligning this option? */ | /* XXX is there any point to aligning this option? */ | ||||
total_len = TCPOLEN_FAST_OPEN_EMPTY + to->to_tfo_len; | total_len = TCPOLEN_FAST_OPEN_EMPTY + to->to_tfo_len; | ||||
if (TCP_MAXOLEN - optlen < total_len) | if (TCP_MAXOLEN - optlen < total_len) { | ||||
to->to_flags &= ~TOF_FASTOPEN; | |||||
continue; | continue; | ||||
} | |||||
*optp++ = TCPOPT_FAST_OPEN; | *optp++ = TCPOPT_FAST_OPEN; | ||||
*optp++ = total_len; | *optp++ = total_len; | ||||
if (to->to_tfo_len > 0) { | if (to->to_tfo_len > 0) { | ||||
bcopy(to->to_tfo_cookie, optp, to->to_tfo_len); | bcopy(to->to_tfo_cookie, optp, to->to_tfo_len); | ||||
optp += to->to_tfo_len; | optp += to->to_tfo_len; | ||||
} | } | ||||
optlen += total_len; | optlen += total_len; | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 86 Lines • Show Last 20 Lines |