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