vcl: close libc epfd on vls epfd close
[vpp.git] / src / vcl / ldp.c
index ade19a7..3d4c01c 100644 (file)
@@ -26,7 +26,7 @@
 #include <stdarg.h>
 #include <sys/resource.h>
 #include <netinet/tcp.h>
-#include <linux/udp.h>
+#include <netinet/udp.h>
 
 #include <vcl/ldp_socket_wrapper.h>
 #include <vcl/ldp.h>
 #define SOCKADDR_GET_SA(__addr) _addr;
 #endif
 
+#ifndef UDP_SEGMENT
+#define UDP_SEGMENT 103
+#endif
+
 typedef struct ldp_worker_ctx_
 {
   u8 *io_buffer;
@@ -155,15 +159,14 @@ ldp_worker_get_current (void)
 static inline void
 ldp_set_app_name (char *app_name)
 {
-  snprintf (ldp->app_name, LDP_APP_NAME_MAX,
-           "ldp-%d-%s", getpid (), app_name);
+  snprintf (ldp->app_name, LDP_APP_NAME_MAX, "%s-ldp-%d", app_name, getpid ());
 }
 
 static inline char *
 ldp_get_app_name ()
 {
   if (ldp->app_name[0] == '\0')
-    ldp_set_app_name ("app");
+    ldp_set_app_name (program_invocation_short_name);
 
   return ldp->app_name;
 }
@@ -328,16 +331,16 @@ close (int fd)
       epfd = vls_attr (vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
       if (epfd > 0)
        {
+         ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
+         u32 size = sizeof (epfd);
+
          LDBG (0, "fd %d: calling libc_close: epfd %u", fd, epfd);
 
-         rv = libc_close (epfd);
-         if (rv < 0)
-           {
-             u32 size = sizeof (epfd);
-             epfd = 0;
+         libc_close (epfd);
+         ldpw->mq_epfd_added = 0;
 
-             (void) vls_attr (vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &epfd, &size);
-           }
+         epfd = 0;
+         (void) vls_attr (vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &epfd, &size);
        }
       else if (PREDICT_FALSE (epfd < 0))
        {
@@ -1556,17 +1559,14 @@ __recv_chk (int fd, void *buf, size_t n, size_t buflen, int flags)
 
 static inline int
 ldp_vls_sendo (vls_handle_t vlsh, const void *buf, size_t n,
-              vppcom_endpt_tlv_t *ep_tlv, int flags,
+              vppcom_endpt_tlv_t *app_tlvs, int flags,
               __CONST_SOCKADDR_ARG _addr, socklen_t addr_len)
 {
   const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
   vppcom_endpt_t *ep = 0;
   vppcom_endpt_t _ep;
 
-  if (ep_tlv)
-    {
-      _ep.app_data = *ep_tlv;
-    }
+  _ep.app_tlvs = app_tlvs;
 
   if (addr)
     {
@@ -1679,6 +1679,97 @@ recvfrom (int fd, void *__restrict buf, size_t n, int flags,
   return size;
 }
 
+static int
+ldp_parse_cmsg (vls_handle_t vlsh, const struct msghdr *msg,
+               vppcom_endpt_tlv_t **app_tlvs)
+{
+  uint8_t *ad, *at = (uint8_t *) *app_tlvs;
+  vppcom_endpt_tlv_t *adh;
+  struct in_pktinfo *pi;
+  struct cmsghdr *cmsg;
+
+  cmsg = CMSG_FIRSTHDR (msg);
+
+  while (cmsg != NULL)
+    {
+      switch (cmsg->cmsg_level)
+       {
+       case SOL_UDP:
+         switch (cmsg->cmsg_type)
+           {
+           case UDP_SEGMENT:
+             vec_add2 (at, adh, sizeof (*adh));
+             adh->data_type = VCL_UDP_SEGMENT;
+             adh->data_len = sizeof (uint16_t);
+             vec_add2 (at, ad, sizeof (uint16_t));
+             *(uint16_t *) ad = *(uint16_t *) CMSG_DATA (cmsg);
+             break;
+           default:
+             LDBG (1, "SOL_UDP cmsg_type %u not supported", cmsg->cmsg_type);
+             break;
+           }
+         break;
+       case SOL_IP:
+         switch (cmsg->cmsg_type)
+           {
+           case IP_PKTINFO:
+             vec_add2 (at, adh, sizeof (*adh));
+             adh->data_type = VCL_IP_PKTINFO;
+             adh->data_len = sizeof (struct in_addr);
+             vec_add2 (at, ad, sizeof (struct in_addr));
+             pi = (void *) CMSG_DATA (cmsg);
+             clib_memcpy_fast (ad, &pi->ipi_spec_dst,
+                               sizeof (struct in_addr));
+             break;
+           default:
+             LDBG (1, "SOL_IP cmsg_type %u not supported", cmsg->cmsg_type);
+             break;
+           }
+         break;
+       default:
+         LDBG (1, "cmsg_level %u not supported", cmsg->cmsg_level);
+         break;
+       }
+      cmsg = CMSG_NXTHDR ((struct msghdr *) msg, cmsg);
+    }
+  *app_tlvs = (vppcom_endpt_tlv_t *) at;
+  return 0;
+}
+
+static int
+ldp_make_cmsg (vls_handle_t vlsh, struct msghdr *msg)
+{
+  u32 optval, optlen = sizeof (optval);
+  struct cmsghdr *cmsg;
+
+  cmsg = CMSG_FIRSTHDR (msg);
+
+  if (!vls_attr (vlsh, VPPCOM_ATTR_GET_IP_PKTINFO, (void *) &optval, &optlen))
+    return 0;
+
+  if (optval)
+    {
+      vppcom_endpt_t ep;
+      u8 addr_buf[sizeof (struct in_addr)];
+      u32 size = sizeof (ep);
+
+      ep.ip = addr_buf;
+
+      if (!vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size))
+       {
+         struct in_pktinfo pi = {};
+
+         clib_memcpy (&pi.ipi_addr, ep.ip, sizeof (struct in_addr));
+         cmsg->cmsg_level = SOL_IP;
+         cmsg->cmsg_type = IP_PKTINFO;
+         cmsg->cmsg_len = CMSG_LEN (sizeof (pi));
+         clib_memcpy (CMSG_DATA (cmsg), &pi, sizeof (pi));
+       }
+    }
+
+  return 0;
+}
+
 ssize_t
 sendmsg (int fd, const struct msghdr * msg, int flags)
 {
@@ -1690,29 +1781,17 @@ sendmsg (int fd, const struct msghdr * msg, int flags)
   vlsh = ldp_fd_to_vlsh (fd);
   if (vlsh != VLS_INVALID_HANDLE)
     {
+      vppcom_endpt_tlv_t *app_tlvs = 0;
       struct iovec *iov = msg->msg_iov;
       ssize_t total = 0;
       int i, rv = 0;
-      struct cmsghdr *cmsg;
-      uint16_t *valp;
-      vppcom_endpt_tlv_t _app_data;
-      vppcom_endpt_tlv_t *p_app_data = NULL;
 
-      cmsg = CMSG_FIRSTHDR (msg);
-      if (cmsg && cmsg->cmsg_type == UDP_SEGMENT)
-       {
-         p_app_data = &_app_data;
-         valp = (void *) CMSG_DATA (cmsg);
-         p_app_data->data_type = VCL_UDP_SEGMENT;
-         p_app_data->data_len = sizeof (*valp);
-         p_app_data->value = *valp;
-       }
+      ldp_parse_cmsg (vlsh, msg, &app_tlvs);
 
       for (i = 0; i < msg->msg_iovlen; ++i)
        {
-         rv =
-           ldp_vls_sendo (vlsh, iov[i].iov_base, iov[i].iov_len, p_app_data,
-                          flags, msg->msg_name, msg->msg_namelen);
+         rv = ldp_vls_sendo (vlsh, iov[i].iov_base, iov[i].iov_len, app_tlvs,
+                             flags, msg->msg_name, msg->msg_namelen);
          if (rv < 0)
            break;
          else
@@ -1723,6 +1802,8 @@ sendmsg (int fd, const struct msghdr * msg, int flags)
            }
        }
 
+      vec_free (app_tlvs);
+
       if (rv < 0 && total == 0)
        {
          errno = -rv;
@@ -1828,7 +1909,11 @@ recvmsg (int fd, struct msghdr * msg, int flags)
          size = -1;
        }
       else
-       size = total;
+       {
+         if (msg->msg_controllen)
+           ldp_make_cmsg (vlsh, msg);
+         size = total;
+       }
     }
   else
     {
@@ -2114,6 +2199,21 @@ setsockopt (int fd, int level, int optname,
              break;
            }
          break;
+       case SOL_IP:
+         switch (optname)
+           {
+           case IP_PKTINFO:
+             rv = vls_attr (vlsh, VPPCOM_ATTR_SET_IP_PKTINFO, (void *) optval,
+                            &optlen);
+             break;
+           default:
+             LDBG (0,
+                   "ERROR: fd %d: setsockopt SOL_IP: vlsh %u optname %d"
+                   "unsupported!",
+                   fd, vlsh, optname);
+             break;
+           }
+         break;
        default:
          break;
        }
@@ -2385,7 +2485,7 @@ static inline int
 ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
                 int timeout, const sigset_t * sigmask)
 {
-  ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
+  ldp_worker_ctx_t *ldpw;
   double time_to_wait = (double) 0, max_time;
   int libc_epfd, rv = 0;
   vls_handle_t ep_vlsh;
@@ -2398,6 +2498,10 @@ ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
       return -1;
     }
 
+  if (PREDICT_FALSE (vppcom_worker_index () == ~0))
+    vls_register_vcl_worker ();
+
+  ldpw = ldp_worker_get_current ();
   if (epfd == ldpw->vcl_mq_epfd)
     return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);