diff options
-rw-r--r-- | src/vnet/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/vnet/sctp/sctp.c | 6 | ||||
-rw-r--r-- | src/vnet/sctp/sctp_output.c | 4 | ||||
-rw-r--r-- | src/vnet/session/application.h | 2 | ||||
-rw-r--r-- | src/vnet/session/session.c | 47 | ||||
-rw-r--r-- | src/vnet/session/session.h | 205 | ||||
-rwxr-xr-x | src/vnet/session/session_api.c | 10 | ||||
-rw-r--r-- | src/vnet/session/session_lookup.c | 55 | ||||
-rw-r--r-- | src/vnet/session/session_lookup.h | 1 | ||||
-rw-r--r-- | src/vnet/session/session_node.c | 9 | ||||
-rw-r--r-- | src/vnet/session/session_types.h | 2 | ||||
-rw-r--r-- | src/vnet/session/transport.c | 34 | ||||
-rw-r--r-- | src/vnet/session/transport.h | 318 | ||||
-rw-r--r-- | src/vnet/session/transport_interface.h | 182 | ||||
-rw-r--r-- | src/vnet/session/transport_types.h | 197 | ||||
-rw-r--r-- | src/vnet/tcp/tcp.c | 6 | ||||
-rw-r--r-- | src/vnet/tcp/tcp_output.c | 17 | ||||
-rw-r--r-- | src/vnet/tls/tls.c | 6 | ||||
-rw-r--r-- | src/vnet/udp/udp.c | 12 |
19 files changed, 571 insertions, 544 deletions
diff --git a/src/vnet/CMakeLists.txt b/src/vnet/CMakeLists.txt index 72da325a08f..6c1eae8dbdf 100644 --- a/src/vnet/CMakeLists.txt +++ b/src/vnet/CMakeLists.txt @@ -1054,7 +1054,7 @@ list(APPEND VNET_HEADERS session/session_lookup.h session/application.h session/transport.h - session/transport_interface.h + session/transport_types.h session/application_interface.h session/application_namespace.h session/session_debug.h diff --git a/src/vnet/sctp/sctp.c b/src/vnet/sctp/sctp.c index 86aef88f432..d0e28c53fe7 100644 --- a/src/vnet/sctp/sctp.c +++ b/src/vnet/sctp/sctp.c @@ -943,9 +943,9 @@ sctp_update_time (f64 now, u8 thread_index) /* *INDENT OFF* */ const static transport_proto_vft_t sctp_proto = { .enable = sctp_enable_disable, - .bind = sctp_session_bind, - .unbind = sctp_session_unbind, - .open = sctp_session_open, + .start_listen = sctp_session_bind, + .stop_listen = sctp_session_unbind, + .connect = sctp_session_open, .close = sctp_session_close, .cleanup = sctp_session_cleanup, .push_header = sctp_push_header, diff --git a/src/vnet/sctp/sctp_output.c b/src/vnet/sctp/sctp_output.c index 17b28a86492..8fea714f6a2 100644 --- a/src/vnet/sctp/sctp_output.c +++ b/src/vnet/sctp/sctp_output.c @@ -264,7 +264,7 @@ sctp_reuse_buffer (vlib_main_t * vm, vlib_buffer_t * b) vnet_buffer (b)->sctp.subconn_idx = MAX_SCTP_CONNECTIONS; /* Leave enough space for headers */ - return vlib_buffer_make_headroom (b, MAX_HDRS_LEN); + return vlib_buffer_make_headroom (b, TRANSPORT_MAX_HDRS_LEN); } always_inline void * @@ -277,7 +277,7 @@ sctp_init_buffer (vlib_main_t * vm, vlib_buffer_t * b) vnet_buffer (b)->sctp.subconn_idx = MAX_SCTP_CONNECTIONS; VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b); /* Leave enough space for headers */ - return vlib_buffer_make_headroom (b, MAX_HDRS_LEN); + return vlib_buffer_make_headroom (b, TRANSPORT_MAX_HDRS_LEN); } always_inline int diff --git a/src/vnet/session/application.h b/src/vnet/session/application.h index f0c0a0d2403..e5bb00e2b14 100644 --- a/src/vnet/session/application.h +++ b/src/vnet/session/application.h @@ -16,7 +16,7 @@ #ifndef SRC_VNET_SESSION_APPLICATION_H_ #define SRC_VNET_SESSION_APPLICATION_H_ -#include <vnet/session/session.h> +#include <vnet/session/session_types.h> #include <vnet/session/segment_manager.h> #include <vnet/session/application_namespace.h> diff --git a/src/vnet/session/session.c b/src/vnet/session/session.c index 7b1c754d31c..6833a93e12b 100644 --- a/src/vnet/session/session.c +++ b/src/vnet/session/session.c @@ -20,12 +20,10 @@ #include <vnet/session/session.h> #include <vnet/session/session_debug.h> #include <vnet/session/application.h> -#include <vlibmemory/api.h> #include <vnet/dpo/load_balance.h> #include <vnet/fib/ip4_fib.h> session_manager_main_t session_manager_main; -extern transport_proto_vft_t *tp_vfts; static inline int session_send_evt_to_thread (void *data, void *args, u32 thread_index, @@ -752,14 +750,13 @@ static void session_switch_pool (void *cb_args) { session_switch_pool_args_t *args = (session_switch_pool_args_t *) cb_args; - transport_proto_t tp; session_t *s; ASSERT (args->thread_index == vlib_get_thread_index ()); s = session_get (args->session_index, args->thread_index); s->tx_fifo->master_session_index = args->new_session_index; s->tx_fifo->master_thread_index = args->new_thread_index; - tp = session_get_transport_proto (s); - tp_vfts[tp].cleanup (s->connection_index, s->thread_index); + transport_cleanup (session_get_transport_proto (s), s->connection_index, + s->thread_index); session_free (s); clib_mem_free (cb_args); } @@ -989,14 +986,14 @@ session_open_cl (u32 app_wrk_index, session_endpoint_t * rmt, u32 opaque) int rv; tep = session_endpoint_to_transport_cfg (rmt); - rv = tp_vfts[rmt->transport_proto].open (tep); + rv = transport_connect (rmt->transport_proto, tep); if (rv < 0) { SESSION_DBG ("Transport failed to open connection."); return VNET_API_ERROR_SESSION_CONNECT; } - tc = tp_vfts[rmt->transport_proto].get_half_open ((u32) rv); + tc = transport_get_half_open (rmt->transport_proto, (u32) rv); /* For dgram type of service, allocate session and fifos now. */ @@ -1024,14 +1021,14 @@ session_open_vc (u32 app_wrk_index, session_endpoint_t * rmt, u32 opaque) int rv; tep = session_endpoint_to_transport_cfg (rmt); - rv = tp_vfts[rmt->transport_proto].open (tep); + rv = transport_connect (rmt->transport_proto, tep); if (rv < 0) { SESSION_DBG ("Transport failed to open connection."); return VNET_API_ERROR_SESSION_CONNECT; } - tc = tp_vfts[rmt->transport_proto].get_half_open ((u32) rv); + tc = transport_get_half_open (rmt->transport_proto, (u32) rv); /* If transport offers a stream service, only allocate session once the * connection has been established. @@ -1059,7 +1056,7 @@ session_open_app (u32 app_wrk_index, session_endpoint_t * rmt, u32 opaque) sep->app_wrk_index = app_wrk_index; sep->opaque = opaque; - return tp_vfts[rmt->transport_proto].open (tep_cfg); + return transport_connect (rmt->transport_proto, tep_cfg); } typedef int (*session_open_service_fn) (u32, session_endpoint_t *, u32); @@ -1088,7 +1085,8 @@ static session_open_service_fn session_open_srv_fns[TRANSPORT_N_SERVICES] = { int session_open (u32 app_wrk_index, session_endpoint_t * rmt, u32 opaque) { - transport_service_type_t tst = tp_vfts[rmt->transport_proto].service_type; + transport_service_type_t tst; + tst = transport_protocol_service_type (rmt->transport_proto); return session_open_srv_fns[tst] (app_wrk_index, rmt, opaque); } @@ -1110,7 +1108,7 @@ session_listen (session_t * ls, session_endpoint_cfg_t * sep) /* Transport bind/listen */ tep = session_endpoint_to_transport (sep); s_index = ls->session_index; - tc_index = tp_vfts[sep->transport_proto].bind (s_index, tep); + tc_index = transport_start_listen (sep->transport_proto, s_index, tep); if (tc_index == (u32) ~ 0) return -1; @@ -1120,7 +1118,7 @@ session_listen (session_t * ls, session_endpoint_cfg_t * sep) ls->connection_index = tc_index; /* Add to the main lookup table after transport was initialized */ - tc = tp_vfts[sep->transport_proto].get_listener (tc_index); + tc = transport_get_listener (sep->transport_proto, tc_index); session_lookup_add_connection (tc, s_index); return 0; } @@ -1135,21 +1133,16 @@ session_stop_listen (session_t * s) { transport_proto_t tp = session_get_transport_proto (s); transport_connection_t *tc; + if (s->session_state != SESSION_STATE_LISTENING) - { - clib_warning ("not a listening session"); - return -1; - } + return -1; - tc = tp_vfts[tp].get_listener (s->connection_index); + tc = transport_get_listener (tp, s->connection_index); if (!tc) - { - clib_warning ("no transport"); - return VNET_API_ERROR_ADDRESS_NOT_IN_USE; - } + return VNET_API_ERROR_ADDRESS_NOT_IN_USE; session_lookup_del_connection (tc); - tp_vfts[tp].unbind (s->connection_index); + transport_stop_listen (tp, s->connection_index); return 0; } @@ -1210,8 +1203,8 @@ session_transport_close (session_t * s) else s->session_state = SESSION_STATE_CLOSED; - tp_vfts[session_get_transport_proto (s)].close (s->connection_index, - s->thread_index); + transport_close (session_get_transport_proto (s), s->connection_index, + s->thread_index); } /** @@ -1228,8 +1221,8 @@ session_transport_cleanup (session_t * s) /* Delete from main lookup table before we axe the the transport */ session_lookup_del_session (s); - tp_vfts[session_get_transport_proto (s)].cleanup (s->connection_index, - s->thread_index); + transport_cleanup (session_get_transport_proto (s), s->connection_index, + s->thread_index); /* Since we called cleanup, no delete notification will come. So, make * sure the session is properly freed. */ session_free_w_fifos (s); diff --git a/src/vnet/session/session.h b/src/vnet/session/session.h index 68d82761dcd..c622e4eb74a 100644 --- a/src/vnet/session/session.h +++ b/src/vnet/session/session.h @@ -17,16 +17,12 @@ #include <vnet/session/session_types.h> #include <vnet/session/session_lookup.h> -#include <vnet/session/transport_interface.h> #include <vnet/session/session_debug.h> #include <vnet/session/segment_manager.h> #include <svm/message_queue.h> #define SESSION_PROXY_LISTENER_INDEX ((u8)~0 - 1) -/* TODO decide how much since we have pre-data as well */ -#define MAX_HDRS_LEN 100 /* Max number of bytes for headers */ - typedef enum { FIFO_EVENT_APP_RX, @@ -298,21 +294,6 @@ extern vlib_node_registration_t session_queue_process_node; #define SESSION_Q_PROCESS_FLUSH_FRAMES 1 #define SESSION_Q_PROCESS_STOP 2 -/* - * Session manager function - */ -always_inline session_manager_main_t * -vnet_get_session_manager_main () -{ - return &session_manager_main; -} - -always_inline session_manager_worker_t * -session_manager_get_worker (u32 thread_index) -{ - return &session_manager_main.wrk[thread_index]; -} - always_inline u8 stream_session_is_valid (u32 si, u8 thread_index) { @@ -438,53 +419,6 @@ session_get_from_handle_safe (u64 handle) } always_inline u32 -transport_max_rx_enqueue (transport_connection_t * tc) -{ - session_t *s = session_get (tc->s_index, tc->thread_index); - return svm_fifo_max_enqueue (s->rx_fifo); -} - -always_inline u32 -transport_max_tx_dequeue (transport_connection_t * tc) -{ - session_t *s = session_get (tc->s_index, tc->thread_index); - return svm_fifo_max_dequeue (s->tx_fifo); -} - -always_inline u32 -transport_rx_fifo_size (transport_connection_t * tc) -{ - session_t *s = session_get (tc->s_index, tc->thread_index); - return s->rx_fifo->nitems; -} - -always_inline u32 -transport_tx_fifo_size (transport_connection_t * tc) -{ - session_t *s = session_get (tc->s_index, tc->thread_index); - return s->tx_fifo->nitems; -} - -always_inline u8 -transport_rx_fifo_has_ooo_data (transport_connection_t * tc) -{ - session_t *s = session_get (tc->c_index, tc->thread_index); - return svm_fifo_has_ooo_data (s->rx_fifo); -} - -always_inline f64 -transport_dispatch_period (u32 thread_index) -{ - return session_manager_main.wrk[thread_index].dispatch_period; -} - -always_inline f64 -transport_time_now (u32 thread_index) -{ - return session_manager_main.wrk[thread_index].last_vlib_time; -} - -always_inline u32 session_get_index (session_t * s) { return (s - session_manager_main.wrk[s->thread_index].sessions); @@ -511,14 +445,34 @@ session_clone_safe (u32 session_index, u32 thread_index) return new_s; } +int session_open (u32 app_index, session_endpoint_t * tep, u32 opaque); +int session_listen (session_t * s, session_endpoint_cfg_t * sep); +int session_stop_listen (session_t * s); +void session_close (session_t * s); +void session_transport_close (session_t * s); +void session_transport_cleanup (session_t * s); +int session_send_io_evt_to_thread (svm_fifo_t * f, + session_evt_type_t evt_type); +int session_dequeue_notify (session_t * s); +int session_send_io_evt_to_thread_custom (void *data, u32 thread_index, + session_evt_type_t evt_type); +void session_send_rpc_evt_to_thread (u32 thread_index, void *fp, + void *rpc_args); transport_connection_t *session_get_transport (session_t * s); -u32 session_tx_fifo_max_dequeue (transport_connection_t * tc); -int -session_enqueue_stream_connection (transport_connection_t * tc, - vlib_buffer_t * b, u32 offset, - u8 queue_event, u8 is_in_order); +u8 *format_stream_session (u8 * s, va_list * args); +uword unformat_stream_session (unformat_input_t * input, va_list * args); +uword unformat_transport_connection (unformat_input_t * input, + va_list * args); + +/* + * Interface to transport protos + */ + +int session_enqueue_stream_connection (transport_connection_t * tc, + vlib_buffer_t * b, u32 offset, + u8 queue_event, u8 is_in_order); int session_enqueue_dgram_connection (session_t * s, session_dgram_hdr_t * hdr, vlib_buffer_t * b, u8 proto, @@ -531,7 +485,6 @@ int session_stream_connect_notify (transport_connection_t * tc, u8 is_fail); int session_dgram_connect_notify (transport_connection_t * tc, u32 old_thread_index, session_t ** new_session); -int session_dequeue_notify (session_t * s); void stream_session_init_fifos_pointers (transport_connection_t * tc, u32 rx_pointer, u32 tx_pointer); @@ -542,30 +495,58 @@ void session_transport_closed_notify (transport_connection_t * tc); void session_transport_reset_notify (transport_connection_t * tc); int stream_session_accept (transport_connection_t * tc, u32 listener_index, u8 notify); -int session_open (u32 app_index, session_endpoint_t * tep, u32 opaque); -int session_listen (session_t * s, session_endpoint_cfg_t * sep); -int session_stop_listen (session_t * s); -void session_close (session_t * s); -void session_transport_close (session_t * s); -void session_transport_cleanup (session_t * s); -int session_send_io_evt_to_thread (svm_fifo_t * f, - session_evt_type_t evt_type); -int session_send_io_evt_to_thread_custom (void *data, u32 thread_index, - session_evt_type_t evt_type); -void session_send_rpc_evt_to_thread (u32 thread_index, void *fp, - void *rpc_args); - -ssvm_private_t *session_manager_get_evt_q_segment (void); - -u8 *format_stream_session (u8 * s, va_list * args); -uword unformat_stream_session (unformat_input_t * input, va_list * args); -uword unformat_transport_connection (unformat_input_t * input, - va_list * args); - +u32 session_tx_fifo_max_dequeue (transport_connection_t * tc); void session_register_transport (transport_proto_t transport_proto, const transport_proto_vft_t * vft, u8 is_ip4, u32 output_node); +always_inline u32 +transport_max_rx_enqueue (transport_connection_t * tc) +{ + session_t *s = session_get (tc->s_index, tc->thread_index); + return svm_fifo_max_enqueue (s->rx_fifo); +} + +always_inline u32 +transport_max_tx_dequeue (transport_connection_t * tc) +{ + session_t *s = session_get (tc->s_index, tc->thread_index); + return svm_fifo_max_dequeue (s->tx_fifo); +} + +always_inline u32 +transport_rx_fifo_size (transport_connection_t * tc) +{ + session_t *s = session_get (tc->s_index, tc->thread_index); + return s->rx_fifo->nitems; +} + +always_inline u32 +transport_tx_fifo_size (transport_connection_t * tc) +{ + session_t *s = session_get (tc->s_index, tc->thread_index); + return s->tx_fifo->nitems; +} + +always_inline u8 +transport_rx_fifo_has_ooo_data (transport_connection_t * tc) +{ + session_t *s = session_get (tc->c_index, tc->thread_index); + return svm_fifo_has_ooo_data (s->rx_fifo); +} + +always_inline f64 +transport_dispatch_period (u32 thread_index) +{ + return session_manager_main.wrk[thread_index].dispatch_period; +} + +always_inline f64 +transport_time_now (u32 thread_index) +{ + return session_manager_main.wrk[thread_index].last_vlib_time; +} + always_inline void transport_add_tx_event (transport_connection_t * tc) { @@ -575,16 +556,9 @@ transport_add_tx_event (transport_connection_t * tc) session_send_io_evt_to_thread (s->tx_fifo, FIFO_EVENT_APP_TX); } -clib_error_t *vnet_session_enable_disable (vlib_main_t * vm, u8 is_en); - -always_inline svm_msg_q_t * -session_manager_get_vpp_event_queue (u32 thread_index) -{ - return session_manager_main.wrk[thread_index].vpp_event_queue; -} - -int session_manager_flush_enqueue_events (u8 proto, u32 thread_index); -int session_manager_flush_all_enqueue_events (u8 transport_proto); +/* + * Listen sessions + */ always_inline u64 listen_session_get_handle (session_t * s) @@ -634,7 +608,27 @@ int listen_session_get_local_session_endpoint (session_t * listener, session_endpoint_t * sep); -void session_flush_frames_main_thread (vlib_main_t * vm); +/* + * Session manager functions + */ + +always_inline session_manager_main_t * +vnet_get_session_manager_main () +{ + return &session_manager_main; +} + +always_inline session_manager_worker_t * +session_manager_get_worker (u32 thread_index) +{ + return &session_manager_main.wrk[thread_index]; +} + +always_inline svm_msg_q_t * +session_manager_get_vpp_event_queue (u32 thread_index) +{ + return session_manager_main.wrk[thread_index].vpp_event_queue; +} always_inline u8 session_manager_is_enabled () @@ -648,7 +642,12 @@ do { \ return clib_error_return(0, "session layer is not enabled"); \ } while (0) +int session_manager_flush_enqueue_events (u8 proto, u32 thread_index); +int session_manager_flush_all_enqueue_events (u8 transport_proto); +void session_flush_frames_main_thread (vlib_main_t * vm); +ssvm_private_t *session_manager_get_evt_q_segment (void); void session_node_enable_disable (u8 is_en); +clib_error_t *vnet_session_enable_disable (vlib_main_t * vm, u8 is_en); #endif /* __included_session_h__ */ diff --git a/src/vnet/session/session_api.c b/src/vnet/session/session_api.c index bd809367ce5..8196f4ca142 100755 --- a/src/vnet/session/session_api.c +++ b/src/vnet/session/session_api.c @@ -201,7 +201,6 @@ static int send_session_accept_callback (session_t * s) { app_worker_t *server_wrk = app_worker_get (s->app_wrk_index); - transport_proto_vft_t *tp_vft; vl_api_accept_session_t *mp; vl_api_registration_t *reg; transport_connection_t *tc; @@ -241,8 +240,8 @@ send_session_accept_callback (session_t * s) vpp_queue = session_manager_get_vpp_event_queue (s->thread_index); mp->vpp_event_queue_address = pointer_to_uword (vpp_queue); mp->handle = session_handle (s); - tp_vft = transport_protocol_get_vft (session_get_transport_proto (s)); - tc = tp_vft->get_connection (s->connection_index, s->thread_index); + tc = transport_get_connection (session_get_transport_proto (s), + s->connection_index, s->thread_index); mp->port = tc->rmt_port; mp->is_ip4 = tc->is_ip4; clib_memcpy_fast (&mp->ip, &tc->rmt_ip, sizeof (tc->rmt_ip)); @@ -420,7 +419,6 @@ mq_send_session_accepted_cb (session_t * s) app_worker_t *app_wrk = app_worker_get (s->app_wrk_index); svm_msg_q_msg_t _msg, *msg = &_msg; svm_msg_q_t *vpp_queue, *app_mq; - transport_proto_vft_t *tp_vft; transport_connection_t *tc; session_t *listener; session_accepted_msg_t *mp; @@ -457,8 +455,8 @@ mq_send_session_accepted_cb (session_t * s) vpp_queue = session_manager_get_vpp_event_queue (s->thread_index); mp->vpp_event_queue_address = pointer_to_uword (vpp_queue); mp->handle = session_handle (s); - tp_vft = transport_protocol_get_vft (session_get_transport_proto (s)); - tc = tp_vft->get_connection (s->connection_index, s->thread_index); + tc = transport_get_connection (session_get_transport_proto (s), + s->connection_index, s->thread_index); mp->port = tc->rmt_port; mp->is_ip4 = tc->is_ip4; clib_memcpy_fast (&mp->ip, &tc->rmt_ip, sizeof (tc->rmt_ip)); diff --git a/src/vnet/session/session_lookup.c b/src/vnet/session/session_lookup.c index 33fcb4250ca..f267a4cb7c3 100644 --- a/src/vnet/session/session_lookup.c +++ b/src/vnet/session/session_lookup.c @@ -30,11 +30,6 @@ #include <vnet/session/application.h> /** - * External vector of per transport virtual functions table - */ -extern transport_proto_vft_t *tp_vfts; - -/** * Network namespace index (i.e., fib index) to session lookup table. We * should have one per network protocol type but for now we only support IP4/6 */ @@ -340,9 +335,9 @@ session_lookup_del_connection (transport_connection_t * tc) int session_lookup_del_session (session_t * s) { - transport_proto_t tp = session_get_transport_proto (s); transport_connection_t *ts; - ts = tp_vfts[tp].get_connection (s->connection_index, s->thread_index); + ts = transport_get_connection (session_get_transport_proto (s), + s->connection_index, s->thread_index); return session_lookup_del_connection (ts); } @@ -812,12 +807,10 @@ session_lookup_half_open_handle (transport_connection_t * tc) transport_connection_t * session_lookup_half_open_connection (u64 handle, u8 proto, u8 is_ip4) { - u32 sst; - if (handle != HALF_OPEN_LOOKUP_INVALID_VALUE) { - sst = session_type_from_proto_and_ip (proto, is_ip4); - return tp_vfts[sst].get_half_open (handle & 0xFFFFFFFF); + u32 sst = session_type_from_proto_and_ip (proto, is_ip4); + return transport_get_half_open (sst, handle & 0xFFFFFFFF); } return 0; } @@ -877,8 +870,8 @@ session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl, return 0; } s = session_get (kv4.value & 0xFFFFFFFFULL, thread_index); - return tp_vfts[proto].get_connection (s->connection_index, - thread_index); + return transport_get_connection (proto, s->connection_index, + thread_index); } /* @@ -886,7 +879,7 @@ session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl, */ rv = clib_bihash_search_inline_16_8 (&st->v4_half_open_hash, &kv4); if (rv == 0) - return tp_vfts[proto].get_half_open (kv4.value & 0xFFFFFFFF); + return transport_get_half_open (proto, kv4.value & 0xFFFFFFFF); /* * Check the session rules table @@ -902,7 +895,7 @@ session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl, } if ((s = session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP4, proto))) - return tp_vfts[proto].get_listener (s->connection_index); + return transport_get_listener (proto, s->connection_index); return 0; } @@ -911,7 +904,7 @@ session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl, */ s = session_lookup_listener4_i (st, lcl, lcl_port, proto, 1); if (s) - return tp_vfts[proto].get_listener (s->connection_index); + return transport_get_listener (proto, s->connection_index); return 0; } @@ -954,8 +947,8 @@ session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl, if (rv == 0) { s = session_get_from_handle (kv4.value); - return tp_vfts[proto].get_connection (s->connection_index, - s->thread_index); + return transport_get_connection (proto, s->connection_index, + s->thread_index); } /* @@ -963,7 +956,7 @@ session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl, */ rv = clib_bihash_search_inline_16_8 (&st->v4_half_open_hash, &kv4); if (rv == 0) - return tp_vfts[proto].get_half_open (kv4.value & 0xFFFFFFFF); + return transport_get_half_open (proto, kv4.value & 0xFFFFFFFF); /* * Check the session rules table @@ -976,7 +969,7 @@ session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl, return 0; if ((s = session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP4, proto))) - return tp_vfts[proto].get_listener (s->connection_index); + return transport_get_listener (proto, s->connection_index); return 0; } @@ -985,7 +978,7 @@ session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl, */ s = session_lookup_listener4_i (st, lcl, lcl_port, proto, 1); if (s) - return tp_vfts[proto].get_listener (s->connection_index); + return transport_get_listener (proto, s->connection_index); return 0; } @@ -1099,14 +1092,14 @@ session_lookup_connection_wt6 (u32 fib_index, ip6_address_t * lcl, return 0; } s = session_get (kv6.value & 0xFFFFFFFFULL, thread_index); - return tp_vfts[proto].get_connection (s->connection_index, - thread_index); + return transport_get_connection (proto, s->connection_index, + thread_index); } /* Try half-open connections */ rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6); if (rv == 0) - return tp_vfts[proto].get_half_open (kv6.value & 0xFFFFFFFF); + return transport_get_half_open (proto, kv6.value & 0xFFFFFFFF); /* Check the session rules table */ action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl, @@ -1120,14 +1113,14 @@ session_lookup_connection_wt6 (u32 fib_index, ip6_address_t * lcl, } if ((s = session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP6, proto))) - return tp_vfts[proto].get_listener (s->connection_index); + return transport_get_listener (proto, s->connection_index); return 0; } /* If nothing is found, check if any listener is available */ s = session_lookup_listener6_i (st, lcl, lcl_port, proto, 1); if (s) - return tp_vfts[proto].get_listener (s->connection_index); + return transport_get_listener (proto, s->connection_index); return 0; } @@ -1168,14 +1161,14 @@ session_lookup_connection6 (u32 fib_index, ip6_address_t * lcl, if (rv == 0) { s = session_get_from_handle (kv6.value); - return tp_vfts[proto].get_connection (s->connection_index, - s->thread_index); + return transport_get_connection (proto, s->connection_index, + s->thread_index); } /* Try half-open connections */ rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6); if (rv == 0) - return tp_vfts[proto].get_half_open (kv6.value & 0xFFFFFFFF); + return transport_get_half_open (proto, kv6.value & 0xFFFFFFFF); /* Check the session rules table */ action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl, @@ -1186,14 +1179,14 @@ session_lookup_connection6 (u32 fib_index, ip6_address_t * lcl, return 0; if ((s = session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP6, proto))) - return tp_vfts[proto].get_listener (s->connection_index); + return transport_get_listener (proto, s->connection_index); return 0; } /* If nothing is found, check if any listener is available */ s = session_lookup_listener6_i (st, lcl, lcl_port, proto, 1); if (s) - return tp_vfts[proto].get_listener (s->connection_index); + return transport_get_listener (proto, s->connection_index); return 0; } diff --git a/src/vnet/session/session_lookup.h b/src/vnet/session/session_lookup.h index 5efb1f41025..995d2aaf980 100644 --- a/src/vnet/session/session_lookup.h +++ b/src/vnet/session/session_lookup.h @@ -18,7 +18,6 @@ #include <vnet/session/session_table.h> #include <vnet/session/session_types.h> -#include <vnet/session/transport.h> #include <vnet/session/application_namespace.h> #define HALF_OPEN_LOOKUP_INVALID_VALUE ((u64)~0) diff --git a/src/vnet/session/session_node.c b/src/vnet/session/session_node.c index fa33ad37f1e..286bd7b32e0 100644 --- a/src/vnet/session/session_node.c +++ b/src/vnet/session/session_node.c @@ -447,7 +447,7 @@ session_tx_fill_buffer (vlib_main_t * vm, session_tx_context_t * ctx, b->flags = VNET_BUFFER_F_LOCALLY_ORIGINATED; b->current_data = 0; - data0 = vlib_buffer_make_headroom (b, MAX_HDRS_LEN); + data0 = vlib_buffer_make_headroom (b, TRANSPORT_MAX_HDRS_LEN); len_to_deq = clib_min (ctx->left_to_snd, ctx->deq_per_first_buf); if (peek_data) @@ -606,12 +606,13 @@ session_tx_set_dequeue_params (vlib_main_t * vm, session_tx_context_t * ctx, } n_bytes_per_buf = VLIB_BUFFER_DATA_SIZE; - ASSERT (n_bytes_per_buf > MAX_HDRS_LEN); - n_bytes_per_seg = MAX_HDRS_LEN + ctx->snd_mss; + ASSERT (n_bytes_per_buf > TRANSPORT_MAX_HDRS_LEN); + n_bytes_per_seg = TRANSPORT_MAX_HDRS_LEN + ctx->snd_mss; ctx->n_bufs_per_seg = ceil ((f64) n_bytes_per_seg / n_bytes_per_buf); ctx->deq_per_buf = clib_min (ctx->snd_mss, n_bytes_per_buf); ctx->deq_per_first_buf = clib_min (ctx->snd_mss, - n_bytes_per_buf - MAX_HDRS_LEN); + n_bytes_per_buf - + TRANSPORT_MAX_HDRS_LEN); } always_inline int diff --git a/src/vnet/session/session_types.h b/src/vnet/session/session_types.h index b334c3c9f69..286f4c49d80 100644 --- a/src/vnet/session/session_types.h +++ b/src/vnet/session/session_types.h @@ -17,7 +17,7 @@ #define SRC_VNET_SESSION_SESSION_TYPES_H_ #include <svm/svm_fifo.h> -#include <vnet/session/transport.h> +#include <vnet/session/transport_types.h> #define SESSION_LOCAL_HANDLE_PREFIX 0x7FFFFFFF diff --git a/src/vnet/session/transport.c b/src/vnet/session/transport.c index df5282cc43a..2c4efe15806 100644 --- a/src/vnet/session/transport.c +++ b/src/vnet/session/transport.c @@ -13,7 +13,7 @@ * limitations under the License. */ -#include <vnet/session/transport_interface.h> +#include <vnet/session/transport.h> #include <vnet/session/session.h> #include <vnet/fib/fib.h> @@ -271,17 +271,35 @@ transport_protocol_tx_fn_type (transport_proto_t tp) return tp_vfts[tp].tx_type; } -transport_connection_t * -transport_get_connection (transport_proto_t tp, u32 conn_index, - u8 thread_index) +void +transport_cleanup (transport_proto_t tp, u32 conn_index, u8 thread_index) +{ + tp_vfts[tp].cleanup (conn_index, thread_index); +} + +int +transport_connect (transport_proto_t tp, transport_endpoint_cfg_t * tep) +{ + return tp_vfts[tp].connect (tep); +} + +void +transport_close (transport_proto_t tp, u32 conn_index, u8 thread_index) { - return tp_vfts[tp].get_connection (conn_index, thread_index); + tp_vfts[tp].close (conn_index, thread_index); } -transport_connection_t * -transport_get_listener (transport_proto_t tp, u32 conn_index) +u32 +transport_start_listen (transport_proto_t tp, u32 session_index, + transport_endpoint_t * tep) +{ + return tp_vfts[tp].start_listen (session_index, tep); +} + +u32 +transport_stop_listen (transport_proto_t tp, u32 conn_index) { - return tp_vfts[tp].get_listener (conn_index); + return tp_vfts[tp].stop_listen (conn_index); } u8 diff --git a/src/vnet/session/transport.h b/src/vnet/session/transport.h index a82dc3d8493..8500e9d2445 100644 --- a/src/vnet/session/transport.h +++ b/src/vnet/session/transport.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 Cisco and/or its affiliates. + * Copyright (c) 2017-2019 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -13,184 +13,194 @@ * limitations under the License. */ -#ifndef VNET_VNET_URI_TRANSPORT_H_ -#define VNET_VNET_URI_TRANSPORT_H_ +#ifndef SRC_VNET_SESSION_TRANSPORT_H_ +#define SRC_VNET_SESSION_TRANSPORT_H_ #include <vnet/vnet.h> -#include <vnet/ip/ip.h> -#include <vnet/tcp/tcp_debug.h> +#include <vnet/session/transport_types.h> -typedef enum transport_dequeue_type_ +/* + * Transport protocol virtual function table + */ +/* *INDENT-OFF* */ +typedef struct _transport_proto_vft { - TRANSPORT_TX_PEEK, /**< reliable transport protos */ - TRANSPORT_TX_DEQUEUE, /**< unreliable transport protos */ - TRANSPORT_TX_INTERNAL, /**< apps acting as transports */ - TRANSPORT_TX_DGRAM, /**< datagram mode */ - TRANSPORT_TX_N_FNS -} transport_tx_fn_type_t; - -typedef enum transport_service_type_ + /* + * Setup + */ + u32 (*start_listen) (u32 session_index, transport_endpoint_t * lcl); + u32 (*stop_listen) (u32 conn_index); + int (*connect) (transport_endpoint_cfg_t * rmt); + void (*close) (u32 conn_index, u32 thread_index); + void (*cleanup) (u32 conn_index, u32 thread_index); + clib_error_t *(*enable) (vlib_main_t * vm, u8 is_en); + + /* + * Transmission + */ + + u32 (*push_header) (transport_connection_t * tconn, vlib_buffer_t * b); + u16 (*send_mss) (transport_connection_t * tc); + u32 (*send_space) (transport_connection_t * tc); + u32 (*tx_fifo_offset) (transport_connection_t * tc); + void (*update_time) (f64 time_now, u8 thread_index); + void (*flush_data) (transport_connection_t *tconn); + + /* + * Connection retrieval + */ + transport_connection_t *(*get_connection) (u32 conn_idx, u32 thread_idx); + transport_connection_t *(*get_listener) (u32 conn_index); + transport_connection_t *(*get_half_open) (u32 conn_index); + + /* + * Format + */ + u8 *(*format_connection) (u8 * s, va_list * args); + u8 *(*format_listener) (u8 * s, va_list * args); + u8 *(*format_half_open) (u8 * s, va_list * args); + + /* + * Properties + */ + transport_tx_fn_type_t tx_type; + transport_service_type_t service_type; +} transport_proto_vft_t; +/* *INDENT-ON* */ + +extern transport_proto_vft_t *tp_vfts; + +#define transport_proto_foreach(VAR, BODY) \ +do { \ + for (VAR = 0; VAR < vec_len (tp_vfts); VAR++) \ + if (tp_vfts[VAR].push_header != 0) \ + do { BODY; } while (0); \ +} while (0) + +int transport_connect (transport_proto_t tp, transport_endpoint_cfg_t * tep); +void transport_close (transport_proto_t tp, u32 conn_index, u8 thread_index); +u32 transport_start_listen (transport_proto_t tp, u32 session_index, + transport_endpoint_t * tep); +u32 transport_stop_listen (transport_proto_t tp, u32 conn_index); +void transport_cleanup (transport_proto_t tp, u32 conn_index, + u8 thread_index); + +static inline transport_connection_t * +transport_get_connection (transport_proto_t tp, u32 conn_index, + u8 thread_index) { - TRANSPORT_SERVICE_VC, /**< virtual circuit service */ - TRANSPORT_SERVICE_CL, /**< connectionless service */ - TRANSPORT_SERVICE_APP, /**< app transport service */ - TRANSPORT_N_SERVICES -} transport_service_type_t; + return tp_vfts[tp].get_connection (conn_index, thread_index); +} -typedef struct _transport_stats +static inline transport_connection_t * +transport_get_listener (transport_proto_t tp, u32 conn_index) { - u64 tx_bytes; -} transport_stats_t; + return tp_vfts[tp].get_listener (conn_index); +} -typedef struct _spacer +static inline transport_connection_t * +transport_get_half_open (transport_proto_t tp, u32 conn_index) { - u64 bucket; - u32 max_burst_size; - f32 tokens_per_period; - u64 last_update; -} spacer_t; + return tp_vfts[tp].get_half_open (conn_index); +} -/* - * Protocol independent transport properties associated to a session - */ -typedef struct _transport_connection -{ - /** Connection ID */ - union - { - /* - * Network connection ID tuple - */ - struct - { - ip46_address_t rmt_ip; /**< Remote IP */ - ip46_address_t lcl_ip; /**< Local IP */ - u16 rmt_port; /**< Remote port */ - u16 lcl_port; /**< Local port */ - u8 is_ip4; /**< Flag if IP4 connection */ - u8 proto; /**< Protocol id */ - u32 fib_index; /**< Network namespace */ - }; - /* - * Opaque connection ID - */ - u8 opaque_conn_id[42]; - }; - - u32 s_index; /**< Parent session index */ - u32 c_index; /**< Connection index in transport pool */ - u32 thread_index; /**< Worker-thread index */ - - /*fib_node_index_t rmt_fei; - dpo_id_t rmt_dpo; */ - - u8 flags; /**< Transport specific flags */ - transport_stats_t stats; /**< Transport connection stats */ - spacer_t pacer; /**< Simple transport pacer */ +void transport_register_protocol (transport_proto_t transport_proto, + const transport_proto_vft_t * vft, + fib_protocol_t fib_proto, u32 output_node); +transport_proto_vft_t *transport_protocol_get_vft (transport_proto_t tp); +void transport_update_time (f64 time_now, u8 thread_index); +int transport_alloc_local_port (u8 proto, ip46_address_t * ip); +int transport_alloc_local_endpoint (u8 proto, transport_endpoint_cfg_t * rmt, + ip46_address_t * lcl_addr, + u16 * lcl_port); +void transport_endpoint_cleanup (u8 proto, ip46_address_t * lcl_ip, u16 port); +void transport_enable_disable (vlib_main_t * vm, u8 is_en); +void transport_init (void); + +always_inline u32 +transport_elog_track_index (transport_connection_t * tc) +{ #if TRANSPORT_DEBUG - elog_track_t elog_track; /**< Event logging */ - u32 cc_stat_tstamp; /**< CC stats timestamp */ + return tc->elog_track.track_index_plus_one - 1; +#else + return ~0; #endif +} - /** Macros for 'derived classes' where base is named "connection" */ -#define c_lcl_ip connection.lcl_ip -#define c_rmt_ip connection.rmt_ip -#define c_lcl_ip4 connection.lcl_ip.ip4 -#define c_rmt_ip4 connection.rmt_ip.ip4 -#define c_lcl_ip6 connection.lcl_ip.ip6 -#define c_rmt_ip6 connection.rmt_ip.ip6 -#define c_lcl_port connection.lcl_port -#define c_rmt_port connection.rmt_port -#define c_proto connection.proto -#define c_fib_index connection.fib_index -#define c_s_index connection.s_index -#define c_c_index connection.c_index -#define c_is_ip4 connection.is_ip4 -#define c_thread_index connection.thread_index -#define c_elog_track connection.elog_track -#define c_cc_stat_tstamp connection.cc_stat_tstamp -#define c_rmt_fei connection.rmt_fei -#define c_rmt_dpo connection.rmt_dpo -#define c_opaque_id connection.opaque_conn_id -#define c_stats connection.stats -#define c_pacer connection.pacer -#define c_flags connection.flags -} transport_connection_t; - -#define TRANSPORT_CONNECTION_F_IS_TX_PACED 1 << 0 - -typedef enum _transport_proto -{ - TRANSPORT_PROTO_TCP, - TRANSPORT_PROTO_UDP, - TRANSPORT_PROTO_SCTP, - TRANSPORT_PROTO_NONE, - TRANSPORT_PROTO_TLS, - TRANSPORT_PROTO_UDPC, - TRANSPORT_N_PROTO -} transport_proto_t; - -u8 *format_transport_proto (u8 * s, va_list * args); -u8 *format_transport_proto_short (u8 * s, va_list * args); -u8 *format_transport_connection (u8 * s, va_list * args); -u8 *format_transport_listen_connection (u8 * s, va_list * args); -u8 *format_transport_half_open_connection (u8 * s, va_list * args); - -uword unformat_transport_proto (unformat_input_t * input, va_list * args); - -#define foreach_transport_endpoint_fields \ - _(ip46_address_t, ip) /**< ip address in net order */ \ - _(u16, port) /**< port in net order */ \ - _(u8, is_ip4) /**< set if ip4 */ \ - _(u32, sw_if_index) /**< interface endpoint is associated with */ \ - _(u32, fib_index) /**< fib table endpoint is associated with */ \ - -typedef struct transport_endpoint_ -{ -#define _(type, name) type name; - foreach_transport_endpoint_fields -#undef _ -} transport_endpoint_t; +void transport_connection_tx_pacer_reset (transport_connection_t * tc, + u32 rate_bytes_per_sec, + u32 initial_bucket, u64 time_now); +/** + * Initialize tx pacer for connection + * + * @param tc transport connection + * @param rate_bytes_per_second initial byte rate + * @param burst_bytes initial burst size in bytes + */ +void transport_connection_tx_pacer_init (transport_connection_t * tc, + u32 rate_bytes_per_sec, + u32 initial_bucket); -#define foreach_transport_endpoint_cfg_fields \ - foreach_transport_endpoint_fields \ - _(transport_endpoint_t, peer) \ +/** + * Update tx pacer pacing rate + * + * @param tc transport connection + * @param bytes_per_sec new pacing rate + */ +void transport_connection_tx_pacer_update (transport_connection_t * tc, + u64 bytes_per_sec); -typedef struct transport_endpoint_pair_ -{ -#define _(type, name) type name; - foreach_transport_endpoint_cfg_fields -#undef _ -} transport_endpoint_cfg_t; +/** + * Get maximum tx burst allowed for transport connection + * + * @param tc transport connection + * @param time_now current cpu time as returned by @ref clib_cpu_time_now + * @param mss transport's mss + */ +u32 transport_connection_snd_space (transport_connection_t * tc, + u64 time_now, u16 mss); -typedef clib_bihash_24_8_t transport_endpoint_table_t; +u32 transport_connection_tx_pacer_burst (transport_connection_t * tc, + u64 time_now); -#define ENDPOINT_INVALID_INDEX ((u32)~0) +/** + * Initialize period for tx pacers + * + * Defines a unit of time with respect to number of cpu cycles that is to + * be used by all tx pacers. + */ +void transport_init_tx_pacers_period (void); +/** + * Check if transport connection is paced + */ always_inline u8 -transport_connection_fib_proto (transport_connection_t * tc) +transport_connection_is_tx_paced (transport_connection_t * tc) { - return tc->is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6; + return (tc->flags & TRANSPORT_CONNECTION_F_IS_TX_PACED); } -always_inline u8 -transport_endpoint_fib_proto (transport_endpoint_t * tep) -{ - return tep->is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6; -} +u8 *format_transport_pacer (u8 * s, va_list * args); -int transport_alloc_local_port (u8 proto, ip46_address_t * ip); -int transport_alloc_local_endpoint (u8 proto, transport_endpoint_cfg_t * rmt, - ip46_address_t * lcl_addr, - u16 * lcl_port); -void transport_endpoint_cleanup (u8 proto, ip46_address_t * lcl_ip, u16 port); -u8 transport_protocol_is_cl (transport_proto_t tp); -transport_service_type_t transport_protocol_service_type (transport_proto_t); -transport_tx_fn_type_t transport_protocol_tx_fn_type (transport_proto_t tp); -void transport_init (void); +/** + * Update tx byte stats for transport connection + * + * If tx pacing is enabled, this also updates pacer bucket to account for the + * amount of bytes that have been sent. + * + * @param tc transport connection + * @param pkts packets recently sent + * @param bytes bytes recently sent + */ +void transport_connection_update_tx_stats (transport_connection_t * tc, + u32 bytes); + +void +transport_connection_tx_pacer_update_bytes (transport_connection_t * tc, + u32 bytes); -#endif /* VNET_VNET_URI_TRANSPORT_H_ */ +#endif /* SRC_VNET_SESSION_TRANSPORT_H_ */ /* * fd.io coding-style-patch-verification: ON diff --git a/src/vnet/session/transport_interface.h b/src/vnet/session/transport_interface.h deleted file mode 100644 index 123048613bf..00000000000 --- a/src/vnet/session/transport_interface.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * 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_VNET_SESSION_TRANSPORT_INTERFACE_H_ -#define SRC_VNET_SESSION_TRANSPORT_INTERFACE_H_ - -#include <vnet/vnet.h> -#include <vnet/session/transport.h> - -/* - * Transport protocol virtual function table - */ -/* *INDENT-OFF* */ -typedef struct _transport_proto_vft -{ - /* - * Setup - */ - u32 (*bind) (u32 session_index, transport_endpoint_t * lcl); - u32 (*unbind) (u32); - int (*open) (transport_endpoint_cfg_t * rmt); - void (*close) (u32 conn_index, u32 thread_index); - void (*cleanup) (u32 conn_index, u32 thread_index); - clib_error_t *(*enable) (vlib_main_t * vm, u8 is_en); - - /* - * Transmission - */ - - u32 (*push_header) (transport_connection_t * tconn, vlib_buffer_t * b); - u16 (*send_mss) (transport_connection_t * tc); - u32 (*send_space) (transport_connection_t * tc); - u32 (*tx_fifo_offset) (transport_connection_t * tc); - void (*update_time) (f64 time_now, u8 thread_index); - void (*flush_data) (transport_connection_t *tconn); - - /* - * Connection retrieval - */ - transport_connection_t *(*get_connection) (u32 conn_idx, u32 thread_idx); - transport_connection_t *(*get_listener) (u32 conn_index); - transport_connection_t *(*get_half_open) (u32 conn_index); - - /* - * Format - */ - u8 *(*format_connection) (u8 * s, va_list * args); - u8 *(*format_listener) (u8 * s, va_list * args); - u8 *(*format_half_open) (u8 * s, va_list * args); - - /* - * Properties - */ - transport_tx_fn_type_t tx_type; - transport_service_type_t service_type; -} transport_proto_vft_t; -/* *INDENT-ON* */ - -extern transport_proto_vft_t *tp_vfts; - -#define transport_proto_foreach(VAR, BODY) \ -do { \ - for (VAR = 0; VAR < vec_len (tp_vfts); VAR++) \ - if (tp_vfts[VAR].push_header != 0) \ - do { BODY; } while (0); \ -} while (0) - -void transport_register_protocol (transport_proto_t transport_proto, - const transport_proto_vft_t * vft, - fib_protocol_t fib_proto, u32 output_node); -transport_proto_vft_t *transport_protocol_get_vft (transport_proto_t tp); -void transport_update_time (f64 time_now, u8 thread_index); -transport_connection_t *transport_get_connection (transport_proto_t tp, - u32 conn_index, - u8 thread_index); -transport_connection_t *transport_get_listener (transport_proto_t tp, - u32 conn_index); -void transport_enable_disable (vlib_main_t * vm, u8 is_en); - -always_inline u32 -transport_elog_track_index (transport_connection_t * tc) -{ -#if TRANSPORT_DEBUG - return tc->elog_track.track_index_plus_one - 1; -#else - return ~0; -#endif -} - -void transport_connection_tx_pacer_reset (transport_connection_t * tc, - u32 rate_bytes_per_sec, - u32 initial_bucket, u64 time_now); -/** - * Initialize tx pacer for connection - * - * @param tc transport connection - * @param rate_bytes_per_second initial byte rate - * @param burst_bytes initial burst size in bytes - */ -void transport_connection_tx_pacer_init (transport_connection_t * tc, - u32 rate_bytes_per_sec, - u32 initial_bucket); - -/** - * Update tx pacer pacing rate - * - * @param tc transport connection - * @param bytes_per_sec new pacing rate - */ -void transport_connection_tx_pacer_update (transport_connection_t * tc, - u64 bytes_per_sec); - -/** - * Get maximum tx burst allowed for transport connection - * - * @param tc transport connection - * @param time_now current cpu time as returned by @ref clib_cpu_time_now - * @param mss transport's mss - */ -u32 transport_connection_snd_space (transport_connection_t * tc, - u64 time_now, u16 mss); - -u32 transport_connection_tx_pacer_burst (transport_connection_t * tc, - u64 time_now); - -/** - * Initialize period for tx pacers - * - * Defines a unit of time with respect to number of cpu cycles that is to - * be used by all tx pacers. - */ -void transport_init_tx_pacers_period (void); - -/** - * Check if transport connection is paced - */ -always_inline u8 -transport_connection_is_tx_paced (transport_connection_t * tc) -{ - return (tc->flags & TRANSPORT_CONNECTION_F_IS_TX_PACED); -} - -u8 *format_transport_pacer (u8 * s, va_list * args); - -/** - * Update tx byte stats for transport connection - * - * If tx pacing is enabled, this also updates pacer bucket to account for the - * amount of bytes that have been sent. - * - * @param tc transport connection - * @param pkts packets recently sent - * @param bytes bytes recently sent - */ -void transport_connection_update_tx_stats (transport_connection_t * tc, - u32 bytes); - -void -transport_connection_tx_pacer_update_bytes (transport_connection_t * tc, - u32 bytes); - -#endif /* SRC_VNET_SESSION_TRANSPORT_INTERFACE_H_ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/session/transport_types.h b/src/vnet/session/transport_types.h new file mode 100644 index 00000000000..d309c581db8 --- /dev/null +++ b/src/vnet/session/transport_types.h @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2016-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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 VNET_VNET_URI_TRANSPORT_TYPES_H_ +#define VNET_VNET_URI_TRANSPORT_TYPES_H_ + +#include <vnet/vnet.h> +#include <vnet/ip/ip.h> +#include <vnet/tcp/tcp_debug.h> + +#define TRANSPORT_MAX_HDRS_LEN 100 /* Max number of bytes for headers */ + +typedef enum transport_dequeue_type_ +{ + TRANSPORT_TX_PEEK, /**< reliable transport protos */ + TRANSPORT_TX_DEQUEUE, /**< unreliable transport protos */ + TRANSPORT_TX_INTERNAL, /**< apps acting as transports */ + TRANSPORT_TX_DGRAM, /**< datagram mode */ + TRANSPORT_TX_N_FNS +} transport_tx_fn_type_t; + +typedef enum transport_service_type_ +{ + TRANSPORT_SERVICE_VC, /**< virtual circuit service */ + TRANSPORT_SERVICE_CL, /**< connectionless service */ + TRANSPORT_SERVICE_APP, /**< app transport service */ + TRANSPORT_N_SERVICES +} transport_service_type_t; + +typedef struct _transport_stats +{ + u64 tx_bytes; +} transport_stats_t; + +typedef struct _spacer +{ + u64 bucket; + u32 max_burst_size; + f32 tokens_per_period; + u64 last_update; +} spacer_t; + +/* + * Protocol independent transport properties associated to a session + */ +typedef struct _transport_connection +{ + /** Connection ID */ + union + { + /* + * Network connection ID tuple + */ + struct + { + ip46_address_t rmt_ip; /**< Remote IP */ + ip46_address_t lcl_ip; /**< Local IP */ + u16 rmt_port; /**< Remote port */ + u16 lcl_port; /**< Local port */ + u8 is_ip4; /**< Flag if IP4 connection */ + u8 proto; /**< Protocol id */ + u32 fib_index; /**< Network namespace */ + }; + /* + * Opaque connection ID + */ + u8 opaque_conn_id[42]; + }; + + u32 s_index; /**< Parent session index */ + u32 c_index; /**< Connection index in transport pool */ + u32 thread_index; /**< Worker-thread index */ + + /*fib_node_index_t rmt_fei; + dpo_id_t rmt_dpo; */ + + u8 flags; /**< Transport specific flags */ + transport_stats_t stats; /**< Transport connection stats */ + spacer_t pacer; /**< Simple transport pacer */ + +#if TRANSPORT_DEBUG + elog_track_t elog_track; /**< Event logging */ + u32 cc_stat_tstamp; /**< CC stats timestamp */ +#endif + + /** Macros for 'derived classes' where base is named "connection" */ +#define c_lcl_ip connection.lcl_ip +#define c_rmt_ip connection.rmt_ip +#define c_lcl_ip4 connection.lcl_ip.ip4 +#define c_rmt_ip4 connection.rmt_ip.ip4 +#define c_lcl_ip6 connection.lcl_ip.ip6 +#define c_rmt_ip6 connection.rmt_ip.ip6 +#define c_lcl_port connection.lcl_port +#define c_rmt_port connection.rmt_port +#define c_proto connection.proto +#define c_fib_index connection.fib_index +#define c_s_index connection.s_index +#define c_c_index connection.c_index +#define c_is_ip4 connection.is_ip4 +#define c_thread_index connection.thread_index +#define c_elog_track connection.elog_track +#define c_cc_stat_tstamp connection.cc_stat_tstamp +#define c_rmt_fei connection.rmt_fei +#define c_rmt_dpo connection.rmt_dpo +#define c_opaque_id connection.opaque_conn_id +#define c_stats connection.stats +#define c_pacer connection.pacer +#define c_flags connection.flags +} transport_connection_t; + +#define TRANSPORT_CONNECTION_F_IS_TX_PACED 1 << 0 + +typedef enum _transport_proto +{ + TRANSPORT_PROTO_TCP, + TRANSPORT_PROTO_UDP, + TRANSPORT_PROTO_SCTP, + TRANSPORT_PROTO_NONE, + TRANSPORT_PROTO_TLS, + TRANSPORT_PROTO_UDPC, + TRANSPORT_N_PROTO +} transport_proto_t; + +u8 *format_transport_proto (u8 * s, va_list * args); +u8 *format_transport_proto_short (u8 * s, va_list * args); +u8 *format_transport_connection (u8 * s, va_list * args); +u8 *format_transport_listen_connection (u8 * s, va_list * args); +u8 *format_transport_half_open_connection (u8 * s, va_list * args); + +uword unformat_transport_proto (unformat_input_t * input, va_list * args); + +#define foreach_transport_endpoint_fields \ + _(ip46_address_t, ip) /**< ip address in net order */ \ + _(u16, port) /**< port in net order */ \ + _(u8, is_ip4) /**< set if ip4 */ \ + _(u32, sw_if_index) /**< interface endpoint is associated with */ \ + _(u32, fib_index) /**< fib table endpoint is associated with */ \ + +typedef struct transport_endpoint_ +{ +#define _(type, name) type name; + foreach_transport_endpoint_fields +#undef _ +} transport_endpoint_t; + +#define foreach_transport_endpoint_cfg_fields \ + foreach_transport_endpoint_fields \ + _(transport_endpoint_t, peer) \ + +typedef struct transport_endpoint_pair_ +{ +#define _(type, name) type name; + foreach_transport_endpoint_cfg_fields +#undef _ +} transport_endpoint_cfg_t; + +typedef clib_bihash_24_8_t transport_endpoint_table_t; + +#define ENDPOINT_INVALID_INDEX ((u32)~0) + +always_inline u8 +transport_connection_fib_proto (transport_connection_t * tc) +{ + return tc->is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6; +} + +always_inline u8 +transport_endpoint_fib_proto (transport_endpoint_t * tep) +{ + return tep->is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6; +} + +u8 transport_protocol_is_cl (transport_proto_t tp); +transport_service_type_t transport_protocol_service_type (transport_proto_t); +transport_tx_fn_type_t transport_protocol_tx_fn_type (transport_proto_t tp); + +#endif /* VNET_VNET_URI_TRANSPORT_TYPES_H_ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vnet/tcp/tcp.c b/src/vnet/tcp/tcp.c index 99b015ba3d8..5fdeec608c9 100644 --- a/src/vnet/tcp/tcp.c +++ b/src/vnet/tcp/tcp.c @@ -1173,13 +1173,13 @@ tcp_session_flush_data (transport_connection_t * tconn) /* *INDENT-OFF* */ const static transport_proto_vft_t tcp_proto = { .enable = vnet_tcp_enable_disable, - .bind = tcp_session_bind, - .unbind = tcp_session_unbind, + .start_listen = tcp_session_bind, + .stop_listen = tcp_session_unbind, .push_header = tcp_session_push_header, .get_connection = tcp_session_get_transport, .get_listener = tcp_session_get_listener, .get_half_open = tcp_half_open_session_get_transport, - .open = tcp_session_open, + .connect = tcp_session_open, .close = tcp_session_close, .cleanup = tcp_session_cleanup, .send_mss = tcp_session_send_mss, diff --git a/src/vnet/tcp/tcp_output.c b/src/vnet/tcp/tcp_output.c index 9032a97a7f9..96ffd2c7efe 100644 --- a/src/vnet/tcp/tcp_output.c +++ b/src/vnet/tcp/tcp_output.c @@ -14,7 +14,6 @@ */ #include <vnet/tcp/tcp.h> -#include <vnet/lisp-cp/packets.h> #include <math.h> vlib_node_registration_t tcp4_output_node; @@ -477,7 +476,7 @@ tcp_reuse_buffer (vlib_main_t * vm, vlib_buffer_t * b) vnet_buffer (b)->tcp.flags = 0; /* Leave enough space for headers */ - return vlib_buffer_make_headroom (b, MAX_HDRS_LEN); + return vlib_buffer_make_headroom (b, TRANSPORT_MAX_HDRS_LEN); } static void * @@ -490,7 +489,7 @@ tcp_init_buffer (vlib_main_t * vm, vlib_buffer_t * b) vnet_buffer (b)->tcp.flags = 0; VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b); /* Leave enough space for headers */ - return vlib_buffer_make_headroom (b, MAX_HDRS_LEN); + return vlib_buffer_make_headroom (b, TRANSPORT_MAX_HDRS_LEN); } /** @@ -1290,7 +1289,7 @@ tcp_prepare_segment (tcp_worker_ctx_t * wrk, tcp_connection_t * tc, int n_bytes = 0; u8 *data; - seg_size = max_deq_bytes + MAX_HDRS_LEN; + seg_size = max_deq_bytes + TRANSPORT_MAX_HDRS_LEN; /* * Prepare options @@ -1339,7 +1338,8 @@ tcp_prepare_segment (tcp_worker_ctx_t * wrk, tcp_connection_t * tc, *b = vlib_get_buffer (vm, wrk->tx_buffers[--n_bufs]); data = tcp_init_buffer (vm, *b); n_bytes = stream_session_peek_bytes (&tc->connection, data, offset, - bytes_per_buffer - MAX_HDRS_LEN); + bytes_per_buffer - + TRANSPORT_MAX_HDRS_LEN); b[0]->current_length = n_bytes; b[0]->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID; b[0]->total_length_not_including_first_buffer = 0; @@ -1710,9 +1710,10 @@ tcp_timer_persist_handler (u32 index) tcp_validate_txf_size (tc, offset); tc->snd_opts_len = tcp_make_options (tc, &tc->snd_opts, tc->state); - max_snd_bytes = clib_min (tc->snd_mss, tm->bytes_per_buffer - MAX_HDRS_LEN); - n_bytes = stream_session_peek_bytes (&tc->connection, data, offset, - max_snd_bytes); + max_snd_bytes = + clib_min (tc->snd_mss, tm->bytes_per_buffer - TRANSPORT_MAX_HDRS_LEN); + n_bytes = + stream_session_peek_bytes (&tc->connection, data, offset, max_snd_bytes); b->current_length = n_bytes; ASSERT (n_bytes != 0 && (tcp_timer_is_active (tc, TCP_TIMER_RETRANSMIT) || tc->snd_nxt == tc->snd_una_max diff --git a/src/vnet/tls/tls.c b/src/vnet/tls/tls.c index 3f21e6e3cb2..ed12378862d 100644 --- a/src/vnet/tls/tls.c +++ b/src/vnet/tls/tls.c @@ -739,12 +739,12 @@ format_tls_half_open (u8 * s, va_list * args) /* *INDENT-OFF* */ const static transport_proto_vft_t tls_proto = { - .open = tls_connect, + .connect = tls_connect, .close = tls_disconnect, - .bind = tls_start_listen, + .start_listen = tls_start_listen, + .stop_listen = tls_stop_listen, .get_connection = tls_connection_get, .get_listener = tls_listener_get, - .unbind = tls_stop_listen, .tx_type = TRANSPORT_TX_INTERNAL, .service_type = TRANSPORT_SERVICE_APP, .format_connection = format_tls_connection, diff --git a/src/vnet/udp/udp.c b/src/vnet/udp/udp.c index 7674ef2e5d6..694cffa6f5f 100644 --- a/src/vnet/udp/udp.c +++ b/src/vnet/udp/udp.c @@ -318,9 +318,9 @@ udp_session_get_half_open (u32 conn_index) /* *INDENT-OFF* */ const static transport_proto_vft_t udp_proto = { - .bind = udp_session_bind, - .open = udp_open_connection, - .unbind = udp_session_unbind, + .start_listen = udp_session_bind, + .connect = udp_open_connection, + .stop_listen = udp_session_unbind, .push_header = udp_push_header, .get_connection = udp_session_get, .get_listener = udp_session_get_listener, @@ -362,9 +362,9 @@ udpc_connection_listen (u32 session_index, transport_endpoint_t * lcl) /* *INDENT-OFF* */ const static transport_proto_vft_t udpc_proto = { - .bind = udpc_connection_listen, - .open = udpc_connection_open, - .unbind = udp_session_unbind, + .start_listen = udpc_connection_listen, + .stop_listen = udp_session_unbind, + .connect = udpc_connection_open, .push_header = udp_push_header, .get_connection = udp_session_get, .get_listener = udp_session_get_listener, |