From 57660d9df62756c5db1516be0dbb48505f996e82 Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Sat, 4 Apr 2020 22:45:34 +0000 Subject: session udp: shared local endpoints Type: improvement Signed-off-by: Florin Coras Change-Id: Ie7102355b95eefb233ec7d146e61819051a7bf07 --- src/vnet/session/segment_manager.c | 22 ++++++++++--- src/vnet/session/session.c | 4 +-- src/vnet/session/session_lookup.c | 13 ++++++++ src/vnet/session/session_lookup.h | 15 +++++---- src/vnet/session/session_node.c | 2 +- src/vnet/session/transport.c | 64 +++++++++++++++++++++++++++----------- src/vnet/session/transport.h | 2 ++ 7 files changed, 89 insertions(+), 33 deletions(-) (limited to 'src/vnet/session') diff --git a/src/vnet/session/segment_manager.c b/src/vnet/session/segment_manager.c index 154c7a61880..716f2a39a4e 100644 --- a/src/vnet/session/segment_manager.c +++ b/src/vnet/session/segment_manager.c @@ -211,6 +211,15 @@ segment_manager_del_segment (segment_manager_t * sm, fifo_segment_t * fs) pool_put (sm->segments, fs); } +static fifo_segment_t * +segment_manager_get_segment_if_valid (segment_manager_t * sm, + u32 segment_index) +{ + if (pool_is_free_index (sm->segments, segment_index)) + return 0; + return pool_elt_at_index (sm->segments, segment_index); +} + /** * Removes segment after acquiring writer lock */ @@ -221,15 +230,18 @@ segment_manager_lock_and_del_segment (segment_manager_t * sm, u32 fs_index) u8 is_prealloc; clib_rwlock_writer_lock (&sm->segments_rwlock); - fs = segment_manager_get_segment (sm, fs_index); + + fs = segment_manager_get_segment_if_valid (sm, fs_index); + if (!fs) + goto done; + is_prealloc = fifo_segment_flags (fs) & FIFO_SEGMENT_F_IS_PREALLOCATED; if (is_prealloc && !segment_manager_app_detached (sm)) - { - clib_rwlock_writer_unlock (&sm->segments_rwlock); - return; - } + goto done; segment_manager_del_segment (sm, fs); + +done: clib_rwlock_writer_unlock (&sm->segments_rwlock); } diff --git a/src/vnet/session/session.c b/src/vnet/session/session.c index ac29627548c..79f93c40693 100644 --- a/src/vnet/session/session.c +++ b/src/vnet/session/session.c @@ -1099,7 +1099,7 @@ session_open_cl (u32 app_wrk_index, session_endpoint_t * rmt, u32 opaque) if (rv < 0) { SESSION_DBG ("Transport failed to open connection."); - return VNET_API_ERROR_SESSION_CONNECT; + return rv; } tc = transport_get_half_open (rmt->transport_proto, (u32) rv); @@ -1133,7 +1133,7 @@ session_open_vc (u32 app_wrk_index, session_endpoint_t * rmt, u32 opaque) if (rv < 0) { SESSION_DBG ("Transport failed to open connection."); - return VNET_API_ERROR_SESSION_CONNECT; + return rv; } tc = transport_get_half_open (rmt->transport_proto, (u32) rv); diff --git a/src/vnet/session/session_lookup.c b/src/vnet/session/session_lookup.c index 986832346fc..4de6fdbe547 100644 --- a/src/vnet/session/session_lookup.c +++ b/src/vnet/session/session_lookup.c @@ -1289,6 +1289,19 @@ session_lookup_safe6 (u32 fib_index, ip6_address_t * lcl, ip6_address_t * rmt, return 0; } +transport_connection_t * +session_lookup_connection (u32 fib_index, ip46_address_t * lcl, + ip46_address_t * rmt, u16 lcl_port, u16 rmt_port, + u8 proto, u8 is_ip4) +{ + if (is_ip4) + return session_lookup_connection4 (fib_index, &lcl->ip4, &rmt->ip4, + lcl_port, rmt_port, proto); + else + return session_lookup_connection6 (fib_index, &lcl->ip6, &rmt->ip6, + lcl_port, rmt_port, proto); +} + int vnet_session_rule_add_del (session_rule_add_del_args_t * args) { diff --git a/src/vnet/session/session_lookup.h b/src/vnet/session/session_lookup.h index 8224219c4e2..4e80566953e 100644 --- a/src/vnet/session/session_lookup.h +++ b/src/vnet/session/session_lookup.h @@ -59,12 +59,15 @@ transport_connection_t *session_lookup_connection6 (u32 fib_index, ip6_address_t * rmt, u16 lcl_port, u16 rmt_port, u8 proto); -session_t *session_lookup_listener4 (u32 fib_index, - ip4_address_t * lcl, u16 lcl_port, - u8 proto, u8 use_wildcard); -session_t *session_lookup_listener6 (u32 fib_index, - ip6_address_t * lcl, u16 lcl_port, - u8 proto, u8 use_wildcard); +transport_connection_t *session_lookup_connection (u32 fib_index, + ip46_address_t * lcl, + ip46_address_t * rmt, + u16 lcl_port, u16 rmt_port, + u8 proto, u8 is_ip4); +session_t *session_lookup_listener4 (u32 fib_index, ip4_address_t * lcl, + u16 lcl_port, u8 proto, u8 use_wildcard); +session_t *session_lookup_listener6 (u32 fib_index, ip6_address_t * lcl, + u16 lcl_port, u8 proto, u8 use_wildcard); session_t *session_lookup_listener (u32 table_index, session_endpoint_t * sep); session_t *session_lookup_listener_wildcard (u32 table_index, diff --git a/src/vnet/session/session_node.c b/src/vnet/session/session_node.c index f023a95c98c..573fbe91b09 100644 --- a/src/vnet/session/session_node.c +++ b/src/vnet/session/session_node.c @@ -137,7 +137,7 @@ session_mq_connect_handler (void *data) if ((rv = vnet_connect (a))) { - clib_warning ("connect returned: %U", format_vnet_api_errno, rv); + clib_warning ("connect returned: %U", format_session_error, rv); app_wrk = application_get_worker (app, mp->wrk_index); mq_send_session_connected_cb (app_wrk->wrk_index, mp->context, 0, rv); } diff --git a/src/vnet/session/transport.c b/src/vnet/session/transport.c index 29c94f363ff..ba6220033c7 100644 --- a/src/vnet/session/transport.c +++ b/src/vnet/session/transport.c @@ -17,6 +17,12 @@ #include #include +typedef struct local_endpoint_ +{ + transport_endpoint_t ep; + int refcnt; +} local_endpoint_t; + /** * Per-type vector of transport protocol virtual function tables */ @@ -35,7 +41,7 @@ static transport_endpoint_table_t local_endpoints_table; /* * Pool of local endpoints */ -static transport_endpoint_t *local_endpoints; +static local_endpoint_t *local_endpoints; /* * Local endpoints pool lock @@ -401,44 +407,64 @@ transport_endpoint_del (u32 tepi) clib_spinlock_unlock_if_init (&local_endpoints_lock); } -always_inline transport_endpoint_t * +always_inline local_endpoint_t * transport_endpoint_new (void) { - transport_endpoint_t *tep; - pool_get_zero (local_endpoints, tep); - return tep; + local_endpoint_t *lep; + pool_get_zero (local_endpoints, lep); + return lep; } void transport_endpoint_cleanup (u8 proto, ip46_address_t * lcl_ip, u16 port) { - u32 tepi; - transport_endpoint_t *tep; + local_endpoint_t *lep; + u32 lepi; /* Cleanup local endpoint if this was an active connect */ - tepi = transport_endpoint_lookup (&local_endpoints_table, proto, lcl_ip, + lepi = transport_endpoint_lookup (&local_endpoints_table, proto, lcl_ip, clib_net_to_host_u16 (port)); - if (tepi != ENDPOINT_INVALID_INDEX) + if (lepi != ENDPOINT_INVALID_INDEX) { - tep = pool_elt_at_index (local_endpoints, tepi); - transport_endpoint_table_del (&local_endpoints_table, proto, tep); - transport_endpoint_del (tepi); + lep = pool_elt_at_index (local_endpoints, lepi); + if (!clib_atomic_sub_fetch (&lep->refcnt, 1)) + { + transport_endpoint_table_del (&local_endpoints_table, proto, + &lep->ep); + transport_endpoint_del (lepi); + } } } static void transport_endpoint_mark_used (u8 proto, ip46_address_t * ip, u16 port) { - transport_endpoint_t *tep; + local_endpoint_t *lep; clib_spinlock_lock_if_init (&local_endpoints_lock); - tep = transport_endpoint_new (); - clib_memcpy_fast (&tep->ip, ip, sizeof (*ip)); - tep->port = port; - transport_endpoint_table_add (&local_endpoints_table, proto, tep, - tep - local_endpoints); + lep = transport_endpoint_new (); + clib_memcpy_fast (&lep->ep.ip, ip, sizeof (*ip)); + lep->ep.port = port; + lep->refcnt = 1; + transport_endpoint_table_add (&local_endpoints_table, proto, &lep->ep, + lep - local_endpoints); clib_spinlock_unlock_if_init (&local_endpoints_lock); } +void +transport_share_local_endpoint (u8 proto, ip46_address_t * lcl_ip, u16 port) +{ + local_endpoint_t *lep; + u32 lepi; + + lepi = transport_endpoint_lookup (&local_endpoints_table, proto, lcl_ip, + clib_net_to_host_u16 (port)); + if (lepi != ENDPOINT_INVALID_INDEX) + { + lep = pool_elt_at_index (local_endpoints, lepi); + clib_atomic_add_fetch (&lep->refcnt, 1); + } +} + /** * Allocate local port and add if successful add entry to local endpoint * table to mark the pair as used. @@ -572,13 +598,13 @@ transport_alloc_local_endpoint (u8 proto, transport_endpoint_cfg_t * rmt_cfg, else { port = clib_net_to_host_u16 (rmt_cfg->peer.port); + *lcl_port = port; tei = transport_endpoint_lookup (&local_endpoints_table, proto, lcl_addr, port); if (tei != ENDPOINT_INVALID_INDEX) return SESSION_E_PORTINUSE; transport_endpoint_mark_used (proto, lcl_addr, port); - *lcl_port = port; } return 0; diff --git a/src/vnet/session/transport.h b/src/vnet/session/transport.h index eb98032b1e4..5592601983d 100644 --- a/src/vnet/session/transport.h +++ b/src/vnet/session/transport.h @@ -239,6 +239,8 @@ 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_share_local_endpoint (u8 proto, ip46_address_t * lcl_ip, + u16 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); -- cgit 1.2.3-korg