virtio: add virtio 1.1 api flags

Type: feature

Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com>
Change-Id: I95d7fc1cc8db5199570c66535f45e867a7cae676
diff --git a/src/vat/api_format.c b/src/vat/api_format.c
index c9e0b62..bbe5a04 100644
--- a/src/vat/api_format.c
+++ b/src/vat/api_format.c
@@ -1829,6 +1829,41 @@
 }
 
 static void
+  vl_api_virtio_pci_create_v2_reply_t_handler
+  (vl_api_virtio_pci_create_v2_reply_t * mp)
+{
+  vat_main_t *vam = &vat_main;
+  i32 retval = ntohl (mp->retval);
+  if (vam->async_mode)
+    {
+      vam->async_errors += (retval < 0);
+    }
+  else
+    {
+      vam->retval = retval;
+      vam->sw_if_index = ntohl (mp->sw_if_index);
+      vam->result_ready = 1;
+    }
+}
+
+static void vl_api_virtio_pci_create_v2_reply_t_handler_json
+  (vl_api_virtio_pci_create_v2_reply_t * mp)
+{
+  vat_main_t *vam = &vat_main;
+  vat_json_node_t node;
+
+  vat_json_init_object (&node);
+  vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
+  vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
+
+  vat_json_print (vam->ofp, &node);
+  vat_json_free (&node);
+
+  vam->retval = ntohl (mp->retval);
+  vam->result_ready = 1;
+}
+
+static void
 vl_api_virtio_pci_delete_reply_t_handler (vl_api_virtio_pci_delete_reply_t *
 					  mp)
 {
@@ -5242,6 +5277,7 @@
 _(TAP_DELETE_V2_REPLY, tap_delete_v2_reply)				\
 _(SW_INTERFACE_TAP_V2_DETAILS, sw_interface_tap_v2_details)             \
 _(VIRTIO_PCI_CREATE_REPLY, virtio_pci_create_reply)			\
+_(VIRTIO_PCI_CREATE_V2_REPLY, virtio_pci_create_v2_reply)		\
 _(VIRTIO_PCI_DELETE_REPLY, virtio_pci_delete_reply)			\
 _(SW_INTERFACE_VIRTIO_PCI_DETAILS, sw_interface_virtio_pci_details)     \
 _(BOND_CREATE_REPLY, bond_create_reply)	   			        \
@@ -7563,16 +7599,15 @@
 }
 
 static int
-api_virtio_pci_create (vat_main_t * vam)
+api_virtio_pci_create_v2 (vat_main_t * vam)
 {
   unformat_input_t *i = vam->input;
-  vl_api_virtio_pci_create_t *mp;
+  vl_api_virtio_pci_create_v2_t *mp;
   u8 mac_address[6];
   u8 random_mac = 1;
-  u8 gso_enabled = 0;
-  u8 checksum_offload_enabled = 0;
   u32 pci_addr = 0;
   u64 features = (u64) ~ (0ULL);
+  u32 virtio_flags = 0;
   int ret;
 
   clib_memset (mac_address, 0, sizeof (mac_address));
@@ -7589,9 +7624,15 @@
       else if (unformat (i, "features 0x%llx", &features))
 	;
       else if (unformat (i, "gso-enabled"))
-	gso_enabled = 1;
+	virtio_flags |= VIRTIO_API_FLAG_GSO;
       else if (unformat (i, "csum-offload-enabled"))
-	checksum_offload_enabled = 1;
+	virtio_flags |= VIRTIO_API_FLAG_CSUM_OFFLOAD;
+      else if (unformat (i, "gro-coalesce"))
+	virtio_flags |= VIRTIO_API_FLAG_GRO_COALESCE;
+      else if (unformat (i, "packed"))
+	virtio_flags |= VIRTIO_API_FLAG_PACKED;
+      else if (unformat (i, "in-order"))
+	virtio_flags |= VIRTIO_API_FLAG_IN_ORDER;
       else
 	break;
     }
@@ -7603,7 +7644,7 @@
     }
 
   /* Construct the API message */
-  M (VIRTIO_PCI_CREATE, mp);
+  M (VIRTIO_PCI_CREATE_V2, mp);
 
   mp->use_random_mac = random_mac;
 
@@ -7613,8 +7654,7 @@
   mp->pci_addr.function = ((vlib_pci_addr_t) pci_addr).function;
 
   mp->features = clib_host_to_net_u64 (features);
-  mp->gso_enabled = gso_enabled;
-  mp->checksum_offload_enabled = checksum_offload_enabled;
+  mp->virtio_flags = clib_host_to_net_u32 (virtio_flags);
 
   if (random_mac == 0)
     clib_memcpy (mp->mac_address, mac_address, 6);
@@ -20667,8 +20707,8 @@
 _(tap_delete_v2,                                                        \
   "<vpp-if-name> | sw_if_index <id>")                                   \
 _(sw_interface_tap_v2_dump, "")                                         \
