2 *------------------------------------------------------------------
3 * Copyright (c) 2020 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 *------------------------------------------------------------------
19 #include <sys/types.h>
31 #define APP_NAME "loopback_example"
32 #define IF0_NAME "lo0"
33 #define IF1_NAME "lo1"
35 memif_connection_t intf0, intf1;
40 packet_generator (memif_connection_t *c, uint16_t num_pkts)
45 for (i = 0; (i < num_pkts) && (bi < c->tx_buf_num); i++)
47 mb = &c->tx_bufs[bi++];
48 memset (mb->data, 1, mb->len);
54 /* informs user about connected status. private_ctx is used by user to identify
57 on_connect (memif_conn_handle_t conn, void *private_ctx)
59 INFO ("memif connected!");
62 memif_connection_t *c = (memif_connection_t *) private_ctx;
65 alloc_memif_buffers (c);
67 err = memif_refill_queue (conn, 0, -1, 0);
68 if (err != MEMIF_ERR_SUCCESS)
70 INFO ("memif_refill_queue: %s", memif_strerror (err));
74 print_memif_details (c);
76 /* Once both interfaces are connected send a test packet, master -> slave.
77 * Slave will use zero-copy method to reply the same pakcet back.
78 * (Configured by assigning responder_zero_copy as on_interrupt callback.)
80 if ((intf0.is_connected == 1) && (intf1.is_connected == 1))
82 send_packets (is_reverse ? &intf1 : &intf0, 0, packet_generator, 1,
89 /* informs user about disconnected status. private_ctx is used by user to
90 * identify connection */
92 on_disconnect (memif_conn_handle_t conn, void *private_ctx)
94 INFO ("memif disconnected!");
96 memif_connection_t *c = (memif_connection_t *) private_ctx;
99 free_memif_buffers (c);
101 /* stop event polling thread */
102 int err = memif_cancel_poll_event (memif_get_socket_handle (conn));
103 if (err != MEMIF_ERR_SUCCESS)
104 INFO ("We are doomed...");
110 verify_packet (memif_conn_handle_t conn, void *private_ctx, uint16_t qid)
112 memif_connection_t *c = (memif_connection_t *) private_ctx;
116 err = memif_rx_burst (conn, qid, c->rx_bufs, MAX_MEMIF_BUFS, &c->rx_buf_num);
117 if (err != MEMIF_ERR_SUCCESS)
119 INFO ("meif_rx_burst: %s", memif_strerror (err));
123 want = malloc (c->rx_bufs[0].len);
126 INFO ("Out of memory");
130 memset (want, 1, c->rx_bufs[0].len);
132 err = memcmp (c->rx_bufs[0].data, want, c->rx_bufs[0].len);
135 INFO ("Received malformed data. ret: %d", err);
139 INFO ("Received correct data.");
143 err = memif_refill_queue (conn, qid, c->rx_buf_num, 0);
144 if (err != MEMIF_ERR_SUCCESS)
145 INFO ("memif_refill_queue: %s", memif_strerror (err));
147 /* stop polling and exit the program */
148 INFO ("Stopping the program");
149 err = memif_cancel_poll_event (memif_get_socket_handle (conn));
150 if (err != MEMIF_ERR_SUCCESS)
151 INFO ("We are doomed...");
157 create_memif_interface (memif_socket_handle_t memif_socket,
158 const char *if_name, int id, uint8_t is_master,
159 memif_connection_t *ctx)
161 memif_conn_args_t memif_conn_args = { 0 };
164 memif_conn_args.socket = memif_socket;
165 memif_conn_args.interface_id = id;
166 strncpy (memif_conn_args.interface_name, if_name,
167 sizeof (memif_conn_args.interface_name));
168 memif_conn_args.is_master = is_master;
170 err = memif_create (&ctx->conn, &memif_conn_args, on_connect, on_disconnect,
171 is_master ? verify_packet : responder_zero_copy,
173 if (err != MEMIF_ERR_SUCCESS)
175 INFO ("memif_create_socket: %s", memif_strerror (err));
185 printf ("LIBMEMIF EXAMPLE APP: %s", APP_NAME);
190 printf ("==============================\n");
191 printf ("libmemif version: %s", LIBMEMIF_VERSION);
197 printf ("memif version: %s\n", memif_get_version_str ());
198 printf ("==============================\n");
199 printf ("In this example, two memif endpoints are connected to create a "
201 printf ("Once connected, a test packet is sent out the memif master "
204 "the memif slave interface, which replies with the same packet in a\n");
205 printf ("zero-copy way.\n");
207 "In reverse mode, the packet is sent from the slave interface and is\n");
208 printf ("looped back by the master interface.\n");
209 printf ("==============================\n");
210 printf ("Usage: loopback [OPTIONS]\n\n");
211 printf ("Options:\n");
212 printf ("\t-r\tReverse mode, verification packet is sent by slave.\n");
213 printf ("\t-?\tShow help and exit.\n");
214 printf ("\t-v\tShow libmemif and memif version information and exit.\n");
218 main (int argc, char *argv[])
220 memif_socket_args_t memif_socket_args = { 0 };
221 memif_socket_handle_t memif_socket;
222 int opt, err, ret = 0;
225 while ((opt = getopt (argc, argv, "r?v")) != -1)
241 /** Create memif socket
243 * Interfaces are internally stored in a database referenced by memif socket.
245 /* Abstract socket supported */
246 memif_socket_args.path[0] = '@';
247 strncpy (memif_socket_args.path + 1, APP_NAME, strlen (APP_NAME));
248 /* Set application name */
249 strncpy (memif_socket_args.app_name, APP_NAME, strlen (APP_NAME));
251 err = memif_create_socket (&memif_socket, &memif_socket_args, NULL);
252 if (err != MEMIF_ERR_SUCCESS)
254 INFO ("memif_create_socket: %s", memif_strerror (err));
258 /** Create memif interfaces
260 * Both interaces are assigned the same socket and same id to create a
264 /* prepare the private data */
265 memset (&intf0, 0, sizeof (intf0));
266 memset (&intf1, 0, sizeof (intf1));
269 intf0.packet_handler = basic_packet_handler;
273 intf1.packet_handler = basic_packet_handler;
277 create_memif_interface (memif_socket, IF0_NAME, 0, /* master */ 1, &intf0);
284 create_memif_interface (memif_socket, IF1_NAME, 0, /* slave */ 0, &intf1);
292 err = memif_poll_event (memif_socket, -1);
294 while (err == MEMIF_ERR_SUCCESS);
301 free_memif_buffers (&intf0);
302 free_memif_buffers (&intf1);
303 memif_delete (&intf0.conn);
304 memif_delete (&intf1.conn);
305 memif_delete_socket (&memif_socket);