Merge "master" into "ovn".
[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,
12 you 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 Getting Started
30 ---------------
31
32 This is a hands-on tutorial.  To get the most out of it, you will need
33 Open vSwitch binaries.  You do not, on the other hand, need any
34 physical networking hardware or even supervisor privilege on your
35 system.  Instead, we will use a script called `ovs-sandbox`, which
36 accompanies the tutorial, that constructs a software simulated network
37 environment based on Open vSwitch.
38
39 You can use `ovs-sandbox` three ways:
40
41   * If you have already installed Open vSwitch on your system, then
42     you should be able to just run `ovs-sandbox` from this directory
43     without any options.
44
45   * If you have not installed Open vSwitch (and you do not want to
46     install it), then you can build Open vSwitch according to the
47     instructions in [INSTALL.md], without installing it.  Then run
48     `./ovs-sandbox -b DIRECTORY` from this directory, substituting
49     the Open vSwitch build directory for `DIRECTORY`.
50
51   * As a slight variant on the latter, you can run `make sandbox`
52     from an Open vSwitch build directory.
53
54 When you run `ovs-sandbox`, it does the following:
55
56   1. **CAUTION:** Deletes any subdirectory of the current directory
57      named "sandbox" and any files in that directory.
58
59   2. Creates a new directory "sandbox" in the current directory.
60
61   3. Sets up special environment variables that ensure that Open
62      vSwitch programs will look inside the "sandbox" directory
63      instead of in the Open vSwitch installation directory.
64
65   4. If you are using a built but not installed Open vSwitch,
66      installs the Open vSwitch manpages in a subdirectory of
67      "sandbox" and adjusts the `MANPATH` environment variable to point
68      to this directory.  This means that you can use, for example,
69      `man ovs-vsctl` to see a manpage for the `ovs-vsctl` program that
70      you built.
71
72   5. Creates an empty Open vSwitch configuration database under
73      "sandbox".
74
75   6. Starts `ovsdb-server` running under "sandbox".
76
77   7. Starts `ovs-vswitchd` running under "sandbox", passing special
78      options that enable a special "dummy" mode for testing.
79
80   8. Starts a nested interactive shell inside "sandbox".
81
82 At this point, you can run all the usual Open vSwitch utilities from
83 the nested shell environment.  You can, for example, use `ovs-vsctl`
84 to create a bridge:
85
86     ovs-vsctl add-br br0
87
88 From Open vSwitch's perspective, the bridge that you create this way
89 is as real as any other.  You can, for example, connect it to an
90 OpenFlow controller or use `ovs-ofctl` to examine and modify it and
91 its OpenFlow flow table.  On the other hand, the bridge is not visible
92 to the operating system's network stack, so `ifconfig` or `ip` cannot
93 see it or affect it, which means that utilities like `ping` and
94 `tcpdump` will not work either.  (That has its good side, too: you
95 can't screw up your computer's network stack by manipulating a
96 sandboxed OVS.)
97
98 When you're done using OVS from the sandbox, exit the nested shell (by
99 entering the "exit" shell command or pressing Control+D).  This will
100 kill the daemons that `ovs-sandbox` started, but it leaves the "sandbox"
101 directory and its contents in place.
102
103 The sandbox directory contains log files for the Open vSwitch dameons.
104 You can examine them while you're running in the sandboxed environment
105 or after you exit.
106
107 Using GDB
108 ---------
109
110 GDB support is not required to go through the tutorial. It is added in case
111 user wants to explore the internals of OVS programs.
112
113 GDB can already be used to debug any running process, with the usual
114 'gdb <program> <process-id>' command.
115
116 'ovs-sandbox' also has a '-g' option for launching ovs-vswitchd under GDB.
117 This option can be handy for setting break points before ovs-vswitchd runs,
118 or for catching early segfaults. Similarly, a '-d' option can be used to
119 run ovsdb-server under GDB. Both options can be specified at the same time.
120
121 To avoid GDB mangling with the sandbox sub shell terminal, 'ovs-sandbox'
122 starts a new xterm to run each GDB session.  For systems that do not support
123 X windows, GDB support is effectively disabled.
124
125 When launching sandbox through the build tree's make file, the '-g' option
126 can be passed via the 'SANDBOXFLAGS' environment variable.
127 'make sandbox SANDBOXFLAGS=-g' will start the sandbox with ovs-vswitchd
128 running under GDB in its own xterm if X is available.
129
130 Motivation
131 ----------
132
133 The goal of this tutorial is to demonstrate the power of Open vSwitch
134 flow tables.  The tutorial works through the implementation of a
135 MAC-learning switch with VLAN trunk and access ports.  Outside of the
136 Open vSwitch features that we will discuss, OpenFlow provides at least
137 two ways to implement such a switch:
138
139   1. An OpenFlow controller to implement MAC learning in a
140      "reactive" fashion.  Whenever a new MAC appears on the switch,
141      or a MAC moves from one switch port to another, the controller
142      adjusts the OpenFlow flow table to match.
143
144   2. The "normal" action.  OpenFlow defines this action to submit a
145      packet to "the traditional non-OpenFlow pipeline of the
146      switch".  That is, if a flow uses this action, then the packets
147      in the flow go through the switch in the same way that they
148      would if OpenFlow was not configured on the switch.
149
150 Each of these approaches has unfortunate pitfalls.  In the first
151 approach, using an OpenFlow controller to implement MAC learning, has
152 a significant cost in terms of network bandwidth and latency.  It also
153 makes the controller more difficult to scale to large numbers of
154 switches, which is especially important in environments with thousands
155 of hypervisors (each of which contains a virtual OpenFlow switch).
156 MAC learning at an OpenFlow controller also behaves poorly if the
157 OpenFlow controller fails, slows down, or becomes unavailable due to
158 network problems.
159
160 The second approach, using the "normal" action, has different
161 problems.  First, little about the "normal" action is standardized, so
162 it behaves differently on switches from different vendors, and the
163 available features and how those features are configured (usually not
164 through OpenFlow) varies widely.  Second, "normal" does not work well
165 with other OpenFlow actions.  It is "all-or-nothing", with little
166 potential to adjust its behavior slightly or to compose it with other
167 features.
168
169
170 Scenario
171 --------
172
173 We will construct Open vSwitch flow tables for a VLAN-capable,
174 MAC-learning switch that has four ports:
175
176   * p1, a trunk port that carries all VLANs, on OpenFlow port 1.
177
178   * p2, an access port for VLAN 20, on OpenFlow port 2.
179
180   * p3 and p4, both access ports for VLAN 30, on OpenFlow ports 3
181     and 4, respectively.
182
183 > The ports' names are not significant.  You could call them eth1
184 > through eth4, or any other names you like.
185
186 > An OpenFlow switch always has a "local" port as well.  This
187 > scenario won't use the local port.
188
189 Our switch design will consist of five main flow tables, each of which
190 implements one stage in the switch pipeline:
191
192   Table 0: Admission control.
193
194   Table 1: VLAN input processing.
195
196   Table 2: Learn source MAC and VLAN for ingress port.
197
198   Table 3: Look up learned port for destination MAC and VLAN.
199
200   Table 4: Output processing.
201
202 The section below describes how to set up the scenario, followed by a
203 section for each OpenFlow table.
204
205 You can cut and paste the `ovs-vsctl` and `ovs-ofctl` commands in each
206 of the sections below into your `ovs-sandbox` shell.  They are also
207 available as shell scripts in this directory, named `t-setup`, `t-stage0`,
208 `t-stage1`, ..., `t-stage4`.  The `ovs-appctl` test commands are intended
209 for cutting and pasting and are not supplied separately.
210
211
212 Setup
213 -----
214
215 To get started, start `ovs-sandbox`.  Inside the interactive shell
216 that it starts, run this command:
217
218     ovs-vsctl add-br br0 -- set Bridge br0 fail-mode=secure
219
220 This command creates a new bridge "br0" and puts "br0" into so-called
221 "fail-secure" mode.  For our purpose, this just means that the
222 OpenFlow flow table starts out empty.
223
224 > If we did not do this, then the flow table would start out with a
225 > single flow that executes the "normal" action.  We could use that
226 > feature to yield a switch that behaves the same as the switch we
227 > are currently building, but with the caveats described under
228 > "Motivation" above.)
229
230 The new bridge has only one port on it so far, the "local port" br0.
231 We need to add p1, p2, p3, and p4.  A shell "for" loop is one way to
232 do it:
233
234     for i in 1 2 3 4; do
235         ovs-vsctl add-port br0 p$i -- set Interface p$i ofport_request=$i
236               ovs-ofctl mod-port br0 p$i up
237     done
238
239 In addition to adding a port, the `ovs-vsctl` command above sets its
240 "ofport_request" column to ensure that port p1 is assigned OpenFlow
241 port 1, p2 is assigned OpenFlow port 2, and so on.
242
243 > We could omit setting the ofport_request and let Open vSwitch
244 > choose port numbers for us, but it's convenient for the purposes
245 > of this tutorial because we can talk about OpenFlow port 1 and
246 > know that it corresponds to p1.
247
248 The `ovs-ofctl` command above brings up the simulated interfaces, which
249 are down initially, using an OpenFlow request.  The effect is similar
250 to `ifconfig up`, but the sandbox's interfaces are not visible to the
251 operating system and therefore `ifconfig` would not affect them.
252
253 We have not configured anything related to VLANs or MAC learning.
254 That's because we're going to implement those features in the flow
255 table.
256
257 To see what we've done so far to set up the scenario, you can run a
258 command like `ovs-vsctl show` or `ovs-ofctl show br0`.
259
260
261 Implementing Table 0: Admission control
262 ---------------------------------------
263
264 Table 0 is where packets enter the switch.  We use this stage to
265 discard packets that for one reason or another are invalid.  For
266 example, packets with a multicast source address are not valid, so we
267 can add a flow to drop them at ingress to the switch with:
268
269     ovs-ofctl add-flow br0 \
270         "table=0, dl_src=01:00:00:00:00:00/01:00:00:00:00:00, actions=drop"
271
272 A switch should also not forward IEEE 802.1D Spanning Tree Protocol
273 (STP) packets, so we can also add a flow to drop those and other
274 packets with reserved multicast protocols:
275
276     ovs-ofctl add-flow br0 \
277         "table=0, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0, actions=drop"
278
279 We could add flows to drop other protocols, but these demonstrate the
280 pattern.
281
282 We need one more flow, with a priority lower than the default, so that
283 flows that don't match either of the "drop" flows we added above go on
284 to pipeline stage 1 in OpenFlow table 1:
285
286     ovs-ofctl add-flow br0 "table=0, priority=0, actions=resubmit(,1)"
287
288 (The "resubmit" action is an Open vSwitch extension to OpenFlow.)
289
290
291 ### Testing Table 0
292
293 If we were using Open vSwitch to set up a physical or a virtual
294 switch, then we would naturally test it by sending packets through it
295 one way or another, perhaps with common network testing tools like
296 `ping` and `tcpdump` or more specialized tools like Scapy.  That's
297 difficult with our simulated switch, since it's not visible to the
298 operating system.
299
300 But our simulated switch has a few specialized testing tools.  The
301 most powerful of these tools is `ofproto/trace`.  Given a switch and
302 the specification of a flow, `ofproto/trace` shows, step-by-step, how
303 such a flow would be treated as it goes through the switch.
304
305
306 ### EXAMPLE 1
307
308 Try this command:
309
310     ovs-appctl ofproto/trace br0 in_port=1,dl_dst=01:80:c2:00:00:05
311
312 The output should look something like this:
313
314     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
315     Rule: table=0 cookie=0 dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0
316     OpenFlow actions=drop
317
318     Final flow: unchanged
319     Datapath actions: drop
320
321 The first block of lines describes an OpenFlow table lookup.  The
322 first line shows the fields used for the table lookup (which is mostly
323 zeros because that's the default if we don't specify everything).  The
324 second line gives the OpenFlow flow that the fields matched (called a
325 "rule" because that is the name used inside Open vSwitch for an
326 OpenFlow flow).  In this case, we see that this packet that has a
327 reserved multicast destination address matches the rule that drops
328 those packets.  The third line gives the rule's OpenFlow actions.
329
330 The second block of lines summarizes the results, which are not very
331 interesting here.
332
333
334 ### EXAMPLE 2
335
336 Try another command:
337
338     ovs-appctl ofproto/trace br0 in_port=1,dl_dst=01:80:c2:00:00:10
339
340 The output should be:
341
342     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
343     Rule: table=0 cookie=0 priority=0
344     OpenFlow actions=resubmit(,1)
345
346             Resubmitted flow: unchanged
347             Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
348             Resubmitted  odp: drop
349             No match
350
351     Final flow: unchanged
352     Datapath actions: drop
353
354 This time the flow we handed to `ofproto/trace` doesn't match any of
355 our "drop" rules, so it falls through to the low-priority "resubmit"
356 rule, which we see in the rule and the actions selected in the first
357 block.  The "resubmit" causes a second lookup in OpenFlow table 1,
358 described by the additional block of indented text in the output.  We
359 haven't yet added any flows to OpenFlow table 1, so no flow actually
360 matches in the second lookup.  Therefore, the packet is still actually
361 dropped, which means that the externally observable results would be
362 identical to our first example.
363
364
365 Implementing Table 1: VLAN Input Processing
366 -------------------------------------------
367
368 A packet that enters table 1 has already passed basic validation in
369 table 0.  The purpose of table 1 is validate the packet's VLAN, based
370 on the VLAN configuration of the switch port through which the packet
371 entered the switch.  We will also use it to attach a VLAN header to
372 packets that arrive on an access port, which allows later processing
373 stages to rely on the packet's VLAN always being part of the VLAN
374 header, reducing special cases.
375
376 Let's start by adding a low-priority flow that drops all packets,
377 before we add flows that pass through acceptable packets.  You can
378 think of this as a "default drop" rule:
379
380     ovs-ofctl add-flow br0 "table=1, priority=0, actions=drop"
381
382 Our trunk port p1, on OpenFlow port 1, is an easy case.  p1 accepts
383 any packet regardless of whether it has a VLAN header or what the VLAN
384 was, so we can add a flow that resubmits everything on input port 1 to
385 the next table:
386
387     ovs-ofctl add-flow br0 \
388         "table=1, priority=99, in_port=1, actions=resubmit(,2)"
389
390 On the access ports, we want to accept any packet that has no VLAN
391 header, tag it with the access port's VLAN number, and then pass it
392 along to the next stage:
393
394     ovs-ofctl add-flows br0 - <<'EOF'
395           table=1, priority=99, in_port=2, vlan_tci=0, actions=mod_vlan_vid:20, resubmit(,2)
396           table=1, priority=99, in_port=3, vlan_tci=0, actions=mod_vlan_vid:30, resubmit(,2)
397           table=1, priority=99, in_port=4, vlan_tci=0, actions=mod_vlan_vid:30, resubmit(,2)
398     EOF
399
400 We don't write any rules that match packets with 802.1Q that enter
401 this stage on any of the access ports, so the "default drop" rule we
402 added earlier causes them to be dropped, which is ordinarily what we
403 want for access ports.
404
405 > Another variation of access ports allows ingress of packets tagged
406 > with VLAN 0 (aka 802.1p priority tagged packets).  To allow such
407 > packets, replace "vlan_tci=0" by "vlan_tci=0/0xfff" above.
408
409
410 ### Testing Table 1
411
412 `ofproto/trace` allows us to test the ingress VLAN rules that we added
413 above.
414
415
416 ### EXAMPLE 1: Packet on Trunk Port
417
418 Here's a test of a packet coming in on the trunk port:
419
420     ovs-appctl ofproto/trace br0 in_port=1,vlan_tci=5
421
422 The output shows the lookup in table 0, the resubmit to table 1, and
423 the resubmit to table 2 (which does nothing because we haven't put
424 anything there yet):
425
426     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
427     Rule: table=0 cookie=0 priority=0
428     OpenFlow actions=resubmit(,1)
429
430             Resubmitted flow: unchanged
431             Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
432             Resubmitted  odp: drop
433             Rule: table=1 cookie=0 priority=99,in_port=1
434             OpenFlow actions=resubmit(,2)
435
436                     Resubmitted flow: unchanged
437                     Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
438                     Resubmitted  odp: drop
439                     No match
440
441     Final flow: unchanged
442     Datapath actions: drop
443
444
445 ### EXAMPLE 2: Valid Packet on Access Port
446
447 Here's a test of a valid packet (a packet without an 802.1Q header)
448 coming in on access port p2:
449
450     ovs-appctl ofproto/trace br0 in_port=2
451
452 The output is similar to that for the previous case, except that it
453 additionally tags the packet with p2's VLAN 20 before it passes it
454 along to table 2:
455
456     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
457     Rule: table=0 cookie=0 priority=0
458     OpenFlow actions=resubmit(,1)
459
460             Resubmitted flow: unchanged
461             Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
462             Resubmitted  odp: drop
463             Rule: table=1 cookie=0 priority=99,in_port=2,vlan_tci=0x0000
464             OpenFlow actions=mod_vlan_vid:20,resubmit(,2)
465
466                     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
467                     Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
468                     Resubmitted  odp: drop
469                     No match
470
471     Final flow: unchanged
472     Datapath actions: drop
473
474
475 ### EXAMPLE 3: Invalid Packet on Access Port
476
477 This tests an invalid packet (one that includes an 802.1Q header)
478 coming in on access port p2:
479
480     ovs-appctl ofproto/trace br0 in_port=2,vlan_tci=5
481
482 The output shows the packet matching the default drop rule:
483
484     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
485     Rule: table=0 cookie=0 priority=0
486     OpenFlow actions=resubmit(,1)
487
488             Resubmitted flow: unchanged
489             Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
490             Resubmitted  odp: drop
491             Rule: table=1 cookie=0 priority=0
492             OpenFlow actions=drop
493
494     Final flow: unchanged
495     Datapath actions: drop
496
497
498 Implementing Table 2: MAC+VLAN Learning for Ingress Port
499 --------------------------------------------------------
500
501 This table allows the switch we're implementing to learn that the
502 packet's source MAC is located on the packet's ingress port in the
503 packet's VLAN.
504
505 > This table is a good example why table 1 added a VLAN tag to
506 > packets that entered the switch through an access port.  We want
507 > to associate a MAC+VLAN with a port regardless of whether the VLAN
508 > in question was originally part of the packet or whether it was an
509 > assumed VLAN associated with an access port.
510
511 It only takes a single flow to do this.  The following command adds
512 it:
513
514     ovs-ofctl add-flow br0 \
515         "table=2 actions=learn(table=10, NXM_OF_VLAN_TCI[0..11], \
516                                NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], \
517                                load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]), \
518                          resubmit(,3)"
519
520 The "learn" action (an Open vSwitch extension to OpenFlow) modifies a
521 flow table based on the content of the flow currently being processed.
522 Here's how you can interpret each part of the "learn" action above:
523
524     table=10
525
526         Modify flow table 10.  This will be the MAC learning table.
527
528     NXM_OF_VLAN_TCI[0..11]
529
530         Make the flow that we add to flow table 10 match the same VLAN
531         ID that the packet we're currently processing contains.  This
532         effectively scopes the MAC learning entry to a single VLAN,
533         which is the ordinary behavior for a VLAN-aware switch.
534
535     NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[]
536
537         Make the flow that we add to flow table 10 match, as Ethernet
538         destination, the Ethernet source address of the packet we're
539         currently processing.
540
541     load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]
542
543         Whereas the preceding parts specify fields for the new flow to
544         match, this specifies an action for the flow to take when it
545         matches.  The action is for the flow to load the ingress port
546         number of the current packet into register 0 (a special field
547         that is an Open vSwitch extension to OpenFlow).
548
549 > A real use of "learn" for MAC learning would probably involve two
550 > additional elements.  First, the "learn" action would specify a
551 > hard_timeout for the new flow, to enable a learned MAC to
552 > eventually expire if no new packets were seen from a given source
553 > within a reasonable interval.  Second, one would usually want to
554 > limit resource consumption by using the Flow_Table table in the
555 > Open vSwitch configuration database to specify a maximum number of
556 > flows in table 10.
557
558 This definitely calls for examples.
559
560
561 ### Testing Table 2
562
563 ### EXAMPLE 1
564
565 Try the following test command:
566
567     ovs-appctl ofproto/trace br0 in_port=1,vlan_tci=20,dl_src=50:00:00:00:00:01 -generate
568
569 The output shows that "learn" was executed, but it isn't otherwise
570 informative, so we won't include it here.
571
572 The `-generate` keyword is new.  Ordinarily, `ofproto/trace` has no
573 side effects: "output" actions do not actually output packets, "learn"
574 actions do not actually modify the flow table, and so on.  With
575 `-generate`, though, `ofproto/trace` does execute "learn" actions.
576 That's important now, because we want to see the effect of the "learn"
577 action on table 10.  You can see that by running:
578
579     ovs-ofctl dump-flows br0 table=10
580
581 which (omitting the "duration" and "idle_age" fields, which will vary
582 based on how soon you ran this command after the previous one, as well
583 as some other uninteresting fields) prints something like:
584
585     NXST_FLOW reply (xid=0x4):
586      table=10, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
587
588 You can see that the packet coming in on VLAN 20 with source MAC
589 50:00:00:00:00:01 became a flow that matches VLAN 20 (written in
590 hexadecimal) and destination MAC 50:00:00:00:00:01.  The flow loads
591 port number 1, the input port for the flow we tested, into register 0.
592
593
594 ### EXAMPLE 2
595
596 Here's a second test command:
597
598     ovs-appctl ofproto/trace br0 in_port=2,dl_src=50:00:00:00:00:01 -generate
599
600 The flow that this command tests has the same source MAC and VLAN as
601 example 1, although the VLAN comes from an access port VLAN rather
602 than an 802.1Q header.  If we again dump the flows for table 10 with:
603
604     ovs-ofctl dump-flows br0 table=10
605
606 then we see that the flow we saw previously has changed to indicate
607 that the learned port is port 2, as we would expect:
608
609     NXST_FLOW reply (xid=0x4):
610      table=10, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:01 actions=load:0x2->NXM_NX_REG0[0..15]
611
612
613 Implementing Table 3: Look Up Destination Port
614 ----------------------------------------------
615
616 This table figures out what port we should send the packet to based on
617 the destination MAC and VLAN.  That is, if we've learned the location
618 of the destination (from table 2 processing some previous packet with
619 that destination as its source), then we want to send the packet
620 there.
621
622 We need only one flow to do the lookup:
623
624     ovs-ofctl add-flow br0 \
625         "table=3 priority=50 actions=resubmit(,10), resubmit(,4)"
626
627 The flow's first action resubmits to table 10, the table that the
628 "learn" action modifies.  As you saw previously, the learned flows in
629 this table write the learned port into register 0.  If the destination
630 for our packet hasn't been learned, then there will be no matching
631 flow, and so the "resubmit" turns into a no-op.  Because registers are
632 initialized to 0, we can use a register 0 value of 0 in our next
633 pipeline stage as a signal to flood the packet.
634
635 The second action resubmits to table 4, continuing to the next
636 pipeline stage.
637
638 We can add another flow to skip the learning table lookup for
639 multicast and broadcast packets, since those should always be flooded:
640
641     ovs-ofctl add-flow br0 \
642         "table=3 priority=99 dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 \
643           actions=resubmit(,4)"
644
645 > We don't strictly need to add this flow, because multicast
646 > addresses will never show up in our learning table.  (In turn,
647 > that's because we put a flow into table 0 to drop packets that
648 > have a multicast source address.)
649
650
651 ### Testing Table 3
652
653 ### EXAMPLE
654
655 Here's a command that should cause OVS to learn that f0:00:00:00:00:01
656 is on p1 in VLAN 20:
657
658     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
659
660 Here's an excerpt from the output that shows (from the "no match"
661 looking up the resubmit to table 10) that the flow's destination was
662 unknown:
663
664                         Resubmitted flow: unchanged
665                         Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
666                         Resubmitted  odp: drop
667                         Rule: table=3 cookie=0 priority=50
668                         OpenFlow actions=resubmit(,10),resubmit(,4)
669
670                                 Resubmitted flow: unchanged
671                                 Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
672                                 Resubmitted  odp: drop
673                                 No match
674
675 You can verify that the packet's source was learned two ways.  The
676 most direct way is to dump the learning table with:
677
678     ovs-ofctl dump-flows br0 table=10
679
680 which ought to show roughly the following, with extraneous details
681 removed:
682
683     table=10, vlan_tci=0x0014/0x0fff,dl_dst=f0:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
684
685 > If you tried the examples for the previous step, or if you did
686 > some of your own experiments, then you might see additional flows
687 > there.  These additional flows are harmless.  If they bother you,
688 > then you can remove them with `ovs-ofctl del-flows br0 table=10`.
689
690 The other way is to inject a packet to take advantage of the learning
691 entry.  For example, we can inject a packet on p2 whose destination is
692 the MAC address that we just learned on p1:
693
694     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
695
696 Here's an interesting excerpt from that command's output.  This group
697 of lines traces the "resubmit(,10)", showing that the packet matched
698 the learned flow for the first MAC we used, loading the OpenFlow port
699 number for the learned port p1 into register 0:
700
701                                 Resubmitted flow: unchanged
702                                 Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
703                                 Resubmitted  odp: drop
704                                 Rule: table=10 cookie=0 vlan_tci=0x0014/0x0fff,dl_dst=f0:00:00:00:00:01
705                                 OpenFlow actions=load:0x1->NXM_NX_REG0[0..15]
706
707
708 If you read the commands above carefully, then you might have noticed
709 that they simply have the Ethernet source and destination addresses
710 exchanged.  That means that if we now rerun the first `ovs-appctl`
711 command above, e.g.:
712
713     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
714
715 then we see in the output that the destination has now been learned:
716
717                                 Resubmitted flow: unchanged
718                                 Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
719                                 Resubmitted  odp: drop
720                                 Rule: table=10 cookie=0 vlan_tci=0x0014/0x0fff,dl_dst=90:00:00:00:00:01
721                                 OpenFlow actions=load:0x2->NXM_NX_REG0[0..15]
722
723
724 Implementing Table 4: Output Processing
725 ---------------------------------------
726
727 At entry to stage 4, we know that register 0 contains either the
728 desired output port or is zero if the packet should be flooded.  We
729 also know that the packet's VLAN is in its 802.1Q header, even if the
730 VLAN was implicit because the packet came in on an access port.
731
732 The job of the final pipeline stage is to actually output packets.
733 The job is trivial for output to our trunk port p1:
734
735     ovs-ofctl add-flow br0 "table=4 reg0=1 actions=1"
736
737 For output to the access ports, we just have to strip the VLAN header
738 before outputting the packet:
739
740     ovs-ofctl add-flows br0 - <<'EOF'
741     table=4 reg0=2 actions=strip_vlan,2
742     table=4 reg0=3 actions=strip_vlan,3
743     table=4 reg0=4 actions=strip_vlan,4
744     EOF
745
746 The only slightly tricky part is flooding multicast and broadcast
747 packets and unicast packets with unlearned destinations.  For those,
748 we need to make sure that we only output the packets to the ports that
749 carry our packet's VLAN, and that we include the 802.1Q header in the
750 copy output to the trunk port but not in copies output to access
751 ports:
752
753     ovs-ofctl add-flows br0 - <<'EOF'
754     table=4 reg0=0 priority=99 dl_vlan=20 actions=1,strip_vlan,2
755     table=4 reg0=0 priority=99 dl_vlan=30 actions=1,strip_vlan,3,4
756     table=4 reg0=0 priority=50            actions=1
757     EOF
758
759 > Our rules rely on the standard OpenFlow behavior that an output
760 > action will not forward a packet back out the port it came in on.
761 > That is, if a packet comes in on p1, and we've learned that the
762 > packet's destination MAC is also on p1, so that we end up with
763 > "actions=1" as our actions, the switch will not forward the packet
764 > back out its input port.  The multicast/broadcast/unknown
765 > destination cases above also rely on this behavior.
766
767
768 ### Testing Table 4
769
770 ### EXAMPLE 1: Broadcast, Multicast, and Unknown Destination
771
772 Try tracing a broadcast packet arriving on p1 in VLAN 30:
773
774     ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=30
775
776 The interesting part of the output is the final line, which shows that
777 the switch would remove the 802.1Q header and then output the packet to
778 p3 and p4, which are access ports for VLAN 30:
779
780     Datapath actions: pop_vlan,3,4
781
782 Similarly, if we trace a broadcast packet arriving on p3:
783
784     ovs-appctl ofproto/trace br0 in_port=3,dl_dst=ff:ff:ff:ff:ff:ff
785
786 then we see that it is output to p1 with an 802.1Q tag and then to p4
787 without one:
788
789     Datapath actions: push_vlan(vid=30,pcp=0),1,pop_vlan,4
790
791 > Open vSwitch could simplify the datapath actions here to just
792 > "4,push_vlan(vid=30,pcp=0),1" but it is not smart enough to do so.
793
794 The following are also broadcasts, but the result is to drop the
795 packets because the VLAN only belongs to the input port:
796
797     ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff
798     ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=55
799
800 Try some other broadcast cases on your own:
801
802     ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=20
803     ovs-appctl ofproto/trace br0 in_port=2,dl_dst=ff:ff:ff:ff:ff:ff
804     ovs-appctl ofproto/trace br0 in_port=4,dl_dst=ff:ff:ff:ff:ff:ff
805
806 You can see the same behavior with multicast packets and with unicast
807 packets whose destination has not been learned, e.g.:
808
809     ovs-appctl ofproto/trace br0 in_port=4,dl_dst=01:00:00:00:00:00
810     ovs-appctl ofproto/trace br0 in_port=1,dl_dst=90:12:34:56:78:90,dl_vlan=20
811     ovs-appctl ofproto/trace br0 in_port=1,dl_dst=90:12:34:56:78:90,dl_vlan=30
812
813
814 ### EXAMPLE 2: MAC Learning
815
816 Let's follow the same pattern as we did for table 3.  First learn a
817 MAC on port p1 in VLAN 30:
818
819     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
820
821 You can see from the last line of output that the packet's destination
822 is unknown, so it gets flooded to both p3 and p4, the other ports in
823 VLAN 30:
824
825     Datapath actions: pop_vlan,3,4
826
827 Then reverse the MACs and learn the first flow's destination on port
828 p4:
829
830     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
831
832 The last line of output shows that the this packet's destination is
833 known to be p1, as learned from our previous command:
834
835     Datapath actions: push_vlan(vid=30,pcp=0),1
836
837 Now, if we rerun our first command:
838
839     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
840
841 we can see that the result is no longer a flood but to the specified
842 learned destination port p4:
843
844     Datapath actions: pop_vlan,4
845
846
847 Contact 
848 =======
849
850 bugs@openvswitch.org
851 http://openvswitch.org/
852
853 [INSTALL.md]:../INSTALL.md