ReactOS 0.4.16-dev-297-gc569aee
test_tcp.c File Reference
#include "test_tcp.h"
#include "lwip/priv/tcp_priv.h"
#include "lwip/stats.h"
#include "lwip/inet.h"
#include "tcp_helper.h"
#include "lwip/inet_chksum.h"
Include dependency graph for test_tcp.c:

Go to the source code of this file.

Macros

#define SEQNO1   (0xFFFFFF00 - TCP_MSS)
 
#define ISS   6510
 

Functions

static void test_tcp_tmr (void)
 
static void tcp_setup (void)
 
static void tcp_teardown (void)
 
 START_TEST (test_tcp_new_abort)
 
END_TEST START_TEST (test_tcp_listen_passive_open)
 
END_TEST START_TEST (test_tcp_recv_inseq)
 
END_TEST START_TEST (test_tcp_recv_inseq_trim)
 
static END_TEST err_t test_tcp_recv_expect1byte (void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
 
static err_t test_tcp_recv_expectclose (void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
 
 START_TEST (test_tcp_passive_close)
 
END_TEST START_TEST (test_tcp_active_abort)
 
END_TEST START_TEST (test_tcp_malformed_header)
 
END_TEST START_TEST (test_tcp_fast_retx_recover)
 
static void check_seqnos (struct tcp_seg *segs, int num_expected, u32_t *seqnos_expected)
 
 START_TEST (test_tcp_fast_rexmit_wraparound)
 
END_TEST START_TEST (test_tcp_rto_rexmit_wraparound)
 
static END_TEST void test_tcp_tx_full_window_lost (u8_t zero_window_probe_from_unsent)
 
 START_TEST (test_tcp_tx_full_window_lost_from_unsent)
 
END_TEST START_TEST (test_tcp_tx_full_window_lost_from_unacked)
 
END_TEST START_TEST (test_tcp_retx_add_to_sent)
 
END_TEST START_TEST (test_tcp_rto_tracking)
 
static END_TEST void test_tcp_rto_timeout_impl (int link_down)
 
 START_TEST (test_tcp_rto_timeout)
 
END_TEST START_TEST (test_tcp_rto_timeout_link_down)
 
static END_TEST void test_tcp_rto_timeout_syn_sent_impl (int link_down)
 
 START_TEST (test_tcp_rto_timeout_syn_sent)
 
END_TEST START_TEST (test_tcp_rto_timeout_syn_sent_link_down)
 
static END_TEST void test_tcp_zwp_timeout_impl (int link_down)
 
 START_TEST (test_tcp_zwp_timeout)
 
END_TEST START_TEST (test_tcp_zwp_timeout_link_down)
 
END_TEST START_TEST (test_tcp_persist_split)
 
END_TEST Suite * tcp_suite (void)
 

Variables

static u32_t seqnos []
 
static u8_t test_tcp_timer
 
static struct netifold_netif_list
 
static struct netifold_netif_default
 
static END_TEST u8_t tx_data [TCP_WND *2]
 

Macro Definition Documentation

◆ ISS

#define ISS   6510

Definition at line 22 of file test_tcp.c.

◆ SEQNO1

#define SEQNO1   (0xFFFFFF00 - TCP_MSS)

Definition at line 21 of file test_tcp.c.

Function Documentation

◆ check_seqnos()

static void check_seqnos ( struct tcp_seg *  segs,
int  num_expected,
u32_t seqnos_expected 
)
static

Definition at line 614 of file test_tcp.c.

615{
616 struct tcp_seg *s = segs;
617 int i;
618 for (i = 0; i < num_expected; i++, s = s->next) {
619 EXPECT_RET(s != NULL);
620 EXPECT(s->tcphdr->seqno == htonl(seqnos_expected[i]));
621 }
622 EXPECT(s == NULL);
623}
#define NULL
Definition: types.h:112
GLdouble s
Definition: gl.h:2039
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define EXPECT(x)
Definition: lwip_check.h:11
#define EXPECT_RET(x)
Definition: lwip_check.h:12
#define htonl(x)
Definition: module.h:214

Referenced by START_TEST(), and test_tcp_zwp_timeout_impl().

◆ START_TEST() [1/21]

END_TEST START_TEST ( test_tcp_active_abort  )

Definition at line 334 of file test_tcp.c.

335{
337 struct tcp_pcb* pcb;
338 char data = 0x0f;
339 struct netif netif;
340 struct test_tcp_txcounters txcounters;
341 LWIP_UNUSED_ARG(_i);
342
343 memset(&txcounters, 0, sizeof(txcounters));
344
345 /* initialize local vars */
347
348 /* initialize counter struct */
349 memset(&counters, 0, sizeof(counters));
350 counters.expected_data_len = 1;
351 counters.expected_data = &data;
352
353 /* create and initialize the pcb */
355 EXPECT_RET(pcb != NULL);
357
358 /* abort the pcb */
359 EXPECT_RET(txcounters.num_tx_calls == 0);
360 txcounters.copy_tx_packets = 1;
361 tcp_abort(pcb);
362 txcounters.copy_tx_packets = 0;
363 EXPECT(txcounters.num_tx_calls == 1);
364 EXPECT(txcounters.num_tx_bytes == 40U);
365 EXPECT(txcounters.tx_packets != NULL);
366 if (txcounters.tx_packets != NULL) {
367 u16_t ret;
368 struct tcp_hdr tcphdr;
369 ret = pbuf_copy_partial(txcounters.tx_packets, &tcphdr, 20, 20);
370 EXPECT(ret == 20);
373 pbuf_free(txcounters.tx_packets);
374 txcounters.tx_packets = NULL;
375 }
376
377 /* don't free the pcb here (part of the test!) */
378}
#define PP_HTONS(x)
Definition: def.h:90
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLuint * counters
Definition: glext.h:11114
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:373
uint16_t u16_t
Definition: arch.h:127
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:727
u16_t pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:1058
#define memset(x, y, z)
Definition: compat.h:39
Definition: netif.h:269
Definition: tcp.h:56
Definition: tcpdef.h:22
__u16 dest
Definition: tcpdef.h:24
void test_tcp_init_netif(struct netif *netif, struct test_tcp_txcounters *txcounters, const ip_addr_t *ip_addr, const ip_addr_t *netmask)
Definition: tcp_helper.c:305
struct tcp_pcb * test_tcp_new_counters_pcb(struct test_tcp_counters *counters)
Definition: tcp_helper.c:244
const ip_addr_t test_local_ip
Definition: tcp_helper.c:14
const ip_addr_t test_remote_ip
Definition: tcp_helper.c:15
#define TEST_REMOTE_PORT
Definition: tcp_helper.h:32
#define TEST_LOCAL_PORT
Definition: tcp_helper.h:33
static __inline void tcp_set_state(struct sock *sk, int state)
Definition: tcpcore.h:3256
static ip4_addr_t test_netmask
Definition: test_etharp.c:18
int ret

◆ START_TEST() [2/21]

END_TEST START_TEST ( test_tcp_fast_retx_recover  )

Provoke fast retransmission by duplicate ACKs and then recover by ACKing all sent data. At the end, send more data.

Definition at line 446 of file test_tcp.c.

447{
448 struct netif netif;
449 struct test_tcp_txcounters txcounters;
451 struct tcp_pcb* pcb;
452 struct pbuf* p;
453 char data1[] = { 1, 2, 3, 4};
454 char data2[] = { 5, 6, 7, 8};
455 char data3[] = { 9, 10, 11, 12};
456 char data4[] = {13, 14, 15, 16};
457 char data5[] = {17, 18, 19, 20};
458 char data6[TCP_MSS] = {21, 22, 23, 24};
459 err_t err;
460 LWIP_UNUSED_ARG(_i);
461
462 /* initialize local vars */
464 memset(&counters, 0, sizeof(counters));
465
466 /* create and initialize the pcb */
468 EXPECT_RET(pcb != NULL);
470 pcb->mss = TCP_MSS;
471 /* disable initial congestion window (we don't send a SYN here...) */
472 pcb->cwnd = pcb->snd_wnd;
473
474 /* send data1 */
475 err = tcp_write(pcb, data1, sizeof(data1), TCP_WRITE_FLAG_COPY);
477 err = tcp_output(pcb);
479 EXPECT_RET(txcounters.num_tx_calls == 1);
480 EXPECT_RET(txcounters.num_tx_bytes == sizeof(data1) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
481 memset(&txcounters, 0, sizeof(txcounters));
482 /* "recv" ACK for data1 */
483 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 4, TCP_ACK);
484 EXPECT_RET(p != NULL);
486 EXPECT_RET(txcounters.num_tx_calls == 0);
487 EXPECT_RET(pcb->unacked == NULL);
488 /* send data2 */
489 err = tcp_write(pcb, data2, sizeof(data2), TCP_WRITE_FLAG_COPY);
491 err = tcp_output(pcb);
493 EXPECT_RET(txcounters.num_tx_calls == 1);
494 EXPECT_RET(txcounters.num_tx_bytes == sizeof(data2) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
495 memset(&txcounters, 0, sizeof(txcounters));
496 /* duplicate ACK for data1 (data2 is lost) */
497 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
498 EXPECT_RET(p != NULL);
500 EXPECT_RET(txcounters.num_tx_calls == 0);
501 EXPECT_RET(pcb->dupacks == 1);
502 /* send data3 */
503 err = tcp_write(pcb, data3, sizeof(data3), TCP_WRITE_FLAG_COPY);
505 err = tcp_output(pcb);
507 /* nagle enabled, no tx calls */
508 EXPECT_RET(txcounters.num_tx_calls == 0);
509 EXPECT_RET(txcounters.num_tx_bytes == 0);
510 memset(&txcounters, 0, sizeof(txcounters));
511 /* 2nd duplicate ACK for data1 (data2 and data3 are lost) */
512 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
513 EXPECT_RET(p != NULL);
515 EXPECT_RET(txcounters.num_tx_calls == 0);
516 EXPECT_RET(pcb->dupacks == 2);
517 /* queue data4, don't send it (unsent-oversize is != 0) */
518 err = tcp_write(pcb, data4, sizeof(data4), TCP_WRITE_FLAG_COPY);
520 /* 3nd duplicate ACK for data1 (data2 and data3 are lost) -> fast retransmission */
521 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
522 EXPECT_RET(p != NULL);
524 /*EXPECT_RET(txcounters.num_tx_calls == 1);*/
525 EXPECT_RET(pcb->dupacks == 3);
526 memset(&txcounters, 0, sizeof(txcounters));
527 /* @todo: check expected data?*/
528
529 /* send data5, not output yet */
530 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
532 /*err = tcp_output(pcb);
533 EXPECT_RET(err == ERR_OK);*/
534 EXPECT_RET(txcounters.num_tx_calls == 0);
535 EXPECT_RET(txcounters.num_tx_bytes == 0);
536 memset(&txcounters, 0, sizeof(txcounters));
537 {
538 int i = 0;
539 do
540 {
541 err = tcp_write(pcb, data6, TCP_MSS, TCP_WRITE_FLAG_COPY);
542 i++;
543 }while(err == ERR_OK);
545 }
546 err = tcp_output(pcb);
548 /*EXPECT_RET(txcounters.num_tx_calls == 0);
549 EXPECT_RET(txcounters.num_tx_bytes == 0);*/
550 memset(&txcounters, 0, sizeof(txcounters));
551
552 /* send even more data */
553 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
555 err = tcp_output(pcb);
557 /* ...and even more data */
558 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
560 err = tcp_output(pcb);
562 /* ...and even more data */
563 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
565 err = tcp_output(pcb);
567 /* ...and even more data */
568 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
570 err = tcp_output(pcb);
572
573 /* send ACKs for data2 and data3 */
574 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 12, TCP_ACK);
575 EXPECT_RET(p != NULL);
577 /*EXPECT_RET(txcounters.num_tx_calls == 0);*/
578
579 /* ...and even more data */
580 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
582 err = tcp_output(pcb);
584 /* ...and even more data */
585 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
587 err = tcp_output(pcb);
589
590#if 0
591 /* create expected segment */
592 p1 = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0);
593 EXPECT_RET(p != NULL);
594 if (p != NULL) {
595 /* pass the segment to tcp_input */
597 /* check if counters are as expected */
598 EXPECT_RET(counters.close_calls == 0);
599 EXPECT_RET(counters.recv_calls == 1);
600 EXPECT_RET(counters.recved_bytes == data_len);
601 EXPECT_RET(counters.err_calls == 0);
602 }
603#endif
604 /* make sure the pcb is freed */
605 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
606 tcp_abort(pcb);
607 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
608}
static int used
Definition: adh-main.c:39
static const char data4[]
Definition: db.c:2864
static const WCHAR data3[]
Definition: db.c:2860
static const WCHAR data5[]
Definition: db.c:2866
static const WCHAR data6[]
Definition: db.c:2884
GLfloat GLfloat p
Definition: glext.h:8902
s8_t err_t
Definition: err.h:96
@ ERR_OK
Definition: err.h:55
#define TCP_MSS
Definition: lwipopts.h:46
#define TCP_ACK
Definition: tcp.h:76
#define err(...)
#define MEMP_STATS_GET(x, i)
Definition: stats.h:409
Definition: tftpd.h:126
Definition: tftpd.h:138
Definition: ip4.h:73
Definition: pbuf.h:186
void test_tcp_input(struct pbuf *p, struct netif *inp)
Definition: tcp_helper.c:259
struct pbuf * tcp_create_rx_segment(struct tcp_pcb *pcb, void *data, size_t data_len, u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags)
Definition: tcp_helper.c:130

◆ START_TEST() [3/21]

START_TEST ( test_tcp_fast_rexmit_wraparound  )

Send data with sequence numbers that wrap around the u32_t range. Then, provoke fast retransmission by duplicate ACKs and check that all segment lists are still properly sorted.

Definition at line 628 of file test_tcp.c.

629{
630 struct netif netif;
631 struct test_tcp_txcounters txcounters;
633 struct tcp_pcb* pcb;
634 struct pbuf* p;
635 err_t err;
636 size_t i;
637 u16_t sent_total = 0;
638 LWIP_UNUSED_ARG(_i);
639
640 for (i = 0; i < sizeof(tx_data); i++) {
641 tx_data[i] = (u8_t)i;
642 }
643
644 /* initialize local vars */
646 memset(&counters, 0, sizeof(counters));
647
648 /* create and initialize the pcb */
649 tcp_ticks = SEQNO1 - ISS;
651 EXPECT_RET(pcb != NULL);
653 pcb->mss = TCP_MSS;
654 /* disable initial congestion window (we don't send a SYN here...) */
655 pcb->cwnd = 2*TCP_MSS;
656 /* start in congestion advoidance */
657 pcb->ssthresh = pcb->cwnd;
658
659 /* send 6 mss-sized segments */
660 for (i = 0; i < 6; i++) {
661 err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
663 sent_total += TCP_MSS;
664 }
665 check_seqnos(pcb->unsent, 6, seqnos);
666 EXPECT(pcb->unacked == NULL);
667 err = tcp_output(pcb);
669 EXPECT(txcounters.num_tx_calls == 2);
670 EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U));
671 memset(&txcounters, 0, sizeof(txcounters));
672
673 check_seqnos(pcb->unacked, 2, seqnos);
674 check_seqnos(pcb->unsent, 4, &seqnos[2]);
675
676 /* ACK the first segment */
679 /* ensure this didn't trigger a retransmission. Only one
680 segment should be transmitted because cwnd opened up by
681 TCP_MSS and a fraction since we are in congestion avoidance */
682 EXPECT(txcounters.num_tx_calls == 1);
683 EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U);
684 memset(&txcounters, 0, sizeof(txcounters));
685 check_seqnos(pcb->unacked, 2, &seqnos[1]);
686 check_seqnos(pcb->unsent, 3, &seqnos[3]);
687
688 /* 3 dupacks */
689 EXPECT(pcb->dupacks == 0);
690 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
692 EXPECT(txcounters.num_tx_calls == 0);
693 EXPECT(pcb->dupacks == 1);
694 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
696 EXPECT(txcounters.num_tx_calls == 0);
697 EXPECT(pcb->dupacks == 2);
698 /* 3rd dupack -> fast rexmit */
699 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
701 EXPECT(pcb->dupacks == 3);
702 EXPECT(txcounters.num_tx_calls == 4);
703 memset(&txcounters, 0, sizeof(txcounters));
704 EXPECT(pcb->unsent == NULL);
705 check_seqnos(pcb->unacked, 5, &seqnos[1]);
706
707 /* make sure the pcb is freed */
708 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
709 tcp_abort(pcb);
710 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
711}
uint8_t u8_t
Definition: arch.h:125
static END_TEST u8_t tx_data[TCP_WND *2]
Definition: test_tcp.c:611
static void check_seqnos(struct tcp_seg *segs, int num_expected, u32_t *seqnos_expected)
Definition: test_tcp.c:614
#define SEQNO1
Definition: test_tcp.c:21
static u32_t seqnos[]
Definition: test_tcp.c:23
#define ISS
Definition: test_tcp.c:22

