aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Rossetto <aaron.rossetto@ni.com>2020-09-03 08:34:18 -0500
committerAaron Rossetto <aaron.rossetto@ni.com>2020-09-03 15:01:12 -0500
commiteada49e4d5a341e0af56c39585a90f63380fb5f8 (patch)
tree10730e51546cfa0a29d69c64573fb13edc347c36
parent61e10fc6b689df44f0a527861ca23801947f7e62 (diff)
downloaduhd-eada49e4d5a341e0af56c39585a90f63380fb5f8.tar.gz
uhd-eada49e4d5a341e0af56c39585a90f63380fb5f8.tar.bz2
uhd-eada49e4d5a341e0af56c39585a90f63380fb5f8.zip
dpdk: Improve link status detection
This change improves the DPDK link status detection algorithm in the following ways: - The status of the links are checked at an interval of 250 ms. If all links report as being up, the driver proceeds. - If any of the DPDK links has not reported as being up by the end of the link status detection timeout (1000 ms by default), the algorithm throws a runtime error rather than proceeds with one or more down links. - Users may override the default link status detection timeout by passing dpdk_link_timeout=N, where N is the desired timeout in milliseconds, either via device arguments or in the UHD configuration file.
-rw-r--r--host/lib/include/uhdlib/transport/dpdk/common.hpp1
-rw-r--r--host/lib/transport/uhd-dpdk/dpdk_common.cpp53
2 files changed, 38 insertions, 16 deletions
diff --git a/host/lib/include/uhdlib/transport/dpdk/common.hpp b/host/lib/include/uhdlib/transport/dpdk/common.hpp
index 280b7da64..c153c7107 100644
--- a/host/lib/include/uhdlib/transport/dpdk/common.hpp
+++ b/host/lib/include/uhdlib/transport/dpdk/common.hpp
@@ -387,6 +387,7 @@ private:
size_t _mtu;
int _num_mbufs;
int _mbuf_cache_size;
+ int _link_init_timeout;
std::mutex _init_mutex;
std::atomic<bool> _init_done;
uhd::dict<uint32_t, port_id_t> _routes;
diff --git a/host/lib/transport/uhd-dpdk/dpdk_common.cpp b/host/lib/transport/uhd-dpdk/dpdk_common.cpp
index 1ce9279ae..78b29513a 100644
--- a/host/lib/transport/uhd-dpdk/dpdk_common.cpp
+++ b/host/lib/transport/uhd-dpdk/dpdk_common.cpp
@@ -18,12 +18,14 @@
namespace uhd { namespace transport { namespace dpdk {
namespace {
-constexpr uint64_t USEC = 1000000;
-constexpr size_t DEFAULT_FRAME_SIZE = 8000;
-constexpr int DEFAULT_NUM_MBUFS = 1024;
-constexpr int DEFAULT_MBUF_CACHE_SIZE = 315;
-constexpr size_t DPDK_HEADERS_SIZE = 14 + 20 + 8; // Ethernet + IPv4 + UDP
-constexpr uint16_t DPDK_DEFAULT_RING_SIZE = 512;
+constexpr uint64_t USEC = 1000000;
+constexpr size_t DEFAULT_FRAME_SIZE = 8000;
+constexpr int DEFAULT_NUM_MBUFS = 1024;
+constexpr int DEFAULT_MBUF_CACHE_SIZE = 315;
+constexpr size_t DPDK_HEADERS_SIZE = 14 + 20 + 8; // Ethernet + IPv4 + UDP
+constexpr uint16_t DPDK_DEFAULT_RING_SIZE = 512;
+constexpr int DEFAULT_DPDK_LINK_INIT_TIMEOUT = 1000;
+constexpr int LINK_STATUS_INTERVAL = 250;
inline char* eal_add_opt(
std::vector<const char*>& argv, size_t n, char* dst, const char* opt, const char* arg)
@@ -123,6 +125,7 @@ dpdk_port::dpdk_port(port_id_t port,
port_conf.rxmode.offloads = rx_offloads | DEV_RX_OFFLOAD_JUMBO_FRAME;
port_conf.rxmode.max_rx_pkt_len = _mtu;
port_conf.txmode.offloads = tx_offloads;
+ port_conf.intr_conf.lsc = 1;
retval = rte_eth_dev_configure(_port, _num_queues, _num_queues, &port_conf);
if (retval != 0) {
@@ -403,6 +406,9 @@ void dpdk_ctx::init(const device_addr_t& user_args)
"mtu: " << _mtu << " num_mbufs: " << _num_mbufs
<< " mbuf_cache_size: " << _mbuf_cache_size);
+ _link_init_timeout =
+ dpdk_args.cast<int>("dpdk_link_timeout", DEFAULT_DPDK_LINK_INIT_TIMEOUT);
+
/* Get device info for all the NIC ports */
int num_dpdk_ports = rte_eth_dev_count_avail();
if (num_dpdk_ports == 0) {
@@ -480,16 +486,31 @@ void dpdk_ctx::init(const device_addr_t& user_args)
}
UHD_LOG_TRACE("DPDK", "Waiting for links to come up...");
- rte_delay_ms(1000);
- for (auto& port : _ports) {
- struct rte_eth_link link;
- auto portid = port.second->get_port_id();
- rte_eth_link_get(portid, &link);
- unsigned int link_status = link.link_status;
- unsigned int link_speed = link.link_speed;
- UHD_LOGGER_TRACE("DPDK") << boost::format("Port %u UP: %d, %u Mbps") % portid
- % link_status % link_speed;
- }
+ do {
+ bool all_ports_up = true;
+ for (auto& port : _ports) {
+ struct rte_eth_link link;
+ auto portid = port.second->get_port_id();
+ rte_eth_link_get(portid, &link);
+ unsigned int link_status = link.link_status;
+ unsigned int link_speed = link.link_speed;
+ UHD_LOGGER_TRACE("DPDK") << boost::format("Port %u UP: %d, %u Mbps")
+ % portid % link_status % link_speed;
+ all_ports_up &= (link.link_status == 1);
+ }
+
+ if (all_ports_up) {
+ break;
+ }
+
+ rte_delay_ms(LINK_STATUS_INTERVAL);
+ _link_init_timeout -= LINK_STATUS_INTERVAL;
+ if (_link_init_timeout <= 0 && not all_ports_up) {
+ UHD_LOG_ERROR("DPDK", "All DPDK links did not report as up!")
+ throw uhd::runtime_error("DPDK: All DPDK links did not report as up!");
+ }
+ } while (true);
+
UHD_LOG_TRACE("DPDK", "Init done -- spawning IO services");
_init_done = true;