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

Generated by: LCOV version 2.0-1