From a2ff7b8cfc829ffbb6d5de7534efb51f7cba9cf3 Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Wed, 8 Nov 2017 17:55:03 -0800 Subject: [PATCH] session: lookup/rules table improvements and cleanup Change-Id: I5217364220023df34d5bee071cb750df1661b093 Signed-off-by: Florin Coras --- src/vnet/api_errno.h | 3 +- src/vnet/session/application.h | 1 + src/vnet/session/application_interface.c | 8 +- src/vnet/session/session_lookup.c | 405 +++++++++++++++++++------------ src/vnet/session/session_lookup.h | 7 +- src/vnet/session/session_rules_table.h | 3 +- src/vnet/session/session_test.c | 143 +++++++---- 7 files changed, 363 insertions(+), 207 deletions(-) diff --git a/src/vnet/api_errno.h b/src/vnet/api_errno.h index d77af973b3b..f24cef4739c 100644 --- a/src/vnet/api_errno.h +++ b/src/vnet/api_errno.h @@ -129,7 +129,8 @@ _(NAME_RESOLUTION_NOT_ENABLED, -136, "Name resolution not enabled") \ _(NAME_SERVER_FORMAT_ERROR, -137, "Server format error (bug!)") \ _(NAME_SERVER_NO_SUCH_NAME, -138, "No such name") \ _(NAME_SERVER_NO_ADDRESSES, -139, "No addresses available") \ -_(NAME_SERVER_NEXT_SERVER, -140, "Retry with new server") +_(NAME_SERVER_NEXT_SERVER, -140, "Retry with new server") \ +_(APP_CONNECT_FILTERED, -141, "Connect was filtered") typedef enum { diff --git a/src/vnet/session/application.h b/src/vnet/session/application.h index b9852131fae..94a4e258298 100644 --- a/src/vnet/session/application.h +++ b/src/vnet/session/application.h @@ -103,6 +103,7 @@ typedef struct _application } application_t; #define APP_INVALID_INDEX ((u32)~0) +#define APP_DROP_INDEX (((u32)~0) - 1) #define APP_NS_INVALID_INDEX ((u32)~0) #define APP_INVALID_SEGMENT_MANAGER_INDEX ((u32) ~0) diff --git a/src/vnet/session/application_interface.c b/src/vnet/session/application_interface.c index a9dda022751..8dab3d67bce 100644 --- a/src/vnet/session/application_interface.c +++ b/src/vnet/session/application_interface.c @@ -109,7 +109,7 @@ vnet_bind_i (u32 app_index, session_endpoint_t * sep, u64 * handle) table_index = application_session_table (app, session_endpoint_fib_proto (sep)); - listener = session_lookup_session_endpoint (table_index, sep); + listener = session_lookup_endpoint_listener (table_index, sep, 1); if (listener != SESSION_INVALID_HANDLE) return VNET_API_ERROR_ADDRESS_IN_USE; @@ -120,7 +120,7 @@ vnet_bind_i (u32 app_index, session_endpoint_t * sep, u64 * handle) if (application_has_local_scope (app) && session_endpoint_is_zero (sep)) { table_index = application_local_session_table (app); - listener = session_lookup_session_endpoint (table_index, sep); + listener = session_lookup_endpoint_listener (table_index, sep, 1); if (listener != SESSION_INVALID_HANDLE) return VNET_API_ERROR_ADDRESS_IN_USE; session_lookup_add_session_endpoint (table_index, sep, app->index); @@ -223,7 +223,9 @@ vnet_connect_i (u32 app_index, u32 api_context, session_endpoint_t * sep, if (application_has_local_scope (app)) { table_index = application_local_session_table (app); - server_index = session_lookup_local_session_endpoint (table_index, sep); + server_index = session_lookup_local_endpoint (table_index, sep); + if (server_index == APP_DROP_INDEX) + return VNET_API_ERROR_APP_CONNECT_FILTERED; /* * Break loop if rule in local table points to connecting app. This diff --git a/src/vnet/session/session_lookup.c b/src/vnet/session/session_lookup.c index afbb8dada52..f4b26f6d931 100644 --- a/src/vnet/session/session_lookup.c +++ b/src/vnet/session/session_lookup.c @@ -348,7 +348,7 @@ session_lookup_del_session (stream_session_t * s) } static u32 -session_lookup_action_to_session (u32 action_index) +session_lookup_action_to_session_index (u32 action_index) { if (action_index != SESSION_RULES_TABLE_ACTION_DROP) return action_index; @@ -367,16 +367,27 @@ session_lookup_app_listen_session (u32 app_index, u8 fib_proto, return application_first_listener (app, fib_proto, transport_proto); } +static stream_session_t * +session_lookup_action_to_session (u32 action_index, u8 fib_proto, + u8 transport_proto) +{ + u32 session_index; + session_index = session_lookup_action_to_session_index (action_index); + /* Nothing sophisticated for now, action index is app index */ + return session_lookup_app_listen_session (session_index, fib_proto, + transport_proto); +} + stream_session_t * -session_lookup_rules_table4 (session_table_t * st, u8 proto, - ip4_address_t * lcl, u16 lcl_port, - ip4_address_t * rmt, u16 rmt_port) +session_lookup_rules_table_session4 (session_table_t * st, u8 proto, + ip4_address_t * lcl, u16 lcl_port, + ip4_address_t * rmt, u16 rmt_port) { session_rules_table_t *srt = &st->session_rules[proto]; u32 action_index, session_index; action_index = session_rules_table_lookup4 (srt, lcl, rmt, lcl_port, rmt_port); - session_index = session_lookup_action_to_session (action_index); + session_index = session_lookup_action_to_session_index (action_index); /* Nothing sophisticated for now, action index is app index */ return session_lookup_app_listen_session (session_index, FIB_PROTOCOL_IP4, proto); @@ -391,20 +402,27 @@ session_lookup_rules_table6 (session_table_t * st, u8 proto, u32 action_index, session_index; action_index = session_rules_table_lookup6 (srt, lcl, rmt, lcl_port, rmt_port); - session_index = session_lookup_action_to_session (action_index); + session_index = session_lookup_action_to_session_index (action_index); return session_lookup_app_listen_session (session_index, FIB_PROTOCOL_IP6, proto); } +/** + * Lookup listener for session endpoint in table + * + * @param table_index table where the endpoint should be looked up + * @param sep session endpoint to be looked up + * @param use_rules flag that indicates if the session rules of the table + * should be used + * @return invalid handle if nothing is found, the handle of a valid listener + * or an action_index if a rule is hit + */ u64 -session_lookup_session_endpoint (u32 table_index, session_endpoint_t * sep) +session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep, + u8 use_rules) { session_rules_table_t *srt; session_table_t *st; - session_kv4_t kv4; - session_kv6_t kv6; - ip4_address_t lcl4; - ip6_address_t lcl6; u32 ai; int rv; u8 sst; @@ -415,94 +433,95 @@ session_lookup_session_endpoint (u32 table_index, session_endpoint_t * sep) return SESSION_INVALID_HANDLE; if (sep->is_ip4) { + session_kv4_t kv4; + ip4_address_t lcl4; + make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port, sst); rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4); if (rv == 0) return kv4.value; - - memset (&lcl4, 0, sizeof (lcl4)); - srt = &st->session_rules[sep->transport_proto]; - ai = session_rules_table_lookup4 (srt, &lcl4, &sep->ip.ip4, 0, - sep->port); - if (ai != SESSION_RULES_TABLE_INVALID_INDEX) - return session_lookup_action_to_session (ai); + if (use_rules) + { + memset (&lcl4, 0, sizeof (lcl4)); + srt = &st->session_rules[sep->transport_proto]; + ai = session_rules_table_lookup4 (srt, &lcl4, &sep->ip.ip4, 0, + sep->port); + if (ai != SESSION_RULES_TABLE_INVALID_INDEX) + return session_lookup_action_to_session_index (ai); + } } else { + session_kv6_t kv6; + ip6_address_t lcl6; + make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port, sst); rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6); if (rv == 0) return kv6.value; - memset (&lcl6, 0, sizeof (lcl6)); - srt = &st->session_rules[sep->transport_proto]; - ai = session_rules_table_lookup6 (srt, &lcl6, &sep->ip.ip6, 0, - sep->port); - if (ai != SESSION_RULES_TABLE_INVALID_INDEX) - return session_lookup_action_to_session (ai); + if (use_rules) + { + memset (&lcl6, 0, sizeof (lcl6)); + srt = &st->session_rules[sep->transport_proto]; + ai = session_rules_table_lookup6 (srt, &lcl6, &sep->ip.ip6, 0, + sep->port); + if (ai != SESSION_RULES_TABLE_INVALID_INDEX) + return session_lookup_action_to_session_index (ai); + } } return SESSION_INVALID_HANDLE; } -stream_session_t * -session_lookup_global_session_endpoint (session_endpoint_t * sep) -{ - session_table_t *st; - session_kv4_t kv4; - session_kv6_t kv6; - ip4_address_t lcl4; - ip6_address_t lcl6; - u8 fib_proto; - u32 table_index; - int rv; - - fib_proto = session_endpoint_fib_proto (sep); - table_index = session_lookup_get_index_for_fib (fib_proto, sep->fib_index); - st = session_table_get (table_index); - if (!st) - return 0; - if (sep->is_ip4) - { - make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port, - sep->transport_proto); - rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4); - if (rv == 0) - return session_get_from_handle (kv4.value); - memset (&lcl4, 0, sizeof (lcl4)); - return session_lookup_rules_table4 (st, sep->transport_proto, &lcl4, 0, - &sep->ip.ip4, sep->port); - } - else - { - make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port, - sep->transport_proto); - rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6); - if (rv == 0) - return session_get_from_handle (kv6.value); - memset (&lcl6, 0, sizeof (lcl6)); - return session_lookup_rules_table6 (st, sep->transport_proto, &lcl6, 0, - &sep->ip.ip6, sep->port); - } -} - +/** + * Look up endpoint in local session table + * + * The result, for now, is an application index and it may in the future + * be extended to a more complicated "action object". The only action we + * emulate now is "drop" and for that we return a special app index. + * + * Lookup logic is to check in order: + * - the rules in the table (connect acls) + * - session sub-table for a listener + * - session sub-table for a local listener (zeroed addr) + * + * @param table_index table where the lookup should be done + * @param sep session endpoint to be looked up + * @return index that can be interpreted as an app index or drop action. + */ u32 -session_lookup_local_session_endpoint (u32 table_index, - session_endpoint_t * sep) +session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep) { session_rules_table_t *srt; session_table_t *st; - session_kv4_t kv4; - session_kv6_t kv6; - ip4_address_t lcl4; - ip6_address_t lcl6; u32 ai; int rv; st = session_table_get (table_index); if (!st) return SESSION_INVALID_INDEX; + ASSERT (st->is_local); + if (sep->is_ip4) { + session_kv4_t kv4; + ip4_address_t lcl4; + + /* + * Check if endpoint has special rules associated + */ + memset (&lcl4, 0, sizeof (lcl4)); + srt = &st->session_rules[sep->transport_proto]; + ai = session_rules_table_lookup4 (srt, &lcl4, &sep->ip.ip4, 0, + sep->port); + if (ai == SESSION_RULES_TABLE_ACTION_DROP) + return APP_DROP_INDEX; + if (ai != SESSION_RULES_TABLE_ACTION_NONE) + return session_lookup_action_to_session_index (ai); + + /* + * Check if session endpoint is a listener + */ make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port, sep->transport_proto); rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4); @@ -517,16 +536,21 @@ session_lookup_local_session_endpoint (u32 table_index, rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4); if (rv == 0) return (u32) kv4.value; + } + else + { + session_kv6_t kv6; + ip6_address_t lcl6; - memset (&lcl4, 0, sizeof (lcl4)); + memset (&lcl6, 0, sizeof (lcl6)); srt = &st->session_rules[sep->transport_proto]; - ai = session_rules_table_lookup4 (srt, &lcl4, &sep->ip.ip4, 0, + ai = session_rules_table_lookup6 (srt, &lcl6, &sep->ip.ip6, 0, sep->port); + if (ai == SESSION_RULES_TABLE_ACTION_DROP) + return APP_DROP_INDEX; if (ai != SESSION_RULES_TABLE_INVALID_INDEX) - return session_lookup_action_to_session (ai); - } - else - { + return session_lookup_action_to_session_index (ai); + make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port, sep->transport_proto); rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6); @@ -540,15 +564,8 @@ session_lookup_local_session_endpoint (u32 table_index, rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6); if (rv == 0) return (u32) kv6.value; - - memset (&lcl6, 0, sizeof (lcl6)); - srt = &st->session_rules[sep->transport_proto]; - ai = session_rules_table_lookup6 (srt, &lcl6, &sep->ip.ip6, 0, - sep->port); - if (ai != SESSION_RULES_TABLE_INVALID_INDEX) - return session_lookup_action_to_session (ai); } - return SESSION_INVALID_INDEX; + return APP_INVALID_INDEX; } static stream_session_t * @@ -725,30 +742,6 @@ session_lookup_half_open_connection (u64 handle, u8 proto, u8 is_ip4) return 0; } -static transport_connection_t * -session_lookup_rules_table_connection4 (session_table_t * st, u8 proto, - ip4_address_t * lcl, u16 lcl_port, - ip4_address_t * rmt, u16 rmt_port) -{ - stream_session_t *s; - s = session_lookup_rules_table4 (st, proto, lcl, lcl_port, rmt, rmt_port); - if (s) - return tp_vfts[s->session_type].get_listener (s->connection_index); - return 0; -} - -static transport_connection_t * -session_lookup_rules_table_connection6 (session_table_t * srt, u8 proto, - ip6_address_t * lcl, u16 lcl_port, - ip6_address_t * rmt, u16 rmt_port) -{ - stream_session_t *s; - s = session_lookup_rules_table6 (srt, proto, lcl, lcl_port, rmt, rmt_port); - if (s) - return tp_vfts[s->session_type].get_listener (s->connection_index); - return 0; -} - /** * Lookup connection with ip4 and transport layer information * @@ -758,10 +751,10 @@ session_lookup_rules_table_connection6 (session_table_t * srt, u8 proto, * The lookup is incremental and returns whenever something is matched. The * steps are: * - Try to find an established session - * - Try to find a fully-formed or local source wildcarded (listener bound to - * all interfaces) listener session * - Try to find a half-open connection * - Try session rules table + * - Try to find a fully-formed or local source wildcarded (listener bound to + * all interfaces) listener session * - return 0 * * @param fib_index index of fib wherein the connection was received @@ -782,13 +775,16 @@ session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl, session_table_t *st; session_kv4_t kv4; stream_session_t *s; + u32 action_index; int rv; st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index); if (PREDICT_FALSE (!st)) return 0; - /* Lookup session amongst established ones */ + /* + * Lookup session amongst established ones + */ make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto); rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4); if (rv == 0) @@ -799,12 +795,9 @@ session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl, thread_index); } - /* If nothing is found, check if any listener is available */ - s = session_lookup_listener4_i (st, lcl, lcl_port, proto); - if (s) - return tp_vfts[s->session_type].get_listener (s->connection_index); - - /* Try half-open connections */ + /* + * Try half-open connections + */ rv = clib_bihash_search_inline_16_8 (&st->v4_half_open_hash, &kv4); if (rv == 0) { @@ -812,9 +805,29 @@ session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl, return tp_vfts[sst].get_half_open (kv4.value & 0xFFFFFFFF); } - /* Check the session rules table */ - return session_lookup_rules_table_connection4 (st, proto, lcl, lcl_port, - rmt, rmt_port); + /* + * Check the session rules table + */ + action_index = session_rules_table_lookup4 (&st->session_rules[proto], lcl, + rmt, lcl_port, rmt_port); + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + if (action_index != SESSION_RULES_TABLE_ACTION_NONE) + { + s = session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP4, + proto); + if (s) + return tp_vfts[s->session_type].get_listener (s->connection_index); + } + + /* + * If nothing is found, check if any listener is available + */ + s = session_lookup_listener4_i (st, lcl, lcl_port, proto); + if (s) + return tp_vfts[s->session_type].get_listener (s->connection_index); + + return 0; } /** @@ -841,13 +854,16 @@ session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl, session_table_t *st; session_kv4_t kv4; stream_session_t *s; + u32 action_index; int rv; st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index); if (PREDICT_FALSE (!st)) return 0; - /* Lookup session amongst established ones */ + /* + * Lookup session amongst established ones + */ make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto); rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4); if (rv == 0) @@ -857,21 +873,39 @@ session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl, s->thread_index); } - /* If nothing is found, check if any listener is available */ - s = session_lookup_listener4_i (st, lcl, lcl_port, proto); - if (s) - return tp_vfts[s->session_type].get_listener (s->connection_index); - - /* Finally, try half-open connections */ + /* + * Try half-open connections + */ rv = clib_bihash_search_inline_16_8 (&st->v4_half_open_hash, &kv4); if (rv == 0) { u32 sst = session_type_from_proto_and_ip (proto, 1); return tp_vfts[sst].get_half_open (kv4.value & 0xFFFFFFFF); } - /* Check the session rules table */ - return session_lookup_rules_table_connection4 (st, proto, lcl, lcl_port, - rmt, rmt_port); + + /* + * Check the session rules table + */ + action_index = session_rules_table_lookup4 (&st->session_rules[proto], lcl, + rmt, lcl_port, rmt_port); + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + if (action_index != SESSION_RULES_TABLE_ACTION_NONE) + { + s = session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP4, + proto); + if (s) + return tp_vfts[s->session_type].get_listener (s->connection_index); + } + + /* + * If nothing is found, check if any listener is available + */ + s = session_lookup_listener4_i (st, lcl, lcl_port, proto); + if (s) + return tp_vfts[s->session_type].get_listener (s->connection_index); + + return 0; } /** @@ -894,23 +928,42 @@ session_lookup_safe4 (u32 fib_index, ip4_address_t * lcl, ip4_address_t * rmt, session_table_t *st; session_kv4_t kv4; stream_session_t *s; + u32 action_index; int rv; st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index); if (PREDICT_FALSE (!st)) return 0; - /* Lookup session amongst established ones */ + /* + * Lookup session amongst established ones + */ make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto); rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4); if (rv == 0) return session_get_from_handle_safe (kv4.value); - /* If nothing is found, check if any listener is available */ + /* + * Check the session rules table + */ + action_index = session_rules_table_lookup4 (&st->session_rules[proto], lcl, + rmt, lcl_port, rmt_port); + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + if (action_index != SESSION_RULES_TABLE_ACTION_NONE) + { + if ((s = session_lookup_action_to_session (action_index, + FIB_PROTOCOL_IP4, proto))) + return s; + } + + /* + * If nothing is found, check if any listener is available + */ if ((s = session_lookup_listener4_i (st, lcl, lcl_port, proto))) return s; - return session_lookup_rules_table4 (st, proto, lcl, - lcl_port, rmt, rmt_port); + + return 0; } /** @@ -922,10 +975,10 @@ session_lookup_safe4 (u32 fib_index, ip4_address_t * lcl, ip4_address_t * rmt, * The lookup is incremental and returns whenever something is matched. The * steps are: * - Try to find an established session - * - Try to find a fully-formed or local source wildcarded (listener bound to - * all interfaces) listener session * - Try to find a half-open connection * - Try session rules table + * - Try to find a fully-formed or local source wildcarded (listener bound to + * all interfaces) listener session * - return 0 * * @param fib_index index of the fib wherein the connection was received @@ -946,6 +999,7 @@ session_lookup_connection_wt6 (u32 fib_index, ip6_address_t * lcl, session_table_t *st; stream_session_t *s; session_kv6_t kv6; + u32 action_index; int rv; st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index); @@ -962,12 +1016,7 @@ session_lookup_connection_wt6 (u32 fib_index, ip6_address_t * lcl, thread_index); } - /* If nothing is found, check if any listener is available */ - s = session_lookup_listener6_i (st, lcl, lcl_port, proto); - if (s) - return tp_vfts[s->session_type].get_listener (s->connection_index); - - /* Finally, try half-open connections */ + /* Try half-open connections */ rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6); if (rv == 0) { @@ -975,8 +1024,25 @@ session_lookup_connection_wt6 (u32 fib_index, ip6_address_t * lcl, return tp_vfts[sst].get_half_open (kv6.value & 0xFFFFFFFF); } - return session_lookup_rules_table_connection6 (st, proto, lcl, lcl_port, - rmt, rmt_port); + /* Check the session rules table */ + action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl, + rmt, lcl_port, rmt_port); + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + if (action_index != SESSION_RULES_TABLE_ACTION_NONE) + { + s = session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP4, + proto); + if (s) + return tp_vfts[s->session_type].get_listener (s->connection_index); + } + + /* If nothing is found, check if any listener is available */ + s = session_lookup_listener6_i (st, lcl, lcl_port, proto); + if (s) + return tp_vfts[s->session_type].get_listener (s->connection_index); + + return 0; } /** @@ -1003,6 +1069,7 @@ session_lookup_connection6 (u32 fib_index, ip6_address_t * lcl, session_table_t *st; stream_session_t *s; session_kv6_t kv6; + u32 action_index; int rv; st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index); @@ -1018,12 +1085,7 @@ session_lookup_connection6 (u32 fib_index, ip6_address_t * lcl, s->thread_index); } - /* If nothing is found, check if any listener is available */ - s = session_lookup_listener6 (fib_index, lcl, lcl_port, proto); - if (s) - return tp_vfts[s->session_type].get_listener (s->connection_index); - - /* Finally, try half-open connections */ + /* Try half-open connections */ rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6); if (rv == 0) { @@ -1031,8 +1093,25 @@ session_lookup_connection6 (u32 fib_index, ip6_address_t * lcl, return tp_vfts[sst].get_half_open (kv6.value & 0xFFFFFFFF); } - return session_lookup_rules_table_connection6 (st, proto, lcl, lcl_port, - rmt, rmt_port); + /* Check the session rules table */ + action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl, + rmt, lcl_port, rmt_port); + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + if (action_index != SESSION_RULES_TABLE_ACTION_NONE) + { + s = session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP4, + proto); + if (s) + return tp_vfts[s->session_type].get_listener (s->connection_index); + } + + /* If nothing is found, check if any listener is available */ + s = session_lookup_listener6 (fib_index, lcl, lcl_port, proto); + if (s) + return tp_vfts[s->session_type].get_listener (s->connection_index); + + return 0; } /** @@ -1055,6 +1134,7 @@ session_lookup_safe6 (u32 fib_index, ip6_address_t * lcl, ip6_address_t * rmt, session_table_t *st; session_kv6_t kv6; stream_session_t *s; + u32 action_index; int rv; st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index); @@ -1066,11 +1146,23 @@ session_lookup_safe6 (u32 fib_index, ip6_address_t * lcl, ip6_address_t * rmt, if (rv == 0) return session_get_from_handle_safe (kv6.value); + /* Check the session rules table */ + action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl, + rmt, lcl_port, rmt_port); + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + if (action_index != SESSION_RULES_TABLE_ACTION_NONE) + { + if ((s = + session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP4, + proto))) + return s; + } + /* If nothing is found, check if any listener is available */ if ((s = session_lookup_listener6_i (st, lcl, lcl_port, proto))) return s; - return session_lookup_rules_table6 (st, proto, lcl, - lcl_port, rmt, rmt_port); + return 0; } u64 @@ -1138,6 +1230,9 @@ vnet_session_rule_add_del (session_rule_add_del_args_t * args) } if (args->scope & SESSION_RULE_SCOPE_LOCAL) { + memset (&args->table_args.lcl, 0, sizeof (args->table_args.lcl)); + args->table_args.lcl.fp_proto = args->table_args.rmt.fp_proto; + args->table_args.lcl_port = 0; st = app_namespace_get_local_table (app_ns); srt = &st->session_rules[args->transport_proto]; error = session_rules_table_add_del (srt, &args->table_args); diff --git a/src/vnet/session/session_lookup.h b/src/vnet/session/session_lookup.h index 246ab524b0f..3bc70311c6e 100644 --- a/src/vnet/session/session_lookup.h +++ b/src/vnet/session/session_lookup.h @@ -59,10 +59,9 @@ stream_session_t *session_lookup_listener (u32 table_index, session_endpoint_t * sep); int session_lookup_add_connection (transport_connection_t * tc, u64 value); int session_lookup_del_connection (transport_connection_t * tc); -u64 session_lookup_session_endpoint (u32 table_index, - session_endpoint_t * sep); -u32 session_lookup_local_session_endpoint (u32 table_index, - session_endpoint_t * sep); +u64 session_lookup_endpoint_listener (u32 table_index, + session_endpoint_t * sep, u8 use_rules); +u32 session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep); stream_session_t *session_lookup_global_session_endpoint (session_endpoint_t *); int session_lookup_add_session_endpoint (u32 table_index, diff --git a/src/vnet/session/session_rules_table.h b/src/vnet/session/session_rules_table.h index 9bab61e7539..ecd2d9b14d6 100644 --- a/src/vnet/session/session_rules_table.h +++ b/src/vnet/session/session_rules_table.h @@ -55,8 +55,9 @@ typedef CLIB_PACKED (struct /* *INDENT-ON* */ #define SESSION_RULE_TAG_MAX_LEN 64 -#define SESSION_RULES_TABLE_ACTION_DROP (((u32)~0) - 1) #define SESSION_RULES_TABLE_INVALID_INDEX MMA_TABLE_INVALID_INDEX +#define SESSION_RULES_TABLE_ACTION_DROP (((u32)~0) - 1) +#define SESSION_RULES_TABLE_ACTION_NONE SESSION_RULES_TABLE_INVALID_INDEX typedef struct _session_rules_table_add_del_args { diff --git a/src/vnet/session/session_test.c b/src/vnet/session/session_test.c index 56d40b81ef8..d592487e5ac 100644 --- a/src/vnet/session/session_test.c +++ b/src/vnet/session/session_test.c @@ -329,8 +329,7 @@ session_test_namespace (vlib_main_t * vm, unformat_input_t * input) "the server"); server_local_st_index = application_local_session_table (server); local_listener = - session_lookup_local_session_endpoint (server_local_st_index, - &server_sep); + session_lookup_local_endpoint (server_local_st_index, &server_sep); SESSION_TEST ((local_listener != SESSION_INVALID_INDEX), "listener should exist in local table"); @@ -382,8 +381,7 @@ session_test_namespace (vlib_main_t * vm, unformat_input_t * input) s = session_lookup_listener (server_st_index, &server_sep); SESSION_TEST ((s == 0), "listener should not exist in global table"); local_listener = - session_lookup_local_session_endpoint (server_local_st_index, - &server_sep); + session_lookup_local_endpoint (server_local_st_index, &server_sep); SESSION_TEST ((s == 0), "listener should not exist in local table"); detach_args.app_index = server_index; @@ -408,8 +406,7 @@ session_test_namespace (vlib_main_t * vm, unformat_input_t * input) SESSION_TEST ((s == 0), "listener should not exist in global table"); server_local_st_index = application_local_session_table (server); local_listener = - session_lookup_local_session_endpoint (server_local_st_index, - &server_sep); + session_lookup_local_endpoint (server_local_st_index, &server_sep); SESSION_TEST ((local_listener != SESSION_INVALID_INDEX), "listener should exist in local table"); @@ -418,8 +415,7 @@ session_test_namespace (vlib_main_t * vm, unformat_input_t * input) SESSION_TEST ((error == 0), "unbind should work"); local_listener = - session_lookup_local_session_endpoint (server_local_st_index, - &server_sep); + session_lookup_local_endpoint (server_local_st_index, &server_sep); SESSION_TEST ((local_listener == SESSION_INVALID_INDEX), "listener should not exist in local table"); @@ -490,8 +486,7 @@ session_test_namespace (vlib_main_t * vm, unformat_input_t * input) "the server"); server_local_st_index = application_local_session_table (server); local_listener = - session_lookup_local_session_endpoint (server_local_st_index, - &server_sep); + session_lookup_local_endpoint (server_local_st_index, &server_sep); SESSION_TEST ((local_listener != SESSION_INVALID_INDEX), "zero listener should exist in local table"); detach_args.app_index = server_index; @@ -896,7 +891,7 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) .port = rmt_port, .transport_proto = TRANSPORT_PROTO_TCP, }; - app_index = session_lookup_local_session_endpoint (local_ns_index, &sep); + app_index = session_lookup_local_endpoint (local_ns_index, &sep); SESSION_TEST ((app_index != server_index), "local session endpoint lookup " "should not work (global scope)"); @@ -919,12 +914,12 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) rmt_port, TRANSPORT_PROTO_TCP, 0); SESSION_TEST ((tc->c_index == listener->connection_index), "optimized lookup for lcl port + 1 should work"); - app_index = session_lookup_local_session_endpoint (local_ns_index, &sep); - SESSION_TEST ((app_index != server_index), "local session endpoint lookup " - "should not work (constrained lcl ip)"); + app_index = session_lookup_local_endpoint (local_ns_index, &sep); + SESSION_TEST ((app_index == server_index), "local session endpoint lookup " + "should work (lcl ip was zeroed)"); /* - * Add drop rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop) + * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop) */ args.table_args.lcl_port = 1234; args.table_args.lcl.fp_addr.ip4 = lcl_ip; @@ -940,7 +935,7 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) { session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4, TRANSPORT_PROTO_TCP); - session_lookup_dump_local_rules_table (0, FIB_PROTOCOL_IP4, + session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4, TRANSPORT_PROTO_TCP); } @@ -948,7 +943,20 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) &rmt_pref.fp_addr.ip4, lcl_port, rmt_port, TRANSPORT_PROTO_TCP, 0); SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 " - "should fail (drop rule)"); + "should fail (deny rule)"); + app_index = session_lookup_local_endpoint (local_ns_index, &sep); + SESSION_TEST ((app_index == APP_DROP_INDEX), "lookup for 1.2.3.4/32 1234 " + "5.6.7.8/16 4321 in local table should return deny"); + tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, + &rmt_pref.fp_addr.ip4, lcl_port, + rmt_port, TRANSPORT_PROTO_TCP, 0); + SESSION_TEST ((tc == 0), + "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 should not work"); + tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, + &rmt_pref.fp_addr.ip4, lcl_port + 1, + rmt_port, TRANSPORT_PROTO_TCP, 0); + SESSION_TEST ((tc->c_index == listener->connection_index), + "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should work"); /* * Add local scope rule for 0/0 * 5.6.7.8/16 4321 action server_index @@ -956,7 +964,7 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) args.table_args.lcl_port = 0; args.table_args.lcl.fp_len = 0; args.table_args.rmt.fp_len = 16; - args.table_args.action_index = server_index; + args.table_args.action_index = -1; error = vnet_session_rule_add_del (&args); SESSION_TEST ((error == 0), "Add * * 5.6.7.8/16 4321 action %d", args.table_args.action_index); @@ -965,57 +973,87 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) { session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4, TRANSPORT_PROTO_TCP); - session_lookup_dump_local_rules_table (0, FIB_PROTOCOL_IP4, + session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4, TRANSPORT_PROTO_TCP); } - app_index = session_lookup_local_session_endpoint (local_ns_index, &sep); - SESSION_TEST ((app_index == server_index), "local session endpoint lookup " - "should work"); + app_index = session_lookup_local_endpoint (local_ns_index, &sep); + SESSION_TEST ((app_index == APP_DROP_INDEX), + "local session endpoint lookup " "should return deny"); + + /* + * Delete 1.2.3.4/32 1234 5.6.7.8/32 4321 deny + */ + args.table_args.is_add = 0; + args.table_args.lcl_port = 1234; + args.table_args.lcl.fp_addr.ip4 = lcl_ip; + args.table_args.lcl.fp_len = 32; + args.table_args.rmt.fp_addr.ip4 = rmt_ip; + args.table_args.rmt.fp_len = 32; + error = vnet_session_rule_add_del (&args); + SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny"); + + app_index = session_lookup_local_endpoint (local_ns_index, &sep); + SESSION_TEST ((app_index == APP_INVALID_INDEX), + "local session endpoint lookup should return invalid"); /* * Delete 0/0 * 5.6.7.8/16 4321, 1.2.3.4/16 * 5.6.7.8/16 4321 and * 1.2.3.4/16 1234 5.6.7.8/16 4321 */ args.table_args.is_add = 0; + args.table_args.lcl_port = 0; + args.table_args.lcl.fp_addr.ip4 = lcl_ip; + args.table_args.lcl.fp_len = 0; + args.table_args.rmt.fp_addr.ip4 = rmt_ip; + args.table_args.rmt.fp_len = 16; + args.table_args.rmt_port = 4321; error = vnet_session_rule_add_del (&args); SESSION_TEST ((error == 0), "Del 0/0 * 5.6.7.8/16 4321"); - app_index = session_lookup_local_session_endpoint (local_ns_index, &sep); + app_index = session_lookup_local_endpoint (local_ns_index, &sep); SESSION_TEST ((app_index != server_index), "local session endpoint lookup " "should not work (removed)"); args.table_args.is_add = 0; args.table_args.lcl = lcl_pref; + + args.table_args.is_add = 0; + args.table_args.lcl_port = 0; + args.table_args.lcl.fp_addr.ip4 = lcl_ip; + args.table_args.lcl.fp_len = 16; + args.table_args.rmt.fp_addr.ip4 = rmt_ip; + args.table_args.rmt.fp_len = 16; + args.table_args.rmt_port = 4321; error = vnet_session_rule_add_del (&args); SESSION_TEST ((error == 0), "Del 1.2.3.4/16 * 5.6.7.8/16 4321"); tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4, lcl_port + 1, rmt_port, TRANSPORT_PROTO_TCP, 0); - SESSION_TEST ((tc == 0), "optimized lookup for lcl port + 1 should not " + SESSION_TEST ((tc == 0), + "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should not " "work (del)"); args.table_args.is_add = 0; args.table_args.lcl_port = 1234; + args.table_args.lcl.fp_addr.ip4 = lcl_ip; + args.table_args.lcl.fp_len = 16; + args.table_args.rmt.fp_addr.ip4 = rmt_ip; + args.table_args.rmt.fp_len = 16; + args.table_args.rmt_port = 4321; error = vnet_session_rule_add_del (&args); SESSION_TEST ((error == 0), "Del 1.2.3.4/16 1234 5.6.7.8/16 4321"); tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4, lcl_port, rmt_port, TRANSPORT_PROTO_TCP, 0); - SESSION_TEST ((tc == 0), - "optimized lookup should not work (del + negative)"); + SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should " + "not work (del + deny)"); - args.table_args.is_add = 0; - args.table_args.lcl_port = 1234; - args.table_args.lcl.fp_addr.ip4 = lcl_ip; - args.table_args.lcl.fp_len = 32; - args.table_args.rmt.fp_addr.ip4 = rmt_ip; - args.table_args.rmt.fp_len = 32; - error = vnet_session_rule_add_del (&args); - SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 drop"); + SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny"); tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4, lcl_port, rmt_port, TRANSPORT_PROTO_TCP, 0); - SESSION_TEST ((tc == 0), "optimized lookup should not work (no-rule)"); + SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should" + " not work (no-rule)"); /* * Test tags. Add/del rule with tag @@ -1026,22 +1064,43 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) args.table_args.lcl.fp_len = 16; args.table_args.rmt.fp_addr.ip4 = rmt_ip; args.table_args.rmt.fp_len = 16; + args.table_args.rmt_port = 4321; args.table_args.tag = format (0, "test_rule"); + args.table_args.action_index = server_index; error = vnet_session_rule_add_del (&args); - SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 drop " + SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 deny " "tag test_rule"); if (verbose) { session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4, TRANSPORT_PROTO_TCP); - session_lookup_dump_local_rules_table (0, FIB_PROTOCOL_IP4, + session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4, TRANSPORT_PROTO_TCP); } + tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, + &rmt_pref.fp_addr.ip4, lcl_port, + rmt_port, TRANSPORT_PROTO_TCP, 0); + SESSION_TEST ((tc->c_index == listener->connection_index), + "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should work"); + args.table_args.is_add = 0; args.table_args.lcl_port += 1; - SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 drop " + error = vnet_session_rule_add_del (&args); + if (verbose) + { + session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4, + TRANSPORT_PROTO_TCP); + session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4, + TRANSPORT_PROTO_TCP); + } + SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny " "tag test_rule"); - + tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, + &rmt_pref.fp_addr.ip4, lcl_port, + rmt_port, TRANSPORT_PROTO_TCP, 0); + SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should not" + " work (del)"); + vec_free (args.table_args.tag); vnet_app_detach_args_t detach_args = { .app_index = server_index, }; @@ -1151,8 +1210,7 @@ session_test_proxy (vlib_main_t * vm, unformat_input_t * input) session_lookup_dump_local_rules_table (app_ns->local_table_index, FIB_PROTOCOL_IP4, TRANSPORT_PROTO_TCP); - app_index = - session_lookup_local_session_endpoint (app_ns->local_table_index, &sep); + app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep); SESSION_TEST ((app_index == server_index), "local session endpoint lookup" " should work"); @@ -1166,8 +1224,7 @@ session_test_proxy (vlib_main_t * vm, unformat_input_t * input) FIB_PROTOCOL_IP4, TRANSPORT_PROTO_TCP); - app_index = - session_lookup_local_session_endpoint (app_ns->local_table_index, &sep); + app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep); SESSION_TEST ((app_index == SESSION_RULES_TABLE_INVALID_INDEX), "local session endpoint lookup should not work after detach"); -- 2.16.6