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