Replace supported admonitions with rst directives
[docs.git] / docs / developer-guide / netide-developer-guide.rst
1 NetIDE Developer Guide
2 ======================
3
4 Overview
5 --------
6
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
14 infrastructure.
15
16 The "Network Engine" is modular by design:
17
18 -  An OpenDaylight plugin, "shim", sends/receives messages to/from
19    subscribed SDN Client Controllers. This consumes the ODL OpenFlow
20    Plugin
21
22 -  An initial suite of SDN Client Controller "Backends": Floodlight,
23    Ryu, Pyretic. Further controllers may be added over time as the
24    engine is extensible.
25
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
35 functions:
36
37 i.   interfacing with the client backends and server shim, controlling
38      the lifecycle of controllers as well as modules in them,
39
40 ii.  orchestrating the execution of individual modules (in one client
41      controller) or complete applications (possibly spread across
42      multiple client controllers),
43
44 iii. interfacing with the tools.
45
46 .. figure:: ./images/netide/arch-engine.jpg
47    :alt: NetIDE Network Engine Architecture
48
49    NetIDE Network Engine Architecture
50
51 NetIDE Intermediate Protocol
52 ----------------------------
53
54 The Intermediate Protocol serves several needs, it has to:
55
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,
59
60 ii.  carry event and action messages between shim, core, and backend,
61      properly demultiplexing such messages to the right module based on
62      identifiers,
63
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.
67
68 The NetIDE packages can be added as dependencies in Maven projects by
69 putting the following code in the *pom.xml* file.
70
71 ::
72
73     <dependency>
74         <groupId>org.opendaylight.netide</groupId>
75         <artifactId>api</artifactId>
76         <version>${NETIDE_VERSION}</version>
77     </dependency>
78
79 The current stable version for NetIDE is ``0.2.0-Boron``.
80
81 Protocol specification
82 ~~~~~~~~~~~~~~~~~~~~~~
83
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
92 elements.
93
94 The NetIDE header is defined as follows:
95
96 ::
97
98      0                   1                   2                   3
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     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
103     |                         xid                                   |
104     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
105     |                       module_id                               |
106     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
107     |                                                               |
108     +                     datapath_id                               +
109     |                                                               |
110     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
111
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
114 following structure:
115
116 ::
117
118     struct netide_header {
119         uint8_t netide_ver ;
120         uint8_t type ;
121         uint16_t length ;
122         uint32_t xid
123         uint32_t module_id
124         uint64_t datapath_id
125     };
126
127 -  ``netide_ver`` is the version of the NetIDE protocol (the current
128    version is v1.2, which is identified with value 0x03).
129
130 -  ``length`` is the total length of the payload in bytes.
131
132 -  ``type`` contains a code that indicates the type of the message
133    according with the following values:
134
135    ::
136
137        enum type {
138            NETIDE_HELLO = 0x01 ,
139            NETIDE_ERROR = 0x02 ,
140            NETIDE_MGMT = 0x03 ,
141            MODULE_ANNOUNCEMENT = 0x04 ,
142            MODULE_ACKNOWLEDGE = 0x05 ,
143            NETIDE_HEARTBEAT = 0x06 ,
144            NETIDE_OPENFLOW = 0x11 ,
145            NETIDE_NETCONF = 0x12 ,
146            NETIDE_OPFLEX = 0x13
147        };
148
149 -  ``datapath_id`` is a 64-bit field that uniquely identifies the
150    network elements.
151
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.
156
157 -  ``xid`` is the transaction identifier associated to the each message.
158    Replies must use the same value to facilitate the pairing.
159
160 Module announcement
161 ~~~~~~~~~~~~~~~~~~~
162
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>.
170
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
174 is the following:
175
176 ::
177
178     struct NetIDE_message {
179         netide_ver = 0x03
180         type = MODULE_ANNOUNCEMENT
181         length = len(" backend -< platform_name >-<pid >")
182         xid = 0
183         module_id = 0
184         datapath_id = 0
185         data = " backend -< platform_name >-<pid >"
186     }
187
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):
191
192 ::
193
194     struct NetIDE_message {
195         netide_ver = 0x03
196         type = MODULE_ACKNOWLEDGE
197         length = len(" backend -< platform_name >-<pid >")
198         xid = 0
199         module_id = MODULE_ID
200         datapath_id = 0
201         data = " backend -< platform_name >-<pid >"
202     }
203
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.
213
214 Heartbeat
215 ~~~~~~~~~
216
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:
230
231 ::
232
233     struct NetIDE_message {
234         netide_ver = 0x03
235         type = NETIDE_HEARTBEAT
236         length = 0
237         xid = 0
238         module_id = backend -id
239         datapath_id = 0
240         data = 0
241     }
242
243 Handshake
244 ~~~~~~~~~
245
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.
249
250 ::
251
252     struct NetIDE_message {
253         struct netide_header header ;
254         uint8 data [0]
255     };
256
257 The header contains the following values:
258
259 -  ``netide ver=0x03``
260
261 -  ``type=NETIDE_HELLO``
262
263 -  ``length=2*NR_PROTOCOLS``
264
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.
273
274 The Core relays hello messages to the server controller which responds
275 with another hello message containing the following:
276
277 -  ``netide ver=0x03``
278
279 -  ``type=NETIDE_HELLO``
280
281 -  ``length=2*NR_PROTOCOLS``
282
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:
288
289 -  ``netide ver=0x03``
290
291 -  ``type=NETIDE_ERROR``
292
293 -  ``length=2*NR_PROTOCOLS``
294
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. \`
299