Skip to content

Commit 35869c8

Browse files
akampmannAlexandru Kampmanncleboennen
authored
Feature/multicast-fastdds-liveliness (#4)
* restore compatibility with Fast-DDS 2.3.1 * add multicast support * add liveliness support (remove dead remote participants) * add ref to embeddedRTPS-Linux Co-authored-by: Alexandru Kampmann <kampmann@embedded.rwth-aachen.de> Co-authored-by: Clemens Boennen <clemens.boennen@rwth-aachen.de>
1 parent e372abd commit 35869c8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1251
-463
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ cmake-build-debug
55
cmake-build-release
66
thirdparty/Micro-CDR/CMakeFiles
77
include/rtps/config.h
8+
CMakeFiles

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "thirdparty/googletest"]
2+
path = thirdparty/googletest
3+
url = https://github.com/google/googletest.git

Readme.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ More information is provided in our ITSC'2019 publication [1], which we kindly a
1010

1111
**Discovery** Simple Participant Discovery Protocol (SPDP) as well as Simple Endpoint Discovery Protocol (SEDP) are implemented.
1212

13-
**Interoperability** We have successfully tested interoperability with eProsima FastRTPS v1.8.0.
13+
**Interoperability** We have sucessfully tested interoperability with **FastDDS 2.3.1**
1414

1515
**QoS Policies** Both reliable as well as best-effort endpoints are implemented.
1616

17-
**UDP Multicast** Our implementation currently does not make use of UDP multicast communication. This can lead to sub-optimal performance.
17+
**UDP Multicast** Our implementation supports multicast locators.
1818

1919
**Message Size** Message size is currently limited by lwIP buffer size and are not split up among multiple buffers
2020

@@ -34,6 +34,12 @@ The following repository provides code examples for running embeddedRTPS on the
3434

3535
- [STM32F767ZI](https://github.com/embedded-software-laboratory/embeddedRTPS-STM32)
3636

37+
#### Runnig on Linux & Unittests
38+
39+
The following repository allow to compile and run embeddedRTPS on Linux for development purposes. This repository also contains unittests for embeddedRTPS.
40+
41+
- [embeddedRTPS-linux](https://github.com/embedded-software-laboratory/embeddedRTPS-Linux)
42+
3743
### Third Party Libraries
3844

3945
embeddedRTPS makes use of the following third party libraries:
@@ -47,7 +53,7 @@ Round-trip-times (RTT) for different platforms and packet sizes are depicted in
4753

4854
**Table 1** 2x Infineon Aurix TC277 running embeddedRTPS.
4955

50-
**Table 2** STM32F7 running embeddedRTPS connected to an Intel NUC running eProsima FastRTPS.
56+
**Table 2** STM32F7 running embeddedRTPS connected to an Intel NUC running eProsima FastRTPS 1.8.0.
5157

5258
<img src="https://raw.githubusercontent.com/embedded-software-laboratory/embeddedRTPS/master/media/performance_rtt.png" width="60%">
5359

include/rtps/common/Locator.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,13 @@ struct Locator {
8787
address[15]);
8888
}
8989

90+
bool isSameAddress(ip4_addr_t *address) {
91+
ip4_addr_t ownaddress = getIp4Address();
92+
return ip4_addr_cmp(&ownaddress, address);
93+
}
94+
95+
inline uint32_t getLocatorPort() { return static_cast<Ip4Port_t>(port); }
96+
9097
inline bool isSameSubnet() const {
9198
return UdpDriver::isSameSubnet(getIp4Address());
9299
}
@@ -109,7 +116,8 @@ inline Locator getUserUnicastLocator(ParticipantId_t participantId) {
109116
Config::IP_ADDRESS[3], getUserUnicastPort(participantId));
110117
}
111118

