FD.io VPP  v19.08.3-2-gbabecb413
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 <libmemif.h>
49 #include <icmp_proto.h>
50 
51 #define APP_NAME "ICMP_Responder"
52 #define IF_NAME "memif_connection"
53 
54 
55 #ifdef ICMP_DBG
56 #define DBG(...) do { \
57  printf (APP_NAME":%s:%d: ", __func__, __LINE__); \
58  printf (__VA_ARGS__); \
59  printf ("\n"); \
60  } while (0)
61 #else
62 #define DBG(...)
63 #endif
64 
65 #define INFO(...) do { \
66  printf ("INFO: "__VA_ARGS__); \
67  printf ("\n"); \
68  } while (0)
69 
70 /* maximum tx/rx memif buffers */
71 #define MAX_MEMIF_BUFS 256
72 #define MAX_CONNS 50
73 #define MAX_QUEUES 2
74 #define MAX_THREADS ((MAX_CONNS) * (MAX_QUEUES))
75 
77 
78 typedef struct
79 {
80  /* thread id */
81  uint8_t id;
82  /* memif connection index */
83  uint16_t index;
84  /* id of queue to be handled by thread */
85  uint8_t qid;
86  uint8_t isRunning;
87 
88  uint16_t rx_buf_num;
89  uint16_t tx_buf_num;
93 
94 typedef struct
95 {
96  uint16_t index;
97  /* memif conenction handle */
99  /* interface ip address */
100  uint8_t ip_addr[4];
101  /* inform pthread about connection termination */
102  uint8_t pending_del;
104 
105 memif_connection_t memif_connection[MAX_CONNS];
107 
108 /* thread data specific for each thread */
110 pthread_t thread[MAX_THREADS];
111 
112 void
114 {
115 }
116 
117 static void
119 {
120  memif_details_t md;
121  ssize_t buflen;
122  char *buf;
123  int err, i, e, ti;
124  buflen = 2048;
125  buf = malloc (buflen);
126  printf ("MEMIF DETAILS\n");
127  printf ("==============================\n");
128  for (i = 0; i < MAX_CONNS; i++)
129  {
130  memif_connection_t *c = &memif_connection[i];
131 
132  memset (&md, 0, sizeof (md));
133  memset (buf, 0, buflen);
134 
135  err = memif_get_details (c->conn, &md, buf, buflen);
136  if (err != MEMIF_ERR_SUCCESS)
137  {
138  if (err != MEMIF_ERR_NOCONN)
139  INFO ("%s", memif_strerror (err));
140  continue;
141  }
142 
143  printf ("interface index: %d\n", i);
144 
145  printf ("\tinterface ip: %u.%u.%u.%u\n",
146  c->ip_addr[0], c->ip_addr[1], c->ip_addr[2], c->ip_addr[3]);
147  printf ("\tinterface name: %s\n", (char *) md.if_name);
148  printf ("\tapp name: %s\n", (char *) md.inst_name);
149  printf ("\tremote interface name: %s\n", (char *) md.remote_if_name);
150  printf ("\tremote app name: %s\n", (char *) md.remote_inst_name);
151  printf ("\tid: %u\n", md.id);
152  printf ("\tsecret: %s\n", (char *) md.secret);
153  printf ("\trole: ");
154  if (md.role)
155  printf ("slave\n");
156  else
157  printf ("master\n");
158  printf ("\tmode: ");
159  switch (md.mode)
160  {
161  case 0:
162  printf ("ethernet\n");
163  break;
164  case 1:
165  printf ("ip\n");
166  break;
167  case 2:
168  printf ("punt/inject\n");
169  break;
170  default:
171  printf ("unknown\n");
172  break;
173  }
174  printf ("\tsocket filename: %s\n", (char *) md.socket_filename);
175  printf ("\trx queues:\n");
176  for (e = 0; e < md.rx_queues_num; e++)
177  {
178  ti = (i * MAX_QUEUES) + e;
179  printf ("\tqueue id: %u\n", md.rx_queues[e].qid);
180  printf ("\t\tring size: %u\n", md.rx_queues[e].ring_size);
181  printf ("\t\tbuffer size: %u\n", md.rx_queues[e].buffer_size);
182  printf ("\t\tthread id: %u\n", thread_data[ti].id);
183  printf ("\t\tthread connection index: %u\n", thread_data[ti].index);
184  printf ("\t\tthread running: ");
185  if (thread_data[ti].isRunning)
186  printf ("yes\n");
187  else
188  printf ("no");
189  }
190  printf ("\ttx queues:\n");
191  for (e = 0; e < md.tx_queues_num; e++)
192  {
193  printf ("\tqueue id: %u\n", md.tx_queues[e].qid);
194  printf ("\t\tring size: %u\n", md.tx_queues[e].ring_size);
195  printf ("\t\tbuffer size: %u\n", md.tx_queues[e].buffer_size);
196  }
197  printf ("\tlink: ");
198  if (md.link_up_down)
199  printf ("up\n");
200  else
201  printf ("down\n");
202  }
203  free (buf);
204 }
205 
206 int
207 add_epoll_fd (int epfd, int fd, uint32_t events)
208 {
209  if (fd < 0)
210  {
211  DBG ("invalid fd %d", fd);
212  return -1;
213  }
214  struct epoll_event evt;
215  memset (&evt, 0, sizeof (evt));
216  evt.events = events;
217  evt.data.fd = fd;
218  if (epoll_ctl (epfd, EPOLL_CTL_ADD, fd, &evt) < 0)
219  {
220  DBG ("epoll_ctl: %s fd %d", strerror (errno), fd);
221  return -1;
222  }
223  DBG ("fd %d added to epoll", fd);
224  return 0;
225 }
226 
227 int
228 mod_epoll_fd (int epfd, int fd, uint32_t events)
229 {
230  if (fd < 0)
231  {
232  DBG ("invalid fd %d", fd);
233  return -1;
234  }
235  struct epoll_event evt;
236  memset (&evt, 0, sizeof (evt));
237  evt.events = events;
238  evt.data.fd = fd;
239  if (epoll_ctl (epfd, EPOLL_CTL_MOD, fd, &evt) < 0)
240  {
241  DBG ("epoll_ctl: %s fd %d", strerror (errno), fd);
242  return -1;
243  }
244  DBG ("fd %d moddified on epoll", fd);
245  return 0;
246 }
247 
248 int
249 del_epoll_fd (int epfd, int fd)
250 {
251  if (fd < 0)
252  {
253  DBG ("invalid fd %d", fd);
254  return -1;
255  }
256  struct epoll_event evt;
257  memset (&evt, 0, sizeof (evt));
258  if (epoll_ctl (epfd, EPOLL_CTL_DEL, fd, &evt) < 0)
259  {
260  DBG ("epoll_ctl: %s fd %d", strerror (errno), fd);
261  return -1;
262  }
263  DBG ("fd %d removed from epoll", fd);
264  return 0;
265 }
266 
267 void *
268 memif_rx_poll (void *ptr)
269 {
271  memif_connection_t *c = &memif_connection[data->index];
272  int err;
273  uint16_t rx = 0, tx = 0, fb = 0;
274 
275  data->rx_bufs = malloc (sizeof (memif_buffer_t) * MAX_MEMIF_BUFS);
276  data->tx_bufs = malloc (sizeof (memif_buffer_t) * MAX_MEMIF_BUFS);
277  data->rx_buf_num = 0;
278  data->tx_buf_num = 0;
279 
280  data->isRunning = 1;
281  INFO ("pthread id %u starts in polling mode", data->id);
282 
283  while (1)
284  {
285  if (c->pending_del)
286  goto close;
287 
288  /* receive data from shared memory buffers */
289  err =
290  memif_rx_burst (c->conn, data->qid, data->rx_bufs, MAX_MEMIF_BUFS,
291  &rx);
292  if (err != MEMIF_ERR_SUCCESS)
293  {
294  INFO ("memif_rx_burst: %s", memif_strerror (err));
295  data->rx_buf_num += rx;
296  goto error;
297  }
298  data->rx_buf_num += rx;
299  if (rx == 0)
300  {
301  continue;
302  }
303 
304  DBG ("thread id: %u", data->id);
305 
306  DBG ("received %d buffers. %u/%u alloc/free buffers",
307  rx, data->rx_buf_num, MAX_MEMIF_BUFS - data->rx_buf_num);
308 
309  err =
310  memif_buffer_alloc (c->conn, data->qid, data->tx_bufs,
311  data->rx_buf_num, &tx, 0);
312  if (err != MEMIF_ERR_SUCCESS)
313  {
314  INFO ("memif_buffer_alloc: %s", memif_strerror (err));
315  data->tx_buf_num += tx;
316  goto error;
317  }
318  data->tx_buf_num += tx;
319  DBG ("allocated %d/%d buffers, %u free buffers",
320  tx, data->rx_buf_num, MAX_MEMIF_BUFS - data->tx_buf_num);
321 
322  int i;
323  for (i = 0; i < rx; i++)
324  {
325  resolve_packet ((void *) (data->rx_bufs + i)->data,
326  (data->rx_bufs + i)->len,
327  (void *) (data->tx_bufs + i)->data,
328  &(data->tx_bufs + i)->len, c->ip_addr);
329  }
330 
331  /* mark memif buffers and shared memory buffers as free */
332  err = memif_refill_queue (c->conn, data->qid, rx, 0);
333  if (err != MEMIF_ERR_SUCCESS)
334  INFO ("memif_buffer_free: %s", memif_strerror (err));
335  data->rx_buf_num -= fb;
336 
337  DBG ("freed %d buffers. %u/%u alloc/free buffers",
338  fb, data->rx_buf_num, MAX_MEMIF_BUFS - data->rx_buf_num);
339 
340  err =
341  memif_tx_burst (c->conn, data->qid, data->tx_bufs, data->tx_buf_num,
342  &tx);
343  if (err != MEMIF_ERR_SUCCESS)
344  {
345  INFO ("memif_tx_burst: %s", memif_strerror (err));
346  goto error;
347  }
348  DBG ("tx: %d/%u", tx, data->tx_buf_num);
349  data->tx_buf_num -= tx;
350  }
351 
352 error:
353  INFO ("thread %u error!", data->id);
354  goto close;
355 
356 close:
357  err = memif_refill_queue (c->conn, data->qid, rx, 0);
358  if (err != MEMIF_ERR_SUCCESS)
359  INFO ("memif_buffer_free: %s", memif_strerror (err));
360  data->rx_buf_num -= fb;
361  DBG ("freed %d buffers. %u/%u alloc/free buffers",
362  fb, data->rx_buf_num, MAX_MEMIF_BUFS - data->rx_buf_num);
363  free (data->rx_bufs);
364  free (data->tx_bufs);
365  data->isRunning = 0;
366  INFO ("pthread id %u exit", data->id);
367  pthread_exit (NULL);
368 }
369 
370 void *
372 {
374  memif_connection_t *c = &memif_connection[data->index];
375  int err;
376  uint16_t rx = 0, tx = 0, fb = 0;
377  struct epoll_event evt;
378  int en = 0;
379  sigset_t sigset;
380 
381  signal (SIGUSR1, user_signal_handler);
382 
383  data->rx_bufs = malloc (sizeof (memif_buffer_t) * MAX_MEMIF_BUFS);
384  data->tx_bufs = malloc (sizeof (memif_buffer_t) * MAX_MEMIF_BUFS);
385  data->rx_buf_num = 0;
386  data->tx_buf_num = 0;
387 
388  data->isRunning = 1;
389  INFO ("pthread id %u starts in interrupt mode", data->id);
390  int thread_epfd = epoll_create (1);
391 
392  /* get interrupt queue id */
393  int fd = -1;
394  err = memif_get_queue_efd (c->conn, data->qid, &fd);
395  if (err != MEMIF_ERR_SUCCESS)
396  {
397  INFO ("memif_get_queue_efd: %s", memif_strerror (err));
398  goto error;
399  }
400  add_epoll_fd (thread_epfd, fd, EPOLLIN);
401 
402  while (1)
403  {
404  memset (&evt, 0, sizeof (evt));
405  evt.events = EPOLLIN | EPOLLOUT;
406  sigemptyset (&sigset);
407  en = epoll_pwait (thread_epfd, &evt, 1, -1, &sigset);
408  if (en < 0)
409  {
410  if (errno == EINTR)
411  goto close;
412  DBG ("epoll_pwait: %s", strerror (errno));
413  goto error;
414  }
415  else if (en > 0)
416  {
417  /* receive data from shared memory buffers */
418  err =
419  memif_rx_burst (c->conn, data->qid, data->rx_bufs, MAX_MEMIF_BUFS,
420  &rx);
421  if (err != MEMIF_ERR_SUCCESS)
422  {
423  INFO ("memif_rx_burst: %s", memif_strerror (err));
424  data->rx_buf_num += rx;
425  goto error;
426  }
427  data->rx_buf_num += rx;
428  if (rx == 0)
429  {
430  continue;
431  }
432 
433  DBG ("thread id: %u", data->id);
434 
435  DBG ("received %d buffers. %u/%u alloc/free buffers",
436  rx, data->rx_buf_num, MAX_MEMIF_BUFS - data->rx_buf_num);
437 
438  err =
439  memif_buffer_alloc (c->conn, data->qid, data->tx_bufs,
440  data->rx_buf_num, &tx, 0);
441  if (err != MEMIF_ERR_SUCCESS)
442  {
443  INFO ("memif_buffer_alloc: %s", memif_strerror (err));
444  data->tx_buf_num += tx;
445  goto error;
446  }
447  data->tx_buf_num += tx;
448  DBG ("allocated %d/%d buffers, %u free buffers",
449  tx, data->rx_buf_num, MAX_MEMIF_BUFS - data->tx_buf_num);
450 
451  int i;
452  for (i = 0; i < rx; i++)
453  {
454  resolve_packet ((void *) (data->rx_bufs + i)->data,
455  (data->rx_bufs + i)->len,
456  (void *) (data->tx_bufs + i)->data,
457  &(data->tx_bufs + i)->len, c->ip_addr);
458  }
459 
460  /* mark memif buffers and shared memory buffers as free */
461  err = memif_refill_queue (c->conn, data->qid, rx, 0);
462  if (err != MEMIF_ERR_SUCCESS)
463  INFO ("memif_buffer_free: %s", memif_strerror (err));
464  data->rx_buf_num -= fb;
465 
466  DBG ("freed %d buffers. %u/%u alloc/free buffers",
467  fb, data->rx_buf_num, MAX_MEMIF_BUFS - data->rx_buf_num);
468 
469  err =
470  memif_tx_burst (c->conn, data->qid, data->tx_bufs,
471  data->tx_buf_num, &tx);
472  if (err != MEMIF_ERR_SUCCESS)
473  {
474  INFO ("memif_tx_burst: %s", memif_strerror (err));
475  goto error;
476  }
477  DBG ("tx: %d/%u", tx, data->tx_buf_num);
478  data->tx_buf_num -= tx;
479  }
480  }
481 
482 error:
483  INFO ("thread %u error!", data->id);
484  goto close;
485 
486 close:
487  err = memif_refill_queue (c->conn, data->qid, rx, 0);
488  if (err != MEMIF_ERR_SUCCESS)
489  INFO ("memif_buffer_free: %s", memif_strerror (err));
490  data->rx_buf_num -= fb;
491  DBG ("freed %d buffers. %u/%u alloc/free buffers",
492  fb, data->rx_buf_num, MAX_MEMIF_BUFS - data->rx_buf_num);
493  free (data->rx_bufs);
494  free (data->tx_bufs);
495  data->isRunning = 0;
496  INFO ("pthread id %u exit", data->id);
497  pthread_exit (NULL);
498 
499 }
500 
501 /* informs user about connected status. private_ctx is used by user to identify connection
502  (multiple connections WIP) */
503 int
504 on_connect (memif_conn_handle_t conn, void *private_ctx)
505 {
506  long index = (*(long *) private_ctx);
507  int err, i, ti;
508  INFO ("memif connected! index %ld", index);
509  memif_connection_t *c = &memif_connection[index];
510  c->pending_del = 0;
511 
512  for (i = 0; i < MAX_QUEUES; i++)
513  {
515  if (err != MEMIF_ERR_SUCCESS)
516  INFO ("memif_set_rx_mode: %s qid: %u", memif_strerror (err), i);
517  else
518  {
519  ti = (index * MAX_QUEUES) + i;
520  if (thread_data[ti].isRunning)
521  {
522  INFO ("thread id: %d already running!", ti);
523  continue;
524  }
525  thread_data[ti].index = index;
526  thread_data[ti].qid = i;
527  thread_data[ti].id = ti;
528  if ((i % 2) == 0)
529  pthread_create (&thread[ti],
530  NULL, memif_rx_poll, (void *) &thread_data[ti]);
531  else
532  pthread_create (&thread[ti],
533  NULL, memif_rx_interrupt,
534  (void *) &thread_data[ti]);
535  }
536 
537  }
538  return 0;
539 }
540 
541 /* informs user about disconnected status. private_ctx is used by user to identify connection
542  (multiple connections WIP) */
543 int
544 on_disconnect (memif_conn_handle_t conn, void *private_ctx)
545 {
546  void *ptr;
547  long index = (*(long *) private_ctx);
548  memif_connection_t *c = &memif_connection[index];
549  int i, ti;
550  INFO ("memif disconnected!");
551  /* inform thread in polling mode about memif disconenction */
552  c->pending_del = 1;
553  for (i = 0; i < MAX_QUEUES; i++)
554  {
555  ti = (index * MAX_QUEUES) + i;
556  if (!thread_data[ti].isRunning)
557  continue;
558  if ((i % 2) != 0)
559  pthread_kill (thread[ti], SIGUSR1); /* interrupt thread in interrupt mode */
560  pthread_join (thread[ti], &ptr);
561  }
562  return 0;
563 }
564 
565 /* user needs to watch new fd or stop watching fd that is about to be closed.
566  control fd will be modified during connection establishment to minimize CPU usage */
567 int
568 control_fd_update (int fd, uint8_t events, void *ctx)
569 {
570  /* convert memif event definitions to epoll events */
571  if (events & MEMIF_FD_EVENT_DEL)
572  return del_epoll_fd (main_epfd, fd);
573 
574  uint32_t evt = 0;
575  if (events & MEMIF_FD_EVENT_READ)
576  evt |= EPOLLIN;
577  if (events & MEMIF_FD_EVENT_WRITE)
578  evt |= EPOLLOUT;
579 
580  if (events & MEMIF_FD_EVENT_MOD)
581  return mod_epoll_fd (main_epfd, fd, evt);
582 
583  return add_epoll_fd (main_epfd, fd, evt);
584 }
585 
586 int
587 icmpr_memif_create (long index)
588 {
589  if (index >= MAX_CONNS)
590  {
591  INFO ("connection array overflow");
592  return 0;
593  }
594  if (index < 0)
595  {
596  INFO ("don't even try...");
597  return 0;
598  }
599  memif_connection_t *c = &memif_connection[index];
600 
601  /* setting memif connection arguments */
602  memif_conn_args_t args;
603  memset (&args, 0, sizeof (args));
604  args.is_master = 0;
605  args.log2_ring_size = 10;
606  args.buffer_size = 2048;
607  args.num_s2m_rings = 2;
608  args.num_m2s_rings = 2;
609  strncpy ((char *) args.interface_name, IF_NAME, strlen (IF_NAME));
610  args.mode = 0;
611  /* socket filename is not specified, because this app is supposed to
612  connect to VPP over memif. so default socket filename will be used */
613  /* default socketfile = /run/vpp/memif.sock */
614 
615  args.interface_id = index;
616  /* last argument for memif_create (void * private_ctx) is used by user
617  to identify connection. this context is returned with callbacks */
618  int err = memif_create (&c->conn,
619  &args, on_connect, on_disconnect, NULL,
620  &ctx[index]);
621  if (err != MEMIF_ERR_SUCCESS)
622  {
623  INFO ("memif_create: %s", memif_strerror (err));
624  return 0;
625  }
626 
627  c->index = index;
628 
629  c->ip_addr[0] = 192;
630  c->ip_addr[1] = 168;
631  c->ip_addr[2] = c->index + 1;
632  c->ip_addr[3] = 2;
633  return 0;
634 }
635 
636 int
637 icmpr_memif_delete (long index)
638 {
639  if (index >= MAX_CONNS)
640  {
641  INFO ("connection array overflow");
642  return 0;
643  }
644  if (index < 0)
645  {
646  INFO ("don't even try...");
647  return 0;
648  }
649  memif_connection_t *c = &memif_connection[index];
650 
651  int err;
652  /* disconenct then delete memif connection */
653  err = memif_delete (&c->conn);
654  if (err != MEMIF_ERR_SUCCESS)
655  INFO ("memif_delete: %s", memif_strerror (err));
656  return 0;
657 }
658 
659 void
661 {
662  printf ("LIBMEMIF EXAMPLE APP: %s", APP_NAME);
663 #ifdef ICMP_DBG
664  printf (" (debug)");
665 #endif
666  printf ("\n");
667  printf ("==============================\n");
668  printf ("libmemif version: %s", LIBMEMIF_VERSION);
669 #ifdef MEMIF_DBG
670  printf (" (debug)");
671 #endif
672  printf ("\n");
673  printf ("memif version: %d\n", memif_get_version ());
674  printf ("commands:\n");
675  printf ("\thelp - prints this help\n");
676  printf ("\texit - exit app\n");
677  printf ("\tconn <index> - create memif (slave-mode)\n");
678  printf ("\tdel <index> - delete memif\n");
679  printf ("\tshow - show connection details\n");
680  printf ("\tip-set <index> <ip-addr> - set interface ip address\n");
681 }
682 
683 int
685 {
686  /* application cleanup */
687  int err;
688  long i;
689  for (i = 0; i < MAX_CONNS; i++)
690  {
691  memif_connection_t *c = &memif_connection[i];
692  if (c->conn)
693  icmpr_memif_delete (i);
694  }
695 
696  err = memif_cleanup ();
697  if (err != MEMIF_ERR_SUCCESS)
698  INFO ("memif_delete: %s", memif_strerror (err));
699 
700  return 0;
701 }
702 
703 int
704 icmpr_set_ip (long index, char *ip)
705 {
706  if (index >= MAX_CONNS)
707  {
708  INFO ("connection array overflow");
709  return 0;
710  }
711  if (index < 0)
712  {
713  INFO ("don't even try...");
714  return 0;
715  }
716  memif_connection_t *c = &memif_connection[index];
717  if (c->conn == NULL)
718  {
719  INFO ("no connection at index %ld", index);
720  return 0;
721  }
722 
723  char *end;
724  char *ui;
725  uint8_t tmp[4];
726  ui = strtok (ip, ".");
727  if (ui == NULL)
728  goto error;
729  tmp[0] = strtol (ui, &end, 10);
730 
731  ui = strtok (NULL, ".");
732  if (ui == NULL)
733  goto error;
734  tmp[1] = strtol (ui, &end, 10);
735 
736  ui = strtok (NULL, ".");
737  if (ui == NULL)
738  goto error;
739  tmp[2] = strtol (ui, &end, 10);
740 
741  ui = strtok (NULL, ".");
742  if (ui == NULL)
743  goto error;
744  tmp[3] = strtol (ui, &end, 10);
745 
746  c->ip_addr[0] = tmp[0];
747  c->ip_addr[1] = tmp[1];
748  c->ip_addr[2] = tmp[2];
749  c->ip_addr[3] = tmp[3];
750 
751  INFO ("memif %ld ip address set to %u.%u.%u.%u",
752  index, c->ip_addr[0], c->ip_addr[1], c->ip_addr[2], c->ip_addr[3]);
753 
754  return 0;
755 
756 error:
757  INFO ("invalid ip address");
758  return 0;
759 }
760 
761 
762 int
764 {
765  char *in = (char *) malloc (256);
766  char *ui = fgets (in, 256, stdin);
767  char *end;
768  if (in[0] == '\n')
769  goto done;
770  ui = strtok (in, " ");
771  if (strncmp (ui, "exit", 4) == 0)
772  {
773  free (in);
774  icmpr_free ();
775  exit (EXIT_SUCCESS);
776  }
777  else if (strncmp (ui, "help", 4) == 0)
778  {
779  print_help ();
780  goto done;
781  }
782  else if (strncmp (ui, "conn", 4) == 0)
783  {
784  ui = strtok (NULL, " ");
785  if (ui != NULL)
786  icmpr_memif_create (strtol (ui, &end, 10));
787  else
788  INFO ("expected id");
789  goto done;
790  }
791  else if (strncmp (ui, "del", 3) == 0)
792  {
793  ui = strtok (NULL, " ");
794  if (ui != NULL)
795  icmpr_memif_delete (strtol (ui, &end, 10));
796  else
797  INFO ("expected id");
798  goto done;
799  }
800  else if (strncmp (ui, "show", 4) == 0)
801  {
803  goto done;
804  }
805  else if (strncmp (ui, "ip-set", 6) == 0)
806  {
807  ui = strtok (NULL, " ");
808  if (ui != NULL)
809  icmpr_set_ip (strtol (ui, &end, 10), strtok (NULL, " "));
810  else
811  INFO ("expected id");
812  goto done;
813  }
814  else
815  {
816  DBG ("unknown command: %s", ui);
817  goto done;
818  }
819 
820  return 0;
821 done:
822  free (in);
823  return 0;
824 }
825 
826 int
827 poll_event (int timeout)
828 {
829  struct epoll_event evt;
830  int app_err = 0, memif_err = 0, en = 0;
831  uint32_t events = 0;
832  memset (&evt, 0, sizeof (evt));
833  evt.events = EPOLLIN | EPOLLOUT;
834  sigset_t sigset;
835  sigemptyset (&sigset);
836  en = epoll_pwait (main_epfd, &evt, 1, timeout, &sigset);
837  if (en < 0)
838  {
839  DBG ("epoll_pwait: %s", strerror (errno));
840  return -1;
841  }
842  if (en > 0)
843  {
844  /* this app does not use any other file descriptors than stds and memif control fds */
845  if (evt.data.fd > 2)
846  {
847  /* event of memif control fd */
848  /* convert epolle events to memif events */
849  if (evt.events & EPOLLIN)
850  events |= MEMIF_FD_EVENT_READ;
851  if (evt.events & EPOLLOUT)
852  events |= MEMIF_FD_EVENT_WRITE;
853  if (evt.events & EPOLLERR)
854  events |= MEMIF_FD_EVENT_ERROR;
855  memif_err = memif_control_fd_handler (evt.data.fd, events);
856  if (memif_err != MEMIF_ERR_SUCCESS)
857  INFO ("memif_control_fd_handler: %s", memif_strerror (memif_err));
858  }
859  else if (evt.data.fd == 0)
860  {
861  app_err = user_input_handler ();
862  }
863  else
864  {
865  DBG ("unexpected event at memif_epfd. fd %d", evt.data.fd);
866  }
867  }
868 
869  if ((app_err < 0) || (memif_err < 0))
870  {
871  if (app_err < 0)
872  DBG ("user input handler error");
873  if (memif_err < 0)
874  DBG ("memif control fd handler error");
875  return -1;
876  }
877 
878  return 0;
879 }
880 
881 int
883 {
884  main_epfd = epoll_create (1);
885  add_epoll_fd (main_epfd, 0, EPOLLIN);
886 
887  /* initialize memory interface */
888  int err, i;
889  /* if valid callback is passed as argument, fd event polling will be done by user
890  all file descriptors and events will be passed to user in this callback */
891  /* if callback is set to NULL libmemif will handle fd event polling */
892  err = memif_init (control_fd_update, APP_NAME, NULL, NULL, NULL);
893  if (err != MEMIF_ERR_SUCCESS)
894  INFO ("memif_init: %s", memif_strerror (err));
895 
896  for (i = 0; i < MAX_CONNS; i++)
897  {
898  memif_connection[i].conn = NULL;
899  ctx[i] = i;
900  }
901 
902  memset (&thread_data, 0, sizeof (memif_thread_data_t) * MAX_THREADS);
903 
904  print_help ();
905 
906  /* main loop */
907  while (1)
908  {
909  if (poll_event (-1) < 0)
910  {
911  DBG ("poll_event error!");
912  }
913  }
914 }
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
uint8_t * inst_name
Definition: libmemif.h:404
uint8_t pending_del
Definition: main.c:102
uint8_t * secret
Definition: libmemif.h:409
uint8_t id
Definition: main.c:81
int on_disconnect(memif_conn_handle_t conn, void *private_ctx)
Definition: main.c:186
#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:89
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.
void user_signal_handler(int sig)
Definition: main.c:113
memif_buffer_t * tx_bufs
Definition: main.c:91
uint16_t buffer_size
Definition: libmemif.h:300
uint32_t interface_id
Definition: libmemif.h:304
uint8_t qid
Definition: main.c:85
int i
uint16_t index
Definition: main.c:83
u8 data[128]
Definition: ipsec.api:251
static void print_memif_details()
Definition: main.c:118
int icmpr_set_ip(long index, char *ip)
Definition: main.c:803
uint8_t * remote_inst_name
Definition: libmemif.h:406
int poll_event(int timeout)
Definition: main.c:975
#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
#define INFO(...)
Definition: main.c:65
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
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
memif_interface_mode_t mode
Definition: libmemif.h:306
uint8_t mode
Definition: libmemif.h:411
memif_buffer_t * rx_bufs
Definition: main.c:90
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
#define MAX_THREADS
Definition: main.c:74
memif_conn_handle_t conn
Definition: main.c:76
uint8_t isRunning
Definition: main.c:86
pthread_t thread[MAX_CONNS]
Definition: main.c:142
uint8_t ip_addr[4]
Definition: main.c:90
uint8_t interface_name[32]
Definition: libmemif.h:305
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
uint16_t rx_buf_num
Definition: main.c:88
#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
#define MAX_MEMIF_BUFS
Definition: main.c:71
#define APP_NAME
Definition: main.c:51
uint8_t is_master
Definition: libmemif.h:302
uint8_t rx_queues_num
Definition: libmemif.h:415
#define MAX_CONNS
Definition: main.c:72
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
int memif_get_queue_efd(memif_conn_handle_t conn, uint16_t qid, int *efd)
Memif get queue event file descriptor
Definition: main.c:2738
#define MAX_QUEUES
Definition: main.c:73
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
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
#define DBG(...)
Definition: main.c:62
memif_queue_details_t * rx_queues
Definition: libmemif.h:417
uint8_t role
Definition: libmemif.h:410
void * memif_rx_poll(void *ptr)
Definition: main.c:268
int memif_cleanup()
Memif cleanup.
Definition: main.c:2761
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
void * memif_rx_interrupt(void *ptr)
Definition: main.c:371
uint8_t tx_queues_num
Definition: libmemif.h:416
void * memif_conn_handle_t
Memif connection handle pointer of type void, pointing to internal structure.
Definition: libmemif.h:108
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:489
int mod_epoll_fd(int fd, uint32_t events)
Definition: main.c:323
uint8_t log2_ring_size
Definition: libmemif.h:301
int epfd
Definition: main.c:94
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
int memif_delete(memif_conn_handle_t *conn)
Memif delete.
Definition: main.c:1816
#define IF_NAME
Definition: main.c:52
#define MEMIF_FD_EVENT_ERROR
inform libmemif that error occured 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:100
memif_queue_details_t * tx_queues
Definition: libmemif.h:418
uint8_t * if_name
Definition: libmemif.h:403
uint16_t tx_buf_num
Definition: main.c:89
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 connection arguments.
Definition: libmemif.h:293
Memif details.
Definition: libmemif.h:401
uint8_t * remote_if_name
Definition: libmemif.h:405
int main_epfd
Definition: main.c:76