This patch implements one approach to using ovn-controller to implement
a software l2 gateway between logical and physical networks.
A new logical port type called "l2gateway" is introduced here. It is very
close to how localnet ports work, with the following exception:
- A localnet port makes OVN use the physical network as the
transport between hypervisors instead of tunnels. An l2gateway port still
uses tunnels between all hypervisors, and packets only go to/from the
specified physical network as needed via the chassis the l2gateway port
is bound to.
- An l2gateway port also gets bound to a chassis while a localnet port does
not. This binding is not done by ovn-controller. It is left as an
administrative function. In the case of OpenStack, the Neutron plugin
will do this.
Signed-off-by: Russell Bryant <russell@ovn.org>
Acked-by: Ryan Moats <rmoats@us.ibm.com>
Acked-by: Ben Pfaff <blp@ovn.org>
Acked-by: Justin Pettit <jpettit@ovn.org>
Ensure that the entire port binding table is processed
when chassis are added/removed or when get_local_iface_ids
finds new ports on the local vswitch.
Side effects:
- Persist local_datapaths and patch_datapaths across runs so
that changes to either can be used as a trigger to reset
incremental flow processing.
- Persist all_lports structure
- Revert commit 9baaabfff3c7df014e9acbd4c68189b568552ca9
(ovn: Fix localnet ports deletion and recreation sometimes
after restart.) as these changes are not desirable once
local_datatpath is persisted.
Signed-off-by: Ryan Moats <rmoats@us.ibm.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
OVS NAT currently cannot do snat and dnat in the same zone.
So we need two zones per gateway router.
Signed-off-by: Gurucharan Shetty <guru@ovn.org>
Acked-by: Ben Pfaff <blp@ovn.org>
Currently OVN has distributed switches and routers. When a packet
exits a container or a VM, the entire lifecycle of the packet
through multiple switches and routers are calculated in source
chassis itself. When the destination endpoint resides on a different
chassis, the packet is sent to the other chassis and it only goes
through the egress pipeline of that chassis once and eventually to
the real destination.
When the packet returns back, the same thing happens. The return
packet leaves the VM/container on the chassis where it resides.
The packet goes through all the switches and routers in the logical
pipleline on that chassis and then sent to the eventual destination
over the tunnel.
The above makes the logical pipeline very flexible and easy. But,
creates a problem for cases where you need to add stateful services
(via conntrack) on switches and routers.
For l3 gateways, we plan to leverage DNAT and SNAT functionality
and we want to apply DNAT and SNAT rules on a router. So we ideally need
the packet to go through that router in both directions in the same
chassis. To achieve this, this commit introduces a new gateway router which is
static and can be connected to your distributed router via a switch.
To make minimal changes in OVN's logical pipeline, this commit
tries to make the switch port connected to a l3 gateway router look like
a container/VM endpoint for every other chassis except the chassis
on which the l3 gateway router resides. On the chassis where the
gateway router resides, the connection looks just like a patch port.
This is achieved by the doing the following:
Introduces a new type of port_binding record called 'gateway'.
On the chassis where the gateway router resides, this port behaves just
like the port of type 'patch'. The ovn-controller on that chassis
populates the "chassis" column for this record as an indication for
other ovn-controllers of its physical location. Other ovn-controllers
treat this port as they would treat a VM/Container port on a different
chassis.
Signed-off-by: Gurucharan Shetty <guru@ovn.org>
Acked-by: Ben Pfaff <blp@ovn.org>
The new helpers get_local_datapath() and get_patched_datapath() make code
a little shorter and easier to read. They also avoid a pitfall that was
present in at least a few of the instances: CONTAINER_OF is not safe on a
null pointer, because it does a raw pointer subtraction and will change
NULL to something else. This wasn't actually a problem in these particular
cases because the value it was subtracting was zero (although arguably it
is still undefined behavior because the compiler is allowed to assume that
a pointer on which arithmetic is performed is nonnull).
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Russell Bryant <russell@ovn.org>
This commit applies a minor restructuring of this code to put the
localnet port specific code in its own block. This is mostly to make a
future patch easier to read.
Signed-off-by: Russell Bryant <russell@ovn.org>
Acked-by: Ben Pfaff <blp@ovn.org>
For non-local datapaths, if there are no patch ports attached, it
means the lflows and port bindings would never be needed on the
Chassis. Since lflow_run() and physical_run() are the bottlenecks,
skipping the processing for such lflows and port bindings can save
significant amount of CPU, at the same time largely reduce the
number of rules in local openflow tables. This is specifically
useful when most of the lswitches are created for bridged networks,
where logical router is not used.
Test precondition:
2k hypervisors, 20k lports, 200 lswitches (each with a localnet
port).
Test case:
step1: add 50 hypervisors (simulated on 1 BM with 40 cores), and
wait for flow updates complete on all new hypervisors.
step2: create a lswitch and a localnet port, create and bind 100
lports evenly on these hypervisors. Repeat this 5 times.
Before the change:
Step1 took around 20 minutes.
Step2 took 936 seconds.
After the change:
Step1 took less than 1 minute: 20x faster.
Step2 took 464 seconds: 2x faster.
Signed-off-by: Han Zhou <zhouhan@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
This reverts commit 3a83007a76bbf05144cee1fda7ad81c1c717dca7. It's really
nonobvious from the code why the condition added by that commit makes sense.
The new condition should not be necessary now that binding_run() always keeps
track of the local datapaths, since commit 7c040135cf351 (binding: Track local
datapaths even when no transaction is possible).
CC: Ramu Ramamurthy <ramu.ramamurthy@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Russell Bryant <russell@ovn.org>
when ctx->ovnsb_idl_txn is null, binding_run exits early
and does not add any local_datapaths, but patch_run
doesnt check this, and ends up deleting localnet ports,
because there are no local datapaths for them,
They get readded in a subsequent run causing unnecessary
deletion and readdition.
Signed-off-by: Ramu Ramamurthy <ramu.ramamurthy@us.ibm.com>
Signed-off-by: Russell Bryant <russell@ovn.org>
Before this patch, inter-chassis communication between VIFs of same
lswitch will always go through tunnel, which end up of modeling a
single physical network with many lswitches and pairs of lports, and
complexity in CMS like OpenStack neutron to manage the lswitches and
lports.
With this patch, inter-chassis communication can go through physical
networks via localnet port with a 1:1 mapping between lswitches and
physical networks. The pipeline becomes:
Ingress -> Egress (local) -> Ingress (remote) -> Egress
The original tunneling mechanism will still be used if there is no
localnet port configured on the lswitch.
Signed-off-by: Han Zhou <zhouhan@gmail.com>
Acked-by: Russell Bryant <russell@ovn.org>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Multiple logical ports on the same chassis that were connected to the
same physical network via localnet ports were not able to send packets
to each other. This was because ovn-controller created a single patch
port between br-int and the physical network access bridge and used it
for all localnet ports.
The fix implemented here is to create a separate patch port for every
logical port of type=localnet. An optimization is included where these
ports are only created if the localnet port is on a logical switch with
another logical port with an associated local VIF.
A nice side effect of this fix is that the code in physical.c got a lot
simpler, as localnet ports are now handled mostly like local VIFs.
Fixes: c02819293d52 ("ovn: Add "localnet" logical port type.")
Reported-by: Han Zhou <zhouhan@gmail.com>
Reported-at: http://openvswitch.org/pipermail/dev/2016-January/064413.html
Signed-off-by: Russell Bryant <russell@ovn.org>
Tested-by: Kyle Mestery <mestery@mestery.com
Acked-By: Kyle Mestery <mestery@mestery.com>
Tested-by: Han Zhou <zhouhan@gmail.com>
Tested-by: Michael Arnaldi <michael.arnaldi@mymoneyex.com>
Acked-by: Ben Pfaff <blp@ovn.org>
This implementation is suboptimal for several reasons. First, it
creates an OVS port for every OVN logical patch port, not just for the
ones that are actually useful on this hypervisor. Second, it's
wasteful to create an OVS patch port per OVN logical patch port, when
really there's no benefit to them beyond a way to identify how a
packet ingressed into a logical datapath.
There are two obvious ways to improve the situation here, by modifying
OVS:
1. Add a way to configure in OVS which fields are preserved on a
hop across an OVS patch port. If MFF_LOG_DATAPATH and
MFF_LOG_INPORT were preserved, then only a single pair of OVS
patch ports would be required regardless of the number of OVN
logical patch ports.
2. Add a new OpenFlow extension action modeled on "resubmit" that
also saves and restores the packet data and metadata (the
inability to do this is the only reason that "resubmit" can't
be used already). Or add OpenFlow extension actions to
otherwise save and restore packet data and metadata.
We should probably choose one of those in the medium to long term, but
I don't know which one.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Justin Pettit <jpettit@nicira.com>
An upcoming patch will introduce a different use for patch ports, so
ovn-patch-port would become an ambiguous name.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Justin Pettit <jpettit@nicira.com>
Calculating the patch port names from the bridge names makes sense when
there's only one pair of patch ports between a pair of bridges, but that
won't be the case for an upcoming use of patch ports.
This changes makes it easy to check for existing patch ports in
create_patch_port(), instead of in its caller, and since that seems like a
more sensible place this change also moves it there.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Justin Pettit <jpettit@nicira.com>
Until now, the code here lumped together what was necessary to create and
destroy patch ports, with what was necessary to identify the patch ports
that were needed. An upcoming patch will add new reasons to create patch
ports, so this commit more cleanly separates those two functions.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Justin Pettit <jpettit@nicira.com>
The whole point of this module is side effects on the Open vSwitch
database, so the whole thing can be skipped if those are impossible.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Justin Pettit <jpettit@nicira.com>
Upcoming patches will introduce new extensive use of patch ports and it
seems reasonable to put it into its own file.
This is mostly code motion. Code changes are limited to those necessary
to make the separated code compile, except for renaming
init_bridge_mappings() to patch_run().
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Justin Pettit <jpettit@nicira.com>