Netwokring

Networking is available via lwip <https://www.nongnu.org/lwip/2_1_x/index.html> library onto which platform’s networking is built. By default, IPv6 protocol is used.

The networking is represented by the class NetworkManager which enables user not only an easier control over network interfaces, their configuration, etc., but also provides additional functionality such as routing support. There should be always one instance of the class running within a single module as the NetworkManager takes care of all its connectors – within the networking, they are represented with Interface – and there is an additional virtual interface (“rl0”) independent of physical connectors used as the main interface of the module. This virtual interface is the interface you want to configure, if you don’t know which one.

The usage is simple, the class itself initializes everything using RoFI. For example, let us initialize networking of a module and assign an IPv6 address to it.

#include <networking/networkManager.hpp>

// ...
// if lwip's tcpip stack is not initialized, call
// tcpip_init( nullptr, nullptr );

hal::RoFI localRofi = RoFI::getLocalRoFI();

NetworkManager net( localRofi );

// adds address fc07:0:0:1::1 with mask /80 to interface "rl0", which is the virtual one
net.addAddress( "fc07:0:0:1::1"_ip, 80, net.interface( "rl0" ) );
// set all interfaces up -- to process incomming/outcomming traffic
net.setUp();

Now, we have a module with an IP address configured. Suppose, that we have a network of interconnected modules where each has its own address. To be able to send a message between two modules, the routing table of a receiver (and all modules in-between) has to contain a path to receiver. To populate the routing table, the routing protocol must be configured.

The RoFI platform offers multiple routing protocols by default; these are SimplePeriodic, SimpleReactive, and RRP. The first two protocols are very simple and they always share their whole routing table. The main difference is the way messages are sent; the first one sends updates periodically, the second one sends messages on network changes only. The third protocol tries to be smarter about sharing routing information; more details can be found in the Protocols section.

Using SimpleReactive protocol, we enable routing with

#include <networking/protocols/simpleReactive.hpp>

// the code from above

// Add protocol into the NetworkManager so that it can be used
auto* simpleReactive = net.addProtocol( SimpleReactive() );

// now we enable the protocol on all interfaces
net.setProtocol( simpleReactive );
// you can also enable the protocol only on certain interfaces
// e.g., to enable the protocol on interface "rd4", you can call
//     net.setProtocol( simpleReactive, net.getInterface( "rd4" ) );
//
// you could also accomplish the same as above with a for loop
//    for ( const auto& i : net.interfaces() ) {
//        net.setProtocol( simpleReactive, net.interface( i.name() ) );
//    }
//

The routing process is now running, so the interconnected modules will share necessary information and populate the routing table. Then you can use regular sockets from lwip library and send messages accross the network.

Network Manager

class NetworkManager

Public Functions

NetworkManager() = delete
inline explicit NetworkManager(hal::RoFI rofi)

Create a Network Manager instance for module corresponding to given RoFI proxy.

This constructor creates MAC adress from the proxy’s id.

inline NetworkManager(hal::RoFI rofi, PhysAddr p)

Create a Network Manager instance for module corresponding to given RoFI proxy.

This constructor uses p as the MAC address.

inline const Interface *findInterface(const Interface::Name &name) const

Finds an interface of given name among Network Manager’s interfaces.

inline const Interface &interface(const Interface::Name &name) const

Returns an interface of given name.

The interface must exist within Network Manager.

inline auto interfaces() const

Get iterable range of interfaces within the Network Manager.

template<std::derived_from<Protocol> Proto>
inline Protocol *addProtocol(const Proto &p)

Add given protocol into the Network Manager.

There must NOT be a protocol with same name and/or listenner address present in the Network Manager.

Parameters:

p – protocol to add

Returns:

Pointer to the added instance under control of the Network Manager.

inline auto protocols() const

Get iterable range of protocols within the Network Manager.

inline bool addAddress(const Ip6Addr &ip, uint8_t mask, const Interface &i)

Add given address and mask onto a given interface.

Returns:

true if the address was added succesfully

Returns:

false otherwise

inline bool removeAddress(const Ip6Addr &ip, uint8_t mask, const Interface &i)

Remove given address and mask from the given interface.

Returns:

true if the address was removed succesfully

Returns:

false otherwise

inline Protocol *getProtocol(const std::string &name)

Get protocol of a given name.

Names are unique within the protocol.

