avf: validate queue size config
[vpp.git] / src / plugins / avf / device.c
index b0cf486..d711504 100644 (file)
@@ -399,6 +399,11 @@ avf_send_to_pf (vlib_main_t * vm, avf_device_t * ad, virtchnl_ops_t op,
   u32 head;
   f64 t0, suspend_time = AVF_SEND_TO_PF_SUSPEND_TIME;
 
+  /* adminq operations should be only done from process node after device
+   * is initialized */
+  ASSERT ((ad->flags & AVF_DEVICE_F_INITIALIZED) == 0 ||
+         vlib_get_current_process_node_index (vm) == avf_process_node.index);
+
   /* suppress interrupt in the next adminq receive slot
      as we are going to wait for response
      we only need interrupts when event is received */
@@ -1158,7 +1163,6 @@ avf_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hw, u32 flags)
 {
   vlib_main_t *vm = vlib_get_main ();
   avf_device_t *ad = avf_get_device (hw->dev_instance);
-  clib_error_t *error;
   u8 promisc_enabled;
 
   switch (flags)
@@ -1174,13 +1178,12 @@ avf_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hw, u32 flags)
     }
 
   promisc_enabled = ((ad->flags & AVF_DEVICE_F_PROMISC) != 0);
-  if ((error = avf_config_promisc_mode (vm, ad, promisc_enabled)))
-    {
-      avf_log_err (ad, "%s: %U", format_clib_error, error);
-      clib_error_free (error);
-      return ~0;
-    }
 
+  vlib_process_signal_event (vm, avf_process_node.index,
+                            promisc_enabled ?
+                            AVF_PROCESS_EVENT_SET_PROMISC_ENABLE :
+                            AVF_PROCESS_EVENT_SET_PROMISC_DISABLE,
+                            hw->dev_instance);
   return 0;
 }
 
@@ -1225,6 +1228,25 @@ avf_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
        case AVF_PROCESS_EVENT_AQ_INT:
          irq = 1;
          break;
+       case AVF_PROCESS_EVENT_SET_PROMISC_ENABLE:
+       case AVF_PROCESS_EVENT_SET_PROMISC_DISABLE:
+         for (int i = 0; i < vec_len (event_data); i++)
+           {
+             avf_device_t *ad = avf_get_device (event_data[i]);
+             clib_error_t *err;
+             int is_enable = 0;
+
+             if (event_type == AVF_PROCESS_EVENT_SET_PROMISC_ENABLE)
+               is_enable = 1;
+
+             if ((err = avf_config_promisc_mode (vm, ad, is_enable)))
+               {
+                 avf_log_err (ad, "error: %U", format_clib_error, err);
+                 clib_error_free (err);
+               }
+           }
+         break;
+
        default:
          ASSERT (0);
        }
@@ -1396,28 +1418,56 @@ avf_delete_if (vlib_main_t * vm, avf_device_t * ad, int with_barrier)
   clib_mem_free (ad);
 }
 
-void
-avf_create_if (vlib_main_t * vm, avf_create_if_args_t * args)
+static u8
+avf_validate_queue_size (avf_create_if_args_t * args)
 {
-  vnet_main_t *vnm = vnet_get_main ();
-  avf_main_t *am = &avf_main;
-  avf_device_t *ad, **adp;
-  vlib_pci_dev_handle_t h;
   clib_error_t *error = 0;
-  int i;
 
-  /* check input args */
   args->rxq_size = (args->rxq_size == 0) ? AVF_RXQ_SZ : args->rxq_size;
   args->txq_size = (args->txq_size == 0) ? AVF_TXQ_SZ : args->txq_size;
 
-  if ((args->rxq_size & (args->rxq_size - 1))
-      || (args->txq_size & (args->txq_size - 1)))
+  if ((args->rxq_size > AVF_QUEUE_SZ_MAX)
+      || (args->txq_size > AVF_QUEUE_SZ_MAX))
+    {
+      args->rv = VNET_API_ERROR_INVALID_VALUE;
+      args->error =
+       clib_error_return (error, "queue size must not be greater than %u",
+                          AVF_QUEUE_SZ_MAX);
+      return 1;
+    }
+  if ((args->rxq_size < AVF_QUEUE_SZ_MIN)
+      || (args->txq_size < AVF_QUEUE_SZ_MIN))
+    {
+      args->rv = VNET_API_ERROR_INVALID_VALUE;
+      args->error =
+       clib_error_return (error, "queue size must not be smaller than %u",
+                          AVF_QUEUE_SZ_MIN);
+      return 1;
+    }
+  if ((args->rxq_size & (args->rxq_size - 1)) ||
+      (args->txq_size & (args->txq_size - 1)))
     {
       args->rv = VNET_API_ERROR_INVALID_VALUE;
       args->error =
        clib_error_return (error, "queue size must be a power of two");
-      return;
+      return 1;
     }
+  return 0;
+}
+
+void
+avf_create_if (vlib_main_t * vm, avf_create_if_args_t * args)
+{
+  vnet_main_t *vnm = vnet_get_main ();
+  avf_main_t *am = &avf_main;
+  avf_device_t *ad, **adp;
+  vlib_pci_dev_handle_t h;
+  clib_error_t *error = 0;
+  int i;
+
+  /* check input args */
+  if (avf_validate_queue_size (args) != 0)
+    return;
 
   pool_get (am->devices, adp);
   adp[0] = ad = clib_mem_alloc_aligned (sizeof (avf_device_t),