• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * @file
3  * TCP API (to be used from TCPIP thread)\n
4  * See also @ref tcp_raw
5  */
6 
7 /*
8  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without modification,
12  * are permitted provided that the following conditions are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright notice,
15  *    this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright notice,
17  *    this list of conditions and the following disclaimer in the documentation
18  *    and/or other materials provided with the distribution.
19  * 3. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
23  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31  * OF SUCH DAMAGE.
32  *
33  * This file is part of the lwIP TCP/IP stack.
34  *
35  * Author: Adam Dunkels <adam@sics.se>
36  *
37  */
38 #ifndef LWIP_HDR_TCP_H
39 #define LWIP_HDR_TCP_H
40 
41 #include "lwip/opt.h"
42 
43 #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
44 
45 #include "lwip/tcpbase.h"
46 #include "lwip/mem.h"
47 #include "lwip/pbuf.h"
48 #include "lwip/ip.h"
49 #include "lwip/icmp.h"
50 #include "lwip/err.h"
51 #include "lwip/ip6.h"
52 #include "lwip/ip6_addr.h"
53 
54 #ifdef __cplusplus
55 extern "C" {
56 #endif
57 
58 #define TCP_SND_QUEUELEN_LOWAT_THRES  5
59 
60 struct tcp_pcb;
61 struct tcp_pcb_listen;
62 
63 /** Function prototype for tcp accept callback functions. Called when a new
64  * connection can be accepted on a listening pcb.
65  *
66  * @param arg Additional argument to pass to the callback function (@see tcp_arg())
67  * @param newpcb The new connection pcb
68  * @param err An error code if there has been an error accepting.
69  *            Only return ERR_ABRT if you have called tcp_abort from within the
70  *            callback function!
71  */
72 typedef err_t (*tcp_accept_fn)(void *arg, struct tcp_pcb *newpcb, err_t err);
73 
74 /** Function prototype for tcp receive callback functions. Called when data has
75  * been received.
76  *
77  * @param arg Additional argument to pass to the callback function (@see tcp_arg())
78  * @param tpcb The connection pcb which received data
79  * @param p The received data (or NULL when the connection has been closed!)
80  * @param err An error code if there has been an error receiving
81  *            Only return ERR_ABRT if you have called tcp_abort from within the
82  *            callback function!
83  */
84 typedef err_t (*tcp_recv_fn)(void *arg, struct tcp_pcb *tpcb,
85                              struct pbuf *p, err_t err);
86 
87 /** Function prototype for tcp sent callback functions. Called when sent data has
88  * been acknowledged by the remote side. Use it to free corresponding resources.
89  * This also means that the pcb has now space available to send new data.
90  *
91  * @param arg Additional argument to pass to the callback function (@see tcp_arg())
92  * @param tpcb The connection pcb for which data has been acknowledged
93  * @param len The amount of bytes acknowledged
94  * @return ERR_OK: try to send some data by calling tcp_output
95  *            Only return ERR_ABRT if you have called tcp_abort from within the
96  *            callback function!
97  */
98 typedef err_t (*tcp_sent_fn)(void *arg, struct tcp_pcb *tpcb,
99                               u16_t len);
100 
101 /** Function prototype for tcp poll callback functions. Called periodically as
102  * specified by @see tcp_poll.
103  *
104  * @param arg Additional argument to pass to the callback function (@see tcp_arg())
105  * @param tpcb tcp pcb
106  * @return ERR_OK: try to send some data by calling tcp_output
107  *            Only return ERR_ABRT if you have called tcp_abort from within the
108  *            callback function!
109  */
110 typedef err_t (*tcp_poll_fn)(void *arg, struct tcp_pcb *tpcb);
111 
112 /** Function prototype for tcp error callback functions. Called when the pcb
113  * receives a RST or is unexpectedly closed for any other reason.
114  *
115  * @note The corresponding pcb is already freed when this callback is called!
116  *
117  * @param arg Additional argument to pass to the callback function (@see tcp_arg())
118  * @param err Error code to indicate why the pcb has been closed
119  *            ERR_ABRT: aborted through tcp_abort or by a TCP timer
120  *            ERR_RST: the connection was reset by the remote host
121  */
122 typedef void  (*tcp_err_fn)(void *arg, err_t err);
123 
124 /** Function prototype for tcp connected callback functions. Called when a pcb
125  * is connected to the remote side after initiating a connection attempt by
126  * calling tcp_connect().
127  *
128  * @param arg Additional argument to pass to the callback function (@see tcp_arg())
129  * @param tpcb The connection pcb which is connected
130  * @param err An unused error code, always ERR_OK currently ;-) @todo!
131  *            Only return ERR_ABRT if you have called tcp_abort from within the
132  *            callback function!
133  *
134  * @note When a connection attempt fails, the error callback is currently called!
135  */
136 typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err);
137 
138 #if DRIVER_STATUS_CHECK
139 typedef void (*tcp_event_sndplus_fn)(void *arg, const struct tcp_pcb *tpcb);
140 #endif
141 
142 #if LWIP_WND_SCALE
143 #define RCV_WND_SCALE(pcb, wnd) (((wnd) >> (pcb)->rcv_scale))
144 #define SND_WND_SCALE(pcb, wnd) (((tcpwnd_size_t)(wnd)  << (pcb)->snd_scale))
145 #define TCPWND16(x)             ((u16_t)LWIP_MIN((x), 0xFFFF))
146 #define TCP_WND_MAX(pcb)        ((tcpwnd_size_t)(((pcb)->flags & TF_WND_SCALE) ? TCP_WND : TCPWND16(TCP_WND)))
147 #else
148 #define RCV_WND_SCALE(pcb, wnd) (wnd)
149 #define SND_WND_SCALE(pcb, wnd) (wnd)
150 #define TCPWND16(x)             (x)
151 #define TCP_WND_MAX(pcb)        TCP_WND
152 #endif
153 /* Increments a tcpwnd_size_t and holds at max value rather than rollover */
154 #define TCP_WND_INC(wnd, inc) do { \
155   if ((tcpwnd_size_t)((wnd) + (inc)) >= (wnd)) { \
156     (wnd) = (tcpwnd_size_t)((wnd) + (inc)); \
157   } else { \
158     (wnd) = (tcpwnd_size_t) - 1; \
159   } \
160   } while (0)
161 
162 #define TCP_WND_DEC(wnd, dec, mss) do { \
163   if ((wnd) >= (dec) && (wnd) >= (mss)) { \
164     (wnd) = (tcpwnd_size_t)(wnd - (dec)); \
165   } else { \
166     (wnd) = (mss); \
167   } \
168   } while (0)
169 
170 #ifndef LWIP_INITIAL_CWND_OVERRIDE
171 /*
172   [RFC 5681] [3.1.  Slow Start and Congestion Avoidance]
173   IW, the initial value of cwnd, MUST be set using the following guidelines as an upper bound.
174 */
175 #define LWIP_TCP_CALC_INITIAL_CWND(SMSS, IW) do { \
176   if ((SMSS) > 2190){ \
177     IW = (tcpwnd_size_t)(2 * LWIP_MIN(SMSS, TCP_MAX_MSS)); \
178   } else if (((SMSS) > 1095) && ((SMSS) <= 2190)) { \
179     IW = (tcpwnd_size_t)(3 * LWIP_MIN(SMSS, TCP_MAX_MSS)); \
180   } else if ((SMSS) <= 1095) { \
181     IW = (tcpwnd_size_t)(4 * LWIP_MIN(SMSS, TCP_MAX_MSS)); \
182   } \
183   } while (0)
184 #else
185 #define LWIP_TCP_CALC_INITIAL_CWND(SMSS, IW) do { \
186   IW = (tcpwnd_size_t)(LWIP_INITIAL_CWND_OVERRIDE * (SMSS)); \
187 } while (0)
188 #endif
189 
190 /* Increments a wnd * mss and holds at max value rather than rollover */
191 #define TCP_CALC_SSTHRESH(pcb, ssthresh, wnd, mss) do { \
192   if (((u64_t)(wnd) * (mss))  < TCP_WND_MAX(pcb)) { \
193     (ssthresh) = (tcpwnd_size_t)((wnd) * (mss)); \
194   } else { \
195     (ssthresh) = TCP_WND_MAX(pcb); \
196   } \
197   } while (0)
198 
199 #ifndef LWIP_CONGCNTRL_DUPACK_THRESH
200 /** Congestion Control duplicate Acknowledgement Threshold */
201 #define DUPACK_THRESH       3
202 #else
203 #define DUPACK_THRESH       LWIP_CONGCNTRL_DUPACK_THRESH
204 #endif
205 
206 /** Initial Congestion Control Window (by MSS). */
207 #define INITIAL_CWND           4U
208 
209 #ifndef LWIP_CONGCNTRL_INITIAL_SSTHRESH
210 /** Initial Congestion Control Slow Start Threshold. */
211 #define INITIAL_SSTHRESH       40
212 #else
213 #define INITIAL_SSTHRESH       LWIP_CONGCNTRL_INITIAL_SSTHRESH
214 #endif
215 
216 #if DRIVER_STATUS_CHECK
217 #define DRV_READY         1
218 #define DRV_NOT_READY     0
219 #endif
220 
221 /* Indicates that this pbuf includes a TCP FIN flag and post to mbox is failed */
222 #define TCP_PBUF_FLAG_TCP_FIN_RECV_SYSPOST_FAIL 0x01U
223 
224 /* Adding for SACK */
225 #if LWIP_SACK
226 struct _sack_seq {
227   struct _sack_seq *next;
228   u32_t left;
229   u32_t right;
230   u32_t order;
231 };
232 #endif
233 
234 #if LWIP_SACK_PERF_OPT
235 struct tcp_sack_fast_rxmited {
236   struct tcp_sack_fast_rxmited *next;
237   struct tcp_seg *seg;
238 };
239 #endif
240 
241 /** Function prototype for deallocation of arguments. Called *just before* the
242  * pcb is freed, so don't expect to be able to do anything with this pcb!
243  *
244  * @param id ext arg id (allocated via @ref tcp_ext_arg_alloc_id)
245  * @param data pointer to the data (set via @ref tcp_ext_arg_set before)
246  */
247 typedef void (*tcp_extarg_callback_pcb_destroyed_fn)(u8_t id, void *data);
248 
249 /** Function prototype to transition arguments from a listening pcb to an accepted pcb
250  *
251  * @param id ext arg id (allocated via @ref tcp_ext_arg_alloc_id)
252  * @param lpcb the listening pcb accepting a connection
253  * @param cpcb the newly allocated connection pcb
254  * @return ERR_OK if OK, any error if connection should be dropped
255  */
256 typedef err_t (*tcp_extarg_callback_passive_open_fn)(u8_t id, struct tcp_pcb_listen *lpcb, struct tcp_pcb *cpcb);
257 
258 /** A table of callback functions that is invoked for ext arguments */
259 struct tcp_ext_arg_callbacks {
260   /** @ref tcp_extarg_callback_pcb_destroyed_fn */
261   tcp_extarg_callback_pcb_destroyed_fn destroy;
262   /** @ref tcp_extarg_callback_passive_open_fn */
263   tcp_extarg_callback_passive_open_fn passive_open;
264 };
265 
266 #define LWIP_TCP_PCB_NUM_EXT_ARG_ID_INVALID 0xFF
267 
268 #if LWIP_SO_SNDBUF
269 #define LWIP_SO_SNDBUF_DECL  u32_t snd_buf_static;
270 #else
271 #define LWIP_SO_SNDBUF_DECL
272 #endif /* LWIP_SO_SNDBUF */
273 
274 #if LWIP_TCP_MAXSEG
275 #define LWIP_TCP_MAXSEG_DECL  u16_t usr_mss;
276 #else
277 #define LWIP_TCP_MAXSEG_DECL
278 #endif /* LWIP_TCP_MAXSEG */
279 
280 #if LWIP_TCP_PCB_NUM_EXT_ARGS
281 /* This is the structure for ext args in tcp pcbs (used as array) */
282 struct tcp_pcb_ext_args {
283   const struct tcp_ext_arg_callbacks *callbacks;
284   void *data;
285 };
286 /* This is a helper define to prevent zero size arrays if disabled */
287 #define TCP_PCB_EXTARGS struct tcp_pcb_ext_args ext_args[LWIP_TCP_PCB_NUM_EXT_ARGS];
288 #else
289 #define TCP_PCB_EXTARGS
290 #endif
291 
292 typedef u32_t tcpflags_t;
293 #define TCP_ALLFLAGS 0xFFFFFFFFU
294 
295 
296 /**
297  * members common to struct tcp_pcb and struct tcp_listen_pcb
298  */
299 #define TCP_PCB_COMMON(type) \
300   type *next; /* for the linked list */ \
301   void *callback_arg; \
302   TCP_PCB_EXTARGS \
303   enum tcp_state state; /* TCP state */ \
304   u8_t prio; \
305   /* ports are in host byte order */ \
306   u16_t local_port; \
307   /* user mss set by TCP_MAXSEG option */ \
308   LWIP_TCP_MAXSEG_DECL \
309   /* Configured send buffer size */ \
310   LWIP_SO_SNDBUF_DECL
311 
312 #if LWIP_TCP_TLP_SUPPORT
313 
314 #define TCP_TLP_MAX_PROBE_CNT 2
315 
316 #define LWIP_TCP_TLP_CLEAR_VARS(_pcb) do { \
317   _pcb->tlp_pto_cnt = 0; \
318   _pcb->tlp_rtx_out = 0; \
319   _pcb->tlp_high_rxt = 0; \
320   _pcb->tlp_time_stamp = 0; \
321 } while (0)
322 
323 #define LWIP_TCP_TLP_WCDELACKT 200 /* RECOMMENDED value is 200ms */
324 #endif /* LWIP_TCP_TLP_SUPPORT */
325 
326 /** the TCP protocol control block for listening pcbs */
327 struct tcp_pcb_listen {
328 /** Common members of all PCB types */
329   IP_PCB;
330 /** Protocol specific PCB members */
331   TCP_PCB_COMMON(struct tcp_pcb_listen);
332 
333 #if LWIP_SO_PRIORITY
334   prio_t priority;
335 #endif /* LWIP_SO_PRIORITY */
336 
337 #if LWIP_CALLBACK_API
338   /* Function to call when a listener has been connected. */
339   tcp_accept_fn accept;
340 #endif /* LWIP_CALLBACK_API */
341 
342 #if TCP_LISTEN_BACKLOG
343   u8_t backlog;
344   u8_t accepts_pending;
345 #endif /* TCP_LISTEN_BACKLOG */
346 };
347 
348 #if DRIVER_STATUS_CHECK
349 #define TF_RST_ON_DRV_WAKE  ((tcpflags_t)0x80000U)   /* From loss receovery it entered to Retrasnmit timeout state */
350 #endif
351 
352 /** the TCP protocol control block */
353 struct tcp_pcb {
354 /** common PCB members */
355   IP_PCB;
356 /** protocol specific PCB members */
357   TCP_PCB_COMMON(struct tcp_pcb);
358 
359 #if LWIP_SO_PRIORITY
360   prio_t priority;
361 #endif /* LWIP_SO_PRIORITY */
362 
363   /* ports are in host byte order */
364   u16_t remote_port;
365 
366   tcpflags_t flags;
367 #define TF_ACK_DELAY   0x01U   /* Delayed ACK. */
368 #define TF_ACK_NOW     0x02U   /* Immediate ACK. */
369 #define TF_INFR        0x04U   /* In fast recovery. */
370 #define TF_CLOSEPEND   0x08U   /* If this is set, tcp_close failed to enqueue the FIN (retried in tcp_tmr) */
371 #define TF_RXCLOSED    0x10U   /* rx closed by tcp_shutdown */
372 #define TF_FIN         0x20U   /* Connection was closed locally (FIN segment enqueued). */
373 #define TF_NODELAY     0x40U   /* Disable Nagle algorithm */
374 #define TF_NAGLEMEMERR 0x80U   /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */
375 #if LWIP_WND_SCALE
376 #define TF_WND_SCALE   0x0100U /* Window Scale option enabled */
377 #endif
378 #if TCP_LISTEN_BACKLOG
379 #define TF_BACKLOGPEND 0x0200U /* If this is set, a connection pcb has increased the backlog on its listener */
380 #endif
381 #if LWIP_TCP_TIMESTAMPS
382 #define TF_TIMESTAMP   0x0400U   /* Timestamp option enabled */
383 #endif
384 
385 /* TCP flags for New Reno */
386 #define TF_INFR_PACK  ((tcpflags_t)0x1000U)   /* Partial ACK recved flag */
387 
388 #define TF_RTO         0x0800U /* RTO timer has fired, in-flight data moved to unsent and being retransmitted */
389 #define TF_INFR_FPACK        ((tcpflags_t)0x4000U)   /* Flag for wait for first parital ack */
390 
391 #if LWIP_SACK
392 /** TCP SACK option enabled. */
393 #define TF_SACK         ((tcpflags_t)0x10000U)
394 /** In SACK based Fast retransmit & loss recovery algorithm */
395 #define TF_IN_SACK_FRLR ((tcpflags_t)0x20000U)
396  /** From loss recovery, it entered to Retrasnmit timeout state. */
397 #define TF_IN_SACK_RTO  ((tcpflags_t)0x40000U)
398 #endif
399 
400 #if DRIVER_STATUS_CHECK
401   /* Netif driver status */
402   u8_t drv_status; /* 0 - Driver not ready. 1- Driver is ready */
403 #endif
404 
405   /* the rest of the fields are in host byte order
406      as we have to do some math with them */
407 
408   /* Timers */
409   u8_t polltmr, pollinterval;
410   u8_t last_timer;
411   u32_t tmr;
412 
413   /* receiver variables */
414   u32_t rcv_nxt;   /* next seqno expected */
415   tcpwnd_size_t rcv_wnd;   /* receiver window available */
416   tcpwnd_size_t rcv_ann_wnd; /* receiver window to announce */
417   u32_t rcv_ann_right_edge; /* announced right edge of window */
418 
419   /* Retransmission timer. */
420   s16_t rtime;
421 
422   u16_t mss;   /* maximum segment size */
423   u16_t rcv_mss; /* mss from peer side */
424 
425   /* RTT (round trip time) estimation variables */
426   u32_t rttest;   /* The start time of RTT sample in ms, the granularity is system tick */
427   u32_t rtseq;    /* sequence number being timed */
428   s16_t sa;   /* smoothed round-trip time, 8 times of SRTT in RFC6298 */
429   s16_t sv;   /* round-trip time variation, 4 times of RTTVAR in RFC6298 */
430 
431   s16_t rto;    /* retransmission time-out (in ticks of TCP_SLOW_INTERVAL) */
432   u8_t nrtx;    /* number of retransmissions */
433 
434   /* fast retransmit/recovery */
435   u8_t dupacks;
436   u32_t lastack; /* Highest acknowledged seqno. */
437 
438   /* congestion avoidance/control variables */
439   tcpwnd_size_t iw;
440   tcpwnd_size_t cwnd;
441   tcpwnd_size_t ssthresh;
442 
443   /* first byte following last rto byte */
444   u32_t rto_end;
445 
446   /* sender variables */
447   u32_t snd_nxt;   /* next new seqno to be sent */
448   u32_t snd_sml;   /* The last byte of the most recently transmitted small packet */
449   u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last
450                              window update. */
451   u32_t snd_lbb;       /* Sequence number of next byte to be buffered. */
452   tcpwnd_size_t snd_wnd;   /* sender window */
453   tcpwnd_size_t snd_wnd_max; /* the maximum sender window announced by the remote host */
454 
455   u32_t snd_buf;   /* Available buffer space for sending (in bytes). */
456 #if LWIP_WND_SCALE
457 #define TCP_SNDQUEUELEN_OVERFLOW (0x03ffffffU - 3)
458 #else /* LWIP_WND_SCALE */
459 #define TCP_SNDQUEUELEN_OVERFLOW (0xffffU - 3)
460 #endif /* LWIP_WND_SCALE */
461   tcpwnd_size_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */
462   tcpwnd_size_t snd_queuelen_max;
463   tcpwnd_size_t snd_queuelen_lowat;
464   u32_t snd_buf_lowat;
465 
466 #if TCP_OVERSIZE
467   /* Extra bytes available at the end of the last pbuf in unsent. */
468   u16_t unsent_oversize;
469 #endif /* TCP_OVERSIZE */
470 
471   tcpwnd_size_t bytes_acked;
472 
473   /* These are ordered by sequence number: */
474   struct tcp_seg *unsent;   /* Unsent (queued) segments. */
475   struct tcp_seg *unacked;  /* Sent but unacknowledged segments. */
476 #if TCP_QUEUE_OOSEQ
477   struct tcp_seg *ooseq;    /* Received out of sequence segments. */
478 #endif /* TCP_QUEUE_OOSEQ */
479 
480   struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer */
481 
482 #if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
483   struct tcp_pcb_listen* listener;
484 #endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */
485 
486 #if LWIP_CALLBACK_API
487   /* Function to be called when more send buffer space is available. */
488   tcp_sent_fn sent;
489   /* Function to be called when (in-sequence) data has arrived. */
490   tcp_recv_fn recv;
491   /* Function to be called when a connection has been set up. */
492   tcp_connected_fn connected;
493   /* Function which is called periodically. */
494   tcp_poll_fn poll;
495   /* Function to be called whenever a fatal error occurs. */
496   tcp_err_fn errf;
497 #endif /* LWIP_CALLBACK_API */
498 
499 #if DRIVER_STATUS_CHECK
500   tcp_event_sndplus_fn  sndplus;
501 #endif
502 
503 #if LWIP_TCP_TIMESTAMPS
504   u32_t ts_lastacksent;
505   u32_t ts_recent;
506 #endif /* LWIP_TCP_TIMESTAMPS */
507 
508   /* idle time before KEEPALIVE is sent */
509   u32_t keep_idle;
510 #if LWIP_TCP_KEEPALIVE
511   u32_t keep_intvl;
512   u32_t keep_cnt;
513 #endif /* LWIP_TCP_KEEPALIVE */
514 
515   /* Persist timer counter */
516   u8_t persist_cnt;
517   /* Persist timer back-off */
518   u8_t persist_backoff;
519   /* Number of persist probes */
520   u8_t persist_probe;
521 
522   /* KEEPALIVE counter */
523   u8_t keep_cnt_sent;
524 
525   u32_t last_payload_len;
526 
527   u32_t fast_recovery_point; /* snd_nxt when enter fast recovery */
528 
529 #if LWIP_SACK
530   struct _sack_seq *sack_seq;
531   /* SACK based pipe algorthim Changes */
532   /* Pipe to hold the number of octets available in network */
533   u32_t pipe;
534   /* Recovery point for stopping loss recovery phase */
535   u32_t recovery_point;
536   /* highest octet covered by any received SACK block */
537   u32_t high_sacked;
538 
539   /* Loss recovery check needs to be started from this seg instead of pcb->unacked */
540   /* This excludes the rexmited and sacked seg from pcb->unacked */
541   /* That means, next_seg_for_lr points to first unsacked and  not retransmitted seg */
542 
543   /* Optimization of SACK based pipe algorthim */
544   struct tcp_seg *next_seg_for_lr;
545 
546   /* highest data trasnfered so far, equivalent to snd_nxt */
547   u32_t high_data;
548   /* highest octet retransmitted so far, as part of SACK based loss recovery algorithm */
549   u32_t high_rxt;
550   /* Rescure rxt as per loss recovery algorithm */
551   u32_t rescue_rxt;
552 
553   u32_t num_sacks;
554   u32_t ooseq_cnt;
555 
556 #if LWIP_SACK_PERF_OPT
557   u32_t pkt_seq_num;  // packet order on which they are transmitted out of stack
558   u32_t high_sacked_pkt_seq;
559   struct tcp_sack_fast_rxmited *fr_segs; /* List of fast retransmitted segments */
560   struct tcp_sack_fast_rxmited *last_frseg; /* The latest fast retransmitted segment. This stores the latest
561                                              * fast retransmitted segment so that when more segments are retransmitted,
562                                              * it can be appended to this segmetn without iterating whole list */
563 #if LWIP_SACK_CWND_OPT
564   tcpwnd_size_t recover_cwnd;
565   tcpwnd_size_t recover_ssthresh;
566 #endif /* LWIP_SACK_CWND_OPT */
567 #endif /* LWIP_SACK_PERF_OPT */
568 
569   u32_t sacked; /* The total SACKed segments count */
570 
571 #if LWIP_FACK_THRESHOLD_BASED_FR
572   u32_t fack;
573 #endif /* LWIP_FACK_THRESHOLD_BASED_FR */
574 
575 #if LWIP_TCP_TLP_SUPPORT
576   u8_t tlp_pto_cnt; /* Consecutive PTOs */
577   u8_t tlp_rtx_out; /* the number of unacknowledged TLP retransmissions in current TLP episode */
578   u32_t tlp_high_rxt; /* SND.NXT at the time it starts doing TLP transmissions during a given TLP episode */
579   u32_t tlp_time_stamp; /* PTO trigger time in ms. 0 is one specially value which means PTO is not scheduled */
580 #endif /* LWIP_TCP_TLP_SUPPORT */
581 #endif /* LWIP_SACK */
582 
583 #if LWIP_WND_SCALE
584   u8_t snd_scale;
585   u8_t rcv_scale;
586 #endif
587 
588   u8_t tcp_pcb_flag;
589 };
590 
591 #if LWIP_EVENT_API
592 
593 enum lwip_event {
594   LWIP_EVENT_ACCEPT,
595   LWIP_EVENT_SENT,
596   LWIP_EVENT_RECV,
597   LWIP_EVENT_CONNECTED,
598   LWIP_EVENT_POLL,
599   LWIP_EVENT_ERR
600 };
601 
602 err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
603          enum lwip_event,
604          struct pbuf *p,
605          u16_t size,
606          err_t err);
607 
608 #endif /* LWIP_EVENT_API */
609 
610 /* Application program's interface: */
611 struct tcp_pcb * tcp_new     (void);
612 struct tcp_pcb * tcp_new_ip_type (u8_t type);
613 
614 void             tcp_arg     (struct tcp_pcb *pcb, void *arg);
615 #if LWIP_CALLBACK_API
616 void             tcp_recv    (struct tcp_pcb *pcb, tcp_recv_fn recv);
617 void             tcp_sent    (struct tcp_pcb *pcb, tcp_sent_fn sent);
618 void             tcp_err     (struct tcp_pcb *pcb, tcp_err_fn err);
619 void             tcp_accept  (struct tcp_pcb *pcb, tcp_accept_fn accept);
620 #endif /* LWIP_CALLBACK_API */
621 void             tcp_poll    (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval);
622 
623 #if LWIP_LOWPOWER
624 u32_t tcp_fast_tmr_tick(void);
625 u32_t tcp_slow_tmr_tick(void);
626 #endif
627 
628 #define          tcp_set_flags(pcb, set_flags)     do { (pcb)->flags = (tcpflags_t)((pcb)->flags |  (set_flags)); } while(0)
629 #define          tcp_clear_flags(pcb, clr_flags)   do { (pcb)->flags = (tcpflags_t)((pcb)->flags & (tcpflags_t)(~(clr_flags) & TCP_ALLFLAGS)); } while(0)
630 #define          tcp_is_flag_set(pcb, flag)        (((pcb)->flags & (flag)) != 0)
631 
632 #if LWIP_TCP_TIMESTAMPS
633 #define          tcp_mss(pcb)             (((pcb)->flags & TF_TIMESTAMP) ? ((pcb)->mss - 12)  : (pcb)->mss)
634 #else /* LWIP_TCP_TIMESTAMPS */
635 /** @ingroup tcp_raw */
636 #define          tcp_mss(pcb)             ((pcb)->mss)
637 #endif /* LWIP_TCP_TIMESTAMPS */
638 /** @ingroup tcp_raw */
639 #define          tcp_sndbuf(pcb)          ((pcb)->snd_buf)
640 /** @ingroup tcp_raw */
641 #define          tcp_sndqueuelen(pcb)     ((pcb)->snd_queuelen)
642 /** @ingroup tcp_raw */
643 #define          tcp_nagle_disable(pcb)   tcp_set_flags(pcb, TF_NODELAY)
644 /** @ingroup tcp_raw */
645 #define          tcp_nagle_enable(pcb)    tcp_clear_flags(pcb, TF_NODELAY)
646 /** @ingroup tcp_raw */
647 #define          tcp_nagle_disabled(pcb)  tcp_is_flag_set(pcb, TF_NODELAY)
648 #if LWIP_SO_SNDBUF
649 #define          tcp_set_sendbufsize(pcb, size)    ((pcb)->snd_buf_static = (size))
650 #define          tcp_get_sendbufsize(pcb)    ((pcb)->snd_buf_static)
651 #endif /* LWIP_SO_SNDBUF */
652 
653 #if TCP_LISTEN_BACKLOG
654 #define          tcp_backlog_set(pcb, new_backlog) do { \
655   LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", (pcb)->state == LISTEN); \
656   ((struct tcp_pcb_listen *)(pcb))->backlog = ((new_backlog) ? (new_backlog) : 1); } while(0)
657 void             tcp_backlog_delayed(struct tcp_pcb* pcb);
658 void             tcp_backlog_accepted(struct tcp_pcb* pcb);
659 #else  /* TCP_LISTEN_BACKLOG */
660 #define          tcp_backlog_set(pcb, new_backlog)
661 #define          tcp_backlog_delayed(pcb)
662 #define          tcp_backlog_accepted(pcb)
663 #endif /* TCP_LISTEN_BACKLOG */
664 #define          tcp_accepted(pcb) do { LWIP_UNUSED_ARG(pcb); } while(0) /* compatibility define, not needed any more */
665 
666 void             tcp_recved  (struct tcp_pcb *pcb, u16_t len);
667 err_t            tcp_bind    (struct tcp_pcb *pcb, const ip_addr_t *ipaddr,
668                               u16_t port);
669 void             tcp_bind_netif(struct tcp_pcb *pcb, const struct netif *netif);
670 err_t            tcp_connect (struct tcp_pcb *pcb, const ip_addr_t *ipaddr,
671                               u16_t port, tcp_connected_fn connected);
672 
673 struct tcp_pcb * tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err);
674 struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog);
675 /** @ingroup tcp_raw */
676 #define          tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG)
677 
678 void             tcp_abort (struct tcp_pcb *pcb);
679 err_t            tcp_close   (struct tcp_pcb *pcb);
680 err_t            tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx);
681 
682 err_t            tcp_write   (struct tcp_pcb *pcb, const void *dataptr, u16_t len,
683                               u8_t apiflags);
684 
685 void             tcp_setprio (struct tcp_pcb *pcb, u8_t prio);
686 
687 #if LWIP_TCP_TLP_SUPPORT
688 /*
689  * This is the TLP probe timeout function as in draft-dukkipati-tcpm-tcp-loss-probe-01
690  *
691  * When PTO fires:
692  *   (a) If a new previously unsent segment exists:
693  *         -> Transmit new segment.
694  *         -> FlightSize += SMSS. cwnd remains unchanged.
695  *   (b) If no new segment exists:
696  *         -> Retransmit the last segment.
697  *   (c) Increment statistics counter for loss probes.
698  *   (d) If conditions in (2) are satisfied:
699  *         -> Reschedule next PTO.
700  *       Else:
701  *         -> Rearm RTO to fire at epoch 'now+RTO'.
702  *
703  * @param pcb Protocol control block for the TCP connection to send data
704  * @return None
705  *
706  */
707 void tcp_pto_fire(struct tcp_pcb *pcb);
708 #endif
709 
710 err_t            tcp_output  (struct tcp_pcb *pcb);
711 
712 err_t            tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif);
713 
714 err_t            tcp_tcp_get_tcp_addrinfo(struct tcp_pcb *pcb, int local, ip_addr_t *addr, u16_t *port);
715 
716 #define tcp_dbg_get_tcp_state(pcb) ((pcb)->state)
717 
718 #if DRIVER_STATUS_CHECK
719 unsigned char tcp_is_netif_addr_check_success(const struct tcp_pcb *pcb, const struct netif *netif);
720 void tcp_flush_pcb_on_wake_queue(struct tcp_pcb *pcb, u8_t status);
721 void tcpip_flush_on_wake_queue(const struct netif *netif, u8_t status);
722 void tcp_ip_flush_pcblist_on_wake_queue(const struct netif *netif, struct tcp_pcb *pcb_list, u8_t status);
723 void tcpip_upd_status_to_tcp_pcbs(const struct netif *netif, u8_t status);
724 void tcp_ip_event_sendplus_on_wake_queue(const struct netif *netif);
725 void tcp_update_drv_status_to_pcbs(struct tcp_pcb *pcb_list, const struct netif *netif, u8_t status);
726 #endif
727 
728 /* for compatibility with older implementation */
729 #define tcp_new_ip6() tcp_new_ip_type(IPADDR_TYPE_V6)
730 
731 void tcp_sndbuf_init(struct tcp_pcb *pcb);
732 
733 #if LWIP_TCP_PCB_NUM_EXT_ARGS
734 u8_t tcp_ext_arg_alloc_id(void);
735 void tcp_ext_arg_set_callbacks(struct tcp_pcb *pcb, uint8_t id, const struct tcp_ext_arg_callbacks * const callbacks);
736 void tcp_ext_arg_set(struct tcp_pcb *pcb, uint8_t id, void *arg);
737 void *tcp_ext_arg_get(const struct tcp_pcb *pcb, uint8_t id);
738 #endif
739 
740 #if LWIP_TCP_TLP_SUPPORT
741 void tcp_tlp_schedule_probe(struct tcp_pcb *pcb, u32_t wnd);
742 #endif /* LWIP_TCP_TLP_SUPPORT */
743 
744 extern const char * const tcp_state_str[];
745 
746 #ifdef __cplusplus
747 }
748 #endif
749 
750 #endif /* LWIP_TCP */
751 
752 #endif /* LWIP_HDR_TCP_H */
753