◆ START_TEST() [4/21]

END_TEST START_TEST ( test_tcp_listen_passive_open  )

Call tcp_new() and tcp_abort() and test memp stats

Definition at line 101 of file test_tcp.c.

102{
103 struct tcp_pcb *pcb, *pcbl;
104 struct tcp_pcb_listen *lpcb;
105 struct netif netif;
106 struct test_tcp_txcounters txcounters;
108 struct pbuf *p;
109 ip_addr_t src_addr;
110 err_t err;
111 LWIP_UNUSED_ARG(_i);
112
113 fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
114
116 /* initialize counter struct */
117 memset(&counters, 0, sizeof(counters));
118
119 pcb = tcp_new();
120 EXPECT_RET(pcb != NULL);
121 err = tcp_bind(pcb, &netif.ip_addr, 1234);
122 EXPECT(err == ERR_OK);
123 pcbl = tcp_listen(pcb);
124 EXPECT_RET(pcbl != NULL);
125 EXPECT_RET(pcbl != pcb);
126 lpcb = (struct tcp_pcb_listen *)pcbl;
127
128 ip_addr_set_ip4_u32_val(src_addr, lwip_htonl(lwip_ntohl(ip_addr_get_ip4_u32(&lpcb->local_ip)) + 1));
129
130 /* check correct syn packet */
131 p = tcp_create_segment(&src_addr, &lpcb->local_ip, 12345,
132 lpcb->local_port, NULL, 0, 12345, 54321, TCP_SYN);
133 EXPECT(p != NULL);
134 if (p != NULL) {
135 /* pass the segment to tcp_input */
137 /* check if counters are as expected */
138 EXPECT(txcounters.num_tx_calls == 1);
139 }
140
141 /* check syn packet with short length */
142 p = tcp_create_segment(&src_addr, &lpcb->local_ip, 12345,
143 lpcb->local_port, NULL, 0, 12345, 54321, TCP_SYN);
144 EXPECT(p != NULL);
145 EXPECT(p->next == NULL);
146 if ((p != NULL) && (p->next == NULL)) {
147 p->len -= 2;
148 p->tot_len -= 2;
149 /* pass the segment to tcp_input */
151 /* check if counters are as expected */
152 EXPECT(txcounters.num_tx_calls == 1);
153 }
154
155 tcp_close(pcbl);
156}
#define lwip_ntohl(x)
Definition: def.h:89
#define lwip_htonl(x)
Definition: def.h:88
ip6_addr_t ip_addr_t
Definition: ip_addr.h:344
#define TCP_SYN
Definition: tcp.h:73
struct pbuf * tcp_create_segment(ip_addr_t *src_ip, ip_addr_t *dst_ip, u16_t src_port, u16_t dst_port, void *data, size_t data_len, u32_t seqno, u32_t ackno, u8_t headerflags)
Definition: tcp_helper.c:117
void tcp_close(struct sock *sk, long timeout)

