- vec_foreach (ap, sm->addresses)
- {
- if (ip0->dst_address.as_u32 == ap->addr.as_u32)
- {
- next0 = NAT44_CLASSIFY_NEXT_OUT2IN;
- goto enqueue0;
- }
- }
-
- if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
- {
- m_key0.addr = ip0->dst_address;
- m_key0.port = 0;
- m_key0.protocol = 0;
- m_key0.fib_index = 0;
- kv0.key = m_key0.as_u64;
- if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv0, &value0))
- {
- m = pool_elt_at_index (sm->static_mappings, value0.value);
- if (m->local_addr.as_u32 != m->external_addr.as_u32)
- next0 = NAT44_CLASSIFY_NEXT_OUT2IN;
- goto enqueue0;
- }
- m_key0.port = clib_net_to_host_u16 (udp0->dst_port);
- m_key0.protocol = ip_proto_to_snat_proto (ip0->protocol);
- kv0.key = m_key0.as_u64;
- if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv0, &value0))
- {
- m = pool_elt_at_index (sm->static_mappings, value0.value);
- if (m->local_addr.as_u32 != m->external_addr.as_u32)
- next0 = NAT44_CLASSIFY_NEXT_OUT2IN;
- }
- }
-
- enqueue0:
- if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- nat44_classify_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->next_in2out = next0 == NAT44_CLASSIFY_NEXT_IN2OUT ? 1 : 0;
- }
-
- /* verify speculative enqueue, maybe switch current next frame */
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, next0);
- }
-
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
-
- return frame->n_vectors;
-}
-
-static uword
-nat44_classify_node_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- return nat44_classify_node_fn_inline (vm, node, frame, 0);
-};
-
-VLIB_REGISTER_NODE (nat44_classify_node) = {
- .function = nat44_classify_node_fn,
- .name = "nat44-classify",
- .vector_size = sizeof (u32),
- .format_trace = format_nat44_classify_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_next_nodes = NAT44_CLASSIFY_N_NEXT,
- .next_nodes = {
- [NAT44_CLASSIFY_NEXT_IN2OUT] = "nat44-in2out",
- [NAT44_CLASSIFY_NEXT_OUT2IN] = "nat44-out2in",
- },
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (nat44_classify_node,
- nat44_classify_node_fn);
-static uword
-nat44_ed_classify_node_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- return nat44_classify_node_fn_inline (vm, node, frame, 1);
-};
-
-VLIB_REGISTER_NODE (nat44_ed_classify_node) = {
- .function = nat44_ed_classify_node_fn,
- .name = "nat44-ed-classify",
- .vector_size = sizeof (u32),
- .format_trace = format_nat44_classify_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_next_nodes = NAT44_CLASSIFY_N_NEXT,
- .next_nodes = {
- [NAT44_CLASSIFY_NEXT_IN2OUT] = "nat44-ed-in2out",
- [NAT44_CLASSIFY_NEXT_OUT2IN] = "nat44-ed-out2in",
- },
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (nat44_ed_classify_node,
- nat44_ed_classify_node_fn);
-
-static uword
-nat44_det_classify_node_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- return nat44_classify_node_fn_inline (vm, node, frame, 0);
-};
-
-VLIB_REGISTER_NODE (nat44_det_classify_node) = {
- .function = nat44_det_classify_node_fn,
- .name = "nat44-det-classify",
- .vector_size = sizeof (u32),
- .format_trace = format_nat44_classify_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_next_nodes = NAT44_CLASSIFY_N_NEXT,
- .next_nodes = {
- [NAT44_CLASSIFY_NEXT_IN2OUT] = "nat44-det-in2out",
- [NAT44_CLASSIFY_NEXT_OUT2IN] = "nat44-det-out2in",
- },
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (nat44_det_classify_node,
- nat44_det_classify_node_fn);
-
-static uword
-nat44_handoff_classify_node_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- return nat44_classify_node_fn_inline (vm, node, frame, 0);
-};
-
-VLIB_REGISTER_NODE (nat44_handoff_classify_node) = {
- .function = nat44_handoff_classify_node_fn,
- .name = "nat44-handoff-classify",
- .vector_size = sizeof (u32),
- .format_trace = format_nat44_classify_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_next_nodes = NAT44_CLASSIFY_N_NEXT,
- .next_nodes = {
- [NAT44_CLASSIFY_NEXT_IN2OUT] = "nat44-in2out-worker-handoff",
- [NAT44_CLASSIFY_NEXT_OUT2IN] = "nat44-out2in-worker-handoff",
- },
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (nat44_handoff_classify_node,
- nat44_handoff_classify_node_fn);
-
-/**
- * @brief Add/del NAT address to FIB.
- *
- * 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.
- *
- * @param addr IPv4 address.
- * @param plen address prefix length
- * @param sw_if_index Interface.
- * @param is_add If 0 delete, otherwise add.
- */
-void
-snat_add_del_addr_to_fib (ip4_address_t * addr, u8 p_len, u32 sw_if_index,
- int is_add)
-{
- 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);
-
- if (is_add)
- fib_table_entry_update_one_path(fib_index,
- &prefix,
- FIB_SOURCE_PLUGIN_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);
- else
- fib_table_entry_delete(fib_index,
- &prefix,
- FIB_SOURCE_PLUGIN_LOW);
-}
-
-int snat_add_address (snat_main_t *sm, ip4_address_t *addr, u32 vrf_id,
- u8 twice_nat)
-{
- snat_address_t * ap;
- snat_interface_t *i;
- vlib_thread_main_t *tm = vlib_get_thread_main ();
-
- if (twice_nat && !sm->endpoint_dependent)
- return VNET_API_ERROR_FEATURE_DISABLED;
-
- /* Check if address already exists */
- vec_foreach (ap, twice_nat ? sm->twice_nat_addresses : sm->addresses)
- {
- if (ap->addr.as_u32 == addr->as_u32)
- return VNET_API_ERROR_VALUE_EXIST;
- }
-
- if (twice_nat)
- vec_add2 (sm->twice_nat_addresses, ap, 1);
- else
- vec_add2 (sm->addresses, ap, 1);
-
- ap->addr = *addr;
- if (vrf_id != ~0)
- ap->fib_index =
- fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
- FIB_SOURCE_PLUGIN_LOW);
- else
- ap->fib_index = ~0;
-#define _(N, i, n, s) \
- clib_bitmap_alloc (ap->busy_##n##_port_bitmap, 65535); \
- ap->busy_##n##_ports = 0; \
- vec_validate_init_empty (ap->busy_##n##_ports_per_thread, tm->n_vlib_mains - 1, 0);
- foreach_snat_protocol
-#undef _
-
- if (twice_nat)
- return 0;
-
- /* Add external address to FIB */
- pool_foreach (i, sm->interfaces,
- ({
- if (nat_interface_is_inside(i) || sm->out2in_dpo)
- continue;