TODO: architecture overview (providers, drivers, protocol)
ONOS interacts with the underlying network with the help of its Providers. Providers in ONOS are standalone ONOS applications based on OSGi components that can be dynamically activated and deactivated at runtime. The main purpose of providers is to abstract the configuration, control and management operations of a specific family of devices (e.g. OpenFlow, SNMP, Netconf, etc.).
- DeviceProvider: responsible of notifying the core through the DeviceProviderService API about the discovery of new devices and their description (such as vendor/model, available ports, hardware/software version, etc.), as long as exposing method to DeviceManager in order to perform operations such as setting a port operational state (up or down).
- PacketProvider: responsible of notifying the core through the PacketProviderService API of a packet-in event received from the data plane, as long as exposing methods to PacketManager in order to generate packet-outs at the data plane.
- LinkProvider: is responsible of notifying the core through the LinkProviderService API of the discovery of new links, while not methods are exposed to any manager since it would make no sense to perform an operation on a logical entity such as a link.
“Protocols” in ONOS are modules contained under the directory /protocols and usually named onos-<protocol_name>. A protocol module contains the implementation of all those features needed by ONOS to communicate with devices implementing a specific runtime control and/or management protocol. Examples of what ONOS considers protocols are OpenFlow, NETCONF, SNMP, OVSDB, etc. A protocol usually depends on third-party communication libraries (e.g. openflowj, snmp4j, thrift, etc.).
A best practice used in ONOS is to divide the protocol module into two submodules, API (named onos-<protocol_name>-api) and CTL (onos-<protocol_name>-ctl). As suggested by the name, API usually contains mostly Java interfaces and simple classes representing the fundamental objects of a protocol (e.g. a FlowMod and a Controller in OpenFlow), while CTL contains the specific implementation of the API.
The division between API and CTL is done for cleanness and inter-module dependency, such that other modules inside ONOS can simply depend on the API without having to bring in all the implementations of the CTL module.
The API module usually contains interfaces that abstract the operations and messages necessary to control a device.. For example, given an example protocol called “Foo”, we can imagine having a FooController interface that exposes informations about the devices connected to it. Another interface can be the FooSession that abstracts the state of the underlying transport session with the device.
Some example of the operation that the protocol module exposes are:
OpenFlow: FlowMods, GroupMods, etc
Rest: implements CRUD operations (GET, POST, DELETE, etc...)
Netconf: Open/close session, setConfiguration, getConfiguration
The CTL module contains the implementation of the APIs. There can be multiple implementations for a single interface to provide different types of logic according to the use case (e.g. persistent and nonpersistent transport sessions). The implementation classes translate between high level Java calls, for example doOperation(operation), to the equivalent wire messages and system calls to communicate with the device over the control channel. Examples of operations implemented in the CTL module are: handshaking, connection establishment and maintenance with the device. If the transport session with the device is a persistent one, for example TCP in OpenFlow or in NETCONF, all the state about the connection is maintained in the protocol subsystem, meaning that upper layers such as drivers or providers, do not need to deal with connection open/close, reconnection in case of network errors, etc.
The Protocol is not an application but a simple set of OSGI components that can be loaded and unloaded from KARAF if somebody needs it. Usually the <protocol-name>Controller is a OSGI component that can be referenced from outside the protocol module, usually in the providers and drivers.
For a new device the contact information and any other detail is fed to the protocol from the provider or taken from the core. If it’s not fed from the core, the end point to talk to the device: IP and port, is taken parsing the deviceId.
Classes and modules
In summary if you are implementing a new protocol in ONOS the protocol module should only contain:
API sub-module with interfaces describing operations and state logic
CTL sub-module with implementation of the logic for the exposed interfaces
Dependencies on third party libraries that enable communication to and from the device.
The protocol module should not contain any device model specific or vendor specific element, just “language” specifics.