vcl: accept zero length writes
[vpp.git] / src / vcl / vppcom.c
index 28f46f1..0c6f6e6 100644 (file)
@@ -1987,6 +1987,10 @@ read_again:
     rv = app_recv_stream_raw (rx_fifo, buf, n, 0, peek);
 
   ASSERT (rv >= 0);
+
+  if (peek)
+    return rv;
+
   n_read += rv;
 
   if (svm_fifo_is_empty_cons (rx_fifo))
@@ -2148,8 +2152,12 @@ vppcom_session_write_inline (vcl_worker_t * wrk, vcl_session_t * s, void *buf,
   svm_msg_q_t *mq;
   u8 is_ct;
 
-  if (PREDICT_FALSE (!buf || n == 0))
-    return VPPCOM_EINVAL;
+  /* Accept zero length writes but just return */
+  if (PREDICT_FALSE (!n))
+    return VPPCOM_OK;
+
+  if (PREDICT_FALSE (!buf))
+    return VPPCOM_EFAULT;
 
   if (PREDICT_FALSE (s->flags & VCL_SESSION_F_IS_VEP))
     {
@@ -2159,7 +2167,7 @@ vppcom_session_write_inline (vcl_worker_t * wrk, vcl_session_t * s, void *buf,
     }
 
   if (PREDICT_FALSE (!vcl_session_is_open (s) ||
-                    s->flags & VCL_SESSION_F_SHUTDOWN))
+                    (s->flags & VCL_SESSION_F_SHUTDOWN)))
     {
       VDBG (1, "session %u [0x%llx]: is not open! state 0x%x (%s)",
            s->session_index, s->vpp_handle, s->session_state,
@@ -2713,6 +2721,12 @@ vppcom_epoll_ctl (uint32_t vep_handle, int op, uint32_t session_handle,
          VDBG (0, "EPOLL_CTL_ADD: NULL pointer to epoll_event structure!");
          return VPPCOM_EINVAL;
        }
+      if (s->flags & VCL_SESSION_F_IS_VEP_SESSION)
+       {
+         VDBG (0, "EPOLL_CTL_ADD: %u already epolled!", s->session_index);
+         rv = VPPCOM_EEXIST;
+         goto done;
+       }
       if (vep_session->vep.next_sh != ~0)
        {
          vcl_session_t *next_session;
@@ -2771,7 +2785,7 @@ vppcom_epoll_ctl (uint32_t vep_handle, int op, uint32_t session_handle,
       else if (PREDICT_FALSE (!(s->flags & VCL_SESSION_F_IS_VEP_SESSION)))
        {
          VDBG (0, "sh %u EPOLL_CTL_MOD: not a vep session!", session_handle);
-         rv = VPPCOM_EINVAL;
+         rv = VPPCOM_ENOENT;
          goto done;
        }
       else if (PREDICT_FALSE (s->vep.vep_sh != vep_handle))
@@ -2782,15 +2796,24 @@ vppcom_epoll_ctl (uint32_t vep_handle, int op, uint32_t session_handle,
          goto done;
        }
 
-      /* Generate EPOLLOUT when tx_fifo/ct_tx_fifo not full */
-      if ((event->events & EPOLLOUT) &&
-         !(s->vep.ev.events & EPOLLOUT) && (vcl_session_write_ready (s) > 0))
+      /* Generate EPOLLOUT if session write ready nd event was not on */
+      if ((event->events & EPOLLOUT) && !(s->vep.ev.events & EPOLLOUT) &&
+         (vcl_session_write_ready (s) > 0))
        {
          session_event_t e = { 0 };
          e.event_type = SESSION_IO_EVT_TX;
          e.session_index = s->session_index;
          vec_add1 (wrk->unhandled_evts_vector, e);
        }
+      /* Generate EPOLLIN if session read ready and event was not on */
+      if ((event->events & EPOLLIN) && !(s->vep.ev.events & EPOLLIN) &&
+         (vcl_session_read_ready (s) > 0))
+       {
+         session_event_t e = { 0 };
+         e.event_type = SESSION_IO_EVT_RX;
+         e.session_index = s->session_index;
+         vec_add1 (wrk->unhandled_evts_vector, e);
+       }
       s->vep.et_mask = VEP_DEFAULT_ET_MASK;
       s->vep.ev = *event;
       txf = vcl_session_is_ct (s) ? s->ct_tx_fifo : s->tx_fifo;
@@ -2809,7 +2832,7 @@ vppcom_epoll_ctl (uint32_t vep_handle, int op, uint32_t session_handle,
       if (PREDICT_FALSE (!(s->flags & VCL_SESSION_F_IS_VEP_SESSION)))
        {
          VDBG (0, "EPOLL_CTL_DEL: %u not a vep session!", session_handle);
-         rv = VPPCOM_EINVAL;
+         rv = VPPCOM_ENOENT;
          goto done;
        }
       else if (PREDICT_FALSE (s->vep.vep_sh != vep_handle))
@@ -3870,12 +3893,9 @@ vppcom_session_sendto (uint32_t session_handle, void *buffer,
   vcl_session_t *s;
 
   s = vcl_session_get_w_handle (wrk, session_handle);
-  if (!s)
+  if (PREDICT_FALSE (!s))
     return VPPCOM_EBADFD;
 
-  if (!buffer)
-    return VPPCOM_EINVAL;
-
   if (ep)
     {
       if (!vcl_session_is_cl (s))