diff options
author | Aaron Rossetto <aaron.rossetto@ni.com> | 2020-09-03 08:34:18 -0500 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2020-09-03 15:01:12 -0500 |
commit | eada49e4d5a341e0af56c39585a90f63380fb5f8 (patch) | |
tree | 10730e51546cfa0a29d69c64573fb13edc347c36 | |
parent | 61e10fc6b689df44f0a527861ca23801947f7e62 (diff) | |
download | uhd-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.hpp | 1 | ||||
-rw-r--r-- | host/lib/transport/uhd-dpdk/dpdk_common.cpp | 53 |
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; |