FD.io VPP  v18.07-rc0-415-g6c78436
Vector Packet Processing
main.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2017 Cisco and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *------------------------------------------------------------------
16  */
17 
18 #include <stdlib.h>
19 #include <stdint.h>
20 #include <net/if.h>
21 #include <sys/types.h>
22 #include <fcntl.h>
23 #include <sys/ioctl.h>
24 #include <sys/socket.h>
25 #include <sys/un.h>
26 #include <sys/uio.h>
27 #include <sys/mman.h>
28 #include <sys/prctl.h>
29 #include <inttypes.h>
30 #include <string.h>
31 #include <stdio.h>
32 #include <netdb.h>
33 #include <linux/ip.h>
34 #include <linux/icmp.h>
35 #include <arpa/inet.h>
36 #include <stdlib.h>
37 #include <netinet/if_ether.h>
38 #include <net/if_arp.h>
39 #include <asm/byteorder.h>
40 #include <byteswap.h>
41 #include <string.h>
42 #include <sys/epoll.h>
43 #include <errno.h>
44 #include <unistd.h>
45 #include <signal.h>
46 #include <pthread.h>
47 
48 #include <time.h>
49 
50 #ifndef TIME_UTC
51 #define TIME_UTC 1
52 #endif
53 
54 #include <libmemif.h>
55 #include <icmp_proto.h>
56 
57 #define APP_NAME "ICMP_Responder"
58 #define IF_NAME "memif_connection"
59 
60 
61 #ifdef ICMP_DBG
62 #define DBG(...) do { \
63  printf (APP_NAME":%s:%d: ", __func__, __LINE__); \
64  printf (__VA_ARGS__); \
65  printf ("\n"); \
66  } while (0)
67 #define LOG(...) do { \
68  if (enable_log) { \
69  dprintf (out_fd, __VA_ARGS__); \
70  dprintf (out_fd, "\n"); \
71  } \
72  } while (0)
73 #define LOG_FILE "/tmp/memif_time_test.txt"
74 #else
75 #define DBG(...)
76 #define LOG(...)
77 #endif
78 
79 #define INFO(...) do { \
80  printf ("INFO: "__VA_ARGS__); \
81  printf ("\n"); \
82  } while (0)
83 
84 
85 /* maximum tx/rx memif buffers */
86 #define MAX_MEMIF_BUFS 256
87 #define MAX_CONNS 50
88 
89 int epfd;
90 int out_fd;
91 uint8_t enable_log;
92 
93 typedef struct
94 {
95  uint16_t index;
96  /* memif conenction handle */
98  /* tx buffers */
99  memif_buffer_t *tx_bufs;
100  /* allocated tx buffers counter */
101  /* number of tx buffers pointing to shared memory */
102  uint16_t tx_buf_num;
103  /* rx buffers */
104  memif_buffer_t *rx_bufs;
105  /* allcoated rx buffers counter */
106  /* number of rx buffers pointing to shared memory */
107  uint16_t rx_buf_num;
108  /* interface ip address */
109  uint8_t ip_addr[4];
110  uint16_t seq;
111  uint64_t tx_counter, rx_counter, tx_err_counter;
112  uint64_t t_sec, t_nsec;
114 
115 typedef struct
116 {
117  uint16_t index;
118  uint64_t packet_num;
119  uint8_t ip_daddr[4];
120  uint8_t hw_daddr[6];
122 
123 memif_connection_t memif_connection[MAX_CONNS];
124 icmpr_thread_data_t icmpr_thread_data[MAX_CONNS];
125 pthread_t thread[MAX_CONNS];
127 
128 /* print details for all memif connections */
129 static void
131 {
132  memif_details_t md;
133  ssize_t buflen;
134  char *buf;
135  int err, i, e;
136  buflen = 2048;
137  buf = malloc (buflen);
138  printf ("MEMIF DETAILS\n");
139  printf ("==============================\n");
140  for (i = 0; i < MAX_CONNS; i++)
141  {
142  memif_connection_t *c = &memif_connection[i];
143 
144  memset (&md, 0, sizeof (md));
145  memset (buf, 0, buflen);
146 
147  err = memif_get_details (c->conn, &md, buf, buflen);
148  if (err != MEMIF_ERR_SUCCESS)
149  {
150  if (err != MEMIF_ERR_NOCONN)
151  INFO ("%s", memif_strerror (err));
152  continue;
153  }
154 
155  printf ("interface index: %d\n", i);
156 
157  printf ("\tinterface ip: %u.%u.%u.%u\n",
158  c->ip_addr[0], c->ip_addr[1], c->ip_addr[2], c->ip_addr[3]);
159  printf ("\tinterface name: %s\n", (char *) md.if_name);
160  printf ("\tapp name: %s\n", (char *) md.inst_name);
161  printf ("\tremote interface name: %s\n", (char *) md.remote_if_name);
162  printf ("\tremote app name: %s\n", (char *) md.remote_inst_name);
163  printf ("\tid: %u\n", md.id);
164  printf ("\tsecret: %s\n", (char *) md.secret);
165  printf ("\trole: ");
166  if (md.role)
167  printf ("slave\n");
168  else
169  printf ("master\n");
170  printf ("\tmode: ");
171  switch (md.mode)
172  {
173  case 0:
174  printf ("ethernet\n");
175  break;
176  case 1:
177  printf ("ip\n");
178  break;
179  case 2:
180  printf ("punt/inject\n");
181  break;
182  default:
183  printf ("unknown\n");
184  break;
185  }
186  printf ("\tsocket filename: %s\n", (char *) md.socket_filename);
187  printf ("\trx queues:\n");
188  for (e = 0; e < md.rx_queues_num; e++)
189  {
190  printf ("\t\tqueue id: %u\n", md.rx_queues[e].qid);
191  printf ("\t\tring size: %u\n", md.rx_queues[e].ring_size);
192  printf ("\t\tring rx mode: %s\n",
193  md.rx_queues[e].flags ? "polling" : "interrupt");
194  printf ("\t\tring head: %u\n", md.rx_queues[e].head);
195  printf ("\t\tring tail: %u\n", md.rx_queues[e].tail);
196  printf ("\t\tbuffer size: %u\n", md.rx_queues[e].buffer_size);
197  }
198  printf ("\ttx queues:\n");
199  for (e = 0; e < md.tx_queues_num; e++)
200  {
201  printf ("\t\tqueue id: %u\n", md.tx_queues[e].qid);
202  printf ("\t\tring size: %u\n", md.tx_queues[e].ring_size);
203  printf ("\t\tring rx mode: %s\n",
204  md.tx_queues[e].flags ? "polling" : "interrupt");
205  printf ("\t\tring head: %u\n", md.tx_queues[e].head);
206  printf ("\t\tring tail: %u\n", md.tx_queues[e].tail);
207  printf ("\t\tbuffer size: %u\n", md.tx_queues[e].buffer_size);
208  }
209  printf ("\tlink: ");
210  if (md.link_up_down)
211  printf ("up\n");
212  else
213  printf ("down\n");
214  }
215  free (buf);
216 }
217 
218 int
219 add_epoll_fd (int fd, uint32_t events)
220 {
221  if (fd < 0)
222  {
223  DBG ("invalid fd %d", fd);
224  return -1;
225  }
226  struct epoll_event evt;
227  memset (&evt, 0, sizeof (evt));
228  evt.events = events;
229  evt.data.fd = fd;
230  if (epoll_ctl (epfd, EPOLL_CTL_ADD, fd, &evt) < 0)
231  {
232  DBG ("epoll_ctl: %s fd %d", strerror (errno), fd);
233  return -1;
234  }
235  DBG ("fd %d added to epoll", fd);
236  return 0;
237 }
238 
239 int
240 mod_epoll_fd (int fd, uint32_t events)
241 {
242  if (fd < 0)
243  {
244  DBG ("invalid fd %d", fd);
245  return -1;
246  }
247  struct epoll_event evt;
248  memset (&evt, 0, sizeof (evt));
249  evt.events = events;
250  evt.data.fd = fd;
251  if (epoll_ctl (epfd, EPOLL_CTL_MOD, fd, &evt) < 0)
252  {
253  DBG ("epoll_ctl: %s fd %d", strerror (errno), fd);
254  return -1;
255  }
256  DBG ("fd %d moddified on epoll", fd);
257  return 0;
258 }
259 
260 int
261 del_epoll_fd (int fd)
262 {
263  if (fd < 0)
264  {
265  DBG ("invalid fd %d", fd);
266  return -1;
267  }
268  struct epoll_event evt;
269  memset (&evt, 0, sizeof (evt));
270  if (epoll_ctl (epfd, EPOLL_CTL_DEL, fd, &evt) < 0)
271  {
272  DBG ("epoll_ctl: %s fd %d", strerror (errno), fd);
273  return -1;
274  }
275  DBG ("fd %d removed from epoll", fd);
276  return 0;
277 }
278 
279 /* informs user about connected status. private_ctx is used by user to identify connection
280  (multiple connections WIP) */
281 int
282 on_connect (memif_conn_handle_t conn, void *private_ctx)
283 {
284  INFO ("memif connected!");
285  memif_refill_queue (conn, 0, -1, 0);
286  enable_log = 1;
287  return 0;
288 }
289 
290 /* informs user about disconnected status. private_ctx is used by user to identify connection
291  (multiple connections WIP) */
292 int
293 on_disconnect (memif_conn_handle_t conn, void *private_ctx)
294 {
295  INFO ("memif disconnected!");
296  return 0;
297 }
298 
299 /* user needs to watch new fd or stop watching fd that is about to be closed.
300  control fd will be modified during connection establishment to minimize CPU usage */
301 int
302 control_fd_update (int fd, uint8_t events)
303 {
304  /* convert memif event definitions to epoll events */
305  if (events & MEMIF_FD_EVENT_DEL)
306  return del_epoll_fd (fd);
307 
308  uint32_t evt = 0;
309  if (events & MEMIF_FD_EVENT_READ)
310  evt |= EPOLLIN;
311  if (events & MEMIF_FD_EVENT_WRITE)
312  evt |= EPOLLOUT;
313 
314  if (events & MEMIF_FD_EVENT_MOD)
315  return mod_epoll_fd (fd, evt);
316 
317  return add_epoll_fd (fd, evt);
318 }
319 
320 int
321 icmpr_buffer_alloc (long index, long n, uint16_t * r, uint16_t i,
322  uint16_t qid)
323 {
324  memif_connection_t *c = &memif_connection[index];
325  int err;
326  /* set data pointer to shared memory and set buffer_len to shared mmeory buffer len */
327  err = memif_buffer_alloc (c->conn, qid, c->tx_bufs + i, n, r, 128);
328  if ((err != MEMIF_ERR_SUCCESS) && (err != MEMIF_ERR_NOBUF_RING))
329  {
330  INFO ("memif_buffer_alloc: %s", memif_strerror (err));
331  return -1;
332  }
333  c->tx_buf_num += *r;
334  DBG ("allocated %d/%ld buffers, %u free buffers", *r, n,
336  return 0;
337 }
338 
339 int
340 icmpr_tx_burst (long index, uint16_t qid)
341 {
342  memif_connection_t *c = &memif_connection[index];
343  int err;
344  uint16_t r;
345  /* inform peer memif interface about data in shared memory buffers */
346  /* mark memif buffers as free */
347  err = memif_tx_burst (c->conn, qid, c->tx_bufs, c->tx_buf_num, &r);
348  if (err != MEMIF_ERR_SUCCESS)
349  INFO ("memif_tx_burst: %s", memif_strerror (err));
350  c->tx_buf_num -= r;
351  c->tx_counter += r;
352  return 0;
353 }
354 
355 /* called when event is polled on interrupt file descriptor.
356  there are packets in shared memory ready to be received */
357 int
358 on_interrupt (memif_conn_handle_t conn, void *private_ctx, uint16_t qid)
359 {
360  long index = *((long *) private_ctx);
361  memif_connection_t *c = &memif_connection[index];
362  if (c->index != index)
363  {
364  INFO ("invalid context: %ld/%u", index, c->index);
365  return 0;
366  }
367 
368  int err = MEMIF_ERR_SUCCESS, ret_val;
369  uint16_t rx = 0, tx = 0;
370  uint16_t fb = 0;
371  int i = 0; /* rx buffer iterator */
372  int j = 0; /* tx bufferiterator */
373 
374  /* loop while there are packets in shm */
375  do
376  {
377  /* receive data from shared memory buffers */
378  err = memif_rx_burst (c->conn, qid, c->rx_bufs, MAX_MEMIF_BUFS, &rx);
379  ret_val = err;
380  c->rx_counter += rx;
381  if ((err != MEMIF_ERR_SUCCESS) && (err != MEMIF_ERR_NOBUF))
382  {
383  INFO ("memif_rx_burst: %s", memif_strerror (err));
384  goto error;
385  }
386 
387  i = 0;
388  memset (c->tx_bufs, 0, sizeof (memif_buffer_t) * rx);
389  err = memif_buffer_alloc (c->conn, qid, c->tx_bufs, rx, &tx, 128);
390  if ((err != MEMIF_ERR_SUCCESS) && (err != MEMIF_ERR_NOBUF_RING))
391  {
392  INFO ("memif_buffer_alloc: %s", memif_strerror (err));
393  goto error;
394  }
395  j = 0;
396  c->tx_err_counter += rx - tx;
397 
398  while (tx)
399  {
400  resolve_packet ((void *) (c->rx_bufs + i)->data,
401  (c->rx_bufs + i)->len,
402  (void *) (c->tx_bufs + j)->data,
403  &(c->tx_bufs + j)->len, c->ip_addr);
404  i++;
405  j++;
406  tx--;
407  }
408 
409  err = memif_refill_queue (c->conn, qid, rx, 0);
410  if (err != MEMIF_ERR_SUCCESS)
411  INFO ("memif_buffer_free: %s", memif_strerror (err));
412  rx -= rx;
413 
414  DBG ("freed %d buffers. %u/%u alloc/free buffers",
415  rx, rx, MAX_MEMIF_BUFS - rx);
416 
417  err = memif_tx_burst (c->conn, qid, c->tx_bufs, j, &tx);
418  if (err != MEMIF_ERR_SUCCESS)
419  {
420  INFO ("memif_tx_burst: %s", memif_strerror (err));
421  goto error;
422  }
423  c->tx_counter += tx;
424 
425  }
426  while (ret_val == MEMIF_ERR_NOBUF);
427 
428  return 0;
429 
430 error:
431  err = memif_refill_queue (c->conn, qid, rx, 0);
432  if (err != MEMIF_ERR_SUCCESS)
433  INFO ("memif_buffer_free: %s", memif_strerror (err));
434  c->rx_buf_num -= rx;
435  DBG ("freed %d buffers. %u/%u alloc/free buffers",
436  fb, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
437  return 0;
438 }
439 
440 /* called when event is polled on interrupt file descriptor.
441  there are packets in shared memory ready to be received */
442 /* dev test modification: loop until TX == RX (don't drop buffers) */
443 int
444 on_interrupt0 (memif_conn_handle_t conn, void *private_ctx, uint16_t qid)
445 {
446  long index = *((long *) private_ctx);
447  memif_connection_t *c = &memif_connection[index];
448  if (c->index != index)
449  {
450  INFO ("invalid context: %ld/%u", index, c->index);
451  return 0;
452  }
453 
454  int err = MEMIF_ERR_SUCCESS, ret_val;
455  uint16_t rx = 0, tx = 0;
456  uint16_t fb;
457  int i; /* rx buffer iterator */
458  int j; /* tx bufferiterator */
459  int prev_i; /* first allocated rx buffer */
460 
461  /* loop while there are packets in shm */
462  do
463  {
464  /* receive data from shared memory buffers */
465  err = memif_rx_burst (c->conn, qid, c->rx_bufs, MAX_MEMIF_BUFS, &rx);
466  ret_val = err;
467  c->rx_counter += rx;
468  if ((err != MEMIF_ERR_SUCCESS) && (err != MEMIF_ERR_NOBUF))
469  {
470  INFO ("memif_rx_burst: %s", memif_strerror (err));
471  goto error;
472  }
473 
474  prev_i = i = 0;
475 
476  /* loop while there are RX buffers to be processed */
477  while (rx)
478  {
479 
480  /* try to alloc required number of buffers buffers */
481  err = memif_buffer_alloc (c->conn, qid, c->tx_bufs, rx, &tx, 128);
482  if ((err != MEMIF_ERR_SUCCESS) && (err != MEMIF_ERR_NOBUF_RING))
483  {
484  INFO ("memif_buffer_alloc: %s", memif_strerror (err));
485  goto error;
486  }
487  j = 0;
488 
489  /* process bufers */
490  while (tx)
491  {
492  while (tx > 2)
493  {
494  resolve_packet ((void *) (c->rx_bufs + i)->data,
495  (c->rx_bufs + i)->len,
496  (void *) (c->tx_bufs + j)->data,
497  &(c->tx_bufs + j)->len, c->ip_addr);
498  resolve_packet ((void *) (c->rx_bufs + i + 1)->data,
499  (c->rx_bufs + i + 1)->len,
500  (void *) (c->tx_bufs + j + 1)->data,
501  &(c->tx_bufs + j + 1)->len, c->ip_addr);
502 
503  i += 2;
504  j += 2;
505  tx -= 2;
506  }
507  resolve_packet ((void *) (c->rx_bufs + i)->data,
508  (c->rx_bufs + i)->len,
509  (void *) (c->tx_bufs + j)->data,
510  &(c->tx_bufs + j)->len, c->ip_addr);
511  i++;
512  j++;
513  tx--;
514  }
515  /* mark memif buffers and shared memory buffers as free */
516  /* free processed buffers */
517  err = memif_refill_queue (c->conn, qid, j, 0);
518  if (err != MEMIF_ERR_SUCCESS)
519  INFO ("memif_buffer_free: %s", memif_strerror (err));
520  rx -= j;
521  prev_i = i;
522 
523  DBG ("freed %d buffers. %u/%u alloc/free buffers",
524  fb, rx, MAX_MEMIF_BUFS - rx);
525 
526  /* transmit allocated buffers */
527  err = memif_tx_burst (c->conn, qid, c->tx_bufs, j, &tx);
528  if (err != MEMIF_ERR_SUCCESS)
529  {
530  INFO ("memif_tx_burst: %s", memif_strerror (err));
531  goto error;
532  }
533  c->tx_counter += tx;
534 
535  }
536 
537  }
538  while (ret_val == MEMIF_ERR_NOBUF);
539 
540  return 0;
541 
542 error:
543  err = memif_refill_queue (c->conn, qid, rx, 0);
544  if (err != MEMIF_ERR_SUCCESS)
545  INFO ("memif_buffer_free: %s", memif_strerror (err));
546  c->rx_buf_num -= rx;
547  DBG ("freed %d buffers. %u/%u alloc/free buffers",
548  fb, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
549  return 0;
550 }
551 
552 /* called when event is polled on interrupt file descriptor.
553  there are packets in shared memory ready to be received */
554 /* dev test modification: handle only ARP requests */
555 int
556 on_interrupt1 (memif_conn_handle_t conn, void *private_ctx, uint16_t qid)
557 {
558  long index = *((long *) private_ctx);
559  memif_connection_t *c = &memif_connection[index];
560  if (c->index != index)
561  {
562  INFO ("invalid context: %ld/%u", index, c->index);
563  return 0;
564  }
565 
566  int err = MEMIF_ERR_SUCCESS, ret_val;
567  int i;
568  uint16_t rx, tx;
569  uint16_t fb;
570  uint16_t pck_seq;
571 
572  do
573  {
574  /* receive data from shared memory buffers */
575  err = memif_rx_burst (c->conn, qid, c->rx_bufs, MAX_MEMIF_BUFS, &rx);
576  ret_val = err;
577  if ((err != MEMIF_ERR_SUCCESS) && (err != MEMIF_ERR_NOBUF))
578  {
579  INFO ("memif_rx_burst: %s", memif_strerror (err));
580  goto error;
581  }
582  c->rx_buf_num += rx;
583  c->rx_counter += rx;
584 
585  for (i = 0; i < rx; i++)
586  {
587  if (((struct ether_header *) (c->rx_bufs + i)->data)->ether_type ==
588  0x0608)
589  {
590  if (icmpr_buffer_alloc (c->index, 1, &tx, i, qid) < 0)
591  break;
592  resolve_packet ((void *) (c->rx_bufs + i)->data,
593  (c->rx_bufs + i)->len,
594  (void *) (c->tx_bufs + i)->data,
595  &(c->tx_bufs + i)->len, c->ip_addr);
596  icmpr_tx_burst (c->index, qid);
597  }
598  }
599 
600  err = memif_refill_queue (c->conn, qid, rx, 0);
601  if (err != MEMIF_ERR_SUCCESS)
602  INFO ("memif_buffer_free: %s", memif_strerror (err));
603  c->rx_buf_num -= rx;
604 
605 
606  }
607  while (ret_val == MEMIF_ERR_NOBUF);
608 
609  return 0;
610 
611 error:
612  err = memif_refill_queue (c->conn, qid, rx, 0);
613  if (err != MEMIF_ERR_SUCCESS)
614  INFO ("memif_buffer_free: %s", memif_strerror (err));
615  c->rx_buf_num -= rx;
616  DBG ("freed %d buffers. %u/%u alloc/free buffers",
617  fb, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
618  return 0;
619 }
620 
621 int
622 icmpr_memif_create (long index, long mode, char *s)
623 {
624  if (index >= MAX_CONNS)
625  {
626  INFO ("connection array overflow");
627  return 0;
628  }
629  if (index < 0)
630  {
631  INFO ("don't even try...");
632  return 0;
633  }
634  memif_connection_t *c = &memif_connection[index];
635 
636  /* setting memif connection arguments */
637  memif_conn_args_t args;
638  int fd = -1;
639  memset (&args, 0, sizeof (args));
640  args.is_master = mode;
641  args.log2_ring_size = 11;
642  args.buffer_size = 2048;
643  args.num_s2m_rings = 1;
644  args.num_m2s_rings = 1;
645  strncpy ((char *) args.interface_name, IF_NAME, strlen (IF_NAME));
646  args.mode = 0;
647  /* socket filename is not specified, because this app is supposed to
648  connect to VPP over memif. so default socket filename will be used */
649  /* default socketfile = /run/vpp/memif.sock */
650 
651  args.interface_id = index;
652  /* last argument for memif_create (void * private_ctx) is used by user
653  to identify connection. this context is returned with callbacks */
654  int err;
655  /* default interrupt */
656  if (s == NULL)
657  {
658  err = memif_create (&c->conn,
660  &ctx[index]);
661  if (err != MEMIF_ERR_SUCCESS)
662  {
663  INFO ("memif_create: %s", memif_strerror (err));
664  return 0;
665  }
666  }
667  else
668  {
669  if (strncmp (s, "0", 1) == 0)
670  {
671  err = memif_create (&c->conn,
673  &ctx[index]);
674  if (err != MEMIF_ERR_SUCCESS)
675  {
676  INFO ("memif_create: %s", memif_strerror (err));
677  return 0;
678  }
679  }
680  else if (strncmp (s, "1", 1) == 0)
681  {
682  err = memif_create (&c->conn,
684  &ctx[index]);
685  if (err != MEMIF_ERR_SUCCESS)
686  {
687  INFO ("memif_create: %s", memif_strerror (err));
688  return 0;
689  }
690  }
691  else
692  {
693  INFO ("Unknown interrupt descriptor");
694  goto done;
695  }
696  }
697 
698  c->index = index;
699  /* alloc memif buffers */
700  c->rx_buf_num = 0;
701  c->rx_bufs =
702  (memif_buffer_t *) malloc (sizeof (memif_buffer_t) * MAX_MEMIF_BUFS);
703  c->tx_buf_num = 0;
704  c->tx_bufs =
705  (memif_buffer_t *) malloc (sizeof (memif_buffer_t) * MAX_MEMIF_BUFS);
706 
707  c->ip_addr[0] = 192;
708  c->ip_addr[1] = 168;
709  c->ip_addr[2] = c->index + 1;
710  c->ip_addr[3] = 2;
711 
712  c->seq = c->tx_err_counter = c->tx_counter = c->rx_counter = 0;
713 
714 done:
715  return 0;
716 }
717 
718 int
719 icmpr_memif_delete (long index)
720 {
721  if (index >= MAX_CONNS)
722  {
723  INFO ("connection array overflow");
724  return 0;
725  }
726  if (index < 0)
727  {
728  INFO ("don't even try...");
729  return 0;
730  }
731  memif_connection_t *c = &memif_connection[index];
732 
733  if (c->rx_bufs)
734  free (c->rx_bufs);
735  c->rx_bufs = NULL;
736  c->rx_buf_num = 0;
737  if (c->tx_bufs)
738  free (c->tx_bufs);
739  c->tx_bufs = NULL;
740  c->tx_buf_num = 0;
741 
742  int err;
743  /* disconenct then delete memif connection */
744  err = memif_delete (&c->conn);
745  if (err != MEMIF_ERR_SUCCESS)
746  INFO ("memif_delete: %s", memif_strerror (err));
747  if (c->conn != NULL)
748  INFO ("memif delete fail");
749  return 0;
750 }
751 
752 void
754 {
755  printf ("LIBMEMIF EXAMPLE APP: %s", APP_NAME);
756 #ifdef ICMP_DBG
757  printf (" (debug)");
758 #endif
759  printf ("\n");
760  printf ("==============================\n");
761  printf ("libmemif version: %s", LIBMEMIF_VERSION);
762 #ifdef MEMIF_DBG
763  printf (" (debug)");
764 #endif
765  printf ("\n");
766  printf ("memif version: %d\n", memif_get_version ());
767  printf ("commands:\n");
768  printf ("\thelp - prints this help\n");
769  printf ("\texit - exit app\n");
770  printf
771  ("\tconn <index> <mode> [<interrupt-desc>] - create memif. index is also used as interface id, mode 0 = slave 1 = master, interrupt-desc none = default 0 = if ring is full wait 1 = handle only ARP requests\n");
772  printf ("\tdel <index> - delete memif\n");
773  printf ("\tshow - show connection details\n");
774  printf ("\tip-set <index> <ip-addr> - set interface ip address\n");
775  printf
776  ("\trx-mode <index> <qid> <polling|interrupt> - set queue rx mode\n");
777  printf ("\tsh-count - print counters\n");
778  printf ("\tcl-count - clear counters\n");
779  printf ("\tsend <index> <tx> <ip> <mac> - send icmp\n");
780 }
781 
782 int
784 {
785  /* application cleanup */
786  int err;
787  long i;
788  if (out_fd > 0)
789  close (out_fd);
790  out_fd = -1;
791  for (i = 0; i < MAX_CONNS; i++)
792  {
793  memif_connection_t *c = &memif_connection[i];
794  if (c->conn)
795  icmpr_memif_delete (i);
796  }
797 
798  err = memif_cleanup ();
799  if (err != MEMIF_ERR_SUCCESS)
800  INFO ("memif_delete: %s", memif_strerror (err));
801 
802  return 0;
803 }
804 
805 int
806 icmpr_set_ip (long index, char *ip)
807 {
808  if (index >= MAX_CONNS)
809  {
810  INFO ("connection array overflow");
811  return 0;
812  }
813  if (index < 0)
814  {
815  INFO ("don't even try...");
816  return 0;
817  }
818  memif_connection_t *c = &memif_connection[index];
819  if (c->conn == NULL)
820  {
821  INFO ("no connection at index %ld", index);
822  return 0;
823  }
824 
825  char *end;
826  char *ui;
827  uint8_t tmp[4];
828  ui = strtok (ip, ".");
829  if (ui == NULL)
830  goto error;
831  tmp[0] = strtol (ui, &end, 10);
832 
833  ui = strtok (NULL, ".");
834  if (ui == NULL)
835  goto error;
836  tmp[1] = strtol (ui, &end, 10);
837 
838  ui = strtok (NULL, ".");
839  if (ui == NULL)
840  goto error;
841  tmp[2] = strtol (ui, &end, 10);
842 
843  ui = strtok (NULL, ".");
844  if (ui == NULL)
845  goto error;
846  tmp[3] = strtol (ui, &end, 10);
847 
848  c->ip_addr[0] = tmp[0];
849  c->ip_addr[1] = tmp[1];
850  c->ip_addr[2] = tmp[2];
851  c->ip_addr[3] = tmp[3];
852 
853  INFO ("memif %ld ip address set to %u.%u.%u.%u",
854  index, c->ip_addr[0], c->ip_addr[1], c->ip_addr[2], c->ip_addr[3]);
855 
856  return 0;
857 
858 error:
859  INFO ("invalid ip address");
860  return 0;
861 }
862 
863 int
864 icmpr_set_rx_mode (long index, long qid, char *mode)
865 {
866  if (index >= MAX_CONNS)
867  {
868  INFO ("connection array overflow");
869  return 0;
870  }
871  if (index < 0)
872  {
873  INFO ("don't even try...");
874  return 0;
875  }
876  memif_connection_t *c = &memif_connection[index];
877 
878  if (c->conn == NULL)
879  {
880  INFO ("no connection at index %ld", index);
881  return 0;
882  }
883 
884  if (strncmp (mode, "interrupt", 9) == 0)
885  {
887  }
888 
889  else if (strncmp (mode, "polling", 7) == 0)
890  {
892  }
893  else
894  INFO ("expected rx mode <interrupt|polling>");
895  return 0;
896 }
897 
898 void
900 {
901  int i;
902  for (i = 0; i < MAX_CONNS; i++)
903  {
904  memif_connection_t *c = &memif_connection[i];
905  if (c->conn == NULL)
906  continue;
907  printf ("===============================\n");
908  printf ("interface index: %d\n", c->index);
909  printf ("\trx: %lu\n", c->rx_counter);
910  printf ("\ttx: %lu\n", c->tx_counter);
911  printf ("\ttx_err: %lu\n", c->tx_err_counter);
912  printf ("\tts: %lus %luns\n", c->t_sec, c->t_nsec);
913  }
914 }
915 
916 void
918 {
919  int i;
920  for (i = 0; i < MAX_CONNS; i++)
921  {
922  memif_connection_t *c = &memif_connection[i];
923  if (c->conn == NULL)
924  continue;
925  c->t_sec = c->t_nsec = c->tx_err_counter = c->tx_counter =
926  c->rx_counter = 0;
927  }
928 }
929 
930 void *
931 icmpr_send_proc (void *data)
932 {
934  int index = d->index;
935  uint64_t count = d->packet_num;
936  memif_connection_t *c = &memif_connection[index];
937  if (c->conn == NULL)
938  {
939  INFO ("No connection at index %d. Thread exiting...\n", index);
940  pthread_exit (NULL);
941  }
942  uint16_t tx, i;
943  int err = MEMIF_ERR_SUCCESS;
944  uint32_t seq = 0;
945  struct timespec start, end;
946  memset (&start, 0, sizeof (start));
947  memset (&end, 0, sizeof (end));
948 
949  timespec_get (&start, TIME_UTC);
950  while (count)
951  {
952  i = 0;
953  err = memif_buffer_alloc (c->conn, 0, c->tx_bufs,
955  count ? count : MAX_MEMIF_BUFS, &tx, 128);
956  if ((err != MEMIF_ERR_SUCCESS) && (err != MEMIF_ERR_NOBUF_RING))
957  {
958  INFO ("memif_buffer_alloc: %s Thread exiting...\n",
959  memif_strerror (err));
960  pthread_exit (NULL);
961  }
962  c->tx_buf_num += tx;
963 
964  while (tx)
965  {
966  while (tx > 2)
967  {
968  generate_packet ((void *) c->tx_bufs[i].data,
969  &c->tx_bufs[i].len, c->ip_addr,
970  d->ip_daddr, d->hw_daddr, seq++);
971  generate_packet ((void *) c->tx_bufs[i + 1].data,
972  &c->tx_bufs[i + 1].len, c->ip_addr,
973  d->ip_daddr, d->hw_daddr, seq++);
974  i += 2;
975  tx -= 2;
976  }
977  generate_packet ((void *) c->tx_bufs[i].data,
978  &c->tx_bufs[i].len, c->ip_addr,
979  d->ip_daddr, d->hw_daddr, seq++);
980  i++;
981  tx--;
982  }
983  err = memif_tx_burst (c->conn, 0, c->tx_bufs, c->tx_buf_num, &tx);
984  if (err != MEMIF_ERR_SUCCESS)
985  {
986  INFO ("memif_tx_burst: %s Thread exiting...\n",
987  memif_strerror (err));
988  pthread_exit (NULL);
989  }
990  c->tx_buf_num -= tx;
991  c->tx_counter += tx;
992  count -= tx;
993  }
994  timespec_get (&end, TIME_UTC);
995  INFO ("Pakcet sequence finished!");
996  INFO ("Seq len: %u", seq);
997  uint64_t t1 = end.tv_sec - start.tv_sec;
998  uint64_t t2;
999  if (end.tv_nsec > start.tv_nsec)
1000  {
1001  t2 = end.tv_nsec - start.tv_nsec;
1002  }
1003  else
1004  {
1005  t2 = start.tv_nsec - end.tv_nsec;
1006  t1--;
1007  }
1008  c->t_sec = t1;
1009  c->t_nsec = t2;
1010  INFO ("Seq time: %lus %luns", t1, t2);
1011  double tmp = t1;
1012  tmp += t2 / 1e+9;
1013  tmp = seq / tmp;
1014  INFO ("Average pps: %f", tmp);
1015  INFO ("Thread exiting...");
1016  pthread_exit (NULL);
1017 }
1018 
1019 int
1020 icmpr_send (long index, long packet_num, char *hw, char *ip)
1021 {
1022  memif_connection_t *c = &memif_connection[index];
1023  char *end;
1024  char *ui;
1025  uint8_t tmp[6];
1026  if (c->conn == NULL)
1027  return -1;
1028  c->seq = 0;
1029  icmpr_thread_data_t *data = &icmpr_thread_data[index];
1030  data->index = index;
1031  data->packet_num = packet_num;
1032  INFO ("PN: %lu", data->packet_num);
1033  printf ("%s\n", ip);
1034  printf ("%s\n", hw);
1035 
1036  ui = strtok (ip, ".");
1037  if (ui == NULL)
1038  goto error;
1039  tmp[0] = strtol (ui, &end, 10);
1040 
1041  ui = strtok (NULL, ".");
1042  if (ui == NULL)
1043  goto error;
1044  tmp[1] = strtol (ui, &end, 10);
1045 
1046  ui = strtok (NULL, ".");
1047  if (ui == NULL)
1048  goto error;
1049  tmp[2] = strtol (ui, &end, 10);
1050 
1051  ui = strtok (NULL, ".");
1052  if (ui == NULL)
1053  goto error;
1054  tmp[3] = strtol (ui, &end, 10);
1055 
1056  data->ip_daddr[0] = tmp[0];
1057  data->ip_daddr[1] = tmp[1];
1058  data->ip_daddr[2] = tmp[2];
1059  data->ip_daddr[3] = tmp[3];
1060 
1061  ui = strtok (hw, ":");
1062  if (ui == NULL)
1063  goto error;
1064  tmp[0] = strtol (ui, &end, 16);
1065  ui = strtok (NULL, ":");
1066  if (ui == NULL)
1067  goto error;
1068  tmp[1] = strtol (ui, &end, 16);
1069  ui = strtok (NULL, ":");
1070  if (ui == NULL)
1071  goto error;
1072  tmp[2] = strtol (ui, &end, 16);
1073  ui = strtok (NULL, ":");
1074  if (ui == NULL)
1075  goto error;
1076  tmp[3] = strtol (ui, &end, 16);
1077  ui = strtok (NULL, ":");
1078  if (ui == NULL)
1079  goto error;
1080  tmp[4] = strtol (ui, &end, 16);
1081  ui = strtok (NULL, ":");
1082  if (ui == NULL)
1083  goto error;
1084  tmp[5] = strtol (ui, &end, 16);
1085 
1086  data->hw_daddr[0] = tmp[0];
1087  data->hw_daddr[1] = tmp[1];
1088  data->hw_daddr[2] = tmp[2];
1089  data->hw_daddr[3] = tmp[3];
1090  data->hw_daddr[4] = tmp[4];
1091  data->hw_daddr[5] = tmp[5];
1092 
1093  pthread_create (&thread[index], NULL, icmpr_send_proc, (void *) data);
1094  return 0;
1095 
1096 error:
1097  INFO ("Invalid input\n");
1098  return 0;
1099 }
1100 
1101 int
1103 {
1104  int i;
1105  char *in = (char *) malloc (256);
1106  char *ui = fgets (in, 256, stdin);
1107  char *end;
1108  long a;
1109  if (in[0] == '\n')
1110  goto done;
1111  ui = strtok (in, " ");
1112  if (strncmp (ui, "exit", 4) == 0)
1113  {
1114  free (in);
1115  icmpr_free ();
1116  exit (EXIT_SUCCESS);
1117  }
1118  else if (strncmp (ui, "help", 4) == 0)
1119  {
1120  print_help ();
1121  goto done;
1122  }
1123  else if (strncmp (ui, "conn", 4) == 0)
1124  {
1125  ui = strtok (NULL, " ");
1126  if (ui != NULL)
1127  a = strtol (ui, &end, 10);
1128  else
1129  {
1130  INFO ("expected id");
1131  goto done;
1132  }
1133  ui = strtok (NULL, " ");
1134  if (ui != NULL)
1135  icmpr_memif_create (a, strtol (ui, &end, 10), strtok (NULL, " "));
1136  else
1137  INFO ("expected mode <0|1>");
1138  goto done;
1139  }
1140  else if (strncmp (ui, "del", 3) == 0)
1141  {
1142  ui = strtok (NULL, " ");
1143  if (ui != NULL)
1144  icmpr_memif_delete (strtol (ui, &end, 10));
1145  else
1146  INFO ("expected id");
1147  goto done;
1148  }
1149  else if (strncmp (ui, "show", 4) == 0)
1150  {
1152  goto done;
1153  }
1154  else if (strncmp (ui, "ip-set", 6) == 0)
1155  {
1156  ui = strtok (NULL, " ");
1157  if (ui != NULL)
1158  icmpr_set_ip (strtol (ui, &end, 10), strtok (NULL, " "));
1159  else
1160  INFO ("expected id");
1161  goto done;
1162  }
1163  else if (strncmp (ui, "rx-mode", 7) == 0)
1164  {
1165  ui = strtok (NULL, " ");
1166  if (ui != NULL)
1167  a = strtol (ui, &end, 10);
1168  else
1169  {
1170  INFO ("expected id");
1171  goto done;
1172  }
1173  ui = strtok (NULL, " ");
1174  if (ui != NULL)
1175  icmpr_set_rx_mode (a, strtol (ui, &end, 10), strtok (NULL, " "));
1176  else
1177  INFO ("expected qid");
1178  goto done;
1179  }
1180  else if (strncmp (ui, "sh-count", 8) == 0)
1181  {
1183  }
1184  else if (strncmp (ui, "cl-count", 8) == 0)
1185  {
1187  }
1188  else if (strncmp (ui, "send", 4) == 0)
1189  {
1190  ui = strtok (NULL, " ");
1191  if (ui != NULL)
1192  a = strtol (ui, &end, 10);
1193  else
1194  {
1195  INFO ("expected id");
1196  goto done;
1197  }
1198  ui = strtok (NULL, " ");
1199  if (ui != NULL)
1200  icmpr_send (a, strtol (ui, &end, 10), strtok (NULL, " "),
1201  strtok (NULL, " "));
1202  else
1203  INFO ("expected count");
1204  goto done;
1205  }
1206  else
1207  {
1208  INFO ("unknown command: %s", ui);
1209  goto done;
1210  }
1211 
1212  return 0;
1213 done:
1214  free (in);
1215  return 0;
1216 }
1217 
1218 int
1219 poll_event (int timeout)
1220 {
1221  struct epoll_event evt, *e;
1222  int app_err = 0, memif_err = 0, en = 0;
1223  int tmp, nfd;
1224  uint32_t events = 0;
1225  struct timespec start, end;
1226  memset (&evt, 0, sizeof (evt));
1227  evt.events = EPOLLIN | EPOLLOUT;
1228  sigset_t sigset;
1229  sigemptyset (&sigset);
1230  en = epoll_pwait (epfd, &evt, 1, timeout, &sigset);
1231  /* id event polled */
1232  timespec_get (&start, TIME_UTC);
1233  if (en < 0)
1234  {
1235  DBG ("epoll_pwait: %s", strerror (errno));
1236  return -1;
1237  }
1238  if (en > 0)
1239  {
1240  /* this app does not use any other file descriptors than stds and memif control fds */
1241  if (evt.data.fd > 2)
1242  {
1243  /* event of memif control fd */
1244  /* convert epolle events to memif events */
1245  if (evt.events & EPOLLIN)
1246  events |= MEMIF_FD_EVENT_READ;
1247  if (evt.events & EPOLLOUT)
1248  events |= MEMIF_FD_EVENT_WRITE;
1249  if (evt.events & EPOLLERR)
1250  events |= MEMIF_FD_EVENT_ERROR;
1251  memif_err = memif_control_fd_handler (evt.data.fd, events);
1252  if (memif_err != MEMIF_ERR_SUCCESS)
1253  INFO ("memif_control_fd_handler: %s", memif_strerror (memif_err));
1254  }
1255  else if (evt.data.fd == 0)
1256  {
1257  app_err = user_input_handler ();
1258  }
1259  else
1260  {
1261  DBG ("unexpected event at memif_epfd. fd %d", evt.data.fd);
1262  }
1263  }
1264 
1265  timespec_get (&end, TIME_UTC);
1266  LOG ("interrupt: %ld", end.tv_nsec - start.tv_nsec);
1267 
1268  if ((app_err < 0) || (memif_err < 0))
1269  {
1270  if (app_err < 0)
1271  DBG ("user input handler error");
1272  if (memif_err < 0)
1273  DBG ("memif control fd handler error");
1274  return -1;
1275  }
1276 
1277  return 0;
1278 }
1279 
1280 int
1282 {
1283  epfd = epoll_create (1);
1284  add_epoll_fd (0, EPOLLIN);
1285 
1286 #ifdef LOG_FILE
1287  remove (LOG_FILE);
1288  enable_log = 0;
1289 
1290  out_fd = open (LOG_FILE, O_WRONLY | O_CREAT, S_IRWXO);
1291  if (out_fd < 0)
1292  INFO ("Error opening log file: %s", strerror (errno));
1293 #endif /* LOG_FILE */
1294 
1295  /* initialize memory interface */
1296  int err, i;
1297  /* if valid callback is passed as argument, fd event polling will be done by user
1298  all file descriptors and events will be passed to user in this callback */
1299  /* if callback is set to NULL libmemif will handle fd event polling */
1301  if (err != MEMIF_ERR_SUCCESS)
1302  {
1303  INFO ("memif_init: %s", memif_strerror (err));
1304  icmpr_free ();
1305  exit (-1);
1306  }
1307 
1308  for (i = 0; i < MAX_CONNS; i++)
1309  {
1310  memset (&memif_connection[i], 0, sizeof (memif_connection_t));
1311  ctx[i] = i;
1312  }
1313 
1314  print_help ();
1315 
1316  /* main loop */
1317  while (1)
1318  {
1319  if (poll_event (-1) < 0)
1320  {
1321  DBG ("poll_event error!");
1322  }
1323  }
1324 }
void icmpr_reset_counters()
Definition: main.c:917
uint64_t rx_counter
Definition: main.c:111
int on_interrupt1(memif_conn_handle_t conn, void *private_ctx, uint16_t qid)
Definition: main.c:556
#define IF_NAME
Definition: main.c:58
int icmpr_memif_delete()
Definition: main.c:193
int mod_epoll_fd(int fd, uint32_t events)
Definition: main.c:240
void print_help()
Definition: main.c:204
a
Definition: bitmap.h:537
uint8_t * inst_name
Definition: libmemif.h:271
uint8_t * secret
Definition: libmemif.h:276
void * icmpr_send_proc(void *data)
Definition: main.c:931
int on_disconnect(memif_conn_handle_t conn, void *private_ctx)
Definition: main.c:186
uint16_t seq
Definition: main.c:110
#define MEMIF_FD_EVENT_READ
user needs to set events that occured on fd and pass them to memif_control_fd_handler ...
Definition: libmemif.h:87
int on_interrupt0(memif_conn_handle_t conn, void *private_ctx, uint16_t qid)
Definition: main.c:444
uint8_t num_m2s_rings
Definition: libmemif.h:187
int control_fd_update(int fd, uint8_t events)
Definition: main.c:302
#define NULL
Definition: clib.h:55
uint16_t buffer_size
Definition: libmemif.h:188
uint32_t interface_id
Definition: libmemif.h:192
int i
int out_fd
Definition: main.c:90
int icmpr_set_ip(long index, char *ip)
Definition: main.c:806
uint8_t * remote_inst_name
Definition: libmemif.h:273
pthread_t thread[MAX_CONNS]
Definition: main.c:125
#define LIBMEMIF_VERSION
Libmemif version.
Definition: libmemif.h:26
int memif_refill_queue(memif_conn_handle_t conn, uint16_t qid, uint16_t count, uint16_t headroom)
Memif refill ring.
Definition: main.c:1664
int on_connect(memif_conn_handle_t conn, void *private_ctx)
Definition: main.c:177
uint8_t num_s2m_rings
Definition: libmemif.h:186
uint32_t len
Definition: libmemif.h:215
int icmpr_free()
Definition: main.c:258
int memif_get_details(memif_conn_handle_t conn, memif_details_t *md, char *buf, ssize_t buflen)
Memif get details.
Definition: main.c:1871
int icmpr_set_rx_mode(long index, long qid, char *mode)
Definition: main.c:864
memif_interface_mode_t mode
Definition: libmemif.h:194
uint8_t mode
Definition: libmemif.h:278
uint8_t link_up_down
Definition: libmemif.h:285
char * memif_strerror(int err_code)
Memif strerror.
Definition: main.c:157
int icmpr_memif_create(int is_master)
Definition: main.c:337
memif_conn_handle_t conn
Definition: main.c:76
#define TIME_UTC
Definition: main.c:51
#define APP_NAME
Definition: main.c:57
int del_epoll_fd(int fd)
Definition: main.c:261
#define MAX_MEMIF_BUFS
Definition: main.c:86
uint8_t ip_addr[4]
Definition: main.c:90
uint16_t rx_buf_num
Definition: main.c:88
#define MAX_CONNS
Definition: main.c:87
uint8_t interface_name[32]
Definition: libmemif.h:193
void * data
Definition: libmemif.h:221
int resolve_packet(void *in_pck, ssize_t in_size, void *out_pck, uint32_t *out_size, uint8_t ip_addr[4])
Definition: icmp_proto.c:208
uint16_t buffer_size
Definition: libmemif.h:249
uint8_t * socket_filename
Definition: libmemif.h:279
#define MEMIF_FD_EVENT_DEL
if set, informs that fd is going to be closed (user may want to stop watching for events on this fd) ...
Definition: libmemif.h:92
int memif_set_rx_mode(memif_conn_handle_t c, memif_rx_mode_t rx_mode, uint16_t qid)
Memif set rx mode.
Definition: main.c:577
struct memif_connection memif_connection_t
uint8_t hw_daddr[6]
Definition: main.c:120
uint8_t is_master
Definition: libmemif.h:190
uint8_t rx_queues_num
Definition: libmemif.h:280
int memif_init(memif_control_fd_update_t *on_control_fd_update, char *app_name, memif_alloc_t *memif_alloc, memif_free_t *memif_free)
Memif initialization.
Definition: main.c:429
#define DBG(...)
Definition: main.c:75
void icmpr_print_counters()
Definition: main.c:899
uint64_t tx_counter
Definition: main.c:111
int icmpr_tx_burst(uint16_t qid)
Definition: main.c:242
uint16_t tx_buf_num
Definition: main.c:83
int on_interrupt(memif_conn_handle_t conn, void *private_ctx, uint16_t qid)
Definition: main.c:287
svmdb_client_t * c
int memif_tx_burst(memif_conn_handle_t conn, uint16_t qid, memif_buffer_t *bufs, uint16_t count, uint16_t *tx)
Memif transmit buffer burst.
Definition: main.c:1719
int memif_buffer_alloc(memif_conn_handle_t conn, uint16_t qid, memif_buffer_t *bufs, uint16_t count, uint16_t *count_out, uint16_t size)
Memif buffer alloc.
Definition: main.c:1535
int add_epoll_fd(int fd, uint32_t events)
Definition: main.c:219
memif_queue_details_t * rx_queues
Definition: libmemif.h:282
uint8_t role
Definition: libmemif.h:277
int icmpr_send(long index, long packet_num, char *hw, char *ip)
Definition: main.c:1020
#define INFO(...)
Definition: main.c:79
uint8_t enable_log
Definition: main.c:91
int memif_cleanup()
Memif cleanup.
Definition: main.c:2018
#define LOG(...)
Definition: main.c:76
uint8_t ip_daddr[4]
Definition: main.c:119
int memif_create(memif_conn_handle_t *c, memif_conn_args_t *args, memif_connection_update_t *on_connect, memif_connection_update_t *on_disconnect, memif_interrupt_t *on_interrupt, void *private_ctx)
Memory interface create function.
Definition: main.c:595
int generate_packet(void *pck, uint32_t *size, uint8_t saddr[4], uint8_t daddr[4], uint8_t hw_daddr[6], uint32_t seq)
Definition: icmp_proto.c:314
long ctx[MAX_CONNS]
Definition: main.c:126
int poll_event(int timeout)
Definition: main.c:1219
uint64_t t_sec
Definition: main.c:112
uint8_t tx_queues_num
Definition: libmemif.h:281
size_t count
Definition: vapi.c:42
uint16_t index
Definition: main.c:117
void * memif_conn_handle_t
Memif connection handle pointer of type void, pointing to internal structure.
Definition: libmemif.h:100
uint64_t packet_num
Definition: main.c:118
int icmpr_buffer_alloc(long n, uint16_t qid)
Definition: main.c:222
int memif_control_fd_handler(int fd, uint8_t events)
Memif control file descriptor handler.
Definition: main.c:859
uint8_t log2_ring_size
Definition: libmemif.h:189
uint64_t tx_err_counter
Definition: main.c:111
int epfd
Definition: main.c:94
uint32_t id
Definition: libmemif.h:275
int memif_rx_burst(memif_conn_handle_t conn, uint16_t qid, memif_buffer_t *bufs, uint16_t count, uint16_t *rx)
Memif receive buffer burst.
Definition: main.c:1786
uint64_t t_nsec
Definition: main.c:112
int memif_delete(memif_conn_handle_t *conn)
Memif delete.
Definition: main.c:1184
static void print_memif_details()
Definition: main.c:130
#define MEMIF_FD_EVENT_ERROR
inform libmemif that error occured on fd
Definition: libmemif.h:90
#define MEMIF_FD_EVENT_MOD
update events
Definition: libmemif.h:94
int main(int argc, char *argv[])
Definition: main.c:98
memif_queue_details_t * tx_queues
Definition: libmemif.h:283
uint8_t * if_name
Definition: libmemif.h:270
uint16_t index
Definition: main.c:74
Memif buffer.
Definition: libmemif.h:211
#define MEMIF_FD_EVENT_WRITE
Definition: libmemif.h:88
uint16_t memif_get_version()
Memif get version.
Definition: main.c:174
memif_buffer_t * tx_bufs
Definition: main.c:80
Memif connection arguments.
Definition: libmemif.h:181
int user_input_handler()
Definition: main.c:1102
Memif details.
Definition: libmemif.h:268
uint8_t * remote_if_name
Definition: libmemif.h:272
memif_buffer_t * rx_bufs
Definition: main.c:85