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