session udp: support connect on listeners 27/26227/18
authorFlorin Coras <fcoras@cisco.com>
Sun, 29 Mar 2020 18:54:04 +0000 (18:54 +0000)
committerFlorin Coras <fcoras@cisco.com>
Wed, 1 Apr 2020 20:24:38 +0000 (20:24 +0000)
Type: feature

Signed-off-by: Florin Coras <fcoras@cisco.com>
Change-Id: I6aaaec20a2b6d4c6ddfbe659d9402acc1be2f7e2

src/plugins/quic/quic.c
src/vcl/vcl_private.c
src/vcl/vcl_private.h
src/vcl/vppcom.c
src/vnet/session/application_interface.h
src/vnet/session/session_node.c
src/vnet/session/session_types.h

index eeea8ab..8689583 100644 (file)
@@ -1320,7 +1320,7 @@ quic_connect_connection (session_endpoint_cfg_t * sep)
   app = application_get (app_wrk->app_index);
   ctx->parent_app_id = app_wrk->app_index;
   cargs->sep_ext.ns_index = app->ns_index;
-  cargs->sep_ext.flags = TRANSPORT_CFG_F_CONNECTED;
+  cargs->sep_ext.transport_flags = TRANSPORT_CFG_F_CONNECTED;
 
   ctx->crypto_engine = sep->crypto_engine;
   ctx->ckpair_index = sep->ckpair_index;
