LCOV - code coverage report
Current view: top level - dpdklibs/src/udp - Utils.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 24.2 % 149 36
Test Date: 2025-12-21 13:07:08 Functions: 14.3 % 14 2

            Line data    Source code
       1              : /**
       2              :  * @file Utils.cpp UDP related utility functions' implementations
       3              :  *
       4              :  * This is part of the DUNE DAQ , copyright 2020.
       5              :  * Licensing/copyright details are in the COPYING file that you should have
       6              :  * received with this code.
       7              :  */
       8              : #include "dpdklibs/udp/Utils.hpp"
       9              : 
      10              : #include "detdataformats/DAQEthHeader.hpp"
      11              : #include "logging/Logging.hpp"
      12              : #include "datahandlinglibs/DataHandlingIssues.hpp"
      13              : 
      14              : #include <algorithm>
      15              : #include <cstring>
      16              : #include <fstream>
      17              : #include <iomanip>
      18              : #include <iterator>
      19              : #include <sstream>
      20              : #include <string>
      21              : #include <utility>
      22              : #include <vector>
      23              : 
      24              : namespace dunedaq {
      25              : namespace dpdklibs {
      26              : namespace udp {
      27              : 
      28              : std::uint16_t
      29            0 : get_payload_size_udp_hdr(struct rte_udp_hdr* udp_hdr)
      30              : {
      31            0 :   return rte_be_to_cpu_16(udp_hdr->dgram_len) - sizeof(struct rte_udp_hdr);
      32              : }
      33              : 
      34              : std::uint16_t
      35            0 : get_payload_size(struct ipv4_udp_packet_hdr* ipv4_udp_hdr)
      36              : {
      37            0 :   return rte_be_to_cpu_16(ipv4_udp_hdr->udp_hdr.dgram_len) - sizeof(struct rte_udp_hdr);
      38              : }
      39              : 
      40              : rte_be32_t
      41            0 : ip_address_dotdecimal_to_binary(std::uint8_t byte1, std::uint8_t byte2, std::uint8_t byte3, std::uint8_t byte4)
      42              : {
      43            0 :   rte_le32_t ip_address = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
      44            0 :   return rte_cpu_to_be_32(ip_address);
      45              : }
      46              : 
      47              : struct ipaddr
      48            0 : ip_address_binary_to_dotdecimal(rte_le32_t binary_ipv4_address)
      49              : {
      50            0 :   struct ipaddr addr;
      51            0 :   memcpy(&addr, &binary_ipv4_address, sizeof(rte_le32_t));
      52            0 :   return addr;
      53              : }
      54              : 
      55              : std::string
      56            0 : get_ipv4_decimal_addr_str(struct ipaddr ipv4_address)
      57              : {
      58            0 :   std::ostringstream ostrs;
      59            0 :   ostrs << (unsigned)ipv4_address.addr_bytes[3] << '.' << (unsigned)ipv4_address.addr_bytes[2] << '.' << (unsigned)ipv4_address.addr_bytes[1] << '.' << (unsigned)ipv4_address.addr_bytes[0];
      60            0 :   return ostrs.str();
      61              :   /*printf("%i.%i.%i.%i",
      62              :         ipv4_address.addr_bytes[3],
      63              :         ipv4_address.addr_bytes[2],
      64              :         ipv4_address.addr_bytes[1],
      65              :         ipv4_address.addr_bytes[0]);
      66              :   */
      67            0 : }
      68              : 
      69              : char*
      70            0 : get_udp_payload(const rte_mbuf* mbuf)
      71              : {
      72            0 :   struct ipv4_udp_packet_hdr* udp_packet = rte_pktmbuf_mtod(mbuf, struct ipv4_udp_packet_hdr*);
      73              :   // dump_udp_header(udp_packet);
      74              :   // uint16_t payload_size = get_payload_size(udp_packet);
      75            0 :   char* payload = (char*)(udp_packet + 1);
      76            0 :   return payload;
      77              : 
      78              :   /*
      79              :   if (dump_mode == 10) {
      80              :     return payload;
      81              :   }
      82              : 
      83              :   if (dump_mode == 0 || dump_mode == 3) {
      84              :     printf("UDP Payload size: %i\n", payload_size);
      85              :     uint byte;
      86              :     for (byte = 0; byte < payload_size; byte++) {
      87              :       printf("%02x ", *(payload + byte) & 0xFF);
      88              :       //printf("%s", (payload + byte));
      89              :     }
      90              :     printf("\n");
      91              :   }
      92              : 
      93              :   if (dump_mode == 1 || dump_mode == 3) {
      94              :     printf("%s\n", payload);
      95              :   }
      96              :   return payload;
      97              :   */
      98              : }
      99              : 
     100              : inline void
     101            0 : hex_digits_to_stream(std::ostringstream& ostrs, int value, char separator = ':', char fill = '0', int digits = 2)
     102              : {
     103            0 :   ostrs << std::setfill(fill) << std::setw(digits) << std::hex << value << std::dec << separator;
     104            0 : }
     105              : 
     106              : std::string
     107              : // dump_udp_header(struct ipv4_udp_packet_hdr * pkt)
     108            0 : get_udp_header_str(struct rte_mbuf* mbuf)
     109              : {
     110            0 :   struct ipv4_udp_packet_hdr* pkt = rte_pktmbuf_mtod(mbuf, struct ipv4_udp_packet_hdr*);
     111            0 :   std::ostringstream ostrs;
     112            0 :   ostrs << "\n------ start of packet ----- \n";
     113            0 :   ostrs << "dst mac addr: ";
     114            0 :   hex_digits_to_stream(ostrs, (int)pkt->eth_hdr.dst_addr.addr_bytes[0]);
     115            0 :   hex_digits_to_stream(ostrs, (int)pkt->eth_hdr.dst_addr.addr_bytes[1]);
     116            0 :   hex_digits_to_stream(ostrs, (int)pkt->eth_hdr.dst_addr.addr_bytes[2]);
     117            0 :   hex_digits_to_stream(ostrs, (int)pkt->eth_hdr.dst_addr.addr_bytes[3]);
     118            0 :   hex_digits_to_stream(ostrs, (int)pkt->eth_hdr.dst_addr.addr_bytes[4]);
     119            0 :   hex_digits_to_stream(ostrs, (int)pkt->eth_hdr.dst_addr.addr_bytes[5], '\n');
     120            0 :   ostrs << "src mac addr: ";
     121            0 :   hex_digits_to_stream(ostrs, (int)pkt->eth_hdr.src_addr.addr_bytes[0]);
     122            0 :   hex_digits_to_stream(ostrs, (int)pkt->eth_hdr.src_addr.addr_bytes[1]);
     123            0 :   hex_digits_to_stream(ostrs, (int)pkt->eth_hdr.src_addr.addr_bytes[2]);
     124            0 :   hex_digits_to_stream(ostrs, (int)pkt->eth_hdr.src_addr.addr_bytes[3]);
     125            0 :   hex_digits_to_stream(ostrs, (int)pkt->eth_hdr.src_addr.addr_bytes[4]);
     126            0 :   hex_digits_to_stream(ostrs, (int)pkt->eth_hdr.src_addr.addr_bytes[5], '\n');
     127            0 :   ostrs << "ethtype: " << (unsigned)pkt->eth_hdr.ether_type << '\n';
     128              : 
     129            0 :   ostrs << "------ IP header ----- \n";
     130            0 :   ostrs << "ipv4 version: " << (unsigned)pkt->ipv4_hdr.version_ihl << '\n';
     131            0 :   ostrs << "ipv4 type_of_service: " << (unsigned)pkt->ipv4_hdr.type_of_service << '\n';
     132            0 :   ostrs << "ipv4 total lenght: " << (unsigned)rte_be_to_cpu_16(pkt->ipv4_hdr.total_length) << '\n';
     133            0 :   ostrs << "ipv4 packet_id: " << (unsigned)pkt->ipv4_hdr.packet_id << '\n';
     134            0 :   ostrs << "ipv4 fragment_offset: " << (unsigned)pkt->ipv4_hdr.fragment_offset << '\n';
     135            0 :   ostrs << "ipv4 time_to_live: " << (unsigned)pkt->ipv4_hdr.time_to_live << '\n';
     136            0 :   ostrs << "ipv4 next_proto_id: " << (unsigned)pkt->ipv4_hdr.next_proto_id << '\n';
     137            0 :   ostrs << "ipv4 checksum: " << (unsigned)rte_be_to_cpu_16(pkt->ipv4_hdr.hdr_checksum) << '\n';
     138            0 :   std::string srcaddr = get_ipv4_decimal_addr_str(ip_address_binary_to_dotdecimal(rte_be_to_cpu_32(pkt->ipv4_hdr.src_addr)));
     139            0 :   std::string dstaddr = get_ipv4_decimal_addr_str(ip_address_binary_to_dotdecimal(rte_be_to_cpu_32(pkt->ipv4_hdr.dst_addr)));
     140            0 :   ostrs << "src_addr: " << srcaddr << '\n';
     141            0 :   ostrs << "dst_addr: " << dstaddr << '\n';
     142              : 
     143            0 :   ostrs << "------ UDP header ----- \n";
     144            0 :   ostrs << "UDP src_port: " << (unsigned)rte_be_to_cpu_16(pkt->udp_hdr.src_port) << '\n';
     145            0 :   ostrs << "UDP dst_port: " << (unsigned)rte_be_to_cpu_16(pkt->udp_hdr.dst_port) << '\n';
     146            0 :   ostrs << "UDP len: " << (unsigned)rte_be_to_cpu_16(pkt->udp_hdr.dgram_len) << '\n';
     147            0 :   ostrs << "UDP checksum: " << (unsigned)rte_be_to_cpu_16(pkt->udp_hdr.dgram_cksum) << '\n';
     148              : 
     149            0 :   return ostrs.str();
     150            0 : }
     151              : 
     152              : std::string
     153            0 : get_udp_packet_str(struct rte_mbuf* mbuf)
     154              : {
     155            0 :   struct ipv4_udp_packet_hdr* pkt = rte_pktmbuf_mtod(mbuf, struct ipv4_udp_packet_hdr*);
     156            0 :   char* payload = (char*)(pkt);
     157            0 :   std::ostringstream ostrs;
     158              :   std::uint8_t byte;
     159            0 :   for (byte = 0; byte < rte_be_to_cpu_16(pkt->udp_hdr.dgram_len); byte++) {
     160            0 :     hex_digits_to_stream(ostrs, (unsigned)(*(payload + byte)), ' ');
     161              :     // printf("%02x ", *(payload + byte) & 0xFF);
     162              :     // printf("%s", (payload + byte));
     163              :   }
     164            0 :   return ostrs.str();
     165            0 : }
     166              : 
     167              : void
     168            2 : add_file_contents_to_vector(const std::string& filename, std::vector<char>& buffervec)
     169              : {
     170              : 
     171            2 :   char byte = 0x0;
     172              : 
     173            2 :   std::ifstream packetfile;
     174            2 :   packetfile.open(filename, std::ios::binary);
     175              : 
     176            2 :   if (!packetfile) {
     177            0 :     throw ::dunedaq::datahandlinglibs::CannotOpenFile(ERS_HERE, filename);
     178              :   }
     179              : 
     180          228 :   while (packetfile.get(byte)) {
     181          226 :     buffervec.push_back(byte);
     182              :   }
     183              : 
     184            2 :   packetfile.close();
     185            2 : }
     186              : 
     187              : std::vector<std::pair<const void*, int>>
     188            5 : get_ethernet_packets(const std::vector<char>& buffervec)
     189              : {
     190              : 
     191            5 :   std::vector<std::pair<const void*, int>> ethernet_packets;
     192            5 :   const std::vector<uint16_t> allowed_ethertypes{ 0x0800, 0x0806 };
     193              : 
     194           10 :   for (int byte_index = 0; byte_index < buffervec.size();) {
     195            7 :     const auto buf_ptr = &buffervec.at(byte_index);
     196            7 :     auto hdr = reinterpret_cast<const ipv4_udp_packet_hdr*>(buf_ptr);
     197              : 
     198              :     // A sanity check
     199            7 :     bool match = false;
     200            9 :     for (auto allowed_ethertype : allowed_ethertypes) {
     201            8 :       if (hdr->eth_hdr.ether_type == rte_be_to_cpu_16(allowed_ethertype)) {
     202              :         match = true;
     203              :         break;
     204              :       }
     205              :     }
     206              : 
     207            7 :     if (!match) {
     208            1 :       std::stringstream msgstr;
     209            1 :       msgstr << "Ether type in ethernet header (value " << std::hex << rte_be_to_cpu_16(hdr->eth_hdr.ether_type) << std::dec << ") either unknown or unsupported";
     210            1 :       throw dunedaq::dpdklibs::BadPacketHeaderIssue(ERS_HERE, msgstr.str());
     211            1 :     }
     212              : 
     213            6 :     int ipv4_packet_size = rte_be_to_cpu_16(hdr->ipv4_hdr.total_length);
     214            6 :     constexpr int min_packet_size = sizeof(rte_ipv4_hdr) + sizeof(rte_udp_hdr);
     215            6 :     constexpr int max_packet_size = 10000;
     216              : 
     217            6 :     if (ipv4_packet_size < min_packet_size || ipv4_packet_size > max_packet_size) {
     218            1 :       std::stringstream msgstr;
     219            1 :       msgstr << "Calculated IPv4 packet size of " << ipv4_packet_size << " bytes is out of the required range of (" << min_packet_size << ", " << max_packet_size << ") bytes";
     220            1 :       throw dunedaq::dpdklibs::BadPacketHeaderIssue(ERS_HERE, msgstr.str());
     221            1 :     }
     222              : 
     223            5 :     int ethernet_packet_size = sizeof(rte_ether_hdr) + ipv4_packet_size;
     224            5 :     ethernet_packets.emplace_back(std::pair<const void*, int>{ buf_ptr, ethernet_packet_size });
     225            5 :     byte_index += ethernet_packet_size;
     226              :   }
     227              : 
     228            3 :   return ethernet_packets;
     229            7 : }
     230              : 
     231              : void
     232            0 : set_daqethheader_test_values(detdataformats::DAQEthHeader& daqethheader_obj) noexcept
     233              : {
     234            0 :   daqethheader_obj.version = 0;
     235            0 :   daqethheader_obj.det_id = 1;
     236            0 :   daqethheader_obj.crate_id = 2;
     237            0 :   daqethheader_obj.slot_id = 3;
     238            0 :   daqethheader_obj.stream_id = 4;
     239            0 :   daqethheader_obj.reserved = 5;
     240            0 :   daqethheader_obj.seq_id = 6;
     241            0 :   daqethheader_obj.block_length = 7;
     242            0 :   daqethheader_obj.timestamp = 8;
     243            0 : }
     244              : 
     245              : std::string
     246            0 : get_rte_mbuf_str(const rte_mbuf* mbuf) noexcept
     247              : {
     248            0 :   std::stringstream ss;
     249              : 
     250            0 :   ss << "\nrte_mbuf info:";
     251            0 :   ss << "\npkt_len: " << mbuf->pkt_len;
     252            0 :   ss << "\ndata_len: " << mbuf->data_len;
     253            0 :   ss << "\nBuffer address: " << std::hex << mbuf->buf_addr;
     254            0 :   ss << "\nRef count: " << std::dec << rte_mbuf_refcnt_read(mbuf);
     255            0 :   ss << "\nport: " << mbuf->port;
     256            0 :   ss << "\nol_flags: " << std::hex << mbuf->ol_flags;
     257            0 :   ss << "\npacket_type: " << std::dec << mbuf->packet_type;
     258            0 :   ss << "\nl2 type: " << static_cast<int>(mbuf->l2_type);
     259            0 :   ss << "\nl3 type: " << static_cast<int>(mbuf->l3_type);
     260            0 :   ss << "\nl4 type: " << static_cast<int>(mbuf->l4_type);
     261            0 :   ss << "\ntunnel type: " << static_cast<int>(mbuf->tun_type);
     262            0 :   ss << "\nInner l2 type: " << static_cast<int>(mbuf->inner_l2_type);
     263            0 :   ss << "\nInner l3 type: " << static_cast<int>(mbuf->inner_l3_type);
     264            0 :   ss << "\nInner l4 type: " << static_cast<int>(mbuf->inner_l4_type);
     265            0 :   ss << "\nbuf_len: " << mbuf->buf_len;
     266            0 :   ss << "\nl2_len: " << mbuf->l2_len;
     267            0 :   ss << "\nl3_len: " << mbuf->l3_len;
     268            0 :   ss << "\nl4_len: " << mbuf->l4_len;
     269            0 :   ss << "\nouter_l2_len: " << mbuf->outer_l2_len;
     270            0 :   ss << "\nouter_l3_len: " << mbuf->outer_l3_len;
     271            0 :   ss << std::dec;
     272              : 
     273            0 :   return ss.str();
     274            0 : }
     275              : 
     276              : std::string
     277            0 : get_opmon_string(const StreamUID& sid)
     278              : {
     279            0 :   std::stringstream opmonstr;
     280            0 :   opmonstr << "det" << sid.det_id << "_crt" << sid.crate_id << "_slt" << sid.slot_id << "_str" << sid.stream_id;
     281            0 :   return opmonstr.str();
     282            0 : }
     283              : 
     284              : } // namespace udp
     285              : } // namespace dpdklibs
     286              : } // namespace dunedaq
        

Generated by: LCOV version 2.0-1