summaryrefslogtreecommitdiffstats
path: root/src/plugins/avf/device.c
diff options
context:
space:
mode:
authorDamjan Marion <damarion@cisco.com>2020-08-20 17:28:20 +0200
committerFlorin Coras <florin.coras@gmail.com>2020-09-11 07:49:45 +0000
commit66bb7dd64ee2377103e18b96f1e6bf6405de44b5 (patch)
tree1a98102ba4c0346431de03717d0c6dbf7344e443 /src/plugins/avf/device.c
parent78681def21b931309a779dfc6a5cbc6ff8b1f814 (diff)
avf: fix race between avf process node and avf_delete_if(...)
It may happen that process node is suspended while it waits for response from adminq and during that time CLI or API process can call avf_delete_if. When avf process node resumes, it may happen that device is not there anymeore. This patch delegates interface deletion to process node, so CLI/API process just sends signal instead of deleting device instance itself. Type: fix Change-Id: I7f12e12df3071650f6e60ad7eb5af23b7acfe335 Signed-off-by: Damjan Marion <damarion@cisco.com>
Diffstat (limited to 'src/plugins/avf/device.c')
-rw-r--r--src/plugins/avf/device.c31
1 files changed, 24 insertions, 7 deletions
diff --git a/src/plugins/avf/device.c b/src/plugins/avf/device.c
index f086cd67741..62a18cc3c5c 100644
--- a/src/plugins/avf/device.c
+++ b/src/plugins/avf/device.c
@@ -35,6 +35,7 @@
#define PCI_DEVICE_ID_INTEL_X722_VF 0x37cd
avf_main_t avf_main;
+void avf_delete_if (vlib_main_t * vm, avf_device_t * ad, int with_barrier);
static pci_device_id_t avf_pci_device_ids[] = {
{.vendor_id = PCI_VENDOR_ID_INTEL,.device_id = PCI_DEVICE_ID_INTEL_AVF},
@@ -1202,7 +1203,6 @@ avf_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
vlib_process_wait_for_event (vm);
event_type = vlib_process_get_events (vm, &event_data);
- vec_reset_length (event_data);
irq = 0;
switch (event_type)
@@ -1213,9 +1213,15 @@ avf_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
case AVF_PROCESS_EVENT_START:
enabled = 1;
break;
- case AVF_PROCESS_EVENT_STOP:
- enabled = 0;
- continue;
+ case AVF_PROCESS_EVENT_DELETE_IF:
+ for (int i = 0; i < vec_len (event_data); i++)
+ {
+ ad = pool_elt_at_index (am->devices, event_data[i]);
+ avf_delete_if (vm, ad, /* with_barrier */ 1);
+ }
+ if (pool_elts (am->devices) < 1)
+ enabled = 0;
+ break;
case AVF_PROCESS_EVENT_AQ_INT:
irq = 1;
break;
@@ -1223,6 +1229,11 @@ avf_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
ASSERT (0);
}
+ vec_reset_length (event_data);
+
+ if (enabled == 0)
+ continue;
+
/* *INDENT-OFF* */
pool_foreach (ad, am->devices,
{
@@ -1235,7 +1246,7 @@ avf_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
}
/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (avf_process_node, static) = {
+VLIB_REGISTER_NODE (avf_process_node) = {
.function = avf_process,
.type = VLIB_NODE_TYPE_PROCESS,
.name = "avf-process",
@@ -1316,17 +1327,23 @@ avf_irq_n_handler (vlib_main_t * vm, vlib_pci_dev_handle_t h, u16 line)
}
void
-avf_delete_if (vlib_main_t * vm, avf_device_t * ad)
+avf_delete_if (vlib_main_t * vm, avf_device_t * ad, int with_barrier)
{
vnet_main_t *vnm = vnet_get_main ();
avf_main_t *am = &avf_main;
int i;
+ ad->flags &= ~AVF_DEVICE_F_ADMIN_UP;
+
if (ad->hw_if_index)
{
+ if (with_barrier)
+ vlib_worker_thread_barrier_sync (vm);
vnet_hw_interface_set_flags (vnm, ad->hw_if_index, 0);
vnet_hw_interface_unassign_rx_thread (vnm, ad->hw_if_index, 0);
ethernet_delete_interface (vnm, ad->hw_if_index);
+ if (with_barrier)
+ vlib_worker_thread_barrier_release (vm);
}
vlib_pci_device_close (vm, ad->pci_dev_handle);
@@ -1530,7 +1547,7 @@ avf_create_if (vlib_main_t * vm, avf_create_if_args_t * args)
return;
error:
- avf_delete_if (vm, ad);
+ avf_delete_if (vm, ad, /* with_barrier */ 0);
args->rv = VNET_API_ERROR_INVALID_INTERFACE;
args->error = clib_error_return (error, "pci-addr %U",
format_vlib_pci_addr, &args->addr);