LCOV - code coverage report
Current view: top level - vnet/ip - ip6_forward.h (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 121 136 89.0 %
Date: 2023-10-26 01:39:38 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 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             : /*
      16             :  * ip/ip6_forward.h: IP v6 forwarding
      17             :  *
      18             :  * Copyright (c) 2008 Eliot Dresselhaus
      19             :  *
      20             :  * Permission is hereby granted, free of charge, to any person obtaining
      21             :  * a copy of this software and associated documentation files (the
      22             :  * "Software"), to deal in the Software without restriction, including
      23             :  * without limitation the rights to use, copy, modify, merge, publish,
      24             :  * distribute, sublicense, and/or sell copies of the Software, and to
      25             :  * permit persons to whom the Software is furnished to do so, subject to
      26             :  * the following conditions:
      27             :  *
      28             :  * The above copyright notice and this permission notice shall be
      29             :  * included in all copies or substantial portions of the Software.
      30             :  *
      31             :  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      32             :  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      33             :  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      34             :  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      35             :  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
      36             :  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
      37             :  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      38             :  */
      39             : 
      40             : #ifndef __included_ip6_forward_h__
      41             : #define __included_ip6_forward_h__
      42             : 
      43             : #include <vnet/fib/ip6_fib.h>
      44             : #include <vnet/dpo/load_balance_map.h>
      45             : #include <vnet/ip/ip6_inlines.h>
      46             : 
      47             : /**
      48             :  * @file
      49             :  * @brief IPv6 Forwarding.
      50             :  *
      51             :  * This file contains the source code for IPv6 forwarding.
      52             :  */
      53             : 
      54             : 
      55             : always_inline uword
      56      229702 : ip6_lookup_inline (vlib_main_t * vm,
      57             :                    vlib_node_runtime_t * node, vlib_frame_t * frame)
      58             : {
      59      229702 :   ip6_main_t *im = &ip6_main;
      60      229702 :   vlib_combined_counter_main_t *cm = &load_balance_main.lbm_to_counters;
      61             :   u32 n_left_from, n_left_to_next, *from, *to_next;
      62             :   ip_lookup_next_t next;
      63      229702 :   u32 thread_index = vm->thread_index;
      64             : 
      65      229702 :   from = vlib_frame_vector_args (frame);
      66      229702 :   n_left_from = frame->n_vectors;
      67      229702 :   next = node->cached_next_index;
      68             : 
      69      459404 :   while (n_left_from > 0)
      70             :     {
      71      229702 :       vlib_get_next_frame (vm, node, next, to_next, n_left_to_next);
      72             : 
      73     4972640 :       while (n_left_from >= 4 && n_left_to_next >= 2)
      74             :         {
      75             :           vlib_buffer_t *p0, *p1;
      76             :           u32 pi0, pi1, lbi0, lbi1, wrong_next;
      77             :           ip_lookup_next_t next0, next1;
      78             :           ip6_header_t *ip0, *ip1;
      79             :           ip6_address_t *dst_addr0, *dst_addr1;
      80             :           u32 flow_hash_config0, flow_hash_config1;
      81             :           const dpo_id_t *dpo0, *dpo1;
      82             :           const load_balance_t *lb0, *lb1;
      83             : 
      84             :           /* Prefetch next iteration. */
      85             :           {
      86             :             vlib_buffer_t *p2, *p3;
      87             : 
      88     4742940 :             p2 = vlib_get_buffer (vm, from[2]);
      89     4742940 :             p3 = vlib_get_buffer (vm, from[3]);
      90             : 
      91     4742940 :             vlib_prefetch_buffer_header (p2, LOAD);
      92     4742940 :             vlib_prefetch_buffer_header (p3, LOAD);
      93     4742940 :             CLIB_PREFETCH (p2->data, sizeof (ip0[0]), LOAD);
      94     4742940 :             CLIB_PREFETCH (p3->data, sizeof (ip0[0]), LOAD);
      95             :           }
      96             : 
      97     4742940 :           pi0 = to_next[0] = from[0];
      98     4742940 :           pi1 = to_next[1] = from[1];
      99             : 
     100     4742940 :           p0 = vlib_get_buffer (vm, pi0);
     101     4742940 :           p1 = vlib_get_buffer (vm, pi1);
     102             : 
     103     4742940 :           ip0 = vlib_buffer_get_current (p0);
     104     4742940 :           ip1 = vlib_buffer_get_current (p1);
     105             : 
     106     4742940 :           dst_addr0 = &ip0->dst_address;
     107     4742940 :           dst_addr1 = &ip1->dst_address;
     108             : 
     109     4742940 :           ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, p0);
     110     4742940 :           ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, p1);
     111             : 
     112     4742940 :           lbi0 = ip6_fib_table_fwding_lookup (vnet_buffer (p0)->ip.fib_index,
     113             :                                               dst_addr0);
     114     4742940 :           lbi1 = ip6_fib_table_fwding_lookup (vnet_buffer (p1)->ip.fib_index,
     115             :                                               dst_addr1);
     116             : 
     117     4742940 :           lb0 = load_balance_get (lbi0);
     118     4742940 :           lb1 = load_balance_get (lbi1);
     119     4742940 :           ASSERT (lb0->lb_n_buckets > 0);
     120     4742940 :           ASSERT (lb1->lb_n_buckets > 0);
     121     4742940 :           ASSERT (is_pow2 (lb0->lb_n_buckets));
     122     4742940 :           ASSERT (is_pow2 (lb1->lb_n_buckets));
     123             : 
     124     4742940 :           vnet_buffer (p0)->ip.flow_hash = vnet_buffer (p1)->ip.flow_hash = 0;
     125             : 
     126     4742940 :           if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
     127             :             {
     128         562 :               flow_hash_config0 = lb0->lb_hash_config;
     129        1124 :               vnet_buffer (p0)->ip.flow_hash =
     130         562 :                 ip6_compute_flow_hash (ip0, flow_hash_config0);
     131             :               dpo0 =
     132         562 :                 load_balance_get_fwd_bucket (lb0,
     133         562 :                                              (vnet_buffer (p0)->ip.flow_hash &
     134         562 :                                               (lb0->lb_n_buckets_minus_1)));
     135             :             }
     136             :           else
     137             :             {
     138     4742370 :               dpo0 = load_balance_get_bucket_i (lb0, 0);
     139             :             }
     140     4742940 :           if (PREDICT_FALSE (lb1->lb_n_buckets > 1))
     141             :             {
     142         562 :               flow_hash_config1 = lb1->lb_hash_config;
     143        1124 :               vnet_buffer (p1)->ip.flow_hash =
     144         562 :                 ip6_compute_flow_hash (ip1, flow_hash_config1);
     145             :               dpo1 =
     146         562 :                 load_balance_get_fwd_bucket (lb1,
     147         562 :                                              (vnet_buffer (p1)->ip.flow_hash &
     148         562 :                                               (lb1->lb_n_buckets_minus_1)));
     149             :             }
     150             :           else
     151             :             {
     152     4742370 :               dpo1 = load_balance_get_bucket_i (lb1, 0);
     153             :             }
     154     4742940 :           next0 = dpo0->dpoi_next_node;
     155     4742940 :           next1 = dpo1->dpoi_next_node;
     156             : 
     157             :           /* Only process the HBH Option Header if explicitly configured to do so */
     158     4742940 :           if (PREDICT_FALSE
     159             :               (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS))
     160             :             {
     161           0 :               next0 = (dpo_is_adj (dpo0) && im->hbh_enabled) ?
     162           0 :                 (ip_lookup_next_t) IP6_LOOKUP_NEXT_HOP_BY_HOP : next0;
     163             :             }
     164     4742940 :           if (PREDICT_FALSE
     165             :               (ip1->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS))
     166             :             {
     167           0 :               next1 = (dpo_is_adj (dpo1) && im->hbh_enabled) ?
     168           0 :                 (ip_lookup_next_t) IP6_LOOKUP_NEXT_HOP_BY_HOP : next1;
     169             :             }
     170     4742940 :           vnet_buffer (p0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
     171     4742940 :           vnet_buffer (p1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
     172             : 
     173     4742940 :           vlib_increment_combined_counter
     174             :             (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0));
     175     4742940 :           vlib_increment_combined_counter
     176             :             (cm, thread_index, lbi1, 1, vlib_buffer_length_in_chain (vm, p1));
     177             : 
     178     4742940 :           from += 2;
     179     4742940 :           to_next += 2;
     180     4742940 :           n_left_to_next -= 2;
     181     4742940 :           n_left_from -= 2;
     182             : 
     183     4742940 :           wrong_next = (next0 != next) + 2 * (next1 != next);
     184     4742940 :           if (PREDICT_FALSE (wrong_next != 0))
     185             :             {
     186        1911 :               switch (wrong_next)
     187             :                 {
     188           0 :                 case 1:
     189             :                   /* A B A */
     190           0 :                   to_next[-2] = pi1;
     191           0 :                   to_next -= 1;
     192           0 :                   n_left_to_next += 1;
     193           0 :                   vlib_set_next_frame_buffer (vm, node, next0, pi0);
     194           0 :                   break;
     195             : 
     196           0 :                 case 2:
     197             :                   /* A A B */
     198           0 :                   to_next -= 1;
     199           0 :                   n_left_to_next += 1;
     200           0 :                   vlib_set_next_frame_buffer (vm, node, next1, pi1);
     201           0 :                   break;
     202             : 
     203        1911 :                 case 3:
     204             :                   /* A B C */
     205        1911 :                   to_next -= 2;
     206        1911 :                   n_left_to_next += 2;
     207        1911 :                   vlib_set_next_frame_buffer (vm, node, next0, pi0);
     208        1911 :                   vlib_set_next_frame_buffer (vm, node, next1, pi1);
     209        1911 :                   if (next0 == next1)
     210             :                     {
     211             :                       /* A B B */
     212        1911 :                       vlib_put_next_frame (vm, node, next, n_left_to_next);
     213        1911 :                       next = next1;
     214        1911 :                       vlib_get_next_frame (vm, node, next, to_next,
     215             :                                            n_left_to_next);
     216             :                     }
     217             :                 }
     218             :             }
     219             :         }
     220             : 
     221      740040 :       while (n_left_from > 0 && n_left_to_next > 0)
     222             :         {
     223             :           vlib_buffer_t *p0;
     224             :           ip6_header_t *ip0;
     225             :           u32 pi0, lbi0;
     226             :           ip_lookup_next_t next0;
     227             :           load_balance_t *lb0;
     228             :           ip6_address_t *dst_addr0;
     229             :           u32 flow_hash_config0;
     230             :           const dpo_id_t *dpo0;
     231             : 
     232      510338 :           pi0 = from[0];
     233      510338 :           to_next[0] = pi0;
     234             : 
     235      510338 :           p0 = vlib_get_buffer (vm, pi0);
     236      510338 :           ip0 = vlib_buffer_get_current (p0);
     237      510338 :           dst_addr0 = &ip0->dst_address;
     238      510338 :           ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, p0);
     239      510338 :           lbi0 = ip6_fib_table_fwding_lookup (vnet_buffer (p0)->ip.fib_index,
     240             :                                               dst_addr0);
     241             : 
     242      510338 :           lb0 = load_balance_get (lbi0);
     243      510338 :           flow_hash_config0 = lb0->lb_hash_config;
     244             : 
     245      510338 :           vnet_buffer (p0)->ip.flow_hash = 0;
     246      510338 :           ASSERT (lb0->lb_n_buckets > 0);
     247      510338 :           ASSERT (is_pow2 (lb0->lb_n_buckets));
     248             : 
     249      510338 :           if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
     250             :             {
     251          25 :               flow_hash_config0 = lb0->lb_hash_config;
     252          50 :               vnet_buffer (p0)->ip.flow_hash =
     253          25 :                 ip6_compute_flow_hash (ip0, flow_hash_config0);
     254             :               dpo0 =
     255          25 :                 load_balance_get_fwd_bucket (lb0,
     256          25 :                                              (vnet_buffer (p0)->ip.flow_hash &
     257          25 :                                               (lb0->lb_n_buckets_minus_1)));
     258             :             }
     259             :           else
     260             :             {
     261      510313 :               dpo0 = load_balance_get_bucket_i (lb0, 0);
     262             :             }
     263             : 
     264      510338 :           dpo0 = load_balance_get_bucket_i (lb0,
     265      510338 :                                             (vnet_buffer (p0)->ip.flow_hash &
     266      510338 :                                              lb0->lb_n_buckets_minus_1));
     267      510338 :           next0 = dpo0->dpoi_next_node;
     268             : 
     269             :           /* Only process the HBH Option Header if explicitly configured to do so */
     270      510338 :           if (PREDICT_FALSE
     271             :               (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS))
     272             :             {
     273          10 :               next0 = (dpo_is_adj (dpo0) && im->hbh_enabled) ?
     274           6 :                 (ip_lookup_next_t) IP6_LOOKUP_NEXT_HOP_BY_HOP : next0;
     275             :             }
     276      510338 :           vnet_buffer (p0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
     277             : 
     278      510338 :           vlib_increment_combined_counter
     279             :             (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0));
     280             : 
     281      510338 :           from += 1;
     282      510338 :           to_next += 1;
     283      510338 :           n_left_to_next -= 1;
     284      510338 :           n_left_from -= 1;
     285             : 
     286      510338 :           if (PREDICT_FALSE (next0 != next))
     287             :             {
     288         775 :               n_left_to_next += 1;
     289         775 :               vlib_put_next_frame (vm, node, next, n_left_to_next);
     290         775 :               next = next0;
     291         775 :               vlib_get_next_frame (vm, node, next, to_next, n_left_to_next);
     292         775 :               to_next[0] = pi0;
     293         775 :               to_next += 1;
     294         775 :               n_left_to_next -= 1;
     295             :             }
     296             :         }
     297             : 
     298      229702 :       vlib_put_next_frame (vm, node, next, n_left_to_next);
     299             :     }
     300             : 
     301      229702 :   if (node->flags & VLIB_NODE_FLAG_TRACE)
     302        3260 :     ip6_forward_next_trace (vm, node, frame, VLIB_TX);
     303             : 
     304      229702 :   return frame->n_vectors;
     305             : }
     306             : 
     307             : #endif /*__included_ip6_forward_h__ */
     308             : 
     309             : /*
     310             :  * fd.io coding-style-patch-verification: ON
     311             :  *
     312             :  * Local Variables:
     313             :  * eval: (c-set-style "gnu")
     314             :  * End:
     315             :  */

Generated by: LCOV version 1.14