Returns:

a pointer to a protocol of a given name

inline void setProtocol(Protocol &proto)

Set protocol to run on all interfaces.

inline void setProtocol(Protocol &proto, const Interface &i)

Set protocol to run on a given interface.

This sets up all necessary listeners, starts processing protocol messages, etc.

inline void removeProtocol(Protocol &proto, const Interface &i)

Remove protocol from the given interface.

This unsets all listeners, stops processing protocol’s messages.

inline void setUp(const Interface &i)

Set the interface up.

The interface starts processing trafic.

inline void setUp()

Set all interfaces up.

inline void setDown(const Interface &i)

Set the interface down.

The interface stops processing trafic.

inline void setDown()

Set all interfaces down.

inline const RoutingTable &routingTable() const

Get network manager’s routing table.

inline bool addRoute(const Ip6Addr ip, uint8_t mask, const Interface::Name &ifname, RoutingTable::Cost cost)

Add a static route into the routing table.

Returns:

true if the route was succesfully added

Returns:

false if the interface does not exist or the route was not added

inline bool rmRoute(const Ip6Addr ip, uint8_t mask, const Interface::Name &ifname)

Remove a static route into the routing table.

Returns:

true if the route was succesfully removed

Returns:

false if the interface does not exist or the route was not removed

inline void log(Logger::Level l, const std::string &msg)

Logs a given message with corresponding severity level.

inline void log(Logger::Level l, const std::string &where, const std::string &msg)

Logs a given message with corresponding severity level specifying the component where the event originated.

inline auto logs() const

Returns an iterable range of logs.

inline auto logsFrom(const Interface &i) const

Returns an iterable range of logs only from the specified component.

inline auto logs(Logger::Level l) const

Returns an iterable range of logs with given severity level.

Protocols

The interface is desribed by the class :cpp:class`Protocol <rofi::net::Protocol>`

class Protocol

Virtual class defining the interface for NetworkManager’s protocols.

Subclassed by rofi::net::LeaderElect, rofi::net::MessageDistributor, rofi::net::RRP, rofi::net::SimplePeriodic, rofi::net::SimpleReactive

Public Types

enum class Route

Enum for communicating the route updates.

Values:

enumerator ADD

A new route to be added.

enumerator RM

A known route is no longer valid.

enum class ConfigAction

Enum for communicating the interface state updates.

Values:

enumerator ADD_IP

Interface shoud get a new IP.

enumerator REMOVE_IP

Interface should lose an IP.

enumerator SHUT_DOWN

Interface should be shut down.

enumerator SET_UP

Interface should be set up.

enumerator RESPOND

A response on obtained update is needed.

using RoutingTableFun = std::function<RoutingTable::Records()>
using ConfigChange = std::tuple<Interface::Name, Ip6Addr, uint8_t>

Public Functions

virtual ~Protocol() = default
virtual bool onMessage(const std::string &interfaceName, hal::PBuf packet) = 0

Process the incomming message on given interface.

Returns:

true if if a change of state is required.

inline virtual bool onInterfaceEvent(const Interface&, bool)

This function is called when an event (Connected, Disconnected) on connector arises.

Parameters:
  • interface – on which event originated

  • connected – true if a connector was connected, false if it was disconnected

Returns:

true if any the event caused any changes.

virtual bool afterMessage(const Interface &i, std::function<void(PBuf&&)> f, void *args) = 0

This function is called after processing updates from onMessage (if any) and provides to the protocol the ability of sending a message via given interface.

Returns:

bool indicating if any local change is required to take place.

inline virtual bool hasRouteUpdates() const

Function that returns true if there are any pending routing updates.

inline virtual std::vector<std::pair<Route, RoutingTable::Record>> getRouteUpdates() const

Function that outputs all routing updates possibly created in onMessage.

This function is called in case onMessage and hasRouteUpdates return true. The default implementation returns an empty vector, so it is not necessary to override this for non-routing protocols.

Returns:

A vector of pairs with the type of change (e.g., a new route) and its RoutingTable::Record to be added.

inline virtual bool hasConfigUpdates() const

Function that returns true if there are any pending configuration updates.

inline virtual std::vector<std::pair<ConfigAction, ConfigChange>> getConfigUpdates() const

Function that outputs all interface/state related updates possibly created in onMessage

This function is called in case onMessage and hasConfigUpdates return true. The default imlementation return an empty vector, so it is not necessary to override this for routing-only protocols.

Returns:

A vector of pairs with the type of change (e.g., a new IP) and its ConfigChange with all necessary information.

virtual void clearUpdates() = 0

Clear any (cached) updates.

This function should clear all the updates within the protocol. By calling this function, the NetworkManager signalizes that all the updates (both – routing and interface related) were gathered already and are no longer needed.

inline virtual bool addAddressOn(const Interface&, const Ip6Addr&, uint8_t)

Indicate a new address on given interface.

Returns:

true if any change was caused by this change.

inline virtual bool rmAddressOn(const Interface&, const Ip6Addr&, uint8_t)

Indicate a removal of an address on given interface.

Returns:

true if any change was caused by this change.

virtual bool addInterface(const Interface &interface) = 0

Add the given interface into the protocol.

Returns:

true if the interface was succesfully added.

virtual bool removeInterface(const Interface &interface) = 0

Remove the given interface from the protocol.

Returns:

true if the interface was succesfully removed.

virtual bool manages(const Interface &interface) const = 0

Given an interface, decide if it is managed by the protocol.

Namely, it should hold that after adding an interface via addInterface which returns true, then manages should return true for such interface.

Returns:

true if the interface is managed by the protocol.

inline void setRoutingTableCB(RoutingTableFun f)

This function can set the callback for the routing table.

The callback itself should be a function that returns the current state of the table for given protocol – records learned through it.

inline RoutingTable::Records routingTableCB() const

Function that outputs all the records from routing table related to the protocol.

Internally, it uses the callback set in setRoutingTableCB function. If any such function is provided, then this function returns an empty collection.

virtual Ip6Addr address() const = 0

Returns a multicast IP on which the protocol listener will be running.

This should be unique for each protocol.

virtual std::string name() const = 0

Returns a name of the protocol.

This should be unique for each protocol.

inline virtual std::string info() const

Returns a string representing some basic information about the protocol (e.g., its name and listenner address).

And there are some default implementations. For routing we have

class SimplePeriodic : public rofi::net::Protocol

Proof-of-concept routing protocol using IP layer only with periodic messages.

Public Functions

inline SimplePeriodic()
inline SimplePeriodic(int period)
inline virtual bool onMessage(const std::string &interfaceName, rofi::hal::PBuf packetWithHeader) override
inline virtual bool afterMessage(const Interface &i, std::function<void(PBuf&&)> f, void *args) override

This function is called after processing updates from onMessage (if any) and provides to the protocol the ability of sending a message via given interface.

Returns:

bool indicating if any local change is required to take place.

inline virtual bool onInterfaceEvent(const Interface &interface, bool connected) override

This function is called when an event (Connected, Disconnected) on connector arises.

Parameters:
  • interface – on which event originated

  • connected – true if a connector was connected, false if it was disconnected

Returns:

true if any the event caused any changes.

inline virtual bool hasRouteUpdates() const override

Function that returns true if there are any pending routing updates.

inline virtual std::vector<std::pair<Route, RoutingTable::Record>> getRouteUpdates() const override

Function that outputs all routing updates possibly created in onMessage.

This function is called in case onMessage and hasRouteUpdates return true. The default implementation returns an empty vector, so it is not necessary to override this for non-routing protocols.

Returns:

A vector of pairs with the type of change (e.g., a new route) and its RoutingTable::Record to be added.

inline virtual void clearUpdates() override

Clear any (cached) updates.

This function should clear all the updates within the protocol. By calling this function, the NetworkManager signalizes that all the updates (both – routing and interface related) were gathered already and are no longer needed.

inline virtual bool addAddressOn(const Interface &interface, const Ip6Addr &ip, uint8_t mask) override

Indicate a new address on given interface.

Returns:

true if any change was caused by this change.

inline virtual bool rmAddressOn(const Interface &interface, const Ip6Addr &ip, uint8_t mask) override

Indicate a removal of an address on given interface.

Returns:

true if any change was caused by this change.

inline virtual bool addInterface(const Interface &interface) override

Add the given interface into the protocol.

Returns:

true if the interface was succesfully added.

inline virtual bool removeInterface(const Interface &interface) override

Remove the given interface from the protocol.

Returns:

true if the interface was succesfully removed.

inline virtual bool manages(const Interface &interface) const override

