SAMV71 Xplained Ultra Software Package 1.0

test_tcp.c

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