LCOV - code coverage report
Current view: top level - vnet - interface_api.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 412 779 52.9 %
Date: 2023-07-05 22:20:52 Functions: 41 59 69.5 %

          Line data    Source code
       1             : /*
       2             :  *------------------------------------------------------------------
       3             :  * interface_api.c - vnet interface api
       4             :  *
       5             :  * Copyright (c) 2016 Cisco and/or its affiliates.
       6             :  * Licensed under the Apache License, Version 2.0 (the "License");
       7             :  * you may not use this file except in compliance with the License.
       8             :  * You may obtain a copy of the License at:
       9             :  *
      10             :  *     http://www.apache.org/licenses/LICENSE-2.0
      11             :  *
      12             :  * Unless required by applicable law or agreed to in writing, software
      13             :  * distributed under the License is distributed on an "AS IS" BASIS,
      14             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15             :  * See the License for the specific language governing permissions and
      16             :  * limitations under the License.
      17             :  *------------------------------------------------------------------
      18             :  */
      19             : 
      20             : #include <vnet/vnet.h>
      21             : #include <vlibmemory/api.h>
      22             : 
      23             : #include <vnet/interface.h>
      24             : #include <vnet/interface/rx_queue_funcs.h>
      25             : #include <vnet/interface/tx_queue_funcs.h>
      26             : #include <vnet/api_errno.h>
      27             : #include <vnet/ethernet/ethernet.h>
      28             : #include <vnet/ip/ip.h>
      29             : #include <vnet/fib/fib_table.h>
      30             : #include <vnet/mfib/mfib_table.h>
      31             : #include <vnet/l2/l2_vtr.h>
      32             : #include <vnet/fib/fib_api.h>
      33             : #include <vnet/mfib/mfib_table.h>
      34             : #include <vlibapi/api_types.h>
      35             : 
      36             : #include <vnet/format_fns.h>
      37             : #include <vnet/ip/ip_types_api.h>
      38             : #include <vnet/ethernet/ethernet_types_api.h>
      39             : 
      40             : #include <interface.api_enum.h>
      41             : #include <interface.api_types.h>
      42             : 
      43             : #define REPLY_MSG_ID_BASE msg_id_base
      44             : #include <vlibapi/api_helper_macros.h>
      45             : 
      46             : static u16 msg_id_base;
      47             : 
      48             : vpe_api_main_t vpe_api_main;
      49             : 
      50             : #define foreach_vpe_api_msg                                                   \
      51             :   _ (SW_INTERFACE_SET_FLAGS, sw_interface_set_flags)                          \
      52             :   _ (SW_INTERFACE_SET_PROMISC, sw_interface_set_promisc)                      \
      53             :   _ (HW_INTERFACE_SET_MTU, hw_interface_set_mtu)                              \
      54             :   _ (SW_INTERFACE_SET_MTU, sw_interface_set_mtu)                              \
      55             :   _ (WANT_INTERFACE_EVENTS, want_interface_events)                            \
      56             :   _ (SW_INTERFACE_DUMP, sw_interface_dump)                                    \
      57             :   _ (SW_INTERFACE_ADD_DEL_ADDRESS, sw_interface_add_del_address)              \
      58             :   _ (SW_INTERFACE_SET_RX_MODE, sw_interface_set_rx_mode)                      \
      59             :   _ (SW_INTERFACE_RX_PLACEMENT_DUMP, sw_interface_rx_placement_dump)          \
      60             :   _ (SW_INTERFACE_TX_PLACEMENT_GET, sw_interface_tx_placement_get)            \
      61             :   _ (SW_INTERFACE_SET_RX_PLACEMENT, sw_interface_set_rx_placement)            \
      62             :   _ (SW_INTERFACE_SET_TX_PLACEMENT, sw_interface_set_tx_placement)            \
      63             :   _ (SW_INTERFACE_SET_TABLE, sw_interface_set_table)                          \
      64             :   _ (SW_INTERFACE_GET_TABLE, sw_interface_get_table)                          \
      65             :   _ (SW_INTERFACE_SET_UNNUMBERED, sw_interface_set_unnumbered)                \
      66             :   _ (SW_INTERFACE_CLEAR_STATS, sw_interface_clear_stats)                      \
      67             :   _ (SW_INTERFACE_TAG_ADD_DEL, sw_interface_tag_add_del)                      \
      68             :   _ (SW_INTERFACE_ADD_DEL_MAC_ADDRESS, sw_interface_add_del_mac_address)      \
      69             :   _ (SW_INTERFACE_SET_MAC_ADDRESS, sw_interface_set_mac_address)              \
      70             :   _ (SW_INTERFACE_GET_MAC_ADDRESS, sw_interface_get_mac_address)              \
      71             :   _ (CREATE_VLAN_SUBIF, create_vlan_subif)                                    \
      72             :   _ (CREATE_SUBIF, create_subif)                                              \
      73             :   _ (DELETE_SUBIF, delete_subif)                                              \
      74             :   _ (CREATE_LOOPBACK, create_loopback)                                        \
      75             :   _ (CREATE_LOOPBACK_INSTANCE, create_loopback_instance)                      \
      76             :   _ (DELETE_LOOPBACK, delete_loopback)                                        \
      77             :   _ (INTERFACE_NAME_RENUMBER, interface_name_renumber)                        \
      78             :   _ (COLLECT_DETAILED_INTERFACE_STATS, collect_detailed_interface_stats)      \
      79             :   _ (SW_INTERFACE_SET_IP_DIRECTED_BROADCAST,                                  \
      80             :      sw_interface_set_ip_directed_broadcast)                                  \
      81             :   _ (SW_INTERFACE_ADDRESS_REPLACE_BEGIN, sw_interface_address_replace_begin)  \
      82             :   _ (SW_INTERFACE_ADDRESS_REPLACE_END, sw_interface_address_replace_end)
      83             : 
      84             : static void
      85        6072 : vl_api_sw_interface_set_flags_t_handler (vl_api_sw_interface_set_flags_t * mp)
      86             : {
      87             :   vl_api_sw_interface_set_flags_reply_t *rmp;
      88        6072 :   vnet_main_t *vnm = vnet_get_main ();
      89        6072 :   int rv = 0;
      90             :   clib_error_t *error;
      91             :   u16 flags;
      92             : 
      93        6072 :   VALIDATE_SW_IF_INDEX (mp);
      94             : 
      95        6072 :   flags =
      96        6072 :     ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_ADMIN_UP) ?
      97        6072 :     VNET_SW_INTERFACE_FLAG_ADMIN_UP : 0;
      98             : 
      99        6072 :   error = vnet_sw_interface_set_flags (vnm, ntohl (mp->sw_if_index), flags);
     100        6072 :   if (error)
     101             :     {
     102           0 :       rv = -1;
     103           0 :       clib_error_report (error);
     104             :     }
     105             : 
     106        6072 :   BAD_SW_IF_INDEX_LABEL;
     107        6072 :   REPLY_MACRO (VL_API_SW_INTERFACE_SET_FLAGS_REPLY);
     108             : }
     109             : 
     110             : static void
     111           0 : vl_api_sw_interface_set_promisc_t_handler (
     112             :   vl_api_sw_interface_set_promisc_t *mp)
     113             : {
     114             :   vl_api_sw_interface_set_promisc_reply_t *rmp;
     115           0 :   vnet_main_t *vnm = vnet_get_main ();
     116           0 :   ethernet_main_t *em = &ethernet_main;
     117           0 :   int rv = 0;
     118             :   ethernet_interface_t *eif;
     119             :   vnet_sw_interface_t *swif;
     120             :   u32 flags, sw_if_index;
     121             : 
     122           0 :   VALIDATE_SW_IF_INDEX (mp);
     123             : 
     124           0 :   sw_if_index = ntohl (mp->sw_if_index);
     125           0 :   swif = vnet_get_sw_interface (vnm, sw_if_index);
     126           0 :   eif = ethernet_get_interface (em, swif->hw_if_index);
     127           0 :   if (!eif)
     128             :     {
     129           0 :       rv = VNET_API_ERROR_INVALID_VALUE;
     130           0 :       goto done;
     131             :     }
     132             : 
     133           0 :   flags = mp->promisc_on ? ETHERNET_INTERFACE_FLAG_ACCEPT_ALL : 0;
     134           0 :   rv = ethernet_set_flags (vnm, swif->hw_if_index, flags);
     135             : 
     136           0 : done:
     137           0 :   BAD_SW_IF_INDEX_LABEL;
     138           0 :   REPLY_MACRO (VL_API_SW_INTERFACE_SET_PROMISC_REPLY);
     139             : }
     140             : 
     141             : static void
     142           0 : vl_api_hw_interface_set_mtu_t_handler (vl_api_hw_interface_set_mtu_t * mp)
     143             : {
     144             :   vl_api_hw_interface_set_mtu_reply_t *rmp;
     145           0 :   vnet_main_t *vnm = vnet_get_main ();
     146           0 :   u32 sw_if_index = ntohl (mp->sw_if_index);
     147           0 :   u16 mtu = ntohs (mp->mtu);
     148           0 :   ethernet_main_t *em = &ethernet_main;
     149             :   clib_error_t *err;
     150           0 :   int rv = 0;
     151             : 
     152           0 :   VALIDATE_SW_IF_INDEX (mp);
     153             : 
     154           0 :   vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
     155           0 :   if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
     156             :     {
     157           0 :       rv = VNET_API_ERROR_INVALID_VALUE;
     158           0 :       goto bad_sw_if_index;
     159             :     }
     160             : 
     161           0 :   ethernet_interface_t *eif = ethernet_get_interface (em, si->hw_if_index);
     162             : 
     163           0 :   if (!eif)
     164             :     {
     165           0 :       rv = VNET_API_ERROR_FEATURE_DISABLED;
     166           0 :       goto bad_sw_if_index;
     167             :     }
     168             : 
     169           0 :   if ((err = vnet_hw_interface_set_mtu (vnm, si->hw_if_index, mtu)))
     170             :     {
     171           0 :       rv = vnet_api_error (err);
     172           0 :       clib_error_free (err);
     173           0 :       goto bad_sw_if_index;
     174             :     }
     175             : 
     176           0 :   BAD_SW_IF_INDEX_LABEL;
     177           0 :   REPLY_MACRO (VL_API_HW_INTERFACE_SET_MTU_REPLY);
     178             : }
     179             : 
     180             : static void
     181         543 : vl_api_sw_interface_set_mtu_t_handler (vl_api_sw_interface_set_mtu_t * mp)
     182             : {
     183             :   vl_api_sw_interface_set_mtu_reply_t *rmp;
     184         543 :   vnet_main_t *vnm = vnet_get_main ();
     185         543 :   u32 sw_if_index = ntohl (mp->sw_if_index);
     186         543 :   int rv = 0;
     187             :   int i;
     188             :   u32 per_protocol_mtu[VNET_N_MTU];
     189             : 
     190         543 :   VALIDATE_SW_IF_INDEX (mp);
     191             : 
     192        2715 :   for (i = 0; i < VNET_N_MTU; i++)
     193             :     {
     194        2172 :       per_protocol_mtu[i] = ntohl (mp->mtu[i]);
     195             :     }
     196         543 :   vnet_sw_interface_set_protocol_mtu (vnm, sw_if_index, per_protocol_mtu);
     197             : 
     198         543 :   BAD_SW_IF_INDEX_LABEL;
     199         543 :   REPLY_MACRO (VL_API_SW_INTERFACE_SET_MTU_REPLY);
     200             : }
     201             : 
     202             : static void
     203           3 :   vl_api_sw_interface_set_ip_directed_broadcast_t_handler
     204             :   (vl_api_sw_interface_set_ip_directed_broadcast_t * mp)
     205             : {
     206             :   vl_api_sw_interface_set_ip_directed_broadcast_reply_t *rmp;
     207           3 :   u32 sw_if_index = ntohl (mp->sw_if_index);
     208           3 :   int rv = 0;
     209             : 
     210           3 :   VALIDATE_SW_IF_INDEX (mp);
     211             : 
     212           3 :   vnet_sw_interface_ip_directed_broadcast (vnet_get_main (),
     213           3 :                                            sw_if_index, mp->enable);
     214             : 
     215           3 :   BAD_SW_IF_INDEX_LABEL;
     216           3 :   REPLY_MACRO (VL_API_SW_INTERFACE_SET_IP_DIRECTED_BROADCAST_REPLY);
     217             : }
     218             : 
     219             : static void
     220        6957 : send_sw_interface_details (vpe_api_main_t * am,
     221             :                            vl_api_registration_t * rp,
     222             :                            vnet_sw_interface_t * swif,
     223             :                            u8 * interface_name, u32 context)
     224             : {
     225             :   vnet_hw_interface_t *hi =
     226        6957 :     vnet_get_sup_hw_interface (am->vnet_main, swif->sw_if_index);
     227             :   vnet_device_class_t *dev_class =
     228        6957 :     vnet_get_device_class (am->vnet_main, hi->dev_class_index);
     229             : 
     230        6957 :   vl_api_sw_interface_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
     231        6957 :   clib_memset (mp, 0, sizeof (*mp));
     232        6957 :   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_DETAILS);
     233        6957 :   mp->sw_if_index = ntohl (swif->sw_if_index);
     234        6957 :   mp->sup_sw_if_index = ntohl (swif->sup_sw_if_index);
     235             : 
     236        6957 :   mp->flags |= (swif->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
     237        6957 :     IF_STATUS_API_FLAG_ADMIN_UP : 0;
     238        6957 :   mp->flags |= (hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ?
     239        6957 :     IF_STATUS_API_FLAG_LINK_UP : 0;
     240        6957 :   mp->flags = ntohl (mp->flags);
     241             : 
     242        6957 :   switch (swif->type)
     243             :     {
     244          90 :     case VNET_SW_INTERFACE_TYPE_SUB:
     245          90 :       mp->type = IF_API_TYPE_SUB;
     246          90 :       break;
     247          23 :     case VNET_SW_INTERFACE_TYPE_P2P:
     248          23 :       mp->type = IF_API_TYPE_P2P;
     249          23 :       break;
     250           0 :     case VNET_SW_INTERFACE_TYPE_PIPE:
     251           0 :       mp->type = IF_API_TYPE_PIPE;
     252           0 :       break;
     253        6844 :     default:
     254        6844 :       mp->type = IF_API_TYPE_HARDWARE;
     255             :     }
     256        6957 :   mp->type = ntohl (mp->type);
     257             : 
     258        6957 :   mp->link_duplex = ntohl (((hi->flags & VNET_HW_INTERFACE_FLAG_DUPLEX_MASK) >>
     259             :                             VNET_HW_INTERFACE_FLAG_DUPLEX_SHIFT));
     260        6957 :   mp->link_speed = ntohl (hi->link_speed);
     261        6957 :   mp->link_mtu = ntohs (hi->max_frame_size - hi->frame_overhead);
     262        6957 :   mp->mtu[VNET_MTU_L3] = ntohl (swif->mtu[VNET_MTU_L3]);
     263        6957 :   mp->mtu[VNET_MTU_IP4] = ntohl (swif->mtu[VNET_MTU_IP4]);
     264        6957 :   mp->mtu[VNET_MTU_IP6] = ntohl (swif->mtu[VNET_MTU_IP6]);
     265        6957 :   mp->mtu[VNET_MTU_MPLS] = ntohl (swif->mtu[VNET_MTU_MPLS]);
     266             : 
     267        6957 :   mp->context = context;
     268             : 
     269        6957 :   strncpy ((char *) mp->interface_name,
     270             :            (char *) interface_name, ARRAY_LEN (mp->interface_name) - 1);
     271             : 
     272        6957 :   if (dev_class && dev_class->name)
     273        6957 :     strncpy ((char *) mp->interface_dev_type, (char *) dev_class->name,
     274             :              ARRAY_LEN (mp->interface_dev_type) - 1);
     275             : 
     276             :   /* Send the L2 address for ethernet physical intfcs */
     277        6957 :   if (swif->sup_sw_if_index == swif->sw_if_index
     278        6844 :       && hi->hw_class_index == ethernet_hw_interface_class.index)
     279        6255 :     {
     280        6255 :       ethernet_main_t *em = ethernet_get_main (am->vlib_main);
     281             :       ethernet_interface_t *ei;
     282             : 
     283        6255 :       ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
     284             :       ASSERT (sizeof (mp->l2_address) >= sizeof (ei->address.mac));
     285        6255 :       mac_address_encode (&ei->address.mac, mp->l2_address);
     286             :     }
     287         702 :   else if (swif->sup_sw_if_index != swif->sw_if_index)
     288             :     {
     289         113 :       vnet_sub_interface_t *sub = &swif->sub;
     290         113 :       mp->sub_id = ntohl (sub->id);
     291         113 :       mp->sub_number_of_tags =
     292         113 :         sub->eth.flags.one_tag + sub->eth.flags.two_tags * 2;
     293         113 :       mp->sub_outer_vlan_id = ntohs (sub->eth.outer_vlan_id);
     294         113 :       mp->sub_inner_vlan_id = ntohs (sub->eth.inner_vlan_id);
     295         113 :       mp->sub_if_flags =
     296         113 :         ntohl (sub->eth.raw_flags & SUB_IF_API_FLAG_MASK_VNET);
     297             :     }
     298             : 
     299             :   /* vlan tag rewrite data */
     300        6957 :   u32 vtr_op = L2_VTR_DISABLED;
     301        6957 :   u32 vtr_push_dot1q = 0, vtr_tag1 = 0, vtr_tag2 = 0;
     302             : 
     303        6957 :   if (l2vtr_get (am->vlib_main, am->vnet_main, swif->sw_if_index,
     304             :                  &vtr_op, &vtr_push_dot1q, &vtr_tag1, &vtr_tag2) != 0)
     305             :     {
     306             :       // error - default to disabled
     307           0 :       mp->vtr_op = ntohl (L2_VTR_DISABLED);
     308           0 :       clib_warning ("cannot get vlan tag rewrite for sw_if_index %d",
     309             :                     swif->sw_if_index);
     310             :     }
     311             :   else
     312             :     {
     313        6957 :       mp->vtr_op = ntohl (vtr_op);
     314        6957 :       mp->vtr_push_dot1q = ntohl (vtr_push_dot1q);
     315        6957 :       mp->vtr_tag1 = ntohl (vtr_tag1);
     316        6957 :       mp->vtr_tag2 = ntohl (vtr_tag2);
     317             :     }
     318             : 
     319             :   /* pbb tag rewrite data */
     320             :   ethernet_header_t eth_hdr;
     321        6957 :   u32 pbb_vtr_op = L2_VTR_DISABLED;
     322        6957 :   u16 outer_tag = 0;
     323        6957 :   u16 b_vlanid = 0;
     324        6957 :   u32 i_sid = 0;
     325        6957 :   clib_memset (&eth_hdr, 0, sizeof (eth_hdr));
     326             : 
     327        6957 :   if (!l2pbb_get (am->vlib_main, am->vnet_main, swif->sw_if_index,
     328             :                   &pbb_vtr_op, &outer_tag, &eth_hdr, &b_vlanid, &i_sid))
     329             :     {
     330           0 :       mp->sub_if_flags |= ntohl (SUB_IF_API_FLAG_DOT1AH);
     331           0 :       mac_address_encode ((mac_address_t *) eth_hdr.dst_address, mp->b_dmac);
     332           0 :       mac_address_encode ((mac_address_t *) eth_hdr.src_address, mp->b_smac);
     333           0 :       mp->b_vlanid = b_vlanid;
     334           0 :       mp->i_sid = i_sid;
     335             :     }
     336             : 
     337        6957 :   u8 *tag = vnet_get_sw_interface_tag (vnet_get_main (), swif->sw_if_index);
     338        6957 :   if (tag)
     339           0 :     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
     340             : 
     341        6957 :   vl_api_send_msg (rp, (u8 *) mp);
     342        6957 : }
     343             : 
     344             : static void
     345        6247 : vl_api_sw_interface_dump_t_handler (vl_api_sw_interface_dump_t * mp)
     346             : {
     347        6247 :   vpe_api_main_t *am = &vpe_api_main;
     348             :   vnet_sw_interface_t *swif;
     349        6247 :   vnet_interface_main_t *im = &am->vnet_main->interface_main;
     350             :   vl_api_registration_t *rp;
     351             :   u32 sw_if_index;
     352             : 
     353        6247 :   rp = vl_api_client_index_to_registration (mp->client_index);
     354             : 
     355        6247 :   if (rp == 0)
     356             :     {
     357           0 :       clib_warning ("Client %d AWOL", mp->client_index);
     358        6099 :       return;
     359             :     }
     360             : 
     361        6247 :   u8 *filter = 0, *name = 0;
     362        6247 :   sw_if_index = ntohl (mp->sw_if_index);
     363             : 
     364        6247 :   if (!mp->name_filter_valid && sw_if_index != ~0 && sw_if_index != 0)
     365             :     {
     366             :       /* is it a valid sw_if_index? */
     367        6099 :       if (!vnet_sw_if_index_is_api_valid (sw_if_index))
     368           1 :         return;
     369             : 
     370        6098 :       swif = vec_elt_at_index (im->sw_interfaces, sw_if_index);
     371             : 
     372        6098 :       vec_reset_length (name);
     373        6098 :       name =
     374        6098 :         format (name, "%U%c", format_vnet_sw_interface_name, am->vnet_main,
     375             :                 swif, 0);
     376        6098 :       send_sw_interface_details (am, rp, swif, name, mp->context);
     377        6098 :       vec_free (name);
     378        6098 :       return;
     379             :     }
     380             : 
     381         148 :   if (mp->name_filter_valid)
     382             :     {
     383           3 :       filter = vl_api_from_api_to_new_vec (mp, &mp->name_filter);
     384           3 :       vec_add1 (filter, 0);     /* Ensure it's a C string for strcasecmp() */
     385             :     }
     386             : 
     387             :   char *strcasestr (char *, char *);    /* lnx hdr file botch */
     388             :   /* *INDENT-OFF* */
     389        1032 :   pool_foreach (swif, im->sw_interfaces)
     390             :    {
     391         884 :     if (!vnet_swif_is_api_visible (swif))
     392           0 :         continue;
     393         884 :     vec_reset_length(name);
     394         884 :     name = format (name, "%U%c", format_vnet_sw_interface_name, am->vnet_main,
     395             :                    swif, 0);
     396             : 
     397         884 :     if (filter && !strcasestr((char *) name, (char *) filter))
     398          25 :         continue;
     399             : 
     400         859 :     send_sw_interface_details (am, rp, swif, name, mp->context);
     401             :   }
     402             :   /* *INDENT-ON* */
     403             : 
     404         148 :   vec_free (name);
     405         148 :   vec_free (filter);
     406             : }
     407             : 
     408             : static void
     409        8153 :   vl_api_sw_interface_add_del_address_t_handler
     410             :   (vl_api_sw_interface_add_del_address_t * mp)
     411             : {
     412        8153 :   vlib_main_t *vm = vlib_get_main ();
     413        8153 :   vnet_main_t *vnm = vnet_get_main ();
     414             :   vl_api_sw_interface_add_del_address_reply_t *rmp;
     415        8153 :   int rv = 0;
     416             :   u32 is_del;
     417        8153 :   clib_error_t *error = 0;
     418             :   ip46_address_t address;
     419             : 
     420        8153 :   VALIDATE_SW_IF_INDEX (mp);
     421             : 
     422        8153 :   is_del = mp->is_add == 0;
     423        8153 :   vnm->api_errno = 0;
     424             : 
     425        8153 :   if (mp->del_all)
     426           0 :     ip_del_all_interface_addresses (vm, ntohl (mp->sw_if_index));
     427        8153 :   else if (ip_address_decode (&mp->prefix.address, &address) == IP46_TYPE_IP6)
     428        3744 :     error = ip6_add_del_interface_address (vm, ntohl (mp->sw_if_index),
     429             :                                            (void *) &address.ip6,
     430        3744 :                                            mp->prefix.len, is_del);
     431             :   else
     432        4409 :     error = ip4_add_del_interface_address (vm, ntohl (mp->sw_if_index),
     433             :                                            (void *) &address.ip4,
     434        4409 :                                            mp->prefix.len, is_del);
     435             : 
     436        8153 :   if (error)
     437             :     {
     438           3 :       rv = vnm->api_errno;
     439           3 :       clib_error_report (error);
     440           3 :       goto done;
     441             :     }
     442             : 
     443        8150 :   BAD_SW_IF_INDEX_LABEL;
     444             : 
     445        8153 : done:
     446        8153 :   REPLY_MACRO (VL_API_SW_INTERFACE_ADD_DEL_ADDRESS_REPLY);
     447             : }
     448             : 
     449             : static void
     450        1425 : vl_api_sw_interface_set_table_t_handler (vl_api_sw_interface_set_table_t * mp)
     451             : {
     452             :   vl_api_sw_interface_set_table_reply_t *rmp;
     453        1425 :   u32 sw_if_index = ntohl (mp->sw_if_index);
     454        1425 :   u32 table_id = ntohl (mp->vrf_id);
     455        1425 :   int rv = 0;
     456             : 
     457        1425 :   VALIDATE_SW_IF_INDEX (mp);
     458             : 
     459        1425 :   if (mp->is_ipv6)
     460         632 :     rv = ip_table_bind (FIB_PROTOCOL_IP6, sw_if_index, table_id);
     461             :   else
     462         793 :     rv = ip_table_bind (FIB_PROTOCOL_IP4, sw_if_index, table_id);
     463             : 
     464        1425 :   BAD_SW_IF_INDEX_LABEL;
     465             : 
     466        1425 :   REPLY_MACRO (VL_API_SW_INTERFACE_SET_TABLE_REPLY);
     467             : }
     468             : 
     469             : void
     470        1625 : fib_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 fib_index)
     471             : {
     472             :   u32 table_id;
     473             : 
     474        1625 :   table_id = fib_table_get_table_id (fib_index, fproto);
     475        1625 :   ASSERT (table_id != ~0);
     476             : 
     477        1625 :   if (FIB_PROTOCOL_IP6 == fproto)
     478             :     {
     479             :       /*
     480             :        * tell those that are interested that the binding is changing.
     481             :        */
     482             :       ip6_table_bind_callback_t *cb;
     483        4374 :       vec_foreach (cb, ip6_main.table_bind_callbacks)
     484        3645 :         cb->function (&ip6_main, cb->function_opaque,
     485             :                       sw_if_index,
     486             :                       fib_index,
     487        3645 :                       ip6_main.fib_index_by_sw_if_index[sw_if_index]);
     488             : 
     489             :       /* unlock currently assigned tables */
     490         729 :       if (0 != ip6_main.fib_index_by_sw_if_index[sw_if_index])
     491         258 :         fib_table_unlock (ip6_main.fib_index_by_sw_if_index[sw_if_index],
     492             :                           FIB_PROTOCOL_IP6, FIB_SOURCE_INTERFACE);
     493             : 
     494         729 :       if (0 != table_id)
     495             :         {
     496             :           /* we need to lock the table now it's inuse */
     497         259 :           fib_table_lock (fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_INTERFACE);
     498             :         }
     499             : 
     500         729 :       ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
     501             :     }
     502             :   else
     503             :     {
     504             :       /*
     505             :        * tell those that are interested that the binding is changing.
     506             :        */
     507             :       ip4_table_bind_callback_t *cb;
     508        8064 :       vec_foreach (cb, ip4_main.table_bind_callbacks)
     509        7168 :         cb->function (&ip4_main, cb->function_opaque,
     510             :                       sw_if_index,
     511             :                       fib_index,
     512        7168 :                       ip4_main.fib_index_by_sw_if_index[sw_if_index]);
     513             : 
     514             :       /* unlock currently assigned tables */
     515         896 :       if (0 != ip4_main.fib_index_by_sw_if_index[sw_if_index])
     516         325 :         fib_table_unlock (ip4_main.fib_index_by_sw_if_index[sw_if_index],
     517             :                           FIB_PROTOCOL_IP4, FIB_SOURCE_INTERFACE);
     518             : 
     519         896 :       if (0 != table_id)
     520             :         {
     521             :           /* we need to lock the table now it's inuse */
     522         356 :           fib_index = fib_table_find_or_create_and_lock (
     523             :             FIB_PROTOCOL_IP4, table_id, FIB_SOURCE_INTERFACE);
     524             :         }
     525             : 
     526         896 :       ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
     527             :     }
     528        1625 : }
     529             : 
     530             : void
     531        1596 : mfib_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 mfib_index)
     532             : {
     533             :   u32 table_id;
     534             : 
     535        1596 :   table_id = mfib_table_get_table_id (mfib_index, fproto);
     536        1596 :   ASSERT (table_id != ~0);
     537             : 
     538        1596 :   if (FIB_PROTOCOL_IP6 == fproto)
     539             :     {
     540         717 :       if (0 != ip6_main.mfib_index_by_sw_if_index[sw_if_index])
     541         254 :         mfib_table_unlock (ip6_main.mfib_index_by_sw_if_index[sw_if_index],
     542             :                            FIB_PROTOCOL_IP6, MFIB_SOURCE_INTERFACE);
     543             : 
     544         717 :       if (0 != table_id)
     545             :         {
     546             :           /* we need to lock the table now it's inuse */
     547         255 :           mfib_table_lock (mfib_index, FIB_PROTOCOL_IP6,
     548             :                            MFIB_SOURCE_INTERFACE);
     549             :         }
     550             : 
     551         717 :       ip6_main.mfib_index_by_sw_if_index[sw_if_index] = mfib_index;
     552             :     }
     553             :   else
     554             :     {
     555         879 :       if (0 != ip4_main.mfib_index_by_sw_if_index[sw_if_index])
     556         321 :         mfib_table_unlock (ip4_main.mfib_index_by_sw_if_index[sw_if_index],
     557             :                            FIB_PROTOCOL_IP4, MFIB_SOURCE_INTERFACE);
     558             : 
     559         879 :       if (0 != table_id)
     560             :         {
     561             :           /* we need to lock the table now it's inuse */
     562         352 :           mfib_index = mfib_table_find_or_create_and_lock (
     563             :             FIB_PROTOCOL_IP4, table_id, MFIB_SOURCE_INTERFACE);
     564             :         }
     565             : 
     566         879 :       ip4_main.mfib_index_by_sw_if_index[sw_if_index] = mfib_index;
     567             :     }
     568        1596 : }
     569             : 
     570             : int
     571        1428 : ip_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 table_id)
     572             : {
     573             :   CLIB_UNUSED (ip_interface_address_t * ia);
     574             :   u32 fib_index, mfib_index;
     575             : 
     576             :   /*
     577             :    * This if table does not exist = error is what we want in the end.
     578             :    */
     579        1428 :   fib_index = fib_table_find (fproto, table_id);
     580        1428 :   mfib_index = mfib_table_find (fproto, table_id);
     581             : 
     582        1428 :   if (~0 == fib_index || ~0 == mfib_index)
     583             :     {
     584           0 :       return (VNET_API_ERROR_NO_SUCH_FIB);
     585             :     }
     586             : 
     587             :   /*
     588             :    * If the interface already has in IP address, then a change int
     589             :    * VRF is not allowed. The IP address applied must first be removed.
     590             :    * We do not do that automatically here, since VPP has no knowledge
     591             :    * of whether those subnets are valid in the destination VRF.
     592             :    */
     593             :   /* clang-format off */
     594        1428 :   foreach_ip_interface_address (FIB_PROTOCOL_IP6 == fproto ?
     595             :                                 &ip6_main.lookup_main : &ip4_main.lookup_main,
     596             :                                 ia, sw_if_index,
     597             :                                 1 /* honor unnumbered */ ,
     598             :   ({
     599             :     return (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE);
     600             :   }));
     601             :   /* clang-format on */
     602             : 
     603        1428 :   fib_table_bind (fproto, sw_if_index, fib_index);
     604        1428 :   mfib_table_bind (fproto, sw_if_index, mfib_index);
     605             : 
     606        1428 :   return (0);
     607             : }
     608             : 
     609             : static void
     610           0 : send_sw_interface_get_table_reply (vl_api_registration_t * reg,
     611             :                                    u32 context, int retval, u32 vrf_id)
     612             : {
     613             :   vl_api_sw_interface_get_table_reply_t *mp;
     614             : 
     615           0 :   mp = vl_msg_api_alloc (sizeof (*mp));
     616           0 :   clib_memset (mp, 0, sizeof (*mp));
     617           0 :   mp->_vl_msg_id =
     618           0 :     ntohs (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_GET_TABLE_REPLY);
     619           0 :   mp->context = context;
     620           0 :   mp->retval = htonl (retval);
     621           0 :   mp->vrf_id = htonl (vrf_id);
     622             : 
     623           0 :   vl_api_send_msg (reg, (u8 *) mp);
     624           0 : }
     625             : 
     626             : static void
     627           0 : vl_api_sw_interface_get_table_t_handler (vl_api_sw_interface_get_table_t * mp)
     628             : {
     629             :   vl_api_registration_t *reg;
     630           0 :   fib_table_t *fib_table = 0;
     631           0 :   u32 sw_if_index = ~0;
     632           0 :   u32 fib_index = ~0;
     633           0 :   u32 table_id = ~0;
     634           0 :   fib_protocol_t fib_proto = FIB_PROTOCOL_IP4;
     635           0 :   int rv = 0;
     636             : 
     637           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
     638           0 :   if (!reg)
     639           0 :     return;
     640             : 
     641           0 :   VALIDATE_SW_IF_INDEX (mp);
     642             : 
     643           0 :   sw_if_index = ntohl (mp->sw_if_index);
     644             : 
     645           0 :   if (mp->is_ipv6)
     646           0 :     fib_proto = FIB_PROTOCOL_IP6;
     647             : 
     648           0 :   fib_index = fib_table_get_index_for_sw_if_index (fib_proto, sw_if_index);
     649           0 :   if (fib_index != ~0)
     650             :     {
     651           0 :       fib_table = fib_table_get (fib_index, fib_proto);
     652           0 :       table_id = fib_table->ft_table_id;
     653             :     }
     654             : 
     655           0 :   BAD_SW_IF_INDEX_LABEL;
     656             : 
     657           0 :   send_sw_interface_get_table_reply (reg, mp->context, rv, table_id);
     658             : }
     659             : 
     660          33 : static void vl_api_sw_interface_set_unnumbered_t_handler
     661             :   (vl_api_sw_interface_set_unnumbered_t * mp)
     662             : {
     663             :   vl_api_sw_interface_set_unnumbered_reply_t *rmp;
     664          33 :   int rv = 0;
     665          33 :   vnet_main_t *vnm = vnet_get_main ();
     666          33 :   u32 sw_if_index = ntohl (mp->sw_if_index);
     667          33 :   u32 unnumbered_sw_if_index = ntohl (mp->unnumbered_sw_if_index);
     668             : 
     669             :   /*
     670             :    * The API message field names are backwards from
     671             :    * the underlying data structure names.
     672             :    * It's not worth changing them now.
     673             :    */
     674          33 :   if (!vnet_sw_interface_is_api_valid (vnm, unnumbered_sw_if_index))
     675             :     {
     676           0 :       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
     677           0 :       goto done;
     678             :     }
     679             : 
     680             :   /* Only check the "use loop0" field when setting the binding */
     681          33 :   if (mp->is_add && !vnet_sw_interface_is_api_valid (vnm, sw_if_index))
     682             :     {
     683           0 :       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX_2;
     684           0 :       goto done;
     685             :     }
     686             : 
     687          33 :   rv = vnet_sw_interface_update_unnumbered (unnumbered_sw_if_index,
     688          33 :                                             sw_if_index, mp->is_add);
     689          33 : done:
     690          33 :   REPLY_MACRO (VL_API_SW_INTERFACE_SET_UNNUMBERED_REPLY);
     691             : }
     692             : 
     693             : static void
     694           0 : vl_api_sw_interface_clear_stats_t_handler (vl_api_sw_interface_clear_stats_t *
     695             :                                            mp)
     696             : {
     697             :   vl_api_sw_interface_clear_stats_reply_t *rmp;
     698             : 
     699           0 :   vnet_main_t *vnm = vnet_get_main ();
     700           0 :   vnet_interface_main_t *im = &vnm->interface_main;
     701             :   vlib_simple_counter_main_t *sm;
     702             :   vlib_combined_counter_main_t *cm;
     703             :   int j, n_counters;
     704           0 :   int rv = 0;
     705             : 
     706           0 :   if (mp->sw_if_index != ~0)
     707           0 :     VALIDATE_SW_IF_INDEX (mp);
     708             : 
     709           0 :   n_counters = vec_len (im->combined_sw_if_counters);
     710             : 
     711           0 :   for (j = 0; j < n_counters; j++)
     712             :     {
     713           0 :       im = &vnm->interface_main;
     714           0 :       cm = im->combined_sw_if_counters + j;
     715           0 :       if (mp->sw_if_index == (u32) ~ 0)
     716           0 :         vlib_clear_combined_counters (cm);
     717             :       else
     718           0 :         vlib_zero_combined_counter (cm, ntohl (mp->sw_if_index));
     719             :     }
     720             : 
     721           0 :   n_counters = vec_len (im->sw_if_counters);
     722             : 
     723           0 :   for (j = 0; j < n_counters; j++)
     724             :     {
     725           0 :       im = &vnm->interface_main;
     726           0 :       sm = im->sw_if_counters + j;
     727           0 :       if (mp->sw_if_index == (u32) ~ 0)
     728           0 :         vlib_clear_simple_counters (sm);
     729             :       else
     730           0 :         vlib_zero_simple_counter (sm, ntohl (mp->sw_if_index));
     731             :     }
     732             : 
     733           0 :   BAD_SW_IF_INDEX_LABEL;
     734             : 
     735           0 :   REPLY_MACRO (VL_API_SW_INTERFACE_CLEAR_STATS_REPLY);
     736             : }
     737             : 
     738             : /*
     739             :  * Events used for sw_interface_events
     740             :  */
     741             : enum api_events
     742             : {
     743             :   API_LINK_STATE_UP_EVENT = 1 << 1,
     744             :   API_LINK_STATE_DOWN_EVENT = 1 << 2,
     745             :   API_ADMIN_UP_EVENT = 1 << 3,
     746             :   API_ADMIN_DOWN_EVENT = 1 << 4,
     747             :   API_SW_INTERFACE_ADD_EVENT = 1 << 5,
     748             :   API_SW_INTERFACE_DEL_EVENT = 1 << 6,
     749             : };
     750             : 
     751             : static void
     752           4 : send_sw_interface_event (vpe_api_main_t * am,
     753             :                          vpe_client_registration_t * reg,
     754             :                          vl_api_registration_t * vl_reg,
     755             :                          u32 sw_if_index, enum api_events events)
     756             : {
     757             :   vl_api_sw_interface_event_t *mp;
     758             : 
     759           4 :   mp = vl_msg_api_alloc (sizeof (*mp));
     760           4 :   clib_memset (mp, 0, sizeof (*mp));
     761           4 :   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_EVENT);
     762           4 :   mp->sw_if_index = ntohl (sw_if_index);
     763           4 :   mp->client_index = reg->client_index;
     764           4 :   mp->pid = reg->client_pid;
     765           4 :   mp->flags = 0;
     766           4 :   mp->flags |= (events & API_ADMIN_UP_EVENT) ?
     767           4 :     IF_STATUS_API_FLAG_ADMIN_UP : 0;
     768           4 :   mp->flags |= (events & API_LINK_STATE_UP_EVENT) ?
     769           4 :     IF_STATUS_API_FLAG_LINK_UP : 0;
     770           4 :   mp->flags = ntohl (mp->flags);
     771           4 :   mp->deleted = events & API_SW_INTERFACE_DEL_EVENT ? true : false;
     772           4 :   vl_api_send_msg (vl_reg, (u8 *) mp);
     773           4 : }
     774             : 
     775             : static uword
     776         559 : link_state_process (vlib_main_t * vm,
     777             :                     vlib_node_runtime_t * rt, vlib_frame_t * f)
     778             : {
     779         559 :   vpe_api_main_t *vam = &vpe_api_main;
     780         559 :   uword *event_by_sw_if_index = 0;
     781             :   vpe_client_registration_t *reg;
     782             :   int i;
     783             :   vl_api_registration_t *vl_reg;
     784             :   uword event_type;
     785         559 :   uword *event_data = 0;
     786             :   u32 sw_if_index;
     787             : 
     788         559 :   vam->link_state_process_up = 1;
     789             : 
     790             :   while (1)
     791             :     {
     792       17695 :       vlib_process_wait_for_event (vm);
     793             : 
     794             :       /* Batch up events */
     795       54262 :       while ((event_type = vlib_process_get_events (vm, &event_data)) != ~0)
     796             :         {
     797       74524 :           for (i = 0; i < vec_len (event_data); i++)
     798             :             {
     799       37398 :               sw_if_index = event_data[i];
     800     1308630 :               vec_validate_init_empty (event_by_sw_if_index, sw_if_index, 0);
     801       37398 :               event_by_sw_if_index[sw_if_index] |= event_type;
     802             :             }
     803       37126 :           vec_reset_length (event_data);
     804             :         }
     805             : 
     806     1288360 :       for (i = 0; i < vec_len (event_by_sw_if_index); i++)
     807             :         {
     808     1271230 :           if (event_by_sw_if_index[i] == 0)
     809     1253970 :             continue;
     810             : 
     811             :           /* *INDENT-OFF* */
     812       17265 :           pool_foreach (reg, vam->interface_events_registrations)
     813             :            {
     814           4 :             vl_reg = vl_api_client_index_to_registration (reg->client_index);
     815           4 :             if (vl_reg)
     816           4 :               send_sw_interface_event (vam, reg, vl_reg, i, event_by_sw_if_index[i]);
     817             :           }
     818             :           /* *INDENT-ON* */
     819             :         }
     820       17136 :       vec_reset_length (event_by_sw_if_index);
     821             :     }
     822             : 
     823             :   return 0;
     824             : }
     825             : 
     826             : static clib_error_t *link_up_down_function (vnet_main_t * vm, u32 hw_if_index,
     827             :                                             u32 flags);
     828             : static clib_error_t *admin_up_down_function (vnet_main_t * vm,
     829             :                                              u32 hw_if_index, u32 flags);
     830             : static clib_error_t *sw_interface_add_del_function (vnet_main_t * vm,
     831             :                                                     u32 sw_if_index,
     832             :                                                     u32 flags);
     833             : 
     834             : /* *INDENT-OFF* */
     835      178120 : VLIB_REGISTER_NODE (link_state_process_node,static) = {
     836             :   .function = link_state_process,
     837             :   .type = VLIB_NODE_TYPE_PROCESS,
     838             :   .name = "vpe-link-state-process",
     839             : };
     840             : /* *INDENT-ON* */
     841             : 
     842        2801 : VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (admin_up_down_function);
     843        2801 : VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (link_up_down_function);
     844        3363 : VNET_SW_INTERFACE_ADD_DEL_FUNCTION (sw_interface_add_del_function);
     845             : 
     846             : static clib_error_t *
     847       13092 : link_up_down_function (vnet_main_t * vm, u32 hw_if_index, u32 flags)
     848             : {
     849       13092 :   vpe_api_main_t *vam = &vpe_api_main;
     850       13092 :   vnet_hw_interface_t *hi = vnet_get_hw_interface (vm, hw_if_index);
     851             : 
     852       13092 :   if (vam->link_state_process_up)
     853             :     {
     854       26184 :       enum api_events event = ((flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ?
     855       13092 :                                API_LINK_STATE_UP_EVENT :
     856             :                                API_LINK_STATE_DOWN_EVENT);
     857       13092 :       vlib_process_signal_event (vam->vlib_main,
     858       13092 :                                  link_state_process_node.index, event,
     859       13092 :                                  hi->sw_if_index);
     860             :     }
     861       13092 :   return 0;
     862             : }
     863             : 
     864             : static clib_error_t *
     865       13268 : admin_up_down_function (vnet_main_t * vm, u32 sw_if_index, u32 flags)
     866             : {
     867       13268 :   vpe_api_main_t *vam = &vpe_api_main;
     868             : 
     869             :   /*
     870             :    * Note: it's perfectly fair to set a subif admin up / admin down.
     871             :    * Note the subtle distinction between this routine and the previous
     872             :    * routine.
     873             :    */
     874       13268 :   if (vam->link_state_process_up)
     875             :     {
     876       26536 :       enum api_events event = ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
     877       13268 :                                API_ADMIN_UP_EVENT : API_ADMIN_DOWN_EVENT);
     878       13268 :       vlib_process_signal_event (vam->vlib_main,
     879       13268 :                                  link_state_process_node.index, event,
     880             :                                  sw_if_index);
     881             :     }
     882       13268 :   return 0;
     883             : }
     884             : 
     885             : static clib_error_t *
     886       11597 : sw_interface_add_del_function (vnet_main_t * vm, u32 sw_if_index, u32 flags)
     887             : {
     888       11597 :   vpe_api_main_t *vam = &vpe_api_main;
     889             : 
     890       11597 :   if (vam->link_state_process_up)
     891             :     {
     892       11038 :       enum api_events event =
     893       11038 :         flags ? API_SW_INTERFACE_ADD_EVENT : API_SW_INTERFACE_DEL_EVENT;
     894       11038 :       vlib_process_signal_event (vam->vlib_main,
     895       11038 :                                  link_state_process_node.index, event,
     896             :                                  sw_if_index);
     897             :     }
     898       11597 :   return 0;
     899             : }
     900             : 
     901           0 : static void vl_api_sw_interface_tag_add_del_t_handler
     902             :   (vl_api_sw_interface_tag_add_del_t * mp)
     903             : {
     904           0 :   vnet_main_t *vnm = vnet_get_main ();
     905             :   vl_api_sw_interface_tag_add_del_reply_t *rmp;
     906           0 :   int rv = 0;
     907             :   u8 *tag;
     908           0 :   u32 sw_if_index = ntohl (mp->sw_if_index);
     909             : 
     910           0 :   VALIDATE_SW_IF_INDEX (mp);
     911             : 
     912           0 :   if (mp->is_add)
     913             :     {
     914           0 :       if (mp->tag[0] == 0)
     915             :         {
     916           0 :           rv = VNET_API_ERROR_INVALID_VALUE;
     917           0 :           goto out;
     918             :         }
     919             : 
     920           0 :       mp->tag[ARRAY_LEN (mp->tag) - 1] = 0;
     921           0 :       tag = format (0, "%s%c", mp->tag, 0);
     922           0 :       vnet_set_sw_interface_tag (vnm, tag, sw_if_index);
     923             :     }
     924             :   else
     925           0 :     vnet_clear_sw_interface_tag (vnm, sw_if_index);
     926             : 
     927           0 :   BAD_SW_IF_INDEX_LABEL;
     928           0 : out:
     929           0 :   REPLY_MACRO (VL_API_SW_INTERFACE_TAG_ADD_DEL_REPLY);
     930             : }
     931             : 
     932           0 : static void vl_api_sw_interface_add_del_mac_address_t_handler
     933             :   (vl_api_sw_interface_add_del_mac_address_t * mp)
     934             : {
     935             :   vl_api_sw_interface_add_del_mac_address_reply_t *rmp;
     936           0 :   vnet_main_t *vnm = vnet_get_main ();
     937           0 :   u32 sw_if_index = ntohl (mp->sw_if_index);
     938             :   vnet_hw_interface_t *hi;
     939             :   clib_error_t *error;
     940           0 :   int rv = 0;
     941             : 
     942           0 :   VALIDATE_SW_IF_INDEX (mp);
     943             : 
     944             :   /* for subifs, the MAC should be changed on the actual hw if */
     945           0 :   hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
     946           0 :   error = vnet_hw_interface_add_del_mac_address (vnm, hi->hw_if_index,
     947           0 :                                                  mp->addr, mp->is_add);
     948           0 :   if (error)
     949             :     {
     950           0 :       rv = VNET_API_ERROR_UNIMPLEMENTED;
     951           0 :       clib_error_report (error);
     952           0 :       goto out;
     953             :     }
     954             : 
     955           0 :   BAD_SW_IF_INDEX_LABEL;
     956           0 : out:
     957           0 :   REPLY_MACRO (VL_API_SW_INTERFACE_ADD_DEL_MAC_ADDRESS_REPLY);
     958             : }
     959             : 
     960           3 : static void vl_api_sw_interface_set_mac_address_t_handler
     961             :   (vl_api_sw_interface_set_mac_address_t * mp)
     962             : {
     963             :   vl_api_sw_interface_set_mac_address_reply_t *rmp;
     964           3 :   vnet_main_t *vnm = vnet_get_main ();
     965           3 :   u32 sw_if_index = ntohl (mp->sw_if_index);
     966             :   vnet_sw_interface_t *si;
     967             :   clib_error_t *error;
     968           3 :   int rv = 0;
     969             :   mac_address_t mac;
     970             : 
     971           3 :   VALIDATE_SW_IF_INDEX (mp);
     972             : 
     973           3 :   si = vnet_get_sw_interface (vnm, sw_if_index);
     974           3 :   mac_address_decode (mp->mac_address, &mac);
     975             :   error =
     976           3 :     vnet_hw_interface_change_mac_address (vnm, si->hw_if_index, (u8 *) & mac);
     977           3 :   if (error)
     978             :     {
     979           0 :       rv = VNET_API_ERROR_UNIMPLEMENTED;
     980           0 :       clib_error_report (error);
     981           0 :       goto out;
     982             :     }
     983             : 
     984           3 :   BAD_SW_IF_INDEX_LABEL;
     985           3 : out:
     986           3 :   REPLY_MACRO (VL_API_SW_INTERFACE_SET_MAC_ADDRESS_REPLY);
     987             : }
     988             : 
     989           0 : static void vl_api_sw_interface_get_mac_address_t_handler
     990             :   (vl_api_sw_interface_get_mac_address_t * mp)
     991             : {
     992             :   vl_api_sw_interface_get_mac_address_reply_t *rmp;
     993             :   vl_api_registration_t *reg;
     994           0 :   vnet_main_t *vnm = vnet_get_main ();
     995           0 :   u32 sw_if_index = ntohl (mp->sw_if_index);
     996             :   vnet_sw_interface_t *si;
     997           0 :   ethernet_interface_t *eth_if = 0;
     998           0 :   int rv = 0;
     999             : 
    1000           0 :   VALIDATE_SW_IF_INDEX (mp);
    1001             : 
    1002           0 :   si = vnet_get_sup_sw_interface (vnm, sw_if_index);
    1003           0 :   if (si->type == VNET_SW_INTERFACE_TYPE_HARDWARE)
    1004           0 :     eth_if = ethernet_get_interface (&ethernet_main, si->hw_if_index);
    1005             : 
    1006           0 :   BAD_SW_IF_INDEX_LABEL;
    1007             : 
    1008           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
    1009           0 :   if (!reg)
    1010           0 :     return;
    1011           0 :   rmp = vl_msg_api_alloc (sizeof (*rmp));
    1012           0 :   rmp->_vl_msg_id =
    1013           0 :     htons (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_GET_MAC_ADDRESS_REPLY);
    1014           0 :   rmp->context = mp->context;
    1015           0 :   rmp->retval = htonl (rv);
    1016           0 :   if (!rv && eth_if)
    1017           0 :     mac_address_encode (&eth_if->address.mac, rmp->mac_address);
    1018           0 :   vl_api_send_msg (reg, (u8 *) rmp);
    1019             : }
    1020             : 
    1021             : static void
    1022           0 : vl_api_sw_interface_set_interface_name_t_handler (
    1023             :   vl_api_sw_interface_set_interface_name_t *mp)
    1024             : {
    1025             :   vl_api_sw_interface_set_interface_name_reply_t *rmp;
    1026           0 :   vnet_main_t *vnm = vnet_get_main ();
    1027           0 :   u32 sw_if_index = ntohl (mp->sw_if_index);
    1028           0 :   vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
    1029             :   clib_error_t *error;
    1030           0 :   int rv = 0;
    1031             : 
    1032           0 :   if (mp->name[0] == 0)
    1033             :     {
    1034           0 :       rv = VNET_API_ERROR_INVALID_VALUE;
    1035           0 :       goto out;
    1036             :     }
    1037           0 :   if (si == 0)
    1038             :     {
    1039           0 :       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
    1040           0 :       goto out;
    1041             :     }
    1042             : 
    1043           0 :   error = vnet_rename_interface (vnm, si->hw_if_index, (char *) mp->name);
    1044           0 :   if (error)
    1045             :     {
    1046           0 :       clib_error_free (error);
    1047           0 :       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
    1048             :     }
    1049             : 
    1050           0 : out:
    1051           0 :   REPLY_MACRO (VL_API_SW_INTERFACE_SET_INTERFACE_NAME_REPLY);
    1052             : }
    1053             : 
    1054           0 : static void vl_api_sw_interface_set_rx_mode_t_handler
    1055             :   (vl_api_sw_interface_set_rx_mode_t * mp)
    1056             : {
    1057             :   vl_api_sw_interface_set_rx_mode_reply_t *rmp;
    1058           0 :   vnet_main_t *vnm = vnet_get_main ();
    1059           0 :   u32 sw_if_index = ntohl (mp->sw_if_index);
    1060             :   vnet_sw_interface_t *si;
    1061             :   clib_error_t *error;
    1062           0 :   int rv = 0;
    1063             :   vnet_hw_if_rx_mode rx_mode;
    1064             : 
    1065           0 :   VALIDATE_SW_IF_INDEX (mp);
    1066             : 
    1067           0 :   si = vnet_get_sw_interface (vnm, sw_if_index);
    1068           0 :   if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
    1069             :     {
    1070           0 :       rv = VNET_API_ERROR_INVALID_VALUE;
    1071           0 :       goto bad_sw_if_index;
    1072             :     }
    1073             : 
    1074           0 :   rx_mode = (vnet_hw_if_rx_mode) ntohl (mp->mode);
    1075           0 :   error = set_hw_interface_change_rx_mode (vnm, si->hw_if_index,
    1076           0 :                                            mp->queue_id_valid,
    1077             :                                            ntohl (mp->queue_id),
    1078             :                                            (vnet_hw_if_rx_mode) rx_mode);
    1079             : 
    1080           0 :   if (error)
    1081             :     {
    1082           0 :       rv = VNET_API_ERROR_UNIMPLEMENTED;
    1083           0 :       clib_error_report (error);
    1084           0 :       goto out;
    1085             :     }
    1086             : 
    1087           0 :   BAD_SW_IF_INDEX_LABEL;
    1088           0 : out:
    1089           0 :   REPLY_MACRO (VL_API_SW_INTERFACE_SET_RX_MODE_REPLY);
    1090             : }
    1091             : 
    1092             : static void
    1093           0 : send_interface_rx_placement_details (vpe_api_main_t * am,
    1094             :                                      vl_api_registration_t * rp,
    1095             :                                      u32 sw_if_index, u32 worker_id,
    1096             :                                      u32 queue_id, u8 mode, u32 context)
    1097             : {
    1098             :   vl_api_sw_interface_rx_placement_details_t *mp;
    1099           0 :   mp = vl_msg_api_alloc (sizeof (*mp));
    1100           0 :   clib_memset (mp, 0, sizeof (*mp));
    1101             : 
    1102           0 :   mp->_vl_msg_id =
    1103           0 :     htons (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_RX_PLACEMENT_DETAILS);
    1104           0 :   mp->sw_if_index = htonl (sw_if_index);
    1105           0 :   mp->queue_id = htonl (queue_id);
    1106           0 :   mp->worker_id = htonl (worker_id);
    1107           0 :   mp->mode = htonl (mode);
    1108           0 :   mp->context = context;
    1109             : 
    1110           0 :   vl_api_send_msg (rp, (u8 *) mp);
    1111           0 : }
    1112             : 
    1113           0 : static void vl_api_sw_interface_rx_placement_dump_t_handler
    1114             :   (vl_api_sw_interface_rx_placement_dump_t * mp)
    1115             : {
    1116           0 :   vnet_main_t *vnm = vnet_get_main ();
    1117           0 :   vpe_api_main_t *am = &vpe_api_main;
    1118           0 :   u32 sw_if_index = ntohl (mp->sw_if_index);
    1119             :   vl_api_registration_t *reg;
    1120             : 
    1121           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
    1122           0 :   if (!reg)
    1123           0 :     return;
    1124             : 
    1125           0 :   if (sw_if_index == ~0)
    1126             :     {
    1127           0 :       vnet_hw_if_rx_queue_t **all_queues = 0;
    1128             :       vnet_hw_if_rx_queue_t **qptr;
    1129             :       vnet_hw_if_rx_queue_t *q;
    1130           0 :       pool_foreach (q, vnm->interface_main.hw_if_rx_queues)
    1131           0 :         vec_add1 (all_queues, q);
    1132           0 :       vec_sort_with_function (all_queues, vnet_hw_if_rxq_cmp_cli_api);
    1133             : 
    1134           0 :       vec_foreach (qptr, all_queues)
    1135             :         {
    1136           0 :           u32 current_thread = qptr[0]->thread_index;
    1137           0 :           u32 hw_if_index = qptr[0]->hw_if_index;
    1138             :           vnet_hw_interface_t *hw_if =
    1139           0 :             vnet_get_hw_interface (vnm, hw_if_index);
    1140           0 :           send_interface_rx_placement_details (
    1141           0 :             am, reg, hw_if->sw_if_index, current_thread, qptr[0]->queue_id,
    1142           0 :             qptr[0]->mode, mp->context);
    1143             :         }
    1144           0 :       vec_free (all_queues);
    1145             :     }
    1146             :   else
    1147             :     {
    1148             :       int i;
    1149             :       vnet_sw_interface_t *si;
    1150             : 
    1151           0 :       if (!vnet_sw_if_index_is_api_valid (sw_if_index))
    1152             :         {
    1153           0 :           clib_warning ("sw_if_index %u does not exist", sw_if_index);
    1154           0 :           goto bad_sw_if_index;
    1155             :         }
    1156             : 
    1157           0 :       si = vnet_get_sw_interface (vnm, sw_if_index);
    1158           0 :       if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
    1159             :         {
    1160           0 :           clib_warning ("interface type is not HARDWARE! P2P, PIPE and SUB"
    1161             :                         " interfaces are not supported");
    1162           0 :           goto bad_sw_if_index;
    1163             :         }
    1164             : 
    1165           0 :       vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, si->hw_if_index);
    1166             : 
    1167           0 :       for (i = 0; i < vec_len (hw->rx_queue_indices); i++)
    1168             :         {
    1169             :           vnet_hw_if_rx_queue_t *rxq =
    1170           0 :             vnet_hw_if_get_rx_queue (vnm, hw->rx_queue_indices[i]);
    1171           0 :           send_interface_rx_placement_details (
    1172             :             am, reg, hw->sw_if_index, rxq->thread_index, rxq->queue_id,
    1173           0 :             rxq->mode, mp->context);
    1174             :         }
    1175             :     }
    1176             : 
    1177           0 :   BAD_SW_IF_INDEX_LABEL;
    1178             : }
    1179             : 
    1180           0 : static void vl_api_sw_interface_set_rx_placement_t_handler
    1181             :   (vl_api_sw_interface_set_rx_placement_t * mp)
    1182             : {
    1183             :   vl_api_sw_interface_set_rx_placement_reply_t *rmp;
    1184           0 :   vnet_main_t *vnm = vnet_get_main ();
    1185           0 :   u32 sw_if_index = ntohl (mp->sw_if_index);
    1186             :   vnet_sw_interface_t *si;
    1187           0 :   clib_error_t *error = 0;
    1188           0 :   int rv = 0;
    1189             : 
    1190           0 :   VALIDATE_SW_IF_INDEX (mp);
    1191             : 
    1192           0 :   si = vnet_get_sw_interface (vnm, sw_if_index);
    1193           0 :   if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
    1194             :     {
    1195           0 :       rv = VNET_API_ERROR_INVALID_VALUE;
    1196           0 :       goto bad_sw_if_index;
    1197             :     }
    1198             : 
    1199           0 :   error = set_hw_interface_rx_placement (si->hw_if_index,
    1200             :                                          ntohl (mp->queue_id),
    1201           0 :                                          ntohl (mp->worker_id), mp->is_main);
    1202           0 :   if (error)
    1203             :     {
    1204           0 :       rv = VNET_API_ERROR_UNIMPLEMENTED;
    1205           0 :       clib_error_report (error);
    1206           0 :       goto out;
    1207             :     }
    1208             : 
    1209           0 :   BAD_SW_IF_INDEX_LABEL;
    1210           0 : out:
    1211           0 :   REPLY_MACRO (VL_API_SW_INTERFACE_SET_RX_PLACEMENT_REPLY);
    1212             : }
    1213             : 
    1214             : static void
    1215           0 : send_interface_tx_placement_details (vnet_hw_if_tx_queue_t **all_queues,
    1216             :                                      u32 index, vl_api_registration_t *rp,
    1217             :                                      u32 context)
    1218             : {
    1219           0 :   vnet_main_t *vnm = vnet_get_main ();
    1220             :   vl_api_sw_interface_tx_placement_details_t *rmp;
    1221           0 :   u32 n_bits = 0, v = ~0;
    1222           0 :   vnet_hw_if_tx_queue_t **q = vec_elt_at_index (all_queues, index);
    1223           0 :   uword *bitmap = q[0]->threads;
    1224           0 :   u32 hw_if_index = q[0]->hw_if_index;
    1225           0 :   vnet_hw_interface_t *hw_if = vnet_get_hw_interface (vnm, hw_if_index);
    1226             : 
    1227           0 :   n_bits = clib_bitmap_count_set_bits (bitmap);
    1228           0 :   u32 n = n_bits * sizeof (u32);
    1229             : 
    1230           0 :   REPLY_MACRO_DETAILS5_END (VL_API_SW_INTERFACE_TX_PLACEMENT_DETAILS, n, rp,
    1231             :                             context, ({
    1232             :                               rmp->sw_if_index = hw_if->sw_if_index;
    1233             :                               rmp->queue_id = q[0]->queue_id;
    1234             :                               rmp->shared = q[0]->shared_queue;
    1235             :                               rmp->array_size = n_bits;
    1236             : 
    1237             :                               v = clib_bitmap_first_set (bitmap);
    1238             :                               for (u32 i = 0; i < n_bits; i++)
    1239             :                                 {
    1240             :                                   rmp->threads[i] = v;
    1241             :                                   v = clib_bitmap_next_set (bitmap, v + 1);
    1242             :                                 }
    1243             :                             }));
    1244           0 : }
    1245             : 
    1246             : static void
    1247           0 : vl_api_sw_interface_tx_placement_get_t_handler (
    1248             :   vl_api_sw_interface_tx_placement_get_t *mp)
    1249             : {
    1250           0 :   vnet_main_t *vnm = vnet_get_main ();
    1251           0 :   vl_api_sw_interface_tx_placement_get_reply_t *rmp = 0;
    1252           0 :   vnet_hw_if_tx_queue_t **all_queues = 0;
    1253             :   vnet_hw_if_tx_queue_t *q;
    1254           0 :   u32 sw_if_index = mp->sw_if_index;
    1255           0 :   i32 rv = 0;
    1256             : 
    1257           0 :   if (pool_elts (vnm->interface_main.hw_if_tx_queues) == 0)
    1258             :     {
    1259           0 :       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
    1260           0 :       goto err;
    1261             :     }
    1262             : 
    1263           0 :   if (sw_if_index == ~0)
    1264             :     {
    1265           0 :       pool_foreach (q, vnm->interface_main.hw_if_tx_queues)
    1266           0 :         vec_add1 (all_queues, q);
    1267           0 :       vec_sort_with_function (all_queues, vnet_hw_if_txq_cmp_cli_api);
    1268             :     }
    1269             :   else
    1270             :     {
    1271           0 :       u32 qi = ~0;
    1272             :       vnet_sw_interface_t *si;
    1273             : 
    1274           0 :       if (!vnet_sw_if_index_is_api_valid (sw_if_index))
    1275             :         {
    1276           0 :           clib_warning ("sw_if_index %u does not exist", sw_if_index);
    1277           0 :           rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
    1278           0 :           goto err;
    1279             :         }
    1280             : 
    1281           0 :       si = vnet_get_sw_interface (vnm, sw_if_index);
    1282           0 :       if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
    1283             :         {
    1284           0 :           clib_warning ("interface type is not HARDWARE! P2P, PIPE and SUB"
    1285             :                         " interfaces are not supported");
    1286           0 :           rv = VNET_API_ERROR_INVALID_INTERFACE;
    1287           0 :           goto err;
    1288             :         }
    1289             : 
    1290           0 :       vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, si->hw_if_index);
    1291           0 :       for (qi = 0; qi < vec_len (hw->tx_queue_indices); qi++)
    1292             :         {
    1293           0 :           q = vnet_hw_if_get_tx_queue (vnm, hw->tx_queue_indices[qi]);
    1294           0 :           vec_add1 (all_queues, q);
    1295             :         }
    1296             :     }
    1297             : 
    1298           0 :   REPLY_AND_DETAILS_VEC_MACRO_END (VL_API_SW_INTERFACE_TX_PLACEMENT_GET_REPLY,
    1299             :                                    all_queues, mp, rmp, rv, ({
    1300             :                                      send_interface_tx_placement_details (
    1301             :                                        all_queues, cursor, rp, mp->context);
    1302             :                                    }));
    1303             : 
    1304           0 :   vec_free (all_queues);
    1305           0 :   return;
    1306             : 
    1307           0 : err:
    1308           0 :   REPLY_MACRO_END (VL_API_SW_INTERFACE_TX_PLACEMENT_GET_REPLY);
    1309             : }
    1310             : 
    1311             : static void
    1312           0 : vl_api_sw_interface_set_tx_placement_t_handler (
    1313             :   vl_api_sw_interface_set_tx_placement_t *mp)
    1314             : {
    1315             :   vl_api_sw_interface_set_tx_placement_reply_t *rmp;
    1316           0 :   vnet_main_t *vnm = vnet_get_main ();
    1317           0 :   u32 sw_if_index = mp->sw_if_index;
    1318             :   vnet_sw_interface_t *si;
    1319           0 :   uword *bitmap = 0;
    1320           0 :   u32 queue_id = ~0;
    1321           0 :   u32 size = 0;
    1322           0 :   clib_error_t *error = 0;
    1323           0 :   int rv = 0;
    1324             : 
    1325           0 :   VALIDATE_SW_IF_INDEX_END (mp);
    1326             : 
    1327           0 :   si = vnet_get_sw_interface (vnm, sw_if_index);
    1328           0 :   if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
    1329             :     {
    1330           0 :       rv = VNET_API_ERROR_INVALID_VALUE;
    1331           0 :       goto bad_sw_if_index;
    1332             :     }
    1333             : 
    1334           0 :   size = mp->array_size;
    1335           0 :   for (u32 i = 0; i < size; i++)
    1336             :     {
    1337           0 :       u32 thread_index = mp->threads[i];
    1338           0 :       bitmap = clib_bitmap_set (bitmap, thread_index, 1);
    1339             :     }
    1340             : 
    1341           0 :   queue_id = mp->queue_id;
    1342           0 :   rv = set_hw_interface_tx_queue (si->hw_if_index, queue_id, bitmap);
    1343             : 
    1344           0 :   switch (rv)
    1345             :     {
    1346           0 :     case VNET_API_ERROR_INVALID_VALUE:
    1347           0 :       error = clib_error_return (
    1348             :         0, "please specify valid thread(s) - last thread index %u",
    1349             :         clib_bitmap_last_set (bitmap));
    1350           0 :       break;
    1351           0 :     case VNET_API_ERROR_INVALID_QUEUE:
    1352           0 :       error = clib_error_return (
    1353             :         0, "unknown queue %u on interface %s", queue_id,
    1354             :         vnet_get_hw_interface (vnet_get_main (), si->hw_if_index)->name);
    1355           0 :       break;
    1356           0 :     default:
    1357           0 :       break;
    1358             :     }
    1359             : 
    1360           0 :   if (error)
    1361             :     {
    1362           0 :       clib_error_report (error);
    1363           0 :       goto out;
    1364             :     }
    1365             : 
    1366           0 :   BAD_SW_IF_INDEX_LABEL;
    1367           0 : out:
    1368           0 :   REPLY_MACRO_END (VL_API_SW_INTERFACE_SET_TX_PLACEMENT_REPLY);
    1369           0 :   clib_bitmap_free (bitmap);
    1370             : }
    1371             : 
    1372             : static void
    1373          72 : vl_api_create_vlan_subif_t_handler (vl_api_create_vlan_subif_t * mp)
    1374             : {
    1375             :   vl_api_create_vlan_subif_reply_t *rmp;
    1376          72 :   vnet_main_t *vnm = vnet_get_main ();
    1377          72 :   u32 sw_if_index = (u32) ~ 0;
    1378             :   vnet_hw_interface_t *hi;
    1379          72 :   int rv = 0;
    1380             :   u32 id;
    1381             :   vnet_sw_interface_t template;
    1382             :   uword *p;
    1383          72 :   vnet_interface_main_t *im = &vnm->interface_main;
    1384             :   u64 sup_and_sub_key;
    1385             :   vl_api_registration_t *reg;
    1386             :   clib_error_t *error;
    1387             : 
    1388          72 :   VALIDATE_SW_IF_INDEX (mp);
    1389             : 
    1390          72 :   hi = vnet_get_sup_hw_interface (vnm, ntohl (mp->sw_if_index));
    1391             : 
    1392          72 :   if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE)
    1393             :     {
    1394           0 :       rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED;
    1395           0 :       goto out;
    1396             :     }
    1397             : 
    1398          72 :   id = ntohl (mp->vlan_id);
    1399          72 :   if (id == 0 || id > 4095)
    1400             :     {
    1401           0 :       rv = VNET_API_ERROR_INVALID_VLAN;
    1402           0 :       goto out;
    1403             :     }
    1404             : 
    1405          72 :   sup_and_sub_key = ((u64) (hi->sw_if_index) << 32) | (u64) id;
    1406             : 
    1407          72 :   p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
    1408          72 :   if (p)
    1409             :     {
    1410           0 :       rv = VNET_API_ERROR_VLAN_ALREADY_EXISTS;
    1411           0 :       goto out;
    1412             :     }
    1413             : 
    1414          72 :   clib_memset (&template, 0, sizeof (template));
    1415          72 :   template.type = VNET_SW_INTERFACE_TYPE_SUB;
    1416          72 :   template.flood_class = VNET_FLOOD_CLASS_NORMAL;
    1417          72 :   template.sup_sw_if_index = hi->sw_if_index;
    1418          72 :   template.sub.id = id;
    1419          72 :   template.sub.eth.raw_flags = 0;
    1420          72 :   template.sub.eth.flags.one_tag = 1;
    1421          72 :   template.sub.eth.outer_vlan_id = id;
    1422          72 :   template.sub.eth.flags.exact_match = 1;
    1423             : 
    1424          72 :   error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
    1425          72 :   if (error)
    1426             :     {
    1427           0 :       clib_error_report (error);
    1428           0 :       rv = VNET_API_ERROR_INVALID_REGISTRATION;
    1429           0 :       goto out;
    1430             :     }
    1431             : 
    1432          72 :   u64 *kp = clib_mem_alloc (sizeof (*kp));
    1433          72 :   *kp = sup_and_sub_key;
    1434             : 
    1435          72 :   hash_set (hi->sub_interface_sw_if_index_by_id, id, sw_if_index);
    1436         144 :   hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
    1437             : 
    1438          72 :   BAD_SW_IF_INDEX_LABEL;
    1439             : 
    1440          72 : out:
    1441          72 :   reg = vl_api_client_index_to_registration (mp->client_index);
    1442          72 :   if (!reg)
    1443           0 :     return;
    1444             : 
    1445          72 :   rmp = vl_msg_api_alloc (sizeof (*rmp));
    1446          72 :   rmp->_vl_msg_id = htons (REPLY_MSG_ID_BASE + VL_API_CREATE_VLAN_SUBIF_REPLY);
    1447          72 :   rmp->context = mp->context;
    1448          72 :   rmp->retval = htonl (rv);
    1449          72 :   rmp->sw_if_index = htonl (sw_if_index);
    1450          72 :   vl_api_send_msg (reg, (u8 *) rmp);
    1451             : }
    1452             : 
    1453             : static void
    1454          18 : vl_api_create_subif_t_handler (vl_api_create_subif_t * mp)
    1455             : {
    1456             :   vl_api_create_subif_reply_t *rmp;
    1457          18 :   vnet_main_t *vnm = vnet_get_main ();
    1458          18 :   u32 sub_sw_if_index = ~0;
    1459             :   vnet_hw_interface_t *hi;
    1460          18 :   int rv = 0;
    1461             : 
    1462          18 :   VALIDATE_SW_IF_INDEX (mp);
    1463             : 
    1464          18 :   hi = vnet_get_sup_hw_interface (vnm, ntohl (mp->sw_if_index));
    1465             : 
    1466          18 :   if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE)
    1467           0 :     rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED;
    1468             :   else
    1469          18 :     rv = vnet_create_sub_interface (ntohl (mp->sw_if_index),
    1470             :                                     ntohl (mp->sub_id),
    1471          18 :                                     ntohl (mp->sub_if_flags),
    1472          18 :                                     ntohs (mp->inner_vlan_id),
    1473          18 :                                     ntohs (mp->outer_vlan_id),
    1474             :                                     &sub_sw_if_index);
    1475             : 
    1476          18 :   BAD_SW_IF_INDEX_LABEL;
    1477             : 
    1478             :   /* *INDENT-OFF* */
    1479          18 :   REPLY_MACRO2(VL_API_CREATE_SUBIF_REPLY,
    1480             :   ({
    1481             :     rmp->sw_if_index = ntohl(sub_sw_if_index);
    1482             :   }));
    1483             :   /* *INDENT-ON* */
    1484             : }
    1485             : 
    1486             : static void
    1487          41 : vl_api_delete_subif_t_handler (vl_api_delete_subif_t * mp)
    1488             : {
    1489             :   vl_api_delete_subif_reply_t *rmp;
    1490             :   int rv;
    1491             : 
    1492          41 :   rv = vnet_delete_sub_interface (ntohl (mp->sw_if_index));
    1493             : 
    1494          41 :   REPLY_MACRO (VL_API_DELETE_SUBIF_REPLY);
    1495             : }
    1496             : 
    1497             : static void
    1498           0 : vl_api_interface_name_renumber_t_handler (vl_api_interface_name_renumber_t *
    1499             :                                           mp)
    1500             : {
    1501             :   vl_api_interface_name_renumber_reply_t *rmp;
    1502           0 :   int rv = 0;
    1503             : 
    1504           0 :   VALIDATE_SW_IF_INDEX (mp);
    1505             : 
    1506           0 :   rv = vnet_interface_name_renumber
    1507             :     (ntohl (mp->sw_if_index), ntohl (mp->new_show_dev_instance));
    1508             : 
    1509           0 :   BAD_SW_IF_INDEX_LABEL;
    1510             : 
    1511           0 :   REPLY_MACRO (VL_API_INTERFACE_NAME_RENUMBER_REPLY);
    1512             : }
    1513             : 
    1514             : static void
    1515         165 : vl_api_create_loopback_t_handler (vl_api_create_loopback_t * mp)
    1516             : {
    1517             :   vl_api_create_loopback_reply_t *rmp;
    1518             :   u32 sw_if_index;
    1519             :   int rv;
    1520             :   mac_address_t mac;
    1521             : 
    1522         165 :   mac_address_decode (mp->mac_address, &mac);
    1523         165 :   rv = vnet_create_loopback_interface (&sw_if_index, (u8 *) & mac, 0, 0);
    1524             : 
    1525             :   /* *INDENT-OFF* */
    1526         165 :   REPLY_MACRO2(VL_API_CREATE_LOOPBACK_REPLY,
    1527             :   ({
    1528             :     rmp->sw_if_index = ntohl (sw_if_index);
    1529             :   }));
    1530             :   /* *INDENT-ON* */
    1531             : }
    1532             : 
    1533           2 : static void vl_api_create_loopback_instance_t_handler
    1534             :   (vl_api_create_loopback_instance_t * mp)
    1535             : {
    1536             :   vl_api_create_loopback_instance_reply_t *rmp;
    1537             :   u32 sw_if_index;
    1538           2 :   u8 is_specified = mp->is_specified;
    1539           2 :   u32 user_instance = ntohl (mp->user_instance);
    1540             :   int rv;
    1541             :   mac_address_t mac;
    1542             : 
    1543           2 :   mac_address_decode (mp->mac_address, &mac);
    1544           2 :   rv = vnet_create_loopback_interface (&sw_if_index, (u8 *) & mac,
    1545             :                                        is_specified, user_instance);
    1546             : 
    1547             :   /* *INDENT-OFF* */
    1548           2 :   REPLY_MACRO2(VL_API_CREATE_LOOPBACK_INSTANCE_REPLY,
    1549             :   ({
    1550             :     rmp->sw_if_index = ntohl (sw_if_index);
    1551             :   }));
    1552             :   /* *INDENT-ON* */
    1553             : }
    1554             : 
    1555             : static void
    1556         107 : vl_api_delete_loopback_t_handler (vl_api_delete_loopback_t * mp)
    1557             : {
    1558             :   vl_api_delete_loopback_reply_t *rmp;
    1559             :   u32 sw_if_index;
    1560             :   int rv;
    1561             : 
    1562         107 :   sw_if_index = ntohl (mp->sw_if_index);
    1563         107 :   rv = vnet_delete_loopback_interface (sw_if_index);
    1564             : 
    1565         107 :   REPLY_MACRO (VL_API_DELETE_LOOPBACK_REPLY);
    1566             : }
    1567             : 
    1568             : static void
    1569           0 :   vl_api_collect_detailed_interface_stats_t_handler
    1570             :   (vl_api_collect_detailed_interface_stats_t * mp)
    1571             : {
    1572             :   vl_api_collect_detailed_interface_stats_reply_t *rmp;
    1573           0 :   int rv = 0;
    1574             : 
    1575             :   rv =
    1576           0 :     vnet_sw_interface_stats_collect_enable_disable (ntohl (mp->sw_if_index),
    1577           0 :                                                     mp->enable_disable);
    1578             : 
    1579           0 :   REPLY_MACRO (VL_API_COLLECT_DETAILED_INTERFACE_STATS_REPLY);
    1580             : }
    1581             : 
    1582             : static void
    1583          10 :   vl_api_sw_interface_address_replace_begin_t_handler
    1584             :   (vl_api_sw_interface_address_replace_begin_t * mp)
    1585             : {
    1586             :   vl_api_sw_interface_address_replace_begin_reply_t *rmp;
    1587          10 :   int rv = 0;
    1588             : 
    1589          10 :   ip_interface_address_mark ();
    1590             : 
    1591          10 :   REPLY_MACRO (VL_API_SW_INTERFACE_ADDRESS_REPLACE_BEGIN_REPLY);
    1592             : }
    1593             : 
    1594             : static void
    1595          10 :   vl_api_sw_interface_address_replace_end_t_handler
    1596             :   (vl_api_sw_interface_address_replace_end_t * mp)
    1597             : {
    1598             :   vl_api_sw_interface_address_replace_end_reply_t *rmp;
    1599          10 :   int rv = 0;
    1600             : 
    1601          10 :   ip_interface_address_sweep ();
    1602             : 
    1603          10 :   REPLY_MACRO (VL_API_SW_INTERFACE_ADDRESS_REPLACE_END_REPLY);
    1604             : }
    1605             : 
    1606             : static void
    1607           3 : vl_api_pcap_trace_on_t_handler (vl_api_pcap_trace_on_t *mp)
    1608             : {
    1609             :   vl_api_pcap_trace_on_reply_t *rmp;
    1610             :   unformat_input_t filename, drop_err_name;
    1611             :   vnet_pcap_dispatch_trace_args_t capture_args;
    1612           3 :   int rv = 0;
    1613             : 
    1614           3 :   VALIDATE_SW_IF_INDEX (mp);
    1615             : 
    1616           3 :   unformat_init_cstring (&filename, (char *) mp->filename);
    1617           3 :   if (!unformat_user (&filename, unformat_vlib_tmpfile,
    1618             :                       &capture_args.filename))
    1619             :     {
    1620           0 :       rv = VNET_API_ERROR_ILLEGAL_NAME;
    1621           0 :       goto out;
    1622             :     }
    1623             : 
    1624           3 :   capture_args.rx_enable = mp->capture_rx;
    1625           3 :   capture_args.tx_enable = mp->capture_tx;
    1626           3 :   capture_args.preallocate_data = mp->preallocate_data;
    1627           3 :   capture_args.free_data = mp->free_data;
    1628           3 :   capture_args.drop_enable = mp->capture_drop;
    1629           3 :   capture_args.status = 0;
    1630           3 :   capture_args.packets_to_capture = ntohl (mp->max_packets);
    1631           3 :   capture_args.sw_if_index = ntohl (mp->sw_if_index);
    1632           3 :   capture_args.filter = mp->filter;
    1633           3 :   capture_args.max_bytes_per_pkt = ntohl (mp->max_bytes_per_packet);
    1634           3 :   capture_args.drop_err = ~0;
    1635             : 
    1636           3 :   unformat_init_cstring (&drop_err_name, (char *) mp->error);
    1637           3 :   unformat_user (&drop_err_name, unformat_vlib_error, vlib_get_main (),
    1638             :                  &capture_args.drop_err);
    1639             : 
    1640           3 :   rv = vnet_pcap_dispatch_trace_configure (&capture_args);
    1641             : 
    1642           3 :   BAD_SW_IF_INDEX_LABEL;
    1643             : 
    1644           3 : out:
    1645           3 :   unformat_free (&filename);
    1646           3 :   unformat_free (&drop_err_name);
    1647             : 
    1648           3 :   REPLY_MACRO (VL_API_PCAP_TRACE_ON_REPLY);
    1649             : }
    1650             : 
    1651             : static void
    1652           3 : vl_api_pcap_trace_off_t_handler (vl_api_pcap_trace_off_t *mp)
    1653             : {
    1654             :   vl_api_pcap_trace_off_reply_t *rmp;
    1655             :   vnet_pcap_dispatch_trace_args_t capture_args;
    1656           3 :   int rv = 0;
    1657             : 
    1658           3 :   clib_memset (&capture_args, 0, sizeof (capture_args));
    1659             : 
    1660           3 :   rv = vnet_pcap_dispatch_trace_configure (&capture_args);
    1661             : 
    1662           3 :   REPLY_MACRO (VL_API_PCAP_TRACE_OFF_REPLY);
    1663             : }
    1664             : 
    1665             : /*
    1666             :  * vpe_api_hookup
    1667             :  * Add vpe's API message handlers to the table.
    1668             :  * vlib has already mapped shared memory and
    1669             :  * added the client registration handlers.
    1670             :  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
    1671             :  */
    1672             : 
    1673        1767 : pub_sub_handler (interface_events, INTERFACE_EVENTS);
    1674             : 
    1675             : #include <vnet/interface.api.c>
    1676             : static clib_error_t *
    1677         559 : interface_api_hookup (vlib_main_t * vm)
    1678             : {
    1679         559 :   api_main_t *am = vlibapi_get_main ();
    1680             : 
    1681             :   /*
    1682             :    * Set up the (msg_name, crc, message-id) table
    1683             :    */
    1684         559 :   REPLY_MSG_ID_BASE = setup_message_id_table ();
    1685             : 
    1686             :   /* Mark these APIs as mp safe */
    1687         559 :   vl_api_set_msg_thread_safe (am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_DUMP,
    1688             :                               1);
    1689         559 :   vl_api_set_msg_thread_safe (
    1690         559 :     am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_DETAILS, 1);
    1691         559 :   vl_api_set_msg_thread_safe (
    1692         559 :     am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_TAG_ADD_DEL, 1);
    1693         559 :   vl_api_set_msg_thread_safe (
    1694         559 :     am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_SET_INTERFACE_NAME, 1);
    1695             : 
    1696             :   /* Do not replay VL_API_SW_INTERFACE_DUMP messages */
    1697         559 :   vl_api_allow_msg_replay (am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_DUMP,
    1698             :                            0);
    1699             : 
    1700             :   /* Mark these APIs as autoendian */
    1701         559 :   vl_api_set_msg_autoendian (
    1702         559 :     am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_SET_TX_PLACEMENT, 1);
    1703         559 :   vl_api_set_msg_autoendian (
    1704         559 :     am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_TX_PLACEMENT_GET, 1);
    1705             : 
    1706         559 :   return 0;
    1707             : }
    1708             : 
    1709        1679 : VLIB_API_INIT_FUNCTION (interface_api_hookup);
    1710             : 
    1711             : /*
    1712             :  * fd.io coding-style-patch-verification: ON
    1713             :  *
    1714             :  * Local Variables:
    1715             :  * eval: (c-set-style "gnu")
    1716             :  * End:
    1717             :  */

Generated by: LCOV version 1.14