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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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 *------------------------------------------------------------------
21 #include <sys/types.h>
23 #include <sys/ioctl.h>
24 #include <sys/socket.h>
28 #include <sys/prctl.h>
34 #include <linux/icmp.h>
35 #include <arpa/inet.h>
37 #include <netinet/if_ether.h>
38 #include <net/if_arp.h>
39 #include <asm/byteorder.h>
42 #include <sys/epoll.h>
48 #include <icmp_proto.h>
50 #define APP_NAME "ICMP_Responder"
51 #define IF_NAME "memif_connection"
55 #define DBG(...) do { \
56 printf (APP_NAME":%s:%d: ", __func__, __LINE__); \
57 printf (__VA_ARGS__); \
64 #define INFO(...) do { \
65 printf ("INFO: "__VA_ARGS__); \
69 /* maximum tx/rx memif buffers */
70 #define MAX_MEMIF_BUFS 256
75 /* memif conenction handle */
76 memif_conn_handle_t conn;
77 /* transmit queue id */
80 memif_buffer_t *tx_bufs;
81 /* allocated tx buffers counter */
82 /* number of tx buffers pointing to shared memory */
85 memif_buffer_t *rx_bufs;
86 /* allcoated rx buffers counter */
87 /* number of rx buffers pointing to shared memory */
89 /* interface ip address */
93 memif_connection_t memif_connection;
97 print_memif_details ()
99 memif_connection_t *c = &memif_connection;
100 printf ("MEMIF DETAILS\n");
101 printf ("==============================\n");
105 memset (&md, 0, sizeof (md));
106 ssize_t buflen = 2048;
107 char *buf = malloc (buflen);
108 memset (buf, 0, buflen);
111 err = memif_get_details (c->conn, &md, buf, buflen);
112 if (err != MEMIF_ERR_SUCCESS)
114 INFO ("%s", memif_strerror (err));
115 if (err == MEMIF_ERR_NOCONN)
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);
137 printf ("ethernet\n");
143 printf ("punt/inject\n");
146 printf ("unknown\n");
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++)
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);
158 printf ("\ttx queues:\n");
159 for (e = 0; e < md.tx_queues_num; e++)
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);
174 /* informs user about connected status. private_ctx is used by user to identify connection
175 (multiple connections WIP) */
177 on_connect (memif_conn_handle_t conn, void *private_ctx)
179 INFO ("memif connected!");
183 /* informs user about disconnected status. private_ctx is used by user to identify connection
184 (multiple connections WIP) */
186 on_disconnect (memif_conn_handle_t conn, void *private_ctx)
188 INFO ("memif disconnected!");
193 icmpr_memif_delete ()
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));
206 printf ("LIBMEMIF EXAMPLE APP: %s", APP_NAME);
211 printf ("==============================\n");
212 printf ("libmemif version: %s", LIBMEMIF_VERSION);
217 printf ("memif version: %d\n", memif_get_version ());
218 printf ("\tuse CTRL+C to exit\n");
222 icmpr_buffer_alloc (long n, uint16_t qid)
224 memif_connection_t *c = &memif_connection;
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)
231 INFO ("memif_buffer_alloc: %s", memif_strerror (err));
236 DBG ("allocated %d/%ld buffers, %u free buffers", r, n,
237 MAX_MEMIF_BUFS - c->tx_buf_num);
242 icmpr_tx_burst (uint16_t qid)
244 memif_connection_t *c = &memif_connection;
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);
260 /* application cleanup */
262 memif_connection_t *c = &memif_connection;
268 err = memif_cleanup ();
269 if (err != MEMIF_ERR_SUCCESS)
270 INFO ("memif_delete: %s", memif_strerror (err));
279 icmpr_memif_delete ();
284 /* called when event is polled on interrupt file descriptor.
285 there are packets in shared memory ready to be received */
287 on_interrupt (memif_conn_handle_t conn, void *private_ctx, uint16_t qid)
290 memif_connection_t *c = &memif_connection;
294 /* receive data from shared memory buffers */
295 err = memif_rx_burst (c->conn, qid, c->rx_bufs, MAX_MEMIF_BUFS, &rx);
298 DBG ("received %d buffers. %u/%u alloc/free buffers",
299 rx, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
301 if (icmpr_buffer_alloc (rx, c->tx_qid) < 0)
303 INFO ("buffer_alloc error");
307 for (i = 0; i < rx; i++)
309 resolve_packet ((void *) (c->rx_bufs + i)->data,
310 (c->rx_bufs + i)->len,
311 (void *) (c->tx_bufs + i)->data,
312 &(c->tx_bufs + i)->len, c->ip_addr);
315 /* mark memif buffers and shared memory buffers as free */
316 err = memif_refill_queue (c->conn, qid, rx, 0);
319 DBG ("freed %d buffers. %u/%u alloc/free buffers",
320 fb, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
322 icmpr_tx_burst (c->tx_qid);
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));
331 DBG ("freed %d buffers. %u/%u alloc/free buffers",
332 fb, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
337 icmpr_memif_create (int is_master)
339 /* setting memif connection arguments */
340 memif_conn_args_t args;
341 memset (&args, 0, sizeof (args));
342 args.is_master = is_master;
343 args.log2_ring_size = 10;
344 args.buffer_size = 2048;
345 args.num_s2m_rings = 2;
346 args.num_m2s_rings = 2;
347 strncpy ((char *) args.interface_name, IF_NAME, strlen (IF_NAME));
349 /* socket filename is not specified, because this app is supposed to
350 connect to VPP over memif. so default socket filename will be used */
351 /* default socketfile = /run/vpp/memif.sock */
353 args.interface_id = 0;
354 /* last argument for memif_create (void * private_ctx) is used by user
355 to identify connection. this context is returned with callbacks */
356 int err = memif_create (&(&memif_connection)->conn,
357 &args, on_connect, on_disconnect, on_interrupt,
359 if (err != MEMIF_ERR_SUCCESS)
360 INFO ("memif_create: %s", memif_strerror (err));
365 main (int argc, char *argv[])
367 memif_connection_t *c = &memif_connection;
369 signal (SIGINT, icmpr_exit);
371 /* initialize global memif connection handle */
378 c->tx_qid = strtol (argv[1], &end, 10);
380 INFO ("tx qid: %u", c->tx_qid);
381 /* alloc memif buffers */
384 (memif_buffer_t *) malloc (sizeof (memif_buffer_t) * MAX_MEMIF_BUFS);
387 (memif_buffer_t *) malloc (sizeof (memif_buffer_t) * MAX_MEMIF_BUFS);
392 /* initialize memory interface */
394 /* if valid callback is passed as argument, fd event polling will be done by user
395 all file descriptors and events will be passed to user in this callback */
396 /* if callback is set to NULL libmemif will handle fd event polling */
397 err = memif_init (NULL, APP_NAME, NULL, NULL, NULL);
398 if (err != MEMIF_ERR_SUCCESS)
399 INFO ("memif_init: %s", memif_strerror (err));
403 icmpr_memif_create (0);
404 print_memif_details ();
409 if (memif_poll_event (-1) < 0)
411 DBG ("poll_event error!");