X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fsession%2Fsession_lookup.c;h=986832346fc00609d9df5def5a43227fab994d94;hb=07063b8ea;hp=f4b26f6d931c345a3e1cf5fbc388cf07ce2d093f;hpb=a2ff7b8cfc829ffbb6d5de7534efb51f7cba9cf3;p=vpp.git diff --git a/src/vnet/session/session_lookup.c b/src/vnet/session/session_lookup.c index f4b26f6d931..986832346fc 100644 --- a/src/vnet/session/session_lookup.c +++ b/src/vnet/session/session_lookup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 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: @@ -29,11 +29,6 @@ #include #include -/** - * External vector of per transport virtual functions table - */ -extern transport_proto_vft_t *tp_vfts; - /** * Network namespace index (i.e., fib index) to session lookup table. We * should have one per network protocol type but for now we only support IP4/6 @@ -86,14 +81,8 @@ 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) { - v4_connection_key_t *key = (v4_connection_key_t *) kv->key; - - 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] = (u64) rmt->as_u32 << 32 | (u64) lcl->as_u32; + kv->key[1] = (u64) proto << 32 | (u64) rmt_port << 16 | (u64) lcl_port; kv->value = ~0ULL; } @@ -101,39 +90,36 @@ always_inline void make_v4_listener_kv (session_kv4_t * kv, ip4_address_t * lcl, u16 lcl_port, 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 = lcl_port; - key->dst_port = 0; - key->proto = proto; + kv->key[0] = (u64) lcl->as_u32; + kv->key[1] = (u64) proto << 32 | (u64) lcl_port; + kv->value = ~0ULL; +} +always_inline void +make_v4_proxy_kv (session_kv4_t * kv, ip4_address_t * lcl, u8 proto) +{ + kv->key[0] = (u64) lcl->as_u32; + kv->key[1] = (u64) proto << 32; kv->value = ~0ULL; } always_inline void -make_v4_ss_kv_from_tc (session_kv4_t * kv, transport_connection_t * t) +make_v4_ss_kv_from_tc (session_kv4_t * kv, transport_connection_t * tc) { - make_v4_ss_kv (kv, &t->lcl_ip.ip4, &t->rmt_ip.ip4, t->lcl_port, t->rmt_port, - session_type_from_proto_and_ip (t->proto, 1)); + make_v4_ss_kv (kv, &tc->lcl_ip.ip4, &tc->rmt_ip.ip4, tc->lcl_port, + tc->rmt_port, tc->proto); } 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) { - 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] = 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; - key->unused = 0; - + kv->key[0] = lcl->as_u64[0]; + kv->key[1] = lcl->as_u64[1]; + kv->key[2] = rmt->as_u64[0]; + kv->key[3] = rmt->as_u64[1]; + kv->key[4] = (u64) proto << 32 | (u64) rmt_port << 16 | (u64) lcl_port; + kv->key[5] = 0; kv->value = ~0ULL; } @@ -141,25 +127,32 @@ 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 = (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 = lcl_port; - key->dst_port = 0; - key->proto = proto; - key->unused = 0; + kv->key[0] = lcl->as_u64[0]; + kv->key[1] = lcl->as_u64[1]; + kv->key[2] = 0; + kv->key[3] = 0; + kv->key[4] = (u64) proto << 32 | (u64) lcl_port; + kv->key[5] = 0; + kv->value = ~0ULL; +} +always_inline void +make_v6_proxy_kv (session_kv6_t * kv, ip6_address_t * lcl, u8 proto) +{ + kv->key[0] = lcl->as_u64[0]; + kv->key[1] = lcl->as_u64[1]; + kv->key[2] = 0; + kv->key[3] = 0; + kv->key[4] = (u64) proto << 32; + kv->key[5] = 0; kv->value = ~0ULL; } always_inline void -make_v6_ss_kv_from_tc (session_kv6_t * kv, transport_connection_t * t) +make_v6_ss_kv_from_tc (session_kv6_t * kv, transport_connection_t * tc) { - make_v6_ss_kv (kv, &t->lcl_ip.ip6, &t->rmt_ip.ip6, t->lcl_port, t->rmt_port, - session_type_from_proto_and_ip (t->proto, 0)); + make_v6_ss_kv (kv, &tc->lcl_ip.ip6, &tc->rmt_ip.ip6, tc->lcl_port, + tc->rmt_port, tc->proto); } static session_table_t * @@ -174,6 +167,7 @@ session_table_get_or_alloc (u8 fib_proto, u8 fib_index) vec_validate (fib_index_to_table_index[fib_proto], fib_index); fib_index_to_table_index[fib_proto][fib_index] = table_index; st->active_fib_proto = fib_proto; + session_table_init (st, fib_proto); return st; } else @@ -306,6 +300,32 @@ session_lookup_del_session_endpoint (u32 table_index, } } +int +session_lookup_del_session_endpoint2 (session_endpoint_t * sep) +{ + fib_protocol_t fib_proto; + session_table_t *st; + session_kv4_t kv4; + session_kv6_t kv6; + + fib_proto = sep->is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6; + st = session_table_get_for_fib_index (fib_proto, sep->fib_index); + if (!st) + return -1; + if (sep->is_ip4) + { + make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port, + sep->transport_proto); + return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4, 0); + } + else + { + make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port, + sep->transport_proto); + return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6, 0); + } +} + /** * Delete transport connection from session table * @@ -339,71 +359,93 @@ session_lookup_del_connection (transport_connection_t * tc) } int -session_lookup_del_session (stream_session_t * s) +session_lookup_del_session (session_t * s) { transport_connection_t *ts; - ts = tp_vfts[s->session_type].get_connection (s->connection_index, - s->thread_index); + ts = transport_get_connection (session_get_transport_proto (s), + s->connection_index, s->thread_index); + if (!ts || (ts->flags & TRANSPORT_CONNECTION_F_NO_LOOKUP)) + return 0; return session_lookup_del_connection (ts); } -static u32 -session_lookup_action_to_session_index (u32 action_index) +static u8 +session_lookup_action_index_is_valid (u32 action_index) +{ + if (action_index == SESSION_RULES_TABLE_ACTION_ALLOW + || action_index == SESSION_RULES_TABLE_INVALID_INDEX) + return 0; + return 1; +} + +static u64 +session_lookup_action_to_handle (u32 action_index) { - if (action_index != SESSION_RULES_TABLE_ACTION_DROP) - return action_index; - return SESSION_INVALID_INDEX; + switch (action_index) + { + case SESSION_RULES_TABLE_ACTION_DROP: + return SESSION_DROP_HANDLE; + case SESSION_RULES_TABLE_ACTION_ALLOW: + case SESSION_RULES_TABLE_INVALID_INDEX: + return SESSION_INVALID_HANDLE; + default: + /* application index */ + return action_index; + } } -static stream_session_t * +static session_t * session_lookup_app_listen_session (u32 app_index, u8 fib_proto, u8 transport_proto) { application_t *app; - app = application_get (app_index); + app = application_get_if_valid (app_index); if (!app) return 0; - return application_first_listener (app, fib_proto, transport_proto); + return app_worker_first_listener (application_get_default_worker (app), + fib_proto, transport_proto); } -static stream_session_t * +static 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); + u32 app_index; + app_index = session_lookup_action_to_handle (action_index); /* Nothing sophisticated for now, action index is app index */ - return session_lookup_app_listen_session (session_index, fib_proto, + return session_lookup_app_listen_session (app_index, fib_proto, transport_proto); } -stream_session_t * +/** UNUSED */ +session_t * 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; + u32 action_index, app_index; action_index = session_rules_table_lookup4 (srt, lcl, rmt, lcl_port, rmt_port); - session_index = session_lookup_action_to_session_index (action_index); + app_index = session_lookup_action_to_handle (action_index); /* Nothing sophisticated for now, action index is app index */ - return session_lookup_app_listen_session (session_index, FIB_PROTOCOL_IP4, + return session_lookup_app_listen_session (app_index, FIB_PROTOCOL_IP4, proto); } -stream_session_t * -session_lookup_rules_table6 (session_table_t * st, u8 proto, - ip6_address_t * lcl, u16 lcl_port, - ip6_address_t * rmt, u16 rmt_port) +/** UNUSED */ +session_t * +session_lookup_rules_table_session6 (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; + u32 action_index, app_index; action_index = session_rules_table_lookup6 (srt, lcl, rmt, lcl_port, rmt_port); - session_index = session_lookup_action_to_session_index (action_index); - return session_lookup_app_listen_session (session_index, FIB_PROTOCOL_IP6, + app_index = session_lookup_action_to_handle (action_index); + return session_lookup_app_listen_session (app_index, FIB_PROTOCOL_IP6, proto); } @@ -415,7 +457,7 @@ session_lookup_rules_table6 (session_table_t * st, u8 proto, * @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 + * or an action derived handle if a rule is hit */ u64 session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep, @@ -425,9 +467,7 @@ session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep, session_table_t *st; 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; @@ -436,18 +476,19 @@ session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep, session_kv4_t kv4; ip4_address_t lcl4; - make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port, sst); + 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 kv4.value; if (use_rules) { - memset (&lcl4, 0, sizeof (lcl4)); + clib_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); + if (session_lookup_action_index_is_valid (ai)) + return session_lookup_action_to_handle (ai); } } else @@ -455,19 +496,20 @@ session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep, session_kv6_t kv6; ip6_address_t lcl6; - make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port, sst); + 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 kv6.value; if (use_rules) { - memset (&lcl6, 0, sizeof (lcl6)); + clib_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); + if (session_lookup_action_index_is_valid (ai)) + return session_lookup_action_to_handle (ai); } } return SESSION_INVALID_HANDLE; @@ -487,9 +529,9 @@ session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep, * * @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. + * @return session handle that can be interpreted as an adjacency */ -u32 +u64 session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep) { session_rules_table_t *srt; @@ -510,14 +552,12 @@ session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep) /* * Check if endpoint has special rules associated */ - memset (&lcl4, 0, sizeof (lcl4)); + clib_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); + if (session_lookup_action_index_is_valid (ai)) + return session_lookup_action_to_handle (ai); /* * Check if session endpoint is a listener @@ -526,83 +566,132 @@ session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep) sep->transport_proto); rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4); if (rv == 0) - return (u32) kv4.value; + return kv4.value; /* * Zero out the ip. Logic is that connect to local ips, say * 127.0.0.1:port, can match 0.0.0.0:port */ - kv4.key[0] = 0; + if (ip4_is_local_host (&sep->ip.ip4)) + { + kv4.key[0] = 0; + rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4); + if (rv == 0) + return kv4.value; + } + else + { + kv4.key[0] = 0; + } + + /* + * 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; + return kv4.value; } else { session_kv6_t kv6; ip6_address_t lcl6; - memset (&lcl6, 0, sizeof (lcl6)); + clib_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); + if (session_lookup_action_index_is_valid (ai)) + return session_lookup_action_to_handle (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); if (rv == 0) - return (u32) kv6.value; + return kv6.value; /* * Zero out the ip. Same logic as above. */ - kv6.key[0] = kv6.key[1] = 0; + + if (ip6_is_local_host (&sep->ip.ip6)) + { + kv6.key[0] = kv6.key[1] = 0; + rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6); + if (rv == 0) + return kv6.value; + } + else + { + kv6.key[0] = kv6.key[1] = 0; + } + + /* + * 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 kv6.value; } - return APP_INVALID_INDEX; + return SESSION_INVALID_HANDLE; } -static stream_session_t * +static inline session_t * session_lookup_listener4_i (session_table_t * st, ip4_address_t * lcl, - u16 lcl_port, u8 proto) + u16 lcl_port, u8 proto, u8 use_wildcard) { 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); + return listen_session_get ((u32) kv4.value); - /* Zero out the lcl ip */ - kv4.key[0] = 0; + /* + * Zero out the lcl ip and check if any 0/0 port binds have been done + */ + if (use_wildcard) + { + kv4.key[0] = 0; + rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4); + if (rv == 0) + return listen_session_get ((u32) kv4.value); + } + else + { + kv4.key[0] = 0; + } + + /* + * 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 listen_session_get ((u32) kv4.value); return 0; } -stream_session_t * +session_t * session_lookup_listener4 (u32 fib_index, ip4_address_t * lcl, u16 lcl_port, - u8 proto) + u8 proto, u8 use_wildcard) { session_table_t *st; st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index); if (!st) return 0; - return session_lookup_listener4_i (st, lcl, lcl_port, proto); + return session_lookup_listener4_i (st, lcl, lcl_port, proto, use_wildcard); } -static stream_session_t * +static session_t * session_lookup_listener6_i (session_table_t * st, ip6_address_t * lcl, - u16 lcl_port, u8 proto) + u16 lcl_port, u8 proto, u8 ip_wildcard) { session_kv6_t kv6; int rv; @@ -610,29 +699,43 @@ session_lookup_listener6_i (session_table_t * st, ip6_address_t * lcl, make_v6_listener_kv (&kv6, lcl, lcl_port, 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 listen_session_get ((u32) kv6.value); /* Zero out the lcl ip */ - kv6.key[0] = kv6.key[1] = 0; + if (ip_wildcard) + { + kv6.key[0] = kv6.key[1] = 0; + rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6); + if (rv == 0) + return listen_session_get ((u32) kv6.value); + } + else + { + kv6.key[0] = kv6.key[1] = 0; + } + + 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 listen_session_get ((u32) kv6.value); return 0; } -stream_session_t * +session_t * session_lookup_listener6 (u32 fib_index, ip6_address_t * lcl, u16 lcl_port, - u8 proto) + u8 proto, u8 use_wildcard) { session_table_t *st; st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index); if (!st) return 0; - return session_lookup_listener6_i (st, lcl, lcl_port, proto); + return session_lookup_listener6_i (st, lcl, lcl_port, proto, use_wildcard); } -stream_session_t * +/** + * Lookup listener, exact or proxy (inaddr_any:0) match + */ +session_t * session_lookup_listener (u32 table_index, session_endpoint_t * sep) { session_table_t *st; @@ -641,10 +744,31 @@ session_lookup_listener (u32 table_index, session_endpoint_t * sep) return 0; if (sep->is_ip4) return session_lookup_listener4_i (st, &sep->ip.ip4, sep->port, - sep->transport_proto); + sep->transport_proto, 0); + else + return session_lookup_listener6_i (st, &sep->ip.ip6, sep->port, + sep->transport_proto, 0); + return 0; +} + +/** + * Lookup listener wildcard match + */ +session_t * +session_lookup_listener_wildcard (u32 table_index, session_endpoint_t * sep) +{ + session_table_t *st; + st = session_table_get (table_index); + if (!st) + return 0; + if (sep->is_ip4) + return session_lookup_listener4_i (st, &sep->ip.ip4, sep->port, + sep->transport_proto, + 1 /* use_wildcard */ ); else return session_lookup_listener6_i (st, &sep->ip.ip6, sep->port, - sep->transport_proto); + sep->transport_proto, + 1 /* use_wildcard */ ); return 0; } @@ -732,12 +856,10 @@ session_lookup_half_open_handle (transport_connection_t * tc) transport_connection_t * session_lookup_half_open_connection (u64 handle, u8 proto, u8 is_ip4) { - u32 sst; - if (handle != HALF_OPEN_LOOKUP_INVALID_VALUE) { - sst = session_type_from_proto_and_ip (proto, is_ip4); - return tp_vfts[sst].get_half_open (handle & 0xFFFFFFFF); + u32 sst = session_type_from_proto_and_ip (proto, is_ip4); + return transport_get_half_open (sst, handle & 0xFFFFFFFF); } return 0; } @@ -764,17 +886,19 @@ session_lookup_half_open_connection (u64 handle, u8 proto, u8 is_ip4) * @param rmt_port remote port * @param proto transport protocol (e.g., tcp, udp) * @param thread_index thread index for request + * @param is_filtered return flag that indicates if connection was filtered. * * @return pointer to transport connection, if one is found, 0 otherwise */ transport_connection_t * session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl, ip4_address_t * rmt, u16 lcl_port, - u16 rmt_port, u8 proto, u32 thread_index) + u16 rmt_port, u8 proto, u32 thread_index, + u8 * result) { session_table_t *st; session_kv4_t kv4; - stream_session_t *s; + session_t *s; u32 action_index; int rv; @@ -789,10 +913,14 @@ session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl, rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4); if (rv == 0) { - ASSERT ((u32) (kv4.value >> 32) == thread_index); + if (PREDICT_FALSE ((u32) (kv4.value >> 32) != thread_index)) + { + *result = SESSION_LOOKUP_RESULT_WRONG_THREAD; + return 0; + } s = session_get (kv4.value & 0xFFFFFFFFULL, thread_index); - return tp_vfts[s->session_type].get_connection (s->connection_index, - thread_index); + return transport_get_connection (proto, s->connection_index, + thread_index); } /* @@ -800,32 +928,32 @@ session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl, */ 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); - } + return transport_get_half_open (proto, kv4.value & 0xFFFFFFFF); /* * 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 (session_lookup_action_index_is_valid (action_index)) { - 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 (action_index == SESSION_RULES_TABLE_ACTION_DROP) + { + *result = SESSION_LOOKUP_RESULT_FILTERED; + return 0; + } + if ((s = session_lookup_action_to_session (action_index, + FIB_PROTOCOL_IP4, proto))) + return transport_get_listener (proto, s->connection_index); + return 0; } /* * If nothing is found, check if any listener is available */ - s = session_lookup_listener4_i (st, lcl, lcl_port, proto); + s = session_lookup_listener4_i (st, lcl, lcl_port, proto, 1); if (s) - return tp_vfts[s->session_type].get_listener (s->connection_index); + return transport_get_listener (proto, s->connection_index); return 0; } @@ -833,9 +961,8 @@ session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl, /** * Lookup connection with ip4 and transport layer information * - * Not optimized. This is used on the fast path so it needs to be fast. - * Thereby, duplication of code and 'hacks' allowed. Lookup logic is identical - * to that of @ref session_lookup_connection_wt4 + * Not optimized. Lookup logic is identical to that of + * @ref session_lookup_connection_wt4 * * @param fib_index index of the fib wherein the connection was received * @param lcl local ip4 address @@ -853,7 +980,7 @@ session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl, { session_table_t *st; session_kv4_t kv4; - stream_session_t *s; + session_t *s; u32 action_index; int rv; @@ -869,8 +996,8 @@ session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl, if (rv == 0) { s = session_get_from_handle (kv4.value); - return tp_vfts[s->session_type].get_connection (s->connection_index, - s->thread_index); + return transport_get_connection (proto, s->connection_index, + s->thread_index); } /* @@ -878,32 +1005,29 @@ session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl, */ 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); - } + return transport_get_half_open (proto, kv4.value & 0xFFFFFFFF); /* * 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 (session_lookup_action_index_is_valid (action_index)) { - 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 (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + if ((s = session_lookup_action_to_session (action_index, + FIB_PROTOCOL_IP4, proto))) + return transport_get_listener (proto, s->connection_index); + return 0; } /* * If nothing is found, check if any listener is available */ - s = session_lookup_listener4_i (st, lcl, lcl_port, proto); + s = session_lookup_listener4_i (st, lcl, lcl_port, proto, 1); if (s) - return tp_vfts[s->session_type].get_listener (s->connection_index); + return transport_get_listener (proto, s->connection_index); return 0; } @@ -921,13 +1045,13 @@ session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl, * * Typically used by dgram connections */ -stream_session_t * +session_t * session_lookup_safe4 (u32 fib_index, ip4_address_t * lcl, ip4_address_t * rmt, u16 lcl_port, u16 rmt_port, u8 proto) { session_table_t *st; session_kv4_t kv4; - stream_session_t *s; + session_t *s; u32 action_index; int rv; @@ -948,19 +1072,18 @@ session_lookup_safe4 (u32 fib_index, ip4_address_t * lcl, ip4_address_t * rmt, */ 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 (session_lookup_action_index_is_valid (action_index)) { - if ((s = session_lookup_action_to_session (action_index, - FIB_PROTOCOL_IP4, proto))) - return s; + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + return session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP4, + proto); } /* * If nothing is found, check if any listener is available */ - if ((s = session_lookup_listener4_i (st, lcl, lcl_port, proto))) + if ((s = session_lookup_listener4_i (st, lcl, lcl_port, proto, 1))) return s; return 0; @@ -994,10 +1117,11 @@ session_lookup_safe4 (u32 fib_index, ip4_address_t * lcl, ip4_address_t * rmt, transport_connection_t * session_lookup_connection_wt6 (u32 fib_index, ip6_address_t * lcl, ip6_address_t * rmt, u16 lcl_port, - u16 rmt_port, u8 proto, u32 thread_index) + u16 rmt_port, u8 proto, u32 thread_index, + u8 * result) { session_table_t *st; - stream_session_t *s; + session_t *s; session_kv6_t kv6; u32 action_index; int rv; @@ -1011,36 +1135,41 @@ session_lookup_connection_wt6 (u32 fib_index, ip6_address_t * lcl, if (rv == 0) { ASSERT ((u32) (kv6.value >> 32) == thread_index); + if (PREDICT_FALSE ((u32) (kv6.value >> 32) != thread_index)) + { + *result = SESSION_LOOKUP_RESULT_WRONG_THREAD; + return 0; + } s = session_get (kv6.value & 0xFFFFFFFFULL, thread_index); - return tp_vfts[s->session_type].get_connection (s->connection_index, - thread_index); + return transport_get_connection (proto, s->connection_index, + thread_index); } /* Try half-open connections */ rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6); if (rv == 0) - { - u32 sst = session_type_from_proto_and_ip (proto, 1); - return tp_vfts[sst].get_half_open (kv6.value & 0xFFFFFFFF); - } + return transport_get_half_open (proto, kv6.value & 0xFFFFFFFF); /* 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 (session_lookup_action_index_is_valid (action_index)) { - 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 (action_index == SESSION_RULES_TABLE_ACTION_DROP) + { + *result = SESSION_LOOKUP_RESULT_FILTERED; + return 0; + } + if ((s = session_lookup_action_to_session (action_index, + FIB_PROTOCOL_IP6, proto))) + return transport_get_listener (proto, s->connection_index); + return 0; } /* If nothing is found, check if any listener is available */ - s = session_lookup_listener6_i (st, lcl, lcl_port, proto); + s = session_lookup_listener6_i (st, lcl, lcl_port, proto, 1); if (s) - return tp_vfts[s->session_type].get_listener (s->connection_index); + return transport_get_listener (proto, s->connection_index); return 0; } @@ -1067,7 +1196,7 @@ session_lookup_connection6 (u32 fib_index, ip6_address_t * lcl, u8 proto) { session_table_t *st; - stream_session_t *s; + session_t *s; session_kv6_t kv6; u32 action_index; int rv; @@ -1081,35 +1210,32 @@ session_lookup_connection6 (u32 fib_index, ip6_address_t * lcl, if (rv == 0) { s = session_get_from_handle (kv6.value); - return tp_vfts[s->session_type].get_connection (s->connection_index, - s->thread_index); + return transport_get_connection (proto, s->connection_index, + s->thread_index); } /* Try half-open connections */ rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6); if (rv == 0) - { - u32 sst = session_type_from_proto_and_ip (proto, 1); - return tp_vfts[sst].get_half_open (kv6.value & 0xFFFFFFFF); - } + return transport_get_half_open (proto, kv6.value & 0xFFFFFFFF); /* 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 (session_lookup_action_index_is_valid (action_index)) { - 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 (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + if ((s = session_lookup_action_to_session (action_index, + FIB_PROTOCOL_IP6, proto))) + return transport_get_listener (proto, s->connection_index); + return 0; } /* If nothing is found, check if any listener is available */ - s = session_lookup_listener6 (fib_index, lcl, lcl_port, proto); + s = session_lookup_listener6_i (st, lcl, lcl_port, proto, 1); if (s) - return tp_vfts[s->session_type].get_listener (s->connection_index); + return transport_get_listener (proto, s->connection_index); return 0; } @@ -1127,13 +1253,13 @@ session_lookup_connection6 (u32 fib_index, ip6_address_t * lcl, * * Typically used by dgram connections */ -stream_session_t * +session_t * session_lookup_safe6 (u32 fib_index, ip6_address_t * lcl, ip6_address_t * rmt, u16 lcl_port, u16 rmt_port, u8 proto) { session_table_t *st; session_kv6_t kv6; - stream_session_t *s; + session_t *s; u32 action_index; int rv; @@ -1149,54 +1275,21 @@ session_lookup_safe6 (u32 fib_index, ip6_address_t * lcl, ip6_address_t * rmt, /* 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 (session_lookup_action_index_is_valid (action_index)) { - if ((s = - session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP4, - proto))) - return s; + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + return session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP6, + proto); } /* If nothing is found, check if any listener is available */ - if ((s = session_lookup_listener6_i (st, lcl, lcl_port, proto))) + if ((s = session_lookup_listener6_i (st, lcl, lcl_port, proto, 1))) return s; return 0; } -u64 -session_lookup_local_listener_make_handle (session_endpoint_t * sep) -{ - return ((u64) SESSION_LOCAL_TABLE_PREFIX << 32 - | (u32) sep->port << 16 | (u32) sep->transport_proto << 8 - | (u32) sep->is_ip4); -} - -u8 -session_lookup_local_is_handle (u64 handle) -{ - if (handle >> 32 == SESSION_LOCAL_TABLE_PREFIX) - return 1; - return 0; -} - int -session_lookup_local_listener_parse_handle (u64 handle, - session_endpoint_t * sep) -{ - u32 local_table_handle; - if (handle >> 32 != SESSION_LOCAL_TABLE_PREFIX) - return -1; - local_table_handle = handle & 0xFFFFFFFFULL; - sep->is_ip4 = local_table_handle & 0xff; - local_table_handle >>= 8; - sep->transport_proto = local_table_handle & 0xff; - sep->port = local_table_handle >> 8; - return 0; -} - -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); @@ -1204,40 +1297,37 @@ vnet_session_rule_add_del (session_rule_add_del_args_t * args) session_table_t *st; u32 fib_index; u8 fib_proto; - clib_error_t *error; + int rv = 0; if (!app_ns) - return clib_error_return_code (0, VNET_API_ERROR_APP_INVALID_NS, 0, - "invalid app ns"); + return VNET_API_ERROR_APP_INVALID_NS; + if (args->scope > 3) - return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0, - "invalid scope"); + return VNET_API_ERROR_INVALID_VALUE; + 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"); + return VNET_API_ERROR_INVALID_VALUE; + 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); 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 ((rv = session_rules_table_add_del (srt, &args->table_args))) + return rv; } if (args->scope & SESSION_RULE_SCOPE_LOCAL) { - memset (&args->table_args.lcl, 0, sizeof (args->table_args.lcl)); + clib_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); + rv = session_rules_table_add_del (srt, &args->table_args); } - return error; + return rv; } /** @@ -1253,7 +1343,7 @@ session_lookup_set_tables_appns (app_namespace_t * app_ns) for (fp = 0; fp < ARRAY_LEN (fib_index_to_table_index); fp++) { fib_index = app_namespace_get_fib_index (app_ns, fp); - st = session_table_get_for_fib_index (fp, fib_index); + st = session_table_get_or_alloc (fp, fib_index); if (st) st->appns_index = app_namespace_index (app_ns); } @@ -1264,29 +1354,33 @@ format_ip4_session_lookup_kvp (u8 * s, va_list * args) { clib_bihash_kv_16_8_t *kvp = va_arg (*args, clib_bihash_kv_16_8_t *); u32 is_local = va_arg (*args, u32); - u8 *app_name, *str = 0; - stream_session_t *session; v4_connection_key_t *key = (v4_connection_key_t *) kvp->key; + session_t *session; + app_worker_t *app_wrk; + const u8 *app_name; + u8 *str = 0; - char *proto = key->proto == TRANSPORT_PROTO_TCP ? "T" : "U"; if (!is_local) { session = session_get_from_handle (kvp->value); - app_name = application_name_from_index (session->app_index); - str = format (0, "[%s] %U:%d->%U:%d", proto, format_ip4_address, - &key->src, clib_net_to_host_u16 (key->src_port), - format_ip4_address, &key->dst, - clib_net_to_host_u16 (key->dst_port)); + app_wrk = app_worker_get (session->app_wrk_index); + app_name = application_name_from_index (app_wrk->app_index); + str = format (0, "[%U] %U:%d->%U:%d", format_transport_proto_short, + key->proto, format_ip4_address, &key->src, + clib_net_to_host_u16 (key->src_port), format_ip4_address, + &key->dst, clib_net_to_host_u16 (key->dst_port)); s = format (s, "%-40v%-30v", str, app_name); } else { - app_name = application_name_from_index (kvp->value); - str = format (0, "[%s] %U:%d", proto, format_ip4_address, - &key->src, clib_net_to_host_u16 (key->src_port)); + session = session_get_from_handle (kvp->value); + app_wrk = app_worker_get (session->app_wrk_index); + app_name = application_name_from_index (app_wrk->app_index); + str = format (0, "[%U] %U:%d", format_transport_proto_short, key->proto, + format_ip4_address, &key->src, + clib_net_to_host_u16 (key->src_port)); s = format (s, "%-30v%-30v", str, app_name); } - vec_free (app_name); return s; } @@ -1340,10 +1434,12 @@ session_rule_command_fn (vlib_main_t * vm, unformat_input_t * input, u8 fib_proto, is_add = 1, *ns_id = 0; u8 *tag = 0; app_namespace_t *app_ns; - clib_error_t *error; + int rv; + + session_cli_return_if_not_enabled (); - memset (&lcl_ip, 0, sizeof (lcl_ip)); - memset (&rmt_ip, 0, sizeof (rmt_ip)); + clib_memset (&lcl_ip, 0, sizeof (lcl_ip)); + clib_memset (&rmt_ip, 0, sizeof (rmt_ip)); while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "del")) @@ -1423,6 +1519,7 @@ session_rule_command_fn (vlib_main_t * vm, unformat_input_t * input, fib_proto = is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6; session_rule_add_del_args_t args = { + .transport_proto = proto, .table_args.lcl.fp_addr = lcl_ip, .table_args.lcl.fp_len = lcl_plen, .table_args.lcl.fp_proto = fib_proto, @@ -1437,9 +1534,11 @@ session_rule_command_fn (vlib_main_t * vm, unformat_input_t * input, .appns_index = appns_index, .scope = scope, }; - error = vnet_session_rule_add_del (&args); + if ((rv = vnet_session_rule_add_del (&args))) + return clib_error_return (0, "rule add del returned %u", rv); + vec_free (tag); - return error; + return 0; } /* *INDENT-OFF* */ @@ -1489,8 +1588,10 @@ show_session_rules_command_fn (vlib_main_t * vm, unformat_input_t * input, session_table_t *st; u8 *ns_id = 0, fib_proto; - memset (&lcl_ip, 0, sizeof (lcl_ip)); - memset (&rmt_ip, 0, sizeof (rmt_ip)); + session_cli_return_if_not_enabled (); + + clib_memset (&lcl_ip, 0, sizeof (lcl_ip)); + clib_memset (&rmt_ip, 0, sizeof (rmt_ip)); while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "%U", unformat_transport_proto, &transport_proto)) @@ -1575,8 +1676,8 @@ show_session_rules_command_fn (vlib_main_t * vm, unformat_input_t * input, VLIB_CLI_COMMAND (show_session_rules_command, static) = { .path = "show session rules", - .short_help = "show session rules [appns proto " - " ]", + .short_help = "show session rules [ appns " + " scope ]", .function = show_session_rules_command_fn, }; /* *INDENT-ON* */