iPXE
Data Structures | Enumerations | Functions | Variables
tcp.c File Reference

TCP protocol. More...

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/timer.h>
#include <ipxe/iobuf.h>
#include <ipxe/malloc.h>
#include <ipxe/init.h>
#include <ipxe/retry.h>
#include <ipxe/refcnt.h>
#include <ipxe/pending.h>
#include <ipxe/xfer.h>
#include <ipxe/open.h>
#include <ipxe/uri.h>
#include <ipxe/netdevice.h>
#include <ipxe/profile.h>
#include <ipxe/process.h>
#include <ipxe/job.h>
#include <ipxe/tcpip.h>
#include <ipxe/tcp.h>

Go to the source code of this file.

Data Structures

struct  tcp_connection
 A TCP connection. More...
 
struct  tcp_rx_queued_header
 TCP internal header. More...
 

Enumerations

enum  tcp_flags { TCP_XFER_CLOSED = 0x0001, TCP_TS_ENABLED = 0x0002, TCP_ACK_PENDING = 0x0004, TCP_SACK_ENABLED = 0x0008 }
 TCP flags. More...
 

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 
static LIST_HEAD (tcp_conns)
 List of registered TCP connections. More...
 
static void tcp_expired (struct retry_timer *timer, int over)
 Retransmission timer expired. More...
 
static void tcp_keepalive_expired (struct retry_timer *timer, int over __unused)
 Keepalive timer expired. More...
 
static void tcp_wait_expired (struct retry_timer *timer, int over __unused)
 Shutdown timer expired. More...
 
static struct tcp_connectiontcp_demux (unsigned int local_port)
 Identify TCP connection by local port number. More...
 
static int tcp_rx_ack (struct tcp_connection *tcp, uint32_t ack, uint32_t win)
 Handle TCP received ACK. More...
 
static const char * tcp_state (int state)
 Name TCP state. More...
 
static void tcp_dump_state (struct tcp_connection *tcp)
 Dump TCP state transition. More...
 
static void tcp_dump_flags (struct tcp_connection *tcp, unsigned int flags)
 Dump TCP flags. More...
 
static int tcp_port_available (int port)
 Check if local TCP port is available. More...
 
static int tcp_open (struct interface *xfer, struct sockaddr *peer, struct sockaddr *local)
 Open a TCP connection. More...
 
static void tcp_close (struct tcp_connection *tcp, int rc)
 Close TCP connection. More...
 
static size_t tcp_xmit_win (struct tcp_connection *tcp)
 Calculate transmission window. More...
 
static size_t tcp_xfer_window (struct tcp_connection *tcp)
 Check data-transfer flow control window. More...
 
static uint32_t tcp_sack_block (struct tcp_connection *tcp, uint32_t seq, struct tcp_sack_block *sack)
 Find selective acknowledgement block. More...
 
static unsigned int tcp_sack (struct tcp_connection *tcp, uint32_t seq)
 Update TCP selective acknowledgement list. More...
 
static size_t tcp_process_tx_queue (struct tcp_connection *tcp, size_t max_len, struct io_buffer *dest, int remove)
 Process TCP transmit queue. More...
 
static void tcp_xmit_sack (struct tcp_connection *tcp, uint32_t sack_seq)
 Transmit any outstanding data (with selective acknowledgement) More...
 
static void tcp_xmit (struct tcp_connection *tcp)
 Transmit any outstanding data. More...
 
static int tcp_xmit_reset (struct tcp_connection *tcp, struct sockaddr_tcpip *st_dest, struct tcp_header *in_tcphdr)
 Send RST response to incoming packet. More...
 
static int tcp_rx_opts (struct tcp_connection *tcp, const struct tcp_header *tcphdr, size_t hlen, struct tcp_options *options)
 Parse TCP received options. More...
 
static void tcp_rx_seq (struct tcp_connection *tcp, uint32_t seq_len)
 Consume received sequence space. More...
 
static int tcp_rx_syn (struct tcp_connection *tcp, uint32_t seq, struct tcp_options *options)
 Handle TCP received SYN. More...
 
static int tcp_rx_data (struct tcp_connection *tcp, uint32_t seq, struct io_buffer *iobuf)
 Handle TCP received data. More...
 
static int tcp_rx_fin (struct tcp_connection *tcp, uint32_t seq)
 Handle TCP received FIN. More...
 
static int tcp_rx_rst (struct tcp_connection *tcp, uint32_t seq)
 Handle TCP received RST. More...
 
static void tcp_rx_enqueue (struct tcp_connection *tcp, uint32_t seq, uint8_t flags, struct io_buffer *iobuf)
 Enqueue received TCP packet. More...
 
static void tcp_process_rx_queue (struct tcp_connection *tcp)
 Process receive queue. More...
 
static int tcp_rx (struct io_buffer *iobuf, struct net_device *netdev __unused, struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest __unused, uint16_t pshdr_csum)
 Process received packet. More...
 
static unsigned int tcp_discard (void)
 Discard some cached TCP data. More...
 
struct cache_discarder tcp_discarder __cache_discarder (CACHE_NORMAL)
 TCP cache discarder. More...
 
static struct tcp_connectiontcp_first_unclosed (void)
 Find first TCP connection that has not yet been closed. More...
 
static struct tcp_connectiontcp_first_unfinished (void)
 Find first TCP connection that has not yet finished all operations. More...
 
static void tcp_shutdown (int booting __unused)
 Shut down all TCP connections. More...
 
struct startup_fn tcp_startup_fn __startup_fn (STARTUP_LATE)
 TCP shutdown function. More...
 
static void tcp_xfer_close (struct tcp_connection *tcp, int rc)
 Close interface. More...
 