◆ START_TEST() [5/21]

END_TEST START_TEST ( test_tcp_malformed_header  )

Check that we handle malformed tcp headers, and discard the pbuf(s)

Definition at line 382 of file test_tcp.c.

383{
385 struct tcp_pcb* pcb;
386 struct pbuf* p;
387 char data[] = {1, 2, 3, 4};
388 u16_t data_len, chksum;
389 struct netif netif;
390 struct test_tcp_txcounters txcounters;
391 struct tcp_hdr *hdr;
392 LWIP_UNUSED_ARG(_i);
393
394 /* initialize local vars */
396 data_len = sizeof(data);
397 /* initialize counter struct */
398 memset(&counters, 0, sizeof(counters));
399 counters.expected_data_len = data_len;
400 counters.expected_data = data;
401
402 /* create and initialize the pcb */
404 EXPECT_RET(pcb != NULL);
406
407 /* create a segment */
408 p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0);
409
410 pbuf_header(p, -(s16_t)sizeof(struct ip_hdr));
411
412 hdr = (struct tcp_hdr *)p->payload;
413 TCPH_HDRLEN_FLAGS_SET(hdr, 15, 0x3d1);
414
415 hdr->chksum = 0;
416
417 chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
419
420 hdr->chksum = chksum;
421
422 pbuf_header(p, sizeof(struct ip_hdr));
423
424 EXPECT(p != NULL);
425 EXPECT(p->next == NULL);
426 if (p != NULL) {
427 /* pass the segment to tcp_input */
429 /* check if counters are as expected */
430 EXPECT(counters.close_calls == 0);
431 EXPECT(counters.recv_calls == 0);
432 EXPECT(counters.recved_bytes == 0);
433 EXPECT(counters.err_calls == 0);
434 }
435
436 /* make sure the pcb is freed */
437 EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
438 tcp_abort(pcb);
439 EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
440}
#define IP_PROTO_TCP
Definition: ip.h:50
int16_t s16_t
Definition: arch.h:128
u16_t ip_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, const ip_addr_t *src, const ip_addr_t *dest)
Definition: inet_chksum.c:379
char hdr[14]
Definition: iptest.cpp:33
#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags)
Definition: tcp.h:91
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
Definition: pbuf.c:649

◆ START_TEST() [6/21]

START_TEST ( test_tcp_new_abort  )

Call tcp_new() and tcp_abort() and test memp stats

Definition at line 83 of file test_tcp.c.

84{
85 struct tcp_pcb* pcb;
87
88 fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
89
90 pcb = tcp_new();
91 fail_unless(pcb != NULL);
92 if (pcb != NULL) {
93 fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
94 tcp_abort(pcb);
95 fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
96 }
97}

◆ START_TEST() [7/21]

START_TEST ( test_tcp_passive_close  )

Definition at line 299 of file test_tcp.c.

300{
302 struct tcp_pcb* pcb;
303 struct pbuf* p;
304 char data = 0x0f;
305 struct netif netif;
306 struct test_tcp_txcounters txcounters;
307 LWIP_UNUSED_ARG(_i);
308
309 /* initialize local vars */
311
312 /* initialize counter struct */
313 memset(&counters, 0, sizeof(counters));
314 counters.expected_data_len = 1;
315 counters.expected_data = &data;
316
317 /* create and initialize the pcb */
319 EXPECT_RET(pcb != NULL);
321
322 /* create a segment without data */
323 p = tcp_create_rx_segment(pcb, &data, 1, 0, 0, TCP_FIN);
324 EXPECT(p != NULL);
325 if (p != NULL) {
327 /* pass the segment to tcp_input */
329 }
330 /* don't free the pcb here (part of the test!) */
331}
STREAM tcp_recv(STREAM s, uint32 length)
Definition: tcp.c:344
#define TCP_FIN
Definition: tcp.h:72
static END_TEST err_t test_tcp_recv_expect1byte(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
Definition: test_tcp.c:280

◆ START_TEST() [8/21]

END_TEST START_TEST ( test_tcp_persist_split  )

Definition at line 1514 of file test_tcp.c.

1515{
1516 struct netif netif;
1517 struct test_tcp_txcounters txcounters;
1519 struct tcp_pcb *pcb;
1520 struct pbuf* p;
1521 err_t err;
1522 size_t i;
1523 LWIP_UNUSED_ARG(_i);
1524
1525 /* Setup data for four segments */
1526 for (i = 0; i < 4 * TCP_MSS; i++) {
1527 tx_data[i] = (u8_t)i;
1528 }
1529
1530 /* initialize local vars */
1532 memset(&counters, 0, sizeof(counters));
1533
1534 /* create and initialize the pcb */
1535 tcp_ticks = SEQNO1 - ISS;
1537 EXPECT_RET(pcb != NULL);
1539 pcb->mss = TCP_MSS;
1540 /* set window to three segments */
1541 pcb->cwnd = 3 * TCP_MSS;
1542 pcb->snd_wnd = 3 * TCP_MSS;
1543 pcb->snd_wnd_max = 3 * TCP_MSS;
1544
1545 /* send four segments. Fourth should stay buffered and is a 3/4 MSS segment to
1546 get coverage on the oversized segment case */
1547 err = tcp_write(pcb, &tx_data[0], (3 * TCP_MSS) + (TCP_MSS - (TCP_MSS / 4)), TCP_WRITE_FLAG_COPY);
1548 EXPECT(err == ERR_OK);
1549 err = tcp_output(pcb);
1550 EXPECT(err == ERR_OK);
1551
1552 /* verify 3 segments are in-flight */
1553 EXPECT(pcb->unacked != NULL);
1554 check_seqnos(pcb->unacked, 3, seqnos);
1555 EXPECT(txcounters.num_tx_calls == 3);
1556 EXPECT(txcounters.num_tx_bytes == 3 * (TCP_MSS + 40U));
1557 memset(&txcounters, 0, sizeof(txcounters));
1558 /* verify 4th segment is on unsent */
1559 EXPECT(pcb->unsent != NULL);
1560 EXPECT(pcb->unsent->len == TCP_MSS - (TCP_MSS / 4));
1561 check_seqnos(pcb->unsent, 1, &seqnos[3]);
1562#if TCP_OVERSIZE
1563 EXPECT(pcb->unsent_oversize == TCP_MSS / 4);
1564#if TCP_OVERSIZE_DBGCHECK
1565 EXPECT(pcb->unsent->oversize_left == pcb->unsent_oversize);
1566#endif /* TCP_OVERSIZE_DBGCHECK */
1567#endif /* TCP_OVERSIZE */
1568
1569 /* ACK the 3 segments and update the window to only 1/2 TCP_MSS.
1570 4th segment should stay on unsent because it's bigger than 1/2 MSS */
1571 p = tcp_create_rx_segment_wnd(pcb, NULL, 0, 0, 3 * TCP_MSS, TCP_ACK, TCP_MSS / 2);
1573 EXPECT(pcb->unacked == NULL);
1574 EXPECT(pcb->snd_wnd == TCP_MSS / 2);
1575 EXPECT(pcb->unsent != NULL);
1576 check_seqnos(pcb->unsent, 1, &seqnos[3]);
1577 EXPECT(txcounters.num_tx_calls == 0);
1578 EXPECT(txcounters.num_tx_bytes == 0);
1579 /* persist timer should be started since 4th segment is stuck waiting on snd_wnd */
1580 EXPECT(pcb->persist_backoff == 1);
1581
1582 /* ensure no errors have been recorded */
1583 EXPECT(counters.err_calls == 0);
1584 EXPECT(counters.last_err == ERR_OK);
1585
1586 /* call tcp_timer some more times to let persist timer count up */
1587 for (i = 0; i < 4; i++) {
1588 test_tcp_tmr();
1589 EXPECT(txcounters.num_tx_calls == 0);
1590 EXPECT(txcounters.num_tx_bytes == 0);
1591 }
1592
1593 /* this should be the first timer shot, which should split the
1594 * segment and send a runt (of the remaining window size) */
1595 txcounters.copy_tx_packets = 1;
1596 test_tcp_tmr();
1597 txcounters.copy_tx_packets = 0;
1598 /* persist will be disabled as RTO timer takes over */
1599 EXPECT(pcb->persist_backoff == 0);
1600 EXPECT(txcounters.num_tx_calls == 1);
1601 EXPECT(txcounters.num_tx_bytes == ((TCP_MSS /2) + 40U));
1602 /* verify 1/2 MSS segment sent, 1/4 MSS still buffered */
1603 EXPECT(pcb->unsent != NULL);
1604 EXPECT(pcb->unsent->len == TCP_MSS / 4);
1605 EXPECT(pcb->unacked != NULL);
1606 EXPECT(pcb->unacked->len == TCP_MSS / 2);
1607#if TCP_OVERSIZE
1608 /* verify there is no oversized remaining since during the
1609 segment split, the remainder pbuf is always the exact length */
1610 EXPECT(pcb->unsent_oversize == 0);
1611#if TCP_OVERSIZE_DBGCHECK
1612 /* Split segment already transmitted, should be at 0 */
1613 EXPECT(pcb->unacked->oversize_left == 0);
1614 /* Remainder segment should match pcb value (which is 0) */
1615 EXPECT(pcb->unsent->oversize_left == pcb->unsent_oversize);
1616#endif /* TCP_OVERSIZE_DBGCHECK */
1617#endif /* TCP_OVERSIZE */
1618
1619 /* verify first half segment */
1620 EXPECT(txcounters.tx_packets != NULL);
1621 if (txcounters.tx_packets != NULL) {
1622 u8_t sent[TCP_MSS / 2];
1623 u16_t ret;
1624 ret = pbuf_copy_partial(txcounters.tx_packets, &sent, TCP_MSS / 2, 40U);
1625 EXPECT(ret == TCP_MSS / 2);
1626 EXPECT(memcmp(sent, &tx_data[3 * TCP_MSS], TCP_MSS / 2) == 0);
1627 }
1628 if (txcounters.tx_packets != NULL) {
1629 pbuf_free(txcounters.tx_packets);
1630 txcounters.tx_packets = NULL;
1631 }
1632 memset(&txcounters, 0, sizeof(txcounters));
1633
1634 /* ACK the half segment, leave window at half segment */
1635 p = tcp_create_rx_segment_wnd(pcb, NULL, 0, 0, TCP_MSS / 2, TCP_ACK, TCP_MSS / 2);
1636 txcounters.copy_tx_packets = 1;
1638 txcounters.copy_tx_packets = 0;
1639 /* ensure remaining segment was sent */
1640 EXPECT(txcounters.num_tx_calls == 1);
1641 EXPECT(txcounters.num_tx_bytes == ((TCP_MSS / 4) + 40U));
1642 EXPECT(pcb->unsent == NULL);
1643 EXPECT(pcb->unacked != NULL);
1644 EXPECT(pcb->unacked->len == TCP_MSS / 4);
1645 EXPECT(pcb->snd_wnd == TCP_MSS / 2);
1646
1647 /* verify remainder segment */
1648 EXPECT(txcounters.tx_packets != NULL);
1649 if (txcounters.tx_packets != NULL) {
1650 u8_t sent[TCP_MSS / 4];
1651 u16_t ret;
1652 ret = pbuf_copy_partial(txcounters.tx_packets, &sent, TCP_MSS / 4, 40U);
1653 EXPECT(ret == TCP_MSS / 4);
1654 EXPECT(memcmp(sent, &tx_data[(3 * TCP_MSS) + TCP_MSS / 2], TCP_MSS / 4) == 0);
1655 }
1656 if (txcounters.tx_packets != NULL) {
1657 pbuf_free(txcounters.tx_packets);
1658 txcounters.tx_packets = NULL;
1659 }
1660
1661 /* ensure no errors have been recorded */
1662 EXPECT(counters.err_calls == 0);
1663 EXPECT(counters.last_err == ERR_OK);
1664
1665 /* make sure the pcb is freed */
1666 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
1667 tcp_abort(pcb);
1668 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
1669}
@ sent
Definition: SystemMenu.c:27
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
struct pbuf * tcp_create_rx_segment_wnd(struct tcp_pcb *pcb, void *data, size_t data_len, u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags, u16_t wnd)
Definition: tcp_helper.c:142
static void test_tcp_tmr(void)
Definition: test_tcp.c:35

◆ START_TEST() [9/21]

END_TEST START_TEST ( test_tcp_recv_inseq  )

Create an ESTABLISHED pcb and check if receive callback is called

Definition at line 160 of file test_tcp.c.

161{
163 struct tcp_pcb* pcb;
164 struct pbuf* p;
165 char data[] = {1, 2, 3, 4};
166 u16_t data_len;
167 struct netif netif;
168 struct test_tcp_txcounters txcounters;
169 LWIP_UNUSED_ARG(_i);
170
171 /* initialize local vars */
173 data_len = sizeof(data);
174 /* initialize counter struct */
175 memset(&counters, 0, sizeof(counters));
176 counters.expected_data_len = data_len;
177 counters.expected_data = data;
178
179 /* create and initialize the pcb */
181 EXPECT_RET(pcb != NULL);
183
184 /* create a segment */
185 p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0);
186 EXPECT(p != NULL);
187 if (p != NULL) {
188 /* pass the segment to tcp_input */
190 /* check if counters are as expected */
191 EXPECT(counters.close_calls == 0);
192 EXPECT(counters.recv_calls == 1);
193 EXPECT(counters.recved_bytes == data_len);
194 EXPECT(counters.err_calls == 0);
195 }
196
197 /* make sure the pcb is freed */
198 EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
199 tcp_abort(pcb);
200 EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
201}

