FD.io VPP  v20.01-48-g3e0dafb74
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 
22 
23 typedef struct
24 {
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 typedef enum
133 {
134 #define _(sym,str) SRV6_END_ERROR_##sym,
136 #undef _
139 
140 typedef enum
141 {
142 #define _(sym,str) SRV6_T_ERROR_##sym,
144 #undef _
147 
148 typedef enum
149 {
150 #define _(sym,str) SRV6_END_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 static char *srv6_end_error_v4_strings[] = {
173 #define _(sym,string) string,
175 #undef _
176 };
177 
178 static char *srv6_t_error_v4_d_strings[] = {
179 #define _(sym,string) string,
181 #undef _
182 };
183 
184 static char *srv6_end_error_v6_e_strings[] = {
185 #define _(sym,string) string,
187 #undef _
188 };
189 
190 static char *srv6_end_error_v6_d_strings[] = {
191 #define _(sym,string) string,
193 #undef _
194 };
195 
197 #define _(sym,string) string,
199 #undef _
200 };
201 
202 typedef enum
203 {
208 
209 typedef enum
210 {
215 
216 typedef enum
217 {
222 
223 typedef enum
224 {
229 
230 typedef enum
231 {
236 
237 static inline u16
239 {
240  u16 *val;
241  val = (u16 *) key;
242 #if uword_bits == 64
243  return val[0] ^ val[1] ^ val[2] ^ val[3];
244 #else
245  return val[0] ^ val[1];
246 #endif
247 }
248 
249 static inline u8
251 {
252  u16 val;
253 
254  val = clib_net_to_host_u16 (tag);
255  if (val & SRH_TAG_ECHO_REPLY)
256  return GTPU_TYPE_ECHO_REPLY;
257  else if (val & SRH_TAG_ECHO_REQUEST)
258  return GTPU_TYPE_ECHO_REQUEST;
259  else if (val & SRH_TAG_ERROR_INDICATION)
261  else if (val & SRH_TAG_END_MARKER)
262  return GTPU_TYPE_END_MARKER;
263 
264  return GTPU_TYPE_GTPU;
265 }
266 
267 // Function for SRv6 GTP4.E function.
271 {
273  ip6_sr_main_t *sm2 = &sr_main;
274  u32 n_left_from, next_index, *from, *to_next;
275  u32 thread_index = vm->thread_index;
276 
277  u32 good_n = 0, bad_n = 0;
278 
279  from = vlib_frame_vector_args (frame);
280  n_left_from = frame->n_vectors;
281  next_index = node->cached_next_index;
282 
283  while (n_left_from > 0)
284  {
285  u32 n_left_to_next;
286 
287  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
288 
289  while (n_left_from > 0 && n_left_to_next > 0)
290  {
291  u32 bi0;
292  vlib_buffer_t *b0;
293  ip6_sr_localsid_t *ls0;
294  srv6_end_gtp4_param_t *ls_param;
295 
296  ip6srv_combo_header_t *ip6srv0;
297  ip6_address_t src0, dst0;
298 
299  ip4_gtpu_header_t *hdr0 = NULL;
300  uword len0;
301 
303 
304  // defaults
305  bi0 = from[0];
306  to_next[0] = bi0;
307  from += 1;
308  to_next += 1;
309  n_left_from -= 1;
310  n_left_to_next -= 1;
311 
312  b0 = vlib_get_buffer (vm, bi0);
313  ls0 =
315  vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
316 
317  ls_param = (srv6_end_gtp4_param_t *) ls0->plugin_mem;
318 
319  ip6srv0 = vlib_buffer_get_current (b0);
320  src0 = ip6srv0->ip.src_address;
321  dst0 = ip6srv0->ip.dst_address;
322 
323  len0 = vlib_buffer_length_in_chain (vm, b0);
324 
325  if ((ip6srv0->ip.protocol == IPPROTO_IPV6_ROUTE
326  && len0 <
327  sizeof (ip6srv_combo_header_t) + ip6srv0->sr.length * 8)
328  || (len0 < sizeof (ip6_header_t)))
329  {
331 
332  bad_n++;
333  }
334  else
335  {
336  u8 gtpu_type = 0;
337  u16 tag = 0;
338  u32 teid = 0;
339  u8 *teid8p = (u8 *) & teid;
340  u8 qfi = 0;
341  u16 seq = 0;
342  u32 index;
343  u32 offset, shift;
344  u32 hdrlen = 0;
345  uword key;
346  u16 port;
347  ip4_address_t dst4;
348  void *p;
349 
350  // we need to be sure there is enough space before
351  // ip6srv0 header, there is some extra space
352  // in the pre_data area for this kind of
353  // logic
354 
355  // jump over variable length data
356  // not sure about the length
357  if (ip6srv0->ip.protocol == IPPROTO_IPV6_ROUTE)
358  {
359  tag = ip6srv0->sr.tag;
360 
362  (word) sizeof (ip6srv_combo_header_t) +
363  ip6srv0->sr.length * 8);
364  }
365  else
366  {
367  vlib_buffer_advance (b0, (word) sizeof (ip6_header_t));
368  }
369 
370  // get length of encapsulated IPv6 packet (the remaining part)
371  p = vlib_buffer_get_current (b0);
372 
373  len0 = vlib_buffer_length_in_chain (vm, b0);
374 
375  offset = ls0->localsid_len / 8;
376  shift = ls0->localsid_len % 8;
377 
378  gtpu_type = gtpu_type_get (tag);
379 
380  if (PREDICT_TRUE (shift == 0))
381  {
382  clib_memcpy_fast (&dst4.as_u8[0], &dst0.as_u8[offset], 4);
383 
384  qfi = dst0.as_u8[offset + 4];
385 
386  if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
387  || gtpu_type == GTPU_TYPE_ECHO_REPLY
388  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
389  {
390  clib_memcpy_fast (&seq, &dst0.as_u8[offset + 5], 2);
391  }
392  else
393  {
394  clib_memcpy_fast (teid8p, &dst0.as_u8[offset + 5], 4);
395  }
396  }
397  else
398  {
399  u8 *sp;
400 
401  for (index = 0; index < 4; index++)
402  {
403  dst4.as_u8[index] = dst0.as_u8[offset + index] << shift;
404  dst4.as_u8[index] |=
405  dst0.as_u8[offset + index + 1] >> (8 - shift);
406  }
407 
408  qfi |= dst0.as_u8[offset + 4] << shift;
409  qfi |= dst0.as_u8[offset + 5] >> (8 - shift);
410 
411  if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
412  || gtpu_type == GTPU_TYPE_ECHO_REPLY
413  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
414  {
415  sp = (u8 *) & seq;
416  for (index = 0; index < 2; index++)
417  {
418  sp[index] = dst0.as_u8[offset + 5 + index] << shift;
419  sp[index] =
420  dst0.as_u8[offset + 6 + index] >> (8 - shift);
421  }
422  }
423  else
424  {
425  for (index = 0; index < 4; index++)
426  {
427  *teid8p = dst0.as_u8[offset + 5 + index] << shift;
428  *teid8p |=
429  dst0.as_u8[offset + 6 + index] >> (8 - shift);
430  teid8p++;
431  }
432  }
433  }
434 
435  if (qfi)
436  {
437  hdrlen =
438  sizeof (gtpu_exthdr_t) + sizeof (gtpu_pdu_session_t);
439  }
440  else if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
441  || gtpu_type == GTPU_TYPE_ECHO_REPLY
442  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
443  {
444  hdrlen = sizeof (gtpu_exthdr_t);
445  }
446  len0 += hdrlen;
447 
448  hdrlen += sizeof (ip4_gtpu_header_t);
449 
450  // IPv4 GTP-U header creation.
451  vlib_buffer_advance (b0, -(word) hdrlen);
452 
453  hdr0 = vlib_buffer_get_current (b0);
454 
455  clib_memcpy_fast (hdr0, &sm->cache_hdr,
456  sizeof (ip4_gtpu_header_t));
457 
458  hdr0->ip4.dst_address.as_u32 = dst4.as_u32;
459 
460  hdr0->gtpu.teid = teid;
461  hdr0->gtpu.length = clib_host_to_net_u16 (len0);
462 
463  hdr0->gtpu.type = gtpu_type;
464 
465  if (qfi)
466  {
467  u8 type = 0;
468  gtpu_pdu_session_t *sess;
469 
471 
472  hdr0->gtpu.ext->seq = 0;
473 
474  hdr0->gtpu.ext->npdu_num = 0;
476 
477  type = qfi & SRV6_PDU_SESSION_U_BIT_MASK;
478 
479  qfi =
480  ((qfi & SRV6_PDU_SESSION_QFI_MASK) >> 2) |
481  ((qfi & SRV6_PDU_SESSION_R_BIT_MASK) << 5);
482 
483  sess =
484  (gtpu_pdu_session_t *) (((char *) hdr0) +
485  sizeof (ip4_gtpu_header_t) +
486  sizeof (gtpu_exthdr_t));
487  sess->exthdrlen = 1;
488  sess->type = type;
489  sess->spare = 0;
490  sess->u.val = qfi;
491  sess->nextexthdr = 0;
492  }
493 
494  if (gtpu_type == GTPU_TYPE_ECHO_REPLY
495  || gtpu_type == GTPU_TYPE_ECHO_REQUEST
496  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
497  {
498  hdr0->gtpu.ver_flags |= GTPU_SEQ_FLAG;
499  hdr0->gtpu.ext->seq = seq;
500  hdr0->gtpu.ext->npdu_num = 0;
501  hdr0->gtpu.ext->nextexthdr = 0;
502  }
503 
504  offset = ls_param->v4src_position / 8;
505  shift = ls_param->v4src_position % 8;
506 
507  if (PREDICT_TRUE (shift == 0))
508  {
509  for (index = 0; index < 4; index++)
510  {
511  hdr0->ip4.src_address.as_u8[index] =
512  src0.as_u8[offset + index];
513  }
514  }
515  else
516  {
517  for (index = 0; index < 4; index++)
518  {
519  hdr0->ip4.src_address.as_u8[index] =
520  src0.as_u8[offset + index] << shift;
521  hdr0->ip4.src_address.as_u8[index] |=
522  src0.as_u8[offset + index + 1] >> (8 - shift);
523  }
524  }
525 
526  key = hash_memory (p, len0, 0);
527  port = hash_uword_to_u16 (&key);
528  hdr0->udp.src_port = port;
529 
530  hdr0->udp.length = clib_host_to_net_u16 (len0 +
531  sizeof (udp_header_t) +
532  sizeof
533  (gtpu_header_t));
534 
535  hdr0->ip4.length = clib_host_to_net_u16 (len0 +
536  sizeof
538 
539  hdr0->ip4.checksum = ip4_header_checksum (&hdr0->ip4);
540 
541  good_n++;
542 
543  if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
544  PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
545  {
547  vlib_add_trace (vm, node, b0, sizeof (*tr));
549  sizeof (tr->src.as_u8));
551  sizeof (tr->dst.as_u8));
552  tr->teid = hdr0->gtpu.teid;
553  }
554  }
555 
557  (((next0 ==
559  &(sm2->sr_ls_valid_counters)), thread_index,
560  ls0 - sm2->localsids, 1, vlib_buffer_length_in_chain (vm, b0));
561 
562  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
563  n_left_to_next, bi0, next0);
564  }
565 
566  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
567  }
568 
570  SRV6_END_ERROR_M_GTP4_E_BAD_PACKETS, bad_n);
571 
573  SRV6_END_ERROR_M_GTP4_E_PACKETS, good_n);
574 
575  return frame->n_vectors;
576 }
577 
578 // Function for SRv6 GTP4.D function.
582 {
584  ip6_sr_main_t *sm2 = &sr_main;
585  u32 n_left_from, next_index, *from, *to_next;
586 
587  u32 good_n = 0, bad_n = 0;
588 
589  from = vlib_frame_vector_args (frame);
590  n_left_from = frame->n_vectors;
591  next_index = node->cached_next_index;
592 
593  while (n_left_from > 0)
594  {
595  u32 n_left_to_next;
596 
597  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
598 
599  while (n_left_from > 0 && n_left_to_next > 0)
600  {
601  u32 bi0;
602  vlib_buffer_t *b0;
603  ip6_sr_sl_t *sl0;
604  srv6_end_gtp4_param_t *ls_param;
605  ip4_header_t *ip4;
606 
607  uword len0;
608 
610 
611  // defaults
612  bi0 = from[0];
613  to_next[0] = bi0;
614  from += 1;
615  to_next += 1;
616  n_left_from -= 1;
617  n_left_to_next -= 1;
618 
619  b0 = vlib_get_buffer (vm, bi0);
620 
621  sl0 =
623  vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
624 
625  ls_param = (srv6_end_gtp4_param_t *) sl0->plugin_mem;
626 
627  len0 = vlib_buffer_length_in_chain (vm, b0);
628 
629  ip4 = vlib_buffer_get_current (b0);
630 
631  if (ip4->protocol != IP_PROTOCOL_UDP
632  || len0 < sizeof (ip4_gtpu_header_t))
633  {
635 
636  bad_n++;
637  }
638  else
639  {
640  uword *p;
641  ip6_sr_policy_t *sr_policy = NULL;
642  ip6_sr_sl_t *sl = NULL;
643  u32 *sl_index;
644  u32 hdr_len;
645 
646  ip4_gtpu_header_t *hdr;
648  u8 *srcp, *dstp;
649  ip6_header_t *encap = NULL;
650  ip6_address_t seg;
651  ip6_address_t src6;
652  u8 gtpu_type;
653  u32 teid;
654  u8 *teidp;
655  u8 qfi = 0;
656  u8 *qfip = NULL;
657  u16 seq = 0;
658  u8 *seqp = NULL;
659  u32 offset, shift, index;
660  ip6srv_combo_header_t *ip6srv;
661  gtpu_pdu_session_t *sess = NULL;
662 
663  // Decap from GTP-U.
664  hdr = (ip4_gtpu_header_t *) ip4;
665 
666  hdr_len = sizeof (ip4_gtpu_header_t);
667 
668  teid = hdr->gtpu.teid;
669  teidp = (u8 *) & teid;
670 
671  gtpu_type = hdr->gtpu.type;
672 
674  {
675  // Extention header.
676  hdr_len += sizeof (gtpu_exthdr_t);
677 
678  seq = hdr->gtpu.ext->seq;
679  seqp = (u8 *) & seq;
680 
682  {
683  // PDU Session Container.
684  sess =
685  (gtpu_pdu_session_t *) (((char *) hdr) + hdr_len);
686  qfi = sess->u.val & ~GTPU_PDU_SESSION_P_BIT_MASK;
687  qfip = (u8 *) & qfi;
688 
689  hdr_len += sizeof (gtpu_pdu_session_t);
690 
691  if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
692  {
693  hdr_len += sizeof (gtpu_paging_policy_t);
694  }
695  }
696  }
697 
698  src = hdr->ip4.src_address;
699  srcp = (u8 *) & src;
700 
701  dst = hdr->ip4.dst_address;
702  dstp = (u8 *) & dst;
703 
704  seg = ls_param->sr_prefix;
705 
706  offset = ls_param->sr_prefixlen / 8;
707  shift = ls_param->sr_prefixlen % 8;
708 
709  if (PREDICT_TRUE (shift == 0))
710  {
711  clib_memcpy_fast (&seg.as_u8[offset], dstp, 4);
712 
713  if (qfip)
714  {
715  qfi =
716  ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
717  ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
718 
719  if (sess->type)
720  {
722  }
723 
724  seg.as_u8[offset + 4] = qfi;
725  }
726 
727  if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
728  || gtpu_type == GTPU_TYPE_ECHO_REPLY
729  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
730  {
731  clib_memcpy_fast (&seg.as_u8[offset + 5], seqp, 2);
732  }
733  else
734  {
735  clib_memcpy_fast (&seg.as_u8[offset + 5], teidp, 4);
736  }
737  }
738  else
739  {
740  for (index = 0; index < 4; index++)
741  {
742  seg.as_u8[offset + index] |= dstp[index] >> shift;
743  seg.as_u8[offset + index + 1] |=
744  dstp[index] << (8 - shift);
745  }
746 
747  if (qfip)
748  {
749  qfi =
750  ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
751  ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
752 
753  if (sess->type)
754  {
756  }
757 
758  seg.as_u8[offset + 4] |= qfi >> shift;
759  seg.as_u8[offset + 5] |= qfi << (8 - shift);
760  }
761 
762  if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
763  || gtpu_type == GTPU_TYPE_ECHO_REPLY
764  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
765  {
766  for (index = 0; index < 2; index++)
767  {
768  seg.as_u8[offset + 5 + index] |=
769  seqp[index] >> shift;
770  seg.as_u8[offset + 6 + index] |=
771  seqp[index] << (8 - shift);
772  }
773  }
774  else
775  {
776  for (index = 0; index < 4; index++)
777  {
778  seg.as_u8[offset + index + 5] |=
779  teidp[index] >> shift;
780  seg.as_u8[offset + index + 6] |=
781  teidp[index] << (8 - shift);
782  }
783  }
784  }
785 
786  src6 = ls_param->v6src_prefix;
787 
788  offset = ls_param->v6src_prefixlen / 8;
789  shift = ls_param->v6src_prefixlen % 8;
790 
791  if (PREDICT_TRUE (shift == 0))
792  {
793  clib_memcpy_fast (&src6.as_u8[offset], srcp, 4);
794  }
795  else
796  {
797  for (index = 0; index < 4; index++)
798  {
799  src6.as_u8[offset + index] |= srcp[offset] >> shift;
800  src6.as_u8[offset + index + 1] |=
801  srcp[offset] << (8 - shift);
802  }
803  }
804 
805  vlib_buffer_advance (b0, (word) hdr_len);
806 
807  // Encap to SRv6.
808  if (PREDICT_TRUE (gtpu_type == GTPU_TYPE_GTPU))
809  {
810  encap = vlib_buffer_get_current (b0);
811  }
812 
813  len0 = vlib_buffer_length_in_chain (vm, b0);
814 
815  p =
817  &ls_param->sr_prefix);
818  if (p)
819  {
820  sr_policy = pool_elt_at_index (sm2->sr_policies, p[0]);
821  }
822 
823  if (sr_policy)
824  {
825  vec_foreach (sl_index, sr_policy->segments_lists)
826  {
827  sl = pool_elt_at_index (sm2->sid_lists, *sl_index);
828  if (sl != NULL)
829  break;
830  }
831  }
832 
833  if (sl)
834  {
835  hdr_len = sizeof (ip6srv_combo_header_t);
836  hdr_len += vec_len (sl->segments) * sizeof (ip6_address_t);
837  hdr_len += sizeof (ip6_address_t);
838  }
839  else
840  {
841  hdr_len = sizeof (ip6_header_t);
842 
843  if (PREDICT_FALSE (gtpu_type != GTPU_TYPE_GTPU))
844  {
845  hdr_len += sizeof (ip6_sr_header_t);
846  hdr_len += sizeof (ip6_address_t);
847  }
848  }
849 
850  vlib_buffer_advance (b0, -(word) hdr_len);
851  ip6srv = vlib_buffer_get_current (b0);
852 
853  if (sl)
854  {
855  clib_memcpy_fast (ip6srv, sl->rewrite,
856  vec_len (sl->rewrite));
857 
858  if (vec_len (sl->segments) > 1)
859  {
860  ip6srv->sr.tag =
861  clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
862 
863  ip6srv->sr.segments_left += 1;
864  ip6srv->sr.last_entry += 1;
865 
866  ip6srv->sr.length += sizeof (ip6_address_t) / 8;
867  ip6srv->sr.segments[0] = seg;
868 
869  clib_memcpy_fast (&ip6srv->sr.segments[1],
870  (u8 *) (sl->rewrite +
871  sizeof (ip6_header_t) +
872  sizeof (ip6_sr_header_t)),
873  vec_len (sl->segments) *
874  sizeof (ip6_address_t));
875  }
876  else
877  {
878  ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
879 
880  ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
881 
882  ip6srv->sr.segments_left = 1;
883  ip6srv->sr.last_entry = 0;
884 
885  ip6srv->sr.length =
886  ((sizeof (ip6_sr_header_t) +
887  sizeof (ip6_address_t)) / 8) - 1;
888  ip6srv->sr.flags = 0;
889 
890  ip6srv->sr.tag =
891  clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
892 
893  ip6srv->sr.segments[0] = seg;
894  if (vec_len (sl->segments))
895  {
896  ip6srv->sr.segments[1] = sl->segments[0];
897  ip6srv->sr.length += sizeof (ip6_address_t) / 8;
898  ip6srv->sr.last_entry++;
899  }
900  }
901 
902  if (PREDICT_TRUE (encap != NULL))
903  {
904  if (ls_param->nhtype == SRV6_NHTYPE_NONE)
905  {
906  if ((clib_net_to_host_u32
908  >> 28) == 6)
909  ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
910  else
911  ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
912  }
913  else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
914  {
915  ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
916  if ((clib_net_to_host_u32
918  >> 28) != 4)
919  {
920  // Bad encap packet.
922  bad_n++;
923  goto DONE;
924  }
925  }
926  else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
927  {
928  ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
929  if ((clib_net_to_host_u32
931  >> 28) != 6)
932  {
933  // Bad encap packet.
935  bad_n++;
936  goto DONE;
937  }
938  }
939  else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
940  {
941  ip6srv->sr.protocol = IP_PROTOCOL_NONE;
942  }
943  }
944  else
945  {
946  ip6srv->sr.protocol = IP_PROTOCOL_NONE;
947  }
948  }
949  else
950  {
951  clib_memcpy_fast (ip6srv, &sm->cache_hdr,
952  sizeof (ip6_header_t));
953 
954  ip6srv->ip.dst_address = seg;
955 
956  if (PREDICT_FALSE (gtpu_type != GTPU_TYPE_GTPU))
957  {
958  ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
959 
960  ip6srv->sr.protocol = IP_PROTOCOL_NONE;
961 
962  ip6srv->sr.tag =
963  clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
964 
965  ip6srv->sr.segments_left = 0;
966  ip6srv->sr.last_entry = 0;
967 
968  ip6srv->sr.length = sizeof (ip6_address_t) / 8;
969  ip6srv->sr.segments[0] = seg;
970  }
971  else
972  {
973  if (ls_param->nhtype == SRV6_NHTYPE_NONE)
974  {
975  if ((clib_net_to_host_u32
977  >> 28) == 6)
978  ip6srv->ip.protocol = IP_PROTOCOL_IPV6;
979  else
980  ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
981  }
982  else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
983  {
984  ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
985  if ((clib_net_to_host_u32
987  >> 28) != 4)
988  {
989  // Bad encap packet.
991  bad_n++;
992  goto DONE;
993  }
994  }
995  else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
996  {
997  ip6srv->ip.protocol = IP_PROTOCOL_IPV6;
998  if ((clib_net_to_host_u32
1000  >> 28) != 6)
1001  {
1002  // Bad encap packet.
1003  next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
1004  bad_n++;
1005  goto DONE;
1006  }
1007  }
1008  else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
1009  {
1010  ip6srv->ip.protocol = IP_PROTOCOL_NONE;
1011  }
1012  }
1013  }
1014 
1015  ip6srv->ip.src_address = src6;
1016 
1017  ip6srv->ip.payload_length =
1018  clib_host_to_net_u16 (len0 + hdr_len - sizeof (ip6_header_t));
1019 
1020  good_n++;
1021 
1022  if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
1023  PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1024  {
1026  vlib_add_trace (vm, node, b0, sizeof (*tr));
1027  clib_memcpy (tr->src.as_u8, ip6srv->ip.src_address.as_u8,
1028  sizeof (tr->src.as_u8));
1029  clib_memcpy (tr->dst.as_u8, ip6srv->ip.dst_address.as_u8,
1030  sizeof (tr->dst.as_u8));
1031  }
1032  }
1033 
1034  DONE:
1035  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1036  n_left_to_next, bi0, next0);
1037  }
1038 
1039  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1040  }
1041 
1043  SRV6_T_ERROR_M_GTP4_D_BAD_PACKETS, bad_n);
1044 
1046  SRV6_T_ERROR_M_GTP4_D_PACKETS, good_n);
1047 
1048  return frame->n_vectors;
1049 }
1050 
1052 {
1053  .name = "srv6-end-m-gtp4-e",.vector_size = sizeof (u32),.format_trace =
1055  ARRAY_LEN (srv6_end_error_v4_strings),.error_strings =
1056  srv6_end_error_v4_strings,.n_next_nodes =
1057  SRV6_END_M_GTP4_E_N_NEXT,.next_nodes =
1058  {
1059  [SRV6_END_M_GTP4_E_NEXT_DROP] = "error-drop",
1060  [SRV6_END_M_GTP4_E_NEXT_LOOKUP] = "ip4-lookup",}
1061 ,};
1062 
1064 {
1065  .name = "srv6-t-m-gtp4-d",.vector_size = sizeof (u32),.format_trace =
1067  ARRAY_LEN (srv6_t_error_v4_d_strings),.error_strings =
1068  srv6_t_error_v4_d_strings,.n_next_nodes =
1069  SRV6_T_M_GTP4_D_N_NEXT,.next_nodes =
1070  {
1071  [SRV6_T_M_GTP4_D_NEXT_DROP] = "error-drop",
1072  [SRV6_T_M_GTP4_D_NEXT_LOOKUP] = "ip6-lookup",}
1073 ,};
1074 
1075 // Function for SRv6 GTP6.E function
1078  vlib_frame_t * frame)
1079 {
1081  ip6_sr_main_t *sm2 = &sr_main;
1082  u32 n_left_from, next_index, *from, *to_next;
1083  u32 thread_index = vm->thread_index;
1084 
1085  u32 good_n = 0, bad_n = 0;
1086 
1087  from = vlib_frame_vector_args (frame);
1088  n_left_from = frame->n_vectors;
1089  next_index = node->cached_next_index;
1090 
1091  while (n_left_from > 0)
1092  {
1093  u32 n_left_to_next;
1094 
1095  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1096 
1097  while (n_left_from > 0 && n_left_to_next > 0)
1098  {
1099  u32 bi0;
1100  vlib_buffer_t *b0;
1101  ip6_sr_localsid_t *ls0;
1102 
1103  ip6srv_combo_header_t *ip6srv0;
1104  ip6_address_t dst0, src0, seg0;
1105 
1106  ip6_gtpu_header_t *hdr0 = NULL;
1107  uword len0;
1108  uword key;
1109  u16 port;
1110  u16 tag;
1111  void *p;
1112 
1114 
1115  // defaults
1116  bi0 = from[0];
1117  to_next[0] = bi0;
1118  from += 1;
1119  to_next += 1;
1120  n_left_from -= 1;
1121  n_left_to_next -= 1;
1122 
1123  b0 = vlib_get_buffer (vm, bi0);
1124  ls0 =
1126  vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1127 
1128  ip6srv0 = vlib_buffer_get_current (b0);
1129  dst0 = ip6srv0->ip.dst_address;
1130  src0 = ip6srv0->ip.src_address;
1131  seg0 = ip6srv0->sr.segments[0];
1132 
1133  tag = ip6srv0->sr.tag;
1134 
1135  len0 = vlib_buffer_length_in_chain (vm, b0);
1136 
1137  if ((ip6srv0->ip.protocol != IPPROTO_IPV6_ROUTE)
1138  || (len0 <
1139  sizeof (ip6srv_combo_header_t) + 8 * ip6srv0->sr.length))
1140  {
1142 
1143  bad_n++;
1144  }
1145  else
1146  {
1147  // we need to be sure there is enough space before
1148  // ip6srv0 header, there is some extra space
1149  // in the pre_data area for this kind of
1150  // logic
1151 
1152  // jump over variable length data
1153  // not sure about the length
1155  ip6srv0->sr.length * 8);
1156 
1157  // get length of encapsulated IPv6 packet (the remaining part)
1158  p = vlib_buffer_get_current (b0);
1159 
1160  len0 = vlib_buffer_length_in_chain (vm, b0);
1161 
1162  u32 teid = 0;
1163  u8 *teid8p = (u8 *) & teid;
1164  u8 qfi = 0;
1165  u16 seq = 0;
1166  u8 gtpu_type = 0;
1167  u16 index;
1168  u16 offset, shift;
1169  u32 hdrlen = 0;
1170 
1171  index = ls0->localsid_len;
1172  index += 8;
1173  offset = index / 8;
1174  shift = index % 8;
1175 
1176  gtpu_type = gtpu_type_get (tag);
1177 
1178  if (PREDICT_TRUE (shift == 0))
1179  {
1180  if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1181  || gtpu_type == GTPU_TYPE_ECHO_REPLY
1182  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1183  {
1184  clib_memcpy_fast (&seq, &dst0.as_u8[offset], 2);
1185  }
1186  else
1187  {
1188  clib_memcpy_fast (teid8p, &dst0.as_u8[offset], 4);
1189  }
1190 
1191  qfi = dst0.as_u8[offset + 4];
1192  }
1193  else
1194  {
1195  u8 *sp;
1196 
1197  if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1198  || gtpu_type == GTPU_TYPE_ECHO_REPLY
1199  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1200  {
1201  sp = (u8 *) & seq;
1202  for (index = 0; index < 2; index++)
1203  {
1204  sp[index] = dst0.as_u8[offset + index] << shift;
1205  sp[index] =
1206  dst0.as_u8[offset + index + 1] >> (8 - shift);
1207  }
1208  }
1209  else
1210  {
1211  for (index = 0; index < 4; index++)
1212  {
1213  *teid8p = dst0.as_u8[offset + index] << shift;
1214  *teid8p |=
1215  dst0.as_u8[offset + index + 1] >> (8 - shift);
1216  teid8p++;
1217  }
1218  }
1219 
1220  qfi |= dst0.as_u8[offset + 4] << shift;
1221  qfi |= dst0.as_u8[offset + 5] >> (8 - shift);
1222  }
1223 
1224  if (qfi)
1225  {
1226  hdrlen =
1227  sizeof (gtpu_exthdr_t) + sizeof (gtpu_pdu_session_t);
1228  }
1229  else if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1230  || gtpu_type == GTPU_TYPE_ECHO_REPLY
1231  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1232  {
1233  hdrlen = sizeof (gtpu_exthdr_t);
1234  }
1235 
1236  len0 += hdrlen;
1237  hdrlen += sizeof (ip6_gtpu_header_t);
1238 
1239  vlib_buffer_advance (b0, -(word) hdrlen);
1240 
1241  hdr0 = vlib_buffer_get_current (b0);
1242 
1243  clib_memcpy_fast (hdr0, &sm->cache_hdr,
1244  sizeof (ip6_gtpu_header_t));
1245 
1246  hdr0->gtpu.teid = teid;
1247  hdr0->gtpu.length = clib_host_to_net_u16 (len0);
1248 
1249  hdr0->gtpu.type = gtpu_type;
1250 
1251  if (qfi)
1252  {
1253  u8 type = 0;
1254  gtpu_pdu_session_t *sess;
1255 
1256  hdr0->gtpu.ver_flags |= GTPU_EXTHDR_FLAG;
1257 
1258  hdr0->gtpu.ext->seq = 0;
1259  hdr0->gtpu.ext->npdu_num = 0;
1261 
1262  type = qfi & SRV6_PDU_SESSION_U_BIT_MASK;
1263 
1264  qfi =
1265  ((qfi & SRV6_PDU_SESSION_QFI_MASK) >> 2) |
1266  ((qfi & SRV6_PDU_SESSION_R_BIT_MASK) << 5);
1267 
1268  sess =
1269  (gtpu_pdu_session_t *) (((char *) hdr0) +
1270  sizeof (ip6_gtpu_header_t) +
1271  sizeof (gtpu_exthdr_t));
1272  sess->exthdrlen = 1;
1273  sess->type = type;
1274  sess->spare = 0;
1275  sess->u.val = qfi;
1276  sess->nextexthdr = 0;
1277  }
1278 
1279  if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1280  || gtpu_type == GTPU_TYPE_ECHO_REPLY
1281  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1282  {
1283  hdr0->gtpu.ver_flags |= GTPU_SEQ_FLAG;
1284  hdr0->gtpu.ext->seq = seq;
1285  hdr0->gtpu.ext->npdu_num = 0;
1286  hdr0->gtpu.ext->nextexthdr = 0;
1287  }
1288 
1289  hdr0->udp.length = clib_host_to_net_u16 (len0 +
1290  sizeof (udp_header_t) +
1291  sizeof
1292  (gtpu_header_t));
1293 
1295  sizeof (ip6_address_t));
1296  clib_memcpy_fast (hdr0->ip6.dst_address.as_u8, &seg0.as_u8,
1297  sizeof (ip6_address_t));
1298 
1299  hdr0->ip6.payload_length = clib_host_to_net_u16 (len0 +
1300  sizeof
1301  (udp_header_t)
1302  +
1303  sizeof
1304  (gtpu_header_t));
1305 
1306  // UDP source port.
1307  key = hash_memory (p, len0, 0);
1308  port = hash_uword_to_u16 (&key);
1309  hdr0->udp.src_port = port;
1310 
1311  good_n++;
1312 
1313  if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
1314  PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1315  {
1317  vlib_add_trace (vm, node, b0, sizeof (*tr));
1318  clib_memcpy (tr->src.as_u8, hdr0->ip6.src_address.as_u8,
1319  sizeof (ip6_address_t));
1320  clib_memcpy (tr->dst.as_u8, hdr0->ip6.dst_address.as_u8,
1321  sizeof (ip6_address_t));
1322  tr->teid = hdr0->gtpu.teid;
1323  }
1324  }
1325 
1327  (((next0 ==
1329  &(sm2->sr_ls_valid_counters)), thread_index,
1330  ls0 - sm2->localsids, 1, vlib_buffer_length_in_chain (vm, b0));
1331 
1332  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1333  n_left_to_next, bi0, next0);
1334  }
1335 
1336  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1337  }
1338 
1340  SRV6_END_ERROR_M_GTP6_E_BAD_PACKETS, bad_n);
1341 
1343  SRV6_END_ERROR_M_GTP6_E_PACKETS, good_n);
1344 
1345  return frame->n_vectors;
1346 }
1347 
1348 // Function for SRv6 GTP6.D function
1351  vlib_frame_t * frame)
1352 {
1354  ip6_sr_main_t *sm2 = &sr_main;
1355  u32 n_left_from, next_index, *from, *to_next;
1356  u32 thread_index = vm->thread_index;
1357 
1358  u32 good_n = 0, bad_n = 0;
1359 
1360  from = vlib_frame_vector_args (frame);
1361  n_left_from = frame->n_vectors;
1362  next_index = node->cached_next_index;
1363 
1364  while (n_left_from > 0)
1365  {
1366  u32 n_left_to_next;
1367 
1368  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1369 
1370  while (n_left_from > 0 && n_left_to_next > 0)
1371  {
1372  u32 bi0;
1373  vlib_buffer_t *b0;
1374  ip6_sr_localsid_t *ls0;
1375  srv6_end_gtp6_param_t *ls_param;
1376 
1377  ip6_gtpu_header_t *hdr0 = NULL;
1378  uword len0;
1379 
1380  ip6_address_t seg0, src0;
1381  u32 teid = 0;
1382  u8 *teidp;
1383  u8 gtpu_type = 0;
1384  u8 qfi;
1385  u8 *qfip = NULL;
1386  u16 seq = 0;
1387  u8 *seqp = NULL;
1388  u32 offset, shift;
1389  u32 hdrlen;
1390  ip6_header_t *encap = NULL;
1391  gtpu_pdu_session_t *sess = NULL;
1392 
1394 
1395  // defaults
1396  bi0 = from[0];
1397  to_next[0] = bi0;
1398  from += 1;
1399  to_next += 1;
1400  n_left_from -= 1;
1401  n_left_to_next -= 1;
1402 
1403  b0 = vlib_get_buffer (vm, bi0);
1404  ls0 =
1406  vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1407 
1408  ls_param = (srv6_end_gtp6_param_t *) ls0->plugin_mem;
1409 
1410  hdr0 = vlib_buffer_get_current (b0);
1411 
1412  hdrlen = sizeof (ip6_gtpu_header_t);
1413 
1414  len0 = vlib_buffer_length_in_chain (vm, b0);
1415 
1416  if ((hdr0->ip6.protocol != IP_PROTOCOL_UDP)
1417  || (hdr0->udp.dst_port !=
1418  clib_host_to_net_u16 (SRV6_GTP_UDP_DST_PORT))
1419  || (len0 < sizeof (ip6_gtpu_header_t)))
1420  {
1422 
1423  bad_n++;
1424  }
1425  else
1426  {
1427  seg0 = ls_param->sr_prefix;
1428  src0 = hdr0->ip6.src_address;
1429 
1430  gtpu_type = hdr0->gtpu.type;
1431 
1432  teid = hdr0->gtpu.teid;
1433  teidp = (u8 *) & teid;
1434 
1435  if (hdr0->gtpu.ver_flags & (GTPU_EXTHDR_FLAG | GTPU_SEQ_FLAG))
1436  {
1437  // Extention header.
1438  hdrlen += sizeof (gtpu_exthdr_t);
1439 
1440  seq = hdr0->gtpu.ext->seq;
1441  seqp = (u8 *) & seq;
1442 
1444  {
1445  // PDU Session Container.
1446  sess =
1447  (gtpu_pdu_session_t *) (((char *) hdr0) +
1448  sizeof (ip6_gtpu_header_t) +
1449  sizeof (gtpu_exthdr_t));
1450  qfi = sess->u.val & ~GTPU_PDU_SESSION_P_BIT_MASK;
1451  qfip = (u8 *) & qfi;
1452 
1453  hdrlen += sizeof (gtpu_pdu_session_t);
1454 
1455  if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
1456  {
1457  hdrlen += sizeof (gtpu_paging_policy_t);
1458  }
1459  }
1460  }
1461 
1462  offset = ls_param->sr_prefixlen / 8;
1463  shift = ls_param->sr_prefixlen % 8;
1464 
1465  offset += 1;
1466  if (PREDICT_TRUE (shift == 0))
1467  {
1468  if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1469  || gtpu_type == GTPU_TYPE_ECHO_REPLY
1470  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1471  {
1472  if (seqp)
1473  clib_memcpy_fast (&seg0.as_u8[offset], seqp, 2);
1474  }
1475  else
1476  {
1477  clib_memcpy_fast (&seg0.as_u8[offset], teidp, 4);
1478  }
1479 
1480  if (qfip)
1481  {
1482  qfi =
1483  ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
1484  ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
1485 
1486  if (sess->type)
1487  {
1489  }
1490 
1491  seg0.as_u8[offset + 4] = qfi;
1492  }
1493  }
1494  else
1495  {
1496  int idx;
1497 
1498  if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1499  || gtpu_type == GTPU_TYPE_ECHO_REPLY
1500  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1501  {
1502  if (seqp)
1503  {
1504  for (idx = 0; idx < 2; idx++)
1505  {
1506  seg0.as_u8[offset + idx] |= seqp[idx] >> shift;
1507  seg0.as_u8[offset + idx + 1] |=
1508  seqp[idx] << (8 - shift);
1509  }
1510  }
1511  }
1512  else
1513  {
1514  for (idx = 0; idx < 4; idx++)
1515  {
1516  seg0.as_u8[offset + idx] |= teidp[idx] >> shift;
1517  seg0.as_u8[offset + idx + 1] |=
1518  teidp[idx] << (8 - shift);
1519  }
1520  }
1521 
1522  if (qfip)
1523  {
1524  qfi =
1525  ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
1526  ((qfi & ~GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
1527 
1528  if (sess->type)
1529  {
1531  }
1532 
1533  seg0.as_u8[offset + 4] |= qfi >> shift;
1534  seg0.as_u8[offset + 5] |= qfi << (8 - shift);
1535  }
1536  }
1537 
1538  // jump over variable length data
1539  vlib_buffer_advance (b0, (word) hdrlen);
1540 
1541  // get length of encapsulated IPv6 packet (the remaining part)
1542  len0 = vlib_buffer_length_in_chain (vm, b0);
1543 
1544  if (PREDICT_TRUE (gtpu_type == GTPU_TYPE_GTPU))
1545  {
1546  encap = vlib_buffer_get_current (b0);
1547  }
1548 
1549  uword *p;
1550  ip6srv_combo_header_t *ip6srv;
1551  ip6_sr_policy_t *sr_policy = NULL;
1552  ip6_sr_sl_t *sl = NULL;
1553  u32 *sl_index;
1554  u32 hdr_len;
1555 
1556  p =
1558  &ls_param->sr_prefix);
1559  if (p)
1560  {
1561  sr_policy = pool_elt_at_index (sm2->sr_policies, p[0]);
1562  }
1563 
1564  if (sr_policy)
1565  {
1566  vec_foreach (sl_index, sr_policy->segments_lists)
1567  {
1568  sl = pool_elt_at_index (sm2->sid_lists, *sl_index);
1569  if (sl != NULL)
1570  break;
1571  }
1572  }
1573 
1574  if (sl)
1575  {
1576  hdr_len = sizeof (ip6srv_combo_header_t);
1577  hdr_len += vec_len (sl->segments) * sizeof (ip6_address_t);
1578  hdr_len += sizeof (ip6_address_t);
1579  }
1580  else
1581  {
1582  hdr_len = sizeof (ip6_header_t);
1583  if (PREDICT_FALSE (gtpu_type) != GTPU_TYPE_GTPU)
1584  {
1585  hdr_len += sizeof (ip6_sr_header_t);
1586  hdr_len += sizeof (ip6_address_t);
1587  }
1588  }
1589 
1590  // jump back to data[0] or pre_data if required
1591  vlib_buffer_advance (b0, -(word) hdr_len);
1592 
1593  ip6srv = vlib_buffer_get_current (b0);
1594 
1595  if (sl)
1596  {
1597  clib_memcpy_fast (ip6srv, sl->rewrite,
1598  vec_len (sl->rewrite));
1599 
1600  if (vec_len (sl->segments) > 1)
1601  {
1602  ip6srv->ip.src_address = src0;
1603 
1604  ip6srv->sr.tag =
1605  clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1606 
1607  ip6srv->sr.segments_left += 1;
1608  ip6srv->sr.last_entry += 1;
1609 
1610  ip6srv->sr.length += sizeof (ip6_address_t) / 8;
1611  ip6srv->sr.segments[0] = seg0;
1612 
1613  clib_memcpy_fast (&ip6srv->sr.segments[1],
1614  (u8 *) (sl->rewrite +
1615  sizeof (ip6_header_t) +
1616  sizeof (ip6_sr_header_t)),
1617  vec_len (sl->segments) *
1618  sizeof (ip6_address_t));
1619  }
1620  else
1621  {
1622  ip6srv->ip.src_address = src0;
1623  ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
1624 
1625  ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
1626  ip6srv->sr.segments_left = 1;
1627  ip6srv->sr.last_entry = 0;
1628  ip6srv->sr.length =
1629  ((sizeof (ip6_sr_header_t) +
1630  sizeof (ip6_address_t)) / 8) - 1;
1631  ip6srv->sr.flags = 0;
1632 
1633  ip6srv->sr.tag =
1634  clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1635 
1636  ip6srv->sr.segments[0] = seg0;
1637 
1638  if (vec_len (sl->segments))
1639  {
1640  ip6srv->sr.segments[1] = sl->segments[0];
1641  ip6srv->sr.last_entry++;
1642  ip6srv->sr.length += sizeof (ip6_address_t) / 8;
1643  }
1644  }
1645 
1646  if (PREDICT_TRUE (encap != NULL))
1647  {
1648  if (ls_param->nhtype == SRV6_NHTYPE_NONE)
1649  {
1650  if ((clib_net_to_host_u32
1652  >> 28) == 6)
1653  ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
1654  else
1655  ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
1656  }
1657  else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
1658  {
1659  ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
1660  if ((clib_net_to_host_u32
1662  >> 28) != 4)
1663  {
1664  // Bad encap packet.
1666  bad_n++;
1667  goto DONE;
1668  }
1669  }
1670  else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
1671  {
1672  ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
1673  if ((clib_net_to_host_u32
1675  >> 28) != 6)
1676  {
1677  // Bad encap packet.
1679  bad_n++;
1680  goto DONE;
1681  }
1682  }
1683  else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
1684  {
1685  ip6srv->sr.protocol = IP_PROTOCOL_NONE;
1686  }
1687  }
1688  else
1689  {
1690  ip6srv->sr.protocol = IP_PROTOCOL_NONE;
1691  }
1692  }
1693  else
1694  {
1695  clib_memcpy_fast (ip6srv, &sm->cache_hdr,
1696  sizeof (ip6_header_t));
1697 
1698  ip6srv->ip.src_address = src0;
1699  ip6srv->ip.dst_address = seg0;
1700 
1701  if (PREDICT_FALSE (gtpu_type) != GTPU_TYPE_GTPU)
1702  {
1703  ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
1704 
1705  ip6srv->sr.protocol = IP_PROTOCOL_NONE;
1706 
1707  ip6srv->sr.tag =
1708  clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1709 
1710  ip6srv->sr.segments_left = 0;
1711  ip6srv->sr.last_entry = 0;
1712 
1713  ip6srv->sr.length = sizeof (ip6_address_t) / 8;
1714  ip6srv->sr.segments[0] = seg0;
1715  }
1716  else
1717  {
1718  if (ls_param->nhtype == SRV6_NHTYPE_NONE)
1719  {
1720  if ((clib_net_to_host_u32
1722  >> 28) != 6)
1723  ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
1724  }
1725  else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
1726  {
1727  ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
1728  if ((clib_net_to_host_u32
1730  >> 28) != 4)
1731  {
1732  // Bad encap packet.
1734  bad_n++;
1735  goto DONE;
1736  }
1737  }
1738  else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
1739  {
1740  ip6srv->ip.protocol = IP_PROTOCOL_IPV6;
1741  if ((clib_net_to_host_u32
1743  >> 28) != 6)
1744  {
1745  // Bad encap packet.
1747  bad_n++;
1748  goto DONE;
1749  }
1750  }
1751  else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
1752  {
1753  ip6srv->ip.protocol = IP_PROTOCOL_NONE;
1754  }
1755  }
1756  }
1757 
1758  ip6srv->ip.payload_length =
1759  clib_host_to_net_u16 (len0 + hdr_len - sizeof (ip6_header_t));
1760 
1761  good_n++;
1762 
1763  if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
1764  PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1765  {
1767  vlib_add_trace (vm, node, b0, sizeof (*tr));
1768  clib_memcpy (tr->src.as_u8, ip6srv->ip.src_address.as_u8,
1769  sizeof (ip6_address_t));
1770  clib_memcpy (tr->dst.as_u8, ip6srv->ip.dst_address.as_u8,
1771  sizeof (ip6_address_t));
1772  tr->teid = teid;
1773  clib_memcpy (tr->sr_prefix.as_u8, ls_param->sr_prefix.as_u8,
1774  sizeof (ip6_address_t));
1775  tr->sr_prefixlen = ls_param->sr_prefixlen;
1776  }
1777  }
1778 
1779  DONE:
1781  (((next0 ==
1783  &(sm2->sr_ls_valid_counters)), thread_index,
1784  ls0 - sm2->localsids, 1, vlib_buffer_length_in_chain (vm, b0));
1785 
1786  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1787  n_left_to_next, bi0, next0);
1788  }
1789 
1790  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1791  }
1792 
1794  SRV6_END_ERROR_M_GTP6_D_BAD_PACKETS, bad_n);
1795 
1797  SRV6_END_ERROR_M_GTP6_D_PACKETS, good_n);
1798 
1799  return frame->n_vectors;
1800 }
1801 
1802 // Function for SRv6 GTP6.D.DI function
1805  vlib_frame_t * frame)
1806 {
1808  ip6_sr_main_t *sm2 = &sr_main;
1809  u32 n_left_from, next_index, *from, *to_next;
1810  u32 thread_index = vm->thread_index;
1811  srv6_end_gtp6_param_t *ls_param;
1812 
1813  u32 good_n = 0, bad_n = 0;
1814 
1815  from = vlib_frame_vector_args (frame);
1816  n_left_from = frame->n_vectors;
1817  next_index = node->cached_next_index;
1818 
1819  while (n_left_from > 0)
1820  {
1821  u32 n_left_to_next;
1822 
1823  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1824 
1825  while (n_left_from > 0 && n_left_to_next > 0)
1826  {
1827  u32 bi0;
1828  vlib_buffer_t *b0;
1829  ip6_sr_localsid_t *ls0;
1830 
1831  ip6_gtpu_header_t *hdr0 = NULL;
1832  uword len0;
1833 
1834  ip6_address_t dst0;
1835  ip6_address_t src0;
1836  ip6_address_t seg0;
1837  u32 teid = 0;
1838  u8 *teidp;
1839  u8 gtpu_type = 0;
1840  u8 qfi = 0;
1841  u8 *qfip = NULL;
1842  u16 seq = 0;
1843  u8 *seqp = NULL;
1844  u32 offset, shift;
1845  u32 hdrlen;
1846  ip6_header_t *encap = NULL;
1847  gtpu_pdu_session_t *sess;
1848 
1850 
1851  // defaults
1852  bi0 = from[0];
1853  to_next[0] = bi0;
1854  from += 1;
1855  to_next += 1;
1856  n_left_from -= 1;
1857  n_left_to_next -= 1;
1858 
1859  b0 = vlib_get_buffer (vm, bi0);
1860  ls0 =
1862  vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1863 
1864  ls_param = (srv6_end_gtp6_param_t *) ls0->plugin_mem;
1865 
1866  hdr0 = vlib_buffer_get_current (b0);
1867 
1868  hdrlen = sizeof (ip6_gtpu_header_t);
1869 
1870  len0 = vlib_buffer_length_in_chain (vm, b0);
1871 
1872  if ((hdr0->ip6.protocol != IP_PROTOCOL_UDP)
1873  || (hdr0->udp.dst_port !=
1874  clib_host_to_net_u16 (SRV6_GTP_UDP_DST_PORT))
1875  || (len0 < sizeof (ip6_gtpu_header_t)))
1876  {
1878 
1879  bad_n++;
1880  }
1881  else
1882  {
1883  dst0 = hdr0->ip6.dst_address;
1884  src0 = hdr0->ip6.src_address;
1885 
1886  gtpu_type = hdr0->gtpu.type;
1887 
1888  seg0 = ls_param->sr_prefix;
1889  teid = hdr0->gtpu.teid;
1890  teidp = (u8 *) & teid;
1891 
1892  if (hdr0->gtpu.ver_flags & (GTPU_EXTHDR_FLAG | GTPU_SEQ_FLAG))
1893  {
1894  // Extention header.
1895  hdrlen += sizeof (gtpu_exthdr_t);
1896 
1897  seq = hdr0->gtpu.ext->seq;
1898  seqp = (u8 *) & seq;
1899 
1901  {
1902  // PDU Session Container.
1903  sess =
1904  (gtpu_pdu_session_t *) (((char *) hdr0) + hdrlen);
1905  qfi = sess->u.val & ~GTPU_PDU_SESSION_P_BIT_MASK;
1906  qfip = &qfi;
1907 
1908  hdrlen += sizeof (gtpu_pdu_session_t);
1909 
1910  if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
1911  {
1912  hdrlen += sizeof (gtpu_paging_policy_t);
1913  }
1914  }
1915  }
1916 
1917  offset = ls_param->sr_prefixlen / 8;
1918  shift = ls_param->sr_prefixlen % 8;
1919 
1920  offset += 1;
1921  if (PREDICT_TRUE (shift == 0))
1922  {
1923  if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1924  || gtpu_type == GTPU_TYPE_ECHO_REPLY
1925  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1926  {
1927  if (seqp)
1928  clib_memcpy_fast (&seg0.as_u8[offset], seqp, 2);
1929  }
1930  else
1931  {
1932  clib_memcpy_fast (&seg0.as_u8[offset], teidp, 4);
1933  }
1934 
1935  if (qfip)
1936  {
1937  qfi =
1938  ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
1939  ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
1940 
1941  if (sess->type)
1942  {
1944  }
1945 
1946  seg0.as_u8[offset + 4] = qfi;
1947  }
1948  }
1949  else
1950  {
1951  int idx;
1952 
1953  if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1954  || gtpu_type == GTPU_TYPE_ECHO_REPLY
1955  || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1956  {
1957  if (seqp)
1958  {
1959  for (idx = 0; idx < 2; idx++)
1960  {
1961  seg0.as_u8[offset + idx] |= seqp[idx] >> shift;
1962  seg0.as_u8[offset + idx + 1] |=
1963  seqp[idx] << (8 - shift);
1964  }
1965  }
1966  }
1967  else
1968  {
1969  for (idx = 0; idx < 4; idx++)
1970  {
1971  seg0.as_u8[offset + idx] |= teidp[idx] >> shift;
1972  seg0.as_u8[offset + idx + 1] |=
1973  teidp[idx] << (8 - shift);
1974  }
1975  }
1976 
1977  if (qfip)
1978  {
1979  qfi =
1980  ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
1981  ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
1982 
1983  if (sess->type)
1984  {
1986  }
1987 
1988  seg0.as_u8[offset + 4] |= qfi >> shift;
1989  seg0.as_u8[offset + 5] |= qfi << (8 - shift);
1990  }
1991  }
1992 
1993  // jump over variable length data
1994  vlib_buffer_advance (b0, (word) hdrlen);
1995 
1996  // get length of encapsulated IPv6 packet (the remaining part)
1997  len0 = vlib_buffer_length_in_chain (vm, b0);
1998 
1999  if (PREDICT_TRUE (gtpu_type == GTPU_TYPE_GTPU))
2000  {
2001  encap = vlib_buffer_get_current (b0);
2002  }
2003 
2004  uword *p;
2005  ip6srv_combo_header_t *ip6srv;
2006  ip6_sr_policy_t *sr_policy = NULL;
2007  ip6_sr_sl_t *sl = NULL;
2008  u32 *sl_index;
2009  u32 hdr_len;
2010 
2011  p =
2013  &ls_param->sr_prefix);
2014  if (p)
2015  {
2016  sr_policy = pool_elt_at_index (sm2->sr_policies, p[0]);
2017  }
2018 
2019  if (sr_policy)
2020  {
2021  vec_foreach (sl_index, sr_policy->segments_lists)
2022  {
2023  sl = pool_elt_at_index (sm2->sid_lists, *sl_index);
2024  if (sl != NULL)
2025  break;
2026  }
2027  }
2028 
2029  hdr_len = sizeof (ip6srv_combo_header_t);
2030 
2031  if (sl)
2032  hdr_len += vec_len (sl->segments) * sizeof (ip6_address_t);
2033 
2034  hdr_len += sizeof (ip6_address_t) * 2;
2035 
2036  // jump back to data[0] or pre_data if required
2037  vlib_buffer_advance (b0, -(word) hdr_len);
2038 
2039  ip6srv = vlib_buffer_get_current (b0);
2040 
2041  if (sl)
2042  {
2043  clib_memcpy_fast (ip6srv, sl->rewrite,
2044  vec_len (sl->rewrite));
2045 
2046  if (vec_len (sl->segments) > 1)
2047  {
2048  ip6srv->ip.src_address = src0;
2049 
2050  ip6srv->sr.tag =
2051  clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
2052 
2053  ip6srv->sr.segments_left += 2;
2054  ip6srv->sr.last_entry += 2;
2055 
2056  ip6srv->sr.length += ((sizeof (ip6_address_t) * 2) / 8);
2057 
2058  ip6srv->sr.segments[0] = dst0;
2059  ip6srv->sr.segments[1] = seg0;
2060 
2061  clib_memcpy_fast (&ip6srv->sr.segments[2],
2062  (u8 *) (sl->rewrite +
2063  sizeof (ip6_header_t) +
2064  sizeof (ip6_sr_header_t)),
2065  vec_len (sl->segments) *
2066  sizeof (ip6_address_t));
2067  }
2068  else
2069  {
2070  ip6srv->ip.src_address = src0;
2071  ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
2072 
2073  ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
2074  ip6srv->sr.segments_left = 2;
2075  ip6srv->sr.last_entry = 1;
2076  ip6srv->sr.length =
2077  ((sizeof (ip6_sr_header_t) +
2078  2 * sizeof (ip6_address_t)) / 8) - 1;
2079  ip6srv->sr.flags = 0;
2080 
2081  ip6srv->sr.tag =
2082  clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
2083 
2084  ip6srv->sr.segments[0] = dst0;
2085  ip6srv->sr.segments[1] = seg0;
2086 
2087  if (vec_len (sl->segments))
2088  {
2089  ip6srv->sr.segments[2] = sl->segments[0];
2090  ip6srv->sr.last_entry++;
2091  ip6srv->sr.length += sizeof (ip6_address_t) / 8;
2092  }
2093  }
2094  }
2095  else
2096  {
2097  clib_memcpy_fast (ip6srv, &sm->cache_hdr,
2098  sizeof (ip6_header_t));
2099 
2100  ip6srv->ip.src_address = src0;
2101  ip6srv->ip.dst_address = seg0;
2102 
2103  ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
2104  ip6srv->sr.segments_left = 1;
2105  ip6srv->sr.last_entry = 0;
2106  ip6srv->sr.length =
2107  ((sizeof (ip6_sr_header_t) +
2108  sizeof (ip6_address_t)) / 8) - 1;
2109  ip6srv->sr.flags = 0;
2110 
2111  ip6srv->sr.tag =
2112  clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
2113 
2114  ip6srv->sr.segments[0] = dst0;
2115  }
2116 
2117  ip6srv->ip.payload_length =
2118  clib_host_to_net_u16 (len0 + hdr_len - sizeof (ip6_header_t));
2119  ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
2120 
2121  if (PREDICT_TRUE (encap != NULL))
2122  {
2123  if (ls_param->nhtype == SRV6_NHTYPE_NONE)
2124  {
2125  if ((clib_net_to_host_u32
2127  28) == 6)
2128  ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
2129  else
2130  ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
2131  }
2132  else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
2133  {
2134  ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
2135  if ((clib_net_to_host_u32
2137  28) != 4)
2138  {
2139  // Bad encap packet.
2141  bad_n++;
2142  goto DONE;
2143  }
2144  }
2145  else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
2146  {
2147  ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
2148  if ((clib_net_to_host_u32
2150  28) != 6)
2151  {
2152  // Bad encap packet.
2154  bad_n++;
2155  goto DONE;
2156  }
2157  }
2158  else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
2159  {
2160  ip6srv->sr.protocol = IP_PROTOCOL_NONE;
2161  }
2162  }
2163  else
2164  {
2165  ip6srv->sr.protocol = IP_PROTOCOL_NONE;
2166  }
2167 
2168  good_n++;
2169 
2170  if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
2171  PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2172  {
2174  vlib_add_trace (vm, node, b0, sizeof (*tr));
2175  clib_memcpy (tr->src.as_u8, ip6srv->ip.src_address.as_u8,
2176  sizeof (ip6_address_t));
2177  clib_memcpy (tr->dst.as_u8, ip6srv->ip.dst_address.as_u8,
2178  sizeof (ip6_address_t));
2179  tr->teid = teid;
2180  clib_memcpy (tr->sr_prefix.as_u8, ls_param->sr_prefix.as_u8,
2181  sizeof (ip6_address_t));
2182  tr->sr_prefixlen = ls_param->sr_prefixlen;
2183  }
2184  }
2185 
2186  DONE:
2188  (((next0 ==
2190  &(sm2->sr_ls_invalid_counters) : &(sm2->sr_ls_valid_counters)),
2191  thread_index, ls0 - sm2->localsids, 1,
2192  vlib_buffer_length_in_chain (vm, b0));
2193 
2194  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2195  n_left_to_next, bi0, next0);
2196  }
2197 
2198  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2199  }
2200 
2202  SRV6_END_ERROR_M_GTP6_D_DI_BAD_PACKETS, bad_n);
2203 
2205  SRV6_END_ERROR_M_GTP6_D_DI_PACKETS, good_n);
2206 
2207  return frame->n_vectors;
2208 }
2209 
2211 {
2212  .name = "srv6-end-m-gtp6-e",.vector_size = sizeof (u32),.format_trace =
2214  ARRAY_LEN (srv6_end_error_v6_e_strings),.error_strings =
2215  srv6_end_error_v6_e_strings,.n_next_nodes =
2216  SRV6_END_M_GTP6_E_N_NEXT,.next_nodes =
2217  {
2218  [SRV6_END_M_GTP6_E_NEXT_DROP] = "error-drop",
2219  [SRV6_END_M_GTP6_E_NEXT_LOOKUP] = "ip6-lookup",}
2220 ,};
2221 
2223 {
2224  .name = "srv6-end-m-gtp6-d",.vector_size = sizeof (u32),.format_trace =
2226  ARRAY_LEN (srv6_end_error_v6_d_strings),.error_strings =
2227  srv6_end_error_v6_d_strings,.n_next_nodes =
2228  SRV6_END_M_GTP6_D_N_NEXT,.next_nodes =
2229  {
2230  [SRV6_END_M_GTP6_D_NEXT_DROP] = "error-drop",
2231  [SRV6_END_M_GTP6_D_NEXT_LOOKUP] = "ip6-lookup",}
2232 ,};
2233 
2235 {
2236  .name = "srv6-end-m-gtp6-d-di",.vector_size = sizeof (u32),.format_trace =
2238  ARRAY_LEN (srv6_end_error_v6_d_di_strings),.error_strings =
2239  srv6_end_error_v6_d_di_strings,.n_next_nodes =
2240  SRV6_END_M_GTP6_D_DI_N_NEXT,.next_nodes =
2241  {
2242  [SRV6_END_M_GTP6_D_DI_NEXT_DROP] = "error-drop",
2243  [SRV6_END_M_GTP6_D_DI_NEXT_LOOKUP] = "ip6-lookup",}
2244 ,};
2245 
2246 /*
2247 * fd.io coding-style-patch-verification: ON
2248 *
2249 * Local Variables:
2250 * eval: (c-set-style "gnu")
2251 * End:
2252 */
#define GTPU_PDU_SESSION_P_BIT_MASK
Definition: mobile.h:118
union gtpu_pdu_session_t::@110 u
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 foreach_srv6_end_v6_d_di_error
Definition: node.c:128
static char * srv6_end_error_v6_e_strings[]
Definition: node.c:184
srv6_end_m_gtp6_d_next_t
Definition: node.c:223
#define GTPU_EXTHDR_PDU_SESSION
Definition: mobile.h:55
#define SRH_TAG_ERROR_INDICATION
Definition: mobile.h:59
#define CLIB_UNUSED(x)
Definition: clib.h:82
#define SRH_TAG_ECHO_REQUEST
Definition: mobile.h:58
ip6_address_t src
Definition: node.c:25
srv6_t_error_v4_d_t
Definition: node.c:140
#define foreach_srv6_end_v6_e_error
Definition: node.c:120
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:118
static u16 srh_tagfield[256]
Definition: node.c:31
ip6_header_t cache_hdr
Definition: mobile.h:221
u32 teid
Definition: mobile.h:77
srv6_end_error_v6_d_t
Definition: node.c:156
#define GTPU_TYPE_GTPU
Definition: mobile.h:86
#define PREDICT_TRUE(x)
Definition: clib.h:112
u8 as_u8[16]
Definition: ip6_packet.h:48
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
#define NULL
Definition: clib.h:58
static u8 gtpu_type_get(u16 tag)
Definition: node.c:250
vlib_node_registration_t srv6_end_m_gtp6_e
(constructor) VLIB_REGISTER_NODE (srv6_end_m_gtp6_e)
Definition: node.c:2210
u32 thread_index
Definition: main.h:218
#define foreach_srv6_end_v6_d_error
Definition: node.c:124
#define GTPU_EXTHDR_FLAG
Definition: mobile.h:53
ip6_address_t * segments
SIDs (key)
Definition: sr.h:70
ip6_address_t sr_prefix
Definition: node.c:26
vl_api_address_t src
Definition: gre.api:60
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
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 length
Definition: mobile.h:76
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:366
vlib_combined_counter_main_t sr_ls_invalid_counters
Definition: sr.h:283
vlib_combined_counter_main_t sr_ls_valid_counters
Definition: sr.h:282
ip6_address_t src_address
Definition: ip6_packet.h:307
unsigned char u8
Definition: types.h:56
srv6_end_main_v6_t srv6_end_main_v6
Definition: gtp6_e.c:24
#define IP_PROTOCOL_NONE
Definition: mobile.h:37
#define clib_memcpy(d, s, n)
Definition: string.h:180
vlib_node_registration_t srv6_end_m_gtp6_d
(constructor) VLIB_REGISTER_NODE (srv6_end_m_gtp6_d)
Definition: node.c:2222
#define GTPU_TYPE_END_MARKER
Definition: mobile.h:85
format_function_t format_ip4_address
Definition: format.h:73
i64 word
Definition: types.h:111
ip4_address_t dst_address
Definition: ip4_packet.h:170
#define SRH_TAG_END_MARKER
Definition: mobile.h:60
SR Segment List (SID list)
Definition: sr.h:68
ip6_header_t ip6
Definition: mobile.h:138
#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
static char * srv6_end_error_v6_d_di_strings[]
Definition: node.c:196
u16 localsid_len
Definition: sr.h:122
u8 npdu_num
Definition: mobile.h:66
vl_api_fib_path_type_t type
Definition: fib_types.api:123
gtpu_header_t gtpu
Definition: mobile.h:131
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:519
#define SRV6_PDU_SESSION_U_BIT_MASK
Definition: mobile.h:122
static char * srv6_end_error_v4_strings[]
Definition: node.c:172
#define GTPU_PDU_SESSION_QFI_MASK
Definition: mobile.h:120
#define SRV6_NHTYPE_IPV4
Definition: mobile.h:32
ip6_sr_header_t sr
Definition: sr.h:61
#define SRV6_NHTYPE_IPV6
Definition: mobile.h:33
unsigned short u16
Definition: types.h:57
ip6_header_t ip
Definition: sr.h:60
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:82
#define PREDICT_FALSE(x)
Definition: clib.h:111
#define GTPU_TYPE_ECHO_REPLY
Definition: mobile.h:83
static u8 * format_srv6_end_rewrite_trace(u8 *s, va_list *args)
Definition: node.c:87
#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:218
vl_api_address_t dst
Definition: gre.api:61
#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:123
srv6_end_error_v4_t
Definition: node.c:132
vlib_main_t * vm
Definition: in2out_ed.c:1810
#define foreach_srv6_end_v4_error
Definition: node.c:112
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1150
static u8 * format_srv6_end_rewrite_trace6(u8 *s, va_list *args)
Definition: node.c:99
ip6_sr_localsid_t * localsids
Definition: sr.h:252
#define SRH_TAG_ECHO_REPLY
Definition: mobile.h:57
vlib_node_registration_t srv6_end_m_gtp6_d_di
(constructor) VLIB_REGISTER_NODE (srv6_end_m_gtp6_d_di)
Definition: node.c:2234
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u32 end_m_gtp4_e_node_index
Definition: mobile.h:174
ip6_address_t v6src_prefix
Definition: mobile.h:163
format_function_t format_ip6_address
Definition: format.h:91
#define GTPU_TYPE_ECHO_REQUEST
Definition: mobile.h:82
srv6_end_main_v6_decap_di_t srv6_end_main_v6_decap_di
Definition: gtp6_d_di.c:24
#define foreach_srv6_t_v4_d_error
Definition: node.c:116
vlib_node_registration_t srv6_t_m_gtp4_d
(constructor) VLIB_REGISTER_NODE (srv6_t_m_gtp4_d)
Definition: node.c:1063
srv6_end_m_gtp6_e_next_t
Definition: node.c:216
u32 * segments_lists
SID lists indexes (vector)
Definition: sr.h:93
vlib_node_registration_t srv6_end_m_gtp4_e
(constructor) VLIB_REGISTER_NODE (srv6_end_m_gtp4_e)
Definition: node.c:1051
#define SRV6_NHTYPE_NONE
Definition: mobile.h:31
#define ARRAY_LEN(x)
Definition: clib.h:62
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:456
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:1810
static u16 hash_uword_to_u16(uword *key)
Definition: node.c:238
#define GTPU_PDU_SESSION_R_BIT_MASK
Definition: mobile.h:119
ip4_gtpu_header_t cache_hdr
Definition: mobile.h:180
ip6_gtpu_header_t cache_hdr
Definition: mobile.h:207
srv6_end_main_v4_t srv6_end_main_v4
Definition: gtp4_e.c:24
udp_header_t udp
Definition: mobile.h:139
u32 end_m_gtp6_e_node_index
Definition: mobile.h:204
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:142
#define GTPU_SEQ_FLAG
Definition: mobile.h:54
uword hash_memory(void *p, word n_bytes, uword state)
Definition: hash.c:275
u8 nextexthdr
Definition: mobile.h:67
srv6_end_m_gtp4_e_next_t
Definition: node.c:202
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:248
mhash_t sr_policies_index_hash
Definition: sr.h:249
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:130
typedef key
Definition: ipsec_types.api:83
ip4_header_t ip4
Definition: mobile.h:129
u32 ip_version_traffic_class_and_flow_label
Definition: ip6_packet.h:294
Definition: defs.h:47
u16 payload_length
Definition: ip6_packet.h:298
ip6_address_t sr_pr_encaps_src
vl_api_address_t ip
Definition: l2.api:490
#define SRV6_PDU_SESSION_QFI_MASK
Definition: mobile.h:124
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
ip6_sr_policy_t * sr_policies
Definition: sr.h:246
ip6_address_t segments[0]
Definition: sr_packet.h:149
SR Policy.
Definition: sr.h:91
static char * srv6_t_error_v4_d_strings[]
Definition: node.c:178
ip6_address_t sr_prefix
Definition: mobile.h:152
u8 * rewrite
Precomputed rewrite header.
Definition: sr.h:74
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
u16 port
Definition: lb_types.api:72
srv6_T_m_gtp4_d_next_t
Definition: node.c:209
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:72
srv6_end_m_gtp6_d_di_next_t
Definition: node.c:230
ip6_sr_sl_t * sid_lists
Definition: sr.h:243
struct clib_bihash_value offset
template key/value backing page structure
#define vnet_buffer(b)
Definition: buffer.h:408
ip6_address_t sr_prefix
Definition: mobile.h:160
Segment Routing main datastructure.
Definition: sr.h:237
#define vec_foreach(var, vec)
Vector iterator.
srv6_end_error_v6_e_t
Definition: node.c:148
u8 ver_flags
Definition: mobile.h:74
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1811
gtpu_header_t gtpu
Definition: mobile.h:140
u32 ip4
Definition: one.api:440
ip6_header_t cache_hdr
Definition: mobile.h:192
gtpu_exthdr_t ext[0]
Definition: mobile.h:78
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:302
#define GTPU_TYPE_ERROR_INDICATION
Definition: mobile.h:84
static char * srv6_end_error_v6_d_strings[]
Definition: node.c:190
ip6srv_combo_header_t cache_hdr
Definition: mobile.h:235
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
srv6_end_error_v6_d_di_t
Definition: node.c:164
ip6_address_t dst_address
Definition: ip6_packet.h:307