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