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