Add support for CIDRs in allowed-adddress-pairs

The current support for allowed-address-pairs only covers
host addresses. This patch adds support for using CIDRs in
allowed address pairs. Since CIDRs are already supported in
upstream neutron, this patch only affects the backend
implementation, which is the get_gbp_details RPC and the
port notifications.

The patch also addresses cleanup of the IP => Port ID
mapping table. Entries in the table weren't affected
if an existing port's allowed-address-pairs property
was changed. This patch checks to see if the changes
address any addresses in the table, and if needed,
removes them.

Change-Id: I7bcfee46b0239577c500f2fa970e4c8400c968d0
This commit is contained in:
Thomas Bachman
2019-01-24 02:07:08 +00:00
parent 96cf38da52
commit a786706373
5 changed files with 179 additions and 26 deletions

View File

@@ -11,6 +11,7 @@
# under the License.
import hashlib
import netaddr
import re
import six
import sqlalchemy as sa
@@ -1942,11 +1943,27 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
else:
owned_addresses = self._get_owned_addresses(
plugin_context, port['id'])
extra_aaps = []
for allowed in aaps:
if allowed['ip_address'] in owned_addresses:
cidr = netaddr.IPNetwork(allowed['ip_address'])
if ((cidr.version == 4 and cidr.prefixlen != 32) or
(cidr.version == 6 and cidr.prefixlen != 128)):
# Never mark CIDRs as "active", but
# look for owned addresses in this CIDR, and
# if present, add them to the allowed-address-pairs
# list, and mark those as "active"
for addr in owned_addresses:
entry = {'ip_address': addr,
'mac_address': allowed['mac_address'],
'active': True}
if addr in cidr and entry not in extra_aaps:
extra_aaps.append(entry)
elif allowed['ip_address'] in owned_addresses:
# Signal the agent that this particular address is active
# on its port
allowed['active'] = True
if extra_aaps:
aaps.extend(extra_aaps)
return aaps
def _get_port_vrf(self, plugin_context, port, details):
@@ -2080,7 +2097,8 @@ class AIMMappingDriver(nrd.CommonNeutronBase, aim_rpc.AIMMappingRPCMixin):
plugin_context,
filters={'network_id': [port['network_id']],
'fixed_ips': {'ip_address': active_addrs}})
fips_filter.extend([p['id'] for p in others])
fips_filter.extend([p['id'] for p in others
if p['id'] != port['id']])
fips = self._get_fips(plugin_context,
filters={'port_id': fips_filter})

View File

@@ -627,9 +627,7 @@ class AIMMappingRPCMixin(ha_ip_db.HAIPOwnerDbMixin):
# network whose address is owned by this port.
# If those ports have FIPs, then steal them.
fips_filter = [str(port_id)]
active_addrs = [str(a['ip_address'])
for a in details['allowed_address_pairs']
if a.get('active')]
active_addrs = details['_cache']['owned_addresses']
if active_addrs:
in_str = self._compose_in_filter_str(active_addrs)
ports_query = (

View File

@@ -81,9 +81,9 @@ class PortForHAIPAddress(object):
ipaddress=ipaddress, network_id=network_id).first()
return port_ha_ip
def get_ha_ipaddresses_for_port(self, port_id):
def get_ha_ipaddresses_for_port(self, port_id, session=None):
"""Returns the HA IP Addressses associated with a Port."""
session = db_api.get_reader_session()
session = session or db_api.get_reader_session()
query = BAKERY(lambda s: s.query(
HAIPAddressToPortAssocation))