X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fsession%2Fsession_lookup.c;h=30e39132d3a9aea44de072e2190452b50855af87;hb=dbd44561538514f6cfce324419042f2ce69fe214;hp=d537b9c1c82f3f91b518fa61e613398ef3a3b0ba;hpb=6c36f53ff0419d27f3e5720a42e0b43d5e7157f0;p=vpp.git diff --git a/src/vnet/session/session_lookup.c b/src/vnet/session/session_lookup.c index d537b9c1c82..30e39132d3a 100644 --- a/src/vnet/session/session_lookup.c +++ b/src/vnet/session/session_lookup.c @@ -112,6 +112,20 @@ make_v4_listener_kv (session_kv4_t * kv, ip4_address_t * lcl, u16 lcl_port, kv->value = ~0ULL; } +always_inline void +make_v4_proxy_kv (session_kv4_t * kv, ip4_address_t * lcl, u8 proto) +{ + v4_connection_key_t *key = (v4_connection_key_t *) kv->key; + + key->src.as_u32 = lcl->as_u32; + key->dst.as_u32 = 0; + key->src_port = 0; + key->dst_port = 0; + key->proto = proto; + + kv->value = ~0ULL; +} + always_inline void make_v4_ss_kv_from_tc (session_kv4_t * kv, transport_connection_t * t) { @@ -155,6 +169,23 @@ make_v6_listener_kv (session_kv6_t * kv, ip6_address_t * lcl, u16 lcl_port, kv->value = ~0ULL; } +always_inline void +make_v6_proxy_kv (session_kv6_t * kv, ip6_address_t * lcl, u8 proto) +{ + v6_connection_key_t *key = (v6_connection_key_t *) kv->key; + + 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 = 0; + key->dst_port = 0; + key->proto = proto; + key->unused = 0; + + kv->value = ~0ULL; +} + always_inline void make_v6_ss_kv_from_tc (session_kv6_t * kv, transport_connection_t * t) { @@ -348,7 +379,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,140 +398,161 @@ 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_rules_table_t * srt, 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, proto, lcl, rmt, lcl_port, + 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); } stream_session_t * -session_lookup_rules_table6 (session_rules_table_t * srt, u8 proto, +session_lookup_rules_table6 (session_table_t * st, u8 proto, ip6_address_t * lcl, u16 lcl_port, ip6_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_lookup6 (srt, proto, lcl, rmt, lcl_port, + 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; + sst = session_type_from_proto_and_ip (sep->transport_proto, sep->is_ip4); st = session_table_get (table_index); if (!st) return SESSION_INVALID_HANDLE; if (sep->is_ip4) { - make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port, - sep->transport_proto); + 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)); - ai = session_rules_table_lookup4 (&st->session_rules, - sep->transport_proto, &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 { - make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port, - sep->transport_proto); + 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)); - ai = session_rules_table_lookup6 (&st->session_rules, - sep->transport_proto, &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->session_rules, - 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->session_rules, - 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); @@ -516,15 +568,28 @@ session_lookup_local_session_endpoint (u32 table_index, if (rv == 0) return (u32) kv4.value; - memset (&lcl4, 0, sizeof (lcl4)); - ai = session_rules_table_lookup4 (&st->session_rules, - sep->transport_proto, &lcl4, - &sep->ip.ip4, 0, sep->port); - if (ai != SESSION_RULES_TABLE_INVALID_INDEX) - return session_lookup_action_to_session (ai); + /* + * Zero out the port and check if we have proxy + */ + kv4.key[1] = 0; + 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 (&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_ACTION_DROP) + return APP_DROP_INDEX; + if (ai != SESSION_RULES_TABLE_INVALID_INDEX) + 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); @@ -539,14 +604,15 @@ session_lookup_local_session_endpoint (u32 table_index, if (rv == 0) return (u32) kv6.value; - memset (&lcl6, 0, sizeof (lcl6)); - ai = session_rules_table_lookup6 (&st->session_rules, - sep->transport_proto, &lcl6, - &sep->ip.ip6, 0, sep->port); - if (ai != SESSION_RULES_TABLE_INVALID_INDEX) - return session_lookup_action_to_session (ai); + /* + * Zero out the port. Same logic as above. + */ + kv6.key[4] = kv6.key[5] = 0; + rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6); + if (rv == 0) + return (u32) kv6.value; } - return SESSION_INVALID_INDEX; + return APP_INVALID_INDEX; } static stream_session_t * @@ -556,17 +622,30 @@ session_lookup_listener4_i (session_table_t * st, ip4_address_t * lcl, session_kv4_t kv4; int rv; + /* + * First, try a fully formed listener + */ make_v4_listener_kv (&kv4, lcl, lcl_port, proto); rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4); if (rv == 0) return session_manager_get_listener (proto, (u32) kv4.value); - /* Zero out the lcl ip */ + /* + * Zero out the lcl ip and check if any 0/0 port binds have been done + */ kv4.key[0] = 0; rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4); if (rv == 0) return session_manager_get_listener (proto, (u32) kv4.value); + /* + * Zero out port and check if we have a proxy set up for our ip + */ + make_v4_proxy_kv (&kv4, lcl, proto); + rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4); + if (rv == 0) + return session_manager_get_listener (proto, (u32) kv4.value); + return 0; } @@ -599,6 +678,10 @@ session_lookup_listener6_i (session_table_t * st, ip6_address_t * lcl, if (rv == 0) return session_manager_get_listener (proto, (u32) kv6.value); + make_v6_proxy_kv (&kv6, lcl, proto); + rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6); + if (rv == 0) + return session_manager_get_listener (proto, (u32) kv6.value); return 0; } @@ -723,30 +806,6 @@ session_lookup_half_open_connection (u64 handle, u8 proto, u8 is_ip4) return 0; } -transport_connection_t * -session_lookup_rules_table_connection4 (session_rules_table_t * srt, 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 (srt, proto, lcl, lcl_port, rmt, rmt_port); - if (s) - return tp_vfts[s->session_type].get_listener (s->connection_index); - return 0; -} - -transport_connection_t * -session_lookup_rules_table_connection6 (session_rules_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 * @@ -756,10 +815,10 @@ session_lookup_rules_table_connection6 (session_rules_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 @@ -780,13 +839,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) @@ -797,12 +859,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) { @@ -810,10 +869,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->session_rules, 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; } /** @@ -840,13 +918,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) @@ -856,22 +937,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->session_rules, 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 +992,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->session_rules, proto, lcl, - lcl_port, rmt, rmt_port); + + return 0; } /** @@ -922,10 +1039,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 +1063,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 +1080,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,9 +1088,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->session_rules, 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; } /** @@ -1004,6 +1133,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); @@ -1019,12 +1149,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) { @@ -1032,9 +1157,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->session_rules, 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; } /** @@ -1057,6 +1198,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); @@ -1068,11 +1210,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->session_rules, proto, lcl, - lcl_port, rmt, rmt_port); + return 0; } u64 @@ -1110,6 +1264,7 @@ clib_error_t * vnet_session_rule_add_del (session_rule_add_del_args_t * args) { app_namespace_t *app_ns = app_namespace_get (args->appns_index); + session_rules_table_t *srt; session_table_t *st; u32 fib_index; u8 fib_proto; @@ -1121,20 +1276,30 @@ vnet_session_rule_add_del (session_rule_add_del_args_t * args) if (args->scope > 3) return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0, "invalid scope"); + if (args->transport_proto != TRANSPORT_PROTO_TCP + && args->transport_proto != TRANSPORT_PROTO_UDP) + return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0, + "invalid transport proto"); if ((args->scope & SESSION_RULE_SCOPE_GLOBAL) || args->scope == 0) { fib_proto = args->table_args.rmt.fp_proto; fib_index = app_namespace_get_fib_index (app_ns, fib_proto); st = session_table_get_for_fib_index (fib_proto, fib_index); - if ((error = session_rules_table_add_del (&st->session_rules, - &args->table_args))) - return error; + srt = &st->session_rules[args->transport_proto]; + if ((error = session_rules_table_add_del (srt, &args->table_args))) + { + clib_error_report (error); + return error; + } } 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); - error = session_rules_table_add_del (&st->session_rules, - &args->table_args); + srt = &st->session_rules[args->transport_proto]; + error = session_rules_table_add_del (srt, &args->table_args); } return error; } @@ -1232,12 +1397,14 @@ static clib_error_t * session_rule_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { - u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen, rmt_plen; + u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen = 0, rmt_plen = 0; u32 appns_index, scope = 0; ip46_address_t lcl_ip, rmt_ip; u8 is_ip4 = 1, conn_set = 0; u8 fib_proto, is_add = 1, *ns_id = 0; + u8 *tag = 0; app_namespace_t *app_ns; + clib_error_t *error; memset (&lcl_ip, 0, sizeof (lcl_ip)); memset (&rmt_ip, 0, sizeof (rmt_ip)); @@ -1275,19 +1442,42 @@ session_rule_command_fn (vlib_main_t * vm, unformat_input_t * input, } else if (unformat (input, "action %d", &action)) ; + else if (unformat (input, "tag %_%v%_", &tag)) + ; else return clib_error_return (0, "unknown input `%U'", format_unformat_error, input); } - if (proto == ~0 || !conn_set || action == ~0) - return clib_error_return (0, "proto, connection and action must be set"); + if (proto == ~0) + { + vlib_cli_output (vm, "proto must be set"); + return 0; + } + if (is_add && !conn_set && action == ~0) + { + vlib_cli_output (vm, "connection and action must be set for add"); + return 0; + } + if (!is_add && !tag && !conn_set) + { + vlib_cli_output (vm, "connection or tag must be set for delete"); + return 0; + } + if (vec_len (tag) > SESSION_RULE_TAG_MAX_LEN) + { + vlib_cli_output (vm, "tag too long (max u64)"); + return 0; + } if (ns_id) { app_ns = app_namespace_get_from_id (ns_id); if (!app_ns) - return clib_error_return (0, "namespace %v does not exist", ns_id); + { + vlib_cli_output (vm, "namespace %v does not exist", ns_id); + return 0; + } } else { @@ -1307,10 +1497,13 @@ session_rule_command_fn (vlib_main_t * vm, unformat_input_t * input, .table_args.rmt_port = rmt_port, .table_args.action_index = action, .table_args.is_add = is_add, + .table_args.tag = tag, .appns_index = appns_index, .scope = scope, }; - return vnet_session_rule_add_del (&args); + error = vnet_session_rule_add_del (&args); + vec_free (tag); + return error; } /* *INDENT-OFF* */ @@ -1328,10 +1521,11 @@ session_lookup_dump_rules_table (u32 fib_index, u8 fib_proto, u8 transport_proto) { vlib_main_t *vm = vlib_get_main (); + session_rules_table_t *srt; session_table_t *st; st = session_table_get_for_fib_index (fib_index, fib_proto); - session_rules_table_cli_dump (vm, &st->session_rules, fib_proto, - transport_proto); + srt = &st->session_rules[transport_proto]; + session_rules_table_cli_dump (vm, srt, fib_proto); } void @@ -1339,10 +1533,11 @@ session_lookup_dump_local_rules_table (u32 table_index, u8 fib_proto, u8 transport_proto) { vlib_main_t *vm = vlib_get_main (); + session_rules_table_t *srt; session_table_t *st; st = session_table_get (table_index); - session_rules_table_cli_dump (vm, &st->session_rules, fib_proto, - transport_proto); + srt = &st->session_rules[transport_proto]; + session_rules_table_cli_dump (vm, srt, fib_proto); } static clib_error_t * @@ -1354,6 +1549,7 @@ show_session_rules_command_fn (vlib_main_t * vm, unformat_input_t * input, ip46_address_t lcl_ip, rmt_ip; u8 is_ip4 = 1, show_one = 0; app_namespace_t *app_ns; + session_rules_table_t *srt; session_table_t *st; u8 *ns_id = 0, fib_proto; @@ -1423,16 +1619,17 @@ show_session_rules_command_fn (vlib_main_t * vm, unformat_input_t * input, if (show_one) { - session_rules_table_show_rule (vm, &st->session_rules, transport_proto, - &lcl_ip, lcl_port, &rmt_ip, rmt_port, - is_ip4); + srt = &st->session_rules[transport_proto]; + session_rules_table_show_rule (vm, srt, &lcl_ip, lcl_port, &rmt_ip, + rmt_port, is_ip4); return 0; } - session_rules_table_cli_dump (vm, &st->session_rules, FIB_PROTOCOL_IP4, - transport_proto); - session_rules_table_cli_dump (vm, &st->session_rules, FIB_PROTOCOL_IP6, - transport_proto); + vlib_cli_output (vm, "%U rules table", format_transport_proto, + transport_proto); + srt = &st->session_rules[transport_proto]; + session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4); + session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP6); vec_free (ns_id); return 0;