static int tcp_xfer_deliver (struct tcp_connection *tcp, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
 Deliver datagram as I/O buffer. More...
 
static int tcp_progress (struct tcp_connection *tcp, struct job_progress *progress)
 Report job progress. More...
 
static int tcp_open_uri (struct interface *xfer, struct uri *uri)
 Open TCP URI. More...
 

Variables

static struct profiler tcp_tx_profiler __profiler = { .name = "tcp.tx" }
 Transmit profiler. More...
 
static struct process_descriptor tcp_process_desc
 TCP process descriptor. More...
 
static struct interface_descriptor tcp_xfer_desc
 TCP data transfer interface descriptor. More...
 
struct tcpip_protocol tcp_protocol __tcpip_protocol
 TCP protocol. More...
 
static struct interface_operation tcp_xfer_operations []
 TCP data transfer interface operations. More...
 
struct socket_opener tcp_ipv4_socket_opener __socket_opener
 TCP IPv4 socket opener. More...
 
int tcp_sock_stream = TCP_SOCK_STREAM
 Linkage hack. More...
 
struct uri_opener tcp_uri_opener __uri_opener
 TCP URI opener. More...
 

Detailed Description

TCP protocol.

Definition in file tcp.c.

Enumeration Type Documentation

◆ tcp_flags

enum tcp_flags

TCP flags.

Enumerator
TCP_XFER_CLOSED 

TCP data transfer interface has been closed.

TCP_TS_ENABLED 

TCP timestamps are enabled.

TCP_ACK_PENDING 

TCP acknowledgement is pending.

TCP_SACK_ENABLED 

TCP selective acknowledgement is enabled.

Definition at line 129 of file tcp.c.

129  {
130  /** TCP data transfer interface has been closed */
131  TCP_XFER_CLOSED = 0x0001,
132  /** TCP timestamps are enabled */
133  TCP_TS_ENABLED = 0x0002,
134  /** TCP acknowledgement is pending */
135  TCP_ACK_PENDING = 0x0004,
136  /** TCP selective acknowledgement is enabled */
137  TCP_SACK_ENABLED = 0x0008,
138 };
TCP selective acknowledgement is enabled.
Definition: tcp.c:137
TCP timestamps are enabled.
Definition: tcp.c:133
TCP data transfer interface has been closed.
Definition: tcp.c:131
TCP acknowledgement is pending.
Definition: tcp.c:135

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ LIST_HEAD()

static LIST_HEAD ( tcp_conns  )
static

List of registered TCP connections.

◆ tcp_expired()

static void tcp_expired ( struct retry_timer timer,
int  over 
)
static

Retransmission timer expired.

Parameters
timerRetransmission timer
overFailure indicator

Definition at line 785 of file tcp.c.

785  {
786  struct tcp_connection *tcp =
787  container_of ( timer, struct tcp_connection, timer );
788 
789  DBGC ( tcp, "TCP %p timer %s in %s for %08x..%08x %08x\n", tcp,
790  ( over ? "expired" : "fired" ), tcp_state ( tcp->tcp_state ),
791  tcp->snd_seq, ( tcp->snd_seq + tcp->snd_sent ), tcp->rcv_ack );
792 
793  assert ( ( tcp->tcp_state == TCP_SYN_SENT ) ||
794  ( tcp->tcp_state == TCP_SYN_RCVD ) ||
795  ( tcp->tcp_state == TCP_ESTABLISHED ) ||
796  ( tcp->tcp_state == TCP_FIN_WAIT_1 ) ||
797  ( tcp->tcp_state == TCP_CLOSE_WAIT ) ||
798  ( tcp->tcp_state == TCP_CLOSING_OR_LAST_ACK ) );
799 
800  if ( over ) {
801  /* If we have finally timed out and given up,
802  * terminate the connection
803  */
804  tcp->tcp_state = TCP_CLOSED;
805  tcp_dump_state ( tcp );
806  tcp_close ( tcp, -ETIMEDOUT );
807  } else {
808  /* Otherwise, retransmit the packet */
809  tcp_xmit ( tcp );
810  }
811 }
A TCP connection.
Definition: tcp.c:33
unsigned int tcp_state
Current TCP state.
Definition: tcp.c:53
#define TCP_SYN_SENT
SYN_SENT.
Definition: tcp.h:215
uint32_t snd_seq
Current sequence number.
Definition: tcp.c:63
#define DBGC(...)
Definition: compiler.h:505
#define TCP_FIN_WAIT_1
FIN_WAIT_1.
Definition: tcp.h:246
A timer.
Definition: timer.h:28
#define TCP_CLOSE_WAIT
CLOSE_WAIT.
Definition: tcp.h:287
static void tcp_close(struct tcp_connection *tcp, int rc)
Close TCP connection.
Definition: tcp.c:349
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
static const char * tcp_state(int state)
Name TCP state.
Definition: tcp.c:196
#define TCP_ESTABLISHED
ESTABLISHED.
Definition: tcp.h:228
uint32_t snd_sent
Unacknowledged sequence count.
Definition: tcp.c:68
#define TCP_CLOSING_OR_LAST_ACK
CLOSING / LAST_ACK.
Definition: tcp.h:268
#define TCP_SYN_RCVD
SYN_RCVD.
Definition: tcp.h:221
uint32_t rcv_ack
Current acknowledgement number.
Definition: tcp.c:78
static void tcp_xmit(struct tcp_connection *tcp)
Transmit any outstanding data.
Definition: tcp.c:769
#define ETIMEDOUT
Connection timed out.
Definition: errno.h:669
#define TCP_CLOSED
CLOSED.
Definition: tcp.h:202
static void tcp_dump_state(struct tcp_connection *tcp)
Dump TCP state transition.
Definition: tcp.c:218

References assert(), container_of, DBGC, ETIMEDOUT, tcp_connection::rcv_ack, tcp_connection::snd_sent, tcp_connection::snd_seq, tcp_close(), TCP_CLOSE_WAIT, TCP_CLOSED, TCP_CLOSING_OR_LAST_ACK, tcp_dump_state(), TCP_ESTABLISHED, TCP_FIN_WAIT_1, tcp_connection::tcp_state, tcp_state(), TCP_SYN_RCVD, TCP_SYN_SENT, and tcp_xmit().

Referenced by tcp_open().

◆ tcp_keepalive_expired()

static void tcp_keepalive_expired ( struct retry_timer timer,
int over  __unused 
)
static

Keepalive timer expired.

Parameters
timerKeepalive timer
overFailure indicator

Definition at line 819 of file tcp.c.

820  {
821  struct tcp_connection *tcp =
823 
824  DBGC ( tcp, "TCP %p sending keepalive\n", tcp );
825 
826  /* Reset keepalive timer */
828 
829  /* Send keepalive. We do this only to preserve or restore
830  * state in intermediate devices (e.g. firewall NAT tables);
831  * we don't actually care about eliciting a response to verify
832  * that the peer is still alive. We therefore send just a
833  * pure ACK, to keep our transmit path simple.
834  */
835  tcp->flags |= TCP_ACK_PENDING;
836  tcp_xmit ( tcp );
837 }
A TCP connection.
Definition: tcp.c:33
struct retry_timer keepalive
Keepalive timer.
Definition: tcp.c:118
#define DBGC(...)
Definition: compiler.h:505
unsigned int flags
Flags.
Definition: tcp.c:40
A timer.
Definition: timer.h:28
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition: retry.c:64
TCP acknowledgement is pending.
Definition: tcp.c:135
#define TCP_KEEPALIVE_DELAY
TCP keepalive period.
Definition: tcp.h:387
static void tcp_xmit(struct tcp_connection *tcp)
Transmit any outstanding data.
Definition: tcp.c:769

References container_of, DBGC, tcp_connection::flags, tcp_connection::keepalive, start_timer_fixed(), TCP_ACK_PENDING, TCP_KEEPALIVE_DELAY, and tcp_xmit().

Referenced by tcp_open().

◆ tcp_wait_expired()

static void tcp_wait_expired ( struct retry_timer timer,
int over  __unused 
)
static

Shutdown timer expired.

Parameters
timerShutdown timer
overFailure indicator

Definition at line 845 of file tcp.c.

845  {
846  struct tcp_connection *tcp =
847  container_of ( timer, struct tcp_connection, wait );
848 
849  assert ( tcp->tcp_state == TCP_TIME_WAIT );
850 
851  DBGC ( tcp, "TCP %p wait complete in %s for %08x..%08x %08x\n", tcp,
852  tcp_state ( tcp->tcp_state ), tcp->snd_seq,
853  ( tcp->snd_seq + tcp->snd_sent ), tcp->rcv_ack );
854 
855  tcp->tcp_state = TCP_CLOSED;
856  tcp_dump_state ( tcp );
857  tcp_close ( tcp, 0 );
858 }
A TCP connection.
Definition: tcp.c:33
struct retry_timer wait
Shutdown (TIME_WAIT) timer.
Definition: tcp.c:120
unsigned int tcp_state
Current TCP state.
Definition: tcp.c:53
uint32_t snd_seq
Current sequence number.
Definition: tcp.c:63
#define DBGC(...)
Definition: compiler.h:505
A timer.
Definition: timer.h:28
static void tcp_close(struct tcp_connection *tcp, int rc)
Close TCP connection.
Definition: tcp.c:349
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
static const char * tcp_state(int state)
Name TCP state.
Definition: tcp.c:196
#define TCP_TIME_WAIT
TIME_WAIT.
Definition: tcp.h:278
uint32_t snd_sent
Unacknowledged sequence count.
Definition: tcp.c:68
uint32_t rcv_ack
Current acknowledgement number.
Definition: tcp.c:78
#define TCP_CLOSED
CLOSED.
Definition: tcp.h:202
static void tcp_dump_state(struct tcp_connection *tcp)
Dump TCP state transition.
Definition: tcp.c:218

References assert(), container_of, DBGC, tcp_connection::rcv_ack, tcp_connection::snd_sent, tcp_connection::snd_seq, tcp_close(), TCP_CLOSED, tcp_dump_state(), tcp_connection::tcp_state, tcp_state(), TCP_TIME_WAIT, and tcp_connection::wait.

Referenced by tcp_open().

◆ tcp_demux()

static struct tcp_connection * tcp_demux ( unsigned int  local_port)
static

Identify TCP connection by local port number.

Parameters
local_portLocal port
Return values
tcpTCP connection, or NULL

Definition at line 929 of file tcp.c.

929  {
930  struct tcp_connection *tcp;
931 
932  list_for_each_entry ( tcp, &tcp_conns, list ) {
933  if ( tcp->local_port == local_port )
934  return tcp;
935  }
936  return NULL;
937 }
A TCP connection.
Definition: tcp.c:33
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:420
unsigned int local_port
Local port.
Definition: tcp.c:48
struct list_head list
List of TCP connections.
Definition: tcp.c:37
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

References tcp_connection::list, list_for_each_entry, tcp_connection::local_port, and NULL.

Referenced by tcp_port_available(), and tcp_rx().

◆ tcp_rx_ack()

static int tcp_rx_ack ( struct tcp_connection tcp,
uint32_t  ack,
uint32_t  win 
)
static

Handle TCP received ACK.

Parameters
tcpTCP connection
ackACK value (in host-endian order)
winWIN value (in host-endian order)
Return values
rcReturn status code

Definition at line 1115 of file tcp.c.

1116  {
1117  uint32_t ack_len = ( ack - tcp->snd_seq );
1118  size_t len;
1119  unsigned int acked_flags;
1120 
1121  /* Check for out-of-range or old duplicate ACKs */
1122  if ( ack_len > tcp->snd_sent ) {
1123  DBGC ( tcp, "TCP %p received ACK for %08x..%08x, "
1124  "sent only %08x..%08x\n", tcp, tcp->snd_seq,
1125  ( tcp->snd_seq + ack_len ), tcp->snd_seq,
1126  ( tcp->snd_seq + tcp->snd_sent ) );
1127 
1128  if ( TCP_HAS_BEEN_ESTABLISHED ( tcp->tcp_state ) ) {
1129  /* Just ignore what might be old duplicate ACKs */
1130  return 0;
1131  } else {
1132  /* Send RST if an out-of-range ACK is received
1133  * on a not-yet-established connection, as per
1134  * RFC 793.
1135  */
1136  return -EINVAL;
1137  }
1138  }
1139 
1140  /* Update window size */
1141  tcp->snd_win = win;
1142 
1143  /* Hold off (or start) the keepalive timer, if applicable */
1144  if ( ! ( tcp->tcp_state & TCP_STATE_SENT ( TCP_FIN ) ) )
1146 
1147  /* Ignore ACKs that don't actually acknowledge any new data.
1148  * (In particular, do not stop the retransmission timer; this
1149  * avoids creating a sorceror's apprentice syndrome when a
1150  * duplicate ACK is received and we still have data in our
1151  * transmit queue.)
1152  */
1153  if ( ack_len == 0 )
1154  return 0;
1155 
1156  /* Stop the retransmission timer */
1157  stop_timer ( &tcp->timer );
1158 
1159  /* Determine acknowledged flags and data length */
1160  len = ack_len;
1161  acked_flags = ( TCP_FLAGS_SENDING ( tcp->tcp_state ) &
1162  ( TCP_SYN | TCP_FIN ) );
1163  if ( acked_flags ) {
1164  len--;
1165  pending_put ( &tcp->pending_flags );
1166  }
1167 
1168  /* Update SEQ and sent counters */
1169  tcp->snd_seq = ack;
1170  tcp->snd_sent = 0;
1171 
1172  /* Remove any acknowledged data from transmit queue */
1173  tcp_process_tx_queue ( tcp, len, NULL, 1 );
1174 
1175  /* Mark SYN/FIN as acknowledged if applicable. */
1176  if ( acked_flags )
1177  tcp->tcp_state |= TCP_STATE_ACKED ( acked_flags );
1178 
1179  /* Start sending FIN if we've had all possible data ACKed */
1180  if ( list_empty ( &tcp->tx_queue ) &&
1181  ( tcp->flags & TCP_XFER_CLOSED ) &&
1182  ! ( tcp->tcp_state & TCP_STATE_SENT ( TCP_FIN ) ) ) {
1183  tcp->tcp_state |= TCP_STATE_SENT ( TCP_FIN );
1184  pending_get ( &tcp->pending_flags );
1185  }
1186 
1187  return 0;
1188 }
#define EINVAL
Invalid argument.
Definition: errno.h:428
unsigned int tcp_state
Current TCP state.
Definition: tcp.c:53
struct retry_timer timer
Retransmission timer.
Definition: tcp.c:116
uint32_t snd_seq
Current sequence number.
Definition: tcp.c:63
#define TCP_FIN
Definition: tcp.h:163
struct retry_timer keepalive
Keepalive timer.
Definition: tcp.c:118
static size_t tcp_process_tx_queue(struct tcp_connection *tcp, size_t max_len, struct io_buffer *dest, int remove)
Process TCP transmit queue.
Definition: tcp.c:568
void pending_put(struct pending_operation *pending)
Mark an operation as no longer pending.
Definition: pending.c:58
#define DBGC(...)
Definition: compiler.h:505
unsigned int flags
Flags.
Definition: tcp.c:40
#define TCP_SYN
Definition: tcp.h:162
#define list_empty(list)
Test whether a list is empty.
Definition: list.h:136
struct list_head tx_queue
Transmit queue.
Definition: tcp.c:110
TCP data transfer interface has been closed.
Definition: tcp.c:131
#define TCP_STATE_SENT(flags)
TCP flags that have been sent in outgoing packets.
Definition: tcp.h:176
#define TCP_HAS_BEEN_ESTABLISHED(state)
Have ever been fully established.
Definition: tcp.h:306
uint32_t snd_sent
Unacknowledged sequence count.
Definition: tcp.c:68
unsigned int uint32_t
Definition: stdint.h:12
#define TCP_STATE_ACKED(flags)
TCP flags that have been acknowledged by the peer.
Definition: tcp.h:183
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition: retry.c:64
uint32_t snd_win
Send window.
Definition: tcp.c:73
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition: retry.c:117
uint32_t len
Length.
Definition: ena.h:14
#define TCP_FLAGS_SENDING(state)
TCP flags that are currently being sent in outgoing packets.
Definition: tcp.h:195
#define TCP_KEEPALIVE_DELAY
TCP keepalive period.
Definition: tcp.h:387
struct pending_operation pending_flags
Pending operations for SYN and FIN.
Definition: tcp.c:123
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
void pending_get(struct pending_operation *pending)
Mark an operation as pending.
Definition: pending.c:45

References DBGC, EINVAL, tcp_connection::flags, tcp_connection::keepalive, len, list_empty, NULL, tcp_connection::pending_flags, pending_get(), pending_put(), tcp_connection::snd_sent, tcp_connection::snd_seq, tcp_connection::snd_win, start_timer_fixed(), stop_timer(), TCP_FIN, TCP_FLAGS_SENDING, TCP_HAS_BEEN_ESTABLISHED, TCP_KEEPALIVE_DELAY, tcp_process_tx_queue(), tcp_connection::tcp_state, TCP_STATE_ACKED, TCP_STATE_SENT, TCP_SYN, TCP_XFER_CLOSED, tcp_connection::timer, and tcp_connection::tx_queue.

Referenced by tcp_close(), and tcp_rx().

◆ tcp_state()

static const char* tcp_state ( int  state)
inlinestatic

Name TCP state.

Parameters
stateTCP state
Return values
nameName of TCP state

Definition at line 196 of file tcp.c.

196  {
197  switch ( state ) {
198  case TCP_CLOSED: return "CLOSED";
199  case TCP_LISTEN: return "LISTEN";
200  case TCP_SYN_SENT: return "SYN_SENT";
201  case TCP_SYN_RCVD: return "SYN_RCVD";
202  case TCP_ESTABLISHED: return "ESTABLISHED";
203  case TCP_FIN_WAIT_1: return "FIN_WAIT_1";
204  case TCP_FIN_WAIT_2: return "FIN_WAIT_2";
205  case TCP_CLOSING_OR_LAST_ACK: return "CLOSING/LAST_ACK";
206  case TCP_TIME_WAIT: return "TIME_WAIT";
207  case TCP_CLOSE_WAIT: return "CLOSE_WAIT";
208  default: return "INVALID";
209  }
210 }
uint8_t state
State.
Definition: eth_slow.h:47
#define TCP_SYN_SENT
SYN_SENT.
Definition: tcp.h:215
#define TCP_LISTEN
LISTEN.
Definition: tcp.h:209
#define TCP_FIN_WAIT_1
FIN_WAIT_1.
Definition: tcp.h:246
#define TCP_CLOSE_WAIT
CLOSE_WAIT.
Definition: tcp.h:287
#define TCP_ESTABLISHED
ESTABLISHED.
Definition: tcp.h:228
#define TCP_TIME_WAIT
TIME_WAIT.
Definition: tcp.h:278
#define TCP_CLOSING_OR_LAST_ACK
CLOSING / LAST_ACK.
Definition: tcp.h:268
#define TCP_SYN_RCVD
SYN_RCVD.
Definition: tcp.h:221
#define TCP_CLOSED
CLOSED.
Definition: tcp.h:202
#define TCP_FIN_WAIT_2
FIN_WAIT_2.
Definition: tcp.h:255

References state, TCP_CLOSE_WAIT, TCP_CLOSED, TCP_CLOSING_OR_LAST_ACK, TCP_ESTABLISHED, TCP_FIN_WAIT_1, TCP_FIN_WAIT_2, TCP_LISTEN, TCP_SYN_RCVD, TCP_SYN_SENT, and TCP_TIME_WAIT.

Referenced by tcp_dump_state(), tcp_expired(), and tcp_wait_expired().

◆ tcp_dump_state()

static void tcp_dump_state ( struct tcp_connection tcp)
inlinestatic

Dump TCP state transition.

Parameters
tcpTCP connection

Definition at line 218 of file tcp.c.

218  {
219 
220  if ( tcp->tcp_state != tcp->prev_tcp_state ) {
221  DBGC ( tcp, "TCP %p transitioned from %s to %s\n", tcp,
222  tcp_state ( tcp->prev_tcp_state ),
223  tcp_state ( tcp->tcp_state ) );
224  }
225  tcp->prev_tcp_state = tcp->tcp_state;
226 }
unsigned int tcp_state
Current TCP state.
Definition: tcp.c:53
#define DBGC(...)
Definition: compiler.h:505
unsigned int prev_tcp_state
Previous TCP state.
Definition: tcp.c:58
static const char * tcp_state(int state)
Name TCP state.
Definition: tcp.c:196

References DBGC, tcp_connection::prev_tcp_state, tcp_connection::tcp_state, and tcp_state().

Referenced by tcp_close(), tcp_expired(), tcp_open(), tcp_rx(), tcp_rx_rst(), tcp_shutdown(), and tcp_wait_expired().

◆ tcp_dump_flags()

static void tcp_dump_flags ( struct tcp_connection tcp,
unsigned int  flags 
)
inlinestatic

Dump TCP flags.

Parameters
flagsTCP flags

Definition at line 234 of file tcp.c.

234  {
235  if ( flags & TCP_RST )
236  DBGC2 ( tcp, " RST" );
237  if ( flags & TCP_SYN )
238  DBGC2 ( tcp, " SYN" );
239  if ( flags & TCP_PSH )
240  DBGC2 ( tcp, " PSH" );
241  if ( flags & TCP_FIN )
242  DBGC2 ( tcp, " FIN" );
243  if ( flags & TCP_ACK )
244  DBGC2 ( tcp, " ACK" );
245 }
#define TCP_FIN
Definition: tcp.h:163
#define TCP_ACK
Definition: tcp.h:159
#define TCP_PSH
Definition: tcp.h:160
#define TCP_RST
Definition: tcp.h:161
#define TCP_SYN
Definition: tcp.h:162
#define DBGC2(...)
Definition: compiler.h:522
uint8_t flags
Flags.
Definition: ena.h:18

References DBGC2, flags, TCP_ACK, TCP_FIN, TCP_PSH, TCP_RST, and TCP_SYN.

Referenced by tcp_rx(), tcp_xmit_reset(), and tcp_xmit_sack().

◆ tcp_port_available()

static int tcp_port_available ( int  port)
static

Check if local TCP port is available.

Parameters
portLocal port number
Return values
portLocal port number, or negative error

Definition at line 260 of file tcp.c.

260  {
261 
262  return ( tcp_demux ( port ) ? -EADDRINUSE : port );
263 }
#define EADDRINUSE
Address already in use.
Definition: errno.h:303
u8 port
Port number.
Definition: CIB_PRM.h:31
static struct tcp_connection * tcp_demux(unsigned int local_port)
Identify TCP connection by local port number.
Definition: tcp.c:929

References EADDRINUSE, port, and tcp_demux().

Referenced by tcp_open().

◆ tcp_open()

static int tcp_open ( struct interface xfer,
struct sockaddr peer,
struct sockaddr local 
)
static

Open a TCP connection.

Parameters
xferData transfer interface
peerPeer socket address
localLocal socket address, or NULL
Return values
rcReturn status code

Definition at line 273 of file tcp.c.

274  {
275  struct sockaddr_tcpip *st_peer = ( struct sockaddr_tcpip * ) peer;
276  struct sockaddr_tcpip *st_local = ( struct sockaddr_tcpip * ) local;
277  struct tcp_connection *tcp;
278  size_t mtu;
279  int port;
280  int rc;
281 
282  /* Allocate and initialise structure */
283  tcp = zalloc ( sizeof ( *tcp ) );
284  if ( ! tcp )
285  return -ENOMEM;
286  DBGC ( tcp, "TCP %p allocated\n", tcp );
287  ref_init ( &tcp->refcnt, NULL );
288  intf_init ( &tcp->xfer, &tcp_xfer_desc, &tcp->refcnt );
290  timer_init ( &tcp->timer, tcp_expired, &tcp->refcnt );
291  timer_init ( &tcp->keepalive, tcp_keepalive_expired, &tcp->refcnt );
292  timer_init ( &tcp->wait, tcp_wait_expired, &tcp->refcnt );
293  tcp->prev_tcp_state = TCP_CLOSED;
294  tcp->tcp_state = TCP_STATE_SENT ( TCP_SYN );
295  tcp_dump_state ( tcp );
296  tcp->snd_seq = random();
297  INIT_LIST_HEAD ( &tcp->tx_queue );
298  INIT_LIST_HEAD ( &tcp->rx_queue );
299  memcpy ( &tcp->peer, st_peer, sizeof ( tcp->peer ) );
300 
301  /* Calculate MSS */
302  mtu = tcpip_mtu ( &tcp->peer );
303  if ( ! mtu ) {
304  DBGC ( tcp, "TCP %p has no route to %s\n",
305  tcp, sock_ntoa ( peer ) );
306  rc = -ENETUNREACH;
307  goto err;
308  }
309  tcp->mss = ( mtu - sizeof ( struct tcp_header ) );
310 
311  /* Bind to local port */
312  port = tcpip_bind ( st_local, tcp_port_available );
313  if ( port < 0 ) {
314  rc = port;
315  DBGC ( tcp, "TCP %p could not bind: %s\n",
316  tcp, strerror ( rc ) );
317  goto err;
318  }
319  tcp->local_port = port;
320  DBGC ( tcp, "TCP %p bound to port %d\n", tcp, tcp->local_port );
321 
322  /* Start timer to initiate SYN */
323  start_timer_nodelay ( &tcp->timer );
324 
325  /* Add a pending operation for the SYN */
326  pending_get ( &tcp->pending_flags );
327 
328  /* Attach parent interface, transfer reference to connection
329  * list and return
330  */
331  intf_plug_plug ( &tcp->xfer, xfer );
332  list_add ( &tcp->list, &tcp_conns );
333  return 0;
334 
335  err:
336  ref_put ( &tcp->refcnt );
337  return rc;
338 }
A TCP connection.
Definition: tcp.c:33
struct retry_timer wait
Shutdown (TIME_WAIT) timer.
Definition: tcp.c:120
TCP/IP socket address.
Definition: tcpip.h:75
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct list_head rx_queue
Receive queue.
Definition: tcp.c:112
size_t tcpip_mtu(struct sockaddr_tcpip *st_dest)
Determine maximum transmission unit.
Definition: tcpip.c:131
unsigned int tcp_state
Current TCP state.
Definition: tcp.c:53
static void start_timer_nodelay(struct retry_timer *timer)
Start timer with no delay.
Definition: retry.h:99
static void tcp_keepalive_expired(struct retry_timer *timer, int over)
Keepalive timer expired.
Definition: tcp.c:819
struct retry_timer timer
Retransmission timer.
Definition: tcp.c:116
uint32_t snd_seq
Current sequence number.
Definition: tcp.c:63
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:69
static int tcp_port_available(int port)
Check if local TCP port is available.
Definition: tcp.c:260
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:64
struct retry_timer keepalive
Keepalive timer.
Definition: tcp.c:118
struct refcnt refcnt
Reference counter.
Definition: tcp.c:35
#define DBGC(...)
Definition: compiler.h:505
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition: interface.c:102
unsigned int prev_tcp_state
Previous TCP state.
Definition: tcp.c:58
int tcpip_bind(struct sockaddr_tcpip *st_local, int(*available)(int port))
Bind to local TCP/IP port.
Definition: tcpip.c:214
#define TCP_SYN
Definition: tcp.h:162
struct list_head tx_queue
Transmit queue.
Definition: tcp.c:110
#define ENOMEM
Not enough space.
Definition: errno.h:534
void * memcpy(void *dest, const void *src, size_t len) __nonnull
u8 port
Port number.
Definition: CIB_PRM.h:31
A TCP header.
Definition: tcp.h:19
unsigned int local_port
Local port.
Definition: tcp.c:48
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
static void tcp_wait_expired(struct retry_timer *timer, int over)
Shutdown timer expired.
Definition: tcp.c:845
#define TCP_STATE_SENT(flags)
TCP flags that have been sent in outgoing packets.
Definition: tcp.h:176
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition: random.c:30
static void process_init_stopped(struct process *process, struct process_descriptor *desc, struct refcnt *refcnt)
Initialise process without adding to process list.
Definition: process.h:145
static void tcp_expired(struct retry_timer *timer, int over)
Retransmission timer expired.
Definition: tcp.c:785
static struct process_descriptor tcp_process_desc
TCP process descriptor.
Definition: tcp.c:180
size_t mss
Maximum segment size.
Definition: tcp.c:50
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition: list.h:45
struct process process
Transmission process.
Definition: tcp.c:114
const char * sock_ntoa(struct sockaddr *sa)
Transcribe socket address.
Definition: socket.c:42
uint32_t mtu
Maximum MTU.
Definition: ena.h:28
struct list_head list
List of TCP connections.
Definition: tcp.c:37
struct interface xfer
Data transfer interface.
Definition: tcp.c:43
static struct interface_descriptor tcp_xfer_desc
TCP data transfer interface descriptor.
Definition: tcp.c:181
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition: interface.h:173
#define ENETUNREACH
Network unreachable.
Definition: errno.h:488
struct pending_operation pending_flags
Pending operations for SYN and FIN.
Definition: tcp.c:123
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
#define TCP_CLOSED
CLOSED.
Definition: tcp.h:202
void pending_get(struct pending_operation *pending)
Mark an operation as pending.
Definition: pending.c:45
static void tcp_dump_state(struct tcp_connection *tcp)
Dump TCP state transition.
Definition: tcp.c:218
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:106
struct sockaddr_tcpip peer
Remote socket address.
Definition: tcp.c:46

References DBGC, ENETUNREACH, ENOMEM, INIT_LIST_HEAD, intf_init(), intf_plug_plug(), tcp_connection::keepalive, tcp_connection::list, list_add, tcp_connection::local_port, memcpy(), tcp_connection::mss, mtu, NULL, tcp_connection::peer, tcp_connection::pending_flags, pending_get(), port, tcp_connection::prev_tcp_state, tcp_connection::process, process_init_stopped(), random(), rc, ref_init, ref_put, tcp_connection::refcnt, tcp_connection::rx_queue, tcp_connection::snd_seq, sock_ntoa(), start_timer_nodelay(), strerror(), TCP_CLOSED, tcp_dump_state(), tcp_expired(), tcp_keepalive_expired(), tcp_port_available(), tcp_process_desc, tcp_connection::tcp_state, TCP_STATE_SENT, TCP_SYN, tcp_wait_expired(), tcp_xfer_desc, tcpip_bind(), tcpip_mtu(), tcp_connection::timer, tcp_connection::tx_queue, tcp_connection::wait, tcp_connection::xfer, and zalloc().

◆ tcp_close()

static void tcp_close ( struct tcp_connection tcp,
int  rc 
)
static

Close TCP connection.

Parameters
tcpTCP connection
rcReason for close

Closes the data transfer interface. If the TCP state machine is in a suitable state, the connection will be deleted.

Definition at line 349 of file tcp.c.

349  {
350  struct io_buffer *iobuf;
351  struct io_buffer *tmp;
352 
353  /* Close data transfer interface */
354  intf_shutdown ( &tcp->xfer, rc );
355  tcp->flags |= TCP_XFER_CLOSED;
356 
357  /* If we are in CLOSED, or have otherwise not yet received a
358  * SYN (i.e. we are in LISTEN or SYN_SENT), just delete the
359  * connection.
360  */
361  if ( ! ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) ) {
362 
363  /* Transition to CLOSED for the sake of debugging messages */
364  tcp->tcp_state = TCP_CLOSED;
365  tcp_dump_state ( tcp );
366 
367  /* Free any unprocessed I/O buffers */
368  list_for_each_entry_safe ( iobuf, tmp, &tcp->rx_queue, list ) {
369  list_del ( &iobuf->list );
370  free_iob ( iobuf );
371  }
372 
373  /* Free any unsent I/O buffers */
374  list_for_each_entry_safe ( iobuf, tmp, &tcp->tx_queue, list ) {
375  list_del ( &iobuf->list );
376  free_iob ( iobuf );
377  pending_put ( &tcp->pending_data );
378  }
379  assert ( ! is_pending ( &tcp->pending_data ) );
380 
381  /* Remove pending operations for SYN and FIN, if applicable */
382  pending_put ( &tcp->pending_flags );
383  pending_put ( &tcp->pending_flags );
384 
385  /* Remove from list and drop reference */
386  process_del ( &tcp->process );
387  stop_timer ( &tcp->timer );
388  stop_timer ( &tcp->keepalive );
389  stop_timer ( &tcp->wait );
390  list_del ( &tcp->list );
391  ref_put ( &tcp->refcnt );
392  DBGC ( tcp, "TCP %p connection deleted\n", tcp );
393  return;
394  }
395 
396  /* If we have not had our SYN acknowledged (i.e. we are in
397  * SYN_RCVD), pretend that it has been acknowledged so that we
398  * can send a FIN without breaking things.
399  */
400  if ( ! ( tcp->tcp_state & TCP_STATE_ACKED ( TCP_SYN ) ) )
401  tcp_rx_ack ( tcp, ( tcp->snd_seq + 1 ), 0 );
402 
403  /* Stop keepalive timer */
404  stop_timer ( &tcp->keepalive );
405 
406  /* If we have no data remaining to send, start sending FIN */
407  if ( list_empty ( &tcp->tx_queue ) &&
408  ! ( tcp->tcp_state & TCP_STATE_SENT ( TCP_FIN ) ) ) {
409 
410  tcp->tcp_state |= TCP_STATE_SENT ( TCP_FIN );
411  tcp_dump_state ( tcp );
412  process_add ( &tcp->process );
413 
414  /* Add a pending operation for the FIN */
415  pending_get ( &tcp->pending_flags );
416  }
417 }
struct retry_timer wait
Shutdown (TIME_WAIT) timer.
Definition: tcp.c:120
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct list_head rx_queue
Receive queue.
Definition: tcp.c:112
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition: interface.c:273
unsigned int tcp_state
Current TCP state.
Definition: tcp.c:53
struct retry_timer timer
Retransmission timer.
Definition: tcp.c:116
uint32_t snd_seq
Current sequence number.
Definition: tcp.c:63
#define TCP_FIN
Definition: tcp.h:163
struct retry_timer keepalive
Keepalive timer.
Definition: tcp.c:118
struct refcnt refcnt
Reference counter.
Definition: tcp.c:35
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:145
void pending_put(struct pending_operation *pending)
Mark an operation as no longer pending.
Definition: pending.c:58
#define DBGC(...)
Definition: compiler.h:505
struct pending_operation pending_data
Pending operations for transmit queue.
Definition: tcp.c:125
void process_del(struct process *process)
Remove process from process list.
Definition: process.c:79
unsigned int flags
Flags.
Definition: tcp.c:40
#define TCP_SYN
Definition: tcp.h:162
#define list_empty(list)
Test whether a list is empty.
Definition: list.h:136
struct list_head tx_queue
Transmit queue.
Definition: tcp.c:110
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
TCP data transfer interface has been closed.
Definition: tcp.c:131
static int is_pending(struct pending_operation *pending)
Check if an operation is pending.
Definition: pending.h:24
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition: list.h:447
void process_add(struct process *process)
Add process to process list.
Definition: process.c:59
#define TCP_STATE_RCVD(flags)
TCP flags that have been received from the peer.
Definition: tcp.h:191
#define TCP_STATE_SENT(flags)
TCP flags that have been sent in outgoing packets.
Definition: tcp.h:176
uint8_t * tmp
Definition: entropy.h:156
#define TCP_STATE_ACKED(flags)
TCP flags that have been acknowledged by the peer.
Definition: tcp.h:183
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition: retry.c:117
struct process process
Transmission process.
Definition: tcp.c:114
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:39
struct list_head list
List of TCP connections.
Definition: tcp.c:37
struct interface xfer
Data transfer interface.
Definition: tcp.c:43
static int tcp_rx_ack(struct tcp_connection *tcp, uint32_t ack, uint32_t win)
Handle TCP received ACK.
Definition: tcp.c:1115
struct pending_operation pending_flags
Pending operations for SYN and FIN.
Definition: tcp.c:123
#define TCP_CLOSED
CLOSED.
Definition: tcp.h:202
void pending_get(struct pending_operation *pending)
Mark an operation as pending.
Definition: pending.c:45
static void tcp_dump_state(struct tcp_connection *tcp)
Dump TCP state transition.
Definition: tcp.c:218
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:106
A persistent I/O buffer.
Definition: iobuf.h:32

