It is possible to set LSC detection mode to polling or interrupt mode
for DPDK interfaces. The default is polling mode. To set interrupt mode,
option dpdk-lsc-interrupt has to be set to true.


Global settings
Service restart is necessary for the global settings to take effect.

Command to set interrupt mode for all interfaces:
ovs-vsctl set Open_vSwitch . other_config:dpdk-lsc-interrupt=true

Command to set polling mode for all interfaces:
ovs-vsctl set Open_vSwitch . other_config:dpdk-lsc-interrupt=false
or:
ovs-vsctl remove Open_vSwitch . other_config dpdk-lsc-interrupt


Interface specific settings (override global settings)
Service restart is not necessary to take effect.

Command to set interrupt mode for a specific interface:
ovs-vsctl set interface <interface_name> other_config:dpdk-lsc-interrupt=true

Command to set polling mode for a specific interface:
ovs-vsctl set interface <interface_name> other_config:dpdk-lsc-interrupt=false

Command to reset to globally defined mode for a specific interface:
ovs-vsctl remove interface <interface_name> other_config dpdk-lsc-interrupt

Signed-off-by: Robert Mulik <robert.mu...@ericsson.com>
---
 lib/dpdk.c            |  6 ++++++
 lib/netdev-dpdk.c     | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 lib/netdev-dpdk.h     |  8 +++++++
 lib/netdev-dummy.c    |  2 ++
 lib/netdev-linux.c    |  2 ++
 lib/netdev-provider.h |  3 +++
 lib/netdev-vport.c    |  2 ++
 lib/netdev.c          | 32 +++++++++++++++++++++++++++
 lib/netdev.h          |  2 ++
 vswitchd/bridge.c     | 34 +++++++++++++++++++++++++++++
 vswitchd/vswitch.xml  | 42 ++++++++++++++++++++++++++++++++++++
 11 files changed, 192 insertions(+), 1 deletion(-)

diff --git a/lib/dpdk.c b/lib/dpdk.c
index 8da6c32..09c4f9b 100644
--- a/lib/dpdk.c
+++ b/lib/dpdk.c
@@ -345,6 +345,12 @@ dpdk_init__(const struct smap *ovs_other_config)
         vhost_sock_dir = sock_dir_subcomponent;
     }

+    if (smap_get_bool(ovs_other_config, "dpdk-lsc-interrupt", false)) {
+        
netdev_dpdk_set_default_lsc_detect_mode(NETDEV_DPDK_LSC_DETECT_INTERRUPT_MODE);
+    } else {
+        
netdev_dpdk_set_default_lsc_detect_mode(NETDEV_DPDK_LSC_DETECT_POLL_MODE);
+    }
+
     argv = grow_argv(&argv, 0, 1);
     argc = 1;
     argv[0] = xstrdup(ovs_get_program_name());
diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index faff842..ac722cc 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -146,7 +146,7 @@ typedef uint8_t dpdk_port_t;
 #define VHOST_ENQ_RETRY_NUM 8
 #define IF_NAME_SZ (PATH_MAX > IFNAMSIZ ? PATH_MAX : IFNAMSIZ)

