/* *------------------------------------------------------------------ * interface_api.c - vnet interface api * * Copyright (c) 2016 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------ */ #include #include #include #include #include #include #include #include #include #include #include #include #define vl_typedefs /* define message structures */ #include #undef vl_typedefs #define vl_endianfun /* define message structures */ #include #undef vl_endianfun /* instantiate all the print functions we know about */ #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) #define vl_printfun #include #undef vl_printfun #include vpe_api_main_t vpe_api_main; #define foreach_vpe_api_msg \ _(SW_INTERFACE_SET_FLAGS, sw_interface_set_flags) \ _(HW_INTERFACE_SET_MTU, hw_interface_set_mtu) \ _(SW_INTERFACE_SET_MTU, sw_interface_set_mtu) \ _(WANT_INTERFACE_EVENTS, want_interface_events) \ _(SW_INTERFACE_DUMP, sw_interface_dump) \ _(SW_INTERFACE_ADD_DEL_ADDRESS, sw_interface_add_del_address) \ _(SW_INTERFACE_SET_RX_MODE, sw_interface_set_rx_mode) \ _(SW_INTERFACE_RX_PLACEMENT_DUMP, sw_interface_rx_placement_dump) \ _(SW_INTERFACE_SET_RX_PLACEMENT, sw_interface_set_rx_placement) \ _(SW_INTERFACE_SET_TABLE, sw_interface_set_table) \ _(SW_INTERFACE_GET_TABLE, sw_interface_get_table) \ _(SW_INTERFACE_SET_UNNUMBERED, sw_interface_set_unnumbered) \ _(SW_INTERFACE_CLEAR_STATS, sw_interface_clear_stats) \ _(SW_INTERFACE_TAG_ADD_DEL, sw_interface_tag_add_del) \ _(SW_INTERFACE_SET_MAC_ADDRESS, sw_interface_set_mac_address) \ _(SW_INTERFACE_GET_MAC_ADDRESS, sw_interface_get_mac_address) \ _(CREATE_VLAN_SUBIF, create_vlan_subif) \ _(CREATE_SUBIF, create_subif) \ _(DELETE_SUBIF, delete_subif) \ _(CREATE_LOOPBACK, create_loopback) \ _(CREATE_LOOPBACK_INSTANCE, create_loopback_instance) \ _(DELETE_LOOPBACK, delete_loopback) \ _(INTERFACE_NAME_RENUMBER, interface_name_renumber) \ _(COLLECT_DETAILED_INTERFACE_STATS, collect_detailed_interface_stats) \ _(SW_INTERFACE_SET_IP_DIRECTED_BROADCAST, \ sw_interface_set_ip_directed_broadcast) static void vl_api_sw_interface_set_flags_t_handler (vl_api_sw_interface_set_flags_t * mp) { vl_api_sw_interface_set_flags_reply_t *rmp; vnet_main_t *vnm = vnet_get_main (); int rv = 0; clib_error_t *error; u16 flags; VALIDATE_SW_IF_INDEX (mp); flags = mp->admin_up_down ? VNET_SW_INTERFACE_FLAG_ADMIN_UP : 0; error = vnet_sw_interface_set_flags (vnm, ntohl (mp->sw_if_index), flags); if (error) { rv = -1; clib_error_report (error); } BAD_SW_IF_INDEX_LABEL; REPLY_MACRO (VL_API_SW_INTERFACE_SET_FLAGS_REPLY); } static void vl_api_hw_interface_set_mtu_t_handler (vl_api_hw_interface_set_mtu_t * mp) { vl_api_hw_interface_set_mtu_reply_t *rmp; vnet_main_t *vnm = vnet_get_main (); u32 sw_if_index = ntohl (mp->sw_if_index); u16 mtu = ntohs (mp->mtu); ethernet_main_t *em = ðernet_main; int rv = 0; VALIDATE_SW_IF_INDEX (mp); vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index); if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE) { rv = VNET_API_ERROR_INVALID_VALUE; goto bad_sw_if_index; } vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, si->hw_if_index); ethernet_interface_t *eif = ethernet_get_interface (em, si->hw_if_index); if (!eif) { rv = VNET_API_ERROR_FEATURE_DISABLED; goto bad_sw_if_index; } if (mtu < hi->min_supported_packet_bytes) { rv = VNET_API_ERROR_INVALID_VALUE; goto bad_sw_if_index; } if (mtu > hi->max_supported_packet_bytes) { rv = VNET_API_ERROR_INVALID_VALUE; goto bad_sw_if_index; } vnet_hw_interface_set_mtu (vnm, si->hw_if_index, mtu); BAD_SW_IF_INDEX_LABEL; REPLY_MACRO (VL_API_HW_INTERFACE_SET_MTU_REPLY); } static void vl_api_sw_interface_set_mtu_t_handler (vl_api_sw_interface_set_mtu_t * mp) { vl_api_sw_interface_set_mtu_reply_t *rmp; vnet_main_t *vnm = vnet_get_main (); u32 sw_if_index = ntohl (mp->sw_if_index); int rv = 0; int i; u32 per_protocol_mtu[VNET_N_MTU]; VALIDATE_SW_IF_INDEX (mp); for (i = 0; i < VNET_N_MTU; i++) per_protocol_mtu[i] = ntohl (mp->mtu[i]); vnet_sw_interface_set_protocol_mtu (vnm, sw_if_index, per_protocol_mtu); BAD_SW_IF_INDEX_LABEL; REPLY_MACRO (VL_API_SW_INTERFACE_SET_MTU_REPLY); } static void vl_api_sw_interface_set_ip_directed_broadcast_t_handler (vl_api_sw_interface_set_ip_directed_broadcast_t * mp) { vl_api_sw_interface_set_ip_directed_broadcast_reply_t *rmp; u32 sw_if_index = ntohl (mp->sw_if_index); int rv = 0; VALIDATE_SW_IF_INDEX (mp); vnet_sw_interface_ip_directed_broadcast (vnet_get_main (), sw_if_index, mp->enable); BAD_SW_IF_INDEX_LABEL; REPLY_MACRO (VL_API_SW_INTERFACE_SET_IP_DIRECTED_BROADCAST_REPLY); } static void send_sw_interface_details (vpe_api_main_t * am, vl_api_registration_t * rp, vnet_sw_interface_t * swif, u8 * interface_name, u32 context) { vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (am->vnet_main, swif->sw_if_index); vl_api_sw_interface_details_t *mp = vl_msg_api_alloc (sizeof (*mp)); clib_memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_DETAILS); mp->sw_if_index = ntohl (swif->sw_if_index); mp->sup_sw_if_index = ntohl (swif->sup_sw_if_index); mp->admin_up_down = (swif->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? 1 : 0; mp->link_up_down = (hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ? 1 : 0; mp->link_duplex = ((hi->flags & VNET_HW_INTERFACE_FLAG_DUPLEX_MASK) >> VNET_HW_INTERFACE_FLAG_DUPLEX_SHIFT); mp->link_speed = ntohl (hi->link_speed); mp->link_mtu = ntohs (hi->max_packet_bytes); mp->mtu[VNET_MTU_L3] = ntohl (swif->mtu[VNET_MTU_L3]); mp->mtu[VNET_MTU_IP4] = ntohl (swif->mtu[VNET_MTU_IP4]); mp->mtu[VNET_MTU_IP6] = ntohl (swif->mtu[VNET_MTU_IP6]); mp->mtu[VNET_MTU_MPLS] = ntohl (swif->mtu[VNET_MTU_MPLS]); mp->context = context; strncpy ((char *) mp->interface_name, (char *) interface_name, ARRAY_LEN (mp->interface_name) - 1); /* Send the L2 address for ethernet physical intfcs */ if (swif->sup_sw_if_index == swif->sw_if_index && hi->hw_class_index == ethernet_hw_interface_class.index) { ethernet_main_t *em = ethernet_get_main (am->vlib_main); ethernet_interface_t *ei; ei = pool_elt_at_index (em->interfaces, hi->hw_instance); ASSERT (sizeof (mp->l2_address) >
/*
 * Copyright (c) 2016 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * bier_entry : The BIER entry
 *
 * The interface to the BIER entry is through a bier_entry_t* rather
 * than an index. This is because the BIER table allocates the entries
 * in a contiguous array once and only once when the table is created.
 * this is done for forwarding performance. The entry is thus not subject
 * to realloc, and does not need to be malloc'd when a route to that
 * bit-position is first learned.
 *
 */

