diff options
author | Damjan Marion <damarion@cisco.com> | 2020-08-20 17:28:20 +0200 |
---|---|---|
committer | Florin Coras <florin.coras@gmail.com> | 2020-09-11 07:49:45 +0000 |
commit | 66bb7dd64ee2377103e18b96f1e6bf6405de44b5 (patch) | |
tree | 1a98102ba4c0346431de03717d0c6dbf7344e443 /src/plugins/avf/device.c | |
parent | 78681def21b931309a779dfc6a5cbc6ff8b1f814 (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.c | 31 |
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); |