X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fnat%2Fnat44-ed%2Fnat44_ed.c;h=3b1c9a2c89f0866864d65c169ee8f533d19bda18;hb=691c630b79ec2230b67944c8a9f77f95b49d95ad;hp=7907d8ffa6bdb1f9de3f8838765dc89978b617df;hpb=aed42948510a94922566fa1a4bfb6eec281e5dee;p=vpp.git diff --git a/src/plugins/nat/nat44-ed/nat44_ed.c b/src/plugins/nat/nat44-ed/nat44_ed.c index 7907d8ffa6b..3b1c9a2c89f 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; @@ -78,7 +76,6 @@ static_always_inline void nat_validate_interface_counters (snat_main_t *sm, } \ 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", @@ -185,34 +154,14 @@ static int nat44_ed_add_static_mapping_internal ( ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, ip_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags, ip4_address_t pool_addr, u8 *tag); -static int nat44_ed_del_static_mapping_internal ( - ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, - ip_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags); +static int nat44_ed_del_static_mapping_internal (ip4_address_t l_addr, + ip4_address_t e_addr, + u16 l_port, u16 e_port, + ip_protocol_t proto, + u32 vrf_id, u32 flags); 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) @@ -290,25 +239,6 @@ nat44_ed_free_session_data (snat_main_t *sm, snat_session_t *s, } } -static int -is_snat_address_used_in_static_mapping (snat_main_t *sm, ip4_address_t addr) -{ - snat_static_mapping_t *m; - pool_foreach (m, sm->static_mappings) - { - if (is_sm_addr_only (m->flags) || is_sm_out2in_only (m->flags) || - is_sm_identity_nat (m->flags)) - { - continue; - } - if (m->external_addr.as_u32 == addr.as_u32) - { - return 1; - } - } - return 0; -} - static ip_interface_address_t * nat44_ed_get_ip_interface_address (u32 sw_if_index, ip4_address_t addr) { @@ -415,41 +345,91 @@ nat44_ed_bind_if_addr_to_nat_addr (u32 sw_if_index) } } +static_always_inline snat_fib_entry_reg_t * +nat44_ed_get_fib_entry_reg (ip4_address_t addr, u32 sw_if_index, int *out_idx) +{ + snat_main_t *sm = &snat_main; + snat_fib_entry_reg_t *fe; + int i; + + for (i = 0; i < vec_len (sm->fib_entry_reg); i++) + { + fe = sm->fib_entry_reg + i; + if ((addr.as_u32 == fe->addr.as_u32) && (sw_if_index == fe->sw_if_index)) + { + if (out_idx) + { + *out_idx = i; + } + return fe; + } + } + return NULL; +} + static void -nat44_ed_add_del_addr_to_fib (ip4_address_t *addr, u8 p_len, u32 sw_if_index, - int is_add) +nat44_ed_add_fib_entry_reg (ip4_address_t addr, u32 sw_if_index) { // Add the external NAT address to the FIB as receive entries. This ensures // that VPP will reply to ARP for this address and we don't need to enable // proxy ARP on the outside interface. - snat_main_t *sm = &snat_main; - fib_prefix_t prefix = { - .fp_len = p_len, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4.as_u32 = addr->as_u32, - }, - }; - u32 fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index); + snat_fib_entry_reg_t *fe; - if (is_add) + if (!(fe = nat44_ed_get_fib_entry_reg (addr, sw_if_index, 0))) { + fib_prefix_t prefix = { + .fp_len = 32, + .fp_proto = FIB_PROTOCOL_IP4, + .fp_addr = { + .ip4.as_u32 = addr.as_u32, + }, + }; + u32 fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index); fib_table_entry_update_one_path (fib_index, &prefix, sm->fib_src_low, (FIB_ENTRY_FLAG_CONNECTED | FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_EXCLUSIVE), DPO_PROTO_IP4, NULL, sw_if_index, ~0, 1, NULL, FIB_ROUTE_PATH_FLAG_NONE); + + vec_add2 (sm->fib_entry_reg, fe, 1); + clib_memset (fe, 0, sizeof (*fe)); + fe->addr.as_u32 = addr.as_u32; + fe->sw_if_index = sw_if_index; } - else + fe->count++; +} + +static void +nat44_ed_del_fib_entry_reg (ip4_address_t addr, u32 sw_if_index) +{ + snat_main_t *sm = &snat_main; + snat_fib_entry_reg_t *fe; + int i; + + if ((fe = nat44_ed_get_fib_entry_reg (addr, sw_if_index, &i))) { - fib_table_entry_delete (fib_index, &prefix, sm->fib_src_low); + fe->count--; + if (0 == fe->count) + { + fib_prefix_t prefix = { + .fp_len = 32, + .fp_proto = FIB_PROTOCOL_IP4, + .fp_addr = { + .ip4.as_u32 = addr.as_u32, + }, + }; + u32 fib_index = + ip4_fib_table_get_index_for_sw_if_index (sw_if_index); + fib_table_entry_delete (fib_index, &prefix, sm->fib_src_low); + vec_del1 (sm->fib_entry_reg, i); + } } } static void -nat44_ed_add_del_addr_to_fib_foreach_out_if (ip4_address_t *addr, u8 is_add) +nat44_ed_add_del_interface_fib_reg_entries (ip4_address_t addr, u8 is_add) { snat_main_t *sm = &snat_main; snat_interface_t *i; @@ -458,42 +438,66 @@ nat44_ed_add_del_addr_to_fib_foreach_out_if (ip4_address_t *addr, u8 is_add) { if (nat44_ed_is_interface_outside (i)) { - nat44_ed_add_del_addr_to_fib (addr, 32, i->sw_if_index, is_add); + if (is_add) + { + nat44_ed_add_fib_entry_reg (addr, i->sw_if_index); + } + else + { + nat44_ed_del_fib_entry_reg (addr, i->sw_if_index); + } } } pool_foreach (i, sm->output_feature_interfaces) { if (nat44_ed_is_interface_outside (i)) { - nat44_ed_add_del_addr_to_fib (addr, 32, i->sw_if_index, is_add); + if (is_add) + { + nat44_ed_add_fib_entry_reg (addr, i->sw_if_index); + } + else + { + nat44_ed_del_fib_entry_reg (addr, i->sw_if_index); + } } } } static_always_inline void -nat44_ed_add_del_addr_to_fib_foreach_addr (u32 sw_if_index, u8 is_add) +nat44_ed_add_del_nat_addr_fib_reg_entries (u32 sw_if_index, u8 is_add) { snat_main_t *sm = &snat_main; snat_address_t *ap; vec_foreach (ap, sm->addresses) { - nat44_ed_add_del_addr_to_fib (&ap->addr, 32, sw_if_index, is_add); + if (is_add) + { + nat44_ed_add_fib_entry_reg (ap->addr, sw_if_index); + } + else + { + nat44_ed_del_fib_entry_reg (ap->addr, sw_if_index); + } } } static_always_inline void -nat44_ed_add_del_addr_to_fib_foreach_addr_only_sm (u32 sw_if_index, u8 is_add) +nat44_ed_add_del_sm_fib_reg_entries (u32 sw_if_index, u8 is_add) { snat_main_t *sm = &snat_main; snat_static_mapping_t *m; pool_foreach (m, sm->static_mappings) { - if (is_sm_addr_only (m->flags) && !is_sm_identity_nat (m->flags)) + if (is_add) { - nat44_ed_add_del_addr_to_fib (&m->external_addr, 32, sw_if_index, - is_add); + nat44_ed_add_fib_entry_reg (m->external_addr, sw_if_index); + } + else + { + nat44_ed_del_fib_entry_reg (m->external_addr, sw_if_index); } } } @@ -544,21 +548,20 @@ nat44_ed_add_address (ip4_address_t *addr, u32 vrf_id, u8 twice_nat) { // if we don't have enabled interface we don't add address // to fib - nat44_ed_add_del_addr_to_fib_foreach_out_if (addr, 1); + nat44_ed_add_del_interface_fib_reg_entries (*addr, 1); nat44_ed_update_outside_if_addresses (ap); } return 0; } int -nat44_ed_del_address (ip4_address_t addr, u8 delete_sm, u8 twice_nat) +nat44_ed_del_address (ip4_address_t addr, u8 twice_nat) { snat_main_t *sm = &snat_main; snat_address_t *a = 0, *addresses; snat_session_t *ses; u32 *ses_to_be_removed = 0, *ses_index; snat_main_per_thread_data_t *tsm; - snat_static_mapping_t *m; int j; addresses = twice_nat ? sm->twice_nat_addresses : sm->addresses; @@ -577,33 +580,15 @@ nat44_ed_del_address (ip4_address_t addr, u8 delete_sm, u8 twice_nat) return VNET_API_ERROR_NO_SUCH_ENTRY; } - if (delete_sm) - { - pool_foreach (m, sm->static_mappings) - { - if (m->external_addr.as_u32 == addr.as_u32) - { - nat44_ed_del_static_mapping_internal ( - m->local_addr, m->external_addr, m->local_port, - m->external_port, ip_proto_to_nat_proto (m->proto), m->vrf_id, - ~0, m->flags); - } - } - } - else - { - if (is_snat_address_used_in_static_mapping (sm, addr)) - { - nat_log_err ("address used in static mapping"); - return VNET_API_ERROR_UNSPECIFIED; - } - } - - // delete sessions using address + // delete dynamic sessions only vec_foreach (tsm, sm->per_thread_data) { pool_foreach (ses, tsm->sessions) { + if (ses->flags & SNAT_SESSION_FLAG_STATIC_MAPPING) + { + continue; + } if (ses->out2in.addr.as_u32 == addr.as_u32) { nat44_ed_free_session_data (sm, ses, tsm - sm->per_thread_data, @@ -621,7 +606,7 @@ nat44_ed_del_address (ip4_address_t addr, u8 delete_sm, u8 twice_nat) if (!twice_nat) { - nat44_ed_add_del_addr_to_fib_foreach_out_if (&addr, 0); + nat44_ed_add_del_interface_fib_reg_entries (addr, 0); } if (a->fib_index != ~0) @@ -641,6 +626,134 @@ nat44_ed_del_address (ip4_address_t addr, u8 delete_sm, 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) { @@ -730,38 +843,18 @@ nat44_ed_sm_i2o_lookup (snat_main_t *sm, ip4_address_t addr, u16 port, return nat44_ed_sm_lookup (sm, &kv); } -void -nat44_ed_add_resolve_record (ip4_address_t l_addr, u16 l_port, u16 e_port, - ip_protocol_t proto, u32 vrf_id, u32 sw_if_index, - u32 flags, ip4_address_t pool_addr, u8 *tag) -{ - snat_static_map_resolve_t *rp; - snat_main_t *sm = &snat_main; - - vec_add2 (sm->to_resolve, rp, 1); - rp->l_addr.as_u32 = l_addr.as_u32; - rp->l_port = l_port; - rp->e_port = e_port; - rp->sw_if_index = sw_if_index; - rp->vrf_id = vrf_id; - rp->proto = proto; - rp->flags = flags; - rp->pool_addr = pool_addr; - rp->tag = vec_dup (tag); -} - -int +static snat_static_mapping_resolve_t * nat44_ed_get_resolve_record (ip4_address_t l_addr, u16 l_port, u16 e_port, ip_protocol_t proto, u32 vrf_id, u32 sw_if_index, - u32 flags, int *out) + u32 flags, int *out_idx) { - snat_static_map_resolve_t *rp; + snat_static_mapping_resolve_t *rp; snat_main_t *sm = &snat_main; int i; - for (i = 0; i < vec_len (sm->to_resolve); i++) + for (i = 0; i < vec_len (sm->sm_to_resolve); i++) { - rp = sm->to_resolve + i; + rp = sm->sm_to_resolve + i; if (rp->sw_if_index == sw_if_index && rp->vrf_id == vrf_id) { @@ -790,27 +883,27 @@ nat44_ed_get_resolve_record (ip4_address_t l_addr, u16 l_port, u16 e_port, { continue; } - if (out) + if (out_idx) { - *out = i; + *out_idx = i; } - return 0; + return rp; } } - return 1; + return NULL; } -int +static int nat44_ed_del_resolve_record (ip4_address_t l_addr, u16 l_port, u16 e_port, ip_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags) { snat_main_t *sm = &snat_main; int i; - if (!nat44_ed_get_resolve_record (l_addr, l_port, e_port, proto, vrf_id, - sw_if_index, flags, &i)) + if (nat44_ed_get_resolve_record (l_addr, l_port, e_port, proto, vrf_id, + sw_if_index, flags, &i)) { - vec_del1 (sm->to_resolve, i); + vec_del1 (sm->sm_to_resolve, i); return 0; } return 1; @@ -835,50 +928,69 @@ nat44_ed_validate_sm_input (u32 flags) return 0; } -snat_address_t * -nat44_ed_addr_lookup (snat_main_t *sm, u32 addr) -{ - for (int i = 0; i < vec_len (sm->addresses); ++i) - { - if (sm->addresses[i].addr.as_u32 == addr) - return &sm->addresses[i]; - } - return NULL; -} - int nat44_ed_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, ip_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags, ip4_address_t pool_addr, u8 *tag) { + snat_static_mapping_resolve_t *rp; snat_main_t *sm = &snat_main; + int rv; + + if (!sm->enabled) + { + return VNET_API_ERROR_UNSUPPORTED; + } + + rv = nat44_ed_validate_sm_input (flags); + if (rv != 0) + { + return rv; + } // interface bound mapping if (is_sm_switch_address (flags)) { - if (!nat44_ed_get_resolve_record (l_addr, l_port, e_port, proto, vrf_id, - sw_if_index, flags, 0)) + if (nat44_ed_get_resolve_record (l_addr, l_port, e_port, proto, vrf_id, + sw_if_index, flags, 0)) { return VNET_API_ERROR_VALUE_EXIST; } - nat44_ed_add_resolve_record (l_addr, l_port, e_port, proto, vrf_id, - sw_if_index, flags, pool_addr, tag); + vec_add2 (sm->sm_to_resolve, rp, 1); + rp->l_addr.as_u32 = l_addr.as_u32; + rp->l_port = l_port; + rp->e_port = e_port; + rp->sw_if_index = sw_if_index; + rp->vrf_id = vrf_id; + rp->proto = proto; + rp->flags = flags; + rp->pool_addr = pool_addr; + rp->tag = vec_dup (tag); + rp->is_resolved = 0; + ip4_address_t *first_int_addr = ip4_interface_first_address (sm->ip4_main, sw_if_index, 0); if (!first_int_addr) { - // dhcp resolution required return 0; } e_addr.as_u32 = first_int_addr->as_u32; + rp->is_resolved = 1; } - return nat44_ed_add_static_mapping_internal (l_addr, e_addr, l_port, e_port, - proto, vrf_id, sw_if_index, - flags, pool_addr, tag); + rv = nat44_ed_add_static_mapping_internal (l_addr, e_addr, l_port, e_port, + proto, vrf_id, sw_if_index, flags, + pool_addr, tag); + if ((0 != rv) && is_sm_switch_address (flags)) + { + nat44_ed_del_resolve_record (l_addr, l_port, e_port, proto, vrf_id, + sw_if_index, flags); + } + + return rv; } int @@ -886,8 +998,19 @@ nat44_ed_del_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, ip_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags) { - snat_main_t *sm = &snat_main; + int rv; + + if (!sm->enabled) + { + return VNET_API_ERROR_UNSUPPORTED; + } + + rv = nat44_ed_validate_sm_input (flags); + if (rv != 0) + { + return rv; + } // interface bound mapping if (is_sm_switch_address (flags)) @@ -909,8 +1032,8 @@ nat44_ed_del_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, e_addr.as_u32 = first_int_addr->as_u32; } - return nat44_ed_del_static_mapping_internal ( - l_addr, e_addr, l_port, e_port, proto, vrf_id, sw_if_index, flags); + return nat44_ed_del_static_mapping_internal (l_addr, e_addr, l_port, e_port, + proto, vrf_id, flags); } static int @@ -924,18 +1047,6 @@ nat44_ed_add_static_mapping_internal (ip4_address_t l_addr, nat44_lb_addr_port_t *local; snat_static_mapping_t *m; u32 fib_index = ~0; - int rv; - - if (!sm->enabled) - { - return VNET_API_ERROR_UNSUPPORTED; - } - - rv = nat44_ed_validate_sm_input (flags); - if (rv != 0) - { - return rv; - } if (is_sm_addr_only (flags)) { @@ -951,13 +1062,14 @@ nat44_ed_add_static_mapping_internal (ip4_address_t l_addr, m = nat44_ed_sm_o2i_lookup (sm, e_addr, e_port, 0, proto); if (m) { + // case: + // adding local identity nat record for different vrf table + if (!is_sm_identity_nat (m->flags)) { return VNET_API_ERROR_VALUE_EXIST; } - // case: - // adding local identity nat record for different vrf table pool_foreach (local, m->locals) { if (local->vrf_id == vrf_id) @@ -1001,21 +1113,6 @@ nat44_ed_add_static_mapping_internal (ip4_address_t l_addr, } } - if (!(is_sm_out2in_only (flags) || is_sm_addr_only (flags) || - sm->static_mapping_only)) - { - if (!nat44_ed_addr_lookup (sm, e_addr.as_u32)) - { - // remove resolve record - if (is_sm_switch_address (flags) && !is_sm_identity_nat (flags)) - { - nat44_ed_del_resolve_record (l_addr, l_port, e_port, proto, - vrf_id, sw_if_index, flags); - } - return VNET_API_ERROR_NO_SUCH_ENTRY; - } - } - pool_get (sm->static_mappings, m); clib_memset (m, 0, sizeof (*m)); @@ -1023,13 +1120,9 @@ nat44_ed_add_static_mapping_internal (ip4_address_t l_addr, m->local_addr = l_addr; m->external_addr = e_addr; + m->pool_addr = pool_addr; m->tag = vec_dup (tag); - if (is_sm_exact_address (flags) && is_sm_twice_nat (flags)) - { - m->pool_addr = pool_addr; - } - if (!is_sm_addr_only (flags)) { m->local_port = l_port; @@ -1048,12 +1141,6 @@ nat44_ed_add_static_mapping_internal (ip4_address_t l_addr, { m->vrf_id = vrf_id; m->fib_index = fib_index; - - // not identity && addr only - if (is_sm_addr_only (flags)) - { - nat44_ed_add_del_addr_to_fib_foreach_out_if (&e_addr, 1); - } } if (!is_sm_out2in_only (flags)) @@ -1076,6 +1163,8 @@ nat44_ed_add_static_mapping_internal (ip4_address_t l_addr, vec_add1 (m->workers, worker_index); } + nat44_ed_add_del_interface_fib_reg_entries (e_addr, 1); + return 0; } @@ -1083,26 +1172,14 @@ static int nat44_ed_del_static_mapping_internal (ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, ip_protocol_t proto, - u32 vrf_id, u32 sw_if_index, u32 flags) + u32 vrf_id, u32 flags) { - snat_main_per_thread_data_t *tsm; - snat_main_t *sm = &snat_main; - - nat44_lb_addr_port_t *local; - snat_static_mapping_t *m; - u32 fib_index = ~0; - int rv; - - if (!sm->enabled) - { - return VNET_API_ERROR_UNSUPPORTED; - } - - rv = nat44_ed_validate_sm_input (flags); - if (rv != 0) - { - return rv; - } + snat_main_per_thread_data_t *tsm; + snat_main_t *sm = &snat_main; + + nat44_lb_addr_port_t *local; + snat_static_mapping_t *m; + u32 fib_index = ~0; if (is_sm_addr_only (flags)) { @@ -1117,13 +1194,8 @@ nat44_ed_del_static_mapping_internal (ip4_address_t l_addr, // fib index 0 m = nat44_ed_sm_o2i_lookup (sm, e_addr, e_port, 0, proto); - if (!m) { - if (is_sm_switch_address (flags)) - { - return 0; - } return VNET_API_ERROR_NO_SUCH_ENTRY; } @@ -1157,32 +1229,24 @@ nat44_ed_del_static_mapping_internal (ip4_address_t l_addr, fib_index = m->fib_index; } - if (!(is_sm_out2in_only (flags) || is_sm_addr_only (flags) || - sm->static_mapping_only)) - { - if (!nat44_ed_addr_lookup (sm, e_addr.as_u32)) - { - return VNET_API_ERROR_INVALID_VALUE; - } - } - if (!is_sm_out2in_only (flags)) { nat44_ed_sm_i2o_del (sm, l_addr, l_port, fib_index, proto); } - if (!sm->static_mapping_only || sm->static_mapping_connection_tracking) + // delete sessions for static mapping + if (sm->num_workers > 1) { - // delete sessions for static mapping - if (sm->num_workers > 1) - tsm = vec_elt_at_index (sm->per_thread_data, m->workers[0]); - else - tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers); - - nat_ed_static_mapping_del_sessions ( - sm, tsm, m->local_addr, m->local_port, m->proto, fib_index, - is_sm_addr_only (flags), e_addr, e_port); + tsm = vec_elt_at_index (sm->per_thread_data, m->workers[0]); } + else + { + tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers); + } + + nat_ed_static_mapping_del_sessions (sm, tsm, m->local_addr, m->local_port, + m->proto, fib_index, + is_sm_addr_only (flags), e_addr, e_port); fib_table_unlock (fib_index, FIB_PROTOCOL_IP4, sm->fib_src_low); @@ -1196,10 +1260,7 @@ nat44_ed_del_static_mapping_internal (ip4_address_t l_addr, vec_free (m->workers); pool_put (sm->static_mappings, m); - if (is_sm_addr_only (flags) && !is_sm_identity_nat (flags)) - { - nat44_ed_add_del_addr_to_fib_foreach_out_if (&e_addr, 0); - } + nat44_ed_add_del_interface_fib_reg_entries (e_addr, 0); } return 0; @@ -1238,7 +1299,7 @@ nat44_ed_add_lb_static_mapping (ip4_address_t e_addr, u16 e_port, return VNET_API_ERROR_INVALID_VALUE; } - if (!(sm->static_mapping_only || is_sm_out2in_only (flags))) + if (!is_sm_out2in_only (flags)) { /* Find external address in allocated addresses and reserve port for address and port pair mapping when dynamic translations enabled */ @@ -1282,7 +1343,7 @@ nat44_ed_add_lb_static_mapping (ip4_address_t e_addr, u16 e_port, if (nat44_ed_sm_o2i_add (sm, m, m->external_addr, m->external_port, 0, m->proto)) { - nat_elog_err (sm, "sm o2i key add failed"); + nat_log_err ("sm o2i key add failed"); return VNET_API_ERROR_UNSPECIFIED; } @@ -1294,7 +1355,7 @@ nat44_ed_add_lb_static_mapping (ip4_address_t e_addr, u16 e_port, { if (nat44_ed_sm_o2i_add (sm, m, e_addr, e_port, 0, proto)) { - nat_elog_err (sm, "sm o2i key add failed"); + nat_log_err ("sm o2i 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 @@ -1357,7 +1418,7 @@ nat44_ed_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, if (nat44_ed_sm_o2i_del (sm, m->external_addr, m->external_port, 0, m->proto)) { - nat_elog_err (sm, "sm o2i key del failed"); + nat_log_err ("sm o2i key del failed"); return VNET_API_ERROR_UNSPECIFIED; } @@ -1369,7 +1430,7 @@ nat44_ed_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, if (nat44_ed_sm_i2o_del (sm, local->addr, local->port, local->fib_index, m->proto)) { - nat_elog_err (sm, "sm i2o key del failed"); + nat_log_err ("sm i2o key del failed"); return VNET_API_ERROR_UNSPECIFIED; } } @@ -1478,7 +1539,7 @@ nat44_ed_add_del_lb_static_mapping_local (ip4_address_t e_addr, u16 e_port, if (nat44_ed_sm_i2o_add (sm, m, l_addr, l_port, local->fib_index, proto)) { - nat_elog_err (sm, "sm i2o key add failed"); + nat_log_err ("sm i2o key add failed"); pool_put (m->locals, local); return VNET_API_ERROR_UNSPECIFIED; } @@ -1499,7 +1560,7 @@ nat44_ed_add_del_lb_static_mapping_local (ip4_address_t e_addr, u16 e_port, { if (nat44_ed_sm_i2o_del (sm, l_addr, l_port, match_local->fib_index, proto)) - nat_elog_err (sm, "sm i2o key del failed"); + nat_log_err ("sm i2o key del failed"); } if (sm->num_workers > 1) @@ -1622,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) @@ -1656,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; @@ -1738,17 +1799,17 @@ 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_addr_to_fib_foreach_addr (sw_if_index, 1); - nat44_ed_add_del_addr_to_fib_foreach_addr_only_sm (sw_if_index, 1); + nat44_ed_add_del_nat_addr_fib_reg_entries (sw_if_index, 1); + nat44_ed_add_del_sm_fib_reg_entries (sw_if_index, 1); nat44_ed_bind_if_addr_to_nat_addr (sw_if_index); } @@ -1766,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; @@ -1851,15 +1912,15 @@ nat44_ed_del_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--; - if (!outside_fib->refcount) + outside_fib->ref_count--; + if (!outside_fib->ref_count) { vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs); } } - nat44_ed_add_del_addr_to_fib_foreach_addr (sw_if_index, 0); - nat44_ed_add_del_addr_to_fib_foreach_addr_only_sm (sw_if_index, 0); + nat44_ed_add_del_nat_addr_fib_reg_entries (sw_if_index, 0); + nat44_ed_add_del_sm_fib_reg_entries (sw_if_index, 0); } return 0; @@ -1870,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; @@ -1948,17 +2009,17 @@ nat44_ed_add_output_interface (u32 sw_if_index) 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_addr_to_fib_foreach_addr (sw_if_index, 1); - nat44_ed_add_del_addr_to_fib_foreach_addr_only_sm (sw_if_index, 1); + nat44_ed_add_del_nat_addr_fib_reg_entries (sw_if_index, 1); + nat44_ed_add_del_sm_fib_reg_entries (sw_if_index, 1); nat44_ed_bind_if_addr_to_nat_addr (sw_if_index); @@ -1970,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; @@ -2038,15 +2099,15 @@ nat44_ed_del_output_interface (u32 sw_if_index) 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); } } - nat44_ed_add_del_addr_to_fib_foreach_addr (sw_if_index, 0); - nat44_ed_add_del_addr_to_fib_foreach_addr_only_sm (sw_if_index, 0); + nat44_ed_add_del_nat_addr_fib_reg_entries (sw_if_index, 0); + nat44_ed_add_del_sm_fib_reg_entries (sw_if_index, 0); return 0; } @@ -2082,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; } @@ -2091,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; @@ -2103,7 +2176,7 @@ nat44_ed_update_outside_fib_cb (ip4_main_t *im, uword opaque, u32 sw_if_index, } pool_foreach (i, sm->interfaces) - { + { if (i->sw_if_index == sw_if_index) { if (!(nat44_ed_is_interface_outside (i))) @@ -2113,7 +2186,7 @@ nat44_ed_update_outside_fib_cb (ip4_main_t *im, uword opaque, u32 sw_if_index, } pool_foreach (i, sm->output_feature_interfaces) - { + { if (i->sw_if_index == sw_if_index) { if (!(nat44_ed_is_interface_outside (i))) @@ -2126,30 +2199,30 @@ nat44_ed_update_outside_fib_cb (ip4_main_t *im, uword opaque, u32 sw_if_index, return; vec_foreach (outside_fib, sm->outside_fibs) - { - if (outside_fib->fib_index == old_fib_index) - { - outside_fib->refcount--; - if (!outside_fib->refcount) - vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs); - break; - } - } + { + if (outside_fib->fib_index == old_fib_index) + { + outside_fib->ref_count--; + if (!outside_fib->ref_count) + vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs); + break; + } + } vec_foreach (outside_fib, sm->outside_fibs) - { - if (outside_fib->fib_index == new_fib_index) - { - outside_fib->refcount++; - is_add = 0; - break; - } - } + { + if (outside_fib->fib_index == new_fib_index) + { + outside_fib->ref_count++; + is_add = 0; + break; + } + } 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; } } @@ -2162,7 +2235,7 @@ static void nat44_ed_add_del_interface_address_cb ( ip4_main_t *im, uword opaque, u32 sw_if_index, ip4_address_t *address, u32 address_length, u32 if_address_index, u32 is_delete); -static void nat44_ed_add_del_static_mapping_addr_only_cb ( +static void nat44_ed_add_del_static_mapping_cb ( ip4_main_t *im, uword opaque, u32 sw_if_index, ip4_address_t *address, u32 address_length, u32 if_address_index, u32 is_delete); @@ -2225,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 \ { \ @@ -2287,8 +2345,6 @@ nat_init (vlib_main_t * vm) 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; @@ -2297,15 +2353,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, \ @@ -2351,7 +2405,7 @@ nat_init (vlib_main_t * vm) /* callbacks to call when interface address changes. */ cbi.function = nat44_ed_add_del_interface_address_cb; vec_add1 (sm->ip4_main->add_del_interface_address_callbacks, cbi); - cbi.function = nat44_ed_add_del_static_mapping_addr_only_cb; + cbi.function = nat44_ed_add_del_static_mapping_cb; vec_add1 (sm->ip4_main->add_del_interface_address_callbacks, cbi); /* callbacks to call when interface to table biding changes */ @@ -2380,26 +2434,15 @@ nat44_plugin_enable (nat44_config_t c) fail_if_enabled (); - if (c.static_mapping_only && !c.connection_tracking) - { - nat_log_err ("unsupported combination of configuration"); - return 1; - } - - sm->static_mapping_only = c.static_mapping_only; - sm->static_mapping_connection_tracking = c.connection_tracking; - sm->forwarding_enabled = 0; sm->mss_clamping = 0; - sm->pat = (!c.static_mapping_only || - (c.static_mapping_only && c.connection_tracking)); if (!c.sessions) 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); @@ -2415,6 +2458,8 @@ nat44_plugin_enable (nat44_config_t c) nat44_ed_db_init (sm->max_translations_per_thread, sm->translation_buckets); + nat44_ed_init_tcp_state_stable (sm); + nat_affinity_enable (); nat_reset_timeouts (&sm->timeouts); @@ -2428,20 +2473,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); } } @@ -2461,7 +2512,7 @@ nat44_ed_del_addresses () vec = vec_dup (sm->addresses); vec_foreach (a, vec) { - error = nat44_ed_del_address (a->addr, 0, 0); + error = nat44_ed_del_address (a->addr, 0); if (error) { nat_log_err ("error occurred while removing adderess"); @@ -2474,7 +2525,7 @@ nat44_ed_del_addresses () vec = vec_dup (sm->twice_nat_addresses); vec_foreach (a, vec) { - error = nat44_ed_del_address (a->addr, 0, 1); + error = nat44_ed_del_address (a->addr, 1); if (error) { nat_log_err ("error occurred while removing adderess"); @@ -2484,11 +2535,8 @@ nat44_ed_del_addresses () vec_free (sm->twice_nat_addresses); sm->twice_nat_addresses = 0; - vec_free (sm->auto_add_sw_if_indices_twice_nat); - sm->auto_add_sw_if_indices_twice_nat = 0; - - vec_free (sm->auto_add_sw_if_indices); - sm->auto_add_sw_if_indices = 0; + vec_free (sm->addr_to_resolve); + sm->addr_to_resolve = 0; return error; } @@ -2557,7 +2605,7 @@ nat44_ed_del_static_mappings () { error = nat44_ed_del_static_mapping_internal ( m->local_addr, m->external_addr, m->local_port, m->external_port, - m->proto, m->vrf_id, ~0, m->flags); + m->proto, m->vrf_id, m->flags); if (error) { nat_log_err ("error occurred while removing mapping"); @@ -2567,8 +2615,8 @@ nat44_ed_del_static_mappings () pool_free (sm->static_mappings); sm->static_mappings = 0; - vec_free (sm->to_resolve); - sm->to_resolve = 0; + vec_free (sm->sm_to_resolve); + sm->sm_to_resolve = 0; return error; } @@ -2598,21 +2646,22 @@ nat44_plugin_disable () if (rc) error = 1; + 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); - if (sm->pat) + vec_foreach (tsm, sm->per_thread_data) { - vec_foreach (tsm, sm->per_thread_data) - { - nat44_ed_worker_db_free (tsm); - } + nat44_ed_worker_db_free (tsm); } clib_memset (&sm->rconfig, 0, sizeof (sm->rconfig)); + nat_affinity_disable (); + sm->forwarding_enabled = 0; sm->enabled = 0; @@ -2668,11 +2717,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, @@ -2680,12 +2730,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, @@ -2693,7 +2744,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) @@ -2707,7 +2758,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; @@ -2716,15 +2767,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; @@ -2868,7 +2920,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, @@ -3064,7 +3116,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; @@ -3078,13 +3130,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 (); @@ -3172,8 +3224,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); @@ -3231,13 +3283,10 @@ nat44_ed_db_init (u32 translations, u32 translation_buckets) reinit_ed_flow_hash (); - if (sm->pat) + vec_foreach (tsm, sm->per_thread_data) { - 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, + sm->translation_buckets); } } @@ -3257,95 +3306,105 @@ nat44_ed_sessions_clear () reinit_ed_flow_hash (); - if (sm->pat) + vec_foreach (tsm, sm->per_thread_data) { - 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_worker_db_free (tsm); + nat44_ed_worker_db_init (tsm, sm->max_translations_per_thread, + sm->translation_buckets); } vlib_zero_simple_counter (&sm->total_sessions, 0); } static void -nat44_ed_add_del_static_mapping_addr_only_cb ( - ip4_main_t *im, uword opaque, u32 sw_if_index, ip4_address_t *address, - u32 address_length, u32 if_address_index, u32 is_delete) +nat44_ed_add_del_static_mapping_cb (ip4_main_t *im, uword opaque, + u32 sw_if_index, ip4_address_t *address, + u32 address_length, u32 if_address_index, + u32 is_delete) { - snat_static_map_resolve_t *rp; + snat_static_mapping_resolve_t *rp; snat_main_t *sm = &snat_main; - snat_static_mapping_t *m; - int i, rv = 0, match = 0; + int rv = 0; if (!sm->enabled) { return; } - // find first addr_only resolve record by sw_if_index - for (i = 0; i < vec_len (sm->to_resolve); i++) + vec_foreach (rp, sm->sm_to_resolve) { - rp = sm->to_resolve + i; - if (is_sm_addr_only (rp->flags) && rp->sw_if_index == sw_if_index) + if (sw_if_index == rp->sw_if_index) { - match = 1; - break; + if (is_delete) + { + if (rp->is_resolved) + { + rv = nat44_ed_del_static_mapping_internal ( + rp->l_addr, address[0], rp->l_port, rp->e_port, rp->proto, + rp->vrf_id, rp->flags); + if (rv) + { + nat_log_err ("ed del static mapping failed"); + } + else + { + rp->is_resolved = 0; + } + } + } + else + { + if (!rp->is_resolved) + { + rv = nat44_ed_add_static_mapping_internal ( + rp->l_addr, address[0], rp->l_port, rp->e_port, rp->proto, + rp->vrf_id, ~0, rp->flags, rp->pool_addr, rp->tag); + if (rv) + { + nat_log_err ("ed add static mapping failed"); + } + else + { + rp->is_resolved = 1; + } + } + } } } - if (!match) - { - return; - } +} - m = nat44_ed_sm_o2i_lookup ( - sm, *address, is_sm_addr_only (rp->flags) ? 0 : rp->e_port, 0, rp->proto); +static int +nat44_ed_get_addr_resolve_record (u32 sw_if_index, u8 twice_nat, int *out) +{ + snat_main_t *sm = &snat_main; + snat_address_resolve_t *rp; + int i; - if (is_delete) - { - if (m) - { - rv = nat44_ed_del_static_mapping_internal ( - rp->l_addr, address[0], rp->l_port, rp->e_port, rp->proto, - rp->vrf_id, ~0, rp->flags); - } - if (rv) - { - nat_elog_notice_X1 (sm, "nat44_ed_del_static_mapping returned %d", - "i4", rv); - } - } - else + for (i = 0; i < vec_len (sm->addr_to_resolve); i++) { - if (!m) - { - rv = nat44_ed_add_static_mapping_internal ( - rp->l_addr, address[0], rp->l_port, rp->e_port, rp->proto, - rp->vrf_id, ~0, rp->flags, rp->pool_addr, rp->tag); - } - // else: don't trip over lease renewal, static config - if (rv) + rp = sm->addr_to_resolve + i; + + if ((rp->sw_if_index == sw_if_index) && (rp->is_twice_nat == twice_nat)) { - nat_elog_notice_X1 (sm, "nat44_ed_add_static_mapping returned %d", - "i4", rv); + if (out) + { + *out = i; + } + return 0; } } + return 1; } - -static_always_inline int -is_sw_if_index_reg_for_auto_resolve (u32 *sw_if_indices, u32 sw_if_index) +static int +nat44_ed_del_addr_resolve_record (u32 sw_if_index, u8 twice_nat) { - u32 *i; - vec_foreach (i, sw_if_indices) + snat_main_t *sm = &snat_main; + int i; + if (!nat44_ed_get_addr_resolve_record (sw_if_index, twice_nat, &i)) { - if (*i == sw_if_index) - { - return 1; - } + vec_del1 (sm->addr_to_resolve, i); + return 0; } - return 0; + return 1; } static void @@ -3355,23 +3414,21 @@ nat44_ed_add_del_interface_address_cb (ip4_main_t *im, uword opaque, u32 if_address_index, u32 is_delete) { snat_main_t *sm = &snat_main; - snat_static_map_resolve_t *rp; - snat_address_t *ap, *addresses = sm->addresses; + snat_address_resolve_t *arp; + snat_address_t *ap; u8 twice_nat = 0; - int rv, i; + int i, rv; if (!sm->enabled) { return; } - if (!is_sw_if_index_reg_for_auto_resolve (sm->auto_add_sw_if_indices, - sw_if_index)) + if (nat44_ed_get_addr_resolve_record (sw_if_index, twice_nat, &i)) { - if (!is_sw_if_index_reg_for_auto_resolve ( - sm->auto_add_sw_if_indices_twice_nat, sw_if_index)) + twice_nat = 1; + if (nat44_ed_get_addr_resolve_record (sw_if_index, twice_nat, &i)) { - // interface resolve u32 fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index); vec_foreach (ap, sm->addresses) @@ -3400,51 +3457,35 @@ nat44_ed_add_del_interface_address_cb (ip4_main_t *im, uword opaque, } return; } - else - { - addresses = sm->twice_nat_addresses; - twice_nat = 1; - } } + arp = sm->addr_to_resolve + i; + if (!is_delete) { - // don't trip over lease renewal, static config - for (i = 0; i < vec_len (addresses); i++) + if (arp->is_resolved) { - if (addresses[i].addr.as_u32 == address->as_u32) - { - return; - } + return; } - (void) nat44_ed_add_address (address, ~0, twice_nat); - - // scan static mapping switch address resolution record vector - for (i = 0; i < vec_len (sm->to_resolve); i++) + rv = nat44_ed_add_address (address, ~0, arp->is_twice_nat); + if (0 == rv) { - rp = sm->to_resolve + i; - if (is_sm_addr_only (rp->flags)) - { - continue; - } - if (rp->sw_if_index == sw_if_index) - { - rv = nat44_ed_add_static_mapping_internal ( - rp->l_addr, address[0], rp->l_port, rp->e_port, rp->proto, - rp->vrf_id, sw_if_index, rp->flags, rp->pool_addr, rp->tag); - if (rv) - { - nat_elog_notice_X1 ( - sm, "add_static_mapping_internal returned %d", "i4", rv); - } - } + arp->is_resolved = 1; } } else { - // remove all static mapping records - (void) nat44_ed_del_address (address[0], 1, twice_nat); + if (!arp->is_resolved) + { + return; + } + + rv = nat44_ed_del_address (address[0], arp->is_twice_nat); + if (0 == rv) + { + arp->is_resolved = 0; + } } } @@ -3454,34 +3495,34 @@ nat44_ed_add_interface_address (u32 sw_if_index, u8 twice_nat) snat_main_t *sm = &snat_main; ip4_main_t *ip4_main = sm->ip4_main; ip4_address_t *first_int_addr; - u32 *auto_add_sw_if_indices = twice_nat ? - sm->auto_add_sw_if_indices_twice_nat : - sm->auto_add_sw_if_indices; - int i; + snat_address_resolve_t *ap; + int rv; - for (i = 0; i < vec_len (auto_add_sw_if_indices); i++) + if (!sm->enabled) { - if (auto_add_sw_if_indices[i] == sw_if_index) - { - return VNET_API_ERROR_VALUE_EXIST; - } + return VNET_API_ERROR_UNSUPPORTED; } - // add to the auto-address list - if (twice_nat) + if (!nat44_ed_get_addr_resolve_record (sw_if_index, twice_nat, 0)) { - vec_add1 (sm->auto_add_sw_if_indices_twice_nat, sw_if_index); - } - else - { - vec_add1 (sm->auto_add_sw_if_indices, sw_if_index); + return VNET_API_ERROR_VALUE_EXIST; } - // if the address is already bound - or static - add it now + vec_add2 (sm->addr_to_resolve, ap, 1); + ap->sw_if_index = sw_if_index; + ap->is_twice_nat = twice_nat; + ap->is_resolved = 0; + first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index, 0); if (first_int_addr) { - (void) nat44_ed_add_address (first_int_addr, ~0, twice_nat); + rv = nat44_ed_add_address (first_int_addr, ~0, twice_nat); + if (0 != rv) + { + nat44_ed_del_addr_resolve_record (sw_if_index, twice_nat); + return rv; + } + ap->is_resolved = 1; } return 0; @@ -3493,62 +3534,24 @@ nat44_ed_del_interface_address (u32 sw_if_index, u8 twice_nat) snat_main_t *sm = &snat_main; ip4_main_t *ip4_main = sm->ip4_main; ip4_address_t *first_int_addr; - snat_static_map_resolve_t *rp; - u32 *indices_to_delete = 0; - int i, j; - u32 *auto_add_sw_if_indices; if (!sm->enabled) { return VNET_API_ERROR_UNSUPPORTED; } - auto_add_sw_if_indices = twice_nat ? sm->auto_add_sw_if_indices_twice_nat : - sm->auto_add_sw_if_indices; - - for (i = 0; i < vec_len (auto_add_sw_if_indices); i++) + if (nat44_ed_del_addr_resolve_record (sw_if_index, twice_nat)) { - if (auto_add_sw_if_indices[i] == sw_if_index) - { - first_int_addr = - ip4_interface_first_address (ip4_main, sw_if_index, 0); - if (first_int_addr) - { - // remove all static mapping records - (void) nat44_ed_del_address (first_int_addr[0], 1, twice_nat); - } - else - { - for (j = 0; j < vec_len (sm->to_resolve); j++) - { - rp = sm->to_resolve + j; - if (rp->sw_if_index == sw_if_index) - { - vec_add1 (indices_to_delete, j); - } - } - if (vec_len (indices_to_delete)) - { - for (j = vec_len (indices_to_delete) - 1; j >= 0; j--) - { - vec_del1 (sm->to_resolve, j); - } - vec_free (indices_to_delete); - } - } + return VNET_API_ERROR_NO_SUCH_ENTRY; + } - if (twice_nat) - { - vec_del1 (sm->auto_add_sw_if_indices_twice_nat, i); - } - else - { - vec_del1 (sm->auto_add_sw_if_indices, i); - } - return 0; - } + first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index, 0); + if (first_int_addr) + { + return nat44_ed_del_address (first_int_addr[0], twice_nat); } - return VNET_API_ERROR_NO_SUCH_ENTRY; + + return 0; } int @@ -3781,7 +3784,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)) { @@ -3797,7 +3800,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); @@ -3877,6 +3880,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); @@ -3884,19 +3890,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; } @@ -3968,110 +3976,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,