2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
17 * @brief NAT44 EI outside to inside network translation
20 #include <vlib/vlib.h>
22 #include <vnet/vnet.h>
23 #include <vnet/ip/ip.h>
24 #include <vnet/ethernet/ethernet.h>
25 #include <vnet/udp/udp_local.h>
26 #include <vnet/fib/ip4_fib.h>
28 #include <vppinfra/hash.h>
29 #include <vppinfra/error.h>
31 #include <nat/lib/log.h>
32 #include <nat/lib/nat_syslog.h>
33 #include <nat/lib/ipfix_logging.h>
34 #include <nat/nat44-ei/nat44_ei_inlines.h>
35 #include <nat/nat44-ei/nat44_ei.h>
42 } nat44_ei_out2in_trace_t;
44 /* packet trace format function */
46 format_nat44_ei_out2in_trace (u8 *s, va_list *args)
48 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
49 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
50 nat44_ei_out2in_trace_t *t = va_arg (*args, nat44_ei_out2in_trace_t *);
54 "NAT44_OUT2IN: sw_if_index %d, next index %d, session index %d",
55 t->sw_if_index, t->next_index, t->session_index);
60 format_nat44_ei_out2in_fast_trace (u8 *s, va_list *args)
62 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
63 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
64 nat44_ei_out2in_trace_t *t = va_arg (*args, nat44_ei_out2in_trace_t *);
66 s = format (s, "NAT44_OUT2IN_FAST: sw_if_index %d, next index %d",
67 t->sw_if_index, t->next_index);
71 #define foreach_nat44_ei_out2in_error \
72 _ (UNSUPPORTED_PROTOCOL, "unsupported protocol") \
73 _ (OUT_OF_PORTS, "out of ports") \
74 _ (BAD_ICMP_TYPE, "unsupported ICMP type") \
75 _ (NO_TRANSLATION, "no translation") \
76 _ (MAX_SESSIONS_EXCEEDED, "maximum sessions exceeded") \
77 _ (CANNOT_CREATE_USER, "cannot create NAT user")
81 #define _(sym, str) NAT44_EI_OUT2IN_ERROR_##sym,
82 foreach_nat44_ei_out2in_error
84 NAT44_EI_OUT2IN_N_ERROR,
85 } nat44_ei_out2in_error_t;
87 static char *nat44_ei_out2in_error_strings[] = {
88 #define _(sym,string) string,
89 foreach_nat44_ei_out2in_error
95 NAT44_EI_OUT2IN_NEXT_DROP,
96 NAT44_EI_OUT2IN_NEXT_LOOKUP,
97 NAT44_EI_OUT2IN_NEXT_ICMP_ERROR,
98 NAT44_EI_OUT2IN_N_NEXT,
99 } nat44_ei_out2in_next_t;
101 #ifndef CLIB_MARCH_VARIANT
103 nat44_o2i_is_idle_session_cb (clib_bihash_kv_8_8_t * kv, void *arg)
105 nat44_ei_main_t *nm = &nat44_ei_main;
106 nat44_ei_is_idle_session_ctx_t *ctx = arg;
107 nat44_ei_session_t *s;
108 u64 sess_timeout_time;
109 nat44_ei_main_per_thread_data_t *tnm =
110 vec_elt_at_index (nm->per_thread_data, ctx->thread_index);
111 clib_bihash_kv_8_8_t s_kv;
113 s = pool_elt_at_index (tnm->sessions, kv->value);
114 sess_timeout_time = s->last_heard + (f64) nat_session_get_timeout (
115 &nm->timeouts, s->nat_proto, s->state);
116 if (ctx->now >= sess_timeout_time)
118 init_nat_i2o_k (&s_kv, s);
119 if (clib_bihash_add_del_8_8 (&nm->in2out, &s_kv, 0))
120 nat_elog_warn (nm, "out2in key del failed");
122 nat_ipfix_logging_nat44_ses_delete (ctx->thread_index,
123 s->in2out.addr.as_u32,
124 s->out2in.addr.as_u32,
128 s->in2out.fib_index);
130 nat_syslog_nat44_apmdel (s->user_index, s->in2out.fib_index,
131 &s->in2out.addr, s->in2out.port,
132 &s->out2in.addr, s->out2in.port, s->nat_proto);
134 nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
135 s->ext_host_port, s->nat_proto, s->out2in.fib_index,
138 if (!nat44_ei_is_session_static (s))
139 nat44_ei_free_outside_address_and_port (
140 nm->addresses, ctx->thread_index, &s->out2in.addr, s->out2in.port,
143 nat44_ei_delete_session (nm, s, ctx->thread_index);
152 * @brief Create session for static mapping.
154 * Create NAT session initiated by host from external network with static
157 * @param nm NAT main.
158 * @param b0 Vlib buffer.
159 * @param in2out In2out NAT44 session key.
160 * @param out2in Out2in NAT44 session key.
161 * @param node Vlib node.
163 * @returns NAT44_EI session if successfully created otherwise 0.
165 static inline nat44_ei_session_t *
166 create_session_for_static_mapping (
167 nat44_ei_main_t *nm, vlib_buffer_t *b0, ip4_address_t i2o_addr, u16 i2o_port,
168 u32 i2o_fib_index, ip4_address_t o2i_addr, u16 o2i_port, u32 o2i_fib_index,
169 nat_protocol_t proto, vlib_node_runtime_t *node, u32 thread_index, f64 now)
172 nat44_ei_session_t *s;
173 clib_bihash_kv_8_8_t kv0;
176 nat44_ei_is_idle_session_ctx_t ctx0;
178 if (PREDICT_FALSE (nat44_ei_maximum_sessions_exceeded (nm, thread_index)))
180 b0->error = node->errors[NAT44_EI_OUT2IN_ERROR_MAX_SESSIONS_EXCEEDED];
181 nat_elog_notice (nm, "maximum sessions exceeded");
185 ip0 = vlib_buffer_get_current (b0);
186 udp0 = ip4_next_header (ip0);
188 u = nat44_ei_user_get_or_create (nm, &i2o_addr, i2o_fib_index, thread_index);
191 b0->error = node->errors[NAT44_EI_OUT2IN_ERROR_CANNOT_CREATE_USER];
195 s = nat44_ei_session_alloc_or_recycle (nm, u, thread_index, now);
198 nat44_ei_delete_user_with_no_session (nm, u, thread_index);
199 nat_elog_warn (nm, "create NAT session failed");
203 s->flags |= NAT44_EI_SESSION_FLAG_STATIC_MAPPING;
204 s->ext_host_addr.as_u32 = ip0->src_address.as_u32;
205 s->ext_host_port = udp0->src_port;
206 nat44_ei_user_session_increment (nm, u, 1 /* static */);
207 s->in2out.addr = i2o_addr;
208 s->in2out.port = i2o_port;
209 s->in2out.fib_index = i2o_fib_index;
210 s->out2in.addr = o2i_addr;
211 s->out2in.port = o2i_port;
212 s->out2in.fib_index = o2i_fib_index;
213 s->nat_proto = proto;
215 /* Add to translation hashes */
217 ctx0.thread_index = thread_index;
218 init_nat_i2o_kv (&kv0, s, thread_index,
219 s - nm->per_thread_data[thread_index].sessions);
220 if (clib_bihash_add_or_overwrite_stale_8_8 (
221 &nm->in2out, &kv0, nat44_i2o_is_idle_session_cb, &ctx0))
222 nat_elog_notice (nm, "in2out key add failed");
224 init_nat_o2i_kv (&kv0, s, thread_index,
225 s - nm->per_thread_data[thread_index].sessions);
226 if (clib_bihash_add_or_overwrite_stale_8_8 (
227 &nm->out2in, &kv0, nat44_o2i_is_idle_session_cb, &ctx0))
228 nat_elog_notice (nm, "out2in key add failed");
231 nat_ipfix_logging_nat44_ses_create (thread_index,
232 s->in2out.addr.as_u32,
233 s->out2in.addr.as_u32,
236 s->out2in.port, s->in2out.fib_index);
238 nat_syslog_nat44_apmadd (s->user_index, s->in2out.fib_index,
239 &s->in2out.addr, s->in2out.port, &s->out2in.addr,
240 s->out2in.port, s->nat_proto);
242 nat_ha_sadd (&s->in2out.addr, s->in2out.port, &s->out2in.addr,
243 s->out2in.port, &s->ext_host_addr, s->ext_host_port,
244 &s->ext_host_nat_addr, s->ext_host_nat_port,
245 s->nat_proto, s->in2out.fib_index, s->flags, thread_index, 0);
250 #ifndef CLIB_MARCH_VARIANT
251 static_always_inline nat44_ei_out2in_error_t
252 icmp_get_key (vlib_buffer_t *b, ip4_header_t *ip0, ip4_address_t *addr,
253 u16 *port, nat_protocol_t *nat_proto)
255 icmp46_header_t *icmp0;
256 icmp_echo_header_t *echo0, *inner_echo0 = 0;
257 ip4_header_t *inner_ip0;
259 icmp46_header_t *inner_icmp0;
261 icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
262 echo0 = (icmp_echo_header_t *) (icmp0 + 1);
264 if (!icmp_type_is_error_message
265 (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags))
267 *nat_proto = NAT_PROTOCOL_ICMP;
268 *addr = ip0->dst_address;
269 *port = vnet_buffer (b)->ip.reass.l4_src_port;
273 inner_ip0 = (ip4_header_t *) (echo0 + 1);
274 l4_header = ip4_next_header (inner_ip0);
275 *nat_proto = ip_proto_to_nat_proto (inner_ip0->protocol);
276 *addr = inner_ip0->src_address;
279 case NAT_PROTOCOL_ICMP:
280 inner_icmp0 = (icmp46_header_t *) l4_header;
281 inner_echo0 = (icmp_echo_header_t *) (inner_icmp0 + 1);
282 *port = inner_echo0->identifier;
284 case NAT_PROTOCOL_UDP:
285 case NAT_PROTOCOL_TCP:
286 *port = ((tcp_udp_header_t *) l4_header)->src_port;
289 return NAT44_EI_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL;
292 return -1; /* success */
296 * Get address and port values to be used for ICMP packet translation
297 * and create session if needed
299 * @param[in,out] nm NAT main
300 * @param[in,out] node NAT node runtime
301 * @param[in] thread_index thread index
302 * @param[in,out] b0 buffer containing packet to be translated
303 * @param[in,out] ip0 ip header
304 * @param[out] p_proto protocol used for matching
305 * @param[out] p_value address and port after NAT translation
306 * @param[out] p_dont_translate if packet should not be translated
307 * @param d optional parameter
308 * @param e optional parameter
311 nat44_ei_icmp_match_out2in_slow (vlib_node_runtime_t *node, u32 thread_index,
312 vlib_buffer_t *b0, ip4_header_t *ip0,
313 ip4_address_t *addr, u16 *port,
314 u32 *fib_index, nat_protocol_t *proto,
315 nat44_ei_session_t **p_s0, u8 *dont_translate)
317 nat44_ei_main_t *nm = &nat44_ei_main;
318 nat44_ei_main_per_thread_data_t *tnm = &nm->per_thread_data[thread_index];
320 nat44_ei_session_t *s0 = 0;
321 clib_bihash_kv_8_8_t kv0, value0;
326 vlib_main_t *vm = vlib_get_main ();
329 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
330 *fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
334 err = icmp_get_key (b0, ip0, addr, port, proto);
337 b0->error = node->errors[NAT44_EI_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL];
338 next0 = NAT44_EI_OUT2IN_NEXT_DROP;
342 ip4_address_t mapping_addr;
344 u32 mapping_fib_index;
346 init_nat_k (&kv0, *addr, *port, *fib_index, *proto);
347 if (clib_bihash_search_8_8 (&nm->out2in, &kv0, &value0))
349 /* Try to match static mapping by external address and port,
350 destination address and port in packet */
351 if (nat44_ei_static_mapping_match (
352 *addr, *port, *fib_index, *proto, &mapping_addr, &mapping_port,
353 &mapping_fib_index, 1, &is_addr_only, &identity_nat))
355 if (!nm->forwarding_enabled)
357 /* Don't NAT packet aimed at the intfc address */
358 if (PREDICT_FALSE (nat44_ei_is_interface_addr (
359 nm->ip4_main, node, sw_if_index0,
360 ip0->dst_address.as_u32)))
365 b0->error = node->errors[NAT44_EI_OUT2IN_ERROR_NO_TRANSLATION];
366 next0 = NAT44_EI_OUT2IN_NEXT_DROP;
377 (vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags !=
379 && (vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags !=
380 ICMP4_echo_request || !is_addr_only)))
382 b0->error = node->errors[NAT44_EI_OUT2IN_ERROR_BAD_ICMP_TYPE];
383 next0 = NAT44_EI_OUT2IN_NEXT_DROP;
387 if (PREDICT_FALSE (identity_nat))
392 /* Create session initiated by host from external network */
393 s0 = create_session_for_static_mapping (
394 nm, b0, mapping_addr, mapping_port, mapping_fib_index, *addr, *port,
395 *fib_index, *proto, node, thread_index, vlib_time_now (vm));
399 next0 = NAT44_EI_OUT2IN_NEXT_DROP;
406 (vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags !=
408 && vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags !=
410 && !icmp_type_is_error_message (vnet_buffer (b0)->ip.
411 reass.icmp_type_or_tcp_flags)))
413 b0->error = node->errors[NAT44_EI_OUT2IN_ERROR_BAD_ICMP_TYPE];
414 next0 = NAT44_EI_OUT2IN_NEXT_DROP;
418 s0 = pool_elt_at_index (tnm->sessions,
419 nat_value_get_session_index (&value0));
425 *addr = s0->in2out.addr;
426 *port = s0->in2out.port;
427 *fib_index = s0->in2out.fib_index;
435 #ifndef CLIB_MARCH_VARIANT
437 nat44_ei_icmp_match_out2in_fast (vlib_node_runtime_t *node, u32 thread_index,
438 vlib_buffer_t *b0, ip4_header_t *ip0,
439 ip4_address_t *mapping_addr,
440 u16 *mapping_port, u32 *mapping_fib_index,
441 nat_protocol_t *proto,
442 nat44_ei_session_t **p_s0, u8 *dont_translate)
444 nat44_ei_main_t *nm = &nat44_ei_main;
454 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
455 rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
457 err = icmp_get_key (b0, ip0, &addr, &port, proto);
460 b0->error = node->errors[err];
461 next0 = NAT44_EI_OUT2IN_NEXT_DROP;
464 if (nat44_ei_static_mapping_match (addr, port, rx_fib_index0, *proto,
465 mapping_addr, mapping_port,
466 mapping_fib_index, 1, &is_addr_only, 0))
468 /* Don't NAT packet aimed at the intfc address */
469 if (nat44_ei_is_interface_addr (nm->ip4_main, node, sw_if_index0,
470 ip0->dst_address.as_u32))
475 b0->error = node->errors[NAT44_EI_OUT2IN_ERROR_NO_TRANSLATION];
476 next0 = NAT44_EI_OUT2IN_NEXT_DROP;
481 (vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags != ICMP4_echo_reply
482 && (vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags !=
483 ICMP4_echo_request || !is_addr_only)
484 && !icmp_type_is_error_message (vnet_buffer (b0)->ip.
485 reass.icmp_type_or_tcp_flags)))
487 b0->error = node->errors[NAT44_EI_OUT2IN_ERROR_BAD_ICMP_TYPE];
488 next0 = NAT44_EI_OUT2IN_NEXT_DROP;
497 u32 nat44_ei_icmp_out2in (vlib_buffer_t *b0, ip4_header_t *ip0,
498 icmp46_header_t *icmp0, u32 sw_if_index0,
499 u32 rx_fib_index0, vlib_node_runtime_t *node,
500 u32 next0, u32 thread_index,
501 nat44_ei_session_t **p_s0);
503 #ifndef CLIB_MARCH_VARIANT
505 nat44_ei_icmp_out2in (vlib_buffer_t *b0, ip4_header_t *ip0,
506 icmp46_header_t *icmp0, u32 sw_if_index0,
507 u32 rx_fib_index0, vlib_node_runtime_t *node, u32 next0,
508 u32 thread_index, nat44_ei_session_t **p_s0)
510 nat44_ei_main_t *nm = &nat44_ei_main;
511 icmp_echo_header_t *echo0, *inner_echo0 = 0;
512 ip4_header_t *inner_ip0 = 0;
514 icmp46_header_t *inner_icmp0;
516 u32 new_addr0, old_addr0;
517 u16 old_id0, new_id0;
521 vlib_main_t *vm = vlib_get_main ();
525 nat_protocol_t proto;
527 echo0 = (icmp_echo_header_t *) (icmp0 + 1);
529 if (PREDICT_TRUE (nm->pat))
531 next0_tmp = nat44_ei_icmp_match_out2in_slow (
532 node, thread_index, b0, ip0, &addr, &port, &fib_index, &proto, p_s0,
537 next0_tmp = nat44_ei_icmp_match_out2in_fast (
538 node, thread_index, b0, ip0, &addr, &port, &fib_index, &proto, p_s0,
544 if (next0 == NAT44_EI_OUT2IN_NEXT_DROP || dont_translate)
547 if (PREDICT_TRUE (!ip4_is_fragment (ip0)))
550 ip_incremental_checksum_buffer (vm, b0,
552 (u8 *) vlib_buffer_get_current (b0),
553 ntohs (ip0->length) -
554 ip4_header_bytes (ip0), 0);
555 checksum0 = ~ip_csum_fold (sum0);
556 if (checksum0 != 0 && checksum0 != 0xffff)
558 next0 = NAT44_EI_OUT2IN_NEXT_DROP;
563 old_addr0 = ip0->dst_address.as_u32;
564 new_addr0 = ip0->dst_address.as_u32 = addr.as_u32;
565 vnet_buffer (b0)->sw_if_index[VLIB_TX] = fib_index;
567 sum0 = ip0->checksum;
568 sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
569 dst_address /* changed member */ );
570 ip0->checksum = ip_csum_fold (sum0);
573 if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
575 if (icmp0->checksum == 0)
576 icmp0->checksum = 0xffff;
578 if (!icmp_type_is_error_message (icmp0->type))
581 if (PREDICT_FALSE (new_id0 != echo0->identifier))
583 old_id0 = echo0->identifier;
585 echo0->identifier = new_id0;
587 sum0 = icmp0->checksum;
589 ip_csum_update (sum0, old_id0, new_id0, icmp_echo_header_t,
590 identifier /* changed member */ );
591 icmp0->checksum = ip_csum_fold (sum0);
596 inner_ip0 = (ip4_header_t *) (echo0 + 1);
597 l4_header = ip4_next_header (inner_ip0);
599 if (!ip4_header_checksum_is_valid (inner_ip0))
601 next0 = NAT44_EI_OUT2IN_NEXT_DROP;
605 old_addr0 = inner_ip0->src_address.as_u32;
606 inner_ip0->src_address = addr;
607 new_addr0 = inner_ip0->src_address.as_u32;
609 sum0 = icmp0->checksum;
610 sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
611 src_address /* changed member */ );
612 icmp0->checksum = ip_csum_fold (sum0);
616 case NAT_PROTOCOL_ICMP:
617 inner_icmp0 = (icmp46_header_t *) l4_header;
618 inner_echo0 = (icmp_echo_header_t *) (inner_icmp0 + 1);
620 old_id0 = inner_echo0->identifier;
622 inner_echo0->identifier = new_id0;
624 sum0 = icmp0->checksum;
626 ip_csum_update (sum0, old_id0, new_id0, icmp_echo_header_t,
628 icmp0->checksum = ip_csum_fold (sum0);
630 case NAT_PROTOCOL_UDP:
631 case NAT_PROTOCOL_TCP:
632 old_id0 = ((tcp_udp_header_t *) l4_header)->src_port;
634 ((tcp_udp_header_t *) l4_header)->src_port = new_id0;
636 sum0 = icmp0->checksum;
637 sum0 = ip_csum_update (sum0, old_id0, new_id0, tcp_udp_header_t,
639 icmp0->checksum = ip_csum_fold (sum0);
653 nat44_ei_icmp_out2in_slow_path (nat44_ei_main_t *nm, vlib_buffer_t *b0,
654 ip4_header_t *ip0, icmp46_header_t *icmp0,
655 u32 sw_if_index0, u32 rx_fib_index0,
656 vlib_node_runtime_t *node, u32 next0, f64 now,
657 u32 thread_index, nat44_ei_session_t **p_s0)
659 vlib_main_t *vm = vlib_get_main ();
661 next0 = nat44_ei_icmp_out2in (b0, ip0, icmp0, sw_if_index0, rx_fib_index0,
662 node, next0, thread_index, p_s0);
663 nat44_ei_session_t *s0 = *p_s0;
664 if (PREDICT_TRUE (next0 != NAT44_EI_OUT2IN_NEXT_DROP && s0))
667 nat44_ei_session_update_counters (
668 s0, now, vlib_buffer_length_in_chain (vm, b0), thread_index);
669 /* Per-user LRU list maintenance */
670 nat44_ei_session_update_lru (nm, s0, thread_index);
676 nat_out2in_sm_unknown_proto (nat44_ei_main_t *nm, vlib_buffer_t *b,
677 ip4_header_t *ip, u32 rx_fib_index)
679 clib_bihash_kv_8_8_t kv, value;
680 nat44_ei_static_mapping_t *m;
681 u32 old_addr, new_addr;
684 init_nat_k (&kv, ip->dst_address, 0, 0, 0);
685 if (clib_bihash_search_8_8 (&nm->static_mapping_by_external, &kv, &value))
688 m = pool_elt_at_index (nm->static_mappings, value.value);
690 old_addr = ip->dst_address.as_u32;
691 new_addr = ip->dst_address.as_u32 = m->local_addr.as_u32;
693 sum = ip_csum_update (sum, old_addr, new_addr, ip4_header_t, dst_address);
694 ip->checksum = ip_csum_fold (sum);
696 vnet_buffer (b)->sw_if_index[VLIB_TX] = m->fib_index;
700 VLIB_NODE_FN (nat44_ei_out2in_node)
701 (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
703 u32 n_left_from, *from;
704 nat44_ei_main_t *nm = &nat44_ei_main;
705 f64 now = vlib_time_now (vm);
706 u32 thread_index = vm->thread_index;
707 nat44_ei_main_per_thread_data_t *tnm = &nm->per_thread_data[thread_index];
709 from = vlib_frame_vector_args (frame);
710 n_left_from = frame->n_vectors;
712 vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
713 u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
714 vlib_get_buffers (vm, from, b, n_left_from);
716 while (n_left_from >= 2)
718 vlib_buffer_t *b0, *b1;
719 u32 next0 = NAT44_EI_OUT2IN_NEXT_LOOKUP;
720 u32 next1 = NAT44_EI_OUT2IN_NEXT_LOOKUP;
721 u32 sw_if_index0, sw_if_index1;
722 ip4_header_t *ip0, *ip1;
723 ip_csum_t sum0, sum1;
724 u32 new_addr0, old_addr0;
725 u16 new_port0, old_port0;
726 u32 new_addr1, old_addr1;
727 u16 new_port1, old_port1;
728 udp_header_t *udp0, *udp1;
729 tcp_header_t *tcp0, *tcp1;
730 icmp46_header_t *icmp0, *icmp1;
731 u32 rx_fib_index0, rx_fib_index1;
733 nat44_ei_session_t *s0 = 0, *s1 = 0;
734 clib_bihash_kv_8_8_t kv0, kv1, value0, value1;
735 u8 identity_nat0, identity_nat1;
736 ip4_address_t sm_addr0, sm_addr1;
737 u16 sm_port0, sm_port1;
738 u32 sm_fib_index0, sm_fib_index1;
745 /* Prefetch next iteration. */
746 if (PREDICT_TRUE (n_left_from >= 4))
748 vlib_buffer_t *p2, *p3;
753 vlib_prefetch_buffer_header (p2, LOAD);
754 vlib_prefetch_buffer_header (p3, LOAD);
756 CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, LOAD);
757 CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, LOAD);
760 vnet_buffer (b0)->snat.flags = 0;
761 vnet_buffer (b1)->snat.flags = 0;
763 ip0 = vlib_buffer_get_current (b0);
764 udp0 = ip4_next_header (ip0);
765 tcp0 = (tcp_header_t *) udp0;
766 icmp0 = (icmp46_header_t *) udp0;
768 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
770 vec_elt (nm->ip4_main->fib_index_by_sw_if_index, sw_if_index0);
772 if (PREDICT_FALSE (ip0->ttl == 1))
774 vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
775 icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
776 ICMP4_time_exceeded_ttl_exceeded_in_transit,
778 next0 = NAT44_EI_OUT2IN_NEXT_ICMP_ERROR;
782 proto0 = ip_proto_to_nat_proto (ip0->protocol);
784 if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_OTHER))
786 if (nat_out2in_sm_unknown_proto (nm, b0, ip0, rx_fib_index0))
788 if (!nm->forwarding_enabled)
791 node->errors[NAT44_EI_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL];
792 next0 = NAT44_EI_OUT2IN_NEXT_DROP;
795 vlib_increment_simple_counter (&nm->counters.slowpath.out2in.other,
796 thread_index, sw_if_index0, 1);
801 if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP))
803 next0 = nat44_ei_icmp_out2in_slow_path (
804 nm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node, next0, now,
806 vlib_increment_simple_counter (&nm->counters.slowpath.out2in.icmp,
807 thread_index, sw_if_index0, 1);
811 init_nat_k (&kv0, ip0->dst_address,
812 vnet_buffer (b0)->ip.reass.l4_dst_port, rx_fib_index0,
814 if (clib_bihash_search_8_8 (&nm->out2in, &kv0, &value0))
816 /* Try to match static mapping by external address and port,
817 destination address and port in packet */
818 if (nat44_ei_static_mapping_match (
819 ip0->dst_address, vnet_buffer (b0)->ip.reass.l4_dst_port,
820 rx_fib_index0, proto0, &sm_addr0, &sm_port0, &sm_fib_index0, 1,
824 * Send DHCP packets to the ipv4 stack, or we won't
825 * be able to use dhcp client on the outside interface
828 (proto0 == NAT_PROTOCOL_UDP
829 && (vnet_buffer (b0)->ip.reass.l4_dst_port ==
830 clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_client))))
832 vnet_feature_next (&next0, b0);
836 if (!nm->forwarding_enabled)
839 node->errors[NAT44_EI_OUT2IN_ERROR_NO_TRANSLATION];
840 next0 = NAT44_EI_OUT2IN_NEXT_DROP;
845 if (PREDICT_FALSE (identity_nat0))
848 /* Create session initiated by host from external network */
849 s0 = create_session_for_static_mapping (
850 nm, b0, sm_addr0, sm_port0, sm_fib_index0, ip0->dst_address,
851 vnet_buffer (b0)->ip.reass.l4_dst_port, rx_fib_index0, proto0,
852 node, thread_index, now);
855 next0 = NAT44_EI_OUT2IN_NEXT_DROP;
860 s0 = pool_elt_at_index (tnm->sessions,
861 nat_value_get_session_index (&value0));
863 old_addr0 = ip0->dst_address.as_u32;
864 ip0->dst_address = s0->in2out.addr;
865 new_addr0 = ip0->dst_address.as_u32;
866 vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
868 sum0 = ip0->checksum;
869 sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
870 ip4_header_t, dst_address /* changed member */ );
871 ip0->checksum = ip_csum_fold (sum0);
873 if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
875 if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
877 old_port0 = vnet_buffer (b0)->ip.reass.l4_dst_port;
878 new_port0 = udp0->dst_port = s0->in2out.port;
879 sum0 = tcp0->checksum;
880 sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
882 dst_address /* changed member */ );
884 sum0 = ip_csum_update (sum0, old_port0, new_port0,
885 ip4_header_t /* cheat */ ,
886 length /* changed member */ );
887 tcp0->checksum = ip_csum_fold (sum0);
889 vlib_increment_simple_counter (&nm->counters.slowpath.out2in.tcp,
890 thread_index, sw_if_index0, 1);
894 if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
896 old_port0 = vnet_buffer (b0)->ip.reass.l4_dst_port;
897 new_port0 = udp0->dst_port = s0->in2out.port;
898 if (PREDICT_FALSE (udp0->checksum))
900 sum0 = udp0->checksum;
901 sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t, dst_address /* changed member */
904 ip_csum_update (sum0, old_port0, new_port0,
905 ip4_header_t /* cheat */ ,
906 length /* changed member */ );
907 udp0->checksum = ip_csum_fold (sum0);
910 vlib_increment_simple_counter (&nm->counters.slowpath.out2in.udp,
911 thread_index, sw_if_index0, 1);
915 nat44_ei_session_update_counters (
916 s0, now, vlib_buffer_length_in_chain (vm, b0), thread_index);
917 /* Per-user LRU list maintenance */
918 nat44_ei_session_update_lru (nm, s0, thread_index);
921 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
922 && (b0->flags & VLIB_BUFFER_IS_TRACED)))
924 nat44_ei_out2in_trace_t *t =
925 vlib_add_trace (vm, node, b0, sizeof (*t));
926 t->sw_if_index = sw_if_index0;
927 t->next_index = next0;
928 t->session_index = ~0;
930 t->session_index = s0 - nm->per_thread_data[thread_index].sessions;
933 if (next0 == NAT44_EI_OUT2IN_NEXT_DROP)
935 vlib_increment_simple_counter (&nm->counters.slowpath.out2in.drops,
936 thread_index, sw_if_index0, 1);
940 ip1 = vlib_buffer_get_current (b1);
941 udp1 = ip4_next_header (ip1);
942 tcp1 = (tcp_header_t *) udp1;
943 icmp1 = (icmp46_header_t *) udp1;
945 sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
947 vec_elt (nm->ip4_main->fib_index_by_sw_if_index, sw_if_index1);
949 if (PREDICT_FALSE (ip1->ttl == 1))
951 vnet_buffer (b1)->sw_if_index[VLIB_TX] = (u32) ~ 0;
952 icmp4_error_set_vnet_buffer (b1, ICMP4_time_exceeded,
953 ICMP4_time_exceeded_ttl_exceeded_in_transit,
955 next1 = NAT44_EI_OUT2IN_NEXT_ICMP_ERROR;
959 proto1 = ip_proto_to_nat_proto (ip1->protocol);
961 if (PREDICT_FALSE (proto1 == NAT_PROTOCOL_OTHER))
963 if (nat_out2in_sm_unknown_proto (nm, b1, ip1, rx_fib_index1))
965 if (!nm->forwarding_enabled)
968 node->errors[NAT44_EI_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL];
969 next1 = NAT44_EI_OUT2IN_NEXT_DROP;
972 vlib_increment_simple_counter (&nm->counters.slowpath.out2in.other,
973 thread_index, sw_if_index1, 1);
977 if (PREDICT_FALSE (proto1 == NAT_PROTOCOL_ICMP))
979 next1 = nat44_ei_icmp_out2in_slow_path (
980 nm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node, next1, now,
982 vlib_increment_simple_counter (&nm->counters.slowpath.out2in.icmp,
983 thread_index, sw_if_index1, 1);
987 init_nat_k (&kv1, ip1->dst_address,
988 vnet_buffer (b1)->ip.reass.l4_dst_port, rx_fib_index1,
990 if (clib_bihash_search_8_8 (&nm->out2in, &kv1, &value1))
992 /* Try to match static mapping by external address and port,
993 destination address and port in packet */
994 if (nat44_ei_static_mapping_match (
995 ip1->dst_address, vnet_buffer (b1)->ip.reass.l4_dst_port,
996 rx_fib_index1, proto1, &sm_addr1, &sm_port1, &sm_fib_index1, 1,
1000 * Send DHCP packets to the ipv4 stack, or we won't
1001 * be able to use dhcp client on the outside interface
1004 (proto1 == NAT_PROTOCOL_UDP
1005 && (vnet_buffer (b1)->ip.reass.l4_dst_port ==
1006 clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_client))))
1008 vnet_feature_next (&next1, b1);
1012 if (!nm->forwarding_enabled)
1015 node->errors[NAT44_EI_OUT2IN_ERROR_NO_TRANSLATION];
1016 next1 = NAT44_EI_OUT2IN_NEXT_DROP;
1021 if (PREDICT_FALSE (identity_nat1))
1024 /* Create session initiated by host from external network */
1025 s1 = create_session_for_static_mapping (
1026 nm, b1, sm_addr1, sm_port1, sm_fib_index1, ip1->dst_address,
1027 vnet_buffer (b1)->ip.reass.l4_dst_port, rx_fib_index1, proto1,
1028 node, thread_index, now);
1031 next1 = NAT44_EI_OUT2IN_NEXT_DROP;
1036 s1 = pool_elt_at_index (nm->per_thread_data[thread_index].sessions,
1037 nat_value_get_session_index (&value1));
1039 old_addr1 = ip1->dst_address.as_u32;
1040 ip1->dst_address = s1->in2out.addr;
1041 new_addr1 = ip1->dst_address.as_u32;
1042 vnet_buffer (b1)->sw_if_index[VLIB_TX] = s1->in2out.fib_index;
1044 sum1 = ip1->checksum;
1045 sum1 = ip_csum_update (sum1, old_addr1, new_addr1,
1046 ip4_header_t, dst_address /* changed member */ );
1047 ip1->checksum = ip_csum_fold (sum1);
1049 if (PREDICT_TRUE (proto1 == NAT_PROTOCOL_TCP))
1051 if (!vnet_buffer (b1)->ip.reass.is_non_first_fragment)
1053 old_port1 = vnet_buffer (b1)->ip.reass.l4_dst_port;
1054 new_port1 = udp1->dst_port = s1->in2out.port;
1056 sum1 = tcp1->checksum;
1057 sum1 = ip_csum_update (sum1, old_addr1, new_addr1,
1059 dst_address /* changed member */ );
1061 sum1 = ip_csum_update (sum1, old_port1, new_port1,
1062 ip4_header_t /* cheat */ ,
1063 length /* changed member */ );
1064 tcp1->checksum = ip_csum_fold (sum1);
1066 vlib_increment_simple_counter (&nm->counters.slowpath.out2in.tcp,
1067 thread_index, sw_if_index1, 1);
1071 if (!vnet_buffer (b1)->ip.reass.is_non_first_fragment)
1073 old_port1 = vnet_buffer (b1)->ip.reass.l4_dst_port;
1074 new_port1 = udp1->dst_port = s1->in2out.port;
1075 if (PREDICT_FALSE (udp1->checksum))
1078 sum1 = udp1->checksum;
1080 ip_csum_update (sum1, old_addr1, new_addr1,
1082 dst_address /* changed member */ );
1084 ip_csum_update (sum1, old_port1, new_port1,
1085 ip4_header_t /* cheat */ ,
1086 length /* changed member */ );
1087 udp1->checksum = ip_csum_fold (sum1);
1090 vlib_increment_simple_counter (&nm->counters.slowpath.out2in.udp,
1091 thread_index, sw_if_index1, 1);
1095 nat44_ei_session_update_counters (
1096 s1, now, vlib_buffer_length_in_chain (vm, b1), thread_index);
1097 /* Per-user LRU list maintenance */
1098 nat44_ei_session_update_lru (nm, s1, thread_index);
1101 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
1102 && (b1->flags & VLIB_BUFFER_IS_TRACED)))
1104 nat44_ei_out2in_trace_t *t =
1105 vlib_add_trace (vm, node, b1, sizeof (*t));
1106 t->sw_if_index = sw_if_index1;
1107 t->next_index = next1;
1108 t->session_index = ~0;
1110 t->session_index = s1 - nm->per_thread_data[thread_index].sessions;
1113 if (next1 == NAT44_EI_OUT2IN_NEXT_DROP)
1115 vlib_increment_simple_counter (&nm->counters.slowpath.out2in.drops,
1116 thread_index, sw_if_index1, 1);
1125 while (n_left_from > 0)
1128 u32 next0 = NAT44_EI_OUT2IN_NEXT_LOOKUP;
1132 u32 new_addr0, old_addr0;
1133 u16 new_port0, old_port0;
1136 icmp46_header_t *icmp0;
1139 nat44_ei_session_t *s0 = 0;
1140 clib_bihash_kv_8_8_t kv0, value0;
1142 ip4_address_t sm_addr0;
1149 vnet_buffer (b0)->snat.flags = 0;
1151 ip0 = vlib_buffer_get_current (b0);
1152 udp0 = ip4_next_header (ip0);
1153 tcp0 = (tcp_header_t *) udp0;
1154 icmp0 = (icmp46_header_t *) udp0;
1156 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1158 vec_elt (nm->ip4_main->fib_index_by_sw_if_index, sw_if_index0);
1160 proto0 = ip_proto_to_nat_proto (ip0->protocol);
1162 if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_OTHER))
1164 if (nat_out2in_sm_unknown_proto (nm, b0, ip0, rx_fib_index0))
1166 if (!nm->forwarding_enabled)
1169 node->errors[NAT44_EI_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL];
1170 next0 = NAT44_EI_OUT2IN_NEXT_DROP;
1173 vlib_increment_simple_counter (&nm->counters.slowpath.out2in.other,
1174 thread_index, sw_if_index0, 1);
1178 if (PREDICT_FALSE (ip0->ttl == 1))
1180 vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1181 icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
1182 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1184 next0 = NAT44_EI_OUT2IN_NEXT_ICMP_ERROR;
1188 if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP))
1190 next0 = nat44_ei_icmp_out2in_slow_path (
1191 nm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node, next0, now,
1193 vlib_increment_simple_counter (&nm->counters.slowpath.out2in.icmp,
1194 thread_index, sw_if_index0, 1);
1198 init_nat_k (&kv0, ip0->dst_address,
1199 vnet_buffer (b0)->ip.reass.l4_dst_port, rx_fib_index0,
1202 if (clib_bihash_search_8_8 (&nm->out2in, &kv0, &value0))
1204 /* Try to match static mapping by external address and port,
1205 destination address and port in packet */
1206 if (nat44_ei_static_mapping_match (
1207 ip0->dst_address, vnet_buffer (b0)->ip.reass.l4_dst_port,
1208 rx_fib_index0, proto0, &sm_addr0, &sm_port0, &sm_fib_index0, 1,
1212 * Send DHCP packets to the ipv4 stack, or we won't
1213 * be able to use dhcp client on the outside interface
1216 (proto0 == NAT_PROTOCOL_UDP
1217 && (vnet_buffer (b0)->ip.reass.l4_dst_port ==
1218 clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_client))))
1220 vnet_feature_next (&next0, b0);
1224 if (!nm->forwarding_enabled)
1227 node->errors[NAT44_EI_OUT2IN_ERROR_NO_TRANSLATION];
1228 next0 = NAT44_EI_OUT2IN_NEXT_DROP;
1233 if (PREDICT_FALSE (identity_nat0))
1236 /* Create session initiated by host from external network */
1237 s0 = create_session_for_static_mapping (
1238 nm, b0, sm_addr0, sm_port0, sm_fib_index0, ip0->dst_address,
1239 vnet_buffer (b0)->ip.reass.l4_dst_port, rx_fib_index0, proto0,
1240 node, thread_index, now);
1243 next0 = NAT44_EI_OUT2IN_NEXT_DROP;
1248 s0 = pool_elt_at_index (nm->per_thread_data[thread_index].sessions,
1249 nat_value_get_session_index (&value0));
1251 old_addr0 = ip0->dst_address.as_u32;
1252 ip0->dst_address = s0->in2out.addr;
1253 new_addr0 = ip0->dst_address.as_u32;
1254 vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
1256 sum0 = ip0->checksum;
1257 sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1258 ip4_header_t, dst_address /* changed member */ );
1259 ip0->checksum = ip_csum_fold (sum0);
1261 if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
1263 if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1265 old_port0 = vnet_buffer (b0)->ip.reass.l4_dst_port;
1266 new_port0 = udp0->dst_port = s0->in2out.port;
1268 sum0 = tcp0->checksum;
1269 sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1271 dst_address /* changed member */ );
1273 sum0 = ip_csum_update (sum0, old_port0, new_port0,
1274 ip4_header_t /* cheat */ ,
1275 length /* changed member */ );
1276 tcp0->checksum = ip_csum_fold (sum0);
1278 vlib_increment_simple_counter (&nm->counters.slowpath.out2in.tcp,
1279 thread_index, sw_if_index0, 1);
1283 if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1285 old_port0 = vnet_buffer (b0)->ip.reass.l4_dst_port;
1286 new_port0 = udp0->dst_port = s0->in2out.port;
1287 if (PREDICT_FALSE (udp0->checksum))
1289 sum0 = udp0->checksum;
1290 sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t, dst_address /* changed member */
1293 ip_csum_update (sum0, old_port0, new_port0,
1294 ip4_header_t /* cheat */ ,
1295 length /* changed member */ );
1296 udp0->checksum = ip_csum_fold (sum0);
1299 vlib_increment_simple_counter (&nm->counters.slowpath.out2in.udp,
1300 thread_index, sw_if_index0, 1);
1304 nat44_ei_session_update_counters (
1305 s0, now, vlib_buffer_length_in_chain (vm, b0), thread_index);
1306 /* Per-user LRU list maintenance */
1307 nat44_ei_session_update_lru (nm, s0, thread_index);
1310 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
1311 && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1313 nat44_ei_out2in_trace_t *t =
1314 vlib_add_trace (vm, node, b0, sizeof (*t));
1315 t->sw_if_index = sw_if_index0;
1316 t->next_index = next0;
1317 t->session_index = ~0;
1319 t->session_index = s0 - nm->per_thread_data[thread_index].sessions;
1322 if (next0 == NAT44_EI_OUT2IN_NEXT_DROP)
1324 vlib_increment_simple_counter (&nm->counters.slowpath.out2in.drops,
1325 thread_index, sw_if_index0, 1);
1333 vlib_buffer_enqueue_to_next (vm, node, from, (u16 *) nexts,
1336 return frame->n_vectors;
1340 VLIB_REGISTER_NODE (nat44_ei_out2in_node) = {
1341 .name = "nat44-ei-out2in",
1342 .vector_size = sizeof (u32),
1343 .format_trace = format_nat44_ei_out2in_trace,
1344 .type = VLIB_NODE_TYPE_INTERNAL,
1346 .n_errors = ARRAY_LEN(nat44_ei_out2in_error_strings),
1347 .error_strings = nat44_ei_out2in_error_strings,
1349 .runtime_data_bytes = sizeof (nat44_ei_runtime_t),
1351 .n_next_nodes = NAT44_EI_OUT2IN_N_NEXT,
1353 /* edit / add dispositions here */
1355 [NAT44_EI_OUT2IN_NEXT_DROP] = "error-drop",
1356 [NAT44_EI_OUT2IN_NEXT_LOOKUP] = "ip4-lookup",
1357 [NAT44_EI_OUT2IN_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1362 VLIB_NODE_FN (nat44_ei_out2in_fast_node)
1363 (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
1365 u32 n_left_from, *from;
1366 nat44_ei_main_t *nm = &nat44_ei_main;
1368 from = vlib_frame_vector_args (frame);
1369 n_left_from = frame->n_vectors;
1371 vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
1372 u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
1373 vlib_get_buffers (vm, from, b, n_left_from);
1374 while (n_left_from > 0)
1377 u32 next0 = NAT44_EI_OUT2IN_NEXT_DROP;
1381 u32 new_addr0, old_addr0;
1382 u16 new_port0, old_port0;
1385 icmp46_header_t *icmp0;
1388 ip4_address_t sm_addr0;
1395 ip0 = vlib_buffer_get_current (b0);
1396 udp0 = ip4_next_header (ip0);
1397 tcp0 = (tcp_header_t *) udp0;
1398 icmp0 = (icmp46_header_t *) udp0;
1400 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1401 rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
1403 vnet_feature_next (&next0, b0);
1405 if (PREDICT_FALSE (ip0->ttl == 1))
1407 vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1408 icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
1409 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1411 next0 = NAT44_EI_OUT2IN_NEXT_ICMP_ERROR;
1415 proto0 = ip_proto_to_nat_proto (ip0->protocol);
1417 if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_OTHER))
1420 if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP))
1422 next0 = nat44_ei_icmp_out2in (b0, ip0, icmp0, sw_if_index0,
1423 rx_fib_index0, node, next0, ~0, 0);
1427 if (nat44_ei_static_mapping_match (ip0->dst_address, udp0->dst_port,
1428 rx_fib_index0, proto0, &sm_addr0,
1429 &sm_port0, &sm_fib_index0, 1, 0, 0))
1431 b0->error = node->errors[NAT44_EI_OUT2IN_ERROR_NO_TRANSLATION];
1435 new_addr0 = sm_addr0.as_u32;
1436 new_port0 = sm_port0;
1437 vnet_buffer (b0)->sw_if_index[VLIB_TX] = sm_fib_index0;
1438 old_addr0 = ip0->dst_address.as_u32;
1439 ip0->dst_address.as_u32 = new_addr0;
1441 sum0 = ip0->checksum;
1442 sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1443 ip4_header_t, dst_address /* changed member */ );
1444 ip0->checksum = ip_csum_fold (sum0);
1446 if (PREDICT_FALSE (new_port0 != udp0->dst_port))
1448 old_port0 = udp0->dst_port;
1449 udp0->dst_port = new_port0;
1451 if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
1453 sum0 = tcp0->checksum;
1454 sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1456 dst_address /* changed member */ );
1457 sum0 = ip_csum_update (sum0, old_port0, new_port0,
1458 ip4_header_t /* cheat */ ,
1459 length /* changed member */ );
1460 tcp0->checksum = ip_csum_fold (sum0);
1462 else if (udp0->checksum)
1464 sum0 = udp0->checksum;
1465 sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1467 dst_address /* changed member */ );
1468 sum0 = ip_csum_update (sum0, old_port0, new_port0,
1469 ip4_header_t /* cheat */ ,
1470 length /* changed member */ );
1471 udp0->checksum = ip_csum_fold (sum0);
1476 if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
1478 sum0 = tcp0->checksum;
1479 sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1481 dst_address /* changed member */ );
1482 tcp0->checksum = ip_csum_fold (sum0);
1484 else if (udp0->checksum)
1486 sum0 = udp0->checksum;
1487 sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1489 dst_address /* changed member */ );
1490 udp0->checksum = ip_csum_fold (sum0);
1496 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
1497 && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1499 nat44_ei_out2in_trace_t *t =
1500 vlib_add_trace (vm, node, b0, sizeof (*t));
1501 t->sw_if_index = sw_if_index0;
1502 t->next_index = next0;
1505 if (next0 == NAT44_EI_OUT2IN_NEXT_DROP)
1507 vlib_increment_simple_counter (&nm->counters.fastpath.out2in.drops,
1508 vm->thread_index, sw_if_index0, 1);
1516 vlib_buffer_enqueue_to_next (vm, node, from, (u16 *) nexts,
1519 return frame->n_vectors;
1523 VLIB_REGISTER_NODE (nat44_ei_out2in_fast_node) = {
1524 .name = "nat44-ei-out2in-fast",
1525 .vector_size = sizeof (u32),
1526 .format_trace = format_nat44_ei_out2in_fast_trace,
1527 .type = VLIB_NODE_TYPE_INTERNAL,
1529 .n_errors = ARRAY_LEN(nat44_ei_out2in_error_strings),
1530 .error_strings = nat44_ei_out2in_error_strings,
1532 .runtime_data_bytes = sizeof (nat44_ei_runtime_t),
1534 .n_next_nodes = NAT44_EI_OUT2IN_N_NEXT,
1536 /* edit / add dispositions here */
1538 [NAT44_EI_OUT2IN_NEXT_LOOKUP] = "ip4-lookup",
1539 [NAT44_EI_OUT2IN_NEXT_DROP] = "error-drop",
1540 [NAT44_EI_OUT2IN_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1546 * fd.io coding-style-patch-verification: ON
1549 * eval: (c-set-style "gnu")