Browse Source

Merge "Introduce a SR-IOV binding driver"

Zuul 1 year ago
parent
commit
4188f679d8

+ 7
- 4
kuryr/lib/binding/__init__.py View File

@@ -14,7 +14,7 @@ from oslo_utils import importutils
14 14
 
15 15
 
16 16
 def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
17
-              segmentation_id=None):
17
+              segmentation_id=None, **kwargs):
18 18
     """Binds the Neutron port to the network interface on the host.
19 19
 
20 20
     :param endpoint_id:   the ID of the endpoint as string
@@ -29,6 +29,7 @@ def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
29 29
                          port of a container which is running inside this Nova
30 30
                          instance (either ipvlan/macvlan or a subport).
31 31
     :param segmentation_id: ID of the segment for container traffic isolation)
32
+    :param kwargs:       Additional driver-specific arguments
32 33
     :returns: the tuple of the names of the veth pair and the tuple of stdout
33 34
               and stderr returned by processutils.execute invoked with the
34 35
               executable script for binding
@@ -38,18 +39,20 @@ def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
38 39
     driver = importutils.import_module(cfg.CONF.binding.driver)
39 40
     return driver.port_bind(endpoint_id, port, subnets, network=network,
40 41
                             vm_port=vm_port,
41
-                            segmentation_id=segmentation_id)
42
+                            segmentation_id=segmentation_id,
43
+                            **kwargs)
42 44
 
43 45
 
44
-def port_unbind(endpoint_id, neutron_port):
46
+def port_unbind(endpoint_id, neutron_port, **kwargs):
45 47
     """Unbinds the Neutron port from the network interface on the host.
46 48
 
47 49
     :param endpoint_id: the ID of the Docker container as string
48 50
     :param neutron_port: a port dictionary returned from python-neutronclient
51
+    :param kwargs:       Additional driver-specific arguments
49 52
     :returns: the tuple of stdout and stderr returned by processutils.execute
50 53
               invoked with the executable script for unbinding
51 54
     :raises: processutils.ProcessExecutionError, pyroute2.NetlinkError
52 55
     """
53 56
     driver = importutils.import_module(cfg.CONF.binding.driver)
54 57
 
55
-    return driver.port_unbind(endpoint_id, neutron_port)
58
+    return driver.port_unbind(endpoint_id, neutron_port, **kwargs)

+ 74
- 0
kuryr/lib/binding/drivers/hw_veb.py View File

@@ -0,0 +1,74 @@
1
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
2
+# not use this file except in compliance with the License. You may obtain
3
+# a copy of the License at
4
+#
5
+#      http://www.apache.org/licenses/LICENSE-2.0
6
+#
7
+# Unless required by applicable law or agreed to in writing, software
8
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10
+# License for the specific language governing permissions and limitations
11
+# under the License.
12
+
13
+from oslo_concurrency import processutils
14
+
15
+from kuryr.lib.binding.drivers import utils
16
+from kuryr.lib import constants
17
+
18
+
19
+def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
20
+              segmentation_id=None, **kwargs):
21
+    """Binds the Neutron port to the network interface on the host.
22
+
23
+    :param endpoint_id:   the ID of the endpoint as string
24
+    :param port:         the container Neutron port dictionary as returned by
25
+                         python-neutronclient
26
+    :param subnets:      an iterable of all the Neutron subnets which the
27
+                         endpoint is trying to join
28
+    :param network:      the Neutron network which the endpoint is trying to
29
+                         join
30
+    :param vm_port:      the Nova instance port dictionary, as returned by
31
+                         python-neutronclient. Container port under binding is
32
+                         running inside this instance (either ipvlan/macvlan or
33
+                         a subport)
34
+    :param segmentation_id: ID of the segment for container traffic isolation)
35
+    :param kwargs:       Additional driver-specific arguments
36
+    :returns: the tuple of the names of the veth pair and the tuple of stdout
37
+              and stderr returned by processutils.execute invoked with the
38
+              executable script for binding
39
+    :raises: kuryr.common.exceptions.VethCreationFailure,
40
+             processutils.ProcessExecutionError
41
+    """
42
+    pf_ifname = kwargs['pf_ifname']
43
+    vf_num = kwargs['vf_num']
44
+    mac_addr = port[utils.MAC_ADDRESS_KEY]
45
+    vlan = port[constants.VIF_DETAILS_KEY][constants.VIF_DETAILS_VLAN_KEY]
46
+    _set_vf_interface_vlan(pf_ifname, vf_num, mac_addr, vlan)
47
+    return None, None, ('', None)
48
+
49
+
50
+def port_unbind(endpoint_id, neutron_port, **kwargs):
51
+    """Unbinds the Neutron port from the network interface on the host.
52
+
53
+    :param endpoint_id: the ID of the Docker container as string
54
+    :param neutron_port: a port dictionary returned from python-neutronclient
55
+    :param kwargs:       Additional driver-specific arguments
56
+    :returns: the tuple of stdout and stderr returned by processutils.execute
57
+              invoked with the executable script for unbinding
58
+    :raises: processutils.ProcessExecutionError, pyroute2.NetlinkError
59
+    """
60
+    pf_ifname = kwargs['pf_ifname']
61
+    vf_num = kwargs['vf_num']
62
+    mac_addr = neutron_port[utils.MAC_ADDRESS_KEY]
63
+    _set_vf_interface_vlan(pf_ifname, vf_num, mac_addr)
64
+    return '', None
65
+
66
+
67
+def _set_vf_interface_vlan(pf_ifname, vf_num, mac_addr, vlan=0):
68
+    exit_code = [0, 2, 254]
69
+    processutils.execute('ip', 'link', 'set', pf_ifname,
70
+                         'vf', vf_num,
71
+                         'mac', mac_addr,
72
+                         'vlan', vlan,
73
+                         run_as_root=True,
74
+                         check_exit_code=exit_code)

+ 2
- 1
kuryr/lib/binding/drivers/ipvlan.py View File

@@ -21,7 +21,7 @@ IPVLAN_MODE_L2 = ifinfmsg.ifinfo.data_map['ipvlan'].modes['IPVLAN_MODE_L2']
21 21
 
22 22
 
23 23
 def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
24
-              segmentation_id=None):
24
+              segmentation_id=None, **kwargs):
25 25
     """Binds the Neutron port to the network interface on the host.
