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")
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")
138 #define _(sym,str) SRV6_END_ERROR_##sym,
139 foreach_srv6_end_v4_error
142 } srv6_end_error_v4_t;
146 #define _(sym,str) SRV6_T_ERROR_##sym,
147 foreach_srv6_t_v4_d_error
150 } srv6_t_error_v4_d_t;
154 #define _(sym,str) SRV6_END_ERROR_##sym,
155 foreach_srv6_end_v6_e_error
157 SRV6_END_N_V6_E_ERROR,
158 } srv6_end_error_v6_e_t;
162 #define _(sym,str) SRV6_END_ERROR_##sym,
163 foreach_srv6_end_v6_d_error
165 SRV6_END_N_V6_D_ERROR,
166 } srv6_end_error_v6_d_t;
170 #define _(sym,str) SRV6_END_ERROR_##sym,
171 foreach_srv6_end_v6_d_di_error
173 SRV6_END_N_V6_D_DI_ERROR,
174 } srv6_end_error_v6_d_di_t;
178 #define _(sym,str) SRV6_END_ERROR_##sym,
179 foreach_srv6_end_v6_dt_error
181 SRV6_END_N_V6_DT_ERROR,
182 } srv6_end_error_v6_dt_t;
184 static char *srv6_end_error_v4_strings[] = {
185 #define _(sym,string) string,
186 foreach_srv6_end_v4_error
190 static char *srv6_t_error_v4_d_strings[] = {
191 #define _(sym,string) string,
192 foreach_srv6_t_v4_d_error
196 static char *srv6_end_error_v6_e_strings[] = {
197 #define _(sym,string) string,
198 foreach_srv6_end_v6_e_error
202 static char *srv6_end_error_v6_d_strings[] = {
203 #define _(sym,string) string,
204 foreach_srv6_end_v6_d_error
208 static char *srv6_end_error_v6_d_di_strings[] = {
209 #define _(sym,string) string,
210 foreach_srv6_end_v6_d_di_error
216 SRV6_END_M_GTP4_E_NEXT_DROP,
217 SRV6_END_M_GTP4_E_NEXT_LOOKUP,
218 SRV6_END_M_GTP4_E_N_NEXT,
219 } srv6_end_m_gtp4_e_next_t;
223 SRV6_T_M_GTP4_D_NEXT_DROP,
224 SRV6_T_M_GTP4_D_NEXT_LOOKUP,
225 SRV6_T_M_GTP4_D_N_NEXT,
226 } srv6_T_m_gtp4_d_next_t;
230 SRV6_END_M_GTP6_E_NEXT_DROP,
231 SRV6_END_M_GTP6_E_NEXT_LOOKUP,
232 SRV6_END_M_GTP6_E_N_NEXT,
233 } srv6_end_m_gtp6_e_next_t;
237 SRV6_END_M_GTP6_D_NEXT_DROP,
238 SRV6_END_M_GTP6_D_NEXT_LOOKUP,
239 SRV6_END_M_GTP6_D_N_NEXT,
240 } srv6_end_m_gtp6_d_next_t;
244 SRV6_END_M_GTP6_D_DI_NEXT_DROP,
245 SRV6_END_M_GTP6_D_DI_NEXT_LOOKUP,
246 SRV6_END_M_GTP6_D_DI_N_NEXT,
247 } srv6_end_m_gtp6_d_di_next_t;
250 hash_uword_to_u16 (uword * key)
255 return val[0] ^ val[1] ^ val[2] ^ val[3];
257 return val[0] ^ val[1];
262 gtp_type_set (gtpu_header_t * gtpu, u16 tag)
266 val = clib_net_to_host_u16 (tag);
267 if (val & SRH_TAG_ECHO_REPLY)
268 gtpu->type = GTPU_TYPE_ECHO_REPLY;
269 else if (val & SRH_TAG_ECHO_REQUEST)
270 gtpu->type = GTPU_TYPE_ECHO_REQUEST;
271 else if (val & SRH_TAG_ERROR_INDICATION)
272 gtpu->type = GTPU_TYPE_ERROR_INDICATION;
273 else if (val & SRH_TAG_END_MARKER)
274 gtpu->type = GTPU_TYPE_END_MARKER;
277 // Function for SRv6 GTP4.E function.
278 VLIB_NODE_FN (srv6_end_m_gtp4_e) (vlib_main_t * vm,
279 vlib_node_runtime_t * node,
280 vlib_frame_t * frame)
282 srv6_end_main_v4_t *sm = &srv6_end_main_v4;
283 ip6_sr_main_t *sm2 = &sr_main;
284 u32 n_left_from, next_index, *from, *to_next;
285 u32 thread_index = vm->thread_index;
287 u32 good_n = 0, bad_n = 0;
289 from = vlib_frame_vector_args (frame);
290 n_left_from = frame->n_vectors;
291 next_index = node->cached_next_index;
293 while (n_left_from > 0)
297 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
299 while (n_left_from > 0 && n_left_to_next > 0)
303 ip6_sr_localsid_t *ls0;
304 srv6_end_gtp4_param_t *ls_param;
306 ip6srv_combo_header_t *ip6srv0;
307 ip6_address_t src0, dst0;
309 ip4_gtpu_header_t *hdr0 = NULL;
312 u32 next0 = SRV6_END_M_GTP4_E_NEXT_LOOKUP;
322 b0 = vlib_get_buffer (vm, bi0);
324 pool_elt_at_index (sm2->localsids,
325 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
327 ls_param = (srv6_end_gtp4_param_t *) ls0->plugin_mem;
329 ip6srv0 = vlib_buffer_get_current (b0);
330 src0 = ip6srv0->ip.src_address;
331 dst0 = ip6srv0->ip.dst_address;
333 len0 = vlib_buffer_length_in_chain (vm, b0);
335 if ((ip6srv0->ip.protocol == IPPROTO_IPV6_ROUTE
337 sizeof (ip6srv_combo_header_t) + ip6srv0->sr.length * 8)
338 || (len0 < sizeof (ip6_header_t)))
340 next0 = SRV6_END_M_GTP4_E_NEXT_DROP;
348 u8 *teid8p = (u8 *) & teid;
358 // we need to be sure there is enough space before
359 // ip6srv0 header, there is some extra space
360 // in the pre_data area for this kind of
363 // jump over variable length data
364 // not sure about the length
365 if (ip6srv0->ip.protocol == IPPROTO_IPV6_ROUTE)
367 tag = ip6srv0->sr.tag;
369 vlib_buffer_advance (b0,
370 (word) sizeof (ip6srv_combo_header_t) +
371 ip6srv0->sr.length * 8);
375 vlib_buffer_advance (b0, (word) sizeof (ip6_header_t));
378 // get length of encapsulated IPv6 packet (the remaining part)
379 p = vlib_buffer_get_current (b0);
381 len0 = vlib_buffer_length_in_chain (vm, b0);
383 offset = ls0->localsid_len / 8;
384 shift = ls0->localsid_len % 8;
386 if (PREDICT_TRUE (shift == 0))
388 clib_memcpy_fast (&dst4.as_u8[0], &dst0.as_u8[offset], 4);
390 qfi = dst0.as_u8[offset + 4];
392 clib_memcpy_fast (teid8p, &dst0.as_u8[offset + 5], 4);
396 for (index = 0; index < 4; index++)
398 dst4.as_u8[index] = dst0.as_u8[offset + index] << shift;
400 dst0.as_u8[offset + index + 1] >> (8 - shift);
403 qfi |= dst0.as_u8[offset + 4] << shift;
404 qfi |= dst0.as_u8[offset + 5] >> (8 - shift);
406 for (index = 0; index < 4; index++)
408 *teid8p = dst0.as_u8[offset + 5 + index] << shift;
410 dst0.as_u8[offset + 6 + index] >> (8 - shift);
418 sizeof (gtpu_exthdr_t) + sizeof (gtpu_pdu_session_t);
421 hdrlen += sizeof (ip4_gtpu_header_t);
423 // IPv4 GTP-U header creation.
424 vlib_buffer_advance (b0, -(word) hdrlen);
426 hdr0 = vlib_buffer_get_current (b0);
428 clib_memcpy_fast (hdr0, &sm->cache_hdr,
429 sizeof (ip4_gtpu_header_t));
431 hdr0->ip4.dst_address.as_u32 = dst4.as_u32;
433 hdr0->gtpu.teid = teid;
434 hdr0->gtpu.length = clib_host_to_net_u16 (len0);
436 if (PREDICT_FALSE (tag != 0))
438 gtp_type_set (&hdr0->gtpu, tag);
444 gtpu_pdu_session_t *sess;
446 hdr0->gtpu.ver_flags |= GTPU_EXTHDR_FLAG;
447 hdr0->gtpu.ext->seq = 0;
448 hdr0->gtpu.ext->npdu_num = 0;
449 hdr0->gtpu.ext->nextexthdr = GTPU_EXTHDR_PDU_SESSION;
451 type = qfi & SRV6_PDU_SESSION_U_BIT_MASK;
454 ((qfi & SRV6_PDU_SESSION_QFI_MASK) >> 2) |
455 ((qfi & SRV6_PDU_SESSION_R_BIT_MASK) << 5);
458 (gtpu_pdu_session_t *) (((char *) hdr0) +
459 sizeof (ip4_gtpu_header_t) +
460 sizeof (gtpu_exthdr_t));
465 sess->nextexthdr = 0;
468 offset = ls_param->v4src_position / 8;
469 shift = ls_param->v4src_position % 8;
471 if (PREDICT_TRUE (shift == 0))
473 for (index = 0; index < 4; index++)
475 hdr0->ip4.src_address.as_u8[index] =
476 src0.as_u8[offset + index];
481 for (index = 0; index < 4; index++)
483 hdr0->ip4.src_address.as_u8[index] =
484 src0.as_u8[offset + index] << shift;
485 hdr0->ip4.src_address.as_u8[index] |=
486 src0.as_u8[offset + index + 1] >> (8 - shift);
490 key = hash_memory (p, len0, 0);
491 port = hash_uword_to_u16 (&key);
492 hdr0->udp.src_port = port;
494 hdr0->udp.length = clib_host_to_net_u16 (len0 +
495 sizeof (udp_header_t) +
499 hdr0->ip4.length = clib_host_to_net_u16 (len0 +
501 (ip4_gtpu_header_t));
503 hdr0->ip4.checksum = ip4_header_checksum (&hdr0->ip4);
507 if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
508 PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
510 srv6_end_rewrite_trace_t *tr =
511 vlib_add_trace (vm, node, b0, sizeof (*tr));
512 clib_memcpy (tr->src.as_u8, hdr0->ip4.src_address.as_u8,
513 sizeof (tr->src.as_u8));
514 clib_memcpy (tr->dst.as_u8, hdr0->ip4.dst_address.as_u8,
515 sizeof (tr->dst.as_u8));
516 tr->teid = hdr0->gtpu.teid;
520 vlib_increment_combined_counter
522 SRV6_END_M_GTP4_E_NEXT_DROP) ? &(sm2->sr_ls_invalid_counters) :
523 &(sm2->sr_ls_valid_counters)), thread_index,
524 ls0 - sm2->localsids, 1, vlib_buffer_length_in_chain (vm, b0));
526 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
527 n_left_to_next, bi0, next0);
530 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
533 vlib_node_increment_counter (vm, sm->end_m_gtp4_e_node_index,
534 SRV6_END_ERROR_M_GTP4_E_BAD_PACKETS, bad_n);
536 vlib_node_increment_counter (vm, sm->end_m_gtp4_e_node_index,
537 SRV6_END_ERROR_M_GTP4_E_PACKETS, good_n);
539 return frame->n_vectors;
542 // Function for SRv6 GTP4.D function.
543 VLIB_NODE_FN (srv6_t_m_gtp4_d) (vlib_main_t * vm,
544 vlib_node_runtime_t * node,
545 vlib_frame_t * frame)
547 srv6_t_main_v4_decap_t *sm = &srv6_t_main_v4_decap;
548 ip6_sr_main_t *sm2 = &sr_main;
549 u32 n_left_from, next_index, *from, *to_next;
551 u32 good_n = 0, bad_n = 0;
553 from = vlib_frame_vector_args (frame);
554 n_left_from = frame->n_vectors;
555 next_index = node->cached_next_index;
557 while (n_left_from > 0)
561 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
563 while (n_left_from > 0 && n_left_to_next > 0)
568 srv6_end_gtp4_param_t *ls_param;
573 u32 next0 = SRV6_T_M_GTP4_D_NEXT_LOOKUP;
583 b0 = vlib_get_buffer (vm, bi0);
586 pool_elt_at_index (sm2->sid_lists,
587 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
589 ls_param = (srv6_end_gtp4_param_t *) sl0->plugin_mem;
591 len0 = vlib_buffer_length_in_chain (vm, b0);
593 ip4 = vlib_buffer_get_current (b0);
595 if (ip4->protocol != IP_PROTOCOL_UDP
596 || len0 < sizeof (ip4_gtpu_header_t))
598 next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
605 ip6_sr_policy_t *sr_policy = NULL;
606 ip6_sr_sl_t *sl = NULL;
610 ip4_gtpu_header_t *hdr;
611 ip4_address_t src, dst;
613 ip6_header_t *encap = NULL;
621 u32 offset, shift, index;
622 ip6srv_combo_header_t *ip6srv;
623 gtpu_pdu_session_t *sess = NULL;
626 hdr = (ip4_gtpu_header_t *) ip4;
628 hdr_len = sizeof (ip4_gtpu_header_t);
630 teid = hdr->gtpu.teid;
631 teidp = (u8 *) & teid;
633 gtpu_type = hdr->gtpu.type;
635 if (hdr->gtpu.ver_flags & GTPU_EXTHDR_FLAG)
638 hdr_len += sizeof (gtpu_exthdr_t);
639 if (hdr->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
641 // PDU Session Container.
643 (gtpu_pdu_session_t *) (((char *) hdr) + hdr_len);
644 qfi = sess->u.val & ~GTPU_PDU_SESSION_P_BIT_MASK;
647 hdr_len += sizeof (gtpu_pdu_session_t);
649 if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
651 hdr_len += sizeof (gtpu_paging_policy_t);
656 src = hdr->ip4.src_address;
659 dst = hdr->ip4.dst_address;
662 seg = ls_param->sr_prefix;
664 offset = ls_param->sr_prefixlen / 8;
665 shift = ls_param->sr_prefixlen % 8;
667 if (PREDICT_TRUE (shift == 0))
669 clib_memcpy_fast (&seg.as_u8[offset], dstp, 4);
674 ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
675 ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
679 qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
682 seg.as_u8[offset + 4] = qfi;
685 clib_memcpy_fast (&seg.as_u8[offset + 5], teidp, 4);
689 for (index = 0; index < 4; index++)
691 seg.as_u8[offset + index] |= dstp[index] >> shift;
692 seg.as_u8[offset + index + 1] |=
693 dstp[index] << (8 - shift);
695 seg.as_u8[offset + index + 5] |= teidp[index] >> shift;
696 seg.as_u8[offset + index + 6] |=
697 teidp[index] << (8 - shift);
703 ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
704 ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
708 qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
711 seg.as_u8[offset + 4] |= qfi >> shift;
712 seg.as_u8[offset + 5] |= qfi << (8 - shift);
716 src6 = ls_param->v6src_prefix;
718 offset = ls_param->v6src_prefixlen / 8;
719 shift = ls_param->v6src_prefixlen % 8;
721 if (PREDICT_TRUE (shift == 0))
723 clib_memcpy_fast (&src6.as_u8[offset], srcp, 4);
727 for (index = 0; index < 4; index++)
729 src6.as_u8[offset + index] |= srcp[offset] >> shift;
730 src6.as_u8[offset + index + 1] |=
731 srcp[offset] << (8 - shift);
735 vlib_buffer_advance (b0, (word) hdr_len);
738 if (PREDICT_TRUE (gtpu_type == GTPU_TYPE_GTPU))
740 encap = vlib_buffer_get_current (b0);
743 len0 = vlib_buffer_length_in_chain (vm, b0);
746 mhash_get (&sm2->sr_policies_index_hash,
747 &ls_param->sr_prefix);
750 sr_policy = pool_elt_at_index (sm2->sr_policies, p[0]);
755 vec_foreach (sl_index, sr_policy->segments_lists)
757 sl = pool_elt_at_index (sm2->sid_lists, *sl_index);
765 hdr_len = sizeof (ip6srv_combo_header_t);
766 hdr_len += vec_len (sl->segments) * sizeof (ip6_address_t);
767 hdr_len += sizeof (ip6_address_t);
771 hdr_len = sizeof (ip6_header_t);
773 if (PREDICT_FALSE (gtpu_type != GTPU_TYPE_GTPU))
775 hdr_len += sizeof (ip6_sr_header_t);
776 hdr_len += sizeof (ip6_address_t);
780 vlib_buffer_advance (b0, -(word) hdr_len);
781 ip6srv = vlib_buffer_get_current (b0);
785 clib_memcpy_fast (ip6srv, sl->rewrite,
786 vec_len (sl->rewrite));
788 ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
791 clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
793 ip6srv->sr.segments_left += 1;
794 ip6srv->sr.last_entry += 1;
796 ip6srv->sr.length += sizeof (ip6_address_t) / 8;
797 ip6srv->sr.segments[0] = seg;
799 if (PREDICT_TRUE (encap != NULL))
801 if (ls_param->nhtype == SRV6_NHTYPE_NONE)
803 if ((clib_net_to_host_u32
804 (encap->ip_version_traffic_class_and_flow_label)
806 ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
808 ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
810 else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
812 ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
813 if ((clib_net_to_host_u32
814 (encap->ip_version_traffic_class_and_flow_label)
818 next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
823 else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
825 ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
826 if ((clib_net_to_host_u32
827 (encap->ip_version_traffic_class_and_flow_label)
831 next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
836 else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
838 ip6srv->sr.protocol = IP_PROTOCOL_NONE;
843 ip6srv->sr.protocol = IP_PROTOCOL_NONE;
846 clib_memcpy_fast (&ip6srv->sr.segments[1],
847 (u8 *) (sl->rewrite +
848 sizeof (ip6_header_t) +
849 sizeof (ip6_sr_header_t)),
850 vec_len (sl->segments) *
851 sizeof (ip6_address_t));
855 clib_memcpy_fast (ip6srv, &sm->cache_hdr,
856 sizeof (ip6_header_t));
858 ip6srv->ip.dst_address = seg;
860 if (PREDICT_FALSE (gtpu_type != GTPU_TYPE_GTPU))
862 ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
864 ip6srv->sr.protocol = IP_PROTOCOL_NONE;
867 clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
869 ip6srv->sr.segments_left = 0;
870 ip6srv->sr.last_entry = 0;
872 ip6srv->sr.length = sizeof (ip6_address_t) / 8;
873 ip6srv->sr.segments[0] = seg;
877 if (ls_param->nhtype == SRV6_NHTYPE_NONE)
879 if ((clib_net_to_host_u32
880 (encap->ip_version_traffic_class_and_flow_label)
882 ip6srv->ip.protocol = IP_PROTOCOL_IPV6;
884 ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
886 else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
888 ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
889 if ((clib_net_to_host_u32
890 (encap->ip_version_traffic_class_and_flow_label)
894 next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
899 else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
901 ip6srv->ip.protocol = IP_PROTOCOL_IPV6;
902 if ((clib_net_to_host_u32
903 (encap->ip_version_traffic_class_and_flow_label)
907 next0 = SRV6_T_M_GTP4_D_NEXT_DROP;
912 else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
914 ip6srv->ip.protocol = IP_PROTOCOL_NONE;
919 ip6srv->ip.src_address = src6;
921 ip6srv->ip.payload_length =
922 clib_host_to_net_u16 (len0 + hdr_len - sizeof (ip6_header_t));
926 if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
927 PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
929 srv6_end_rewrite_trace_t *tr =
930 vlib_add_trace (vm, node, b0, sizeof (*tr));
931 clib_memcpy (tr->src.as_u8, ip6srv->ip.src_address.as_u8,
932 sizeof (tr->src.as_u8));
933 clib_memcpy (tr->dst.as_u8, ip6srv->ip.dst_address.as_u8,
934 sizeof (tr->dst.as_u8));
939 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
940 n_left_to_next, bi0, next0);
943 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
946 vlib_node_increment_counter (vm, sm->t_m_gtp4_d_node_index,
947 SRV6_T_ERROR_M_GTP4_D_BAD_PACKETS, bad_n);
949 vlib_node_increment_counter (vm, sm->t_m_gtp4_d_node_index,
950 SRV6_T_ERROR_M_GTP4_D_PACKETS, good_n);
952 return frame->n_vectors;
955 VLIB_REGISTER_NODE (srv6_end_m_gtp4_e) =
957 .name = "srv6-end-m-gtp4-e",.vector_size = sizeof (u32),.format_trace =
958 format_srv6_end_rewrite_trace,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
959 ARRAY_LEN (srv6_end_error_v4_strings),.error_strings =
960 srv6_end_error_v4_strings,.n_next_nodes =
961 SRV6_END_M_GTP4_E_N_NEXT,.next_nodes =
963 [SRV6_END_M_GTP4_E_NEXT_DROP] = "error-drop",
964 [SRV6_END_M_GTP4_E_NEXT_LOOKUP] = "ip4-lookup",}
967 VLIB_REGISTER_NODE (srv6_t_m_gtp4_d) =
969 .name = "srv6-t-m-gtp4-d",.vector_size = sizeof (u32),.format_trace =
970 format_srv6_end_rewrite_trace,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
971 ARRAY_LEN (srv6_t_error_v4_d_strings),.error_strings =
972 srv6_t_error_v4_d_strings,.n_next_nodes =
973 SRV6_T_M_GTP4_D_N_NEXT,.next_nodes =
975 [SRV6_T_M_GTP4_D_NEXT_DROP] = "error-drop",
976 [SRV6_T_M_GTP4_D_NEXT_LOOKUP] = "ip6-lookup",}
979 // Function for SRv6 GTP6.E function
980 VLIB_NODE_FN (srv6_end_m_gtp6_e) (vlib_main_t * vm,
981 vlib_node_runtime_t * node,
982 vlib_frame_t * frame)
984 srv6_end_main_v6_t *sm = &srv6_end_main_v6;
985 ip6_sr_main_t *sm2 = &sr_main;
986 u32 n_left_from, next_index, *from, *to_next;
987 u32 thread_index = vm->thread_index;
989 u32 good_n = 0, bad_n = 0;
991 from = vlib_frame_vector_args (frame);
992 n_left_from = frame->n_vectors;
993 next_index = node->cached_next_index;
995 while (n_left_from > 0)
999 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1001 while (n_left_from > 0 && n_left_to_next > 0)
1005 ip6_sr_localsid_t *ls0;
1007 ip6srv_combo_header_t *ip6srv0;
1008 ip6_address_t dst0, src0, seg0;
1010 ip6_gtpu_header_t *hdr0 = NULL;
1017 u32 next0 = SRV6_END_M_GTP6_E_NEXT_LOOKUP;
1025 n_left_to_next -= 1;
1027 b0 = vlib_get_buffer (vm, bi0);
1029 pool_elt_at_index (sm2->localsids,
1030 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1032 ip6srv0 = vlib_buffer_get_current (b0);
1033 dst0 = ip6srv0->ip.dst_address;
1034 src0 = ip6srv0->ip.src_address;
1035 seg0 = ip6srv0->sr.segments[0];
1037 tag = ip6srv0->sr.tag;
1039 len0 = vlib_buffer_length_in_chain (vm, b0);
1041 if ((ip6srv0->ip.protocol != IPPROTO_IPV6_ROUTE)
1043 sizeof (ip6srv_combo_header_t) + 8 * ip6srv0->sr.length))
1045 next0 = SRV6_END_M_GTP6_E_NEXT_DROP;
1051 // we need to be sure there is enough space before
1052 // ip6srv0 header, there is some extra space
1053 // in the pre_data area for this kind of
1056 // jump over variable length data
1057 // not sure about the length
1058 vlib_buffer_advance (b0, (word) sizeof (ip6srv_combo_header_t) +
1059 ip6srv0->sr.length * 8);
1061 // get length of encapsulated IPv6 packet (the remaining part)
1062 p = vlib_buffer_get_current (b0);
1064 len0 = vlib_buffer_length_in_chain (vm, b0);
1067 u8 *teid8p = (u8 *) & teid;
1073 index = ls0->localsid_len;
1078 if (PREDICT_TRUE (shift == 0))
1080 clib_memcpy_fast (teid8p, &dst0.as_u8[offset], 4);
1082 qfi = dst0.as_u8[offset + 4];
1086 for (index = offset; index < offset + 4; index++)
1088 *teid8p = dst0.as_u8[index] << shift;
1089 *teid8p |= dst0.as_u8[index + 1] >> (8 - shift);
1093 qfi |= dst0.as_u8[offset + 4] << shift;
1094 qfi |= dst0.as_u8[offset + 5] >> (8 - shift);
1100 sizeof (gtpu_exthdr_t) + sizeof (gtpu_pdu_session_t);
1103 hdrlen += sizeof (ip6_gtpu_header_t);
1105 vlib_buffer_advance (b0, -(word) hdrlen);
1107 hdr0 = vlib_buffer_get_current (b0);
1109 clib_memcpy_fast (hdr0, &sm->cache_hdr,
1110 sizeof (ip6_gtpu_header_t));
1112 hdr0->gtpu.teid = teid;
1113 hdr0->gtpu.length = clib_host_to_net_u16 (len0);
1115 if (PREDICT_FALSE (tag != 0))
1117 gtp_type_set (&hdr0->gtpu, tag);
1123 gtpu_pdu_session_t *sess;
1125 hdr0->gtpu.ver_flags |= GTPU_EXTHDR_FLAG;
1126 hdr0->gtpu.ext->seq = 0;
1127 hdr0->gtpu.ext->npdu_num = 0;
1128 hdr0->gtpu.ext->nextexthdr = GTPU_EXTHDR_PDU_SESSION;
1130 type = qfi & SRV6_PDU_SESSION_U_BIT_MASK;
1133 ((qfi & SRV6_PDU_SESSION_QFI_MASK) >> 2) |
1134 ((qfi & SRV6_PDU_SESSION_R_BIT_MASK) << 5);
1137 (gtpu_pdu_session_t *) (((char *) hdr0) +
1138 sizeof (ip6_gtpu_header_t) +
1139 sizeof (gtpu_exthdr_t));
1140 sess->exthdrlen = 1;
1144 sess->nextexthdr = 0;
1147 hdr0->udp.length = clib_host_to_net_u16 (len0 +
1148 sizeof (udp_header_t) +
1152 clib_memcpy_fast (hdr0->ip6.src_address.as_u8, src0.as_u8,
1153 sizeof (ip6_address_t));
1154 clib_memcpy_fast (hdr0->ip6.dst_address.as_u8, &seg0.as_u8,
1155 sizeof (ip6_address_t));
1157 hdr0->ip6.payload_length = clib_host_to_net_u16 (len0 +
1165 key = hash_memory (p, len0, 0);
1166 port = hash_uword_to_u16 (&key);
1167 hdr0->udp.src_port = port;
1171 if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
1172 PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1174 srv6_end_rewrite_trace_t *tr =
1175 vlib_add_trace (vm, node, b0, sizeof (*tr));
1176 clib_memcpy (tr->src.as_u8, hdr0->ip6.src_address.as_u8,
1177 sizeof (ip6_address_t));
1178 clib_memcpy (tr->dst.as_u8, hdr0->ip6.dst_address.as_u8,
1179 sizeof (ip6_address_t));
1180 tr->teid = hdr0->gtpu.teid;
1184 vlib_increment_combined_counter
1186 SRV6_END_M_GTP6_E_NEXT_DROP) ? &(sm2->sr_ls_invalid_counters) :
1187 &(sm2->sr_ls_valid_counters)), thread_index,
1188 ls0 - sm2->localsids, 1, vlib_buffer_length_in_chain (vm, b0));
1190 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1191 n_left_to_next, bi0, next0);
1194 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1197 vlib_node_increment_counter (vm, sm->end_m_gtp6_e_node_index,
1198 SRV6_END_ERROR_M_GTP6_E_BAD_PACKETS, bad_n);
1200 vlib_node_increment_counter (vm, sm->end_m_gtp6_e_node_index,
1201 SRV6_END_ERROR_M_GTP6_E_PACKETS, good_n);
1203 return frame->n_vectors;
1206 // Function for SRv6 GTP6.D function
1207 VLIB_NODE_FN (srv6_end_m_gtp6_d) (vlib_main_t * vm,
1208 vlib_node_runtime_t * node,
1209 vlib_frame_t * frame)
1211 srv6_end_main_v6_decap_t *sm = &srv6_end_main_v6_decap;
1212 ip6_sr_main_t *sm2 = &sr_main;
1213 u32 n_left_from, next_index, *from, *to_next;
1214 u32 thread_index = vm->thread_index;
1216 u32 good_n = 0, bad_n = 0;
1218 from = vlib_frame_vector_args (frame);
1219 n_left_from = frame->n_vectors;
1220 next_index = node->cached_next_index;
1222 while (n_left_from > 0)
1226 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1228 while (n_left_from > 0 && n_left_to_next > 0)
1232 ip6_sr_localsid_t *ls0;
1233 srv6_end_gtp6_param_t *ls_param;
1235 ip6_gtpu_header_t *hdr0 = NULL;
1238 ip6_address_t seg0, src0;
1246 ip6_header_t *encap = NULL;
1247 gtpu_pdu_session_t *sess = NULL;
1249 u32 next0 = SRV6_END_M_GTP6_D_NEXT_LOOKUP;
1257 n_left_to_next -= 1;
1259 b0 = vlib_get_buffer (vm, bi0);
1261 pool_elt_at_index (sm2->localsids,
1262 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1264 ls_param = (srv6_end_gtp6_param_t *) ls0->plugin_mem;
1266 hdr0 = vlib_buffer_get_current (b0);
1268 hdrlen = sizeof (ip6_gtpu_header_t);
1270 len0 = vlib_buffer_length_in_chain (vm, b0);
1272 if ((hdr0->ip6.protocol != IP_PROTOCOL_UDP)
1273 || (hdr0->udp.dst_port !=
1274 clib_host_to_net_u16 (SRV6_GTP_UDP_DST_PORT))
1275 || (len0 < sizeof (ip6_gtpu_header_t)))
1277 next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
1283 seg0 = ls_param->sr_prefix;
1284 src0 = hdr0->ip6.src_address;
1286 gtpu_type = hdr0->gtpu.type;
1288 teid = hdr0->gtpu.teid;
1289 teidp = (u8 *) & teid;
1291 if (hdr0->gtpu.ver_flags & GTPU_EXTHDR_FLAG)
1293 // Extention header.
1294 hdrlen += sizeof (gtpu_exthdr_t);
1295 if (hdr0->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
1297 // PDU Session Container.
1299 (gtpu_pdu_session_t *) (((char *) hdr0) +
1300 sizeof (ip6_gtpu_header_t) +
1301 sizeof (gtpu_exthdr_t));
1302 qfi = sess->u.val & ~GTPU_PDU_SESSION_P_BIT_MASK;
1303 qfip = (u8 *) & qfi;
1305 hdrlen += sizeof (gtpu_pdu_session_t);
1307 if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
1309 hdrlen += sizeof (gtpu_paging_policy_t);
1314 offset = ls_param->sr_prefixlen / 8;
1315 shift = ls_param->sr_prefixlen % 8;
1318 if (PREDICT_TRUE (shift == 0))
1320 clib_memcpy_fast (&seg0.as_u8[offset], teidp, 4);
1324 ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
1325 ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
1329 qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
1332 seg0.as_u8[offset + 4] = qfi;
1339 for (idx = 0; idx < 4; idx++)
1341 seg0.as_u8[offset + idx] |= teidp[idx] >> shift;
1342 seg0.as_u8[offset + idx + 1] |=
1343 teidp[idx] << (8 - shift);
1349 ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
1350 ((qfi & ~GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
1354 qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
1357 seg0.as_u8[offset + 4] |= qfi >> shift;
1358 seg0.as_u8[offset + 5] |= qfi << (8 - shift);
1362 // jump over variable length data
1363 vlib_buffer_advance (b0, (word) hdrlen);
1365 // get length of encapsulated IPv6 packet (the remaining part)
1366 len0 = vlib_buffer_length_in_chain (vm, b0);
1368 if (PREDICT_TRUE (gtpu_type == GTPU_TYPE_GTPU))
1370 encap = vlib_buffer_get_current (b0);
1374 ip6srv_combo_header_t *ip6srv;
1375 ip6_sr_policy_t *sr_policy = NULL;
1376 ip6_sr_sl_t *sl = NULL;
1381 mhash_get (&sm2->sr_policies_index_hash,
1382 &ls_param->sr_prefix);
1385 sr_policy = pool_elt_at_index (sm2->sr_policies, p[0]);
1390 vec_foreach (sl_index, sr_policy->segments_lists)
1392 sl = pool_elt_at_index (sm2->sid_lists, *sl_index);
1400 hdr_len = sizeof (ip6srv_combo_header_t);
1401 hdr_len += vec_len (sl->segments) * sizeof (ip6_address_t);
1402 hdr_len += sizeof (ip6_address_t);
1406 hdr_len = sizeof (ip6_header_t);
1407 if (PREDICT_FALSE (gtpu_type) != GTPU_TYPE_GTPU)
1409 hdr_len += sizeof (ip6_sr_header_t);
1410 hdr_len += sizeof (ip6_address_t);
1414 // jump back to data[0] or pre_data if required
1415 vlib_buffer_advance (b0, -(word) hdr_len);
1417 ip6srv = vlib_buffer_get_current (b0);
1421 clib_memcpy_fast (ip6srv, sl->rewrite,
1422 vec_len (sl->rewrite));
1424 ip6srv->ip.src_address = src0;
1425 ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
1428 clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1430 ip6srv->sr.segments_left += 1;
1431 ip6srv->sr.last_entry += 1;
1433 ip6srv->sr.length += sizeof (ip6_address_t) / 8;
1434 ip6srv->sr.segments[0] = seg0;
1436 if (PREDICT_TRUE (encap != NULL))
1438 if (ls_param->nhtype == SRV6_NHTYPE_NONE)
1440 if ((clib_net_to_host_u32
1441 (encap->ip_version_traffic_class_and_flow_label)
1443 ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
1445 ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
1447 else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
1449 ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
1450 if ((clib_net_to_host_u32
1451 (encap->ip_version_traffic_class_and_flow_label)
1454 // Bad encap packet.
1455 next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
1460 else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
1462 ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
1463 if ((clib_net_to_host_u32
1464 (encap->ip_version_traffic_class_and_flow_label)
1467 // Bad encap packet.
1468 next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
1473 else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
1475 ip6srv->sr.protocol = IP_PROTOCOL_NONE;
1480 ip6srv->sr.protocol = IP_PROTOCOL_NONE;
1483 clib_memcpy_fast (&ip6srv->sr.segments[1],
1484 (u8 *) (sl->rewrite +
1485 sizeof (ip6_header_t) +
1486 sizeof (ip6_sr_header_t)),
1487 vec_len (sl->segments) *
1488 sizeof (ip6_address_t));
1492 clib_memcpy_fast (ip6srv, &sm->cache_hdr,
1493 sizeof (ip6_header_t));
1495 ip6srv->ip.src_address = src0;
1496 ip6srv->ip.dst_address = seg0;
1498 if (PREDICT_FALSE (gtpu_type) != GTPU_TYPE_GTPU)
1500 ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
1502 ip6srv->sr.protocol = IP_PROTOCOL_NONE;
1505 clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1507 ip6srv->sr.segments_left = 0;
1508 ip6srv->sr.last_entry = 0;
1510 ip6srv->sr.length = sizeof (ip6_address_t) / 8;
1511 ip6srv->sr.segments[0] = seg0;
1515 if (ls_param->nhtype == SRV6_NHTYPE_NONE)
1517 if ((clib_net_to_host_u32
1518 (encap->ip_version_traffic_class_and_flow_label)
1520 ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
1522 else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
1524 ip6srv->ip.protocol = IP_PROTOCOL_IP_IN_IP;
1525 if ((clib_net_to_host_u32
1526 (encap->ip_version_traffic_class_and_flow_label)
1529 // Bad encap packet.
1530 next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
1535 else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
1537 ip6srv->ip.protocol = IP_PROTOCOL_IPV6;
1538 if ((clib_net_to_host_u32
1539 (encap->ip_version_traffic_class_and_flow_label)
1542 // Bad encap packet.
1543 next0 = SRV6_END_M_GTP6_D_NEXT_DROP;
1548 else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
1550 ip6srv->ip.protocol = IP_PROTOCOL_NONE;
1555 ip6srv->ip.payload_length =
1556 clib_host_to_net_u16 (len0 + hdr_len - sizeof (ip6_header_t));
1560 if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
1561 PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1563 srv6_end_rewrite_trace_t *tr =
1564 vlib_add_trace (vm, node, b0, sizeof (*tr));
1565 clib_memcpy (tr->src.as_u8, ip6srv->ip.src_address.as_u8,
1566 sizeof (ip6_address_t));
1567 clib_memcpy (tr->dst.as_u8, ip6srv->ip.dst_address.as_u8,
1568 sizeof (ip6_address_t));
1570 clib_memcpy (tr->sr_prefix.as_u8, ls_param->sr_prefix.as_u8,
1571 sizeof (ip6_address_t));
1572 tr->sr_prefixlen = ls_param->sr_prefixlen;
1577 vlib_increment_combined_counter
1579 SRV6_END_M_GTP6_D_NEXT_DROP) ? &(sm2->sr_ls_invalid_counters) :
1580 &(sm2->sr_ls_valid_counters)), thread_index,
1581 ls0 - sm2->localsids, 1, vlib_buffer_length_in_chain (vm, b0));
1583 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1584 n_left_to_next, bi0, next0);
1587 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1590 vlib_node_increment_counter (vm, sm->end_m_gtp6_d_node_index,
1591 SRV6_END_ERROR_M_GTP6_D_BAD_PACKETS, bad_n);
1593 vlib_node_increment_counter (vm, sm->end_m_gtp6_d_node_index,
1594 SRV6_END_ERROR_M_GTP6_D_PACKETS, good_n);
1596 return frame->n_vectors;
1599 // Function for SRv6 GTP6.D.DI function
1600 VLIB_NODE_FN (srv6_end_m_gtp6_d_di) (vlib_main_t * vm,
1601 vlib_node_runtime_t * node,
1602 vlib_frame_t * frame)
1604 srv6_end_main_v6_decap_di_t *sm = &srv6_end_main_v6_decap_di;
1605 ip6_sr_main_t *sm2 = &sr_main;
1606 u32 n_left_from, next_index, *from, *to_next;
1607 u32 thread_index = vm->thread_index;
1608 srv6_end_gtp6_param_t *ls_param;
1610 u32 good_n = 0, bad_n = 0;
1612 from = vlib_frame_vector_args (frame);
1613 n_left_from = frame->n_vectors;
1614 next_index = node->cached_next_index;
1616 while (n_left_from > 0)
1620 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1622 while (n_left_from > 0 && n_left_to_next > 0)
1626 ip6_sr_localsid_t *ls0;
1628 ip6_gtpu_header_t *hdr0 = NULL;
1641 ip6_header_t *encap = NULL;
1642 gtpu_pdu_session_t *sess;
1644 u32 next0 = SRV6_END_M_GTP6_D_DI_NEXT_LOOKUP;
1652 n_left_to_next -= 1;
1654 b0 = vlib_get_buffer (vm, bi0);
1656 pool_elt_at_index (sm2->localsids,
1657 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1659 ls_param = (srv6_end_gtp6_param_t *) ls0->plugin_mem;
1661 hdr0 = vlib_buffer_get_current (b0);
1663 hdrlen = sizeof (ip6_gtpu_header_t);
1665 len0 = vlib_buffer_length_in_chain (vm, b0);
1667 if ((hdr0->ip6.protocol != IP_PROTOCOL_UDP)
1668 || (hdr0->udp.dst_port !=
1669 clib_host_to_net_u16 (SRV6_GTP_UDP_DST_PORT))
1670 || (len0 < sizeof (ip6_gtpu_header_t)))
1672 next0 = SRV6_END_M_GTP6_D_DI_NEXT_DROP;
1678 dst0 = hdr0->ip6.dst_address;
1679 src0 = hdr0->ip6.src_address;
1681 gtpu_type = hdr0->gtpu.type;
1683 seg0 = ls_param->sr_prefix;
1684 teid = hdr0->gtpu.teid;
1685 teidp = (u8 *) & teid;
1687 if (hdr0->gtpu.ver_flags & GTPU_EXTHDR_FLAG)
1689 // Extention header.
1690 hdrlen += sizeof (gtpu_exthdr_t);
1691 if (hdr0->gtpu.ext->nextexthdr == GTPU_EXTHDR_PDU_SESSION)
1693 // PDU Session Container.
1695 (gtpu_pdu_session_t *) (((char *) hdr0) + hdrlen);
1696 qfi = sess->u.val & ~GTPU_PDU_SESSION_P_BIT_MASK;
1699 hdrlen += sizeof (gtpu_pdu_session_t);
1701 if (sess->u.val & GTPU_PDU_SESSION_P_BIT_MASK)
1703 hdrlen += sizeof (gtpu_paging_policy_t);
1708 offset = ls_param->sr_prefixlen / 8;
1709 shift = ls_param->sr_prefixlen % 8;
1712 if (PREDICT_TRUE (shift == 0))
1714 clib_memcpy_fast (&seg0.as_u8[offset], teidp, 4);
1719 ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
1720 ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
1724 qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
1727 seg0.as_u8[offset + 4] = qfi;
1734 for (idx = 0; idx < 4; idx++)
1736 seg0.as_u8[offset + idx] |= teidp[idx] >> shift;
1737 seg0.as_u8[offset + idx + 1] |=
1738 teidp[idx] << (8 - shift);
1744 ((qfi & GTPU_PDU_SESSION_QFI_MASK) << 2) |
1745 ((qfi & GTPU_PDU_SESSION_R_BIT_MASK) >> 5);
1749 qfi |= SRV6_PDU_SESSION_U_BIT_MASK;
1752 seg0.as_u8[offset + 4] |= qfi >> shift;
1753 seg0.as_u8[offset + 5] |= qfi << (8 - shift);
1757 // jump over variable length data
1758 vlib_buffer_advance (b0, (word) hdrlen);
1760 // get length of encapsulated IPv6 packet (the remaining part)
1761 len0 = vlib_buffer_length_in_chain (vm, b0);
1763 if (PREDICT_TRUE (gtpu_type == GTPU_TYPE_GTPU))
1765 encap = vlib_buffer_get_current (b0);
1769 ip6srv_combo_header_t *ip6srv;
1770 ip6_sr_policy_t *sr_policy = NULL;
1771 ip6_sr_sl_t *sl = NULL;
1776 mhash_get (&sm2->sr_policies_index_hash,
1777 &ls_param->sr_prefix);
1780 sr_policy = pool_elt_at_index (sm2->sr_policies, p[0]);
1785 vec_foreach (sl_index, sr_policy->segments_lists)
1787 sl = pool_elt_at_index (sm2->sid_lists, *sl_index);
1793 hdr_len = sizeof (ip6srv_combo_header_t);
1796 hdr_len += vec_len (sl->segments) * sizeof (ip6_address_t);
1798 hdr_len += sizeof (ip6_address_t) * 2;
1800 // jump back to data[0] or pre_data if required
1801 vlib_buffer_advance (b0, -(word) hdr_len);
1803 ip6srv = vlib_buffer_get_current (b0);
1807 clib_memcpy_fast (ip6srv, sl->rewrite,
1808 vec_len (sl->rewrite));
1810 ip6srv->ip.src_address = src0;
1813 clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1815 ip6srv->sr.segments_left += 2;
1816 ip6srv->sr.last_entry += 2;
1820 clib_memcpy_fast (ip6srv, &sm->cache_hdr,
1821 sizeof (ip6_header_t));
1823 ip6srv->ip.src_address = src0;
1824 ip6srv->ip.dst_address = seg0;
1827 clib_host_to_net_u16 (srh_tagfield[gtpu_type]);
1829 ip6srv->sr.segments_left += 1;
1830 ip6srv->sr.last_entry += 1;
1831 ip6srv->sr.type = ROUTING_HEADER_TYPE_SR;
1834 ip6srv->ip.payload_length =
1835 clib_host_to_net_u16 (len0 + hdr_len - sizeof (ip6_header_t));
1836 ip6srv->ip.protocol = IP_PROTOCOL_IPV6_ROUTE;
1838 if (PREDICT_TRUE (encap != NULL))
1840 if (ls_param->nhtype == SRV6_NHTYPE_NONE)
1842 if ((clib_net_to_host_u32
1843 (encap->ip_version_traffic_class_and_flow_label) >>
1845 ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
1847 ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
1849 else if (ls_param->nhtype == SRV6_NHTYPE_IPV4)
1851 ip6srv->sr.protocol = IP_PROTOCOL_IP_IN_IP;
1852 if ((clib_net_to_host_u32
1853 (encap->ip_version_traffic_class_and_flow_label) >>
1856 // Bad encap packet.
1857 next0 = SRV6_END_M_GTP6_D_DI_NEXT_DROP;
1862 else if (ls_param->nhtype == SRV6_NHTYPE_IPV6)
1864 ip6srv->sr.protocol = IP_PROTOCOL_IPV6;
1865 if ((clib_net_to_host_u32
1866 (encap->ip_version_traffic_class_and_flow_label) >>
1869 // Bad encap packet.
1870 next0 = SRV6_END_M_GTP6_D_DI_NEXT_DROP;
1875 else if (ls_param->nhtype == SRV6_NHTYPE_NON_IP)
1877 ip6srv->sr.protocol = IP_PROTOCOL_NONE;
1882 ip6srv->sr.protocol = IP_PROTOCOL_NONE;
1885 ip6srv->sr.length += ((sizeof (ip6_address_t) * 2) / 8);
1886 ip6srv->sr.segments[0] = dst0;
1887 ip6srv->sr.segments[1] = seg0;
1891 clib_memcpy_fast (&ip6srv->sr.segments[2],
1892 (u8 *) (sl->rewrite +
1893 sizeof (ip6_header_t) +
1894 sizeof (ip6_sr_header_t)),
1895 vec_len (sl->segments) *
1896 sizeof (ip6_address_t));
1901 if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
1902 PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1904 srv6_end_rewrite_trace_t *tr =
1905 vlib_add_trace (vm, node, b0, sizeof (*tr));
1906 clib_memcpy (tr->src.as_u8, ip6srv->ip.src_address.as_u8,
1907 sizeof (ip6_address_t));
1908 clib_memcpy (tr->dst.as_u8, ip6srv->ip.dst_address.as_u8,
1909 sizeof (ip6_address_t));
1911 clib_memcpy (tr->sr_prefix.as_u8, ls_param->sr_prefix.as_u8,
1912 sizeof (ip6_address_t));
1913 tr->sr_prefixlen = ls_param->sr_prefixlen;
1918 vlib_increment_combined_counter
1920 SRV6_END_M_GTP6_D_DI_NEXT_DROP) ?
1921 &(sm2->sr_ls_invalid_counters) : &(sm2->sr_ls_valid_counters)),
1922 thread_index, ls0 - sm2->localsids, 1,
1923 vlib_buffer_length_in_chain (vm, b0));
1925 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1926 n_left_to_next, bi0, next0);
1929 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1932 vlib_node_increment_counter (vm, sm->end_m_gtp6_d_di_node_index,
1933 SRV6_END_ERROR_M_GTP6_D_DI_BAD_PACKETS, bad_n);
1935 vlib_node_increment_counter (vm, sm->end_m_gtp6_d_di_node_index,
1936 SRV6_END_ERROR_M_GTP6_D_DI_PACKETS, good_n);
1938 return frame->n_vectors;
1941 VLIB_REGISTER_NODE (srv6_end_m_gtp6_e) =
1943 .name = "srv6-end-m-gtp6-e",.vector_size = sizeof (u32),.format_trace =
1944 format_srv6_end_rewrite_trace6,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
1945 ARRAY_LEN (srv6_end_error_v6_e_strings),.error_strings =
1946 srv6_end_error_v6_e_strings,.n_next_nodes =
1947 SRV6_END_M_GTP6_E_N_NEXT,.next_nodes =
1949 [SRV6_END_M_GTP6_E_NEXT_DROP] = "error-drop",
1950 [SRV6_END_M_GTP6_E_NEXT_LOOKUP] = "ip6-lookup",}
1953 VLIB_REGISTER_NODE (srv6_end_m_gtp6_d) =
1955 .name = "srv6-end-m-gtp6-d",.vector_size = sizeof (u32),.format_trace =
1956 format_srv6_end_rewrite_trace6,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
1957 ARRAY_LEN (srv6_end_error_v6_d_strings),.error_strings =
1958 srv6_end_error_v6_d_strings,.n_next_nodes =
1959 SRV6_END_M_GTP6_D_N_NEXT,.next_nodes =
1961 [SRV6_END_M_GTP6_D_NEXT_DROP] = "error-drop",
1962 [SRV6_END_M_GTP6_D_NEXT_LOOKUP] = "ip6-lookup",}
1965 VLIB_REGISTER_NODE (srv6_end_m_gtp6_d_di) =
1967 .name = "srv6-end-m-gtp6-d-di",.vector_size = sizeof (u32),.format_trace =
1968 format_srv6_end_rewrite_trace6,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
1969 ARRAY_LEN (srv6_end_error_v6_d_di_strings),.error_strings =
1970 srv6_end_error_v6_d_di_strings,.n_next_nodes =
1971 SRV6_END_M_GTP6_D_DI_N_NEXT,.next_nodes =
1973 [SRV6_END_M_GTP6_D_DI_NEXT_DROP] = "error-drop",
1974 [SRV6_END_M_GTP6_D_DI_NEXT_LOOKUP] = "ip6-lookup",}
1978 * fd.io coding-style-patch-verification: ON
1981 * eval: (c-set-style "gnu")