FD.io VPP  v17.10-9-gd594711
Vector Packet Processing
sock_test.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef __sock_test_h__
17 #define __sock_test_h__
18 
19 #include <netdb.h>
20 #include <errno.h>
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #define SOCK_TEST_TOKEN_HELP "#H"
25 #define SOCK_TEST_TOKEN_EXIT "#X"
26 #define SOCK_TEST_TOKEN_VERBOSE "#V"
27 #define SOCK_TEST_TOKEN_TXBUF_SIZE "#T:"
28 #define SOCK_TEST_TOKEN_NUM_TEST_SCKTS "#I:"
29 #define SOCK_TEST_TOKEN_NUM_WRITES "#N:"
30 #define SOCK_TEST_TOKEN_RXBUF_SIZE "#R:"
31 #define SOCK_TEST_TOKEN_SHOW_CFG "#C"
32 #define SOCK_TEST_TOKEN_RUN_UNI "#U"
33 #define SOCK_TEST_TOKEN_RUN_BI "#B"
34 
35 #define SOCK_TEST_BANNER_STRING \
36  "============================================\n"
37 #define SOCK_TEST_SEPARATOR_STRING \
38  " -----------------------------\n"
39 
40 #define ONE_GIG (1024*1024*1024)
41 #define SOCK_TEST_SERVER_PORT 22000
42 #define SOCK_TEST_LOCALHOST_IPADDR "127.0.0.1"
43 
44 #define SOCK_TEST_CFG_CTRL_MAGIC 0xfeedface
45 #define SOCK_TEST_CFG_NUM_WRITES_DEF 1000000
46 #define SOCK_TEST_CFG_TXBUF_SIZE_DEF 8192
47 #define SOCK_TEST_CFG_RXBUF_SIZE_DEF (64*SOCK_TEST_CFG_TXBUF_SIZE_DEF)
48 #define SOCK_TEST_CFG_BUF_SIZE_MIN 128
49 #define SOCK_TEST_CFG_MAX_TEST_SCKTS 5
50 
51 typedef enum
52 {
58 } sock_test_t;
59 
60 typedef struct __attribute__ ((packed))
61 {
62  uint32_t magic;
63  uint32_t test;
64  uint32_t ctrl_handle;
65  uint32_t num_test_sockets;
66  uint32_t verbose;
67  uint64_t rxbuf_size;
68  uint64_t txbuf_size;
69  uint64_t num_writes;
70  uint64_t total_bytes;
72 
73 typedef struct
74 {
75  uint64_t rx_xacts;
76  uint64_t rx_bytes;
77  uint32_t rx_eagain;
78  uint32_t rx_incomp;
79  uint64_t tx_xacts;
80  uint64_t tx_bytes;
81  uint32_t tx_eagain;
82  uint32_t tx_incomp;
83  struct timespec start;
84  struct timespec stop;
86 
87 typedef struct
88 {
89  int fd;
90  uint32_t txbuf_size;
91  char *txbuf;
92  uint32_t rxbuf_size;
93  char *rxbuf;
97 
98 static inline void
100  sock_test_stats_t * incr)
101 {
102  accum->rx_xacts += incr->rx_xacts;
103  accum->rx_bytes += incr->rx_bytes;
104  accum->rx_eagain += incr->rx_eagain;
105  accum->rx_incomp += incr->rx_incomp;
106  accum->tx_xacts += incr->tx_xacts;
107  accum->tx_bytes += incr->tx_bytes;
108  accum->tx_eagain += incr->tx_eagain;
109  accum->tx_incomp += incr->tx_incomp;
110 }
111 
112 static inline void
114 {
116  cfg->test = SOCK_TEST_TYPE_NONE;
117  cfg->ctrl_handle = ~0;
118  cfg->num_test_sockets = 1;
119  cfg->verbose = 0;
123  cfg->total_bytes = cfg->num_writes * cfg->txbuf_size;
124 }
125 
126 static inline int
128 {
129  /* Note: txbuf & rxbuf on server are the same buffer,
130  * so txbuf_size is not included in this check.
131  */
132  return ((cfg->magic == valid_cfg->magic)
133  && (cfg->test == valid_cfg->test)
134  && (cfg->verbose == valid_cfg->verbose)
135  && (cfg->rxbuf_size == valid_cfg->rxbuf_size)
136  && (cfg->num_writes == valid_cfg->num_writes)
137  && (cfg->total_bytes == valid_cfg->total_bytes));
138 }
139 
140 static inline void
141 sock_test_buf_alloc (sock_test_cfg_t *cfg, uint8_t is_rxbuf, uint8_t **buf,
142  uint32_t *bufsize)
143 {
144  uint32_t alloc_size = is_rxbuf ? cfg->rxbuf_size : cfg->txbuf_size;
145  uint8_t *lb = realloc (*buf, (size_t) alloc_size);
146 
147  if (lb)
148  {
149  if (is_rxbuf)
150  cfg->rxbuf_size = *bufsize = alloc_size;
151  else
152  cfg->txbuf_size = *bufsize = alloc_size;
153 
154  *buf = lb;
155  }
156  else
157  {
158  int errno_val = errno;
159  perror ("ERROR in sock_test_buf_alloc()");
160  fprintf (stderr, "ERROR: Buffer allocation failed (errno = %d)!\n"
161  " Using buffer size %d instead of desired"
162  " size (%d)\n", errno_val, *bufsize, alloc_size);
163  }
164 }
165 
166 static inline void
168 {
169  socket->rxbuf_size = socket->cfg.rxbuf_size;
170  socket->txbuf_size = socket->cfg.txbuf_size;
171  sock_test_buf_alloc (&socket->cfg, 0 /* is_rxbuf */ ,
172  (uint8_t **) &socket->txbuf, &socket->txbuf_size);
173  sock_test_buf_alloc (&socket->cfg, 1 /* is_rxbuf */ ,
174  (uint8_t **) &socket->rxbuf, &socket->rxbuf_size);
175 }
176 
177 static inline char *
179 {
180  switch (t)
181  {
182  case SOCK_TEST_TYPE_NONE:
183  return "NONE";
184 
185  case SOCK_TEST_TYPE_ECHO:
186  return "ECHO";
187 
188  case SOCK_TEST_TYPE_UNI:
189  return "UNI";
190 
191  case SOCK_TEST_TYPE_BI:
192  return "BI";
193 
194  case SOCK_TEST_TYPE_EXIT:
195  return "EXIT";
196 
197  default:
198  return "Unknown";
199  }
200 }
201 
202 static inline void
203 sock_test_cfg_dump (sock_test_cfg_t * cfg, uint8_t is_client)
204 {
205  char *spc = " ";
206 
207  printf (" test config (%p):\n"
209  " magic: 0x%08x\n"
210  "%-5s test: %s (%d)\n"
211  " ctrl handle: %d (0x%x)\n"
212  "%-5s num test sockets: %u (0x%08x)\n"
213  "%-5s verbose: %s (%d)\n"
214  "%-5s rxbuf size: %lu (0x%08lx)\n"
215  "%-5s txbuf size: %lu (0x%08lx)\n"
216  "%-5s num writes: %lu (0x%08lx)\n"
217  " client tx bytes: %lu (0x%08lx)\n"
219  (void *) cfg, cfg->magic,
220  is_client && (cfg->test == SOCK_TEST_TYPE_UNI) ?
222  is_client && (cfg->test == SOCK_TEST_TYPE_BI) ?
223  "'"SOCK_TEST_TOKEN_RUN_BI"'" : spc,
224  sock_test_type_str (cfg->test), cfg->test,
225  cfg->ctrl_handle, cfg->ctrl_handle,
226  is_client ? "'"SOCK_TEST_TOKEN_NUM_TEST_SCKTS"'" : spc,
228  is_client ? "'"SOCK_TEST_TOKEN_VERBOSE"'" : spc,
229  cfg->verbose ? "on" : "off", cfg->verbose,
230  is_client ? "'"SOCK_TEST_TOKEN_RXBUF_SIZE"'" : spc,
231  cfg->rxbuf_size, cfg->rxbuf_size,
232  is_client ? "'"SOCK_TEST_TOKEN_TXBUF_SIZE"'" : spc,
233  cfg->txbuf_size, cfg->txbuf_size,
234  is_client ? "'"SOCK_TEST_TOKEN_NUM_WRITES"'" : spc,
235  cfg->num_writes, cfg->num_writes,
236  cfg->total_bytes, cfg->total_bytes);
237 }
238 
239 static inline void
240 sock_test_stats_dump (char * header, sock_test_stats_t * stats,
241  uint8_t show_rx, uint8_t show_tx,
242  uint8_t verbose)
243 {
244  struct timespec diff;
245  double duration, rate;
246  uint64_t total_bytes;
247 
248  if ((stats->stop.tv_nsec - stats->start.tv_nsec) < 0)
249  {
250  diff.tv_sec = stats->stop.tv_sec - stats->start.tv_sec - 1;
251  diff.tv_nsec = stats->stop.tv_nsec - stats->start.tv_nsec + 1000000000;
252  }
253  else
254  {
255  diff.tv_sec = stats->stop.tv_sec - stats->start.tv_sec;
256  diff.tv_nsec = stats->stop.tv_nsec - stats->start.tv_nsec;
257  }
258  duration = (double) diff.tv_sec + (1e-9 * diff.tv_nsec);
259 
260  total_bytes = stats->tx_bytes + stats->rx_bytes;
261  rate = (double) total_bytes * 8 / duration / ONE_GIG;
262  printf ("\n%s: Streamed %lu bytes\n"
263  " in %lf seconds (%lf Gbps %s-duplex)!\n",
264  header, total_bytes, duration, rate,
265  (show_rx && show_tx) ? "full" : "half");
266 
267  if (show_tx)
268  {
270  " tx stats (0x%p):\n"
272  " writes: %lu (0x%08lx)\n"
273  " tx bytes: %lu (0x%08lx)\n"
274  " tx eagain: %u (0x%08x)\n"
275  " tx incomplete: %u (0x%08x)\n",
276  (void *)stats, stats->tx_xacts, stats->tx_xacts,
277  stats->tx_bytes, stats->tx_bytes,
278  stats->tx_eagain, stats->tx_eagain,
279  stats->tx_incomp, stats->tx_incomp);
280  }
281  if (show_rx)
282  {
284  " rx stats (0x%p):\n"
286  " reads: %lu (0x%08lx)\n"
287  " rx bytes: %lu (0x%08lx)\n"
288  " rx eagain: %u (0x%08x)\n"
289  " rx incomplete: %u (0x%08x)\n",
290  (void *)stats, stats->rx_xacts, stats->rx_xacts,
291  stats->rx_bytes, stats->rx_bytes,
292  stats->rx_eagain, stats->rx_eagain,
293  stats->rx_incomp, stats->rx_incomp);
294  }
295  if (verbose)
296  printf (" start.tv_sec: %ld\n"
297  " start.tv_nsec: %ld\n"
298  " stop.tv_sec: %ld\n"
299  " stop.tv_nsec: %ld\n",
300  stats->start.tv_sec, stats->start.tv_nsec,
301  stats->stop.tv_sec, stats->stop.tv_nsec);
302 
304 }
305 
306 static inline int
307 sock_test_read (int fd, uint8_t *buf, uint32_t nbytes,
308  sock_test_stats_t *stats)
309 {
310  int rx_bytes, errno_val;
311 
312  do
313  {
314  if (stats)
315  stats->rx_xacts++;
316 #ifdef VCL_TEST
317  rx_bytes = vppcom_session_read (fd, buf, nbytes);
318 
319  if (rx_bytes < 0)
320  {
321  errno = -rx_bytes;
322  rx_bytes = -1;
323  }
324 #else
325  rx_bytes = read (fd, buf, nbytes);
326 #endif
327  if (stats)
328  {
329  if ((rx_bytes == 0) ||
330  ((rx_bytes < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK))))
331  stats->rx_eagain++;
332  else if (rx_bytes < nbytes)
333  stats->rx_incomp++;
334  }
335  }
336  while ((rx_bytes == 0) ||
337  ((rx_bytes < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK))));
338 
339  if (rx_bytes < 0)
340  {
341  errno_val = errno;
342  perror ("ERROR in sock_test_read()");
343  fprintf (stderr, "ERROR: socket read failed (errno = %d)!\n",
344  errno_val);
345  errno = errno_val;
346  }
347  else if (stats)
348  stats->rx_bytes += rx_bytes;
349 
350  return (rx_bytes);
351 }
352 
353 static inline int
354 sock_test_write (int fd, uint8_t *buf, uint32_t nbytes,
355  sock_test_stats_t *stats, uint32_t verbose)
356 {
357  int tx_bytes = 0;
358  int nbytes_left = nbytes;
359  int rv, errno_val;
360 
361  do
362  {
363  if (stats)
364  stats->tx_xacts++;
365 #ifdef VCL_TEST
366  rv = vppcom_session_write (fd, buf, nbytes_left);
367  if (rv < 0)
368  {
369  errno = -rv;
370  rv = -1;
371  }
372 #else
373  rv = write (fd, buf, nbytes_left);
374 #endif
375  if (rv < 0)
376  {
377  if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
378  {
379  if (stats)
380  stats->tx_eagain++;
381  continue;
382  }
383  else
384  break;
385  }
386  tx_bytes += rv;
387 
388  if (tx_bytes != nbytes)
389  {
390  nbytes_left = nbytes_left - rv;
391  if (stats)
392  stats->tx_incomp++;
393  if (verbose)
394  {
395  printf ("WARNING: bytes written (%d) != bytes to write (%d)!\n",
396  tx_bytes, nbytes);
397  }
398  }
399 
400  } while (tx_bytes != nbytes);
401 
402  if (tx_bytes < 0)
403  {
404  errno_val = errno;
405  perror ("ERROR in sock_test_write()");
406  fprintf (stderr, "ERROR: socket write failed (errno = %d)!\n",
407  errno_val);
408  }
409  else if (stats)
410  stats->tx_bytes += tx_bytes;
411 
412  return (tx_bytes);
413 }
414 
415 #endif /* __sock_test_h__ */
uint64_t tx_xacts
Definition: sock_test.h:79
uint32_t rx_incomp
Definition: sock_test.h:78
#define SOCK_TEST_TOKEN_RXBUF_SIZE
Definition: sock_test.h:30
#define SOCK_TEST_TOKEN_RUN_UNI
Definition: sock_test.h:32
uint32_t ctrl_handle
Definition: sock_test.h:64
uint64_t rx_bytes
Definition: sock_test.h:76
uint32_t magic
Definition: sock_test.h:62
static int sock_test_write(int fd, uint8_t *buf, uint32_t nbytes, sock_test_stats_t *stats, uint32_t verbose)
Definition: sock_test.h:354
#define SOCK_TEST_CFG_CTRL_MAGIC
Definition: sock_test.h:44
uint32_t test
Definition: sock_test.h:63
static void sock_test_buf_alloc(sock_test_cfg_t *cfg, uint8_t is_rxbuf, uint8_t **buf, uint32_t *bufsize)
Definition: sock_test.h:141
static void sock_test_cfg_init(sock_test_cfg_t *cfg)
Definition: sock_test.h:113
uint32_t verbose
Definition: sock_test.h:66
#define SOCK_TEST_TOKEN_NUM_TEST_SCKTS
Definition: sock_test.h:28
static void sock_test_cfg_dump(sock_test_cfg_t *cfg, uint8_t is_client)
Definition: sock_test.h:203
uint64_t tx_bytes
Definition: sock_test.h:80
uint32_t num_test_sockets
Definition: sock_test.h:65
#define SOCK_TEST_TOKEN_NUM_WRITES
Definition: sock_test.h:29
#define SOCK_TEST_TOKEN_VERBOSE
Definition: sock_test.h:26
#define SOCK_TEST_CFG_NUM_WRITES_DEF
Definition: sock_test.h:45
uint64_t total_bytes
Definition: sock_test.h:70
struct timespec stop
Definition: sock_test.h:84
sock_test_t
Definition: sock_test.h:51
struct timespec start
Definition: sock_test.h:83
static void sock_test_stats_dump(char *header, sock_test_stats_t *stats, uint8_t show_rx, uint8_t show_tx, uint8_t verbose)
Definition: sock_test.h:240
#define ONE_GIG
Definition: sock_test.h:40
#define SOCK_TEST_TOKEN_TXBUF_SIZE
Definition: sock_test.h:27
uint64_t txbuf_size
Definition: sock_test.h:68
static void sock_test_socket_buf_alloc(sock_test_socket_t *socket)
Definition: sock_test.h:167
#define SOCK_TEST_TOKEN_RUN_BI
Definition: sock_test.h:33
static int sock_test_cfg_verify(sock_test_cfg_t *cfg, sock_test_cfg_t *valid_cfg)
Definition: sock_test.h:127
uint64_t num_writes
Definition: sock_test.h:69
static int sock_test_read(int fd, uint8_t *buf, uint32_t nbytes, sock_test_stats_t *stats)
Definition: sock_test.h:307
static char * sock_test_type_str(sock_test_t t)
Definition: sock_test.h:178
#define SOCK_TEST_CFG_TXBUF_SIZE_DEF
Definition: sock_test.h:46
sock_test_stats_t stats
Definition: sock_test.h:95
uint32_t rxbuf_size
Definition: sock_test.h:92
uint32_t tx_eagain
Definition: sock_test.h:81
#define SOCK_TEST_SEPARATOR_STRING
Definition: sock_test.h:37
sock_test_cfg_t cfg
Definition: sock_test.h:94
static void sock_test_stats_accumulate(sock_test_stats_t *accum, sock_test_stats_t *incr)
Definition: sock_test.h:99
int vppcom_session_read(uint32_t session_index, void *buf, int n)
Definition: vppcom.c:2111
uint32_t rx_eagain
Definition: sock_test.h:77
uint64_t rx_xacts
Definition: sock_test.h:75
#define SOCK_TEST_CFG_RXBUF_SIZE_DEF
Definition: sock_test.h:47
uint64_t rxbuf_size
Definition: sock_test.h:67
uint32_t txbuf_size
Definition: sock_test.h:90
uint32_t tx_incomp
Definition: sock_test.h:82
int vppcom_session_write(uint32_t session_index, void *buf, int n)
Definition: vppcom.c:2194