References assert(), DBGC, tcp_connection::flags, free_iob(), intf_shutdown(), is_pending(), tcp_connection::keepalive, io_buffer::list, tcp_connection::list, list_del, list_empty, list_for_each_entry_safe, tcp_connection::pending_data, tcp_connection::pending_flags, pending_get(), pending_put(), tcp_connection::process, process_add(), process_del(), rc, ref_put, tcp_connection::refcnt, tcp_connection::rx_queue, tcp_connection::snd_seq, stop_timer(), TCP_CLOSED, tcp_dump_state(), TCP_FIN, tcp_rx_ack(), tcp_connection::tcp_state, TCP_STATE_ACKED, TCP_STATE_RCVD, TCP_STATE_SENT, TCP_SYN, TCP_XFER_CLOSED, tcp_connection::timer, tmp, tcp_connection::tx_queue, tcp_connection::wait, and tcp_connection::xfer.

Referenced by tcp_expired(), tcp_rx_fin(), tcp_rx_rst(), tcp_shutdown(), tcp_wait_expired(), and tcp_xfer_close().

◆ tcp_xmit_win()

static size_t tcp_xmit_win ( struct tcp_connection tcp)
static

Calculate transmission window.

Parameters
tcpTCP connection
Return values
lenMaximum length that can be sent in a single packet

Definition at line 432 of file tcp.c.

432  {
433  size_t len;
434 
435  /* Not ready if we're not in a suitable connection state */
436  if ( ! TCP_CAN_SEND_DATA ( tcp->tcp_state ) )
437  return 0;
438 
439  /* Length is the minimum of the receiver's window and the path MTU */
440  len = tcp->snd_win;
441  if ( len > TCP_PATH_MTU )
442  len = TCP_PATH_MTU;
443 
444  return len;
445 }
unsigned int tcp_state
Current TCP state.
Definition: tcp.c:53
#define TCP_CAN_SEND_DATA(state)
Can send data in current state.
Definition: tcp.h:296
uint32_t snd_win
Send window.
Definition: tcp.c:73
uint32_t len
Length.
Definition: ena.h:14
#define TCP_PATH_MTU
Path MTU.
Definition: tcp.h:372

References len, tcp_connection::snd_win, TCP_CAN_SEND_DATA, TCP_PATH_MTU, and tcp_connection::tcp_state.

Referenced by tcp_xfer_window(), and tcp_xmit_sack().

◆ tcp_xfer_window()

static size_t tcp_xfer_window ( struct tcp_connection tcp)
static

Check data-transfer flow control window.

Parameters
tcpTCP connection
Return values
lenLength of window

Definition at line 453 of file tcp.c.

453  {
454 
455  /* Not ready if data queue is non-empty. This imposes a limit
456  * of only one unACKed packet in the TX queue at any time; we
457  * do this to conserve memory usage.
458  */
459  if ( ! list_empty ( &tcp->tx_queue ) )
460  return 0;
461 
462  /* Return TCP window length */
463  return tcp_xmit_win ( tcp );
464 }
#define list_empty(list)
Test whether a list is empty.
Definition: list.h:136
struct list_head tx_queue
Transmit queue.
Definition: tcp.c:110
static size_t tcp_xmit_win(struct tcp_connection *tcp)
Calculate transmission window.
Definition: tcp.c:432

References list_empty, tcp_xmit_win(), and tcp_connection::tx_queue.

Referenced by tcp_rx().

◆ tcp_sack_block()

static uint32_t tcp_sack_block ( struct tcp_connection tcp,
uint32_t  seq,
struct tcp_sack_block sack 
)
static

Find selective acknowledgement block.

Parameters
tcpTCP connection
seqSEQ value in SACK block (in host-endian order)
sackSACK block to fill in (in host-endian order)
Return values
lenLength of SACK block

Definition at line 474 of file tcp.c.

475  {
476  struct io_buffer *iobuf;
477  struct tcp_rx_queued_header *tcpqhdr;
478  uint32_t left = tcp->rcv_ack;
479  uint32_t right = left;
480 
481  /* Find highest block which does not start after SEQ */
482  list_for_each_entry ( iobuf, &tcp->rx_queue, list ) {
483  tcpqhdr = iobuf->data;
484  if ( tcp_cmp ( tcpqhdr->seq, right ) > 0 ) {
485  if ( tcp_cmp ( tcpqhdr->seq, seq ) > 0 )
486  break;
487  left = tcpqhdr->seq;
488  }
489  if ( tcp_cmp ( tcpqhdr->nxt, right ) > 0 )
490  right = tcpqhdr->nxt;
491  }
492 
493  /* Fail if this block does not contain SEQ */
494  if ( tcp_cmp ( right, seq ) < 0 )
495  return 0;
496 
497  /* Populate SACK block */
498  sack->left = left;
499  sack->right = right;
500  return ( right - left );
501 }
struct list_head rx_queue
Receive queue.
Definition: tcp.c:112
u16 seq
802.11 Sequence Control field
Definition: ieee80211.h:19
uint32_t right
Definition: tcp.h:106
uint32_t seq
SEQ value, in host-endian order.
Definition: tcp.c:151
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:420
uint32_t nxt
Next SEQ value, in host-endian order.
Definition: tcp.c:153
unsigned int uint32_t
Definition: stdint.h:12
uint32_t left
Definition: tcp.h:105
void * data
Start of data.
Definition: iobuf.h:44
TCP internal header.
Definition: tcp.c:145
uint32_t rcv_ack
Current acknowledgement number.
Definition: tcp.c:78
static int32_t tcp_cmp(uint32_t seq1, uint32_t seq2)
Compare TCP sequence numbers.
Definition: tcp.h:412
A persistent I/O buffer.
Definition: iobuf.h:32

References io_buffer::data, tcp_sack_block::left, list_for_each_entry, tcp_rx_queued_header::nxt, tcp_connection::rcv_ack, tcp_sack_block::right, tcp_connection::rx_queue, seq, tcp_rx_queued_header::seq, and tcp_cmp().

Referenced by tcp_sack().

◆ tcp_sack()

static unsigned int tcp_sack ( struct tcp_connection tcp,
uint32_t  seq 
)
static

Update TCP selective acknowledgement list.

Parameters
tcpTCP connection
seqSEQ value in first SACK block (in host-endian order)
Return values
countNumber of SACK blocks

Definition at line 510 of file tcp.c.

