ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

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