Microchip® Advanced Software Framework

tcp_out.c File Reference

Transmission Control Protocol, outgoing traffic.

The output functions of TCP.

#include "lwip/opt.h"
#include "lwip/tcp_impl.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/inet_chksum.h"
#include "lwip/stats.h"
#include "lwip/snmp.h"
#include "lwip/ip6.h"
#include "lwip/ip6_addr.h"
#include <string.h>

Macros

#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK   0
 Define this to 1 for an extra check that the output checksum is valid (usefule when the checksum is generated by the application, not the stack) More...
 
#define TCP_DATA_COPY(dst, src, len, seg)   MEMCPY(dst, src, len)
 
#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped)   MEMCPY(dst, src, len)
 
#define TCP_OVERSIZE_CALC_LENGTH(length)   ((length) + TCP_OVERSIZE)
 The size of segment pbufs created when TCP_OVERSIZE is enabled. More...
 

Functions

static struct tcp_segtcp_create_segment (struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, u8_t optflags)
 Create a TCP segment with prefilled header. More...
 
err_t tcp_enqueue_flags (struct tcp_pcb *pcb, u8_t flags)
 Enqueue TCP options for transmission. More...
 
void tcp_keepalive (struct tcp_pcb *pcb)
 Send keepalive packets to keep a connection active although no data is sent over it. More...
 
err_t tcp_output (struct tcp_pcb *pcb)
 Find out what we can send and send it. More...
 
static struct pbuftcp_output_alloc_header (struct tcp_pcb *pcb, u16_t optlen, u16_t datalen, u32_t seqno_be)
 Allocate a pbuf and create a tcphdr at p->payload, used for output functions other than the default tcp_output -> tcp_output_segment (e.g. More...
 
static void tcp_output_segment (struct tcp_seg *seg, struct tcp_pcb *pcb)
 Called by tcp_output() to actually send a TCP segment over IP. More...
 
static struct pbuftcp_pbuf_prealloc (pbuf_layer layer, u16_t length, u16_t max_length, u16_t *oversize, struct tcp_pcb *pcb, u8_t apiflags, u8_t first_seg)
 Allocate a PBUF_RAM pbuf, perhaps with extra space at the end. More...
 
void tcp_rexmit (struct tcp_pcb *pcb)
 Requeue the first unacked segment for retransmission. More...
 
void tcp_rexmit_fast (struct tcp_pcb *pcb)
 Handle retransmission after three dupacks received. More...
 
void tcp_rexmit_rto (struct tcp_pcb *pcb)
 Requeue all unacked segments for retransmission. More...
 
void tcp_rst_impl (u32_t seqno, u32_t ackno, ipX_addr_t *local_ip, ipX_addr_t *remote_ip, u16_t local_port, u16_t remote_port, u8_t isipv6)
 Send a TCP RESET packet (empty segment with RST flag set) either to abort a connection or to show that there is no matching local connection for a received segment. More...
 
err_t tcp_send_empty_ack (struct tcp_pcb *pcb)
 Send an ACK without data. More...
 
err_t tcp_send_fin (struct tcp_pcb *pcb)
 Called by tcp_close() to send a segment including FIN flag but not data. More...
 
err_t tcp_write (struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
 Write data for sending (but does not send it immediately). More...
 
static err_t tcp_write_checks (struct tcp_pcb *pcb, u16_t len)
 Checks if tcp_write is allowed or not (checks state, snd_buf and snd_queuelen). More...
 
void tcp_zero_window_probe (struct tcp_pcb *pcb)
 Send persist timer zero-window probes to keep a connection active when a window update is lost. More...
 

#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK   0

Define this to 1 for an extra check that the output checksum is valid (usefule when the checksum is generated by the application, not the stack)

#define TCP_DATA_COPY (   dst,
  src,
  len,
  seg 
)    MEMCPY(dst, src, len)

Referenced by tcp_write().

#define TCP_DATA_COPY2 (   dst,
  src,
  len,
  chksum,
  chksum_swapped 
)    MEMCPY(dst, src, len)

Referenced by tcp_write().

#define TCP_OVERSIZE_CALC_LENGTH (   length)    ((length) + TCP_OVERSIZE)

The size of segment pbufs created when TCP_OVERSIZE is enabled.

