Line data Source code
1 : /*
2 : * Copyright (c) 2015 Cisco and/or its affiliates.
3 : * Licensed under the Apache License, Version 2.0 (the "License");
4 : * you may not use this file except in compliance with the License.
5 : * You may obtain a copy of the License at:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
9 : * Unless required by applicable law or agreed to in writing, software
10 : * distributed under the License is distributed on an "AS IS" BASIS,
11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : * See the License for the specific language governing permissions and
13 : * limitations under the License.
14 : */
15 : #include <vlib/vlib.h>
16 : #include <vnet/vnet.h>
17 : #include <vppinfra/error.h>
18 : #include <srv6-as/as.h>
19 :
20 :
21 : /******************************* Packet tracing *******************************/
22 :
23 : typedef struct
24 : {
25 : u32 localsid_index;
26 : } srv6_as_localsid_trace_t;
27 :
28 : typedef struct
29 : {
30 : u8 error;
31 : ip6_address_t src, dst;
32 : } srv6_as_rewrite_trace_t;
33 :
34 : static u8 *
35 0 : format_srv6_as_localsid_trace (u8 * s, va_list * args)
36 : {
37 0 : CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
38 0 : CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
39 0 : srv6_as_localsid_trace_t *t = va_arg (*args, srv6_as_localsid_trace_t *);
40 :
41 0 : return format (s, "SRv6-AS-localsid: localsid_index %d", t->localsid_index);
42 : }
43 :
44 : static u8 *
45 18 : format_srv6_as_rewrite_trace (u8 * s, va_list * args)
46 : {
47 18 : CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
48 18 : CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
49 18 : srv6_as_rewrite_trace_t *t = va_arg (*args, srv6_as_rewrite_trace_t *);
50 :
51 18 : if (PREDICT_FALSE (t->error != 0))
52 : {
53 0 : return format (s, "SRv6-AS-rewrite: cache is empty");
54 : }
55 :
56 18 : return format (s, "SRv6-AS-rewrite: src %U dst %U",
57 : format_ip6_address, &t->src, format_ip6_address, &t->dst);
58 : }
59 :
60 :
61 : /***************************** Nodes registration *****************************/
62 :
63 : vlib_node_registration_t srv6_as4_rewrite_node;
64 : vlib_node_registration_t srv6_as6_rewrite_node;
65 :
66 :
67 : /****************************** Packet counters *******************************/
68 :
69 : #define foreach_srv6_as_rewrite_counter \
70 : _(PROCESSED, "srv6-as rewritten packets") \
71 : _(NO_RW, "(Error) No header for rewriting.")
72 :
73 : typedef enum
74 : {
75 : #define _(sym,str) SRV6_AS_REWRITE_COUNTER_##sym,
76 : foreach_srv6_as_rewrite_counter
77 : #undef _
78 : SRV6_AS_REWRITE_N_COUNTERS,
79 : } srv6_as_rewrite_counters;
80 :
81 : static char *srv6_as_rewrite_counter_strings[] = {
82 : #define _(sym,string) string,
83 : foreach_srv6_as_rewrite_counter
84 : #undef _
85 : };
86 :
87 :
88 : /********************************* Next nodes *********************************/
89 :
90 : typedef enum
91 : {
92 : SRV6_AS_LOCALSID_NEXT_ERROR,
93 : SRV6_AS_LOCALSID_NEXT_REWRITE4,
94 : SRV6_AS_LOCALSID_NEXT_REWRITE6,
95 : SRV6_AS_LOCALSID_NEXT_INTERFACE,
96 : SRV6_AS_LOCALSID_N_NEXT,
97 : } srv6_as_localsid_next_t;
98 :
99 : typedef enum
100 : {
101 : SRV6_AS_REWRITE_NEXT_ERROR,
102 : SRV6_AS_REWRITE_NEXT_LOOKUP,
103 : SRV6_AS_REWRITE_N_NEXT,
104 : } srv6_as_rewrite_next_t;
105 :
106 :
107 : /******************************* Local SID node *******************************/
108 :
109 : /**
110 : * @brief Function doing SRH processing for AS behavior
111 : */
112 : static_always_inline void
113 18 : end_as_processing (vlib_buffer_t * b0,
114 : ip6_header_t * ip0,
115 : srv6_as_localsid_t * ls0_mem, u32 * next0)
116 : {
117 : u16 encap_len;
118 : ip6_ext_header_t *ext_hdr;
119 : u8 hdr_type;
120 :
121 : /* Compute encapsulation headers length */
122 18 : encap_len = sizeof (ip6_header_t);
123 18 : ext_hdr = (ip6_ext_header_t *) (ip0 + 1);
124 18 : hdr_type = ip0->protocol;
125 :
126 36 : while (ip6_ext_hdr (hdr_type))
127 : {
128 18 : encap_len += ip6_ext_header_len (ext_hdr);
129 18 : hdr_type = ext_hdr->next_hdr;
130 18 : ext_hdr = ip6_ext_next_header (ext_hdr);
131 : }
132 :
133 : /* Make sure next header is valid */
134 18 : if (PREDICT_FALSE (hdr_type != IP_PROTOCOL_IPV6 &&
135 : hdr_type != IP_PROTOCOL_IP_IN_IP &&
136 : hdr_type != IP_PROTOCOL_IP6_ETHERNET))
137 : {
138 0 : return;
139 : }
140 :
141 : /* Remove IP header and extensions */
142 18 : vlib_buffer_advance (b0, encap_len);
143 :
144 18 : if (hdr_type == IP_PROTOCOL_IP6_ETHERNET)
145 : {
146 : /* Set output interface */
147 6 : vnet_buffer (b0)->sw_if_index[VLIB_TX] = ls0_mem->sw_if_index_out;
148 :
149 : /* Set next node to interface-output */
150 6 : *next0 = SRV6_AS_LOCALSID_NEXT_INTERFACE;
151 : }
152 : else
153 : {
154 : /* Set Xconnect adjacency to VNF */
155 12 : vnet_buffer (b0)->ip.adj_index[VLIB_TX] = ls0_mem->nh_adj;
156 :
157 : /* Set next node to ip-rewrite */
158 12 : *next0 = (hdr_type == IP_PROTOCOL_IPV6) ?
159 12 : SRV6_AS_LOCALSID_NEXT_REWRITE6 : SRV6_AS_LOCALSID_NEXT_REWRITE4;
160 : }
161 : }
162 :
163 : /**
164 : * @brief SRv6 AS Localsid graph node
165 : */
166 : static uword
167 6 : srv6_as_localsid_fn (vlib_main_t * vm,
168 : vlib_node_runtime_t * node, vlib_frame_t * frame)
169 : {
170 6 : ip6_sr_main_t *sm = &sr_main;
171 : u32 n_left_from, next_index, *from, *to_next;
172 :
173 6 : from = vlib_frame_vector_args (frame);
174 6 : n_left_from = frame->n_vectors;
175 6 : next_index = node->cached_next_index;
176 :
177 12 : while (n_left_from > 0)
178 : {
179 : u32 n_left_to_next;
180 :
181 6 : vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
182 :
183 : /* TODO: Dual/quad loop */
184 :
185 24 : while (n_left_from > 0 && n_left_to_next > 0)
186 : {
187 : u32 bi0;
188 : vlib_buffer_t *b0;
189 18 : ip6_header_t *ip0 = 0;
190 : ip6_sr_localsid_t *ls0;
191 18 : u32 next0 = SRV6_AS_LOCALSID_NEXT_ERROR;
192 :
193 18 : bi0 = from[0];
194 18 : to_next[0] = bi0;
195 18 : from += 1;
196 18 : to_next += 1;
197 18 : n_left_from -= 1;
198 18 : n_left_to_next -= 1;
199 :
200 18 : b0 = vlib_get_buffer (vm, bi0);
201 18 : ip0 = vlib_buffer_get_current (b0);
202 :
203 : /* Lookup the SR End behavior based on IP DA (adj) */
204 18 : ls0 = pool_elt_at_index (sm->localsids,
205 : vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
206 :
207 : /* SRH processing */
208 18 : end_as_processing (b0, ip0, ls0->plugin_mem, &next0);
209 :
210 18 : if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
211 : {
212 : srv6_as_localsid_trace_t *tr =
213 18 : vlib_add_trace (vm, node, b0, sizeof *tr);
214 18 : tr->localsid_index = ls0 - sm->localsids;
215 : }
216 :
217 : /* This increments the SRv6 per LocalSID counters. */
218 36 : vlib_increment_combined_counter (((next0 ==
219 : SRV6_AS_LOCALSID_NEXT_ERROR) ?
220 : &(sm->sr_ls_invalid_counters) :
221 : &(sm->sr_ls_valid_counters)),
222 : vm->thread_index,
223 18 : ls0 - sm->localsids, 1,
224 : vlib_buffer_length_in_chain (vm,
225 : b0));
226 :
227 18 : vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
228 : n_left_to_next, bi0, next0);
229 : }
230 :
231 6 : vlib_put_next_frame (vm, node, next_index, n_left_to_next);
232 : }
233 :
234 6 : return frame->n_vectors;
235 : }
236 :
237 : /* *INDENT-OFF* */
238 36287 : VLIB_REGISTER_NODE (srv6_as_localsid_node) = {
239 : .function = srv6_as_localsid_fn,
240 : .name = "srv6-as-localsid",
241 : .vector_size = sizeof (u32),
242 : .format_trace = format_srv6_as_localsid_trace,
243 : .type = VLIB_NODE_TYPE_INTERNAL,
244 : .n_next_nodes = SRV6_AS_LOCALSID_N_NEXT,
245 : .next_nodes = {
246 : [SRV6_AS_LOCALSID_NEXT_REWRITE4] = "ip4-rewrite",
247 : [SRV6_AS_LOCALSID_NEXT_REWRITE6] = "ip6-rewrite",
248 : [SRV6_AS_LOCALSID_NEXT_INTERFACE] = "interface-output",
249 : [SRV6_AS_LOCALSID_NEXT_ERROR] = "error-drop",
250 : },
251 : };
252 : /* *INDENT-ON* */
253 :
254 :
255 : /******************************* Rewriting node *******************************/
256 :
257 : /**
258 : * @brief Graph node for applying a SR policy into an IPv6 packet. Encapsulation
259 : */
260 : static uword
261 2 : srv6_as2_rewrite_fn (vlib_main_t * vm,
262 : vlib_node_runtime_t * node, vlib_frame_t * frame)
263 : {
264 2 : ip6_sr_main_t *srm = &sr_main;
265 2 : srv6_as_main_t *sm = &srv6_as_main;
266 : u32 n_left_from, next_index, *from, *to_next;
267 2 : u32 cnt_packets = 0;
268 :
269 2 : from = vlib_frame_vector_args (frame);
270 2 : n_left_from = frame->n_vectors;
271 2 : next_index = node->cached_next_index;
272 :
273 4 : while (n_left_from > 0)
274 : {
275 : u32 n_left_to_next;
276 :
277 2 : vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
278 :
279 : /* TODO: Dual/quad loop */
280 :
281 8 : while (n_left_from > 0 && n_left_to_next > 0)
282 : {
283 : u32 bi0;
284 : vlib_buffer_t *b0;
285 : ethernet_header_t *en0;
286 6 : ip6_header_t *ip0 = 0;
287 : ip6_sr_localsid_t *ls0;
288 : srv6_as_localsid_t *ls0_mem;
289 6 : u32 next0 = SRV6_AS_REWRITE_NEXT_LOOKUP;
290 :
291 6 : bi0 = from[0];
292 6 : to_next[0] = bi0;
293 6 : from += 1;
294 6 : to_next += 1;
295 6 : n_left_from -= 1;
296 6 : n_left_to_next -= 1;
297 :
298 6 : b0 = vlib_get_buffer (vm, bi0);
299 6 : en0 = vlib_buffer_get_current (b0);
300 6 : ls0 = pool_elt_at_index (srm->localsids,
301 : sm->sw_iface_localsid2[vnet_buffer
302 : (b0)->sw_if_index
303 : [VLIB_RX]]);
304 6 : ls0_mem = ls0->plugin_mem;
305 :
306 6 : if (PREDICT_FALSE (ls0_mem == NULL || ls0_mem->rewrite == NULL))
307 : {
308 0 : next0 = SRV6_AS_REWRITE_NEXT_ERROR;
309 0 : b0->error = node->errors[SRV6_AS_REWRITE_COUNTER_NO_RW];
310 : }
311 : else
312 : {
313 6 : ASSERT (VLIB_BUFFER_PRE_DATA_SIZE >=
314 : (vec_len (ls0_mem->rewrite) + b0->current_data));
315 :
316 12 : clib_memcpy_fast (((u8 *) en0) - vec_len (ls0_mem->rewrite),
317 12 : ls0_mem->rewrite, vec_len (ls0_mem->rewrite));
318 6 : vlib_buffer_advance (b0, -(word) vec_len (ls0_mem->rewrite));
319 :
320 6 : ip0 = vlib_buffer_get_current (b0);
321 :
322 6 : ip0->payload_length =
323 6 : clib_host_to_net_u16 (b0->current_length -
324 : sizeof (ip6_header_t));
325 : }
326 :
327 6 : if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
328 6 : PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
329 : {
330 : srv6_as_rewrite_trace_t *tr =
331 6 : vlib_add_trace (vm, node, b0, sizeof *tr);
332 6 : tr->error = 0;
333 :
334 6 : if (next0 == SRV6_AS_REWRITE_NEXT_ERROR)
335 : {
336 0 : tr->error = 1;
337 : }
338 : else
339 : {
340 6 : clib_memcpy_fast (tr->src.as_u8, ip0->src_address.as_u8,
341 : sizeof tr->src.as_u8);
342 6 : clib_memcpy_fast (tr->dst.as_u8, ip0->dst_address.as_u8,
343 : sizeof tr->dst.as_u8);
344 : }
345 : }
346 :
347 : /* Increment per-SID AS rewrite counters */
348 6 : vlib_increment_combined_counter (((next0 ==
349 : SRV6_AS_LOCALSID_NEXT_ERROR) ?
350 : &(sm->invalid_counters) :
351 : &(sm->valid_counters)),
352 : vm->thread_index, ls0_mem->index,
353 : 1, vlib_buffer_length_in_chain (vm,
354 : b0));
355 :
356 6 : vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
357 : n_left_to_next, bi0, next0);
358 :
359 6 : cnt_packets++;
360 : }
361 :
362 2 : vlib_put_next_frame (vm, node, next_index, n_left_to_next);
363 : }
364 :
365 : /* Update counters */
366 2 : vlib_node_increment_counter (vm, srv6_as4_rewrite_node.index,
367 : SRV6_AS_REWRITE_COUNTER_PROCESSED,
368 : cnt_packets);
369 :
370 2 : return frame->n_vectors;
371 : }
372 :
373 : /* *INDENT-OFF* */
374 36287 : VLIB_REGISTER_NODE (srv6_as2_rewrite_node) = {
375 : .function = srv6_as2_rewrite_fn,
376 : .name = "srv6-as2-rewrite",
377 : .vector_size = sizeof (u32),
378 : .format_trace = format_srv6_as_rewrite_trace,
379 : .type = VLIB_NODE_TYPE_INTERNAL,
380 : .n_errors = SRV6_AS_REWRITE_N_COUNTERS,
381 : .error_strings = srv6_as_rewrite_counter_strings,
382 : .n_next_nodes = SRV6_AS_REWRITE_N_NEXT,
383 : .next_nodes = {
384 : [SRV6_AS_REWRITE_NEXT_LOOKUP] = "ip6-lookup",
385 : [SRV6_AS_REWRITE_NEXT_ERROR] = "error-drop",
386 : },
387 : };
388 : /* *INDENT-ON* */
389 :
390 :
391 : /**
392 : * @brief Graph node for applying a SR policy into an IPv6 packet. Encapsulation
393 : */
394 : static uword
395 2 : srv6_as4_rewrite_fn (vlib_main_t * vm,
396 : vlib_node_runtime_t * node, vlib_frame_t * frame)
397 : {
398 2 : ip6_sr_main_t *srm = &sr_main;
399 2 : srv6_as_main_t *sm = &srv6_as_main;
400 : u32 n_left_from, next_index, *from, *to_next;
401 2 : u32 cnt_packets = 0;
402 :
403 2 : from = vlib_frame_vector_args (frame);
404 2 : n_left_from = frame->n_vectors;
405 2 : next_index = node->cached_next_index;
406 :
407 4 : while (n_left_from > 0)
408 : {
409 : u32 n_left_to_next;
410 :
411 2 : vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
412 :
413 : /* TODO: Dual/quad loop */
414 :
415 8 : while (n_left_from > 0 && n_left_to_next > 0)
416 : {
417 : u32 bi0;
418 : vlib_buffer_t *b0;
419 6 : ip4_header_t *ip0_encap = 0;
420 6 : ip6_header_t *ip0 = 0;
421 : ip6_sr_localsid_t *ls0;
422 : srv6_as_localsid_t *ls0_mem;
423 6 : u32 next0 = SRV6_AS_REWRITE_NEXT_LOOKUP;
424 6 : u16 new_l0 = 0;
425 :
426 6 : bi0 = from[0];
427 6 : to_next[0] = bi0;
428 6 : from += 1;
429 6 : to_next += 1;
430 6 : n_left_from -= 1;
431 6 : n_left_to_next -= 1;
432 :
433 6 : b0 = vlib_get_buffer (vm, bi0);
434 6 : ip0_encap = vlib_buffer_get_current (b0);
435 6 : ls0 = pool_elt_at_index (srm->localsids,
436 : sm->sw_iface_localsid4[vnet_buffer
437 : (b0)->sw_if_index
438 : [VLIB_RX]]);
439 6 : ls0_mem = ls0->plugin_mem;
440 :
441 6 : if (PREDICT_FALSE (ls0_mem == NULL || ls0_mem->rewrite == NULL))
442 : {
443 0 : next0 = SRV6_AS_REWRITE_NEXT_ERROR;
444 0 : b0->error = node->errors[SRV6_AS_REWRITE_COUNTER_NO_RW];
445 : }
446 : else
447 : {
448 6 : ASSERT (VLIB_BUFFER_PRE_DATA_SIZE >=
449 : (vec_len (ls0_mem->rewrite) + b0->current_data));
450 :
451 12 : clib_memcpy_fast (((u8 *) ip0_encap) -
452 6 : vec_len (ls0_mem->rewrite), ls0_mem->rewrite,
453 6 : vec_len (ls0_mem->rewrite));
454 6 : vlib_buffer_advance (b0, -(word) vec_len (ls0_mem->rewrite));
455 :
456 6 : ip0 = vlib_buffer_get_current (b0);
457 :
458 : /* Update inner IPv4 TTL and checksum */
459 : u32 checksum0;
460 6 : ip0_encap->ttl -= 1;
461 6 : checksum0 = ip0_encap->checksum + clib_host_to_net_u16 (0x0100);
462 6 : checksum0 += checksum0 >= 0xffff;
463 6 : ip0_encap->checksum = checksum0;
464 :
465 : /* Update outer IPv6 length (in case it has changed) */
466 6 : new_l0 = vec_len (ls0_mem->rewrite) - sizeof (ip6_header_t) +
467 6 : clib_net_to_host_u16 (ip0_encap->length);
468 6 : ip0->payload_length = clib_host_to_net_u16 (new_l0);
469 : }
470 :
471 6 : if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
472 6 : PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
473 : {
474 : srv6_as_rewrite_trace_t *tr =
475 6 : vlib_add_trace (vm, node, b0, sizeof *tr);
476 6 : tr->error = 0;
477 :
478 6 : if (next0 == SRV6_AS_REWRITE_NEXT_ERROR)
479 : {
480 0 : tr->error = 1;
481 : }
482 : else
483 : {
484 6 : clib_memcpy_fast (tr->src.as_u8, ip0->src_address.as_u8,
485 : sizeof tr->src.as_u8);
486 6 : clib_memcpy_fast (tr->dst.as_u8, ip0->dst_address.as_u8,
487 : sizeof tr->dst.as_u8);
488 : }
489 : }
490 :
491 : /* Increment per-SID AS rewrite counters */
492 6 : vlib_increment_combined_counter (((next0 ==
493 : SRV6_AS_LOCALSID_NEXT_ERROR) ?
494 : &(sm->invalid_counters) :
495 : &(sm->valid_counters)),
496 : vm->thread_index, ls0_mem->index,
497 : 1, vlib_buffer_length_in_chain (vm,
498 : b0));
499 :
500 6 : vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
501 : n_left_to_next, bi0, next0);
502 :
503 6 : cnt_packets++;
504 : }
505 :
506 2 : vlib_put_next_frame (vm, node, next_index, n_left_to_next);
507 : }
508 :
509 : /* Update counters */
510 2 : vlib_node_increment_counter (vm, srv6_as4_rewrite_node.index,
511 : SRV6_AS_REWRITE_COUNTER_PROCESSED,
512 : cnt_packets);
513 :
514 2 : return frame->n_vectors;
515 : }
516 :
517 : /* *INDENT-OFF* */
518 36287 : VLIB_REGISTER_NODE (srv6_as4_rewrite_node) = {
519 : .function = srv6_as4_rewrite_fn,
520 : .name = "srv6-as4-rewrite",
521 : .vector_size = sizeof (u32),
522 : .format_trace = format_srv6_as_rewrite_trace,
523 : .type = VLIB_NODE_TYPE_INTERNAL,
524 : .n_errors = SRV6_AS_REWRITE_N_COUNTERS,
525 : .error_strings = srv6_as_rewrite_counter_strings,
526 : .n_next_nodes = SRV6_AS_REWRITE_N_NEXT,
527 : .next_nodes = {
528 : [SRV6_AS_REWRITE_NEXT_LOOKUP] = "ip6-lookup",
529 : [SRV6_AS_REWRITE_NEXT_ERROR] = "error-drop",
530 : },
531 : };
532 : /* *INDENT-ON* */
533 :
534 :
535 : /**
536 : * @brief Graph node for applying a SR policy into an IPv6 packet. Encapsulation
537 : */
538 : static uword
539 2 : srv6_as6_rewrite_fn (vlib_main_t * vm,
540 : vlib_node_runtime_t * node, vlib_frame_t * frame)
541 : {
542 2 : ip6_sr_main_t *srm = &sr_main;
543 2 : srv6_as_main_t *sm = &srv6_as_main;
544 : u32 n_left_from, next_index, *from, *to_next;
545 2 : u32 cnt_packets = 0;
546 :
547 2 : from = vlib_frame_vector_args (frame);
548 2 : n_left_from = frame->n_vectors;
549 2 : next_index = node->cached_next_index;
550 :
551 4 : while (n_left_from > 0)
552 : {
553 : u32 n_left_to_next;
554 :
555 2 : vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
556 :
557 : /* TODO: Dual/quad loop */
558 :
559 8 : while (n_left_from > 0 && n_left_to_next > 0)
560 : {
561 : u32 bi0;
562 : vlib_buffer_t *b0;
563 6 : ip6_header_t *ip0 = 0, *ip0_encap = 0;
564 : ip6_sr_localsid_t *ls0;
565 : srv6_as_localsid_t *ls0_mem;
566 6 : u32 next0 = SRV6_AS_REWRITE_NEXT_LOOKUP;
567 6 : u16 new_l0 = 0;
568 :
569 6 : bi0 = from[0];
570 6 : to_next[0] = bi0;
571 6 : from += 1;
572 6 : to_next += 1;
573 6 : n_left_from -= 1;
574 6 : n_left_to_next -= 1;
575 :
576 6 : b0 = vlib_get_buffer (vm, bi0);
577 6 : ip0_encap = vlib_buffer_get_current (b0);
578 6 : ls0 = pool_elt_at_index (srm->localsids,
579 : sm->sw_iface_localsid6[vnet_buffer
580 : (b0)->sw_if_index
581 : [VLIB_RX]]);
582 6 : ls0_mem = ls0->plugin_mem;
583 :
584 6 : if (PREDICT_FALSE (ls0_mem == NULL || ls0_mem->rewrite == NULL))
585 : {
586 0 : next0 = SRV6_AS_REWRITE_NEXT_ERROR;
587 0 : b0->error = node->errors[SRV6_AS_REWRITE_COUNTER_NO_RW];
588 : }
589 : else
590 : {
591 6 : ASSERT (VLIB_BUFFER_PRE_DATA_SIZE >=
592 : (vec_len (ls0_mem->rewrite) + b0->current_data));
593 :
594 12 : clib_memcpy_fast (((u8 *) ip0_encap) -
595 6 : vec_len (ls0_mem->rewrite), ls0_mem->rewrite,
596 6 : vec_len (ls0_mem->rewrite));
597 6 : vlib_buffer_advance (b0, -(word) vec_len (ls0_mem->rewrite));
598 :
599 6 : ip0 = vlib_buffer_get_current (b0);
600 :
601 : /* Update inner IPv6 hop limit */
602 6 : ip0_encap->hop_limit -= 1;
603 :
604 : /* Update outer IPv6 length (in case it has changed) */
605 6 : new_l0 = vec_len (ls0_mem->rewrite) +
606 6 : clib_net_to_host_u16 (ip0_encap->payload_length);
607 6 : ip0->payload_length = clib_host_to_net_u16 (new_l0);
608 : }
609 :
610 6 : if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
611 6 : PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
612 : {
613 : srv6_as_rewrite_trace_t *tr =
614 6 : vlib_add_trace (vm, node, b0, sizeof *tr);
615 6 : tr->error = 0;
616 :
617 6 : if (next0 == SRV6_AS_REWRITE_NEXT_ERROR)
618 : {
619 0 : tr->error = 1;
620 : }
621 : else
622 : {
623 6 : clib_memcpy_fast (tr->src.as_u8, ip0->src_address.as_u8,
624 : sizeof tr->src.as_u8);
625 6 : clib_memcpy_fast (tr->dst.as_u8, ip0->dst_address.as_u8,
626 : sizeof tr->dst.as_u8);
627 : }
628 : }
629 :
630 : /* Increment per-SID AS rewrite counters */
631 6 : vlib_increment_combined_counter (((next0 ==
632 : SRV6_AS_LOCALSID_NEXT_ERROR) ?
633 : &(sm->invalid_counters) :
634 : &(sm->valid_counters)),
635 : vm->thread_index, ls0_mem->index,
636 : 1, vlib_buffer_length_in_chain (vm,
637 : b0));
638 :
639 6 : vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
640 : n_left_to_next, bi0, next0);
641 :
642 6 : cnt_packets++;
643 : }
644 :
645 2 : vlib_put_next_frame (vm, node, next_index, n_left_to_next);
646 : }
647 :
648 : /* Update counters */
649 2 : vlib_node_increment_counter (vm, srv6_as6_rewrite_node.index,
650 : SRV6_AS_REWRITE_COUNTER_PROCESSED,
651 : cnt_packets);
652 :
653 2 : return frame->n_vectors;
654 : }
655 :
656 : /* *INDENT-OFF* */
657 36287 : VLIB_REGISTER_NODE (srv6_as6_rewrite_node) = {
658 : .function = srv6_as6_rewrite_fn,
659 : .name = "srv6-as6-rewrite",
660 : .vector_size = sizeof (u32),
661 : .format_trace = format_srv6_as_rewrite_trace,
662 : .type = VLIB_NODE_TYPE_INTERNAL,
663 : .n_errors = SRV6_AS_REWRITE_N_COUNTERS,
664 : .error_strings = srv6_as_rewrite_counter_strings,
665 : .n_next_nodes = SRV6_AS_REWRITE_N_NEXT,
666 : .next_nodes = {
667 : [SRV6_AS_REWRITE_NEXT_LOOKUP] = "ip6-lookup",
668 : [SRV6_AS_REWRITE_NEXT_ERROR] = "error-drop",
669 : },
670 : };
671 : /* *INDENT-ON* */
672 :
673 : /*
674 : * fd.io coding-style-patch-verification: ON
675 : *
676 : * Local Variables:
677 : * eval: (c-set-style "gnu")
678 : * End:
679 : */
|