LCOV - code coverage report
Current view: top level - hermesmodules/plugins - HermesModule.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 97 0
Test Date: 2026-10-11 15:05:20 Functions: 0.0 % 9 0

            Line data    Source code
       1              : /**
       2              :  * @file HermesModule.cpp
       3              :  *
       4              :  * Implementations of HermesModule's functions
       5              :  *
       6              :  * This is part of the DUNE DAQ Software Suite, copyright 2020.
       7              :  * Licensing/copyright details are in the COPYING file that you should have
       8              :  * received with this code.
       9              :  */
      10              : 
      11              : #include "appmodel/HermesModule.hpp"
      12              : #include "appmodel/HermesDataSender.hpp"
      13              : #include "appmodel/IpbusAddressTable.hpp"
      14              : #include "appmodel/appmodelIssues.hpp"
      15              : #include "confmodel/DetectorStream.hpp"
      16              : #include "confmodel/GeoId.hpp"
      17              : #include "confmodel/NetworkDevice.hpp"
      18              : #include "confmodel/Session.hpp"
      19              : 
      20              : #include "HermesModule.hpp"
      21              : #include "hermesmodules/opmon/hermescontroller.pb.h"
      22              : 
      23              : #include "logging/Logging.hpp"
      24              : #include <arpa/inet.h>
      25              : #include <fmt/core.h>
      26              : #include <netinet/ether.h>
      27              : #include <string>
      28              : 
      29              : namespace dunedaq::hermesmodules {
      30              : 
      31              : //-----------------------------------------------------------------------------
      32              : uint64_t
      33            0 : ether_atou64(const std::string& addr_str)
      34              : {
      35            0 :   union
      36              :   {
      37              :     uint64_t result;
      38              :     struct ether_addr address;
      39              :   };
      40            0 :   result = 0;
      41            0 :   struct ether_addr* ptr = ether_aton_r(addr_str.c_str(), &address);
      42            0 :   if (!ptr) {
      43              :     return (~0);
      44              :   }
      45              :   // Big to little endian
      46            0 :   return (__builtin_bswap64(result) >> 16);
      47              : }
      48              : 
      49              : //-----------------------------------------------------------------------------
      50              : uint32_t
      51            0 : ip_atou32(const std::string& addr_str)
      52              : {
      53              :   // Big to little endian
      54            0 :   return __builtin_bswap32(inet_addr(addr_str.c_str()));
      55              : }
      56              : 
      57              : //-----------------------------------------------------------------------------
      58            0 : HermesModule::HermesModule(const std::string& name)
      59            0 :   : dunedaq::appfwk::DAQModule(name)
      60              : {
      61            0 :   register_command("conf", &HermesModule::do_conf);
      62            0 :   register_command("start", &HermesModule::do_start);
      63            0 :   register_command("stop", &HermesModule::do_stop);
      64            0 : }
      65              : 
      66              : //-----------------------------------------------------------------------------
      67              : void
      68            0 : HermesModule::init(std::shared_ptr<appfwk::ConfigurationManager> mcfg)
      69              : {
      70            0 :   uhal::setLogLevelTo(uhal::Error());
      71              : 
      72              :   // Save our DAL for later use by do_conf
      73            0 :   m_dal = mcfg->get_dal<appmodel::HermesModule>(get_name());
      74            0 :   m_session = mcfg->get_session();
      75            0 : }
      76              : 
      77              : //-----------------------------------------------------------------------------
      78              : void
      79            0 : HermesModule::generate_opmon_data()
      80              : {
      81            0 :   opmon::ControllerInfo ginfo;
      82            0 :   ginfo.set_total_amount(m_total_amount);
      83            0 :   ginfo.set_amount_since_last_get_info_call(m_amount_since_last_get_info_call.exchange(0));
      84            0 :   publish(std::move(ginfo));
      85              : 
      86            0 :   if (!m_core_controller)
      87            0 :     return;
      88              : 
      89            0 :   const auto& core_info = m_core_controller->get_info();
      90              : 
      91            0 :   for (uint16_t i(0); i < core_info.n_mgt; ++i) {
      92              : 
      93            0 :     try {
      94            0 :       auto geo_info = m_core_controller->read_link_geo_info(i);
      95            0 :       publish(m_core_controller->read_link_stats(i),
      96            0 :               { { "detector", std::to_string(geo_info.detid) },
      97            0 :                 { "crate", std::to_string(geo_info.crateid) },
      98            0 :                 { "slot", std::to_string(geo_info.slotid) },
      99            0 :                 { "link", std::to_string(i) } });
     100            0 :     } catch (const uhal::exception::exception& e) {
     101            0 :       ers::warning(FailedToRetrieveStats(ERS_HERE, i, e));
     102            0 :     }
     103              : 
     104              :   } // loop over links
     105            0 : }
     106              : 
     107              : //-----------------------------------------------------------------------------
     108              : void
     109            0 : HermesModule::do_conf(const CommandData_t& /*conf_as_json*/)
     110              : {
     111              :   // Create the ipbus
     112            0 :   auto hw = uhal::ConnectionManager::getDevice(m_dal->UID(), m_dal->get_uri(), m_dal->get_address_table()->get_uri());
     113            0 :   hw.setTimeoutPeriod(m_dal->get_timeout_ms());
     114              : 
     115            0 :   m_core_controller = std::make_unique<HermesCoreController>(hw);
     116              : 
     117            0 :   const auto& core_info = m_core_controller->get_info();
     118            0 :   fmt::print("Hermes\n");
     119            0 :   fmt::print("n_mgt {}\n", core_info.n_mgt);
     120            0 :   fmt::print("n_src {}\n", core_info.n_src);
     121            0 :   fmt::print("ref_freq {}\n", core_info.ref_freq);
     122            0 :   std::cout << std::flush;
     123              : 
     124            0 :   auto links = m_dal->get_links();
     125              :   // Size check on link conf
     126            0 :   if (links.size() != core_info.n_mgt) {
     127            0 :     throw FirmwareConfigLinkMismatch(ERS_HERE, links.size(), core_info.n_mgt);
     128              :   }
     129              : 
     130              :   // Sequence id check
     131            0 :   std::set<uint32_t> ids;
     132            0 :   for (const auto l : links) {
     133            0 :     ids.insert(l->get_link_id());
     134              :   }
     135              : 
     136              :   // Look duplicate link ids
     137            0 :   if (ids.size() != links.size()) {
     138            0 :     throw DuplicatedLinkIDs(ERS_HERE, links.size(), ids.size());
     139              :   }
     140              : 
     141              :   // Make sure that the last link id is n_mgt-1
     142            0 :   if (*ids.rbegin() != (core_info.n_mgt - 1)) {
     143            0 :     throw LinkIDConfigurationError(ERS_HERE, *ids.rend(), core_info.n_mgt - 1);
     144              :   }
     145              : 
     146              :   // Check ip address consistency
     147              :   // Redundant check, schema enforces 1:1
     148            0 :   if (m_dal->get_destination()->get_ip_address().size() != 1) {
     149            0 :     throw MultipleIPAddressConfigurationError(
     150            0 :       ERS_HERE, m_dal->get_destination()->UID(), m_dal->get_destination()->get_ip_address().size());
     151              :   }
     152              : 
     153              :   // Redundant check, schema enforces 1:1
     154            0 :   for (const auto& l : links) {
     155            0 :     if (l->get_uses()->get_ip_address().size() != 1) {
     156            0 :       throw MultipleIPAddressConfigurationError(ERS_HERE, l->get_uses()->UID(), l->get_uses()->get_ip_address().size());
     157              :     }
     158              :   }
     159              :   // All good
     160            0 :   for (uint16_t i(0); i < core_info.n_mgt; ++i) {
     161              :     // Put the endpoint in a safe state
     162            0 :     m_core_controller->enable(i, false);
     163              :   }
     164              : 
     165            0 :   m_core_controller->reset();
     166              : 
     167              :   // FIXME: What the hell is this again?
     168            0 :   uint32_t filter_control = 0x07400307;
     169            0 :   for (const auto& l : links) {
     170            0 :     if (l->is_excluded(*m_session)) {
     171            0 :       continue;
     172              :     }
     173              : 
     174            0 :     m_enabled_link_ids.push_back(l->get_link_id());
     175              : 
     176            0 :     m_core_controller->config_udp(l->get_link_id(),
     177            0 :                                   ether_atou64(l->get_uses()->get_mac_address()),
     178            0 :                                   ip_atou32(l->get_uses()->get_ip_address().at(0)),
     179            0 :                                   l->get_port(),
     180            0 :                                   ether_atou64(m_dal->get_destination()->get_mac_address()),
     181            0 :                                   ip_atou32(m_dal->get_destination()->get_ip_address().at(0)),
     182            0 :                                   l->get_port(),
     183              :                                   filter_control);
     184              : 
     185              :     // Get the first DetectorStream
     186              :     // and use it for the geo id information.
     187            0 :     const confmodel::DetectorStream* source = l->get_streams()[0];
     188            0 :     m_core_controller->config_mux(l->get_link_id(),
     189            0 :                                   source->get_geo_id()->get_detector_id(),
     190            0 :                                   source->get_geo_id()->get_crate_id(),
     191            0 :                                   source->get_geo_id()->get_slot_id());
     192              :   }
     193            0 : }
     194              : 
     195              : void
     196            0 : HermesModule::do_start(const CommandData_t& /*d*/)
     197              : {
     198              : 
     199            0 :   for (auto id : m_enabled_link_ids) {
     200              :     // Put the endpoint in a safe state
     201            0 :     m_core_controller->enable(id, true);
     202              :   }
     203              : 
     204            0 :   for (auto id : m_enabled_link_ids) {
     205              :     // Put the endpoint in a safe state
     206            0 :     m_core_controller->is_link_in_error(id, true);
     207              :   }
     208              : 
     209              :   // for ( uint16_t i(0); i<core_info.n_mgt; ++i){
     210              :   //   // Put the endpoint in a safe state
     211              :   //   m_core_controller->enable(i, true);
     212              :   // }
     213              : 
     214              :   // for ( uint16_t i(0); i<core_info.n_mgt; ++i){
     215              :   //   // Put the endpoint in a safe state
     216              :   //   m_core_controller->is_link_in_error(i);
     217              :   // }
     218            0 : }
     219              : 
     220              : void
     221            0 : HermesModule::do_stop(const CommandData_t& /*d*/)
     222              : {
     223              : 
     224            0 :   for (auto id : m_enabled_link_ids) {
     225              :     // Put the endpoint in a safe state
     226            0 :     m_core_controller->enable(id, false);
     227              :   }
     228            0 : }
     229              : 
     230              : } // namespace dunedaq::hermesmodules
     231              : 
     232            0 : DEFINE_DUNE_DAQ_MODULE(dunedaq::hermesmodules::HermesModule)
        

Generated by: LCOV version 2.0-1