-_(virtio_pci_create,                                                    \
-  "pci-addr <pci-address> [use_random_mac | hw-addr <mac-addr>] [features <hex-value>] [gso-enabled | csum-offload-enabled]") \
+_(virtio_pci_create_v2,                                                    \
+  "pci-addr <pci-address> [use_random_mac | hw-addr <mac-addr>] [features <hex-value>] [gso-enabled [gro-coalesce] | csum-offload-enabled] [packed] [in-order]") \
 _(virtio_pci_delete,                                                    \
   "<vpp-if-name> | sw_if_index <id>")                                   \
 _(sw_interface_virtio_pci_dump, "")                                     \
diff --git a/src/vnet/devices/virtio/pci.h b/src/vnet/devices/virtio/pci.h
index f9a5828..47c74ab 100644
--- a/src/vnet/devices/virtio/pci.h
+++ b/src/vnet/devices/virtio/pci.h
@@ -242,6 +242,20 @@
   void (*device_debug_config_space) (vlib_main_t * vm, virtio_if_t * vif);
 } virtio_pci_func_t;
 
+#define foreach_virtio_flags  \
+  _ (GSO, 0)                  \
+  _ (CSUM_OFFLOAD, 1)         \
+  _ (GRO_COALESCE, 2)         \
+  _ (PACKED, 3)               \
+  _ (IN_ORDER, 4)
+
+typedef enum
+{
+#define _(a, b) VIRTIO_FLAG_##a = (1 << b),
+  foreach_virtio_flags
+#undef _
+} virtio_flag_t;
+
 typedef struct
 {
   u32 addr;
@@ -253,6 +267,7 @@
   u64 features;
   u8 gso_enabled;
   u8 checksum_offload_enabled;
+  u32 virtio_flags;
   clib_error_t *error;
 } virtio_pci_create_if_args_t;
 
diff --git a/src/vnet/devices/virtio/virtio.api b/src/vnet/devices/virtio/virtio.api
index 34f00fa..143d25b 100644
--- a/src/vnet/devices/virtio/virtio.api
+++ b/src/vnet/devices/virtio/virtio.api
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-option version = "2.0.0";
+option version = "3.0.0";
 
 import "vnet/interface_types.api";
 import "vnet/ethernet/ethernet_types.api";
