X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fnat%2Fnat64.c;h=936ea9e9988bf106188d7ab309a828b797ee0412;hb=0938dcf192d203dcbe89d2819d3819d2f93408bf;hp=b04901fade420da8b8147e22aed614fdcc64b1ee;hpb=2ba92e32e0197f676dd905e5edcb4ff3e1bec241;p=vpp.git diff --git a/src/plugins/nat/nat64.c b/src/plugins/nat/nat64.c index b04901fade4..936ea9e9988 100644 --- a/src/plugins/nat/nat64.c +++ b/src/plugins/nat/nat64.c @@ -47,12 +47,47 @@ static u8 well_known_prefix[] = { /* *INDENT-ON* */ +static void +nat64_ip4_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) +{ + nat64_main_t *nm = &nat64_main; + int i, j; + + for (i = 0; i < vec_len (nm->auto_add_sw_if_indices); i++) + { + if (sw_if_index == nm->auto_add_sw_if_indices[i]) + { + if (!is_delete) + { + /* Don't trip over lease renewal, static config */ + for (j = 0; j < vec_len (nm->addr_pool); j++) + if (nm->addr_pool[j].addr.as_u32 == address->as_u32) + return; + + (void) nat64_add_del_pool_addr (address, ~0, 1); + return; + } + else + { + (void) nat64_add_del_pool_addr (address, ~0, 0); + return; + } + } + } +} + clib_error_t * nat64_init (vlib_main_t * vm) { nat64_main_t *nm = &nat64_main; clib_error_t *error = 0; vlib_thread_main_t *tm = vlib_get_thread_main (); + ip4_add_del_interface_address_callback_t cb4; + ip4_main_t *im = &ip4_main; nm->is_disabled = 0; @@ -75,6 +110,12 @@ nat64_init (vlib_main_t * vm) nm->tcp_est_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT; nm->tcp_incoming_syn_timeout = SNAT_TCP_INCOMING_SYN; + /* Set up the interface address add/del callback */ + cb4.function = nat64_ip4_add_del_interface_address_cb; + cb4.function_opaque = 0; + vec_add1 (im->add_del_interface_address_callbacks, cb4); + nm->ip4_main = im; + error: return error; } @@ -107,7 +148,8 @@ nat64_add_del_pool_addr (ip4_address_t * addr, u32 vrf_id, u8 is_add) a->fib_index = 0; if (vrf_id != ~0) a->fib_index = - fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id); + fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id, + FIB_SOURCE_PLUGIN_HI); #define _(N, i, n, s) \ clib_bitmap_alloc (a->busy_##n##_port_bitmap, 65535); foreach_snat_protocol @@ -119,7 +161,8 @@ nat64_add_del_pool_addr (ip4_address_t * addr, u32 vrf_id, u8 is_add) return VNET_API_ERROR_NO_SUCH_ENTRY; if (a->fib_index) - fib_table_unlock (a->fib_index, FIB_PROTOCOL_IP6); + fib_table_unlock (a->fib_index, FIB_PROTOCOL_IP6, + FIB_SOURCE_PLUGIN_HI); #define _(N, id, n, s) \ clib_bitmap_free (a->busy_##n##_port_bitmap); @@ -134,7 +177,7 @@ nat64_add_del_pool_addr (ip4_address_t * addr, u32 vrf_id, u8 is_add) /* *INDENT-OFF* */ pool_foreach (interface, nm->interfaces, ({ - if (interface->is_inside) + if (nat_interface_is_inside(interface)) continue; snat_add_del_addr_to_fib (addr, 32, interface->sw_if_index, is_add); @@ -160,6 +203,47 @@ nat64_pool_addr_walk (nat64_pool_addr_walk_fn_t fn, void *ctx) /* *INDENT-ON* */ } +int +nat64_add_interface_address (u32 sw_if_index, int is_add) +{ + nat64_main_t *nm = &nat64_main; + ip4_main_t *ip4_main = nm->ip4_main; + ip4_address_t *first_int_addr; + int i; + + first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index, 0); + + for (i = 0; i < vec_len (nm->auto_add_sw_if_indices); i++) + { + if (nm->auto_add_sw_if_indices[i] == sw_if_index) + { + if (is_add) + return VNET_API_ERROR_VALUE_EXIST; + else + { + /* if have address remove it */ + if (first_int_addr) + (void) nat64_add_del_pool_addr (first_int_addr, ~0, 0); + + vec_del1 (nm->auto_add_sw_if_indices, i); + return 0; + } + } + } + + if (!is_add) + return VNET_API_ERROR_NO_SUCH_ENTRY; + + /* add to the auto-address list */ + vec_add1 (nm->auto_add_sw_if_indices, sw_if_index); + + /* If the address is already bound - or static - add it now */ + if (first_int_addr) + (void) nat64_add_del_pool_addr (first_int_addr, ~0, 1); + + return 0; +} + int nat64_add_del_interface (u32 sw_if_index, u8 is_inside, u8 is_add) { @@ -168,7 +252,7 @@ nat64_add_del_interface (u32 sw_if_index, u8 is_inside, u8 is_add) snat_address_t *ap; const char *feature_name, *arc_name; - /* Check if address already exists */ + /* Check if interface already exists */ /* *INDENT-OFF* */ pool_foreach (i, nm->interfaces, ({ @@ -183,19 +267,29 @@ nat64_add_del_interface (u32 sw_if_index, u8 is_inside, u8 is_add) if (is_add) { if (interface) - return VNET_API_ERROR_VALUE_EXIST; + goto set_flags; pool_get (nm->interfaces, interface); interface->sw_if_index = sw_if_index; - interface->is_inside = is_inside; - + interface->flags = 0; + set_flags: + if (is_inside) + interface->flags |= NAT_INTERFACE_FLAG_IS_INSIDE; + else + interface->flags |= NAT_INTERFACE_FLAG_IS_OUTSIDE; } else { if (!interface) return VNET_API_ERROR_NO_SUCH_ENTRY; - pool_put (nm->interfaces, interface); + if ((nat_interface_is_inside (interface) + && nat_interface_is_outside (interface))) + interface->flags &= + is_inside ? ~NAT_INTERFACE_FLAG_IS_INSIDE : + ~NAT_INTERFACE_FLAG_IS_OUTSIDE; + else + pool_put (nm->interfaces, interface); } if (!is_inside) @@ -353,8 +447,8 @@ nat64_add_del_static_bib_entry (ip6_address_t * in_addr, { nat64_main_t *nm = &nat64_main; nat64_db_bib_entry_t *bibe; - u32 fib_index = - fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id); + u32 fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id, + FIB_SOURCE_PLUGIN_HI); snat_protocol_t p = ip_proto_to_snat_proto (proto); ip46_address_t addr; int i; @@ -644,7 +738,8 @@ nat64_add_del_prefix (ip6_address_t * prefix, u8 plen, u32 vrf_id, u8 is_add) { vec_add2 (nm->pref64, p, 1); p->fib_index = - fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id); + fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id, + FIB_SOURCE_PLUGIN_HI); p->vrf_id = vrf_id; }