#ifndef __BIER_ENTRY_H__
#define __BIER_ENTRY_H__

#include <vlib/vlib.h>
#include <vnet/fib/fib_node.h>
#include <vnet/bier/bier_types.h>

/**
 * Forward declarations
 */
struct bier_route_update_t_;
struct bier_fmask_db_t_;

/**
 * The BIER entry
 *
 * the BIER entry is the representation of a BIER forwarding egress router (BFER)
 * (or the egress PE) that is assigned a bit position.
 */
typedef struct bier_entry_t_ {
    /**
     * linkage into the FIB graph
     */
    fib_node_t be_node;

    /**
     * The index of the BIER table in which this entry resides
     */
    index_t be_bti;

    /**
     * the bit position this entry represents.
     *  this is the key table insertion
     */
    bier_bp_t be_bp;

    /**
     * the FIB path-list this entry resolves through.
     * the path-list is itself resoved on the entry's fmasks
     */
    fib_node_index_t be_path_list;
    /**
     * sibling index on the path list
     */
    fib_node_index_t be_sibling_index;
} bier_entry_t;

extern index_t bier_entry_create(index_t bti,
                                 bier_bp_t bp);
extern void bier_entry_delete(index_t bei);

extern void bier_entry_path_update (index_t bei,
                                    const fib_route_path_t *rpaths);

