session vcl: add support for vcl transport attributes 73/41673/6
authorFlorin Coras <[email protected]>
Thu, 3 Oct 2024 07:34:03 +0000 (00:34 -0700)
committerDave Wallace <[email protected]>
Fri, 4 Oct 2024 17:59:01 +0000 (17:59 +0000)
Session layer can push transport attributes to vcl sessions which are
stored as vector for session lifetime.

Store original_dst_ip and port when available in vcl session attribute
vector.

Type: feature

Change-Id: Iab6c65ddcfed220fc919f564cd19083561812faf
Signed-off-by: Florin Coras <[email protected]>
src/vcl/vcl_private.h
src/vcl/vppcom.c
src/vcl/vppcom.h
src/vnet/session/application_interface.h
src/vnet/session/transport_types.h

index b89052f..0f1a6d2 100644 (file)
@@ -181,8 +181,7 @@ typedef struct vcl_session_
   elog_track_t elog_track;
 #endif
 
-  u16 original_dst_port; /**< original dst port (network order) */
-  u32 original_dst_ip4;         /**< original dst ip4 (network order) */
+  transport_endpt_attr_t *tep_attrs; /**< vector of attributes */
 } vcl_session_t;
 
 typedef struct vppcom_cfg_t_
@@ -409,6 +408,7 @@ vcl_session_free (vcl_worker_t * wrk, vcl_session_t * s)
   vcl_session_detach_fifos (s);
   if (s->ext_config)
     clib_mem_free (s->ext_config);
+  vec_free (s->tep_attrs);
   pool_put (wrk->sessions, s);
 }
 
@@ -664,6 +664,18 @@ vcl_session_clear_attr (vcl_session_t * s, u8 attr)
   s->attributes &= ~(1 << attr);
 }
 
+static inline transport_endpt_attr_t *
+vcl_session_tep_attr_get (vcl_session_t *s, transport_endpt_attr_type_t at)
+{
+  transport_endpt_attr_t *tepa;
+  vec_foreach (tepa, s->tep_attrs)
+    {
+      if (tepa->type == at)
+       return tepa;
+    }
+  return 0;
+}
+
 static inline session_evt_type_t
 vcl_session_dgram_tx_evt (vcl_session_t *s, session_evt_type_t et)
 {
index 2ebb1d8..1db0a96 100644 (file)
@@ -351,10 +351,16 @@ 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)
+  if (mp->rmt.is_ip4 && mp->original_dst_port)
     {
-      session->original_dst_ip4 = mp->original_dst_ip4;
-      session->original_dst_port = mp->original_dst_port;
+      transport_endpt_attr_t *tep_attr;
+      vec_add2 (session->tep_attrs, tep_attr, 1);
+      /* Expecting to receive this on accepted connections
+       * and the external transport endpoint received is
+       * the local one, prior to something like nat */
+      tep_attr->type = TRANSPORT_ENDPT_ATTR_EXT_ENDPT;
+      tep_attr->ext_endpt.port = mp->original_dst_port;
+      tep_attr->ext_endpt.ip.ip4.as_u32 = mp->original_dst_ip4;
     }
   session->transport.rmt_port = mp->rmt.port;
   session->transport.is_ip4 = mp->rmt.is_ip4;
@@ -988,6 +994,24 @@ vcl_worker_rpc_handler (vcl_worker_t * wrk, void *data)
   (vcm->wrk_rpc_fn) (((session_app_wrk_rpc_msg_t *) data)->data);
 }
 
