blob: 0ecf272f157a9535ade58e3fbb39025b5e167754 [file] [log] [blame]
Charles Chan9e5c6172019-09-07 11:24:54 -07001External Connectivity
2=====================
Charles Chan8d3ae672019-09-07 22:07:22 -07003
4vRouter
5-------
6
Charles Chan8d3ae672019-09-07 22:07:22 -07007Physical Connectivity
8^^^^^^^^^^^^^^^^^^^^^
9External routers must be physically connected to one of the fabric leaf switches.
10Currently there is a limitation that the **external/upstream router and the Quagga instance must be connected to the same fabric leaf switch**.
11
12Therefore 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.
13
Charles Chan976d8a02019-09-08 17:18:50 -070014.. image:: ../images/config-vr-physical.png
Charles Chan8d3ae672019-09-07 22:07:22 -070015
16Configure vRouter
17^^^^^^^^^^^^^^^^^
18The operator will need to configure a subnet between the Leaf-switch, the external/upstream router and the Quagga instance.
19There are 3 IP addresses we need to allocate - 1 on the switch port, 1 in Quagga, and 1 on the upstream router.
20This means the peering subnet **cannot be smaller than a /29**.
21
22BGP peering happens between the IP addresses configured on the interfaces in Quagga and the external router.
23
24Routes are advertised by Quagga to the upstream with the next-hop set to the switch port IP address.
25This 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.
26
27The following shows an ONOS interface configuration example:
28
29.. code-block:: json
30
Charles Chan8299f072019-09-23 11:32:26 -070031 {
32 "ports" : {
33 "of:0000000000000001/1" : {
34 "interfaces" : [
35 {
36 "name" : "upstream1",
37 "ips" : [ "10.0.1.2/24" ],
38 "vlan-untagged" : 4000
39 }
40 ]
41 },
42 "of:0000000000000001/2" : {
43 "interfaces" : [
44 {
45 "name" : "quagga",
46 "ips" : [ "10.0.1.2/24" ],
47 "vlan-untagged" : 4000
48 }
49 ]
50 }
51 }
52 }
Charles Chan8d3ae672019-09-07 22:07:22 -070053
54- ``name``: An arbitrary name string for the interface. Optional.
55- ``ips``: Configure the peering subnet (10.0.1.0/24) and the switch port IP (10.0.1.2).
56 Note that we use the same IP address on both the quagga and upstream interfaces.
57- ``vlan-untagged``: Configure the same VLAN ID on both interfaces.
58 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.
59
60In this case the peering subnet is ``10.0.1.0/24``.
61The upstream router is using the ``10.0.1.1`` address.
62Quagga is assigned ``10.0.1.3``, which is the address used for peering.
63The 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.
64
65Of course you are not obliged to use ``10.0.1.0/24``, you should use a subnet that makes sense for your peering environment.
66
67.. note::
Charles Chan8299f072019-09-23 11:32:26 -070068 This configuration will set up an L2 link between the two fabric switch ports, over which the Quagga and external router can communicate.
69 Both Quagga and the upstream router will receive untagged packets
70 (i.e they will never see packets with vlanId 4000, which is used inside the leaf switch to establish a bridging domain).
Charles Chan8d3ae672019-09-07 22:07:22 -070071
Charles Chan8299f072019-09-23 11:32:26 -070072 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.
Charles Chan8d3ae672019-09-07 22:07:22 -070073
74Deploy the Quagga Docker Image
75^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
76Trellis uses a slightly modified version of Quagga, so the easiest way to deploy this is to use the provided docker image.
77
78.. code-block:: console
79
Charles Chan8299f072019-09-23 11:32:26 -070080 $ docker pull opencord/quagga
Charles Chan8d3ae672019-09-07 22:07:22 -070081
82We 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.
83
84.. code-block:: console
85
Charles Chan8299f072019-09-23 11:32:26 -070086 $ wget https://raw.githubusercontent.com/jpetazzo/pipework/master/pipework
87 $ chmod +x pipework
Charles Chan8d3ae672019-09-07 22:07:22 -070088
89Create a directory for your Quagga configuration files, and create a bgpd.conf and zebra.conf in there.
90This folder is going to be mounted into the Quagga container.
91More on configuring Quagga later.
92
93.. code-block:: console
94
Charles Chan8299f072019-09-23 11:32:26 -070095 $ mkdir configs
96 $ touch zebra.conf bgpd.conf
Charles Chan8d3ae672019-09-07 22:07:22 -070097
98Now run the docker image (make sure the path the config directory matches what is on your system):
99
100.. code-block:: console
101
Charles Chan8299f072019-09-23 11:32:26 -0700102 $ sudo docker run --privileged -d -v configs:/etc/quagga -n quagga opencord/quagga
Charles Chan8d3ae672019-09-07 22:07:22 -0700103
104Finally, we can use the pipework tool to add the physical interface into the container so that Quagga can talk out over the fabric:
105
106.. code-block:: console
107
Charles Chan8299f072019-09-23 11:32:26 -0700108 $ sudo ./pipework mlx1 -i eth1 quagga 10.0.1.3/24
Charles Chan8d3ae672019-09-07 22:07:22 -0700109
110This will add host interface ``mlx1`` to the container with name ``quagga`` with interface name ``eth1`` inside the container.
111The newly added interface will have the IP ``10.0.1.3``.
112This IP address should be the peering subnet address that you want to assign to Quagga.
113
114If 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:
115
116.. code-block:: console
117
Charles Chan8299f072019-09-23 11:32:26 -0700118 $ sudo docker rm -f quagga
119 $ sudo docker run --privileged -d -v configs:/etc/quagga -n quagga opencord/quagga
Charles Chan8d3ae672019-09-07 22:07:22 -0700120
121Configure Quagga
122^^^^^^^^^^^^^^^^
123At this point Quagga should have IP connectivity to the external routers, and it should be able to ping them on the peering subnet.
124
125Now Quagga and the upstream routers can be configured to peer with one another.
126This 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.
127It is recommended to consult the Quagga documentation for exhaustive information on Quagga's capabilities and configuration.
128Here I will attempt to provide a few basic examples of Quagga configuration to get you started.
129You'll have to enhance these with the features and functions that are needed in your network.
130
131Zebra configuration
132"""""""""""""""""""
133Regardless of which routing protocols you are using in your network,
134it is important to configure Zebra's FPM connection to send routes to the FPM app running on ONOS.
135This feature was enabled by the patch that was applied earlier when we installed Quagga.
136
137A minimal Zebra configuration might look like this:
138
139.. code-block:: text
140
Charles Chan8299f072019-09-23 11:32:26 -0700141 !
142 hostname cord-zebra
143 password cord
144 !
145 fpm connection ip 10.6.0.1 port 2620
146 !
Charles Chan8d3ae672019-09-07 22:07:22 -0700147
148The FPM connection IP address is the IP address of **one of the onos cluster instances** - does not matter which one.
149If you have other configuration that needs to go in zebra.conf you should add that here as well.
150
151BGP configuration
152"""""""""""""""""
153An example simple BGP configuration for peering with one BGP peer might look like this:
154
155.. code-block:: text
156
Charles Chan8299f072019-09-23 11:32:26 -0700157 hostname bgp
158 password cord
159 !
160 ip prefix-list 1 seq 10 permit 192.168.0.0/16
161 !
162 route-map NEXTHOP permit 10
163 match ip address prefix-list 1
164 set ip next-hop 10.0.1.2
165 !
166 router bgp 65535
167 bgp router-id 10.0.1.3
168 !
169 network 192.168.0.0/16
170 !
171 neighbor 10.0.1.1 remote-as 65540
172 neighbor 10.0.1.1 description upstream1
173 neighbor 10.0.1.1 route-map NEXTHOP out
174 !
Charles Chan8d3ae672019-09-07 22:07:22 -0700175
176This configuration peers with one upstream router ``10.0.1.1`` and advertises one route ``192.168.0.0/16``.
177Note that Quagga (and as a result Trellis) is in a different AS ``65535`` from the upstream router AS ``65540``,
178as we are using E-BGP for this connectivity.
179
180.. note::
Charles Chan8299f072019-09-23 11:32:26 -0700181 Pay attention to the configuration to rewrite the next hop of routes that are advertised to the upstream router.
182 A ``route-map`` is used to set the next hop of advertised routes to ``10.0.1.2``,
183 which is **different from the address that Quagga is using to peer with the external router**.
184 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.
Charles Chan8d3ae672019-09-07 22:07:22 -0700185
186
187Route service and static route
188------------------------------
189
190Access route service via CLI
191^^^^^^^^^^^^^^^^^^^^^^^^^^^^
192
193View routes
194"""""""""""
195This will show routes from all sources, including static and dynamic routes.
196The example below shows routes learned from the upstream router (Source: FPM) and routes configured manually (Source: STATIC)
197
198.. code-block:: text
199
Charles Chan8299f072019-09-23 11:32:26 -0700200 onos> routes
Charles Chan8d3ae672019-09-07 22:07:22 -0700201
Charles Chan8299f072019-09-23 11:32:26 -0700202 B: Best route, R: Resolved route
Charles Chan8d3ae672019-09-07 22:07:22 -0700203
Charles Chan8299f072019-09-23 11:32:26 -0700204 Table: ipv4
205 B R Network Next Hop Source (Node)
206 0.0.0.0/0 172.16.0.1 FPM (127.0.0.1)
207 > * 1.1.0.0/18 10.0.1.20 STATIC
208 > * 10.0.99.0/24 10.0.1.1 FPM (127.0.0.1)
209 * 10.0.99.0/24 10.0.6.1 FPM (127.0.0.1)
210 Total: 2
Charles Chan8d3ae672019-09-07 22:07:22 -0700211
Charles Chan8299f072019-09-23 11:32:26 -0700212 Table: ipv6
213 B R Network Next Hop Source (Node)
214 > * 2000::7700/120 fe80::288:ff:fe00:1 FPM (127.0.0.1)
215 > * 2000::8800/120 fe80::288:ff:fe00:2 FPM (127.0.0.1)
216 > * 2000::9900/120 fe80::288:ff:fe00:1 FPM (127.0.0.1)
217 * 2000::9900/120 fe80::288:ff:fe00:2 FPM (127.0.0.1)
218 Total: 3
Charles Chan8d3ae672019-09-07 22:07:22 -0700219
220
221Add a static route
222""""""""""""""""""
223
224.. code-block:: console
225
Charles Chan8299f072019-09-23 11:32:26 -0700226 onos> route-add <prefix> <nexthop>
227 onos> route-add 1.1.0.0/18 10.0.1.20
228 onos> route-add 2020::101/120 2000::1
Charles Chan8d3ae672019-09-07 22:07:22 -0700229
230
231Remove a static route
232"""""""""""""""""""""
233
234.. code-block:: console
235
Charles Chan8299f072019-09-23 11:32:26 -0700236 onos> route-remove <prefix> <nexthop>
237 onos> route-remove 1.1.0.0/18 10.0.1.20
Charles Chan8d3ae672019-09-07 22:07:22 -0700238
239
240Access route service via REST
241^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
242
243Single route
244""""""""""""
245
246.. code-block:: console
247
Charles Chan8299f072019-09-23 11:32:26 -0700248 $ curl --user onos:rocks -X POST -H 'Content-Type:application/json' http://<controller-ip>:8181/onos/routeservice/routes -d@routes.json
249 $ curl --user onos:rocks -X GET -H 'Accept:application/json' http://<controller-ip>:8181/onos/routeservice/routes | python -mjson.tool
250 $ curl --user onos:rocks -X DELETE -H 'Content-Type:application/json' http://<controller-ip>:8181/onos/routeservice/routes -d@routes.json
Charles Chan8d3ae672019-09-07 22:07:22 -0700251
252with identical json format for both POST and DELETE:
253
254.. code-block:: json
255
Charles Chan8299f072019-09-23 11:32:26 -0700256 {
257 "prefix": "20.0.0.1/24",
258 "nextHop": "10.0.1.10"
259 }
Charles Chan8d3ae672019-09-07 22:07:22 -0700260
261
262Bulk routes
263"""""""""""
264
265.. code-block:: console
266
Charles Chan8299f072019-09-23 11:32:26 -0700267 $ curl --user onos:rocks -X POST -H 'Content-Type:application/json' http://<controller-ip>:8181/onos/routeservice/routes/bulk -d@routes.json
268 $ curl --user onos:rocks -X DELETE -H 'Content-Type:application/json' http://<controller-ip>:8181/onos/routeservice/routes/bulk -d@routes.json
Charles Chan8d3ae672019-09-07 22:07:22 -0700269
270with identical json format for both POST and DELETE:
271
272.. code-block:: json
273
Charles Chan8299f072019-09-23 11:32:26 -0700274 {
275 "routes": [
276 {
277 "prefix": "20.0.0.1/24",
278 "nextHop": "10.0.1.10"
279 },
280 {
281 "prefix": "30.0.0.1/24",
282 "nextHop": "10.0.2.15"
283 }
284 ]
285 }
Charles Chan8d3ae672019-09-07 22:07:22 -0700286
287
288Verify routes
289^^^^^^^^^^^^^
290Check the leaf switches that the route (e.g. 1.1.0.0/18) has been programmed in the routing table (table 30).
291
292.. code-block:: console
293
Charles Chan8299f072019-09-23 11:32:26 -0700294 onos> flows any of:0000000000000205 30
295 <snip>
296 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],
297 treatment=DefaultTrafficTreatment{immediate=[], deferred=[GROUP:0x70000014], transition=TABLE:60, meter=None, cleared=false, metadata=null}
298 <snip>
Charles Chan8d3ae672019-09-07 22:07:22 -0700299
300Notes about next hops
301^^^^^^^^^^^^^^^^^^^^^
302The next hop of a route should be resolvable to a MAC address that is known to ONOS.
303Typically the next hop is a server interface that is known to ONOS as a host learned via ARP or DHCP.
304If you are not sure, check the ``hosts`` command on the ONOS CLI.
305
306.. code-block:: console
307
Charles Chan8299f072019-09-23 11:32:26 -0700308 onos> hosts
309 <snip>
310 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
311 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
312 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
Charles Chan8d3ae672019-09-07 22:07:22 -0700313
314If 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.
315Learn more about how to configure a host using `Network Config Host Provider <https://wiki.onosproject.org/display/ONOS/Network+Config+Host+Provider>`_
316
317Finally 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.
318
319
320Route blackhole
321---------------
322The blackhole consists of a rule on table 30 on every edge device on the fabric.
323The Table 30 rule matches on a given IP address and mask and has nothing but a clearDeferred action, practically dropping the packet.
324Every IP we want to blackhole will have it's own rule in every edge switch.
325
326An example of such rule is:
327
328.. code-block:: text
329
Charles Chan8299f072019-09-23 11:32:26 -0700330 ADDED, bytes=0, packets=0, table=30, priority=48010, selector=[ETH_TYPE:ipv4, IPV4_DST:50.0.0.0/24], treatment=[transition=TABLE:60]
Charles Chan8d3ae672019-09-07 22:07:22 -0700331
332Route blackholing can be done via network configuration.
333
334.. code-block:: json
335
Charles Chan8299f072019-09-23 11:32:26 -0700336 {
337 "apps" : {
338 "org.onosproject.segmentrouting" : {
339 "segmentrouting": {
340 "blackholeIps": [
341 "50.0.0.0/24"
342 ]
343 }
344 }
345 }
346 }