6d3240e77c4b2ce0b42e9ae561de9db62e1d8c44
[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               u16 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                       && payload_len > hdr_len - sizeof (ip4_gtpu_header_t))
906                     {
907                       u8 *ies;
908
909                       ies = (u8 *) ((u8 *) hdr + hdr_len);
910                       ie_size =
911                         payload_len - (hdr_len - sizeof (ip4_gtpu_header_t));
912                       clib_memcpy_fast (ie_buf, ies, ie_size);
913                       hdr_len += ie_size;
914                     }
915                 }
916
917               src6 = ls_param->v6src_prefix;
918
919               offset = ls_param->v6src_prefixlen / 8;
920               shift = ls_param->v6src_prefixlen % 8;
921
922               if (PREDICT_TRUE (shift == 0))
923                 {
924                   clib_memcpy_fast (&src6.as_u8[offset], srcp, 4);
925                 }
926               else
927                 {
928                   for (index = 0; index < 4; index++)
929                     {
930                       src6.as_u8[offset + index] |= srcp[offset] >> shift;
931                       src6.as_u8[offset + index + 1] |=
932                         srcp[offset] << (8 - shift);
933                     }
934                 }
935
936               vlib_buffer_advance (b0, (word) hdr_len);
937
938               // Encap to SRv6.
939               if (PREDICT_TRUE (gtpu_type == GTPU_TYPE_GTPU))
940                 {
941                   encap = vlib_buffer_get_current (b0);
942                 }
943
944               len0 = vlib_buffer_length_in_chain (vm, b0);
945
946               p =
947                 mhash_get (&sm2->sr_policies_index_hash,
948                            &ls_param->sr_prefix);
949               if (p)
950                 {
951                   sr_policy = pool_elt_at_index (sm2->sr_policies, p[0]);
952                 }
953
954               if (sr_policy)
955                 {
956                   vec_foreach (sl_index, sr_policy->segments_lists)
957                   {
958                     sl = pool_elt_at_index (sm2->sid_lists, *sl_index);
959                     if (sl != NULL)
960                       break;
961                   }
962                 }
963
964               if (sl)
965                 {
966                   hdr_len = sizeof (ip6srv_combo_header_t);
967                   hdr_len += vec_len (sl->segments) * sizeof (ip6_address_t);
968                   hdr_len += sizeof (ip6_address_t);
969                 }
970               else
971                 {
972                   hdr_len = sizeof (ip6_header_t);
973
974                   if (PREDICT_FALSE (gtpu_type != GTPU_TYPE_GTPU))
975                     {
976                       hdr_len += sizeof (ip6_sr_header_t);
977                       hdr_len += sizeof (ip6_address_t);
978                     }
979                 }
980
981               if (ie_size)
982                 {
983                   tlv_siz =
984                     sizeof (ip6_sr_tlv_t) + sizeof (user_plane_sub_tlv_t) +
985                     ie_size;
986
987                   tlv_siz = (tlv_siz & ~0x07) + (tlv_siz & 0x07 ? 0x08 : 0x0);
988                   hdr_len += tlv_siz;
989                 }
990
991               vlib_buffer_advance (b0, -(word) hdr_len);
992               ip6srv = vlib_buffer_get_current (b0);
993
994               if (sl)
995                 {
996                   clib_memcpy_fast (ip6srv, sl->rewrite,
997                                     vec_len (sl->rewrite));
998
999                   if (vec_len (sl->segments) > 1)
1000                     {
1001                       ip6srv->sr.tag =
1002                         clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1003
1004                       ip6srv->sr.segments_left += 1;
1005                       ip6srv->sr.last_entry += 1;
1006
1007                       ip6srv->sr.length += sizeof (ip6_address_t) / 8;
1008                       ip6srv->sr.segments[0] = seg;
1009
1010                       clib_memcpy_fast (&ip6srv->sr.segments[1],
1011                                         (u8 *) (sl->rewrite +
1012                                                 sizeof (ip6_header_t) +
1013                                                 sizeof (ip6_sr_header_t)),
1014                                         vec_len (sl->segments) *
1015                                         sizeof (ip6_address_t));
1016                     }
1017                   else
1018                     {
1019                       ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
1020
1021                       ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
1022
1023                       ip6srv->sr.segments_left = 1;
1024                       ip6srv->sr.last_entry = 0;
1025
1026                       ip6srv->sr.length =
1027                         ((sizeof (ip6_sr_header_t) +
1028                           sizeof (ip6_address_t)) / 8) - 1;
1029                       ip6srv->sr.flags = 0;
1030
1031                       ip6srv->sr.tag =
1032                         clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1033
1034                       ip6srv->sr.segments[0] = seg;
1035                       if (vec_len (sl->segments))
1036                         {
1037                           ip6srv->sr.segments[1] = sl->segments[0];
1038                           ip6srv->sr.length += sizeof (ip6_address_t) / 8;
1039                           ip6srv->sr.last_entry++;
1040                         }
1041                     }
1042
1043                   if (PREDICT_TRUE (encap != NULL))
1044                     {
1045                       if (ls_param->nhtype == SRV6_NHTYPE_NONE)
1046                         {
1047                           if ((clib_net_to_host_u32
1048                                (encap->ip_version_traffic_class_and_flow_label)
1049                                >> 28) == 6)
1050                             ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
1051                           else
1052                             ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
1053                         }
1054                       else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
1055                         {
1056                           ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
1057                           if ((clib_net_to_host_u32
1058                                (encap->ip_version_traffic_class_and_flow_label)
1059                                >> 28) != 4)
1060                             {
1061                               // Bad encap packet.
1062                               next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
1063                               bad_n++;
1064                               goto DONE;
1065                             }
1066                         }
1067                       else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
1068                         {
1069                           ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
1070                           if ((clib_net_to_host_u32
1071                                (encap->ip_version_traffic_class_and_flow_label)
1072                                >> 28) != 6)
1073                             {
1074                               // Bad encap packet.
1075                               next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
1076                               bad_n++;
1077                               goto DONE;
1078                             }
1079                         }
1080                       else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
1081                         {
1082                           ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
1083                         }
1084                     }
1085                   else
1086                     {
1087                       ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
1088                     }
1089                 }
1090               else
1091                 {
1092                   clib_memcpy_fast (ip6srv, &sm->cache_hdr,
1093                                     sizeof (ip6_header_t));
1094
1095                   ip6srv->ip.dst_address = seg;
1096
1097                   if (PREDICT_FALSE (gtpu_type != GTPU_TYPE_GTPU))
1098                     {
1099                       ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
1100
1101                       ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
1102
1103                       ip6srv->sr.tag =
1104                         clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1105
1106                       ip6srv->sr.segments_left = 0;
1107                       ip6srv->sr.last_entry = 0;
1108
1109                       ip6srv->sr.length = sizeof (ip6_address_t) / 8;
1110                       ip6srv->sr.segments[0] = seg;
1111                     }
1112                   else
1113                     {
1114                       if (ls_param->nhtype == SRV6_NHTYPE_NONE)
1115                         {
1116                           if ((clib_net_to_host_u32
1117                                (encap->ip_version_traffic_class_and_flow_label)
1118                                >> 28) == 6)
1119                             ip6srv->ip.protocol = IP_PROTOCOL_IPV6;
1120                           else
1121                             ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
1122                         }
1123                       else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
1124                         {
1125                           ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
1126                           if ((clib_net_to_host_u32
1127                                (encap->ip_version_traffic_class_and_flow_label)
1128                                >> 28) != 4)
1129                             {
1130                               // Bad encap packet.
1131                               next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
1132                               bad_n++;
1133                               goto DONE;
1134                             }
1135                         }
1136                       else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
1137                         {
1138                           ip6srv->ip.protocol = IP_PROTOCOL_IPV6;
1139                           if ((clib_net_to_host_u32
1140                                (encap->ip_version_traffic_class_and_flow_label)
1141                                >> 28) != 6)
1142                             {
1143                               // Bad encap packet.
1144                               next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
1145                               bad_n++;
1146                               goto DONE;
1147                             }
1148                         }
1149                       else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
1150                         {
1151                           ip6srv->ip.protocol = IP_PROTOCOL_IP6_ETHERNET;
1152                         }
1153                     }
1154                 }
1155
1156               ip6srv->ip.src_address = src6;
1157
1158               if (PREDICT_FALSE (ie_size))
1159                 {
1160                   ip6_sr_tlv_t *tlv;
1161                   user_plane_sub_tlv_t *sub_tlv;
1162
1163                   tlv =
1164                     (ip6_sr_tlv_t *) ((u8 *) ip6srv + (hdr_len - tlv_siz));
1165                   tlv->type = SRH_TLV_USER_PLANE_CONTAINER;
1166                   tlv->length = tlv_siz - sizeof (ip6_sr_tlv_t);
1167                   clib_memset (tlv->value, 0, tlv->length);
1168
1169                   sub_tlv = (user_plane_sub_tlv_t *) tlv->value;
1170                   sub_tlv->type = USER_PLANE_SUB_TLV_IE;
1171                   sub_tlv->length = ie_size;
1172                   clib_memcpy_fast (sub_tlv->value, ie_buf, ie_size);
1173
1174                   ip6srv->sr.length += tlv_siz / 8;
1175                 }
1176
1177               ip6srv->ip.payload_length =
1178                 clib_host_to_net_u16 (len0 + hdr_len - sizeof (ip6_header_t));
1179
1180               good_n++;
1181
1182               if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
1183                   PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1184                 {
1185                   srv6_end_rewrite_trace_t *tr =
1186                     vlib_add_trace (vm, node, b0, sizeof (*tr));
1187                   clib_memcpy (tr->src.as_u8, ip6srv->ip.src_address.as_u8,
1188                                sizeof (tr->src.as_u8));
1189                   clib_memcpy (tr->dst.as_u8, ip6srv->ip.dst_address.as_u8,
1190                                sizeof (tr->dst.as_u8));
1191                 }
1192             }
1193
1194         DONE:
1195           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1196                                            n_left_to_next, bi0, next0);
1197         }
1198
1199       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1200     }
1201
1202   vlib_node_increment_counter (vm, sm->t_m_gtp4_d_node_index,
1203                                SRV6_T_ERROR_M_GTP4_D_BAD_PACKETS, bad_n);
1204
1205   vlib_node_increment_counter (vm, sm->t_m_gtp4_d_node_index,
1206                                SRV6_T_ERROR_M_GTP4_D_PACKETS, good_n);
1207
1208   return frame->n_vectors;
1209 }
1210
1211 VLIB_REGISTER_NODE (srv6_end_m_gtp4_e) =
1212 {
1213   .name = "srv6-end-m-gtp4-e",.vector_size = sizeof (u32),.format_trace =
1214     format_srv6_end_rewrite_trace,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
1215     ARRAY_LEN (srv6_end_error_v4_strings),.error_strings =
1216     srv6_end_error_v4_strings,.n_next_nodes =
1217     SRV6_END_M_GTP4_E_N_NEXT,.next_nodes =
1218   {
1219   [SRV6_END_M_GTP4_E_NEXT_DROP] =
1220       "error-drop",[SRV6_END_M_GTP4_E_NEXT_LOOKUP] = "ip4-lookup",}
1221 ,};
1222
1223 VLIB_REGISTER_NODE (srv6_t_m_gtp4_d) =
1224 {
1225   .name = "srv6-t-m-gtp4-d",.vector_size = sizeof (u32),.format_trace =
1226     format_srv6_end_rewrite_trace,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
1227     ARRAY_LEN (srv6_t_error_v4_d_strings),.error_strings =
1228     srv6_t_error_v4_d_strings,.n_next_nodes =
1229     SRV6_T_M_GTP4_D_N_NEXT,.next_nodes =
1230   {
1231   [SRV6_T_M_GTP4_D_NEXT_DROP] =
1232       "error-drop",[SRV6_T_M_GTP4_D_NEXT_LOOKUP] = "ip6-lookup",}
1233 ,};
1234
1235 // Function for SRv6 GTP6.E function
1236 VLIB_NODE_FN (srv6_end_m_gtp6_e) (vlib_main_t * vm,
1237                                   vlib_node_runtime_t * node,
1238                                   vlib_frame_t * frame)
1239 {
1240   srv6_end_main_v6_t *sm = &srv6_end_main_v6;
1241   ip6_sr_main_t *sm2 = &sr_main;
1242   u32 n_left_from, next_index, *from, *to_next;
1243   u32 thread_index = vm->thread_index;
1244
1245   u32 good_n = 0, bad_n = 0;
1246
1247   from = vlib_frame_vector_args (frame);
1248   n_left_from = frame->n_vectors;
1249   next_index = node->cached_next_index;
1250
1251   while (n_left_from > 0)
1252     {
1253       u32 n_left_to_next;
1254
1255       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1256
1257       while (n_left_from > 0 && n_left_to_next > 0)
1258         {
1259           u32 bi0;
1260           vlib_buffer_t *b0;
1261           ip6_sr_localsid_t *ls0;
1262
1263           ip6srv_combo_header_t *ip6srv0;
1264           ip6_address_t dst0, src0, seg0;
1265
1266           ip6_gtpu_header_t *hdr0 = NULL;
1267           uword len0;
1268           uword key;
1269           u16 port;
1270           u16 tag;
1271           void *p;
1272           uword plen;
1273
1274           u32 next0 = SRV6_END_M_GTP6_E_NEXT_LOOKUP;
1275
1276           // defaults
1277           bi0 = from[0];
1278           to_next[0] = bi0;
1279           from += 1;
1280           to_next += 1;
1281           n_left_from -= 1;
1282           n_left_to_next -= 1;
1283
1284           b0 = vlib_get_buffer (vm, bi0);
1285           ls0 =
1286             pool_elt_at_index (sm2->localsids,
1287                                vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1288
1289           ip6srv0 = vlib_buffer_get_current (b0);
1290           dst0 = ip6srv0->ip.dst_address;
1291           src0 = ip6srv0->ip.src_address;
1292           seg0 = ip6srv0->sr.segments[0];
1293
1294           tag = ip6srv0->sr.tag;
1295
1296           len0 = vlib_buffer_length_in_chain (vm, b0);
1297
1298           if ((ip6srv0->ip.protocol != IPPROTO_IPV6_ROUTE)
1299               || (len0 <
1300                   sizeof (ip6srv_combo_header_t) + 8 * ip6srv0->sr.length))
1301             {
1302               next0 = SRV6_END_M_GTP6_E_NEXT_DROP;
1303
1304               bad_n++;
1305             }
1306           else
1307             {
1308               // we need to be sure there is enough space before
1309               // ip6srv0 header, there is some extra space
1310               // in the pre_data area for this kind of
1311               // logic
1312
1313               u32 teid = 0;
1314               u8 *teid8p = (u8 *) & teid;
1315               u8 qfi = 0;
1316               u16 seq = 0;
1317               u8 gtpu_type = 0;
1318               u16 index;
1319               u16 offset, shift;
1320               u32 hdrlen = 0;
1321               u16 ie_size = 0;
1322               u8 ie_buf[GTPU_IE_MAX_SIZ];
1323
1324               index = ls0->localsid_prefix_len;
1325               index += 8;
1326               offset = index / 8;
1327               shift = index % 8;
1328
1329               gtpu_type = gtpu_type_get (tag);
1330
1331               if (PREDICT_TRUE (shift == 0))
1332                 {
1333                   if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1334                       || gtpu_type == GTPU_TYPE_ECHO_REPLY
1335                       || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1336                     {
1337                       clib_memcpy_fast (&seq, &dst0.as_u8[offset], 2);
1338                     }
1339                   else
1340                     {
1341                       clib_memcpy_fast (teid8p, &dst0.as_u8[offset], 4);
1342                     }
1343
1344                   qfi = dst0.as_u8[offset + 4];
1345                 }
1346               else
1347                 {
1348                   u8 *sp;
1349
1350                   if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1351                       || gtpu_type == GTPU_TYPE_ECHO_REPLY
1352                       || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1353                     {
1354                       sp = (u8 *) & seq;
1355                       for (index = 0; index < 2; index++)
1356                         {
1357                           sp[index] = dst0.as_u8[offset + index] << shift;
1358                           sp[index] |=
1359                             dst0.as_u8[offset + index + 1] >> (8 - shift);
1360                         }
1361                     }
1362                   else
1363                     {
1364                       for (index = 0; index < 4; index++)
1365                         {
1366                           *teid8p = dst0.as_u8[offset + index] << shift;
1367                           *teid8p |=
1368                             dst0.as_u8[offset + index + 1] >> (8 - shift);
1369                           teid8p++;
1370                         }
1371                     }
1372
1373                   qfi |= dst0.as_u8[offset + 4] << shift;
1374                   qfi |= dst0.as_u8[offset + 5] >> (8 - shift);
1375                 }
1376
1377               if (qfi)
1378                 {
1379                   hdrlen =
1380                     sizeof (gtpu_exthdr_t) + sizeof (gtpu_pdu_session_t);
1381                 }
1382               else if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1383                        || gtpu_type == GTPU_TYPE_ECHO_REPLY
1384                        || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1385                 {
1386                   hdrlen = sizeof (gtpu_exthdr_t);
1387                 }
1388
1389               if (gtpu_type == GTPU_TYPE_ECHO_REPLY)
1390                 {
1391                   hdrlen += sizeof (gtpu_recovery_ie);
1392                 }
1393
1394               if (PREDICT_FALSE (gtpu_type == GTPU_TYPE_ERROR_INDICATION))
1395                 {
1396                   ip6_sr_tlv_t *tlv;
1397                   u16 ext_len;
1398
1399                   ext_len = ip6srv0->sr.length * 8;
1400
1401                   if (ext_len >
1402                       sizeof (ip6_address_t) * (ip6srv0->sr.last_entry + 1))
1403                     {
1404                       tlv =
1405                         (ip6_sr_tlv_t *) ((u8 *) & ip6srv0->sr +
1406                                           sizeof (ip6_sr_header_t) +
1407                                           sizeof (ip6_address_t) *
1408                                           (ip6srv0->sr.last_entry + 1));
1409
1410                       if (tlv->type == SRH_TLV_USER_PLANE_CONTAINER)
1411                         {
1412                           user_plane_sub_tlv_t *sub_tlv;
1413
1414                           sub_tlv = (user_plane_sub_tlv_t *) tlv->value;
1415
1416                           ie_size = sub_tlv->length;
1417                           clib_memcpy_fast (ie_buf, sub_tlv->value, ie_size);
1418
1419                           hdrlen += ie_size;
1420                         }
1421                     }
1422                 }
1423
1424               vlib_buffer_advance (b0,
1425                                    (word) sizeof (ip6srv_combo_header_t) +
1426                                    ip6srv0->sr.length * 8);
1427
1428               // get length of encapsulated IPv6 packet (the remaining part)
1429               p = vlib_buffer_get_current (b0);
1430
1431               plen = len0 = vlib_buffer_length_in_chain (vm, b0);
1432
1433               len0 += hdrlen;
1434
1435               hdrlen += sizeof (ip6_gtpu_header_t);
1436
1437               vlib_buffer_advance (b0, -(word) hdrlen);
1438
1439               hdr0 = vlib_buffer_get_current (b0);
1440
1441               clib_memcpy_fast (hdr0, &sm->cache_hdr,
1442                                 sizeof (ip6_gtpu_header_t));
1443
1444               hdr0->gtpu.teid = teid;
1445               hdr0->gtpu.length = clib_host_to_net_u16 (len0);
1446
1447               hdr0->gtpu.type = gtpu_type;
1448
1449               if (qfi)
1450                 {
1451                   u8 type = 0;
1452                   gtpu_pdu_session_t *sess;
1453
1454                   hdr0->gtpu.ver_flags |= GTPU_EXTHDR_FLAG;
1455
1456                   hdr0->gtpu.ext->seq = 0;
1457                   hdr0->gtpu.ext->npdu_num = 0;
1458                   hdr0->gtpu.ext->nextexthdr = GTPU_EXTHDR_PDU_SESSION;
1459
1460                   type = qfi & SRV6_PDU_SESSION_U_BIT_MASK;
1461
1462                   qfi =
1463                     ((qfi & SRV6_PDU_SESSION_QFI_MASK) >> 2) |
1464                     ((qfi & SRV6_PDU_SESSION_R_BIT_MASK) << 5);
1465
1466                   sess =
1467                     (gtpu_pdu_session_t *) (((char *) hdr0) +
1468                                             sizeof (ip6_gtpu_header_t) +
1469                                             sizeof (gtpu_exthdr_t));
1470                   sess->exthdrlen = 1;
1471                   sess->type = type;
1472                   sess->spare = 0;
1473                   sess->u.val = qfi;
1474                   sess->nextexthdr = 0;
1475                 }
1476
1477               if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1478                   || gtpu_type == GTPU_TYPE_ECHO_REPLY
1479                   || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1480                 {
1481                   hdr0->gtpu.ver_flags |= GTPU_SEQ_FLAG;
1482                   hdr0->gtpu.ext->seq = seq;
1483                   hdr0->gtpu.ext->npdu_num = 0;
1484                   hdr0->gtpu.ext->nextexthdr = 0;
1485
1486                   if (gtpu_type == GTPU_TYPE_ECHO_REPLY)
1487                     {
1488                       gtpu_recovery_ie *recovery;
1489
1490                       recovery =
1491                         (gtpu_recovery_ie *) ((u8 *) hdr0 +
1492                                               (hdrlen -
1493                                                sizeof (gtpu_recovery_ie)));
1494                       recovery->type = GTPU_RECOVERY_IE_TYPE;
1495                       recovery->restart_counter = 0;
1496                     }
1497                   else if (gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1498                     {
1499                       if (ie_size)
1500                         {
1501                           u8 *ie_ptr;
1502
1503                           ie_ptr = (u8 *) ((u8 *) hdr0 + (hdrlen - ie_size));
1504                           clib_memcpy_fast (ie_ptr, ie_buf, ie_size);
1505                         }
1506                     }
1507                 }
1508
1509               hdr0->udp.length = clib_host_to_net_u16 (len0 +
1510                                                        sizeof (udp_header_t) +
1511                                                        sizeof
1512                                                        (gtpu_header_t));
1513
1514               clib_memcpy_fast (hdr0->ip6.src_address.as_u8, src0.as_u8,
1515                                 sizeof (ip6_address_t));
1516               clib_memcpy_fast (hdr0->ip6.dst_address.as_u8, &seg0.as_u8,
1517                                 sizeof (ip6_address_t));
1518
1519               hdr0->ip6.payload_length = clib_host_to_net_u16 (len0 +
1520                                                                sizeof
1521                                                                (udp_header_t)
1522                                                                +
1523                                                                sizeof
1524                                                                (gtpu_header_t));
1525
1526               // UDP source port.
1527               key = hash_memory (p, plen < 40 ? plen : 40, 0);
1528               port = hash_uword_to_u16 (&key);
1529               hdr0->udp.src_port = port;
1530
1531               good_n++;
1532
1533               if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
1534                   PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1535                 {
1536                   srv6_end_rewrite_trace_t *tr =
1537                     vlib_add_trace (vm, node, b0, sizeof (*tr));
1538                   clib_memcpy (tr->src.as_u8, hdr0->ip6.src_address.as_u8,
1539                                sizeof (ip6_address_t));
1540                   clib_memcpy (tr->dst.as_u8, hdr0->ip6.dst_address.as_u8,
1541                                sizeof (ip6_address_t));
1542                   tr->teid = hdr0->gtpu.teid;
1543                 }
1544             }
1545
1546           vlib_increment_combined_counter
1547             (((next0 ==
1548                SRV6_END_M_GTP6_E_NEXT_DROP) ? &(sm2->sr_ls_invalid_counters) :
1549               &(sm2->sr_ls_valid_counters)), thread_index,
1550              ls0 - sm2->localsids, 1, vlib_buffer_length_in_chain (vm, b0));
1551
1552           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1553                                            n_left_to_next, bi0, next0);
1554         }
1555
1556       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1557     }
1558
1559   vlib_node_increment_counter (vm, sm->end_m_gtp6_e_node_index,
1560                                SRV6_END_ERROR_M_GTP6_E_BAD_PACKETS, bad_n);
1561
1562   vlib_node_increment_counter (vm, sm->end_m_gtp6_e_node_index,
1563                                SRV6_END_ERROR_M_GTP6_E_PACKETS, good_n);
1564
1565   return frame->n_vectors;
1566 }
1567
1568 // Function for SRv6 GTP6.D function
1569 VLIB_NODE_FN (srv6_end_m_gtp6_d) (vlib_main_t * vm,
1570                                   vlib_node_runtime_t * node,
1571                                   vlib_frame_t * frame)
1572 {
1573   srv6_end_main_v6_decap_t *sm = &srv6_end_main_v6_decap;
1574   ip6_sr_main_t *sm2 = &sr_main;
1575   u32 n_left_from, next_index, *from, *to_next;
1576   u32 thread_index = vm->thread_index;
1577
1578   u32 good_n = 0, bad_n = 0;
1579
1580   from = vlib_frame_vector_args (frame);
1581   n_left_from = frame->n_vectors;
1582   next_index = node->cached_next_index;
1583
1584   while (n_left_from > 0)
1585     {
1586       u32 n_left_to_next;
1587
1588       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1589
1590       while (n_left_from > 0 && n_left_to_next > 0)
1591         {
1592           u32 bi0;
1593           vlib_buffer_t *b0;
1594           ip6_sr_localsid_t *ls0;
1595           srv6_end_gtp6_param_t *ls_param;
1596
1597           ip6_gtpu_header_t *hdr0 = NULL;
1598           uword len0;
1599
1600           ip6_address_t seg0, src0;
1601           u32 teid = 0;
1602           u8 *teidp;
1603           u8 gtpu_type = 0;
1604           u8 qfi;
1605           u8 *qfip = NULL;
1606           u16 seq = 0;
1607           u8 *seqp;
1608           u32 offset, shift;
1609           u32 hdrlen;
1610           ip6_header_t *encap = NULL;
1611           gtpu_pdu_session_t *sess = NULL;
1612           u16 ie_size = 0;
1613           u16 tlv_siz = 0;
1614           u8 ie_buf[GTPU_IE_MAX_SIZ];
1615
1616           u32 next0 = SRV6_END_M_GTP6_D_NEXT_LOOKUP;
1617
1618           // defaults
1619           bi0 = from[0];
1620           to_next[0] = bi0;
1621           from += 1;
1622           to_next += 1;
1623           n_left_from -= 1;
1624           n_left_to_next -= 1;
1625
1626           b0 = vlib_get_buffer (vm, bi0);
1627           ls0 =
1628             pool_elt_at_index (sm2->localsids,
1629                                vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1630
1631           ls_param = (srv6_end_gtp6_param_t *) ls0->plugin_mem;
1632
1633           hdr0 = vlib_buffer_get_current (b0);
1634
1635           hdrlen = sizeof (ip6_gtpu_header_t);
1636
1637           len0 = vlib_buffer_length_in_chain (vm, b0);
1638
1639           if ((hdr0->ip6.protocol != IP_PROTOCOL_UDP)
1640               || (hdr0->udp.dst_port !=
1641                   clib_host_to_net_u16 (SRV6_GTP_UDP_DST_PORT))
1642               || (len0 < sizeof (ip6_gtpu_header_t)))
1643             {
1644               next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
1645
1646               bad_n++;
1647             }
1648           else
1649             {
1650               seg0 = ls_param->sr_prefix;
1651               src0 = hdr0->ip6.src_address;
1652
1653               gtpu_type = hdr0->gtpu.type;
1654
1655               teid = hdr0->gtpu.teid;
1656               teidp = (u8 *) & teid;
1657
1658               seqp = (u8 *) & seq;
1659
1660               if (hdr0->gtpu.ver_flags & (GTPU_EXTHDR_FLAG | GTPU_SEQ_FLAG))
1661                 {
1662                   // Extention header.
1663                   hdrlen += sizeof (gtpu_exthdr_t);
1664
1665                   seq = hdr0->gtpu.ext->seq;
1666
1667                   if (hdr0->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
1668                     {
1669                       // PDU Session Container.
1670                       sess =
1671                         (gtpu_pdu_session_t *) (((char *) hdr0) +
1672                                                 sizeof (ip6_gtpu_header_t) +
1673                                                 sizeof (gtpu_exthdr_t));
1674                       qfi = sess->u.val & ~GTPU_PDU_SESSION_P_BIT_MASK;
1675                       qfip = (u8 *) & qfi;
1676
1677                       hdrlen += sizeof (gtpu_pdu_session_t);
1678
1679                       if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
1680                         {
1681                           hdrlen += sizeof (gtpu_paging_policy_t);
1682                         }
1683                     }
1684                 }
1685
1686               offset = ls_param->sr_prefixlen / 8;
1687               shift = ls_param->sr_prefixlen % 8;
1688
1689               offset += 1;
1690               if (PREDICT_TRUE (shift == 0))
1691                 {
1692                   if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1693                       || gtpu_type == GTPU_TYPE_ECHO_REPLY
1694                       || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1695                     {
1696                       clib_memcpy_fast (&seg0.as_u8[offset], seqp, 2);
1697                     }
1698                   else
1699                     {
1700                       clib_memcpy_fast (&seg0.as_u8[offset], teidp, 4);
1701                     }
1702
1703                   if (qfip)
1704                     {
1705                       qfi =
1706                         ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
1707                         ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
1708
1709                       if (sess->type)
1710                         {
1711                           qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
1712                         }
1713
1714                       seg0.as_u8[offset + 4] = qfi;
1715                     }
1716                 }
1717               else
1718                 {
1719                   int idx;
1720
1721                   if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1722                       || gtpu_type == GTPU_TYPE_ECHO_REPLY
1723                       || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1724                     {
1725                       for (idx = 0; idx < 2; idx++)
1726                         {
1727                           seg0.as_u8[offset + idx] |= seqp[idx] >> shift;
1728                           seg0.as_u8[offset + idx + 1] |=
1729                             seqp[idx] << (8 - shift);
1730                         }
1731                     }
1732                   else
1733                     {
1734                       for (idx = 0; idx < 4; idx++)
1735                         {
1736                           seg0.as_u8[offset + idx] |= teidp[idx] >> shift;
1737                           seg0.as_u8[offset + idx + 1] |=
1738                             teidp[idx] << (8 - shift);
1739                         }
1740                     }
1741
1742                   if (qfip)
1743                     {
1744                       qfi =
1745                         ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
1746                         ((qfi & ~GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
1747
1748                       if (sess->type)
1749                         {
1750                           qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
1751                         }
1752
1753                       seg0.as_u8[offset + 4] |= qfi >> shift;
1754                       seg0.as_u8[offset + 5] |= qfi << (8 - shift);
1755                     }
1756                 }
1757
1758               if (PREDICT_FALSE (gtpu_type == GTPU_TYPE_ERROR_INDICATION))
1759                 {
1760                   u16 payload_len;
1761
1762                   payload_len = clib_net_to_host_u16 (hdr0->gtpu.length);
1763                   if (payload_len != 0
1764                       && payload_len > hdrlen - sizeof (ip6_gtpu_header_t))
1765                     {
1766                       u8 *ies;
1767
1768                       ies = (u8 *) ((u8 *) hdr0 + hdrlen);
1769                       ie_size =
1770                         payload_len - (hdrlen - sizeof (ip6_gtpu_header_t));
1771                       clib_memcpy_fast (ie_buf, ies, ie_size);
1772                       hdrlen += ie_size;
1773                     }
1774                 }
1775
1776               // jump over variable length data
1777               vlib_buffer_advance (b0, (word) hdrlen);
1778
1779               // get length of encapsulated IPv6 packet (the remaining part)
1780               len0 = vlib_buffer_length_in_chain (vm, b0);
1781
1782               if (PREDICT_TRUE (gtpu_type == GTPU_TYPE_GTPU))
1783                 {
1784                   encap = vlib_buffer_get_current (b0);
1785                 }
1786
1787               uword *p;
1788               ip6srv_combo_header_t *ip6srv;
1789               ip6_sr_policy_t *sr_policy = NULL;
1790               ip6_sr_sl_t *sl = NULL;
1791               u32 *sl_index;
1792               u32 hdr_len;
1793
1794               p =
1795                 mhash_get (&sm2->sr_policies_index_hash,
1796                            &ls_param->sr_prefix);
1797               if (p)
1798                 {
1799                   sr_policy = pool_elt_at_index (sm2->sr_policies, p[0]);
1800                 }
1801
1802               if (sr_policy)
1803                 {
1804                   vec_foreach (sl_index, sr_policy->segments_lists)
1805                   {
1806                     sl = pool_elt_at_index (sm2->sid_lists, *sl_index);
1807                     if (sl != NULL)
1808                       break;
1809                   }
1810                 }
1811
1812               if (sl)
1813                 {
1814                   hdr_len = sizeof (ip6srv_combo_header_t);
1815                   hdr_len += vec_len (sl->segments) * sizeof (ip6_address_t);
1816                   hdr_len += sizeof (ip6_address_t);
1817                 }
1818               else
1819                 {
1820                   hdr_len = sizeof (ip6_header_t);
1821                   if (PREDICT_FALSE (gtpu_type) != GTPU_TYPE_GTPU)
1822                     {
1823                       hdr_len += sizeof (ip6_sr_header_t);
1824                       hdr_len += sizeof (ip6_address_t);
1825                     }
1826                 }
1827
1828               if (ie_size)
1829                 {
1830                   tlv_siz =
1831                     sizeof (ip6_sr_tlv_t) + sizeof (user_plane_sub_tlv_t) +
1832                     ie_size;
1833
1834                   tlv_siz = (tlv_siz & ~0x07) + (tlv_siz & 0x07 ? 0x08 : 0x0);
1835                   hdr_len += tlv_siz;
1836                 }
1837
1838               // jump back to data[0] or pre_data if required
1839               vlib_buffer_advance (b0, -(word) hdr_len);
1840
1841               ip6srv = vlib_buffer_get_current (b0);
1842
1843               if (sl)
1844                 {
1845                   clib_memcpy_fast (ip6srv, sl->rewrite,
1846                                     vec_len (sl->rewrite));
1847
1848                   if (vec_len (sl->segments) > 1)
1849                     {
1850                       ip6srv->ip.src_address = src0;
1851
1852                       ip6srv->sr.tag =
1853                         clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1854
1855                       ip6srv->sr.segments_left += 1;
1856                       ip6srv->sr.last_entry += 1;
1857
1858                       ip6srv->sr.length += sizeof (ip6_address_t) / 8;
1859                       ip6srv->sr.segments[0] = seg0;
1860
1861                       clib_memcpy_fast (&ip6srv->sr.segments[1],
1862                                         (u8 *) (sl->rewrite +
1863                                                 sizeof (ip6_header_t) +
1864                                                 sizeof (ip6_sr_header_t)),
1865                                         vec_len (sl->segments) *
1866                                         sizeof (ip6_address_t));
1867                     }
1868                   else
1869                     {
1870                       ip6srv->ip.src_address = src0;
1871                       ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
1872
1873                       ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
1874                       ip6srv->sr.segments_left = 1;
1875                       ip6srv->sr.last_entry = 0;
1876                       ip6srv->sr.length =
1877                         ((sizeof (ip6_sr_header_t) +
1878                           sizeof (ip6_address_t)) / 8) - 1;
1879                       ip6srv->sr.flags = 0;
1880
1881                       ip6srv->sr.tag =
1882                         clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1883
1884                       ip6srv->sr.segments[0] = seg0;
1885
1886                       if (vec_len (sl->segments))
1887                         {
1888                           ip6srv->sr.segments[1] = sl->segments[0];
1889                           ip6srv->sr.last_entry++;
1890                           ip6srv->sr.length += sizeof (ip6_address_t) / 8;
1891                         }
1892                     }
1893
1894                   if (PREDICT_TRUE (encap != NULL))
1895                     {
1896                       if (ls_param->nhtype == SRV6_NHTYPE_NONE)
1897                         {
1898                           if ((clib_net_to_host_u32
1899                                (encap->ip_version_traffic_class_and_flow_label)
1900                                >> 28) == 6)
1901                             ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
1902                           else
1903                             ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
1904                         }
1905                       else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
1906                         {
1907                           ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
1908                           if ((clib_net_to_host_u32
1909                                (encap->ip_version_traffic_class_and_flow_label)
1910                                >> 28) != 4)
1911                             {
1912                               // Bad encap packet.
1913                               next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
1914                               bad_n++;
1915                               goto DONE;
1916                             }
1917                         }
1918                       else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
1919                         {
1920                           ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
1921                           if ((clib_net_to_host_u32
1922                                (encap->ip_version_traffic_class_and_flow_label)
1923                                >> 28) != 6)
1924                             {
1925                               // Bad encap packet.
1926                               next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
1927                               bad_n++;
1928                               goto DONE;
1929                             }
1930                         }
1931                       else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
1932                         {
1933                           ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
1934                         }
1935                     }
1936                   else
1937                     {
1938                       ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
1939                     }
1940                 }
1941               else
1942                 {
1943                   clib_memcpy_fast (ip6srv, &sm->cache_hdr,
1944                                     sizeof (ip6_header_t));
1945
1946                   ip6srv->ip.src_address = src0;
1947                   ip6srv->ip.dst_address = seg0;
1948
1949                   if (PREDICT_FALSE (gtpu_type) != GTPU_TYPE_GTPU)
1950                     {
1951                       ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
1952
1953                       ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
1954
1955                       ip6srv->sr.tag =
1956                         clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1957
1958                       ip6srv->sr.segments_left = 0;
1959                       ip6srv->sr.last_entry = 0;
1960
1961                       ip6srv->sr.length = sizeof (ip6_address_t) / 8;
1962                       ip6srv->sr.segments[0] = seg0;
1963                     }
1964                   else
1965                     {
1966                       if (ls_param->nhtype == SRV6_NHTYPE_NONE)
1967                         {
1968                           if ((clib_net_to_host_u32
1969                                (encap->ip_version_traffic_class_and_flow_label)
1970                                >> 28) != 6)
1971                             ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
1972                         }
1973                       else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
1974                         {
1975                           ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
1976                           if ((clib_net_to_host_u32
1977                                (encap->ip_version_traffic_class_and_flow_label)
1978                                >> 28) != 4)
1979                             {
1980                               // Bad encap packet.
1981                               next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
1982                               bad_n++;
1983                               goto DONE;
1984                             }
1985                         }
1986                       else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
1987                         {
1988                           ip6srv->ip.protocol = IP_PROTOCOL_IPV6;
1989                           if ((clib_net_to_host_u32
1990                                (encap->ip_version_traffic_class_and_flow_label)
1991                                >> 28) != 6)
1992                             {
1993                               // Bad encap packet.
1994                               next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
1995                               bad_n++;
1996                               goto DONE;
1997                             }
1998                         }
1999                       else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
2000                         {
2001                           ip6srv->ip.protocol = IP_PROTOCOL_IP6_ETHERNET;
2002                         }
2003                     }
2004                 }
2005
2006               if (PREDICT_FALSE (ie_size))
2007                 {
2008                   ip6_sr_tlv_t *tlv;
2009                   user_plane_sub_tlv_t *sub_tlv;
2010
2011                   tlv =
2012                     (ip6_sr_tlv_t *) ((u8 *) ip6srv + (hdr_len - tlv_siz));
2013                   tlv->type = SRH_TLV_USER_PLANE_CONTAINER;
2014                   tlv->length = tlv_siz - sizeof (ip6_sr_tlv_t);
2015                   clib_memset (tlv->value, 0, tlv->length);
2016
2017                   sub_tlv = (user_plane_sub_tlv_t *) tlv->value;
2018                   sub_tlv->type = USER_PLANE_SUB_TLV_IE;
2019                   sub_tlv->length = ie_size;
2020                   clib_memcpy_fast (sub_tlv->value, ie_buf, ie_size);
2021
2022                   ip6srv->sr.length += tlv_siz / 8;
2023                 }
2024
2025               ip6srv->ip.payload_length =
2026                 clib_host_to_net_u16 (len0 + hdr_len - sizeof (ip6_header_t));
2027
2028               good_n++;
2029
2030               if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
2031                   PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2032                 {
2033                   srv6_end_rewrite_trace_t *tr =
2034                     vlib_add_trace (vm, node, b0, sizeof (*tr));
2035                   clib_memcpy (tr->src.as_u8, ip6srv->ip.src_address.as_u8,
2036                                sizeof (ip6_address_t));
2037                   clib_memcpy (tr->dst.as_u8, ip6srv->ip.dst_address.as_u8,
2038                                sizeof (ip6_address_t));
2039                   tr->teid = teid;
2040                   clib_memcpy (tr->sr_prefix.as_u8, ls_param->sr_prefix.as_u8,
2041                                sizeof (ip6_address_t));
2042                   tr->sr_prefixlen = ls_param->sr_prefixlen;
2043                 }
2044             }
2045
2046         DONE:
2047           vlib_increment_combined_counter
2048             (((next0 ==
2049                SRV6_END_M_GTP6_D_NEXT_DROP) ? &(sm2->sr_ls_invalid_counters) :
2050               &(sm2->sr_ls_valid_counters)), thread_index,
2051              ls0 - sm2->localsids, 1, vlib_buffer_length_in_chain (vm, b0));
2052
2053           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2054                                            n_left_to_next, bi0, next0);
2055         }
2056
2057       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2058     }
2059
2060   vlib_node_increment_counter (vm, sm->end_m_gtp6_d_node_index,
2061                                SRV6_END_ERROR_M_GTP6_D_BAD_PACKETS, bad_n);
2062
2063   vlib_node_increment_counter (vm, sm->end_m_gtp6_d_node_index,
2064                                SRV6_END_ERROR_M_GTP6_D_PACKETS, good_n);
2065
2066   return frame->n_vectors;
2067 }
2068
2069 // Function for SRv6 GTP6.D.DI function
2070 VLIB_NODE_FN (srv6_end_m_gtp6_d_di) (vlib_main_t * vm,
2071                                      vlib_node_runtime_t * node,
2072                                      vlib_frame_t * frame)
2073 {
2074   srv6_end_main_v6_decap_di_t *sm = &srv6_end_main_v6_decap_di;
2075   ip6_sr_main_t *sm2 = &sr_main;
2076   u32 n_left_from, next_index, *from, *to_next;
2077   u32 thread_index = vm->thread_index;
2078   srv6_end_gtp6_param_t *ls_param;
2079
2080   u32 good_n = 0, bad_n = 0;
2081
2082   from = vlib_frame_vector_args (frame);
2083   n_left_from = frame->n_vectors;
2084   next_index = node->cached_next_index;
2085
2086   while (n_left_from > 0)
2087     {
2088       u32 n_left_to_next;
2089
2090       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2091
2092       while (n_left_from > 0 && n_left_to_next > 0)
2093         {
2094           u32 bi0;
2095           vlib_buffer_t *b0;
2096           ip6_sr_localsid_t *ls0;
2097
2098           ip6_gtpu_header_t *hdr0 = NULL;
2099           uword len0;
2100
2101           ip6_address_t dst0;
2102           ip6_address_t src0;
2103           ip6_address_t seg0;
2104           u32 teid = 0;
2105           u8 *teidp;
2106           u8 gtpu_type = 0;
2107           u8 qfi = 0;
2108           u8 *qfip = NULL;
2109           u16 seq = 0;
2110           u8 *seqp;
2111           u32 offset, shift;
2112           u32 hdrlen;
2113           ip6_header_t *encap = NULL;
2114           gtpu_pdu_session_t *sess;
2115           u16 ie_size = 0;
2116           u16 tlv_siz = 0;
2117           u8 ie_buf[GTPU_IE_MAX_SIZ];
2118
2119           u32 next0 = SRV6_END_M_GTP6_D_DI_NEXT_LOOKUP;
2120
2121           // defaults
2122           bi0 = from[0];
2123           to_next[0] = bi0;
2124           from += 1;
2125           to_next += 1;
2126           n_left_from -= 1;
2127           n_left_to_next -= 1;
2128
2129           b0 = vlib_get_buffer (vm, bi0);
2130           ls0 =
2131             pool_elt_at_index (sm2->localsids,
2132                                vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
2133
2134           ls_param = (srv6_end_gtp6_param_t *) ls0->plugin_mem;
2135
2136           hdr0 = vlib_buffer_get_current (b0);
2137
2138           hdrlen = sizeof (ip6_gtpu_header_t);
2139
2140           len0 = vlib_buffer_length_in_chain (vm, b0);
2141
2142           if ((hdr0->ip6.protocol != IP_PROTOCOL_UDP)
2143               || (hdr0->udp.dst_port !=
2144                   clib_host_to_net_u16 (SRV6_GTP_UDP_DST_PORT))
2145               || (len0 < sizeof (ip6_gtpu_header_t)))
2146             {
2147               next0 = SRV6_END_M_GTP6_D_DI_NEXT_DROP;
2148
2149               bad_n++;
2150             }
2151           else
2152             {
2153               dst0 = hdr0->ip6.dst_address;
2154               src0 = hdr0->ip6.src_address;
2155
2156               gtpu_type = hdr0->gtpu.type;
2157
2158               seg0 = ls_param->sr_prefix;
2159               teid = hdr0->gtpu.teid;
2160               teidp = (u8 *) & teid;
2161
2162               seqp = (u8 *) & seq;
2163
2164               if (hdr0->gtpu.ver_flags & (GTPU_EXTHDR_FLAG | GTPU_SEQ_FLAG))
2165                 {
2166                   // Extention header.
2167                   hdrlen += sizeof (gtpu_exthdr_t);
2168
2169                   seq = hdr0->gtpu.ext->seq;
2170
2171                   if (hdr0->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
2172                     {
2173                       // PDU Session Container.
2174                       sess =
2175                         (gtpu_pdu_session_t *) (((char *) hdr0) + hdrlen);
2176                       qfi = sess->u.val & ~GTPU_PDU_SESSION_P_BIT_MASK;
2177                       qfip = &qfi;
2178
2179                       hdrlen += sizeof (gtpu_pdu_session_t);
2180
2181                       if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
2182                         {
2183                           hdrlen += sizeof (gtpu_paging_policy_t);
2184                         }
2185                     }
2186                 }
2187
2188               offset = ls_param->sr_prefixlen / 8;
2189               shift = ls_param->sr_prefixlen % 8;
2190
2191               offset += 1;
2192               if (PREDICT_TRUE (shift == 0))
2193                 {
2194                   if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
2195                       || gtpu_type == GTPU_TYPE_ECHO_REPLY
2196                       || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
2197                     {
2198                       clib_memcpy_fast (&seg0.as_u8[offset], seqp, 2);
2199                     }
2200                   else
2201                     {
2202                       clib_memcpy_fast (&seg0.as_u8[offset], teidp, 4);
2203                     }
2204
2205                   if (qfip)
2206                     {
2207                       qfi =
2208                         ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
2209                         ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
2210
2211                       if (sess->type)
2212                         {
2213                           qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
2214                         }
2215
2216                       seg0.as_u8[offset + 4] = qfi;
2217                     }
2218                 }
2219               else
2220                 {
2221                   int idx;
2222
2223                   if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
2224                       || gtpu_type == GTPU_TYPE_ECHO_REPLY
2225                       || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
2226                     {
2227                       for (idx = 0; idx < 2; idx++)
2228                         {
2229                           seg0.as_u8[offset + idx] |= seqp[idx] >> shift;
2230                           seg0.as_u8[offset + idx + 1] |=
2231                             seqp[idx] << (8 - shift);
2232                         }
2233                     }
2234                   else
2235                     {
2236                       for (idx = 0; idx < 4; idx++)
2237                         {
2238                           seg0.as_u8[offset + idx] |= teidp[idx] >> shift;
2239                           seg0.as_u8[offset + idx + 1] |=
2240                             teidp[idx] << (8 - shift);
2241                         }
2242                     }
2243
2244                   if (qfip)
2245                     {
2246                       qfi =
2247                         ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
2248                         ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
2249
2250                       if (sess->type)
2251                         {
2252                           qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
2253                         }
2254
2255                       seg0.as_u8[offset + 4] |= qfi >> shift;
2256                       seg0.as_u8[offset + 5] |= qfi << (8 - shift);
2257                     }
2258                 }
2259
2260               if (PREDICT_FALSE (gtpu_type == GTPU_TYPE_ERROR_INDICATION))
2261                 {
2262                   u16 payload_len;
2263
2264                   payload_len = clib_net_to_host_u16 (hdr0->gtpu.length);
2265                   if (payload_len != 0
2266                       && payload_len > hdrlen - sizeof (ip6_gtpu_header_t))
2267                     {
2268                       u8 *ies;
2269
2270                       ies = (u8 *) ((u8 *) hdr0 + hdrlen);
2271                       ie_size =
2272                         payload_len - (hdrlen - sizeof (ip6_gtpu_header_t));
2273                       clib_memcpy_fast (ie_buf, ies, ie_size);
2274                       hdrlen += ie_size;
2275                     }
2276                 }
2277
2278               // jump over variable length data
2279               vlib_buffer_advance (b0, (word) hdrlen);
2280
2281               // get length of encapsulated IPv6 packet (the remaining part)
2282               len0 = vlib_buffer_length_in_chain (vm, b0);
2283
2284               if (PREDICT_TRUE (gtpu_type == GTPU_TYPE_GTPU))
2285                 {
2286                   encap = vlib_buffer_get_current (b0);
2287                 }
2288
2289               uword *p;
2290               ip6srv_combo_header_t *ip6srv;
2291               ip6_sr_policy_t *sr_policy = NULL;
2292               ip6_sr_sl_t *sl = NULL;
2293               u32 *sl_index;
2294               u32 hdr_len;
2295
2296               p =
2297                 mhash_get (&sm2->sr_policies_index_hash,
2298                            &ls_param->sr_prefix);
2299               if (p)
2300                 {
2301                   sr_policy = pool_elt_at_index (sm2->sr_policies, p[0]);
2302                 }
2303
2304               if (sr_policy)
2305                 {
2306                   vec_foreach (sl_index, sr_policy->segments_lists)
2307                   {
2308                     sl = pool_elt_at_index (sm2->sid_lists, *sl_index);
2309                     if (sl != NULL)
2310                       break;
2311                   }
2312                 }
2313
2314               hdr_len = sizeof (ip6srv_combo_header_t);
2315
2316               if (sl)
2317                 hdr_len += vec_len (sl->segments) * sizeof (ip6_address_t);
2318
2319               hdr_len += sizeof (ip6_address_t) * 2;
2320
2321               if (ie_size)
2322                 {
2323                   tlv_siz =
2324                     sizeof (ip6_sr_tlv_t) + sizeof (user_plane_sub_tlv_t) +
2325                     ie_size;
2326
2327                   tlv_siz = (tlv_siz & ~0x07) + (tlv_siz & 0x07 ? 0x08 : 0x0);
2328                   hdr_len += tlv_siz;
2329                 }
2330
2331               // jump back to data[0] or pre_data if required
2332               vlib_buffer_advance (b0, -(word) hdr_len);
2333
2334               ip6srv = vlib_buffer_get_current (b0);
2335
2336               if (sl)
2337                 {
2338                   clib_memcpy_fast (ip6srv, sl->rewrite,
2339                                     vec_len (sl->rewrite));
2340
2341                   if (vec_len (sl->segments) > 1)
2342                     {
2343                       ip6srv->ip.src_address = src0;
2344
2345                       ip6srv->sr.tag =
2346                         clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
2347
2348                       ip6srv->sr.segments_left += 2;
2349                       ip6srv->sr.last_entry += 2;
2350
2351                       ip6srv->sr.length += ((sizeof (ip6_address_t) * 2) / 8);
2352
2353                       ip6srv->sr.segments[0] = dst0;
2354                       ip6srv->sr.segments[1] = seg0;
2355
2356                       clib_memcpy_fast (&ip6srv->sr.segments[2],
2357                                         (u8 *) (sl->rewrite +
2358                                                 sizeof (ip6_header_t) +
2359                                                 sizeof (ip6_sr_header_t)),
2360                                         vec_len (sl->segments) *
2361                                         sizeof (ip6_address_t));
2362                     }
2363                   else
2364                     {
2365                       ip6srv->ip.src_address = src0;
2366                       ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
2367
2368                       ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
2369                       ip6srv->sr.segments_left = 2;
2370                       ip6srv->sr.last_entry = 1;
2371                       ip6srv->sr.length =
2372                         ((sizeof (ip6_sr_header_t) +
2373                           2 * sizeof (ip6_address_t)) / 8) - 1;
2374                       ip6srv->sr.flags = 0;
2375
2376                       ip6srv->sr.tag =
2377                         clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
2378
2379                       ip6srv->sr.segments[0] = dst0;
2380                       ip6srv->sr.segments[1] = seg0;
2381
2382                       if (vec_len (sl->segments))
2383                         {
2384                           ip6srv->sr.segments[2] = sl->segments[0];
2385                           ip6srv->sr.last_entry++;
2386                           ip6srv->sr.length += sizeof (ip6_address_t) / 8;
2387                         }
2388                     }
2389                 }
2390               else
2391                 {
2392                   clib_memcpy_fast (ip6srv, &sm->cache_hdr,
2393                                     sizeof (ip6_header_t));
2394
2395                   ip6srv->ip.src_address = src0;
2396                   ip6srv->ip.dst_address = seg0;
2397
2398                   ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
2399                   ip6srv->sr.segments_left = 1;
2400                   ip6srv->sr.last_entry = 0;
2401                   ip6srv->sr.length =
2402                     ((sizeof (ip6_sr_header_t) +
2403                       sizeof (ip6_address_t)) / 8) - 1;
2404                   ip6srv->sr.flags = 0;
2405
2406                   ip6srv->sr.tag =
2407                     clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
2408
2409                   ip6srv->sr.segments[0] = dst0;
2410                 }
2411
2412               if (PREDICT_FALSE (ie_size))
2413                 {
2414                   ip6_sr_tlv_t *tlv;
2415                   user_plane_sub_tlv_t *sub_tlv;
2416
2417                   tlv =
2418                     (ip6_sr_tlv_t *) ((u8 *) ip6srv + (hdr_len - tlv_siz));
2419                   tlv->type = SRH_TLV_USER_PLANE_CONTAINER;
2420                   tlv->length = tlv_siz - sizeof (ip6_sr_tlv_t);
2421                   clib_memset (tlv->value, 0, tlv->length);
2422
2423                   sub_tlv = (user_plane_sub_tlv_t *) tlv->value;
2424                   sub_tlv->length = ie_size;
2425                   clib_memcpy_fast (sub_tlv->value, ie_buf, ie_size);
2426
2427                   ip6srv->sr.length += tlv_siz / 8;
2428                 }
2429
2430               ip6srv->ip.payload_length =
2431                 clib_host_to_net_u16 (len0 + hdr_len - sizeof (ip6_header_t));
2432               ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
2433
2434               if (PREDICT_TRUE (encap != NULL))
2435                 {
2436                   if (ls_param->nhtype == SRV6_NHTYPE_NONE)
2437                     {
2438                       if ((clib_net_to_host_u32
2439                            (encap->ip_version_traffic_class_and_flow_label) >>
2440                            28) == 6)
2441                         ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
2442                       else
2443                         ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
2444                     }
2445                   else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
2446                     {
2447                       ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
2448                       if ((clib_net_to_host_u32
2449                            (encap->ip_version_traffic_class_and_flow_label) >>
2450                            28) != 4)
2451                         {
2452                           // Bad encap packet.
2453                           next0 = SRV6_END_M_GTP6_D_DI_NEXT_DROP;
2454                           bad_n++;
2455                           goto DONE;
2456                         }
2457                     }
2458                   else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
2459                     {
2460                       ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
2461                       if ((clib_net_to_host_u32
2462                            (encap->ip_version_traffic_class_and_flow_label) >>
2463                            28) != 6)
2464                         {
2465                           // Bad encap packet.
2466                           next0 = SRV6_END_M_GTP6_D_DI_NEXT_DROP;
2467                           bad_n++;
2468                           goto DONE;
2469                         }
2470                     }
2471                   else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
2472                     {
2473                       ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
2474                     }
2475                 }
2476               else
2477                 {
2478                   ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
2479                 }
2480
2481               good_n++;
2482
2483               if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
2484                   PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2485                 {
2486                   srv6_end_rewrite_trace_t *tr =
2487                     vlib_add_trace (vm, node, b0, sizeof (*tr));
2488                   clib_memcpy (tr->src.as_u8, ip6srv->ip.src_address.as_u8,
2489                                sizeof (ip6_address_t));
2490                   clib_memcpy (tr->dst.as_u8, ip6srv->ip.dst_address.as_u8,
2491                                sizeof (ip6_address_t));
2492                   tr->teid = teid;
2493                   clib_memcpy (tr->sr_prefix.as_u8, ls_param->sr_prefix.as_u8,
2494                                sizeof (ip6_address_t));
2495                   tr->sr_prefixlen = ls_param->sr_prefixlen;
2496                 }
2497             }
2498
2499         DONE:
2500           vlib_increment_combined_counter
2501             (((next0 ==
2502                SRV6_END_M_GTP6_D_DI_NEXT_DROP) ?
2503               &(sm2->sr_ls_invalid_counters) : &(sm2->sr_ls_valid_counters)),
2504              thread_index, ls0 - sm2->localsids, 1,
2505              vlib_buffer_length_in_chain (vm, b0));
2506
2507           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2508                                            n_left_to_next, bi0, next0);
2509         }
2510
2511       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2512     }
2513
2514   vlib_node_increment_counter (vm, sm->end_m_gtp6_d_di_node_index,
2515                                SRV6_END_ERROR_M_GTP6_D_DI_BAD_PACKETS, bad_n);
2516
2517   vlib_node_increment_counter (vm, sm->end_m_gtp6_d_di_node_index,
2518                                SRV6_END_ERROR_M_GTP6_D_DI_PACKETS, good_n);
2519
2520   return frame->n_vectors;
2521 }
2522
2523 // Function for SRv6 GTP6.DT function
2524 VLIB_NODE_FN (srv6_end_m_gtp6_dt) (vlib_main_t * vm,
2525                                    vlib_node_runtime_t * node,
2526                                    vlib_frame_t * frame)
2527 {
2528   srv6_end_main_v6_dt_t *sm = &srv6_end_main_v6_dt;
2529   ip6_sr_main_t *sm2 = &sr_main;
2530   u32 n_left_from, next_index, *from, *to_next;
2531   u32 thread_index = vm->thread_index;
2532
2533   u32 good_n = 0, bad_n = 0;
2534
2535   from = vlib_frame_vector_args (frame);
2536   n_left_from = frame->n_vectors;
2537   next_index = node->cached_next_index;
2538
2539   while (n_left_from > 0)
2540     {
2541       u32 n_left_to_next;
2542
2543       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2544
2545       while (n_left_from > 0 && n_left_to_next > 0)
2546         {
2547           u32 bi0;
2548           vlib_buffer_t *b0;
2549           srv6_end_gtp6_dt_param_t *ls_param;
2550           ip6_sr_localsid_t *ls0;
2551
2552           ip6_gtpu_header_t *hdr0 = NULL;
2553           ip4_header_t *ip4 = NULL;
2554           ip6_header_t *ip6 = NULL;
2555           ip6_address_t src, dst;
2556           u32 teid;
2557           u32 hdrlen;
2558           u32 len0;
2559
2560           u32 next0 = SRV6_END_M_GTP6_DT_NEXT_DROP;
2561
2562           bi0 = from[0];
2563           to_next[0] = bi0;
2564           from += 1;
2565           to_next += 1;
2566           n_left_from -= 1;
2567           n_left_to_next -= 1;
2568
2569           b0 = vlib_get_buffer (vm, bi0);
2570           ls0 =
2571             pool_elt_at_index (sm2->localsids,
2572                                vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
2573
2574           ls_param = (srv6_end_gtp6_dt_param_t *) ls0->plugin_mem;
2575
2576           hdr0 = vlib_buffer_get_current (b0);
2577
2578           hdrlen = sizeof (ip6_gtpu_header_t);
2579
2580           len0 = vlib_buffer_length_in_chain (vm, b0);
2581
2582           if ((hdr0->ip6.protocol != IP_PROTOCOL_UDP)
2583               || (hdr0->udp.dst_port !=
2584                   clib_host_to_net_u16 (SRV6_GTP_UDP_DST_PORT))
2585               || (len0 < sizeof (ip6_gtpu_header_t)))
2586             {
2587               next0 = SRV6_END_M_GTP6_DT_NEXT_DROP;
2588
2589               bad_n++;
2590             }
2591           else
2592             {
2593               clib_memcpy_fast (src.as_u8, hdr0->ip6.src_address.as_u8,
2594                                 sizeof (ip6_address_t));
2595               clib_memcpy_fast (dst.as_u8, hdr0->ip6.dst_address.as_u8,
2596                                 sizeof (ip6_address_t));
2597
2598               teid = hdr0->gtpu.teid;
2599
2600               if (hdr0->gtpu.ver_flags & GTPU_EXTHDR_FLAG)
2601                 {
2602                   hdrlen += sizeof (gtpu_exthdr_t);
2603                   if (hdr0->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
2604                     {
2605                       gtpu_pdu_session_t *sess;
2606
2607                       sess =
2608                         (gtpu_pdu_session_t *) (((char *) hdr0) +
2609                                                 sizeof (ip6_gtpu_header_t) +
2610                                                 sizeof (gtpu_exthdr_t));
2611
2612                       hdrlen += sizeof (gtpu_pdu_session_t);
2613                       if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
2614                         {
2615                           hdrlen += sizeof (gtpu_paging_policy_t);
2616                         }
2617                     }
2618                 }
2619
2620               if (ls_param->type == SRV6_GTP6_DT4)
2621                 {
2622                   vlib_buffer_advance (b0, (word) hdrlen);
2623                   ip4 = vlib_buffer_get_current (b0);
2624                   if ((ip4->ip_version_and_header_length & 0xf0) != 0x40)
2625                     {
2626                       next0 = SRV6_END_M_GTP6_DT_NEXT_DROP;
2627                       bad_n++;
2628                       goto DONE;
2629                     }
2630
2631                   next0 = SRV6_END_M_GTP6_DT_NEXT_LOOKUP4;
2632                   vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2633                     ls_param->fib4_index;
2634                 }
2635               else if (ls_param->type == SRV6_GTP6_DT6)
2636                 {
2637                   ip6 = (ip6_header_t *) ((u8 *) hdr0 + hdrlen);
2638                   if ((clib_net_to_host_u32
2639                        (ip6->ip_version_traffic_class_and_flow_label) >> 28)
2640                       != 6)
2641                     {
2642                       next0 = SRV6_END_M_GTP6_DT_NEXT_DROP;
2643                       bad_n++;
2644                       goto DONE;
2645                     }
2646
2647                   next0 = SRV6_END_M_GTP6_DT_NEXT_LOOKUP6;
2648                   if ((ip6->dst_address.as_u8[0] == 0xff)
2649                       && ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80))
2650                     {
2651                       vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2652                         ls_param->local_fib_index;
2653                     }
2654                   else
2655                     {
2656                       vlib_buffer_advance (b0, (word) hdrlen);
2657                       vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2658                         ls_param->fib6_index;
2659                     }
2660                 }
2661               else if (ls_param->type == SRV6_GTP6_DT46)
2662                 {
2663                   ip6 = (ip6_header_t *) ((u8 *) hdr0 + hdrlen);
2664                   if ((clib_net_to_host_u32
2665                        (ip6->ip_version_traffic_class_and_flow_label) >> 28)
2666                       == 6)
2667                     {
2668                       next0 = SRV6_END_M_GTP6_DT_NEXT_LOOKUP6;
2669                       if ((ip6->dst_address.as_u8[0] == 0xff)
2670                           && ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80))
2671                         {
2672                           vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2673                             ls_param->local_fib_index;
2674                         }
2675                       else
2676                         {
2677                           vlib_buffer_advance (b0, (word) hdrlen);
2678                           vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2679                             ls_param->fib6_index;
2680                         }
2681                     }
2682                   else
2683                     if ((clib_net_to_host_u32
2684                          (ip6->ip_version_traffic_class_and_flow_label) >> 28)
2685                         == 4)
2686                     {
2687                       vlib_buffer_advance (b0, (word) hdrlen);
2688                       next0 = SRV6_END_M_GTP6_DT_NEXT_LOOKUP4;
2689                       vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2690                         ls_param->fib4_index;
2691                     }
2692                   else
2693                     {
2694                       next0 = SRV6_END_M_GTP6_DT_NEXT_DROP;
2695                       bad_n++;
2696                       goto DONE;
2697                     }
2698                 }
2699               else
2700                 {
2701                   next0 = SRV6_END_M_GTP6_DT_NEXT_DROP;
2702                   bad_n++;
2703                   goto DONE;
2704                 }
2705
2706               good_n++;
2707
2708               if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
2709                   PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2710                 {
2711                   srv6_end_rewrite_trace_t *tr =
2712                     vlib_add_trace (vm, node, b0, sizeof (*tr));
2713                   clib_memcpy (tr->src.as_u8, src.as_u8,
2714                                sizeof (ip6_address_t));
2715                   clib_memcpy (tr->dst.as_u8, dst.as_u8,
2716                                sizeof (ip6_address_t));
2717                   tr->teid = teid;
2718                 }
2719             }
2720
2721         DONE:
2722           vlib_increment_combined_counter
2723             (((next0 ==
2724                SRV6_END_M_GTP6_DT_NEXT_DROP) ? &(sm2->sr_ls_invalid_counters)
2725               : &(sm2->sr_ls_valid_counters)), thread_index,
2726              ls0 - sm2->localsids, 1, vlib_buffer_length_in_chain (vm, b0));
2727
2728           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2729                                            n_left_to_next, bi0, next0);
2730         }
2731
2732       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2733     }
2734
2735   vlib_node_increment_counter (vm, sm->end_m_gtp6_dt_node_index,
2736                                SRV6_END_ERROR_M_GTP6_DT_BAD_PACKETS, bad_n);
2737
2738   vlib_node_increment_counter (vm, sm->end_m_gtp6_dt_node_index,
2739                                SRV6_END_ERROR_M_GTP6_DT_PACKETS, good_n);
2740
2741   return frame->n_vectors;
2742 }
2743
2744 // Function for SRv6 GTP4.DT function
2745 VLIB_NODE_FN (srv6_t_m_gtp4_dt) (vlib_main_t * vm,
2746                                  vlib_node_runtime_t * node,
2747                                  vlib_frame_t * frame)
2748 {
2749   srv6_t_main_v4_dt_t *sm = &srv6_t_main_v4_dt;
2750   ip6_sr_main_t *sm2 = &sr_main;
2751   u32 n_left_from, next_index, *from, *to_next;
2752
2753   u32 good_n = 0, bad_n = 0;
2754
2755   from = vlib_frame_vector_args (frame);
2756   n_left_from = frame->n_vectors;
2757   next_index = node->cached_next_index;
2758
2759   while (n_left_from > 0)
2760     {
2761       u32 n_left_to_next;
2762
2763       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2764
2765       while (n_left_from > 0 && n_left_to_next > 0)
2766         {
2767           u32 bi0;
2768           vlib_buffer_t *b0;
2769           srv6_t_gtp4_dt_param_t *ls_param;
2770           ip6_sr_sl_t *ls0;
2771
2772           ip4_gtpu_header_t *hdr0 = NULL;
2773           ip4_header_t *ip4 = NULL;
2774           ip6_header_t *ip6 = NULL;
2775           ip6_address_t src, dst;
2776           u32 teid;
2777           u32 hdrlen;
2778           u32 len0;
2779
2780           u32 next0 = SRV6_T_M_GTP4_DT_NEXT_DROP;
2781
2782           bi0 = from[0];
2783           to_next[0] = bi0;
2784           from += 1;
2785           to_next += 1;
2786           n_left_from -= 1;
2787           n_left_to_next -= 1;
2788
2789           b0 = vlib_get_buffer (vm, bi0);
2790           ls0 =
2791             pool_elt_at_index (sm2->sid_lists,
2792                                vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
2793
2794           ls_param = (srv6_t_gtp4_dt_param_t *) ls0->plugin_mem;
2795
2796           hdr0 = vlib_buffer_get_current (b0);
2797
2798           hdrlen = sizeof (ip4_gtpu_header_t);
2799
2800           len0 = vlib_buffer_length_in_chain (vm, b0);
2801
2802           if ((hdr0->ip4.protocol != IP_PROTOCOL_UDP)
2803               || (hdr0->udp.dst_port !=
2804                   clib_host_to_net_u16 (SRV6_GTP_UDP_DST_PORT))
2805               || (len0 < sizeof (ip4_gtpu_header_t)))
2806             {
2807               next0 = SRV6_T_M_GTP4_DT_NEXT_DROP;
2808
2809               bad_n++;
2810             }
2811           else
2812             {
2813               clib_memcpy_fast (src.as_u8, hdr0->ip4.src_address.as_u8,
2814                                 sizeof (ip4_address_t));
2815               clib_memcpy_fast (dst.as_u8, hdr0->ip4.dst_address.as_u8,
2816                                 sizeof (ip4_address_t));
2817
2818               teid = hdr0->gtpu.teid;
2819
2820               if (hdr0->gtpu.ver_flags & GTPU_EXTHDR_FLAG)
2821                 {
2822                   hdrlen += sizeof (gtpu_exthdr_t);
2823                   if (hdr0->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
2824                     {
2825                       gtpu_pdu_session_t *sess;
2826
2827                       sess =
2828                         (gtpu_pdu_session_t *) (((char *) hdr0) +
2829                                                 sizeof (ip6_gtpu_header_t) +
2830                                                 sizeof (gtpu_exthdr_t));
2831
2832                       hdrlen += sizeof (gtpu_pdu_session_t);
2833                       if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
2834                         {
2835                           hdrlen += sizeof (gtpu_paging_policy_t);
2836                         }
2837                     }
2838                 }
2839
2840               if (ls_param->type == SRV6_GTP4_DT4)
2841                 {
2842                   vlib_buffer_advance (b0, (word) hdrlen);
2843                   ip4 = vlib_buffer_get_current (b0);
2844                   if ((ip4->ip_version_and_header_length & 0xf0) != 0x40)
2845                     {
2846                       next0 = SRV6_T_M_GTP4_DT_NEXT_DROP;
2847                       bad_n++;
2848                       goto DONE;
2849                     }
2850
2851                   next0 = SRV6_T_M_GTP4_DT_NEXT_LOOKUP4;
2852                   vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2853                     ls_param->fib4_index;
2854                 }
2855               else if (ls_param->type == SRV6_GTP4_DT6)
2856                 {
2857                   ip6 = (ip6_header_t *) ((u8 *) hdr0 + hdrlen);
2858                   if ((clib_net_to_host_u32
2859                        (ip6->ip_version_traffic_class_and_flow_label) >> 28)
2860                       != 6)
2861                     {
2862                       next0 = SRV6_T_M_GTP4_DT_NEXT_DROP;
2863                       bad_n++;
2864                       goto DONE;
2865                     }
2866
2867                   next0 = SRV6_T_M_GTP4_DT_NEXT_LOOKUP6;
2868                   if ((ip6->dst_address.as_u8[0] == 0xff)
2869                       && ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80))
2870                     {
2871                       next0 = SRV6_T_M_GTP4_DT_NEXT_LOOKUP4;
2872                       vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2873                         ls_param->local_fib_index;
2874                     }
2875                   else
2876                     {
2877                       vlib_buffer_advance (b0, (word) hdrlen);
2878                       vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2879                         ls_param->fib6_index;
2880                     }
2881                 }
2882               else if (ls_param->type == SRV6_GTP4_DT46)
2883                 {
2884                   ip6 = (ip6_header_t *) ((u8 *) hdr0 + hdrlen);
2885                   if ((clib_net_to_host_u32
2886                        (ip6->ip_version_traffic_class_and_flow_label) >> 28)
2887                       == 6)
2888                     {
2889                       next0 = SRV6_T_M_GTP4_DT_NEXT_LOOKUP6;
2890                       if ((ip6->dst_address.as_u8[0] == 0xff)
2891                           && ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80))
2892                         {
2893                           next0 = SRV6_T_M_GTP4_DT_NEXT_LOOKUP4;
2894                           vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2895                             ls_param->local_fib_index;
2896                         }
2897                       else
2898                         {
2899                           vlib_buffer_advance (b0, (word) hdrlen);
2900                           vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2901                             ls_param->fib6_index;
2902                         }
2903                     }
2904                   else
2905                     if ((clib_net_to_host_u32
2906                          (ip6->ip_version_traffic_class_and_flow_label) >> 28)
2907                         == 4)
2908                     {
2909                       vlib_buffer_advance (b0, (word) hdrlen);
2910                       next0 = SRV6_T_M_GTP4_DT_NEXT_LOOKUP4;
2911                       vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2912                         ls_param->fib4_index;
2913                     }
2914                   else
2915                     {
2916                       next0 = SRV6_T_M_GTP4_DT_NEXT_DROP;
2917                       bad_n++;
2918                       goto DONE;
2919                     }
2920                 }
2921               else
2922                 {
2923                   next0 = SRV6_T_M_GTP4_DT_NEXT_DROP;
2924                   bad_n++;
2925                   goto DONE;
2926                 }
2927
2928               good_n++;
2929
2930               if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
2931                   PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2932                 {
2933                   srv6_end_rewrite_trace_t *tr =
2934                     vlib_add_trace (vm, node, b0, sizeof (*tr));
2935                   clib_memcpy (tr->src.as_u8, src.as_u8,
2936                                sizeof (ip6_address_t));
2937                   clib_memcpy (tr->dst.as_u8, dst.as_u8,
2938                                sizeof (ip6_address_t));
2939                   tr->teid = teid;
2940                 }
2941             }
2942
2943         DONE:
2944           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2945                                            n_left_to_next, bi0, next0);
2946         }
2947
2948       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2949     }
2950
2951   vlib_node_increment_counter (vm, sm->t_m_gtp4_dt_node_index,
2952                                SRV6_T_ERROR_M_GTP4_DT_BAD_PACKETS, bad_n);
2953
2954   vlib_node_increment_counter (vm, sm->t_m_gtp4_dt_node_index,
2955                                SRV6_T_ERROR_M_GTP4_DT_PACKETS, good_n);
2956
2957   return frame->n_vectors;
2958 }
2959
2960 VLIB_REGISTER_NODE (srv6_end_m_gtp6_e) =
2961 {
2962   .name = "srv6-end-m-gtp6-e",.vector_size = sizeof (u32),.format_trace =
2963     format_srv6_end_rewrite_trace6,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
2964     ARRAY_LEN (srv6_end_error_v6_e_strings),.error_strings =
2965     srv6_end_error_v6_e_strings,.n_next_nodes =
2966     SRV6_END_M_GTP6_E_N_NEXT,.next_nodes =
2967   {
2968   [SRV6_END_M_GTP6_E_NEXT_DROP] =
2969       "error-drop",[SRV6_END_M_GTP6_E_NEXT_LOOKUP] = "ip6-lookup",}
2970 ,};
2971
2972 VLIB_REGISTER_NODE (srv6_end_m_gtp6_d) =
2973 {
2974   .name = "srv6-end-m-gtp6-d",.vector_size = sizeof (u32),.format_trace =
2975     format_srv6_end_rewrite_trace6,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
2976     ARRAY_LEN (srv6_end_error_v6_d_strings),.error_strings =
2977     srv6_end_error_v6_d_strings,.n_next_nodes =
2978     SRV6_END_M_GTP6_D_N_NEXT,.next_nodes =
2979   {
2980   [SRV6_END_M_GTP6_D_NEXT_DROP] =
2981       "error-drop",[SRV6_END_M_GTP6_D_NEXT_LOOKUP] = "ip6-lookup",}
2982 ,};
2983
2984 VLIB_REGISTER_NODE (srv6_end_m_gtp6_d_di) =
2985 {
2986   .name = "srv6-end-m-gtp6-d-di",.vector_size = sizeof (u32),.format_trace =
2987     format_srv6_end_rewrite_trace6,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
2988     ARRAY_LEN (srv6_end_error_v6_d_di_strings),.error_strings =
2989     srv6_end_error_v6_d_di_strings,.n_next_nodes =
2990     SRV6_END_M_GTP6_D_DI_N_NEXT,.next_nodes =
2991   {
2992   [SRV6_END_M_GTP6_D_DI_NEXT_DROP] = "error-drop",
2993       [SRV6_END_M_GTP6_D_DI_NEXT_LOOKUP] = "ip6-lookup",}
2994 ,};
2995
2996 VLIB_REGISTER_NODE (srv6_end_m_gtp6_dt) =
2997 {
2998   .name = "srv6-end-m-gtp6-dt",.vector_size = sizeof (u32),.format_trace =
2999     format_srv6_end_rewrite_trace6,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
3000     ARRAY_LEN (srv6_end_error_v6_dt_strings),.error_strings =
3001     srv6_end_error_v6_dt_strings,.n_next_nodes =
3002     SRV6_END_M_GTP6_DT_N_NEXT,.next_nodes =
3003   {
3004   [SRV6_END_M_GTP6_DT_NEXT_DROP] =
3005       "error-drop",
3006       [SRV6_END_M_GTP6_DT_NEXT_LOOKUP4]
3007       = "ip4-lookup",[SRV6_END_M_GTP6_DT_NEXT_LOOKUP6] = "ip6-lookup",}
3008 ,};
3009
3010 VLIB_REGISTER_NODE (srv6_t_m_gtp4_dt) =
3011 {
3012   .name = "srv6-t-m-gtp4-dt",.vector_size = sizeof (u32),.format_trace =
3013     format_srv6_end_rewrite_trace6,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
3014     ARRAY_LEN (srv6_t_error_v4_dt_strings),.error_strings =
3015     srv6_t_error_v4_dt_strings,.n_next_nodes =
3016     SRV6_T_M_GTP4_DT_N_NEXT,.next_nodes =
3017   {
3018   [SRV6_T_M_GTP4_DT_NEXT_DROP] =
3019       "error-drop",
3020       [SRV6_T_M_GTP4_DT_NEXT_LOOKUP4] =
3021       "ip4-lookup",[SRV6_T_M_GTP4_DT_NEXT_LOOKUP6] = "ip6-lookup",}
3022 ,};
3023
3024 /*
3025 * fd.io coding-style-patch-verification: ON
3026 *
3027 * Local Variables:
3028 * eval: (c-set-style "gnu")
3029 * End:
3030 */