vcl: ldp support SO_ORIGINAL_DST
[vpp.git] / src / vcl / vppcom.c
index 424b14b..06a345d 100644 (file)
@@ -351,6 +351,11 @@ vcl_session_accepted_handler (vcl_worker_t * wrk, session_accepted_msg_t * mp,
 
   session->vpp_handle = mp->handle;
   session->session_state = VCL_STATE_READY;
+  if (mp->rmt.is_ip4)
+    {
+      session->original_dst_ip4 = mp->original_dst_ip4;
+      session->original_dst_port = mp->original_dst_port;
+    }
   session->transport.rmt_port = mp->rmt.port;
   session->transport.is_ip4 = mp->rmt.is_ip4;
   clib_memcpy_fast (&session->transport.rmt_ip, &mp->rmt.ip,
@@ -3414,13 +3419,13 @@ vcl_epoll_wait_handle_lt (vcl_worker_t *wrk, struct epoll_event *events,
        {
          events[*n_evts].events = evt_flags;
          events[*n_evts].data.u64 = evt_data;
-         *n_evts += 1;
-         add_event = 0;
-         evt_flags = 0;
          if (EPOLLONESHOT & s->vep.ev.events)
            s->vep.ev.events = EPOLLHUP | EPOLLERR;
          if (evt_flags & EPOLLHUP)
            s->vep.ev.events = 0;
+         *n_evts += 1;
+         add_event = 0;
+         evt_flags = 0;
          if (*n_evts == maxevents)
            {
              wrk->ep_lt_current = next;
@@ -3611,6 +3616,33 @@ vppcom_session_attr (uint32_t session_handle, uint32_t op,
        rv = VPPCOM_EINVAL;
       break;
 
+    case VPPCOM_ATTR_GET_ORIGINAL_DST:
+      if (!session->transport.is_ip4)
+       {
+         /* now original dst only support ipv4*/
+         rv = VPPCOM_EAFNOSUPPORT;
+         break;
+       }
+      if (PREDICT_TRUE (buffer && buflen && (*buflen >= sizeof (*ep)) &&
+                       ep->ip))
+       {
+         ep->is_ip4 = session->transport.is_ip4;
+         ep->port = session->original_dst_port;
+         clib_memcpy_fast (ep->ip, &session->original_dst_ip4,
+                           sizeof (ip4_address_t));
+         *buflen = sizeof (*ep);
+         VDBG (1,
+               "VPPCOM_ATTR_GET_ORIGINAL_DST: sh %u, is_ip4 = %u, addr = %U"
+               " port %d",
+               session_handle, ep->is_ip4, vcl_format_ip4_address,
+               (ip4_address_t *) (&session->original_dst_ip4),
+               ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
+               clib_net_to_host_u16 (ep->port));
+       }
+      else
+       rv = VPPCOM_EINVAL;
+      break;
+
     case VPPCOM_ATTR_SET_LCL_ADDR:
       if (PREDICT_TRUE (buffer && buflen &&
                        (*buflen >= sizeof (*ep)) && ep->ip))