FD.io VPP  v18.07.1-19-g511ce25
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 
47 #include <libmemif.h>
48 #include <icmp_proto.h>
49 
50 #define APP_NAME "ICMP_Responder"
51 #define IF_NAME "memif_connection"
52 
53 
54 #ifdef ICMP_DBG
55 #define DBG(...) do { \
56  printf (APP_NAME":%s:%d: ", __func__, __LINE__); \
57  printf (__VA_ARGS__); \
58  printf ("\n"); \
59  } while (0)
60 #else
61 #define DBG(...)
62 #endif
63 
64 #define INFO(...) do { \
65  printf ("INFO: "__VA_ARGS__); \
66  printf ("\n"); \
67  } while (0)
68 
69 /* maximum tx/rx memif buffers */
70 #define MAX_MEMIF_BUFS 256
71 
72 typedef struct
73 {
74  uint16_t index;
75  /* memif conenction handle */
77  /* transmit queue id */
78  uint16_t tx_qid;
79  /* tx buffers */
81  /* allocated tx buffers counter */
82  /* number of tx buffers pointing to shared memory */
83  uint16_t tx_buf_num;
84  /* rx buffers */
86  /* allcoated rx buffers counter */
87  /* number of rx buffers pointing to shared memory */
88  uint16_t rx_buf_num;
89  /* interface ip address */
90  uint8_t ip_addr[4];
92 
94 int epfd;
95 
96 static void
98 {
100  printf ("MEMIF DETAILS\n");
101  printf ("==============================\n");
102 
103 
104  memif_details_t md;
105  memset (&md, 0, sizeof (md));
106  ssize_t buflen = 2048;
107  char *buf = malloc (buflen);
108  memset (buf, 0, buflen);
109  int err, e;
110 
111  err = memif_get_details (c->conn, &md, buf, buflen);
112  if (err != MEMIF_ERR_SUCCESS)
113  {
114  INFO ("%s", memif_strerror (err));
115  if (err == MEMIF_ERR_NOCONN)
116  {
117  free (buf);
118  return;
119  }
120  }
121 
122  printf ("\tinterface name: %s\n", (char *) md.if_name);
123  printf ("\tapp name: %s\n", (char *) md.inst_name);
124  printf ("\tremote interface name: %s\n", (char *) md.remote_if_name);
125  printf ("\tremote app name: %s\n", (char *) md.remote_inst_name);
126  printf ("\tid: %u\n", md.id);
127  printf ("\tsecret: %s\n", (char *) md.secret);
128  printf ("\trole: ");
129  if (md.role)
130  printf ("slave\n");
131  else
132  printf ("master\n");
133  printf ("\tmode: ");
134  switch (md.mode)
135  {
136  case 0:
137  printf ("ethernet\n");
138  break;
139  case 1:
140  printf ("ip\n");
141  break;
142  case 2:
143  printf ("punt/inject\n");
144  break;
145  default:
146  printf ("unknown\n");
147  break;
148  }
149  printf ("\tsocket filename: %s\n", (char *) md.socket_filename);
150  printf ("\tsocket filename: %s\n", (char *) md.socket_filename);
151  printf ("\trx queues:\n");
152  for (e = 0; e < md.rx_queues_num; e++)
153  {
154  printf ("\t\tqueue id: %u\n", md.rx_queues[e].qid);
155  printf ("\t\tring size: %u\n", md.rx_queues[e].ring_size);
156  printf ("\t\tbuffer size: %u\n", md.rx_queues[e].buffer_size);
157  }
158  printf ("\ttx queues:\n");
159  for (e = 0; e < md.tx_queues_num; e++)
160  {
161  printf ("\t\tqueue id: %u\n", md.tx_queues[e].qid);
162  printf ("\t\tring size: %u\n", md.tx_queues[e].ring_size);
163  printf ("\t\tbuffer size: %u\n", md.tx_queues[e].buffer_size);
164  }
165  printf ("\tlink: ");
166  if (md.link_up_down)
167  printf ("up\n");
168  else
169  printf ("down\n");
170 
171  free (buf);
172 }
173 
174 /* informs user about connected status. private_ctx is used by user to identify connection
175  (multiple connections WIP) */
176 int
177 on_connect (memif_conn_handle_t conn, void *private_ctx)
178 {
179  INFO ("memif connected!");
180  return 0;
181 }
182 
183 /* informs user about disconnected status. private_ctx is used by user to identify connection
184  (multiple connections WIP) */
185 int
186 on_disconnect (memif_conn_handle_t conn, void *private_ctx)
187 {
188  INFO ("memif disconnected!");
189  return 0;
190 }
191 
192 int
194 {
195  int err;
196  /* disconenct then delete memif connection */
197  err = memif_delete (&(&memif_connection)->conn);
198  if (err != MEMIF_ERR_SUCCESS)
199  INFO ("memif_delete: %s", memif_strerror (err));
200  return 0;
201 }
202 
203 void
205 {
206  printf ("LIBMEMIF EXAMPLE APP: %s", APP_NAME);
207 #ifdef ICMP_DBG
208  printf (" (debug)");
209 #endif
210  printf ("\n");
211  printf ("==============================\n");
212  printf ("libmemif version: %s", LIBMEMIF_VERSION);
213 #ifdef MEMIF_DBG
214  printf (" (debug)");
215 #endif
216  printf ("\n");
217  printf ("memif version: %d\n", memif_get_version ());
218  printf ("\tuse CTRL+C to exit\n");
219 }
220 
221 int
222 icmpr_buffer_alloc (long n, uint16_t qid)
223 {
225  int err;
226  uint16_t r;
227  /* set data pointer to shared memory and set buffer_len to shared mmeory buffer len */
228  err = memif_buffer_alloc (c->conn, qid, c->tx_bufs, n, &r, 0);
229  if (err != MEMIF_ERR_SUCCESS)
230  {
231  INFO ("memif_buffer_alloc: %s", memif_strerror (err));
232  c->tx_buf_num += r;
233  return -1;
234  }
235  c->tx_buf_num += r;
236  DBG ("allocated %d/%ld buffers, %u free buffers", r, n,
238  return 0;
239 }
240 
241 int
242 icmpr_tx_burst (uint16_t qid)
243 {
245  int err;
246  uint16_t r;
247  /* inform peer memif interface about data in shared memory buffers */
248  /* mark memif buffers as free */
249  err = memif_tx_burst (c->conn, qid, c->tx_bufs, c->tx_buf_num, &r);
250  if (err != MEMIF_ERR_SUCCESS)
251  INFO ("memif_tx_burst: %s", memif_strerror (err));
252  DBG ("tx: %d/%u", r, c->tx_buf_num);
253  c->tx_buf_num -= r;
254  return 0;
255 }
256 
257 int
259 {
260  /* application cleanup */
261  int err;
263  free (c->tx_bufs);
264  c->tx_bufs = NULL;
265  free (c->rx_bufs);
266  c->rx_bufs = NULL;
267 
268  err = memif_cleanup ();
269  if (err != MEMIF_ERR_SUCCESS)
270  INFO ("memif_delete: %s", memif_strerror (err));
271 
272  return 0;
273 }
274 
275 void
276 icmpr_exit (int sig)
277 {
278  printf ("\n");
280  icmpr_free ();
281  exit (EXIT_SUCCESS);
282 }
283 
284 /* called when event is polled on interrupt file descriptor.
285  there are packets in shared memory ready to be received */
286 int
287 on_interrupt (memif_conn_handle_t conn, void *private_ctx, uint16_t qid)
288 {
289  DBG ("interrupted");
291  int err;
292  uint16_t rx;
293  /* receive data from shared memory buffers */
294  err = memif_rx_burst (c->conn, qid, c->rx_bufs, MAX_MEMIF_BUFS, &rx);
295  c->rx_buf_num += rx;
296 
297  DBG ("received %d buffers. %u/%u alloc/free buffers",
298  rx, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
299 
300  if (icmpr_buffer_alloc (rx, c->tx_qid) < 0)
301  {
302  INFO ("buffer_alloc error");
303  goto error;
304  }
305  int i;
306  for (i = 0; i < rx; i++)
307  {
308  resolve_packet ((void *) (c->rx_bufs + i)->data,
309  (c->rx_bufs + i)->len,
310  (void *) (c->tx_bufs + i)->data,
311  &(c->tx_bufs + i)->len, c->ip_addr);
312  }
313 
314  uint16_t fb;
315  /* mark memif buffers and shared memory buffers as free */
316  err = memif_refill_queue (c->conn, qid, rx, 0);
317  c->rx_buf_num -= fb;
318 
319  DBG ("freed %d buffers. %u/%u alloc/free buffers",
320  fb, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
321 
322  icmpr_tx_burst (c->tx_qid);
323 
324  return 0;
325 
326 error:
327  err = memif_refill_queue (c->conn, qid, rx, 0);
328  if (err != MEMIF_ERR_SUCCESS)
329  INFO ("memif_buffer_free: %s", memif_strerror (err));
330  c->rx_buf_num -= fb;
331  DBG ("freed %d buffers. %u/%u alloc/free buffers",
332  fb, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
333  return 0;
334 }
335 
336 int
337 icmpr_memif_create (int is_master)
338 {
339  /* setting memif connection arguments */
340  memif_conn_args_t args;
341  int fd = -1;
342  memset (&args, 0, sizeof (args));
343  args.is_master = is_master;
344  args.log2_ring_size = 10;
345  args.buffer_size = 2048;
346  args.num_s2m_rings = 2;
347  args.num_m2s_rings = 2;
348  strncpy ((char *) args.interface_name, IF_NAME, strlen (IF_NAME));
349  args.mode = 0;
350  /* socket filename is not specified, because this app is supposed to
351  connect to VPP over memif. so default socket filename will be used */
352  /* default socketfile = /run/vpp/memif.sock */
353 
354  args.interface_id = 0;
355  /* last argument for memif_create (void * private_ctx) is used by user
356  to identify connection. this context is returned with callbacks */
357  int err = memif_create (&(&memif_connection)->conn,
359  NULL);
360  if (err != MEMIF_ERR_SUCCESS)
361  INFO ("memif_create: %s", memif_strerror (err));
362  return 0;
363 }
364 
365 int
366 main (int argc, char *argv[])
367 {
369 
370  signal (SIGINT, icmpr_exit);
371 
372  /* initialize global memif connection handle */
373  c->conn = NULL;
374  if (argc == 1)
375  c->tx_qid = 0;
376  else
377  {
378  char *end;
379  c->tx_qid = strtol (argv[1], &end, 10);
380  }
381  INFO ("tx qid: %u", c->tx_qid);
382  /* alloc memif buffers */
383  c->rx_buf_num = 0;
384  c->rx_bufs =
385  (memif_buffer_t *) malloc (sizeof (memif_buffer_t) * MAX_MEMIF_BUFS);
386  c->tx_buf_num = 0;
387  c->tx_bufs =
388  (memif_buffer_t *) malloc (sizeof (memif_buffer_t) * MAX_MEMIF_BUFS);
389  c->ip_addr[0] = 192;
390  c->ip_addr[1] = 168;
391  c->ip_addr[2] = 1;
392  c->ip_addr[3] = 2;
393  /* initialize memory interface */
394  int err;
395  /* if valid callback is passed as argument, fd event polling will be done by user
396  all file descriptors and events will be passed to user in this callback */
397  /* if callback is set to NULL libmemif will handle fd event polling */
398  err = memif_init (NULL, APP_NAME, NULL, NULL);
399  if (err != MEMIF_ERR_SUCCESS)
400  INFO ("memif_init: %s", memif_strerror (err));
401 
402  print_help ();
403 
404  icmpr_memif_create (0);
406 
407  /* main loop */
408  while (1)
409  {
410  if (memif_poll_event (-1) < 0)
411  {
412  DBG ("poll_event error!");
413  }
414  }
415 }
#define APP_NAME
Definition: main.c:50
int icmpr_memif_delete()
Definition: main.c:193
void print_help()
Definition: main.c:204
uint8_t * inst_name
Definition: libmemif.h:271
uint8_t * secret
Definition: libmemif.h:276
int on_disconnect(memif_conn_handle_t conn, void *private_ctx)
Definition: main.c:186
uint8_t num_m2s_rings
Definition: libmemif.h:187
#define NULL
Definition: clib.h:55
uint16_t buffer_size
Definition: libmemif.h:188
uint32_t interface_id
Definition: libmemif.h:192
int i
uint8_t * remote_inst_name
Definition: libmemif.h:273
#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:1659
int on_connect(memif_conn_handle_t conn, void *private_ctx)
Definition: main.c:177
uint8_t num_s2m_rings
Definition: libmemif.h:186
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:1866
memif_interface_mode_t mode
Definition: libmemif.h:194
uint8_t mode
Definition: libmemif.h:278
uint8_t link_up_down
Definition: libmemif.h:285
char * memif_strerror(int err_code)
Memif strerror.
Definition: main.c:157
int icmpr_memif_create(int is_master)
Definition: main.c:337
memif_conn_handle_t conn
Definition: main.c:76
uint8_t ip_addr[4]
Definition: main.c:90
uint16_t rx_buf_num
Definition: main.c:88
uint8_t interface_name[32]
Definition: libmemif.h:193
int resolve_packet(void *in_pck, ssize_t in_size, void *out_pck, uint32_t *out_size, uint8_t ip_addr[4])
Definition: icmp_proto.c:208
uint16_t buffer_size
Definition: libmemif.h:249
uint8_t * socket_filename
Definition: libmemif.h:279
void icmpr_exit(int sig)
Definition: main.c:276
struct memif_connection memif_connection_t
uint8_t is_master
Definition: libmemif.h:190
uint8_t rx_queues_num
Definition: libmemif.h:280
int memif_init(memif_control_fd_update_t *on_control_fd_update, char *app_name, memif_alloc_t *memif_alloc, memif_free_t *memif_free)
Memif initialization.
Definition: main.c:429
int icmpr_tx_burst(uint16_t qid)
Definition: main.c:242
#define IF_NAME
Definition: main.c:51
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:1714
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:1533
int memif_poll_event(int timeout)
Memif poll event.
Definition: main.c:1009
static void print_memif_details()
Definition: main.c:97
memif_queue_details_t * rx_queues
Definition: libmemif.h:282
uint8_t role
Definition: libmemif.h:277
int memif_cleanup()
Memif cleanup.
Definition: main.c:2013
int memif_create(memif_conn_handle_t *c, memif_conn_args_t *args, memif_connection_update_t *on_connect, memif_connection_update_t *on_disconnect, memif_interrupt_t *on_interrupt, void *private_ctx)
Memory interface create function.
Definition: main.c:595
memif_connection_t memif_connection
Definition: main.c:93
uint8_t tx_queues_num
Definition: libmemif.h:281
#define DBG(...)
Definition: main.c:61
#define MAX_MEMIF_BUFS
Definition: main.c:70
void * memif_conn_handle_t
Memif connection handle pointer of type void, pointing to internal structure.
Definition: libmemif.h:100
int icmpr_buffer_alloc(long n, uint16_t qid)
Definition: main.c:222
uint8_t log2_ring_size
Definition: libmemif.h:189
int epfd
Definition: main.c:94
uint32_t id
Definition: libmemif.h:275
int memif_rx_burst(memif_conn_handle_t conn, uint16_t qid, memif_buffer_t *bufs, uint16_t count, uint16_t *rx)
Memif receive buffer burst.
Definition: main.c:1781
int memif_delete(memif_conn_handle_t *conn)
Memif delete.
Definition: main.c:1184
int main(int argc, char *argv[])
Definition: main.c:102
memif_queue_details_t * tx_queues
Definition: libmemif.h:283
uint8_t * if_name
Definition: libmemif.h:270
uint16_t index
Definition: main.c:74
Memif buffer.
Definition: libmemif.h:211
uint16_t tx_qid
Definition: main.c:78
uint16_t memif_get_version()
Memif get version.
Definition: main.c:174
#define INFO(...)
Definition: main.c:64
memif_buffer_t * tx_bufs
Definition: main.c:80
Memif connection arguments.
Definition: libmemif.h:181
Memif details.
Definition: libmemif.h:268
uint8_t * remote_if_name
Definition: libmemif.h:272
memif_buffer_t * rx_bufs
Definition: main.c:85