libmemif: don't consume rx queue interrupt, if memif_rx_burst fails
[vpp.git] / extras / libmemif / src / main.c
index def51a7..b80dd64 100644 (file)
@@ -309,10 +309,7 @@ memif_control_fd_update (int fd, uint8_t events, void *private_ctx)
 {
   libmemif_main_t *lm;
 
-  if (private_ctx == NULL)
-    return MEMIF_ERR_INVAL_ARG;
-
-  lm = (libmemif_main_t *) private_ctx;
+  lm = (private_ctx == NULL) ? &libmemif_main : (libmemif_main_t *) private_ctx;
 
   if (events & MEMIF_FD_EVENT_DEL)
     return memif_del_epoll_fd (lm, fd);
@@ -559,7 +556,7 @@ memif_init (memif_control_fd_update_t * on_control_fd_update, char *app_name,
          DBG ("eventfd: %s", strerror (err));
          return memif_syscall_error_handler (err);
        }
-      lm->control_fd_update (lm->poll_cancel_fd, MEMIF_FD_EVENT_READ, NULL);
+      lm->control_fd_update (lm->poll_cancel_fd, MEMIF_FD_EVENT_READ, lm->private_ctx);
       DBG ("libmemif event polling initialized");
     }
 
@@ -633,7 +630,7 @@ memif_init (memif_control_fd_update_t * on_control_fd_update, char *app_name,
   lm->arm.it_interval.tv_sec = MEMIF_DEFAULT_RECONNECT_PERIOD_SEC;
   lm->arm.it_interval.tv_nsec = MEMIF_DEFAULT_RECONNECT_PERIOD_NSEC;
 
-  if (lm->control_fd_update (lm->timerfd, MEMIF_FD_EVENT_READ, NULL) < 0)
+  if (lm->control_fd_update (lm->timerfd, MEMIF_FD_EVENT_READ, lm->private_ctx) < 0)
     {
       DBG ("callback type memif_control_fd_update_t error!");
       err = MEMIF_ERR_CB_FDUPDATE;
@@ -718,6 +715,10 @@ memif_per_thread_init (memif_per_thread_main_handle_t * pt_main,
     memif_control_fd_update_register (lm, on_control_fd_update);
   else
     {
+      /* private_ctx only used internally by memif_control_fd_update
+       * pointer to this libmemif main
+       */
+      lm->private_ctx = lm;
       lm->epfd = epoll_create (1);
       memif_control_fd_update_register (lm, memif_control_fd_update);
       if ((lm->poll_cancel_fd = eventfd (0, EFD_NONBLOCK)) < 0)
@@ -911,7 +912,8 @@ memif_socket_start_listening (memif_socket_t * ms)
   elt.key = ms->fd;
   elt.data_struct = ms;
   add_list_elt (lm, &elt, &lm->socket_list, &lm->socket_list_len);
-  lm->control_fd_update (ms->fd, MEMIF_FD_EVENT_READ, ms->private_ctx);
+  /* if lm->private_ctx == lm event polling is done by libmemif */
+  lm->control_fd_update (ms->fd, MEMIF_FD_EVENT_READ, lm->private_ctx);
 
   ms->type = MEMIF_SOCKET_TYPE_LISTENER;
 
@@ -1231,7 +1233,7 @@ int
 memif_request_connection (memif_conn_handle_t c)
 {
   memif_connection_t *conn = (memif_connection_t *) c;
-  libmemif_main_t *lm = get_libmemif_main (conn->args.socket);
+  libmemif_main_t *lm;
   memif_socket_t *ms;
   int err = MEMIF_ERR_SUCCESS;
   int sockfd = -1;
@@ -1241,6 +1243,8 @@ memif_request_connection (memif_conn_handle_t c)
     return MEMIF_ERR_NOCONN;
 
   ms = (memif_socket_t *) conn->args.socket;
+  lm = get_libmemif_main (ms);
+
 
   if (conn->args.is_master || ms->type == MEMIF_SOCKET_TYPE_LISTENER)
     return MEMIF_ERR_INVAL_ARG;
@@ -1267,10 +1271,9 @@ memif_request_connection (memif_conn_handle_t c)
       conn->error_fn = memif_conn_fd_error;
 
       lm->control_list[conn->index].key = conn->fd;
-
       lm->control_fd_update (sockfd,
                             MEMIF_FD_EVENT_READ |
-                            MEMIF_FD_EVENT_WRITE, conn->private_ctx);
+                            MEMIF_FD_EVENT_WRITE, lm->private_ctx);
 
       lm->disconn_slaves--;
       if (lm->disconn_slaves == 0)
@@ -1661,10 +1664,9 @@ memif_msg_queue_free (libmemif_main_t * lm, memif_msg_queue_elt_t ** e)
 int
 memif_disconnect_internal (memif_connection_t * c)
 {
-  uint16_t num;
   int err = MEMIF_ERR_SUCCESS, i;      /* 0 */
   memif_queue_t *mq;
-  libmemif_main_t *lm = get_libmemif_main (c->args.socket);
+  libmemif_main_t *lm;
   memif_list_elt_t *e;
 
   if (c == NULL)
@@ -1673,12 +1675,14 @@ memif_disconnect_internal (memif_connection_t * c)
       return MEMIF_ERR_NOCONN;
     }
 
+  lm = get_libmemif_main (c->args.socket);
+
   c->on_disconnect ((void *) c, c->private_ctx);
 
   if (c->fd > 0)
     {
       memif_msg_send_disconnect (c->fd, (uint8_t *) "interface deleted", 0);
-      lm->control_fd_update (c->fd, MEMIF_FD_EVENT_DEL, c->private_ctx);
+      lm->control_fd_update (c->fd, MEMIF_FD_EVENT_DEL, lm->private_ctx);
       close (c->fd);
     }
   get_list_elt (&e, lm->control_list, lm->control_list_len, c->fd);
@@ -1691,10 +1695,7 @@ memif_disconnect_internal (memif_connection_t * c)
 
   if (c->tx_queues != NULL)
     {
-      num =
-       (c->args.is_master) ? c->run_args.num_m2s_rings : c->
-       run_args.num_s2m_rings;
-      for (i = 0; i < num; i++)
+      for (i = 0; i < c->tx_queues_num; i++)
        {
          mq = &c->tx_queues[i];
          if (mq != NULL)
@@ -1709,13 +1710,11 @@ memif_disconnect_internal (memif_connection_t * c)
       lm->free (c->tx_queues);
       c->tx_queues = NULL;
     }
+  c->tx_queues_num = 0;
 
   if (c->rx_queues != NULL)
     {
-      num =
-       (c->args.is_master) ? c->run_args.num_s2m_rings : c->
-       run_args.num_m2s_rings;
-      for (i = 0; i < num; i++)
+      for (i = 0; i < c->rx_queues_num; i++)
        {
          mq = &c->rx_queues[i];
          if (mq != NULL)
@@ -1724,7 +1723,7 @@ memif_disconnect_internal (memif_connection_t * c)
                {
                  if (c->on_interrupt != NULL)
                    lm->control_fd_update (mq->int_fd, MEMIF_FD_EVENT_DEL,
-                                          c->private_ctx);
+                                          lm->private_ctx);
                  close (mq->int_fd);
                }
              free_list_elt (lm->interrupt_list, lm->interrupt_list_len,
@@ -1735,6 +1734,7 @@ memif_disconnect_internal (memif_connection_t * c)
       lm->free (c->rx_queues);
       c->rx_queues = NULL;
     }
+  c->rx_queues_num = 0;
 
   for (i = 0; i < c->regions_num; i++)
     {
@@ -1794,12 +1794,14 @@ int
 memif_delete_socket (memif_socket_handle_t * sock)
 {
   memif_socket_t *ms = (memif_socket_t *) * sock;
-  libmemif_main_t *lm = get_libmemif_main (ms);
+  libmemif_main_t *lm;
 
   /* check if socket is in use */
-  if (ms == NULL || ms->type != MEMIF_SOCKET_TYPE_NONE)
+  if (ms == NULL || ms->use_count > 0)
     return MEMIF_ERR_INVAL_ARG;
 
+  lm = get_libmemif_main (ms);
+
   lm->free (ms->interface_list);
   ms->interface_list = NULL;
   lm->free (ms->filename);
@@ -1814,7 +1816,7 @@ int
 memif_delete (memif_conn_handle_t * conn)
 {
   memif_connection_t *c = (memif_connection_t *) * conn;
-  libmemif_main_t *lm = get_libmemif_main (c->args.socket);
+  libmemif_main_t *lm;
   memif_socket_t *ms = NULL;
   int err = MEMIF_ERR_SUCCESS;
 
@@ -1832,6 +1834,8 @@ memif_delete (memif_conn_handle_t * conn)
        return err;
     }
 
+  lm = get_libmemif_main (c->args.socket);
+
   free_list_elt_ctx (lm->control_list, lm->control_list_len, c);
 
   ms = (memif_socket_t *) c->args.socket;
@@ -1843,7 +1847,7 @@ memif_delete (memif_conn_handle_t * conn)
       /* stop listening on this socket */
       if (ms->type == MEMIF_SOCKET_TYPE_LISTENER)
        {
-         lm->control_fd_update (ms->fd, MEMIF_FD_EVENT_DEL, ms->private_ctx);
+         lm->control_fd_update (ms->fd, MEMIF_FD_EVENT_DEL, lm->private_ctx);
          free_list_elt (lm->socket_list, lm->socket_list_len, ms->fd);
          close (ms->fd);
          ms->fd = -1;
@@ -1875,11 +1879,16 @@ memif_delete (memif_conn_handle_t * conn)
 int
 memif_connect1 (memif_connection_t * c)
 {
-  libmemif_main_t *lm = get_libmemif_main (c->args.socket);
+  libmemif_main_t *lm;
   memif_region_t *mr;
   memif_queue_t *mq;
   int i;
 
+  if (c == NULL)
+    return MEMIF_ERR_INVAL_ARG;
+
+  lm = get_libmemif_main (c->args.socket);
+
   for (i = 0; i < c->regions_num; i++)
     {
       mr = &c->regions[i];
@@ -1944,7 +1953,7 @@ memif_connect1 (memif_connection_t * c)
     }
 
   lm->control_fd_update (c->fd, MEMIF_FD_EVENT_READ | MEMIF_FD_EVENT_MOD,
-                        c->private_ctx);
+                        lm->private_ctx);
 
   return 0;
 }
@@ -2069,6 +2078,7 @@ memif_init_queues (libmemif_main_t * lm, memif_connection_t * conn)
       mq[x].alloc_bufs = 0;
     }
   conn->tx_queues = mq;
+  conn->tx_queues_num = conn->run_args.num_s2m_rings;
 
   mq =
     (memif_queue_t *) lm->alloc (sizeof (memif_queue_t) *
@@ -2094,6 +2104,7 @@ memif_init_queues (libmemif_main_t * lm, memif_connection_t * conn)
       mq[x].alloc_bufs = 0;
     }
   conn->rx_queues = mq;
+  conn->rx_queues_num = conn->run_args.num_m2s_rings;
 
   return MEMIF_ERR_SUCCESS;
 }
@@ -2102,7 +2113,12 @@ int
 memif_init_regions_and_queues (memif_connection_t * conn)
 {
   memif_region_t *r;
-  libmemif_main_t *lm = get_libmemif_main (conn->args.socket);
+  libmemif_main_t *lm;
+
+  if (conn == NULL)
+    return MEMIF_ERR_INVAL_ARG;
+
+  lm = get_libmemif_main (conn->args.socket);
 
   /* region 0. rings */
   memif_add_region (lm, conn, /* has_buffers */ 0);
@@ -2490,14 +2506,18 @@ memif_rx_burst (memif_conn_handle_t conn, uint16_t qid,
   *rx = 0;
 
   uint64_t b;
-  ssize_t r = read (mq->int_fd, &b, sizeof (b));
-  if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
-    return memif_syscall_error_handler (errno);
+  ssize_t r;
 
   cur_slot = (c->args.is_master) ? mq->last_head : mq->last_tail;
   last_slot = (c->args.is_master) ? ring->head : ring->tail;
   if (cur_slot == last_slot)
-    return MEMIF_ERR_SUCCESS;
+    {
+      r = read (mq->int_fd, &b, sizeof (b));
+      if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
+                       return memif_syscall_error_handler (errno);
+
+      return MEMIF_ERR_SUCCESS;
+    }
 
   ns = last_slot - cur_slot;
 
@@ -2546,6 +2566,10 @@ memif_rx_burst (memif_conn_handle_t conn, uint16_t qid,
       return MEMIF_ERR_NOBUF;
     }
 
+  r = read (mq->int_fd, &b, sizeof (b));
+  if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
+    return memif_syscall_error_handler (errno);
+
   return MEMIF_ERR_SUCCESS;    /* 0 */
 }
 
@@ -2554,7 +2578,7 @@ memif_get_details (memif_conn_handle_t conn, memif_details_t * md,
                   char *buf, ssize_t buflen)
 {
   memif_connection_t *c = (memif_connection_t *) conn;
-  libmemif_main_t *lm = get_libmemif_main (c->args.socket);
+  libmemif_main_t *lm;
   memif_socket_t *ms;
   int err = MEMIF_ERR_SUCCESS, i;
   ssize_t l0 = 0, l1;
@@ -2563,6 +2587,7 @@ memif_get_details (memif_conn_handle_t conn, memif_details_t * md,
     return MEMIF_ERR_NOCONN;
 
   ms = (memif_socket_t *) c->args.socket;
+  lm = get_libmemif_main (ms);
 
   l1 = strlen ((char *) c->args.interface_name);
   if (l0 + l1 < buflen)
@@ -2736,8 +2761,11 @@ int
 memif_cleanup ()
 {
   libmemif_main_t *lm = &libmemif_main;
+  int err;
 
-  memif_delete_socket ((memif_socket_handle_t *) & lm->default_socket);
+  err = memif_delete_socket ((memif_socket_handle_t *) & lm->default_socket);
+  if (err != MEMIF_ERR_SUCCESS)
+    return err;
 
   if (lm->control_list)
     lm->free (lm->control_list);