~ubuntu-branches/ubuntu/wily/openvswitch/wily

« back to all changes in this revision

Viewing changes to tutorial/Tutorial

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2015-08-10 11:35:15 UTC
  • mfrom: (1.1.30)
  • Revision ID: package-import@ubuntu.com-20150810113515-575vj06oq29emxsn
Tags: 2.4.0~git20150810.97bab95-0ubuntu1
* New upstream snapshot from 2.4 branch:
  - d/*: Align any relevant packaging changes with upstream.
* d/*: wrap-and-sort.
* d/openvswitch-{common,vswitch}.install: Correct install location for
  bash completion files.
* d/tests/openflow.py: Explicitly use ovs-testcontroller as provided
  by 2.4.0 release.

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/