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.
Fork of OmniWheels by
main.cpp
00001 /* 00002 * Copyright (c) 2013-2017, 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 #ifndef MBED_CONF_APP_CONNECT_STATEMENT 00019 #error [NOT_SUPPORTED] No network configuration found for this target. 00020 #endif 00021 00022 #ifndef MBED_EXTENDED_TESTS 00023 #error [NOT_SUPPORTED] Pressure tests are not supported by default 00024 #endif 00025 00026 #include "mbed.h" 00027 #include MBED_CONF_APP_HEADER_FILE 00028 #include "UDPSocket.h" 00029 #include "greentea-client/test_env.h" 00030 #include "unity/unity.h" 00031 #include "utest.h" 00032 00033 using namespace utest::v1; 00034 00035 00036 #ifndef MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN 00037 #define MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN 64 00038 #endif 00039 00040 #ifndef MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MAX 00041 #define MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MAX 0x80000 00042 #endif 00043 00044 #ifndef MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT 00045 #define MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT 100 00046 #endif 00047 00048 #ifndef MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_SEED 00049 #define MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 00050 #endif 00051 00052 #ifndef MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_DEBUG 00053 #define MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_DEBUG false 00054 #endif 00055 00056 #define STRINGIZE(x) STRINGIZE2(x) 00057 #define STRINGIZE2(x) #x 00058 00059 00060 // Simple xorshift pseudorandom number generator 00061 class RandSeq 00062 { 00063 private: 00064 uint32_t x; 00065 uint32_t y; 00066 static const int A = 15; 00067 static const int B = 18; 00068 static const int C = 11; 00069 00070 public: 00071 RandSeq(uint32_t seed = MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_SEED) 00072 : x(seed), y(seed) {} 00073 00074 uint32_t next(void) 00075 { 00076 x ^= x << A; 00077 x ^= x >> B; 00078 x ^= y ^ (y >> C); 00079 return x + y; 00080 } 00081 00082 void skip(size_t size) 00083 { 00084 for (size_t i = 0; i < size; i++) { 00085 next(); 00086 } 00087 } 00088 00089 void buffer(uint8_t *buffer, size_t size) 00090 { 00091 RandSeq lookahead = *this; 00092 00093 for (size_t i = 0; i < size; i++) { 00094 buffer[i] = lookahead.next() & 0xff; 00095 } 00096 } 00097 00098 int cmp(uint8_t *buffer, size_t size) 00099 { 00100 RandSeq lookahead = *this; 00101 00102 for (size_t i = 0; i < size; i++) { 00103 int diff = buffer[i] - (lookahead.next() & 0xff); 00104 if (diff != 0) { 00105 return diff; 00106 } 00107 } 00108 return 0; 00109 } 00110 }; 00111 00112 // Shared buffer for network transactions 00113 uint8_t *buffer; 00114 size_t buffer_size; 00115 00116 // Tries to get the biggest buffer possible on the device. Exponentially 00117 // grows a buffer until heap runs out of space, and uses half to leave 00118 // space for the rest of the program 00119 void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) 00120 { 00121 size_t i = min; 00122 while (i < max) { 00123 void *b = malloc(i); 00124 if (!b) { 00125 i /= 4; 00126 if (i < min) { 00127 i = min; 00128 } 00129 break; 00130 } 00131 free(b); 00132 i *= 2; 00133 } 00134 00135 *buffer = (uint8_t *)malloc(i); 00136 *size = i; 00137 TEST_ASSERT(buffer); 00138 } 00139 00140 void test_udp_packet_pressure() 00141 { 00142 generate_buffer(&buffer, &buffer_size, 00143 MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN, 00144 MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MAX); 00145 printf("MBED: Generated buffer %d\r\n", buffer_size); 00146 00147 NetworkInterface* net = MBED_CONF_APP_OBJECT_CONSTRUCTION; 00148 int err = MBED_CONF_APP_CONNECT_STATEMENT; 00149 TEST_ASSERT_EQUAL(0, err); 00150 00151 printf("MBED: UDPClient IP address is '%s'\n", net->get_ip_address()); 00152 00153 UDPSocket sock; 00154 #if defined(MBED_CONF_APP_ECHO_SERVER_ADDR) && defined(MBED_CONF_APP_ECHO_SERVER_PORT) 00155 SocketAddress udp_addr(MBED_CONF_APP_ECHO_SERVER_ADDR, MBED_CONF_APP_ECHO_SERVER_PORT); 00156 #else /* MBED_CONF_APP_ECHO_SERVER_ADDR && MBED_CONF_APP_ECHO_SERVER_PORT */ 00157 char recv_key[] = "host_port"; 00158 char ipbuf[60] = {0}; 00159 char portbuf[16] = {0}; 00160 unsigned int port = 0; 00161 00162 greentea_send_kv("target_ip", net->get_ip_address()); 00163 greentea_send_kv("host_ip", " "); 00164 greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf)); 00165 00166 greentea_send_kv("host_port", " "); 00167 greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf)); 00168 sscanf(portbuf, "%u", &port); 00169 00170 SocketAddress udp_addr(ipbuf, port); 00171 #endif /* MBED_CONF_APP_ECHO_SERVER_ADDR && MBED_CONF_APP_ECHO_SERVER_PORT */ 00172 00173 Timer timer; 00174 timer.start(); 00175 00176 // Tests exponentially growing sequences 00177 for (size_t size = MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN; 00178 size < MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MAX; 00179 size *= 2) { 00180 err = sock.open(net); 00181 TEST_ASSERT_EQUAL(0, err); 00182 printf("UDP: %s:%d streaming %d bytes\r\n", 00183 udp_addr.get_ip_address(), udp_addr.get_port(), size); 00184 00185 sock.set_blocking(false); 00186 00187 // Loop to send/recv all data 00188 RandSeq tx_seq; 00189 RandSeq rx_seq; 00190 size_t rx_count = 0; 00191 size_t tx_count = 0; 00192 int known_time = timer.read_ms(); 00193 size_t window = buffer_size; 00194 00195 while (tx_count < size || rx_count < size) { 00196 // Send out packets 00197 if (tx_count < size) { 00198 size_t chunk_size = size - tx_count; 00199 if (chunk_size > window) { 00200 chunk_size = window; 00201 } 00202 00203 tx_seq.buffer(buffer, chunk_size); 00204 int td = sock.sendto(udp_addr, buffer, chunk_size); 00205 00206 if (td > 0) { 00207 if (MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { 00208 printf("UDP: tx -> %d\r\n", td); 00209 } 00210 tx_seq.skip(td); 00211 tx_count += td; 00212 } else if (td != NSAPI_ERROR_WOULD_BLOCK ) { 00213 // We may fail to send because of buffering issues, revert to 00214 // last good sequence and cut buffer in half 00215 if (window > MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN) { 00216 window /= 2; 00217 } 00218 00219 if (MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { 00220 printf("UDP: Not sent (%d), window = %d\r\n", td, window); 00221 } 00222 } 00223 } 00224 00225 // Prioritize receiving over sending packets to avoid flooding 00226 // the network while handling erronous packets 00227 while (rx_count < size) { 00228 int rd = sock.recvfrom(NULL, buffer, buffer_size); 00229 TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK ); 00230 00231 if (rd > 0) { 00232 if (MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { 00233 printf("UDP: rx <- %d\r\n", rd); 00234 } 00235 00236 if (rx_seq.cmp(buffer, rd) == 0) { 00237 rx_seq.skip(rd); 00238 rx_count += rd; 00239 known_time = timer.read_ms(); 00240 if (window < MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MAX) { 00241 window += MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN; 00242 } 00243 } 00244 } else if (timer.read_ms() - known_time > 00245 MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT) { 00246 // Dropped packet or out of order, revert to last good sequence 00247 // and cut buffer in half 00248 tx_seq = rx_seq; 00249 tx_count = rx_count; 00250 known_time = timer.read_ms(); 00251 if (window > MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN) { 00252 window /= 2; 00253 } 00254 00255 if (MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { 00256 printf("UDP: Dropped, window = %d\r\n", window); 00257 } 00258 } else if (rd == NSAPI_ERROR_WOULD_BLOCK ) { 00259 break; 00260 } 00261 } 00262 } 00263 00264 err = sock.close(); 00265 TEST_ASSERT_EQUAL(0, err); 00266 } 00267 00268 timer.stop(); 00269 printf("MBED: Time taken: %fs\r\n", timer.read()); 00270 printf("MBED: Speed: %.3fkb/s\r\n", 00271 8 * (2 * MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MAX - 00272 MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN) / (1000 * timer.read())); 00273 00274 net->disconnect(); 00275 } 00276 00277 00278 // Test setup 00279 utest::v1::status_t test_setup(const size_t number_of_cases) 00280 { 00281 GREENTEA_SETUP(120, "udp_echo"); 00282 return verbose_test_setup_handler(number_of_cases); 00283 } 00284 00285 Case cases[] = { 00286 Case("UDP packet pressure", test_udp_packet_pressure), 00287 }; 00288 00289 Specification specification(test_setup, cases); 00290 00291 int main() 00292 { 00293 return !Harness::run(specification); 00294 }
Generated on Fri Jul 22 2022 04:53:56 by
1.7.2
