Skip to content

Commit 0539865

Browse files
authored
Merge pull request #141 from DUNE-DAQ/thea/multi_garp
Multi-garp testing
2 parents 218adc9 + 521f5dd commit 0539865

File tree

5 files changed

+340
-47
lines changed

5 files changed

+340
-47
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ daq_add_plugin(DPDKReaderModule duneDAQModule LINK_LIBRARIES appfwk::appfwk dpdk
7373
daq_add_application(dpdklibs_test_eal test_eal_app.cxx TEST LINK_LIBRARIES dpdklibs ${DPDK_LIBRARIES})
7474
daq_add_application(dpdklibs_test_frame_transmitter test_frame_transmitter.cxx TEST LINK_LIBRARIES dpdklibs CLI11::CLI11 ${DPDK_LIBRARIES} )
7575
daq_add_application(dpdklibs_test_frame_receiver test_frame_receiver.cxx TEST LINK_LIBRARIES dpdklibs CLI11::CLI11 ${DPDK_LIBRARIES} opmonlib::opmonlib)
76+
daq_add_application(dpdklibs_test_garp test_garp.cxx TEST LINK_LIBRARIES dpdklibs CLI11::CLI11 ${DPDK_LIBRARIES} )
7677
daq_add_application(dpdklibs_test_arp_response test_arp_response.cxx TEST LINK_LIBRARIES dpdklibs ${DPDK_LIBRARIES})
7778
daq_add_application(dpdklibs_test_transmit_and_receive test_transmit_and_receive.cxx TEST LINK_LIBRARIES dpdklibs CLI11::CLI11 ${DPDK_LIBRARIES})
7879
daq_add_application(dpdklibs_test_dpdk_stats test_dpdk_stats.cxx TEST LINK_LIBRARIES dpdklibs CLI11::CLI11 ${DPDK_LIBRARIES})

scripts/dpdklibs_udp_receiver.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ def dump_data(data):
3636
@click.command()
3737
@click.option('-d', '--dump', is_flag=True, default=False)
3838
@click.option('-c', '--count', type=int, default=None)
39-
@click.option('-p', '--port', type=int, default=None)
39+
@click.option('-p', '--port', type=int, default=0x4444)
4040
@click.option('-g', '--gap', type=int, default=None)
4141
@click.option('-f', '--frame-type', type=click.Choice(['wib', 'tde']), default='wib')
4242
def main(dump, count, port, gap, frame_type):
4343
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
4444

45-
s.bind(('0.0.0.0', port))
45+
s.bind(('', port))
4646

4747
prev_stream = {}
4848
i=0

src/EALSetup.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
* Licensing/copyright details are in the COPYING file that you should have
66
* received with this code.
77
*/
8-
#ifndef DPDKLIBS_INCLUDE_DPDKLIBS_EALSETUP_HPP_
9-
#define DPDKLIBS_INCLUDE_DPDKLIBS_EALSETUP_HPP_
8+
// #ifndef DPDKLIBS_INCLUDE_DPDKLIBS_EALSETUP_HPP_
9+
// #define DPDKLIBS_INCLUDE_DPDKLIBS_EALSETUP_HPP_
1010

1111
#include "logging/Logging.hpp"
1212

@@ -57,7 +57,7 @@ std::string get_mac_addr_str(const rte_ether_addr& addr) {
5757

5858
// Modifies Ethernet device configuration to multi-queue RSS with offload
5959
void
60-
iface_conf_rss_mode(struct rte_eth_conf& iface_conf, bool mode = false, bool offload = false)
60+
iface_conf_rss_mode(struct rte_eth_conf& iface_conf, bool mode, bool offload)
6161
{
6262
if (mode) {
6363
iface_conf.rxmode.mq_mode = RTE_ETH_MQ_RX_RSS;
@@ -71,7 +71,7 @@ iface_conf_rss_mode(struct rte_eth_conf& iface_conf, bool mode = false, bool off
7171

7272
// Enables RX in promiscuous mode for the Ethernet device.
7373
int
74-
iface_promiscuous_mode(std::uint16_t iface, bool mode = false)
74+
iface_promiscuous_mode(std::uint16_t iface, bool mode)
7575
{
7676
int retval = -1;
7777
retval = rte_eth_promiscuous_get(iface);
@@ -332,5 +332,5 @@ void finish_eal() {
332332
} // namespace ealutils
333333
} // namespace dpdklibs
334334
} // namespace dunedaq
335+
// #endif // DPDKLIBS_INCLUDE_DPDKLIBS_EALSETUP_HPP_
335336

336-
#endif // DPDKLIBS_INCLUDE_DPDKLIBS_EALSETUP_HPP_

test/apps/test_frame_receiver.cxx

Lines changed: 115 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
/* Application will run until quit or killed. */
3-
#include <fmt/core.h>
3+
44
#include <inttypes.h>
55
#include <rte_cycles.h>
66
#include <rte_eal.h>
@@ -21,10 +21,20 @@
2121
#include "CLI/Formatter.hpp"
2222

2323
#include "detdataformats/DAQEthHeader.hpp"
24+
#include "dpdklibs/EALSetup.hpp"
2425
#include "dpdklibs/udp/PacketCtor.hpp"
2526
#include "dpdklibs/udp/Utils.hpp"
2627
#include "logging/Logging.hpp"
27-
#include "dpdklibs/EALSetup.hpp"
28+
29+
#include "dpdklibs/udp/PacketCtor.hpp"
30+
#include "dpdklibs/udp/Utils.hpp"
31+
#include "dpdklibs/arp/ARP.hpp"
32+
#include "dpdklibs/ipv4_addr.hpp"
33+
34+
#include <fmt/core.h>
35+
#include <fmt/ranges.h>
36+
37+
#include <regex>
2838

2939
#define RX_RING_SIZE 1024
3040
#define TX_RING_SIZE 1024
@@ -117,8 +127,10 @@ namespace {
117127
std::atomic<uint64_t> max_payload_size = 0;
118128
std::atomic<uint64_t> udp_pkt_counter = 0;
119129

120-
std::ofstream datafile;
121-
const std::string output_data_filename = "dpdklibs_test_frame_receiver.dat";
130+
std::atomic<int64_t> garps_sent = 0;
131+
132+
// std::ofstream datafile;
133+
// const std::string output_data_filename = "dpdklibs_test_frame_receiver.dat";
122134

123135

124136
} // namespace
@@ -190,7 +202,7 @@ static inline int check_packet_size(struct rte_mbuf* mbuf, StreamUID unique_str_
190202
return 0;
191203
}
192204

193-
static int lcore_main(struct rte_mempool* mbuf_pool, uint16_t iface, uint64_t time_per_report){
205+
static int lcore_main(struct rte_mempool* mbuf_pool, uint16_t iface, uint64_t time_per_report, const std::vector<std::string>& garp_ip_addr_strs){
194206
/*
195207
* Check that the iface is on the same NUMA node as the polling thread
196208
* for best performance.
@@ -260,34 +272,69 @@ static int lcore_main(struct rte_mempool* mbuf_pool, uint16_t iface, uint64_t ti
260272
}
261273
});
262274

263-
struct rte_mbuf **bufs = (rte_mbuf**) malloc(sizeof(struct rte_mbuf*) * burst_size);
264-
rte_pktmbuf_alloc_bulk(mbuf_pool, bufs, burst_size);
265-
266-
datafile.open(output_data_filename, std::ios::out | std::ios::binary);
267-
if ( (datafile.rdstate() & std::ofstream::failbit ) != 0 ) {
268-
fmt::print("WARNING: Unable to open output file \"{}\"\n", output_data_filename);
275+
//
276+
// Prepare and start GARP thread
277+
//
278+
std::vector<rte_be32_t> ip_addr_bin_vector;
279+
for( const auto& ip_addr_str : garp_ip_addr_strs ) {
280+
TLOG() << "IP address for ARP responses: " << ip_addr_str;
281+
IpAddr ip_addr(ip_addr_str);
282+
rte_be32_t ip_addr_bin = ip_address_dotdecimal_to_binary(
283+
ip_addr.addr_bytes[3],
284+
ip_addr.addr_bytes[2],
285+
ip_addr.addr_bytes[1],
286+
ip_addr.addr_bytes[0]
287+
);
288+
ip_addr_bin_vector.push_back(ip_addr_bin);
269289
}
270290

291+
struct rte_mbuf **tx_bufs = (rte_mbuf**) malloc(sizeof(struct rte_mbuf*) * burst_size);
292+
rte_pktmbuf_alloc_bulk(mbuf_pool, tx_bufs, burst_size);
293+
294+
auto garp = std::thread([&]() {
295+
while (true) {
296+
// TLOG() << "Packets/s: " << num_packets << " Bytes/s: " << num_bytes << " Total packets: " << total_packets << " Failed packets: " << failed_packets;
297+
// num_packets.exchange(0);
298+
// num_bytes.exchange(0);
299+
300+
for(const auto& ip_addr_bin : ip_addr_bin_vector ) {
301+
arp::pktgen_send_garp(tx_bufs[0], iface, ip_addr_bin);
302+
++garps_sent;
303+
}
304+
305+
std::this_thread::sleep_for(std::chrono::seconds(1)); // If we sample for anything other than 1s, the rate calculation will need to change
306+
}
307+
});
308+
309+
310+
struct rte_mbuf **rx_bufs = (rte_mbuf**) malloc(sizeof(struct rte_mbuf*) * burst_size);
311+
rte_pktmbuf_alloc_bulk(mbuf_pool, rx_bufs, burst_size);
312+
313+
// datafile.open(output_data_filename, std::ios::out | std::ios::binary);
314+
// if ( (datafile.rdstate() & std::ofstream::failbit ) != 0 ) {
315+
// fmt::print("WARNING: Unable to open output file \"{}\"\n", output_data_filename);
316+
// }
317+
271318
while (true) {
272319
/* Get burst of RX packets, from first iface of pair. */
273-
const uint16_t nb_rx = rte_eth_rx_burst(iface, 0, bufs, burst_size);
320+
const uint16_t nb_rx = rte_eth_rx_burst(iface, 0, rx_bufs, burst_size);
274321

275322
num_packets += nb_rx;
276323
total_packets += nb_rx;
277324

278325
for (int i_b = 0; i_b < nb_rx; ++i_b) {
279-
num_bytes += bufs[i_b]->pkt_len;
326+
num_bytes += rx_bufs[i_b]->pkt_len;
280327

281328

282329
bool dump_packet = false;
283-
if (not RTE_ETH_IS_IPV4_HDR(bufs[i_b]->packet_type)) {
330+
if (not RTE_ETH_IS_IPV4_HDR(rx_bufs[i_b]->packet_type)) {
284331
non_ipv4_packets++;
285332
dump_packet = true;
286333
continue;
287334
}
288335
++udp_pkt_counter;
289336

290-
char* udp_payload = udp::get_udp_payload(bufs[i_b]);
337+
char* udp_payload = udp::get_udp_payload(rx_bufs[i_b]);
291338
const detdataformats::DAQEthHeader* daq_hdr = reinterpret_cast<const detdataformats::DAQEthHeader*>(udp_payload);
292339

293340
// uint64_t unique_str_id = (daq_hdr->det_id<<22) + (daq_hdr->crate_id<<12) + (daq_hdr->slot_id<<8) + daq_hdr->stream_id;
@@ -300,12 +347,12 @@ static int lcore_main(struct rte_mempool* mbuf_pool, uint16_t iface, uint64_t ti
300347
stream_stats[unique_str_id];
301348
stream_stats[unique_str_id].prev_seq_id = daq_hdr->seq_id - 1;
302349
}
303-
stream_stats[unique_str_id].num_bytes += bufs[i_b]->pkt_len;
350+
stream_stats[unique_str_id].num_bytes += rx_bufs[i_b]->pkt_len;
304351

305352
if (check_against_previous_stream(daq_hdr, 2048) != 0){
306353
dump_packet = true;
307354
}
308-
if (check_packet_size(bufs[i_b], unique_str_id) != 0){
355+
if (check_packet_size(rx_bufs[i_b], unique_str_id) != 0){
309356
dump_packet = true;
310357
}
311358

@@ -316,11 +363,11 @@ static int lcore_main(struct rte_mempool* mbuf_pool, uint16_t iface, uint64_t ti
316363
if (dump_packet && dumped_packet_count < max_packets_to_dump) {
317364
dumped_packet_count++;
318365

319-
rte_pktmbuf_dump(stdout, bufs[i_b], bufs[i_b]->pkt_len);
366+
rte_pktmbuf_dump(stdout, rx_bufs[i_b], rx_bufs[i_b]->pkt_len);
320367
}
321368
}
322369

323-
rte_pktmbuf_free_bulk(bufs, nb_rx);
370+
rte_pktmbuf_free_bulk(rx_bufs, nb_rx);
324371
}
325372

326373
return 0;
@@ -329,39 +376,66 @@ static int lcore_main(struct rte_mempool* mbuf_pool, uint16_t iface, uint64_t ti
329376
// Define the function to be called when ctrl-c (SIGINT) is sent to process
330377
void signal_callback_handler(int signum){
331378
fmt::print("Caught signal {}\n", signum);
332-
if (datafile.is_open()) {
333-
datafile.close();
334-
}
335-
// Terminate program
336379
std::exit(signum);
337380
}
338381

339382
int main(int argc, char** argv){
340383
uint64_t time_per_report = 1;
341384
uint16_t iface = 0;
385+
std::vector<std::string> garp_ip_addresses;
386+
std::vector<std::string> pcie_addresses;
342387

343388
CLI::App app{"test frame receiver"};
344-
app.add_option("-s", expected_packet_size, "Expected frame size");
345-
app.add_option("-i", iface, "Interface to init");
346-
app.add_option("-t", time_per_report, "Time Per Report");
389+
app.add_option("-g,--garp-ip-address", garp_ip_addresses, "IP Addresses");
390+
app.add_option("-m,--pcie-mask", pcie_addresses, "PCIE Addresses device mask");
391+
app.add_option("-s,--exp-frame-size", expected_packet_size, "Expected frame size");
392+
app.add_option("-i,--iface", iface, "Interface to init");
393+
app.add_option("-t,--report-interval-time", time_per_report, "Time Per Report");
347394
app.add_flag("--check-time", check_timestamp, "Report back differences in timestamp");
348-
app.add_flag("-p", per_stream_reports, "Detailed per stream reports");
395+
app.add_flag("-p,--per-stream-reports", per_stream_reports, "Detailed per stream reports");
396+
349397
CLI11_PARSE(app, argc, argv);
350398

399+
// Validate arguments
400+
fmt::print("ips : {}\n", fmt::join(garp_ip_addresses," | "));
401+
fmt::print("pcies : {}\n", fmt::join(pcie_addresses," | "));
402+
403+
std::regex re_ipv4("[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}");
404+
std::regex re_pcie("^0{0,4}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}.[0-9]$");
405+
406+
fmt::print("IP addresses\n");
407+
bool all_ip_ok = true;
408+
for( const auto& ip: garp_ip_addresses) {
409+
bool ip_ok = std::regex_match(ip, re_ipv4);
410+
fmt::print("- {} {}\n", ip, ip_ok);
411+
all_ip_ok &= ip_ok;
412+
}
413+
414+
fmt::print("PCIE addresses\n");
415+
bool all_pcie_ok = true;
416+
for( const auto& pcie: pcie_addresses) {
417+
bool pcie_ok = std::regex_match(pcie, re_pcie);
418+
fmt::print("- {} {}\n", pcie, pcie_ok);
419+
all_pcie_ok &= pcie_ok;
420+
}
421+
422+
if (!all_ip_ok or !all_pcie_ok) {
423+
return -1;
424+
}
425+
426+
351427
// define function to be called when ctrl+c is called.
352428
std::signal(SIGINT, signal_callback_handler);
353429

354430
std::vector<std::string> eal_args;
355-
eal_args.push_back("dpdklibds_test_frame_receiver");
356-
431+
eal_args.push_back("dpdklibds_test_garp");
432+
for( const auto& pcie: pcie_addresses) {
433+
eal_args.push_back("-a");
434+
eal_args.push_back(pcie);
435+
}
357436

358-
// initialise eal with constructed argc and argv
359-
std::vector<char*> vec_argv = construct_argv(eal_args);
360-
char** constructed_argv = vec_argv.data();
361-
int constructed_argc = eal_args.size();
362437

363-
int ret = rte_eal_init(constructed_argc, constructed_argv);
364-
if (ret < 0) {rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");}
438+
dunedaq::dpdklibs::ealutils::init_eal(eal_args);
365439

366440
auto n_ifaces = rte_eth_dev_count_avail();
367441
fmt::print("# of available ifaces: {}\n", n_ifaces);
@@ -374,9 +448,10 @@ int main(int argc, char** argv){
374448
// Allocate pools and mbufs per queue
375449
std::map<int, std::unique_ptr<rte_mempool>> mbuf_pools;
376450
std::map<int, struct rte_mbuf **> bufs;
377-
uint16_t n_rx_qs = 1;
378-
const uint16_t rx_ring_size = 1024;
379-
const uint16_t tx_ring_size = 1024;
451+
const uint16_t n_rx_qs = 1;
452+
const uint16_t n_tx_qs = 1;
453+
const uint16_t rx_ring_size = 2048;
454+
const uint16_t tx_ring_size = 2048;
380455

381456
std::cout << "Allocating pools and mbufs.\n";
382457
for (size_t i=0; i<n_rx_qs; ++i) {
@@ -390,9 +465,9 @@ int main(int argc, char** argv){
390465

391466
// Setting up only one iface
392467
fmt::print("Initialize only iface {}!\n", iface);
393-
ealutils::iface_init(iface, n_rx_qs, 0, rx_ring_size, tx_ring_size, mbuf_pools); // just init iface, no TX queues
468+
ealutils::iface_init(iface, n_rx_qs, n_tx_qs, rx_ring_size, tx_ring_size, mbuf_pools); // just init iface, no TX queues
394469

395-
lcore_main(mbuf_pools[0].get(), iface, time_per_report);
470+
lcore_main(mbuf_pools[0].get(), iface, time_per_report, garp_ip_addresses);
396471

397472
rte_eal_cleanup();
398473

0 commit comments

Comments
 (0)