adds support for vhost user reconnect.
- vhost-user reconnect is a new feature added in dpdk 16.07 and qemu 2.7. - vhost-user reconnect allows VMs using vhost-user interfaces to reconnect to the vhost-user backend if the backend terminates either as a result of a graceful shutdown or a crash with out requiring the vm to reboot. - vhost-user reconnect requires qemu to be the vhost-user server and ovs to be the client. - dpdk prior to 16.07 only supports qemu client/ dpdk server mode. - This change extends the ovs mech driver to select the correct qemu vhost user socket mode based on the available interface types reported by the agent. Change-Id: Iec89eaa597311e086c5f6e8d67308d446b07ac33 Closes-Bug: #1604924 Depends-on: Ia5da5b3ef28d1b23b217adc5196199df47b54ed9
This commit is contained in:
parent
eb5871535c
commit
ca60a91cbd
@ -127,6 +127,7 @@ EXTENSION_DRIVER_TYPE = 'ovs'
|
||||
OVS_DATAPATH_SYSTEM = 'system'
|
||||
OVS_DATAPATH_NETDEV = 'netdev'
|
||||
OVS_DPDK_VHOST_USER = 'dpdkvhostuser'
|
||||
OVS_DPDK_VHOST_USER_CLIENT = 'dpdkvhostuserclient'
|
||||
|
||||
# default ovs vhost-user socket location
|
||||
VHOST_USER_SOCKET_DIR = '/var/run/openvswitch'
|
||||
|
@ -81,12 +81,22 @@ class OpenvswitchMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
|
||||
|
||||
def get_vif_type(self, agent, context):
|
||||
caps = agent['configurations'].get('ovs_capabilities', {})
|
||||
if (a_const.OVS_DPDK_VHOST_USER in caps.get('iface_types', []) and
|
||||
agent['configurations'].get('datapath_type') ==
|
||||
a_const.OVS_DATAPATH_NETDEV):
|
||||
if (any(x in caps.get('iface_types', []) for x
|
||||
in [a_const.OVS_DPDK_VHOST_USER,
|
||||
a_const.OVS_DPDK_VHOST_USER_CLIENT]) and
|
||||
agent['configurations'].get('datapath_type') ==
|
||||
a_const.OVS_DATAPATH_NETDEV):
|
||||
return portbindings.VIF_TYPE_VHOST_USER
|
||||
return self.vif_type
|
||||
|
||||
def get_vhost_mode(self, iface_types):
|
||||
# NOTE(sean-k-mooney): this function converts the ovs vhost user
|
||||
# driver mode into the qemu vhost user mode. If OVS is the server,
|
||||
# qemu is the client and vice-versa.
|
||||
if (a_const.OVS_DPDK_VHOST_USER_CLIENT in iface_types):
|
||||
return portbindings.VHOST_USER_MODE_SERVER
|
||||
return portbindings.VHOST_USER_MODE_CLIENT
|
||||
|
||||
def get_vif_details(self, agent, context):
|
||||
vif_details = self._pre_get_vif_details(agent, context)
|
||||
self._set_bridge_name(context.current, vif_details)
|
||||
@ -107,7 +117,8 @@ class OpenvswitchMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
|
||||
|
||||
def _pre_get_vif_details(self, agent, context):
|
||||
a_config = agent['configurations']
|
||||
if a_config.get('datapath_type') != a_const.OVS_DATAPATH_NETDEV:
|
||||
vif_type = self.get_vif_type(agent, context)
|
||||
if vif_type != portbindings.VIF_TYPE_VHOST_USER:
|
||||
details = dict(self.vif_details)
|
||||
hybrid = portbindings.OVS_HYBRID_PLUG
|
||||
if hybrid in a_config:
|
||||
@ -115,13 +126,14 @@ class OpenvswitchMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
|
||||
# in the constructor if the agent specifically requests it
|
||||
details[hybrid] = a_config[hybrid]
|
||||
return details
|
||||
caps = a_config.get('ovs_capabilities', {})
|
||||
if a_const.OVS_DPDK_VHOST_USER in caps.get('iface_types', []):
|
||||
else:
|
||||
sock_path = self.agent_vhu_sockpath(agent, context.current['id'])
|
||||
caps = a_config.get('ovs_capabilities', {})
|
||||
mode = self.get_vhost_mode(caps.get('iface_types', []))
|
||||
return {
|
||||
portbindings.CAP_PORT_FILTER: False,
|
||||
portbindings.VHOST_USER_MODE:
|
||||
portbindings.VHOST_USER_MODE_CLIENT,
|
||||
portbindings.OVS_HYBRID_PLUG: False,
|
||||
portbindings.VHOST_USER_MODE: mode,
|
||||
portbindings.VHOST_USER_OVS_PLUG: True,
|
||||
portbindings.VHOST_USER_SOCKET: sock_path
|
||||
}
|
||||
|
@ -177,3 +177,62 @@ class OpenvswitchMechanismFirewallUndefinedTestCase(
|
||||
cfg.CONF.set_override('firewall_driver', '', 'SECURITYGROUP')
|
||||
self.driver = mech_openvswitch.OpenvswitchMechanismDriver()
|
||||
self.driver.initialize()
|
||||
|
||||
|
||||
class OpenvswitchMechanismDPDKTestCase(OpenvswitchMechanismBaseTestCase):
|
||||
|
||||
GOOD_MAPPINGS = {'fake_physical_network': 'fake_bridge'}
|
||||
|
||||
GOOD_TUNNEL_TYPES = ['gre', 'vxlan']
|
||||
|
||||
VHOST_CONFIGS = {'bridge_mappings': GOOD_MAPPINGS,
|
||||
'tunnel_types': GOOD_TUNNEL_TYPES,
|
||||
'datapath_type': a_const.OVS_DATAPATH_NETDEV,
|
||||
'ovs_capabilities': {
|
||||
'iface_types': [a_const.OVS_DPDK_VHOST_USER]}}
|
||||
|
||||
VHOST_SERVER_CONFIGS = {'bridge_mappings': GOOD_MAPPINGS,
|
||||
'tunnel_types': GOOD_TUNNEL_TYPES,
|
||||
'datapath_type': a_const.OVS_DATAPATH_NETDEV,
|
||||
'ovs_capabilities': {
|
||||
'iface_types': [a_const.OVS_DPDK_VHOST_USER_CLIENT]}}
|
||||
|
||||
SYSTEM_CONFIGS = {'bridge_mappings': GOOD_MAPPINGS,
|
||||
'tunnel_types': GOOD_TUNNEL_TYPES,
|
||||
'datapath_type': a_const.OVS_DATAPATH_SYSTEM,
|
||||
'ovs_capabilities': {'iface_types': []}}
|
||||
|
||||
AGENT = {'alive': True,
|
||||
'configurations': VHOST_CONFIGS,
|
||||
'host': 'host'}
|
||||
|
||||
AGENT_SERVER = {'alive': True,
|
||||
'configurations': VHOST_SERVER_CONFIGS,
|
||||
'host': 'host'}
|
||||
|
||||
AGENT_SYSTEM = {'alive': True,
|
||||
'configurations': SYSTEM_CONFIGS,
|
||||
'host': 'host'}
|
||||
|
||||
def test_get_vhost_mode(self):
|
||||
ifaces = []
|
||||
result = self.driver.get_vhost_mode(ifaces)
|
||||
self.assertEqual(portbindings.VHOST_USER_MODE_CLIENT, result)
|
||||
|
||||
ifaces = [a_const.OVS_DPDK_VHOST_USER]
|
||||
result = self.driver.get_vhost_mode(ifaces)
|
||||
self.assertEqual(portbindings.VHOST_USER_MODE_CLIENT, result)
|
||||
|
||||
ifaces = [a_const.OVS_DPDK_VHOST_USER_CLIENT]
|
||||
result = self.driver.get_vhost_mode(ifaces)
|
||||
self.assertEqual(portbindings.VHOST_USER_MODE_SERVER, result)
|
||||
|
||||
def test_get_vif_type(self):
|
||||
result = self.driver.get_vif_type(self.AGENT, None)
|
||||
self.assertEqual(portbindings.VIF_TYPE_VHOST_USER, result)
|
||||
|
||||
result = self.driver.get_vif_type(self.AGENT_SERVER, None)
|
||||
self.assertEqual(portbindings.VIF_TYPE_VHOST_USER, result)
|
||||
|
||||
result = self.driver.get_vif_type(self.AGENT_SYSTEM, None)
|
||||
self.assertEqual(portbindings.VIF_TYPE_OVS, result)
|
||||
|
@ -0,0 +1,21 @@
|
||||
---
|
||||
features:
|
||||
- vhost-user reconnect is a mechanism which allows
|
||||
a vhost-user frontend to reconnect to a vhost-user
|
||||
backend in the event the backend terminates.
|
||||
This enable a VM utilising a vhost-user interface
|
||||
to reconnect automatically to the backend e.g.
|
||||
a vSwitch without requiring the VM to reboot.
|
||||
In this release, support was added to the neutron
|
||||
Open vSwitch agent and ml2 driver for vhost-user
|
||||
reconnect.
|
||||
other:
|
||||
- vhost-user reconnect allows VMs using vhost-user
|
||||
interfaces to reconnect to the vhost-user backend if
|
||||
the backend terminates either as a result of a graceful
|
||||
shutdown or a crash without requiring the VM to reboot.
|
||||
- vhost-user reconnect requires dpdk 16.07 and qemu 2.7
|
||||
and ovs 2.6 to function. if an older qemu is used,
|
||||
reconnect will not be available but vhost-user will
|
||||
still function.
|
||||
|
Loading…
Reference in New Issue
Block a user