112-
inline Locator getUserMulticastLocator() {
119+
inline Locator getUserMulticastLocator() { // this would be a unicastaddress, as
120+
// defined in config
113121
return Locator::createUDPv4Locator(
114122
Config::IP_ADDRESS[0], Config::IP_ADDRESS[1], Config::IP_ADDRESS[2],
115123
Config::IP_ADDRESS[3], getUserMulticastPort());

include/rtps/common/types.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ enum class ReliabilityKind_t : uint32_t {
7777
RELIABLE = 2 // Specification says 3 but eprosima sends 2
7878
};
7979

80+
enum class DurabilityKind_t : uint32_t {
81+
VOLATILE = 0,
82+
TRANSIENT_LOCAL = 1,
83+
TRANSIENT = 2,
84+
PERSISTENT = 3
85+
};
86+
8087
struct GuidPrefix_t {
8188
std::array<uint8_t, 12> id;
8289

@@ -97,13 +104,24 @@ struct EntityId_t {
97104
bool operator!=(const EntityId_t &other) const { return !(*this == other); }
98105
};
99106

100-
struct Guid {
107+
struct Guid_t {
101108
GuidPrefix_t prefix;
102109
EntityId_t entityId;
103110

104-
bool operator==(const Guid &other) const {
111+
bool operator==(const Guid_t &other) const {
105112
return this->prefix == other.prefix && this->entityId == other.entityId;
106113
}
114+
115+
static uint32_t sum(const Guid_t &other) {
116+
uint32_t ret = 0;
117+
for (const auto &i : other.prefix.id) {
118+
ret += i;
119+
}
120+
for (const auto &i : other.entityId.entityKey) {
121+
ret += i;
122+
}
123+
return ret;
124+
}
107125
};
108126

109127
// Described as long but there wasn't any definition. Other than 32 bit does not
@@ -240,6 +258,7 @@ const EntityId_t ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER = {
240258
{00, 02, 00}, EntityKind_t::BUILD_IN_READER_WITH_KEY};
241259

242260
const GuidPrefix_t GUIDPREFIX_UNKNOWN{};
261+
const Guid_t GUID_UNKNOWN{};
243262

244263
const ParticipantId_t PARTICIPANT_ID_INVALID = -1;
245264

include/rtps/config_aurix.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ namespace rtps {
3131

3232
#define IS_LITTLE_ENDIAN 1
3333

34+
// define only if using FreeRTOS
35+
#define OS_IS_FREERTOS
36+
3437
namespace Config {
3538
const VendorId_t VENDOR_ID = {13, 37};
3639
const std::array<uint8_t, 4> IP_ADDRESS = {192, 168, 0, 42};
@@ -59,6 +62,8 @@ const uint16_t SPDP_WRITER_STACKSIZE = 550; // byte
5962

6063
const uint16_t SF_WRITER_HB_PERIOD_MS = 4000;
6164
const uint16_t SPDP_RESEND_PERIOD_MS = 10000;
65+
const uint8_t SPDP_CYCLECOUNT_HEARTBEAT =
66+
2; // skip x SPDP rounds before checking liveliness
6267
const uint8_t SPDP_WRITER_PRIO = 3;
6368
const uint8_t SPDP_MAX_NUMBER_FOUND_PARTICIPANTS = 5;
6469
const uint8_t SPDP_MAX_NUM_LOCATORS = 5;

include/rtps/config_desktop.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ namespace rtps {
3434
namespace Config {
3535
const VendorId_t VENDOR_ID = {13, 37};
3636
const std::array<uint8_t, 4> IP_ADDRESS = {
37-
192, 168, 0, 66}; // Needs to be set in lwipcfg.h too.
37+
192, 168, 1, 2}; // Needs to be set in lwipcfg.h too.
3838
const GuidPrefix_t BASE_GUID_PREFIX{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9};
3939

4040
const uint8_t DOMAIN_ID = 0; // 230 possible with UDP
@@ -64,12 +64,19 @@ const int THREAD_POOL_WRITER_STACKSIZE = 1100; // byte
6464
const int THREAD_POOL_READER_STACKSIZE = 1600; // byte
6565
const uint16_t SPDP_WRITER_STACKSIZE = 550; // byte
6666

67-
const uint16_t SF_WRITER_HB_PERIOD_MS = 4000;
67+
const uint16_t SF_WRITER_HB_PERIOD_MS = 500;
6868
const uint16_t SPDP_RESEND_PERIOD_MS = 10000;
69+
const uint8_t SPDP_CYCLECOUNT_HEARTBEAT =
70+
2; // skip x SPDP rounds before checking liveliness
6971
const uint8_t SPDP_WRITER_PRIO = 3;
7072
const uint8_t SPDP_MAX_NUMBER_FOUND_PARTICIPANTS = 5;
7173
const uint8_t SPDP_MAX_NUM_LOCATORS = 5;
72-
const Duration_t SPDP_LEASE_DURATION = {100, 0};
74+
const Duration_t SPDP_DEFAULT_REMOTE_LEASE_DURATION = {
75+
100, 0}; // Default lease duration for remote participants, usually
76+
// overwritten by remote info
77+
const Duration_t SPDP_MAX_REMOTE_LEASE_DURATION = {
78+
180,
79+
0}; // Absolute maximum lease duration, ignoring remote participant info
7380

7481
const int MAX_NUM_UDP_CONNECTIONS = 10;
7582

include/rtps/config_r5.h

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
*
3+
* Author: Andreas Wüstenberg (andreas.wuestenberg@rwth-aachen.de)
4+
*/
5+
6+
#ifndef RTPS_CONFIG_H
7+
#define RTPS_CONFIG_H
8+
9+
#include "rtps/common/types.h"
10+
11+
namespace rtps {
12+
13+
#define IS_LITTLE_ENDIAN 1
14+
15+
namespace Config {
16+
const VendorId_t VENDOR_ID = {13, 37};
17+
const std::array<uint8_t, 4> IP_ADDRESS = {
18+
192, 168, 1, 10}; // Needs to be set in lwipcfg.h too.
19+
const GuidPrefix_t BASE_GUID_PREFIX{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12};
20+
21+
const uint8_t DOMAIN_ID = 0; // 230 possible with UDP
22+
const uint8_t NUM_STATELESS_WRITERS = 64;
23+
const uint8_t NUM_STATELESS_READERS = 64;
24+
const uint8_t NUM_STATEFUL_READERS = 4;
25+
const uint8_t NUM_STATEFUL_WRITERS = 4;
26+
const uint8_t MAX_NUM_PARTICIPANTS = 1;
27+
const uint8_t NUM_WRITERS_PER_PARTICIPANT =
28+
64; // 3 will be reserved for SPDP & SEDP
29+
const uint8_t NUM_READERS_PER_PARTICIPANT =
30+
64; // 3 will be reserved for SPDP & SEDP
31+
const uint8_t NUM_WRITER_PROXIES_PER_READER = 30;
32+
const uint8_t NUM_READER_PROXIES_PER_WRITER = 30;
33+
34+
const uint8_t HISTORY_SIZE = 64;
35+
36+
const uint8_t MAX_TYPENAME_LENGTH = 64;
37+
const uint8_t MAX_TOPICNAME_LENGTH = 64;
38+
39+
const int HEARTBEAT_STACKSIZE = 1200; // byte
40+
const int THREAD_POOL_WRITER_STACKSIZE = 1100; // byte
41+
const int THREAD_POOL_READER_STACKSIZE = 1600; // byte
42+
const uint16_t SPDP_WRITER_STACKSIZE = 550; // byte
43+
44+
const uint16_t SF_WRITER_HB_PERIOD_MS = 4000;
45+
const uint16_t SPDP_RESEND_PERIOD_MS = 1000;
46+
const uint8_t SPDP_WRITER_PRIO = 3;
47+
const uint8_t SPDP_CYCLECOUNT_HEARTBEAT =
48+
2; // Every X*SPDP_RESEND_PERIOD_MS, check for missing heartbeats
49+
const uint8_t SPDP_MAX_NUMBER_FOUND_PARTICIPANTS = 50;
50+
const uint8_t SPDP_MAX_NUM_LOCATORS = 5;
51+
const Duration_t SPDP_DEFAULT_REMOTE_LEASE_DURATION = {
52+
100, 0}; // Default lease duration for remote participants, usually
53+
// overwritten by remote info
54+
const Duration_t SPDP_MAX_REMOTE_LEASE_DURATION = {
55+
180,
56+
0}; // Absolute maximum lease duration, ignoring remote participant info
57+
58+
const int MAX_NUM_UDP_CONNECTIONS = 10;
59+
60+
const int THREAD_POOL_NUM_WRITERS = 1;
61+
const int THREAD_POOL_NUM_READERS = 1;
62+
const int THREAD_POOL_WRITER_PRIO = 3;
63+
const int THREAD_POOL_READER_PRIO = 3;
64+
const int THREAD_POOL_WORKLOAD_QUEUE_LENGTH = 10;
65+
66+
constexpr int OVERALL_HEAP_SIZE =
67+
THREAD_POOL_NUM_WRITERS * THREAD_POOL_WRITER_STACKSIZE +
68+
THREAD_POOL_NUM_READERS * THREAD_POOL_READER_STACKSIZE +
69+
MAX_NUM_PARTICIPANTS * SPDP_WRITER_STACKSIZE +
70+
NUM_STATEFUL_WRITERS * HEARTBEAT_STACKSIZE;
71+
} // namespace Config
72+
} // namespace rtps
73+
74+
#endif // RTPS_CONFIG_H

include/rtps/config_stm.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,13 @@ namespace rtps {
3131

3232
#define IS_LITTLE_ENDIAN 1
3333

34+
// define only if using FreeRTOS
35+
#define OS_IS_FREERTOS
36+
3437
namespace Config {
3538
const VendorId_t VENDOR_ID = {13, 37};
3639
const std::array<uint8_t, 4> IP_ADDRESS = {
37-
192, 168, 0, 47}; // Needs to be set in lwipcfg.h too.
40+
192, 168, 0, 66}; // Needs to be set in lwipcfg.h too.
3841
const GuidPrefix_t BASE_GUID_PREFIX{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12};
3942

4043
const uint8_t DOMAIN_ID = 0; // 230 possible with UDP
@@ -60,6 +63,8 @@ const uint16_t SPDP_WRITER_STACKSIZE = 550; // byte
6063

6164
const uint16_t SF_WRITER_HB_PERIOD_MS = 4000;
6265
const uint16_t SPDP_RESEND_PERIOD_MS = 10000;
66+
const uint8_t SPDP_CYCLECOUNT_HEARTBEAT =
67+
2; // skip x SPDP rounds before checking liveliness
6368
const uint8_t SPDP_WRITER_PRIO = 3;
6469
const uint8_t SPDP_MAX_NUMBER_FOUND_PARTICIPANTS = 5;
6570
const uint8_t SPDP_MAX_NUM_LOCATORS = 5;

include/rtps/discovery/ParticipantProxyData.h

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ Author: i11 - Embedded Software, RWTH Aachen University
2929
#include "rtps/config.h"
3030
#include "rtps/messages/MessageTypes.h"
3131
#include "ucdr/microcdr.h"
32-
32+
#if defined(unix) || defined(__unix__)
33+
#include <chrono>
34+
#endif
3335
#include <array>
3436

3537
namespace rtps {
@@ -40,11 +42,11 @@ typedef uint32_t BuiltinEndpointSet_t;
4042

4143
class ParticipantProxyData {
4244
public:
43-
ParticipantProxyData() = default;
44-
ParticipantProxyData(Guid guid);
45+
ParticipantProxyData() { onAliveSignal(); }
46+
ParticipantProxyData(Guid_t guid);
4547

4648
ProtocolVersion_t m_protocolVersion = PROTOCOLVERSION;
47-
Guid m_guid = Guid{GUIDPREFIX_UNKNOWN, ENTITYID_UNKNOWN};
49+
Guid_t m_guid = Guid_t{GUIDPREFIX_UNKNOWN, ENTITYID_UNKNOWN};
4850
VendorId_t m_vendorId = VENDOR_UNKNOWN;
4951
bool m_expectsInlineQos = false;
5052
BuiltinEndpointSet_t m_availableBuiltInEndpoints;
@@ -57,8 +59,13 @@ class ParticipantProxyData {
5759
std::array<Locator, Config::SPDP_MAX_NUM_LOCATORS>
5860
m_defaultMulticastLocatorList;
5961
Count_t m_manualLivelinessCount{1};
60-
Duration_t m_leaseDuration = Config::SPDP_LEASE_DURATION;
61-
62+
Duration_t m_leaseDuration = Config::SPDP_DEFAULT_REMOTE_LEASE_DURATION;
63+
#if defined(unix) || defined(__unix__)
64+
std::chrono::time_point<std::chrono::high_resolution_clock>
65+
m_lastLivelinessReceivedTimestamp;
66+
#else
67+
TickType_t m_lastLivelinessReceivedTickCount = 0;
68+
#endif
6269
void reset();
6370

6471
bool readFromUcdrBuffer(ucdrBuffer &buffer);
@@ -70,6 +77,10 @@ class ParticipantProxyData {
7077
inline bool hasSubscriptionWriter();
7178
inline bool hasSubscriptionReader();
7279

80+
inline void onAliveSignal();
81+
inline bool isAlive();
82+
inline uint32_t getAliveSignalAgeInMilliseconds();
83+
7384
private:
7485
bool
7586
readLocatorIntoList(ucdrBuffer &buffer,
@@ -131,5 +142,45 @@ bool ParticipantProxyData::hasSubscriptionReader() {
131142
return (m_availableBuiltInEndpoints &
132143
DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_DETECTOR) != 0;
133144
}
145+
146+
void ParticipantProxyData::onAliveSignal() {
147+
#if defined(unix) || defined(__unix__)
148+
m_lastLivelinessReceivedTimestamp = std::chrono::high_resolution_clock::now();
149+
#else
150+
m_lastLivelinessReceivedTickCount = xTaskGetTickCount();
151+
#endif
152+
}
153+
154+
uint32_t ParticipantProxyData::getAliveSignalAgeInMilliseconds() {
155+
#if defined(unix) || defined(__unix__)
156+
auto now = std::chrono::high_resolution_clock::now();
157+
std::chrono::duration<double, std::milli> duration =
158+
now - m_lastLivelinessReceivedTimestamp;
159+
return duration.count();
160+
#else
161+
return (xTaskGetTickCount() - m_lastLivelinessReceivedTickCount) *
162+
(1000 / configTICK_RATE_HZ);
163+
#endif
164+
}
165+
166+
/*
167+
* Returns true if last heartbeat within lease duration, else false
168+
*/
169+
bool ParticipantProxyData::isAlive() {
170+
uint32_t lease_in_ms =
171+
m_leaseDuration.seconds * 1000 + m_leaseDuration.fraction * 1e-6;
172+
173+
uint32_t max_lease_in_ms =
174+
Config::SPDP_MAX_REMOTE_LEASE_DURATION.seconds * 1000 +
175+
Config::SPDP_MAX_REMOTE_LEASE_DURATION.fraction * 1e-6;
176+
177+
auto heatbeat_age_in_ms = getAliveSignalAgeInMilliseconds();
178+
179+
if (heatbeat_age_in_ms > std::min(lease_in_ms, max_lease_in_ms)) {
180+
return false;
181+
}
182+
return true;
183+
}
184+
134185
} // namespace rtps
135186
#endif // RTPS_PARTICIPANTPROXYDATA_H

0 commit comments

Comments
 (0)