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, you
12
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
33
This is a hands-on tutorial. To get the most out of it, you will need
34
Open vSwitch binaries. You do not, on the other hand, need any
35
physical networking hardware or even supervisor privilege on your
36
system. Instead, we will use a script called "ovs-sandbox", which
37
accompanies the tutorial, that constructs a software simulated network
38
environment based on Open vSwitch.
40
You can use "ovs-sandbox" three ways:
42
* If you have already installed Open vSwitch on your system, then
43
you should be able to just run "ovs-sandbox" from this directory
46
* If you have not installed Open vSwitch (and you do not want to
47
install it), then you can build Open vSwitch according to the
48
instructions in INSTALL, without installing it. Then run
49
"./ovs-sandbox -b DIRECTORY" from this directory, substituting
50
the Open vSwitch build directory for DIRECTORY.
52
* As a slight variant on the latter, you can run "make sandbox"
53
from an Open vSwitch build directory.
55
When you run ovs-sandbox, it does the following:
57
1. CAUTION: Deletes any subdirectory of the current directory
58
named "sandbox" and any files in that directory.
60
2. Creates a new directory "sandbox" in the current directory.
62
3. Sets up special environment variables that ensure that Open
63
vSwitch programs will look inside the "sandbox" directory
64
instead of in the Open vSwitch installation directory.
66
4. If you are using a built but not installed Open vSwitch,
67
installs the Open vSwitch manpages in a subdirectory of
68
"sandbox" and adjusts the MANPATH environment variable to point
69
to this directory. This means that you can use, for example,
70
"man ovs-vsctl" to see a manpage for the ovs-vsctl program that
73
5. Creates an empty Open vSwitch configuration database under
76
6. Starts ovsdb-server running under "sandbox".
78
7. Starts ovs-vswitchd running under "sandbox", passing special
79
options that enable a special "dummy" mode for testing.
81
8. Starts a nested interactive shell inside "sandbox".
83
At this point, you can run all the usual Open vSwitch utilities from
84
the nested shell environment. You can, for example, use ovs-vsctl to
89
From Open vSwitch's perspective, the bridge that you create this way
90
is as real as any other. You can, for example, connect it to an
91
OpenFlow controller or use "ovs-ofctl" to examine and modify it and
92
its OpenFlow flow table. On the other hand, the bridge is not visible
93
to the operating system's network stack, so "ifconfig" or "ip" cannot
94
see it or affect it, which means that utilities like "ping" and
95
"tcpdump" will not work either. (That has its good side, too: you
96
can't screw up your computer's network stack by manipulating a
99
When you're done using OVS from the sandbox, exit the nested shell (by
100
entering the "exit" shell command or pressing Control+D). This will
101
kill the daemons that ovs-sandbox started, but it leaves the "sandbox"
102
directory and its contents in place.
104
The sandbox directory contains log files for the Open vSwitch dameons.
105
You can examine them while you're running in the sandboxed environment
112
The goal of this tutorial is to demonstrate the power of Open vSwitch
113
flow tables. The tutorial works through the implementation of a
114
MAC-learning switch with VLAN trunk and access ports. Outside of the
115
Open vSwitch features that we will discuss, OpenFlow provides at least
116
two ways to implement such a switch:
118
1. An OpenFlow controller to implement MAC learning in a
119
"reactive" fashion. Whenever a new MAC appears on the switch,
120
or a MAC moves from one switch port to another, the controller
121
adjusts the OpenFlow flow table to match.
123
2. The "normal" action. OpenFlow defines this action to submit a
124
packet to "the traditional non-OpenFlow pipeline of the
125
switch". That is, if a flow uses this action, then the packets
126
in the flow go through the switch in the same way that they
127
would if OpenFlow was not configured on the switch.
129
Each of these approaches has unfortunate pitfalls. In the first
130
approach, using an OpenFlow controller to implement MAC learning, has
131
a significant cost in terms of network bandwidth and latency. It also
132
makes the controller more difficult to scale to large numbers of
133
switches, which is especially important in environments with thousands
134
of hypervisors (each of which contains a virtual OpenFlow switch).
135
MAC learning at an OpenFlow controller also behaves poorly if the
136
OpenFlow controller fails, slows down, or becomes unavailable due to
139
The second approach, using the "normal" action, has different
140
problems. First, little about the "normal" action is standardized, so
141
it behaves differently on switches from different vendors, and the
142
available features and how those features are configured (usually not
143
through OpenFlow) varies widely. Second, "normal" does not work well
144
with other OpenFlow actions. It is "all-or-nothing", with little
145
potential to adjust its behavior slightly or to compose it with other
152
We will construct Open vSwitch flow tables for a VLAN-capable,
153
MAC-learning switch that has four ports:
155
* p1, a trunk port that carries all VLANs, on OpenFlow port 1.
157
* p2, an access port for VLAN 20, on OpenFlow port 2.
159
* p3 and p4, both access ports for VLAN 30, on OpenFlow ports 3
162
>>> The ports' names are not significant. You could call them eth1
163
through eth4, or any other names you like.
165
>>> An OpenFlow switch always has a "local" port as well. This
166
scenario won't use the local port.
168
Our switch design will consist of five main flow tables, each of which
169
implements one stage in the switch pipeline:
171
Table 0: Admission control.
173
Table 1: VLAN input processing.
175
Table 2: Learn source MAC and VLAN for ingress port.
177
Table 3: Look up learned port for destination MAC and VLAN.
179
Table 4: Output processing.
181
The section below describes how to set up the scenario, followed by a
182
section for each OpenFlow table.
184
You can cut and paste the "ovs-vsctl" and "ovs-ofctl" commands in each
185
of the sections below into your "ovs-sandbox" shell. They are also
186
available as shell scripts in this directory, named t-setup, t-stage0,
187
t-stage1, ..., t-stage4. The "ovs-appctl" test commands are intended
188
for cutting and pasting and are not supplied separately.
194
To get started, start "ovs-sandbox". Inside the interactive shell
195
that it starts, run this command:
197
ovs-vsctl add-br br0 -- set Bridge br0 fail-mode=secure
199
This command creates a new bridge "br0" and puts "br0" into so-called
200
"fail-secure" mode. For our purpose, this just means that the
201
OpenFlow flow table starts out empty.
203
>>> If we did not do this, then the flow table would start out with a
204
single flow that executes the "normal" action. We could use that
205
feature to yield a switch that behaves the same as the switch we
206
are currently building, but with the caveats described under
209
The new bridge has only one port on it so far, the "local port" br0.
210
We need to add p1, p2, p3, and p4. A shell "for" loop is one way to
214
ovs-vsctl add-port br0 p$i -- set Interface p$i ofport_request=$i
215
ovs-ofctl mod-port br0 p$i up
218
In addition to adding a port, the ovs-vsctl command above sets its
219
"ofport_request" column to ensure that port p1 is assigned OpenFlow
220
port 1, p2 is assigned OpenFlow port 2, and so on.
222
>>> We could omit setting the ofport_request and let Open vSwitch
223
choose port numbers for us, but it's convenient for the purposes
224
of this tutorial because we can talk about OpenFlow port 1 and
225
know that it corresponds to p1.
227
The ovs-ofctl command above brings up the simulated interfaces, which
228
are down initially, using an OpenFlow request. The effect is similar
229
to "ifconfig up", but the sandbox's interfaces are not visible to the
230
operating system and therefore "ifconfig" would not affect them.
232
We have not configured anything related to VLANs or MAC learning.
233
That's because we're going to implement those features in the flow
236
To see what we've done so far to set up the scenario, you can run a
237
command like "ovs-vsctl show" or "ovs-ofctl show br0".
240
Implementing Table 0: Admission control
241
=======================================
243
Table 0 is where packets enter the switch. We use this stage to
244
discard packets that for one reason or another are invalid. For
245
example, packets with a multicast source address are not valid, so we
246
can add a flow to drop them at ingress to the switch with:
248
ovs-ofctl add-flow br0 \
249
"table=0, dl_src=01:00:00:00:00:00/01:00:00:00:00:00, actions=drop"
251
A switch should also not forward IEEE 802.1D Spanning Tree Protocol
252
(STP) packets, so we can also add a flow to drop those and other
253
packets with reserved multicast protocols:
255
ovs-ofctl add-flow br0 \
256
"table=0, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0, actions=drop"
258
We could add flows to drop other protocols, but these demonstrate the
261
We need one more flow, with a priority lower than the default, so that
262
flows that don't match either of the "drop" flows we added above go on
263
to pipeline stage 1 in OpenFlow table 1:
265
ovs-ofctl add-flow br0 "table=0, priority=0, actions=resubmit(,1)"
267
(The "resubmit" action is an Open vSwitch extension to OpenFlow.)
273
If we were using Open vSwitch to set up a physical or a virtual
274
switch, then we would naturally test it by sending packets through it
275
one way or another, perhaps with common network testing tools like
276
"ping" and "tcpdump" or more specialized tools like Scapy. That's
277
difficult with our simulated switch, since it's not visible to the
280
But our simulated switch has a few specialized testing tools. The
281
most powerful of these tools is "ofproto/trace". Given a switch and
282
the specification of a flow, "ofproto/trace" shows, step-by-step, how
283
such a flow would be treated as it goes through the switch.
290
ovs-appctl ofproto/trace br0 in_port=1,dl_dst=01:80:c2:00:00:05
292
The output should look something like this:
294
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
295
Rule: table=0 cookie=0 dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0
296
OpenFlow actions=drop
298
Final flow: unchanged
299
Datapath actions: drop
301
The first block of lines describes an OpenFlow table lookup. The
302
first line shows the fields used for the table lookup (which is mostly
303
zeros because that's the default if we don't specify everything). The
304
second line gives the OpenFlow flow that the fields matched (called a
305
"rule" because that is the name used inside Open vSwitch for an
306
OpenFlow flow). In this case, we see that this packet that has a
307
reserved multicast destination address matches the rule that drops
308
those packets. The third line gives the rule's OpenFlow actions.
310
The second block of lines summarizes the results, which are not very
318
ovs-appctl ofproto/trace br0 in_port=1,dl_dst=01:80:c2:00:00:10
320
The output should be:
322
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
323
Rule: table=0 cookie=0 priority=0
324
OpenFlow actions=resubmit(,1)
326
Resubmitted flow: unchanged
327
Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
328
Resubmitted odp: drop
331
Final flow: unchanged
332
Datapath actions: drop
334
This time the flow we handed to "ofproto/trace" doesn't match any of
335
our "drop" rules, so it falls through to the low-priority "resubmit"
336
rule, which we see in the rule and the actions selected in the first
337
block. The "resubmit" causes a second lookup in OpenFlow table 1,
338
described by the additional block of indented text in the output. We
339
haven't yet added any flows to OpenFlow table 1, so no flow actually
340
matches in the second lookup. Therefore, the packet is still actually
341
dropped, which means that the externally observable results would be
342
identical to our first example.
345
Implementing Table 1: VLAN Input Processing
346
===========================================
348
A packet that enters table 1 has already passed basic validation in
349
table 0. The purpose of table 1 is validate the packet's VLAN, based
350
on the VLAN configuration of the switch port through which the packet
351
entered the switch. We will also use it to attach a VLAN header to
352
packets that arrive on an access port, which allows later processing
353
stages to rely on the packet's VLAN always being part of the VLAN
354
header, reducing special cases.
356
Let's start by adding a low-priority flow that drops all packets,
357
before we add flows that pass through acceptable packets. You can
358
think of this as a "default drop" rule:
360
ovs-ofctl add-flow br0 "table=1, priority=0, actions=drop"
362
Our trunk port p1, on OpenFlow port 1, is an easy case. p1 accepts
363
any packet regardless of whether it has a VLAN header or what the VLAN
364
was, so we can add a flow that resubmits everything on input port 1 to
367
ovs-ofctl add-flow br0 \
368
"table=1, priority=99, in_port=1, actions=resubmit(,2)"
370
On the access ports, we want to accept any packet that has no VLAN
371
header, tag it with the access port's VLAN number, and then pass it
372
along to the next stage:
374
ovs-ofctl add-flows br0 - <<'EOF'
375
table=1, priority=99, in_port=2, vlan_tci=0, actions=mod_vlan_vid:20, resubmit(,2)
376
table=1, priority=99, in_port=3, vlan_tci=0, actions=mod_vlan_vid:30, resubmit(,2)
377
table=1, priority=99, in_port=4, vlan_tci=0, actions=mod_vlan_vid:30, resubmit(,2)
380
We don't write any rules that match packets with 802.1Q that enter
381
this stage on any of the access ports, so the "default drop" rule we
382
added earlier causes them to be dropped, which is ordinarily what we
383
want for access ports.
385
>>> Another variation of access ports allows ingress of packets tagged
386
with VLAN 0 (aka 802.1p priority tagged packets). To allow such
387
packets, replace "vlan_tci=0" by "vlan_tci=0/0xfff" above.
393
"ofproto/trace" allows us to test the ingress VLAN rules that we added
397
== EXAMPLE 1: Packet on Trunk Port ==
399
Here's a test of a packet coming in on the trunk port:
401
ovs-appctl ofproto/trace br0 in_port=1,vlan_tci=5
403
The output shows the lookup in table 0, the resubmit to table 1, and
404
the resubmit to table 2 (which does nothing because we haven't put
407
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
408
Rule: table=0 cookie=0 priority=0
409
OpenFlow actions=resubmit(,1)
411
Resubmitted flow: unchanged
412
Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
413
Resubmitted odp: drop
414
Rule: table=1 cookie=0 priority=99,in_port=1
415
OpenFlow actions=resubmit(,2)
417
Resubmitted flow: unchanged
418
Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
419
Resubmitted odp: drop
422
Final flow: unchanged
423
Datapath actions: drop
426
== EXAMPLE 2: Valid Packet on Access Port ==
428
Here's a test of a valid packet (a packet without an 802.1Q header)
429
coming in on access port p2:
431
ovs-appctl ofproto/trace br0 in_port=2
433
The output is similar to that for the previous case, except that it
434
additionally tags the packet with p2's VLAN 20 before it passes it
437
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
438
Rule: table=0 cookie=0 priority=0
439
OpenFlow actions=resubmit(,1)
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
444
Rule: table=1 cookie=0 priority=99,in_port=2,vlan_tci=0x0000
445
OpenFlow actions=mod_vlan_vid:20,resubmit(,2)
447
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
448
Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
449
Resubmitted odp: drop
452
Final flow: unchanged
453
Datapath actions: drop
456
== EXAMPLE 3: Invalid Packet on Access Port ==
458
This tests an invalid packet (one that includes an 802.1Q header)
459
coming in on access port p2:
461
ovs-appctl ofproto/trace br0 in_port=2,vlan_tci=5
463
The output shows the packet matching the default drop rule:
465
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
466
Rule: table=0 cookie=0 priority=0
467
OpenFlow actions=resubmit(,1)
469
Resubmitted flow: unchanged
470
Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
471
Resubmitted odp: drop
472
Rule: table=1 cookie=0 priority=0
473
OpenFlow actions=drop
475
Final flow: unchanged
476
Datapath actions: drop
479
Implementing Table 2: MAC+VLAN Learning for Ingress Port
480
========================================================
482
This table allows the switch we're implementing to learn that the
483
packet's source MAC is located on the packet's ingress port in the
486
>>> This table is a good example why table 1 added a VLAN tag to
487
packets that entered the switch through an access port. We want
488
to associate a MAC+VLAN with a port regardless of whether the VLAN
489
in question was originally part of the packet or whether it was an
490
assumed VLAN associated with an access port.
492
It only takes a single flow to do this. The following command adds
495
ovs-ofctl add-flow br0 \
496
"table=2 actions=learn(table=10, NXM_OF_VLAN_TCI[0..11], \
497
NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], \
498
load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]), \
501
The "learn" action (an Open vSwitch extension to OpenFlow) modifies a
502
flow table based on the content of the flow currently being processed.
503
Here's how you can interpret each part of the "learn" action above:
507
Modify flow table 10. This will be the MAC learning table.
509
NXM_OF_VLAN_TCI[0..11]
511
Make the flow that we add to flow table 10 match the same VLAN
512
ID that the packet we're currently processing contains. This
513
effectively scopes the MAC learning entry to a single VLAN,
514
which is the ordinary behavior for a VLAN-aware switch.
516
NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[]
518
Make the flow that we add to flow table 10 match, as Ethernet
519
destination, the Ethernet source address of the packet we're
520
currently processing.
522
load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]
524
Whereas the preceding parts specify fields for the new flow to
525
match, this specifies an action for the flow to take when it
526
matches. The action is for the flow to load the ingress port
527
number of the current packet into register 0 (a special field
528
that is an Open vSwitch extension to OpenFlow).
530
>>> A real use of "learn" for MAC learning would probably involve two
531
additional elements. First, the "learn" action would specify a
532
hard_timeout for the new flow, to enable a learned MAC to
533
eventually expire if no new packets were seen from a given source
534
within a reasonable interval. Second, one would usually want to
535
limit resource consumption by using the Flow_Table table in the
536
Open vSwitch configuration database to specify a maximum number of
539
This definitely calls for examples.
547
Try the following test command:
549
ovs-appctl ofproto/trace br0 in_port=1,vlan_tci=20,dl_src=50:00:00:00:00:01 -generate
551
The output shows that "learn" was executed, but it isn't otherwise
552
informative, so we won't include it here.
554
The "-generate" keyword is new. Ordinarily, "ofproto/trace" has no
555
side effects: "output" actions do not actually output packets, "learn"
556
actions do not actually modify the flow table, and so on. With
557
"-generate", though, "ofproto/trace" does execute "learn" actions.
558
That's important now, because we want to see the effect of the "learn"
559
action on table 10. You can see that by running:
561
ovs-ofctl dump-flows br0 table=10
563
which (omitting the "duration" and "idle_age" fields, which will vary
564
based on how soon you ran this command after the previous one, as well
565
as some other uninteresting fields) prints something like:
567
NXST_FLOW reply (xid=0x4):
568
table=10, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
570
You can see that the packet coming in on VLAN 20 with source MAC
571
50:00:00:00:00:01 became a flow that matches VLAN 20 (written in
572
hexadecimal) and destination MAC 50:00:00:00:00:01. The flow loads
573
port number 1, the input port for the flow we tested, into register 0.
578
Here's a second test command:
580
ovs-appctl ofproto/trace br0 in_port=2,dl_src=50:00:00:00:00:01 -generate
582
The flow that this command tests has the same source MAC and VLAN as
583
example 1, although the VLAN comes from an access port VLAN rather
584
than an 802.1Q header. If we again dump the flows for table 10 with:
586
ovs-ofctl dump-flows br0 table=10
588
then we see that the flow we saw previously has changed to indicate
589
that the learned port is port 2, as we would expect:
591
NXST_FLOW reply (xid=0x4):
592
table=10, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:01 actions=load:0x2->NXM_NX_REG0[0..15]
595
Implementing Table 3: Look Up Destination Port
596
==============================================
598
This table figures out what port we should send the packet to based on
599
the destination MAC and VLAN. That is, if we've learned the location
600
of the destination (from table 2 processing some previous packet with
601
that destination as its source), then we want to send the packet
604
We need only one flow to do the lookup:
606
ovs-ofctl add-flow br0 \
607
"table=3 priority=50 actions=resubmit(,10), resubmit(,4)"
609
The flow's first action resubmits to table 10, the table that the
610
"learn" action modifies. As you saw previously, the learned flows in
611
this table write the learned port into register 0. If the destination
612
for our packet hasn't been learned, then there will be no matching
613
flow, and so the "resubmit" turns into a no-op. Because registers are
614
initialized to 0, we can use a register 0 value of 0 in our next
615
pipeline stage as a signal to flood the packet.
617
The second action resubmits to table 4, continuing to the next
620
We can add another flow to skip the learning table lookup for
621
multicast and broadcast packets, since those should always be flooded:
623
ovs-ofctl add-flow br0 \
624
"table=3 priority=99 dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 \
625
actions=resubmit(,4)"
627
>>> We don't strictly need to add this flow, because multicast
628
addresses will never show up in our learning table. (In turn,
629
that's because we put a flow into table 0 to drop packets that
630
have a multicast source address.)
638
Here's a command that should cause OVS to learn that f0:00:00:00:00:01
641
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
643
Here's an excerpt from the output that shows (from the "no match"
644
looking up the resubmit to table 10) that the flow's destination was
647
Resubmitted flow: unchanged
648
Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
649
Resubmitted odp: drop
650
Rule: table=3 cookie=0 priority=50
651
OpenFlow actions=resubmit(,10),resubmit(,4)
653
Resubmitted flow: unchanged
654
Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
655
Resubmitted odp: drop
658
You can verify that the packet's source was learned two ways. The
659
most direct way is to dump the learning table with:
661
ovs-ofctl dump-flows br0 table=10
663
which ought to show roughly the following, with extraneous details
666
table=10, vlan_tci=0x0014/0x0fff,dl_dst=f0:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
668
>>> If you tried the examples for the previous step, or if you did
669
some of your own experiments, then you might see additional flows
670
there. These additional flows are harmless. If they bother you,
671
then you can remove them with "ovs-ofctl del-flows br0 table=10".
673
The other way is to inject a packet to take advantage of the learning
674
entry. For example, we can inject a packet on p2 whose destination is
675
the MAC address that we just learned on p1:
677
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
679
Here's an interesting excerpt from that command's output. This group
680
of lines traces the "resubmit(,10)", showing that the packet matched
681
the learned flow for the first MAC we used, loading the OpenFlow port
682
number for the learned port p1 into register 0:
684
Resubmitted flow: unchanged
685
Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
686
Resubmitted odp: drop
687
Rule: table=10 cookie=0 vlan_tci=0x0014/0x0fff,dl_dst=f0:00:00:00:00:01
688
OpenFlow actions=load:0x1->NXM_NX_REG0[0..15]
691
If you read the commands above carefully, then you might have noticed
692
that they simply have the Ethernet source and destination addresses
693
exchanged. That means that if we now rerun the first ovs-appctl
696
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
698
then we see in the output that the destination has now been learned:
700
Resubmitted flow: unchanged
701
Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
702
Resubmitted odp: drop
703
Rule: table=10 cookie=0 vlan_tci=0x0014/0x0fff,dl_dst=90:00:00:00:00:01
704
OpenFlow actions=load:0x2->NXM_NX_REG0[0..15]
707
Implementing Table 4: Output Processing
708
=======================================
710
At entry to stage 4, we know that register 0 contains either the
711
desired output port or is zero if the packet should be flooded. We
712
also know that the packet's VLAN is in its 802.1Q header, even if the
713
VLAN was implicit because the packet came in on an access port.
715
The job of the final pipeline stage is to actually output packets.
716
The job is trivial for output to our trunk port p1:
718
ovs-ofctl add-flow br0 "table=4 reg0=1 actions=1"
720
For output to the access ports, we just have to strip the VLAN header
721
before outputting the packet:
723
ovs-ofctl add-flows br0 - <<'EOF'
724
table=4 reg0=2 actions=strip_vlan,2
725
table=4 reg0=3 actions=strip_vlan,3
726
table=4 reg0=4 actions=strip_vlan,4
729
The only slightly tricky part is flooding multicast and broadcast
730
packets and unicast packets with unlearned destinations. For those,
731
we need to make sure that we only output the packets to the ports that
732
carry our packet's VLAN, and that we include the 802.1Q header in the
733
copy output to the trunk port but not in copies output to access
736
ovs-ofctl add-flows br0 - <<'EOF'
737
table=4 reg0=0 priority=99 dl_vlan=20 actions=1,strip_vlan,2
738
table=4 reg0=0 priority=99 dl_vlan=30 actions=1,strip_vlan,3,4
739
table=4 reg0=0 priority=50 actions=1
742
>>> Our rules rely on the standard OpenFlow behavior that an output
743
action will not forward a packet back out the port it came in on.
744
That is, if a packet comes in on p1, and we've learned that the
745
packet's destination MAC is also on p1, so that we end up with
746
"actions=1" as our actions, the switch will not forward the packet
747
back out its input port. The multicast/broadcast/unknown
748
destination cases above also rely on this behavior.
754
== EXAMPLE 1: Broadcast, Multicast, and Unknown Destination ==
756
Try tracing a broadcast packet arriving on p1 in VLAN 30:
758
ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=30
760
The interesting part of the output is the final line, which shows that
761
the switch would remove the 802.1Q header and then output the packet to
762
p3 and p4, which are access ports for VLAN 30:
764
Datapath actions: pop_vlan,3,4
766
Similarly, if we trace a broadcast packet arriving on p3:
768
ovs-appctl ofproto/trace br0 in_port=3,dl_dst=ff:ff:ff:ff:ff:ff
770
then we see that it is output to p1 with an 802.1Q tag and then to p4
773
Datapath actions: push_vlan(vid=30,pcp=0),1,pop_vlan,4
775
>>> Open vSwitch could simplify the datapath actions here to just
776
"4,push_vlan(vid=30,pcp=0),1" but it is not smart enough to do so.
778
The following are also broadcasts, but the result is to drop the
779
packets because the VLAN only belongs to the input port:
781
ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff
782
ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=55
784
Try some other broadcast cases on your own:
786
ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=20
787
ovs-appctl ofproto/trace br0 in_port=2,dl_dst=ff:ff:ff:ff:ff:ff
788
ovs-appctl ofproto/trace br0 in_port=4,dl_dst=ff:ff:ff:ff:ff:ff
790
You can see the same behavior with multicast packets and with unicast
791
packets whose destination has not been learned, e.g.:
793
ovs-appctl ofproto/trace br0 in_port=4,dl_dst=01:00:00:00:00:00
794
ovs-appctl ofproto/trace br0 in_port=1,dl_dst=90:12:34:56:78:90,dl_vlan=20
795
ovs-appctl ofproto/trace br0 in_port=1,dl_dst=90:12:34:56:78:90,dl_vlan=30
798
== EXAMPLE 2: MAC Learning ==
800
Let's follow the same pattern as we did for table 3. First learn a
801
MAC on port p1 in VLAN 30:
803
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
805
You can see from the last line of output that the packet's destination
806
is unknown, so it gets flooded to both p3 and p4, the other ports in
809
Datapath actions: pop_vlan,3,4
811
Then reverse the MACs and learn the first flow's destination on port
814
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
816
The last line of output shows that the this packet's destination is
817
known to be p1, as learned from our previous command:
819
Datapath actions: push_vlan(vid=30,pcp=0),1
821
Now, if we rerun our first command:
823
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
825
we can see that the result is no longer a flood but to the specified
826
learned destination port p4:
828
Datapath actions: pop_vlan,4
835
http://openvswitch.org/