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/vnet/session/application_interface.h b/src/vnet/session/application_interface.h
index 2683e35..3f333af 100644
--- a/src/vnet/session/application_interface.h
+++ b/src/vnet/session/application_interface.h
@@ -535,6 +535,22 @@
   u8 data[64];		/**< rpc data */
 } __clib_packed session_app_wrk_rpc_msg_t;
 
+typedef struct session_transport_attr_msg_
+{
+  u32 client_index;
+  session_handle_t handle;
+  transport_endpt_attr_t attr;
+  u8 is_get;
+} __clib_packed session_transport_attr_msg_t;
+
+typedef struct session_transport_attr_reply_msg_
+{
+  i32 retval;
+  session_handle_t handle;
+  transport_endpt_attr_t attr;
+  u8 is_get;
+} __clib_packed session_transport_attr_reply_msg_t;
+
 typedef struct app_session_event_
 {
   svm_msg_q_msg_t msg;
diff --git a/src/vnet/session/session.c b/src/vnet/session/session.c
index 7513aa3..fd52f2b 100644
--- a/src/vnet/session/session.c
+++ b/src/vnet/session/session.c
@@ -1661,6 +1661,18 @@
 					    s->connection_index, tep, is_lcl);
 }
 
+int
+session_transport_attribute (session_t *s, u8 is_get,
+			     transport_endpt_attr_t *attr)
+{
+  if (s->session_state < SESSION_STATE_READY)
+    return -1;
+
+  return transport_connection_attribute (session_get_transport_proto (s),
+					 s->connection_index, s->thread_index,
+					 is_get, attr);
+}
+
 transport_connection_t *
 listen_session_get_transport (session_t * s)
 {
diff --git a/src/vnet/session/session.h b/src/vnet/session/session.h
index a05ecb4..44cbaeb 100644
--- a/src/vnet/session/session.h
+++ b/src/vnet/session/session.h
@@ -477,6 +477,8 @@
 transport_connection_t *session_get_transport (session_t * s);
 void session_get_endpoint (session_t * s, transport_endpoint_t * tep,
 			   u8 is_lcl);
+int session_transport_attribute (session_t *s, u8 is_get,
+				 transport_endpt_attr_t *attr);
 
 u8 *format_session (u8 * s, va_list * args);
 uword unformat_session (unformat_input_t * input, va_list * args);
diff --git a/src/vnet/session/session_node.c b/src/vnet/session/session_node.c
index d40411c..22ab3e8 100644
--- a/src/vnet/session/session_node.c
+++ b/src/vnet/session/session_node.c
@@ -520,6 +520,51 @@
   svm_msg_q_add_and_unlock (app_wrk->event_queue, msg);
 }
 
+static void
+session_mq_transport_attr_handler (void *data)
+{
+  session_transport_attr_msg_t *mp = (session_transport_attr_msg_t *) data;
+  session_transport_attr_reply_msg_t *rmp;
+  svm_msg_q_msg_t _msg, *msg = &_msg;
+  app_worker_t *app_wrk;
+  session_event_t *evt;
+  application_t *app;
+  session_t *s;
+  int rv;
+
+  app = application_lookup (mp->client_index);
+  if (!app)
+    return;
+
+  if (!(s = session_get_from_handle_if_valid (mp->handle)))
+    {
+      clib_warning ("invalid handle %llu", mp->handle);
+      return;
+    }
+  app_wrk = app_worker_get (s->app_wrk_index);
+  if (app_wrk->app_index != app->app_index)
+    {
+      clib_warning ("app %u does not own session %llu", app->app_index,
+		    mp->handle);
+      return;
+    }
+
+  rv = session_transport_attribute (s, mp->is_get, &mp->attr);
+
+  svm_msg_q_lock_and_alloc_msg_w_ring (
+    app_wrk->event_queue, SESSION_MQ_CTRL_EVT_RING, SVM_Q_WAIT, msg);
+  evt = svm_msg_q_msg_data (app_wrk->event_queue, msg);
+  clib_memset (evt, 0, sizeof (*evt));
+  evt->event_type = SESSION_CTRL_EVT_TRANSPORT_ATTR_REPLY;
+  rmp = (session_transport_attr_reply_msg_t *) evt->data;
+  rmp->handle = mp->handle;
+  rmp->retval = rv;
+  rmp->is_get = mp->is_get;
+  if (!rv && mp->is_get)
+    rmp->attr = mp->attr;
+  svm_msg_q_add_and_unlock (app_wrk->event_queue, msg);
+}
+
 vlib_node_registration_t session_queue_node;
 
 typedef struct
