FD.io VPP  v18.01-8-g0eacf49
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)->data_len,
328  (void *) (data->tx_bufs + i)->data,
329  &(data->tx_bufs + i)->data_len, c->ip_addr);
330  }
331 
332  /* mark memif buffers and shared memory buffers as free */
333  err = memif_buffer_free (c->conn, data->qid, data->rx_bufs, rx, &fb);
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_buffer_free (c->conn, data->qid, data->rx_bufs, rx, &fb);
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)->data_len,
458  (void *) (data->tx_bufs + i)->data,
459  &(data->tx_bufs + i)->data_len, c->ip_addr);
460  }
461 
462  /* mark memif buffers and shared memory buffers as free */
463  err =
464  memif_buffer_free (c->conn, data->qid, data->rx_bufs, rx, &fb);
465  if (err != MEMIF_ERR_SUCCESS)
466  INFO ("memif_buffer_free: %s", memif_strerror (err));
467  data->rx_buf_num -= fb;
468 
469  DBG ("freed %d buffers. %u/%u alloc/free buffers",
470  fb, data->rx_buf_num, MAX_MEMIF_BUFS - data->rx_buf_num);
471 
472  err =
473  memif_tx_burst (c->conn, data->qid, data->tx_bufs,
474  data->tx_buf_num, &tx);
475  if (err != MEMIF_ERR_SUCCESS)
476  {
477  INFO ("memif_tx_burst: %s", memif_strerror (err));
478  goto error;
479  }
480  DBG ("tx: %d/%u", tx, data->tx_buf_num);
481  data->tx_buf_num -= tx;
482  }
483  }
484 
485 error:
486  INFO ("thread %u error!", data->id);
487  goto close;
488 
489 close:
490  err = memif_buffer_free (c->conn, data->qid, data->rx_bufs, rx, &fb);
491  if (err != MEMIF_ERR_SUCCESS)
492  INFO ("memif_buffer_free: %s", memif_strerror (err));
493  data->rx_buf_num -= fb;
494  DBG ("freed %d buffers. %u/%u alloc/free buffers",
495  fb, data->rx_buf_num, MAX_MEMIF_BUFS - data->rx_buf_num);
496  free (data->rx_bufs);
497  free (data->tx_bufs);
498  data->isRunning = 0;
499  INFO ("pthread id %u exit", data->id);
500  pthread_exit (NULL);
501 
502 }
503 
504 /* informs user about connected status. private_ctx is used by user to identify connection
505  (multiple connections WIP) */
506 int
507 on_connect (memif_conn_handle_t conn, void *private_ctx)
508 {
509  long index = (*(long *) private_ctx);
510  int err, i, ti;
511  INFO ("memif connected! index %ld", index);
512  memif_connection_t *c = &memif_connection[index];
513  c->pending_del = 0;
514 
515  for (i = 0; i < MAX_QUEUES; i++)
516  {
518  if (err != MEMIF_ERR_SUCCESS)
519  INFO ("memif_set_rx_mode: %s qid: %u", memif_strerror (err), i);
520  else
521  {
522  ti = (index * MAX_QUEUES) + i;
523  if (thread_data[ti].isRunning)
524  {
525  INFO ("thread id: %d already running!", ti);
526  continue;
527  }
528  thread_data[ti].index = index;
529  thread_data[ti].qid = i;
530  thread_data[ti].id = ti;
531  if ((i % 2) == 0)
532  pthread_create (&thread[ti],
533  NULL, memif_rx_poll, (void *) &thread_data[ti]);
534  else
535  pthread_create (&thread[ti],
537  (void *) &thread_data[ti]);
538  }
539 
540  }
541  return 0;
542 }
543 
544 /* informs user about disconnected status. private_ctx is used by user to identify connection
545  (multiple connections WIP) */
546 int
547 on_disconnect (memif_conn_handle_t conn, void *private_ctx)
548 {
549  void *ptr;
550  long index = (*(long *) private_ctx);
551  memif_connection_t *c = &memif_connection[index];
552  int i, ti;
553  INFO ("memif disconnected!");
554  /* inform thread in polling mode about memif disconenction */
555  c->pending_del = 1;
556  for (i = 0; i < MAX_QUEUES; i++)
557  {
558  ti = (index * MAX_QUEUES) + i;
559  if (!thread_data[ti].isRunning)
560  continue;
561  if ((i % 2) != 0)
562  pthread_kill (thread[ti], SIGUSR1); /* interrupt thread in interrupt mode */
563  pthread_join (thread[ti], &ptr);
564  }
565  return 0;
566 }
567 
568 /* user needs to watch new fd or stop watching fd that is about to be closed.
569  control fd will be modified during connection establishment to minimize CPU usage */
570 int
571 control_fd_update (int fd, uint8_t events)
572 {
573  /* convert memif event definitions to epoll events */
574  if (events & MEMIF_FD_EVENT_DEL)
575  return del_epoll_fd (main_epfd, fd);
576 
577  uint32_t evt = 0;
578  if (events & MEMIF_FD_EVENT_READ)
579  evt |= EPOLLIN;
580  if (events & MEMIF_FD_EVENT_WRITE)
581  evt |= EPOLLOUT;
582 
583  if (events & MEMIF_FD_EVENT_MOD)
584  return mod_epoll_fd (main_epfd, fd, evt);
585 
586  return add_epoll_fd (main_epfd, fd, evt);
587 }
588 
589 int
590 icmpr_memif_create (long index)
591 {
592  if (index >= MAX_CONNS)
593  {
594  INFO ("connection array overflow");
595  return 0;
596  }
597  if (index < 0)
598  {
599  INFO ("don't even try...");
600  return 0;
601  }
602  memif_connection_t *c = &memif_connection[index];
603 
604  /* setting memif connection arguments */
605  memif_conn_args_t args;
606  int fd = -1;
607  memset (&args, 0, sizeof (args));
608  args.is_master = 0;
609  args.log2_ring_size = 10;
610  args.buffer_size = 2048;
611  args.num_s2m_rings = 2;
612  args.num_m2s_rings = 2;
613  strncpy ((char *) args.interface_name, IF_NAME, strlen (IF_NAME));
614  strncpy ((char *) args.instance_name, APP_NAME, strlen (APP_NAME));
615  args.mode = 0;
616  /* socket filename is not specified, because this app is supposed to
617  connect to VPP over memif. so default socket filename will be used */
618  /* default socketfile = /run/vpp/memif.sock */
619 
620  args.interface_id = index;
621  /* last argument for memif_create (void * private_ctx) is used by user
622  to identify connection. this context is returned with callbacks */
623  int err = memif_create (&c->conn,
624  &args, on_connect, on_disconnect, NULL,
625  &ctx[index]);
626  if (err != MEMIF_ERR_SUCCESS)
627  {
628  INFO ("memif_create: %s", memif_strerror (err));
629  return 0;
630  }
631 
632  c->index = index;
633 
634  c->ip_addr[0] = 192;
635  c->ip_addr[1] = 168;
636  c->ip_addr[2] = c->index + 1;
637  c->ip_addr[3] = 2;
638  return 0;
639 }
640 
641 int
642 icmpr_memif_delete (long index)
643 {
644  if (index >= MAX_CONNS)
645  {
646  INFO ("connection array overflow");
647  return 0;
648  }
649  if (index < 0)
650  {
651  INFO ("don't even try...");
652  return 0;
653  }
654  memif_connection_t *c = &memif_connection[index];
655 
656  int err;
657  /* disconenct then delete memif connection */
658  err = memif_delete (&c->conn);
659  if (err != MEMIF_ERR_SUCCESS)
660  INFO ("memif_delete: %s", memif_strerror (err));
661  return 0;
662 }
663 
664 void
666 {
667  printf ("LIBMEMIF EXAMPLE APP: %s", APP_NAME);
668 #ifdef ICMP_DBG
669  printf (" (debug)");
670 #endif
671  printf ("\n");
672  printf ("==============================\n");
673  printf ("libmemif version: %s", LIBMEMIF_VERSION);
674 #ifdef MEMIF_DBG
675  printf (" (debug)");
676 #endif
677  printf ("\n");
678  printf ("memif version: %d\n", MEMIF_VERSION);
679  printf ("commands:\n");
680  printf ("\thelp - prints this help\n");
681  printf ("\texit - exit app\n");
682  printf ("\tconn <index> - create memif (slave-mode)\n");
683  printf ("\tdel <index> - delete memif\n");
684  printf ("\tshow - show connection details\n");
685  printf ("\tip-set <index> <ip-addr> - set interface ip address\n");
686 }
687 
688 int
690 {
691  /* application cleanup */
692  int err;
693  long i;
694  for (i = 0; i < MAX_CONNS; i++)
695  {
696  memif_connection_t *c = &memif_connection[i];
697  if (c->conn)
698  icmpr_memif_delete (i);
699  }
700 
701  err = memif_cleanup ();
702  if (err != MEMIF_ERR_SUCCESS)
703  INFO ("memif_delete: %s", memif_strerror (err));
704 
705  return 0;
706 }
707 
708 int
709 icmpr_set_ip (long index, char *ip)
710 {
711  if (index >= MAX_CONNS)
712  {
713  INFO ("connection array overflow");
714  return 0;
715  }
716  if (index < 0)
717  {
718  INFO ("don't even try...");
719  return 0;
720  }
721  memif_connection_t *c = &memif_connection[index];
722  if (c->conn == NULL)
723  {
724  INFO ("no connection at index %ld", index);
725  return 0;
726  }
727 
728  char *end;
729  char *ui;
730  uint8_t tmp[4];
731  ui = strtok (ip, ".");
732  if (ui == NULL)
733  goto error;
734  tmp[0] = strtol (ui, &end, 10);
735 
736  ui = strtok (NULL, ".");
737  if (ui == NULL)
738  goto error;
739  tmp[1] = strtol (ui, &end, 10);
740 
741  ui = strtok (NULL, ".");
742  if (ui == NULL)
743  goto error;
744  tmp[2] = strtol (ui, &end, 10);
745 
746  ui = strtok (NULL, ".");
747  if (ui == NULL)
748  goto error;
749  tmp[3] = strtol (ui, &end, 10);
750 
751  c->ip_addr[0] = tmp[0];
752  c->ip_addr[1] = tmp[1];
753  c->ip_addr[2] = tmp[2];
754  c->ip_addr[3] = tmp[3];
755 
756  INFO ("memif %ld ip address set to %u.%u.%u.%u",
757  index, c->ip_addr[0], c->ip_addr[1], c->ip_addr[2], c->ip_addr[3]);
758 
759  return 0;
760 
761 error:
762  INFO ("invalid ip address");
763  return 0;
764 }
765 
766 
767 int
769 {
770  int i;
771  char *in = (char *) malloc (256);
772  char *ui = fgets (in, 256, stdin);
773  char *end;
774  if (in[0] == '\n')
775  goto done;
776  ui = strtok (in, " ");
777  if (strncmp (ui, "exit", 4) == 0)
778  {
779  free (in);
780  icmpr_free ();
781  exit (EXIT_SUCCESS);
782  }
783  else if (strncmp (ui, "help", 4) == 0)
784  {
785  print_help ();
786  goto done;
787  }
788  else if (strncmp (ui, "conn", 4) == 0)
789  {
790  ui = strtok (NULL, " ");
791  if (ui != NULL)
792  icmpr_memif_create (strtol (ui, &end, 10));
793  else
794  INFO ("expected id");
795  goto done;
796  }
797  else if (strncmp (ui, "del", 3) == 0)
798  {
799  ui = strtok (NULL, " ");
800  if (ui != NULL)
801  icmpr_memif_delete (strtol (ui, &end, 10));
802  else
803  INFO ("expected id");
804  goto done;
805  }
806  else if (strncmp (ui, "show", 4) == 0)
807  {
809  goto done;
810  }
811  else if (strncmp (ui, "ip-set", 6) == 0)
812  {
813  ui = strtok (NULL, " ");
814  if (ui != NULL)
815  icmpr_set_ip (strtol (ui, &end, 10), strtok (NULL, " "));
816  else
817  INFO ("expected id");
818  goto done;
819  }
820  else
821  {
822  DBG ("unknown command: %s", ui);
823  goto done;
824  }
825 
826  return 0;
827 done:
828  free (in);
829  return 0;
830 }
831 
832 int
833 poll_event (int timeout)
834 {
835  struct epoll_event evt, *e;
836  int app_err = 0, memif_err = 0, en = 0;
837  int tmp, nfd;
838  uint32_t events = 0;
839  memset (&evt, 0, sizeof (evt));
840  evt.events = EPOLLIN | EPOLLOUT;
841  sigset_t sigset;
842  sigemptyset (&sigset);
843  en = epoll_pwait (main_epfd, &evt, 1, timeout, &sigset);
844  if (en < 0)
845  {
846  DBG ("epoll_pwait: %s", strerror (errno));
847  return -1;
848  }
849  if (en > 0)
850  {
851  /* this app does not use any other file descriptors than stds and memif control fds */
852  if (evt.data.fd > 2)
853  {
854  /* event of memif control fd */
855  /* convert epolle events to memif events */
856  if (evt.events & EPOLLIN)
857  events |= MEMIF_FD_EVENT_READ;
858  if (evt.events & EPOLLOUT)
859  events |= MEMIF_FD_EVENT_WRITE;
860  if (evt.events & EPOLLERR)
861  events |= MEMIF_FD_EVENT_ERROR;
862  memif_err = memif_control_fd_handler (evt.data.fd, events);
863  if (memif_err != MEMIF_ERR_SUCCESS)
864  INFO ("memif_control_fd_handler: %s", memif_strerror (memif_err));
865  }
866  else if (evt.data.fd == 0)
867  {
868  app_err = user_input_handler ();
869  }
870  else
871  {
872  DBG ("unexpected event at memif_epfd. fd %d", evt.data.fd);
873  }
874  }
875 
876  if ((app_err < 0) || (memif_err < 0))
877  {
878  if (app_err < 0)
879  DBG ("user input handler error");
880  if (memif_err < 0)
881  DBG ("memif control fd handler error");
882  return -1;
883  }
884 
885  return 0;
886 }
887 
888 int
890 {
891  main_epfd = epoll_create (1);
892  add_epoll_fd (main_epfd, 0, EPOLLIN);
893 
894  /* initialize memory interface */
895  int err, i;
896  /* if valid callback is passed as argument, fd event polling will be done by user
897  all file descriptors and events will be passed to user in this callback */
898  /* if callback is set to NULL libmemif will handle fd event polling */
900  if (err != MEMIF_ERR_SUCCESS)
901  INFO ("memif_init: %s", memif_strerror (err));
902 
903  for (i = 0; i < MAX_CONNS; i++)
904  {
905  memif_connection[i].conn = NULL;
906  ctx[i] = i;
907  }
908 
909  memset (&thread_data, 0, sizeof (memif_thread_data_t) * MAX_THREADS);
910 
911  print_help ();
912 
913  /* main loop */
914  while (1)
915  {
916  if (poll_event (-1) < 0)
917  {
918  DBG ("poll_event error!");
919  }
920  }
921 }
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
int icmpr_memif_delete()
Definition: main.c:193
memif_log2_ring_size_t log2_ring_size
Definition: libmemif.h:167
int mod_epoll_fd(int fd, uint32_t events)
Definition: main.c:236
void print_help()
Definition: main.c:204
uint8_t * inst_name
Definition: libmemif.h:244
uint8_t pending_del
Definition: main.c:102
uint8_t * secret
Definition: libmemif.h:249
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:165
int control_fd_update(int fd, uint8_t events)
Definition: main.c:297
void user_signal_handler(int sig)
Definition: main.c:113
memif_buffer_t * tx_bufs
Definition: main.c:91
#define NULL
Definition: clib.h:55
uint16_t buffer_size
Definition: libmemif.h:166
memif_interface_id_t interface_id
Definition: libmemif.h:170
uint8_t qid
Definition: main.c:85
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:822
uint8_t * remote_inst_name
Definition: libmemif.h:246
pthread_t thread[MAX_CONNS]
Definition: main.c:121
#define LIBMEMIF_VERSION
Libmemif version.
Definition: libmemif.h:26
#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:164
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:1948
memif_interface_mode_t mode
Definition: libmemif.h:173
int memif_buffer_free(memif_conn_handle_t conn, uint16_t qid, memif_buffer_t *bufs, uint16_t count, uint16_t *count_out)
Memif buffer free.
Definition: main.c:1491
uint8_t mode
Definition: libmemif.h:251
memif_buffer_t * rx_bufs
Definition: main.c:90
uint8_t link_up_down
Definition: libmemif.h:258
char * memif_strerror(int err_code)
Memif strerror.
Definition: main.c:153
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
int del_epoll_fd(int fd)
Definition: main.c:257
uint8_t ip_addr[4]
Definition: main.c:90
uint8_t interface_name[32]
Definition: libmemif.h:171
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:207
uint16_t buffer_size
Definition: libmemif.h:222
uint8_t * socket_filename
Definition: libmemif.h:252
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:520
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:168
uint8_t rx_queues_num
Definition: libmemif.h:253
#define MAX_CONNS
Definition: main.c:72
int memif_get_queue_efd(memif_conn_handle_t conn, uint16_t qid, int *efd)
Memif get queue event file descriptor
Definition: main.c:2074
#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:1562
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:1380
#define DBG(...)
Definition: main.c:62
int add_epoll_fd(int fd, uint32_t events)
Definition: main.c:215
memif_queue_details_t * rx_queues
Definition: libmemif.h:255
uint8_t role
Definition: libmemif.h:250
void * memif_rx_poll(void *ptr)
Definition: main.c:269
uint8_t instance_name[32]
Definition: libmemif.h:172
int memif_cleanup()
Memif cleanup.
Definition: main.c:2094
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:538
void * memif_rx_interrupt(void *ptr)
Definition: main.c:372
long ctx[MAX_CONNS]
Definition: main.c:122
#define MEMIF_VERSION
Definition: memif.h:28
int poll_event(int timeout)
Definition: main.c:1235
uint8_t tx_queues_num
Definition: libmemif.h:254
void * memif_conn_handle_t
*brief 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:787
int epfd
Definition: main.c:94
int memif_init(memif_control_fd_update_t *on_control_fd_update, char *app_name)
Memif initialization.
Definition: main.c:405
uint32_t id
Definition: libmemif.h:248
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:1785
int memif_delete(memif_conn_handle_t *conn)
Memif delete.
Definition: main.c:1111
#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:56
memif_queue_details_t * tx_queues
Definition: libmemif.h:256
uint8_t * if_name
Definition: libmemif.h:243
uint16_t tx_buf_num
Definition: main.c:89
uint16_t index
Definition: main.c:74
Memif buffer.
Definition: libmemif.h:189
#define MEMIF_FD_EVENT_WRITE
Definition: libmemif.h:89
Memif connection arguments.
Definition: libmemif.h:159
int user_input_handler()
Definition: main.c:1118
Memif details.
Definition: libmemif.h:241
uint8_t * remote_if_name
Definition: libmemif.h:245
int main_epfd
Definition: main.c:76