FD.io VPP  v21.01
Vector Packet Processing
node.c
Go to the documentation of this file.
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;
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  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;
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  {
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 
1548  (((next0 ==
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 
1561  SRV6_END_ERROR_M_GTP6_E_BAD_PACKETS, bad_n);
1562 
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
1572  vlib_frame_t * frame)
1573 {
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 
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 =
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  {
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 
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  {
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  {
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 =
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
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
1912  >> 28) != 4)
1913  {
1914  // Bad encap packet.
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
1925  >> 28) != 6)
1926  {
1927  // Bad encap packet.
1929  bad_n++;
1930  goto DONE;
1931  }
1932  }
1933  else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
1934  {
1936  }
1937  }
1938  else
1939  {
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 
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
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
1980  >> 28) != 4)
1981  {
1982  // Bad encap packet.
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
1993  >> 28) != 6)
1994  {
1995  // Bad encap packet.
1997  bad_n++;
1998  goto DONE;
1999  }
2000  }
2001  else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
2002  {
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));
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  {
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:
2050  (((next0 ==
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 
2063  SRV6_END_ERROR_M_GTP6_D_BAD_PACKETS, bad_n);
2064 
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
2074  vlib_frame_t * frame)
2075 {
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 
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 =
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  {
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 
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  {
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  {
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 =
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));
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
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
2453  28) != 4)
2454  {
2455  // Bad encap packet.
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
2466  28) != 6)
2467  {
2468  // Bad encap packet.
2470  bad_n++;
2471  goto DONE;
2472  }
2473  }
2474  else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
2475  {
2477  }
2478  }
2479  else
2480  {
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  {
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:
2504  (((next0 ==
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 
2518  SRV6_END_ERROR_M_GTP6_D_DI_BAD_PACKETS, bad_n);
2519 
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
2529  vlib_frame_t * frame)
2530 {
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 
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 =
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  {
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);
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  {
2630  bad_n++;
2631  goto DONE;
2632  }
2633 
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
2643  != 6)
2644  {
2646  bad_n++;
2647  goto DONE;
2648  }
2649 
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
2669  == 6)
2670  {
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
2688  == 4)
2689  {
2690  vlib_buffer_advance (b0, (word) hdrlen);
2692  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2693  ls_param->fib4_index;
2694  }
2695  else
2696  {
2698  bad_n++;
2699  goto DONE;
2700  }
2701  }
2702  else
2703  {
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  {
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:
2726  (((next0 ==
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 
2739  SRV6_END_ERROR_M_GTP6_DT_BAD_PACKETS, bad_n);
2740 
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
2750  vlib_frame_t * frame)
2751 {
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 
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 =
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  {
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);
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  {
2850  bad_n++;
2851  goto DONE;
2852  }
2853 
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
2863  != 6)
2864  {
2866  bad_n++;
2867  goto DONE;
2868  }
2869 
2871  if ((ip6->dst_address.as_u8[0] == 0xff)
2872  && ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80))
2873  {
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
2890  == 6)
2891  {
2893  if ((ip6->dst_address.as_u8[0] == 0xff)
2894  && ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80))
2895  {
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
2910  == 4)
2911  {
2912  vlib_buffer_advance (b0, (word) hdrlen);
2914  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2915  ls_param->fib4_index;
2916  }
2917  else
2918  {
2920  bad_n++;
2921  goto DONE;
2922  }
2923  }
2924  else
2925  {
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  {
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 
2955  SRV6_T_ERROR_M_GTP4_DT_BAD_PACKETS, bad_n);
2956 
2958  SRV6_T_ERROR_M_GTP4_DT_PACKETS, good_n);
2959 
2960  return frame->n_vectors;
2961 }
2962 
2964 {
2965  .name = "srv6-end-m-gtp6-e",.vector_size = sizeof (u32),.format_trace =
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  {
2972  "error-drop",[SRV6_END_M_GTP6_E_NEXT_LOOKUP] = "ip6-lookup",}
2973 ,};
2974 
2976 {
2977  .name = "srv6-end-m-gtp6-d",.vector_size = sizeof (u32),.format_trace =
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  {
2984  "error-drop",[SRV6_END_M_GTP6_D_NEXT_LOOKUP] = "ip6-lookup",}
2985 ,};
2986 
2988 {
2989  .name = "srv6-end-m-gtp6-d-di",.vector_size = sizeof (u32),.format_trace =
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 
3000 {
3001  .name = "srv6-end-m-gtp6-dt",.vector_size = sizeof (u32),.format_trace =
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  {
3008  "error-drop",
3010  = "ip4-lookup",[SRV6_END_M_GTP6_DT_NEXT_LOOKUP6] = "ip6-lookup",}
3011 ,};
3012 
3014 {
3015  .name = "srv6-t-m-gtp4-dt",.vector_size = sizeof (u32),.format_trace =
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  {
3022  "error-drop",
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 */
#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:87
#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:239
#define SRV6_GTP_UDP_DST_PORT
Definition: mobile.h:29
ip4_address_t src_address
Definition: ip4_packet.h:125
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:122
#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:2987
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:250
#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
vlib_main_t * vm
Definition: in2out_ed.c:1578
#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:203
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
u32 sl_index
Definition: sr.api:35
#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:3013
#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:125
#define SRH_TAG_END_MARKER
Definition: mobile.h:65
union gtpu_pdu_session_t::@152 u
SR Segment List (SID list)
Definition: sr.h:70
description fragment has unexpected format
Definition: map.api:433
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:546
#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:2975
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:233
void * plugin_mem
Definition: sr.h:84
srv6_end_error_v6_dt_t
Definition: node.c:180
#define PREDICT_FALSE(x)
Definition: clib.h:121
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:391
#define SRV6_PDU_SESSION_R_BIT_MASK
Definition: mobile.h:141
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:1231
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:170
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:2963
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:67
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
__clib_export uword hash_memory(void *p, word n_bytes, uword state)
Definition: hash.c:275
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:1578
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
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:252
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
udp_header_t udp
Definition: mobile.h:148
typedef key
Definition: ipsec_types.api:86
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:2999
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
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1579
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:297
u32 index
Definition: flow_types.api:221
static char * srv6_end_error_v4_strings[]
Definition: node.c:196
u8 restart_counter
Definition: mobile.h:76
u16 port
Definition: lb_types.api:73
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
u32 teid
Definition: flow_types.api:182
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
gtpu_header_t gtpu
Definition: mobile.h:158
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:634
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:93
#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:302
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:314
ip6_address_t dst_address
Definition: ip6_packet.h:310
#define SRV6_GTP4_DT4
Definition: mobile.h:46