Referenced by tcp_pbuf_prealloc().

static struct tcp_seg* tcp_create_segment ( struct tcp_pcb pcb,
struct pbuf p,
u8_t  flags,
u32_t  seqno,
u8_t  optflags 
)
static

Create a TCP segment with prefilled header.

Called by tcp_write and tcp_enqueue_flags.

Parameters
pcbProtocol control block for the TCP connection.
ppbuf that is used to hold the TCP header.
flagsTCP flags for header.
seqnoTCP sequence number of this packet
optflagsoptions to include in TCP header
Returns
a new tcp_seg pointing to p, or NULL. The TCP header is filled in except ackno and wnd. p is freed on failure.

References tcp_seg::flags, htonl, htons, tcp_seg::len, LWIP_ASSERT, LWIP_DEBUGF, LWIP_TCP_OPT_LENGTH, memp_malloc(), tcp_seg::next, NULL, tcp_seg::p, pbuf::payload, pbuf_free(), pbuf_header(), tcp_pcb::remote_port, TCP_HLEN, TCP_OUTPUT_DEBUG, tcp_seg_free(), TCP_STATS_INC, TCPH_HDRLEN_FLAGS_SET, tcp_seg::tcphdr, TF_SEG_DATA_CHECKSUMMED, and pbuf::tot_len.

Referenced by tcp_enqueue_flags(), and tcp_write().

err_t tcp_enqueue_flags ( struct tcp_pcb pcb,
u8_t  flags 
)
void tcp_keepalive ( struct tcp_pcb pcb)

Send keepalive packets to keep a connection active although no data is sent over it.

Called by tcp_slowtmr()

Parameters
pcbthe tcp_pcb for which to send a keepalive packet

References htonl, IP_PROTO_TCP, ipX_addr_debug_print, ipX_chksum_pseudo, ipX_output, ipX_output_hinted, tcp_pcb::keep_cnt_sent, LWIP_DEBUGF, NULL, pbuf::payload, pbuf_free(), PCB_ISIPV6, tcp_pcb::rcv_nxt, tcp_pcb::snd_nxt, TCP_DEBUG, tcp_output_alloc_header(), TCP_STATS_INC, tcp_ticks, tcphdr, tcp_pcb::tmr, pbuf::tot_len, U16_F, and U32_F.

Referenced by tcp_slowtmr().

static struct pbuf* tcp_output_alloc_header ( struct tcp_pcb pcb,
u16_t  optlen,
u16_t  datalen,
u32_t  seqno_be 
)
static

Allocate a pbuf and create a tcphdr at p->payload, used for output functions other than the default tcp_output -> tcp_output_segment (e.g.

tcp_send_empty_ack, etc.)

Parameters
pcbtcp pcb for which to send a packet (used to initialize tcp_hdr)
optlenlength of header-options
datalenlength of tcp data to reserve in pbuf
seqno_beseqno in network byte order (big-endian)
Returns
pbuf with p->payload being the tcp_hdr

References htonl, htons, pbuf::len, LWIP_ASSERT, NULL, pbuf::payload, pbuf_alloc(), PBUF_IP, PBUF_RAM, tcp_pcb::rcv_ann_right_edge, tcp_pcb::rcv_ann_wnd, tcp_pcb::rcv_nxt, RCV_WND_SCALE, tcp_pcb::remote_port, TCP_ACK, TCP_HLEN, TCPH_HDRLEN_FLAGS_SET, and tcphdr.

Referenced by tcp_keepalive(), tcp_send_empty_ack(), and tcp_zero_window_probe().

static struct pbuf* tcp_pbuf_prealloc ( pbuf_layer  layer,
u16_t  length,
u16_t  max_length,
u16_t oversize,
struct tcp_pcb pcb,
u8_t  apiflags,
u8_t  first_seg 
)
static

Allocate a PBUF_RAM pbuf, perhaps with extra space at the end.

This function is like pbuf_alloc(layer, length, PBUF_RAM) except there may be extra bytes available at the end.

Parameters
layerflag to define header size.
lengthsize of the pbuf's payload.
max_lengthmaximum usable size of payload+oversize.
oversizepointer to a u16_t that will receive the number of usable tail bytes.
pcbThe TCP connection that willo enqueue the pbuf.
apiflagsAPI flags given to tcp_write.
first_segtrue when this pbuf will be used in the first enqueued segment.

