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