LCOV - code coverage report
Current view: top level - dpdklibs/src/detail - IfaceWrapper.hxx (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 96 0
Test Date: 2026-10-11 15:05:20 Functions: 0.0 % 12 0

            Line data    Source code
       1              : #include "dpdklibs/udp/IPV4UDPPacket.hpp"
       2              : #include <rte_arp.h>
       3              : #include <rte_ethdev.h>
       4              : #include <time.h>
       5              : 
       6              : namespace dunedaq {
       7              : namespace dpdklibs {
       8              : 
       9              : int
      10            0 : IfaceWrapper::rx_runner(void* arg __rte_unused)
      11              : {
      12              : 
      13              :   // Timespec for opportunistic sleep. Nanoseconds configured in conf.
      14            0 :   struct timespec sleep_request = { 0, (long)m_lcore_sleep_ns };
      15              : 
      16              :   // bool once = true; // One shot action variable.
      17            0 :   uint16_t iface = m_iface_id;
      18              : 
      19            0 :   const uint16_t lid = rte_lcore_id();
      20            0 :   auto queues = m_rx_core_map[lid];
      21              : 
      22            0 :   if (rte_eth_dev_socket_id(iface) >= 0 && rte_eth_dev_socket_id(iface) != (int)rte_socket_id()) {
      23            0 :     TLOG() << "WARNING, iface " << iface << " is on remote NUMA node to polling thread! "
      24            0 :            << "Performance will not be optimal.";
      25              :   }
      26              : 
      27            0 :   TLOG() << "LCore RX runner on CPU[" << lid << "]: Main loop starts for iface " << iface << " !";
      28              : 
      29            0 :   std::map<int, int> nb_rx_map;
      30              :   // While loop of quit atomic member in IfaceWrapper
      31            0 :   while (!this->m_lcore_quit_signal.load()) {
      32              : 
      33              :     // Loop over assigned queues to process
      34            0 :     uint8_t fb_count(0);
      35            0 :     for (const auto& q : queues) {
      36            0 :       auto src_rx_q = q.first;
      37            0 :       auto* q_bufs = m_bufs[src_rx_q];
      38              : 
      39              :       // Get burst from queue
      40            0 :       const uint16_t nb_rx = rte_eth_rx_burst(iface, src_rx_q, q_bufs, m_burst_size);
      41            0 :       nb_rx_map[src_rx_q] = nb_rx;
      42              :     }
      43              : 
      44            0 :     for (const auto& q : queues) {
      45              : 
      46            0 :       auto src_rx_q = q.first;
      47            0 :       auto* q_bufs = m_bufs[src_rx_q];
      48            0 :       const uint16_t nb_rx = nb_rx_map[src_rx_q];
      49              : 
      50              :       // We got packets from burst on this queue
      51            0 :       if (nb_rx != 0) [[likely]] {
      52              : 
      53              :         // Update max burst size counter of this queue
      54            0 :         m_max_burst_size[src_rx_q] = std::max(nb_rx, m_max_burst_size[src_rx_q].load());
      55              : 
      56              :         // -------
      57              :         // Iterate on burst packets
      58            0 :         for (int i_b = 0; i_b < nb_rx; ++i_b) {
      59              : 
      60              :           // Check if packet is segmented. Implement support for it if needed.
      61              :           // if (q_bufs[i_b]->nb_segs > 1) [[unlikely]] {
      62              :           //  TLOG_DEBUG(10) << "It appears a packet is spread across more than one receiving buffer;"
      63              :           //                 << " there's currently no logic in this program to handle this";
      64              :           //}
      65              : 
      66              :           // Check packet type, decide their fate: ignore unexpected ones, FIXME: monitor occurrences
      67            0 :           auto pkt_type = q_bufs[i_b]->packet_type;
      68              :           // Handle non IPV4 frames.
      69            0 :           if (not RTE_ETH_IS_IPV4_HDR(pkt_type)) [[unlikely]] {
      70              :             // TLOG_DEBUG(10) << "Non-Ethernet packet type: " << (unsigned)pkt_type << " original: " << pkt_type;
      71            0 :             if (pkt_type == RTE_PTYPE_L2_ETHER_ARP) {
      72              :               // TLOG() << "Unexpected: Should handle an ARP request from lcore=" << lid << " rx_q=" << src_rx_q << "!
      73              :               // Flow should be steered to dedicated RX Queue.";
      74            0 :             } else if (pkt_type == RTE_PTYPE_L2_ETHER_LLDP) {
      75              :               // TLOG_DEBUG(10) << "TODO: Handle LLDP packet!";
      76              :             } else {
      77              :               // TLOG_DEBUG(10) << "Unidentified! Dumping...";
      78              :               // rte_pktmbuf_dump(stdout, q_bufs[i_b], m_bufs[src_rx_q][i_b]->pkt_len);
      79              :             }
      80            0 :             ++m_num_unhandled_non_ipv4[lid];
      81            0 :             continue;
      82              :           }
      83              : 
      84              :           // Check if frame is non UDP: in that case, ignore it.
      85            0 :           if ((pkt_type & RTE_PTYPE_L4_MASK) != RTE_PTYPE_L4_UDP) [[unlikely]] {
      86            0 :             ++m_num_unhandled_non_udp[lid];
      87            0 :             continue; // ommit it
      88              :           }
      89              : 
      90              :           // Check for JUMBO frames (bigger than 1500 Bytes)
      91            0 :           if (q_bufs[i_b]->pkt_len > 1500) [[likely]] { // RS FIXME: do proper check on data length later
      92              : 
      93              :             // If flow enabled, handle the payload.
      94            0 :             if (m_lcore_enable_flow.load()) [[likely]] {
      95              :               // Get length of user payload. (Ethernet headers excluded.)
      96            0 :               struct udp::ipv4_udp_packet_hdr* udp_packet =
      97            0 :                 rte_pktmbuf_mtod(q_bufs[i_b], struct udp::ipv4_udp_packet_hdr*);
      98            0 :               char* message = udp::get_udp_payload(q_bufs[i_b]);
      99            0 :               std::size_t udp_payload_len = udp::get_payload_size_udp_hdr(&udp_packet->udp_hdr);
     100              : 
     101            0 :               if (m_strict_parsing) { // all sources maintain DAQ protocol
     102            0 :                 parse_udp_payload(src_rx_q, message, udp_payload_len);
     103              :               } else { // avoid size checks and scattering
     104            0 :                 passthrough_udp_payload(src_rx_q, message, udp_payload_len);
     105              :               }
     106              :             }
     107              : 
     108              :             // Update metrics of queue: frame and Byte counters
     109            0 :             ++m_num_frames_rxq[src_rx_q];
     110            0 :             std::size_t data_len = q_bufs[i_b]->data_len;
     111            0 :             m_num_bytes_rxq[src_rx_q] += data_len;
     112              :           } else {
     113            0 :             ++m_num_unhandled_non_jumbo_udp[lid];
     114              :           }
     115              :         }
     116              : 
     117              :         // Bulk free of mbufs
     118            0 :         rte_pktmbuf_free_bulk(q_bufs, nb_rx);
     119              : 
     120              :       } // per burst
     121              :       // -----------
     122              : 
     123              :       // Full burst counter
     124            0 :       if (nb_rx == m_burst_size) {
     125            0 :         ++fb_count;
     126            0 :         ++m_num_full_bursts[src_rx_q];
     127              :       }
     128              :     } // per queue
     129              : 
     130              :     // If no full buffers in burst...
     131            0 :     if (!fb_count) {
     132            0 :       if (m_lcore_sleep_ns) {
     133              :         // Sleep n nanoseconds... (value from config, timespec initialized in lcore first lines)
     134            0 :         /*int response =*/nanosleep(&sleep_request, nullptr);
     135              :       }
     136              :     }
     137              : 
     138              :   } // main while(quit) loop
     139              : 
     140            0 :   TLOG() << "LCore RX runner on CPU[" << lid << "] returned.";
     141            0 :   return 0;
     142            0 : }
     143              : 
     144              : int
     145            0 : IfaceWrapper::arp_response_runner(void* arg __rte_unused)
     146              : {
     147              : 
     148              :   // Timespec for opportunistic sleep. Nanoseconds configured in conf.
     149            0 :   struct timespec sleep_request = { 0, (long)900000 };
     150              : 
     151              :   // bool once = true; // One shot action variable.
     152            0 :   uint16_t iface = m_iface_id;
     153              : 
     154            0 :   const uint16_t lid = rte_lcore_id();
     155            0 :   unsigned arp_rx_queue = m_arp_rx_queue;
     156              : 
     157            0 :   TLOG() << "LCore ARP responder on CPU[" << lid << "]: Main loop starts for iface " << iface
     158            0 :          << " rx queue: " << arp_rx_queue;
     159              : 
     160              :   // While loop of quit atomic member in IfaceWrapper
     161            0 :   while (!this->m_lcore_quit_signal.load()) {
     162              : 
     163            0 :     const uint16_t nb_rx = rte_eth_rx_burst(iface, arp_rx_queue, m_arp_bufs[arp_rx_queue], m_burst_size);
     164              : 
     165              :     // We got packets from burst on this queue
     166            0 :     if (nb_rx != 0) {
     167              :       // Iterate on burst packets
     168            0 :       for (int i_b = 0; i_b < nb_rx; ++i_b) {
     169              : 
     170              :         // Check packet type, ommit/drop unexpected ones.
     171            0 :         auto pkt_type = m_arp_bufs[arp_rx_queue][i_b]->packet_type;
     172              :         //// Handle non IPV4 packets
     173            0 :         if (not RTE_ETH_IS_IPV4_HDR(pkt_type)) {
     174              :           // TLOG_DEBUG(10) << "Non-Ethernet packet type: " << (unsigned)pkt_type << " original: " << pkt_type;
     175            0 :           if (pkt_type == RTE_PTYPE_L2_ETHER_ARP) {
     176            0 :             TLOG_DEBUG(10) << "Handling ARP request";
     177            0 :             struct rte_ether_hdr* eth_hdr = rte_pktmbuf_mtod(m_arp_bufs[arp_rx_queue][i_b], struct rte_ether_hdr*);
     178            0 :             struct rte_arp_hdr* arp_hdr = (struct rte_arp_hdr*)(eth_hdr + 1);
     179              : 
     180            0 :             std::string srcaddr = dunedaq::dpdklibs::udp::get_ipv4_decimal_addr_str(
     181            0 :               dunedaq::dpdklibs::udp::ip_address_binary_to_dotdecimal(rte_be_to_cpu_32(arp_hdr->arp_data.arp_sip)));
     182            0 :             TLOG_DEBUG(10) << "SRC IP: " << srcaddr;
     183            0 :             std::string dstaddr = dunedaq::dpdklibs::udp::get_ipv4_decimal_addr_str(
     184            0 :               dunedaq::dpdklibs::udp::ip_address_binary_to_dotdecimal(rte_be_to_cpu_32(arp_hdr->arp_data.arp_tip)));
     185            0 :             TLOG_DEBUG(10) << "DEST IP: " << dstaddr;
     186              : 
     187            0 :             for (const auto& ip_addr_bin : m_ip_addr_bin) {
     188            0 :               std::string localaddr = dunedaq::dpdklibs::udp::get_ipv4_decimal_addr_str(
     189            0 :                 dunedaq::dpdklibs::udp::ip_address_binary_to_dotdecimal(rte_be_to_cpu_32(ip_addr_bin)));
     190            0 :               TLOG_DEBUG(10) << "LOCAL IP: " << localaddr;
     191            0 :             }
     192              : 
     193            0 :             if (std::find(m_ip_addr_bin.begin(), m_ip_addr_bin.end(), arp_hdr->arp_data.arp_tip) !=
     194            0 :                 m_ip_addr_bin.end()) {
     195            0 :               arp::pktgen_process_arp(m_arp_bufs[arp_rx_queue][i_b], m_iface_id, arp_hdr->arp_data.arp_tip);
     196              :             } else {
     197            0 :               TLOG_DEBUG(10) << "I'm not the ARP target";
     198              :             }
     199            0 :           } else if (pkt_type == RTE_PTYPE_L2_ETHER_LLDP) {
     200              :             // TLOG_DEBUG(10) << "TODO: Handle LLDP packet!";
     201              :           } else {
     202              :             // TLOG_DEBUG(10) << "Unidentified! Dumping...";
     203              :             // rte_pktmbuf_dump(stdout, m_arp_bufs[arp_rx_queue][i_b], m_bufs[src_rx_q][i_b]->pkt_len);
     204              :           }
     205            0 :           continue;
     206            0 :         }
     207              :       }
     208              : 
     209              :       // Bulk free of mbufs
     210            0 :       rte_pktmbuf_free_bulk(m_arp_bufs[arp_rx_queue], nb_rx);
     211              : 
     212              :     } // per burst
     213              : 
     214              :     // If no full buffers in burst...
     215            0 :     if (m_lcore_sleep_ns) {
     216              :       // Sleep n nanoseconds... (value from config, timespec initialized in lcore first lines)
     217            0 :       /*int response =*/nanosleep(&sleep_request, nullptr);
     218              :     }
     219              : 
     220              :   } // main while(quit) loop
     221              : 
     222            0 :   TLOG() << "LCore ARP responder on CPU[" << lid << "] returned.";
     223            0 :   return 0;
     224              : }
     225              : 
     226              : } // namespace dpdklibs
     227              : } // namespace dunedaq
        

Generated by: LCOV version 2.0-1