◆ START_TEST() [10/21]

END_TEST START_TEST ( test_tcp_recv_inseq_trim  )

Create an ESTABLISHED pcb and check if receive callback is called if a segment overlapping rcv_nxt is received

Definition at line 206 of file test_tcp.c.

207{
209 struct tcp_pcb* pcb;
210 struct pbuf* p;
211 char data[PBUF_POOL_BUFSIZE*2];
212 u16_t data_len;
213 struct netif netif;
214 struct test_tcp_txcounters txcounters;
215 const u32_t new_data_len = 40;
216 LWIP_UNUSED_ARG(_i);
217
218 /* initialize local vars */
220 data_len = sizeof(data);
221 memset(data, 0, sizeof(data));
222 /* initialize counter struct */
223 memset(&counters, 0, sizeof(counters));
224 counters.expected_data_len = data_len;
225 counters.expected_data = data;
226
227 /* create and initialize the pcb */
229 EXPECT_RET(pcb != NULL);
231
232 /* create a segment (with an overlapping/old seqno so that the new data begins in the 2nd pbuf) */
233 p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, (u32_t)(0-(data_len-new_data_len)), 0, 0);
234 EXPECT(p != NULL);
235 if (p != NULL) {
236 EXPECT(p->next != NULL);
237 if (p->next != NULL) {
238 EXPECT(p->next->next != NULL);
239 }
240 }
241 if ((p != NULL) && (p->next != NULL) && (p->next->next != NULL)) {
242 /* pass the segment to tcp_input */
244 /* check if counters are as expected */
245 EXPECT(counters.close_calls == 0);
246 EXPECT(counters.recv_calls == 1);
247 EXPECT(counters.recved_bytes == new_data_len);
248 EXPECT(counters.err_calls == 0);
249 }
250
251 /* make sure the pcb is freed */
252 EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
253 tcp_abort(pcb);
254 EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
255}
uint32_t u32_t
Definition: arch.h:129
#define PBUF_POOL_BUFSIZE
Definition: opt.h:1599

◆ START_TEST() [11/21]

END_TEST START_TEST ( test_tcp_retx_add_to_sent  )

Send data, provoke retransmission and then add data to a segment that already has been sent before.

Definition at line 949 of file test_tcp.c.

