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 137 buf = malloc (buflen);
138 printf (
"MEMIF DETAILS\n");
139 printf (
"==============================\n");
144 memset (&md, 0,
sizeof (md));
145 memset (buf, 0, buflen);
155 printf (
"interface index: %d\n", i);
157 printf (
"\tinterface ip: %u.%u.%u.%u\n",
159 printf (
"\tinterface name: %s\n", (
char *) md.
if_name);
160 printf (
"\tapp name: %s\n", (
char *) md.
inst_name);
161 printf (
"\tremote interface name: %s\n", (
char *) md.
remote_if_name);
163 printf (
"\tid: %u\n", md.
id);
164 printf (
"\tsecret: %s\n", (
char *) md.
secret);
174 printf (
"ethernet\n");
180 printf (
"punt/inject\n");
183 printf (
"unknown\n");
187 printf (
"\trx queues:\n");
192 printf (
"\t\tring rx mode: %s\n",
198 printf (
"\ttx queues:\n");
203 printf (
"\t\tring rx mode: %s\n",
223 DBG (
"invalid fd %d", fd);
226 struct epoll_event evt;
227 memset (&evt, 0,
sizeof (evt));
230 if (epoll_ctl (
epfd, EPOLL_CTL_ADD, fd, &evt) < 0)
232 DBG (
"epoll_ctl: %s fd %d", strerror (errno), fd);
235 DBG (
"fd %d added to epoll", fd);
244 DBG (
"invalid fd %d", fd);
247 struct epoll_event evt;
248 memset (&evt, 0,
sizeof (evt));
251 if (epoll_ctl (
epfd, EPOLL_CTL_MOD, fd, &evt) < 0)
253 DBG (
"epoll_ctl: %s fd %d", strerror (errno), fd);
256 DBG (
"fd %d moddified on epoll", fd);
265 DBG (
"invalid fd %d", fd);
268 struct epoll_event evt;
269 memset (&evt, 0,
sizeof (evt));
270 if (epoll_ctl (
epfd, EPOLL_CTL_DEL, fd, &evt) < 0)
272 DBG (
"epoll_ctl: %s fd %d", strerror (errno), fd);
275 DBG (
"fd %d removed from epoll", fd);
284 INFO (
"memif connected!");
295 INFO (
"memif disconnected!");
334 DBG (
"allocated %d/%ld buffers, %u free buffers", *r, n,
360 long index = *((
long *) private_ctx);
362 if (c->
index != index)
364 INFO (
"invalid context: %ld/%u", index, c->
index);
369 uint16_t rx = 0, tx = 0;
402 (
void *) (c->
tx_bufs + j)->data,
414 DBG (
"freed %d buffers. %u/%u alloc/free buffers",
435 DBG (
"freed %d buffers. %u/%u alloc/free buffers",
446 long index = *((
long *) private_ctx);
448 if (c->
index != index)
450 INFO (
"invalid context: %ld/%u", index, c->
index);
455 uint16_t rx = 0, tx = 0;
496 (
void *) (c->
tx_bufs + j)->data,
500 (
void *) (c->
tx_bufs + j + 1)->data,
509 (
void *) (c->
tx_bufs + j)->data,
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);
560 if (c->
index != index)
562 INFO (
"invalid context: %ld/%u", index, c->
index);
585 for (i = 0; i < rx; i++)
587 if (((
struct ether_header *) (c->
rx_bufs + i)->data)->ether_type ==
594 (
void *) (c->
tx_bufs + i)->data,
616 DBG (
"freed %d buffers. %u/%u alloc/free buffers",
626 INFO (
"connection array overflow");
631 INFO (
"don't even try...");
639 memset (&args, 0,
sizeof (args));
669 if (strncmp (s,
"0", 1) == 0)
680 else if (strncmp (s,
"1", 1) == 0)
693 INFO (
"Unknown interrupt descriptor");
723 INFO (
"connection array overflow");
728 INFO (
"don't even try...");
748 INFO (
"memif delete fail");
755 printf (
"LIBMEMIF EXAMPLE APP: %s",
APP_NAME);
760 printf (
"==============================\n");
767 printf (
"commands:\n");
768 printf (
"\thelp - prints this help\n");
769 printf (
"\texit - exit app\n");
771 (
"\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");
772 printf (
"\tdel <index> - delete memif\n");
773 printf (
"\tshow - show connection details\n");
774 printf (
"\tip-set <index> <ip-addr> - set interface ip address\n");
776 (
"\trx-mode <index> <qid> <polling|interrupt> - set queue rx mode\n");
777 printf (
"\tsh-count - print counters\n");
778 printf (
"\tcl-count - clear counters\n");
779 printf (
"\tsend <index> <tx> <ip> <mac> - send icmp\n");
810 INFO (
"connection array overflow");
815 INFO (
"don't even try...");
821 INFO (
"no connection at index %ld", index);
828 ui = strtok (ip,
".");
831 tmp[0] = strtol (ui, &end, 10);
833 ui = strtok (
NULL,
".");
836 tmp[1] = strtol (ui, &end, 10);
838 ui = strtok (
NULL,
".");
841 tmp[2] = strtol (ui, &end, 10);
843 ui = strtok (
NULL,
".");
846 tmp[3] = strtol (ui, &end, 10);
853 INFO (
"memif %ld ip address set to %u.%u.%u.%u",
859 INFO (
"invalid ip address");
868 INFO (
"connection array overflow");
873 INFO (
"don't even try...");
880 INFO (
"no connection at index %ld", index);
884 if (strncmp (mode,
"interrupt", 9) == 0)
889 else if (strncmp (mode,
"polling", 7) == 0)
894 INFO (
"expected rx mode <interrupt|polling>");
907 printf (
"===============================\n");
908 printf (
"interface index: %d\n", c->
index);
912 printf (
"\tts: %lus %luns\n", c->
t_sec, c->
t_nsec);
934 int index = d->
index;
939 INFO (
"No connection at index %d. Thread exiting...\n", index);
945 struct timespec start, end;
946 memset (&start, 0,
sizeof (start));
947 memset (&end, 0,
sizeof (end));
958 INFO (
"memif_buffer_alloc: %s Thread exiting...\n",
986 INFO (
"memif_tx_burst: %s Thread exiting...\n",
995 INFO (
"Pakcet sequence finished!");
996 INFO (
"Seq len: %u", seq);
997 uint64_t t1 = end.tv_sec - start.tv_sec;
999 if (end.tv_nsec > start.tv_nsec)
1001 t2 = end.tv_nsec - start.tv_nsec;
1005 t2 = start.tv_nsec - end.tv_nsec;
1010 INFO (
"Seq time: %lus %luns", t1, t2);
1014 INFO (
"Average pps: %f", tmp);
1015 INFO (
"Thread exiting...");
1016 pthread_exit (
NULL);
1030 data->
index = index;
1033 printf (
"%s\n", ip);
1034 printf (
"%s\n", hw);
1036 ui = strtok (ip,
".");
1039 tmp[0] = strtol (ui, &end, 10);
1041 ui = strtok (
NULL,
".");
1044 tmp[1] = strtol (ui, &end, 10);
1046 ui = strtok (
NULL,
".");
1049 tmp[2] = strtol (ui, &end, 10);
1051 ui = strtok (
NULL,
".");
1054 tmp[3] = strtol (ui, &end, 10);
1061 ui = strtok (hw,
":");
1064 tmp[0] = strtol (ui, &end, 16);
1065 ui = strtok (
NULL,
":");
1068 tmp[1] = strtol (ui, &end, 16);
1069 ui = strtok (
NULL,
":");
1072 tmp[2] = strtol (ui, &end, 16);
1073 ui = strtok (
NULL,
":");
1076 tmp[3] = strtol (ui, &end, 16);
1077 ui = strtok (
NULL,
":");
1080 tmp[4] = strtol (ui, &end, 16);
1081 ui = strtok (
NULL,
":");
1084 tmp[5] = strtol (ui, &end, 16);
1097 INFO (
"Invalid input\n");
1105 char *in = (
char *) malloc (256);
1106 char *ui = fgets (in, 256, stdin);
1111 ui = strtok (in,
" ");
1112 if (strncmp (ui,
"exit", 4) == 0)
1116 exit (EXIT_SUCCESS);
1118 else if (strncmp (ui,
"help", 4) == 0)
1123 else if (strncmp (ui,
"conn", 4) == 0)
1125 ui = strtok (
NULL,
" ");
1127 a = strtol (ui, &end, 10);
1130 INFO (
"expected id");
1133 ui = strtok (
NULL,
" ");
1137 INFO (
"expected mode <0|1>");
1140 else if (strncmp (ui,
"del", 3) == 0)
1142 ui = strtok (
NULL,
" ");
1146 INFO (
"expected id");
1149 else if (strncmp (ui,
"show", 4) == 0)
1154 else if (strncmp (ui,
"ip-set", 6) == 0)
1156 ui = strtok (
NULL,
" ");
1160 INFO (
"expected id");
1163 else if (strncmp (ui,
"rx-mode", 7) == 0)
1165 ui = strtok (
NULL,
" ");
1167 a = strtol (ui, &end, 10);
1170 INFO (
"expected id");
1173 ui = strtok (
NULL,
" ");
1177 INFO (
"expected qid");
1180 else if (strncmp (ui,
"sh-count", 8) == 0)
1184 else if (strncmp (ui,
"cl-count", 8) == 0)
1188 else if (strncmp (ui,
"send", 4) == 0)
1190 ui = strtok (
NULL,
" ");
1192 a = strtol (ui, &end, 10);
1195 INFO (
"expected id");
1198 ui = strtok (
NULL,
" ");
1201 strtok (
NULL,
" "));
1203 INFO (
"expected count");
1208 INFO (
"unknown command: %s", ui);
1221 struct epoll_event evt, *e;
1222 int app_err = 0, memif_err = 0, en = 0;
1224 uint32_t events = 0;
1225 struct timespec start, end;
1226 memset (&evt, 0,
sizeof (evt));
1227 evt.events = EPOLLIN | EPOLLOUT;
1229 sigemptyset (&sigset);
1230 en = epoll_pwait (
epfd, &evt, 1, timeout, &sigset);
1235 DBG (
"epoll_pwait: %s", strerror (errno));
1241 if (evt.data.fd > 2)
1245 if (evt.events & EPOLLIN)
1247 if (evt.events & EPOLLOUT)
1249 if (evt.events & EPOLLERR)
1255 else if (evt.data.fd == 0)
1261 DBG (
"unexpected event at memif_epfd. fd %d", evt.data.fd);
1266 LOG (
"interrupt: %ld", end.tv_nsec - start.tv_nsec);
1268 if ((app_err < 0) || (memif_err < 0))
1271 DBG (
"user input handler error");
1273 DBG (
"memif control fd handler error");
1283 epfd = epoll_create (1);
1290 out_fd = open (LOG_FILE, O_WRONLY | O_CREAT, S_IRWXO);
1292 INFO (
"Error opening log file: %s", strerror (errno));
1321 DBG (
"poll_event error!");
void icmpr_reset_counters()
int on_interrupt1(memif_conn_handle_t conn, void *private_ctx, uint16_t qid)
int mod_epoll_fd(int fd, uint32_t events)
void * icmpr_send_proc(void *data)
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 ...
int on_interrupt0(memif_conn_handle_t conn, void *private_ctx, uint16_t qid)
int control_fd_update(int fd, uint8_t events)
int icmpr_set_ip(long index, char *ip)
uint8_t * remote_inst_name
pthread_t thread[MAX_CONNS]
#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.
int icmpr_set_rx_mode(long index, long qid, char *mode)
memif_interface_mode_t mode
char * memif_strerror(int err_code)
Memif strerror.
int icmpr_memif_create(int is_master)
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_free_t *memif_free)
Memif initialization.
void icmpr_print_counters()
int icmpr_tx_burst(uint16_t qid)
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.
int add_epoll_fd(int fd, uint32_t events)
memif_queue_details_t * rx_queues
int icmpr_send(long index, long packet_num, char *hw, char *ip)
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 poll_event(int timeout)
void * memif_conn_handle_t
Memif connection handle pointer of type void, pointing to internal structure.
int icmpr_buffer_alloc(long n, uint16_t qid)
int memif_control_fd_handler(int fd, uint8_t events)
Memif control file descriptor 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 memif_delete(memif_conn_handle_t *conn)
Memif delete.
static void print_memif_details()
#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.