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