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

            Line data    Source code
       1              : /* Application will run until quit or killed. */
       2              : 
       3              : #include "dpdklibs/EALSetup.hpp"
       4              : #include "dpdklibs/arp/ARP.hpp"
       5              : #include "dpdklibs/ipv4_addr.hpp"
       6              : #include "dpdklibs/udp/PacketCtor.hpp"
       7              : #include "dpdklibs/udp/Utils.hpp"
       8              : #include "logging/Logging.hpp"
       9              : 
      10              : #include <inttypes.h>
      11              : #include <rte_cycles.h>
      12              : #include <rte_eal.h>
      13              : #include <rte_ethdev.h>
      14              : #include <rte_lcore.h>
      15              : #include <rte_mbuf.h>
      16              : 
      17              : #include <csignal>
      18              : #include <fstream>
      19              : #include <iomanip>
      20              : #include <limits>
      21              : #include <sstream>
      22              : #include <stdint.h>
      23              : 
      24              : #include "CLI/App.hpp"
      25              : #include "CLI/Config.hpp"
      26              : #include "CLI/Formatter.hpp"
      27              : 
      28              : #include <fmt/core.h>
      29              : #include <fmt/ranges.h>
      30              : 
      31              : #include <regex>
      32              : 
      33              : using namespace dunedaq;
      34              : using namespace dpdklibs;
      35              : using namespace udp;
      36              : 
      37              : namespace {
      38              : constexpr int burst_size = 256;
      39              : 
      40              : std::atomic<int> num_packets = 0;
      41              : std::atomic<int> num_bytes = 0;
      42              : std::atomic<int64_t> total_packets = 0;
      43              : std::atomic<int64_t> failed_packets = 0;
      44              : 
      45              : std::atomic<int64_t> garps_sent = 0;
      46              : 
      47              : } // namespace ""
      48              : 
      49              : static int
      50            0 : lcore_main(struct rte_mempool* mbuf_pool, const std::vector<std::string>& ip_addr_strs)
      51              : {
      52            0 :   uint16_t iface = 0;
      53            0 :   TLOG() << "Launch lcore for interface: " << iface;
      54              : 
      55              :   // IP for ARP
      56              :   // std::vector<std::string> ip_addr_strs = {
      57              :   //   "10.73.139.26",
      58              :   //   "10.73.139.27"
      59              :   // };
      60              : 
      61            0 :   std::vector<rte_be32_t> ip_addr_bin_vector;
      62            0 :   for (const auto& ip_addr_str : ip_addr_strs) {
      63            0 :     TLOG() << "IP address for ARP responses: " << ip_addr_str;
      64            0 :     IpAddr ip_addr(ip_addr_str);
      65            0 :     rte_be32_t ip_addr_bin = ip_address_dotdecimal_to_binary(
      66            0 :       ip_addr.addr_bytes[3], ip_addr.addr_bytes[2], ip_addr.addr_bytes[1], ip_addr.addr_bytes[0]);
      67            0 :     ip_addr_bin_vector.push_back(ip_addr_bin);
      68              :   }
      69              : 
      70            0 :   struct rte_mbuf** tx_bufs = (rte_mbuf**)malloc(sizeof(struct rte_mbuf*) * burst_size);
      71            0 :   rte_pktmbuf_alloc_bulk(mbuf_pool, tx_bufs, burst_size);
      72              : 
      73            0 :   auto garp = std::thread([&]() {
      74            0 :     while (true) {
      75            0 :       TLOG() << "Packets/s: " << num_packets << " Bytes/s: " << num_bytes << " Total packets: " << total_packets
      76            0 :              << " Failed packets: " << failed_packets;
      77            0 :       num_packets.exchange(0);
      78            0 :       num_bytes.exchange(0);
      79              : 
      80            0 :       for (const auto& ip_addr_bin : ip_addr_bin_vector) {
      81            0 :         arp::pktgen_send_garp(tx_bufs[0], iface, ip_addr_bin);
      82            0 :         ++garps_sent;
      83              :       }
      84              : 
      85            0 :       std::this_thread::sleep_for(
      86            0 :         std::chrono::seconds(1)); // If we sample for anything other than 1s, the rate calculation will need to change
      87            0 :     }
      88            0 :   });
      89              : 
      90            0 :   struct rte_mbuf** bufs = (rte_mbuf**)malloc(sizeof(struct rte_mbuf*) * burst_size);
      91            0 :   rte_pktmbuf_alloc_bulk(mbuf_pool, bufs, burst_size);
      92              : 
      93              :   bool once = true; // one shot variable
      94            0 :   while (true) {
      95            0 :     const uint16_t nb_rx = rte_eth_rx_burst(iface, 0, bufs, burst_size);
      96            0 :     if (nb_rx != 0) {
      97            0 :       num_packets += nb_rx;
      98              :       // Iterate on burst packets
      99            0 :       for (int i_b = 0; i_b < nb_rx; ++i_b) {
     100            0 :         num_bytes += bufs[i_b]->pkt_len;
     101              : 
     102              :         // Check for segmentation
     103            0 :         if (bufs[i_b]->nb_segs > 1) {
     104            0 :           TLOG() << "It appears a packet is spread across more than one receiving buffer;"
     105            0 :                  << " there's currently no logic in this program to handle this";
     106              :         }
     107              : 
     108              :         // Check packet type
     109            0 :         auto pkt_type = bufs[i_b]->packet_type;
     110              :         //// Handle non IPV4 packets
     111            0 :         if (not RTE_ETH_IS_IPV4_HDR(pkt_type)) {
     112            0 :           TLOG() << "Non-Ethernet packet type: " << (unsigned)pkt_type;
     113            0 :           if (pkt_type == RTE_PTYPE_L2_ETHER_ARP) {
     114            0 :             TLOG() << "TODO: Handle ARP request!";
     115            0 :             rte_pktmbuf_dump(stdout, bufs[i_b], bufs[i_b]->pkt_len);
     116              :             // arp::pktgen_process_arp(bufs[i_b], 0, ip_addr_bin);
     117            0 :           } else if (pkt_type == RTE_PTYPE_L2_ETHER_LLDP) {
     118            0 :             TLOG() << "TODO: Handle LLDP packet!";
     119            0 :             rte_pktmbuf_dump(stdout, bufs[i_b], bufs[i_b]->pkt_len);
     120              :           } else {
     121            0 :             TLOG() << "Unidentified! Dumping...";
     122            0 :             rte_pktmbuf_dump(stdout, bufs[i_b], bufs[i_b]->pkt_len);
     123              :           }
     124            0 :           continue;
     125            0 :         }
     126              :       }
     127            0 :       rte_pktmbuf_free_bulk(bufs, nb_rx);
     128              :     }
     129              :   } // main loop
     130              : 
     131              :   return 0;
     132            0 : }
     133              : 
     134              : int
     135            0 : main(int argc, char* argv[])
     136              : {
     137              : 
     138            0 :   std::vector<std::string> ip_addresses;
     139            0 :   std::vector<std::string> pcie_addresses;
     140              : 
     141            0 :   CLI::App app{ "test_garp" };
     142            0 :   app.add_option("-i", ip_addresses, "IP Addresses");
     143            0 :   app.add_option("-p", pcie_addresses, "PCIE Addresses");
     144            0 :   CLI11_PARSE(app, argc, argv);
     145              : 
     146            0 :   fmt::print("ips   : {}\n", fmt::join(ip_addresses, " | "));
     147            0 :   fmt::print("pcies   : {}\n", fmt::join(pcie_addresses, " | "));
     148              : 
     149            0 :   std::regex re_ipv4("[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}");
     150            0 :   std::regex re_pcie("^0{0,4}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}.[0-9]$");
     151              : 
     152            0 :   fmt::print("IP addresses\n");
     153            0 :   bool all_ip_ok = true;
     154            0 :   for (const auto& ip : ip_addresses) {
     155            0 :     bool ip_ok = std::regex_match(ip, re_ipv4);
     156            0 :     fmt::print("- {} {}\n", ip, ip_ok);
     157            0 :     all_ip_ok &= ip_ok;
     158              :   }
     159              : 
     160            0 :   fmt::print("PCIE addresses\n");
     161            0 :   bool all_pcie_ok = true;
     162            0 :   for (const auto& pcie : pcie_addresses) {
     163            0 :     bool pcie_ok = std::regex_match(pcie, re_pcie);
     164            0 :     fmt::print("- {} {}\n", pcie, pcie_ok);
     165            0 :     all_pcie_ok &= pcie_ok;
     166              :   }
     167              : 
     168            0 :   if (!all_ip_ok or !all_pcie_ok) {
     169            0 :     return -1;
     170              :   }
     171              : 
     172            0 :   std::vector<std::string> eal_args;
     173            0 :   eal_args.push_back("dpdklibds_test_garp");
     174            0 :   for (const auto& pcie : pcie_addresses) {
     175            0 :     eal_args.push_back("-a");
     176            0 :     eal_args.push_back(pcie);
     177              :   }
     178              : 
     179            0 :   dunedaq::dpdklibs::ealutils::init_eal(eal_args);
     180              : 
     181              :   // Iface ID and its queue numbers
     182            0 :   int iface_id = 0;
     183            0 :   const uint16_t rx_qs = 1;
     184            0 :   const uint16_t tx_qs = 1;
     185            0 :   const uint16_t rx_ring_size = 2048;
     186            0 :   const uint16_t tx_ring_size = 2048;
     187              :   // Get pool
     188            0 :   std::map<int, std::unique_ptr<rte_mempool>> mbuf_pools;
     189            0 :   TLOG() << "Allocating pool";
     190            0 :   for (unsigned p_i = 0; p_i < rx_qs; ++p_i) {
     191            0 :     std::ostringstream ss;
     192            0 :     ss << "MBP-" << p_i;
     193            0 :     mbuf_pools[p_i] = ealutils::get_mempool(ss.str());
     194            0 :   }
     195              : 
     196              :   // Setup interface
     197            0 :   auto nb_ifaces = rte_eth_dev_count_avail();
     198            0 :   TLOG() << "# of available interfaces: " << nb_ifaces;
     199            0 :   TLOG() << "Initialize interface " << iface_id;
     200            0 :   ealutils::iface_init(iface_id, rx_qs, tx_qs, rx_ring_size, tx_ring_size, mbuf_pools);
     201            0 :   ealutils::iface_promiscuous_mode(iface_id, true); // should come from config
     202              : 
     203              :   // Launch lcores
     204            0 :   lcore_main(mbuf_pools[0].get(), ip_addresses);
     205              : 
     206              :   // Cleanup
     207              :   TLOG() << "EAL cleanup...";
     208              :   ealutils::wait_for_lcores();
     209              :   rte_eal_cleanup();
     210              : 
     211              :   return 0;
     212            0 : }
        

Generated by: LCOV version 2.0-1