extern void bier_entry_path_add(index_t bei,
                                const fib_route_path_t *brp);

extern int bier_entry_path_remove(index_t bei,
                                  const fib_route_path_t *brp);

extern u8* format_bier_entry(u8* s, va_list *ap);

extern void bier_entry_contribute_forwarding(index_t bei,
                                             dpo_id_t *dpo);

extern bier_entry_t *bier_entry_pool;
always_inline bier_entry_t* bier_entry_get(index_t bei)
{
    return (&bier_entry_pool[bei]);
}
#endif
in_t * vm, u32 sw_if_index, u32 flags) { vpe_api_main_t *vam = &vpe_api_main; if (vam->link_state_process_up) { enum api_events event = flags ? API_SW_INTERFACE_ADD_EVENT : API_SW_INTERFACE_DEL_EVENT; vlib_process_signal_event (vam->vlib_main, link_state_process_node.index, event, sw_if_index); } return 0; } static void vl_api_sw_interface_tag_add_del_t_handler (vl_api_sw_interface_tag_add_del_t * mp) { vnet_main_t *vnm = vnet_get_main (); vl_api_sw_interface_tag_add_del_reply_t *rmp; int rv = 0; u8 *tag; u32 sw_if_index = ntohl (mp->sw_if_index); VALIDATE_SW_IF_INDEX (mp); if (mp->is_add) { if (mp->tag[0] == 0) { rv = VNET_API_ERROR_INVALID_VALUE; goto out; } mp->tag[ARRAY_LEN (mp->tag) - 1] = 0; tag = format (0, "%s%c", mp->tag, 0); vnet_set_sw_interface_tag (vnm, tag, sw_if_index); } else vnet_clear_sw_interface_tag (vnm, sw_if_index); BAD_SW_IF_INDEX_LABEL; out: REPLY_MACRO (VL_API_SW_INTERFACE_TAG_ADD_DEL_REPLY); } static void vl_api_sw_interface_set_mac_address_t_handler (vl_api_sw_interface_set_mac_address_t * mp) { vl_api_sw_interface_set_mac_address_reply_t *rmp; vnet_main_t *vnm = vnet_get_main (); u32 sw_if_index = ntohl (mp->sw_if_index); vnet_sw_interface_t *si; clib_error_t *error; int rv = 0; VALIDATE_SW_IF_INDEX (mp); si = vnet_get_sw_interface (vnm, sw_if_index); error = vnet_hw_interface_change_mac_address (vnm, si->hw_if_index, mp->mac_address); if (error) { rv = VNET_API_ERROR_UNIMPLEMENTED; clib_error_report (error); goto out; } BAD_SW_IF_INDEX_LABEL; out: REPLY_MACRO (VL_API_SW_INTERFACE_SET_MAC_ADDRESS_REPLY); } static void vl_api_sw_interface_get_mac_address_t_handler (vl_api_sw_interface_get_mac_address_t * mp) { vl_api_sw_interface_get_mac_address_reply_t *rmp; vl_api_registration_t *reg; vnet_main_t *vnm = vnet_get_main (); u32 sw_if_index = ntohl (mp->sw_if_index); vnet_sw_interface_t *si; ethernet_interface_t *eth_if = 0; int rv = 0; VALIDATE_SW_IF_INDEX (mp); si = vnet_get_sup_sw_interface (vnm, sw_if_index); if (si->type == VNET_SW_INTERFACE_TYPE_HARDWARE) eth_if = ethernet_get_interface (ðernet_main, si->hw_if_index); BAD_SW_IF_INDEX_LABEL; reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) return; rmp = vl_msg_api_alloc (sizeof (*rmp)); rmp->_vl_msg_id = htons (VL_API_SW_INTERFACE_GET_MAC_ADDRESS_REPLY); rmp->context = mp->context; rmp->retval = htonl (rv); if (!rv && eth_if) memcpy (rmp->mac_address, eth_if->address, 6); vl_api_send_msg (reg, (u8 *) rmp); } static void vl_api_sw_interface_set_rx_mode_t_handler (vl_api_sw_interface_set_rx_mode_t * mp) { vl_api_sw_interface_set_rx_mode_reply_t *rmp; vnet_main_t *vnm = vnet_get_main (); u32 sw_if_index = ntohl (mp->sw_if_index); vnet_sw_interface_t *si; clib_error_t *error; int rv = 0; VALIDATE_SW_IF_INDEX (mp); si = vnet_get_sw_interface (vnm, sw_if_index); if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE) { rv = VNET_API_ERROR_INVALID_VALUE; goto bad_sw_if_index; } error = set_hw_interface_change_rx_mode (vnm, si->hw_if_index, mp->queue_id_valid, ntohl (mp->queue_id), mp->mode); if (error) { rv = VNET_API_ERROR_UNIMPLEMENTED; clib_error_report (error); goto out; } BAD_SW_IF_INDEX_LABEL; out: REPLY_MACRO (VL_API_SW_INTERFACE_SET_RX_MODE_REPLY); } static void send_interface_rx_placement_details (vpe_api_main_t * am, vl_api_registration_t * rp, u32 sw_if_index, u32 worker_id, u32 queue_id, u8 mode, u32 context) { vl_api_sw_interface_rx_placement_details_t *mp; mp = vl_msg_api_alloc (sizeof (*mp)); clib_memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = htons (VL_API_SW_INTERFACE_RX_PLACEMENT_DETAILS); mp->sw_if_index = htonl (sw_if_index); mp->queue_id = htonl (queue_id); mp->worker_id = htonl (worker_id); mp->mode = mode; mp->context = context; vl_api_send_msg (rp, (u8 *) mp); } static void vl_api_sw_interface_rx_placement_dump_t_handler (vl_api_sw_interface_rx_placement_dump_t * mp) { vnet_main_t *vnm = vnet_get_main (); vpe_api_main_t *am = &vpe_api_main; u32 sw_if_index = ntohl (mp->sw_if_index); vl_api_registration_t *reg; reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) return; if (sw_if_index == ~0) { vnet_device_input_runtime_t *rt; vnet_device_and_queue_t *dq; vlib_node_t *pn = vlib_get_node_by_name (am->vlib_main, (u8 *) "device-input"); uword si; int index = 0; /* *INDENT-OFF* */ foreach_vlib_main (({ clib_bitmap_foreach (si, pn->sibling_bitmap, ({ rt = vlib_node_get_runtime_data (this_vlib_main, si); vec_foreach (dq, rt->devices_and_queues) { vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, dq->hw_if_index); send_interface_rx_placement_details (am, reg, hw->sw_if_index, index, dq->queue_id, dq->mode, mp->context); } })); index++; })); /* *INDENT-ON* */ } else { int i; vnet_sw_interface_t *si; if (!vnet_sw_if_index_is_api_valid (sw_if_index)) { clib_warning ("sw_if_index %u does not exist", sw_if_index); goto bad_sw_if_index; } si = vnet_get_sw_interface (vnm, sw_if_index); if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE) { clib_warning ("interface type is not HARDWARE! P2P, PIPE and SUB" " interfaces are not supported"); goto bad_sw_if_index; } vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, si->hw_if_index); for (i = 0; i < vec_len (hw->dq_runtime_index_by_queue); i++) { send_interface_rx_placement_details (am, reg, hw->sw_if_index, hw->input_node_thread_index_by_queue [i], i, hw->rx_mode_by_queue[i], mp->context); } } BAD_SW_IF_INDEX_LABEL; } static void vl_api_sw_interface_set_rx_placement_t_handler (vl_api_sw_interface_set_rx_placement_t * mp) { vl_api_sw_interface_set_rx_placement_reply_t *rmp; vnet_main_t *vnm = vnet_get_main (); u32 sw_if_index = ntohl (mp->sw_if_index); vnet_sw_interface_t *si; clib_error_t *error = 0; int rv = 0; VALIDATE_SW_IF_INDEX (mp); si = vnet_get_sw_interface (vnm, sw_if_index); if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE) { rv = VNET_API_ERROR_INVALID_VALUE; goto bad_sw_if_index; } error = set_hw_interface_rx_placement (si->hw_if_index, ntohl (mp->queue_id), ntohl (mp->worker_id), mp->is_main); if (error) { rv = VNET_API_ERROR_UNIMPLEMENTED; clib_error_report (error); goto out; } BAD_SW_IF_INDEX_LABEL; out: REPLY_MACRO (VL_API_SW_INTERFACE_SET_RX_PLACEMENT_REPLY); } static void vl_api_create_vlan_subif_t_handler (vl_api_create_vlan_subif_t * mp) { vl_api_create_vlan_subif_reply_t *rmp; vnet_main_t *vnm = vnet_get_main (); u32 sw_if_index = (u32) ~ 0; vnet_hw_interface_t *hi; int rv = 0; u32 id; vnet_sw_interface_t template; uword *p; vnet_interface_main_t *im = &vnm->interface_main; u64 sup_and_sub_key; vl_api_registration_t *reg; clib_error_t *error; VALIDATE_SW_IF_INDEX (mp); hi = vnet_get_sup_hw_interface (vnm, ntohl (mp->sw_if_index)); if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE) { rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED; goto out; } id = ntohl (mp->vlan_id); if (id == 0 || id > 4095) { rv = VNET_API_ERROR_INVALID_VLAN; goto out; } sup_and_sub_key = ((u64) (hi->sw_if_index) << 32) | (u64) id; p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key); if (p) { rv = VNET_API_ERROR_VLAN_ALREADY_EXISTS; goto out; } clib_memset (&template, 0, sizeof (template)); template.type = VNET_SW_INTERFACE_TYPE_SUB; template.flood_class = VNET_FLOOD_CLASS_NORMAL; template.sup_sw_if_index = hi->sw_if_index; template.sub.id = id; template.sub.eth.raw_flags = 0; template.sub.eth.flags.one_tag = 1; template.sub.eth.outer_vlan_id = id; template.sub.eth.flags.exact_match = 1; error = vnet_create_sw_interface (vnm, &template, &sw_if_index); if (error) { clib_error_report (error); rv = VNET_API_ERROR_INVALID_REGISTRATION; goto out; } u64 *kp = clib_mem_alloc (sizeof (*kp)); *kp = sup_and_sub_key; hash_set (hi->sub_interface_sw_if_index_by_id, id, sw_if_index); hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index); BAD_SW_IF_INDEX_LABEL; out: reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) return; rmp = vl_msg_api_alloc (sizeof (*rmp)); rmp->_vl_msg_id = htons (VL_API_CREATE_VLAN_SUBIF_REPLY); rmp->context = mp->context; rmp->retval = htonl (rv); rmp->sw_if_index = htonl (sw_if_index); vl_api_send_msg (reg, (u8 *) rmp); } static void vl_api_create_subif_t_handler (vl_api_create_subif_t * mp) { vl_api_create_subif_reply_t *rmp; vnet_main_t *vnm = vnet_get_main (); u32 sw_if_index = ~0; int rv = 0; u32 sub_id; vnet_sw_interface_t *si; vnet_hw_interface_t *hi; vnet_sw_interface_t template; uword *p; vnet_interface_main_t *im = &vnm->interface_main; u64 sup_and_sub_key; clib_error_t *error; VALIDATE_SW_IF_INDEX (mp); si = vnet_get_sup_sw_interface (vnm, ntohl (mp->sw_if_index)); hi = vnet_get_sup_hw_interface (vnm, ntohl (mp->sw_if_index)); if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE) { rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED; goto out; } sw_if_index = si->sw_if_index; sub_id = ntohl (mp->sub_id); sup_and_sub_key = ((u64) (sw_if_index) << 32) | (u64) sub_id; p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key); if (p) { if (CLIB_DEBUG > 0) clib_warning ("sup sw_if_index %d, sub id %d already exists\n", sw_if_index, sub_id); rv = VNET_API_ERROR_SUBIF_ALREADY_EXISTS; goto out; } clib_memset (&template, 0, sizeof (template)); template.type = VNET_SW_INTERFACE_TYPE_SUB; template.flood_class = VNET_FLOOD_CLASS_NORMAL; template.sup_sw_if_index = sw_if_index; template.sub.id = sub_id; template.sub.eth.flags.no_tags = mp->no_tags; template.sub.eth.flags.one_tag = mp->one_tag; template.sub.eth.flags.two_tags = mp->two_tags; template.sub.eth.flags.dot1ad = mp->dot1ad; template.sub.eth.flags.exact_match = mp->exact_match; template.sub.eth.flags.default_sub = mp->default_sub; template.sub.eth.flags.outer_vlan_id_any = mp->outer_vlan_id_any; template.sub.eth.flags.inner_vlan_id_any = mp->inner_vlan_id_any; template.sub.eth.outer_vlan_id = ntohs (mp->outer_vlan_id); template.sub.eth.inner_vlan_id = ntohs (mp->inner_vlan_id); error = vnet_create_sw_interface (vnm, &template, &sw_if_index); if (error) { clib_error_report (error); rv = VNET_API_ERROR_SUBIF_CREATE_FAILED; goto out; } u64 *kp = clib_mem_alloc (sizeof (*kp)); *kp = sup_and_sub_key; hash_set (hi->sub_interface_sw_if_index_by_id, sub_id, sw_if_index); hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index); BAD_SW_IF_INDEX_LABEL; out: /* *INDENT-OFF* */ REPLY_MACRO2(VL_API_CREATE_SUBIF_REPLY, ({ rmp->sw_if_index = ntohl(sw_if_index); })); /* *INDENT-ON* */ } static void vl_api_delete_subif_t_handler (vl_api_delete_subif_t * mp) { vl_api_delete_subif_reply_t *rmp; int rv; rv = vnet_delete_sub_interface (ntohl (mp->sw_if_index)); REPLY_MACRO (VL_API_DELETE_SUBIF_REPLY); } static void vl_api_interface_name_renumber_t_handler (vl_api_interface_name_renumber_t * mp) { vl_api_interface_name_renumber_reply_t *rmp; int rv = 0; VALIDATE_SW_IF_INDEX (mp); rv = vnet_interface_name_renumber (ntohl (mp->sw_if_index), ntohl (mp->new_show_dev_instance)); BAD_SW_IF_INDEX_LABEL; REPLY_MACRO (VL_API_INTERFACE_NAME_RENUMBER_REPLY); } static void vl_api_create_loopback_t_handler (vl_api_create_loopback_t * mp) { vl_api_create_loopback_reply_t *rmp; u32 sw_if_index; int rv; rv = vnet_create_loopback_interface (&sw_if_index, mp->mac_address, 0, 0); /* *INDENT-OFF* */ REPLY_MACRO2(VL_API_CREATE_LOOPBACK_REPLY, ({ rmp->sw_if_index = ntohl (sw_if_index); })); /* *INDENT-ON* */ } static void vl_api_create_loopback_instance_t_handler (vl_api_create_loopback_instance_t * mp) { vl_api_create_loopback_instance_reply_t *rmp; u32 sw_if_index; u8 is_specified = mp->is_specified; u32 user_instance = ntohl (mp->user_instance); int rv; rv = vnet_create_loopback_interface (&sw_if_index, mp->mac_address, is_specified, user_instance); /* *INDENT-OFF* */ REPLY_MACRO2(VL_API_CREATE_LOOPBACK_INSTANCE_REPLY, ({ rmp->sw_if_index = ntohl (sw_if_index); })); /* *INDENT-ON* */ } static void vl_api_delete_loopback_t_handler (vl_api_delete_loopback_t * mp) { vl_api_delete_loopback_reply_t *rmp; u32 sw_if_index; int rv; sw_if_index = ntohl (mp->sw_if_index); rv = vnet_delete_loopback_interface (sw_if_index); REPLY_MACRO (VL_API_DELETE_LOOPBACK_REPLY); } static void vl_api_collect_detailed_interface_stats_t_handler (vl_api_collect_detailed_interface_stats_t * mp) { vl_api_collect_detailed_interface_stats_reply_t *rmp; int rv = 0; rv = vnet_sw_interface_stats_collect_enable_disable (ntohl (mp->sw_if_index), mp->enable_disable); REPLY_MACRO (VL_API_COLLECT_DETAILED_INTERFACE_STATS_REPLY); } /* * vpe_api_hookup * Add vpe's API message handlers to the table. * vlib has already mapped shared memory and * added the client registration handlers. * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process() */ #define vl_msg_name_crc_list #include #undef vl_msg_name_crc_list static void setup_message_id_table (api_main_t * am) { #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id); foreach_vl_msg_name_crc_interface; #undef _ } pub_sub_handler (interface_events, INTERFACE_EVENTS); static clib_error_t * interface_api_hookup (vlib_main_t * vm) { api_main_t *am = &api_main; #define _(N,n) \ vl_msg_api_set_handlers(VL_API_##N, #n, \ vl_api_##n##_t_handler, \ vl_noop_handler, \ vl_api_##n##_t_endian, \ vl_api_##n##_t_print, \ sizeof(vl_api_##n##_t), 1); foreach_vpe_api_msg; #undef _ /* Mark these APIs as mp safe */ am->is_mp_safe[VL_API_SW_INTERFACE_DUMP] = 1; am->is_mp_safe[VL_API_SW_INTERFACE_DETAILS] = 1; am->is_mp_safe[VL_API_SW_INTERFACE_TAG_ADD_DEL] = 1; /* * Set up the (msg_name, crc, message-id) table */ setup_message_id_table (am); return 0; } VLIB_API_INIT_FUNCTION (interface_api_hookup); /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */