|
AquilaOS documentation
How it works, and its code
|
TCP output. More...
#include <core/system.h>#include <core/arch.h>#include <core/string.h>#include <net/byteorder.h>#include <net/inet.h>#include <net/netif.h>#include <net/tcp.h>#include <aquila/errno.h>Go to the source code of this file.
Macros | |
| #define | RTO_MIN 1000000000ULL |
| #define | RTO_MAX 60000000000ULL |
| #define | RTT_GRANULARITY 2000000ULL |
| #define | DACK_DELAY 100000000ULL |
| #define | SYN_RETRIES 5 |
| #define | DATA_RETRIES 8 |
Functions | |
| static void | rexmt_timeout (void *arg) |
| Handles the retransmission timer. | |
| static uint16_t | our_mss (struct tcp_pcb *pcb) |
| Returns the most data a segment we send may carry: the interface's MTU, less the headers. | |
| uint16_t | tcp_rcv_window (struct tcp_pcb *pcb) |
| Computes the window to advertise: the room in the receive buffer. | |
| static int | segment (struct tcp_pcb *pcb, uint32_t seq, int flags, size_t off, size_t len) |
| Sends a segment with sequence number seq, carrying len bytes of the send buffer from offset off, and acknowledging rcv_nxt if flags has TH_ACK. | |
| void | tcp_rexmt_start (struct tcp_pcb *pcb) |
| Starts the retransmission timer, if it isn't running. | |
| void | tcp_send_syn (struct tcp_pcb *pcb) |
| Sends the SYN (or, in SYN_RECEIVED, the SYN and ACK), the first time or again, and starts the retransmission timer. | |
| void | tcp_send_ack (struct tcp_pcb *pcb) |
| Sends an ACK, now. | |
| void | tcp_send_keepalive (struct tcp_pcb *pcb) |
| Sends a keepalive probe: a segment one byte before what the peer has acknowledged (with no data), which the peer answers with an ACK. | |
| void | tcp_send_rst (struct tcp_pcb *pcb) |
| Sends a reset on a connection. | |
| void | tcp_reply_rst (struct netif *netif, const struct ipv4_hdr *ih, const struct tcp_hdr *th, size_t len) |
| Answers a segment that is for no connection with a reset (RFC 9293 3.10.7.1). | |
| static int | sending (struct tcp_pcb *pcb) |
| Returns whether data and the FIN may be sent in the connection's state. | |
| void | tcp_output (struct tcp_pcb *pcb) |
| Sends as much of the send buffer as the windows allow, in segments of at most mss bytes. | |
| void | tcp_rtt_update (struct tcp_pcb *pcb, uint64_t rtt) |
| Updates the round trip estimates with a new measurement, and the retransmission timeout from them (RFC 6298). | |
| static void | dack_timeout (void *arg) |
| Sends the delayed ACK, when its delay is over. | |
| void | tcp_dack (struct tcp_pcb *pcb) |
| Acknowledges a received segment: at once if it's the second one not acknowledged yet, or else after DACK_DELAY. | |
TCP output.
Segments are made from the send buffer as the windows allow: the peer's receive window and the congestion window. One timer handles both retransmission (RFC 6298) and the probes of a zero window. ACKs are delayed (RFC 1122): sent for every second segment, or after DACK_DELAY.
Definition in file tcp_output.c.
| #define DACK_DELAY 100000000ULL |
Definition at line 24 of file tcp_output.c.
Referenced by tcp_dack().
| #define DATA_RETRIES 8 |
Definition at line 27 of file tcp_output.c.
Referenced by rexmt_timeout().
| #define RTO_MAX 60000000000ULL |
Definition at line 22 of file tcp_output.c.
Referenced by rexmt_timeout(), and tcp_rtt_update().
| #define RTO_MIN 1000000000ULL |
Definition at line 21 of file tcp_output.c.
Referenced by tcp_rtt_update().
| #define RTT_GRANULARITY 2000000ULL |
Definition at line 23 of file tcp_output.c.
Referenced by tcp_rtt_update().
| #define SYN_RETRIES 5 |
Definition at line 26 of file tcp_output.c.
Referenced by rexmt_timeout().
|
static |
Sends the delayed ACK, when its delay is over.
Definition at line 333 of file tcp_output.c.
References dack_timeout(), and tcp_send_ack().
Referenced by dack_timeout(), and tcp_dack().
Returns the most data a segment we send may carry: the interface's MTU, less the headers.
Definition at line 33 of file tcp_output.c.
References ipv4_route(), netif::mtu, our_mss(), tcp_pcb::raddr, and TCP_MSS_DEFAULT.
|
static |
Handles the retransmission timer.
It probes a zero window, or retransmits from the first unacknowledged byte (backing off, and starting the congestion window over), or gives up on the connection (ETIMEDOUT) after too many tries.
Definition at line 358 of file tcp_output.c.
References tcp_pcb::cwnd, DATA_RETRIES, tcp_pcb::dupacks, tcp_pcb::in_recovery, MAX, MIN, tcp_pcb::mss, net_callout_set(), tcp_pcb::persist, tcp_pcb::retries, tcp_pcb::rexmt, rexmt_timeout(), tcp_pcb::rto, RTO_MAX, tcp_pcb::rtt_timing, segment(), SEQ_GT, tcp_pcb::snd_max, tcp_pcb::snd_nxt, tcp_pcb::snd_una, tcp_pcb::snd_wnd, tcp_pcb::sndbuf, tcp_pcb::ssthresh, tcp_pcb::state, SYN_RETRIES, tcp_drop(), tcp_output(), tcp_send_syn(), TCP_SYN_RECEIVED, TCP_SYN_SENT, and TH_ACK.
Referenced by rexmt_timeout(), tcp_output(), and tcp_rexmt_start().
Sends a segment with sequence number seq, carrying len bytes of the send buffer from offset off, and acknowledging rcv_nxt if flags has TH_ACK.
A SYN carries our MSS option. Returns 0 or a negative errno.
Definition at line 65 of file tcp_output.c.
References tcp_hdr::ack, tcp_pcb::ack_pending, callout_stop(), tcp_hdr::checksum, tcp_pcb::dack, tcp_hdr::dst, tcp_hdr::flags, htonl, htons, inet_checksum_pseudo(), IP_PROTO_TCP, ipv4_output(), ipv4_route(), tcp_pcb::laddr, netbuf::len, tcp_pcb::lport, netbuf_alloc(), netbuf_push(), tcp_hdr::off, our_mss(), tcp_pcb::raddr, tcp_pcb::rcv_adv, tcp_pcb::rcv_nxt, tcp_pcb::rport, segment(), tcp_hdr::seq, tcp_pcb::sndbuf, tcp_hdr::src, tcp_rcv_window(), TH_ACK, TH_SYN, tcp_hdr::urg, and tcp_hdr::win.
Referenced by rexmt_timeout(), segment(), tcp_output(), tcp_send_ack(), tcp_send_keepalive(), tcp_send_rst(), and tcp_send_syn().
|
static |
Returns whether data and the FIN may be sent in the connection's state.
Definition at line 225 of file tcp_output.c.
References sending(), tcp_pcb::state, TCP_CLOSE_WAIT, TCP_CLOSING, TCP_ESTABLISHED, TCP_FIN_WAIT_1, and TCP_LAST_ACK.
Referenced by sending(), and tcp_output().
| void tcp_dack | ( | struct tcp_pcb * | pcb | ) |
Acknowledges a received segment: at once if it's the second one not acknowledged yet, or else after DACK_DELAY.
| pcb | the connection |
Definition at line 344 of file tcp_output.c.
References tcp_pcb::ack_pending, tcp_pcb::dack, DACK_DELAY, dack_timeout(), net_callout_set(), callout::pending, tcp_dack(), and tcp_send_ack().
Referenced by segment_input(), and tcp_dack().
| void tcp_output | ( | struct tcp_pcb * | pcb | ) |
Sends as much of the send buffer as the windows allow, in segments of at most mss bytes.
A smaller segment goes only if it has the last of the data and nothing is unacknowledged (Nagle's algorithm, unless TCP_NODELAY), and never just because the peer's window is small (the sender's silly window avoidance). The FIN goes with the last of the data. If the peer's window is zero, the persist timer probes it.
| pcb | the connection |
Definition at line 249 of file tcp_output.c.
References arch_rtime_ns(), tcp_pcb::cwnd, tcp_pcb::fin_queued, tcp_hdr::flags, MIN, tcp_pcb::mss, net_callout_set(), tcp_pcb::nodelay, callout::pending, tcp_pcb::persist, tcp_pcb::rexmt, rexmt_timeout(), tcp_pcb::rto, tcp_pcb::rtt_seq, tcp_pcb::rtt_start, tcp_pcb::rtt_timing, segment(), sending(), tcp_hdr::seq, SEQ_GT, tcp_pcb::snd_max, tcp_pcb::snd_nxt, tcp_pcb::snd_una, tcp_pcb::snd_wnd, tcp_pcb::sndbuf, tcp_output(), tcp_rexmt_start(), TH_ACK, TH_FIN, and TH_PSH.
Referenced by ack_input(), retransmit_first(), rexmt_timeout(), segment_input(), send_fin(), socket_tcp_send(), socket_tcp_setsockopt(), and tcp_output().
Computes the window to advertise: the room in the receive buffer.
Its right edge only moves forward by at least a segment (or half the buffer), so that the peer isn't offered small windows (RFC 9293 3.8.6.2.2, the receiver's silly window avoidance), and it never moves back.
| pcb | the connection |
Definition at line 49 of file tcp_output.c.
References MIN, tcp_pcb::mss, tcp_pcb::rcv_adv, tcp_pcb::rcv_nxt, tcp_pcb::rcvbuf, SEQ_GT, TCP_BUFSIZE, and tcp_rcv_window().
Referenced by segment(), tcp_rcv_window(), and window_update().
| void tcp_reply_rst | ( | struct netif * | netif, |
| const struct ipv4_hdr * | ih, | ||
| const struct tcp_hdr * | th, | ||
| size_t | len ) |
Answers a segment that is for no connection with a reset (RFC 9293 3.10.7.1).
A reset itself isn't answered.
| netif | the interface it came in on |
| ih | its IPv4 header |
| th | its TCP header |
| len | the length of its data |
Definition at line 192 of file tcp_output.c.
References tcp_hdr::ack, tcp_hdr::checksum, ipv4_hdr::dst, tcp_hdr::dst, tcp_hdr::flags, htonl, inet_checksum_pseudo(), IP_PROTO_TCP, ipv4_output(), netbuf::len, memset(), netbuf_alloc(), netbuf_push(), ntohl, tcp_hdr::off, tcp_hdr::seq, ipv4_hdr::src, tcp_hdr::src, tcp_reply_rst(), TH_ACK, TH_FIN, TH_RST, and TH_SYN.
Referenced by listen_input(), segment_input(), syn_sent_input(), tcp_input(), and tcp_reply_rst().
| void tcp_rexmt_start | ( | struct tcp_pcb * | pcb | ) |
Starts the retransmission timer, if it isn't running.
| pcb | the connection |
Definition at line 122 of file tcp_output.c.
References net_callout_set(), callout::pending, tcp_pcb::rexmt, rexmt_timeout(), tcp_pcb::rto, and tcp_rexmt_start().
Referenced by ack_input(), tcp_output(), tcp_rexmt_start(), and tcp_send_syn().
Updates the round trip estimates with a new measurement, and the retransmission timeout from them (RFC 6298).
| pcb | the connection |
| rtt | the round trip measured, in ns |
Definition at line 316 of file tcp_output.c.
References MAX, MIN, tcp_pcb::rto, RTO_MAX, RTO_MIN, RTT_GRANULARITY, tcp_pcb::rttvar, tcp_pcb::srtt, and tcp_rtt_update().
Referenced by tcp_rtt_update().
| void tcp_send_ack | ( | struct tcp_pcb * | pcb | ) |
Sends an ACK, now.
| pcb | the connection |
Definition at line 157 of file tcp_output.c.
References segment(), tcp_pcb::snd_nxt, tcp_send_ack(), and TH_ACK.
Referenced by ack_input(), dack_timeout(), fin_input(), segment_input(), syn_sent_input(), tcp_dack(), tcp_send_ack(), and window_update().
| void tcp_send_keepalive | ( | struct tcp_pcb * | pcb | ) |
Sends a keepalive probe: a segment one byte before what the peer has acknowledged (with no data), which the peer answers with an ACK.
| pcb | the connection |
Definition at line 168 of file tcp_output.c.
References segment(), tcp_pcb::snd_una, tcp_send_keepalive(), and TH_ACK.
Referenced by keepalive_timeout(), and tcp_send_keepalive().
| void tcp_send_rst | ( | struct tcp_pcb * | pcb | ) |
Sends a reset on a connection.
| pcb | the connection |
Definition at line 178 of file tcp_output.c.
References segment(), tcp_pcb::snd_nxt, tcp_send_rst(), TH_ACK, and TH_RST.
Referenced by keepalive_timeout(), segment_input(), socket_tcp_shutdown(), and tcp_send_rst().
| void tcp_send_syn | ( | struct tcp_pcb * | pcb | ) |
Sends the SYN (or, in SYN_RECEIVED, the SYN and ACK), the first time or again, and starts the retransmission timer.
The first one is timed, to measure the round trip.
| pcb | the connection |
Definition at line 135 of file tcp_output.c.
References arch_rtime_ns(), tcp_hdr::flags, tcp_pcb::iss, tcp_pcb::retries, tcp_pcb::rtt_seq, tcp_pcb::rtt_start, tcp_pcb::rtt_timing, segment(), tcp_pcb::snd_max, tcp_pcb::snd_nxt, tcp_pcb::state, tcp_rexmt_start(), tcp_send_syn(), TCP_SYN_RECEIVED, TH_ACK, and TH_SYN.
Referenced by listen_input(), rexmt_timeout(), socket_tcp_connect(), syn_sent_input(), and tcp_send_syn().