References tcp_pcb::flags, pbuf::len, LWIP_ASSERT, LWIP_MEM_ALIGN_SIZE, LWIP_MIN, pbuf::next, NULL, pbuf_alloc(), PBUF_RAM, TCP_OVERSIZE_CALC_LENGTH, TCP_WRITE_FLAG_MORE, TF_NODELAY, pbuf::tot_len, tcp_pcb::unacked, and tcp_pcb::unsent.

Referenced by tcp_write().

void tcp_rexmit ( struct tcp_pcb pcb)

Requeue the first unacked segment for retransmission.

Called by tcp_receive() for fast retramsmit.

Parameters
pcbthe tcp_pcb for which to retransmit the first unacked segment

References tcp_seg::next, tcp_pcb::nrtx, ntohl, NULL, tcp_pcb::rttest, snmp_inc_tcpretranssegs, TCP_SEQ_LT, tcp_seg::tcphdr, tcp_pcb::unacked, tcp_pcb::unsent, and tcp_pcb::unsent_oversize.

Referenced by tcp_process(), and tcp_rexmit_fast().

void tcp_rexmit_fast ( struct tcp_pcb pcb)

Handle retransmission after three dupacks received.

Parameters
pcbthe tcp_pcb for which to retransmit the first unacked segment

References tcp_pcb::cwnd, tcp_pcb::dupacks, tcp_pcb::flags, tcp_pcb::lastack, LWIP_DEBUGF, tcp_pcb::mss, ntohl, NULL, tcp_pcb::snd_wnd, tcp_pcb::ssthresh, TCP_FR_DEBUG, tcp_rexmit(), tcp_seg::tcphdr, TF_INFR, U16_F, U32_F, and tcp_pcb::unacked.

Referenced by tcp_receive().

void tcp_rexmit_rto ( struct tcp_pcb pcb)

Requeue all unacked segments for retransmission.

Called by tcp_slowtmr() for slow retransmission.

Parameters
pcbthe tcp_pcb for which to re-enqueue all unacked segments

References tcp_seg::next, tcp_pcb::nrtx, NULL, tcp_pcb::rttest, tcp_output(), tcp_pcb::unacked, tcp_pcb::unsent, and tcp_pcb::unsent_oversize.

Referenced by tcp_slowtmr().

void tcp_rst_impl ( u32_t  seqno,
u32_t  ackno,
ipX_addr_t local_ip,
ipX_addr_t remote_ip,
u16_t  local_port,
u16_t  remote_port,
u8_t  isipv6 
)

Send a TCP RESET packet (empty segment with RST flag set) either to abort a connection or to show that there is no matching local connection for a received segment.

Called by tcp_abort() (to abort a local connection), tcp_input() (if no matching local pcb was found), tcp_listen_input() (if incoming segment has ACK flag set) and tcp_process() (received segment in the wrong state)

Since a RST segment is in most cases not sent for an active connection, tcp_rst() has a number of arguments that are taken from a tcp_pcb for most other segment output functions.

Parameters
seqnothe sequence number to use for the outgoing segment
acknothe acknowledge number to use for the outgoing segment
local_ipthe local IP address to send the segment from
remote_ipthe remote IP address to send the segment to
local_portthe local TCP port to send the segment from
remote_portthe remote TCP port to send the segment to

References htonl, htons, IP_PROTO_TCP, ipX_chksum_pseudo, ipX_output, pbuf::len, LWIP_ASSERT, LWIP_DEBUGF, NULL, pbuf::payload, pbuf_alloc(), pbuf_free(), PBUF_IP, PBUF_RAM, PP_HTONS, snmp_inc_tcpoutrsts, TCP_ACK, TCP_DEBUG, TCP_HLEN, TCP_RST, TCP_RST_DEBUG, TCP_STATS_INC, TCP_WND, TCPH_HDRLEN_FLAGS_SET, tcphdr, pbuf::tot_len, and U32_F.

err_t tcp_send_empty_ack ( struct tcp_pcb pcb)
err_t tcp_send_fin ( struct tcp_pcb pcb)

Called by tcp_close() to send a segment including FIN flag but not data.