Given an interface, decide if it is managed by the protocol.

Namely, it should hold that after adding an interface via addInterface which returns true, then manages should return true for such interface.

Returns:

true if the interface is managed by the protocol.

inline virtual Ip6Addr address() const

Returns a multicast IP on which the protocol listener will be running.

This should be unique for each protocol.

inline virtual std::string name() const

Returns a name of the protocol.

This should be unique for each protocol.

class SimpleReactive : public rofi::net::Protocol

Proof-of-concept routing protocol using IP layer only with reactive messages.

Public Functions

inline virtual bool onMessage(const std::string &interfaceName, rofi::hal::PBuf packetWithHeader) override
inline virtual bool afterMessage(const Interface &i, std::function<void(PBuf&&)> f, void*) override

This function is called after processing updates from onMessage (if any) and provides to the protocol the ability of sending a message via given interface.

Returns:

bool indicating if any local change is required to take place.

inline virtual bool onInterfaceEvent(const Interface &interface, bool connected) override

This function is called when an event (Connected, Disconnected) on connector arises.

Parameters:
  • interface – on which event originated

  • connected – true if a connector was connected, false if it was disconnected

Returns:

true if any the event caused any changes.

inline virtual bool hasRouteUpdates() const override

Function that returns true if there are any pending routing updates.

inline virtual std::vector<std::pair<Route, RoutingTable::Record>> getRouteUpdates() const override

Function that outputs all routing updates possibly created in onMessage.

This function is called in case onMessage and hasRouteUpdates return true. The default implementation returns an empty vector, so it is not necessary to override this for non-routing protocols.

Returns:

A vector of pairs with the type of change (e.g., a new route) and its RoutingTable::Record to be added.

inline virtual void clearUpdates() override

Clear any (cached) updates.

This function should clear all the updates within the protocol. By calling this function, the NetworkManager signalizes that all the updates (both – routing and interface related) were gathered already and are no longer needed.

inline virtual bool addAddressOn(const Interface &interface, const Ip6Addr &ip, uint8_t mask) override

Indicate a new address on given interface.

Returns:

true if any change was caused by this change.

inline virtual bool rmAddressOn(const Interface &interface, const Ip6Addr &ip, uint8_t mask) override

Indicate a removal of an address on given interface.

Returns:

true if any change was caused by this change.

inline virtual bool addInterface(const Interface &interface) override

Add the given interface into the protocol.

Returns:

true if the interface was succesfully added.

inline virtual bool removeInterface(const Interface &interface) override

Remove the given interface from the protocol.

Returns:

true if the interface was succesfully removed.

inline virtual bool manages(const Interface &interface) const override

Given an interface, decide if it is managed by the protocol.

Namely, it should hold that after adding an interface via addInterface which returns true, then manages should return true for such interface.

Returns:

true if the interface is managed by the protocol.

inline virtual Ip6Addr address() const

Returns a multicast IP on which the protocol listener will be running.

This should be unique for each protocol.

inline virtual std::string name() const

Returns a name of the protocol.

This should be unique for each protocol.

class RRP : public rofi::net::Protocol

Public Types

using Cost = uint8_t

Public Functions

virtual ~RRP() = default
inline virtual bool afterMessage(const Interface &i, std::function<void(PBuf&&)> f, void*) override

This function is called after processing updates from onMessage (if any) and provides to the protocol the ability of sending a message via given interface.

Returns:

bool indicating if any local change is required to take place.

inline virtual bool onMessage(const std::string &interfaceName, rofi::hal::PBuf packet) override
inline virtual bool onInterfaceEvent(const Interface &interface, bool connected) override

This function is called when an event (Connected, Disconnected) on connector arises.

Parameters:
  • interface – on which event originated

  • connected – true if a connector was connected, false if it was disconnected

Returns:

true if any the event caused any changes.

inline virtual bool hasRouteUpdates() const override

Function that returns true if there are any pending routing updates.

inline virtual std::vector<std::pair<Route, RoutingTable::Record>> getRouteUpdates() const override

Function that outputs all routing updates possibly created in onMessage.

This function is called in case onMessage and hasRouteUpdates return true. The default implementation returns an empty vector, so it is not necessary to override this for non-routing protocols.

Returns:

A vector of pairs with the type of change (e.g., a new route) and its RoutingTable::Record to be added.

