blob: 1f887b1859aad3f9b64f35316aa276b7b12838cf [file] [log] [blame]
Charles Chanfcfe8902022-02-02 17:06:27 -08001.. SPDX-FileCopyrightText: 2021 Open Networking Foundation <info@opennetworking.org>
2.. SPDX-License-Identifier: Apache-2.0
3
Wailok Shumbb7408b2021-09-30 22:41:32 +08004External Connectivity
5=====================
6
7vRouter
8-------
9
10Physical Connectivity
11^^^^^^^^^^^^^^^^^^^^^
12
13External routers must be physically connected to one of the fabric leaf
14switches.
15
16Currently there is a limitation that the **external/upstream router and the
17Quagga instance must be connected to the same fabric leaf switch**.
18
19Therefore it is necessary to use an additional front panel port on the
20leaf-switch (or at least an additional VLAN) to connect to the compute node
21hosting Quagga.
22
23.. image:: ../../images/config-vr-physical.png
24
25Configure vRouter
26^^^^^^^^^^^^^^^^^
27
28The operator will need to configure a subnet between the Leaf-switch, the
29external/upstream router and the Quagga instance. There are 3 IP addresses we
30need to allocate - 1 on the switch port, 1 in Quagga, and 1 on the upstream
31router. This means the peering subnet **cannot be smaller than a /29**.
32
33BGP peering happens between the IP addresses configured on the interfaces in
34Quagga and the external router.
35
36Routes are advertised by Quagga to the upstream with the next-hop set to the
37switch port IP address. This means that when traffic comes to the fabric leaf
38switch from outside, the switch is able to distinguish peering traffic from
39data traffic and treat each appropriately.
40
41The following shows an ONOS interface configuration example:
42
43.. code-block:: json
44
45 {
46 "ports" : {
47 "of:0000000000000001/1" : {
48 "interfaces" : [
49 {
50 "name" : "upstream1",
51 "ips" : [ "10.0.1.2/24" ],
52 "vlan-untagged" : 4000
53 }
54 ]
55 },
56 "of:0000000000000001/2" : {
57 "interfaces" : [
58 {
59 "name" : "quagga",
60 "ips" : [ "10.0.1.2/24" ],
61 "vlan-untagged" : 4000
62 }
63 ]
64 }
65 }
66 }
67
68- ``name``: An arbitrary name string for the interface. Optional.
69
70- ``ips``: Configure the peering subnet (10.0.1.0/24) and the switch port IP
71 (10.0.1.2). Note that we use the same IP address on both the Quagga and
72 upstream interfaces.
73
Carmelo Cascone43989982021-10-12 00:01:19 -070074- ``vlan-untagged``: Configure the same VLAN ID on both interfaces. It doesn't
Wailok Shumbb7408b2021-09-30 22:41:32 +080075 matter exactly what the VLAN ID is, but it must be the same on both the
76 Quagga-facing and upstream-facing interfaces.
77
78In this case the peering subnet is ``10.0.1.0/24``.
79The upstream router is using the ``10.0.1.1`` address.
80Quagga is assigned ``10.0.1.3``, which is the address used for peering.
81
82The upstream router needs to be configured with ``10.0.1.3`` as its BGP
83neighbor, and the BGP peering will be established between ``10.0.1.1`` and
84``10.0.1.3``. The ``10.0.1.2`` address is used by the fabric switch and for the
85next-hop for routes advertised by Quagga.
86
87Of course you are not obliged to use ``10.0.1.0/24``, you should use a subnet
88that makes sense for your peering environment.
89
90.. note::
91 This configuration will set up an L2 link between the two fabric switch
92 ports, over which the Quagga and external router can communicate.
93
94 Both Quagga and the upstream router will receive untagged packets (i.e they
95 will never see packets with VLAN id 4000, which is used inside the leaf
96 switch to establish a bridging domain).
97
98 If you need a VLAN tag in the compute node to distinguish the traffic going
99 to Quagga, you can change the VLAN assignment on the switch port
100 "of:0000000000000001/2" to be ``vlan-tagged`` instead of ``vlan-untagged``.
101
102Deploy the Quagga Docker Image
103^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
104
105SD-Fabric uses a slightly modified version of Quagga, so the easiest way to
106deploy this is to use the provided docker image.
107
108.. code-block:: console
109
110 $ docker pull opencord/quagga
111
112We also need to download the **pipework** tool which will be used to connect
113the docker image to the physical interface that we set aside earlier.
114
115.. code-block:: console
116
117 $ wget https://raw.githubusercontent.com/jpetazzo/pipework/master/pipework
118 $ chmod +x pipework
119
120Create a directory for your Quagga configuration files, and create a ``bgpd.conf``
121and ``zebra.conf`` in there. This folder is going to be mounted into the Quagga
122container. More on configuring Quagga later.
123
124.. code-block:: console
125
126 $ mkdir configs
127 $ touch zebra.conf bgpd.conf
128
129Now run the docker image (make sure the path the config directory matches what
130is on your system):
131
132.. code-block:: console
133
134 $ sudo docker run --privileged -d -v configs:/etc/quagga -n quagga opencord/quagga
135
136Finally, we can use the pipework tool to add the physical interface into the
137container so that Quagga can talk out over the fabric:
138
139.. code-block:: console
140
141 $ sudo ./pipework mlx1 -i eth1 quagga 10.0.1.3/24
142
143This will add host interface ``mlx1`` to the container with name ``quagga``
144with interface name ``eth1`` inside the container. The newly added interface
145will have the IP ``10.0.1.3``. This IP address should be the peering subnet
146address that you want to assign to Quagga.
147
148If you need to change anything about the container (for example if you change
149the Quagga configuration) you can remove the original container and run a new
150one:
151
152.. code-block:: console
153
154 $ sudo docker rm -f quagga
155 $ sudo docker run --privileged -d -v configs:/etc/quagga -n quagga opencord/quagga
156
157Configure Quagga
158^^^^^^^^^^^^^^^^
159
160At this point Quagga should have IP connectivity to the external routers, and
161it should be able to ping them on the peering subnet.
162
163Now Quagga and the upstream routers can be configured to peer with one another.
164This configuration of Quagga is going to be highly dependent on the
165configuration of the upstream network, so it won't be possible to give
166comprehensive configuration examples here.
167
168It is recommended to consult the Quagga documentation for exhaustive
169information on Quagga's capabilities and configuration. Here I will attempt to
170provide a few basic examples of Quagga configuration to get you started.
171You'll have to enhance these with the features and functions that are needed in
172your network.
173
174Zebra configuration
175"""""""""""""""""""
176
177Regardless of which routing protocols you are using in your network, it is
178important to configure Zebra's FPM connection to send routes to the FPM app
179running on ONOS. This feature was enabled by the patch that was applied
180earlier when we installed Quagga.
181
182A minimal Zebra configuration might look like this:
183
184.. code-block:: text
185
186 !
187 hostname cord-zebra
188 password cord
189 !
190 fpm connection ip 10.6.0.1 port 2620
191 !
192
pudelkoM964f63e2021-10-08 11:10:28 -0700193The FPM connection IP address is the IP address of **one of the ONOS cluster
Wailok Shumbb7408b2021-09-30 22:41:32 +0800194instances** - does not matter which one. If you have other configuration that
195needs to go in ``zebra.conf`` you should add that here as well.
196
197BGP configuration
198"""""""""""""""""
199
200An example simple BGP configuration for peering with one BGP peer might look
201like this:
202
203.. code-block:: text
204
205 hostname bgp
206 password cord
207 !
208 ip prefix-list 1 seq 10 permit 192.168.0.0/16
209 !
210 route-map NEXTHOP permit 10
211 match ip address prefix-list 1
212 set ip next-hop 10.0.1.2
213 !
214 router bgp 65535
215 bgp router-id 10.0.1.3
216 !
217 network 192.168.0.0/16
218 !
219 neighbor 10.0.1.1 remote-as 65540
220 neighbor 10.0.1.1 description upstream1
221 neighbor 10.0.1.1 route-map NEXTHOP out
222 !
223
224This configuration peers with one upstream router ``10.0.1.1`` and advertises
225one route ``192.168.0.0/16``. Note that Quagga (and as a result SD-Fabric) is in
226a different AS ``65535`` from the upstream router AS ``65540``, as we are using
227E-BGP for this connectivity.
228
229.. note::
230 Pay attention to the configuration to rewrite the next hop of routes that
231 are advertised to the upstream router.
232
233 A ``route-map`` is used to set the next hop of advertised routes to
234 ``10.0.1.2``, which is **different from the address that Quagga is using to
235 peer with the external router**.
236
237 As mentioned above, it is important that this rewriting is done correctly
238 so that the fabric switch is able to **distinguish data plane and control
239 plane** traffic.
240
241Route service and static route
242------------------------------
243
244Access route service via CLI
245^^^^^^^^^^^^^^^^^^^^^^^^^^^^
246
247View routes
248"""""""""""
249
250This will show routes from all sources, including static and dynamic routes.
251
252The example below shows routes learned from the upstream router (Source: FPM)
253and routes configured manually (Source: STATIC)
254
255.. code-block:: text
256
257 onos> routes
258
259 B: Best route, R: Resolved route
260
261 Table: ipv4
262 B R Network Next Hop Source (Node)
263 0.0.0.0/0 172.16.0.1 FPM (127.0.0.1)
264 > * 1.1.0.0/18 10.0.1.20 STATIC
265 > * 10.0.99.0/24 10.0.1.1 FPM (127.0.0.1)
266 * 10.0.99.0/24 10.0.6.1 FPM (127.0.0.1)
267 Total: 2
268
269 Table: ipv6
270 B R Network Next Hop Source (Node)
271 > * 2000::7700/120 fe80::288:ff:fe00:1 FPM (127.0.0.1)
272 > * 2000::8800/120 fe80::288:ff:fe00:2 FPM (127.0.0.1)
273 > * 2000::9900/120 fe80::288:ff:fe00:1 FPM (127.0.0.1)
274 * 2000::9900/120 fe80::288:ff:fe00:2 FPM (127.0.0.1)
275 Total: 3
276
277
278Add a static route
279""""""""""""""""""
280
281.. code-block:: console
282
283 onos> route-add <prefix> <nexthop>
284 onos> route-add 1.1.0.0/18 10.0.1.20
285 onos> route-add 2020::101/120 2000::1
286
287
288Remove a static route
289"""""""""""""""""""""
290
291.. code-block:: console
292
293 onos> route-remove <prefix> <nexthop>
294 onos> route-remove 1.1.0.0/18 10.0.1.20
295
296
297Access route service via REST
298^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
299
300Single route
301""""""""""""
302
303.. code-block:: console
304
305 $ curl --user onos:rocks -X POST -H 'Content-Type:application/json' http://<controller-ip>:8181/onos/routeservice/routes -d@routes.json
306 $ curl --user onos:rocks -X GET -H 'Accept:application/json' http://<controller-ip>:8181/onos/routeservice/routes | python -mjson.tool
307 $ curl --user onos:rocks -X DELETE -H 'Content-Type:application/json' http://<controller-ip>:8181/onos/routeservice/routes -d@routes.json
308
309with identical json format for both POST and DELETE:
310
311.. code-block:: json
312
313 {
314 "prefix": "20.0.0.1/24",
315 "nextHop": "10.0.1.10"
316 }
317
318
319Bulk routes
320"""""""""""
321
322.. code-block:: console
323
324 $ curl --user onos:rocks -X POST -H 'Content-Type:application/json' http://<controller-ip>:8181/onos/routeservice/routes/bulk -d@routes.json
325 $ curl --user onos:rocks -X DELETE -H 'Content-Type:application/json' http://<controller-ip>:8181/onos/routeservice/routes/bulk -d@routes.json
326
327with identical json format for both POST and DELETE:
328
329.. code-block:: json
330
331 {
332 "routes": [
333 {
334 "prefix": "20.0.0.1/24",
335 "nextHop": "10.0.1.10"
336 },
337 {
338 "prefix": "30.0.0.1/24",
339 "nextHop": "10.0.2.15"
340 }
341 ]
342 }
343
344
345Verify routes
346^^^^^^^^^^^^^
347Check the leaf switches that the route (e.g. 1.1.0.0/18) has been programmed in
348the routing table (table 30).
349
350.. code-block:: console
351
352 onos> flows any of:0000000000000205 30
353 <snip>
354 id=670000d1f6782c, state=ADDED, bytes=0, packets=0, duration=39, liveType=UNKNOWN, priority=36010, tableId=30, appId=org.onosproject.segmentrouting, payLoad=null, selector=[ETH_TYPE:ipv4, IPV4_DST:1.1.0.0/18],
355 treatment=DefaultTrafficTreatment{immediate=[], deferred=[GROUP:0x70000014], transition=TABLE:60, meter=None, cleared=false, metadata=null}
356 <snip>
357
358Notes about next hops
359^^^^^^^^^^^^^^^^^^^^^
360The next hop of a route should be resolvable to a MAC address that is known to
361ONOS. Typically the next hop is a server interface that is known to ONOS as a
362host learned via ARP or DHCP. If you are not sure, check the ``hosts`` command
363on the ONOS CLI.
364
365.. code-block:: console
366
367 onos> hosts
368 <snip>
369 id=A2:9B:32:9D:7F:B3/None, mac=A2:9B:32:9D:7F:B3, location=of:0000000000000205/48, vlan=None, ip(s)=[192.168.101.2], configured=false
370 id=B2:A4:E2:72:D1:91/None, mac=B2:A4:E2:72:D1:91, location=of:0000000000000204/16, vlan=None, ip(s)=[10.0.1.20], configured=false
371 id=EE:22:F7:BE:86:50/None, mac=EE:22:F7:BE:86:50, location=of:0000000000000205/16, vlan=None, ip(s)=[10.0.2.15], configured=false
372
373If the next hop has not been resolved for any reason, it would be necessary to
374configure the next hop as a host (/32 prefix) together with MAC address and
375location.
376
377Learn more about how to configure a host using `Network Config Host Provider
378<https://wiki.onosproject.org/display/ONOS/Network+Config+Host+Provider>`_
379
380Finally note that if you are configuring routes manually/statically and they
381are publicly routable IPs that should be reachable from “outside”, you would
382need to configure Quagga to advertise them upstream.
383
384
385Route blackhole
386---------------
387The blackhole consists of a rule on table 30 on every edge device on the
388fabric. The Table 30 rule matches on a given IP address and mask and has
389nothing but a ``clearDeferred`` action, practically dropping the packet. Every IP
390we want to blackhole will have it's own rule in every edge switch.
391
392An example of such rule is:
393
394.. code-block:: text
395
396 ADDED, bytes=0, packets=0, table=30, priority=48010, selector=[ETH_TYPE:ipv4, IPV4_DST:50.0.0.0/24], treatment=[transition=TABLE:60]
397
398Route blackholing can be done via network configuration.
399
400.. code-block:: json
401
402 {
403 "apps" : {
404 "org.onosproject.segmentrouting" : {
405 "segmentrouting": {
406 "blackholeIps": [
407 "50.0.0.0/24"
408 ]
409 }
410 }
411 }
412 }
413
414Ignore certain FPM peer
415-----------------------
416The ``FpmConnectionInfo`` consists a new flag ``acceptRoutes``, indicating
417whether we want to accept or discard the routes advertised by certain FPM peer.
418Per current requirement, we always have the ``acceptRoutes`` flag set to
419``true`` by default, meaning that we will accept routes from all peers.
420
421We can updated the flag using REST API and CLI command as below
422
423REST API
424^^^^^^^^
425- ``POST /acceptRoutes`` to enable or disable ``acceptRoutes`` flag
426- ``GET /acceptRoutes`` to fetch the current status of the FPM connection
427
428.. image:: ../../images/config-fpm-rest.png
429 :width: 900px
430
431CLI
432^^^
433
434- ``fpm-set-accept-routes`` to enable or disable ``acceptRoutes`` flag
435
436 .. code-block:: console
437
438 onos> fpm-set-accept-routes 10.250.16.40 52560 false
439
440- ``fpm-get-accept-route`` to fetch the current status of the FPM connection
441
442 .. code-block:: console
443
444 onos> fpm-get-accept-route
445 <snip>
446 peer 10.250.16.40 port 52560 acceptRoutes false
447 peer 10.250.16.41 port 52594 acceptRoutes true
448 <snip>