LCOV - code coverage report
Current view: top level - plugins/srv6-as - node.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 195 211 92.4 %
Date: 2023-10-26 01:39:38 Functions: 14 15 93.3 %

          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             : */

Generated by: LCOV version 1.14