510  {
511  struct tcp_sack_block sack[TCP_SACK_MAX];
512  unsigned int old = 0;
513  unsigned int new = 0;
514  unsigned int i;
515  uint32_t len;
516 
517  /* Populate first new SACK block */
518  len = tcp_sack_block ( tcp, seq, &sack[0] );
519  if ( len )
520  new++;
521 
522  /* Populate remaining new SACK blocks based on old SACK blocks */
523  for ( old = 0 ; old < TCP_SACK_MAX ; old++ ) {
524 
525  /* Stop if we run out of space in the new list */
526  if ( new == TCP_SACK_MAX )
527  break;
528 
529  /* Skip empty old SACK blocks */
530  if ( tcp->sack[old].left == tcp->sack[old].right )
531  continue;
532 
533  /* Populate new SACK block */
534  len = tcp_sack_block ( tcp, tcp->sack[old].left, &sack[new] );
535  if ( len == 0 )
536  continue;
537 
538  /* Eliminate duplicates */
539  for ( i = 0 ; i < new ; i++ ) {
540  if ( sack[i].left == sack[new].left ) {
541  new--;
542  break;
543  }
544  }
545  new++;
546  }
547 
548  /* Update SACK list */
549  memset ( tcp->sack, 0, sizeof ( tcp->sack ) );
550  memcpy ( tcp->sack, sack, ( new * sizeof ( tcp->sack[0] ) ) );
551  return new;
552 }
int old
Definition: bitops.h:64
u16 seq
802.11 Sequence Control field
Definition: ieee80211.h:19
uint32_t right
Definition: tcp.h:106
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define TCP_SACK_MAX
Maximum number of selective acknowledgement blocks.
Definition: tcp.h:113
struct tcp_sack_block sack[TCP_SACK_MAX]
Selective acknowledgement list (in host-endian order)
Definition: tcp.c:107
static uint32_t tcp_sack_block(struct tcp_connection *tcp, uint32_t seq, struct tcp_sack_block *sack)
Find selective acknowledgement block.
Definition: tcp.c:474
unsigned int uint32_t
Definition: stdint.h:12
uint32_t len
Length.
Definition: ena.h:14
uint32_t left
Definition: tcp.h:105
TCP selective acknowledgement block.
Definition: tcp.h:104
void * memset(void *dest, int character, size_t len) __nonnull

References tcp_sack_block::left, len, memcpy(), memset(), old, tcp_sack_block::right, tcp_connection::sack, seq, tcp_sack_block(), and TCP_SACK_MAX.

Referenced by tcp_xmit_sack().

◆ tcp_process_tx_queue()

static size_t tcp_process_tx_queue ( struct tcp_connection tcp,
size_t  max_len,
struct io_buffer dest,
int  remove 
)
static

Process TCP transmit queue.

Parameters
tcpTCP connection
max_lenMaximum length to process
destI/O buffer to fill with data, or NULL
removeRemove data from queue
Return values
lenLength of data processed

This processes at most max_len bytes from the TCP connection's transmit queue. Data will be copied into the dest I/O buffer (if provided) and, if remove is true, removed from the transmit queue.

Definition at line 568 of file tcp.c.

569  {
570  struct io_buffer *iobuf;
571  struct io_buffer *tmp;
572  size_t frag_len;
573  size_t len = 0;
574 
575  list_for_each_entry_safe ( iobuf, tmp, &tcp->tx_queue, list ) {
576  frag_len = iob_len ( iobuf );
577  if ( frag_len > max_len )
578  frag_len = max_len;
579  if ( dest ) {
580  memcpy ( iob_put ( dest, frag_len ), iobuf->data,
581  frag_len );
582  }
583  if ( remove ) {
584  iob_pull ( iobuf, frag_len );
585  if ( ! iob_len ( iobuf ) ) {
586  list_del ( &iobuf->list );
587  free_iob ( iobuf );
588  pending_put ( &tcp->pending_data );
589  }
590  }
591  len += frag_len;
592  max_len -= frag_len;
593  }
594  return len;
595 }
#define iob_pull(iobuf, len)
Definition: iobuf.h:98
#define iob_put(iobuf, len)
Definition: iobuf.h:116
static void size_t size_t max_len
Definition: entropy.h:153
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:145
void pending_put(struct pending_operation *pending)
Mark an operation as no longer pending.
Definition: pending.c:58
struct pending_operation pending_data
Pending operations for transmit queue.
Definition: tcp.c:125
struct list_head tx_queue
Transmit queue.
Definition: tcp.c:110
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
void * memcpy(void *dest, const void *src, size_t len) __nonnull
static void * dest
Definition: strings.h:176
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition: list.h:447
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:151
uint8_t * tmp
Definition: entropy.h:156
static struct xen_remove_from_physmap * remove
Definition: xenmem.h:39
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:39
uint32_t len
Length.
Definition: ena.h:14
void * data
Start of data.
Definition: iobuf.h:44
A persistent I/O buffer.
Definition: iobuf.h:32

References io_buffer::data, dest, free_iob(), iob_len(), iob_pull, iob_put, len, io_buffer::list, list_del, list_for_each_entry_safe, max_len, memcpy(), tcp_connection::pending_data, pending_put(), remove, tmp, and tcp_connection::tx_queue.

Referenced by tcp_rx_ack(), and tcp_xmit_sack().

◆ tcp_xmit_sack()

static void tcp_xmit_sack ( struct tcp_connection tcp,
uint32_t  sack_seq 
)
static

Transmit any outstanding data (with selective acknowledgement)

Parameters
tcpTCP connection
sack_seqSEQ for first selective acknowledgement (if any)

Transmits any outstanding data on the connection.

Note that even if an error is returned, the retransmission timer will have been started if necessary, and so the stack will eventually attempt to retransmit the failed packet.

Definition at line 609 of file tcp.c.

609  {
610  struct io_buffer *iobuf;
611  struct tcp_header *tcphdr;
612  struct tcp_mss_option *mssopt;
617  struct tcp_sack_block *sack;
618  void *payload;
619  unsigned int flags;
620  unsigned int sack_count;
621  unsigned int i;
622  size_t len = 0;
623  size_t sack_len;
624  uint32_t seq_len;
625  uint32_t max_rcv_win;
626  uint32_t max_representable_win;
627  int rc;
628 
629  /* Start profiling */
630  profile_start ( &tcp_tx_profiler );
631 
632  /* If retransmission timer is already running, do nothing */
633  if ( timer_running ( &tcp->timer ) )
634  return;
635 
636  /* Calculate both the actual (payload) and sequence space
637  * lengths that we wish to transmit.
638  */
639  if ( TCP_CAN_SEND_DATA ( tcp->tcp_state ) ) {
640  len = tcp_process_tx_queue ( tcp, tcp_xmit_win ( tcp ),
641  NULL, 0 );
642  }
643  seq_len = len;
644  flags = TCP_FLAGS_SENDING ( tcp->tcp_state );
645  if ( flags & ( TCP_SYN | TCP_FIN ) ) {
646  /* SYN or FIN consume one byte, and we can never send both */
647  assert ( ! ( ( flags & TCP_SYN ) && ( flags & TCP_FIN ) ) );
648  seq_len++;
649  }
650  tcp->snd_sent = seq_len;
651 
652  /* If we have nothing to transmit, stop now */
653  if ( ( seq_len == 0 ) && ! ( tcp->flags & TCP_ACK_PENDING ) )
654  return;
655 
656  /* If we are transmitting anything that requires
657  * acknowledgement (i.e. consumes sequence space), start the
658  * retransmission timer. Do this before attempting to
659  * allocate the I/O buffer, in case allocation itself fails.
660  */
661  if ( seq_len )
662  start_timer ( &tcp->timer );
663 
664  /* Allocate I/O buffer */
665  iobuf = alloc_iob ( len + TCP_MAX_HEADER_LEN );
666  if ( ! iobuf ) {
667  DBGC ( tcp, "TCP %p could not allocate iobuf for %08x..%08x "
668  "%08x\n", tcp, tcp->snd_seq, ( tcp->snd_seq + seq_len ),
669  tcp->rcv_ack );
670  return;
671  }
672  iob_reserve ( iobuf, TCP_MAX_HEADER_LEN );
673 
674  /* Fill data payload from transmit queue */
675  tcp_process_tx_queue ( tcp, len, iobuf, 0 );
676 
677  /* Expand receive window if possible */
678  max_rcv_win = xfer_window ( &tcp->xfer );
679  if ( max_rcv_win > TCP_MAX_WINDOW_SIZE )
680  max_rcv_win = TCP_MAX_WINDOW_SIZE;
681  max_representable_win = ( 0xffff << tcp->rcv_win_scale );
682  if ( max_rcv_win > max_representable_win )
683  max_rcv_win = max_representable_win;
684  max_rcv_win &= ~0x03; /* Keep everything dword-aligned */
685  if ( tcp->rcv_win < max_rcv_win )
686  tcp->rcv_win = max_rcv_win;
687 
688  /* Fill up the TCP header */
689  payload = iobuf->data;
690  if ( flags & TCP_SYN ) {
691  mssopt = iob_push ( iobuf, sizeof ( *mssopt ) );
692  mssopt->kind = TCP_OPTION_MSS;
693  mssopt->length = sizeof ( *mssopt );
694  mssopt->mss = htons ( tcp->mss );
695  wsopt = iob_push ( iobuf, sizeof ( *wsopt ) );
696  wsopt->nop = TCP_OPTION_NOP;
697  wsopt->wsopt.kind = TCP_OPTION_WS;
698  wsopt->wsopt.length = sizeof ( wsopt->wsopt );
700  spopt = iob_push ( iobuf, sizeof ( *spopt ) );
701  memset ( spopt->nop, TCP_OPTION_NOP, sizeof ( spopt->nop ) );
703  spopt->spopt.length = sizeof ( spopt->spopt );
704  }
705  if ( ( flags & TCP_SYN ) || ( tcp->flags & TCP_TS_ENABLED ) ) {
706  tsopt = iob_push ( iobuf, sizeof ( *tsopt ) );
707  memset ( tsopt->nop, TCP_OPTION_NOP, sizeof ( tsopt->nop ) );
708  tsopt->tsopt.kind = TCP_OPTION_TS;
709  tsopt->tsopt.length = sizeof ( tsopt->tsopt );
710  tsopt->tsopt.tsval = htonl ( currticks() );
711  tsopt->tsopt.tsecr = htonl ( tcp->ts_recent );
712  }
713  if ( ( tcp->flags & TCP_SACK_ENABLED ) &&
714  ( ! list_empty ( &tcp->rx_queue ) ) &&
715  ( ( sack_count = tcp_sack ( tcp, sack_seq ) ) != 0 ) ) {
716  sack_len = ( sack_count * sizeof ( *sack ) );
717  sackopt = iob_push ( iobuf, ( sizeof ( *sackopt ) + sack_len ));
718  memset ( sackopt->nop, TCP_OPTION_NOP, sizeof ( sackopt->nop ));
719  sackopt->sackopt.kind = TCP_OPTION_SACK;
720  sackopt->sackopt.length =
721  ( sizeof ( sackopt->sackopt ) + sack_len );
722  sack = ( ( ( void * ) sackopt ) + sizeof ( *sackopt ) );
723  for ( i = 0 ; i < sack_count ; i++, sack++ ) {
724  sack->left = htonl ( tcp->sack[i].left );
725  sack->right = htonl ( tcp->sack[i].right );
726  }
727  }
728  if ( len != 0 )
729  flags |= TCP_PSH;
730  tcphdr = iob_push ( iobuf, sizeof ( *tcphdr ) );
731  memset ( tcphdr, 0, sizeof ( *tcphdr ) );
732  tcphdr->src = htons ( tcp->local_port );
733  tcphdr->dest = tcp->peer.st_port;
734  tcphdr->seq = htonl ( tcp->snd_seq );
735  tcphdr->ack = htonl ( tcp->rcv_ack );
736  tcphdr->hlen = ( ( payload - iobuf->data ) << 2 );
737  tcphdr->flags = flags;
738  tcphdr->win = htons ( tcp->rcv_win >> tcp->rcv_win_scale );
739  tcphdr->csum = tcpip_chksum ( iobuf->data, iob_len ( iobuf ) );
740 
741  /* Dump header */
742  DBGC2 ( tcp, "TCP %p TX %d->%d %08x..%08x %08x %4zd",
743  tcp, ntohs ( tcphdr->src ), ntohs ( tcphdr->dest ),
744  ntohl ( tcphdr->seq ), ( ntohl ( tcphdr->seq ) + seq_len ),
745  ntohl ( tcphdr->ack ), len );
746  tcp_dump_flags ( tcp, tcphdr->flags );
747  DBGC2 ( tcp, "\n" );
748 
749  /* Transmit packet */
750  if ( ( rc = tcpip_tx ( iobuf, &tcp_protocol, NULL, &tcp->peer, NULL,
751  &tcphdr->csum ) ) != 0 ) {
752  DBGC ( tcp, "TCP %p could not transmit %08x..%08x %08x: %s\n",
753  tcp, tcp->snd_seq, ( tcp->snd_seq + tcp->snd_sent ),
754  tcp->rcv_ack, strerror ( rc ) );
755  return;
756  }
757 
758  /* Clear ACK-pending flag */
759  tcp->flags &= ~TCP_ACK_PENDING;
760 
761  profile_stop ( &tcp_tx_profiler );
762 }
#define TCP_OPTION_NOP
TCP option pad.
Definition: tcp.h:39
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct tcp_timestamp_option tsopt
Definition: tcp.h:135
Padded TCP window scale option (used for sending)
Definition: tcp.h:65
struct list_head rx_queue
Receive queue.
Definition: tcp.c:112
unsigned int tcp_state
Current TCP state.
Definition: tcp.c:53
uint8_t nop[2]
Definition: tcp.h:117
uint8_t kind
Definition: tcp.h:49
struct retry_timer timer
Retransmission timer.
Definition: tcp.c:116
Padded TCP selective acknowledgement option (used for sending)
Definition: tcp.h:116
uint32_t snd_seq
Current sequence number.
Definition: tcp.c:63
#define TCP_FIN
Definition: tcp.h:163
#define TCP_RX_WINDOW_SCALE
Advertised TCP window scale.
Definition: tcp.h:80
#define iob_push(iobuf, len)
Definition: iobuf.h:80
static size_t tcp_process_tx_queue(struct tcp_connection *tcp, size_t max_len, struct io_buffer *dest, int remove)
Process TCP transmit queue.
Definition: tcp.c:568
uint8_t kind
Definition: tcp.h:99
uint8_t length
Definition: tcp.h:100
#define TCP_PSH
Definition: tcp.h:160
#define DBGC(...)
Definition: compiler.h:505
uint32_t tsecr
Definition: tcp.h:129
TCP selective acknowledgement is enabled.
Definition: tcp.c:137
#define TCP_OPTION_MSS
Code for the TCP MSS option.
Definition: tcp.h:55
TCP timestamps are enabled.
Definition: tcp.c:133
#define ntohl(value)
Definition: byteswap.h:134
#define ntohs(value)
Definition: byteswap.h:136
static void profile_stop(struct profiler *profiler)
Stop profiling.
Definition: profile.h:171
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:128
#define htonl(value)
Definition: byteswap.h:133
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition: xfer.c:115
#define TCP_OPTION_TS
Code for the TCP timestamp option.
Definition: tcp.h:139
#define TCP_MAX_WINDOW_SIZE
Maxmimum advertised TCP window size.
Definition: tcp.h:356
unsigned int flags
Flags.
Definition: tcp.c:40
#define TCP_SYN
Definition: tcp.h:162
#define list_empty(list)
Test whether a list is empty.
Definition: list.h:136
uint32_t right
Definition: tcp.h:106
#define TCP_OPTION_WS
Code for the TCP window scale option.
Definition: tcp.h:71
uint32_t ts_recent
Most recent received timestamp that advanced the window.
Definition: tcp.c:94
#define TCP_OPTION_SACK_PERMITTED
Code for the TCP selective acknowledgement permitted option.
Definition: tcp.h:95
Padded TCP selective acknowledgement permitted option (used for sending)
Definition: tcp.h:89
#define TCP_OPTION_SACK
Code for the TCP selective acknowledgement option.
Definition: tcp.h:122
Padded TCP timestamp option (used for sending)
Definition: tcp.h:133
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
uint8_t length
Definition: tcp.h:60
A TCP header.
Definition: tcp.h:19
#define TCP_CAN_SEND_DATA(state)
Can send data in current state.
Definition: tcp.h:296
static void profile_start(struct profiler *profiler)
Start profiling.
Definition: profile.h:158
uint8_t rcv_win_scale
Receive window scale.
Definition: tcp.c:104
uint16_t st_port
TCP/IP port.
Definition: tcpip.h:81
unsigned int local_port
Local port.
Definition: tcp.c:48
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static size_t tcp_xmit_win(struct tcp_connection *tcp)
Calculate transmission window.
Definition: tcp.c:432
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:151
struct tcp_sack_block sack[TCP_SACK_MAX]
Selective acknowledgement list (in host-endian order)
Definition: tcp.c:107
int32_t seq
Definition: old_tcp.h:23
Definition: old_tcp.h:20
uint16_t src
Definition: old_tcp.h:21
uint32_t snd_sent
Unacknowledged sequence count.
Definition: tcp.c:68
unsigned int uint32_t
Definition: stdint.h:12
TCP MSS option.
Definition: tcp.h:48
uint8_t kind
Definition: tcp.h:126
size_t mss
Maximum segment size.
Definition: tcp.c:50
void start_timer(struct retry_timer *timer)
Start timer.
Definition: retry.c:93
#define iob_reserve(iobuf, len)
Definition: iobuf.h:63
struct tcp_sack_option sackopt
Definition: tcp.h:118
uint8_t length
Definition: tcp.h:127
uint32_t len
Length.
Definition: ena.h:14
#define DBGC2(...)
Definition: compiler.h:522
uint32_t left
Definition: tcp.h:105
#define TCP_FLAGS_SENDING(state)
TCP flags that are currently being sent in outgoing packets.
Definition: tcp.h:195
struct tcp_window_scale_option wsopt
Definition: tcp.h:14
void * data
Start of data.
Definition: iobuf.h:44
static void tcp_dump_flags(struct tcp_connection *tcp, unsigned int flags)
Dump TCP flags.
Definition: tcp.c:234
uint32_t rcv_ack
Current acknowledgement number.
Definition: tcp.c:78
uint16_t mss
Definition: tcp.h:51
static unsigned int tcp_sack(struct tcp_connection *tcp, uint32_t seq)
Update TCP selective acknowledgement list.
Definition: tcp.c:510
struct interface xfer
Data transfer interface.
Definition: tcp.c:43
TCP acknowledgement is pending.
Definition: tcp.c:135
uint32_t tsval
Definition: tcp.h:128
unsigned long currticks(void)
Get current system time in ticks.
Definition: timer.c:42
#define TCP_MAX_HEADER_LEN
TCP maximum header length.
Definition: tcp.h:393
TCP selective acknowledgement block.
Definition: tcp.h:104
int32_t ack
Definition: old_tcp.h:24
int tcpip_tx(struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol, struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest, struct net_device *netdev, uint16_t *trans_csum)
Transmit a TCP/IP packet.
Definition: tcpip.c:91
uint16_t tcpip_chksum(const void *data, size_t len)
Calculate TCP/IP checkum.
Definition: tcpip.c:203
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
#define htons(value)
Definition: byteswap.h:135
struct tcp_sack_permitted_option spopt
Definition: tcp.h:91
uint32_t rcv_win
Receive window.
Definition: tcp.c:83
struct sockaddr_tcpip peer
Remote socket address.
Definition: tcp.c:46
void * memset(void *dest, int character, size_t len) __nonnull
A persistent I/O buffer.
Definition: iobuf.h:32
uint8_t length
Definition: tcp.h:50
uint8_t flags
Flags.
Definition: ena.h:18

