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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
21 extern ip6_address_t sr_pr_encaps_src;
25 ip6_address_t src, dst;
26 ip6_address_t sr_prefix;
29 } srv6_end_rewrite_trace_t;
31 static u16 srh_tagfield[256] = {
34 /* 1 : Echo Request */
39 0x0, 0x0, 0x0, 0x0, 0x0,
41 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
43 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
46 /* 26 : Error Indication */
49 0x0, 0x0, 0x0, 0x0, 0x0,
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,
79 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
87 format_srv6_end_rewrite_trace (u8 * s, va_list * args)
89 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
90 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
91 srv6_end_rewrite_trace_t *t = va_arg (*args, srv6_end_rewrite_trace_t *);
93 return format (s, "SRv6-END-rewrite: src %U dst %U\n\tTEID: 0x%x",
94 format_ip4_address, &t->src, format_ip4_address, &t->dst,
95 clib_net_to_host_u32 (t->teid));
99 format_srv6_end_rewrite_trace6 (u8 * s, va_list * args)
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 *);
106 s, "SRv6-END-rewrite: src %U dst %U\n\tTEID: 0x%x\n\tsr_prefix: %U/%d",
107 format_ip6_address, &t->src, format_ip6_address, &t->dst,
108 clib_net_to_host_u32 (t->teid), format_ip6_address, &t->sr_prefix,
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")
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")
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")
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")
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")
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")
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")
142 #define _(sym,str) SRV6_END_ERROR_##sym,
143 foreach_srv6_end_v4_error
146 } srv6_end_error_v4_t;
150 #define _(sym,str) SRV6_T_ERROR_##sym,
151 foreach_srv6_t_v4_d_error
154 } srv6_t_error_v4_d_t;
158 #define _(sym,str) SRV6_END_ERROR_##sym,
159 foreach_srv6_end_v6_e_error
161 SRV6_END_N_V6_E_ERROR,
162 } srv6_end_error_v6_e_t;
166 #define _(sym,str) SRV6_END_ERROR_##sym,
167 foreach_srv6_end_v6_d_error
169 SRV6_END_N_V6_D_ERROR,
170 } srv6_end_error_v6_d_t;
174 #define _(sym,str) SRV6_END_ERROR_##sym,
175 foreach_srv6_end_v6_d_di_error
177 SRV6_END_N_V6_D_DI_ERROR,
178 } srv6_end_error_v6_d_di_t;
182 #define _(sym,str) SRV6_END_ERROR_##sym,
183 foreach_srv6_end_v6_dt_error
185 SRV6_END_N_V6_DT_ERROR,
186 } srv6_end_error_v6_dt_t;
190 #define _(sym,str) SRV6_T_ERROR_##sym,
191 foreach_srv6_t_v4_dt_error
193 SRV6_T_N_V4_DT_ERROR,
194 } srv6_t_error_v4_dt_t;
196 static char *srv6_end_error_v4_strings[] = {
197 #define _(sym,string) string,
198 foreach_srv6_end_v4_error
202 static char *srv6_t_error_v4_d_strings[] = {
203 #define _(sym,string) string,
204 foreach_srv6_t_v4_d_error
208 static char *srv6_end_error_v6_e_strings[] = {
209 #define _(sym,string) string,
210 foreach_srv6_end_v6_e_error
214 static char *srv6_end_error_v6_d_strings[] = {
215 #define _(sym,string) string,
216 foreach_srv6_end_v6_d_error
220 static char *srv6_end_error_v6_d_di_strings[] = {
221 #define _(sym,string) string,
222 foreach_srv6_end_v6_d_di_error
226 static char *srv6_end_error_v6_dt_strings[] = {
227 #define _(sym,string) string,
228 foreach_srv6_end_v6_dt_error
232 static char *srv6_t_error_v4_dt_strings[] = {
233 #define _(sym,string) string,
234 foreach_srv6_t_v4_dt_error
240 SRV6_END_M_GTP4_E_NEXT_DROP,
241 SRV6_END_M_GTP4_E_NEXT_LOOKUP,
242 SRV6_END_M_GTP4_E_N_NEXT,
243 } srv6_end_m_gtp4_e_next_t;
247 SRV6_T_M_GTP4_D_NEXT_DROP,
248 SRV6_T_M_GTP4_D_NEXT_LOOKUP4,
249 SRV6_T_M_GTP4_D_NEXT_LOOKUP6,
250 SRV6_T_M_GTP4_D_N_NEXT,
251 } srv6_T_m_gtp4_d_next_t;
255 SRV6_END_M_GTP6_E_NEXT_DROP,
256 SRV6_END_M_GTP6_E_NEXT_LOOKUP,
257 SRV6_END_M_GTP6_E_N_NEXT,
258 } srv6_end_m_gtp6_e_next_t;
262 SRV6_END_M_GTP6_D_NEXT_DROP,
263 SRV6_END_M_GTP6_D_NEXT_LOOKUP4,
264 SRV6_END_M_GTP6_D_NEXT_LOOKUP6,
265 SRV6_END_M_GTP6_D_N_NEXT,
266 } srv6_end_m_gtp6_d_next_t;
270 SRV6_END_M_GTP6_D_DI_NEXT_DROP,
271 SRV6_END_M_GTP6_D_DI_NEXT_LOOKUP,
272 SRV6_END_M_GTP6_D_DI_N_NEXT,
273 } srv6_end_m_gtp6_d_di_next_t;
277 SRV6_END_M_GTP6_DT_NEXT_DROP,
278 SRV6_END_M_GTP6_DT_NEXT_LOOKUP4,
279 SRV6_END_M_GTP6_DT_NEXT_LOOKUP6,
280 SRV6_END_M_GTP6_DT_N_NEXT,
281 } srv6_end_m_gtp6_dt_next_t;
285 SRV6_T_M_GTP4_DT_NEXT_DROP,
286 SRV6_T_M_GTP4_DT_NEXT_LOOKUP4,
287 SRV6_T_M_GTP4_DT_NEXT_LOOKUP6,
288 SRV6_T_M_GTP4_DT_N_NEXT,
289 } srv6_t_m_gtp4_dt_next_t;
292 hash_uword_to_u16 (uword * key)
297 return val[0] ^ val[1] ^ val[2] ^ val[3];
299 return val[0] ^ val[1];
304 gtpu_type_get (u16 tag)
308 val = clib_net_to_host_u16 (tag);
309 if (val & SRH_TAG_ECHO_REPLY)
310 return GTPU_TYPE_ECHO_REPLY;
311 else if (val & SRH_TAG_ECHO_REQUEST)
312 return GTPU_TYPE_ECHO_REQUEST;
313 else if (val & SRH_TAG_ERROR_INDICATION)
314 return GTPU_TYPE_ERROR_INDICATION;
315 else if (val & SRH_TAG_END_MARKER)
316 return GTPU_TYPE_END_MARKER;
318 return GTPU_TYPE_GTPU;
321 // Function for SRv6 GTP4.E function.
322 VLIB_NODE_FN (srv6_end_m_gtp4_e)
323 (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
325 srv6_end_main_v4_t *sm = &srv6_end_main_v4;
326 ip6_sr_main_t *sm2 = &sr_main;
327 u32 n_left_from, next_index, *from, *to_next;
328 u32 thread_index = vm->thread_index;
330 u32 good_n = 0, bad_n = 0;
332 from = vlib_frame_vector_args (frame);
333 n_left_from = frame->n_vectors;
334 next_index = node->cached_next_index;
336 while (n_left_from > 0)
340 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
342 while (n_left_from > 0 && n_left_to_next > 0)
346 ip6_sr_localsid_t *ls0;
347 srv6_end_gtp4_e_param_t *ls_param;
349 ip6srv_combo_header_t *ip6srv0;
350 ip6_address_t src0, dst0;
352 ip4_gtpu_header_t *hdr0 = NULL;
355 u32 next0 = SRV6_END_M_GTP4_E_NEXT_LOOKUP;
365 b0 = vlib_get_buffer (vm, bi0);
366 ls0 = pool_elt_at_index (sm2->localsids,
367 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
369 ls_param = (srv6_end_gtp4_e_param_t *) ls0->plugin_mem;
371 ip6srv0 = vlib_buffer_get_current (b0);
372 src0 = ip6srv0->ip.src_address;
373 dst0 = ip6srv0->ip.dst_address;
375 len0 = vlib_buffer_length_in_chain (vm, b0);
377 if ((ip6srv0->ip.protocol == IPPROTO_IPV6_ROUTE &&
379 sizeof (ip6srv_combo_header_t) + ip6srv0->sr.length * 8) ||
380 (len0 < sizeof (ip6_header_t)))
382 next0 = SRV6_END_M_GTP4_E_NEXT_DROP;
391 u8 *teid8p = (u8 *) &teid;
401 u8 ie_buf[GTPU_IE_MAX_SIZ];
405 if (ip6srv0->ip.protocol == IPPROTO_IPV6_ROUTE)
407 tag = ip6srv0->sr.tag;
410 offset = ls0->localsid_prefix_len / 8;
411 shift = ls0->localsid_prefix_len % 8;
413 gtpu_type = gtpu_type_get (tag);
415 if (PREDICT_TRUE (shift == 0))
417 clib_memcpy_fast (&dst4.as_u8[0], &dst0.as_u8[offset], 4);
419 qfi = dst0.as_u8[offset + 4];
421 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
422 gtpu_type == GTPU_TYPE_ECHO_REPLY ||
423 gtpu_type == GTPU_TYPE_ERROR_INDICATION)
425 clib_memcpy_fast (&seq, &dst0.as_u8[offset + 5], 2);
429 clib_memcpy_fast (teid8p, &dst0.as_u8[offset + 5], 4);
436 for (index = 0; index < 4; index++)
438 dst4.as_u8[index] = dst0.as_u8[offset + index] << shift;
440 dst0.as_u8[offset + index + 1] >> (8 - shift);
443 qfi |= dst0.as_u8[offset + 4] << shift;
444 qfi |= dst0.as_u8[offset + 5] >> (8 - shift);
446 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
447 gtpu_type == GTPU_TYPE_ECHO_REPLY ||
448 gtpu_type == GTPU_TYPE_ERROR_INDICATION)
451 for (index = 0; index < 2; index++)
453 sp[index] = dst0.as_u8[offset + 5 + index] << shift;
455 dst0.as_u8[offset + 6 + index] >> (8 - shift);
460 for (index = 0; index < 4; index++)
462 *teid8p = dst0.as_u8[offset + 5 + index] << shift;
464 dst0.as_u8[offset + 6 + index] >> (8 - shift);
473 sizeof (gtpu_exthdr_t) + sizeof (gtpu_pdu_session_t);
475 else if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
476 gtpu_type == GTPU_TYPE_ECHO_REPLY ||
477 gtpu_type == GTPU_TYPE_ERROR_INDICATION)
479 hdrlen = sizeof (gtpu_exthdr_t);
482 if (PREDICT_FALSE (gtpu_type == GTPU_TYPE_ECHO_REPLY))
484 hdrlen += sizeof (gtpu_recovery_ie);
487 if (PREDICT_FALSE (gtpu_type == GTPU_TYPE_ERROR_INDICATION))
492 ext_len = ip6srv0->sr.length * 8;
495 sizeof (ip6_address_t) * (ip6srv0->sr.last_entry + 1))
497 tlv = (ip6_sr_tlv_t *) ((u8 *) &ip6srv0->sr +
498 sizeof (ip6_sr_header_t) +
499 sizeof (ip6_address_t) *
500 (ip6srv0->sr.last_entry + 1));
502 if (tlv->type == SRH_TLV_USER_PLANE_CONTAINER)
504 user_plane_sub_tlv_t *sub_tlv;
506 sub_tlv = (user_plane_sub_tlv_t *) tlv->value;
508 ie_size = sub_tlv->length;
509 clib_memcpy_fast (ie_buf, sub_tlv->value, ie_size);
516 if (ip6srv0->ip.protocol == IPPROTO_IPV6_ROUTE)
518 vlib_buffer_advance (b0,
519 (word) sizeof (ip6srv_combo_header_t) +
520 ip6srv0->sr.length * 8);
524 vlib_buffer_advance (b0, (word) sizeof (ip6_header_t));
527 // get length of encapsulated IPv6 packet (the remaining part)
528 p = vlib_buffer_get_current (b0);
530 plen = len0 = vlib_buffer_length_in_chain (vm, b0);
534 hdrlen += sizeof (ip4_gtpu_header_t);
536 // IPv4 GTP-U header creation.
537 vlib_buffer_advance (b0, -(word) hdrlen);
539 hdr0 = vlib_buffer_get_current (b0);
541 clib_memcpy_fast (hdr0, &sm->cache_hdr,
542 sizeof (ip4_gtpu_header_t));
544 hdr0->ip4.dst_address.as_u32 = dst4.as_u32;
546 hdr0->gtpu.teid = teid;
547 hdr0->gtpu.length = clib_host_to_net_u16 (len0);
549 hdr0->gtpu.type = gtpu_type;
551 if (gtpu_type == GTPU_TYPE_ECHO_REPLY ||
552 gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
553 gtpu_type == GTPU_TYPE_ERROR_INDICATION)
555 hdr0->gtpu.ver_flags |= GTPU_SEQ_FLAG;
556 hdr0->gtpu.ext->seq = seq;
557 hdr0->gtpu.ext->npdu_num = 0;
558 hdr0->gtpu.ext->nextexthdr = 0;
560 if (gtpu_type == GTPU_TYPE_ECHO_REPLY)
562 gtpu_recovery_ie *recovery;
565 (gtpu_recovery_ie *) ((u8 *) hdr0 +
567 sizeof (gtpu_recovery_ie)));
568 recovery->type = GTPU_RECOVERY_IE_TYPE;
569 recovery->restart_counter = 0;
571 else if (gtpu_type == GTPU_TYPE_ERROR_INDICATION)
577 ie_ptr = (u8 *) ((u8 *) hdr0 + (hdrlen - ie_size));
578 clib_memcpy_fast (ie_ptr, ie_buf, ie_size);
586 hdr0->gtpu.ext->seq = 0;
587 hdr0->gtpu.ext->npdu_num = 0;
594 gtpu_pdu_session_t *sess;
596 hdr0->gtpu.ver_flags |= GTPU_EXTHDR_FLAG;
598 hdr0->gtpu.ext->nextexthdr = GTPU_EXTHDR_PDU_SESSION;
600 type = qfi & SRV6_PDU_SESSION_U_BIT_MASK;
602 qfi = ((qfi & SRV6_PDU_SESSION_QFI_MASK) >> 2) |
603 ((qfi & SRV6_PDU_SESSION_R_BIT_MASK) << 5);
605 sess = (gtpu_pdu_session_t *) (((char *) hdr0) +
606 sizeof (ip4_gtpu_header_t) +
607 sizeof (gtpu_exthdr_t));
612 sess->nextexthdr = 0;
615 vnet_buffer (b0)->sw_if_index[VLIB_TX] = ls_param->fib4_index;
617 if (ls_param->v4src_position)
619 offset = ls_param->v4src_position / 8;
620 shift = ls_param->v4src_position % 8;
622 if (PREDICT_TRUE (shift == 0))
624 for (index = 0; index < 4; index++)
626 hdr0->ip4.src_address.as_u8[index] =
627 src0.as_u8[offset + index];
632 for (index = 0; index < 4; index++)
634 hdr0->ip4.src_address.as_u8[index] =
635 src0.as_u8[offset + index] << shift;
636 hdr0->ip4.src_address.as_u8[index] |=
637 src0.as_u8[offset + index + 1] >> (8 - shift);
643 clib_memcpy_fast (&hdr0->ip4.src_address,
644 &ls_param->v4src_addr, 4);
647 key = hash_memory (p, plen < 40 ? plen : 40, 0);
648 port = hash_uword_to_u16 (&key);
649 hdr0->udp.src_port = port;
651 hdr0->udp.length = clib_host_to_net_u16 (
652 len0 + sizeof (udp_header_t) + sizeof (gtpu_header_t));
655 clib_host_to_net_u16 (len0 + sizeof (ip4_gtpu_header_t));
657 hdr0->ip4.checksum = ip4_header_checksum (&hdr0->ip4);
661 if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
662 PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
664 srv6_end_rewrite_trace_t *tr =
665 vlib_add_trace (vm, node, b0, sizeof (*tr));
666 clib_memcpy (tr->src.as_u8, hdr0->ip4.src_address.as_u8,
667 sizeof (hdr0->ip4.src_address.as_u8));
668 clib_memcpy (tr->dst.as_u8, hdr0->ip4.dst_address.as_u8,
669 sizeof (hdr0->ip4.dst_address.as_u8));
670 tr->teid = hdr0->gtpu.teid;
674 vlib_increment_combined_counter (
675 ((next0 == SRV6_END_M_GTP4_E_NEXT_DROP) ?
676 &(sm2->sr_ls_invalid_counters) :
677 &(sm2->sr_ls_valid_counters)),
678 thread_index, ls0 - sm2->localsids, 1,
679 vlib_buffer_length_in_chain (vm, b0));
681 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
682 n_left_to_next, bi0, next0);
685 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
688 vlib_node_increment_counter (vm, sm->end_m_gtp4_e_node_index,
689 SRV6_END_ERROR_M_GTP4_E_BAD_PACKETS, bad_n);
691 vlib_node_increment_counter (vm, sm->end_m_gtp4_e_node_index,
692 SRV6_END_ERROR_M_GTP4_E_PACKETS, good_n);
694 return frame->n_vectors;
697 // Function for SRv6 GTP4.D function.
699 srv6_gtp4_decap_processing (vlib_main_t *vm, vlib_node_runtime_t *node,
702 srv6_t_main_v4_decap_t *sm = &srv6_t_main_v4_decap;
703 ip6_sr_main_t *sm2 = &sr_main;
706 srv6_end_gtp4_d_param_t *ls_param;
711 u32 next0 = SRV6_T_M_GTP4_D_NEXT_LOOKUP6;
713 sl0 = pool_elt_at_index (sm2->sid_lists,
714 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
716 ls_param = (srv6_end_gtp4_d_param_t *) sl0->plugin_mem;
718 len0 = vlib_buffer_length_in_chain (vm, b0);
720 ip4 = vlib_buffer_get_current (b0);
722 if (ip4->protocol != IP_PROTOCOL_UDP || len0 < sizeof (ip4_gtpu_header_t))
724 next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
729 ip6_sr_policy_t *sr_policy = NULL;
730 ip6_sr_sl_t *sl = NULL;
734 ip4_gtpu_header_t *hdr;
735 ip4_address_t src, dst;
737 ip6_header_t *encap = NULL;
747 u32 offset, shift, index;
748 ip6srv_combo_header_t *ip6srv;
749 gtpu_pdu_session_t *sess = NULL;
752 u8 ie_buf[GTPU_IE_MAX_SIZ];
755 hdr = (ip4_gtpu_header_t *) ip4;
757 hdr_len = sizeof (ip4_gtpu_header_t);
759 teid = hdr->gtpu.teid;
760 teidp = (u8 *) &teid;
764 gtpu_type = hdr->gtpu.type;
766 if (hdr->gtpu.ver_flags & (GTPU_EXTHDR_FLAG | GTPU_SEQ_FLAG))
769 hdr_len += sizeof (gtpu_exthdr_t);
771 seq = hdr->gtpu.ext->seq;
773 if (hdr->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
775 // PDU Session Container.
776 sess = (gtpu_pdu_session_t *) (((char *) hdr) + hdr_len);
777 qfi = sess->u.val & ~GTPU_PDU_SESSION_P_BIT_MASK;
780 hdr_len += sizeof (gtpu_pdu_session_t);
782 if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
784 hdr_len += sizeof (gtpu_paging_policy_t);
789 src = hdr->ip4.src_address;
792 dst = hdr->ip4.dst_address;
795 seg = ls_param->sr_prefix;
797 offset = ls_param->sr_prefixlen / 8;
798 shift = ls_param->sr_prefixlen % 8;
800 if (PREDICT_TRUE (shift == 0))
802 clib_memcpy_fast (&seg.as_u8[offset], dstp, 4);
806 qfi = ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
807 ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
811 qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
814 seg.as_u8[offset + 4] = qfi;
817 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
818 gtpu_type == GTPU_TYPE_ECHO_REPLY ||
819 gtpu_type == GTPU_TYPE_ERROR_INDICATION)
821 clib_memcpy_fast (&seg.as_u8[offset + 5], seqp, 2);
825 clib_memcpy_fast (&seg.as_u8[offset + 5], teidp, 4);
830 for (index = 0; index < 4; index++)
832 seg.as_u8[offset + index] |= dstp[index] >> shift;
833 seg.as_u8[offset + index + 1] |= dstp[index] << (8 - shift);
838 qfi = ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
839 ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
843 qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
846 seg.as_u8[offset + 4] |= qfi >> shift;
847 seg.as_u8[offset + 5] |= qfi << (8 - shift);
850 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
851 gtpu_type == GTPU_TYPE_ECHO_REPLY ||
852 gtpu_type == GTPU_TYPE_ERROR_INDICATION)
854 for (index = 0; index < 2; index++)
856 seg.as_u8[offset + 5 + index] |= seqp[index] >> shift;
857 seg.as_u8[offset + 6 + index] |= seqp[index] << (8 - shift);
862 for (index = 0; index < 4; index++)
864 seg.as_u8[offset + index + 5] |= teidp[index] >> shift;
865 seg.as_u8[offset + index + 6] |= teidp[index] << (8 - shift);
870 if (PREDICT_FALSE (gtpu_type == GTPU_TYPE_ERROR_INDICATION))
874 payload_len = clib_net_to_host_u16 (hdr->gtpu.length);
875 if (payload_len != 0)
877 ie_size = payload_len - (hdr_len - sizeof (ip4_gtpu_header_t));
882 ies = (u8 *) ((u8 *) hdr + hdr_len);
883 clib_memcpy_fast (ie_buf, ies, ie_size);
889 src6 = ls_param->v6src_prefix;
891 offset = ls_param->v6src_prefixlen / 8;
892 shift = ls_param->v6src_prefixlen % 8;
894 if (PREDICT_TRUE (shift == 0))
896 clib_memcpy_fast (&src6.as_u8[offset], srcp, 4);
900 for (index = 0; index < 4; index++)
902 src6.as_u8[offset + index] |= srcp[offset] >> shift;
903 src6.as_u8[offset + index + 1] |= srcp[offset] << (8 - shift);
907 vlib_buffer_advance (b0, (word) hdr_len);
910 if (PREDICT_TRUE (gtpu_type == GTPU_TYPE_GTPU))
912 encap = vlib_buffer_get_current (b0);
915 len0 = vlib_buffer_length_in_chain (vm, b0);
917 p = mhash_get (&sm2->sr_policies_index_hash, &ls_param->sr_prefix);
920 sr_policy = pool_elt_at_index (sm2->sr_policies, p[0]);
925 vec_foreach (sl_index, sr_policy->segments_lists)
927 sl = pool_elt_at_index (sm2->sid_lists, *sl_index);
935 hdr_len = sizeof (ip6srv_combo_header_t);
936 hdr_len += vec_len (sl->segments) * sizeof (ip6_address_t);
937 hdr_len += sizeof (ip6_address_t);
941 hdr_len = sizeof (ip6_header_t);
943 if (PREDICT_FALSE (gtpu_type != GTPU_TYPE_GTPU))
945 hdr_len += sizeof (ip6_sr_header_t);
946 hdr_len += sizeof (ip6_address_t);
953 sizeof (ip6_sr_tlv_t) + sizeof (user_plane_sub_tlv_t) + ie_size;
955 tlv_siz = (tlv_siz & ~0x07) + (tlv_siz & 0x07 ? 0x08 : 0x0);
959 vlib_buffer_advance (b0, -(word) hdr_len);
960 ip6srv = vlib_buffer_get_current (b0);
964 clib_memcpy_fast (ip6srv, sl->rewrite, vec_len (sl->rewrite));
966 if (vec_len (sl->segments) > 1)
968 ip6srv->sr.tag = clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
970 ip6srv->sr.segments_left += 1;
971 ip6srv->sr.last_entry += 1;
973 ip6srv->sr.length += sizeof (ip6_address_t) / 8;
974 ip6srv->sr.segments[0] = seg;
976 clib_memcpy_fast (&ip6srv->sr.segments[1],
977 (u8 *) (sl->rewrite + sizeof (ip6_header_t) +
978 sizeof (ip6_sr_header_t)),
979 vec_len (sl->segments) *
980 sizeof (ip6_address_t));
984 ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
986 ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
988 ip6srv->sr.segments_left = 1;
989 ip6srv->sr.last_entry = 0;
992 ((sizeof (ip6_sr_header_t) + sizeof (ip6_address_t)) / 8) - 1;
993 ip6srv->sr.flags = 0;
995 ip6srv->sr.tag = clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
997 ip6srv->sr.segments[0] = seg;
998 if (vec_len (sl->segments))
1000 ip6srv->sr.segments[1] = sl->segments[0];
1001 ip6srv->sr.length += sizeof (ip6_address_t) / 8;
1002 ip6srv->sr.last_entry++;
1006 if (PREDICT_TRUE (encap != NULL))
1008 if (ls_param->nhtype == SRV6_NHTYPE_NONE)
1010 if ((clib_net_to_host_u32 (
1011 encap->ip_version_traffic_class_and_flow_label) >>
1013 ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
1015 ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
1017 else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
1019 ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
1020 if ((clib_net_to_host_u32 (
1021 encap->ip_version_traffic_class_and_flow_label) >>
1024 // Bad encap packet.
1025 next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
1029 else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
1031 ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
1032 if ((clib_net_to_host_u32 (
1033 encap->ip_version_traffic_class_and_flow_label) >>
1036 // Bad encap packet.
1037 next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
1041 else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
1043 ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
1048 ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
1053 clib_memcpy_fast (ip6srv, &sm->cache_hdr, sizeof (ip6_header_t));
1055 ip6srv->ip.dst_address = seg;
1057 if (PREDICT_FALSE (gtpu_type != GTPU_TYPE_GTPU))
1059 ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
1061 ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
1063 ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
1065 ip6srv->sr.tag = clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1067 ip6srv->sr.segments_left = 0;
1068 ip6srv->sr.last_entry = 0;
1070 ip6srv->sr.length = sizeof (ip6_address_t) / 8;
1071 ip6srv->sr.segments[0] = seg;
1075 if (ls_param->nhtype == SRV6_NHTYPE_NONE)
1077 if ((clib_net_to_host_u32 (
1078 encap->ip_version_traffic_class_and_flow_label) >>
1080 ip6srv->ip.protocol = IP_PROTOCOL_IPV6;
1082 ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
1084 else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
1086 ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
1087 if ((clib_net_to_host_u32 (
1088 encap->ip_version_traffic_class_and_flow_label) >>
1091 // Bad encap packet.
1092 next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
1096 else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
1098 ip6srv->ip.protocol = IP_PROTOCOL_IPV6;
1099 if ((clib_net_to_host_u32 (
1100 encap->ip_version_traffic_class_and_flow_label) >>
1103 // Bad encap packet.
1104 next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
1108 else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
1110 ip6srv->ip.protocol = IP_PROTOCOL_IP6_ETHERNET;
1115 ip6srv->ip.src_address = src6;
1117 if (PREDICT_FALSE (ie_size))
1120 user_plane_sub_tlv_t *sub_tlv;
1122 tlv = (ip6_sr_tlv_t *) ((u8 *) ip6srv + (hdr_len - tlv_siz));
1123 tlv->type = SRH_TLV_USER_PLANE_CONTAINER;
1124 tlv->length = (u8) (tlv_siz - sizeof (ip6_sr_tlv_t));
1125 clib_memset (tlv->value, 0, tlv->length);
1127 sub_tlv = (user_plane_sub_tlv_t *) tlv->value;
1128 sub_tlv->type = USER_PLANE_SUB_TLV_IE;
1129 sub_tlv->length = (u8) ie_size;
1130 clib_memcpy_fast (sub_tlv->value, ie_buf, ie_size);
1132 ip6srv->sr.length += (u8) (tlv_siz / 8);
1135 ip6srv->ip.payload_length =
1136 clib_host_to_net_u16 (len0 + hdr_len - sizeof (ip6_header_t));
1138 vnet_buffer (b0)->sw_if_index[VLIB_TX] = 0; /* default FIB */
1140 if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
1141 PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1143 srv6_end_rewrite_trace_t *tr =
1144 vlib_add_trace (vm, node, b0, sizeof (*tr));
1145 clib_memcpy (tr->src.as_u8, ip6srv->ip.src_address.as_u8,
1146 sizeof (tr->src.as_u8));
1147 clib_memcpy (tr->dst.as_u8, ip6srv->ip.dst_address.as_u8,
1148 sizeof (tr->dst.as_u8));
1156 VLIB_NODE_FN (srv6_t_m_gtp4_d)
1157 (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
1159 srv6_t_main_v4_decap_t *sm = &srv6_t_main_v4_decap;
1160 ip6_sr_main_t *sm2 = &sr_main;
1161 u32 n_left_from, next_index, *from, *to_next;
1164 srv6_end_gtp4_d_param_t *ls_param;
1166 u32 good_n = 0, bad_n = 0;
1168 from = vlib_frame_vector_args (frame);
1169 n_left_from = frame->n_vectors;
1170 next_index = node->cached_next_index;
1172 while (n_left_from > 0)
1176 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1178 while (n_left_from > 0 && n_left_to_next > 0)
1185 ip4_gtpu_header_t *hdr;
1197 n_left_to_next -= 1;
1199 b0 = vlib_get_buffer (vm, bi0);
1201 sl0 = pool_elt_at_index (sm2->sid_lists,
1202 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1204 ls_param = (srv6_end_gtp4_d_param_t *) sl0->plugin_mem;
1206 hdr = vlib_buffer_get_current (b0);
1207 gtpu_type = hdr->gtpu.type;
1212 if (PREDICT_FALSE (gtpu_type != GTPU_TYPE_GTPU || ls_param->drop_in))
1220 hdrlen = sizeof (ip4_gtpu_header_t);
1222 if (hdr->gtpu.ver_flags & (GTPU_EXTHDR_FLAG | GTPU_SEQ_FLAG))
1224 hdrlen += sizeof (gtpu_exthdr_t);
1225 if (hdr->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
1227 gtpu_pdu_session_t *sess;
1228 sess = (gtpu_pdu_session_t *) (((char *) hdr) + hdrlen);
1229 hdrlen += sizeof (gtpu_pdu_session_t);
1231 if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
1233 hdrlen += sizeof (gtpu_paging_policy_t);
1238 ip6 = (ip6_header_t *) (((char *) hdr) + hdrlen);
1239 if ((clib_net_to_host_u32 (
1240 ip6->ip_version_traffic_class_and_flow_label) >>
1244 if (((ip6->dst_address.as_u8[0] == 0xff) &&
1245 (ip6->dst_address.as_u8[1] == 0x02)) ||
1246 ((ip6->dst_address.as_u8[0] == 0xfe) &&
1247 ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80)))
1249 // Inner desitnation is IPv6 link local
1257 next0 = srv6_gtp4_decap_processing (vm, node, b0);
1258 if (PREDICT_TRUE (next0 == SRV6_T_M_GTP4_D_NEXT_LOOKUP6))
1265 /* Strip off the outer header (IPv4 + GTP + UDP + IEs) */
1266 vlib_buffer_advance (b0, (word) hdrlen);
1270 next0 = SRV6_T_M_GTP4_D_NEXT_LOOKUP4;
1271 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1272 ls_param->fib4_index;
1276 next0 = SRV6_T_M_GTP4_D_NEXT_LOOKUP6;
1277 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1278 ls_param->fib6_index;
1282 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1283 n_left_to_next, bi0, next0);
1286 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1289 vlib_node_increment_counter (vm, sm->t_m_gtp4_d_node_index,
1290 SRV6_T_ERROR_M_GTP4_D_BAD_PACKETS, bad_n);
1292 vlib_node_increment_counter (vm, sm->t_m_gtp4_d_node_index,
1293 SRV6_T_ERROR_M_GTP4_D_PACKETS, good_n);
1295 return frame->n_vectors;
1298 VLIB_REGISTER_NODE (srv6_end_m_gtp4_e) =
1300 .name = "srv6-end-m-gtp4-e",.vector_size = sizeof (u32),.format_trace =
1301 format_srv6_end_rewrite_trace,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
1302 ARRAY_LEN (srv6_end_error_v4_strings),.error_strings =
1303 srv6_end_error_v4_strings,.n_next_nodes =
1304 SRV6_END_M_GTP4_E_N_NEXT,.next_nodes =
1306 [SRV6_END_M_GTP4_E_NEXT_DROP] = "error-drop",
1307 [SRV6_END_M_GTP4_E_NEXT_LOOKUP] = "ip4-lookup",}
1310 VLIB_REGISTER_NODE (srv6_t_m_gtp4_d) =
1312 .name = "srv6-t-m-gtp4-d",.vector_size = sizeof (u32),.format_trace =
1313 format_srv6_end_rewrite_trace,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
1314 ARRAY_LEN (srv6_t_error_v4_d_strings),.error_strings =
1315 srv6_t_error_v4_d_strings,.n_next_nodes =
1316 SRV6_T_M_GTP4_D_N_NEXT,.next_nodes =
1318 [SRV6_T_M_GTP4_D_NEXT_DROP] = "error-drop",
1319 [SRV6_T_M_GTP4_D_NEXT_LOOKUP4] = "ip4-lookup",
1320 [SRV6_T_M_GTP4_D_NEXT_LOOKUP6] = "ip6-lookup",}
1323 // Function for SRv6 GTP6.E function
1324 VLIB_NODE_FN (srv6_end_m_gtp6_e)
1325 (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
1327 srv6_end_main_v6_t *sm = &srv6_end_main_v6;
1328 ip6_sr_main_t *sm2 = &sr_main;
1329 u32 n_left_from, next_index, *from, *to_next;
1330 u32 thread_index = vm->thread_index;
1332 u32 good_n = 0, bad_n = 0;
1334 from = vlib_frame_vector_args (frame);
1335 n_left_from = frame->n_vectors;
1336 next_index = node->cached_next_index;
1338 while (n_left_from > 0)
1342 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1344 while (n_left_from > 0 && n_left_to_next > 0)
1348 ip6_sr_localsid_t *ls0;
1349 srv6_end_gtp6_e_param_t *ls_param;
1351 ip6srv_combo_header_t *ip6srv0;
1352 ip6_address_t dst0, src0, seg0;
1354 ip6_gtpu_header_t *hdr0 = NULL;
1362 u32 next0 = SRV6_END_M_GTP6_E_NEXT_LOOKUP;
1370 n_left_to_next -= 1;
1372 b0 = vlib_get_buffer (vm, bi0);
1373 ls0 = pool_elt_at_index (sm2->localsids,
1374 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1376 ls_param = (srv6_end_gtp6_e_param_t *) ls0->plugin_mem;
1378 ip6srv0 = vlib_buffer_get_current (b0);
1379 dst0 = ip6srv0->ip.dst_address;
1380 src0 = ip6srv0->ip.src_address;
1381 seg0 = ip6srv0->sr.segments[0];
1383 tag = ip6srv0->sr.tag;
1385 len0 = vlib_buffer_length_in_chain (vm, b0);
1387 if ((ip6srv0->ip.protocol != IPPROTO_IPV6_ROUTE) ||
1388 (len0 < sizeof (ip6srv_combo_header_t) + 8 * ip6srv0->sr.length))
1390 next0 = SRV6_END_M_GTP6_E_NEXT_DROP;
1396 // we need to be sure there is enough space before
1397 // ip6srv0 header, there is some extra space
1398 // in the pre_data area for this kind of
1402 u8 *teid8p = (u8 *) &teid;
1410 u8 ie_buf[GTPU_IE_MAX_SIZ];
1412 index = ls0->localsid_prefix_len;
1416 gtpu_type = gtpu_type_get (tag);
1418 if (PREDICT_TRUE (shift == 0))
1420 qfi = dst0.as_u8[offset];
1421 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
1422 gtpu_type == GTPU_TYPE_ECHO_REPLY ||
1423 gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1425 clib_memcpy_fast (&seq, &dst0.as_u8[offset + 1], 2);
1429 clib_memcpy_fast (teid8p, &dst0.as_u8[offset + 1], 4);
1436 qfi |= dst0.as_u8[offset] << shift;
1437 qfi |= dst0.as_u8[offset + 1] >> (8 - shift);
1439 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
1440 gtpu_type == GTPU_TYPE_ECHO_REPLY ||
1441 gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1444 for (index = 0; index < 2; index++)
1446 sp[index] = dst0.as_u8[offset + 1 + index] << shift;
1448 dst0.as_u8[offset + index + 2] >> (8 - shift);
1453 for (index = 0; index < 4; index++)
1455 *teid8p = dst0.as_u8[offset + index + 1] << shift;
1457 dst0.as_u8[offset + index + 2] >> (8 - shift);
1466 sizeof (gtpu_exthdr_t) + sizeof (gtpu_pdu_session_t);
1468 else if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
1469 gtpu_type == GTPU_TYPE_ECHO_REPLY ||
1470 gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1472 hdrlen = sizeof (gtpu_exthdr_t);
1475 if (gtpu_type == GTPU_TYPE_ECHO_REPLY)
1477 hdrlen += sizeof (gtpu_recovery_ie);
1480 if (PREDICT_FALSE (gtpu_type == GTPU_TYPE_ERROR_INDICATION))
1485 ext_len = ip6srv0->sr.length * 8;
1488 sizeof (ip6_address_t) * (ip6srv0->sr.last_entry + 1))
1490 tlv = (ip6_sr_tlv_t *) ((u8 *) &ip6srv0->sr +
1491 sizeof (ip6_sr_header_t) +
1492 sizeof (ip6_address_t) *
1493 (ip6srv0->sr.last_entry + 1));
1495 if (tlv->type == SRH_TLV_USER_PLANE_CONTAINER)
1497 user_plane_sub_tlv_t *sub_tlv;
1499 sub_tlv = (user_plane_sub_tlv_t *) tlv->value;
1501 ie_size = sub_tlv->length;
1502 clib_memcpy_fast (ie_buf, sub_tlv->value, ie_size);
1509 vlib_buffer_advance (b0, (word) sizeof (ip6srv_combo_header_t) +
1510 ip6srv0->sr.length * 8);
1512 // get length of encapsulated IPv6 packet (the remaining part)
1513 p = vlib_buffer_get_current (b0);
1515 plen = len0 = vlib_buffer_length_in_chain (vm, b0);
1519 hdrlen += sizeof (ip6_gtpu_header_t);
1521 vlib_buffer_advance (b0, -(word) hdrlen);
1523 hdr0 = vlib_buffer_get_current (b0);
1525 clib_memcpy_fast (hdr0, &sm->cache_hdr,
1526 sizeof (ip6_gtpu_header_t));
1528 hdr0->gtpu.teid = teid;
1529 hdr0->gtpu.length = clib_host_to_net_u16 (len0);
1531 hdr0->gtpu.type = gtpu_type;
1533 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
1534 gtpu_type == GTPU_TYPE_ECHO_REPLY ||
1535 gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1537 hdr0->gtpu.ver_flags |= GTPU_SEQ_FLAG;
1538 hdr0->gtpu.ext->seq = seq;
1539 hdr0->gtpu.ext->npdu_num = 0;
1540 hdr0->gtpu.ext->nextexthdr = 0;
1542 if (gtpu_type == GTPU_TYPE_ECHO_REPLY)
1544 gtpu_recovery_ie *recovery;
1547 (gtpu_recovery_ie *) ((u8 *) hdr0 +
1549 sizeof (gtpu_recovery_ie)));
1550 recovery->type = GTPU_RECOVERY_IE_TYPE;
1551 recovery->restart_counter = 0;
1553 else if (gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1559 ie_ptr = (u8 *) ((u8 *) hdr0 + (hdrlen - ie_size));
1560 clib_memcpy_fast (ie_ptr, ie_buf, ie_size);
1568 hdr0->gtpu.ext->seq = 0;
1569 hdr0->gtpu.ext->npdu_num = 0;
1576 gtpu_pdu_session_t *sess;
1578 hdr0->gtpu.ver_flags |= GTPU_EXTHDR_FLAG;
1580 hdr0->gtpu.ext->nextexthdr = GTPU_EXTHDR_PDU_SESSION;
1582 type = qfi & SRV6_PDU_SESSION_U_BIT_MASK;
1584 qfi = ((qfi & SRV6_PDU_SESSION_QFI_MASK) >> 2) |
1585 ((qfi & SRV6_PDU_SESSION_R_BIT_MASK) << 5);
1587 sess = (gtpu_pdu_session_t *) (((char *) hdr0) +
1588 sizeof (ip6_gtpu_header_t) +
1589 sizeof (gtpu_exthdr_t));
1590 sess->exthdrlen = 1;
1594 sess->nextexthdr = 0;
1597 hdr0->udp.length = clib_host_to_net_u16 (
1598 len0 + sizeof (udp_header_t) + sizeof (gtpu_header_t));
1600 clib_memcpy_fast (hdr0->ip6.src_address.as_u8, src0.as_u8,
1601 sizeof (ip6_address_t));
1602 clib_memcpy_fast (hdr0->ip6.dst_address.as_u8, &seg0.as_u8,
1603 sizeof (ip6_address_t));
1605 hdr0->ip6.payload_length = clib_host_to_net_u16 (
1606 len0 + sizeof (udp_header_t) + sizeof (gtpu_header_t));
1609 key = hash_memory (p, plen < 40 ? plen : 40, 0);
1610 port = hash_uword_to_u16 (&key);
1611 hdr0->udp.src_port = port;
1613 vnet_buffer (b0)->sw_if_index[VLIB_TX] = ls_param->fib6_index;
1617 if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
1618 PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1620 srv6_end_rewrite_trace_t *tr =
1621 vlib_add_trace (vm, node, b0, sizeof (*tr));
1622 clib_memcpy (tr->src.as_u8, hdr0->ip6.src_address.as_u8,
1623 sizeof (ip6_address_t));
1624 clib_memcpy (tr->dst.as_u8, hdr0->ip6.dst_address.as_u8,
1625 sizeof (ip6_address_t));
1626 tr->teid = hdr0->gtpu.teid;
1630 vlib_increment_combined_counter (
1631 ((next0 == SRV6_END_M_GTP6_E_NEXT_DROP) ?
1632 &(sm2->sr_ls_invalid_counters) :
1633 &(sm2->sr_ls_valid_counters)),
1634 thread_index, ls0 - sm2->localsids, 1,
1635 vlib_buffer_length_in_chain (vm, b0));
1637 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1638 n_left_to_next, bi0, next0);
1641 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1644 vlib_node_increment_counter (vm, sm->end_m_gtp6_e_node_index,
1645 SRV6_END_ERROR_M_GTP6_E_BAD_PACKETS, bad_n);
1647 vlib_node_increment_counter (vm, sm->end_m_gtp6_e_node_index,
1648 SRV6_END_ERROR_M_GTP6_E_PACKETS, good_n);
1650 return frame->n_vectors;
1653 // Function for SRv6 GTP6.D function
1655 srv6_gtp6_decap_processing (vlib_main_t *vm, vlib_node_runtime_t *node,
1658 srv6_end_main_v6_decap_t *sm = &srv6_end_main_v6_decap;
1659 ip6_sr_main_t *sm2 = &sr_main;
1661 ip6_sr_localsid_t *ls0;
1662 srv6_end_gtp6_d_param_t *ls_param;
1664 ip6_gtpu_header_t *hdr0 = NULL;
1667 ip6_address_t seg0, src0, dst0;
1677 ip6_header_t *encap = NULL;
1678 gtpu_pdu_session_t *sess = NULL;
1681 u8 ie_buf[GTPU_IE_MAX_SIZ];
1683 u32 next0 = SRV6_END_M_GTP6_D_NEXT_LOOKUP6;
1685 ls0 = pool_elt_at_index (sm2->localsids,
1686 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1688 ls_param = (srv6_end_gtp6_d_param_t *) ls0->plugin_mem;
1690 hdr0 = vlib_buffer_get_current (b0);
1692 hdrlen = sizeof (ip6_gtpu_header_t);
1694 len0 = vlib_buffer_length_in_chain (vm, b0);
1696 if ((hdr0->ip6.protocol != IP_PROTOCOL_UDP) ||
1697 (hdr0->udp.dst_port != clib_host_to_net_u16 (SRV6_GTP_UDP_DST_PORT)) ||
1698 (len0 < sizeof (ip6_gtpu_header_t)))
1700 next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
1704 seg0 = ls_param->sr_prefix;
1705 src0 = hdr0->ip6.src_address;
1706 dst0 = hdr0->ip6.dst_address;
1708 gtpu_type = hdr0->gtpu.type;
1710 teid = hdr0->gtpu.teid;
1711 teidp = (u8 *) &teid;
1715 if (hdr0->gtpu.ver_flags & (GTPU_EXTHDR_FLAG | GTPU_SEQ_FLAG))
1717 // Extention header.
1718 hdrlen += sizeof (gtpu_exthdr_t);
1720 seq = hdr0->gtpu.ext->seq;
1722 if (hdr0->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
1724 // PDU Session Container.
1725 sess = (gtpu_pdu_session_t *) (((char *) hdr0) +
1726 sizeof (ip6_gtpu_header_t) +
1727 sizeof (gtpu_exthdr_t));
1728 qfi = sess->u.val & ~GTPU_PDU_SESSION_P_BIT_MASK;
1731 hdrlen += sizeof (gtpu_pdu_session_t);
1733 if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
1735 hdrlen += sizeof (gtpu_paging_policy_t);
1740 offset = ls_param->sr_prefixlen / 8;
1741 shift = ls_param->sr_prefixlen % 8;
1743 if (PREDICT_TRUE (shift == 0))
1747 qfi = ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
1748 ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
1752 qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
1755 seg0.as_u8[offset] = qfi;
1758 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
1759 gtpu_type == GTPU_TYPE_ECHO_REPLY ||
1760 gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1762 clib_memcpy_fast (&seg0.as_u8[offset + 1], seqp, 2);
1766 clib_memcpy_fast (&seg0.as_u8[offset + 1], teidp, 4);
1775 qfi = ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
1776 ((qfi & ~GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
1780 qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
1783 seg0.as_u8[offset] |= qfi >> shift;
1784 seg0.as_u8[offset + 1] |= qfi << (8 - shift);
1787 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
1788 gtpu_type == GTPU_TYPE_ECHO_REPLY ||
1789 gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1791 for (idx = 0; idx < 2; idx++)
1793 seg0.as_u8[offset + idx + 1] |= seqp[idx] >> shift;
1794 seg0.as_u8[offset + idx + 2] |= seqp[idx] << (8 - shift);
1799 for (idx = 0; idx < 4; idx++)
1801 seg0.as_u8[offset + idx + 1] |= teidp[idx] >> shift;
1802 seg0.as_u8[offset + idx + 2] |= teidp[idx] << (8 - shift);
1807 if (PREDICT_FALSE (gtpu_type == GTPU_TYPE_ERROR_INDICATION))
1811 payload_len = clib_net_to_host_u16 (hdr0->gtpu.length);
1812 if (payload_len != 0)
1814 ie_size = payload_len - (hdrlen - sizeof (ip6_gtpu_header_t));
1819 ies = (u8 *) ((u8 *) hdr0 + hdrlen);
1820 clib_memcpy_fast (ie_buf, ies, ie_size);
1826 // jump over variable length data
1827 vlib_buffer_advance (b0, (word) hdrlen);
1829 // get length of encapsulated IPv6 packet (the remaining part)
1830 len0 = vlib_buffer_length_in_chain (vm, b0);
1832 if (PREDICT_TRUE (gtpu_type == GTPU_TYPE_GTPU))
1834 encap = vlib_buffer_get_current (b0);
1838 ip6srv_combo_header_t *ip6srv;
1839 ip6_sr_policy_t *sr_policy = NULL;
1840 ip6_sr_sl_t *sl = NULL;
1844 p = mhash_get (&sm2->sr_policies_index_hash, &ls_param->sr_prefix);
1847 sr_policy = pool_elt_at_index (sm2->sr_policies, p[0]);
1852 vec_foreach (sl_index, sr_policy->segments_lists)
1854 sl = pool_elt_at_index (sm2->sid_lists, *sl_index);
1862 hdr_len = sizeof (ip6srv_combo_header_t);
1863 hdr_len += vec_len (sl->segments) * sizeof (ip6_address_t);
1864 hdr_len += sizeof (ip6_address_t) * 2;
1868 hdr_len = sizeof (ip6_header_t);
1869 hdr_len += sizeof (ip6_sr_header_t);
1870 hdr_len += sizeof (ip6_address_t) * 2;
1876 sizeof (ip6_sr_tlv_t) + sizeof (user_plane_sub_tlv_t) + ie_size;
1878 tlv_siz = (tlv_siz & ~0x07) + (tlv_siz & 0x07 ? 0x08 : 0x0);
1882 // jump back to data[0] or pre_data if required
1883 vlib_buffer_advance (b0, -(word) hdr_len);
1885 ip6srv = vlib_buffer_get_current (b0);
1889 clib_memcpy_fast (ip6srv, sl->rewrite, vec_len (sl->rewrite));
1891 if (vec_len (sl->segments) > 1)
1893 ip6srv->ip.src_address = src0;
1895 ip6srv->sr.tag = clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1897 ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
1898 ip6srv->sr.segments_left += 2;
1899 ip6srv->sr.last_entry += 2;
1901 ip6srv->sr.length += (sizeof (ip6_address_t) * 2) / 8;
1902 ip6srv->sr.segments[0] = dst0;
1903 ip6srv->sr.segments[1] = seg0;
1905 clib_memcpy_fast (&ip6srv->sr.segments[2],
1906 (u8 *) (sl->rewrite + sizeof (ip6_header_t) +
1907 sizeof (ip6_sr_header_t)),
1908 vec_len (sl->segments) *
1909 sizeof (ip6_address_t));
1913 ip6srv->ip.src_address = src0;
1914 ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
1916 ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
1917 ip6srv->sr.segments_left = 2;
1918 ip6srv->sr.last_entry = 1;
1919 ip6srv->sr.length = (sizeof (ip6_address_t) * 2) / 8;
1920 ip6srv->sr.flags = 0;
1922 ip6srv->sr.tag = clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1924 ip6srv->sr.segments[0] = dst0;
1925 ip6srv->sr.segments[1] = seg0;
1927 if (vec_len (sl->segments))
1929 ip6srv->sr.segments[2] = sl->segments[0];
1930 ip6srv->sr.last_entry++;
1931 ip6srv->sr.length += sizeof (ip6_address_t) / 8;
1935 if (PREDICT_TRUE (encap != NULL))
1937 if (ls_param->nhtype == SRV6_NHTYPE_NONE)
1939 if ((clib_net_to_host_u32 (
1940 encap->ip_version_traffic_class_and_flow_label) >>
1942 ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
1944 ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
1946 else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
1948 ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
1949 if ((clib_net_to_host_u32 (
1950 encap->ip_version_traffic_class_and_flow_label) >>
1953 // Bad encap packet.
1954 next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
1958 else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
1960 ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
1961 if ((clib_net_to_host_u32 (
1962 encap->ip_version_traffic_class_and_flow_label) >>
1965 // Bad encap packet.
1966 next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
1970 else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
1972 ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
1977 ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
1982 clib_memcpy_fast (ip6srv, &sm->cache_hdr, sizeof (ip6_header_t));
1984 ip6srv->ip.src_address = src0;
1985 ip6srv->ip.dst_address = seg0;
1987 ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
1989 ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
1990 ip6srv->sr.segments_left = 1;
1991 ip6srv->sr.last_entry = 1;
1993 ip6srv->sr.length = (sizeof (ip6_address_t) * 2) / 8;
1994 ip6srv->sr.segments[0] = dst0;
1995 ip6srv->sr.segments[1] = seg0;
1997 if (PREDICT_FALSE (gtpu_type) != GTPU_TYPE_GTPU)
1999 ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
2000 ip6srv->sr.tag = clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
2004 if (ls_param->nhtype == SRV6_NHTYPE_NONE)
2006 if ((clib_net_to_host_u32 (
2007 encap->ip_version_traffic_class_and_flow_label) >>
2009 ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
2011 else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
2013 ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
2014 if ((clib_net_to_host_u32 (
2015 encap->ip_version_traffic_class_and_flow_label) >>
2018 // Bad encap packet.
2019 next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
2023 else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
2025 ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
2026 if ((clib_net_to_host_u32 (
2027 encap->ip_version_traffic_class_and_flow_label) >>
2030 // Bad encap packet.
2031 next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
2035 else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
2037 ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
2042 if (PREDICT_FALSE (ie_size))
2045 user_plane_sub_tlv_t *sub_tlv;
2047 tlv = (ip6_sr_tlv_t *) ((u8 *) ip6srv + (hdr_len - tlv_siz));
2048 tlv->type = SRH_TLV_USER_PLANE_CONTAINER;
2049 tlv->length = (u8) (tlv_siz - sizeof (ip6_sr_tlv_t));
2050 clib_memset (tlv->value, 0, tlv->length);
2052 sub_tlv = (user_plane_sub_tlv_t *) tlv->value;
2053 sub_tlv->type = USER_PLANE_SUB_TLV_IE;
2054 sub_tlv->length = (u8) ie_size;
2055 clib_memcpy_fast (sub_tlv->value, ie_buf, ie_size);
2057 ip6srv->sr.length += (u8) (tlv_siz / 8);
2060 ip6srv->ip.payload_length =
2061 clib_host_to_net_u16 (len0 + hdr_len - sizeof (ip6_header_t));
2063 vnet_buffer (b0)->sw_if_index[VLIB_TX] = 0; /* default FIB */
2065 if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
2066 PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2068 srv6_end_rewrite_trace_t *tr =
2069 vlib_add_trace (vm, node, b0, sizeof (*tr));
2070 clib_memcpy (tr->src.as_u8, ip6srv->ip.src_address.as_u8,
2071 sizeof (ip6_address_t));
2072 clib_memcpy (tr->dst.as_u8, ip6srv->ip.dst_address.as_u8,
2073 sizeof (ip6_address_t));
2075 clib_memcpy (tr->sr_prefix.as_u8, ls_param->sr_prefix.as_u8,
2076 sizeof (ip6_address_t));
2077 tr->sr_prefixlen = ls_param->sr_prefixlen;
2085 VLIB_NODE_FN (srv6_end_m_gtp6_d)
2086 (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
2088 srv6_end_main_v6_decap_t *sm = &srv6_end_main_v6_decap;
2089 ip6_sr_main_t *sm2 = &sr_main;
2090 u32 n_left_from, next_index, *from, *to_next;
2091 u32 thread_index = vm->thread_index;
2092 ip6_sr_localsid_t *ls0;
2093 srv6_end_gtp6_d_param_t *ls_param;
2095 u32 good_n = 0, bad_n = 0;
2097 from = vlib_frame_vector_args (frame);
2098 n_left_from = frame->n_vectors;
2099 next_index = node->cached_next_index;
2101 while (n_left_from > 0)
2105 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2107 while (n_left_from > 0 && n_left_to_next > 0)
2114 ip6_gtpu_header_t *hdr;
2126 n_left_to_next -= 1;
2128 b0 = vlib_get_buffer (vm, bi0);
2130 ls0 = pool_elt_at_index (sm2->localsids,
2131 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
2133 ls_param = (srv6_end_gtp6_d_param_t *) ls0->plugin_mem;
2135 hdr = vlib_buffer_get_current (b0);
2136 gtpu_type = hdr->gtpu.type;
2141 if (PREDICT_FALSE (gtpu_type != GTPU_TYPE_GTPU || ls_param->drop_in))
2149 hdrlen = sizeof (ip6_gtpu_header_t);
2151 if (hdr->gtpu.ver_flags & (GTPU_EXTHDR_FLAG | GTPU_SEQ_FLAG))
2153 hdrlen += sizeof (gtpu_exthdr_t);
2154 if (hdr->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
2156 gtpu_pdu_session_t *sess;
2157 sess = (gtpu_pdu_session_t *) (((char *) hdr) + hdrlen);
2158 hdrlen += sizeof (gtpu_pdu_session_t);
2160 if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
2162 hdrlen += sizeof (gtpu_paging_policy_t);
2167 ip6 = (ip6_header_t *) (((char *) hdr) + hdrlen);
2168 if ((clib_net_to_host_u32 (
2169 ip6->ip_version_traffic_class_and_flow_label) >>
2173 if (((ip6->dst_address.as_u8[0] == 0xff) &&
2174 (ip6->dst_address.as_u8[1] == 0x02)) ||
2175 ((ip6->dst_address.as_u8[0] == 0xfe) &&
2176 ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80)))
2178 // Inner desitnation is IPv6 link local
2186 next0 = srv6_gtp6_decap_processing (vm, node, b0);
2187 if (PREDICT_TRUE (next0 == SRV6_END_M_GTP6_D_NEXT_LOOKUP6))
2192 vlib_increment_combined_counter (
2193 ((next0 == SRV6_END_M_GTP6_D_NEXT_DROP) ?
2194 &(sm2->sr_ls_invalid_counters) :
2195 &(sm2->sr_ls_valid_counters)),
2196 thread_index, ls0 - sm2->localsids, 1,
2197 vlib_buffer_length_in_chain (vm, b0));
2201 /* Strip off the outer header (IPv6 + GTP + UDP + IEs) */
2202 vlib_buffer_advance (b0, (word) hdrlen);
2206 next0 = SRV6_END_M_GTP6_D_NEXT_LOOKUP4;
2207 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2208 ls_param->fib4_index;
2212 next0 = SRV6_END_M_GTP6_D_NEXT_LOOKUP6;
2213 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2214 ls_param->fib6_index;
2218 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2219 n_left_to_next, bi0, next0);
2222 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2225 vlib_node_increment_counter (vm, sm->end_m_gtp6_d_node_index,
2226 SRV6_END_ERROR_M_GTP6_D_BAD_PACKETS, bad_n);
2228 vlib_node_increment_counter (vm, sm->end_m_gtp6_d_node_index,
2229 SRV6_END_ERROR_M_GTP6_D_PACKETS, good_n);
2231 return frame->n_vectors;
2234 // Function for SRv6 GTP6.D.DI function
2235 VLIB_NODE_FN (srv6_end_m_gtp6_d_di)
2236 (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
2238 srv6_end_main_v6_decap_di_t *sm = &srv6_end_main_v6_decap_di;
2239 ip6_sr_main_t *sm2 = &sr_main;
2240 u32 n_left_from, next_index, *from, *to_next;
2241 u32 thread_index = vm->thread_index;
2242 srv6_end_gtp6_d_param_t *ls_param;
2244 u32 good_n = 0, bad_n = 0;
2246 from = vlib_frame_vector_args (frame);
2247 n_left_from = frame->n_vectors;
2248 next_index = node->cached_next_index;
2250 while (n_left_from > 0)
2254 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2256 while (n_left_from > 0 && n_left_to_next > 0)
2260 ip6_sr_localsid_t *ls0;
2262 ip6_gtpu_header_t *hdr0 = NULL;
2277 ip6_header_t *encap = NULL;
2278 gtpu_pdu_session_t *sess;
2281 u8 ie_buf[GTPU_IE_MAX_SIZ];
2283 u32 next0 = SRV6_END_M_GTP6_D_DI_NEXT_LOOKUP;
2291 n_left_to_next -= 1;
2293 b0 = vlib_get_buffer (vm, bi0);
2294 ls0 = pool_elt_at_index (sm2->localsids,
2295 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
2297 ls_param = (srv6_end_gtp6_d_param_t *) ls0->plugin_mem;
2299 hdr0 = vlib_buffer_get_current (b0);
2301 hdrlen = sizeof (ip6_gtpu_header_t);
2303 len0 = vlib_buffer_length_in_chain (vm, b0);
2305 if ((hdr0->ip6.protocol != IP_PROTOCOL_UDP) ||
2306 (hdr0->udp.dst_port !=
2307 clib_host_to_net_u16 (SRV6_GTP_UDP_DST_PORT)) ||
2308 (len0 < sizeof (ip6_gtpu_header_t)))
2310 next0 = SRV6_END_M_GTP6_D_DI_NEXT_DROP;
2316 dst0 = hdr0->ip6.dst_address;
2317 src0 = hdr0->ip6.src_address;
2319 gtpu_type = hdr0->gtpu.type;
2321 seg0 = ls_param->sr_prefix;
2322 teid = hdr0->gtpu.teid;
2323 teidp = (u8 *) &teid;
2327 if (hdr0->gtpu.ver_flags & (GTPU_EXTHDR_FLAG | GTPU_SEQ_FLAG))
2329 // Extention header.
2330 hdrlen += sizeof (gtpu_exthdr_t);
2332 seq = hdr0->gtpu.ext->seq;
2334 if (hdr0->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
2336 // PDU Session Container.
2337 sess = (gtpu_pdu_session_t *) (((char *) hdr0) + hdrlen);
2338 qfi = sess->u.val & ~GTPU_PDU_SESSION_P_BIT_MASK;
2341 hdrlen += sizeof (gtpu_pdu_session_t);
2343 if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
2345 hdrlen += sizeof (gtpu_paging_policy_t);
2350 offset = ls_param->sr_prefixlen / 8;
2351 shift = ls_param->sr_prefixlen % 8;
2354 if (PREDICT_TRUE (shift == 0))
2356 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
2357 gtpu_type == GTPU_TYPE_ECHO_REPLY ||
2358 gtpu_type == GTPU_TYPE_ERROR_INDICATION)
2360 clib_memcpy_fast (&seg0.as_u8[offset], seqp, 2);
2364 clib_memcpy_fast (&seg0.as_u8[offset], teidp, 4);
2369 qfi = ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
2370 ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
2374 qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
2377 seg0.as_u8[offset + 4] = qfi;
2384 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST ||
2385 gtpu_type == GTPU_TYPE_ECHO_REPLY ||
2386 gtpu_type == GTPU_TYPE_ERROR_INDICATION)
2388 for (idx = 0; idx < 2; idx++)
2390 seg0.as_u8[offset + idx] |= seqp[idx] >> shift;
2391 seg0.as_u8[offset + idx + 1] |= seqp[idx]
2397 for (idx = 0; idx < 4; idx++)
2399 seg0.as_u8[offset + idx] |= teidp[idx] >> shift;
2400 seg0.as_u8[offset + idx + 1] |= teidp[idx]
2407 qfi = ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
2408 ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
2412 qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
2415 seg0.as_u8[offset + 4] |= qfi >> shift;
2416 seg0.as_u8[offset + 5] |= qfi << (8 - shift);
2420 if (PREDICT_FALSE (gtpu_type == GTPU_TYPE_ERROR_INDICATION))
2424 payload_len = clib_net_to_host_u16 (hdr0->gtpu.length);
2425 if (payload_len != 0)
2428 payload_len - (hdrlen - sizeof (ip6_gtpu_header_t));
2433 ies = (u8 *) ((u8 *) hdr0 + hdrlen);
2434 clib_memcpy_fast (ie_buf, ies, ie_size);
2440 // jump over variable length data
2441 vlib_buffer_advance (b0, (word) hdrlen);
2443 // get length of encapsulated IPv6 packet (the remaining part)
2444 len0 = vlib_buffer_length_in_chain (vm, b0);
2446 if (PREDICT_TRUE (gtpu_type == GTPU_TYPE_GTPU))
2448 encap = vlib_buffer_get_current (b0);
2452 ip6srv_combo_header_t *ip6srv;
2453 ip6_sr_policy_t *sr_policy = NULL;
2454 ip6_sr_sl_t *sl = NULL;
2459 mhash_get (&sm2->sr_policies_index_hash, &ls_param->sr_prefix);
2462 sr_policy = pool_elt_at_index (sm2->sr_policies, p[0]);
2467 vec_foreach (sl_index, sr_policy->segments_lists)
2469 sl = pool_elt_at_index (sm2->sid_lists, *sl_index);
2475 hdr_len = sizeof (ip6srv_combo_header_t);
2478 hdr_len += vec_len (sl->segments) * sizeof (ip6_address_t);
2480 hdr_len += sizeof (ip6_address_t) * 2;
2484 tlv_siz = sizeof (ip6_sr_tlv_t) +
2485 sizeof (user_plane_sub_tlv_t) + ie_size;
2487 tlv_siz = (tlv_siz & ~0x07) + (tlv_siz & 0x07 ? 0x08 : 0x0);
2491 // jump back to data[0] or pre_data if required
2492 vlib_buffer_advance (b0, -(word) hdr_len);
2494 ip6srv = vlib_buffer_get_current (b0);
2498 clib_memcpy_fast (ip6srv, sl->rewrite,
2499 vec_len (sl->rewrite));
2501 if (vec_len (sl->segments) > 1)
2503 ip6srv->ip.src_address = src0;
2506 clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
2508 ip6srv->sr.segments_left += 2;
2509 ip6srv->sr.last_entry += 2;
2511 ip6srv->sr.length += ((sizeof (ip6_address_t) * 2) / 8);
2513 ip6srv->sr.segments[0] = dst0;
2514 ip6srv->sr.segments[1] = seg0;
2517 &ip6srv->sr.segments[2],
2518 (u8 *) (sl->rewrite + sizeof (ip6_header_t) +
2519 sizeof (ip6_sr_header_t)),
2520 vec_len (sl->segments) * sizeof (ip6_address_t));
2524 ip6srv->ip.src_address = src0;
2525 ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
2527 ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
2528 ip6srv->sr.segments_left = 2;
2529 ip6srv->sr.last_entry = 1;
2530 ip6srv->sr.length = ((sizeof (ip6_sr_header_t) +
2531 2 * sizeof (ip6_address_t)) /
2534 ip6srv->sr.flags = 0;
2537 clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
2539 ip6srv->sr.segments[0] = dst0;
2540 ip6srv->sr.segments[1] = seg0;
2542 if (vec_len (sl->segments))
2544 ip6srv->sr.segments[2] = sl->segments[0];
2545 ip6srv->sr.last_entry++;
2546 ip6srv->sr.length += sizeof (ip6_address_t) / 8;
2552 clib_memcpy_fast (ip6srv, &sm->cache_hdr,
2553 sizeof (ip6_header_t));
2555 ip6srv->ip.src_address = src0;
2556 ip6srv->ip.dst_address = seg0;
2558 ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
2559 ip6srv->sr.segments_left = 1;
2560 ip6srv->sr.last_entry = 0;
2562 ((sizeof (ip6_sr_header_t) + sizeof (ip6_address_t)) / 8) -
2564 ip6srv->sr.flags = 0;
2567 clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
2569 ip6srv->sr.segments[0] = dst0;
2572 if (PREDICT_FALSE (ie_size))
2575 user_plane_sub_tlv_t *sub_tlv;
2577 tlv = (ip6_sr_tlv_t *) ((u8 *) ip6srv + (hdr_len - tlv_siz));
2578 tlv->type = SRH_TLV_USER_PLANE_CONTAINER;
2579 tlv->length = (u8) (tlv_siz - sizeof (ip6_sr_tlv_t));
2580 clib_memset (tlv->value, 0, tlv->length);
2582 sub_tlv = (user_plane_sub_tlv_t *) tlv->value;
2583 sub_tlv->length = (u8) (ie_size);
2584 clib_memcpy_fast (sub_tlv->value, ie_buf, ie_size);
2586 ip6srv->sr.length += (u8) (tlv_siz / 8);
2589 ip6srv->ip.payload_length =
2590 clib_host_to_net_u16 (len0 + hdr_len - sizeof (ip6_header_t));
2591 ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
2593 if (PREDICT_TRUE (encap != NULL))
2595 if (ls_param->nhtype == SRV6_NHTYPE_NONE)
2597 if ((clib_net_to_host_u32 (
2598 encap->ip_version_traffic_class_and_flow_label) >>
2600 ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
2602 ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
2604 else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
2606 ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
2607 if ((clib_net_to_host_u32 (
2608 encap->ip_version_traffic_class_and_flow_label) >>
2611 // Bad encap packet.
2612 next0 = SRV6_END_M_GTP6_D_DI_NEXT_DROP;
2617 else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
2619 ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
2620 if ((clib_net_to_host_u32 (
2621 encap->ip_version_traffic_class_and_flow_label) >>
2624 // Bad encap packet.
2625 next0 = SRV6_END_M_GTP6_D_DI_NEXT_DROP;
2630 else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
2632 ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
2637 ip6srv->sr.protocol = IP_PROTOCOL_IP6_ETHERNET;
2642 if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
2643 PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2645 srv6_end_rewrite_trace_t *tr =
2646 vlib_add_trace (vm, node, b0, sizeof (*tr));
2647 clib_memcpy (tr->src.as_u8, ip6srv->ip.src_address.as_u8,
2648 sizeof (ip6_address_t));
2649 clib_memcpy (tr->dst.as_u8, ip6srv->ip.dst_address.as_u8,
2650 sizeof (ip6_address_t));
2652 clib_memcpy (tr->sr_prefix.as_u8, ls_param->sr_prefix.as_u8,
2653 sizeof (ip6_address_t));
2654 tr->sr_prefixlen = ls_param->sr_prefixlen;
2659 vlib_increment_combined_counter (
2660 ((next0 == SRV6_END_M_GTP6_D_DI_NEXT_DROP) ?
2661 &(sm2->sr_ls_invalid_counters) :
2662 &(sm2->sr_ls_valid_counters)),
2663 thread_index, ls0 - sm2->localsids, 1,
2664 vlib_buffer_length_in_chain (vm, b0));
2666 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2667 n_left_to_next, bi0, next0);
2670 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2673 vlib_node_increment_counter (vm, sm->end_m_gtp6_d_di_node_index,
2674 SRV6_END_ERROR_M_GTP6_D_DI_BAD_PACKETS, bad_n);
2676 vlib_node_increment_counter (vm, sm->end_m_gtp6_d_di_node_index,
2677 SRV6_END_ERROR_M_GTP6_D_DI_PACKETS, good_n);
2679 return frame->n_vectors;
2682 // Function for SRv6 GTP6.DT function
2683 VLIB_NODE_FN (srv6_end_m_gtp6_dt)
2684 (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
2686 srv6_end_main_v6_dt_t *sm = &srv6_end_main_v6_dt;
2687 ip6_sr_main_t *sm2 = &sr_main;
2688 u32 n_left_from, next_index, *from, *to_next;
2689 u32 thread_index = vm->thread_index;
2691 u32 good_n = 0, bad_n = 0;
2693 from = vlib_frame_vector_args (frame);
2694 n_left_from = frame->n_vectors;
2695 next_index = node->cached_next_index;
2697 while (n_left_from > 0)
2701 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2703 while (n_left_from > 0 && n_left_to_next > 0)
2707 srv6_end_gtp6_dt_param_t *ls_param;
2708 ip6_sr_localsid_t *ls0;
2710 ip6_gtpu_header_t *hdr0 = NULL;
2711 ip4_header_t *ip4 = NULL;
2712 ip6_header_t *ip6 = NULL;
2713 ip6_address_t src, dst;
2718 u32 next0 = SRV6_END_M_GTP6_DT_NEXT_DROP;
2725 n_left_to_next -= 1;
2727 b0 = vlib_get_buffer (vm, bi0);
2728 ls0 = pool_elt_at_index (sm2->localsids,
2729 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
2731 ls_param = (srv6_end_gtp6_dt_param_t *) ls0->plugin_mem;
2733 hdr0 = vlib_buffer_get_current (b0);
2735 hdrlen = sizeof (ip6_gtpu_header_t);
2737 len0 = vlib_buffer_length_in_chain (vm, b0);
2739 if ((hdr0->ip6.protocol != IP_PROTOCOL_UDP) ||
2740 (hdr0->udp.dst_port !=
2741 clib_host_to_net_u16 (SRV6_GTP_UDP_DST_PORT)) ||
2742 (len0 < sizeof (ip6_gtpu_header_t)))
2744 next0 = SRV6_END_M_GTP6_DT_NEXT_DROP;
2750 clib_memcpy_fast (src.as_u8, hdr0->ip6.src_address.as_u8,
2751 sizeof (ip6_address_t));
2752 clib_memcpy_fast (dst.as_u8, hdr0->ip6.dst_address.as_u8,
2753 sizeof (ip6_address_t));
2755 teid = hdr0->gtpu.teid;
2757 if (hdr0->gtpu.ver_flags & GTPU_EXTHDR_FLAG)
2759 hdrlen += sizeof (gtpu_exthdr_t);
2760 if (hdr0->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
2762 gtpu_pdu_session_t *sess;
2765 (gtpu_pdu_session_t *) (((char *) hdr0) +
2766 sizeof (ip6_gtpu_header_t) +
2767 sizeof (gtpu_exthdr_t));
2769 hdrlen += sizeof (gtpu_pdu_session_t);
2770 if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
2772 hdrlen += sizeof (gtpu_paging_policy_t);
2777 if (ls_param->type == SRV6_GTP6_DT4)
2779 vlib_buffer_advance (b0, (word) hdrlen);
2780 ip4 = vlib_buffer_get_current (b0);
2781 if ((ip4->ip_version_and_header_length & 0xf0) != 0x40)
2783 next0 = SRV6_END_M_GTP6_DT_NEXT_DROP;
2788 next0 = SRV6_END_M_GTP6_DT_NEXT_LOOKUP4;
2789 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2790 ls_param->fib4_index;
2792 else if (ls_param->type == SRV6_GTP6_DT6)
2794 ip6 = (ip6_header_t *) ((u8 *) hdr0 + hdrlen);
2795 if ((clib_net_to_host_u32 (
2796 ip6->ip_version_traffic_class_and_flow_label) >>
2799 next0 = SRV6_END_M_GTP6_DT_NEXT_DROP;
2804 next0 = SRV6_END_M_GTP6_DT_NEXT_LOOKUP6;
2805 if (((ip6->dst_address.as_u8[0] == 0xff) &&
2806 (ip6->dst_address.as_u8[1] == 0x02)) ||
2807 ((ip6->dst_address.as_u8[0] == 0xfe) &&
2808 ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80)))
2810 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2811 ls_param->local_fib_index;
2815 vlib_buffer_advance (b0, (word) hdrlen);
2816 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2817 ls_param->fib6_index;
2820 else if (ls_param->type == SRV6_GTP6_DT46)
2822 ip6 = (ip6_header_t *) ((u8 *) hdr0 + hdrlen);
2823 if ((clib_net_to_host_u32 (
2824 ip6->ip_version_traffic_class_and_flow_label) >>
2827 next0 = SRV6_END_M_GTP6_DT_NEXT_LOOKUP6;
2828 if (((ip6->dst_address.as_u8[0] == 0xff) &&
2829 (ip6->dst_address.as_u8[1] == 0x02)) ||
2830 ((ip6->dst_address.as_u8[0] == 0xfe) &&
2831 ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80)))
2833 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2834 ls_param->local_fib_index;
2838 vlib_buffer_advance (b0, (word) hdrlen);
2839 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2840 ls_param->fib6_index;
2843 else if ((clib_net_to_host_u32 (
2844 ip6->ip_version_traffic_class_and_flow_label) >>
2847 vlib_buffer_advance (b0, (word) hdrlen);
2848 next0 = SRV6_END_M_GTP6_DT_NEXT_LOOKUP4;
2849 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
2850 ls_param->fib4_index;
2854 next0 = SRV6_END_M_GTP6_DT_NEXT_DROP;
2861 next0 = SRV6_END_M_GTP6_DT_NEXT_DROP;
2868 if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
2869 PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2871 srv6_end_rewrite_trace_t *tr =
2872 vlib_add_trace (vm, node, b0, sizeof (*tr));
2873 clib_memcpy (tr->src.as_u8, src.as_u8,
2874 sizeof (ip6_address_t));
2875 clib_memcpy (tr->dst.as_u8, dst.as_u8,
2876 sizeof (ip6_address_t));
2882 vlib_increment_combined_counter (
2883 ((next0 == SRV6_END_M_GTP6_DT_NEXT_DROP) ?
2884 &(sm2->sr_ls_invalid_counters) :
2885 &(sm2->sr_ls_valid_counters)),
2886 thread_index, ls0 - sm2->localsids, 1,
2887 vlib_buffer_length_in_chain (vm, b0));
2889 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2890 n_left_to_next, bi0, next0);
2893 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2896 vlib_node_increment_counter (vm, sm->end_m_gtp6_dt_node_index,
2897 SRV6_END_ERROR_M_GTP6_DT_BAD_PACKETS, bad_n);
2899 vlib_node_increment_counter (vm, sm->end_m_gtp6_dt_node_index,
2900 SRV6_END_ERROR_M_GTP6_DT_PACKETS, good_n);
2902 return frame->n_vectors;
2905 // Function for SRv6 GTP4.DT function
2906 VLIB_NODE_FN (srv6_t_m_gtp4_dt)
2907 (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
2909 srv6_t_main_v4_dt_t *sm = &srv6_t_main_v4_dt;
2910 ip6_sr_main_t *sm2 = &sr_main;
2911 u32 n_left_from, next_index, *from, *to_next;
2913 u32 good_n = 0, bad_n = 0;
2915 from = vlib_frame_vector_args (frame);
2916 n_left_from = frame->n_vectors;
2917 next_index = node->cached_next_index;
2919 while (n_left_from > 0)
2923 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2925 while (n_left_from > 0 && n_left_to_next > 0)
2929 srv6_t_gtp4_dt_param_t *ls_param;
2932 ip4_gtpu_header_t *hdr0 = NULL;
2933 ip4_header_t *ip4 = NULL;
2934 ip6_header_t *ip6 = NULL;
2935 ip6_address_t src, dst;
2940 u32 next0 = SRV6_T_M_GTP4_DT_NEXT_DROP;
2947 n_left_to_next -= 1;
2949 b0 = vlib_get_buffer (vm, bi0);
2950 ls0 = pool_elt_at_index (sm2->sid_lists,
2951 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
2953 ls_param = (srv6_t_gtp4_dt_param_t *) ls0->plugin_mem;
2955 hdr0 = vlib_buffer_get_current (b0);
2957 hdrlen = sizeof (ip4_gtpu_header_t);
2959 len0 = vlib_buffer_length_in_chain (vm, b0);
2961 if ((hdr0->ip4.protocol != IP_PROTOCOL_UDP) ||
2962 (hdr0->udp.dst_port !=
2963 clib_host_to_net_u16 (SRV6_GTP_UDP_DST_PORT)) ||
2964 (len0 < sizeof (ip4_gtpu_header_t)))
2966 next0 = SRV6_T_M_GTP4_DT_NEXT_DROP;
2972 clib_memcpy_fast (src.as_u8, hdr0->ip4.src_address.as_u8,
2973 sizeof (ip4_address_t));
2974 clib_memcpy_fast (dst.as_u8, hdr0->ip4.dst_address.as_u8,
2975 sizeof (ip4_address_t));
2977 teid = hdr0->gtpu.teid;
2979 if (hdr0->gtpu.ver_flags & GTPU_EXTHDR_FLAG)
2981 hdrlen += sizeof (gtpu_exthdr_t);
2982 if (hdr0->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
2984 gtpu_pdu_session_t *sess;
2987 (gtpu_pdu_session_t *) (((char *) hdr0) +
2988 sizeof (ip6_gtpu_header_t) +
2989 sizeof (gtpu_exthdr_t));
2991 hdrlen += sizeof (gtpu_pdu_session_t);
2992 if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
2994 hdrlen += sizeof (gtpu_paging_policy_t);
2999 if (ls_param->type == SRV6_GTP4_DT4)
3001 vlib_buffer_advance (b0, (word) hdrlen);
3002 ip4 = vlib_buffer_get_current (b0);
3003 if ((ip4->ip_version_and_header_length & 0xf0) != 0x40)
3005 next0 = SRV6_T_M_GTP4_DT_NEXT_DROP;
3010 next0 = SRV6_T_M_GTP4_DT_NEXT_LOOKUP4;
3011 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
3012 ls_param->fib4_index;
3014 else if (ls_param->type == SRV6_GTP4_DT6)
3016 ip6 = (ip6_header_t *) ((u8 *) hdr0 + hdrlen);
3017 if ((clib_net_to_host_u32 (
3018 ip6->ip_version_traffic_class_and_flow_label) >>
3021 next0 = SRV6_T_M_GTP4_DT_NEXT_DROP;
3026 next0 = SRV6_T_M_GTP4_DT_NEXT_LOOKUP6;
3027 if (((ip6->dst_address.as_u8[0] == 0xff) &&
3028 (ip6->dst_address.as_u8[1] == 0x02)) ||
3029 ((ip6->dst_address.as_u8[0] == 0xfe) &&
3030 ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80)))
3032 next0 = SRV6_T_M_GTP4_DT_NEXT_LOOKUP4;
3033 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
3034 ls_param->local_fib_index;
3038 vlib_buffer_advance (b0, (word) hdrlen);
3039 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
3040 ls_param->fib6_index;
3043 else if (ls_param->type == SRV6_GTP4_DT46)
3045 ip6 = (ip6_header_t *) ((u8 *) hdr0 + hdrlen);
3046 if ((clib_net_to_host_u32 (
3047 ip6->ip_version_traffic_class_and_flow_label) >>
3050 next0 = SRV6_T_M_GTP4_DT_NEXT_LOOKUP6;
3051 if (((ip6->dst_address.as_u8[0] == 0xff) &&
3052 (ip6->dst_address.as_u8[1] == 0x02)) ||
3053 ((ip6->dst_address.as_u8[0] == 0xfe) &&
3054 ((ip6->dst_address.as_u8[1] & 0xc0) == 0x80)))
3056 next0 = SRV6_T_M_GTP4_DT_NEXT_LOOKUP4;
3057 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
3058 ls_param->local_fib_index;
3062 vlib_buffer_advance (b0, (word) hdrlen);
3063 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
3064 ls_param->fib6_index;
3067 else if ((clib_net_to_host_u32 (
3068 ip6->ip_version_traffic_class_and_flow_label) >>
3071 vlib_buffer_advance (b0, (word) hdrlen);
3072 next0 = SRV6_T_M_GTP4_DT_NEXT_LOOKUP4;
3073 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
3074 ls_param->fib4_index;
3078 next0 = SRV6_T_M_GTP4_DT_NEXT_DROP;
3085 next0 = SRV6_T_M_GTP4_DT_NEXT_DROP;
3092 if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
3093 PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
3095 srv6_end_rewrite_trace_t *tr =
3096 vlib_add_trace (vm, node, b0, sizeof (*tr));
3097 clib_memcpy (tr->src.as_u8, src.as_u8,
3098 sizeof (ip6_address_t));
3099 clib_memcpy (tr->dst.as_u8, dst.as_u8,
3100 sizeof (ip6_address_t));
3106 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
3107 n_left_to_next, bi0, next0);
3110 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
3113 vlib_node_increment_counter (vm, sm->t_m_gtp4_dt_node_index,
3114 SRV6_T_ERROR_M_GTP4_DT_BAD_PACKETS, bad_n);
3116 vlib_node_increment_counter (vm, sm->t_m_gtp4_dt_node_index,
3117 SRV6_T_ERROR_M_GTP4_DT_PACKETS, good_n);
3119 return frame->n_vectors;
3122 VLIB_REGISTER_NODE (srv6_end_m_gtp6_e) =
3124 .name = "srv6-end-m-gtp6-e",.vector_size = sizeof (u32),.format_trace =
3125 format_srv6_end_rewrite_trace6,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
3126 ARRAY_LEN (srv6_end_error_v6_e_strings),.error_strings =
3127 srv6_end_error_v6_e_strings,.n_next_nodes =
3128 SRV6_END_M_GTP6_E_N_NEXT,.next_nodes =
3130 [SRV6_END_M_GTP6_E_NEXT_DROP] = "error-drop",
3131 [SRV6_END_M_GTP6_E_NEXT_LOOKUP] = "ip6-lookup",}
3134 VLIB_REGISTER_NODE (srv6_end_m_gtp6_d) =
3136 .name = "srv6-end-m-gtp6-d",.vector_size = sizeof (u32),.format_trace =
3137 format_srv6_end_rewrite_trace6,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
3138 ARRAY_LEN (srv6_end_error_v6_d_strings),.error_strings =
3139 srv6_end_error_v6_d_strings,.n_next_nodes =
3140 SRV6_END_M_GTP6_D_N_NEXT,.next_nodes =
3142 [SRV6_END_M_GTP6_D_NEXT_DROP] = "error-drop",
3143 [SRV6_END_M_GTP6_D_NEXT_LOOKUP4] = "ip4-lookup",
3144 [SRV6_END_M_GTP6_D_NEXT_LOOKUP6] = "ip6-lookup",}
3147 VLIB_REGISTER_NODE (srv6_end_m_gtp6_d_di) =
3149 .name = "srv6-end-m-gtp6-d-di",.vector_size = sizeof (u32),.format_trace =
3150 format_srv6_end_rewrite_trace6,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
3151 ARRAY_LEN (srv6_end_error_v6_d_di_strings),.error_strings =
3152 srv6_end_error_v6_d_di_strings,.n_next_nodes =
3153 SRV6_END_M_GTP6_D_DI_N_NEXT,.next_nodes =
3155 [SRV6_END_M_GTP6_D_DI_NEXT_DROP] = "error-drop",
3156 [SRV6_END_M_GTP6_D_DI_NEXT_LOOKUP] = "ip6-lookup",}
3159 VLIB_REGISTER_NODE (srv6_end_m_gtp6_dt) =
3161 .name = "srv6-end-m-gtp6-dt",.vector_size = sizeof (u32),.format_trace =
3162 format_srv6_end_rewrite_trace6,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
3163 ARRAY_LEN (srv6_end_error_v6_dt_strings),.error_strings =
3164 srv6_end_error_v6_dt_strings,.n_next_nodes =
3165 SRV6_END_M_GTP6_DT_N_NEXT,.next_nodes =
3167 [SRV6_END_M_GTP6_DT_NEXT_DROP] = "error-drop",
3168 [SRV6_END_M_GTP6_DT_NEXT_LOOKUP4] = "ip4-lookup",
3169 [SRV6_END_M_GTP6_DT_NEXT_LOOKUP6] = "ip6-lookup",}
3172 VLIB_REGISTER_NODE (srv6_t_m_gtp4_dt) =
3174 .name = "srv6-t-m-gtp4-dt",.vector_size = sizeof (u32),.format_trace =
3175 format_srv6_end_rewrite_trace6,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
3176 ARRAY_LEN (srv6_t_error_v4_dt_strings),.error_strings =
3177 srv6_t_error_v4_dt_strings,.n_next_nodes =
3178 SRV6_T_M_GTP4_DT_N_NEXT,.next_nodes =
3180 [SRV6_T_M_GTP4_DT_NEXT_DROP] = "error-drop",
3181 [SRV6_T_M_GTP4_DT_NEXT_LOOKUP4] = "ip4-lookup",
3182 [SRV6_T_M_GTP4_DT_NEXT_LOOKUP6] = "ip6-lookup",}
3186 * fd.io coding-style-patch-verification: ON
3189 * eval: (c-set-style "gnu")