22 #include <sys/types.h> 24 #include <sys/ioctl.h> 25 #include <sys/socket.h> 29 #include <sys/prctl.h> 35 #include <linux/icmp.h> 36 #include <arpa/inet.h> 38 #include <netinet/if_ether.h> 39 #include <net/if_arp.h> 40 #include <asm/byteorder.h> 43 #include <sys/epoll.h> 57 #define APP_NAME "ICMP_Responder" 58 #define IF_NAME "memif_connection" 61 #define DBG(...) do { \ 62 printf(APP_NAME":%s:%d",__func__,__LINE__); \ 63 printf(__VA_ARGS__); \ 70 #define INFO(...) do { \ 71 printf("INFO: "__VA_ARGS__); \ 75 #define MAX_MEMIF_BUFS 256 79 #ifndef __NR_memfd_create 80 #if defined __x86_64__ 81 #define __NR_memfd_create 319 83 #define __NR_memfd_create 385 84 #elif defined __aarch64__ 85 #define __NR_memfd_create 279 87 #error "__NR_memfd_create unknown for this architecture" 91 #ifndef HAVE_MEMFD_CREATE 95 return syscall (__NR_memfd_create, name, flags);
99 #ifndef F_LINUX_SPECIFIC_BASE 100 #define F_LINUX_SPECIFIC_BASE 1024 103 #ifndef MFD_ALLOW_SEALING 104 #define MFD_ALLOW_SEALING 0x0002U 108 #define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9) 109 #define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10) 111 #define F_SEAL_SEAL 0x0001 112 #define F_SEAL_SHRINK 0x0002 113 #define F_SEAL_GROW 0x0004 114 #define F_SEAL_WRITE 0x0008 150 printf (
"LIBMEMIF EXAMPLE APP: %s",
APP_NAME);
155 printf (
"==============================\n");
162 printf (
"commands:\n");
163 printf (
"\thelp - prints this help\n");
164 printf (
"\texit - exit app\n");
166 (
"\tconn <index> <mode> <interrupt> - create memif. index used as interface id. mode: 0 = slave | 1 = master. interrupt: none = default | 1 = handle ARP only\n");
167 printf (
"\tdel <index> - delete memif\n");
168 printf (
"\tshow - show connection details\n");
169 printf (
"\tsend <index> <tx> <ip> <mac> - send icmp\n");
180 buf = malloc (buflen);
181 printf (
"MEMIF DETAILS\n");
182 printf (
"==============================\n");
187 memset (&md, 0,
sizeof (md));
188 memset (buf, 0, buflen);
198 printf (
"interface index: %d\n", i);
200 printf (
"\tinterface ip: %u.%u.%u.%u\n",
202 printf (
"\tinterface name: %s\n", (
char *) md.
if_name);
203 printf (
"\tapp name: %s\n", (
char *) md.
inst_name);
204 printf (
"\tremote interface name: %s\n", (
char *) md.
remote_if_name);
206 printf (
"\tid: %u\n", md.
id);
207 printf (
"\tsecret: %s\n", (
char *) md.
secret);
217 printf (
"ethernet\n");
223 printf (
"punt/inject\n");
226 printf (
"unknown\n");
230 printf (
"\tregions:\n");
236 printf (
"\t\tfd: %d\n", md.
regions[e].
fd);
238 printf (
"\t\texternal\n");
240 printf (
"\trx queues:\n");
245 printf (
"\t\tring rx mode: %s\n",
251 printf (
"\ttx queues:\n");
256 printf (
"\t\tring rx mode: %s\n",
280 printf (
"===============================\n");
281 printf (
"interface index: %d\n", c->
index);
306 DBG (
"invalid fd %d", fd);
309 struct epoll_event evt;
310 memset (&evt, 0,
sizeof (evt));
313 if (epoll_ctl (
epfd, EPOLL_CTL_ADD, fd, &evt) < 0)
315 DBG (
"epoll_ctl: %s fd %d", strerror (errno), fd);
318 DBG (
"fd %d added to epoll", fd);
327 DBG (
"invalid fd %d", fd);
330 struct epoll_event evt;
331 memset (&evt, 0,
sizeof (evt));
334 if (epoll_ctl (
epfd, EPOLL_CTL_MOD, fd, &evt) < 0)
336 DBG (
"epoll_ctl: %s fd %d", strerror (errno), fd);
339 DBG (
"fd %d moddified on epoll", fd);
348 DBG (
"invalid fd %d", fd);
351 struct epoll_event evt;
352 memset (&evt, 0,
sizeof (evt));
353 if (epoll_ctl (
epfd, EPOLL_CTL_DEL, fd, &evt) < 0)
355 DBG (
"epoll_ctl: %s fd %d", strerror (errno), fd);
358 DBG (
"fd %d removed from epoll", fd);
365 INFO (
"memif connected!");
373 INFO (
"memif disconnected!");
401 INFO (
"connection array overflow");
406 INFO (
"don't even try...");
426 INFO (
"memif delete fail");
463 err = ftruncate (rfd, size);
468 raddr = mmap (
NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, rfd, 0);
479 return mmap (
NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
496 long index = *((
long *) private_ctx);
498 if (c->
index != index)
500 INFO (
"invalid context: %ld/%u", index, c->
index);
505 uint16_t rx = 0, tx = 0;
534 (
void *) (c->
tx_bufs + j)->data,
565 DBG (
"freed %d buffers. %u/%u alloc/free buffers", rx, c->
rx_buf_num,
573 long index = *((
long *) private_ctx);
575 if (c->
index != index)
577 INFO (
"invalid context: %ld/%u", index, c->
index);
598 for (i = 0; i < rx; i++)
600 if (((
struct ether_header *) (c->
rx_bufs + i)->data)->ether_type ==
612 (
void *) (c->
tx_bufs + i)->data,
639 DBG (
"freed %d buffers. %u/%u alloc/free buffers",
649 INFO (
"connection array overflow");
660 memset (&args, 0,
sizeof (args));
684 if (strncmp (s,
"1", 1) == 0)
697 INFO (
"Unknown interrupt descriptor");
723 int index = d->
index;
728 INFO (
"No connection at index %d.", index);
734 struct timespec start, end;
735 memset (&start, 0,
sizeof (start));
736 memset (&end, 0,
sizeof (end));
791 INFO (
"\n\nPacket sequence finished!\nSeq len: %u", seq);
792 uint64_t t1 = end.tv_sec - start.tv_sec;
794 if (end.tv_nsec > start.tv_nsec)
796 t2 = end.tv_nsec - start.tv_nsec;
800 t2 = start.tv_nsec - end.tv_nsec;
808 INFO (
"Seq time: %lus %luns\nAverage pps: %f", t1, t2, tmp);
811 INFO (
"Thread exiting...");
821 INFO (
"connection array overflow");
838 ui = strtok (ip,
".");
841 tmp[0] = strtol (ui, &end, 10);
842 ui = strtok (
NULL,
".");
845 tmp[1] = strtol (ui, &end, 10);
846 ui = strtok (
NULL,
".");
849 tmp[2] = strtol (ui, &end, 10);
850 ui = strtok (
NULL,
".");
853 tmp[3] = strtol (ui, &end, 10);
860 ui = strtok (hw,
":");
863 tmp[0] = strtol (ui, &end, 16);
864 ui = strtok (
NULL,
":");
867 tmp[1] = strtol (ui, &end, 16);
868 ui = strtok (
NULL,
":");
871 tmp[2] = strtol (ui, &end, 16);
872 ui = strtok (
NULL,
":");
875 tmp[3] = strtol (ui, &end, 16);
876 ui = strtok (
NULL,
":");
879 tmp[4] = strtol (ui, &end, 16);
880 ui = strtok (
NULL,
":");
883 tmp[5] = strtol (ui, &end, 16);
889 INFO (
"Invalid input\n");
896 char *in = (
char *) malloc (256);
897 char *ui = fgets (in, 256, stdin);
904 ui = strtok (in,
" ");
906 if (strncmp (ui,
"exit", 4) == 0)
912 else if (strncmp (ui,
"help", 4) == 0)
917 else if (strncmp (ui,
"conn", 4) == 0)
919 ui = strtok (
NULL,
" ");
921 a = strtol (ui, &end, 10);
924 INFO (
"expected id");
927 ui = strtok (
NULL,
" ");
931 INFO (
"expected mode <0|1>");
934 else if (strncmp (ui,
"del", 3) == 0)
936 ui = strtok (
NULL,
" ");
941 INFO (
"expected id");
945 else if (strncmp (ui,
"send", 4) == 0)
947 ui = strtok (
NULL,
" ");
949 a = strtol (ui, &end, 10);
952 INFO (
"expected id");
955 ui = strtok (
NULL,
" ");
960 INFO (
"expected count");
963 else if (strncmp (ui,
"show", 4) == 0)
977 struct epoll_event evt;
978 int app_err = 0, memif_err = 0, en = 0;
980 memset (&evt, 0,
sizeof (evt));
981 evt.events = EPOLLIN | EPOLLOUT;
983 sigemptyset (&sigset);
984 en = epoll_pwait (
epfd, &evt, 1, timeout, &sigset);
988 DBG (
"epoll_pwait: %s", strerror (errno));
998 if (evt.events & EPOLLIN)
1000 if (evt.events & EPOLLOUT)
1002 if (evt.events & EPOLLERR)
1008 else if (evt.data.fd == 0)
1014 DBG (
"unexpected event at memif_epfd. fd %d", evt.data.fd);
1018 if ((app_err < 0) || (memif_err < 0))
1021 DBG (
"user input handler error");
1023 DBG (
"memif control fd handler error");
1033 epfd = epoll_create (1);
1066 DBG (
"poll_event error!");
void * icmpr_send_proc(void *data)
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.
int on_interrupt1(memif_conn_handle_t conn, void *private_ctx, uint16_t qid)
void icmpr_print_counters()
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.
#define MFD_ALLOW_SEALING
int on_connect(memif_conn_handle_t conn, void *private_ctx)
int control_fd_update(int fd, uint8_t events, void *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.
static int memfd_create(const char *name, unsigned int flags)
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) ...
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.
static void print_memif_details()
int icmpr_del_external_region(void *addr, uint32_t size, int fd, void *private_ctx)
int on_interrupt(memif_conn_handle_t conn, void *private_ctx, uint16_t qid)
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
vl_api_vxlan_gbp_api_tunnel_mode_t mode
void * icmpr_get_external_region_addr(uint32_t size, int fd, void *private_ctx)
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.
int generate_packet(void *pck, uint32_t *size, uint8_t saddr[4], uint8_t daddr[4], uint8_t hw_daddr[6], uint32_t seq)
int icmpr_add_external_region(void **addr, uint32_t size, int *fd, void *private_ctx)
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)
void icmpr_reset_counters()
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.
memif_region_details_t * regions
#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[])
int icmpr_send(long index, long packet_num, char *hw, char *ip)
memif_queue_details_t * tx_queues
#define MEMIF_FD_EVENT_WRITE
uint16_t memif_get_version()
Memif get version.
Memif connection arguments.
void memif_register_external_region(memif_add_external_region_t *ar, memif_get_external_region_addr_t *gr, memif_del_external_region_t *dr, memif_get_external_buffer_offset_t *go)
Register external region.