LCOV - code coverage report
Current view: top level - vnet/mfib - mfib_forward.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 155 158 98.1 %
Date: 2023-10-26 01:39:38 Functions: 35 47 74.5 %

          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             : #include <vnet/mfib/mfib_itf.h>
      17             : #include <vnet/mfib/mfib_entry.h>
      18             : #include <vnet/dpo/replicate_dpo.h>
      19             : #include <vnet/mfib/ip4_mfib.h>
      20             : #include <vnet/mfib/ip6_mfib.h>
      21             : #include <vnet/mfib/mfib_signal.h>
      22             : #include <vnet/fib/ip4_fib.h>
      23             : #include <vnet/fib/ip6_fib.h>
      24             : 
      25             : #include <vnet/ip/ip4.h>
      26             : #include <vnet/vnet.h>
      27             : 
      28             : typedef struct mfib_forward_lookup_trace_t_ {
      29             :     u32 entry_index;
      30             :     u32 fib_index;
      31             : } mfib_forward_lookup_trace_t;
      32             : 
      33             : static u8 *
      34        2964 : format_mfib_forward_lookup_trace (u8 * s, va_list * args)
      35             : {
      36        2964 :     CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
      37        2964 :     CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
      38        2964 :     mfib_forward_lookup_trace_t * t = va_arg (*args, mfib_forward_lookup_trace_t *);
      39             : 
      40        2964 :     s = format (s, "fib %d entry %d", t->fib_index, t->entry_index);
      41        2964 :     return s;
      42             : }
      43             : 
      44             : /* Common trace function for all ip4-forward next nodes. */
      45             : static void
      46        1712 : mfib_forward_lookup_trace (vlib_main_t * vm,
      47             :                            vlib_node_runtime_t * node,
      48             :                            vlib_frame_t * frame)
      49             : {
      50             :     u32 * from, n_left;
      51        1712 :     ip4_main_t * im = &ip4_main;
      52             : 
      53        1712 :     n_left = frame->n_vectors;
      54        1712 :     from = vlib_frame_vector_args (frame);
      55             : 
      56        3117 :     while (n_left >= 4)
      57             :     {
      58             :         mfib_forward_lookup_trace_t * t0, * t1;
      59             :         vlib_buffer_t * b0, * b1;
      60             :         u32 bi0, bi1;
      61             : 
      62             :         /* Prefetch next iteration. */
      63        1405 :         vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
      64        1405 :         vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
      65             : 
      66        1405 :         bi0 = from[0];
      67        1405 :         bi1 = from[1];
      68             : 
      69        1405 :         b0 = vlib_get_buffer (vm, bi0);
      70        1405 :         b1 = vlib_get_buffer (vm, bi1);
      71             : 
      72        1405 :         if (b0->flags & VLIB_BUFFER_IS_TRACED)
      73             :         {
      74        1405 :             t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
      75        1405 :             t0->entry_index = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
      76        1405 :             t0->fib_index = vec_elt (im->mfib_index_by_sw_if_index,
      77             :                                      vnet_buffer(b1)->sw_if_index[VLIB_RX]);
      78             :         }
      79        1405 :         if (b1->flags & VLIB_BUFFER_IS_TRACED)
      80             :         {
      81        1405 :             t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
      82        1405 :             t1->entry_index = vnet_buffer (b1)->ip.adj_index[VLIB_TX];
      83        1405 :             t1->fib_index = vec_elt (im->mfib_index_by_sw_if_index,
      84             :                                      vnet_buffer(b1)->sw_if_index[VLIB_RX]);
      85             :         }
      86        1405 :         from += 2;
      87        1405 :         n_left -= 2;
      88             :     }
      89             : 
      90        3490 :     while (n_left >= 1)
      91             :     {
      92             :         mfib_forward_lookup_trace_t * t0;
      93             :         vlib_buffer_t * b0;
      94             :         u32 bi0;
      95             : 
      96        1778 :         bi0 = from[0];
      97             : 
      98        1778 :         b0 = vlib_get_buffer (vm, bi0);
      99             : 
     100        1778 :         if (b0->flags & VLIB_BUFFER_IS_TRACED)
     101             :         {
     102        1778 :             t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
     103        1778 :             t0->entry_index = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
     104        1778 :             t0->fib_index = vec_elt (im->mfib_index_by_sw_if_index,
     105             :                                      vnet_buffer(b0)->sw_if_index[VLIB_RX]);
     106             :         }
     107        1778 :         from += 1;
     108        1778 :         n_left -= 1;
     109             :     }
     110        1712 : }
     111             : 
     112             : typedef enum mfib_forward_lookup_next_t_ {
     113             :     MFIB_FORWARD_LOOKUP_NEXT_RPF,
     114             :     MFIB_FORWARD_LOOKUP_N_NEXT,
     115             : } mfib_forward_lookup_next_t;
     116             : 
     117             : static uword
     118        2190 : mfib_forward_lookup (vlib_main_t * vm,
     119             :                      vlib_node_runtime_t * node,
     120             :                      vlib_frame_t * frame,
     121             :                      int is_v4)
     122             : {
     123             :     u32 n_left_from, n_left_to_next, * from, * to_next;
     124             : 
     125        2190 :     from = vlib_frame_vector_args (frame);
     126        2190 :     n_left_from = frame->n_vectors;
     127             : 
     128        4380 :     while (n_left_from > 0)
     129             :     {
     130        2190 :         vlib_get_next_frame (vm, node, MFIB_FORWARD_LOOKUP_NEXT_RPF,
     131             :                              to_next, n_left_to_next);
     132             : 
     133        7355 :         while (n_left_from > 0 && n_left_to_next > 0)
     134             :         {
     135             :             fib_node_index_t mfei0;
     136             :             vlib_buffer_t * p0;
     137             :             u32 fib_index0;
     138             :             u32 pi0;
     139             : 
     140        5165 :             pi0 = from[0];
     141        5165 :             to_next[0] = pi0;
     142        5165 :             from += 1;
     143        5165 :             to_next += 1;
     144        5165 :             n_left_to_next -= 1;
     145        5165 :             n_left_from -= 1;
     146             : 
     147        5165 :             p0 = vlib_get_buffer (vm, pi0);
     148             : 
     149        5165 :             if (is_v4)
     150             :             {
     151             :                 ip4_header_t * ip0;
     152             : 
     153        2090 :                 ip_lookup_set_buffer_fib_index (
     154             :                   ip4_main.fib_index_by_sw_if_index, p0);
     155        2090 :                 fib_index0 = vec_elt (ip4_main.mfib_index_by_sw_if_index,
     156             :                                       vnet_buffer (p0)->sw_if_index[VLIB_RX]);
     157        2090 :                 ip0 = vlib_buffer_get_current (p0);
     158        2090 :                 mfei0 = ip4_mfib_table_lookup (ip4_mfib_get (fib_index0),
     159        2090 :                                                &ip0->src_address,
     160        2090 :                                                &ip0->dst_address, 64);
     161             :             }
     162             :             else
     163             :               {
     164             :                 ip6_header_t *ip0;
     165             : 
     166        3075 :                 ip_lookup_set_buffer_fib_index (
     167             :                   ip6_main.fib_index_by_sw_if_index, p0);
     168        3075 :                 fib_index0 = vec_elt (ip6_main.mfib_index_by_sw_if_index,
     169             :                                       vnet_buffer (p0)->sw_if_index[VLIB_RX]);
     170        3075 :                 ip0 = vlib_buffer_get_current (p0);
     171        3075 :                 mfei0 = ip6_mfib_table_fwd_lookup (ip6_mfib_get (fib_index0),
     172        3075 :                                                    &ip0->src_address,
     173        3075 :                                                    &ip0->dst_address);
     174             :               }
     175             : 
     176        5165 :             vnet_buffer (p0)->ip.adj_index[VLIB_TX] = mfei0;
     177             :         }
     178             : 
     179        2190 :         vlib_put_next_frame (vm, node, MFIB_FORWARD_LOOKUP_NEXT_RPF,
     180             :                              n_left_to_next);
     181             :     }
     182             : 
     183        2190 :     if (node->flags & VLIB_NODE_FLAG_TRACE)
     184        1712 :         mfib_forward_lookup_trace(vm, node, frame);
     185             : 
     186        2190 :     return frame->n_vectors;
     187             : }
     188             : 
     189        2334 : VLIB_NODE_FN (ip4_mfib_forward_lookup_node) (vlib_main_t * vm,
     190             :                          vlib_node_runtime_t * node,
     191             :                          vlib_frame_t * frame)
     192             : {
     193          34 :     return (mfib_forward_lookup (vm, node, frame, 1));
     194             : }
     195             : 
     196      183788 : VLIB_REGISTER_NODE (ip4_mfib_forward_lookup_node) = {
     197             :     .name = "ip4-mfib-forward-lookup",
     198             :     .vector_size = sizeof (u32),
     199             : 
     200             :     .format_trace = format_mfib_forward_lookup_trace,
     201             : 
     202             :     .n_next_nodes = MFIB_FORWARD_LOOKUP_N_NEXT,
     203             :     .next_nodes = {
     204             :         [MFIB_FORWARD_LOOKUP_NEXT_RPF] = "ip4-mfib-forward-rpf",
     205             :     },
     206             : };
     207             : 
     208        4456 : VLIB_NODE_FN (ip6_mfib_forward_lookup_node) (vlib_main_t * vm,
     209             :                          vlib_node_runtime_t * node,
     210             :                          vlib_frame_t * frame)
     211             : {
     212        2156 :     return (mfib_forward_lookup (vm, node, frame, 0));
     213             : }
     214             : 
     215      183788 : VLIB_REGISTER_NODE (ip6_mfib_forward_lookup_node) = {
     216             :     .name = "ip6-mfib-forward-lookup",
     217             :     .vector_size = sizeof (u32),
     218             : 
     219             :     .format_trace = format_mfib_forward_lookup_trace,
     220             : 
     221             :     .n_next_nodes = MFIB_FORWARD_LOOKUP_N_NEXT,
     222             :     .next_nodes = {
     223             :         [MFIB_FORWARD_LOOKUP_NEXT_RPF] = "ip6-mfib-forward-rpf",
     224             :     },
     225             : };
     226             : 
     227             : 
     228             : typedef struct mfib_forward_rpf_trace_t_ {
     229             :     u32 entry_index;
     230             :     u32 sw_if_index;
     231             :     mfib_itf_flags_t itf_flags;
     232             : } mfib_forward_rpf_trace_t;
     233             : 
     234             : typedef enum mfib_forward_rpf_next_t_ {
     235             :     MFIB_FORWARD_RPF_NEXT_DROP,
     236             :     MFIB_FORWARD_RPF_N_NEXT,
     237             : } mfib_forward_rpf_next_t;
     238             : 
     239             : static u8 *
     240        3952 : format_mfib_forward_rpf_trace (u8 * s, va_list * args)
     241             : {
     242        3952 :     CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
     243        3952 :     CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
     244        3952 :     mfib_forward_rpf_trace_t * t = va_arg (*args, mfib_forward_rpf_trace_t *);
     245             : 
     246        3952 :     s = format (s, "entry %d", t->entry_index);
     247        3952 :     s = format (s, " itf %d", t->sw_if_index);
     248        3952 :     s = format (s, " flags %U", format_mfib_itf_flags, t->itf_flags);
     249             : 
     250        3952 :     return s;
     251             : }
     252             : 
     253             : static int
     254         364 : mfib_forward_connected_check (vlib_buffer_t * b0,
     255             :                               u32 sw_if_index,
     256             :                               int is_v4)
     257             : {
     258             :     /*
     259             :      * Lookup the source of the IP packet in the
     260             :      * FIB. return true if the entry is attached.
     261             :      */
     262             :     index_t lbi0;
     263             : 
     264         364 :     if (is_v4)
     265             :     {
     266             :         load_balance_t *lb0;
     267             :         ip4_header_t *ip0;
     268             : 
     269         364 :         ip0 = vlib_buffer_get_current(b0);
     270             : 
     271         364 :         lbi0 = ip4_fib_forwarding_lookup(
     272             :                    ip4_fib_table_get_index_for_sw_if_index(
     273             :                        sw_if_index),
     274         364 :                    &ip0->src_address);
     275         364 :         lb0 = load_balance_get(lbi0);
     276             : 
     277         364 :         return (FIB_ENTRY_FLAG_ATTACHED &
     278         364 :                 lb0->lb_fib_entry_flags);
     279             :     }
     280             :     else
     281             :     {
     282           0 :         ASSERT(0);
     283             :     }
     284           0 :     return (0);
     285             : }
     286             : 
     287             : static void
     288         637 : mfib_forward_itf_signal (vlib_main_t *vm,
     289             :                          const mfib_entry_t *mfe,
     290             :                          mfib_itf_t *mfi,
     291             :                          vlib_buffer_t *b0)
     292             : {
     293             :     mfib_itf_flags_t old_flags;
     294             : 
     295         637 :     old_flags = clib_atomic_fetch_or(&mfi->mfi_flags,
     296             :                                      MFIB_ITF_FLAG_SIGNAL_PRESENT);
     297             : 
     298         637 :     if (!(old_flags & MFIB_ITF_FLAG_SIGNAL_PRESENT))
     299             :     {
     300             :         /*
     301             :          * we were the lucky ones to set the signal present flag
     302             :          */
     303           7 :         if (!(old_flags & MFIB_ITF_FLAG_DONT_PRESERVE))
     304             :         {
     305             :             /*
     306             :              * preserve a copy of the packet for the control
     307             :              * plane to examine.
     308             :              * Only allow one preserved packet at at time, since
     309             :              * when the signal present flag is cleared so is the
     310             :              * preserved packet.
     311             :              */
     312           7 :             mfib_signal_push(mfe, mfi, b0);
     313             :         }
     314             :         else
     315             :         {
     316             :             /*
     317             :              *  The control plane just wants the signal, not the packet as well
     318             :              */
     319           0 :             mfib_signal_push(mfe, mfi, NULL);
     320             :         }
     321             :     }
     322             :     /*
     323             :      * else
     324             :      *   there is already a signal present on this interface that the
     325             :      *   control plane has not yet acknowledged
     326             :      */
     327         637 : }
     328             : 
     329             : always_inline uword
     330        2209 : mfib_forward_rpf (vlib_main_t * vm,
     331             :                   vlib_node_runtime_t * node,
     332             :                   vlib_frame_t * frame,
     333             :                   int is_v4)
     334             : {
     335             :     u32 n_left_from, n_left_to_next, * from, * to_next;
     336             :     mfib_forward_rpf_next_t next;
     337             :     vlib_node_runtime_t *error_node;
     338             : 
     339        2209 :     if (is_v4)
     340          45 :         error_node = vlib_node_get_runtime (vm, ip4_input_node.index);
     341             :     else
     342        2164 :         error_node = vlib_node_get_runtime (vm, ip6_input_node.index);
     343        2209 :     from = vlib_frame_vector_args (frame);
     344        2209 :     n_left_from = frame->n_vectors;
     345        2209 :     next = MFIB_FORWARD_RPF_NEXT_DROP;
     346             : 
     347        4418 :     while (n_left_from > 0)
     348             :     {
     349        2209 :         vlib_get_next_frame (vm, node, next,
     350             :                              to_next, n_left_to_next);
     351             : 
     352        9055 :         while (n_left_from > 0 && n_left_to_next > 0)
     353             :         {
     354             :             fib_node_index_t mfei0;
     355             :             const mfib_entry_t *mfe0;
     356             :             mfib_itf_t *mfi0;
     357             :             vlib_buffer_t * b0;
     358             :             u32 pi0, next0;
     359             :             mfib_itf_flags_t iflags0;
     360             :             mfib_entry_flags_t eflags0;
     361             :             u8 error0;
     362             : 
     363        6846 :             pi0 = from[0];
     364        6846 :             to_next[0] = pi0;
     365        6846 :             from += 1;
     366        6846 :             to_next += 1;
     367        6846 :             n_left_to_next -= 1;
     368        6846 :             n_left_from -= 1;
     369             : 
     370        6846 :             error0 = IP4_ERROR_NONE;
     371        6846 :             b0 = vlib_get_buffer (vm, pi0);
     372        6846 :             mfei0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
     373        6846 :             mfe0 = mfib_entry_get(mfei0);
     374        6846 :             mfi0 = mfib_entry_get_itf(mfe0,
     375        6846 :                                       vnet_buffer(b0)->sw_if_index[VLIB_RX]);
     376             : 
     377             :             /*
     378             :              * throughout this function we are 'PREDICT' optimising
     379             :              * for the case of throughput traffic that is not replicated
     380             :              * to the host stack nor sets local flags
     381             :              */
     382             : 
     383             :             /*
     384             :              * If the mfib entry has a configured RPF-ID check that
     385             :              * in preference to an interface based RPF
     386             :              */
     387        6846 :             if (MFIB_RPF_ID_NONE != mfe0->mfe_rpf_id)
     388             :             {
     389        1423 :                 iflags0 = (mfe0->mfe_rpf_id == vnet_buffer(b0)->ip.rpf_id ?
     390        1423 :                            MFIB_ITF_FLAG_ACCEPT :
     391             :                            MFIB_ITF_FLAG_NONE);
     392             :             }
     393             :             else
     394             :             {
     395        5423 :                 if (PREDICT_TRUE(NULL != mfi0))
     396             :                 {
     397        4974 :                     iflags0 = mfi0->mfi_flags;
     398             :                 }
     399             :                 else
     400             :                 {
     401         449 :                     iflags0 = MFIB_ITF_FLAG_NONE;
     402             :                 }
     403             :             }
     404        6846 :             eflags0 = mfe0->mfe_flags;
     405             : 
     406        6846 :             if (PREDICT_FALSE(eflags0 & MFIB_ENTRY_FLAG_CONNECTED))
     407             :             {
     408             :                 /*
     409             :                  * lookup the source in the unicast FIB - check it
     410             :                  * matches a connected.
     411             :                  */
     412         364 :                 if (mfib_forward_connected_check(
     413             :                         b0,
     414         364 :                         vnet_buffer(b0)->sw_if_index[VLIB_RX],
     415             :                         is_v4))
     416             :                 {
     417         364 :                     mfib_forward_itf_signal(vm, mfe0, mfi0, b0);
     418             :                 }
     419             :             }
     420        6846 :             if (PREDICT_FALSE((eflags0 & MFIB_ENTRY_FLAG_SIGNAL) ^
     421             :                               (iflags0 & MFIB_ITF_FLAG_NEGATE_SIGNAL)))
     422             :             {
     423             :                 /*
     424             :                  * Entry signal XOR interface negate-signal
     425             :                  */
     426         273 :                 if (NULL != mfi0)
     427             :                 {
     428         273 :                     mfib_forward_itf_signal(vm, mfe0, mfi0, b0);
     429             :                 }
     430             :             }
     431             : 
     432        6846 :             if (PREDICT_TRUE((iflags0 & MFIB_ITF_FLAG_ACCEPT) ||
     433             :                              (eflags0 & MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF)))
     434             :             {
     435             :                 /*
     436             :                  * This interface is accepting packets for the matching entry
     437             :                  */
     438        5801 :                 next0 = mfe0->mfe_rep.dpoi_next_node;
     439             : 
     440        5801 :                 vnet_buffer(b0)->ip.adj_index[VLIB_TX] =
     441        5801 :                     mfe0->mfe_rep.dpoi_index;
     442             :             }
     443             :             else
     444             :             {
     445        1045 :                 next0 = MFIB_FORWARD_RPF_NEXT_DROP;
     446        1045 :                 error0 =
     447             :                   (is_v4 ? IP4_ERROR_RPF_FAILURE : IP6_ERROR_RPF_FAILURE);
     448             :             }
     449             : 
     450        6846 :             b0->error = error0 ? error_node->errors[error0] : 0;
     451             : 
     452        6846 :             if (b0->flags & VLIB_BUFFER_IS_TRACED)
     453             :               {
     454             :                 mfib_forward_rpf_trace_t *t0;
     455             : 
     456        6269 :                 t0 = vlib_add_trace (vm, node, b0, sizeof (*t0));
     457        6269 :                 t0->entry_index = mfei0;
     458        6269 :                 t0->itf_flags = iflags0;
     459        6269 :                 if (NULL == mfi0)
     460             :                   {
     461        1872 :                     t0->sw_if_index = ~0;
     462             :                   }
     463             :                 else
     464             :                   {
     465        4397 :                     t0->sw_if_index = mfi0->mfi_sw_if_index;
     466             :                   }
     467             :               }
     468        6846 :             vlib_validate_buffer_enqueue_x1 (vm, node, next, to_next,
     469             :                                              n_left_to_next, pi0, next0);
     470             :         }
     471             : 
     472        2209 :         vlib_put_next_frame (vm, node, next, n_left_to_next);
     473             :     }
     474             : 
     475        2209 :     return frame->n_vectors;
     476             : }
     477             : 
     478        2345 : VLIB_NODE_FN (ip4_mfib_forward_rpf_node) (vlib_main_t * vm,
     479             :                       vlib_node_runtime_t * node,
     480             :                       vlib_frame_t * frame)
     481             : {
     482          45 :     return (mfib_forward_rpf(vm, node, frame, 1));
     483             : }
     484             : 
     485             : 
     486      183788 : VLIB_REGISTER_NODE (ip4_mfib_forward_rpf_node) = {
     487             :     .name = "ip4-mfib-forward-rpf",
     488             :     .vector_size = sizeof (u32),
     489             : 
     490             :     .format_trace = format_mfib_forward_rpf_trace,
     491             : 
     492             :     .n_next_nodes = MFIB_FORWARD_RPF_N_NEXT,
     493             :     .next_nodes = {
     494             :         [MFIB_FORWARD_RPF_NEXT_DROP] = "ip4-drop",
     495             :     },
     496             : };
     497             : 
     498        4464 : VLIB_NODE_FN (ip6_mfib_forward_rpf_node) (vlib_main_t * vm,
     499             :                       vlib_node_runtime_t * node,
     500             :                       vlib_frame_t * frame)
     501             : {
     502        2164 :     return (mfib_forward_rpf(vm, node, frame, 0));
     503             : }
     504             : 
     505             : 
     506      183788 : VLIB_REGISTER_NODE (ip6_mfib_forward_rpf_node) = {
     507             :     .name = "ip6-mfib-forward-rpf",
     508             :     .vector_size = sizeof (u32),
     509             : 
     510             :     .format_trace = format_mfib_forward_rpf_trace,
     511             : 
     512             :     .n_next_nodes = MFIB_FORWARD_RPF_N_NEXT,
     513             :     .next_nodes = {
     514             :         [MFIB_FORWARD_RPF_NEXT_DROP] = "ip6-drop",
     515             :     },
     516             : };
     517             : 

Generated by: LCOV version 1.14