STM32F769IDiscovery  1.00
uDANTE Audio Networking with STM32F7 DISCO board
lwiperf.c
Go to the documentation of this file.
1 
12 /*
13  * Copyright (c) 2014 Simon Goldschmidt
14  * All rights reserved.
15  *
16  * Redistribution and use in source and binary forms, with or without modification,
17  * are permitted provided that the following conditions are met:
18  *
19  * 1. Redistributions of source code must retain the above copyright notice,
20  * this list of conditions and the following disclaimer.
21  * 2. Redistributions in binary form must reproduce the above copyright notice,
22  * this list of conditions and the following disclaimer in the documentation
23  * and/or other materials provided with the distribution.
24  * 3. The name of the author may not be used to endorse or promote products
25  * derived from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
28  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
29  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
30  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
32  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
35  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
36  * OF SUCH DAMAGE.
37  *
38  * This file is part of the lwIP TCP/IP stack.
39  *
40  * Author: Simon Goldschmidt
41  */
42 
43 #include "lwip/apps/lwiperf.h"
44 
45 #include "lwip/tcp.h"
46 #include "lwip/sys.h"
47 
48 #include <string.h>
49 
50 /* Currently, only TCP-over-IPv4 is implemented (does iperf support IPv6 anyway?) */
51 #if LWIP_IPV4 && LWIP_TCP
52 
54 #ifndef LWIPERF_TCP_MAX_IDLE_SEC
55 #define LWIPERF_TCP_MAX_IDLE_SEC 10U
56 #endif
57 #if LWIPERF_TCP_MAX_IDLE_SEC > 255
58 #error LWIPERF_TCP_MAX_IDLE_SEC must fit into an u8_t
59 #endif
60 
61 /* File internal memory allocation (struct lwiperf_*): this defaults to
62  the heap */
63 #ifndef LWIPERF_ALLOC
64 #define LWIPERF_ALLOC(type) mem_malloc(sizeof(type))
65 #define LWIPERF_FREE(type, item) mem_free(item)
66 #endif
67 
69 #ifndef LWIPERF_CHECK_RX_DATA
70 #define LWIPERF_CHECK_RX_DATA 0
71 #endif
72 
74 typedef struct _lwiperf_settings {
75 #define LWIPERF_FLAGS_ANSWER_TEST 0x80000000
76 #define LWIPERF_FLAGS_ANSWER_NOW 0x00000001
77  u32_t flags;
78  u32_t num_threads; /* unused for now */
79  u32_t remote_port;
80  u32_t buffer_len; /* unused for now */
81  u32_t win_band; /* TCP window / UDP rate: unused for now */
82  u32_t amount; /* pos. value: bytes?; neg. values: time (unit is 10ms: 1/100 second) */
83 } lwiperf_settings_t;
84 
86 struct _lwiperf_state_base;
87 typedef struct _lwiperf_state_base lwiperf_state_base_t;
88 struct _lwiperf_state_base {
89  /* 1=tcp, 0=udp */
90  u8_t tcp;
91  /* 1=server, 0=client */
92  u8_t server;
93  lwiperf_state_base_t* next;
94  lwiperf_state_base_t* related_server_state;
95 };
96 
98 typedef struct _lwiperf_state_tcp {
99  lwiperf_state_base_t base;
100  struct tcp_pcb* server_pcb;
101  struct tcp_pcb* conn_pcb;
102  u32_t time_started;
103  lwiperf_report_fn report_fn;
104  void* report_arg;
105  u8_t poll_count;
106  u8_t next_num;
107  u32_t bytes_transferred;
108  lwiperf_settings_t settings;
109  u8_t have_settings_buf;
110 } lwiperf_state_tcp_t;
111 
113 static lwiperf_state_base_t* lwiperf_all_connections;
115 static const u8_t lwiperf_txbuf_const[1600] = {
116  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
117  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
118  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
119  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
120  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
121  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
122  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
123  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
124  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
125  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
126  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
127  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
128  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
129  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
130  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
131  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
132  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
133  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
134  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
135  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
136  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
137  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
138  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
139  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
140  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
141  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
142  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
143  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
144  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
145  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
146  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
147  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
148  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
149  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
150  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
151  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
152  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
153  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
154  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
155  '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
156 };
157 
158 static err_t lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb);
159 static void lwiperf_tcp_err(void *arg, err_t err);
160 
162 static void
163 lwiperf_list_add(lwiperf_state_base_t* item)
164 {
165  if (lwiperf_all_connections == NULL) {
166  lwiperf_all_connections = item;
167  } else {
168  item = lwiperf_all_connections;
169  }
170 }
171 
173 static void
174 lwiperf_list_remove(lwiperf_state_base_t* item)
175 {
176  lwiperf_state_base_t* prev = NULL;
177  lwiperf_state_base_t* iter;
178  for (iter = lwiperf_all_connections; iter != NULL; prev = iter, iter = iter->next) {
179  if (iter == item) {
180  if (prev == NULL) {
181  lwiperf_all_connections = iter->next;
182  } else {
183  prev->next = item;
184  }
185  /* @debug: ensure this item is listed only once */
186  for (iter = iter->next; iter != NULL; iter = iter->next) {
187  LWIP_ASSERT("duplicate entry", iter != item);
188  }
189  break;
190  }
191  }
192 }
193 
195 static void
196 lwip_tcp_conn_report(lwiperf_state_tcp_t* conn, enum lwiperf_report_type report_type)
197 {
198  if ((conn != NULL) && (conn->report_fn != NULL)) {
199  u32_t now, duration_ms, bandwidth_kbitpsec;
200  now = sys_now();
201  duration_ms = now - conn->time_started;
202  if (duration_ms == 0) {
203  bandwidth_kbitpsec = 0;
204  } else {
205  bandwidth_kbitpsec = (conn->bytes_transferred / duration_ms) * 8U;
206  }
207  conn->report_fn(conn->report_arg, report_type,
208  &conn->conn_pcb->local_ip, conn->conn_pcb->local_port,
209  &conn->conn_pcb->remote_ip, conn->conn_pcb->remote_port,
210  conn->bytes_transferred, duration_ms, bandwidth_kbitpsec);
211  }
212 }
213 
215 static void
216 lwiperf_tcp_close(lwiperf_state_tcp_t* conn, enum lwiperf_report_type report_type)
217 {
218  err_t err;
219 
220  lwip_tcp_conn_report(conn, report_type);
221  lwiperf_list_remove(&conn->base);
222  if (conn->conn_pcb != NULL) {
223  tcp_arg(conn->conn_pcb, NULL);
224  tcp_poll(conn->conn_pcb, NULL, 0);
225  tcp_sent(conn->conn_pcb, NULL);
226  tcp_recv(conn->conn_pcb, NULL);
227  tcp_err(conn->conn_pcb, NULL);
228  err = tcp_close(conn->conn_pcb);
229  if (err != ERR_OK) {
230  /* don't want to wait for free memory here... */
231  tcp_abort(conn->conn_pcb);
232  }
233  } else {
234  /* no conn pcb, this is the server pcb */
235  err = tcp_close(conn->server_pcb);
236  LWIP_ASSERT("error", err != ERR_OK);
237  }
238  LWIPERF_FREE(lwiperf_state_tcp_t, conn);
239 }
240 
242 static err_t
243 lwiperf_tcp_client_send_more(lwiperf_state_tcp_t* conn)
244 {
245  int send_more;
246  err_t err;
247  u16_t txlen;
248  u16_t txlen_max;
249  void* txptr;
250  u8_t apiflags;
251 
252  LWIP_ASSERT("conn invalid", (conn != NULL) && conn->base.tcp && (conn->base.server == 0));
253 
254  do {
255  send_more = 0;
256  if (conn->settings.amount & PP_HTONL(0x80000000)) {
257  /* this session is time-limited */
258  u32_t now = sys_now();
259  u32_t diff_ms = now - conn->time_started;
260  u32_t time = (u32_t)-(s32_t)htonl(conn->settings.amount);
261  u32_t time_ms = time * 10;
262  if (diff_ms >= time_ms) {
263  /* time specified by the client is over -> close the connection */
264  lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT);
265  return ERR_OK;
266  }
267  } else {
268  /* this session is byte-limited */
269  u32_t amount_bytes = htonl(conn->settings.amount);
270  /* @todo: this can send up to 1*MSS more than requested... */
271  if (amount_bytes >= conn->bytes_transferred) {
272  /* all requested bytes transferred -> close the connection */
273  lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT);
274  return ERR_OK;
275  }
276  }
277 
278  if (conn->bytes_transferred < 24) {
279  /* transmit the settings a first time */
280  txptr = &((u8_t*)&conn->settings)[conn->bytes_transferred];
281  txlen_max = (u16_t)(24 - conn->bytes_transferred);
282  apiflags = TCP_WRITE_FLAG_COPY;
283  } else if (conn->bytes_transferred < 48) {
284  /* transmit the settings a second time */
285  txptr = &((u8_t*)&conn->settings)[conn->bytes_transferred - 24];
286  txlen_max = (u16_t)(48 - conn->bytes_transferred);
287  apiflags = TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE;
288  send_more = 1;
289  } else {
290  /* transmit data */
291  /* @todo: every x bytes, transmit the settings again */
292  txptr = (void*)(size_t)&lwiperf_txbuf_const[conn->bytes_transferred % 10];
293  txlen_max = TCP_MSS;
294  if (conn->bytes_transferred == 48) { /* @todo: fix this for intermediate settings, too */
295  txlen_max = TCP_MSS - 24;
296  }
297  apiflags = 0; /* no copying needed */
298  send_more = 1;
299  }
300  txlen = txlen_max;
301  do {
302  err = tcp_write(conn->conn_pcb, txptr, txlen, apiflags);
303  if (err == ERR_MEM) {
304  txlen /= 2;
305  }
306  } while ((err == ERR_MEM) && (txlen >= (TCP_MSS/2)));
307 
308  if (err == ERR_OK) {
309  conn->bytes_transferred += txlen;
310  } else {
311  send_more = 0;
312  }
313  } while(send_more);
314 
315  tcp_output(conn->conn_pcb);
316  return ERR_OK;
317 }
318 
320 static err_t
321 lwiperf_tcp_client_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
322 {
323  lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg;
324  /* @todo: check 'len' (e.g. to time ACK of all data)? for now, we just send more... */
325  LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb);
326  LWIP_UNUSED_ARG(tpcb);
327  LWIP_UNUSED_ARG(len);
328 
329  conn->poll_count = 0;
330 
331  return lwiperf_tcp_client_send_more(conn);
332 }
333 
335 static err_t
336 lwiperf_tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
337 {
338  lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg;
339  LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb);
340  LWIP_UNUSED_ARG(tpcb);
341  if (err != ERR_OK) {
342  lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE);
343  return ERR_OK;
344  }
345  conn->poll_count = 0;
346  conn->time_started = sys_now();
347  return lwiperf_tcp_client_send_more(conn);
348 }
349 
353 static err_t
354 lwiperf_tx_start(lwiperf_state_tcp_t* conn)
355 {
356  err_t err;
357  lwiperf_state_tcp_t* client_conn;
358  struct tcp_pcb* newpcb;
359  ip_addr_t remote_addr;
360  u16_t remote_port;
361 
362  client_conn = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t);
363  if (client_conn == NULL) {
364  return ERR_MEM;
365  }
366  newpcb = tcp_new();
367  if (newpcb == NULL) {
368  LWIPERF_FREE(lwiperf_state_tcp_t, client_conn);
369  return ERR_MEM;
370  }
371 
372  memcpy(client_conn, conn, sizeof(lwiperf_state_tcp_t));
373  client_conn->base.server = 0;
374  client_conn->server_pcb = NULL;
375  client_conn->conn_pcb = newpcb;
376  client_conn->time_started = sys_now(); /* TODO: set this again on 'connected' */
377  client_conn->poll_count = 0;
378  client_conn->next_num = 4; /* initial nr is '4' since the header has 24 byte */
379  client_conn->bytes_transferred = 0;
380  client_conn->settings.flags = 0; /* prevent the remote side starting back as client again */
381 
382  tcp_arg(newpcb, client_conn);
383  tcp_sent(newpcb, lwiperf_tcp_client_sent);
384  tcp_poll(newpcb, lwiperf_tcp_poll, 2U);
385  tcp_err(newpcb, lwiperf_tcp_err);
386 
387  ip_addr_copy(remote_addr, conn->conn_pcb->remote_ip);
388  remote_port = (u16_t)htonl(client_conn->settings.remote_port);
389 
390  err = tcp_connect(newpcb, &remote_addr, remote_port, lwiperf_tcp_client_connected);
391  if (err != ERR_OK) {
392  lwiperf_tcp_close(client_conn, LWIPERF_TCP_ABORTED_LOCAL);
393  return err;
394  }
395  lwiperf_list_add(&client_conn->base);
396  return ERR_OK;
397 }
398 
400 static err_t
401 lwiperf_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
402 {
403  u16_t tot_len;
404  u32_t packet_idx;
405  struct pbuf* q;
406  lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg;
407 
408  LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb);
409  LWIP_UNUSED_ARG(tpcb);
410 
411  if (err != ERR_OK) {
412  lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE);
413  return ERR_OK;
414  }
415  if (p == NULL) {
416  /* connection closed -> test done */
417  if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) ==
418  PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST)) {
419  /* client requested transmission after end of test */
420  lwiperf_tx_start(conn);
421  }
422  lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_SERVER);
423  return ERR_OK;
424  }
425  tot_len = p->tot_len;
426 
427  conn->poll_count = 0;
428 
429  if ((!conn->have_settings_buf) || ((conn->bytes_transferred -24) % (1024*128) == 0)) {
430  /* wait for 24-byte header */
431  if (p->tot_len < sizeof(lwiperf_settings_t)) {
432  lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR);
433  pbuf_free(p);
434  return ERR_VAL;
435  }
436  if (!conn->have_settings_buf) {
437  if (pbuf_copy_partial(p, &conn->settings, sizeof(lwiperf_settings_t), 0) != sizeof(lwiperf_settings_t)) {
438  lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL);
439  pbuf_free(p);
440  return ERR_VAL;
441  }
442  conn->have_settings_buf = 1;
443  if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) ==
444  PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) {
445  /* client requested parallel transmission test */
446  err_t err2 = lwiperf_tx_start(conn);
447  if (err2 != ERR_OK) {
448  lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_TXERROR);
449  pbuf_free(p);
450  return err2;
451  }
452  }
453  } else {
454  if (pbuf_memcmp(p, 0, &conn->settings, sizeof(lwiperf_settings_t)) != 0) {
455  lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR);
456  pbuf_free(p);
457  return ERR_VAL;
458  }
459  }
460  conn->bytes_transferred += sizeof(lwiperf_settings_t);
461  if(conn->bytes_transferred <= 24) {
462  conn->time_started = sys_now();
463  tcp_recved(tpcb, p->tot_len);
464  pbuf_free(p);
465  return ERR_OK;
466  }
467  conn->next_num = 4; /* 24 bytes received... */
468  err = pbuf_header(p, -24);
469  LWIP_ASSERT("pbuf_header failed", err == ERR_OK);
470  }
471 
472  packet_idx = 0;
473  for (q = p; q != NULL; q = q->next) {
474 #if LWIPERF_CHECK_RX_DATA
475  const u8_t* payload = (const u8_t*)q->payload;
476  u16_t i;
477  for (i = 0; i < q->len; i++) {
478  u8_t val = payload[i];
479  u8_t num = val - '0';
480  if (num == conn->next_num) {
481  conn->next_num++;
482  if (conn->next_num == 10) {
483  conn->next_num = 0;
484  }
485  } else {
486  lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR);
487  pbuf_free(p);
488  return ERR_VAL;
489  }
490  }
491  packet_idx += i;
492 #else
493  packet_idx += q->len;
494 #endif
495  }
496  LWIP_ASSERT("count mismatch", packet_idx == p->tot_len);
497  conn->bytes_transferred += packet_idx;
498  tcp_recved(tpcb, tot_len);
499  pbuf_free(p);
500  return ERR_OK;
501 }
502 
504 static void
505 lwiperf_tcp_err(void *arg, err_t err)
506 {
507  lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg;
508  LWIP_UNUSED_ARG(err);
509  lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE);
510 }
511 
513 static err_t
514 lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb)
515 {
516  lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg;
517  LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb);
518  LWIP_UNUSED_ARG(tpcb);
519  if (++conn->poll_count >= LWIPERF_TCP_MAX_IDLE_SEC) {
520  lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL);
521  }
522 
523  if (!conn->base.server) {
524  lwiperf_tcp_client_send_more(conn);
525  }
526 
527  return ERR_OK;
528 }
529 
531 static err_t
532 lwiperf_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
533 {
534  lwiperf_state_tcp_t *s, *conn;
535  if ((err != ERR_OK) || (newpcb == NULL) || (arg == NULL)) {
536  return ERR_VAL;
537  }
538 
539  s = (lwiperf_state_tcp_t*)arg;
540  conn = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t);
541  if (conn == NULL) {
542  return ERR_MEM;
543  }
544  memset(conn, 0, sizeof(lwiperf_state_tcp_t));
545  conn->base.tcp = 1;
546  conn->base.server = 1;
547  conn->base.related_server_state = &s->base;
548  conn->server_pcb = s->server_pcb;
549  conn->conn_pcb = newpcb;
550  conn->time_started = sys_now();
551  conn->report_fn = s->report_fn;
552  conn->report_arg = s->report_arg;
553 
554  /* setup the tcp rx connection */
555  tcp_arg(newpcb, conn);
556  tcp_recv(newpcb, lwiperf_tcp_recv);
557  tcp_poll(newpcb, lwiperf_tcp_poll, 2U);
558  tcp_err(conn->conn_pcb, lwiperf_tcp_err);
559 
560  lwiperf_list_add(&conn->base);
561  return ERR_OK;
562 }
563 
570 void*
571 lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void* report_arg)
572 {
574  report_fn, report_arg);
575 }
576 
583 void*
584 lwiperf_start_tcp_server(const ip_addr_t* local_addr, u16_t local_port,
585  lwiperf_report_fn report_fn, void* report_arg)
586 {
587  err_t err;
588  struct tcp_pcb* pcb;
589  lwiperf_state_tcp_t* s = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t);
590  if (s == NULL) {
591  return NULL;
592  }
593  memset(s, 0, sizeof(lwiperf_state_tcp_t));
594  s->base.tcp = 1;
595  s->base.server = 1;
596  s->report_fn = report_fn;
597  s->report_arg = report_arg;
598 
599  pcb = tcp_new();
600  if (pcb != NULL) {
601  err = tcp_bind(pcb, local_addr, local_port);
602  if (err == ERR_OK) {
603  s->server_pcb = tcp_listen_with_backlog(pcb, 1);
604  }
605  }
606  if (s->server_pcb == NULL) {
607  if (pcb != NULL) {
608  tcp_close(pcb);
609  }
610  LWIPERF_FREE(lwiperf_state_tcp_t, s);
611  return NULL;
612  }
613  pcb = NULL;
614 
615  tcp_arg(s->server_pcb, s);
616  tcp_accept(s->server_pcb, lwiperf_tcp_accept);
617 
618  lwiperf_list_add(&s->base);
619  return s;
620 }
621 
623 void
624 lwiperf_abort(void* lwiperf_session)
625 {
626  lwiperf_state_base_t* i, *dealloc, *last = NULL;
627 
628  for (i = lwiperf_all_connections; i != NULL; ) {
629  if ((i == lwiperf_session) || (i->related_server_state == lwiperf_session)) {
630  dealloc = i;
631  i = i->next;
632  if (last != NULL) {
633  last->next = i;
634  }
635  LWIPERF_FREE(lwiperf_state_tcp_t, dealloc); /* TODO: type? */
636  } else {
637  last = i;
638  i = i->next;
639  }
640  }
641 }
642 
643 #endif /* LWIP_IPV4 && LWIP_TCP */
#define PP_HTONL(x)
Definition: def.h:99
void * lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void *report_arg)
lwiperf_report_type
Definition: lwiperf.h:44
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
Definition: pbuf.c:603
#define ERR_VAL
Definition: err.h:58
u16_t pbuf_memcmp(struct pbuf *p, u16_t offset, const void *s2, u16_t n)
Definition: pbuf.c:1260
void(* lwiperf_report_fn)(void *arg, enum lwiperf_report_type report_type, const ip_addr_t *local_addr, u16_t local_port, const ip_addr_t *remote_addr, u16_t remote_port, u32_t bytes_transferred, u32_t ms_duration, u32_t bandwidth_kbitpsec)
Definition: lwiperf.h:61
u16_t len
Definition: pbuf.h:125
#define LWIPERF_TCP_PORT_DEFAULT
Definition: lwiperf.h:42
#define NULL
Definition: usbd_def.h:53
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:652
#define ip_addr_copy(dest, src)
Definition: ip_addr.h:203
void * lwiperf_start_tcp_server(const ip_addr_t *local_addr, u16_t local_port, lwiperf_report_fn report_fn, void *report_arg)
unsigned long u32_t
Definition: cc.h:42
#define ERR_OK
Definition: err.h:52
u16_t tot_len
Definition: pbuf.h:122
Definition: pbuf.h:108
s8_t err_t
Definition: err.h:47
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:70
void lwiperf_abort(void *lwiperf_session)
struct pbuf * next
Definition: pbuf.h:110
u32_t sys_now(void)
u16_t pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:952
unsigned char u8_t
Definition: cc.h:38
#define TCP_MSS
Definition: lwipopts.h:117
ip6_addr_t ip_addr_t
Definition: ip_addr.h:194
signed long s32_t
Definition: cc.h:43
#define ERR_MEM
Definition: err.h:53
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:89
#define htonl(x)
Definition: def.h:88
unsigned short u16_t
Definition: cc.h:40
void * payload
Definition: pbuf.h:113