26 26
 
27 27
     :param endpoint_id:   the ID of the endpoint as string
@@ -35,6 +35,7 @@ def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
35 35
                          python-neutronclient. Container is running inside
36 36
                          this instance (either ipvlan/macvlan or a subport)
37 37
     :param segmentation_id: ID of the segment for container traffic isolation)
38
+    :param kwargs:       Additional driver-specific arguments
38 39
     :returns: the tuple of the names of the veth pair and the tuple of stdout
39 40
               and stderr returned by processutils.execute invoked with the
40 41
               executable script for binding

+ 2
- 1
kuryr/lib/binding/drivers/macvlan.py View File

@@ -20,7 +20,7 @@ MACVLAN_MODE_BRIDGE = 'bridge'
20 20
 
21 21
 
22 22
 def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
23
-              segmentation_id=None):
23
+              segmentation_id=None, **kwargs):
24 24
     """Binds the Neutron port to the network interface on the host.
25 25
 
26 26
     :param endpoint_id:   the ID of the endpoint as string
@@ -34,6 +34,7 @@ def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
34 34
                          python-neutronclient. Container is running inside
35 35
                          instance.
36 36
     :param segmentation_id: ID of the segment for container traffic isolation)
37
+    :param kwargs:       Additional driver-specific arguments
37 38
     :returns: the tuple of the names of the veth pair and the tuple of stdout
38 39
               and stderr returned by processutils.execute invoked with the
39 40
               executable script for binding

+ 2
- 1
kuryr/lib/binding/drivers/nested.py View File

@@ -31,11 +31,12 @@ def get_link_iface(port):
31 31
     return link
32 32
 
33 33
 
34
-def port_unbind(endpoint_id, neutron_port):
34
+def port_unbind(endpoint_id, neutron_port, **kwargs):
35 35
     """Unbinds the Neutron port from the network interface on the host.
36 36
 
37 37
     :param endpoint_id: the ID of the Docker container as string
38 38
     :param neutron_port: a port dictionary returned from python-neutronclient
39
+    :param kwargs:       Additional driver-specific arguments
39 40
     :returns: the tuple of stdout and stderr returned by processutils.execute
40 41
               invoked with the executable script for unbinding
