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 "SRv6-END-rewrite: src %U dst %U\n\tTEID: 0x%x\n\tsr_prefix: %U/%d",
107 format_ip6_address, &t->src, format_ip6_address, &t->dst,
108 clib_net_to_host_u32 (t->teid), format_ip6_address,
109 &t->sr_prefix, t->sr_prefixlen);
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")
134 #define _(sym,str) SRV6_END_ERROR_##sym,
135 foreach_srv6_end_v4_error
138 } srv6_end_error_v4_t;
142 #define _(sym,str) SRV6_T_ERROR_##sym,
143 foreach_srv6_t_v4_d_error
146 } srv6_t_error_v4_d_t;
150 #define _(sym,str) SRV6_END_ERROR_##sym,
151 foreach_srv6_end_v6_e_error
153 SRV6_END_N_V6_E_ERROR,
154 } srv6_end_error_v6_e_t;
158 #define _(sym,str) SRV6_END_ERROR_##sym,
159 foreach_srv6_end_v6_d_error
161 SRV6_END_N_V6_D_ERROR,
162 } srv6_end_error_v6_d_t;
166 #define _(sym,str) SRV6_END_ERROR_##sym,
167 foreach_srv6_end_v6_d_di_error
169 SRV6_END_N_V6_D_DI_ERROR,
170 } srv6_end_error_v6_d_di_t;
172 static char *srv6_end_error_v4_strings[] = {
173 #define _(sym,string) string,
174 foreach_srv6_end_v4_error
178 static char *srv6_t_error_v4_d_strings[] = {
179 #define _(sym,string) string,
180 foreach_srv6_t_v4_d_error
184 static char *srv6_end_error_v6_e_strings[] = {
185 #define _(sym,string) string,
186 foreach_srv6_end_v6_e_error
190 static char *srv6_end_error_v6_d_strings[] = {
191 #define _(sym,string) string,
192 foreach_srv6_end_v6_d_error
196 static char *srv6_end_error_v6_d_di_strings[] = {
197 #define _(sym,string) string,
198 foreach_srv6_end_v6_d_di_error
204 SRV6_END_M_GTP4_E_NEXT_DROP,
205 SRV6_END_M_GTP4_E_NEXT_LOOKUP,
206 SRV6_END_M_GTP4_E_N_NEXT,
207 } srv6_end_m_gtp4_e_next_t;
211 SRV6_T_M_GTP4_D_NEXT_DROP,
212 SRV6_T_M_GTP4_D_NEXT_LOOKUP,
213 SRV6_T_M_GTP4_D_N_NEXT,
214 } srv6_T_m_gtp4_d_next_t;
218 SRV6_END_M_GTP6_E_NEXT_DROP,
219 SRV6_END_M_GTP6_E_NEXT_LOOKUP,
220 SRV6_END_M_GTP6_E_N_NEXT,
221 } srv6_end_m_gtp6_e_next_t;
225 SRV6_END_M_GTP6_D_NEXT_DROP,
226 SRV6_END_M_GTP6_D_NEXT_LOOKUP,
227 SRV6_END_M_GTP6_D_N_NEXT,
228 } srv6_end_m_gtp6_d_next_t;
232 SRV6_END_M_GTP6_D_DI_NEXT_DROP,
233 SRV6_END_M_GTP6_D_DI_NEXT_LOOKUP,
234 SRV6_END_M_GTP6_D_DI_N_NEXT,
235 } srv6_end_m_gtp6_d_di_next_t;
238 hash_uword_to_u16 (uword * key)
243 return val[0] ^ val[1] ^ val[2] ^ val[3];
245 return val[0] ^ val[1];
250 gtpu_type_get (u16 tag)
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)
260 return GTPU_TYPE_ERROR_INDICATION;
261 else if (val & SRH_TAG_END_MARKER)
262 return GTPU_TYPE_END_MARKER;
264 return GTPU_TYPE_GTPU;
267 // Function for SRv6 GTP4.E function.
268 VLIB_NODE_FN (srv6_end_m_gtp4_e) (vlib_main_t * vm,
269 vlib_node_runtime_t * node,
270 vlib_frame_t * frame)
272 srv6_end_main_v4_t *sm = &srv6_end_main_v4;
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;
277 u32 good_n = 0, bad_n = 0;
279 from = vlib_frame_vector_args (frame);
280 n_left_from = frame->n_vectors;
281 next_index = node->cached_next_index;
283 while (n_left_from > 0)
287 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
289 while (n_left_from > 0 && n_left_to_next > 0)
293 ip6_sr_localsid_t *ls0;
294 srv6_end_gtp4_param_t *ls_param;
296 ip6srv_combo_header_t *ip6srv0;
297 ip6_address_t src0, dst0;
299 ip4_gtpu_header_t *hdr0 = NULL;
302 u32 next0 = SRV6_END_M_GTP4_E_NEXT_LOOKUP;
312 b0 = vlib_get_buffer (vm, bi0);
314 pool_elt_at_index (sm2->localsids,
315 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
317 ls_param = (srv6_end_gtp4_param_t *) ls0->plugin_mem;
319 ip6srv0 = vlib_buffer_get_current (b0);
320 src0 = ip6srv0->ip.src_address;
321 dst0 = ip6srv0->ip.dst_address;
323 len0 = vlib_buffer_length_in_chain (vm, b0);
325 if ((ip6srv0->ip.protocol == IPPROTO_IPV6_ROUTE
327 sizeof (ip6srv_combo_header_t) + ip6srv0->sr.length * 8)
328 || (len0 < sizeof (ip6_header_t)))
330 next0 = SRV6_END_M_GTP4_E_NEXT_DROP;
339 u8 *teid8p = (u8 *) & teid;
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
355 // jump over variable length data
356 // not sure about the length
357 if (ip6srv0->ip.protocol == IPPROTO_IPV6_ROUTE)
359 tag = ip6srv0->sr.tag;
361 vlib_buffer_advance (b0,
362 (word) sizeof (ip6srv_combo_header_t) +
363 ip6srv0->sr.length * 8);
367 vlib_buffer_advance (b0, (word) sizeof (ip6_header_t));
370 // get length of encapsulated IPv6 packet (the remaining part)
371 p = vlib_buffer_get_current (b0);
373 len0 = vlib_buffer_length_in_chain (vm, b0);
375 offset = ls0->localsid_len / 8;
376 shift = ls0->localsid_len % 8;
378 gtpu_type = gtpu_type_get (tag);
380 if (PREDICT_TRUE (shift == 0))
382 clib_memcpy_fast (&dst4.as_u8[0], &dst0.as_u8[offset], 4);
384 qfi = dst0.as_u8[offset + 4];
386 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
387 || gtpu_type == GTPU_TYPE_ECHO_REPLY
388 || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
390 clib_memcpy_fast (&seq, &dst0.as_u8[offset + 5], 2);
394 clib_memcpy_fast (teid8p, &dst0.as_u8[offset + 5], 4);
401 for (index = 0; index < 4; index++)
403 dst4.as_u8[index] = dst0.as_u8[offset + index] << shift;
405 dst0.as_u8[offset + index + 1] >> (8 - shift);
408 qfi |= dst0.as_u8[offset + 4] << shift;
409 qfi |= dst0.as_u8[offset + 5] >> (8 - shift);
411 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
412 || gtpu_type == GTPU_TYPE_ECHO_REPLY
413 || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
416 for (index = 0; index < 2; index++)
418 sp[index] = dst0.as_u8[offset + 5 + index] << shift;
420 dst0.as_u8[offset + 6 + index] >> (8 - shift);
425 for (index = 0; index < 4; index++)
427 *teid8p = dst0.as_u8[offset + 5 + index] << shift;
429 dst0.as_u8[offset + 6 + index] >> (8 - shift);
438 sizeof (gtpu_exthdr_t) + sizeof (gtpu_pdu_session_t);
440 else if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
441 || gtpu_type == GTPU_TYPE_ECHO_REPLY
442 || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
444 hdrlen = sizeof (gtpu_exthdr_t);
448 hdrlen += sizeof (ip4_gtpu_header_t);
450 // IPv4 GTP-U header creation.
451 vlib_buffer_advance (b0, -(word) hdrlen);
453 hdr0 = vlib_buffer_get_current (b0);
455 clib_memcpy_fast (hdr0, &sm->cache_hdr,
456 sizeof (ip4_gtpu_header_t));
458 hdr0->ip4.dst_address.as_u32 = dst4.as_u32;
460 hdr0->gtpu.teid = teid;
461 hdr0->gtpu.length = clib_host_to_net_u16 (len0);
463 hdr0->gtpu.type = gtpu_type;
468 gtpu_pdu_session_t *sess;
470 hdr0->gtpu.ver_flags |= GTPU_EXTHDR_FLAG;
472 hdr0->gtpu.ext->seq = 0;
474 hdr0->gtpu.ext->npdu_num = 0;
475 hdr0->gtpu.ext->nextexthdr = GTPU_EXTHDR_PDU_SESSION;
477 type = qfi & SRV6_PDU_SESSION_U_BIT_MASK;
480 ((qfi & SRV6_PDU_SESSION_QFI_MASK) >> 2) |
481 ((qfi & SRV6_PDU_SESSION_R_BIT_MASK) << 5);
484 (gtpu_pdu_session_t *) (((char *) hdr0) +
485 sizeof (ip4_gtpu_header_t) +
486 sizeof (gtpu_exthdr_t));
491 sess->nextexthdr = 0;
494 if (gtpu_type == GTPU_TYPE_ECHO_REPLY
495 || gtpu_type == GTPU_TYPE_ECHO_REQUEST
496 || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
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;
504 offset = ls_param->v4src_position / 8;
505 shift = ls_param->v4src_position % 8;
507 if (PREDICT_TRUE (shift == 0))
509 for (index = 0; index < 4; index++)
511 hdr0->ip4.src_address.as_u8[index] =
512 src0.as_u8[offset + index];
517 for (index = 0; index < 4; index++)
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);
526 key = hash_memory (p, len0, 0);
527 port = hash_uword_to_u16 (&key);
528 hdr0->udp.src_port = port;
530 hdr0->udp.length = clib_host_to_net_u16 (len0 +
531 sizeof (udp_header_t) +
535 hdr0->ip4.length = clib_host_to_net_u16 (len0 +
537 (ip4_gtpu_header_t));
539 hdr0->ip4.checksum = ip4_header_checksum (&hdr0->ip4);
543 if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
544 PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
546 srv6_end_rewrite_trace_t *tr =
547 vlib_add_trace (vm, node, b0, sizeof (*tr));
548 clib_memcpy (tr->src.as_u8, hdr0->ip4.src_address.as_u8,
549 sizeof (tr->src.as_u8));
550 clib_memcpy (tr->dst.as_u8, hdr0->ip4.dst_address.as_u8,
551 sizeof (tr->dst.as_u8));
552 tr->teid = hdr0->gtpu.teid;
556 vlib_increment_combined_counter
558 SRV6_END_M_GTP4_E_NEXT_DROP) ? &(sm2->sr_ls_invalid_counters) :
559 &(sm2->sr_ls_valid_counters)), thread_index,
560 ls0 - sm2->localsids, 1, vlib_buffer_length_in_chain (vm, b0));
562 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
563 n_left_to_next, bi0, next0);
566 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
569 vlib_node_increment_counter (vm, sm->end_m_gtp4_e_node_index,
570 SRV6_END_ERROR_M_GTP4_E_BAD_PACKETS, bad_n);
572 vlib_node_increment_counter (vm, sm->end_m_gtp4_e_node_index,
573 SRV6_END_ERROR_M_GTP4_E_PACKETS, good_n);
575 return frame->n_vectors;
578 // Function for SRv6 GTP4.D function.
579 VLIB_NODE_FN (srv6_t_m_gtp4_d) (vlib_main_t * vm,
580 vlib_node_runtime_t * node,
581 vlib_frame_t * frame)
583 srv6_t_main_v4_decap_t *sm = &srv6_t_main_v4_decap;
584 ip6_sr_main_t *sm2 = &sr_main;
585 u32 n_left_from, next_index, *from, *to_next;
587 u32 good_n = 0, bad_n = 0;
589 from = vlib_frame_vector_args (frame);
590 n_left_from = frame->n_vectors;
591 next_index = node->cached_next_index;
593 while (n_left_from > 0)
597 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
599 while (n_left_from > 0 && n_left_to_next > 0)
604 srv6_end_gtp4_param_t *ls_param;
609 u32 next0 = SRV6_T_M_GTP4_D_NEXT_LOOKUP;
619 b0 = vlib_get_buffer (vm, bi0);
622 pool_elt_at_index (sm2->sid_lists,
623 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
625 ls_param = (srv6_end_gtp4_param_t *) sl0->plugin_mem;
627 len0 = vlib_buffer_length_in_chain (vm, b0);
629 ip4 = vlib_buffer_get_current (b0);
631 if (ip4->protocol != IP_PROTOCOL_UDP
632 || len0 < sizeof (ip4_gtpu_header_t))
634 next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
641 ip6_sr_policy_t *sr_policy = NULL;
642 ip6_sr_sl_t *sl = NULL;
646 ip4_gtpu_header_t *hdr;
647 ip4_address_t src, dst;
649 ip6_header_t *encap = NULL;
659 u32 offset, shift, index;
660 ip6srv_combo_header_t *ip6srv;
661 gtpu_pdu_session_t *sess = NULL;
664 hdr = (ip4_gtpu_header_t *) ip4;
666 hdr_len = sizeof (ip4_gtpu_header_t);
668 teid = hdr->gtpu.teid;
669 teidp = (u8 *) & teid;
671 gtpu_type = hdr->gtpu.type;
673 if (hdr->gtpu.ver_flags & (GTPU_EXTHDR_FLAG | GTPU_SEQ_FLAG))
676 hdr_len += sizeof (gtpu_exthdr_t);
678 seq = hdr->gtpu.ext->seq;
681 if (hdr->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
683 // PDU Session Container.
685 (gtpu_pdu_session_t *) (((char *) hdr) + hdr_len);
686 qfi = sess->u.val & ~GTPU_PDU_SESSION_P_BIT_MASK;
689 hdr_len += sizeof (gtpu_pdu_session_t);
691 if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
693 hdr_len += sizeof (gtpu_paging_policy_t);
698 src = hdr->ip4.src_address;
701 dst = hdr->ip4.dst_address;
704 seg = ls_param->sr_prefix;
706 offset = ls_param->sr_prefixlen / 8;
707 shift = ls_param->sr_prefixlen % 8;
709 if (PREDICT_TRUE (shift == 0))
711 clib_memcpy_fast (&seg.as_u8[offset], dstp, 4);
716 ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
717 ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
721 qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
724 seg.as_u8[offset + 4] = qfi;
727 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
728 || gtpu_type == GTPU_TYPE_ECHO_REPLY
729 || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
731 clib_memcpy_fast (&seg.as_u8[offset + 5], seqp, 2);
735 clib_memcpy_fast (&seg.as_u8[offset + 5], teidp, 4);
740 for (index = 0; index < 4; index++)
742 seg.as_u8[offset + index] |= dstp[index] >> shift;
743 seg.as_u8[offset + index + 1] |=
744 dstp[index] << (8 - shift);
750 ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
751 ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
755 qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
758 seg.as_u8[offset + 4] |= qfi >> shift;
759 seg.as_u8[offset + 5] |= qfi << (8 - shift);
762 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
763 || gtpu_type == GTPU_TYPE_ECHO_REPLY
764 || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
766 for (index = 0; index < 2; index++)
768 seg.as_u8[offset + 5 + index] |=
769 seqp[index] >> shift;
770 seg.as_u8[offset + 6 + index] |=
771 seqp[index] << (8 - shift);
776 for (index = 0; index < 4; index++)
778 seg.as_u8[offset + index + 5] |=
779 teidp[index] >> shift;
780 seg.as_u8[offset + index + 6] |=
781 teidp[index] << (8 - shift);
786 src6 = ls_param->v6src_prefix;
788 offset = ls_param->v6src_prefixlen / 8;
789 shift = ls_param->v6src_prefixlen % 8;
791 if (PREDICT_TRUE (shift == 0))
793 clib_memcpy_fast (&src6.as_u8[offset], srcp, 4);
797 for (index = 0; index < 4; index++)
799 src6.as_u8[offset + index] |= srcp[offset] >> shift;
800 src6.as_u8[offset + index + 1] |=
801 srcp[offset] << (8 - shift);
805 vlib_buffer_advance (b0, (word) hdr_len);
808 if (PREDICT_TRUE (gtpu_type == GTPU_TYPE_GTPU))
810 encap = vlib_buffer_get_current (b0);
813 len0 = vlib_buffer_length_in_chain (vm, b0);
816 mhash_get (&sm2->sr_policies_index_hash,
817 &ls_param->sr_prefix);
820 sr_policy = pool_elt_at_index (sm2->sr_policies, p[0]);
825 vec_foreach (sl_index, sr_policy->segments_lists)
827 sl = pool_elt_at_index (sm2->sid_lists, *sl_index);
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);
841 hdr_len = sizeof (ip6_header_t);
843 if (PREDICT_FALSE (gtpu_type != GTPU_TYPE_GTPU))
845 hdr_len += sizeof (ip6_sr_header_t);
846 hdr_len += sizeof (ip6_address_t);
850 vlib_buffer_advance (b0, -(word) hdr_len);
851 ip6srv = vlib_buffer_get_current (b0);
855 clib_memcpy_fast (ip6srv, sl->rewrite,
856 vec_len (sl->rewrite));
858 if (vec_len (sl->segments) > 1)
861 clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
863 ip6srv->sr.segments_left += 1;
864 ip6srv->sr.last_entry += 1;
866 ip6srv->sr.length += sizeof (ip6_address_t) / 8;
867 ip6srv->sr.segments[0] = seg;
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));
878 ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
880 ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
882 ip6srv->sr.segments_left = 1;
883 ip6srv->sr.last_entry = 0;
886 ((sizeof (ip6_sr_header_t) +
887 sizeof (ip6_address_t)) / 8) - 1;
888 ip6srv->sr.flags = 0;
891 clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
893 ip6srv->sr.segments[0] = seg;
894 if (vec_len (sl->segments))
896 ip6srv->sr.segments[1] = sl->segments[0];
897 ip6srv->sr.length += sizeof (ip6_address_t) / 8;
898 ip6srv->sr.last_entry++;
902 if (PREDICT_TRUE (encap != NULL))
904 if (ls_param->nhtype == SRV6_NHTYPE_NONE)
906 if ((clib_net_to_host_u32
907 (encap->ip_version_traffic_class_and_flow_label)
909 ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
911 ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
913 else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
915 ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
916 if ((clib_net_to_host_u32
917 (encap->ip_version_traffic_class_and_flow_label)
921 next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
926 else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
928 ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
929 if ((clib_net_to_host_u32
930 (encap->ip_version_traffic_class_and_flow_label)
934 next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
939 else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
941 ip6srv->sr.protocol = IP_PROTOCOL_NONE;
946 ip6srv->sr.protocol = IP_PROTOCOL_NONE;
951 clib_memcpy_fast (ip6srv, &sm->cache_hdr,
952 sizeof (ip6_header_t));
954 ip6srv->ip.dst_address = seg;
956 if (PREDICT_FALSE (gtpu_type != GTPU_TYPE_GTPU))
958 ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
960 ip6srv->sr.protocol = IP_PROTOCOL_NONE;
963 clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
965 ip6srv->sr.segments_left = 0;
966 ip6srv->sr.last_entry = 0;
968 ip6srv->sr.length = sizeof (ip6_address_t) / 8;
969 ip6srv->sr.segments[0] = seg;
973 if (ls_param->nhtype == SRV6_NHTYPE_NONE)
975 if ((clib_net_to_host_u32
976 (encap->ip_version_traffic_class_and_flow_label)
978 ip6srv->ip.protocol = IP_PROTOCOL_IPV6;
980 ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
982 else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
984 ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
985 if ((clib_net_to_host_u32
986 (encap->ip_version_traffic_class_and_flow_label)
990 next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
995 else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
997 ip6srv->ip.protocol = IP_PROTOCOL_IPV6;
998 if ((clib_net_to_host_u32
999 (encap->ip_version_traffic_class_and_flow_label)
1002 // Bad encap packet.
1003 next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
1008 else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
1010 ip6srv->ip.protocol = IP_PROTOCOL_NONE;
1015 ip6srv->ip.src_address = src6;
1017 ip6srv->ip.payload_length =
1018 clib_host_to_net_u16 (len0 + hdr_len - sizeof (ip6_header_t));
1022 if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
1023 PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1025 srv6_end_rewrite_trace_t *tr =
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));
1035 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1036 n_left_to_next, bi0, next0);
1039 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1042 vlib_node_increment_counter (vm, sm->t_m_gtp4_d_node_index,
1043 SRV6_T_ERROR_M_GTP4_D_BAD_PACKETS, bad_n);
1045 vlib_node_increment_counter (vm, sm->t_m_gtp4_d_node_index,
1046 SRV6_T_ERROR_M_GTP4_D_PACKETS, good_n);
1048 return frame->n_vectors;
1051 VLIB_REGISTER_NODE (srv6_end_m_gtp4_e) =
1053 .name = "srv6-end-m-gtp4-e",.vector_size = sizeof (u32),.format_trace =
1054 format_srv6_end_rewrite_trace,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
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 =
1059 [SRV6_END_M_GTP4_E_NEXT_DROP] = "error-drop",
1060 [SRV6_END_M_GTP4_E_NEXT_LOOKUP] = "ip4-lookup",}
1063 VLIB_REGISTER_NODE (srv6_t_m_gtp4_d) =
1065 .name = "srv6-t-m-gtp4-d",.vector_size = sizeof (u32),.format_trace =
1066 format_srv6_end_rewrite_trace,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
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 =
1071 [SRV6_T_M_GTP4_D_NEXT_DROP] = "error-drop",
1072 [SRV6_T_M_GTP4_D_NEXT_LOOKUP] = "ip6-lookup",}
1075 // Function for SRv6 GTP6.E function
1076 VLIB_NODE_FN (srv6_end_m_gtp6_e) (vlib_main_t * vm,
1077 vlib_node_runtime_t * node,
1078 vlib_frame_t * frame)
1080 srv6_end_main_v6_t *sm = &srv6_end_main_v6;
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;
1085 u32 good_n = 0, bad_n = 0;
1087 from = vlib_frame_vector_args (frame);
1088 n_left_from = frame->n_vectors;
1089 next_index = node->cached_next_index;
1091 while (n_left_from > 0)
1095 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1097 while (n_left_from > 0 && n_left_to_next > 0)
1101 ip6_sr_localsid_t *ls0;
1103 ip6srv_combo_header_t *ip6srv0;
1104 ip6_address_t dst0, src0, seg0;
1106 ip6_gtpu_header_t *hdr0 = NULL;
1113 u32 next0 = SRV6_END_M_GTP6_E_NEXT_LOOKUP;
1121 n_left_to_next -= 1;
1123 b0 = vlib_get_buffer (vm, bi0);
1125 pool_elt_at_index (sm2->localsids,
1126 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
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];
1133 tag = ip6srv0->sr.tag;
1135 len0 = vlib_buffer_length_in_chain (vm, b0);
1137 if ((ip6srv0->ip.protocol != IPPROTO_IPV6_ROUTE)
1139 sizeof (ip6srv_combo_header_t) + 8 * ip6srv0->sr.length))
1141 next0 = SRV6_END_M_GTP6_E_NEXT_DROP;
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
1152 // jump over variable length data
1153 // not sure about the length
1154 vlib_buffer_advance (b0, (word) sizeof (ip6srv_combo_header_t) +
1155 ip6srv0->sr.length * 8);
1157 // get length of encapsulated IPv6 packet (the remaining part)
1158 p = vlib_buffer_get_current (b0);
1160 len0 = vlib_buffer_length_in_chain (vm, b0);
1163 u8 *teid8p = (u8 *) & teid;
1171 index = ls0->localsid_len;
1176 gtpu_type = gtpu_type_get (tag);
1178 if (PREDICT_TRUE (shift == 0))
1180 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1181 || gtpu_type == GTPU_TYPE_ECHO_REPLY
1182 || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1184 clib_memcpy_fast (&seq, &dst0.as_u8[offset], 2);
1188 clib_memcpy_fast (teid8p, &dst0.as_u8[offset], 4);
1191 qfi = dst0.as_u8[offset + 4];
1197 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1198 || gtpu_type == GTPU_TYPE_ECHO_REPLY
1199 || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1202 for (index = 0; index < 2; index++)
1204 sp[index] = dst0.as_u8[offset + index] << shift;
1206 dst0.as_u8[offset + index + 1] >> (8 - shift);
1211 for (index = 0; index < 4; index++)
1213 *teid8p = dst0.as_u8[offset + index] << shift;
1215 dst0.as_u8[offset + index + 1] >> (8 - shift);
1220 qfi |= dst0.as_u8[offset + 4] << shift;
1221 qfi |= dst0.as_u8[offset + 5] >> (8 - shift);
1227 sizeof (gtpu_exthdr_t) + sizeof (gtpu_pdu_session_t);
1229 else if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1230 || gtpu_type == GTPU_TYPE_ECHO_REPLY
1231 || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1233 hdrlen = sizeof (gtpu_exthdr_t);
1237 hdrlen += sizeof (ip6_gtpu_header_t);
1239 vlib_buffer_advance (b0, -(word) hdrlen);
1241 hdr0 = vlib_buffer_get_current (b0);
1243 clib_memcpy_fast (hdr0, &sm->cache_hdr,
1244 sizeof (ip6_gtpu_header_t));
1246 hdr0->gtpu.teid = teid;
1247 hdr0->gtpu.length = clib_host_to_net_u16 (len0);
1249 hdr0->gtpu.type = gtpu_type;
1254 gtpu_pdu_session_t *sess;
1256 hdr0->gtpu.ver_flags |= GTPU_EXTHDR_FLAG;
1258 hdr0->gtpu.ext->seq = 0;
1259 hdr0->gtpu.ext->npdu_num = 0;
1260 hdr0->gtpu.ext->nextexthdr = GTPU_EXTHDR_PDU_SESSION;
1262 type = qfi & SRV6_PDU_SESSION_U_BIT_MASK;
1265 ((qfi & SRV6_PDU_SESSION_QFI_MASK) >> 2) |
1266 ((qfi & SRV6_PDU_SESSION_R_BIT_MASK) << 5);
1269 (gtpu_pdu_session_t *) (((char *) hdr0) +
1270 sizeof (ip6_gtpu_header_t) +
1271 sizeof (gtpu_exthdr_t));
1272 sess->exthdrlen = 1;
1276 sess->nextexthdr = 0;
1279 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1280 || gtpu_type == GTPU_TYPE_ECHO_REPLY
1281 || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
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;
1289 hdr0->udp.length = clib_host_to_net_u16 (len0 +
1290 sizeof (udp_header_t) +
1294 clib_memcpy_fast (hdr0->ip6.src_address.as_u8, src0.as_u8,
1295 sizeof (ip6_address_t));
1296 clib_memcpy_fast (hdr0->ip6.dst_address.as_u8, &seg0.as_u8,
1297 sizeof (ip6_address_t));
1299 hdr0->ip6.payload_length = clib_host_to_net_u16 (len0 +
1307 key = hash_memory (p, len0, 0);
1308 port = hash_uword_to_u16 (&key);
1309 hdr0->udp.src_port = port;
1313 if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
1314 PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1316 srv6_end_rewrite_trace_t *tr =
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;
1326 vlib_increment_combined_counter
1328 SRV6_END_M_GTP6_E_NEXT_DROP) ? &(sm2->sr_ls_invalid_counters) :
1329 &(sm2->sr_ls_valid_counters)), thread_index,
1330 ls0 - sm2->localsids, 1, vlib_buffer_length_in_chain (vm, b0));
1332 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1333 n_left_to_next, bi0, next0);
1336 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1339 vlib_node_increment_counter (vm, sm->end_m_gtp6_e_node_index,
1340 SRV6_END_ERROR_M_GTP6_E_BAD_PACKETS, bad_n);
1342 vlib_node_increment_counter (vm, sm->end_m_gtp6_e_node_index,
1343 SRV6_END_ERROR_M_GTP6_E_PACKETS, good_n);
1345 return frame->n_vectors;
1348 // Function for SRv6 GTP6.D function
1349 VLIB_NODE_FN (srv6_end_m_gtp6_d) (vlib_main_t * vm,
1350 vlib_node_runtime_t * node,
1351 vlib_frame_t * frame)
1353 srv6_end_main_v6_decap_t *sm = &srv6_end_main_v6_decap;
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;
1358 u32 good_n = 0, bad_n = 0;
1360 from = vlib_frame_vector_args (frame);
1361 n_left_from = frame->n_vectors;
1362 next_index = node->cached_next_index;
1364 while (n_left_from > 0)
1368 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1370 while (n_left_from > 0 && n_left_to_next > 0)
1374 ip6_sr_localsid_t *ls0;
1375 srv6_end_gtp6_param_t *ls_param;
1377 ip6_gtpu_header_t *hdr0 = NULL;
1380 ip6_address_t seg0, src0;
1390 ip6_header_t *encap = NULL;
1391 gtpu_pdu_session_t *sess = NULL;
1393 u32 next0 = SRV6_END_M_GTP6_D_NEXT_LOOKUP;
1401 n_left_to_next -= 1;
1403 b0 = vlib_get_buffer (vm, bi0);
1405 pool_elt_at_index (sm2->localsids,
1406 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1408 ls_param = (srv6_end_gtp6_param_t *) ls0->plugin_mem;
1410 hdr0 = vlib_buffer_get_current (b0);
1412 hdrlen = sizeof (ip6_gtpu_header_t);
1414 len0 = vlib_buffer_length_in_chain (vm, b0);
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)))
1421 next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
1427 seg0 = ls_param->sr_prefix;
1428 src0 = hdr0->ip6.src_address;
1430 gtpu_type = hdr0->gtpu.type;
1432 teid = hdr0->gtpu.teid;
1433 teidp = (u8 *) & teid;
1435 if (hdr0->gtpu.ver_flags & (GTPU_EXTHDR_FLAG | GTPU_SEQ_FLAG))
1437 // Extention header.
1438 hdrlen += sizeof (gtpu_exthdr_t);
1440 seq = hdr0->gtpu.ext->seq;
1441 seqp = (u8 *) & seq;
1443 if (hdr0->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
1445 // PDU Session Container.
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;
1453 hdrlen += sizeof (gtpu_pdu_session_t);
1455 if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
1457 hdrlen += sizeof (gtpu_paging_policy_t);
1462 offset = ls_param->sr_prefixlen / 8;
1463 shift = ls_param->sr_prefixlen % 8;
1466 if (PREDICT_TRUE (shift == 0))
1468 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1469 || gtpu_type == GTPU_TYPE_ECHO_REPLY
1470 || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1473 clib_memcpy_fast (&seg0.as_u8[offset], seqp, 2);
1477 clib_memcpy_fast (&seg0.as_u8[offset], teidp, 4);
1483 ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
1484 ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
1488 qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
1491 seg0.as_u8[offset + 4] = qfi;
1498 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1499 || gtpu_type == GTPU_TYPE_ECHO_REPLY
1500 || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1504 for (idx = 0; idx < 2; idx++)
1506 seg0.as_u8[offset + idx] |= seqp[idx] >> shift;
1507 seg0.as_u8[offset + idx + 1] |=
1508 seqp[idx] << (8 - shift);
1514 for (idx = 0; idx < 4; idx++)
1516 seg0.as_u8[offset + idx] |= teidp[idx] >> shift;
1517 seg0.as_u8[offset + idx + 1] |=
1518 teidp[idx] << (8 - shift);
1525 ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
1526 ((qfi & ~GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
1530 qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
1533 seg0.as_u8[offset + 4] |= qfi >> shift;
1534 seg0.as_u8[offset + 5] |= qfi << (8 - shift);
1538 // jump over variable length data
1539 vlib_buffer_advance (b0, (word) hdrlen);
1541 // get length of encapsulated IPv6 packet (the remaining part)
1542 len0 = vlib_buffer_length_in_chain (vm, b0);
1544 if (PREDICT_TRUE (gtpu_type == GTPU_TYPE_GTPU))
1546 encap = vlib_buffer_get_current (b0);
1550 ip6srv_combo_header_t *ip6srv;
1551 ip6_sr_policy_t *sr_policy = NULL;
1552 ip6_sr_sl_t *sl = NULL;
1557 mhash_get (&sm2->sr_policies_index_hash,
1558 &ls_param->sr_prefix);
1561 sr_policy = pool_elt_at_index (sm2->sr_policies, p[0]);
1566 vec_foreach (sl_index, sr_policy->segments_lists)
1568 sl = pool_elt_at_index (sm2->sid_lists, *sl_index);
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);
1582 hdr_len = sizeof (ip6_header_t);
1583 if (PREDICT_FALSE (gtpu_type) != GTPU_TYPE_GTPU)
1585 hdr_len += sizeof (ip6_sr_header_t);
1586 hdr_len += sizeof (ip6_address_t);
1590 // jump back to data[0] or pre_data if required
1591 vlib_buffer_advance (b0, -(word) hdr_len);
1593 ip6srv = vlib_buffer_get_current (b0);
1597 clib_memcpy_fast (ip6srv, sl->rewrite,
1598 vec_len (sl->rewrite));
1600 if (vec_len (sl->segments) > 1)
1602 ip6srv->ip.src_address = src0;
1605 clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1607 ip6srv->sr.segments_left += 1;
1608 ip6srv->sr.last_entry += 1;
1610 ip6srv->sr.length += sizeof (ip6_address_t) / 8;
1611 ip6srv->sr.segments[0] = seg0;
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));
1622 ip6srv->ip.src_address = src0;
1623 ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
1625 ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
1626 ip6srv->sr.segments_left = 1;
1627 ip6srv->sr.last_entry = 0;
1629 ((sizeof (ip6_sr_header_t) +
1630 sizeof (ip6_address_t)) / 8) - 1;
1631 ip6srv->sr.flags = 0;
1634 clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1636 ip6srv->sr.segments[0] = seg0;
1638 if (vec_len (sl->segments))
1640 ip6srv->sr.segments[1] = sl->segments[0];
1641 ip6srv->sr.last_entry++;
1642 ip6srv->sr.length += sizeof (ip6_address_t) / 8;
1646 if (PREDICT_TRUE (encap != NULL))
1648 if (ls_param->nhtype == SRV6_NHTYPE_NONE)
1650 if ((clib_net_to_host_u32
1651 (encap->ip_version_traffic_class_and_flow_label)
1653 ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
1655 ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
1657 else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
1659 ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
1660 if ((clib_net_to_host_u32
1661 (encap->ip_version_traffic_class_and_flow_label)
1664 // Bad encap packet.
1665 next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
1670 else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
1672 ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
1673 if ((clib_net_to_host_u32
1674 (encap->ip_version_traffic_class_and_flow_label)
1677 // Bad encap packet.
1678 next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
1683 else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
1685 ip6srv->sr.protocol = IP_PROTOCOL_NONE;
1690 ip6srv->sr.protocol = IP_PROTOCOL_NONE;
1695 clib_memcpy_fast (ip6srv, &sm->cache_hdr,
1696 sizeof (ip6_header_t));
1698 ip6srv->ip.src_address = src0;
1699 ip6srv->ip.dst_address = seg0;
1701 if (PREDICT_FALSE (gtpu_type) != GTPU_TYPE_GTPU)
1703 ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
1705 ip6srv->sr.protocol = IP_PROTOCOL_NONE;
1708 clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1710 ip6srv->sr.segments_left = 0;
1711 ip6srv->sr.last_entry = 0;
1713 ip6srv->sr.length = sizeof (ip6_address_t) / 8;
1714 ip6srv->sr.segments[0] = seg0;
1718 if (ls_param->nhtype == SRV6_NHTYPE_NONE)
1720 if ((clib_net_to_host_u32
1721 (encap->ip_version_traffic_class_and_flow_label)
1723 ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
1725 else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
1727 ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
1728 if ((clib_net_to_host_u32
1729 (encap->ip_version_traffic_class_and_flow_label)
1732 // Bad encap packet.
1733 next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
1738 else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
1740 ip6srv->ip.protocol = IP_PROTOCOL_IPV6;
1741 if ((clib_net_to_host_u32
1742 (encap->ip_version_traffic_class_and_flow_label)
1745 // Bad encap packet.
1746 next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
1751 else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
1753 ip6srv->ip.protocol = IP_PROTOCOL_NONE;
1758 ip6srv->ip.payload_length =
1759 clib_host_to_net_u16 (len0 + hdr_len - sizeof (ip6_header_t));
1763 if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
1764 PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1766 srv6_end_rewrite_trace_t *tr =
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));
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;
1780 vlib_increment_combined_counter
1782 SRV6_END_M_GTP6_D_NEXT_DROP) ? &(sm2->sr_ls_invalid_counters) :
1783 &(sm2->sr_ls_valid_counters)), thread_index,
1784 ls0 - sm2->localsids, 1, vlib_buffer_length_in_chain (vm, b0));
1786 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1787 n_left_to_next, bi0, next0);
1790 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1793 vlib_node_increment_counter (vm, sm->end_m_gtp6_d_node_index,
1794 SRV6_END_ERROR_M_GTP6_D_BAD_PACKETS, bad_n);
1796 vlib_node_increment_counter (vm, sm->end_m_gtp6_d_node_index,
1797 SRV6_END_ERROR_M_GTP6_D_PACKETS, good_n);
1799 return frame->n_vectors;
1802 // Function for SRv6 GTP6.D.DI function
1803 VLIB_NODE_FN (srv6_end_m_gtp6_d_di) (vlib_main_t * vm,
1804 vlib_node_runtime_t * node,
1805 vlib_frame_t * frame)
1807 srv6_end_main_v6_decap_di_t *sm = &srv6_end_main_v6_decap_di;
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;
1813 u32 good_n = 0, bad_n = 0;
1815 from = vlib_frame_vector_args (frame);
1816 n_left_from = frame->n_vectors;
1817 next_index = node->cached_next_index;
1819 while (n_left_from > 0)
1823 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1825 while (n_left_from > 0 && n_left_to_next > 0)
1829 ip6_sr_localsid_t *ls0;
1831 ip6_gtpu_header_t *hdr0 = NULL;
1846 ip6_header_t *encap = NULL;
1847 gtpu_pdu_session_t *sess;
1849 u32 next0 = SRV6_END_M_GTP6_D_DI_NEXT_LOOKUP;
1857 n_left_to_next -= 1;
1859 b0 = vlib_get_buffer (vm, bi0);
1861 pool_elt_at_index (sm2->localsids,
1862 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1864 ls_param = (srv6_end_gtp6_param_t *) ls0->plugin_mem;
1866 hdr0 = vlib_buffer_get_current (b0);
1868 hdrlen = sizeof (ip6_gtpu_header_t);
1870 len0 = vlib_buffer_length_in_chain (vm, b0);
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)))
1877 next0 = SRV6_END_M_GTP6_D_DI_NEXT_DROP;
1883 dst0 = hdr0->ip6.dst_address;
1884 src0 = hdr0->ip6.src_address;
1886 gtpu_type = hdr0->gtpu.type;
1888 seg0 = ls_param->sr_prefix;
1889 teid = hdr0->gtpu.teid;
1890 teidp = (u8 *) & teid;
1892 if (hdr0->gtpu.ver_flags & (GTPU_EXTHDR_FLAG | GTPU_SEQ_FLAG))
1894 // Extention header.
1895 hdrlen += sizeof (gtpu_exthdr_t);
1897 seq = hdr0->gtpu.ext->seq;
1898 seqp = (u8 *) & seq;
1900 if (hdr0->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
1902 // PDU Session Container.
1904 (gtpu_pdu_session_t *) (((char *) hdr0) + hdrlen);
1905 qfi = sess->u.val & ~GTPU_PDU_SESSION_P_BIT_MASK;
1908 hdrlen += sizeof (gtpu_pdu_session_t);
1910 if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
1912 hdrlen += sizeof (gtpu_paging_policy_t);
1917 offset = ls_param->sr_prefixlen / 8;
1918 shift = ls_param->sr_prefixlen % 8;
1921 if (PREDICT_TRUE (shift == 0))
1923 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1924 || gtpu_type == GTPU_TYPE_ECHO_REPLY
1925 || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1928 clib_memcpy_fast (&seg0.as_u8[offset], seqp, 2);
1932 clib_memcpy_fast (&seg0.as_u8[offset], teidp, 4);
1938 ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
1939 ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
1943 qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
1946 seg0.as_u8[offset + 4] = qfi;
1953 if (gtpu_type == GTPU_TYPE_ECHO_REQUEST
1954 || gtpu_type == GTPU_TYPE_ECHO_REPLY
1955 || gtpu_type == GTPU_TYPE_ERROR_INDICATION)
1959 for (idx = 0; idx < 2; idx++)
1961 seg0.as_u8[offset + idx] |= seqp[idx] >> shift;
1962 seg0.as_u8[offset + idx + 1] |=
1963 seqp[idx] << (8 - shift);
1969 for (idx = 0; idx < 4; idx++)
1971 seg0.as_u8[offset + idx] |= teidp[idx] >> shift;
1972 seg0.as_u8[offset + idx + 1] |=
1973 teidp[idx] << (8 - shift);
1980 ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
1981 ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
1985 qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
1988 seg0.as_u8[offset + 4] |= qfi >> shift;
1989 seg0.as_u8[offset + 5] |= qfi << (8 - shift);
1993 // jump over variable length data
1994 vlib_buffer_advance (b0, (word) hdrlen);
1996 // get length of encapsulated IPv6 packet (the remaining part)
1997 len0 = vlib_buffer_length_in_chain (vm, b0);
1999 if (PREDICT_TRUE (gtpu_type == GTPU_TYPE_GTPU))
2001 encap = vlib_buffer_get_current (b0);
2005 ip6srv_combo_header_t *ip6srv;
2006 ip6_sr_policy_t *sr_policy = NULL;
2007 ip6_sr_sl_t *sl = NULL;
2012 mhash_get (&sm2->sr_policies_index_hash,
2013 &ls_param->sr_prefix);
2016 sr_policy = pool_elt_at_index (sm2->sr_policies, p[0]);
2021 vec_foreach (sl_index, sr_policy->segments_lists)
2023 sl = pool_elt_at_index (sm2->sid_lists, *sl_index);
2029 hdr_len = sizeof (ip6srv_combo_header_t);
2032 hdr_len += vec_len (sl->segments) * sizeof (ip6_address_t);
2034 hdr_len += sizeof (ip6_address_t) * 2;
2036 // jump back to data[0] or pre_data if required
2037 vlib_buffer_advance (b0, -(word) hdr_len);
2039 ip6srv = vlib_buffer_get_current (b0);
2043 clib_memcpy_fast (ip6srv, sl->rewrite,
2044 vec_len (sl->rewrite));
2046 if (vec_len (sl->segments) > 1)
2048 ip6srv->ip.src_address = src0;
2051 clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
2053 ip6srv->sr.segments_left += 2;
2054 ip6srv->sr.last_entry += 2;
2056 ip6srv->sr.length += ((sizeof (ip6_address_t) * 2) / 8);
2058 ip6srv->sr.segments[0] = dst0;
2059 ip6srv->sr.segments[1] = seg0;
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));
2070 ip6srv->ip.src_address = src0;
2071 ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
2073 ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
2074 ip6srv->sr.segments_left = 2;
2075 ip6srv->sr.last_entry = 1;
2077 ((sizeof (ip6_sr_header_t) +
2078 2 * sizeof (ip6_address_t)) / 8) - 1;
2079 ip6srv->sr.flags = 0;
2082 clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
2084 ip6srv->sr.segments[0] = dst0;
2085 ip6srv->sr.segments[1] = seg0;
2087 if (vec_len (sl->segments))
2089 ip6srv->sr.segments[2] = sl->segments[0];
2090 ip6srv->sr.last_entry++;
2091 ip6srv->sr.length += sizeof (ip6_address_t) / 8;
2097 clib_memcpy_fast (ip6srv, &sm->cache_hdr,
2098 sizeof (ip6_header_t));
2100 ip6srv->ip.src_address = src0;
2101 ip6srv->ip.dst_address = seg0;
2103 ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
2104 ip6srv->sr.segments_left = 1;
2105 ip6srv->sr.last_entry = 0;
2107 ((sizeof (ip6_sr_header_t) +
2108 sizeof (ip6_address_t)) / 8) - 1;
2109 ip6srv->sr.flags = 0;
2112 clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
2114 ip6srv->sr.segments[0] = dst0;
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;
2121 if (PREDICT_TRUE (encap != NULL))
2123 if (ls_param->nhtype == SRV6_NHTYPE_NONE)
2125 if ((clib_net_to_host_u32
2126 (encap->ip_version_traffic_class_and_flow_label) >>
2128 ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
2130 ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
2132 else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
2134 ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
2135 if ((clib_net_to_host_u32
2136 (encap->ip_version_traffic_class_and_flow_label) >>
2139 // Bad encap packet.
2140 next0 = SRV6_END_M_GTP6_D_DI_NEXT_DROP;
2145 else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
2147 ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
2148 if ((clib_net_to_host_u32
2149 (encap->ip_version_traffic_class_and_flow_label) >>
2152 // Bad encap packet.
2153 next0 = SRV6_END_M_GTP6_D_DI_NEXT_DROP;
2158 else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
2160 ip6srv->sr.protocol = IP_PROTOCOL_NONE;
2165 ip6srv->sr.protocol = IP_PROTOCOL_NONE;
2170 if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
2171 PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2173 srv6_end_rewrite_trace_t *tr =
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));
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;
2187 vlib_increment_combined_counter
2189 SRV6_END_M_GTP6_D_DI_NEXT_DROP) ?
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));
2194 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2195 n_left_to_next, bi0, next0);
2198 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2201 vlib_node_increment_counter (vm, sm->end_m_gtp6_d_di_node_index,
2202 SRV6_END_ERROR_M_GTP6_D_DI_BAD_PACKETS, bad_n);
2204 vlib_node_increment_counter (vm, sm->end_m_gtp6_d_di_node_index,
2205 SRV6_END_ERROR_M_GTP6_D_DI_PACKETS, good_n);
2207 return frame->n_vectors;
2210 VLIB_REGISTER_NODE (srv6_end_m_gtp6_e) =
2212 .name = "srv6-end-m-gtp6-e",.vector_size = sizeof (u32),.format_trace =
2213 format_srv6_end_rewrite_trace6,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
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 =
2218 [SRV6_END_M_GTP6_E_NEXT_DROP] = "error-drop",
2219 [SRV6_END_M_GTP6_E_NEXT_LOOKUP] = "ip6-lookup",}
2222 VLIB_REGISTER_NODE (srv6_end_m_gtp6_d) =
2224 .name = "srv6-end-m-gtp6-d",.vector_size = sizeof (u32),.format_trace =
2225 format_srv6_end_rewrite_trace6,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
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 =
2230 [SRV6_END_M_GTP6_D_NEXT_DROP] = "error-drop",
2231 [SRV6_END_M_GTP6_D_NEXT_LOOKUP] = "ip6-lookup",}
2234 VLIB_REGISTER_NODE (srv6_end_m_gtp6_d_di) =
2236 .name = "srv6-end-m-gtp6-d-di",.vector_size = sizeof (u32),.format_trace =
2237 format_srv6_end_rewrite_trace6,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
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 =
2242 [SRV6_END_M_GTP6_D_DI_NEXT_DROP] = "error-drop",
2243 [SRV6_END_M_GTP6_D_DI_NEXT_LOOKUP] = "ip6-lookup",}
2247 * fd.io coding-style-patch-verification: ON
2250 * eval: (c-set-style "gnu")