@@ -32,6 +32,7 @@
 */
 define virtio_pci_create
 {
+  option deprecated="21.01";
   u32 client_index;
   u32 context;
   vl_api_pci_address_t pci_addr;
@@ -49,6 +50,47 @@
 */
 define virtio_pci_create_reply
 {
+  option deprecated="21.01";
+  u32 context;
+  i32 retval;
+  vl_api_interface_index_t sw_if_index;
+};
+
+enum virtio_flags {
+        VIRTIO_API_FLAG_GSO = 1, /* enable gso on the interface */
+        VIRTIO_API_FLAG_CSUM_OFFLOAD = 2, /* enable checksum offload without gso on the interface */
+        VIRTIO_API_FLAG_GRO_COALESCE = 4, /* enable packet coalescing on tx side, provided gso enabled */
+        VIRTIO_API_FLAG_PACKED = 8, /* enable packed ring support, provided it is available from backend */
+        VIRTIO_API_FLAG_IN_ORDER = 16, /* enable in order support, provided it is available from backend */
+};
+
+/** \brief Initialize a new virtio pci interface with the given parameters
+    @param client_index - opaque cookie to identify the sender
+    @param context - sender context, to match reply w/ request
+    @param pci_addr - pci address
+    @param use_random_mac - let the system generate a unique mac address
+    @param mac_address - mac addr to assign to the interface if use_random not set
+    @param virtio_flags - feature flags to enable
+    @param features - the virtio features which driver should negotiate with device
+*/
+define virtio_pci_create_v2
+{
+  u32 client_index;
+  u32 context;
+  vl_api_pci_address_t pci_addr;
+  bool use_random_mac;
+  vl_api_mac_address_t mac_address;
+  vl_api_virtio_flags_t virtio_flags;
+  u64 features;
+};
+
+/** \brief Reply for virtio pci create reply
+    @param context - returned sender context, to match reply w/ request
+    @param retval - return code
+    @param sw_if_index - software index allocated for the new virtio pci interface
+*/
+define virtio_pci_create_v2_reply
+{
   u32 context;
   i32 retval;
   vl_api_interface_index_t sw_if_index;
diff --git a/src/vnet/devices/virtio/virtio_api.c b/src/vnet/devices/virtio/virtio_api.c
index 96ed927..9a145d9 100644
--- a/src/vnet/devices/virtio/virtio_api.c
+++ b/src/vnet/devices/virtio/virtio_api.c
@@ -47,9 +47,11 @@
 
 #define foreach_virtio_pci_api_msg                        \
 _(VIRTIO_PCI_CREATE, virtio_pci_create)                   \
+_(VIRTIO_PCI_CREATE_V2, virtio_pci_create_v2)             \
 _(VIRTIO_PCI_DELETE, virtio_pci_delete)                   \
 _(SW_INTERFACE_VIRTIO_PCI_DUMP, sw_interface_virtio_pci_dump)
 
+/* It will be deprecated in 21.01 */
 static void
 vl_api_virtio_pci_create_t_handler (vl_api_virtio_pci_create_t * mp)
 {
@@ -94,6 +96,65 @@
 }
 
 static void
+vl_api_virtio_pci_create_v2_t_handler (vl_api_virtio_pci_create_v2_t * mp)
+{
+  vlib_main_t *vm = vlib_get_main ();
+  vl_api_virtio_pci_create_v2_reply_t *rmp;
+  vl_api_registration_t *reg;
+  virtio_pci_create_if_args_t _a, *ap = &_a;
+
+  clib_memset (ap, 0, sizeof (*ap));
+
+  pci_address_decode (&mp->pci_addr, (vlib_pci_addr_t *) & ap->addr);
+  if (!mp->use_random_mac)
+    {
+      clib_memcpy (ap->mac_addr, mp->mac_address, 6);
+      ap->mac_addr_set = 1;
+    }
+  ap->sw_if_index = (u32) ~ 0;
+
+  STATIC_ASSERT (((int) VIRTIO_API_FLAG_GSO == (int) VIRTIO_FLAG_GSO),
+		 "virtio gso api flag mismatch");
+  STATIC_ASSERT (((int) VIRTIO_API_FLAG_CSUM_OFFLOAD ==
+		  (int) VIRTIO_FLAG_CSUM_OFFLOAD),
+		 "virtio checksum offload api flag mismatch");
+  STATIC_ASSERT (((int) VIRTIO_API_FLAG_GRO_COALESCE ==
+		  (int) VIRTIO_FLAG_GRO_COALESCE),
+		 "virtio gro coalesce api flag mismatch");
+  STATIC_ASSERT (((int) VIRTIO_API_FLAG_PACKED == (int) VIRTIO_FLAG_PACKED),
+		 "virtio packed api flag mismatch");
+  STATIC_ASSERT (((int) VIRTIO_API_FLAG_IN_ORDER ==
+		  (int) VIRTIO_FLAG_IN_ORDER),
+		 "virtio in-order api flag mismatch");
+
+  ap->virtio_flags = clib_net_to_host_u32 (mp->virtio_flags);
+  ap->features = clib_net_to_host_u64 (mp->features);
+
+  if (ap->virtio_flags & VIRTIO_FLAG_GSO)
+    ap->gso_enabled = 1;
+  else
+    ap->gso_enabled = 0;
+  if (ap->virtio_flags & VIRTIO_FLAG_CSUM_OFFLOAD)
+    ap->checksum_offload_enabled = 1;
+  else
+    ap->checksum_offload_enabled = 0;
+
+  virtio_pci_create_if (vm, ap);
+
+  reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
+    return;;
+
+  rmp = vl_msg_api_alloc (sizeof (*rmp));
+  rmp->_vl_msg_id = htons (VL_API_VIRTIO_PCI_CREATE_V2_REPLY);
+  rmp->context = mp->context;
+  rmp->retval = htonl (ap->rv);
+  rmp->sw_if_index = htonl (ap->sw_if_index);
+
+  vl_api_send_msg (reg, (u8 *) rmp);
+}
+
+static void
 vl_api_virtio_pci_delete_t_handler (vl_api_virtio_pci_delete_t * mp)
 {
   vnet_main_t *vnm = vnet_get_main ();
diff --git a/src/vpp/api/custom_dump.c b/src/vpp/api/custom_dump.c
index 8f2975d..79e5da4 100644
--- a/src/vpp/api/custom_dump.c
+++ b/src/vpp/api/custom_dump.c
@@ -643,6 +643,35 @@
 }
 
 __clib_unused
+  static void *vl_api_virtio_pci_create_v2_t_print
+  (vl_api_virtio_pci_create_v2_t * mp, void *handle)
+{
+  u8 *s;
+  u8 null_mac[6];
+
+  clib_memset (null_mac, 0, sizeof (null_mac));
+
+  s = format (0, "SCRIPT: virtio_pci_create_v2 ");
+  s = format (s, "pci_addr %U ", format_vlib_pci_addr, (mp->pci_addr));
+  if (memcmp (mp->mac_address, null_mac, 6))
+    s = format (s, "mac-address %U ",
+		format_ethernet_address, mp->mac_address);
+  if (mp->features)
+    s = format (s, "features 0x%llx ", clib_net_to_host_u64 (mp->features));
+  if (mp->virtio_flags & VIRTIO_API_FLAG_GSO)
+    s = format (s, "gso-enabled ");
+  if (mp->virtio_flags & VIRTIO_API_FLAG_CSUM_OFFLOAD)
+    s = format (s, "checksum_offload_enabled ");
+  if ((mp->virtio_flags) & VIRTIO_API_FLAG_GRO_COALESCE)
+    s = format (s, "gro-coalesce-enabled ");
+  if ((mp->virtio_flags) & VIRTIO_API_FLAG_PACKED)
+    s = format (s, "packed ");
+  if ((mp->virtio_flags) & VIRTIO_API_FLAG_IN_ORDER)
+    s = format (s, "in-order ");
+  FINISH;
+}
+
+__clib_unused
   static void *vl_api_virtio_pci_delete_t_print
   (vl_api_virtio_pci_delete_t * mp, void *handle)
 {