References tcphdr::ack, alloc_iob(), assert(), currticks(), io_buffer::data, DBGC, DBGC2, flags, tcp_connection::flags, htonl, htons, iob_len(), iob_push, iob_reserve, tcp_mss_option::kind, tcp_window_scale_option::kind, tcp_sack_permitted_option::kind, tcp_sack_option::kind, tcp_timestamp_option::kind, tcp_sack_block::left, len, tcp_mss_option::length, tcp_window_scale_option::length, tcp_sack_permitted_option::length, tcp_sack_option::length, tcp_timestamp_option::length, list_empty, tcp_connection::local_port, memset(), tcp_connection::mss, tcp_mss_option::mss, tcp_sack_permitted_padded_option::nop, tcp_sack_padded_option::nop, tcp_timestamp_padded_option::nop, ntohl, ntohs, NULL, tcp_connection::peer, profile_start(), profile_stop(), rc, tcp_connection::rcv_ack, tcp_connection::rcv_win, tcp_connection::rcv_win_scale, tcp_sack_block::right, tcp_connection::rx_queue, tcp_connection::sack, tcp_sack_padded_option::sackopt, tcp_window_scale_option::scale, tcphdr::seq, tcp_connection::snd_sent, tcp_connection::snd_seq, tcp_sack_permitted_padded_option::spopt, tcphdr::src, sockaddr_tcpip::st_port, start_timer(), strerror(), TCP_ACK_PENDING, TCP_CAN_SEND_DATA, tcp_dump_flags(), TCP_FIN, TCP_FLAGS_SENDING, TCP_MAX_HEADER_LEN, TCP_MAX_WINDOW_SIZE, TCP_OPTION_MSS, TCP_OPTION_NOP, TCP_OPTION_SACK, TCP_OPTION_SACK_PERMITTED, TCP_OPTION_TS, TCP_OPTION_WS, tcp_process_tx_queue(), TCP_PSH, TCP_RX_WINDOW_SCALE, tcp_sack(), TCP_SACK_ENABLED, tcp_connection::tcp_state, TCP_SYN, TCP_TS_ENABLED, tcp_xmit_win(), tcpip_chksum(), tcpip_tx(), tcp_connection::timer, tcp_connection::ts_recent, tcp_timestamp_option::tsecr, tcp_timestamp_padded_option::tsopt, tcp_timestamp_option::tsval, wsopt, tcp_connection::xfer, and xfer_window().

Referenced by tcp_rx(), and tcp_xmit().

◆ tcp_xmit()

static void tcp_xmit ( struct tcp_connection tcp)
static

Transmit any outstanding data.

Parameters
tcpTCP connection

Definition at line 769 of file tcp.c.

769  {
770 
771  /* Transmit without an explicit first SACK */
772  tcp_xmit_sack ( tcp, tcp->rcv_ack );
773 }
static void tcp_xmit_sack(struct tcp_connection *tcp, uint32_t sack_seq)
Transmit any outstanding data (with selective acknowledgement)
Definition: tcp.c:609
uint32_t rcv_ack
Current acknowledgement number.
Definition: tcp.c:78

References tcp_connection::rcv_ack, and tcp_xmit_sack().

Referenced by tcp_expired(), tcp_keepalive_expired(), tcp_xfer_close(), and tcp_xfer_deliver().

◆ tcp_xmit_reset()

static int tcp_xmit_reset ( struct tcp_connection tcp,
struct sockaddr_tcpip st_dest,
struct tcp_header in_tcphdr 
)
static

Send RST response to incoming packet.

Parameters
in_tcphdrTCP header of incoming packet
Return values
rcReturn status code

Definition at line 866 of file tcp.c.

868  {
869  struct io_buffer *iobuf;
870  struct tcp_header *tcphdr;
871  int rc;
872 
873  /* Allocate space for dataless TX buffer */
874  iobuf = alloc_iob ( TCP_MAX_HEADER_LEN );
875  if ( ! iobuf ) {
876  DBGC ( tcp, "TCP %p could not allocate iobuf for RST "
877  "%08x..%08x %08x\n", tcp, ntohl ( in_tcphdr->ack ),
878  ntohl ( in_tcphdr->ack ), ntohl ( in_tcphdr->seq ) );
879  return -ENOMEM;
880  }
881  iob_reserve ( iobuf, TCP_MAX_HEADER_LEN );
882 
883  /* Construct RST response */
884  tcphdr = iob_push ( iobuf, sizeof ( *tcphdr ) );
885  memset ( tcphdr, 0, sizeof ( *tcphdr ) );
886  tcphdr->src = in_tcphdr->dest;
887  tcphdr->dest = in_tcphdr->src;
888  tcphdr->seq = in_tcphdr->ack;
889  tcphdr->ack = in_tcphdr->seq;
890  tcphdr->hlen = ( ( sizeof ( *tcphdr ) / 4 ) << 4 );
891  tcphdr->flags = ( TCP_RST | TCP_ACK );
892  tcphdr->win = htons ( 0 );
893  tcphdr->csum = tcpip_chksum ( iobuf->data, iob_len ( iobuf ) );
894 
895  /* Dump header */
896  DBGC2 ( tcp, "TCP %p TX %d->%d %08x..%08x %08x %4d",
897  tcp, ntohs ( tcphdr->src ), ntohs ( tcphdr->dest ),
898  ntohl ( tcphdr->seq ), ( ntohl ( tcphdr->seq ) ),
899  ntohl ( tcphdr->ack ), 0 );
900  tcp_dump_flags ( tcp, tcphdr->flags );
901  DBGC2 ( tcp, "\n" );
902 
903  /* Transmit packet */
904  if ( ( rc = tcpip_tx ( iobuf, &tcp_protocol, NULL, st_dest,
905  NULL, &tcphdr->csum ) ) != 0 ) {
906  DBGC ( tcp, "TCP %p could not transmit RST %08x..%08x %08x: "
907  "%s\n", tcp, ntohl ( in_tcphdr->ack ),
908  ntohl ( in_tcphdr->ack ), ntohl ( in_tcphdr->seq ),
909  strerror ( rc ) );
910  return rc;
911  }
912 
913  return 0;
914 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define TCP_ACK
Definition: tcp.h:159
#define iob_push(iobuf, len)
Definition: iobuf.h:80
#define DBGC(...)
Definition: compiler.h:505
uint32_t seq
Definition: tcp.h:22
#define ntohl(value)
Definition: byteswap.h:134
#define ntohs(value)
Definition: byteswap.h:136
#define TCP_RST
Definition: tcp.h:161
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:128
#define ENOMEM
Not enough space.
Definition: errno.h:534
uint32_t ack
Definition: tcp.h:23
A TCP header.
Definition: tcp.h:19
uint16_t dest
Definition: tcp.h:21
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:151
int32_t seq
Definition: old_tcp.h:23
Definition: old_tcp.h:20
uint16_t src
Definition: old_tcp.h:21
#define iob_reserve(iobuf, len)
Definition: iobuf.h:63
#define DBGC2(...)
Definition: compiler.h:522
void * data
Start of data.
Definition: iobuf.h:44
static void tcp_dump_flags(struct tcp_connection *tcp, unsigned int flags)
Dump TCP flags.
Definition: tcp.c:234
uint16_t src
Definition: tcp.h:20
#define TCP_MAX_HEADER_LEN
TCP maximum header length.
Definition: tcp.h:393
int32_t ack
Definition: old_tcp.h:24
int tcpip_tx(struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol, struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest, struct net_device *netdev, uint16_t *trans_csum)
Transmit a TCP/IP packet.
Definition: tcpip.c:91
uint16_t tcpip_chksum(const void *data, size_t len)
Calculate TCP/IP checkum.
Definition: tcpip.c:203
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
#define htons(value)
Definition: byteswap.h:135
void * memset(void *dest, int character, size_t len) __nonnull
A persistent I/O buffer.
Definition: iobuf.h:32

References tcp_header::ack, tcphdr::ack, alloc_iob(), io_buffer::data, DBGC, DBGC2, tcp_header::dest, ENOMEM, htons, iob_len(), iob_push, iob_reserve, memset(), ntohl, ntohs, NULL, rc, tcp_header::seq, tcphdr::seq, tcp_header::src, tcphdr::src, strerror(), TCP_ACK, tcp_dump_flags(), TCP_MAX_HEADER_LEN, TCP_RST, tcpip_chksum(), and tcpip_tx().

Referenced by tcp_rx().

◆ tcp_rx_opts()

static int tcp_rx_opts ( struct tcp_connection tcp,
const struct tcp_header tcphdr,
size_t  hlen,
struct tcp_options options 
)
static

Parse TCP received options.

Parameters
tcpTCP connection (may be NULL)
tcphdrTCP header
hlenTCP header length
optionsOptions structure to fill in
Return values
rcReturn status code

Definition at line 948 of file tcp.c.

950  {
951  const void *data = ( ( ( void * ) tcphdr ) + sizeof ( *tcphdr ) );
952  const void *end = ( ( ( void * ) tcphdr ) + hlen );
953  const struct tcp_option *option;
954  unsigned int kind;
955  size_t remaining;
956  size_t min;
957 
958  /* Sanity check */
959  assert ( hlen >= sizeof ( *tcphdr ) );
960 
961  /* Parse options */
962  memset ( options, 0, sizeof ( *options ) );
963  while ( ( remaining = ( end - data ) ) ) {
964 
965  /* Extract option code */
966  option = data;
967  kind = option->kind;
968 
969  /* Handle single-byte options */
970  if ( kind == TCP_OPTION_END )
971  break;
972  if ( kind == TCP_OPTION_NOP ) {
973  data++;
974  continue;
975  }
976 
977  /* Handle multi-byte options */
978  min = sizeof ( *option );
979  switch ( kind ) {
980  case TCP_OPTION_MSS:
981  /* Ignore received MSS */
982  break;
983  case TCP_OPTION_WS:
984  options->wsopt = data;
985  min = sizeof ( *options->wsopt );
986  break;
988  options->spopt = data;
989  min = sizeof ( *options->spopt );
990  break;
991  case TCP_OPTION_SACK:
992  /* Ignore received SACKs */
993  break;
994  case TCP_OPTION_TS:
995  options->tsopt = data;
996  min = sizeof ( *options->tsopt );
997  break;
998  default:
999  DBGC ( tcp, "TCP %p received unknown option %d\n",
1000  tcp, kind );
1001  break;
1002  }
1003  if ( remaining < min ) {
1004  DBGC ( tcp, "TCP %p received truncated option %d\n",
1005  tcp, kind );
1006  return -EINVAL;
1007  }
1008  if ( option->length < min ) {
1009  DBGC ( tcp, "TCP %p received underlength option %d\n",
1010  tcp, kind );
1011  return -EINVAL;
1012  }
1013  if ( option->length > remaining ) {
1014  DBGC ( tcp, "TCP %p received overlength option %d\n",
1015  tcp, kind );
1016  return -EINVAL;
1017  }
1018  data += option->length;
1019  }
1020 
1021  return 0;
1022 }
#define TCP_OPTION_NOP
TCP option pad.
Definition: tcp.h:39
#define EINVAL
Invalid argument.
Definition: errno.h:428
#define DBGC(...)
Definition: compiler.h:505
#define min(x, y)
Definition: ath.h:34
#define TCP_OPTION_MSS
Code for the TCP MSS option.
Definition: tcp.h:55
#define TCP_OPTION_TS
Code for the TCP timestamp option.
Definition: tcp.h:139
#define TCP_OPTION_WS
Code for the TCP window scale option.
Definition: tcp.h:71
#define TCP_OPTION_SACK_PERMITTED
Code for the TCP selective acknowledgement permitted option.
Definition: tcp.h:95
#define TCP_OPTION_SACK
Code for the TCP selective acknowledgement option.
Definition: tcp.h:122
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
A long option, as used for getopt_long()
Definition: getopt.h:24
static int options
Definition: 3c515.c:286
Generic TCP option.
Definition: tcp.h:42
uint8_t kind
Definition: tcp.h:43
Definition: old_tcp.h:20
#define TCP_OPTION_END
End of TCP options list.
Definition: tcp.h:36
uint32_t end
Ending offset.
Definition: netvsc.h:18
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
uint8_t hlen
Definition: tcp.h:24
void * memset(void *dest, int character, size_t len) __nonnull

References assert(), data, DBGC, EINVAL, end, tcp_option::kind, memset(), min, options, TCP_OPTION_END, TCP_OPTION_MSS, TCP_OPTION_NOP, TCP_OPTION_SACK, TCP_OPTION_SACK_PERMITTED, TCP_OPTION_TS, and TCP_OPTION_WS.

Referenced by tcp_rx().

◆ tcp_rx_seq()

static void tcp_rx_seq ( struct tcp_connection tcp,
uint32_t  seq_len 
)
static

Consume received sequence space.

Parameters
tcpTCP connection
seq_lenSequence space length to consume

Definition at line 1030 of file tcp.c.

1030  {
1031  unsigned int sack;
1032 
1033  /* Sanity check */
1034  assert ( seq_len > 0 );
1035 
1036  /* Update acknowledgement number */
1037  tcp->rcv_ack += seq_len;
1038 
1039  /* Update window */
1040  if ( tcp->rcv_win > seq_len ) {
1041  tcp->rcv_win -= seq_len;
1042  } else {
1043  tcp->rcv_win = 0;
1044  }
1045 
1046  /* Update timestamp */
1047  tcp->ts_recent = tcp->ts_val;
1048 
1049  /* Update SACK list */
1050  for ( sack = 0 ; sack < TCP_SACK_MAX ; sack++ ) {
1051  if ( tcp->sack[sack].left == tcp->sack[sack].right )
1052  continue;
1053  if ( tcp_cmp ( tcp->sack[sack].left, tcp->rcv_ack ) < 0 )
1054  tcp->sack[sack].left = tcp->rcv_ack;
1055  if ( tcp_cmp ( tcp->sack[sack].right, tcp->rcv_ack ) < 0 )
1056  tcp->sack[sack].right = tcp->rcv_ack;
1057  }
1058 
1059  /* Mark ACK as pending */
1060  tcp->flags |= TCP_ACK_PENDING;
1061 }
unsigned int flags
Flags.
Definition: tcp.c:40
uint32_t right
Definition: tcp.h:106
uint32_t ts_recent
Most recent received timestamp that advanced the window.
Definition: tcp.c:94
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
uint32_t ts_val
Received timestamp value.
Definition: tcp.c:89
#define TCP_SACK_MAX
Maximum number of selective acknowledgement blocks.
Definition: tcp.h:113
struct tcp_sack_block sack[TCP_SACK_MAX]
Selective acknowledgement list (in host-endian order)
Definition: tcp.c:107
uint32_t left
Definition: tcp.h:105
uint32_t rcv_ack
Current acknowledgement number.
Definition: tcp.c:78
static int32_t tcp_cmp(uint32_t seq1, uint32_t seq2)
Compare TCP sequence numbers.
Definition: tcp.h:412
TCP acknowledgement is pending.
Definition: tcp.c:135
uint32_t rcv_win
Receive window.
Definition: tcp.c:83

References assert(), tcp_connection::flags, tcp_sack_block::left, tcp_connection::rcv_ack, tcp_connection::rcv_win, tcp_sack_block::right, tcp_connection::sack, TCP_ACK_PENDING, tcp_cmp(), TCP_SACK_MAX, tcp_connection::ts_recent, and tcp_connection::ts_val.

Referenced by tcp_rx_data(), tcp_rx_fin(), and tcp_rx_syn().

◆ tcp_rx_syn()

static int tcp_rx_syn ( struct tcp_connection tcp,
uint32_t  seq,
struct tcp_options options 
)
static

Handle TCP received SYN.

Parameters
tcpTCP connection
seqSEQ value (in host-endian order)
optionsTCP options
Return values
rcReturn status code

Definition at line 1071 of file tcp.c.

1072  {
1073 
1074  /* Synchronise sequence numbers on first SYN */
1075  if ( ! ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) ) {
1076  tcp->rcv_ack = seq;
1077  if ( options->tsopt )
1078  tcp->flags |= TCP_TS_ENABLED;
1079  if ( options->spopt )
1080  tcp->flags |= TCP_SACK_ENABLED;
1081  if ( options->wsopt ) {
1082  tcp->snd_win_scale = options->wsopt->scale;
1084  }
1085  DBGC ( tcp, "TCP %p using %stimestamps, %sSACK, TX window "
1086  "x%d, RX window x%d\n", tcp,
1087  ( ( tcp->flags & TCP_TS_ENABLED ) ? "" : "no " ),
1088  ( ( tcp->flags & TCP_SACK_ENABLED ) ? "" : "no " ),
1089  ( 1 << tcp->snd_win_scale ),
1090  ( 1 << tcp->rcv_win_scale ) );
1091  }
1092 
1093  /* Ignore duplicate SYN */
1094  if ( seq != tcp->rcv_ack )
1095  return 0;
1096 
1097  /* Acknowledge SYN */
1098  tcp_rx_seq ( tcp, 1 );
1099 
1100  /* Mark SYN as received and start sending ACKs with each packet */
1101  tcp->tcp_state |= ( TCP_STATE_SENT ( TCP_ACK ) |
1102  TCP_STATE_RCVD ( TCP_SYN ) );
1103 
1104  return 0;
1105 }
unsigned int tcp_state
Current TCP state.
Definition: tcp.c:53
#define TCP_RX_WINDOW_SCALE
Advertised TCP window scale.
Definition: tcp.h:80
#define TCP_ACK
Definition: tcp.h:159
#define DBGC(...)
Definition: compiler.h:505
TCP selective acknowledgement is enabled.
Definition: tcp.c:137
TCP timestamps are enabled.
Definition: tcp.c:133
uint8_t snd_win_scale
Send window scale.
Definition: tcp.c:99
u16 seq
802.11 Sequence Control field
Definition: ieee80211.h:19
unsigned int flags
Flags.
Definition: tcp.c:40
#define TCP_SYN
Definition: tcp.h:162
static int options
Definition: 3c515.c:286
static void tcp_rx_seq(struct tcp_connection *tcp, uint32_t seq_len)
Consume received sequence space.
Definition: tcp.c:1030
uint8_t rcv_win_scale
Receive window scale.
Definition: tcp.c:104
#define TCP_STATE_RCVD(flags)
TCP flags that have been received from the peer.
Definition: tcp.h:191
#define TCP_STATE_SENT(flags)
TCP flags that have been sent in outgoing packets.
Definition: tcp.h:176
uint32_t rcv_ack
Current acknowledgement number.
Definition: tcp.c:78

