From c75423981ad2d44c4f2abc5dbe69d6a1a9930d1e Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Mon, 22 Jul 2019 08:08:43 -0700 Subject: udp: support close with data Also adds connection flags. Type: feature Change-Id: I76f21eb88ab203076149b7c03dc31c22fc0f342e Signed-off-by: Florin Coras --- src/vnet/udp/udp.c | 43 ++++++++++++++++++++++++++++++------------- src/vnet/udp/udp.h | 11 ++++++++--- src/vnet/udp/udp_input.c | 6 +++--- 3 files changed, 41 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/vnet/udp/udp.c b/src/vnet/udp/udp.c index 7dd0d2a10ff..949c6356d33 100644 --- a/src/vnet/udp/udp.c +++ b/src/vnet/udp/udp.c @@ -63,6 +63,18 @@ udp_connection_free (udp_connection_t * uc) clib_memset (uc, 0xFA, sizeof (*uc)); } +void +udp_connection_delete (udp_connection_t * uc) +{ + if ((uc->flags & UDP_CONN_F_OWNS_PORT) + || !(uc->flags & UDP_CONN_F_CONNECTED)) + udp_unregister_dst_port (vlib_get_main (), + clib_net_to_host_u16 (uc->c_lcl_port), + uc->c_is_ip4); + session_transport_delete_notify (&uc->connection); + udp_connection_free (uc); +} + u32 udp_session_bind (u32 session_index, transport_endpoint_t * lcl) { @@ -95,7 +107,7 @@ udp_session_bind (u32 session_index, transport_endpoint_t * lcl) listener->c_proto = TRANSPORT_PROTO_UDP; listener->c_s_index = session_index; listener->c_fib_index = lcl->fib_index; - listener->owns_port = 1; + listener->flags |= UDP_CONN_F_OWNS_PORT; clib_spinlock_init (&listener->rx_lock); node_index = lcl->is_ip4 ? udp4_input_node.index : udp6_input_node.index; @@ -148,6 +160,12 @@ udp_push_header (transport_connection_t * tc, vlib_buffer_t * b) vnet_buffer (b)->sw_if_index[VLIB_TX] = uc->c_fib_index; b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED; + if (PREDICT_FALSE (uc->flags & UDP_CONN_F_CLOSING)) + { + if (!transport_max_tx_dequeue (&uc->connection)) + udp_connection_delete (uc); + } + return 0; } @@ -164,17 +182,16 @@ udp_session_get (u32 connection_index, u32 thread_index) void udp_session_close (u32 connection_index, u32 thread_index) { - vlib_main_t *vm = vlib_get_main (); udp_connection_t *uc; + uc = udp_connection_get (connection_index, thread_index); - if (uc) - { - if (uc->owns_port || !uc->is_connected) - udp_unregister_dst_port (vm, clib_net_to_host_u16 (uc->c_lcl_port), - uc->c_is_ip4); - session_transport_delete_notify (&uc->connection); - udp_connection_free (uc); - } + if (!uc) + return; + + if (!transport_max_tx_dequeue (&uc->connection)) + udp_connection_delete (uc); + else + uc->flags |= UDP_CONN_F_CLOSING; } void @@ -308,7 +325,7 @@ udp_open_connection (transport_endpoint_cfg_t * rmt) uc->c_is_ip4 = rmt->is_ip4; uc->c_proto = TRANSPORT_PROTO_UDP; uc->c_fib_index = rmt->fib_index; - uc->owns_port = 1; + uc->flags |= UDP_CONN_F_OWNS_PORT; return uc->c_c_index; } @@ -362,7 +379,7 @@ udpc_connection_open (transport_endpoint_cfg_t * rmt) if (uc_index == (u32) ~ 0) return -1; uc = udp_connection_get (uc_index, thread_index); - uc->is_connected = 1; + uc->flags |= UDP_CONN_F_CONNECTED; return uc_index; } @@ -375,7 +392,7 @@ udpc_connection_listen (u32 session_index, transport_endpoint_t * lcl) if (li_index == (u32) ~ 0) return -1; listener = udp_listener_get (li_index); - listener->is_connected = 1; + listener->flags |= UDP_CONN_F_CONNECTED; return li_index; } diff --git a/src/vnet/udp/udp.h b/src/vnet/udp/udp.h index f5efbbca0ff..88a46db277e 100644 --- a/src/vnet/udp/udp.h +++ b/src/vnet/udp/udp.h @@ -34,14 +34,20 @@ typedef enum UDP_N_ERROR, } udp_error_t; +typedef enum +{ + UDP_CONN_F_CONNECTED, /**< connected mode */ + UDP_CONN_F_OWNS_PORT, /**< port belong to conn (UDPC) */ + UDP_CONN_F_CLOSING, /**< conn closed with data */ +} udp_conn_flags_t; + typedef struct { /** Required for pool_get_aligned */ CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); transport_connection_t connection; /**< must be first */ clib_spinlock_t rx_lock; /**< rx fifo lock */ - u8 is_connected; /**< connected mode */ - u8 owns_port; /**< does port belong to conn (UDPC) */ + u8 flags; /**< connection flags */ } udp_connection_t; #define foreach_udp4_dst_port \ @@ -235,7 +241,6 @@ udp_connection_clone_safe (u32 connection_index, u32 thread_index) udp_pool_remove_peeker (thread_index); new_c->c_thread_index = current_thread_index; new_c->c_c_index = udp_connection_index (new_c); - new_c->is_connected = old_c->is_connected; new_c->c_fib_index = old_c->c_fib_index; return new_c; } diff --git a/src/vnet/udp/udp_input.c b/src/vnet/udp/udp_input.c index cc5ae2bd0eb..f6d89dcf673 100644 --- a/src/vnet/udp/udp_input.c +++ b/src/vnet/udp/udp_input.c @@ -162,7 +162,7 @@ udp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, */ tc0 = session_get_transport (s0); uc0 = udp_get_connection_from_transport (tc0); - if (uc0->is_connected) + if (uc0->flags & UDP_CONN_F_CONNECTED) { /* * Clone the transport. It will be cleaned up with the @@ -190,7 +190,7 @@ udp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, { tc0 = listen_session_get_transport (s0); uc0 = udp_get_connection_from_transport (tc0); - if (uc0->is_connected) + if (uc0->flags & UDP_CONN_F_CONNECTED) { child0 = udp_connection_alloc (my_thread_index); if (is_ip4) @@ -207,7 +207,7 @@ udp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, child0->c_rmt_port = udp0->src_port; child0->c_is_ip4 = is_ip4; child0->c_fib_index = tc0->fib_index; - child0->is_connected = 1; + child0->flags |= UDP_CONN_F_CONNECTED; if (session_stream_accept (&child0->connection, tc0->s_index, tc0->thread_index, -- cgit 1.2.3-korg