net/enic: add devarg to specify ingress VLAN rewrite mode
authorHyong Youb Kim <hyonkim@cisco.com>
Fri, 29 Jun 2018 09:29:35 +0000 (02:29 -0700)
committerFerruh Yigit <ferruh.yigit@intel.com>
Mon, 2 Jul 2018 23:54:15 +0000 (01:54 +0200)
Add a new devarg "ig-vlan-rewrite" to allow the user to set
non-default rewrite mode. The UCS VIC may add/remove/modify the VLAN
header of an ingress packet depending on the ingress VLAN rewrite
mode.

By default, the driver sets the pass-through mode, which tells the NIC
"do not touch VLAN header and preserve it as is". This mode is usually
sufficient, but can complicate deployments for certain environments.
For example, OVS-DPDK in UCS blade environments may want to use "untag
default VLAN mode", which removes the VLAN header from an ingress
packet if it matches vNIC's default VLAN.

Signed-off-by: Hyong Youb Kim <hyonkim@cisco.com>
Reviewed-by: John Daley <johndale@cisco.com>
doc/guides/nics/enic.rst
drivers/net/enic/enic.h
drivers/net/enic/enic_ethdev.c
drivers/net/enic/enic_main.c

index d650ba0..7764c86 100644 (file)
@@ -351,9 +351,10 @@ Limitations
   In test setups where an Ethernet port of a Cisco adapter in TRUNK mode is
   connected point-to-point to another adapter port or connected though a router
   instead of a switch, all ingress packets will be VLAN tagged. Programs such
-  as l3fwd which do not account for VLAN tags in packets will misbehave. The
-  solution is to enable VLAN stripping on ingress. The following code fragment is
-  an example of how to accomplish this:
+  as l3fwd may not account for VLAN tags in packets and may misbehave. One
+  solution is to enable VLAN stripping on ingress so the VLAN tag is removed
+  from the packet and put into the mbuf->vlan_tci field. Here is an example
+  of how to accomplish this:
 
 .. code-block:: console
 
@@ -361,6 +362,14 @@ Limitations
      vlan_offload |= ETH_VLAN_STRIP_OFFLOAD;
      rte_eth_dev_set_vlan_offload(port, vlan_offload);
 
+Another alternative is modify the adapter's ingress VLAN rewrite mode so that
+packets with the default VLAN tag are stripped by the adapter and presented to
+DPDK as untagged packets. In this case mbuf->vlan_tci and the PKT_RX_VLAN and
+PKT_RX_VLAN_STRIPPED mbuf flags would not be set. This mode is enabled with the
+``devargs`` parameter ``ig-vlan-rewrite=1``. For example::
+
+    -w 12:00.0,ig-vlan-rewrite=1
+
 - Limited flow director support on 1200 series and 1300 series Cisco VIC
   adapters with old firmware. Please see :ref:`enic-flow-director`.
 
