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