41 42
     :raises: processutils.ProcessExecutionError, pyroute2.NetlinkError

+ 5
- 3
kuryr/lib/binding/drivers/veth.py View File

@@ -27,7 +27,7 @@ KIND = 'veth'
27 27
 
28 28
 
29 29
 def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
30
-              segmentation_id=None):
30
+              segmentation_id=None, **kwargs):
31 31
     """Binds the Neutron port to the network interface on the host.
32 32
 
33 33
     :param endpoint_id:   the ID of the endpoint as string
@@ -37,11 +37,12 @@ def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
37 37
                          endpoint is trying to join
38 38
     :param network:      the Neutron network which the endpoint is trying to
39 39
                          join
40
-    :param vm_port:      the Nova instance dictionary, as returned by
40
+    :param vm_port:      the Nova instance port dictionary, as returned by
41 41
                          python-neutronclient. Container port under binding is
42 42
                          running inside this instance (either ipvlan/macvlan or
43 43
                          a subport)
44 44
     :param segmentation_id: ID of the segment for container traffic isolation)
45
+    :param kwargs:       Additional driver-specific arguments
45 46
     :returns: the tuple of the names of the veth pair and the tuple of stdout
46 47
               and stderr returned by processutils.execute invoked with the
47 48
               executable script for binding
@@ -84,11 +85,12 @@ def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
84 85
     return host_ifname, container_ifname, (stdout, stderr)
85 86
 
86 87
 
87
-def port_unbind(endpoint_id, neutron_port):
88
+def port_unbind(endpoint_id, neutron_port, **kwargs):
88 89
     """Unbinds the Neutron port from the network interface on the host.
89 90
 
90 91
     :param endpoint_id: the ID of the Docker container as string
91 92
     :param neutron_port: a port dictionary returned from python-neutronclient
93
+    :param kwargs:       Additional driver-specific arguments
92 94
     :returns: the tuple of stdout and stderr returned by processutils.execute
93 95
               invoked with the executable script for unbinding
94 96
     :raises: processutils.ProcessExecutionError, pyroute2.NetlinkError

+ 2
- 1
kuryr/lib/binding/drivers/vlan.py View File

@@ -18,7 +18,7 @@ KIND = 'vlan'
18 18
 
19 19
 
