|
FD.io VPP
v21.06-3-gbb25fbf28
Vector Packet Processing
|
Go to the documentation of this file.
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>
57 #define APP_NAME "ICMP_Responder"
58 #define IF_NAME "memif_connection"
62 #define DBG(...) do { \
63 printf (APP_NAME":%s:%d: ", __func__, __LINE__); \
64 printf (__VA_ARGS__); \
67 #define LOG(...) do { \
69 dprintf (out_fd, __VA_ARGS__); \
70 dprintf (out_fd, "\n"); \
73 #define LOG_FILE "/tmp/memif_time_test.txt"
79 #define INFO(...) do { \
80 printf ("INFO: "__VA_ARGS__); \
86 #define MAX_MEMIF_BUFS 256
89 #define ICMPR_HEADROOM 64
113 uint64_t tx_counter, rx_counter, tx_err_counter;
114 uint64_t t_sec, t_nsec;
140 printf (
"MEMIF DETAILS\n");
141 printf (
"==============================\n");
146 memset (&md, 0,
sizeof (md));
147 memset (
buf, 0, buflen);
157 printf (
"interface index: %d\n",
i);
159 printf (
"\tinterface ip: %u.%u.%u.%u\n",
160 c->ip_addr[0],
c->ip_addr[1],
c->ip_addr[2],
c->ip_addr[3]);
161 printf (
"\tinterface name: %s\n", (
char *) md.
if_name);
162 printf (
"\tapp name: %s\n", (
char *) md.
inst_name);
163 printf (
"\tremote interface name: %s\n", (
char *) md.
remote_if_name);
165 printf (
"\tid: %u\n", md.
id);
166 printf (
"\tsecret: %s\n", (
char *) md.
secret);
176 printf (
"ethernet\n");
182 printf (
"punt/inject\n");
185 printf (
"unknown\n");
189 printf (
"\trx queues:\n");
194 printf (
"\t\tring rx mode: %s\n",
200 printf (
"\ttx queues:\n");
205 printf (
"\t\tring rx mode: %s\n",
217 printf (
"\treason: %s\n", md.
error);
228 DBG (
"invalid fd %d", fd);
231 struct epoll_event evt;
232 memset (&evt, 0,
sizeof (evt));
235 if (epoll_ctl (
epfd, EPOLL_CTL_ADD, fd, &evt) < 0)
237 DBG (
"epoll_ctl: %s fd %d", strerror (errno), fd);
240 DBG (
"fd %d added to epoll", fd);
249 DBG (
"invalid fd %d", fd);
252 struct epoll_event evt;
253 memset (&evt, 0,
sizeof (evt));
256 if (epoll_ctl (
epfd, EPOLL_CTL_MOD, fd, &evt) < 0)
258 DBG (
"epoll_ctl: %s fd %d", strerror (errno), fd);
261 DBG (
"fd %d modified on epoll", fd);
270 DBG (
"invalid fd %d", fd);
273 struct epoll_event evt;
274 memset (&evt, 0,
sizeof (evt));
275 if (epoll_ctl (
epfd, EPOLL_CTL_DEL, fd, &evt) < 0)
277 DBG (
"epoll_ctl: %s fd %d", strerror (errno), fd);
280 DBG (
"fd %d removed from epoll", fd);
289 INFO (
"memif connected!");
300 INFO (
"memif disconnected!");
339 DBG (
"allocated %d/%ld buffers, %u free buffers", *
r, n,
365 long index = *((
long *) private_ctx);
369 INFO (
"invalid context: %ld/%u",
index,
c->index);
374 uint16_t rx = 0, tx = 0;
400 c->tx_err_counter += rx - tx;
405 (
c->rx_bufs +
i)->len,
406 (
void *) (
c->tx_bufs + j)->data,
407 &(
c->tx_bufs + j)->len,
c->ip_addr);
438 DBG (
"freed %d buffers. %u/%u alloc/free buffers",
449 long index = *((
long *) private_ctx);
453 INFO (
"invalid context: %ld/%u",
index,
c->index);
458 uint16_t rx = 0, tx = 0;
496 (
c->rx_bufs +
i)->len,
497 (
void *) (
c->tx_bufs + j)->data,
498 &(
c->tx_bufs + j)->len,
c->ip_addr);
500 (
c->rx_bufs +
i + 1)->len,
501 (
void *) (
c->tx_bufs + j + 1)->data,
502 &(
c->tx_bufs + j + 1)->len,
c->ip_addr);
509 (
c->rx_bufs +
i)->len,
510 (
void *) (
c->tx_bufs + j)->data,
511 &(
c->tx_bufs + j)->len,
c->ip_addr);
523 DBG (
"freed %d buffers. %u/%u alloc/free buffers",
547 DBG (
"freed %d buffers. %u/%u alloc/free buffers",
558 long index = *((
long *) private_ctx);
562 INFO (
"invalid context: %ld/%u",
index,
c->index);
583 for (
i = 0;
i < rx;
i++)
585 if (((
struct ether_header *) (
c->rx_bufs +
i)->data)->ether_type ==
591 (
c->rx_bufs +
i)->len,
592 (
void *) (
c->tx_bufs +
i)->data,
593 &(
c->tx_bufs +
i)->len,
c->ip_addr);
614 DBG (
"freed %d buffers. %u/%u alloc/free buffers",
624 INFO (
"connection array overflow");
629 INFO (
"don't even try...");
636 memset (&args, 0,
sizeof (args));
666 if (strncmp (s,
"0", 1) == 0)
677 else if (strncmp (s,
"1", 1) == 0)
690 INFO (
"Unknown interrupt descriptor");
706 c->ip_addr[2] =
c->index + 1;
709 c->seq =
c->tx_err_counter =
c->tx_counter =
c->rx_counter = 0;
720 INFO (
"connection array overflow");
725 INFO (
"don't even try...");
745 INFO (
"memif delete fail");
752 printf (
"LIBMEMIF EXAMPLE APP: %s",
APP_NAME);
757 printf (
"==============================\n");
764 printf (
"commands:\n");
765 printf (
"\thelp - prints this help\n");
766 printf (
"\texit - exit app\n");
768 (
"\tconn <index> <mode> [<interrupt-desc>] - create memif. index is also used as interface id, mode 0 = slave 1 = master, interrupt-desc none = default 0 = if ring is full wait 1 = handle only ARP requests\n");
769 printf (
"\tdel <index> - delete memif\n");
770 printf (
"\tshow - show connection details\n");
771 printf (
"\tip-set <index> <ip-addr> - set interface ip address\n");
773 (
"\trx-mode <index> <qid> <polling|interrupt> - set queue rx mode\n");
774 printf (
"\tsh-count - print counters\n");
775 printf (
"\tcl-count - clear counters\n");
776 printf (
"\tsend <index> <tx> <ip> <mac> - send icmp\n");
807 INFO (
"connection array overflow");
812 INFO (
"don't even try...");
818 INFO (
"no connection at index %ld",
index);
825 ui = strtok (
ip,
".");
828 tmp[0] = strtol (ui, &
end, 10);
830 ui = strtok (NULL,
".");
833 tmp[1] = strtol (ui, &
end, 10);
835 ui = strtok (NULL,
".");
838 tmp[2] = strtol (ui, &
end, 10);
840 ui = strtok (NULL,
".");
843 tmp[3] = strtol (ui, &
end, 10);
845 c->ip_addr[0] =
tmp[0];
846 c->ip_addr[1] =
tmp[1];
847 c->ip_addr[2] =
tmp[2];
848 c->ip_addr[3] =
tmp[3];
850 INFO (
"memif %ld ip address set to %u.%u.%u.%u",
851 index,
c->ip_addr[0],
c->ip_addr[1],
c->ip_addr[2],
c->ip_addr[3]);
856 INFO (
"invalid ip address");
865 INFO (
"connection array overflow");
870 INFO (
"don't even try...");
877 INFO (
"no connection at index %ld",
index);
881 if (strncmp (
mode,
"interrupt", 9) == 0)
886 else if (strncmp (
mode,
"polling", 7) == 0)
891 INFO (
"expected rx mode <interrupt|polling>");
904 printf (
"===============================\n");
905 printf (
"interface index: %d\n",
c->index);
906 printf (
"\trx: %lu\n",
c->rx_counter);
907 printf (
"\ttx: %lu\n",
c->tx_counter);
908 printf (
"\ttx_err: %lu\n",
c->tx_err_counter);
909 printf (
"\tts: %lus %luns\n",
c->t_sec,
c->t_nsec);
922 c->t_sec =
c->t_nsec =
c->tx_err_counter =
c->tx_counter =
936 INFO (
"No connection at index %d. Thread exiting...\n",
index);
942 struct timespec start,
end;
943 memset (&start, 0,
sizeof (start));
944 memset (&
end, 0,
sizeof (
end));
955 INFO (
"memif_buffer_alloc: %s Thread exiting...\n",
966 &
c->tx_bufs[
i].len,
c->ip_addr,
969 &
c->tx_bufs[
i + 1].len,
c->ip_addr,
975 &
c->tx_bufs[
i].len,
c->ip_addr,
983 INFO (
"memif_tx_burst: %s Thread exiting...\n",
993 INFO (
"Packet sequence finished!");
994 INFO (
"Seq len: %u", seq);
995 uint64_t t1 =
end.tv_sec - start.tv_sec;
997 if (
end.tv_nsec > start.tv_nsec)
999 t2 =
end.tv_nsec - start.tv_nsec;
1003 t2 = start.tv_nsec -
end.tv_nsec;
1008 INFO (
"Seq time: %lus %luns", t1, t2);
1012 INFO (
"Average pps: %f",
tmp);
1013 INFO (
"Thread exiting...");
1014 pthread_exit (NULL);
1024 if (
c->conn == NULL)
1029 data->packet_num = packet_num;
1030 INFO (
"PN: %lu",
data->packet_num);
1031 printf (
"%s\n",
ip);
1032 printf (
"%s\n", hw);
1034 ui = strtok (
ip,
".");
1037 tmp[0] = strtol (ui, &
end, 10);
1039 ui = strtok (NULL,
".");
1042 tmp[1] = strtol (ui, &
end, 10);
1044 ui = strtok (NULL,
".");
1047 tmp[2] = strtol (ui, &
end, 10);
1049 ui = strtok (NULL,
".");
1052 tmp[3] = strtol (ui, &
end, 10);
1059 ui = strtok (hw,
":");
1062 tmp[0] = strtol (ui, &
end, 16);
1063 ui = strtok (NULL,
":");
1066 tmp[1] = strtol (ui, &
end, 16);
1067 ui = strtok (NULL,
":");
1070 tmp[2] = strtol (ui, &
end, 16);
1071 ui = strtok (NULL,
":");
1074 tmp[3] = strtol (ui, &
end, 16);
1075 ui = strtok (NULL,
":");
1078 tmp[4] = strtol (ui, &
end, 16);
1079 ui = strtok (NULL,
":");
1082 tmp[5] = strtol (ui, &
end, 16);
1095 INFO (
"Invalid input\n");
1102 char *in = (
char *)
malloc (256);
1103 char *ui = fgets (in, 256, stdin);
1108 ui = strtok (in,
" ");
1109 if (strncmp (ui,
"exit", 4) == 0)
1113 exit (EXIT_SUCCESS);
1115 else if (strncmp (ui,
"help", 4) == 0)
1120 else if (strncmp (ui,
"conn", 4) == 0)
1122 ui = strtok (NULL,
" ");
1124 a = strtol (ui, &
end, 10);
1127 INFO (
"expected id");
1130 ui = strtok (NULL,
" ");
1134 INFO (
"expected mode <0|1>");
1137 else if (strncmp (ui,
"del", 3) == 0)
1139 ui = strtok (NULL,
" ");
1143 INFO (
"expected id");
1146 else if (strncmp (ui,
"show", 4) == 0)
1151 else if (strncmp (ui,
"ip-set", 6) == 0)
1153 ui = strtok (NULL,
" ");
1157 INFO (
"expected id");
1160 else if (strncmp (ui,
"rx-mode", 7) == 0)
1162 ui = strtok (NULL,
" ");
1164 a = strtol (ui, &
end, 10);
1167 INFO (
"expected id");
1170 ui = strtok (NULL,
" ");
1174 INFO (
"expected qid");
1177 else if (strncmp (ui,
"sh-count", 8) == 0)
1181 else if (strncmp (ui,
"cl-count", 8) == 0)
1185 else if (strncmp (ui,
"send", 4) == 0)
1187 ui = strtok (NULL,
" ");
1189 a = strtol (ui, &
end, 10);
1192 INFO (
"expected id");
1195 ui = strtok (NULL,
" ");
1198 strtok (NULL,
" "));
1200 INFO (
"expected count");
1205 INFO (
"unknown command: %s", ui);
1218 struct epoll_event evt;
1219 int app_err = 0, memif_err = 0, en = 0;
1221 struct timespec start,
end;
1222 memset (&evt, 0,
sizeof (evt));
1223 evt.events = EPOLLIN | EPOLLOUT;
1225 sigemptyset (&sigset);
1226 en = epoll_pwait (
epfd, &evt, 1, timeout, &sigset);
1231 DBG (
"epoll_pwait: %s", strerror (errno));
1237 if (evt.data.fd > 2)
1241 if (evt.events & EPOLLIN)
1243 if (evt.events & EPOLLOUT)
1245 if (evt.events & EPOLLERR)
1251 else if (evt.data.fd == 0)
1257 DBG (
"unexpected event at memif_epfd. fd %d", evt.data.fd);
1262 LOG (
"interrupt: %ld",
end.tv_nsec - start.tv_nsec);
1264 if ((app_err < 0) || (memif_err < 0))
1267 DBG (
"user input handler error");
1269 DBG (
"memif control fd handler error");
1279 epfd = epoll_create (1);
1286 out_fd = open (LOG_FILE, O_WRONLY | O_CREAT, S_IRWXO);
1288 INFO (
"Error opening log file: %s", strerror (errno));
1317 DBG (
"poll_event error!");
#define MEMIF_FD_EVENT_MOD
update events
int icmpr_set_ip(long index, char *ip)
@ MEMIF_RX_MODE_INTERRUPT
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.
memif_queue_details_t * tx_queues
vnet_hw_if_output_node_runtime_t * r
int on_disconnect(memif_conn_handle_t conn, void *private_ctx)
int on_interrupt0(memif_conn_handle_t conn, void *private_ctx, uint16_t qid)
int icmpr_tx_burst(uint16_t qid)
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.
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.
sll srl srl sll sra u16x4 i
static perfmon_event_t events[]
int memif_set_rx_mode(memif_conn_handle_t c, memif_rx_mode_t rx_mode, uint16_t qid)
Memif set rx mode.
int icmpr_set_rx_mode(long index, long qid, char *mode)
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)
uint8_t * socket_filename
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.
static void print_memif_details()
int memif_control_fd_handler(int fd, uint8_t events)
Memif control file descriptor handler.
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 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)
int icmpr_buffer_alloc(long n, uint16_t qid)