Vanetza
 
Loading...
Searching...
No Matches
location_table.cpp
1#include "location_table.hpp"
2#include <chrono>
3#include <limits>
4
5namespace vanetza
6{
7namespace geonet
8{
9
10static_assert(std::numeric_limits<double>::has_quiet_NaN, "quiet NaN value unavailable");
11
12LocationTableEntry::LocationTableEntry(const Runtime& rt) :
13 m_runtime(rt), m_is_neighbour(Clock::time_point::min()), m_has_position_vector(false),
14 m_pdr(std::numeric_limits<double>::quiet_NaN()), m_pdr_update(rt.now())
15{
16}
17
18StationType LocationTableEntry::station_type() const
19{
20 return geonet_address().station_type();
21}
22
23const Address& LocationTableEntry::geonet_address() const
24{
25 return m_position_vector.gn_addr;
26}
27
28const MacAddress& LocationTableEntry::link_layer_address() const
29{
30 return geonet_address().mid();
31}
32
33bool LocationTableEntry::is_neighbour() const
34{
35 return m_is_neighbour > m_runtime.now();
36}
37
38void LocationTableEntry::update_pdr(std::size_t packet_size, double beta)
39{
40 using namespace vanetza::units;
41
42 if (std::isnan(m_pdr)) {
43 m_pdr = 0.0;
44 m_pdr_update = m_runtime.now();
45 } else if (beta > 0.0 && beta < 1.0) {
46 const std::chrono::duration<double> time_period = m_runtime.now() - m_pdr_update;
47 if (time_period.count() > 0.0) {
48 double instant_pdr = packet_size / time_period.count();
49 m_pdr *= beta;
50 m_pdr += (1.0 - beta) * instant_pdr;
51 m_pdr_update = m_runtime.now();
52 }
53 }
54}
55
56bool LocationTableEntry::set_position_vector(const LongPositionVector& pv)
57{
58 if (is_valid(pv)) {
59 m_has_position_vector = true;
60 m_position_vector = pv;
61 return true;
62 } else {
63 return false;
64 }
65}
66
67bool LocationTableEntry::update_position_vector(const LongPositionVector& lpv)
68{
69 if (has_position_vector()) {
70 if (get_position_vector().timestamp < lpv.timestamp) {
71 return set_position_vector(lpv);
72 }
73 } else {
74 return set_position_vector(lpv);
75 }
76
77 return false;
78}
79
80void LocationTableEntry::set_neighbour(bool flag)
81{
82 m_is_neighbour = flag ? Clock::time_point::max() : Clock::time_point::min();
83}
84
85void LocationTableEntry::set_neighbour(bool flag, Clock::duration expiry)
86{
87 if (flag && expiry > Clock::duration::zero()) {
88 m_is_neighbour = m_runtime.now() + expiry;
89 } else {
90 set_neighbour(flag);
91 }
92}
93
94
95LocationTable::LocationTable(const MIB& mib, Runtime& rt) :
96 m_table(rt, LocationTableEntryCreator(rt))
97{
98 m_table.set_lifetime(std::chrono::seconds(mib.itsGnLifetimeLocTE / units::si::seconds));
99}
100
101bool LocationTable::has_entry(const Address& addr) const
102{
103 return m_table.has_value(addr.mid());
104}
105
106bool LocationTable::has_neighbours() const
107{
108 bool found_neighbour = false;
109 for (const auto& entry : m_table.map()) {
110 if (entry.second.is_neighbour()) {
111 found_neighbour = true;
112 break;
113 }
114 }
115 return found_neighbour;
116}
117
118auto LocationTable::neighbours() const -> neighbour_range
119{
120 const entry_predicate neighbour_predicate =
121 [](const MacAddress&, const LocationTableEntry& entry) {
122 return entry.is_neighbour();
123 };
124 return filter(neighbour_predicate);
125}
126
127auto LocationTable::filter(const entry_predicate& predicate) const -> entry_range
128{
129 using namespace boost::adaptors;
130 std::function<bool(const typename table_type::value_type&)> filter_fn =
131 [predicate](const typename table_type::value_type& v) {
132 return predicate(v.first, v.second);
133 };
134 return m_table.map() | filtered(filter_fn) | map_values;
135}
136
137void LocationTable::visit(const entry_visitor& visitor) const
138{
139 for (const auto& entry : m_table.map()) {
140 visitor(entry.first, entry.second);
141 }
142}
143
144LocationTableEntry& LocationTable::update(const LongPositionVector& lpv)
145{
146 LocationTableEntry* entry = m_table.get_value_ptr(lpv.gn_addr.mid());
147 if (entry && entry->has_position_vector()) {
148 if (entry->update_position_vector(lpv)) {
149 m_table.refresh(lpv.gn_addr.mid());
150 }
151 } else {
152 entry = &m_table.refresh(lpv.gn_addr.mid());
153 entry->update_position_vector(lpv);
154 }
155 return *entry;
156}
157
158LocationTableEntry& LocationTable::get_or_create_entry(const Address& addr)
159{
160 return m_table.get_value(addr.mid());
161}
162
163LocationTableEntry& LocationTable::get_or_create_entry(const MacAddress& mac)
164{
165 return m_table.get_value(mac);
166}
167
168const LocationTableEntry* LocationTable::get_entry(const Address& addr) const
169{
170 return m_table.get_value_ptr(addr.mid());
171}
172
173const LocationTableEntry* LocationTable::get_entry(const MacAddress& mac) const
174{
175 return m_table.get_value_ptr(mac);
176}
177
178const LongPositionVector* LocationTable::get_position(const Address& addr) const
179{
180 return get_position(addr.mid());
181}
182
183const LongPositionVector* LocationTable::get_position(const MacAddress& mac) const
184{
185 const LongPositionVector* position = nullptr;
186 auto* entry = m_table.get_value_ptr(mac);
187 if (entry && entry->has_position_vector()) {
188 position = &entry->get_position_vector();
189 }
190 return position;
191}
192
193} // namespace geonet
194} // namespace vanetza
195
bool update_position_vector(const LongPositionVector &pv)
const LongPositionVector & get_position_vector() const
bool has_value(const key_type &key) const
mapped_type & refresh(const key_type &key)
mapped_type & get_value(const key_type &key)
mapped_type * get_value_ptr(const key_type &key)
STL namespace.