AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
tcp.h File Reference
#include <core/system.h>
#include <ds/hashmap.h>
#include <ds/queue.h>
#include <ds/ringbuf.h>
#include <net/inet.h>
#include <sys/callout.h>

Go to the source code of this file.

Data Structures

struct  tcp_hdr
 A TCP segment's header. More...
struct  tcp_pcb
 A connection (its control block, or PCB). More...

Macros

#define TH_FIN   0x01
#define TH_SYN   0x02
#define TH_RST   0x04
#define TH_PSH   0x08
#define TH_ACK   0x10
#define TH_URG   0x20
#define SEQ_LT(a, b)
#define SEQ_LEQ(a, b)
#define SEQ_GT(a, b)
#define SEQ_GEQ(a, b)
#define TCP_BUFSIZE   65536
#define TCP_MSS_DEFAULT   536

Enumerations

enum  tcp_state {
  TCP_CLOSED , TCP_LISTEN , TCP_SYN_SENT , TCP_SYN_RECEIVED ,
  TCP_ESTABLISHED , TCP_FIN_WAIT_1 , TCP_FIN_WAIT_2 , TCP_CLOSE_WAIT ,
  TCP_CLOSING , TCP_LAST_ACK , TCP_TIME_WAIT
}

Functions

void tcp_input (struct netif *netif, struct netbuf *nb, const struct ipv4_hdr *ih)
 Takes in a TCP segment that IPv4 received, and passes it to its connection or listener.
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_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_send_ack (struct tcp_pcb *pcb)
 Sends an ACK, now.
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_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).
void tcp_rexmt_start (struct tcp_pcb *pcb)
 Starts the retransmission timer, if it isn't running.
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).
uint16_t tcp_rcv_window (struct tcp_pcb *pcb)
 Computes the window to advertise: the room in the receive buffer.
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.
struct tcp_pcb * tcp_pcb_new (void)
 Makes a connection, CLOSED, with its send and receive buffers, on the list of connections.
void tcp_pcb_free (struct tcp_pcb *pcb)
 Frees a connection: its timers stop, it leaves the lists, and its buffers and waiting segments are freed.
struct tcp_pcb * tcp_lookup (uint32_t laddr, uint16_t lport, uint32_t raddr, uint16_t rport)
 Finds a connection by both ends' addresses and ports.
struct tcp_pcb * tcp_listener (uint32_t laddr, uint16_t lport)
 Finds the listener for a local address and port: one bound to that address, or else one bound to any address.
int tcp_insert (struct tcp_pcb *pcb)
 Adds a connection to the hashmap of connections, by its addresses and ports, which it must have now.
uint32_t tcp_iss (struct tcp_pcb *pcb)
 Chooses a connection's initial sequence number (RFC 6528): a clock that ticks every 4 us, plus a hash of the connection's addresses and ports with a secret, so that it can't be guessed.
void tcp_fin_wait_2 (struct tcp_pcb *pcb)
 Handles our FIN being acknowledged (FIN_WAIT_2): if the socket is closed, the connection waits for the peer's FIN only for a while.
void tcp_keepalive_reset (struct tcp_pcb *pcb)
 Restarts the keepalive timer, when the peer was heard from.
void tcp_established (struct tcp_pcb *pcb)
 Moves a connection to ESTABLISHED: its congestion window starts, and a listener's connection is queued for accept().
void tcp_drop (struct tcp_pcb *pcb, int err)
 Drops a connection that is lost, giving its socket an error.
void tcp_closed (struct tcp_pcb *pcb)
 Moves a connection to CLOSED: it leaves the hashmap, its timers stop, and its waiters wake up.
void tcp_time_wait (struct tcp_pcb *pcb)
 Moves a connection to TIME_WAIT, which it leaves after 2 MSL.
void tcp_wakeup (struct tcp_pcb *pcb)
 Wakes up the threads waiting on a connection (in accept(), connect(), recv() or send()).

Variables

struct tcp_pcb * tcp_pcbs

Macro Definition Documentation

◆ SEQ_GEQ

#define SEQ_GEQ ( a,
b )
Value:
((int32_t) ((a) - (b)) >= 0)
signed int int32_t
Definition stddef.h:18

Definition at line 53 of file tcp.h.

Referenced by ack_input().

◆ SEQ_GT

#define SEQ_GT ( a,
b )

◆ SEQ_LEQ

#define SEQ_LEQ ( a,
b )
Value:
((int32_t) ((a) - (b)) <= 0)

Definition at line 51 of file tcp.h.

Referenced by ack_input(), ooo_drain(), segment_input(), and syn_sent_input().

◆ SEQ_LT

#define SEQ_LT ( a,
b )
Value:
((int32_t) ((a) - (b)) < 0)

Definition at line 50 of file tcp.h.

Referenced by ack_input(), ooo_insert(), and segment_input().

◆ TCP_BUFSIZE

#define TCP_BUFSIZE   65536

◆ TCP_MSS_DEFAULT

#define TCP_MSS_DEFAULT   536

Definition at line 59 of file tcp.h.

Referenced by our_mss(), set_mss(), and tcp_pcb_new().

◆ TH_ACK

◆ TH_FIN

#define TH_FIN   0x01

Definition at line 27 of file tcp.h.

Referenced by acceptable(), ack_input(), segment_input(), tcp_output(), and tcp_reply_rst().

◆ TH_PSH

#define TH_PSH   0x08

Definition at line 30 of file tcp.h.

Referenced by tcp_output().

◆ TH_RST

#define TH_RST   0x04

Definition at line 29 of file tcp.h.

Referenced by listen_input(), segment_input(), syn_sent_input(), tcp_reply_rst(), and tcp_send_rst().

◆ TH_SYN

#define TH_SYN   0x02

◆ TH_URG

#define TH_URG   0x20

Definition at line 32 of file tcp.h.

Enumeration Type Documentation

◆ tcp_state

enum tcp_state
Enumerator
TCP_CLOSED 
TCP_LISTEN 
TCP_SYN_SENT 
TCP_SYN_RECEIVED 
TCP_ESTABLISHED 
TCP_FIN_WAIT_1 
TCP_FIN_WAIT_2 
TCP_CLOSE_WAIT 
TCP_CLOSING 
TCP_LAST_ACK 
TCP_TIME_WAIT 

Definition at line 35 of file tcp.h.

Function Documentation

◆ tcp_closed()

void tcp_closed ( struct tcp_pcb * pcb)

Moves a connection to CLOSED: it leaves the hashmap, its timers stop, and its waiters wake up.

It is freed if nothing holds it anymore; otherwise its socket keeps it.

Parameters
pcbthe connection

Definition at line 295 of file tcp_socket.c.

References callout_stop(), conns, tcp_pcb::dack, tcp_pcb::detached, tcp_pcb::hnode, NULL, tcp_pcb::parent, tcp_pcb::rexmt, tcp_pcb::state, TCP_CLOSED, tcp_closed(), tcp_pcb_free(), tcp_wakeup(), tcp_pcb::timer2, and unlink_parent().

Referenced by ack_input(), segment_input(), tcp_closed(), tcp_drop(), and timer2_closed().

◆ 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_drop()

void tcp_drop ( struct tcp_pcb * pcb,
int err )

Drops a connection that is lost, giving its socket an error.

Parameters
pcbthe connection
errthe error for the socket (a positive errno), or 0

Definition at line 323 of file tcp_socket.c.

References tcp_pcb::error, tcp_closed(), and tcp_drop().

Referenced by keepalive_timeout(), rexmt_timeout(), segment_input(), socket_tcp_shutdown(), syn_sent_input(), and tcp_drop().

◆ tcp_established()

void tcp_established ( struct tcp_pcb * pcb)

Moves a connection to ESTABLISHED: its congestion window starts, and a listener's connection is queued for accept().

Parameters
pcbthe connection

Definition at line 335 of file tcp_socket.c.