950{
951 struct netif netif;
952 struct test_tcp_txcounters txcounters;
954 struct tcp_pcb* pcb;
955 struct pbuf* p;
956 char data1a[] = { 1, 2, 3};
957 char data1b[] = { 4};
958 char data2a[] = { 5, 6, 7, 8};
959 char data2b[] = { 5, 6, 7};
960 char data3[] = { 9, 10, 11, 12, 12};
961 char data4[] = { 13, 14, 15, 16,17};
962 err_t err;
963 int i;
964 LWIP_UNUSED_ARG(_i);
965
966 /* initialize local vars */
968 memset(&counters, 0, sizeof(counters));
969
970 /* create and initialize the pcb */
972 EXPECT_RET(pcb != NULL);
974 pcb->mss = TCP_MSS;
975 /* disable initial congestion window (we don't send a SYN here...) */
976 pcb->cwnd = pcb->snd_wnd;
977
978 /* send data1 */
979 err = tcp_write(pcb, data1a, sizeof(data1a), TCP_WRITE_FLAG_COPY);
981 err = tcp_write(pcb, data1b, sizeof(data1b), TCP_WRITE_FLAG_COPY);
983 err = tcp_output(pcb);
985 EXPECT_RET(txcounters.num_tx_calls == 1);
986 EXPECT_RET(txcounters.num_tx_bytes == sizeof(data1a) + sizeof(data1b) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
987 memset(&txcounters, 0, sizeof(txcounters));
988 /* "recv" ACK for data1 */
989 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 4, TCP_ACK);
990 EXPECT_RET(p != NULL);
992 EXPECT_RET(txcounters.num_tx_calls == 0);
993 EXPECT_RET(pcb->unacked == NULL);
994 /* send data2 */
995 err = tcp_write(pcb, data2a, sizeof(data2a), TCP_WRITE_FLAG_COPY);
997 err = tcp_write(pcb, data2b, sizeof(data2b), TCP_WRITE_FLAG_COPY);
999 err = tcp_output(pcb);
1000 EXPECT_RET(err == ERR_OK);
1001 EXPECT_RET(txcounters.num_tx_calls == 1);
1002 EXPECT_RET(txcounters.num_tx_bytes == sizeof(data2a) + sizeof(data2b) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
1003 memset(&txcounters, 0, sizeof(txcounters));
1004 /* send data3 */
1005 err = tcp_write(pcb, data3, sizeof(data3), TCP_WRITE_FLAG_COPY);
1006 EXPECT_RET(err == ERR_OK);
1007 err = tcp_output(pcb);
1008 EXPECT_RET(err == ERR_OK);
1009 EXPECT_RET(txcounters.num_tx_calls == 0);
1010 EXPECT_RET(txcounters.num_tx_bytes == 0);
1011 memset(&txcounters, 0, sizeof(txcounters));
1012
1013 /* data3 not sent yet (nagle) */
1014 EXPECT_RET(pcb->unacked != NULL);
1015 EXPECT_RET(pcb->unsent != NULL);
1016
1017 /* disable nagle for this test so data to sent segment can be added below... */
1018 tcp_nagle_disable(pcb);
1019
1020 /* call the tcp timer some times */
1021 for (i = 0; i < 20; i++) {
1022 test_tcp_tmr();
1023 if (txcounters.num_tx_calls != 0) {
1024 break;
1025 }
1026 }
1027 /* data3 sent */
1028 EXPECT_RET(txcounters.num_tx_calls == 1);
1029 EXPECT_RET(txcounters.num_tx_bytes == sizeof(data3) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
1030 EXPECT_RET(pcb->unacked != NULL);
1031 EXPECT_RET(pcb->unsent == NULL);
1032 memset(&txcounters, 0, sizeof(txcounters));
1033
1034 tcp_nagle_enable(pcb);
1035
1036 /* call the tcp timer some times */
1037 for (i = 0; i < 20; i++) {
1038 test_tcp_tmr();
1039 if (txcounters.num_tx_calls != 0) {
1040 break;
1041 }
1042 }
1043 /* RTO: rexmit of data2 */
1044 EXPECT_RET(txcounters.num_tx_calls == 1);
1045 EXPECT_RET(txcounters.num_tx_bytes == sizeof(data2a) + sizeof(data2b) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
1046 EXPECT_RET(pcb->unacked != NULL);
1047 EXPECT_RET(pcb->unsent != NULL);
1048 memset(&txcounters, 0, sizeof(txcounters));
1049
1050 /* send data4 */
1051 err = tcp_write(pcb, data4, sizeof(data4), TCP_WRITE_FLAG_COPY);
1052 EXPECT_RET(err == ERR_OK);
1053 /* disable nagle for this test so data to transmit without further ACKs... */
1054 tcp_nagle_disable(pcb);
1055 err = tcp_output(pcb);
1056 EXPECT_RET(err == ERR_OK);
1057 /* nagle enabled, no tx calls */
1058 EXPECT_RET(txcounters.num_tx_calls == 1);
1059 EXPECT_RET(txcounters.num_tx_bytes == sizeof(data3) + sizeof(data4) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
1060 memset(&txcounters, 0, sizeof(txcounters));
1061 /* make sure the pcb is freed */
1062 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
1063 tcp_abort(pcb);
1064 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
1065}

◆ START_TEST() [12/21]

END_TEST START_TEST ( test_tcp_rto_rexmit_wraparound  )

Send data with sequence numbers that wrap around the u32_t range. Then, provoke RTO retransmission and check that all segment lists are still properly sorted.

Definition at line 717 of file test_tcp.c.

718{
719 struct netif netif;
720 struct test_tcp_txcounters txcounters;
722 struct tcp_pcb* pcb;
723 struct tcp_pcb dummy_pcb_for_iss; /* we need this for tcp_next_iss() only */
724 err_t err;
725 size_t i;
726 u16_t sent_total = 0;
727 LWIP_UNUSED_ARG(_i);
728
729 for (i = 0; i < sizeof(tx_data); i++) {
730 tx_data[i] = (u8_t)i;
731 }
732
733 /* initialize local vars */
735 memset(&counters, 0, sizeof(counters));
736
737 /* create and initialize the pcb */
738 tcp_ticks = 0;
739 tcp_ticks = 0 - tcp_next_iss(&dummy_pcb_for_iss);
740 tcp_ticks = SEQNO1 - tcp_next_iss(&dummy_pcb_for_iss);
742 EXPECT_RET(pcb != NULL);
744 pcb->mss = TCP_MSS;
745 /* disable initial congestion window (we don't send a SYN here...) */
746 pcb->cwnd = 2*TCP_MSS;
747
748 /* send 6 mss-sized segments */
749 for (i = 0; i < 6; i++) {
750 err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
752 sent_total += TCP_MSS;
753 }
754 check_seqnos(pcb->unsent, 6, seqnos);
755 EXPECT(pcb->unacked == NULL);
756 err = tcp_output(pcb);
758 EXPECT(txcounters.num_tx_calls == 2);
759 EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U));
760 memset(&txcounters, 0, sizeof(txcounters));
761
762 check_seqnos(pcb->unacked, 2, seqnos);
763 check_seqnos(pcb->unsent, 4, &seqnos[2]);
764
765 /* call the tcp timer some times */
766 for (i = 0; i < 10; i++) {
767 test_tcp_tmr();
768 EXPECT(txcounters.num_tx_calls == 0);
769 }
770 /* 11th call to tcp_tmr: RTO rexmit fires */
771 test_tcp_tmr();
772 EXPECT(txcounters.num_tx_calls == 1);
773 check_seqnos(pcb->unacked, 1, seqnos);
774 check_seqnos(pcb->unsent, 5, &seqnos[1]);
775
776 /* fake greater cwnd */
777 pcb->cwnd = pcb->snd_wnd;
778 /* send more data */
779 err = tcp_output(pcb);
780 EXPECT(err == ERR_OK);
781 /* check queues are sorted */
782 EXPECT(pcb->unsent == NULL);
783 check_seqnos(pcb->unacked, 6, seqnos);
784
785 /* make sure the pcb is freed */
786 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
787 tcp_abort(pcb);
788 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
789}

◆ START_TEST() [13/21]

START_TEST ( test_tcp_rto_timeout  )

Definition at line 1275 of file test_tcp.c.

1276{
1277 LWIP_UNUSED_ARG(_i);
1279}
static END_TEST void test_tcp_rto_timeout_impl(int link_down)
Definition: test_tcp.c:1191

◆ START_TEST() [14/21]

END_TEST START_TEST ( test_tcp_rto_timeout_link_down  )

Definition at line 1282 of file test_tcp.c.

1283{
1284 LWIP_UNUSED_ARG(_i);
1286}

◆ START_TEST() [15/21]

START_TEST ( test_tcp_rto_timeout_syn_sent  )

Definition at line 1371 of file test_tcp.c.

1372{
1373 LWIP_UNUSED_ARG(_i);
1375}
static END_TEST void test_tcp_rto_timeout_syn_sent_impl(int link_down)
Definition: test_tcp.c:1289

◆ START_TEST() [16/21]

END_TEST START_TEST ( test_tcp_rto_timeout_syn_sent_link_down  )

Definition at line 1378 of file test_tcp.c.

1379{
1380 LWIP_UNUSED_ARG(_i);
1382}

◆ START_TEST() [17/21]

END_TEST START_TEST ( test_tcp_rto_tracking  )

Definition at line 1068 of file test_tcp.c.

1069{
1070 struct netif netif;
1071 struct test_tcp_txcounters txcounters;
1073 struct tcp_pcb* pcb;
1074 struct pbuf* p;
1075 err_t err;
1076 size_t i;
1077 u16_t sent_total = 0;
1078 LWIP_UNUSED_ARG(_i);
1079
1080 for (i = 0; i < sizeof(tx_data); i++) {
1081 tx_data[i] = (u8_t)i;
1082 }
1083
1084 /* initialize local vars */
1086 memset(&counters, 0, sizeof(counters));
1087
1088 /* create and initialize the pcb */
1089 tcp_ticks = SEQNO1 - ISS;
1091 EXPECT_RET(pcb != NULL);
1093 pcb->mss = TCP_MSS;
1094 /* Set congestion window large enough to send all our segments */
1095 pcb->cwnd = 5*TCP_MSS;
1096
1097 /* send 5 mss-sized segments */
1098 for (i = 0; i < 5; i++) {
1099 err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
1100 EXPECT_RET(err == ERR_OK);
1101 sent_total += TCP_MSS;
1102 }
1103 check_seqnos(pcb->unsent, 5, seqnos);
1104 EXPECT(pcb->unacked == NULL);
1105 err = tcp_output(pcb);
1106 EXPECT_RET(err == ERR_OK);
1107 EXPECT(txcounters.num_tx_calls == 5);
1108 EXPECT(txcounters.num_tx_bytes == 5 * (TCP_MSS + 40U));
1109 memset(&txcounters, 0, sizeof(txcounters));
1110 /* Check all 5 are in-flight */
1111 EXPECT(pcb->unsent == NULL);
1112 check_seqnos(pcb->unacked, 5, seqnos);
1113
1114 /* Force us into retransmisson timeout */
1115 while (!(pcb->flags & TF_RTO)) {
1116 test_tcp_tmr();
1117 }
1118 /* Ensure 4 remaining segments are back on unsent, ready for retransmission */
1119 check_seqnos(pcb->unsent, 4, &seqnos[1]);
1120 /* Ensure 1st segment is on unacked (already retransmitted) */
1121 check_seqnos(pcb->unacked, 1, seqnos);
1122 EXPECT(txcounters.num_tx_calls == 1);
1123 EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U);
1124 memset(&txcounters, 0, sizeof(txcounters));
1125 /* Ensure rto_end points to next byte */
1126 EXPECT(pcb->rto_end == seqnos[5]);
1127 EXPECT(pcb->rto_end == pcb->snd_nxt);
1128 /* Check cwnd was reset */
1129 EXPECT(pcb->cwnd == pcb->mss);
1130
1131 /* Add another segment to send buffer which is outside of RTO */
1132 err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
1133 EXPECT_RET(err == ERR_OK);
1134 sent_total += TCP_MSS;
1135 check_seqnos(pcb->unsent, 5, &seqnos[1]);
1136 /* Ensure no new data was sent */
1137 EXPECT(txcounters.num_tx_calls == 0);
1138 EXPECT(txcounters.num_tx_bytes == 0);
1139 EXPECT(pcb->rto_end == pcb->snd_nxt);
1140
1141 /* ACK first segment */
1142 p = tcp_create_rx_segment(pcb, NULL, 0, 0, TCP_MSS, TCP_ACK);
1144 /* Next two retranmissions should go out, due to cwnd in slow start */
1145 EXPECT(txcounters.num_tx_calls == 2);
1146 EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U));
1147 memset(&txcounters, 0, sizeof(txcounters));
1148 check_seqnos(pcb->unacked, 2, &seqnos[1]);
1149 check_seqnos(pcb->unsent, 3, &seqnos[3]);
1150 /* RTO should still be marked */
1151 EXPECT(pcb->flags & TF_RTO);
1152 /* cwnd should have only grown by 1 MSS */
1153 EXPECT(pcb->cwnd == (tcpwnd_size_t)(2 * pcb->mss));
1154 /* Ensure no new data was sent */
1155 EXPECT(pcb->rto_end == pcb->snd_nxt);
1156
1157 /* ACK the next two segments */
1158 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 2*TCP_MSS, TCP_ACK);
1160 /* Final 2 retransmissions and 1 new data should go out */
1161 EXPECT(txcounters.num_tx_calls == 3);
1162 EXPECT(txcounters.num_tx_bytes == 3 * (TCP_MSS + 40U));
1163 memset(&txcounters, 0, sizeof(txcounters));
1164 check_seqnos(pcb->unacked, 3, &seqnos[3]);
1165 EXPECT(pcb->unsent == NULL);
1166 /* RTO should still be marked */
1167 EXPECT(pcb->flags & TF_RTO);
1168 /* cwnd should have only grown by 1 MSS */
1169 EXPECT(pcb->cwnd == (tcpwnd_size_t)(3 * pcb->mss));
1170 /* snd_nxt should have been advanced past rto_end */
1171 EXPECT(TCP_SEQ_GT(pcb->snd_nxt, pcb->rto_end));
1172
1173 /* ACK the next two segments, finishing our RTO, leaving new segment unacked */
1174 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 2*TCP_MSS, TCP_ACK);
1176 EXPECT(!(pcb->flags & TF_RTO));
1177 check_seqnos(pcb->unacked, 1, &seqnos[5]);
1178 /* We should be in ABC congestion avoidance, so no change in cwnd */
1179 EXPECT(pcb->cwnd == (tcpwnd_size_t)(3 * pcb->mss));
1180 EXPECT(pcb->cwnd >= pcb->ssthresh);
1181 /* Ensure ABC congestion avoidance is tracking bytes acked */
1182 EXPECT(pcb->bytes_acked == (tcpwnd_size_t)(2 * pcb->mss));
1183
1184 /* make sure the pcb is freed */
1185 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
1186 tcp_abort(pcb);
1187 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
1188}

