FD.io VPP  v20.05-21-gb1500e9ff
Vector Packet Processing
node.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 Arrcus Inc and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <vlib/vlib.h>
16 #include <vnet/vnet.h>
17 #include <vppinfra/error.h>
18 #include <vppinfra/hash.h>
19 #include <srv6-mobile/mobile.h>
20 
21 extern ip6_address_t sr_pr_encaps_src;
22 
23 typedef struct
24 {
25  ip6_address_t src, dst;
26  ip6_address_t sr_prefix;
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 *);
92 
93  return format (s, "SRv6-END-rewrite: src %U dst %U\n\tTEID: 0x%x",
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",
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,
144 #undef _
147 
148 typedef enum
149 {
150 #define _(sym,str) SRV6_T_ERROR_##sym,
152 #undef _
155 
156 typedef enum
157 {
158 #define _(sym,str) SRV6_END_ERROR_##sym,
160 #undef _
163 
164 typedef enum
165 {
166 #define _(sym,str) SRV6_END_ERROR_##sym,
168 #undef _
171 
172 typedef enum
173 {
174 #define _(sym,str) SRV6_END_ERROR_##sym,
176 #undef _
179 
180 typedef enum
181 {
182 #define _(sym,str) SRV6_END_ERROR_##sym,
184 #undef _
187 
188 typedef enum
189 {
190 #define _(sym,str) SRV6_T_ERROR_##sym,
192 #undef _
195 
196 static char *srv6_end_error_v4_strings[] = {
197 #define _(sym,string) string,
199 #undef _
200 };
201 
202 static char *srv6_t_error_v4_d_strings[] = {
203 #define _(sym,string) string,
205 #undef _
206 };
207 
208 static char *srv6_end_error_v6_e_strings[] = {
209 #define _(sym,string) string,
211 #undef _
212 };
213 
214 static char *srv6_end_error_v6_d_strings[] = {
215 #define _(sym,string) string,
217 #undef _
218 };
219 
221 #define _(sym,string) string,
223 #undef _
224 };
225 
227 #define _(sym,string) string,
229 #undef _
230 };
231 
232 static char *srv6_t_error_v4_dt_strings[] = {
233 #define _(sym,string) string,
235 #undef _
236 };
237 
238 typedef enum
239 {
244 
245 typedef enum
246 {
251 
252 typedef enum
253 {
258 
259 typedef enum
260 {
265 
266 typedef enum
267 {
272 
273 typedef enum
274 {
280 
281 typedef enum
282 {
288 
289 static inline u16
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
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)
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.
323 {
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 
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 =
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  {
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 
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  {
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 
558 
559  hdr0->gtpu.ext->seq = 0;
560 
561  hdr0->gtpu.ext->npdu_num = 0;
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
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  {
656  vlib_add_trace (vm, node, b0, sizeof (*tr));
657  clib_memcpy (tr->src.as_u8, hdr0->ip4.src_address.as_u8,
658  sizeof (tr->src.as_u8));
659  clib_memcpy (tr->dst.as_u8, hdr0->ip4.dst_address.as_u8,
660  sizeof (tr->dst.as_u8));
661  tr->teid = hdr0->gtpu.teid;
662  }
663  }
664 
666  (((next0 ==
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 
679  SRV6_END_ERROR_M_GTP4_E_BAD_PACKETS, bad_n);
680 
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.
691 {
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 
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 =
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  {
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;
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 
788  {
789  // Extention header.
790  hdr_len += sizeof (gtpu_exthdr_t);
791 
792  seq = hdr->gtpu.ext->seq;
793 
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  {
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  {
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 =
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
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
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
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  {
1085  }
1086  }
1087  else
1088  {
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 
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
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
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
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  {
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));
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  {
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 
1205  SRV6_T_ERROR_M_GTP4_D_BAD_PACKETS, bad_n);
1206 
1208  SRV6_T_ERROR_M_GTP4_D_PACKETS, good_n);
1209 
1210  return frame->n_vectors;
1211 }
1212 
1214 {
1215  .name = "srv6-end-m-gtp4-e",.vector_size = sizeof (u32),.format_trace =
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  {
1222  "error-drop",[SRV6_END_M_GTP4_E_NEXT_LOOKUP] = "ip4-lookup",}
1223 ,};
1224 
1226 {
1227  .name = "srv6-t-m-gtp4-d",.vector_size = sizeof (u32),.format_trace =
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  {
1234  "error-drop",[SRV6_T_M_GTP4_D_NEXT_LOOKUP] = "ip6-lookup",}
1235 ,};
1236 
1237 // Function for SRv6 GTP6.E function
1240  vlib_frame_t * frame)
1241 {
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 
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 =
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  {
1305 
1306  bad_n++;
1307  }
1308  else
1309  {
1310  // we need to be sure there is enough space before
1311  // ip6srv0 header, there is some extra space
1312  // in the pre_data area for this kind of
1313  // logic
1314 
1315  u32 teid = 0;
1316  u8 *teid8p = (u8 *) & teid;
1317  u8 qfi = 0;
1318  u16 seq = 0;
1319  u8 gtpu_type = 0;
1320  u16 index;
1321  u16 offset, shift;
1322  u32 hdrlen = 0;
1323  u16 ie_size = 0;
1324  u8 ie_buf[GTPU_IE_MAX_SIZ];
1325 
1326  index = ls0->localsid_prefix_len;
1327  index += 8;
1328  offset = index / 8;
1329  shift = index % 8;
1330 
1331  gtpu_type = gtpu_type_get (tag);
1332 
1333  if (PREDICT_TRUE (shift == 0))
1334  {
1335  if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1336  || gtpu_type == GTPU_TYPE_ECHO_REPLY
1337  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1338  {
1339  clib_memcpy_fast (&seq, &dst0.as_u8[offset], 2);
1340  }
1341  else
1342  {
1343  clib_memcpy_fast (teid8p, &dst0.as_u8[offset], 4);
1344  }
1345 
1346  qfi = dst0.as_u8[offset + 4];
1347  }
1348  else
1349  {
1350  u8 *sp;
1351 
1352  if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1353  || gtpu_type == GTPU_TYPE_ECHO_REPLY
1354  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1355  {
1356  sp = (u8 *) & seq;
1357  for (index = 0; index < 2; index++)
1358  {
1359  sp[index] = dst0.as_u8[offset + index] << shift;
1360  sp[index] |=
1361  dst0.as_u8[offset + index + 1] >> (8 - shift);
1362  }
1363  }
1364  else
1365  {
1366  for (index = 0; index < 4; index++)
1367  {
1368  *teid8p = dst0.as_u8[offset + index] << shift;
1369  *teid8p |=
1370  dst0.as_u8[offset + index + 1] >> (8 - shift);
1371  teid8p++;
1372  }
1373  }
1374 
1375  qfi |= dst0.as_u8[offset + 4] << shift;
1376  qfi |= dst0.as_u8[offset + 5] >> (8 - shift);
1377  }
1378 
1379  if (qfi)
1380  {
1381  hdrlen =
1382  sizeof (gtpu_exthdr_t) + sizeof (gtpu_pdu_session_t);
1383  }
1384  else if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1385  || gtpu_type == GTPU_TYPE_ECHO_REPLY
1386  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1387  {
1388  hdrlen = sizeof (gtpu_exthdr_t);
1389  }
1390 
1391  if (gtpu_type == GTPU_TYPE_ECHO_REPLY)
1392  {
1393  hdrlen += sizeof (gtpu_recovery_ie);
1394  }
1395 
1396  if (PREDICT_FALSE (gtpu_type == GTPU_TYPE_ERROR_INDICATION))
1397  {
1398  ip6_sr_tlv_t *tlv;
1399  u16 ext_len;
1400 
1401  ext_len = ip6srv0->sr.length * 8;
1402 
1403  if (ext_len >
1404  sizeof (ip6_address_t) * (ip6srv0->sr.last_entry + 1))
1405  {
1406  tlv =
1407  (ip6_sr_tlv_t *) ((u8 *) & ip6srv0->sr +
1408  sizeof (ip6_sr_header_t) +
1409  sizeof (ip6_address_t) *
1410  (ip6srv0->sr.last_entry + 1));
1411 
1412  if (tlv->type == SRH_TLV_USER_PLANE_CONTAINER)
1413  {
1414  user_plane_sub_tlv_t *sub_tlv;
1415 
1416  sub_tlv = (user_plane_sub_tlv_t *) tlv->value;
1417 
1418  ie_size = sub_tlv->length;
1419  clib_memcpy_fast (ie_buf, sub_tlv->value, ie_size);
1420 
1421  hdrlen += ie_size;
1422  }
1423  }
1424  }
1425 
1426  vlib_buffer_advance (b0,
1427  (word) sizeof (ip6srv_combo_header_t) +
1428  ip6srv0->sr.length * 8);
1429 
1430  // get length of encapsulated IPv6 packet (the remaining part)
1431  p = vlib_buffer_get_current (b0);
1432 
1433  plen = len0 = vlib_buffer_length_in_chain (vm, b0);
1434 
1435  len0 += hdrlen;
1436 
1437  hdrlen += sizeof (ip6_gtpu_header_t);
1438 
1439  vlib_buffer_advance (b0, -(word) hdrlen);
1440 
1441  hdr0 = vlib_buffer_get_current (b0);
1442 
1443  clib_memcpy_fast (hdr0, &sm->cache_hdr,
1444  sizeof (ip6_gtpu_header_t));
1445 
1446  hdr0->gtpu.teid = teid;
1447  hdr0->gtpu.length = clib_host_to_net_u16 (len0);
1448 
1449  hdr0->gtpu.type = gtpu_type;
1450 
1451  if (qfi)
1452  {
1453  u8 type = 0;
1454  gtpu_pdu_session_t *sess;
1455 
1456  hdr0->gtpu.ver_flags |= GTPU_EXTHDR_FLAG;
1457 
1458  hdr0->gtpu.ext->seq = 0;
1459  hdr0->gtpu.ext->npdu_num = 0;
1461 
1462  type = qfi & SRV6_PDU_SESSION_U_BIT_MASK;
1463 
1464  qfi =
1465  ((qfi & SRV6_PDU_SESSION_QFI_MASK) >> 2) |
1466  ((qfi & SRV6_PDU_SESSION_R_BIT_MASK) << 5);
1467 
1468  sess =
1469  (gtpu_pdu_session_t *) (((char *) hdr0) +
1470  sizeof (ip6_gtpu_header_t) +
1471  sizeof (gtpu_exthdr_t));
1472  sess->exthdrlen = 1;
1473  sess->type = type;
1474  sess->spare = 0;
1475  sess->u.val = qfi;
1476  sess->nextexthdr = 0;
1477  }
1478 
1479  if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1480  || gtpu_type == GTPU_TYPE_ECHO_REPLY
1481  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1482  {
1483  hdr0->gtpu.ver_flags |= GTPU_SEQ_FLAG;
1484  hdr0->gtpu.ext->seq = seq;
1485  hdr0->gtpu.ext->npdu_num = 0;
1486  hdr0->gtpu.ext->nextexthdr = 0;
1487 
1488  if (gtpu_type == GTPU_TYPE_ECHO_REPLY)
1489  {
1490  gtpu_recovery_ie *recovery;
1491 
1492  recovery =
1493  (gtpu_recovery_ie *) ((u8 *) hdr0 +
1494  (hdrlen -
1495  sizeof (gtpu_recovery_ie)));
1496  recovery->type = GTPU_RECOVERY_IE_TYPE;
1497  recovery->restart_counter = 0;
1498  }
1499  else if (gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1500  {
1501  if (ie_size)
1502  {
1503  u8 *ie_ptr;
1504 
1505  ie_ptr = (u8 *) ((u8 *) hdr0 + (hdrlen - ie_size));
1506  clib_memcpy_fast (ie_ptr, ie_buf, ie_size);
1507  }
1508  }
1509  }
1510 
1511  hdr0->udp.length = clib_host_to_net_u16 (len0 +
1512  sizeof (udp_header_t) +
1513  sizeof
1514  (gtpu_header_t));
1515 
1516  clib_memcpy_fast (hdr0->ip6.src_address.as_u8, src0.as_u8,
1517  sizeof (ip6_address_t));
1518  clib_memcpy_fast (hdr0->ip6.dst_address.as_u8, &seg0.as_u8,
1519  sizeof (ip6_address_t));
1520 
1521  hdr0->ip6.payload_length = clib_host_to_net_u16 (len0 +
1522  sizeof
1523  (udp_header_t)
1524  +
1525  sizeof
1526  (gtpu_header_t));
1527 
1528  // UDP source port.
1529  key = hash_memory (p, plen < 40 ? plen : 40, 0);
1530  port = hash_uword_to_u16 (&key);
1531  hdr0->udp.src_port = port;
1532 
1533  good_n++;
1534 
1535  if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
1536  PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1537  {
1539  vlib_add_trace (vm, node, b0, sizeof (*tr));
1540  clib_memcpy (tr->src.as_u8, hdr0->ip6.src_address.as_u8,
1541  sizeof (ip6_address_t));
1542  clib_memcpy (tr->dst.as_u8, hdr0->ip6.dst_address.as_u8,
1543  sizeof (ip6_address_t));
1544  tr->teid = hdr0->gtpu.teid;
1545  }
1546  }
1547 
1549  (((next0 ==
1551  &(sm2->sr_ls_valid_counters)), thread_index,
1552  ls0 - sm2->localsids, 1, vlib_buffer_length_in_chain (vm, b0));
1553 
1554  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1555  n_left_to_next, bi0, next0);
1556  }
1557 
1558  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1559  }
1560 
1562  SRV6_END_ERROR_M_GTP6_E_BAD_PACKETS, bad_n);
1563 
1565  SRV6_END_ERROR_M_GTP6_E_PACKETS, good_n);
1566 
1567  return frame->n_vectors;
1568 }
1569 
1570 // Function for SRv6 GTP6.D function
1573  vlib_frame_t * frame)
1574 {
1576  ip6_sr_main_t *sm2 = &sr_main;
1577  u32 n_left_from, next_index, *from, *to_next;
1578  u32 thread_index = vm->thread_index;
1579 
1580  u32 good_n = 0, bad_n = 0;
1581 
1582  from = vlib_frame_vector_args (frame);
1583  n_left_from = frame->n_vectors;
1584  next_index = node->cached_next_index;
1585 
1586  while (n_left_from > 0)
1587  {
1588  u32 n_left_to_next;
1589 
1590  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1591 
1592  while (n_left_from > 0 && n_left_to_next > 0)
1593  {
1594  u32 bi0;
1595  vlib_buffer_t *b0;
1596  ip6_sr_localsid_t *ls0;
1597  srv6_end_gtp6_param_t *ls_param;
1598 
1599  ip6_gtpu_header_t *hdr0 = NULL;
1600  uword len0;
1601 
1602  ip6_address_t seg0, src0;
1603  u32 teid = 0;
1604  u8 *teidp;
1605  u8 gtpu_type = 0;
1606  u8 qfi;
1607  u8 *qfip = NULL;
1608  u16 seq = 0;
1609  u8 *seqp;
1610  u32 offset, shift;
1611  u32 hdrlen;
1612  ip6_header_t *encap = NULL;
1613  gtpu_pdu_session_t *sess = NULL;
1614  int ie_size = 0;
1615  u16 tlv_siz = 0;
1616  u8 ie_buf[GTPU_IE_MAX_SIZ];
1617 
1619 
1620  // defaults
1621  bi0 = from[0];
1622  to_next[0] = bi0;
1623  from += 1;
1624  to_next += 1;
1625  n_left_from -= 1;
1626  n_left_to_next -= 1;
1627 
1628  b0 = vlib_get_buffer (vm, bi0);
1629  ls0 =
1631  vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1632 
1633  ls_param = (srv6_end_gtp6_param_t *) ls0->plugin_mem;
1634 
1635  hdr0 = vlib_buffer_get_current (b0);
1636 
1637  hdrlen = sizeof (ip6_gtpu_header_t);
1638 
1639  len0 = vlib_buffer_length_in_chain (vm, b0);
1640 
1641  if ((hdr0->ip6.protocol != IP_PROTOCOL_UDP)
1642  || (hdr0->udp.dst_port !=
1643  clib_host_to_net_u16 (SRV6_GTP_UDP_DST_PORT))
1644  || (len0 < sizeof (ip6_gtpu_header_t)))
1645  {
1647 
1648  bad_n++;
1649  }
1650  else
1651  {
1652  seg0 = ls_param->sr_prefix;
1653  src0 = hdr0->ip6.src_address;
1654 
1655  gtpu_type = hdr0->gtpu.type;
1656 
1657  teid = hdr0->gtpu.teid;
1658  teidp = (u8 *) & teid;
1659 
1660  seqp = (u8 *) & seq;
1661 
1662  if (hdr0->gtpu.ver_flags & (GTPU_EXTHDR_FLAG | GTPU_SEQ_FLAG))
1663  {
1664  // Extention header.
1665  hdrlen += sizeof (gtpu_exthdr_t);
1666 
1667  seq = hdr0->gtpu.ext->seq;
1668 
1670  {
1671  // PDU Session Container.
1672  sess =
1673  (gtpu_pdu_session_t *) (((char *) hdr0) +
1674  sizeof (ip6_gtpu_header_t) +
1675  sizeof (gtpu_exthdr_t));
1676  qfi = sess->u.val & ~GTPU_PDU_SESSION_P_BIT_MASK;
1677  qfip = (u8 *) & qfi;
1678 
1679  hdrlen += sizeof (gtpu_pdu_session_t);
1680 
1681  if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
1682  {
1683  hdrlen += sizeof (gtpu_paging_policy_t);
1684  }
1685  }
1686  }
1687 
1688  offset = ls_param->sr_prefixlen / 8;
1689  shift = ls_param->sr_prefixlen % 8;
1690 
1691  offset += 1;
1692  if (PREDICT_TRUE (shift == 0))
1693  {
1694  if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1695  || gtpu_type == GTPU_TYPE_ECHO_REPLY
1696  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1697  {
1698  clib_memcpy_fast (&seg0.as_u8[offset], seqp, 2);
1699  }
1700  else
1701  {
1702  clib_memcpy_fast (&seg0.as_u8[offset], teidp, 4);
1703  }
1704 
1705  if (qfip)
1706  {
1707  qfi =
1708  ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
1709  ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
1710 
1711  if (sess->type)
1712  {
1714  }
1715 
1716  seg0.as_u8[offset + 4] = qfi;
1717  }
1718  }
1719  else
1720  {
1721  int idx;
1722 
1723  if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1724  || gtpu_type == GTPU_TYPE_ECHO_REPLY
1725  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1726  {
1727  for (idx = 0; idx < 2; idx++)
1728  {
1729  seg0.as_u8[offset + idx] |= seqp[idx] >> shift;
1730  seg0.as_u8[offset + idx + 1] |=
1731  seqp[idx] << (8 - shift);
1732  }
1733  }
1734  else
1735  {
1736  for (idx = 0; idx < 4; idx++)
1737  {
1738  seg0.as_u8[offset + idx] |= teidp[idx] >> shift;
1739  seg0.as_u8[offset + idx + 1] |=
1740  teidp[idx] << (8 - shift);
1741  }
1742  }
1743 
1744  if (qfip)
1745  {
1746  qfi =
1747  ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
1748  ((qfi & ~GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
1749 
1750  if (sess->type)
1751  {
1753  }
1754 
1755  seg0.as_u8[offset + 4] |= qfi >> shift;
1756  seg0.as_u8[offset + 5] |= qfi << (8 - shift);
1757  }
1758  }
1759 
1760  if (PREDICT_FALSE (gtpu_type == GTPU_TYPE_ERROR_INDICATION))
1761  {
1762  u16 payload_len;
1763 
1764  payload_len = clib_net_to_host_u16 (hdr0->gtpu.length);
1765  if (payload_len != 0)
1766  {
1767  ie_size =
1768  payload_len - (hdrlen - sizeof (ip6_gtpu_header_t));
1769  if (ie_size > 0)
1770  {
1771  u8 *ies;
1772 
1773  ies = (u8 *) ((u8 *) hdr0 + hdrlen);
1774  clib_memcpy_fast (ie_buf, ies, ie_size);
1775  hdrlen += ie_size;
1776  }
1777  }
1778  }
1779 
1780  // jump over variable length data
1781  vlib_buffer_advance (b0, (word) hdrlen);
1782 
1783  // get length of encapsulated IPv6 packet (the remaining part)
1784  len0 = vlib_buffer_length_in_chain (vm, b0);
1785 
1786  if (PREDICT_TRUE (gtpu_type == GTPU_TYPE_GTPU))
1787  {
1788  encap = vlib_buffer_get_current (b0);
1789  }
1790 
1791  uword *p;
1792  ip6srv_combo_header_t *ip6srv;
1793  ip6_sr_policy_t *sr_policy = NULL;
1794  ip6_sr_sl_t *sl = NULL;
1795  u32 *sl_index;
1796  u32 hdr_len;
1797 
1798  p =
1800  &ls_param->sr_prefix);
1801  if (p)
1802  {
1803  sr_policy = pool_elt_at_index (sm2->sr_policies, p[0]);
1804  }
1805 
1806  if (sr_policy)
1807  {
1808  vec_foreach (sl_index, sr_policy->segments_lists)
1809  {
1810  sl = pool_elt_at_index (sm2->sid_lists, *sl_index);
1811  if (sl != NULL)
1812  break;
1813  }
1814  }
1815 
1816  if (sl)
1817  {
1818  hdr_len = sizeof (ip6srv_combo_header_t);
1819  hdr_len += vec_len (sl->segments) * sizeof (ip6_address_t);
1820  hdr_len += sizeof (ip6_address_t);
1821  }
1822  else
1823  {
1824  hdr_len = sizeof (ip6_header_t);
1825  if (PREDICT_FALSE (gtpu_type) != GTPU_TYPE_GTPU)
1826  {
1827  hdr_len += sizeof (ip6_sr_header_t);
1828  hdr_len += sizeof (ip6_address_t);
1829  }
1830  }
1831 
1832  if (ie_size)
1833  {
1834  tlv_siz =
1835  sizeof (ip6_sr_tlv_t) + sizeof (user_plane_sub_tlv_t) +
1836  ie_size;
1837 
1838  tlv_siz = (tlv_siz & ~0x07) + (tlv_siz & 0x07 ? 0x08 : 0x0);
1839  hdr_len += tlv_siz;
1840  }
1841 
1842  // jump back to data[0] or pre_data if required
1843  vlib_buffer_advance (b0, -(word) hdr_len);
1844 
1845  ip6srv = vlib_buffer_get_current (b0);
1846 
1847  if (sl)
1848  {
1849  clib_memcpy_fast (ip6srv, sl->rewrite,
1850  vec_len (sl->rewrite));
1851 
1852  if (vec_len (sl->segments) > 1)
1853  {
1854  ip6srv->ip.src_address = src0;
1855 
1856  ip6srv->sr.tag =
1857  clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1858 
1859  ip6srv->sr.segments_left += 1;
1860  ip6srv->sr.last_entry += 1;
1861 
1862  ip6srv->sr.length += sizeof (ip6_address_t) / 8;
1863  ip6srv->sr.segments[0] = seg0;
1864 
1865  clib_memcpy_fast (&ip6srv->sr.segments[1],
1866  (u8 *) (sl->rewrite +
1867  sizeof (ip6_header_t) +
1868  sizeof (ip6_sr_header_t)),
1869  vec_len (sl->segments) *
1870  sizeof (ip6_address_t));
1871  }
1872  else
1873  {
1874  ip6srv->ip.src_address = src0;
1875  ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
1876 
1877  ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
1878  ip6srv->sr.segments_left = 1;
1879  ip6srv->sr.last_entry = 0;
1880  ip6srv->sr.length =
1881  ((sizeof (ip6_sr_header_t) +
1882  sizeof (ip6_address_t)) / 8) - 1;
1883  ip6srv->sr.flags = 0;
1884 
1885  ip6srv->sr.tag =
1886  clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1887 
1888  ip6srv->sr.segments[0] = seg0;
1889 
1890  if (vec_len (sl->segments))
1891  {
1892  ip6srv->sr.segments[1] = sl->segments[0];
1893  ip6srv->sr.last_entry++;
1894  ip6srv->sr.length += sizeof (ip6_address_t) / 8;
1895  }
1896  }
1897 
1898  if (PREDICT_TRUE (encap != NULL))
1899  {
1900  if (ls_param->nhtype == SRV6_NHTYPE_NONE)
1901  {
1902  if ((clib_net_to_host_u32
1904  >> 28) == 6)
1905  ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
1906  else
1907  ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
1908  }
1909  else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
1910  {
1911  ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
1912  if ((clib_net_to_host_u32
1914  >> 28) != 4)
1915  {
1916  // Bad encap packet.
1918  bad_n++;
1919  goto DONE;
1920  }
1921  }
1922  else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
1923  {
1924  ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
1925  if ((clib_net_to_host_u32
1927  >> 28) != 6)
1928  {
1929  // Bad encap packet.
1931  bad_n++;
1932  goto DONE;
1933  }
1934  }
1935  else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
1936  {
1938  }
1939  }
1940  else
1941  {
1943  }
1944  }
1945  else
1946  {
1947  clib_memcpy_fast (ip6srv, &sm->cache_hdr,
1948  sizeof (ip6_header_t));
1949 
1950  ip6srv->ip.src_address = src0;
1951  ip6srv->ip.dst_address = seg0;
1952 
1953  if (PREDICT_FALSE (gtpu_type) != GTPU_TYPE_GTPU)
1954  {
1955  ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
1956 
1958 
1959  ip6srv->sr.tag =
1960  clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1961 
1962  ip6srv->sr.segments_left = 0;
1963  ip6srv->sr.last_entry = 0;
1964 
1965  ip6srv->sr.length = sizeof (ip6_address_t) / 8;
1966  ip6srv->sr.segments[0] = seg0;
1967  }
1968  else
1969  {
1970  if (ls_param->nhtype == SRV6_NHTYPE_NONE)
1971  {
1972  if ((clib_net_to_host_u32
1974  >> 28) != 6)
1975  ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
1976  }
1977  else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
1978  {
1979  ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
1980  if ((clib_net_to_host_u32
1982  >> 28) != 4)
1983  {
1984  // Bad encap packet.
1986  bad_n++;
1987  goto DONE;
1988  }
1989  }
1990  else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
1991  {
1992  ip6srv->ip.protocol = IP_PROTOCOL_IPV6;
1993  if ((clib_net_to_host_u32
1995  >> 28) != 6)
1996  {
1997  // Bad encap packet.
1999  bad_n++;
2000  goto DONE;
2001  }
2002  }
2003  else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
2004  {
2006  }
2007  }
2008  }
2009 
2010  if (PREDICT_FALSE (ie_size))
2011  {
2012  ip6_sr_tlv_t *tlv;
2013  user_plane_sub_tlv_t *sub_tlv;
2014 
2015  tlv =
2016  (ip6_sr_tlv_t *) ((u8 *) ip6srv + (hdr_len - tlv_siz));
2018  tlv->length = (u8) (tlv_siz - sizeof (ip6_sr_tlv_t));
2019  clib_memset (tlv->value, 0, tlv->length);
2020 
2021  sub_tlv = (user_plane_sub_tlv_t *) tlv->value;
2022  sub_tlv->type = USER_PLANE_SUB_TLV_IE;
2023  sub_tlv->length = (u8) ie_size;
2024  clib_memcpy_fast (sub_tlv->value, ie_buf, ie_size);
2025 
2026  ip6srv->sr.length += (u8) (tlv_siz / 8);
2027  }
2028 
2029  ip6srv->ip.payload_length =
2030  clib_host_to_net_u16 (len0 + hdr_len - sizeof (ip6_header_t));
2031 
2032  good_n++;
2033 
2034  if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
2035  PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2036  {
2038  vlib_add_trace (vm, node, b0, sizeof (*tr));
2039  clib_memcpy (tr->src.as_u8, ip6srv->ip.src_address.as_u8,
2040  sizeof (ip6_address_t));
2041  clib_memcpy (tr->dst.as_u8, ip6srv->ip.dst_address.as_u8,
2042  sizeof (ip6_address_t));
2043  tr->teid = teid;
2044  clib_memcpy (tr->sr_prefix.as_u8, ls_param->sr_prefix.as_u8,
2045  sizeof (ip6_address_t));
2046  tr->sr_prefixlen = ls_param->sr_prefixlen;
2047  }
2048  }
2049 
2050  DONE:
2052  (((next0 ==
2054  &(sm2->sr_ls_valid_counters)), thread_index,
2055  ls0 - sm2->localsids, 1, vlib_buffer_length_in_chain (vm, b0));
2056 
2057  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2058  n_left_to_next, bi0, next0);
2059  }
2060 
2061  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2062  }
2063 
2065  SRV6_END_ERROR_M_GTP6_D_BAD_PACKETS, bad_n);
2066 
2068  SRV6_END_ERROR_M_GTP6_D_PACKETS, good_n);
2069 
2070  return frame->n_vectors;
2071 }
2072 
2073 // Function for SRv6 GTP6.D.DI function
2076  vlib_frame_t * frame)
2077 {
2079  ip6_sr_main_t *sm2 = &sr_main;
2080  u32 n_left_from, next_index, *from, *to_next;
2081  u32 thread_index = vm->thread_index;
2082  srv6_end_gtp6_param_t *ls_param;
2083 
2084  u32 good_n = 0, bad_n = 0;
2085 
2086  from = vlib_frame_vector_args (frame);
2087  n_left_from = frame->n_vectors;
2088  next_index = node->cached_next_index;
2089 
2090  while (n_left_from > 0)
2091  {
2092  u32 n_left_to_next;
2093 
2094  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2095 
2096  while (n_left_from > 0 && n_left_to_next > 0)
2097  {
2098  u32 bi0;
2099  vlib_buffer_t *b0;
2100  ip6_sr_localsid_t *ls0;
2101 
2102  ip6_gtpu_header_t *hdr0 = NULL;
2103  uword len0;
2104 
2105  ip6_address_t dst0;
2106  ip6_address_t src0;
2107  ip6_address_t seg0;
2108  u32 teid = 0;
2109  u8 *teidp;
2110  u8 gtpu_type = 0;
2111  u8 qfi = 0;
2112  u8 *qfip = NULL;
2113  u16 seq = 0;
2114  u8 *seqp;
2115  u32 offset, shift;
2116  u32 hdrlen;
2117  ip6_header_t *encap = NULL;
2118  gtpu_pdu_session_t *sess;
2119  int ie_size = 0;
2120  u16 tlv_siz = 0;
2121  u8 ie_buf[GTPU_IE_MAX_SIZ];
2122 
2124 
2125  // defaults
2126  bi0 = from[0];
2127  to_next[0] = bi0;
2128  from += 1;
2129  to_next += 1;
2130  n_left_from -= 1;
2131  n_left_to_next -= 1;
2132 
2133  b0 = vlib_get_buffer (vm, bi0);
2134  ls0 =
2136  vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
2137 
2138  ls_param = (srv6_end_gtp6_param_t *) ls0->plugin_mem;
2139 
2140  hdr0 = vlib_buffer_get_current (b0);
2141 
2142  hdrlen = sizeof (ip6_gtpu_header_t);
2143 
2144  len0 = vlib_buffer_length_in_chain (vm, b0);
2145 
2146  if ((hdr0->ip6.protocol != IP_PROTOCOL_UDP)
2147  || (hdr0->udp.dst_port !=
2148  clib_host_to_net_u16 (SRV6_GTP_UDP_DST_PORT))
2149  || (len0 < sizeof (ip6_gtpu_header_t)))
2150  {
2152 
2153  bad_n++;
2154  }
2155  else
2156  {
2157  dst0 = hdr0->ip6.dst_address;
2158  src0 = hdr0->ip6.src_address;
2159 
2160  gtpu_type = hdr0->gtpu.type;
2161 
2162  seg0 = ls_param->sr_prefix;
2163  teid = hdr0->gtpu.teid;
2164  teidp = (u8 *) & teid;
2165 
2166  seqp = (u8 *) & seq;
2167 
2168  if (hdr0->gtpu.ver_flags & (GTPU_EXTHDR_FLAG | GTPU_SEQ_FLAG))
2169  {
2170  // Extention header.
2171  hdrlen += sizeof (gtpu_exthdr_t);
2172 
2173  seq = hdr0->gtpu.ext->seq;
2174 
2176  {
2177  // PDU Session Container.
2178  sess =
2179  (gtpu_pdu_session_t *) (((char *) hdr0) + hdrlen);
2180  qfi = sess->u.val & ~GTPU_PDU_SESSION_P_BIT_MASK;
2181  qfip = &qfi;
2182 
2183  hdrlen += sizeof (gtpu_pdu_session_t);
2184 
2185  if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
2186  {
2187  hdrlen += sizeof (gtpu_paging_policy_t);
2188  }
2189  }
2190  }
2191 
2192  offset = ls_param->sr_prefixlen / 8;
2193  shift = ls_param->sr_prefixlen % 8;
2194 
2195  offset += 1;
2196  if (PREDICT_TRUE (shift == 0))
2197  {
2198  if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
2199  || gtpu_type == GTPU_TYPE_ECHO_REPLY
2200  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
2201  {
2202  clib_memcpy_fast (&seg0.as_u8[offset], seqp, 2);
2203  }
2204  else
2205  {
2206  clib_memcpy_fast (&seg0.as_u8[offset], teidp, 4);
2207  }
2208 
2209  if (qfip)
2210  {
2211  qfi =
2212  ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
2213  ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
2214 
2215  if (sess->type)
2216  {
2218  }
2219 
2220  seg0.as_u8[offset + 4] = qfi;
2221  }
2222  }
2223  else
2224  {
2225  int idx;
2226 
2227  if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
2228  || gtpu_type == GTPU_TYPE_ECHO_REPLY
2229  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
2230  {
2231  for (idx = 0; idx < 2; idx++)
2232  {
2233  seg0.as_u8[offset + idx] |= seqp[idx] >> shift;
2234  seg0.as_u8[offset + idx + 1] |=
2235  seqp[idx] << (8 - shift);
2236  }
2237  }
2238  else
2239  {
2240  for (idx = 0; idx < 4; idx++)
2241  {
2242  seg0.as_u8[offset + idx] |= teidp[idx] >> shift;
2243  seg0.as_u8[offset + idx + 1] |=
2244  teidp[idx] << (8 - shift);
2245  }
2246  }
2247 
2248  if (qfip)
2249  {
2250  qfi =
2251  ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
2252  ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
2253 
2254  if (sess->type)
2255  {
2257  }
2258 
2259  seg0.as_u8[offset + 4] |= qfi >> shift;
2260  seg0.as_u8[offset + 5] |= qfi << (8 - shift);
2261  }
2262  }
2263 
2264  if (PREDICT_FALSE (gtpu_type == GTPU_TYPE_ERROR_INDICATION))
2265  {
2266  u16 payload_len;
2267 
2268  payload_len = clib_net_to_host_u16 (hdr0->gtpu.length);
2269  if (payload_len != 0)
2270  {
2271  ie_size =
2272  payload_len - (hdrlen - sizeof (ip6_gtpu_header_t));
2273  if (ie_size > 0)
2274  {
2275  u8 *ies;
2276 
2277  ies = (u8 *) ((u8 *) hdr0 + hdrlen);
2278  clib_memcpy_fast (ie_buf, ies, ie_size);
2279  hdrlen += ie_size;
2280  }
2281  }
2282  }
2283 
2284  // jump over variable length data
2285  vlib_buffer_advance (b0, (word) hdrlen);
2286 
2287  // get length of encapsulated IPv6 packet (the remaining part)
2288  len0 = vlib_buffer_length_in_chain (vm, b0);
2289 
2290  if (PREDICT_TRUE (gtpu_type == GTPU_TYPE_GTPU))
2291  {
2292  encap = vlib_buffer_get_current (b0);
2293  }
2294 
2295  uword *p;
2296  ip6srv_combo_header_t *ip6srv;
2297  ip6_sr_policy_t *sr_policy = NULL;
2298  ip6_sr_sl_t *sl = NULL;
2299  u32 *sl_index;
2300  u32 hdr_len;
2301 
2302  p =
2304  &ls_param->sr_prefix);
2305  if (p)
2306  {
2307  sr_policy = pool_elt_at_index (sm2->sr_policies, p[0]);
2308  }
2309 
2310  if (sr_policy)
2311  {
2312  vec_foreach (sl_index, sr_policy->segments_lists)
2313  {
2314  sl = pool_elt_at_index (sm2->sid_lists, *sl_index);
2315  if (sl != NULL)
2316  break;
2317  }
2318  }
2319 
2320  hdr_len = sizeof (ip6srv_combo_header_t);
2321 
2322  if (sl)
2323  hdr_len += vec_len (sl->segments) * sizeof (ip6_address_t);
2324 
2325  hdr_len += sizeof (ip6_address_t) * 2;
2326 
2327  if (ie_size)
2328  {
2329  tlv_siz =
2330  sizeof (ip6_sr_tlv_t) + sizeof (user_plane_sub_tlv_t) +
2331  ie_size;
2332 
2333  tlv_siz = (tlv_siz & ~0x07) + (tlv_siz & 0x07 ? 0x08 : 0x0);
2334  hdr_len += tlv_siz;
2335  }
2336 
2337  // jump back to data[0] or pre_data if required
2338  vlib_buffer_advance (b0, -(word) hdr_len);
2339 
2340  ip6srv = vlib_buffer_get_current (b0);
2341 
2342  if (sl)
2343  {
2344  clib_memcpy_fast (ip6srv, sl->rewrite,
2345  vec_len (sl->rewrite));
2346 
2347  if (vec_len (sl->segments) > 1)
2348  {
2349  ip6srv->ip.src_address = src0;
2350 
2351  ip6srv->sr.tag =
2352  clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
2353 
2354  ip6srv->sr.segments_left += 2;
2355  ip6srv->sr.last_entry += 2;
2356 
2357  ip6srv->sr.length += ((sizeof (ip6_address_t) * 2) / 8);
2358 
2359  ip6srv->sr.segments[0] = dst0;
2360  ip6srv->sr.segments[1] = seg0;
2361 
2362  clib_memcpy_fast (&ip6srv->sr.segments[2],
2363  (u8 *) (sl->rewrite +
2364  sizeof (ip6_header_t) +
2365  sizeof (ip6_sr_header_t)),
2366  vec_len (sl->segments) *
2367  sizeof (ip6_address_t));
2368  }
2369  else
2370  {
2371  ip6srv->ip.src_address = src0;
2372  ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
2373 
2374  ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
2375  ip6srv->sr.segments_left = 2;
2376  ip6srv->sr.last_entry = 1;
2377  ip6srv->sr.length =
2378  ((sizeof (ip6_sr_header_t) +
2379  2 * sizeof (ip6_address_t)) / 8) - 1;
2380  ip6srv->sr.flags = 0;
2381 
2382  ip6srv->sr.tag =
2383  clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
2384 
2385  ip6srv->sr.segments[0] = dst0;
2386  ip6srv->sr.segments[1] = seg0;
2387 
2388  if (vec_len (sl->segments))
2389  {
2390  ip6srv->sr.segments[2] = sl->segments[0];
2391  ip6srv->sr.last_entry++;
2392  ip6srv->sr.length += sizeof (ip6_address_t) / 8;
2393  }
2394  }
2395  }
2396  else
2397  {
2398  clib_memcpy_fast (ip6srv, &sm->cache_hdr,
2399  sizeof (ip6_header_t));
2400 
2401  ip6srv->ip.src_address = src0;
2402  ip6srv->ip.dst_address = seg0;
2403 
2404  ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
2405  ip6srv->sr.segments_left = 1;
2406  ip6srv->sr.last_entry = 0;
2407  ip6srv->sr.length =
2408  ((sizeof (ip6_sr_header_t) +
2409  sizeof (ip6_address_t)) / 8) - 1;
2410  ip6srv->sr.flags = 0;
2411 
2412  ip6srv->sr.tag =
2413  clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
2414 
2415  ip6srv->sr.segments[0] = dst0;
2416  }
2417 
2418  if (PREDICT_FALSE (ie_size))
2419  {
2420  ip6_sr_tlv_t *tlv;
2421  user_plane_sub_tlv_t *sub_tlv;
2422 
2423  tlv =
2424  (ip6_sr_tlv_t *) ((u8 *) ip6srv + (hdr_len - tlv_siz));
2426  tlv->length = (u8) (tlv_siz - sizeof (ip6_sr_tlv_t));
2427  clib_memset (tlv->value, 0, tlv->length);
2428 
2429  sub_tlv = (user_plane_sub_tlv_t *) tlv->value;
2430  sub_tlv->length = (u8) (ie_size);
2431  clib_memcpy_fast (sub_tlv->value, ie_buf, ie_size);
2432 
2433  ip6srv->sr.length += (u8) (tlv_siz / 8);
2434  }
2435 
2436  ip6srv->ip.payload_length =
2437  clib_host_to_net_u16 (len0 + hdr_len - sizeof (ip6_header_t));
2438  ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
2439 
2440  if (PREDICT_TRUE (encap != NULL))
2441  {
2442  if (ls_param->nhtype == SRV6_NHTYPE_NONE)
2443  {
2444  if ((clib_net_to_host_u32
2446  28) == 6)
2447  ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
2448  else
2449  ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
2450  }
2451  else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
2452  {
2453  ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
2454  if ((clib_net_to_host_u32
2456  28) != 4)
2457  {
2458  // Bad encap packet.
2460  bad_n++;
2461  goto DONE;
2462  }
2463  }
2464  else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
2465  {
2466  ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
2467  if ((clib_net_to_host_u32
2469  28) != 6)
2470  {
2471  // Bad encap packet.
2473  bad_n++;
2474  goto DONE;
2475  }
2476  }
2477  else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
2478  {
2480  }
2481  }
2482  else
2483  {
2485  }
2486 
2487  good_n++;
2488 
2489  if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
2490  PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2491  {
2493  vlib_add_trace (vm, node, b0, sizeof (*tr));
2494  clib_memcpy (tr->src.as_u8, ip6srv->ip.src_address.as_u8,
2495  sizeof (ip6_address_t));
2496  clib_memcpy (tr->dst.as_u8, ip6srv->ip.dst_address.as_u8,
2497  sizeof (ip6_address_t));
2498  tr->teid = teid;
2499  clib_memcpy (tr->sr_prefix.as_u8, ls_param->sr_prefix.as_u8,
2500  sizeof (ip6_address_t));
2501  tr->sr_prefixlen = ls_param->sr_prefixlen;
2502  }
2503  }
2504 
2505  DONE:
2507  (((next0 ==
2509  &(sm2->sr_ls_invalid_counters) : &(sm2->sr_ls_valid_counters)),
2510  thread_index, ls0 - sm2->localsids, 1,
2511  vlib_buffer_length_in_chain (vm, b0));
2512 
2513  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2514  n_left_to_next, bi0, next0);
2515  }
2516 
2517  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2518  }
2519 
2521  SRV6_END_ERROR_M_GTP6_D_DI_BAD_PACKETS, bad_n);
2522 
2524  SRV6_END_ERROR_M_GTP6_D_DI_PACKETS, good_n);
2525 
2526  return frame->n_vectors;
2527 }
2528 
2529 // Function for SRv6 GTP6.DT function
2532  vlib_frame_t * frame)
2533 {
2535  ip6_sr_main_t *sm2 = &sr_main;
2536  u32 n_left_from, next_index, *from, *to_next;
2537  u32 thread_index = vm->thread_index;
2538 
2539  u32 good_n = 0, bad_n = 0;
2540 
2541  from = vlib_frame_vector_args (frame);
2542  n_left_from = frame->n_vectors;
2543  next_index = node->cached_next_index;
2544 
2545  while (n_left_from > 0)
2546  {
2547  u32 n_left_to_next;
2548 
2549  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2550 
2551  while (n_left_from > 0 && n_left_to_next > 0)
2552  {
2553  u32 bi0;
2554  vlib_buffer_t *b0;
2555  srv6_end_gtp6_dt_param_t *ls_param;
2556  ip6_sr_localsid_t *ls0;
2557 
2558  ip6_gtpu_header_t *hdr0 = NULL;
2559  ip4_header_t *ip4 = NULL;
2560  ip6_header_t *ip6 = NULL;
2561  ip6_address_t src, dst;
2562  u32 teid;
2563  u32 hdrlen;
2564  u32 len0;
2565 
2567 
2568  bi0 = from[0];
2569  to_next[0] = bi0;
2570  from += 1;
2571  to_next += 1;
2572  n_left_from -= 1;
2573  n_left_to_next -= 1;
2574 
2575  b0 = vlib_get_buffer (vm, bi0);
2576  ls0 =
2578  vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
2579 
2580  ls_param = (srv6_end_gtp6_dt_param_t *) ls0->plugin_mem;
2581 
2582  hdr0 = vlib_buffer_get_current (b0);
2583 
2584  hdrlen = sizeof (ip6_gtpu_header_t);
2585 
2586  len0 = vlib_buffer_length_in_chain (vm, b0);
2587 
2588  if ((hdr0->ip6.protocol != IP_PROTOCOL_UDP)
2589  || (hdr0->udp.dst_port !=
2590  clib_host_to_net_u16 (SRV6_GTP_UDP_DST_PORT))
2591  || (len0 < sizeof (ip6_gtpu_header_t)))
2592  {
2594 
2595  bad_n++;
2596  }
2597  else
2598  {
2599  clib_memcpy_fast (src.as_u8, hdr0->ip6.src_address.as_u8,
2600  sizeof (ip6_address_t));
2601  clib_memcpy_fast (dst.as_u8, hdr0->ip6.dst_address.as_u8,
2602  sizeof (ip6_address_t));
2603 
2604  teid = hdr0->gtpu.teid;
2605 
2606  if (hdr0->gtpu.ver_flags & GTPU_EXTHDR_FLAG)
2607  {
2608  hdrlen += sizeof (gtpu_exthdr_t);
2610  {
2611  gtpu_pdu_session_t *sess;
2612 
2613  sess =
2614  (gtpu_pdu_session_t *) (((char *) hdr0) +
2615  sizeof (ip6_gtpu_header_t) +
2616  sizeof (gtpu_exthdr_t));
2617 
2618  hdrlen += sizeof (gtpu_pdu_session_t);
2619  if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
2620  {
2621  hdrlen += sizeof (gtpu_paging_policy_t);
2622  }
2623  }
2624  }
2625 
2626  if (ls_param->type == SRV6_GTP6_DT4)
2627  {
2628  vlib_buffer_advance (b0, (word) hdrlen);
2629  ip4 = vlib_buffer_get_current (b0);
2630  if ((ip4->ip_version_and_header_length & 0xf0) != 0x40)
2631  {
2633  bad_n++;
2634  goto DONE;
2635  }
2636 
2638  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2639  ls_param->fib4_index;
2640  }
2641  else if (ls_param->type == SRV6_GTP6_DT6)
2642  {
2643  ip6 = (ip6_header_t *) ((u8 *) hdr0 + hdrlen);
2644  if ((clib_net_to_host_u32
2646  != 6)
2647  {
2649  bad_n++;
2650  goto DONE;
2651  }
2652 
2654  if ((ip6->dst_address.as_u8[0] == 0xff)
2655  && ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80))
2656  {
2657  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2658  ls_param->local_fib_index;
2659  }
2660  else
2661  {
2662  vlib_buffer_advance (b0, (word) hdrlen);
2663  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2664  ls_param->fib6_index;
2665  }
2666  }
2667  else if (ls_param->type == SRV6_GTP6_DT46)
2668  {
2669  ip6 = (ip6_header_t *) ((u8 *) hdr0 + hdrlen);
2670  if ((clib_net_to_host_u32
2672  == 6)
2673  {
2675  if ((ip6->dst_address.as_u8[0] == 0xff)
2676  && ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80))
2677  {
2678  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2679  ls_param->local_fib_index;
2680  }
2681  else
2682  {
2683  vlib_buffer_advance (b0, (word) hdrlen);
2684  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2685  ls_param->fib6_index;
2686  }
2687  }
2688  else
2689  if ((clib_net_to_host_u32
2691  == 4)
2692  {
2693  vlib_buffer_advance (b0, (word) hdrlen);
2695  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2696  ls_param->fib4_index;
2697  }
2698  else
2699  {
2701  bad_n++;
2702  goto DONE;
2703  }
2704  }
2705  else
2706  {
2708  bad_n++;
2709  goto DONE;
2710  }
2711 
2712  good_n++;
2713 
2714  if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
2715  PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2716  {
2718  vlib_add_trace (vm, node, b0, sizeof (*tr));
2719  clib_memcpy (tr->src.as_u8, src.as_u8,
2720  sizeof (ip6_address_t));
2721  clib_memcpy (tr->dst.as_u8, dst.as_u8,
2722  sizeof (ip6_address_t));
2723  tr->teid = teid;
2724  }
2725  }
2726 
2727  DONE:
2729  (((next0 ==
2731  : &(sm2->sr_ls_valid_counters)), thread_index,
2732  ls0 - sm2->localsids, 1, vlib_buffer_length_in_chain (vm, b0));
2733 
2734  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2735  n_left_to_next, bi0, next0);
2736  }
2737 
2738  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2739  }
2740 
2742  SRV6_END_ERROR_M_GTP6_DT_BAD_PACKETS, bad_n);
2743 
2745  SRV6_END_ERROR_M_GTP6_DT_PACKETS, good_n);
2746 
2747  return frame->n_vectors;
2748 }
2749 
2750 // Function for SRv6 GTP4.DT function
2753  vlib_frame_t * frame)
2754 {
2756  ip6_sr_main_t *sm2 = &sr_main;
2757  u32 n_left_from, next_index, *from, *to_next;
2758 
2759  u32 good_n = 0, bad_n = 0;
2760 
2761  from = vlib_frame_vector_args (frame);
2762  n_left_from = frame->n_vectors;
2763  next_index = node->cached_next_index;
2764 
2765  while (n_left_from > 0)
2766  {
2767  u32 n_left_to_next;
2768 
2769  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2770 
2771  while (n_left_from > 0 && n_left_to_next > 0)
2772  {
2773  u32 bi0;
2774  vlib_buffer_t *b0;
2775  srv6_t_gtp4_dt_param_t *ls_param;
2776  ip6_sr_sl_t *ls0;
2777 
2778  ip4_gtpu_header_t *hdr0 = NULL;
2779  ip4_header_t *ip4 = NULL;
2780  ip6_header_t *ip6 = NULL;
2781  ip6_address_t src, dst;
2782  u32 teid;
2783  u32 hdrlen;
2784  u32 len0;
2785 
2787 
2788  bi0 = from[0];
2789  to_next[0] = bi0;
2790  from += 1;
2791  to_next += 1;
2792  n_left_from -= 1;
2793  n_left_to_next -= 1;
2794 
2795  b0 = vlib_get_buffer (vm, bi0);
2796  ls0 =
2798  vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
2799 
2800  ls_param = (srv6_t_gtp4_dt_param_t *) ls0->plugin_mem;
2801 
2802  hdr0 = vlib_buffer_get_current (b0);
2803 
2804  hdrlen = sizeof (ip4_gtpu_header_t);
2805 
2806  len0 = vlib_buffer_length_in_chain (vm, b0);
2807 
2808  if ((hdr0->ip4.protocol != IP_PROTOCOL_UDP)
2809  || (hdr0->udp.dst_port !=
2810  clib_host_to_net_u16 (SRV6_GTP_UDP_DST_PORT))
2811  || (len0 < sizeof (ip4_gtpu_header_t)))
2812  {
2814 
2815  bad_n++;
2816  }
2817  else
2818  {
2819  clib_memcpy_fast (src.as_u8, hdr0->ip4.src_address.as_u8,
2820  sizeof (ip4_address_t));
2821  clib_memcpy_fast (dst.as_u8, hdr0->ip4.dst_address.as_u8,
2822  sizeof (ip4_address_t));
2823 
2824  teid = hdr0->gtpu.teid;
2825 
2826  if (hdr0->gtpu.ver_flags & GTPU_EXTHDR_FLAG)
2827  {
2828  hdrlen += sizeof (gtpu_exthdr_t);
2830  {
2831  gtpu_pdu_session_t *sess;
2832 
2833  sess =
2834  (gtpu_pdu_session_t *) (((char *) hdr0) +
2835  sizeof (ip6_gtpu_header_t) +
2836  sizeof (gtpu_exthdr_t));
2837 
2838  hdrlen += sizeof (gtpu_pdu_session_t);
2839  if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
2840  {
2841  hdrlen += sizeof (gtpu_paging_policy_t);
2842  }
2843  }
2844  }
2845 
2846  if (ls_param->type == SRV6_GTP4_DT4)
2847  {
2848  vlib_buffer_advance (b0, (word) hdrlen);
2849  ip4 = vlib_buffer_get_current (b0);
2850  if ((ip4->ip_version_and_header_length & 0xf0) != 0x40)
2851  {
2853  bad_n++;
2854  goto DONE;
2855  }
2856 
2858  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2859  ls_param->fib4_index;
2860  }
2861  else if (ls_param->type == SRV6_GTP4_DT6)
2862  {
2863  ip6 = (ip6_header_t *) ((u8 *) hdr0 + hdrlen);
2864  if ((clib_net_to_host_u32
2866  != 6)
2867  {
2869  bad_n++;
2870  goto DONE;
2871  }
2872 
2874  if ((ip6->dst_address.as_u8[0] == 0xff)
2875  && ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80))
2876  {
2878  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2879  ls_param->local_fib_index;
2880  }
2881  else
2882  {
2883  vlib_buffer_advance (b0, (word) hdrlen);
2884  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2885  ls_param->fib6_index;
2886  }
2887  }
2888  else if (ls_param->type == SRV6_GTP4_DT46)
2889  {
2890  ip6 = (ip6_header_t *) ((u8 *) hdr0 + hdrlen);
2891  if ((clib_net_to_host_u32
2893  == 6)
2894  {
2896  if ((ip6->dst_address.as_u8[0] == 0xff)
2897  && ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80))
2898  {
2900  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2901  ls_param->local_fib_index;
2902  }
2903  else
2904  {
2905  vlib_buffer_advance (b0, (word) hdrlen);
2906  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2907  ls_param->fib6_index;
2908  }
2909  }
2910  else
2911  if ((clib_net_to_host_u32
2913  == 4)
2914  {
2915  vlib_buffer_advance (b0, (word) hdrlen);
2917  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2918  ls_param->fib4_index;
2919  }
2920  else
2921  {
2923  bad_n++;
2924  goto DONE;
2925  }
2926  }
2927  else
2928  {
2930  bad_n++;
2931  goto DONE;
2932  }
2933 
2934  good_n++;
2935 
2936  if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
2937  PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2938  {
2940  vlib_add_trace (vm, node, b0, sizeof (*tr));
2941  clib_memcpy (tr->src.as_u8, src.as_u8,
2942  sizeof (ip6_address_t));
2943  clib_memcpy (tr->dst.as_u8, dst.as_u8,
2944  sizeof (ip6_address_t));
2945  tr->teid = teid;
2946  }
2947  }
2948 
2949  DONE:
2950  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2951  n_left_to_next, bi0, next0);
2952  }
2953 
2954  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2955  }
2956 
2958  SRV6_T_ERROR_M_GTP4_DT_BAD_PACKETS, bad_n);
2959 
2961  SRV6_T_ERROR_M_GTP4_DT_PACKETS, good_n);
2962 
2963  return frame->n_vectors;
2964 }
2965 
2967 {
2968  .name = "srv6-end-m-gtp6-e",.vector_size = sizeof (u32),.format_trace =
2970  ARRAY_LEN (srv6_end_error_v6_e_strings),.error_strings =
2971  srv6_end_error_v6_e_strings,.n_next_nodes =
2972  SRV6_END_M_GTP6_E_N_NEXT,.next_nodes =
2973  {
2975  "error-drop",[SRV6_END_M_GTP6_E_NEXT_LOOKUP] = "ip6-lookup",}
2976 ,};
2977 
2979 {
2980  .name = "srv6-end-m-gtp6-d",.vector_size = sizeof (u32),.format_trace =
2982  ARRAY_LEN (srv6_end_error_v6_d_strings),.error_strings =
2983  srv6_end_error_v6_d_strings,.n_next_nodes =
2984  SRV6_END_M_GTP6_D_N_NEXT,.next_nodes =
2985  {
2987  "error-drop",[SRV6_END_M_GTP6_D_NEXT_LOOKUP] = "ip6-lookup",}
2988 ,};
2989 
2991 {
2992  .name = "srv6-end-m-gtp6-d-di",.vector_size = sizeof (u32),.format_trace =
2994  ARRAY_LEN (srv6_end_error_v6_d_di_strings),.error_strings =
2995  srv6_end_error_v6_d_di_strings,.n_next_nodes =
2996  SRV6_END_M_GTP6_D_DI_N_NEXT,.next_nodes =
2997  {
2998  [SRV6_END_M_GTP6_D_DI_NEXT_DROP] = "error-drop",
2999  [SRV6_END_M_GTP6_D_DI_NEXT_LOOKUP] = "ip6-lookup",}
3000 ,};
3001 
3003 {
3004  .name = "srv6-end-m-gtp6-dt",.vector_size = sizeof (u32),.format_trace =
3006  ARRAY_LEN (srv6_end_error_v6_dt_strings),.error_strings =
3007  srv6_end_error_v6_dt_strings,.n_next_nodes =
3008  SRV6_END_M_GTP6_DT_N_NEXT,.next_nodes =
3009  {
3011  "error-drop",
3013  = "ip4-lookup",[SRV6_END_M_GTP6_DT_NEXT_LOOKUP6] = "ip6-lookup",}
3014 ,};
3015 
3017 {
3018  .name = "srv6-t-m-gtp4-dt",.vector_size = sizeof (u32),.format_trace =
3020  ARRAY_LEN (srv6_t_error_v4_dt_strings),.error_strings =
3021  srv6_t_error_v4_dt_strings,.n_next_nodes =
3022  SRV6_T_M_GTP4_DT_N_NEXT,.next_nodes =
3023  {
3025  "error-drop",
3027  "ip4-lookup",[SRV6_T_M_GTP4_DT_NEXT_LOOKUP6] = "ip6-lookup",}
3028 ,};
3029 
3030 /*
3031 * fd.io coding-style-patch-verification: ON
3032 *
3033 * Local Variables:
3034 * eval: (c-set-style "gnu")
3035 * End:
3036 */
#define GTPU_PDU_SESSION_P_BIT_MASK
Definition: mobile.h:136
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
ip6_sr_main_t sr_main
Definition: sr.c:31
#define SRV6_GTP4_DT6
Definition: mobile.h:47
srv6_end_main_v6_dt_t srv6_end_main_v6_dt
Definition: gtp6_dt.c:25
#define GTPU_EXTHDR_PDU_SESSION
Definition: mobile.h:60
#define SRH_TAG_ERROR_INDICATION
Definition: mobile.h:64
#define foreach_srv6_t_v4_d_error
Definition: node.c:116
#define CLIB_UNUSED(x)
Definition: clib.h:86
#define SRH_TAG_ECHO_REQUEST
Definition: mobile.h:63
#define IP_PROTOCOL_IP6_ETHERNET
Definition: mobile.h:37
ip6_address_t src
Definition: node.c:25
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 thread_index, u32 index, u64 n_packets, u64 n_bytes)
Increment a combined counter.
Definition: counter.h:220
#define SRV6_GTP_UDP_DST_PORT
Definition: mobile.h:29
ip4_address_t src_address
Definition: ip4_packet.h:170
SR LocalSID.
Definition: sr.h:120
ip6_header_t cache_hdr
Definition: mobile.h:268
u32 teid
Definition: mobile.h:95
#define foreach_srv6_end_v6_e_error
Definition: node.c:120
#define GTPU_TYPE_GTPU
Definition: mobile.h:104
#define PREDICT_TRUE(x)
Definition: clib.h:119
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
vlib_node_registration_t srv6_end_m_gtp6_d_di
(constructor) VLIB_REGISTER_NODE (srv6_end_m_gtp6_d_di)
Definition: node.c:2990
union gtpu_pdu_session_t::@128 u
srv6_t_main_v4_dt_t srv6_t_main_v4_dt
Definition: gtp4_dt.c:25
#define foreach_srv6_end_v6_d_di_error
Definition: node.c:128
u32 thread_index
Definition: main.h:218
#define GTPU_EXTHDR_FLAG
Definition: mobile.h:58
ip6_address_t * segments
SIDs (key)
Definition: sr.h:72
ip6_address_t sr_prefix
Definition: node.c:26
vl_api_address_t src
Definition: gre.api:54
#define USER_PLANE_SUB_TLV_IE
Definition: mobile.h:175
#define foreach_srv6_t_v4_dt_error
Definition: node.c:136
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
#define GTPU_RECOVERY_IE_TYPE
Definition: mobile.h:67
srv6_end_main_v6_decap_t srv6_end_main_v6_decap
Definition: gtp6_d.c:24
#define ROUTING_HEADER_TYPE_SR
Definition: sr_packet.h:117
#define VLIB_NODE_FN(node)
Definition: node.h:202
u16 localsid_prefix_len
Definition: sr.h:124
u16 length
Definition: mobile.h:94
u8 value[0]
Definition: sr_packet.h:156
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:402
vlib_combined_counter_main_t sr_ls_invalid_counters
Definition: sr.h:301
vlib_combined_counter_main_t sr_ls_valid_counters
Definition: sr.h:300
ip6_address_t src_address
Definition: ip6_packet.h:310
unsigned char u8
Definition: types.h:56
srv6_end_main_v6_t srv6_end_main_v6
Definition: gtp6_e.c:24
#define GTPU_IE_MAX_SIZ
Definition: mobile.h:69
#define clib_memcpy(d, s, n)
Definition: string.h:180
static u16 srh_tagfield[256]
Definition: node.c:31
vlib_node_registration_t srv6_t_m_gtp4_dt
(constructor) VLIB_REGISTER_NODE (srv6_t_m_gtp4_dt)
Definition: node.c:3016
#define GTPU_TYPE_END_MARKER
Definition: mobile.h:103
format_function_t format_ip4_address
Definition: format.h:73
ip6_address_t sr_pr_encaps_src
i64 word
Definition: types.h:111
vl_api_ip6_address_t ip6
Definition: one.api:424
ip4_address_t dst_address
Definition: ip4_packet.h:170
#define SRH_TAG_END_MARKER
Definition: mobile.h:65
SR Segment List (SID list)
Definition: sr.h:70
ip6_header_t ip6
Definition: mobile.h:156
#define SRV6_NHTYPE_NON_IP
Definition: mobile.h:34
#define IPPROTO_IPV6_ROUTE
Definition: sr_packet.h:114
unsigned int u32
Definition: types.h:88
#define SRV6_GTP6_DT6
Definition: mobile.h:42
static u8 * format_srv6_end_rewrite_trace(u8 *s, va_list *args)
Definition: node.c:87
srv6_t_error_v4_d_t
Definition: node.c:148
srv6_t_error_v4_dt_t
Definition: node.c:188
u8 npdu_num
Definition: mobile.h:84
static char * srv6_end_error_v6_e_strings[]
Definition: node.c:208
vl_api_fib_path_type_t type
Definition: fib_types.api:123
gtpu_header_t gtpu
Definition: mobile.h:149
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:534
#define SRV6_PDU_SESSION_U_BIT_MASK
Definition: mobile.h:140
#define GTPU_PDU_SESSION_QFI_MASK
Definition: mobile.h:138
#define SRV6_NHTYPE_IPV4
Definition: mobile.h:32
ip6_sr_header_t sr
Definition: sr.h:63
srv6_end_error_v6_e_t
Definition: node.c:156
static char * srv6_t_error_v4_d_strings[]
Definition: node.c:202
srv6_end_m_gtp4_e_next_t
Definition: node.c:238
#define SRV6_NHTYPE_IPV6
Definition: mobile.h:33
unsigned short u16
Definition: types.h:57
ip6_header_t ip
Definition: sr.h:62
vlib_node_registration_t srv6_end_m_gtp6_d
(constructor) VLIB_REGISTER_NODE (srv6_end_m_gtp6_d)
Definition: node.c:2978
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
void * plugin_mem
Definition: sr.h:84
srv6_end_error_v6_dt_t
Definition: node.c:180
#define PREDICT_FALSE(x)
Definition: clib.h:118
vl_api_ip4_address_t ip4
Definition: one.api:376
#define GTPU_TYPE_ECHO_REPLY
Definition: mobile.h:101
srv6_end_error_v6_d_di_t
Definition: node.c:172
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:224
vl_api_address_t dst
Definition: gre.api:55
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:338
#define SRV6_PDU_SESSION_R_BIT_MASK
Definition: mobile.h:141
vlib_main_t * vm
Definition: in2out_ed.c:1599
static char * srv6_end_error_v6_dt_strings[]
Definition: node.c:226
srv6_T_m_gtp4_d_next_t
Definition: node.c:245
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1150
ip6_sr_localsid_t * localsids
Definition: sr.h:270
vlib_node_registration_t srv6_end_m_gtp4_e
(constructor) VLIB_REGISTER_NODE (srv6_end_m_gtp4_e)
Definition: node.c:1213
#define SRH_TAG_ECHO_REPLY
Definition: mobile.h:62
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u32 end_m_gtp4_e_node_index
Definition: mobile.h:221
srv6_end_error_v6_d_t
Definition: node.c:164
ip6_address_t v6src_prefix
Definition: mobile.h:210
format_function_t format_ip6_address
Definition: format.h:91
#define GTPU_TYPE_ECHO_REQUEST
Definition: mobile.h:100
srv6_end_error_v4_t
Definition: node.c:140
vlib_node_registration_t srv6_t_m_gtp4_d
(constructor) VLIB_REGISTER_NODE (srv6_t_m_gtp4_d)
Definition: node.c:1225
srv6_end_main_v6_decap_di_t srv6_end_main_v6_decap_di
Definition: gtp6_d_di.c:24
u32 * segments_lists
SID lists indexes (vector)
Definition: sr.h:95
u32 t_m_gtp4_dt_node_index
Definition: mobile.h:305
vlib_node_registration_t srv6_end_m_gtp6_e
(constructor) VLIB_REGISTER_NODE (srv6_end_m_gtp6_e)
Definition: node.c:2966
srv6_end_m_gtp6_d_di_next_t
Definition: node.c:266
#define SRV6_NHTYPE_NONE
Definition: mobile.h:31
#define ARRAY_LEN(x)
Definition: clib.h:66
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:483
srv6_t_main_v4_decap_t srv6_t_main_v4_decap
Definition: gtp4_d.c:24
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1599
static char * srv6_t_error_v4_dt_strings[]
Definition: node.c:232
#define GTPU_PDU_SESSION_R_BIT_MASK
Definition: mobile.h:137
ip4_gtpu_header_t cache_hdr
Definition: mobile.h:227
#define SRV6_GTP4_DT46
Definition: mobile.h:48
ip6_gtpu_header_t cache_hdr
Definition: mobile.h:254
srv6_end_main_v4_t srv6_end_main_v4
Definition: gtp4_e.c:24
udp_header_t udp
Definition: mobile.h:157
u32 end_m_gtp6_e_node_index
Definition: mobile.h:251
static uword * mhash_get(mhash_t *h, const void *key)
Definition: mhash.h:110
void * plugin_mem
Memory to be used by the plugin callback functions.
Definition: sr.h:153
#define GTPU_SEQ_FLAG
Definition: mobile.h:59
uword hash_memory(void *p, word n_bytes, uword state)
Definition: hash.c:275
static u8 * format_srv6_end_rewrite_trace6(u8 *s, va_list *args)
Definition: node.c:99
u8 nextexthdr
Definition: mobile.h:85
srv6_end_m_gtp6_d_next_t
Definition: node.c:259
#define SRV6_GTP6_DT4
Definition: mobile.h:41
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:248
static u8 gtpu_type_get(u16 tag)
Definition: node.c:302
mhash_t sr_policies_index_hash
Definition: sr.h:267
srv6_end_m_gtp6_dt_next_t
Definition: node.c:273
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
udp_header_t udp
Definition: mobile.h:148
typedef key
Definition: ipsec_types.api:85
ip4_header_t ip4
Definition: mobile.h:147
u32 ip_version_traffic_class_and_flow_label
Definition: ip6_packet.h:297
vlib_node_registration_t srv6_end_m_gtp6_dt
(constructor) VLIB_REGISTER_NODE (srv6_end_m_gtp6_dt)
Definition: node.c:3002
Definition: defs.h:47
u16 payload_length
Definition: ip6_packet.h:301
vl_api_address_t ip
Definition: l2.api:501
#define SRV6_PDU_SESSION_QFI_MASK
Definition: mobile.h:142
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
ip6_sr_policy_t * sr_policies
Definition: sr.h:264
ip6_address_t segments[0]
Definition: sr_packet.h:149
SR Policy.
Definition: sr.h:93
ip6_address_t sr_prefix
Definition: mobile.h:181
u8 * rewrite
Precomputed rewrite header.
Definition: sr.h:76
static char * srv6_end_error_v6_d_strings[]
Definition: node.c:214
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
ip6_address_t dst
Definition: node.c:25
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
static char * srv6_end_error_v4_strings[]
Definition: node.c:196
u8 restart_counter
Definition: mobile.h:76
u16 port
Definition: lb_types.api:72
Bits Octets 8 7 6 5 4 3 2 1 1 Version PT (*) E S PN 2 Message Type 3 Length (1st Octet) 4 Length...
Definition: mobile.h:90
ip6_sr_sl_t * sid_lists
Definition: sr.h:261
#define foreach_srv6_end_v4_error
Definition: node.c:112
struct clib_bihash_value offset
template key/value backing page structure
srv6_end_m_gtp6_e_next_t
Definition: node.c:252
u32 end_m_gtp6_dt_node_index
Definition: mobile.h:293
#define vnet_buffer(b)
Definition: buffer.h:417
ip6_address_t sr_prefix
Definition: mobile.h:207
Segment Routing main datastructure.
Definition: sr.h:255
#define vec_foreach(var, vec)
Vector iterator.
u8 ver_flags
Definition: mobile.h:92
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1600
gtpu_header_t gtpu
Definition: mobile.h:158
static char * srv6_end_error_v6_d_di_strings[]
Definition: node.c:220
#define foreach_srv6_end_v6_dt_error
Definition: node.c:132
#define foreach_srv6_end_v6_d_error
Definition: node.c:124
u8 ip_version_and_header_length
Definition: ip4_packet.h:138
#define SRV6_GTP6_DT46
Definition: mobile.h:43
ip6_header_t cache_hdr
Definition: mobile.h:239
gtpu_exthdr_t ext[0]
Definition: mobile.h:96
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:304
srv6_t_m_gtp4_dt_next_t
Definition: node.c:281
static u16 hash_uword_to_u16(uword *key)
Definition: node.c:290
#define SRH_TLV_USER_PLANE_CONTAINER
Definition: mobile.h:70
#define GTPU_TYPE_ERROR_INDICATION
Definition: mobile.h:102
ip6srv_combo_header_t cache_hdr
Definition: mobile.h:282
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:247
ip6_address_t dst_address
Definition: ip6_packet.h:310
#define SRV6_GTP4_DT4
Definition: mobile.h:46