#include <vnet/adj/adj_mcast.h>
#include <vnet/ip/ip.h>
#include <vnet/interface/rx_queue_funcs.h>
+#include <vnet/interface/tx_queue_funcs.h>
/* *INDENT-OFF* */
VLIB_REGISTER_LOG_CLASS (if_default_log, static) = {
goto done;
}
- /* save the si admin up flag */
- old_flags = si->flags;
-
/* update si admin up flag in advance if we are going admin down */
if (!(flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
si->flags &= ~VNET_SW_INTERFACE_FLAG_ADMIN_UP;
n->format_trace = dev_class->format_tx_trace;
- /// XXX: Update this to use counter structure
- vlib_register_errors (vm, node_index,
- dev_class->tx_function_n_errors,
- dev_class->tx_function_error_strings, 0);
+ vlib_register_errors (vm, node_index, dev_class->tx_function_n_errors,
+ dev_class->tx_function_error_strings,
+ dev_class->tx_function_error_counters);
}
static void
r.type = VLIB_NODE_TYPE_INTERNAL;
r.runtime_data = &rt;
r.runtime_data_bytes = sizeof (rt);
- r.scalar_size = 0;
+ r.scalar_size = sizeof (vnet_hw_if_tx_frame_t);
r.vector_size = sizeof (u32);
r.flags = VLIB_NODE_FLAG_IS_OUTPUT;
static char *e[] = {
"interface is down",
"interface is deleted",
- "no buffers to segment GSO",
};
r.n_errors = ARRAY_LEN (e);
/* Call delete callbacks. */
call_hw_interface_add_del_callbacks (vnm, hw_if_index, /* is_create */ 0);
- /* delete rx queues */
+ /* delete rx & tx queues */
vnet_hw_if_unregister_all_rx_queues (vnm, hw_if_index);
+ vnet_hw_if_unregister_all_tx_queues (vnm, hw_if_index);
vnet_hw_if_update_runtime_data (vnm, hw_if_index);
/* Delete any sub-interfaces. */
hash_unset_mem (im->hw_interface_by_name, hw->name);
vec_free (hw->name);
vec_free (hw->hw_address);
- vec_free (hw->input_node_thread_index_by_queue);
- vec_free (hw->rx_queue_indices);
+ vec_free (hw->output_node_thread_runtimes);
pool_put (im->hw_interfaces, hw);
}
return (hc->flags & VNET_HW_INTERFACE_CLASS_FLAG_NBMA);
}
+clib_error_t *
+vnet_sw_interface_supports_addressing (vnet_main_t *vnm, u32 sw_if_index)
+{
+ if (sw_if_index == 0)
+ {
+ return clib_error_create (
+ "local0 interface doesn't support IP addressing");
+ }
+
+ if (vnet_sw_interface_is_sub (vnm, sw_if_index))
+ {
+ vnet_sw_interface_t *si;
+ si = vnet_get_sw_interface_or_null (vnm, sw_if_index);
+ if (si && si->type == VNET_SW_INTERFACE_TYPE_SUB &&
+ si->sub.eth.flags.exact_match == 0)
+ {
+ return clib_error_create (
+ "sub-interface without exact-match doesn't support IP addressing");
+ }
+ }
+ return NULL;
+}
+
clib_error_t *
vnet_interface_init (vlib_main_t * vm)
{
im->rxq_index_by_hw_if_index_and_queue_id =
hash_create_mem (0, sizeof (u64), sizeof (u32));
+ im->txq_index_by_hw_if_index_and_queue_id =
+ hash_create_mem (0, sizeof (u64), sizeof (u32));
im->sw_if_index_by_sup_and_sub = hash_create_mem (0, sizeof (u64),
sizeof (uword));
{
(vnm, hw_if_index, mac_address);
}
+static int
+vnet_sw_interface_check_table_same (u32 unnumbered_sw_if_index,
+ u32 ip_sw_if_index)
+{
+ if (ip4_main.fib_index_by_sw_if_index[unnumbered_sw_if_index] !=
+ ip4_main.fib_index_by_sw_if_index[ip_sw_if_index])
+ return VNET_API_ERROR_UNEXPECTED_INTF_STATE;
+
+ if (ip4_main.mfib_index_by_sw_if_index[unnumbered_sw_if_index] !=
+ ip4_main.mfib_index_by_sw_if_index[ip_sw_if_index])
+ return VNET_API_ERROR_UNEXPECTED_INTF_STATE;
+
+ if (ip6_main.fib_index_by_sw_if_index[unnumbered_sw_if_index] !=
+ ip6_main.fib_index_by_sw_if_index[ip_sw_if_index])
+ return VNET_API_ERROR_UNEXPECTED_INTF_STATE;
+
+ if (ip6_main.mfib_index_by_sw_if_index[unnumbered_sw_if_index] !=
+ ip6_main.mfib_index_by_sw_if_index[ip_sw_if_index])
+ return VNET_API_ERROR_UNEXPECTED_INTF_STATE;
+
+ return 0;
+}
+
/* update the unnumbered state of an interface*/
-void
+int
vnet_sw_interface_update_unnumbered (u32 unnumbered_sw_if_index,
u32 ip_sw_if_index, u8 enable)
{
vnet_main_t *vnm = vnet_get_main ();
vnet_sw_interface_t *si;
u32 was_unnum;
+ int rv = 0;
si = vnet_get_sw_interface (vnm, unnumbered_sw_if_index);
was_unnum = (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED);
if (enable)
{
+ rv = vnet_sw_interface_check_table_same (unnumbered_sw_if_index,
+ ip_sw_if_index);
+ if (rv != 0)
+ return rv;
si->flags |= VNET_SW_INTERFACE_FLAG_UNNUMBERED;
si->unnumbered_sw_if_index = ip_sw_if_index;
}
else
{
- si->flags &= ~(VNET_SW_INTERFACE_FLAG_UNNUMBERED);
- si->unnumbered_sw_if_index = (u32) ~ 0;
+ /*
+ * Unless the interface is actually unnumbered, don't
+ * smash e.g. if_address_pool_index_by_sw_if_index
+ */
+ if (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
+ {
+ si->flags &= ~(VNET_SW_INTERFACE_FLAG_UNNUMBERED);
+ si->unnumbered_sw_if_index = (u32) ~0;
- ip4_main.lookup_main.if_address_pool_index_by_sw_if_index
- [unnumbered_sw_if_index] = ~0;
- ip6_main.lookup_main.if_address_pool_index_by_sw_if_index
- [unnumbered_sw_if_index] = ~0;
+ ip4_main.lookup_main
+ .if_address_pool_index_by_sw_if_index[unnumbered_sw_if_index] = ~0;
+ ip6_main.lookup_main
+ .if_address_pool_index_by_sw_if_index[unnumbered_sw_if_index] = ~0;
+ }
}
if (was_unnum != (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED))
ip4_sw_interface_enable_disable (unnumbered_sw_if_index, enable);
ip6_sw_interface_enable_disable (unnumbered_sw_if_index, enable);
}
+
+ return 0;
}
vnet_l3_packet_type_t