◆ START_TEST() [18/21]

END_TEST START_TEST ( test_tcp_tx_full_window_lost_from_unacked  )

Definition at line 940 of file test_tcp.c.

941{
942 LWIP_UNUSED_ARG(_i);
944}
static END_TEST void test_tcp_tx_full_window_lost(u8_t zero_window_probe_from_unsent)
Definition: test_tcp.c:794

◆ START_TEST() [19/21]

START_TEST ( test_tcp_tx_full_window_lost_from_unsent  )

Definition at line 933 of file test_tcp.c.

934{
935 LWIP_UNUSED_ARG(_i);
937}

◆ START_TEST() [20/21]

START_TEST ( test_tcp_zwp_timeout  )

Definition at line 1500 of file test_tcp.c.

1501{
1502 LWIP_UNUSED_ARG(_i);
1504}
static END_TEST void test_tcp_zwp_timeout_impl(int link_down)
Definition: test_tcp.c:1385

◆ START_TEST() [21/21]

END_TEST START_TEST ( test_tcp_zwp_timeout_link_down  )

Definition at line 1507 of file test_tcp.c.

1508{
1509 LWIP_UNUSED_ARG(_i);
1511}

◆ tcp_setup()

static void tcp_setup ( void  )
static

Definition at line 48 of file test_tcp.c.

49{
50 struct tcp_pcb dummy_pcb; /* we need this for tcp_next_iss() only */
51
56 /* reset iss to default (6510) */
57 tcp_ticks = 0;
58 tcp_ticks = 0 - (tcp_next_iss(&dummy_pcb) - 6510);
59 tcp_next_iss(&dummy_pcb);
60 tcp_ticks = 0;
61
64 lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
65}
#define SKIP_POOL(x)
Definition: lwip_check.h:48
void lwip_check_ensure_no_alloc(unsigned int skip)
struct netif * netif_list
Definition: netif.c:113
struct netif * netif_default
Definition: netif.c:115
void tcp_remove_all(void)
Definition: tcp_helper.c:38
static struct netif * old_netif_list
Definition: test_tcp.c:44
static struct netif * old_netif_default
Definition: test_tcp.c:45
static u8_t test_tcp_timer
Definition: test_tcp.c:31

Referenced by tcp_suite().

◆ tcp_suite()

END_TEST Suite * tcp_suite ( void  )

Create the suite including all tests for this module

Definition at line 1674 of file test_tcp.c.

1675{
1676 testfunc tests[] = {
1677 TESTFUNC(test_tcp_new_abort),
1678 TESTFUNC(test_tcp_listen_passive_open),
1679 TESTFUNC(test_tcp_recv_inseq),
1680 TESTFUNC(test_tcp_recv_inseq_trim),
1681 TESTFUNC(test_tcp_passive_close),
1682 TESTFUNC(test_tcp_active_abort),
1683 TESTFUNC(test_tcp_malformed_header),
1684 TESTFUNC(test_tcp_fast_retx_recover),
1685 TESTFUNC(test_tcp_fast_rexmit_wraparound),
1686 TESTFUNC(test_tcp_rto_rexmit_wraparound),
1687 TESTFUNC(test_tcp_tx_full_window_lost_from_unacked),
1688 TESTFUNC(test_tcp_tx_full_window_lost_from_unsent),
1689 TESTFUNC(test_tcp_retx_add_to_sent),
1690 TESTFUNC(test_tcp_rto_tracking),
1691 TESTFUNC(test_tcp_rto_timeout),
1692 TESTFUNC(test_tcp_rto_timeout_link_down),
1693 TESTFUNC(test_tcp_rto_timeout_syn_sent),
1694 TESTFUNC(test_tcp_rto_timeout_syn_sent_link_down),
1695 TESTFUNC(test_tcp_zwp_timeout),
1696 TESTFUNC(test_tcp_zwp_timeout_link_down),
1697 TESTFUNC(test_tcp_persist_split)
1698 };
1699 return create_suite("TCP", tests, sizeof(tests)/sizeof(testfunc), tcp_setup, tcp_teardown);
1700}
Suite * create_suite(const char *name, testfunc *tests, size_t num_tests, SFun setup, SFun teardown)
#define TESTFUNC(x)
Definition: lwip_check.h:22
static struct test_info tests[]
static void tcp_teardown(void)
Definition: test_tcp.c:68
static void tcp_setup(void)
Definition: test_tcp.c:48

Referenced by main().

◆ tcp_teardown()

static void tcp_teardown ( void  )
static

Definition at line 68 of file test_tcp.c.

69{
73 /* restore netif_list for next tests (e.g. loopif) */
76 lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
77}

Referenced by tcp_suite().

◆ test_tcp_recv_expect1byte()

static err_t test_tcp_recv_expect1byte ( void arg,
struct tcp_pcb *  pcb,
struct pbuf p,
err_t  err 
)
static

Definition at line 280 of file test_tcp.c.

