~james-page/ubuntu/saucy/openvswitch/1.12-snapshot

« back to all changes in this revision

Viewing changes to tutorial/Tutorial

  • Committer: James Page
  • Date: 2013-08-21 10:16:57 UTC
  • mfrom: (1.1.20)
  • Revision ID: james.page@canonical.com-20130821101657-3o0z0qeiv5zkwlzi
New upstream snapshot

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
Open vSwitch Advanced Features Tutorial
 
2
=======================================
 
3
 
 
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
 
8
here afterward.
 
9
 
 
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.
 
13
 
 
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.
 
19
 
 
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.
 
24
 
 
25
>>> In this tutorial, paragraphs set off like this designate notes
 
26
    with additional information that readers may wish to skip on a
 
27
    first read.
 
28
 
 
29
 
 
30
Getting Started
 
31
===============
 
32
 
 
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.
 
39
 
 
40
You can use "ovs-sandbox" three ways:
 
41
 
 
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
 
44
      without any options.
 
45
 
 
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.
 
51
 
 
52
    * As a slight variant on the latter, you can run "make sandbox"
 
53
      from an Open vSwitch build directory.
 
54
 
 
55
When you run ovs-sandbox, it does the following:
 
56
 
 
57
    1. CAUTION: Deletes any subdirectory of the current directory
 
58
       named "sandbox" and any files in that directory.
 
59
 
 
60
    2. Creates a new directory "sandbox" in the current directory.
 
61
 
 
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.
 
65
 
 
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
 
71
       you built.
 
72
 
 
73
    5. Creates an empty Open vSwitch configuration database under
 
74
       "sandbox".
 
75
 
 
76
    6. Starts ovsdb-server running under "sandbox".
 
77
 
 
78
    7. Starts ovs-vswitchd running under "sandbox", passing special
 
79
       options that enable a special "dummy" mode for testing.
 
80
 
 
81
    8. Starts a nested interactive shell inside "sandbox".
 
82
 
 
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
 
85
create a bridge:
 
86
 
 
87
    ovs-vsctl add-br br0
 
88
 
 
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
 
97
sandboxed OVS.)
 
98
 
 
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.
 
103
 
 
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
 
106
or after you exit.
 
107
 
 
108
 
 
109
Motivation
 
110
==========
 
111
 
 
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:
 
117
 
 
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.
 
122
 
 
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.
 
128
 
 
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
 
137
network problems.
 
138
 
 
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
 
146
features.
 
147
 
 
148
 
 
149
Scenario
 
150
========
 
151
 
 
152
We will construct Open vSwitch flow tables for a VLAN-capable,
 
153
MAC-learning switch that has four ports:
 
154
 
 
155
    * p1, a trunk port that carries all VLANs, on OpenFlow port 1.
 
156
 
 
157
    * p2, an access port for VLAN 20, on OpenFlow port 2.
 
158
 
 
159
    * p3 and p4, both access ports for VLAN 30, on OpenFlow ports 3
 
160
      and 4, respectively.
 
161
 
 
162
>>> The ports' names are not significant.  You could call them eth1
 
163
    through eth4, or any other names you like.
 
164
 
 
165
>>> An OpenFlow switch always has a "local" port as well.  This
 
166
    scenario won't use the local port.
 
167
 
 
168
Our switch design will consist of five main flow tables, each of which
 
169
implements one stage in the switch pipeline:
 
170
 
 
171
    Table 0: Admission control.
 
172
 
 
173
    Table 1: VLAN input processing.
 
174
 
 
175
    Table 2: Learn source MAC and VLAN for ingress port.
 
176
 
 
177
    Table 3: Look up learned port for destination MAC and VLAN.
 
178
 
 
179
    Table 4: Output processing.
 
180
 
 
181
The section below describes how to set up the scenario, followed by a
 
182
section for each OpenFlow table.
 
183
 
 
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.
 
