ofproto-dpif-xlate: Avoid recursively taking read side of ofgroup rwlock.
[sliver-openvswitch.git] / tutorial / Tutorial
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/