moving developers-guide to developer-guide for consistency
[docs.git] / manuals / developer-guide / src / main / asciidoc / lispflow.adoc
1 == Lisp Flow Mapping
2
3 // This chapter contains:
4
5 //* <<OpenDaylight Locator/ID Separation Protocol (LISP) Flow Mapping Overview>>
6 //* <<Installing LISP Flow Mapping>>
7
8 === OpenDaylight Locator/ID Separation Protocol (LISP) Flow Mapping Overview
9
10 http://tools.ietf.org/html/rfc6830[Locator/ID Separation Protocol (LISP)] is a technology that provides a flexible map-and-encap framework that can be used for overlay network applications such as data center network virtualization and Network Function Virtualization (NFV).
11
12 LISP provides the following name spaces: 
13
14 * http://tools.ietf.org/html/rfc6830#page-6[Endpoint Identifiers (EIDs)]
15 * http://tools.ietf.org/html/rfc6830#section-3[Routing Locators (RLOCs)]
16
17 In a virtualization environment EIDs can be viewed as virtual address space and RLOCs can be viewed as physical network address space. 
18
19 The LISP framework decouples network control plane from the forwarding plane by providing: 
20
21 * A data plane that specifies how the virtualized network addresses are encapsulated in addresses from the underlying physical network.
22 *  A control plane that stores the mapping of the virtual-to-physical address spaces and the associated forwarding policies and serves this information to the data plane on demand. 
23
24 Network programmability is achieved by programming forwarding policies such as transparent mobility, service chaining, and traffic engineering in the mapping system; where the data plane elements can fetch these policies on demand as new flows arrive. This chapter describes the LISP Flow Mapping project in OpenDaylight and how it can be used to enable advanced SDN and NFV use cases. 
25
26 LISP data plane Tunnel Routers are available at http://LISPmob.org/[LISPmob.org] in the open source community on the following platforms: 
27
28 * Linux 
29 * Android 
30 * OpenWRT 
31
32 For more details and support for LISP data plane software please visit http://LISPmob.org/[the LISPmob web site].
33
34 === LISP Flow Mapping Service
35
36 The LISP Flow Mapping service provides LISP Mapping System services. This includes LISP  Map-Server and LISP Map-Resolver services to store and serve mapping data to data plane nodes as well as to OpenDaylight applications. Mapping data can include mapping of virtual addresses to physical network address where the virtual nodes are reachable or hosted at. Mapping data can also include a variety of routing policies including traffic engineering and load balancing. To leverage this service, OpenDaylight applications and services can use the northbound REST API to define the mappings and policies in the LISP Mapping Service. Data plane devices capable of LISP control protocol can leverage this service through a southbound LISP plugin via the LISP control protocol (Map-Register, Map-Request, Map-Reply messages). 
37
38 The following figure depicts the described components:
39
40 .Architecture Overview
41
42 image::lispflow-arch-overview-helium.jpg["Architecture Overview", width=512]
43
44
45 === LISP Service Architecture
46
47 The following figure shows the various LISP Flow Mapping modules. 
48
49 .LISP Mapping Service Internal Architecture
50
51 image::lispflow-technical-arch-overview-helium.jpg["LISP Mapping Service Internal Architecture", width=460]
52
53 A brief description of each module is as follows:
54
55 * *DAO:* This layer separates the LISP logic from the database, so that we can separate the map server and map resolver from the specific implementation of the DHT (Distributed Hash Table). Currently we have an implementation of this layer with the controller cluster service as a DHT, but it can be switched to any other DHT and you only need to implement the ILISPDAO interface.
56 * *Map Server:* This module processes the adding or registration of keys and mappings. For a detailed specification of LISP Map Server, see http://tools.ietf.org/search/rfc6830[LISP].
57 * *Map Resolver:* This module receives and processes the mapping lookup queries and provides the mappings to requester. For a detailed specification of LISP Map Server, see http://tools.ietf.org/search/rfc6830[LISP].
58 * *Northbound API:* This is part of the ODL northbound API. This module enables defining key-EID associations as well as adding mapping information through the Map Server. Key-EID associations can also be queried via this API. The Northbound API also provides capability of querying the mapping information for an EID prefix.
59 * *Neutron:* This module implements the ODL Neutron Service APIs. It provides integration between the LISP service and the ODL Neutron service.
60 * *NETCONF:* This module enables the LISP service to communicate to NETCONF-enabled devices through ODL's NETCONF plugin.
61 * *Java API:* The API module exposes the Map Server and Map Resolver capabilities via Java API.
62 * *LISP Southbound Plugin:* This plugin enables data plane devices that support LISP control plane protocol (see LISP) to register and query mappings to the LISP Flow Mapping via the LISP control plane protocol.
63
64 === LISP APIs
65
66 The LISP Flow Mapping service has JAVA APIs and REST APIs. The Java API reference documentation is auto-generated from the Java build and is available at:
67
68 * https://jenkins.opendaylight.org/lispflowmapping/job/lispflowmapping-merge-develop/247/artifact/target/apidocs/index.html[JAVA APIs]
69
70 Below you will find the detailed information about the module's REST resources and their verbs (description, URI, parameters, responses, and status codes), schemas, example XML, example JSON, as well as programming examples.
71
72 * https://jenkins.opendaylight.org/lispflowmapping/job/lispflowmapping-merge-develop/247/artifact/mappingservice/northbound/target/site/wsdocs/index.html[REST APIS]
73
74 //TODO Need to update the links once the stable/helium branch is cut and the corresponding Jenkins merge job is created.  For now, instead of 'lastSuccessfulBuild' let's use the merge job corresponding to the commit that's supposed to be released as Helium
75
76 === LISP Configuration Options
77
78 The +etc/custom.properties+ file in the Karaf distribution allows configuration of several OpenDaylight parameters.  The LISP service has two properties that can be adjusted: +lisp.mappingOverwrite+ and +lisp.smr+.
79
80 *lisp.mappingOverwrite* (default: 'true')::
81     Configures handling of mapping updates.  When set to 'true' (default) a mapping update (either through the southbound plugin via a Map-Register message or through a northbound API PUT REST call) the existing RLOC set associated to an EID prefix is overwritten.  When set to 'false', the RLOCs of the update are merged to the existing set.
82
83 *lisp.smr* (default: 'false')::
84     Enables/disables the http://tools.ietf.org/html/rfc6830#section-6.6.2[Solicit-Map-Request (SMR)] functionality.  SMR is a method to notify changes in an EID-to-RLOC mapping to "subscribers".  The LISP service considers all Map-Request's source RLOC as a subscriber to the requested EID prefix, and will send an SMR control message to that RLOC if the mapping changes.
85
86 === Developer Tutorial
87
88 This section provides instructions to set up a LISP network of three nodes (one "client" node and two "server" nodes) using LISPmob and Open vSwitch (OVS) as data plane LISP nodes and the LISP Flow Mapping project from ODL as the LISP programmable mapping system for the LISP network. The steps shown below will demonstrate performing a failover between the two "server" nodes. The three LISP data plane nodes and the LISP mapping system are assumed to be running in Linux virtual machines using the following IPv4 addresses on their eth0 interfaces (please adjust configuration files, JSON examples, etc. accordingly if you're using another addressing scheme):
89
90 .Nodes in the tutorial
91 [align="right",options="header"]
92 |===
93 | Node          |  Node Type     | IP Address
94 | *controller*  |  OpenDaylight  | 10.33.12.32
95 | *client*      |  LISPmob       | 10.33.12.35
96 | *server1*     |  LISPmob       | 10.33.12.37
97 | *server2*     |  Open vSwitch  | 10.33.12.44
98 |===
99
100 NOTE: While the tutorial uses LISPmob and OVS as the data plane, they could be any LISP-enabled HW or SW router (commercial/open source).
101
102 The below steps are using the command line tool cURL to talk to the LISP Flow Mapping northbound REST API. This is so that you can see the actual request URLs and body content on the page. 
103
104 NOTE: It is more convenient to use the Postman Chrome browser plugin to edit and send the requests. The project git repository hosts a collection of the requests that are used in this tutorial in the +resources/tutorial/ODL_Summit_LISP_Demo.json+ file. You can import this file to Postman by following 'Collections->Import a collection->Import from URL' and then entering the following link: +https://git.opendaylight.org/gerrit/gitweb?p=lispflowmapping.git;a=blob_plain;f=resources/tutorial/ODL_Summit_LISP_Demo.json;hb=refs/heads/develop+. Alternatively, you can save the file on your machine, or if you have the repository checked out, you can import from there. You will need to define some variables to point to your OpenDaylight controller instance.
105
106 NOTE: It is assumed that commands are executed as the 'root' user. 
107
108 NOTE: To set up a basic LISP network overlay (no fail-over) without dealing with OVS, you can skip steps 7 and 8 and just use LISPmob as your dataplane. If you do want to test fail-over, but not using OVS, skip steps 7 and 8, but set up LISPmob on *server2* as well, with identical configuration.
109
110 . Install and run OpenDaylight Helium release on the controller VM. Please follow the general OpenDaylight Helium Installation Guide for this step. Once the OpenDaylight controller is running install the 'odl-openflowplugin-all', 'odl-adsal-compatibility-all', 'odl-ovsdb-all', and 'odl-lispflowmapping-all' features from the CLI:
111
112  feature:install odl-openflowplugin-all odl-adsal-compatibility-all odl-ovsdb-all odl-lispflowmapping-all
113 +
114 NOTE: If you're not planning on using OVS you can skip the first three and install 'odl-lispflowmapping-all' only.
115 +
116 It takes quite a while to load and initialize all features and their dependencies. It's worth running the command +log:tail+ in the Karaf console to see when is the log output winding down, and continue after that.
117     
118 . Install LISPmob on the *client* and *server1* VMs following the installation instructions https://github.com/LISPmob/lispmob#software-prerequisites[from the LISPmob README file].
119
120 . Configure the LISPmob installations from the previous step. Starting from the +lispd.conf.example+ file in the distribution, set the EID in each +lispd.conf+ file from the IP address space selected for your virtual/LISP network. In this tutorial the EID of the *client* is set to 1.1.1.1/32, and that of *server1* to 2.2.2.2/32. Set the RLOC interface in each +lispd.conf+. LISP will determine the RLOC (IP address of the corresponding VM) based on this interface. Set the Map-Resolver address to the IP address of the *controller*, and on the *client* the Map-Server too. On *server1* set the Map-Server to something else, so that it doesn't interfere with the mappings on the controller, since we're going to program them manually. Modify the "key" parameter in each +lispd.conf+ file to a key/password of your choice, 'asdf' in this tutorial. The +resources/tutorial+ directory in the 'develop' branch of the project git repository has the files used in the tutorial checked in: https://git.opendaylight.org/gerrit/gitweb?p=lispflowmapping.git;a=blob_plain;f=resources/tutorial/lispd.conf.client;hb=refs/heads/develop[lispd.conf.client] and https://git.opendaylight.org/gerrit/gitweb?p=lispflowmapping.git;a=blob_plain;f=resources/tutorial/lispd.conf.server1;hb=refs/heads/develop[lispd.conf.server1]. Copy the files to +/root/lispd.conf+ on the respective VMs.
121
122 . Define a key and EID prefix association in ODL using the northbound API for both EIDs (1.1.1.1/32 and 2.2.2.2/32).  Run the below commands on the *controller* (or any machine that can reach *controller*, by replacing 'localhost' with the IP address of *controller*).
123
124  curl -u "admin":"admin" -H "Content-type: application/json" -X PUT \
125      http://localhost:8080/lispflowmapping/nb/v2/default/key \
126      --data @key1.json
127  curl -u "admin":"admin" -H "Content-type: application/json" -X PUT \
128      http://localhost:8080/lispflowmapping/nb/v2/default/key \
129      --data @key2.json
130
131 +
132 where the content of the 'key1.json' and 'key2.json' files is the following (with different "ipAddress"):
133 +
134 [source,json]
135 ----
136 {
137   "key" : "asdf",
138   "maskLength" : 32,
139   "address" :
140   {
141     "ipAddress" : "1.1.1.1",
142     "afi" : 1
143   }
144 }
145 ----
146
147 . Verify that the key is added properly by requesting the following URL:
148
149  curl -u "admin":"admin" http://localhost:8080/lispflowmapping/nb/v2/default/key/0/1/1.1.1.1/32
150  curl -u "admin":"admin" http://localhost:8080/lispflowmapping/nb/v2/default/key/0/1/2.2.2.2/32
151
152 . Run the lispd LISPmob daemon on the *client* and *server1* VMs:
153
154  lispd -f /root/lispd.conf
155
156 . Prepare the OVS environment on *server2*:
157
158  .. Start the ovsdb-server and ovs-vswitchd daemons (or check that your distribution's init scripts already started them)
159  .. Start listening for OVSDB manager connections on the standard 6640 TCP port:
160
161  ovs-vsctl set-manager "ptcp:6640"
162  ovs-vsctl show
163
164 +
165  .. Create a TAP port for communications with the guest VM.  We'll have another VM inside the *server2* VM, that will be set up with the 2.2.2.2/24 EID.  It also needs a ficticious gateway, and a static ARP entry for that gateway, with any MAC address.
166
167  tunctl -t tap0
168  ifconfig tap0 up
169
170 +
171  .. Start the guest VM:
172
173  modprobe kvm
174  kvm -daemonize -vnc :0 -m 128 -net nic,macaddr=00:00:0C:15:C0:A1 \
175      -net tap,ifname=tap0,script=no,downscript=no \
176      -drive file=ubuntu.12-04.x86-64.20120425.static_ip_2.2.2.2.qcow2
177
178 +
179 . Set up the OVS environment on *server2* using the ODL northbound API
180  .. Connect to the OVSDB management port from ODL:
181
182  curl -u "admin":"admin" -X PUT \
183      http://localhost:8080/controller/nb/v2/connectionmanager/node/server2/address/10.33.12.44/port/6640
184
185 +
186 You can check if this and the next requests have the desired effect on OVS by running the following on *server2*
187
188  ovs-vsctl show
189
190 +
191 It should now show the "Manager" connection as connected
192
193  .. Create the bridge +br0+:
194
195  curl -u "admin":"admin" -H "Content-type: application/json" -X POST \
196      http://localhost:8080/controller/nb/v2/networkconfig/bridgedomain/bridge/OVS/server2/br0 -d "{}"
197
198  .. Add +tap0+ to +br0+:
199
200  curl -u "admin":"admin" -H "Content-type: application/json" -X POST \
201      http://localhost:8080/controller/nb/v2/networkconfig/bridgedomain/port/OVS/server2/br0/tap0 -d "{}"
202
203 +
204  .. Add the +lisp0+ LISP tunneling virtual port to +br0+:
205
206  curl -u "admin":"admin" -H "Content-type: application/json" -X POST \
207      http://localhost:8080/controller/nb/v2/networkconfig/bridgedomain/port/OVS/server2/br0/lisp0 -d @lisp0.json
208 +
209 where 'lisp0.json' has the following content:
210 +
211 [source,json]
212 ----
213 {
214   "type": "tunnel",
215   "tunnel_type": "lisp",
216   "dest_ip": "10.33.12.35"
217 }
218 ----
219 The *dest_ip* parameter sets the tunnel destination to the *client* VM. This has to be done manually (from the controller), since OVS doesn't have a LISP control plane to fetch mappings.
220
221  .. We will now need to set up flows on +br0+ to to steer traffic received on the LISP virtual port in OVS to the VM connected to +tap0+ and vice-versa. For that we will need the node id of the bridge, which is based on its MAC address, which is generated at creation time. So we look at the list of connections on the controller:
222
223  curl -u "admin":"admin" http://localhost:8080/controller/nb/v2/connectionmanager/nodes
224 +
225 The response should look similar to this:
226 +
227 [literal]
228 {"id":"00:00:62:71:36:30:7b:44","type":"OF"}]},{"id":"10.33.12.35","type":"LISP"},{"id":"server2","type":"OVS"}]}
229 +
230 There are three types of nodes connected to ODL: one "OF" node (the OpenFlow connection to +br0+ on *server2*), one "LISP" node (the *client* VM sending LISP Map-Register control messages to the controller which is acting as a LISP Map-Server), and one "OVS" node (this is the OVSDB connection to *server2*). We will need the id of the "OF" node in order to set up flows.
231
232  .. The first flow will decapsulate traffic received from the client VM on *server2* and send it to the guest VM through the +tap0+ port.
233
234  curl -u "admin":"admin" -H "Content-type: application/json" -X PUT \
235      http://localhost:8080/controller/nb/v2/flowprogrammer/default/node/OF/00:00:62:71:36:30:7b:44/staticFlow/Decap -d @flow_decap.json
236 +
237 Make sure that the bridge id after the OF path component of the URL is the id from the previous step. It should also be the same on line 6 in 'flow_decap.json' file (see below), which should have the MAC address of the KVM instance started on *server2* on line 11 (+SET_DL_DST+):
238 +
239 [source,json]
240 ----
241 {
242   "installInHw": "true",
243   "name": "Decap",
244   "node": {
245     "type": "OF",
246     "id": "00:00:62:71:36:30:7b:44"
247   },
248   "priority": "10",
249   "dlDst": "02:00:00:00:00:00",
250   "actions": [
251     "SET_DL_DST=00:00:0c:15:c0:a1",
252     "OUTPUT=1"
253   ]
254 }
255 ----
256
257  .. The second flow will encapsulate traffic received from the guest VM on *server2* through the +tap0+ port.
258
259  curl -u "admin":"admin" -H "Content-type: application/json" -X PUT \
260      http://localhost:8080/controller/nb/v2/flowprogrammer/default/node/OF/00:00:62:71:36:30:7b:44/staticFlow/Encap -d @flow_encap.json
261 +
262 The 'flow_encap.json' file should look like this:
263 +
264 [source,json]
265 ----
266 {
267   "installInHw": "true",
268   "name": "Decap",
269   "node": {
270     "type": "OF",
271     "id": "00:00:62:71:36:30:7b:44"
272   },
273   "priority": "5",
274   "ingressPort": "1",
275   "etherType": "0x0800",
276   "vlanId": "0",
277   "nwDst": "1.1.1.1/32",
278   "actions": [
279     "OUTPUT=2"
280   ]
281 }
282 ----
283
284  .. Check if the flows have been created correctly. First, in ODL
285
286  curl -u "admin":"admin" http://localhost:8080/controller/nb/v2/flowprogrammer/default
287 +
288 And most importantly, on *server2*
289
290  ovs-ofctl dump-flows br0 -O OpenFlow13
291
292 . The *client* LISPmob node should now register its EID-to-RLOC mapping in ODL. To verify you can lookup the corresponding EIDs via the northbound API
293
294  curl -u "admin":"admin" http://localhost:8080/lispflowmapping/nb/v2/default/mapping/0/1/1.1.1.1/32
295
296  . Register the EID-to-RLOC mapping of the server EID 2.2.2.2/32 to the controller, pointing to *server1* and *server2* with a higher priority for *server1*
297
298  curl -u "admin":"admin" -H "Content-type: application/json" -X PUT \
299      http://localhost:8080/lispflowmapping/nb/v2/default/mapping \
300      -d @mapping.json
301 +
302 where the 'mapping.json' file looks like this
303 +
304 [source,json]
305 ----
306 {
307 "key" : "asdf",
308 "mapregister" :
309   {
310   "proxyMapReply" : true,
311   "eidToLocatorRecords" :
312     [
313       {
314       "authoritative" : true,
315       "prefixGeneric" :
316         {
317         "ipAddress" : "2.2.2.2",
318         "afi" : 1
319         },
320       "mapVersion" : 0,
321       "maskLength" : 32,
322       "action" : "NoAction",
323       "locators" :
324         [
325           {
326           "multicastPriority" : 1,
327           "locatorGeneric" :
328             {
329             "ipAddress" : "10.33.12.37",
330             "afi" : 1
331             },
332           "routed" : true,
333           "multicastWeight" : 0,
334           "rlocProbed" : false,
335           "localLocator" : false,
336           "priority" : 126,
337           "weight" : 1
338           } ,
339           {
340           "multicastPriority" : 1,
341           "locatorGeneric" :
342             {
343             "ipAddress" : "10.33.12.44",
344             "afi" : 1
345             },
346           "routed" : true,
347           "multicastWeight" : 0,
348           "rlocProbed" : false,
349           "localLocator" : false,
350           "priority" : 127,
351           "weight" : 1
352           }
353         ],
354       "recordTtl" : 5
355       }
356     ],
357   "keyId" : 0
358   }
359 }
360 ----
361 +
362 Here the priority of the second RLOC (10.33.12.44 - *server2*) is 127, a higher numeric value than the priority of 10.33.12.37, which is 126. This policy is saying that *server1* is preferred to *server2* for reaching EID 2.2.2.2/32. Note that lower priority has higher preference in LISP.
363
364  . Verify the correct registration of the 2.2.2.2/32 EID:
365
366  curl -u "admin":"admin" http://localhost:8080/lispflowmapping/nb/v2/default/mapping/0/1/2.2.2.2/32
367
368  . Now the LISP network is up. To verify, log into the *client* VM and ping the server EID:
369
370  ping 2.2.2.2
371
372  . Let's test fail-over now. Suppose you had a service on *server1* which became unavailable, but *server1* itself is still reachable. LISP will not automatically fail over, even if the mapping for 2.2.2.2/32 has two locators, since both locators are still reachable and uses the one with the higher priority (lowest priority value). To force a failover, we need to set the priority of *server2* to a lower value. Using the file mapping.json above, swap the priority values between the two locators and repeat the request from step 10. You can also repeat step 11 to see if the mapping is correctly registered. Not that the previous locators are still present, so you should see a list of four locators. If you leave the ping on, and monitor the traffic using wireshark you can see that the ping traffic will be diverted from *server1* to *server2*.
373 +
374 With the default ODL configuration this may take some time, because the mapping stays in the *client* map-cache until the TTL expires. LISP has a http://tools.ietf.org/html/rfc6830#section-6.6.2[Solicit-Map-Request (SMR) mechanism] that can ask a LISP data plane element to update its mapping for a certain EID. This is disabled by default, and is controlled by the +lisp.smr+ variable in +etc/custom.porperties+. When enabled, any mapping change from the northbound will trigger an SMR packet to all data plane elements that have requested the mapping in a certain time window.
375
376 If you used the Postman collection, you will notice an "ELP" mapping. This is for supporting service chaining, but it requires a Re-encapsulating Tunnel Router (RTR). Support for RTR functionality in LISPmob is in progress, and we will update the tutorial to demonstrate service chaining when it becomes available.
377
378 === LISP Support
379
380 For support please contact the lispflowmapping project at: 
381
382 * Lisp Flow Mapping users mailing list: lispflowmapping-users@lists.opendaylight.org 
383
384 * Lisp Flow Mapping dev mailing list: lispflowmapping-dev@lists.opendaylight.org 
385
386 You can also reach us at the following channel on IRC:
387
388 * #opendaylight-lispflowmapping on irc.freenode.net
389
390 Additional information is also available on the wiki:
391
392 * https://wiki.opendaylight.org/view/OpenDaylight_Lisp_Flow_Mapping:Main[Lisp Flow Mapping wiki]
393
394 === Installing LISP Flow Mapping
395
396 This chapter contains installation instructions for Locator ID Separation Protocol (LISP) provides guidelines for installation from the lispflowmapping repository.
397
398 ==== Setting up Gerritt
399
400 Code reviews are enabled through Gerrit. For setting up gerritt, see https://wiki.opendaylight.org/view/OpenDaylight_Controller:Gerrit_Setup[Set up Gerrit]. 
401 >>>>>>> a8dd6f1... added installation section into the lisp doc
402
403 NOTE: You will need to perform the Gerrit Setup before you can access git via ssh as described below. 
404
405 ==== Pulling code via Git CLI
406
407 Pull the code by cloning the LispFlowMapping repository. 
408
409 ----
410  git clone ssh://<username>@git.opendaylight.org:29418/lispflowmapping.git
411 ----
412
413 or if you just want to do an anonymous git clone, you can use: 
414
415 ----
416  git clone https://git.opendaylight.org/gerrit/p/lispflowmapping.git
417 ----
418
419 ==== Setting up Gerrit Change-id Commit Message Hook 
420
421 This command inserts a unique Change-Id tag in the footer of a commit message. This step is optional but highly recommended for tracking changes. 
422
423 ----
424  cd lispflowmapping
425  scp -p -P 29418 <username>@git.opendaylight.org:hooks/commit-msg .git/hooks/
426  chmod 755 .git/hooks/commit-msg
427 ----
428
429 Install and setup gitreview. The instaructions can be found at http://www.mediawiki.org/wiki/Gerrit/git-review#Installation%7Chere[here].
430
431 ==== Hacking the Code 
432
433 The following tasks are used to help you hack the code. 
434
435 *Setup Eclipse*
436
437 . Run Eclipse (Kepler is the current version).
438 . Open Git Repository perspective.
439 . Add an existing repository and choose the Lisp Flow Mapping repository that was pulled earlier.
440 . Import existing Maven projects and choose the following under the lispflowmapping directory:
441
442     * api/pom.xl
443     * implementation/pom.xml
444         
445 *Build the code*
446
447 ----
448  mvn clean install
449 ----
450
451 To run without unitests you can skip building those tests running the following: 
452
453 ----
454  mvn clean install -DskipTests
455  /* instead of "mvn clean install" */
456 ----
457
458 *Run the controller*
459
460 ----
461  cd distribution-karaf/target/assembly/bin
462  ./karaf
463 ----
464
465 At this point the ODL controller is running. Open a web browser and point your browser at http://localhost:8080/ 
466
467 For complete documentation on running the controller, see the ODL Helium Installation Guide.
468
469 ==== Commit the code using Git CLI
470
471 NOTE: To be accepted, all code must come with a http://elinux.org/Developer_Certificate_Of_Origin[developer certificate of origin] as expressed by having a Signed-off-by. This means that you are asserting that you have made the change and you understand that the work was done as part of an open-source license. 
472
473 ----
474 Developer's Certificate of Origin 1.1
475
476         By making a contribution to this project, I certify that:
477
478         (a) The contribution was created in whole or in part by me and I
479             have the right to submit it under the open source license
480             indicated in the file; or
481
482         (b) The contribution is based upon previous work that, to the best
483             of my knowledge, is covered under an appropriate open source
484             license and I have the right under that license to submit that
485             work with modifications, whether created in whole or in part
486             by me, under the same open source license (unless I am
487             permitted to submit under a different license), as indicated
488             in the file; or
489
490         (c) The contribution was provided directly to me by some other
491             person who certified (a), (b) or (c) and I have not modified
492             it.
493
494         (d) I understand and agree that this project and the contribution
495             are public and that a record of the contribution (including all
496             personal information I submit with it, including my sign-off) is
497             maintained indefinitely and may be redistributed consistent with
498             this project or the open source license(s) involved.
499 ----
500                         
501 *Mechanically you do it this way*:
502
503 ----
504 git commit --signoff
505 ----
506
507 You will be prompted for a commit message. If you are fixing a buzilla bug you can add the associated bug number to your commit message and it will get linked from Gerrit: 
508
509 .For Example:
510
511 ----
512 Fix for bug 2.
513
514 Signed-off-by: Ed Warnicke <eaw@cisco.com>
515 # Please enter the commit message for your changes. Lines starting
516 # with '#' will be ignored, and an empty message aborts the commit.
517 # On branch develop
518 # Changes to be committed:
519 #   (use "git reset HEAD <file>..." to unstage)
520 #
521 #       modified:   README
522 #
523 ----
524
525 ==== Pushing the Code via Git CLI
526
527 Use gitreview to push your changes back to the remote repository using: 
528
529 ----
530  git review
531 ----
532
533 You can set a topic for your patch by:
534
535 ----
536  git review -t <topic>
537 ----
538
539 The Jenkins Controller User will verify your code. 
540
541 ==== Pulling the Code changes via Git CLI
542
543 Use git pull to get the latest changes from the remote repository 
544
545 ----
546 git pull origin HEAD:refs/for/develop
547 ----
548
549 ==== Pushing the Code via Git CLI
550
551 Use git push to push your changes back to the remote repository. 
552
553 ----
554 git push  origin HEAD:refs/for/develop
555 ----
556
557 You will get a message pointing you to your gerrit request like: 
558
559 ----
560 ==========================
561 remote: Resolving deltas: 100% (2/2) + 
562 remote: Processing changes: new: 1, refs: 1, done    + 
563 remote: + 
564 remote: New Changes: + 
565 remote:   http://git.opendaylight.org/gerrit/64 + 
566 remote: + 
567 ==========================
568 ----
569
570 ==== Viewing your Changes in Gerrit
571
572 Follow the link you got above to see your commit in Gerrit: 
573
574 .Gerritt Code Review Sample
575 image::gerrit-code-review.png["Gerritt Code Review Sample",width=500]
576
577 Note that the Jenkins Controller User has verified your code and at the bottom is a link to the Jenkins build. 
578
579 Once your code has been reviewed and submitted by a committer it will be merged into the authoritative repo, which would look like this: 
580
581 .Gerritt Code Merge Sample
582 image::gerrit-merged.png["Gerritt Code Merge Sample",width=500]
583
584 ==== Troubleshooting
585
586 . *What to do if your Firewall blocks port 29418*
587
588 There have been reports that many corporate firewalls block port 29418. If that's the case, please follow the https://wiki.opendaylight.org/view/OpenDaylight_Controller:Setting_up_HTTP_in_Gerrit[Setting up HTTP in Gerrit] instructions and use git URL: 
589
590 ----
591 git clone https://<your_username>@git.opendaylight.org/gerrit/p/lispflowmapping.git
592 ----
593
594 You will be prompted for the password you generated in https://wiki.opendaylight.org/view/OpenDaylight_Controller:Setting_up_HTTP_in_Gerrit[Setting up HTTP in Gerrit].
595
596 All other instructions on this page remain unchanged.
597
598 To download pre-built images with ODP bootstraps see the following Github project: 
599
600 https://github.com/nerdalert/OpenDaylight-Lab[Pre-Built OpenDaylight VM Images]
601
602