Skip to content

Commit 98b85c1

Browse files
committed
Added per-queue timeout value
Signed-off-by: Cliff Burdick <cburdick@nvidia.com>
1 parent 6f8b3dd commit 98b85c1

File tree

4 files changed

+65
-4
lines changed

4 files changed

+65
-4
lines changed

operators/advanced_network/adv_network_common.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,11 @@ struct YAML::convert<holoscan::ops::AdvNetConfigYaml> {
586586
HOLOSCAN_LOG_ERROR("Failed to parse RxQueueConfig");
587587
return false;
588588
}
589+
590+
try {
591+
q.timeout_us_ = q_item["timeout_us"].as<uint64_t>();
592+
} catch (const std::exception& e) { q.timeout_us_ = 0; }
593+
589594
rx_cfg.queues_.emplace_back(std::move(q));
590595
}
591596

operators/advanced_network/adv_network_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ struct MemoryRegion {
331331

332332
struct RxQueueConfig {
333333
CommonQueueConfig common_;
334+
uint64_t timeout_us_;
334335
std::string output_port_;
335336
};
336337

operators/advanced_network/managers/dpdk/adv_network_dpdk_mgr.cpp

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ struct RxWorkerParams {
4747
int port;
4848
int queue;
4949
int num_segs;
50+
uint64_t timeout_us;
5051
uint32_t batch_size;
5152
struct rte_ring* ring;
5253
struct rte_mempool* flowid_pool;
@@ -1199,6 +1200,7 @@ void DpdkMgr::run() {
11991200
params->flowid_pool = rx_flow_id_buffer;
12001201
params->meta_pool = rx_meta;
12011202
params->batch_size = q.common_.batch_size_;
1203+
params->timeout_us = q.timeout_us_;
12021204
rte_eal_remote_launch(
12031205
rx_worker, (void*)params, strtol(q.common_.cpu_core_.c_str(), NULL, 10));
12041206
}
@@ -1237,6 +1239,30 @@ void DpdkMgr::flush_packets(int port) {
12371239
while (rte_eth_rx_burst(port, 0, &rx_mbuf, 1) != 0) { rte_pktmbuf_free(rx_mbuf); }
12381240
}
12391241

1242+
inline uint64_t DpdkMgr::get_tsc_hz() {
1243+
#define CYC_PER_1MHZ 1E6
1244+
/* Use the generic counter ticks to calculate the PMU
1245+
* cycle frequency.
1246+
*/
1247+
uint64_t ticks;
1248+
uint64_t start_ticks, cur_ticks;
1249+
uint64_t start_pmu_cycles, end_pmu_cycles;
1250+
1251+
/* Number of ticks for 1/10 second */
1252+
ticks = __rte_arm64_cntfrq() / 10;
1253+
1254+
start_ticks = __rte_arm64_cntvct_precise();
1255+
start_pmu_cycles = rte_rdtsc_precise();
1256+
do {
1257+
cur_ticks = __rte_arm64_cntvct();
1258+
} while ((cur_ticks - start_ticks) < ticks);
1259+
end_pmu_cycles = rte_rdtsc_precise();
1260+
1261+
/* Adjust the cycles to next 1Mhz */
1262+
return RTE_ALIGN_MUL_CEIL(end_pmu_cycles - start_pmu_cycles,
1263+
CYC_PER_1MHZ) * 10;
1264+
}
1265+
12401266
////////////////////////////////////////////////////////////////////////////////
12411267
///
12421268
/// \brief
@@ -1246,9 +1272,11 @@ int DpdkMgr::rx_core_worker(void* arg) {
12461272
RxWorkerParams* tparams = (RxWorkerParams*)arg;
12471273
struct rte_mbuf* rx_mbufs[DEFAULT_NUM_RX_BURST];
12481274
int ret = 0;
1249-
uint64_t freq = rte_get_tsc_hz();
1250-
uint64_t timeout_ticks = freq * 0.02; // expect all packets within 20ms
12511275

1276+
// In the future we may want to periodically update this if the CPU clock drifts
1277+
uint64_t freq = rte_get_tsc_hz();
1278+
uint64_t timeout_cycles = freq * (tparams->timeout_us/1e6);
1279+
uint64_t last_cycles = rte_get_tsc_cycles();
12521280
uint64_t total_pkts = 0;
12531281

12541282
flush_packets(tparams->port);
@@ -1336,7 +1364,21 @@ int DpdkMgr::rx_core_worker(void* arg) {
13361364
reinterpret_cast<rte_mbuf**>(&mbuf_arr[0]),
13371365
DEFAULT_NUM_RX_BURST);
13381366

1339-
if (nb_rx == 0) { continue; }
1367+
if (nb_rx == 0) {
1368+
if (burst->hdr.hdr.num_pkts > 0 && timeout_cycles > 0) {
1369+
const auto cur_cycles = rte_get_tsc_cycles();
1370+
1371+
// We hit our timeout. Send the partial batch immediately
1372+
if ((cur_cycles - last_cycles) > timeout_cycles) {
1373+
cur_pkt_in_batch = 0;
1374+
rte_ring_enqueue(tparams->ring, reinterpret_cast<void*>(burst));
1375+
last_cycles = cur_cycles;
1376+
break;
1377+
}
1378+
}
1379+
1380+
continue;
1381+
}
13401382

13411383
to_copy = std::min(nb_rx, (int)(tparams->batch_size - burst->hdr.hdr.num_pkts));
13421384
memcpy(&burst->pkts[0][burst->hdr.hdr.num_pkts], &mbuf_arr, sizeof(rte_mbuf*) * to_copy);
@@ -1366,10 +1408,22 @@ int DpdkMgr::rx_core_worker(void* arg) {
13661408
nb_rx -= to_copy;
13671409

13681410
if (burst->hdr.hdr.num_pkts == tparams->batch_size) {
1369-
cur_pkt_in_batch = 0;
13701411
rte_ring_enqueue(tparams->ring, reinterpret_cast<void*>(burst));
1412+
cur_pkt_in_batch = 0;
1413+
last_cycles = rte_get_tsc_cycles();
13711414
break;
13721415
}
1416+
else if (timeout_cycles > 0) {
1417+
const auto cur_cycles = rte_get_tsc_cycles();
1418+
1419+
// We hit our timeout. Send the partial batch immediately
1420+
if ((cur_cycles - last_cycles) > timeout_cycles) {
1421+
rte_ring_enqueue(tparams->ring, reinterpret_cast<void*>(burst));
1422+
cur_pkt_in_batch = 0;
1423+
last_cycles = cur_cycles;
1424+
break;
1425+
}
1426+
}
13731427
} while (!force_quit.load());
13741428
}
13751429

operators/advanced_network/managers/dpdk/adv_network_dpdk_mgr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ class DpdkMgr : public ANOMgr {
202202
bool validate_config() const override;
203203

204204
private:
205+
static uint64_t get_tsc_hz();
205206
static void PrintDpdkStats(int port);
206207
static std::string generate_random_string(int len);
207208
static int rx_core_worker(void* arg);

0 commit comments

Comments
 (0)