device: Add callback for set interface rx-mode 28/6628/4
authorSteven <sluong@cisco.com>
Tue, 9 May 2017 23:19:50 +0000 (16:19 -0700)
committerDamjan Marion <dmarion.lists@gmail.com>
Wed, 10 May 2017 15:49:27 +0000 (15:49 +0000)
- When the interface rx-mode is changed via CLI, the corresponding device
may want to know about it and to reset the driver. This patch is to add
the callback.

- In the function vnet_hw_interface_set_rx_mode, it appears it is missing
a line
  hw->rx_mode_by_queue[queue_id] = mode

because the function is checking if the new mode is the same as
hw->rx_mode_by_queue which is initialized to POLLING. So if the function is
called to change the mode to interrupt, it just returns without doing
anything. This is the check that I am talking about in the same function.

  if (hw->rx_mode_by_queue[queue_id] == mode)
    return 0;

Change-Id: Iaca2651c43e0ae3fda6fd8dc128e247b0851cc65
Signed-off-by: Steven <sluong@cisco.com>
src/vnet/devices/devices.c
src/vnet/interface.h
src/vnet/interface_cli.c

index d75d905..e71be60 100644 (file)
@@ -225,6 +225,7 @@ vnet_hw_interface_set_rx_mode (vnet_main_t * vnm, u32 hw_if_index,
       (hw->flags & VNET_HW_INTERFACE_FLAG_SUPPORTS_INT_MODE) == 0)
     return VNET_API_ERROR_UNSUPPORTED;
 
+  hw->rx_mode_by_queue[queue_id] = mode;
   thread_index = hw->input_node_thread_index_by_queue[queue_id];
   vm = vlib_mains[thread_index];
 
index 2344348..1c98555 100644 (file)
@@ -48,6 +48,15 @@ struct vnet_hw_interface_t;
 struct vnet_sw_interface_t;
 struct ip46_address_t;
 
+typedef enum
+{
+  VNET_HW_INTERFACE_RX_MODE_UNKNOWN,
+  VNET_HW_INTERFACE_RX_MODE_POLLING,
+  VNET_HW_INTERFACE_RX_MODE_INTERRUPT,
+  VNET_HW_INTERFACE_RX_MODE_ADAPTIVE,
+  VNET_HW_INTERFACE_NUM_RX_MODES,
+} vnet_hw_interface_rx_mode;
+
 /* Interface up/down callback. */
 typedef clib_error_t *(vnet_interface_function_t)
   (struct vnet_main_t * vnm, u32 if_index, u32 flags);
@@ -61,6 +70,11 @@ typedef clib_error_t *(vnet_subif_add_del_function_t)
 typedef clib_error_t *(vnet_interface_set_mac_address_function_t)
   (struct vnet_hw_interface_t * hi, char *address);
 
+/* Interface set rx mode callback. */
+typedef clib_error_t *(vnet_interface_set_rx_mode_function_t)
+  (struct vnet_main_t * vnm, u32 if_index, u32 queue_id,
+   vnet_hw_interface_rx_mode mode);
+
 typedef enum vnet_interface_function_priority_t_
 {
   VNET_ITF_FUNC_PRIORITY_LOW,
@@ -134,6 +148,9 @@ typedef struct _vnet_device_class
   /* Function to call when sub-interface is added/deleted */
   vnet_subif_add_del_function_t *subif_add_del_function;
 
+  /* Function to call interface rx mode is changed */
+  vnet_interface_set_rx_mode_function_t *rx_mode_change_function;
+
   /* Redistribute flag changes/existence of this interface class. */
   u32 redistribute;
 
@@ -492,15 +509,6 @@ typedef enum
   VNET_SW_INTERFACE_TYPE_SUB,
 } vnet_sw_interface_type_t;
 
-typedef enum
-{
-  VNET_HW_INTERFACE_RX_MODE_UNKNOWN,
-  VNET_HW_INTERFACE_RX_MODE_POLLING,
-  VNET_HW_INTERFACE_RX_MODE_INTERRUPT,
-  VNET_HW_INTERFACE_RX_MODE_ADAPTIVE,
-  VNET_HW_INTERFACE_NUM_RX_MODES,
-} vnet_hw_interface_rx_mode;
-
 typedef struct
 {
   /*
index bfce03e..e18a80f 100644 (file)
@@ -1175,6 +1175,54 @@ VLIB_CLI_COMMAND (clear_tag_command, static) = {
 };
 /* *INDENT-ON* */
 
+static clib_error_t *
+set_hw_interface_rx_mode (vnet_main_t * vnm, u32 hw_if_index,
+                         u32 queue_id, vnet_hw_interface_rx_mode mode)
+{
+  vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
+  vnet_device_class_t *dev_class =
+    vnet_get_device_class (vnm, hw->dev_class_index);
+  clib_error_t *error;
+  vnet_hw_interface_rx_mode old_mode;
+  int rv;
+
+  rv = vnet_hw_interface_get_rx_mode (vnm, hw_if_index, queue_id, &old_mode);
+  switch (rv)
+    {
+    case 0:
+      if (old_mode == mode)
+       return 0;               /* same rx-mode, no change */
+      break;
+    case VNET_API_ERROR_INVALID_INTERFACE:
+      return clib_error_return (0, "invalid interface");
+    default:
+      return clib_error_return (0, "unknown error");
+    }
+
+  if (dev_class->rx_mode_change_function)
+    {
+      error = dev_class->rx_mode_change_function (vnm, hw_if_index, queue_id,
+                                                 mode);
+      if (error)
+       return (error);
+    }
+
+  rv = vnet_hw_interface_set_rx_mode (vnm, hw_if_index, queue_id, mode);
+  switch (rv)
+    {
+    case 0:
+      break;
+    case VNET_API_ERROR_UNSUPPORTED:
+      return clib_error_return (0, "unsupported");
+    case VNET_API_ERROR_INVALID_INTERFACE:
+      return clib_error_return (0, "invalid interface");
+    default:
+      return clib_error_return (0, "unknown error");
+    }
+
+  return 0;
+}
+
 static clib_error_t *
 set_interface_rx_mode (vlib_main_t * vm, unformat_input_t * input,
                       vlib_cli_command_t * cmd)
@@ -1186,7 +1234,7 @@ set_interface_rx_mode (vlib_main_t * vm, unformat_input_t * input,
   u32 hw_if_index = (u32) ~ 0;
   u32 queue_id = (u32) ~ 0;
   vnet_hw_interface_rx_mode mode = VNET_HW_INTERFACE_RX_MODE_UNKNOWN;
-  int i, rv = 0;
+  int i;
 
   if (!unformat_user (input, unformat_line_input, line_input))
     return 0;
@@ -1226,26 +1274,14 @@ set_interface_rx_mode (vlib_main_t * vm, unformat_input_t * input,
   if (queue_id == ~0)
     for (i = 0; i < vec_len (hw->dq_runtime_index_by_queue); i++)
       {
-       rv = vnet_hw_interface_set_rx_mode (vnm, hw_if_index, i, mode);
-       if (rv)
-         goto error;
+       error = set_hw_interface_rx_mode (vnm, hw_if_index, i, mode);
+       if (error)
+         break;
       }
   else
-    rv = vnet_hw_interface_set_rx_mode (vnm, hw_if_index, queue_id, mode);
-
-  if (rv)
-    goto error;
-
-  return 0;
-
-error:
-  if (rv == VNET_API_ERROR_UNSUPPORTED)
-    return clib_error_return (0, "unsupported");
-
-  if (rv == VNET_API_ERROR_INVALID_INTERFACE)
-    return clib_error_return (0, "invalid interfaace");
+    error = set_hw_interface_rx_mode (vnm, hw_if_index, queue_id, mode);
 
-  return clib_error_return (0, "unknown error");
+  return (error);
 }
 
 /*?