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