52 #include <sys/socket.h> 53 #include <sys/epoll.h> 54 #include <sys/eventfd.h> 59 #include <kernel_appif.h> 60 #include <utils_nbqueue.h> 61 #include <tas_memif.h> 65 #define EP_LISTEN (NULL) 67 #define EP_NOTIFY ((void *) (-1)) 69 static int uxsocket_init(
void);
70 static void *uxsocket_thread(
void *arg);
71 static void uxsocket_accept(
void);
72 static void uxsocket_notify(
void);
73 static void uxsocket_error(
struct application *app);
74 static void uxsocket_receive(
struct application *app);
75 static void uxsocket_notify_app(
struct application *app);
105 if (uxsocket_init()) {
110 for (i = FLEXNIC_PL_APPST_CTX_NUM; i > 0; i--) {
111 if ((adb = malloc(
sizeof(*adb))) == NULL) {
112 perror(
"appif_init: malloc doorbell failed");
117 free_doorbells = adb;
123 if (pthread_create(&
pt_ux, NULL, uxsocket_thread, NULL) != 0) {
142 while ((p = nbqueue_deq(&
ux_to_poll)) != NULL) {
148 for (app = applications; app != NULL; app = app->next) {
150 if (app->need_reg_ctx != NULL) {
151 ctx = app->need_reg_ctx;
152 app->need_reg_ctx = NULL;
154 for (i = 0; i < tas_info->
cores_num; i++) {
155 rxq_offs[i] = app->resp->flexnic_qs[i].rxq_off;
156 txq_offs[i] = app->resp->flexnic_qs[i].txq_off;
160 app->req.rxq_len, txq_offs, app->req.txq_len, ctx->evfd) != 0)
162 fprintf(stderr,
"appif_poll: registering context failed\n");
168 ret = write(
notifyfd, &cnt,
sizeof(cnt));
170 perror(
"appif_poll: error writing to notify fd");
174 for (ctx = app->contexts; ctx != NULL; ctx = ctx->next) {
175 if (ctx->ready == 0) {
186 static int uxsocket_init(
void)
189 struct sockaddr_un saun;
190 struct epoll_event ev;
192 if ((fd =
socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
193 perror(
"uxsocket_init: socket failed");
197 memset(&saun, 0,
sizeof(saun));
198 saun.sun_family = AF_UNIX;
199 memcpy(saun.sun_path, KERNEL_SOCKET_PATH,
sizeof(KERNEL_SOCKET_PATH));
200 if (bind(fd, (
struct sockaddr *) &saun,
sizeof(saun))) {
201 perror(
"uxsocket_init: bind failed");
206 perror(
"uxsocket_init: listen failed");
210 if ((nfd = eventfd(0, EFD_NONBLOCK)) == -1) {
211 perror(
"uxsocket_init: eventfd failed");
214 if ((efd = epoll_create1(0)) == -1) {
215 perror(
"uxsocket_init: epoll_create1 failed");
221 if (epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ev) != 0) {
222 perror(
"uxsocket_init: epoll_ctl listen failed");
228 if (epoll_ctl(efd, EPOLL_CTL_ADD, nfd, &ev) != 0) {
229 perror(
"uxsocket_init: epoll_ctl notify failed");
246 static void *uxsocket_thread(
void *arg)
249 struct epoll_event evs[32];
254 n = epoll_wait(
epfd, evs, 32, -1);
260 perror(
"uxsocket_thread: epoll_wait");
264 for (i = 0; i < n; i++) {
265 app = evs[i].data.ptr;
271 if ((evs[i].events & (EPOLLRDHUP | EPOLLHUP | EPOLLERR)) != 0) {
273 }
else if ((evs[i].events & EPOLLIN) != 0) {
274 uxsocket_receive(app);
280 notify_slowpath_core();
286 static void uxsocket_accept(
void)
290 struct epoll_event ev;
297 if ((cfd = accept(
uxfd, NULL, NULL)) < 0) {
298 fprintf(stderr,
"uxsocket_accept: accept failed\n");
304 .iov_len =
sizeof(uint32_t),
307 char buf[CMSG_SPACE(
sizeof(
int) * 4)];
308 struct cmsghdr align;
310 struct msghdr msg = {
315 .msg_control = u.buf,
316 .msg_controllen =
sizeof(u.buf),
320 struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
321 cmsg->cmsg_level = SOL_SOCKET;
322 cmsg->cmsg_type = SCM_RIGHTS;
323 cmsg->cmsg_len = CMSG_LEN(
sizeof(
int));
325 pfd = (
int *) CMSG_DATA(cmsg);
326 *pfd = kernel_notifyfd;
329 if((tx = sendmsg(cfd, &msg, 0)) !=
sizeof(uint32_t)) {
330 fprintf(stderr,
"tx == %zd\n", tx);
332 fprintf(stderr,
"errno == %d\n", errno);
342 memset(&msg, 0,
sizeof(msg));
345 msg.msg_control = u.buf;
346 msg.msg_controllen =
sizeof(u.buf);
350 cmsg->cmsg_level = SOL_SOCKET;
351 cmsg->cmsg_type = SCM_RIGHTS;
352 cmsg->cmsg_len = CMSG_LEN(
sizeof(
int) * n);
354 pfd = (
int *) CMSG_DATA(cmsg);
355 for (j = 0; j < n; j++) {
356 pfd[j] = ctxs[off++]->evfd;
360 if((tx = sendmsg(cfd, &msg, 0)) != 1) {
361 fprintf(stderr,
"tx fd == %zd\n", tx);
363 fprintf(stderr,
"errno fd == %d\n", errno);
370 if ((app = malloc(
sizeof(*app))) == NULL) {
371 fprintf(stderr,
"uxsocket_accept: malloc of app struct failed\n");
376 sz =
sizeof(*app->resp) +
377 tas_info->
cores_num *
sizeof(app->resp->flexnic_qs[0]);
379 if ((app->resp = malloc(sz)) == NULL) {
380 fprintf(stderr,
"uxsocket_accept: malloc of app resp struct failed\n");
387 ev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR;
389 if (epoll_ctl(
epfd, EPOLL_CTL_ADD, cfd, &ev) != 0) {
390 perror(
"uxsocket_accept: epoll_ctl failed");
398 app->contexts = NULL;
399 app->need_reg_ctx = NULL;
402 app->listeners = NULL;
407 static void uxsocket_notify(
void)
414 ret = read(
notifyfd, &x,
sizeof(x));
415 if (ret == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
416 perror(
"uxsocket_notify: read on notifyfd failed");
420 while ((p = nbqueue_deq(&
poll_to_ux)) != NULL) {
422 uxsocket_notify_app(app);
426 static void uxsocket_error(
struct application *app)
432 static void uxsocket_receive(
struct application *app)
437 uintptr_t off_in, off_out, off_rxq, off_txq;
438 size_t kin_qsize, kout_qsize, ctx_sz;
439 struct epoll_event ev;
445 .iov_base = &app->req,
446 .iov_len =
sizeof(app->req) - app->req_rx,
449 char buf[CMSG_SPACE(
sizeof(
int))];
450 struct cmsghdr align;
452 struct msghdr msg = {
457 .msg_control = u.buf,
458 .msg_controllen =
sizeof(u.buf),
461 rx = recvmsg(app->fd, &msg, 0);
463 if(msg.msg_controllen > 0) {
464 struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
465 assert(cmsg->cmsg_len == CMSG_LEN(
sizeof(
int)));
466 int* data = (
int*) CMSG_DATA(cmsg);
471 perror(
"uxsocket_receive: recv failed");
472 goto error_abort_app;
473 }
else if (rx + app->req_rx <
sizeof(app->req)) {
483 ctx_sz =
sizeof(*ctx) + tas_info->
cores_num *
sizeof(ctx->handles[0]);
484 if ((ctx = malloc(ctx_sz)) == NULL) {
485 perror(
"uxsocket_receive: ctx malloc failed");
486 goto error_ctxmalloc;
495 fprintf(stderr,
"uxsocket_receive: packetmem_alloc in failed\n");
496 goto error_pktmem_in;
499 fprintf(stderr,
"uxsocket_receive: packetmem_alloc out failed\n");
500 goto error_pktmem_out;
504 for (i = 0; i < tas_info->
cores_num; i++) {
508 fprintf(stderr,
"uxsocket_receive: packetmem_alloc rxq failed\n");
514 fprintf(stderr,
"uxsocket_receive: packetmem_alloc txq failed\n");
518 memset((uint8_t *) tas_shm + off_rxq, 0, app->req.rxq_len);
519 memset((uint8_t *) tas_shm + off_txq, 0, app->req.txq_len);
520 app->resp->flexnic_qs[i].rxq_off = off_rxq;
521 app->resp->flexnic_qs[i].txq_off = off_txq;
525 if ((ctx->doorbell = free_doorbells) == NULL) {
526 fprintf(stderr,
"uxsocket_receive: allocating doorbell failed\n");
529 free_doorbells = ctx->doorbell->next;
535 ctx->kin_handle = pm_in;
536 ctx->kin_base = (uint8_t *) tas_shm + off_in;
539 memset(ctx->kin_base, 0, kin_qsize);
541 ctx->kout_handle = pm_out;
542 ctx->kout_base = (uint8_t *) tas_shm + off_out;
543 ctx->kout_len = kout_qsize /
sizeof(
struct kernel_appin);
545 memset(ctx->kout_base, 0, kout_qsize);
551 ctx->next = app->contexts;
556 app->resp->app_out_off = off_in;
557 app->resp->app_out_len = kin_qsize;
558 app->resp->app_in_off = off_out;
559 app->resp->app_in_len = kout_qsize;
560 app->resp->flexnic_db_id = ctx->doorbell->id;
561 app->resp->flexnic_qs_num = tas_info->
cores_num;
562 app->resp->status = 0;
565 ev.events = EPOLLRDHUP | EPOLLERR;
567 if (epoll_ctl(
epfd, EPOLL_CTL_MOD, app->fd, &ev) != 0) {
569 perror(
"uxsocket_receive: epoll_ctl failed");
573 app->need_reg_ctx_done = ctx;
575 app->need_reg_ctx = ctx;
578 tx = send(app->fd, &resp,
sizeof(resp), 0);
580 perror(
"uxsocket_receive: send failed");
581 goto error_abort_app;
582 }
else if (tx <
sizeof(resp)) {
584 fprintf(stderr,
"uxsocket_receive: short send for response (TODO)\n");
585 goto error_abort_app;
607 static void uxsocket_notify_app(
struct application *app)
610 struct epoll_event ev;
613 if (app->comp.status != 0) {
615 fprintf(stderr,
"uxsocket_notify_app: status = %d, terminating app\n",
621 ctx = app->need_reg_ctx_done;
625 tx = send(app->fd, app->resp, app->resp_sz, 0);
627 perror(
"uxsocket_notify_app: send failed");
629 }
else if (tx < app->resp_sz) {
631 fprintf(stderr,
"uxsocket_notify_app: short send for response (TODO)\n");
636 ev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR;
638 if (epoll_ctl(
epfd, EPOLL_CTL_MOD, app->fd, &ev) != 0) {
640 perror(
"uxsocket_notify_app: epoll_ctl failed");
static struct application * applications
static uint16_t app_id_next
static struct nbqueue poll_to_ux
int packetmem_alloc(size_t length, uintptr_t *off, struct packetmem_handle **handle)
static struct nbqueue ux_to_poll
void packetmem_free(struct packetmem_handle *handle)
int nicif_appctx_add(uint16_t appid, uint32_t db, uint64_t *rxq_base, uint32_t rxq_len, uint64_t *txq_base, uint32_t txq_len, int evfd)
static struct app_doorbell * free_doorbells
unsigned appif_poll(void)
unsigned appif_ctx_poll(struct application *app, struct app_context *ctx)