/* *------------------------------------------------------------------ * 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_L
/*
 * 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.
 */

#ifndef __BIER_UPDATE_H__
#define __BIER_UPDATE_H__

#include <vppinfra/types.h>
#include <vnet/bier/bier_types.h>
#include <vnet/ip/ip.h>


#endif
B_PROTOCOL_IP4, msrc); } else { /* we need to lock the table now it's inuse */ fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id, src); mfib_index = mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id, msrc); } ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index; ip4_main.mfib_index_by_sw_if_index[sw_if_index] = mfib_index; } return (0); } static void send_sw_interface_get_table_reply (vl_api_registration_t * reg, u32 context, int retval, u32 vrf_id) { vl_api_sw_interface_get_table_reply_t *mp; mp = vl_msg_api_alloc (sizeof (*mp)); memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_GET_TABLE_REPLY); mp->context = context; mp->retval = htonl (retval); mp->vrf_id = htonl (vrf_id); vl_api_send_msg (reg, (u8 *) mp); } static void vl_api_sw_interface_get_table_t_handler (vl_api_sw_interface_get_table_t * mp) { vl_api_registration_t *reg; fib_table_t *fib_table = 0; u32 sw_if_index = ~0; u32 fib_index = ~0; u32 table_id = ~0; fib_protocol_t fib_proto = FIB_PROTOCOL_IP4; int rv = 0; reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) return; VALIDATE_SW_IF_INDEX (mp); sw_if_index = ntohl (mp->sw_if_index); if (mp->is_ipv6) fib_proto = FIB_PROTOCOL_IP6; fib_index = fib_table_get_index_for_sw_if_index (fib_proto, sw_if_index); if (fib_index != ~0) { fib_table = fib_table_get (fib_index, fib_proto); table_id = fib_table->ft_table_id; } BAD_SW_IF_INDEX_LABEL; send_sw_interface_get_table_reply (reg, mp->context, rv, table_id); } static void vl_api_sw_interface_set_unnumbered_t_handler (vl_api_sw_interface_set_unnumbered_t * mp) { vl_api_sw_interface_set_unnumbered_reply_t *rmp; int rv = 0; vnet_main_t *vnm = vnet_get_main (); u32 sw_if_index = ntohl (mp->sw_if_index); u32 unnumbered_sw_if_index = ntohl (mp->unnumbered_sw_if_index); /* * The API message field names are backwards from * the underlying data structure names. * It's not worth changing them now. */ if (!vnet_sw_interface_is_api_valid (vnm, unnumbered_sw_if_index)) { rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; goto done; } /* Only check the "use loop0" field when setting the binding */ if (mp->is_add && !vnet_sw_interface_is_api_valid (vnm, sw_if_index)) { rv = VNET_API_ERROR_INVALID_SW_IF_INDEX_2; goto done; } vnet_sw_interface_update_unnumbered (unnumbered_sw_if_index, sw_if_index, mp->is_add); done: REPLY_MACRO (VL_API_SW_INTERFACE_SET_UNNUMBERED_REPLY); } static void vl_api_sw_interface_clear_stats_t_handler (vl_api_sw_interface_clear_stats_t * mp) { vl_api_sw_interface_clear_stats_reply_t *rmp; vnet_main_t *vnm = vnet_get_main (); vnet_interface_main_t *im = &vnm->interface_main; vlib_simple_counter_main_t *sm; vlib_combined_counter_main_t *cm; static vnet_main_t **my_vnet_mains; int i, j, n_counters; int rv = 0; if (mp->sw_if_index != ~0) VALIDATE_SW_IF_INDEX (mp); vec_reset_length (my_vnet_mains); for (i = 0; i < vec_len (vnet_mains); i++) { if (vnet_mains[i]) vec_add1 (my_vnet_mains, vnet_mains[i]); } if (vec_len (vnet_mains) == 0) vec_add1 (my_vnet_mains, vnm); n_counters = vec_len (im->combined_sw_if_counters); for (j = 0; j < n_counters; j++) { for (i = 0; i < vec_len (my_vnet_mains); i++) { im = &my_vnet_mains[i]->interface_main; cm = im->combined_sw_if_counters + j; if (mp->sw_if_index == (u32) ~ 0) vlib_clear_combined_counters (cm); else vlib_zero_combined_counter (cm, ntohl (mp->sw_if_index)); } } n_counters = vec_len (im->sw_if_counters); for (j = 0; j < n_counters; j++) { for (i = 0; i < vec_len (my_vnet_mains); i++) { im = &my_vnet_mains[i]->interface_main; sm = im->sw_if_counters + j; if (mp->sw_if_index == (u32) ~ 0) vlib_clear_simple_counters (sm); else vlib_zero_simple_counter (sm, ntohl (mp->sw_if_index)); } } BAD_SW_IF_INDEX_LABEL; REPLY_MACRO (VL_API_SW_INTERFACE_CLEAR_STATS_REPLY); } #define API_LINK_STATE_EVENT 1 #define API_ADMIN_UP_DOWN_EVENT 2 static int event_data_cmp (void *a1, void *a2) { uword *e1 = a1; uword *e2 = a2; return (word) e1[0] - (word) e2[0]; } static void send_sw_interface_event (vpe_api_main_t * am, vpe_client_registration_t * reg, vl_api_registration_t * vl_reg, vnet_sw_interface_t * swif) { vl_api_sw_interface_event_t *mp; vnet_main_t *vnm = am->vnet_main; vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, swif->sw_if_index); mp = vl_msg_api_alloc (sizeof (*mp)); memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_EVENT); mp->sw_if_index = ntohl (swif->sw_if_index); mp->client_index = reg->client_index; mp->pid = reg->client_pid; 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; vl_api_send_msg (vl_reg, (u8 *) mp); } static uword link_state_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) { vpe_api_main_t *vam = &vpe_api_main; vnet_main_t *vnm = vam->vnet_main; vnet_sw_interface_t *swif; uword *event_data = 0; vpe_client_registration_t *reg; int i; u32 prev_sw_if_index; vl_api_registration_t *vl_reg; vam->link_state_process_up = 1; while (1) { vlib_process_wait_for_event (vm); /* Unified list of changed link or admin state sw_if_indices */ vlib_process_get_events_with_type (vm, &event_data, API_LINK_STATE_EVENT); vlib_process_get_events_with_type (vm, &event_data, API_ADMIN_UP_DOWN_EVENT); /* Sort, so we can eliminate duplicates */ vec_sort_with_function (event_data, event_data_cmp); prev_sw_if_index = ~0; for (i = 0; i < vec_len (event_data); i++) { /* Only one message per swif */ if (prev_sw_if_index == event_data[i]) continue; prev_sw_if_index = event_data[i]; /* *INDENT-OFF* */ pool_foreach(reg, vam->interface_events_registrations, ({ vl_reg = vl_api_client_index_to_registration (reg->client_index); if (vl_reg) { /* sw_interface may be deleted already */ if (!pool_is_free_index (vnm->interface_main.sw_interfaces, event_data[i])) { swif = vnet_get_sw_interface (vnm, event_data[i]); send_sw_interface_event (vam, reg, vl_reg, swif); } } })); /* *INDENT-ON* */ } vec_reset_length (event_data); } return 0; } static clib_error_t *link_up_down_function (vnet_main_t * vm, u32 hw_if_index, u32 flags); static clib_error_t *admin_up_down_function (vnet_main_t * vm, u32 hw_if_index, u32 flags); /* *INDENT-OFF* */ VLIB_REGISTER_NODE (link_state_process_node,static) = { .function = link_state_process, .type = VLIB_NODE_TYPE_PROCESS, .name = "vpe-link-state-process", }; /* *INDENT-ON* */ VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (admin_up_down_function); VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (link_up_down_function); static clib_error_t * link_up_down_function (vnet_main_t * vm, u32 hw_if_index, u32 flags) { vpe_api_main_t *vam = &vpe_api_main; vnet_hw_interface_t *hi = vnet_get_hw_interface (vm, hw_if_index); if (vam->link_state_process_up) vlib_process_signal_event (vam->vlib_main, link_state_process_node.index, API_LINK_STATE_EVENT, hi->sw_if_index); return 0; } static clib_error_t * admin_up_down_function (vnet_main_t * vm, u32 sw_if_index, u32 flags) { vpe_api_main_t *vam = &vpe_api_main; /* * Note: it's perfectly fair to set a subif admin up / admin down. * Note the subtle distinction between this routine and the previous * routine. */ if (vam->link_state_process_up) vlib_process_signal_event (vam->vlib_main, link_state_process_node.index, API_ADMIN_UP_DOWN_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)); 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; } memset (&template, 0, sizeof (template)); template.type = VNET_SW_INTERFACE_TYPE_SUB; 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; } memset (&template, 0, sizeof (template)); template.type = VNET_SW_INTERFACE_TYPE_SUB; 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 _ /* * 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: */