References tcp_pcb::accept_head, tcp_pcb::accept_next, tcp_pcb::accept_tail, tcp_pcb::connected, tcp_pcb::cwnd, MAX, MIN, tcp_pcb::mss, tcp_pcb::parent, tcp_pcb::snd_max, tcp_pcb::snd_nxt, tcp_pcb::snd_una, tcp_pcb::state, TCP_ESTABLISHED, tcp_established(), tcp_keepalive_reset(), and tcp_wakeup().

Referenced by segment_input(), syn_sent_input(), and tcp_established().

◆ tcp_fin_wait_2()

void tcp_fin_wait_2 ( struct tcp_pcb * pcb)

Handles our FIN being acknowledged (FIN_WAIT_2): if the socket is closed, the connection waits for the peer's FIN only for a while.

Parameters
pcbthe connection

Definition at line 387 of file tcp_socket.c.

References tcp_pcb::detached, FIN_WAIT_2_TIME, net_callout_set(), tcp_fin_wait_2(), tcp_pcb::timer2, and timer2_closed().

Referenced by ack_input(), socket_tcp_shutdown(), and tcp_fin_wait_2().

◆ tcp_input()

void tcp_input ( struct netif * netif,
struct netbuf * nb,
const struct ipv4_hdr * ih )

Takes in a TCP segment that IPv4 received, and passes it to its connection or listener.

A segment with a bad checksum or header, or not sent to one of our addresses, is dropped.

Parameters
netifthe interface it came in on
nbthe segment, from its TCP header; it is freed or kept
ihits IPv4 header

Definition at line 585 of file tcp_input.c.

References tcp_hdr::ack, netbuf::data, ipv4_hdr::dst, tcp_hdr::dst, tcp_hdr::flags, inet_checksum_pseudo(), IP_PROTO_TCP, ipv4_is_local(), netbuf::len, seg::len, listen_input(), netbuf_free(), ntohl, ntohs, tcp_hdr::off, options(), segment_input(), tcp_hdr::seq, ipv4_hdr::src, tcp_hdr::src, tcp_pcb::state, netif::stats, syn_sent_input(), tcp_input(), tcp_listener(), tcp_lookup(), tcp_reply_rst(), TCP_SYN_SENT, and tcp_hdr::win.

Referenced by ipv4_input(), and tcp_input().

◆ tcp_insert()

int tcp_insert ( struct tcp_pcb * pcb)

Adds a connection to the hashmap of connections, by its addresses and ports, which it must have now.

Parameters
pcbthe connection
Returns
0, -EADDRINUSE if another connection has the same ones, or -ENOMEM

Definition at line 112 of file tcp_socket.c.

References conns, tcp_pcb::hnode, key_eq(), key_hash(), tcp_pcb::laddr, tcp_pcb::lport, tcp_pcb::raddr, tcp_pcb::rport, and tcp_insert().

Referenced by listen_input(), socket_tcp_connect(), and tcp_insert().

◆ tcp_iss()

uint32_t tcp_iss ( struct tcp_pcb * pcb)

Chooses a connection's initial sequence number (RFC 6528): a clock that ticks every 4 us, plus a hash of the connection's addresses and ports with a secret, so that it can't be guessed.

Parameters
pcbthe connection, with its addresses and ports
Returns
the initial sequence number

Definition at line 231 of file tcp_socket.c.

References arch_rtime_ns(), iss_secret, tcp_pcb::laddr, tcp_pcb::lport, memcpy(), tcp_pcb::raddr, random_get(), tcp_pcb::rport, and tcp_iss().

Referenced by listen_input(), socket_tcp_connect(), and tcp_iss().

◆ tcp_keepalive_reset()

void tcp_keepalive_reset ( struct tcp_pcb * pcb)

Restarts the keepalive timer, when the peer was heard from.

Parameters
pcbthe connection

Definition at line 417 of file tcp_socket.c.

References KEEP_IDLE, tcp_pcb::keep_probes, tcp_pcb::keepalive, keepalive_timeout(), net_callout_set(), tcp_pcb::state, TCP_ESTABLISHED, tcp_keepalive_reset(), and tcp_pcb::timer2.

Referenced by segment_input(), socket_tcp_setsockopt(), tcp_established(), and tcp_keepalive_reset().

◆ tcp_listener()

