Daiki Kato / mbed-os-lychee

Dependents:   mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more

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   tcp_remove_all();
00050   netif_list = NULL;
00051   netif_default = NULL;
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 
00426   /* send 6 mss-sized segments */
00427   for (i = 0; i < 6; i++) {
00428     err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
00429     EXPECT_RET(err == ERR_OK);
00430     sent_total += TCP_MSS;
00431   }
00432   check_seqnos(pcb->unsent, 6, seqnos);
00433   EXPECT(pcb->unacked == NULL);
00434   err = tcp_output(pcb);
00435   EXPECT(txcounters.num_tx_calls == 2);
00436   EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U));
00437   memset(&txcounters, 0, sizeof(txcounters));
00438 
00439   check_seqnos(pcb->unacked, 2, seqnos);
00440   check_seqnos(pcb->unsent, 4, &seqnos[2]);
00441 
00442   /* ACK the first segment */
00443   p = tcp_create_rx_segment(pcb, NULL, 0, 0, TCP_MSS, TCP_ACK);
00444   test_tcp_input(p, &netif);
00445   /* ensure this didn't trigger a retransmission */
00446   EXPECT(txcounters.num_tx_calls == 1);
00447   EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U);
00448   memset(&txcounters, 0, sizeof(txcounters));
00449   check_seqnos(pcb->unacked, 2, &seqnos[1]);
00450   check_seqnos(pcb->unsent, 3, &seqnos[3]);
00451 
00452   /* 3 dupacks */
00453   EXPECT(pcb->dupacks == 0);
00454   p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
00455   test_tcp_input(p, &netif);
00456   EXPECT(txcounters.num_tx_calls == 0);
00457   EXPECT(pcb->dupacks == 1);
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 == 2);
00462   /* 3rd dupack -> fast rexmit */
00463   p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
00464   test_tcp_input(p, &netif);
00465   EXPECT(pcb->dupacks == 3);
00466   EXPECT(txcounters.num_tx_calls == 4);
00467   memset(&txcounters, 0, sizeof(txcounters));
00468   EXPECT(pcb->unsent == NULL);
00469   check_seqnos(pcb->unacked, 5, &seqnos[1]);
00470 
00471   /* make sure the pcb is freed */
00472   EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
00473   tcp_abort(pcb);
00474   EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
00475 }
00476 END_TEST
00477 
00478 /** Send data with sequence numbers that wrap around the u32_t range.
00479  * Then, provoke RTO retransmission and check that all
00480  * segment lists are still properly sorted. */
00481 START_TEST(test_tcp_rto_rexmit_wraparound)
00482 {
00483   struct netif netif;
00484   struct test_tcp_txcounters txcounters;
00485   struct test_tcp_counters counters;
00486   struct tcp_pcb* pcb;
00487   ip_addr_t remote_ip, local_ip, netmask;
00488   u16_t remote_port = 0x100, local_port = 0x101;
00489   err_t err;
00490 #define SEQNO1 (0xFFFFFF00 - TCP_MSS)
00491 #define ISS    6510
00492   u16_t i, sent_total = 0;
00493   u32_t seqnos[] = {
00494     SEQNO1,
00495     SEQNO1 + (1 * TCP_MSS),
00496     SEQNO1 + (2 * TCP_MSS),
00497     SEQNO1 + (3 * TCP_MSS),
00498     SEQNO1 + (4 * TCP_MSS),
00499     SEQNO1 + (5 * TCP_MSS)};
00500   LWIP_UNUSED_ARG(_i);
00501 
00502   for (i = 0; i < sizeof(tx_data); i++) {
00503     tx_data[i] = (u8_t)i;
00504   }
00505 
00506   /* initialize local vars */
00507   IP_ADDR4(&local_ip,  192, 168,   1, 1);
00508   IP_ADDR4(&remote_ip, 192, 168,   1, 2);
00509   IP_ADDR4(&netmask,   255, 255, 255, 0);
00510   test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask);
00511   memset(&counters, 0, sizeof(counters));
00512 
00513   /* create and initialize the pcb */
00514   tcp_ticks = 0;
00515   tcp_ticks = 0 - tcp_next_iss(NULL);
00516   tcp_ticks = SEQNO1 - tcp_next_iss(NULL);
00517   pcb = test_tcp_new_counters_pcb(&counters);
00518   EXPECT_RET(pcb != NULL);
00519   tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
00520   pcb->mss = TCP_MSS;
00521   /* disable initial congestion window (we don't send a SYN here...) */
00522   pcb->cwnd = 2*TCP_MSS;
00523 
00524   /* send 6 mss-sized segments */
00525   for (i = 0; i < 6; i++) {
00526     err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
00527     EXPECT_RET(err == ERR_OK);
00528     sent_total += TCP_MSS;
00529   }
00530   check_seqnos(pcb->unsent, 6, seqnos);
00531   EXPECT(pcb->unacked == NULL);
00532   err = tcp_output(pcb);
00533   EXPECT(txcounters.num_tx_calls == 2);
00534   EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U));
00535   memset(&txcounters, 0, sizeof(txcounters));
00536 
00537   check_seqnos(pcb->unacked, 2, seqnos);
00538   check_seqnos(pcb->unsent, 4, &seqnos[2]);
00539 
00540   /* call the tcp timer some times */
00541   for (i = 0; i < 10; i++) {
00542     test_tcp_tmr();
00543     EXPECT(txcounters.num_tx_calls == 0);
00544   }
00545   /* 11th call to tcp_tmr: RTO rexmit fires */
00546   test_tcp_tmr();
00547   EXPECT(txcounters.num_tx_calls == 1);
00548   check_seqnos(pcb->unacked, 1, seqnos);
00549   check_seqnos(pcb->unsent, 5, &seqnos[1]);
00550 
00551   /* fake greater cwnd */
00552   pcb->cwnd = pcb->snd_wnd;
00553   /* send more data */
00554   err = tcp_output(pcb);
00555   EXPECT(err == ERR_OK);
00556   /* check queues are sorted */
00557   EXPECT(pcb->unsent == NULL);
00558   check_seqnos(pcb->unacked, 6, seqnos);
00559 
00560   /* make sure the pcb is freed */
00561   EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
00562   tcp_abort(pcb);
00563   EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
00564 }
00565 END_TEST
00566 
00567 /** Provoke fast retransmission by duplicate ACKs and then recover by ACKing all sent data.
00568  * At the end, send more data. */
00569 static void test_tcp_tx_full_window_lost(u8_t zero_window_probe_from_unsent)
00570 {
00571   struct netif netif;
00572   struct test_tcp_txcounters txcounters;
00573   struct test_tcp_counters counters;
00574   struct tcp_pcb* pcb;
00575   struct pbuf *p;
00576   ip_addr_t remote_ip, local_ip, netmask;
00577   u16_t remote_port = 0x100, local_port = 0x101;
00578   err_t err;
00579   u16_t sent_total, i;
00580   u8_t expected = 0xFE;
00581 
00582   for (i = 0; i < sizeof(tx_data); i++) {
00583     u8_t d = (u8_t)i;
00584     if (d == 0xFE) {
00585       d = 0xF0;
00586     }
00587     tx_data[i] = d;
00588   }
00589   if (zero_window_probe_from_unsent) {
00590     tx_data[TCP_WND] = expected;
00591   } else {
00592     tx_data[0] = expected;
00593   }
00594 
00595   /* initialize local vars */
00596   IP_ADDR4(&local_ip,  192, 168,   1, 1);
00597   IP_ADDR4(&remote_ip, 192, 168,   1, 2);
00598   IP_ADDR4(&netmask,   255, 255, 255, 0);
00599   test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask);
00600   memset(&counters, 0, sizeof(counters));
00601   memset(&txcounters, 0, sizeof(txcounters));
00602 
00603   /* create and initialize the pcb */
00604   pcb = test_tcp_new_counters_pcb(&counters);
00605   EXPECT_RET(pcb != NULL);
00606   tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
00607   pcb->mss = TCP_MSS;
00608   /* disable initial congestion window (we don't send a SYN here...) */
00609   pcb->cwnd = pcb->snd_wnd;
00610 
00611   /* send a full window (minus 1 packets) of TCP data in MSS-sized chunks */
00612   sent_total = 0;
00613   if ((TCP_WND - TCP_MSS) % TCP_MSS != 0) {
00614     u16_t initial_data_len = (TCP_WND - TCP_MSS) % TCP_MSS;
00615     err = tcp_write(pcb, &tx_data[sent_total], initial_data_len, TCP_WRITE_FLAG_COPY);
00616     EXPECT_RET(err == ERR_OK);
00617     err = tcp_output(pcb);
00618     EXPECT_RET(err == ERR_OK);
00619     EXPECT(txcounters.num_tx_calls == 1);
00620     EXPECT(txcounters.num_tx_bytes == initial_data_len + 40U);
00621     memset(&txcounters, 0, sizeof(txcounters));
00622     sent_total += initial_data_len;
00623   }
00624   for (; sent_total < (TCP_WND - TCP_MSS); sent_total += TCP_MSS) {
00625     err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
00626     EXPECT_RET(err == ERR_OK);
00627     err = tcp_output(pcb);
00628     EXPECT_RET(err == ERR_OK);
00629     EXPECT(txcounters.num_tx_calls == 1);
00630     EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U);
00631     memset(&txcounters, 0, sizeof(txcounters));
00632   }
00633   EXPECT(sent_total == (TCP_WND - TCP_MSS));
00634 
00635   /* now ACK the packet before the first */
00636   p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
00637   test_tcp_input(p, &netif);
00638   /* ensure this didn't trigger a retransmission */
00639   EXPECT(txcounters.num_tx_calls == 0);
00640   EXPECT(txcounters.num_tx_bytes == 0);
00641 
00642   EXPECT(pcb->persist_backoff == 0);
00643   /* send the last packet, now a complete window has been sent */
00644   err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
00645   sent_total += TCP_MSS;
00646   EXPECT_RET(err == ERR_OK);
00647   err = tcp_output(pcb);
00648   EXPECT_RET(err == ERR_OK);
00649   EXPECT(txcounters.num_tx_calls == 1);
00650   EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U);
00651   memset(&txcounters, 0, sizeof(txcounters));
00652   EXPECT(pcb->persist_backoff == 0);
00653 
00654   if (zero_window_probe_from_unsent) {
00655     /* ACK all data but close the TX window */
00656     p = tcp_create_rx_segment_wnd(pcb, NULL, 0, 0, TCP_WND, TCP_ACK, 0);
00657     test_tcp_input(p, &netif);
00658     /* ensure this didn't trigger any transmission */
00659     EXPECT(txcounters.num_tx_calls == 0);
00660     EXPECT(txcounters.num_tx_bytes == 0);
00661     EXPECT(pcb->persist_backoff == 1);
00662   }
00663 
00664   /* send one byte more (out of window) -> persist timer starts */
00665   err = tcp_write(pcb, &tx_data[sent_total], 1, TCP_WRITE_FLAG_COPY);
00666   EXPECT_RET(err == ERR_OK);
00667   err = tcp_output(pcb);
00668   EXPECT_RET(err == ERR_OK);
00669   EXPECT(txcounters.num_tx_calls == 0);
00670   EXPECT(txcounters.num_tx_bytes == 0);
00671   memset(&txcounters, 0, sizeof(txcounters));
00672   if (!zero_window_probe_from_unsent) {
00673     /* no persist timer unless a zero window announcement has been received */
00674     EXPECT(pcb->persist_backoff == 0);
00675   } else {
00676     EXPECT(pcb->persist_backoff == 1);
00677 
00678     /* call tcp_timer some more times to let persist timer count up */
00679     for (i = 0; i < 4; i++) {
00680       test_tcp_tmr();
00681       EXPECT(txcounters.num_tx_calls == 0);
00682       EXPECT(txcounters.num_tx_bytes == 0);
00683     }
00684 
00685     /* this should trigger the zero-window-probe */
00686     txcounters.copy_tx_packets = 1;
00687     test_tcp_tmr();
00688     txcounters.copy_tx_packets = 0;
00689     EXPECT(txcounters.num_tx_calls == 1);
00690     EXPECT(txcounters.num_tx_bytes == 1 + 40U);
00691     EXPECT(txcounters.tx_packets != NULL);
00692     if (txcounters.tx_packets != NULL) {
00693       u8_t sent;
00694       u16_t ret;
00695       ret = pbuf_copy_partial(txcounters.tx_packets, &sent, 1, 40U);
00696       EXPECT(ret == 1);
00697       EXPECT(sent == expected);
00698     }
00699     if (txcounters.tx_packets != NULL) {
00700       pbuf_free(txcounters.tx_packets);
00701       txcounters.tx_packets = NULL;
00702     }
00703   }
00704 
00705   /* make sure the pcb is freed */
00706   EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
00707   tcp_abort(pcb);
00708   EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
00709 }
00710 
00711 START_TEST(test_tcp_tx_full_window_lost_from_unsent)
00712 {
00713   LWIP_UNUSED_ARG(_i);
00714   test_tcp_tx_full_window_lost(1);
00715 }
00716 END_TEST
00717 
00718 START_TEST(test_tcp_tx_full_window_lost_from_unacked)
00719 {
00720   LWIP_UNUSED_ARG(_i);
00721   test_tcp_tx_full_window_lost(0);
00722 }
00723 END_TEST
00724 
00725 /** Create the suite including all tests for this module */
00726 Suite *
00727 tcp_suite(void)
00728 {
00729   testfunc tests[] = {
00730     TESTFUNC(test_tcp_new_abort),
00731     TESTFUNC(test_tcp_recv_inseq),
00732     TESTFUNC(test_tcp_malformed_header),
00733     TESTFUNC(test_tcp_fast_retx_recover),
00734     TESTFUNC(test_tcp_fast_rexmit_wraparound),
00735     TESTFUNC(test_tcp_rto_rexmit_wraparound),
00736     TESTFUNC(test_tcp_tx_full_window_lost_from_unacked),
00737     TESTFUNC(test_tcp_tx_full_window_lost_from_unsent)
00738   };
00739   return create_suite("TCP", tests, sizeof(tests)/sizeof(testfunc), tcp_setup, tcp_teardown);
00740 }