Merge "net_utils: Add a random mac generator"

This commit is contained in:
Zuul 2018-07-18 22:15:42 +00:00 committed by Gerrit Code Review
commit 168fdca181
3 changed files with 70 additions and 0 deletions

View File

@ -11,6 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import itertools
import random
import socket
@ -46,6 +47,37 @@ class TestGetRandomMac(base.BaseTestCase):
mock_rnd.assert_called_with(8)
class TestRandomMacGenerator(base.BaseTestCase):
def test_all_macs_generated(self):
mac = ['aa', 'bb', 'cc', 'dd', 'ee', 'ff']
generator = itertools.islice(net.random_mac_generator(mac), 70000)
self.assertEqual(2**16, len(list(generator)))
@mock.patch.object(random, 'getrandbits', return_value=0xa2)
def test_first_generated_mac(self, mock_rnd):
mac = ['aa', 'bb', 'cc', '00', 'ee', 'ff']
generator = itertools.islice(net.random_mac_generator(mac), 1)
self.assertEqual(['aa:bb:cc:a2:a2:a2'], list(generator))
mock_rnd.assert_called_with(8)
@mock.patch.object(random, 'getrandbits', return_value=0xa2)
def test_respected_early_zeroes_generated_mac(self, mock_rnd):
mac1 = ['00', 'bb', 'cc', '00', 'ee', 'ff']
generator = itertools.islice(net.random_mac_generator(mac1), 1)
self.assertEqual(['00:bb:cc:a2:a2:a2'], list(generator))
mac2 = ['aa', '00', 'cc', '00', 'ee', 'ff']
generator = itertools.islice(net.random_mac_generator(mac2), 1)
self.assertEqual(['aa:00:cc:a2:a2:a2'], list(generator))
mac3 = ['aa', 'bb', '00', '00', 'ee', 'ff']
generator = itertools.islice(net.random_mac_generator(mac3), 1)
self.assertEqual(['aa:bb:00:a2:a2:a2'], list(generator))
mock_rnd.assert_called_with(8)
class TestPortDeviceOwner(base.BaseTestCase):
def test_is_port_trusted(self):

View File

@ -43,6 +43,36 @@ def get_random_mac(base_mac):
return ':'.join(["%02x" % x for x in mac])
def random_mac_generator(base_mac):
"""Generates random mac addresses from a specified base format.
The first 3 octets of each MAC address will remain unchanged. If the 4th
octet is not 00, it will also be used. The others will be randomly
generated.
:param base_mac: Base mac address represented by an array of 6 strings.
:returns: A mac address string generator.
"""
fixed = list(base_mac[0:3])
to_generate = 3
if base_mac[3] != '00':
fixed += base_mac[3]
to_generate = 2
beginning = ':'.join(fixed) + ':'
form = '{}' + ':'.join('{:02x}' for _ in range(to_generate))
max_macs = 2 ** (to_generate * 8)
seen = set()
while len(seen) < max_macs:
numbers = [random.getrandbits(8) for _ in range(to_generate)]
mac = form.format(beginning, *numbers)
if mac in seen:
continue
else:
seen.add(mac)
yield mac
def is_port_trusted(port):
"""Used to determine if port can be trusted not to attack network.

View File

@ -0,0 +1,8 @@
---
features:
- |
Introduced ``neutron_lib.utils.net.random_mac_generator(basemac)``. It allows
you to get a mac address string Python generator from the same kind of
basemac that ``neutron_lib.utils.net.get_random_mac(basemac)`` expects. If
there are a lot of macs to get, this will speed the process up
significantly over generating single macs and testing for collisions.