+static void
+vcl_session_transport_attr_handler (vcl_worker_t *wrk, void *data)
+{
+  session_transport_attr_msg_t *mp = (session_transport_attr_msg_t *) data;
+  vcl_session_t *s;
+
+  s = vcl_session_get_w_vpp_handle (wrk, mp->handle);
+  if (!s)
+    {
+      VDBG (0, "session transport attr with wrong handle %llx", mp->handle);
+      return;
+    }
+
+  VDBG (0, "session %u [0x%llx]: transport attr %u", s->session_index,
+       s->vpp_handle, mp->attr.type);
+  vec_add1 (s->tep_attrs, mp->attr);
+}
+
 static void
 vcl_session_transport_attr_reply_handler (vcl_worker_t *wrk, void *data)
 {
@@ -1129,6 +1153,9 @@ vcl_handle_mq_event (vcl_worker_t * wrk, session_event_t * e)
     case SESSION_CTRL_EVT_APP_WRK_RPC:
       vcl_worker_rpc_handler (wrk, e->data);
       break;
+    case SESSION_CTRL_EVT_TRANSPORT_ATTR:
+      vcl_session_transport_attr_handler (wrk, e->data);
+      break;
     case SESSION_CTRL_EVT_TRANSPORT_ATTR_REPLY:
       vcl_session_transport_attr_reply_handler (wrk, e->data);
       break;
@@ -2607,6 +2634,9 @@ vcl_select_handle_mq_event (vcl_worker_t * wrk, session_event_t * e,
     case SESSION_CTRL_EVT_APP_WRK_RPC:
       vcl_worker_rpc_handler (wrk, e->data);
       break;
+    case SESSION_CTRL_EVT_TRANSPORT_ATTR:
+      vcl_session_transport_attr_handler (wrk, e->data);
+      break;
     default:
       clib_warning ("unhandled: %u", e->event_type);
       break;
@@ -3382,6 +3412,9 @@ vcl_epoll_wait_handle_mq_event (vcl_worker_t * wrk, session_event_t * e,
     case SESSION_CTRL_EVT_APP_WRK_RPC:
       vcl_worker_rpc_handler (wrk, e->data);
       break;
+    case SESSION_CTRL_EVT_TRANSPORT_ATTR:
+      vcl_session_transport_attr_handler (wrk, e->data);
+      break;
     default:
       VDBG (0, "unhandled: %u", e->event_type);
       break;
@@ -3672,7 +3705,7 @@ vppcom_session_attr (uint32_t session_handle, uint32_t op,
   vcl_worker_t *wrk = vcl_worker_get_current ();
   u32 *flags = buffer;
   vppcom_endpt_t *ep = buffer;
-  transport_endpt_attr_t tea;
+  transport_endpt_attr_t tea, *tepap;
   vcl_session_t *session;
   int rv = VPPCOM_OK;
 
@@ -3795,24 +3828,49 @@ vppcom_session_attr (uint32_t session_handle, uint32_t op,
          rv = VPPCOM_EAFNOSUPPORT;
          break;
        }
-      if (PREDICT_TRUE (buffer && buflen && (*buflen >= sizeof (*ep)) &&
-                       ep->ip))
+      if (PREDICT_FALSE (!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));
+         rv = VPPCOM_EINVAL;
+         break;
        }
-      else
-       rv = VPPCOM_EINVAL;
+
+      tepap =
+       vcl_session_tep_attr_get (session, TRANSPORT_ENDPT_ATTR_EXT_ENDPT);
+      if (!tepap)
+       {
+         rv = VPPCOM_EINVAL;
+         break;
+       }
+      vcl_ip_copy_to_ep (&tepap->ext_endpt.ip, ep, tepap->ext_endpt.is_ip4);
+      ep->port = tepap->ext_endpt.port;
+      *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 *) ep->ip,
+           ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
+           clib_net_to_host_u16 (ep->port));
+      break;
+
+    case VPPCOM_ATTR_GET_EXT_ENDPT:
+      if (PREDICT_FALSE (!buffer || !buflen || (*buflen < sizeof (*ep)) ||
+                        !ep->ip))
+       {
+         rv = VPPCOM_EINVAL;
+         break;
+       }
+      tepap =
+       vcl_session_tep_attr_get (session, TRANSPORT_ENDPT_ATTR_EXT_ENDPT);
+      if (!tepap)
+       {
+         rv = VPPCOM_EINVAL;
+         break;
+       }
+      vcl_ip_copy_to_ep (&tepap->ext_endpt.ip, ep, tepap->ext_endpt.is_ip4);
+      ep->port = tepap->ext_endpt.port;
       break;
 
     case VPPCOM_ATTR_SET_LCL_ADDR:
index 164dc37..a11db95 100644 (file)
@@ -186,6 +186,7 @@ typedef enum
   VPPCOM_ATTR_GET_IP_PKTINFO,
   VPPCOM_ATTR_GET_ORIGINAL_DST,
   VPPCOM_ATTR_GET_NWRITEQ,
+  VPPCOM_ATTR_GET_EXT_ENDPT,
 } vppcom_attr_op_t;
 
 typedef struct _vcl_poll
index f175e4a..1702a37 100644 (file)
@@ -396,6 +396,7 @@ typedef struct session_accepted_msg_
   transport_endpoint_t lcl;
   transport_endpoint_t rmt;
   u8 flags;
+  /* TODO(fcoras) maybe refactor to pass as transport attr */
   u32 original_dst_ip4;
   u16 original_dst_port;
 } __clib_packed session_accepted_msg_t;
index c92cb79..f6058c6 100644 (file)
@@ -259,7 +259,8 @@ typedef enum transport_endpt_attr_flag_
   _ (u64, next_output_node, NEXT_OUTPUT_NODE)                                 \
   _ (u16, mss, MSS)                                                           \
   _ (u8, flags, FLAGS)                                                        \
-  _ (u8, cc_algo, CC_ALGO)
+  _ (u8, cc_algo, CC_ALGO)                                                    \
+  _ (transport_endpoint_t, ext_endpt, EXT_ENDPT)
 
 typedef enum transport_endpt_attr_type_
 {