Dual-stack L3-Policy mapping

The initial spec for address scope and subnetpool support mentioned
support for dual-stack. This commit extends the existing spec to
define that support.

Change-Id: I0966d200c75c1d571a15687062020528e97648da
Partially-implements: blueprint address-scope-mapping
This commit is contained in:
Thomas Bachman 2017-04-20 16:03:03 +00:00
parent 449643f905
commit c200c8997f
1 changed files with 131 additions and 42 deletions

View File

@ -30,50 +30,94 @@ Proposed change
The current mapping of GBP l3_policy to a list of Neutron routers will be
augmented with the mapping to a Neutron address_scope (one each for IPv4 and
IPv6) and subnetpools. This spec attempts to lay the foundation for the use
of IPv6, and dual-stack (both IPv4 and IPv6) in the l3_policy. The API and DB
model constructs to support this are being addressed in this spec. The details
for IPv6 implementation are not addresed in this spec and will be laid out in
a forthcoming complementary spec.
of IPv6 and dual-stack (both IPv4 and IPv6) in the l3_policy. The API and DB
model constructs to support this are addressed in this spec.
For each address family (IPv4 and/or IPv6) the l3_policy supports, there will
be a 1-1 mapping between GBP l3_policy and the Neutron address_scope,
and 1-many mapping between GBP l3_policy and Neutron subnetpools. The 1-many
The ip_version attribute of GBP's l3_policy is extended to allow specifying
dual-stack support. Currently allowed values for ip_version are 4 for IPv4
and 6 for IPv6. The value 46 may now be used to enable dual-stack support.
For each address family (IPv4 and/or IPv6) enabled by an l3_policy, there
will be a 1-1 mapping between GBP l3_policy and a Neutron address_scope,
and a 1-many mapping between GBP l3_policy and Neutron subnetpools. The 1-many
mapping allows for use cases where the l3_policy (and address_scope) is shared
across tenants, while the subnetpool is created per tenant and not shared.
The subnetpools that are explicitly associated with the l3_policy, need to
belong to the same address_scope that is associated with that l3_policy. GBP
Within each enabled address family, the subnetpools that are explicitly
associated with the l3_policy must all belong to the same address_scope. GBP
will allocate subnets only from the subnetpools that are associated with the
corresponding l3_policy. The list of subnets associated with the l3_policy can
be updated by adding or removing subnetpools (subnetpools which are currently
being used cannot be removed).
being used cannot be removed), or by updating the prefixes attribute of
subnetpools already associated with the l3_policy
The implicit subnetpools extension is used to control the desired behavior
when an implicit workflow is used with L3 policies [#]_. Implicit subnetpools
are only used when the ip_version requests a given address family (IPv4 or
IPv6) and the user hasn't explicitly provided any CIDRs for that address
family (e.g. via the ip_pool parameter, or a subnetpool and/or address scope).
The current implicit subnetpool semantics do not account for different address
families. Therefore, the semantics must be amended as follows to account for a
subnetpool per address family:
- Only one implicit subnetpool *per address family* can exist *per tenant*
(if not shared)
- Only one shared implicit subnetpool *per address family* can exist in the
whole system. This doesn't affect private implicit subnetpools
The subnet_prefix_length is now allowed to be None. The point of adding
the None value is for use with explicit subnetpools, where the default prefix
length should be determined by each pool, rather than by this parameter. It
also is limited to use with v4 subnetpools, as the only v6 default prefix
supported by the L3 Policy is /64.
Two properties of address scopes are address namespace and routability.
Address namespace simply means that addresses are guaranteed to be unique
within an address scope. Routability means that a neutron router may only
forward between interfaces that have subnets which were allocated from
subnetpools with the same address scope (note: forwarding is still possible
via NAT when they aren't in the same scope). It's worth pointing out that
since address scopes can span multiple l3_policies, the address uniqueness is
applied across the l3_policies. However, even though sharing a common address
scope implies routability across l3_policies, actual connectivity between
l3_policies is not implied because each l3_policy maps to a distinct router.
In GBP, connectivity between l3_policies remains subject to a PTG providing
a PRS that is consumed by an external_policy.
Let's consider the various combinations that are possible based on the choice
of implicit and explicit arguments.
#. A l3_policy is created with an ip_pool, ip_version, and
subnet_prefix_length but no address_scope or subnetpool(s) are provided. In
this case an address_scope with the address family of the ip_version will be
created implicitly, and a subnetpool with the ip_pool CIDR will be created
in that address_scope. If the l3_policy is shared, the implcitily create
address_scope and subnetpool will also be shared. The ip_version of the
l3_policy will be used for the address_scope and the subnetpool. The
default_prefixlen, will be set to the subnet_prefix_length of the l3_policy.
(The min_prefixlen, and max_prefixlen of the subnetpool will default to 8
and 32 as defined in Neutron.)
subnet_prefix_length (IPv4 only), but no address_scope or subnetpool(s)
are provided for that address family. There are two possibilities in this
scenario:
#. A l3_policy is created with an ip_pool, ip_version, subnet_prefix_length,
and address_scope, but no subnetpools are provided. In this case the
ip_version of the l3_policy is ignored, and the subnetpool is created in
this address_scope as before. If both, v4 and v6, address_scopes are
provided, a subnetpool will be created for each family. If a subnetpool
already exists in this address_scope, and overlaps with the CIDR of the
ip_pool, an exception will be raised.
* An implicit subnetpool exists for an address family enabled by
ip_version. In this case the implicit subnetpool and its address
scope are associated with the l3_policy and any supplied ip_pool
is ignored.
* An implicit subnetpool does not exist for an address family enabled
by ip_version. In this case an address_scope with the address family
enabled by the ip_version will be created, and a subnetpool with the
CIDRs of that address family found in the ip_pool value will be
created in that address_scope. If no CIDRs for the address family
are found in ip_pool, an exception is raised. If the l3_policy is
shared, the implicitly created address_scope and subnetpool will
also be shared. For IPv4, the default_prefixlen of the subnetpool
will be set to the subnet_prefix_length of the l3_policy, the
min_prefixlen will be set to 8, and the max_prefixlen will be be
set to 32. For IPv6, the default_prefixlen, min_prefixlen, and
max_prefixlen of the subnetpool will all be set to 64.
#. An l3_policy is created with an address_scope of the enabled address
family, but no subnetpools of that address family are provided. In this
case the subnetpool is created in this address_scope as before. If a
subnetpool already exists in this address_scope, and overlaps with the
CIDR of the ip_pool, an exception will be raised.
#. A l3_policy is created with an address_scope, and subnetpool(s). Since the
ip_version is already defined for the address_scope and the CIDR and prefix
lengths are defined for the subnetpool(s), the ip_version, ip_pool and
subnet_prefix_length of the l3_policy will be ignored if provided.
supplied subnetpool(s) define how subnets will be allocated, any supplied
ip_pool for that address family is ignored.
#. A l3_policy is created with one or more subnetpools. The address_scope
associated with the subnetpool(s) is associated with the l3_policy. If
@ -87,9 +131,9 @@ In all of the above cases, if subnetpools are associated with an address_scope
that is associated with a l3_policy, they will be considered for subnet
allocation only if they are explicitly associated with the l3_policy.
A minor variation of all the above cases is the one where either or all of
ip_pool, ip_version, and subnet_prefix_length are not provided. In such cases
the GBP defaults for these attributes will be used (but overridden by the
A minor variation of all the above cases is the one where either or both of
the ip_pool and subnet_prefix_length are not provided. In such cases the GBP
defaults for these attributes will be used (but overridden by the
corresponding attributes in the address_scope and subnetpools if any of those
are explicitly provided).
@ -106,15 +150,7 @@ It should be noted that the ip_pool, subnet_prefix_length, and ip_version
attributes of the l3_policy may only have effect at the l3_policy creation
time. In the body of response for GET l3_policy call, the ip_pool will be set
to a comma separated string consisting of a list of CIDRs corresponding to each
subnetpool currently present in the address_scope. To preserve API backward
compatibility (i.e. to not immediately break existing clients and integration
tests), the subnet_prefix_length and ip_version will be set to the
corresponding subnet_prefix_length and ip_version when only one CIDR is
present. If more than one CIDR is present, these will be set to null. In the
case where multiple CIDRs are present, more details like the prefix length of
the subnets that are drawn from the subnetpools corresponding to these CIDRs
can be obtained by navigating the resource relationship from l3_policy to
address_scope to subnetpool.
subnetpool currently present in the address_scope.
Data model impact
@ -204,6 +240,56 @@ extension definition
'is_visible': True, 'default': None},
},
In addition, the l3_policy itself needs modifications to support:
* the new value 46 for ip_version:
* a type change for ip_pool (subnet to string)
* change to the conversion for subnet_prefix_length to allow None
::
L3_POLICIES: {
'id': {'allow_post': False, 'allow_put': False,
'validate': {'type:uuid': None}, 'is_visible': True,
'primary_key': True},
'name': {'allow_post': True, 'allow_put': True,
'validate': {'type:gbp_resource_name': None},
'default': '', 'is_visible': True},
'description': {'allow_post': True, 'allow_put': True,
'validate': {'type:string': None},
'is_visible': True, 'default': ''},
'tenant_id': {'allow_post': True, 'allow_put': False,
'validate': {'type:string': None},
'required_by_policy': True, 'is_visible': True},
'status': {'allow_post': False, 'allow_put': False,
'is_visible': True},
'status_details': {'allow_post': False, 'allow_put': False,
'is_visible': True},
'ip_version': {'allow_post': True, 'allow_put': False,
'convert_to': conv.convert_to_int,
'validate': {'type:values': [4, 6, 46]},
'default': 4, 'is_visible': True},
'ip_pool': {'allow_post': True, 'allow_put': False,
'validate': {'type:string': None},
'default': '10.0.0.0/8', 'is_visible': True},
'subnet_prefix_length': {'allow_post': True, 'allow_put': True,
'convert_to': conv.convert_to_int_if_not_none,
# for ipv4 legal values are 2 to 30
# for ipv6 legal values are 2 to 127
'default': 24, 'is_visible': True},
'l2_policies': {'allow_post': False, 'allow_put': False,
'validate': {'type:uuid_list': None},
'convert_to': conv.convert_none_to_empty_list,
'default': None, 'is_visible': True},
attr.SHARED: {'allow_post': True, 'allow_put': True,
'default': False, 'convert_to': conv.convert_to_boolean,
'is_visible': True, 'required_by_policy': True,
'enforce_policy': True},
'external_segments': {
'allow_post': True, 'allow_put': True, 'default': None,
'validate': {'type:external_dict': None},
'convert_to': conv.convert_none_to_empty_dict, 'is_visible': True},
},
Security impact
---------------
@ -271,7 +357,9 @@ snaiksat + GBP team
Work items
----------
API, DB, and driver layer updates to GBP Resources.
API, DB, and driver layer updates to GBP Resources. Also work on the CLI and
python client to handle either a list or single element for the ip_pool
parameter.
Dependencies
============
@ -320,3 +408,4 @@ References
==========
.. [#] http://docs.openstack.org/developer/neutron/devref/address_scopes.html
.. [#] https://review.openstack.org/#/c/419315/