Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers test_tcp.c Source File

test_tcp.c

00001 #include "test_tcp.h"
00002 
00003 #include "lwip/priv/tcp_priv.h"
00004 #include "lwip/stats.h"
00005 #include "tcp_helper.h"
00006 #include "lwip/inet_chksum.h"
00007 
00008 #ifdef _MSC_VER
00009 #pragma warning(disable: 4307) /* we explicitly wrap around TCP seqnos */
00010 #endif
00011 
00012 #if !LWIP_STATS || !TCP_STATS || !MEMP_STATS
00013 #error "This tests needs TCP- and MEMP-statistics enabled"
00014 #endif
00015 #if TCP_SND_BUF <= TCP_WND
00016 #error "This tests needs TCP_SND_BUF to be > TCP_WND"
00017 #endif
00018 
00019 static u8_t test_tcp_timer;
00020 
00021 /* our own version of tcp_tmr so we can reset fast/slow timer state */
00022 static void
00023 test_tcp_tmr(void)
00024 {
00025   tcp_fasttmr();
00026   if (++test_tcp_timer & 1) {
00027     tcp_slowtmr();
00028   }
00029 }
00030 
00031 /* Setups/teardown functions */
00032 
00033 static void
00034 tcp_setup(void)
00035 {
00036   /* reset iss to default (6510) */
00037   tcp_ticks = 0;
00038   tcp_ticks = 0 - (tcp_next_iss(NULL) - 6510);
00039   tcp_next_iss(NULL);
00040   tcp_ticks = 0;
00041 
00042   test_tcp_timer = 0;
00043   tcp_remove_all();
00044 }
00045 
00046 static void
00047 tcp_teardown(void)
00048 {
00049   netif_list = NULL;
00050   netif_default = NULL;
00051   tcp_remove_all();
00052 }
00053 
00054 
00055 /* Test functions */
00056 
00057 /** Call tcp_new() and tcp_abort() and test memp stats */
00058 START_TEST(test_tcp_new_abort)
00059 {
00060   struct tcp_pcb* pcb;
00061   LWIP_UNUSED_ARG(_i);
00062 
00063   fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
00064 
00065   pcb = tcp_new();
00066   fail_unless(pcb != NULL);
00067   if (pcb != NULL) {
00068     fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
00069     tcp_abort(pcb);
00070     fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
00071   }
00072 }
00073 END_TEST
00074 
00075 /** Create an ESTABLISHED pcb and check if receive callback is called */
00076 START_TEST(test_tcp_recv_inseq)
00077 {
00078   struct test_tcp_counters counters;
00079   struct tcp_pcb* pcb;
00080   struct pbuf* p;
00081   char data[] = {1, 2, 3, 4};
00082   ip_addr_t remote_ip, local_ip, netmask;
00083   u16_t data_len;
00084   u16_t remote_port = 0x100, local_port = 0x101;
00085   struct netif netif;
00086   struct test_tcp_txcounters txcounters;
00087   LWIP_UNUSED_ARG(_i);
00088 
00089   /* initialize local vars */
00090   memset(&netif, 0, sizeof(netif));
00091   IP_ADDR4(&local_ip, 192, 168, 1, 1);
00092   IP_ADDR4(&remote_ip, 192, 168, 1, 2);
00093   IP_ADDR4(&netmask,   255, 255, 255, 0);
00094   test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask);
00095   data_len = sizeof(data);
00096   /* initialize counter struct */
00097   memset(&counters, 0, sizeof(counters));
00098   counters.expected_data_len = data_len;
00099   counters.expected_data = data;
00100 
00101   /* create and initialize the pcb */
00102   pcb = test_tcp_new_counters_pcb(&counters);
00103   EXPECT_RET(pcb != NULL);
00104   tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
00105 
00106   /* create a segment */
00107   p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0);
00108   EXPECT(p != NULL);
00109   if (p != NULL) {
00110     /* pass the segment to tcp_input */
00111     test_tcp_input(p, &netif);
00112     /* check if counters are as expected */
00113     EXPECT(counters.close_calls == 0);
00114     EXPECT(counters.recv_calls == 1);
00115     EXPECT(counters.recved_bytes == data_len);
00116     EXPECT(counters.err_calls == 0);
00117   }
00118 
00119   /* make sure the pcb is freed */
00120   EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
00121   tcp_abort(pcb);
00122   EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
00123 }
00124 END_TEST
00125 
00126 /** Check that we handle malformed tcp headers, and discard the pbuf(s) */
00127 START_TEST(test_tcp_malformed_header)
00128 {
00129   struct test_tcp_counters counters;
00130   struct tcp_pcb* pcb;
00131   struct pbuf* p;
00132   char data[] = {1, 2, 3, 4};
00133   ip_addr_t remote_ip, local_ip, netmask;
00134   u16_t data_len, chksum;
00135   u16_t remote_port = 0x100, local_port = 0x101;
00136   struct netif netif;
00137   struct test_tcp_txcounters txcounters;
00138   struct tcp_hdr *hdr;
00139   LWIP_UNUSED_ARG(_i);
00140 
00141   /* initialize local vars */
00142   memset(&netif, 0, sizeof(netif));
00143   IP_ADDR4(&local_ip, 192, 168, 1, 1);
00144   IP_ADDR4(&remote_ip, 192, 168, 1, 2);
00145   IP_ADDR4(&netmask,   255, 255, 255, 0);
00146   test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask);
00147   data_len = sizeof(data);
00148   /* initialize counter struct */
00149   memset(&counters, 0, sizeof(counters));
00150   counters.expected_data_len = data_len;
00151   counters.expected_data = data;
00152 
00153   /* create and initialize the pcb */
00154   pcb = test_tcp_new_counters_pcb(&counters);
00155   EXPECT_RET(pcb != NULL);
00156   tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
00157 
00158   /* create a segment */
00159   p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0);
00160 
00161   pbuf_header(p, -(s16_t)sizeof(struct ip_hdr));
00162 
00163   hdr = (struct tcp_hdr *)p->payload;
00164   TCPH_HDRLEN_FLAGS_SET(hdr, 15, 0x3d1);
00165 
00166   hdr->chksum = 0;
00167 
00168   chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
00169                              &remote_ip, &local_ip);
00170 
00171   hdr->chksum = chksum;
00172 
00173   pbuf_header(p, sizeof(struct ip_hdr));
00174 
00175   EXPECT(p != NULL);
00176   EXPECT(p->next == NULL);
00177   if (p != NULL) {
00178     /* pass the segment to tcp_input */
00179     test_tcp_input(p, &netif);
00180     /* check if counters are as expected */
00181     EXPECT(counters.close_calls == 0);
00182     EXPECT(counters.recv_calls == 0);
00183     EXPECT(counters.recved_bytes == 0);
00184     EXPECT(counters.err_calls == 0);
00185   }
00186 
00187   /* make sure the pcb is freed */
00188   EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
00189   tcp_abort(pcb);
00190   EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
00191 }
00192 END_TEST
00193 
00194 
00195 /** Provoke fast retransmission by duplicate ACKs and then recover by ACKing all sent data.
00196  * At the end, send more data. */
00197 START_TEST(test_tcp_fast_retx_recover)
00198 {
00199   struct netif netif;
00200   struct test_tcp_txcounters txcounters;
00201   struct test_tcp_counters counters;
00202   struct tcp_pcb* pcb;
00203   struct pbuf* p;
00204   char data1[] = { 1,  2,  3,  4};
00205   char data2[] = { 5,  6,  7,  8};
00206   char data3[] = { 9, 10, 11, 12};
00207   char data4[] = {13, 14, 15, 16};
00208   char data5[] = {17, 18, 19, 20};
00209   char data6[TCP_MSS] = {21, 22, 23, 24};
00210   ip_addr_t remote_ip, local_ip, netmask;
00211   u16_t remote_port = 0x100, local_port = 0x101;
00212   err_t err;
00213   LWIP_UNUSED_ARG(_i);
00214 
00215   /* initialize local vars */
00216   IP_ADDR4(&local_ip,  192, 168,   1, 1);
00217   IP_ADDR4(&remote_ip, 192, 168,   1, 2);
00218   IP_ADDR4(&netmask,   255, 255, 255, 0);
00219   test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask);
00220   memset(&counters, 0, sizeof(counters));
00221 
00222   /* create and initialize the pcb */
00223   pcb = test_tcp_new_counters_pcb(&counters);
00224   EXPECT_RET(pcb != NULL);
00225   tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
00226   pcb->mss = TCP_MSS;
00227   /* disable initial congestion window (we don't send a SYN here...) */
00228   pcb->cwnd = pcb->snd_wnd;
00229 
00230   /* send data1 */
00231   err = tcp_write(pcb, data1, sizeof(data1), TCP_WRITE_FLAG_COPY);
00232   EXPECT_RET(err == ERR_OK);
00233   err = tcp_output(pcb);
00234   EXPECT_RET(err == ERR_OK);
00235   EXPECT_RET(txcounters.num_tx_calls == 1);
00236   EXPECT_RET(txcounters.num_tx_bytes == sizeof(data1) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
00237   memset(&txcounters, 0, sizeof(txcounters));
00238  /* "recv" ACK for data1 */
00239   p = tcp_create_rx_segment(pcb, NULL, 0, 0, 4, TCP_ACK);
00240   EXPECT_RET(p != NULL);
00241   test_tcp_input(p, &netif);
00242   EXPECT_RET(txcounters.num_tx_calls == 0);
00243   EXPECT_RET(pcb->unacked == NULL);
00244   /* send data2 */
00245   err = tcp_write(pcb, data2, sizeof(data2), TCP_WRITE_FLAG_COPY);
00246   EXPECT_RET(err == ERR_OK);
00247   err = tcp_output(pcb);
00248   EXPECT_RET(err == ERR_OK);
00249   EXPECT_RET(txcounters.num_tx_calls == 1);
00250   EXPECT_RET(txcounters.num_tx_bytes == sizeof(data2) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
00251   memset(&txcounters, 0, sizeof(txcounters));
00252   /* duplicate ACK for data1 (data2 is lost) */
00253   p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
00254   EXPECT_RET(p != NULL);
00255   test_tcp_input(p, &netif);
00256   EXPECT_RET(txcounters.num_tx_calls == 0);
00257   EXPECT_RET(pcb->dupacks == 1);
00258   /* send data3 */
00259   err = tcp_write(pcb, data3, sizeof(data3), TCP_WRITE_FLAG_COPY);
00260   EXPECT_RET(err == ERR_OK);
00261   err = tcp_output(pcb);
00262   EXPECT_RET(err == ERR_OK);
00263   /* nagle enabled, no tx calls */
00264   EXPECT_RET(txcounters.num_tx_calls == 0);
00265   EXPECT_RET(txcounters.num_tx_bytes == 0);
00266   memset(&txcounters, 0, sizeof(txcounters));
00267   /* 2nd duplicate ACK for data1 (data2 and data3 are lost) */
00268   p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
00269   EXPECT_RET(p != NULL);
00270   test_tcp_input(p, &netif);
00271   EXPECT_RET(txcounters.num_tx_calls == 0);
00272   EXPECT_RET(pcb->dupacks == 2);
00273   /* queue data4, don't send it (unsent-oversize is != 0) */
00274   err = tcp_write(pcb, data4, sizeof(data4), TCP_WRITE_FLAG_COPY);
00275   EXPECT_RET(err == ERR_OK);
00276   /* 3nd duplicate ACK for data1 (data2 and data3 are lost) -> fast retransmission */
00277   p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
00278   EXPECT_RET(p != NULL);
00279   test_tcp_input(p, &netif);
00280   /*EXPECT_RET(txcounters.num_tx_calls == 1);*/
00281   EXPECT_RET(pcb->dupacks == 3);
00282   memset(&txcounters, 0, sizeof(txcounters));
00283   /* @todo: check expected data?*/
00284   
00285   /* send data5, not output yet */
00286   err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
00287   EXPECT_RET(err == ERR_OK);
00288   /*err = tcp_output(pcb);
00289   EXPECT_RET(err == ERR_OK);*/
00290   EXPECT_RET(txcounters.num_tx_calls == 0);
00291   EXPECT_RET(txcounters.num_tx_bytes == 0);
00292   memset(&txcounters, 0, sizeof(txcounters));
00293   {
00294     int i = 0;
00295     do
00296     {
00297       err = tcp_write(pcb, data6, TCP_MSS, TCP_WRITE_FLAG_COPY);
00298       i++;
00299     }while(err == ERR_OK);
00300     EXPECT_RET(err != ERR_OK);
00301   }
00302   err = tcp_output(pcb);
00303   EXPECT_RET(err == ERR_OK);
00304   /*EXPECT_RET(txcounters.num_tx_calls == 0);
00305   EXPECT_RET(txcounters.num_tx_bytes == 0);*/
00306   memset(&txcounters, 0, sizeof(txcounters));
00307 
00308   /* send even more data */
00309   err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
00310   EXPECT_RET(err == ERR_OK);
00311   err = tcp_output(pcb);
00312   EXPECT_RET(err == ERR_OK);
00313   /* ...and even more data */
00314   err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
00315   EXPECT_RET(err == ERR_OK);
00316   err = tcp_output(pcb);
00317   EXPECT_RET(err == ERR_OK);
00318   /* ...and even more data */
00319   err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
00320   EXPECT_RET(err == ERR_OK);
00321   err = tcp_output(pcb);
00322   EXPECT_RET(err == ERR_OK);
00323   /* ...and even more data */
00324   err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
00325   EXPECT_RET(err == ERR_OK);
00326   err = tcp_output(pcb);
00327   EXPECT_RET(err == ERR_OK);
00328 
00329   /* send ACKs for data2 and data3 */
00330   p = tcp_create_rx_segment(pcb, NULL, 0, 0, 12, TCP_ACK);
00331   EXPECT_RET(p != NULL);
00332   test_tcp_input(p, &netif);
00333   /*EXPECT_RET(txcounters.num_tx_calls == 0);*/
00334 
00335   /* ...and even more data */
00336   err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
00337   EXPECT_RET(err == ERR_OK);
00338   err = tcp_output(pcb);
00339   EXPECT_RET(err == ERR_OK);
00340   /* ...and even more data */
00341   err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
00342   EXPECT_RET(err == ERR_OK);
00343   err = tcp_output(pcb);
00344   EXPECT_RET(err == ERR_OK);
00345 
00346 #if 0
00347   /* create expected segment */
00348   p1 = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0);
00349   EXPECT_RET(p != NULL);
00350   if (p != NULL) {
00351     /* pass the segment to tcp_input */
00352     test_tcp_input(p, &netif);
00353     /* check if counters are as expected */
00354     EXPECT_RET(counters.close_calls == 0);
00355     EXPECT_RET(counters.recv_calls == 1);
00356     EXPECT_RET(counters.recved_bytes == data_len);
00357     EXPECT_RET(counters.err_calls == 0);
00358   }
00359 #endif
00360   /* make sure the pcb is freed */
00361   EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
00362   tcp_abort(pcb);
00363   EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
00364 }
00365 END_TEST
00366 
00367 static u8_t tx_data[TCP_WND*2];
00368 
00369 static void
00370 check_seqnos(struct tcp_seg *segs, int num_expected, u32_t *seqnos_expected)
00371 {
00372   struct tcp_seg *s = segs;
00373   int i;
00374   for (i = 0; i < num_expected; i++, s = s->next) {
00375     EXPECT_RET(s != NULL);
00376     EXPECT(s->tcphdr->seqno == htonl(seqnos_expected[i]));
00377   }
00378   EXPECT(s == NULL);
00379 }
00380 
00381 /** Send data with sequence numbers that wrap around the u32_t range.
00382  * Then, provoke fast retransmission by duplicate ACKs and check that all
00383  * segment lists are still properly sorted. */
00384 START_TEST(test_tcp_fast_rexmit_wraparound)
00385 {
00386   struct netif netif;
00387   struct test_tcp_txcounters txcounters;
00388   struct test_tcp_counters counters;
00389   struct tcp_pcb* pcb;
00390   struct pbuf* p;
00391   ip_addr_t remote_ip, local_ip, netmask;
00392   u16_t remote_port = 0x100, local_port = 0x101;
00393   err_t err;
00394 #define SEQNO1 (0xFFFFFF00 - TCP_MSS)
00395 #define ISS    6510
00396   u16_t i, sent_total = 0;
00397   u32_t seqnos[] = {
00398     SEQNO1,
00399     SEQNO1 + (1 * TCP_MSS),
00400     SEQNO1 + (2 * TCP_MSS),
00401     SEQNO1 + (3 * TCP_MSS),
00402     SEQNO1 + (4 * TCP_MSS),
00403     SEQNO1 + (5 * TCP_MSS)};
00404   LWIP_UNUSED_ARG(_i);
00405 
00406   for (i = 0; i < sizeof(tx_data); i++) {
00407     tx_data[i] = (u8_t)i;
00408   }
00409 
00410   /* initialize local vars */
00411   IP_ADDR4(&local_ip,  192, 168,   1, 1);
00412   IP_ADDR4(&remote_ip, 192, 168,   1, 2);
00413   IP_ADDR4(&netmask,   255, 255, 255, 0);
00414   test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask);
00415   memset(&counters, 0, sizeof(counters));
00416 
00417   /* create and initialize the pcb */
00418   tcp_ticks = SEQNO1 - ISS;
00419   pcb = test_tcp_new_counters_pcb(&counters);
00420   EXPECT_RET(pcb != NULL);
00421   tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
00422   pcb->mss = TCP_MSS;
00423   /* disable initial congestion window (we don't send a SYN here...) */
00424   pcb->cwnd = 2*TCP_MSS;
00425   /* start in congestion advoidance */
00426   pcb->ssthresh = pcb->cwnd;
00427 
00428   /* send 6 mss-sized segments */
00429   for (i = 0; i < 6; i++) {
00430     err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
00431     EXPECT_RET(err == ERR_OK);
00432     sent_total += TCP_MSS;
00433   }
00434   check_seqnos(pcb->unsent, 6, seqnos);
00435   EXPECT(pcb->unacked == NULL);
00436   err = tcp_output(pcb);
00437   EXPECT(txcounters.num_tx_calls == 2);
00438   EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U));
00439   memset(&txcounters, 0, sizeof(txcounters));
00440 
00441   check_seqnos(pcb->unacked, 2, seqnos);
00442   check_seqnos(pcb->unsent, 4, &seqnos[2]);
00443 
00444   /* ACK the first segment */
00445   p = tcp_create_rx_segment(pcb, NULL, 0, 0, TCP_MSS, TCP_ACK);
00446   test_tcp_input(p, &netif);
00447   /* ensure this didn't trigger a retransmission. Only one
00448   segment should be transmitted because cwnd opened up by
00449   TCP_MSS and a fraction since we are in congestion avoidance */
00450   EXPECT(txcounters.num_tx_calls == 1);
00451   EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U);
00452   memset(&txcounters, 0, sizeof(txcounters));
00453   check_seqnos(pcb->unacked, 2, &seqnos[1]);
00454   check_seqnos(pcb->unsent, 3, &seqnos[3]);
00455 
00456   /* 3 dupacks */
00457   EXPECT(pcb->dupacks == 0);
00458   p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
00459   test_tcp_input(p, &netif);
00460   EXPECT(txcounters.num_tx_calls == 0);
00461   EXPECT(pcb->dupacks == 1);
00462   p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
00463   test_tcp_input(p, &netif);
00464   EXPECT(txcounters.num_tx_calls == 0);
00465   EXPECT(pcb->dupacks == 2);
00466   /* 3rd dupack -> fast rexmit */
00467   p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
00468   test_tcp_input(p, &netif);
00469   EXPECT(pcb->dupacks == 3);
00470   EXPECT(txcounters.num_tx_calls == 4);
00471   memset(&txcounters, 0, sizeof(txcounters));
00472   EXPECT(pcb->unsent == NULL);
00473   check_seqnos(pcb->unacked, 5, &seqnos[1]);
00474 
00475   /* make sure the pcb is freed */
00476   EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
00477   tcp_abort(pcb);
00478   EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
00479 }
00480 END_TEST
00481 
00482 /** Send data with sequence numbers that wrap around the u32_t range.
00483  * Then, provoke RTO retransmission and check that all
00484  * segment lists are still properly sorted. */
00485 START_TEST(test_tcp_rto_rexmit_wraparound)
00486 {
00487   struct netif netif;
00488   struct test_tcp_txcounters txcounters;
00489   struct test_tcp_counters counters;
00490   struct tcp_pcb* pcb;
00491   ip_addr_t remote_ip, local_ip, netmask;
00492   u16_t remote_port = 0x100, local_port = 0x101;
00493   err_t err;
00494 #define SEQNO1 (0xFFFFFF00 - TCP_MSS)
00495 #define ISS    6510
00496   u16_t i, sent_total = 0;
00497   u32_t seqnos[] = {
00498     SEQNO1,
00499     SEQNO1 + (1 * TCP_MSS),
00500     SEQNO1 + (2 * TCP_MSS),
00501     SEQNO1 + (3 * TCP_MSS),
00502     SEQNO1 + (4 * TCP_MSS),
00503     SEQNO1 + (5 * TCP_MSS)};
00504   LWIP_UNUSED_ARG(_i);
00505 
00506   for (i = 0; i < sizeof(tx_data); i++) {
00507     tx_data[i] = (u8_t)i;
00508   }
00509 
00510   /* initialize local vars */
00511   IP_ADDR4(&local_ip,  192, 168,   1, 1);
00512   IP_ADDR4(&remote_ip, 192, 168,   1, 2);
00513   IP_ADDR4(&netmask,   255, 255, 255, 0);
00514   test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask);
00515   memset(&counters, 0, sizeof(counters));
00516 
00517   /* create and initialize the pcb */
00518   tcp_ticks = 0;
00519   tcp_ticks = 0 - tcp_next_iss(NULL);
00520   tcp_ticks = SEQNO1 - tcp_next_iss(NULL);
00521   pcb = test_tcp_new_counters_pcb(&counters);
00522   EXPECT_RET(pcb != NULL);
00523   tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
00524   pcb->mss = TCP_MSS;
00525   /* disable initial congestion window (we don't send a SYN here...) */
00526   pcb->cwnd = 2*TCP_MSS;
00527 
00528   /* send 6 mss-sized segments */
00529   for (i = 0; i < 6; i++) {
00530     err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
00531     EXPECT_RET(err == ERR_OK);
00532     sent_total += TCP_MSS;
00533   }
00534   check_seqnos(pcb->unsent, 6, seqnos);
00535   EXPECT(pcb->unacked == NULL);
00536   err = tcp_output(pcb);
00537   EXPECT(txcounters.num_tx_calls == 2);
00538   EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U));
00539   memset(&txcounters, 0, sizeof(txcounters));
00540 
00541   check_seqnos(pcb->unacked, 2, seqnos);
00542   check_seqnos(pcb->unsent, 4, &seqnos[2]);
00543 
00544   /* call the tcp timer some times */
00545   for (i = 0; i < 10; i++) {
00546     test_tcp_tmr();
00547     EXPECT(txcounters.num_tx_calls == 0);
00548   }
00549   /* 11th call to tcp_tmr: RTO rexmit fires */
00550   test_tcp_tmr();
00551   EXPECT(txcounters.num_tx_calls == 1);
00552   check_seqnos(pcb->unacked, 1, seqnos);
00553   check_seqnos(pcb->unsent, 5, &seqnos[1]);
00554 
00555   /* fake greater cwnd */
00556   pcb->cwnd = pcb->snd_wnd;
00557   /* send more data */
00558   err = tcp_output(pcb);
00559   EXPECT(err == ERR_OK);
00560   /* check queues are sorted */
00561   EXPECT(pcb->unsent == NULL);
00562   check_seqnos(pcb->unacked, 6, seqnos);
00563 
00564   /* make sure the pcb is freed */
00565   EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
00566   tcp_abort(pcb);
00567   EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
00568 }
00569 END_TEST
00570 
00571 /** Provoke fast retransmission by duplicate ACKs and then recover by ACKing all sent data.
00572  * At the end, send more data. */
00573 static void test_tcp_tx_full_window_lost(u8_t zero_window_probe_from_unsent)
00574 {
00575   struct netif netif;
00576   struct test_tcp_txcounters txcounters;
00577   struct test_tcp_counters counters;
00578   struct tcp_pcb* pcb;
00579   struct pbuf *p;
00580   ip_addr_t remote_ip, local_ip, netmask;
00581   u16_t remote_port = 0x100, local_port = 0x101;
00582   err_t err;
00583   u16_t sent_total, i;
00584   u8_t expected = 0xFE;
00585 
00586   for (i = 0; i < sizeof(tx_data); i++) {
00587     u8_t d = (u8_t)i;
00588     if (d == 0xFE) {
00589       d = 0xF0;
00590     }
00591     tx_data[i] = d;
00592   }
00593   if (zero_window_probe_from_unsent) {
00594     tx_data[TCP_WND] = expected;
00595   } else {
00596     tx_data[0] = expected;
00597   }
00598 
00599   /* initialize local vars */
00600   IP_ADDR4(&local_ip,  192, 168,   1, 1);
00601   IP_ADDR4(&remote_ip, 192, 168,   1, 2);
00602   IP_ADDR4(&netmask,   255, 255, 255, 0);
00603   test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask);
00604   memset(&counters, 0, sizeof(counters));
00605   memset(&txcounters, 0, sizeof(txcounters));
00606 
00607   /* create and initialize the pcb */
00608   pcb = test_tcp_new_counters_pcb(&counters);
00609   EXPECT_RET(pcb != NULL);
00610   tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
00611   pcb->mss = TCP_MSS;
00612   /* disable initial congestion window (we don't send a SYN here...) */
00613   pcb->cwnd = pcb->snd_wnd;
00614 
00615   /* send a full window (minus 1 packets) of TCP data in MSS-sized chunks */
00616   sent_total = 0;
00617   if ((TCP_WND - TCP_MSS) % TCP_MSS != 0) {
00618     u16_t initial_data_len = (TCP_WND - TCP_MSS) % TCP_MSS;
00619     err = tcp_write(pcb, &tx_data[sent_total], initial_data_len, TCP_WRITE_FLAG_COPY);
00620     EXPECT_RET(err == ERR_OK);
00621     err = tcp_output(pcb);
00622     EXPECT_RET(err == ERR_OK);
00623     EXPECT(txcounters.num_tx_calls == 1);
00624     EXPECT(txcounters.num_tx_bytes == initial_data_len + 40U);
00625     memset(&txcounters, 0, sizeof(txcounters));
00626     sent_total += initial_data_len;
00627   }
00628   for (; sent_total < (TCP_WND - TCP_MSS); sent_total += TCP_MSS) {
00629     err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
00630     EXPECT_RET(err == ERR_OK);
00631     err = tcp_output(pcb);
00632     EXPECT_RET(err == ERR_OK);
00633     EXPECT(txcounters.num_tx_calls == 1);
00634     EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U);
00635     memset(&txcounters, 0, sizeof(txcounters));
00636   }
00637   EXPECT(sent_total == (TCP_WND - TCP_MSS));
00638 
00639   /* now ACK the packet before the first */
00640   p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
00641   test_tcp_input(p, &netif);
00642   /* ensure this didn't trigger a retransmission */
00643   EXPECT(txcounters.num_tx_calls == 0);
00644   EXPECT(txcounters.num_tx_bytes == 0);
00645 
00646   EXPECT(pcb->persist_backoff == 0);
00647   /* send the last packet, now a complete window has been sent */
00648   err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
00649   sent_total += TCP_MSS;
00650   EXPECT_RET(err == ERR_OK);
00651   err = tcp_output(pcb);
00652   EXPECT_RET(err == ERR_OK);
00653   EXPECT(txcounters.num_tx_calls == 1);
00654   EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U);
00655   memset(&txcounters, 0, sizeof(txcounters));
00656   EXPECT(pcb->persist_backoff == 0);
00657 
00658   if (zero_window_probe_from_unsent) {
00659     /* ACK all data but close the TX window */
00660     p = tcp_create_rx_segment_wnd(pcb, NULL, 0, 0, TCP_WND, TCP_ACK, 0);
00661     test_tcp_input(p, &netif);
00662     /* ensure this didn't trigger any transmission */
00663     EXPECT(txcounters.num_tx_calls == 0);
00664     EXPECT(txcounters.num_tx_bytes == 0);
00665     EXPECT(pcb->persist_backoff == 1);
00666   }
00667 
00668   /* send one byte more (out of window) -> persist timer starts */
00669   err = tcp_write(pcb, &tx_data[sent_total], 1, TCP_WRITE_FLAG_COPY);
00670   EXPECT_RET(err == ERR_OK);
00671   err = tcp_output(pcb);
00672   EXPECT_RET(err == ERR_OK);
00673   EXPECT(txcounters.num_tx_calls == 0);
00674   EXPECT(txcounters.num_tx_bytes == 0);
00675   memset(&txcounters, 0, sizeof(txcounters));
00676   if (!zero_window_probe_from_unsent) {
00677     /* no persist timer unless a zero window announcement has been received */
00678     EXPECT(pcb->persist_backoff == 0);
00679   } else {
00680     EXPECT(pcb->persist_backoff == 1);
00681 
00682     /* call tcp_timer some more times to let persist timer count up */
00683     for (i = 0; i < 4; i++) {
00684       test_tcp_tmr();
00685       EXPECT(txcounters.num_tx_calls == 0);
00686       EXPECT(txcounters.num_tx_bytes == 0);
00687     }
00688 
00689     /* this should trigger the zero-window-probe */
00690     txcounters.copy_tx_packets = 1;
00691     test_tcp_tmr();
00692     txcounters.copy_tx_packets = 0;
00693     EXPECT(txcounters.num_tx_calls == 1);
00694     EXPECT(txcounters.num_tx_bytes == 1 + 40U);
00695     EXPECT(txcounters.tx_packets != NULL);
00696     if (txcounters.tx_packets != NULL) {
00697       u8_t sent;
00698       u16_t ret;
00699       ret = pbuf_copy_partial(txcounters.tx_packets, &sent, 1, 40U);
00700       EXPECT(ret == 1);
00701       EXPECT(sent == expected);
00702     }
00703     if (txcounters.tx_packets != NULL) {
00704       pbuf_free(txcounters.tx_packets);
00705       txcounters.tx_packets = NULL;
00706     }
00707   }
00708 
00709   /* make sure the pcb is freed */
00710   EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
00711   tcp_abort(pcb);
00712   EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
00713 }
00714 
00715 START_TEST(test_tcp_tx_full_window_lost_from_unsent)
00716 {
00717   LWIP_UNUSED_ARG(_i);
00718   test_tcp_tx_full_window_lost(1);
00719 }
00720 END_TEST
00721 
00722 START_TEST(test_tcp_tx_full_window_lost_from_unacked)
00723 {
00724   LWIP_UNUSED_ARG(_i);
00725   test_tcp_tx_full_window_lost(0);
00726 }
00727 END_TEST
00728 
00729 /** Create the suite including all tests for this module */
00730 Suite *
00731 tcp_suite(void)
00732 {
00733   testfunc tests[] = {
00734     TESTFUNC(test_tcp_new_abort),
00735     TESTFUNC(test_tcp_recv_inseq),
00736     TESTFUNC(test_tcp_malformed_header),
00737     TESTFUNC(test_tcp_fast_retx_recover),
00738     TESTFUNC(test_tcp_fast_rexmit_wraparound),
00739     TESTFUNC(test_tcp_rto_rexmit_wraparound),
00740     TESTFUNC(test_tcp_tx_full_window_lost_from_unacked),
00741     TESTFUNC(test_tcp_tx_full_window_lost_from_unsent)
00742   };
00743   return create_suite("TCP", tests, sizeof(tests)/sizeof(testfunc), tcp_setup, tcp_teardown);
00744 }