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