1 Open vSwitch Advanced Features Tutorial
2 =======================================
4 Many tutorials cover the basics of OpenFlow. This is not such a
5 tutorial. Rather, a knowledge of the basics of OpenFlow is a
6 prerequisite. If you do not already understand how an OpenFlow flow
7 table works, please go read a basic tutorial and then continue reading
10 It is also important to understand the basics of Open vSwitch before
11 you begin. If you have never used `ovs-vsctl` or `ovs-ofctl` before,
12 you should learn a little about them before proceeding.
14 Most of the features covered in this tutorial are Open vSwitch
15 extensions to OpenFlow. Also, most of the features in this tutorial
16 are specific to the software Open vSwitch implementation. If you are
17 using an Open vSwitch port to an ASIC-based hardware switch, this
18 tutorial will not help you.
20 This tutorial does not cover every aspect of the features that it
21 mentions. You can find the details elsewhere in the Open vSwitch
22 documentation, especially `ovs-ofctl(8)` and the comments in the
23 `include/openflow/nicira-ext.h` header file.
25 > In this tutorial, paragraphs set off like this designate notes
26 > with additional information that readers may wish to skip on a
32 This is a hands-on tutorial. To get the most out of it, you will need
33 Open vSwitch binaries. You do not, on the other hand, need any
34 physical networking hardware or even supervisor privilege on your
35 system. Instead, we will use a script called `ovs-sandbox`, which
36 accompanies the tutorial, that constructs a software simulated network
37 environment based on Open vSwitch.
39 You can use `ovs-sandbox` three ways:
41 * If you have already installed Open vSwitch on your system, then
42 you should be able to just run `ovs-sandbox` from this directory
45 * If you have not installed Open vSwitch (and you do not want to
46 install it), then you can build Open vSwitch according to the
47 instructions in [INSTALL.md], without installing it. Then run
48 `./ovs-sandbox -b DIRECTORY` from this directory, substituting
49 the Open vSwitch build directory for `DIRECTORY`.
51 * As a slight variant on the latter, you can run `make sandbox`
52 from an Open vSwitch build directory.
54 When you run `ovs-sandbox`, it does the following:
56 1. **CAUTION:** Deletes any subdirectory of the current directory
57 named "sandbox" and any files in that directory.
59 2. Creates a new directory "sandbox" in the current directory.
61 3. Sets up special environment variables that ensure that Open
62 vSwitch programs will look inside the "sandbox" directory
63 instead of in the Open vSwitch installation directory.
65 4. If you are using a built but not installed Open vSwitch,
66 installs the Open vSwitch manpages in a subdirectory of
67 "sandbox" and adjusts the `MANPATH` environment variable to point
68 to this directory. This means that you can use, for example,
69 `man ovs-vsctl` to see a manpage for the `ovs-vsctl` program that
72 5. Creates an empty Open vSwitch configuration database under
75 6. Starts `ovsdb-server` running under "sandbox".
77 7. Starts `ovs-vswitchd` running under "sandbox", passing special
78 options that enable a special "dummy" mode for testing.
80 8. Starts a nested interactive shell inside "sandbox".
82 At this point, you can run all the usual Open vSwitch utilities from
83 the nested shell environment. You can, for example, use `ovs-vsctl`
88 From Open vSwitch's perspective, the bridge that you create this way
89 is as real as any other. You can, for example, connect it to an
90 OpenFlow controller or use `ovs-ofctl` to examine and modify it and
91 its OpenFlow flow table. On the other hand, the bridge is not visible
92 to the operating system's network stack, so `ifconfig` or `ip` cannot
93 see it or affect it, which means that utilities like `ping` and
94 `tcpdump` will not work either. (That has its good side, too: you
95 can't screw up your computer's network stack by manipulating a
98 When you're done using OVS from the sandbox, exit the nested shell (by
99 entering the "exit" shell command or pressing Control+D). This will
100 kill the daemons that `ovs-sandbox` started, but it leaves the "sandbox"
101 directory and its contents in place.
103 The sandbox directory contains log files for the Open vSwitch dameons.
104 You can examine them while you're running in the sandboxed environment
110 GDB support is not required to go through the tutorial. It is added in case
111 user wants to explore the internals of OVS programs.
113 GDB can already be used to debug any running process, with the usual
114 'gdb <program> <process-id>' command.
116 'ovs-sandbox' also has a '-g' option for launching ovs-vswitchd under GDB.
117 This option can be handy for setting break points before ovs-vswitchd runs,
118 or for catching early segfaults. Similarly, a '-d' option can be used to
119 run ovsdb-server under GDB. Both options can be specified at the same time.
121 In addition, a '-e' option also launches ovs-vswitchd under GDB. However,
122 instead of displaying a 'gdb>' prompt and waiting for user input, ovs-vswitchd
123 will start to execute immediately. '-r' option is the corresponding option
124 for running ovsdb-server under gdb with immediate execution.
126 To avoid GDB mangling with the sandbox sub shell terminal, 'ovs-sandbox'
127 starts a new xterm to run each GDB session. For systems that do not support
128 X windows, GDB support is effectively disabled.
130 When launching sandbox through the build tree's make file, the '-g' option
131 can be passed via the 'SANDBOXFLAGS' environment variable.
132 'make sandbox SANDBOXFLAGS=-g' will start the sandbox with ovs-vswitchd
133 running under GDB in its own xterm if X is available.
138 The goal of this tutorial is to demonstrate the power of Open vSwitch
139 flow tables. The tutorial works through the implementation of a
140 MAC-learning switch with VLAN trunk and access ports. Outside of the
141 Open vSwitch features that we will discuss, OpenFlow provides at least
142 two ways to implement such a switch:
144 1. An OpenFlow controller to implement MAC learning in a
145 "reactive" fashion. Whenever a new MAC appears on the switch,
146 or a MAC moves from one switch port to another, the controller
147 adjusts the OpenFlow flow table to match.
149 2. The "normal" action. OpenFlow defines this action to submit a
150 packet to "the traditional non-OpenFlow pipeline of the
151 switch". That is, if a flow uses this action, then the packets
152 in the flow go through the switch in the same way that they
153 would if OpenFlow was not configured on the switch.
155 Each of these approaches has unfortunate pitfalls. In the first
156 approach, using an OpenFlow controller to implement MAC learning, has
157 a significant cost in terms of network bandwidth and latency. It also
158 makes the controller more difficult to scale to large numbers of
159 switches, which is especially important in environments with thousands
160 of hypervisors (each of which contains a virtual OpenFlow switch).
161 MAC learning at an OpenFlow controller also behaves poorly if the
162 OpenFlow controller fails, slows down, or becomes unavailable due to
165 The second approach, using the "normal" action, has different
166 problems. First, little about the "normal" action is standardized, so
167 it behaves differently on switches from different vendors, and the
168 available features and how those features are configured (usually not
169 through OpenFlow) varies widely. Second, "normal" does not work well
170 with other OpenFlow actions. It is "all-or-nothing", with little
171 potential to adjust its behavior slightly or to compose it with other
178 We will construct Open vSwitch flow tables for a VLAN-capable,
179 MAC-learning switch that has four ports:
181 * p1, a trunk port that carries all VLANs, on OpenFlow port 1.
183 * p2, an access port for VLAN 20, on OpenFlow port 2.
185 * p3 and p4, both access ports for VLAN 30, on OpenFlow ports 3
188 > The ports' names are not significant. You could call them eth1
189 > through eth4, or any other names you like.
191 > An OpenFlow switch always has a "local" port as well. This
192 > scenario won't use the local port.
194 Our switch design will consist of five main flow tables, each of which
195 implements one stage in the switch pipeline:
197 Table 0: Admission control.
199 Table 1: VLAN input processing.
201 Table 2: Learn source MAC and VLAN for ingress port.
203 Table 3: Look up learned port for destination MAC and VLAN.
205 Table 4: Output processing.
207 The section below describes how to set up the scenario, followed by a
208 section for each OpenFlow table.
210 You can cut and paste the `ovs-vsctl` and `ovs-ofctl` commands in each
211 of the sections below into your `ovs-sandbox` shell. They are also
212 available as shell scripts in this directory, named `t-setup`, `t-stage0`,
213 `t-stage1`, ..., `t-stage4`. The `ovs-appctl` test commands are intended
214 for cutting and pasting and are not supplied separately.
220 To get started, start `ovs-sandbox`. Inside the interactive shell
221 that it starts, run this command:
223 ovs-vsctl add-br br0 -- set Bridge br0 fail-mode=secure
225 This command creates a new bridge "br0" and puts "br0" into so-called
226 "fail-secure" mode. For our purpose, this just means that the
227 OpenFlow flow table starts out empty.
229 > If we did not do this, then the flow table would start out with a
230 > single flow that executes the "normal" action. We could use that
231 > feature to yield a switch that behaves the same as the switch we
232 > are currently building, but with the caveats described under
233 > "Motivation" above.)
235 The new bridge has only one port on it so far, the "local port" br0.
236 We need to add p1, p2, p3, and p4. A shell "for" loop is one way to
240 ovs-vsctl add-port br0 p$i -- set Interface p$i ofport_request=$i
241 ovs-ofctl mod-port br0 p$i up
244 In addition to adding a port, the `ovs-vsctl` command above sets its
245 "ofport_request" column to ensure that port p1 is assigned OpenFlow
246 port 1, p2 is assigned OpenFlow port 2, and so on.
248 > We could omit setting the ofport_request and let Open vSwitch
249 > choose port numbers for us, but it's convenient for the purposes
250 > of this tutorial because we can talk about OpenFlow port 1 and
251 > know that it corresponds to p1.
253 The `ovs-ofctl` command above brings up the simulated interfaces, which
254 are down initially, using an OpenFlow request. The effect is similar
255 to `ifconfig up`, but the sandbox's interfaces are not visible to the
256 operating system and therefore `ifconfig` would not affect them.
258 We have not configured anything related to VLANs or MAC learning.
259 That's because we're going to implement those features in the flow
262 To see what we've done so far to set up the scenario, you can run a
263 command like `ovs-vsctl show` or `ovs-ofctl show br0`.
266 Implementing Table 0: Admission control
267 ---------------------------------------
269 Table 0 is where packets enter the switch. We use this stage to
270 discard packets that for one reason or another are invalid. For
271 example, packets with a multicast source address are not valid, so we
272 can add a flow to drop them at ingress to the switch with:
274 ovs-ofctl add-flow br0 \
275 "table=0, dl_src=01:00:00:00:00:00/01:00:00:00:00:00, actions=drop"
277 A switch should also not forward IEEE 802.1D Spanning Tree Protocol
278 (STP) packets, so we can also add a flow to drop those and other
279 packets with reserved multicast protocols:
281 ovs-ofctl add-flow br0 \
282 "table=0, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0, actions=drop"
284 We could add flows to drop other protocols, but these demonstrate the
287 We need one more flow, with a priority lower than the default, so that
288 flows that don't match either of the "drop" flows we added above go on
289 to pipeline stage 1 in OpenFlow table 1:
291 ovs-ofctl add-flow br0 "table=0, priority=0, actions=resubmit(,1)"
293 (The "resubmit" action is an Open vSwitch extension to OpenFlow.)
298 If we were using Open vSwitch to set up a physical or a virtual
299 switch, then we would naturally test it by sending packets through it
300 one way or another, perhaps with common network testing tools like
301 `ping` and `tcpdump` or more specialized tools like Scapy. That's
302 difficult with our simulated switch, since it's not visible to the
305 But our simulated switch has a few specialized testing tools. The
306 most powerful of these tools is `ofproto/trace`. Given a switch and
307 the specification of a flow, `ofproto/trace` shows, step-by-step, how
308 such a flow would be treated as it goes through the switch.
315 ovs-appctl ofproto/trace br0 in_port=1,dl_dst=01:80:c2:00:00:05
317 The output should look something like this:
319 Flow: metadata=0,in_port=1,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=01:80:c2:00:00:05,dl_type=0x0000
320 Rule: table=0 cookie=0 dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0
321 OpenFlow actions=drop
323 Final flow: unchanged
324 Datapath actions: drop
326 The first block of lines describes an OpenFlow table lookup. The
327 first line shows the fields used for the table lookup (which is mostly
328 zeros because that's the default if we don't specify everything). The
329 second line gives the OpenFlow flow that the fields matched (called a
330 "rule" because that is the name used inside Open vSwitch for an
331 OpenFlow flow). In this case, we see that this packet that has a
332 reserved multicast destination address matches the rule that drops
333 those packets. The third line gives the rule's OpenFlow actions.
335 The second block of lines summarizes the results, which are not very
343 ovs-appctl ofproto/trace br0 in_port=1,dl_dst=01:80:c2:00:00:10
345 The output should be:
347 Flow: metadata=0,in_port=1,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=01:80:c2:00:00:10,dl_type=0x0000
348 Rule: table=0 cookie=0 priority=0
349 OpenFlow actions=resubmit(,1)
351 Resubmitted flow: unchanged
352 Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
353 Resubmitted odp: drop
356 Final flow: unchanged
357 Datapath actions: drop
359 This time the flow we handed to `ofproto/trace` doesn't match any of
360 our "drop" rules, so it falls through to the low-priority "resubmit"
361 rule, which we see in the rule and the actions selected in the first
362 block. The "resubmit" causes a second lookup in OpenFlow table 1,
363 described by the additional block of indented text in the output. We
364 haven't yet added any flows to OpenFlow table 1, so no flow actually
365 matches in the second lookup. Therefore, the packet is still actually
366 dropped, which means that the externally observable results would be
367 identical to our first example.
370 Implementing Table 1: VLAN Input Processing
371 -------------------------------------------
373 A packet that enters table 1 has already passed basic validation in
374 table 0. The purpose of table 1 is validate the packet's VLAN, based
375 on the VLAN configuration of the switch port through which the packet
376 entered the switch. We will also use it to attach a VLAN header to
377 packets that arrive on an access port, which allows later processing
378 stages to rely on the packet's VLAN always being part of the VLAN
379 header, reducing special cases.
381 Let's start by adding a low-priority flow that drops all packets,
382 before we add flows that pass through acceptable packets. You can
383 think of this as a "default drop" rule:
385 ovs-ofctl add-flow br0 "table=1, priority=0, actions=drop"
387 Our trunk port p1, on OpenFlow port 1, is an easy case. p1 accepts
388 any packet regardless of whether it has a VLAN header or what the VLAN
389 was, so we can add a flow that resubmits everything on input port 1 to
392 ovs-ofctl add-flow br0 \
393 "table=1, priority=99, in_port=1, actions=resubmit(,2)"
395 On the access ports, we want to accept any packet that has no VLAN
396 header, tag it with the access port's VLAN number, and then pass it
397 along to the next stage:
399 ovs-ofctl add-flows br0 - <<'EOF'
400 table=1, priority=99, in_port=2, vlan_tci=0, actions=mod_vlan_vid:20, resubmit(,2)
401 table=1, priority=99, in_port=3, vlan_tci=0, actions=mod_vlan_vid:30, resubmit(,2)
402 table=1, priority=99, in_port=4, vlan_tci=0, actions=mod_vlan_vid:30, resubmit(,2)
405 We don't write any rules that match packets with 802.1Q that enter
406 this stage on any of the access ports, so the "default drop" rule we
407 added earlier causes them to be dropped, which is ordinarily what we
408 want for access ports.
410 > Another variation of access ports allows ingress of packets tagged
411 > with VLAN 0 (aka 802.1p priority tagged packets). To allow such
412 > packets, replace "vlan_tci=0" by "vlan_tci=0/0xfff" above.
417 `ofproto/trace` allows us to test the ingress VLAN rules that we added
421 ### EXAMPLE 1: Packet on Trunk Port
423 Here's a test of a packet coming in on the trunk port:
425 ovs-appctl ofproto/trace br0 in_port=1,vlan_tci=5
427 The output shows the lookup in table 0, the resubmit to table 1, and
428 the resubmit to table 2 (which does nothing because we haven't put
431 Flow: metadata=0,in_port=1,vlan_tci=0x0005,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000
432 Rule: table=0 cookie=0 priority=0
433 OpenFlow actions=resubmit(,1)
435 Resubmitted flow: unchanged
436 Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
437 Resubmitted odp: drop
438 Rule: table=1 cookie=0 priority=99,in_port=1
439 OpenFlow actions=resubmit(,2)
441 Resubmitted flow: unchanged
442 Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
443 Resubmitted odp: drop
446 Final flow: unchanged
447 Datapath actions: drop
450 ### EXAMPLE 2: Valid Packet on Access Port
452 Here's a test of a valid packet (a packet without an 802.1Q header)
453 coming in on access port p2:
455 ovs-appctl ofproto/trace br0 in_port=2
457 The output is similar to that for the previous case, except that it
458 additionally tags the packet with p2's VLAN 20 before it passes it
461 Flow: metadata=0,in_port=2,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000
462 Rule: table=0 cookie=0 priority=0
463 OpenFlow actions=resubmit(,1)
465 Resubmitted flow: unchanged
466 Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
467 Resubmitted odp: drop
468 Rule: table=1 cookie=0 priority=99,in_port=2,vlan_tci=0x0000
469 OpenFlow actions=mod_vlan_vid:20,resubmit(,2)
471 Resubmitted flow: metadata=0,in_port=2,dl_vlan=20,dl_vlan_pcp=0,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000
472 Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
473 Resubmitted odp: drop
476 Final flow: unchanged
477 Datapath actions: drop
480 ### EXAMPLE 3: Invalid Packet on Access Port
482 This tests an invalid packet (one that includes an 802.1Q header)
483 coming in on access port p2:
485 ovs-appctl ofproto/trace br0 in_port=2,vlan_tci=5
487 The output shows the packet matching the default drop rule:
489 Flow: metadata=0,in_port=2,vlan_tci=0x0005,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000
490 Rule: table=0 cookie=0 priority=0
491 OpenFlow actions=resubmit(,1)
493 Resubmitted flow: unchanged
494 Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
495 Resubmitted odp: drop
496 Rule: table=1 cookie=0 priority=0
497 OpenFlow actions=drop
499 Final flow: unchanged
500 Datapath actions: drop
503 Implementing Table 2: MAC+VLAN Learning for Ingress Port
504 --------------------------------------------------------
506 This table allows the switch we're implementing to learn that the
507 packet's source MAC is located on the packet's ingress port in the
510 > This table is a good example why table 1 added a VLAN tag to
511 > packets that entered the switch through an access port. We want
512 > to associate a MAC+VLAN with a port regardless of whether the VLAN
513 > in question was originally part of the packet or whether it was an
514 > assumed VLAN associated with an access port.
516 It only takes a single flow to do this. The following command adds
519 ovs-ofctl add-flow br0 \
520 "table=2 actions=learn(table=10, NXM_OF_VLAN_TCI[0..11], \
521 NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], \
522 load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]), \
525 The "learn" action (an Open vSwitch extension to OpenFlow) modifies a
526 flow table based on the content of the flow currently being processed.
527 Here's how you can interpret each part of the "learn" action above:
531 Modify flow table 10. This will be the MAC learning table.
533 NXM_OF_VLAN_TCI[0..11]
535 Make the flow that we add to flow table 10 match the same VLAN
536 ID that the packet we're currently processing contains. This
537 effectively scopes the MAC learning entry to a single VLAN,
538 which is the ordinary behavior for a VLAN-aware switch.
540 NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[]
542 Make the flow that we add to flow table 10 match, as Ethernet
543 destination, the Ethernet source address of the packet we're
544 currently processing.
546 load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]
548 Whereas the preceding parts specify fields for the new flow to
549 match, this specifies an action for the flow to take when it
550 matches. The action is for the flow to load the ingress port
551 number of the current packet into register 0 (a special field
552 that is an Open vSwitch extension to OpenFlow).
554 > A real use of "learn" for MAC learning would probably involve two
555 > additional elements. First, the "learn" action would specify a
556 > hard_timeout for the new flow, to enable a learned MAC to
557 > eventually expire if no new packets were seen from a given source
558 > within a reasonable interval. Second, one would usually want to
559 > limit resource consumption by using the Flow_Table table in the
560 > Open vSwitch configuration database to specify a maximum number of
563 This definitely calls for examples.
570 Try the following test command:
572 ovs-appctl ofproto/trace br0 in_port=1,vlan_tci=20,dl_src=50:00:00:00:00:01 -generate
574 The output shows that "learn" was executed, but it isn't otherwise
575 informative, so we won't include it here.
577 The `-generate` keyword is new. Ordinarily, `ofproto/trace` has no
578 side effects: "output" actions do not actually output packets, "learn"
579 actions do not actually modify the flow table, and so on. With
580 `-generate`, though, `ofproto/trace` does execute "learn" actions.
581 That's important now, because we want to see the effect of the "learn"
582 action on table 10. You can see that by running:
584 ovs-ofctl dump-flows br0 table=10
586 which (omitting the "duration" and "idle_age" fields, which will vary
587 based on how soon you ran this command after the previous one, as well
588 as some other uninteresting fields) prints something like:
590 NXST_FLOW reply (xid=0x4):
591 table=10, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
593 You can see that the packet coming in on VLAN 20 with source MAC
594 50:00:00:00:00:01 became a flow that matches VLAN 20 (written in
595 hexadecimal) and destination MAC 50:00:00:00:00:01. The flow loads
596 port number 1, the input port for the flow we tested, into register 0.
601 Here's a second test command:
603 ovs-appctl ofproto/trace br0 in_port=2,dl_src=50:00:00:00:00:01 -generate
605 The flow that this command tests has the same source MAC and VLAN as
606 example 1, although the VLAN comes from an access port VLAN rather
607 than an 802.1Q header. If we again dump the flows for table 10 with:
609 ovs-ofctl dump-flows br0 table=10
611 then we see that the flow we saw previously has changed to indicate
612 that the learned port is port 2, as we would expect:
614 NXST_FLOW reply (xid=0x4):
615 table=10, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:01 actions=load:0x2->NXM_NX_REG0[0..15]
618 Implementing Table 3: Look Up Destination Port
619 ----------------------------------------------
621 This table figures out what port we should send the packet to based on
622 the destination MAC and VLAN. That is, if we've learned the location
623 of the destination (from table 2 processing some previous packet with
624 that destination as its source), then we want to send the packet
627 We need only one flow to do the lookup:
629 ovs-ofctl add-flow br0 \
630 "table=3 priority=50 actions=resubmit(,10), resubmit(,4)"
632 The flow's first action resubmits to table 10, the table that the
633 "learn" action modifies. As you saw previously, the learned flows in
634 this table write the learned port into register 0. If the destination
635 for our packet hasn't been learned, then there will be no matching
636 flow, and so the "resubmit" turns into a no-op. Because registers are
637 initialized to 0, we can use a register 0 value of 0 in our next
638 pipeline stage as a signal to flood the packet.
640 The second action resubmits to table 4, continuing to the next
643 We can add another flow to skip the learning table lookup for
644 multicast and broadcast packets, since those should always be flooded:
646 ovs-ofctl add-flow br0 \
647 "table=3 priority=99 dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 \
648 actions=resubmit(,4)"
650 > We don't strictly need to add this flow, because multicast
651 > addresses will never show up in our learning table. (In turn,
652 > that's because we put a flow into table 0 to drop packets that
653 > have a multicast source address.)
660 Here's a command that should cause OVS to learn that f0:00:00:00:00:01
663 ovs-appctl ofproto/trace br0 in_port=1,dl_vlan=20,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01 -generate
665 Here's an excerpt from the output that shows (from the "no match"
666 looking up the resubmit to table 10) that the flow's destination was
669 Resubmitted flow: unchanged
670 Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
671 Resubmitted odp: drop
672 Rule: table=3 cookie=0 priority=50
673 OpenFlow actions=resubmit(,10),resubmit(,4)
675 Resubmitted flow: unchanged
676 Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
677 Resubmitted odp: drop
680 You can verify that the packet's source was learned two ways. The
681 most direct way is to dump the learning table with:
683 ovs-ofctl dump-flows br0 table=10
685 which ought to show roughly the following, with extraneous details
688 table=10, vlan_tci=0x0014/0x0fff,dl_dst=f0:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
690 > If you tried the examples for the previous step, or if you did
691 > some of your own experiments, then you might see additional flows
692 > there. These additional flows are harmless. If they bother you,
693 > then you can remove them with `ovs-ofctl del-flows br0 table=10`.
695 The other way is to inject a packet to take advantage of the learning
696 entry. For example, we can inject a packet on p2 whose destination is
697 the MAC address that we just learned on p1:
699 ovs-appctl ofproto/trace br0 in_port=2,dl_src=90:00:00:00:00:01,dl_dst=f0:00:00:00:00:01 -generate
701 Here's an interesting excerpt from that command's output. This group
702 of lines traces the "resubmit(,10)", showing that the packet matched
703 the learned flow for the first MAC we used, loading the OpenFlow port
704 number for the learned port p1 into register 0:
706 Resubmitted flow: unchanged
707 Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
708 Resubmitted odp: drop
709 Rule: table=10 cookie=0 vlan_tci=0x0014/0x0fff,dl_dst=f0:00:00:00:00:01
710 OpenFlow actions=load:0x1->NXM_NX_REG0[0..15]
713 If you read the commands above carefully, then you might have noticed
714 that they simply have the Ethernet source and destination addresses
715 exchanged. That means that if we now rerun the first `ovs-appctl`
718 ovs-appctl ofproto/trace br0 in_port=1,dl_vlan=20,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01 -generate
720 then we see in the output that the destination has now been learned:
722 Resubmitted flow: unchanged
723 Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
724 Resubmitted odp: drop
725 Rule: table=10 cookie=0 vlan_tci=0x0014/0x0fff,dl_dst=90:00:00:00:00:01
726 OpenFlow actions=load:0x2->NXM_NX_REG0[0..15]
729 Implementing Table 4: Output Processing
730 ---------------------------------------
732 At entry to stage 4, we know that register 0 contains either the
733 desired output port or is zero if the packet should be flooded. We
734 also know that the packet's VLAN is in its 802.1Q header, even if the
735 VLAN was implicit because the packet came in on an access port.
737 The job of the final pipeline stage is to actually output packets.
738 The job is trivial for output to our trunk port p1:
740 ovs-ofctl add-flow br0 "table=4 reg0=1 actions=1"
742 For output to the access ports, we just have to strip the VLAN header
743 before outputting the packet:
745 ovs-ofctl add-flows br0 - <<'EOF'
746 table=4 reg0=2 actions=strip_vlan,2
747 table=4 reg0=3 actions=strip_vlan,3
748 table=4 reg0=4 actions=strip_vlan,4
751 The only slightly tricky part is flooding multicast and broadcast
752 packets and unicast packets with unlearned destinations. For those,
753 we need to make sure that we only output the packets to the ports that
754 carry our packet's VLAN, and that we include the 802.1Q header in the
755 copy output to the trunk port but not in copies output to access
758 ovs-ofctl add-flows br0 - <<'EOF'
759 table=4 reg0=0 priority=99 dl_vlan=20 actions=1,strip_vlan,2
760 table=4 reg0=0 priority=99 dl_vlan=30 actions=1,strip_vlan,3,4
761 table=4 reg0=0 priority=50 actions=1
764 > Our rules rely on the standard OpenFlow behavior that an output
765 > action will not forward a packet back out the port it came in on.
766 > That is, if a packet comes in on p1, and we've learned that the
767 > packet's destination MAC is also on p1, so that we end up with
768 > "actions=1" as our actions, the switch will not forward the packet
769 > back out its input port. The multicast/broadcast/unknown
770 > destination cases above also rely on this behavior.
775 ### EXAMPLE 1: Broadcast, Multicast, and Unknown Destination
777 Try tracing a broadcast packet arriving on p1 in VLAN 30:
779 ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=30
781 The interesting part of the output is the final line, which shows that
782 the switch would remove the 802.1Q header and then output the packet to
783 p3 and p4, which are access ports for VLAN 30:
785 Datapath actions: pop_vlan,3,4
787 Similarly, if we trace a broadcast packet arriving on p3:
789 ovs-appctl ofproto/trace br0 in_port=3,dl_dst=ff:ff:ff:ff:ff:ff
791 then we see that it is output to p1 with an 802.1Q tag and then to p4
794 Datapath actions: push_vlan(vid=30,pcp=0),1,pop_vlan,4
796 > Open vSwitch could simplify the datapath actions here to just
797 > "4,push_vlan(vid=30,pcp=0),1" but it is not smart enough to do so.
799 The following are also broadcasts, but the result is to drop the
800 packets because the VLAN only belongs to the input port:
802 ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff
803 ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=55
805 Try some other broadcast cases on your own:
807 ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=20
808 ovs-appctl ofproto/trace br0 in_port=2,dl_dst=ff:ff:ff:ff:ff:ff
809 ovs-appctl ofproto/trace br0 in_port=4,dl_dst=ff:ff:ff:ff:ff:ff
811 You can see the same behavior with multicast packets and with unicast
812 packets whose destination has not been learned, e.g.:
814 ovs-appctl ofproto/trace br0 in_port=4,dl_dst=01:00:00:00:00:00
815 ovs-appctl ofproto/trace br0 in_port=1,dl_dst=90:12:34:56:78:90,dl_vlan=20
816 ovs-appctl ofproto/trace br0 in_port=1,dl_dst=90:12:34:56:78:90,dl_vlan=30
819 ### EXAMPLE 2: MAC Learning
821 Let's follow the same pattern as we did for table 3. First learn a
822 MAC on port p1 in VLAN 30:
824 ovs-appctl ofproto/trace br0 in_port=1,dl_vlan=30,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01 -generate
826 You can see from the last line of output that the packet's destination
827 is unknown, so it gets flooded to both p3 and p4, the other ports in
830 Datapath actions: pop_vlan,3,4
832 Then reverse the MACs and learn the first flow's destination on port
835 ovs-appctl ofproto/trace br0 in_port=4,dl_src=20:00:00:00:00:01,dl_dst=10:00:00:00:00:01 -generate
837 The last line of output shows that the this packet's destination is
838 known to be p1, as learned from our previous command:
840 Datapath actions: push_vlan(vid=30,pcp=0),1
842 Now, if we rerun our first command:
844 ovs-appctl ofproto/trace br0 in_port=1,dl_vlan=30,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01 -generate
846 we can see that the result is no longer a flood but to the specified
847 learned destination port p4:
849 Datapath actions: pop_vlan,4
856 http://openvswitch.org/
858 [INSTALL.md]:../INSTALL.md