/* * Copyright (c) 2020 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <vnet/fib/fib_table.h> #include <nat/lib/log.h> #include <nat/lib/nat_inlines.h> #include <nat/lib/ipfix_logging.h> #include <nat/nat44-ei/nat44_ei.h> #include <nat/nat44-ei/nat44_ei_ha.h> #define NAT44_EI_EXPECTED_ARGUMENT "expected required argument(s)" u8 * format_nat44_ei_session (u8 *s, va_list *args) { nat44_ei_main_per_thread_data_t *tnm = va_arg (*args, nat44_ei_main_per_thread_data_t *); nat44_ei_session_t *sess = va_arg (*args, nat44_ei_session_t *); if (nat44_ei_is_unk_proto_session (sess)) { s = format (s, " i2o %U proto %u fib %u\n", format_ip4_address, &sess->in2out.addr, sess->in2out.port, sess->in2out.fib_index); s = format (s, " o2i %U proto %u fib %u\n", format_ip4_address, &sess->out2in.addr, sess->out2in.port, sess->out2in.fib_index); } else { s = format (s, " i2o %U proto %U port %d fib %d\n", format_ip4_address, &sess->in2out.addr, format_nat_protocol, sess->nat_proto, clib_net_to_host_u16 (sess->in2out.port), sess->in2out.fib_index); s = format (s, " o2i %U proto %U port %d fib %d\n", format_ip4_address, &sess->out2in.addr, format_nat_protocol, sess->nat_proto, clib_net_to_host_u16 (sess->out2in.port), sess->out2in.fib_index); } s = format (s, " index %llu\n", sess - tnm->sessions); s = format (s, " last heard %.2f\n", sess->last_heard); s = format (s, " total pkts %d, total bytes %lld\n", sess->total_pkts, sess->total_bytes); if (nat44_ei_is_session_static (sess)) s = format (s, " static translation\n"); else s = format (s, " dynamic translation\n"); return s; } u8 * format_nat44_ei_user (u8 *s, va_list *args) { nat44_ei_main_per_thread_data_t *tnm = va_arg (*args, nat44_ei_main_per_thread_data_t *); nat44_ei_user_t *u = va_arg (*args, nat44_ei_user_t *); int verbose = va_arg (*args, int); dlist_elt_t *head, *elt; u32 elt_index, head_index; u32 session_index; nat44_ei_session_t *sess; s = format (s, "%U: %d dynamic translations, %d static translations\n", format_ip4_address, &u->addr, u->nsessions, u->nstaticsessions); if (verbose == 0) return s; if (u->nsessions || u->nstaticsessions) { head_index = u->sessions_per_user_list_head_index; head = pool_elt_at_index (tnm->list_pool, head_index); elt_index = head->next; elt = pool_elt_at_index (tnm->list_pool, elt_index); session_index = elt->value; while (session_index != ~0) { sess = pool_elt_at_index (tnm->sessions, session_index); s = format (s, " %U\n", format_nat44_ei_session, tnm, sess); elt_index = elt->next; elt = pool_elt_at_index (tnm->list_pool, elt_index); session_index = elt->value; } } return s; } u8 * format_nat44_ei_static_mapping (u8 *s, va_list *args) { nat44_ei_static_mapping_t *m = va_arg (*args, nat44_ei_static_mapping_t *); nat44_ei_lb_addr_port_t *local; if (is_sm_identity_nat (m->flags)) { if (is_sm_addr_only (m->flags)) s = format (s, "identity mapping %U", format_ip4_address, &m->local_addr); else s = format (s, "identity mapping %U %U:%d", format_nat_protocol, m->proto, format_ip4_address, &m->local_addr, clib_net_to_host_u16 (m->local_port)); pool_foreach (local, m->locals) { s = format (s, " vrf %d", local->vrf_id); } return s; } if (is_sm_addr_only (m->flags)) { s = format (s, "local %U external %U vrf %d", format_ip4_address, &m->local_addr, format_ip4_address, &m->external_addr, m->vrf_id); } else { s = format (s, "%U local %U:%d external %U:%d vrf %d", format_nat_protocol, m->proto, format_ip4_address, &m->local_addr, clib_net_to_host_u16 (m->local_port), format_ip4_address, &m->external_addr, clib_net_to_host_u16 (m->external_port), m->vrf_id); } return s; } u8 * format_nat44_ei_static_map_to_resolve (u8 *s, va_list *args) { nat44_ei_static_map_resolve_t *m = va_arg (*args, nat44_ei_static_map_resolve_t *); vnet_main_t *vnm = vnet_get_main (); if (is_sm_addr_only (m->flags)) s = format (s, "local %U external %U vrf %d", format_ip4_address, &m->l_addr, format_vnet_sw_if_index_name, vnm, m->sw_if_index, m->vrf_id); else s = format (s, "%U local %U:%d external %U:%d vrf %d", format_nat_protocol, m->proto, format_ip4_address, &m->l_addr, clib_net_to_host_u16 (m->l_port), format_vnet_sw_if_index_name, vnm, m->sw_if_index, clib_net_to_host_u16 (m->e_port), m->vrf_id); return s; } static clib_error_t * nat44_ei_enable_disable_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { nat44_ei_main_t *nm = &nat44_ei_main; unformat_input_t _line_input, *line_input = &_line_input; clib_error_t *error = 0; nat44_ei_config_t c = { 0 }; u8 enable_set = 0, enable = 0, mode_set = 0; if (!unformat_user (input, unformat_line_input, line_input)) return clib_error_return (0, NAT44_EI_EXPECTED_ARGUMENT); while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (!mode_set && unformat (line_input, "static-mapping-only")) { mode_set = 1; c.static_mapping_only = 1; if (unformat (line_input, "connection-tracking")) { c.connection_tracking = 1; } } else if (!mode_set && unformat (line_input, "out2in-dpo")) { mode_set = 1; c.out2in_dpo = 1; } else if (unformat (line_input, "inside-vrf %u", &c.inside_vrf)) ; else if (unformat (line_input, "outside-vrf %u", &c.outside_vrf)) ; else if (unformat (line_input, "users %u", &c.users)) ; else if (unformat (line_input, "sessions %u", &c.sessions)) ; else if (unformat (line_input, "user-sessions %u", &c.user_sessions)) ; else if (!enable_set) { enable_set = 1; if (unformat (line_input, "disable")) ; else if (unformat (line_input, "enable")) enable = 1; } else { error = clib_error_return (0, "unknown input '%U'", format_unformat_error, line_input); goto done; } } if (!enable_set) { error = clib_error_return (0, "expected enable | disable"); goto done; } if (enable) { if (nm->enabled) { error = clib_error_return (0, "already enabled"); goto done; } if (nat44_ei_plugin_enable (c) != 0) error = clib_error_return (0, "enable failed"); } else { if (!nm->enabled) { error = clib_error_return (0, "already disabled"); goto done; } if (nat44_ei_plugin_disable () != 0) error = clib_error_return (0, "disable failed"); } done: unformat_free (line_input); return error; } static clib_error_t * set_workers_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { unformat_input_t _line_input, *line_input = &_line_input; uword *bitmap = 0; int rv = 0; clib_error_t *error = 0; if (!unformat_user (input, unformat_line_input, line_input)) return clib_error_return (0, NAT44_EI_EXPECTED_ARGUMENT); while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "%U", unformat_bitmap_list, &bitmap)) ; else { error = clib_error_return (0, "unknown input '%U'", format_unformat_error, line_input); goto done; } } if (bitmap == 0) { error = clib_error_return (0, "List of workers must be specified."); goto done; } rv = nat44_ei_set_workers (bitmap); clib_bitmap_free (bitmap); switch (rv) { case VNET_API_ERROR_INVALID_WORKER: error = clib_error_return (0, "Invalid worker(s)."); goto done; case VNET_API_ERROR_FEATURE_DISABLED: error = clib_error_return (0, "Supported only if 2 or more workes available."); goto done; default: break; } done: unformat_free (line_input); return error; } static clib_error_t * nat_show_workers_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { nat44_ei_main_t *nm = &nat44_ei_main; u32 *worker; if (nm->num_workers > 1) { vlib_cli_output (vm, "%d workers", vec_len (nm->workers)); vec_foreach (worker, nm->workers) { vlib_worker_thread_t *w = vlib_worker_threads + *worker + nm->first_worker_index; vlib_cli_output (vm, " %s", w->name); } } return 0; } static clib_error_t * nat44_ei_set_log_level_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { unformat_input_t _line_input, *line_input = &_line_input; nat44_ei_main_t *nm = &nat44_ei_main; u32 log_level = NAT_LOG_NONE; clib_error_t *error = 0; if (!unformat_user (input, unformat_line_input, line_input)) return clib_error_return (0, NAT44_EI_EXPECTED_ARGUMENT); if (!unformat (line_input, "%d", &log_level)) { error = clib_error_return (0, "unknown input '%U'", format_unformat_error, line_input); goto done; } if (log_level > NAT_LOG_DEBUG) { error = clib_error_return (0, "unknown logging level '%d'", log_level); goto done; } nm->log_level = log_level; done: unformat_free (line_input); return error; } static clib_error_t * nat44_ei_ipfix_logging_enable_disable_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { unformat_input_t _line_input, *line_input = &_line_input; clib_error_t *error = 0; u32 domain_id = 0, src_port = 0; u8 enable_set = 0, enable = 0; if (!unformat_user (input, unformat_line_input, line_input)) return clib_error_return (0, NAT44_EI_EXPECTED_ARGUMENT); while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "domain %d", &domain_id)) ; else if (unformat (line_input, "src-port %d", &src_port)) ; else if (unformat (line_input, "disable")) enable = 0; else if (!enable_set) { enable_set = 1; if (unformat (line_input, "disable")) ; else if (unformat (line_input, "enable")) enable = 1; } else { error = clib_error_return (0, "unknown input '%U'", format_unformat_error, line_input); goto done; } } if (!enable_set) { error = clib_error_return (0, "expected enable | disable"); goto done; } if (nat_ipfix_logging_enable_disable (enable, domain_id, (u16) src_port)) { error = clib_error_return (0, "ipfix logging enable failed"); goto done; } done: unformat_free (line_input); return error; } static clib_error_t * nat44_ei_show_hash_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { nat44_ei_main_t *nm = &nat44_ei_main; nat44_ei_main_per_thread_data_t *tnm; int i; int verbose = 0; if (unformat (input, "detail")) verbose = 1; else if (unformat (input, "verbose")) verbose = 2; vlib_cli_output (vm, "%U", format_bihash_8_8, &nm->static_mapping_by_local, verbose); vlib_cli_output (vm, "%U", format_bihash_8_8, &nm->static_mapping_by_external, verbose); vec_foreach_index (i, nm->per_thread_data) { tnm = vec_elt_at_index (nm->per_thread_data, i); vlib_cli_output (vm, "-------- thread %d %s --------\n", i, vlib_worker_threads[i].name); vlib_cli_output (vm, "%U", format_bihash_8_8, &nm->in2out, verbose); vlib_cli_output (vm, "%U", format_bihash_8_8, &nm->out2in, verbose); vlib_cli_output (vm, "%U", format_bihash_8_8, &tnm->user_hash, verbose); } vlib_cli_output (vm, "-------- hash table parameters --------\n"); vlib_cli_output (vm, "translation buckets: %u", nm->translation_buckets); vlib_cli_output (vm, "user buckets: %u", nm->user_buckets); return 0; } static clib_error_t * nat44_ei_set_alloc_addr_and_port_alg_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { unformat_input_t _line_input, *line_input = &_line_input; clib_error_t *error = 0; u32 psid, psid_offset, psid_length, port_start, port_end; if (!unformat_user (input, unformat_line_input, line_input)) return clib_error_return (0, NAT44_EI_EXPECTED_ARGUMENT); while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "default")) nat44_ei_set_alloc_default (); else if (unformat (line_input, "map-e psid %d psid-offset %d psid-len %d", &psid, &psid_offset, &psid_length)) nat44_ei_set_alloc_mape ((u16) psid, (u16) psid_offset, (u16) psid_length); else if (unformat (line_input, "port-range %d - %d", &port_start, &port_end)) { if (port_end <= port_start) { error = clib_error_return ( 0, "The end-port must be greater than start-port"); goto done; } nat44_ei_set_alloc_range ((u16) port_start, (u16) port_end); } else { error = clib_error_return (0, "unknown input '%U'", format_unformat_error, line_input); goto done; } } done: unformat_free (line_input); return error; }; u8 * format_nat44_ei_addr_and_port_alloc_alg (u8 *s, va_list *args) { u32 i = va_arg (*args, u32); u8 *t = 0; switch (i) { #define _(v, N, s) \ case NAT44_EI_ADDR_AND_PORT_ALLOC_ALG_##N: \ t = (u8 *) s; \ break; foreach_nat44_ei_addr_and_port_alloc_alg #undef _ default : s = format (s, "unknown"); return s; } s = format (s, "%s", t); return s; } static clib_error_t * nat44_ei_show_alloc_addr_and_port_alg_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { nat44_ei_main_t *nm = &nat44_ei_main; vlib_cli_output (vm, "NAT address and port: %U", format_nat44_ei_addr_and_port_alloc_alg, nm->addr_and_port_alloc_alg); switch (nm->addr_and_port_alloc_alg) { case NAT44_EI_ADDR_AND_PORT_ALLOC_ALG_MAPE: vlib_cli_output (vm, " psid %d psid-offset %d psid-len %d", nm->psid, nm->psid_offset, nm->psid_length); break; case NAT44_EI_ADDR_AND_PORT_ALLOC_ALG_RANGE: vlib_cli_output (vm, " start-port %d end-port %d", nm->start_port, nm->end_port); break; default: break; } return 0; } static clib_error_t * nat_set_mss_clamping_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { unformat_input_t _line_input, *line_input = &_line_input; nat44_ei_main_t *nm = &nat44_ei_main; clib_error_t *error = 0; u32 mss; if (!unformat_user (input, unformat_line_input, line_input)) return clib_error_return (0, NAT44_EI_EXPECTED_ARGUMENT); while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "disable")) nm->mss_clamping = 0; else if (unformat (line_input, "%d", &mss)) nm->mss_clamping = (u16) mss; else { error = clib_error_return (0, "unknown input '%U'", format_unformat_error, line_input); goto done; } } done: unformat_free (line_input); return error; } static clib_error_t * nat_show_mss_clamping_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { nat44_ei_main_t *nm = &nat44_ei_main; if (nm->mss_clamping) vlib_cli_output (vm, "mss-clamping %d", nm->mss_clamping); else vlib_cli_output (vm, "mss-clamping disabled"); return 0; } static clib_error_t * nat_ha_failover_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { unformat_input_t _line_input, *line_input = &_line_input; ip4_address_t addr; u32 port, session_refresh_interval = 10; int rv; clib_error_t *error = 0; if (!unformat_user (input, unformat_line_input, line_input)) return clib_error_return (0, NAT44_EI_EXPECTED_ARGUMENT); while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "%U:%u", unformat_ip4_address, &addr, &port)) ; else if (unformat (line_input, "refresh-interval %u", &session_refresh_interval)) ; else { error = clib_error_return (0, "unknown input '%U'", format_unformat_error, line_input); goto done; } } rv = nat_ha_set_failover (vm, &addr, (u16) port, session_refresh_interval); if (rv) error = clib_error_return (0, "set HA failover failed"); done: unformat_free (line_input); return error; } static clib_error_t * nat_ha_listener_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { unformat_input_t _line_input, *line_input = &_line_input; ip4_address_t addr; u32 port, path_mtu = 512; int rv; clib_error_t *error = 0; if (!unformat_user (input, unformat_line_input, line_input)) return clib_error_return (0, NAT44_EI_EXPECTED_ARGUMENT); while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "%U:%u", unformat_ip4_address, &addr, &port)) ; else if (unformat (line_input, "path-mtu %u", &path_mtu)) ; else { error = clib_error_return (0, "unknown input '%U'", format_unformat_error, line_input); goto done; } } rv = nat_ha_set_listener (vm, &addr, (u16) port, path_mtu); if (rv) error = clib_error_return (0, "set HA listener failed"); done: unformat_free (line_input); return error; } static clib_error_t * nat_show_ha_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { ip4_address_t addr; u16 port; u32 path_mtu, session_refresh_interval, resync_ack_missed; u8 in_resync; nat_ha_get_listener (&addr, &port, &path_mtu); if (!port) { vlib_cli_output (vm, "NAT HA disabled\n"); return 0; } vlib_cli_output (vm, "LISTENER:\n"); vlib_cli_output (vm, " %U:%u path-mtu %u\n", format_ip4_address, &addr, port, path_mtu); nat_ha_get_failover (&addr, &port, &session_refresh_interval); vlib_cli_output (vm, "FAILOVER:\n"); if (port) vlib_cli_output (vm, " %U:%u refresh-interval %usec\n", format_ip4_address, &addr, port, session_refresh_interval); else vlib_cli_output (vm, " NA\n"); nat_ha_get_resync_status (&in_resync, &resync_ack_missed); vlib_cli_output (vm, "RESYNC:\n"); if (in_resync) vlib_cli_output (vm, " in progress\n"); else vlib_cli_output (vm, " completed (%d ACK missed)\n", resync_ack_missed); return 0; } static clib_error_t * nat_ha_flush_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { nat_ha_flush (0); return 0; } static clib_error_t * nat_ha_resync_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { clib_error_t *error = 0; if (nat_ha_resync (0, 0, 0)) error = clib_error_return (0, "NAT HA resync already running"); return error; } static clib_error_t * add_address_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { unformat_input_t _line_input, *line_input = &_line_input; nat44_ei_main_t *nm = &nat44_ei_main; ip4_address_t start_addr, end_addr, this_addr; u32 start_host_order, end_host_order; u32 vrf_id = ~0; int i, count; int is_add = 1; int rv = 0; clib_error_t *error = 0; if (!unformat_user (input, unformat_line_input, line_input)) return clib_error_return (0, NAT44_EI_EXPECTED_ARGUMENT); while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "%U - %U", unformat_ip4_address, &start_addr, unformat_ip4_address, &end_addr)) ; else if (unformat (line_input, "tenant-vrf %u", &vrf_id)) ; else if (unformat (line_input, "%U", unformat_ip4_address, &start_addr)) end_addr = start_addr; else if (unformat (line_input, "del")) is_add = 0; else { error = clib_error_return (0, "unknown input '%U'", format_unformat_error, line_input); goto done; } } if (nm->static_mapping_only) { error = clib_error_return (0, "static mapping only mode"); goto done; } start_host_order = clib_host_to_net_u32 (start_addr.as_u32); end_host_order = clib_host_to_net_u32 (end_addr.as_u32); if (end_host_order < start_host_order) { error = clib_error_return (0, "end address less than start address"); goto done; } count = (end_host_order - start_host_order) + 1; if (count > 1024) nat44_ei_log_info ("%U - %U, %d addresses...", format_ip4_address, &start_addr, format_ip4_address, &end_addr, count); this_addr = start_addr; for (i = 0; i < count; i++) { if (is_add) rv = nat44_ei_add_address (&this_addr, vrf_id); else rv = nat44_ei_del_address (this_addr, 0); switch (rv) { case VNET_API_ERROR_VALUE_EXIST: error = clib_error_return (0, "NAT address already in use."); goto done; case VNET_API_ERROR_NO_SUCH_ENTRY: error = clib_error_return (0, "NAT address not exist."); goto done; case VNET_API_ERROR_UNSPECIFIED: error = clib_error_return (0, "NAT address used in static mapping."); goto done; case VNET_API_ERROR_FEATURE_DISABLED: goto done; default: break; } if (nm->out2in_dpo) nat44_ei_add_del_address_dpo (this_addr, is_add); increment_v4_address (&this_addr); } done: unformat_free (line_input); return error; } static clib_error_t * nat44_ei_show_addresses_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { nat44_ei_main_t *nm = &nat44_ei_main; nat44_ei_address_t *ap; vlib_cli_output (vm, "NAT44 pool addresses:"); vec_foreach (ap, nm->addresses) { vlib_cli_output (vm, "%U", format_ip4_address, &ap->addr); if (ap->fib_index != ~0) vlib_cli_output ( vm, " tenant VRF: %u", fib_table_get (ap->fib_index, FIB_PROTOCOL_IP4)->ft_table_id); else vlib_cli_output (vm, " tenant VRF independent"); #define _(N, i, n, s) \ vlib_cli_output (vm, " %d busy %s ports", ap->busy_ports[i], s); foreach_nat_protocol #undef _ } return 0; } static clib_error_t * nat44_ei_feature_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { unformat_input_t _line_input, *line_input = &_line_input; vnet_main_t *vnm = vnet_get_main (); clib_error_t *error = 0; u32 sw_if_index; u32 *inside_sw_if_indices = 0; u32 *outside_sw_if_indices = 0; u8 is_output_feature = 0; int i, rv, is_del = 0; sw_if_index = ~0; if (!unformat_user (input, unformat_line_input, line_input)) return clib_error_return (0, NAT44_EI_EXPECTED_ARGUMENT); while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "in %U", unformat_vnet_sw_interface, vnm, &sw_if_index)) vec_add1 (inside_sw_if_indices, sw_if_index); else if (unformat (line_input, "out %U", unformat_vnet_sw_interface, vnm, &sw_if_index)) vec_add1 (outside_sw_if_indices, sw_if_index); else if (unformat (line_input, "output-feature")) is_output_feature = 1; else if (unformat (line_input, "del")) is_del = 1; else { error = clib_error_return (0, "unknown input '%U'", format_unformat_error, line_input); goto done; } } if (vec_len (inside_sw_if_indices)) { for (i = 0; i < vec_len (inside_sw_if_indices); i++) { sw_if_index = inside_sw_if_indices[i]; if (is_output_feature) { if (is_del) { rv = nat44_ei_del_output_interface (sw_if_index); } else { rv = nat44_ei_add_output_interface (sw_if_index); } if (rv) { error = clib_error_return ( 0, "%s %U failed", is_del ? "del" : "add", format_vnet_sw_if_index_name, vnm, sw_if_index); goto done; } } else { if (is_del) { rv = nat44_ei_del_interface (sw_if_index, 1); } else { rv = nat44_ei_add_interface (sw_if_index, 1); } if (rv) { error = clib_error_return ( 0, "%s %U failed", is_del ? "del" : "add", format_vnet_sw_if_index_name, vnm, sw_if_index); goto done; } } } } if (vec_len (outside_sw_if_indices)) { for (i = 0; i < vec_len (outside_sw_if_indices); i++) { sw_if_index = outside_sw_if_indices[i]; if (is_output_feature) { if (is_del) { rv = nat44_ei_del_output_interface (sw_if_index); } else { rv = nat44_ei_add_output_interface (sw_if_index); } if (rv) { error = clib_error_return ( 0, "%s %U failed", is_del ? "del" : "add", format_vnet_sw_if_index_name, vnm, sw_if_index); goto done; } } else { if (is_del) { rv = nat44_ei_del_interface (sw_if_index, 0); } else { rv = nat44_ei_add_interface (sw_if_index, 0); } if (rv) { error = clib_error_return ( 0, "%s %U failed", is_del ? "del" : "add", format_vnet_sw_if_index_name, vnm, sw_if_index); goto done; } } } } done: unformat_free (line_input); vec_free (inside_sw_if_indices); vec_free (outside_sw_if_indices); return error; } static clib_error_t * nat44_ei_show_interfaces_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { nat44_ei_main_t *nm = &nat44_ei_main; nat44_ei_interface_t *i; vnet_main_t *vnm = vnet_get_main (); vlib_cli_output (vm, "NAT44 interfaces:"); pool_foreach (i, nm->interfaces) { vlib_cli_output (vm, " %U %s", format_vnet_sw_if_index_name, vnm, i->sw_if_index, (nat44_ei_interface_is_inside (i) && nat44_ei_interface_is_outside (i)) ? "in out" : (nat44_ei_interface_is_inside (i) ? "in" : "out")); } pool_foreach (i, nm->output_feature_interfaces) { vlib_cli_output (vm, " %U output-feature %s", format_vnet_sw_if_index_name, vnm, i->sw_if_index, (nat44_ei_interface_is_inside (i) && nat44_ei_interface_is_outside (i)) ? "in out" : (nat44_ei_interface_is_inside (i) ? "in" : "out")); } return 0; } static clib_error_t * add_static_mapping_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { unformat_input_t _line_input, *line_input = &_line_input; vnet_main_t *vnm = vnet_get_main (); clib_error_t *error = 0; int rv; nat_protocol_t proto = NAT_PROTOCOL_OTHER; ip4_address_t l_addr, e_addr, pool_addr = { 0 }; u32 l_port = 0, e_port = 0, vrf_id = ~0; u8 l_port_set = 0, e_port_set = 0; u32 sw_if_index = ~0, flags = 0; int is_add = 1; if (!unformat_user (input, unformat_line_input, line_input)) return clib_error_return (0, NAT44_EI_EXPECTED_ARGUMENT); while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "local %U %u", unformat_ip4_address, &l_addr, &l_port)) { l_port_set = 1; } else if (unformat (line_input, "local %U", unformat_ip4_address, &l_addr)) ; else if (unformat (line_input, "external %U %u", unformat_ip4_address, &e_addr, &e_port)) { e_port_set = 1; } else if (unformat (line_input, "external %U", unformat_ip4_address, &e_addr)) ; else if (unformat (line_input, "external %U %u", unformat_vnet_sw_interface, vnm, &sw_if_index, &e_port)) { e_port_set = 1; } else if (unformat (line_input, "external %U", unformat_vnet_sw_interface, vnm, &sw_if_index)) ; else if (unformat (line_input, "vrf %u", &vrf_id)) ; else if (unformat (line_input, "%U", unformat_nat_protocol, &proto)) ; else if (unformat (line_input, "del")) { is_add = 0; } else { error = clib_error_return (0, "unknown input: '%U'", format_unformat_error, line_input); goto done; } } if (l_port_set != e_port_set) { error = clib_error_return (0, "Either both ports are set or none."); goto done; } if (!l_port_set) { flags |= NAT44_EI_SM_FLAG_ADDR_ONLY; } else { l_port = clib_host_to_net_u16 (l_port); e_port = clib_host_to_net_u16 (e_port); } if (sw_if_index != ~0) { flags |= NAT44_EI_SM_FLAG_SWITCH_ADDRESS; } if (is_add) { rv = nat44_ei_add_static_mapping (l_addr, e_addr, l_port, e_port, proto, vrf_id, sw_if_index, flags, pool_addr, 0); } else { rv = nat44_ei_del_static_mapping (l_addr, e_addr, l_port, e_port, proto, vrf_id, sw_if_index, flags); } switch (rv) { case VNET_API_ERROR_INVALID_VALUE: error = clib_error_return (0, "External port already in use."); goto done; case VNET_API_ERROR_NO_SUCH_ENTRY: if (is_add) error = clib_error_return (0, "External address must be allocated."); else error = clib_error_return (0, "Mapping not exist."); goto done; case VNET_API_ERROR_NO_SUCH_FIB: error = clib_error_return (0, "No such VRF id."); goto done; case VNET_API_ERROR_VALUE_EXIST: error = clib_error_return (0, "Mapping already exist."); goto done; case VNET_API_ERROR_FEATURE_DISABLED: goto done; default: break; } done: unformat_free (line_input); return error; } static clib_error_t * add_identity_mapping_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { unformat_input_t _line_input, *line_input = &_line_input; vnet_main_t *vnm = vnet_get_main (); clib_error_t *error = 0; int rv, is_add = 1, port_set = 0; u32 sw_if_index = ~0, port, flags, vrf_id = ~0; nat_protocol_t proto = NAT_PROTOCOL_OTHER; ip4_address_t addr; flags = NAT44_EI_SM_FLAG_IDENTITY_NAT; if (!unformat_user (input, unformat_line_input, line_input)) return clib_error_return (0, NAT44_EI_EXPECTED_ARGUMENT); while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "%U", unformat_ip4_address, &addr)) ; else if (unformat (line_input, "external %U", unformat_vnet_sw_interface, vnm, &sw_if_index)) ; else if (unformat (line_input, "vrf %u", &vrf_id)) ; else if (unformat (line_input, "%U %u", unformat_nat_protocol, &proto, &port)) { port_set = 1; } else if (unformat (line_input, "del")) { is_add = 0; } else { error = clib_error_return (0, "unknown input: '%U'", format_unformat_error, line_input); goto done; } } if (!port_set) { flags |= NAT44_EI_SM_FLAG_ADDR_ONLY; } else { port = clib_host_to_net_u16 (port); } if (sw_if_index != ~0) { flags |= NAT44_EI_SM_FLAG_SWITCH_ADDRESS; } if (is_add) { rv = nat44_ei_add_static_mapping (addr, addr, port, port, proto, vrf_id, sw_if_index, flags, addr, 0); } else { rv = nat44_ei_del_static_mapping (addr, addr, port, port, proto, vrf_id, sw_if_index, flags); } switch (rv) { case VNET_API_ERROR_INVALID_VALUE: error = clib_error_return (0, "External port already in use."); goto done; case VNET_API_ERROR_NO_SUCH_ENTRY: if (is_add) error = clib_error_return (0, "External address must be allocated."); else error = clib_error_return (0, "Mapping not exist."); goto done; case VNET_API_ERROR_NO_SUCH_FIB: error = clib_error_return (0, "No such VRF id."); goto done; case VNET_API_ERROR_VALUE_EXIST: error = clib_error_return (0, "Mapping already exist."); goto done; default: break; } done: unformat_free (line_input); return error; } static clib_error_t * nat44_ei_show_static_mappings_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { nat44_ei_main_t *nm = &nat44_ei_main; nat44_ei_static_mapping_t *m; nat44_ei_static_map_resolve_t *rp; vlib_cli_output (vm, "NAT44 static mappings:"); pool_foreach (m, nm->static_mappings) { vlib_cli_output (vm, " %U", format_nat44_ei_static_mapping, m); } vec_foreach (rp, nm->to_resolve) vlib_cli_output (vm, " %U", format_nat44_ei_static_map_to_resolve, rp); return 0; } static clib_error_t * nat44_ei_add_interface_address_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { unformat_input_t _line_input, *line_input = &_line_input; nat44_ei_main_t *nm = &nat44_ei_main; clib_error_t *error = 0; int rv, is_del = 0; u32 sw_if_index; if (!unformat_user (input, unformat_line_input, line_input)) return clib_error_return (0, NAT44_EI_EXPECTED_ARGUMENT); while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "%U", unformat_vnet_sw_interface, nm->vnet_main, &sw_if_index)) ; else if (unformat (line_input, "del")) { is_del = 1; } else { error = clib_error_return (0, "unknown input '%U'", format_unformat_error, line_input); goto done; } } if (!is_del) { rv = nat44_ei_add_interface_address (sw_if_index); if (rv) { error = clib_error_return (0, "add address returned %d", rv); } } else { rv = nat44_ei_del_interface_address (sw_if_index); if (rv) { error = clib_error_return (0, "del address returned %d", rv); } } done: unformat_free (line_input); return error; } static clib_error_t * nat44_ei_show_interface_address_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { nat44_ei_main_t *nm = &nat44_ei_main; vnet_main_t *vnm = vnet_get_main (); u32 *sw_if_index; vlib_cli_output (vm, "NAT44 pool address interfaces:"); vec_foreach (sw_if_index, nm->auto_add_sw_if_indices) { vlib_cli_output (vm, " %U", format_vnet_sw_if_index_name, vnm, *sw_if_index); } return 0; } static clib_error_t * nat44_ei_show_sessions_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { unformat_input_t _line_input, *line_input = &_line_input; clib_error_t *error = 0; ip4_address_t saddr; u8 filter_saddr = 0; nat44_ei_main_per_thread_data_t *tnm; nat44_ei_main_t *nm = &nat44_ei_main; int detail = 0; int i = 0; if (!unformat_user (input, unformat_line_input, line_input)) goto print; while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "detail")) detail = 1; else if (unformat (line_input, "filter saddr %U", unformat_ip4_address, &saddr)) filter_saddr = 1; else { error = clib_error_return (0, "unknown input '%U'", format_unformat_error, line_input); break; } } unformat_free (line_input); print: vlib_cli_output (vm, "NAT44 sessions:"); vec_foreach_index (i, nm->per_thread_data) { tnm = vec_elt_at_index (nm->per_thread_data, i); vlib_cli_output (vm, "-------- thread %d %s: %d sessions --------\n", i, vlib_worker_threads[i].name, pool_elts (tnm->sessions)); nat44_ei_user_t *u; pool_foreach (u, tnm->users) { if (filter_saddr && saddr.as_u32 != u->addr.as_u32) continue; vlib_cli_output (vm, " %U", format_nat44_ei_user, tnm, u, detail); } } return error; } static clib_error_t * nat44_ei_del_user_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { unformat_input_t _line_input, *line_input = &_line_input; clib_error_t *error = 0; ip4_address_t addr; u32 fib_index = 0; int rv; if (!unformat_user (input, unformat_line_input, line_input)) return clib_error_return (0, NAT44_EI_EXPECTED_ARGUMENT); while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "%U", unformat_ip4_address, &addr)) ; else if (unformat (line_input, "fib %u", &fib_index)) ; else { error = clib_error_return (0, "unknown input '%U'", format_unformat_error, line_input); goto done; } } rv = nat44_ei_user_del (&addr, fib_index); if (!rv) { error = clib_error_return (0, "nat44_ei_user_del returned %d", rv); } done: unformat_free (line_input); return error; } static clib_error_t * nat44_ei_clear_sessions_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { clib_error_t *error = 0; nat44_ei_sessions_clear (); return error; } static clib_error_t * nat44_ei_del_session_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { nat44_ei_main_t *nm = &nat44_ei_main; unformat_input_t _line_input, *line_input = &_line_input; u32 port = 0, vrf_id = nm->outside_vrf_id; clib_error_t *error = 0; nat_protocol_t proto; ip4_address_t addr; int rv, is_in = 0; if (!unformat_user (input, unformat_line_input, line_input)) return clib_error_return (0, NAT44_EI_EXPECTED_ARGUMENT); while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "%U:%u %U", unformat_ip4_address, &addr, &port, unformat_nat_protocol, &proto)) ; else if (unformat (line_input, "in")) { is_in = 1; vrf_id = nm->inside_vrf_id; } else if (unformat (line_input, "out")) { is_in = 0; vrf_id = nm->outside_vrf_id; } else if (unformat (line_input, "vrf %u", &vrf_id)) ; else { error = clib_error_return (0, "unknown input '%U'", format_unformat_error, line_input); goto done; } } rv = nat44_ei_del_session (nm, &addr, clib_host_to_net_u16 (port), proto, vrf_id, is_in); switch (rv) { case 0: break; default: error = clib_error_return (0, "nat44_ei_del_session returned %d", rv); goto done; } done: unformat_free (line_input); return error; } static clib_error_t * nat44_ei_forwarding_set_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { nat44_ei_main_t *nm = &nat44_ei_main; unformat_input_t _line_input, *line_input = &_line_input; clib_error_t *error = 0; u8 enable_set = 0, enable = 0; if (!unformat_user (input, unformat_line_input, line_input)) return clib_error_return (0, NAT44_EI_EXPECTED_ARGUMENT); while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (!enable_set) { enable_set = 1; if (unformat (line_input, "disable")) ; else if (unformat (line_input, "enable")) enable = 1; } else { error = clib_error_return (0, "unknown input '%U'", format_unformat_error, line_input); goto done; } } if (!enable_set) error = clib_error_return (0, "expected enable | disable"); else nm->forwarding_enabled = enable; done: unformat_free (line_input); return error; } static clib_error_t * set_timeout_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { nat44_ei_main_t *nm = &nat44_ei_main; unformat_input_t _line_input, *line_input = &_line_input; clib_error_t *error = 0; if (!unformat_user (input, unformat_line_input, line_input)) return clib_error_return (0, NAT44_EI_EXPECTED_ARGUMENT); while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "udp %u", &nm->timeouts.udp)) ; else if (unformat (line_input, "tcp-established %u", &nm->timeouts.tcp.established)) ; else if (unformat (line_input, "tcp-transitory %u", &nm->timeouts.tcp.transitory)) ; else if (unformat (line_input, "icmp %u", &nm->timeouts.icmp)) ; else if (unformat (line_input, "reset")) nat_reset_timeouts (&nm->timeouts); else { error = clib_error_return (0, "unknown input '%U'", format_unformat_error, line_input); goto done; } } done: unformat_free (line_input); return error; } static clib_error_t * nat_show_timeouts_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) { nat44_ei_main_t *nm = &nat44_ei_main; vlib_cli_output (vm, "udp timeout: %dsec", nm->timeouts.udp); vlib_cli_output (vm, "tcp-established timeout: %dsec", nm->timeouts.tcp.established); vlib_cli_output (vm, "tcp-transitory timeout: %dsec", nm->timeouts.tcp.transitory); vlib_cli_output (vm, "icmp timeout: %dsec", nm->timeouts.icmp); return 0; } /*? * @cliexpar * @cliexstart{nat44 ei} * Enable nat44 ei plugin * To enable nat44-ei, use: * vpp# nat44 ei plugin enable * To disable nat44-ei, use: * vpp# nat44 ei plugin disable * To enable nat44 ei static mapping only, use: * vpp# nat44 ei plugin enable static-mapping * To enable nat44 ei static mapping with connection tracking, use: * vpp# nat44 ei plugin enable static-mapping connection-tracking * To enable nat44 ei out2in dpo, use: * vpp# nat44 ei plugin enable out2in-dpo * To set inside-vrf outside-vrf, use: * vpp# nat44 ei plugin enable inside-vrf <id> outside-vrf <id> * @cliexend ?*/ VLIB_CLI_COMMAND (nat44_ei_enable_disable_command, static) = { .path = "nat44 ei plugin", .short_help = "nat44 ei plugin <enable [sessions <max-number>] [users <max-number>] " "[static-mappig-only [connection-tracking]|out2in-dpo] [inside-vrf " "<vrf-id>] [outside-vrf <vrf-id>] [user-sessions <max-number>]>|disable", .function = nat44_ei_enable_disable_command_fn, }; /*? * @cliexpar * @cliexstart{set snat44 ei workers} * Set NAT workers if 2 or more workers available, use: * vpp# set snat44 ei workers 0-2,5 * @cliexend ?*/ VLIB_CLI_COMMAND (set_workers_command, static) = { .path = "set nat44 ei workers", .function = set_workers_command_fn, .short_help = "set nat44 ei workers <workers-list>", }; /*? * @cliexpar * @cliexstart{show nat44 ei workers} * Show NAT workers. * vpp# show nat44 ei workers: * 2 workers * vpp_wk_0 * vpp_wk_1 * @cliexend ?*/ VLIB_CLI_COMMAND (nat_show_workers_command, static) = { .path = "show nat44 ei workers", .short_help = "show nat44 ei workers", .function = nat_show_workers_command_fn, }; /*? * @cliexpar * @cliexstart{set nat44 ei timeout} * Set values of timeouts for NAT sessions (in seconds), use: * vpp# set nat44 ei timeout udp 120 tcp-established 7500 tcp-transitory 250 icmp 90 * To reset default values use: * vpp# set nat44 ei timeout reset * @cliexend ?*/ VLIB_CLI_COMMAND (set_timeout_command, static) = { .path = "set nat44 ei timeout", .function = set_timeout_command_fn, .short_help = "set nat44 ei timeout [udp <sec> | tcp-established <sec> " "tcp-transitory <sec> | icmp <sec> | reset]", }; /*? * @cliexpar * @cliexstart{show nat44 ei timeouts} * Show values of timeouts for NAT sessions. * vpp# show nat44 ei timeouts * udp timeout: 300sec * tcp-established timeout: 7440sec * tcp-transitory timeout: 240sec * icmp timeout: 60sec * @cliexend ?*/ VLIB_CLI_COMMAND (nat_show_timeouts_command, static) = { .path = "show nat44 ei timeouts", .short_help = "show nat44 ei timeouts", .function = nat_show_timeouts_command_fn, }; /*? * @cliexpar * @cliexstart{nat44 ei set logging level} * To set NAT logging level use: * Set nat44 ei logging level * @cliexend ?*/ VLIB_CLI_COMMAND (nat44_ei_set_log_level_command, static) = { .path = "nat44 ei set logging level", .function = nat44_ei_set_log_level_command_fn, .short_help = "nat44 ei set logging level <level>", }; /*? * @cliexpar * @cliexstart{snat44 ei ipfix logging} * To enable NAT IPFIX logging use: * vpp# nat44 ei ipfix logging * To set IPFIX exporter use: * vpp# set ipfix exporter collector 10.10.10.3 src 10.10.10.1 * @cliexend ?*/ VLIB_CLI_COMMAND (nat44_ei_ipfix_logging_enable_disable_command, static) = { .path = "nat44 ei ipfix logging", .function = nat44_ei_ipfix_logging_enable_disable_command_fn, .short_help = "nat44 ei ipfix logging <enable [domain <domain-id>] " "[src-port <port>]>|disable", }; /*? * @cliexpar * @cliexstart{nat44 ei addr-port-assignment-alg} * Set address and port assignment algorithm * For the MAP-E CE limit port choice based on PSID use: * vpp# nat44 ei addr-port-assignment-alg map-e psid 10 psid-offset 6 psid-len 6 * For port range use: * vpp# nat44 ei addr-port-assignment-alg port-range <start-port> - <end-port> * To set standard (default) address and port assignment algorithm use: * vpp# nat44 ei addr-port-assignment-alg default * @cliexend ?*/ VLIB_CLI_COMMAND (nat44_ei_set_alloc_addr_and_port_alg_command, static) = { .path = "nat44 ei addr-port-assignment-alg", .short_help = "nat44 ei addr-port-assignment-alg <alg-name> [<alg-params>]", .function = nat44_ei_set_alloc_addr_and_port_alg_command_fn, }; /*? * @cliexpar * @cliexstart{show nat44 ei addr-port-assignment-alg} * Show address and port assignment algorithm * @cliexend ?*/ VLIB_CLI_COMMAND (nat44_ei_show_alloc_addr_and_port_alg_command, static) = { .path = "show nat44 ei addr-port-assignment-alg", .short_help = "show nat44 ei addr-port-assignment-alg", .function = nat44_ei_show_alloc_addr_and_port_alg_command_fn, }; /*? * @cliexpar * @cliexstart{nat44 ei mss-clamping} * Set TCP MSS rewriting configuration * To enable TCP MSS rewriting use: * vpp# nat44 ei mss-clamping 1452 * To disbale TCP MSS rewriting use: * vpp# nat44 ei mss-clamping disable * @cliexend ?*/ VLIB_CLI_COMMAND (nat_set_mss_clamping_command, static) = { .path = "nat44 ei mss-clamping", .short_help = "nat44 ei mss-clamping <mss-value>|disable", .function = nat_set_mss_clamping_command_fn, }; /*? * @cliexpar * @cliexstart{show nat44 ei mss-clamping} * Show TCP MSS rewriting configuration * @cliexend ?*/ VLIB_CLI_COMMAND (nat_show_mss_clamping_command, static) = { .path = "show nat44 ei mss-clamping", .short_help = "show nat44 ei mss-clamping", .function = nat_show_mss_clamping_command_fn, }; /*? * @cliexpar * @cliexstart{nat44 ei ha failover} * Set HA failover (remote settings) * @cliexend ?*/ VLIB_CLI_COMMAND (nat_ha_failover_command, static) = { .path = "nat44 ei ha failover", .short_help = "nat44 ei ha failover <ip4-address>:<port> [refresh-interval <sec>]", .function = nat_ha_failover_command_fn, }; /*? * @cliexpar * @cliexstart{nat44 ei ha listener} * Set HA listener (local settings) * @cliexend ?*/ VLIB_CLI_COMMAND (nat_ha_listener_command, static) = { .path = "nat44 ei ha listener", .short_help = "nat44 ei ha listener <ip4-address>:<port> [path-mtu <path-mtu>]", .function = nat_ha_listener_command_fn, }; /*? * @cliexpar * @cliexstart{show nat44 ei ha} * Show HA configuration/status * @cliexend ?*/ VLIB_CLI_COMMAND (nat_show_ha_command, static) = { .path = "show nat44 ei ha", .short_help = "show nat44 ei ha", .function = nat_show_ha_command_fn, }; /*? * @cliexpar * @cliexstart{nat44 ei ha flush} * Flush the current HA data (for testing) * @cliexend ?*/ VLIB_CLI_COMMAND (nat_ha_flush_command, static) = { .path = "nat44 ei ha flush", .short_help = "nat44 ei ha flush", .function = nat_ha_flush_command_fn, }; /*? * @cliexpar * @cliexstart{nat44 ei ha resync} * Resync HA (resend existing sessions to new failover) * @cliexend ?*/ VLIB_CLI_COMMAND (nat_ha_resync_command, static) = { .path = "nat44 ei ha resync", .short_help = "nat44 ei ha resync", .function = nat_ha_resync_command_fn, }; /*? * @cliexpar * @cliexstart{show nat44 ei hash tables} * Show NAT44 hash tables * @cliexend ?*/ VLIB_CLI_COMMAND (nat44_ei_show_hash, static) = { .path = "show nat44 ei hash tables", .short_help = "show nat44 ei hash tables [detail|verbose]", .function = nat44_ei_show_hash_command_fn, }; /*? * @cliexpar * @cliexstart{nat44 ei add address} * Add/delete NAT44 pool address. * To add NAT44 pool address use: * vpp# nat44 ei add address 172.16.1.3 * vpp# nat44 ei add address 172.16.2.2 - 172.16.2.24 * To add NAT44 pool address for specific tenant (identified by VRF id) use: * vpp# nat44 ei add address 172.16.1.3 tenant-vrf 10 * @cliexend ?*/ VLIB_CLI_COMMAND (add_address_command, static) = { .path = "nat44 ei add address", .short_help = "nat44 ei add address <ip4-range-start> [- <ip4-range-end>] " "[tenant-vrf <vrf-id>] [del]", .function = add_address_command_fn, }; /*? * @cliexpar * @cliexstart{show nat44 ei addresses} * Show NAT44 pool addresses. * vpp# show nat44 ei addresses * NAT44 pool addresses: * 172.16.2.2 * tenant VRF independent * 10 busy udp ports * 0 busy tcp ports * 0 busy icmp ports * 172.16.1.3 * tenant VRF: 10 * 0 busy udp ports * 2 busy tcp ports * 0 busy icmp ports * @cliexend ?*/ VLIB_CLI_COMMAND (nat44_ei_show_addresses_command, static) = { .path = "show nat44 ei addresses", .short_help = "show nat44 ei addresses", .function = nat44_ei_show_addresses_command_fn, }; /*? * @cliexpar * @cliexstart{set interface nat44} * Enable/disable NAT44 feature on the interface. * To enable NAT44 feature with local network interface use: * vpp# set interface nat44 ei in GigabitEthernet0/8/0 * To enable NAT44 feature with external network interface use: * vpp# set interface nat44 ei out GigabitEthernet0/a/0 * @cliexend ?*/ VLIB_CLI_COMMAND (set_interface_nat44_ei_command, static) = { .path = "set interface nat44 ei", .function = nat44_ei_feature_command_fn, .short_help = "set interface nat44 ei in <intfc> out <intfc> [output-feature] " "[del]", }; /*? * @cliexpar * @cliexstart{show nat44 ei interfaces} * Show interfaces with NAT44 feature. * vpp# show nat44 ei interfaces * NAT44 interfaces: * GigabitEthernet0/8/0 in * GigabitEthernet0/a/0 out * @cliexend ?*/ VLIB_CLI_COMMAND (nat44_ei_show_interfaces_command, static) = { .path = "show nat44 ei interfaces", .short_help = "show nat44 ei interfaces", .function = nat44_ei_show_interfaces_command_fn, }; /*? * @cliexpar * @cliexstart{nat44 ei add static mapping} * Static mapping allows hosts on the external network to initiate connection * to to the local network host. * To create static mapping between local host address 10.0.0.3 port 6303 and * external address 4.4.4.4 port 3606 for TCP protocol use: * vpp# nat44 ei add static mapping tcp local 10.0.0.3 6303 external 4.4.4.4 3606 * If not runnig "static mapping only" NAT plugin mode use before: * vpp# nat44 ei add address 4.4.4.4 * To create address only static mapping between local and external address use: * vpp# nat44 ei add static mapping local 10.0.0.3 external 4.4.4.4 * To create ICMP static mapping between local and external with ICMP echo * identifier 10 use: * vpp# nat44 ei add static mapping icmp local 10.0.0.3 10 external 4.4.4.4 10 * @cliexend ?*/ VLIB_CLI_COMMAND (add_static_mapping_command, static) = { .path = "nat44 ei add static mapping", .function = add_static_mapping_command_fn, .short_help = "nat44 ei add static mapping tcp|udp|icmp local <addr> " "[<port|icmp-echo-id>] " "external <addr> [<port|icmp-echo-id>] [vrf <table-id>] [del]", }; /*? * @cliexpar * @cliexstart{nat44 ei add identity mapping} * Identity mapping translate an IP address to itself. * To create identity mapping for address 10.0.0.3 port 6303 for TCP protocol * use: * vpp# nat44 ei add identity mapping 10.0.0.3 tcp 6303 * To create identity mapping for address 10.0.0.3 use: * vpp# nat44 ei add identity mapping 10.0.0.3 * To create identity mapping for DHCP addressed interface use: * vpp# nat44 ei add identity mapping external GigabitEthernet0/a/0 tcp 3606 * @cliexend ?*/ VLIB_CLI_COMMAND (add_identity_mapping_command, static) = { .path = "nat44 ei add identity mapping", .function = add_identity_mapping_command_fn, .short_help = "nat44 ei add identity mapping <ip4-addr>|external <interface> " "[<protocol> <port>] [vrf <table-id>] [del]", }; /*? * @cliexpar * @cliexstart{show nat44 ei static mappings} * Show NAT44 static mappings. * vpp# show nat44 ei static mappings * NAT44 static mappings: * local 10.0.0.3 external 4.4.4.4 vrf 0 * tcp local 192.168.0.4:6303 external 4.4.4.3:3606 vrf 0 * tcp vrf 0 external 1.2.3.4:80 * local 10.100.10.10:8080 probability 80 * local 10.100.10.20:8080 probability 20 * tcp local 10.0.0.10:3603 external GigabitEthernet0/a/0:6306 vrf 10 * @cliexend ?*/ VLIB_CLI_COMMAND (nat44_ei_show_static_mappings_command, static) = { .path = "show nat44 ei static mappings", .short_help = "show nat44 ei static mappings", .function = nat44_ei_show_static_mappings_command_fn, }; /*? * @cliexpar * @cliexstart{nat44 ei add interface address} * Use NAT44 pool address from specific interfce * To add NAT44 pool address from specific interface use: * vpp# nat44 ei add interface address GigabitEthernet0/8/0 * @cliexend ?*/ VLIB_CLI_COMMAND (nat44_ei_add_interface_address_command, static) = { .path = "nat44 ei add interface address", .short_help = "nat44 ei add interface address <interface> [del]", .function = nat44_ei_add_interface_address_command_fn, }; /*? * @cliexpar * @cliexstart{show nat44 ei interface address} * Show NAT44 pool address interfaces * vpp# show nat44 ei interface address * NAT44 pool address interfaces: * GigabitEthernet0/a/0 * @cliexend ?*/ VLIB_CLI_COMMAND (nat44_ei_show_interface_address_command, static) = { .path = "show nat44 ei interface address", .short_help = "show nat44 ei interface address", .function = nat44_ei_show_interface_address_command_fn, }; /*? * @cliexpar * @cliexstart{show nat44 ei sessions} * Show NAT44 sessions. * @cliexend ?*/ VLIB_CLI_COMMAND (nat44_ei_show_sessions_command, static) = { .path = "show nat44 ei sessions", .short_help = "show nat44 ei sessions [detail] [filter saddr <ip>]", .function = nat44_ei_show_sessions_command_fn, }; /*? * @cliexpar * @cliexstart{nat44 ei del user} * To delete all NAT44 user sessions: * vpp# nat44 ei del user 10.0.0.3 * @cliexend ?*/ VLIB_CLI_COMMAND (nat44_ei_del_user_command, static) = { .path = "nat44 ei del user", .short_help = "nat44 ei del user <addr> [fib <index>]", .function = nat44_ei_del_user_command_fn, }; /*? * @cliexpar * @cliexstart{clear nat44 ei sessions} * To clear all NAT44 sessions * vpp# clear nat44 ei sessions * @cliexend ?*/ VLIB_CLI_COMMAND (nat44_ei_clear_sessions_command, static) = { .path = "clear nat44 ei sessions", .short_help = "clear nat44 ei sessions", .function = nat44_ei_clear_sessions_command_fn, }; /*? * @cliexpar * @cliexstart{nat44 ei del session} * To administratively delete NAT44 session by inside address and port use: * vpp# nat44 ei del session in 10.0.0.3:6303 tcp * To administratively delete NAT44 session by outside address and port use: * vpp# nat44 ei del session out 1.0.0.3:6033 udp * @cliexend ?*/ VLIB_CLI_COMMAND (nat44_ei_del_session_command, static) = { .path = "nat44 ei del session", .short_help = "nat44 ei del session in|out <addr>:<port> tcp|udp|icmp [vrf " "<id>] [external-host <addr>:<port>]", .function = nat44_ei_del_session_command_fn, }; /*? * @cliexpar * @cliexstart{nat44 ei forwarding} * Enable or disable forwarding * Forward packets which don't match existing translation * or static mapping instead of dropping them. * To enable forwarding, use: * vpp# nat44 ei forwarding enable * To disable forwarding, use: * vpp# nat44 ei forwarding disable * @cliexend ?*/ VLIB_CLI_COMMAND (nat44_ei_forwarding_set_command, static) = { .path = "nat44 ei forwarding", .short_help = "nat44 ei forwarding enable|disable", .function = nat44_ei_forwarding_set_command_fn, }; /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */