avf: add avf flow framework
[vpp.git] / src / plugins / avf / device.c
index c6bf2df..def8a79 100644 (file)
 #include <vlib/unix/unix.h>
 #include <vlib/pci/pci.h>
 #include <vnet/ethernet/ethernet.h>
+#include <vnet/interface/rx_queue_funcs.h>
 
 #include <avf/avf.h>
 
 #define AVF_MBOX_LEN 64
-#define AVF_MBOX_BUF_SZ 512
+#define AVF_MBOX_BUF_SZ 4096
 #define AVF_RXQ_SZ 512
 #define AVF_TXQ_SZ 512
 #define AVF_ITR_INT 250
@@ -484,7 +485,7 @@ retry:
       goto done;
     }
 
-  if (d->flags & AVF_AQ_F_BUF)
+  if (out_len && d->flags & AVF_AQ_F_BUF)
     {
       void *buf = ad->arq_bufs + ad->arq_next_slot * AVF_MBOX_BUF_SZ;
       clib_memcpy_fast (out, buf, out_len);
@@ -555,10 +556,11 @@ avf_op_get_vf_resources (vlib_main_t * vm, avf_device_t * ad,
                         virtchnl_vf_resource_t * res)
 {
   clib_error_t *err = 0;
-  u32 bitmap = (VIRTCHNL_VF_OFFLOAD_L2 | VIRTCHNL_VF_OFFLOAD_RSS_PF |
-               VIRTCHNL_VF_OFFLOAD_WB_ON_ITR | VIRTCHNL_VF_OFFLOAD_VLAN |
-               VIRTCHNL_VF_OFFLOAD_RX_POLLING |
-               VIRTCHNL_VF_CAP_ADV_LINK_SPEED);
+  u32 bitmap =
+    (VIRTCHNL_VF_OFFLOAD_L2 | VIRTCHNL_VF_OFFLOAD_RSS_PF |
+     VIRTCHNL_VF_OFFLOAD_WB_ON_ITR | VIRTCHNL_VF_OFFLOAD_VLAN |
+     VIRTCHNL_VF_OFFLOAD_RX_POLLING | VIRTCHNL_VF_CAP_ADV_LINK_SPEED |
+     VIRTCHNL_VF_OFFLOAD_FDIR_PF | VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF);
 
   avf_log_debug (ad, "get_vf_reqources: bitmap 0x%x", bitmap);
   err = avf_send_to_pf (vm, ad, VIRTCHNL_OP_GET_VF_RESOURCES, &bitmap,
@@ -1175,6 +1177,20 @@ error:
   vlib_log_err (avf_log.class, "%U", format_clib_error, ad->error);
 }
 
+clib_error_t *
+avf_op_program_flow (vlib_main_t *vm, avf_device_t *ad, int is_create,
+                    u8 *rule, u32 rule_len, u8 *program_status,
+                    u32 status_len)
+{
+  avf_log_debug (ad, "avf_op_program_flow: vsi_id %u is_create %u", ad->vsi_id,
+                is_create);
+
+  return avf_send_to_pf (vm, ad,
+                        is_create ? VIRTCHNL_OP_ADD_FDIR_FILTER :
+                                    VIRTCHNL_OP_DEL_FDIR_FILTER,
+                        rule, rule_len, program_status, status_len);
+}
+
 static void
 avf_process_handle_request (vlib_main_t * vm, avf_process_req_t * req)
 {
@@ -1185,6 +1201,10 @@ avf_process_handle_request (vlib_main_t * vm, avf_process_req_t * req)
                                          req->is_add);
   else if (req->type == AVF_PROCESS_REQ_CONFIG_PROMISC_MDDE)
     req->error = avf_op_config_promisc_mode (vm, ad, req->is_enable);
+  else if (req->type == AVF_PROCESS_REQ_PROGRAM_FLOW)
+    req->error =
+      avf_op_program_flow (vm, ad, req->is_add, req->rule, req->rule_len,
+                          req->program_status, req->status_len);
   else
     clib_panic ("BUG: unknown avf proceess request type");
 
@@ -1307,10 +1327,10 @@ avf_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
        * during suspend */
       vec_reset_length (dev_pointers);
       /* *INDENT-OFF* */
-      pool_foreach_index (i, am->devices,
+      pool_foreach_index (i, am->devices)
         {
          vec_add1 (dev_pointers, avf_get_device (i));
-       });
+       }
 
       vec_foreach_index (i, dev_pointers)
         {
@@ -1373,6 +1393,7 @@ avf_irq_n_handler (vlib_main_t * vm, vlib_pci_dev_handle_t h, u16 line)
   vnet_main_t *vnm = vnet_get_main ();
   uword pd = vlib_pci_get_private_data (vm, h);
   avf_device_t *ad = avf_get_device (pd);
+  avf_rxq_t *rxq = vec_elt_at_index (ad->rxqs, line - 1);
 
   if (ad->flags & AVF_DEVICE_F_ELOG)
     {
@@ -1396,8 +1417,8 @@ avf_irq_n_handler (vlib_main_t * vm, vlib_pci_dev_handle_t h, u16 line)
 
   line--;
 
-  if (ad->flags & AVF_DEVICE_F_RX_INT && ad->rxqs[line].int_mode)
-    vnet_device_input_set_interrupt_pending (vnm, ad->hw_if_index, line);
+  if (ad->flags & AVF_DEVICE_F_RX_INT && rxq->int_mode)
+    vnet_hw_if_rx_queue_set_int_pending (vnm, rxq->queue_index);
   avf_irq_n_set_state (ad, line, AVF_IRQ_STATE_ENABLED);
 }
 
@@ -1415,7 +1436,6 @@ avf_delete_if (vlib_main_t * vm, avf_device_t * ad, int with_barrier)
       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);
@@ -1519,7 +1539,7 @@ avf_create_if (vlib_main_t * vm, avf_create_if_args_t * args)
     return;
 
   /* *INDENT-OFF* */
-  pool_foreach (adp, am->devices, ({
+  pool_foreach (adp, am->devices)  {
        if ((*adp)->pci_addr.as_u32 == args->addr.as_u32)
       {
        args->rv = VNET_API_ERROR_ADDRESS_IN_USE;
@@ -1528,7 +1548,7 @@ avf_create_if (vlib_main_t * vm, avf_create_if_args_t * args)
                             &args->addr, "pci address in use");
        return;
       }
-  }));
+  }
   /* *INDENT-ON* */
 
   pool_get (am->devices, adp);
