LCOV - code coverage report
Current view: top level - plugins/nat/det44 - det44_in2out.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 336 518 64.9 %
Date: 2023-07-05 22:20:52 Functions: 10 13 76.9 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2020 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             : /**
      17             :  * @file
      18             :  * @brief Deterministic NAT (CGN) inside to outside translation
      19             :  */
      20             : 
      21             : #include <vlib/vlib.h>
      22             : #include <vnet/vnet.h>
      23             : #include <vnet/ip/ip.h>
      24             : #include <vnet/fib/ip4_fib.h>
      25             : #include <vppinfra/error.h>
      26             : #include <vppinfra/elog.h>
      27             : 
      28             : #include <nat/det44/det44.h>
      29             : #include <nat/det44/det44_inlines.h>
      30             : 
      31             : #include <nat/lib/lib.h>
      32             : #include <nat/lib/inlines.h>
      33             : #include <nat/lib/nat_inlines.h>
      34             : 
      35             : typedef enum
      36             : {
      37             :   DET44_IN2OUT_NEXT_LOOKUP,
      38             :   DET44_IN2OUT_NEXT_DROP,
      39             :   DET44_IN2OUT_NEXT_ICMP_ERROR,
      40             :   DET44_IN2OUT_N_NEXT,
      41             : } det44_in2out_next_t;
      42             : 
      43             : typedef struct
      44             : {
      45             :   u32 sw_if_index;
      46             :   u32 next_index;
      47             :   u32 session_index;
      48             : } det44_in2out_trace_t;
      49             : 
      50             : #define foreach_det44_in2out_error                 \
      51             : _(UNSUPPORTED_PROTOCOL, "Unsupported protocol")    \
      52             : _(NO_TRANSLATION, "No translation")                \
      53             : _(BAD_ICMP_TYPE, "unsupported ICMP type")          \
      54             : _(OUT_OF_PORTS, "Out of ports")                    \
      55             : _(IN2OUT_PACKETS, "Good in2out packets processed")
      56             : 
      57             : typedef enum
      58             : {
      59             : #define _(sym,str) DET44_IN2OUT_ERROR_##sym,
      60             :   foreach_det44_in2out_error
      61             : #undef _
      62             :     DET44_IN2OUT_N_ERROR,
      63             : } det44_in2out_error_t;
      64             : 
      65             : static char *det44_in2out_error_strings[] = {
      66             : #define _(sym,string) string,
      67             :   foreach_det44_in2out_error
      68             : #undef _
      69             : };
      70             : 
      71             : static u8 *
      72           4 : format_det44_in2out_trace (u8 * s, va_list * args)
      73             : {
      74           4 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
      75           4 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
      76           4 :   det44_in2out_trace_t *t = va_arg (*args, det44_in2out_trace_t *);
      77             : 
      78           4 :   s = format (s, "DET44_IN2OUT: sw_if_index %d, next index %d, session %d",
      79             :               t->sw_if_index, t->next_index, t->session_index);
      80             : 
      81           4 :   return s;
      82             : }
      83             : 
      84             : #ifndef CLIB_MARCH_VARIANT
      85             : /**
      86             :  * Get address and port values to be used for ICMP packet translation
      87             :  * and create session if needed
      88             :  *
      89             :  * @param[in,out] node           NAT node runtime
      90             :  * @param[in] thread_index       thread index
      91             :  * @param[in,out] b0             buffer containing packet to be translated
      92             :  * @param[in,out] ip0            ip header
      93             :  * @param[out] p_proto           protocol used for matching
      94             :  * @param[out] p_value           address and port after NAT translation
      95             :  * @param[out] p_dont_translate  if packet should not be translated
      96             :  * @param d                      optional parameter
      97             :  * @param e                      optional parameter
      98             :  */
      99             : u32
     100           2 : icmp_match_in2out_det (vlib_node_runtime_t * node,
     101             :                        u32 thread_index, vlib_buffer_t * b0,
     102             :                        ip4_header_t * ip0, ip4_address_t * addr,
     103             :                        u16 * port, u32 * fib_index,
     104             :                        nat_protocol_t * proto, void *d, void *e,
     105             :                        u8 * dont_translate)
     106             : {
     107           2 :   det44_main_t *dm = &det44_main;
     108           2 :   vlib_main_t *vm = vlib_get_main ();
     109             :   icmp46_header_t *icmp0;
     110             :   u32 sw_if_index0;
     111             :   u32 rx_fib_index0;
     112             :   nat_protocol_t protocol;
     113             :   snat_det_out_key_t key0;
     114           2 :   u32 next0 = ~0;
     115           2 :   icmp_echo_header_t *echo0, *inner_echo0 = 0;
     116             :   ip4_header_t *inner_ip0;
     117           2 :   void *l4_header = 0;
     118             :   icmp46_header_t *inner_icmp0;
     119           2 :   snat_det_map_t *mp0 = 0;
     120             :   ip4_address_t new_addr0;
     121             :   u16 lo_port0, i0;
     122           2 :   snat_det_session_t *ses0 = 0;
     123             :   ip4_address_t in_addr;
     124             :   u16 in_port;
     125           2 :   *dont_translate = 0;
     126             : 
     127           2 :   icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
     128           2 :   echo0 = (icmp_echo_header_t *) (icmp0 + 1);
     129           2 :   sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
     130           2 :   rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
     131             : 
     132           2 :   if (!icmp_type_is_error_message
     133           2 :       (vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags))
     134             :     {
     135           2 :       protocol = NAT_PROTOCOL_ICMP;
     136           2 :       in_addr = ip0->src_address;
     137           2 :       in_port = vnet_buffer (b0)->ip.reass.l4_src_port;
     138             :     }
     139             :   else
     140             :     {
     141             :       /* if error message, then it's not fragmented and we can access it */
     142           0 :       inner_ip0 = (ip4_header_t *) (echo0 + 1);
     143           0 :       l4_header = ip4_next_header (inner_ip0);
     144           0 :       protocol = ip_proto_to_nat_proto (inner_ip0->protocol);
     145           0 :       in_addr = inner_ip0->dst_address;
     146           0 :       switch (protocol)
     147             :         {
     148           0 :         case NAT_PROTOCOL_ICMP:
     149           0 :           inner_icmp0 = (icmp46_header_t *) l4_header;
     150           0 :           inner_echo0 = (icmp_echo_header_t *) (inner_icmp0 + 1);
     151           0 :           in_port = inner_echo0->identifier;
     152           0 :           break;
     153           0 :         case NAT_PROTOCOL_UDP:
     154             :         case NAT_PROTOCOL_TCP:
     155           0 :           in_port = ((tcp_udp_header_t *) l4_header)->dst_port;
     156           0 :           break;
     157           0 :         default:
     158           0 :           b0->error = node->errors[DET44_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
     159           0 :           next0 = DET44_IN2OUT_NEXT_DROP;
     160           0 :           goto out;
     161             :         }
     162             :     }
     163             : 
     164           2 :   mp0 = snat_det_map_by_user (&in_addr);
     165           2 :   if (PREDICT_FALSE (!mp0))
     166             :     {
     167           0 :       if (PREDICT_FALSE (det44_translate (node, sw_if_index0, ip0,
     168             :                                           IP_PROTOCOL_ICMP, rx_fib_index0)))
     169             :         {
     170           0 :           *dont_translate = 1;
     171           0 :           goto out;
     172             :         }
     173           0 :       next0 = DET44_IN2OUT_NEXT_DROP;
     174           0 :       b0->error = node->errors[DET44_IN2OUT_ERROR_NO_TRANSLATION];
     175           0 :       goto out;
     176             :     }
     177             : 
     178           2 :   snat_det_forward (mp0, &in_addr, &new_addr0, &lo_port0);
     179             : 
     180           2 :   key0.ext_host_addr = ip0->dst_address;
     181           2 :   key0.ext_host_port = 0;
     182             : 
     183           2 :   ses0 = snat_det_find_ses_by_in (mp0, &in_addr, in_port, key0);
     184           2 :   if (PREDICT_FALSE (!ses0))
     185             :     {
     186           2 :       if (PREDICT_FALSE (det44_translate (node, sw_if_index0, ip0,
     187             :                                           IP_PROTOCOL_ICMP, rx_fib_index0)))
     188             :         {
     189           0 :           *dont_translate = 1;
     190           0 :           goto out;
     191             :         }
     192           2 :       if (icmp0->type != ICMP4_echo_request)
     193             :         {
     194           0 :           b0->error = node->errors[DET44_IN2OUT_ERROR_BAD_ICMP_TYPE];
     195           0 :           next0 = DET44_IN2OUT_NEXT_DROP;
     196           0 :           goto out;
     197             :         }
     198           2 :       for (i0 = 0; i0 < mp0->ports_per_host; i0++)
     199             :         {
     200           4 :           key0.out_port = clib_host_to_net_u16 (lo_port0 +
     201           4 :                                                 ((i0 +
     202           4 :                                                   clib_net_to_host_u16
     203           2 :                                                   (echo0->identifier)) %
     204           2 :                                                  mp0->ports_per_host));
     205             : 
     206           2 :           if (snat_det_get_ses_by_out (mp0, &in_addr, key0.as_u64))
     207           0 :             continue;
     208             : 
     209             :           ses0 =
     210           2 :             snat_det_ses_create (thread_index, mp0,
     211           2 :                                  &in_addr, echo0->identifier, &key0);
     212           2 :           break;
     213             :         }
     214           2 :       if (PREDICT_FALSE (!ses0))
     215             :         {
     216           0 :           next0 = DET44_IN2OUT_NEXT_DROP;
     217           0 :           b0->error = node->errors[DET44_IN2OUT_ERROR_OUT_OF_PORTS];
     218           0 :           goto out;
     219             :         }
     220             :     }
     221             : 
     222           2 :   if (PREDICT_FALSE
     223             :       (vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags != ICMP4_echo_request
     224             :        && !icmp_type_is_error_message (vnet_buffer (b0)->ip.
     225             :                                        reass.icmp_type_or_tcp_flags)))
     226             :     {
     227           0 :       b0->error = node->errors[DET44_IN2OUT_ERROR_BAD_ICMP_TYPE];
     228           0 :       next0 = DET44_IN2OUT_NEXT_DROP;
     229           0 :       goto out;
     230             :     }
     231             : 
     232           2 :   u32 now = (u32) vlib_time_now (vm);
     233             : 
     234           2 :   ses0->state = DET44_SESSION_ICMP_ACTIVE;
     235           2 :   ses0->expire = now + dm->timeouts.icmp;
     236             : 
     237           2 : out:
     238           2 :   *proto = protocol;
     239           2 :   if (ses0)
     240             :     {
     241           2 :       *addr = new_addr0;
     242           2 :       *fib_index = dm->outside_fib_index;
     243           2 :       *port = ses0->out.out_port;
     244             :     }
     245           2 :   if (d)
     246           2 :     *(snat_det_session_t **) d = ses0;
     247           2 :   if (e)
     248           2 :     *(snat_det_map_t **) e = mp0;
     249           2 :   return next0;
     250             : }
     251             : #endif
     252             : 
     253             : #ifndef CLIB_MARCH_VARIANT
     254             : u32
     255           2 : det44_icmp_in2out (vlib_buffer_t * b0,
     256             :                    ip4_header_t * ip0,
     257             :                    icmp46_header_t * icmp0,
     258             :                    u32 sw_if_index0,
     259             :                    u32 rx_fib_index0,
     260             :                    vlib_node_runtime_t * node,
     261             :                    u32 next0, u32 thread_index, void *d, void *e)
     262             : {
     263           2 :   vlib_main_t *vm = vlib_get_main ();
     264             :   u16 old_id0, new_id0, port, checksum0, old_checksum0, new_checksum0;
     265             :   u32 new_addr0, old_addr0, next0_tmp, fib_index;
     266             :   icmp_echo_header_t *echo0, *inner_echo0;
     267             :   icmp46_header_t *inner_icmp0;
     268             :   ip4_header_t *inner_ip0;
     269             :   ip4_address_t addr;
     270             :   void *l4_header;
     271             :   u8 dont_translate;
     272             :   ip_csum_t sum0;
     273             :   nat_protocol_t protocol;
     274             : 
     275           2 :   echo0 = (icmp_echo_header_t *) (icmp0 + 1);
     276           2 :   next0_tmp = icmp_match_in2out_det (node, thread_index, b0, ip0,
     277             :                                      &addr, &port, &fib_index, &protocol,
     278             :                                      d, e, &dont_translate);
     279           2 :   if (next0_tmp != ~0)
     280           0 :     next0 = next0_tmp;
     281           2 :   if (next0 == DET44_IN2OUT_NEXT_DROP || dont_translate)
     282           0 :     goto out;
     283             : 
     284           2 :   if (PREDICT_TRUE (!ip4_is_fragment (ip0)))
     285             :     {
     286             :       sum0 =
     287           4 :         ip_incremental_checksum_buffer (vm, b0,
     288           2 :                                         (u8 *) icmp0 -
     289           2 :                                         (u8 *) vlib_buffer_get_current (b0),
     290           2 :                                         ntohs (ip0->length) -
     291           2 :                                         ip4_header_bytes (ip0), 0);
     292           2 :       checksum0 = ~ip_csum_fold (sum0);
     293           2 :       if (PREDICT_FALSE (checksum0 != 0 && checksum0 != 0xffff))
     294             :         {
     295           0 :           next0 = DET44_IN2OUT_NEXT_DROP;
     296           0 :           goto out;
     297             :         }
     298             :     }
     299             : 
     300           2 :   old_addr0 = ip0->src_address.as_u32;
     301           2 :   new_addr0 = ip0->src_address.as_u32 = addr.as_u32;
     302             : 
     303           2 :   sum0 = ip0->checksum;
     304           2 :   sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
     305             :                          src_address /* changed member */ );
     306           2 :   ip0->checksum = ip_csum_fold (sum0);
     307             : 
     308           2 :   if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
     309             :     {
     310           2 :       if (icmp0->checksum == 0)
     311           0 :         icmp0->checksum = 0xffff;
     312             : 
     313           2 :       if (!icmp_type_is_error_message (icmp0->type))
     314             :         {
     315           2 :           new_id0 = port;
     316           2 :           if (PREDICT_FALSE (new_id0 != echo0->identifier))
     317             :             {
     318           2 :               old_id0 = echo0->identifier;
     319           2 :               new_id0 = port;
     320           2 :               echo0->identifier = new_id0;
     321             : 
     322           2 :               sum0 = icmp0->checksum;
     323             :               sum0 =
     324           2 :                 ip_csum_update (sum0, old_id0, new_id0, icmp_echo_header_t,
     325             :                                 identifier);
     326           2 :               icmp0->checksum = ip_csum_fold (sum0);
     327             :             }
     328             :         }
     329             :       else
     330             :         {
     331           0 :           inner_ip0 = (ip4_header_t *) (echo0 + 1);
     332           0 :           l4_header = ip4_next_header (inner_ip0);
     333             : 
     334           0 :           if (!ip4_header_checksum_is_valid (inner_ip0))
     335             :             {
     336           0 :               next0 = DET44_IN2OUT_NEXT_DROP;
     337           0 :               goto out;
     338             :             }
     339             : 
     340             :           /* update inner destination IP address */
     341           0 :           old_addr0 = inner_ip0->dst_address.as_u32;
     342           0 :           inner_ip0->dst_address = addr;
     343           0 :           new_addr0 = inner_ip0->dst_address.as_u32;
     344           0 :           sum0 = icmp0->checksum;
     345           0 :           sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
     346             :                                  dst_address /* changed member */ );
     347           0 :           icmp0->checksum = ip_csum_fold (sum0);
     348             : 
     349             :           /* update inner IP header checksum */
     350           0 :           old_checksum0 = inner_ip0->checksum;
     351           0 :           sum0 = inner_ip0->checksum;
     352           0 :           sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
     353             :                                  dst_address /* changed member */ );
     354           0 :           inner_ip0->checksum = ip_csum_fold (sum0);
     355           0 :           new_checksum0 = inner_ip0->checksum;
     356           0 :           sum0 = icmp0->checksum;
     357             :           sum0 =
     358           0 :             ip_csum_update (sum0, old_checksum0, new_checksum0, ip4_header_t,
     359             :                             checksum);
     360           0 :           icmp0->checksum = ip_csum_fold (sum0);
     361             : 
     362           0 :           switch (protocol)
     363             :             {
     364           0 :             case NAT_PROTOCOL_ICMP:
     365           0 :               inner_icmp0 = (icmp46_header_t *) l4_header;
     366           0 :               inner_echo0 = (icmp_echo_header_t *) (inner_icmp0 + 1);
     367             : 
     368           0 :               old_id0 = inner_echo0->identifier;
     369           0 :               new_id0 = port;
     370           0 :               inner_echo0->identifier = new_id0;
     371             : 
     372           0 :               sum0 = icmp0->checksum;
     373             :               sum0 =
     374           0 :                 ip_csum_update (sum0, old_id0, new_id0, icmp_echo_header_t,
     375             :                                 identifier);
     376           0 :               icmp0->checksum = ip_csum_fold (sum0);
     377           0 :               break;
     378           0 :             case NAT_PROTOCOL_UDP:
     379             :             case NAT_PROTOCOL_TCP:
     380           0 :               old_id0 = ((tcp_udp_header_t *) l4_header)->dst_port;
     381           0 :               new_id0 = port;
     382           0 :               ((tcp_udp_header_t *) l4_header)->dst_port = new_id0;
     383             : 
     384           0 :               sum0 = icmp0->checksum;
     385           0 :               sum0 = ip_csum_update (sum0, old_id0, new_id0, tcp_udp_header_t,
     386             :                                      dst_port);
     387           0 :               icmp0->checksum = ip_csum_fold (sum0);
     388           0 :               break;
     389           0 :             default:
     390           0 :               ASSERT (0);
     391             :             }
     392             :         }
     393             :     }
     394             : 
     395           2 :   if (vnet_buffer (b0)->sw_if_index[VLIB_TX] == ~0)
     396           2 :     vnet_buffer (b0)->sw_if_index[VLIB_TX] = fib_index;
     397           0 : out:
     398           2 :   return next0;
     399             : }
     400             : #endif
     401             : 
     402        2249 : VLIB_NODE_FN (det44_in2out_node) (vlib_main_t * vm,
     403             :                                   vlib_node_runtime_t * node,
     404             :                                   vlib_frame_t * frame)
     405             : {
     406             :   u32 n_left_from, *from;
     407          13 :   u32 pkts_processed = 0;
     408          13 :   det44_main_t *dm = &det44_main;
     409          13 :   u32 now = (u32) vlib_time_now (vm);
     410          13 :   u32 thread_index = vm->thread_index;
     411             : 
     412          13 :   from = vlib_frame_vector_args (frame);
     413          13 :   n_left_from = frame->n_vectors;
     414             : 
     415          13 :   vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
     416          13 :   u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
     417          13 :   vlib_get_buffers (vm, from, b, n_left_from);
     418             : 
     419          16 :   while (n_left_from >= 2)
     420             :     {
     421             :       vlib_buffer_t *b0, *b1;
     422             :       u32 next0, next1;
     423             :       u32 sw_if_index0, sw_if_index1;
     424             :       ip4_header_t *ip0, *ip1;
     425             :       ip_csum_t sum0, sum1;
     426             :       ip4_address_t new_addr0, old_addr0, new_addr1, old_addr1;
     427             :       u16 old_port0, new_port0, lo_port0, i0;
     428             :       u16 old_port1, new_port1, lo_port1, i1;
     429             :       udp_header_t *udp0, *udp1;
     430             :       tcp_header_t *tcp0, *tcp1;
     431             :       u32 proto0, proto1;
     432             :       snat_det_out_key_t key0, key1;
     433             :       snat_det_map_t *mp0, *mp1;
     434           3 :       snat_det_session_t *ses0 = 0, *ses1 = 0;
     435             :       u32 rx_fib_index0, rx_fib_index1;
     436             :       icmp46_header_t *icmp0, *icmp1;
     437             : 
     438           3 :       b0 = *b;
     439           3 :       b++;
     440           3 :       b1 = *b;
     441           3 :       b++;
     442             : 
     443             :       /* Prefetch next iteration. */
     444           3 :       if (PREDICT_TRUE (n_left_from >= 4))
     445             :         {
     446             :           vlib_buffer_t *p2, *p3;
     447             : 
     448           0 :           p2 = *b;
     449           0 :           p3 = *(b + 1);
     450             : 
     451           0 :           vlib_prefetch_buffer_header (p2, LOAD);
     452           0 :           vlib_prefetch_buffer_header (p3, LOAD);
     453             : 
     454           0 :           clib_prefetch_load (p2->data);
     455           0 :           clib_prefetch_load (p3->data);
     456             :         }
     457             : 
     458           3 :       next0 = DET44_IN2OUT_NEXT_LOOKUP;
     459           3 :       next1 = DET44_IN2OUT_NEXT_LOOKUP;
     460             : 
     461           3 :       ip0 = vlib_buffer_get_current (b0);
     462           3 :       udp0 = ip4_next_header (ip0);
     463           3 :       tcp0 = (tcp_header_t *) udp0;
     464             : 
     465           3 :       sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
     466             : 
     467           3 :       if (PREDICT_FALSE (ip0->ttl == 1))
     468             :         {
     469           0 :           vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
     470           0 :           icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
     471             :                                        ICMP4_time_exceeded_ttl_exceeded_in_transit,
     472             :                                        0);
     473           0 :           next0 = DET44_IN2OUT_NEXT_ICMP_ERROR;
     474           0 :           goto trace0;
     475             :         }
     476             : 
     477           3 :       proto0 = ip_proto_to_nat_proto (ip0->protocol);
     478             : 
     479           3 :       if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP))
     480             :         {
     481             :           rx_fib_index0 =
     482           0 :             ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
     483           0 :           icmp0 = (icmp46_header_t *) udp0;
     484             : 
     485             :           // TODO:
     486           0 :           next0 = det44_icmp_in2out (b0, ip0, icmp0, sw_if_index0,
     487             :                                      rx_fib_index0, node, next0,
     488             :                                      thread_index, &ses0, &mp0);
     489           0 :           goto trace0;
     490             :         }
     491             : 
     492           3 :       mp0 = snat_det_map_by_user (&ip0->src_address);
     493           3 :       if (PREDICT_FALSE (!mp0))
     494             :         {
     495           0 :           det44_log_info ("no match for internal host %U",
     496             :                           format_ip4_address, &ip0->src_address);
     497           0 :           next0 = DET44_IN2OUT_NEXT_DROP;
     498           0 :           b0->error = node->errors[DET44_IN2OUT_ERROR_NO_TRANSLATION];
     499           0 :           goto trace0;
     500             :         }
     501             : 
     502           3 :       snat_det_forward (mp0, &ip0->src_address, &new_addr0, &lo_port0);
     503             : 
     504           3 :       key0.ext_host_addr = ip0->dst_address;
     505           3 :       key0.ext_host_port = tcp0->dst;
     506             : 
     507           3 :       ses0 =
     508           3 :         snat_det_find_ses_by_in (mp0, &ip0->src_address, tcp0->src, key0);
     509           3 :       if (PREDICT_FALSE (!ses0))
     510             :         {
     511           1 :           for (i0 = 0; i0 < mp0->ports_per_host; i0++)
     512             :             {
     513           2 :               key0.out_port = clib_host_to_net_u16 (lo_port0 +
     514           2 :                                                     ((i0 +
     515           2 :                                                       clib_net_to_host_u16
     516           1 :                                                       (tcp0->src)) %
     517           1 :                                                      mp0->ports_per_host));
     518             : 
     519           1 :               if (snat_det_get_ses_by_out
     520             :                   (mp0, &ip0->src_address, key0.as_u64))
     521           0 :                 continue;
     522             : 
     523           1 :               ses0 =
     524           1 :                 snat_det_ses_create (thread_index, mp0, &ip0->src_address,
     525           1 :                                      tcp0->src, &key0);
     526           1 :               break;
     527             :             }
     528           1 :           if (PREDICT_FALSE (!ses0))
     529             :             {
     530             :               /* too many sessions for user, send ICMP error packet */
     531           0 :               vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
     532           0 :               icmp4_error_set_vnet_buffer (b0,
     533             :                                            ICMP4_destination_unreachable,
     534             :                                            ICMP4_destination_unreachable_destination_unreachable_host,
     535             :                                            0);
     536           0 :               next0 = DET44_IN2OUT_NEXT_ICMP_ERROR;
     537           0 :               goto trace0;
     538             :             }
     539             :         }
     540             : 
     541           3 :       old_port0 = udp0->src_port;
     542           3 :       udp0->src_port = new_port0 = ses0->out.out_port;
     543             : 
     544           3 :       old_addr0.as_u32 = ip0->src_address.as_u32;
     545           3 :       ip0->src_address.as_u32 = new_addr0.as_u32;
     546           3 :       vnet_buffer (b0)->sw_if_index[VLIB_TX] = dm->outside_fib_index;
     547             : 
     548           3 :       sum0 = ip0->checksum;
     549           3 :       sum0 = ip_csum_update (sum0, old_addr0.as_u32, new_addr0.as_u32,
     550             :                              ip4_header_t, src_address /* changed member */ );
     551           3 :       ip0->checksum = ip_csum_fold (sum0);
     552             : 
     553           3 :       if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
     554             :         {
     555           3 :           if (tcp0->flags & TCP_FLAG_SYN)
     556           2 :             ses0->state = DET44_SESSION_TCP_SYN_SENT;
     557           1 :           else if (tcp0->flags & TCP_FLAG_ACK
     558           1 :                    && ses0->state == DET44_SESSION_TCP_SYN_SENT)
     559           0 :             ses0->state = DET44_SESSION_TCP_ESTABLISHED;
     560           1 :           else if (tcp0->flags & TCP_FLAG_FIN
     561           0 :                    && ses0->state == DET44_SESSION_TCP_ESTABLISHED)
     562           0 :             ses0->state = DET44_SESSION_TCP_FIN_WAIT;
     563           1 :           else if (tcp0->flags & TCP_FLAG_ACK
     564           1 :                    && ses0->state == DET44_SESSION_TCP_FIN_WAIT)
     565           0 :             snat_det_ses_close (mp0, ses0);
     566           1 :           else if (tcp0->flags & TCP_FLAG_FIN
     567           0 :                    && ses0->state == DET44_SESSION_TCP_CLOSE_WAIT)
     568           0 :             ses0->state = DET44_SESSION_TCP_LAST_ACK;
     569           1 :           else if (tcp0->flags == 0 && ses0->state == DET44_SESSION_UNKNOWN)
     570           0 :             ses0->state = DET44_SESSION_TCP_ESTABLISHED;
     571             : 
     572           3 :           sum0 = tcp0->checksum;
     573           3 :           sum0 = ip_csum_update (sum0, old_addr0.as_u32, new_addr0.as_u32,
     574             :                                  ip4_header_t,
     575             :                                  dst_address /* changed member */ );
     576           3 :           sum0 = ip_csum_update (sum0, old_port0, new_port0,
     577             :                                  ip4_header_t /* cheat */ ,
     578             :                                  length /* changed member */ );
     579           3 :           mss_clamping (dm->mss_clamping, tcp0, &sum0);
     580           3 :           tcp0->checksum = ip_csum_fold (sum0);
     581             :         }
     582             :       else
     583             :         {
     584           0 :           ses0->state = DET44_SESSION_UDP_ACTIVE;
     585             : 
     586           0 :           if (PREDICT_FALSE (udp0->checksum))
     587             :             {
     588           0 :               sum0 = udp0->checksum;
     589           0 :               sum0 =
     590           0 :                 ip_csum_update (sum0, old_addr0.as_u32, new_addr0.as_u32,
     591             :                                 ip4_header_t,
     592             :                                 dst_address /* changed member */ );
     593           0 :               sum0 =
     594           0 :                 ip_csum_update (sum0, old_port0, new_port0,
     595             :                                 ip4_header_t /* cheat */ ,
     596             :                                 length /* changed member */ );
     597           0 :               udp0->checksum = ip_csum_fold (sum0);
     598             :             }
     599             :         }
     600             : 
     601           3 :       switch (ses0->state)
     602             :         {
     603           0 :         case DET44_SESSION_UDP_ACTIVE:
     604           0 :           ses0->expire = now + dm->timeouts.udp;
     605           0 :           break;
     606           3 :         case DET44_SESSION_TCP_SYN_SENT:
     607             :         case DET44_SESSION_TCP_FIN_WAIT:
     608             :         case DET44_SESSION_TCP_CLOSE_WAIT:
     609             :         case DET44_SESSION_TCP_LAST_ACK:
     610           3 :           ses0->expire = now + dm->timeouts.tcp.transitory;
     611           3 :           break;
     612           0 :         case DET44_SESSION_TCP_ESTABLISHED:
     613           0 :           ses0->expire = now + dm->timeouts.tcp.established;
     614           0 :           break;
     615             :         }
     616             : 
     617           3 :     trace0:
     618           3 :       if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
     619             :                          && (b0->flags & VLIB_BUFFER_IS_TRACED)))
     620             :         {
     621             :           det44_in2out_trace_t *t =
     622           3 :             vlib_add_trace (vm, node, b0, sizeof (*t));
     623           3 :           t->sw_if_index = sw_if_index0;
     624           3 :           t->next_index = next0;
     625           3 :           t->session_index = ~0;
     626           3 :           if (ses0)
     627           3 :             t->session_index = ses0 - mp0->sessions;
     628             :         }
     629             : 
     630           3 :       pkts_processed += next0 != DET44_IN2OUT_NEXT_DROP;
     631             : 
     632           3 :       ip1 = vlib_buffer_get_current (b1);
     633           3 :       udp1 = ip4_next_header (ip1);
     634           3 :       tcp1 = (tcp_header_t *) udp1;
     635             : 
     636           3 :       sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
     637             : 
     638           3 :       if (PREDICT_FALSE (ip1->ttl == 1))
     639             :         {
     640           0 :           vnet_buffer (b1)->sw_if_index[VLIB_TX] = (u32) ~ 0;
     641           0 :           icmp4_error_set_vnet_buffer (b1, ICMP4_time_exceeded,
     642             :                                        ICMP4_time_exceeded_ttl_exceeded_in_transit,
     643             :                                        0);
     644           0 :           next1 = DET44_IN2OUT_NEXT_ICMP_ERROR;
     645           0 :           goto trace1;
     646             :         }
     647             : 
     648           3 :       proto1 = ip_proto_to_nat_proto (ip1->protocol);
     649             : 
     650           3 :       if (PREDICT_FALSE (proto1 == NAT_PROTOCOL_ICMP))
     651             :         {
     652             :           rx_fib_index1 =
     653           0 :             ip4_fib_table_get_index_for_sw_if_index (sw_if_index1);
     654           0 :           icmp1 = (icmp46_header_t *) udp1;
     655             : 
     656           0 :           next1 = det44_icmp_in2out (b1, ip1, icmp1, sw_if_index1,
     657             :                                      rx_fib_index1, node, next1,
     658             :                                      thread_index, &ses1, &mp1);
     659           0 :           goto trace1;
     660             :         }
     661             : 
     662           3 :       mp1 = snat_det_map_by_user (&ip1->src_address);
     663           3 :       if (PREDICT_FALSE (!mp1))
     664             :         {
     665           0 :           det44_log_info ("no match for internal host %U",
     666             :                           format_ip4_address, &ip0->src_address);
     667           0 :           next1 = DET44_IN2OUT_NEXT_DROP;
     668           0 :           b1->error = node->errors[DET44_IN2OUT_ERROR_NO_TRANSLATION];
     669           0 :           goto trace1;
     670             :         }
     671             : 
     672           3 :       snat_det_forward (mp1, &ip1->src_address, &new_addr1, &lo_port1);
     673             : 
     674           3 :       key1.ext_host_addr = ip1->dst_address;
     675           3 :       key1.ext_host_port = tcp1->dst;
     676             : 
     677           3 :       ses1 =
     678           3 :         snat_det_find_ses_by_in (mp1, &ip1->src_address, tcp1->src, key1);
     679           3 :       if (PREDICT_FALSE (!ses1))
     680             :         {
     681           2 :           for (i1 = 0; i1 < mp1->ports_per_host; i1++)
     682             :             {
     683           4 :               key1.out_port = clib_host_to_net_u16 (lo_port1 +
     684           4 :                                                     ((i1 +
     685           4 :                                                       clib_net_to_host_u16
     686           2 :                                                       (tcp1->src)) %
     687           2 :                                                      mp1->ports_per_host));
     688             : 
     689           2 :               if (snat_det_get_ses_by_out
     690             :                   (mp1, &ip1->src_address, key1.as_u64))
     691           0 :                 continue;
     692             : 
     693           2 :               ses1 =
     694           2 :                 snat_det_ses_create (thread_index, mp1, &ip1->src_address,
     695           2 :                                      tcp1->src, &key1);
     696           2 :               break;
     697             :             }
     698           2 :           if (PREDICT_FALSE (!ses1))
     699             :             {
     700             :               /* too many sessions for user, send ICMP error packet */
     701           0 :               vnet_buffer (b1)->sw_if_index[VLIB_TX] = (u32) ~ 0;
     702           0 :               icmp4_error_set_vnet_buffer (b1,
     703             :                                            ICMP4_destination_unreachable,
     704             :                                            ICMP4_destination_unreachable_destination_unreachable_host,
     705             :                                            0);
     706           0 :               next1 = DET44_IN2OUT_NEXT_ICMP_ERROR;
     707           0 :               goto trace1;
     708             :             }
     709             :         }
     710             : 
     711           3 :       old_port1 = udp1->src_port;
     712           3 :       udp1->src_port = new_port1 = ses1->out.out_port;
     713             : 
     714           3 :       old_addr1.as_u32 = ip1->src_address.as_u32;
     715           3 :       ip1->src_address.as_u32 = new_addr1.as_u32;
     716           3 :       vnet_buffer (b1)->sw_if_index[VLIB_TX] = dm->outside_fib_index;
     717             : 
     718           3 :       sum1 = ip1->checksum;
     719           3 :       sum1 = ip_csum_update (sum1, old_addr1.as_u32, new_addr1.as_u32,
     720             :                              ip4_header_t, src_address /* changed member */ );
     721           3 :       ip1->checksum = ip_csum_fold (sum1);
     722             : 
     723           3 :       if (PREDICT_TRUE (proto1 == NAT_PROTOCOL_TCP))
     724             :         {
     725           1 :           if (tcp1->flags & TCP_FLAG_SYN)
     726           0 :             ses1->state = DET44_SESSION_TCP_SYN_SENT;
     727           1 :           else if (tcp1->flags & TCP_FLAG_ACK
     728           0 :                    && ses1->state == DET44_SESSION_TCP_SYN_SENT)
     729           0 :             ses1->state = DET44_SESSION_TCP_ESTABLISHED;
     730           1 :           else if (tcp1->flags & TCP_FLAG_FIN
     731           1 :                    && ses1->state == DET44_SESSION_TCP_ESTABLISHED)
     732           0 :             ses1->state = DET44_SESSION_TCP_FIN_WAIT;
     733           1 :           else if (tcp1->flags & TCP_FLAG_ACK
     734           0 :                    && ses1->state == DET44_SESSION_TCP_FIN_WAIT)
     735           0 :             snat_det_ses_close (mp1, ses1);
     736           1 :           else if (tcp1->flags & TCP_FLAG_FIN
     737           1 :                    && ses1->state == DET44_SESSION_TCP_CLOSE_WAIT)
     738           1 :             ses1->state = DET44_SESSION_TCP_LAST_ACK;
     739           0 :           else if (tcp1->flags == 0 && ses1->state == DET44_SESSION_UNKNOWN)
     740           0 :             ses1->state = DET44_SESSION_TCP_ESTABLISHED;
     741             : 
     742           1 :           sum1 = tcp1->checksum;
     743           1 :           sum1 = ip_csum_update (sum1, old_addr1.as_u32, new_addr1.as_u32,
     744             :                                  ip4_header_t,
     745             :                                  dst_address /* changed member */ );
     746           1 :           sum1 = ip_csum_update (sum1, old_port1, new_port1,
     747             :                                  ip4_header_t /* cheat */ ,
     748             :                                  length /* changed member */ );
     749           1 :           mss_clamping (dm->mss_clamping, tcp1, &sum1);
     750           1 :           tcp1->checksum = ip_csum_fold (sum1);
     751             :         }
     752             :       else
     753             :         {
     754           2 :           ses1->state = DET44_SESSION_UDP_ACTIVE;
     755             : 
     756           2 :           if (PREDICT_FALSE (udp1->checksum))
     757             :             {
     758           2 :               sum1 = udp1->checksum;
     759           2 :               sum1 =
     760           2 :                 ip_csum_update (sum1, old_addr1.as_u32, new_addr1.as_u32,
     761             :                                 ip4_header_t,
     762             :                                 dst_address /* changed member */ );
     763           2 :               sum1 =
     764           2 :                 ip_csum_update (sum1, old_port1, new_port1,
     765             :                                 ip4_header_t /* cheat */ ,
     766             :                                 length /* changed member */ );
     767           2 :               udp1->checksum = ip_csum_fold (sum1);
     768             :             }
     769             :         }
     770             : 
     771           3 :       switch (ses1->state)
     772             :         {
     773           2 :         case DET44_SESSION_UDP_ACTIVE:
     774           2 :           ses1->expire = now + dm->timeouts.udp;
     775           2 :           break;
     776           1 :         case DET44_SESSION_TCP_SYN_SENT:
     777             :         case DET44_SESSION_TCP_FIN_WAIT:
     778             :         case DET44_SESSION_TCP_CLOSE_WAIT:
     779             :         case DET44_SESSION_TCP_LAST_ACK:
     780           1 :           ses1->expire = now + dm->timeouts.tcp.transitory;
     781           1 :           break;
     782           0 :         case DET44_SESSION_TCP_ESTABLISHED:
     783           0 :           ses1->expire = now + dm->timeouts.tcp.established;
     784           0 :           break;
     785             :         }
     786             : 
     787           3 :     trace1:
     788           3 :       if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
     789             :                          && (b1->flags & VLIB_BUFFER_IS_TRACED)))
     790             :         {
     791             :           det44_in2out_trace_t *t =
     792           3 :             vlib_add_trace (vm, node, b1, sizeof (*t));
     793           3 :           t->sw_if_index = sw_if_index1;
     794           3 :           t->next_index = next1;
     795           3 :           t->session_index = ~0;
     796           3 :           if (ses1)
     797           3 :             t->session_index = ses1 - mp1->sessions;
     798             :         }
     799             : 
     800           3 :       pkts_processed += next1 != DET44_IN2OUT_NEXT_DROP;
     801             : 
     802           3 :       n_left_from -= 2;
     803           3 :       next[0] = next0;
     804           3 :       next[1] = next1;
     805           3 :       next += 2;
     806             :     }
     807             : 
     808          25 :   while (n_left_from > 0)
     809             :     {
     810             :       vlib_buffer_t *b0;
     811             :       u32 next0;
     812             :       u32 sw_if_index0;
     813             :       ip4_header_t *ip0;
     814             :       ip_csum_t sum0;
     815             :       ip4_address_t new_addr0, old_addr0;
     816             :       u16 old_port0, new_port0, lo_port0, i0;
     817             :       udp_header_t *udp0;
     818             :       tcp_header_t *tcp0;
     819             :       u32 proto0;
     820             :       snat_det_out_key_t key0;
     821             :       snat_det_map_t *mp0;
     822          12 :       snat_det_session_t *ses0 = 0;
     823             :       u32 rx_fib_index0;
     824             :       icmp46_header_t *icmp0;
     825             : 
     826          12 :       b0 = *b;
     827          12 :       b++;
     828          12 :       next0 = DET44_IN2OUT_NEXT_LOOKUP;
     829             : 
     830          12 :       ip0 = vlib_buffer_get_current (b0);
     831          12 :       udp0 = ip4_next_header (ip0);
     832          12 :       tcp0 = (tcp_header_t *) udp0;
     833             : 
     834          12 :       sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
     835             : 
     836          12 :       if (PREDICT_FALSE (ip0->ttl == 1))
     837             :         {
     838           0 :           vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
     839           0 :           icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
     840             :                                        ICMP4_time_exceeded_ttl_exceeded_in_transit,
     841             :                                        0);
     842           0 :           next0 = DET44_IN2OUT_NEXT_ICMP_ERROR;
     843           0 :           goto trace00;
     844             :         }
     845             : 
     846          12 :       proto0 = ip_proto_to_nat_proto (ip0->protocol);
     847             : 
     848          12 :       if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP))
     849             :         {
     850             :           rx_fib_index0 =
     851           2 :             ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
     852           2 :           icmp0 = (icmp46_header_t *) udp0;
     853             : 
     854           2 :           next0 = det44_icmp_in2out (b0, ip0, icmp0, sw_if_index0,
     855             :                                      rx_fib_index0, node, next0,
     856             :                                      thread_index, &ses0, &mp0);
     857           2 :           goto trace00;
     858             :         }
     859             : 
     860          10 :       mp0 = snat_det_map_by_user (&ip0->src_address);
     861          10 :       if (PREDICT_FALSE (!mp0))
     862             :         {
     863           0 :           det44_log_info ("no match for internal host %U",
     864             :                           format_ip4_address, &ip0->src_address);
     865           0 :           next0 = DET44_IN2OUT_NEXT_DROP;
     866           0 :           b0->error = node->errors[DET44_IN2OUT_ERROR_NO_TRANSLATION];
     867           0 :           goto trace00;
     868             :         }
     869             : 
     870          10 :       snat_det_forward (mp0, &ip0->src_address, &new_addr0, &lo_port0);
     871             : 
     872          10 :       key0.ext_host_addr = ip0->dst_address;
     873          10 :       key0.ext_host_port = tcp0->dst;
     874             : 
     875          10 :       ses0 =
     876          10 :         snat_det_find_ses_by_in (mp0, &ip0->src_address, tcp0->src, key0);
     877          10 :       if (PREDICT_FALSE (!ses0))
     878             :         {
     879           5 :           for (i0 = 0; i0 < mp0->ports_per_host; i0++)
     880             :             {
     881          10 :               key0.out_port = clib_host_to_net_u16 (lo_port0 +
     882          10 :                                                     ((i0 +
     883          10 :                                                       clib_net_to_host_u16
     884           5 :                                                       (tcp0->src)) %
     885           5 :                                                      mp0->ports_per_host));
     886             : 
     887           5 :               if (snat_det_get_ses_by_out
     888             :                   (mp0, &ip0->src_address, key0.as_u64))
     889           0 :                 continue;
     890             : 
     891           5 :               ses0 =
     892           5 :                 snat_det_ses_create (thread_index, mp0, &ip0->src_address,
     893           5 :                                      tcp0->src, &key0);
     894           5 :               break;
     895             :             }
     896           5 :           if (PREDICT_FALSE (!ses0))
     897             :             {
     898             :               /* too many sessions for user, send ICMP error packet */
     899           0 :               vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
     900           0 :               icmp4_error_set_vnet_buffer (b0,
     901             :                                            ICMP4_destination_unreachable,
     902             :                                            ICMP4_destination_unreachable_destination_unreachable_host,
     903             :                                            0);
     904           0 :               next0 = DET44_IN2OUT_NEXT_ICMP_ERROR;
     905           0 :               goto trace00;
     906             :             }
     907             :         }
     908             : 
     909          10 :       old_port0 = udp0->src_port;
     910          10 :       udp0->src_port = new_port0 = ses0->out.out_port;
     911             : 
     912          10 :       old_addr0.as_u32 = ip0->src_address.as_u32;
     913          10 :       ip0->src_address.as_u32 = new_addr0.as_u32;
     914          10 :       vnet_buffer (b0)->sw_if_index[VLIB_TX] = dm->outside_fib_index;
     915             : 
     916          10 :       sum0 = ip0->checksum;
     917          10 :       sum0 = ip_csum_update (sum0, old_addr0.as_u32, new_addr0.as_u32,
     918             :                              ip4_header_t, src_address /* changed member */ );
     919          10 :       ip0->checksum = ip_csum_fold (sum0);
     920             : 
     921          10 :       if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
     922             :         {
     923          10 :           if (tcp0->flags & TCP_FLAG_SYN)
     924           5 :             ses0->state = DET44_SESSION_TCP_SYN_SENT;
     925           5 :           else if (tcp0->flags & TCP_FLAG_ACK
     926           4 :                    && ses0->state == DET44_SESSION_TCP_SYN_SENT)
     927           3 :             ses0->state = DET44_SESSION_TCP_ESTABLISHED;
     928           2 :           else if (tcp0->flags & TCP_FLAG_FIN
     929           1 :                    && ses0->state == DET44_SESSION_TCP_ESTABLISHED)
     930           1 :             ses0->state = DET44_SESSION_TCP_FIN_WAIT;
     931           1 :           else if (tcp0->flags & TCP_FLAG_ACK
     932           1 :                    && ses0->state == DET44_SESSION_TCP_FIN_WAIT)
     933           1 :             snat_det_ses_close (mp0, ses0);
     934           0 :           else if (tcp0->flags & TCP_FLAG_FIN
     935           0 :                    && ses0->state == DET44_SESSION_TCP_CLOSE_WAIT)
     936           0 :             ses0->state = DET44_SESSION_TCP_LAST_ACK;
     937           0 :           else if (tcp0->flags == 0 && ses0->state == DET44_SESSION_UNKNOWN)
     938           0 :             ses0->state = DET44_SESSION_TCP_ESTABLISHED;
     939             : 
     940          10 :           sum0 = tcp0->checksum;
     941          10 :           sum0 = ip_csum_update (sum0, old_addr0.as_u32, new_addr0.as_u32,
     942             :                                  ip4_header_t,
     943             :                                  dst_address /* changed member */ );
     944          10 :           sum0 = ip_csum_update (sum0, old_port0, new_port0,
     945             :                                  ip4_header_t /* cheat */ ,
     946             :                                  length /* changed member */ );
     947          10 :           mss_clamping (dm->mss_clamping, tcp0, &sum0);
     948          10 :           tcp0->checksum = ip_csum_fold (sum0);
     949             :         }
     950             :       else
     951             :         {
     952           0 :           ses0->state = DET44_SESSION_UDP_ACTIVE;
     953             : 
     954           0 :           if (PREDICT_FALSE (udp0->checksum))
     955             :             {
     956           0 :               sum0 = udp0->checksum;
     957           0 :               sum0 =
     958           0 :                 ip_csum_update (sum0, old_addr0.as_u32, new_addr0.as_u32,
     959             :                                 ip4_header_t,
     960             :                                 dst_address /* changed member */ );
     961           0 :               sum0 =
     962           0 :                 ip_csum_update (sum0, old_port0, new_port0,
     963             :                                 ip4_header_t /* cheat */ ,
     964             :                                 length /* changed member */ );
     965           0 :               udp0->checksum = ip_csum_fold (sum0);
     966             :             }
     967             :         }
     968             : 
     969          10 :       switch (ses0->state)
     970             :         {
     971           0 :         case DET44_SESSION_UDP_ACTIVE:
     972           0 :           ses0->expire = now + dm->timeouts.udp;
     973           0 :           break;
     974           7 :         case DET44_SESSION_TCP_SYN_SENT:
     975             :         case DET44_SESSION_TCP_FIN_WAIT:
     976             :         case DET44_SESSION_TCP_CLOSE_WAIT:
     977             :         case DET44_SESSION_TCP_LAST_ACK:
     978           7 :           ses0->expire = now + dm->timeouts.tcp.transitory;
     979           7 :           break;
     980           3 :         case DET44_SESSION_TCP_ESTABLISHED:
     981           3 :           ses0->expire = now + dm->timeouts.tcp.established;
     982           3 :           break;
     983             :         }
     984             : 
     985          12 :     trace00:
     986          12 :       if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
     987             :                          && (b0->flags & VLIB_BUFFER_IS_TRACED)))
     988             :         {
     989             :           det44_in2out_trace_t *t =
     990          12 :             vlib_add_trace (vm, node, b0, sizeof (*t));
     991          12 :           t->sw_if_index = sw_if_index0;
     992          12 :           t->next_index = next0;
     993          12 :           t->session_index = ~0;
     994          12 :           if (ses0)
     995          12 :             t->session_index = ses0 - mp0->sessions;
     996             :         }
     997             : 
     998          12 :       pkts_processed += next0 != DET44_IN2OUT_NEXT_DROP;
     999             : 
    1000          12 :       n_left_from--;
    1001          12 :       next[0] = next0;
    1002          12 :       next++;
    1003             :     }
    1004             : 
    1005          13 :   vlib_buffer_enqueue_to_next (vm, node, from, (u16 *) nexts,
    1006          13 :                                frame->n_vectors);
    1007             : 
    1008          13 :   vlib_node_increment_counter (vm, dm->in2out_node_index,
    1009             :                                DET44_IN2OUT_ERROR_IN2OUT_PACKETS,
    1010             :                                pkts_processed);
    1011          13 :   return frame->n_vectors;
    1012             : }
    1013             : 
    1014             : /* *INDENT-OFF* */
    1015      156280 : VLIB_REGISTER_NODE (det44_in2out_node) = {
    1016             :   .name = "det44-in2out",
    1017             :   .vector_size = sizeof (u32),
    1018             :   .format_trace = format_det44_in2out_trace,
    1019             :   .type = VLIB_NODE_TYPE_INTERNAL,
    1020             :   .n_errors = ARRAY_LEN(det44_in2out_error_strings),
    1021             :   .error_strings = det44_in2out_error_strings,
    1022             :   .runtime_data_bytes = sizeof (det44_runtime_t),
    1023             :   .n_next_nodes = DET44_IN2OUT_N_NEXT,
    1024             :   /* edit / add dispositions here */
    1025             :   .next_nodes = {
    1026             :     [DET44_IN2OUT_NEXT_DROP] = "error-drop",
    1027             :     [DET44_IN2OUT_NEXT_LOOKUP] = "ip4-lookup",
    1028             :     [DET44_IN2OUT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
    1029             :   },
    1030             : };
    1031             : /* *INDENT-ON* */
    1032             : 
    1033             : /*
    1034             :  * fd.io coding-style-patch-verification: ON
    1035             :  *
    1036             :  * Local Variables:
    1037             :  * eval: (c-set-style "gnu")
    1038             :  * End:
    1039             :  */

Generated by: LCOV version 1.14