takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers udpsocket_echotest_burst.cpp Source File

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