LCOV - code coverage report
Current view: top level - dpdklibs/test/apps - test_frame_receiver.cxx (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 217 0
Test Date: 2026-10-11 15:05:20 Functions: 0.0 % 10 0

            Line data    Source code
       1              : 
       2              : /* Application will run until quit or killed. */
       3              : 
       4              : #include <inttypes.h>
       5              : #include <rte_cycles.h>
       6              : #include <rte_eal.h>
       7              : #include <rte_ethdev.h>
       8              : #include <rte_lcore.h>
       9              : #include <rte_mbuf.h>
      10              : #include <stdint.h>
      11              : #include <tuple>
      12              : 
      13              : #include <csignal>
      14              : #include <fstream>
      15              : #include <iomanip>
      16              : #include <limits>
      17              : #include <sstream>
      18              : 
      19              : #include "CLI/App.hpp"
      20              : #include "CLI/Config.hpp"
      21              : #include "CLI/Formatter.hpp"
      22              : 
      23              : #include "detdataformats/DAQEthHeader.hpp"
      24              : #include "dpdklibs/EALSetup.hpp"
      25              : #include "dpdklibs/udp/PacketCtor.hpp"
      26              : #include "dpdklibs/udp/Utils.hpp"
      27              : #include "logging/Logging.hpp"
      28              : 
      29              : #include "dpdklibs/arp/ARP.hpp"
      30              : #include "dpdklibs/ipv4_addr.hpp"
      31              : #include "dpdklibs/udp/PacketCtor.hpp"
      32              : #include "dpdklibs/udp/Utils.hpp"
      33              : 
      34              : #include <fmt/core.h>
      35              : #include <fmt/ranges.h>
      36              : 
      37              : #include <regex>
      38              : 
      39              : #define RX_RING_SIZE 1024
      40              : #define TX_RING_SIZE 1024
      41              : 
      42              : #define NUM_MBUFS 8191
      43              : #define MBUF_CACHE_SIZE 250
      44              : 
      45              : #define NSTREAM 128
      46              : 
      47              : #define PG_JUMBO_FRAME_LEN (9600 + RTE_ETHER_CRC_LEN + RTE_ETHER_HDR_LEN)
      48              : #ifndef RTE_JUMBO_ETHER_MTU
      49              : #define RTE_JUMBO_ETHER_MTU (PG_JUMBO_FRAME_LEN - RTE_ETHER_HDR_LEN - RTE_ETHER_CRC_LEN) /*< Ethernet MTU. */
      50              : #endif
      51              : 
      52              : using namespace dunedaq;
      53              : using namespace dpdklibs;
      54              : using namespace udp;
      55              : 
      56              : namespace {
      57              : 
      58              : std::ostream&
      59              : operator<<(std::ostream& out, const StreamUID& obj)
      60              : {
      61              :   return out << static_cast<std::string>(obj);
      62              : }
      63              : 
      64              : struct StreamStats
      65              : {
      66              :   std::atomic<uint64_t> total_packets = 0;
      67              :   std::atomic<uint64_t> num_packets = 0;
      68              :   std::atomic<uint64_t> num_bytes = 0;
      69              :   std::atomic<uint64_t> num_bad_timestamp = 0;
      70              :   std::atomic<uint64_t> max_timestamp_skip = 0;
      71              :   std::atomic<uint64_t> num_bad_seq_id = 0;
      72              :   std::atomic<uint64_t> max_seq_id_skip = 0;
      73              :   std::atomic<uint64_t> num_bad_payload_size = 0;
      74              :   std::atomic<uint64_t> min_payload_size = 0;
      75              :   std::atomic<uint64_t> max_payload_size = 0;
      76              :   std::atomic<uint64_t> prev_seq_id = 0;
      77              :   std::atomic<uint64_t> prev_timestamp = 0;
      78              : 
      79            0 :   void reset()
      80              :   {
      81            0 :     num_packets.exchange(0);
      82            0 :     num_bytes.exchange(0);
      83            0 :     num_bad_timestamp.exchange(0);
      84            0 :     max_timestamp_skip.exchange(0);
      85            0 :     num_bad_seq_id.exchange(0);
      86            0 :     max_seq_id_skip.exchange(0);
      87            0 :     num_bad_payload_size.exchange(0);
      88            0 :     min_payload_size.exchange(0);
      89            0 :     max_payload_size.exchange(0);
      90            0 :   }
      91              : };
      92              : 
      93              : std::map<StreamUID, StreamStats> stream_stats;
      94              : 
      95              : // Apparently only 8 and above works for "burst_size"
      96              : 
      97              : // From the dpdk documentation, describing the rte_eth_rx_burst
      98              : // function (and keeping in mind that their "nb_pkts" variable is the
      99              : // same as our "burst size" variable below):
     100              : // "Some drivers using vector instructions require that nb_pkts is
     101              : // divisible by 4 or 8, depending on the driver implementation."
     102              : 
     103              : bool check_timestamp = false;
     104              : bool per_stream_reports = false;
     105              : 
     106              : constexpr int burst_size = 256;
     107              : 
     108              : constexpr uint32_t expected_packet_type = 0x291;
     109              : 
     110              : constexpr int default_mbuf_size = 9000; // As opposed to RTE_MBUF_DEFAULT_BUF_SIZE
     111              : 
     112              : constexpr int max_packets_to_dump = 10;
     113              : int dumped_packet_count = 0;
     114              : 
     115              : uint16_t expected_packet_size = 0; // 7243; // i.e., every packet that isn't the initial one
     116              : 
     117              : std::atomic<uint64_t> num_packets = 0;
     118              : std::atomic<uint64_t> num_bytes = 0;
     119              : std::atomic<uint64_t> total_packets = 0;
     120              : std::atomic<uint64_t> non_ipv4_packets = 0;
     121              : std::atomic<uint64_t> total_bad_timestamp = 0;
     122              : std::atomic<uint64_t> num_bad_timestamp = 0;
     123              : std::atomic<uint64_t> max_timestamp_skip = 0;
     124              : std::atomic<uint64_t> total_bad_seq_id = 0;
     125              : std::atomic<uint64_t> num_bad_seq_id = 0;
     126              : std::atomic<uint64_t> max_seq_id_skip = 0;
     127              : std::atomic<uint64_t> total_bad_payload_size = 0;
     128              : std::atomic<uint64_t> num_bad_payload_size = 0;
     129              : std::atomic<uint64_t> min_payload_size = 0;
     130              : std::atomic<uint64_t> max_payload_size = 0;
     131              : std::atomic<uint64_t> udp_pkt_counter = 0;
     132              : 
     133              : std::atomic<int64_t> garps_sent = 0;
     134              : 
     135              : // std::ofstream datafile;
     136              : // const std::string output_data_filename = "dpdklibs_test_frame_receiver.dat";
     137              : 
     138              : } // namespace
     139              : 
     140              : std::vector<char*>
     141            0 : construct_argv(std::vector<std::string>& std_argv)
     142              : {
     143            0 :   std::vector<char*> vec_argv;
     144            0 :   for (int i = 0; i < std_argv.size(); i++) {
     145            0 :     vec_argv.insert(vec_argv.end(), std_argv[i].data());
     146              :   }
     147            0 :   return vec_argv;
     148            0 : }
     149              : 
     150              : static inline int
     151            0 : check_against_previous_stream(const detdataformats::DAQEthHeader* daq_hdr, uint64_t exp_ts_diff)
     152              : {
     153              :   // uint64_t unique_str_id = (daq_hdr->det_id<<22) + (daq_hdr->crate_id<<12) + (daq_hdr->slot_id<<8) +
     154              :   // daq_hdr->stream_id;
     155            0 :   StreamUID unique_str_id(*daq_hdr);
     156            0 :   uint64_t stream_ts = daq_hdr->timestamp;
     157            0 :   uint64_t seq_id = daq_hdr->seq_id;
     158            0 :   int ret_val = 0;
     159              : 
     160            0 :   if (check_timestamp) {
     161            0 :     if (stream_stats[unique_str_id].prev_timestamp == 0) {
     162            0 :       stream_stats[unique_str_id].prev_timestamp = stream_ts;
     163              :     } else {
     164            0 :       uint64_t expected_ts = stream_stats[unique_str_id].prev_timestamp + exp_ts_diff;
     165            0 :       if (stream_ts != expected_ts) {
     166            0 :         uint64_t ts_difference = stream_ts - stream_stats[unique_str_id].prev_timestamp;
     167            0 :         ret_val = 1;
     168            0 :         ++num_bad_timestamp;
     169            0 :         ++stream_stats[unique_str_id].num_bad_timestamp;
     170            0 :         ++total_bad_timestamp;
     171            0 :         if (ts_difference > max_timestamp_skip) {
     172            0 :           max_timestamp_skip = ts_difference;
     173              :         }
     174            0 :         if (ts_difference > stream_stats[unique_str_id].max_timestamp_skip) {
     175            0 :           stream_stats[unique_str_id].max_timestamp_skip = ts_difference;
     176              :         }
     177              :       }
     178            0 :       stream_stats[unique_str_id].prev_timestamp = stream_ts;
     179              :     }
     180              :   }
     181              : 
     182            0 :   uint64_t expected_seq_id =
     183            0 :     (stream_stats[unique_str_id].prev_seq_id == 4095) ? 0 : stream_stats[unique_str_id].prev_seq_id + 1;
     184            0 :   if (seq_id != expected_seq_id) {
     185            0 :     uint64_t adj_expected_seq_id = (expected_seq_id == 0) ? 4096 : expected_seq_id;
     186            0 :     uint64_t adj_seq_id = (seq_id < adj_expected_seq_id) ? (4096 + seq_id) : seq_id;
     187            0 :     uint64_t seq_id_difference = adj_seq_id - adj_expected_seq_id;
     188            0 :     ret_val += 2;
     189            0 :     ++num_bad_seq_id;
     190            0 :     ++total_bad_seq_id;
     191            0 :     ++stream_stats[unique_str_id].num_bad_seq_id;
     192            0 :     if (seq_id_difference > max_seq_id_skip) {
     193            0 :       max_seq_id_skip = seq_id_difference;
     194              :     }
     195            0 :     if (seq_id_difference > stream_stats[unique_str_id].max_seq_id_skip) {
     196            0 :       stream_stats[unique_str_id].max_seq_id_skip = seq_id_difference;
     197              :     }
     198              :   }
     199              : 
     200            0 :   return ret_val;
     201              : }
     202              : 
     203              : static inline int
     204            0 : check_packet_size(struct rte_mbuf* mbuf, StreamUID unique_str_id)
     205              : {
     206            0 :   std::size_t packet_size = mbuf->data_len;
     207              : 
     208            0 :   if (packet_size > max_payload_size) {
     209            0 :     max_payload_size = packet_size;
     210              :   }
     211            0 :   if (packet_size < min_payload_size) {
     212            0 :     min_payload_size = packet_size;
     213              :   }
     214            0 :   if (packet_size > stream_stats[unique_str_id].max_payload_size) {
     215            0 :     stream_stats[unique_str_id].max_payload_size = packet_size;
     216              :   }
     217            0 :   if (packet_size < stream_stats[unique_str_id].min_payload_size) {
     218            0 :     stream_stats[unique_str_id].min_payload_size = packet_size;
     219              :   }
     220              : 
     221            0 :   if (expected_packet_size and (packet_size != expected_packet_size)) {
     222            0 :     ++num_bad_payload_size;
     223            0 :     ++total_bad_payload_size;
     224            0 :     ++stream_stats[unique_str_id].num_bad_payload_size;
     225            0 :     return 1;
     226              :   }
     227              :   return 0;
     228              : }
     229              : 
     230              : static int
     231            0 : lcore_main(struct rte_mempool* mbuf_pool,
     232              :            uint16_t iface,
     233              :            uint64_t time_per_report,
     234              :            const std::vector<std::string>& garp_ip_addr_strs)
     235              : {
     236              :   /*
     237              :    * Check that the iface is on the same NUMA node as the polling thread
     238              :    * for best performance.
     239              :    */
     240              : 
     241            0 :   if (rte_eth_dev_socket_id(iface) >= 0 && rte_eth_dev_socket_id(iface) != static_cast<int>(rte_socket_id())) {
     242            0 :     fmt::print("WARNING, iface {} is on remote NUMA node to polling thread.\n\tPerformance will not be optimal.\n",
     243              :                iface);
     244              :   }
     245              : 
     246            0 :   auto stats = std::thread([&]() {
     247            0 :     while (true) {
     248            0 :       uint64_t packets_per_second = num_packets / time_per_report;
     249            0 :       uint64_t bytes_per_second = num_bytes / time_per_report;
     250            0 :       fmt::print("Since the last report {} seconds ago:\n"
     251              :                  "Packets/s: {} Bytes/s: {} Total packets: {} Non-IPV4 packets: {} Total UDP packets: {}\n"
     252              :                  "Packets with wrong sequence id: {}, Max wrong seq_id jump {}, Total Packets with Wrong seq_id {}\n"
     253              :                  "Max udp payload: {}, Min udp payload: {}\n",
     254              :                  time_per_report,
     255              :                  packets_per_second,
     256              :                  bytes_per_second,
     257              :                  total_packets,
     258              :                  non_ipv4_packets,
     259              :                  udp_pkt_counter,
     260              :                  num_bad_seq_id,
     261              :                  max_seq_id_skip,
     262              :                  total_bad_seq_id,
     263              :                  max_payload_size,
     264              :                  min_payload_size);
     265              : 
     266            0 :       if (expected_packet_size) {
     267            0 :         fmt::print("Packets with wrong payload size: {}, Total Packets with Wrong size {}\n",
     268              :                    num_bad_payload_size,
     269              :                    total_bad_payload_size);
     270              :       }
     271              : 
     272            0 :       if (check_timestamp) {
     273            0 :         fmt::print("Wrong Timestamp difference Packets: {}, Max wrong Timestamp difference {}, Total Packets with "
     274              :                    "Wrong Timestamp {}\n",
     275              :                    num_bad_timestamp,
     276              :                    max_timestamp_skip,
     277              :                    total_bad_timestamp);
     278              :       }
     279              : 
     280            0 :       fmt::print("\n");
     281              :       // for (auto stream = stream_stats.begin(); stream != stream_stats.end(); stream++) {
     282            0 :       for (auto& [suid, stats] : stream_stats) {
     283            0 :         fmt::print("Stream {:15}: n.pkts {} (tot. {})", (std::string)suid, stats.num_packets, stats.total_packets);
     284            0 :         if (per_stream_reports) {
     285            0 :           float stream_bytes_per_second = (float)stats.num_bytes / (1024. * 1024.) / (float)time_per_report;
     286            0 :           fmt::print(" {:8.3f} MB/s, seq. jumps: {}", stream_bytes_per_second, stats.num_bad_seq_id);
     287              :         }
     288            0 :         stats.reset();
     289            0 :         fmt::print("\n");
     290              :       }
     291              : 
     292            0 :       fmt::print("\n");
     293            0 :       num_packets.exchange(0);
     294            0 :       num_bytes.exchange(0);
     295            0 :       num_bad_timestamp.exchange(0);
     296            0 :       num_bad_seq_id.exchange(0);
     297            0 :       num_bad_payload_size.exchange(0);
     298            0 :       max_payload_size.exchange(0);
     299            0 :       min_payload_size.exchange(0);
     300            0 :       max_seq_id_skip.exchange(0);
     301            0 :       max_timestamp_skip.exchange(0);
     302            0 :       std::this_thread::sleep_for(std::chrono::seconds(time_per_report));
     303            0 :     }
     304            0 :   });
     305              : 
     306              :   //
     307              :   // Prepare and start GARP thread
     308              :   //
     309            0 :   std::vector<rte_be32_t> ip_addr_bin_vector;
     310            0 :   for (const auto& ip_addr_str : garp_ip_addr_strs) {
     311            0 :     TLOG() << "IP address for ARP responses: " << ip_addr_str;
     312            0 :     IpAddr ip_addr(ip_addr_str);
     313            0 :     rte_be32_t ip_addr_bin = ip_address_dotdecimal_to_binary(
     314            0 :       ip_addr.addr_bytes[0], ip_addr.addr_bytes[1], ip_addr.addr_bytes[2], ip_addr.addr_bytes[3]);
     315            0 :     ip_addr_bin_vector.push_back(ip_addr_bin);
     316              :   }
     317              : 
     318            0 :   struct rte_mbuf** tx_bufs = (rte_mbuf**)malloc(sizeof(struct rte_mbuf*) * burst_size);
     319            0 :   rte_pktmbuf_alloc_bulk(mbuf_pool, tx_bufs, burst_size);
     320              : 
     321            0 :   auto garp = std::thread([&]() {
     322            0 :     while (true) {
     323              :       // TLOG() << "Packets/s: " << num_packets << " Bytes/s: " << num_bytes << " Total packets: " << total_packets << "
     324              :       // Failed packets: " << failed_packets; num_packets.exchange(0); num_bytes.exchange(0);
     325              : 
     326            0 :       for (const auto& ip_addr_bin : ip_addr_bin_vector) {
     327            0 :         arp::pktgen_send_garp(tx_bufs[0], iface, ip_addr_bin);
     328            0 :         ++garps_sent;
     329              :       }
     330              : 
     331            0 :       std::this_thread::sleep_for(
     332            0 :         std::chrono::seconds(1)); // If we sample for anything other than 1s, the rate calculation will need to change
     333            0 :     }
     334            0 :   });
     335              : 
     336            0 :   struct rte_mbuf** rx_bufs = (rte_mbuf**)malloc(sizeof(struct rte_mbuf*) * burst_size);
     337            0 :   rte_pktmbuf_alloc_bulk(mbuf_pool, rx_bufs, burst_size);
     338              : 
     339              :   // datafile.open(output_data_filename, std::ios::out | std::ios::binary);
     340              :   // if ( (datafile.rdstate() & std::ofstream::failbit ) != 0 ) {
     341              :   // fmt::print("WARNING: Unable to open output file \"{}\"\n", output_data_filename);
     342              :   // }
     343              : 
     344            0 :   while (true) {
     345              :     /* Get burst of RX packets, from first iface of pair. */
     346            0 :     const uint16_t nb_rx = rte_eth_rx_burst(iface, 0, rx_bufs, burst_size);
     347              : 
     348            0 :     num_packets += nb_rx;
     349            0 :     total_packets += nb_rx;
     350              : 
     351            0 :     for (int i_b = 0; i_b < nb_rx; ++i_b) {
     352            0 :       num_bytes += rx_bufs[i_b]->pkt_len;
     353              : 
     354            0 :       bool dump_packet = false;
     355            0 :       if (not RTE_ETH_IS_IPV4_HDR(rx_bufs[i_b]->packet_type)) {
     356            0 :         non_ipv4_packets++;
     357            0 :         dump_packet = true;
     358            0 :         continue;
     359              :       }
     360            0 :       ++udp_pkt_counter;
     361              : 
     362            0 :       char* udp_payload = udp::get_udp_payload(rx_bufs[i_b]);
     363            0 :       const detdataformats::DAQEthHeader* daq_hdr = reinterpret_cast<const detdataformats::DAQEthHeader*>(udp_payload);
     364              : 
     365              :       // uint64_t unique_str_id = (daq_hdr->det_id<<22) + (daq_hdr->crate_id<<12) + (daq_hdr->slot_id<<8) +
     366              :       // daq_hdr->stream_id;
     367            0 :       StreamUID unique_str_id(*daq_hdr);
     368              : 
     369              :       // if ((udp_pkt_counter % 1000000) == 0 ) {
     370              :       //     std::cout << "\nDAQ HEADER:\n" << *daq_hdr<< "\n";
     371              :       // }
     372            0 :       if (stream_stats.find(unique_str_id) == stream_stats.end()) {
     373            0 :         stream_stats[unique_str_id];
     374            0 :         stream_stats[unique_str_id].prev_seq_id = daq_hdr->seq_id - 1;
     375              :       }
     376            0 :       stream_stats[unique_str_id].num_bytes += rx_bufs[i_b]->pkt_len;
     377              : 
     378            0 :       if (check_against_previous_stream(daq_hdr, 2048) != 0) {
     379            0 :         dump_packet = true;
     380              :       }
     381            0 :       if (check_packet_size(rx_bufs[i_b], unique_str_id) != 0) {
     382            0 :         dump_packet = true;
     383              :       }
     384              : 
     385            0 :       ++stream_stats[unique_str_id].total_packets;
     386            0 :       ++stream_stats[unique_str_id].num_packets;
     387            0 :       stream_stats[unique_str_id].prev_seq_id = daq_hdr->seq_id;
     388              : 
     389            0 :       if (dump_packet && dumped_packet_count < max_packets_to_dump) {
     390            0 :         dumped_packet_count++;
     391              : 
     392            0 :         rte_pktmbuf_dump(stdout, rx_bufs[i_b], rx_bufs[i_b]->pkt_len);
     393              :       }
     394              :     }
     395              : 
     396            0 :     rte_pktmbuf_free_bulk(rx_bufs, nb_rx);
     397              :   }
     398              : 
     399              :   return 0;
     400            0 : }
     401              : 
     402              : // Define the function to be called when ctrl-c (SIGINT) is sent to process
     403              : void
     404            0 : signal_callback_handler(int signum)
     405              : {
     406            0 :   fmt::print("Caught signal {}\n", signum);
     407            0 :   std::exit(signum);
     408              : }
     409              : 
     410              : int
     411            0 : main(int argc, char** argv)
     412              : {
     413            0 :   uint64_t time_per_report = 1;
     414            0 :   uint16_t iface = 0;
     415            0 :   std::vector<std::string> garp_ip_addresses;
     416            0 :   std::vector<std::string> pcie_addresses;
     417              : 
     418            0 :   CLI::App app{ "test frame receiver" };
     419            0 :   app.add_option("-g,--garp-ip-address", garp_ip_addresses, "IP Addresses");
     420            0 :   app.add_option("-m,--pcie-mask", pcie_addresses, "PCIE Addresses device mask");
     421            0 :   app.add_option("-s,--exp-frame-size", expected_packet_size, "Expected frame size");
     422            0 :   app.add_option("-i,--iface", iface, "Interface to init");
     423            0 :   app.add_option("-t,--report-interval-time", time_per_report, "Time Per Report");
     424            0 :   app.add_flag("--check-time", check_timestamp, "Report back differences in timestamp");
     425            0 :   app.add_flag("-p,--per-stream-reports", per_stream_reports, "Detailed per stream reports");
     426              : 
     427            0 :   CLI11_PARSE(app, argc, argv);
     428              : 
     429              :   // Validate arguments
     430            0 :   fmt::print("ips   : {}\n", fmt::join(garp_ip_addresses, " | "));
     431            0 :   fmt::print("pcies   : {}\n", fmt::join(pcie_addresses, " | "));
     432              : 
     433            0 :   std::regex re_ipv4("[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}");
     434            0 :   std::regex re_pcie("^0{0,4}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}.[0-9]$");
     435              : 
     436            0 :   fmt::print("IP addresses\n");
     437            0 :   bool all_ip_ok = true;
     438            0 :   for (const auto& ip : garp_ip_addresses) {
     439            0 :     bool ip_ok = std::regex_match(ip, re_ipv4);
     440            0 :     fmt::print("- {} {}\n", ip, ip_ok);
     441            0 :     all_ip_ok &= ip_ok;
     442              :   }
     443              : 
     444            0 :   fmt::print("PCIE addresses\n");
     445            0 :   bool all_pcie_ok = true;
     446            0 :   for (const auto& pcie : pcie_addresses) {
     447            0 :     bool pcie_ok = std::regex_match(pcie, re_pcie);
     448            0 :     fmt::print("- {} {}\n", pcie, pcie_ok);
     449            0 :     all_pcie_ok &= pcie_ok;
     450              :   }
     451              : 
     452            0 :   if (!all_ip_ok or !all_pcie_ok) {
     453              :     return -1;
     454              :   }
     455              : 
     456              :   //    define function to be called when ctrl+c is called.
     457            0 :   std::signal(SIGINT, signal_callback_handler);
     458              : 
     459            0 :   std::vector<std::string> eal_args;
     460            0 :   eal_args.push_back("dpdklibds_test_garp");
     461            0 :   for (const auto& pcie : pcie_addresses) {
     462            0 :     eal_args.push_back("-a");
     463            0 :     eal_args.push_back(pcie);
     464              :   }
     465              : 
     466            0 :   dunedaq::dpdklibs::ealutils::init_eal(eal_args);
     467              : 
     468            0 :   auto n_ifaces = rte_eth_dev_count_avail();
     469            0 :   fmt::print("# of available ifaces: {}\n", n_ifaces);
     470            0 :   if (n_ifaces == 0) {
     471            0 :     std::cout << "WARNING: no available ifaces. exiting...\n";
     472            0 :     rte_eal_cleanup();
     473            0 :     return 1;
     474              :   }
     475              : 
     476              :   // Allocate pools and mbufs per queue
     477            0 :   std::map<int, std::unique_ptr<rte_mempool>> mbuf_pools;
     478            0 :   std::map<int, struct rte_mbuf**> bufs;
     479            0 :   const uint16_t n_rx_qs = 1;
     480            0 :   const uint16_t n_tx_qs = 1;
     481            0 :   const uint16_t rx_ring_size = 2048;
     482            0 :   const uint16_t tx_ring_size = 2048;
     483              : 
     484            0 :   std::cout << "Allocating pools and mbufs.\n";
     485            0 :   for (size_t i = 0; i < n_rx_qs; ++i) {
     486            0 :     std::stringstream ss;
     487            0 :     ss << "MBP-" << i;
     488            0 :     fmt::print("Pool acquire: {}\n", ss.str());
     489            0 :     mbuf_pools[i] = ealutils::get_mempool(ss.str());
     490            0 :     bufs[i] = (rte_mbuf**)malloc(sizeof(struct rte_mbuf*) * burst_size);
     491            0 :     rte_pktmbuf_alloc_bulk(mbuf_pools[i].get(), bufs[i], burst_size);
     492            0 :   }
     493              : 
     494              :   // Setting up only one iface
     495            0 :   fmt::print("Initialize only iface {}!\n", iface);
     496            0 :   ealutils::iface_init(
     497              :     iface, n_rx_qs, n_tx_qs, rx_ring_size, tx_ring_size, mbuf_pools); // just init iface, no TX queues
     498              : 
     499            0 :   lcore_main(mbuf_pools[0].get(), iface, time_per_report, garp_ip_addresses);
     500              : 
     501              :   rte_eal_cleanup();
     502              : 
     503              :   return 0;
     504            0 : }
        

Generated by: LCOV version 2.0-1