LCOV - code coverage report
Current view: top level - vnet/l2 - l2_api.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 384 634 60.6 %
Date: 2023-10-26 01:39:38 Functions: 32 46 69.6 %

          Line data    Source code
       1             : /*
       2             :  *------------------------------------------------------------------
       3             :  * l2_api.c - layer 2 forwarding api
       4             :  *
       5             :  * Copyright (c) 2016 Cisco and/or its affiliates.
       6             :  * Copyright (c) 2022 Nordix Foundation.
       7             :  * Licensed under the Apache License, Version 2.0 (the "License");
       8             :  * you may not use this file except in compliance with the License.
       9             :  * You may obtain a copy of the License at:
      10             :  *
      11             :  *     http://www.apache.org/licenses/LICENSE-2.0
      12             :  *
      13             :  * Unless required by applicable law or agreed to in writing, software
      14             :  * distributed under the License is distributed on an "AS IS" BASIS,
      15             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      16             :  * See the License for the specific language governing permissions and
      17             :  * limitations under the License.
      18             :  *------------------------------------------------------------------
      19             :  */
      20             : 
      21             : #include <vnet/vnet.h>
      22             : #include <vlibmemory/api.h>
      23             : 
      24             : #include <vnet/interface.h>
      25             : #include <vnet/api_errno.h>
      26             : #include <vnet/l2/l2_input.h>
      27             : #include <vnet/l2/l2_fib.h>
      28             : #include <vnet/l2/l2_vtr.h>
      29             : #include <vnet/l2/l2_learn.h>
      30             : #include <vnet/l2/l2_bd.h>
      31             : #include <vnet/l2/l2_bvi.h>
      32             : #include <vnet/l2/l2_arp_term.h>
      33             : #include <vnet/ip/ip_types_api.h>
      34             : #include <vnet/ethernet/ethernet_types_api.h>
      35             : 
      36             : #include <vnet/format_fns.h>
      37             : #include <vnet/l2/l2.api_enum.h>
      38             : #include <vnet/l2/l2.api_types.h>
      39             : 
      40             : #define REPLY_MSG_ID_BASE l2input_main.msg_id_base
      41             : #include <vlibapi/api_helper_macros.h>
      42             : 
      43             : static void
      44           0 : send_l2_xconnect_details (vl_api_registration_t * reg, u32 context,
      45             :                           u32 rx_sw_if_index, u32 tx_sw_if_index)
      46             : {
      47             :   vl_api_l2_xconnect_details_t *mp;
      48             : 
      49           0 :   mp = vl_msg_api_alloc (sizeof (*mp));
      50           0 :   clib_memset (mp, 0, sizeof (*mp));
      51           0 :   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_L2_XCONNECT_DETAILS);
      52           0 :   mp->context = context;
      53           0 :   mp->rx_sw_if_index = htonl (rx_sw_if_index);
      54           0 :   mp->tx_sw_if_index = htonl (tx_sw_if_index);
      55             : 
      56           0 :   vl_api_send_msg (reg, (u8 *) mp);
      57           0 : }
      58             : 
      59             : static void
      60           0 : vl_api_l2_xconnect_dump_t_handler (vl_api_l2_xconnect_dump_t * mp)
      61             : {
      62             :   vl_api_registration_t *reg;
      63           0 :   l2input_main_t *l2im = &l2input_main;
      64             :   u32 sw_if_index;
      65             :   l2_input_config_t *config;
      66             : 
      67           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
      68           0 :   if (!reg)
      69           0 :     return;
      70             : 
      71             :   /* *INDENT-OFF* */
      72           0 :   vec_foreach_index (sw_if_index, l2im->configs)
      73             :     {
      74           0 :       config = vec_elt_at_index (l2im->configs, sw_if_index);
      75           0 :       if (l2_input_is_xconnect (config))
      76           0 :         send_l2_xconnect_details (reg, mp->context, sw_if_index,
      77             :                                   config->output_sw_if_index);
      78             :     }
      79             :   /* *INDENT-ON* */
      80             : }
      81             : 
      82             : static void
      83           0 : vl_api_l2_fib_clear_table_t_handler (vl_api_l2_fib_clear_table_t * mp)
      84             : {
      85           0 :   int rv = 0;
      86             :   vl_api_l2_fib_clear_table_reply_t *rmp;
      87             : 
      88             :   /* Clear all MACs including static MACs  */
      89           0 :   l2fib_clear_table ();
      90             : 
      91           0 :   REPLY_MACRO (VL_API_L2_FIB_CLEAR_TABLE_REPLY);
      92             : }
      93             : 
      94             : static void
      95          39 : send_l2fib_table_entry (vpe_api_main_t * am,
      96             :                         vl_api_registration_t * reg,
      97             :                         l2fib_entry_key_t * l2fe_key,
      98             :                         l2fib_entry_result_t * l2fe_res, u32 context)
      99             : {
     100             :   vl_api_l2_fib_table_details_t *mp;
     101             : 
     102          39 :   mp = vl_msg_api_alloc (sizeof (*mp));
     103          39 :   clib_memset (mp, 0, sizeof (*mp));
     104          39 :   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_L2_FIB_TABLE_DETAILS);
     105             : 
     106          39 :   mp->bd_id =
     107          39 :     ntohl (l2input_main.bd_configs[l2fe_key->fields.bd_index].bd_id);
     108             : 
     109          39 :   mac_address_encode ((mac_address_t *) l2fe_key->fields.mac, mp->mac);
     110          39 :   mp->sw_if_index = ntohl (l2fe_res->fields.sw_if_index);
     111          39 :   mp->static_mac = (l2fib_entry_result_is_set_STATIC (l2fe_res) ? 1 : 0);
     112          39 :   mp->filter_mac = (l2fib_entry_result_is_set_FILTER (l2fe_res) ? 1 : 0);
     113          39 :   mp->bvi_mac = (l2fib_entry_result_is_set_BVI (l2fe_res) ? 1 : 0);
     114          39 :   mp->context = context;
     115             : 
     116          39 :   vl_api_send_msg (reg, (u8 *) mp);
     117          39 : }
     118             : 
     119             : static void
     120          19 : vl_api_l2_fib_table_dump_t_handler (vl_api_l2_fib_table_dump_t * mp)
     121             : {
     122          19 :   vpe_api_main_t *am = &vpe_api_main;
     123          19 :   bd_main_t *bdm = &bd_main;
     124          19 :   l2fib_entry_key_t *l2fe_key = NULL;
     125          19 :   l2fib_entry_result_t *l2fe_res = NULL;
     126          19 :   u32 ni, bd_id = ntohl (mp->bd_id);
     127             :   u32 bd_index;
     128             :   vl_api_registration_t *reg;
     129             :   uword *p;
     130             : 
     131          19 :   reg = vl_api_client_index_to_registration (mp->client_index);
     132          19 :   if (!reg)
     133           8 :     return;
     134             : 
     135             :   /* see l2fib_table_dump: ~0 means "any" */
     136          19 :   if (bd_id == ~0)
     137           0 :     bd_index = ~0;
     138             :   else
     139             :     {
     140          19 :       p = hash_get (bdm->bd_index_by_bd_id, bd_id);
     141          19 :       if (p == 0)
     142           8 :         return;
     143             : 
     144          11 :       bd_index = p[0];
     145             :     }
     146             : 
     147          11 :   l2fib_table_dump (bd_index, &l2fe_key, &l2fe_res);
     148             : 
     149          50 :   vec_foreach_index (ni, l2fe_key)
     150             :   {
     151          39 :     send_l2fib_table_entry (am, reg, vec_elt_at_index (l2fe_key, ni),
     152          39 :                             vec_elt_at_index (l2fe_res, ni), mp->context);
     153             :   }
     154          11 :   vec_free (l2fe_key);
     155          11 :   vec_free (l2fe_res);
     156             : }
     157             : 
     158             : static void
     159        1416 : vl_api_l2fib_add_del_t_handler (vl_api_l2fib_add_del_t * mp)
     160             : {
     161        1416 :   bd_main_t *bdm = &bd_main;
     162        1416 :   l2input_main_t *l2im = &l2input_main;
     163             :   vl_api_l2fib_add_del_reply_t *rmp;
     164        1416 :   int rv = 0;
     165        1416 :   u32 bd_id = ntohl (mp->bd_id);
     166        1416 :   uword *p = hash_get (bdm->bd_index_by_bd_id, bd_id);
     167             : 
     168        1416 :   if (!p)
     169             :     {
     170           0 :       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
     171           0 :       goto bad_sw_if_index;
     172             :     }
     173        1416 :   u32 bd_index = p[0];
     174             : 
     175             :   mac_address_t mac;
     176             : 
     177        1416 :   mac_address_decode (mp->mac, &mac);
     178        1416 :   if (mp->is_add)
     179             :     {
     180        1380 :       if (mp->filter_mac)
     181           0 :         l2fib_add_filter_entry (mac.bytes, bd_index);
     182             :       else
     183             :         {
     184        1380 :           l2fib_entry_result_flags_t flags = L2FIB_ENTRY_RESULT_FLAG_NONE;
     185        1380 :           u32 sw_if_index = ntohl (mp->sw_if_index);
     186        1380 :           VALIDATE_SW_IF_INDEX (mp);
     187        1380 :           if (vec_len (l2im->configs) <= sw_if_index)
     188             :             {
     189           0 :               rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
     190           0 :               goto bad_sw_if_index;
     191             :             }
     192             :           else
     193             :             {
     194             :               l2_input_config_t *config;
     195        1380 :               config = vec_elt_at_index (l2im->configs, sw_if_index);
     196        1380 :               if (!l2_input_is_bridge (config))
     197             :                 {
     198           0 :                   rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
     199           0 :                   goto bad_sw_if_index;
     200             :                 }
     201             :             }
     202        1380 :           if (mp->static_mac)
     203        1380 :             flags |= L2FIB_ENTRY_RESULT_FLAG_STATIC;
     204        1380 :           if (mp->bvi_mac)
     205           0 :             flags |= L2FIB_ENTRY_RESULT_FLAG_BVI;
     206        1380 :           l2fib_add_entry (mac.bytes, bd_index, sw_if_index, flags);
     207             :         }
     208             :     }
     209             :   else
     210             :     {
     211          36 :       u32 sw_if_index = ntohl (mp->sw_if_index);
     212          36 :       if (l2fib_del_entry (mac.bytes, bd_index, sw_if_index))
     213           0 :         rv = VNET_API_ERROR_NO_SUCH_ENTRY;
     214             :     }
     215             : 
     216          36 :   BAD_SW_IF_INDEX_LABEL;
     217             : 
     218        1416 :   REPLY_MACRO (VL_API_L2FIB_ADD_DEL_REPLY);
     219             : }
     220             : 
     221             : static void
     222           4 : vl_api_want_l2_macs_events2_t_handler (vl_api_want_l2_macs_events2_t *mp)
     223             : {
     224           4 :   int rv = 0;
     225             :   vl_api_want_l2_macs_events2_reply_t *rmp;
     226           4 :   l2learn_main_t *lm = &l2learn_main;
     227           4 :   l2fib_main_t *fm = &l2fib_main;
     228           4 :   u32 pid = ntohl (mp->pid);
     229             : 
     230           4 :   if (mp->enable_disable)
     231             :     {
     232           2 :       if ((lm->client_pid == 0) || (lm->client_pid == pid))
     233             :         {
     234           2 :           if (mp->max_macs_in_event)
     235           2 :             fm->max_macs_in_event = mp->max_macs_in_event * 10;
     236             :           else
     237             :             {
     238           0 :               rv = VNET_API_ERROR_INVALID_VALUE;
     239           0 :               goto exit;
     240             :             }
     241             : 
     242             :           /* if scan_delay was not set before */
     243           2 :           if (fm->event_scan_delay == 0.0)
     244           0 :             fm->event_scan_delay = (f64) (10) * 10e-3;
     245             : 
     246           2 :           lm->client_pid = pid;
     247           2 :           lm->client_index = mp->client_index;
     248           2 :           l2fib_flush_all_mac (vlib_get_main ());
     249             :         }
     250           0 :       else if (lm->client_pid != pid)
     251             :         {
     252           0 :           rv = VNET_API_ERROR_L2_MACS_EVENT_CLINET_PRESENT;
     253           0 :           goto exit;
     254             :         }
     255             :     }
     256           2 :   else if (lm->client_pid)
     257             :     {
     258           2 :       lm->client_pid = 0;
     259           2 :       lm->client_index = 0;
     260             :     }
     261             : 
     262           0 : exit:
     263           4 :   REPLY_MACRO (VL_API_WANT_L2_MACS_EVENTS2_REPLY);
     264             : }
     265             : 
     266             : static void
     267           6 : vl_api_want_l2_macs_events_t_handler (vl_api_want_l2_macs_events_t *mp)
     268             : {
     269           6 :   int rv = 0;
     270             :   vl_api_want_l2_macs_events_reply_t *rmp;
     271           6 :   l2learn_main_t *lm = &l2learn_main;
     272           6 :   l2fib_main_t *fm = &l2fib_main;
     273           6 :   u32 pid = ntohl (mp->pid);
     274           6 :   u32 learn_limit = ntohl (mp->learn_limit);
     275             : 
     276           6 :   if (mp->enable_disable)
     277             :     {
     278           4 :       if ((lm->client_pid == 0) || (lm->client_pid == pid))
     279             :         {
     280           4 :           if ((mp->max_macs_in_event == 0) || (mp->scan_delay == 0) ||
     281           4 :               (learn_limit == 0) || (learn_limit > L2LEARN_DEFAULT_LIMIT))
     282             :             {
     283           0 :               rv = VNET_API_ERROR_INVALID_VALUE;
     284           0 :               goto exit;
     285             :             }
     286           4 :           lm->client_pid = pid;
     287           4 :           lm->client_index = mp->client_index;
     288             : 
     289           4 :           fm->max_macs_in_event = mp->max_macs_in_event * 10;
     290           4 :           fm->event_scan_delay = (f64) (mp->scan_delay) * 10e-3;
     291             : 
     292             :           /* change learn limit and flush all learned MACs */
     293           4 :           lm->global_learn_limit = learn_limit;
     294           4 :           l2fib_flush_all_mac (vlib_get_main ());
     295             :         }
     296           0 :       else if (lm->client_pid != pid)
     297             :         {
     298           0 :           rv = VNET_API_ERROR_L2_MACS_EVENT_CLINET_PRESENT;
     299           0 :           goto exit;
     300             :         }
     301             :     }
     302           2 :   else if (lm->client_pid)
     303             :     {
     304           2 :       lm->client_pid = 0;
     305           2 :       lm->client_index = 0;
     306           2 :       if (learn_limit && (learn_limit <= L2LEARN_DEFAULT_LIMIT))
     307           2 :         lm->global_learn_limit = learn_limit;
     308             :       else
     309           0 :         lm->global_learn_limit = L2LEARN_DEFAULT_LIMIT;
     310             :     }
     311             : 
     312           0 : exit:
     313           6 :   REPLY_MACRO (VL_API_WANT_L2_MACS_EVENTS_REPLY);
     314             : }
     315             : 
     316             : static void
     317           1 : vl_api_l2fib_flush_int_t_handler (vl_api_l2fib_flush_int_t * mp)
     318             : {
     319           1 :   int rv = 0;
     320           1 :   vlib_main_t *vm = vlib_get_main ();
     321             :   vl_api_l2fib_flush_int_reply_t *rmp;
     322             : 
     323           1 :   VALIDATE_SW_IF_INDEX (mp);
     324             : 
     325           1 :   u32 sw_if_index = ntohl (mp->sw_if_index);
     326           1 :   l2fib_flush_int_mac (vm, sw_if_index);
     327             : 
     328           1 :   BAD_SW_IF_INDEX_LABEL;
     329           1 :   REPLY_MACRO (VL_API_L2FIB_FLUSH_INT_REPLY);
     330             : }
     331             : 
     332             : static void
     333           1 : vl_api_l2fib_flush_all_t_handler (vl_api_l2fib_flush_all_t * mp)
     334             : {
     335           1 :   int rv = 0;
     336             :   vl_api_l2fib_flush_all_reply_t *rmp;
     337             : 
     338           1 :   l2fib_flush_all_mac (vlib_get_main ());
     339           1 :   REPLY_MACRO (VL_API_L2FIB_FLUSH_ALL_REPLY);
     340             : }
     341             : 
     342             : static void
     343           1 : vl_api_l2fib_flush_bd_t_handler (vl_api_l2fib_flush_bd_t * mp)
     344             : {
     345           1 :   int rv = 0;
     346           1 :   vlib_main_t *vm = vlib_get_main ();
     347           1 :   bd_main_t *bdm = &bd_main;
     348             :   vl_api_l2fib_flush_bd_reply_t *rmp;
     349             : 
     350           1 :   u32 bd_id = ntohl (mp->bd_id);
     351           1 :   uword *p = hash_get (bdm->bd_index_by_bd_id, bd_id);
     352           1 :   if (p == 0)
     353             :     {
     354           0 :       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
     355           0 :       goto out;
     356             :     }
     357           1 :   l2fib_flush_bd_mac (vm, *p);
     358           1 : out:
     359           1 :   REPLY_MACRO (VL_API_L2FIB_FLUSH_BD_REPLY);
     360             : }
     361             : 
     362             : static void
     363           2 : vl_api_l2fib_set_scan_delay_t_handler (vl_api_l2fib_set_scan_delay_t *mp)
     364             : {
     365           2 :   int rv = 0;
     366           2 :   l2fib_main_t *fm = &l2fib_main;
     367             :   vl_api_l2fib_set_scan_delay_reply_t *rmp;
     368           2 :   u16 scan_delay = ntohs (mp->scan_delay);
     369             : 
     370           2 :   if (mp->scan_delay)
     371             :     {
     372           2 :       fm->event_scan_delay = (f64) (scan_delay) *10e-3;
     373           2 :       l2fib_flush_all_mac (vlib_get_main ());
     374             :     }
     375             :   else
     376             :     {
     377           0 :       rv = VNET_API_ERROR_INVALID_VALUE;
     378           0 :       goto exit;
     379             :     }
     380             : 
     381           2 : exit:
     382           2 :   REPLY_MACRO (VL_API_L2FIB_SET_SCAN_DELAY_REPLY);
     383             : }
     384             : 
     385             : static void
     386           0 : vl_api_l2_flags_t_handler (vl_api_l2_flags_t * mp)
     387             : {
     388             :   vl_api_l2_flags_reply_t *rmp;
     389           0 :   int rv = 0;
     390           0 :   u32 rbm = 0;
     391             : 
     392           0 :   VALIDATE_SW_IF_INDEX (mp);
     393             : 
     394           0 :   u32 sw_if_index = ntohl (mp->sw_if_index);
     395           0 :   u32 flags = ntohl (mp->feature_bitmap);
     396           0 :   u32 bitmap = 0;
     397             : 
     398           0 :   if (flags & L2_LEARN)
     399           0 :     bitmap |= L2INPUT_FEAT_LEARN;
     400             : 
     401           0 :   if (flags & L2_FWD)
     402           0 :     bitmap |= L2INPUT_FEAT_FWD;
     403             : 
     404           0 :   if (flags & L2_FLOOD)
     405           0 :     bitmap |= L2INPUT_FEAT_FLOOD;
     406             : 
     407           0 :   if (flags & L2_UU_FLOOD)
     408           0 :     bitmap |= L2INPUT_FEAT_UU_FLOOD;
     409             : 
     410           0 :   if (flags & L2_ARP_TERM)
     411           0 :     bitmap |= L2INPUT_FEAT_ARP_TERM;
     412             : 
     413           0 :   rbm = l2input_intf_bitmap_enable (sw_if_index, bitmap, mp->is_set);
     414             : 
     415           0 :   BAD_SW_IF_INDEX_LABEL;
     416             : 
     417             :   /* *INDENT-OFF* */
     418           0 :   REPLY_MACRO2(VL_API_L2_FLAGS_REPLY,
     419             :   ({
     420             :     rmp->resulting_feature_bitmap = ntohl(rbm);
     421             :   }));
     422             :   /* *INDENT-ON* */
     423             : }
     424             : 
     425             : static void
     426           1 : vl_api_bridge_domain_set_default_learn_limit_t_handler (
     427             :   vl_api_bridge_domain_set_default_learn_limit_t *mp)
     428             : {
     429             :   vl_api_bridge_domain_set_default_learn_limit_reply_t *rmp;
     430           1 :   int rv = 0;
     431             : 
     432           1 :   l2learn_main.bd_default_learn_limit = ntohl (mp->learn_limit);
     433           1 :   REPLY_MACRO (VL_API_BRIDGE_DOMAIN_SET_DEFAULT_LEARN_LIMIT_REPLY);
     434             : }
     435             : 
     436             : static void
     437           1 : vl_api_bridge_domain_set_learn_limit_t_handler (
     438             :   vl_api_bridge_domain_set_learn_limit_t *mp)
     439             : {
     440           1 :   vlib_main_t *vm = vlib_get_main ();
     441           1 :   bd_main_t *bdm = &bd_main;
     442             :   vl_api_bridge_domain_set_learn_limit_reply_t *rmp;
     443           1 :   int rv = 0;
     444           1 :   u32 bd_id = ntohl (mp->bd_id);
     445             :   uword *p;
     446             : 
     447           1 :   if (bd_id == 0)
     448             :     {
     449           0 :       rv = VNET_API_ERROR_BD_NOT_MODIFIABLE;
     450           0 :       goto out;
     451             :     }
     452             : 
     453           1 :   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
     454           1 :   if (p == 0)
     455             :     {
     456           0 :       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
     457           0 :       goto out;
     458             :     }
     459           1 :   bd_set_learn_limit (vm, *p, ntohl (mp->learn_limit));
     460           1 : out:
     461           1 :   REPLY_MACRO (VL_API_BRIDGE_DOMAIN_SET_LEARN_LIMIT_REPLY);
     462             : }
     463             : 
     464             : static void
     465           0 : vl_api_bridge_domain_set_mac_age_t_handler (vl_api_bridge_domain_set_mac_age_t
     466             :                                             * mp)
     467             : {
     468           0 :   vlib_main_t *vm = vlib_get_main ();
     469           0 :   bd_main_t *bdm = &bd_main;
     470             :   vl_api_bridge_domain_set_mac_age_reply_t *rmp;
     471           0 :   int rv = 0;
     472           0 :   u32 bd_id = ntohl (mp->bd_id);
     473             :   uword *p;
     474             : 
     475           0 :   if (bd_id == 0)
     476             :     {
     477           0 :       rv = VNET_API_ERROR_BD_NOT_MODIFIABLE;
     478           0 :       goto out;
     479             :     }
     480             : 
     481           0 :   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
     482           0 :   if (p == 0)
     483             :     {
     484           0 :       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
     485           0 :       goto out;
     486             :     }
     487           0 :   bd_set_mac_age (vm, *p, mp->mac_age);
     488           0 : out:
     489           0 :   REPLY_MACRO (VL_API_BRIDGE_DOMAIN_SET_MAC_AGE_REPLY);
     490             : }
     491             : 
     492             : static void
     493           0 : vl_api_bridge_domain_add_del_t_handler (vl_api_bridge_domain_add_del_t * mp)
     494             : {
     495           0 :   l2_bridge_domain_add_del_args_t a = {
     496           0 :     .is_add = mp->is_add,
     497           0 :     .flood = mp->flood,
     498           0 :     .uu_flood = mp->uu_flood,
     499           0 :     .forward = mp->forward,
     500           0 :     .learn = mp->learn,
     501           0 :     .arp_term = mp->arp_term,
     502           0 :     .arp_ufwd = mp->arp_ufwd,
     503           0 :     .mac_age = mp->mac_age,
     504           0 :     .bd_id = ntohl (mp->bd_id),
     505           0 :     .bd_tag = mp->bd_tag
     506             :   };
     507             : 
     508           0 :   int rv = bd_add_del (&a);
     509             : 
     510             :   vl_api_bridge_domain_add_del_reply_t *rmp;
     511           0 :   REPLY_MACRO (VL_API_BRIDGE_DOMAIN_ADD_DEL_REPLY);
     512             : }
     513             : 
     514             : static void
     515         127 : vl_api_bridge_domain_add_del_v2_t_handler (
     516             :   vl_api_bridge_domain_add_del_v2_t *mp)
     517             : {
     518             :   vl_api_bridge_domain_add_del_v2_reply_t *rmp;
     519         127 :   u32 bd_id = ntohl (mp->bd_id);
     520         127 :   int rv = 0;
     521             : 
     522         127 :   if ((~0 == bd_id) && (mp->is_add))
     523          17 :     bd_id = bd_get_unused_id ();
     524             : 
     525         127 :   if ((~0 == bd_id) && (mp->is_add))
     526           0 :     rv = VNET_API_ERROR_EAGAIN;
     527             :   else
     528             :     {
     529         127 :       l2_bridge_domain_add_del_args_t a = { .is_add = mp->is_add,
     530         127 :                                             .flood = mp->flood,
     531         127 :                                             .uu_flood = mp->uu_flood,
     532         127 :                                             .forward = mp->forward,
     533         127 :                                             .learn = mp->learn,
     534         127 :                                             .arp_term = mp->arp_term,
     535         127 :                                             .arp_ufwd = mp->arp_ufwd,
     536         127 :                                             .mac_age = mp->mac_age,
     537             :                                             .bd_id = bd_id,
     538         127 :                                             .bd_tag = mp->bd_tag };
     539         127 :       rv = bd_add_del (&a);
     540             :     }
     541         127 :   REPLY_MACRO2 (VL_API_BRIDGE_DOMAIN_ADD_DEL_V2_REPLY,
     542             :                 ({ rmp->bd_id = htonl (bd_id); }));
     543             : }
     544             : 
     545             : static void
     546          81 : send_bridge_domain_details (l2input_main_t * l2im,
     547             :                             vl_api_registration_t * reg,
     548             :                             l2_bridge_domain_t * bd_config,
     549             :                             u32 n_sw_ifs, u32 context)
     550             : {
     551             :   vl_api_bridge_domain_details_t *mp;
     552             :   l2_flood_member_t *m;
     553             :   vl_api_bridge_domain_sw_if_t *sw_ifs;
     554             :   l2_input_config_t *input_cfg;
     555             : 
     556          81 :   mp = vl_msg_api_alloc (sizeof (*mp) +
     557          81 :                          (n_sw_ifs * sizeof (vl_api_bridge_domain_sw_if_t)));
     558          81 :   clib_memset (mp, 0, sizeof (*mp));
     559          81 :   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_BRIDGE_DOMAIN_DETAILS);
     560          81 :   mp->bd_id = ntohl (bd_config->bd_id);
     561          81 :   mp->flood = bd_feature_flood (bd_config);
     562          81 :   mp->uu_flood = bd_feature_uu_flood (bd_config);
     563          81 :   mp->forward = bd_feature_forward (bd_config);
     564          81 :   mp->learn = bd_feature_learn (bd_config);
     565          81 :   mp->arp_term = bd_feature_arp_term (bd_config);
     566          81 :   mp->arp_ufwd = bd_feature_arp_ufwd (bd_config);
     567          81 :   mp->bvi_sw_if_index = ntohl (bd_config->bvi_sw_if_index);
     568          81 :   mp->uu_fwd_sw_if_index = ntohl (bd_config->uu_fwd_sw_if_index);
     569          81 :   mp->mac_age = bd_config->mac_age;
     570          81 :   if (bd_config->bd_tag)
     571             :     {
     572           0 :       strncpy ((char *) mp->bd_tag, (char *) bd_config->bd_tag,
     573             :                ARRAY_LEN (mp->bd_tag) - 1);
     574           0 :       mp->bd_tag[ARRAY_LEN (mp->bd_tag) - 1] = 0;
     575             :     }
     576             : 
     577          81 :   mp->context = context;
     578             : 
     579          81 :   sw_ifs = (vl_api_bridge_domain_sw_if_t *) mp->sw_if_details;
     580         174 :   vec_foreach (m, bd_config->members)
     581             :   {
     582          93 :     sw_ifs->sw_if_index = ntohl (m->sw_if_index);
     583          93 :     input_cfg = vec_elt_at_index (l2im->configs, m->sw_if_index);
     584          93 :     sw_ifs->shg = input_cfg->shg;
     585          93 :     sw_ifs++;
     586          93 :     mp->n_sw_ifs++;
     587             :   }
     588          81 :   mp->n_sw_ifs = htonl (mp->n_sw_ifs);
     589             : 
     590          81 :   vl_api_send_msg (reg, (u8 *) mp);
     591          81 : }
     592             : 
     593             : static void
     594         112 : vl_api_bridge_domain_dump_t_handler (vl_api_bridge_domain_dump_t * mp)
     595             : {
     596         112 :   bd_main_t *bdm = &bd_main;
     597         112 :   l2input_main_t *l2im = &l2input_main;
     598             :   vl_api_registration_t *reg;
     599             :   u32 bd_id, bd_index, end, filter_sw_if_index;
     600             : 
     601         112 :   reg = vl_api_client_index_to_registration (mp->client_index);
     602         112 :   if (!reg)
     603           0 :     return;
     604             : 
     605         112 :   filter_sw_if_index = ntohl (mp->sw_if_index);
     606         112 :   if (filter_sw_if_index != ~0)
     607           0 :     return;                     /* UNIMPLEMENTED */
     608             : 
     609         112 :   bd_id = ntohl (mp->bd_id);
     610         112 :   if (bd_id == 0)
     611           0 :     return;
     612             : 
     613         112 :   if (bd_id == ~0)
     614           0 :     bd_index = 0, end = vec_len (l2im->bd_configs);
     615             :   else
     616             :     {
     617         112 :       bd_index = bd_find_index (bdm, bd_id);
     618         112 :       if (bd_index == ~0)
     619          31 :         return;
     620             : 
     621          81 :       end = bd_index + 1;
     622             :     }
     623             : 
     624         162 :   for (; bd_index < end; bd_index++)
     625             :     {
     626             :       l2_bridge_domain_t *bd_config =
     627          81 :         l2input_bd_config_from_index (l2im, bd_index);
     628             :       /* skip placeholder bd_id 0 */
     629          81 :       if (bd_config && (bd_config->bd_id > 0))
     630          81 :         send_bridge_domain_details (l2im, reg, bd_config,
     631          81 :                                     vec_len (bd_config->members),
     632             :                                     mp->context);
     633             :     }
     634             : }
     635             : 
     636             : static bd_flags_t
     637          71 : bd_flags_decode (vl_api_bd_flags_t v)
     638             : {
     639          71 :   bd_flags_t f = L2_NONE;
     640             : 
     641          71 :   v = ntohl (v);
     642             : 
     643          71 :   if (v & BRIDGE_API_FLAG_LEARN)
     644          40 :     f |= L2_LEARN;
     645          71 :   if (v & BRIDGE_API_FLAG_FWD)
     646           2 :     f |= L2_FWD;
     647          71 :   if (v & BRIDGE_API_FLAG_FLOOD)
     648          10 :     f |= L2_FLOOD;
     649          71 :   if (v & BRIDGE_API_FLAG_UU_FLOOD)
     650          11 :     f |= L2_UU_FLOOD;
     651          71 :   if (v & BRIDGE_API_FLAG_ARP_TERM)
     652           8 :     f |= L2_ARP_TERM;
     653          71 :   if (v & BRIDGE_API_FLAG_ARP_UFWD)
     654           0 :     f |= L2_ARP_UFWD;
     655             : 
     656          71 :   return (f);
     657             : }
     658             : 
     659             : static void
     660          71 : vl_api_bridge_flags_t_handler (vl_api_bridge_flags_t * mp)
     661             : {
     662          71 :   vlib_main_t *vm = vlib_get_main ();
     663          71 :   bd_main_t *bdm = &bd_main;
     664             :   vl_api_bridge_flags_reply_t *rmp;
     665          71 :   u32 bitmap = 0;
     666          71 :   int rv = 0;
     667             : 
     668          71 :   bd_flags_t flags = bd_flags_decode (mp->flags);
     669          71 :   u32 bd_id = ntohl (mp->bd_id);
     670          71 :   if (bd_id == 0)
     671             :     {
     672           0 :       rv = VNET_API_ERROR_BD_NOT_MODIFIABLE;
     673           0 :       goto out;
     674             :     }
     675             : 
     676          71 :   u32 bd_index = bd_find_index (bdm, bd_id);
     677          71 :   if (bd_index == ~0)
     678             :     {
     679           0 :       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
     680           0 :       goto out;
     681             :     }
     682             : 
     683          71 :   bitmap = bd_set_flags (vm, bd_index, flags, mp->is_set);
     684             : 
     685          71 : out:
     686             :   /* *INDENT-OFF* */
     687          71 :   REPLY_MACRO2(VL_API_BRIDGE_FLAGS_REPLY,
     688             :   ({
     689             :     rmp->resulting_feature_bitmap = ntohl(bitmap);
     690             :   }));
     691             :   /* *INDENT-ON* */
     692             : }
     693             : 
     694             : static void
     695         175 :   vl_api_l2_interface_vlan_tag_rewrite_t_handler
     696             :   (vl_api_l2_interface_vlan_tag_rewrite_t * mp)
     697             : {
     698         175 :   int rv = 0;
     699             :   vl_api_l2_interface_vlan_tag_rewrite_reply_t *rmp;
     700         175 :   vnet_main_t *vnm = vnet_get_main ();
     701         175 :   vlib_main_t *vm = vlib_get_main ();
     702             :   u32 vtr_op;
     703             : 
     704         175 :   VALIDATE_SW_IF_INDEX (mp);
     705             : 
     706         175 :   vtr_op = ntohl (mp->vtr_op);
     707             : 
     708             :   /* The L2 code is unsuspicious */
     709         175 :   switch (vtr_op)
     710             :     {
     711         175 :     case L2_VTR_DISABLED:
     712             :     case L2_VTR_PUSH_1:
     713             :     case L2_VTR_PUSH_2:
     714             :     case L2_VTR_POP_1:
     715             :     case L2_VTR_POP_2:
     716             :     case L2_VTR_TRANSLATE_1_1:
     717             :     case L2_VTR_TRANSLATE_1_2:
     718             :     case L2_VTR_TRANSLATE_2_1:
     719             :     case L2_VTR_TRANSLATE_2_2:
     720         175 :       break;
     721             : 
     722           0 :     default:
     723           0 :       rv = VNET_API_ERROR_INVALID_VALUE;
     724           0 :       goto bad_sw_if_index;
     725             :     }
     726             : 
     727         175 :   rv = l2vtr_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
     728             :                         ntohl (mp->push_dot1q), ntohl (mp->tag1),
     729             :                         ntohl (mp->tag2));
     730             : 
     731         175 :   BAD_SW_IF_INDEX_LABEL;
     732             : 
     733         175 :   REPLY_MACRO (VL_API_L2_INTERFACE_VLAN_TAG_REWRITE_REPLY);
     734             : }
     735             : 
     736             : static void
     737           0 :   vl_api_l2_interface_pbb_tag_rewrite_t_handler
     738             :   (vl_api_l2_interface_pbb_tag_rewrite_t * mp)
     739             : {
     740             :   vl_api_l2_interface_pbb_tag_rewrite_reply_t *rmp;
     741           0 :   vnet_main_t *vnm = vnet_get_main ();
     742           0 :   vlib_main_t *vm = vlib_get_main ();
     743             :   u32 vtr_op;
     744           0 :   int rv = 0;
     745             :   mac_address_t b_dmac, b_smac;
     746             : 
     747           0 :   VALIDATE_SW_IF_INDEX (mp);
     748             : 
     749           0 :   vtr_op = ntohl (mp->vtr_op);
     750             : 
     751           0 :   switch (vtr_op)
     752             :     {
     753           0 :     case L2_VTR_DISABLED:
     754             :     case L2_VTR_PUSH_2:
     755             :     case L2_VTR_POP_2:
     756             :     case L2_VTR_TRANSLATE_2_1:
     757           0 :       break;
     758             : 
     759           0 :     default:
     760           0 :       rv = VNET_API_ERROR_INVALID_VALUE;
     761           0 :       goto bad_sw_if_index;
     762             :     }
     763             : 
     764           0 :   mac_address_decode (mp->b_dmac, &b_dmac);
     765           0 :   mac_address_decode (mp->b_smac, &b_smac);
     766             : 
     767           0 :   rv = l2pbb_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
     768           0 :                         b_dmac.bytes, b_smac.bytes, ntohs (mp->b_vlanid),
     769           0 :                         ntohl (mp->i_sid), ntohs (mp->outer_tag));
     770             : 
     771           0 :   BAD_SW_IF_INDEX_LABEL;
     772             : 
     773           0 :   REPLY_MACRO (VL_API_L2_INTERFACE_PBB_TAG_REWRITE_REPLY);
     774             : }
     775             : 
     776             : static void
     777          82 :   vl_api_sw_interface_set_l2_xconnect_t_handler
     778             :   (vl_api_sw_interface_set_l2_xconnect_t * mp)
     779             : {
     780             :   vl_api_sw_interface_set_l2_xconnect_reply_t *rmp;
     781          82 :   int rv = 0;
     782          82 :   u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
     783          82 :   u32 tx_sw_if_index = ntohl (mp->tx_sw_if_index);
     784          82 :   vlib_main_t *vm = vlib_get_main ();
     785          82 :   vnet_main_t *vnm = vnet_get_main ();
     786             : 
     787          82 :   VALIDATE_RX_SW_IF_INDEX (mp);
     788             : 
     789          82 :   if (mp->enable)
     790             :     {
     791          48 :       VALIDATE_TX_SW_IF_INDEX (mp);
     792          48 :       rv = set_int_l2_mode (vm, vnm, MODE_L2_XC,
     793             :                             rx_sw_if_index, 0,
     794             :                             L2_BD_PORT_TYPE_NORMAL, 0, tx_sw_if_index);
     795             :     }
     796             :   else
     797             :     {
     798          34 :       rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0,
     799             :                             L2_BD_PORT_TYPE_NORMAL, 0, 0);
     800             :     }
     801             : 
     802          82 :   switch (rv)
     803             :     {
     804           0 :     case MODE_ERROR_ETH:
     805           0 :       rv = VNET_API_ERROR_NON_ETHERNET;
     806           0 :       break;
     807           0 :     case MODE_ERROR_BVI_DEF:
     808           0 :       rv = VNET_API_ERROR_BD_ALREADY_HAS_BVI;
     809           0 :       break;
     810             :     }
     811             : 
     812          82 :   BAD_RX_SW_IF_INDEX_LABEL;
     813          82 :   BAD_TX_SW_IF_INDEX_LABEL;
     814             : 
     815          82 :   REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_XCONNECT_REPLY);
     816             : }
     817             : 
     818             : static int
     819        1438 : l2_bd_port_type_decode (vl_api_l2_port_type_t v, l2_bd_port_type_t * l)
     820             : {
     821        1438 :   v = clib_net_to_host_u32 (v);
     822             : 
     823        1438 :   switch (v)
     824             :     {
     825        1421 :     case L2_API_PORT_TYPE_NORMAL:
     826        1421 :       *l = L2_BD_PORT_TYPE_NORMAL;
     827        1421 :       return 0;
     828          13 :     case L2_API_PORT_TYPE_BVI:
     829          13 :       *l = L2_BD_PORT_TYPE_BVI;
     830          13 :       return 0;
     831           4 :     case L2_API_PORT_TYPE_UU_FWD:
     832           4 :       *l = L2_BD_PORT_TYPE_UU_FWD;
     833           4 :       return 0;
     834             :     }
     835             : 
     836           0 :   return (VNET_API_ERROR_INVALID_VALUE);
     837             : }
     838             : 
     839             : static void
     840        1438 :   vl_api_sw_interface_set_l2_bridge_t_handler
     841             :   (vl_api_sw_interface_set_l2_bridge_t * mp)
     842             : {
     843        1438 :   bd_main_t *bdm = &bd_main;
     844             :   vl_api_sw_interface_set_l2_bridge_reply_t *rmp;
     845        1438 :   int rv = 0;
     846        1438 :   vlib_main_t *vm = vlib_get_main ();
     847        1438 :   vnet_main_t *vnm = vnet_get_main ();
     848             :   l2_bd_port_type_t pt;
     849             : 
     850        1438 :   VALIDATE_RX_SW_IF_INDEX (mp);
     851        1438 :   u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
     852        1438 :   rv = l2_bd_port_type_decode (mp->port_type, &pt);
     853             : 
     854        1438 :   if (0 != rv)
     855           0 :     goto out;
     856        1438 :   if (mp->enable)
     857             :     {
     858        1256 :       VALIDATE_BD_ID (mp);
     859        1256 :       u32 bd_id = ntohl (mp->bd_id);
     860        1256 :       u32 bd_index = bd_find_or_add_bd_index (bdm, bd_id);
     861             : 
     862        1256 :       rv = set_int_l2_mode (vm, vnm, MODE_L2_BRIDGE,
     863        1256 :                             rx_sw_if_index, bd_index, pt, mp->shg, 0);
     864             :     }
     865             :   else
     866             :     {
     867         182 :       rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0, pt, 0, 0);
     868             :     }
     869             : 
     870        1438 :   switch (rv)
     871             :     {
     872           0 :     case MODE_ERROR_ETH:
     873           0 :       rv = VNET_API_ERROR_NON_ETHERNET;
     874           0 :       break;
     875           0 :     case MODE_ERROR_BVI_DEF:
     876           0 :       rv = VNET_API_ERROR_BD_ALREADY_HAS_BVI;
     877           0 :       break;
     878             :     }
     879             : 
     880        1438 :   BAD_RX_SW_IF_INDEX_LABEL;
     881        1438 :   BAD_BD_ID_LABEL;
     882        1438 : out:
     883        1438 :   REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_BRIDGE_REPLY);
     884             : }
     885             : 
     886             : static void
     887           0 : send_bd_ip_mac_entry (vpe_api_main_t * am,
     888             :                       vl_api_registration_t * reg,
     889             :                       u32 bd_id,
     890             :                       const ip46_address_t * ip,
     891             :                       ip46_type_t itype,
     892             :                       const mac_address_t * mac, u32 context)
     893             : {
     894             :   vl_api_bd_ip_mac_details_t *mp;
     895             : 
     896           0 :   mp = vl_msg_api_alloc (sizeof (*mp));
     897           0 :   clib_memset (mp, 0, sizeof (*mp));
     898           0 :   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_BD_IP_MAC_DETAILS);
     899             : 
     900           0 :   mp->context = context;
     901           0 :   mp->entry.bd_id = ntohl (bd_id);
     902             : 
     903           0 :   ip_address_encode (ip, itype, &mp->entry.ip);
     904           0 :   mac_address_encode (mac, mp->entry.mac);
     905             : 
     906           0 :   vl_api_send_msg (reg, (u8 *) mp);
     907           0 : }
     908             : 
     909             : static void
     910           0 : vl_api_bd_ip_mac_dump_t_handler (vl_api_bd_ip_mac_dump_t * mp)
     911             : {
     912           0 :   vpe_api_main_t *am = &vpe_api_main;
     913           0 :   bd_main_t *bdm = &bd_main;
     914             :   l2_bridge_domain_t *bd_config;
     915           0 :   u32 bd_id = ntohl (mp->bd_id);
     916             :   u32 bd_index, start, end;
     917             :   vl_api_registration_t *reg;
     918             :   uword *p;
     919             : 
     920           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
     921           0 :   if (!reg)
     922           0 :     return;
     923             : 
     924             :   /* see bd_id: ~0 means "any" */
     925           0 :   if (bd_id == ~0)
     926             :     {
     927           0 :       start = 1;
     928           0 :       end = vec_len (l2input_main.bd_configs);
     929             :     }
     930             :   else
     931             :     {
     932           0 :       p = hash_get (bdm->bd_index_by_bd_id, bd_id);
     933           0 :       if (p == 0)
     934           0 :         return;
     935             : 
     936           0 :       bd_index = p[0];
     937           0 :       vec_validate (l2input_main.bd_configs, bd_index);
     938           0 :       start = bd_index;
     939           0 :       end = start + 1;
     940             :     }
     941             : 
     942           0 :   for (bd_index = start; bd_index < end; bd_index++)
     943             :     {
     944           0 :       bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
     945           0 :       if (bd_is_valid (bd_config))
     946             :         {
     947             :           ip4_address_t ip4_addr;
     948             :           ip6_address_t *ip6_addr;
     949             :           mac_address_t mac;
     950             :           u64 mac64;
     951           0 :           bd_id = bd_config->bd_id;
     952             : 
     953             :          /* *INDENT-OFF* */
     954           0 :          hash_foreach (ip4_addr.as_u32, mac64, bd_config->mac_by_ip4,
     955             :          ({
     956             :            ip46_address_t ip = {
     957             :              .ip4 = ip4_addr,
     958             :            };
     959             :            mac_address_from_u64(&mac, mac64);
     960             : 
     961             :            send_bd_ip_mac_entry (am, reg, bd_id, &ip, IP46_TYPE_IP4,
     962             :                                  &mac, mp->context);
     963             :          }));
     964             : 
     965           0 :          hash_foreach_mem (ip6_addr, mac64, bd_config->mac_by_ip6,
     966             :          ({
     967             :            ip46_address_t ip = {
     968             :              .ip6 = *ip6_addr,
     969             :            };
     970             :            mac_address_from_u64(&mac, mac64);
     971             : 
     972             :            send_bd_ip_mac_entry (am, reg, bd_id, &ip, IP46_TYPE_IP6,
     973             :                                  &mac, mp->context);
     974             :          }));
     975             :          /* *INDENT-ON* */
     976             :         }
     977             :     }
     978             : }
     979             : 
     980             : static void
     981          85 : vl_api_bd_ip_mac_add_del_t_handler (vl_api_bd_ip_mac_add_del_t * mp)
     982             : {
     983          85 :   ip46_address_t ip_addr = ip46_address_initializer;
     984             :   vl_api_bd_ip_mac_add_del_reply_t *rmp;
     985          85 :   bd_main_t *bdm = &bd_main;
     986             :   u32 bd_index, bd_id;
     987             :   mac_address_t mac;
     988             :   ip46_type_t type;
     989          85 :   int rv = 0;
     990             :   uword *p;
     991             : 
     992          85 :   bd_id = ntohl (mp->entry.bd_id);
     993             : 
     994          85 :   if (bd_id == 0)
     995             :     {
     996           0 :       rv = VNET_API_ERROR_BD_NOT_MODIFIABLE;
     997           0 :       goto out;
     998             :     }
     999             : 
    1000          85 :   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
    1001          85 :   if (p == 0)
    1002             :     {
    1003           0 :       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
    1004           0 :       goto out;
    1005             :     }
    1006          85 :   bd_index = p[0];
    1007             : 
    1008          85 :   type = ip_address_decode (&mp->entry.ip, &ip_addr);
    1009          85 :   mac_address_decode (mp->entry.mac, &mac);
    1010             : 
    1011          85 :   if (bd_add_del_ip_mac (bd_index, type, &ip_addr, &mac, mp->is_add))
    1012           0 :     rv = VNET_API_ERROR_UNSPECIFIED;
    1013             : 
    1014          85 : out:
    1015          85 :   REPLY_MACRO (VL_API_BD_IP_MAC_ADD_DEL_REPLY);
    1016             : }
    1017             : 
    1018             : static void
    1019           0 : vl_api_bd_ip_mac_flush_t_handler (vl_api_bd_ip_mac_flush_t * mp)
    1020             : {
    1021             :   vl_api_bd_ip_mac_flush_reply_t *rmp;
    1022           0 :   bd_main_t *bdm = &bd_main;
    1023             :   u32 bd_index, bd_id;
    1024           0 :   int rv = 0;
    1025             :   uword *p;
    1026             : 
    1027           0 :   bd_id = ntohl (mp->bd_id);
    1028             : 
    1029           0 :   if (bd_id == 0)
    1030             :     {
    1031           0 :       rv = VNET_API_ERROR_BD_NOT_MODIFIABLE;
    1032           0 :       goto out;
    1033             :     }
    1034             : 
    1035           0 :   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
    1036           0 :   if (p == 0)
    1037             :     {
    1038           0 :       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
    1039           0 :       goto out;
    1040             :     }
    1041           0 :   bd_index = p[0];
    1042             : 
    1043           0 :   bd_flush_ip_mac (bd_index);
    1044             : 
    1045           0 : out:
    1046           0 :   REPLY_MACRO (VL_API_BD_IP_MAC_FLUSH_REPLY);
    1047             : }
    1048             : 
    1049             : extern void l2_efp_filter_configure (vnet_main_t * vnet_main,
    1050             :                                      u32 sw_if_index, u8 enable);
    1051             : 
    1052             : static void
    1053           0 : vl_api_l2_interface_efp_filter_t_handler (vl_api_l2_interface_efp_filter_t *
    1054             :                                           mp)
    1055             : {
    1056             :   int rv;
    1057             :   vl_api_l2_interface_efp_filter_reply_t *rmp;
    1058           0 :   vnet_main_t *vnm = vnet_get_main ();
    1059             : 
    1060           0 :   VALIDATE_SW_IF_INDEX (mp);
    1061             : 
    1062             :   // enable/disable the feature
    1063           0 :   l2_efp_filter_configure (vnm, ntohl (mp->sw_if_index), mp->enable_disable);
    1064           0 :   rv = vnm->api_errno;
    1065             : 
    1066           0 :   BAD_SW_IF_INDEX_LABEL;
    1067           0 :   REPLY_MACRO (VL_API_L2_INTERFACE_EFP_FILTER_REPLY);
    1068             : }
    1069             : 
    1070             : static void
    1071           0 : vl_api_l2_patch_add_del_t_handler (vl_api_l2_patch_add_del_t * mp)
    1072             : {
    1073             :   extern int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
    1074             :                                     int is_add);
    1075             :   vl_api_l2_patch_add_del_reply_t *rmp;
    1076             :   int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
    1077             :                              int is_add);
    1078           0 :   int rv = 0;
    1079             : 
    1080           0 :   VALIDATE_RX_SW_IF_INDEX (mp);
    1081           0 :   VALIDATE_TX_SW_IF_INDEX (mp);
    1082             : 
    1083           0 :   rv = vnet_l2_patch_add_del (ntohl (mp->rx_sw_if_index),
    1084             :                               ntohl (mp->tx_sw_if_index),
    1085           0 :                               (int) (mp->is_add != 0));
    1086             : 
    1087           0 :   BAD_RX_SW_IF_INDEX_LABEL;
    1088           0 :   BAD_TX_SW_IF_INDEX_LABEL;
    1089             : 
    1090           0 :   REPLY_MACRO (VL_API_L2_PATCH_ADD_DEL_REPLY);
    1091             : }
    1092             : 
    1093             : static void
    1094           0 : vl_api_sw_interface_set_vpath_t_handler (vl_api_sw_interface_set_vpath_t * mp)
    1095             : {
    1096             :   vl_api_sw_interface_set_vpath_reply_t *rmp;
    1097           0 :   int rv = 0;
    1098           0 :   u32 sw_if_index = ntohl (mp->sw_if_index);
    1099             : 
    1100           0 :   VALIDATE_SW_IF_INDEX (mp);
    1101             : 
    1102           0 :   l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_VPATH, mp->enable);
    1103           0 :   vnet_feature_enable_disable ("ip4-unicast", "vpath-input-ip4",
    1104           0 :                                sw_if_index, mp->enable, 0, 0);
    1105           0 :   vnet_feature_enable_disable ("ip4-multicast", "vpath-input-ip4",
    1106           0 :                                sw_if_index, mp->enable, 0, 0);
    1107           0 :   vnet_feature_enable_disable ("ip6-unicast", "vpath-input-ip6",
    1108           0 :                                sw_if_index, mp->enable, 0, 0);
    1109           0 :   vnet_feature_enable_disable ("ip6-multicast", "vpath-input-ip6",
    1110           0 :                                sw_if_index, mp->enable, 0, 0);
    1111             : 
    1112           0 :   BAD_SW_IF_INDEX_LABEL;
    1113             : 
    1114           0 :   REPLY_MACRO (VL_API_SW_INTERFACE_SET_VPATH_REPLY);
    1115             : }
    1116             : 
    1117             : static void
    1118           4 : vl_api_bvi_create_t_handler (vl_api_bvi_create_t * mp)
    1119             : {
    1120             :   vl_api_bvi_create_reply_t *rmp;
    1121             :   mac_address_t mac;
    1122             :   u32 sw_if_index;
    1123             :   int rv;
    1124             : 
    1125           4 :   mac_address_decode (mp->mac, &mac);
    1126             : 
    1127           4 :   rv = l2_bvi_create (ntohl (mp->user_instance), &mac, &sw_if_index);
    1128             : 
    1129             :   /* *INDENT-OFF* */
    1130           4 :   REPLY_MACRO2(VL_API_BVI_CREATE_REPLY,
    1131             :   ({
    1132             :     rmp->sw_if_index = ntohl (sw_if_index);
    1133             :   }));
    1134             :   /* *INDENT-ON* */
    1135             : }
    1136             : 
    1137             : static void
    1138           0 : vl_api_bvi_delete_t_handler (vl_api_bvi_delete_t * mp)
    1139             : {
    1140             :   vl_api_bvi_delete_reply_t *rmp;
    1141             :   int rv;
    1142             : 
    1143           0 :   rv = l2_bvi_delete (ntohl (mp->sw_if_index));
    1144             : 
    1145           0 :   REPLY_MACRO (VL_API_BVI_DELETE_REPLY);
    1146             : }
    1147             : 
    1148             : static bool
    1149          20 : l2_arp_term_publish_event_is_equal (const l2_arp_term_publish_event_t * e1,
    1150             :                                     const l2_arp_term_publish_event_t * e2)
    1151             : {
    1152          20 :   if (e1 == NULL || e2 == NULL)
    1153           0 :     return false;
    1154          20 :   return (ip46_address_is_equal (&e1->ip, &e2->ip) &&
    1155          28 :           (e1->sw_if_index == e2->sw_if_index) &&
    1156           8 :           (mac_address_equal (&e1->mac, &e2->mac)));
    1157             : }
    1158             : 
    1159             : static uword
    1160         575 : l2_arp_term_process (vlib_main_t * vm, vlib_node_runtime_t * rt,
    1161             :                      vlib_frame_t * f)
    1162             : {
    1163             :   /* These cross the longjmp boundary (vlib_process_wait_for_event)
    1164             :    * and need to be volatile - to prevent them from being optimized into
    1165             :    * a register - which could change during suspension */
    1166         575 :   volatile f64 last = vlib_time_now (vm);
    1167         575 :   volatile l2_arp_term_publish_event_t last_event = { };
    1168             : 
    1169         575 :   l2_arp_term_main_t *l2am = &l2_arp_term_main;
    1170             : 
    1171             :   while (1)
    1172           4 :     {
    1173         579 :       uword event_type = L2_ARP_TERM_EVENT_PUBLISH;
    1174             :       vpe_client_registration_t *reg;
    1175             :       f64 now;
    1176             : 
    1177         579 :       vlib_process_wait_for_event (vm);
    1178             : 
    1179           4 :       vlib_process_get_event_data (vm, &event_type);
    1180           4 :       now = vlib_time_now (vm);
    1181             : 
    1182           4 :       if (event_type == L2_ARP_TERM_EVENT_PUBLISH)
    1183             :         {
    1184             :           l2_arp_term_publish_event_t *event;
    1185             : 
    1186          24 :           vec_foreach (event, l2am->publish_events)
    1187             :           {
    1188             :             /* dampen duplicate events - cast away volatile */
    1189          20 :             if (l2_arp_term_publish_event_is_equal
    1190           8 :                 (event, (l2_arp_term_publish_event_t *) & last_event) &&
    1191           8 :                 (now - last) < 10.0)
    1192             :               {
    1193           8 :                 continue;
    1194             :               }
    1195          12 :             last_event = *event;
    1196          12 :             last = now;
    1197             : 
    1198          24 :             pool_foreach (reg, vpe_api_main.l2_arp_term_events_registrations)
    1199             :               {
    1200             :                 vl_api_registration_t *vl_reg;
    1201             :                 vl_reg =
    1202          12 :                   vl_api_client_index_to_registration (reg->client_index);
    1203          12 :                 ALWAYS_ASSERT (vl_reg != NULL);
    1204             : 
    1205          12 :                 if (vl_reg && vl_api_can_send_msg (vl_reg))
    1206             :                   {
    1207             :                     vl_api_l2_arp_term_event_t *vevent;
    1208          12 :                     vevent = vl_msg_api_alloc (sizeof *vevent);
    1209          12 :                     clib_memset (vevent, 0, sizeof *vevent);
    1210          12 :                     vevent->_vl_msg_id =
    1211          12 :                       htons (REPLY_MSG_ID_BASE + VL_API_L2_ARP_TERM_EVENT);
    1212          12 :                     vevent->client_index = reg->client_index;
    1213          12 :                     vevent->pid = reg->client_pid;
    1214          12 :                     ip_address_encode (&event->ip, event->type, &vevent->ip);
    1215          12 :                     vevent->sw_if_index = htonl (event->sw_if_index);
    1216          12 :                     mac_address_encode (&event->mac, vevent->mac);
    1217          12 :                     vl_api_send_msg (vl_reg, (u8 *) vevent);
    1218             :                   }
    1219             :               }
    1220             :           }
    1221           4 :           vec_reset_length (l2am->publish_events);
    1222             :         }
    1223             :     }
    1224             : 
    1225             :   return 0;
    1226             : }
    1227             : 
    1228             : /* *INDENT-OFF* */
    1229      183788 : VLIB_REGISTER_NODE (l2_arp_term_process_node) = {
    1230             :   .function = l2_arp_term_process,
    1231             :   .type = VLIB_NODE_TYPE_PROCESS,
    1232             :   .name = "l2-arp-term-publisher",
    1233             : };
    1234             : /* *INDENT-ON* */
    1235             : 
    1236             : static void
    1237           4 : vl_api_want_l2_arp_term_events_t_handler (vl_api_want_l2_arp_term_events_t *
    1238             :                                           mp)
    1239             : {
    1240             :   vl_api_want_l2_arp_term_events_reply_t *rmp;
    1241           4 :   vpe_api_main_t *am = &vpe_api_main;
    1242             :   vpe_client_registration_t *rp;
    1243           4 :   int rv = 0;
    1244             :   uword *p;
    1245             : 
    1246           4 :   p = hash_get (am->l2_arp_term_events_registration_hash, mp->client_index);
    1247             : 
    1248           4 :   if (p)
    1249             :     {
    1250           2 :       if (mp->enable)
    1251             :         {
    1252           0 :           clib_warning ("pid %d: already enabled...", mp->pid);
    1253           0 :           rv = VNET_API_ERROR_INVALID_REGISTRATION;
    1254           0 :           goto reply;
    1255             :         }
    1256             :       else
    1257             :         {
    1258           2 :           rp = pool_elt_at_index (am->l2_arp_term_events_registrations, p[0]);
    1259           2 :           pool_put (am->l2_arp_term_events_registrations, rp);
    1260           2 :           hash_unset (am->l2_arp_term_events_registration_hash,
    1261             :                       mp->client_index);
    1262           2 :           if (pool_elts (am->l2_arp_term_events_registrations) == 0)
    1263           2 :             l2_arp_term_set_publisher_node (false);
    1264           2 :           goto reply;
    1265             :         }
    1266             :     }
    1267           2 :   if (mp->enable == 0)
    1268             :     {
    1269           0 :       clib_warning ("pid %d: already disabled...", mp->pid);
    1270           0 :       rv = VNET_API_ERROR_INVALID_REGISTRATION;
    1271           0 :       goto reply;
    1272             :     }
    1273           2 :   pool_get (am->l2_arp_term_events_registrations, rp);
    1274           2 :   rp->client_index = mp->client_index;
    1275           2 :   rp->client_pid = mp->pid;
    1276           2 :   hash_set (am->l2_arp_term_events_registration_hash, rp->client_index,
    1277             :             rp - am->l2_arp_term_events_registrations);
    1278           2 :   l2_arp_term_set_publisher_node (true);
    1279             : 
    1280           4 : reply:
    1281           4 :   REPLY_MACRO (VL_API_WANT_L2_ARP_TERM_EVENTS_REPLY);
    1282             : }
    1283             : 
    1284             : static clib_error_t *
    1285        1241 : want_l2_arp_term_events_reaper (u32 client_index)
    1286             : {
    1287             :   vpe_client_registration_t *rp;
    1288             :   vpe_api_main_t *am;
    1289             :   uword *p;
    1290             : 
    1291        1241 :   am = &vpe_api_main;
    1292             : 
    1293             :   /* remove from the registration hash */
    1294        1241 :   p = hash_get (am->l2_arp_term_events_registration_hash, client_index);
    1295             : 
    1296        1241 :   if (p)
    1297             :     {
    1298           0 :       rp = pool_elt_at_index (am->l2_arp_term_events_registrations, p[0]);
    1299           0 :       pool_put (am->l2_arp_term_events_registrations, rp);
    1300           0 :       hash_unset (am->l2_arp_term_events_registration_hash, client_index);
    1301           0 :       if (pool_elts (am->l2_arp_term_events_registrations) == 0)
    1302           0 :         l2_arp_term_set_publisher_node (false);
    1303             :     }
    1304        1241 :   return (NULL);
    1305             : }
    1306             : 
    1307         575 : VL_MSG_API_REAPER_FUNCTION (want_l2_arp_term_events_reaper);
    1308             : 
    1309             : #include <vnet/l2/l2.api.c>
    1310             : static clib_error_t *
    1311         575 : l2_api_hookup (vlib_main_t * vm)
    1312             : {
    1313         575 :   api_main_t *am = vlibapi_get_main ();
    1314             : 
    1315             :   /*
    1316             :    * Set up the (msg_name, crc, message-id) table
    1317             :    */
    1318         575 :   REPLY_MSG_ID_BASE = setup_message_id_table ();
    1319             : 
    1320             :   /* Mark VL_API_BRIDGE_DOMAIN_DUMP as mp safe */
    1321         575 :   vl_api_set_msg_thread_safe (
    1322         575 :     am, REPLY_MSG_ID_BASE + VL_API_BRIDGE_DOMAIN_DUMP, 1);
    1323             : 
    1324         575 :   return 0;
    1325             : }
    1326             : 
    1327        3455 : VLIB_API_INIT_FUNCTION (l2_api_hookup);
    1328             : 
    1329             : /*
    1330             :  * fd.io coding-style-patch-verification: ON
    1331             :  *
    1332             :  * Local Variables:
    1333             :  * eval: (c-set-style "gnu")
    1334             :  * End:
    1335             :  */

Generated by: LCOV version 1.14