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

TCP input (RFC 9293 3.10.7, "SEGMENT ARRIVES"). 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.

Data Structures

struct  seg
 A received segment, with its header in host byte order. More...

Macros

#define IN_WINDOW(x)

Functions

static void options (const struct tcp_hdr *th, size_t hlen, struct seg *s)
 Reads a segment's options; the only one used is the MSS.
static void set_mss (struct tcp_pcb *pcb, uint16_t peer)
 Sets the connection's segment size: the peer's MSS (536 if it didn't send one), but no more than ours.
static void rtt_sample (struct tcp_pcb *pcb, uint32_t ack)
 Takes a round trip measurement, if ack acknowledges the segment that is being timed.
static void listen_input (struct tcp_pcb *l, const struct ipv4_hdr *ih, const struct tcp_hdr *th, struct seg *s, struct netif *netif)
 Handles a segment for a listening socket.
static void syn_sent_input (struct tcp_pcb *pcb, const struct ipv4_hdr *ih, const struct tcp_hdr *th, struct seg *s, struct netif *netif)
 Handles a segment for a connection in SYN_SENT (RFC 9293 3.10.7.3): the peer's SYN and ACK establish it, a reset refuses it.
static int acceptable (struct tcp_pcb *pcb, struct seg *s, uint32_t wnd)
 Returns whether a segment is acceptable (RFC 9293 3.10.7.4): it falls within the window we advertised.
static void retransmit_first (struct tcp_pcb *pcb)
 Retransmits the first unacknowledged segment, for a fast retransmit or a partial ACK.
static int ack_input (struct tcp_pcb *pcb, struct seg *s)
 Handles a segment's acknowledgment of what we sent: the send buffer, the congestion window, the timers and the peer's window.
static void ooo_insert (struct tcp_pcb *pcb, struct netbuf *nb, struct seg *s, int fin)
 Queues a segment that came ahead of rcv_nxt, sorted by sequence number; its netbuf now holds just its data.
static void ooo_purge (struct tcp_pcb *pcb)
 Drops the segments that still wait, once the FIN is in: nothing follows the FIN, so they are only copies of what came before it, cut differently.
static int ooo_drain (struct tcp_pcb *pcb)
 Takes the waiting segments that now follow rcv_nxt into the receive buffer.
static void fin_input (struct tcp_pcb *pcb)
 Handles the peer's FIN, once all the data before it is in: the end of its data, and a change of state.
static void segment_input (struct tcp_pcb *pcb, struct netbuf *nb, struct seg *s, const struct ipv4_hdr *ih, const struct tcp_hdr *th, struct netif *netif)
 Handles a segment for a connection in a synchronized state (RFC 9293 3.10.7.4).
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.

Detailed Description

TCP input (RFC 9293 3.10.7, "SEGMENT ARRIVES").

A segment goes to its connection's state machine, or to a listener, which makes a new connection for a SYN. A segment for no connection is answered with a reset.

Acknowledgments drive the congestion window (RFC 5681): slow start, then congestion avoidance; three duplicate ACKs mean a lost segment, which is retransmitted at once, with NewReno's recovery (RFC 6582). Data that arrives out of order waits in a sorted list until what is missing comes, and a duplicate ACK tells the peer what is missing.

Definition in file tcp_input.c.

Macro Definition Documentation

◆ IN_WINDOW

#define IN_WINDOW ( x)
Value:
(SEQ_GEQ(x, nxt) && SEQ_LT(x, nxt + wnd))
#define SEQ_GEQ(a, b)
Definition tcp.h:53
#define SEQ_LT(a, b)
Definition tcp.h:50

Referenced by acceptable().

Function Documentation

◆ acceptable()

int acceptable ( struct tcp_pcb * pcb,
struct seg * s,
uint32_t wnd )
static

Returns whether a segment is acceptable (RFC 9293 3.10.7.4): it falls within the window we advertised.

Definition at line 186 of file tcp_input.c.

References acceptable(), seg::flags, IN_WINDOW, seg::len, tcp_pcb::rcv_nxt, seg::seq, TH_FIN, and TH_SYN.

Referenced by acceptable(), and segment_input().

◆ ack_input()

◆ fin_input()

void fin_input ( struct tcp_pcb * pcb)
static

Handles the peer's FIN, once all the data before it is in: the end of its data, and a change of state.

Definition at line 404 of file tcp_input.c.

References fin_input(), tcp_pcb::fin_received, tcp_pcb::rcv_nxt, tcp_pcb::state, TCP_CLOSE_WAIT, TCP_CLOSING, TCP_ESTABLISHED, TCP_FIN_WAIT_1, TCP_FIN_WAIT_2, tcp_send_ack(), TCP_SYN_RECEIVED, TCP_TIME_WAIT, tcp_time_wait(), and tcp_wakeup().

Referenced by fin_input(), and segment_input().

◆ listen_input()

void listen_input ( struct tcp_pcb * l,
const struct ipv4_hdr * ih,
const struct tcp_hdr * th,
struct seg * s,
struct netif * netif )
static

◆ ooo_drain()

int ooo_drain ( struct tcp_pcb * pcb)
static

Takes the waiting segments that now follow rcv_nxt into the receive buffer.

Returns 1 if the FIN came with them, or 0.

Definition at line 369 of file tcp_input.c.

References netbuf::data, netbuf::fin, netbuf::len, netbuf_free(), netbuf::next, tcp_pcb::ooo, ooo_drain(), ooo_purge(), tcp_pcb::rcv_nxt, tcp_pcb::rcvbuf, netbuf::seq, SEQ_LEQ, and skip.

Referenced by ooo_drain(), and segment_input().

◆ ooo_insert()

void ooo_insert ( struct tcp_pcb * pcb,
struct netbuf * nb,
struct seg * s,
int fin )
static

Queues a segment that came ahead of rcv_nxt, sorted by sequence number; its netbuf now holds just its data.

Definition at line 332 of file tcp_input.c.

References netbuf::data, seg::data, netbuf::fin, netbuf::len, seg::len, netbuf_free(), netbuf::next, tcp_pcb::ooo, ooo_insert(), netbuf::seq, seg::seq, and SEQ_LT.

Referenced by ooo_insert(), and segment_input().

◆ ooo_purge()

void ooo_purge ( struct tcp_pcb * pcb)
static

Drops the segments that still wait, once the FIN is in: nothing follows the FIN, so they are only copies of what came before it, cut differently.

(They aren't data no one read, which socket_tcp_shutdown() deals with.)

Definition at line 358 of file tcp_input.c.

References netbuf_free(), netbuf::next, tcp_pcb::ooo, and ooo_purge().

Referenced by ooo_drain(), ooo_purge(), and segment_input().

◆ options()

void options ( const struct tcp_hdr * th,
size_t hlen,
struct seg * s )
static

Reads a segment's options; the only one used is the MSS.

Definition at line 36 of file tcp_input.c.

References seg::mss, and options().

Referenced by options(), sys_waitpid(), and tcp_input().

◆ retransmit_first()

void retransmit_first ( struct tcp_pcb * pcb)
static

Retransmits the first unacknowledged segment, for a fast retransmit or a partial ACK.

Definition at line 203 of file tcp_input.c.

References tcp_pcb::cwnd, tcp_pcb::mss, tcp_pcb::nodelay, retransmit_first(), tcp_pcb::rtt_timing, SEQ_GT, tcp_pcb::snd_nxt, tcp_pcb::snd_una, and tcp_output().

Referenced by ack_input(), and retransmit_first().

◆ rtt_sample()

void rtt_sample ( struct tcp_pcb * pcb,
uint32_t ack )
static

Takes a round trip measurement, if ack acknowledges the segment that is being timed.

Definition at line 73 of file tcp_input.c.

References rtt_sample(), tcp_pcb::rtt_seq, tcp_pcb::rtt_timing, and SEQ_GT.

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

◆ segment_input()

◆ set_mss()

void set_mss ( struct tcp_pcb * pcb,
uint16_t peer )
static

Sets the connection's segment size: the peer's MSS (536 if it didn't send one), but no more than ours.

Definition at line 62 of file tcp_input.c.

References ipv4_route(), MIN, netif::mtu, tcp_pcb::raddr, set_mss(), and TCP_MSS_DEFAULT.

Referenced by listen_input(), set_mss(), and syn_sent_input().

◆ syn_sent_input()

void syn_sent_input ( struct tcp_pcb * pcb,
const struct ipv4_hdr * ih,
const struct tcp_hdr * th,
struct seg * s,
struct netif * netif )
static

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