189
 
 
190
 
 
191
Setup
 
192
=====
 
193
 
 
194
To get started, start "ovs-sandbox".  Inside the interactive shell
 
195
that it starts, run this command:
 
196
 
 
197
    ovs-vsctl add-br br0 -- set Bridge br0 fail-mode=secure
 
198
 
 
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.
 
202
 
 
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
 
207
    "Motivation" above.)
 
208
 
 
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
 
211
do it:
 
212
 
 
213
    for i in 1 2 3 4; do
 
214
        ovs-vsctl add-port br0 p$i -- set Interface p$i ofport_request=$i
 
215
        ovs-ofctl mod-port br0 p$i up
 
216
    done
 
217
 
 
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.
 
221
 
 
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.
 
226
 
 
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.
 
231
 
 
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
 
234
table.
 
235
 
 
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".
 
238
 
 
239
 
 
240
Implementing Table 0: Admission control
 
241
=======================================
 
242
 
 
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:
 
247
 
 
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"
 
250
 
 
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:
 
254
 
 
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"
 
257
 
 
258
We could add flows to drop other protocols, but these demonstrate the
 
259
pattern.
 
260
 
 
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:
 
264
 
 
265
    ovs-ofctl add-flow br0 "table=0, priority=0, actions=resubmit(,1)"
 
266
 
 
267
(The "resubmit" action is an Open vSwitch extension to OpenFlow.)
 
268
 
 
269
 
 
270
Testing Table 0
 
271
---------------
 
272
 
 
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
 
278
operating system.
 
279
 
 
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.
 
284
 
 
285
 
 
286
== EXAMPLE 1 ==
 
287
 
 
288
Try this command:
 
289
 
 
290
    ovs-appctl ofproto/trace br0 in_port=1,dl_dst=01:80:c2:00:00:05
 
291
 
 
292
The output should look something like this:
 
293
 
 
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
 
297
 
 
298
    Final flow: unchanged
 
299
    Datapath actions: drop
 
300
 
 
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.
 
309
 
 
310
The second block of lines summarizes the results, which are not very
 
311
interesting here.
 
312
 
 
313
 
 
314
== EXAMPLE 2 ==
 
315
 
 
316
Try another command:
 
317
 
 
318
    ovs-appctl ofproto/trace br0 in_port=1,dl_dst=01:80:c2:00:00:10
 
319
 
 
320
The output should be:
 
321
 
 
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)
 
325
 
 
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
 
329
            No match
 
330
 
 
331
    Final flow: unchanged
 
332
    Datapath actions: drop
 
333
 
 
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.
 
343
 
 
344
 
 
345
Implementing Table 1: VLAN Input Processing
 
346
===========================================
 
347
 
 
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.
 
355
 
 
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:
 
359
 
 
360
    ovs-ofctl add-flow br0 "table=1, priority=0, actions=drop"
 
361
 
 
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
 
365
the next table:
 
366
 
 
367
    ovs-ofctl add-flow br0 \
 
368
        "table=1, priority=99, in_port=1, actions=resubmit(,2)"
 
369
 
 
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:
 
373
 
 
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)
 
378
EOF
 
379
 
 
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.
 
384
 
 
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.
 
388
 
 
389
 
 
390
Testing Table 1
 
391
---------------
 
392
 
 
393
"ofproto/trace" allows us to test the ingress VLAN rules that we added
 
394
above.
 
395
 
 
396
 
 
397
== EXAMPLE 1: Packet on Trunk Port ==
 
398
 
 
399
Here's a test of a packet coming in on the trunk port:
 
400
 
 
401
    ovs-appctl ofproto/trace br0 in_port=1,vlan_tci=5
 
402
 
 
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
 
405
anything there yet):
 
406
 
 
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)
 
410
 
 
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)
 
416
 
 
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
 
420
                    No match
 
421
 
 
422
    Final flow: unchanged
 
