AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
tcp_output.c File Reference

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.

Detailed Description

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.

Macro Definition Documentation

◆ DACK_DELAY

#define DACK_DELAY   100000000ULL

Definition at line 24 of file tcp_output.c.

Referenced by tcp_dack().

◆ DATA_RETRIES

#define DATA_RETRIES   8

Definition at line 27 of file tcp_output.c.

Referenced by rexmt_timeout().

◆ RTO_MAX

#define RTO_MAX   60000000000ULL

Definition at line 22 of file tcp_output.c.

Referenced by rexmt_timeout(), and tcp_rtt_update().

◆ RTO_MIN

#define RTO_MIN   1000000000ULL

Definition at line 21 of file tcp_output.c.

Referenced by tcp_rtt_update().

◆ RTT_GRANULARITY

#define RTT_GRANULARITY   2000000ULL

Definition at line 23 of file tcp_output.c.

Referenced by tcp_rtt_update().

◆ SYN_RETRIES

#define SYN_RETRIES   5

Definition at line 26 of file tcp_output.c.

Referenced by rexmt_timeout().

Function Documentation

◆ dack_timeout()

void dack_timeout ( void * arg)
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().

◆ our_mss()

uint16_t our_mss ( struct tcp_pcb * pcb)
static

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.

Referenced by our_mss(), and segment().

◆ rexmt_timeout()

void rexmt_timeout ( void * arg)
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().

◆ segment()

int segment ( struct tcp_pcb * pcb,
uint32_t seq,
int flags,
size_t off,
size_t len )
static

◆ sending()

int sending ( struct tcp_pcb * pcb)
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().

◆ tcp_dack()

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.

Parameters
pcbthe 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().

◆ tcp_output()

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.

Parameters
pcbthe 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().

◆ tcp_rcv_window()

uint16_t tcp_rcv_window ( struct tcp_pcb * pcb)

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.

Parameters
pcbthe connection
Returns
the window, at most 65535 (window scaling isn't supported)

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().

◆ tcp_reply_rst()

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.

Parameters
netifthe interface it came in on
ihits IPv4 header
thits TCP header
lenthe 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().

◆ tcp_rexmt_start()

void tcp_rexmt_start ( struct tcp_pcb * pcb)

Starts the retransmission timer, if it isn't running.

Parameters
pcbthe 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().

◆ tcp_rtt_update()

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).

Parameters
pcbthe connection
rttthe 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().

◆ tcp_send_ack()

void tcp_send_ack ( struct tcp_pcb * pcb)

Sends an ACK, now.

Parameters
pcbthe 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().

◆ tcp_send_keepalive()

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.

Parameters
pcbthe 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().

◆ tcp_send_rst()

void tcp_send_rst ( struct tcp_pcb * pcb)

Sends a reset on a connection.

Parameters
pcbthe 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().

◆ tcp_send_syn()

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.

Parameters
pcbthe 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().