X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=vnet%2Fvnet%2Finterface.c;h=33827e2b6733ce84ec3d021d2d9aae3fe400741d;hb=dc5252b17ad929725101d6436e040b8c2bc68aa3;hp=595ed1432bc7b364d695a2111fd7f23b6510f70b;hpb=0bfe5d8c792abcdbcf27bfcc7b7b353fba04aee2;p=vpp.git diff --git a/vnet/vnet/interface.c b/vnet/vnet/interface.c index 595ed1432bc..33827e2b673 100644 --- a/vnet/vnet/interface.c +++ b/vnet/vnet/interface.c @@ -39,6 +39,8 @@ #include #include +#include +#include #define VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE (1 << 0) #define VNET_INTERFACE_SET_FLAGS_HELPER_WANT_REDISTRIBUTE (1 << 1) @@ -238,17 +240,25 @@ unserialize_vnet_interface_state (serialize_main_t * m, va_list * va) static clib_error_t * call_elf_section_interface_callbacks (vnet_main_t * vnm, u32 if_index, u32 flags, - _vnet_interface_function_list_elt_t * - elt) + _vnet_interface_function_list_elt_t ** + elts) { + _vnet_interface_function_list_elt_t *elt; + vnet_interface_function_priority_t prio; clib_error_t *error = 0; - while (elt) + for (prio = VNET_ITF_FUNC_PRIORITY_LOW; + prio <= VNET_ITF_FUNC_PRIORITY_HIGH; prio++) { - error = elt->fp (vnm, if_index, flags); - if (error) - return error; - elt = elt->next_interface_function; + elt = elts[prio]; + + while (elt) + { + error = elt->fp (vnm, if_index, flags); + if (error) + return error; + elt = elt->next_interface_function; + } } return error; } @@ -621,6 +631,16 @@ vnet_delete_sw_interface (vnet_main_t * vnm, u32 sw_if_index) vnet_sw_interface_t *sw = pool_elt_at_index (im->sw_interfaces, sw_if_index); + /* Make sure the interface is in L3 mode (removed from L2 BD or XConnect) */ + vlib_main_t *vm = vlib_get_main (); + l2_input_config_t *config; + config = vec_elt_at_index (l2input_main.configs, sw_if_index); + if (config->xconnect) + set_int_l2_mode (vm, vnm, MODE_L3, config->output_sw_if_index, 0, 0, 0, + 0); + if (config->xconnect || config->bridge) + set_int_l2_mode (vm, vnm, MODE_L3, sw_if_index, 0, 0, 0, 0); + /* Bring down interface in case it is up. */ if (sw->flags != 0) vnet_sw_interface_set_flags (vnm, sw_if_index, /* flags */ 0); @@ -638,6 +658,7 @@ setup_tx_node (vlib_main_t * vm, n->function = dev_class->tx_function; n->format_trace = dev_class->format_tx_trace; + vlib_register_errors (vm, node_index, dev_class->tx_function_n_errors, dev_class->tx_function_error_strings); @@ -718,6 +739,8 @@ vnet_register_interface (vnet_main_t * vnm, { vnet_hw_interface_nodes_t *hn; vnet_interface_output_runtime_t *rt; + vlib_node_t *node; + vlib_node_runtime_t *nrt; hn = vec_end (im->deleted_hw_interface_nodes) - 1; @@ -739,6 +762,22 @@ vnet_register_interface (vnet_main_t * vnm, rt->sw_if_index = hw->sw_if_index; rt->dev_instance = hw->dev_instance; + /* The new class may differ from the old one. + * Functions have to be updated. */ + node = vlib_get_node (vm, hw->output_node_index); + node->function = dev_class->no_flatten_output_chains ? + vnet_interface_output_node_no_flatten_multiarch_select () : + vnet_interface_output_node_multiarch_select (); + node->format_trace = format_vnet_interface_output_trace; + nrt = vlib_node_get_runtime (vm, hw->output_node_index); + nrt->function = node->function; + + node = vlib_get_node (vm, hw->tx_node_index); + node->function = dev_class->tx_function; + node->format_trace = dev_class->format_tx_trace; + nrt = vlib_node_get_runtime (vm, hw->tx_node_index); + nrt->function = node->function; + vlib_worker_thread_node_runtime_update (); _vec_len (im->deleted_hw_interface_nodes) -= 1; } @@ -787,14 +826,9 @@ vnet_register_interface (vnet_main_t * vnm, } hw->output_node_index = vlib_register_node (vm, &r); -#define _(sym,str) vlib_node_add_named_next_with_slot (vm, \ - hw->output_node_index, str, \ - VNET_INTERFACE_OUTPUT_NEXT_##sym); - foreach_intf_output_feat -#undef _ - vlib_node_add_named_next_with_slot (vm, hw->output_node_index, - "error-drop", - VNET_INTERFACE_OUTPUT_NEXT_DROP); + vlib_node_add_named_next_with_slot (vm, hw->output_node_index, + "error-drop", + VNET_INTERFACE_OUTPUT_NEXT_DROP); vlib_node_add_next_with_slot (vm, hw->output_node_index, hw->tx_node_index, VNET_INTERFACE_OUTPUT_NEXT_TX); @@ -862,6 +896,27 @@ vnet_delete_hw_interface (vnet_main_t * vnm, u32 hw_if_index) pool_put (im->hw_interfaces, hw); } +void +vnet_hw_interface_walk_sw (vnet_main_t * vnm, + u32 hw_if_index, + vnet_hw_sw_interface_walk_t fn, void *ctx) +{ + vnet_hw_interface_t *hi; + u32 id, sw_if_index; + + hi = vnet_get_hw_interface (vnm, hw_if_index); + /* the super first, then the and sub interfaces */ + fn (vnm, hi->sw_if_index, ctx); + + /* *INDENT-OFF* */ + hash_foreach (id, sw_if_index, + hi->sub_interface_sw_if_index_by_id, + ({ + fn (vnm, sw_if_index, ctx); + })); + /* *INDENT-ON* */ +} + static void serialize_vnet_hw_interface_set_class (serialize_main_t * m, va_list * va) { @@ -1042,6 +1097,16 @@ vnet_hw_interface_compare (vnet_main_t * vnm, return (word) h0->hw_instance - (word) h1->hw_instance; } +int +vnet_sw_interface_is_p2p (vnet_main_t * vnm, u32 sw_if_index) +{ + vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index); + vnet_hw_interface_class_t *hc = + vnet_get_hw_interface_class (vnm, hw->hw_class_index); + + return (hc->flags & VNET_HW_INTERFACE_CLASS_FLAG_P2P); +} + clib_error_t * vnet_interface_init (vlib_main_t * vm) { @@ -1118,6 +1183,12 @@ vnet_interface_init (vlib_main_t * vm) { c->index = vec_len (im->hw_interface_classes); hash_set_mem (im->hw_interface_class_by_name, c->name, c->index); + + if (NULL == c->build_rewrite) + c->build_rewrite = default_build_rewrite; + if (NULL == c->update_adjacency) + c->update_adjacency = default_update_adjacency; + vec_add1 (im->hw_interface_classes, c[0]); c = c->next_class_registration; } @@ -1165,34 +1236,6 @@ vnet_interface_name_renumber (u32 sw_if_index, u32 new_show_dev_instance) return rv; } -int -vnet_interface_add_del_feature (vnet_main_t * vnm, - vlib_main_t * vm, - u32 sw_if_index, - intf_output_feat_t feature, int is_add) -{ - vnet_sw_interface_t *sw; - - sw = vnet_get_sw_interface (vnm, sw_if_index); - - if (is_add) - { - - sw->output_feature_bitmap |= (1 << feature); - sw->output_feature_bitmap |= (1 << INTF_OUTPUT_FEAT_DONE); - - } - else - { /* delete */ - - sw->output_feature_bitmap &= ~(1 << feature); - if (sw->output_feature_bitmap == (1 << INTF_OUTPUT_FEAT_DONE)) - sw->output_feature_bitmap = 0; - - } - return 0; -} - clib_error_t * vnet_rename_interface (vnet_main_t * vnm, u32 hw_if_index, char *new_name) { @@ -1229,6 +1272,107 @@ vnet_rename_interface (vnet_main_t * vnm, u32 hw_if_index, char *new_name) return error; } +static clib_error_t * +vnet_hw_interface_change_mac_address_helper (vnet_main_t * vnm, + u32 hw_if_index, u64 mac_address) +{ + clib_error_t *error = 0; + vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index); + + if (hi->hw_address) + { + vnet_device_class_t *dev_class = + vnet_get_device_class (vnm, hi->dev_class_index); + if (dev_class->mac_addr_change_function) + { + error = + dev_class->mac_addr_change_function (vnet_get_hw_interface + (vnm, hw_if_index), + (char *) &mac_address); + } + if (!error) + { + ethernet_main_t *em = ðernet_main; + ethernet_interface_t *ei = + pool_elt_at_index (em->interfaces, hi->hw_instance); + + vec_validate (hi->hw_address, + STRUCT_SIZE_OF (ethernet_header_t, src_address) - 1); + clib_memcpy (hi->hw_address, &mac_address, + vec_len (hi->hw_address)); + + clib_memcpy (ei->address, (u8 *) & mac_address, + sizeof (ei->address)); + ethernet_arp_change_mac (vnm, hw_if_index); + ethernet_ndp_change_mac (vnm->vlib_main, hw_if_index); + } + else + { + error = + clib_error_return (0, + "MAC Address Change is not supported on this interface"); + } + } + else + { + error = + clib_error_return (0, + "mac address change is not supported for interface index %u", + hw_if_index); + } + return error; +} + +clib_error_t * +vnet_hw_interface_change_mac_address (vnet_main_t * vnm, u32 hw_if_index, + u64 mac_address) +{ + return vnet_hw_interface_change_mac_address_helper + (vnm, hw_if_index, mac_address); +} + +vnet_l3_packet_type_t +vnet_link_to_l3_proto (vnet_link_t link) +{ + switch (link) + { + case VNET_LINK_IP4: + return (VNET_L3_PACKET_TYPE_IP4); + case VNET_LINK_IP6: + return (VNET_L3_PACKET_TYPE_IP6); + case VNET_LINK_MPLS: + return (VNET_L3_PACKET_TYPE_MPLS_UNICAST); + case VNET_LINK_ARP: + return (VNET_L3_PACKET_TYPE_ARP); + case VNET_LINK_ETHERNET: + ASSERT (0); + break; + } + ASSERT (0); + return (0); +} + +u8 * +default_build_rewrite (vnet_main_t * vnm, + u32 sw_if_index, + vnet_link_t link_type, const void *dst_address) +{ + return (NULL); +} + +void +default_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai) +{ + u8 *rewrite; + + rewrite = vnet_build_rewrite_for_sw_interface (vnm, sw_if_index, + adj_get_link_type (ai), + NULL); + + adj_nbr_update_rewrite (ai, ADJ_NBR_REWRITE_FLAG_COMPLETE, rewrite); +} + + /* * fd.io coding-style-patch-verification: ON *