281{
282 EXPECT_RETX(pcb != NULL, ERR_OK);
285
286 if (p != NULL) {
287 if ((p->len == 1) && (p->tot_len == 1)) {
289 } else {
290 fail();
291 }
292 pbuf_free(p);
293 } else {
294 fail();
295 }
296 return ERR_OK;
297}
#define EXPECT_RETX(x, y)
Definition: lwip_check.h:13
static err_t test_tcp_recv_expectclose(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
Definition: test_tcp.c:261

Referenced by START_TEST(), and test_tcp_recv_expectclose().

◆ test_tcp_recv_expectclose()

static err_t test_tcp_recv_expectclose ( void arg,
struct tcp_pcb *  pcb,
struct pbuf p,
err_t  err 
)
static

Definition at line 261 of file test_tcp.c.

262{
263 EXPECT_RETX(pcb != NULL, ERR_OK);
266
267 if (p != NULL) {
268 fail();
269 } else {
270 /* correct: FIN received; close our end, too */
271 err_t err2 = tcp_close(pcb);
272 fail_unless(err2 == ERR_OK);
273 /* set back to some other rx function, just to not get here again */
275 }
276 return ERR_OK;
277}

Referenced by test_tcp_recv_expect1byte().

◆ test_tcp_rto_timeout_impl()

static END_TEST void test_tcp_rto_timeout_impl ( int  link_down)
static

Definition at line 1191 of file test_tcp.c.

1192{
1193 struct netif netif;
1194 struct test_tcp_txcounters txcounters;
1196 struct tcp_pcb *pcb, *cur;
1197 err_t err;
1198 size_t i;
1199 const size_t max_wait_ctr = 1024 * 1024;
1200
1201 /* Setup data for a single segment */
1202 for (i = 0; i < TCP_MSS; i++) {
1203 tx_data[i] = (u8_t)i;
1204 }
1205
1206 /* initialize local vars */
1208 memset(&counters, 0, sizeof(counters));
1209
1210 /* create and initialize the pcb */
1211 tcp_ticks = SEQNO1 - ISS;
1213 EXPECT_RET(pcb != NULL);
1215 pcb->mss = TCP_MSS;
1216 pcb->cwnd = TCP_MSS;
1217
1218 /* send our segment */
1219 err = tcp_write(pcb, &tx_data[0], TCP_MSS, TCP_WRITE_FLAG_COPY);
1220 EXPECT_RET(err == ERR_OK);
1221 err = tcp_output(pcb);
1222 EXPECT_RET(err == ERR_OK);
1223 EXPECT(txcounters.num_tx_calls == 1);
1224 EXPECT(txcounters.num_tx_bytes == 1 * (TCP_MSS + 40U));
1225 memset(&txcounters, 0, sizeof(txcounters));
1226
1227 /* ensure no errors have been recorded */
1228 EXPECT(counters.err_calls == 0);
1229 EXPECT(counters.last_err == ERR_OK);
1230
1231 /* Force us into retransmisson timeout */
1232 for (i = 0; !(pcb->flags & TF_RTO) && i < max_wait_ctr; i++) {
1233 test_tcp_tmr();
1234 }
1235 EXPECT(i < max_wait_ctr);
1236
1237 /* check first rexmit */
1238 EXPECT(pcb->nrtx == 1);
1239 EXPECT(txcounters.num_tx_calls == 1);
1240 EXPECT(txcounters.num_tx_bytes == 1 * (TCP_MSS + 40U));
1241
1242 /* still no error expected */
1243 EXPECT(counters.err_calls == 0);
1244 EXPECT(counters.last_err == ERR_OK);
1245
1246 if (link_down) {
1248 }
1249
1250 /* keep running the timer till we hit our maximum RTO */
1251 for (i = 0; counters.last_err == ERR_OK && i < max_wait_ctr; i++) {
1252 test_tcp_tmr();
1253 }
1254 EXPECT(i < max_wait_ctr);
1255
1256 /* check number of retransmissions */
1257 if (link_down) {
1258 EXPECT(txcounters.num_tx_calls == 1);
1259 EXPECT(txcounters.num_tx_bytes == 1 * (TCP_MSS + 40U));
1260 } else {
1261 EXPECT(txcounters.num_tx_calls == TCP_MAXRTX);
1262 EXPECT(txcounters.num_tx_bytes == TCP_MAXRTX * (TCP_MSS + 40U));
1263 }
1264
1265 /* check the connection (pcb) has been aborted */
1266 EXPECT(counters.err_calls == 1);
1267 EXPECT(counters.last_err == ERR_ABRT);
1268 /* check our pcb is no longer active */
1269 for (cur = tcp_active_pcbs; cur != NULL; cur = cur->next) {
1270 EXPECT(cur != pcb);
1271 }
1272 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
1273}
FxCollectionEntry * cur
@ ERR_ABRT
Definition: err.h:82
void netif_set_link_down(struct netif *netif)
Definition: netif.c:1056
#define TCP_MAXRTX
Definition: lwipopts.h:52

Referenced by START_TEST().

◆ test_tcp_rto_timeout_syn_sent_impl()

static END_TEST void test_tcp_rto_timeout_syn_sent_impl ( int  link_down)
static

Definition at line 1289 of file test_tcp.c.

1290{
1291 struct netif netif;
1292 struct test_tcp_txcounters txcounters;
1294 struct tcp_pcb *pcb, *cur;
1295 err_t err;
1296 size_t i;
1297 const size_t max_wait_ctr = 1024 * 1024;
1298 const u16_t tcp_syn_opts_len = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_MSS|TF_SEG_OPTS_WND_SCALE|TF_SEG_OPTS_SACK_PERM|TF_SEG_OPTS_TS);
1299
1300 /* Setup data for a single segment */
1301 for (i = 0; i < TCP_MSS; i++) {
1302 tx_data[i] = (u8_t)i;
1303 }
1304
1305 /* initialize local vars */
1307 memset(&counters, 0, sizeof(counters));
1308
1309 /* create and initialize the pcb */
1310 tcp_ticks = SEQNO1 - ISS;
1312 EXPECT_RET(pcb != NULL);
1313 err = tcp_connect(pcb, &netif.gw, 123, NULL);
1314 EXPECT_RET(err == ERR_OK);
1315 EXPECT_RET(pcb->state == SYN_SENT);
1316 EXPECT(txcounters.num_tx_calls == 1);
1317 EXPECT(txcounters.num_tx_bytes == 40U + tcp_syn_opts_len);
1318
1319 /* ensure no errors have been recorded */
1320 EXPECT(counters.err_calls == 0);
1321 EXPECT(counters.last_err == ERR_OK);
1322
1323 txcounters.num_tx_calls = 0;
1324 txcounters.num_tx_bytes = 0;
1325
1326 /* Force us into retransmisson timeout */
1327 for (i = 0; !(pcb->flags & TF_RTO) && i < max_wait_ctr; i++) {
1328 test_tcp_tmr();
1329 }
1330 EXPECT(i < max_wait_ctr);
1331
1332 /* check first rexmit */
1333 EXPECT(pcb->nrtx == 1);
1334 EXPECT(txcounters.num_tx_calls == 1);
1335 EXPECT(txcounters.num_tx_bytes == 40U + tcp_syn_opts_len); /* 40: headers; >=: options */
1336
1337 /* still no error expected */
1338 EXPECT(counters.err_calls == 0);
1339 EXPECT(counters.last_err == ERR_OK);
1340
1341 if (link_down) {
1342 /* set link down and check what happens to the RTO counter */
1344 }
1345
1346 /* keep running the timer till we hit our maximum RTO */
1347 for (i = 0; counters.last_err == ERR_OK && i < max_wait_ctr; i++) {
1348 test_tcp_tmr();
1349 }
1350 EXPECT(i < max_wait_ctr);
1351
1352 /* check number of retransmissions */
1353 if (link_down) {
1354 EXPECT(txcounters.num_tx_calls == 1);
1355 EXPECT(txcounters.num_tx_bytes == 40U + tcp_syn_opts_len);
1356 } else {
1357 EXPECT(txcounters.num_tx_calls == TCP_SYNMAXRTX);
1358 EXPECT(txcounters.num_tx_bytes == TCP_SYNMAXRTX * (tcp_syn_opts_len + 40U));
1359 }
1360
1361 /* check the connection (pcb) has been aborted */
1362 EXPECT(counters.err_calls == 1);
1363 EXPECT(counters.last_err == ERR_ABRT);
1364 /* check our pcb is no longer active */
1365 for (cur = tcp_active_pcbs; cur != NULL; cur = cur->next) {
1366 EXPECT(cur != pcb);
1367 }
1368 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
1369}
RD_BOOL tcp_connect(char *server)
Definition: tcp.c:717
#define TCP_SYNMAXRTX
Definition: lwipopts.h:54

Referenced by START_TEST().

◆ test_tcp_tmr()

static void test_tcp_tmr ( void  )
static

Definition at line 35 of file test_tcp.c.

36{
37 tcp_fasttmr();
38 if (++test_tcp_timer & 1) {
39 tcp_slowtmr();
40 }
41}

Referenced by START_TEST(), test_tcp_rto_timeout_impl(), test_tcp_rto_timeout_syn_sent_impl(), test_tcp_tx_full_window_lost(), and test_tcp_zwp_timeout_impl().

◆ test_tcp_tx_full_window_lost()

static END_TEST void test_tcp_tx_full_window_lost ( u8_t  zero_window_probe_from_unsent)
static

Provoke fast retransmission by duplicate ACKs and then recover by ACKing all sent data. At the end, send more data.

Definition at line 794 of file test_tcp.c.

