Fix DVR flow problems for IPv6 subnet

This code fixes DVR flow problems by changing proto='ip' to
proto='ipv6' and changing nw_dst to ipv6_dst.

When DVR is enabled, RADVD is spawned by l3 agent on each compute
node. This code also prevent IPv6 Router Advertisement from
sending to other compute nodes.

Change-Id: Id94acd85ea124eff6cfdfbfc546f5dd4ca81ef43
Closes-Bug: 1398244
Closes-Bug: 1398627
Partial-Bug: 1376325
This commit is contained in:
Xu Han Peng 2014-12-03 14:58:34 +08:00 committed by Xu Han Peng
parent 197838bb7d
commit 727417e71e
2 changed files with 294 additions and 96 deletions

View File

@ -388,23 +388,27 @@ class OVSDVRNeutronAgent(dvr_rpc.DVRAgentRpcApiMixin):
ofports = ','.join(map(str, ldm.get_compute_ofports().values()))
if csnat_ofport != constants.OFPORT_INVALID:
ofports = str(csnat_ofport) + ',' + ofports
ip_version = subnet_info['ip_version']
if ofports:
self.int_br.add_flow(table=constants.DVR_TO_SRC_MAC,
priority=2,
proto='ip',
dl_vlan=local_vlan,
nw_dst=ip_subnet,
actions="strip_vlan,mod_dl_src:%s,"
"output:%s" %
(subnet_info['gateway_mac'], ofports))
args = self._get_flow_args_by_version(
ip_version, constants.DVR_TO_SRC_MAC, local_vlan, ip_subnet,
2, ("strip_vlan,mod_dl_src:%s,output:%s" %
(subnet_info['gateway_mac'], ofports)))
self.int_br.add_flow(**args)
self.tun_br.add_flow(table=constants.DVR_PROCESS,
priority=3,
dl_vlan=local_vlan,
proto='arp',
nw_dst=subnet_info['gateway_ip'],
actions="drop")
args = {'table': constants.DVR_PROCESS,
'priority': 3,
'dl_vlan': local_vlan,
'actions': "drop"}
if ip_version == 4:
args['proto'] = 'arp'
args['nw_dst'] = subnet_info['gateway_ip']
else:
args['proto'] = 'icmp6'
args['icmp_type'] = n_const.ICMPV6_TYPE_RA
args['dl_src'] = subnet_info['gateway_mac']
self.tun_br.add_flow(**args)
self.tun_br.add_flow(table=constants.DVR_PROCESS,
priority=2,
dl_vlan=local_vlan,
@ -477,14 +481,12 @@ class OVSDVRNeutronAgent(dvr_rpc.DVRAgentRpcApiMixin):
if csnat_ofport != constants.OFPORT_INVALID:
ofports = str(csnat_ofport) + ',' + ofports
self.int_br.add_flow(table=constants.DVR_TO_SRC_MAC,
priority=2,
proto='ip',
dl_vlan=local_vlan,
nw_dst=ip_subnet,
actions="strip_vlan,mod_dl_src:%s,"
" output:%s" %
(subnet_info['gateway_mac'], ofports))
ip_version = subnet_info['ip_version']
args = self._get_flow_args_by_version(
ip_version, constants.DVR_TO_SRC_MAC, local_vlan, ip_subnet,
2, ("strip_vlan,mod_dl_src:%s,output:%s" %
(subnet_info['gateway_mac'], ofports)))
self.int_br.add_flow(**args)
def _bind_centralized_snat_port_on_dvr_subnet(self, port, fixed_ips,
device_owner, local_vlan):
@ -532,14 +534,15 @@ class OVSDVRNeutronAgent(dvr_rpc.DVRAgentRpcApiMixin):
ofports = ','.join(map(str, ldm.get_compute_ofports().values()))
ofports = str(ldm.get_csnat_ofport()) + ',' + ofports
ip_subnet = subnet_info['cidr']
self.int_br.add_flow(table=constants.DVR_TO_SRC_MAC,
priority=2,
proto='ip',
dl_vlan=local_vlan,
nw_dst=ip_subnet,
actions="strip_vlan,mod_dl_src:%s,"
" output:%s" %
(subnet_info['gateway_mac'], ofports))
# TODO(xuhanp) remove the IPv6 related add_flow once SNAT is not
# used for IPv6 DVR.
ip_version = subnet_info['ip_version']
args = self._get_flow_args_by_version(
ip_version, constants.DVR_TO_SRC_MAC, local_vlan, ip_subnet,
2, ("strip_vlan,mod_dl_src:%s,output:%s" %
(subnet_info['gateway_mac'], ofports)))
self.int_br.add_flow(**args)
def bind_port_to_dvr(self, port, network_type, fixed_ips,
device_owner, local_vlan_id):
@ -592,32 +595,39 @@ class OVSDVRNeutronAgent(dvr_rpc.DVRAgentRpcApiMixin):
dl_vlan=local_vlan,
dl_dst=ovsport.get_mac())
ldm.remove_all_compute_ofports()
ip_version = subnet_info['ip_version']
if ldm.get_csnat_ofport() != -1:
# If there is a csnat port on this agent, preserve
# the local_dvr_map state
ofports = str(ldm.get_csnat_ofport())
self.int_br.add_flow(table=constants.DVR_TO_SRC_MAC,
priority=2,
proto='ip',
dl_vlan=local_vlan,
nw_dst=ip_subnet,
actions="strip_vlan,mod_dl_src:%s,"
" output:%s" %
(subnet_info['gateway_mac'], ofports))
args = self._get_flow_args_by_version(
ip_version, constants.DVR_TO_SRC_MAC,
local_vlan, ip_subnet,
2, ("strip_vlan,mod_dl_src:%s,output:%s" %
(subnet_info['gateway_mac'], ofports)))
self.int_br.add_flow(**args)
else:
# removed port is a distributed router interface
self.int_br.delete_flows(table=constants.DVR_TO_SRC_MAC,
proto='ip', dl_vlan=local_vlan,
nw_dst=ip_subnet)
args = self._get_flow_args_by_version(
ip_version, constants.DVR_TO_SRC_MAC,
local_vlan, ip_subnet, None, None)
self.int_br.delete_flows(**args)
# remove subnet from local_dvr_map as no dvr (or) csnat
# ports available on this agent anymore
self.local_dvr_map.pop(sub_uuid, None)
self.tun_br.delete_flows(table=constants.DVR_PROCESS,
dl_vlan=local_vlan,
proto='arp',
nw_dst=subnet_info['gateway_ip'])
args = {'table': constants.DVR_PROCESS,
'dl_vlan': local_vlan}
if ip_version == 4:
args['proto'] = 'arp'
args['nw_dst'] = subnet_info['gateway_ip']
else:
args['proto'] = 'icmp6'
args['icmp_type'] = n_const.ICMPV6_TYPE_RA
args['dl_src'] = subnet_info['gateway_mac']
self.tun_br.delete_flows(**args)
ovsport.remove_subnet(sub_uuid)
self.tun_br.delete_flows(table=constants.DVR_PROCESS,
@ -649,7 +659,7 @@ class OVSDVRNeutronAgent(dvr_rpc.DVRAgentRpcApiMixin):
ldm.remove_compute_ofport(port.vif_id)
ofports = ','.join(map(str, ldm.get_compute_ofports().values()))
ip_subnet = subnet_info['cidr']
ip_version = subnet_info['ip_version']
# first remove this vm port rule
self.int_br.delete_flows(table=constants.DVR_TO_SRC_MAC,
dl_vlan=local_vlan,
@ -658,33 +668,29 @@ class OVSDVRNeutronAgent(dvr_rpc.DVRAgentRpcApiMixin):
# If there is a csnat port on this agent, preserve
# the local_dvr_map state
ofports = str(ldm.get_csnat_ofport()) + ',' + ofports
self.int_br.add_flow(table=constants.DVR_TO_SRC_MAC,
priority=2,
proto='ip',
dl_vlan=local_vlan,
nw_dst=ip_subnet,
actions="strip_vlan,mod_dl_src:%s,"
" output:%s" %
(subnet_info['gateway_mac'], ofports))
args = self._get_flow_args_by_version(
ip_version, constants.DVR_TO_SRC_MAC,
local_vlan, ip_subnet,
2, ("strip_vlan,mod_dl_src:%s,output:%s" %
(subnet_info['gateway_mac'], ofports)))
self.int_br.add_flow(**args)
else:
if ofports:
self.int_br.add_flow(table=constants.DVR_TO_SRC_MAC,
priority=2,
proto='ip',
dl_vlan=local_vlan,
nw_dst=ip_subnet,
actions="strip_vlan,mod_dl_src:%s,"
" output:%s" %
(subnet_info['gateway_mac'],
ofports))
args = self._get_flow_args_by_version(
ip_version, constants.DVR_TO_SRC_MAC,
local_vlan, ip_subnet,
2, ("strip_vlan,mod_dl_src:%s,output:%s" %
(subnet_info['gateway_mac'], ofports)))
self.int_br.add_flow(**args)
else:
# remove the flow altogether, as no ports (both csnat/
# compute) are available on this subnet in this
# agent
self.int_br.delete_flows(table=constants.DVR_TO_SRC_MAC,
proto='ip',
dl_vlan=local_vlan,
nw_dst=ip_subnet)
args = self._get_flow_args_by_version(
ip_version, constants.DVR_TO_SRC_MAC,
local_vlan, ip_subnet, None, None)
self.int_br.delete_flows(**args)
# release port state
self.local_ports.pop(port.vif_id, None)
@ -708,22 +714,23 @@ class OVSDVRNeutronAgent(dvr_rpc.DVRAgentRpcApiMixin):
self.int_br.delete_flows(table=constants.DVR_TO_SRC_MAC,
dl_vlan=local_vlan,
dl_dst=ovsport.get_mac())
ofports = ','.join(map(str, ldm.get_compute_ofports().values()))
ip_version = subnet_info['ip_version']
if ofports:
self.int_br.add_flow(table=constants.DVR_TO_SRC_MAC,
priority=2,
proto='ip',
dl_vlan=local_vlan,
nw_dst=ip_subnet,
actions="strip_vlan,mod_dl_src:%s,"
" output:%s" %
(subnet_info['gateway_mac'], ofports))
# TODO(xuhanp) remove the IPv6 related add_flow once SNAT is not
# used for IPv6 DVR.
args = self._get_flow_args_by_version(
ip_version, constants.DVR_TO_SRC_MAC,
local_vlan, ip_subnet,
2, ("strip_vlan,mod_dl_src:%s,output:%s" %
(subnet_info['gateway_mac'], ofports)))
self.int_br.add_flow(**args)
else:
self.int_br.delete_flows(table=constants.DVR_TO_SRC_MAC,
proto='ip',
dl_vlan=local_vlan,
nw_dst=ip_subnet)
args = self._get_flow_args_by_version(
ip_version, constants.DVR_TO_SRC_MAC,
local_vlan, ip_subnet, None, None)
self.int_br.delete_flows(**args)
if not ldm.is_dvr_owned():
# if not owned by DVR (only used for csnat), remove this
# subnet state altogether
@ -732,6 +739,27 @@ class OVSDVRNeutronAgent(dvr_rpc.DVRAgentRpcApiMixin):
# release port state
self.local_ports.pop(port.vif_id, None)
def _get_flow_args_by_version(self, ip_version, table,
vlan, subnet, priority, actions):
"""
Get flow args for DVR by IP version.
priority and actions are optional to support both add_flows
and delete_flows
"""
args = {'table': table,
'dl_vlan': vlan}
if ip_version == 4:
args['proto'] = 'ip'
args['nw_dst'] = subnet
else:
args['proto'] = 'ipv6'
args['ipv6_dst'] = subnet
if priority:
args['priority'] = priority
if actions:
args['actions'] = actions
return args
def unbind_port_from_dvr(self, vif_port, local_vlan_id):
if not self.in_distributed_mode():
return

View File

@ -219,6 +219,7 @@ class TestOvsNeutronAgent(base.BaseTestCase):
self.agent.dvr_agent.plugin_rpc, 'get_subnet_for_dvr',
return_value={'gateway_ip': '1.1.1.1',
'cidr': '1.1.1.0/24',
'ip_version': 4,
'gateway_mac': 'aa:bb:cc:11:22:33'}),
mock.patch.object(self.agent.dvr_agent.plugin_rpc,
'get_ports_on_host_by_subnet',
@ -241,8 +242,14 @@ class TestOvsNeutronAgent(base.BaseTestCase):
self.assertTrue(add_flow_tun_fn.called)
self.assertTrue(delete_flows_int_fn.called)
def _test_port_bound_for_dvr(self, device_owner):
def _test_port_bound_for_dvr(self, device_owner, ip_version=4):
self._setup_for_dvr_test()
if ip_version == 4:
gateway_ip = '1.1.1.1'
cidr = '1.1.1.0/24'
else:
gateway_ip = '2001:100::1'
cidr = '2001:100::0/64'
with mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
'set_db_attribute',
return_value=True):
@ -253,8 +260,9 @@ class TestOvsNeutronAgent(base.BaseTestCase):
mock.patch.object(self.agent.dvr_agent.plugin_rpc,
'get_subnet_for_dvr',
return_value={
'gateway_ip': '1.1.1.1',
'cidr': '1.1.1.0/24',
'gateway_ip': gateway_ip,
'cidr': cidr,
'ip_version': ip_version,
'gateway_mac': 'aa:bb:cc:11:22:33'}),
mock.patch.object(self.agent.dvr_agent.plugin_rpc,
'get_ports_on_host_by_subnet',
@ -274,24 +282,96 @@ class TestOvsNeutronAgent(base.BaseTestCase):
None, None, self._fixed_ips,
n_const.DEVICE_OWNER_DVR_INTERFACE,
False)
expected = [
mock.call(
table=constants.TUN_TABLE['vxlan'],
priority=1, tun_id=None,
actions="mod_vlan_vid:%s,"
"resubmit(,%s)" %
(self.agent.local_vlan_map[self._net_uuid].vlan,
constants.DVR_NOT_LEARN)),
mock.call(
table=constants.DVR_PROCESS, priority=2,
dl_vlan=(
self.agent.local_vlan_map[self._net_uuid].vlan),
dl_dst=self._port.vif_mac,
actions='drop'),
mock.call(
table=constants.DVR_PROCESS, priority=1,
dl_vlan=(
self.agent.local_vlan_map[self._net_uuid].vlan),
dl_src=self._port.vif_mac,
actions="mod_dl_src:%s,resubmit(,%s)" % (
self.agent.dvr_agent.dvr_mac_address,
constants.PATCH_LV_TO_TUN))]
if ip_version == 4:
expected.insert(1, mock.call(
proto='arp',
nw_dst=gateway_ip, actions='drop',
priority=3, table=constants.DVR_PROCESS,
dl_vlan=(
self.agent.local_vlan_map[self._net_uuid].vlan)))
else:
expected.insert(1, mock.call(
icmp_type=n_const.ICMPV6_TYPE_RA, proto='icmp6',
dl_src='aa:bb:cc:11:22:33', actions='drop',
priority=3, table=constants.DVR_PROCESS,
dl_vlan=(
self.agent.local_vlan_map[self._net_uuid].vlan)))
self.assertEqual(expected, add_flow_tun_fn.call_args_list)
self.agent.port_bound(self._compute_port, self._net_uuid,
'vxlan', None, None,
self._compute_fixed_ips,
device_owner, False)
self.assertTrue(add_flow_tun_fn.called)
self.assertTrue(add_flow_int_fn.called)
expected = [
mock.call(table=constants.DVR_TO_SRC_MAC, priority=4,
dl_dst=self._compute_port.vif_mac,
dl_vlan=self.agent.local_vlan_map[self._net_uuid].vlan,
actions="strip_vlan,mod_dl_src:%s,"
"output:%s" %
('aa:bb:cc:11:22:33', self._compute_port.ofport))
]
if ip_version == 4:
expected.append(mock.call(
table=constants.DVR_TO_SRC_MAC,
priority=2, proto='ip',
nw_dst=cidr,
dl_vlan=(
self.agent.local_vlan_map[self._net_uuid].vlan),
actions="strip_vlan,mod_dl_src:%s,"
"output:%s" %
('aa:bb:cc:11:22:33', self._compute_port.ofport)))
else:
expected.append(mock.call(
table=constants.DVR_TO_SRC_MAC,
priority=2, proto='ipv6',
ipv6_dst=cidr,
dl_vlan=(
self.agent.local_vlan_map[self._net_uuid].vlan),
actions="strip_vlan,mod_dl_src:%s,"
"output:%s" %
('aa:bb:cc:11:22:33', self._compute_port.ofport)))
self.assertEqual(expected, add_flow_int_fn.call_args_list)
self.assertTrue(delete_flows_int_fn.called)
def test_port_bound_for_dvr_with_compute_ports(self):
self._test_port_bound_for_dvr(device_owner="compute:None")
self._test_port_bound_for_dvr(
device_owner="compute:None")
self._test_port_bound_for_dvr(
device_owner="compute:None", ip_version=6)
def test_port_bound_for_dvr_with_lbaas_vip_ports(self):
self._test_port_bound_for_dvr(
device_owner=n_const.DEVICE_OWNER_LOADBALANCER)
self._test_port_bound_for_dvr(
device_owner=n_const.DEVICE_OWNER_LOADBALANCER, ip_version=6)
def test_port_bound_for_dvr_with_dhcp_ports(self):
self._test_port_bound_for_dvr(
device_owner=n_const.DEVICE_OWNER_DHCP)
self._test_port_bound_for_dvr(
device_owner=n_const.DEVICE_OWNER_DHCP, ip_version=6)
def test_port_bound_for_dvr_with_csnat_ports(self, ofport=10):
self._setup_for_dvr_test()
@ -306,6 +386,7 @@ class TestOvsNeutronAgent(base.BaseTestCase):
self.agent.dvr_agent.plugin_rpc, 'get_subnet_for_dvr',
return_value={'gateway_ip': '1.1.1.1',
'cidr': '1.1.1.0/24',
'ip_version': 4,
'gateway_mac': 'aa:bb:cc:11:22:33'}),
mock.patch.object(self.agent.dvr_agent.plugin_rpc,
'get_ports_on_host_by_subnet',
@ -329,7 +410,19 @@ class TestOvsNeutronAgent(base.BaseTestCase):
self.assertTrue(delete_flows_int_fn.called)
def test_treat_devices_removed_for_dvr_interface(self, ofport=10):
self._test_treat_devices_removed_for_dvr_interface(ofport)
self._test_treat_devices_removed_for_dvr_interface(
ofport, ip_version=6)
def _test_treat_devices_removed_for_dvr_interface(self, ofport=10,
ip_version=4):
self._setup_for_dvr_test()
if ip_version == 4:
gateway_ip = '1.1.1.1'
cidr = '1.1.1.0/24'
else:
gateway_ip = '2001:100::1'
cidr = '2001:100::0/64'
with mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
'set_db_attribute',
return_value=True):
@ -339,8 +432,9 @@ class TestOvsNeutronAgent(base.BaseTestCase):
return_value=str(self._old_local_vlan)),
mock.patch.object(
self.agent.dvr_agent.plugin_rpc, 'get_subnet_for_dvr',
return_value={'gateway_ip': '1.1.1.1',
'cidr': '1.1.1.0/24',
return_value={'gateway_ip': gateway_ip,
'cidr': cidr,
'ip_version': ip_version,
'gateway_mac': 'aa:bb:cc:11:22:33'}),
mock.patch.object(self.agent.dvr_agent.plugin_rpc,
'get_ports_on_host_by_subnet',
@ -374,11 +468,58 @@ class TestOvsNeutronAgent(base.BaseTestCase):
delete_flows_int_fn,
delete_flows_tun_fn):
self.agent.treat_devices_removed([self._port.vif_id])
self.assertTrue(delete_flows_int_fn.called)
self.assertTrue(delete_flows_tun_fn.called)
if ip_version == 4:
expected = [mock.call(
table=constants.DVR_TO_SRC_MAC,
nw_dst=cidr,
dl_vlan=(
self.agent.local_vlan_map[self._net_uuid].vlan),
proto='ip')]
else:
expected = [mock.call(
table=constants.DVR_TO_SRC_MAC,
ipv6_dst=cidr,
dl_vlan=(
self.agent.local_vlan_map[self._net_uuid].vlan),
proto='ipv6')]
self.assertEqual(expected,
delete_flows_int_fn.call_args_list)
if ip_version == 4:
expected = [mock.call(
proto='arp',
nw_dst=gateway_ip,
table=constants.DVR_PROCESS,
dl_vlan=(
self.agent.local_vlan_map[self._net_uuid].vlan))]
else:
expected = [mock.call(
icmp_type=n_const.ICMPV6_TYPE_RA, proto='icmp6',
dl_src='aa:bb:cc:11:22:33',
table=constants.DVR_PROCESS,
dl_vlan=(
self.agent.local_vlan_map[self._net_uuid].vlan))]
expected.extend([
mock.call(
table=constants.DVR_PROCESS,
dl_dst=self._port.vif_mac,
dl_vlan=(
self.agent.local_vlan_map[self._net_uuid].vlan)),
mock.call(
table=constants.DVR_PROCESS,
dl_vlan=(
self.agent.local_vlan_map[self._net_uuid].vlan),
dl_src=self._port.vif_mac)
])
self.assertEqual(expected, delete_flows_tun_fn.call_args_list)
def _test_treat_devices_removed_for_dvr(self, device_owner):
def _test_treat_devices_removed_for_dvr(self, device_owner, ip_version=4):
self._setup_for_dvr_test()
if ip_version == 4:
gateway_ip = '1.1.1.1'
cidr = '1.1.1.0/24'
else:
gateway_ip = '2001:100::1'
cidr = '2001:100::0/64'
with mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
'set_db_attribute',
return_value=True):
@ -388,8 +529,9 @@ class TestOvsNeutronAgent(base.BaseTestCase):
return_value=str(self._old_local_vlan)),
mock.patch.object(
self.agent.dvr_agent.plugin_rpc, 'get_subnet_for_dvr',
return_value={'gateway_ip': '1.1.1.1',
'cidr': '1.1.1.0/24',
return_value={'gateway_ip': gateway_ip,
'cidr': cidr,
'ip_version': ip_version,
'gateway_mac': 'aa:bb:cc:11:22:33'}),
mock.patch.object(self.agent.dvr_agent.plugin_rpc,
'get_ports_on_host_by_subnet',
@ -427,18 +569,45 @@ class TestOvsNeutronAgent(base.BaseTestCase):
update_dev_down_fn,
delete_flows_int_fn):
self.agent.treat_devices_removed([self._compute_port.vif_id])
self.assertTrue(delete_flows_int_fn.called)
expected = [
mock.call(
table=constants.DVR_TO_SRC_MAC,
dl_dst=self._compute_port.vif_mac,
dl_vlan=(
self.agent.local_vlan_map[self._net_uuid].vlan))]
if ip_version == 4:
expected.append(mock.call(
table=constants.DVR_TO_SRC_MAC,
proto='ip', nw_dst=cidr,
dl_vlan=(
self.agent.local_vlan_map[self._net_uuid].vlan))
)
else:
expected.append(mock.call(
table=constants.DVR_TO_SRC_MAC,
proto='ipv6', ipv6_dst=cidr,
dl_vlan=(
self.agent.local_vlan_map[self._net_uuid].vlan))
)
self.assertEqual(expected, delete_flows_int_fn.call_args_list)
def test_treat_devices_removed_for_dvr_with_compute_ports(self):
self._test_treat_devices_removed_for_dvr(device_owner="compute:None")
self._test_treat_devices_removed_for_dvr(
device_owner="compute:None")
self._test_treat_devices_removed_for_dvr(
device_owner="compute:None", ip_version=6)
def test_treat_devices_removed_for_dvr_with_lbaas_vip_ports(self):
self._test_treat_devices_removed_for_dvr(
device_owner=n_const.DEVICE_OWNER_LOADBALANCER)
self._test_treat_devices_removed_for_dvr(
device_owner=n_const.DEVICE_OWNER_LOADBALANCER, ip_version=6)
def test_treat_devices_removed_for_dvr_with_dhcp_ports(self):
self._test_treat_devices_removed_for_dvr(
device_owner=n_const.DEVICE_OWNER_DHCP)
self._test_treat_devices_removed_for_dvr(
device_owner=n_const.DEVICE_OWNER_DHCP, ip_version=6)
def test_treat_devices_removed_for_dvr_csnat_port(self, ofport=10):
self._setup_for_dvr_test()
@ -453,6 +622,7 @@ class TestOvsNeutronAgent(base.BaseTestCase):
self.agent.dvr_agent.plugin_rpc, 'get_subnet_for_dvr',
return_value={'gateway_ip': '1.1.1.1',
'cidr': '1.1.1.0/24',
'ip_version': 4,
'gateway_mac': 'aa:bb:cc:11:22:33'}),
mock.patch.object(self.agent.dvr_agent.plugin_rpc,
'get_ports_on_host_by_subnet',