X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Finterface_api.c;h=ee13135f08626af30c20b31b029b5977dd3dea9e;hb=f9342023c19887da656133e2688a90d70383b0c5;hp=9949f83660b93200f4fe8f53b02e2c6b8f38e96d;hpb=d292ab1e0f600c20d380a93180cccb6226c220e3;p=vpp.git diff --git a/src/vnet/interface_api.c b/src/vnet/interface_api.c index 9949f83660b..ee13135f086 100644 --- a/src/vnet/interface_api.c +++ b/src/vnet/interface_api.c @@ -98,8 +98,15 @@ vl_api_sw_interface_set_mtu_t_handler (vl_api_sw_interface_set_mtu_t * mp) VALIDATE_SW_IF_INDEX (mp); - vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, sw_if_index); - ethernet_interface_t *eif = ethernet_get_interface (em, sw_if_index); + 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) { @@ -122,7 +129,7 @@ vl_api_sw_interface_set_mtu_t_handler (vl_api_sw_interface_set_mtu_t * mp) if (hi->max_packet_bytes != mtu) { hi->max_packet_bytes = mtu; - ethernet_set_flags (vnm, sw_if_index, flags); + ethernet_set_flags (vnm, si->hw_if_index, flags); } BAD_SW_IF_INDEX_LABEL; @@ -131,7 +138,7 @@ vl_api_sw_interface_set_mtu_t_handler (vl_api_sw_interface_set_mtu_t * mp) static void send_sw_interface_details (vpe_api_main_t * am, - unix_shared_memory_queue_t * q, + vl_api_registration_t * rp, vnet_sw_interface_t * swif, u8 * interface_name, u32 context) { @@ -226,7 +233,7 @@ send_sw_interface_details (vpe_api_main_t * am, if (tag) strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1); - vl_msg_api_send_shmem (q, (u8 *) & mp); + vl_msg_api_send (rp, (u8 *) mp); } static void @@ -235,11 +242,15 @@ vl_api_sw_interface_dump_t_handler (vl_api_sw_interface_dump_t * mp) vpe_api_main_t *am = &vpe_api_main; vnet_sw_interface_t *swif; vnet_interface_main_t *im = &am->vnet_main->interface_main; + vl_api_registration_t *rp; - unix_shared_memory_queue_t *q = - vl_api_client_index_to_input_queue (mp->client_index); - if (q == 0) - return; + rp = vl_api_client_index_to_registration (mp->client_index); + + if (rp == 0) + { + clib_warning ("Client %d AWOL", mp->client_index); + return; + } u8 *filter = 0, *name = 0; if (mp->name_filter_valid) @@ -261,7 +272,7 @@ vl_api_sw_interface_dump_t_handler (vl_api_sw_interface_dump_t * mp) if (filter && !strcasestr((char *) name, (char *) filter)) continue; - send_sw_interface_details (am, q, swif, name, mp->context); + send_sw_interface_details (am, rp, swif, name, mp->context); })); /* *INDENT-ON* */ @@ -274,27 +285,38 @@ static void (vl_api_sw_interface_add_del_address_t * mp) { vlib_main_t *vm = vlib_get_main (); + vnet_main_t *vnm = vnet_get_main (); vl_api_sw_interface_add_del_address_reply_t *rmp; int rv = 0; u32 is_del; + clib_error_t *error = 0; VALIDATE_SW_IF_INDEX (mp); is_del = mp->is_add == 0; + vnm->api_errno = 0; if (mp->del_all) ip_del_all_interface_addresses (vm, ntohl (mp->sw_if_index)); else if (mp->is_ipv6) - ip6_add_del_interface_address (vm, ntohl (mp->sw_if_index), - (void *) mp->address, - mp->address_length, is_del); + error = ip6_add_del_interface_address (vm, ntohl (mp->sw_if_index), + (void *) mp->address, + mp->address_length, is_del); else - ip4_add_del_interface_address (vm, ntohl (mp->sw_if_index), - (void *) mp->address, - mp->address_length, is_del); + error = ip4_add_del_interface_address (vm, ntohl (mp->sw_if_index), + (void *) mp->address, + mp->address_length, is_del); + + if (error) + { + rv = vnm->api_errno; + clib_error_report (error); + goto done; + } BAD_SW_IF_INDEX_LABEL; +done: REPLY_MACRO (VL_API_SW_INTERFACE_ADD_DEL_ADDRESS_REPLY); } @@ -313,68 +335,162 @@ stats_dsunlock (void) static void vl_api_sw_interface_set_table_t_handler (vl_api_sw_interface_set_table_t * mp) { - int rv = 0; - u32 table_id = ntohl (mp->vrf_id); - u32 sw_if_index = ntohl (mp->sw_if_index); vl_api_sw_interface_set_table_reply_t *rmp; - CLIB_UNUSED (ip_interface_address_t * ia); - u32 fib_index; + u32 sw_if_index = ntohl (mp->sw_if_index); + u32 table_id = ntohl (mp->vrf_id); + int rv = 0; VALIDATE_SW_IF_INDEX (mp); stats_dslock_with_hint (1 /* release hint */ , 4 /* tag */ ); if (mp->is_ipv6) + rv = ip_table_bind (FIB_PROTOCOL_IP6, sw_if_index, table_id, 1); + else + rv = ip_table_bind (FIB_PROTOCOL_IP4, sw_if_index, table_id, 1); + + stats_dsunlock (); + + 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) +{ + CLIB_UNUSED (ip_interface_address_t * ia); + u32 fib_index, mfib_index; + fib_source_t src; + mfib_source_t msrc; + + 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 (is_api) + { + src = FIB_SOURCE_API; + msrc = MFIB_SOURCE_API; + } + else + { + src = FIB_SOURCE_CLI; + msrc = MFIB_SOURCE_CLI; + } + + 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 thoses subnets are valid in the destination VRF. + */ /* *INDENT-OFF* */ foreach_ip_interface_address (&ip6_main.lookup_main, ia, sw_if_index, 1 /* honor unnumbered */ , ({ - rv = VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE; - goto done; + return (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE); })); /* *INDENT-ON* */ - fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, - table_id); vec_validate (ip6_main.fib_index_by_sw_if_index, sw_if_index); - ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index; - - fib_index = mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, - table_id); vec_validate (ip6_main.mfib_index_by_sw_if_index, sw_if_index); - ip6_main.mfib_index_by_sw_if_index[sw_if_index] = fib_index; + + /* + * tell those that are interested that the binding is changing. + */ + ip6_table_bind_callback_t *cb; + vec_foreach (cb, ip6_main.table_bind_callbacks) + cb->function (&ip6_main, cb->function_opaque, + sw_if_index, + 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); + + } + else + { + /* 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); + } + + 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 thoses subnets are valid in the destination VRF. + */ /* *INDENT-OFF* */ foreach_ip_interface_address (&ip4_main.lookup_main, ia, sw_if_index, 1 /* honor unnumbered */ , ({ - rv = VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE; - goto done; + return (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE); })); /* *INDENT-ON* */ - fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, - table_id); vec_validate (ip4_main.fib_index_by_sw_if_index, sw_if_index); - ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index; - - fib_index = mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, - table_id); vec_validate (ip4_main.mfib_index_by_sw_if_index, sw_if_index); - ip4_main.mfib_index_by_sw_if_index[sw_if_index] = fib_index; - } -done: - stats_dsunlock (); + /* + * tell those that are interested that the binding is changing. + */ + ip4_table_bind_callback_t *cb; + vec_foreach (cb, ip4_main.table_bind_callbacks) + cb->function (&ip4_main, cb->function_opaque, + sw_if_index, + 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); - BAD_SW_IF_INDEX_LABEL; + } + 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); - REPLY_MACRO (VL_API_SW_INTERFACE_SET_TABLE_REPLY); + 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 @@ -736,6 +852,7 @@ static void vl_api_sw_interface_set_mac_address_t_handler 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; u64 mac; clib_error_t *error; int rv = 0; @@ -749,7 +866,8 @@ static void vl_api_sw_interface_set_mac_address_t_handler | (u64) mp->mac_address[4] << (8 * 4) | (u64) mp->mac_address[5] << (8 * 5)); - error = vnet_hw_interface_change_mac_address (vnm, sw_if_index, mac); + si = vnet_get_sw_interface (vnm, sw_if_index); + error = vnet_hw_interface_change_mac_address (vnm, si->hw_if_index, mac); if (error) { rv = VNET_API_ERROR_UNIMPLEMENTED;