-static const struct rte_eth_conf port_conf = {
+static struct rte_eth_conf port_conf = {
     .rxmode = {
         .mq_mode = ETH_MQ_RX_RSS,
         .split_hdr_size = 0,
@@ -165,6 +165,9 @@ static const struct rte_eth_conf port_conf = {
     .txmode = {
         .mq_mode = ETH_MQ_TX_NONE,
     },
+    .intr_conf = {
+        .lsc = (uint16_t)NETDEV_DPDK_LSC_DETECT_POLL_MODE, /* LSC interrupt 
mode disabled, polling mode used. */
+    },
 };

 /*
@@ -397,6 +400,9 @@ struct netdev_dpdk {
         int requested_n_rxq;
         int requested_rxq_size;
         int requested_txq_size;
+        enum netdev_dpdk_lsc_detect_mode requested_lsc_detect_mode;
+
+        enum netdev_dpdk_lsc_detect_mode lsc_detect_mode;

         /* Number of rx/tx descriptors for physical devices */
         int rxq_size;
@@ -430,6 +436,18 @@ int netdev_dpdk_get_vid(const struct netdev_dpdk *dev);
 struct ingress_policer *
 netdev_dpdk_get_ingress_policer(const struct netdev_dpdk *dev);

+void
+netdev_dpdk_set_default_lsc_detect_mode(enum netdev_dpdk_lsc_detect_mode 
default_lsc)
+{
+    port_conf.intr_conf.lsc = (uint16_t)default_lsc;
+}
+
+enum netdev_dpdk_lsc_detect_mode
+netdev_dpdk_get_default_lsc_detect_mode(void)
+{
+    return port_conf.intr_conf.lsc;
+}
+
 static bool
 is_dpdk_class(const struct netdev_class *class)
 {
@@ -663,6 +681,8 @@ dpdk_eth_dev_queue_setup(struct netdev_dpdk *dev, int 
n_rxq, int n_txq)
     int i;
     struct rte_eth_conf conf = port_conf;

+    conf.intr_conf.lsc = dev->lsc_detect_mode;
+
     /* For some NICs (e.g. Niantic), scatter_rx mode needs to be explicitly
      * enabled. */
     if (dev->mtu > ETHER_MTU) {
@@ -868,6 +888,7 @@ common_construct(struct netdev *netdev, dpdk_port_t port_no,
     dev->flags = 0;
     dev->requested_mtu = ETHER_MTU;
     dev->max_packet_len = MTU_TO_FRAME_LEN(dev->mtu);
+    dev->requested_lsc_detect_mode = netdev_dpdk_get_default_lsc_detect_mode();
     ovsrcu_index_init(&dev->vid, -1);
     dev->vhost_reconfigured = false;
     dev->attached = false;
@@ -2005,6 +2026,38 @@ netdev_dpdk_set_mtu(struct netdev *netdev, int mtu)
 }

 static int
+netdev_dpdk_get_lsc_detect_mode(const struct netdev *netdev, uint16_t *lscp)
+{
+    struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
+
+    ovs_mutex_lock(&dev->mutex);
+    *lscp = (uint16_t)dev->lsc_detect_mode;
+    ovs_mutex_unlock(&dev->mutex);
+
+    return 0;
+}
+
+static int
+netdev_dpdk_set_lsc_detect_mode(struct netdev *netdev, uint16_t 
lsc_detect_mode)
+{
+    struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
+
+    if (lsc_detect_mode > NETDEV_DPDK_LSC_DETECT_MAX) {
+        VLOG_WARN("%s: invalid LSC value %d\n", dev->up.name, lsc_detect_mode);
+        return EINVAL;
+    }
+
+    ovs_mutex_lock(&dev->mutex);
+    if (dev->requested_lsc_detect_mode != (enum 
netdev_dpdk_lsc_detect_mode)lsc_detect_mode) {
+        dev->requested_lsc_detect_mode = (enum 
netdev_dpdk_lsc_detect_mode)lsc_detect_mode;
+        netdev_request_reconfigure(netdev);
+    }
+    ovs_mutex_unlock(&dev->mutex);
+
+    return 0;
+}
+
+static int
 netdev_dpdk_get_carrier(const struct netdev *netdev, bool *carrier);

 static int
@@ -3166,6 +3219,7 @@ netdev_dpdk_reconfigure(struct netdev *netdev)
     if (netdev->n_txq == dev->requested_n_txq
         && netdev->n_rxq == dev->requested_n_rxq
         && dev->mtu == dev->requested_mtu
+        && dev->lsc_detect_mode == dev->requested_lsc_detect_mode
         && dev->rxq_size == dev->requested_rxq_size
         && dev->txq_size == dev->requested_txq_size
         && dev->socket_id == dev->requested_socket_id) {
@@ -3181,6 +3235,8 @@ netdev_dpdk_reconfigure(struct netdev *netdev)
         goto out;
     }

+    dev->lsc_detect_mode = dev->requested_lsc_detect_mode;
+
     netdev->n_txq = dev->requested_n_txq;
     netdev->n_rxq = dev->requested_n_rxq;

@@ -3343,6 +3399,8 @@ unlock:
     netdev_dpdk_get_etheraddr,                                \
     netdev_dpdk_get_mtu,                                      \
     netdev_dpdk_set_mtu,                                      \
+    netdev_dpdk_get_lsc_detect_mode,                          \
+    netdev_dpdk_set_lsc_detect_mode,                          \
     netdev_dpdk_get_ifindex,                                  \
     GET_CARRIER,                                              \
     netdev_dpdk_get_carrier_resets,                           \
diff --git a/lib/netdev-dpdk.h b/lib/netdev-dpdk.h
index b7d02a7..28a6c98 100644
--- a/lib/netdev-dpdk.h
+++ b/lib/netdev-dpdk.h
@@ -25,8 +25,16 @@ struct dp_packet;

 #ifdef DPDK_NETDEV

+enum netdev_dpdk_lsc_detect_mode {
+    NETDEV_DPDK_LSC_DETECT_POLL_MODE,
+    NETDEV_DPDK_LSC_DETECT_INTERRUPT_MODE,
+    NETDEV_DPDK_LSC_DETECT_MAX = NETDEV_DPDK_LSC_DETECT_INTERRUPT_MODE,
+};
+
 void netdev_dpdk_register(void);
 void free_dpdk_buf(struct dp_packet *);
+void netdev_dpdk_set_default_lsc_detect_mode(enum netdev_dpdk_lsc_detect_mode 
default_lsc);
+enum netdev_dpdk_lsc_detect_mode netdev_dpdk_get_default_lsc_detect_mode(void);

 #else

diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c
index 246cdf1..31052c7 100644
--- a/lib/netdev-dummy.c
+++ b/lib/netdev-dummy.c
@@ -1378,6 +1378,8 @@ netdev_dummy_update_flags(struct netdev *netdev_,
     netdev_dummy_get_etheraddr,                                 \
     netdev_dummy_get_mtu,                                       \
     netdev_dummy_set_mtu,                                       \
+    NULL,                       /* get_lsc_detect_mode */       \
+    NULL,                       /* set_lsc_detect_mode */       \
     netdev_dummy_get_ifindex,                                   \
     NULL,                       /* get_carrier */               \
     NULL,                       /* get_carrier_resets */        \
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index e809b88..252a8f9 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -2848,6 +2848,8 @@ netdev_linux_update_flags(struct netdev *netdev_, enum 
netdev_flags off,
     netdev_linux_get_etheraddr,                                 \
     netdev_linux_get_mtu,                                       \
     netdev_linux_set_mtu,                                       \
+    NULL,                       /* get_lsc_detect_mode */       \
+    NULL,                       /* set_lsc_detect_mode */       \
     netdev_linux_get_ifindex,                                   \
     netdev_linux_get_carrier,                                   \
     netdev_linux_get_carrier_resets,                            \
diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h
index 1720deb..865c0c4 100644
--- a/lib/netdev-provider.h
+++ b/lib/netdev-provider.h
@@ -413,6 +413,9 @@ struct netdev_class {
      * null if it would always return EOPNOTSUPP. */
     int (*set_mtu)(struct netdev *netdev, int mtu);

+    int (*get_lsc_detect_mode)(const struct netdev *netdev, uint16_t *lscp);
+    int (*set_lsc_detect_mode)(struct netdev *netdev, uint16_t lsc);
+
     /* Returns the ifindex of 'netdev', if successful, as a positive number.
      * On failure, returns a negative errno value.
      *
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index 518058a..7788ce8 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -901,6 +901,8 @@ netdev_vport_get_ifindex(const struct netdev *netdev_)
     netdev_vport_get_etheraddr,                             \
     NULL,                       /* get_mtu */               \
     NULL,                       /* set_mtu */               \
+    NULL,                       /* get_lsc_detect_mode */   \
+    NULL,                       /* set_lsc_detect_mode */   \
     GET_IFINDEX,                                            \
     NULL,                       /* get_carrier */           \
     NULL,                       /* get_carrier_resets */    \
diff --git a/lib/netdev.c b/lib/netdev.c
index 2d69fe5..3ea2394 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -960,6 +960,38 @@ netdev_set_mtu(struct netdev *netdev, int mtu)
     return error;
 }

+int
+netdev_get_lsc_detect_mode(const struct netdev *netdev, uint16_t *lscp)
+{
+    const struct netdev_class *class = netdev->netdev_class;
+    int error;
+
+    error = class->get_lsc_detect_mode ? class->get_lsc_detect_mode(netdev, 
lscp) : EOPNOTSUPP;
+    if (error) {
+        *lscp = 0;
+        if (error != EOPNOTSUPP) {
+            VLOG_DBG_RL(&rl, "failed to retrieve LSC for network device %s: "
+                         "%s", netdev_get_name(netdev), ovs_strerror(error));
+        }
+    }
+    return error;
+}
+
+int
+netdev_set_lsc_detect_mode(struct netdev *netdev, uint16_t lsc)
+{
+    const struct netdev_class *class = netdev->netdev_class;
+    int error;
+
+    error = class->set_lsc_detect_mode ? class->set_lsc_detect_mode(netdev, 
lsc) : EOPNOTSUPP;
+    if (error && error != EOPNOTSUPP) {
+        VLOG_DBG_RL(&rl, "failed to set LSC for network device %s: %s",
+                     netdev_get_name(netdev), ovs_strerror(error));
+    }
+
+    return error;
+}
+
 /* If 'user_config' is true, the user wants to control 'netdev''s MTU and we
  * should not override it.  If 'user_config' is false, we may adjust
  * 'netdev''s MTU (e.g., if 'netdev' is internal). */
diff --git a/lib/netdev.h b/lib/netdev.h
index 3a545fe..465285a 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
@@ -162,6 +162,8 @@ const char *netdev_get_type(const struct netdev *);
 const char *netdev_get_type_from_name(const char *);
 int netdev_get_mtu(const struct netdev *, int *mtup);
 int netdev_set_mtu(struct netdev *, int mtu);
+int netdev_get_lsc_detect_mode(const struct netdev *, uint16_t *lscp);
+int netdev_set_lsc_detect_mode(struct netdev *, uint16_t lsc);
 void netdev_mtu_user_config(struct netdev *, bool);
 bool netdev_mtu_is_user_config(struct netdev *);
 int netdev_get_ifindex(const struct netdev *);
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index 630c6fa..2249e75 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -68,6 +68,9 @@
 #include "lib/vswitch-idl.h"
 #include "xenserver.h"
 #include "vlan-bitmap.h"
+#ifdef DPDK_NETDEV
+#include "./lib/netdev-provider.h"
+#endif

 VLOG_DEFINE_THIS_MODULE(bridge);

@@ -776,6 +779,30 @@ iface_set_netdev_mtu(const struct ovsrec_interface 
*iface_cfg,
     return 0;
 }

+#ifdef DPDK_NETDEV
+static void
+iface_set_netdev_lsc_detect_mode(struct netdev *netdev,
+                                 const struct ovsrec_interface *cfg)
+{
+    if(netdev && netdev_get_class(netdev) && 
netdev_get_class(netdev)->set_lsc_detect_mode)
+    {
+        struct smap_node *node = smap_get_node(&cfg->other_config, 
"dpdk-lsc-interrupt");
+        uint16_t lsc;
+
+        if(node) {
+            /* Set local LSC interrupt config for interface. */
+            lsc = smap_get_bool(&cfg->other_config, "dpdk-lsc-interrupt", 
false);
+        } else {
+            /* Set global LSC interrupt config if port specific is not 
defined. */
+            lsc = netdev_dpdk_get_default_lsc_detect_mode();
+        }
+        /* Update port specific configuration, and reconfigure device.
+           Can be applied only for physical interfaces. */
+        netdev_set_lsc_detect_mode(netdev, lsc);
+    }
+}
+#endif
+
 static void
 bridge_delete_or_reconfigure_ports(struct bridge *br)
 {
@@ -832,6 +859,10 @@ bridge_delete_or_reconfigure_ports(struct bridge *br)

         iface_set_netdev_mtu(iface->cfg, iface->netdev);

+#ifdef DPDK_NETDEV
+        iface_set_netdev_lsc_detect_mode(iface->netdev, iface->cfg);
+#endif
+
         /* If the requested OpenFlow port for 'iface' changed, and it's not
          * already the correct port, then we might want to temporarily delete
          * this interface, so we can add it back again with the new OpenFlow
@@ -1794,6 +1825,9 @@ iface_do_create(const struct bridge *br,
     }

     iface_set_netdev_mtu(iface_cfg, netdev);
+#ifdef DPDK_NETDEV
+    iface_set_netdev_lsc_detect_mode(netdev, iface_cfg);
+#endif

     *ofp_portp = iface_pick_ofport(iface_cfg);
     error = ofproto_port_add(br->ofproto, netdev, ofp_portp);
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index c145e1a..87c0b52 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -320,6 +320,29 @@
         </p>
       </column>

+      <column name="other_config" key="dpdk-lsc-interrupt"
+              type='{"type": "boolean"}'>
+        <p>
+          Set this value to <code>true</code> to set interrupt mode for Link
+          State Change (LSC) detection instead of poll mode for DPDK 
interfaces.
+        </p>
+        <p>
+          The default value is <code>false</code>. Changing this value requires
+          restarting the daemon
+        </p>
+        <p>
+          If this value is <code>false</code> at startup, poll mode is used for
+          all netdev dpdk interfaces.
+        </p>
+        <p>
+          This value can be overridden for a single interface in the 
other_config
+          section of that interface.
+        </p>
+        <p>
+          This parameter has any effect only on netdev dpdk interfaces.
+        </p>
+      </column>
+
       <column name="other_config" key="dpdk-extra"
               type='{"type": "string"}'>
         <p>
@@ -3512,6 +3535,25 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch 
options:peer=p1 \
       </column>
     </group>

+    <group title="Link State Change detection mode">
+      <column name="other_config" key="dpdk-lsc-interrupt"
+              type='{"type": "boolean"}'>
+        <p>
+          Set this value to <code>true</code> to set interrupt mode for Link
+          State Change (LSC) detection instead of poll mode for the DPDK 
interface.
+        </p>
+        <p>
+          If this value is not set, the value is taken from the global 
settings.
+        </p>
+        <p>
+          If this value is set, the global LSC interrupt settings are 
overridden.
+        </p>
+        <p>
+          This parameter has any effect only on netdev dpdk interfaces.
+        </p>
+      </column>
+    </group>
+
     <group title="Common Columns">
       The overall purpose of these columns is described under <code>Common
       Columns</code> at the beginning of this document.
--
1.9.1

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to