LCOV - code coverage report
Current view: top level - vnet - interface_api.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 412 794 51.9 %
Date: 2023-10-26 01:39:38 Functions: 41 60 68.3 %

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

Generated by: LCOV version 1.14