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