X-Git-Url: https://gerrit.fd.io/r/gitweb?p=vpp.git;a=blobdiff_plain;f=src%2Fvnet%2Fsession%2Ftransport.h;h=e5c09cd767d12c052d298a111b83abaafa1178df;hp=2d4415ba6a3666a6b09eb7b4bb18bc30b318179c;hb=07063b8ea;hpb=68b0fb0c620c7451ef1a6380c43c39de6614db51 diff --git a/src/vnet/session/transport.h b/src/vnet/session/transport.h index 2d4415ba6a3..e5c09cd767d 100644 --- a/src/vnet/session/transport.h +++ b/src/vnet/session/transport.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 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,68 +13,70 @@ * 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 -#include -#include -#include +#include -/* - * Protocol independent transport properties associated to a session - */ -typedef struct _transport_connection +#define TRANSPORT_PACER_MIN_MSS 1460 +#define TRANSPORT_PACER_MIN_BURST TRANSPORT_PACER_MIN_MSS +#define TRANSPORT_PACER_MAX_BURST (43 * TRANSPORT_PACER_MIN_MSS) +#define TRANSPORT_PACER_MIN_IDLE 100 +#define TRANSPORT_PACER_IDLE_FACTOR 0.05 + +typedef struct _transport_options_t +{ + char *name; + char *short_name; + transport_tx_fn_type_t tx_type; + transport_service_type_t service_type; + u8 half_open_has_fifos; +} transport_options_t; + +typedef enum transport_snd_flags_ +{ + TRANSPORT_SND_F_DESCHED = 1 << 0, + TRANSPORT_SND_F_POSTPONE = 1 << 1, + TRANSPORT_SND_N_FLAGS +} __clib_packed transport_snd_flags_t; + +typedef struct transport_send_params_ { - ip46_address_t rmt_ip; /**< Remote IP */ - ip46_address_t lcl_ip; /**< Local IP */ - u16 lcl_port; /**< Local port */ - u16 rmt_port; /**< Remote port */ - u8 proto; /**< Transport protocol id */ - - u32 s_index; /**< Parent session index */ - u32 c_index; /**< Connection index in transport pool */ - u8 is_ip4; /**< Flag if IP4 connection */ - u32 thread_index; /**< Worker-thread index */ - - /** 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_state connection.state -#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 -} transport_connection_t; + u32 snd_space; + u32 tx_offset; + u16 snd_mss; + transport_snd_flags_t flags; +} transport_send_params_t; /* * Transport protocol virtual function table */ +/* *INDENT-OFF* */ typedef struct _transport_proto_vft { /* * Setup */ - u32 (*bind) (vlib_main_t *, u32, ip46_address_t *, u16); - u32 (*unbind) (vlib_main_t *, u32); - int (*open) (ip46_address_t * addr, u16 port_host_byte_order); + 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 (*reset) (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 (*rx_fifo_offset) (transport_connection_t * tc); + + u32 (*push_header) (transport_connection_t * tconn, vlib_buffer_t * b); + int (*send_params) (transport_connection_t * tconn, + transport_send_params_t *sp); + void (*update_time) (f64 time_now, u8 thread_index); + void (*flush_data) (transport_connection_t *tconn); + int (*custom_tx) (void *session, u32 max_burst_size); + int (*app_rx_evt) (transport_connection_t *tconn); /* * Connection retrieval @@ -90,156 +92,229 @@ typedef struct _transport_proto_vft u8 *(*format_listener) (u8 * s, va_list * args); u8 *(*format_half_open) (u8 * s, va_list * args); + /* + * Properties retrieval + */ + 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); + + /* + * Properties + */ + transport_options_t transport_options; } 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); +void transport_reset (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); +void transport_get_endpoint (transport_proto_t tp, u32 conn_index, + u32 thread_index, transport_endpoint_t * tep, + u8 is_lcl); +void transport_get_listener_endpoint (transport_proto_t tp, u32 conn_index, + transport_endpoint_t * tep, u8 is_lcl); + +static inline transport_connection_t * +transport_get_connection (transport_proto_t tp, u32 conn_index, + u8 thread_index) +{ + return tp_vfts[tp].get_connection (conn_index, thread_index); +} -/* 16 octets */ -typedef CLIB_PACKED (struct - { - union - { - struct - { - ip4_address_t src; ip4_address_t dst; - u16 src_port; - u16 dst_port; - /* align by making this 4 octets even though its a 1-bit field - * NOTE: avoid key overlap with other transports that use 5 tuples for - * session identification. - */ - u32 proto; - }; - u64 as_u64[2]; - }; - }) v4_connection_key_t; - -typedef CLIB_PACKED (struct - { - union - { - struct - { - /* 48 octets */ - ip6_address_t src; ip6_address_t dst; - u16 src_port; - u16 dst_port; u32 proto; u8 unused_for_now[8]; - }; u64 as_u64[6]; - }; - }) v6_connection_key_t; - -typedef clib_bihash_kv_16_8_t session_kv4_t; -typedef clib_bihash_kv_48_8_t session_kv6_t; - -always_inline void -make_v4_ss_kv (session_kv4_t * kv, ip4_address_t * lcl, ip4_address_t * rmt, - u16 lcl_port, u16 rmt_port, u8 proto) +static inline transport_connection_t * +transport_get_listener (transport_proto_t tp, u32 conn_index) { - v4_connection_key_t key; - memset (&key, 0, sizeof (v4_connection_key_t)); - - key.src.as_u32 = lcl->as_u32; - key.dst.as_u32 = rmt->as_u32; - key.src_port = lcl_port; - key.dst_port = rmt_port; - key.proto = proto; - - kv->key[0] = key.as_u64[0]; - kv->key[1] = key.as_u64[1]; - kv->value = ~0ULL; + return tp_vfts[tp].get_listener (conn_index); } -always_inline void -make_v4_listener_kv (session_kv4_t * kv, ip4_address_t * lcl, u16 lcl_port, - u8 proto) +static inline transport_connection_t * +transport_get_half_open (transport_proto_t tp, u32 conn_index) { - v4_connection_key_t key; - memset (&key, 0, sizeof (v4_connection_key_t)); - - key.src.as_u32 = lcl->as_u32; - key.dst.as_u32 = 0; - key.src_port = lcl_port; - key.dst_port = 0; - key.proto = proto; - - kv->key[0] = key.as_u64[0]; - kv->key[1] = key.as_u64[1]; - kv->value = ~0ULL; + return tp_vfts[tp].get_half_open (conn_index); } -always_inline void -make_v4_ss_kv_from_tc (session_kv4_t * kv, transport_connection_t * t) +static inline int +transport_custom_tx (transport_proto_t tp, void *s, u32 max_burst_size) { - return make_v4_ss_kv (kv, &t->lcl_ip.ip4, &t->rmt_ip.ip4, t->lcl_port, - t->rmt_port, t->proto); + return tp_vfts[tp].custom_tx (s, max_burst_size); } -always_inline void -make_v6_ss_kv (session_kv6_t * kv, ip6_address_t * lcl, ip6_address_t * rmt, - u16 lcl_port, u16 rmt_port, u8 proto) +static inline int +transport_app_rx_evt (transport_proto_t tp, u32 conn_index, u32 thread_index) { - v6_connection_key_t key; - memset (&key, 0, sizeof (v6_connection_key_t)); - - key.src.as_u64[0] = lcl->as_u64[0]; - key.src.as_u64[1] = lcl->as_u64[1]; - key.dst.as_u64[0] = rmt->as_u64[0]; - key.dst.as_u64[1] = rmt->as_u64[1]; - key.src_port = lcl_port; - key.dst_port = rmt_port; - key.proto = proto; - - kv->key[0] = key.as_u64[0]; - kv->key[1] = key.as_u64[1]; - kv->value = ~0ULL; + transport_connection_t *tc; + if (!tp_vfts[tp].app_rx_evt) + return 0; + tc = transport_get_connection (tp, conn_index, thread_index); + return tp_vfts[tp].app_rx_evt (tc); } -always_inline void -make_v6_listener_kv (session_kv6_t * kv, ip6_address_t * lcl, u16 lcl_port, - u8 proto) +/** + * Get send parameters for transport connection + * + * These include maximum tx burst, mss, tx offset and other flags + * transport might want to provide to sessin layer + * + * @param tc transport connection + * @param sp send paramaters + * + */ +static inline u32 +transport_connection_snd_params (transport_connection_t * tc, + transport_send_params_t * sp) { - v6_connection_key_t key; - memset (&key, 0, sizeof (v6_connection_key_t)); - - key.src.as_u64[0] = lcl->as_u64[0]; - key.src.as_u64[1] = lcl->as_u64[1]; - key.dst.as_u64[0] = 0; - key.dst.as_u64[1] = 0; - key.src_port = lcl_port; - key.dst_port = 0; - key.proto = proto; - - kv->key[0] = key.as_u64[0]; - kv->key[1] = key.as_u64[1]; - kv->value = ~0ULL; + return tp_vfts[tc->proto].send_params (tc, sp); } -always_inline void -make_v6_ss_kv_from_tc (session_kv6_t * kv, transport_connection_t * t) +static inline u8 +transport_connection_is_descheduled (transport_connection_t * tc) { - make_v6_ss_kv (kv, &t->lcl_ip.ip6, &t->rmt_ip.ip6, t->lcl_port, - t->rmt_port, t->proto); + return ((tc->flags & TRANSPORT_CONNECTION_F_DESCHED) ? 1 : 0); } -typedef struct _transport_endpoint +static inline void +transport_connection_deschedule (transport_connection_t * tc) { - ip46_address_t ip; - u16 port; - u8 is_ip4; - u32 vrf; -} transport_endpoint_t; + tc->flags |= TRANSPORT_CONNECTION_F_DESCHED; +} + +void transport_connection_reschedule (transport_connection_t * tc); -typedef clib_bihash_24_8_t transport_endpoint_table_t; +/** + * Register transport virtual function table. + * + * @param transport_proto - transport protocol type (i.e., TCP, UDP ..) + * @param vft - virtual function table for transport proto + * @param fib_proto - network layer protocol + * @param output_node - output node index that session layer will hand off + * buffers to, for requested fib proto + */ +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_t +transport_register_new_protocol (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 (clib_time_type_t 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 + return tc->elog_track.track_index_plus_one - 1; +#else + return ~0; +#endif +} -#define TRANSPORT_ENDPOINT_INVALID_INDEX ((u32)~0) +void transport_connection_tx_pacer_reset (transport_connection_t * tc, + u64 rate_bytes_per_sec, + u32 initial_bucket, + clib_us_time_t rtt); +/** + * 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, + u64 rate_bytes_per_sec, + u32 initial_bucket); + +/** + * Update tx pacer pacing rate + * + * @param tc transport connection + * @param bytes_per_sec new pacing rate + * @param rtt connection rtt that is used to compute + * inactivity time after which pacer bucket is + * reset to 1 mtu + */ +void transport_connection_tx_pacer_update (transport_connection_t * tc, + u64 bytes_per_sec, + clib_us_time_t rtt); + +/** + * Get tx pacer max burst + * + * @param tc transport connection + * @param time_now current cpu time + * @return max burst for connection + */ +u32 transport_connection_tx_pacer_burst (transport_connection_t * tc); + +/** + * Get tx pacer current rate + * + * @param tc transport connection + * @return rate for connection in bytes/s + */ +u64 transport_connection_tx_pacer_rate (transport_connection_t * tc); + +/** + * Reset tx pacer bucket + * + * @param tc transport connection + * @param bucket value the bucket will be reset to + */ +void transport_connection_tx_pacer_reset_bucket (transport_connection_t * tc, + u32 bucket); + +/** + * 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 bytes for paced transport connection + * + * If tx pacing is enabled, this update pacer bucket to account for the + * amount of bytes that have been sent. + * + * @param tc transport connection + * @param bytes bytes recently sent + */ +void transport_connection_update_tx_bytes (transport_connection_t * tc, + u32 bytes); -u32 -transport_endpoint_lookup (transport_endpoint_table_t * ht, - ip46_address_t * ip, u16 port); -void transport_endpoint_table_add (transport_endpoint_table_t * ht, - transport_endpoint_t * te, u32 value); -void transport_endpoint_table_del (transport_endpoint_table_t * ht, - transport_endpoint_t * te); +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