From 8bf975e87c56de12307659c5483c2a2a8be0d2f4 Mon Sep 17 00:00:00 2001 From: Miguel Company Date: Fri, 4 Oct 2024 07:43:55 +0200 Subject: [PATCH] Fix issues in Dynamic Network Interfaces (#5282) * Refs #21690. Parse `--rescan` argument on communication applications. Signed-off-by: Miguel Company * Refs #21690. Implement rescan mechanism. Signed-off-by: Miguel Company * Refs #21690. Add docker infrastructure. Signed-off-by: Miguel Company * Refs #21690. Add CMake infrastructure. Signed-off-by: Miguel Company * Refs #21690. Ensure same domain and topic name are used. Signed-off-by: Miguel Company * Refs #21690. Add `--loops` argument to publisher. Signed-off-by: Miguel Company * Refs #21690. Publisher exits after publishing all samples. Signed-off-by: Miguel Company * Refs #21690. Improve subscriber script. Signed-off-by: Miguel Company * Refs #21690. Add test. Signed-off-by: Miguel Company * Refs #21690. Make publisher wait subscriber. Signed-off-by: Miguel Company * Refs #21690. Possible fix. Signed-off-by: Miguel Company * Refs #21690. Clear locators before recalculating them. Signed-off-by: Miguel Company * Refs #21690. Move local participant proxy update to PDP. Signed-off-by: Miguel Company * Refs #21690. Improve new method's logic. Signed-off-by: Miguel Company * Refs #21690. Include what you use. Signed-off-by: Miguel Company * Refs #21690. Add empty method to update endpoint locators. Signed-off-by: Miguel Company * Refs #21690. Add implementation for `update_endpoint_locators_if_default_nts`. Signed-off-by: Miguel Company * Refs #21690. Compare against old default locators. Signed-off-by: Miguel Company * Refs #21690. Update locators in attributes. Signed-off-by: Miguel Company * Refs #17283. Avoid early return on `PDP::local_participant_attributes_update_nts`. Signed-off-by: Miguel Company * Refs #17283. Apply suggestions. Signed-off-by: Miguel Company --------- Signed-off-by: Miguel Company (cherry picked from commit 91bd7c857d8760f1a523e878368f895fbc41a955) # Conflicts: # include/fastdds/rtps/builtin/discovery/participant/PDP.h # src/cpp/rtps/builtin/discovery/participant/PDP.cpp # src/cpp/rtps/participant/RTPSParticipantImpl.cpp # test/dds/communication/PublisherModule.hpp # test/dds/communication/SubscriberModule.hpp # test/dds/communication/security/PublisherModule.hpp # test/dds/communication/security/SubscriberModule.hpp --- .../rtps/builtin/discovery/participant/PDP.h | 49 ++++++ .../builtin/discovery/participant/PDP.cpp | 161 ++++++++++++++++++ .../rtps/participant/RTPSParticipantImpl.cpp | 22 +++ test/dds/communication/CMakeLists.txt | 4 + test/dds/communication/PubSubMain.cpp | 6 +- test/dds/communication/PublisherMain.cpp | 28 ++- test/dds/communication/PublisherModule.cpp | 20 +++ test/dds/communication/PublisherModule.hpp | 20 ++- test/dds/communication/SubscriberMain.cpp | 19 ++- test/dds/communication/SubscriberModule.cpp | 23 ++- test/dds/communication/SubscriberModule.hpp | 21 ++- .../communication/dyn_network/CMakeLists.txt | 61 +++++++ test/dds/communication/dyn_network/Dockerfile | 27 +++ .../dynamic_interfaces.compose.yml | 42 +++++ .../dyn_network/launch_subscriber.bash | 33 ++++ .../communication/security/PublisherMain.cpp | 16 +- .../security/PublisherModule.cpp | 20 +++ .../security/PublisherModule.hpp | 19 ++- .../communication/security/SubscriberMain.cpp | 15 +- .../security/SubscriberModule.cpp | 25 ++- .../security/SubscriberModule.hpp | 19 ++- 21 files changed, 613 insertions(+), 37 deletions(-) create mode 100644 test/dds/communication/dyn_network/CMakeLists.txt create mode 100644 test/dds/communication/dyn_network/Dockerfile create mode 100644 test/dds/communication/dyn_network/dynamic_interfaces.compose.yml create mode 100755 test/dds/communication/dyn_network/launch_subscriber.bash diff --git a/include/fastdds/rtps/builtin/discovery/participant/PDP.h b/include/fastdds/rtps/builtin/discovery/participant/PDP.h index f9eb5f2731b..bf5d06e7142 100644 --- a/include/fastdds/rtps/builtin/discovery/participant/PDP.h +++ b/include/fastdds/rtps/builtin/discovery/participant/PDP.h @@ -22,10 +22,14 @@ #ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC #include +#include #include #include #include +#include +#include +<<<<<<< HEAD:include/fastdds/rtps/builtin/discovery/participant/PDP.h #include #include #include @@ -37,6 +41,35 @@ #include #include #include +======= +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +>>>>>>> 91bd7c857 (Fix issues in Dynamic Network Interfaces (#5282)):src/cpp/rtps/builtin/discovery/participant/PDP.h namespace eprosima { @@ -51,6 +84,7 @@ struct IProxyObserver; namespace rtps { +<<<<<<< HEAD:include/fastdds/rtps/builtin/discovery/participant/PDP.h class PDPServerListener; class PDPEndpoints; @@ -68,8 +102,13 @@ namespace rtps { class RTPSWriter; class RTPSReader; +======= +class BaseWriter; +class BaseReader; +>>>>>>> 91bd7c857 (Fix issues in Dynamic Network Interfaces (#5282)):src/cpp/rtps/builtin/discovery/participant/PDP.h class WriterHistory; class ReaderHistory; +struct RTPSParticipantAllocationAttributes; class RTPSParticipantImpl; class RTPSParticipantListener; class BuiltinProtocols; @@ -79,6 +118,7 @@ class ReaderProxyData; class WriterProxyData; class ParticipantProxyData; class ReaderListener; +class PDPEndpoints; class PDPListener; class PDPServerListener; class ITopicPayloadPool; @@ -493,6 +533,15 @@ class PDP : public fastdds::statistics::rtps::IProxyQueryable #endif // FASTDDS_STATISTICS + virtual void local_participant_attributes_update_nts( + const RTPSParticipantAttributes& new_atts); + + virtual void update_endpoint_locators_if_default_nts( + const std::vector& writers, + const std::vector& readers, + const RTPSParticipantAttributes& old_atts, + const RTPSParticipantAttributes& new_atts); + protected: //!Pointer to the builtin protocols object. diff --git a/src/cpp/rtps/builtin/discovery/participant/PDP.cpp b/src/cpp/rtps/builtin/discovery/participant/PDP.cpp index 6aaa543991f..025aaedc7fb 100644 --- a/src/cpp/rtps/builtin/discovery/participant/PDP.cpp +++ b/src/cpp/rtps/builtin/discovery/participant/PDP.cpp @@ -66,6 +66,52 @@ #include #include +<<<<<<< HEAD +======= +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if HAVE_SECURITY +#include +#endif // if HAVE_SECURITY +#include +#include +#include +#include + +>>>>>>> 91bd7c857 (Fix issues in Dynamic Network Interfaces (#5282)) namespace eprosima { namespace fastrtps { namespace rtps { @@ -1662,6 +1708,121 @@ void PDP::add_builtin_security_attributes( #endif // HAVE_SECURITY +void PDP::local_participant_attributes_update_nts( + const RTPSParticipantAttributes& new_atts) +{ + // Update user data + auto participant_data = getLocalParticipantProxyData(); + participant_data->m_userData.data_vec(new_atts.userData); + + // If we are intraprocess only, we do not need to update locators + bool announce_locators = !mp_RTPSParticipant->is_intraprocess_only(); + if (announce_locators) + { + // Clear all locators + participant_data->metatraffic_locators.unicast.clear(); + participant_data->metatraffic_locators.multicast.clear(); + participant_data->default_locators.unicast.clear(); + participant_data->default_locators.multicast.clear(); + + // Update default locators + for (const Locator_t& loc : new_atts.defaultUnicastLocatorList) + { + participant_data->default_locators.add_unicast_locator(loc); + } + for (const Locator_t& loc : new_atts.defaultMulticastLocatorList) + { + participant_data->default_locators.add_multicast_locator(loc); + } + + // Update metatraffic locators + for (const auto& locator : new_atts.builtin.metatrafficUnicastLocatorList) + { + participant_data->metatraffic_locators.add_unicast_locator(locator); + } + if (!new_atts.builtin.avoid_builtin_multicast || participant_data->metatraffic_locators.unicast.empty()) + { + for (const auto& locator : new_atts.builtin.metatrafficMulticastLocatorList) + { + participant_data->metatraffic_locators.add_multicast_locator(locator); + } + } + + fastdds::rtps::network::external_locators::add_external_locators(*participant_data, + new_atts.builtin.metatraffic_external_unicast_locators, + new_atts.default_external_unicast_locators); + } +} + +void PDP::update_endpoint_locators_if_default_nts( + const std::vector& writers, + const std::vector& readers, + const RTPSParticipantAttributes& old_atts, + const RTPSParticipantAttributes& new_atts) +{ + // Check if default locators have changed + const auto& old_default_unicast = old_atts.defaultUnicastLocatorList; + const auto& old_default_multicast = old_atts.defaultMulticastLocatorList; + const auto& new_default_unicast = new_atts.defaultUnicastLocatorList; + const auto& new_default_multicast = new_atts.defaultMulticastLocatorList; + + // Early return if there is no change in default unicast locators + if ((old_default_unicast == new_default_unicast) && + (old_default_multicast == new_default_multicast)) + { + return; + } + + // Update proxies of endpoints with default configured locators + EDP* edp = get_edp(); + for (BaseWriter* writer : writers) + { + if ((old_default_multicast == writer->getAttributes().multicastLocatorList) && + (old_default_unicast == writer->getAttributes().unicastLocatorList)) + { + writer->getAttributes().multicastLocatorList = new_default_multicast; + writer->getAttributes().unicastLocatorList = new_default_unicast; + + WriterProxyData* wdata = nullptr; + GUID_t participant_guid; + wdata = addWriterProxyData(writer->getGuid(), participant_guid, + [](WriterProxyData* proxy, bool is_update, const ParticipantProxyData& participant) + { + static_cast(is_update); + assert(is_update); + + proxy->set_locators(participant.default_locators); + return true; + }); + assert(wdata != nullptr); + edp->process_writer_proxy_data(writer, wdata); + } + } + for (BaseReader* reader : readers) + { + if ((old_default_multicast == reader->getAttributes().multicastLocatorList) && + (old_default_unicast == reader->getAttributes().unicastLocatorList)) + { + reader->getAttributes().multicastLocatorList = new_default_multicast; + reader->getAttributes().unicastLocatorList = new_default_unicast; + + ReaderProxyData* rdata = nullptr; + GUID_t participant_guid; + rdata = addReaderProxyData(reader->getGuid(), participant_guid, + [](ReaderProxyData* proxy, bool is_update, const ParticipantProxyData& participant) + { + static_cast(is_update); + assert(is_update); + + proxy->set_locators(participant.default_locators); + return true; + }); + assert(rdata != nullptr); + edp->process_reader_proxy_data(reader, rdata); + } + } +} + } /* namespace rtps */ } /* namespace fastrtps */ } /* namespace eprosima */ diff --git a/src/cpp/rtps/participant/RTPSParticipantImpl.cpp b/src/cpp/rtps/participant/RTPSParticipantImpl.cpp index 921257b3926..bc017513028 100644 --- a/src/cpp/rtps/participant/RTPSParticipantImpl.cpp +++ b/src/cpp/rtps/participant/RTPSParticipantImpl.cpp @@ -1539,9 +1539,16 @@ void RTPSParticipantImpl::update_attributes( // Check if new interfaces have been added if (internal_metatraffic_locators_) { +<<<<<<< HEAD LocatorList_t metatraffic_unicast_locator_list = m_att.builtin.metatrafficUnicastLocatorList; get_default_metatraffic_locators(); if (!(metatraffic_unicast_locator_list == m_att.builtin.metatrafficUnicastLocatorList)) +======= + LocatorList_t metatraffic_unicast_locator_list = temp_atts.builtin.metatrafficUnicastLocatorList; + temp_atts.builtin.metatrafficUnicastLocatorList.clear(); + get_default_metatraffic_locators(temp_atts); + if (!(metatraffic_unicast_locator_list == temp_atts.builtin.metatrafficUnicastLocatorList)) +>>>>>>> 91bd7c857 (Fix issues in Dynamic Network Interfaces (#5282)) { local_interfaces_changed = true; EPROSIMA_LOG_INFO(RTPS_PARTICIPANT, m_att.getName() << " updated its metatraffic locators"); @@ -1549,9 +1556,16 @@ void RTPSParticipantImpl::update_attributes( } if (internal_default_locators_) { +<<<<<<< HEAD LocatorList_t default_unicast_locator_list = m_att.defaultUnicastLocatorList; get_default_unicast_locators(); if (!(default_unicast_locator_list == m_att.defaultUnicastLocatorList)) +======= + LocatorList_t default_unicast_locator_list = temp_atts.defaultUnicastLocatorList; + temp_atts.defaultUnicastLocatorList.clear(); + get_default_unicast_locators(temp_atts); + if (!(default_unicast_locator_list == temp_atts.defaultUnicastLocatorList)) +>>>>>>> 91bd7c857 (Fix issues in Dynamic Network Interfaces (#5282)) { local_interfaces_changed = true; EPROSIMA_LOG_INFO(RTPS_PARTICIPANT, @@ -1673,7 +1687,9 @@ void RTPSParticipantImpl::update_attributes( { std::lock_guard lock(*pdp->getMutex()); + pdp->local_participant_attributes_update_nts(temp_atts); +<<<<<<< HEAD // Update user data auto local_participant_proxy_data = pdp->getLocalParticipantProxyData(); local_participant_proxy_data->m_userData.data_vec(m_att.userData); @@ -1692,6 +1708,12 @@ void RTPSParticipantImpl::update_attributes( for (auto locator : m_att.defaultUnicastLocatorList) { local_participant_proxy_data->default_locators.add_unicast_locator(locator); +======= + if (local_interfaces_changed && internal_default_locators_) + { + std::lock_guard _(endpoints_list_mutex); + pdp->update_endpoint_locators_if_default_nts(m_userWriterList, m_userReaderList, m_att, temp_atts); +>>>>>>> 91bd7c857 (Fix issues in Dynamic Network Interfaces (#5282)) } if (local_interfaces_changed) diff --git a/test/dds/communication/CMakeLists.txt b/test/dds/communication/CMakeLists.txt index d2696757422..37e11ef4f00 100644 --- a/test/dds/communication/CMakeLists.txt +++ b/test/dds/communication/CMakeLists.txt @@ -314,3 +314,7 @@ if(Python3_Interpreter_FOUND) endif() endif() + +if(UNIX AND NOT(APPLE) AND NOT(QNXNTO) AND NOT(ANDROID)) + add_subdirectory(dyn_network) +endif() diff --git a/test/dds/communication/PubSubMain.cpp b/test/dds/communication/PubSubMain.cpp index 46553c9f64b..11ea78de1ee 100644 --- a/test/dds/communication/PubSubMain.cpp +++ b/test/dds/communication/PubSubMain.cpp @@ -52,7 +52,7 @@ void publisher_run( publisher->wait_discovery(wait); } - publisher->run(samples, loops, interval); + publisher->run(samples, 0, loops, interval); } int main( @@ -197,7 +197,7 @@ int main( DomainParticipantFactory::get_instance()->load_XML_profiles_file(xml_file); } - SubscriberModule subscriber(publishers, samples, fixed_type, zero_copy); + SubscriberModule subscriber(publishers, samples, fixed_type, zero_copy, false, false); PublisherModule publisher(exit_on_lost_liveliness, fixed_type, zero_copy); uint32_t result = 1; @@ -208,7 +208,7 @@ int main( if (subscriber.init(seed, magic)) { - result = subscriber.run(notexit, timeout) ? 0 : -1; + result = subscriber.run(notexit, 0, timeout) ? 0 : -1; } publisher_thread.join(); diff --git a/test/dds/communication/PublisherMain.cpp b/test/dds/communication/PublisherMain.cpp index 0d72b20ae5b..3124e1c592d 100644 --- a/test/dds/communication/PublisherMain.cpp +++ b/test/dds/communication/PublisherMain.cpp @@ -29,9 +29,11 @@ using namespace eprosima::fastdds::dds; * --seed * --wait * --samples + * --loops + * --interval * --magic * --xmlfile - * --interval + * --rescan */ int main( @@ -46,7 +48,9 @@ int main( uint32_t wait = 0; char* xml_file = nullptr; uint32_t samples = 4; + uint32_t loops = 0; uint32_t interval = 250; + uint32_t rescan_interval_seconds = 0; std::string magic; while (arg_count < argc) @@ -93,6 +97,16 @@ int main( samples = strtol(argv[arg_count], nullptr, 10); } + else if (strcmp(argv[arg_count], "--loops") == 0) + { + if (++arg_count >= argc) + { + std::cout << "--loops expects a parameter" << std::endl; + return -1; + } + + loops = strtol(argv[arg_count], nullptr, 10); + } else if (strcmp(argv[arg_count], "--interval") == 0) { if (++arg_count >= argc) @@ -123,6 +137,16 @@ int main( xml_file = argv[arg_count]; } + else if (strcmp(argv[arg_count], "--rescan") == 0) + { + if (++arg_count >= argc) + { + std::cout << "--rescan expects a parameter" << std::endl; + return -1; + } + + rescan_interval_seconds = strtol(argv[arg_count], nullptr, 10); + } else { std::cout << "Wrong argument " << argv[arg_count] << std::endl; @@ -146,7 +170,7 @@ int main( publisher.wait_discovery(wait); } - publisher.run(samples, 0, interval); + publisher.run(samples, rescan_interval_seconds, loops, interval); return 0; } diff --git a/test/dds/communication/PublisherModule.cpp b/test/dds/communication/PublisherModule.cpp index d798a5c8434..f43a4c3062d 100644 --- a/test/dds/communication/PublisherModule.cpp +++ b/test/dds/communication/PublisherModule.cpp @@ -134,6 +134,7 @@ void PublisherModule::wait_discovery( void PublisherModule::run( uint32_t samples, + const uint32_t rescan_interval, const uint32_t loops, uint32_t interval) { @@ -141,6 +142,22 @@ void PublisherModule::run( uint16_t index = 1; void* sample = nullptr; + std::thread net_rescan_thread([this, rescan_interval]() + { + if (rescan_interval > 0) + { + auto interval = std::chrono::seconds(rescan_interval); + while (run_) + { + std::this_thread::sleep_for(interval); + if (run_) + { + participant_->set_qos(participant_->get_qos()); + } + } + } + }); + while (run_ && (loops == 0 || loops > current_loop)) { if (zero_copy_) @@ -187,6 +204,9 @@ void PublisherModule::run( std::this_thread::sleep_for(std::chrono::milliseconds(interval)); } + + run_ = false; + net_rescan_thread.join(); } void PublisherModule::on_publication_matched( diff --git a/test/dds/communication/PublisherModule.hpp b/test/dds/communication/PublisherModule.hpp index fb144821a0a..0f8905c13ff 100644 --- a/test/dds/communication/PublisherModule.hpp +++ b/test/dds/communication/PublisherModule.hpp @@ -19,6 +19,15 @@ #ifndef TEST_DDS_COMMUNICATION_PUBLISHERMODULE_HPP #define TEST_DDS_COMMUNICATION_PUBLISHERMODULE_HPP +<<<<<<< HEAD +======= +#include +#include +#include +#include + +#include +>>>>>>> 91bd7c857 (Fix issues in Dynamic Network Interfaces (#5282)) #include #include #include @@ -41,8 +50,8 @@ class PublisherModule PublisherModule( bool exit_on_lost_liveliness, - bool fixed_type = false, - bool zero_copy = false) + bool fixed_type, + bool zero_copy) : exit_on_lost_liveliness_(exit_on_lost_liveliness) , fixed_type_(zero_copy || fixed_type) // If zero copy active, fixed type is required , zero_copy_(zero_copy) @@ -80,8 +89,9 @@ class PublisherModule void run( uint32_t samples, - uint32_t loops = 0, - uint32_t interval = 250); + const uint32_t rescan_interval, + uint32_t loops, + uint32_t interval); private: @@ -93,7 +103,7 @@ class PublisherModule bool exit_on_lost_liveliness_ = false; bool fixed_type_ = false; bool zero_copy_ = false; - bool run_ = true; + std::atomic_bool run_{true}; DomainParticipant* participant_ = nullptr; TypeSupport type_; Publisher* publisher_ = nullptr; diff --git a/test/dds/communication/SubscriberMain.cpp b/test/dds/communication/SubscriberMain.cpp index cb96f16ffb8..eee9b3e0e1e 100644 --- a/test/dds/communication/SubscriberMain.cpp +++ b/test/dds/communication/SubscriberMain.cpp @@ -26,13 +26,15 @@ using namespace eprosima::fastdds::dds; * --notexit * --fixed_type * --zero_copy + * --succeed_on_timeout * --seed * --samples * --magic + * --timeout * --xmlfile * --publishers - * --succeed_on_timeout - * --timeout + * --die_on_data_received + * --rescan */ int main( @@ -49,6 +51,7 @@ int main( uint32_t samples = 4; uint32_t publishers = 1; uint32_t timeout = 86400000; // 24 h in ms + uint32_t rescan_interval_seconds = 0; char* xml_file = nullptr; std::string magic; @@ -134,6 +137,16 @@ int main( { die_on_data_received = true; } + else if (strcmp(argv[arg_count], "--rescan") == 0) + { + if (++arg_count >= argc) + { + std::cout << "--rescan expects a parameter" << std::endl; + return -1; + } + + rescan_interval_seconds = strtol(argv[arg_count], nullptr, 10); + } else { std::cout << "Wrong argument " << argv[arg_count] << std::endl; @@ -152,7 +165,7 @@ int main( if (subscriber.init(seed, magic)) { - return subscriber.run(notexit, timeout) ? 0 : -1; + return subscriber.run(notexit, rescan_interval_seconds, timeout) ? 0 : -1; } return -1; diff --git a/test/dds/communication/SubscriberModule.cpp b/test/dds/communication/SubscriberModule.cpp index 77992bbd823..d0336e6dc73 100644 --- a/test/dds/communication/SubscriberModule.cpp +++ b/test/dds/communication/SubscriberModule.cpp @@ -132,17 +132,35 @@ bool SubscriberModule::init( bool SubscriberModule::run( bool notexit, + const uint32_t rescan_interval, uint32_t timeout) { - return run_for(notexit, std::chrono::milliseconds(timeout)); + return run_for(notexit, rescan_interval, std::chrono::milliseconds(timeout)); } bool SubscriberModule::run_for( bool notexit, + const uint32_t rescan_interval, const std::chrono::milliseconds& timeout) { bool returned_value = false; + std::thread net_rescan_thread([this, rescan_interval]() + { + if (rescan_interval > 0) + { + auto interval = std::chrono::seconds(rescan_interval); + while (run_) + { + std::this_thread::sleep_for(interval); + if (run_) + { + participant_->set_qos(participant_->get_qos()); + } + } + } + }); + while (notexit && run_) { std::this_thread::sleep_for(std::chrono::milliseconds(250)); @@ -192,6 +210,9 @@ bool SubscriberModule::run_for( returned_value = false; } + run_ = false; + net_rescan_thread.join(); + return returned_value; } diff --git a/test/dds/communication/SubscriberModule.hpp b/test/dds/communication/SubscriberModule.hpp index 901e3137dc7..62226538c8c 100644 --- a/test/dds/communication/SubscriberModule.hpp +++ b/test/dds/communication/SubscriberModule.hpp @@ -19,6 +19,7 @@ #ifndef TEST_COMMUNICATION_SUBSCRIBER_HPP #define TEST_COMMUNICATION_SUBSCRIBER_HPP +<<<<<<< HEAD #include #include #include @@ -28,9 +29,13 @@ #include "types/HelloWorldPubSubTypes.h" #include +======= +#include +#include +>>>>>>> 91bd7c857 (Fix issues in Dynamic Network Interfaces (#5282)) #include #include -#include +#include namespace eprosima { namespace fastdds { @@ -44,10 +49,10 @@ class SubscriberModule SubscriberModule( const uint32_t publishers, const uint32_t max_number_samples, - bool fixed_type = false, - bool zero_copy = false, - bool succeed_on_timeout = false, - bool die_on_data_received = false) + bool fixed_type, + bool zero_copy, + bool succeed_on_timeout, + bool die_on_data_received) : publishers_(publishers) , max_number_samples_(max_number_samples) , fixed_type_(zero_copy || fixed_type) // If zero copy active, fixed type is required @@ -86,10 +91,12 @@ class SubscriberModule bool run( bool notexit, - uint32_t timeout = 86400000); + const uint32_t rescan_interval, + uint32_t timeout); bool run_for( bool notexit, + const uint32_t rescan_interval, const std::chrono::milliseconds& timeout); private: @@ -103,7 +110,7 @@ class SubscriberModule std::map number_samples_; bool fixed_type_ = false; bool zero_copy_ = false; - bool run_ = true; + std::atomic_bool run_{true}; bool succeed_on_timeout_ = false; DomainParticipant* participant_ = nullptr; TypeSupport type_; diff --git a/test/dds/communication/dyn_network/CMakeLists.txt b/test/dds/communication/dyn_network/CMakeLists.txt new file mode 100644 index 00000000000..0d95ac665e0 --- /dev/null +++ b/test/dds/communication/dyn_network/CMakeLists.txt @@ -0,0 +1,61 @@ +# Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +message(STATUS "Configuring dynamic network interfaces tests") + +# Find docker +find_program(DOCKER_EXECUTABLE docker) +if(NOT DOCKER_EXECUTABLE) + message(FATAL_ERROR "Docker not found") +endif() + +set(SHELL_EXECUTABLE "") +set(TINYXML2_LIB_DIR_COMPOSE_VOLUME "") +set(TINYXML2_LIB_DIR_COMPOSE_LD_LIBRARY_PATH "") + +# Linux configurations +if(UNIX AND NOT(APPLE) AND NOT(QNXNTO) AND NOT(ANDROID)) + # Find bash + find_program(BASH_EXECUTABLE bash) + if(NOT BASH_EXECUTABLE) + message(FATAL_ERROR "bash not found") + endif() + + set(SHELL_EXECUTABLE ${BASH_EXECUTABLE}) + +# Windows configurations +elseif(WIN32) + # We don't know which docker image to use for Windows yet + message(FATAL_ERROR "Windows not supported yet") + +# Unsupported platform +else() + message(FATAL_ERROR "Unsupported platform") +endif() + +# Configure TinyXML2 library path if installed in user library path +if(NOT (TINYXML2_FROM_SOURCE OR TINYXML2_FROM_THIRDPARTY)) + get_filename_component(TINYXML2_LIB_DIR ${TINYXML2_LIBRARY} DIRECTORY) + set(TINYXML2_LIB_DIR_COMPOSE_VOLUME "- ${TINYXML2_LIB_DIR}:${CMAKE_INSTALL_PREFIX}/${DATA_INSTALL_DIR}/fastdds:ro") + set(TINYXML2_LIB_DIR_COMPOSE_LD_LIBRARY_PATH ":${CMAKE_INSTALL_PREFIX}/${DATA_INSTALL_DIR}/fastdds") +endif() + +configure_file(Dockerfile + ${CMAKE_CURRENT_BINARY_DIR}/Dockerfile @ONLY) +configure_file(dynamic_interfaces.compose.yml + ${CMAKE_CURRENT_BINARY_DIR}/dynamic_interfaces.compose.yml @ONLY) +configure_file(launch_subscriber.bash + ${CMAKE_CURRENT_BINARY_DIR}/launch_subscriber.bash @ONLY) +add_test(NAME dds.communication.dynamic_interfaces + COMMAND ${DOCKER_EXECUTABLE} compose -f ${CMAKE_CURRENT_BINARY_DIR}/dynamic_interfaces.compose.yml up + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/test/dds/communication/dyn_network/Dockerfile b/test/dds/communication/dyn_network/Dockerfile new file mode 100644 index 00000000000..ebdcae10bba --- /dev/null +++ b/test/dds/communication/dyn_network/Dockerfile @@ -0,0 +1,27 @@ +# Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Tag, branch, or commit in github.com/eProsima/DDS-Suite +ARG ubuntu_version=22.04 +FROM ubuntu:$ubuntu_version AS ubuntu-net-tools + +# Needed for a dependency that forces to set timezone +ENV TZ=Europe/Madrid +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +# Avoids using interactions during building +ENV DEBIAN_FRONTEND=noninteractive + +# Install apt dependencies +RUN apt-get update && apt-get install --yes net-tools && rm -rf /var/lib/apt/lists/* diff --git a/test/dds/communication/dyn_network/dynamic_interfaces.compose.yml b/test/dds/communication/dyn_network/dynamic_interfaces.compose.yml new file mode 100644 index 00000000000..9d45abbbc48 --- /dev/null +++ b/test/dds/communication/dyn_network/dynamic_interfaces.compose.yml @@ -0,0 +1,42 @@ +# Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +version: "3" + +services: + publisher: + image: ubuntu:22.04 + volumes: + - @PROJECT_BINARY_DIR@:@PROJECT_BINARY_DIR@ + - @fastcdr_LIB_DIR@:@fastcdr_LIB_DIR@ + @TINYXML2_LIB_DIR_COMPOSE_VOLUME@ + environment: + LD_LIBRARY_PATH: @PROJECT_BINARY_DIR@/src/cpp:@fastcdr_LIB_DIR@@TINYXML2_LIB_DIR_COMPOSE_LD_LIBRARY_PATH@ + EXAMPLE_DIR: @PROJECT_BINARY_DIR@/test/dds/communication + command: @SHELL_EXECUTABLE@ -c "$${EXAMPLE_DIR}/DDSCommunicationPublisher --xmlfile $${EXAMPLE_DIR}/simple_reliable_profile.xml --wait 1 --samples 10 --loops 1 --seed 0 --magic T" + + subscriber: + build: . + image: ubuntu-net-tools:22.04 + privileged: true + volumes: + - @PROJECT_BINARY_DIR@:@PROJECT_BINARY_DIR@ + - @fastcdr_LIB_DIR@:@fastcdr_LIB_DIR@ + @TINYXML2_LIB_DIR_COMPOSE_VOLUME@ + environment: + LD_LIBRARY_PATH: @PROJECT_BINARY_DIR@/src/cpp:@fastcdr_LIB_DIR@@TINYXML2_LIB_DIR_COMPOSE_LD_LIBRARY_PATH@ + EXAMPLE_DIR: @PROJECT_BINARY_DIR@/test/dds/communication + working_dir: @PROJECT_BINARY_DIR@/test/dds/communication + command: @SHELL_EXECUTABLE@ "dyn_network/launch_subscriber.bash" + depends_on: + - publisher diff --git a/test/dds/communication/dyn_network/launch_subscriber.bash b/test/dds/communication/dyn_network/launch_subscriber.bash new file mode 100755 index 00000000000..9ee62e1338b --- /dev/null +++ b/test/dds/communication/dyn_network/launch_subscriber.bash @@ -0,0 +1,33 @@ +# Copyright 2019 Proyectos y Sistemas de Mantenimiento SL (eProsima). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#!/bin/bash + +# Note: This script is intended to be used in a privileged container, since it requires to bring down and up the eth0 interface. + +echo "Putting down eth0 interface..." +ifconfig eth0 down + +echo "Launching subscriber..." +${EXAMPLE_DIR}/DDSCommunicationSubscriber --xmlfile ${EXAMPLE_DIR}/simple_reliable_profile.xml --samples 10 --seed 0 --magic T --rescan 2 & +subs_pid=$! +echo "Subscriber launched." + +echo "Waiting 2 seconds and bring up eth0 interface..." +sleep 2s +ifconfig eth0 up +echo "eth0 interface is up." + +echo "Waiting 3s for the subscriber (process id $subs_pid) to finish..." +wait $subs_pid diff --git a/test/dds/communication/security/PublisherMain.cpp b/test/dds/communication/security/PublisherMain.cpp index 0d72b20ae5b..75ef39f8ff3 100644 --- a/test/dds/communication/security/PublisherMain.cpp +++ b/test/dds/communication/security/PublisherMain.cpp @@ -29,9 +29,10 @@ using namespace eprosima::fastdds::dds; * --seed * --wait * --samples + * --interval * --magic * --xmlfile - * --interval + * --rescan */ int main( @@ -47,6 +48,7 @@ int main( char* xml_file = nullptr; uint32_t samples = 4; uint32_t interval = 250; + uint32_t rescan_interval_seconds = 0; std::string magic; while (arg_count < argc) @@ -123,6 +125,16 @@ int main( xml_file = argv[arg_count]; } + else if (strcmp(argv[arg_count], "--rescan") == 0) + { + if (++arg_count >= argc) + { + std::cout << "--rescan expects a parameter" << std::endl; + return -1; + } + + rescan_interval_seconds = strtol(argv[arg_count], nullptr, 10); + } else { std::cout << "Wrong argument " << argv[arg_count] << std::endl; @@ -146,7 +158,7 @@ int main( publisher.wait_discovery(wait); } - publisher.run(samples, 0, interval); + publisher.run(samples, rescan_interval_seconds, 0, interval); return 0; } diff --git a/test/dds/communication/security/PublisherModule.cpp b/test/dds/communication/security/PublisherModule.cpp index 3d9477ede9b..28e6eb92c6e 100644 --- a/test/dds/communication/security/PublisherModule.cpp +++ b/test/dds/communication/security/PublisherModule.cpp @@ -134,6 +134,7 @@ void PublisherModule::wait_discovery( void PublisherModule::run( uint32_t samples, + const uint32_t rescan_interval, const uint32_t loops, uint32_t interval) { @@ -141,6 +142,22 @@ void PublisherModule::run( uint16_t index = 1; void* sample = nullptr; + std::thread net_rescan_thread([this, rescan_interval]() + { + if (rescan_interval > 0) + { + auto interval = std::chrono::seconds(rescan_interval); + while (run_) + { + std::this_thread::sleep_for(interval); + if (run_) + { + participant_->set_qos(participant_->get_qos()); + } + } + } + }); + while (run_ && (loops == 0 || loops > current_loop)) { if (zero_copy_) @@ -187,6 +204,9 @@ void PublisherModule::run( std::this_thread::sleep_for(std::chrono::milliseconds(interval)); } + + run_ = false; + net_rescan_thread.join(); } void PublisherModule::on_publication_matched( diff --git a/test/dds/communication/security/PublisherModule.hpp b/test/dds/communication/security/PublisherModule.hpp index fb144821a0a..3f4b63bf1ec 100644 --- a/test/dds/communication/security/PublisherModule.hpp +++ b/test/dds/communication/security/PublisherModule.hpp @@ -19,6 +19,14 @@ #ifndef TEST_DDS_COMMUNICATION_PUBLISHERMODULE_HPP #define TEST_DDS_COMMUNICATION_PUBLISHERMODULE_HPP +<<<<<<< HEAD +======= +#include +#include +#include + +#include +>>>>>>> 91bd7c857 (Fix issues in Dynamic Network Interfaces (#5282)) #include #include #include @@ -41,8 +49,8 @@ class PublisherModule PublisherModule( bool exit_on_lost_liveliness, - bool fixed_type = false, - bool zero_copy = false) + bool fixed_type, + bool zero_copy) : exit_on_lost_liveliness_(exit_on_lost_liveliness) , fixed_type_(zero_copy || fixed_type) // If zero copy active, fixed type is required , zero_copy_(zero_copy) @@ -80,8 +88,9 @@ class PublisherModule void run( uint32_t samples, - uint32_t loops = 0, - uint32_t interval = 250); + const uint32_t rescan_interval, + uint32_t loops, + uint32_t interval); private: @@ -93,7 +102,7 @@ class PublisherModule bool exit_on_lost_liveliness_ = false; bool fixed_type_ = false; bool zero_copy_ = false; - bool run_ = true; + std::atomic_bool run_ {true}; DomainParticipant* participant_ = nullptr; TypeSupport type_; Publisher* publisher_ = nullptr; diff --git a/test/dds/communication/security/SubscriberMain.cpp b/test/dds/communication/security/SubscriberMain.cpp index f1f0d513ee6..3f0e01effff 100644 --- a/test/dds/communication/security/SubscriberMain.cpp +++ b/test/dds/communication/security/SubscriberMain.cpp @@ -31,6 +31,8 @@ using namespace eprosima::fastdds::dds; * --magic * --xmlfile * --publishers + * --die_on_data_received + * --rescan */ int main( @@ -45,6 +47,7 @@ int main( uint32_t seed = 7800; uint32_t samples = 4; uint32_t publishers = 1; + uint32_t rescan_interval_seconds = 0; char* xml_file = nullptr; std::string magic; @@ -116,6 +119,16 @@ int main( { die_on_data_received = true; } + else if (strcmp(argv[arg_count], "--rescan") == 0) + { + if (++arg_count >= argc) + { + std::cout << "--rescan expects a parameter" << std::endl; + return -1; + } + + rescan_interval_seconds = strtol(argv[arg_count], nullptr, 10); + } else { std::cout << "Wrong argument " << argv[arg_count] << std::endl; @@ -134,7 +147,7 @@ int main( if (subscriber.init(seed, magic)) { - return subscriber.run(notexit) ? 0 : -1; + return subscriber.run(notexit, rescan_interval_seconds) ? 0 : -1; } return -1; diff --git a/test/dds/communication/security/SubscriberModule.cpp b/test/dds/communication/security/SubscriberModule.cpp index 4160e127297..102231a5566 100644 --- a/test/dds/communication/security/SubscriberModule.cpp +++ b/test/dds/communication/security/SubscriberModule.cpp @@ -130,17 +130,35 @@ bool SubscriberModule::init( } bool SubscriberModule::run( - bool notexit) + bool notexit, + const uint32_t rescan_interval) { - return run_for(notexit, std::chrono::hours(24)); + return run_for(notexit, rescan_interval, std::chrono::hours(24)); } bool SubscriberModule::run_for( bool notexit, + const uint32_t rescan_interval, const std::chrono::milliseconds& timeout) { bool returned_value = false; + std::thread net_rescan_thread([this, rescan_interval]() + { + if (rescan_interval > 0) + { + auto interval = std::chrono::seconds(rescan_interval); + while (run_) + { + std::this_thread::sleep_for(interval); + if (run_) + { + participant_->set_qos(participant_->get_qos()); + } + } + } + }); + while (notexit && run_) { std::this_thread::sleep_for(std::chrono::milliseconds(250)); @@ -184,6 +202,9 @@ bool SubscriberModule::run_for( returned_value = false; } + run_ = false; + net_rescan_thread.join(); + return returned_value; } diff --git a/test/dds/communication/security/SubscriberModule.hpp b/test/dds/communication/security/SubscriberModule.hpp index 980c6c5acc6..c082d73fb80 100644 --- a/test/dds/communication/security/SubscriberModule.hpp +++ b/test/dds/communication/security/SubscriberModule.hpp @@ -19,6 +19,7 @@ #ifndef TEST_COMMUNICATION_SUBSCRIBER_HPP #define TEST_COMMUNICATION_SUBSCRIBER_HPP +<<<<<<< HEAD #include #include #include @@ -28,9 +29,13 @@ #include "types/HelloWorldPubSubTypes.h" #include +======= +#include +#include +>>>>>>> 91bd7c857 (Fix issues in Dynamic Network Interfaces (#5282)) #include #include -#include +#include namespace eprosima { namespace fastdds { @@ -44,9 +49,9 @@ class SubscriberModule SubscriberModule( const uint32_t publishers, const uint32_t max_number_samples, - bool fixed_type = false, - bool zero_copy = false, - bool die_on_data_received = false) + bool fixed_type, + bool zero_copy, + bool die_on_data_received) : publishers_(publishers) , max_number_samples_(max_number_samples) , fixed_type_(zero_copy || fixed_type) // If zero copy active, fixed type is required @@ -83,10 +88,12 @@ class SubscriberModule const std::string& magic); bool run( - bool notexit); + bool notexit, + const uint32_t rescan_interval); bool run_for( bool notexit, + const uint32_t rescan_interval, const std::chrono::milliseconds& timeout); private: @@ -100,7 +107,7 @@ class SubscriberModule std::map number_samples_; bool fixed_type_ = false; bool zero_copy_ = false; - bool run_ = true; + std::atomic_bool run_{true}; DomainParticipant* participant_ = nullptr; TypeSupport type_; Subscriber* subscriber_ = nullptr;