References DBGC, tcp_connection::flags, options, tcp_connection::rcv_ack, tcp_connection::rcv_win_scale, seq, tcp_connection::snd_win_scale, TCP_ACK, tcp_rx_seq(), TCP_RX_WINDOW_SCALE, TCP_SACK_ENABLED, tcp_connection::tcp_state, TCP_STATE_RCVD, TCP_STATE_SENT, TCP_SYN, and TCP_TS_ENABLED.

Referenced by tcp_rx().

◆ tcp_rx_data()

static int tcp_rx_data ( struct tcp_connection tcp,
uint32_t  seq,
struct io_buffer iobuf 
)
static

Handle TCP received data.

Parameters
tcpTCP connection
seqSEQ value (in host-endian order)
iobufI/O buffer
Return values
rcReturn status code

This function takes ownership of the I/O buffer.

Definition at line 1200 of file tcp.c.

1201  {
1202  uint32_t already_rcvd;
1203  uint32_t len;
1204  int rc;
1205 
1206  /* Ignore duplicate or out-of-order data */
1207  already_rcvd = ( tcp->rcv_ack - seq );
1208  len = iob_len ( iobuf );
1209  if ( already_rcvd >= len ) {
1210  free_iob ( iobuf );
1211  return 0;
1212  }
1213  iob_pull ( iobuf, already_rcvd );
1214  len -= already_rcvd;
1215 
1216  /* Acknowledge new data */
1217  tcp_rx_seq ( tcp, len );
1218 
1219  /* Deliver data to application */
1220  profile_start ( &tcp_xfer_profiler );
1221  if ( ( rc = xfer_deliver_iob ( &tcp->xfer, iobuf ) ) != 0 ) {
1222  DBGC ( tcp, "TCP %p could not deliver %08x..%08x: %s\n",
1223  tcp, seq, ( seq + len ), strerror ( rc ) );
1224  return rc;
1225  }
1226  profile_stop ( &tcp_xfer_profiler );
1227 
1228  return 0;
1229 }
#define iob_pull(iobuf, len)
Definition: iobuf.h:98
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
int xfer_deliver_iob(struct interface *intf, struct io_buffer *iobuf)
Deliver datagram as I/O buffer without metadata.
Definition: xfer.c:254
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:145
#define DBGC(...)
Definition: compiler.h:505
static void profile_stop(struct profiler *profiler)
Stop profiling.
Definition: profile.h:171
u16 seq
802.11 Sequence Control field
Definition: ieee80211.h:19
static void tcp_rx_seq(struct tcp_connection *tcp, uint32_t seq_len)
Consume received sequence space.
Definition: tcp.c:1030
static void profile_start(struct profiler *profiler)
Start profiling.
Definition: profile.h:158
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:151
unsigned int uint32_t
Definition: stdint.h:12
uint32_t len
Length.
Definition: ena.h:14
uint32_t rcv_ack
Current acknowledgement number.
Definition: tcp.c:78
struct interface xfer
Data transfer interface.
Definition: tcp.c:43

References DBGC, free_iob(), iob_len(), iob_pull, len, profile_start(), profile_stop(), rc, tcp_connection::rcv_ack, seq, strerror(), tcp_rx_seq(), tcp_connection::xfer, and xfer_deliver_iob().

Referenced by tcp_process_rx_queue().

◆ tcp_rx_fin()

static int tcp_rx_fin ( struct tcp_connection tcp,
uint32_t  seq 
)
static

Handle TCP received FIN.

Parameters
tcpTCP connection
seqSEQ value (in host-endian order)
Return values
rcReturn status code

Definition at line 1238 of file tcp.c.

1238  {
1239 
1240  /* Ignore duplicate or out-of-order FIN */
1241  if ( seq != tcp->rcv_ack )
1242  return 0;
1243 
1244  /* Acknowledge FIN */
1245  tcp_rx_seq ( tcp, 1 );
1246 
1247  /* Mark FIN as received */
1248  tcp->tcp_state |= TCP_STATE_RCVD ( TCP_FIN );
1249 
1250  /* Close connection */
1251  tcp_close ( tcp, 0 );
1252 
1253  return 0;
1254 }
unsigned int tcp_state
Current TCP state.
Definition: tcp.c:53
#define TCP_FIN
Definition: tcp.h:163
u16 seq
802.11 Sequence Control field
Definition: ieee80211.h:19
static void tcp_close(struct tcp_connection *tcp, int rc)
Close TCP connection.
Definition: tcp.c:349
static void tcp_rx_seq(struct tcp_connection *tcp, uint32_t seq_len)
Consume received sequence space.
Definition: tcp.c:1030
#define TCP_STATE_RCVD(flags)
TCP flags that have been received from the peer.
Definition: tcp.h:191
uint32_t rcv_ack
Current acknowledgement number.
Definition: tcp.c:78

References tcp_connection::rcv_ack, seq, tcp_close(), TCP_FIN, tcp_rx_seq(), tcp_connection::tcp_state, and TCP_STATE_RCVD.

Referenced by tcp_process_rx_queue().

◆ tcp_rx_rst()

static int tcp_rx_rst ( struct tcp_connection tcp,
uint32_t  seq 
)
static

Handle TCP received RST.

Parameters
tcpTCP connection
seqSEQ value (in host-endian order)
Return values
rcReturn status code

Definition at line 1263 of file tcp.c.

1263  {
1264 
1265  /* Accept RST only if it falls within the window. If we have
1266  * not yet received a SYN, then we have no window to test
1267  * against, so fall back to checking that our SYN has been
1268  * ACKed.
1269  */
1270  if ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) {
1271  if ( ! tcp_in_window ( seq, tcp->rcv_ack, tcp->rcv_win ) )
1272  return 0;
1273  } else {
1274  if ( ! ( tcp->tcp_state & TCP_STATE_ACKED ( TCP_SYN ) ) )
1275  return 0;
1276  }
1277 
1278  /* Abort connection */
1279  tcp->tcp_state = TCP_CLOSED;
1280  tcp_dump_state ( tcp );
1281  tcp_close ( tcp, -ECONNRESET );
1282 
1283  DBGC ( tcp, "TCP %p connection reset by peer\n", tcp );
1284  return -ECONNRESET;
1285 }
#define ECONNRESET
Connection reset.
Definition: errno.h:363
unsigned int tcp_state
Current TCP state.
Definition: tcp.c:53
#define DBGC(...)
Definition: compiler.h:505
u16 seq
802.11 Sequence Control field
Definition: ieee80211.h:19
#define TCP_SYN
Definition: tcp.h:162
static void tcp_close(struct tcp_connection *tcp, int rc)
Close TCP connection.
Definition: tcp.c:349
#define TCP_STATE_RCVD(flags)
TCP flags that have been received from the peer.
Definition: tcp.h:191
static int tcp_in_window(uint32_t seq, uint32_t start, uint32_t len)
Check if TCP sequence number lies within window.
Definition: tcp.h:424
#define TCP_STATE_ACKED(flags)
TCP flags that have been acknowledged by the peer.
Definition: tcp.h:183
uint32_t rcv_ack
Current acknowledgement number.
Definition: tcp.c:78
#define TCP_CLOSED
CLOSED.
Definition: tcp.h:202
static void tcp_dump_state(struct tcp_connection *tcp)
Dump TCP state transition.
Definition: tcp.c:218
uint32_t rcv_win
Receive window.
Definition: tcp.c:83

References DBGC, ECONNRESET, tcp_connection::rcv_ack, tcp_connection::rcv_win, seq, tcp_close(), TCP_CLOSED, tcp_dump_state(), tcp_in_window(), tcp_connection::tcp_state, TCP_STATE_ACKED, TCP_STATE_RCVD, and TCP_SYN.

Referenced by tcp_rx().

◆ tcp_rx_enqueue()

static void tcp_rx_enqueue ( struct tcp_connection tcp,
uint32_t  seq,
uint8_t  flags,
struct io_buffer iobuf 
)
static

Enqueue received TCP packet.

Parameters
tcpTCP connection
seqSEQ value (in host-endian order)
flagsTCP flags
iobufI/O buffer

Definition at line 1295 of file tcp.c.

1296  {
1297  struct tcp_rx_queued_header *tcpqhdr;
1298  struct io_buffer *queued;
1299  size_t len;
1300  uint32_t seq_len;
1301  uint32_t nxt;
1302 
1303  /* Calculate remaining flags and sequence length. Note that
1304  * SYN, if present, has already been processed by this point.
1305  */
1306  flags &= TCP_FIN;
1307  len = iob_len ( iobuf );
1308  seq_len = ( len + ( flags ? 1 : 0 ) );
1309  nxt = ( seq + seq_len );
1310 
1311  /* Discard immediately (to save memory) if:
1312  *
1313  * a) we have not yet received a SYN (and so have no defined
1314  * receive window), or
1315  * b) the packet lies entirely outside the receive window, or
1316  * c) there is no further content to process.
1317  */
1318  if ( ( ! ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) ) ||
1319  ( tcp_cmp ( seq, tcp->rcv_ack + tcp->rcv_win ) >= 0 ) ||
1320  ( tcp_cmp ( nxt, tcp->rcv_ack ) < 0 ) ||
1321  ( seq_len == 0 ) ) {
1322  free_iob ( iobuf );
1323  return;
1324  }
1325 
1326  /* Add internal header */
1327  tcpqhdr = iob_push ( iobuf, sizeof ( *tcpqhdr ) );
1328  tcpqhdr->seq = seq;
1329  tcpqhdr->nxt = nxt;
1330  tcpqhdr->flags = flags;
1331 
1332  /* Add to RX queue */
1333  list_for_each_entry ( queued, &tcp->rx_queue, list ) {
1334  tcpqhdr = queued->data;
1335  if ( tcp_cmp ( seq, tcpqhdr->seq ) < 0 )
1336  break;
1337  }
1338  list_add_tail ( &iobuf->list, &queued->list );
1339 }
struct list_head rx_queue
Receive queue.
Definition: tcp.c:112
unsigned int tcp_state
Current TCP state.
Definition: tcp.c:53
#define TCP_FIN
Definition: tcp.h:163
#define iob_push(iobuf, len)
Definition: iobuf.h:80
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:145
u16 seq
802.11 Sequence Control field
Definition: ieee80211.h:19
#define TCP_SYN
Definition: tcp.h:162
uint32_t seq
SEQ value, in host-endian order.
Definition: tcp.c:151
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:420
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition: list.h:93
uint32_t nxt
Next SEQ value, in host-endian order.
Definition: tcp.c:153
#define TCP_STATE_RCVD(flags)
TCP flags that have been received from the peer.
Definition: tcp.h:191
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:151
unsigned int uint32_t
Definition: stdint.h:12
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:39
uint32_t len
Length.
Definition: ena.h:14
void * data
Start of data.
Definition: iobuf.h:44
TCP internal header.
Definition: tcp.c:145
uint32_t rcv_ack
Current acknowledgement number.
Definition: tcp.c:78
static int32_t tcp_cmp(uint32_t seq1, uint32_t seq2)
Compare TCP sequence numbers.
Definition: tcp.h:412
uint8_t flags
Flags.
Definition: tcp.c:160
uint32_t rcv_win
Receive window.
Definition: tcp.c:83
A persistent I/O buffer.
Definition: iobuf.h:32
uint8_t flags
Flags.
Definition: ena.h:18

