X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fnat%2Fnat44-ed%2Fnat44_ed.c;h=08e577747c381bd842852926925a838b09ecb73b;hb=4f30bc74577959efddfe4bc544cea4ec5c7019da;hp=e389a81aab1986184f4dc8b5837bbdbb1f83e7fb;hpb=56c492aa0502751de2dd9d890096a82c5f04776d;p=vpp.git diff --git a/src/plugins/nat/nat44-ed/nat44_ed.c b/src/plugins/nat/nat44-ed/nat44_ed.c index e389a81aab1..08e577747c3 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed.c +++ b/src/plugins/nat/nat44-ed/nat44_ed.c @@ -1,6 +1,4 @@ /* - * snat.c - simple nat plugin - * * Copyright (c) 2016 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. @@ -38,7 +36,7 @@ #include #include -#include +#include snat_main_t snat_main; @@ -61,7 +59,7 @@ static_always_inline void nat_validate_interface_counters (snat_main_t *sm, if (PREDICT_FALSE (sm->enabled)) \ { \ nat_log_err ("plugin enabled"); \ - return 1; \ + return VNET_API_ERROR_FEATURE_ALREADY_ENABLED; \ } \ } \ while (0) @@ -73,12 +71,11 @@ static_always_inline void nat_validate_interface_counters (snat_main_t *sm, if (PREDICT_FALSE (!sm->enabled)) \ { \ nat_log_err ("plugin disabled"); \ - return 1; \ + return VNET_API_ERROR_FEATURE_ALREADY_DISABLED; \ } \ } \ while (0) -/* Hook up input features */ VNET_FEATURE_INIT (nat_pre_in2out, static) = { .arc_name = "ip4-unicast", .node_name = "nat-pre-in2out", @@ -92,6 +89,18 @@ VNET_FEATURE_INIT (nat_pre_out2in, static) = { "ip4-dhcp-client-detect", "ip4-sv-reassembly-feature"), }; +VNET_FEATURE_INIT (ip4_nat44_ed_classify, static) = { + .arc_name = "ip4-unicast", + .node_name = "nat44-ed-classify", + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa", + "ip4-sv-reassembly-feature"), +}; +VNET_FEATURE_INIT (ip4_nat_handoff_classify, static) = { + .arc_name = "ip4-unicast", + .node_name = "nat44-handoff-classify", + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa", + "ip4-sv-reassembly-feature"), +}; VNET_FEATURE_INIT (snat_in2out_worker_handoff, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-in2out-worker-handoff", @@ -103,17 +112,6 @@ VNET_FEATURE_INIT (snat_out2in_worker_handoff, static) = { .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa", "ip4-dhcp-client-detect"), }; -VNET_FEATURE_INIT (ip4_snat_in2out, static) = { - .arc_name = "ip4-unicast", - .node_name = "nat44-in2out", - .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"), -}; -VNET_FEATURE_INIT (ip4_snat_out2in, static) = { - .arc_name = "ip4-unicast", - .node_name = "nat44-out2in", - .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature", - "ip4-dhcp-client-detect"), -}; VNET_FEATURE_INIT (ip4_nat44_ed_in2out, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-ed-in2out", @@ -125,32 +123,9 @@ VNET_FEATURE_INIT (ip4_nat44_ed_out2in, static) = { .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature", "ip4-dhcp-client-detect"), }; -VNET_FEATURE_INIT (ip4_nat44_ed_classify, static) = { - .arc_name = "ip4-unicast", - .node_name = "nat44-ed-classify", - .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"), -}; -VNET_FEATURE_INIT (ip4_nat_handoff_classify, static) = { - .arc_name = "ip4-unicast", - .node_name = "nat44-handoff-classify", - .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"), -}; -VNET_FEATURE_INIT (ip4_snat_in2out_fast, static) = { - .arc_name = "ip4-unicast", - .node_name = "nat44-in2out-fast", - .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"), -}; -VNET_FEATURE_INIT (ip4_snat_out2in_fast, static) = { - .arc_name = "ip4-unicast", - .node_name = "nat44-out2in-fast", - .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature", - "ip4-dhcp-client-detect"), -}; - -/* Hook up output features */ -VNET_FEATURE_INIT (ip4_snat_in2out_output, static) = { +VNET_FEATURE_INIT (nat_pre_in2out_output, static) = { .arc_name = "ip4-output", - .node_name = "nat44-in2out-output", + .node_name = "nat-pre-in2out-output", .runs_after = VNET_FEATURES ("ip4-sv-reassembly-output-feature"), .runs_before = VNET_FEATURES ("acl-plugin-out-ip4-fa"), }; @@ -160,12 +135,6 @@ VNET_FEATURE_INIT (ip4_snat_in2out_output_worker_handoff, static) = { .runs_after = VNET_FEATURES ("ip4-sv-reassembly-output-feature"), .runs_before = VNET_FEATURES ("acl-plugin-out-ip4-fa"), }; -VNET_FEATURE_INIT (nat_pre_in2out_output, static) = { - .arc_name = "ip4-output", - .node_name = "nat-pre-in2out-output", - .runs_after = VNET_FEATURES ("ip4-sv-reassembly-output-feature"), - .runs_before = VNET_FEATURES ("acl-plugin-out-ip4-fa"), -}; VNET_FEATURE_INIT (ip4_nat44_ed_in2out_output, static) = { .arc_name = "ip4-output", .node_name = "nat44-ed-in2out-output", @@ -178,7 +147,8 @@ VLIB_PLUGIN_REGISTER () = { .description = "Network Address Translation (NAT)", }; -static void nat44_ed_db_init (u32 translations, u32 translation_buckets); +static void nat44_ed_db_init (); +static void nat44_ed_db_free (); static void nat44_ed_worker_db_free (snat_main_per_thread_data_t *tsm); static int nat44_ed_add_static_mapping_internal ( @@ -193,28 +163,6 @@ static int nat44_ed_del_static_mapping_internal (ip4_address_t l_addr, u32 nat_calc_bihash_buckets (u32 n_elts); -u8 * -format_ed_session_kvp (u8 * s, va_list * args) -{ - clib_bihash_kv_16_8_t *v = va_arg (*args, clib_bihash_kv_16_8_t *); - - u8 proto; - u16 r_port, l_port; - ip4_address_t l_addr, r_addr; - u32 fib_index; - - split_ed_kv (v, &l_addr, &r_addr, &proto, &fib_index, &l_port, &r_port); - s = format (s, - "local %U:%d remote %U:%d proto %U fib %d thread-index %u " - "session-index %u", - format_ip4_address, &l_addr, clib_net_to_host_u16 (l_port), - format_ip4_address, &r_addr, clib_net_to_host_u16 (r_port), - format_ip_protocol, proto, fib_index, - ed_value_get_thread_index (v), ed_value_get_session_index (v)); - - return s; -} - static_always_inline int nat44_ed_sm_i2o_add (snat_main_t *sm, snat_static_mapping_t *m, ip4_address_t addr, u16 port, u32 fib_index, u8 proto) @@ -339,8 +287,7 @@ nat44_ed_resolve_nat_addr_len (snat_address_t *ap, { ap->addr_len = ia->address_length; ap->sw_if_index = i->sw_if_index; - ap->net.as_u32 = (ap->addr.as_u32 >> (32 - ap->addr_len)) - << (32 - ap->addr_len); + ap->net.as_u32 = ap->addr.as_u32 & ip4_main.fib_masks[ap->addr_len]; nat_log_debug ("pool addr %U binds to -> sw_if_idx: %u net: %U/%u", format_ip4_address, &ap->addr, ap->sw_if_index, @@ -387,8 +334,7 @@ nat44_ed_bind_if_addr_to_nat_addr (u32 sw_if_index) { ap->addr_len = ia->address_length; ap->sw_if_index = sw_if_index; - ap->net.as_u32 = (ap->addr.as_u32 >> (32 - ap->addr_len)) - << (32 - ap->addr_len); + ap->net.as_u32 = ap->addr.as_u32 & ip4_main.fib_masks[ap->addr_len]; nat_log_debug ("pool addr %U binds to -> sw_if_idx: %u net: %U/%u", format_ip4_address, &ap->addr, ap->sw_if_index, @@ -679,6 +625,134 @@ nat44_ed_del_address (ip4_address_t addr, u8 twice_nat) return 0; } +vrf_table_t * +nat44_ed_get_vrf_table (u32 table_vrf_id) +{ + snat_main_t *sm = &snat_main; + vrf_table_t *t; + + pool_foreach (t, sm->vrf_tables) + { + if (table_vrf_id == t->table_vrf_id) + { + return t; + } + } + return NULL; +} + +vrf_route_t * +nat44_ed_get_vrf_route (vrf_table_t *t, u32 vrf_id) +{ + vrf_route_t *r; + + pool_foreach (r, t->routes) + { + if (vrf_id == r->vrf_id) + { + return r; + } + } + return NULL; +} + +int +nat44_ed_add_del_vrf_table (u32 table_vrf_id, bool is_add) +{ + snat_main_t *sm = &snat_main; + vrf_table_t *t; + vrf_route_t *r; + + t = nat44_ed_get_vrf_table (table_vrf_id); + if (t) + { + if (is_add) + { + return VNET_API_ERROR_VALUE_EXIST; + } + pool_foreach (r, t->routes) + { + fib_table_unlock (r->fib_index, FIB_PROTOCOL_IP4, sm->fib_src_low); + } + fib_table_unlock (t->table_fib_index, FIB_PROTOCOL_IP4, sm->fib_src_low); + + pool_free (t->routes); + pool_put (sm->vrf_tables, t); + } + else + { + if (!is_add) + { + return VNET_API_ERROR_NO_SUCH_ENTRY; + } + pool_get (sm->vrf_tables, t); + clib_memset (t, 0, sizeof (*t)); + t->table_vrf_id = table_vrf_id; + t->table_fib_index = fib_table_find_or_create_and_lock ( + FIB_PROTOCOL_IP4, table_vrf_id, sm->fib_src_low); + } + + return 0; +} + +void +nat44_ed_del_vrf_tables () +{ + snat_main_t *sm = &snat_main; + vrf_table_t *t; + vrf_route_t *r; + + pool_foreach (t, sm->vrf_tables) + { + pool_foreach (r, t->routes) + { + fib_table_unlock (r->fib_index, FIB_PROTOCOL_IP4, sm->fib_src_low); + } + fib_table_unlock (t->table_fib_index, FIB_PROTOCOL_IP4, sm->fib_src_low); + pool_free (t->routes); + } + pool_free (sm->vrf_tables); +} + +int +nat44_ed_add_del_vrf_route (u32 table_vrf_id, u32 vrf_id, bool is_add) +{ + snat_main_t *sm = &snat_main; + vrf_table_t *t; + vrf_route_t *r; + + t = nat44_ed_get_vrf_table (table_vrf_id); + if (!t) + { + return VNET_API_ERROR_NO_SUCH_ENTRY; + } + + r = nat44_ed_get_vrf_route (t, vrf_id); + if (r) + { + if (is_add) + { + return VNET_API_ERROR_VALUE_EXIST; + } + fib_table_unlock (r->fib_index, FIB_PROTOCOL_IP4, sm->fib_src_low); + pool_put (t->routes, r); + } + else + { + if (!is_add) + { + return VNET_API_ERROR_NO_SUCH_ENTRY; + } + pool_get (t->routes, r); + clib_memset (r, 0, sizeof (*r)); + r->vrf_id = vrf_id; + r->fib_index = fib_table_find_or_create_and_lock ( + FIB_PROTOCOL_IP4, vrf_id, sm->fib_src_low); + } + + return 0; +} + u32 get_thread_idx_by_port (u16 e_port) { @@ -686,9 +760,9 @@ get_thread_idx_by_port (u16 e_port) u32 thread_idx = sm->num_workers; if (sm->num_workers > 1) { - thread_idx = - sm->first_worker_index + - sm->workers[(e_port - 1024) / sm->port_per_thread]; + thread_idx = sm->first_worker_index + + sm->workers[(e_port - ED_USER_PORT_OFFSET) / + sm->port_per_thread % _vec_len (sm->workers)]; } return thread_idx; } @@ -1278,9 +1352,10 @@ nat44_ed_add_lb_static_mapping (ip4_address_t e_addr, u16 e_port, FIB_PROTOCOL_IP4, locals[i].vrf_id, sm->fib_src_low); if (!is_sm_out2in_only (flags)) { - if (nat44_ed_sm_o2i_add (sm, m, e_addr, e_port, 0, proto)) + if (nat44_ed_sm_i2o_add (sm, m, locals[i].addr, locals[i].port, 0, + proto)) { - nat_log_err ("sm o2i key add failed"); + nat_log_err ("sm i2o key add failed"); rc = VNET_API_ERROR_UNSPECIFIED; // here we continue with add operation so that it can be safely // reversed in delete path - otherwise we'd have to track what @@ -1356,7 +1431,7 @@ nat44_ed_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, local->fib_index, m->proto)) { nat_log_err ("sm i2o key del failed"); - return VNET_API_ERROR_UNSPECIFIED; + // For the same reasons as above } } @@ -1560,19 +1635,19 @@ expire_per_vrf_sessions (u32 fib_index) vec_foreach (tsm, sm->per_thread_data) { - vec_foreach (per_vrf_sessions, tsm->per_vrf_sessions_vec) - { - if ((per_vrf_sessions->rx_fib_index == fib_index) || - (per_vrf_sessions->tx_fib_index == fib_index)) - { - per_vrf_sessions->expired = 1; - } - } + pool_foreach (per_vrf_sessions, tsm->per_vrf_sessions_pool) + { + if ((per_vrf_sessions->rx_fib_index == fib_index) || + (per_vrf_sessions->tx_fib_index == fib_index)) + { + per_vrf_sessions->expired = 1; + } + } } } void -update_per_vrf_sessions_vec (u32 fib_index, int is_del) +update_per_vrf_sessions_pool (u32 fib_index, int is_del) { snat_main_t *sm = &snat_main; nat_fib_t *fib; @@ -1608,10 +1683,10 @@ update_per_vrf_sessions_vec (u32 fib_index, int is_del) } } -static_always_inline nat_outside_fib_t * -nat44_ed_get_outside_fib (nat_outside_fib_t *outside_fibs, u32 fib_index) +static_always_inline nat_fib_t * +nat44_ed_get_outside_fib (nat_fib_t *outside_fibs, u32 fib_index) { - nat_outside_fib_t *f; + nat_fib_t *f; vec_foreach (f, outside_fibs) { if (f->fib_index == fib_index) @@ -1642,7 +1717,7 @@ nat44_ed_add_interface (u32 sw_if_index, u8 is_inside) const char *del_feature_name, *feature_name; snat_main_t *sm = &snat_main; - nat_outside_fib_t *outside_fib; + nat_fib_t *outside_fib; snat_interface_t *i; u32 fib_index; int rv; @@ -1715,7 +1790,7 @@ nat44_ed_add_interface (u32 sw_if_index, u8 is_inside) fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index); - update_per_vrf_sessions_vec (fib_index, 0 /*is_del*/); + update_per_vrf_sessions_pool (fib_index, 0 /*is_del*/); if (!is_inside) { @@ -1724,13 +1799,13 @@ nat44_ed_add_interface (u32 sw_if_index, u8 is_inside) outside_fib = nat44_ed_get_outside_fib (sm->outside_fibs, fib_index); if (outside_fib) { - outside_fib->refcount++; + outside_fib->ref_count++; } else { vec_add2 (sm->outside_fibs, outside_fib, 1); outside_fib->fib_index = fib_index; - outside_fib->refcount = 1; + outside_fib->ref_count = 1; } nat44_ed_add_del_nat_addr_fib_reg_entries (sw_if_index, 1); @@ -1752,7 +1827,7 @@ nat44_ed_del_interface (u32 sw_if_index, u8 is_inside) const char *del_feature_name, *feature_name; snat_main_t *sm = &snat_main; - nat_outside_fib_t *outside_fib; + nat_fib_t *outside_fib; snat_interface_t *i; u32 fib_index; int rv; @@ -1830,15 +1905,15 @@ nat44_ed_del_interface (u32 sw_if_index, u8 is_inside) fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index); - update_per_vrf_sessions_vec (fib_index, 1 /*is_del*/); + update_per_vrf_sessions_pool (fib_index, 1 /*is_del*/); if (!is_inside) { outside_fib = nat44_ed_get_outside_fib (sm->outside_fibs, fib_index); if (outside_fib) { - outside_fib->refcount--; - if (!outside_fib->refcount) + outside_fib->ref_count--; + if (!outside_fib->ref_count) { vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs); } @@ -1856,7 +1931,7 @@ nat44_ed_add_output_interface (u32 sw_if_index) { snat_main_t *sm = &snat_main; - nat_outside_fib_t *outside_fib; + nat_fib_t *outside_fib; snat_interface_t *i; u32 fib_index; int rv; @@ -1929,18 +2004,18 @@ nat44_ed_add_output_interface (u32 sw_if_index) fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index); - update_per_vrf_sessions_vec (fib_index, 0 /*is_del*/); + update_per_vrf_sessions_pool (fib_index, 0 /*is_del*/); outside_fib = nat44_ed_get_outside_fib (sm->outside_fibs, fib_index); if (outside_fib) { - outside_fib->refcount++; + outside_fib->ref_count++; } else { vec_add2 (sm->outside_fibs, outside_fib, 1); outside_fib->fib_index = fib_index; - outside_fib->refcount = 1; + outside_fib->ref_count = 1; } nat44_ed_add_del_nat_addr_fib_reg_entries (sw_if_index, 1); @@ -1956,7 +2031,7 @@ nat44_ed_del_output_interface (u32 sw_if_index) { snat_main_t *sm = &snat_main; - nat_outside_fib_t *outside_fib; + nat_fib_t *outside_fib; snat_interface_t *i; u32 fib_index; int rv; @@ -2019,13 +2094,13 @@ nat44_ed_del_output_interface (u32 sw_if_index) fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index); - update_per_vrf_sessions_vec (fib_index, 1 /*is_del*/); + update_per_vrf_sessions_pool (fib_index, 1 /*is_del*/); outside_fib = nat44_ed_get_outside_fib (sm->outside_fibs, fib_index); if (outside_fib) { - outside_fib->refcount--; - if (!outside_fib->refcount) + outside_fib->ref_count--; + if (!outside_fib->ref_count) { vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs); } @@ -2058,7 +2133,7 @@ snat_set_workers (uword * bitmap) j++; } - sm->port_per_thread = (0xffff - 1024) / _vec_len (sm->workers); + sm->port_per_thread = (65536 - ED_USER_PORT_OFFSET) / _vec_len (sm->workers); return 0; } @@ -2068,6 +2143,18 @@ nat44_ed_set_frame_queue_nelts (u32 frame_queue_nelts) { fail_if_enabled (); snat_main_t *sm = &snat_main; + + if ((sm->fq_in2out_index != ~0) || (sm->fq_out2in_index != ~0) || + (sm->fq_in2out_output_index != ~0)) + { + // frame queu nelts can be set only before first + // call to nat44_plugin_enable after that it + // doesn't make sense + nat_log_err ("Frame queue was already initialized. " + "Change is not possible"); + return 1; + } + sm->frame_queue_nelts = frame_queue_nelts; return 0; } @@ -2077,7 +2164,7 @@ nat44_ed_update_outside_fib_cb (ip4_main_t *im, uword opaque, u32 sw_if_index, u32 new_fib_index, u32 old_fib_index) { snat_main_t *sm = &snat_main; - nat_outside_fib_t *outside_fib; + nat_fib_t *outside_fib; snat_interface_t *i; u8 is_add = 1; u8 match = 0; @@ -2115,8 +2202,8 @@ nat44_ed_update_outside_fib_cb (ip4_main_t *im, uword opaque, u32 sw_if_index, { if (outside_fib->fib_index == old_fib_index) { - outside_fib->refcount--; - if (!outside_fib->refcount) + outside_fib->ref_count--; + if (!outside_fib->ref_count) vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs); break; } @@ -2126,7 +2213,7 @@ nat44_ed_update_outside_fib_cb (ip4_main_t *im, uword opaque, u32 sw_if_index, { if (outside_fib->fib_index == new_fib_index) { - outside_fib->refcount++; + outside_fib->ref_count++; is_add = 0; break; } @@ -2135,7 +2222,7 @@ nat44_ed_update_outside_fib_cb (ip4_main_t *im, uword opaque, u32 sw_if_index, if (is_add) { vec_add2 (sm->outside_fibs, outside_fib, 1); - outside_fib->refcount = 1; + outside_fib->ref_count = 1; outside_fib->fib_index = new_fib_index; } } @@ -2211,21 +2298,6 @@ nat_ip_table_add_del (vnet_main_t * vnm, u32 table_id, u32 is_add) VNET_IP_TABLE_ADD_DEL_FUNCTION (nat_ip_table_add_del); -void -nat44_set_node_indexes (snat_main_t * sm, vlib_main_t * vm) -{ - vlib_node_t *node; - - node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-out2in"); - sm->out2in_node_index = node->index; - - node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out"); - sm->in2out_node_index = node->index; - - node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out-output"); - sm->in2out_output_node_index = node->index; -} - #define nat_validate_simple_counter(c, i) \ do \ { \ @@ -2269,12 +2341,8 @@ nat_init (vlib_main_t * vm) clib_memset (sm, 0, sizeof (*sm)); - // required - sm->vnet_main = vnet_get_main (); // convenience sm->ip4_main = &ip4_main; - sm->api_main = vlibapi_get_main (); - sm->ip4_lookup_main = &ip4_main.lookup_main; // frame queue indices used for handoff sm->fq_out2in_index = ~0; @@ -2283,15 +2351,13 @@ nat_init (vlib_main_t * vm) sm->log_level = NAT_LOG_ERROR; - nat44_set_node_indexes (sm, vm); - sm->log_class = vlib_log_register_class ("nat", 0); nat_ipfix_logging_init (vm); nat_init_simple_counter (sm->total_sessions, "total-sessions", "/nat44-ed/total-sessions"); - sm->max_cfg_sessions_gauge = stat_segment_new_entry ( - (u8 *) "/nat44-ed/max-cfg-sessions", STAT_DIR_TYPE_SCALAR_INDEX); + sm->max_cfg_sessions_gauge = + vlib_stats_add_gauge ("/nat44-ed/max-cfg-sessions"); #define _(x) \ nat_init_simple_counter (sm->counters.fastpath.in2out.x, #x, \ @@ -2318,7 +2384,7 @@ nat_init (vlib_main_t * vm) } } num_threads = tm->n_vlib_mains - 1; - sm->port_per_thread = 0xffff - 1024; + sm->port_per_thread = 65536 - ED_USER_PORT_OFFSET; vec_validate (sm->per_thread_data, num_threads); /* Use all available workers by default */ @@ -2373,8 +2439,8 @@ nat44_plugin_enable (nat44_config_t c) c.sessions = 63 * 1024; sm->max_translations_per_thread = c.sessions; - stat_segment_set_state_counter (sm->max_cfg_sessions_gauge, - sm->max_translations_per_thread); + vlib_stats_set_gauge (sm->max_cfg_sessions_gauge, + sm->max_translations_per_thread); sm->translation_buckets = nat_calc_bihash_buckets (c.sessions); vec_add1 (sm->max_translations_per_fib, sm->max_translations_per_thread); @@ -2388,9 +2454,7 @@ nat44_plugin_enable (nat44_config_t c) sm->outside_fib_index = fib_table_find_or_create_and_lock ( FIB_PROTOCOL_IP4, c.outside_vrf, sm->fib_src_hi); - nat44_ed_db_init (sm->max_translations_per_thread, sm->translation_buckets); - - nat44_ed_init_tcp_state_stable (sm); + nat44_ed_db_init (); nat_affinity_enable (); @@ -2405,20 +2469,26 @@ nat44_plugin_enable (nat44_config_t c) if (sm->num_workers > 1) { + vlib_main_t *vm = vlib_get_main (); + vlib_node_t *node; + if (sm->fq_in2out_index == ~0) { - sm->fq_in2out_index = vlib_frame_queue_main_init ( - sm->in2out_node_index, sm->frame_queue_nelts); + node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out"); + sm->fq_in2out_index = + vlib_frame_queue_main_init (node->index, sm->frame_queue_nelts); } if (sm->fq_out2in_index == ~0) { - sm->fq_out2in_index = vlib_frame_queue_main_init ( - sm->out2in_node_index, sm->frame_queue_nelts); + node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-out2in"); + sm->fq_out2in_index = + vlib_frame_queue_main_init (node->index, sm->frame_queue_nelts); } if (sm->fq_in2out_output_index == ~0) { - sm->fq_in2out_output_index = vlib_frame_queue_main_init ( - sm->in2out_output_node_index, sm->frame_queue_nelts); + node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out-output"); + sm->fq_in2out_output_index = + vlib_frame_queue_main_init (node->index, sm->frame_queue_nelts); } } @@ -2519,6 +2589,55 @@ nat44_ed_del_output_interfaces () return error; } +static clib_error_t * +nat44_ed_sw_interface_add_del (vnet_main_t *vnm, u32 sw_if_index, u32 is_add) +{ + snat_main_t *sm = &snat_main; + snat_interface_t *i; + int error = 0; + + if (is_add) + return 0; + + if (!sm->enabled) + return 0; + + i = nat44_ed_get_interface (sm->interfaces, sw_if_index); + if (i) + { + bool is_inside = nat44_ed_is_interface_inside (i); + bool is_outside = nat44_ed_is_interface_outside (i); + + if (is_inside) + { + error |= nat44_ed_del_interface (sw_if_index, 1); + } + if (is_outside) + { + error |= nat44_ed_del_interface (sw_if_index, 0); + } + + if (error) + { + nat_log_err ("error occurred while removing interface"); + } + } + + i = nat44_ed_get_interface (sm->output_feature_interfaces, sw_if_index); + if (i) + { + error = nat44_ed_del_output_interface (sw_if_index); + if (error) + { + nat_log_err ("error occurred while removing output interface"); + } + } + + return 0; +} + +VNET_SW_INTERFACE_ADD_DEL_FUNCTION (nat44_ed_sw_interface_add_del); + int nat44_ed_del_static_mappings () { @@ -2550,7 +2669,6 @@ nat44_ed_del_static_mappings () int nat44_plugin_disable () { - snat_main_per_thread_data_t *tsm; snat_main_t *sm = &snat_main; int rc, error = 0; @@ -2558,32 +2676,31 @@ nat44_plugin_disable () rc = nat44_ed_del_static_mappings (); if (rc) - error = 1; + error = VNET_API_ERROR_BUG; rc = nat44_ed_del_addresses (); if (rc) - error = 1; + error = VNET_API_ERROR_BUG; rc = nat44_ed_del_interfaces (); if (rc) - error = 1; + error = VNET_API_ERROR_BUG; rc = nat44_ed_del_output_interfaces (); if (rc) - error = 1; + error = VNET_API_ERROR_BUG; + + nat44_ed_del_vrf_tables (); vec_free (sm->max_translations_per_fib); sm->max_translations_per_fib = 0; - clib_bihash_free_16_8 (&sm->flow_hash); - - vec_foreach (tsm, sm->per_thread_data) - { - nat44_ed_worker_db_free (tsm); - } + nat44_ed_db_free (); clib_memset (&sm->rconfig, 0, sizeof (sm->rconfig)); + nat_affinity_disable (); + sm->forwarding_enabled = 0; sm->enabled = 0; @@ -2639,11 +2756,12 @@ nat44_ed_sm_match (snat_main_t *sm, ip4_address_t match_addr, u16 match_port, if (m) return m; - /* Try address only mapping */ + // try address only mapping m = nat44_ed_sm_i2o_lookup (sm, match_addr, 0, match_fib_index, 0); if (m) return m; + // default static mapping fib index (based on configuration) if (sm->inside_fib_index != match_fib_index) { m = nat44_ed_sm_i2o_lookup (sm, match_addr, match_port, @@ -2651,12 +2769,13 @@ nat44_ed_sm_match (snat_main_t *sm, ip4_address_t match_addr, u16 match_port, if (m) return m; - /* Try address only mapping */ + // try address only mapping m = nat44_ed_sm_i2o_lookup (sm, match_addr, 0, sm->inside_fib_index, 0); if (m) return m; } + // TODO: this specific use case may be deprecated (needs testing) if (sm->outside_fib_index != match_fib_index) { m = nat44_ed_sm_i2o_lookup (sm, match_addr, match_port, @@ -2664,7 +2783,7 @@ nat44_ed_sm_match (snat_main_t *sm, ip4_address_t match_addr, u16 match_port, if (m) return m; - /* Try address only mapping */ + // try address only mapping m = nat44_ed_sm_i2o_lookup (sm, match_addr, 0, sm->outside_fib_index, 0); if (m) @@ -2678,7 +2797,7 @@ nat44_ed_sm_match (snat_main_t *sm, ip4_address_t match_addr, u16 match_port, if (m) return m; - /* Try address only mapping */ + // try address only mapping m = nat44_ed_sm_o2i_lookup (sm, match_addr, 0, 0, 0); if (m) return m; @@ -2687,15 +2806,16 @@ nat44_ed_sm_match (snat_main_t *sm, ip4_address_t match_addr, u16 match_port, } int -snat_static_mapping_match (vlib_main_t *vm, snat_main_t *sm, - ip4_address_t match_addr, u16 match_port, - u32 match_fib_index, ip_protocol_t match_protocol, +snat_static_mapping_match (vlib_main_t *vm, ip4_address_t match_addr, + u16 match_port, u32 match_fib_index, + ip_protocol_t match_protocol, ip4_address_t *mapping_addr, u16 *mapping_port, u32 *mapping_fib_index, int by_external, u8 *is_addr_only, twice_nat_type_t *twice_nat, lb_nat_type_t *lb, ip4_address_t *ext_host_addr, u8 *is_identity_nat, snat_static_mapping_t **out) { + snat_main_t *sm = &snat_main; snat_static_mapping_t *m; u32 rand, lo = 0, hi, mid, *tmp = 0, i; nat44_lb_addr_port_t *local; @@ -2839,7 +2959,7 @@ nat44_ed_get_in2out_worker_index (vlib_buffer_t *b, ip4_header_t *ip, if (PREDICT_FALSE (is_output)) { fib_index = sm->outside_fib_index; - nat_outside_fib_t *outside_fib; + nat_fib_t *outside_fib; fib_node_index_t fei = FIB_NODE_INDEX_INVALID; fib_prefix_t pfx = { .fp_proto = FIB_PROTOCOL_IP4, @@ -2925,7 +3045,9 @@ nat44_ed_get_in2out_worker_index (vlib_buffer_t *b, ip4_header_t *ip, } hash = ip->src_address.as_u32 + (ip->src_address.as_u32 >> 8) + - (ip->src_address.as_u32 >> 16) + (ip->src_address.as_u32 >> 24); + (ip->src_address.as_u32 >> 16) + (ip->src_address.as_u32 >> 24) + + rx_fib_index + (rx_fib_index >> 8) + (rx_fib_index >> 16) + + (rx_fib_index >> 24); if (PREDICT_TRUE (is_pow2 (_vec_len (sm->workers)))) next_worker_index += sm->workers[hash & (_vec_len (sm->workers) - 1)]; @@ -3035,7 +3157,7 @@ nat44_ed_get_out2in_worker_index (vlib_buffer_t *b, ip4_header_t *ip, { udp_header_t *udp = ip4_next_header (ip); icmp46_header_t *icmp = (icmp46_header_t *) udp; - icmp_echo_header_t *echo = (icmp_echo_header_t *) (icmp + 1); + nat_icmp_echo_header_t *echo = (nat_icmp_echo_header_t *) (icmp + 1); if (!icmp_type_is_error_message (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags)) port = vnet_buffer (b)->ip.reass.l4_src_port; @@ -3049,13 +3171,13 @@ nat44_ed_get_out2in_worker_index (vlib_buffer_t *b, ip4_header_t *ip, { case IP_PROTOCOL_ICMP: icmp = (icmp46_header_t *) l4_header; - echo = (icmp_echo_header_t *) (icmp + 1); + echo = (nat_icmp_echo_header_t *) (icmp + 1); port = echo->identifier; break; case IP_PROTOCOL_UDP: /* breakthrough */ case IP_PROTOCOL_TCP: - port = ((tcp_udp_header_t *) l4_header)->src_port; + port = ((nat_tcp_udp_header_t *) l4_header)->src_port; break; default: next_worker_index = vlib_get_thread_index (); @@ -3089,9 +3211,7 @@ nat44_ed_get_out2in_worker_index (vlib_buffer_t *b, ip4_header_t *ip, } /* worker by outside port */ - next_worker_index = sm->first_worker_index; - next_worker_index += - sm->workers[(clib_net_to_host_u16 (port) - 1024) / sm->port_per_thread]; + next_worker_index = get_thread_idx_by_port (clib_net_to_host_u16 (port)); done: nat_elog_debug_handoff (sm, "HANDOFF OUT2IN", next_worker_index, @@ -3120,16 +3240,12 @@ nat44_set_session_limit (u32 session_limit, u32 vrf_id) { snat_main_t *sm = &snat_main; u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id); - u32 len = vec_len (sm->max_translations_per_fib); - if (len <= fib_index) - { - vec_validate (sm->max_translations_per_fib, fib_index + 1); - - for (; len < vec_len (sm->max_translations_per_fib); len++) - sm->max_translations_per_fib[len] = sm->max_translations_per_thread; - } + if (~0 == fib_index) + return -1; + vec_validate_init_empty (sm->max_translations_per_fib, fib_index, + sm->max_translations_per_thread); sm->max_translations_per_fib[fib_index] = session_limit; return 0; } @@ -3143,8 +3259,8 @@ nat44_update_session_limit (u32 session_limit, u32 vrf_id) return 1; sm->max_translations_per_thread = nat44_get_max_session_limit (); - stat_segment_set_state_counter (sm->max_cfg_sessions_gauge, - sm->max_translations_per_thread); + vlib_stats_set_gauge (sm->max_cfg_sessions_gauge, + sm->max_translations_per_thread); sm->translation_buckets = nat_calc_bihash_buckets (sm->max_translations_per_thread); @@ -3154,11 +3270,11 @@ nat44_update_session_limit (u32 session_limit, u32 vrf_id) } static void -nat44_ed_worker_db_init (snat_main_per_thread_data_t *tsm, u32 translations, - u32 translation_buckets) +nat44_ed_worker_db_init (snat_main_per_thread_data_t *tsm, u32 translations) { dlist_elt_t *head; + pool_alloc (tsm->per_vrf_sessions_pool, translations); pool_alloc (tsm->sessions, translations); pool_alloc (tsm->lru_pool, translations); @@ -3184,7 +3300,7 @@ nat44_ed_worker_db_init (snat_main_per_thread_data_t *tsm, u32 translations, } static void -reinit_ed_flow_hash () +nat44_ed_flow_hash_init () { snat_main_t *sm = &snat_main; // we expect 2 flows per session, so multiply translation_buckets by 2 @@ -3195,17 +3311,16 @@ reinit_ed_flow_hash () } static void -nat44_ed_db_init (u32 translations, u32 translation_buckets) +nat44_ed_db_init () { snat_main_t *sm = &snat_main; snat_main_per_thread_data_t *tsm; - reinit_ed_flow_hash (); + nat44_ed_flow_hash_init (); vec_foreach (tsm, sm->per_thread_data) { - nat44_ed_worker_db_init (tsm, sm->max_translations_per_thread, - sm->translation_buckets); + nat44_ed_worker_db_init (tsm, sm->max_translations_per_thread); } } @@ -3214,23 +3329,38 @@ nat44_ed_worker_db_free (snat_main_per_thread_data_t *tsm) { pool_free (tsm->lru_pool); pool_free (tsm->sessions); - vec_free (tsm->per_vrf_sessions_vec); + pool_free (tsm->per_vrf_sessions_pool); } -void -nat44_ed_sessions_clear () +static void +nat44_ed_flow_hash_free () { snat_main_t *sm = &snat_main; - snat_main_per_thread_data_t *tsm; - reinit_ed_flow_hash (); + clib_bihash_free_16_8 (&sm->flow_hash); +} + +static void +nat44_ed_db_free () +{ + snat_main_t *sm = &snat_main; + snat_main_per_thread_data_t *tsm; vec_foreach (tsm, sm->per_thread_data) { nat44_ed_worker_db_free (tsm); - nat44_ed_worker_db_init (tsm, sm->max_translations_per_thread, - sm->translation_buckets); } + + nat44_ed_flow_hash_free (); +} + +void +nat44_ed_sessions_clear () +{ + snat_main_t *sm = &snat_main; + + nat44_ed_db_free (); + nat44_ed_db_init (); vlib_zero_simple_counter (&sm->total_sessions, 0); } @@ -3359,8 +3489,8 @@ nat44_ed_add_del_interface_address_cb (ip4_main_t *im, uword opaque, { ap->addr_len = address_length; ap->sw_if_index = sw_if_index; - ap->net.as_u32 = (ap->addr.as_u32 >> (32 - ap->addr_len)) - << (32 - ap->addr_len); + ap->net.as_u32 = + ap->addr.as_u32 & ip4_main.fib_masks[ap->addr_len]; nat_log_debug ( "pool addr %U binds to -> sw_if_idx: %u net: %U/%u", @@ -3419,6 +3549,7 @@ nat44_ed_add_interface_address (u32 sw_if_index, u8 twice_nat) if (!sm->enabled) { + nat_log_err ("nat44 is disabled"); return VNET_API_ERROR_UNSUPPORTED; } @@ -3456,6 +3587,7 @@ nat44_ed_del_interface_address (u32 sw_if_index, u8 twice_nat) if (!sm->enabled) { + nat_log_err ("nat44 is disabled"); return VNET_API_ERROR_UNSUPPORTED; } @@ -3703,7 +3835,7 @@ nat_6t_flow_icmp_translate (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, return NAT_ED_TRNSL_ERR_TRANSLATION_FAILED; icmp46_header_t *icmp = ip4_next_header (ip); - icmp_echo_header_t *echo = (icmp_echo_header_t *) (icmp + 1); + nat_icmp_echo_header_t *echo = (nat_icmp_echo_header_t *) (icmp + 1); if ((!vnet_buffer (b)->ip.reass.is_non_first_fragment)) { @@ -3719,7 +3851,7 @@ nat_6t_flow_icmp_translate (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, { ip_csum_t sum = icmp->checksum; sum = ip_csum_update (sum, echo->identifier, f->rewrite.icmp_id, - icmp_echo_header_t, + nat_icmp_echo_header_t, identifier /* changed member */); echo->identifier = f->rewrite.icmp_id; icmp->checksum = ip_csum_fold (sum); @@ -3799,6 +3931,9 @@ nat_6t_flow_icmp_translate (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, icmp->checksum = new_icmp_sum; break; case IP_PROTOCOL_ICMP: + nat_6t_flow_ip4_translate (sm, b, inner_ip, f, inner_proto, + 1 /* is_icmp_inner_ip4 */, + 0 /* skip_saddr_rewrite */); if (f->ops & NAT_FLOW_OP_ICMP_ID_REWRITE) { icmp46_header_t *inner_icmp = ip4_next_header (inner_ip); @@ -3806,19 +3941,21 @@ nat_6t_flow_icmp_translate (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, { return NAT_ED_TRNSL_ERR_PACKET_TRUNCATED; } - icmp_echo_header_t *inner_echo = - (icmp_echo_header_t *) (inner_icmp + 1); + nat_icmp_echo_header_t *inner_echo = + (nat_icmp_echo_header_t *) (inner_icmp + 1); if (f->rewrite.icmp_id != inner_echo->identifier) { ip_csum_t sum = icmp->checksum; - sum = ip_csum_update ( - sum, inner_echo->identifier, f->rewrite.icmp_id, - icmp_echo_header_t, identifier /* changed member */); + sum = ip_csum_update (sum, inner_echo->identifier, + f->rewrite.icmp_id, + nat_icmp_echo_header_t, + identifier /* changed member */); icmp->checksum = ip_csum_fold (sum); ip_csum_t inner_sum = inner_icmp->checksum; inner_sum = ip_csum_update ( sum, inner_echo->identifier, f->rewrite.icmp_id, - icmp_echo_header_t, identifier /* changed member */); + nat_icmp_echo_header_t, + identifier /* changed member */); inner_icmp->checksum = ip_csum_fold (inner_sum); inner_echo->identifier = f->rewrite.icmp_id; } @@ -3890,110 +4027,7 @@ nat_6t_flow_buf_translate_o2i (vlib_main_t *vm, snat_main_t *sm, 0 /* is_i2o */); } -u8 * -format_nat_6t (u8 *s, va_list *args) -{ - nat_6t_t *t = va_arg (*args, nat_6t_t *); - - s = format (s, "saddr %U sport %u daddr %U dport %u proto %U fib_idx %u", - format_ip4_address, t->saddr.as_u8, - clib_net_to_host_u16 (t->sport), format_ip4_address, - t->daddr.as_u8, clib_net_to_host_u16 (t->dport), - format_ip_protocol, t->proto, t->fib_index); - return s; -} - -u8 * -format_nat_ed_translation_error (u8 *s, va_list *args) -{ - nat_translation_error_e e = va_arg (*args, nat_translation_error_e); - - switch (e) - { - case NAT_ED_TRNSL_ERR_SUCCESS: - s = format (s, "success"); - break; - case NAT_ED_TRNSL_ERR_TRANSLATION_FAILED: - s = format (s, "translation-failed"); - break; - case NAT_ED_TRNSL_ERR_FLOW_MISMATCH: - s = format (s, "flow-mismatch"); - break; - case NAT_ED_TRNSL_ERR_PACKET_TRUNCATED: - s = format (s, "packet-truncated"); - break; - case NAT_ED_TRNSL_ERR_INNER_IP_CORRUPT: - s = format (s, "inner-ip-corrupted"); - break; - case NAT_ED_TRNSL_ERR_INVALID_CSUM: - s = format (s, "invalid-checksum"); - break; - } - return s; -} - -u8 * -format_nat_6t_flow (u8 *s, va_list *args) -{ - nat_6t_flow_t *f = va_arg (*args, nat_6t_flow_t *); - - s = format (s, "match: %U ", format_nat_6t, &f->match); - int r = 0; - if (f->ops & NAT_FLOW_OP_SADDR_REWRITE) - { - s = format (s, "rewrite: saddr %U ", format_ip4_address, - f->rewrite.saddr.as_u8); - r = 1; - } - if (f->ops & NAT_FLOW_OP_SPORT_REWRITE) - { - if (!r) - { - s = format (s, "rewrite: "); - r = 1; - } - s = format (s, "sport %u ", clib_net_to_host_u16 (f->rewrite.sport)); - } - if (f->ops & NAT_FLOW_OP_DADDR_REWRITE) - { - if (!r) - { - s = format (s, "rewrite: "); - r = 1; - } - s = format (s, "daddr %U ", format_ip4_address, f->rewrite.daddr.as_u8); - } - if (f->ops & NAT_FLOW_OP_DPORT_REWRITE) - { - if (!r) - { - s = format (s, "rewrite: "); - r = 1; - } - s = format (s, "dport %u ", clib_net_to_host_u16 (f->rewrite.dport)); - } - if (f->ops & NAT_FLOW_OP_ICMP_ID_REWRITE) - { - if (!r) - { - s = format (s, "rewrite: "); - r = 1; - } - s = format (s, "icmp-id %u ", clib_net_to_host_u16 (f->rewrite.icmp_id)); - } - if (f->ops & NAT_FLOW_OP_TXFIB_REWRITE) - { - if (!r) - { - s = format (s, "rewrite: "); - r = 1; - } - s = format (s, "txfib %u ", f->rewrite.fib_index); - } - return s; -} - -static inline void +static_always_inline void nat_syslog_nat44_sess (u32 ssubix, u32 sfibix, ip4_address_t *isaddr, u16 isport, ip4_address_t *xsaddr, u16 xsport, ip4_address_t *idaddr, u16 idport, @@ -4067,52 +4101,49 @@ nat_syslog_nat44_sdel (u32 ssubix, u32 sfibix, ip4_address_t *isaddr, idaddr, idport, xdaddr, xdport, proto, 0, is_twicenat); } - -u8 * -format_nat44_ed_tcp_state (u8 *s, va_list *args) +__clib_export void +nat44_original_dst_lookup (ip4_address_t *i2o_src, u16 i2o_src_port, + ip4_address_t *i2o_dst, u16 i2o_dst_port, + ip_protocol_t proto, u32 *original_dst, + u16 *original_dst_port) { - nat44_ed_tcp_state_e e = va_arg (*args, nat44_ed_tcp_state_e); - switch (e) + snat_main_per_thread_data_t *tsm; + snat_main_t *sm = &snat_main; + u32 fib_index = 0; + snat_session_t *s; + ip4_header_t ip; + + ip.src_address.as_u32 = i2o_src->as_u32; + fib_index = fib_table_find (FIB_PROTOCOL_IP4, 0); + + if (sm->num_workers > 1) { - case NAT44_ED_TCP_STATE_CLOSED: - s = format (s, "closed"); - break; - case NAT44_ED_TCP_STATE_SYN_I2O: - s = format (s, "SYN seen in in2out direction"); - break; - case NAT44_ED_TCP_STATE_SYN_O2I: - s = format (s, "SYN seen in out2in direction"); - break; - case NAT44_ED_TCP_STATE_ESTABLISHED: - s = format (s, "SYN seen in both directions/established"); - break; - case NAT44_ED_TCP_STATE_FIN_I2O: - s = format (s, "FIN seen in in2out direction"); - break; - case NAT44_ED_TCP_STATE_FIN_O2I: - s = format (s, "FIN seen in out2in direction"); - break; - case NAT44_ED_TCP_STATE_RST_TRANS: - s = format (s, "RST seen/transitory timeout"); - break; - case NAT44_ED_TCP_STATE_FIN_TRANS: - s = format (s, "FIN seen in both directions/transitory timeout"); - break; - case NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_O2I: - s = format (s, "FIN seen in both directions/transitory timeout/session " - "reopening in out2in direction"); - break; - case NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_I2O: - s = format (s, "FIN seen in both directions/transitory timeout/session " - "reopening in in2out direction"); - break; - case NAT44_ED_TCP_N_STATE: - s = format (s, "BUG! unexpected N_STATE! BUG!"); - break; + tsm = vec_elt_at_index ( + sm->per_thread_data, + nat44_ed_get_in2out_worker_index (0, &ip, fib_index, 0)); + } + else + { + tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers); } - return s; -} + /* query */ + clib_bihash_kv_16_8_t kv = { 0 }, value; + init_ed_k (&kv, i2o_src->as_u32, i2o_src_port, i2o_dst->as_u32, i2o_dst_port, + fib_index, proto); + if (tsm->sessions == NULL || + clib_bihash_search_16_8 (&sm->flow_hash, &kv, &value)) + { + return; + } + s = pool_elt_at_index (tsm->sessions, ed_value_get_session_index (&value)); + if (s) + { + *original_dst = s->i2o.rewrite.saddr.as_u32; + *original_dst_port = s->i2o.rewrite.sport; + } + return; +} /* * fd.io coding-style-patch-verification: ON *