795{
796 struct netif netif;
797 struct test_tcp_txcounters txcounters;
799 struct tcp_pcb* pcb;
800 struct pbuf *p;
801 err_t err;
802 size_t i;
803 u16_t sent_total;
804 u8_t expected = 0xFE;
805
806 for (i = 0; i < sizeof(tx_data); i++) {
807 u8_t d = (u8_t)i;
808 if (d == 0xFE) {
809 d = 0xF0;
810 }
811 tx_data[i] = d;
812 }
813 if (zero_window_probe_from_unsent) {
815 } else {
816 tx_data[0] = expected;
817 }
818
819 /* initialize local vars */
821 memset(&counters, 0, sizeof(counters));
822
823 /* create and initialize the pcb */
825 EXPECT_RET(pcb != NULL);
827 pcb->mss = TCP_MSS;
828 /* disable initial congestion window (we don't send a SYN here...) */
829 pcb->cwnd = pcb->snd_wnd;
830
831 /* send a full window (minus 1 packets) of TCP data in MSS-sized chunks */
832 sent_total = 0;
833 if ((TCP_WND - TCP_MSS) % TCP_MSS != 0) {
834 u16_t initial_data_len = (TCP_WND - TCP_MSS) % TCP_MSS;
835 err = tcp_write(pcb, &tx_data[sent_total], initial_data_len, TCP_WRITE_FLAG_COPY);
837 err = tcp_output(pcb);
839 EXPECT(txcounters.num_tx_calls == 1);
840 EXPECT(txcounters.num_tx_bytes == initial_data_len + 40U);
841 memset(&txcounters, 0, sizeof(txcounters));
842 sent_total += initial_data_len;
843 }
844 for (; sent_total < (TCP_WND - TCP_MSS); sent_total += TCP_MSS) {
845 err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
847 err = tcp_output(pcb);
849 EXPECT(txcounters.num_tx_calls == 1);
850 EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U);
851 memset(&txcounters, 0, sizeof(txcounters));
852 }
853 EXPECT(sent_total == (TCP_WND - TCP_MSS));
854
855 /* now ACK the packet before the first */
856 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
858 /* ensure this didn't trigger a retransmission */
859 EXPECT(txcounters.num_tx_calls == 0);
860 EXPECT(txcounters.num_tx_bytes == 0);
861
862 EXPECT(pcb->persist_backoff == 0);
863 /* send the last packet, now a complete window has been sent */
864 err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
865 sent_total += TCP_MSS;
867 err = tcp_output(pcb);
869 EXPECT(txcounters.num_tx_calls == 1);
870 EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U);
871 memset(&txcounters, 0, sizeof(txcounters));
872 EXPECT(pcb->persist_backoff == 0);
873
874 if (zero_window_probe_from_unsent) {
875 /* ACK all data but close the TX window */
878 /* ensure this didn't trigger any transmission */
879 EXPECT(txcounters.num_tx_calls == 0);
880 EXPECT(txcounters.num_tx_bytes == 0);
881 /* window is completely full, but persist timer is off since send buffer is empty */
882 EXPECT(pcb->snd_wnd == 0);
883 EXPECT(pcb->persist_backoff == 0);
884 }
885
886 /* send one byte more (out of window) -> persist timer starts */
887 err = tcp_write(pcb, &tx_data[sent_total], 1, TCP_WRITE_FLAG_COPY);
889 err = tcp_output(pcb);
891 EXPECT(txcounters.num_tx_calls == 0);
892 EXPECT(txcounters.num_tx_bytes == 0);
893 memset(&txcounters, 0, sizeof(txcounters));
894 if (!zero_window_probe_from_unsent) {
895 /* no persist timer unless a zero window announcement has been received */
896 EXPECT(pcb->persist_backoff == 0);
897 } else {
898 EXPECT(pcb->persist_backoff == 1);
899
900 /* call tcp_timer some more times to let persist timer count up */
901 for (i = 0; i < 4; i++) {
902 test_tcp_tmr();
903 EXPECT(txcounters.num_tx_calls == 0);
904 EXPECT(txcounters.num_tx_bytes == 0);
905 }
906
907 /* this should trigger the zero-window-probe */
908 txcounters.copy_tx_packets = 1;
909 test_tcp_tmr();
910 txcounters.copy_tx_packets = 0;
911 EXPECT(txcounters.num_tx_calls == 1);
912 EXPECT(txcounters.num_tx_bytes == 1 + 40U);
913 EXPECT(txcounters.tx_packets != NULL);
914 if (txcounters.tx_packets != NULL) {
915 u8_t sent;
916 u16_t ret;
917 ret = pbuf_copy_partial(txcounters.tx_packets, &sent, 1, 40U);
918 EXPECT(ret == 1);
919 EXPECT(sent == expected);
920 }
921 if (txcounters.tx_packets != NULL) {
922 pbuf_free(txcounters.tx_packets);
923 txcounters.tx_packets = NULL;
924 }
925 }
926
927 /* make sure the pcb is freed */
928 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
929 tcp_abort(pcb);
930 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
931}
#define TCP_WND
Definition: lwipopts.h:48
#define d
Definition: ke_i.h:81
BOOL expected
Definition: store.c:2063

Referenced by START_TEST().

◆ test_tcp_zwp_timeout_impl()

static END_TEST void test_tcp_zwp_timeout_impl ( int  link_down)
static

Definition at line 1385 of file test_tcp.c.

1386{
1387 struct netif netif;
1388 struct test_tcp_txcounters txcounters;
1390 struct tcp_pcb *pcb, *cur;
1391 struct pbuf* p;
1392 err_t err;
1393 size_t i;
1394
1395 /* Setup data for two segments */
1396 for (i = 0; i < 2*TCP_MSS; i++) {
1397 tx_data[i] = (u8_t)i;
1398 }
1399
1400 /* initialize local vars */
1402 memset(&counters, 0, sizeof(counters));
1403
1404 /* create and initialize the pcb */
1405 tcp_ticks = SEQNO1 - ISS;
1407 EXPECT_RET(pcb != NULL);
1409 pcb->mss = TCP_MSS;
1410 pcb->cwnd = TCP_MSS;
1411
1412 /* send first segment */
1413 err = tcp_write(pcb, &tx_data[0], TCP_MSS, TCP_WRITE_FLAG_COPY);
1414 EXPECT(err == ERR_OK);
1415 err = tcp_output(pcb);
1416 EXPECT(err == ERR_OK);
1417
1418 /* verify segment is in-flight */
1419 EXPECT(pcb->unsent == NULL);
1420 check_seqnos(pcb->unacked, 1, seqnos);
1421 EXPECT(txcounters.num_tx_calls == 1);
1422 EXPECT(txcounters.num_tx_bytes == 1 * (TCP_MSS + 40U));
1423 memset(&txcounters, 0, sizeof(txcounters));
1424
1425 /* ACK the segment and close the TX window */
1426 p = tcp_create_rx_segment_wnd(pcb, NULL, 0, 0, TCP_MSS, TCP_ACK, 0);
1428 EXPECT(pcb->unacked == NULL);
1429 EXPECT(pcb->unsent == NULL);
1430 /* send buffer empty, persist should be off */
1431 EXPECT(pcb->persist_backoff == 0);
1432 EXPECT(pcb->snd_wnd == 0);
1433
1434 /* send second segment, should be buffered */
1435 err = tcp_write(pcb, &tx_data[TCP_MSS], TCP_MSS, TCP_WRITE_FLAG_COPY);
1436 EXPECT(err == ERR_OK);
1437 err = tcp_output(pcb);
1438 EXPECT(err == ERR_OK);
1439
1440 /* ensure it is buffered and persist timer started */
1441 EXPECT(pcb->unacked == NULL);
1442 check_seqnos(pcb->unsent, 1, &seqnos[1]);
1443 EXPECT(txcounters.num_tx_calls == 0);
1444 EXPECT(txcounters.num_tx_bytes == 0);
1445 EXPECT(pcb->persist_backoff == 1);
1446
1447 /* ensure no errors have been recorded */
1448 EXPECT(counters.err_calls == 0);
1449 EXPECT(counters.last_err == ERR_OK);
1450
1451 /* run timer till first probe */
1452 EXPECT(pcb->persist_probe == 0);
1453 while (pcb->persist_probe == 0) {
1454 test_tcp_tmr();
1455 }
1456 EXPECT(txcounters.num_tx_calls == 1);
1457 EXPECT(txcounters.num_tx_bytes == (1 + 40U));
1458 memset(&txcounters, 0, sizeof(txcounters));
1459
1460 /* respond to probe with remote's current SEQ, ACK, and zero-window */
1461 p = tcp_create_rx_segment_wnd(pcb, NULL, 0, 0, 0, TCP_ACK, 0);
1463 /* ensure zero-window is still active, but probe count reset */
1464 EXPECT(pcb->persist_backoff > 1);
1465 EXPECT(pcb->persist_probe == 0);
1466 EXPECT(pcb->snd_wnd == 0);
1467
1468 /* ensure no errors have been recorded */
1469 EXPECT(counters.err_calls == 0);
1470 EXPECT(counters.last_err == ERR_OK);
1471
1472 if (link_down) {
1474 }
1475
1476 /* now run the timer till we hit our maximum probe count */
1477 while (counters.last_err == ERR_OK) {
1478 test_tcp_tmr();
1479 }
1480
1481 if (link_down) {
1482 EXPECT(txcounters.num_tx_calls == 0);
1483 EXPECT(txcounters.num_tx_bytes == 0);
1484 } else {
1485 /* check maximum number of 1 byte probes were sent */
1486 EXPECT(txcounters.num_tx_calls == TCP_MAXRTX);
1487 EXPECT(txcounters.num_tx_bytes == TCP_MAXRTX * (1 + 40U));
1488 }
1489
1490 /* check the connection (pcb) has been aborted */
1491 EXPECT(counters.err_calls == 1);
1492 EXPECT(counters.last_err == ERR_ABRT);
1493 /* check our pcb is no longer active */
1494 for (cur = tcp_active_pcbs; cur != NULL; cur = cur->next) {
1495 EXPECT(cur != pcb);
1496 }
1497 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
1498}

Referenced by START_TEST().

Variable Documentation

◆ old_netif_default

struct netif* old_netif_default
static

Definition at line 45 of file test_tcp.c.

Referenced by tcp_setup(), and tcp_teardown().

◆ old_netif_list

struct netif* old_netif_list
static

Definition at line 44 of file test_tcp.c.

Referenced by tcp_setup(), and tcp_teardown().

◆ seqnos

u32_t seqnos[]
static
Initial value:
= {
SEQNO1 + (1 * TCP_MSS),
SEQNO1 + (2 * TCP_MSS),
SEQNO1 + (3 * TCP_MSS),
SEQNO1 + (4 * TCP_MSS),
SEQNO1 + (5 * TCP_MSS) }

Definition at line 23 of file test_tcp.c.

Referenced by START_TEST(), and test_tcp_zwp_timeout_impl().

◆ test_tcp_timer

u8_t test_tcp_timer
static

Definition at line 31 of file test_tcp.c.

Referenced by tcp_setup(), and test_tcp_tmr().

◆ tx_data