doc: Convert docs to Markdown language
[cascardo/ovs.git] / tutorial / Tutorial.md
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 If we were using Open vSwitch to set up a physical or a virtual
273 switch, then we would naturally test it by sending packets through it
274 one way or another, perhaps with common network testing tools like
275 "ping" and "tcpdump" or more specialized tools like Scapy.  That's
276 difficult with our simulated switch, since it's not visible to the
277 operating system.
278
279 But our simulated switch has a few specialized testing tools.  The
280 most powerful of these tools is "ofproto/trace".  Given a switch and
281 the specification of a flow, "ofproto/trace" shows, step-by-step, how
282 such a flow would be treated as it goes through the switch.
283
284
285 ### EXAMPLE 1
286
287 Try this command:
288
289     ovs-appctl ofproto/trace br0 in_port=1,dl_dst=01:80:c2:00:00:05
290
291 The output should look something like this:
292
293     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
294     Rule: table=0 cookie=0 dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0
295     OpenFlow actions=drop
296
297     Final flow: unchanged
298     Datapath actions: drop
299
300 The first block of lines describes an OpenFlow table lookup.  The
301 first line shows the fields used for the table lookup (which is mostly
302 zeros because that's the default if we don't specify everything).  The
303 second line gives the OpenFlow flow that the fields matched (called a
304 "rule" because that is the name used inside Open vSwitch for an
305 OpenFlow flow).  In this case, we see that this packet that has a
306 reserved multicast destination address matches the rule that drops
307 those packets.  The third line gives the rule's OpenFlow actions.
308
309 The second block of lines summarizes the results, which are not very
310 interesting here.
311
312
313 ### EXAMPLE 2
314
315 Try another command:
316
317     ovs-appctl ofproto/trace br0 in_port=1,dl_dst=01:80:c2:00:00:10
318
319 The output should be:
320
321     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
322     Rule: table=0 cookie=0 priority=0
323     OpenFlow actions=resubmit(,1)
324
325             Resubmitted flow: unchanged
326             Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
327             Resubmitted  odp: drop
328             No match
329
330     Final flow: unchanged
331     Datapath actions: drop
332
333 This time the flow we handed to "ofproto/trace" doesn't match any of
334 our "drop" rules, so it falls through to the low-priority "resubmit"
335 rule, which we see in the rule and the actions selected in the first
336 block.  The "resubmit" causes a second lookup in OpenFlow table 1,
337 described by the additional block of indented text in the output.  We
338 haven't yet added any flows to OpenFlow table 1, so no flow actually
339 matches in the second lookup.  Therefore, the packet is still actually
340 dropped, which means that the externally observable results would be
341 identical to our first example.
342
343
344 Implementing Table 1: VLAN Input Processing
345 -------------------------------------------
346
347 A packet that enters table 1 has already passed basic validation in
348 table 0.  The purpose of table 1 is validate the packet's VLAN, based
349 on the VLAN configuration of the switch port through which the packet
350 entered the switch.  We will also use it to attach a VLAN header to
351 packets that arrive on an access port, which allows later processing
352 stages to rely on the packet's VLAN always being part of the VLAN
353 header, reducing special cases.
354
355 Let's start by adding a low-priority flow that drops all packets,
356 before we add flows that pass through acceptable packets.  You can
357 think of this as a "default drop" rule:
358
359     ovs-ofctl add-flow br0 "table=1, priority=0, actions=drop"
360
361 Our trunk port p1, on OpenFlow port 1, is an easy case.  p1 accepts
362 any packet regardless of whether it has a VLAN header or what the VLAN
363 was, so we can add a flow that resubmits everything on input port 1 to
364 the next table:
365
366     ovs-ofctl add-flow br0 \
367         "table=1, priority=99, in_port=1, actions=resubmit(,2)"
368
369 On the access ports, we want to accept any packet that has no VLAN
370 header, tag it with the access port's VLAN number, and then pass it
371 along to the next stage:
372
373     ovs-ofctl add-flows br0 - <<'EOF'
374           table=1, priority=99, in_port=2, vlan_tci=0, actions=mod_vlan_vid:20, resubmit(,2)
375           table=1, priority=99, in_port=3, vlan_tci=0, actions=mod_vlan_vid:30, resubmit(,2)
376           table=1, priority=99, in_port=4, vlan_tci=0, actions=mod_vlan_vid:30, resubmit(,2)
377     EOF
378
379 We don't write any rules that match packets with 802.1Q that enter
380 this stage on any of the access ports, so the "default drop" rule we
381 added earlier causes them to be dropped, which is ordinarily what we
382 want for access ports.
383
384 >>> Another variation of access ports allows ingress of packets tagged
385     with VLAN 0 (aka 802.1p priority tagged packets).  To allow such
386     packets, replace "vlan_tci=0" by "vlan_tci=0/0xfff" above.
387
388
389 ### Testing Table 1
390
391 "ofproto/trace" allows us to test the ingress VLAN rules that we added
392 above.
393
394
395 ### EXAMPLE 1: Packet on Trunk Port
396
397 Here's a test of a packet coming in on the trunk port:
398
399     ovs-appctl ofproto/trace br0 in_port=1,vlan_tci=5
400
401 The output shows the lookup in table 0, the resubmit to table 1, and
402 the resubmit to table 2 (which does nothing because we haven't put
403 anything there yet):
404
405     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
406     Rule: table=0 cookie=0 priority=0
407     OpenFlow actions=resubmit(,1)
408
409             Resubmitted flow: unchanged
410             Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
411             Resubmitted  odp: drop
412             Rule: table=1 cookie=0 priority=99,in_port=1
413             OpenFlow actions=resubmit(,2)
414
415                     Resubmitted flow: unchanged
416                     Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
417                     Resubmitted  odp: drop
418                     No match
419
420     Final flow: unchanged
421     Datapath actions: drop
422
423
424 ### EXAMPLE 2: Valid Packet on Access Port
425
426 Here's a test of a valid packet (a packet without an 802.1Q header)
427 coming in on access port p2:
428
429     ovs-appctl ofproto/trace br0 in_port=2
430
431 The output is similar to that for the previous case, except that it
432 additionally tags the packet with p2's VLAN 20 before it passes it
433 along to table 2:
434
435     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
436     Rule: table=0 cookie=0 priority=0
437     OpenFlow actions=resubmit(,1)
438
439             Resubmitted flow: unchanged
440             Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
441             Resubmitted  odp: drop
442             Rule: table=1 cookie=0 priority=99,in_port=2,vlan_tci=0x0000
443             OpenFlow actions=mod_vlan_vid:20,resubmit(,2)
444
445                     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
446                     Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
447                     Resubmitted  odp: drop
448                     No match
449
450     Final flow: unchanged
451     Datapath actions: drop
452
453
454 ### EXAMPLE 3: Invalid Packet on Access Port
455
456 This tests an invalid packet (one that includes an 802.1Q header)
457 coming in on access port p2:
458
459     ovs-appctl ofproto/trace br0 in_port=2,vlan_tci=5
460
461 The output shows the packet matching the default drop rule:
462
463     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
464     Rule: table=0 cookie=0 priority=0
465     OpenFlow actions=resubmit(,1)
466
467             Resubmitted flow: unchanged
468             Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
469             Resubmitted  odp: drop
470             Rule: table=1 cookie=0 priority=0
471             OpenFlow actions=drop
472
473     Final flow: unchanged
474     Datapath actions: drop
475
476
477 Implementing Table 2: MAC+VLAN Learning for Ingress Port
478 --------------------------------------------------------
479
480 This table allows the switch we're implementing to learn that the
481 packet's source MAC is located on the packet's ingress port in the
482 packet's VLAN.
483
484 >>> This table is a good example why table 1 added a VLAN tag to
485     packets that entered the switch through an access port.  We want
486     to associate a MAC+VLAN with a port regardless of whether the VLAN
487     in question was originally part of the packet or whether it was an
488     assumed VLAN associated with an access port.
489
490 It only takes a single flow to do this.  The following command adds
491 it:
492
493     ovs-ofctl add-flow br0 \
494         "table=2 actions=learn(table=10, NXM_OF_VLAN_TCI[0..11], \
495                                NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], \
496                                load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]), \
497                          resubmit(,3)"
498
499 The "learn" action (an Open vSwitch extension to OpenFlow) modifies a
500 flow table based on the content of the flow currently being processed.
501 Here's how you can interpret each part of the "learn" action above:
502
503     table=10
504
505         Modify flow table 10.  This will be the MAC learning table.
506
507     NXM_OF_VLAN_TCI[0..11]
508
509         Make the flow that we add to flow table 10 match the same VLAN
510         ID that the packet we're currently processing contains.  This
511         effectively scopes the MAC learning entry to a single VLAN,
512         which is the ordinary behavior for a VLAN-aware switch.
513
514     NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[]
515
516         Make the flow that we add to flow table 10 match, as Ethernet
517         destination, the Ethernet source address of the packet we're
518         currently processing.
519
520     load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]
521
522         Whereas the preceding parts specify fields for the new flow to
523         match, this specifies an action for the flow to take when it
524         matches.  The action is for the flow to load the ingress port
525         number of the current packet into register 0 (a special field
526         that is an Open vSwitch extension to OpenFlow).
527
528 >>> A real use of "learn" for MAC learning would probably involve two
529     additional elements.  First, the "learn" action would specify a
530     hard_timeout for the new flow, to enable a learned MAC to
531     eventually expire if no new packets were seen from a given source
532     within a reasonable interval.  Second, one would usually want to
533     limit resource consumption by using the Flow_Table table in the
534     Open vSwitch configuration database to specify a maximum number of
535     flows in table 10.
536
537 This definitely calls for examples.
538
539
540 ### Testing Table 2
541
542 ### EXAMPLE 1
543
544 Try the following test command:
545
546     ovs-appctl ofproto/trace br0 in_port=1,vlan_tci=20,dl_src=50:00:00:00:00:01 -generate
547
548 The output shows that "learn" was executed, but it isn't otherwise
549 informative, so we won't include it here.
550
551 The "-generate" keyword is new.  Ordinarily, "ofproto/trace" has no
552 side effects: "output" actions do not actually output packets, "learn"
553 actions do not actually modify the flow table, and so on.  With
554 "-generate", though, "ofproto/trace" does execute "learn" actions.
555 That's important now, because we want to see the effect of the "learn"
556 action on table 10.  You can see that by running:
557
558     ovs-ofctl dump-flows br0 table=10
559
560 which (omitting the "duration" and "idle_age" fields, which will vary
561 based on how soon you ran this command after the previous one, as well
562 as some other uninteresting fields) prints something like:
563
564     NXST_FLOW reply (xid=0x4):
565      table=10, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
566
567 You can see that the packet coming in on VLAN 20 with source MAC
568 50:00:00:00:00:01 became a flow that matches VLAN 20 (written in
569 hexadecimal) and destination MAC 50:00:00:00:00:01.  The flow loads
570 port number 1, the input port for the flow we tested, into register 0.
571
572
573 ### EXAMPLE 2
574
575 Here's a second test command:
576
577     ovs-appctl ofproto/trace br0 in_port=2,dl_src=50:00:00:00:00:01 -generate
578
579 The flow that this command tests has the same source MAC and VLAN as
580 example 1, although the VLAN comes from an access port VLAN rather
581 than an 802.1Q header.  If we again dump the flows for table 10 with:
582
583     ovs-ofctl dump-flows br0 table=10
584
585 then we see that the flow we saw previously has changed to indicate
586 that the learned port is port 2, as we would expect:
587
588     NXST_FLOW reply (xid=0x4):
589      table=10, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:01 actions=load:0x2->NXM_NX_REG0[0..15]
590
591
592 Implementing Table 3: Look Up Destination Port
593 ----------------------------------------------
594
595 This table figures out what port we should send the packet to based on
596 the destination MAC and VLAN.  That is, if we've learned the location
597 of the destination (from table 2 processing some previous packet with
598 that destination as its source), then we want to send the packet
599 there.
600
601 We need only one flow to do the lookup:
602
603     ovs-ofctl add-flow br0 \
604         "table=3 priority=50 actions=resubmit(,10), resubmit(,4)"
605
606 The flow's first action resubmits to table 10, the table that the
607 "learn" action modifies.  As you saw previously, the learned flows in
608 this table write the learned port into register 0.  If the destination
609 for our packet hasn't been learned, then there will be no matching
610 flow, and so the "resubmit" turns into a no-op.  Because registers are
611 initialized to 0, we can use a register 0 value of 0 in our next
612 pipeline stage as a signal to flood the packet.
613
614 The second action resubmits to table 4, continuing to the next
615 pipeline stage.
616
617 We can add another flow to skip the learning table lookup for
618 multicast and broadcast packets, since those should always be flooded:
619
620     ovs-ofctl add-flow br0 \
621         "table=3 priority=99 dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 \
622           actions=resubmit(,4)"
623
624 >>> We don't strictly need to add this flow, because multicast
625     addresses will never show up in our learning table.  (In turn,
626     that's because we put a flow into table 0 to drop packets that
627     have a multicast source address.)
628
629
630 ### Testing Table 3
631
632 ### EXAMPLE
633
634 Here's a command that should cause OVS to learn that f0:00:00:00:00:01
635 is on p1 in VLAN 20:
636
637     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
638
639 Here's an excerpt from the output that shows (from the "no match"
640 looking up the resubmit to table 10) that the flow's destination was
641 unknown:
642
643                         Resubmitted flow: unchanged
644                         Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
645                         Resubmitted  odp: drop
646                         Rule: table=3 cookie=0 priority=50
647                         OpenFlow actions=resubmit(,10),resubmit(,4)
648
649                                 Resubmitted flow: unchanged
650                                 Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
651                                 Resubmitted  odp: drop
652                                 No match
653
654 You can verify that the packet's source was learned two ways.  The
655 most direct way is to dump the learning table with:
656
657     ovs-ofctl dump-flows br0 table=10
658
659 which ought to show roughly the following, with extraneous details
660 removed:
661
662     table=10, vlan_tci=0x0014/0x0fff,dl_dst=f0:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
663
664 >>> If you tried the examples for the previous step, or if you did
665     some of your own experiments, then you might see additional flows
666     there.  These additional flows are harmless.  If they bother you,
667     then you can remove them with "ovs-ofctl del-flows br0 table=10".
668
669 The other way is to inject a packet to take advantage of the learning
670 entry.  For example, we can inject a packet on p2 whose destination is
671 the MAC address that we just learned on p1:
672
673     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
674
675 Here's an interesting excerpt from that command's output.  This group
676 of lines traces the "resubmit(,10)", showing that the packet matched
677 the learned flow for the first MAC we used, loading the OpenFlow port
678 number for the learned port p1 into register 0:
679
680                                 Resubmitted flow: unchanged
681                                 Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
682                                 Resubmitted  odp: drop
683                                 Rule: table=10 cookie=0 vlan_tci=0x0014/0x0fff,dl_dst=f0:00:00:00:00:01
684                                 OpenFlow actions=load:0x1->NXM_NX_REG0[0..15]
685
686
687 If you read the commands above carefully, then you might have noticed
688 that they simply have the Ethernet source and destination addresses
689 exchanged.  That means that if we now rerun the first ovs-appctl
690 command above, e.g.:
691
692     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
693
694 then we see in the output that the destination has now been learned:
695
696                                 Resubmitted flow: unchanged
697                                 Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
698                                 Resubmitted  odp: drop
699                                 Rule: table=10 cookie=0 vlan_tci=0x0014/0x0fff,dl_dst=90:00:00:00:00:01
700                                 OpenFlow actions=load:0x2->NXM_NX_REG0[0..15]
701
702
703 Implementing Table 4: Output Processing
704 ---------------------------------------
705
706 At entry to stage 4, we know that register 0 contains either the
707 desired output port or is zero if the packet should be flooded.  We
708 also know that the packet's VLAN is in its 802.1Q header, even if the
709 VLAN was implicit because the packet came in on an access port.
710
711 The job of the final pipeline stage is to actually output packets.
712 The job is trivial for output to our trunk port p1:
713
714     ovs-ofctl add-flow br0 "table=4 reg0=1 actions=1"
715
716 For output to the access ports, we just have to strip the VLAN header
717 before outputting the packet:
718
719     ovs-ofctl add-flows br0 - <<'EOF'
720     table=4 reg0=2 actions=strip_vlan,2
721     table=4 reg0=3 actions=strip_vlan,3
722     table=4 reg0=4 actions=strip_vlan,4
723     EOF
724
725 The only slightly tricky part is flooding multicast and broadcast
726 packets and unicast packets with unlearned destinations.  For those,
727 we need to make sure that we only output the packets to the ports that
728 carry our packet's VLAN, and that we include the 802.1Q header in the
729 copy output to the trunk port but not in copies output to access
730 ports:
731
732     ovs-ofctl add-flows br0 - <<'EOF'
733     table=4 reg0=0 priority=99 dl_vlan=20 actions=1,strip_vlan,2
734     table=4 reg0=0 priority=99 dl_vlan=30 actions=1,strip_vlan,3,4
735     table=4 reg0=0 priority=50            actions=1
736     EOF
737
738 >>> Our rules rely on the standard OpenFlow behavior that an output
739     action will not forward a packet back out the port it came in on.
740     That is, if a packet comes in on p1, and we've learned that the
741     packet's destination MAC is also on p1, so that we end up with
742     "actions=1" as our actions, the switch will not forward the packet
743     back out its input port.  The multicast/broadcast/unknown
744     destination cases above also rely on this behavior.
745
746
747 ### Testing Table 4
748
749 ### EXAMPLE 1: Broadcast, Multicast, and Unknown Destination
750
751 Try tracing a broadcast packet arriving on p1 in VLAN 30:
752
753     ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=30
754
755 The interesting part of the output is the final line, which shows that
756 the switch would remove the 802.1Q header and then output the packet to
757 p3 and p4, which are access ports for VLAN 30:
758
759     Datapath actions: pop_vlan,3,4
760
761 Similarly, if we trace a broadcast packet arriving on p3:
762
763     ovs-appctl ofproto/trace br0 in_port=3,dl_dst=ff:ff:ff:ff:ff:ff
764
765 then we see that it is output to p1 with an 802.1Q tag and then to p4
766 without one:
767
768     Datapath actions: push_vlan(vid=30,pcp=0),1,pop_vlan,4
769
770 >>> Open vSwitch could simplify the datapath actions here to just
771     "4,push_vlan(vid=30,pcp=0),1" but it is not smart enough to do so.
772
773 The following are also broadcasts, but the result is to drop the
774 packets because the VLAN only belongs to the input port:
775
776     ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff
777     ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=55
778
779 Try some other broadcast cases on your own:
780
781     ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=20
782     ovs-appctl ofproto/trace br0 in_port=2,dl_dst=ff:ff:ff:ff:ff:ff
783     ovs-appctl ofproto/trace br0 in_port=4,dl_dst=ff:ff:ff:ff:ff:ff
784
785 You can see the same behavior with multicast packets and with unicast
786 packets whose destination has not been learned, e.g.:
787
788     ovs-appctl ofproto/trace br0 in_port=4,dl_dst=01:00:00:00:00:00
789     ovs-appctl ofproto/trace br0 in_port=1,dl_dst=90:12:34:56:78:90,dl_vlan=20
790     ovs-appctl ofproto/trace br0 in_port=1,dl_dst=90:12:34:56:78:90,dl_vlan=30
791
792
793 ### EXAMPLE 2: MAC Learning
794
795 Let's follow the same pattern as we did for table 3.  First learn a
796 MAC on port p1 in VLAN 30:
797
798     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
799
800 You can see from the last line of output that the packet's destination
801 is unknown, so it gets flooded to both p3 and p4, the other ports in
802 VLAN 30:
803
804     Datapath actions: pop_vlan,3,4
805
806 Then reverse the MACs and learn the first flow's destination on port
807 p4:
808
809     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
810
811 The last line of output shows that the this packet's destination is
812 known to be p1, as learned from our previous command:
813
814     Datapath actions: push_vlan(vid=30,pcp=0),1
815
816 Now, if we rerun our first command:
817
818     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
819
820 we can see that the result is no longer a flood but to the specified
821 learned destination port p4:
822
823     Datapath actions: pop_vlan,4
824
825
826 Contact 
827 =======
828
829 bugs@openvswitch.org
830 http://openvswitch.org/