Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more
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 }
Generated on Tue Jul 12 2022 11:02:33 by
1.7.2