inline virtual void clearUpdates() override

Clear any (cached) updates.

This function should clear all the updates within the protocol. By calling this function, the NetworkManager signalizes that all the updates (both – routing and interface related) were gathered already and are no longer needed.

inline virtual bool addAddressOn(const Interface &interface, const Ip6Addr &ip, uint8_t mask) override

Indicate a new address on given interface.

Returns:

true if any change was caused by this change.

inline virtual bool rmAddressOn(const Interface &interface, const Ip6Addr &ip, uint8_t mask) override

Indicate a removal of an address on given interface.

Returns:

true if any change was caused by this change.

inline virtual bool addInterface(const Interface &interface) override

Add the given interface into the protocol.

Returns:

true if the interface was succesfully added.

inline virtual bool removeInterface(const Interface &interface) override

Remove the given interface from the protocol.

Returns:

true if the interface was succesfully removed.

inline virtual bool manages(const Interface &interface) const override

Given an interface, decide if it is managed by the protocol.

Namely, it should hold that after adding an interface via addInterface which returns true, then manages should return true for such interface.

Returns:

true if the interface is managed by the protocol.

inline virtual rofi::hal::Ip6Addr address() const override

Returns a multicast IP on which the protocol listener will be running.

This should be unique for each protocol.

inline virtual std::string name() const override

Returns a name of the protocol.

This should be unique for each protocol.

inline virtual std::string info() const override

Returns a string representing some basic information about the protocol (e.g., its name and listenner address).

and there is also a simple leader elect protocol available

class LeaderElect : public rofi::net::Protocol

Proof-of-concept of a leader election protocol using IP layer only.

Public Functions

inline LeaderElect(int id, const Ip6Addr &leaderAddr, uint8_t mask)
virtual ~LeaderElect() = default
inline virtual bool onMessage(const std::string &interfaceName, rofi::hal::PBuf packetWithHeader)
inline virtual bool afterMessage(const Interface &i, std::function<void(PBuf&&)> f, void*)

This function is called after processing updates from onMessage (if any) and provides to the protocol the ability of sending a message via given interface.

Returns:

bool indicating if any local change is required to take place.

inline virtual bool hasConfigUpdates() const override

Function that returns true if there are any pending configuration updates.

inline virtual std::vector<std::pair<ConfigAction, ConfigChange>> getConfigUpdates() const

Function that outputs all interface/state related updates possibly created in onMessage

This function is called in case onMessage and hasConfigUpdates return true. The default imlementation return an empty vector, so it is not necessary to override this for routing-only protocols.

Returns:

A vector of pairs with the type of change (e.g., a new IP) and its ConfigChange with all necessary information.

inline virtual void clearUpdates()

Clear any (cached) updates.

This function should clear all the updates within the protocol. By calling this function, the NetworkManager signalizes that all the updates (both – routing and interface related) were gathered already and are no longer needed.

inline virtual bool addInterface(const Interface &interface)

Add the given interface into the protocol.

Returns:

true if the interface was succesfully added.

inline virtual bool removeInterface(const Interface &interface)

Remove the given interface from the protocol.

Returns:

true if the interface was succesfully removed.

inline virtual bool manages(const Interface &interface) const override

Given an interface, decide if it is managed by the protocol.

Namely, it should hold that after adding an interface via addInterface which returns true, then manages should return true for such interface.

Returns:

true if the interface is managed by the protocol.

inline virtual Ip6Addr address() const override

Returns a multicast IP on which the protocol listener will be running.

This should be unique for each protocol.

inline virtual std::string name() const override

Returns a name of the protocol.

This should be unique for each protocol.

inline virtual std::string info() const override

Returns a string representing some basic information about the protocol (e.g., its name and listenner address).

Command Line Interface (CLI)

Simple CLI interface for the network management is availabe.

class NetworkManagerCli

Class for CLI management for NetworkManager class.

Public Functions

inline NetworkManagerCli(NetworkManager &netManager)
inline bool command(const std::string &cmd)

Process given command and makes appropriate changes to underlying NetworkManager.

Returns:

true if the command was succesfully parsed.

inline bool command(std::istream &ss)

Overloaded variant of the previous command function.

inline void help() const

Prints out help message containing the usage description.

Components

The rest of components are listed here. The user will encouter them, but changes in their configuration should be done indirectly via NetworkManager.