summaryrefslogtreecommitdiffstats
path: root/src/vcl/vcl_private.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/vcl/vcl_private.h')
-rw-r--r--src/vcl/vcl_private.h337
1 files changed, 337 insertions, 0 deletions
diff --git a/src/vcl/vcl_private.h b/src/vcl/vcl_private.h
new file mode 100644
index 00000000000..4283b6e1167
--- /dev/null
+++ b/src/vcl/vcl_private.h
@@ -0,0 +1,337 @@
+/*
+ * Copyright (c) 2018 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_VCL_VCL_PRIVATE_H_
+#define SRC_VCL_VCL_PRIVATE_H_
+
+#include <vnet/session/application_interface.h>
+#include <vcl/vppcom.h>
+#include <vcl/vcl_event.h>
+#include <vcl/vcl_debug.h>
+
+#if (CLIB_DEBUG > 0)
+/* Set VPPCOM_DEBUG_INIT 2 for connection debug,
+ * 3 for read/write debug output
+ * or
+ * export VCL_DEBUG=<#> to set dynamically.
+ */
+#define VPPCOM_DEBUG_INIT 1
+#else
+#define VPPCOM_DEBUG_INIT 0
+#endif
+
+#define VPPCOM_DEBUG vcm->debug
+
+/*
+ * VPPCOM Private definitions and functions.
+ */
+typedef enum
+{
+ STATE_APP_START,
+ STATE_APP_CONN_VPP,
+ STATE_APP_ENABLED,
+ STATE_APP_ATTACHED,
+} app_state_t;
+
+typedef enum
+{
+ STATE_START = 0x01,
+ STATE_CONNECT = 0x02,
+ STATE_LISTEN = 0x04,
+ STATE_ACCEPT = 0x08,
+ STATE_CLOSE_ON_EMPTY = 0x10,
+ STATE_DISCONNECT = 0x20,
+ STATE_FAILED = 0x40
+} session_state_t;
+
+#define SERVER_STATE_OPEN (STATE_ACCEPT|STATE_CLOSE_ON_EMPTY)
+#define CLIENT_STATE_OPEN (STATE_CONNECT|STATE_CLOSE_ON_EMPTY)
+
+typedef struct epoll_event vppcom_epoll_event_t;
+
+typedef struct
+{
+ u32 next_sid;
+ u32 prev_sid;
+ u32 vep_idx;
+ vppcom_epoll_event_t ev;
+#define VEP_DEFAULT_ET_MASK (EPOLLIN|EPOLLOUT)
+#define VEP_UNSUPPORTED_EVENTS (EPOLLONESHOT|EPOLLEXCLUSIVE)
+ u32 et_mask;
+} vppcom_epoll_t;
+
+typedef struct
+{
+ u8 is_ip4;
+ ip46_address_t ip46;
+} vppcom_ip46_t;
+
+enum
+{
+ VCL_SESS_ATTR_SERVER,
+ VCL_SESS_ATTR_CUT_THRU,
+ VCL_SESS_ATTR_VEP,
+ VCL_SESS_ATTR_VEP_SESSION,
+ VCL_SESS_ATTR_LISTEN, // SOL_SOCKET,SO_ACCEPTCONN
+ VCL_SESS_ATTR_NONBLOCK, // fcntl,O_NONBLOCK
+ VCL_SESS_ATTR_REUSEADDR, // SOL_SOCKET,SO_REUSEADDR
+ VCL_SESS_ATTR_REUSEPORT, // SOL_SOCKET,SO_REUSEPORT
+ VCL_SESS_ATTR_BROADCAST, // SOL_SOCKET,SO_BROADCAST
+ VCL_SESS_ATTR_V6ONLY, // SOL_TCP,IPV6_V6ONLY
+ VCL_SESS_ATTR_KEEPALIVE, // SOL_SOCKET,SO_KEEPALIVE
+ VCL_SESS_ATTR_TCP_NODELAY, // SOL_TCP,TCP_NODELAY
+ VCL_SESS_ATTR_TCP_KEEPIDLE, // SOL_TCP,TCP_KEEPIDLE
+ VCL_SESS_ATTR_TCP_KEEPINTVL, // SOL_TCP,TCP_KEEPINTVL
+ VCL_SESS_ATTR_MAX
+} vppcom_session_attr_t;
+
+#define VCL_SESS_ATTR_SET(ATTR, VAL) \
+do { \
+ (ATTR) |= 1 << (VAL); \
+ } while (0)
+
+#define VCL_SESS_ATTR_CLR(ATTR, VAL) \
+do { \
+ (ATTR) &= ~(1 << (VAL)); \
+ } while (0)
+
+#define VCL_SESS_ATTR_TEST(ATTR, VAL) \
+ ((ATTR) & (1 << (VAL)) ? 1 : 0)
+
+typedef struct
+{
+#define _(type, name) type name;
+ foreach_app_session_field
+#undef _
+ 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)
+ u8 *segment_name;
+ u32 sm_seg_index;
+ u32 client_context;
+ u64 vpp_handle;
+
+ /* Socket configuration state */
+ u8 is_vep;
+ u8 is_vep_session;
+ u32 attr;
+ u32 wait_cont_idx;
+ vppcom_epoll_t vep;
+ int libc_epfd;
+ u64 client_queue_address;
+ u64 options[16];
+ vce_event_handler_reg_t *poll_reg;
+#if VCL_ELOG
+ elog_track_t elog_track;
+#endif
+} vcl_session_t;
+
+typedef struct vppcom_cfg_t_
+{
+ u64 heapsize;
+ u32 vpp_api_q_length;
+ u64 segment_baseva;
+ u32 segment_size;
+ u32 add_segment_size;
+ u32 preallocated_fifo_pairs;
+ u32 rx_fifo_size;
+ u32 tx_fifo_size;
+ u32 event_queue_size;
+ u32 listen_queue_size;
+ u8 app_proxy_transport_tcp;
+ u8 app_proxy_transport_udp;
+ u8 app_scope_local;
+ u8 app_scope_global;
+ u8 *namespace_id;
+ u64 namespace_secret;
+ f64 app_timeout;
+ f64 session_timeout;
+ f64 accept_timeout;
+ u32 event_ring_size;
+ char *event_log_path;
+ u8 *vpp_api_filename;
+} vppcom_cfg_t;
+
+void vppcom_cfg (vppcom_cfg_t * vcl_cfg);
+
+typedef struct vppcom_main_t_
+{
+ u8 init;
+ u32 debug;
+ int main_cpu;
+
+ /* FIFO for accepted connections - used in epoll/select */
+ clib_spinlock_t session_fifo_lockp;
+ u32 *client_session_index_fifo;
+
+ /* vpp input queue */
+ svm_queue_t *vl_input_queue;
+
+ /* API client handle */
+ u32 my_client_index;
+ /* Session pool */
+ clib_spinlock_t sessions_lockp;
+ vcl_session_t *sessions;
+
+ /* Hash table for disconnect processing */
+ uword *session_index_by_vpp_handles;
+
+ /* Select bitmaps */
+ clib_bitmap_t *rd_bitmap;
+ clib_bitmap_t *wr_bitmap;
+ clib_bitmap_t *ex_bitmap;
+
+ /* Our event queue */
+ svm_queue_t *app_event_queue;
+
+ /* unique segment name counter */
+ u32 unique_segment_index;
+
+ /* For deadman timers */
+ clib_time_t clib_time;
+
+ /* State of the connection, shared between msg RX thread and main thread */
+ volatile app_state_t app_state;
+
+ vppcom_cfg_t cfg;
+
+ /* Event thread */
+ vce_event_thread_t event_thread;
+
+ /* IO thread */
+ vppcom_session_io_thread_t session_io_thread;
+
+#ifdef VCL_ELOG
+ /* VPP Event-logger */
+ elog_main_t elog_main;
+ elog_track_t elog_track;
+#endif
+
+ /* VNET_API_ERROR_FOO -> "Foo" hash table */
+ uword *error_string_by_error_number;
+} vppcom_main_t;
+
+extern vppcom_main_t *vcm;
+
+#define VCL_SESSION_LOCK_AND_GET(I, S) \
+do { \
+ clib_spinlock_lock (&vcm->sessions_lockp); \
+ rv = vppcom_session_at_index (I, S); \
+ if (PREDICT_FALSE (rv)) \
+ { \
+ clib_spinlock_unlock (&vcm->sessions_lockp); \
+ clib_warning ("VCL<%d>: ERROR: Invalid ##I (%u)!", \
+ getpid (), I); \
+ goto done; \
+ } \
+} while (0)
+
+#define VCL_SESSION_LOCK() clib_spinlock_lock (&(vcm->sessions_lockp))
+#define VCL_SESSION_UNLOCK() clib_spinlock_unlock (&(vcm->sessions_lockp))
+
+#define VCL_IO_SESSIONS_LOCK() \
+ clib_spinlock_lock (&(vcm->session_io_thread.io_sessions_lockp))
+#define VCL_IO_SESSIONS_UNLOCK() \
+ clib_spinlock_unlock (&(vcm->session_io_thread.io_sessions_lockp))
+
+#define VCL_ACCEPT_FIFO_LOCK() clib_spinlock_lock (&(vcm->session_fifo_lockp))
+#define VCL_ACCEPT_FIFO_UNLOCK() \
+ clib_spinlock_unlock (&(vcm->session_fifo_lockp))
+
+#define VCL_EVENTS_LOCK() \
+ clib_spinlock_lock (&(vcm->event_thread.events_lockp))
+#define VCL_EVENTS_UNLOCK() \
+ clib_spinlock_unlock (&(vcm->event_thread.events_lockp))
+
+static inline int
+vppcom_session_at_index (u32 session_index, vcl_session_t * volatile *sess)
+{
+ /* Assumes that caller has acquired spinlock: vcm->sessions_lockp */
+ if (PREDICT_FALSE ((session_index == ~0) ||
+ pool_is_free_index (vcm->sessions, session_index)))
+ {
+ clib_warning ("VCL<%d>: invalid session, sid (%u) has been closed!",
+ getpid (), session_index);
+ return VPPCOM_EBADFD;
+ }
+ *sess = pool_elt_at_index (vcm->sessions, session_index);
+ return VPPCOM_OK;
+}
+
+static inline void
+vppcom_session_table_add_listener (u64 listener_handle, u32 value)
+{
+ /* Session and listener handles have different formats. The latter has
+ * the thread index in the upper 32 bits while the former has the session
+ * type. Knowing that, for listeners we just flip the MSB to 1 */
+ listener_handle |= 1ULL << 63;
+ hash_set (vcm->session_index_by_vpp_handles, listener_handle, value);
+}
+
+static inline vcl_session_t *
+vppcom_session_table_lookup_listener (u64 listener_handle)
+{
+ uword *p;
+ u64 handle = listener_handle | (1ULL << 63);
+ vcl_session_t *session;
+
+ p = hash_get (vcm->session_index_by_vpp_handles, handle);
+ if (!p)
+ {
+ clib_warning ("VCL<%d>: couldn't find listen session: unknown vpp "
+ "listener handle %llx", getpid (), listener_handle);
+ return 0;
+ }
+ if (pool_is_free_index (vcm->sessions, p[0]))
+ {
+ VDBG (1, "VCL<%d>: invalid listen session, sid (%u)", getpid (), p[0]);
+ return 0;
+ }
+
+ session = pool_elt_at_index (vcm->sessions, p[0]);
+ ASSERT (session->session_state & STATE_LISTEN);
+ return session;
+}
+
+const char *vppcom_session_state_str (session_state_t state);
+
+/*
+ * VCL Binary API
+ */
+int vppcom_connect_to_vpp (char *app_name);
+void vppcom_init_error_string_table (void);
+void vppcom_send_session_enable_disable (u8 is_enable);
+void vppcom_app_send_attach (void);
+void vppcom_app_send_detach (void);
+void vppcom_send_connect_sock (vcl_session_t * session, u32 session_index);
+void vppcom_send_disconnect_session_reply (u64 vpp_handle, u32 session_index,
+ int rv);
+void vppcom_send_disconnect_session (u64 vpp_handle, u32 session_index);
+void vppcom_send_bind_sock (vcl_session_t * session, u32 session_index);
+void vppcom_send_unbind_sock (u64 vpp_handle);
+void vppcom_api_hookup (void);
+void vppcom_send_accept_session_reply (u64 handle, u32 context, int retval);
+
+u32 vcl_max_nsid_len (void);
+
+#endif /* SRC_VCL_VCL_PRIVATE_H_ */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */