7 The NetIDE Network Engine enables portability and cooperation inside a
8 single network by using a client/server multi-controller SDN
9 architecture. Separate "Client SDN Controllers" host the various SDN
10 Applications with their access to the actual physical network abstracted
11 and coordinated through a single "Server SDN Controller", in this
12 instance OpenDaylight. This allows applications written for
13 Ryu/Floodlight/Pyretic to execute on OpenDaylight managed
16 The "Network Engine" is modular by design:
18 - An OpenDaylight plugin, "shim", sends/receives messages to/from
19 subscribed SDN Client Controllers. This consumes the ODL OpenFlow
22 - An initial suite of SDN Client Controller "Backends": Floodlight,
23 Ryu, Pyretic. Further controllers may be added over time as the
26 The Network Engine provides a compatibility layer capable of translating
27 calls of the network applications running on top of the client
28 controllers, into calls for the server controller framework. The
29 communication between the client and the server layers is achieved
30 through the NetIDE intermediate protocol, which is an application-layer
31 protocol on top of TCP that transmits the network control/management
32 messages from the client to the server controller and vice-versa.
33 Between client and server controller sits the Core Layer which also
34 "speaks" the intermediate protocol. The core layer implements three main
37 i. interfacing with the client backends and server shim, controlling
38 the lifecycle of controllers as well as modules in them,
40 ii. orchestrating the execution of individual modules (in one client
41 controller) or complete applications (possibly spread across
42 multiple client controllers),
44 iii. interfacing with the tools.
46 .. figure:: ./images/netide/arch-engine.jpg
47 :alt: NetIDE Network Engine Architecture
49 NetIDE Network Engine Architecture
51 NetIDE Intermediate Protocol
52 ----------------------------
54 The Intermediate Protocol serves several needs, it has to:
56 i. carry control messages between core and shim/backend, e.g., to
57 start up/take down a particular module, providing unique
58 identifiers for modules,
60 ii. carry event and action messages between shim, core, and backend,
61 properly demultiplexing such messages to the right module based on
64 iii. encapsulate messages specific to a particular SBI protocol version
65 (e.g., OpenFlow 1.X, NETCONF, etc.) towards the client controllers
66 with proper information to recognize these messages as such.
68 The NetIDE packages can be added as dependencies in Maven projects by
69 putting the following code in the *pom.xml* file.
74 <groupId>org.opendaylight.netide</groupId>
75 <artifactId>api</artifactId>
76 <version>${NETIDE_VERSION}</version>
79 The current stable version for NetIDE is ``0.2.0-Boron``.
81 Protocol specification
82 ~~~~~~~~~~~~~~~~~~~~~~
84 Messages of the NetIDE protocol contain two basic elements: the NetIDE
85 header and the data (or payload). The NetIDE header, described below, is
86 placed before the payload and serves as the communication and control
87 link between the different components of the Network Engine. The payload
88 can contain management messages, used by the components of the Network
89 Engine to exchange relevant information, or control/configuration
90 messages (such as OpenFlow, NETCONF, etc.) crossing the Network Engine
91 generated by either network application modules or by the network
94 The NetIDE header is defined as follows:
99 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
100 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
101 | netide_ver | type | length |
102 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
104 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
106 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
110 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
112 where each tick mark represents one bit position. Alternatively, in a
113 C-style coding format, the NetIDE header can be represented with the
118 struct netide_header {
127 - ``netide_ver`` is the version of the NetIDE protocol (the current
128 version is v1.2, which is identified with value 0x03).
130 - ``length`` is the total length of the payload in bytes.
132 - ``type`` contains a code that indicates the type of the message
133 according with the following values:
138 NETIDE_HELLO = 0x01 ,
139 NETIDE_ERROR = 0x02 ,
141 MODULE_ANNOUNCEMENT = 0x04 ,
142 MODULE_ACKNOWLEDGE = 0x05 ,
143 NETIDE_HEARTBEAT = 0x06 ,
144 NETIDE_OPENFLOW = 0x11 ,
145 NETIDE_NETCONF = 0x12 ,
149 - ``datapath_id`` is a 64-bit field that uniquely identifies the
152 - ``module_id`` is a 32-bits field that uniquely identifies Backends
153 and application modules running on top of each client controller. The
154 composition mechanism in the core layer leverages on this field to
155 implement the correct execution flow of these modules.
157 - ``xid`` is the transaction identifier associated to the each message.
158 Replies must use the same value to facilitate the pairing.
163 The first operation performed by a Backend is registering itself and the
164 modules that it is running to the Core. This is done by using the
165 ``MODULE_ANNOUNCEMENT`` and ``MODULE_ACKNOWLEDGE`` message types. As a
166 result of this process, each Backend and application module can be
167 recognized by the Core through an identifier (the ``module_id``) placed
168 in the NetIDE header. First, a Backend registers itself by using the
169 following schema: backend-<platform name>-<pid>.
171 For example,odule a Ryu Backend will register by using the following
172 name in the message backend-ryu-12345 where 12345 is the process ID of
173 the registering instance of the Ryu platform. The format of the message
178 struct NetIDE_message {
180 type = MODULE_ANNOUNCEMENT
181 length = len(" backend -< platform_name >-<pid >")
185 data = " backend -< platform_name >-<pid >"
188 The answer generated by the Core will include a ``module_id`` number and
189 the Backend name in the payload (the same indicated in the
190 ``MODULE_ANNOUNCEMENT`` message):
194 struct NetIDE_message {
196 type = MODULE_ACKNOWLEDGE
197 length = len(" backend -< platform_name >-<pid >")
199 module_id = MODULE_ID
201 data = " backend -< platform_name >-<pid >"
204 Once a Backend has successfully registered itself, it can start
205 registering its modules with the same procedure described above by
206 indicating the name of the module in the data (e.g. data="Firewall").
207 From this point on, the Backend will insert its own ``module_id`` in the
208 header of the messages it generates (e.g. heartbeat, hello messages,
209 OpenFlow echo messages from the client controllers, etc.). Otherwise, it
210 will encapsulate the control/configuration messages (e.g. FlowMod,
211 PacketOut, FeatureRequest, NETCONF request, etc.) generated by network
212 application modules with the specific +module\_id+s.
217 The heartbeat mechanism has been introduced after the adoption of the
218 ZeroMQ messaging queuing library to transmit the NetIDE messages.
219 Unfortunately, the ZeroMQ library does not offer any mechanism to find
220 out about disrupted connections (and also completely unresponsive
221 peers). This limitation of the ZeroMQ library can be an issue for the
222 Core’s composition mechanism and for the tools connected to the Network
223 Engine, as they cannot understand when an client controller disconnects
224 or crashes. As a consequence, Backends must periodically send (let’s say
225 every 5 seconds) a "heartbeat" message to the Core. If the Core does not
226 receive at least one "heartbeat" message from the Backend within a
227 certain timeframe, the Core considers it disconnected, removes all the
228 related data from its memory structures and informs the relevant tools.
229 The format of the message is the following:
233 struct NetIDE_message {
235 type = NETIDE_HEARTBEAT
238 module_id = backend -id
246 Upon a successful connection with the Core, the client controller must
247 immediately send a hello message with the list of the control and/or
248 management protocols needed by the applications deployed on top of it.
252 struct NetIDE_message {
253 struct netide_header header ;
257 The header contains the following values:
259 - ``netide ver=0x03``
261 - ``type=NETIDE_HELLO``
263 - ``length=2*NR_PROTOCOLS``
265 - ``data`` contains one 2-byte word (in big endian order) for each
266 protocol, with the first byte containing the code of the protocol
267 according to the above enum, while the second byte in- dictates the
268 version of the protocol (e.g. according to the ONF specification,
269 0x01 for OpenFlow v1.0, 0x02 for OpenFlow v1.1, etc.). NETCONF
270 version is marked with 0x01 that refers to the specification in the
271 RFC6241, while OpFlex version is marked with 0x00 since this protocol
272 is still in work-in-progress stage.
274 The Core relays hello messages to the server controller which responds
275 with another hello message containing the following:
277 - ``netide ver=0x03``
279 - ``type=NETIDE_HELLO``
281 - ``length=2*NR_PROTOCOLS``
283 If at least one of the protocols requested by the client is supported.
284 In particular, ``data`` contains the codes of the protocols that match
285 the client’s request (2-bytes words, big endian order). If the hand-
286 shake fails because none of the requested protocols is supported by the
287 server controller, the header of the answer is as follows:
289 - ``netide ver=0x03``
291 - ``type=NETIDE_ERROR``
293 - ``length=2*NR_PROTOCOLS``
295 - ``data`` contains the codes of all the protocols supported by the
296 server controller (2-bytes words, big endian order). In this case,
297 the TCP session is terminated by the server controller just after the
298 answer is received by the client. \`