@@ -1277,6 +1322,9 @@
     case SESSION_CTRL_EVT_APP_WRK_RPC:
       session_mq_app_wrk_rpc_handler (session_evt_ctrl_data (wrk, elt));
       break;
+    case SESSION_CTRL_EVT_TRANSPORT_ATTR:
+      session_mq_transport_attr_handler (session_evt_ctrl_data (wrk, elt));
+      break;
     default:
       clib_warning ("unhandled event type %d", e->event_type);
     }
diff --git a/src/vnet/session/session_types.h b/src/vnet/session/session_types.h
index 32cb953..3a026a1 100644
--- a/src/vnet/session/session_types.h
+++ b/src/vnet/session/session_types.h
@@ -360,33 +360,36 @@
   SESSION_CTRL_EVT_MIGRATED,
   SESSION_CTRL_EVT_CLEANUP,
   SESSION_CTRL_EVT_APP_WRK_RPC,
+  SESSION_CTRL_EVT_TRANSPORT_ATTR,
+  SESSION_CTRL_EVT_TRANSPORT_ATTR_REPLY,
 } session_evt_type_t;
 
-#define foreach_session_ctrl_evt				\
-  _(LISTEN, listen)						\
-  _(LISTEN_URI, listen_uri)					\
-  _(BOUND, bound)						\
-  _(UNLISTEN, unlisten)						\
-  _(UNLISTEN_REPLY, unlisten_reply)				\
-  _(ACCEPTED, accepted)						\
-  _(ACCEPTED_REPLY, accepted_reply)				\
-  _(CONNECT, connect)						\
-  _(CONNECT_URI, connect_uri)					\
-  _(CONNECTED, connected)					\
-  _(DISCONNECT, disconnect)					\
-  _(DISCONNECTED, disconnected)					\
-  _(DISCONNECTED_REPLY, disconnected_reply)			\
-  _(RESET_REPLY, reset_reply)					\
-  _(REQ_WORKER_UPDATE, req_worker_update)			\
-  _(WORKER_UPDATE, worker_update)				\
-  _(WORKER_UPDATE_REPLY, worker_update_reply)			\
-  _(APP_DETACH, app_detach)					\
-  _(APP_ADD_SEGMENT, app_add_segment)				\
-  _(APP_DEL_SEGMENT, app_del_segment)				\
-  _(MIGRATED, migrated)						\
-  _(CLEANUP, cleanup)						\
-  _(APP_WRK_RPC, app_wrk_rpc)					\
-
+#define foreach_session_ctrl_evt                                              \
+  _ (LISTEN, listen)                                                          \
+  _ (LISTEN_URI, listen_uri)                                                  \
+  _ (BOUND, bound)                                                            \
+  _ (UNLISTEN, unlisten)                                                      \
+  _ (UNLISTEN_REPLY, unlisten_reply)                                          \
+  _ (ACCEPTED, accepted)                                                      \
+  _ (ACCEPTED_REPLY, accepted_reply)                                          \
+  _ (CONNECT, connect)                                                        \
+  _ (CONNECT_URI, connect_uri)                                                \
+  _ (CONNECTED, connected)                                                    \
+  _ (DISCONNECT, disconnect)                                                  \
+  _ (DISCONNECTED, disconnected)                                              \
+  _ (DISCONNECTED_REPLY, disconnected_reply)                                  \
+  _ (RESET_REPLY, reset_reply)                                                \
+  _ (REQ_WORKER_UPDATE, req_worker_update)                                    \
+  _ (WORKER_UPDATE, worker_update)                                            \
+  _ (WORKER_UPDATE_REPLY, worker_update_reply)                                \
+  _ (APP_DETACH, app_detach)                                                  \
+  _ (APP_ADD_SEGMENT, app_add_segment)                                        \
+  _ (APP_DEL_SEGMENT, app_del_segment)                                        \
+  _ (MIGRATED, migrated)                                                      \
+  _ (CLEANUP, cleanup)                                                        \
+  _ (APP_WRK_RPC, app_wrk_rpc)                                                \
+  _ (TRANSPORT_ATTR, transport_attr)                                          \
+  _ (TRANSPORT_ATTR_REPLY, transport_attr_reply)                              \
 /* Deprecated and will be removed. Use types above */
 #define FIFO_EVENT_APP_RX SESSION_IO_EVT_RX
 #define FIFO_EVENT_APP_TX SESSION_IO_EVT_TX
