#include <vnet/vnet.h>
#include <vnet/plugin/plugin.h>
#include <vnet/fib/ip6_fib.h>
+#include <vnet/adj/adj.h>
#define VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE (1 << 0)
#define VNET_INTERFACE_SET_FLAGS_HELPER_WANT_REDISTRIBUTE (1 << 1)
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;
}
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);
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);
{
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;
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;
}
}
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);
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)
{
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)
{
{
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;
}
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)
{
ethernet_interface_t *ei =
pool_elt_at_index (em->interfaces, hi->hw_instance);
- clib_memcpy (hi->hw_address, (u8 *) & mac_address,
- sizeof (hi->hw_address));
+ 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);
(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
*