1195972f6Sopenharmony_ci/** 2195972f6Sopenharmony_ci * @file 3195972f6Sopenharmony_ci * Sockets stresstest 4195972f6Sopenharmony_ci * 5195972f6Sopenharmony_ci * This file uses the lwIP socket API to do stress tests that should test the 6195972f6Sopenharmony_ci * stability when used in many different situations, with many concurrent 7195972f6Sopenharmony_ci * sockets making concurrent transfers in different manners. 8195972f6Sopenharmony_ci * 9195972f6Sopenharmony_ci * - test rely on loopback sockets for now, so netif drivers are not tested 10195972f6Sopenharmony_ci * - all enabled functions shall be used 11195972f6Sopenharmony_ci * - parallelism of the tests depend on enough resources being available 12195972f6Sopenharmony_ci * (configure your lwipopts.h settings high enough) 13195972f6Sopenharmony_ci * - test should also be able to run in a real target 14195972f6Sopenharmony_ci * 15195972f6Sopenharmony_ci * TODO: 16195972f6Sopenharmony_ci * - full duplex 17195972f6Sopenharmony_ci * - add asserts about internal socket/netconn/pcb state? 18195972f6Sopenharmony_ci */ 19195972f6Sopenharmony_ci 20195972f6Sopenharmony_ci /* 21195972f6Sopenharmony_ci * Copyright (c) 2017 Simon Goldschmidt 22195972f6Sopenharmony_ci * All rights reserved. 23195972f6Sopenharmony_ci * 24195972f6Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, 25195972f6Sopenharmony_ci * are permitted provided that the following conditions are met: 26195972f6Sopenharmony_ci * 27195972f6Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, 28195972f6Sopenharmony_ci * this list of conditions and the following disclaimer. 29195972f6Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, 30195972f6Sopenharmony_ci * this list of conditions and the following disclaimer in the documentation 31195972f6Sopenharmony_ci * and/or other materials provided with the distribution. 32195972f6Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote products 33195972f6Sopenharmony_ci * derived from this software without specific prior written permission. 34195972f6Sopenharmony_ci * 35195972f6Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 36195972f6Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 37195972f6Sopenharmony_ci * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 38195972f6Sopenharmony_ci * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 39195972f6Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 40195972f6Sopenharmony_ci * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 41195972f6Sopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 42195972f6Sopenharmony_ci * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 43195972f6Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 44195972f6Sopenharmony_ci * OF SUCH DAMAGE. 45195972f6Sopenharmony_ci * 46195972f6Sopenharmony_ci * This file is part of the lwIP TCP/IP stack. 47195972f6Sopenharmony_ci * 48195972f6Sopenharmony_ci * Author: Simon Goldschmidt <goldsimon@gmx.de> 49195972f6Sopenharmony_ci * 50195972f6Sopenharmony_ci */ 51195972f6Sopenharmony_ci 52195972f6Sopenharmony_ci#include "lwip/opt.h" 53195972f6Sopenharmony_ci#include "sockets_stresstest.h" 54195972f6Sopenharmony_ci 55195972f6Sopenharmony_ci#include "lwip/sockets.h" 56195972f6Sopenharmony_ci#include "lwip/sys.h" 57195972f6Sopenharmony_ci 58195972f6Sopenharmony_ci#include "lwip/mem.h" 59195972f6Sopenharmony_ci 60195972f6Sopenharmony_ci#include <stdio.h> 61195972f6Sopenharmony_ci#include <string.h> 62195972f6Sopenharmony_ci 63195972f6Sopenharmony_ci#if LWIP_SOCKET && LWIP_IPV4 /* this uses IPv4 loopback sockets, currently */ 64195972f6Sopenharmony_ci 65195972f6Sopenharmony_ci#ifndef TEST_SOCKETS_STRESS 66195972f6Sopenharmony_ci#define TEST_SOCKETS_STRESS LWIP_DBG_OFF 67195972f6Sopenharmony_ci#endif 68195972f6Sopenharmony_ci 69195972f6Sopenharmony_ci#define TEST_TIME_SECONDS 10 70195972f6Sopenharmony_ci#define TEST_TXRX_BUFSIZE (TCP_MSS * 2) 71195972f6Sopenharmony_ci#define TEST_MAX_RXWAIT_MS 50 72195972f6Sopenharmony_ci#define TEST_MAX_CONNECTIONS 50 73195972f6Sopenharmony_ci 74195972f6Sopenharmony_ci#define TEST_SOCK_READABLE 0x01 75195972f6Sopenharmony_ci#define TEST_SOCK_WRITABLE 0x02 76195972f6Sopenharmony_ci#define TEST_SOCK_ERR 0x04 77195972f6Sopenharmony_ci 78195972f6Sopenharmony_ci#define TEST_MODE_SELECT 0x01 79195972f6Sopenharmony_ci#define TEST_MODE_POLL 0x02 80195972f6Sopenharmony_ci#define TEST_MODE_NONBLOCKING 0x04 81195972f6Sopenharmony_ci#define TEST_MODE_WAIT 0x08 82195972f6Sopenharmony_ci#define TEST_MODE_RECVTIMEO 0x10 83195972f6Sopenharmony_ci#define TEST_MODE_SLEEP 0x20 84195972f6Sopenharmony_ci 85195972f6Sopenharmony_cistatic int sockets_stresstest_numthreads; 86195972f6Sopenharmony_ci 87195972f6Sopenharmony_cistruct test_settings { 88195972f6Sopenharmony_ci struct sockaddr_storage addr; 89195972f6Sopenharmony_ci int start_client; 90195972f6Sopenharmony_ci int loop_cnt; 91195972f6Sopenharmony_ci}; 92195972f6Sopenharmony_ci 93195972f6Sopenharmony_cistruct sockets_stresstest_fullduplex { 94195972f6Sopenharmony_ci int s; 95195972f6Sopenharmony_ci volatile int closed; 96195972f6Sopenharmony_ci}; 97195972f6Sopenharmony_ci 98195972f6Sopenharmony_cistatic void 99195972f6Sopenharmony_cifill_test_data(void *buf, size_t buf_len_bytes) 100195972f6Sopenharmony_ci{ 101195972f6Sopenharmony_ci u8_t *p = (u8_t*)buf; 102195972f6Sopenharmony_ci u16_t i, chk; 103195972f6Sopenharmony_ci 104195972f6Sopenharmony_ci LWIP_ASSERT("buffer too short", buf_len_bytes >= 4); 105195972f6Sopenharmony_ci LWIP_ASSERT("buffer too big", buf_len_bytes <= 0xFFFF); 106195972f6Sopenharmony_ci /* store the total number of bytes */ 107195972f6Sopenharmony_ci p[0] = (u8_t)(buf_len_bytes >> 8); 108195972f6Sopenharmony_ci p[1] = (u8_t)buf_len_bytes; 109195972f6Sopenharmony_ci 110195972f6Sopenharmony_ci /* fill buffer with random */ 111195972f6Sopenharmony_ci chk = 0; 112195972f6Sopenharmony_ci for (i = 4; i < buf_len_bytes; i++) { 113195972f6Sopenharmony_ci u8_t rnd = (u8_t)LWIP_RAND(); 114195972f6Sopenharmony_ci p[i] = rnd; 115195972f6Sopenharmony_ci chk += rnd; 116195972f6Sopenharmony_ci } 117195972f6Sopenharmony_ci /* store checksum */ 118195972f6Sopenharmony_ci p[2] = (u8_t)(chk >> 8); 119195972f6Sopenharmony_ci p[3] = (u8_t)chk; 120195972f6Sopenharmony_ci} 121195972f6Sopenharmony_ci 122195972f6Sopenharmony_cistatic size_t 123195972f6Sopenharmony_cicheck_test_data(const void *buf, size_t buf_len_bytes) 124195972f6Sopenharmony_ci{ 125195972f6Sopenharmony_ci u8_t *p = (u8_t*)buf; 126195972f6Sopenharmony_ci u16_t i, chk, chk_rx, len_rx; 127195972f6Sopenharmony_ci 128195972f6Sopenharmony_ci LWIP_ASSERT("buffer too short", buf_len_bytes >= 4); 129195972f6Sopenharmony_ci len_rx = (((u16_t)p[0]) << 8) | p[1]; 130195972f6Sopenharmony_ci LWIP_ASSERT("len too short", len_rx >= 4); 131195972f6Sopenharmony_ci if (len_rx > buf_len_bytes) { 132195972f6Sopenharmony_ci /* not all data received in this segment */ 133195972f6Sopenharmony_ci LWIP_DEBUGF(TEST_SOCKETS_STRESS | LWIP_DBG_TRACE, ("check-\n")); 134195972f6Sopenharmony_ci return buf_len_bytes; 135195972f6Sopenharmony_ci } 136195972f6Sopenharmony_ci chk_rx = (((u16_t)p[2]) << 8) | p[3]; 137195972f6Sopenharmony_ci /* calculate received checksum */ 138195972f6Sopenharmony_ci chk = 0; 139195972f6Sopenharmony_ci for (i = 4; i < len_rx; i++) { 140195972f6Sopenharmony_ci chk += p[i]; 141195972f6Sopenharmony_ci } 142195972f6Sopenharmony_ci LWIP_ASSERT("invalid checksum", chk == chk_rx); 143195972f6Sopenharmony_ci if (len_rx < buf_len_bytes) { 144195972f6Sopenharmony_ci size_t data_left = buf_len_bytes - len_rx; 145195972f6Sopenharmony_ci memmove(p, &p[len_rx], data_left); 146195972f6Sopenharmony_ci return data_left; 147195972f6Sopenharmony_ci } 148195972f6Sopenharmony_ci /* if we come here, we received exactly one chunk 149195972f6Sopenharmony_ci -> next offset is 0 */ 150195972f6Sopenharmony_ci return 0; 151195972f6Sopenharmony_ci} 152195972f6Sopenharmony_ci 153195972f6Sopenharmony_cistatic size_t 154195972f6Sopenharmony_cirecv_and_check_data_return_offset(int s, char *rxbuf, size_t rxbufsize, size_t rxoff, int *closed, const char *dbg) 155195972f6Sopenharmony_ci{ 156195972f6Sopenharmony_ci ssize_t ret; 157195972f6Sopenharmony_ci 158195972f6Sopenharmony_ci ret = lwip_read(s, &rxbuf[rxoff], rxbufsize - rxoff); 159195972f6Sopenharmony_ci if (ret == 0) { 160195972f6Sopenharmony_ci *closed = 1; 161195972f6Sopenharmony_ci return rxoff; 162195972f6Sopenharmony_ci } 163195972f6Sopenharmony_ci *closed = 0; 164195972f6Sopenharmony_ci LWIP_DEBUGF(TEST_SOCKETS_STRESS | LWIP_DBG_TRACE, ("%s %d rx %d\n", dbg, s, (int)ret)); 165195972f6Sopenharmony_ci if (ret == -1) { 166195972f6Sopenharmony_ci /* TODO: for this to work, 'errno' has to support multithreading... */ 167195972f6Sopenharmony_ci int err = errno; 168195972f6Sopenharmony_ci if (err == ENOTCONN) { 169195972f6Sopenharmony_ci *closed = 1; 170195972f6Sopenharmony_ci return 0; 171195972f6Sopenharmony_ci } 172195972f6Sopenharmony_ci LWIP_ASSERT("err == 0", err == 0); 173195972f6Sopenharmony_ci } 174195972f6Sopenharmony_ci LWIP_ASSERT("ret > 0", ret > 0); 175195972f6Sopenharmony_ci return check_test_data(rxbuf, rxoff + ret); 176195972f6Sopenharmony_ci} 177195972f6Sopenharmony_ci 178195972f6Sopenharmony_ci#if LWIP_SOCKET_SELECT 179195972f6Sopenharmony_cistatic int 180195972f6Sopenharmony_cisockets_stresstest_wait_readable_select(int s, int timeout_ms) 181195972f6Sopenharmony_ci{ 182195972f6Sopenharmony_ci int ret; 183195972f6Sopenharmony_ci struct timeval tv; 184195972f6Sopenharmony_ci fd_set fs_r; 185195972f6Sopenharmony_ci fd_set fs_w; 186195972f6Sopenharmony_ci fd_set fs_e; 187195972f6Sopenharmony_ci 188195972f6Sopenharmony_ci FD_ZERO(&fs_r); 189195972f6Sopenharmony_ci FD_ZERO(&fs_w); 190195972f6Sopenharmony_ci FD_ZERO(&fs_e); 191195972f6Sopenharmony_ci 192195972f6Sopenharmony_ci FD_SET(s, &fs_r); 193195972f6Sopenharmony_ci FD_SET(s, &fs_e); 194195972f6Sopenharmony_ci 195195972f6Sopenharmony_ci tv.tv_sec = timeout_ms / 1000; 196195972f6Sopenharmony_ci tv.tv_usec = (timeout_ms - (tv.tv_sec * 1000)) * 1000; 197195972f6Sopenharmony_ci ret = lwip_select(s + 1, &fs_r, &fs_w, &fs_e, &tv); 198195972f6Sopenharmony_ci LWIP_ASSERT("select error", ret >= 0); 199195972f6Sopenharmony_ci if (ret) { 200195972f6Sopenharmony_ci /* convert poll flags to our flags */ 201195972f6Sopenharmony_ci ret = 0; 202195972f6Sopenharmony_ci if (FD_ISSET(s, &fs_r)) { 203195972f6Sopenharmony_ci ret |= TEST_SOCK_READABLE; 204195972f6Sopenharmony_ci } 205195972f6Sopenharmony_ci if (FD_ISSET(s, &fs_w)) { 206195972f6Sopenharmony_ci ret |= TEST_SOCK_WRITABLE; 207195972f6Sopenharmony_ci } 208195972f6Sopenharmony_ci if (FD_ISSET(s, &fs_e)) { 209195972f6Sopenharmony_ci ret |= TEST_SOCK_ERR; 210195972f6Sopenharmony_ci } 211195972f6Sopenharmony_ci return ret; 212195972f6Sopenharmony_ci } 213195972f6Sopenharmony_ci return 0; 214195972f6Sopenharmony_ci} 215195972f6Sopenharmony_ci#endif 216195972f6Sopenharmony_ci 217195972f6Sopenharmony_ci#if LWIP_SOCKET_POLL 218195972f6Sopenharmony_cistatic int 219195972f6Sopenharmony_cisockets_stresstest_wait_readable_poll(int s, int timeout_ms) 220195972f6Sopenharmony_ci{ 221195972f6Sopenharmony_ci int ret; 222195972f6Sopenharmony_ci struct pollfd pfd; 223195972f6Sopenharmony_ci 224195972f6Sopenharmony_ci pfd.fd = s; 225195972f6Sopenharmony_ci pfd.revents = 0; 226195972f6Sopenharmony_ci pfd.events = POLLIN | POLLERR; 227195972f6Sopenharmony_ci 228195972f6Sopenharmony_ci ret = lwip_poll(&pfd, 1, timeout_ms); 229195972f6Sopenharmony_ci if (ret) { 230195972f6Sopenharmony_ci /* convert poll flags to our flags */ 231195972f6Sopenharmony_ci ret = 0; 232195972f6Sopenharmony_ci if (pfd.revents & POLLIN) { 233195972f6Sopenharmony_ci ret |= TEST_SOCK_READABLE; 234195972f6Sopenharmony_ci } 235195972f6Sopenharmony_ci if (pfd.revents & POLLOUT) { 236195972f6Sopenharmony_ci ret |= TEST_SOCK_WRITABLE; 237195972f6Sopenharmony_ci } 238195972f6Sopenharmony_ci if (pfd.revents & POLLERR) { 239195972f6Sopenharmony_ci ret |= TEST_SOCK_ERR; 240195972f6Sopenharmony_ci } 241195972f6Sopenharmony_ci return ret; 242195972f6Sopenharmony_ci } 243195972f6Sopenharmony_ci return 0; 244195972f6Sopenharmony_ci} 245195972f6Sopenharmony_ci#endif 246195972f6Sopenharmony_ci 247195972f6Sopenharmony_ci#if LWIP_SO_RCVTIMEO 248195972f6Sopenharmony_cistatic int 249195972f6Sopenharmony_cisockets_stresstest_wait_readable_recvtimeo(int s, int timeout_ms) 250195972f6Sopenharmony_ci{ 251195972f6Sopenharmony_ci int ret; 252195972f6Sopenharmony_ci char buf; 253195972f6Sopenharmony_ci#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD 254195972f6Sopenharmony_ci int opt_on = timeout_ms; 255195972f6Sopenharmony_ci int opt_off = 0; 256195972f6Sopenharmony_ci#else 257195972f6Sopenharmony_ci struct timeval opt_on, opt_off; 258195972f6Sopenharmony_ci opt_on.tv_sec = timeout_ms / 1000; 259195972f6Sopenharmony_ci opt_on.tv_usec = (timeout_ms - (opt_on.tv_sec * 1000)) * 1000; 260195972f6Sopenharmony_ci opt_off.tv_sec = 0; 261195972f6Sopenharmony_ci opt_off.tv_usec = 0; 262195972f6Sopenharmony_ci#endif 263195972f6Sopenharmony_ci 264195972f6Sopenharmony_ci /* enable receive timeout */ 265195972f6Sopenharmony_ci ret = lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &opt_on, sizeof(opt_on)); 266195972f6Sopenharmony_ci LWIP_ASSERT("setsockopt error", ret == 0); 267195972f6Sopenharmony_ci 268195972f6Sopenharmony_ci /* peek for one byte with timeout */ 269195972f6Sopenharmony_ci ret = lwip_recv(s, &buf, 1, MSG_PEEK); 270195972f6Sopenharmony_ci 271195972f6Sopenharmony_ci /* disable receive timeout */ 272195972f6Sopenharmony_ci ret = lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &opt_off, sizeof(opt_off)); 273195972f6Sopenharmony_ci LWIP_ASSERT("setsockopt error", ret == 0); 274195972f6Sopenharmony_ci 275195972f6Sopenharmony_ci if (ret == 1) { 276195972f6Sopenharmony_ci return TEST_SOCK_READABLE; 277195972f6Sopenharmony_ci } 278195972f6Sopenharmony_ci if (ret == 0) { 279195972f6Sopenharmony_ci return 0; 280195972f6Sopenharmony_ci } 281195972f6Sopenharmony_ci if (ret == -1) { 282195972f6Sopenharmony_ci return TEST_SOCK_ERR; 283195972f6Sopenharmony_ci } 284195972f6Sopenharmony_ci LWIP_ASSERT("invalid return value", 0); 285195972f6Sopenharmony_ci return TEST_SOCK_ERR; 286195972f6Sopenharmony_ci} 287195972f6Sopenharmony_ci#endif 288195972f6Sopenharmony_ci 289195972f6Sopenharmony_cistatic int 290195972f6Sopenharmony_cisockets_stresstest_wait_readable_wait_peek(int s, int timeout_ms) 291195972f6Sopenharmony_ci{ 292195972f6Sopenharmony_ci int ret; 293195972f6Sopenharmony_ci char buf; 294195972f6Sopenharmony_ci 295195972f6Sopenharmony_ci LWIP_UNUSED_ARG(timeout_ms); /* cannot time out here */ 296195972f6Sopenharmony_ci 297195972f6Sopenharmony_ci /* peek for one byte */ 298195972f6Sopenharmony_ci ret = lwip_recv(s, &buf, 1, MSG_PEEK); 299195972f6Sopenharmony_ci 300195972f6Sopenharmony_ci if (ret == 1) { 301195972f6Sopenharmony_ci return TEST_SOCK_READABLE; 302195972f6Sopenharmony_ci } 303195972f6Sopenharmony_ci if (ret == 0) { 304195972f6Sopenharmony_ci return 0; 305195972f6Sopenharmony_ci } 306195972f6Sopenharmony_ci if (ret == -1) { 307195972f6Sopenharmony_ci return TEST_SOCK_ERR; 308195972f6Sopenharmony_ci } 309195972f6Sopenharmony_ci LWIP_ASSERT("invalid return value", 0); 310195972f6Sopenharmony_ci return TEST_SOCK_ERR; 311195972f6Sopenharmony_ci} 312195972f6Sopenharmony_ci 313195972f6Sopenharmony_cistatic int 314195972f6Sopenharmony_cisockets_stresstest_wait_readable_nonblock(int s, int timeout_ms) 315195972f6Sopenharmony_ci{ 316195972f6Sopenharmony_ci int ret; 317195972f6Sopenharmony_ci char buf; 318195972f6Sopenharmony_ci u32_t wait_until = sys_now() + timeout_ms; 319195972f6Sopenharmony_ci 320195972f6Sopenharmony_ci while(sys_now() < wait_until) { 321195972f6Sopenharmony_ci /* peek for one byte */ 322195972f6Sopenharmony_ci ret = lwip_recv(s, &buf, 1, MSG_PEEK | MSG_DONTWAIT); 323195972f6Sopenharmony_ci 324195972f6Sopenharmony_ci if (ret == 1) { 325195972f6Sopenharmony_ci return TEST_SOCK_READABLE; 326195972f6Sopenharmony_ci } 327195972f6Sopenharmony_ci if (ret == -1) { 328195972f6Sopenharmony_ci /* TODO: for this to work, 'errno' has to support multithreading... */ 329195972f6Sopenharmony_ci int err = errno; 330195972f6Sopenharmony_ci if (err != EWOULDBLOCK) { 331195972f6Sopenharmony_ci return TEST_SOCK_ERR; 332195972f6Sopenharmony_ci } 333195972f6Sopenharmony_ci } 334195972f6Sopenharmony_ci /* TODO: sleep? */ 335195972f6Sopenharmony_ci } 336195972f6Sopenharmony_ci return 0; 337195972f6Sopenharmony_ci} 338195972f6Sopenharmony_ci 339195972f6Sopenharmony_cistatic int sockets_stresstest_rand_mode(int allow_wait, int allow_rx) 340195972f6Sopenharmony_ci{ 341195972f6Sopenharmony_ci u32_t random_value = LWIP_RAND(); 342195972f6Sopenharmony_ci#if LWIP_SOCKET_SELECT 343195972f6Sopenharmony_ci if (random_value & TEST_MODE_SELECT) { 344195972f6Sopenharmony_ci return TEST_MODE_SELECT; 345195972f6Sopenharmony_ci } 346195972f6Sopenharmony_ci#endif 347195972f6Sopenharmony_ci#if LWIP_SOCKET_POLL 348195972f6Sopenharmony_ci if (random_value & TEST_MODE_POLL) { 349195972f6Sopenharmony_ci return TEST_MODE_POLL; 350195972f6Sopenharmony_ci } 351195972f6Sopenharmony_ci#endif 352195972f6Sopenharmony_ci if (!allow_rx) { 353195972f6Sopenharmony_ci return TEST_MODE_SLEEP; 354195972f6Sopenharmony_ci } 355195972f6Sopenharmony_ci#if LWIP_SO_RCVTIMEO 356195972f6Sopenharmony_ci if (random_value & TEST_MODE_RECVTIMEO) { 357195972f6Sopenharmony_ci return TEST_MODE_RECVTIMEO; 358195972f6Sopenharmony_ci } 359195972f6Sopenharmony_ci#endif 360195972f6Sopenharmony_ci if (allow_wait) { 361195972f6Sopenharmony_ci if (random_value & TEST_MODE_RECVTIMEO) { 362195972f6Sopenharmony_ci return TEST_MODE_RECVTIMEO; 363195972f6Sopenharmony_ci } 364195972f6Sopenharmony_ci } 365195972f6Sopenharmony_ci return TEST_MODE_NONBLOCKING; 366195972f6Sopenharmony_ci} 367195972f6Sopenharmony_ci 368195972f6Sopenharmony_cistatic int 369195972f6Sopenharmony_cisockets_stresstest_wait_readable(int mode, int s, int timeout_ms) 370195972f6Sopenharmony_ci{ 371195972f6Sopenharmony_ci switch(mode) 372195972f6Sopenharmony_ci { 373195972f6Sopenharmony_ci#if LWIP_SOCKET_SELECT 374195972f6Sopenharmony_ci case TEST_MODE_SELECT: 375195972f6Sopenharmony_ci return sockets_stresstest_wait_readable_select(s, timeout_ms); 376195972f6Sopenharmony_ci#endif 377195972f6Sopenharmony_ci#if LWIP_SOCKET_POLL 378195972f6Sopenharmony_ci case TEST_MODE_POLL: 379195972f6Sopenharmony_ci return sockets_stresstest_wait_readable_poll(s, timeout_ms); 380195972f6Sopenharmony_ci#endif 381195972f6Sopenharmony_ci#if LWIP_SO_RCVTIMEO 382195972f6Sopenharmony_ci case TEST_MODE_RECVTIMEO: 383195972f6Sopenharmony_ci return sockets_stresstest_wait_readable_recvtimeo(s, timeout_ms); 384195972f6Sopenharmony_ci#endif 385195972f6Sopenharmony_ci case TEST_MODE_WAIT: 386195972f6Sopenharmony_ci return sockets_stresstest_wait_readable_wait_peek(s, timeout_ms); 387195972f6Sopenharmony_ci case TEST_MODE_NONBLOCKING: 388195972f6Sopenharmony_ci return sockets_stresstest_wait_readable_nonblock(s, timeout_ms); 389195972f6Sopenharmony_ci case TEST_MODE_SLEEP: 390195972f6Sopenharmony_ci { 391195972f6Sopenharmony_ci sys_msleep(timeout_ms); 392195972f6Sopenharmony_ci return 1; 393195972f6Sopenharmony_ci } 394195972f6Sopenharmony_ci default: 395195972f6Sopenharmony_ci LWIP_ASSERT("invalid mode", 0); 396195972f6Sopenharmony_ci break; 397195972f6Sopenharmony_ci } 398195972f6Sopenharmony_ci return 0; 399195972f6Sopenharmony_ci} 400195972f6Sopenharmony_ci 401195972f6Sopenharmony_ci#if LWIP_NETCONN_FULLDUPLEX 402195972f6Sopenharmony_cistatic void 403195972f6Sopenharmony_cisockets_stresstest_conn_client_r(void *arg) 404195972f6Sopenharmony_ci{ 405195972f6Sopenharmony_ci struct sockets_stresstest_fullduplex *fd = (struct sockets_stresstest_fullduplex *)arg; 406195972f6Sopenharmony_ci int s = fd->s; 407195972f6Sopenharmony_ci size_t rxoff = 0; 408195972f6Sopenharmony_ci char rxbuf[TEST_TXRX_BUFSIZE]; 409195972f6Sopenharmony_ci 410195972f6Sopenharmony_ci while (1) { 411195972f6Sopenharmony_ci int closed; 412195972f6Sopenharmony_ci if (fd->closed) { 413195972f6Sopenharmony_ci break; 414195972f6Sopenharmony_ci } 415195972f6Sopenharmony_ci rxoff = recv_and_check_data_return_offset(s, rxbuf, sizeof(rxbuf), rxoff, &closed, "cli"); 416195972f6Sopenharmony_ci if (fd->closed) { 417195972f6Sopenharmony_ci break; 418195972f6Sopenharmony_ci } 419195972f6Sopenharmony_ci if (closed) { 420195972f6Sopenharmony_ci lwip_close(s); 421195972f6Sopenharmony_ci break; 422195972f6Sopenharmony_ci } 423195972f6Sopenharmony_ci } 424195972f6Sopenharmony_ci 425195972f6Sopenharmony_ci SYS_ARCH_DEC(sockets_stresstest_numthreads, 1); 426195972f6Sopenharmony_ci LWIP_ASSERT("", sockets_stresstest_numthreads >= 0); 427195972f6Sopenharmony_ci} 428195972f6Sopenharmony_ci#endif 429195972f6Sopenharmony_ci 430195972f6Sopenharmony_cistatic void 431195972f6Sopenharmony_cisockets_stresstest_conn_client(void *arg) 432195972f6Sopenharmony_ci{ 433195972f6Sopenharmony_ci struct sockaddr_storage addr; 434195972f6Sopenharmony_ci struct sockaddr_in *addr_in; 435195972f6Sopenharmony_ci int s, ret; 436195972f6Sopenharmony_ci char txbuf[TEST_TXRX_BUFSIZE]; 437195972f6Sopenharmony_ci char rxbuf[TEST_TXRX_BUFSIZE]; 438195972f6Sopenharmony_ci size_t rxoff = 0; 439195972f6Sopenharmony_ci u32_t max_time = sys_now() + (TEST_TIME_SECONDS * 1000); 440195972f6Sopenharmony_ci int do_rx = 1; 441195972f6Sopenharmony_ci struct sockets_stresstest_fullduplex *data = NULL; 442195972f6Sopenharmony_ci 443195972f6Sopenharmony_ci memcpy(&addr, arg, sizeof(addr)); 444195972f6Sopenharmony_ci LWIP_ASSERT("", addr.ss_family == AF_INET); 445195972f6Sopenharmony_ci addr_in = (struct sockaddr_in *)&addr; 446195972f6Sopenharmony_ci addr_in->sin_addr.s_addr = inet_addr("127.0.0.1"); 447195972f6Sopenharmony_ci 448195972f6Sopenharmony_ci /* sleep a random time between 1 and 2 seconds */ 449195972f6Sopenharmony_ci sys_msleep(1000 + (LWIP_RAND() % 1000)); 450195972f6Sopenharmony_ci 451195972f6Sopenharmony_ci /* connect to the server */ 452195972f6Sopenharmony_ci s = lwip_socket(addr.ss_family, SOCK_STREAM, 0); 453195972f6Sopenharmony_ci LWIP_ASSERT("s >= 0", s >= 0); 454195972f6Sopenharmony_ci 455195972f6Sopenharmony_ci#if LWIP_NETCONN_FULLDUPLEX 456195972f6Sopenharmony_ci if (LWIP_RAND() & 1) { 457195972f6Sopenharmony_ci sys_thread_t t; 458195972f6Sopenharmony_ci data = (struct sockets_stresstest_fullduplex*)mem_malloc(sizeof(struct sockets_stresstest_fullduplex)); 459195972f6Sopenharmony_ci LWIP_ASSERT("data != NULL", data != 0); 460195972f6Sopenharmony_ci SYS_ARCH_INC(sockets_stresstest_numthreads, 1); 461195972f6Sopenharmony_ci data->s = s; 462195972f6Sopenharmony_ci data->closed = 0; 463195972f6Sopenharmony_ci t = sys_thread_new("sockets_stresstest_conn_client_r", sockets_stresstest_conn_client_r, data, 0, 0); 464195972f6Sopenharmony_ci LWIP_ASSERT("thread != NULL", t != 0); 465195972f6Sopenharmony_ci do_rx = 0; 466195972f6Sopenharmony_ci } 467195972f6Sopenharmony_ci#endif 468195972f6Sopenharmony_ci 469195972f6Sopenharmony_ci /* @todo: nonblocking connect? */ 470195972f6Sopenharmony_ci ret = lwip_connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_storage)); 471195972f6Sopenharmony_ci LWIP_ASSERT("ret == 0", ret == 0); 472195972f6Sopenharmony_ci 473195972f6Sopenharmony_ci while (sys_now() < max_time) { 474195972f6Sopenharmony_ci int closed; 475195972f6Sopenharmony_ci int mode = sockets_stresstest_rand_mode(0, do_rx); 476195972f6Sopenharmony_ci int timeout_ms = LWIP_RAND() % TEST_MAX_RXWAIT_MS; 477195972f6Sopenharmony_ci ret = sockets_stresstest_wait_readable(mode, s, timeout_ms); 478195972f6Sopenharmony_ci if (ret) { 479195972f6Sopenharmony_ci if (do_rx) { 480195972f6Sopenharmony_ci /* read some */ 481195972f6Sopenharmony_ci LWIP_ASSERT("readable", ret == TEST_SOCK_READABLE); 482195972f6Sopenharmony_ci rxoff = recv_and_check_data_return_offset(s, rxbuf, sizeof(rxbuf), rxoff, &closed, "cli"); 483195972f6Sopenharmony_ci LWIP_ASSERT("client got closed", !closed); 484195972f6Sopenharmony_ci } 485195972f6Sopenharmony_ci } else { 486195972f6Sopenharmony_ci /* timeout, send some */ 487195972f6Sopenharmony_ci size_t send_len = (LWIP_RAND() % (sizeof(txbuf) - 4)) + 4; 488195972f6Sopenharmony_ci fill_test_data(txbuf, send_len); 489195972f6Sopenharmony_ci LWIP_DEBUGF(TEST_SOCKETS_STRESS | LWIP_DBG_TRACE, ("cli %d tx %d\n", s, (int)send_len)); 490195972f6Sopenharmony_ci ret = lwip_write(s, txbuf, send_len); 491195972f6Sopenharmony_ci if (ret == -1) { 492195972f6Sopenharmony_ci /* TODO: for this to work, 'errno' has to support multithreading... */ 493195972f6Sopenharmony_ci int err = errno; 494195972f6Sopenharmony_ci LWIP_ASSERT("err == 0", err == 0); 495195972f6Sopenharmony_ci } 496195972f6Sopenharmony_ci LWIP_ASSERT("ret == send_len", ret == (int)send_len); 497195972f6Sopenharmony_ci } 498195972f6Sopenharmony_ci } 499195972f6Sopenharmony_ci if (data) { 500195972f6Sopenharmony_ci data->closed = 1; 501195972f6Sopenharmony_ci } 502195972f6Sopenharmony_ci ret = lwip_close(s); 503195972f6Sopenharmony_ci LWIP_ASSERT("ret == 0", ret == 0); 504195972f6Sopenharmony_ci 505195972f6Sopenharmony_ci SYS_ARCH_DEC(sockets_stresstest_numthreads, 1); 506195972f6Sopenharmony_ci LWIP_ASSERT("", sockets_stresstest_numthreads >= 0); 507195972f6Sopenharmony_ci} 508195972f6Sopenharmony_ci 509195972f6Sopenharmony_cistatic void 510195972f6Sopenharmony_cisockets_stresstest_conn_server(void *arg) 511195972f6Sopenharmony_ci{ 512195972f6Sopenharmony_ci int s, ret; 513195972f6Sopenharmony_ci char txbuf[TEST_TXRX_BUFSIZE]; 514195972f6Sopenharmony_ci char rxbuf[TEST_TXRX_BUFSIZE]; 515195972f6Sopenharmony_ci size_t rxoff = 0; 516195972f6Sopenharmony_ci 517195972f6Sopenharmony_ci s = (int)arg; 518195972f6Sopenharmony_ci 519195972f6Sopenharmony_ci while (1) { 520195972f6Sopenharmony_ci int closed; 521195972f6Sopenharmony_ci int mode = sockets_stresstest_rand_mode(1, 1); 522195972f6Sopenharmony_ci int timeout_ms = LWIP_RAND() % TEST_MAX_RXWAIT_MS; 523195972f6Sopenharmony_ci ret = sockets_stresstest_wait_readable(mode, s, timeout_ms); 524195972f6Sopenharmony_ci if (ret) { 525195972f6Sopenharmony_ci if (ret & TEST_SOCK_ERR) { 526195972f6Sopenharmony_ci /* closed? */ 527195972f6Sopenharmony_ci break; 528195972f6Sopenharmony_ci } 529195972f6Sopenharmony_ci /* read some */ 530195972f6Sopenharmony_ci LWIP_ASSERT("readable", ret == TEST_SOCK_READABLE); 531195972f6Sopenharmony_ci rxoff = recv_and_check_data_return_offset(s, rxbuf, sizeof(rxbuf), rxoff, &closed, "srv"); 532195972f6Sopenharmony_ci if (closed) { 533195972f6Sopenharmony_ci break; 534195972f6Sopenharmony_ci } 535195972f6Sopenharmony_ci } else { 536195972f6Sopenharmony_ci /* timeout, send some */ 537195972f6Sopenharmony_ci size_t send_len = (LWIP_RAND() % (sizeof(txbuf) - 4)) + 4; 538195972f6Sopenharmony_ci fill_test_data(txbuf, send_len); 539195972f6Sopenharmony_ci LWIP_DEBUGF(TEST_SOCKETS_STRESS | LWIP_DBG_TRACE, ("srv %d tx %d\n", s, (int)send_len)); 540195972f6Sopenharmony_ci ret = lwip_write(s, txbuf, send_len); 541195972f6Sopenharmony_ci if (ret == -1) { 542195972f6Sopenharmony_ci /* TODO: for this to work, 'errno' has to support multithreading... */ 543195972f6Sopenharmony_ci int err = errno; 544195972f6Sopenharmony_ci if (err == ECONNRESET) { 545195972f6Sopenharmony_ci break; 546195972f6Sopenharmony_ci } 547195972f6Sopenharmony_ci if (err == ENOTCONN) { 548195972f6Sopenharmony_ci break; 549195972f6Sopenharmony_ci } 550195972f6Sopenharmony_ci LWIP_ASSERT("unknown error", 0); 551195972f6Sopenharmony_ci } 552195972f6Sopenharmony_ci LWIP_ASSERT("ret == send_len", ret == (int)send_len); 553195972f6Sopenharmony_ci } 554195972f6Sopenharmony_ci } 555195972f6Sopenharmony_ci ret = lwip_close(s); 556195972f6Sopenharmony_ci LWIP_ASSERT("ret == 0", ret == 0); 557195972f6Sopenharmony_ci 558195972f6Sopenharmony_ci SYS_ARCH_DEC(sockets_stresstest_numthreads, 1); 559195972f6Sopenharmony_ci LWIP_ASSERT("", sockets_stresstest_numthreads >= 0); 560195972f6Sopenharmony_ci} 561195972f6Sopenharmony_ci 562195972f6Sopenharmony_cistatic int 563195972f6Sopenharmony_cisockets_stresstest_start_clients(const struct sockaddr_storage *remote_addr) 564195972f6Sopenharmony_ci{ 565195972f6Sopenharmony_ci /* limit the number of connections */ 566195972f6Sopenharmony_ci const int max_connections = LWIP_MIN(TEST_MAX_CONNECTIONS, MEMP_NUM_TCP_PCB/3); 567195972f6Sopenharmony_ci int i; 568195972f6Sopenharmony_ci 569195972f6Sopenharmony_ci for (i = 0; i < max_connections; i++) { 570195972f6Sopenharmony_ci sys_thread_t t; 571195972f6Sopenharmony_ci SYS_ARCH_INC(sockets_stresstest_numthreads, 1); 572195972f6Sopenharmony_ci t = sys_thread_new("sockets_stresstest_conn_client", sockets_stresstest_conn_client, (void*)remote_addr, 0, 0); 573195972f6Sopenharmony_ci LWIP_ASSERT("thread != NULL", t != 0); 574195972f6Sopenharmony_ci } 575195972f6Sopenharmony_ci return max_connections; 576195972f6Sopenharmony_ci} 577195972f6Sopenharmony_ci 578195972f6Sopenharmony_cistatic void 579195972f6Sopenharmony_cisockets_stresstest_listener(void *arg) 580195972f6Sopenharmony_ci{ 581195972f6Sopenharmony_ci int slisten; 582195972f6Sopenharmony_ci int ret; 583195972f6Sopenharmony_ci struct sockaddr_storage addr; 584195972f6Sopenharmony_ci socklen_t addr_len; 585195972f6Sopenharmony_ci struct test_settings *settings = (struct test_settings *)arg; 586195972f6Sopenharmony_ci int num_clients, num_servers = 0; 587195972f6Sopenharmony_ci 588195972f6Sopenharmony_ci slisten = lwip_socket(AF_INET, SOCK_STREAM, 0); 589195972f6Sopenharmony_ci LWIP_ASSERT("slisten >= 0", slisten >= 0); 590195972f6Sopenharmony_ci 591195972f6Sopenharmony_ci memcpy(&addr, &settings->addr, sizeof(struct sockaddr_storage)); 592195972f6Sopenharmony_ci ret = lwip_bind(slisten, (struct sockaddr *)&addr, sizeof(addr)); 593195972f6Sopenharmony_ci LWIP_ASSERT("ret == 0", ret == 0); 594195972f6Sopenharmony_ci 595195972f6Sopenharmony_ci ret = lwip_listen(slisten, 0); 596195972f6Sopenharmony_ci LWIP_ASSERT("ret == 0", ret == 0); 597195972f6Sopenharmony_ci 598195972f6Sopenharmony_ci addr_len = sizeof(addr); 599195972f6Sopenharmony_ci ret = lwip_getsockname(slisten, (struct sockaddr *)&addr, &addr_len); 600195972f6Sopenharmony_ci LWIP_ASSERT("ret == 0", ret == 0); 601195972f6Sopenharmony_ci 602195972f6Sopenharmony_ci num_clients = sockets_stresstest_start_clients(&addr); 603195972f6Sopenharmony_ci 604195972f6Sopenharmony_ci while (num_servers < num_clients) { 605195972f6Sopenharmony_ci struct sockaddr_storage aclient; 606195972f6Sopenharmony_ci socklen_t aclient_len = sizeof(aclient); 607195972f6Sopenharmony_ci int sclient = lwip_accept(slisten, (struct sockaddr *)&aclient, &aclient_len); 608195972f6Sopenharmony_ci#if 1 609195972f6Sopenharmony_ci /* using server threads */ 610195972f6Sopenharmony_ci { 611195972f6Sopenharmony_ci sys_thread_t t; 612195972f6Sopenharmony_ci SYS_ARCH_INC(sockets_stresstest_numthreads, 1); 613195972f6Sopenharmony_ci num_servers++; 614195972f6Sopenharmony_ci t = sys_thread_new("sockets_stresstest_conn_server", sockets_stresstest_conn_server, (void*)sclient, 0, 0); 615195972f6Sopenharmony_ci LWIP_ASSERT("thread != NULL", t != 0); 616195972f6Sopenharmony_ci } 617195972f6Sopenharmony_ci#else 618195972f6Sopenharmony_ci /* using server select */ 619195972f6Sopenharmony_ci#endif 620195972f6Sopenharmony_ci } 621195972f6Sopenharmony_ci LWIP_DEBUGF(TEST_SOCKETS_STRESS | LWIP_DBG_STATE, ("sockets_stresstest_listener: all %d connections established\n", num_clients)); 622195972f6Sopenharmony_ci 623195972f6Sopenharmony_ci /* accepted all clients */ 624195972f6Sopenharmony_ci while (sockets_stresstest_numthreads > 0) { 625195972f6Sopenharmony_ci sys_msleep(1); 626195972f6Sopenharmony_ci } 627195972f6Sopenharmony_ci 628195972f6Sopenharmony_ci ret = lwip_close(slisten); 629195972f6Sopenharmony_ci LWIP_ASSERT("ret == 0", ret == 0); 630195972f6Sopenharmony_ci 631195972f6Sopenharmony_ci LWIP_DEBUGF(TEST_SOCKETS_STRESS |LWIP_DBG_STATE, ("sockets_stresstest_listener: done\n")); 632195972f6Sopenharmony_ci} 633195972f6Sopenharmony_ci 634195972f6Sopenharmony_cistatic void 635195972f6Sopenharmony_cisockets_stresstest_listener_loop(void *arg) 636195972f6Sopenharmony_ci{ 637195972f6Sopenharmony_ci int i; 638195972f6Sopenharmony_ci struct test_settings *settings = (struct test_settings *)arg; 639195972f6Sopenharmony_ci 640195972f6Sopenharmony_ci if (settings->loop_cnt) { 641195972f6Sopenharmony_ci for (i = 0; i < settings->loop_cnt; i++) { 642195972f6Sopenharmony_ci LWIP_DEBUGF(TEST_SOCKETS_STRESS |LWIP_DBG_STATE, ("sockets_stresstest_listener_loop: iteration %d\n", i)); 643195972f6Sopenharmony_ci sockets_stresstest_listener(arg); 644195972f6Sopenharmony_ci sys_msleep(2); 645195972f6Sopenharmony_ci } 646195972f6Sopenharmony_ci LWIP_DEBUGF(TEST_SOCKETS_STRESS |LWIP_DBG_STATE, ("sockets_stresstest_listener_loop: done\n")); 647195972f6Sopenharmony_ci } else { 648195972f6Sopenharmony_ci for (i = 0; ; i++) { 649195972f6Sopenharmony_ci LWIP_DEBUGF(TEST_SOCKETS_STRESS |LWIP_DBG_STATE, ("sockets_stresstest_listener_loop: iteration %d\n", i)); 650195972f6Sopenharmony_ci sockets_stresstest_listener(arg); 651195972f6Sopenharmony_ci sys_msleep(2); 652195972f6Sopenharmony_ci } 653195972f6Sopenharmony_ci } 654195972f6Sopenharmony_ci} 655195972f6Sopenharmony_ci 656195972f6Sopenharmony_civoid 657195972f6Sopenharmony_cisockets_stresstest_init_loopback(int addr_family) 658195972f6Sopenharmony_ci{ 659195972f6Sopenharmony_ci sys_thread_t t; 660195972f6Sopenharmony_ci struct test_settings *settings = (struct test_settings *)mem_malloc(sizeof(struct test_settings)); 661195972f6Sopenharmony_ci 662195972f6Sopenharmony_ci LWIP_ASSERT("OOM", settings != NULL); 663195972f6Sopenharmony_ci memset(settings, 0, sizeof(struct test_settings)); 664195972f6Sopenharmony_ci#if LWIP_IPV4 && LWIP_IPV6 665195972f6Sopenharmony_ci LWIP_ASSERT("invalid addr_family", (addr_family == AF_INET) || (addr_family == AF_INET6)); 666195972f6Sopenharmony_ci#endif 667195972f6Sopenharmony_ci settings->addr.ss_family = (sa_family_t)addr_family; 668195972f6Sopenharmony_ci LWIP_UNUSED_ARG(addr_family); 669195972f6Sopenharmony_ci settings->start_client = 1; 670195972f6Sopenharmony_ci 671195972f6Sopenharmony_ci t = sys_thread_new("sockets_stresstest_listener_loop", sockets_stresstest_listener_loop, settings, 0, 0); 672195972f6Sopenharmony_ci LWIP_ASSERT("thread != NULL", t != 0); 673195972f6Sopenharmony_ci} 674195972f6Sopenharmony_ci 675195972f6Sopenharmony_civoid 676195972f6Sopenharmony_cisockets_stresstest_init_server(int addr_family, u16_t server_port) 677195972f6Sopenharmony_ci{ 678195972f6Sopenharmony_ci sys_thread_t t; 679195972f6Sopenharmony_ci struct test_settings *settings = (struct test_settings *)mem_malloc(sizeof(struct test_settings)); 680195972f6Sopenharmony_ci 681195972f6Sopenharmony_ci LWIP_ASSERT("OOM", settings != NULL); 682195972f6Sopenharmony_ci memset(settings, 0, sizeof(struct test_settings)); 683195972f6Sopenharmony_ci#if LWIP_IPV4 && LWIP_IPV6 684195972f6Sopenharmony_ci LWIP_ASSERT("invalid addr_family", (addr_family == AF_INET) || (addr_family == AF_INET6)); 685195972f6Sopenharmony_ci settings->addr.ss_family = (sa_family_t)addr_family; 686195972f6Sopenharmony_ci#endif 687195972f6Sopenharmony_ci LWIP_UNUSED_ARG(addr_family); 688195972f6Sopenharmony_ci ((struct sockaddr_in *)(&settings->addr))->sin_port = server_port; 689195972f6Sopenharmony_ci 690195972f6Sopenharmony_ci t = sys_thread_new("sockets_stresstest_listener", sockets_stresstest_listener, settings, 0, 0); 691195972f6Sopenharmony_ci LWIP_ASSERT("thread != NULL", t != 0); 692195972f6Sopenharmony_ci} 693195972f6Sopenharmony_ci 694195972f6Sopenharmony_civoid 695195972f6Sopenharmony_cisockets_stresstest_init_client(const char *remote_ip, u16_t remote_port) 696195972f6Sopenharmony_ci{ 697195972f6Sopenharmony_ci#if LWIP_IPV4 698195972f6Sopenharmony_ci ip4_addr_t ip4; 699195972f6Sopenharmony_ci#endif 700195972f6Sopenharmony_ci#if LWIP_IPV6 701195972f6Sopenharmony_ci ip6_addr_t ip6; 702195972f6Sopenharmony_ci#endif 703195972f6Sopenharmony_ci struct sockaddr_storage *addr = (struct sockaddr_storage *)mem_malloc(sizeof(struct sockaddr_storage)); 704195972f6Sopenharmony_ci 705195972f6Sopenharmony_ci LWIP_ASSERT("OOM", addr != NULL); 706195972f6Sopenharmony_ci memset(addr, 0, sizeof(struct test_settings)); 707195972f6Sopenharmony_ci#if LWIP_IPV4 708195972f6Sopenharmony_ci if (ip4addr_aton(remote_ip, &ip4)) { 709195972f6Sopenharmony_ci addr->ss_family = AF_INET; 710195972f6Sopenharmony_ci ((struct sockaddr_in *)addr)->sin_addr.s_addr = ip4_addr_get_u32(&ip4); 711195972f6Sopenharmony_ci } 712195972f6Sopenharmony_ci#endif 713195972f6Sopenharmony_ci#if LWIP_IPV4 && LWIP_IPV6 714195972f6Sopenharmony_ci else 715195972f6Sopenharmony_ci#endif 716195972f6Sopenharmony_ci#if LWIP_IPV6 717195972f6Sopenharmony_ci if (ip6addr_aton(remote_ip, &ip6)) { 718195972f6Sopenharmony_ci addr->ss_family = AF_INET6; 719195972f6Sopenharmony_ci /* todo: copy ipv6 address */ 720195972f6Sopenharmony_ci } 721195972f6Sopenharmony_ci#endif 722195972f6Sopenharmony_ci ((struct sockaddr_in *)addr)->sin_port = remote_port; 723195972f6Sopenharmony_ci sockets_stresstest_start_clients(addr); 724195972f6Sopenharmony_ci} 725195972f6Sopenharmony_ci 726195972f6Sopenharmony_ci#endif /* LWIP_SOCKET && LWIP_IPV4 */ 727