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.
udpsocket_echotest_burst.cpp
00001 /* 00002 * Copyright (c) 2018, ARM Limited, All Rights Reserved 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00006 * not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include "mbed.h" 00019 #include "UDPSocket.h" 00020 #include "greentea-client/test_env.h" 00021 #include "unity/unity.h" 00022 #include "utest.h" 00023 #include "udp_tests.h" 00024 00025 using namespace utest::v1; 00026 00027 namespace { 00028 static const int SIGNAL_SIGIO = 0x1; 00029 static const int SIGIO_TIMEOUT = 5000; //[ms] 00030 static const int RECV_TIMEOUT = 1; //[s] 00031 00032 static const int BURST_CNT = 100; 00033 static const int BURST_PKTS = 5; 00034 static const int PKG_SIZES[BURST_PKTS] = {100, 200, 300, 120, 500}; 00035 static const int RECV_TOTAL = 1220; 00036 00037 static const double EXPECTED_LOSS_RATIO = 0.0; 00038 static const double TOLERATED_LOSS_RATIO = 0.3; 00039 00040 typedef struct pkg { 00041 int len; 00042 char *payload; 00043 } pkg_t; 00044 pkg_t tx_buffers[BURST_PKTS]; 00045 char rx_buffer[500] = {0}; 00046 } 00047 00048 void prepare_tx_buffers() 00049 { 00050 // TX buffers to be preserved for comparison 00051 for (int x = 0; x < BURST_PKTS; x++) { 00052 tx_buffers[x].len = PKG_SIZES[x]; 00053 tx_buffers[x].payload = (char *)(malloc(PKG_SIZES[x])); 00054 TEST_ASSERT_NOT_NULL(tx_buffers[x].payload); 00055 fill_tx_buffer_ascii(tx_buffers[x].payload, tx_buffers[x].len); 00056 } 00057 } 00058 00059 void free_tx_buffers() 00060 { 00061 for (int x = 0; x < BURST_PKTS; x++) { 00062 free(tx_buffers[x].payload); 00063 } 00064 } 00065 00066 static void _sigio_handler(osThreadId id) 00067 { 00068 osSignalSet(id, SIGNAL_SIGIO); 00069 } 00070 00071 void UDPSOCKET_ECHOTEST_BURST() 00072 { 00073 SocketAddress udp_addr; 00074 get_interface()->gethostbyname(MBED_CONF_APP_ECHO_SERVER_ADDR, &udp_addr); 00075 udp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT); 00076 00077 UDPSocket sock; 00078 const int TIMEOUT = 5000; // [ms] 00079 TEST_ASSERT_EQUAL(NSAPI_ERROR_OK , sock.open(get_interface())); 00080 sock.set_timeout(TIMEOUT); 00081 sock.sigio(callback(_sigio_handler, Thread::gettid())); 00082 00083 // TX buffers to be preserved for comparison 00084 prepare_tx_buffers(); 00085 00086 int bt_total = 0; 00087 int ok_bursts = 0; 00088 int pkg_fail = 0; 00089 int recvd = 0; 00090 int recv_timeout = RECV_TIMEOUT;; 00091 SocketAddress temp_addr; 00092 for (int i = 0; i < BURST_CNT; i++) { 00093 for (int x = 0; x < BURST_PKTS; x++) { 00094 TEST_ASSERT_EQUAL(tx_buffers[x].len, sock.sendto(udp_addr, tx_buffers[x].payload, tx_buffers[x].len)); 00095 } 00096 00097 bt_total = 0; 00098 recvd = 0; 00099 for (int j = 0; j < BURST_PKTS; j++) { 00100 recvd = sock.recvfrom(&temp_addr, rx_buffer, 500); 00101 if (recvd == NSAPI_ERROR_WOULD_BLOCK ) { 00102 if (osSignalWait(SIGNAL_SIGIO, SIGIO_TIMEOUT).status == osEventTimeout) { 00103 pkg_fail += BURST_PKTS - j; 00104 break; 00105 } 00106 } else if (recvd < 0) { 00107 pkg_fail += BURST_PKTS - j; // Assume all the following packets of the burst to be lost 00108 printf("[%02d] network error %d\n", i, recvd); 00109 wait(recv_timeout); 00110 recv_timeout *= 2; // Back off, 00111 break; 00112 } else if (temp_addr != udp_addr) { 00113 printf("[%02d] packet from wrong address\n", i); 00114 --j; 00115 continue; 00116 } 00117 00118 recv_timeout = recv_timeout > RECV_TIMEOUT ? recv_timeout / 2 : RECV_TIMEOUT; 00119 00120 // Packets might arrive unordered 00121 for (int k = 0; k < BURST_PKTS; k++) { 00122 if (tx_buffers[k].len == recvd && 00123 (memcmp(tx_buffers[k].payload, rx_buffer, recvd) == 0)) { 00124 bt_total += recvd; 00125 } 00126 } 00127 } 00128 00129 if (bt_total == RECV_TOTAL) { 00130 ok_bursts++; 00131 } else { 00132 drop_bad_packets(sock, TIMEOUT); 00133 printf("[%02d] burst failure\n", i); 00134 } 00135 } 00136 00137 free_tx_buffers(); 00138 00139 double loss_ratio = 1 - ((double)(BURST_CNT * BURST_PKTS - pkg_fail) / (double)(BURST_CNT * BURST_PKTS)); 00140 printf("Packets sent: %d, packets received %d, loss ratio %.2lf\r\n", 00141 BURST_CNT * BURST_PKTS, BURST_CNT * BURST_PKTS - pkg_fail, loss_ratio); 00142 // Packet loss up to 30% tolerated 00143 TEST_ASSERT_DOUBLE_WITHIN(TOLERATED_LOSS_RATIO, EXPECTED_LOSS_RATIO, loss_ratio); 00144 // 70% of the bursts need to be successful 00145 TEST_ASSERT_INT_WITHIN(3 * (BURST_CNT / 10), BURST_CNT, ok_bursts); 00146 00147 TEST_ASSERT_EQUAL(NSAPI_ERROR_OK , sock.close()); 00148 } 00149 00150 void UDPSOCKET_ECHOTEST_BURST_NONBLOCK() 00151 { 00152 SocketAddress udp_addr; 00153 get_interface()->gethostbyname(MBED_CONF_APP_ECHO_SERVER_ADDR, &udp_addr); 00154 udp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT); 00155 00156 UDPSocket sock; 00157 TEST_ASSERT_EQUAL(NSAPI_ERROR_OK , sock.open(get_interface())); 00158 sock.set_blocking(false); 00159 sock.sigio(callback(_sigio_handler, Thread::gettid())); 00160 00161 // TX buffers to be preserved for comparison 00162 prepare_tx_buffers(); 00163 00164 int ok_bursts = 0; 00165 int pkg_fail = 0; 00166 SocketAddress temp_addr; 00167 int recvd = 0; 00168 int bt_total = 0; 00169 for (int i = 0; i < BURST_CNT; i++) { 00170 for (int x = 0; x < BURST_PKTS; x++) { 00171 TEST_ASSERT_EQUAL(tx_buffers[x].len, sock.sendto(udp_addr, tx_buffers[x].payload, tx_buffers[x].len)); 00172 } 00173 00174 recvd = 0; 00175 bt_total = 0; 00176 for (int j = 0; j < BURST_PKTS; j++) { 00177 recvd = sock.recvfrom(&temp_addr, rx_buffer, 500); 00178 if (recvd == NSAPI_ERROR_WOULD_BLOCK ) { 00179 if (osSignalWait(SIGNAL_SIGIO, SIGIO_TIMEOUT).status == osEventTimeout) { 00180 pkg_fail += BURST_PKTS - j; 00181 break; 00182 } 00183 --j; 00184 continue; 00185 } else if (recvd < 0) { 00186 pkg_fail++; 00187 continue; 00188 } else if (temp_addr != udp_addr) { 00189 continue; 00190 } 00191 00192 // Packets might arrive unordered 00193 for (int k = 0; k < BURST_PKTS; k++) { 00194 if (tx_buffers[k].len == recvd && 00195 (memcmp(tx_buffers[k].payload, rx_buffer, recvd) == 0)) { 00196 bt_total += recvd; 00197 goto PKT_OK; 00198 } 00199 } 00200 printf("[bt#%02d] corrupted packet...", i); 00201 pkg_fail++; 00202 break; 00203 PKT_OK: 00204 continue; 00205 } 00206 00207 if (bt_total == RECV_TOTAL) { 00208 ok_bursts++; 00209 } else { 00210 drop_bad_packets(sock, -1); // timeout equivalent to set_blocking(false) 00211 sock.set_blocking(false); 00212 } 00213 } 00214 00215 free_tx_buffers(); 00216 00217 double loss_ratio = 1 - ((double)(BURST_CNT * BURST_PKTS - pkg_fail) / (double)(BURST_CNT * BURST_PKTS)); 00218 printf("Packets sent: %d, packets received %d, loss ratio %.2lf\r\n", 00219 BURST_CNT * BURST_PKTS, BURST_CNT * BURST_PKTS - pkg_fail, loss_ratio); 00220 // Packet loss up to 30% tolerated 00221 TEST_ASSERT_DOUBLE_WITHIN(TOLERATED_LOSS_RATIO, EXPECTED_LOSS_RATIO, loss_ratio); 00222 // 70% of the bursts need to be successful 00223 TEST_ASSERT_INT_WITHIN(3 * (BURST_CNT / 10), BURST_CNT, ok_bursts); 00224 00225 TEST_ASSERT_EQUAL(NSAPI_ERROR_OK , sock.close()); 00226 } 00227
Generated on Tue Aug 9 2022 00:37:24 by
1.7.2