1#include <stdlib.h> 2#include <string.h> 3#include <stdint.h> 4#include "pico_ipv6.h" 5#include "pico_stack.h" 6#include "pico_socket.h" 7#include "utils.h" 8 9#define DURATION 30 10 11struct iperf_hdr { 12 int32_t flags; /* 0 */ 13 int32_t numThreads; /* 1 */ 14 int32_t mPort; /* 5001 */ 15 int32_t bufferlen; /* 0 */ 16 int32_t mWinBand; /* 0 */ 17 int32_t mAmount; /* 0xfffffc18 */ 18}; 19 20#define IPERF_PORT 5001 21#define MTU 1444 22#define SEND_BUF_SIZ (1024 * 2048) 23 24char *cpy_arg(char **dst, char *str); 25extern int IPV6_MODE; 26 27static pico_time deadline; 28 29static void panic(void) 30{ 31 for(;; ) ; 32} 33 34static char buf[MTU] = {}; 35 36static void buf_paint(void) 37{ 38 char paint[11] = "0123456789"; 39 int i; 40 for (i = 0; i < MTU; i++) { 41 buf[i] = paint[i % 10]; 42 } 43} 44 45static void send_hdr(struct pico_socket *s) 46{ 47 struct iperf_hdr hdr = {}; 48 hdr.numThreads = long_be(1); 49 hdr.mPort = long_be(5001); 50 hdr.mAmount = long_be(0xfffffc18); 51 pico_socket_write(s, &hdr, sizeof(hdr)); 52 deadline = PICO_TIME_MS() + DURATION * 1000; 53} 54 55static void iperf_cb(uint16_t ev, struct pico_socket *s) 56{ 57 int r; 58 static int end = 0; 59 if (ev & PICO_SOCK_EV_CONN) { 60 send_hdr(s); 61 return; 62 } 63 64 if ((!end) && (ev & PICO_SOCK_EV_WR)) { 65 if (PICO_TIME_MS() > deadline) { 66 pico_socket_close(s); 67 if (!pico_timer_add(2000, deferred_exit, NULL)) { 68 printf("Failed to start exit timer, exiting now\n"); 69 exit(1); 70 } 71 end++; 72 } 73 74 pico_socket_write(s, buf, MTU); 75 } 76 77 if (!(end) && (ev & (PICO_SOCK_EV_FIN | PICO_SOCK_EV_CLOSE))) { 78 if (!pico_timer_add(2000, deferred_exit, NULL)) { 79 printf("Failed to start exit timer, exiting now\n"); 80 exit(1); 81 } 82 end++; 83 } 84} 85 86static void iperfc_socket_setup(union pico_address *addr, uint16_t family) 87{ 88 int yes = 1; 89 uint16_t send_port = 0; 90 struct pico_socket *s = NULL; 91 uint32_t bufsize = SEND_BUF_SIZ; 92 send_port = short_be(5001); 93 s = pico_socket_open(family, PICO_PROTO_TCP, &iperf_cb); 94 pico_socket_setoption(s, PICO_SOCKET_OPT_SNDBUF, &bufsize); 95 pico_socket_connect(s, addr, send_port); 96} 97 98void app_iperfc(char *arg) 99{ 100 struct pico_ip4 my_eth_addr, netmask; 101 struct pico_device *pico_dev_eth; 102 char *daddr = NULL, *dport = NULL; 103 char *nxt = arg; 104 uint16_t send_port = 0, listen_port = short_be(5001); 105 int i = 0, ret = 0, yes = 1; 106 struct pico_socket *s = NULL; 107 uint16_t family = PICO_PROTO_IPV4; 108 union pico_address dst = { 109 .ip4 = {0}, .ip6 = {{0}} 110 }; 111 union pico_address inaddr_any = { 112 .ip4 = {0}, .ip6 = {{0}} 113 }; 114 115 /* start of argument parsing */ 116 if (nxt) { 117 nxt = cpy_arg(&daddr, arg); 118 if (daddr) { 119 if (!IPV6_MODE) 120 pico_string_to_ipv4(daddr, &dst.ip4.addr); 121 122 #ifdef PICO_SUPPORT_IPV6 123 else { 124 pico_string_to_ipv6(daddr, dst.ip6.addr); 125 family = PICO_PROTO_IPV6; 126 } 127 #endif 128 } else { 129 goto out; 130 } 131 } else { 132 /* missing dest_addr */ 133 goto out; 134 } 135 136 iperfc_socket_setup(&dst, family); 137 return; 138out: 139 dbg("Error parsing options!\n"); 140 exit(1); 141} 142 143