session tcp vcl: api to update connection attributes

Type: feature

Signed-off-by: Florin Coras <fcoras@cisco.com>
Change-Id: Ifdd6024daf044751895bb8d2deabad41d3a80c92
diff --git a/src/vcl/vcl_private.h b/src/vcl/vcl_private.h
index 1ac9691..34e05f2 100644
--- a/src/vcl/vcl_private.h
+++ b/src/vcl/vcl_private.h
@@ -165,7 +165,6 @@
 
   u32 sndbuf_size;		// VPP-TBD: Hack until support setsockopt(SO_SNDBUF)
   u32 rcvbuf_size;		// VPP-TBD: Hack until support setsockopt(SO_RCVBUF)
-  u32 user_mss;			// VPP-TBD: Hack until support setsockopt(TCP_MAXSEG)
 
 #if VCL_ELOG
   elog_track_t elog_track;
@@ -292,6 +291,10 @@
   volatile vcl_bapi_app_state_t bapi_app_state;
   volatile uword bapi_return;
 
+  u8 session_attr_op;
+  int session_attr_op_rv;
+  transport_endpt_attr_t session_attr_rv;
+
   /** vcl needs next epoll_create to go to libc_epoll */
   u8 vcl_needs_real_epoll;
   volatile int rpc_done;
diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c
index 3e4ba2f..ce67889 100644
--- a/src/vcl/vppcom.c
+++ b/src/vcl/vppcom.c
@@ -360,6 +360,42 @@
   return ret;
 }
 
+int
+vcl_session_transport_attr (vcl_worker_t *wrk, vcl_session_t *s, u8 is_get,
+			    transport_endpt_attr_t *attr)
+{
+  app_session_evt_t _app_evt, *app_evt = &_app_evt;
+  session_transport_attr_msg_t *mp;
+  svm_msg_q_t *mq;
+  f64 timeout;
+
+  ASSERT (!wrk->session_attr_op);
+  wrk->session_attr_op = 1;
+  wrk->session_attr_op_rv = -1;
+
+  mq = s->vpp_evt_q;
+  app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_TRANSPORT_ATTR);
+  mp = (session_transport_attr_msg_t *) app_evt->evt->data;
+  memset (mp, 0, sizeof (*mp));
+  mp->client_index = wrk->api_client_handle;
+  mp->handle = s->vpp_handle;
+  mp->is_get = is_get;
+  mp->attr = *attr;
+  app_send_ctrl_evt_to_vpp (mq, app_evt);
+
+  timeout = clib_time_now (&wrk->clib_time) + 1;
+
+  while (wrk->session_attr_op && clib_time_now (&wrk->clib_time) < timeout)
+    vcl_flush_mq_events ();
+
+  if (!wrk->session_attr_op_rv && is_get)
+    *attr = wrk->session_attr_rv;
+
+  wrk->session_attr_op = 0;
+
+  return wrk->session_attr_op_rv;
+}
+
 static u32
 vcl_session_accepted_handler (vcl_worker_t * wrk, session_accepted_msg_t * mp,
 			      u32 ls_index)
@@ -936,6 +972,21 @@
   (vcm->wrk_rpc_fn) (((session_app_wrk_rpc_msg_t *) data)->data);
 }
 
+static void
+vcl_session_transport_attr_reply_handler (vcl_worker_t *wrk, void *data)
+{
+  session_transport_attr_reply_msg_t *mp;
+
+  if (!wrk->session_attr_op)
+    return;
+
+  mp = (session_transport_attr_reply_msg_t *) data;
+
+  wrk->session_attr_op_rv = mp->retval;
+  wrk->session_attr_op = 0;
+  wrk->session_attr_rv = mp->attr;
+}
+
 static int
 vcl_handle_mq_event (vcl_worker_t * wrk, session_event_t * e)
 {
@@ -1031,6 +1082,9 @@
     case SESSION_CTRL_EVT_APP_WRK_RPC:
       vcl_worker_rpc_handler (wrk, e->data);
       break;
+    case SESSION_CTRL_EVT_TRANSPORT_ATTR_REPLY:
+      vcl_session_transport_attr_reply_handler (wrk, e->data);
+      break;
     default:
       clib_warning ("unhandled %u", e->event_type);
     }