References io_buffer::data, flags, tcp_rx_queued_header::flags, free_iob(), iob_len(), iob_push, len, io_buffer::list, list_add_tail, list_for_each_entry, tcp_rx_queued_header::nxt, tcp_connection::rcv_ack, tcp_connection::rcv_win, tcp_connection::rx_queue, seq, tcp_rx_queued_header::seq, tcp_cmp(), TCP_FIN, tcp_connection::tcp_state, TCP_STATE_RCVD, and TCP_SYN.

Referenced by tcp_rx().

◆ tcp_process_rx_queue()

static void tcp_process_rx_queue ( struct tcp_connection tcp)
static

Process receive queue.

Parameters
tcpTCP connection

Definition at line 1346 of file tcp.c.

1346  {
1347  struct io_buffer *iobuf;
1348  struct tcp_rx_queued_header *tcpqhdr;
1349  uint32_t seq;
1350  unsigned int flags;
1351  size_t len;
1352 
1353  /* Process all applicable received buffers. Note that we
1354  * cannot use list_for_each_entry() to iterate over the RX
1355  * queue, since tcp_discard() may remove packets from the RX
1356  * queue while we are processing.
1357  */
1358  while ( ( iobuf = list_first_entry ( &tcp->rx_queue, struct io_buffer,
1359  list ) ) ) {
1360 
1361  /* Stop processing when we hit the first gap */
1362  tcpqhdr = iobuf->data;
1363  if ( tcp_cmp ( tcpqhdr->seq, tcp->rcv_ack ) > 0 )
1364  break;
1365 
1366  /* Strip internal header and remove from RX queue */
1367  list_del ( &iobuf->list );
1368  seq = tcpqhdr->seq;
1369  flags = tcpqhdr->flags;
1370  iob_pull ( iobuf, sizeof ( *tcpqhdr ) );
1371  len = iob_len ( iobuf );
1372 
1373  /* Handle new data, if any */
1374  tcp_rx_data ( tcp, seq, iob_disown ( iobuf ) );
1375  seq += len;
1376 
1377  /* Handle FIN, if present */
1378  if ( flags & TCP_FIN ) {
1379  tcp_rx_fin ( tcp, seq );
1380  seq++;
1381  }
1382  }
1383 }
#define iob_pull(iobuf, len)
Definition: iobuf.h:98
struct list_head rx_queue
Receive queue.
Definition: tcp.c:112
#define TCP_FIN
Definition: tcp.h:163
static int tcp_rx_fin(struct tcp_connection *tcp, uint32_t seq)
Handle TCP received FIN.
Definition: tcp.c:1238
u16 seq
802.11 Sequence Control field
Definition: ieee80211.h:19
#define list_first_entry(list, type, member)
Get the container of the first entry in a list.
Definition: list.h:333
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition: iobuf.h:208
uint32_t seq
SEQ value, in host-endian order.
Definition: tcp.c:151
static int tcp_rx_data(struct tcp_connection *tcp, uint32_t seq, struct io_buffer *iobuf)
Handle TCP received data.
Definition: tcp.c:1200
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:151
unsigned int uint32_t
Definition: stdint.h:12
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:39
uint32_t len
Length.
Definition: ena.h:14
void * data
Start of data.
Definition: iobuf.h:44
TCP internal header.
Definition: tcp.c:145
uint32_t rcv_ack
Current acknowledgement number.
Definition: tcp.c:78
static int32_t tcp_cmp(uint32_t seq1, uint32_t seq2)
Compare TCP sequence numbers.
Definition: tcp.h:412
uint8_t flags
Flags.
Definition: tcp.c:160
A persistent I/O buffer.
Definition: iobuf.h:32
uint8_t flags
Flags.
Definition: ena.h:18

References io_buffer::data, flags, tcp_rx_queued_header::flags, iob_disown, iob_len(), iob_pull, len, io_buffer::list, list_del, list_first_entry, tcp_connection::rcv_ack, tcp_connection::rx_queue, seq, tcp_rx_queued_header::seq, tcp_cmp(), TCP_FIN, tcp_rx_data(), and tcp_rx_fin().

Referenced by tcp_rx().

◆ tcp_rx()

static int tcp_rx ( struct io_buffer iobuf,
struct net_device *netdev  __unused,
struct sockaddr_tcpip st_src,
struct sockaddr_tcpip *st_dest  __unused,
uint16_t  pshdr_csum 
)
static

Process received packet.

Parameters
iobufI/O buffer
netdevNetwork device
st_srcPartially-filled source address
st_destPartially-filled destination address
pshdr_csumPseudo-header checksum
Return values
rcReturn status code

Definition at line 1395 of file tcp.c.

1399  {
1400  struct tcp_header *tcphdr = iobuf->data;
1401  struct tcp_connection *tcp;
1402  struct tcp_options options;
1403  size_t hlen;
1404  uint16_t csum;
1405  uint32_t seq;
1406  uint32_t ack;
1407  uint16_t raw_win;
1408  uint32_t win;
1409  unsigned int flags;
1410  size_t len;
1411  uint32_t seq_len;
1412  size_t old_xfer_window;
1413  int rc;
1414 
1415  /* Start profiling */
1416  profile_start ( &tcp_rx_profiler );
1417 
1418  /* Sanity check packet */
1419  if ( iob_len ( iobuf ) < sizeof ( *tcphdr ) ) {
1420  DBG ( "TCP packet too short at %zd bytes (min %zd bytes)\n",
1421  iob_len ( iobuf ), sizeof ( *tcphdr ) );
1422  rc = -EINVAL;
1423  goto discard;
1424  }
1425  hlen = ( ( tcphdr->hlen & TCP_MASK_HLEN ) / 16 ) * 4;
1426  if ( hlen < sizeof ( *tcphdr ) ) {
1427  DBG ( "TCP header too short at %zd bytes (min %zd bytes)\n",
1428  hlen, sizeof ( *tcphdr ) );
1429  rc = -EINVAL;
1430  goto discard;
1431  }
1432  if ( hlen > iob_len ( iobuf ) ) {
1433  DBG ( "TCP header too long at %zd bytes (max %zd bytes)\n",
1434  hlen, iob_len ( iobuf ) );
1435  rc = -EINVAL;
1436  goto discard;
1437  }
1438  csum = tcpip_continue_chksum ( pshdr_csum, iobuf->data,
1439  iob_len ( iobuf ) );
1440  if ( csum != 0 ) {
1441  DBG ( "TCP checksum incorrect (is %04x including checksum "
1442  "field, should be 0000)\n", csum );
1443  rc = -EINVAL;
1444  goto discard;
1445  }
1446 
1447  /* Parse parameters from header and strip header */
1448  tcp = tcp_demux ( ntohs ( tcphdr->dest ) );
1449  seq = ntohl ( tcphdr->seq );
1450  ack = ntohl ( tcphdr->ack );
1451  raw_win = ntohs ( tcphdr->win );
1452  flags = tcphdr->flags;
1453  if ( ( rc = tcp_rx_opts ( tcp, tcphdr, hlen, &options ) ) != 0 )
1454  goto discard;
1455  if ( tcp && options.tsopt )
1456  tcp->ts_val = ntohl ( options.tsopt->tsval );
1457  iob_pull ( iobuf, hlen );
1458  len = iob_len ( iobuf );
1459  seq_len = ( len + ( ( flags & TCP_SYN ) ? 1 : 0 ) +
1460  ( ( flags & TCP_FIN ) ? 1 : 0 ) );
1461 
1462  /* Dump header */
1463  DBGC2 ( tcp, "TCP %p RX %d<-%d %08x %08x..%08x %4zd",
1464  tcp, ntohs ( tcphdr->dest ), ntohs ( tcphdr->src ),
1465  ntohl ( tcphdr->ack ), ntohl ( tcphdr->seq ),
1466  ( ntohl ( tcphdr->seq ) + seq_len ), len );
1467  tcp_dump_flags ( tcp, tcphdr->flags );
1468  DBGC2 ( tcp, "\n" );
1469 
1470  /* If no connection was found, silently drop packet */
1471  if ( ! tcp ) {
1472  rc = -ENOTCONN;
1473  goto discard;
1474  }
1475 
1476  /* Record old data-transfer window */
1477  old_xfer_window = tcp_xfer_window ( tcp );
1478 
1479  /* Handle ACK, if present */
1480  if ( flags & TCP_ACK ) {
1481  win = ( raw_win << tcp->snd_win_scale );
1482  if ( ( rc = tcp_rx_ack ( tcp, ack, win ) ) != 0 ) {
1483  tcp_xmit_reset ( tcp, st_src, tcphdr );
1484  goto discard;
1485  }
1486  }
1487 
1488  /* Force an ACK if this packet is out of order */
1489  if ( ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) &&
1490  ( seq != tcp->rcv_ack ) ) {
1491  tcp->flags |= TCP_ACK_PENDING;
1492  }
1493 
1494  /* Handle SYN, if present */
1495  if ( flags & TCP_SYN ) {
1496  tcp_rx_syn ( tcp, seq, &options );
1497  seq++;
1498  }
1499 
1500  /* Handle RST, if present */
1501  if ( flags & TCP_RST ) {
1502  if ( ( rc = tcp_rx_rst ( tcp, seq ) ) != 0 )
1503  goto discard;
1504  }
1505 
1506  /* Enqueue received data */
1507  tcp_rx_enqueue ( tcp, seq, flags, iob_disown ( iobuf ) );
1508 
1509  /* Process receive queue */
1510  tcp_process_rx_queue ( tcp );
1511 
1512  /* Dump out any state change as a result of the received packet */
1513  tcp_dump_state ( tcp );
1514 
1515  /* Schedule transmission of ACK (and any pending data). If we
1516  * have received any out-of-order packets (i.e. if the receive
1517  * queue remains non-empty after processing) then send the ACK
1518  * immediately in order to trigger Fast Retransmission.
1519  */
1520  if ( list_empty ( &tcp->rx_queue ) ) {
1521  process_add ( &tcp->process );
1522  } else {
1523  tcp_xmit_sack ( tcp, seq );
1524  }
1525 
1526  /* If this packet was the last we expect to receive, set up
1527  * timer to expire and cause the connection to be freed.
1528  */
1529  if ( TCP_CLOSED_GRACEFULLY ( tcp->tcp_state ) ) {
1530  stop_timer ( &tcp->wait );
1531  start_timer_fixed ( &tcp->wait, ( 2 * TCP_MSL ) );
1532  }
1533 
1534  /* Notify application if window has changed */
1535  if ( tcp_xfer_window ( tcp ) != old_xfer_window )
1536  xfer_window_changed ( &tcp->xfer );
1537 
1538  profile_stop ( &tcp_rx_profiler );
1539  return 0;
1540 
1541  discard:
1542  /* Free received packet */
1543  free_iob ( iobuf );
1544  return rc;
1545 }
A TCP connection.
Definition: tcp.c:33
#define iob_pull(iobuf, len)
Definition: iobuf.h:98
struct retry_timer wait
Shutdown (TIME_WAIT) timer.
Definition: tcp.c:120
#define EINVAL
Invalid argument.
Definition: errno.h:428
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
Definition: xfer.c:145
unsigned short uint16_t
Definition: stdint.h:11
struct list_head rx_queue
Receive queue.
Definition: tcp.c:112
unsigned int tcp_state
Current TCP state.
Definition: tcp.c:53
Parsed TCP options.
Definition: tcp.h:142
#define TCP_MASK_HLEN
Mask for TCP header length field.
Definition: tcp.h:324
#define TCP_FIN
Definition: tcp.h:163
#define TCP_ACK
Definition: tcp.h:159
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:145
static int tcp_xmit_reset(struct tcp_connection *tcp, struct sockaddr_tcpip *st_dest, struct tcp_header *in_tcphdr)
Send RST response to incoming packet.
Definition: tcp.c:866
static int tcp_rx_rst(struct tcp_connection *tcp, uint32_t seq)
Handle TCP received RST.
Definition: tcp.c:1263
#define ntohl(value)
Definition: byteswap.h:134
uint8_t snd_win_scale
Send window scale.
Definition: tcp.c:99
#define ntohs(value)
Definition: byteswap.h:136
#define TCP_MSL
TCP maximum segment lifetime.
Definition: tcp.h:379
#define TCP_RST
Definition: tcp.h:161
static size_t tcp_xfer_window(struct tcp_connection *tcp)
Check data-transfer flow control window.
Definition: tcp.c:453
static void profile_stop(struct profiler *profiler)
Stop profiling.
Definition: profile.h:171
u16 seq
802.11 Sequence Control field
Definition: ieee80211.h:19
unsigned int flags
Flags.
Definition: tcp.c:40
#define TCP_SYN
Definition: tcp.h:162
#define list_empty(list)
Test whether a list is empty.
Definition: list.h:136
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition: iobuf.h:208
uint32_t ts_val
Received timestamp value.
Definition: tcp.c:89
static int tcp_rx_opts(struct tcp_connection *tcp, const struct tcp_header *tcphdr, size_t hlen, struct tcp_options *options)
Parse TCP received options.
Definition: tcp.c:948
static int options
Definition: 3c515.c:286
A TCP header.
Definition: tcp.h:19
static void profile_start(struct profiler *profiler)
Start profiling.
Definition: profile.h:158
void process_add(struct process *process)
Add process to process list.
Definition: process.c:59
#define ENOTCONN
The socket is not connected.
Definition: errno.h:569
#define TCP_STATE_RCVD(flags)
TCP flags that have been received from the peer.
Definition: tcp.h:191
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:151
int32_t seq
Definition: old_tcp.h:23
Definition: old_tcp.h:20
uint16_t src
Definition: old_tcp.h:21
unsigned int uint32_t
Definition: stdint.h:12
static void tcp_rx_enqueue(struct tcp_connection *tcp, uint32_t seq, uint8_t flags, struct io_buffer *iobuf)
Enqueue received TCP packet.
Definition: tcp.c:1295
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition: retry.c:64
static int tcp_rx_syn(struct tcp_connection *tcp, uint32_t seq, struct tcp_options *options)
Handle TCP received SYN.
Definition: tcp.c:1071
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition: retry.c:117
struct process process
Transmission process.
Definition: tcp.c:114
uint32_t len
Length.
Definition: ena.h:14
#define DBGC2(...)
Definition: compiler.h:522
void * data
Start of data.
Definition: iobuf.h:44
static void tcp_dump_flags(struct tcp_connection *tcp, unsigned int flags)
Dump TCP flags.
Definition: tcp.c:234
static void tcp_xmit_sack(struct tcp_connection *tcp, uint32_t sack_seq)
Transmit any outstanding data (with selective acknowledgement)
Definition: tcp.c:609
uint32_t rcv_ack
Current acknowledgement number.
Definition: tcp.c:78
static struct tcp_connection * tcp_demux(unsigned int local_port)
Identify TCP connection by local port number.
Definition: tcp.c:929
struct interface xfer
Data transfer interface.
Definition: tcp.c:43
TCP acknowledgement is pending.
Definition: tcp.c:135
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
int32_t ack
Definition: old_tcp.h:24
static int tcp_rx_ack(struct tcp_connection *tcp, uint32_t ack, uint32_t win)
Handle TCP received ACK.
Definition: tcp.c:1115
#define TCP_CLOSED_GRACEFULLY(state)
Have closed gracefully.
Definition: tcp.h:316
static void tcp_process_rx_queue(struct tcp_connection *tcp)
Process receive queue.
Definition: tcp.c:1346
uint16_t tcpip_continue_chksum(uint16_t partial, const void *data, size_t len)
Calculate continued TCP/IP checkum.
Definition: x86_tcpip.c:45
static void tcp_dump_state(struct tcp_connection *tcp)
Dump TCP state transition.
Definition: tcp.c:218
uint8_t flags
Flags.
Definition: ena.h:18