index 3cb76c6..14582ce 100644 (file)
@@ -308,6 +308,8 @@ vcl_cleanup_bapi (void)
 int
 vcl_session_read_ready (vcl_session_t * session)
 {
+  u32 max_deq;
+
   /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
   if (PREDICT_FALSE (session->is_vep))
     {
@@ -335,7 +337,23 @@ vcl_session_read_ready (vcl_session_t * session)
   if (vcl_session_is_ct (session))
     return svm_fifo_max_dequeue_cons (session->ct_rx_fifo);
 
-  return svm_fifo_max_dequeue_cons (session->rx_fifo);
+  max_deq = svm_fifo_max_dequeue_cons (session->rx_fifo);
+
+  if (session->is_dgram)
+    {
+      session_dgram_pre_hdr_t ph;
+
+      if (max_deq <= SESSION_CONN_HDR_LEN)
+       return 0;
+      if (svm_fifo_peek (session->rx_fifo, 0, sizeof (ph), (u8 *) & ph) < 0)
+       return 0;
+      if (ph.data_length + SESSION_CONN_HDR_LEN > max_deq)
+       return 0;
+
+      return ph.data_length;
+    }
+
+  return max_deq;
 }
 
 int
index 650d254..433e08e 100644 (file)
@@ -149,6 +149,11 @@ do {                                            \
 #define VCL_SESS_ATTR_TEST(ATTR, VAL)           \
   ((ATTR) & (1 << (VAL)) ? 1 : 0)
 
+typedef enum vcl_session_flags_
+{
+  VCL_SESSION_F_CONNECTED,
+} __clib_packed vcl_session_flags_t;
+
 typedef struct
 {
   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
@@ -167,6 +172,7 @@ typedef struct
   /* Socket configuration state */
   u8 is_vep;
   u8 is_vep_session;
+  vcl_session_flags_t flags;
   /* VCL session index of the listening session (if any) */
   u32 listener_index;
   /* Accepted sessions on this listener */
index 03bd32c..ba1f116 100644 (file)
@@ -231,7 +231,10 @@ vcl_send_session_connect (vcl_worker_t * wrk, vcl_session_t * s)
   clib_memcpy_fast (&mp->ip, &s->transport.rmt_ip, sizeof (mp->ip));
   clib_memcpy_fast (&mp->lcl_ip, &s->transport.lcl_ip, sizeof (mp->lcl_ip));
   mp->port = s->transport.rmt_port;
+  mp->lcl_port = s->transport.lcl_port;
   mp->proto = s->session_type;
+  if (s->flags & VCL_SESSION_F_CONNECTED)
+    mp->flags |= TRANSPORT_CFG_F_CONNECTED;
   app_send_ctrl_evt_to_vpp (mq, app_evt);
 }
 
@@ -612,11 +615,21 @@ vcl_session_unlisten_reply_handler (vcl_worker_t * wrk, void *data)
   vcl_session_t *s;
 
   s = vcl_session_get_w_vpp_handle (wrk, mp->handle);
-  if (!s || s->session_state != STATE_DISCONNECT)
+  if (!s)
     {
       VDBG (0, "Unlisten reply with wrong handle %llx", mp->handle);
       return;
     }
+  if (s->session_state != STATE_DISCONNECT)
+    {
+      /* Connected udp listener */
+      if (s->session_type == VPPCOM_PROTO_UDP
+         && s->session_state == STATE_CLOSED)
+       return;
+
+      VDBG (0, "Unlisten session in wrong state %llx", mp->handle);
+      return;
+    }
 
   if (mp->retval)
     VDBG (0, "ERROR: session %u [0xllx]: unlisten failed: %U",
@@ -1686,13 +1699,24 @@ vppcom_session_connect (uint32_t session_handle, vppcom_endpt_t * server_ep)
       return VPPCOM_OK;
     }
 
+  /* Attempt to connect a connectionless listener */
+  if (PREDICT_FALSE (session->session_state & STATE_LISTEN))
+    {
+      if (session->session_type != VPPCOM_PROTO_UDP)
+       return VPPCOM_EINVAL;
+      vcl_send_session_unlisten (wrk, session);
+      session->session_state = STATE_CLOSED;
+    }
+
   session->transport.is_ip4 = server_ep->is_ip4;
   vcl_ip_copy_from_ep (&session->transport.rmt_ip, server_ep);
   session->transport.rmt_port = server_ep->port;
   session->parent_handle = VCL_INVALID_SESSION_HANDLE;
+  session->flags |= VCL_SESSION_F_CONNECTED;
 
-  VDBG (0, "session handle %u: connecting to server %s %U "
+  VDBG (0, "session handle %u (%s): connecting to peer %s %U "
        "port %d proto %s", session_handle,
+       vppcom_session_state_str (session->session_state),
        session->transport.is_ip4 ? "IPv4" : "IPv6",
        format_ip46_address,
        &session->transport.rmt_ip, session->transport.is_ip4 ?
@@ -3562,7 +3586,7 @@ vppcom_session_recvfrom (uint32_t session_handle, void *buffer,
       return VPPCOM_EAFNOSUPPORT;
     }
 
-  if (ep && !rv)
+  if (ep && rv > 0)
     {
       session = vcl_session_get_w_handle (wrk, session_handle);
       if (session->transport.is_ip4)
@@ -3594,7 +3618,8 @@ vppcom_session_sendto (uint32_t session_handle, void *buffer,
       if (!s)
        return VPPCOM_EBADFD;
 
-      if (s->session_type != VPPCOM_PROTO_UDP)
+      if (s->session_type != VPPCOM_PROTO_UDP
+         || (s->flags & VCL_SESSION_F_CONNECTED))
        return VPPCOM_EINVAL;
 
       /* Session not connected/bound in vpp. Create it by 'connecting' it */
index bf94676..b1ab847 100644 (file)
@@ -387,6 +387,7 @@ typedef struct session_connect_msg_
   u32 wrk_index;
   u32 vrf;
   u16 port;
+  u16 lcl_port;
   u8 proto;
   u8 is_ip4;
   ip46_address_t ip;
@@ -681,7 +682,7 @@ app_recv_dgram_raw (svm_fifo_t * f, u8 * buf, u32 len,
   int rv;
 
   max_deq = svm_fifo_max_dequeue_cons (f);
-  if (max_deq < sizeof (session_dgram_hdr_t))
+  if (max_deq <= sizeof (session_dgram_hdr_t))
     {
       if (clear_evt)
        svm_fifo_unset_event (f);
@@ -699,6 +700,7 @@ app_recv_dgram_raw (svm_fifo_t * f, u8 * buf, u32 len,
   rv = svm_fifo_peek (f, ph.data_offset + SESSION_CONN_HDR_LEN, len, buf);
   if (peek)
     return rv;
+  ASSERT (rv > 0);
   ph.data_offset += rv;
   if (ph.data_offset == ph.data_length)
     svm_fifo_dequeue_drop (f, ph.data_length + SESSION_CONN_HDR_LEN);
index 2a4bb6b..66300bc 100644 (file)
@@ -113,6 +113,7 @@ session_mq_connect_handler (void *data)
   a->sep.transport_proto = mp->proto;
   a->sep.peer.fib_index = mp->vrf;
   clib_memcpy_fast (&a->sep.peer.ip, &mp->lcl_ip, sizeof (mp->lcl_ip));
+  a->sep.peer.port = mp->lcl_port;
   a->sep.peer.sw_if_index = ENDPOINT_INVALID_INDEX;
   a->sep_ext.parent_handle = mp->parent_handle;
   a->sep_ext.ckpair_index = mp->ckpair_index;
index aa0e865..a036013 100644 (file)
@@ -21,7 +21,7 @@
 
 #define SESSION_INVALID_INDEX ((u32)~0)
 #define SESSION_INVALID_HANDLE ((u64)~0)
-#define SESSION_CTRL_MSG_MAX_SIZE 84
+#define SESSION_CTRL_MSG_MAX_SIZE 86
 
 #define foreach_session_endpoint_fields                                \
   foreach_transport_endpoint_cfg_fields                                \