- b0 = vlib_get_buffer (vm, bi0);
- next0 = SNAT_OUT2IN_NEXT_LOOKUP;
-
- sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
- rx_fib_index0 = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
- sw_if_index0);
-
- if (PREDICT_FALSE (nat_reass_is_drop_frag(0)))
- {
- next0 = SNAT_OUT2IN_NEXT_DROP;
- b0->error = node->errors[SNAT_OUT2IN_ERROR_DROP_FRAGMENT];
- goto trace0;
- }
-
- ip0 = (ip4_header_t *) vlib_buffer_get_current (b0);
- udp0 = ip4_next_header (ip0);
- tcp0 = (tcp_header_t *) udp0;
- proto0 = ip_proto_to_snat_proto (ip0->protocol);
-
- reass0 = nat_ip4_reass_find_or_create (ip0->src_address,
- ip0->dst_address,
- ip0->fragment_id,
- ip0->protocol,
- 1,
- &fragments_to_drop);
-
- if (PREDICT_FALSE (!reass0))
- {
- next0 = SNAT_OUT2IN_NEXT_DROP;
- b0->error = node->errors[SNAT_OUT2IN_ERROR_MAX_REASS];
- nat_log_notice ("maximum reassemblies exceeded");
- goto trace0;
- }
-
- if (PREDICT_FALSE (ip4_is_first_fragment (ip0)))
- {
- key0.addr = ip0->dst_address;
- key0.port = udp0->dst_port;
- key0.protocol = proto0;
- key0.fib_index = rx_fib_index0;
- kv0.key = key0.as_u64;
-
- if (clib_bihash_search_8_8 (&per_thread_data->out2in, &kv0, &value0))
- {
- /* Try to match static mapping by external address and port,
- destination address and port in packet */
- if (snat_static_mapping_match(sm, key0, &sm0, 1, 0, 0, 0))
- {
- /*
- * Send DHCP packets to the ipv4 stack, or we won't
- * be able to use dhcp client on the outside interface
- */
- if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_UDP
- && (udp0->dst_port
- == clib_host_to_net_u16(UDP_DST_PORT_dhcp_to_client))))
- {
- vnet_feature_next
- (vnet_buffer (b0)->sw_if_index[VLIB_RX],
- &next0, b0);
- goto trace0;
- }
-
- if (!sm->forwarding_enabled)
- {
- b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
- next0 = SNAT_OUT2IN_NEXT_DROP;
- goto trace0;
- }
- else
- {
- if (next_src_nat(sm, ip0, proto0, udp0->src_port, thread_index))
- {
- next0 = SNAT_OUT2IN_NEXT_IN2OUT;
- goto trace0;
- }
- create_bypass_for_fwd(sm, ip0, rx_fib_index0, thread_index);
- goto trace0;
- }
- }
-
- /* Create session initiated by host from external network */
- s0 = create_session_for_static_mapping(sm, b0, sm0, key0, node,
- thread_index);
- if (!s0)
- {
- b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
- next0 = SNAT_OUT2IN_NEXT_DROP;
- goto trace0;
- }
- reass0->sess_index = s0 - per_thread_data->sessions;
- reass0->thread_index = thread_index;
- }
- else
- {
- s0 = pool_elt_at_index (per_thread_data->sessions,
- value0.value);
- reass0->sess_index = value0.value;
- }
- nat_ip4_reass_get_frags (reass0, &fragments_to_loopback);
- }
- else
- {
- if (PREDICT_FALSE (reass0->sess_index == (u32) ~0))
- {
- if (nat_ip4_reass_add_fragment (reass0, bi0))
- {
- b0->error = node->errors[SNAT_OUT2IN_ERROR_MAX_FRAG];
- nat_log_notice ("maximum fragments per reassembly exceeded");
- next0 = SNAT_OUT2IN_NEXT_DROP;
- goto trace0;
- }
- cached0 = 1;
- goto trace0;
- }
- s0 = pool_elt_at_index (per_thread_data->sessions,
- reass0->sess_index);
- }
-
- old_addr0 = ip0->dst_address.as_u32;
- ip0->dst_address = s0->in2out.addr;
- new_addr0 = ip0->dst_address.as_u32;
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
-
- sum0 = ip0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
- ip4_header_t,
- dst_address /* changed member */);
- ip0->checksum = ip_csum_fold (sum0);
-
- if (PREDICT_FALSE (ip4_is_first_fragment (ip0)))
- {
- if (PREDICT_TRUE(proto0 == SNAT_PROTOCOL_TCP))
- {
- old_port0 = tcp0->dst_port;
- tcp0->dst_port = s0->in2out.port;
- new_port0 = tcp0->dst_port;
-
- sum0 = tcp0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
- ip4_header_t,
- dst_address /* changed member */);
-
- sum0 = ip_csum_update (sum0, old_port0, new_port0,
- ip4_header_t /* cheat */,
- length /* changed member */);
- tcp0->checksum = ip_csum_fold(sum0);
- }
- else
- {
- old_port0 = udp0->dst_port;
- udp0->dst_port = s0->in2out.port;
- udp0->checksum = 0;
- }
- }
-
- /* Accounting */
- nat44_session_update_counters (s0, now,
- vlib_buffer_length_in_chain (vm, b0));
- /* Per-user LRU list maintenance */
- nat44_session_update_lru (sm, s0, thread_index);
-
- trace0:
- if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- nat44_out2in_reass_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->cached = cached0;
- t->sw_if_index = sw_if_index0;
- t->next_index = next0;
- }
-
- if (cached0)
- {
- n_left_to_next++;
- to_next--;
- }
- else
- {
- pkts_processed += next0 != SNAT_OUT2IN_NEXT_DROP;
-
- /* 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);
- }
-
- if (n_left_from == 0 && vec_len (fragments_to_loopback))