References tcphdr::ack, io_buffer::data, DBG, DBGC2, EINVAL, ENOTCONN, flags, tcp_connection::flags, free_iob(), iob_disown, iob_len(), iob_pull, len, list_empty, ntohl, ntohs, options, tcp_connection::process, process_add(), profile_start(), profile_stop(), rc, tcp_connection::rcv_ack, tcp_connection::rx_queue, seq, tcphdr::seq, tcp_connection::snd_win_scale, tcphdr::src, start_timer_fixed(), stop_timer(), TCP_ACK, TCP_ACK_PENDING, TCP_CLOSED_GRACEFULLY, tcp_demux(), tcp_dump_flags(), tcp_dump_state(), TCP_FIN, TCP_MASK_HLEN, TCP_MSL, tcp_process_rx_queue(), TCP_RST, tcp_rx_ack(), tcp_rx_enqueue(), tcp_rx_opts(), tcp_rx_rst(), tcp_rx_syn(), tcp_connection::tcp_state, TCP_STATE_RCVD, TCP_SYN, tcp_xfer_window(), tcp_xmit_reset(), tcp_xmit_sack(), tcpip_continue_chksum(), tcp_connection::ts_val, tcp_connection::wait, tcp_connection::xfer, and xfer_window_changed().

◆ tcp_discard()

static unsigned int tcp_discard ( void  )
static

Discard some cached TCP data.

Return values
discardedNumber of cached items discarded

Definition at line 1559 of file tcp.c.

1559  {
1560  struct tcp_connection *tcp;
1561  struct io_buffer *iobuf;
1562  unsigned int discarded = 0;
1563 
1564  /* Try to drop one queued RX packet from each connection */
1565  list_for_each_entry ( tcp, &tcp_conns, list ) {
1566  list_for_each_entry_reverse ( iobuf, &tcp->rx_queue, list ) {
1567 
1568  /* Remove packet from queue */
1569  list_del ( &iobuf->list );
1570  free_iob ( iobuf );
1571 
1572  /* Report discard */
1573  discarded++;
1574  break;
1575  }
1576  }
1577 
1578  return discarded;
1579 }
A TCP connection.
Definition: tcp.c:33
struct list_head rx_queue
Receive queue.
Definition: tcp.c:112
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:145
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:420
#define list_for_each_entry_reverse(pos, head, member)
Iterate over entries in a list in reverse order.
Definition: list.h:433
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:39
A persistent I/O buffer.
Definition: iobuf.h:32

References free_iob(), io_buffer::list, list_del, list_for_each_entry, list_for_each_entry_reverse, and tcp_connection::rx_queue.

◆ __cache_discarder()

struct cache_discarder tcp_discarder __cache_discarder ( CACHE_NORMAL  )

TCP cache discarder.

◆ tcp_first_unclosed()

static struct tcp_connection* tcp_first_unclosed ( void  )
static

Find first TCP connection that has not yet been closed.

Return values
tcpFirst unclosed connection, or NULL

Definition at line 1591 of file tcp.c.

1591  {
1592  struct tcp_connection *tcp;
1593 
1594  /* Find first connection which has not yet been closed */
1595  list_for_each_entry ( tcp, &tcp_conns, list ) {
1596  if ( ! ( tcp->flags & TCP_XFER_CLOSED ) )
1597  return tcp;
1598  }
1599  return NULL;
1600 }
A TCP connection.
Definition: tcp.c:33
unsigned int flags
Flags.
Definition: tcp.c:40
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:420
TCP data transfer interface has been closed.
Definition: tcp.c:131
struct list_head list
List of TCP connections.
Definition: tcp.c:37
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

References tcp_connection::flags, tcp_connection::list, list_for_each_entry, NULL, and TCP_XFER_CLOSED.

Referenced by tcp_shutdown().

◆ tcp_first_unfinished()

static struct tcp_connection* tcp_first_unfinished ( void  )
static

Find first TCP connection that has not yet finished all operations.

Return values
tcpFirst unfinished connection, or NULL

Definition at line 1607 of file tcp.c.

1607  {
1608  struct tcp_connection *tcp;
1609 
1610  /* Find first connection which has not yet closed gracefully,
1611  * or which still has a pending transmission (e.g. to ACK the
1612  * received FIN).
1613  */
1614  list_for_each_entry ( tcp, &tcp_conns, list ) {
1615  if ( ( ! TCP_CLOSED_GRACEFULLY ( tcp->tcp_state ) ) ||
1616  process_running ( &tcp->process ) ) {
1617  return tcp;
1618  }
1619  }
1620  return NULL;
1621 }
A TCP connection.
Definition: tcp.c:33
unsigned int tcp_state
Current TCP state.
Definition: tcp.c:53
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:420
static int process_running(struct process *process)
Check if process is running.
Definition: process.h:175
struct process process
Transmission process.
Definition: tcp.c:114
struct list_head list
List of TCP connections.
Definition: tcp.c:37
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
#define TCP_CLOSED_GRACEFULLY(state)
Have closed gracefully.
Definition: tcp.h:316

References tcp_connection::list, list_for_each_entry, NULL, tcp_connection::process, process_running(), TCP_CLOSED_GRACEFULLY, and tcp_connection::tcp_state.

Referenced by tcp_shutdown().

◆ tcp_shutdown()

static void tcp_shutdown ( int booting  __unused)
static

Shut down all TCP connections.

Definition at line 1627 of file tcp.c.

1627  {
1628  struct tcp_connection *tcp;
1629  unsigned long start;
1630  unsigned long elapsed;
1631 
1632  /* Initiate a graceful close of all connections, allowing for
1633  * the fact that the connection list may change as we do so.
1634  */
1635  while ( ( tcp = tcp_first_unclosed() ) ) {
1636  DBGC ( tcp, "TCP %p closing for shutdown\n", tcp );
1637  tcp_close ( tcp, -ECANCELED );
1638  }
1639 
1640  /* Wait for all connections to finish closing gracefully */
1641  start = currticks();
1642  while ( ( tcp = tcp_first_unfinished() ) &&
1643  ( ( elapsed = ( currticks() - start ) ) < TCP_FINISH_TIMEOUT )){
1644  step();
1645  }
1646 
1647  /* Forcibly close any remaining connections */
1648  while ( ( tcp = list_first_entry ( &tcp_conns, struct tcp_connection,
1649  list ) ) != NULL ) {
1650  tcp->tcp_state = TCP_CLOSED;
1651  tcp_dump_state ( tcp );
1652  tcp_close ( tcp, -ECANCELED );
1653  }
1654 }
A TCP connection.
Definition: tcp.c:33
unsigned int tcp_state
Current TCP state.
Definition: tcp.c:53
#define DBGC(...)
Definition: compiler.h:505
#define ECANCELED
Operation canceled.
Definition: errno.h:343
uint32_t start
Starting offset.
Definition: netvsc.h:12
#define list_first_entry(list, type, member)
Get the container of the first entry in a list.
Definition: list.h:333
static void tcp_close(struct tcp_connection *tcp, int rc)
Close TCP connection.
Definition: tcp.c:349
static struct tcp_connection * tcp_first_unclosed(void)
Find first TCP connection that has not yet been closed.
Definition: tcp.c:1591
static struct tcp_connection * tcp_first_unfinished(void)
Find first TCP connection that has not yet finished all operations.
Definition: tcp.c:1607
struct list_head list
List of TCP connections.
Definition: tcp.c:37
void step(void)
Single-step a single process.
Definition: process.c:98
#define TCP_FINISH_TIMEOUT
TCP finish wait time.
Definition: tcp.h:434
unsigned long currticks(void)
Get current system time in ticks.
Definition: timer.c:42
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
#define TCP_CLOSED
CLOSED.
Definition: tcp.h:202
static void tcp_dump_state(struct tcp_connection *tcp)
Dump TCP state transition.
Definition: tcp.c:218

References currticks(), DBGC, ECANCELED, tcp_connection::list, list_first_entry, NULL, start, step(), tcp_close(), TCP_CLOSED, tcp_dump_state(), TCP_FINISH_TIMEOUT, tcp_first_unclosed(), tcp_first_unfinished(), and tcp_connection::tcp_state.

◆ __startup_fn()

struct startup_fn tcp_startup_fn __startup_fn ( STARTUP_LATE  )

TCP shutdown function.

◆ tcp_xfer_close()

static void tcp_xfer_close ( struct tcp_connection tcp,
int  rc 
)
static

Close interface.

Parameters
tcpTCP connection
rcReason for close

Definition at line 1675 of file tcp.c.

1675  {
1676 
1677  /* Close data transfer interface */
1678  tcp_close ( tcp, rc );
1679 
1680  /* Transmit FIN, if possible */
1681  tcp_xmit ( tcp );
1682 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
static void tcp_close(struct tcp_connection *tcp, int rc)
Close TCP connection.
Definition: tcp.c:349
static void tcp_xmit(struct tcp_connection *tcp)
Transmit any outstanding data.
Definition: tcp.c:769

References rc, tcp_close(), and tcp_xmit().

◆ tcp_xfer_deliver()

static int tcp_xfer_deliver ( struct tcp_connection tcp,
struct io_buffer iobuf,
struct xfer_metadata *meta  __unused 
)
static

Deliver datagram as I/O buffer.

Parameters
tcpTCP connection
iobufDatagram I/O buffer
metaData transfer metadata
Return values
rcReturn status code

Definition at line 1692 of file tcp.c.

1694  {
1695 
1696  /* Enqueue packet */
1697  list_add_tail ( &iobuf->list, &tcp->tx_queue );
1698 
1699  /* Each enqueued packet is a pending operation */
1700  pending_get ( &tcp->pending_data );
1701 
1702  /* Transmit data, if possible */
1703  tcp_xmit ( tcp );
1704 
1705  return 0;
1706 }
struct pending_operation pending_data
Pending operations for transmit queue.
Definition: tcp.c:125
struct list_head tx_queue
Transmit queue.
Definition: tcp.c:110
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition: list.h:93
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:39
static void tcp_xmit(struct tcp_connection *tcp)
Transmit any outstanding data.
Definition: tcp.c:769
void pending_get(struct pending_operation *pending)
Mark an operation as pending.
Definition: pending.c:45

References io_buffer::list, list_add_tail, tcp_connection::pending_data, pending_get(), tcp_xmit(), and tcp_connection::tx_queue.

◆ tcp_progress()

static int tcp_progress ( struct tcp_connection tcp,
struct job_progress progress 
)
static

Report job progress.

Parameters
tcpTCP connection
progressProgress report to fill in
Return values
ongoing_rcOngoing job status code (if known)

Definition at line 1715 of file tcp.c.

1716  {
1717 
1718  /* Report connection in progress if applicable */
1719  if ( ! TCP_HAS_BEEN_ESTABLISHED ( tcp->tcp_state ) ) {
1720  snprintf ( progress->message, sizeof ( progress->message ),
1721  "connecting" );
1722  }
1723 
1724  return 0;
1725 }
unsigned int tcp_state
Current TCP state.
Definition: tcp.c:53
#define TCP_HAS_BEEN_ESTABLISHED(state)
Have ever been fully established.
Definition: tcp.h:306
char message[32]
Message (optional)
Definition: job.h:32
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition: vsprintf.c:382

References job_progress::message, snprintf(), TCP_HAS_BEEN_ESTABLISHED, and tcp_connection::tcp_state.

◆ tcp_open_uri()

static int tcp_open_uri ( struct interface xfer,
struct uri uri 
)
static

Open TCP URI.

Parameters
xferData transfer interface
uriURI
Return values
rcReturn status code

Definition at line 1770 of file tcp.c.

1770  {
1771  struct sockaddr_tcpip peer;
1772 
1773  /* Sanity check */
1774  if ( ! uri->host )
1775  return -EINVAL;
1776 
1777  memset ( &peer, 0, sizeof ( peer ) );
1778  peer.st_port = htons ( uri_port ( uri, 0 ) );
1779  return xfer_open_named_socket ( xfer, SOCK_STREAM,
1780  ( struct sockaddr * ) &peer,
1781  uri->host, NULL );
1782 }
#define EINVAL
Invalid argument.
Definition: errno.h:428
TCP/IP socket address.
Definition: tcpip.h:75
Generalized socket address structure.
Definition: socket.h:96
#define SOCK_STREAM
Definition: socket.h:24
const char * host
Host name.
Definition: uri.h:62
unsigned int uri_port(const struct uri *uri, unsigned int default_port)
Get port from URI.
Definition: uri.c:441
A Uniform Resource Identifier.
Definition: uri.h:50
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
#define htons(value)
Definition: byteswap.h:135
int xfer_open_named_socket(struct interface *xfer, int semantics, struct sockaddr *peer, const char *name, struct sockaddr *local)
Open named socket.
Definition: resolv.c:402
void * memset(void *dest, int character, size_t len) __nonnull

References EINVAL, uri::host, htons, memset(), NULL, SOCK_STREAM, sockaddr_tcpip::st_port, uri_port(), and xfer_open_named_socket().

Variable Documentation

◆ __profiler

struct profiler tcp_xfer_profiler __profiler = { .name = "tcp.tx" }
static

Transmit profiler.

Data transfer profiler.

Receive profiler.

Definition at line 171 of file tcp.c.

◆ tcp_process_desc

static struct process_descriptor tcp_process_desc
static
Initial value:
=
A TCP connection.
Definition: tcp.c:33
A process.
Definition: process.h:17
#define PROC_DESC_ONCE(object_type, process, _step)
Define a process descriptor for a process that runs only once.
Definition: process.h:97
static void tcp_xmit(struct tcp_connection *tcp)
Transmit any outstanding data.
Definition: tcp.c:769

TCP process descriptor.

Definition at line 180 of file tcp.c.

Referenced by tcp_open().

◆ tcp_xfer_desc

static struct interface_descriptor tcp_xfer_desc
static
Initial value:
=
A TCP connection.
Definition: tcp.c:33
static struct interface_operation tcp_xfer_operations[]
TCP data transfer interface operations.
Definition: tcp.c:1728
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition: interface.h:65

TCP data transfer interface descriptor.

Definition at line 181 of file tcp.c.

Referenced by tcp_open().

◆ __tcpip_protocol

struct tcpip_protocol tcp_protocol __tcpip_protocol
Initial value:
= {
.name = "TCP",
.rx = tcp_rx,
.tcpip_proto = IP_TCP,
}
static int tcp_rx(struct io_buffer *iobuf, struct net_device *netdev __unused, struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest __unused, uint16_t pshdr_csum)
Process received packet.
Definition: tcp.c:1395
#define IP_TCP
Definition: in.h:13

TCP protocol.

ICMPv4 TCP/IP protocol.

Definition at line 1548 of file tcp.c.

◆ tcp_xfer_operations

struct interface_operation tcp_xfer_operations[]
static
Initial value:
= {
}
A TCP connection.
Definition: tcp.c:33
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:244
static size_t tcp_xfer_window(struct tcp_connection *tcp)
Check data-transfer flow control window.
Definition: tcp.c:453
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition: xfer.c:115
Job progress.
Definition: job.h:15
static void tcp_xfer_close(struct tcp_connection *tcp, int rc)
Close interface.
Definition: tcp.c:1675
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:32
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:193
static int tcp_progress(struct tcp_connection *tcp, struct job_progress *progress)
Report job progress.
Definition: tcp.c:1715
static int tcp_xfer_deliver(struct tcp_connection *tcp, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
Deliver datagram as I/O buffer.
Definition: tcp.c:1692

TCP data transfer interface operations.

Definition at line 1728 of file tcp.c.

◆ __socket_opener

struct socket_opener tcp_ipv6_socket_opener __socket_opener
Initial value:
= {
.semantics = TCP_SOCK_STREAM,
.family = AF_INET,
.open = tcp_open,
}
#define TCP_SOCK_STREAM
Definition: socket.h:23
static int tcp_open(struct interface *xfer, struct sockaddr *peer, struct sockaddr *local)
Open a TCP connection.
Definition: tcp.c:273
#define AF_INET
IPv4 Internet addresses.
Definition: socket.h:63

TCP IPv4 socket opener.

TCP IPv6 socket opener.

Definition at line 1747 of file tcp.c.

◆ __uri_opener

struct uri_opener tcp_uri_opener __uri_opener
Initial value:
= {
.scheme = "tcp",
.open = tcp_open_uri,
}
static int tcp_open_uri(struct interface *xfer, struct uri *uri)
Open TCP URI.
Definition: tcp.c:1770

TCP URI opener.

Definition at line 1785 of file tcp.c.