X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Finterface_api.c;h=c727e5191388fc85e69158462adcfce9d8648191;hb=HEAD;hp=387ef32a20723164d018afe800b572a1896331d1;hpb=aa27dcb84cb312277370b77370a69b2a3596c4c5;p=vpp.git diff --git a/src/vnet/interface_api.c b/src/vnet/interface_api.c index 387ef32a207..c727e519138 100644 --- a/src/vnet/interface_api.c +++ b/src/vnet/interface_api.c @@ -17,70 +17,72 @@ *------------------------------------------------------------------ */ +#define _GNU_SOURCE +#include + #include #include #include +#include +#include #include #include #include #include #include #include -#include #include #include - #include +#include #include #include -#define vl_typedefs /* define message structures */ -#include -#undef vl_typedefs +#include +#include -#define vl_endianfun /* define message structures */ -#include -#undef vl_endianfun +#define REPLY_MSG_ID_BASE msg_id_base +#include -/* 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 +static u16 msg_id_base; -#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_ADD_DEL_MAC_ADDRESS, sw_interface_add_del_mac_address) \ -_(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) +#define foreach_vpe_api_msg \ + _ (SW_INTERFACE_SET_FLAGS, sw_interface_set_flags) \ + _ (SW_INTERFACE_SET_PROMISC, sw_interface_set_promisc) \ + _ (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_TX_PLACEMENT_GET, sw_interface_tx_placement_get) \ + _ (SW_INTERFACE_SET_RX_PLACEMENT, sw_interface_set_rx_placement) \ + _ (SW_INTERFACE_SET_TX_PLACEMENT, sw_interface_set_tx_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_ADD_DEL_MAC_ADDRESS, sw_interface_add_del_mac_address) \ + _ (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) \ + _ (SW_INTERFACE_ADDRESS_REPLACE_BEGIN, sw_interface_address_replace_begin) \ + _ (SW_INTERFACE_ADDRESS_REPLACE_END, sw_interface_address_replace_end) static void vl_api_sw_interface_set_flags_t_handler (vl_api_sw_interface_set_flags_t * mp) @@ -108,6 +110,37 @@ vl_api_sw_interface_set_flags_t_handler (vl_api_sw_interface_set_flags_t * mp) REPLY_MACRO (VL_API_SW_INTERFACE_SET_FLAGS_REPLY); } +static void +vl_api_sw_interface_set_promisc_t_handler ( + vl_api_sw_interface_set_promisc_t *mp) +{ + vl_api_sw_interface_set_promisc_reply_t *rmp; + vnet_main_t *vnm = vnet_get_main (); + ethernet_main_t *em = ðernet_main; + int rv = 0; + ethernet_interface_t *eif; + vnet_sw_interface_t *swif; + u32 flags, sw_if_index; + + VALIDATE_SW_IF_INDEX (mp); + + sw_if_index = ntohl (mp->sw_if_index); + swif = vnet_get_sw_interface (vnm, sw_if_index); + eif = ethernet_get_interface (em, swif->hw_if_index); + if (!eif) + { + rv = VNET_API_ERROR_INVALID_VALUE; + goto done; + } + + flags = mp->promisc_on ? ETHERNET_INTERFACE_FLAG_ACCEPT_ALL : 0; + rv = ethernet_set_flags (vnm, swif->hw_if_index, flags); + +done: + BAD_SW_IF_INDEX_LABEL; + REPLY_MACRO (VL_API_SW_INTERFACE_SET_PROMISC_REPLY); +} + static void vl_api_hw_interface_set_mtu_t_handler (vl_api_hw_interface_set_mtu_t * mp) { @@ -116,6 +149,7 @@ vl_api_hw_interface_set_mtu_t_handler (vl_api_hw_interface_set_mtu_t * mp) u32 sw_if_index = ntohl (mp->sw_if_index); u16 mtu = ntohs (mp->mtu); ethernet_main_t *em = ðernet_main; + clib_error_t *err; int rv = 0; VALIDATE_SW_IF_INDEX (mp); @@ -127,7 +161,6 @@ vl_api_hw_interface_set_mtu_t_handler (vl_api_hw_interface_set_mtu_t * mp) 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) @@ -136,20 +169,13 @@ vl_api_hw_interface_set_mtu_t_handler (vl_api_hw_interface_set_mtu_t * mp) goto bad_sw_if_index; } - if (mtu < hi->min_supported_packet_bytes) + if ((err = vnet_hw_interface_set_mtu (vnm, si->hw_if_index, mtu))) { - rv = VNET_API_ERROR_INVALID_VALUE; + rv = vnet_api_error (err); + clib_error_free (err); 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); } @@ -169,7 +195,6 @@ vl_api_sw_interface_set_mtu_t_handler (vl_api_sw_interface_set_mtu_t * mp) for (i = 0; i < VNET_N_MTU; i++) { per_protocol_mtu[i] = ntohl (mp->mtu[i]); - clib_warning ("MTU %u", per_protocol_mtu[i]); } vnet_sw_interface_set_protocol_mtu (vnm, sw_if_index, per_protocol_mtu); @@ -207,7 +232,7 @@ send_sw_interface_details (vpe_api_main_t * am, 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->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + 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); @@ -233,10 +258,10 @@ send_sw_interface_details (vpe_api_main_t * am, } mp->type = ntohl (mp->type); - mp->link_duplex = ((hi->flags & VNET_HW_INTERFACE_FLAG_DUPLEX_MASK) >> - VNET_HW_INTERFACE_FLAG_DUPLEX_SHIFT); + mp->link_duplex = ntohl (((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->link_mtu = ntohs (hi->max_frame_size - hi->frame_overhead); 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]); @@ -259,8 +284,8 @@ send_sw_interface_details (vpe_api_main_t * am, ethernet_interface_t *ei; ei = pool_elt_at_index (em->interfaces, hi->hw_instance); - ASSERT (sizeof (mp->l2_address) >= sizeof (ei->address)); - mac_address_encode ((mac_address_t *) ei->address, mp->l2_address); + ASSERT (sizeof (mp->l2_address) >= sizeof (ei->address.mac)); + mac_address_encode (&ei->address.mac, mp->l2_address); } else if (swif->sup_sw_if_index != swif->sw_if_index) { @@ -358,14 +383,12 @@ vl_api_sw_interface_dump_t_handler (vl_api_sw_interface_dump_t * mp) if (mp->name_filter_valid) { - filter = vl_api_from_api_to_vec (&mp->name_filter); + filter = vl_api_from_api_to_new_vec (mp, &mp->name_filter); vec_add1 (filter, 0); /* Ensure it's a C string for strcasecmp() */ } - char *strcasestr (char *, char *); /* lnx hdr file botch */ - /* *INDENT-OFF* */ - pool_foreach (swif, im->sw_interfaces, - ({ + pool_foreach (swif, im->sw_interfaces) + { if (!vnet_swif_is_api_visible (swif)) continue; vec_reset_length(name); @@ -376,8 +399,7 @@ vl_api_sw_interface_dump_t_handler (vl_api_sw_interface_dump_t * mp) continue; send_sw_interface_details (am, rp, swif, name, mp->context); - })); - /* *INDENT-ON* */ + } vec_free (name); vec_free (filter); @@ -435,66 +457,25 @@ vl_api_sw_interface_set_table_t_handler (vl_api_sw_interface_set_table_t * mp) VALIDATE_SW_IF_INDEX (mp); if (mp->is_ipv6) - rv = ip_table_bind (FIB_PROTOCOL_IP6, sw_if_index, table_id, 1); + rv = ip_table_bind (FIB_PROTOCOL_IP6, sw_if_index, table_id); else - rv = ip_table_bind (FIB_PROTOCOL_IP4, sw_if_index, table_id, 1); + rv = ip_table_bind (FIB_PROTOCOL_IP4, sw_if_index, table_id); BAD_SW_IF_INDEX_LABEL; REPLY_MACRO (VL_API_SW_INTERFACE_SET_TABLE_REPLY); } -int -ip_table_bind (fib_protocol_t fproto, - u32 sw_if_index, u32 table_id, u8 is_api) +void +fib_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 fib_index) { - CLIB_UNUSED (ip_interface_address_t * ia); - u32 fib_index, mfib_index; - fib_source_t src; - mfib_source_t msrc; - - if (is_api) - { - src = FIB_SOURCE_API; - msrc = MFIB_SOURCE_API; - } - else - { - src = FIB_SOURCE_CLI; - msrc = MFIB_SOURCE_CLI; - } - - /* - * This if table does not exist = error is what we want in the end. - */ - fib_index = fib_table_find (fproto, table_id); - mfib_index = mfib_table_find (fproto, table_id); + u32 table_id; - if (~0 == fib_index || ~0 == mfib_index) - { - return (VNET_API_ERROR_NO_SUCH_FIB); - } + table_id = fib_table_get_table_id (fib_index, fproto); + ASSERT (table_id != ~0); if (FIB_PROTOCOL_IP6 == fproto) { - /* - * If the interface already has in IP address, then a change int - * VRF is not allowed. The IP address applied must first be removed. - * We do not do that automatically here, since VPP has no knowledge - * of whether those subnets are valid in the destination VRF. - */ - /* *INDENT-OFF* */ - foreach_ip_interface_address (&ip6_main.lookup_main, - ia, sw_if_index, - 1 /* honor unnumbered */ , - ({ - return (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE); - })); - /* *INDENT-ON* */ - - vec_validate (ip6_main.fib_index_by_sw_if_index, sw_if_index); - vec_validate (ip6_main.mfib_index_by_sw_if_index, sw_if_index); - /* * tell those that are interested that the binding is changing. */ @@ -505,47 +486,21 @@ ip_table_bind (fib_protocol_t fproto, fib_index, ip6_main.fib_index_by_sw_if_index[sw_if_index]); - if (0 == table_id) - { - /* reset back to default */ - if (0 != ip6_main.fib_index_by_sw_if_index[sw_if_index]) - fib_table_unlock (ip6_main.fib_index_by_sw_if_index[sw_if_index], - FIB_PROTOCOL_IP6, src); - if (0 != ip6_main.mfib_index_by_sw_if_index[sw_if_index]) - mfib_table_unlock (ip6_main.mfib_index_by_sw_if_index - [sw_if_index], FIB_PROTOCOL_IP6, msrc); + /* unlock currently assigned tables */ + if (0 != ip6_main.fib_index_by_sw_if_index[sw_if_index]) + fib_table_unlock (ip6_main.fib_index_by_sw_if_index[sw_if_index], + FIB_PROTOCOL_IP6, FIB_SOURCE_INTERFACE); - } - else + if (0 != table_id) { /* we need to lock the table now it's inuse */ - fib_table_lock (fib_index, FIB_PROTOCOL_IP6, src); - mfib_table_lock (mfib_index, FIB_PROTOCOL_IP6, msrc); + fib_table_lock (fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_INTERFACE); } ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index; - ip6_main.mfib_index_by_sw_if_index[sw_if_index] = mfib_index; } else { - /* - * If the interface already has in IP address, then a change int - * VRF is not allowed. The IP address applied must first be removed. - * We do not do that automatically here, since VPP has no knowledge - * of whether those subnets are valid in the destination VRF. - */ - /* *INDENT-OFF* */ - foreach_ip_interface_address (&ip4_main.lookup_main, - ia, sw_if_index, - 1 /* honor unnumbered */ , - ({ - return (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE); - })); - /* *INDENT-ON* */ - - vec_validate (ip4_main.fib_index_by_sw_if_index, sw_if_index); - vec_validate (ip4_main.mfib_index_by_sw_if_index, sw_if_index); - /* * tell those that are interested that the binding is changing. */ @@ -556,30 +511,97 @@ ip_table_bind (fib_protocol_t fproto, fib_index, ip4_main.fib_index_by_sw_if_index[sw_if_index]); - if (0 == table_id) - { - /* reset back to default */ - if (0 != ip4_main.fib_index_by_sw_if_index[sw_if_index]) - fib_table_unlock (ip4_main.fib_index_by_sw_if_index[sw_if_index], - FIB_PROTOCOL_IP4, src); - if (0 != ip4_main.mfib_index_by_sw_if_index[sw_if_index]) - mfib_table_unlock (ip4_main.mfib_index_by_sw_if_index - [sw_if_index], FIB_PROTOCOL_IP4, msrc); + /* unlock currently assigned tables */ + if (0 != ip4_main.fib_index_by_sw_if_index[sw_if_index]) + fib_table_unlock (ip4_main.fib_index_by_sw_if_index[sw_if_index], + FIB_PROTOCOL_IP4, FIB_SOURCE_INTERFACE); + if (0 != table_id) + { + /* we need to lock the table now it's inuse */ + fib_index = fib_table_find_or_create_and_lock ( + FIB_PROTOCOL_IP4, table_id, FIB_SOURCE_INTERFACE); } - else + + ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index; + } +} + +void +mfib_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 mfib_index) +{ + u32 table_id; + + table_id = mfib_table_get_table_id (mfib_index, fproto); + ASSERT (table_id != ~0); + + if (FIB_PROTOCOL_IP6 == fproto) + { + if (0 != ip6_main.mfib_index_by_sw_if_index[sw_if_index]) + mfib_table_unlock (ip6_main.mfib_index_by_sw_if_index[sw_if_index], + FIB_PROTOCOL_IP6, MFIB_SOURCE_INTERFACE); + + if (0 != table_id) { /* 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_table_lock (mfib_index, FIB_PROTOCOL_IP6, + MFIB_SOURCE_INTERFACE); + } - mfib_index = mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, - table_id, msrc); + ip6_main.mfib_index_by_sw_if_index[sw_if_index] = mfib_index; + } + else + { + if (0 != ip4_main.mfib_index_by_sw_if_index[sw_if_index]) + mfib_table_unlock (ip4_main.mfib_index_by_sw_if_index[sw_if_index], + FIB_PROTOCOL_IP4, MFIB_SOURCE_INTERFACE); + + if (0 != table_id) + { + /* we need to lock the table now it's inuse */ + mfib_index = mfib_table_find_or_create_and_lock ( + FIB_PROTOCOL_IP4, table_id, MFIB_SOURCE_INTERFACE); } - 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; } +} + +int +ip_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 table_id) +{ + CLIB_UNUSED (ip_interface_address_t * ia); + u32 fib_index, mfib_index; + + /* + * This if table does not exist = error is what we want in the end. + */ + fib_index = fib_table_find (fproto, table_id); + mfib_index = mfib_table_find (fproto, table_id); + + if (~0 == fib_index || ~0 == mfib_index) + { + return (VNET_API_ERROR_NO_SUCH_FIB); + } + + /* + * If the interface already has in IP address, then a change int + * VRF is not allowed. The IP address applied must first be removed. + * We do not do that automatically here, since VPP has no knowledge + * of whether those subnets are valid in the destination VRF. + */ + /* clang-format off */ + foreach_ip_interface_address (FIB_PROTOCOL_IP6 == fproto ? + &ip6_main.lookup_main : &ip4_main.lookup_main, + ia, sw_if_index, + 1 /* honor unnumbered */ , + ({ + return (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE); + })); + /* clang-format on */ + + fib_table_bind (fproto, sw_if_index, fib_index); + mfib_table_bind (fproto, sw_if_index, mfib_index); return (0); } @@ -592,7 +614,8 @@ send_sw_interface_get_table_reply (vl_api_registration_t * reg, mp = vl_msg_api_alloc (sizeof (*mp)); clib_memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_GET_TABLE_REPLY); + mp->_vl_msg_id = + ntohs (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_GET_TABLE_REPLY); mp->context = context; mp->retval = htonl (retval); mp->vrf_id = htonl (vrf_id); @@ -661,8 +684,8 @@ static void vl_api_sw_interface_set_unnumbered_t_handler goto done; } - vnet_sw_interface_update_unnumbered (unnumbered_sw_if_index, - sw_if_index, mp->is_add); + rv = 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); } @@ -735,7 +758,7 @@ send_sw_interface_event (vpe_api_main_t * am, mp = vl_msg_api_alloc (sizeof (*mp)); clib_memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_EVENT); + mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_EVENT); mp->sw_if_index = ntohl (sw_if_index); mp->client_index = reg->client_index; mp->pid = reg->client_pid; @@ -785,14 +808,12 @@ link_state_process (vlib_main_t * vm, if (event_by_sw_if_index[i] == 0) continue; - /* *INDENT-OFF* */ - pool_foreach(reg, vam->interface_events_registrations, - ({ + pool_foreach (reg, vam->interface_events_registrations) + { vl_reg = vl_api_client_index_to_registration (reg->client_index); if (vl_reg) send_sw_interface_event (vam, reg, vl_reg, i, event_by_sw_if_index[i]); - })); - /* *INDENT-ON* */ + } } vec_reset_length (event_by_sw_if_index); } @@ -808,13 +829,11 @@ static clib_error_t *sw_interface_add_del_function (vnet_main_t * vm, u32 sw_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); @@ -986,14 +1005,47 @@ static void vl_api_sw_interface_get_mac_address_t_handler if (!reg) return; rmp = vl_msg_api_alloc (sizeof (*rmp)); - rmp->_vl_msg_id = htons (VL_API_SW_INTERFACE_GET_MAC_ADDRESS_REPLY); + rmp->_vl_msg_id = + htons (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_GET_MAC_ADDRESS_REPLY); rmp->context = mp->context; rmp->retval = htonl (rv); if (!rv && eth_if) - mac_address_encode ((mac_address_t *) eth_if->address, rmp->mac_address); + mac_address_encode (ð_if->address.mac, rmp->mac_address); vl_api_send_msg (reg, (u8 *) rmp); } +static void +vl_api_sw_interface_set_interface_name_t_handler ( + vl_api_sw_interface_set_interface_name_t *mp) +{ + vl_api_sw_interface_set_interface_name_reply_t *rmp; + vnet_main_t *vnm = vnet_get_main (); + clib_error_t *error; + int rv = 0; + + VALIDATE_SW_IF_INDEX (mp); + + u32 sw_if_index = ntohl (mp->sw_if_index); + vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index); + + if (mp->name[0] == 0) + { + rv = VNET_API_ERROR_INVALID_VALUE; + goto out; + } + + error = vnet_rename_interface (vnm, si->hw_if_index, (char *) mp->name); + if (error) + { + clib_error_free (error); + rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; + } + +out: + BAD_SW_IF_INDEX_LABEL; + REPLY_MACRO (VL_API_SW_INTERFACE_SET_INTERFACE_NAME_REPLY); +} + static void vl_api_sw_interface_set_rx_mode_t_handler (vl_api_sw_interface_set_rx_mode_t * mp) { @@ -1003,6 +1055,7 @@ static void vl_api_sw_interface_set_rx_mode_t_handler vnet_sw_interface_t *si; clib_error_t *error; int rv = 0; + vnet_hw_if_rx_mode rx_mode; VALIDATE_SW_IF_INDEX (mp); @@ -1013,11 +1066,11 @@ static void vl_api_sw_interface_set_rx_mode_t_handler goto bad_sw_if_index; } + rx_mode = (vnet_hw_if_rx_mode) ntohl (mp->mode); error = set_hw_interface_change_rx_mode (vnm, si->hw_if_index, mp->queue_id_valid, ntohl (mp->queue_id), - (vnet_hw_interface_rx_mode) - mp->mode); + (vnet_hw_if_rx_mode) rx_mode); if (error) { @@ -1041,11 +1094,12 @@ send_interface_rx_placement_details (vpe_api_main_t * am, 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->_vl_msg_id = + htons (REPLY_MSG_ID_BASE + 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->mode = htonl (mode); mp->context = context; vl_api_send_msg (rp, (u8 *) mp); @@ -1065,29 +1119,24 @@ static void vl_api_sw_interface_rx_placement_dump_t_handler 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* */ + vnet_hw_if_rx_queue_t **all_queues = 0; + vnet_hw_if_rx_queue_t **qptr; + vnet_hw_if_rx_queue_t *q; + pool_foreach (q, vnm->interface_main.hw_if_rx_queues) + vec_add1 (all_queues, q); + vec_sort_with_function (all_queues, vnet_hw_if_rxq_cmp_cli_api); + + vec_foreach (qptr, all_queues) + { + u32 current_thread = qptr[0]->thread_index; + u32 hw_if_index = qptr[0]->hw_if_index; + vnet_hw_interface_t *hw_if = + vnet_get_hw_interface (vnm, hw_if_index); + send_interface_rx_placement_details ( + am, reg, hw_if->sw_if_index, current_thread, qptr[0]->queue_id, + qptr[0]->mode, mp->context); + } + vec_free (all_queues); } else { @@ -1110,13 +1159,13 @@ static void vl_api_sw_interface_rx_placement_dump_t_handler 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++) + for (i = 0; i < vec_len (hw->rx_queue_indices); 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); + vnet_hw_if_rx_queue_t *rxq = + vnet_hw_if_get_rx_queue (vnm, hw->rx_queue_indices[i]); + send_interface_rx_placement_details ( + am, reg, hw->sw_if_index, rxq->thread_index, rxq->queue_id, + rxq->mode, mp->context); } } @@ -1157,6 +1206,164 @@ out: REPLY_MACRO (VL_API_SW_INTERFACE_SET_RX_PLACEMENT_REPLY); } +static void +send_interface_tx_placement_details (vnet_hw_if_tx_queue_t **all_queues, + u32 index, vl_api_registration_t *rp, + u32 context) +{ + vnet_main_t *vnm = vnet_get_main (); + vl_api_sw_interface_tx_placement_details_t *rmp; + u32 n_bits = 0, v = ~0; + vnet_hw_if_tx_queue_t **q = vec_elt_at_index (all_queues, index); + uword *bitmap = q[0]->threads; + u32 hw_if_index = q[0]->hw_if_index; + vnet_hw_interface_t *hw_if = vnet_get_hw_interface (vnm, hw_if_index); + + n_bits = clib_bitmap_count_set_bits (bitmap); + u32 n = n_bits * sizeof (u32); + + REPLY_MACRO_DETAILS5_END (VL_API_SW_INTERFACE_TX_PLACEMENT_DETAILS, n, rp, + context, ({ + rmp->sw_if_index = hw_if->sw_if_index; + rmp->queue_id = q[0]->queue_id; + rmp->shared = q[0]->shared_queue; + rmp->array_size = n_bits; + + v = clib_bitmap_first_set (bitmap); + for (u32 i = 0; i < n_bits; i++) + { + rmp->threads[i] = v; + v = clib_bitmap_next_set (bitmap, v + 1); + } + })); +} + +static void +vl_api_sw_interface_tx_placement_get_t_handler ( + vl_api_sw_interface_tx_placement_get_t *mp) +{ + vnet_main_t *vnm = vnet_get_main (); + vl_api_sw_interface_tx_placement_get_reply_t *rmp = 0; + vnet_hw_if_tx_queue_t **all_queues = 0; + vnet_hw_if_tx_queue_t *q; + u32 sw_if_index = mp->sw_if_index; + i32 rv = 0; + + if (pool_elts (vnm->interface_main.hw_if_tx_queues) == 0) + { + rv = VNET_API_ERROR_NO_SUCH_ENTRY; + goto err; + } + + if (sw_if_index == ~0) + { + pool_foreach (q, vnm->interface_main.hw_if_tx_queues) + vec_add1 (all_queues, q); + vec_sort_with_function (all_queues, vnet_hw_if_txq_cmp_cli_api); + } + else + { + u32 qi = ~0; + 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); + rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; + goto err; + } + + 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"); + rv = VNET_API_ERROR_INVALID_INTERFACE; + goto err; + } + + vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, si->hw_if_index); + for (qi = 0; qi < vec_len (hw->tx_queue_indices); qi++) + { + q = vnet_hw_if_get_tx_queue (vnm, hw->tx_queue_indices[qi]); + vec_add1 (all_queues, q); + } + } + + REPLY_AND_DETAILS_VEC_MACRO_END (VL_API_SW_INTERFACE_TX_PLACEMENT_GET_REPLY, + all_queues, mp, rmp, rv, ({ + send_interface_tx_placement_details ( + all_queues, cursor, rp, mp->context); + })); + + vec_free (all_queues); + return; + +err: + REPLY_MACRO_END (VL_API_SW_INTERFACE_TX_PLACEMENT_GET_REPLY); +} + +static void +vl_api_sw_interface_set_tx_placement_t_handler ( + vl_api_sw_interface_set_tx_placement_t *mp) +{ + vl_api_sw_interface_set_tx_placement_reply_t *rmp; + vnet_main_t *vnm = vnet_get_main (); + u32 sw_if_index = mp->sw_if_index; + vnet_sw_interface_t *si; + uword *bitmap = 0; + u32 queue_id = ~0; + u32 size = 0; + clib_error_t *error = 0; + int rv = 0; + + VALIDATE_SW_IF_INDEX_END (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; + } + + size = mp->array_size; + for (u32 i = 0; i < size; i++) + { + u32 thread_index = mp->threads[i]; + bitmap = clib_bitmap_set (bitmap, thread_index, 1); + } + + queue_id = mp->queue_id; + rv = set_hw_interface_tx_queue (si->hw_if_index, queue_id, bitmap); + + switch (rv) + { + case VNET_API_ERROR_INVALID_VALUE: + error = clib_error_return ( + 0, "please specify valid thread(s) - last thread index %u", + clib_bitmap_last_set (bitmap)); + break; + case VNET_API_ERROR_INVALID_QUEUE: + error = clib_error_return ( + 0, "unknown queue %u on interface %s", queue_id, + vnet_get_hw_interface (vnet_get_main (), si->hw_if_index)->name); + break; + default: + break; + } + + if (error) + { + clib_error_report (error); + goto out; + } + + BAD_SW_IF_INDEX_LABEL; +out: + REPLY_MACRO_END (VL_API_SW_INTERFACE_SET_TX_PLACEMENT_REPLY); + clib_bitmap_free (bitmap); +} + static void vl_api_create_vlan_subif_t_handler (vl_api_create_vlan_subif_t * mp) { @@ -1231,7 +1438,7 @@ out: return; rmp = vl_msg_api_alloc (sizeof (*rmp)); - rmp->_vl_msg_id = htons (VL_API_CREATE_VLAN_SUBIF_REPLY); + rmp->_vl_msg_id = htons (REPLY_MSG_ID_BASE + VL_API_CREATE_VLAN_SUBIF_REPLY); rmp->context = mp->context; rmp->retval = htonl (rv); rmp->sw_if_index = htonl (sw_if_index); @@ -1263,12 +1470,10 @@ vl_api_create_subif_t_handler (vl_api_create_subif_t * mp) BAD_SW_IF_INDEX_LABEL; - /* *INDENT-OFF* */ REPLY_MACRO2(VL_API_CREATE_SUBIF_REPLY, ({ rmp->sw_if_index = ntohl(sub_sw_if_index); })); - /* *INDENT-ON* */ } static void @@ -1310,12 +1515,10 @@ vl_api_create_loopback_t_handler (vl_api_create_loopback_t * mp) mac_address_decode (mp->mac_address, &mac); rv = vnet_create_loopback_interface (&sw_if_index, (u8 *) & mac, 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 @@ -1332,12 +1535,10 @@ static void vl_api_create_loopback_instance_t_handler rv = vnet_create_loopback_interface (&sw_if_index, (u8 *) & mac, 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 @@ -1367,6 +1568,116 @@ static void REPLY_MACRO (VL_API_COLLECT_DETAILED_INTERFACE_STATS_REPLY); } +static void + vl_api_sw_interface_address_replace_begin_t_handler + (vl_api_sw_interface_address_replace_begin_t * mp) +{ + vl_api_sw_interface_address_replace_begin_reply_t *rmp; + int rv = 0; + + ip_interface_address_mark (); + + REPLY_MACRO (VL_API_SW_INTERFACE_ADDRESS_REPLACE_BEGIN_REPLY); +} + +static void + vl_api_sw_interface_address_replace_end_t_handler + (vl_api_sw_interface_address_replace_end_t * mp) +{ + vl_api_sw_interface_address_replace_end_reply_t *rmp; + int rv = 0; + + ip_interface_address_sweep (); + + REPLY_MACRO (VL_API_SW_INTERFACE_ADDRESS_REPLACE_END_REPLY); +} + +static void +vl_api_pcap_set_filter_function_t_handler ( + vl_api_pcap_set_filter_function_t *mp) +{ + vnet_main_t *vnm = vnet_get_main (); + vnet_pcap_t *pp = &vnm->pcap; + vl_api_pcap_set_filter_function_reply_t *rmp; + unformat_input_t input = { 0 }; + vlib_is_packet_traced_fn_t *f; + char *filter_name; + int rv = 0; + filter_name = vl_api_from_api_to_new_c_string (&mp->filter_function_name); + unformat_init_cstring (&input, filter_name); + if (unformat (&input, "%U", unformat_vlib_trace_filter_function, &f) == 0) + { + rv = -1; + goto done; + } + + pp->current_filter_function = f; + +done: + unformat_free (&input); + vec_free (filter_name); + REPLY_MACRO (VL_API_PCAP_SET_FILTER_FUNCTION_REPLY); +} + +static void +vl_api_pcap_trace_on_t_handler (vl_api_pcap_trace_on_t *mp) +{ + vl_api_pcap_trace_on_reply_t *rmp; + unformat_input_t filename, drop_err_name; + vnet_pcap_dispatch_trace_args_t capture_args; + int rv = 0; + + VALIDATE_SW_IF_INDEX (mp); + + unformat_init_cstring (&filename, (char *) mp->filename); + if (!unformat_user (&filename, unformat_vlib_tmpfile, + &capture_args.filename)) + { + rv = VNET_API_ERROR_ILLEGAL_NAME; + goto out; + } + + capture_args.rx_enable = mp->capture_rx; + capture_args.tx_enable = mp->capture_tx; + capture_args.preallocate_data = mp->preallocate_data; + capture_args.free_data = mp->free_data; + capture_args.drop_enable = mp->capture_drop; + capture_args.status = 0; + capture_args.packets_to_capture = ntohl (mp->max_packets); + capture_args.sw_if_index = ntohl (mp->sw_if_index); + capture_args.filter = mp->filter; + capture_args.max_bytes_per_pkt = ntohl (mp->max_bytes_per_packet); + capture_args.drop_err = ~0; + + unformat_init_cstring (&drop_err_name, (char *) mp->error); + unformat_user (&drop_err_name, unformat_vlib_error, vlib_get_main (), + &capture_args.drop_err); + + rv = vnet_pcap_dispatch_trace_configure (&capture_args); + + BAD_SW_IF_INDEX_LABEL; + +out: + unformat_free (&filename); + unformat_free (&drop_err_name); + + REPLY_MACRO (VL_API_PCAP_TRACE_ON_REPLY); +} + +static void +vl_api_pcap_trace_off_t_handler (vl_api_pcap_trace_off_t *mp) +{ + vl_api_pcap_trace_off_reply_t *rmp; + vnet_pcap_dispatch_trace_args_t capture_args; + int rv = 0; + + clib_memset (&capture_args, 0, sizeof (capture_args)); + + rv = vnet_pcap_dispatch_trace_configure (&capture_args); + + REPLY_MACRO (VL_API_PCAP_TRACE_OFF_REPLY); +} + /* * vpe_api_hookup * Add vpe's API message handlers to the table. @@ -1374,47 +1685,39 @@ static void * 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); +#include 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; - - /* Do not replay VL_API_SW_INTERFACE_DUMP messages */ - am->api_trace_cfg[VL_API_SW_INTERFACE_DUMP].replay_enable = 0; + api_main_t *am = vlibapi_get_main (); /* * Set up the (msg_name, crc, message-id) table */ - setup_message_id_table (am); + REPLY_MSG_ID_BASE = setup_message_id_table (); + + /* Mark these APIs as mp safe */ + vl_api_set_msg_thread_safe (am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_DUMP, + 1); + vl_api_set_msg_thread_safe ( + am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_DETAILS, 1); + vl_api_set_msg_thread_safe ( + am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_TAG_ADD_DEL, 1); + vl_api_set_msg_thread_safe ( + am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_SET_INTERFACE_NAME, 1); + + /* Do not replay VL_API_SW_INTERFACE_DUMP messages */ + vl_api_allow_msg_replay (am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_DUMP, + 0); + + /* Mark these APIs as autoendian */ + vl_api_set_msg_autoendian ( + am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_SET_TX_PLACEMENT, 1); + vl_api_set_msg_autoendian ( + am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_TX_PLACEMENT_GET, 1); return 0; }