misc: fix issues reported by clang-15
[vpp.git] / src / plugins / srv6-as / node.c
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 format_srv6_as_localsid_trace (u8 * s, va_list * args)
36 {
37   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
38   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
39   srv6_as_localsid_trace_t *t = va_arg (*args, srv6_as_localsid_trace_t *);
40
41   return format (s, "SRv6-AS-localsid: localsid_index %d", t->localsid_index);
42 }
43
44 static u8 *
45 format_srv6_as_rewrite_trace (u8 * s, va_list * args)
46 {
47   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
48   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
49   srv6_as_rewrite_trace_t *t = va_arg (*args, srv6_as_rewrite_trace_t *);
50
51   if (PREDICT_FALSE (t->error != 0))
52     {
53       return format (s, "SRv6-AS-rewrite: cache is empty");
54     }
55
56   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 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   encap_len = sizeof (ip6_header_t);
123   ext_hdr = (ip6_ext_header_t *) (ip0 + 1);
124   hdr_type = ip0->protocol;
125
126   while (ip6_ext_hdr (hdr_type))
127     {
128       encap_len += ip6_ext_header_len (ext_hdr);
129       hdr_type = ext_hdr->next_hdr;
130       ext_hdr = ip6_ext_next_header (ext_hdr);
131     }
132
133   /* Make sure next header is valid */
134   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       return;
139     }
140
141   /* Remove IP header and extensions */
142   vlib_buffer_advance (b0, encap_len);
143
144   if (hdr_type == IP_PROTOCOL_IP6_ETHERNET)
145     {
146       /* Set output interface */
147       vnet_buffer (b0)->sw_if_index[VLIB_TX] = ls0_mem->sw_if_index_out;
148
149       /* Set next node to interface-output */
150       *next0 = SRV6_AS_LOCALSID_NEXT_INTERFACE;
151     }
152   else
153     {
154       /* Set Xconnect adjacency to VNF */
155       vnet_buffer (b0)->ip.adj_index[VLIB_TX] = ls0_mem->nh_adj;
156
157       /* Set next node to ip-rewrite */
158       *next0 = (hdr_type == IP_PROTOCOL_IPV6) ?
159         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 srv6_as_localsid_fn (vlib_main_t * vm,
168                      vlib_node_runtime_t * node, vlib_frame_t * frame)
169 {
170   ip6_sr_main_t *sm = &sr_main;
171   u32 n_left_from, next_index, *from, *to_next;
172
173   from = vlib_frame_vector_args (frame);
174   n_left_from = frame->n_vectors;
175   next_index = node->cached_next_index;
176
177   while (n_left_from > 0)
178     {
179       u32 n_left_to_next;
180
181       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
182
183       /* TODO: Dual/quad loop */
184
185       while (n_left_from > 0 && n_left_to_next > 0)
186         {
187           u32 bi0;
188           vlib_buffer_t *b0;
189           ip6_header_t *ip0 = 0;
190           ip6_sr_localsid_t *ls0;
191           u32 next0 = SRV6_AS_LOCALSID_NEXT_ERROR;
192
193           bi0 = from[0];
194           to_next[0] = bi0;
195           from += 1;
196           to_next += 1;
197           n_left_from -= 1;
198           n_left_to_next -= 1;
199
200           b0 = vlib_get_buffer (vm, bi0);
201           ip0 = vlib_buffer_get_current (b0);
202
203           /* Lookup the SR End behavior based on IP DA (adj) */
204           ls0 = pool_elt_at_index (sm->localsids,
205                                    vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
206
207           /* SRH processing */
208           end_as_processing (b0, ip0, ls0->plugin_mem, &next0);
209
210           if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
211             {
212               srv6_as_localsid_trace_t *tr =
213                 vlib_add_trace (vm, node, b0, sizeof *tr);
214               tr->localsid_index = ls0 - sm->localsids;
215             }
216
217           /* This increments the SRv6 per LocalSID counters. */
218           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                                            ls0 - sm->localsids, 1,
224                                            vlib_buffer_length_in_chain (vm,
225                                                                         b0));
226
227           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
228                                            n_left_to_next, bi0, next0);
229         }
230
231       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
232     }
233
234   return frame->n_vectors;
235 }
236
237 /* *INDENT-OFF* */
238 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 srv6_as2_rewrite_fn (vlib_main_t * vm,
262                      vlib_node_runtime_t * node, vlib_frame_t * frame)
263 {
264   ip6_sr_main_t *srm = &sr_main;
265   srv6_as_main_t *sm = &srv6_as_main;
266   u32 n_left_from, next_index, *from, *to_next;
267   u32 cnt_packets = 0;
268
269   from = vlib_frame_vector_args (frame);
270   n_left_from = frame->n_vectors;
271   next_index = node->cached_next_index;
272
273   while (n_left_from > 0)
274     {
275       u32 n_left_to_next;
276
277       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
278
279       /* TODO: Dual/quad loop */
280
281       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           ip6_header_t *ip0 = 0;
287           ip6_sr_localsid_t *ls0;
288           srv6_as_localsid_t *ls0_mem;
289           u32 next0 = SRV6_AS_REWRITE_NEXT_LOOKUP;
290
291           bi0 = from[0];
292           to_next[0] = bi0;
293           from += 1;
294           to_next += 1;
295           n_left_from -= 1;
296           n_left_to_next -= 1;
297
298           b0 = vlib_get_buffer (vm, bi0);
299           en0 = vlib_buffer_get_current (b0);
300           ls0 = pool_elt_at_index (srm->localsids,
301                                    sm->sw_iface_localsid2[vnet_buffer
302                                                           (b0)->sw_if_index
303                                                           [VLIB_RX]]);
304           ls0_mem = ls0->plugin_mem;
305
306           if (PREDICT_FALSE (ls0_mem == NULL || ls0_mem->rewrite == NULL))
307             {
308               next0 = SRV6_AS_REWRITE_NEXT_ERROR;
309               b0->error = node->errors[SRV6_AS_REWRITE_COUNTER_NO_RW];
310             }
311           else
312             {
313               ASSERT (VLIB_BUFFER_PRE_DATA_SIZE >=
314                       (vec_len (ls0_mem->rewrite) + b0->current_data));
315
316               clib_memcpy_fast (((u8 *) en0) - vec_len (ls0_mem->rewrite),
317                                 ls0_mem->rewrite, vec_len (ls0_mem->rewrite));
318               vlib_buffer_advance (b0, -(word) vec_len (ls0_mem->rewrite));
319
320               ip0 = vlib_buffer_get_current (b0);
321
322               ip0->payload_length =
323                 clib_host_to_net_u16 (b0->current_length -
324                                       sizeof (ip6_header_t));
325             }
326
327           if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
328               PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
329             {
330               srv6_as_rewrite_trace_t *tr =
331                 vlib_add_trace (vm, node, b0, sizeof *tr);
332               tr->error = 0;
333
334               if (next0 == SRV6_AS_REWRITE_NEXT_ERROR)
335                 {
336                   tr->error = 1;
337                 }
338               else
339                 {
340                   clib_memcpy_fast (tr->src.as_u8, ip0->src_address.as_u8,
341                                     sizeof tr->src.as_u8);
342                   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           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           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
357                                            n_left_to_next, bi0, next0);
358
359           cnt_packets++;
360         }
361
362       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
363     }
364
365   /* Update counters */
366   vlib_node_increment_counter (vm, srv6_as4_rewrite_node.index,
367                                SRV6_AS_REWRITE_COUNTER_PROCESSED,
368                                cnt_packets);
369
370   return frame->n_vectors;
371 }
372
373 /* *INDENT-OFF* */
374 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 srv6_as4_rewrite_fn (vlib_main_t * vm,
396                      vlib_node_runtime_t * node, vlib_frame_t * frame)
397 {
398   ip6_sr_main_t *srm = &sr_main;
399   srv6_as_main_t *sm = &srv6_as_main;
400   u32 n_left_from, next_index, *from, *to_next;
401   u32 cnt_packets = 0;
402
403   from = vlib_frame_vector_args (frame);
404   n_left_from = frame->n_vectors;
405   next_index = node->cached_next_index;
406
407   while (n_left_from > 0)
408     {
409       u32 n_left_to_next;
410
411       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
412
413       /* TODO: Dual/quad loop */
414
415       while (n_left_from > 0 && n_left_to_next > 0)
416         {
417           u32 bi0;
418           vlib_buffer_t *b0;
419           ip4_header_t *ip0_encap = 0;
420           ip6_header_t *ip0 = 0;
421           ip6_sr_localsid_t *ls0;
422           srv6_as_localsid_t *ls0_mem;
423           u32 next0 = SRV6_AS_REWRITE_NEXT_LOOKUP;
424           u16 new_l0 = 0;
425
426           bi0 = from[0];
427           to_next[0] = bi0;
428           from += 1;
429           to_next += 1;
430           n_left_from -= 1;
431           n_left_to_next -= 1;
432
433           b0 = vlib_get_buffer (vm, bi0);
434           ip0_encap = vlib_buffer_get_current (b0);
435           ls0 = pool_elt_at_index (srm->localsids,
436                                    sm->sw_iface_localsid4[vnet_buffer
437                                                           (b0)->sw_if_index
438                                                           [VLIB_RX]]);
439           ls0_mem = ls0->plugin_mem;
440
441           if (PREDICT_FALSE (ls0_mem == NULL || ls0_mem->rewrite == NULL))
442             {
443               next0 = SRV6_AS_REWRITE_NEXT_ERROR;
444               b0->error = node->errors[SRV6_AS_REWRITE_COUNTER_NO_RW];
445             }
446           else
447             {
448               ASSERT (VLIB_BUFFER_PRE_DATA_SIZE >=
449                       (vec_len (ls0_mem->rewrite) + b0->current_data));
450
451               clib_memcpy_fast (((u8 *) ip0_encap) -
452                                 vec_len (ls0_mem->rewrite), ls0_mem->rewrite,
453                                 vec_len (ls0_mem->rewrite));
454               vlib_buffer_advance (b0, -(word) vec_len (ls0_mem->rewrite));
455
456               ip0 = vlib_buffer_get_current (b0);
457
458               /* Update inner IPv4 TTL and checksum */
459               u32 checksum0;
460               ip0_encap->ttl -= 1;
461               checksum0 = ip0_encap->checksum + clib_host_to_net_u16 (0x0100);
462               checksum0 += checksum0 >= 0xffff;
463               ip0_encap->checksum = checksum0;
464
465               /* Update outer IPv6 length (in case it has changed) */
466               new_l0 = vec_len (ls0_mem->rewrite) - sizeof (ip6_header_t) +
467                 clib_net_to_host_u16 (ip0_encap->length);
468               ip0->payload_length = clib_host_to_net_u16 (new_l0);
469             }
470
471           if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
472               PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
473             {
474               srv6_as_rewrite_trace_t *tr =
475                 vlib_add_trace (vm, node, b0, sizeof *tr);
476               tr->error = 0;
477
478               if (next0 == SRV6_AS_REWRITE_NEXT_ERROR)
479                 {
480                   tr->error = 1;
481                 }
482               else
483                 {
484                   clib_memcpy_fast (tr->src.as_u8, ip0->src_address.as_u8,
485                                     sizeof tr->src.as_u8);
486                   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           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           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
501                                            n_left_to_next, bi0, next0);
502
503           cnt_packets++;
504         }
505
506       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
507     }
508
509   /* Update counters */
510   vlib_node_increment_counter (vm, srv6_as4_rewrite_node.index,
511                                SRV6_AS_REWRITE_COUNTER_PROCESSED,
512                                cnt_packets);
513
514   return frame->n_vectors;
515 }
516
517 /* *INDENT-OFF* */
518 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 srv6_as6_rewrite_fn (vlib_main_t * vm,
540                      vlib_node_runtime_t * node, vlib_frame_t * frame)
541 {
542   ip6_sr_main_t *srm = &sr_main;
543   srv6_as_main_t *sm = &srv6_as_main;
544   u32 n_left_from, next_index, *from, *to_next;
545   u32 cnt_packets = 0;
546
547   from = vlib_frame_vector_args (frame);
548   n_left_from = frame->n_vectors;
549   next_index = node->cached_next_index;
550
551   while (n_left_from > 0)
552     {
553       u32 n_left_to_next;
554
555       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
556
557       /* TODO: Dual/quad loop */
558
559       while (n_left_from > 0 && n_left_to_next > 0)
560         {
561           u32 bi0;
562           vlib_buffer_t *b0;
563           ip6_header_t *ip0 = 0, *ip0_encap = 0;
564           ip6_sr_localsid_t *ls0;
565           srv6_as_localsid_t *ls0_mem;
566           u32 next0 = SRV6_AS_REWRITE_NEXT_LOOKUP;
567           u16 new_l0 = 0;
568
569           bi0 = from[0];
570           to_next[0] = bi0;
571           from += 1;
572           to_next += 1;
573           n_left_from -= 1;
574           n_left_to_next -= 1;
575
576           b0 = vlib_get_buffer (vm, bi0);
577           ip0_encap = vlib_buffer_get_current (b0);
578           ls0 = pool_elt_at_index (srm->localsids,
579                                    sm->sw_iface_localsid6[vnet_buffer
580                                                           (b0)->sw_if_index
581                                                           [VLIB_RX]]);
582           ls0_mem = ls0->plugin_mem;
583
584           if (PREDICT_FALSE (ls0_mem == NULL || ls0_mem->rewrite == NULL))
585             {
586               next0 = SRV6_AS_REWRITE_NEXT_ERROR;
587               b0->error = node->errors[SRV6_AS_REWRITE_COUNTER_NO_RW];
588             }
589           else
590             {
591               ASSERT (VLIB_BUFFER_PRE_DATA_SIZE >=
592                       (vec_len (ls0_mem->rewrite) + b0->current_data));
593
594               clib_memcpy_fast (((u8 *) ip0_encap) -
595                                 vec_len (ls0_mem->rewrite), ls0_mem->rewrite,
596                                 vec_len (ls0_mem->rewrite));
597               vlib_buffer_advance (b0, -(word) vec_len (ls0_mem->rewrite));
598
599               ip0 = vlib_buffer_get_current (b0);
600
601               /* Update inner IPv6 hop limit */
602               ip0_encap->hop_limit -= 1;
603
604               /* Update outer IPv6 length (in case it has changed) */
605               new_l0 = vec_len (ls0_mem->rewrite) +
606                 clib_net_to_host_u16 (ip0_encap->payload_length);
607               ip0->payload_length = clib_host_to_net_u16 (new_l0);
608             }
609
610           if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
611               PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
612             {
613               srv6_as_rewrite_trace_t *tr =
614                 vlib_add_trace (vm, node, b0, sizeof *tr);
615               tr->error = 0;
616
617               if (next0 == SRV6_AS_REWRITE_NEXT_ERROR)
618                 {
619                   tr->error = 1;
620                 }
621               else
622                 {
623                   clib_memcpy_fast (tr->src.as_u8, ip0->src_address.as_u8,
624                                     sizeof tr->src.as_u8);
625                   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           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           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
640                                            n_left_to_next, bi0, next0);
641
642           cnt_packets++;
643         }
644
645       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
646     }
647
648   /* Update counters */
649   vlib_node_increment_counter (vm, srv6_as6_rewrite_node.index,
650                                SRV6_AS_REWRITE_COUNTER_PROCESSED,
651                                cnt_packets);
652
653   return frame->n_vectors;
654 }
655
656 /* *INDENT-OFF* */
657 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 */