]> git.proxmox.com Git - ovs.git/blame - tutorial/OVN-Tutorial.md
lib: Retire packet buffering feature.
[ovs.git] / tutorial / OVN-Tutorial.md
CommitLineData
9107431f
RB
1OVN Tutorial
2============
3
4This tutorial is intended to give you a tour of the basic OVN features using
5`ovs-sandbox` as a simulated test environment. It’s assumed that you have an
6understanding of OVS before going through this tutorial. Detail about OVN is
848cb198 7covered in [ovn-architecture(7)], but this tutorial lets you quickly see it in
9107431f
RB
8action.
9
10Getting Started
11---------------
12
13For some general information about `ovs-sandbox`, see the “Getting Started”
14section of [Tutorial.md].
15
16`ovs-sandbox` does not include OVN support by default. To enable OVN, you must
17pass the `--ovn` flag. For example, if running it straight from the ovs git
18tree you would run:
19
7cc36b8f 20 $ make sandbox SANDBOXFLAGS="--ovn"
9107431f
RB
21
22Running the sandbox with OVN enabled does the following additional steps to the
23environment:
24
25 1. Creates the `OVN_Northbound` and `OVN_Southbound` databases as described in
848cb198 26 [ovn-nb(5)] and [ovn-sb(5)].
9107431f 27
9ec13182
AZ
28 2. Creates a backup server for `OVN_Southbond` database. Sandbox launch
29 screen provides the instructions on accessing the backup database.
30 However access to the backup server is not required to go through the
31 tutorial.
9107431f 32
9ec13182
AZ
33 3. Creates the `hardware_vtep` database as described in [vtep(5)].
34
35 4. Runs the [ovn-northd(8)], [ovn-controller(8)], and [ovn-controller-vtep(8)]
848cb198 36 daemons.
9107431f 37
9ec13182 38 5. Makes OVN and VTEP utilities available for use in the environment,
848cb198 39 including [vtep-ctl(8)], [ovn-nbctl(8)], and [ovn-sbctl(8)].
9107431f
RB
40
41Note that each of these demos assumes you start with a fresh sandbox
b3ecab7e
FF
42environment. **Re-run `ovs-sandbox` before starting each section.**
43
44Using GDB
45---------
46
47GDB support is not required to go through the tutorial. See the “Using GDB”
48section of [Tutorial.md] for more info. Additional flags exist for launching
49the debugger for the OVN programs:
50
51 --gdb-ovn-northd
52 --gdb-ovn-controller
53 --gdb-ovn-controller-vtep
54
9107431f
RB
55
561) Simple two-port setup
57------------------------
58
59This first environment is the simplest OVN example. It demonstrates using OVN
60with a single logical switch that has two logical ports, both residing on the
61same hypervisor.
62
63Start by running the setup script for this environment.
64
65[View ovn/env1/setup.sh][env1setup].
66
67 $ ovn/env1/setup.sh
68
69You can use the `ovn-nbctl` utility to see an overview of the logical topology.
70
71 $ ovn-nbctl show
ea46a4e9 72 switch 78687d53-e037-4555-bcd3-f4f8eaf3f2aa (sw0)
31ed1192 73 port sw0-port1
ae3b45b6 74 addresses: [“00:00:00:00:00:01”]
31ed1192 75 port sw0-port2
ae3b45b6 76 addresses: [“00:00:00:00:00:02”]
9107431f
RB
77
78The `ovn-sbctl` utility can be used to see into the state stored in the
79`OVN_Southbound` database. The `show` command shows that there is a single
80chassis with two logical ports bound to it. In a more realistic
81multi-hypervisor environment, this would list all hypervisors and where all
82logical ports are located.
83
84 $ ovn-sbctl show
85 Chassis “56b18105-5706-46ef-80c4-ff20979ab068”
86 Encap geneve
87 ip: “127.0.0.1”
88 Port_Binding “sw0-port1”
89 Port_Binding “sw0-port2”
90
91OVN creates logical flows to describe how the network should behave in logical
92space. Each chassis then creates OpenFlow flows based on those logical flows
93that reflect its own local view of the network. The `ovn-sbctl` command can
94show the logical flows.
95
96 $ ovn-sbctl lflow-list
1e25f5ca
RB
97 Datapath: 2503dd42-14b1-414a-abbf-33e554e09ddc Pipeline: ingress
98 table=0 (ls_in_port_sec_l2 ), priority=100 , match=(eth.src[40]), action=(drop;)
99 table=0 (ls_in_port_sec_l2 ), priority=100 , match=(vlan.present), action=(drop;)
100 table=0 (ls_in_port_sec_l2 ), priority=50 , match=(inport == “sw0-port1” && eth.src == {00:00:00:00:00:01}), action=(next;)
101 table=0 (ls_in_port_sec_l2 ), priority=50 , match=(inport == “sw0-port2” && eth.src == {00:00:00:00:00:02}), action=(next;)
102 table=1 (ls_in_port_sec_ip ), priority=0 , match=(1), action=(next;)
103 table=2 (ls_in_port_sec_nd ), priority=90 , match=(inport == “sw0-port1” && eth.src == 00:00:00:00:00:01 && arp.sha == 00:00:00:00:00:01), action=(next;)
104 table=2 (ls_in_port_sec_nd ), priority=90 , match=(inport == “sw0-port1” && eth.src == 00:00:00:00:00:01 && ip6 && nd && ((nd.sll == 00:00:00:00:00:00 || nd.sll == 00:00:00:00:00:01) || ((nd.tll == 00:00:00:00:00:00 || nd.tll == 00:00:00:00:00:01)))), action=(next;)
105 table=2 (ls_in_port_sec_nd ), priority=90 , match=(inport == “sw0-port2” && eth.src == 00:00:00:00:00:02 && arp.sha == 00:00:00:00:00:02), action=(next;)
106 table=2 (ls_in_port_sec_nd ), priority=90 , match=(inport == “sw0-port2” && eth.src == 00:00:00:00:00:02 && ip6 && nd && ((nd.sll == 00:00:00:00:00:00 || nd.sll == 00:00:00:00:00:02) || ((nd.tll == 00:00:00:00:00:00 || nd.tll == 00:00:00:00:00:02)))), action=(next;)
107 table=2 (ls_in_port_sec_nd ), priority=80 , match=(inport == “sw0-port1” && (arp || nd)), action=(drop;)
108 table=2 (ls_in_port_sec_nd ), priority=80 , match=(inport == “sw0-port2” && (arp || nd)), action=(drop;)
109 table=2 (ls_in_port_sec_nd ), priority=0 , match=(1), action=(next;)
110 table=3 (ls_in_pre_acl ), priority=0 , match=(1), action=(next;)
111 table=4 (ls_in_pre_lb ), priority=0 , match=(1), action=(next;)
112 table=5 (ls_in_pre_stateful ), priority=100 , match=(reg0[0] == 1), action=(ct_next;)
113 table=5 (ls_in_pre_stateful ), priority=0 , match=(1), action=(next;)
114 table=6 (ls_in_acl ), priority=0 , match=(1), action=(next;)
115 table=7 (ls_in_lb ), priority=0 , match=(1), action=(next;)
116 table=8 (ls_in_stateful ), priority=100 , match=(reg0[1] == 1), action=(ct_commit; next;)
117 table=8 (ls_in_stateful ), priority=100 , match=(reg0[2] == 1), action=(ct_lb;)
118 table=8 (ls_in_stateful ), priority=0 , match=(1), action=(next;)
119 table=9 (ls_in_arp_rsp ), priority=0 , match=(1), action=(next;)
120 table=10(ls_in_l2_lkup ), priority=100 , match=(eth.mcast), action=(outport = “_MC_flood”; output;)
121 table=10(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:00:01), action=(outport = “sw0-port1”; output;)
122 table=10(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:00:02), action=(outport = “sw0-port2”; output;)
123 Datapath: 2503dd42-14b1-414a-abbf-33e554e09ddc Pipeline: egress
124 table=0 (ls_out_pre_lb ), priority=0 , match=(1), action=(next;)
125 table=1 (ls_out_pre_acl ), priority=0 , match=(1), action=(next;)
126 table=2 (ls_out_pre_stateful), priority=100 , match=(reg0[0] == 1), action=(ct_next;)
127 table=2 (ls_out_pre_stateful), priority=0 , match=(1), action=(next;)
128 table=3 (ls_out_lb ), priority=0 , match=(1), action=(next;)
129 table=4 (ls_out_acl ), priority=0 , match=(1), action=(next;)
130 table=5 (ls_out_stateful ), priority=100 , match=(reg0[1] == 1), action=(ct_commit; next;)
131 table=5 (ls_out_stateful ), priority=100 , match=(reg0[2] == 1), action=(ct_lb;)
132 table=5 (ls_out_stateful ), priority=0 , match=(1), action=(next;)
133 table=6 (ls_out_port_sec_ip ), priority=0 , match=(1), action=(next;)
134 table=7 (ls_out_port_sec_l2 ), priority=100 , match=(eth.mcast), action=(output;)
135 table=7 (ls_out_port_sec_l2 ), priority=50 , match=(outport == “sw0-port1” && eth.dst == {00:00:00:00:00:01}), action=(output;)
136 table=7 (ls_out_port_sec_l2 ), priority=50 , match=(outport == “sw0-port2” && eth.dst == {00:00:00:00:00:02}), action=(output;)
9107431f
RB
137
138Now we can start taking a closer look at how `ovn-controller` has programmed the
139local switch. Before looking at the flows, we can use `ovs-ofctl` to verify the
140OpenFlow port numbers for each of the logical ports on the switch. The output
141shows that `lport1`, which corresponds with our logical port `sw0-port1`, has an
142OpenFlow port number of `1`. Similarly, `lport2` has an OpenFlow port number of
143`2`.
144
145 $ ovs-ofctl show br-int
146 OFPT_FEATURES_REPLY (xid=0x2): dpid:00003e1ba878364d
c184807c 147 n_tables:254, n_buffers:0
9107431f
RB
148 capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP
149 actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst mod_nw_src mod_nw_dst mod_nw_tos mod_tp_src mod_tp_dst
150 1(lport1): addr:aa:55:aa:55:00:07
151 config: PORT_DOWN
152 state: LINK_DOWN
153 speed: 0 Mbps now, 0 Mbps max
154 2(lport2): addr:aa:55:aa:55:00:08
155 config: PORT_DOWN
156 state: LINK_DOWN
157 speed: 0 Mbps now, 0 Mbps max
158 LOCAL(br-int): addr:3e:1b:a8:78:36:4d
159 config: PORT_DOWN
160 state: LINK_DOWN
161 speed: 0 Mbps now, 0 Mbps max
162 OFPT_GET_CONFIG_REPLY (xid=0x4): frags=normal miss_send_len=0
163
164Finally, use `ovs-ofctl` to see the OpenFlow flows for `br-int`. Note that some
165fields have been omitted for brevity.
166
167 $ ovs-ofctl -O OpenFlow13 dump-flows br-int
168 OFPST_FLOW reply (OF1.3) (xid=0x2):
ae3b45b6
RB
169 table=0, priority=100,in_port=1 actions=set_field:0x1->metadata,set_field:0x1->reg6,resubmit(,16)
170 table=0, priority=100,in_port=2 actions=set_field:0x1->metadata,set_field:0x2->reg6,resubmit(,16)
9107431f 171 table=16, priority=100,metadata=0x1,vlan_tci=0x1000/0x1000 actions=drop
b3ecab7e 172 table=16, priority=100,metadata=0x1,dl_src=01:00:00:00:00:00/01:00:00:00:00:00 actions=drop
9107431f
RB
173 table=16, priority=50,reg6=0x1,metadata=0x1,dl_src=00:00:00:00:00:01 actions=resubmit(,17)
174 table=16, priority=50,reg6=0x2,metadata=0x1,dl_src=00:00:00:00:00:02 actions=resubmit(,17)
175 table=17, priority=0,metadata=0x1 actions=resubmit(,18)
b3ecab7e
FF
176 table=18, priority=90,icmp6,reg6=0x2,metadata=0x1,dl_src=00:00:00:00:00:02,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:00:00 actions=resubmit(,19)
177 table=18, priority=90,icmp6,reg6=0x2,metadata=0x1,dl_src=00:00:00:00:00:02,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:00:02 actions=resubmit(,19)
178 table=18, priority=90,icmp6,reg6=0x1,metadata=0x1,dl_src=00:00:00:00:00:01,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:00:00 actions=resubmit(,19)
179 table=18, priority=90,icmp6,reg6=0x1,metadata=0x1,dl_src=00:00:00:00:00:01,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:00:01 actions=resubmit(,19)
180 table=18, priority=90,icmp6,reg6=0x1,metadata=0x1,dl_src=00:00:00:00:00:01,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:01 actions=resubmit(,19)
181 table=18, priority=90,icmp6,reg6=0x1,metadata=0x1,dl_src=00:00:00:00:00:01,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:00 actions=resubmit(,19)
182 table=18, priority=90,icmp6,reg6=0x2,metadata=0x1,dl_src=00:00:00:00:00:02,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:00 actions=resubmit(,19)
183 table=18, priority=90,icmp6,reg6=0x2,metadata=0x1,dl_src=00:00:00:00:00:02,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:02 actions=resubmit(,19)
184 table=18, priority=90,arp,reg6=0x1,metadata=0x1,dl_src=00:00:00:00:00:01,arp_sha=00:00:00:00:00:01 actions=resubmit(,19)
185 table=18, priority=90,arp,reg6=0x2,metadata=0x1,dl_src=00:00:00:00:00:02,arp_sha=00:00:00:00:00:02 actions=resubmit(,19)
186 table=18, priority=80,icmp6,reg6=0x2,metadata=0x1,icmp_type=136,icmp_code=0 actions=drop
187 table=18, priority=80,icmp6,reg6=0x1,metadata=0x1,icmp_type=136,icmp_code=0 actions=drop
188 table=18, priority=80,icmp6,reg6=0x1,metadata=0x1,icmp_type=135,icmp_code=0 actions=drop
189 table=18, priority=80,icmp6,reg6=0x2,metadata=0x1,icmp_type=135,icmp_code=0 actions=drop
190 table=18, priority=80,arp,reg6=0x2,metadata=0x1 actions=drop
191 table=18, priority=80,arp,reg6=0x1,metadata=0x1 actions=drop
192 table=18, priority=0,metadata=0x1 actions=resubmit(,19)
193 table=19, priority=0,metadata=0x1 actions=resubmit(,20)
194 table=20, priority=0,metadata=0x1 actions=resubmit(,21)
195 table=21, priority=0,metadata=0x1 actions=resubmit(,22)
ae3b45b6
RB
196 table=22, priority=0,metadata=0x1 actions=resubmit(,23)
197 table=23, priority=0,metadata=0x1 actions=resubmit(,24)
198 table=24, priority=0,metadata=0x1 actions=resubmit(,25)
199 table=25, priority=0,metadata=0x1 actions=resubmit(,26)
200 table=26, priority=100,metadata=0x1,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=set_field:0xffff->reg7,resubmit(,32)
201 table=26, priority=50,metadata=0x1,dl_dst=00:00:00:00:00:01 actions=set_field:0x1->reg7,resubmit(,32)
202 table=26, priority=50,metadata=0x1,dl_dst=00:00:00:00:00:02 actions=set_field:0x2->reg7,resubmit(,32)
9107431f 203 table=32, priority=0 actions=resubmit(,33)
ae3b45b6
RB
204 table=33, priority=100,reg7=0x1,metadata=0x1 actions=resubmit(,34)
205 table=33, priority=100,reg7=0xffff,metadata=0x1 actions=set_field:0x2->reg7,resubmit(,34),set_field:0x1->reg7,resubmit(,34),set_field:0xffff->reg7
206 table=33, priority=100,reg7=0x2,metadata=0x1 actions=resubmit(,34)
9107431f
RB
207 table=34, priority=100,reg6=0x1,reg7=0x1,metadata=0x1 actions=drop
208 table=34, priority=100,reg6=0x2,reg7=0x2,metadata=0x1 actions=drop
ae3b45b6 209 table=34, priority=0 actions=set_field:0->reg0,set_field:0->reg1,set_field:0->reg2,resubmit(,48)
9107431f 210 table=48, priority=0,metadata=0x1 actions=resubmit(,49)
b3ecab7e
FF
211 table=49, priority=0,metadata=0x1 actions=resubmit(,50)
212 table=50, priority=0,metadata=0x1 actions=resubmit(,51)
ae3b45b6
RB
213 table=51, priority=0,metadata=0x1 actions=resubmit(,52)
214 table=52, priority=0,metadata=0x1 actions=resubmit(,53)
215 table=53, priority=0,metadata=0x1 actions=resubmit(,54)
216 table=54, priority=0,metadata=0x1 actions=resubmit(,55)
217 table=55, priority=100,metadata=0x1,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,64)
218 table=55, priority=50,reg7=0x2,metadata=0x1,dl_dst=00:00:00:00:00:02 actions=resubmit(,64)
219 table=55, priority=50,reg7=0x1,metadata=0x1,dl_dst=00:00:00:00:00:01 actions=resubmit(,64)
9107431f 220 table=64, priority=100,reg7=0x1,metadata=0x1 actions=output:1
9107431f 221
848cb198 222The `ovs-appctl` command can be used to generate an OpenFlow trace of how a
9107431f
RB
223packet would be processed in this configuration. This first trace shows a
224packet from `sw0-port1` to `sw0-port2`. The packet arrives from port `1` and
225should be output to port `2`.
226
227[View ovn/env1/packet1.sh][env1packet1].
228
229 $ ovn/env1/packet1.sh
230
231Trace a broadcast packet from `sw0-port1`. The packet arrives from port `1` and
232should be output to port `2`.
233
234[View ovn/env1/packet2.sh][env1packet2].
235
236 $ ovn/env1/packet2.sh
237
238You can extend this setup by adding additional ports. For example, to add a
239third port, run this command:
240
241[View ovn/env1/add-third-port.sh][env1thirdport].
242
243 $ ovn/env1/add-third-port.sh
244
245Now if you do another trace of a broadcast packet from `sw0-port1`, you will see
246that it is output to both ports `2` and `3`.
247
248 $ ovn/env1/packet2.sh
249
dd52c85c 250The logical port may have an unknown set of Ethernet addresses. When an OVN logical
251switch processes a unicast Ethernet frame whose destination MAC address is not in any
252logical port’s addresses column, it delivers it to the port (or ports) whose addresses
253columns include unknown.
254
255[View ovn/env1/add-unknown-ports.sh][env1unknownports].
256
257 $ ovn/env1/add-unknown-ports.sh
258
259This trace shows a packet from `sw0-port1` to `sw0-port4`, `sw0-port5` whose addresses
260columns include unknown. You will see that it is output to both ports `4` and `5`.
261
262[View ovn/env1/packet3.sh][env1packet3].
263
264 $ ovn/env1/packet3.sh
265
266The logical port would restrict the host to sending packets from and receiving packets
267to the ethernet addresses defined in the logical port’s port_security column.
268In addition to the restrictions described for Ethernet addresses above, such an element
269of port_security restricts the IPv4 or IPv6 addresses from which the host may send and
270to which it may receive packets to the specified addresses.
271
272[View ovn/env1/add-security-ip-ports.sh][env1securityport].
273
274 $ ovn/env1/add-security-ip-ports.sh
275
276This trace shows a packet from `sw0-port6` to `sw0-port7`.
277
278[View ovn/env1/packet4.sh][env1packet4].
279
280 $ ovn/env1/packet4.sh
281
9107431f
RB
2822) 2 switches, 4 ports
283----------------------
284
285This environment is an extension of the last example. The previous example
286showed two ports on a single logical switch. In this environment we add a
287second logical switch that also has two ports. This lets you start to see how
288`ovn-controller` creates flows for isolated networks to co-exist on the same
289switch.
290
291[View ovn/env2/setup.sh][env2setup].
292
293 $ ovn/env2/setup.sh
294
295View the logical topology with `ovn-nbctl`.
296
297 $ ovn-nbctl show
ea46a4e9 298 switch e3190dc2-89d1-44ed-9308-e7077de782b3 (sw0)
31ed1192 299 port sw0-port1
2fa326a3 300 addresses: 00:00:00:00:00:01
31ed1192 301 port sw0-port2
2fa326a3 302 addresses: 00:00:00:00:00:02
ea46a4e9 303 switch c8ed4c5f-9733-43f6-93da-795b1aabacb1 (sw1)
31ed1192 304 port sw1-port1
2fa326a3 305 addresses: 00:00:00:00:00:03
31ed1192 306 port sw1-port2
2fa326a3 307 addresses: 00:00:00:00:00:04
9107431f
RB
308
309Physically, all ports reside on the same chassis.
310
311 $ ovn-sbctl show
312 Chassis “56b18105-5706-46ef-80c4-ff20979ab068”
313 Encap geneve
314 ip: “127.0.0.1”
315 Port_Binding “sw1-port2”
316 Port_Binding “sw0-port2”
317 Port_Binding “sw0-port1”
318 Port_Binding “sw1-port1”
319
320OVN creates separate logical flows for each logical switch.
321
322 $ ovn-sbctl lflow-list
1e25f5ca
RB
323 Datapath: 7ee908c1-b0d3-4d03-acc9-42cd7ef7f27d Pipeline: ingress
324 table=0 (ls_in_port_sec_l2 ), priority=100 , match=(eth.src[40]), action=(drop;)
325 table=0 (ls_in_port_sec_l2 ), priority=100 , match=(vlan.present), action=(drop;)
326 table=0 (ls_in_port_sec_l2 ), priority=50 , match=(inport == "sw1-port1" && eth.src == {00:00:00:00:00:03}), action=(next;)
327 table=0 (ls_in_port_sec_l2 ), priority=50 , match=(inport == "sw1-port2" && eth.src == {00:00:00:00:00:04}), action=(next;)
328 table=1 (ls_in_port_sec_ip ), priority=0 , match=(1), action=(next;)
329 table=2 (ls_in_port_sec_nd ), priority=90 , match=(inport == "sw1-port1" && eth.src == 00:00:00:00:00:03 && arp.sha == 00:00:00:00:00:03), action=(next;)
330 table=2 (ls_in_port_sec_nd ), priority=90 , match=(inport == "sw1-port1" && eth.src == 00:00:00:00:00:03 && ip6 && nd && ((nd.sll == 00:00:00:00:00:00 || nd.sll == 00:00:00:00:00:03) || ((nd.tll == 00:00:00:00:00:00 || nd.tll == 00:00:00:00:00:03)))), action=(next;)
331 table=2 (ls_in_port_sec_nd ), priority=90 , match=(inport == "sw1-port2" && eth.src == 00:00:00:00:00:04 && arp.sha == 00:00:00:00:00:04), action=(next;)
332 table=2 (ls_in_port_sec_nd ), priority=90 , match=(inport == "sw1-port2" && eth.src == 00:00:00:00:00:04 && ip6 && nd && ((nd.sll == 00:00:00:00:00:00 || nd.sll == 00:00:00:00:00:04) || ((nd.tll == 00:00:00:00:00:00 || nd.tll == 00:00:00:00:00:04)))), action=(next;)
333 table=2 (ls_in_port_sec_nd ), priority=80 , match=(inport == "sw1-port1" && (arp || nd)), action=(drop;)
334 table=2 (ls_in_port_sec_nd ), priority=80 , match=(inport == "sw1-port2" && (arp || nd)), action=(drop;)
335 table=2 (ls_in_port_sec_nd ), priority=0 , match=(1), action=(next;)
336 table=3 (ls_in_pre_acl ), priority=0 , match=(1), action=(next;)
337 table=4 (ls_in_pre_lb ), priority=0 , match=(1), action=(next;)
338 table=5 (ls_in_pre_stateful ), priority=100 , match=(reg0[0] == 1), action=(ct_next;)
339 table=5 (ls_in_pre_stateful ), priority=0 , match=(1), action=(next;)
340 table=6 (ls_in_acl ), priority=0 , match=(1), action=(next;)
341 table=7 (ls_in_lb ), priority=0 , match=(1), action=(next;)
342 table=8 (ls_in_stateful ), priority=100 , match=(reg0[1] == 1), action=(ct_commit; next;)
343 table=8 (ls_in_stateful ), priority=100 , match=(reg0[2] == 1), action=(ct_lb;)
344 table=8 (ls_in_stateful ), priority=0 , match=(1), action=(next;)
345 table=9 (ls_in_arp_rsp ), priority=0 , match=(1), action=(next;)
346 table=10(ls_in_l2_lkup ), priority=100 , match=(eth.mcast), action=(outport = "_MC_flood"; output;)
347 table=10(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:00:03), action=(outport = "sw1-port1"; output;)
348 table=10(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:00:04), action=(outport = "sw1-port2"; output;)
349 Datapath: 7ee908c1-b0d3-4d03-acc9-42cd7ef7f27d Pipeline: egress
350 table=0 (ls_out_pre_lb ), priority=0 , match=(1), action=(next;)
351 table=1 (ls_out_pre_acl ), priority=0 , match=(1), action=(next;)
352 table=2 (ls_out_pre_stateful), priority=100 , match=(reg0[0] == 1), action=(ct_next;)
353 table=2 (ls_out_pre_stateful), priority=0 , match=(1), action=(next;)
354 table=3 (ls_out_lb ), priority=0 , match=(1), action=(next;)
355 table=4 (ls_out_acl ), priority=0 , match=(1), action=(next;)
356 table=5 (ls_out_stateful ), priority=100 , match=(reg0[1] == 1), action=(ct_commit; next;)
357 table=5 (ls_out_stateful ), priority=100 , match=(reg0[2] == 1), action=(ct_lb;)
358 table=5 (ls_out_stateful ), priority=0 , match=(1), action=(next;)
359 table=6 (ls_out_port_sec_ip ), priority=0 , match=(1), action=(next;)
360 table=7 (ls_out_port_sec_l2 ), priority=100 , match=(eth.mcast), action=(output;)
361 table=7 (ls_out_port_sec_l2 ), priority=50 , match=(outport == "sw1-port1" && eth.dst == {00:00:00:00:00:03}), action=(output;)
362 table=7 (ls_out_port_sec_l2 ), priority=50 , match=(outport == "sw1-port2" && eth.dst == {00:00:00:00:00:04}), action=(output;)
363 Datapath: 9ea0c8f9-4f82-4be3-a6c7-6e6f9c2de583 Pipeline: ingress
364 table=0 (ls_in_port_sec_l2 ), priority=100 , match=(eth.src[40]), action=(drop;)
365 table=0 (ls_in_port_sec_l2 ), priority=100 , match=(vlan.present), action=(drop;)
366 table=0 (ls_in_port_sec_l2 ), priority=50 , match=(inport == "sw0-port1" && eth.src == {00:00:00:00:00:01}), action=(next;)
367 table=0 (ls_in_port_sec_l2 ), priority=50 , match=(inport == "sw0-port2" && eth.src == {00:00:00:00:00:02}), action=(next;)
368 table=1 (ls_in_port_sec_ip ), priority=0 , match=(1), action=(next;)
369 table=2 (ls_in_port_sec_nd ), priority=90 , match=(inport == "sw0-port1" && eth.src == 00:00:00:00:00:01 && arp.sha == 00:00:00:00:00:01), action=(next;)
370 table=2 (ls_in_port_sec_nd ), priority=90 , match=(inport == "sw0-port1" && eth.src == 00:00:00:00:00:01 && ip6 && nd && ((nd.sll == 00:00:00:00:00:00 || nd.sll == 00:00:00:00:00:01) || ((nd.tll == 00:00:00:00:00:00 || nd.tll == 00:00:00:00:00:01)))), action=(next;)
371 table=2 (ls_in_port_sec_nd ), priority=90 , match=(inport == "sw0-port2" && eth.src == 00:00:00:00:00:02 && arp.sha == 00:00:00:00:00:02), action=(next;)
372 table=2 (ls_in_port_sec_nd ), priority=90 , match=(inport == "sw0-port2" && eth.src == 00:00:00:00:00:02 && ip6 && nd && ((nd.sll == 00:00:00:00:00:00 || nd.sll == 00:00:00:00:00:02) || ((nd.tll == 00:00:00:00:00:00 || nd.tll == 00:00:00:00:00:02)))), action=(next;)
373 table=2 (ls_in_port_sec_nd ), priority=80 , match=(inport == "sw0-port1" && (arp || nd)), action=(drop;)
374 table=2 (ls_in_port_sec_nd ), priority=80 , match=(inport == "sw0-port2" && (arp || nd)), action=(drop;)
375 table=2 (ls_in_port_sec_nd ), priority=0 , match=(1), action=(next;)
376 table=3 (ls_in_pre_acl ), priority=0 , match=(1), action=(next;)
377 table=4 (ls_in_pre_lb ), priority=0 , match=(1), action=(next;)
378 table=5 (ls_in_pre_stateful ), priority=100 , match=(reg0[0] == 1), action=(ct_next;)
379 table=5 (ls_in_pre_stateful ), priority=0 , match=(1), action=(next;)
380 table=6 (ls_in_acl ), priority=0 , match=(1), action=(next;)
381 table=7 (ls_in_lb ), priority=0 , match=(1), action=(next;)
382 table=8 (ls_in_stateful ), priority=100 , match=(reg0[1] == 1), action=(ct_commit; next;)
383 table=8 (ls_in_stateful ), priority=100 , match=(reg0[2] == 1), action=(ct_lb;)
384 table=8 (ls_in_stateful ), priority=0 , match=(1), action=(next;)
385 table=9 (ls_in_arp_rsp ), priority=0 , match=(1), action=(next;)
386 table=10(ls_in_l2_lkup ), priority=100 , match=(eth.mcast), action=(outport = "_MC_flood"; output;)
387 table=10(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:00:01), action=(outport = "sw0-port1"; output;)
388 table=10(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:00:02), action=(outport = "sw0-port2"; output;)
389 Datapath: 9ea0c8f9-4f82-4be3-a6c7-6e6f9c2de583 Pipeline: egress
390 table=0 (ls_out_pre_lb ), priority=0 , match=(1), action=(next;)
391 table=1 (ls_out_pre_acl ), priority=0 , match=(1), action=(next;)
392 table=2 (ls_out_pre_stateful), priority=100 , match=(reg0[0] == 1), action=(ct_next;)
393 table=2 (ls_out_pre_stateful), priority=0 , match=(1), action=(next;)
394 table=3 (ls_out_lb ), priority=0 , match=(1), action=(next;)
395 table=4 (ls_out_acl ), priority=0 , match=(1), action=(next;)
396 table=5 (ls_out_stateful ), priority=100 , match=(reg0[1] == 1), action=(ct_commit; next;)
397 table=5 (ls_out_stateful ), priority=100 , match=(reg0[2] == 1), action=(ct_lb;)
398 table=5 (ls_out_stateful ), priority=0 , match=(1), action=(next;)
399 table=6 (ls_out_port_sec_ip ), priority=0 , match=(1), action=(next;)
400 table=7 (ls_out_port_sec_l2 ), priority=100 , match=(eth.mcast), action=(output;)
401 table=7 (ls_out_port_sec_l2 ), priority=50 , match=(outport == "sw0-port1" && eth.dst == {00:00:00:00:00:01}), action=(output;)
402 table=7 (ls_out_port_sec_l2 ), priority=50 , match=(outport == "sw0-port2" && eth.dst == {00:00:00:00:00:02}), action=(output;)
9107431f
RB
403
404In this setup, `sw0-port1` and `sw0-port2` can send packets to each other, but
405not to either of the ports on `sw1`. This first trace shows a packet from
406`sw0-port1` to `sw0-port2`. You should see th packet arrive on OpenFlow port
407`1` and output to OpenFlow port `2`.
408
409[View ovn/env2/packet1.sh][env2packet1].
410
411 $ ovn/env2/packet1.sh
412
413This next example shows a packet from `sw0-port1` with a destination MAC address
414of `00:00:00:00:00:03`, which is the MAC address for `sw1-port1`. Since these
415ports are not on the same logical switch, the packet should just be dropped.
416
417[View ovn/env2/packet2.sh][env2packet2].
418
419 $ ovn/env2/packet2.sh
420
4213) Two Hypervisors
422------------------
423
424The first two examples started by showing OVN on a single hypervisor. A more
425realistic deployment of OVN would span multiple hypervisors. This example
426creates a single logical switch with 4 logical ports. It then simulates having
427two hypervisors with two of the logical ports bound to each hypervisor.
428
429[View ovn/env3/setup.sh][env3setup].
430
431 $ ovn/env3/setup.sh
432
433You can start by viewing the logical topology with `ovn-nbctl`.
434
435 $ ovn-nbctl show
ea46a4e9 436 switch b977dc03-79a5-41ba-9665-341a80e1abfd (sw0)
31ed1192 437 port sw0-port1
2fa326a3 438 addresses: 00:00:00:00:00:01
31ed1192 439 port sw0-port2
2fa326a3 440 addresses: 00:00:00:00:00:02
31ed1192 441 port sw0-port4
2fa326a3 442 addresses: 00:00:00:00:00:04
31ed1192 443 port sw0-port3
2fa326a3 444 addresses: 00:00:00:00:00:03
9107431f
RB
445
446Using `ovn-sbctl` to view the state of the system, we can see that there are two
447chassis: one local that we can interact with, and a fake remote chassis. Two
448logical ports are bound to each. Both chassis have an IP address of localhost,
449but in a realistic deployment that would be the IP address used for tunnels to
450that chassis.
451
452 $ ovn-sbctl show
453 Chassis “56b18105-5706-46ef-80c4-ff20979ab068”
454 Encap geneve
455 ip: “127.0.0.1”
456 Port_Binding “sw0-port2”
457 Port_Binding “sw0-port1”
458 Chassis fakechassis
459 Encap geneve
460 ip: “127.0.0.1”
461 Port_Binding “sw0-port4”
462 Port_Binding “sw0-port3”
463
464Packets between `sw0-port1` and `sw0-port2` behave just like the previous
465examples. Packets to ports on a remote chassis are the interesting part of this
466example. You may have noticed before that OVN’s logical flows are broken up
467into ingress and egress tables. Given a packet from `sw0-port1` on the local
468chassis to `sw0-port3` on the remote chassis, the ingress pipeline is executed
469on the local switch. OVN then determines that it must forward the packet over a
470geneve tunnel. When it arrives at the remote chassis, the egress pipeline will
471be executed there.
472
473This first packet trace shows the first part of this example. It’s a packet
474from `sw0-port1` to `sw0-port3` from the perspective of the local chassis.
475`sw0-port1` is OpenFlow port `1`. The tunnel to the fake remote chassis is
476OpenFlow port `3`. You should see the ingress pipeline being executed and then
477the packet output to port `3`, the geneve tunnel.
478
479[View ovn/env3/packet1.sh][env3packet1].
480
481 $ ovn/env3/packet1.sh
482
483To simulate what would happen when that packet arrives at the remote chassis we
484can flip this example around. Consider a packet from `sw0-port3` to
485`sw0-port1`. This trace shows what would happen when that packet arrives at the
486local chassis. The packet arrives on OpenFlow port `3` (the tunnel). You should
487then see the egress pipeline get executed and the packet output to OpenFlow port
488`1`.
489
490[View ovn/env3/packet2.sh][env3packet2].
491
492 $ ovn/env3/packet2.sh
493
4944) Locally attached networks
495----------------------------
496
497While OVN is generally focused on the implementation of logical networks using
498overlays, it’s also possible to use OVN as a control plane to manage logically
499direct connectivity to networks that are locally accessible to each chassis.
500
501This example includes two hypervisors. Both hypervisors have two ports on them.
502We want to use OVN to manage the connectivity of these ports to a network
503attached to each hypervisor that we will call “physnet1”.
504
505This scenario requires some additional configuration of `ovn-controller`. We
506must configure a mapping between `physnet1` and a local OVS bridge that provides
507connectivity to that network. We call these “bridge mappings”. For our
508example, the following script creates a bridge called `br-eth1` and then
509configures `ovn-controller` with a bridge mapping from `physnet1` to `br-eth1`.
510
2b2f2b2f 511We want to create a fake second chassis and then create the topology that tells
512OVN we want both ports on both hypervisors connected to `physnet1`. The way this
513is modeled in OVN is by creating a logical switch for each port. The logical
514switch has the regular VIF port and a `localnet` port.
9107431f 515
2b2f2b2f 516[View ovn/env4/setup.sh][env4setup].
517
518 $ ovn/env4/setup.sh
9107431f
RB
519
520At this point we should be able to see that `ovn-controller` has automatically
521created patch ports between `br-int` and `br-eth1`.
522
523 $ ovs-vsctl show
2b2f2b2f 524 c0a06d85-d70a-4e11-9518-76a92588b34e
525 Bridge "br-eth1"
526 Port "patch-provnet1-1-physnet1-to-br-int"
527 Interface "patch-provnet1-1-physnet1-to-br-int"
528 type: patch
529 options: {peer="patch-br-int-to-provnet1-1-physnet1"}
530 Port "br-eth1"
531 Interface "br-eth1"
532 type: internal
533 Port "patch-provnet1-2-physnet1-to-br-int"
534 Interface "patch-provnet1-2-physnet1-to-br-int"
535 type: patch
536 options: {peer="patch-br-int-to-provnet1-2-physnet1"}
9107431f
RB
537 Bridge br-int
538 fail_mode: secure
2b2f2b2f 539 Port "ovn-fakech-0"
540 Interface "ovn-fakech-0"
541 type: geneve
542 options: {key=flow, remote_ip="127.0.0.1"}
543 Port "patch-br-int-to-provnet1-2-physnet1"
544 Interface "patch-br-int-to-provnet1-2-physnet1"
9107431f 545 type: patch
2b2f2b2f 546 options: {peer="patch-provnet1-2-physnet1-to-br-int"}
9107431f
RB
547 Port br-int
548 Interface br-int
549 type: internal
2b2f2b2f 550 Port "patch-br-int-to-provnet1-1-physnet1"
551 Interface "patch-br-int-to-provnet1-1-physnet1"
9107431f 552 type: patch
2b2f2b2f 553 options: {peer="patch-provnet1-1-physnet1-to-br-int"}
554 Port "lport2"
555 Interface "lport2"
556 Port "lport1"
557 Interface "lport1
9107431f 558
9107431f
RB
559
560The logical topology from `ovn-nbctl` should look like this.
561
562 $ ovn-nbctl show
2b2f2b2f 563 switch 9db81140-5504-4f60-be3d-2bee45b57e27 (provnet1-2)
564 port provnet1-2-port1
565 addresses: ["00:00:00:00:00:02"]
566 port provnet1-2-physnet1
567 addresses: ["unknown"]
568 switch cf175cb9-35c5-41cf-8bc7-2d322cdbead0 (provnet1-3)
569 port provnet1-3-physnet1
570 addresses: ["unknown"]
571 port provnet1-3-port1
572 addresses: ["00:00:00:00:00:03"]
573 switch b85f7af6-8055-4db2-ba93-efc7887cf38f (provnet1-1)
574 port provnet1-1-port1
575 addresses: ["00:00:00:00:00:01"]
576 port provnet1-1-physnet1
577 addresses: ["unknown"]
578 switch 63a5e276-8807-417d-bbec-a7e907e106b1 (provnet1-4)
579 port provnet1-4-port1
580 addresses: ["00:00:00:00:00:04"]
581 port provnet1-4-physnet1
582 addresses: ["unknown"]
9107431f
RB
583
584`port1` on each logical switch represents a regular logical port for a VIF on a
585hypervisor. `physnet1` on each logical switch is the special `localnet` port.
586You can use `ovn-nbctl` to see that this port has a `type` and `options` set.
587
31ed1192 588 $ ovn-nbctl lsp-get-type provnet1-1-physnet1
9107431f
RB
589 localnet
590
31ed1192 591 $ ovn-nbctl lsp-get-options provnet1-1-physnet1
9107431f
RB
592 network_name=physnet1
593
594The physical topology should reflect that there are two regular ports on each
595chassis.
596
597 $ ovn-sbctl show
2b2f2b2f 598 Chassis "56b18105-5706-46ef-80c4-ff20979ab068"
599 hostname: sandbox
9107431f 600 Encap geneve
2b2f2b2f 601 ip: "127.0.0.1"
602 Port_Binding "provnet1-1-port1"
603 Port_Binding "provnet1-2-port1"
604 Chassis fakechassis
9107431f 605 Encap geneve
2b2f2b2f 606 ip: "127.0.0.1"
607 Port_Binding "provnet1-3-port1"
608 Port_Binding "provnet1-4-port1"
9107431f
RB
609
610All four of our ports should be able to communicate with each other, but they do
611so through `physnet1`. A packet from any of these ports to any destination
612should be output to the OpenFlow port number that corresponds to the patch port
613to `br-eth1`.
614
615This example assumes following OpenFlow port number mappings:
616
2b2f2b2f 617* 1 = tunnel to the fake second chassis
618* 2 = `lport1`, which is the logical port named `provnet1-1-port1`
619* 3 = `patch-br-int-to-provnet1-1-physnet1`, patch port to `br-eth1`
620* 4 = `lport2`, which is the logical port named `provnet1-2-port1`
621* 5 = `patch-br-int-to-provnet1-2-physnet1`, patch port to `br-eth1`
9107431f
RB
622
623We get those port numbers using `ovs-ofctl`:
624
625 $ ovs-ofctl show br-int
2b2f2b2f 626 OFPT_FEATURES_REPLY (xid=0x2): dpid:00002a84824b0d40
c184807c 627 n_tables:254, n_buffers:0
9107431f 628 capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP
2b2f2b2f 629 actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst
630 1(ovn-fakech-0): addr:aa:55:aa:55:00:0e
9107431f
RB
631 config: PORT_DOWN
632 state: LINK_DOWN
633 speed: 0 Mbps now, 0 Mbps max
2b2f2b2f 634 2(lport1): addr:aa:55:aa:55:00:0f
9107431f
RB
635 config: PORT_DOWN
636 state: LINK_DOWN
637 speed: 0 Mbps now, 0 Mbps max
2b2f2b2f 638 3(patch-br-int-to): addr:7a:6f:8a:d5:69:2a
639 config: 0
640 state: 0
641 speed: 0 Mbps now, 0 Mbps max
642 4(lport2): addr:aa:55:aa:55:00:10
9107431f
RB
643 config: PORT_DOWN
644 state: LINK_DOWN
645 speed: 0 Mbps now, 0 Mbps max
2b2f2b2f 646 5(patch-br-int-to): addr:4a:fd:c1:11:fc:a5
647 config: 0
648 state: 0
649 speed: 0 Mbps now, 0 Mbps max
650 LOCAL(br-int): addr:2a:84:82:4b:0d:40
9107431f
RB
651 config: PORT_DOWN
652 state: LINK_DOWN
653 speed: 0 Mbps now, 0 Mbps max
654 OFPT_GET_CONFIG_REPLY (xid=0x4): frags=normal miss_send_len=0
655
656This first trace shows a packet from `provnet1-1-port1` with a destination MAC
2b2f2b2f 657address of `provnet1-2-port1`. We expect the packets from `lport1`(OpenFlow port 2)
658to be sent out to `lport2`(OpenFlow port 4). For example, the following topology
659illustrates how the packets travel from `lport1` to `lport2`.
660
661 `lport1` --> `patch-br-int-to-provnet1-1-physnet1`(OpenFlow port 3)
662 --> `br-eth1` --> `patch-br-int-to-provnet1-2-physnet1` --> `lport2`(OpenFlow port 4)
663
664Similarly, We expect the packets from `provnet1-2-port1` to be sent out to
665`provnet1-1-port1`. We then expect the network to handle getting the packet to its
666destination. In practice, this will be optimized at `br-eth1` and the packet won’t
667actually go out and back on the network.
9107431f
RB
668
669[View ovn/env4/packet1.sh][env4packet1].
670
671 $ ovn/env4/packet1.sh
672
2b2f2b2f 673This next trace shows an example of a packet being sent to a destination on another
674hypervisor. The source is `provnet1-1-port1`, but the destination is `provnet1-3-port1`,
675which is on the other fake chassis. As usual, we expect the output to be to `br-eth1`
676(`patch-br-int-to-provnet1-1-physnet1`, OpenFlow port 3).
9107431f
RB
677
678[View ovn/env4/packet2.sh][env4packet2].
679
680 $ ovn/env4/packet2.sh
681
9107431f 682This next test shows a broadcast packet. The destination should still only be
2b2f2b2f 683OpenFlow port 3 and 4.
9107431f 684
2b2f2b2f 685[View ovn/env4/packet3.sh][env4packet3]
9107431f 686
2b2f2b2f 687 $ ovn/env4/packet3.sh
9107431f
RB
688
689Finally, this last trace shows what happens when a broadcast packet arrives
690from the network. In this case, it simulates a broadcast that originated from a
691port on the remote fake chassis and arrived at the local chassis via `br-eth1`.
692We should see it output to both local ports that are attached to this network
2b2f2b2f 693(OpenFlow ports 2 and 4).
9107431f 694
2b2f2b2f 695[View ovn/env4/packet4.sh][env4packet4]
9107431f 696
2b2f2b2f 697 $ ovn/env4/packet4.sh
9107431f
RB
698
6995) Locally attached networks with VLANs
700---------------------------------------
701
702This example is an extension of the previous one. We take the same setup and
703add two more ports to each hypervisor. Instead of having the new ports directly
704connected to `physnet1` as before, we indicate that we want them on VLAN 101 of
705`physnet1`. This shows how `localnet` ports can be used to provide connectivity
706to either a flat network or a VLAN on that network.
707
708[View ovn/env5/setup.sh][env5setup]
709
710 $ ovn/env5/setup.sh
711
712The logical topology shown by `ovn-nbctl` is similar to `env4`, except we now
713have 8 regular VIF ports connected to `physnet1` instead of 4. The additional 4
714ports we have added are all on VLAN 101 of `physnet1`. Note that the `localnet`
715ports representing connectivity to VLAN 101 of `physnet1` have the `tag` field
716set to `101`.
717
718 $ ovn-nbctl show
2b2f2b2f 719 switch 3e60b940-00bf-44c6-9db6-04abf28d7e5f (provnet1-1)
720 port provnet1-1-physnet1
721 addresses: ["unknown"]
722 port provnet1-1-port1
723 addresses: ["00:00:00:00:00:01"]
724 switch 87f6bea0-f74d-4f39-aa65-ca1f94670429 (provnet1-2)
725 port provnet1-2-port1
726 addresses: ["00:00:00:00:00:02"]
727 port provnet1-2-physnet1
728 addresses: ["unknown"]
729 switch e6c9cb69-a056-428d-aa40-e903ce416dcd (provnet1-6-101)
730 port provnet1-6-101-port1
731 addresses: ["00:00:00:00:00:06"]
732 port provnet1-6-physnet1-101
733 parent:
734 tag: 101
735 addresses: ["unknown"]
736 switch 5f8f72ca-6030-4f66-baea-fe6174eb54df (provnet1-4)
737 port provnet1-4-port1
738 addresses: ["00:00:00:00:00:04"]
739 port provnet1-4-physnet1
740 addresses: ["unknown"]
741 switch 15d585eb-d2c1-45ea-a946-b08de0eb2f55 (provnet1-7-101)
742 port provnet1-7-physnet1-101
743 parent:
744 tag: 101
745 addresses: ["unknown"]
746 port provnet1-7-101-port1
747 addresses: ["00:00:00:00:00:07"]
748 switch 7be4aabe-1bb0-4e16-a755-a1f6d81c1c2f (provnet1-5-101)
749 port provnet1-5-101-port1
750 addresses: ["00:00:00:00:00:05"]
751 port provnet1-5-physnet1-101
752 parent:
753 tag: 101
754 addresses: ["unknown"]
755 switch 9bbdbf0e-50f3-4286-ba5a-29bf347531bb (provnet1-8-101)
756 port provnet1-8-101-port1
757 addresses: ["00:00:00:00:00:08"]
758 port provnet1-8-physnet1-101
759 parent:
760 tag: 101
761 addresses: ["unknown"]
762 switch 70d053f7-2bca-4dff-96ae-bd728d3ba1d2 (provnet1-3)
763 port provnet1-3-physnet1
764 addresses: ["unknown"]
765 port provnet1-3-port1
766 addresses: ["00:00:00:00:00:03"]
9107431f
RB
767
768The physical topology shows that we have 4 regular VIF ports on each simulated
769hypervisor.
770
771 $ ovn-sbctl show
9107431f
RB
772 Chassis fakechassis
773 Encap geneve
2b2f2b2f 774 ip: "127.0.0.1"
775 Port_Binding "provnet1-3-port1"
776 Port_Binding "provnet1-8-101-port1"
777 Port_Binding "provnet1-7-101-port1"
778 Port_Binding "provnet1-4-port1"
779 Chassis "56b18105-5706-46ef-80c4-ff20979ab068"
780 hostname: sandbox
781 Encap geneve
782 ip: "127.0.0.1"
783 Port_Binding "provnet1-2-port1"
784 Port_Binding "provnet1-5-101-port1"
785 Port_Binding "provnet1-1-port1"
786 Port_Binding "provnet1-6-101-port1"
9107431f
RB
787
788All of the traces from the previous example, `env4`, should work in this
789environment and provide the same result. Now we can show what happens for the
790ports connected to VLAN 101. This first example shows a packet originating from
2b2f2b2f 791`provnet1-5-101-port1`, which is OpenFlow port 6. We should see VLAN tag 101
792pushed on the packet and then output to OpenFlow port 7, the patch port to
793`br-eth1` (the bridge providing connectivity to `physnet1`), and finally arrives
794on OpenFlow port 8.
9107431f
RB
795
796[View ovn/env5/packet1.sh][env5packet1].
797
798 $ ovn/env5/packet1.sh
799
800If we look at a broadcast packet arriving on VLAN 101 of `physnet1`, we should
2b2f2b2f 801see it output to OpenFlow ports 6 and 8 only.
9107431f
RB
802
803[View ovn/env5/packet2.sh][env5packet2].
804
805 $ ovn/env5/packet2.sh
806
807
0df6430e
RB
8086) Stateful ACLs
809----------------
810
811ACLs provide a way to do distributed packet filtering for OVN networks. One
812example use of ACLs is that OpenStack Neutron uses them to implement security
813groups. ACLs are implemented using conntrack integration with OVS.
814
815Start with a simple logical switch with 2 logical ports.
816
817[View ovn/env6/setup.sh][env6setup].
818
819 $ ovn/env6/setup.sh
820
821A common use case would be the following policy applied for `sw0-port1`:
822
823* Allow outbound IP traffic and associated return traffic.
824* Allow incoming ICMP requests and associated return traffic.
825* Allow incoming SSH connections and associated return traffic.
826* Drop other incoming IP traffic.
827
828The following script applies this policy to our environment.
829
830[View ovn/env6/add-acls.sh][env6acls].
831
832 $ ovn/env6/add-acls.sh
833
834We can view the configured ACLs on this network using the `ovn-nbctl` command.
835
836 $ ovn-nbctl acl-list sw0
837 from-lport 1002 (inport == “sw0-port1” && ip) allow-related
838 to-lport 1002 (outport == “sw0-port1” && ip && icmp) allow-related
839 to-lport 1002 (outport == “sw0-port1” && ip && tcp && tcp.dst == 22) allow-related
840 to-lport 1001 (outport == “sw0-port1” && ip) drop
841
842Now that we have ACLs configured, there are new entries in the logical flow
843table in the stages `switch_in_pre_acl`, switch_in_acl`, `switch_out_pre_acl`,
844and `switch_out_acl`.
845
846 $ ovn-sbctl lflow-list
847
848Let’s look more closely at `switch_out_pre_acl` and `switch_out_acl`.
849
850In `switch_out_pre_acl`, we match IP traffic and put it through the connection
851tracker. This populates the connection state fields so that we can apply policy
852as appropriate.
853
854 table=0(switch_out_pre_acl), priority= 100, match=(ip), action=(ct_next;)
f18d4462 855 table=1(switch_out_pre_acl), priority= 0, match=(1), action=(next;)
0df6430e
RB
856
857In `switch_out_acl`, we allow packets associated with existing connections. We
858drop packets that are deemed to be invalid (such as non-SYN TCP packet not
859associated with an existing connection).
860
861 table=1(switch_out_acl), priority=65535, match=(!ct.est && ct.rel && !ct.new && !ct.inv), action=(next;)
862 table=1(switch_out_acl), priority=65535, match=(ct.est && !ct.rel && !ct.new && !ct.inv), action=(next;)
863 table=1(switch_out_acl), priority=65535, match=(ct.inv), action=(drop;)
864
865For new connections, we apply our configured ACL policy to decide whether to
866allow the connection or not. In this case, we’ll allow ICMP or SSH. Otherwise,
867we’ll drop the packet.
868
869 table=1(switch_out_acl), priority= 2002, match=(ct.new && (outport == “sw0-port1” && ip && icmp)), action=(ct_commit; next;)
870 table=1(switch_out_acl), priority= 2002, match=(ct.new && (outport == “sw0-port1” && ip && tcp && tcp.dst == 22)), action=(ct_commit; next;)
871 table=1(switch_out_acl), priority= 2001, match=(outport == “sw0-port1” && ip), action=(drop;)
872
873When using ACLs, the default policy is to allow and track IP connections. Based
874on our above policy, IP traffic directed at `sw0-port1` will never hit this flow
875at priority 1.
876
877 table=1(switch_out_acl), priority= 1, match=(ip), action=(ct_commit; next;)
878 table=1(switch_out_acl), priority= 0, match=(1), action=(next;)
879
880Note that conntrack integration is not yet supported in ovs-sandbox, so the
881OpenFlow flows will not represent what you’d see in a real environment. The
882logical flows described above give a very good idea of what the flows look like,
883though.
884
885[This blog post][openstack-ovn-acl-blog] discusses OVN ACLs from an OpenStack
886perspective and also provides an example of what the resulting OpenFlow flows
887look like.
888
a97eef91
NS
8897) Container Ports
890------------------
891
892OVN supports containers running directly on the hypervisors and running
893containers inside VMs. This example shows how OVN supports network
894virtualization to containers when run inside VMs. Details about how to use
895docker containers in OVS can be found [here][openvswitch-docker].
896
897To support container traffic created inside a VM and to distinguish network
898traffic coming from different container vifs, for each container a logical
899port needs to be created with parent name set to the VM's logical port and
900the tag set to the vlan tag of the container vif.
901
902Start with a simple logical switch with 3 logical ports.
903
904[View ovn/env7/setup.sh][env7setup].
905
906 $ ovn/env7/setup.sh
907
908Lets create a container vif attached to the logical port 'sw0-port1' and
909another container vif attached to the logical port 'sw0-port2'.
910
911[View ovn/env7/add-container-ports.sh][env7contports]
912
913 $ ovn/env7/add-container-ports.sh
914
915Run the `ovn-nbctl` command to see the logical ports
916
917 $ovn-nbctl show
918
919
920As you can see a logical port 'csw0-cport1' is created on a logical
921switch 'csw0' whose parent is 'sw0-port1' and it has tag set to 42.
922And a logical port 'csw0-cport2' is created on the logical switch 'csw0'
923whose parent is 'sw0-port2' and it has tag set to 43.
924
925Bridge 'br-vmport1' represents the ovs bridge running inside the VM
926connected to the logical port 'sw0-port1'. In this tutorial the ovs port
927to 'sw0-port1' is created as a patch port with its peer connected to the
928ovs bridge 'br-vmport1'. An ovs port 'cport1' is added to 'br-vmport1'
929which represents the container interface connected to the ovs bridge
930and vlan tag set to 42. Similarly 'br-vmport2' represents the ovs bridge
931for the logical port 'sw0-port2' and 'cport2' connected to 'br-vmport2'
932with vlan tag set to 43.
933
934This first trace shows a packet from 'csw0-port1' with a destination mac
935address of 'csw0-port2'. You can see ovs bridge of the vm 'br-vmport1' tags
936the traffic with vlan id 42 and the traffic reaches to the br-int because
937of the patch port. As you can see below `ovn-controller` has added a flow
938to strip the vlan tag and set the reg6 and metadata appropriately.
939
940 $ ovs-ofctl -O OpenFlow13 dump-flows br-int
941 OFPST_FLOW reply (OF1.3) (xid=0x2):
942 cookie=0x0, duration=2767.032s, table=0, n_packets=0, n_bytes=0, priority=150,in_port=3,dl_vlan=42 actions=pop_vlan,set_field:0x3->reg5,set_field:0x2->metadata,set_field:0x1->reg6,resubmit(,16)
943 cookie=0x0, duration=2767.002s, table=0, n_packets=0, n_bytes=0, priority=150,in_port=4,dl_vlan=43 actions=pop_vlan,set_field:0x4->reg5,set_field:0x2->metadata,set_field:0x2->reg6,resubmit(,16)
944 cookie=0x0, duration=2767.032s, table=0, n_packets=0, n_bytes=0, priority=100,in_port=3 actions=set_field:0x1->reg5,set_field:0x1->metadata,set_field:0x1->reg6,resubmit(,16)
945 cookie=0x0, duration=2767.001s, table=0, n_packets=0, n_bytes=0, priority=100,in_port=4 actions=set_field:0x2->reg5,set_field:0x1->metadata,set_field:0x2->reg6,resubmit(,16)
946
947[View ovn/env7/packet1.sh][env7packet1].
948
949 $ ovn/env5/packet1.sh
950
951
952The second trace shows a packet from 'csw0-port2' to 'csw0-port1'.
953
954[View ovn/env7/packet2.sh][env7packet2].
955
956 $ ovn/env5/packet1.sh
957
958You can extend this setup by adding additional container ports with two
959hypervisors. Please see the tutorial 3 above.
960
2b2f2b2f 9618) L2Gateway Ports
962------------------
963
964L2Gateway provides a way to connect logical switch ports of type `l2gateway` to
965a physical network. The difference between `l2gateway` ports and `localnet` ports
966is that an `l2gateway` port is bound to a specific chassis. A single chassis
967serves as the L2 gateway to the physical network and all traffic between
968chassis continues to go over geneve tunnels.
969
970Start with a simple logical switch with 3 logical ports.
971
972[View ovn/env8/setup.sh][env8setup].
973
974 $ ovn/env8/setup.sh
975
976This first example shows a packet originating from `lport1`, which is OpenFlow port 1.
977We expect all packets from `lport1` to be sent out to br-eth1 (`patch-br-int-to-sw0-port3`,
978OpenFlow port 3). The patch port to br-eth1 provides connectivity to the physical network.
979
980[View ovn/env8/packet1.sh][env8packet1].
981
982 $ ovn/env8/packet1.sh
983
984The last trace shows what happens when a broadcast packet arrives from the network.
985In this case, it simulates a broadcast that originated from a port on the physical network
986and arrived at the local chassis via br-eth1. We should see it output to the local port `lport1`
987and `lport2`.
988
989[View ovn/env8/packet2.sh][env8packet2].
990
991 $ ovn/env8/packet2.sh
992
848cb198 993[ovn-architecture(7)]:http://openvswitch.org/support/dist-docs/ovn-architecture.7.html
2552e0e0 994[Tutorial.md]:https://github.com/openvswitch/ovs/blob/master/tutorial/Tutorial.md
848cb198
RB
995[ovn-nb(5)]:http://openvswitch.org/support/dist-docs/ovn-nb.5.html
996[ovn-sb(5)]:http://openvswitch.org/support/dist-docs/ovn-sb.5.html
997[vtep(5)]:http://openvswitch.org/support/dist-docs/vtep.5.html
f987d2af 998[ovn-northd(8)]:http://openvswitch.org/support/dist-docs/ovn-northd.8.html
848cb198
RB
999[ovn-controller(8)]:http://openvswitch.org/support/dist-docs/ovn-controller.8.html
1000[ovn-controller-vtep(8)]:http://openvswitch.org/support/dist-docs/ovn-controller-vtep.8.html
1001[vtep-ctl(8)]:http://openvswitch.org/support/dist-docs/vtep-ctl.8.html
1002[ovn-nbctl(8)]:http://openvswitch.org/support/dist-docs/ovn-nbctl.8.html
1003[ovn-sbctl(8)]:http://openvswitch.org/support/dist-docs/ovn-sbctl.8.html
2552e0e0
RB
1004[env1setup]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env1/setup.sh
1005[env1packet1]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env1/packet1.sh
1006[env1packet2]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env1/packet2.sh
1007[env1thirdport]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env1/add-third-port.sh
dd52c85c 1008[env1unknownports]:https://github.com/nickcooper-zhangtonghao/ovs/blob/master/tutorial/ovn/env1/add-unknown-ports.sh
1009[env1securityport]:https://github.com/nickcooper-zhangtonghao/ovs/blob/master/tutorial/ovn/env1/add-security-ip-ports.sh
1010[env1packet3]:https://github.com/nickcooper-zhangtonghao/ovs/blob/master/tutorial/ovn/env1/packet3.sh
1011[env1packet4]:https://github.com/nickcooper-zhangtonghao/ovs/blob/master/tutorial/ovn/env1/packet4.sh
2552e0e0
RB
1012[env2setup]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env2/setup.sh
1013[env2packet1]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env2/packet1.sh
1014[env2packet2]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env2/packet2.sh
1015[env3setup]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env3/setup.sh
1016[env3packet1]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env3/packet1.sh
1017[env3packet2]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env3/packet2.sh
2b2f2b2f 1018[env4setup]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env4/setup.sh
2552e0e0
RB
1019[env4packet1]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env4/packet1.sh
1020[env4packet2]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env4/packet2.sh
1021[env4packet3]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env4/packet3.sh
1022[env4packet4]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env4/packet4.sh
2552e0e0
RB
1023[env5setup]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env5/setup.sh
1024[env5packet1]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env5/packet1.sh
1025[env5packet2]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env5/packet2.sh
1026[env6setup]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env6/setup.sh
1027[env6acls]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env6/add-acls.sh
a97eef91
NS
1028[env7setup]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env7/setup.sh
1029[env7contports]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env7/add-container-ports.sh
1030[env7packet1]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env7/packet1.sh
1031[env7packet2]:https://github.com/openvswitch/ovs/blob/master/tutorial/ovn/env7/packet2.sh
2b2f2b2f 1032[env8setup]:https://github.com/nickcooper-zhangtonghao/ovs/blob/master/tutorial/ovn/env8/setup.sh
1033[env8packet1]:https://github.com/nickcooper-zhangtonghao/ovs/blob/master/tutorial/ovn/env8/packet1.sh
1034[env8packet2]:https://github.com/nickcooper-zhangtonghao/ovs/blob/master/tutorial/ovn/env8/packet2.sh
0df6430e 1035[openstack-ovn-acl-blog]:http://blog.russellbryant.net/2015/10/22/openstack-security-groups-using-ovn-acls/
a97eef91 1036[openvswitch-docker]:http://openvswitch.org/support/dist-docs/INSTALL.Docker.md.txt