@@ -3061,6 +3115,7 @@
   vcl_worker_t *wrk = vcl_worker_get_current ();
   u32 *flags = buffer, tmp_flags = 0;
   vppcom_endpt_t *ep = buffer;
+  transport_endpt_attr_t tea;
   vcl_session_t *session;
   int rv = VPPCOM_OK;
 
@@ -3559,30 +3614,41 @@
       break;
 
     case VPPCOM_ATTR_GET_TCP_USER_MSS:
-      if (buffer && buflen && (*buflen >= sizeof (u32)))
+      if (!(buffer && buflen && (*buflen >= sizeof (u32))))
 	{
-	  /* VPP-TBD */
-	  *(u32 *) buffer = session->user_mss;
-	  *buflen = sizeof (int);
-
-	  VDBG (2, "VPPCOM_ATTR_GET_TCP_USER_MSS: %d, buflen %d, #VPP-TBD#",
-		*(int *) buffer, *buflen);
+	  rv = VPPCOM_EINVAL;
+	  break;
 	}
-      else
-	rv = VPPCOM_EINVAL;
+
+      tea.type = TRANSPORT_ENDPT_ATTR_MSS;
+      tea.mss = *(u32 *) buffer;
+      if (vcl_session_transport_attr (wrk, session, 1 /* is_get */, &tea))
+	rv = VPPCOM_ENOPROTOOPT;
+
+      if (!rv)
+	{
+	  *(u32 *) buffer = tea.mss;
+	  *buflen = sizeof (int);
+	}
+
+      VDBG (2, "VPPCOM_ATTR_GET_TCP_USER_MSS: %d, buflen %d", *(int *) buffer,
+	    *buflen);
       break;
 
     case VPPCOM_ATTR_SET_TCP_USER_MSS:
-      if (buffer && buflen && (*buflen == sizeof (u32)))
+      if (!(buffer && buflen && (*buflen == sizeof (u32))))
 	{
-	  /* VPP-TBD */
-	  session->user_mss = *(u32 *) buffer;
-
-	  VDBG (2, "VPPCOM_ATTR_SET_TCP_USER_MSS: %u, buflen %d, #VPP-TBD#",
-		session->user_mss, *buflen);
+	  rv = VPPCOM_EINVAL;
+	  break;
 	}
-      else
-	rv = VPPCOM_EINVAL;
+
+      tea.type = TRANSPORT_ENDPT_ATTR_MSS;
+      tea.mss = *(u32 *) buffer;
+      if (vcl_session_transport_attr (wrk, session, 0 /* is_get */, &tea))
+	rv = VPPCOM_ENOPROTOOPT;
+
+      VDBG (2, "VPPCOM_ATTR_SET_TCP_USER_MSS: %u, buflen %d", tea.mss,
+	    *buflen);
       break;
 
     case VPPCOM_ATTR_SET_SHUT:
diff --git a/src/vcl/vppcom.h b/src/vcl/vppcom.h
index c808829..d956b5f 100644
--- a/src/vcl/vppcom.h
+++ b/src/vcl/vppcom.h
@@ -96,7 +96,8 @@
   VPPCOM_ENOTCONN = -ENOTCONN,
   VPPCOM_ECONNREFUSED = -ECONNREFUSED,
   VPPCOM_ETIMEDOUT = -ETIMEDOUT,
-  VPPCOM_EEXIST = -EEXIST
+  VPPCOM_EEXIST = -EEXIST,
+  VPPCOM_ENOPROTOOPT = -ENOPROTOOPT
 } vppcom_error_t;
 
 typedef enum