@@ -1648,10 +1668,9 @@ avf_create_if (vlib_main_t * vm, avf_create_if_args_t * args)
   /* Indicate ability to support L3 DMAC filtering and
    * initialize interface to L3 non-promisc mode */
   vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, ad->hw_if_index);
-  hi->flags |=
-    VNET_HW_INTERFACE_FLAG_SUPPORTS_MAC_FILTER |
-    VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD |
-    VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO;
+  hi->caps |= VNET_HW_INTERFACE_CAP_SUPPORTS_MAC_FILTER |
+             VNET_HW_INTERFACE_CAP_SUPPORTS_L4_TX_CKSUM |
+             VNET_HW_INTERFACE_CAP_SUPPORTS_TCP_GSO;
   ethernet_set_flags (vnm, ad->hw_if_index,
                      ETHERNET_INTERFACE_FLAG_DEFAULT_L3);
 
@@ -1659,12 +1678,23 @@ avf_create_if (vlib_main_t * vm, avf_create_if_args_t * args)
   args->sw_if_index = ad->sw_if_index = sw->sw_if_index;
 
   vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, ad->hw_if_index);
-  hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_INT_MODE;
-  vnet_hw_interface_set_input_node (vnm, ad->hw_if_index,
-                                   avf_input_node.index);
+  hw->caps |= VNET_HW_INTERFACE_CAP_SUPPORTS_INT_MODE;
+  vnet_hw_if_set_input_node (vnm, ad->hw_if_index, avf_input_node.index);
 
   for (i = 0; i < ad->n_rx_queues; i++)
-    vnet_hw_interface_assign_rx_thread (vnm, ad->hw_if_index, i, ~0);
+    {
+      u32 qi, fi;
+      qi = vnet_hw_if_register_rx_queue (vnm, ad->hw_if_index, i,
+                                        VNET_HW_IF_RXQ_THREAD_ANY);
+
+      if (ad->flags & AVF_DEVICE_F_RX_INT)
+       {
+         fi = vlib_pci_get_msix_file_index (vm, ad->pci_dev_handle, i + 1);
+         vnet_hw_if_set_rx_queue_file_index (vnm, qi, fi);
+       }
+      ad->rxqs[i].queue_index = qi;
+    }
+  vnet_hw_if_update_runtime_data (vnm, ad->hw_if_index);
 
   if (pool_elts (am->devices) == 1)
     vlib_process_signal_event (vm, avf_process_node.index,
@@ -1782,9 +1812,26 @@ avf_clear_hw_interface_counters (u32 instance)
                    &ad->eth_stats, sizeof (ad->eth_stats));
 }
 
-/* *INDENT-OFF* */
-VNET_DEVICE_CLASS (avf_device_class,) =
+clib_error_t *
+avf_program_flow (u32 dev_instance, int is_add, u8 *rule, u32 rule_len,
+                 u8 *program_status, u32 status_len)
 {
+  vlib_main_t *vm = vlib_get_main ();
+  avf_process_req_t req;
+
+  req.dev_instance = dev_instance;
+  req.type = AVF_PROCESS_REQ_PROGRAM_FLOW;
+  req.is_add = is_add;
+  req.rule = rule;
+  req.rule_len = rule_len;
+  req.program_status = program_status;
+  req.status_len = status_len;
+
+  return avf_process_request (vm, &req);
+}
+
+/* *INDENT-OFF* */
+VNET_DEVICE_CLASS (avf_device_class, ) = {
   .name = "Adaptive Virtual Function (AVF) interface",
   .clear_counters = avf_clear_hw_interface_counters,
   .format_device = format_avf_device,
@@ -1795,6 +1842,7 @@ VNET_DEVICE_CLASS (avf_device_class,) =
   .mac_addr_add_del_function = avf_add_del_mac_address,
   .tx_function_n_errors = AVF_TX_N_ERROR,
   .tx_function_error_strings = avf_tx_func_error_strings,
+  .flow_ops_function = avf_flow_ops_fn,
 };
 /* *INDENT-ON* */