diff --git a/src/vnet/session/transport.c b/src/vnet/session/transport.c
index 4f6ac8b..a420dcd 100644
--- a/src/vnet/session/transport.c
+++ b/src/vnet/session/transport.c
@@ -399,6 +399,17 @@
     }
 }
 
+int
+transport_connection_attribute (transport_proto_t tp, u32 conn_index,
+				u8 thread_index, u8 is_get,
+				transport_endpt_attr_t *attr)
+{
+  if (!tp_vfts[tp].attribute)
+    return -1;
+
+  return tp_vfts[tp].attribute (conn_index, thread_index, is_get, attr);
+}
+
 #define PORT_MASK ((1 << 16)- 1)
 
 void
diff --git a/src/vnet/session/transport.h b/src/vnet/session/transport.h
index efd2507..67583d2 100644
--- a/src/vnet/session/transport.h
+++ b/src/vnet/session/transport.h
@@ -107,13 +107,15 @@
   u8 *(*format_half_open) (u8 * s, va_list * args);
 
   /*
-   *  Properties retrieval
+   *  Properties retrieval/setting
    */
   void (*get_transport_endpoint) (u32 conn_index, u32 thread_index,
 				  transport_endpoint_t *tep, u8 is_lcl);
   void (*get_transport_listener_endpoint) (u32 conn_index,
 					   transport_endpoint_t *tep,
 					   u8 is_lcl);
+  int (*attribute) (u32 conn_index, u32 thread_index, u8 is_get,
+		    transport_endpt_attr_t *attr);
 
   /*
    * Properties
@@ -145,6 +147,9 @@
 			     u8 is_lcl);
 void transport_get_listener_endpoint (transport_proto_t tp, u32 conn_index,
 				      transport_endpoint_t * tep, u8 is_lcl);
+int transport_connection_attribute (transport_proto_t tp, u32 conn_index,
+				    u8 thread_index, u8 is_get,
+				    transport_endpt_attr_t *attr);
 
 static inline transport_connection_t *
 transport_get_connection (transport_proto_t tp, u32 conn_index,
diff --git a/src/vnet/session/transport_types.h b/src/vnet/session/transport_types.h
index 1e7d567..f0fc285 100644
--- a/src/vnet/session/transport_types.h
+++ b/src/vnet/session/transport_types.h
@@ -215,6 +215,42 @@
 #undef _
 } transport_endpoint_cfg_t;
 
+#define foreach_transport_endpt_cfg_flags                                     \
+  _ (CSUM_OFFLOAD)                                                            \
+  _ (GSO)                                                                     \
+  _ (RATE_SAMPLING)
+
+typedef enum transport_endpt_attr_flag_
+{
+#define _(name) TRANSPORT_ENDPT_ATTR_F_##name,
+  foreach_transport_endpt_cfg_flags
+#undef _
+} __clib_packed transport_endpt_attr_flag_t;
+
+#define foreach_transport_attr_fields                                         \
+  _ (u64, next_output_node, NEXT_OUTPUT_NODE)                                 \
+  _ (u16, mss, MSS)                                                           \
+  _ (u8, flags, FLAGS)                                                        \
+  _ (u8, cc_algo, CC_ALGO)
+
+typedef enum transport_endpt_attr_type_
+{
+#define _(type, name, str) TRANSPORT_ENDPT_ATTR_##str,
+  foreach_transport_attr_fields
+#undef _
+} __clib_packed transport_endpt_attr_type_t;
+
+typedef struct transport_endpt_attr_
+{
+  transport_endpt_attr_type_t type;
+  union
+  {
+#define _(type, name, str) type name;
+    foreach_transport_attr_fields
+#undef _
+  };
+} transport_endpt_attr_t;
+
 typedef clib_bihash_24_8_t transport_endpoint_table_t;
 
 #define ENDPOINT_INVALID_INDEX ((u32)~0)