LCOV - code coverage report
Current view: top level - plugins/srv6-mobile - node.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 486 1324 36.7 %
Date: 2023-10-26 01:39:38 Functions: 31 34 91.2 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2019 Arrcus Inc 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             : #include <vlib/vlib.h>
      16             : #include <vnet/vnet.h>
      17             : #include <vppinfra/error.h>
      18             : #include <vppinfra/hash.h>
      19             : #include <srv6-mobile/mobile.h>
      20             : 
      21             : extern ip6_address_t sr_pr_encaps_src;
      22             : 
      23             : typedef struct
      24             : {
      25             :   ip6_address_t src, dst;
      26             :   ip6_address_t sr_prefix;
      27             :   u16 sr_prefixlen;
      28             :   u32 teid;
      29             : } srv6_end_rewrite_trace_t;
      30             : 
      31             : static u16 srh_tagfield[256] = {
      32             :   /* 0 */
      33             :   0x0,
      34             :   /* 1 : Echo Request */
      35             :   0x0004,
      36             :   /* 2 : Echo Reply */
      37             :   0x0008,
      38             :   /* 3 - 7 */
      39             :   0x0, 0x0, 0x0, 0x0, 0x0,
      40             :   /* 8 - 15 */
      41             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      42             :   /* 16 - 23 */
      43             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      44             :   /* 24 - 25 */
      45             :   0x0, 0x0,
      46             :   /* 26 : Error Indication */
      47             :   0x0002,
      48             :   /* 27 - 31 */
      49             :   0x0, 0x0, 0x0, 0x0, 0x0,
      50             :   /* 32 - 247 */
      51             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      52             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      53             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      54             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      55             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      56             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      57             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      58             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      59             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      60             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      61             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      62             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      63             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      64             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      65             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      66             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      67             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      68             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      69             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      70             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      71             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      72             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      73             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      74             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      75             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      76             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      77             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      78             :   /* 248 - 253 */
      79             :   0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
      80             :   /* 254 : End Maker */
      81             :   0x0001,
      82             :   /* 255 : G_PDU */
      83             :   0x0
      84             : };
      85             : 
      86             : static u8 *
      87           4 : format_srv6_end_rewrite_trace (u8 * s, va_list * args)
      88             : {
      89           4 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
      90           4 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
      91           4 :   srv6_end_rewrite_trace_t *t = va_arg (*args, srv6_end_rewrite_trace_t *);
      92             : 
      93           4 :   return format (s, "SRv6-END-rewrite: src %U dst %U\n\tTEID: 0x%x",
      94             :                  format_ip4_address, &t->src, format_ip4_address, &t->dst,
      95             :                  clib_net_to_host_u32 (t->teid));
      96             : }
      97             : 
      98             : static u8 *
      99           4 : format_srv6_end_rewrite_trace6 (u8 * s, va_list * args)
     100             : {
     101           4 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
     102           4 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
     103           4 :   srv6_end_rewrite_trace_t *t = va_arg (*args, srv6_end_rewrite_trace_t *);
     104             : 
     105           4 :   return format (
     106             :     s, "SRv6-END-rewrite: src %U dst %U\n\tTEID: 0x%x\n\tsr_prefix: %U/%d",
     107             :     format_ip6_address, &t->src, format_ip6_address, &t->dst,
     108             :     clib_net_to_host_u32 (t->teid), format_ip6_address, &t->sr_prefix,
     109           4 :     t->sr_prefixlen);
     110             : }
     111             : 
     112             : #define foreach_srv6_end_v4_error \
     113             :   _(M_GTP4_E_PACKETS, "srv6 End.M.GTP4.E packets") \
     114             :   _(M_GTP4_E_BAD_PACKETS, "srv6 End.M.GTP4.E bad packets")
     115             : 
     116             : #define foreach_srv6_t_v4_d_error \
     117             :   _(M_GTP4_D_PACKETS, "srv6 T.M.GTP4.D packets") \
     118             :   _(M_GTP4_D_BAD_PACKETS, "srv6 T.M.GTP4.D bad packets")
     119             : 
     120             : #define foreach_srv6_end_v6_e_error \
     121             :   _(M_GTP6_E_PACKETS, "srv6 End.M.GTP6.E packets") \
     122             :   _(M_GTP6_E_BAD_PACKETS, "srv6 End.M.GTP6.E bad packets")
     123             : 
     124             : #define foreach_srv6_end_v6_d_error \
     125             :   _(M_GTP6_D_PACKETS, "srv6 End.M.GTP6.D packets") \
     126             :   _(M_GTP6_D_BAD_PACKETS, "srv6 End.M.GTP6.D bad packets")
     127             : 
     128             : #define foreach_srv6_end_v6_d_di_error \
     129             :   _(M_GTP6_D_DI_PACKETS, "srv6 End.M.GTP6.D.DI packets") \
     130             :   _(M_GTP6_D_DI_BAD_PACKETS, "srv6 End.M.GTP6.D.DI bad packets")
     131             : 
     132             : #define foreach_srv6_end_v6_dt_error \
     133             :   _(M_GTP6_DT_PACKETS, "srv6 End.M.GTP6.DT packets") \
     134             :   _(M_GTP6_DT_BAD_PACKETS, "srv6 End.M.GTP6.DT bad packets")
     135             : 
     136             : #define foreach_srv6_t_v4_dt_error \
     137             :   _(M_GTP4_DT_PACKETS, "srv6 T.M.GTP4.DT packets") \
     138             :   _(M_GTP4_DT_BAD_PACKETS, "srv6 T.M.GTP4.DT bad packets")
     139             : 
     140             : typedef enum
     141             : {
     142             : #define _(sym,str) SRV6_END_ERROR_##sym,
     143             :   foreach_srv6_end_v4_error
     144             : #undef _
     145             :     SRV6_END_N_V4_ERROR,
     146             : } srv6_end_error_v4_t;
     147             : 
     148             : typedef enum
     149             : {
     150             : #define _(sym,str) SRV6_T_ERROR_##sym,
     151             :   foreach_srv6_t_v4_d_error
     152             : #undef _
     153             :     SRV6_T_N_V4_D_ERROR,
     154             : } srv6_t_error_v4_d_t;
     155             : 
     156             : typedef enum
     157             : {
     158             : #define _(sym,str) SRV6_END_ERROR_##sym,
     159             :   foreach_srv6_end_v6_e_error
     160             : #undef _
     161             :     SRV6_END_N_V6_E_ERROR,
     162             : } srv6_end_error_v6_e_t;
     163             : 
     164             : typedef enum
     165             : {
     166             : #define _(sym,str) SRV6_END_ERROR_##sym,
     167             :   foreach_srv6_end_v6_d_error
     168             : #undef _
     169             :     SRV6_END_N_V6_D_ERROR,
     170             : } srv6_end_error_v6_d_t;
     171             : 
     172             : typedef enum
     173             : {
     174             : #define _(sym,str) SRV6_END_ERROR_##sym,
     175             :   foreach_srv6_end_v6_d_di_error
     176             : #undef _
     177             :     SRV6_END_N_V6_D_DI_ERROR,
     178             : } srv6_end_error_v6_d_di_t;
     179             : 
     180             : typedef enum
     181             : {
     182             : #define _(sym,str) SRV6_END_ERROR_##sym,
     183             :   foreach_srv6_end_v6_dt_error
     184             : #undef _
     185             :     SRV6_END_N_V6_DT_ERROR,
     186             : } srv6_end_error_v6_dt_t;
     187             : 
     188             : typedef enum
     189             : {
     190             : #define _(sym,str) SRV6_T_ERROR_##sym,
     191             :   foreach_srv6_t_v4_dt_error
     192             : #undef _
     193             :     SRV6_T_N_V4_DT_ERROR,
     194             : } srv6_t_error_v4_dt_t;
     195             : 
     196             : static char *srv6_end_error_v4_strings[] = {
     197             : #define _(sym,string) string,
     198             :   foreach_srv6_end_v4_error
     199             : #undef _
     200             : };
     201             : 
     202             : static char *srv6_t_error_v4_d_strings[] = {
     203             : #define _(sym,string) string,
     204             :   foreach_srv6_t_v4_d_error
     205             : #undef _
     206             : };
     207             : 
     208             : static char *srv6_end_error_v6_e_strings[] = {
     209             : #define _(sym,string) string,
     210             :   foreach_srv6_end_v6_e_error
     211             : #undef _
     212             : };
     213             : 
     214             : static char *srv6_end_error_v6_d_strings[] = {
     215             : #define _(sym,string) string,
     216             :   foreach_srv6_end_v6_d_error
     217             : #undef _
     218             : };
     219             : 
     220             : static char *srv6_end_error_v6_d_di_strings[] = {
     221             : #define _(sym,string) string,
     222             :   foreach_srv6_end_v6_d_di_error
     223             : #undef _
     224             : };
     225             : 
     226             : static char *srv6_end_error_v6_dt_strings[] = {
     227             : #define _(sym,string) string,
     228             :   foreach_srv6_end_v6_dt_error
     229             : #undef _
     230             : };
     231             : 
     232             : static char *srv6_t_error_v4_dt_strings[] = {
     233             : #define _(sym,string) string,
     234             :   foreach_srv6_t_v4_dt_error
     235             : #undef _
     236             : };
     237             : 
     238             : typedef enum
     239             : {
     240             :   SRV6_END_M_GTP4_E_NEXT_DROP,
     241             :   SRV6_END_M_GTP4_E_NEXT_LOOKUP,
     242             :   SRV6_END_M_GTP4_E_N_NEXT,
     243             : } srv6_end_m_gtp4_e_next_t;
     244             : 
     245             : typedef enum
     246             : {
     247             :   SRV6_T_M_GTP4_D_NEXT_DROP,
     248             :   SRV6_T_M_GTP4_D_NEXT_LOOKUP4,
     249             :   SRV6_T_M_GTP4_D_NEXT_LOOKUP6,
     250             :   SRV6_T_M_GTP4_D_N_NEXT,
     251             : } srv6_T_m_gtp4_d_next_t;
     252             : 
     253             : typedef enum
     254             : {
     255             :   SRV6_END_M_GTP6_E_NEXT_DROP,
     256             :   SRV6_END_M_GTP6_E_NEXT_LOOKUP,
     257             :   SRV6_END_M_GTP6_E_N_NEXT,
     258             : } srv6_end_m_gtp6_e_next_t;
     259             : 
     260             : typedef enum
     261             : {
     262             :   SRV6_END_M_GTP6_D_NEXT_DROP,
     263             :   SRV6_END_M_GTP6_D_NEXT_LOOKUP4,
     264             :   SRV6_END_M_GTP6_D_NEXT_LOOKUP6,
     265             :   SRV6_END_M_GTP6_D_N_NEXT,
     266             : } srv6_end_m_gtp6_d_next_t;
     267             : 
     268             : typedef enum
     269             : {
     270             :   SRV6_END_M_GTP6_D_DI_NEXT_DROP,
     271             :   SRV6_END_M_GTP6_D_DI_NEXT_LOOKUP,
     272             :   SRV6_END_M_GTP6_D_DI_N_NEXT,
     273             : } srv6_end_m_gtp6_d_di_next_t;
     274             : 
     275             : typedef enum
     276             : {
     277             :   SRV6_END_M_GTP6_DT_NEXT_DROP,
     278             :   SRV6_END_M_GTP6_DT_NEXT_LOOKUP4,
     279             :   SRV6_END_M_GTP6_DT_NEXT_LOOKUP6,
     280             :   SRV6_END_M_GTP6_DT_N_NEXT,
     281             : } srv6_end_m_gtp6_dt_next_t;
     282             : 
     283             : typedef enum
     284             : {
     285             :   SRV6_T_M_GTP4_DT_NEXT_DROP,
     286             :   SRV6_T_M_GTP4_DT_NEXT_LOOKUP4,
     287             :   SRV6_T_M_GTP4_DT_NEXT_LOOKUP6,
     288             :   SRV6_T_M_GTP4_DT_N_NEXT,
     289             : } srv6_t_m_gtp4_dt_next_t;
     290             : 
     291             : static inline u16
     292           4 : hash_uword_to_u16 (uword * key)
     293             : {
     294             :   u16 *val;
     295           4 :   val = (u16 *) key;
     296             : #if uword_bits == 64
     297           4 :   return val[0] ^ val[1] ^ val[2] ^ val[3];
     298             : #else
     299             :   return val[0] ^ val[1];
     300             : #endif
     301             : }
     302             : 
     303             : static inline u8
     304           4 : gtpu_type_get (u16 tag)
     305             : {
     306             :   u16 val;
     307             : 
     308           4 :   val = clib_net_to_host_u16 (tag);
     309           4 :   if (val & SRH_TAG_ECHO_REPLY)
     310           0 :     return GTPU_TYPE_ECHO_REPLY;
     311           4 :   else if (val & SRH_TAG_ECHO_REQUEST)
     312           0 :     return GTPU_TYPE_ECHO_REQUEST;
     313           4 :   else if (val & SRH_TAG_ERROR_INDICATION)
     314           0 :     return GTPU_TYPE_ERROR_INDICATION;
     315           4 :   else if (val & SRH_TAG_END_MARKER)
     316           0 :     return GTPU_TYPE_END_MARKER;
     317             : 
     318           4 :   return GTPU_TYPE_GTPU;
     319             : }
     320             : 
     321             : // Function for SRv6 GTP4.E function.
     322         576 : VLIB_NODE_FN (srv6_end_m_gtp4_e)
     323             : (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
     324             : {
     325           1 :   srv6_end_main_v4_t *sm = &srv6_end_main_v4;
     326           1 :   ip6_sr_main_t *sm2 = &sr_main;
     327             :   u32 n_left_from, next_index, *from, *to_next;
     328           1 :   u32 thread_index = vm->thread_index;
     329             : 
     330           1 :   u32 good_n = 0, bad_n = 0;
     331             : 
     332           1 :   from = vlib_frame_vector_args (frame);
     333           1 :   n_left_from = frame->n_vectors;
     334           1 :   next_index = node->cached_next_index;
     335             : 
     336           2 :   while (n_left_from > 0)
     337             :     {
     338             :       u32 n_left_to_next;
     339             : 
     340           1 :       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
     341             : 
     342           3 :       while (n_left_from > 0 && n_left_to_next > 0)
     343             :         {
     344             :           u32 bi0;
     345             :           vlib_buffer_t *b0;
     346             :           ip6_sr_localsid_t *ls0;
     347             :           srv6_end_gtp4_e_param_t *ls_param;
     348             : 
     349             :           ip6srv_combo_header_t *ip6srv0;
     350             :           ip6_address_t src0, dst0;
     351             : 
     352           2 :           ip4_gtpu_header_t *hdr0 = NULL;
     353             :           uword len0;
     354             : 
     355           2 :           u32 next0 = SRV6_END_M_GTP4_E_NEXT_LOOKUP;
     356             : 
     357             :           // defaults
     358           2 :           bi0 = from[0];
     359           2 :           to_next[0] = bi0;
     360           2 :           from += 1;
     361           2 :           to_next += 1;
     362           2 :           n_left_from -= 1;
     363           2 :           n_left_to_next -= 1;
     364             : 
     365           2 :           b0 = vlib_get_buffer (vm, bi0);
     366           2 :           ls0 = pool_elt_at_index (sm2->localsids,
     367             :                                    vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
     368             : 
     369           2 :           ls_param = (srv6_end_gtp4_e_param_t *) ls0->plugin_mem;
     370             : 
     371           2 :           ip6srv0 = vlib_buffer_get_current (b0);
     372           2 :           src0 = ip6srv0->ip.src_address;
     373           2 :           dst0 = ip6srv0->ip.dst_address;
     374             : 
     375           2 :           len0 = vlib_buffer_length_in_chain (vm, b0);
     376             : 
     377           2 :           if ((ip6srv0->ip.protocol == IPPROTO_IPV6_ROUTE &&
     378             :                len0 <
     379           2 :                  sizeof (ip6srv_combo_header_t) + ip6srv0->sr.length * 8) ||
     380             :               (len0 < sizeof (ip6_header_t)))
     381             :             {
     382           0 :               next0 = SRV6_END_M_GTP4_E_NEXT_DROP;
     383             : 
     384           0 :               bad_n++;
     385             :             }
     386             :           else
     387             :             {
     388           2 :               u8 gtpu_type = 0;
     389           2 :               u16 tag = 0;
     390           2 :               u32 teid = 0;
     391           2 :               u8 *teid8p = (u8 *) &teid;
     392           2 :               u8 qfi = 0;
     393           2 :               u16 seq = 0;
     394             :               u32 index;
     395             :               u32 offset, shift;
     396           2 :               u32 hdrlen = 0;
     397             :               uword key;
     398             :               u16 port;
     399             :               ip4_address_t dst4;
     400           2 :               u16 ie_size = 0;
     401             :               u8 ie_buf[GTPU_IE_MAX_SIZ];
     402             :               void *p;
     403             :               uword plen;
     404             : 
     405           2 :               if (ip6srv0->ip.protocol == IPPROTO_IPV6_ROUTE)
     406             :                 {
     407           2 :                   tag = ip6srv0->sr.tag;
     408             :                 }
     409             : 
     410           2 :               offset = ls0->localsid_prefix_len / 8;
     411           2 :               shift = ls0->localsid_prefix_len % 8;
     412             : 
     413           2 :               gtpu_type = gtpu_type_get (tag);
     414             : 
     415           2 :               if (PREDICT_TRUE (shift == 0))
     416             :                 {
     417           2 :                   clib_memcpy_fast (&dst4.as_u8[0], &dst0.as_u8[offset], 4);
     418             : 
     419           2 :                   qfi = dst0.as_u8[offset + 4];
     420             : 
     421           2 :                   if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
     422           2 :                       gtpu_type == GTPU_TYPE_ECHO_REPLY ||
     423             :                       gtpu_type == GTPU_TYPE_ERROR_INDICATION)
     424             :                     {
     425           0 :                       clib_memcpy_fast (&seq, &dst0.as_u8[offset + 5], 2);
     426             :                     }
     427             :                   else
     428             :                     {
     429           2 :                       clib_memcpy_fast (teid8p, &dst0.as_u8[offset + 5], 4);
     430             :                     }
     431             :                 }
     432             :               else
     433             :                 {
     434             :                   u8 *sp;
     435             : 
     436           0 :                   for (index = 0; index < 4; index++)
     437             :                     {
     438           0 :                       dst4.as_u8[index] = dst0.as_u8[offset + index] << shift;
     439           0 :                       dst4.as_u8[index] |=
     440           0 :                         dst0.as_u8[offset + index + 1] >> (8 - shift);
     441             :                     }
     442             : 
     443           0 :                   qfi |= dst0.as_u8[offset + 4] << shift;
     444           0 :                   qfi |= dst0.as_u8[offset + 5] >> (8 - shift);
     445             : 
     446           0 :                   if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
     447           0 :                       gtpu_type == GTPU_TYPE_ECHO_REPLY ||
     448             :                       gtpu_type == GTPU_TYPE_ERROR_INDICATION)
     449             :                     {
     450           0 :                       sp = (u8 *) &seq;
     451           0 :                       for (index = 0; index < 2; index++)
     452             :                         {
     453           0 :                           sp[index] = dst0.as_u8[offset + 5 + index] << shift;
     454           0 :                           sp[index] |=
     455           0 :                             dst0.as_u8[offset + 6 + index] >> (8 - shift);
     456             :                         }
     457             :                     }
     458             :                   else
     459             :                     {
     460           0 :                       for (index = 0; index < 4; index++)
     461             :                         {
     462           0 :                           *teid8p = dst0.as_u8[offset + 5 + index] << shift;
     463           0 :                           *teid8p |=
     464           0 :                             dst0.as_u8[offset + 6 + index] >> (8 - shift);
     465           0 :                           teid8p++;
     466             :                         }
     467             :                     }
     468             :                 }
     469             : 
     470           2 :               if (qfi)
     471             :                 {
     472           2 :                   hdrlen =
     473             :                     sizeof (gtpu_exthdr_t) + sizeof (gtpu_pdu_session_t);
     474             :                 }
     475           0 :               else if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
     476           0 :                        gtpu_type == GTPU_TYPE_ECHO_REPLY ||
     477             :                        gtpu_type == GTPU_TYPE_ERROR_INDICATION)
     478             :                 {
     479           0 :                   hdrlen = sizeof (gtpu_exthdr_t);
     480             :                 }
     481             : 
     482           2 :               if (PREDICT_FALSE (gtpu_type == GTPU_TYPE_ECHO_REPLY))
     483             :                 {
     484           0 :                   hdrlen += sizeof (gtpu_recovery_ie);
     485             :                 }
     486             : 
     487           2 :               if (PREDICT_FALSE (gtpu_type == GTPU_TYPE_ERROR_INDICATION))
     488             :                 {
     489             :                   ip6_sr_tlv_t *tlv;
     490             :                   u16 ext_len;
     491             : 
     492           0 :                   ext_len = ip6srv0->sr.length * 8;
     493             : 
     494           0 :                   if (ext_len >
     495           0 :                       sizeof (ip6_address_t) * (ip6srv0->sr.last_entry + 1))
     496             :                     {
     497           0 :                       tlv = (ip6_sr_tlv_t *) ((u8 *) &ip6srv0->sr +
     498           0 :                                               sizeof (ip6_sr_header_t) +
     499           0 :                                               sizeof (ip6_address_t) *
     500           0 :                                                 (ip6srv0->sr.last_entry + 1));
     501             : 
     502           0 :                       if (tlv->type == SRH_TLV_USER_PLANE_CONTAINER)
     503             :                         {
     504             :                           user_plane_sub_tlv_t *sub_tlv;
     505             : 
     506           0 :                           sub_tlv = (user_plane_sub_tlv_t *) tlv->value;
     507             : 
     508           0 :                           ie_size = sub_tlv->length;
     509           0 :                           clib_memcpy_fast (ie_buf, sub_tlv->value, ie_size);
     510             : 
     511           0 :                           hdrlen += ie_size;
     512             :                         }
     513             :                     }
     514             :                 }
     515             : 
     516           2 :               if (ip6srv0->ip.protocol == IPPROTO_IPV6_ROUTE)
     517             :                 {
     518           2 :                   vlib_buffer_advance (b0,
     519             :                                        (word) sizeof (ip6srv_combo_header_t) +
     520           2 :                                          ip6srv0->sr.length * 8);
     521             :                 }
     522             :               else
     523             :                 {
     524           0 :                   vlib_buffer_advance (b0, (word) sizeof (ip6_header_t));
     525             :                 }
     526             : 
     527             :               // get length of encapsulated IPv6 packet (the remaining part)
     528           2 :               p = vlib_buffer_get_current (b0);
     529             : 
     530           2 :               plen = len0 = vlib_buffer_length_in_chain (vm, b0);
     531             : 
     532           2 :               len0 += hdrlen;
     533             : 
     534           2 :               hdrlen += sizeof (ip4_gtpu_header_t);
     535             : 
     536             :               // IPv4 GTP-U header creation.
     537           2 :               vlib_buffer_advance (b0, -(word) hdrlen);
     538             : 
     539           2 :               hdr0 = vlib_buffer_get_current (b0);
     540             : 
     541           2 :               clib_memcpy_fast (hdr0, &sm->cache_hdr,
     542             :                                 sizeof (ip4_gtpu_header_t));
     543             : 
     544           2 :               hdr0->ip4.dst_address.as_u32 = dst4.as_u32;
     545             : 
     546           2 :               hdr0->gtpu.teid = teid;
     547           2 :               hdr0->gtpu.length = clib_host_to_net_u16 (len0);
     548             : 
     549           2 :               hdr0->gtpu.type = gtpu_type;
     550             : 
     551           2 :               if (gtpu_type == GTPU_TYPE_ECHO_REPLY ||
     552           2 :                   gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
     553             :                   gtpu_type == GTPU_TYPE_ERROR_INDICATION)
     554             :                 {
     555           0 :                   hdr0->gtpu.ver_flags |= GTPU_SEQ_FLAG;
     556           0 :                   hdr0->gtpu.ext->seq = seq;
     557           0 :                   hdr0->gtpu.ext->npdu_num = 0;
     558           0 :                   hdr0->gtpu.ext->nextexthdr = 0;
     559             : 
     560           0 :                   if (gtpu_type == GTPU_TYPE_ECHO_REPLY)
     561             :                     {
     562             :                       gtpu_recovery_ie *recovery;
     563             : 
     564           0 :                       recovery =
     565           0 :                         (gtpu_recovery_ie *) ((u8 *) hdr0 +
     566             :                                               (hdrlen -
     567             :                                                sizeof (gtpu_recovery_ie)));
     568           0 :                       recovery->type = GTPU_RECOVERY_IE_TYPE;
     569           0 :                       recovery->restart_counter = 0;
     570             :                     }
     571           0 :                   else if (gtpu_type == GTPU_TYPE_ERROR_INDICATION)
     572             :                     {
     573           0 :                       if (ie_size)
     574             :                         {
     575             :                           u8 *ie_ptr;
     576             : 
     577           0 :                           ie_ptr = (u8 *) ((u8 *) hdr0 + (hdrlen - ie_size));
     578           0 :                           clib_memcpy_fast (ie_ptr, ie_buf, ie_size);
     579             :                         }
     580             :                     }
     581             :                 }
     582             :               else
     583             :                 {
     584           2 :                   if (qfi)
     585             :                     {
     586           2 :                       hdr0->gtpu.ext->seq = 0;
     587           2 :                       hdr0->gtpu.ext->npdu_num = 0;
     588             :                     }
     589             :                 }
     590             : 
     591           2 :               if (qfi)
     592             :                 {
     593           2 :                   u8 type = 0;
     594             :                   gtpu_pdu_session_t *sess;
     595             : 
     596           2 :                   hdr0->gtpu.ver_flags |= GTPU_EXTHDR_FLAG;
     597             : 
     598           2 :                   hdr0->gtpu.ext->nextexthdr = GTPU_EXTHDR_PDU_SESSION;
     599             : 
     600           2 :                   type = qfi & SRV6_PDU_SESSION_U_BIT_MASK;
     601             : 
     602           2 :                   qfi = ((qfi & SRV6_PDU_SESSION_QFI_MASK) >> 2) |
     603           2 :                         ((qfi & SRV6_PDU_SESSION_R_BIT_MASK) << 5);
     604             : 
     605           2 :                   sess = (gtpu_pdu_session_t *) (((char *) hdr0) +
     606             :                                                  sizeof (ip4_gtpu_header_t) +
     607             :                                                  sizeof (gtpu_exthdr_t));
     608           2 :                   sess->exthdrlen = 1;
     609           2 :                   sess->type = type;
     610           2 :                   sess->spare = 0;
     611           2 :                   sess->u.val = qfi;
     612           2 :                   sess->nextexthdr = 0;
     613             :                 }
     614             : 
     615           2 :               vnet_buffer (b0)->sw_if_index[VLIB_TX] = ls_param->fib4_index;
     616             : 
     617           2 :               if (ls_param->v4src_position)
     618             :                 {
     619           2 :                   offset = ls_param->v4src_position / 8;
     620           2 :                   shift = ls_param->v4src_position % 8;
     621             : 
     622           2 :                   if (PREDICT_TRUE (shift == 0))
     623             :                     {
     624          10 :                       for (index = 0; index < 4; index++)
     625             :                         {
     626           8 :                           hdr0->ip4.src_address.as_u8[index] =
     627           8 :                             src0.as_u8[offset + index];
     628             :                         }
     629             :                     }
     630             :                   else
     631             :                     {
     632           0 :                       for (index = 0; index < 4; index++)
     633             :                         {
     634           0 :                           hdr0->ip4.src_address.as_u8[index] =
     635           0 :                             src0.as_u8[offset + index] << shift;
     636           0 :                           hdr0->ip4.src_address.as_u8[index] |=
     637           0 :                             src0.as_u8[offset + index + 1] >> (8 - shift);
     638             :                         }
     639             :                     }
     640             :                 }
     641             :               else
     642             :                 {
     643           0 :                   clib_memcpy_fast (&hdr0->ip4.src_address,
     644           0 :                                     &ls_param->v4src_addr, 4);
     645             :                 }
     646             : 
     647           2 :               key = hash_memory (p, plen < 40 ? plen : 40, 0);
     648           2 :               port = hash_uword_to_u16 (&key);
     649           2 :               hdr0->udp.src_port = port;
     650             : 
     651           4 :               hdr0->udp.length = clib_host_to_net_u16 (
     652           2 :                 len0 + sizeof (udp_header_t) + sizeof (gtpu_header_t));
     653             : 
     654           2 :               hdr0->ip4.length =
     655           2 :                 clib_host_to_net_u16 (len0 + sizeof (ip4_gtpu_header_t));
     656             : 
     657           2 :               hdr0->ip4.checksum = ip4_header_checksum (&hdr0->ip4);
     658             : 
     659           2 :               good_n++;
     660             : 
     661           2 :               if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
     662           2 :                   PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
     663             :                 {
     664             :                   srv6_end_rewrite_trace_t *tr =
     665           2 :                     vlib_add_trace (vm, node, b0, sizeof (*tr));
     666           2 :                   clib_memcpy (tr->src.as_u8, hdr0->ip4.src_address.as_u8,
     667             :                                sizeof (hdr0->ip4.src_address.as_u8));
     668           2 :                   clib_memcpy (tr->dst.as_u8, hdr0->ip4.dst_address.as_u8,
     669             :                                sizeof (hdr0->ip4.dst_address.as_u8));
     670           2 :                   tr->teid = hdr0->gtpu.teid;
     671             :                 }
     672             :             }
     673             : 
     674           4 :           vlib_increment_combined_counter (
     675             :             ((next0 == SRV6_END_M_GTP4_E_NEXT_DROP) ?
     676             :                &(sm2->sr_ls_invalid_counters) :
     677             :                &(sm2->sr_ls_valid_counters)),
     678           2 :             thread_index, ls0 - sm2->localsids, 1,
     679             :             vlib_buffer_length_in_chain (vm, b0));
     680             : 
     681           2 :           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
     682             :                                            n_left_to_next, bi0, next0);
     683             :         }
     684             : 
     685           1 :       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
     686             :     }
     687             : 
     688           1 :   vlib_node_increment_counter (vm, sm->end_m_gtp4_e_node_index,
     689             :                                SRV6_END_ERROR_M_GTP4_E_BAD_PACKETS, bad_n);
     690             : 
     691           1 :   vlib_node_increment_counter (vm, sm->end_m_gtp4_e_node_index,
     692             :                                SRV6_END_ERROR_M_GTP4_E_PACKETS, good_n);
     693             : 
     694           1 :   return frame->n_vectors;
     695             : }
     696             : 
     697             : // Function for SRv6 GTP4.D function.
     698             : static inline u32
     699           2 : srv6_gtp4_decap_processing (vlib_main_t *vm, vlib_node_runtime_t *node,
     700             :                             vlib_buffer_t *b0)
     701             : {
     702           2 :   srv6_t_main_v4_decap_t *sm = &srv6_t_main_v4_decap;
     703           2 :   ip6_sr_main_t *sm2 = &sr_main;
     704             : 
     705             :   ip6_sr_sl_t *sl0;
     706             :   srv6_end_gtp4_d_param_t *ls_param;
     707             :   ip4_header_t *ip4;
     708             : 
     709             :   uword len0;
     710             : 
     711           2 :   u32 next0 = SRV6_T_M_GTP4_D_NEXT_LOOKUP6;
     712             : 
     713           2 :   sl0 = pool_elt_at_index (sm2->sid_lists,
     714             :                            vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
     715             : 
     716           2 :   ls_param = (srv6_end_gtp4_d_param_t *) sl0->plugin_mem;
     717             : 
     718           2 :   len0 = vlib_buffer_length_in_chain (vm, b0);
     719             : 
     720           2 :   ip4 = vlib_buffer_get_current (b0);
     721             : 
     722           2 :   if (ip4->protocol != IP_PROTOCOL_UDP || len0 < sizeof (ip4_gtpu_header_t))
     723             :     {
     724           0 :       next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
     725             :     }
     726             :   else
     727             :     {
     728             :       uword *p;
     729           2 :       ip6_sr_policy_t *sr_policy = NULL;
     730           2 :       ip6_sr_sl_t *sl = NULL;
     731             :       u32 *sl_index;
     732             :       u32 hdr_len;
     733             : 
     734             :       ip4_gtpu_header_t *hdr;
     735             :       ip4_address_t src, dst;
     736             :       u8 *srcp, *dstp;
     737           2 :       ip6_header_t *encap = NULL;
     738             :       ip6_address_t seg;
     739             :       ip6_address_t src6;
     740             :       u8 gtpu_type;
     741             :       u32 teid;
     742             :       u8 *teidp;
     743           2 :       u8 qfi = 0;
     744           2 :       u8 *qfip = NULL;
     745           2 :       u16 seq = 0;
     746             :       u8 *seqp;
     747             :       u32 offset, shift, index;
     748             :       ip6srv_combo_header_t *ip6srv;
     749           2 :       gtpu_pdu_session_t *sess = NULL;
     750           2 :       int ie_size = 0;
     751           2 :       u16 tlv_siz = 0;
     752             :       u8 ie_buf[GTPU_IE_MAX_SIZ];
     753             : 
     754             :       // Decap from GTP-U.
     755           2 :       hdr = (ip4_gtpu_header_t *) ip4;
     756             : 
     757           2 :       hdr_len = sizeof (ip4_gtpu_header_t);
     758             : 
     759           2 :       teid = hdr->gtpu.teid;
     760           2 :       teidp = (u8 *) &teid;
     761             : 
     762           2 :       seqp = (u8 *) &seq;
     763             : 
     764           2 :       gtpu_type = hdr->gtpu.type;
     765             : 
     766           2 :       if (hdr->gtpu.ver_flags & (GTPU_EXTHDR_FLAG | GTPU_SEQ_FLAG))
     767             :         {
     768             :           // Extention header.
     769           0 :           hdr_len += sizeof (gtpu_exthdr_t);
     770             : 
     771           0 :           seq = hdr->gtpu.ext->seq;
     772             : 
     773           0 :           if (hdr->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
     774             :             {
     775             :               // PDU Session Container.
     776           0 :               sess = (gtpu_pdu_session_t *) (((char *) hdr) + hdr_len);
     777           0 :               qfi = sess->u.val & ~GTPU_PDU_SESSION_P_BIT_MASK;
     778           0 :               qfip = (u8 *) &qfi;
     779             : 
     780           0 :               hdr_len += sizeof (gtpu_pdu_session_t);
     781             : 
     782           0 :               if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
     783             :                 {
     784           0 :                   hdr_len += sizeof (gtpu_paging_policy_t);
     785             :                 }
     786             :             }
     787             :         }
     788             : 
     789           2 :       src = hdr->ip4.src_address;
     790           2 :       srcp = (u8 *) &src;
     791             : 
     792           2 :       dst = hdr->ip4.dst_address;
     793           2 :       dstp = (u8 *) &dst;
     794             : 
     795           2 :       seg = ls_param->sr_prefix;
     796             : 
     797           2 :       offset = ls_param->sr_prefixlen / 8;
     798           2 :       shift = ls_param->sr_prefixlen % 8;
     799             : 
     800           2 :       if (PREDICT_TRUE (shift == 0))
     801             :         {
     802           2 :           clib_memcpy_fast (&seg.as_u8[offset], dstp, 4);
     803             : 
     804           2 :           if (qfip)
     805             :             {
     806           0 :               qfi = ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
     807           0 :                     ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
     808             : 
     809           0 :               if (sess->type)
     810             :                 {
     811           0 :                   qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
     812             :                 }
     813             : 
     814           0 :               seg.as_u8[offset + 4] = qfi;
     815             :             }
     816             : 
     817           2 :           if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
     818           2 :               gtpu_type == GTPU_TYPE_ECHO_REPLY ||
     819             :               gtpu_type == GTPU_TYPE_ERROR_INDICATION)
     820             :             {
     821           0 :               clib_memcpy_fast (&seg.as_u8[offset + 5], seqp, 2);
     822             :             }
     823             :           else
     824             :             {
     825           2 :               clib_memcpy_fast (&seg.as_u8[offset + 5], teidp, 4);
     826             :             }
     827             :         }
     828             :       else
     829             :         {
     830           0 :           for (index = 0; index < 4; index++)
     831             :             {
     832           0 :               seg.as_u8[offset + index] |= dstp[index] >> shift;
     833           0 :               seg.as_u8[offset + index + 1] |= dstp[index] << (8 - shift);
     834             :             }
     835             : 
     836           0 :           if (qfip)
     837             :             {
     838           0 :               qfi = ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
     839           0 :                     ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
     840             : 
     841           0 :               if (sess->type)
     842             :                 {
     843           0 :                   qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
     844             :                 }
     845             : 
     846           0 :               seg.as_u8[offset + 4] |= qfi >> shift;
     847           0 :               seg.as_u8[offset + 5] |= qfi << (8 - shift);
     848             :             }
     849             : 
     850           0 :           if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
     851           0 :               gtpu_type == GTPU_TYPE_ECHO_REPLY ||
     852             :               gtpu_type == GTPU_TYPE_ERROR_INDICATION)
     853             :             {
     854           0 :               for (index = 0; index < 2; index++)
     855             :                 {
     856           0 :                   seg.as_u8[offset + 5 + index] |= seqp[index] >> shift;
     857           0 :                   seg.as_u8[offset + 6 + index] |= seqp[index] << (8 - shift);
     858             :                 }
     859             :             }
     860             :           else
     861             :             {
     862           0 :               for (index = 0; index < 4; index++)
     863             :                 {
     864           0 :                   seg.as_u8[offset + index + 5] |= teidp[index] >> shift;
     865           0 :                   seg.as_u8[offset + index + 6] |= teidp[index] << (8 - shift);
     866             :                 }
     867             :             }
     868             :         }
     869             : 
     870           2 :       if (PREDICT_FALSE (gtpu_type == GTPU_TYPE_ERROR_INDICATION))
     871             :         {
     872             :           u16 payload_len;
     873             : 
     874           0 :           payload_len = clib_net_to_host_u16 (hdr->gtpu.length);
     875           0 :           if (payload_len != 0)
     876             :             {
     877           0 :               ie_size = payload_len - (hdr_len - sizeof (ip4_gtpu_header_t));
     878           0 :               if (ie_size > 0)
     879             :                 {
     880             :                   u8 *ies;
     881             : 
     882           0 :                   ies = (u8 *) ((u8 *) hdr + hdr_len);
     883           0 :                   clib_memcpy_fast (ie_buf, ies, ie_size);
     884           0 :                   hdr_len += ie_size;
     885             :                 }
     886             :             }
     887             :         }
     888             : 
     889           2 :       src6 = ls_param->v6src_prefix;
     890             : 
     891           2 :       offset = ls_param->v6src_prefixlen / 8;
     892           2 :       shift = ls_param->v6src_prefixlen % 8;
     893             : 
     894           2 :       if (PREDICT_TRUE (shift == 0))
     895             :         {
     896           2 :           clib_memcpy_fast (&src6.as_u8[offset], srcp, 4);
     897             :         }
     898             :       else
     899             :         {
     900           0 :           for (index = 0; index < 4; index++)
     901             :             {
     902           0 :               src6.as_u8[offset + index] |= srcp[offset] >> shift;
     903           0 :               src6.as_u8[offset + index + 1] |= srcp[offset] << (8 - shift);
     904             :             }
     905             :         }
     906             : 
     907           2 :       vlib_buffer_advance (b0, (word) hdr_len);
     908             : 
     909             :       // Encap to SRv6.
     910           2 :       if (PREDICT_TRUE (gtpu_type == GTPU_TYPE_GTPU))
     911             :         {
     912           2 :           encap = vlib_buffer_get_current (b0);
     913             :         }
     914             : 
     915           2 :       len0 = vlib_buffer_length_in_chain (vm, b0);
     916             : 
     917           2 :       p = mhash_get (&sm2->sr_policies_index_hash, &ls_param->sr_prefix);
     918           2 :       if (p)
     919             :         {
     920           2 :           sr_policy = pool_elt_at_index (sm2->sr_policies, p[0]);
     921             :         }
     922             : 
     923           2 :       if (sr_policy)
     924             :         {
     925           2 :           vec_foreach (sl_index, sr_policy->segments_lists)
     926             :             {
     927           2 :               sl = pool_elt_at_index (sm2->sid_lists, *sl_index);
     928           2 :               if (sl != NULL)
     929           2 :                 break;
     930             :             }
     931             :         }
     932             : 
     933           2 :       if (sl)
     934             :         {
     935           2 :           hdr_len = sizeof (ip6srv_combo_header_t);
     936           2 :           hdr_len += vec_len (sl->segments) * sizeof (ip6_address_t);
     937           2 :           hdr_len += sizeof (ip6_address_t);
     938             :         }
     939             :       else
     940             :         {
     941           0 :           hdr_len = sizeof (ip6_header_t);
     942             : 
     943           0 :           if (PREDICT_FALSE (gtpu_type != GTPU_TYPE_GTPU))
     944             :             {
     945           0 :               hdr_len += sizeof (ip6_sr_header_t);
     946           0 :               hdr_len += sizeof (ip6_address_t);
     947             :             }
     948             :         }
     949             : 
     950           2 :       if (ie_size)
     951             :         {
     952           0 :           tlv_siz =
     953           0 :             sizeof (ip6_sr_tlv_t) + sizeof (user_plane_sub_tlv_t) + ie_size;
     954             : 
     955           0 :           tlv_siz = (tlv_siz & ~0x07) + (tlv_siz & 0x07 ? 0x08 : 0x0);
     956           0 :           hdr_len += tlv_siz;
     957             :         }
     958             : 
     959           2 :       vlib_buffer_advance (b0, -(word) hdr_len);
     960           2 :       ip6srv = vlib_buffer_get_current (b0);
     961             : 
     962           2 :       if (sl)
     963             :         {
     964           2 :           clib_memcpy_fast (ip6srv, sl->rewrite, vec_len (sl->rewrite));
     965             : 
     966           2 :           if (vec_len (sl->segments) > 1)
     967             :             {
     968           2 :               ip6srv->sr.tag = clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
     969             : 
     970           2 :               ip6srv->sr.segments_left += 1;
     971           2 :               ip6srv->sr.last_entry += 1;
     972             : 
     973           2 :               ip6srv->sr.length += sizeof (ip6_address_t) / 8;
     974           2 :               ip6srv->sr.segments[0] = seg;
     975             : 
     976           0 :               clib_memcpy_fast (&ip6srv->sr.segments[1],
     977           2 :                                 (u8 *) (sl->rewrite + sizeof (ip6_header_t) +
     978             :                                         sizeof (ip6_sr_header_t)),
     979           2 :                                 vec_len (sl->segments) *
     980             :                                   sizeof (ip6_address_t));
     981             :             }
     982             :           else
     983             :             {
     984           0 :               ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
     985             : 
     986           0 :               ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
     987             : 
     988           0 :               ip6srv->sr.segments_left = 1;
     989           0 :               ip6srv->sr.last_entry = 0;
     990             : 
     991           0 :               ip6srv->sr.length =
     992             :                 ((sizeof (ip6_sr_header_t) + sizeof (ip6_address_t)) / 8) - 1;
     993           0 :               ip6srv->sr.flags = 0;
     994             : 
     995           0 :               ip6srv->sr.tag = clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
     996             : 
     997           0 :               ip6srv->sr.segments[0] = seg;
     998           0 :               if (vec_len (sl->segments))
     999             :                 {
    1000           0 :                   ip6srv->sr.segments[1] = sl->segments[0];
    1001           0 :                   ip6srv->sr.length += sizeof (ip6_address_t) / 8;
    1002           0 :                   ip6srv->sr.last_entry++;
    1003             :                 }
    1004             :             }
    1005             : 
    1006           2 :           if (PREDICT_TRUE (encap != NULL))
    1007             :             {
    1008           2 :               if (ls_param->nhtype == SRV6_NHTYPE_NONE)
    1009             :                 {
    1010           0 :                   if ((clib_net_to_host_u32 (
    1011           0 :                          encap->ip_version_traffic_class_and_flow_label) >>
    1012             :                        28) == 6)
    1013           0 :                     ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
    1014             :                   else
    1015           0 :                     ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
    1016             :                 }
    1017           2 :               else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
    1018             :                 {
    1019           0 :                   ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
    1020           0 :                   if ((clib_net_to_host_u32 (
    1021           0 :                          encap->ip_version_traffic_class_and_flow_label) >>
    1022             :                        28) != 4)
    1023             :                     {
    1024             :                       // Bad encap packet.
    1025           0 :                       next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
    1026           0 :                       goto DONE;
    1027             :                     }
    1028             :                 }
    1029           2 :               else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
    1030             :                 {
    1031           2 :                   ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
    1032           2 :                   if ((clib_net_to_host_u32 (
    1033           2 :                          encap->ip_version_traffic_class_and_flow_label) >>
    1034             :                        28) != 6)
    1035             :                     {
    1036             :                       // Bad encap packet.
    1037           0 :                       next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
    1038           0 :                       goto DONE;
    1039             :                     }
    1040             :                 }
    1041           0 :               else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
    1042             :                 {
    1043           0 :                   ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
    1044             :                 }
    1045             :             }
    1046             :           else
    1047             :             {
    1048           0 :               ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
    1049             :             }
    1050             :         }
    1051             :       else
    1052             :         {
    1053           0 :           clib_memcpy_fast (ip6srv, &sm->cache_hdr, sizeof (ip6_header_t));
    1054             : 
    1055           0 :           ip6srv->ip.dst_address = seg;
    1056             : 
    1057           0 :           if (PREDICT_FALSE (gtpu_type != GTPU_TYPE_GTPU))
    1058             :             {
    1059           0 :               ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
    1060             : 
    1061           0 :               ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
    1062             : 
    1063           0 :               ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
    1064             : 
    1065           0 :               ip6srv->sr.tag = clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
    1066             : 
    1067           0 :               ip6srv->sr.segments_left = 0;
    1068           0 :               ip6srv->sr.last_entry = 0;
    1069             : 
    1070           0 :               ip6srv->sr.length = sizeof (ip6_address_t) / 8;
    1071           0 :               ip6srv->sr.segments[0] = seg;
    1072             :             }
    1073             :           else
    1074             :             {
    1075           0 :               if (ls_param->nhtype == SRV6_NHTYPE_NONE)
    1076             :                 {
    1077           0 :                   if ((clib_net_to_host_u32 (
    1078           0 :                          encap->ip_version_traffic_class_and_flow_label) >>
    1079             :                        28) == 6)
    1080           0 :                     ip6srv->ip.protocol = IP_PROTOCOL_IPV6;
    1081             :                   else
    1082           0 :                     ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
    1083             :                 }
    1084           0 :               else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
    1085             :                 {
    1086           0 :                   ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
    1087           0 :                   if ((clib_net_to_host_u32 (
    1088           0 :                          encap->ip_version_traffic_class_and_flow_label) >>
    1089             :                        28) != 4)
    1090             :                     {
    1091             :                       // Bad encap packet.
    1092           0 :                       next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
    1093           0 :                       goto DONE;
    1094             :                     }
    1095             :                 }
    1096           0 :               else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
    1097             :                 {
    1098           0 :                   ip6srv->ip.protocol = IP_PROTOCOL_IPV6;
    1099           0 :                   if ((clib_net_to_host_u32 (
    1100           0 :                          encap->ip_version_traffic_class_and_flow_label) >>
    1101             :                        28) != 6)
    1102             :                     {
    1103             :                       // Bad encap packet.
    1104           0 :                       next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
    1105           0 :                       goto DONE;
    1106             :                     }
    1107             :                 }
    1108           0 :               else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
    1109             :                 {
    1110           0 :                   ip6srv->ip.protocol = IP_PROTOCOL_IP6_ETHERNET;
    1111             :                 }
    1112             :             }
    1113             :         }
    1114             : 
    1115           2 :       ip6srv->ip.src_address = src6;
    1116             : 
    1117           2 :       if (PREDICT_FALSE (ie_size))
    1118             :         {
    1119             :           ip6_sr_tlv_t *tlv;
    1120             :           user_plane_sub_tlv_t *sub_tlv;
    1121             : 
    1122           0 :           tlv = (ip6_sr_tlv_t *) ((u8 *) ip6srv + (hdr_len - tlv_siz));
    1123           0 :           tlv->type = SRH_TLV_USER_PLANE_CONTAINER;
    1124           0 :           tlv->length = (u8) (tlv_siz - sizeof (ip6_sr_tlv_t));
    1125           0 :           clib_memset (tlv->value, 0, tlv->length);
    1126             : 
    1127           0 :           sub_tlv = (user_plane_sub_tlv_t *) tlv->value;
    1128           0 :           sub_tlv->type = USER_PLANE_SUB_TLV_IE;
    1129           0 :           sub_tlv->length = (u8) ie_size;
    1130           0 :           clib_memcpy_fast (sub_tlv->value, ie_buf, ie_size);
    1131             : 
    1132           0 :           ip6srv->sr.length += (u8) (tlv_siz / 8);
    1133             :         }
    1134             : 
    1135           2 :       ip6srv->ip.payload_length =
    1136           2 :         clib_host_to_net_u16 (len0 + hdr_len - sizeof (ip6_header_t));
    1137             : 
    1138           2 :       vnet_buffer (b0)->sw_if_index[VLIB_TX] = 0; /* default FIB */
    1139             : 
    1140           2 :       if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
    1141           2 :           PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
    1142             :         {
    1143             :           srv6_end_rewrite_trace_t *tr =
    1144           2 :             vlib_add_trace (vm, node, b0, sizeof (*tr));
    1145           2 :           clib_memcpy (tr->src.as_u8, ip6srv->ip.src_address.as_u8,
    1146             :                        sizeof (tr->src.as_u8));
    1147           2 :           clib_memcpy (tr->dst.as_u8, ip6srv->ip.dst_address.as_u8,
    1148             :                        sizeof (tr->dst.as_u8));
    1149             :         }
    1150             :     }
    1151             : 
    1152           2 : DONE:
    1153           2 :   return next0;
    1154             : }
    1155             : 
    1156         576 : VLIB_NODE_FN (srv6_t_m_gtp4_d)
    1157             : (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
    1158             : {
    1159           1 :   srv6_t_main_v4_decap_t *sm = &srv6_t_main_v4_decap;
    1160           1 :   ip6_sr_main_t *sm2 = &sr_main;
    1161             :   u32 n_left_from, next_index, *from, *to_next;
    1162             : 
    1163             :   ip6_sr_sl_t *sl0;
    1164             :   srv6_end_gtp4_d_param_t *ls_param;
    1165             : 
    1166           1 :   u32 good_n = 0, bad_n = 0;
    1167             : 
    1168           1 :   from = vlib_frame_vector_args (frame);
    1169           1 :   n_left_from = frame->n_vectors;
    1170           1 :   next_index = node->cached_next_index;
    1171             : 
    1172           2 :   while (n_left_from > 0)
    1173             :     {
    1174             :       u32 n_left_to_next;
    1175             : 
    1176           1 :       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
    1177             : 
    1178           3 :       while (n_left_from > 0 && n_left_to_next > 0)
    1179             :         {
    1180             :           u32 bi0;
    1181             :           vlib_buffer_t *b0;
    1182             : 
    1183             :           u32 next0;
    1184             : 
    1185             :           ip4_gtpu_header_t *hdr;
    1186             :           u32 hdrlen;
    1187             :           u8 gtpu_type;
    1188             :           bool gtp4;
    1189             :           bool ipv4;
    1190             : 
    1191             :           // defaults
    1192           2 :           bi0 = from[0];
    1193           2 :           to_next[0] = bi0;
    1194           2 :           from += 1;
    1195           2 :           to_next += 1;
    1196           2 :           n_left_from -= 1;
    1197           2 :           n_left_to_next -= 1;
    1198             : 
    1199           2 :           b0 = vlib_get_buffer (vm, bi0);
    1200             : 
    1201           2 :           sl0 = pool_elt_at_index (sm2->sid_lists,
    1202             :                                    vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
    1203             : 
    1204           2 :           ls_param = (srv6_end_gtp4_d_param_t *) sl0->plugin_mem;
    1205             : 
    1206           2 :           hdr = vlib_buffer_get_current (b0);
    1207           2 :           gtpu_type = hdr->gtpu.type;
    1208             : 
    1209           2 :           gtp4 = false;
    1210           2 :           ipv4 = true;
    1211             : 
    1212           2 :           if (PREDICT_FALSE (gtpu_type != GTPU_TYPE_GTPU || ls_param->drop_in))
    1213             :             {
    1214           2 :               gtp4 = true;
    1215             :             }
    1216             :           else
    1217             :             {
    1218             :               ip6_header_t *ip6;
    1219             : 
    1220           0 :               hdrlen = sizeof (ip4_gtpu_header_t);
    1221             : 
    1222           0 :               if (hdr->gtpu.ver_flags & (GTPU_EXTHDR_FLAG | GTPU_SEQ_FLAG))
    1223             :                 {
    1224           0 :                   hdrlen += sizeof (gtpu_exthdr_t);
    1225           0 :                   if (hdr->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
    1226             :                     {
    1227             :                       gtpu_pdu_session_t *sess;
    1228           0 :                       sess = (gtpu_pdu_session_t *) (((char *) hdr) + hdrlen);
    1229           0 :                       hdrlen += sizeof (gtpu_pdu_session_t);
    1230             : 
    1231           0 :                       if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
    1232             :                         {
    1233           0 :                           hdrlen += sizeof (gtpu_paging_policy_t);
    1234             :                         }
    1235             :                     }
    1236             :                 }
    1237             : 
    1238           0 :               ip6 = (ip6_header_t *) (((char *) hdr) + hdrlen);
    1239           0 :               if ((clib_net_to_host_u32 (
    1240           0 :                      ip6->ip_version_traffic_class_and_flow_label) >>
    1241             :                    28) == 6)
    1242             :                 {
    1243           0 :                   ipv4 = false;
    1244           0 :                   if (((ip6->dst_address.as_u8[0] == 0xff) &&
    1245           0 :                        (ip6->dst_address.as_u8[1] == 0x02)) ||
    1246           0 :                       ((ip6->dst_address.as_u8[0] == 0xfe) &&
    1247           0 :                        ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80)))
    1248             :                     {
    1249             :                       // Inner desitnation is IPv6 link local
    1250           0 :                       gtp4 = true;
    1251             :                     }
    1252             :                 }
    1253             :             }
    1254             : 
    1255           2 :           if (gtp4)
    1256             :             {
    1257           2 :               next0 = srv6_gtp4_decap_processing (vm, node, b0);
    1258           2 :               if (PREDICT_TRUE (next0 == SRV6_T_M_GTP4_D_NEXT_LOOKUP6))
    1259           2 :                 good_n++;
    1260             :               else
    1261           0 :                 bad_n++;
    1262             :             }
    1263             :           else
    1264             :             {
    1265             :               /* Strip off the outer header (IPv4 + GTP + UDP + IEs) */
    1266           0 :               vlib_buffer_advance (b0, (word) hdrlen);
    1267             : 
    1268           0 :               if (ipv4)
    1269             :                 {
    1270           0 :                   next0 = SRV6_T_M_GTP4_D_NEXT_LOOKUP4;
    1271           0 :                   vnet_buffer (b0)->sw_if_index[VLIB_TX] =
    1272           0 :                     ls_param->fib4_index;
    1273             :                 }
    1274             :               else
    1275             :                 {
    1276           0 :                   next0 = SRV6_T_M_GTP4_D_NEXT_LOOKUP6;
    1277           0 :                   vnet_buffer (b0)->sw_if_index[VLIB_TX] =
    1278           0 :                     ls_param->fib6_index;
    1279             :                 }
    1280             :             }
    1281             : 
    1282           2 :           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
    1283             :                                            n_left_to_next, bi0, next0);
    1284             :         }
    1285             : 
    1286           1 :       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
    1287             :     }
    1288             : 
    1289           1 :   vlib_node_increment_counter (vm, sm->t_m_gtp4_d_node_index,
    1290             :                                SRV6_T_ERROR_M_GTP4_D_BAD_PACKETS, bad_n);
    1291             : 
    1292           1 :   vlib_node_increment_counter (vm, sm->t_m_gtp4_d_node_index,
    1293             :                                SRV6_T_ERROR_M_GTP4_D_PACKETS, good_n);
    1294             : 
    1295           1 :   return frame->n_vectors;
    1296             : }
    1297             : 
    1298       32255 : VLIB_REGISTER_NODE (srv6_end_m_gtp4_e) =
    1299             : {
    1300             :   .name = "srv6-end-m-gtp4-e",.vector_size = sizeof (u32),.format_trace =
    1301             :     format_srv6_end_rewrite_trace,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
    1302             :     ARRAY_LEN (srv6_end_error_v4_strings),.error_strings =
    1303             :     srv6_end_error_v4_strings,.n_next_nodes =
    1304             :     SRV6_END_M_GTP4_E_N_NEXT,.next_nodes =
    1305             :   {
    1306             :   [SRV6_END_M_GTP4_E_NEXT_DROP] = "error-drop",
    1307             :   [SRV6_END_M_GTP4_E_NEXT_LOOKUP] = "ip4-lookup",}
    1308             : ,};
    1309             : 
    1310       32255 : VLIB_REGISTER_NODE (srv6_t_m_gtp4_d) =
    1311             : {
    1312             :   .name = "srv6-t-m-gtp4-d",.vector_size = sizeof (u32),.format_trace =
    1313             :     format_srv6_end_rewrite_trace,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
    1314             :     ARRAY_LEN (srv6_t_error_v4_d_strings),.error_strings =
    1315             :     srv6_t_error_v4_d_strings,.n_next_nodes =
    1316             :     SRV6_T_M_GTP4_D_N_NEXT,.next_nodes =
    1317             :   {
    1318             :   [SRV6_T_M_GTP4_D_NEXT_DROP] = "error-drop",
    1319             :   [SRV6_T_M_GTP4_D_NEXT_LOOKUP4] = "ip4-lookup",
    1320             :   [SRV6_T_M_GTP4_D_NEXT_LOOKUP6] = "ip6-lookup",}
    1321             : ,};
    1322             : 
    1323             : // Function for SRv6 GTP6.E function
    1324         576 : VLIB_NODE_FN (srv6_end_m_gtp6_e)
    1325             : (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
    1326             : {
    1327           1 :   srv6_end_main_v6_t *sm = &srv6_end_main_v6;
    1328           1 :   ip6_sr_main_t *sm2 = &sr_main;
    1329             :   u32 n_left_from, next_index, *from, *to_next;
    1330           1 :   u32 thread_index = vm->thread_index;
    1331             : 
    1332           1 :   u32 good_n = 0, bad_n = 0;
    1333             : 
    1334           1 :   from = vlib_frame_vector_args (frame);
    1335           1 :   n_left_from = frame->n_vectors;
    1336           1 :   next_index = node->cached_next_index;
    1337             : 
    1338           2 :   while (n_left_from > 0)
    1339             :     {
    1340             :       u32 n_left_to_next;
    1341             : 
    1342           1 :       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
    1343             : 
    1344           3 :       while (n_left_from > 0 && n_left_to_next > 0)
    1345             :         {
    1346             :           u32 bi0;
    1347             :           vlib_buffer_t *b0;
    1348             :           ip6_sr_localsid_t *ls0;
    1349             :           srv6_end_gtp6_e_param_t *ls_param;
    1350             : 
    1351             :           ip6srv_combo_header_t *ip6srv0;
    1352             :           ip6_address_t dst0, src0, seg0;
    1353             : 
    1354           2 :           ip6_gtpu_header_t *hdr0 = NULL;
    1355             :           uword len0;
    1356             :           uword key;
    1357             :           u16 port;
    1358             :           u16 tag;
    1359             :           void *p;
    1360             :           uword plen;
    1361             : 
    1362           2 :           u32 next0 = SRV6_END_M_GTP6_E_NEXT_LOOKUP;
    1363             : 
    1364             :           // defaults
    1365           2 :           bi0 = from[0];
    1366           2 :           to_next[0] = bi0;
    1367           2 :           from += 1;
    1368           2 :           to_next += 1;
    1369           2 :           n_left_from -= 1;
    1370           2 :           n_left_to_next -= 1;
    1371             : 
    1372           2 :           b0 = vlib_get_buffer (vm, bi0);
    1373           2 :           ls0 = pool_elt_at_index (sm2->localsids,
    1374             :                                    vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
    1375             : 
    1376           2 :           ls_param = (srv6_end_gtp6_e_param_t *) ls0->plugin_mem;
    1377             : 
    1378           2 :           ip6srv0 = vlib_buffer_get_current (b0);
    1379           2 :           dst0 = ip6srv0->ip.dst_address;
    1380           2 :           src0 = ip6srv0->ip.src_address;
    1381           2 :           seg0 = ip6srv0->sr.segments[0];
    1382             : 
    1383           2 :           tag = ip6srv0->sr.tag;
    1384             : 
    1385           2 :           len0 = vlib_buffer_length_in_chain (vm, b0);
    1386             : 
    1387           2 :           if ((ip6srv0->ip.protocol != IPPROTO_IPV6_ROUTE) ||
    1388           2 :               (len0 < sizeof (ip6srv_combo_header_t) + 8 * ip6srv0->sr.length))
    1389             :             {
    1390           0 :               next0 = SRV6_END_M_GTP6_E_NEXT_DROP;
    1391             : 
    1392           0 :               bad_n++;
    1393             :             }
    1394             :           else
    1395             :             {
    1396             :               // we need to be sure there is enough space before
    1397             :               // ip6srv0 header, there is some extra space
    1398             :               // in the pre_data area for this kind of
    1399             :               // logic
    1400             : 
    1401           2 :               u32 teid = 0;
    1402           2 :               u8 *teid8p = (u8 *) &teid;
    1403           2 :               u8 qfi = 0;
    1404           2 :               u16 seq = 0;
    1405           2 :               u8 gtpu_type = 0;
    1406             :               u16 index;
    1407             :               u16 offset, shift;
    1408           2 :               u32 hdrlen = 0;
    1409           2 :               u16 ie_size = 0;
    1410             :               u8 ie_buf[GTPU_IE_MAX_SIZ];
    1411             : 
    1412           2 :               index = ls0->localsid_prefix_len;
    1413           2 :               offset = index / 8;
    1414           2 :               shift = index % 8;
    1415             : 
    1416           2 :               gtpu_type = gtpu_type_get (tag);
    1417             : 
    1418           2 :               if (PREDICT_TRUE (shift == 0))
    1419             :                 {
    1420           2 :                   qfi = dst0.as_u8[offset];
    1421           2 :                   if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
    1422           2 :                       gtpu_type == GTPU_TYPE_ECHO_REPLY ||
    1423             :                       gtpu_type == GTPU_TYPE_ERROR_INDICATION)
    1424             :                     {
    1425           0 :                       clib_memcpy_fast (&seq, &dst0.as_u8[offset + 1], 2);
    1426             :                     }
    1427             :                   else
    1428             :                     {
    1429           2 :                       clib_memcpy_fast (teid8p, &dst0.as_u8[offset + 1], 4);
    1430             :                     }
    1431             :                 }
    1432             :               else
    1433             :                 {
    1434             :                   u8 *sp;
    1435             : 
    1436           0 :                   qfi |= dst0.as_u8[offset] << shift;
    1437           0 :                   qfi |= dst0.as_u8[offset + 1] >> (8 - shift);
    1438             : 
    1439           0 :                   if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
    1440           0 :                       gtpu_type == GTPU_TYPE_ECHO_REPLY ||
    1441             :                       gtpu_type == GTPU_TYPE_ERROR_INDICATION)
    1442             :                     {
    1443           0 :                       sp = (u8 *) &seq;
    1444           0 :                       for (index = 0; index < 2; index++)
    1445             :                         {
    1446           0 :                           sp[index] = dst0.as_u8[offset + 1 + index] << shift;
    1447           0 :                           sp[index] |=
    1448           0 :                             dst0.as_u8[offset + index + 2] >> (8 - shift);
    1449             :                         }
    1450             :                     }
    1451             :                   else
    1452             :                     {
    1453           0 :                       for (index = 0; index < 4; index++)
    1454             :                         {
    1455           0 :                           *teid8p = dst0.as_u8[offset + index + 1] << shift;
    1456           0 :                           *teid8p |=
    1457           0 :                             dst0.as_u8[offset + index + 2] >> (8 - shift);
    1458           0 :                           teid8p++;
    1459             :                         }
    1460             :                     }
    1461             :                 }
    1462             : 
    1463           2 :               if (qfi)
    1464             :                 {
    1465           0 :                   hdrlen =
    1466             :                     sizeof (gtpu_exthdr_t) + sizeof (gtpu_pdu_session_t);
    1467             :                 }
    1468           2 :               else if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
    1469           2 :                        gtpu_type == GTPU_TYPE_ECHO_REPLY ||
    1470             :                        gtpu_type == GTPU_TYPE_ERROR_INDICATION)
    1471             :                 {
    1472           0 :                   hdrlen = sizeof (gtpu_exthdr_t);
    1473             :                 }
    1474             : 
    1475           2 :               if (gtpu_type == GTPU_TYPE_ECHO_REPLY)
    1476             :                 {
    1477           0 :                   hdrlen += sizeof (gtpu_recovery_ie);
    1478             :                 }
    1479             : 
    1480           2 :               if (PREDICT_FALSE (gtpu_type == GTPU_TYPE_ERROR_INDICATION))
    1481             :                 {
    1482             :                   ip6_sr_tlv_t *tlv;
    1483             :                   u16 ext_len;
    1484             : 
    1485           0 :                   ext_len = ip6srv0->sr.length * 8;
    1486             : 
    1487           0 :                   if (ext_len >
    1488           0 :                       sizeof (ip6_address_t) * (ip6srv0->sr.last_entry + 1))
    1489             :                     {
    1490           0 :                       tlv = (ip6_sr_tlv_t *) ((u8 *) &ip6srv0->sr +
    1491           0 :                                               sizeof (ip6_sr_header_t) +
    1492           0 :                                               sizeof (ip6_address_t) *
    1493           0 :                                                 (ip6srv0->sr.last_entry + 1));
    1494             : 
    1495           0 :                       if (tlv->type == SRH_TLV_USER_PLANE_CONTAINER)
    1496             :                         {
    1497             :                           user_plane_sub_tlv_t *sub_tlv;
    1498             : 
    1499           0 :                           sub_tlv = (user_plane_sub_tlv_t *) tlv->value;
    1500             : 
    1501           0 :                           ie_size = sub_tlv->length;
    1502           0 :                           clib_memcpy_fast (ie_buf, sub_tlv->value, ie_size);
    1503             : 
    1504           0 :                           hdrlen += ie_size;
    1505             :                         }
    1506             :                     }
    1507             :                 }
    1508             : 
    1509           2 :               vlib_buffer_advance (b0, (word) sizeof (ip6srv_combo_header_t) +
    1510           2 :                                          ip6srv0->sr.length * 8);
    1511             : 
    1512             :               // get length of encapsulated IPv6 packet (the remaining part)
    1513           2 :               p = vlib_buffer_get_current (b0);
    1514             : 
    1515           2 :               plen = len0 = vlib_buffer_length_in_chain (vm, b0);
    1516             : 
    1517           2 :               len0 += hdrlen;
    1518             : 
    1519           2 :               hdrlen += sizeof (ip6_gtpu_header_t);
    1520             : 
    1521           2 :               vlib_buffer_advance (b0, -(word) hdrlen);
    1522             : 
    1523           2 :               hdr0 = vlib_buffer_get_current (b0);
    1524             : 
    1525           2 :               clib_memcpy_fast (hdr0, &sm->cache_hdr,
    1526             :                                 sizeof (ip6_gtpu_header_t));
    1527             : 
    1528           2 :               hdr0->gtpu.teid = teid;
    1529           2 :               hdr0->gtpu.length = clib_host_to_net_u16 (len0);
    1530             : 
    1531           2 :               hdr0->gtpu.type = gtpu_type;
    1532             : 
    1533           2 :               if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
    1534           2 :                   gtpu_type == GTPU_TYPE_ECHO_REPLY ||
    1535             :                   gtpu_type == GTPU_TYPE_ERROR_INDICATION)
    1536             :                 {
    1537           0 :                   hdr0->gtpu.ver_flags |= GTPU_SEQ_FLAG;
    1538           0 :                   hdr0->gtpu.ext->seq = seq;
    1539           0 :                   hdr0->gtpu.ext->npdu_num = 0;
    1540           0 :                   hdr0->gtpu.ext->nextexthdr = 0;
    1541             : 
    1542           0 :                   if (gtpu_type == GTPU_TYPE_ECHO_REPLY)
    1543             :                     {
    1544             :                       gtpu_recovery_ie *recovery;
    1545             : 
    1546           0 :                       recovery =
    1547           0 :                         (gtpu_recovery_ie *) ((u8 *) hdr0 +
    1548             :                                               (hdrlen -
    1549             :                                                sizeof (gtpu_recovery_ie)));
    1550           0 :                       recovery->type = GTPU_RECOVERY_IE_TYPE;
    1551           0 :                       recovery->restart_counter = 0;
    1552             :                     }
    1553           0 :                   else if (gtpu_type == GTPU_TYPE_ERROR_INDICATION)
    1554             :                     {
    1555           0 :                       if (ie_size)
    1556             :                         {
    1557             :                           u8 *ie_ptr;
    1558             : 
    1559           0 :                           ie_ptr = (u8 *) ((u8 *) hdr0 + (hdrlen - ie_size));
    1560           0 :                           clib_memcpy_fast (ie_ptr, ie_buf, ie_size);
    1561             :                         }
    1562             :                     }
    1563             :                 }
    1564             :               else
    1565             :                 {
    1566           2 :                   if (qfi)
    1567             :                     {
    1568           0 :                       hdr0->gtpu.ext->seq = 0;
    1569           0 :                       hdr0->gtpu.ext->npdu_num = 0;
    1570             :                     }
    1571             :                 }
    1572             : 
    1573           2 :               if (qfi)
    1574             :                 {
    1575           0 :                   u8 type = 0;
    1576             :                   gtpu_pdu_session_t *sess;
    1577             : 
    1578           0 :                   hdr0->gtpu.ver_flags |= GTPU_EXTHDR_FLAG;
    1579             : 
    1580           0 :                   hdr0->gtpu.ext->nextexthdr = GTPU_EXTHDR_PDU_SESSION;
    1581             : 
    1582           0 :                   type = qfi & SRV6_PDU_SESSION_U_BIT_MASK;
    1583             : 
    1584           0 :                   qfi = ((qfi & SRV6_PDU_SESSION_QFI_MASK) >> 2) |
    1585           0 :                         ((qfi & SRV6_PDU_SESSION_R_BIT_MASK) << 5);
    1586             : 
    1587           0 :                   sess = (gtpu_pdu_session_t *) (((char *) hdr0) +
    1588             :                                                  sizeof (ip6_gtpu_header_t) +
    1589             :                                                  sizeof (gtpu_exthdr_t));
    1590           0 :                   sess->exthdrlen = 1;
    1591           0 :                   sess->type = type;
    1592           0 :                   sess->spare = 0;
    1593           0 :                   sess->u.val = qfi;
    1594           0 :                   sess->nextexthdr = 0;
    1595             :                 }
    1596             : 
    1597           4 :               hdr0->udp.length = clib_host_to_net_u16 (
    1598           2 :                 len0 + sizeof (udp_header_t) + sizeof (gtpu_header_t));
    1599             : 
    1600           2 :               clib_memcpy_fast (hdr0->ip6.src_address.as_u8, src0.as_u8,
    1601             :                                 sizeof (ip6_address_t));
    1602           2 :               clib_memcpy_fast (hdr0->ip6.dst_address.as_u8, &seg0.as_u8,
    1603             :                                 sizeof (ip6_address_t));
    1604             : 
    1605           4 :               hdr0->ip6.payload_length = clib_host_to_net_u16 (
    1606           2 :                 len0 + sizeof (udp_header_t) + sizeof (gtpu_header_t));
    1607             : 
    1608             :               // UDP source port.
    1609           2 :               key = hash_memory (p, plen < 40 ? plen : 40, 0);
    1610           2 :               port = hash_uword_to_u16 (&key);
    1611           2 :               hdr0->udp.src_port = port;
    1612             : 
    1613           2 :               vnet_buffer (b0)->sw_if_index[VLIB_TX] = ls_param->fib6_index;
    1614             : 
    1615           2 :               good_n++;
    1616             : 
    1617           2 :               if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
    1618           2 :                   PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
    1619             :                 {
    1620             :                   srv6_end_rewrite_trace_t *tr =
    1621           2 :                     vlib_add_trace (vm, node, b0, sizeof (*tr));
    1622           2 :                   clib_memcpy (tr->src.as_u8, hdr0->ip6.src_address.as_u8,
    1623             :                                sizeof (ip6_address_t));
    1624           2 :                   clib_memcpy (tr->dst.as_u8, hdr0->ip6.dst_address.as_u8,
    1625             :                                sizeof (ip6_address_t));
    1626           2 :                   tr->teid = hdr0->gtpu.teid;
    1627             :                 }
    1628             :             }
    1629             : 
    1630           4 :           vlib_increment_combined_counter (
    1631             :             ((next0 == SRV6_END_M_GTP6_E_NEXT_DROP) ?
    1632             :                &(sm2->sr_ls_invalid_counters) :
    1633             :                &(sm2->sr_ls_valid_counters)),
    1634           2 :             thread_index, ls0 - sm2->localsids, 1,
    1635             :             vlib_buffer_length_in_chain (vm, b0));
    1636             : 
    1637           2 :           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
    1638             :                                            n_left_to_next, bi0, next0);
    1639             :         }
    1640             : 
    1641           1 :       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
    1642             :     }
    1643             : 
    1644           1 :   vlib_node_increment_counter (vm, sm->end_m_gtp6_e_node_index,
    1645             :                                SRV6_END_ERROR_M_GTP6_E_BAD_PACKETS, bad_n);
    1646             : 
    1647           1 :   vlib_node_increment_counter (vm, sm->end_m_gtp6_e_node_index,
    1648             :                                SRV6_END_ERROR_M_GTP6_E_PACKETS, good_n);
    1649             : 
    1650           1 :   return frame->n_vectors;
    1651             : }
    1652             : 
    1653             : // Function for SRv6 GTP6.D function
    1654             : static inline u32
    1655           2 : srv6_gtp6_decap_processing (vlib_main_t *vm, vlib_node_runtime_t *node,
    1656             :                             vlib_buffer_t *b0)
    1657             : {
    1658           2 :   srv6_end_main_v6_decap_t *sm = &srv6_end_main_v6_decap;
    1659           2 :   ip6_sr_main_t *sm2 = &sr_main;
    1660             : 
    1661             :   ip6_sr_localsid_t *ls0;
    1662             :   srv6_end_gtp6_d_param_t *ls_param;
    1663             : 
    1664           2 :   ip6_gtpu_header_t *hdr0 = NULL;
    1665             :   uword len0;
    1666             : 
    1667             :   ip6_address_t seg0, src0, dst0;
    1668           2 :   u32 teid = 0;
    1669             :   u8 *teidp;
    1670           2 :   u8 gtpu_type = 0;
    1671             :   u8 qfi;
    1672           2 :   u8 *qfip = NULL;
    1673           2 :   u16 seq = 0;
    1674             :   u8 *seqp;
    1675             :   u32 offset, shift;
    1676             :   u32 hdrlen;
    1677           2 :   ip6_header_t *encap = NULL;
    1678           2 :   gtpu_pdu_session_t *sess = NULL;
    1679           2 :   int ie_size = 0;
    1680           2 :   u16 tlv_siz = 0;
    1681             :   u8 ie_buf[GTPU_IE_MAX_SIZ];
    1682             : 
    1683           2 :   u32 next0 = SRV6_END_M_GTP6_D_NEXT_LOOKUP6;
    1684             : 
    1685           2 :   ls0 = pool_elt_at_index (sm2->localsids,
    1686             :                            vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
    1687             : 
    1688           2 :   ls_param = (srv6_end_gtp6_d_param_t *) ls0->plugin_mem;
    1689             : 
    1690           2 :   hdr0 = vlib_buffer_get_current (b0);
    1691             : 
    1692           2 :   hdrlen = sizeof (ip6_gtpu_header_t);
    1693             : 
    1694           2 :   len0 = vlib_buffer_length_in_chain (vm, b0);
    1695             : 
    1696           4 :   if ((hdr0->ip6.protocol != IP_PROTOCOL_UDP) ||
    1697           4 :       (hdr0->udp.dst_port != clib_host_to_net_u16 (SRV6_GTP_UDP_DST_PORT)) ||
    1698             :       (len0 < sizeof (ip6_gtpu_header_t)))
    1699             :     {
    1700           0 :       next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
    1701             :     }
    1702             :   else
    1703             :     {
    1704           2 :       seg0 = ls_param->sr_prefix;
    1705           2 :       src0 = hdr0->ip6.src_address;
    1706           2 :       dst0 = hdr0->ip6.dst_address;
    1707             : 
    1708           2 :       gtpu_type = hdr0->gtpu.type;
    1709             : 
    1710           2 :       teid = hdr0->gtpu.teid;
    1711           2 :       teidp = (u8 *) &teid;
    1712             : 
    1713           2 :       seqp = (u8 *) &seq;
    1714             : 
    1715           2 :       if (hdr0->gtpu.ver_flags & (GTPU_EXTHDR_FLAG | GTPU_SEQ_FLAG))
    1716             :         {
    1717             :           // Extention header.
    1718           0 :           hdrlen += sizeof (gtpu_exthdr_t);
    1719             : 
    1720           0 :           seq = hdr0->gtpu.ext->seq;
    1721             : 
    1722           0 :           if (hdr0->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
    1723             :             {
    1724             :               // PDU Session Container.
    1725           0 :               sess = (gtpu_pdu_session_t *) (((char *) hdr0) +
    1726             :                                              sizeof (ip6_gtpu_header_t) +
    1727             :                                              sizeof (gtpu_exthdr_t));
    1728           0 :               qfi = sess->u.val & ~GTPU_PDU_SESSION_P_BIT_MASK;
    1729           0 :               qfip = (u8 *) &qfi;
    1730             : 
    1731           0 :               hdrlen += sizeof (gtpu_pdu_session_t);
    1732             : 
    1733           0 :               if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
    1734             :                 {
    1735           0 :                   hdrlen += sizeof (gtpu_paging_policy_t);
    1736             :                 }
    1737             :             }
    1738             :         }
    1739             : 
    1740           2 :       offset = ls_param->sr_prefixlen / 8;
    1741           2 :       shift = ls_param->sr_prefixlen % 8;
    1742             : 
    1743           2 :       if (PREDICT_TRUE (shift == 0))
    1744             :         {
    1745           2 :           if (qfip)
    1746             :             {
    1747           0 :               qfi = ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
    1748           0 :                     ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
    1749             : 
    1750           0 :               if (sess->type)
    1751             :                 {
    1752           0 :                   qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
    1753             :                 }
    1754             : 
    1755           0 :               seg0.as_u8[offset] = qfi;
    1756             :             }
    1757             : 
    1758           2 :           if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
    1759           2 :               gtpu_type == GTPU_TYPE_ECHO_REPLY ||
    1760             :               gtpu_type == GTPU_TYPE_ERROR_INDICATION)
    1761             :             {
    1762           0 :               clib_memcpy_fast (&seg0.as_u8[offset + 1], seqp, 2);
    1763             :             }
    1764             :           else
    1765             :             {
    1766           2 :               clib_memcpy_fast (&seg0.as_u8[offset + 1], teidp, 4);
    1767             :             }
    1768             :         }
    1769             :       else
    1770             :         {
    1771             :           int idx;
    1772             : 
    1773           0 :           if (qfip)
    1774             :             {
    1775           0 :               qfi = ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
    1776           0 :                     ((qfi & ~GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
    1777             : 
    1778           0 :               if (sess->type)
    1779             :                 {
    1780           0 :                   qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
    1781             :                 }
    1782             : 
    1783           0 :               seg0.as_u8[offset] |= qfi >> shift;
    1784           0 :               seg0.as_u8[offset + 1] |= qfi << (8 - shift);
    1785             :             }
    1786             : 
    1787           0 :           if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
    1788           0 :               gtpu_type == GTPU_TYPE_ECHO_REPLY ||
    1789             :               gtpu_type == GTPU_TYPE_ERROR_INDICATION)
    1790             :             {
    1791           0 :               for (idx = 0; idx < 2; idx++)
    1792             :                 {
    1793           0 :                   seg0.as_u8[offset + idx + 1] |= seqp[idx] >> shift;
    1794           0 :                   seg0.as_u8[offset + idx + 2] |= seqp[idx] << (8 - shift);
    1795             :                 }
    1796             :             }
    1797             :           else
    1798             :             {
    1799           0 :               for (idx = 0; idx < 4; idx++)
    1800             :                 {
    1801           0 :                   seg0.as_u8[offset + idx + 1] |= teidp[idx] >> shift;
    1802           0 :                   seg0.as_u8[offset + idx + 2] |= teidp[idx] << (8 - shift);
    1803             :                 }
    1804             :             }
    1805             :         }
    1806             : 
    1807           2 :       if (PREDICT_FALSE (gtpu_type == GTPU_TYPE_ERROR_INDICATION))
    1808             :         {
    1809             :           u16 payload_len;
    1810             : 
    1811           0 :           payload_len = clib_net_to_host_u16 (hdr0->gtpu.length);
    1812           0 :           if (payload_len != 0)
    1813             :             {
    1814           0 :               ie_size = payload_len - (hdrlen - sizeof (ip6_gtpu_header_t));
    1815           0 :               if (ie_size > 0)
    1816             :                 {
    1817             :                   u8 *ies;
    1818             : 
    1819           0 :                   ies = (u8 *) ((u8 *) hdr0 + hdrlen);
    1820           0 :                   clib_memcpy_fast (ie_buf, ies, ie_size);
    1821           0 :                   hdrlen += ie_size;
    1822             :                 }
    1823             :             }
    1824             :         }
    1825             : 
    1826             :       // jump over variable length data
    1827           2 :       vlib_buffer_advance (b0, (word) hdrlen);
    1828             : 
    1829             :       // get length of encapsulated IPv6 packet (the remaining part)
    1830           2 :       len0 = vlib_buffer_length_in_chain (vm, b0);
    1831             : 
    1832           2 :       if (PREDICT_TRUE (gtpu_type == GTPU_TYPE_GTPU))
    1833             :         {
    1834           2 :           encap = vlib_buffer_get_current (b0);
    1835             :         }
    1836             : 
    1837             :       uword *p;
    1838             :       ip6srv_combo_header_t *ip6srv;
    1839           2 :       ip6_sr_policy_t *sr_policy = NULL;
    1840           2 :       ip6_sr_sl_t *sl = NULL;
    1841             :       u32 *sl_index;
    1842             :       u32 hdr_len;
    1843             : 
    1844           2 :       p = mhash_get (&sm2->sr_policies_index_hash, &ls_param->sr_prefix);
    1845           2 :       if (p)
    1846             :         {
    1847           2 :           sr_policy = pool_elt_at_index (sm2->sr_policies, p[0]);
    1848             :         }
    1849             : 
    1850           2 :       if (sr_policy)
    1851             :         {
    1852           2 :           vec_foreach (sl_index, sr_policy->segments_lists)
    1853             :             {
    1854           2 :               sl = pool_elt_at_index (sm2->sid_lists, *sl_index);
    1855           2 :               if (sl != NULL)
    1856           2 :                 break;
    1857             :             }
    1858             :         }
    1859             : 
    1860           2 :       if (sl)
    1861             :         {
    1862           2 :           hdr_len = sizeof (ip6srv_combo_header_t);
    1863           2 :           hdr_len += vec_len (sl->segments) * sizeof (ip6_address_t);
    1864           2 :           hdr_len += sizeof (ip6_address_t) * 2;
    1865             :         }
    1866             :       else
    1867             :         {
    1868           0 :           hdr_len = sizeof (ip6_header_t);
    1869           0 :           hdr_len += sizeof (ip6_sr_header_t);
    1870           0 :           hdr_len += sizeof (ip6_address_t) * 2;
    1871             :         }
    1872             : 
    1873           2 :       if (ie_size)
    1874             :         {
    1875           0 :           tlv_siz =
    1876           0 :             sizeof (ip6_sr_tlv_t) + sizeof (user_plane_sub_tlv_t) + ie_size;
    1877             : 
    1878           0 :           tlv_siz = (tlv_siz & ~0x07) + (tlv_siz & 0x07 ? 0x08 : 0x0);
    1879           0 :           hdr_len += tlv_siz;
    1880             :         }
    1881             : 
    1882             :       // jump back to data[0] or pre_data if required
    1883           2 :       vlib_buffer_advance (b0, -(word) hdr_len);
    1884             : 
    1885           2 :       ip6srv = vlib_buffer_get_current (b0);
    1886             : 
    1887           2 :       if (sl)
    1888             :         {
    1889           2 :           clib_memcpy_fast (ip6srv, sl->rewrite, vec_len (sl->rewrite));
    1890             : 
    1891           2 :           if (vec_len (sl->segments) > 1)
    1892             :             {
    1893           2 :               ip6srv->ip.src_address = src0;
    1894             : 
    1895           2 :               ip6srv->sr.tag = clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
    1896             : 
    1897           2 :               ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
    1898           2 :               ip6srv->sr.segments_left += 2;
    1899           2 :               ip6srv->sr.last_entry += 2;
    1900             : 
    1901           2 :               ip6srv->sr.length += (sizeof (ip6_address_t) * 2) / 8;
    1902           2 :               ip6srv->sr.segments[0] = dst0;
    1903           2 :               ip6srv->sr.segments[1] = seg0;
    1904             : 
    1905           0 :               clib_memcpy_fast (&ip6srv->sr.segments[2],
    1906           2 :                                 (u8 *) (sl->rewrite + sizeof (ip6_header_t) +
    1907             :                                         sizeof (ip6_sr_header_t)),
    1908           2 :                                 vec_len (sl->segments) *
    1909             :                                   sizeof (ip6_address_t));
    1910             :             }
    1911             :           else
    1912             :             {
    1913           0 :               ip6srv->ip.src_address = src0;
    1914           0 :               ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
    1915             : 
    1916           0 :               ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
    1917           0 :               ip6srv->sr.segments_left = 2;
    1918           0 :               ip6srv->sr.last_entry = 1;
    1919           0 :               ip6srv->sr.length = (sizeof (ip6_address_t) * 2) / 8;
    1920           0 :               ip6srv->sr.flags = 0;
    1921             : 
    1922           0 :               ip6srv->sr.tag = clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
    1923             : 
    1924           0 :               ip6srv->sr.segments[0] = dst0;
    1925           0 :               ip6srv->sr.segments[1] = seg0;
    1926             : 
    1927           0 :               if (vec_len (sl->segments))
    1928             :                 {
    1929           0 :                   ip6srv->sr.segments[2] = sl->segments[0];
    1930           0 :                   ip6srv->sr.last_entry++;
    1931           0 :                   ip6srv->sr.length += sizeof (ip6_address_t) / 8;
    1932             :                 }
    1933             :             }
    1934             : 
    1935           2 :           if (PREDICT_TRUE (encap != NULL))
    1936             :             {
    1937           2 :               if (ls_param->nhtype == SRV6_NHTYPE_NONE)
    1938             :                 {
    1939           2 :                   if ((clib_net_to_host_u32 (
    1940           2 :                          encap->ip_version_traffic_class_and_flow_label) >>
    1941             :                        28) == 6)
    1942           2 :                     ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
    1943             :                   else
    1944           0 :                     ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
    1945             :                 }
    1946           0 :               else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
    1947             :                 {
    1948           0 :                   ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
    1949           0 :                   if ((clib_net_to_host_u32 (
    1950           0 :                          encap->ip_version_traffic_class_and_flow_label) >>
    1951             :                        28) != 4)
    1952             :                     {
    1953             :                       // Bad encap packet.
    1954           0 :                       next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
    1955           0 :                       goto DONE;
    1956             :                     }
    1957             :                 }
    1958           0 :               else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
    1959             :                 {
    1960           0 :                   ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
    1961           0 :                   if ((clib_net_to_host_u32 (
    1962           0 :                          encap->ip_version_traffic_class_and_flow_label) >>
    1963             :                        28) != 6)
    1964             :                     {
    1965             :                       // Bad encap packet.
    1966           0 :                       next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
    1967           0 :                       goto DONE;
    1968             :                     }
    1969             :                 }
    1970           0 :               else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
    1971             :                 {
    1972           0 :                   ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
    1973             :                 }
    1974             :             }
    1975             :           else
    1976             :             {
    1977           0 :               ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
    1978             :             }
    1979             :         }
    1980             :       else
    1981             :         {
    1982           0 :           clib_memcpy_fast (ip6srv, &sm->cache_hdr, sizeof (ip6_header_t));
    1983             : 
    1984           0 :           ip6srv->ip.src_address = src0;
    1985           0 :           ip6srv->ip.dst_address = seg0;
    1986             : 
    1987           0 :           ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
    1988             : 
    1989           0 :           ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
    1990           0 :           ip6srv->sr.segments_left = 1;
    1991           0 :           ip6srv->sr.last_entry = 1;
    1992             : 
    1993           0 :           ip6srv->sr.length = (sizeof (ip6_address_t) * 2) / 8;
    1994           0 :           ip6srv->sr.segments[0] = dst0;
    1995           0 :           ip6srv->sr.segments[1] = seg0;
    1996             : 
    1997           0 :           if (PREDICT_FALSE (gtpu_type) != GTPU_TYPE_GTPU)
    1998             :             {
    1999           0 :               ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
    2000           0 :               ip6srv->sr.tag = clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
    2001             :             }
    2002             :           else
    2003             :             {
    2004           0 :               if (ls_param->nhtype == SRV6_NHTYPE_NONE)
    2005             :                 {
    2006           0 :                   if ((clib_net_to_host_u32 (
    2007           0 :                          encap->ip_version_traffic_class_and_flow_label) >>
    2008             :                        28) != 6)
    2009           0 :                     ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
    2010             :                 }
    2011           0 :               else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
    2012             :                 {
    2013           0 :                   ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
    2014           0 :                   if ((clib_net_to_host_u32 (
    2015           0 :                          encap->ip_version_traffic_class_and_flow_label) >>
    2016             :                        28) != 4)
    2017             :                     {
    2018             :                       // Bad encap packet.
    2019           0 :                       next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
    2020           0 :                       goto DONE;
    2021             :                     }
    2022             :                 }
    2023           0 :               else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
    2024             :                 {
    2025           0 :                   ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
    2026           0 :                   if ((clib_net_to_host_u32 (
    2027           0 :                          encap->ip_version_traffic_class_and_flow_label) >>
    2028             :                        28) != 6)
    2029             :                     {
    2030             :                       // Bad encap packet.
    2031           0 :                       next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
    2032           0 :                       goto DONE;
    2033             :                     }
    2034             :                 }
    2035           0 :               else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
    2036             :                 {
    2037           0 :                   ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
    2038             :                 }
    2039             :             }
    2040             :         }
    2041             : 
    2042           2 :       if (PREDICT_FALSE (ie_size))
    2043             :         {
    2044             :           ip6_sr_tlv_t *tlv;
    2045             :           user_plane_sub_tlv_t *sub_tlv;
    2046             : 
    2047           0 :           tlv = (ip6_sr_tlv_t *) ((u8 *) ip6srv + (hdr_len - tlv_siz));
    2048           0 :           tlv->type = SRH_TLV_USER_PLANE_CONTAINER;
    2049           0 :           tlv->length = (u8) (tlv_siz - sizeof (ip6_sr_tlv_t));
    2050           0 :           clib_memset (tlv->value, 0, tlv->length);
    2051             : 
    2052           0 :           sub_tlv = (user_plane_sub_tlv_t *) tlv->value;
    2053           0 :           sub_tlv->type = USER_PLANE_SUB_TLV_IE;
    2054           0 :           sub_tlv->length = (u8) ie_size;
    2055           0 :           clib_memcpy_fast (sub_tlv->value, ie_buf, ie_size);
    2056             : 
    2057           0 :           ip6srv->sr.length += (u8) (tlv_siz / 8);
    2058             :         }
    2059             : 
    2060           2 :       ip6srv->ip.payload_length =
    2061           2 :         clib_host_to_net_u16 (len0 + hdr_len - sizeof (ip6_header_t));
    2062             : 
    2063           2 :       vnet_buffer (b0)->sw_if_index[VLIB_TX] = 0; /* default FIB */
    2064             : 
    2065           2 :       if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
    2066           2 :           PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
    2067             :         {
    2068             :           srv6_end_rewrite_trace_t *tr =
    2069           2 :             vlib_add_trace (vm, node, b0, sizeof (*tr));
    2070           2 :           clib_memcpy (tr->src.as_u8, ip6srv->ip.src_address.as_u8,
    2071             :                        sizeof (ip6_address_t));
    2072           2 :           clib_memcpy (tr->dst.as_u8, ip6srv->ip.dst_address.as_u8,
    2073             :                        sizeof (ip6_address_t));
    2074           2 :           tr->teid = teid;
    2075           2 :           clib_memcpy (tr->sr_prefix.as_u8, ls_param->sr_prefix.as_u8,
    2076             :                        sizeof (ip6_address_t));
    2077           2 :           tr->sr_prefixlen = ls_param->sr_prefixlen;
    2078             :         }
    2079             :     }
    2080             : 
    2081           0 : DONE:
    2082           2 :   return next0;
    2083             : }
    2084             : 
    2085         576 : VLIB_NODE_FN (srv6_end_m_gtp6_d)
    2086             : (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
    2087             : {
    2088           1 :   srv6_end_main_v6_decap_t *sm = &srv6_end_main_v6_decap;
    2089           1 :   ip6_sr_main_t *sm2 = &sr_main;
    2090             :   u32 n_left_from, next_index, *from, *to_next;
    2091           1 :   u32 thread_index = vm->thread_index;
    2092             :   ip6_sr_localsid_t *ls0;
    2093             :   srv6_end_gtp6_d_param_t *ls_param;
    2094             : 
    2095           1 :   u32 good_n = 0, bad_n = 0;
    2096             : 
    2097           1 :   from = vlib_frame_vector_args (frame);
    2098           1 :   n_left_from = frame->n_vectors;
    2099           1 :   next_index = node->cached_next_index;
    2100             : 
    2101           2 :   while (n_left_from > 0)
    2102             :     {
    2103             :       u32 n_left_to_next;
    2104             : 
    2105           1 :       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
    2106             : 
    2107           3 :       while (n_left_from > 0 && n_left_to_next > 0)
    2108             :         {
    2109             :           u32 bi0;
    2110             :           vlib_buffer_t *b0;
    2111             : 
    2112             :           u32 next0;
    2113             : 
    2114             :           ip6_gtpu_header_t *hdr;
    2115             :           u32 hdrlen;
    2116             :           u8 gtpu_type;
    2117             :           bool gtp6;
    2118             :           bool ipv4;
    2119             : 
    2120             :           // defaults
    2121           2 :           bi0 = from[0];
    2122           2 :           to_next[0] = bi0;
    2123           2 :           from += 1;
    2124           2 :           to_next += 1;
    2125           2 :           n_left_from -= 1;
    2126           2 :           n_left_to_next -= 1;
    2127             : 
    2128           2 :           b0 = vlib_get_buffer (vm, bi0);
    2129             : 
    2130           2 :           ls0 = pool_elt_at_index (sm2->localsids,
    2131             :                                    vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
    2132             : 
    2133           2 :           ls_param = (srv6_end_gtp6_d_param_t *) ls0->plugin_mem;
    2134             : 
    2135           2 :           hdr = vlib_buffer_get_current (b0);
    2136           2 :           gtpu_type = hdr->gtpu.type;
    2137             : 
    2138           2 :           gtp6 = false;
    2139           2 :           ipv4 = true;
    2140             : 
    2141           2 :           if (PREDICT_FALSE (gtpu_type != GTPU_TYPE_GTPU || ls_param->drop_in))
    2142             :             {
    2143           2 :               gtp6 = true;
    2144             :             }
    2145             :           else
    2146             :             {
    2147             :               ip6_header_t *ip6;
    2148             : 
    2149           0 :               hdrlen = sizeof (ip6_gtpu_header_t);
    2150             : 
    2151           0 :               if (hdr->gtpu.ver_flags & (GTPU_EXTHDR_FLAG | GTPU_SEQ_FLAG))
    2152             :                 {
    2153           0 :                   hdrlen += sizeof (gtpu_exthdr_t);
    2154           0 :                   if (hdr->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
    2155             :                     {
    2156             :                       gtpu_pdu_session_t *sess;
    2157           0 :                       sess = (gtpu_pdu_session_t *) (((char *) hdr) + hdrlen);
    2158           0 :                       hdrlen += sizeof (gtpu_pdu_session_t);
    2159             : 
    2160           0 :                       if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
    2161             :                         {
    2162           0 :                           hdrlen += sizeof (gtpu_paging_policy_t);
    2163             :                         }
    2164             :                     }
    2165             :                 }
    2166             : 
    2167           0 :               ip6 = (ip6_header_t *) (((char *) hdr) + hdrlen);
    2168           0 :               if ((clib_net_to_host_u32 (
    2169           0 :                      ip6->ip_version_traffic_class_and_flow_label) >>
    2170             :                    28) == 6)
    2171             :                 {
    2172           0 :                   ipv4 = false;
    2173           0 :                   if (((ip6->dst_address.as_u8[0] == 0xff) &&
    2174           0 :                        (ip6->dst_address.as_u8[1] == 0x02)) ||
    2175           0 :                       ((ip6->dst_address.as_u8[0] == 0xfe) &&
    2176           0 :                        ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80)))
    2177             :                     {
    2178             :                       // Inner desitnation is IPv6 link local
    2179           0 :                       gtp6 = true;
    2180             :                     }
    2181             :                 }
    2182             :             }
    2183             : 
    2184           2 :           if (gtp6)
    2185             :             {
    2186           2 :               next0 = srv6_gtp6_decap_processing (vm, node, b0);
    2187           2 :               if (PREDICT_TRUE (next0 == SRV6_END_M_GTP6_D_NEXT_LOOKUP6))
    2188           2 :                 good_n++;
    2189             :               else
    2190           0 :                 bad_n++;
    2191             : 
    2192           4 :               vlib_increment_combined_counter (
    2193             :                 ((next0 == SRV6_END_M_GTP6_D_NEXT_DROP) ?
    2194             :                    &(sm2->sr_ls_invalid_counters) :
    2195             :                    &(sm2->sr_ls_valid_counters)),
    2196           2 :                 thread_index, ls0 - sm2->localsids, 1,
    2197             :                 vlib_buffer_length_in_chain (vm, b0));
    2198             :             }
    2199             :           else
    2200             :             {
    2201             :               /* Strip off the outer header (IPv6 + GTP + UDP + IEs) */
    2202           0 :               vlib_buffer_advance (b0, (word) hdrlen);
    2203             : 
    2204           0 :               if (ipv4)
    2205             :                 {
    2206           0 :                   next0 = SRV6_END_M_GTP6_D_NEXT_LOOKUP4;
    2207           0 :                   vnet_buffer (b0)->sw_if_index[VLIB_TX] =
    2208           0 :                     ls_param->fib4_index;
    2209             :                 }
    2210             :               else
    2211             :                 {
    2212           0 :                   next0 = SRV6_END_M_GTP6_D_NEXT_LOOKUP6;
    2213           0 :                   vnet_buffer (b0)->sw_if_index[VLIB_TX] =
    2214           0 :                     ls_param->fib6_index;
    2215             :                 }
    2216             :             }
    2217             : 
    2218           2 :           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
    2219             :                                            n_left_to_next, bi0, next0);
    2220             :         }
    2221             : 
    2222           1 :       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
    2223             :     }
    2224             : 
    2225           1 :   vlib_node_increment_counter (vm, sm->end_m_gtp6_d_node_index,
    2226             :                                SRV6_END_ERROR_M_GTP6_D_BAD_PACKETS, bad_n);
    2227             : 
    2228           1 :   vlib_node_increment_counter (vm, sm->end_m_gtp6_d_node_index,
    2229             :                                SRV6_END_ERROR_M_GTP6_D_PACKETS, good_n);
    2230             : 
    2231           1 :   return frame->n_vectors;
    2232             : }
    2233             : 
    2234             : // Function for SRv6 GTP6.D.DI function
    2235         575 : VLIB_NODE_FN (srv6_end_m_gtp6_d_di)
    2236             : (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
    2237             : {
    2238           0 :   srv6_end_main_v6_decap_di_t *sm = &srv6_end_main_v6_decap_di;
    2239           0 :   ip6_sr_main_t *sm2 = &sr_main;
    2240             :   u32 n_left_from, next_index, *from, *to_next;
    2241           0 :   u32 thread_index = vm->thread_index;
    2242             :   srv6_end_gtp6_d_param_t *ls_param;
    2243             : 
    2244           0 :   u32 good_n = 0, bad_n = 0;
    2245             : 
    2246           0 :   from = vlib_frame_vector_args (frame);
    2247           0 :   n_left_from = frame->n_vectors;
    2248           0 :   next_index = node->cached_next_index;
    2249             : 
    2250           0 :   while (n_left_from > 0)
    2251             :     {
    2252             :       u32 n_left_to_next;
    2253             : 
    2254           0 :       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
    2255             : 
    2256           0 :       while (n_left_from > 0 && n_left_to_next > 0)
    2257             :         {
    2258             :           u32 bi0;
    2259             :           vlib_buffer_t *b0;
    2260             :           ip6_sr_localsid_t *ls0;
    2261             : 
    2262           0 :           ip6_gtpu_header_t *hdr0 = NULL;
    2263             :           uword len0;
    2264             : 
    2265             :           ip6_address_t dst0;
    2266             :           ip6_address_t src0;
    2267             :           ip6_address_t seg0;
    2268           0 :           u32 teid = 0;
    2269             :           u8 *teidp;
    2270           0 :           u8 gtpu_type = 0;
    2271           0 :           u8 qfi = 0;
    2272           0 :           u8 *qfip = NULL;
    2273           0 :           u16 seq = 0;
    2274             :           u8 *seqp;
    2275             :           u32 offset, shift;
    2276             :           u32 hdrlen;
    2277           0 :           ip6_header_t *encap = NULL;
    2278             :           gtpu_pdu_session_t *sess;
    2279           0 :           int ie_size = 0;
    2280           0 :           u16 tlv_siz = 0;
    2281             :           u8 ie_buf[GTPU_IE_MAX_SIZ];
    2282             : 
    2283           0 :           u32 next0 = SRV6_END_M_GTP6_D_DI_NEXT_LOOKUP;
    2284             : 
    2285             :           // defaults
    2286           0 :           bi0 = from[0];
    2287           0 :           to_next[0] = bi0;
    2288           0 :           from += 1;
    2289           0 :           to_next += 1;
    2290           0 :           n_left_from -= 1;
    2291           0 :           n_left_to_next -= 1;
    2292             : 
    2293           0 :           b0 = vlib_get_buffer (vm, bi0);
    2294           0 :           ls0 = pool_elt_at_index (sm2->localsids,
    2295             :                                    vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
    2296             : 
    2297           0 :           ls_param = (srv6_end_gtp6_d_param_t *) ls0->plugin_mem;
    2298             : 
    2299           0 :           hdr0 = vlib_buffer_get_current (b0);
    2300             : 
    2301           0 :           hdrlen = sizeof (ip6_gtpu_header_t);
    2302             : 
    2303           0 :           len0 = vlib_buffer_length_in_chain (vm, b0);
    2304             : 
    2305           0 :           if ((hdr0->ip6.protocol != IP_PROTOCOL_UDP) ||
    2306           0 :               (hdr0->udp.dst_port !=
    2307           0 :                clib_host_to_net_u16 (SRV6_GTP_UDP_DST_PORT)) ||
    2308             :               (len0 < sizeof (ip6_gtpu_header_t)))
    2309             :             {
    2310           0 :               next0 = SRV6_END_M_GTP6_D_DI_NEXT_DROP;
    2311             : 
    2312           0 :               bad_n++;
    2313             :             }
    2314             :           else
    2315             :             {
    2316           0 :               dst0 = hdr0->ip6.dst_address;
    2317           0 :               src0 = hdr0->ip6.src_address;
    2318             : 
    2319           0 :               gtpu_type = hdr0->gtpu.type;
    2320             : 
    2321           0 :               seg0 = ls_param->sr_prefix;
    2322           0 :               teid = hdr0->gtpu.teid;
    2323           0 :               teidp = (u8 *) &teid;
    2324             : 
    2325           0 :               seqp = (u8 *) &seq;
    2326             : 
    2327           0 :               if (hdr0->gtpu.ver_flags & (GTPU_EXTHDR_FLAG | GTPU_SEQ_FLAG))
    2328             :                 {
    2329             :                   // Extention header.
    2330           0 :                   hdrlen += sizeof (gtpu_exthdr_t);
    2331             : 
    2332           0 :                   seq = hdr0->gtpu.ext->seq;
    2333             : 
    2334           0 :                   if (hdr0->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
    2335             :                     {
    2336             :                       // PDU Session Container.
    2337           0 :                       sess = (gtpu_pdu_session_t *) (((char *) hdr0) + hdrlen);
    2338           0 :                       qfi = sess->u.val & ~GTPU_PDU_SESSION_P_BIT_MASK;
    2339           0 :                       qfip = &qfi;
    2340             : 
    2341           0 :                       hdrlen += sizeof (gtpu_pdu_session_t);
    2342             : 
    2343           0 :                       if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
    2344             :                         {
    2345           0 :                           hdrlen += sizeof (gtpu_paging_policy_t);
    2346             :                         }
    2347             :                     }
    2348             :                 }
    2349             : 
    2350           0 :               offset = ls_param->sr_prefixlen / 8;
    2351           0 :               shift = ls_param->sr_prefixlen % 8;
    2352             : 
    2353           0 :               offset += 1;
    2354           0 :               if (PREDICT_TRUE (shift == 0))
    2355             :                 {
    2356           0 :                   if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
    2357           0 :                       gtpu_type == GTPU_TYPE_ECHO_REPLY ||
    2358             :                       gtpu_type == GTPU_TYPE_ERROR_INDICATION)
    2359             :                     {
    2360           0 :                       clib_memcpy_fast (&seg0.as_u8[offset], seqp, 2);
    2361             :                     }
    2362             :                   else
    2363             :                     {
    2364           0 :                       clib_memcpy_fast (&seg0.as_u8[offset], teidp, 4);
    2365             :                     }
    2366             : 
    2367           0 :                   if (qfip)
    2368             :                     {
    2369           0 :                       qfi = ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
    2370           0 :                             ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
    2371             : 
    2372           0 :                       if (sess->type)
    2373             :                         {
    2374           0 :                           qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
    2375             :                         }
    2376             : 
    2377           0 :                       seg0.as_u8[offset + 4] = qfi;
    2378             :                     }
    2379             :                 }
    2380             :               else
    2381             :                 {
    2382             :                   int idx;
    2383             : 
    2384           0 :                   if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
    2385           0 :                       gtpu_type == GTPU_TYPE_ECHO_REPLY ||
    2386             :                       gtpu_type == GTPU_TYPE_ERROR_INDICATION)
    2387             :                     {
    2388           0 :                       for (idx = 0; idx < 2; idx++)
    2389             :                         {
    2390           0 :                           seg0.as_u8[offset + idx] |= seqp[idx] >> shift;
    2391           0 :                           seg0.as_u8[offset + idx + 1] |= seqp[idx]
    2392           0 :                                                           << (8 - shift);
    2393             :                         }
    2394             :                     }
    2395             :                   else
    2396             :                     {
    2397           0 :                       for (idx = 0; idx < 4; idx++)
    2398             :                         {
    2399           0 :                           seg0.as_u8[offset + idx] |= teidp[idx] >> shift;
    2400           0 :                           seg0.as_u8[offset + idx + 1] |= teidp[idx]
    2401           0 :                                                           << (8 - shift);
    2402             :                         }
    2403             :                     }
    2404             : 
    2405           0 :                   if (qfip)
    2406             :                     {
    2407           0 :                       qfi = ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
    2408           0 :                             ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
    2409             : 
    2410           0 :                       if (sess->type)
    2411             :                         {
    2412           0 :                           qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
    2413             :                         }
    2414             : 
    2415           0 :                       seg0.as_u8[offset + 4] |= qfi >> shift;
    2416           0 :                       seg0.as_u8[offset + 5] |= qfi << (8 - shift);
    2417             :                     }
    2418             :                 }
    2419             : 
    2420           0 :               if (PREDICT_FALSE (gtpu_type == GTPU_TYPE_ERROR_INDICATION))
    2421             :                 {
    2422             :                   u16 payload_len;
    2423             : 
    2424           0 :                   payload_len = clib_net_to_host_u16 (hdr0->gtpu.length);
    2425           0 :                   if (payload_len != 0)
    2426             :                     {
    2427           0 :                       ie_size =
    2428           0 :                         payload_len - (hdrlen - sizeof (ip6_gtpu_header_t));
    2429           0 :                       if (ie_size > 0)
    2430             :                         {
    2431             :                           u8 *ies;
    2432             : 
    2433           0 :                           ies = (u8 *) ((u8 *) hdr0 + hdrlen);
    2434           0 :                           clib_memcpy_fast (ie_buf, ies, ie_size);
    2435           0 :                           hdrlen += ie_size;
    2436             :                         }
    2437             :                     }
    2438             :                 }
    2439             : 
    2440             :               // jump over variable length data
    2441           0 :               vlib_buffer_advance (b0, (word) hdrlen);
    2442             : 
    2443             :               // get length of encapsulated IPv6 packet (the remaining part)
    2444           0 :               len0 = vlib_buffer_length_in_chain (vm, b0);
    2445             : 
    2446           0 :               if (PREDICT_TRUE (gtpu_type == GTPU_TYPE_GTPU))
    2447             :                 {
    2448           0 :                   encap = vlib_buffer_get_current (b0);
    2449             :                 }
    2450             : 
    2451             :               uword *p;
    2452             :               ip6srv_combo_header_t *ip6srv;
    2453           0 :               ip6_sr_policy_t *sr_policy = NULL;
    2454           0 :               ip6_sr_sl_t *sl = NULL;
    2455             :               u32 *sl_index;
    2456             :               u32 hdr_len;
    2457             : 
    2458             :               p =
    2459           0 :                 mhash_get (&sm2->sr_policies_index_hash, &ls_param->sr_prefix);
    2460           0 :               if (p)
    2461             :                 {
    2462           0 :                   sr_policy = pool_elt_at_index (sm2->sr_policies, p[0]);
    2463             :                 }
    2464             : 
    2465           0 :               if (sr_policy)
    2466             :                 {
    2467           0 :                   vec_foreach (sl_index, sr_policy->segments_lists)
    2468             :                     {
    2469           0 :                       sl = pool_elt_at_index (sm2->sid_lists, *sl_index);
    2470           0 :                       if (sl != NULL)
    2471           0 :                         break;
    2472             :                     }
    2473             :                 }
    2474             : 
    2475           0 :               hdr_len = sizeof (ip6srv_combo_header_t);
    2476             : 
    2477           0 :               if (sl)
    2478           0 :                 hdr_len += vec_len (sl->segments) * sizeof (ip6_address_t);
    2479             : 
    2480           0 :               hdr_len += sizeof (ip6_address_t) * 2;
    2481             : 
    2482           0 :               if (ie_size)
    2483             :                 {
    2484           0 :                   tlv_siz = sizeof (ip6_sr_tlv_t) +
    2485           0 :                             sizeof (user_plane_sub_tlv_t) + ie_size;
    2486             : 
    2487           0 :                   tlv_siz = (tlv_siz & ~0x07) + (tlv_siz & 0x07 ? 0x08 : 0x0);
    2488           0 :                   hdr_len += tlv_siz;
    2489             :                 }
    2490             : 
    2491             :               // jump back to data[0] or pre_data if required
    2492           0 :               vlib_buffer_advance (b0, -(word) hdr_len);
    2493             : 
    2494           0 :               ip6srv = vlib_buffer_get_current (b0);
    2495             : 
    2496           0 :               if (sl)
    2497             :                 {
    2498           0 :                   clib_memcpy_fast (ip6srv, sl->rewrite,
    2499           0 :                                     vec_len (sl->rewrite));
    2500             : 
    2501           0 :                   if (vec_len (sl->segments) > 1)
    2502             :                     {
    2503           0 :                       ip6srv->ip.src_address = src0;
    2504             : 
    2505           0 :                       ip6srv->sr.tag =
    2506           0 :                         clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
    2507             : 
    2508           0 :                       ip6srv->sr.segments_left += 2;
    2509           0 :                       ip6srv->sr.last_entry += 2;
    2510             : 
    2511           0 :                       ip6srv->sr.length += ((sizeof (ip6_address_t) * 2) / 8);
    2512             : 
    2513           0 :                       ip6srv->sr.segments[0] = dst0;
    2514           0 :                       ip6srv->sr.segments[1] = seg0;
    2515             : 
    2516           0 :                       clib_memcpy_fast (
    2517           0 :                         &ip6srv->sr.segments[2],
    2518           0 :                         (u8 *) (sl->rewrite + sizeof (ip6_header_t) +
    2519             :                                 sizeof (ip6_sr_header_t)),
    2520           0 :                         vec_len (sl->segments) * sizeof (ip6_address_t));
    2521             :                     }
    2522             :                   else
    2523             :                     {
    2524           0 :                       ip6srv->ip.src_address = src0;
    2525           0 :                       ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
    2526             : 
    2527           0 :                       ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
    2528           0 :                       ip6srv->sr.segments_left = 2;
    2529           0 :                       ip6srv->sr.last_entry = 1;
    2530           0 :                       ip6srv->sr.length = ((sizeof (ip6_sr_header_t) +
    2531             :                                             2 * sizeof (ip6_address_t)) /
    2532             :                                            8) -
    2533             :                                           1;
    2534           0 :                       ip6srv->sr.flags = 0;
    2535             : 
    2536           0 :                       ip6srv->sr.tag =
    2537           0 :                         clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
    2538             : 
    2539           0 :                       ip6srv->sr.segments[0] = dst0;
    2540           0 :                       ip6srv->sr.segments[1] = seg0;
    2541             : 
    2542           0 :                       if (vec_len (sl->segments))
    2543             :                         {
    2544           0 :                           ip6srv->sr.segments[2] = sl->segments[0];
    2545           0 :                           ip6srv->sr.last_entry++;
    2546           0 :                           ip6srv->sr.length += sizeof (ip6_address_t) / 8;
    2547             :                         }
    2548             :                     }
    2549             :                 }
    2550             :               else
    2551             :                 {
    2552           0 :                   clib_memcpy_fast (ip6srv, &sm->cache_hdr,
    2553             :                                     sizeof (ip6_header_t));
    2554             : 
    2555           0 :                   ip6srv->ip.src_address = src0;
    2556           0 :                   ip6srv->ip.dst_address = seg0;
    2557             : 
    2558           0 :                   ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
    2559           0 :                   ip6srv->sr.segments_left = 1;
    2560           0 :                   ip6srv->sr.last_entry = 0;
    2561           0 :                   ip6srv->sr.length =
    2562             :                     ((sizeof (ip6_sr_header_t) + sizeof (ip6_address_t)) / 8) -
    2563             :                     1;
    2564           0 :                   ip6srv->sr.flags = 0;
    2565             : 
    2566           0 :                   ip6srv->sr.tag =
    2567           0 :                     clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
    2568             : 
    2569           0 :                   ip6srv->sr.segments[0] = dst0;
    2570             :                 }
    2571             : 
    2572           0 :               if (PREDICT_FALSE (ie_size))
    2573             :                 {
    2574             :                   ip6_sr_tlv_t *tlv;
    2575             :                   user_plane_sub_tlv_t *sub_tlv;
    2576             : 
    2577           0 :                   tlv = (ip6_sr_tlv_t *) ((u8 *) ip6srv + (hdr_len - tlv_siz));
    2578           0 :                   tlv->type = SRH_TLV_USER_PLANE_CONTAINER;
    2579           0 :                   tlv->length = (u8) (tlv_siz - sizeof (ip6_sr_tlv_t));
    2580           0 :                   clib_memset (tlv->value, 0, tlv->length);
    2581             : 
    2582           0 :                   sub_tlv = (user_plane_sub_tlv_t *) tlv->value;
    2583           0 :                   sub_tlv->length = (u8) (ie_size);
    2584           0 :                   clib_memcpy_fast (sub_tlv->value, ie_buf, ie_size);
    2585             : 
    2586           0 :                   ip6srv->sr.length += (u8) (tlv_siz / 8);
    2587             :                 }
    2588             : 
    2589           0 :               ip6srv->ip.payload_length =
    2590           0 :                 clib_host_to_net_u16 (len0 + hdr_len - sizeof (ip6_header_t));
    2591           0 :               ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
    2592             : 
    2593           0 :               if (PREDICT_TRUE (encap != NULL))
    2594             :                 {
    2595           0 :                   if (ls_param->nhtype == SRV6_NHTYPE_NONE)
    2596             :                     {
    2597           0 :                       if ((clib_net_to_host_u32 (
    2598           0 :                              encap->ip_version_traffic_class_and_flow_label) >>
    2599             :                            28) == 6)
    2600           0 :                         ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
    2601             :                       else
    2602           0 :                         ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
    2603             :                     }
    2604           0 :                   else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
    2605             :                     {
    2606           0 :                       ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
    2607           0 :                       if ((clib_net_to_host_u32 (
    2608           0 :                              encap->ip_version_traffic_class_and_flow_label) >>
    2609             :                            28) != 4)
    2610             :                         {
    2611             :                           // Bad encap packet.
    2612           0 :                           next0 = SRV6_END_M_GTP6_D_DI_NEXT_DROP;
    2613           0 :                           bad_n++;
    2614           0 :                           goto DONE;
    2615             :                         }
    2616             :                     }
    2617           0 :                   else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
    2618             :                     {
    2619           0 :                       ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
    2620           0 :                       if ((clib_net_to_host_u32 (
    2621           0 :                              encap->ip_version_traffic_class_and_flow_label) >>
    2622             :                            28) != 6)
    2623             :                         {
    2624             :                           // Bad encap packet.
    2625           0 :                           next0 = SRV6_END_M_GTP6_D_DI_NEXT_DROP;
    2626           0 :                           bad_n++;
    2627           0 :                           goto DONE;
    2628             :                         }
    2629             :                     }
    2630           0 :                   else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
    2631             :                     {
    2632           0 :                       ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
    2633             :                     }
    2634             :                 }
    2635             :               else
    2636             :                 {
    2637           0 :                   ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
    2638             :                 }
    2639             : 
    2640           0 :               good_n++;
    2641             : 
    2642           0 :               if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
    2643           0 :                   PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
    2644             :                 {
    2645             :                   srv6_end_rewrite_trace_t *tr =
    2646           0 :                     vlib_add_trace (vm, node, b0, sizeof (*tr));
    2647           0 :                   clib_memcpy (tr->src.as_u8, ip6srv->ip.src_address.as_u8,
    2648             :                                sizeof (ip6_address_t));
    2649           0 :                   clib_memcpy (tr->dst.as_u8, ip6srv->ip.dst_address.as_u8,
    2650             :                                sizeof (ip6_address_t));
    2651           0 :                   tr->teid = teid;
    2652           0 :                   clib_memcpy (tr->sr_prefix.as_u8, ls_param->sr_prefix.as_u8,
    2653             :                                sizeof (ip6_address_t));
    2654           0 :                   tr->sr_prefixlen = ls_param->sr_prefixlen;
    2655             :                 }
    2656             :             }
    2657             : 
    2658           0 :         DONE:
    2659           0 :           vlib_increment_combined_counter (
    2660             :             ((next0 == SRV6_END_M_GTP6_D_DI_NEXT_DROP) ?
    2661             :                &(sm2->sr_ls_invalid_counters) :
    2662             :                &(sm2->sr_ls_valid_counters)),
    2663           0 :             thread_index, ls0 - sm2->localsids, 1,
    2664             :             vlib_buffer_length_in_chain (vm, b0));
    2665             : 
    2666           0 :           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
    2667             :                                            n_left_to_next, bi0, next0);
    2668             :         }
    2669             : 
    2670           0 :       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
    2671             :     }
    2672             : 
    2673           0 :   vlib_node_increment_counter (vm, sm->end_m_gtp6_d_di_node_index,
    2674             :                                SRV6_END_ERROR_M_GTP6_D_DI_BAD_PACKETS, bad_n);
    2675             : 
    2676           0 :   vlib_node_increment_counter (vm, sm->end_m_gtp6_d_di_node_index,
    2677             :                                SRV6_END_ERROR_M_GTP6_D_DI_PACKETS, good_n);
    2678             : 
    2679           0 :   return frame->n_vectors;
    2680             : }
    2681             : 
    2682             : // Function for SRv6 GTP6.DT function
    2683         575 : VLIB_NODE_FN (srv6_end_m_gtp6_dt)
    2684             : (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
    2685             : {
    2686           0 :   srv6_end_main_v6_dt_t *sm = &srv6_end_main_v6_dt;
    2687           0 :   ip6_sr_main_t *sm2 = &sr_main;
    2688             :   u32 n_left_from, next_index, *from, *to_next;
    2689           0 :   u32 thread_index = vm->thread_index;
    2690             : 
    2691           0 :   u32 good_n = 0, bad_n = 0;
    2692             : 
    2693           0 :   from = vlib_frame_vector_args (frame);
    2694           0 :   n_left_from = frame->n_vectors;
    2695           0 :   next_index = node->cached_next_index;
    2696             : 
    2697           0 :   while (n_left_from > 0)
    2698             :     {
    2699             :       u32 n_left_to_next;
    2700             : 
    2701           0 :       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
    2702             : 
    2703           0 :       while (n_left_from > 0 && n_left_to_next > 0)
    2704             :         {
    2705             :           u32 bi0;
    2706             :           vlib_buffer_t *b0;
    2707             :           srv6_end_gtp6_dt_param_t *ls_param;
    2708             :           ip6_sr_localsid_t *ls0;
    2709             : 
    2710           0 :           ip6_gtpu_header_t *hdr0 = NULL;
    2711           0 :           ip4_header_t *ip4 = NULL;
    2712           0 :           ip6_header_t *ip6 = NULL;
    2713             :           ip6_address_t src, dst;
    2714             :           u32 teid;
    2715             :           u32 hdrlen;
    2716             :           u32 len0;
    2717             : 
    2718           0 :           u32 next0 = SRV6_END_M_GTP6_DT_NEXT_DROP;
    2719             : 
    2720           0 :           bi0 = from[0];
    2721           0 :           to_next[0] = bi0;
    2722           0 :           from += 1;
    2723           0 :           to_next += 1;
    2724           0 :           n_left_from -= 1;
    2725           0 :           n_left_to_next -= 1;
    2726             : 
    2727           0 :           b0 = vlib_get_buffer (vm, bi0);
    2728           0 :           ls0 = pool_elt_at_index (sm2->localsids,
    2729             :                                    vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
    2730             : 
    2731           0 :           ls_param = (srv6_end_gtp6_dt_param_t *) ls0->plugin_mem;
    2732             : 
    2733           0 :           hdr0 = vlib_buffer_get_current (b0);
    2734             : 
    2735           0 :           hdrlen = sizeof (ip6_gtpu_header_t);
    2736             : 
    2737           0 :           len0 = vlib_buffer_length_in_chain (vm, b0);
    2738             : 
    2739           0 :           if ((hdr0->ip6.protocol != IP_PROTOCOL_UDP) ||
    2740           0 :               (hdr0->udp.dst_port !=
    2741           0 :                clib_host_to_net_u16 (SRV6_GTP_UDP_DST_PORT)) ||
    2742             :               (len0 < sizeof (ip6_gtpu_header_t)))
    2743             :             {
    2744           0 :               next0 = SRV6_END_M_GTP6_DT_NEXT_DROP;
    2745             : 
    2746           0 :               bad_n++;
    2747             :             }
    2748             :           else
    2749             :             {
    2750           0 :               clib_memcpy_fast (src.as_u8, hdr0->ip6.src_address.as_u8,
    2751             :                                 sizeof (ip6_address_t));
    2752           0 :               clib_memcpy_fast (dst.as_u8, hdr0->ip6.dst_address.as_u8,
    2753             :                                 sizeof (ip6_address_t));
    2754             : 
    2755           0 :               teid = hdr0->gtpu.teid;
    2756             : 
    2757           0 :               if (hdr0->gtpu.ver_flags & GTPU_EXTHDR_FLAG)
    2758             :                 {
    2759           0 :                   hdrlen += sizeof (gtpu_exthdr_t);
    2760           0 :                   if (hdr0->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
    2761             :                     {
    2762             :                       gtpu_pdu_session_t *sess;
    2763             : 
    2764           0 :                       sess =
    2765             :                         (gtpu_pdu_session_t *) (((char *) hdr0) +
    2766             :                                                 sizeof (ip6_gtpu_header_t) +
    2767             :                                                 sizeof (gtpu_exthdr_t));
    2768             : 
    2769           0 :                       hdrlen += sizeof (gtpu_pdu_session_t);
    2770           0 :                       if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
    2771             :                         {
    2772           0 :                           hdrlen += sizeof (gtpu_paging_policy_t);
    2773             :                         }
    2774             :                     }
    2775             :                 }
    2776             : 
    2777           0 :               if (ls_param->type == SRV6_GTP6_DT4)
    2778             :                 {
    2779           0 :                   vlib_buffer_advance (b0, (word) hdrlen);
    2780           0 :                   ip4 = vlib_buffer_get_current (b0);
    2781           0 :                   if ((ip4->ip_version_and_header_length & 0xf0) != 0x40)
    2782             :                     {
    2783           0 :                       next0 = SRV6_END_M_GTP6_DT_NEXT_DROP;
    2784           0 :                       bad_n++;
    2785           0 :                       goto DONE;
    2786             :                     }
    2787             : 
    2788           0 :                   next0 = SRV6_END_M_GTP6_DT_NEXT_LOOKUP4;
    2789           0 :                   vnet_buffer (b0)->sw_if_index[VLIB_TX] =
    2790           0 :                     ls_param->fib4_index;
    2791             :                 }
    2792           0 :               else if (ls_param->type == SRV6_GTP6_DT6)
    2793             :                 {
    2794           0 :                   ip6 = (ip6_header_t *) ((u8 *) hdr0 + hdrlen);
    2795           0 :                   if ((clib_net_to_host_u32 (
    2796           0 :                          ip6->ip_version_traffic_class_and_flow_label) >>
    2797             :                        28) != 6)
    2798             :                     {
    2799           0 :                       next0 = SRV6_END_M_GTP6_DT_NEXT_DROP;
    2800           0 :                       bad_n++;
    2801           0 :                       goto DONE;
    2802             :                     }
    2803             : 
    2804           0 :                   next0 = SRV6_END_M_GTP6_DT_NEXT_LOOKUP6;
    2805           0 :                   if (((ip6->dst_address.as_u8[0] == 0xff) &&
    2806           0 :                        (ip6->dst_address.as_u8[1] == 0x02)) ||
    2807           0 :                       ((ip6->dst_address.as_u8[0] == 0xfe) &&
    2808           0 :                        ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80)))
    2809             :                     {
    2810           0 :                       vnet_buffer (b0)->sw_if_index[VLIB_TX] =
    2811           0 :                         ls_param->local_fib_index;
    2812             :                     }
    2813             :                   else
    2814             :                     {
    2815           0 :                       vlib_buffer_advance (b0, (word) hdrlen);
    2816           0 :                       vnet_buffer (b0)->sw_if_index[VLIB_TX] =
    2817           0 :                         ls_param->fib6_index;
    2818             :                     }
    2819             :                 }
    2820           0 :               else if (ls_param->type == SRV6_GTP6_DT46)
    2821             :                 {
    2822           0 :                   ip6 = (ip6_header_t *) ((u8 *) hdr0 + hdrlen);
    2823           0 :                   if ((clib_net_to_host_u32 (
    2824           0 :                          ip6->ip_version_traffic_class_and_flow_label) >>
    2825             :                        28) == 6)
    2826             :                     {
    2827           0 :                       next0 = SRV6_END_M_GTP6_DT_NEXT_LOOKUP6;
    2828           0 :                       if (((ip6->dst_address.as_u8[0] == 0xff) &&
    2829           0 :                            (ip6->dst_address.as_u8[1] == 0x02)) ||
    2830           0 :                           ((ip6->dst_address.as_u8[0] == 0xfe) &&
    2831           0 :                            ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80)))
    2832             :                         {
    2833           0 :                           vnet_buffer (b0)->sw_if_index[VLIB_TX] =
    2834           0 :                             ls_param->local_fib_index;
    2835             :                         }
    2836             :                       else
    2837             :                         {
    2838           0 :                           vlib_buffer_advance (b0, (word) hdrlen);
    2839           0 :                           vnet_buffer (b0)->sw_if_index[VLIB_TX] =
    2840           0 :                             ls_param->fib6_index;
    2841             :                         }
    2842             :                     }
    2843           0 :                   else if ((clib_net_to_host_u32 (
    2844           0 :                               ip6->ip_version_traffic_class_and_flow_label) >>
    2845             :                             28) == 4)
    2846             :                     {
    2847           0 :                       vlib_buffer_advance (b0, (word) hdrlen);
    2848           0 :                       next0 = SRV6_END_M_GTP6_DT_NEXT_LOOKUP4;
    2849           0 :                       vnet_buffer (b0)->sw_if_index[VLIB_TX] =
    2850           0 :                         ls_param->fib4_index;
    2851             :                     }
    2852             :                   else
    2853             :                     {
    2854           0 :                       next0 = SRV6_END_M_GTP6_DT_NEXT_DROP;
    2855           0 :                       bad_n++;
    2856           0 :                       goto DONE;
    2857             :                     }
    2858             :                 }
    2859             :               else
    2860             :                 {
    2861           0 :                   next0 = SRV6_END_M_GTP6_DT_NEXT_DROP;
    2862           0 :                   bad_n++;
    2863           0 :                   goto DONE;
    2864             :                 }
    2865             : 
    2866           0 :               good_n++;
    2867             : 
    2868           0 :               if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
    2869           0 :                   PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
    2870             :                 {
    2871             :                   srv6_end_rewrite_trace_t *tr =
    2872           0 :                     vlib_add_trace (vm, node, b0, sizeof (*tr));
    2873           0 :                   clib_memcpy (tr->src.as_u8, src.as_u8,
    2874             :                                sizeof (ip6_address_t));
    2875           0 :                   clib_memcpy (tr->dst.as_u8, dst.as_u8,
    2876             :                                sizeof (ip6_address_t));
    2877           0 :                   tr->teid = teid;
    2878             :                 }
    2879             :             }
    2880             : 
    2881           0 :         DONE:
    2882           0 :           vlib_increment_combined_counter (
    2883             :             ((next0 == SRV6_END_M_GTP6_DT_NEXT_DROP) ?
    2884             :                &(sm2->sr_ls_invalid_counters) :
    2885             :                &(sm2->sr_ls_valid_counters)),
    2886           0 :             thread_index, ls0 - sm2->localsids, 1,
    2887             :             vlib_buffer_length_in_chain (vm, b0));
    2888             : 
    2889           0 :           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
    2890             :                                            n_left_to_next, bi0, next0);
    2891             :         }
    2892             : 
    2893           0 :       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
    2894             :     }
    2895             : 
    2896           0 :   vlib_node_increment_counter (vm, sm->end_m_gtp6_dt_node_index,
    2897             :                                SRV6_END_ERROR_M_GTP6_DT_BAD_PACKETS, bad_n);
    2898             : 
    2899           0 :   vlib_node_increment_counter (vm, sm->end_m_gtp6_dt_node_index,
    2900             :                                SRV6_END_ERROR_M_GTP6_DT_PACKETS, good_n);
    2901             : 
    2902           0 :   return frame->n_vectors;
    2903             : }
    2904             : 
    2905             : // Function for SRv6 GTP4.DT function
    2906         575 : VLIB_NODE_FN (srv6_t_m_gtp4_dt)
    2907             : (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
    2908             : {
    2909           0 :   srv6_t_main_v4_dt_t *sm = &srv6_t_main_v4_dt;
    2910           0 :   ip6_sr_main_t *sm2 = &sr_main;
    2911             :   u32 n_left_from, next_index, *from, *to_next;
    2912             : 
    2913           0 :   u32 good_n = 0, bad_n = 0;
    2914             : 
    2915           0 :   from = vlib_frame_vector_args (frame);
    2916           0 :   n_left_from = frame->n_vectors;
    2917           0 :   next_index = node->cached_next_index;
    2918             : 
    2919           0 :   while (n_left_from > 0)
    2920             :     {
    2921             :       u32 n_left_to_next;
    2922             : 
    2923           0 :       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
    2924             : 
    2925           0 :       while (n_left_from > 0 && n_left_to_next > 0)
    2926             :         {
    2927             :           u32 bi0;
    2928             :           vlib_buffer_t *b0;
    2929             :           srv6_t_gtp4_dt_param_t *ls_param;
    2930             :           ip6_sr_sl_t *ls0;
    2931             : 
    2932           0 :           ip4_gtpu_header_t *hdr0 = NULL;
    2933           0 :           ip4_header_t *ip4 = NULL;
    2934           0 :           ip6_header_t *ip6 = NULL;
    2935             :           ip6_address_t src, dst;
    2936             :           u32 teid;
    2937             :           u32 hdrlen;
    2938             :           u32 len0;
    2939             : 
    2940           0 :           u32 next0 = SRV6_T_M_GTP4_DT_NEXT_DROP;
    2941             : 
    2942           0 :           bi0 = from[0];
    2943           0 :           to_next[0] = bi0;
    2944           0 :           from += 1;
    2945           0 :           to_next += 1;
    2946           0 :           n_left_from -= 1;
    2947           0 :           n_left_to_next -= 1;
    2948             : 
    2949           0 :           b0 = vlib_get_buffer (vm, bi0);
    2950           0 :           ls0 = pool_elt_at_index (sm2->sid_lists,
    2951             :                                    vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
    2952             : 
    2953           0 :           ls_param = (srv6_t_gtp4_dt_param_t *) ls0->plugin_mem;
    2954             : 
    2955           0 :           hdr0 = vlib_buffer_get_current (b0);
    2956             : 
    2957           0 :           hdrlen = sizeof (ip4_gtpu_header_t);
    2958             : 
    2959           0 :           len0 = vlib_buffer_length_in_chain (vm, b0);
    2960             : 
    2961           0 :           if ((hdr0->ip4.protocol != IP_PROTOCOL_UDP) ||
    2962           0 :               (hdr0->udp.dst_port !=
    2963           0 :                clib_host_to_net_u16 (SRV6_GTP_UDP_DST_PORT)) ||
    2964             :               (len0 < sizeof (ip4_gtpu_header_t)))
    2965             :             {
    2966           0 :               next0 = SRV6_T_M_GTP4_DT_NEXT_DROP;
    2967             : 
    2968           0 :               bad_n++;
    2969             :             }
    2970             :           else
    2971             :             {
    2972           0 :               clib_memcpy_fast (src.as_u8, hdr0->ip4.src_address.as_u8,
    2973             :                                 sizeof (ip4_address_t));
    2974           0 :               clib_memcpy_fast (dst.as_u8, hdr0->ip4.dst_address.as_u8,
    2975             :                                 sizeof (ip4_address_t));
    2976             : 
    2977           0 :               teid = hdr0->gtpu.teid;
    2978             : 
    2979           0 :               if (hdr0->gtpu.ver_flags & GTPU_EXTHDR_FLAG)
    2980             :                 {
    2981           0 :                   hdrlen += sizeof (gtpu_exthdr_t);
    2982           0 :                   if (hdr0->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
    2983             :                     {
    2984             :                       gtpu_pdu_session_t *sess;
    2985             : 
    2986           0 :                       sess =
    2987             :                         (gtpu_pdu_session_t *) (((char *) hdr0) +
    2988             :                                                 sizeof (ip6_gtpu_header_t) +
    2989             :                                                 sizeof (gtpu_exthdr_t));
    2990             : 
    2991           0 :                       hdrlen += sizeof (gtpu_pdu_session_t);
    2992           0 :                       if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
    2993             :                         {
    2994           0 :                           hdrlen += sizeof (gtpu_paging_policy_t);
    2995             :                         }
    2996             :                     }
    2997             :                 }
    2998             : 
    2999           0 :               if (ls_param->type == SRV6_GTP4_DT4)
    3000             :                 {
    3001           0 :                   vlib_buffer_advance (b0, (word) hdrlen);
    3002           0 :                   ip4 = vlib_buffer_get_current (b0);
    3003           0 :                   if ((ip4->ip_version_and_header_length & 0xf0) != 0x40)
    3004             :                     {
    3005           0 :                       next0 = SRV6_T_M_GTP4_DT_NEXT_DROP;
    3006           0 :                       bad_n++;
    3007           0 :                       goto DONE;
    3008             :                     }
    3009             : 
    3010           0 :                   next0 = SRV6_T_M_GTP4_DT_NEXT_LOOKUP4;
    3011           0 :                   vnet_buffer (b0)->sw_if_index[VLIB_TX] =
    3012           0 :                     ls_param->fib4_index;
    3013             :                 }
    3014           0 :               else if (ls_param->type == SRV6_GTP4_DT6)
    3015             :                 {
    3016           0 :                   ip6 = (ip6_header_t *) ((u8 *) hdr0 + hdrlen);
    3017           0 :                   if ((clib_net_to_host_u32 (
    3018           0 :                          ip6->ip_version_traffic_class_and_flow_label) >>
    3019             :                        28) != 6)
    3020             :                     {
    3021           0 :                       next0 = SRV6_T_M_GTP4_DT_NEXT_DROP;
    3022           0 :                       bad_n++;
    3023           0 :                       goto DONE;
    3024             :                     }
    3025             : 
    3026           0 :                   next0 = SRV6_T_M_GTP4_DT_NEXT_LOOKUP6;
    3027           0 :                   if (((ip6->dst_address.as_u8[0] == 0xff) &&
    3028           0 :                        (ip6->dst_address.as_u8[1] == 0x02)) ||
    3029           0 :                       ((ip6->dst_address.as_u8[0] == 0xfe) &&
    3030           0 :                        ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80)))
    3031             :                     {
    3032           0 :                       next0 = SRV6_T_M_GTP4_DT_NEXT_LOOKUP4;
    3033           0 :                       vnet_buffer (b0)->sw_if_index[VLIB_TX] =
    3034           0 :                         ls_param->local_fib_index;
    3035             :                     }
    3036             :                   else
    3037             :                     {
    3038           0 :                       vlib_buffer_advance (b0, (word) hdrlen);
    3039           0 :                       vnet_buffer (b0)->sw_if_index[VLIB_TX] =
    3040           0 :                         ls_param->fib6_index;
    3041             :                     }
    3042             :                 }
    3043           0 :               else if (ls_param->type == SRV6_GTP4_DT46)
    3044             :                 {
    3045           0 :                   ip6 = (ip6_header_t *) ((u8 *) hdr0 + hdrlen);
    3046           0 :                   if ((clib_net_to_host_u32 (
    3047           0 :                          ip6->ip_version_traffic_class_and_flow_label) >>
    3048             :                        28) == 6)
    3049             :                     {
    3050           0 :                       next0 = SRV6_T_M_GTP4_DT_NEXT_LOOKUP6;
    3051           0 :                       if (((ip6->dst_address.as_u8[0] == 0xff) &&
    3052           0 :                            (ip6->dst_address.as_u8[1] == 0x02)) ||
    3053           0 :                           ((ip6->dst_address.as_u8[0] == 0xfe) &&
    3054           0 :                            ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80)))
    3055             :                         {
    3056           0 :                           next0 = SRV6_T_M_GTP4_DT_NEXT_LOOKUP4;
    3057           0 :                           vnet_buffer (b0)->sw_if_index[VLIB_TX] =
    3058           0 :                             ls_param->local_fib_index;
    3059             :                         }
    3060             :                       else
    3061             :                         {
    3062           0 :                           vlib_buffer_advance (b0, (word) hdrlen);
    3063           0 :                           vnet_buffer (b0)->sw_if_index[VLIB_TX] =
    3064           0 :                             ls_param->fib6_index;
    3065             :                         }
    3066             :                     }
    3067           0 :                   else if ((clib_net_to_host_u32 (
    3068           0 :                               ip6->ip_version_traffic_class_and_flow_label) >>
    3069             :                             28) == 4)
    3070             :                     {
    3071           0 :                       vlib_buffer_advance (b0, (word) hdrlen);
    3072           0 :                       next0 = SRV6_T_M_GTP4_DT_NEXT_LOOKUP4;
    3073           0 :                       vnet_buffer (b0)->sw_if_index[VLIB_TX] =
    3074           0 :                         ls_param->fib4_index;
    3075             :                     }
    3076             :                   else
    3077             :                     {
    3078           0 :                       next0 = SRV6_T_M_GTP4_DT_NEXT_DROP;
    3079           0 :                       bad_n++;
    3080           0 :                       goto DONE;
    3081             :                     }
    3082             :                 }
    3083             :               else
    3084             :                 {
    3085           0 :                   next0 = SRV6_T_M_GTP4_DT_NEXT_DROP;
    3086           0 :                   bad_n++;
    3087           0 :                   goto DONE;
    3088             :                 }
    3089             : 
    3090           0 :               good_n++;
    3091             : 
    3092           0 :               if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
    3093           0 :                   PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
    3094             :                 {
    3095             :                   srv6_end_rewrite_trace_t *tr =
    3096           0 :                     vlib_add_trace (vm, node, b0, sizeof (*tr));
    3097           0 :                   clib_memcpy (tr->src.as_u8, src.as_u8,
    3098             :                                sizeof (ip6_address_t));
    3099           0 :                   clib_memcpy (tr->dst.as_u8, dst.as_u8,
    3100             :                                sizeof (ip6_address_t));
    3101           0 :                   tr->teid = teid;
    3102             :                 }
    3103             :             }
    3104             : 
    3105           0 :         DONE:
    3106           0 :           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
    3107             :                                            n_left_to_next, bi0, next0);
    3108             :         }
    3109             : 
    3110           0 :       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
    3111             :     }
    3112             : 
    3113           0 :   vlib_node_increment_counter (vm, sm->t_m_gtp4_dt_node_index,
    3114             :                                SRV6_T_ERROR_M_GTP4_DT_BAD_PACKETS, bad_n);
    3115             : 
    3116           0 :   vlib_node_increment_counter (vm, sm->t_m_gtp4_dt_node_index,
    3117             :                                SRV6_T_ERROR_M_GTP4_DT_PACKETS, good_n);
    3118             : 
    3119           0 :   return frame->n_vectors;
    3120             : }
    3121             : 
    3122       32255 : VLIB_REGISTER_NODE (srv6_end_m_gtp6_e) =
    3123             : {
    3124             :   .name = "srv6-end-m-gtp6-e",.vector_size = sizeof (u32),.format_trace =
    3125             :     format_srv6_end_rewrite_trace6,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
    3126             :     ARRAY_LEN (srv6_end_error_v6_e_strings),.error_strings =
    3127             :     srv6_end_error_v6_e_strings,.n_next_nodes =
    3128             :     SRV6_END_M_GTP6_E_N_NEXT,.next_nodes =
    3129             :   {
    3130             :   [SRV6_END_M_GTP6_E_NEXT_DROP] = "error-drop",
    3131             :   [SRV6_END_M_GTP6_E_NEXT_LOOKUP] = "ip6-lookup",}
    3132             : ,};
    3133             : 
    3134       32255 : VLIB_REGISTER_NODE (srv6_end_m_gtp6_d) =
    3135             : {
    3136             :   .name = "srv6-end-m-gtp6-d",.vector_size = sizeof (u32),.format_trace =
    3137             :     format_srv6_end_rewrite_trace6,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
    3138             :     ARRAY_LEN (srv6_end_error_v6_d_strings),.error_strings =
    3139             :     srv6_end_error_v6_d_strings,.n_next_nodes =
    3140             :     SRV6_END_M_GTP6_D_N_NEXT,.next_nodes =
    3141             :   {
    3142             :   [SRV6_END_M_GTP6_D_NEXT_DROP] = "error-drop",
    3143             :   [SRV6_END_M_GTP6_D_NEXT_LOOKUP4] = "ip4-lookup",
    3144             :   [SRV6_END_M_GTP6_D_NEXT_LOOKUP6] = "ip6-lookup",}
    3145             : ,};
    3146             : 
    3147       32255 : VLIB_REGISTER_NODE (srv6_end_m_gtp6_d_di) =
    3148             : {
    3149             :   .name = "srv6-end-m-gtp6-d-di",.vector_size = sizeof (u32),.format_trace =
    3150             :     format_srv6_end_rewrite_trace6,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
    3151             :     ARRAY_LEN (srv6_end_error_v6_d_di_strings),.error_strings =
    3152             :     srv6_end_error_v6_d_di_strings,.n_next_nodes =
    3153             :     SRV6_END_M_GTP6_D_DI_N_NEXT,.next_nodes =
    3154             :   {
    3155             :   [SRV6_END_M_GTP6_D_DI_NEXT_DROP] = "error-drop",
    3156             :   [SRV6_END_M_GTP6_D_DI_NEXT_LOOKUP] = "ip6-lookup",}
    3157             : ,};
    3158             : 
    3159       32255 : VLIB_REGISTER_NODE (srv6_end_m_gtp6_dt) =
    3160             : {
    3161             :   .name = "srv6-end-m-gtp6-dt",.vector_size = sizeof (u32),.format_trace =
    3162             :     format_srv6_end_rewrite_trace6,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
    3163             :     ARRAY_LEN (srv6_end_error_v6_dt_strings),.error_strings =
    3164             :     srv6_end_error_v6_dt_strings,.n_next_nodes =
    3165             :     SRV6_END_M_GTP6_DT_N_NEXT,.next_nodes =
    3166             :   {
    3167             :   [SRV6_END_M_GTP6_DT_NEXT_DROP] = "error-drop",
    3168             :   [SRV6_END_M_GTP6_DT_NEXT_LOOKUP4] = "ip4-lookup",
    3169             :   [SRV6_END_M_GTP6_DT_NEXT_LOOKUP6] = "ip6-lookup",}
    3170             : ,};
    3171             : 
    3172       32255 : VLIB_REGISTER_NODE (srv6_t_m_gtp4_dt) =
    3173             : {
    3174             :   .name = "srv6-t-m-gtp4-dt",.vector_size = sizeof (u32),.format_trace =
    3175             :     format_srv6_end_rewrite_trace6,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
    3176             :     ARRAY_LEN (srv6_t_error_v4_dt_strings),.error_strings =
    3177             :     srv6_t_error_v4_dt_strings,.n_next_nodes =
    3178             :     SRV6_T_M_GTP4_DT_N_NEXT,.next_nodes =
    3179             :   {
    3180             :   [SRV6_T_M_GTP4_DT_NEXT_DROP] = "error-drop",
    3181             :   [SRV6_T_M_GTP4_DT_NEXT_LOOKUP4] = "ip4-lookup",
    3182             :   [SRV6_T_M_GTP4_DT_NEXT_LOOKUP6] = "ip6-lookup",}
    3183             : ,};
    3184             : 
    3185             : /*
    3186             : * fd.io coding-style-patch-verification: ON
    3187             : *
    3188             : * Local Variables:
    3189             : * eval: (c-set-style "gnu")
    3190             : * End:
    3191             : */

Generated by: LCOV version 1.14