[ovs-dev] [PATCH ovn 1/4] Documentation cleanup: tutorial section
nusiddiq at redhat.com
nusiddiq at redhat.com
Wed Jun 12 07:18:22 UTC 2019
From: Numan Siddique <nusiddiq at redhat.com>
Also deleted the contents of Documentation/howto/ipsec.rst
and Documentation/howto/ssl.rst and instead updated them
to refer to the Open vSwitch documentation.
Signed-off-by: Numan Siddique <nusiddiq at redhat.com>
---
Documentation/automake.mk | 4 -
Documentation/howto/ipsec.rst | 167 +--
Documentation/howto/ssl.rst | 311 +----
Documentation/index.rst | 6 +-
Documentation/tutorials/faucet.rst | 1436 ---------------------
Documentation/tutorials/index.rst | 4 -
Documentation/tutorials/ipsec.rst | 347 -----
Documentation/tutorials/ovn-ipsec.rst | 4 +-
Documentation/tutorials/ovn-sandbox.rst | 8 +-
Documentation/tutorials/ovs-advanced.rst | 941 --------------
Documentation/tutorials/ovs-conntrack.rst | 572 --------
11 files changed, 9 insertions(+), 3791 deletions(-)
delete mode 100644 Documentation/tutorials/faucet.rst
delete mode 100644 Documentation/tutorials/ipsec.rst
delete mode 100644 Documentation/tutorials/ovs-advanced.rst
delete mode 100644 Documentation/tutorials/ovs-conntrack.rst
diff --git a/Documentation/automake.mk b/Documentation/automake.mk
index a5ef29252..181a69cab 100644
--- a/Documentation/automake.mk
+++ b/Documentation/automake.mk
@@ -22,12 +22,8 @@ DOC_SOURCE = \
Documentation/intro/install/windows.rst \
Documentation/intro/install/xenserver.rst \
Documentation/tutorials/index.rst \
- Documentation/tutorials/faucet.rst \
- Documentation/tutorials/ovs-advanced.rst \
Documentation/tutorials/ovn-openstack.rst \
Documentation/tutorials/ovn-sandbox.rst \
- Documentation/tutorials/ovs-conntrack.rst \
- Documentation/tutorials/ipsec.rst \
Documentation/tutorials/ovn-ipsec.rst \
Documentation/tutorials/ovn-rbac.rst \
Documentation/topics/index.rst \
diff --git a/Documentation/howto/ipsec.rst b/Documentation/howto/ipsec.rst
index 17153ac2b..7730b5050 100644
--- a/Documentation/howto/ipsec.rst
+++ b/Documentation/howto/ipsec.rst
@@ -25,170 +25,5 @@
Encrypt Open vSwitch Tunnels with IPsec
=======================================
-This document gives detailed description on the OVS IPsec tunnel and its
-configuration modes. If you want to follow a step-by-step guide to run and
-test IPsec tunnel, please refer to :doc:`/tutorials/ipsec`.
+Please refer to the Open vSwitch documentation on ipsec.
-Overview
---------
-
-Why do encryption?
-~~~~~~~~~~~~~~~~~~
-
-OVS tunnel packets are transported from one machine to another. Along the path,
-the packets are processed by physical routers and physical switches. There are
-risks that these physical devices might read or write the contents of the
-tunnel packets. IPsec encrypts IP payload and prevents the malicious party
-sniffing or manipulating the tunnel traffic.
-
-OVS IPsec
-~~~~~~~~~
-
-OVS IPsec aims to provide a simple interface for user to add encryption on OVS
-tunnels. It supports GRE, GENEVE, VXLAN, and STT tunnel. The IPsec
-configuration is done by setting options of the tunnel interface and
-other_config of Open_vSwitch. You can choose different authentication methods
-and plaintext tunnel policies based on your requirements.
-
-OVS does not currently provide any support for IPsec encryption for traffic not
-encapsulated in a tunnel.
-
-Configuration
--------------
-
-Authentication Methods
-~~~~~~~~~~~~~~~~~~~~~~
-
-Hosts of the IPsec tunnel need to authenticate each other to build a secure
-channel. There are three authentication methods:
-
-1) You can use a pre-shared key (PSK) to do authentication. In both hosts, set
- the same PSK value. This PSK is like your password. You should never reveal
- it to untrusted parties. This method is easier to use but less secure than
- the certificate-based methods::
-
- $ ovs-vsctl add-port br0 ipsec_gre0 -- \
- set interface ipsec_gre0 type=gre \
- options:remote_ip=2.2.2.2 \
- options:psk=swordfish
-
-2) You can use a self-signed certificate to do authentication. In each host,
- generate a certificate and the paired private key. Copy the certificate of
- the remote host to the local host and configure the OVS as following::
-
- $ ovs-vsctl set Open_vSwitch . \
- other_config:certificate=/path/to/local_cert.pem \
- other_config:private_key=/path/to/priv_key.pem
- $ ovs-vsctl add-port br0 ipsec_gre0 -- \
- set interface ipsec_gre0 type=gre \
- options:remote_ip=2.2.2.2 \
- options:remote_cert=/path/to/remote_cert.pem
-
- `local_cert.pem` is the certificate of the local host. `priv_key.pem`
- is the private key of the local host. `priv_key.pem` needs to be stored in
- a secure location. `remote_cert.pem` is the certificate of the remote host.
-
- .. note::
-
- OVS IPsec requires x.509 version 3 certificate with the subjectAltName
- DNS field setting the same string as the common name (CN) field. You can
- follow the tutorial in :doc:`/tutorials/ipsec` and use ovs-pki(8) to
- generate compatible certificate and key.
-
- (Before OVS version 2.10.90, ovs-pki(8) did not generate x.509 v3
- certificates, so if your existing PKI was generated by an older version,
- it is not suitable for this purpose.)
-
-3) You can also use CA-signed certificate to do authentication. First, you need
- to create a CA certificate and sign each host certificate with the CA key
- (please see :doc:`/tutorials/ipsec`). Copy the CA certificate to each
- host and configure the OVS as following::
-
- $ ovs-vsctl set Open_vSwitch . \
- other_config:certificate=/path/to/local_cert.pem \
- other_config:private_key=/path/to/priv_key.pem \
- other_config:ca_cert=/path/to/ca_cert.pem
- $ ovs-vsctl add-port br0 ipsec_gre0 -- \
- set interface ipsec_gre0 type=gre \
- options:remote_ip=2.2.2.2 \
- options:remote_name=remote_cn
-
- `ca_cert.pem` is the CA certificate. You need to set `remote_cn` as the
- common name (CN) of the remote host's certificate so that only the
- certificate with the expected CN can be trusted in this connection. It is
- preferable to use this method than 2) if there are many remote hosts since
- you don't have to copy every remote certificate to the local host.
-
- .. note::
-
- When using certificate-based authentication, you should not set psk in
- the interface options. When using psk-based authentication, you should
- not set certificate, private_key, ca_cert, remote_cert, and remote_name.
-
-Plaintext Policies
-~~~~~~~~~~~~~~~~~~
-
-When an IPsec tunnel is configured in this database, multiple independent
-components take responsibility for implementing it. ``ovs-vswitchd`` and its
-datapath handle packet forwarding to the tunnel and a separate daemon pushes
-the tunnel's IPsec policy configuration to the kernel or other entity that
-implements it. There is a race: if the former configuration completes before
-the latter, then packets sent by the local host over the tunnel can be
-transmitted in plaintext. Using this setting, OVS users can avoid this
-undesirable situation.
-
-1) The default setting allows unencrypted packets to be sent before IPsec
- completes negotiation::
-
- $ ovs-vsctl add-port br0 ipsec_gre0 -- \
- set interface ipsec_gre0 type=gre \
- options:remote_ip=2.2.2.2 \
- options:psk=swordfish
-
- This setting should be used only and only if tunnel configuration is static
- and/or if there is firewall that can drop the plain packets that
- occasionally leak the tunnel unencrypted on OVSDB (re)configuration events.
-
-2) Setiing ipsec_skb_mark drops unencrypted packets by using skb_mark of
- tunnel packets::
-
- $ ovs-vsctl set Open_vSwitch . other_config:ipsec_skb_mark=0/1
- $ ovs-vsctl add-port br0 ipsec_gre0 -- \
- set interface ipsec_gre0 type=gre \
- options:remote_ip=2.2.2.2 \
- options:psk=swordfish
-
- OVS IPsec drops unencrypted packets which carry the same skb_mark as
- `ipsec_skb_mark`. By setting the ipsec_skb_mark as 0/1, OVS IPsec prevents
- all unencrypted tunnel packets leaving the host since the default skb_mark
- value for tunnel packets are 0. This affects all OVS tunnels including those
- without IPsec being set up. You can install OpenFlow rules to whitelist
- those non-IPsec tunnels by setting the skb_mark of the tunnel traffic as
- non-zero value.
-
-3) Setting `ipsec_skb_mark` as 1/1 only drops tunnel packets with skb_mark
- value being 1::
-
- $ ovs-vsctl set Open_vSwitch . other_config:ipsec_skb_mark=1/1
- $ ovs-vsctl add-port br0 ipsec_gre0 -- \
- set interface ipsec_gre0 type=gre \
- options:remote_ip=2.2.2.2 \
- options:psk=swordfish
-
- Opposite to 2), this setting passes through unencrypted tunnel packets by
- default. To drop unencrypted IPsec tunnel traffic, you need to explicitly
- set skb_mark to a non-zero value for those tunnel traffic by installing
- OpenFlow rules.
-
-Bug Reporting
--------------
-
-If you think you may have found a bug with security implications, like
-
-1) IPsec protected tunnel accepted packets that came unencrypted; OR
-2) IPsec protected tunnel allowed packets to leave unencrypted
-
-then please report such bugs according to :doc:`/internals/security`.
-
-If the bug does not have security implications, then report it according to
-instructions in :doc:`/internals/bugs`.
diff --git a/Documentation/howto/ssl.rst b/Documentation/howto/ssl.rst
index 3085206fb..c2c540435 100644
--- a/Documentation/howto/ssl.rst
+++ b/Documentation/howto/ssl.rst
@@ -25,314 +25,5 @@
Open vSwitch with SSL
=====================
-If you plan to configure Open vSwitch to connect across the network to an
-OpenFlow controller, then we recommend that you build Open vSwitch with
-OpenSSL. SSL support ensures integrity and confidentiality of the OpenFlow
-connections, increasing network security.
+Please refer to the Open vSwitch documentation on SSL.
-This document describes how to configure an Open vSwitch to connect to an
-OpenFlow controller over SSL. Refer to :doc:`/intro/install/general`. for
-instructions on building Open vSwitch with SSL support.
-
-Open vSwitch uses TLS version 1.0 or later (TLSv1), as specified by RFC 2246,
-which is very similar to SSL version 3.0. TLSv1 was released in January 1999,
-so all current software and hardware should implement it.
-
-This document assumes basic familiarity with public-key cryptography and
-public-key infrastructure.
-
-SSL Concepts for OpenFlow
--------------------------
-
-This section is an introduction to the public-key infrastructure architectures
-that Open vSwitch supports for SSL authentication.
-
-To connect over SSL, every Open vSwitch must have a unique private/public key
-pair and a certificate that signs that public key. Typically, the Open vSwitch
-generates its own public/private key pair. There are two common ways to obtain
-a certificate for a switch:
-
-* Self-signed certificates: The Open vSwitch signs its certificate with its own
- private key. In this case, each switch must be individually approved by the
- OpenFlow controller(s), since there is no central authority.
-
- This is the only switch PKI model currently supported by NOX
- (http://noxrepo.org).
-
-* Switch certificate authority: A certificate authority (the "switch CA") signs
- each Open vSwitch's public key. The OpenFlow controllers then check that any
- connecting switches' certificates are signed by that certificate authority.
-
- This is the only switch PKI model supported by the simple OpenFlow controller
- included with Open vSwitch.
-
-Each Open vSwitch must also have a copy of the CA certificate for the
-certificate authority that signs OpenFlow controllers' keys (the "controller
-CA" certificate). Typically, the same controller CA certificate is installed
-on all of the switches within a given administrative unit. There are two
-common ways for a switch to obtain the controller CA certificate:
-
-* Manually copy the certificate to the switch through some secure means, e.g.
- using a USB flash drive, or over the network with "scp", or even FTP or HTTP
- followed by manual verification.
-
-* Open vSwitch "bootstrap" mode, in which Open vSwitch accepts and saves the
- controller CA certificate that it obtains from the OpenFlow controller on its
- first connection. Thereafter the switch will only connect to controllers
- signed by the same CA certificate.
-
-Establishing a Public Key Infrastructure
-----------------------------------------
-
-Open vSwitch can make use of your existing public key infrastructure. If you
-already have a PKI, you may skip forward to the next section. Otherwise, if
-you do not have a PKI, the ovs-pki script included with Open vSwitch can help.
-To create an initial PKI structure, invoke it as:
-
-::
-
- $ ovs-pki init
-
-This will create and populate a new PKI directory. The default location for
-the PKI directory depends on how the Open vSwitch tree was configured (to see
-the configured default, look for the ``--dir`` option description in the output
-of ``ovs-pki --help``).
-
-The pki directory contains two important subdirectories. The `controllerca`
-subdirectory contains controller CA files, including the following:
-
-`cacert.pem`
- Root certificate for the controller certificate authority. Each Open vSwitch
- must have a copy of this file to allow it to authenticate valid controllers.
-
-`private/cakey.pem`
- Private signing key for the controller certificate authority. This file must
- be kept secret. There is no need for switches or controllers to have a copy
- of it.
-
-The `switchca` subdirectory contains switch CA files, analogous to those in the
-`controllerca` subdirectory:
-
-`cacert.pem`
- Root certificate for the switch certificate authority. The OpenFlow
- controller must have this file to enable it to authenticate valid switches.
-
-`private/cakey.pem`
- Private signing key for the switch certificate authority. This file must be
- kept secret. There is no need for switches or controllers to have a copy of
- it.
-
-After you create the initial structure, you can create keys and certificates
-for switches and controllers with ovs-pki. Refer to the ovs-pki(8) manage for
-complete details. A few examples of its use follow:
-
-Controller Key Generation
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-To create a controller private key and certificate in files named
-ctl-privkey.pem and ctl-cert.pem, run the following on the machine that
-contains the PKI structure:
-
-::
-
- $ ovs-pki req+sign ctl controller
-
-ctl-privkey.pem and ctl-cert.pem would need to be copied to the controller for
-its use at runtime. If, for testing purposes, you were to use
-ovs-testcontroller, the simple OpenFlow controller included with Open vSwitch,
-then the --private-key and --certificate options, respectively, would point to
-these files.
-
-It is very important to make sure that no stray copies of ctl-privkey.pem are
-created, because they could be used to impersonate the controller.
-
-Switch Key Generation with Self-Signed Certificates
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-If you are using self-signed certificates (see "SSL Concepts for OpenFlow"),
-this is one way to create an acceptable certificate for your controller to
-approve.
-
-1. Run the following command on the Open vSwitch itself::
-
- $ ovs-pki self-sign sc
-
- .. note::
- This command does not require a copy of any of the PKI files generated by
- ``ovs-pki init``, and you should not copy them to the switch because some
- of them have contents that must remain secret for security.)
-
- The ``ovs-pki self-sign`` command has the following output:
-
- sc-privkey.pem
- the switch private key file. For security, the contents of this file must
- remain secret. There is ordinarily no need to copy this file off the Open
- vSwitch.
-
- sc-cert.pem
- the switch certificate, signed by the switch's own private key. Its
- contents are not a secret.
-
-2. Optionally, copy `controllerca/cacert.pem` from the machine that has the
- OpenFlow PKI structure and verify that it is correct. (Otherwise, you will
- have to use CA certificate bootstrapping when you configure Open vSwitch in
- the next step.)
-
-3. Configure Open vSwitch to use the keys and certificates (see "Configuring
- SSL Support", below).
-
-Switch Key Generation with a Switch PKI (Easy Method)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-If you are using a switch PKI (see "SSL Concepts for OpenFlow", above), this
-method of switch key generation is a little easier than the alternate method
-described below, but it is also a little less secure because it requires
-copying a sensitive private key from file from the machine hosting the PKI to
-the switch.
-
-1. Run the following on the machine that contains the PKI structure::
-
- $ ovs-pki req+sign sc switch
-
- This command has the following output:
-
- sc-privkey.pem
- the switch private key file. For security, the contents of this file must
- remain secret.
-
- sc-cert.pem
- the switch certificate. Its contents are not a secret.
-
-2. Copy sc-privkey.pem and sc-cert.pem, plus controllerca/cacert.pem, to the
- Open vSwitch.
-
-3. Delete the copies of sc-privkey.pem and sc-cert.pem on the PKI machine and
- any other copies that may have been made in transit. It is very important
- to make sure that there are no stray copies of sc-privkey.pem, because they
- could be used to impersonate the switch.
-
- .. warning::
- Don't delete controllerca/cacert.pem! It is not security-sensitive and
- you will need it to configure additional switches.
-
-4. Configure Open vSwitch to use the keys and certificates (see "Configuring
- SSL Support", below).
-
-Switch Key Generation with a Switch PKI (More Secure)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-If you are using a switch PKI (see "SSL Concepts for OpenFlow", above), then,
-compared to the previous method, the method described here takes a little more
-work, but it does not involve copying the private key from one machine to
-another, so it may also be a little more secure.
-
-1. Run the following command on the Open vSwitch itself::
-
- $ ovs-pki req sc
-
- .. note::
- This command does not require a copy of any of the PKI files generated by
- "ovs-pki init", and you should not copy them to the switch because some of
- them have contents that must remain secret for security.
-
- The "ovs-pki req" command has the following output:
-
- sc-privkey.pem
- the switch private key file. For security, the contents of this file must
- remain secret. There is ordinarily no need to copy this file off the Open
- vSwitch.
-
- sc-req.pem
- the switch "certificate request", which is essentially the switch's public
- key. Its contents are not a secret.
-
- a fingerprint
- this is output on stdout.
-
-2. Write the fingerprint down on a slip of paper and copy `sc-req.pem` to the
- machine that contains the PKI structure.
-
-3. On the machine that contains the PKI structure, run::
-
- $ ovs-pki sign sc switch
-
- This command will output a fingerprint to stdout and request that you verify
- it. Check that it is the same as the fingerprint that you wrote down on the
- slip of paper before you answer "yes".
-
- ``ovs-pki sign`` creates a file named `sc-cert.pem`, which is the switch
- certificate. Its contents are not a secret.
-
-4. Copy the generated `sc-cert.pem`, plus `controllerca/cacert.pem` from the
- PKI structure, to the Open vSwitch, and verify that they were copied
- correctly.
-
- You may delete `sc-cert.pem` from the machine that hosts the PKI
- structure now, although it is not important that you do so.
-
- .. warning::
- Don't delete `controllerca/cacert.pem`! It is not security-sensitive and
- you will need it to configure additional switches.
-
-5. Configure Open vSwitch to use the keys and certificates (see "Configuring
- SSL Support", below).
-
-Configuring SSL Support
------------------------
-
-SSL configuration requires three additional configuration files. The first two
-of these are unique to each Open vSwitch. If you used the instructions above
-to build your PKI, then these files will be named `sc-privkey.pem` and
-`sc-cert.pem`, respectively:
-
-- A private key file, which contains the private half of an RSA or DSA key.
-
- This file can be generated on the Open vSwitch itself, for the greatest
- security, or it can be generated elsewhere and copied to the Open vSwitch.
-
- The contents of the private key file are secret and must not be exposed.
-
-- A certificate file, which certifies that the private key is that of a
- trustworthy Open vSwitch.
-
- This file has to be generated on a machine that has the private key for the
- switch certification authority, which should not be an Open vSwitch; ideally,
- it should be a machine that is not networked at all.
-
- The certificate file itself is not a secret.
-
-The third configuration file is typically the same across all the switches in a
-given administrative unit. If you used the instructions above to build your
-PKI, then this file will be named `cacert.pem`:
-
-- The root certificate for the controller certificate authority. The Open
- vSwitch verifies it that is authorized to connect to an OpenFlow controller
- by verifying a signature against this CA certificate.
-
-Once you have these files, configure ovs-vswitchd to use them using the
-``ovs-vsctl set-ssl`` command, e.g.::
-
- $ ovs-vsctl set-ssl /etc/openvswitch/sc-privkey.pem \
- /etc/openvswitch/sc-cert.pem /etc/openvswitch/cacert.pem
-
-Substitute the correct file names, of course, if they differ from the ones used
-above. You should use absolute file names (ones that begin with ``/``),
-because ovs-vswitchd's current directory is unrelated to the one from which you
-run ovs-vsctl.
-
-If you are using self-signed certificates (see "SSL Concepts for OpenFlow") and
-you did not copy controllerca/cacert.pem from the PKI machine to the Open
-vSwitch, then add the ``--bootstrap`` option, e.g.::
-
- $ ovs-vsctl -- --bootstrap set-ssl /etc/openvswitch/sc-privkey.pem \
- /etc/openvswitch/sc-cert.pem /etc/openvswitch/cacert.pem
-
-After you have added all of these configuration keys, you may specify ``ssl:``
-connection methods elsewhere in the configuration database. ``tcp:`` connection
-methods are still allowed even after SSL has been configured, so for security
-you should use only ``ssl:`` connections.
-
-Reporting Bugs
---------------
-
-Report problems to bugs at openvswitch.org.
diff --git a/Documentation/index.rst b/Documentation/index.rst
index 78b7d89b0..192ed7631 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -59,12 +59,8 @@ vSwitch? Start here.
:doc:`intro/install/windows` |
:doc:`intro/install/xenserver`
-- **Tutorials:** :doc:`tutorials/faucet` |
- :doc:`tutorials/ovs-advanced` |
- :doc:`tutorials/ovn-sandbox` |
+- **Tutorials:** :doc:`tutorials/ovn-sandbox` |
:doc:`tutorials/ovn-openstack` |
- :doc:`tutorials/ovs-conntrack` |
- :doc:`tutorials/ipsec` |
:doc:`tutorials/ovn-ipsec` |
:doc:`tutorials/ovn-rbac`
diff --git a/Documentation/tutorials/faucet.rst b/Documentation/tutorials/faucet.rst
deleted file mode 100644
index 9696dfd02..000000000
--- a/Documentation/tutorials/faucet.rst
+++ /dev/null
@@ -1,1436 +0,0 @@
-..
- Licensed under the Apache License, Version 2.0 (the "License"); you may
- not use this file except in compliance with the License. You may obtain
- a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- License for the specific language governing permissions and limitations
- under the License.
-
- Convention for heading levels in Open vSwitch documentation:
-
- ======= Heading 0 (reserved for the title in a document)
- ------- Heading 1
- ~~~~~~~ Heading 2
- +++++++ Heading 3
- ''''''' Heading 4
-
- Avoid deeper levels because they do not render well.
-
-===================
-OVS Faucet Tutorial
-===================
-
-This tutorial demonstrates how Open vSwitch works with a general-purpose
-OpenFlow controller, using the Faucet controller as a simple way to get
-started. It was tested with the "master" branch of Open vSwitch and version
-1.6.15 of Faucet. It does not use advanced or recently added features in OVS
-or Faucet, so other versions of both pieces of software are likely to work
-equally well.
-
-The goal of the tutorial is to demonstrate Open vSwitch and Faucet in an
-end-to-end way, that is, to show how it works from the Faucet controller
-configuration at the top, through the OpenFlow flow table, to the datapath
-processing. Along the way, in addition to helping to understand the
-architecture at each level, we discuss performance and troubleshooting issues.
-We hope that this demonstration makes it easier for users and potential users
-to understand how Open vSwitch works and how to debug and troubleshoot it.
-
-We provide enough details in the tutorial that you should be able to fully
-follow along by following the instructions.
-
-Setting Up OVS
---------------
-
-This section explains how to set up Open vSwitch for the purpose of using it
-with Faucet for the tutorial.
-
-You might already have Open vSwitch installed on one or more computers or VMs,
-perhaps set up to control a set of VMs or a physical network. This is
-admirable, but we will be using Open vSwitch in a different way to set up a
-simulation environment called the OVS "sandbox". The sandbox does not use
-virtual machines or containers, which makes it more limited, but on the other
-hand it is (in this writer's opinion) easier to set up.
-
-There are two ways to start a sandbox: one that uses the Open vSwitch that is
-already installed on a system, and another that uses a copy of Open vSwitch
-that has been built but not yet installed. The latter is more often used and
-thus better tested, but both should work. The instructions below explain both
-approaches:
-
-1. Get a copy of the Open vSwitch source repository using Git, then ``cd`` into
- the new directory::
-
- $ git clone https://github.com/openvswitch/ovs.git
- $ cd ovs
-
- The default checkout is the master branch. You can check out a tag
- (such as v2.8.0) or a branch (such as origin/branch-2.8), if you
- prefer.
-
-2. If you do not already have an installed copy of Open vSwitch on your system,
- or if you do not want to use it for the sandbox (the sandbox will not
- disturb the functionality of any existing switches), then proceed to step 3.
- If you do have an installed copy and you want to use it for the sandbox, try
- to start the sandbox by running::
-
- $ tutorial/ovs-sandbox
-
- If it is successful, you will find yourself in a subshell environment, which
- is the sandbox (you can exit with ``exit`` or Control+D). If so, you're
- finished and do not need to complete the rest of the steps. If it fails,
- you can proceed to step 3 to build Open vSwitch anyway.
-
-3. Before you build, you might want to check that your system meets the build
- requirements. Read :doc:`/intro/install/general` to find out. For this
- tutorial, there is no need to compile the Linux kernel module, or to use any
- of the optional libraries such as OpenSSL, DPDK, or libcap-ng.
-
-4. Configure and build Open vSwitch::
-
- $ ./boot.sh
- $ ./configure
- $ make -j4
-
-5. Try out the sandbox by running::
-
- $ make sandbox
-
- You can exit the sandbox with ``exit`` or Control+D.
-
-Setting up Faucet
------------------
-
-This section explains how to get a copy of Faucet and set it up
-appropriately for the tutorial. There are many other ways to install
-Faucet, but this simple approach worked well for me. It has the
-advantage that it does not require modifying any system-level files or
-directories on your machine. It does, on the other hand, require
-Docker, so make sure you have it installed and working.
-
-It will be a little easier to go through the rest of the tutorial if
-you run these instructions in a separate terminal from the one that
-you're using for Open vSwitch, because it's often necessary to switch
-between one and the other.
-
-1. Get a copy of the Faucet source repository using Git, then ``cd``
- into the new directory::
-
- $ git clone https://github.com/faucetsdn/faucet.git
- $ cd faucet
-
- At this point I checked out the latest tag::
-
- $ latest_tag=$(git describe --tags $(git rev-list --tags --max-count=1))
- $ git checkout $latest_tag
-
-2. Build a docker container image::
-
- $ docker build -t faucet/faucet .
-
- This will take a few minutes.
-
-3. Create an installation directory under the ``faucet`` directory for
- the docker image to use::
-
- $ mkdir inst
-
- The Faucet configuration will go in ``inst/faucet.yaml`` and its
- main log will appear in ``inst/faucet.log``. (The official Faucet
- installation instructions call to put these in ``/etc/ryu/faucet``
- and ``/var/log/ryu/faucet``, respectively, but we avoid modifying
- these system directories.)
-
-4. Create a container and start Faucet::
-
- $ docker run -d --name faucet --restart=always -v $(pwd)/inst/:/etc/faucet/ -v $(pwd)/inst/:/var/log/faucet/ -p 6653:6653 -p 9302:9302 faucet/faucet
-
-5. Look in ``inst/faucet.log`` to verify that Faucet started. It will
- probably start with an exception and traceback because we have not
- yet created ``inst/faucet.yaml``.
-
-6. Later on, to make a new or updated Faucet configuration take
- effect quickly, you can run::
-
- $ docker exec faucet pkill -HUP -f faucet.faucet
-
- Another way is to stop and start the Faucet container::
-
- $ docker restart faucet
-
- You can also stop and delete the container; after this, to start it
- again, you need to rerun the ``docker run`` command::
-
- $ docker stop faucet
- $ docker rm faucet
-
-Overview
---------
-
-Now that Open vSwitch and Faucet are ready, here's an overview of what
-we're going to do for the remainder of the tutorial:
-
-1. Switching: Set up an L2 network with Faucet.
-
-2. Routing: Route between multiple L3 networks with Faucet.
-
-3. ACLs: Add and modify access control rules.
-
-At each step, we will take a look at how the features in question work
-from Faucet at the top to the data plane layer at the bottom. From
-the highest to lowest level, these layers and the software components
-that connect them are:
-
-Faucet.
- As the top level in the system, this is the authoritative source of the
- network configuration.
-
- Faucet connects to a variety of monitoring and performance tools,
- but we won't use them in this tutorial. Our main insights into the
- system will be through ``faucet.yaml`` for configuration and
- ``faucet.log`` to observe state, such as MAC learning and ARP
- resolution, and to tell when we've screwed up configuration syntax
- or semantics.
-
-The OpenFlow subsystem in Open vSwitch.
- OpenFlow is the protocol, standardized by the Open Networking Foundation,
- that controllers like Faucet use to control how Open vSwitch and other
- switches treat packets in the network.
-
- We will use ``ovs-ofctl``, a utility that comes with Open vSwitch,
- to observe and occasionally modify Open vSwitch's OpenFlow behavior.
- We will also use ``ovs-appctl``, a utility for communicating with
- ``ovs-vswitchd`` and other Open vSwitch daemons, to ask "what-if?"
- type questions.
-
- In addition, the OVS sandbox by default raises the Open vSwitch
- logging level for OpenFlow high enough that we can learn a great
- deal about OpenFlow behavior simply by reading its log file.
-
-Open vSwitch datapath.
- This is essentially a cache designed to accelerate packet processing. Open
- vSwitch includes a few different datapaths, such as one based on the Linux
- kernel and a userspace-only datapath (sometimes called the "DPDK" datapath).
- The OVS sandbox uses the latter, but the principles behind it apply equally
- well to other datapaths.
-
-At each step, we discuss how the design of each layer influences
-performance. We demonstrate how Open vSwitch features can be used to
-debug, troubleshoot, and understand the system as a whole.
-
-Switching
----------
-
-Layer-2 (L2) switching is the basis of modern networking. It's also
-very simple and a good place to start, so let's set up a switch with
-some VLANs in Faucet and see how it works at each layer. Begin by
-putting the following into ``inst/faucet.yaml``::
-
- dps:
- switch-1:
- dp_id: 0x1
- timeout: 3600
- arp_neighbor_timeout: 3600
- interfaces:
- 1:
- native_vlan: 100
- 2:
- native_vlan: 100
- 3:
- native_vlan: 100
- 4:
- native_vlan: 200
- 5:
- native_vlan: 200
- vlans:
- 100:
- 200:
-
-This configuration file defines a single switch ("datapath" or "dp")
-named ``switch-1``. The switch has five ports, numbered 1 through 5.
-Ports 1, 2, and 3 are in VLAN 100, and ports 4 and 5 are in VLAN 2.
-Faucet can identify the switch from its datapath ID, which is defined
-to be 0x1.
-
-.. note::
-
- This also sets high MAC learning and ARP timeouts. The defaults are
- 5 minutes and about 8 minutes, which are fine in production but
- sometimes too fast for manual experimentation. (Don't use a timeout
- bigger than about 65000 seconds because it will crash Faucet.)
-
-Now restart Faucet so that the configuration takes effect, e.g.::
-
- $ docker restart faucet
-
-Assuming that the configuration update is successful, you should now
-see a new line at the end of ``inst/faucet.log``::
-
- Jan 06 15:14:35 faucet INFO Add new datapath DPID 1 (0x1)
-
-Faucet is now waiting for a switch with datapath ID 0x1 to connect to
-it over OpenFlow, so our next step is to create a switch with OVS and
-make it connect to Faucet. To do that, switch to the terminal where
-you checked out OVS and start a sandbox with ``make sandbox`` or
-``tutorial/ovs-sandbox`` (as explained earlier under `Setting Up
-OVS`_). You should see something like this toward the end of the
-output::
-
- ----------------------------------------------------------------------
- You are running in a dummy Open vSwitch environment. You can use
- ovs-vsctl, ovs-ofctl, ovs-appctl, and other tools to work with the
- dummy switch.
-
- Log files, pidfiles, and the configuration database are in the
- "sandbox" subdirectory.
-
- Exit the shell to kill the running daemons.
- blp at sigabrt:~/nicira/ovs/tutorial(0)$
-
-Inside the sandbox, create a switch ("bridge") named ``br0``, set its
-datapath ID to 0x1, add simulated ports to it named ``p1`` through
-``p5``, and tell it to connect to the Faucet controller. To make it
-easier to understand, we request for port ``p1`` to be assigned
-OpenFlow port 1, ``p2`` port 2, and so on. As a final touch,
-configure the controller to be "out-of-band" (this is mainly to avoid
-some annoying messages in the ``ovs-vswitchd`` logs; for more
-information, run ``man ovs-vswitchd.conf.db`` and search for
-``connection_mode``)::
-
- $ ovs-vsctl add-br br0 \
- -- set bridge br0 other-config:datapath-id=0000000000000001 \
- -- add-port br0 p1 -- set interface p1 ofport_request=1 \
- -- add-port br0 p2 -- set interface p2 ofport_request=2 \
- -- add-port br0 p3 -- set interface p3 ofport_request=3 \
- -- add-port br0 p4 -- set interface p4 ofport_request=4 \
- -- add-port br0 p5 -- set interface p5 ofport_request=5 \
- -- set-controller br0 tcp:127.0.0.1:6653 \
- -- set controller br0 connection-mode=out-of-band
-
-.. note::
-
- You don't have to run all of these as a single ``ovs-vsctl``
- invocation. It is a little more efficient, though, and since it
- updates the OVS configuration in a single database transaction it
- means that, for example, there is never a time when the controller
- is set but it has not yet been configured as out-of-band.
-
-Now, if you look at ``inst/faucet.log`` again, you should see that
-Faucet recognized and configured the new switch and its ports::
-
- Jan 06 15:17:10 faucet INFO DPID 1 (0x1) connected
- Jan 06 15:17:10 faucet.valve INFO DPID 1 (0x1) Cold start configuring DP
- Jan 06 15:17:10 faucet.valve INFO DPID 1 (0x1) Configuring VLAN 100 vid:100 ports:Port 1,Port 2,Port 3
- Jan 06 15:17:10 faucet.valve INFO DPID 1 (0x1) Configuring VLAN 200 vid:200 ports:Port 4,Port 5
- Jan 06 15:17:10 faucet.valve INFO DPID 1 (0x1) Port 1 up, configuring
- Jan 06 15:17:10 faucet.valve INFO DPID 1 (0x1) Port 2 up, configuring
- Jan 06 15:17:10 faucet.valve INFO DPID 1 (0x1) Port 3 up, configuring
- Jan 06 15:17:10 faucet.valve INFO DPID 1 (0x1) Port 4 up, configuring
- Jan 06 15:17:10 faucet.valve INFO DPID 1 (0x1) Port 5 up, configuring
-
-Over on the Open vSwitch side, you can see a lot of related activity
-if you take a look in ``sandbox/ovs-vswitchd.log``. For example, here
-is the basic OpenFlow session setup and Faucet's probe of the switch's
-ports and capabilities::
-
- rconn|INFO|br0<->tcp:127.0.0.1:6653: connecting...
- vconn|DBG|tcp:127.0.0.1:6653: sent (Success): OFPT_HELLO (OF1.4) (xid=0x1):
- version bitmap: 0x01, 0x02, 0x03, 0x04, 0x05
- vconn|DBG|tcp:127.0.0.1:6653: received: OFPT_HELLO (OF1.3) (xid=0x2f24810a):
- version bitmap: 0x01, 0x02, 0x03, 0x04
- vconn|DBG|tcp:127.0.0.1:6653: negotiated OpenFlow version 0x04 (we support version 0x05 and earlier, peer supports version 0x04 and earlier)
- rconn|INFO|br0<->tcp:127.0.0.1:6653: connected
- vconn|DBG|tcp:127.0.0.1:6653: received: OFPT_ECHO_REQUEST (OF1.3) (xid=0x2f24810b): 0 bytes of payload
- vconn|DBG|tcp:127.0.0.1:6653: sent (Success): OFPT_ECHO_REPLY (OF1.3) (xid=0x2f24810b): 0 bytes of payload
- vconn|DBG|tcp:127.0.0.1:6653: received: OFPT_FEATURES_REQUEST (OF1.3) (xid=0x2f24810c):
- vconn|DBG|tcp:127.0.0.1:6653: sent (Success): OFPT_FEATURES_REPLY (OF1.3) (xid=0x2f24810c): dpid:0000000000000001
- n_tables:254, n_buffers:0
- capabilities: FLOW_STATS TABLE_STATS PORT_STATS GROUP_STATS QUEUE_STATS
- vconn|DBG|tcp:127.0.0.1:6653: received: OFPST_PORT_DESC request (OF1.3) (xid=0x2f24810d): port=ANY
- vconn|DBG|tcp:127.0.0.1:6653: sent (Success): OFPST_PORT_DESC reply (OF1.3) (xid=0x2f24810d):
- 1(p1): addr:aa:55:aa:55:00:14
- config: PORT_DOWN
- state: LINK_DOWN
- speed: 0 Mbps now, 0 Mbps max
- 2(p2): addr:aa:55:aa:55:00:15
- config: PORT_DOWN
- state: LINK_DOWN
- speed: 0 Mbps now, 0 Mbps max
- 3(p3): addr:aa:55:aa:55:00:16
- config: PORT_DOWN
- state: LINK_DOWN
- speed: 0 Mbps now, 0 Mbps max
- 4(p4): addr:aa:55:aa:55:00:17
- config: PORT_DOWN
- state: LINK_DOWN
- speed: 0 Mbps now, 0 Mbps max
- 5(p5): addr:aa:55:aa:55:00:18
- config: PORT_DOWN
- state: LINK_DOWN
- speed: 0 Mbps now, 0 Mbps max
- LOCAL(br0): addr:c6:64:ff:59:48:41
- config: PORT_DOWN
- state: LINK_DOWN
- speed: 0 Mbps now, 0 Mbps max
-
-After that, you can see Faucet delete all existing flows and then
-start adding new ones::
-
- vconn|DBG|tcp:127.0.0.1:6653: received: OFPT_FLOW_MOD (OF1.3) (xid=0x2f24810e): DEL table:255 priority=0 actions=drop
- vconn|DBG|tcp:127.0.0.1:6653: received: OFPT_BARRIER_REQUEST (OF1.3) (xid=0x2f24810f):
- vconn|DBG|tcp:127.0.0.1:6653: sent (Success): OFPT_BARRIER_REPLY (OF1.3) (xid=0x2f24810f):
- vconn|DBG|tcp:127.0.0.1:6653: received: OFPT_FLOW_MOD (OF1.3) (xid=0x2f248110): ADD priority=0 cookie:0x5adc15c0 out_port:0 actions=drop
- vconn|DBG|tcp:127.0.0.1:6653: received: OFPT_FLOW_MOD (OF1.3) (xid=0x2f248111): ADD table:1 priority=0 cookie:0x5adc15c0 out_port:0 actions=drop
- ...
-
-OpenFlow Layer
-~~~~~~~~~~~~~~
-
-Let's take a look at the OpenFlow tables that Faucet set up. Before
-we do that, it's helpful to take a look at ``docs/architecture.rst``
-in the Faucet documentation to learn how Faucet structures its flow
-tables. In summary, this document says:
-
-Table 0
- Port-based ACLs
-
-Table 1
- Ingress VLAN processing
-
-Table 2
- VLAN-based ACLs
-
-Table 3
- Ingress L2 processing, MAC learning
-
-Table 4
- L3 forwarding for IPv4
-
-Table 5
- L3 forwarding for IPv6
-
-Table 6
- Virtual IP processing, e.g. for router IP addresses implemented by Faucet
-
-Table 7
- Egress L2 processing
-
-Table 8
- Flooding
-
-With that in mind, let's dump the flow tables. The simplest way is to
-just run plain ``ovs-ofctl dump-flows``::
-
- $ ovs-ofctl dump-flows br0
-
-If you run that bare command, it produces a lot of extra junk that
-makes the output harder to read, like statistics and "cookie" values
-that are all the same. In addition, for historical reasons
-``ovs-ofctl`` always defaults to using OpenFlow 1.0 even though Faucet
-and most modern controllers use OpenFlow 1.3, so it's best to force it
-to use OpenFlow 1.3. We could throw in a lot of options to fix these,
-but we'll want to do this more than once, so let's start by defining a
-shell function for ourselves::
-
- $ dump-flows () {
- ovs-ofctl -OOpenFlow13 --names --no-stat dump-flows "$@" \
- | sed 's/cookie=0x5adc15c0, //'
- }
-
-Let's also define ``save-flows`` and ``diff-flows`` functions for
-later use::
-
- $ save-flows () {
- ovs-ofctl -OOpenFlow13 --no-names --sort dump-flows "$@"
- }
- $ diff-flows () {
- ovs-ofctl -OOpenFlow13 diff-flows "$@" | sed 's/cookie=0x5adc15c0 //'
- }
-
-Now let's take a look at the flows we've got and what they mean, like
-this::
-
- $ dump-flows br0
-
-First, table 0 has a flow that just jumps to table 1 for each
-configured port, and drops other unrecognized packets. Presumably it
-will do more if we configured port-based ACLs::
-
- priority=9099,in_port=p1 actions=goto_table:1
- priority=9099,in_port=p2 actions=goto_table:1
- priority=9099,in_port=p3 actions=goto_table:1
- priority=9099,in_port=p4 actions=goto_table:1
- priority=9099,in_port=p5 actions=goto_table:1
- priority=0 actions=drop
-
-Table 1, for ingress VLAN processing, has a bunch of flows that drop
-inappropriate packets, such as LLDP and STP::
-
- table=1, priority=9099,dl_dst=01:80:c2:00:00:00 actions=drop
- table=1, priority=9099,dl_dst=01:00:0c:cc:cc:cd actions=drop
- table=1, priority=9099,dl_type=0x88cc actions=drop
-
-Table 1 also has some more interesting flows that recognize packets
-without a VLAN header on each of our ports
-(``vlan_tci=0x0000/0x1fff``), push on the VLAN configured for the
-port, and proceed to table 3. Presumably these skip table 2 because
-we did not configure any VLAN-based ACLs. There is also a fallback
-flow to drop other packets, which in practice means that if any
-received packet already has a VLAN header then it will be dropped::
-
- table=1, priority=9000,in_port=p1,vlan_tci=0x0000/0x1fff actions=push_vlan:0x8100,set_field:4196->vlan_vid,goto_table:3
- table=1, priority=9000,in_port=p2,vlan_tci=0x0000/0x1fff actions=push_vlan:0x8100,set_field:4196->vlan_vid,goto_table:3
- table=1, priority=9000,in_port=p3,vlan_tci=0x0000/0x1fff actions=push_vlan:0x8100,set_field:4196->vlan_vid,goto_table:3
- table=1, priority=9000,in_port=p4,vlan_tci=0x0000/0x1fff actions=push_vlan:0x8100,set_field:4296->vlan_vid,goto_table:3
- table=1, priority=9000,in_port=p5,vlan_tci=0x0000/0x1fff actions=push_vlan:0x8100,set_field:4296->vlan_vid,goto_table:3
- table=1, priority=0 actions=drop
-
-.. note::
-
- The syntax ``set_field:4196->vlan_vid`` is curious and somewhat
- misleading. OpenFlow 1.3 defines the ``vlan_vid`` field as a 13-bit
- field where bit 12 is set to 1 if the VLAN header is present. Thus,
- since 4196 is 0x1064, this action sets VLAN value 0x64, which in
- decimal is 100.
-
-Table 2 isn't used because there are no VLAN-based ACLs. It just has
-a drop flow::
-
- table=2, priority=0 actions=drop
-
-Table 3 is used for MAC learning but the controller hasn't learned any
-MAC yet. It also drops some inappropriate packets such as those that claim
-to be from a broadcast source address (why not from all multicast source
-addresses, though?). We'll come back here later::
-
- table=3, priority=9099,dl_src=ff:ff:ff:ff:ff:ff actions=drop
- table=3, priority=9001,dl_src=0e:00:00:00:00:01 actions=drop
- table=3, priority=0 actions=drop
- table=3, priority=9000 actions=CONTROLLER:96,goto_table:7
-
-Tables 4, 5, and 6 aren't used because we haven't configured any
-routing::
-
- table=4, priority=0 actions=drop
- table=5, priority=0 actions=drop
- table=6, priority=0 actions=drop
-
-Table 7 is used to direct packets to learned MACs but Faucet hasn't
-learned any MACs yet, so it just sends all the packets along to table
-8::
-
- table=7, priority=0 actions=drop
- table=7, priority=9000 actions=goto_table:8
-
-Table 8 implements flooding, broadcast, and multicast. The flows for
-broadcast and flood are easy to understand: if the packet came in on a
-given port and needs to be flooded or broadcast, output it to all the
-other ports in the same VLAN::
-
- table=8, priority=9008,in_port=p1,dl_vlan=100,dl_dst=ff:ff:ff:ff:ff:ff actions=pop_vlan,output:p2,output:p3
- table=8, priority=9008,in_port=p2,dl_vlan=100,dl_dst=ff:ff:ff:ff:ff:ff actions=pop_vlan,output:p1,output:p3
- table=8, priority=9008,in_port=p3,dl_vlan=100,dl_dst=ff:ff:ff:ff:ff:ff actions=pop_vlan,output:p1,output:p2
- table=8, priority=9008,in_port=p4,dl_vlan=200,dl_dst=ff:ff:ff:ff:ff:ff actions=pop_vlan,output:p5
- table=8, priority=9008,in_port=p5,dl_vlan=200,dl_dst=ff:ff:ff:ff:ff:ff actions=pop_vlan,output:p4
- table=8, priority=9000,in_port=p1,dl_vlan=100 actions=pop_vlan,output:p2,output:p3
- table=8, priority=9000,in_port=p2,dl_vlan=100 actions=pop_vlan,output:p1,output:p3
- table=8, priority=9000,in_port=p3,dl_vlan=100 actions=pop_vlan,output:p1,output:p2
- table=8, priority=9000,in_port=p4,dl_vlan=200 actions=pop_vlan,output:p5
- table=8, priority=9000,in_port=p5,dl_vlan=200 actions=pop_vlan,output:p4
-
-.. note::
-
- These flows could apparently be simpler because OpenFlow says that
- ``output:<port>`` is ignored if ``<port>`` is the input port. That
- means that the first three flows above could apparently be collapsed
- into just::
-
- table=8, priority=9008,dl_vlan=100,dl_dst=ff:ff:ff:ff:ff:ff actions=pop_vlan,output:p1,output:p2,output:p3
-
- There might be some reason why this won't work or isn't practical,
- but that isn't obvious from looking at the flow table.
-
-There are also some flows for handling some standard forms of
-multicast, and a fallback drop flow::
-
- table=8, priority=9006,in_port=p1,dl_vlan=100,dl_dst=33:33:00:00:00:00/ff:ff:00:00:00:00 actions=pop_vlan,output:p2,output:p3
- table=8, priority=9006,in_port=p2,dl_vlan=100,dl_dst=33:33:00:00:00:00/ff:ff:00:00:00:00 actions=pop_vlan,output:p1,output:p3
- table=8, priority=9006,in_port=p3,dl_vlan=100,dl_dst=33:33:00:00:00:00/ff:ff:00:00:00:00 actions=pop_vlan,output:p1,output:p2
- table=8, priority=9006,in_port=p4,dl_vlan=200,dl_dst=33:33:00:00:00:00/ff:ff:00:00:00:00 actions=pop_vlan,output:p5
- table=8, priority=9006,in_port=p5,dl_vlan=200,dl_dst=33:33:00:00:00:00/ff:ff:00:00:00:00 actions=pop_vlan,output:p4
- table=8, priority=9002,in_port=p1,dl_vlan=100,dl_dst=01:80:c2:00:00:00/ff:ff:ff:00:00:00 actions=pop_vlan,output:p2,output:p3
- table=8, priority=9002,in_port=p2,dl_vlan=100,dl_dst=01:80:c2:00:00:00/ff:ff:ff:00:00:00 actions=pop_vlan,output:p1,output:p3
- table=8, priority=9002,in_port=p3,dl_vlan=100,dl_dst=01:80:c2:00:00:00/ff:ff:ff:00:00:00 actions=pop_vlan,output:p1,output:p2
- table=8, priority=9004,in_port=p1,dl_vlan=100,dl_dst=01:00:5e:00:00:00/ff:ff:ff:00:00:00 actions=pop_vlan,output:p2,output:p3
- table=8, priority=9004,in_port=p2,dl_vlan=100,dl_dst=01:00:5e:00:00:00/ff:ff:ff:00:00:00 actions=pop_vlan,output:p1,output:p3
- table=8, priority=9004,in_port=p3,dl_vlan=100,dl_dst=01:00:5e:00:00:00/ff:ff:ff:00:00:00 actions=pop_vlan,output:p1,output:p2
- table=8, priority=9002,in_port=p4,dl_vlan=200,dl_dst=01:80:c2:00:00:00/ff:ff:ff:00:00:00 actions=pop_vlan,output:p5
- table=8, priority=9002,in_port=p5,dl_vlan=200,dl_dst=01:80:c2:00:00:00/ff:ff:ff:00:00:00 actions=pop_vlan,output:p4
- table=8, priority=9004,in_port=p4,dl_vlan=200,dl_dst=01:00:5e:00:00:00/ff:ff:ff:00:00:00 actions=pop_vlan,output:p5
- table=8, priority=9004,in_port=p5,dl_vlan=200,dl_dst=01:00:5e:00:00:00/ff:ff:ff:00:00:00 actions=pop_vlan,output:p4
- table=8, priority=0 actions=drop
-
-Tracing
-~~~~~~~
-
-Let's go a level deeper. So far, everything we've done has been
-fairly general. We can also look at something more specific: the path
-that a particular packet would take through Open vSwitch. We can use
-OVN ``ofproto/trace`` command to play "what-if?" games. This command
-is one that we send directly to ``ovs-vswitchd``, using the
-``ovs-appctl`` utility.
-
-.. note::
-
- ``ovs-appctl`` is actually a very simple-minded JSON-RPC client, so you could
- also use some other utility that speaks JSON-RPC, or access it from a program
- as an API.
-
-The ``ovs-vswitchd``\(8) manpage has a lot of detail on how to use
-``ofproto/trace``, but let's just start by building up from a simple
-example. You can start with a command that just specifies the
-datapath (e.g. ``br0``), an input port, and nothing else; unspecified
-fields default to all-zeros. Let's look at the full output for this
-trivial example::
-
- $ ovs-appctl ofproto/trace br0 in_port=p1
- Flow: in_port=1,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000
-
- bridge("br0")
- -------------
- 0. in_port=1, priority 9099, cookie 0x5adc15c0
- goto_table:1
- 1. in_port=1,vlan_tci=0x0000/0x1fff, priority 9000, cookie 0x5adc15c0
- push_vlan:0x8100
- set_field:4196->vlan_vid
- goto_table:3
- 3. priority 9000, cookie 0x5adc15c0
- CONTROLLER:96
- goto_table:7
- 7. priority 9000, cookie 0x5adc15c0
- goto_table:8
- 8. in_port=1,dl_vlan=100, priority 9000, cookie 0x5adc15c0
- pop_vlan
- output:2
- output:3
-
- Final flow: unchanged
- Megaflow: recirc_id=0,eth,in_port=1,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000
- Datapath actions: push_vlan(vid=100,pcp=0),userspace(pid=0,controller(reason=1,flags=1,recirc_id=1,rule_cookie=0x5adc15c0,controller_id=0,max_len=96)),pop_vlan,2,3
-
-The first line of output, beginning with ``Flow:``, just repeats our
-request in a more verbose form, including the L2 fields that were
-zeroed.
-
-Each of the numbered items under ``bridge("br0")`` shows what would
-happen to our hypothetical packet in the table with the given number.
-For example, we see in table 1 that the packet matches a flow that
-push on a VLAN header, set the VLAN ID to 100, and goes on to further
-processing in table 3. In table 3, the packet gets sent to the
-controller to allow MAC learning to take place, and then table 8
-floods the packet to the other ports in the same VLAN.
-
-Summary information follows the numbered tables. The packet hasn't
-been changed (overall, even though a VLAN was pushed and then popped
-back off) since ingress, hence ``Final flow: unchanged``. We'll look
-at the ``Megaflow`` information later. The ``Datapath actions``
-summarize what would actually happen to such a packet.
-
-Triggering MAC Learning
-~~~~~~~~~~~~~~~~~~~~~~~
-
-We just saw how a packet gets sent to the controller to trigger MAC
-learning. Let's actually send the packet and see what happens. But
-before we do that, let's save a copy of the current flow tables for
-later comparison::
-
- $ save-flows br0 > flows1
-
-Now use ``ofproto/trace``, as before, with a few new twists: we
-specify the source and destination Ethernet addresses and append the
-``-generate`` option so that side effects like sending a packet to the
-controller actually happen::
-
- $ ovs-appctl ofproto/trace br0 in_port=p1,dl_src=00:11:11:00:00:00,dl_dst=00:22:22:00:00:00 -generate
-
-The output is almost identical to that before, so it is not repeated
-here. But, take a look at ``inst/faucet.log`` now. It should now
-include a line at the end that says that it learned about our MAC
-00:11:11:00:00:00, like this::
-
- Jan 06 15:56:02 faucet.valve INFO DPID 1 (0x1) L2 learned 00:11:11:00:00:00 (L2 type 0x0000, L3 src None) on Port 1 on VLAN 100 (1 hosts total
-
-Now compare the flow tables that we saved to the current ones::
-
- diff-flows flows1 br0
-
-The result should look like this, showing new flows for the learned
-MACs::
-
- +table=3 priority=9098,in_port=1,dl_vlan=100,dl_src=00:11:11:00:00:00 hard_timeout=3601 actions=goto_table:7
- +table=7 priority=9099,dl_vlan=100,dl_dst=00:11:11:00:00:00 idle_timeout=3601 actions=pop_vlan,output:1
-
-To demonstrate the usefulness of the learned MAC, try tracing (with
-side effects) a packet arriving on ``p2`` (or ``p3``) and destined to
-the address learned on ``p1``, like this::
-
- $ ovs-appctl ofproto/trace br0 in_port=p2,dl_src=00:22:22:00:00:00,dl_dst=00:11:11:00:00:00 -generate
-
-The first time you run this command, you will notice that it sends the
-packet to the controller, to learn ``p2``'s 00:22:22:00:00:00 source
-address::
-
- bridge("br0")
- -------------
- 0. in_port=2, priority 9099, cookie 0x5adc15c0
- goto_table:1
- 1. in_port=2,vlan_tci=0x0000/0x1fff, priority 9000, cookie 0x5adc15c0
- push_vlan:0x8100
- set_field:4196->vlan_vid
- goto_table:3
- 3. priority 9000, cookie 0x5adc15c0
- CONTROLLER:96
- goto_table:7
- 7. dl_vlan=100,dl_dst=00:11:11:00:00:00, priority 9099, cookie 0x5adc15c0
- pop_vlan
- output:1
-
-If you check ``inst/faucet.log``, you can see that ``p2``'s MAC has
-been learned too::
-
- Jan 06 15:58:09 faucet.valve INFO DPID 1 (0x1) L2 learned 00:22:22:00:00:00 (L2 type 0x0000, L3 src None) on Port 2 on VLAN 100 (2 hosts total)
-
-Similarly for ``diff-flows``::
-
- $ diff-flows flows1 br0
- +table=3 priority=9098,in_port=1,dl_vlan=100,dl_src=00:11:11:00:00:00 hard_timeout=3601 actions=goto_table:7
- +table=3 priority=9098,in_port=2,dl_vlan=100,dl_src=00:22:22:00:00:00 hard_timeout=3604 actions=goto_table:7
- +table=7 priority=9099,dl_vlan=100,dl_dst=00:11:11:00:00:00 idle_timeout=3601 actions=pop_vlan,output:1
- +table=7 priority=9099,dl_vlan=100,dl_dst=00:22:22:00:00:00 idle_timeout=3604 actions=pop_vlan,output:2
-
-Then, if you re-run either of the ``ofproto/trace`` commands (with or
-without ``-generate``), you can see that the packets go back and forth
-without any further MAC learning, e.g.::
-
- $ ovs-appctl ofproto/trace br0 in_port=p2,dl_src=00:22:22:00:00:00,dl_dst=00:11:11:00:00:00 -generate
- Flow: in_port=2,vlan_tci=0x0000,dl_src=00:22:22:00:00:00,dl_dst=00:11:11:00:00:00,dl_type=0x0000
-
- bridge("br0")
- -------------
- 0. in_port=2, priority 9099, cookie 0x5adc15c0
- goto_table:1
- 1. in_port=2,vlan_tci=0x0000/0x1fff, priority 9000, cookie 0x5adc15c0
- push_vlan:0x8100
- set_field:4196->vlan_vid
- goto_table:3
- 3. in_port=2,dl_vlan=100,dl_src=00:22:22:00:00:00, priority 9098, cookie 0x5adc15c0
- goto_table:7
- 7. dl_vlan=100,dl_dst=00:11:11:00:00:00, priority 9099, cookie 0x5adc15c0
- pop_vlan
- output:1
-
- Final flow: unchanged
- Megaflow: recirc_id=0,eth,in_port=2,vlan_tci=0x0000/0x1fff,dl_src=00:22:22:00:00:00,dl_dst=00:11:11:00:00:00,dl_type=0x0000
- Datapath actions: 1
-
-Performance
-~~~~~~~~~~~
-
-Open vSwitch has a concept of a "fast path" and a "slow path"; ideally
-all packets stay in the fast path. This distinction between slow path
-and fast path is the key to making sure that Open vSwitch performs as
-fast as possible.
-
-Some factors can force a flow or a packet to take the slow path. As one
-example, all CFM, BFD, LACP, STP, and LLDP processing takes place in the
-slow path, in the cases where Open vSwitch processes these protocols
-itself instead of delegating to controller-written flows. As a second
-example, any flow that modifies ARP fields is processed in the slow
-path. These are corner cases that are unlikely to cause performance
-problems in practice because these protocols send packets at a
-relatively slow rate, and users and controller authors do not normally
-need to be concerned about them.
-
-To understand what cases users and controller authors should consider,
-we need to talk about how Open vSwitch optimizes for performance. The
-Open vSwitch code is divided into two major components which, as
-already mentioned, are called the "slow path" and "fast path" (aka
-"datapath"). The slow path is embedded in the ``ovs-vswitchd``
-userspace program. It is the part of the Open vSwitch packet
-processing logic that understands OpenFlow. Its job is to take a
-packet and run it through the OpenFlow tables to determine what should
-happen to it. It outputs a list of actions in a form similar to
-OpenFlow actions but simpler, called "ODP actions" or "datapath
-actions". It then passes the ODP actions to the datapath, which
-applies them to the packet.
-
-.. note::
-
- Open vSwitch contains a single slow path and multiple fast paths.
- The difference between using Open vSwitch with the Linux kernel
- versus with DPDK is the datapath.
-
-If every packet passed through the slow path and the fast path in this
-way, performance would be terrible. The key to getting high
-performance from this architecture is caching. Open vSwitch includes
-a multi-level cache. It works like this:
-
-1. A packet initially arrives at the datapath. Some datapaths (such
- as DPDK and the in-tree version of the OVS kernel module) have a
- first-level cache called the "microflow cache". The microflow
- cache is the key to performance for relatively long-lived, high
- packet rate flows. If the datapath has a microflow cache, then it
- consults it and, if there is a cache hit, the datapath executes the
- associated actions. Otherwise, it proceeds to step 2.
-
-2. The datapath consults its second-level cache, called the "megaflow
- cache". The megaflow cache is the key to performance for shorter
- or low packet rate flows. If there is a megaflow cache hit, the
- datapath executes the associated actions. Otherwise, it proceeds
- to step 3.
-
-3. The datapath passes the packet to the slow path, which runs it
- through the OpenFlow table to yield ODP actions, a process that is
- often called "flow translation". It then passes the packet back to
- the datapath to execute the actions and to, if possible, install a
- megaflow cache entry so that subsequent similar packets can be
- handled directly by the fast path. (We already described above
- most of the cases where a cache entry cannot be installed.)
-
-The megaflow cache is the key cache to consider for performance
-tuning. Open vSwitch provides tools for understanding and optimizing
-its behavior. The ``ofproto/trace`` command that we have already been
-using is the most common tool for this use. Let's take another look
-at the most recent ``ofproto/trace`` output::
-
- $ ovs-appctl ofproto/trace br0 in_port=p2,dl_src=00:22:22:00:00:00,dl_dst=00:11:11:00:00:00 -generate
- Flow: in_port=2,vlan_tci=0x0000,dl_src=00:22:22:00:00:00,dl_dst=00:11:11:00:00:00,dl_type=0x0000
-
- bridge("br0")
- -------------
- 0. in_port=2, priority 9099, cookie 0x5adc15c0
- goto_table:1
- 1. in_port=2,vlan_tci=0x0000/0x1fff, priority 9000, cookie 0x5adc15c0
- push_vlan:0x8100
- set_field:4196->vlan_vid
- goto_table:3
- 3. in_port=2,dl_vlan=100,dl_src=00:22:22:00:00:00, priority 9098, cookie 0x5adc15c0
- goto_table:7
- 7. dl_vlan=100,dl_dst=00:11:11:00:00:00, priority 9099, cookie 0x5adc15c0
- pop_vlan
- output:1
-
- Final flow: unchanged
- Megaflow: recirc_id=0,eth,in_port=2,vlan_tci=0x0000/0x1fff,dl_src=00:22:22:00:00:00,dl_dst=00:11:11:00:00:00,dl_type=0x0000
- Datapath actions: 1
-
-This time, it's the last line that we're interested in. This line
-shows the entry that Open vSwitch would insert into the megaflow cache
-given the particular packet with the current flow tables. The
-megaflow entry includes:
-
-* ``recirc_id``. This is an implementation detail that users don't
- normally need to understand.
-
-* ``eth``. This just indicates that the cache entry matches only
- Ethernet packets; Open vSwitch also supports other types of packets,
- such as IP packets not encapsulated in Ethernet.
-
-* All of the fields matched by any of the flows that the packet
- visited:
-
- ``in_port``
- In tables 0, 1, and 3.
-
- ``vlan_tci``
- In tables 1, 3, and 7 (``vlan_tci`` includes the VLAN ID and PCP
- fields and``dl_vlan`` is just the VLAN ID).
-
- ``dl_src``
- In table 3
-
- ``dl_dst``
- In table 7.
-
-* All of the fields matched by flows that had to be ruled out to
- ensure that the ones that actually matched were the highest priority
- matching rules.
-
-The last one is important. Notice how the megaflow matches on
-``dl_type=0x0000``, even though none of the tables matched on
-``dl_type`` (the Ethernet type). One reason is because of this flow
-in OpenFlow table 1 (which shows up in ``dump-flows`` output)::
-
- table=1, priority=9099,dl_type=0x88cc actions=drop
-
-This flow has higher priority than the flow in table 1 that actually
-matched. This means that, to put it in the megaflow cache,
-``ovs-vswitchd`` has to add a match on ``dl_type`` to ensure that the
-cache entry doesn't match LLDP packets (with Ethertype 0x88cc).
-
-.. note::
-
- In fact, in some cases ``ovs-vswitchd`` matches on fields that
- aren't strictly required according to this description. ``dl_type``
- is actually one of those, so deleting the LLDP flow probably would
- not have any effect on the megaflow. But the principle here is
- sound.
-
-So why does any of this matter? It's because, the more specific a
-megaflow is, that is, the more fields or bits within fields that a
-megaflow matches, the less valuable it is from a caching viewpoint. A
-very specific megaflow might match on L2 and L3 addresses and L4 port
-numbers. When that happens, only packets in one (half-)connection
-match the megaflow. If that connection has only a few packets, as
-many connections do, then the high cost of the slow path translation
-is amortized over only a few packets, so the average cost of
-forwarding those packets is high. On the other hand, if a megaflow
-only matches a relatively small number of L2 and L3 packets, then the
-cache entry can potentially be used by many individual connections,
-and the average cost is low.
-
-For more information on how Open vSwitch constructs megaflows,
-including about ways that it can make megaflow entries less specific
-than one would infer from the discussion here, please refer to the
-2015 NSDI paper, "The Design and Implementation of Open vSwitch",
-which focuses on this algorithm.
-
-Routing
--------
-
-We've looked at how Faucet implements switching in OpenFlow, and how
-Open vSwitch implements OpenFlow through its datapath architecture.
-Now let's start over, adding L3 routing into the picture.
-
-It's remarkably easy to enable routing. We just change our ``vlans``
-section in ``inst/faucet.yaml`` to specify a router IP address for
-each VLAN and define a router between them. The ``dps`` section is unchanged::
-
- dps:
- switch-1:
- dp_id: 0x1
- timeout: 3600
- arp_neighbor_timeout: 3600
- interfaces:
- 1:
- native_vlan: 100
- 2:
- native_vlan: 100
- 3:
- native_vlan: 100
- 4:
- native_vlan: 200
- 5:
- native_vlan: 200
- vlans:
- 100:
- faucet_vips: ["10.100.0.254/24"]
- 200:
- faucet_vips: ["10.200.0.254/24"]
- routers:
- router-1:
- vlans: [100, 200]
-
-Then we restart Faucet::
-
- $ docker restart faucet
-
-.. note::
-
- One should be able to tell Faucet to re-read its configuration file
- without restarting it. I sometimes saw anomalous behavior when I
- did this, although I didn't characterize it well enough to make a
- quality bug report. I found restarting the container to be
- reliable.
-
-OpenFlow Layer
-~~~~~~~~~~~~~~
-
-Back in the OVS sandbox, let's see how the flow table has changed, with::
-
- $ diff-flows flows1 br0
-
-First, table 3 has new flows to direct ARP packets to table 6 (the
-virtual IP processing table), presumably to handle ARP for the router
-IPs. New flows also send IP packets destined to a particular Ethernet
-address to table 4 (the L3 forwarding table); we can make the educated
-guess that the Ethernet address is the one used by the Faucet router::
-
- +table=3 priority=9131,arp,dl_vlan=100 actions=goto_table:6
- +table=3 priority=9131,arp,dl_vlan=200 actions=goto_table:6
- +table=3 priority=9099,ip,dl_vlan=100,dl_dst=0e:00:00:00:00:01 actions=goto_table:4
- +table=3 priority=9099,ip,dl_vlan=200,dl_dst=0e:00:00:00:00:01 actions=goto_table:4
-
-The new flows in table 4 appear to be verifying that the packets are
-indeed addressed to a network or IP address that Faucet knows how to
-route::
-
- +table=4 priority=9131,ip,dl_vlan=100,nw_dst=10.100.0.254 actions=goto_table:6
- +table=4 priority=9131,ip,dl_vlan=200,nw_dst=10.200.0.254 actions=goto_table:6
- +table=4 priority=9123,ip,dl_vlan=100,nw_dst=10.100.0.0/24 actions=goto_table:6
- +table=4 priority=9123,ip,dl_vlan=200,nw_dst=10.100.0.0/24 actions=goto_table:6
- +table=4 priority=9123,ip,dl_vlan=100,nw_dst=10.200.0.0/24 actions=goto_table:6
- +table=4 priority=9123,ip,dl_vlan=200,nw_dst=10.200.0.0/24 actions=goto_table:6
-
-Table 6 has a few different things going on. It sends ARP requests
-for the router IPs to the controller; presumably the controller will
-generate replies and send them back to the requester. It switches
-other ARP packets, either broadcasting them if they have a broadcast
-destination or attempting to unicast them otherwise. It sends all
-other IP packets to the controller::
-
- +table=6 priority=9133,arp,arp_tpa=10.100.0.254 actions=CONTROLLER:128
- +table=6 priority=9133,arp,arp_tpa=10.200.0.254 actions=CONTROLLER:128
- +table=6 priority=9132,arp,dl_dst=ff:ff:ff:ff:ff:ff actions=goto_table:8
- +table=6 priority=9131,arp actions=goto_table:7
- +table=6 priority=9130,ip actions=CONTROLLER:128
-
-Performance is clearly going to be poor if every packet that needs to
-be routed has to go to the controller, but it's unlikely that's the
-full story. In the next section, we'll take a closer look.
-
-Tracing
-~~~~~~~
-
-As in our switching example, we can play some "what-if?" games to
-figure out how this works. Let's suppose that a machine with IP
-10.100.0.1, on port ``p1``, wants to send a IP packet to a machine
-with IP 10.200.0.1 on port ``p4``. Assuming that these hosts have not
-been in communication recently, the steps to accomplish this are
-normally the following:
-
-1. Host 10.100.0.1 sends an ARP request to router 10.100.0.254.
-
-2. The router sends an ARP reply to the host.
-
-3. Host 10.100.0.1 sends an IP packet to 10.200.0.1, via the router's
- Ethernet address.
-
-4. The router broadcasts an ARP request to ``p4`` and ``p5``, the
- ports that carry the 10.200.0.<x> network.
-
-5. Host 10.200.0.1 sends an ARP reply to the router.
-
-6. Either the router sends the IP packet (which it buffered) to
- 10.200.0.1, or eventually 10.100.0.1 times out and resends it.
-
-Let's use ``ofproto/trace`` to see whether Faucet and OVS follow this
-procedure.
-
-Before we start, save a new snapshot of the flow tables for later
-comparison::
-
- $ save-flows br0 > flows2
-
-Step 1: Host ARP for Router
-+++++++++++++++++++++++++++
-
-Let's simulate the ARP from 10.100.0.1 to its gateway router
-10.100.0.254. This requires more detail than any of the packets we've
-simulated previously::
-
- $ ovs-appctl ofproto/trace br0 in_port=p1,dl_src=00:01:02:03:04:05,dl_dst=ff:ff:ff:ff:ff:ff,dl_type=0x806,arp_spa=10.100.0.1,arp_tpa=10.100.0.254,arp_sha=00:01:02:03:04:05,arp_tha=ff:ff:ff:ff:ff:ff,arp_op=1 -generate
-
-The important part of the output is where it shows that the packet was
-recognized as an ARP request destined to the router gateway and
-therefore sent to the controller::
-
- 6. arp,arp_tpa=10.100.0.254, priority 9133, cookie 0x5adc15c0
- CONTROLLER:128
-
-The Faucet log shows that Faucet learned the host's MAC address,
-its MAC-to-IP mapping, and responded to the ARP request::
-
- Jan 06 16:12:23 faucet.valve INFO DPID 1 (0x1) Adding new route 10.100.0.1/32 via 10.100.0.1 (00:01:02:03:04:05) on VLAN 100
- Jan 06 16:12:23 faucet.valve INFO DPID 1 (0x1) Responded to ARP request for 10.100.0.254 from 10.100.0.1 (00:01:02:03:04:05) on VLAN 100
- Jan 06 16:12:23 faucet.valve INFO DPID 1 (0x1) L2 learned 00:01:02:03:04:05 (L2 type 0x0806, L3 src 10.100.0.1) on Port 1 on VLAN 100 (1 hosts total)
-
-We can also look at the changes to the flow tables::
-
- $ diff-flows flows2 br0
- +table=3 priority=9098,in_port=1,dl_vlan=100,dl_src=00:01:02:03:04:05 hard_timeout=3600 actions=goto_table:7
- +table=4 priority=9131,ip,dl_vlan=100,nw_dst=10.100.0.1 actions=set_field:4196->vlan_vid,set_field:0e:00:00:00:00:01->eth_src,set_field:00:01:02:03:04:05->eth_dst,dec_ttl,goto_table:7
- +table=4 priority=9131,ip,dl_vlan=200,nw_dst=10.100.0.1 actions=set_field:4196->vlan_vid,set_field:0e:00:00:00:00:01->eth_src,set_field:00:01:02:03:04:05->eth_dst,dec_ttl,goto_table:7
- +table=7 priority=9099,dl_vlan=100,dl_dst=00:01:02:03:04:05 idle_timeout=3600 actions=pop_vlan,output:1
-
-The new flows include one in table 3 and one in table 7 for the
-learned MAC, which have the same forms we saw before. The new flows
-in table 4 are different. They matches packets directed to 10.100.0.1
-(in two VLANs) and forward them to the host by updating the Ethernet
-source and destination addresses appropriately, decrementing the TTL,
-and skipping ahead to unicast output in table 7. This means that
-packets sent **to** 10.100.0.1 should now get to their destination.
-
-Step 2: Router Sends ARP Reply
-++++++++++++++++++++++++++++++
-
-``inst/faucet.log`` said that the router sent an ARP reply. How can
-we see it? Simulated packets just get dropped by default. One way is
-to configure the dummy ports to write the packets they receive to a
-file. Let's try that. First configure the port::
-
- $ ovs-vsctl set interface p1 options:pcap=p1.pcap
-
-Then re-run the "trace" command::
-
- $ ovs-appctl ofproto/trace br0 in_port=p1,dl_src=00:01:02:03:04:05,dl_dst=ff:ff:ff:ff:ff:ff,dl_type=0x806,arp_spa=10.100.0.1,arp_tpa=10.100.0.254,arp_sha=00:01:02:03:04:05,arp_tha=ff:ff:ff:ff:ff:ff,arp_op=1 -generate
-
-And dump the reply packet::
-
- $ /usr/sbin/tcpdump -evvvr sandbox/p1.pcap
- reading from file sandbox/p1.pcap, link-type EN10MB (Ethernet)
- 16:14:47.670727 0e:00:00:00:00:01 (oui Unknown) > 00:01:02:03:04:05 (oui Unknown), ethertype ARP (0x0806), length 60: Ethernet (len 6), IPv4 (len 4), Reply 10.100.0.254 is-at 0e:00:00:00:00:01 (oui Unknown), length 46
-
-We clearly see the ARP reply, which tells us that the Faucet router's
-Ethernet address is 0e:00:00:00:00:01 (as we guessed before from the
-flow table.
-
-Let's configure the rest of our ports to log their packets, too::
-
- $ for i in 2 3 4 5; do ovs-vsctl set interface p$i options:pcap=p$i.pcap; done
-
-Step 3: Host Sends IP Packet
-++++++++++++++++++++++++++++
-
-Now that host 10.100.0.1 has the MAC address for its router, it can
-send an IP packet to 10.200.0.1 via the router's MAC address, like
-this::
-
- $ ovs-appctl ofproto/trace br0 in_port=p1,dl_src=00:01:02:03:04:05,dl_dst=0e:00:00:00:00:01,udp,nw_src=10.100.0.1,nw_dst=10.200.0.1,nw_ttl=64 -generate
- Flow: udp,in_port=1,vlan_tci=0x0000,dl_src=00:01:02:03:04:05,dl_dst=0e:00:00:00:00:01,nw_src=10.100.0.1,nw_dst=10.200.0.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=0,tp_dst=0
-
- bridge("br0")
- -------------
- 0. in_port=1, priority 9099, cookie 0x5adc15c0
- goto_table:1
- 1. in_port=1,vlan_tci=0x0000/0x1fff, priority 9000, cookie 0x5adc15c0
- push_vlan:0x8100
- set_field:4196->vlan_vid
- goto_table:3
- 3. ip,dl_vlan=100,dl_dst=0e:00:00:00:00:01, priority 9099, cookie 0x5adc15c0
- goto_table:4
- 4. ip,dl_vlan=100,nw_dst=10.200.0.0/24, priority 9123, cookie 0x5adc15c0
- goto_table:6
- 6. ip, priority 9130, cookie 0x5adc15c0
- CONTROLLER:128
-
- Final flow: udp,in_port=1,dl_vlan=100,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=00:01:02:03:04:05,dl_dst=0e:00:00:00:00:01,nw_src=10.100.0.1,nw_dst=10.200.0.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=0,tp_dst=0
- Megaflow: recirc_id=0,eth,ip,in_port=1,vlan_tci=0x0000/0x1fff,dl_src=00:01:02:03:04:05,dl_dst=0e:00:00:00:00:01,nw_dst=10.200.0.0/25,nw_frag=no
- Datapath actions: push_vlan(vid=100,pcp=0),userspace(pid=0,controller(reason=1,flags=0,recirc_id=6,rule_cookie=0x5adc15c0,controller_id=0,max_len=128))
-
-Observe that the packet gets recognized as destined to the router, in
-table 3, and then as properly destined to the 10.200.0.0/24 network,
-in table 4. In table 6, however, it gets sent to the controller.
-Presumably, this is because Faucet has not yet resolved an Ethernet
-address for the destination host 10.200.0.1. It probably sent out an
-ARP request. Let's take a look in the next step.
-
-Step 4: Router Broadcasts ARP Request
-+++++++++++++++++++++++++++++++++++++
-
-The router needs to know the Ethernet address of 10.200.0.1. It knows
-that, if this machine exists, it's on port ``p4`` or ``p5``, since we
-configured those ports as VLAN 200.
-
-Let's make sure::
-
- $ /usr/sbin/tcpdump -evvvr sandbox/p4.pcap
- reading from file sandbox/p4.pcap, link-type EN10MB (Ethernet)
- 16:17:43.174006 0e:00:00:00:00:01 (oui Unknown) > Broadcast, ethertype ARP (0x0806), length 60: Ethernet (len 6), IPv4 (len 4), Request who-has 10.200.0.1 tell 10.200.0.254, length 46
-
-and::
-
- $ /usr/sbin/tcpdump -evvvr sandbox/p5.pcap
- reading from file sandbox/p5.pcap, link-type EN10MB (Ethernet)
- 16:17:43.174268 0e:00:00:00:00:01 (oui Unknown) > Broadcast, ethertype ARP (0x0806), length 60: Ethernet (len 6), IPv4 (len 4), Request who-has 10.200.0.1 tell 10.200.0.254, length 46
-
-For good measure, let's make sure that it wasn't sent to ``p3``::
-
- $ /usr/sbin/tcpdump -evvvr sandbox/p3.pcap
- reading from file sandbox/p3.pcap, link-type EN10MB (Ethernet)
-
-Step 5: Host 2 Sends ARP Reply
-++++++++++++++++++++++++++++++
-
-The Faucet controller sent an ARP request, so we can send an ARP
-reply::
-
- $ ovs-appctl ofproto/trace br0 in_port=p4,dl_src=00:10:20:30:40:50,dl_dst=0e:00:00:00:00:01,dl_type=0x806,arp_spa=10.200.0.1,arp_tpa=10.200.0.254,arp_sha=00:10:20:30:40:50,arp_tha=0e:00:00:00:00:01,arp_op=2 -generate
- Flow: arp,in_port=4,vlan_tci=0x0000,dl_src=00:10:20:30:40:50,dl_dst=0e:00:00:00:00:01,arp_spa=10.200.0.1,arp_tpa=10.200.0.254,arp_op=2,arp_sha=00:10:20:30:40:50,arp_tha=0e:00:00:00:00:01
-
- bridge("br0")
- -------------
- 0. in_port=4, priority 9099, cookie 0x5adc15c0
- goto_table:1
- 1. in_port=4,vlan_tci=0x0000/0x1fff, priority 9000, cookie 0x5adc15c0
- push_vlan:0x8100
- set_field:4296->vlan_vid
- goto_table:3
- 3. arp,dl_vlan=200, priority 9131, cookie 0x5adc15c0
- goto_table:6
- 6. arp,arp_tpa=10.200.0.254, priority 9133, cookie 0x5adc15c0
- CONTROLLER:128
-
- Final flow: arp,in_port=4,dl_vlan=200,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=00:10:20:30:40:50,dl_dst=0e:00:00:00:00:01,arp_spa=10.200.0.1,arp_tpa=10.200.0.254,arp_op=2,arp_sha=00:10:20:30:40:50,arp_tha=0e:00:00:00:00:01
- Megaflow: recirc_id=0,eth,arp,in_port=4,vlan_tci=0x0000/0x1fff,dl_dst=0e:00:00:00:00:01,arp_tpa=10.200.0.254
- Datapath actions: push_vlan(vid=200,pcp=0),userspace(pid=0,controller(reason=1,flags=0,recirc_id=7,rule_cookie=0x5adc15c0,controller_id=0,max_len=128))
-
-It shows up in ``inst/faucet.log``::
-
- Jan 06 03:20:11 faucet.valve INFO DPID 1 (0x1) Adding new route 10.200.0.1/32 via 10.200.0.1 (00:10:20:30:40:50) on VLAN 200
- Jan 06 03:20:11 faucet.valve INFO DPID 1 (0x1) ARP response 10.200.0.1 (00:10:20:30:40:50) on VLAN 200
- Jan 06 03:20:11 faucet.valve INFO DPID 1 (0x1) L2 learned 00:10:20:30:40:50 (L2 type 0x0806, L3 src 10.200.0.1) on Port 4 on VLAN 200 (1 hosts total)
-
-and in the OVS flow tables::
-
- $ diff-flows flows2 br0
- +table=3 priority=9098,in_port=4,dl_vlan=200,dl_src=00:10:20:30:40:50 hard_timeout=3601 actions=goto_table:7
- ...
- +table=4 priority=9131,ip,dl_vlan=200,nw_dst=10.200.0.1 actions=set_field:4296->vlan_vid,set_field:0e:00:00:00:00:01->eth_src,set_field:00:10:20:30:40:50->eth_dst,dec_ttl,goto_table:7
- +table=4 priority=9131,ip,dl_vlan=100,nw_dst=10.200.0.1 actions=set_field:4296->vlan_vid,set_field:0e:00:00:00:00:01->eth_src,set_field:00:10:20:30:40:50->eth_dst,dec_ttl,goto_table:7
- ...
- +table=4 priority=9123,ip,dl_vlan=100,nw_dst=10.200.0.0/24 actions=goto_table:6
- +table=7 priority=9099,dl_vlan=200,dl_dst=00:10:20:30:40:50 idle_timeout=3601 actions=pop_vlan,output:4
-
-Step 6: IP Packet Delivery
-++++++++++++++++++++++++++
-
-Now both the host and the router have everything they need to deliver
-the packet. There are two ways it might happen. If Faucet's router
-is smart enough to buffer the packet that trigger ARP resolution, then
-it might have delivered it already. If so, then it should show up in
-``p4.pcap``. Let's take a look::
-
- $ /usr/sbin/tcpdump -evvvr sandbox/p4.pcap ip
- reading from file sandbox/p4.pcap, link-type EN10MB (Ethernet)
-
-Nope. That leaves the other possibility, which is that Faucet waits
-for the original sending host to re-send the packet. We can do that
-by re-running the trace::
-
- $ ovs-appctl ofproto/trace br0 in_port=p1,dl_src=00:01:02:03:04:05,dl_dst=0e:00:00:00:00:01,udp,nw_src=10.100.0.1,nw_dst=10.200.0.1,nw_ttl=64 -generate
- Flow: udp,in_port=1,vlan_tci=0x0000,dl_src=00:01:02:03:04:05,dl_dst=0e:00:00:00:00:01,nw_src=10.100.0.1,nw_dst=10.200.0.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=0,tp_dst=0
-
- bridge("br0")
- -------------
- 0. in_port=1, priority 9099, cookie 0x5adc15c0
- goto_table:1
- 1. in_port=1,vlan_tci=0x0000/0x1fff, priority 9000, cookie 0x5adc15c0
- push_vlan:0x8100
- set_field:4196->vlan_vid
- goto_table:3
- 3. ip,dl_vlan=100,dl_dst=0e:00:00:00:00:01, priority 9099, cookie 0x5adc15c0
- goto_table:4
- 4. ip,dl_vlan=100,nw_dst=10.200.0.1, priority 9131, cookie 0x5adc15c0
- set_field:4296->vlan_vid
- set_field:0e:00:00:00:00:01->eth_src
- set_field:00:10:20:30:40:50->eth_dst
- dec_ttl
- goto_table:7
- 7. dl_vlan=200,dl_dst=00:10:20:30:40:50, priority 9099, cookie 0x5adc15c0
- pop_vlan
- output:4
-
- Final flow: udp,in_port=1,vlan_tci=0x0000,dl_src=0e:00:00:00:00:01,dl_dst=00:10:20:30:40:50,nw_src=10.100.0.1,nw_dst=10.200.0.1,nw_tos=0,nw_ecn=0,nw_ttl=63,tp_src=0,tp_dst=0
- Megaflow: recirc_id=0,eth,ip,in_port=1,vlan_tci=0x0000/0x1fff,dl_src=00:01:02:03:04:05,dl_dst=0e:00:00:00:00:01,nw_dst=10.200.0.1,nw_ttl=64,nw_frag=no
- Datapath actions: set(eth(src=0e:00:00:00:00:01,dst=00:10:20:30:40:50)),set(ipv4(dst=10.200.0.1,ttl=63)),4
-
-Finally, we have working IP packet forwarding!
-
-Performance
-~~~~~~~~~~~
-
-Take another look at the megaflow line above::
-
- Megaflow: recirc_id=0,eth,ip,in_port=1,vlan_tci=0x0000/0x1fff,dl_src=00:01:02:03:04:05,dl_dst=0e:00:00:00:00:01,nw_dst=10.200.0.1,nw_ttl=64,nw_frag=no
-
-This means that (almost) any packet between these Ethernet source and
-destination hosts, destined to the given IP host, will be handled by
-this single megaflow cache entry. So regardless of the number of UDP
-packets or TCP connections that these hosts exchange, Open vSwitch
-packet processing won't need to fall back to the slow path. It is
-quite efficient.
-
-.. note::
-
- The exceptions are packets with a TTL other than 64, and fragmented
- packets. Most hosts use a constant TTL for outgoing packets, and
- fragments are rare. If either of those did change, then that would
- simply result in a new megaflow cache entry.
-
-The datapath actions might also be worth a look::
-
- Datapath actions: set(eth(src=0e:00:00:00:00:01,dst=00:10:20:30:40:50)),set(ipv4(dst=10.200.0.1,ttl=63)),4
-
-This just means that, to process these packets, the datapath changes
-the Ethernet source and destination addresses and the IP TTL, and then
-transmits the packet to port ``p4`` (also numbered 4). Notice in
-particular that, despite the OpenFlow actions that pushed, modified,
-and popped back off a VLAN, there is nothing in the datapath actions
-about VLANs. This is because the OVS flow translation code "optimizes
-out" redundant or unneeded actions, which saves time when the cache
-entry is executed later.
-
-.. note::
-
- It's not clear why the actions also re-set the IP destination
- address to its original value. Perhaps this is a minor performance
- bug.
-
-ACLs
-----
-
-Let's try out some ACLs, since they do a good job illustrating some of
-the ways that OVS tries to optimize megaflows. Update
-``inst/faucet.yaml`` to the following::
-
- dps:
- switch-1:
- dp_id: 0x1
- timeout: 3600
- arp_neighbor_timeout: 3600
- interfaces:
- 1:
- native_vlan: 100
- acl_in: 1
- 2:
- native_vlan: 100
- 3:
- native_vlan: 100
- 4:
- native_vlan: 200
- 5:
- native_vlan: 200
- vlans:
- 100:
- faucet_vips: ["10.100.0.254/24"]
- 200:
- faucet_vips: ["10.200.0.254/24"]
- routers:
- router-1:
- vlans: [100, 200]
- acls:
- 1:
- - rule:
- dl_type: 0x800
- nw_proto: 6
- tcp_dst: 8080
- actions:
- allow: 0
- - rule:
- actions:
- allow: 1
-
-Then restart Faucet::
-
- $ docker restart faucet
-
-On port 1, this new configuration blocks all traffic to TCP port 8080
-and allows all other traffic. The resulting change in the flow table
-shows this clearly too::
-
- $ diff-flows flows2 br0
- -priority=9099,in_port=1 actions=goto_table:1
- +priority=9098,in_port=1 actions=goto_table:1
- +priority=9099,tcp,in_port=1,tp_dst=8080 actions=drop
-
-The most interesting question here is performance. If you recall the
-earlier discussion, when a packet through the flow table encounters a
-match on a given field, the resulting megaflow has to match on that
-field, even if the flow didn't actually match. This is expensive.
-
-In particular, here you can see that any TCP packet is going to
-encounter the ACL flow, even if it is directed to a port other than
-8080. If that means that every megaflow for a TCP packet is going to
-have to match on the TCP destination, that's going to be bad for
-caching performance because there will be a need for a separate
-megaflow for every TCP destination port that actually appears in
-traffic, which means a lot more megaflows than otherwise. (Really, in
-practice, if such a simple ACL blew up performance, OVS wouldn't be a
-very good switch!)
-
-Let's see what happens, by sending a packet to port 80 (instead of
-8080)::
-
- $ ovs-appctl ofproto/trace br0 in_port=p1,dl_src=00:01:02:03:04:05,dl_dst=0e:00:00:00:00:01,tcp,nw_src=10.100.0.1,nw_dst=10.200.0.1,nw_ttl=64,tp_dst=80 -generate
- Flow: tcp,in_port=1,vlan_tci=0x0000,dl_src=00:01:02:03:04:05,dl_dst=0e:00:00:00:00:01,nw_src=10.100.0.1,nw_dst=10.200.0.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=0,tp_dst=80,tcp_flags=0
-
- bridge("br0")
- -------------
- 0. in_port=1, priority 9098, cookie 0x5adc15c0
- goto_table:1
- 1. in_port=1,vlan_tci=0x0000/0x1fff, priority 9000, cookie 0x5adc15c0
- push_vlan:0x8100
- set_field:4196->vlan_vid
- goto_table:3
- 3. ip,dl_vlan=100,dl_dst=0e:00:00:00:00:01, priority 9099, cookie 0x5adc15c0
- goto_table:4
- 4. ip,dl_vlan=100,nw_dst=10.200.0.0/24, priority 9123, cookie 0x5adc15c0
- goto_table:6
- 6. ip, priority 9130, cookie 0x5adc15c0
- CONTROLLER:128
-
- Final flow: tcp,in_port=1,dl_vlan=100,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=00:01:02:03:04:05,dl_dst=0e:00:00:00:00:01,nw_src=10.100.0.1,nw_dst=10.200.0.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=0,tp_dst=80,tcp_flags=0
- Megaflow: recirc_id=0,eth,tcp,in_port=1,vlan_tci=0x0000/0x1fff,dl_src=00:01:02:03:04:05,dl_dst=0e:00:00:00:00:01,nw_dst=10.200.0.1,nw_frag=no,tp_dst=0x0/0xf000
- Datapath actions: push_vlan(vid=100,pcp=0)
-
-Take a look at the Megaflow line and in particular the match on
-``tp_dst``, which says ``tp_dst=0x0/0xf000``. What this means is that
-the megaflow matches on only the top 4 bits of the TCP destination
-port. That works because::
-
- 80 (base 10) == 0000,0000,0101,0000 (base 2)
- 8080 (base 10) == 0001,1111,1001,0000 (base 2)
-
-and so by matching on only the top 4 bits, rather than all 16, the OVS
-fast path can distinguish port 80 from port 8080. This allows this
-megaflow to match one-sixteenth of the TCP destination port address
-space, rather than just 1/65536th of it.
-
-.. note::
-
- The algorithm OVS uses for this purpose isn't perfect. In this
- case, a single-bit match would work (e.g. tp_dst=0x0/0x1000), and
- would be superior since it would only match half the port address
- space instead of one-sixteenth.
-
-For details of this algorithm, please refer to ``lib/classifier.c`` in
-the Open vSwitch source tree, or our 2015 NSDI paper "The Design and
-Implementation of Open vSwitch".
-
-Finishing Up
-------------
-
-When you're done, you probably want to exit the sandbox session, with
-Control+D or ``exit``, and stop the Faucet controller with ``docker
-stop faucet; docker rm faucet``.
-
-Further Directions
-------------------
-
-We've looked a fair bit at how Faucet interacts with Open vSwitch. If
-you still have some interest, you might want to explore some of these
-directions:
-
-* Adding more than one switch. Faucet can control multiple switches
- but we've only been simulating one of them. It's easy enough to
- make a single OVS instance act as multiple switches (just
- ``ovs-vsctl add-br`` another bridge), or you could use genuinely
- separate OVS instances.
-
-* Additional features. Faucet has more features than we've
- demonstrated, such as IPv6 routing and port mirroring. These should
- also interact gracefully with Open vSwitch.
-
-* Real performance testing. We've looked at how flows and traces
- **should** demonstrate good performance, but of course there's no
- proof until it actually works in practice. We've also only tested
- with trivial configurations. Open vSwitch can scale to millions of
- OpenFlow flows, but the scaling in practice depends on the
- particular flow tables and traffic patterns, so it's valuable to
- test with large configurations, either in the way we've done it or
- with real traffic.
diff --git a/Documentation/tutorials/index.rst b/Documentation/tutorials/index.rst
index 35340ee56..4f3e3103d 100644
--- a/Documentation/tutorials/index.rst
+++ b/Documentation/tutorials/index.rst
@@ -39,11 +39,7 @@ vSwitch.
.. toctree::
:maxdepth: 2
- faucet
- ipsec
- ovs-advanced
ovn-sandbox
ovn-openstack
ovn-rbac
ovn-ipsec
- ovs-conntrack
diff --git a/Documentation/tutorials/ipsec.rst b/Documentation/tutorials/ipsec.rst
deleted file mode 100644
index b4c323513..000000000
--- a/Documentation/tutorials/ipsec.rst
+++ /dev/null
@@ -1,347 +0,0 @@
-..
- Licensed under the Apache License, Version 2.0 (the "License"); you may
- not use this file except in compliance with the License. You may obtain
- a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- License for the specific language governing permissions and limitations
- under the License.
-
- Convention for heading levels in Open vSwitch documentation:
-
- ======= Heading 0 (reserved for the title in a document)
- ------- Heading 1
- ~~~~~~~ Heading 2
- +++++++ Heading 3
- ''''''' Heading 4
-
- Avoid deeper levels because they do not render well.
-
-==================
-OVS IPsec Tutorial
-==================
-
-This document provides a step-by-step guide for running IPsec tunnel in Open
-vSwitch. A more detailed description on OVS IPsec tunnel and its
-configuration modes can be found in :doc:`/howto/ipsec`.
-
-Requirements
-------------
-
-OVS IPsec tunnel requires Linux kernel (>= v3.10.0) and OVS out-of-tree kernel
-module. The compatible IKE daemons are LibreSwan (>= v3.23) and StrongSwan
-(>= v5.3.5).
-
-.. _install-ovs-ipsec:
-
-Installing OVS and IPsec Packages
----------------------------------
-
-OVS IPsec has .deb and .rpm packages. You should use the right package
-based on your Linux distribution. This tutorial uses Ubuntu 16.04 and Fedora 27
-as examples.
-
-Ubuntu
-~~~~~~
-
-1. Follow :doc:`/intro/install/debian` to build debian packages.
-
- .. note::
-
- If you have already installed OVS, then you only need to install
- openvswitch-pki_*.deb and openvswitch-ipsec_*.deb in the following step.
- If your kernel version is below v4.13.0, update your kernel to v4.13.0 or
- above.
-
-2. Install the related packages::
-
- $ apt-get install dkms strongswan
- $ dpkg -i libopenvswitch_*.deb openvswitch-common_*.deb \
- openvswitch-switch_*.deb openvswitch-datapath-dkms_*.deb \
- python-openvswitch_*.deb openvswitch-pki_*.deb \
- openvswitch-ipsec_*.deb
-
- If the installation is successful, you should be able to see the
- ovs-monitor-ipsec daemon is running in your system.
-
-Fedora
-~~~~~~
-
-1. Follow :doc:`/intro/install/fedora` to build RPM packages.
-
-2. Install the related packages::
-
- $ dnf install python2-openvswitch libreswan \
- "kernel-devel-uname-r == $(uname -r)"
- $ rpm -i openvswitch-*.rpm openvswitch-kmod-*.rpm \
- openvswitch-openvswitch-ipsec-*.rpm
-
-3. Install firewall rules to allow ESP and IKE traffic::
-
- $ iptables -A IN_FedoraServer_allow -p esp -j ACCEPT
- $ iptables -A IN_FedoraServer_allow -p udp --dport 500 -j ACCEPT
-
-4. Run the openvswitch-ipsec service::
-
- $ systemctl start openvswitch-ipsec.service
-
- .. note::
-
- The SELinux policies might prevent openvswitch-ipsec.service to access
- certain resources. You can configure SELinux to remove such restrictions.
-
-Configuring IPsec tunnel
-------------------------
-
-Suppose you want to build IPsec tunnel between two hosts. Assume `host_1`'s
-external IP is 1.1.1.1, and `host_2`'s external IP is 2.2.2.2. Make sure
-`host_1` and `host_2` can ping each other via these external IPs.
-
-0. Set up some variables to make life easier. On both hosts, set ``ip_1`` and
- ``ip_2`` variables, e.g.::
-
- $ ip_1=1.1.1.1
- $ ip_2=2.2.2.2
-
-1. Set up OVS bridges in both hosts.
-
- In `host_1`::
-
- $ ovs-vsctl add-br br-ipsec
- $ ip addr add 192.0.0.1/24 dev br-ipsec
- $ ip link set br-ipsec up
-
- In `host_2`::
-
- $ ovs-vsctl add-br br-ipsec
- $ ip addr add 192.0.0.2/24 dev br-ipsec
- $ ip link set br-ipsec up
-
-2. Set up IPsec tunnel.
-
- There are three authentication methods. You can choose one to set up your
- IPsec tunnel.
-
- a) Using pre-shared key:
-
- In `host_1`::
-
- $ ovs-vsctl add-port br-ipsec tun -- \
- set interface tun type=gre \
- options:remote_ip=$ip_2 \
- options:psk=swordfish
-
- In `host_2`::
-
- $ ovs-vsctl add-port br-ipsec tun -- \
- set interface tun type=gre \
- options:remote_ip=$ip_1 \
- options:psk=swordfish
-
- .. note::
-
- Pre-shared key (PSK) based authentication is easy to set up but less
- secure compared with other authentication methods. You should use it
- cautiously in production systems.
-
- b) Using self-signed certificate:
-
- Generate self-signed certificate in both `host_1` and `host_2`. Then copy
- the certificate of `host_1` to `host_2` and the certificate of `host_2`
- to `host_1`.
-
- In `host_1`::
-
- $ ovs-pki req -u host_1
- $ ovs-pki self-sign host_1
- $ scp host_1-cert.pem $ip_2:/etc/keys/host_1-cert.pem
-
- In `host_2`::
-
- $ ovs-pki req -u host_2
- $ ovs-pki self-sign host_2
- $ scp host_2-cert.pem $ip_1:/etc/keys/host_2-cert.pem
-
- .. note::
-
- If you use StrongSwan as IKE daemon, please move the host certificates
- to /etc/ipsec.d/certs/ and private key to /etc/ipsec.d/private/ so that
- StrongSwan has permission to access those files.
-
- Configure IPsec tunnel to use self-signed certificates.
-
- In `host_1`::
-
- $ ovs-vsctl set Open_vSwitch . \
- other_config:certificate=/etc/keys/host_1-cert.pem \
- other_config:private_key=/etc/keys/host_1-privkey.pem
- $ ovs-vsctl add-port br-ipsec tun -- \
- set interface tun type=gre \
- options:remote_ip=$ip_2 \
- options:remote_cert=/etc/keys/host_2-cert.pem
-
- In `host_2`::
-
- $ ovs-vsctl set Open_vSwitch . \
- other_config:certificate=/etc/keys/host_2-cert.pem \
- other_config:private_key=/etc/keys/host_2-privkey.pem
- $ ovs-vsctl add-port br-ipsec tun -- \
- set interface tun type=gre \
- options:remote_ip=$ip_1 \
- options:remote_cert=/etc/keys/host_1-cert.pem
-
- .. note::
-
- The confidentiality of the private key is very critical. Don't copy it
- to places where it might be compromised. (The certificate need not be
- kept confidential.)
-
- c) Using CA-signed certificate:
-
- First you need to establish a public key infrastructure (PKI). Suppose
- you choose `host_1` to host PKI.
-
- In `host_1`::
-
- $ ovs-pki init
-
- Generate certificate requests and copy the certificate request of
- `host_2` to `host_1`.
-
- In `host_1`::
-
- $ ovs-pki req -u host_1
-
- In `host_2`::
-
- $ ovs-pki req -u host_2
- $ scp host_2-req.pem $ip_1:/etc/keys/host_2-req.pem
-
- Sign the certificate requests with the CA key. Copy `host_2`'s signed
- certificate and the CA certificate to `host_2`.
-
- In `host_1`::
-
- $ ovs-pki sign host_1 switch
- $ ovs-pki sign host_2 switch
- $ scp host_2-cert.pem $ip_2:/etc/keys/host_2-cert.pem
- $ scp /var/lib/openvswitch/pki/switchca/cacert.pem \
- $ip_2:/etc/keys/cacert.pem
-
- .. note::
-
- If you use StrongSwan as IKE daemon, please move the host certificates
- to /etc/ipsec.d/certs/, CA certificate to /etc/ipsec.d/cacerts/, and
- private key to /etc/ipsec.d/private/ so that StrongSwan has permission
- to access those files.
-
- Configure IPsec tunnel to use CA-signed certificate.
-
- In `host_1`::
-
- $ ovs-vsctl set Open_vSwitch . \
- other_config:certificate=/etc/keys/host_1-cert.pem \
- other_config:private_key=/etc/keys/host_1-privkey.pem \
- other_config:ca_cert=/etc/keys/cacert.pem
- $ ovs-vsctl add-port br-ipsec tun -- \
- set interface tun type=gre \
- options:remote_ip=$ip_2 \
- options:remote_name=host_2
-
- In `host_2`::
-
- $ ovs-vsctl set Open_vSwitch . \
- other_config:certificate=/etc/keys/host_2-cert.pem \
- other_config:private_key=/etc/keys/host_2-privkey.pem \
- other_config:ca_cert=/etc/keys/cacert.pem
- $ ovs-vsctl add-port br-ipsec tun -- \
- set interface tun type=gre \
- options:remote_ip=$ip_1 \
- options:remote_name=host_1
-
- .. note::
-
- remote_name is the common name (CN) of the signed-certificate. It must
- match the name given as the argument to the ``ovs-pki sign command``.
- It ensures that only certificate with the expected CN can be
- authenticated; otherwise, any certificate signed by the CA would be
- accepted.
-
-3. Test IPsec tunnel.
-
- Now you should have an IPsec GRE tunnel running between two hosts. To verify
- it, in `host_1`::
-
- $ ping 192.0.0.2 &
- $ tcpdump -ni any net $ip_2
-
- You should be able to see that ESP packets are being sent from `host_1` to
- `host_2`.
-
-Troubleshooting
----------------
-
-The ``ovs-monitor-ipsec`` daemon manages and monitors the IPsec tunnel state.
-Use the following ``ovs-appctl`` command to view ``ovs-monitor-ipsec`` internal
-representation of tunnel configuration::
-
- $ ovs-appctl -t ovs-monitor-ipsec tunnels/show
-
-If there is misconfiguration, then ``ovs-appctl`` should indicate why.
-For example::
-
- Interface name: gre0 v5 (CONFIGURED) <--- Should be set to CONFIGURED.
- Otherwise, error message will
- be provided
- Tunnel Type: gre
- Remote IP: 2.2.2.2
- SKB mark: None
- Local cert: None
- Local name: None
- Local key: None
- Remote cert: None
- Remote name: None
- CA cert: None
- PSK: swordfish
- Ofport: 1 <--- Whether ovs-vswitchd has assigned Ofport
- number to this Tunnel Port
- CFM state: Up <--- Whether CFM declared this tunnel healthy
- Kernel policies installed:
- ... <--- IPsec policies for this OVS tunnel in
- Linux Kernel installed by strongSwan
- Kernel security associations installed:
- ... <--- IPsec security associations for this OVS
- tunnel in Linux Kernel installed by
- strongswan
- IPsec connections that are active:
- ... <--- IPsec "connections" for this OVS
- tunnel
-
-If you don't see any active connections, try to run the following command to
-refresh the ``ovs-monitor-ipsec`` daemon::
-
- $ ovs-appctl -t ovs-monitor-ipsec refresh
-
-You can also check the logs of the ``ovs-monitor-ipsec`` daemon and the IKE
-daemon to locate issues. ``ovs-monitor-ipsec`` outputs log messages to
-/var/log/openvswitch/ovs-monitor-ipsec.log.
-
-Bug Reporting
--------------
-
-If you think you may have found a bug with security implications, like
-
-1. IPsec protected tunnel accepted packets that came unencrypted; OR
-2. IPsec protected tunnel allowed packets to leave unencrypted;
-
-Then report such bugs according to :doc:`/internals/security`.
-
-If bug does not have security implications, then report it according to
-instructions in :doc:`/internals/bugs`.
-
-If you have suggestions to improve this tutorial, please send a email to
-ovs-discuss at openvswitch.org.
diff --git a/Documentation/tutorials/ovn-ipsec.rst b/Documentation/tutorials/ovn-ipsec.rst
index feb695ea3..e0c702a04 100644
--- a/Documentation/tutorials/ovn-ipsec.rst
+++ b/Documentation/tutorials/ovn-ipsec.rst
@@ -34,8 +34,8 @@ manipulated. More details about the OVN IPsec design can be found in
``ovn-architecture``\(7) manpage.
This document assumes OVN is installed in your system and runs normally. Also,
-you need to install OVS IPsec packages in each chassis (refer to
-:ref:`install-ovs-ipsec`).
+you need to install OVS IPsec packages in each chassis (refer to Open vSwitch
+documentation on ipsec).
Generating Certificates and Keys
--------------------------------
diff --git a/Documentation/tutorials/ovn-sandbox.rst b/Documentation/tutorials/ovn-sandbox.rst
index b906b799d..3acc7b210 100644
--- a/Documentation/tutorials/ovn-sandbox.rst
+++ b/Documentation/tutorials/ovn-sandbox.rst
@@ -33,8 +33,8 @@ ovn-architecture_, but this tutorial lets you quickly see it in action.
Getting Started
---------------
-For some general information about ``ovs-sandbox``, see the "Getting Started"
-section of :doc:`ovs-advanced`.
+For some general information about ``ovs-sandbox``, see the Open vSwitch
+documentaion on ``ovs-sandbox``.
``ovs-sandbox`` does not include OVN support by default. To enable OVN, you
must pass the ``--ovn`` flag. For example, if running it straight from the OVS
@@ -64,8 +64,8 @@ Using GDB
---------
GDB support is not required to go through the tutorial. See the "Using GDB"
-section of :doc:`ovs-advanced` for more info. Additional flags exist for
-launching the debugger for the OVN programs::
+section of ovs-advanced in Open vSwitch documentation for more info.
+Additional flags exist for launching the debugger for the OVN programs::
--gdb-ovn-northd
--gdb-ovn-controller
diff --git a/Documentation/tutorials/ovs-advanced.rst b/Documentation/tutorials/ovs-advanced.rst
deleted file mode 100644
index fa9fdc7bf..000000000
--- a/Documentation/tutorials/ovs-advanced.rst
+++ /dev/null
@@ -1,941 +0,0 @@
-..
- Licensed under the Apache License, Version 2.0 (the "License"); you may
- not use this file except in compliance with the License. You may obtain
- a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- License for the specific language governing permissions and limitations
- under the License.
-
- Convention for heading levels in Open vSwitch documentation:
-
- ======= Heading 0 (reserved for the title in a document)
- ------- Heading 1
- ~~~~~~~ Heading 2
- +++++++ Heading 3
- ''''''' Heading 4
-
- Avoid deeper levels because they do not render well.
-
-==============================
-Open vSwitch Advanced Features
-==============================
-
-Many tutorials cover the basics of OpenFlow. This is not such a tutorial.
-Rather, a knowledge of the basics of OpenFlow is a prerequisite. If you do not
-already understand how an OpenFlow flow table works, please go read a basic
-tutorial and then continue reading here afterward.
-
-It is also important to understand the basics of Open vSwitch before you begin.
-If you have never used ovs-vsctl or ovs-ofctl before, you should learn a little
-about them before proceeding.
-
-Most of the features covered in this tutorial are Open vSwitch extensions to
-OpenFlow. Also, most of the features in this tutorial are specific to the
-software Open vSwitch implementation. If you are using an Open vSwitch port to
-an ASIC-based hardware switch, this tutorial will not help you.
-
-This tutorial does not cover every aspect of the features that it mentions.
-You can find the details elsewhere in the Open vSwitch documentation,
-especially ``ovs-ofctl(8)`` and the comments in the
-``include/openflow/nicira-ext.h`` and ``include/openvswitch/meta-flow.h``
-header files.
-
-Getting Started
----------------
-
-This is a hands-on tutorial. To get the most out of it, you will need Open
-vSwitch binaries. You do not, on the other hand, need any physical networking
-hardware or even supervisor privilege on your system. Instead, we will use a
-script called ``ovs-sandbox``, which accompanies the tutorial, that constructs
-a software simulated network environment based on Open vSwitch.
-
-You can use ``ovs-sandbox`` three ways:
-
-* If you have already installed Open vSwitch on your system, then you should be
- able to just run ``ovs-sandbox`` from this directory without any options.
-
-* If you have not installed Open vSwitch (and you do not want to install it),
- then you can build Open vSwitch according to the instructions in
- :doc:`/intro/install/general`, without installing it. Then run
- ``./ovs-sandbox -b DIRECTORY`` from this directory, substituting the Open
- vSwitch build directory for ``DIRECTORY``.
-
-* As a slight variant on the latter, you can run ``make sandbox`` from an Open
- vSwitch build directory.
-
-When you run ``ovs-sandbox``, it does the following:
-
-1. **CAUTION:** Deletes any subdirectory of the current directory named
- "sandbox" and any files in that directory.
-
-2. Creates a new directory "sandbox" in the current directory.
-
-3. Sets up special environment variables that ensure that Open vSwitch programs
- will look inside the "sandbox" directory instead of in the Open vSwitch
- installation directory.
-
-4. If you are using a built but not installed Open vSwitch, installs the Open
- vSwitch manpages in a subdirectory of "sandbox" and adjusts the ``MANPATH``
- environment variable to point to this directory. This means that you can
- use, for example, ``man ovs-vsctl`` to see a manpage for the ``ovs-vsctl``
- program that you built.
-
-5. Creates an empty Open vSwitch configuration database under "sandbox".
-
-6. Starts ``ovsdb-server`` running under "sandbox".
-
-7. Starts ``ovs-vswitchd`` running under "sandbox", passing special options
- that enable a special "dummy" mode for testing.
-
-8. Starts a nested interactive shell inside "sandbox".
-
-At this point, you can run all the usual Open vSwitch utilities from the nested
-shell environment. You can, for example, use ``ovs-vsctl`` to create a bridge::
-
- $ ovs-vsctl add-br br0
-
-From Open vSwitch's perspective, the bridge that you create this way is as real
-as any other. You can, for example, connect it to an OpenFlow controller or
-use ``ovs-ofctl`` to examine and modify it and its OpenFlow flow table. On the
-other hand, the bridge is not visible to the operating system's network stack,
-so ``ip`` cannot see it or affect it, which means that utilities like ``ping``
-and ``tcpdump`` will not work either. (That has its good side, too: you can't
-screw up your computer's network stack by manipulating a sandboxed OVS.)
-
-When you're done using OVS from the sandbox, exit the nested shell (by entering
-the "exit" shell command or pressing Control+D). This will kill the daemons
-that ``ovs-sandbox`` started, but it leaves the "sandbox" directory and its
-contents in place.
-
-The sandbox directory contains log files for the Open vSwitch dameons. You can
-examine them while you're running in the sandboxed environment or after you
-exit.
-
-Using GDB
----------
-
-GDB support is not required to go through the tutorial. It is added in case
-user wants to explore the internals of OVS programs.
-
-GDB can already be used to debug any running process, with the usual
-``gdb <program> <process-id>`` command.
-
-``ovs-sandbox`` also has a ``-g`` option for launching ovs-vswitchd under GDB.
-This option can be handy for setting break points before ovs-vswitchd runs, or
-for catching early segfaults. Similarly, a ``-d`` option can be used to run
-ovsdb-server under GDB. Both options can be specified at the same time.
-
-In addition, a ``-e`` option also launches ovs-vswitchd under GDB. However,
-instead of displaying a ``gdb>`` prompt and waiting for user input,
-ovs-vswitchd will start to execute immediately. ``-r`` option is the
-corresponding option for running ovsdb-server under gdb with immediate
-execution.
-
-To avoid GDB mangling with the sandbox sub shell terminal, ``ovs-sandbox``
-starts a new xterm to run each GDB session. For systems that do not support X
-windows, GDB support is effectively disabled.
-
-When launching sandbox through the build tree's make file, the ``-g`` option
-can be passed via the ``SANDBOXFLAGS`` environment variable. ``make sandbox
-SANDBOXFLAGS=-g`` will start the sandbox with ovs-vswitchd running under GDB in
-its own xterm if X is available.
-
-In addition, a set of GDB macros are available in ``utilities/gdb/ovs_gdb.py``.
-Which are able to dump various internal data structures. See the header of the
-file itself for some more details and an example.
-
-Motivation
-----------
-
-The goal of this tutorial is to demonstrate the power of Open vSwitch flow
-tables. The tutorial works through the implementation of a MAC-learning switch
-with VLAN trunk and access ports. Outside of the Open vSwitch features that we
-will discuss, OpenFlow provides at least two ways to implement such a switch:
-
-1. An OpenFlow controller to implement MAC learning in a "reactive" fashion.
- Whenever a new MAC appears on the switch, or a MAC moves from one switch
- port to another, the controller adjusts the OpenFlow flow table to match.
-
-2. The "normal" action. OpenFlow defines this action to submit a packet to
- "the traditional non-OpenFlow pipeline of the switch". That is, if a flow
- uses this action, then the packets in the flow go through the switch in the
- same way that they would if OpenFlow was not configured on the switch.
-
-Each of these approaches has unfortunate pitfalls. In the first approach,
-using an OpenFlow controller to implement MAC learning, has a significant cost
-in terms of network bandwidth and latency. It also makes the controller more
-difficult to scale to large numbers of switches, which is especially important
-in environments with thousands of hypervisors (each of which contains a virtual
-OpenFlow switch). MAC learning at an OpenFlow controller also behaves poorly
-if the OpenFlow controller fails, slows down, or becomes unavailable due to
-network problems.
-
-The second approach, using the "normal" action, has different problems. First,
-little about the "normal" action is standardized, so it behaves differently on
-switches from different vendors, and the available features and how those
-features are configured (usually not through OpenFlow) varies widely. Second,
-"normal" does not work well with other OpenFlow actions. It is
-"all-or-nothing", with little potential to adjust its behavior slightly or to
-compose it with other features.
-
-Scenario
---------
-
-We will construct Open vSwitch flow tables for a VLAN-capable,
-MAC-learning switch that has four ports:
-
-p1
- a trunk port that carries all VLANs, on OpenFlow port 1.
-
-p2
- an access port for VLAN 20, on OpenFlow port 2.
-
-p3, p4
- both access ports for VLAN 30, on OpenFlow ports 3 and 4, respectively.
-
-.. note::
- The ports' names are not significant. You could call them eth1 through eth4,
- or any other names you like.
-
-.. note::
- An OpenFlow switch always has a "local" port as well. This scenario won't
- use the local port.
-
-Our switch design will consist of five main flow tables, each of which
-implements one stage in the switch pipeline:
-
-Table 0
- Admission control.
-
-Table 1
- VLAN input processing.
-
-Table 2
- Learn source MAC and VLAN for ingress port.
-
-Table 3
- Look up learned port for destination MAC and VLAN.
-
-Table 4
- Output processing.
-
-The section below describes how to set up the scenario, followed by a section
-for each OpenFlow table.
-
-You can cut and paste the ``ovs-vsctl`` and ``ovs-ofctl`` commands in each of
-the sections below into your ``ovs-sandbox`` shell. They are also available as
-shell scripts in this directory, named ``t-setup``, ``t-stage0``, ``t-stage1``,
-..., ``t-stage4``. The ``ovs-appctl`` test commands are intended for cutting
-and pasting and are not supplied separately.
-
-Setup
------
-
-To get started, start ``ovs-sandbox``. Inside the interactive shell that it
-starts, run this command::
-
- $ ovs-vsctl add-br br0 -- set Bridge br0 fail-mode=secure
-
-This command creates a new bridge "br0" and puts "br0" into so-called
-"fail-secure" mode. For our purpose, this just means that the OpenFlow flow
-table starts out empty.
-
-.. note::
- If we did not do this, then the flow table would start out with a single flow
- that executes the "normal" action. We could use that feature to yield a
- switch that behaves the same as the switch we are currently building, but
- with the caveats described under "Motivation" above.)
-
-The new bridge has only one port on it so far, the "local port" br0. We need
-to add ``p1``, ``p2``, ``p3``, and ``p4``. A shell ``for`` loop is one way to
-do it::
-
- for i in 1 2 3 4; do
- ovs-vsctl add-port br0 p$i -- set Interface p$i ofport_request=$i
- ovs-ofctl mod-port br0 p$i up
- done
-
-In addition to adding a port, the ``ovs-vsctl`` command above sets its
-``ofport_request`` column to ensure that port ``p1`` is assigned OpenFlow port
-1, ``p2`` is assigned OpenFlow port 2, and so on.
-
-.. note::
- We could omit setting the ofport_request and let Open vSwitch choose port
- numbers for us, but it's convenient for the purposes of this tutorial because
- we can talk about OpenFlow port 1 and know that it corresponds to ``p1``.
-
-The ``ovs-ofctl`` command above brings up the simulated interfaces, which are
-down initially, using an OpenFlow request. The effect is similar to ``ip link
-up``, but the sandbox's interfaces are not visible to the operating system and
-therefore ``ip`` would not affect them.
-
-We have not configured anything related to VLANs or MAC learning. That's
-because we're going to implement those features in the flow table.
-
-To see what we've done so far to set up the scenario, you can run a command
-like ``ovs-vsctl show`` or ``ovs-ofctl show br0``.
-
-Implementing Table 0: Admission control
----------------------------------------
-
-Table 0 is where packets enter the switch. We use this stage to discard
-packets that for one reason or another are invalid. For example, packets with
-a multicast source address are not valid, so we can add a flow to drop them at
-ingress to the switch with::
-
- $ ovs-ofctl add-flow br0 \
- "table=0, dl_src=01:00:00:00:00:00/01:00:00:00:00:00, actions=drop"
-
-A switch should also not forward IEEE 802.1D Spanning Tree Protocol (STP)
-packets, so we can also add a flow to drop those and other packets with
-reserved multicast protocols::
-
- $ ovs-ofctl add-flow br0 \
- "table=0, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0, actions=drop"
-
-We could add flows to drop other protocols, but these demonstrate the pattern.
-
-We need one more flow, with a priority lower than the default, so that flows
-that don't match either of the "drop" flows we added above go on to pipeline
-stage 1 in OpenFlow table 1::
-
- $ ovs-ofctl add-flow br0 "table=0, priority=0, actions=resubmit(,1)"
-
-.. note::
- The "resubmit" action is an Open vSwitch extension to OpenFlow.
-
-Testing Table 0
----------------
-
-If we were using Open vSwitch to set up a physical or a virtual switch, then we
-would naturally test it by sending packets through it one way or another,
-perhaps with common network testing tools like ``ping`` and ``tcpdump`` or more
-specialized tools like Scapy. That's difficult with our simulated switch,
-since it's not visible to the operating system.
-
-But our simulated switch has a few specialized testing tools. The most
-powerful of these tools is ``ofproto/trace``. Given a switch and the
-specification of a flow, ``ofproto/trace`` shows, step-by-step, how such a flow
-would be treated as it goes through the switch.
-
-Example 1
-~~~~~~~~~
-
-Try this command::
-
- $ ovs-appctl ofproto/trace br0 in_port=1,dl_dst=01:80:c2:00:00:05
-
-The output should look something like this::
-
- Flow: 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
-
- bridge("br0")
- -------------
- 0. dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0, priority 32768
- drop
-
- Final flow: unchanged
- Megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
- Datapath actions: drop
-
-The first line shows the flow being traced, in slightly greater detail
-than specified on the command line. It is mostly zeros because
-unspecified fields default to zeros.
-
-The second group of lines shows the packet's trip through bridge br0.
-We see, in table 0, the OpenFlow flow that the fields matched, along
-with its priority, followed by its actions, one per line. In this
-case, we see that this packet that has a reserved multicast
-destination address matches the flow that drops those packets.
-
-The final block of lines summarizes the results, which are not very
-interesting here.
-
-Example 2
-~~~~~~~~~
-
-Try another command::
-
- $ ovs-appctl ofproto/trace br0 in_port=1,dl_dst=01:80:c2:00:00:10
-
-The output should be::
-
- Flow: 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
-
- bridge("br0")
- -------------
- 0. priority 0
- resubmit(,1)
- 1. No match.
- drop
-
- Final flow: unchanged
- Megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=01:80:c2:00:00:10/ff:ff:ff:ff:ff:f0,dl_type=0x0000
- Datapath actions: drop
-
-This time the flow we handed to ``ofproto/trace`` doesn't match any of
-our "drop" flows in table 0, so it falls through to the low-priority
-"resubmit" flow. The "resubmit" causes a second lookup in OpenFlow
-table 1, described by the block of text that starts with "1." We
-haven't yet added any flows to OpenFlow table 1, so no flow actually
-matches in the second lookup. Therefore, the packet is still actually
-dropped, which means that the externally observable results would be
-identical to our first example.
-
-Implementing Table 1: VLAN Input Processing
--------------------------------------------
-
-A packet that enters table 1 has already passed basic validation in table 0.
-The purpose of table 1 is validate the packet's VLAN, based on the VLAN
-configuration of the switch port through which the packet entered the switch.
-We will also use it to attach a VLAN header to packets that arrive on an access
-port, which allows later processing stages to rely on the packet's VLAN always
-being part of the VLAN header, reducing special cases.
-
-Let's start by adding a low-priority flow that drops all packets, before we add
-flows that pass through acceptable packets. You can think of this as a
-"default drop" flow::
-
- $ ovs-ofctl add-flow br0 "table=1, priority=0, actions=drop"
-
-Our trunk port ``p1``, on OpenFlow port 1, is an easy case. ``p1`` accepts any
-packet regardless of whether it has a VLAN header or what the VLAN was, so we
-can add a flow that resubmits everything on input port 1 to the next table::
-
- $ ovs-ofctl add-flow br0 \
- "table=1, priority=99, in_port=1, actions=resubmit(,2)"
-
-On the access ports, we want to accept any packet that has no VLAN header, tag
-it with the access port's VLAN number, and then pass it along to the next
-stage::
-
- $ ovs-ofctl add-flows br0 - <<'EOF'
- table=1, priority=99, in_port=2, vlan_tci=0, actions=mod_vlan_vid:20, resubmit(,2)
- table=1, priority=99, in_port=3, vlan_tci=0, actions=mod_vlan_vid:30, resubmit(,2)
- table=1, priority=99, in_port=4, vlan_tci=0, actions=mod_vlan_vid:30, resubmit(,2)
- EOF
-
-We don't write any flows that match packets with 802.1Q that enter this stage
-on any of the access ports, so the "default drop" flow we added earlier causes
-them to be dropped, which is ordinarily what we want for access ports.
-
-.. note::
- Another variation of access ports allows ingress of packets tagged with VLAN
- 0 (aka 802.1p priority tagged packets). To allow such packets, replace
- ``vlan_tci=0`` by ``vlan_tci=0/0xfff`` above.
-
-Testing Table 1
----------------
-
-``ofproto/trace`` allows us to test the ingress VLAN flows that we added above.
-
-Example 1: Packet on Trunk Port
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Here's a test of a packet coming in on the trunk port::
-
- $ ovs-appctl ofproto/trace br0 in_port=1,vlan_tci=5
-
-The output shows the lookup in table 0, the resubmit to table 1, and the
-resubmit to table 2 (which does nothing because we haven't put anything there
-yet)::
-
- Flow: 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
-
- bridge("br0")
- -------------
- 0. priority 0
- resubmit(,1)
- 1. in_port=1, priority 99
- resubmit(,2)
- 2. No match.
- drop
-
- Final flow: unchanged
- Megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=00:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
- Datapath actions: drop
-
-Example 2: Valid Packet on Access Port
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Here's a test of a valid packet (a packet without an 802.1Q header) coming in
-on access port ``p2``::
-
- $ ovs-appctl ofproto/trace br0 in_port=2
-
-The output is similar to that for the previous case, except that it
-additionally tags the packet with ``p2``'s VLAN 20 before it passes it along to
-table 2::
-
- Flow: 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
-
- bridge("br0")
- -------------
- 0. priority 0
- resubmit(,1)
- 1. in_port=2,vlan_tci=0x0000, priority 99
- mod_vlan_vid:20
- resubmit(,2)
- 2. No match.
- drop
-
- Final flow: 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
- Megaflow: recirc_id=0,in_port=2,vlan_tci=0x0000,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=00:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
- Datapath actions: drop
-
-Example 3: Invalid Packet on Access Port
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-This tests an invalid packet (one that includes an 802.1Q header) coming in on
-access port ``p2``::
-
- $ ovs-appctl ofproto/trace br0 in_port=2,vlan_tci=5
-
-The output shows the packet matching the default drop flow::
-
- Flow: 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
-
- bridge("br0")
- -------------
- 0. priority 0
- resubmit(,1)
- 1. priority 0
- drop
-
- Final flow: unchanged
- Megaflow: recirc_id=0,in_port=2,vlan_tci=0x0005,dl_src=00:00:00:00:00:00/01:00:00:00:00:00,dl_dst=00:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
- Datapath actions: drop
-
-Implementing Table 2: MAC+VLAN Learning for Ingress Port
---------------------------------------------------------
-
-This table allows the switch we're implementing to learn that the packet's
-source MAC is located on the packet's ingress port in the packet's VLAN.
-
-.. note::
- This table is a good example why table 1 added a VLAN tag to packets that
- entered the switch through an access port. We want to associate a MAC+VLAN
- with a port regardless of whether the VLAN in question was originally part of
- the packet or whether it was an assumed VLAN associated with an access port.
-
-It only takes a single flow to do this. The following command adds it::
-
- $ ovs-ofctl add-flow br0 \
- "table=2 actions=learn(table=10, NXM_OF_VLAN_TCI[0..11], \
- NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], \
- load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]), \
- resubmit(,3)"
-
-The "learn" action (an Open vSwitch extension to OpenFlow) modifies a flow
-table based on the content of the flow currently being processed. Here's how
-you can interpret each part of the "learn" action above:
-
-``table=10``
- Modify flow table 10. This will be the MAC learning table.
-
-``NXM_OF_VLAN_TCI[0..11]``
- Make the flow that we add to flow table 10 match the same VLAN ID that the
- packet we're currently processing contains. This effectively scopes the
- MAC learning entry to a single VLAN, which is the ordinary behavior for a
- VLAN-aware switch.
-
-``NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[]``
- Make the flow that we add to flow table 10 match, as Ethernet destination,
- the Ethernet source address of the packet we're currently processing.
-
-``load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]``
- Whereas the preceding parts specify fields for the new flow to match, this
- specifies an action for the flow to take when it matches. The action is
- for the flow to load the ingress port number of the current packet into
- register 0 (a special field that is an Open vSwitch extension to OpenFlow).
-
-.. note::
- A real use of "learn" for MAC learning would probably involve two additional
- elements. First, the "learn" action would specify a hard_timeout for the new
- flow, to enable a learned MAC to eventually expire if no new packets were
- seen from a given source within a reasonable interval. Second, one would
- usually want to limit resource consumption by using the Flow_Table table in
- the Open vSwitch configuration database to specify a maximum number of flows
- in table 10.
-
-This definitely calls for examples.
-
-Testing Table 2
----------------
-
-Example 1
-~~~~~~~~~
-
-Try the following test command::
-
- $ ovs-appctl ofproto/trace br0 \
- in_port=1,vlan_tci=20,dl_src=50:00:00:00:00:01 -generate
-
-The output shows that "learn" was executed in table 2 and the
-particular flow that was added::
-
- Flow: in_port=1,vlan_tci=0x0014,dl_src=50:00:00:00:00:01,dl_dst=00:00:00:00:00:00,dl_type=0x0000
-
- bridge("br0")
- -------------
- 0. priority 0
- resubmit(,1)
- 1. in_port=1, priority 99
- resubmit(,2)
- 2. priority 32768
- learn(table=10,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15])
- -> table=10 vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:01 priority=32768 actions=load:0x1->NXM_NX_REG0[0..15]
- resubmit(,3)
- 3. No match.
- drop
-
- Final flow: unchanged
- Megaflow: recirc_id=0,in_port=1,vlan_tci=0x0014/0x1fff,dl_src=50:00:00:00:00:01,dl_dst=00:00:00:00:00:00/ff:ff:ff:ff:ff:f0,dl_type=0x0000
- Datapath actions: drop
-
-The ``-generate`` keyword is new. Ordinarily, ``ofproto/trace`` has no side
-effects: "output" actions do not actually output packets, "learn" actions do
-not actually modify the flow table, and so on. With ``-generate``, though,
-``ofproto/trace`` does execute "learn" actions. That's important now, because
-we want to see the effect of the "learn" action on table 10. You can see that
-by running::
-
- $ ovs-ofctl dump-flows br0 table=10
-
-which (omitting the ``duration`` and ``idle_age`` fields, which will vary based
-on how soon you ran this command after the previous one, as well as some other
-uninteresting fields) prints something like::
-
- NXST_FLOW reply (xid=0x4):
- table=10, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
-
-You can see that the packet coming in on VLAN ``20`` with source MAC
-``50:00:00:00:00:01`` became a flow that matches VLAN ``20`` (written in
-hexadecimal) and destination MAC ``50:00:00:00:00:01``. The flow loads port
-number ``1``, the input port for the flow we tested, into register 0.
-
-Example 2
-~~~~~~~~~
-
-Here's a second test command::
-
- $ ovs-appctl ofproto/trace br0 \
- in_port=2,dl_src=50:00:00:00:00:01 -generate
-
-The flow that this command tests has the same source MAC and VLAN as example 1,
-although the VLAN comes from an access port VLAN rather than an 802.1Q header.
-If we again dump the flows for table 10 with::
-
- $ ovs-ofctl dump-flows br0 table=10
-
-then we see that the flow we saw previously has changed to indicate that the
-learned port is port 2, as we would expect::
-
- NXST_FLOW reply (xid=0x4):
- table=10, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:01 actions=load:0x2->NXM_NX_REG0[0..15]
-
-Implementing Table 3: Look Up Destination Port
-----------------------------------------------
-
-This table figures out what port we should send the packet to based on the
-destination MAC and VLAN. That is, if we've learned the location of the
-destination (from table 2 processing some previous packet with that destination
-as its source), then we want to send the packet there.
-
-We need only one flow to do the lookup::
-
- $ ovs-ofctl add-flow br0 \
- "table=3 priority=50 actions=resubmit(,10), resubmit(,4)"
-
-The flow's first action resubmits to table 10, the table that the "learn"
-action modifies. As you saw previously, the learned flows in this table write
-the learned port into register 0. If the destination for our packet hasn't
-been learned, then there will be no matching flow, and so the "resubmit" turns
-into a no-op. Because registers are initialized to 0, we can use a register 0
-value of 0 in our next pipeline stage as a signal to flood the packet.
-
-The second action resubmits to table 4, continuing to the next pipeline stage.
-
-We can add another flow to skip the learning table lookup for multicast and
-broadcast packets, since those should always be flooded::
-
- $ ovs-ofctl add-flow br0 \
- "table=3 priority=99 dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 \
- actions=resubmit(,4)"
-
-.. note::
- We don't strictly need to add this flow, because multicast addresses will
- never show up in our learning table. (In turn, that's because we put a flow
- into table 0 to drop packets that have a multicast source address.)
-
-Testing Table 3
----------------
-
-Example
-~~~~~~~
-
-Here's a command that should cause OVS to learn that ``f0:00:00:00:00:01`` is
-on ``p1`` in VLAN ``20``::
-
- $ 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
-
-The output shows (from the "no match" looking up the resubmit to
-table 10) that the flow's destination was unknown::
-
- Flow: in_port=1,dl_vlan=20,dl_vlan_pcp=0,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01,dl_type=0x0000
-
- bridge("br0")
- -------------
- 0. priority 0
- resubmit(,1)
- 1. in_port=1, priority 99
- resubmit(,2)
- 2. priority 32768
- learn(table=10,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15])
- -> table=10 vlan_tci=0x0014/0x0fff,dl_dst=f0:00:00:00:00:01 priority=32768 actions=load:0x1->NXM_NX_REG0[0..15]
- resubmit(,3)
- 3. priority 50
- resubmit(,10)
- 10. No match.
- drop
- resubmit(,4)
- 4. No match.
- drop
-
- Final flow: unchanged
- Megaflow: recirc_id=0,in_port=1,dl_vlan=20,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01,dl_type=0x0000
- Datapath actions: drop
-
-There are two ways that you can verify that the packet's source was
-learned. The most direct way is to dump the learning table with::
-
- $ ovs-ofctl dump-flows br0 table=10
-
-which ought to show roughly the following, with extraneous details removed::
-
- table=10, vlan_tci=0x0014/0x0fff,dl_dst=f0:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
-
-.. note::
- If you tried the examples for the previous step, or if you did some of your
- own experiments, then you might see additional flows there. These
- additional flows are harmless. If they bother you, then you can remove
- them with `ovs-ofctl del-flows br0 table=10`.
-
-The other way is to inject a packet to take advantage of the learning entry.
-For example, we can inject a packet on p2 whose destination is the MAC address
-that we just learned on p1::
-
- $ 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
-
-Here is this command's output. Take a look at the lines that trace
-the ``resubmit(,10)``, showing that the packet matched the learned
-flow for the first MAC we used, loading the OpenFlow port number for
-the learned port ``p1`` into register ``0``::
-
- Flow: in_port=2,vlan_tci=0x0000,dl_src=90:00:00:00:00:01,dl_dst=f0:00:00:00:00:01,dl_type=0x0000
-
- bridge("br0")
- -------------
- 0. priority 0
- resubmit(,1)
- 1. in_port=2,vlan_tci=0x0000, priority 99
- mod_vlan_vid:20
- resubmit(,2)
- 2. priority 32768
- learn(table=10,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15])
- -> table=10 vlan_tci=0x0014/0x0fff,dl_dst=90:00:00:00:00:01 priority=32768 actions=load:0x2->NXM_NX_REG0[0..15]
- resubmit(,3)
- 3. priority 50
- resubmit(,10)
- 10. vlan_tci=0x0014/0x0fff,dl_dst=f0:00:00:00:00:01, priority 32768
- load:0x1->NXM_NX_REG0[0..15]
- resubmit(,4)
- 4. No match.
- drop
-
- Final flow: reg0=0x1,in_port=2,dl_vlan=20,dl_vlan_pcp=0,dl_src=90:00:00:00:00:01,dl_dst=f0:00:00:00:00:01,dl_type=0x0000
- Megaflow: recirc_id=0,in_port=2,vlan_tci=0x0000,dl_src=90:00:00:00:00:01,dl_dst=f0:00:00:00:00:01,dl_type=0x0000
- Datapath actions: drop
-
-If you read the commands above carefully, then you might have noticed that they
-simply have the Ethernet source and destination addresses exchanged. That
-means that if we now rerun the first ``ovs-appctl`` command above, e.g.::
-
- $ 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
-
-then we see in the output, looking at the indented "load" action
-executed in table 10, that the destination has now been learned::
-
- Flow: in_port=1,dl_vlan=20,dl_vlan_pcp=0,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01,dl_type=0x0000
-
- bridge("br0")
- -------------
- 0. priority 0
- resubmit(,1)
- 1. in_port=1, priority 99
- resubmit(,2)
- 2. priority 32768
- learn(table=10,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15])
- -> table=10 vlan_tci=0x0014/0x0fff,dl_dst=f0:00:00:00:00:01 priority=32768 actions=load:0x1->NXM_NX_REG0[0..15]
- resubmit(,3)
- 3. priority 50
- resubmit(,10)
- 10. vlan_tci=0x0014/0x0fff,dl_dst=90:00:00:00:00:01, priority 32768
- load:0x2->NXM_NX_REG0[0..15]
- resubmit(,4)
- 4. No match.
- drop
-
-
-Implementing Table 4: Output Processing
----------------------------------------
-
-At entry to stage 4, we know that register 0 contains either the desired output
-port or is zero if the packet should be flooded. We also know that the
-packet's VLAN is in its 802.1Q header, even if the VLAN was implicit because
-the packet came in on an access port.
-
-The job of the final pipeline stage is to actually output packets. The job is
-trivial for output to our trunk port ``p1``::
-
- $ ovs-ofctl add-flow br0 "table=4 reg0=1 actions=1"
-
-For output to the access ports, we just have to strip the VLAN header before
-outputting the packet::
-
- $ ovs-ofctl add-flows br0 - <<'EOF'
- table=4 reg0=2 actions=strip_vlan,2
- table=4 reg0=3 actions=strip_vlan,3
- table=4 reg0=4 actions=strip_vlan,4
- EOF
-
-The only slightly tricky part is flooding multicast and broadcast packets and
-unicast packets with unlearned destinations. For those, we need to make sure
-that we only output the packets to the ports that carry our packet's VLAN, and
-that we include the 802.1Q header in the copy output to the trunk port but not
-in copies output to access ports::
-
- $ ovs-ofctl add-flows br0 - <<'EOF'
- table=4 reg0=0 priority=99 dl_vlan=20 actions=1,strip_vlan,2
- table=4 reg0=0 priority=99 dl_vlan=30 actions=1,strip_vlan,3,4
- table=4 reg0=0 priority=50 actions=1
- EOF
-
-.. note::
- Our flows rely on the standard OpenFlow behavior that an output action will
- not forward a packet back out the port it came in on. That is, if a packet
- comes in on p1, and we've learned that the packet's destination MAC is also
- on p1, so that we end up with ``actions=1`` as our actions, the switch will
- not forward the packet back out its input port. The
- multicast/broadcast/unknown destination cases above also rely on this
- behavior.
-
-Testing Table 4
----------------
-
-Example 1: Broadcast, Multicast, and Unknown Destination
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Try tracing a broadcast packet arriving on ``p1`` in VLAN ``30``::
-
- $ ovs-appctl ofproto/trace br0 \
- in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=30
-
-The interesting part of the output is the final line, which shows that the
-switch would remove the 802.1Q header and then output the packet to ``p3``
-and ``p4``, which are access ports for VLAN ``30``::
-
- Datapath actions: pop_vlan,3,4
-
-Similarly, if we trace a broadcast packet arriving on ``p3``::
-
- $ ovs-appctl ofproto/trace br0 in_port=3,dl_dst=ff:ff:ff:ff:ff:ff
-
-then we see that it is output to ``p1`` with an 802.1Q tag and then to ``p4``
-without one::
-
- Datapath actions: push_vlan(vid=30,pcp=0),1,pop_vlan,4
-
-.. note::
- Open vSwitch could simplify the datapath actions here to just
- ``4,push_vlan(vid=30,pcp=0),1`` but it is not smart enough to do so.
-
-The following are also broadcasts, but the result is to drop the packets
-because the VLAN only belongs to the input port::
-
- $ ovs-appctl ofproto/trace br0 \
- in_port=1,dl_dst=ff:ff:ff:ff:ff:ff
- $ ovs-appctl ofproto/trace br0 \
- in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=55
-
-Try some other broadcast cases on your own::
-
- $ ovs-appctl ofproto/trace br0 \
- in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=20
- $ ovs-appctl ofproto/trace br0 \
- in_port=2,dl_dst=ff:ff:ff:ff:ff:ff
- $ ovs-appctl ofproto/trace br0 \
- in_port=4,dl_dst=ff:ff:ff:ff:ff:ff
-
-You can see the same behavior with multicast packets and with unicast
-packets whose destination has not been learned, e.g.::
-
- $ ovs-appctl ofproto/trace br0 \
- in_port=4,dl_dst=01:00:00:00:00:00
- $ ovs-appctl ofproto/trace br0 \
- in_port=1,dl_dst=90:12:34:56:78:90,dl_vlan=20
- $ ovs-appctl ofproto/trace br0 \
- in_port=1,dl_dst=90:12:34:56:78:90,dl_vlan=30
-
-Example 2: MAC Learning
-~~~~~~~~~~~~~~~~~~~~~~~
-
-Let's follow the same pattern as we did for table 3. First learn a MAC on port
-``p1`` in VLAN ``30``::
-
- $ 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
-
-You can see from the last line of output that the packet's destination is
-unknown, so it gets flooded to both ``p3`` and ``p4``, the other ports in VLAN
-``30``::
-
- Datapath actions: pop_vlan,3,4
-
-Then reverse the MACs and learn the first flow's destination on port ``p4``::
-
- $ 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
-
-The last line of output shows that the this packet's destination is known to be
-``p1``, as learned from our previous command::
-
- Datapath actions: push_vlan(vid=30,pcp=0),1
-
-Now, if we rerun our first command::
-
- $ 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
-
-...we can see that the result is no longer a flood but to the specified learned
-destination port ``p4``::
-
- Datapath actions: pop_vlan,4
-
-Contact
-=======
-
-bugs at openvswitch.org
-http://openvswitch.org/
diff --git a/Documentation/tutorials/ovs-conntrack.rst b/Documentation/tutorials/ovs-conntrack.rst
deleted file mode 100644
index 27d6e04c3..000000000
--- a/Documentation/tutorials/ovs-conntrack.rst
+++ /dev/null
@@ -1,572 +0,0 @@
-..
- Licensed under the Apache License, Version 2.0 (the "License"); you may
- not use this file except in compliance with the License. You may obtain
- a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- License for the specific language governing permissions and limitations
- under the License.
-
- Convention for heading levels in Open vSwitch documentation:
-
- ======= Heading 0 (reserved for the title in a document)
- ------- Heading 1
- ~~~~~~~ Heading 2
- +++++++ Heading 3
- ''''''' Heading 4
-
- Avoid deeper levels because they do not render well.
-
-======================
-OVS Conntrack Tutorial
-======================
-
-OVS can be used with the Connection tracking system
-where OpenFlow flow can be used to match on the state of a TCP, UDP, ICMP,
-etc., connections. (Connection tracking system supports tracking of both
-statefull and stateless protocols)
-
-This tutorial demonstrates how OVS can use the connection tracking system
-to match on the TCP segments from connection setup to connection tear down.
-It will use OVS with the Linux kernel module as the datapath for this
-tutorial. (The datapath that utilizes the openvswitch kernel module to do
-the packet processing in the Linux kernel)
-It was tested with the “master” branch of Open vSwitch.
-
-Definitions
------------
-
-**conntrack**: is a connection tracking module for stateful packet
-inspection.
-
-**pipeline**: is the packet processing pipeline which is the path taken by
-the packet when traversing through the tables where the packet matches the
-match fields of a flow in the table and performs the actions present in
-the matched flow.
-
-**network namespace**: is a way to create virtual routing domains within
-a single instance of linux kernel. Each network namespace has it's own
-instance of network tables (arp, routing) and certain interfaces attached
-to it.
-
-**flow**: used in this tutorial refers to the OpenFlow flow which can be
-programmed using an OpenFlow controller or OVS command line tools like
-ovs-ofctl which is used here. A flow will have match fields and actions.
-
-Conntrack Related Fields
-------------------------
-
-Match Fields
-~~~~~~~~~~~~
-OVS supports following match fields related to conntrack:
-
-1. **ct_state**:
-The state of a connection matching the packet.
-Possible values:
-
- - *new*
- - *est*
- - *rel*
- - *rpl*
- - *inv*
- - *trk*
- - *snat*
- - *dnat*
-
-Each of these flags is preceded by either a "+" for a flag that
-must be set, or a "-" for a flag that must be unset.
-Multiple flags can also be specified e.g. ct_state=+trk+new.
-We will see the usage of some of these flags below. For a detailed
-description, please see the OVS fields documentation at:
-http://openvswitch.org/support/dist-docs/ovs-fields.7.txt
-
-2. **ct_zone**: A zone is an independent connection tracking context which can
-be set by a ct action.
-A 16-bit ct_zone set by the most recent ct action (by an OpenFlow
-flow on a conntrack entry) can be used as a match field in
-another flow entry.
-
-3. **ct_mark**:
-The 32-bit metadata committed, by an action within the exec
-parameter to the ct action, to the connection to which the
-current packet belongs.
-
-4. **ct_label**:
-The 128-bit label committed by an action within the exec parameter to
-the ct action, to the connection to which the current packet
-belongs.
-
-5. **ct_nw_src** / **ct_ipv6_src**:
-Matches IPv4/IPv6 conntrack original direction tuple
-source address.
-
-6. **ct_nw_dst** / **ct_ipv6_dst**:
-Matches IPv4/IPv6 conntrack original direction tuple destination address.
-
-7. **ct_nw_proto**:
-Matches conntrack original direction tuple IP protocol type.
-
-8. **ct_tp_src**:
-Matches on the conntrack original direction tuple
-transport source port.
-
-9. **ct_tp_dst**:
-Matches on the conntrack original direction tuple
-transport destination port.
-
-
-Actions
-~~~~~~~
-OVS supports "ct" action related to conntrack.
-
-*ct([argument][,argument...])*
-
-The **ct** action sends the packet through the connection tracker.
-
-The following arguments are supported:
-
-1. **commit**:
-Commit the connection to the connection tracking module which
-will be stored beyond the lifetime of packet in the pipeline.
-
-2. **force**:
-The force flag may be used in addition to commit flag to effectively
-terminate the existing connection and start a new one in the
-current direction.
-
-3. **table=number**:
-Fork pipeline processing in two. The original instance of the packet
-will continue processing the current actions list as an untracked packet.
-An additional instance of the packet will be sent to the connection
-tracker, which will be re-injected into the OpenFlow pipeline to resume
-processing in table number, with the ct_state and other ct match fields set.
-
-4. **zone=value OR
-zone=src[start..end]**:
-A 16-bit context id that can be used to isolate connections into separate
-domains, allowing over‐lapping network addresses in different zones. If a
-zone is not provided, then the default is to use zone zero.
-
-5. **exec([action][,action...])**:
-Perform restricted set of actions within the context of connection tracking.
-Only actions which modify the *ct_mark* or *ct_label* fields are accepted
-within the exec action.
-
-6. **alg=<ftp/tftp>**:
-Specify alg (application layer gateway) to track specific connection
-types.
-
-7. **nat**:
-Specifies the address and port translation for the connection being tracked.
-
-
-
-Sample Topology
----------------
-This tutorial uses the following topology to carry out the tests.
-
-::
-
- + +
- | |
- | +-----+ |
- | | | |
- | | | |
- | +----------+ | OVS | +----------+ |
- | | left | | | | right | |
- | | namespace| | | |namespace | |
- +-----+ A +------+ +-----+ B +--------+
- | | | A'| | B' | | |
- | | | | | | | |
- | +----------+ | | +----------+ |
- | | | |
- | | | |
- | | | |
- | +-----+ |
- | |
- | |
- + +
- 192.168.0.X n/w 10.0.0.X n/w
-
- A = veth_l1
- A' = veth_l0
- B = veth_r1
- B' = veth_r0
-
- Diagram: Sample Topology for conntrack testing
-
-
-The steps for creation of the setup are mentioned below.
-
-Create "left" network namespace::
-
- $ ip netns add left
-
-Create "right" network namespace::
-
- $ ip netns add right
-
-Create first pair of veth interfaces::
-
- $ ip link add veth_l0 type veth peer name veth_l1
-
-Add veth_l1 to "left" network namespace::
-
- $ ip link set veth_l1 netns left
-
-Create second pair of veth interfaces::
-
- $ ip link add veth_r0 type veth peer name veth_r1
-
-Add veth_r1 to "right" network namespace::
-
- $ ip link set veth_r1 netns right
-
-Create a bridge br0::
-
- $ ovs-vsctl add-br br0
-
-Add veth_l0 and veth_r0 to br0::
-
- $ ovs-vsctl add-port br0 veth_l0
- $ ovs-vsctl add-port br0 veth_r0
-
-
-Packets generated with src/dst IP set to 192.168.0.X / 10.0.0.X
-in the "left" and the inverse in the "right" namespaces
-will appear to OVS as hosts in two networks (192.168.0.X and 10.0.0.X)
-communicating with each other.
-This is basically a simulation of two networks / subnets with hosts
-communicating with each other with OVS in middle.
-
-Tool used to generate TCP segments
-----------------------------------
-You can use scapy to generate the TCP segments. We used scapy on Ubuntu 16.04
-for the steps carried out in this testing.
-(Installation of scapy is not discussed and is out of scope of this document.)
-
-You can keep two scapy sessions active on each of the namespaces::
-
- $ sudo ip netns exec left sudo `which scapy`
-
- $ sudo ip netns exec right sudo `which scapy`
-
-Note: In case you encounter this error::
-
- ifreq = ioctl(s, SIOCGIFADDR,struct.pack("16s16x",LOOPBACK_NAME))
-
- IOError: [Errno 99] Cannot assign requested address
-
-run the command::
-
- $ sudo ip netns exec <namespace> sudo ip link set lo up
-
-
-Matching TCP packets
---------------------
-
-TCP Connection setup
-~~~~~~~~~~~~~~~~~~~~
-Two simple flows can be added in OVS which will forward
-packets from "left" to "right" and from "right" to "left"::
-
- $ ovs-ofctl add-flow br0 \
- "table=0, priority=10, in_port=veth_l0, actions=veth_r0"
-
- $ ovs-ofctl add-flow br0 \
- "table=0, priority=10, in_port=veth_r0, actions=veth_l0"
-
-Instead of adding these two flows, we will add flows to match on the
-states of the TCP segments.
-
-We will send the TCP connection setup segments namely:
-syn, syn-ack and ack between hosts 192.168.0.2 in the "left" namespace and
-10.0.0.2 in the "right" namespace.
-
-First, let's add a flow to start "tracking" a packet received at OVS.
-
-*How do we start tracking a packet?*
-
-To start tracking a packet, it first needs to match a flow, which has action
-as "ct". This action sends the packet through the connection tracker. To
-identify that a packet is an "untracked" packet, the ct_state in the flow
-match field must be set to "-trk", which means it is not a tracked packet.
-Once the packet is sent to the connection tracker, then only we will know about
-its conntrack state. (i.e. whether this packet represents start of a new
-connection or the packet belongs to an existing connection or it is
-a malformed packet and so on.)
-
-Let's add that flow::
-
- (flow #1)
- $ ovs-ofctl add-flow br0 \
- "table=0, priority=50, ct_state=-trk, tcp, in_port=veth_l0, actions=ct(table=0)"
-
-A TCP syn packet sent from "left" namespace will match flow #1
-because the packet is coming to OVS from veth_l0 port and it is not being
-tracked. (as the packet just entered OVS. All packets entering OVS for the
-first time are "untracked")
-The flow will send the packet to the connection tracker due to the action "ct".
-Also "table=0" in the "ct" action forks the pipeline processing in two. The
-original instance of packet will continue processing the current action list
-as untracked packet. (Since there are no actions after this, the original
-packet gets dropped.)
-The forked instance of the packet will be sent to the connection tracker,
-which will be re-injected into the OpenFlow pipeline to resume processing
-in table number, with the ct_state and other ct match fields set.
-In this case, the packet with the ct_state and other ct match fields comes back
-to table 0.
-
-Next, we add a flow to match on the packet coming back from conntrack::
-
- (flow #2)
- $ ovs-ofctl add-flow br0 \
- "table=0, priority=50, ct_state=+trk+new, tcp, in_port=veth_l0, actions=ct(commit),veth_r0"
-
-Now that the packet is coming back from conntrack, the ct_state would have
-the "trk" set.
-Also, if this is the first packet of the TCP connection, the ct_state "new"
-would be set. (Which is the condition here as there does not exist any TCP
-connection between hosts 192.168.0.2 and 10.0.0.2)
-The ct argument "commit" will commit the connection to the connection tracking
-module. The significance of this action is that the information about the
-connection will now be stored beyond the lifetime of the packet in the
-pipeline.
-
-Let's send the TCP syn segment using scapy (at the "left" scapy session)
-(flags=0x02 is syn)::
-
- $ >>> sendp(Ether()/IP(src="192.168.0.2", dst="10.0.0.2")/TCP(sport=1024, dport=2048, flags=0x02, seq=100), iface="veth_l1")
-
-This packet will match flow #1 and flow #2.
-
-The conntrack module will now have an entry for this connection::
-
- $ ovs-appctl dpctl/dump-conntrack | grep "192.168.0.2"
- tcp,orig=(src=192.168.0.2,dst=10.0.0.2,sport=1024,dport=2048),reply=(src=10.0.0.2,dst=192.168.0.2,sport=2048,dport=1024),protoinfo=(state=SYN_SENT)
-
-
-Note: At this stage, if the TCP syn packet is re-transmitted, it will again
-match flow #1 (since a new packet is untracked) and it will match flow #2.
-The reason it will match flow #2 is that although conntrack has information
-about the connection, but it is not in "ESTABLISHED" state, therefore it
-matches the "new" state again.
-
-Next for the TCP syn-ack from the opposite/server direction, we need
-following flows at OVS::
-
- (flow #3)
- $ ovs-ofctl add-flow br0 \
- "table=0, priority=50, ct_state=-trk, tcp, in_port=veth_r0, actions=ct(table=0)"
- (flow #4)
- $ ovs-ofctl add-flow br0 \
- "table=0, priority=50, ct_state=+trk+est, tcp, in_port=veth_r0, actions=veth_l0"
-
-
-flow #3 matches untracked packets coming back from server (10.0.0.2) and sends
-this to conntrack. (Alternatively, we could have also combined
-flow #1 and flow #3 into one flow by not having the "in_port" match)
-
-The syn-ack packet which has now gone through the conntrack has the ct_state of
-"est".
-
-Note: Conntrack puts the ct_state of the connection to "est" state when
-it sees bidirectional traffic, but till it does not get the third ack from
-client, it puts a short cleanup timer on the conntrack entry.
-
-Sending TCP syn-ack segment using scapy (at the "right" scapy session)
-(flags=0x12 is ack and syn)::
-
- $ >>> sendp(Ether()/IP(src="10.0.0.2", dst="192.168.0.2")/TCP(sport=2048, dport=1024, flags=0x12, seq=200, ack=101), iface="veth_r1")
-
-This packet will match flow #3 and flow #4.
-
-conntrack entry::
-
- $ ovs-appctl dpctl/dump-conntrack | grep "192.168.0.2"
-
- tcp,orig=(src=192.168.0.2,dst=10.0.0.2,sport=1024,dport=2048),reply=(src=10.0.0.2,dst=192.168.0.2,sport=2048,dport=1024),protoinfo=(state=ESTABLISHED)
-
-The conntrack state is "ESTABLISHED" on receiving just syn and syn-ack packets,
-but at this point if it does not receive the third ack (from client), the
-connection gets cleared up from conntrack quickly.
-
-Next, for a TCP ack from client direction, we can add following flows to
-match on the packet::
-
- (flow #5)
- $ ovs-ofctl add-flow br0 \
- "table=0, priority=50, ct_state=+trk+est, tcp, in_port=veth_l0, actions=veth_r0"
-
-Send the third TCP ack segment using scapy (at the "left" scapy session)
-(flags=0x10 is ack)::
-
- $ >>> sendp(Ether()/IP(src="192.168.0.2", dst="10.0.0.2")/TCP(sport=1024, dport=2048, flags=0x10, seq=101, ack=201), iface="veth_l1")
-
-This packet will match on flow #1 and flow #5.
-
-
-conntrack entry::
-
- $ ovs-appctl dpctl/dump-conntrack | grep "192.168.0.2"
-
- tcp,orig=(src=192.168.0.2,dst=10.0.0.2,sport=1024,dport=2048), \
- reply=(src=10.0.0.2,dst=192.168.0.2,sport=2048,dport=1024), \
- protoinfo=(state=ESTABLISHED)
-
-The conntrack state stays in "ESTABLISHED" state, but now since it has received
-the ack from client, it will stay in this state for a longer time even without
-receiving any data on this connection.
-
-TCP Data
-~~~~~~~~
-When a data segment, carrying one byte of TCP payload, is sent from
-192.168.0.2 to 10.0.0.2, the packet carrying the segment would hit flow #1
-and then flow #5.
-
-Send a TCP segment with one byte data using scapy
-(at the "left" scapy session)
-(flags=0x10 is ack)::
-
- $ >>> sendp(Ether()/IP(src="192.168.0.2", dst="10.0.0.2")/TCP(sport=1024, dport=2048, flags=0x10, seq=101, ack=201)/"X", iface="veth_l1")
-
-
-Send the TCP ack for the above segment using scapy (at the
-"right" scapy session)
-(flags=0x10 is ack)::
-
- $ >>> sendp(Ether()/IP(src="10.0.0.2", dst="192.168.0.2")/TCP(sport=2048, dport=1024, flags=0X10, seq=201, ack=102), iface="veth_r1")
-
-The acknowledgement for the data would hit flow #3 and flow #4.
-
-TCP Connection Teardown
-~~~~~~~~~~~~~~~~~~~~~~~
-There are different ways to tear down TCP connection. We will tear down the
-connection by sending "fin" from client, "fin-ack" from server followed
-by the last "ack" by client.
-
-All the packets from client to server would hit flow #1 and flow #5.
-All the packets from server to client would hit flow #3 and flow #4.
-Interesting point to note is that even when the TCP connection is going
-down, all the packets (which are actually tearing down the connection) still
-hits "+est" state. A packet, for which the conntrack
-entry *is* or *was* in "ESTABLISHED" state, would continue to match
-"+est" ct_state in OVS.
-
-Note: In fact, when the conntrack connection state is in "TIME_WAIT" state
-(after all the TCP fins and their acks are exchanged),
-a re-transmitted data packet (from 192.168.0.2 -> 10.0.0.2), still hits
-flows #1 and #5.
-
-Sending TCP fin segment using scapy (at the "left" scapy session)
-(flags=0x11 is ack and fin)::
-
- $ >>> sendp(Ether()/IP(src="192.168.0.2", dst="10.0.0.2")/TCP(sport=1024, dport=2048, flags=0x11, seq=102, ack=201), iface="veth_l1")
-
-This packet hits flow #1 and flow #5.
-
-conntrack entry::
-
- $ sudo ovs-appctl dpctl/dump-conntrack | grep "192.168.0.2"
-
- tcp,orig=(src=192.168.0.2,dst=10.0.0.2,sport=1024,dport=2048),reply=(src=10.0.0.2,dst=192.168.0.2,sport=2048,dport=1024),protoinfo=(state=FIN_WAIT_1)
-
-
-Sending TCP fin-ack segment using scapy (at the "right" scapy session)
-(flags=0x11 is ack and fin)::
-
- $ >>> sendp(Ether()/IP(src="10.0.0.2", dst="192.168.0.2")/TCP(sport=2048, dport=1024, flags=0X11, seq=201, ack=103), iface="veth_r1")
-
-This packet hits flow #3 and flow #4.
-
-conntrack entry::
-
- $ sudo ovs-appctl dpctl/dump-conntrack | grep "192.168.0.2"
-
- tcp,orig=(src=192.168.0.2,dst=10.0.0.2,sport=1024,dport=2048),reply=(src=10.0.0.2,dst=192.168.0.2,sport=2048,dport=1024),protoinfo=(state=LAST_ACK)
-
-
-Sending TCP ack segment using scapy (at the "left" scapy session)
-(flags=0x10 is ack)::
-
- $ >>> sendp(Ether()/IP(src="192.168.0.2", dst="10.0.0.2")/TCP(sport=1024, dport=2048, flags=0x10, seq=103, ack=202), iface="veth_l1")
-
-This packet hits flow #1 and flow #5.
-
-conntrack entry::
-
- $ sudo ovs-appctl dpctl/dump-conntrack | grep "192.168.0.2"
-
- tcp,orig=(src=192.168.0.2,dst=10.0.0.2,sport=1024,dport=2048),reply=(src=10.0.0.2,dst=192.168.0.2,sport=2048,dport=1024),protoinfo=(state=TIME_WAIT)
-
-
-Summary
--------
-
-Following table summarizes the TCP segments exchanged against the flow
-match fields
-
- +-------------------------------------------------------+-------------------+
- | TCP Segment |ct_state(flow#) |
- +=======================================================+===================+
- | **Connection Setup** | |
- +-------------------------------------------------------+-------------------+
- |192.168.0.2 → 10.0.0.2 [SYN] Seq=0 | -trk(#1) then |
- | | +trk+new(#2) |
- +-------------------------------------------------------+-------------------+
- |10.0.0.2 → 192.168.0.2 [SYN, ACK] Seq=0 Ack=1 | -trk(#3) then |
- | | +trk+est(#4) |
- +-------------------------------------------------------+-------------------+
- |192.168.0.2 → 10.0.0.2 [ACK] Seq=1 Ack=1 | -trk(#1) then |
- | | +trk+est(#5) |
- +-------------------------------------------------------+-------------------+
- | **Data Transfer** | |
- +-------------------------------------------------------+-------------------+
- |192.168.0.2 → 10.0.0.2 [ACK] Seq=1 Ack=1 | -trk(#1) then |
- | | +trk+est(#5) |
- +-------------------------------------------------------+-------------------+
- |10.0.0.2 → 192.168.0.2 [ACK] Seq=1 Ack=2 | -trk(#3) then |
- | | +trk+est(#4) |
- +-------------------------------------------------------+-------------------+
- | **Connection Teardown** | |
- +-------------------------------------------------------+-------------------+
- |192.168.0.2 → 10.0.0.2 [FIN, ACK] Seq=2 Ack=1 | -trk(#1) then |
- | | +trk+est(#5) |
- +-------------------------------------------------------+-------------------+
- |10.0.0.2 → 192.168.0.2 [FIN, ACK] Seq=1 Ack=3 | -trk(#3) then |
- | | +trk+est(#4) |
- +-------------------------------------------------------+-------------------+
- |192.168.0.2 → 10.0.0.2 [ACK] Seq=3 Ack=2 | -trk(#1) then |
- | | +trk+est(#5) |
- +-------------------------------------------------------+-------------------+
-
-Note: Relative sequence number and acknowledgement numbers are shown as
-captured from tshark.
-
-Flows
-~~~~~
-::
-
- (flow #1)
- $ ovs-ofctl add-flow br0 \
- "table=0, priority=50, ct_state=-trk, tcp, in_port=veth_l0, actions=ct(table=0)"
-
- (flow #2)
- $ ovs-ofctl add-flow br0 \
- "table=0, priority=50, ct_state=+trk+new, tcp, in_port=veth_l0, actions=ct(commit),veth_r0"
-
- (flow #3)
- $ ovs-ofctl add-flow br0 \
- "table=0, priority=50, ct_state=-trk, tcp, in_port=veth_r0, actions=ct(table=0)"
-
- (flow #4)
- $ ovs-ofctl add-flow br0 \
- "table=0, priority=50, ct_state=+trk+est, tcp, in_port=veth_r0, actions=veth_l0"
-
- (flow #5)
- $ ovs-ofctl add-flow br0 \
- "table=0, priority=50, ct_state=+trk+est, tcp, in_port=veth_l0, actions=veth_r0"
--
2.21.0
More information about the dev
mailing list