takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers udpsocket_echotest.cpp Source File

udpsocket_echotest.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 WAIT2RECV_TIMEOUT = 1000; //[ms]
00031 static const int RETRIES = 2;
00032 
00033 static const double EXPECTED_LOSS_RATIO = 0.0;
00034 static const double TOLERATED_LOSS_RATIO = 0.3;
00035 
00036 UDPSocket sock;
00037 Semaphore tx_sem(0, 1);
00038 
00039 static const int BUFF_SIZE = 1200;
00040 char rx_buffer[BUFF_SIZE] = {0};
00041 char tx_buffer[BUFF_SIZE] = {0};
00042 
00043 static const int PKTS = 22;
00044 static const int pkt_sizes[PKTS] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, \
00045                                     100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, \
00046                                     1100, 1200
00047                                    };
00048 }
00049 
00050 static void _sigio_handler(osThreadId id)
00051 {
00052     osSignalSet(id, SIGNAL_SIGIO);
00053 }
00054 
00055 void UDPSOCKET_ECHOTEST()
00056 {
00057     SocketAddress udp_addr;
00058     get_interface()->gethostbyname(MBED_CONF_APP_ECHO_SERVER_ADDR, &udp_addr);
00059     udp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT);
00060 
00061     UDPSocket sock;
00062     TEST_ASSERT_EQUAL(NSAPI_ERROR_OK , sock.open(get_interface()));
00063 
00064     int recvd;
00065     int sent;
00066     int s_idx = 0;
00067     int packets_sent = 0;
00068     int packets_recv = 0;
00069     for (int pkt_s = pkt_sizes[s_idx]; s_idx < PKTS; pkt_s = ++s_idx) {
00070         pkt_s = pkt_sizes[s_idx];
00071 
00072         fill_tx_buffer_ascii(tx_buffer, BUFF_SIZE);
00073 
00074         for (int retry_cnt = 0; retry_cnt <= 2; retry_cnt++) {
00075             memset(rx_buffer, 0, BUFF_SIZE);
00076             sent = sock.sendto(udp_addr, tx_buffer, pkt_s);
00077             if (sent > 0) {
00078                 packets_sent++;
00079             }
00080             if (sent != pkt_s) {
00081                 printf("[Round#%02d - Sender] error, returned %d\n", s_idx, sent);
00082                 continue;
00083             }
00084             recvd = sock.recvfrom(NULL, rx_buffer, pkt_s);
00085             if (recvd == pkt_s) {
00086                 break;
00087             }
00088         }
00089         if (memcmp(tx_buffer, rx_buffer, pkt_s) == 0) {
00090             packets_recv++;
00091         }
00092     }
00093     // Packet loss up to 30% tolerated
00094     if (packets_sent > 0) {
00095         double loss_ratio = 1 - ((double)packets_recv / (double)packets_sent);
00096         printf("Packets sent: %d, packets received %d, loss ratio %.2lf\r\n", packets_sent, packets_recv, loss_ratio);
00097         TEST_ASSERT_DOUBLE_WITHIN(TOLERATED_LOSS_RATIO, EXPECTED_LOSS_RATIO, loss_ratio);
00098     }
00099     TEST_ASSERT_EQUAL(NSAPI_ERROR_OK , sock.close());
00100 }
00101 
00102 void udpsocket_echotest_nonblock_receiver(void *receive_bytes)
00103 {
00104     int expt2recv = *(int *)receive_bytes;
00105     int recvd;
00106     for (int retry_cnt = 0; retry_cnt <= RETRIES; retry_cnt++) {
00107         recvd = sock.recvfrom(NULL, rx_buffer, expt2recv);
00108         if (recvd == NSAPI_ERROR_WOULD_BLOCK ) {
00109             wait_ms(WAIT2RECV_TIMEOUT);
00110             --retry_cnt;
00111             continue;
00112         } else if (recvd == expt2recv) {
00113             break;
00114         }
00115     }
00116 
00117     drop_bad_packets(sock, -1); // timeout equivalent to set_blocking(false)
00118 
00119     tx_sem.release();
00120 }
00121 
00122 void UDPSOCKET_ECHOTEST_NONBLOCK()
00123 {
00124     SocketAddress udp_addr;
00125     get_interface()->gethostbyname(MBED_CONF_APP_ECHO_SERVER_ADDR, &udp_addr);
00126     udp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT);
00127 
00128     TEST_ASSERT_EQUAL(NSAPI_ERROR_OK , sock.open(get_interface()));
00129     sock.set_blocking(false);
00130     sock.sigio(callback(_sigio_handler, Thread::gettid()));
00131 
00132     int sent;
00133     int s_idx = 0;
00134     int packets_sent = 0;
00135     int packets_recv = 0;
00136     Thread *thread;
00137     unsigned char *stack_mem = (unsigned char *)malloc(OS_STACK_SIZE);
00138     TEST_ASSERT_NOT_NULL(stack_mem);
00139 
00140     for (int pkt_s = pkt_sizes[s_idx]; s_idx < PKTS; ++s_idx) {
00141         pkt_s = pkt_sizes[s_idx];
00142 
00143         thread = new Thread(osPriorityNormal,
00144                             OS_STACK_SIZE,
00145                             stack_mem,
00146                             "receiver");
00147         TEST_ASSERT_EQUAL(osOK, thread->start(callback(udpsocket_echotest_nonblock_receiver, &pkt_s)));
00148 
00149         for (int retry_cnt = 0; retry_cnt <= RETRIES; retry_cnt++) {
00150             fill_tx_buffer_ascii(tx_buffer, pkt_s);
00151 
00152             sent = sock.sendto(udp_addr, tx_buffer, pkt_s);
00153             if (sent > 0) {
00154                 packets_sent++;
00155             }
00156             if (sent == NSAPI_ERROR_WOULD_BLOCK ) {
00157                 if (osSignalWait(SIGNAL_SIGIO, SIGIO_TIMEOUT).status == osEventTimeout) {
00158                     continue;
00159                 }
00160                 --retry_cnt;
00161             } else if (sent != pkt_s) {
00162                 printf("[Round#%02d - Sender] error, returned %d\n", s_idx, sent);
00163                 continue;
00164             }
00165             if (tx_sem.wait(WAIT2RECV_TIMEOUT * 2) == 0) { // RX might wait up to WAIT2RECV_TIMEOUT before recvfrom
00166                 continue;
00167             }
00168             break;
00169         }
00170         thread->join();
00171         delete thread;
00172         if (memcmp(tx_buffer, rx_buffer, pkt_s) == 0) {
00173             packets_recv++;
00174         }
00175     }
00176     free(stack_mem);
00177     // Packet loss up to 30% tolerated
00178     if (packets_sent > 0) {
00179         double loss_ratio = 1 - ((double)packets_recv / (double)packets_sent);
00180         printf("Packets sent: %d, packets received %d, loss ratio %.2lf\r\n", packets_sent, packets_recv, loss_ratio);
00181         TEST_ASSERT_DOUBLE_WITHIN(TOLERATED_LOSS_RATIO, EXPECTED_LOSS_RATIO, loss_ratio);
00182     }
00183     TEST_ASSERT_EQUAL(NSAPI_ERROR_OK , sock.close());
00184 }