Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
RoutingLogic.hxx
Go to the documentation of this file.
1
36#ifndef _OPENLCB_ROUTNGLOGIC_HXX_
37#define _OPENLCB_ROUTNGLOGIC_HXX_
38
39#include <set>
40#include <map>
41#include <unordered_map>
42
43#include "os/OS.hxx"
45
46namespace openlcb
47{
48
58uint8_t event_range_to_bit_count(EventId *event);
59
65template <class Port, typename Address> class RoutingLogic
66{
67public:
69 {
70 }
72 {
73 }
74
80 void remove_port(Port *port)
81 {
83 eventRoutingTable_.erase(port);
84 // Removing entries from a hashmap invalidates an iterator, thus it is
85 // safer to null them out than actually remove. Having a null value
86 // will cause address lookup to return null for a node that has not
87 // been seen since then elsewhere, which is exactly the behavior we
88 // want.
89 for (auto &it : addressRoutingTable_)
90 {
91 if (it.second == port)
92 {
93 it.second = nullptr;
94 }
95 }
96 }
97
105 void add_node_id_to_route(Port *port, Address source)
106 {
107 OSMutexLock l(&lock_);
108 addressRoutingTable_[source] = port;
109 }
110
118 Port *lookup_port_for_address(Address dest)
119 {
120 OSMutexLock l(&lock_);
121 auto it = addressRoutingTable_.find(dest);
122 if (it == addressRoutingTable_.end())
123 return nullptr;
124 return it->second;
125 }
126
133 void register_consumer(Port *port, EventId event)
134 {
135 OSMutexLock l(&lock_);
136 eventRoutingTable_[port].registeredConsumers_[0].insert(event);
137 }
138
145 void register_consumer_range(Port *port, EventId encoded_range)
146 {
147 OSMutexLock l(&lock_);
148 uint8_t bit_count = event_range_to_bit_count(&encoded_range);
149 eventRoutingTable_[port].registeredConsumers_[bit_count].insert(
150 encoded_range);
151 }
152
159 void register_producer(Port *port, EventId event)
160 {
161 // For the moment we do not keep separate routing tables for producers
162 // and consumers.
163 register_consumer(port, event);
164 }
165
172 void register_producer_range(Port *port, EventId encoded_range)
173 {
174 // For the moment we do not keep separate routing tables for producers
175 // and consumers.
176 register_consumer_range(port, encoded_range);
177 }
178
185 bool check_pcer(Port *port, EventId event)
186 {
187 OSMutexLock l(&lock_);
188 auto ip = eventRoutingTable_.find(port);
189 if (ip == eventRoutingTable_.end())
190 {
191 return false;
192 }
193 for (auto im = ip->second.registeredConsumers_.begin();
194 im != ip->second.registeredConsumers_.end(); ++im)
195 {
196 if (im->first == 0)
197 {
198 if (im->second.find(event) != im->second.end())
199 return true;
200 }
201 else if (im->first == 64)
202 {
203 if (!im->second.empty())
204 return true;
205 }
206 else
207 {
208 EventId masked_range =
209 event & ~((UINT64_C(1) << im->first) - 1);
210 if (im->second.find(masked_range) != im->second.end())
211 return true;
212 }
213 }
214 return false;
215 }
216
217private:
220
222 std::unordered_map<Address, Port *> addressRoutingTable_;
223
225 struct EventSet
226 {
229 std::map<uint8_t, std::set<EventId>> registeredConsumers_;
230 };
231
233 std::map<Port *, EventSet> eventRoutingTable_;
234};
235
236} // namespace openlcb
237
238#endif // _OPENLCB_ROUTNGLOGIC_HXX_
Class to allow convenient locking and unlocking of mutexes in a C context.
Definition OS.hxx:494
This class provides a mutex API.
Definition OS.hxx:427
Routing table for gateways and routers in OpenLCB.
void register_consumer_range(Port *port, EventId encoded_range)
Declares that there is a consumer for the given event ID range on the given port.
Port * lookup_port_for_address(Address dest)
Looks up which port an addressed packet should be sent to.
std::unordered_map< Address, Port * > addressRoutingTable_
Stores all known addresses and which port they route to.
void remove_port(Port *port)
Clears all entries in the routing table related to a given port, as the given port is being removed.
void register_producer_range(Port *port, EventId encoded_range)
Declares that there is a producer for the given event ID range on the given port.
bool check_pcer(Port *port, EventId event)
Checks if a given PCER message should be forwarded to the given port.
void add_node_id_to_route(Port *port, Address source)
Declares that a given node ID is reachable via a specific port.
void register_producer(Port *port, EventId event)
Declares that there is a producer for the given event ID on the given port.
OSMutex lock_
Protects all internal data structures.
std::map< Port *, EventSet > eventRoutingTable_
Stores per-port event information.
void register_consumer(Port *port, EventId event)
Declares that there is a consumer for the given event ID on the given port.
uint8_t event_range_to_bit_count(EventId *event)
Decodes an event range, encoded according to the Event Transport protocol specification.
The per-port event information.
std::map< uint8_t, std::set< EventId > > registeredConsumers_
key: number of bits set in the mask part.