nat: do not use nat session object after deletion
[vpp.git] / src / plugins / nat / nat44-ed / nat44_ed_out2in.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/ip/ip.h>
23 #include <vnet/ethernet/ethernet.h>
24 #include <vnet/fib/ip4_fib.h>
25 #include <vnet/udp/udp_local.h>
26 #include <vppinfra/error.h>
27
28 #include <nat/lib/ipfix_logging.h>
29
30 #include <nat/nat44-ed/nat44_ed.h>
31 #include <nat/nat44-ed/nat44_ed_inlines.h>
32
33 static char *nat_out2in_ed_error_strings[] = {
34 #define _(sym,string) string,
35   foreach_nat_out2in_ed_error
36 #undef _
37 };
38
39 typedef enum
40 {
41   NAT_ED_SP_REASON_NO_REASON,
42   NAT_ED_SP_REASON_LOOKUP_FAILED,
43   NAT_ED_SP_REASON_VRF_EXPIRED,
44   NAT_ED_SP_SESS_EXPIRED,
45 } nat_slow_path_reason_e;
46
47 typedef struct
48 {
49   u32 sw_if_index;
50   u32 next_index;
51   u32 session_index;
52   nat_translation_error_e translation_error;
53   nat_6t_flow_t i2of;
54   nat_6t_flow_t o2if;
55   clib_bihash_kv_16_8_t search_key;
56   u8 is_slow_path;
57   u8 translation_via_i2of;
58   u8 lookup_skipped;
59   u8 tcp_state;
60   nat_slow_path_reason_e slow_path_reason;
61 } nat44_ed_out2in_trace_t;
62
63 static u8 *
64 format_slow_path_reason (u8 *s, va_list *args)
65 {
66   nat_slow_path_reason_e reason = va_arg (*args, nat_slow_path_reason_e);
67   switch (reason)
68     {
69     case NAT_ED_SP_REASON_NO_REASON:
70       return format (s, "no reason for slow path");
71     case NAT_ED_SP_REASON_LOOKUP_FAILED:
72       return format (s, "slow path because lookup failed");
73     case NAT_ED_SP_REASON_VRF_EXPIRED:
74       return format (s, "slow path because vrf expired");
75     case NAT_ED_SP_SESS_EXPIRED:
76       return format (s, "slow path because session expired");
77     }
78   return format (s, "invalid reason value");
79 }
80
81 static u8 *
82 format_nat44_ed_out2in_trace (u8 * s, va_list * args)
83 {
84   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
85   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
86   nat44_ed_out2in_trace_t *t = va_arg (*args, nat44_ed_out2in_trace_t *);
87   char *tag;
88
89   tag =
90     t->is_slow_path ? "NAT44_OUT2IN_ED_SLOW_PATH" :
91     "NAT44_OUT2IN_ED_FAST_PATH";
92
93   s = format (s, "%s: sw_if_index %d, next index %d", tag, t->sw_if_index,
94               t->next_index);
95   if (~0 != t->session_index)
96     {
97       s = format (s, ", session %d, translation result '%U' via %s",
98                   t->session_index, format_nat_ed_translation_error,
99                   t->translation_error,
100                   t->translation_via_i2of ? "i2of" : "o2if");
101       s = format (s, "\n  i2of %U", format_nat_6t_flow, &t->i2of);
102       s = format (s, "\n  o2if %U", format_nat_6t_flow, &t->o2if);
103     }
104   if (!t->is_slow_path)
105     {
106       if (t->lookup_skipped)
107         {
108           s = format (s, "\n  lookup skipped - cached session index used");
109         }
110       else
111         {
112           s = format (s, "\n  search key %U", format_ed_session_kvp,
113                       &t->search_key);
114         }
115       s = format (s, "\n  %U", format_slow_path_reason, t->slow_path_reason);
116     }
117   if (IP_PROTOCOL_TCP == t->i2of.match.proto)
118     {
119       s = format (s, "\n  TCP state: %U", format_nat44_ed_tcp_state,
120                   t->tcp_state);
121     }
122
123   return s;
124 }
125
126 static int
127 next_src_nat (snat_main_t *sm, ip4_header_t *ip, u16 src_port, u16 dst_port,
128               u32 rx_fib_index)
129 {
130   clib_bihash_kv_16_8_t kv, value;
131
132   init_ed_k (&kv, ip->src_address.as_u32, src_port, ip->dst_address.as_u32,
133              dst_port, rx_fib_index, ip->protocol);
134   if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv, &value))
135     return 1;
136
137   return 0;
138 }
139
140 static void create_bypass_for_fwd (snat_main_t *sm, vlib_buffer_t *b,
141                                    snat_session_t *s, ip4_header_t *ip,
142                                    u32 rx_fib_index, u32 thread_index);
143
144 static snat_session_t *create_session_for_static_mapping_ed (
145   snat_main_t *sm, vlib_buffer_t *b, ip4_address_t i2o_addr, u16 i2o_port,
146   u32 i2o_fib_index, ip4_address_t o2i_addr, u16 o2i_port, u32 o2i_fib_index,
147   ip_protocol_t proto, vlib_node_runtime_t *node, u32 thread_index,
148   twice_nat_type_t twice_nat, lb_nat_type_t lb_nat, f64 now,
149   snat_static_mapping_t *mapping);
150
151 static inline u32
152 icmp_out2in_ed_slow_path (snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip,
153                           icmp46_header_t *icmp, u32 sw_if_index,
154                           u32 rx_fib_index, vlib_node_runtime_t *node,
155                           u32 next, f64 now, u32 thread_index,
156                           snat_session_t **s_p)
157 {
158   vlib_main_t *vm = vlib_get_main ();
159
160   ip_csum_t sum;
161   u16 checksum;
162
163   snat_session_t *s = 0;
164   u8 is_addr_only, identity_nat;
165   ip4_address_t sm_addr;
166   u16 sm_port;
167   u32 sm_fib_index;
168   snat_static_mapping_t *m;
169   u8 lookup_protocol;
170   ip4_address_t lookup_saddr, lookup_daddr;
171   u16 lookup_sport, lookup_dport;
172
173   sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
174   rx_fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
175
176   if (nat_get_icmp_session_lookup_values (b, ip, &lookup_saddr, &lookup_sport,
177                                           &lookup_daddr, &lookup_dport,
178                                           &lookup_protocol))
179     {
180       b->error = node->errors[NAT_OUT2IN_ED_ERROR_UNSUPPORTED_PROTOCOL];
181       next = NAT_NEXT_DROP;
182       goto out;
183     }
184
185   if (snat_static_mapping_match (vm, ip->dst_address, lookup_sport,
186                                  rx_fib_index, ip->protocol, &sm_addr,
187                                  &sm_port, &sm_fib_index, 1, &is_addr_only, 0,
188                                  0, 0, &identity_nat, &m))
189     {
190       // static mapping not matched
191       if (!sm->forwarding_enabled)
192         {
193           /* Don't NAT packet aimed at the intfc address */
194           if (!is_interface_addr (sm, node, sw_if_index,
195                                   ip->dst_address.as_u32))
196             {
197               b->error = node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
198               next = NAT_NEXT_DROP;
199             }
200         }
201       else
202         {
203           if (next_src_nat (sm, ip, lookup_sport, lookup_dport, rx_fib_index))
204             {
205               next = NAT_NEXT_IN2OUT_ED_FAST_PATH;
206             }
207           else
208             {
209               create_bypass_for_fwd (sm, b, s, ip, rx_fib_index, thread_index);
210             }
211         }
212       goto out;
213     }
214
215   if (PREDICT_FALSE (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags !=
216                        ICMP4_echo_reply &&
217                      (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags !=
218                         ICMP4_echo_request ||
219                       !is_addr_only)))
220     {
221       b->error = node->errors[NAT_OUT2IN_ED_ERROR_BAD_ICMP_TYPE];
222       next = NAT_NEXT_DROP;
223       goto out;
224     }
225
226   if (PREDICT_FALSE (identity_nat))
227     {
228       goto out;
229     }
230
231   /* Create session initiated by host from external network */
232   s = create_session_for_static_mapping_ed (
233     sm, b, sm_addr, sm_port, sm_fib_index, ip->dst_address, lookup_sport,
234     rx_fib_index, lookup_protocol, node, thread_index, 0, 0,
235     vlib_time_now (vm), m);
236   if (!s)
237     next = NAT_NEXT_DROP;
238
239   if (PREDICT_TRUE (!ip4_is_fragment (ip)))
240     {
241       sum = ip_incremental_checksum_buffer (
242         vm, b, (u8 *) icmp - (u8 *) vlib_buffer_get_current (b),
243         ntohs (ip->length) - ip4_header_bytes (ip), 0);
244       checksum = ~ip_csum_fold (sum);
245       if (checksum != 0 && checksum != 0xffff)
246         {
247           next = NAT_NEXT_DROP;
248           goto out;
249         }
250     }
251
252   if (PREDICT_TRUE (next != NAT_NEXT_DROP && s))
253     {
254       /* Accounting */
255       nat44_session_update_counters (
256         s, now, vlib_buffer_length_in_chain (vm, b), thread_index);
257       /* Per-user LRU list maintenance */
258       nat44_session_update_lru (sm, s, thread_index);
259     }
260 out:
261   if (NAT_NEXT_DROP == next && s)
262     {
263       nat_ed_session_delete (sm, s, thread_index, 1);
264       s = 0;
265     }
266   *s_p = s;
267   return next;
268 }
269
270 static_always_inline int
271 nat44_ed_alloc_i2o_port (snat_main_t *sm, snat_address_t *a, snat_session_t *s,
272                          ip4_address_t i2o_addr, u16 i2o_port,
273                          u32 i2o_fib_index, ip_protocol_t proto,
274                          u32 thread_index, u32 snat_thread_index,
275                          ip4_address_t *outside_addr, u16 *outside_port)
276 {
277   u32 portnum;
278
279   for (int i = 0; i < ED_PORT_ALLOC_ATTEMPTS; ++i)
280     {
281       portnum = (sm->port_per_thread * snat_thread_index) +
282                 snat_random_port (0, sm->port_per_thread - 1) +
283                 ED_USER_PORT_OFFSET;
284       portnum = clib_host_to_net_u16 (portnum);
285       nat_6t_i2o_flow_init (sm, thread_index, s, i2o_addr, i2o_port, a->addr,
286                             portnum, i2o_fib_index, proto);
287       if (!nat_ed_ses_i2o_flow_hash_add_del (sm, thread_index, s,
288                                              1 /* is_add */))
289         {
290           *outside_addr = a->addr;
291           *outside_port = portnum;
292           return 0;
293         }
294     }
295
296   /* Totally out of translations to use... */
297   nat_ipfix_logging_addresses_exhausted (thread_index, 0);
298   return 1;
299 }
300
301 static_always_inline int
302 nat44_ed_alloc_i2o_addr_and_port (snat_main_t *sm, snat_address_t *addresses,
303                                   snat_session_t *s, ip4_address_t i2o_addr,
304                                   u16 i2o_port, u32 i2o_fib_index,
305                                   ip_protocol_t proto, u32 thread_index,
306                                   u32 snat_thread_index,
307                                   ip4_address_t *outside_addr,
308                                   u16 *outside_port)
309 {
310   snat_address_t *a, *ga = 0;
311   int i;
312
313   if (vec_len (addresses) > 0)
314     {
315       int s_addr_offset = i2o_addr.as_u32 % vec_len (addresses);
316
317       for (i = s_addr_offset; i < vec_len (addresses); ++i)
318         {
319           a = addresses + i;
320           if (a->fib_index == i2o_fib_index)
321             {
322               return nat44_ed_alloc_i2o_port (
323                 sm, a, s, i2o_addr, i2o_port, i2o_fib_index, proto,
324                 thread_index, snat_thread_index, outside_addr, outside_port);
325             }
326           else if (a->fib_index == ~0)
327             {
328               ga = a;
329             }
330         }
331
332       for (i = 0; i < s_addr_offset; ++i)
333         {
334           a = addresses + i;
335           if (a->fib_index == i2o_fib_index)
336             {
337               return nat44_ed_alloc_i2o_port (
338                 sm, a, s, i2o_addr, i2o_port, i2o_fib_index, proto,
339                 thread_index, snat_thread_index, outside_addr, outside_port);
340             }
341           else if (a->fib_index == ~0)
342             {
343               ga = a;
344             }
345         }
346
347       if (ga)
348         {
349           return nat44_ed_alloc_i2o_port (
350             sm, a, s, i2o_addr, i2o_port, i2o_fib_index, proto, thread_index,
351             snat_thread_index, outside_addr, outside_port);
352         }
353     }
354
355   /* Totally out of translations to use... */
356   nat_ipfix_logging_addresses_exhausted (thread_index, 0);
357   return 1;
358 }
359
360 static snat_session_t *
361 create_session_for_static_mapping_ed (
362   snat_main_t *sm, vlib_buffer_t *b, ip4_address_t i2o_addr, u16 i2o_port,
363   u32 i2o_fib_index, ip4_address_t o2i_addr, u16 o2i_port, u32 o2i_fib_index,
364   ip_protocol_t proto, vlib_node_runtime_t *node, u32 thread_index,
365   twice_nat_type_t twice_nat, lb_nat_type_t lb_nat, f64 now,
366   snat_static_mapping_t *mapping)
367 {
368   snat_session_t *s;
369   ip4_header_t *ip;
370   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
371
372   if (PREDICT_FALSE (
373         nat44_ed_maximum_sessions_exceeded (sm, o2i_fib_index, thread_index)))
374     {
375       b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_SESSIONS_EXCEEDED];
376       nat_elog_notice (sm, "maximum sessions exceeded");
377       return 0;
378     }
379
380   s = nat_ed_session_alloc (sm, thread_index, now, proto);
381   if (!s)
382     {
383       b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_SESSIONS_EXCEEDED];
384       nat_elog_warn (sm, "create NAT session failed");
385       return 0;
386     }
387
388   ip = vlib_buffer_get_current (b);
389
390   s->ext_host_addr.as_u32 = ip->src_address.as_u32;
391   s->ext_host_port =
392     proto == IP_PROTOCOL_ICMP ? 0 : vnet_buffer (b)->ip.reass.l4_src_port;
393   s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
394   if (lb_nat)
395     s->flags |= SNAT_SESSION_FLAG_LOAD_BALANCING;
396   if (lb_nat == AFFINITY_LB_NAT)
397     s->flags |= SNAT_SESSION_FLAG_AFFINITY;
398   s->out2in.addr = o2i_addr;
399   s->out2in.port = o2i_port;
400   s->out2in.fib_index = o2i_fib_index;
401   s->in2out.addr = i2o_addr;
402   s->in2out.port = i2o_port;
403   s->in2out.fib_index = i2o_fib_index;
404   s->proto = proto;
405
406   if (IP_PROTOCOL_ICMP == proto)
407     {
408       nat_6t_o2i_flow_init (sm, thread_index, s, s->ext_host_addr, o2i_port,
409                             o2i_addr, o2i_port, o2i_fib_index, ip->protocol);
410       nat_6t_flow_icmp_id_rewrite_set (&s->o2i, i2o_port);
411     }
412   else
413     {
414       nat_6t_o2i_flow_init (sm, thread_index, s, s->ext_host_addr,
415                             s->ext_host_port, o2i_addr, o2i_port,
416                             o2i_fib_index, ip->protocol);
417       nat_6t_flow_dport_rewrite_set (&s->o2i, i2o_port);
418     }
419   nat_6t_flow_daddr_rewrite_set (&s->o2i, i2o_addr.as_u32);
420   nat_6t_flow_txfib_rewrite_set (&s->o2i, i2o_fib_index);
421
422   if (nat_ed_ses_o2i_flow_hash_add_del (sm, thread_index, s, 1))
423     {
424       b->error = node->errors[NAT_OUT2IN_ED_ERROR_HASH_ADD_FAILED];
425       nat_ed_session_delete (sm, s, thread_index, 1);
426       nat_elog_warn (sm, "out2in flow hash add failed");
427       return 0;
428     }
429
430   if (twice_nat == TWICE_NAT || (twice_nat == TWICE_NAT_SELF &&
431                                  ip->src_address.as_u32 == i2o_addr.as_u32))
432     {
433       int rc = 0;
434       snat_address_t *filter = 0;
435
436       // if exact address is specified use this address
437       if (is_sm_exact_address (mapping->flags))
438         {
439           snat_address_t *ap;
440           vec_foreach (ap, sm->twice_nat_addresses)
441           {
442             if (mapping->pool_addr.as_u32 == ap->addr.as_u32)
443               {
444                 filter = ap;
445                 break;
446               }
447           }
448         }
449
450       if (filter)
451         {
452           rc = nat44_ed_alloc_i2o_port (
453             sm, filter, s, i2o_addr, i2o_port, i2o_fib_index, proto,
454             thread_index, tsm->snat_thread_index, &s->ext_host_nat_addr,
455             &s->ext_host_nat_port);
456           s->flags |= SNAT_SESSION_FLAG_EXACT_ADDRESS;
457         }
458       else
459         {
460           rc = nat44_ed_alloc_i2o_addr_and_port (
461             sm, sm->twice_nat_addresses, s, i2o_addr, i2o_port, i2o_fib_index,
462             proto, thread_index, tsm->snat_thread_index, &s->ext_host_nat_addr,
463             &s->ext_host_nat_port);
464         }
465
466       if (rc)
467         {
468           b->error = node->errors[NAT_OUT2IN_ED_ERROR_OUT_OF_PORTS];
469           nat_ed_session_delete (sm, s, thread_index, 1);
470           return 0;
471         }
472
473       s->flags |= SNAT_SESSION_FLAG_TWICE_NAT;
474
475       nat_6t_flow_saddr_rewrite_set (&s->o2i, s->ext_host_nat_addr.as_u32);
476       if (IP_PROTOCOL_ICMP == proto)
477         {
478           nat_6t_flow_icmp_id_rewrite_set (&s->o2i, s->ext_host_nat_port);
479         }
480       else
481         {
482           nat_6t_flow_sport_rewrite_set (&s->o2i, s->ext_host_nat_port);
483         }
484
485       nat_6t_l3_l4_csum_calc (&s->o2i);
486
487       nat_6t_flow_daddr_rewrite_set (&s->i2o, s->ext_host_addr.as_u32);
488       if (IP_PROTOCOL_ICMP == proto)
489         {
490           nat_6t_flow_icmp_id_rewrite_set (&s->i2o, s->ext_host_port);
491         }
492       else
493         {
494           nat_6t_flow_dport_rewrite_set (&s->i2o, s->ext_host_port);
495         }
496
497       nat_6t_flow_saddr_rewrite_set (&s->i2o, o2i_addr.as_u32);
498       if (IP_PROTOCOL_ICMP == proto)
499         {
500           nat_6t_flow_icmp_id_rewrite_set (&s->i2o, o2i_port);
501         }
502       else
503         {
504           nat_6t_flow_sport_rewrite_set (&s->i2o, o2i_port);
505         }
506       nat_6t_l3_l4_csum_calc (&s->i2o);
507     }
508   else
509     {
510       if (IP_PROTOCOL_ICMP == proto)
511         {
512           nat_6t_i2o_flow_init (sm, thread_index, s, i2o_addr, i2o_port,
513                                 s->ext_host_addr, i2o_port, i2o_fib_index,
514                                 ip->protocol);
515         }
516       else
517         {
518           nat_6t_i2o_flow_init (sm, thread_index, s, i2o_addr, i2o_port,
519                                 s->ext_host_addr, s->ext_host_port,
520                                 i2o_fib_index, ip->protocol);
521         }
522
523   nat_6t_flow_saddr_rewrite_set (&s->i2o, o2i_addr.as_u32);
524   if (IP_PROTOCOL_ICMP == proto)
525     {
526       nat_6t_flow_icmp_id_rewrite_set (&s->i2o, o2i_port);
527     }
528   else
529     {
530       nat_6t_flow_sport_rewrite_set (&s->i2o, o2i_port);
531     }
532
533   if (nat_ed_ses_i2o_flow_hash_add_del (sm, thread_index, s, 1))
534     {
535       nat_elog_notice (sm, "in2out flow hash add failed");
536       if (nat_ed_ses_o2i_flow_hash_add_del (sm, thread_index, s, 0))
537         {
538           nat_elog_warn (sm, "out2in flow hash del failed");
539         }
540       nat_ed_session_delete (sm, s, thread_index, 1);
541       return 0;
542     }
543     }
544   nat_ipfix_logging_nat44_ses_create (
545     thread_index, s->in2out.addr.as_u32, s->out2in.addr.as_u32, s->proto,
546     s->in2out.port, s->out2in.port, s->in2out.fib_index);
547
548   nat_syslog_nat44_sadd (0, s->in2out.fib_index, &s->in2out.addr,
549                          s->in2out.port, &s->ext_host_nat_addr,
550                          s->ext_host_nat_port, &s->out2in.addr, s->out2in.port,
551                          &s->ext_host_addr, s->ext_host_port, s->proto,
552                          nat44_ed_is_twice_nat_session (s));
553
554   per_vrf_sessions_register_session (s, thread_index);
555
556   return s;
557 }
558
559 static void
560 create_bypass_for_fwd (snat_main_t *sm, vlib_buffer_t *b, snat_session_t *s,
561                        ip4_header_t *ip, u32 rx_fib_index, u32 thread_index)
562 {
563   clib_bihash_kv_16_8_t kv, value;
564   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
565   vlib_main_t *vm = vlib_get_main ();
566   f64 now = vlib_time_now (vm);
567   u16 lookup_sport, lookup_dport;
568   u8 lookup_protocol;
569   ip4_address_t lookup_saddr, lookup_daddr;
570
571   if (ip->protocol == IP_PROTOCOL_ICMP)
572     {
573       if (nat_get_icmp_session_lookup_values (b, ip, &lookup_daddr,
574                                               &lookup_sport, &lookup_saddr,
575                                               &lookup_dport, &lookup_protocol))
576         return;
577     }
578   else
579     {
580       if (ip->protocol == IP_PROTOCOL_UDP || ip->protocol == IP_PROTOCOL_TCP)
581         {
582           lookup_sport = vnet_buffer (b)->ip.reass.l4_dst_port;
583           lookup_dport = vnet_buffer (b)->ip.reass.l4_src_port;
584         }
585       else
586         {
587           lookup_sport = 0;
588           lookup_dport = 0;
589         }
590       lookup_saddr.as_u32 = ip->dst_address.as_u32;
591       lookup_daddr.as_u32 = ip->src_address.as_u32;
592       lookup_protocol = ip->protocol;
593     }
594
595   init_ed_k (&kv, lookup_saddr.as_u32, lookup_sport, lookup_daddr.as_u32,
596              lookup_dport, rx_fib_index, lookup_protocol);
597
598   if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv, &value))
599     {
600       ASSERT (thread_index == ed_value_get_thread_index (&value));
601       s =
602         pool_elt_at_index (tsm->sessions,
603                            ed_value_get_session_index (&value));
604     }
605   else if (ip->protocol == IP_PROTOCOL_ICMP &&
606            icmp_type_is_error_message
607            (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags))
608     {
609       return;
610     }
611   else
612     {
613       if (PREDICT_FALSE
614           (nat44_ed_maximum_sessions_exceeded
615            (sm, rx_fib_index, thread_index)))
616         return;
617
618       s = nat_ed_session_alloc (sm, thread_index, now, ip->protocol);
619       if (!s)
620         {
621           nat_elog_warn (sm, "create NAT session failed");
622           return;
623         }
624
625       s->ext_host_addr = ip->src_address;
626       s->ext_host_port = lookup_dport;
627       s->flags |= SNAT_SESSION_FLAG_FWD_BYPASS;
628       s->out2in.addr = ip->dst_address;
629       s->out2in.port = lookup_sport;
630       s->proto = ip->protocol;
631       s->out2in.fib_index = rx_fib_index;
632       s->in2out.addr = s->out2in.addr;
633       s->in2out.port = s->out2in.port;
634       s->in2out.fib_index = s->out2in.fib_index;
635
636       nat_6t_i2o_flow_init (sm, thread_index, s, ip->dst_address, lookup_sport,
637                             ip->src_address, lookup_dport, rx_fib_index,
638                             ip->protocol);
639       nat_6t_flow_txfib_rewrite_set (&s->i2o, rx_fib_index);
640       if (nat_ed_ses_i2o_flow_hash_add_del (sm, thread_index, s, 1))
641         {
642           nat_elog_notice (sm, "in2out flow add failed");
643           nat_ed_session_delete (sm, s, thread_index, 1);
644           return;
645         }
646
647       per_vrf_sessions_register_session (s, thread_index);
648     }
649
650   if (ip->protocol == IP_PROTOCOL_TCP)
651     {
652       nat44_set_tcp_session_state_o2i (
653         sm, now, s, vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags,
654         thread_index);
655     }
656
657   /* Accounting */
658   nat44_session_update_counters (s, now, 0, thread_index);
659   /* Per-user LRU list maintenance */
660   nat44_session_update_lru (sm, s, thread_index);
661 }
662
663 static snat_session_t *
664 nat44_ed_out2in_slowpath_unknown_proto (snat_main_t *sm, vlib_buffer_t *b,
665                                         ip4_header_t *ip, u32 rx_fib_index,
666                                         u32 thread_index, f64 now,
667                                         vlib_main_t *vm,
668                                         vlib_node_runtime_t *node)
669 {
670   snat_static_mapping_t *m;
671   snat_session_t *s;
672
673   if (PREDICT_FALSE (
674         nat44_ed_maximum_sessions_exceeded (sm, rx_fib_index, thread_index)))
675     {
676       b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_SESSIONS_EXCEEDED];
677       nat_elog_notice (sm, "maximum sessions exceeded");
678       return 0;
679     }
680
681   m = nat44_ed_sm_o2i_lookup (sm, ip->dst_address, 0, 0, ip->protocol);
682   if (!m)
683     {
684       b->error = node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
685       return 0;
686     }
687
688   /* Create a new session */
689   s = nat_ed_session_alloc (sm, thread_index, now, ip->protocol);
690   if (!s)
691     {
692       b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_SESSIONS_EXCEEDED];
693       nat_elog_warn (sm, "create NAT session failed");
694       return 0;
695     }
696
697   s->ext_host_addr.as_u32 = ip->src_address.as_u32;
698   s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
699   s->out2in.addr.as_u32 = ip->dst_address.as_u32;
700   s->out2in.fib_index = rx_fib_index;
701   s->in2out.addr.as_u32 = m->local_addr.as_u32;
702   s->in2out.fib_index = m->fib_index;
703   s->in2out.port = s->out2in.port = ip->protocol;
704
705   nat_6t_o2i_flow_init (sm, thread_index, s, ip->dst_address, 0,
706                         ip->src_address, 0, m->fib_index, ip->protocol);
707   nat_6t_flow_saddr_rewrite_set (&s->i2o, ip->dst_address.as_u32);
708   if (nat_ed_ses_i2o_flow_hash_add_del (sm, thread_index, s, 1))
709     {
710       nat_elog_notice (sm, "in2out key add failed");
711       nat_ed_session_delete (sm, s, thread_index, 1);
712       return NULL;
713     }
714
715   nat_6t_o2i_flow_init (sm, thread_index, s, ip->src_address, 0,
716                         ip->dst_address, 0, rx_fib_index, ip->protocol);
717   nat_6t_flow_daddr_rewrite_set (&s->o2i, m->local_addr.as_u32);
718   nat_6t_flow_txfib_rewrite_set (&s->o2i, m->fib_index);
719   if (nat_ed_ses_o2i_flow_hash_add_del (sm, thread_index, s, 1))
720     {
721       nat_elog_notice (sm, "out2in flow hash add failed");
722       nat_ed_session_delete (sm, s, thread_index, 1);
723       return NULL;
724     }
725
726   per_vrf_sessions_register_session (s, thread_index);
727
728   /* Accounting */
729   nat44_session_update_counters (s, now, vlib_buffer_length_in_chain (vm, b),
730                                  thread_index);
731   /* Per-user LRU list maintenance */
732   nat44_session_update_lru (sm, s, thread_index);
733
734   return s;
735 }
736
737 static inline uword
738 nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm,
739                                           vlib_node_runtime_t * node,
740                                           vlib_frame_t * frame,
741                                           int is_multi_worker)
742 {
743   u32 n_left_from, *from;
744   snat_main_t *sm = &snat_main;
745   f64 now = vlib_time_now (vm);
746   u32 thread_index = vm->thread_index;
747   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
748
749   from = vlib_frame_vector_args (frame);
750   n_left_from = frame->n_vectors;
751
752   vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
753   u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
754   vlib_get_buffers (vm, from, b, n_left_from);
755
756   while (n_left_from > 0)
757     {
758       vlib_buffer_t *b0;
759       u32 sw_if_index0, rx_fib_index0;
760       ip_protocol_t proto0;
761       ip4_header_t *ip0;
762       snat_session_t *s0 = 0;
763       clib_bihash_kv_16_8_t kv0 = {}, value0;
764       nat_translation_error_e translation_error = NAT_ED_TRNSL_ERR_SUCCESS;
765       nat_slow_path_reason_e slow_path_reason = NAT_ED_SP_REASON_NO_REASON;
766       nat_6t_flow_t *f = 0;
767       nat_6t_t lookup;
768       int lookup_skipped = 0;
769
770       b0 = *b;
771       b++;
772
773       /* Prefetch next iteration. */
774       if (PREDICT_TRUE (n_left_from >= 2))
775         {
776           vlib_buffer_t *p2;
777
778           p2 = *b;
779
780           vlib_prefetch_buffer_header (p2, LOAD);
781
782           clib_prefetch_load (p2->data);
783         }
784
785       next[0] = vnet_buffer2 (b0)->nat.arc_next;
786
787       lookup.sport = vnet_buffer (b0)->ip.reass.l4_src_port;
788       lookup.dport = vnet_buffer (b0)->ip.reass.l4_dst_port;
789
790       vnet_buffer (b0)->snat.flags = 0;
791       ip0 = vlib_buffer_get_current (b0);
792
793       sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
794       rx_fib_index0 =
795         fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index0);
796
797       lookup.fib_index = rx_fib_index0;
798
799       if (PREDICT_FALSE (ip0->ttl == 1))
800         {
801           vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
802           icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
803                                        ICMP4_time_exceeded_ttl_exceeded_in_transit,
804                                        0);
805           next[0] = NAT_NEXT_ICMP_ERROR;
806           goto trace0;
807         }
808
809       proto0 = ip0->protocol;
810
811       if (PREDICT_FALSE (proto0 == IP_PROTOCOL_ICMP))
812         {
813           if (vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags !=
814                 ICMP4_echo_request &&
815               vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags !=
816                 ICMP4_echo_reply &&
817               !icmp_type_is_error_message (
818                 vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags))
819             {
820               b0->error = node->errors[NAT_OUT2IN_ED_ERROR_BAD_ICMP_TYPE];
821               next[0] = NAT_NEXT_DROP;
822               goto trace0;
823             }
824           int err = nat_get_icmp_session_lookup_values (
825             b0, ip0, &lookup.saddr, &lookup.sport, &lookup.daddr,
826             &lookup.dport, &lookup.proto);
827           if (err != 0)
828             {
829               b0->error = node->errors[err];
830               next[0] = NAT_NEXT_DROP;
831               goto trace0;
832             }
833         }
834       else
835         {
836           lookup.saddr.as_u32 = ip0->src_address.as_u32;
837           lookup.daddr.as_u32 = ip0->dst_address.as_u32;
838           lookup.proto = ip0->protocol;
839         }
840
841       /* there might be a stashed index in vnet_buffer2 from handoff or
842        * classify node, see if it can be used */
843       if (is_multi_worker &&
844           !pool_is_free_index (tsm->sessions,
845                                vnet_buffer2 (b0)->nat.cached_session_index))
846         {
847           s0 = pool_elt_at_index (tsm->sessions,
848                                   vnet_buffer2 (b0)->nat.cached_session_index);
849           if (PREDICT_TRUE (nat_6t_t_eq (&s0->o2i.match, &lookup)) ||
850               (s0->flags & SNAT_SESSION_FLAG_TWICE_NAT &&
851                nat_6t_t_eq (&s0->i2o.match, &lookup)))
852             {
853               /* yes, this is the droid we're looking for */
854               lookup_skipped = 1;
855               goto skip_lookup;
856             }
857           s0 = NULL;
858         }
859
860       init_ed_k (&kv0, lookup.saddr.as_u32, lookup.sport, lookup.daddr.as_u32,
861                  lookup.dport, lookup.fib_index, lookup.proto);
862
863       // lookup flow
864       if (clib_bihash_search_16_8 (&sm->flow_hash, &kv0, &value0))
865         {
866           // flow does not exist go slow path
867           slow_path_reason = NAT_ED_SP_REASON_LOOKUP_FAILED;
868           next[0] = NAT_NEXT_OUT2IN_ED_SLOW_PATH;
869           goto trace0;
870         }
871       ASSERT (thread_index == ed_value_get_thread_index (&value0));
872       s0 =
873         pool_elt_at_index (tsm->sessions,
874                            ed_value_get_session_index (&value0));
875     skip_lookup:
876
877       ASSERT (thread_index == s0->thread_index);
878
879       if (PREDICT_FALSE (per_vrf_sessions_is_expired (s0, thread_index)))
880         {
881           // session is closed, go slow path
882           nat44_ed_free_session_data (sm, s0, thread_index, 0);
883           nat_ed_session_delete (sm, s0, thread_index, 1);
884           s0 = 0;
885           slow_path_reason = NAT_ED_SP_REASON_VRF_EXPIRED;
886           next[0] = NAT_NEXT_OUT2IN_ED_SLOW_PATH;
887           goto trace0;
888         }
889
890       // drop if session expired
891       u64 sess_timeout_time;
892       sess_timeout_time =
893         s0->last_heard + (f64) nat44_session_get_timeout (sm, s0);
894       if (now >= sess_timeout_time)
895         {
896           // session is closed, go slow path
897           nat44_ed_free_session_data (sm, s0, thread_index, 0);
898           nat_ed_session_delete (sm, s0, thread_index, 1);
899           s0 = 0;
900           slow_path_reason = NAT_ED_SP_SESS_EXPIRED;
901           next[0] = NAT_NEXT_OUT2IN_ED_SLOW_PATH;
902           goto trace0;
903         }
904
905       if (nat_6t_t_eq (&s0->o2i.match, &lookup))
906         {
907           f = &s0->o2i;
908         }
909       else if (s0->flags & SNAT_SESSION_FLAG_TWICE_NAT &&
910                nat_6t_t_eq (&s0->i2o.match, &lookup))
911         {
912           f = &s0->i2o;
913         }
914       else
915         {
916           /*
917            * Send DHCP packets to the ipv4 stack, or we won't
918            * be able to use dhcp client on the outside interface
919            */
920           if (PREDICT_FALSE (
921                 proto0 == IP_PROTOCOL_UDP &&
922                 (vnet_buffer (b0)->ip.reass.l4_dst_port ==
923                  clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_client))))
924             {
925               goto trace0;
926             }
927
928           if (!sm->forwarding_enabled)
929             {
930               b0->error = node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
931               next[0] = NAT_NEXT_DROP;
932               goto trace0;
933             }
934           else
935             {
936               if (nat_6t_t_eq (&s0->i2o.match, &lookup))
937                 {
938                   f = &s0->i2o;
939                 }
940               else
941                 {
942                   // FIXME TODO bypass ???
943                   //  create_bypass_for_fwd (sm, b0, s0, ip0, rx_fib_index0,
944                   //                       thread_index);
945                   translation_error = NAT_ED_TRNSL_ERR_FLOW_MISMATCH;
946                   nat44_ed_free_session_data (sm, s0, thread_index, 0);
947                   nat_ed_session_delete (sm, s0, thread_index, 1);
948                   s0 = 0;
949                   next[0] = NAT_NEXT_DROP;
950                   b0->error = node->errors[NAT_OUT2IN_ED_ERROR_TRNSL_FAILED];
951                   goto trace0;
952                 }
953             }
954         }
955
956       if (NAT_ED_TRNSL_ERR_SUCCESS !=
957           (translation_error = nat_6t_flow_buf_translate_o2i (
958              vm, sm, b0, ip0, f, proto0, 0 /* is_output_feature */)))
959         {
960           next[0] = NAT_NEXT_DROP;
961           b0->error = node->errors[NAT_OUT2IN_ED_ERROR_TRNSL_FAILED];
962           goto trace0;
963         }
964
965       switch (proto0)
966         {
967         case IP_PROTOCOL_TCP:
968           vlib_increment_simple_counter (&sm->counters.fastpath.out2in.tcp,
969                                          thread_index, sw_if_index0, 1);
970           nat44_set_tcp_session_state_o2i (sm, now, s0,
971                                            vnet_buffer (b0)->ip.
972                                            reass.icmp_type_or_tcp_flags,
973                                            thread_index);
974           break;
975         case IP_PROTOCOL_UDP:
976           vlib_increment_simple_counter (&sm->counters.fastpath.out2in.udp,
977                                          thread_index, sw_if_index0, 1);
978           break;
979         case IP_PROTOCOL_ICMP:
980           vlib_increment_simple_counter (&sm->counters.fastpath.out2in.icmp,
981                                          thread_index, sw_if_index0, 1);
982           break;
983         default:
984           vlib_increment_simple_counter (&sm->counters.fastpath.out2in.other,
985                                          thread_index, sw_if_index0, 1);
986           break;
987         }
988
989       /* Accounting */
990       nat44_session_update_counters (s0, now,
991                                      vlib_buffer_length_in_chain (vm, b0),
992                                      thread_index);
993       /* Per-user LRU list maintenance */
994       nat44_session_update_lru (sm, s0, thread_index);
995
996     trace0:
997       if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
998                          && (b0->flags & VLIB_BUFFER_IS_TRACED)))
999         {
1000           nat44_ed_out2in_trace_t *t =
1001             vlib_add_trace (vm, node, b0, sizeof (*t));
1002           t->sw_if_index = sw_if_index0;
1003           t->next_index = next[0];
1004           t->is_slow_path = 0;
1005           t->translation_error = translation_error;
1006           clib_memcpy (&t->search_key, &kv0, sizeof (t->search_key));
1007           t->lookup_skipped = lookup_skipped;
1008           t->slow_path_reason = slow_path_reason;
1009
1010           if (s0)
1011             {
1012               t->session_index = s0 - tsm->sessions;
1013               clib_memcpy (&t->i2of, &s0->i2o, sizeof (t->i2of));
1014               clib_memcpy (&t->o2if, &s0->o2i, sizeof (t->o2if));
1015               t->translation_via_i2of = (&s0->i2o == f);
1016               t->tcp_state = s0->tcp_state;
1017             }
1018           else
1019             {
1020               t->session_index = ~0;
1021             }
1022         }
1023
1024       if (next[0] == NAT_NEXT_DROP)
1025         {
1026           vlib_increment_simple_counter (&sm->counters.fastpath.out2in.drops,
1027                                          thread_index, sw_if_index0, 1);
1028         }
1029
1030       n_left_from--;
1031       next++;
1032     }
1033
1034   vlib_buffer_enqueue_to_next (vm, node, from, (u16 *) nexts,
1035                                frame->n_vectors);
1036   return frame->n_vectors;
1037 }
1038
1039 static inline uword
1040 nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm,
1041                                           vlib_node_runtime_t * node,
1042                                           vlib_frame_t * frame)
1043 {
1044   u32 n_left_from, *from;
1045   snat_main_t *sm = &snat_main;
1046   f64 now = vlib_time_now (vm);
1047   u32 thread_index = vm->thread_index;
1048   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
1049   snat_static_mapping_t *m;
1050
1051   from = vlib_frame_vector_args (frame);
1052   n_left_from = frame->n_vectors;
1053
1054   vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
1055   u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
1056   vlib_get_buffers (vm, from, b, n_left_from);
1057
1058   while (n_left_from > 0)
1059     {
1060       vlib_buffer_t *b0;
1061       u32 sw_if_index0, rx_fib_index0;
1062       ip_protocol_t proto0;
1063       ip4_header_t *ip0;
1064       udp_header_t *udp0;
1065       icmp46_header_t *icmp0;
1066       snat_session_t *s0 = 0;
1067       clib_bihash_kv_16_8_t kv0 = {}, value0;
1068       lb_nat_type_t lb_nat0;
1069       twice_nat_type_t twice_nat0;
1070       u8 identity_nat0;
1071       ip4_address_t sm_addr;
1072       u16 sm_port;
1073       u32 sm_fib_index;
1074       nat_translation_error_e translation_error = NAT_ED_TRNSL_ERR_SUCCESS;
1075
1076       b0 = *b;
1077       next[0] = vnet_buffer2 (b0)->nat.arc_next;
1078
1079       vnet_buffer (b0)->snat.flags = 0;
1080       ip0 = vlib_buffer_get_current (b0);
1081
1082       sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1083       rx_fib_index0 =
1084         fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index0);
1085
1086       if (PREDICT_FALSE (ip0->ttl == 1))
1087         {
1088           vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1089           icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
1090                                        ICMP4_time_exceeded_ttl_exceeded_in_transit,
1091                                        0);
1092           next[0] = NAT_NEXT_ICMP_ERROR;
1093           goto trace0;
1094         }
1095
1096       udp0 = ip4_next_header (ip0);
1097       icmp0 = (icmp46_header_t *) udp0;
1098       proto0 = ip0->protocol;
1099
1100       if (PREDICT_FALSE (nat44_ed_is_unk_proto (proto0)))
1101         {
1102           s0 = nat44_ed_out2in_slowpath_unknown_proto (
1103             sm, b0, ip0, rx_fib_index0, thread_index, now, vm, node);
1104           if (!sm->forwarding_enabled)
1105             {
1106               if (!s0)
1107                 next[0] = NAT_NEXT_DROP;
1108             }
1109           if (NAT_NEXT_DROP != next[0] && s0 &&
1110               NAT_ED_TRNSL_ERR_SUCCESS !=
1111                 (translation_error = nat_6t_flow_buf_translate_o2i (
1112                    vm, sm, b0, ip0, &s0->o2i, proto0,
1113                    0 /* is_output_feature */)))
1114             {
1115               next[0] = NAT_NEXT_DROP;
1116               b0->error = node->errors[NAT_OUT2IN_ED_ERROR_TRNSL_FAILED];
1117               goto trace0;
1118             }
1119
1120           vlib_increment_simple_counter (&sm->counters.slowpath.out2in.other,
1121                                          thread_index, sw_if_index0, 1);
1122           goto trace0;
1123         }
1124
1125       if (PREDICT_FALSE (proto0 == IP_PROTOCOL_ICMP))
1126         {
1127           next[0] = icmp_out2in_ed_slow_path
1128             (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
1129              next[0], now, thread_index, &s0);
1130
1131           if (NAT_NEXT_DROP != next[0] && s0 &&
1132               NAT_ED_TRNSL_ERR_SUCCESS !=
1133                 (translation_error = nat_6t_flow_buf_translate_o2i (
1134                    vm, sm, b0, ip0, &s0->o2i, proto0,
1135                    0 /* is_output_feature */)))
1136             {
1137               next[0] = NAT_NEXT_DROP;
1138               b0->error = node->errors[NAT_OUT2IN_ED_ERROR_TRNSL_FAILED];
1139               goto trace0;
1140             }
1141
1142           if (NAT_NEXT_DROP != next[0])
1143             {
1144               vlib_increment_simple_counter (
1145                 &sm->counters.slowpath.out2in.icmp, thread_index, sw_if_index0,
1146                 1);
1147             }
1148           goto trace0;
1149         }
1150
1151       init_ed_k (
1152         &kv0, ip0->src_address.as_u32, vnet_buffer (b0)->ip.reass.l4_src_port,
1153         ip0->dst_address.as_u32, vnet_buffer (b0)->ip.reass.l4_dst_port,
1154         rx_fib_index0, ip0->protocol);
1155
1156       s0 = NULL;
1157       if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv0, &value0))
1158         {
1159           ASSERT (thread_index == ed_value_get_thread_index (&value0));
1160           s0 =
1161             pool_elt_at_index (tsm->sessions,
1162                                ed_value_get_session_index (&value0));
1163         }
1164
1165       if (!s0)
1166         {
1167           /* Try to match static mapping by external address and port,
1168              destination address and port in packet */
1169
1170           if (snat_static_mapping_match (
1171                 vm, ip0->dst_address, vnet_buffer (b0)->ip.reass.l4_dst_port,
1172                 rx_fib_index0, proto0, &sm_addr, &sm_port, &sm_fib_index, 1, 0,
1173                 &twice_nat0, &lb_nat0, &ip0->src_address, &identity_nat0, &m))
1174             {
1175               /*
1176                * Send DHCP packets to the ipv4 stack, or we won't
1177                * be able to use dhcp client on the outside interface
1178                */
1179               if (PREDICT_FALSE (
1180                     proto0 == IP_PROTOCOL_UDP &&
1181                     (vnet_buffer (b0)->ip.reass.l4_dst_port ==
1182                      clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_client))))
1183                 {
1184                   goto trace0;
1185                 }
1186
1187               if (!sm->forwarding_enabled)
1188                 {
1189                   b0->error =
1190                     node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
1191                   next[0] = NAT_NEXT_DROP;
1192                 }
1193               else
1194                 {
1195                   if (next_src_nat (
1196                         sm, ip0, vnet_buffer (b0)->ip.reass.l4_src_port,
1197                         vnet_buffer (b0)->ip.reass.l4_dst_port, rx_fib_index0))
1198                     {
1199                       next[0] = NAT_NEXT_IN2OUT_ED_FAST_PATH;
1200                     }
1201                   else
1202                     {
1203                       create_bypass_for_fwd (sm, b0, s0, ip0, rx_fib_index0,
1204                                              thread_index);
1205                     }
1206                 }
1207               goto trace0;
1208             }
1209
1210           if (PREDICT_FALSE (identity_nat0))
1211             goto trace0;
1212
1213           if ((proto0 == IP_PROTOCOL_TCP) &&
1214               !tcp_flags_is_init (
1215                 vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags))
1216             {
1217               b0->error = node->errors[NAT_OUT2IN_ED_ERROR_NON_SYN];
1218               next[0] = NAT_NEXT_DROP;
1219               goto trace0;
1220             }
1221
1222           /* Create session initiated by host from external network */
1223           s0 = create_session_for_static_mapping_ed (
1224             sm, b0, sm_addr, sm_port, sm_fib_index, ip0->dst_address,
1225             vnet_buffer (b0)->ip.reass.l4_dst_port, rx_fib_index0, proto0,
1226             node, thread_index, twice_nat0, lb_nat0, now, m);
1227           if (!s0)
1228             {
1229               next[0] = NAT_NEXT_DROP;
1230               goto trace0;
1231             }
1232         }
1233
1234       if (NAT_ED_TRNSL_ERR_SUCCESS !=
1235           (translation_error = nat_6t_flow_buf_translate_o2i (
1236              vm, sm, b0, ip0, &s0->o2i, proto0, 0 /* is_output_feature */)))
1237         {
1238           next[0] = NAT_NEXT_DROP;
1239           goto trace0;
1240         }
1241
1242       if (PREDICT_TRUE (proto0 == IP_PROTOCOL_TCP))
1243         {
1244           vlib_increment_simple_counter (&sm->counters.slowpath.out2in.tcp,
1245                                          thread_index, sw_if_index0, 1);
1246           nat44_set_tcp_session_state_o2i (sm, now, s0,
1247                                            vnet_buffer (b0)->ip.
1248                                            reass.icmp_type_or_tcp_flags,
1249                                            thread_index);
1250         }
1251       else
1252         {
1253           vlib_increment_simple_counter (&sm->counters.slowpath.out2in.udp,
1254                                          thread_index, sw_if_index0, 1);
1255         }
1256
1257       /* Accounting */
1258       nat44_session_update_counters (s0, now,
1259                                      vlib_buffer_length_in_chain (vm, b0),
1260                                      thread_index);
1261       /* Per-user LRU list maintenance */
1262       nat44_session_update_lru (sm, s0, thread_index);
1263
1264     trace0:
1265       if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
1266                          && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1267         {
1268           nat44_ed_out2in_trace_t *t =
1269             vlib_add_trace (vm, node, b0, sizeof (*t));
1270           t->sw_if_index = sw_if_index0;
1271           t->next_index = next[0];
1272           t->is_slow_path = 1;
1273           t->translation_error = translation_error;
1274           clib_memcpy (&t->search_key, &kv0, sizeof (t->search_key));
1275
1276           if (s0)
1277             {
1278               t->session_index = s0 - tsm->sessions;
1279               clib_memcpy (&t->i2of, &s0->i2o, sizeof (t->i2of));
1280               clib_memcpy (&t->o2if, &s0->o2i, sizeof (t->o2if));
1281               t->tcp_state = s0->tcp_state;
1282             }
1283           else
1284             {
1285               t->session_index = ~0;
1286             }
1287         }
1288
1289       if (next[0] == NAT_NEXT_DROP)
1290         {
1291           vlib_increment_simple_counter (&sm->counters.slowpath.out2in.drops,
1292                                          thread_index, sw_if_index0, 1);
1293         }
1294
1295       n_left_from--;
1296       next++;
1297       b++;
1298     }
1299
1300   vlib_buffer_enqueue_to_next (vm, node, from, (u16 *) nexts,
1301                                frame->n_vectors);
1302
1303   return frame->n_vectors;
1304 }
1305
1306 VLIB_NODE_FN (nat44_ed_out2in_node) (vlib_main_t * vm,
1307                                      vlib_node_runtime_t * node,
1308                                      vlib_frame_t * frame)
1309 {
1310   if (snat_main.num_workers > 1)
1311     {
1312       return nat44_ed_out2in_fast_path_node_fn_inline (vm, node, frame, 1);
1313     }
1314   else
1315     {
1316       return nat44_ed_out2in_fast_path_node_fn_inline (vm, node, frame, 0);
1317     }
1318 }
1319
1320 VLIB_REGISTER_NODE (nat44_ed_out2in_node) = {
1321   .name = "nat44-ed-out2in",
1322   .vector_size = sizeof (u32),
1323   .sibling_of = "nat-default",
1324   .format_trace = format_nat44_ed_out2in_trace,
1325   .type = VLIB_NODE_TYPE_INTERNAL,
1326   .n_errors = ARRAY_LEN(nat_out2in_ed_error_strings),
1327   .error_strings = nat_out2in_ed_error_strings,
1328   .runtime_data_bytes = sizeof (snat_runtime_t),
1329 };
1330
1331 VLIB_NODE_FN (nat44_ed_out2in_slowpath_node) (vlib_main_t * vm,
1332                                               vlib_node_runtime_t * node,
1333                                               vlib_frame_t * frame)
1334 {
1335   return nat44_ed_out2in_slow_path_node_fn_inline (vm, node, frame);
1336 }
1337
1338 VLIB_REGISTER_NODE (nat44_ed_out2in_slowpath_node) = {
1339   .name = "nat44-ed-out2in-slowpath",
1340   .vector_size = sizeof (u32),
1341   .sibling_of = "nat-default",
1342   .format_trace = format_nat44_ed_out2in_trace,
1343   .type = VLIB_NODE_TYPE_INTERNAL,
1344   .n_errors = ARRAY_LEN(nat_out2in_ed_error_strings),
1345   .error_strings = nat_out2in_ed_error_strings,
1346   .runtime_data_bytes = sizeof (snat_runtime_t),
1347 };
1348
1349 static u8 *
1350 format_nat_pre_trace (u8 * s, va_list * args)
1351 {
1352   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1353   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1354   nat_pre_trace_t *t = va_arg (*args, nat_pre_trace_t *);
1355   return format (s, "out2in next_index %d arc_next_index %d", t->next_index,
1356                  t->arc_next_index);
1357 }
1358
1359 VLIB_NODE_FN (nat_pre_out2in_node) (vlib_main_t * vm,
1360                                     vlib_node_runtime_t * node,
1361                                     vlib_frame_t * frame)
1362 {
1363   return nat_pre_node_fn_inline (vm, node, frame,
1364                                  NAT_NEXT_OUT2IN_ED_FAST_PATH);
1365 }
1366
1367 VLIB_REGISTER_NODE (nat_pre_out2in_node) = {
1368   .name = "nat-pre-out2in",
1369   .vector_size = sizeof (u32),
1370   .sibling_of = "nat-default",
1371   .format_trace = format_nat_pre_trace,
1372   .type = VLIB_NODE_TYPE_INTERNAL,
1373   .n_errors = 0,
1374  };
1375
1376 /*
1377  * fd.io coding-style-patch-verification: ON
1378  *
1379  * Local Variables:
1380  * eval: (c-set-style "gnu")
1381  * End:
1382  */