423
    Datapath actions: drop
 
424
 
 
425
 
 
426
== EXAMPLE 2: Valid Packet on Access Port ==
 
427
 
 
428
Here's a test of a valid packet (a packet without an 802.1Q header)
 
429
coming in on access port p2:
 
430
 
 
431
    ovs-appctl ofproto/trace br0 in_port=2
 
432
 
 
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
 
435
along to table 2:
 
436
 
 
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)
 
440
 
 
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)
 
446
 
 
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
 
450
                    No match
 
451
 
 
452
    Final flow: unchanged
 
453
    Datapath actions: drop
 
454
 
 
455
 
 
456
== EXAMPLE 3: Invalid Packet on Access Port ==
 
457
 
 
458
This tests an invalid packet (one that includes an 802.1Q header)
 
459
coming in on access port p2:
 
460
 
 
461
    ovs-appctl ofproto/trace br0 in_port=2,vlan_tci=5
 
462
 
 
463
The output shows the packet matching the default drop rule:
 
464
 
 
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)
 
468
 
 
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
 
474
 
 
475
    Final flow: unchanged
 
476
    Datapath actions: drop
 
477
 
 
478
 
 
479
Implementing Table 2: MAC+VLAN Learning for Ingress Port
 
480
========================================================
 
481
 
 
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
 
484
packet's VLAN.
 
485
 
 
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.
 
491
 
 
492
It only takes a single flow to do this.  The following command adds
 
493
it:
 
494
 
 
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]), \
 
499
                         resubmit(,3)"
 
500
 
 
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:
 
504
 
 
505
    table=10
 
506
 
 
507
        Modify flow table 10.  This will be the MAC learning table.
 
508
 
 
509
    NXM_OF_VLAN_TCI[0..11]
 
510
 
 
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.
 
515
 
 
516
    NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[]
 
517
 
 
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.
 
521
 
 
522
    load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]
 
523
 
 
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).
 
529
 
 
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
 
537
    flows in table 10.
 
538
 
 
539
This definitely calls for examples.
 
540
 
 
541
 
 
542
Testing Table 2
 
543
---------------
 
544
 
 
545
== EXAMPLE 1 ==
 
546
 
 
547
Try the following test command:
 
548
 
 
549
    ovs-appctl ofproto/trace br0 in_port=1,vlan_tci=20,dl_src=50:00:00:00:00:01 -generate
 
550
 
 
551
The output shows that "learn" was executed, but it isn't otherwise
 
552
informative, so we won't include it here.
 
553
 
 
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:
 
560
 
 
561
    ovs-ofctl dump-flows br0 table=10
 
562
 
 
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:
 
566
 
 
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]
 
569
 
 
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.
 
574
 
 
575
 
 
576
== EXAMPLE 2 ==
 
577
 
 
578
Here's a second test command:
 
579
 
 
580
    ovs-appctl ofproto/trace br0 in_port=2,dl_src=50:00:00:00:00:01 -generate
 
581
 
 
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:
 
585
 
 
586
    ovs-ofctl dump-flows br0 table=10
 
587
 
 
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:
 
590
 
 
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]
 
593
 
 
594
 
 
595
Implementing Table 3: Look Up Destination Port
 
596
==============================================
 
597
 
 
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
 
602
there.
 
603
 
 
604
We need only one flow to do the lookup:
 
605
 
 
606
    ovs-ofctl add-flow br0 \
 
607
        "table=3 priority=50 actions=resubmit(,10), resubmit(,4)"
 
608
 
 
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.
 
616
 
 
617
The second action resubmits to table 4, continuing to the next
 
618
pipeline stage.
 
619
 
 
620
We can add another flow to skip the learning table lookup for
 
621
multicast and broadcast packets, since those should always be flooded:
 
622
 
 
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)"
 
626
 
 
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.)
 
631
 
 
632
 
 
633
Testing Table 3
 
634
---------------
 
