LCOV - code coverage report
Current view: top level - vnet/l2 - l2_bvi.h (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 28 36 77.8 %
Date: 2023-07-05 22:20:52 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /*
       2             :  * l2_bvi.h : layer 2 Bridged Virtual Interface
       3             :  *
       4             :  * Copyright (c) 2013 Cisco and/or its affiliates.
       5             :  * Licensed under the Apache License, Version 2.0 (the "License");
       6             :  * you may not use this file except in compliance with the License.
       7             :  * You may obtain a copy of the License at:
       8             :  *
       9             :  *     http://www.apache.org/licenses/LICENSE-2.0
      10             :  *
      11             :  * Unless required by applicable law or agreed to in writing, software
      12             :  * distributed under the License is distributed on an "AS IS" BASIS,
      13             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14             :  * See the License for the specific language governing permissions and
      15             :  * limitations under the License.
      16             :  */
      17             : 
      18             : #ifndef included_l2bvi_h
      19             : #define included_l2bvi_h
      20             : 
      21             : #include <vlib/vlib.h>
      22             : #include <vnet/ethernet/ethernet.h>
      23             : #include <vppinfra/sparse_vec.h>
      24             : 
      25             : #include <vnet/l2/l2_input.h>
      26             : 
      27             : #define TO_BVI_ERR_OK        0
      28             : #define TO_BVI_ERR_BAD_MAC   1
      29             : #define TO_BVI_ERR_ETHERTYPE 2
      30             : 
      31             : static_always_inline u32
      32        1649 : l2_to_bvi_dmac_check (vnet_hw_interface_t * hi, u8 * dmac,
      33             :                       ethernet_interface_t * ei, u8 have_sec_dmac)
      34             : {
      35             :   ethernet_interface_address_t *sec_addr;
      36             : 
      37        1649 :   if (ethernet_mac_address_equal (dmac, hi->hw_address))
      38        1649 :     return TO_BVI_ERR_OK;
      39             : 
      40           0 :   if (have_sec_dmac)
      41             :     {
      42           0 :       vec_foreach (sec_addr, ei->secondary_addrs)
      43             :       {
      44           0 :         if (ethernet_mac_address_equal (dmac, sec_addr->mac.bytes))
      45           0 :           return TO_BVI_ERR_OK;
      46             :       }
      47             :     }
      48             : 
      49           0 :   return TO_BVI_ERR_BAD_MAC;
      50             : }
      51             : 
      52             : /**
      53             :  * Send a packet from L2 processing to L3 via the BVI interface.
      54             :  * Set next0 to the proper L3 input node.
      55             :  * Return an error if the packet isn't what we expect.
      56             :  */
      57             : 
      58             : static_always_inline u32
      59        1931 : l2_to_bvi (vlib_main_t * vlib_main,
      60             :            vnet_main_t * vnet_main,
      61             :            vlib_buffer_t * b0,
      62             :            u32 bvi_sw_if_index, next_by_ethertype_t * l3_next, u16 * next0)
      63             : {
      64        1931 :   ethernet_main_t *em = &ethernet_main;
      65             : 
      66             :   /* Perform L3 my-mac filter */
      67        1931 :   ethernet_header_t *e0 = vlib_buffer_get_current (b0);
      68        1931 :   if (!ethernet_address_cast (e0->dst_address))
      69             :     {
      70             :       vnet_hw_interface_t *hi =
      71        1649 :         vnet_get_sup_hw_interface (vnet_main, bvi_sw_if_index);
      72        1649 :       ethernet_interface_t *ei = ethernet_get_interface (em, hi->hw_if_index);
      73             :       u32 rv;
      74             : 
      75        1649 :       if (PREDICT_FALSE (ei && (vec_len (ei->secondary_addrs) > 0)))
      76        1649 :         rv = l2_to_bvi_dmac_check (hi, e0->dst_address, ei,
      77             :                                    1 /* have_sec_dmac */ );
      78             :       else
      79           0 :         rv = l2_to_bvi_dmac_check (hi, e0->dst_address, ei,
      80             :                                    0 /* have_sec_dmac */ );
      81             : 
      82        1649 :       if (rv != TO_BVI_ERR_OK)
      83           0 :         return rv;
      84             :     }
      85             : 
      86             :   /* Save L2 header position which may be changed due to packet replication */
      87        1931 :   vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
      88             : 
      89             :   /* Strip L2 header */
      90        1931 :   u8 l2_len = vnet_buffer (b0)->l2.l2_len;
      91        1931 :   vlib_buffer_advance (b0, l2_len);
      92             : 
      93        1931 :   u8 *l3h = vlib_buffer_get_current (b0);
      94        1931 :   u16 ethertype = clib_net_to_host_u16 (*(u16 *) (l3h - 2));
      95             : 
      96             :   /* Set the input interface to be the BVI interface */
      97        1931 :   vnet_buffer (b0)->sw_if_index[VLIB_RX] = bvi_sw_if_index;
      98        1931 :   vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
      99             : 
     100             :   /* Go to appropriate L3 input node */
     101        1931 :   if (ethertype == ETHERNET_TYPE_IP4)
     102             :     {
     103        1773 :       *next0 = l3_next->input_next_ip4;
     104             :     }
     105         158 :   else if (ethertype == ETHERNET_TYPE_IP6)
     106             :     {
     107         144 :       *next0 = l3_next->input_next_ip6;
     108             :     }
     109             :   else
     110             :     {
     111             :       /* uncommon ethertype, check table */
     112          14 :       u32 i0 = sparse_vec_index (l3_next->input_next_by_type, ethertype);
     113          14 :       *next0 = vec_elt (l3_next->input_next_by_type, i0);
     114             : 
     115          14 :       if (i0 == SPARSE_VEC_INVALID_INDEX)
     116             :         {
     117           0 :           return TO_BVI_ERR_ETHERTYPE;
     118             :         }
     119             :     }
     120             : 
     121             :   /* increment BVI RX interface stat */
     122        1931 :   vlib_increment_combined_counter
     123             :     (vnet_main->interface_main.combined_sw_if_counters
     124             :      + VNET_INTERFACE_COUNTER_RX,
     125             :      vlib_main->thread_index, bvi_sw_if_index,
     126             :      1, vlib_buffer_length_in_chain (vlib_main, b0));
     127        1931 :   return TO_BVI_ERR_OK;
     128             : }
     129             : 
     130             : void
     131             : l2bvi_register_input_type (vlib_main_t * vm,
     132             :                            ethernet_type_t type, u32 node_index);
     133             : 
     134             : extern int l2_bvi_create (u32 instance, const mac_address_t * mac,
     135             :                           u32 * sw_if_index);
     136             : extern int l2_bvi_delete (u32 sw_if_index);
     137             : 
     138             : #endif
     139             : 
     140             : /*
     141             :  * fd.io coding-style-patch-verification: ON
     142             :  *
     143             :  * Local Variables:
     144             :  * eval: (c-set-style "gnu")
     145             :  * End:
     146             :  */

Generated by: LCOV version 1.14