Implementation details to support trunk ports
This patch explains in details the changes needed for the OVS agent to support vlan aware vms using two different models: vlan interfaces and trunk bridge. Change-Id: I74e0748869d1a2f27db95aafadf7d104cb1a1b3d Partially-implements: blueprint vlan-aware-vms
This commit is contained in:
parent
3088e93097
commit
8817c7d14d
@ -301,6 +301,297 @@ investing in the agent-based architecture is an effective strategy,
|
||||
especially if the end result would look a lot like other maturing
|
||||
alternatives.
|
||||
|
||||
Implementation VLAN Interfaces (Option A)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
This implementation doesn't require any modification of the vif-drivers since
|
||||
Nova will plug the vif of the VM the same way as it does for traditional ports.
|
||||
|
||||
Trunk port creation
|
||||
+++++++++++++++++++
|
||||
A VM is spawned passing to Nova the port-id of a parent port associated with
|
||||
a trunk. Nova/libvirt will create the tap interface and will plug it into
|
||||
br-int or into the firewall bridge if using iptables firewall. In the
|
||||
external-ids of the port Nova will store the port ID of the parent port.
|
||||
The OVS agent detects that a new vif has been plugged. It gets
|
||||
the details of the new port and wires it.
|
||||
The agent configures it in the same way as a traditional port: packets coming out
|
||||
from the VM will be tagged using the internal VLAN ID associated to the network,
|
||||
packets going to the VM will be stripped of the VLAN ID.
|
||||
After wiring it successfully the OVS agent will send a message notifying Neutron
|
||||
server that the parent port is up. Neutron will send back to Nova an event to
|
||||
signal that the wiring was successful.
|
||||
If the parent port is associated with one or more subports the agent will process
|
||||
them as described in the next paragraph.
|
||||
|
||||
Subport creation
|
||||
++++++++++++++++
|
||||
If a subport is added to a parent port but no VM was booted using that parent port
|
||||
yet, no L2 agent will process it (because at that point the parent port is
|
||||
not bound to any host).
|
||||
When a subport is created for a parent port and a VM that uses that parent port is
|
||||
already running, the OVS agent will create a VLAN interface on the VM tap
|
||||
using the VLAN ID specified in the subport segmentation id. There's a small possibility
|
||||
that a race might occur: the firewall bridge might be created and plugged while the vif
|
||||
is not there yet. The OVS agent needs to check if the vif exists before trying to create
|
||||
a subinterface.
|
||||
Let's see how the models differ when using the iptables firewall or the ovs native
|
||||
firewall.
|
||||
|
||||
Iptables Firewall
|
||||
'''''''''''''''''
|
||||
|
||||
::
|
||||
|
||||
+----------------------------+
|
||||
| VM |
|
||||
| eth0 eth0.100 |
|
||||
+-----+-----------------+----+
|
||||
|
|
||||
|
|
||||
+---+---+ +-----+-----+
|
||||
| tap1 |-------| tap1.100 |
|
||||
+---+---+ +-----+-----+
|
||||
| |
|
||||
| |
|
||||
+---+---+ +---+---+
|
||||
| qbr1 | | qbr2 |
|
||||
+---+---+ +---+---+
|
||||
| |
|
||||
| |
|
||||
+-----+-----------------+----+
|
||||
| port 1 port 2 |
|
||||
| |
|
||||
| br-int |
|
||||
+----------------------------+
|
||||
|
||||
Let's assume the subport is on network2 and uses segmentation ID 100.
|
||||
In the case of hybrid plugging the OVS agent will have to create the firewall
|
||||
bridge (qbr2), create tap1.100 and plug it into qbr2. It will connect qbr2 to
|
||||
br-int and set the subport ID in the external-ids of port 2.
|
||||
|
||||
*Inbound traffic from the VM point of view*
|
||||
|
||||
The untagged traffic will flow from port 1 to eth0 through qbr1.
|
||||
For the traffic coming out of port 2, the internal VLAN ID of network2 will be
|
||||
stripped. The packet will then go untagged through qbr2 where
|
||||
iptables rules will filter the traffic. The tag 100 will be pushed by tap1.100
|
||||
and the packet will finally get to eth0.100.
|
||||
|
||||
*Outbound traffic from the VM point of view*
|
||||
|
||||
The untagged traffic will flow from eth0 to port1 going through qbr1 where
|
||||
firewall rules will be applied. Traffic tagged with VLAN 100 will leave eth0.100,
|
||||
go through tap1.100 where the VLAN 100 is stripped. It will reach qbr2 where
|
||||
iptables rules will be applied and go to port 2. The internal VLAN of network2
|
||||
will be pushed by br-int when the packet enters port2 because it's a tagged port.
|
||||
|
||||
|
||||
OVS Firewall case
|
||||
'''''''''''''''''
|
||||
|
||||
::
|
||||
|
||||
+----------------------------+
|
||||
| VM |
|
||||
| eth0 eth0.100 |
|
||||
+-----+-----------------+----+
|
||||
|
|
||||
|
|
||||
+---+---+ +-----+-----+
|
||||
| tap1 |-------| tap1.100 |
|
||||
+---+---+ +-----+-----+
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
+-----+-----------------+----+
|
||||
| port 1 port 2 |
|
||||
| |
|
||||
| br-int |
|
||||
+----------------------------+
|
||||
|
||||
When a subport is created the OVS agent will create the VLAN interface tap1.100 and
|
||||
plug it into br-int. Let's assume the subport is on network2.
|
||||
|
||||
*Inbound traffic from the VM point of view*
|
||||
|
||||
The traffic will flow untagged from port 1 to eth0. The traffic going out from port 2
|
||||
will be stripped of the VLAN ID assigned to network2. It will be filtered by the rules
|
||||
installed by the firewall and reach tap1.100.
|
||||
tap1.100 will tag the traffic using VLAN 100. It will then reach the VM's eth0.100.
|
||||
|
||||
*Outbound traffic from the VM point of view*
|
||||
|
||||
The untagged traffic will flow and reach port 1 where it will be tagged using the
|
||||
VLAN ID associated to the network. Traffic tagged with VLAN 100 will leave eth0.100
|
||||
reach tap1.100 where VLAN 100 will be stripped. It will then reach port2.
|
||||
It will be filtered by the rules installed by the firewall on port 2. Then the packets
|
||||
will be tagged using the internal VLAN associated to network2 by br-int since port 2 is a
|
||||
tagged port.
|
||||
|
||||
Parent port deletion
|
||||
++++++++++++++++++++
|
||||
|
||||
Deleting a port that is an active parent in a trunk is forbidden. If the parent port has
|
||||
no trunk associated (it's a "normal" port), it can be deleted.
|
||||
The OVS agent doesn't need to perform any action, the deletion will result in a removal
|
||||
of the port data from the DB.
|
||||
|
||||
|
||||
Trunk deletion
|
||||
++++++++++++++
|
||||
|
||||
When Nova deletes a VM, it deletes the VM's corresponding Neutron ports only if they were
|
||||
created by Nova when booting the VM. In the vlan-aware-vm case the parent port is passed to Nova, so
|
||||
the port data will remain in the DB after the VM deletion. Nova will delete
|
||||
the VIF of the VM (in the example tap1) as part of the VM termination. The OVS agent
|
||||
will detect that deletion and notify the Neutron server that the parent port is down.
|
||||
The OVS agent will clean up the corresponding subports as explained in the next paragraph.
|
||||
|
||||
The deletion of a trunk that is used by a VM is not allowed.
|
||||
The trunk can be deleted (leaving the parent port intact) when the parent port is not
|
||||
used by any VM. After the trunk is deleted, the parent port can also be deleted.
|
||||
|
||||
Subport deletion
|
||||
++++++++++++++++
|
||||
|
||||
Removing a subport that is associated with a parent port that was not used to boot any
|
||||
VM is a no op from the OVS agent perspective.
|
||||
When a subport associated with a parent port that was used to boot a VM is deleted,
|
||||
the OVS agent will take care of removing the firewall bridge if using iptables firewall
|
||||
and the port on br-int.
|
||||
|
||||
|
||||
Implementation Trunk Bridge (Option C)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This implementation is based on this `_etherpad <https://etherpad.openstack.org/p/trunk-bridge-tagged-patch-experiment>`.
|
||||
Credits to Bence Romsics.
|
||||
The option use_veth_interconnection=true won't be supported, it will probably be deprecated soon,
|
||||
see [1].
|
||||
|
||||
::
|
||||
|
||||
+--------------------------------+
|
||||
| VM |
|
||||
| eth0 eth0.100 |
|
||||
+-----+--------------------+-----+
|
||||
|
|
||||
|
|
||||
+-----+--------------------------+
|
||||
| tap1 |
|
||||
| br-trunk-1 |
|
||||
| |
|
||||
| tp-patch-trunk sp-patch-trunk |
|
||||
+-----+-----------------+--------+
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
+-----+-----------------+---------+
|
||||
| tp-patch-int sp-patch-int |
|
||||
| |
|
||||
| br-int |
|
||||
+---------------------------------+
|
||||
|
||||
tp-patch-trunk: trunk bridge side of the patch port that implements a trunk
|
||||
tp-patch-int: int bridge side of the patch port that implements a trunk
|
||||
sp-patch-trunk: trunk bridge side of the patch port that implements a subport
|
||||
sp-patch-int: int bridge side of the patch port that implements a subport
|
||||
|
||||
[1] https://bugs.launchpad.net/neutron/+bug/1587296
|
||||
|
||||
Trunk creation
|
||||
++++++++++++++
|
||||
|
||||
A VM is spawned passing to Nova the port-id of a parent port associated with
|
||||
a trunk. Neutron will pass to Nova the bridge where to plug the vif as part of the vif details.
|
||||
The os-vif driver creates the trunk bridge br-trunk-1 if it does not exist in plug().
|
||||
It will create the tap interface tap1 and plug it into br-trunk-1 setting the parent port ID in the external-ids.
|
||||
The OVS agent will be monitoring the creation of ports on the trunk bridges. When it detects
|
||||
that a new port has been created on the trunk bridge, it will do the following:
|
||||
|
||||
ovs-vsctl add-port br-trunk-1 tp-patch-trunk -- set Interface tp-patch-trunk type=patch options:peer=tp-patch-int
|
||||
ovs-vsctl add-port br-int tp-patch-int tag=3 -- set Interface tp-patch-int type=patch options:peer=tp-patch-trunk
|
||||
|
||||
|
||||
A patch port is created to connect the trunk bridge to the integration bridge.
|
||||
tp-patch-trunk, the trunk bridge side of the patch is not associated to any
|
||||
tag. It will carry untagged traffic.
|
||||
tp-patch-int, the br-int side the patch port is tagged with VLAN 3. We assume that the
|
||||
trunk is on network1 that on this host is associated with VLAN 3.
|
||||
The OVS agent will set the trunk ID in the external-ids of tp-patch-trunk and tp-patch-int.
|
||||
If the parent port is associated with one or more subports the agent will process them as
|
||||
described in the next paragraph.
|
||||
|
||||
Subport creation
|
||||
++++++++++++++++
|
||||
|
||||
If a subport is added to a parent port but no VM was booted using that parent port
|
||||
yet, the agent won't process the subport (because at this point there's no node
|
||||
associated with the parent port).
|
||||
When a subport is added to a parent port that is used by a VM the OVS agent will
|
||||
create a new patch port:
|
||||
|
||||
|
||||
ovs-vsctl add-port br-trunk-1 sp-patch-trunk tag=100 -- set Interface sp-patch-trunk type=patch options:peer=sp-patch-int
|
||||
ovs-vsctl add-port br-int sp-patch-int tag=5 -- set Interface sp-patch-int type=patch options:peer=sp-patch-trunk
|
||||
|
||||
This patch port connects the trunk bridge to the integration bridge.
|
||||
sp-patch-trunk, the trunk bridge side of the patch is tagged using VLAN 100.
|
||||
We assume that the segmentation ID of the subport is 100.
|
||||
sp-patch-int, the br-int side of the patch port is tagged with VLAN 5. We
|
||||
assume that the subport is on network2 that on this host uses VLAN 5.
|
||||
The OVS agent will set the subport ID in the external-ids of sp-patch-trunk and sp-patch-int.
|
||||
|
||||
*Inbound traffic from the VM point of view*
|
||||
|
||||
The traffic coming out of tp-patch-int will be stripped by br-int of VLAN 3.
|
||||
It will reach tp-patch-trunk untagged and from there tap1.
|
||||
The traffic coming out of sp-patch-int will be stripped by br-int of VLAN 5.
|
||||
It will reach sp-patch-trunk where it will be tagged with VLAN 100 and it will
|
||||
then get to tap1 tagged.
|
||||
|
||||
|
||||
*Outbound traffic from the VM point of view*
|
||||
|
||||
The untagged traffic coming from tap1 will reach tp-patch-trunk and from there
|
||||
tp-patch-int where it will be tagged using VLAN 3.
|
||||
The traffic tagged with VLAN 100 from tap1 will reach sp-patch-trunk.
|
||||
VLAN 100 will be stripped since sp-patch-trunk is a tagged port and the packet
|
||||
will reach sp-patch-int, where it's tagged using VLAN 5.
|
||||
|
||||
Parent port deletion
|
||||
++++++++++++++++++++
|
||||
|
||||
Deleting a port that is an active parent in a trunk is forbidden. If the parent port has
|
||||
no trunk associated, it can be deleted. The OVS agent doesn't need to perform any action.
|
||||
|
||||
Trunk deletion
|
||||
++++++++++++++
|
||||
|
||||
When Nova deletes a VM, it deletes the VM's corresponding Neutron ports only if they were
|
||||
created by Nova when booting the VM. In the vlan-aware-vm case the parent port is passed to Nova, so
|
||||
the port data will remain in the DB after the VM deletion. Nova will delete
|
||||
the port on the trunk bridge where the VM is plugged. The L2 agent
|
||||
will detect that and delete the trunk bridge. It will notify the Neutron server that the parent
|
||||
port is down.
|
||||
|
||||
The deletion of a trunk that is used by a VM is not allowed.
|
||||
The trunk can be deleted (leaving the parent port intact) when the parent port is not
|
||||
used by any VM. After the trunk is deleted, the parent port can also be deleted.
|
||||
|
||||
Subport deletion
|
||||
++++++++++++++++
|
||||
|
||||
The OVS agent will delete the patch port pair corresponding to the subport deleted.
|
||||
|
||||
Agent resync
|
||||
~~~~~~~~~~~~
|
||||
|
||||
During resync the agent should check that all the trunk and subports are
|
||||
still valid. It will delete the stale trunk and subports using the procedure specified
|
||||
in the previous paragraphs according to the implementation.
|
||||
|
||||
|
||||
Further Reading
|
||||
---------------
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user