24 #include "ns3/abort.h"
25 #include "ns3/assert.h"
26 #include "ns3/random-variable-stream.h"
27 #include "ns3/ipv4-route.h"
29 #include "ns3/names.h"
30 #include "ns3/rip-header.h"
31 #include "ns3/udp-header.h"
33 #include "ns3/uinteger.h"
34 #include "ns3/ipv4-packet-info-tag.h"
35 #include "ns3/loopback-net-device.h"
37 #define RIP_ALL_NODE "224.0.0.9"
47 : m_ipv4 (0), m_splitHorizonStrategy (
Rip::POISON_REVERSE), m_initialized (false)
49 m_rng = CreateObject<UniformRandomVariable> ();
61 .SetGroupName (
"Internet")
62 .AddConstructor<
Rip> ()
63 .AddAttribute (
"UnsolicitedRoutingUpdate",
"The time between two Unsolicited Routing Updates.",
67 .AddAttribute (
"StartupDelay",
"Maximum random delay for protocol startup (send route requests).",
71 .AddAttribute (
"TimeoutDelay",
"The delay to invalidate a route.",
75 .AddAttribute (
"GarbageCollectionDelay",
"The delay to delete an expired route.",
79 .AddAttribute (
"MinTriggeredCooldown",
"Min cooldown delay after a Triggered Update.",
83 .AddAttribute (
"MaxTriggeredCooldown",
"Max cooldown delay after a Triggered Update.",
87 .AddAttribute (
"SplitHorizon",
"Split Horizon strategy.",
93 .AddAttribute (
"LinkDownValue",
"Value for link down in count to infinity.",
96 MakeUintegerChecker<uint32_t> ())
113 bool addedGlobal =
false;
121 for (uint32_t i = 0 ; i <
m_ipv4->GetNInterfaces (); i++)
129 bool activeInterface =
false;
132 activeInterface =
true;
133 m_ipv4->SetForwarding (i,
true);
136 for (uint32_t j = 0; j <
m_ipv4->GetNAddresses (i); j++)
147 int ret = socket->
Bind (local);
207 rtentry =
Lookup (destination,
true, oif);
228 uint32_t iif =
m_ipv4->GetInterfaceForDevice (idev);
236 lcb (p, header, iif);
258 NS_LOG_LOGIC (
"Dropping packet not for me and with dst Broadcast");
267 if (
m_ipv4->IsForwarding (iif) ==
false)
269 NS_LOG_LOGIC (
"Forwarding disabled for this interface");
282 NS_LOG_LOGIC (
"Found unicast destination - calling unicast callback");
283 ucb (rtentry, p, header);
288 NS_LOG_LOGIC (
"Did not find unicast destination - returning false");
303 for (uint32_t j = 0; j <
m_ipv4->GetNAddresses (i); j++)
321 bool sendSocketFound =
false;
324 if (iter->second == i)
326 sendSocketFound =
true;
331 bool activeInterface =
false;
334 activeInterface =
true;
335 m_ipv4->SetForwarding (i,
true);
338 for (uint32_t j = 0; j <
m_ipv4->GetNAddresses (i); j++)
350 socket->
Bind (local);
383 if (it->first->GetInterface () == interface)
391 NS_LOG_INFO (
"Checking socket for interface " << interface);
392 if (iter->second == interface)
394 NS_LOG_INFO (
"Removed socket for interface " << interface);
395 iter->first->Close ();
411 if (!
m_ipv4->IsUp (interface))
436 if (!
m_ipv4->IsUp (interface))
453 if (it->first->GetInterface () == interface
454 && it->first->IsNetwork ()
455 && it->first->GetDestNetwork () == networkAddress
456 && it->first->GetDestNetworkMask () == networkMask)
477 for (i = 0; i <
m_ipv4->GetNInterfaces (); i++)
496 std::ios oldState (
nullptr);
497 oldState.copyfmt (*os);
499 *os << std::resetiosflags (std::ios::adjustfield) << std::setiosflags (std::ios::left);
501 *os <<
"Node: " <<
m_ipv4->GetObject<
Node> ()->GetId ()
502 <<
", Time: " <<
Now().
As (unit)
503 <<
", Local time: " <<
m_ipv4->GetObject<
Node> ()->GetLocalTime ().As (unit)
504 <<
", IPv4 RIP table" << std::endl;
508 *os <<
"Destination Gateway Genmask Flags Metric Ref Use Iface" << std::endl;
516 std::ostringstream dest, gw, mask, flags;
518 *os << std::setw (16) << dest.str ();
520 *os << std::setw (16) << gw.str ();
522 *os << std::setw (16) << mask.str ();
532 *os << std::setw (6) << flags.str ();
552 (*os).copyfmt (oldState);
572 iter->first->Close ();
589 uint16_t longestMask = 0;
594 NS_ASSERT_MSG (interface,
"Try to send on local multicast address, and no interface index is given!");
595 rtentry = Create<Ipv4Route> ();
596 rtentry->SetSource (
m_ipv4->SourceAddressSelection (
m_ipv4->GetInterfaceForDevice (interface), dst));
597 rtentry->SetDestination (dst);
599 rtentry->SetOutputDevice (interface);
613 NS_LOG_LOGIC (
"Searching for route to " << dst <<
", mask length " << maskLen);
617 NS_LOG_LOGIC (
"Found global network route " << j <<
", mask length " << maskLen);
622 if (maskLen < longestMask)
628 longestMask = maskLen;
632 rtentry = Create<Ipv4Route> ();
638 rtentry->SetSource (
m_ipv4->SourceAddressSelection (interfaceIdx, route->
GetGateway ()));
642 rtentry->SetSource (
m_ipv4->SourceAddressSelection (interfaceIdx, route->
GetDest ()));
646 rtentry->SetDestination (route->
GetDest ());
648 rtentry->SetOutputDevice (
m_ipv4->GetNetDevice (interfaceIdx));
656 NS_LOG_LOGIC (
"Matching route via " << rtentry->GetDestination () <<
" (through " << rtentry->GetGateway () <<
") at the end");
663 NS_LOG_FUNCTION (
this << network << networkPrefix << nextHop << interface);
691 if (it->first == route)
696 if (it->second.IsRunning ())
698 it->second.Cancel ();
704 NS_ABORT_MSG (
"RIP::InvalidateRoute - cannot find the route to update");
713 if (it->first == route)
720 NS_ABORT_MSG (
"RIP::DeleteRoute - cannot find the route to delete");
734 uint16_t senderPort = senderAddr.
GetPort ();
738 NS_LOG_LOGIC (
"Received a packet from the multicast socket");
742 NS_LOG_LOGIC (
"Received a packet from one of the unicast sockets");
748 NS_ABORT_MSG (
"No incoming interface on RIP message, aborting.");
750 uint32_t incomingIf = interfaceInfo.
GetRecvIf ();
751 Ptr<Node> node = this->GetObject<Node> ();
753 uint32_t ipInterfaceIndex =
m_ipv4->GetInterfaceForDevice (dev);
758 NS_ABORT_MSG (
"No incoming Hop Count on RIP message, aborting.");
760 uint8_t hopLimit = hoplimitTag.
GetTtl ();
762 int32_t interfaceForAddress =
m_ipv4->GetInterfaceForAddress (senderAddress);
763 if (interfaceForAddress != -1)
780 HandleRequests (hdr, senderAddress, senderPort, ipInterfaceIndex, hopLimit);
791 NS_LOG_FUNCTION (
this << senderAddress <<
int (senderPort) << incomingInterface <<
int (hopLimit) << requestHdr);
793 std::list<RipRte> rtes = requestHdr.
GetRteList ();
801 if (rtes.size () == 1)
804 rtes.begin ()->GetSubnetMask ().GetPrefixLength () == 0 &&
805 rtes.begin ()->GetRouteMetric () ==
m_linkDown)
815 if (iter->second == incomingInterface)
817 sendingSocket = iter->first;
820 NS_ASSERT_MSG (sendingSocket,
"HandleRequest - Impossible to find a socket to send the reply");
822 uint16_t mtu =
m_ipv4->GetMtu (incomingInterface);
843 bool splitHorizoning = (rtIter->first->GetInterface () == incomingInterface);
850 (rtIter->first->GetInterface () != incomingInterface));
852 if ((isGlobal || isDefaultRoute) &&
856 rte.
SetPrefix (rtIter->first->GetDestNetwork ());
911 for (std::list<RipRte>::iterator iter = rtes.begin ();
912 iter != rtes.end (); iter++)
923 requestedAddress.
CombineMask (iter->GetSubnetMask ());
924 Ipv4Address rtAddress = rtIter->first->GetDestNetwork ();
925 rtAddress.
CombineMask (rtIter->first->GetDestNetworkMask ());
927 if (requestedAddress == rtAddress)
929 iter->SetRouteMetric (rtIter->first->GetRouteMetric ());
930 iter->SetRouteTag (rtIter->first->GetRouteTag ());
940 iter->SetRouteTag (0);
953 NS_LOG_FUNCTION (
this << senderAddress << incomingInterface <<
int (hopLimit) << hdr);
957 NS_LOG_LOGIC (
"Ignoring an update message from an excluded interface: " << incomingInterface);
964 for (std::list<RipRte>::iterator iter = rtes.begin ();
965 iter != rtes.end (); iter++)
967 if (iter->GetRouteMetric () == 0 || iter->GetRouteMetric () >
m_linkDown)
969 NS_LOG_LOGIC (
"Ignoring an update message with malformed metric: " <<
int (iter->GetRouteMetric ()));
972 if (iter->GetPrefix ().IsLocalhost () ||
973 iter->GetPrefix ().IsBroadcast () ||
974 iter->GetPrefix ().IsMulticast ())
976 NS_LOG_LOGIC (
"Ignoring an update message with wrong prefixes: " << iter->GetPrefix ());
981 bool changed =
false;
983 for (std::list<RipRte>::iterator iter = rtes.begin ();
984 iter != rtes.end (); iter++)
986 Ipv4Mask rtePrefixMask = iter->GetSubnetMask ();
991 uint32_t interfaceMetric = 1;
996 uint64_t rteMetric = iter->GetRouteMetric () + interfaceMetric;
1006 if (it->first->GetDestNetwork () == rteAddr &&
1007 it->first->GetDestNetworkMask () == rtePrefixMask)
1010 if (rteMetric < it->
first->GetRouteMetric ())
1012 if (senderAddress != it->first->GetGateway ())
1020 it->first->SetRouteTag (iter->GetRouteTag ());
1021 it->first->SetRouteChanged (
true);
1022 it->second.Cancel ();
1026 else if (rteMetric == it->first->GetRouteMetric ())
1028 if (senderAddress == it->first->GetGateway ())
1030 it->second.Cancel ();
1044 it->second.Cancel ();
1050 else if (rteMetric > it->first->GetRouteMetric () && senderAddress == it->first->GetGateway ())
1052 it->second.Cancel ();
1055 it->first->SetRouteMetric (rteMetric);
1057 it->first->SetRouteTag (iter->GetRouteTag ());
1058 it->first->SetRouteChanged (
true);
1059 it->second.Cancel ();
1072 NS_LOG_LOGIC (
"Received a RTE with new route, adding.");
1097 uint32_t
interface = iter->
second;
1101 uint16_t mtu =
m_ipv4->GetMtu (interface);
1114 bool splitHorizoning = (rtIter->first->GetInterface () == interface);
1117 NS_LOG_DEBUG (
"Processing RT " << rtDestAddr <<
" " <<
int(rtIter->first->IsRouteChanged ()));
1122 (rtIter->first->GetInterface () != interface));
1124 bool sameNetwork =
false;
1125 for (uint32_t index = 0; index <
m_ipv4->GetNAddresses (interface); index++)
1134 if ((isGlobal || isDefaultRoute) &&
1135 (periodic || rtIter->first->IsRouteChanged ()) &&
1139 rte.
SetPrefix (rtIter->first->GetDestNetwork ());
1178 rtIter->first->SetRouteChanged (
false);
1188 NS_LOG_LOGIC (
"Skipping Triggered Update due to cooldown");
1243 std::map<uint32_t, uint8_t>::const_iterator iter =
m_interfaceMetrics.find (interface);
1246 return iter->second;
1284 uint32_t
interface = iter->
second;
1307 : m_tag (0), m_metric (0), m_status (RIP_INVALID), m_changed (false)
1313 m_tag (0), m_metric (0), m_status (RIP_INVALID), m_changed (false)
1319 m_tag (0), m_metric (0), m_status (RIP_INVALID), m_changed (false)
1330 if (
m_tag != routeTag)
1383 os << static_cast<const Ipv4RoutingTableEntry &>(rte);
a polymophic address class
bool IsNull(void) const
Check for null implementation.
Hold variables of type enum.
An identifier for simulation events.
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
uint16_t GetPort(void) const
Ipv4Address GetIpv4(void) const
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
Ipv4 addresses are stored in host order in this class.
bool IsMulticast(void) const
bool IsBroadcast(void) const
static Ipv4Address GetAny(void)
bool IsLocalMulticast(void) const
Ipv4Address CombineMask(Ipv4Mask const &mask) const
Combine this address with a network mask.
static Ipv4Address GetZero(void)
a class to store IPv4 address information on an interface
Ipv4InterfaceAddress::InterfaceAddressScope_e GetScope(void) const
Get address scope.
Ipv4Mask GetMask(void) const
Get the network mask.
Ipv4Address GetLocal(void) const
Get the local address.
a class to represent an Ipv4 address mask
uint16_t GetPrefixLength(void) const
static Ipv4Mask GetZero(void)
bool IsMatch(Ipv4Address a, Ipv4Address b) const
This class implements Linux struct pktinfo in order to deliver ancillary information to the socket in...
uint32_t GetRecvIf(void) const
Get the tag's receiving interface.
Abstract base class for IPv4 routing protocols.
A record of an IPv4 routing table entry for Ipv4GlobalRouting and Ipv4StaticRouting.
uint32_t GetInterface(void) const
bool IsGateway(void) const
Ipv4Address GetDestNetwork(void) const
Ipv4Address GetDest(void) const
Ipv4Mask GetDestNetworkMask(void) const
Ipv4Address GetGateway(void) const
static std::string FindName(Ptr< Object > object)
Given a pointer to an object, look to see if that object has a name associated with it and,...
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
virtual void DoDispose(void)
Destructor implementation.
virtual void DoInitialize(void)
Initialize() implementation.
std::ostream * GetStream(void)
Return a pointer to an ostream previously set in the wrapper.
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
void AddHeader(const Header &header)
Add header to this packet.
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Smart pointer class similar to boost::intrusive_ptr.
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
RIP Routing Protocol, defined in RFC 2453.
std::map< Ptr< Socket >, uint32_t >::iterator SocketListI
Socket list type iterator.
void SetInterfaceMetric(uint32_t interface, uint8_t metric)
Set the metric for an interface.
void DoSendRouteUpdate(bool periodic)
Send Routing Updates on all interfaces.
virtual void NotifyInterfaceDown(uint32_t interface)
std::list< std::pair< RipRoutingTableEntry *, EventId > >::const_iterator RoutesCI
Const Iterator for container for the network routes.
SplitHorizonType_e m_splitHorizonStrategy
Split Horizon strategy.
Time m_startupDelay
Random delay before protocol startup.
std::map< uint32_t, uint8_t > m_interfaceMetrics
Map of interface metrics.
std::set< uint32_t > m_interfaceExclusions
Set of excluded interfaces.
uint32_t m_linkDown
Link down value.
void HandleRequests(RipHeader hdr, Ipv4Address senderAddress, uint16_t senderPort, uint32_t incomingInterface, uint8_t hopLimit)
Handle RIP requests.
bool RouteInput(Ptr< const Packet > p, const Ipv4Header &header, Ptr< const NetDevice > idev, UnicastForwardCallback ucb, MulticastForwardCallback mcb, LocalDeliverCallback lcb, ErrorCallback ecb)
Route an input packet (to be forwarded or locally delivered)
void DeleteRoute(RipRoutingTableEntry *route)
Delete a route.
void InvalidateRoute(RipRoutingTableEntry *route)
Invalidate a route.
void Receive(Ptr< Socket > socket)
Receive RIP packets.
Ptr< Ipv4Route > Lookup(Ipv4Address dest, bool setSource, Ptr< NetDevice >=0)
Lookup in the forwarding table for destination.
virtual void DoDispose()
Dispose this object.
virtual void NotifyInterfaceUp(uint32_t interface)
EventId m_nextUnsolicitedUpdate
Next Unsolicited Update event.
Ptr< Ipv4Route > RouteOutput(Ptr< Packet > p, const Ipv4Header &header, Ptr< NetDevice > oif, Socket::SocketErrno &sockerr)
Query routing cache for an existing route, for an outbound packet.
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
void DoInitialize()
Start protocol operation.
virtual void NotifyRemoveAddress(uint32_t interface, Ipv4InterfaceAddress address)
EventId m_nextTriggeredUpdate
Next Triggered Update event.
Ptr< Ipv4 > m_ipv4
IPv4 reference.
void SendRouteRequest()
Send Routing Request on all interfaces.
std::list< std::pair< RipRoutingTableEntry *, EventId > >::iterator RoutesI
Iterator for container for the network routes.
Time m_timeoutDelay
Delay before invalidating a route.
void AddNetworkRouteTo(Ipv4Address network, Ipv4Mask networkPrefix, Ipv4Address nextHop, uint32_t interface)
Add route to network.
Ptr< Socket > m_multicastRecvSocket
multicast receive socket
Time m_minTriggeredUpdateDelay
Min cooldown delay after a Triggered Update.
virtual void NotifyAddAddress(uint32_t interface, Ipv4InterfaceAddress address)
@ SPLIT_HORIZON
Split Horizon.
@ NO_SPLIT_HORIZON
No Split Horizon.
@ POISON_REVERSE
Poison Reverse Split Horizon.
Time m_unsolicitedUpdate
time between two Unsolicited Routing Updates
std::set< uint32_t > GetInterfaceExclusions() const
Get the set of interface excluded from the protocol.
virtual void SetIpv4(Ptr< Ipv4 > ipv4)
virtual void PrintRoutingTable(Ptr< OutputStreamWrapper > stream, Time::Unit unit=Time::S) const
Print the Routing Table entries.
uint8_t GetInterfaceMetric(uint32_t interface) const
Get the metric for an interface.
static TypeId GetTypeId(void)
Get the type ID.
SocketList m_unicastSocketList
list of sockets for unicast messages (socket, interface index)
Time m_garbageCollectionDelay
Delay before deleting an INVALID route.
bool m_initialized
flag to allow socket's late-creation.
void SetInterfaceExclusions(std::set< uint32_t > exceptions)
Set the set of interface excluded from the protocol.
void AddDefaultRouteTo(Ipv4Address nextHop, uint32_t interface)
Add a default route to the router through the nextHop located on interface.
void SendUnsolicitedRouteUpdate(void)
Send Unsolicited Routing Updates on all interfaces.
Routes m_routes
the forwarding table for network.
Time m_maxTriggeredUpdateDelay
Max cooldown delay after a Triggered Update.
void SendTriggeredRouteUpdate()
Send Triggered Routing Updates on all interfaces.
void HandleResponses(RipHeader hdr, Ipv4Address senderAddress, uint32_t incomingInterface, uint8_t hopLimit)
Handle RIP responses.
Ptr< UniformRandomVariable > m_rng
Rng stream.
void SetRouteMetric(uint8_t routeMetric)
Set the route metric.
Status_e m_status
route status
uint8_t GetRouteMetric(void) const
Get the route metric.
bool m_changed
route has been updated
void SetRouteStatus(Status_e status)
Set the route status.
bool IsRouteChanged(void) const
Get the route changed status.
void SetRouteTag(uint16_t routeTag)
Set the route tag.
uint16_t GetRouteTag(void) const
Get the route tag.
void SetRouteChanged(bool changed)
Set the route as changed.
Status_e GetRouteStatus(void) const
Get the route status.
uint8_t m_metric
route metric
RipRoutingTableEntry(void)
virtual ~RipRoutingTableEntry()
Rip v2 Routing Table Entry (RTE) - see RFC 2453.
void SetSubnetMask(Ipv4Mask subnetMask)
Set the subnet mask.
void SetRouteMetric(uint32_t routeMetric)
Set the route metric.
void SetPrefix(Ipv4Address prefix)
Set the prefix.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
void SetRouteTag(uint16_t routeTag)
Set the route tag.
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
void SetRecvPktInfo(bool flag)
Enable/Disable receive packet information to socket.
virtual void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
virtual int Close(void)=0
Close a socket.
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
This method wraps the creation of sockets that is performed on a given node by a SocketFactory specif...
SocketErrno
Enumeration of the possible errors returned by a socket.
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
void SetIpRecvTtl(bool ipv4RecvTtl)
Tells a socket to pass information about IP_TTL up the stack.
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)=0
Read a single packet from the socket and retrieve the sender address.
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)=0
Send data to a specified peer.
This class implements a tag that carries the socket-specific TTL of a packet to the IP layer.
uint8_t GetTtl(void) const
Get the tag's TTL.
void SetTtl(uint8_t ttl)
Set the tag's TTL.
Simulation virtual time values and global simulation resolution.
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Unit
The unit to use to interpret a number representing time.
TimeWithUnit As(const enum Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
AttributeValue implementation for Time.
a unique identifier for an interface.
static TypeId LookupByName(std::string name)
Get a TypeId by name.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Hold an unsigned integer type.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Time Seconds(double value)
Construct a Time in the indicated unit.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeEnumChecker(int v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...