X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fsession%2Ftransport.h;h=993b8bd7354378ed3bef9c741178f422e1ab6ba7;hb=317b8e08367c769b90463613231b9fcfad486098;hp=7ea7af1589bc936db64606d535ab82e4e4ac1b28;hpb=6cf30adc2cd3aa818e5d97cf71ea8b2fc2aaefa7;p=vpp.git diff --git a/src/vnet/session/transport.h b/src/vnet/session/transport.h index 7ea7af1589b..993b8bd7354 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,73 +13,40 @@ * 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 -{ - 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 (also session type) */ - - 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 */ - -#if TRANSPORT_DEBUG - elog_track_t elog_track; /**< Event logging */ -#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_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 -#define c_elog_track connection.elog_track -} transport_connection_t; +#include /* * Transport protocol virtual function table */ +/* *INDENT-OFF* */ typedef struct _transport_proto_vft { /* * Setup */ - u32 (*bind) (u32, ip46_address_t *, u16); - u32 (*unbind) (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 (*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); + + 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); + int (*custom_tx) (void *session); + int (*app_rx_evt) (transport_connection_t *tconn); /* * Connection retrieval @@ -94,169 +61,164 @@ typedef struct _transport_proto_vft 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); -} transport_proto_vft_t; -/* *INDENT-OFF* */ -/* 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; + /* + * Properties + */ + transport_tx_fn_type_t tx_type; + transport_service_type_t service_type; +} transport_proto_vft_t; /* *INDENT-ON* */ -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) +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) { - 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_connection (conn_index, thread_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_listener (transport_proto_t tp, u32 conn_index) { - v4_connection_key_t key; - memset (&key, 0, sizeof (v4_connection_key_t)); + return tp_vfts[tp].get_listener (conn_index); +} - key.src.as_u32 = lcl->as_u32; - key.dst.as_u32 = 0; - key.src_port = lcl_port; - key.dst_port = 0; - key.proto = proto; +static inline transport_connection_t * +transport_get_half_open (transport_proto_t tp, u32 conn_index) +{ + return tp_vfts[tp].get_half_open (conn_index); +} - kv->key[0] = key.as_u64[0]; - kv->key[1] = key.as_u64[1]; - kv->value = ~0ULL; +static inline int +transport_custom_tx (transport_proto_t tp, void *s) +{ + return tp_vfts[tp].custom_tx (s); } -always_inline void -make_v4_ss_kv_from_tc (session_kv4_t * kv, transport_connection_t * t) +static inline int +transport_app_rx_evt (transport_proto_t tp, u32 conn_index, u32 thread_index) { - return make_v4_ss_kv (kv, &t->lcl_ip.ip4, &t->rmt_ip.ip4, t->lcl_port, - t->rmt_port, t->proto); + 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_ss_kv (session_kv6_t * kv, ip6_address_t * lcl, ip6_address_t * rmt, - u16 lcl_port, u16 rmt_port, u8 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_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) { - v6_connection_key_t key; - memset (&key, 0, sizeof (v6_connection_key_t)); +#if TRANSPORT_DEBUG + return tc->elog_track.track_index_plus_one - 1; +#else + return ~0; +#endif +} - 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; +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); - kv->key[0] = key.as_u64[0]; - kv->key[1] = key.as_u64[1]; - kv->key[2] = 0; - kv->key[3] = 0; - kv->key[4] = 0; - kv->key[5] = 0; - kv->value = ~0ULL; -} +/** + * 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); -always_inline void -make_v6_listener_kv (session_kv6_t * kv, ip6_address_t * lcl, u16 lcl_port, - u8 proto) -{ - v6_connection_key_t key; - memset (&key, 0, sizeof (v6_connection_key_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); - 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; +u32 transport_connection_tx_pacer_burst (transport_connection_t * tc, + u64 time_now); - kv->key[0] = key.as_u64[0]; - kv->key[1] = key.as_u64[1]; - kv->key[2] = 0; - kv->key[3] = 0; - kv->key[4] = 0; - kv->key[5] = 0; - kv->value = ~0ULL; -} +/** + * 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); -always_inline void -make_v6_ss_kv_from_tc (session_kv6_t * kv, transport_connection_t * t) +/** + * Check if transport connection is paced + */ +always_inline u8 +transport_connection_is_tx_paced (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_IS_TX_PACED); } -typedef struct _transport_endpoint -{ - ip46_address_t ip; /** ip address */ - u16 port; /** port in host order */ - u8 is_ip4; /** 1 if ip4 */ - u32 vrf; /** fib table the endpoint is associated with */ -} transport_endpoint_t; - -typedef clib_bihash_24_8_t transport_endpoint_table_t; +u8 *format_transport_pacer (u8 * s, va_list * args); -#define TRANSPORT_ENDPOINT_INVALID_INDEX ((u32)~0) +/** + * 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); -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