nat: fix ED mode unknown proto session management
[vpp.git] / src / plugins / nat / out2in_ed.c
1 /*
2  * Copyright (c) 2018 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:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
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.
14  */
15 /**
16  * @file
17  * @brief NAT44 endpoint-dependent outside to inside network translation
18  */
19
20 #include <vlib/vlib.h>
21 #include <vnet/vnet.h>
22 #include <vnet/pg/pg.h>
23 #include <vnet/ip/ip.h>
24 #include <vnet/ethernet/ethernet.h>
25 #include <vnet/fib/ip4_fib.h>
26 #include <vnet/udp/udp.h>
27 #include <vppinfra/error.h>
28 #include <nat/nat.h>
29 #include <nat/nat_ipfix_logging.h>
30 #include <nat/nat_reass.h>
31 #include <nat/nat_inlines.h>
32 #include <nat/nat_syslog.h>
33 #include <nat/nat_ha.h>
34
35 #define foreach_nat_out2in_ed_error                     \
36 _(UNSUPPORTED_PROTOCOL, "unsupported protocol")         \
37 _(OUT2IN_PACKETS, "good out2in packets processed")      \
38 _(OUT_OF_PORTS, "out of ports")                         \
39 _(BAD_ICMP_TYPE, "unsupported ICMP type")               \
40 _(NO_TRANSLATION, "no translation")                     \
41 _(MAX_SESSIONS_EXCEEDED, "maximum sessions exceeded")   \
42 _(DROP_FRAGMENT, "drop fragment")                       \
43 _(MAX_REASS, "maximum reassemblies exceeded")           \
44 _(MAX_FRAG, "maximum fragments per reassembly exceeded")\
45 _(NON_SYN, "non-SYN packet try to create session")      \
46 _(TCP_PACKETS, "TCP packets")                           \
47 _(UDP_PACKETS, "UDP packets")                           \
48 _(ICMP_PACKETS, "ICMP packets")                         \
49 _(OTHER_PACKETS, "other protocol packets")              \
50 _(FRAGMENTS, "fragments")                               \
51 _(CACHED_FRAGMENTS, "cached fragments")                 \
52 _(PROCESSED_FRAGMENTS, "processed fragments")
53
54 typedef enum
55 {
56 #define _(sym,str) NAT_OUT2IN_ED_ERROR_##sym,
57   foreach_nat_out2in_ed_error
58 #undef _
59     NAT_OUT2IN_ED_N_ERROR,
60 } nat_out2in_ed_error_t;
61
62 static char *nat_out2in_ed_error_strings[] = {
63 #define _(sym,string) string,
64   foreach_nat_out2in_ed_error
65 #undef _
66 };
67
68 typedef enum
69 {
70   NAT44_ED_OUT2IN_NEXT_DROP,
71   NAT44_ED_OUT2IN_NEXT_LOOKUP,
72   NAT44_ED_OUT2IN_NEXT_ICMP_ERROR,
73   NAT44_ED_OUT2IN_NEXT_IN2OUT,
74   NAT44_ED_OUT2IN_NEXT_SLOW_PATH,
75   NAT44_ED_OUT2IN_NEXT_REASS,
76   NAT44_ED_OUT2IN_N_NEXT,
77 } nat44_ed_out2in_next_t;
78
79 typedef struct
80 {
81   u32 sw_if_index;
82   u32 next_index;
83   u32 session_index;
84   u32 is_slow_path;
85 } nat44_ed_out2in_trace_t;
86
87 static u8 *
88 format_nat44_ed_out2in_trace (u8 * s, va_list * args)
89 {
90   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
91   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
92   nat44_ed_out2in_trace_t *t = va_arg (*args, nat44_ed_out2in_trace_t *);
93   char *tag;
94
95   tag =
96     t->is_slow_path ? "NAT44_OUT2IN_ED_SLOW_PATH" :
97     "NAT44_OUT2IN_ED_FAST_PATH";
98
99   s = format (s, "%s: sw_if_index %d, next index %d, session %d", tag,
100               t->sw_if_index, t->next_index, t->session_index);
101
102   return s;
103 }
104
105 static inline u32
106 icmp_out2in_ed_slow_path (snat_main_t * sm, vlib_buffer_t * b0,
107                           ip4_header_t * ip0, icmp46_header_t * icmp0,
108                           u32 sw_if_index0, u32 rx_fib_index0,
109                           vlib_node_runtime_t * node, u32 next0, f64 now,
110                           u32 thread_index, snat_session_t ** p_s0)
111 {
112   next0 = icmp_out2in (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
113                        next0, thread_index, p_s0, 0);
114   snat_session_t *s0 = *p_s0;
115   if (PREDICT_TRUE (next0 != NAT44_ED_OUT2IN_NEXT_DROP && s0))
116     {
117       /* Accounting */
118       nat44_session_update_counters (s0, now,
119                                      vlib_buffer_length_in_chain
120                                      (sm->vlib_main, b0), thread_index);
121       /* Per-user LRU list maintenance */
122       nat44_session_update_lru (sm, s0, thread_index);
123     }
124   return next0;
125 }
126
127 #ifndef CLIB_MARCH_VARIANT
128 int
129 nat44_o2i_ed_is_idle_session_cb (clib_bihash_kv_16_8_t * kv, void *arg)
130 {
131   snat_main_t *sm = &snat_main;
132   nat44_is_idle_session_ctx_t *ctx = arg;
133   snat_session_t *s;
134   u64 sess_timeout_time;
135   nat_ed_ses_key_t ed_key;
136   clib_bihash_kv_16_8_t ed_kv;
137   int i;
138   snat_address_t *a;
139   snat_session_key_t key;
140   snat_main_per_thread_data_t *tsm = vec_elt_at_index (sm->per_thread_data,
141                                                        ctx->thread_index);
142
143   s = pool_elt_at_index (tsm->sessions, kv->value);
144   sess_timeout_time = s->last_heard + (f64) nat44_session_get_timeout (sm, s);
145   if (ctx->now >= sess_timeout_time)
146     {
147       ed_key.l_addr = s->in2out.addr;
148       ed_key.r_addr = s->ext_host_addr;
149       ed_key.fib_index = s->in2out.fib_index;
150       if (snat_is_unk_proto_session (s))
151         {
152           ed_key.proto = s->in2out.port;
153           ed_key.r_port = 0;
154           ed_key.l_port = 0;
155         }
156       else
157         {
158           ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
159           ed_key.l_port = s->in2out.port;
160           ed_key.r_port = s->ext_host_port;
161         }
162       if (is_twice_nat_session (s))
163         {
164           ed_key.r_addr = s->ext_host_nat_addr;
165           ed_key.r_port = s->ext_host_nat_port;
166         }
167       ed_kv.key[0] = ed_key.as_u64[0];
168       ed_kv.key[1] = ed_key.as_u64[1];
169       if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))
170         nat_log_warn ("in2out_ed key del failed");
171
172       if (snat_is_unk_proto_session (s))
173         goto delete;
174
175       snat_ipfix_logging_nat44_ses_delete (ctx->thread_index,
176                                            s->in2out.addr.as_u32,
177                                            s->out2in.addr.as_u32,
178                                            s->in2out.protocol,
179                                            s->in2out.port,
180                                            s->out2in.port,
181                                            s->in2out.fib_index);
182
183       nat_syslog_nat44_sdel (s->user_index, s->in2out.fib_index,
184                              &s->in2out.addr, s->in2out.port,
185                              &s->ext_host_nat_addr, s->ext_host_nat_port,
186                              &s->out2in.addr, s->out2in.port,
187                              &s->ext_host_addr, s->ext_host_port,
188                              s->in2out.protocol, is_twice_nat_session (s));
189
190       nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
191                    s->ext_host_port, s->out2in.protocol, s->out2in.fib_index,
192                    ctx->thread_index);
193
194       if (is_twice_nat_session (s))
195         {
196           for (i = 0; i < vec_len (sm->twice_nat_addresses); i++)
197             {
198               key.protocol = s->in2out.protocol;
199               key.port = s->ext_host_nat_port;
200               a = sm->twice_nat_addresses + i;
201               if (a->addr.as_u32 == s->ext_host_nat_addr.as_u32)
202                 {
203                   snat_free_outside_address_and_port (sm->twice_nat_addresses,
204                                                       ctx->thread_index,
205                                                       &key);
206                   break;
207                 }
208             }
209         }
210
211       if (snat_is_session_static (s))
212         goto delete;
213
214       snat_free_outside_address_and_port (sm->addresses, ctx->thread_index,
215                                           &s->out2in);
216     delete:
217       nat44_delete_session (sm, s, ctx->thread_index);
218       return 1;
219     }
220
221   return 0;
222 }
223 #endif
224
225 static snat_session_t *
226 create_session_for_static_mapping_ed (snat_main_t * sm,
227                                       vlib_buffer_t * b,
228                                       snat_session_key_t l_key,
229                                       snat_session_key_t e_key,
230                                       vlib_node_runtime_t * node,
231                                       u32 thread_index,
232                                       twice_nat_type_t twice_nat,
233                                       lb_nat_type_t lb_nat, f64 now)
234 {
235   snat_session_t *s;
236   snat_user_t *u;
237   ip4_header_t *ip;
238   udp_header_t *udp;
239   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
240   clib_bihash_kv_16_8_t kv;
241   snat_session_key_t eh_key;
242   nat44_is_idle_session_ctx_t ctx;
243
244   if (PREDICT_FALSE (maximum_sessions_exceeded (sm, thread_index)))
245     {
246       b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_SESSIONS_EXCEEDED];
247       nat_log_notice ("maximum sessions exceeded");
248       return 0;
249     }
250
251   u = nat_user_get_or_create (sm, &l_key.addr, l_key.fib_index, thread_index);
252   if (!u)
253     {
254       nat_log_warn ("create NAT user failed");
255       return 0;
256     }
257
258   s = nat_ed_session_alloc (sm, u, thread_index, now);
259   if (!s)
260     {
261       nat44_delete_user_with_no_session (sm, u, thread_index);
262       nat_log_warn ("create NAT session failed");
263       return 0;
264     }
265
266   ip = vlib_buffer_get_current (b);
267   udp = ip4_next_header (ip);
268
269   s->ext_host_addr.as_u32 = ip->src_address.as_u32;
270   s->ext_host_port = e_key.protocol == SNAT_PROTOCOL_ICMP ? 0 : udp->src_port;
271   s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
272   if (lb_nat)
273     s->flags |= SNAT_SESSION_FLAG_LOAD_BALANCING;
274   if (lb_nat == AFFINITY_LB_NAT)
275     s->flags |= SNAT_SESSION_FLAG_AFFINITY;
276   s->flags |= SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT;
277   s->out2in = e_key;
278   s->in2out = l_key;
279   s->in2out.protocol = s->out2in.protocol;
280   user_session_increment (sm, u, 1);
281
282   /* Add to lookup tables */
283   make_ed_kv (&kv, &e_key.addr, &s->ext_host_addr, ip->protocol,
284               e_key.fib_index, e_key.port, s->ext_host_port);
285   kv.value = s - tsm->sessions;
286   ctx.now = now;
287   ctx.thread_index = thread_index;
288   if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->out2in_ed, &kv,
289                                                nat44_o2i_ed_is_idle_session_cb,
290                                                &ctx))
291     nat_log_notice ("out2in-ed key add failed");
292
293   if (twice_nat == TWICE_NAT || (twice_nat == TWICE_NAT_SELF &&
294                                  ip->src_address.as_u32 == l_key.addr.as_u32))
295     {
296       eh_key.protocol = e_key.protocol;
297       if (snat_alloc_outside_address_and_port (sm->twice_nat_addresses, 0,
298                                                thread_index, &eh_key,
299                                                sm->port_per_thread,
300                                                tsm->snat_thread_index))
301         {
302           b->error = node->errors[NAT_OUT2IN_ED_ERROR_OUT_OF_PORTS];
303           nat44_delete_session (sm, s, thread_index);
304           if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &kv, 0))
305             nat_log_notice ("out2in-ed key del failed");
306           return 0;
307         }
308       s->ext_host_nat_addr.as_u32 = eh_key.addr.as_u32;
309       s->ext_host_nat_port = eh_key.port;
310       s->flags |= SNAT_SESSION_FLAG_TWICE_NAT;
311       make_ed_kv (&kv, &l_key.addr, &s->ext_host_nat_addr, ip->protocol,
312                   l_key.fib_index, l_key.port, s->ext_host_nat_port);
313     }
314   else
315     {
316       make_ed_kv (&kv, &l_key.addr, &s->ext_host_addr, ip->protocol,
317                   l_key.fib_index, l_key.port, s->ext_host_port);
318     }
319   kv.value = s - tsm->sessions;
320   if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->in2out_ed, &kv,
321                                                nat44_i2o_ed_is_idle_session_cb,
322                                                &ctx))
323     nat_log_notice ("in2out-ed key add failed");
324
325   snat_ipfix_logging_nat44_ses_create (thread_index,
326                                        s->in2out.addr.as_u32,
327                                        s->out2in.addr.as_u32,
328                                        s->in2out.protocol,
329                                        s->in2out.port,
330                                        s->out2in.port, s->in2out.fib_index);
331
332   nat_syslog_nat44_sadd (s->user_index, s->in2out.fib_index,
333                          &s->in2out.addr, s->in2out.port,
334                          &s->ext_host_nat_addr, s->ext_host_nat_port,
335                          &s->out2in.addr, s->out2in.port,
336                          &s->ext_host_addr, s->ext_host_port,
337                          s->in2out.protocol, is_twice_nat_session (s));
338
339   nat_ha_sadd (&s->in2out.addr, s->in2out.port, &s->out2in.addr,
340                s->out2in.port, &s->ext_host_addr, s->ext_host_port,
341                &s->ext_host_nat_addr, s->ext_host_nat_port,
342                s->in2out.protocol, s->in2out.fib_index, s->flags,
343                thread_index, 0);
344
345   return s;
346 }
347
348 static_always_inline int
349 icmp_get_ed_key (ip4_header_t * ip0, nat_ed_ses_key_t * p_key0)
350 {
351   icmp46_header_t *icmp0;
352   nat_ed_ses_key_t key0;
353   icmp_echo_header_t *echo0, *inner_echo0 = 0;
354   ip4_header_t *inner_ip0;
355   void *l4_header = 0;
356   icmp46_header_t *inner_icmp0;
357
358   icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
359   echo0 = (icmp_echo_header_t *) (icmp0 + 1);
360
361   if (!icmp_is_error_message (icmp0))
362     {
363       key0.proto = IP_PROTOCOL_ICMP;
364       key0.l_addr = ip0->dst_address;
365       key0.r_addr = ip0->src_address;
366       key0.l_port = echo0->identifier;
367       key0.r_port = 0;
368     }
369   else
370     {
371       inner_ip0 = (ip4_header_t *) (echo0 + 1);
372       l4_header = ip4_next_header (inner_ip0);
373       key0.proto = inner_ip0->protocol;
374       key0.l_addr = inner_ip0->src_address;
375       key0.r_addr = inner_ip0->dst_address;
376       switch (ip_proto_to_snat_proto (inner_ip0->protocol))
377         {
378         case SNAT_PROTOCOL_ICMP:
379           inner_icmp0 = (icmp46_header_t *) l4_header;
380           inner_echo0 = (icmp_echo_header_t *) (inner_icmp0 + 1);
381           key0.l_port = inner_echo0->identifier;
382           key0.r_port = 0;
383           break;
384         case SNAT_PROTOCOL_UDP:
385         case SNAT_PROTOCOL_TCP:
386           key0.l_port = ((tcp_udp_header_t *) l4_header)->src_port;
387           key0.r_port = ((tcp_udp_header_t *) l4_header)->dst_port;
388           break;
389         default:
390           return -1;
391         }
392     }
393   *p_key0 = key0;
394   return 0;
395 }
396
397 static int
398 next_src_nat (snat_main_t * sm, ip4_header_t * ip, u8 proto, u16 src_port,
399               u16 dst_port, u32 thread_index, u32 rx_fib_index)
400 {
401   clib_bihash_kv_16_8_t kv, value;
402   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
403
404   make_ed_kv (&kv, &ip->src_address, &ip->dst_address, proto,
405               rx_fib_index, src_port, dst_port);
406   if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
407     return 1;
408
409   return 0;
410 }
411
412 static void
413 create_bypass_for_fwd (snat_main_t * sm, ip4_header_t * ip, u32 rx_fib_index,
414                        u32 thread_index)
415 {
416   nat_ed_ses_key_t key;
417   clib_bihash_kv_16_8_t kv, value;
418   udp_header_t *udp;
419   snat_user_t *u;
420   snat_session_t *s = 0;
421   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
422   f64 now = vlib_time_now (sm->vlib_main);
423
424   if (ip->protocol == IP_PROTOCOL_ICMP)
425     {
426       if (icmp_get_ed_key (ip, &key))
427         return;
428     }
429   else if (ip->protocol == IP_PROTOCOL_UDP || ip->protocol == IP_PROTOCOL_TCP)
430     {
431       udp = ip4_next_header (ip);
432       key.r_addr = ip->src_address;
433       key.l_addr = ip->dst_address;
434       key.proto = ip->protocol;
435       key.l_port = udp->dst_port;
436       key.r_port = udp->src_port;
437     }
438   else
439     {
440       key.r_addr = ip->src_address;
441       key.l_addr = ip->dst_address;
442       key.proto = ip->protocol;
443       key.l_port = key.r_port = 0;
444     }
445   key.fib_index = 0;
446   kv.key[0] = key.as_u64[0];
447   kv.key[1] = key.as_u64[1];
448
449   if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
450     {
451       s = pool_elt_at_index (tsm->sessions, value.value);
452     }
453   else
454     {
455       u32 proto;
456
457       if (PREDICT_FALSE (maximum_sessions_exceeded (sm, thread_index)))
458         return;
459
460       u = nat_user_get_or_create (sm, &ip->dst_address, sm->inside_fib_index,
461                                   thread_index);
462       if (!u)
463         {
464           nat_log_warn ("create NAT user failed");
465           return;
466         }
467
468       s = nat_ed_session_alloc (sm, u, thread_index, now);
469       if (!s)
470         {
471           nat44_delete_user_with_no_session (sm, u, thread_index);
472           nat_log_warn ("create NAT session failed");
473           return;
474         }
475
476       proto = ip_proto_to_snat_proto (key.proto);
477
478       s->ext_host_addr = key.r_addr;
479       s->ext_host_port = key.r_port;
480       s->flags |= SNAT_SESSION_FLAG_FWD_BYPASS;
481       s->out2in.addr = key.l_addr;
482       s->out2in.port = key.l_port;
483       s->out2in.protocol = proto;
484       if (proto == ~0)
485         {
486           s->flags |= SNAT_SESSION_FLAG_UNKNOWN_PROTO;
487           s->out2in.port = ip->protocol;
488         }
489       s->out2in.fib_index = 0;
490       s->in2out = s->out2in;
491       user_session_increment (sm, u, 0);
492
493       kv.value = s - tsm->sessions;
494       if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &kv, 1))
495         nat_log_notice ("in2out_ed key add failed");
496     }
497
498   if (ip->protocol == IP_PROTOCOL_TCP)
499     {
500       tcp_header_t *tcp = ip4_next_header (ip);
501       if (nat44_set_tcp_session_state_o2i (sm, s, tcp, thread_index))
502         return;
503     }
504
505   /* Accounting */
506   nat44_session_update_counters (s, now, 0, thread_index);
507   /* Per-user LRU list maintenance */
508   nat44_session_update_lru (sm, s, thread_index);
509 }
510
511 #ifndef CLIB_MARCH_VARIANT
512 u32
513 icmp_match_out2in_ed (snat_main_t * sm, vlib_node_runtime_t * node,
514                       u32 thread_index, vlib_buffer_t * b, ip4_header_t * ip,
515                       u8 * p_proto, snat_session_key_t * p_value,
516                       u8 * p_dont_translate, void *d, void *e)
517 {
518   u32 next = ~0, sw_if_index, rx_fib_index;
519   icmp46_header_t *icmp;
520   nat_ed_ses_key_t key;
521   clib_bihash_kv_16_8_t kv, value;
522   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
523   snat_session_t *s = 0;
524   u8 dont_translate = 0, is_addr_only, identity_nat;
525   snat_session_key_t e_key, l_key;
526
527   icmp = (icmp46_header_t *) ip4_next_header (ip);
528   sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
529   rx_fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
530
531   if (icmp_get_ed_key (ip, &key))
532     {
533       b->error = node->errors[NAT_OUT2IN_ED_ERROR_UNSUPPORTED_PROTOCOL];
534       next = NAT44_ED_OUT2IN_NEXT_DROP;
535       goto out;
536     }
537   key.fib_index = rx_fib_index;
538   kv.key[0] = key.as_u64[0];
539   kv.key[1] = key.as_u64[1];
540
541   if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
542     {
543       /* Try to match static mapping */
544       e_key.addr = ip->dst_address;
545       e_key.port = key.l_port;
546       e_key.protocol = ip_proto_to_snat_proto (key.proto);
547       e_key.fib_index = rx_fib_index;
548       if (snat_static_mapping_match
549           (sm, e_key, &l_key, 1, &is_addr_only, 0, 0, 0, &identity_nat))
550         {
551           if (!sm->forwarding_enabled)
552             {
553               /* Don't NAT packet aimed at the intfc address */
554               if (PREDICT_FALSE (is_interface_addr (sm, node, sw_if_index,
555                                                     ip->dst_address.as_u32)))
556                 {
557                   dont_translate = 1;
558                   goto out;
559                 }
560               b->error = node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
561               next = NAT44_ED_OUT2IN_NEXT_DROP;
562               goto out;
563             }
564           else
565             {
566               dont_translate = 1;
567               if (next_src_nat (sm, ip, key.proto, key.l_port, key.r_port,
568                                 thread_index, rx_fib_index))
569                 {
570                   next = NAT44_ED_OUT2IN_NEXT_IN2OUT;
571                   goto out;
572                 }
573               create_bypass_for_fwd (sm, ip, rx_fib_index, thread_index);
574               goto out;
575             }
576         }
577
578       if (PREDICT_FALSE (icmp->type != ICMP4_echo_reply &&
579                          (icmp->type != ICMP4_echo_request || !is_addr_only)))
580         {
581           b->error = node->errors[NAT_OUT2IN_ED_ERROR_BAD_ICMP_TYPE];
582           next = NAT44_ED_OUT2IN_NEXT_DROP;
583           goto out;
584         }
585
586       if (PREDICT_FALSE (identity_nat))
587         {
588           dont_translate = 1;
589           goto out;
590         }
591
592       /* Create session initiated by host from external network */
593       s = create_session_for_static_mapping_ed (sm, b, l_key, e_key, node,
594                                                 thread_index, 0, 0,
595                                                 vlib_time_now
596                                                 (sm->vlib_main));
597
598       if (!s)
599         {
600           next = NAT44_ED_OUT2IN_NEXT_DROP;
601           goto out;
602         }
603     }
604   else
605     {
606       if (PREDICT_FALSE (icmp->type != ICMP4_echo_reply &&
607                          icmp->type != ICMP4_echo_request &&
608                          !icmp_is_error_message (icmp)))
609         {
610           b->error = node->errors[NAT_OUT2IN_ED_ERROR_BAD_ICMP_TYPE];
611           next = NAT44_ED_OUT2IN_NEXT_DROP;
612           goto out;
613         }
614
615       s = pool_elt_at_index (tsm->sessions, value.value);
616     }
617
618   *p_proto = ip_proto_to_snat_proto (key.proto);
619 out:
620   if (s)
621     *p_value = s->in2out;
622   *p_dont_translate = dont_translate;
623   if (d)
624     *(snat_session_t **) d = s;
625   return next;
626 }
627 #endif
628
629 static snat_session_t *
630 nat44_ed_out2in_unknown_proto (snat_main_t * sm,
631                                vlib_buffer_t * b,
632                                ip4_header_t * ip,
633                                u32 rx_fib_index,
634                                u32 thread_index,
635                                f64 now,
636                                vlib_main_t * vm, vlib_node_runtime_t * node)
637 {
638   clib_bihash_kv_8_8_t kv, value;
639   clib_bihash_kv_16_8_t s_kv, s_value;
640   snat_static_mapping_t *m;
641   u32 old_addr, new_addr;
642   ip_csum_t sum;
643   snat_session_t *s;
644   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
645   snat_user_t *u;
646
647   old_addr = ip->dst_address.as_u32;
648
649   make_ed_kv (&s_kv, &ip->dst_address, &ip->src_address, ip->protocol,
650               rx_fib_index, 0, 0);
651
652   if (!clib_bihash_search_16_8 (&tsm->out2in_ed, &s_kv, &s_value))
653     {
654       s = pool_elt_at_index (tsm->sessions, s_value.value);
655       new_addr = ip->dst_address.as_u32 = s->in2out.addr.as_u32;
656     }
657   else
658     {
659       if (PREDICT_FALSE (maximum_sessions_exceeded (sm, thread_index)))
660         {
661           b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_SESSIONS_EXCEEDED];
662           nat_log_notice ("maximum sessions exceeded");
663           return 0;
664         }
665
666       make_sm_kv (&kv, &ip->dst_address, 0, 0, 0);
667       if (clib_bihash_search_8_8
668           (&sm->static_mapping_by_external, &kv, &value))
669         {
670           b->error = node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
671           return 0;
672         }
673
674       m = pool_elt_at_index (sm->static_mappings, value.value);
675
676       new_addr = ip->dst_address.as_u32 = m->local_addr.as_u32;
677
678       u = nat_user_get_or_create (sm, &m->local_addr, m->fib_index,
679                                   thread_index);
680       if (!u)
681         {
682           nat_log_warn ("create NAT user failed");
683           return 0;
684         }
685
686       /* Create a new session */
687       s = nat_ed_session_alloc (sm, u, thread_index, now);
688       if (!s)
689         {
690           nat44_delete_user_with_no_session (sm, u, thread_index);
691           nat_log_warn ("create NAT session failed");
692           return 0;
693         }
694
695       s->ext_host_addr.as_u32 = ip->src_address.as_u32;
696       s->flags |= SNAT_SESSION_FLAG_UNKNOWN_PROTO;
697       s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
698       s->flags |= SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT;
699       s->out2in.addr.as_u32 = old_addr;
700       s->out2in.fib_index = rx_fib_index;
701       s->in2out.addr.as_u32 = new_addr;
702       s->in2out.fib_index = m->fib_index;
703       s->in2out.port = s->out2in.port = ip->protocol;
704       user_session_increment (sm, u, 1);
705
706       /* Add to lookup tables */
707       s_kv.value = s - tsm->sessions;
708       if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &s_kv, 1))
709         nat_log_notice ("out2in key add failed");
710
711       make_ed_kv (&s_kv, &ip->dst_address, &ip->src_address, ip->protocol,
712                   m->fib_index, 0, 0);
713       s_kv.value = s - tsm->sessions;
714       if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &s_kv, 1))
715         nat_log_notice ("in2out key add failed");
716     }
717
718   /* Update IP checksum */
719   sum = ip->checksum;
720   sum = ip_csum_update (sum, old_addr, new_addr, ip4_header_t, dst_address);
721   ip->checksum = ip_csum_fold (sum);
722
723   vnet_buffer (b)->sw_if_index[VLIB_TX] = s->in2out.fib_index;
724
725   /* Accounting */
726   nat44_session_update_counters (s, now, vlib_buffer_length_in_chain (vm, b),
727                                  thread_index);
728   /* Per-user LRU list maintenance */
729   nat44_session_update_lru (sm, s, thread_index);
730
731   return s;
732 }
733
734 static inline uword
735 nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
736                                 vlib_node_runtime_t * node,
737                                 vlib_frame_t * frame, int is_slow_path)
738 {
739   u32 n_left_from, *from, *to_next, pkts_processed = 0, stats_node_index;
740   nat44_ed_out2in_next_t next_index;
741   snat_main_t *sm = &snat_main;
742   f64 now = vlib_time_now (vm);
743   u32 thread_index = vm->thread_index;
744   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
745   u32 tcp_packets = 0, udp_packets = 0, icmp_packets = 0, other_packets =
746     0, fragments = 0;
747
748   stats_node_index = is_slow_path ? sm->ed_out2in_slowpath_node_index :
749     sm->ed_out2in_node_index;
750
751   from = vlib_frame_vector_args (frame);
752   n_left_from = frame->n_vectors;
753   next_index = node->cached_next_index;
754
755   while (n_left_from > 0)
756     {
757       u32 n_left_to_next;
758
759       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
760
761       while (n_left_from >= 4 && n_left_to_next >= 2)
762         {
763           u32 bi0, bi1;
764           vlib_buffer_t *b0, *b1;
765           u32 next0, sw_if_index0, rx_fib_index0, proto0, old_addr0,
766             new_addr0;
767           u32 next1, sw_if_index1, rx_fib_index1, proto1, old_addr1,
768             new_addr1;
769           u16 old_port0, new_port0, old_port1, new_port1;
770           ip4_header_t *ip0, *ip1;
771           udp_header_t *udp0, *udp1;
772           tcp_header_t *tcp0, *tcp1;
773           icmp46_header_t *icmp0, *icmp1;
774           snat_session_t *s0 = 0, *s1 = 0;
775           clib_bihash_kv_16_8_t kv0, value0, kv1, value1;
776           ip_csum_t sum0, sum1;
777           snat_session_key_t e_key0, l_key0, e_key1, l_key1;
778           lb_nat_type_t lb_nat0, lb_nat1;
779           twice_nat_type_t twice_nat0, twice_nat1;
780           u8 identity_nat0, identity_nat1;
781
782           /* Prefetch next iteration. */
783           {
784             vlib_buffer_t *p2, *p3;
785
786             p2 = vlib_get_buffer (vm, from[2]);
787             p3 = vlib_get_buffer (vm, from[3]);
788
789             vlib_prefetch_buffer_header (p2, LOAD);
790             vlib_prefetch_buffer_header (p3, LOAD);
791
792             CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
793             CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
794           }
795
796           /* speculatively enqueue b0 and b1 to the current next frame */
797           to_next[0] = bi0 = from[0];
798           to_next[1] = bi1 = from[1];
799           from += 2;
800           to_next += 2;
801           n_left_from -= 2;
802           n_left_to_next -= 2;
803
804           b0 = vlib_get_buffer (vm, bi0);
805           b1 = vlib_get_buffer (vm, bi1);
806
807           next0 = NAT44_ED_OUT2IN_NEXT_LOOKUP;
808           vnet_buffer (b0)->snat.flags = 0;
809           ip0 = vlib_buffer_get_current (b0);
810
811           sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
812           rx_fib_index0 =
813             fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
814                                                  sw_if_index0);
815
816           if (PREDICT_FALSE (ip0->ttl == 1))
817             {
818               vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
819               icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
820                                            ICMP4_time_exceeded_ttl_exceeded_in_transit,
821                                            0);
822               next0 = NAT44_ED_OUT2IN_NEXT_ICMP_ERROR;
823               goto trace00;
824             }
825
826           udp0 = ip4_next_header (ip0);
827           tcp0 = (tcp_header_t *) udp0;
828           icmp0 = (icmp46_header_t *) udp0;
829           proto0 = ip_proto_to_snat_proto (ip0->protocol);
830
831           if (is_slow_path)
832             {
833               if (PREDICT_FALSE (proto0 == ~0))
834                 {
835                   s0 =
836                     nat44_ed_out2in_unknown_proto (sm, b0, ip0, rx_fib_index0,
837                                                    thread_index, now, vm,
838                                                    node);
839                   other_packets++;
840                   if (!sm->forwarding_enabled)
841                     {
842                       if (!s0)
843                         next0 = NAT44_ED_OUT2IN_NEXT_DROP;
844                       goto trace00;
845                     }
846                 }
847
848               if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
849                 {
850                   next0 = icmp_out2in_ed_slow_path
851                     (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
852                      next0, now, thread_index, &s0);
853                   icmp_packets++;
854                   goto trace00;
855                 }
856             }
857           else
858             {
859               if (PREDICT_FALSE (proto0 == ~0))
860                 {
861                   next0 = NAT44_ED_OUT2IN_NEXT_SLOW_PATH;
862                   goto trace00;
863                 }
864
865               if (ip4_is_fragment (ip0))
866                 {
867                   next0 = NAT44_ED_OUT2IN_NEXT_REASS;
868                   fragments++;
869                   goto trace00;
870                 }
871
872               if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
873                 {
874                   next0 = NAT44_ED_OUT2IN_NEXT_SLOW_PATH;
875                   goto trace00;
876                 }
877             }
878
879           make_ed_kv (&kv0, &ip0->dst_address, &ip0->src_address,
880                       ip0->protocol, rx_fib_index0, udp0->dst_port,
881                       udp0->src_port);
882
883           if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv0, &value0))
884             {
885               if (is_slow_path)
886                 {
887                   /* Try to match static mapping by external address and port,
888                      destination address and port in packet */
889                   e_key0.addr = ip0->dst_address;
890                   e_key0.port = udp0->dst_port;
891                   e_key0.protocol = proto0;
892                   e_key0.fib_index = rx_fib_index0;
893                   if (snat_static_mapping_match (sm, e_key0, &l_key0, 1, 0,
894                                                  &twice_nat0, &lb_nat0,
895                                                  &ip0->src_address,
896                                                  &identity_nat0))
897                     {
898                       /*
899                        * Send DHCP packets to the ipv4 stack, or we won't
900                        * be able to use dhcp client on the outside interface
901                        */
902                       if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_UDP
903                                          && (udp0->dst_port ==
904                                              clib_host_to_net_u16
905                                              (UDP_DST_PORT_dhcp_to_client))))
906                         {
907                           vnet_feature_next (&next0, b0);
908                           goto trace00;
909                         }
910
911                       if (!sm->forwarding_enabled)
912                         {
913                           b0->error =
914                             node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
915                           next0 = NAT44_ED_OUT2IN_NEXT_DROP;
916                         }
917                       else
918                         {
919                           if (next_src_nat (sm, ip0, ip0->protocol,
920                                             udp0->src_port, udp0->dst_port,
921                                             thread_index, rx_fib_index0))
922                             {
923                               next0 = NAT44_ED_OUT2IN_NEXT_IN2OUT;
924                               goto trace00;
925                             }
926                           create_bypass_for_fwd (sm, ip0, rx_fib_index0,
927                                                  thread_index);
928                         }
929                       goto trace00;
930                     }
931
932                   if (PREDICT_FALSE (identity_nat0))
933                     goto trace00;
934
935                   if ((proto0 == SNAT_PROTOCOL_TCP) && !tcp_is_init (tcp0))
936                     {
937                       b0->error = node->errors[NAT_OUT2IN_ED_ERROR_NON_SYN];
938                       next0 = NAT44_ED_OUT2IN_NEXT_DROP;
939                       goto trace00;
940                     }
941
942                   /* Create session initiated by host from external network */
943                   s0 = create_session_for_static_mapping_ed (sm, b0, l_key0,
944                                                              e_key0, node,
945                                                              thread_index,
946                                                              twice_nat0,
947                                                              lb_nat0, now);
948
949                   if (!s0)
950                     {
951                       next0 = NAT44_ED_OUT2IN_NEXT_DROP;
952                       goto trace00;
953                     }
954                 }
955               else
956                 {
957                   next0 = NAT44_ED_OUT2IN_NEXT_SLOW_PATH;
958                   goto trace00;
959                 }
960             }
961           else
962             {
963               s0 = pool_elt_at_index (tsm->sessions, value0.value);
964             }
965
966           old_addr0 = ip0->dst_address.as_u32;
967           new_addr0 = ip0->dst_address.as_u32 = s0->in2out.addr.as_u32;
968           vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
969
970           sum0 = ip0->checksum;
971           sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
972                                  dst_address);
973           if (PREDICT_FALSE (is_twice_nat_session (s0)))
974             sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
975                                    s0->ext_host_nat_addr.as_u32, ip4_header_t,
976                                    src_address);
977           ip0->checksum = ip_csum_fold (sum0);
978
979           if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
980             {
981               old_port0 = tcp0->dst_port;
982               new_port0 = tcp0->dst_port = s0->in2out.port;
983
984               sum0 = tcp0->checksum;
985               sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
986                                      dst_address);
987               sum0 = ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
988                                      length);
989               if (is_twice_nat_session (s0))
990                 {
991                   sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
992                                          s0->ext_host_nat_addr.as_u32,
993                                          ip4_header_t, dst_address);
994                   sum0 = ip_csum_update (sum0, tcp0->src_port,
995                                          s0->ext_host_nat_port, ip4_header_t,
996                                          length);
997                   tcp0->src_port = s0->ext_host_nat_port;
998                   ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
999                 }
1000               tcp0->checksum = ip_csum_fold (sum0);
1001               tcp_packets++;
1002               if (nat44_set_tcp_session_state_o2i
1003                   (sm, s0, tcp0, thread_index))
1004                 goto trace00;
1005             }
1006           else
1007             {
1008               udp0->dst_port = s0->in2out.port;
1009               if (is_twice_nat_session (s0))
1010                 {
1011                   udp0->src_port = s0->ext_host_nat_port;
1012                   ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
1013                 }
1014               udp0->checksum = 0;
1015               udp_packets++;
1016             }
1017
1018           /* Accounting */
1019           nat44_session_update_counters (s0, now,
1020                                          vlib_buffer_length_in_chain (vm, b0),
1021                                          thread_index);
1022           /* Per-user LRU list maintenance */
1023           nat44_session_update_lru (sm, s0, thread_index);
1024
1025         trace00:
1026           if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
1027                              && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1028             {
1029               nat44_ed_out2in_trace_t *t =
1030                 vlib_add_trace (vm, node, b0, sizeof (*t));
1031               t->is_slow_path = is_slow_path;
1032               t->sw_if_index = sw_if_index0;
1033               t->next_index = next0;
1034               t->session_index = ~0;
1035               if (s0)
1036                 t->session_index = s0 - tsm->sessions;
1037             }
1038
1039           pkts_processed += next0 == NAT44_ED_OUT2IN_NEXT_LOOKUP;
1040
1041           next1 = NAT44_ED_OUT2IN_NEXT_LOOKUP;
1042           vnet_buffer (b1)->snat.flags = 0;
1043           ip1 = vlib_buffer_get_current (b1);
1044
1045           sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1046           rx_fib_index1 =
1047             fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
1048                                                  sw_if_index1);
1049
1050           if (PREDICT_FALSE (ip1->ttl == 1))
1051             {
1052               vnet_buffer (b1)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1053               icmp4_error_set_vnet_buffer (b1, ICMP4_time_exceeded,
1054                                            ICMP4_time_exceeded_ttl_exceeded_in_transit,
1055                                            0);
1056               next1 = NAT44_ED_OUT2IN_NEXT_ICMP_ERROR;
1057               goto trace01;
1058             }
1059
1060           udp1 = ip4_next_header (ip1);
1061           tcp1 = (tcp_header_t *) udp1;
1062           icmp1 = (icmp46_header_t *) udp1;
1063           proto1 = ip_proto_to_snat_proto (ip1->protocol);
1064
1065           if (is_slow_path)
1066             {
1067               if (PREDICT_FALSE (proto1 == ~0))
1068                 {
1069                   s1 =
1070                     nat44_ed_out2in_unknown_proto (sm, b1, ip1, rx_fib_index1,
1071                                                    thread_index, now, vm,
1072                                                    node);
1073                   other_packets++;
1074                   if (!sm->forwarding_enabled)
1075                     {
1076                       if (!s1)
1077                         next1 = NAT44_ED_OUT2IN_NEXT_DROP;
1078                       goto trace01;
1079                     }
1080                 }
1081
1082               if (PREDICT_FALSE (proto1 == SNAT_PROTOCOL_ICMP))
1083                 {
1084                   next1 = icmp_out2in_ed_slow_path
1085                     (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node,
1086                      next1, now, thread_index, &s1);
1087                   icmp_packets++;
1088                   goto trace01;
1089                 }
1090             }
1091           else
1092             {
1093               if (PREDICT_FALSE (proto1 == ~0))
1094                 {
1095                   next1 = NAT44_ED_OUT2IN_NEXT_SLOW_PATH;
1096                   goto trace01;
1097                 }
1098
1099               if (ip4_is_fragment (ip1))
1100                 {
1101                   next1 = NAT44_ED_OUT2IN_NEXT_REASS;
1102                   fragments++;
1103                   goto trace01;
1104                 }
1105
1106               if (PREDICT_FALSE (proto1 == SNAT_PROTOCOL_ICMP))
1107                 {
1108                   next1 = NAT44_ED_OUT2IN_NEXT_SLOW_PATH;
1109                   goto trace01;
1110                 }
1111             }
1112
1113           make_ed_kv (&kv1, &ip1->dst_address, &ip1->src_address,
1114                       ip1->protocol, rx_fib_index1, udp1->dst_port,
1115                       udp1->src_port);
1116
1117           if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv1, &value1))
1118             {
1119               if (is_slow_path)
1120                 {
1121                   /* Try to match static mapping by external address and port,
1122                      destination address and port in packet */
1123                   e_key1.addr = ip1->dst_address;
1124                   e_key1.port = udp1->dst_port;
1125                   e_key1.protocol = proto1;
1126                   e_key1.fib_index = rx_fib_index1;
1127                   if (snat_static_mapping_match (sm, e_key1, &l_key1, 1, 0,
1128                                                  &twice_nat1, &lb_nat1,
1129                                                  &ip1->src_address,
1130                                                  &identity_nat1))
1131                     {
1132                       /*
1133                        * Send DHCP packets to the ipv4 stack, or we won't
1134                        * be able to use dhcp client on the outside interface
1135                        */
1136                       if (PREDICT_FALSE (proto1 == SNAT_PROTOCOL_UDP
1137                                          && (udp1->dst_port ==
1138                                              clib_host_to_net_u16
1139                                              (UDP_DST_PORT_dhcp_to_client))))
1140                         {
1141                           vnet_feature_next (&next1, b1);
1142                           goto trace01;
1143                         }
1144
1145                       if (!sm->forwarding_enabled)
1146                         {
1147                           b1->error =
1148                             node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
1149                           next1 = NAT44_ED_OUT2IN_NEXT_DROP;
1150                         }
1151                       else
1152                         {
1153                           if (next_src_nat (sm, ip1, ip1->protocol,
1154                                             udp1->src_port, udp1->dst_port,
1155                                             thread_index, rx_fib_index1))
1156                             {
1157                               next1 = NAT44_ED_OUT2IN_NEXT_IN2OUT;
1158                               goto trace01;
1159                             }
1160                           create_bypass_for_fwd (sm, ip1, rx_fib_index1,
1161                                                  thread_index);
1162                         }
1163                       goto trace01;
1164                     }
1165
1166                   if (PREDICT_FALSE (identity_nat1))
1167                     goto trace01;
1168
1169                   if ((proto1 == SNAT_PROTOCOL_TCP) && !tcp_is_init (tcp1))
1170                     {
1171                       b1->error = node->errors[NAT_OUT2IN_ED_ERROR_NON_SYN];
1172                       next1 = NAT44_ED_OUT2IN_NEXT_DROP;
1173                       goto trace01;
1174                     }
1175
1176                   /* Create session initiated by host from external network */
1177                   s1 = create_session_for_static_mapping_ed (sm, b1, l_key1,
1178                                                              e_key1, node,
1179                                                              thread_index,
1180                                                              twice_nat1,
1181                                                              lb_nat1, now);
1182
1183                   if (!s1)
1184                     {
1185                       next1 = NAT44_ED_OUT2IN_NEXT_DROP;
1186                       goto trace01;
1187                     }
1188                 }
1189               else
1190                 {
1191                   next1 = NAT44_ED_OUT2IN_NEXT_SLOW_PATH;
1192                   goto trace01;
1193                 }
1194             }
1195           else
1196             {
1197               s1 = pool_elt_at_index (tsm->sessions, value1.value);
1198             }
1199
1200           old_addr1 = ip1->dst_address.as_u32;
1201           new_addr1 = ip1->dst_address.as_u32 = s1->in2out.addr.as_u32;
1202           vnet_buffer (b1)->sw_if_index[VLIB_TX] = s1->in2out.fib_index;
1203
1204           sum1 = ip1->checksum;
1205           sum1 = ip_csum_update (sum1, old_addr1, new_addr1, ip4_header_t,
1206                                  dst_address);
1207           if (PREDICT_FALSE (is_twice_nat_session (s1)))
1208             sum1 = ip_csum_update (sum1, ip1->src_address.as_u32,
1209                                    s1->ext_host_nat_addr.as_u32, ip4_header_t,
1210                                    src_address);
1211           ip1->checksum = ip_csum_fold (sum1);
1212
1213           if (PREDICT_TRUE (proto1 == SNAT_PROTOCOL_TCP))
1214             {
1215               old_port1 = tcp1->dst_port;
1216               new_port1 = tcp1->dst_port = s1->in2out.port;
1217
1218               sum1 = tcp1->checksum;
1219               sum1 = ip_csum_update (sum1, old_addr1, new_addr1, ip4_header_t,
1220                                      dst_address);
1221               sum1 = ip_csum_update (sum1, old_port1, new_port1, ip4_header_t,
1222                                      length);
1223               if (is_twice_nat_session (s1))
1224                 {
1225                   sum1 = ip_csum_update (sum1, ip1->src_address.as_u32,
1226                                          s1->ext_host_nat_addr.as_u32,
1227                                          ip4_header_t, dst_address);
1228                   sum1 = ip_csum_update (sum1, tcp1->src_port,
1229                                          s1->ext_host_nat_port, ip4_header_t,
1230                                          length);
1231                   tcp1->src_port = s1->ext_host_nat_port;
1232                   ip1->src_address.as_u32 = s1->ext_host_nat_addr.as_u32;
1233                 }
1234               tcp1->checksum = ip_csum_fold (sum1);
1235               tcp_packets++;
1236               if (nat44_set_tcp_session_state_o2i
1237                   (sm, s1, tcp1, thread_index))
1238                 goto trace01;
1239             }
1240           else
1241             {
1242               udp1->dst_port = s1->in2out.port;
1243               if (is_twice_nat_session (s1))
1244                 {
1245                   udp1->src_port = s1->ext_host_nat_port;
1246                   ip1->src_address.as_u32 = s1->ext_host_nat_addr.as_u32;
1247                 }
1248               udp1->checksum = 0;
1249               udp_packets++;
1250             }
1251
1252           /* Accounting */
1253           nat44_session_update_counters (s1, now,
1254                                          vlib_buffer_length_in_chain (vm, b1),
1255                                          thread_index);
1256           /* Per-user LRU list maintenance */
1257           nat44_session_update_lru (sm, s1, thread_index);
1258
1259         trace01:
1260           if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
1261                              && (b1->flags & VLIB_BUFFER_IS_TRACED)))
1262             {
1263               nat44_ed_out2in_trace_t *t =
1264                 vlib_add_trace (vm, node, b1, sizeof (*t));
1265               t->is_slow_path = is_slow_path;
1266               t->sw_if_index = sw_if_index1;
1267               t->next_index = next1;
1268               t->session_index = ~0;
1269               if (s1)
1270                 t->session_index = s1 - tsm->sessions;
1271             }
1272
1273           pkts_processed += next1 == NAT44_ED_OUT2IN_NEXT_LOOKUP;
1274
1275           /* verify speculative enqueues, maybe switch current next frame */
1276           vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
1277                                            to_next, n_left_to_next,
1278                                            bi0, bi1, next0, next1);
1279         }
1280
1281       while (n_left_from > 0 && n_left_to_next > 0)
1282         {
1283           u32 bi0;
1284           vlib_buffer_t *b0;
1285           u32 next0, sw_if_index0, rx_fib_index0, proto0, old_addr0,
1286             new_addr0;
1287           u16 old_port0, new_port0;
1288           ip4_header_t *ip0;
1289           udp_header_t *udp0;
1290           tcp_header_t *tcp0;
1291           icmp46_header_t *icmp0;
1292           snat_session_t *s0 = 0;
1293           clib_bihash_kv_16_8_t kv0, value0;
1294           ip_csum_t sum0;
1295           snat_session_key_t e_key0, l_key0;
1296           lb_nat_type_t lb_nat0;
1297           twice_nat_type_t twice_nat0;
1298           u8 identity_nat0;
1299
1300           /* speculatively enqueue b0 to the current next frame */
1301           bi0 = from[0];
1302           to_next[0] = bi0;
1303           from += 1;
1304           to_next += 1;
1305           n_left_from -= 1;
1306           n_left_to_next -= 1;
1307
1308           b0 = vlib_get_buffer (vm, bi0);
1309           next0 = NAT44_ED_OUT2IN_NEXT_LOOKUP;
1310           vnet_buffer (b0)->snat.flags = 0;
1311           ip0 = vlib_buffer_get_current (b0);
1312
1313           sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1314           rx_fib_index0 =
1315             fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
1316                                                  sw_if_index0);
1317
1318           if (PREDICT_FALSE (ip0->ttl == 1))
1319             {
1320               vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1321               icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
1322                                            ICMP4_time_exceeded_ttl_exceeded_in_transit,
1323                                            0);
1324               next0 = NAT44_ED_OUT2IN_NEXT_ICMP_ERROR;
1325               goto trace0;
1326             }
1327
1328           udp0 = ip4_next_header (ip0);
1329           tcp0 = (tcp_header_t *) udp0;
1330           icmp0 = (icmp46_header_t *) udp0;
1331           proto0 = ip_proto_to_snat_proto (ip0->protocol);
1332
1333           if (is_slow_path)
1334             {
1335               if (PREDICT_FALSE (proto0 == ~0))
1336                 {
1337                   s0 =
1338                     nat44_ed_out2in_unknown_proto (sm, b0, ip0, rx_fib_index0,
1339                                                    thread_index, now, vm,
1340                                                    node);
1341                   other_packets++;
1342                   if (!sm->forwarding_enabled)
1343                     {
1344                       if (!s0)
1345                         next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1346                       goto trace0;
1347                     }
1348                 }
1349
1350               if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1351                 {
1352                   next0 = icmp_out2in_ed_slow_path
1353                     (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
1354                      next0, now, thread_index, &s0);
1355                   icmp_packets++;
1356                   goto trace0;
1357                 }
1358             }
1359           else
1360             {
1361               if (PREDICT_FALSE (proto0 == ~0))
1362                 {
1363                   next0 = NAT44_ED_OUT2IN_NEXT_SLOW_PATH;
1364                   goto trace0;
1365                 }
1366
1367               if (ip4_is_fragment (ip0))
1368                 {
1369                   next0 = NAT44_ED_OUT2IN_NEXT_REASS;
1370                   fragments++;
1371                   goto trace0;
1372                 }
1373
1374               if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1375                 {
1376                   next0 = NAT44_ED_OUT2IN_NEXT_SLOW_PATH;
1377                   goto trace0;
1378                 }
1379             }
1380
1381           make_ed_kv (&kv0, &ip0->dst_address, &ip0->src_address,
1382                       ip0->protocol, rx_fib_index0, udp0->dst_port,
1383                       udp0->src_port);
1384
1385           if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv0, &value0))
1386             {
1387               if (is_slow_path)
1388                 {
1389                   /* Try to match static mapping by external address and port,
1390                      destination address and port in packet */
1391                   e_key0.addr = ip0->dst_address;
1392                   e_key0.port = udp0->dst_port;
1393                   e_key0.protocol = proto0;
1394                   e_key0.fib_index = rx_fib_index0;
1395                   if (snat_static_mapping_match (sm, e_key0, &l_key0, 1, 0,
1396                                                  &twice_nat0, &lb_nat0,
1397                                                  &ip0->src_address,
1398                                                  &identity_nat0))
1399                     {
1400                       /*
1401                        * Send DHCP packets to the ipv4 stack, or we won't
1402                        * be able to use dhcp client on the outside interface
1403                        */
1404                       if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_UDP
1405                                          && (udp0->dst_port ==
1406                                              clib_host_to_net_u16
1407                                              (UDP_DST_PORT_dhcp_to_client))))
1408                         {
1409                           vnet_feature_next (&next0, b0);
1410                           goto trace0;
1411                         }
1412
1413                       if (!sm->forwarding_enabled)
1414                         {
1415                           b0->error =
1416                             node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
1417                           next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1418                         }
1419                       else
1420                         {
1421                           if (next_src_nat (sm, ip0, ip0->protocol,
1422                                             udp0->src_port, udp0->dst_port,
1423                                             thread_index, rx_fib_index0))
1424                             {
1425                               next0 = NAT44_ED_OUT2IN_NEXT_IN2OUT;
1426                               goto trace0;
1427                             }
1428                           create_bypass_for_fwd (sm, ip0, rx_fib_index0,
1429                                                  thread_index);
1430                         }
1431                       goto trace0;
1432                     }
1433
1434                   if (PREDICT_FALSE (identity_nat0))
1435                     goto trace0;
1436
1437                   if ((proto0 == SNAT_PROTOCOL_TCP) && !tcp_is_init (tcp0))
1438                     {
1439                       b0->error = node->errors[NAT_OUT2IN_ED_ERROR_NON_SYN];
1440                       next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1441                       goto trace0;
1442                     }
1443
1444                   /* Create session initiated by host from external network */
1445                   s0 = create_session_for_static_mapping_ed (sm, b0, l_key0,
1446                                                              e_key0, node,
1447                                                              thread_index,
1448                                                              twice_nat0,
1449                                                              lb_nat0, now);
1450
1451                   if (!s0)
1452                     {
1453                       next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1454                       goto trace0;
1455                     }
1456                 }
1457               else
1458                 {
1459                   next0 = NAT44_ED_OUT2IN_NEXT_SLOW_PATH;
1460                   goto trace0;
1461                 }
1462             }
1463           else
1464             {
1465               s0 = pool_elt_at_index (tsm->sessions, value0.value);
1466             }
1467
1468           old_addr0 = ip0->dst_address.as_u32;
1469           new_addr0 = ip0->dst_address.as_u32 = s0->in2out.addr.as_u32;
1470           vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
1471
1472           sum0 = ip0->checksum;
1473           sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1474                                  dst_address);
1475           if (PREDICT_FALSE (is_twice_nat_session (s0)))
1476             sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
1477                                    s0->ext_host_nat_addr.as_u32, ip4_header_t,
1478                                    src_address);
1479           ip0->checksum = ip_csum_fold (sum0);
1480
1481           if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
1482             {
1483               old_port0 = tcp0->dst_port;
1484               new_port0 = tcp0->dst_port = s0->in2out.port;
1485
1486               sum0 = tcp0->checksum;
1487               sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1488                                      dst_address);
1489               sum0 = ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
1490                                      length);
1491               if (is_twice_nat_session (s0))
1492                 {
1493                   sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
1494                                          s0->ext_host_nat_addr.as_u32,
1495                                          ip4_header_t, dst_address);
1496                   sum0 = ip_csum_update (sum0, tcp0->src_port,
1497                                          s0->ext_host_nat_port, ip4_header_t,
1498                                          length);
1499                   tcp0->src_port = s0->ext_host_nat_port;
1500                   ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
1501                 }
1502               tcp0->checksum = ip_csum_fold (sum0);
1503               tcp_packets++;
1504               if (nat44_set_tcp_session_state_o2i
1505                   (sm, s0, tcp0, thread_index))
1506                 goto trace0;
1507             }
1508           else
1509             {
1510               udp0->dst_port = s0->in2out.port;
1511               if (is_twice_nat_session (s0))
1512                 {
1513                   udp0->src_port = s0->ext_host_nat_port;
1514                   ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
1515                 }
1516               udp0->checksum = 0;
1517               udp_packets++;
1518             }
1519
1520           /* Accounting */
1521           nat44_session_update_counters (s0, now,
1522                                          vlib_buffer_length_in_chain (vm, b0),
1523                                          thread_index);
1524           /* Per-user LRU list maintenance */
1525           nat44_session_update_lru (sm, s0, thread_index);
1526
1527         trace0:
1528           if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
1529                              && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1530             {
1531               nat44_ed_out2in_trace_t *t =
1532                 vlib_add_trace (vm, node, b0, sizeof (*t));
1533               t->is_slow_path = is_slow_path;
1534               t->sw_if_index = sw_if_index0;
1535               t->next_index = next0;
1536               t->session_index = ~0;
1537               if (s0)
1538                 t->session_index = s0 - tsm->sessions;
1539             }
1540
1541           pkts_processed += next0 == NAT44_ED_OUT2IN_NEXT_LOOKUP;
1542           /* verify speculative enqueue, maybe switch current next frame */
1543           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1544                                            to_next, n_left_to_next,
1545                                            bi0, next0);
1546         }
1547
1548       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1549     }
1550
1551   vlib_node_increment_counter (vm, stats_node_index,
1552                                NAT_OUT2IN_ED_ERROR_OUT2IN_PACKETS,
1553                                pkts_processed);
1554   vlib_node_increment_counter (vm, stats_node_index,
1555                                NAT_OUT2IN_ED_ERROR_TCP_PACKETS, tcp_packets);
1556   vlib_node_increment_counter (vm, stats_node_index,
1557                                NAT_OUT2IN_ED_ERROR_UDP_PACKETS, udp_packets);
1558   vlib_node_increment_counter (vm, stats_node_index,
1559                                NAT_OUT2IN_ED_ERROR_ICMP_PACKETS,
1560                                icmp_packets);
1561   vlib_node_increment_counter (vm, stats_node_index,
1562                                NAT_OUT2IN_ED_ERROR_OTHER_PACKETS,
1563                                other_packets);
1564   vlib_node_increment_counter (vm, stats_node_index,
1565                                NAT_OUT2IN_ED_ERROR_FRAGMENTS, fragments);
1566   return frame->n_vectors;
1567 }
1568
1569 VLIB_NODE_FN (nat44_ed_out2in_node) (vlib_main_t * vm,
1570                                      vlib_node_runtime_t * node,
1571                                      vlib_frame_t * frame)
1572 {
1573   return nat44_ed_out2in_node_fn_inline (vm, node, frame, 0);
1574 }
1575
1576 /* *INDENT-OFF* */
1577 VLIB_REGISTER_NODE (nat44_ed_out2in_node) = {
1578   .name = "nat44-ed-out2in",
1579   .vector_size = sizeof (u32),
1580   .format_trace = format_nat44_ed_out2in_trace,
1581   .type = VLIB_NODE_TYPE_INTERNAL,
1582   .n_errors = ARRAY_LEN(nat_out2in_ed_error_strings),
1583   .error_strings = nat_out2in_ed_error_strings,
1584   .runtime_data_bytes = sizeof (snat_runtime_t),
1585   .n_next_nodes = NAT44_ED_OUT2IN_N_NEXT,
1586   .next_nodes = {
1587     [NAT44_ED_OUT2IN_NEXT_DROP] = "error-drop",
1588     [NAT44_ED_OUT2IN_NEXT_LOOKUP] = "ip4-lookup",
1589     [NAT44_ED_OUT2IN_NEXT_SLOW_PATH] = "nat44-ed-out2in-slowpath",
1590     [NAT44_ED_OUT2IN_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1591     [NAT44_ED_OUT2IN_NEXT_IN2OUT] = "nat44-ed-in2out",
1592     [NAT44_ED_OUT2IN_NEXT_REASS] = "nat44-ed-out2in-reass",
1593   },
1594 };
1595 /* *INDENT-ON* */
1596
1597 VLIB_NODE_FN (nat44_ed_out2in_slowpath_node) (vlib_main_t * vm,
1598                                               vlib_node_runtime_t * node,
1599                                               vlib_frame_t * frame)
1600 {
1601   return nat44_ed_out2in_node_fn_inline (vm, node, frame, 1);
1602 }
1603
1604 /* *INDENT-OFF* */
1605 VLIB_REGISTER_NODE (nat44_ed_out2in_slowpath_node) = {
1606   .name = "nat44-ed-out2in-slowpath",
1607   .vector_size = sizeof (u32),
1608   .format_trace = format_nat44_ed_out2in_trace,
1609   .type = VLIB_NODE_TYPE_INTERNAL,
1610   .n_errors = ARRAY_LEN(nat_out2in_ed_error_strings),
1611   .error_strings = nat_out2in_ed_error_strings,
1612   .runtime_data_bytes = sizeof (snat_runtime_t),
1613   .n_next_nodes = NAT44_ED_OUT2IN_N_NEXT,
1614   .next_nodes = {
1615     [NAT44_ED_OUT2IN_NEXT_DROP] = "error-drop",
1616     [NAT44_ED_OUT2IN_NEXT_LOOKUP] = "ip4-lookup",
1617     [NAT44_ED_OUT2IN_NEXT_SLOW_PATH] = "nat44-ed-out2in-slowpath",
1618     [NAT44_ED_OUT2IN_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1619     [NAT44_ED_OUT2IN_NEXT_IN2OUT] = "nat44-ed-in2out",
1620     [NAT44_ED_OUT2IN_NEXT_REASS] = "nat44-ed-out2in-reass",
1621   },
1622 };
1623 /* *INDENT-ON* */
1624
1625 VLIB_NODE_FN (nat44_ed_out2in_reass_node) (vlib_main_t * vm,
1626                                            vlib_node_runtime_t * node,
1627                                            vlib_frame_t * frame)
1628 {
1629   u32 n_left_from, *from, *to_next;
1630   nat44_ed_out2in_next_t next_index;
1631   u32 pkts_processed = 0;
1632   snat_main_t *sm = &snat_main;
1633   f64 now = vlib_time_now (vm);
1634   u32 thread_index = vm->thread_index;
1635   snat_main_per_thread_data_t *per_thread_data =
1636     &sm->per_thread_data[thread_index];
1637   u32 *fragments_to_drop = 0;
1638   u32 *fragments_to_loopback = 0;
1639
1640   from = vlib_frame_vector_args (frame);
1641   n_left_from = frame->n_vectors;
1642   next_index = node->cached_next_index;
1643
1644   while (n_left_from > 0)
1645     {
1646       u32 n_left_to_next;
1647
1648       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1649
1650       while (n_left_from > 0 && n_left_to_next > 0)
1651         {
1652           u32 bi0, sw_if_index0, proto0, rx_fib_index0, new_addr0, old_addr0;
1653           vlib_buffer_t *b0;
1654           u32 next0;
1655           u8 cached0 = 0;
1656           ip4_header_t *ip0;
1657           nat_reass_ip4_t *reass0;
1658           udp_header_t *udp0;
1659           tcp_header_t *tcp0;
1660           icmp46_header_t *icmp0;
1661           clib_bihash_kv_16_8_t kv0, value0;
1662           snat_session_t *s0 = 0;
1663           u16 old_port0, new_port0;
1664           ip_csum_t sum0;
1665           snat_session_key_t e_key0, l_key0;
1666           lb_nat_type_t lb0;
1667           twice_nat_type_t twice_nat0;
1668           u8 identity_nat0;
1669
1670           /* speculatively enqueue b0 to the current next frame */
1671           bi0 = from[0];
1672           to_next[0] = bi0;
1673           from += 1;
1674           to_next += 1;
1675           n_left_from -= 1;
1676           n_left_to_next -= 1;
1677
1678           b0 = vlib_get_buffer (vm, bi0);
1679           next0 = NAT44_ED_OUT2IN_NEXT_LOOKUP;
1680
1681           sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1682           rx_fib_index0 =
1683             fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
1684                                                  sw_if_index0);
1685
1686           if (PREDICT_FALSE (nat_reass_is_drop_frag (0)))
1687             {
1688               next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1689               b0->error = node->errors[NAT_OUT2IN_ED_ERROR_DROP_FRAGMENT];
1690               goto trace0;
1691             }
1692
1693           ip0 = (ip4_header_t *) vlib_buffer_get_current (b0);
1694           udp0 = ip4_next_header (ip0);
1695           tcp0 = (tcp_header_t *) udp0;
1696           icmp0 = (icmp46_header_t *) udp0;
1697           proto0 = ip_proto_to_snat_proto (ip0->protocol);
1698
1699           reass0 = nat_ip4_reass_find_or_create (ip0->src_address,
1700                                                  ip0->dst_address,
1701                                                  ip0->fragment_id,
1702                                                  ip0->protocol,
1703                                                  1, &fragments_to_drop);
1704
1705           if (PREDICT_FALSE (!reass0))
1706             {
1707               next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1708               b0->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_REASS];
1709               nat_log_notice ("maximum reassemblies exceeded");
1710               goto trace0;
1711             }
1712
1713           if (PREDICT_FALSE (ip4_is_first_fragment (ip0)))
1714             {
1715               if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1716                 {
1717                   next0 = icmp_out2in_ed_slow_path
1718                     (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
1719                      next0, now, thread_index, &s0);
1720
1721                   if (PREDICT_TRUE (next0 != NAT44_ED_OUT2IN_NEXT_DROP))
1722                     {
1723                       if (s0)
1724                         reass0->sess_index = s0 - per_thread_data->sessions;
1725                       else
1726                         reass0->flags |= NAT_REASS_FLAG_ED_DONT_TRANSLATE;
1727                       reass0->thread_index = thread_index;
1728                       nat_ip4_reass_get_frags (reass0,
1729                                                &fragments_to_loopback);
1730                     }
1731
1732                   goto trace0;
1733                 }
1734
1735               make_ed_kv (&kv0, &ip0->dst_address, &ip0->src_address,
1736                           ip0->protocol, rx_fib_index0, udp0->dst_port,
1737                           udp0->src_port);
1738
1739               if (clib_bihash_search_16_8
1740                   (&per_thread_data->out2in_ed, &kv0, &value0))
1741                 {
1742                   /* Try to match static mapping by external address and port,
1743                      destination address and port in packet */
1744                   e_key0.addr = ip0->dst_address;
1745                   e_key0.port = udp0->dst_port;
1746                   e_key0.protocol = proto0;
1747                   e_key0.fib_index = rx_fib_index0;
1748                   if (snat_static_mapping_match (sm, e_key0, &l_key0, 1, 0,
1749                                                  &twice_nat0, &lb0, 0,
1750                                                  &identity_nat0))
1751                     {
1752                       /*
1753                        * Send DHCP packets to the ipv4 stack, or we won't
1754                        * be able to use dhcp client on the outside interface
1755                        */
1756                       if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_UDP
1757                                          && (udp0->dst_port
1758                                              ==
1759                                              clib_host_to_net_u16
1760                                              (UDP_DST_PORT_dhcp_to_client))))
1761                         {
1762                           vnet_feature_next (&next0, b0);
1763                           goto trace0;
1764                         }
1765
1766                       if (!sm->forwarding_enabled)
1767                         {
1768                           b0->error =
1769                             node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
1770                           next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1771                         }
1772                       else
1773                         {
1774                           if (next_src_nat (sm, ip0, ip0->protocol,
1775                                             udp0->src_port, udp0->dst_port,
1776                                             thread_index, rx_fib_index0))
1777                             {
1778                               next0 = NAT44_ED_OUT2IN_NEXT_IN2OUT;
1779                               goto trace0;
1780                             }
1781                           create_bypass_for_fwd (sm, ip0, rx_fib_index0,
1782                                                  thread_index);
1783                           reass0->flags |= NAT_REASS_FLAG_ED_DONT_TRANSLATE;
1784                           nat_ip4_reass_get_frags (reass0,
1785                                                    &fragments_to_loopback);
1786                         }
1787                       goto trace0;
1788                     }
1789
1790                   if (PREDICT_FALSE (identity_nat0))
1791                     {
1792                       reass0->flags |= NAT_REASS_FLAG_ED_DONT_TRANSLATE;
1793                       goto trace0;
1794                     }
1795
1796                   if ((proto0 == SNAT_PROTOCOL_TCP) && !tcp_is_init (tcp0))
1797                     {
1798                       b0->error = node->errors[NAT_OUT2IN_ED_ERROR_NON_SYN];
1799                       next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1800                       goto trace0;
1801                     }
1802
1803                   /* Create session initiated by host from external network */
1804                   s0 = create_session_for_static_mapping_ed (sm, b0, l_key0,
1805                                                              e_key0, node,
1806                                                              thread_index,
1807                                                              twice_nat0, lb0,
1808                                                              now);
1809                   if (!s0)
1810                     {
1811                       b0->error =
1812                         node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
1813                       next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1814                       goto trace0;
1815                     }
1816                   reass0->sess_index = s0 - per_thread_data->sessions;
1817                   reass0->thread_index = thread_index;
1818                 }
1819               else
1820                 {
1821                   s0 = pool_elt_at_index (per_thread_data->sessions,
1822                                           value0.value);
1823                   reass0->sess_index = value0.value;
1824                 }
1825               nat_ip4_reass_get_frags (reass0, &fragments_to_loopback);
1826             }
1827           else
1828             {
1829               if (reass0->flags & NAT_REASS_FLAG_ED_DONT_TRANSLATE)
1830                 goto trace0;
1831               if (PREDICT_FALSE (reass0->sess_index == (u32) ~ 0))
1832                 {
1833                   if (nat_ip4_reass_add_fragment
1834                       (thread_index, reass0, bi0, &fragments_to_drop))
1835                     {
1836                       b0->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_FRAG];
1837                       nat_log_notice
1838                         ("maximum fragments per reassembly exceeded");
1839                       next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1840                       goto trace0;
1841                     }
1842                   cached0 = 1;
1843                   goto trace0;
1844                 }
1845               s0 = pool_elt_at_index (per_thread_data->sessions,
1846                                       reass0->sess_index);
1847             }
1848
1849           old_addr0 = ip0->dst_address.as_u32;
1850           ip0->dst_address = s0->in2out.addr;
1851           new_addr0 = ip0->dst_address.as_u32;
1852           vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
1853
1854           sum0 = ip0->checksum;
1855           sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1856                                  ip4_header_t,
1857                                  dst_address /* changed member */ );
1858           if (PREDICT_FALSE (is_twice_nat_session (s0)))
1859             sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
1860                                    s0->ext_host_nat_addr.as_u32, ip4_header_t,
1861                                    src_address);
1862           ip0->checksum = ip_csum_fold (sum0);
1863
1864           if (PREDICT_FALSE (ip4_is_first_fragment (ip0)))
1865             {
1866               if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
1867                 {
1868                   old_port0 = tcp0->dst_port;
1869                   tcp0->dst_port = s0->in2out.port;
1870                   new_port0 = tcp0->dst_port;
1871
1872                   sum0 = tcp0->checksum;
1873                   sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1874                                          ip4_header_t,
1875                                          dst_address /* changed member */ );
1876
1877                   sum0 = ip_csum_update (sum0, old_port0, new_port0,
1878                                          ip4_header_t /* cheat */ ,
1879                                          length /* changed member */ );
1880                   if (is_twice_nat_session (s0))
1881                     {
1882                       sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
1883                                              s0->ext_host_nat_addr.as_u32,
1884                                              ip4_header_t, dst_address);
1885                       sum0 = ip_csum_update (sum0, tcp0->src_port,
1886                                              s0->ext_host_nat_port,
1887                                              ip4_header_t, length);
1888                       tcp0->src_port = s0->ext_host_nat_port;
1889                       ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
1890                     }
1891                   tcp0->checksum = ip_csum_fold (sum0);
1892                 }
1893               else
1894                 {
1895                   old_port0 = udp0->dst_port;
1896                   udp0->dst_port = s0->in2out.port;
1897                   if (is_twice_nat_session (s0))
1898                     {
1899                       udp0->src_port = s0->ext_host_nat_port;
1900                       ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
1901                     }
1902                   udp0->checksum = 0;
1903                 }
1904             }
1905
1906           /* Accounting */
1907           nat44_session_update_counters (s0, now,
1908                                          vlib_buffer_length_in_chain (vm, b0),
1909                                          thread_index);
1910           /* Per-user LRU list maintenance */
1911           nat44_session_update_lru (sm, s0, thread_index);
1912
1913         trace0:
1914           if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
1915                              && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1916             {
1917               nat44_reass_trace_t *t =
1918                 vlib_add_trace (vm, node, b0, sizeof (*t));
1919               t->cached = cached0;
1920               t->sw_if_index = sw_if_index0;
1921               t->next_index = next0;
1922             }
1923
1924           if (cached0)
1925             {
1926               n_left_to_next++;
1927               to_next--;
1928             }
1929           else
1930             {
1931               pkts_processed += next0 != NAT44_ED_OUT2IN_NEXT_DROP;
1932
1933               /* verify speculative enqueue, maybe switch current next frame */
1934               vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1935                                                to_next, n_left_to_next,
1936                                                bi0, next0);
1937             }
1938
1939           if (n_left_from == 0 && vec_len (fragments_to_loopback))
1940             {
1941               from = vlib_frame_vector_args (frame);
1942               u32 len = vec_len (fragments_to_loopback);
1943               if (len <= VLIB_FRAME_SIZE)
1944                 {
1945                   clib_memcpy_fast (from, fragments_to_loopback,
1946                                     sizeof (u32) * len);
1947                   n_left_from = len;
1948                   vec_reset_length (fragments_to_loopback);
1949                 }
1950               else
1951                 {
1952                   clib_memcpy_fast (from, fragments_to_loopback +
1953                                     (len - VLIB_FRAME_SIZE),
1954                                     sizeof (u32) * VLIB_FRAME_SIZE);
1955                   n_left_from = VLIB_FRAME_SIZE;
1956                   _vec_len (fragments_to_loopback) = len - VLIB_FRAME_SIZE;
1957                 }
1958             }
1959         }
1960
1961       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1962     }
1963
1964   vlib_node_increment_counter (vm, sm->ed_out2in_reass_node_index,
1965                                NAT_OUT2IN_ED_ERROR_OUT2IN_PACKETS,
1966                                pkts_processed);
1967
1968   nat_send_all_to_node (vm, fragments_to_drop, node,
1969                         &node->errors[NAT_OUT2IN_ED_ERROR_DROP_FRAGMENT],
1970                         NAT44_ED_OUT2IN_NEXT_DROP);
1971
1972   vec_free (fragments_to_drop);
1973   vec_free (fragments_to_loopback);
1974   return frame->n_vectors;
1975 }
1976
1977 /* *INDENT-OFF* */
1978 VLIB_REGISTER_NODE (nat44_ed_out2in_reass_node) = {
1979   .name = "nat44-ed-out2in-reass",
1980   .vector_size = sizeof (u32),
1981   .format_trace = format_nat44_reass_trace,
1982   .type = VLIB_NODE_TYPE_INTERNAL,
1983   .n_errors = ARRAY_LEN(nat_out2in_ed_error_strings),
1984   .error_strings = nat_out2in_ed_error_strings,
1985   .n_next_nodes = NAT44_ED_OUT2IN_N_NEXT,
1986   .next_nodes = {
1987     [NAT44_ED_OUT2IN_NEXT_DROP] = "error-drop",
1988     [NAT44_ED_OUT2IN_NEXT_LOOKUP] = "ip4-lookup",
1989     [NAT44_ED_OUT2IN_NEXT_SLOW_PATH] = "nat44-ed-out2in-slowpath",
1990     [NAT44_ED_OUT2IN_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1991     [NAT44_ED_OUT2IN_NEXT_IN2OUT] = "nat44-ed-in2out",
1992     [NAT44_ED_OUT2IN_NEXT_REASS] = "nat44-ed-out2in-reass",
1993   },
1994 };
1995 /* *INDENT-ON* */
1996
1997 /*
1998  * fd.io coding-style-patch-verification: ON
1999  *
2000  * Local Variables:
2001  * eval: (c-set-style "gnu")
2002  * End:
2003  */