|
FD.io VPP
v21.10.1-2-g0a485f517
Vector Packet Processing
|
Go to the documentation of this file.
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");
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",
201 c->ip_addr[0],
c->ip_addr[1],
c->ip_addr[2],
c->ip_addr[3]);
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);
282 printf (
"\trx: %lu\n",
c->rx_counter);
283 printf (
"\ttx: %lu\n",
c->tx_counter);
284 printf (
"\ttx_err: %lu\n",
c->tx_err_counter);
297 c->tx_err_counter =
c->tx_counter =
c->rx_counter = 0;
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 modified 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);
500 INFO (
"invalid context: %ld/%u",
index,
c->index);
505 uint16_t rx = 0, tx = 0;
528 c->tx_err_counter += rx - tx;
533 (
c->rx_bufs +
i)->len,
534 (
void *) (
c->tx_bufs + j)->data,
535 &(
c->tx_bufs + j)->len,
c->ip_addr);
565 DBG (
"freed %d buffers. %u/%u alloc/free buffers", rx,
c->rx_buf_num,
573 long index = *((
long *) private_ctx);
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 ==
611 (
c->rx_bufs +
i)->len,
612 (
void *) (
c->tx_bufs +
i)->data,
613 &(
c->tx_bufs +
i)->len,
c->ip_addr);
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");
712 c->ip_addr[2] =
c->index + 1;
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));
762 &
c->tx_bufs[
i + 1].len,
c->ip_addr,
765 &
c->tx_bufs[
i + 2].len,
c->ip_addr,
768 &
c->tx_bufs[
i + 3].len,
c->ip_addr,
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");
836 data->packet_num = packet_num;
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!");
#define MEMIF_FD_EVENT_MOD
update events
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.
void icmpr_print_counters()
icmpr_thread_data_t icmpr_thread_data[MAX_CONNS]
#define MEMIF_FD_EVENT_WRITE
int on_connect(memif_conn_handle_t conn, void *private_ctx)
memif_interface_mode_t mode
int control_fd_update(int fd, uint8_t events, void *ctx)
int icmpr_memif_create(int is_master)
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.
pthread_t thread[MAX_CONNS]
Memif connection arguments.
vl_api_tunnel_mode_t mode
int add_epoll_fd(int fd, uint32_t events)
int memif_get_details(memif_conn_handle_t conn, memif_details_t *md, char *buf, ssize_t buflen)
Memif get details.
int icmpr_del_external_region(void *addr, uint32_t size, int fd, void *private_ctx)
memif_queue_details_t * tx_queues
int on_disconnect(memif_conn_handle_t conn, void *private_ctx)
int on_interrupt(memif_conn_handle_t conn, void *private_ctx, uint16_t qid)
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.
void * icmpr_get_external_region_addr(uint32_t size, int fd, void *private_ctx)
int generate_packet(void *pck, uint32_t *size, uint8_t saddr[4], uint8_t daddr[4], uint8_t hw_daddr[6], uint32_t seq)
uint16_t memif_get_version()
Memif get version.
int poll_event(int timeout)
struct memif_connection memif_connection_t
f64 end
end of the time range
uint8_t * remote_inst_name
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.
#define LIBMEMIF_VERSION
Libmemif version.
static perfmon_event_t events[]
#define MFD_ALLOW_SEALING
int memif_cleanup()
Memif cleanup.
void icmpr_reset_counters()
#define MEMIF_FD_EVENT_ERROR
inform libmemif that error occurred on fd
#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)
void * memif_conn_handle_t
Memif connection handle pointer of type void, pointing to internal structure.
int icmpr_send(long index, long packet_num, char *hw, char *ip)
static int memfd_create(const char *name, unsigned int flags)
uint8_t * socket_filename
memif_region_details_t * regions
int main(int argc, char *argv[])
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_control_fd_handler(int fd, uint8_t events)
Memif control file descriptor handler.
static void print_memif_details()
void * icmpr_send_proc(void *data)
uint8_t interface_name[32]
int memif_delete(memif_conn_handle_t *conn)
Memif delete.
int resolve_packet(void *in_pck, ssize_t in_size, void *out_pck, uint32_t *out_size, uint8_t ip_addr[4])
char * memif_strerror(int err_code)
Memif strerror.
void * malloc(size_t size)
memif_queue_details_t * rx_queues
int icmpr_add_external_region(void **addr, uint32_t size, int *fd, void *private_ctx)
int memif_refill_queue(memif_conn_handle_t conn, uint16_t qid, uint16_t count, uint16_t headroom)
Memif refill queue.
#define MEMIF_FD_EVENT_READ
user needs to set events that occurred on fd and pass them to memif_control_fd_handler
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 on_interrupt1(memif_conn_handle_t conn, void *private_ctx, uint16_t qid)
int mod_epoll_fd(int fd, uint32_t events)
vl_api_wireguard_peer_flags_t flags