struct tcp_pcb * tcp_listener ( uint32_t laddr,
uint16_t lport )

Finds the listener for a local address and port: one bound to that address, or else one bound to any address.

Parameters
laddrthe local address
lportthe local port
Returns
the listener, or NULL

Definition at line 138 of file tcp_socket.c.

References tcp_pcb::laddr, tcp_pcb::lport, tcp_pcb::next, NULL, TCP_LISTEN, tcp_listener(), and tcp_pcbs.

Referenced by tcp_input(), and tcp_listener().

◆ tcp_lookup()

struct tcp_pcb * tcp_lookup ( uint32_t laddr,
uint16_t lport,
uint32_t raddr,
uint16_t rport )

Finds a connection by both ends' addresses and ports.

Parameters
laddrthe local address
lportthe local port
raddrthe remote address
rportthe remote port
Returns
the connection, or NULL

Definition at line 96 of file tcp_socket.c.

References conns, hashmap_node::entry, key_hash(), tcp_key::laddr, tcp_key::lport, NULL, tcp_key::raddr, tcp_key::rport, and tcp_lookup().

Referenced by tcp_input(), and tcp_lookup().

◆ 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_pcb_free()

void tcp_pcb_free ( struct tcp_pcb * pcb)

Frees a connection: its timers stop, it leaves the lists, and its buffers and waiting segments are freed.

Parameters
pcbthe connection

Definition at line 196 of file tcp_socket.c.

References callout_stop(), conns, tcp_pcb::dack, tcp_pcb::hnode, kfree(), netbuf_free(), netbuf::next, tcp_pcb::next, tcp_pcb::ooo, tcp_pcb::rcvbuf, tcp_pcb::rexmt, tcp_pcb::sndbuf, tcp_pcb_free(), tcp_pcbs, and tcp_pcb::timer2.

Referenced by listen_input(), socket_tcp_create(), socket_tcp_shutdown(), tcp_closed(), and tcp_pcb_free().

◆ tcp_pcb_new()

struct tcp_pcb * tcp_pcb_new ( void )

Makes a connection, CLOSED, with its send and receive buffers, on the list of connections.

Returns
the connection, or NULL if there was no memory

Definition at line 162 of file tcp_socket.c.

References kfree(), kmalloc(), M_ZERO, tcp_pcb::mss, tcp_pcb::next, NULL, tcp_pcb::rcvbuf, tcp_pcb::rto, RTO_INITIAL, tcp_pcb::sndbuf, tcp_pcb::ssthresh, tcp_pcb::state, TCP_BUFSIZE, TCP_CLOSED, TCP_MSS_DEFAULT, tcp_pcb_new(), and tcp_pcbs.

Referenced by listen_input(), socket_tcp_create(), and tcp_pcb_new().

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

◆ tcp_time_wait()

void tcp_time_wait ( struct tcp_pcb * pcb)

Moves a connection to TIME_WAIT, which it leaves after 2 MSL.

Parameters
pcbthe connection

Definition at line 373 of file tcp_socket.c.

References callout_stop(), MSL, net_callout_set(), tcp_pcb::rexmt, tcp_pcb::state, TCP_TIME_WAIT, tcp_time_wait(), tcp_wakeup(), tcp_pcb::timer2, and timer2_closed().

Referenced by ack_input(), fin_input(), and tcp_time_wait().

◆ tcp_wakeup()

void tcp_wakeup ( struct tcp_pcb * pcb)

Wakes up the threads waiting on a connection (in accept(), connect(), recv() or send()).

Parameters
pcbthe connection

Definition at line 257 of file tcp_socket.c.

References tcp_wakeup(), tcp_pcb::wait, and waitq_wakeup().

Referenced by ack_input(), fin_input(), segment_input(), socket_tcp_shut(), tcp_closed(), tcp_established(), tcp_time_wait(), and tcp_wakeup().

Variable Documentation

◆ tcp_pcbs

struct tcp_pcb* tcp_pcbs
extern

Definition at line 55 of file tcp_socket.c.

Referenced by port_used(), socket_tcp_shutdown(), tcp_listener(), tcp_pcb_free(), and tcp_pcb_new().