20 20
 def port_bind(endpoint_id, port, subnets, network=None,
21
-              vm_port=None, segmentation_id=None):
21
+              vm_port=None, segmentation_id=None, **kwargs):
22 22
     """Binds the Neutron port to the network interface on the host.
23 23
 
24 24
     :param endpoint_id:   the ID of the endpoint as string
@@ -32,6 +32,7 @@ def port_bind(endpoint_id, port, subnets, network=None,
32 32
                          python-neutronclient. Container is running inside this
33 33
                          instance (either ipvlan/macvlan or a subport)
34 34
     :param segmentation_id: ID of the segment for container traffic isolation)
35
+    :param kwargs:       Additional driver-specific arguments
35 36
     :returns: the tuple of the names of the veth pair and the tuple of stdout
36 37
               and stderr returned by processutils.execute invoked with the
37 38
               executable script for binding

+ 1
- 0
kuryr/lib/constants.py View File

@@ -28,4 +28,5 @@ DEFAULT_NETWORK_MTU = 1500
28 28
 FALLBACK_VIF_TYPE = 'unbound'
29 29
 UNBINDING_SUBCOMMAND = 'unbind'
30 30
 VIF_DETAILS_KEY = 'binding:vif_details'
31
+VIF_DETAILS_VLAN_KEY = 'vlan'
31 32
 VIF_TYPE_KEY = 'binding:vif_type'

+ 94
- 0
kuryr/tests/unit/binding/drivers/test_hw_veb.py View File

@@ -0,0 +1,94 @@
1
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
2
+# not use this file except in compliance with the License. You may obtain
3
+# a copy of the License at
4
+#
5
+#      http://www.apache.org/licenses/LICENSE-2.0
6
+#
7
+# Unless required by applicable law or agreed to in writing, software
8
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10
+# License for the specific language governing permissions and limitations
11
+# under the License.
12
+
13
+
14
+import mock
15
+from oslo_utils import uuidutils
16
+
17
+from kuryr.lib.binding.drivers import hw_veb
18
+from kuryr.lib import constants
19
+from kuryr.lib import utils
20
+from kuryr.tests.unit import base
21
+
22
+
23
+mock_create = mock.MagicMock()
24
+mock_interface = mock.MagicMock()
25
+
26
+
27
+class TestHwVebDriver(base.TestCase):
28
+    """Unit tests for hw_veb driver"""
29
+
30
+    @mock.patch('oslo_concurrency.processutils.execute',
31
+                return_value=('fake_stdout', 'fake_stderr'))
32
+    def test_port_bind(self, mock_execute):
33
+        fake_docker_endpoint_id = utils.get_hash()
34
+        fake_docker_network_id = utils.get_hash()
35
+        fake_port_id = uuidutils.generate_uuid()
36
+        fake_neutron_v4_subnet_id = uuidutils.generate_uuid()
37
+        fake_neutron_v6_subnet_id = uuidutils.generate_uuid()
38
+        fake_vlan_id = 100
39
+        fake_vif_details = {constants.VIF_DETAILS_VLAN_KEY: fake_vlan_id}
40
+        fake_vif_type = "ovs"
41
+        fake_port = self._get_fake_port(
42
+            fake_docker_endpoint_id, fake_docker_network_id,
43
+            fake_port_id, constants.PORT_STATUS_ACTIVE,
44
+            fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id,
45
+            vif_details=fake_vif_details, vif_type=fake_vif_type)
46
+        fake_subnets = self._get_fake_subnets(
47
+            fake_docker_endpoint_id, fake_docker_network_id,
48
+            fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id)
49
+        fake_network = self._get_fake_networks(fake_docker_network_id)
50
+        fake_pf_ifname = 'eth13'
51
+        fake_vf_num = 1
52
+
53
+        hw_veb.port_bind(fake_docker_endpoint_id,
54
+                         fake_port['port'],
55
+                         fake_subnets['subnets'],
56
+                         fake_network['networks'][0],
57
+                         pf_ifname=fake_pf_ifname,
58
+                         vf_num=fake_vf_num)
59
+
60
+        mock_execute.assert_called_once_with(
61
+            'ip', 'link', 'set', fake_pf_ifname,
62
+            'vf', fake_vf_num,
63
+            'mac', fake_port['port']['mac_address'],
64
+            'vlan', fake_vlan_id,
65
+            run_as_root=True,
66
+            check_exit_code=[0, 2, 254])
67
+
68
+    @mock.patch('oslo_concurrency.processutils.execute',
69
+                return_value=('fake_stdout', 'fake_stderr'))
70
+    def test_port_unbind(self, mock_execute):
71
+        fake_docker_endpoint_id = utils.get_hash()
72
+        fake_docker_network_id = utils.get_hash()
73
+        fake_port_id = uuidutils.generate_uuid()
74
+        fake_neutron_v4_subnet_id = uuidutils.generate_uuid()
75
+        fake_neutron_v6_subnet_id = uuidutils.generate_uuid()
76
+        fake_vif_type = "ovs"
77
+        fake_port = self._get_fake_port(
78
+            fake_docker_endpoint_id, fake_docker_network_id,
79
+            fake_port_id, constants.PORT_STATUS_ACTIVE,
80
+            fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id,
81
+            vif_type=fake_vif_type)
82
+        fake_pf_ifname = 'eth13'
83
+        fake_vf_num = 1
84
+        hw_veb.port_unbind(fake_docker_endpoint_id, fake_port['port'],
85
+                           pf_ifname=fake_pf_ifname,
86
+                           vf_num=fake_vf_num)
87
+        mock_execute.assert_called_once()
88
+        mock_execute.assert_called_once_with(
89
+            'ip', 'link', 'set', fake_pf_ifname,
90
+            'vf', fake_vf_num,
91
+            'mac', fake_port['port']['mac_address'],
92
+            'vlan', 0,
93
+            run_as_root=True,
94
+            check_exit_code=[0, 2, 254])

+ 5
- 0
releasenotes/notes/bp-sriov-binding-7cebeae1c9f27ea4.yaml View File

@@ -0,0 +1,5 @@
1
+---
2
+features:
3
+  - |
4
+    Introduce hw_veb binding driver. This driver can perform binding
5
+    of SR-IOV neutron port.

Loading…
Cancel
Save