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