diff --git a/api-ref/source/v2/networks.inc b/api-ref/source/v2/networks.inc index b4a3f349c..917d49060 100644 --- a/api-ref/source/v2/networks.inc +++ b/api-ref/source/v2/networks.inc @@ -141,6 +141,15 @@ Most Networking plug-ins (e.g. ML2 Plugin) and drivers do not support updating any provider related attributes. Check your plug-in whether it supports updating. +QinQ +==== + +The ``qinq`` extension adds the ``qinq`` boolean attribute which allows to +control the VLAN QinQ (vlan in vlan) of the network. It uses ``0x8a88`` ethertype for +the double tagged packets. If the service does not support VLAN QinQ and a user +requests a VLAN QinQ network, the plug-in refuses to create one and returns an +appropriate error to the user. + QoS extension ============= diff --git a/api-ref/source/v2/parameters.yaml b/api-ref/source/v2/parameters.yaml index a7ff5df74..c795e2d1a 100644 --- a/api-ref/source/v2/parameters.yaml +++ b/api-ref/source/v2/parameters.yaml @@ -1290,6 +1290,13 @@ provider:segmentation_id-query: in: query required: false type: integer +qinq-query: + description: | + Filter the network list by the VLAN QinQ mode of the network, + which is VLAN QinQ enabled (``true``) or disabled (``false``). + in: query + required: false + type: boolean qos-rule-direction-query: description: | Filter the list result by the direction of the traffic to which the QoS @@ -5681,6 +5688,20 @@ psk: in: body required: true type: string +qinq: + description: | + Indicates the VLAN QinQ mode of the network, which is + VLAN QinQ enabled (``true``) or disabled (``false``). + in: body + required: true + type: boolean +qinq-request: + description: | + Indicates the VLAN QinQ mode of the network, which is + VLAN QinQ enabled (``true``) or disabled (``false``). + in: body + required: false + type: boolean qos-backend-drivers: description: | List of loaded QoS drivers with supported diff --git a/api-ref/source/v2/samples/agents/agent-dhcp-networks-list-response.json b/api-ref/source/v2/samples/agents/agent-dhcp-networks-list-response.json index e12a2c03a..c22fb48bd 100644 --- a/api-ref/source/v2/samples/agents/agent-dhcp-networks-list-response.json +++ b/api-ref/source/v2/samples/agents/agent-dhcp-networks-list-response.json @@ -27,6 +27,7 @@ "tenant_id": "4fd44f30292945e481c7b8a0c8908869", "updated_at": "2016-03-08T20:19:41", "vlan_transparent": true, + "qinq": false, "description": "", "is_default": false }, @@ -57,6 +58,7 @@ "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e", "updated_at": "2016-03-08T20:19:41", "vlan_transparent": false, + "qinq": false, "description": "", "is_default": false } diff --git a/api-ref/source/v2/samples/networks/network-create-response.json b/api-ref/source/v2/samples/networks/network-create-response.json index 898d6e7c0..e2d85b03d 100644 --- a/api-ref/source/v2/samples/networks/network-create-response.json +++ b/api-ref/source/v2/samples/networks/network-create-response.json @@ -25,6 +25,7 @@ "tenant_id": "9bacb3c5d39d41a79512987f338cf177", "updated_at": "2016-03-08T20:19:41", "vlan_transparent": false, + "qinq": false, "description": "", "is_default": false } diff --git a/api-ref/source/v2/samples/networks/network-multi-show-response.json b/api-ref/source/v2/samples/networks/network-multi-show-response.json index 820c66641..16a4e21e3 100644 --- a/api-ref/source/v2/samples/networks/network-multi-show-response.json +++ b/api-ref/source/v2/samples/networks/network-multi-show-response.json @@ -39,6 +39,7 @@ "tenant_id": "4fd44f30292945e481c7b8a0c8908869", "updated_at": "2016-03-08T20:19:41", "vlan_transparent": false, + "qinq": false, "description": "", "is_default": false } diff --git a/api-ref/source/v2/samples/networks/network-provider-show-response.json b/api-ref/source/v2/samples/networks/network-provider-show-response.json index 71c28ad86..68cbc61e5 100644 --- a/api-ref/source/v2/samples/networks/network-provider-show-response.json +++ b/api-ref/source/v2/samples/networks/network-provider-show-response.json @@ -30,6 +30,7 @@ "tenant_id": "4fd44f30292945e481c7b8a0c8908869", "updated_at": "2016-03-08T20:19:41", "vlan_transparent": false, + "qinq": false, "description": "", "is_default": true } diff --git a/api-ref/source/v2/samples/networks/network-show-response.json b/api-ref/source/v2/samples/networks/network-show-response.json index 08070725f..43c61fe5a 100644 --- a/api-ref/source/v2/samples/networks/network-show-response.json +++ b/api-ref/source/v2/samples/networks/network-show-response.json @@ -27,6 +27,7 @@ "tenant_id": "4fd44f30292945e481c7b8a0c8908869", "updated_at": "2016-03-08T20:19:41", "vlan_transparent": false, + "qinq": false, "description": "", "is_default": true } diff --git a/api-ref/source/v2/samples/networks/network-update-response.json b/api-ref/source/v2/samples/networks/network-update-response.json index 754f9ef38..00e2343db 100644 --- a/api-ref/source/v2/samples/networks/network-update-response.json +++ b/api-ref/source/v2/samples/networks/network-update-response.json @@ -27,6 +27,7 @@ "tenant_id": "4fd44f30292945e481c7b8a0c8908869", "updated_at": "2016-03-08T20:19:41", "vlan_transparent": false, + "qinq": false, "description": "", "is_default": false } diff --git a/api-ref/source/v2/samples/networks/networks-bulk-create-response.json b/api-ref/source/v2/samples/networks/networks-bulk-create-response.json index 5092db88c..fc0dd11dc 100644 --- a/api-ref/source/v2/samples/networks/networks-bulk-create-response.json +++ b/api-ref/source/v2/samples/networks/networks-bulk-create-response.json @@ -25,6 +25,7 @@ "tenant_id": "4fd44f30292945e481c7b8a0c8908869", "updated_at": "2016-03-08T20:19:41", "vlan_transparent": false, + "qinq": false, "description": "", "port_security_enabled": true, "is_default": false @@ -54,6 +55,7 @@ "tenant_id": "4fd44f30292945e481c7b8a0c8908869", "updated_at": "2016-03-08T20:19:41", "vlan_transparent": false, + "qinq": false, "description": "", "port_security_enabled": true, "is_default": false diff --git a/api-ref/source/v2/samples/networks/networks-list-response.json b/api-ref/source/v2/samples/networks/networks-list-response.json index e12a2c03a..3fee4f6a4 100644 --- a/api-ref/source/v2/samples/networks/networks-list-response.json +++ b/api-ref/source/v2/samples/networks/networks-list-response.json @@ -27,6 +27,7 @@ "tenant_id": "4fd44f30292945e481c7b8a0c8908869", "updated_at": "2016-03-08T20:19:41", "vlan_transparent": true, + "qinq": true, "description": "", "is_default": false }, @@ -57,6 +58,7 @@ "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e", "updated_at": "2016-03-08T20:19:41", "vlan_transparent": false, + "qinq": false, "description": "", "is_default": false } diff --git a/api-ref/source/v2/samples/networks/networks-provider-list-response.json b/api-ref/source/v2/samples/networks/networks-provider-list-response.json index da7975105..f3a494f8c 100644 --- a/api-ref/source/v2/samples/networks/networks-provider-list-response.json +++ b/api-ref/source/v2/samples/networks/networks-provider-list-response.json @@ -31,6 +31,7 @@ "tenant_id": "4fd44f30292945e481c7b8a0c8908869", "updated_at": "2016-03-08T20:19:41", "vlan_transparent": true, + "qinq": false, "description": "", "is_default": false }, @@ -78,6 +79,7 @@ "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e", "updated_at": "2016-03-08T20:19:41", "vlan_transparent": false, + "qinq": false, "description": "", "is_default": false } diff --git a/neutron_lib/api/definitions/__init__.py b/neutron_lib/api/definitions/__init__.py index 55488fe90..9bc622981 100644 --- a/neutron_lib/api/definitions/__init__.py +++ b/neutron_lib/api/definitions/__init__.py @@ -106,6 +106,7 @@ from neutron_lib.api.definitions import portbindings_extended from neutron_lib.api.definitions import project_default_networks from neutron_lib.api.definitions import project_id from neutron_lib.api.definitions import provider_net +from neutron_lib.api.definitions import qinq from neutron_lib.api.definitions import qos from neutron_lib.api.definitions import qos_bw_limit_direction from neutron_lib.api.definitions import qos_bw_minimum_ingress @@ -268,6 +269,7 @@ _ALL_API_DEFINITIONS = { project_default_networks, project_id, provider_net, + qinq, qos, qos_bw_limit_direction, qos_bw_minimum_ingress, diff --git a/neutron_lib/api/definitions/qinq.py b/neutron_lib/api/definitions/qinq.py new file mode 100644 index 000000000..790309861 --- /dev/null +++ b/neutron_lib/api/definitions/qinq.py @@ -0,0 +1,48 @@ +# Copyright (c) 2024 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +from neutron_lib.api import converters +from neutron_lib.api.definitions import network +from neutron_lib import constants + +ALIAS = 'qinq' +IS_SHIM_EXTENSION = False +IS_STANDARD_ATTR_EXTENSION = False +NAME = "QinQ networks" +DESCRIPTION = ( + "Expose network 'qinq' attribute in the API. " + "This allows to configure network to allow vlan in vlan " + "configuration using 0x8a88 ethertype (QinQ)." +) +UPDATED_TIMESTAMP = "2024-12-02T10:00:00-00:00" +RESOURCE_NAME = network.RESOURCE_NAME +COLLECTION_NAME = network.COLLECTION_NAME +QINQ_FIELD = 'qinq' +RESOURCE_ATTRIBUTE_MAP = { + COLLECTION_NAME: { + QINQ_FIELD: { + 'allow_post': True, + 'allow_put': False, + 'convert_to': converters.convert_to_boolean, + 'default': constants.ATTR_NOT_SPECIFIED, + 'is_visible': True, + 'is_filter': True, + 'validate': {'type:boolean': None} + } + }, +} +SUB_RESOURCE_ATTRIBUTE_MAP = None +ACTION_MAP = {} +ACTION_STATUS = {} +REQUIRED_EXTENSIONS = [] +OPTIONAL_EXTENSIONS = [] diff --git a/neutron_lib/tests/unit/api/definitions/test_qinq.py b/neutron_lib/tests/unit/api/definitions/test_qinq.py new file mode 100644 index 000000000..9b71e6c22 --- /dev/null +++ b/neutron_lib/tests/unit/api/definitions/test_qinq.py @@ -0,0 +1,22 @@ +# Copyright 2024 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from neutron_lib.api.definitions import qinq +from neutron_lib.tests.unit.api.definitions import base + + +class QinQDefinitionTestCase(base.DefinitionBaseTestCase): + extension_module = qinq + extension_resources = (qinq.COLLECTION_NAME,) + extension_attributes = (qinq.QINQ_FIELD,) diff --git a/releasenotes/notes/QinQ-API-extension-a7b95d0a7a35411c.yaml b/releasenotes/notes/QinQ-API-extension-a7b95d0a7a35411c.yaml new file mode 100644 index 000000000..d92c89730 --- /dev/null +++ b/releasenotes/notes/QinQ-API-extension-a7b95d0a7a35411c.yaml @@ -0,0 +1,9 @@ +--- +features: + - | + The ``qinq`` extension adds a ``qinq`` attribute to the network + resource. This new attribute can be used in a similar way to + ``vlan_transparent`` but networks created with ``qinq`` set will use + ``0x8a88`` ethertype for the double vlan tagged traffic. + Attributes ``qinq`` and ``vlan_transparent`` can't be used together + for the same network.