index ea0a688..f1895fe 100644 (file)
@@ -125,6 +125,7 @@ struct enic {
        bool disable_overlay; /* devargs disable_overlay=1 */
        bool nic_cfg_chk;     /* NIC_CFG_CHK available */
        bool udp_rss_weak;    /* Bodega style UDP RSS */
+       uint8_t ig_vlan_rewrite_mode; /* devargs ig-vlan-rewrite */
 
        unsigned int flags;
        unsigned int priv_flags;
index 697dd65..111bdc8 100644 (file)
@@ -41,6 +41,7 @@ static const struct rte_pci_id pci_id_enic_map[] = {
 };
 
 #define ENIC_DEVARG_DISABLE_OVERLAY "disable-overlay"
+#define ENIC_DEVARG_IG_VLAN_REWRITE "ig-vlan-rewrite"
 
 RTE_INIT(enicpmd_init_log);
 static void
@@ -858,23 +859,61 @@ static int enic_parse_disable_overlay(__rte_unused const char *key,
        return 0;
 }
 
+static int enic_parse_ig_vlan_rewrite(__rte_unused const char *key,
+                                     const char *value,
+                                     void *opaque)
+{
+       struct enic *enic;
+
+       enic = (struct enic *)opaque;
+       if (strcmp(value, "trunk") == 0) {
+               /* Trunk mode: always tag */
+               enic->ig_vlan_rewrite_mode = IG_VLAN_REWRITE_MODE_DEFAULT_TRUNK;
+       } else if (strcmp(value, "untag") == 0) {
+               /* Untag default VLAN mode: untag if VLAN = default VLAN */
+               enic->ig_vlan_rewrite_mode =
+                       IG_VLAN_REWRITE_MODE_UNTAG_DEFAULT_VLAN;
+       } else if (strcmp(value, "priority") == 0) {
+               /*
+                * Priority-tag default VLAN mode: priority tag (VLAN header
+                * with ID=0) if VLAN = default
+                */
+               enic->ig_vlan_rewrite_mode =
+                       IG_VLAN_REWRITE_MODE_PRIORITY_TAG_DEFAULT_VLAN;
+       } else if (strcmp(value, "pass") == 0) {
+               /* Pass through mode: do not touch tags */
+               enic->ig_vlan_rewrite_mode = IG_VLAN_REWRITE_MODE_PASS_THRU;
+       } else {
+               dev_err(enic, "Invalid value for " ENIC_DEVARG_IG_VLAN_REWRITE
+                       ": expected=trunk|untag|priority|pass given=%s\n",
+                       value);
+               return -EINVAL;
+       }
+       return 0;
+}
+
 static int enic_check_devargs(struct rte_eth_dev *dev)
 {
        static const char *const valid_keys[] = {
-               ENIC_DEVARG_DISABLE_OVERLAY, NULL};
+               ENIC_DEVARG_DISABLE_OVERLAY,
+               ENIC_DEVARG_IG_VLAN_REWRITE,
+               NULL};
        struct enic *enic = pmd_priv(dev);
        struct rte_kvargs *kvlist;
 
        ENICPMD_FUNC_TRACE();
 
        enic->disable_overlay = false;
+       enic->ig_vlan_rewrite_mode = IG_VLAN_REWRITE_MODE_PASS_THRU;
        if (!dev->device->devargs)
                return 0;
        kvlist = rte_kvargs_parse(dev->device->devargs->args, valid_keys);
        if (!kvlist)
                return -EINVAL;
        if (rte_kvargs_process(kvlist, ENIC_DEVARG_DISABLE_OVERLAY,
-                              enic_parse_disable_overlay, enic) < 0) {
+                              enic_parse_disable_overlay, enic) < 0 ||
+           rte_kvargs_process(kvlist, ENIC_DEVARG_IG_VLAN_REWRITE,
+                              enic_parse_ig_vlan_rewrite, enic) < 0) {
                rte_kvargs_free(kvlist);
                return -EINVAL;
        }
@@ -939,4 +978,5 @@ RTE_PMD_REGISTER_PCI(net_enic, rte_enic_pmd);
 RTE_PMD_REGISTER_PCI_TABLE(net_enic, pci_id_enic_map);
 RTE_PMD_REGISTER_KMOD_DEP(net_enic, "* igb_uio | uio_pci_generic | vfio-pci");
 RTE_PMD_REGISTER_PARAM_STRING(net_enic,
-                             ENIC_DEVARG_DISABLE_OVERLAY "=<0|1> ");
+       ENIC_DEVARG_DISABLE_OVERLAY "=0|1 "
+       ENIC_DEVARG_IG_VLAN_REWRITE "=trunk|untag|priority|pass");
index 2cd8516..24de38d 100644 (file)
@@ -1637,8 +1637,10 @@ int enic_probe(struct enic *enic)
        }
 
        /* Set ingress vlan rewrite mode before vnic initialization */
+       dev_debug(enic, "Set ig_vlan_rewrite_mode=%u\n",
+                 enic->ig_vlan_rewrite_mode);
        err = vnic_dev_set_ig_vlan_rewrite_mode(enic->vdev,
-               IG_VLAN_REWRITE_MODE_PASS_THRU);
+               enic->ig_vlan_rewrite_mode);
        if (err) {
                dev_err(enic,
                        "Failed to set ingress vlan rewrite mode, aborting.\n");