dev: secondary interfaces support

Type: feature
Change-Id: I6cc4340431b8273022955fca1600061a722e3ace
Signed-off-by: Damjan Marion <damarion@cisco.com>
This commit is contained in:
Damjan Marion
2024-10-08 20:50:56 +02:00
committed by Damjan Marion
parent de020ab478
commit 61e287b9f8
11 changed files with 765 additions and 183 deletions

View File

@ -156,6 +156,7 @@ vnet_dev_api_create_port_if (vlib_main_t *vm,
{
vnet_dev_t *dev = vnet_dev_by_index (args->dev_index);
vnet_dev_port_t *port = 0;
vnet_dev_port_if_create_args_t a = {};
u16 n_threads = vlib_get_n_threads ();
int default_is_intr_mode;
vnet_dev_rv_t rv;
@ -181,7 +182,7 @@ vnet_dev_api_create_port_if (vlib_main_t *vm,
if (!port)
return VNET_DEV_ERR_INVALID_DEVICE_ID;
if (port->interface_created)
if (port->interfaces)
return VNET_DEV_ERR_ALREADY_EXISTS;
if (args->args)
@ -202,47 +203,82 @@ vnet_dev_api_create_port_if (vlib_main_t *vm,
{
if (args->num_rx_queues > port->attr.max_rx_queues)
return VNET_DEV_ERR_INVALID_NUM_RX_QUEUES;
port->intf.num_rx_queues = args->num_rx_queues;
a.num_rx_queues = args->num_rx_queues;
}
else
port->intf.num_rx_queues = clib_min (port->attr.max_tx_queues, 1);
a.num_rx_queues = clib_min (port->attr.max_tx_queues, 1);
if (args->num_tx_queues)
{
if (args->num_tx_queues > port->attr.max_tx_queues)
return VNET_DEV_ERR_INVALID_NUM_TX_QUEUES;
port->intf.num_tx_queues = args->num_tx_queues;
a.num_tx_queues = args->num_tx_queues;
}
else
port->intf.num_tx_queues = clib_min (port->attr.max_tx_queues, n_threads);
a.num_tx_queues = clib_min (port->attr.max_tx_queues, n_threads);
if (args->rx_queue_size)
{
if (!_vnet_dev_queue_size_validate (args->rx_queue_size,
port->rx_queue_config))
return VNET_DEV_ERR_INVALID_RX_QUEUE_SIZE;
port->intf.rxq_sz = args->rx_queue_size;
a.rxq_sz = args->rx_queue_size;
}
else
port->intf.rxq_sz = port->rx_queue_config.default_size;
a.rxq_sz = port->rx_queue_config.default_size;
if (args->tx_queue_size)
{
if (!_vnet_dev_queue_size_validate (args->tx_queue_size,
port->tx_queue_config))
return VNET_DEV_ERR_INVALID_TX_QUEUE_SIZE;
port->intf.txq_sz = args->tx_queue_size;
a.txq_sz = args->tx_queue_size;
}
else
port->intf.txq_sz = port->tx_queue_config.default_size;
a.txq_sz = port->tx_queue_config.default_size;
clib_memcpy (port->intf.name, args->intf_name, sizeof (port->intf.name));
port->intf.default_is_intr_mode = default_is_intr_mode;
port->intf.consistent_qp =
(args->flags.n & VNET_DEV_PORT_F_CONSISTENT_QP) != 0;
clib_memcpy (a.name, args->intf_name, sizeof (a.name));
a.default_is_intr_mode = default_is_intr_mode;
a.consistent_qp = (args->flags.n & VNET_DEV_PORT_F_CONSISTENT_QP) != 0;
rv = vnet_dev_process_call_port_op (vm, port, vnet_dev_port_if_create);
args->sw_if_index = (rv == VNET_DEV_OK) ? port->intf.sw_if_index : ~0;
rv = vnet_dev_process_call_port_op_with_ptr (vm, port,
vnet_dev_port_if_create, &a);
args->sw_if_index = (rv == VNET_DEV_OK) ? a.sw_if_index : ~0;
return rv;
}
vnet_dev_rv_t
vnet_dev_api_port_add_sec_if (vlib_main_t *vm,
vnet_dev_api_port_add_sec_if_args_t *args)
{
vnet_dev_port_t *port = 0;
vnet_dev_t *dev = 0;
vnet_dev_port_sec_if_create_args_t a = {};
vnet_dev_rv_t rv = VNET_DEV_OK;
port = vnet_dev_get_port_from_sw_if_index (args->primary_sw_if_index);
if (port == 0)
return VNET_DEV_ERR_NOT_FOUND;
log_debug (dev,
"create_port_if: primary_sw_if_index %u intf_name '%s' "
"args '%v'",
args->primary_sw_if_index, args->intf_name, args->args);
if (port->interfaces == 0)
return VNET_DEV_ERR_PRIMARY_INTERFACE_MISSING;
clib_memcpy (a.name, args->intf_name, sizeof (a.name));
a.args = args->args;
rv = vnet_dev_process_call_port_op_with_ptr (vm, port,
vnet_dev_port_add_sec_if, &a);
if (rv != VNET_DEV_OK)
args->sw_if_index = ~0;
else
args->sw_if_index = a.sw_if_index;
return rv;
}
@ -250,10 +286,24 @@ vnet_dev_api_create_port_if (vlib_main_t *vm,
vnet_dev_rv_t
vnet_dev_api_remove_port_if (vlib_main_t *vm,
vnet_dev_api_remove_port_if_args_t *args)
{
vnet_dev_port_t *port;
port = vnet_dev_get_port_from_sw_if_index (args->sw_if_index);
if (port == 0)
return VNET_DEV_ERR_UNKNOWN_INTERFACE;
return vnet_dev_process_call_port_op (vm, port, vnet_dev_port_if_remove);
}
vnet_dev_rv_t
vnet_dev_api_port_del_sec_if (vlib_main_t *vm,
vnet_dev_api_port_del_sec_if_args_t *args)
{
vnet_dev_main_t *dm = &vnet_dev_main;
vnet_main_t *vnm = vnet_get_main ();
vnet_sw_interface_t *si;
vnet_sw_interface_t *si, *sup_si;
vnet_hw_interface_t *hi;
vnet_dev_port_t *port;
@ -261,7 +311,14 @@ vnet_dev_api_remove_port_if (vlib_main_t *vm,
if (!si)
return VNET_DEV_ERR_UNKNOWN_INTERFACE;
hi = vnet_get_hw_interface_or_null (vnm, si->hw_if_index);
if (si->sup_sw_if_index == si->sw_if_index)
return VNET_DEV_ERR_UNKNOWN_INTERFACE;
sup_si = vnet_get_sw_interface_or_null (vnm, si->sup_sw_if_index);
if (!sup_si)
return VNET_DEV_ERR_UNKNOWN_INTERFACE;
hi = vnet_get_hw_interface_or_null (vnm, sup_si->hw_if_index);
if (!hi)
return VNET_DEV_ERR_UNKNOWN_INTERFACE;
@ -270,8 +327,10 @@ vnet_dev_api_remove_port_if (vlib_main_t *vm,
port = vnet_dev_get_port_from_dev_instance (hi->dev_instance);
if (port->intf.hw_if_index != si->hw_if_index)
if (port->interfaces->primary_interface.hw_if_index != si->hw_if_index)
return VNET_DEV_ERR_UNKNOWN_INTERFACE;
return vnet_dev_process_call_port_op (vm, port, vnet_dev_port_if_remove);
return vnet_dev_process_call_port_op_with_ptr (
vm, port, vnet_dev_port_del_sec_if,
&(vnet_dev_port_del_sec_if_args_t){ .sw_if_index = args->sw_if_index });
}

View File

@ -65,4 +65,27 @@ vnet_dev_rv_t
vnet_dev_api_remove_port_if (vlib_main_t *,
vnet_dev_api_remove_port_if_args_t *);
typedef struct
{
u32 primary_sw_if_index;
vnet_dev_if_name_t intf_name;
u8 *args;
/* return */
u32 sw_if_index;
} vnet_dev_api_port_add_sec_if_args_t;
vnet_dev_rv_t
vnet_dev_api_port_add_sec_if (vlib_main_t *,
vnet_dev_api_port_add_sec_if_args_t *);
typedef struct
{
u32 sw_if_index;
} vnet_dev_api_port_del_sec_if_args_t;
vnet_dev_rv_t
vnet_dev_api_port_del_sec_if (vlib_main_t *,
vnet_dev_api_port_del_sec_if_args_t *);
#endif /* _VNET_DEV_API_H_ */

View File

@ -222,6 +222,94 @@ VLIB_CLI_COMMAND (device_remove_if_cmd, static) = {
.is_mp_safe = 1,
};
static clib_error_t *
device_create_sec_if_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
vlib_cli_command_t *cmd)
{
vnet_dev_api_port_add_sec_if_args_t a = {};
vnet_main_t *vnm = vnet_get_main ();
vnet_dev_rv_t rv;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
if (!a.intf_name[0] &&
unformat (input, "if-name %U", unformat_c_string_array, a.intf_name,
sizeof (a.intf_name)))
;
else if (unformat (input, "primary-if-name %U",
unformat_vnet_sw_interface, vnm,
&a.primary_sw_if_index))
;
else if (unformat (input, "primary-sw-if-index %u",
&a.primary_sw_if_index))
;
else if (!a.args && unformat (input, "args %v", &a.args))
;
else
return clib_error_return (0, "unknown input `%U'",
format_unformat_error, input);
}
rv = vnet_dev_api_port_add_sec_if (vm, &a);
vec_free (a.args);
if (rv != VNET_DEV_OK)
return clib_error_return (0, "unable to create secondary interface: %U",
format_vnet_dev_rv, rv);
return 0;
}
VLIB_CLI_COMMAND (device_create_sec_if_cmd, static) = {
.path = "device create-secondary-interface",
.short_help = "device create-secondary-interface [<interface-name> | "
"sw-if-index <n>] id <n> [args <sec-if-args>]",
.function = device_create_sec_if_cmd_fn,
.is_mp_safe = 1,
};
static clib_error_t *
device_remove_sec_if_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
vlib_cli_command_t *cmd)
{
vnet_dev_api_port_del_sec_if_args_t a = { .sw_if_index = ~0 };
vnet_main_t *vnm = vnet_get_main ();
vnet_dev_rv_t rv;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
if (unformat (input, "%U", unformat_vnet_sw_interface, vnm,
&a.sw_if_index))
;
else if (unformat (input, "sw-if-index %u", &a.sw_if_index))
;
else
return clib_error_return (0, "unknown input `%U'",
format_unformat_error, input);
}
if (a.sw_if_index == ~0)
return clib_error_return (
0, "please specify existing secondary interface name");
rv = vnet_dev_api_port_del_sec_if (vm, &a);
if (rv != VNET_DEV_OK)
return clib_error_return (0, "unable to remove secondary interface: %U",
format_vnet_dev_rv, rv);
return 0;
}
VLIB_CLI_COMMAND (device_remove_sec_if_cmd, static) = {
.path = "device remove-secondary-interface",
.short_help =
"device remove-secondary-interface [<interface-name> | sw-if-index <n>]",
.function = device_remove_sec_if_cmd_fn,
.is_mp_safe = 1,
};
static clib_error_t *
show_devices_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
vlib_cli_command_t *cmd)

View File

@ -130,7 +130,7 @@ vnet_dev_deinit (vlib_main_t *vm, vnet_dev_t *dev)
vnet_dev_validate (vm, dev);
foreach_vnet_dev_port (p, dev)
ASSERT (p->interface_created == 0);
ASSERT (p->interfaces == 0);
if (dev->ops.deinit)
dev->ops.deinit (vm, dev);
@ -188,7 +188,7 @@ void
vnet_dev_detach (vlib_main_t *vm, vnet_dev_t *dev)
{
foreach_vnet_dev_port (p, dev)
if (p->interface_created)
if (p->interfaces)
vnet_dev_port_if_remove (vm, p);
vnet_dev_deinit (vm, dev);
vnet_dev_free (vm, dev);
@ -260,6 +260,8 @@ vnet_dev_feature_update_cb (u32 sw_if_index, u8 arc_index, u8 is_enable,
vnet_feature_config_main_t *cm;
vnet_dev_main_t *vdm = &vnet_dev_main;
vnet_dev_port_t *port;
vnet_dev_port_interface_t *intf;
vnet_dev_instance_t *di;
vnet_hw_interface_t *hw;
u32 current_config_index = ~0;
u32 next_index = ~0;
@ -269,9 +271,18 @@ vnet_dev_feature_update_cb (u32 sw_if_index, u8 arc_index, u8 is_enable,
return;
hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
port = vnet_dev_get_port_from_dev_instance (hw->dev_instance);
di = vnet_dev_get_dev_instance (hw->dev_instance);
if (port == 0 || port->intf.sw_if_index != sw_if_index)
if (!di)
return;
intf = di->is_primary_if ?
vnet_dev_port_get_primary_if (di->port) :
vnet_dev_port_get_sec_if_by_index (di->port, di->sec_if_index);
port = di->port;
if (port == 0 || intf->sw_if_index != sw_if_index)
return;
if (vnet_have_features (arc_index, sw_if_index))
@ -281,28 +292,27 @@ vnet_dev_feature_update_cb (u32 sw_if_index, u8 arc_index, u8 is_enable,
vec_elt (cm->config_index_by_sw_if_index, sw_if_index);
vnet_get_config_data (&cm->config_main, &current_config_index,
&next_index, 0);
if (port->intf.feature_arc == 0 ||
port->intf.rx_next_index != next_index ||
port->intf.current_config_index != current_config_index)
if (intf->feature_arc == 0 || intf->rx_next_index != next_index ||
intf->current_config_index != current_config_index)
{
port->intf.current_config_index = current_config_index;
port->intf.rx_next_index = next_index;
port->intf.feature_arc_index = arc_index;
port->intf.feature_arc = 1;
intf->current_config_index = current_config_index;
intf->rx_next_index = next_index;
intf->feature_arc_index = arc_index;
intf->feature_arc = 1;
update_runtime = 1;
}
}
else
{
if (port->intf.feature_arc)
if (intf->feature_arc)
{
port->intf.current_config_index = 0;
port->intf.rx_next_index =
port->intf.redirect_to_node ?
port->intf.redirect_to_node_next_index :
vnet_dev_default_next_index_by_port_type[port->attr.type];
port->intf.feature_arc_index = 0;
port->intf.feature_arc = 0;
intf->current_config_index = 0;
intf->rx_next_index =
intf->redirect_to_node ?
intf->redirect_to_node_next_index :
vnet_dev_default_next_index_by_port_type[port->attr.type];
intf->feature_arc_index = 0;
intf->feature_arc = 0;
update_runtime = 1;
}
}

View File

@ -29,7 +29,8 @@ typedef enum
_ (interrupt_mode) \
_ (rss) \
_ (change_max_rx_frame_size) \
_ (mac_filter)
_ (mac_filter) \
_ (secondary_interfaces)
#define foreach_vnet_dev_port_rx_offloads _ (ip4_cksum)
@ -253,6 +254,8 @@ typedef struct
vnet_dev_port_op_no_rv_t *deinit;
vnet_dev_port_op_no_rv_t *free;
vnet_dev_port_op_no_rv_t *clear_counters;
vnet_dev_port_op_with_ptr_t *add_sec_if;
vnet_dev_port_op_with_ptr_t *del_sec_if;
format_function_t *format_status;
format_function_t *format_flow;
} vnet_dev_port_ops_t;
@ -269,30 +272,41 @@ typedef union
u8 as_number;
} vnet_dev_rx_queue_rt_req_t;
typedef struct
{
vlib_buffer_template_t buffer_template;
u32 sw_if_index;
u16 next_index;
u16 sec_if_index;
} vnet_dev_rx_queue_if_rt_data_t;
typedef struct vnet_dev_rx_queue
{
CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
vnet_dev_port_t *port;
u16 rx_thread_index;
u16 index;
vnet_dev_counter_main_t *counter_main;
CLIB_CACHE_LINE_ALIGN_MARK (runtime0);
vnet_dev_rx_queue_t *next_on_thread;
u16 size;
u8 interrupt_mode : 1;
u8 enabled : 1;
u8 started : 1;
u8 suspended : 1;
vnet_dev_queue_id_t queue_id;
u16 size;
u16 next_index;
vnet_dev_rx_queue_rt_req_t runtime_request;
vnet_dev_counter_main_t *counter_main;
vnet_dev_rx_queue_t *next_on_thread;
vnet_dev_queue_id_t queue_id;
vnet_dev_rx_queue_if_rt_data_t **sec_if_rt_data;
CLIB_CACHE_LINE_ALIGN_MARK (runtime1);
vlib_buffer_template_t buffer_template;
vnet_dev_rx_queue_if_rt_data_t if_rt_data;
CLIB_CACHE_LINE_ALIGN_MARK (driver_data);
u8 data[];
} vnet_dev_rx_queue_t;
#if CLIB_CACHE_LINE_BYTES > 64
STATIC_ASSERT_SIZEOF (vnet_dev_rx_queue_t, 2 * CLIB_CACHE_LINE_BYTES);
#else
STATIC_ASSERT_SIZEOF (vnet_dev_rx_queue_t, 3 * CLIB_CACHE_LINE_BYTES);
#endif
typedef struct vnet_dev_tx_queue
{
@ -314,6 +328,38 @@ typedef struct vnet_dev_tx_queue
STATIC_ASSERT_SIZEOF (vnet_dev_tx_queue_t, 2 * CLIB_CACHE_LINE_BYTES);
typedef struct
{
vnet_dev_if_name_t name;
u8 interface_created : 1;
u8 feature_arc : 1;
u8 redirect_to_node : 1;
u8 feature_arc_index;
u16 rx_next_index;
u32 index;
u32 sw_if_index;
u32 hw_if_index;
u32 dev_instance;
u32 tx_node_index;
u32 next_index;
u32 current_config_index;
u16 redirect_to_node_next_index;
u32 user_data;
vnet_dev_arg_t *args;
} vnet_dev_port_interface_t;
typedef struct
{
u32 rx_node_index;
u8 default_is_intr_mode : 1;
u16 num_rx_queues;
u16 num_tx_queues;
u16 txq_sz;
u16 rxq_sz;
vnet_dev_port_interface_t primary_interface;
vnet_dev_port_interface_t **secondary_interfaces;
} vnet_dev_port_interfaces_t;
typedef struct vnet_dev_port
{
CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
@ -324,7 +370,6 @@ typedef struct vnet_dev_port
u8 started : 1;
u8 link_up : 1;
u8 promisc : 1;
u8 interface_created : 1;
u8 rx_node_assigned : 1;
vnet_dev_counter_main_t *counter_main;
vnet_dev_queue_config_t rx_queue_config;
@ -339,32 +384,12 @@ typedef struct vnet_dev_port
vnet_dev_tx_queue_t **tx_queues;
vnet_dev_port_ops_t port_ops;
vnet_dev_arg_t *args;
vnet_dev_arg_t *sec_if_args;
vnet_dev_rx_queue_ops_t rx_queue_ops;
vnet_dev_tx_queue_ops_t tx_queue_ops;
vnet_dev_node_t rx_node;
vnet_dev_node_t tx_node;
struct
{
vnet_dev_if_name_t name;
u32 dev_instance;
u32 rx_node_index;
u32 current_config_index;
u16 rx_next_index;
u16 redirect_to_node_next_index;
u8 feature_arc_index;
u8 feature_arc : 1;
u8 redirect_to_node : 1;
u8 default_is_intr_mode : 1;
u8 consistent_qp : 1;
u32 tx_node_index;
u32 hw_if_index;
u32 sw_if_index;
u16 num_rx_queues;
u16 num_tx_queues;
u16 txq_sz;
u16 rxq_sz;
} intf;
vnet_dev_port_interfaces_t *interfaces;
CLIB_CACHE_LINE_ALIGN_MARK (data0);
u8 data[];
@ -463,6 +488,8 @@ typedef struct
typedef struct
{
vnet_dev_port_t *port;
u32 sec_if_index;
u8 is_primary_if : 1;
} vnet_dev_instance_t;
typedef struct
@ -493,6 +520,7 @@ typedef struct
vnet_dev_port_attr_t attr;
vnet_dev_port_ops_t ops;
vnet_dev_arg_t *args;
vnet_dev_arg_t *sec_if_args;
u16 data_size;
void *initial_data;
} port;
@ -578,12 +606,44 @@ void vnet_dev_clear_hw_interface_counters (u32);
void vnet_dev_set_interface_next_node (vnet_main_t *, u32, u32);
/* port.c */
typedef struct
{
vnet_dev_if_name_t name;
u16 num_rx_queues;
u16 num_tx_queues;
u16 rxq_sz;
u16 txq_sz;
u8 default_is_intr_mode : 1;
u8 consistent_qp : 1;
/* return */
u32 sw_if_index;
} vnet_dev_port_if_create_args_t;
typedef struct
{
vnet_dev_if_name_t name;
u8 *args;
/* return */
u32 sw_if_index;
} vnet_dev_port_sec_if_create_args_t;
typedef struct
{
u32 sw_if_index;
} vnet_dev_port_del_sec_if_args_t;
vnet_dev_port_op_t vnet_dev_port_start;
vnet_dev_port_op_t vnet_dev_port_start_all_rx_queues;
vnet_dev_port_op_t vnet_dev_port_start_all_tx_queues;
vnet_dev_port_op_no_rv_t vnet_dev_port_stop;
vnet_dev_port_op_no_rv_t vnet_dev_port_deinit;
vnet_dev_port_op_no_rv_t vnet_dev_port_free;
vnet_dev_port_op_with_ptr_t vnet_dev_port_add_sec_if;
vnet_dev_port_op_with_ptr_t vnet_dev_port_del_sec_if;
void vnet_dev_port_add_counters (vlib_main_t *, vnet_dev_port_t *,
vnet_dev_counter_t *, u16);
vnet_dev_port_op_no_rv_t vnet_dev_port_free_counters;
@ -596,7 +656,7 @@ vnet_dev_port_cfg_change_req_validate (vlib_main_t *, vnet_dev_port_t *,
vnet_dev_port_cfg_change_req_t *);
vnet_dev_rv_t vnet_dev_port_cfg_change (vlib_main_t *, vnet_dev_port_t *,
vnet_dev_port_cfg_change_req_t *);
vnet_dev_port_op_t vnet_dev_port_if_create;
vnet_dev_port_op_with_ptr_t vnet_dev_port_if_create;
vnet_dev_port_op_t vnet_dev_port_if_remove;
/* queue.c */

View File

@ -60,6 +60,18 @@ vnet_dev_get_dev_instance (u32 dev_instance)
return pool_elt_at_index (dm->dev_instances, dev_instance);
}
static_always_inline vnet_dev_port_interface_t *
vnet_dev_port_get_primary_if (vnet_dev_port_t *p)
{
return &p->interfaces->primary_interface;
}
static_always_inline vnet_dev_port_interface_t *
vnet_dev_port_get_sec_if_by_index (vnet_dev_port_t *p, u32 index)
{
return *pool_elt_at_index (p->interfaces->secondary_interfaces, index);
}
static_always_inline vnet_dev_port_t *
vnet_dev_get_port_from_dev_instance (u32 dev_instance)
{
@ -76,7 +88,8 @@ vnet_dev_get_port_from_hw_if_index (u32 hw_if_index)
hw = vnet_get_hw_interface (vnet_get_main (), hw_if_index);
port = vnet_dev_get_port_from_dev_instance (hw->dev_instance);
if (!port || port->intf.hw_if_index != hw_if_index)
if (!port || !port->interfaces ||
port->interfaces->primary_interface.hw_if_index != hw_if_index)
return 0;
return port;
@ -85,19 +98,32 @@ vnet_dev_get_port_from_hw_if_index (u32 hw_if_index)
static_always_inline u32
vnet_dev_get_rx_queue_if_sw_if_index (vnet_dev_rx_queue_t *rxq)
{
return rxq->port->intf.sw_if_index;
return rxq->port->interfaces->primary_interface.sw_if_index;
}
static_always_inline u32
vnet_dev_get_rx_queue_if_hw_if_index (vnet_dev_rx_queue_t *rxq)
{
return rxq->port->intf.hw_if_index;
return rxq->port->interfaces->primary_interface.hw_if_index;
}
static_always_inline u32
vnet_dev_get_port_rx_node_index (vnet_dev_port_t *port)
{
return port->intf.rx_node_index;
return port->interfaces->rx_node_index;
}
static_always_inline vnet_dev_port_t *
vnet_dev_get_port_from_sw_if_index (u32 sw_if_index)
{
vnet_main_t *vnm = vnet_get_main ();
vnet_sw_interface_t *si;
si = vnet_get_sw_interface_or_null (vnm, sw_if_index);
if (!si)
return 0;
return vnet_dev_get_port_from_hw_if_index (si->hw_if_index);
}
static_always_inline vnet_dev_t *
@ -219,22 +245,49 @@ vnet_dev_tx_queue_unlock_if_needed (vnet_dev_tx_queue_t *txq)
__atomic_store_n (&txq->lock, 0, __ATOMIC_RELEASE);
}
static_always_inline vnet_dev_rx_queue_if_rt_data_t *
vnet_dev_get_rx_queue_if_rt_data (vnet_dev_rx_queue_t *rxq)
{
return &rxq->if_rt_data;
}
static_always_inline vnet_dev_rx_queue_if_rt_data_t *
vnet_dev_get_rx_queue_sec_if_rt_data (vnet_dev_rx_queue_t *rxq,
u32 sec_if_index)
{
return rxq->sec_if_rt_data[sec_if_index];
}
static_always_inline vlib_buffer_template_t
vnet_dev_get_rx_queue_if_buffer_template (vnet_dev_rx_queue_t *rxq)
{
return rxq->buffer_template;
return rxq->if_rt_data.buffer_template;
}
static_always_inline vlib_buffer_template_t
vnet_dev_get_rx_queue_sec_if_buffer_template (vnet_dev_rx_queue_t *rxq,
u32 sec_if_index)
{
return rxq->sec_if_rt_data[sec_if_index]->buffer_template;
}
static_always_inline u16
vnet_dev_get_rx_queue_if_next_index (vnet_dev_rx_queue_t *rxq)
{
return rxq->next_index;
return rxq->if_rt_data.next_index;
}
static_always_inline u16
vnet_dev_get_rx_queue_sec_if_next_index (vnet_dev_rx_queue_t *rxq,
u32 sec_if_index)
{
return rxq->sec_if_rt_data[sec_if_index]->next_index;
}
static_always_inline u8
vnet_dev_get_rx_queue_buffer_pool_index (vnet_dev_rx_queue_t *rxq)
{
return rxq->buffer_template.buffer_pool_index;
return rxq->if_rt_data.buffer_template.buffer_pool_index;
}
static_always_inline u32
@ -269,8 +322,8 @@ static_always_inline vnet_dev_rx_queue_t *
foreach_vnet_dev_rx_queue_runtime_helper (vlib_node_runtime_t *node,
vnet_dev_rx_queue_t *rxq)
{
vnet_dev_port_t *port;
vnet_dev_rx_queue_rt_req_t req;
vnet_dev_port_interfaces_t *ifs;
if (rxq == 0)
rxq = vnet_dev_get_rx_node_runtime (node)->first_rx_queue;
@ -287,15 +340,34 @@ foreach_vnet_dev_rx_queue_runtime_helper (vlib_node_runtime_t *node,
req.as_number =
__atomic_exchange_n (&rxq->runtime_request.as_number, 0, __ATOMIC_ACQUIRE);
port = rxq->port;
ifs = rxq->port->interfaces;
if (req.update_next_index)
rxq->next_index = port->intf.rx_next_index;
{
vnet_dev_port_interface_t **si =
rxq->port->interfaces->secondary_interfaces;
rxq->if_rt_data.next_index = ifs->primary_interface.rx_next_index;
vec_foreach_pointer (rtd, rxq->sec_if_rt_data)
if (rtd)
rtd->next_index = si[rtd->sec_if_index]->next_index;
}
if (req.update_feature_arc)
{
vlib_buffer_template_t *bt = &rxq->buffer_template;
bt->current_config_index = port->intf.current_config_index;
vnet_buffer (bt)->feature_arc_index = port->intf.feature_arc_index;
vnet_dev_port_interface_t **si =
rxq->port->interfaces->secondary_interfaces;
vlib_buffer_template_t *bt = &rxq->if_rt_data.buffer_template;
bt->current_config_index = ifs->primary_interface.current_config_index;
vnet_buffer (bt)->feature_arc_index =
ifs->primary_interface.feature_arc_index;
vec_foreach_pointer (rtd, rxq->sec_if_rt_data)
if (rtd)
{
vlib_buffer_template_t *bt = &rtd->buffer_template;
bt->current_config_index =
si[rtd->sec_if_index]->current_config_index;
vnet_buffer (bt)->feature_arc_index =
si[rtd->sec_if_index]->feature_arc_index;
}
}
if (req.suspend_on)

View File

@ -37,9 +37,12 @@
_ (TIMEOUT, "timeout") \
_ (UNKNOWN_DEVICE, "unknown device") \
_ (UNKNOWN_INTERFACE, "unknown interface") \
_ (NOT_PRIMARY_INTERFACE, "not primary interface") \
_ (PRIMARY_INTERFACE_MISSING, "primary interface missing") \
_ (UNSUPPORTED_CONFIG, "unsupported config") \
_ (UNSUPPORTED_DEVICE, "unsupported device") \
_ (UNSUPPORTED_DEVICE_VER, "unsupported device version") \
_ (UNSUPPORTED_INTERFACE, "unsupported interface") \
_ (ALREADY_DONE, "already done") \
_ (NO_SUCH_INTERFACE, "no such interface") \
_ (INIT_FAILED, "init failed")

View File

@ -44,9 +44,15 @@ u8 *
format_vnet_dev_interface_name (u8 *s, va_list *args)
{
u32 i = va_arg (*args, u32);
vnet_dev_port_t *port = vnet_dev_get_port_from_dev_instance (i);
vnet_dev_instance_t *di = vnet_dev_get_dev_instance (i);
vnet_dev_port_interface_t *si;
vnet_dev_port_t *p = di->port;
return format (s, "%s", port->intf.name);
if (di->is_primary_if)
return format (s, "%s", p->interfaces->primary_interface.name);
si = vnet_dev_port_get_sec_if_by_index (p, di->sec_if_index);
return format (s, "%s", si->name);
}
u8 *
@ -138,12 +144,22 @@ format_vnet_dev_port_info (u8 *s, va_list *args)
format_vnet_dev_args, port->args);
s = format (s, "\n%UInterface ", format_white_space, indent);
if (port->interface_created)
if (port->interfaces)
{
s = format (s, "assigned, interface name is '%U', RX node is '%U'",
format_vnet_sw_if_index_name, vnm, port->intf.sw_if_index,
format_vlib_node_name, vm,
vnet_dev_get_port_rx_node_index (port));
s = format (
s, "assigned, primary interface name is '%U', RX node is '%U'",
format_vnet_sw_if_index_name, vnm,
port->interfaces->primary_interface.sw_if_index, format_vlib_node_name,
vm, vnet_dev_get_port_rx_node_index (port));
pool_foreach_pointer (sif, port->interfaces->secondary_interfaces)
{
s = format (s, "\n%USecondary interface '%U'", format_white_space,
indent, format_vnet_sw_if_index_name, vnm,
sif->sw_if_index);
if (sif->args)
s = format (s, "\n%U args '%U", format_white_space, indent,
format_vnet_dev_args, sif->args);
}
}
else
s = format (s, "not assigned");

View File

@ -19,7 +19,8 @@ vnet_dev_port_set_max_frame_size (vnet_main_t *vnm, vnet_hw_interface_t *hw,
u32 frame_size)
{
vlib_main_t *vm = vlib_get_main ();
vnet_dev_port_t *p = vnet_dev_get_port_from_dev_instance (hw->dev_instance);
vnet_dev_instance_t *di = vnet_dev_get_dev_instance (hw->dev_instance);
vnet_dev_port_t *p;
vnet_dev_rv_t rv;
vnet_dev_port_cfg_change_req_t req = {
@ -27,6 +28,11 @@ vnet_dev_port_set_max_frame_size (vnet_main_t *vnm, vnet_hw_interface_t *hw,
.max_rx_frame_size = frame_size,
};
p = di->port;
if (!di->is_primary_if)
return vnet_dev_port_err (vm, p, VNET_DEV_ERR_NOT_PRIMARY_INTERFACE, "");
log_debug (p->dev, "size %u", frame_size);
rv = vnet_dev_port_cfg_change_req_validate (vm, p, &req);
@ -49,13 +55,17 @@ vnet_dev_port_eth_flag_change (vnet_main_t *vnm, vnet_hw_interface_t *hw,
u32 flags)
{
vlib_main_t *vm = vlib_get_main ();
vnet_dev_port_t *p = vnet_dev_get_port_from_dev_instance (hw->dev_instance);
vnet_dev_instance_t *di = vnet_dev_get_dev_instance (hw->dev_instance);
vnet_dev_port_t *p = di->port;
vnet_dev_rv_t rv;
vnet_dev_port_cfg_change_req_t req = {
.type = VNET_DEV_PORT_CFG_PROMISC_MODE,
};
if (!di->is_primary_if)
return ~0;
switch (flags)
{
case ETHERNET_INTERFACE_FLAG_DEFAULT_L3:
@ -87,13 +97,17 @@ vnet_dev_port_mac_change (vnet_hw_interface_t *hi, const u8 *old,
const u8 *new)
{
vlib_main_t *vm = vlib_get_main ();
vnet_dev_port_t *p = vnet_dev_get_port_from_dev_instance (hi->dev_instance);
vnet_dev_instance_t *di = vnet_dev_get_dev_instance (hi->dev_instance);
vnet_dev_port_t *p = di->port;
vnet_dev_rv_t rv;
vnet_dev_port_cfg_change_req_t req = {
.type = VNET_DEV_PORT_CFG_CHANGE_PRIMARY_HW_ADDR,
};
if (!di->is_primary_if)
return vnet_dev_port_err (vm, p, VNET_DEV_ERR_NOT_PRIMARY_INTERFACE, "");
vnet_dev_set_hw_addr_eth_mac (&req.addr, new);
log_debug (p->dev, "new mac %U", format_vnet_dev_hw_addr, &req.addr);
@ -116,7 +130,8 @@ vnet_dev_add_del_mac_address (vnet_hw_interface_t *hi, const u8 *address,
u8 is_add)
{
vlib_main_t *vm = vlib_get_main ();
vnet_dev_port_t *p = vnet_dev_get_port_from_dev_instance (hi->dev_instance);
vnet_dev_instance_t *di = vnet_dev_get_dev_instance (hi->dev_instance);
vnet_dev_port_t *p = di->port;
vnet_dev_rv_t rv;
vnet_dev_port_cfg_change_req_t req = {
@ -124,6 +139,9 @@ vnet_dev_add_del_mac_address (vnet_hw_interface_t *hi, const u8 *address,
VNET_DEV_PORT_CFG_REMOVE_SECONDARY_HW_ADDR,
};
if (!di->is_primary_if)
return vnet_dev_port_err (vm, p, VNET_DEV_ERR_NOT_PRIMARY_INTERFACE, "");
vnet_dev_set_hw_addr_eth_mac (&req.addr, address);
log_debug (p->dev, "received (addr %U is_add %u", format_vnet_dev_hw_addr,
@ -147,10 +165,19 @@ vnet_dev_flow_ops_fn (vnet_main_t *vnm, vnet_flow_dev_op_t op,
u32 dev_instance, u32 flow_index, uword *private_data)
{
vlib_main_t *vm = vlib_get_main ();
vnet_dev_port_t *p = vnet_dev_get_port_from_dev_instance (dev_instance);
vnet_dev_instance_t *di = vnet_dev_get_dev_instance (dev_instance);
vnet_dev_port_t *p;
vnet_dev_port_cfg_change_req_t req;
vnet_dev_rv_t rv;
if (!di)
return VNET_FLOW_ERROR_NO_SUCH_INTERFACE;
if (di->is_primary_if)
return VNET_FLOW_ERROR_NOT_SUPPORTED;
p = di->port;
switch (op)
{
case VNET_FLOW_DEV_OP_ADD_FLOW:
@ -201,10 +228,12 @@ vnet_dev_interface_set_rss_queues (vnet_main_t *vnm, vnet_hw_interface_t *hi,
void
vnet_dev_clear_hw_interface_counters (u32 instance)
{
vnet_dev_port_t *port = vnet_dev_get_port_from_dev_instance (instance);
vnet_dev_instance_t *di = vnet_dev_get_dev_instance (instance);
vlib_main_t *vm = vlib_get_main ();
vnet_dev_process_call_port_op_no_rv (vm, port, vnet_dev_port_clear_counters);
if (di->is_primary_if)
vnet_dev_process_call_port_op_no_rv (vm, di->port,
vnet_dev_port_clear_counters);
}
void
@ -213,44 +242,49 @@ vnet_dev_set_interface_next_node (vnet_main_t *vnm, u32 hw_if_index,
{
vlib_main_t *vm = vlib_get_main ();
vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
vnet_dev_port_t *port =
vnet_dev_get_port_from_dev_instance (hw->dev_instance);
vnet_dev_instance_t *di = vnet_dev_get_dev_instance (hw->dev_instance);
vnet_dev_port_interface_t *intf;
int runtime_update = 0;
if (di->is_primary_if)
intf = vnet_dev_port_get_primary_if (di->port);
else
intf = vnet_dev_port_get_sec_if_by_index (di->port, di->sec_if_index);
if (node_index == ~0)
{
port->intf.redirect_to_node_next_index = 0;
if (port->intf.feature_arc == 0)
intf->redirect_to_node_next_index = 0;
if (intf->feature_arc == 0)
{
port->intf.rx_next_index =
vnet_dev_default_next_index_by_port_type[port->attr.type];
intf->rx_next_index =
vnet_dev_default_next_index_by_port_type[di->port->attr.type];
runtime_update = 1;
}
port->intf.redirect_to_node = 0;
intf->redirect_to_node = 0;
}
else
{
u16 next_index = vlib_node_add_next (vlib_get_main (),
port_rx_eth_node.index, node_index);
port->intf.redirect_to_node_next_index = next_index;
if (port->intf.feature_arc == 0)
intf->redirect_to_node_next_index = next_index;
if (intf->feature_arc == 0)
{
port->intf.rx_next_index = next_index;
intf->rx_next_index = next_index;
runtime_update = 1;
}
port->intf.redirect_to_node = 1;
intf->redirect_to_node = 1;
}
port->intf.rx_next_index =
intf->rx_next_index =
node_index == ~0 ?
vnet_dev_default_next_index_by_port_type[port->attr.type] :
node_index;
vnet_dev_default_next_index_by_port_type[di->port->attr.type] :
node_index;
if (runtime_update)
{
foreach_vnet_dev_port_rx_queue (rxq, port)
foreach_vnet_dev_port_rx_queue (rxq, di->port)
vnet_dev_rx_queue_rt_request (
vm, rxq, (vnet_dev_rx_queue_rt_req_t){ .update_next_index = 1 });
log_debug (port->dev, "runtime update requested due to chgange in "
"reditect-to-next configuration");
log_debug (di->port->dev, "runtime update requested due to chgange in "
"reditect-to-next configuration");
}
}

File diff suppressed because it is too large Load Diff

View File

@ -36,7 +36,6 @@ vnet_dev_rx_queue_alloc (vlib_main_t *vm, vnet_dev_port_t *port,
vnet_dev_t *dev = port->dev;
vnet_dev_rv_t rv = VNET_DEV_OK;
u16 n_threads = vlib_get_n_threads ();
u8 buffer_pool_index;
vnet_dev_port_validate (vm, port);
@ -65,15 +64,6 @@ vnet_dev_rx_queue_alloc (vlib_main_t *vm, vnet_dev_port_t *port,
dm->next_rx_queue_thread = 1;
}
buffer_pool_index =
vlib_buffer_pool_get_default_for_numa (vm, dev->numa_node);
vlib_buffer_pool_t *bp = vlib_get_buffer_pool (vm, buffer_pool_index);
rxq->buffer_template = bp->buffer_template;
vnet_buffer (&rxq->buffer_template)->sw_if_index[VLIB_TX] = ~0;
rxq->next_index = vnet_dev_default_next_index_by_port_type[port->attr.type];
if (port->rx_queue_ops.alloc)
rv = port->rx_queue_ops.alloc (vm, rxq);