635
 
 
636
== EXAMPLE ==
 
637
 
 
638
Here's a command that should cause OVS to learn that f0:00:00:00:00:01
 
639
is on p1 in VLAN 20:
 
640
 
 
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
 
642
 
 
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
 
645
unknown:
 
646
 
 
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)
 
652
 
 
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
 
656
                                No match
 
657
 
 
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:
 
660
 
 
661
    ovs-ofctl dump-flows br0 table=10
 
662
 
 
663
which ought to show roughly the following, with extraneous details
 
664
removed:
 
665
 
 
666
    table=10, vlan_tci=0x0014/0x0fff,dl_dst=f0:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
 
667
 
 
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".
 
672
 
 
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:
 
676
 
 
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
 
678
 
 
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:
 
683
 
 
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]
 
689
 
 
690
 
 
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
 
694
command above, e.g.:
 
695
 
 
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
 
697
 
 
698
then we see in the output that the destination has now been learned:
 
699
 
 
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]
 
705
 
 
706
 
 
707
Implementing Table 4: Output Processing
 
708
=======================================
 
709
 
 
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.
 
714
 
 
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:
 
717
 
 
718
    ovs-ofctl add-flow br0 "table=4 reg0=1 actions=1"
 
719
 
 
720
For output to the access ports, we just have to strip the VLAN header
 
721
before outputting the packet:
 
722
 
 
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
 
727
EOF
 
728
 
 
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
 
734
ports:
 
735
 
 
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
 
740
EOF
 
741
 
 
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.
 
749
 
 
750
 
 
751
Testing Table 4
 
752
---------------
 
753
 
 
754
== EXAMPLE 1: Broadcast, Multicast, and Unknown Destination ==
 
755
 
 
756
Try tracing a broadcast packet arriving on p1 in VLAN 30:
 
757
 
 
758
    ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=30
 
759
 
 
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:
 
763
 
 
764
    Datapath actions: pop_vlan,3,4
 
765
 
 
766
Similarly, if we trace a broadcast packet arriving on p3:
 
767
 
 
768
    ovs-appctl ofproto/trace br0 in_port=3,dl_dst=ff:ff:ff:ff:ff:ff
 
769
 
 
770
then we see that it is output to p1 with an 802.1Q tag and then to p4
 
771
without one:
 
772
 
 
773
    Datapath actions: push_vlan(vid=30,pcp=0),1,pop_vlan,4
 
774
 
 
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.
 
777
 
 
778
The following are also broadcasts, but the result is to drop the
 
779
packets because the VLAN only belongs to the input port:
 
780
 
 
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
 
783
 
 
784
Try some other broadcast cases on your own:
 
785
 
 
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
 
789
 
 
790
You can see the same behavior with multicast packets and with unicast
 
791
packets whose destination has not been learned, e.g.:
 
792
 
 
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
 
796
 
 
797
 
 
798
== EXAMPLE 2: MAC Learning ==
 
799
 
 
800
Let's follow the same pattern as we did for table 3.  First learn a
 
801
MAC on port p1 in VLAN 30:
 
802
 
 
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
 
804
 
 
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
 
807
VLAN 30:
 
808
 
 
809
    Datapath actions: pop_vlan,3,4
 
810
 
 
811
Then reverse the MACs and learn the first flow's destination on port
 
812
p4:
 
813
 
 
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
 
815
 
 
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:
 
818
 
 
819
    Datapath actions: push_vlan(vid=30,pcp=0),1
 
820
 
 
821
Now, if we rerun our first command:
 
822
 
 
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
 
824
 
 
825
we can see that the result is no longer a flood but to the specified
 
826
learned destination port p4:
 
827
 
 
828
    Datapath actions: pop_vlan,4
 
829
 
 
830
 
 
831
Contact 
 
832
=======
 
833
 
 
834
bugs@openvswitch.org
 
835
http://openvswitch.org/