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> 51 #define APP_NAME "ICMP_Responder" 52 #define IF_NAME "memif_connection" 56 #define DBG(...) do { \ 57 printf (APP_NAME":%s:%d: ", __func__, __LINE__); \ 58 printf (__VA_ARGS__); \ 65 #define INFO(...) do { \ 66 printf ("INFO: "__VA_ARGS__); \ 71 #define MAX_MEMIF_BUFS 256 74 #define MAX_THREADS ((MAX_CONNS) * (MAX_QUEUES)) 126 buf = malloc (buflen);
127 printf (
"MEMIF DETAILS\n");
128 printf (
"==============================\n");
133 memset (&md, 0,
sizeof (md));
134 memset (buf, 0, buflen);
144 printf (
"interface index: %d\n", i);
146 printf (
"\tinterface ip: %u.%u.%u.%u\n",
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);
152 printf (
"\tid: %u\n", md.
id);
153 printf (
"\tsecret: %s\n", (
char *) md.
secret);
163 printf (
"ethernet\n");
169 printf (
"punt/inject\n");
172 printf (
"unknown\n");
176 printf (
"\trx queues:\n");
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)
191 printf (
"\ttx queues:\n");
212 DBG (
"invalid fd %d", fd);
215 struct epoll_event evt;
216 memset (&evt, 0,
sizeof (evt));
219 if (epoll_ctl (epfd, EPOLL_CTL_ADD, fd, &evt) < 0)
221 DBG (
"epoll_ctl: %s fd %d", strerror (errno), fd);
224 DBG (
"fd %d added to epoll", fd);
233 DBG (
"invalid fd %d", fd);
236 struct epoll_event evt;
237 memset (&evt, 0,
sizeof (evt));
240 if (epoll_ctl (epfd, EPOLL_CTL_MOD, fd, &evt) < 0)
242 DBG (
"epoll_ctl: %s fd %d", strerror (errno), fd);
245 DBG (
"fd %d moddified on epoll", fd);
254 DBG (
"invalid fd %d", fd);
257 struct epoll_event evt;
258 memset (&evt, 0,
sizeof (evt));
259 if (epoll_ctl (epfd, EPOLL_CTL_DEL, fd, &evt) < 0)
261 DBG (
"epoll_ctl: %s fd %d", strerror (errno), fd);
264 DBG (
"fd %d removed from epoll", fd);
274 uint16_t rx = 0, tx = 0, fb = 0;
282 INFO (
"pthread id %u starts in polling mode", data->
id);
305 DBG (
"thread id: %u", data->
id);
307 DBG (
"received %d buffers. %u/%u alloc/free buffers",
320 DBG (
"allocated %d/%d buffers, %u free buffers",
324 for (i = 0; i < rx; i++)
328 (
void *) (data->
tx_bufs + i)->data,
338 DBG (
"freed %d buffers. %u/%u alloc/free buffers",
354 INFO (
"thread %u error!", data->
id);
362 DBG (
"freed %d buffers. %u/%u alloc/free buffers",
367 INFO (
"pthread id %u exit", data->
id);
377 uint16_t rx = 0, tx = 0, fb = 0;
378 struct epoll_event evt, *e;
391 INFO (
"pthread id %u starts in interrupt mode", data->
id);
392 int thread_epfd = epoll_create (1);
406 memset (&evt, 0,
sizeof (evt));
407 evt.events = EPOLLIN | EPOLLOUT;
408 sigemptyset (&sigset);
409 en = epoll_pwait (thread_epfd, &evt, 1, -1, &sigset);
414 DBG (
"epoll_pwait: %s", strerror (errno));
435 DBG (
"thread id: %u", data->
id);
437 DBG (
"received %d buffers. %u/%u alloc/free buffers",
450 DBG (
"allocated %d/%d buffers, %u free buffers",
454 for (i = 0; i < rx; i++)
458 (
void *) (data->
tx_bufs + i)->data,
468 DBG (
"freed %d buffers. %u/%u alloc/free buffers",
485 INFO (
"thread %u error!", data->
id);
493 DBG (
"freed %d buffers. %u/%u alloc/free buffers",
498 INFO (
"pthread id %u exit", data->
id);
508 long index = (*(
long *) private_ctx);
510 INFO (
"memif connected! index %ld", index);
522 if (thread_data[ti].isRunning)
524 INFO (
"thread id: %d already running!", ti);
527 thread_data[ti].
index = index;
528 thread_data[ti].
qid =
i;
529 thread_data[ti].
id = ti;
531 pthread_create (&
thread[ti],
534 pthread_create (&
thread[ti],
536 (
void *) &thread_data[ti]);
549 long index = (*(
long *) private_ctx);
552 INFO (
"memif disconnected!");
558 if (!thread_data[ti].isRunning)
561 pthread_kill (
thread[ti], SIGUSR1);
562 pthread_join (
thread[ti], &ptr);
593 INFO (
"connection array overflow");
598 INFO (
"don't even try...");
606 memset (&args, 0,
sizeof (args));
644 INFO (
"connection array overflow");
649 INFO (
"don't even try...");
665 printf (
"LIBMEMIF EXAMPLE APP: %s",
APP_NAME);
670 printf (
"==============================\n");
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");
711 INFO (
"connection array overflow");
716 INFO (
"don't even try...");
722 INFO (
"no connection at index %ld", index);
729 ui = strtok (ip,
".");
732 tmp[0] = strtol (ui, &end, 10);
734 ui = strtok (
NULL,
".");
737 tmp[1] = strtol (ui, &end, 10);
739 ui = strtok (
NULL,
".");
742 tmp[2] = strtol (ui, &end, 10);
744 ui = strtok (
NULL,
".");
747 tmp[3] = strtol (ui, &end, 10);
754 INFO (
"memif %ld ip address set to %u.%u.%u.%u",
760 INFO (
"invalid ip address");
769 char *in = (
char *) malloc (256);
770 char *ui = fgets (in, 256, stdin);
774 ui = strtok (in,
" ");
775 if (strncmp (ui,
"exit", 4) == 0)
781 else if (strncmp (ui,
"help", 4) == 0)
786 else if (strncmp (ui,
"conn", 4) == 0)
788 ui = strtok (
NULL,
" ");
792 INFO (
"expected id");
795 else if (strncmp (ui,
"del", 3) == 0)
797 ui = strtok (
NULL,
" ");
801 INFO (
"expected id");
804 else if (strncmp (ui,
"show", 4) == 0)
809 else if (strncmp (ui,
"ip-set", 6) == 0)
811 ui = strtok (
NULL,
" ");
815 INFO (
"expected id");
820 DBG (
"unknown command: %s", ui);
833 struct epoll_event evt, *e;
834 int app_err = 0, memif_err = 0, en = 0;
837 memset (&evt, 0,
sizeof (evt));
838 evt.events = EPOLLIN | EPOLLOUT;
840 sigemptyset (&sigset);
841 en = epoll_pwait (
main_epfd, &evt, 1, timeout, &sigset);
844 DBG (
"epoll_pwait: %s", strerror (errno));
854 if (evt.events & EPOLLIN)
856 if (evt.events & EPOLLOUT)
858 if (evt.events & EPOLLERR)
864 else if (evt.data.fd == 0)
870 DBG (
"unexpected event at memif_epfd. fd %d", evt.data.fd);
874 if ((app_err < 0) || (memif_err < 0))
877 DBG (
"user input handler error");
879 DBG (
"memif control fd handler error");
916 DBG (
"poll_event error!");
int add_epoll_fd(int fd, uint32_t events)
int on_disconnect(memif_conn_handle_t conn, void *private_ctx)
#define MEMIF_FD_EVENT_READ
user needs to set events that occured on fd and pass them to memif_control_fd_handler ...
Optimized string handling code, including c11-compliant "safe C library" variants.
void user_signal_handler(int sig)
static void print_memif_details()
int icmpr_set_ip(long index, char *ip)
uint8_t * remote_inst_name
int poll_event(int timeout)
#define LIBMEMIF_VERSION
Libmemif version.
int memif_refill_queue(memif_conn_handle_t conn, uint16_t qid, uint16_t count, uint16_t headroom)
Memif refill ring.
int on_connect(memif_conn_handle_t conn, void *private_ctx)
int memif_get_details(memif_conn_handle_t conn, memif_details_t *md, char *buf, ssize_t buflen)
Memif get details.
memif_interface_mode_t mode
char * memif_strerror(int err_code)
Memif strerror.
int icmpr_memif_create(int is_master)
pthread_t thread[MAX_CONNS]
uint8_t interface_name[32]
int resolve_packet(void *in_pck, ssize_t in_size, void *out_pck, uint32_t *out_size, uint8_t ip_addr[4])
uint8_t * socket_filename
#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) ...
int memif_set_rx_mode(memif_conn_handle_t c, memif_rx_mode_t rx_mode, uint16_t qid)
Memif set rx mode.
struct memif_connection memif_connection_t
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.
int memif_get_queue_efd(memif_conn_handle_t conn, uint16_t qid, int *efd)
Memif get queue event file descriptor
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.
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.
memif_queue_details_t * rx_queues
void * memif_rx_poll(void *ptr)
int memif_cleanup()
Memif cleanup.
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.
void * memif_rx_interrupt(void *ptr)
void * memif_conn_handle_t
Memif connection handle pointer of type void, pointing to internal structure.
int memif_control_fd_handler(int fd, uint8_t events)
Memif control file descriptor handler.
int mod_epoll_fd(int fd, uint32_t events)
int control_fd_update(int fd, uint8_t events)
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.
int memif_delete(memif_conn_handle_t *conn)
Memif delete.
#define MEMIF_FD_EVENT_ERROR
inform libmemif that error occured on fd
#define MEMIF_FD_EVENT_MOD
update events
int main(int argc, char *argv[])
memif_queue_details_t * tx_queues
#define MEMIF_FD_EVENT_WRITE
uint16_t memif_get_version()
Memif get version.
Memif connection arguments.