Parameters
pcbthe tcp_pcb over which to send a segment
Returns
ERR_OK if sent, another err_t otherwise

References ERR_OK, tcp_pcb::flags, tcp_seg::next, NULL, tcp_enqueue_flags(), TCP_FIN, TCP_RST, TCP_SYN, TCPH_FLAGS, TCPH_SET_FLAG, tcp_seg::tcphdr, TF_FIN, and tcp_pcb::unsent.

Referenced by tcp_close_shutdown().

err_t tcp_write ( struct tcp_pcb pcb,
const void arg,
u16_t  len,
u8_t  apiflags 
)

Write data for sending (but does not send it immediately).

It waits in the expectation of more data being sent soon (as it can send them more efficiently by combining them together). To prompt the system to send data now, call tcp_output() after calling tcp_write().

Parameters
pcbProtocol control block for the TCP connection to enqueue data for.
argPointer to the data to be enqueued for sending.
lenData length in bytes
apiflagscombination of following flags :
  • TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack
  • TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent,
Returns
ERR_OK if enqueued, another err_t on error

References ERR_ARG, ERR_MEM, ERR_OK, tcp_pcb::flags, tcp_seg::flags, inet_chksum(), pbuf::len, tcp_seg::len, LWIP_ASSERT, LWIP_DBG_STATE, LWIP_DBG_TRACE, LWIP_DEBUGF, LWIP_ERROR(), LWIP_MAX, LWIP_MIN, LWIP_TCP_OPT_LENGTH, tcp_pcb::mss, pbuf::next, tcp_seg::next, ntohl, NULL, tcp_seg::p, pbuf::payload, pbuf_alloc(), pbuf_cat(), pbuf_clen(), pbuf_free(), PBUF_RAM, PBUF_RAW, PBUF_ROM, PBUF_TRANSPORT, S16_F, tcp_pcb::snd_buf, tcp_pcb::snd_lbb, tcp_pcb::snd_queuelen, tcp_pcb::snd_wnd_max, SWAP_BYTES_IN_WORD, tcp_create_segment(), TCP_DATA_COPY, TCP_DATA_COPY2, TCP_OUTPUT_DEBUG, tcp_pbuf_prealloc(), TCP_PSH, TCP_QLEN_DEBUG, tcp_segs_free(), TCP_SND_QUEUELEN, TCP_SNDQUEUELEN_OVERFLOW, TCP_STATS_INC, TCP_TCPLEN, tcp_write_checks(), TCP_WRITE_FLAG_COPY, TCP_WRITE_FLAG_MORE, TCPH_SET_FLAG, TCPWNDSIZE_F, TF_NAGLEMEMERR, TF_SEG_DATA_CHECKSUMMED, TF_SEG_OPTS_TS, TF_TIMESTAMP, pbuf::tot_len, U16_F, U32_F, tcp_pcb::unacked, tcp_pcb::unsent, and tcp_pcb::unsent_oversize.

Referenced by lwip_netconn_do_writemore().

static err_t tcp_write_checks ( struct tcp_pcb pcb,
u16_t  len 
)
static

Checks if tcp_write is allowed or not (checks state, snd_buf and snd_queuelen).

Parameters
pcbthe tcp pcb to check for
lenlength of data to send (checked agains snd_buf)
Returns
ERR_OK if tcp_write is allowed to proceed, another err_t otherwise

References CLOSE_WAIT, ERR_CONN, ERR_MEM, ERR_OK, ESTABLISHED, tcp_pcb::flags, LWIP_ASSERT, LWIP_DBG_LEVEL_SEVERE, LWIP_DBG_STATE, LWIP_DEBUGF, NULL, tcp_pcb::snd_buf, tcp_pcb::snd_queuelen, SYN_RCVD, SYN_SENT, TCP_OUTPUT_DEBUG, TCP_QLEN_DEBUG, TCP_SND_QUEUELEN, TCP_SNDQUEUELEN_OVERFLOW, TCP_STATS_INC, TCPWNDSIZE_F, TF_NAGLEMEMERR, U16_F, tcp_pcb::unacked, and tcp_pcb::unsent.

Referenced by tcp_write().

void tcp_zero_window_probe ( struct tcp_pcb pcb)