Add a few MAC checks
Notably mac.is_multicast() which is needed for TAPs / LCPs and interfaces. Add a test for interface MAC addresses being non-multicast.
This commit is contained in:
@ -17,6 +17,8 @@ sudo pip3 install argparse
|
||||
sudo pip3 install yamale
|
||||
sudo pip3 install pyyaml
|
||||
sudo pip3 install pyinstaller
|
||||
sudo pip3 install netaddr
|
||||
sudo pip3 install ipaddress
|
||||
|
||||
## Ensure all unittests pass.
|
||||
./tests.py -d -t unittest/yaml/*.yaml
|
||||
|
@ -18,6 +18,7 @@ import config.loopback as loopback
|
||||
import config.vxlan_tunnel as vxlan_tunnel
|
||||
import config.lcp as lcp
|
||||
import config.address as address
|
||||
import config.mac as mac
|
||||
|
||||
def get_qinx_parent_by_name(yaml, ifname):
|
||||
""" Returns the sub-interface which matches a QinAD or QinQ outer tag, or None,None
|
||||
@ -424,6 +425,10 @@ def validate_interfaces(yaml):
|
||||
if not 'state' in iface:
|
||||
iface['state'] = 'up'
|
||||
|
||||
if 'mac' in iface and mac.is_multicast(iface['mac']):
|
||||
msgs.append("interface %s MAC address %s cannot be multicast" % (ifname, iface['mac']))
|
||||
result = False
|
||||
|
||||
iface_mtu = get_mtu(yaml, ifname)
|
||||
iface_lcp = get_lcp(yaml, ifname)
|
||||
iface_address = has_address(yaml, ifname)
|
||||
|
48
config/mac.py
Normal file
48
config/mac.py
Normal file
@ -0,0 +1,48 @@
|
||||
#
|
||||
# Copyright (c) 2022 Pim van Pelt
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
import logging
|
||||
import netaddr
|
||||
|
||||
def is_valid(mac):
|
||||
""" Return True if the string given in `mac` is a valid (6-byte) MAC address,
|
||||
as defined by netaddr.EUI """
|
||||
try:
|
||||
addr = netaddr.EUI(mac)
|
||||
except:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_local(mac):
|
||||
""" Return True if a MAC address is a valid locally administered one. """
|
||||
try:
|
||||
addr = netaddr.EUI(mac)
|
||||
except:
|
||||
return False
|
||||
return bool(addr.words[0] & 0b10)
|
||||
|
||||
def is_multicast(mac):
|
||||
""" Return True if a MAC address is a valid multicast one. """
|
||||
try:
|
||||
addr = netaddr.EUI(mac)
|
||||
except:
|
||||
return False
|
||||
return bool(addr.words[0] & 0b01)
|
||||
|
||||
def is_unicast(mac):
|
||||
""" Return True if a MAC address is a valid unicast one. """
|
||||
try:
|
||||
addr = netaddr.EUI(mac)
|
||||
except:
|
||||
return False
|
||||
return not bool(addr.words[0] & 0b01)
|
21
config/test_mac.py
Normal file
21
config/test_mac.py
Normal file
@ -0,0 +1,21 @@
|
||||
import unittest
|
||||
import config.mac as mac
|
||||
|
||||
class TestMACMethods(unittest.TestCase):
|
||||
def test_is_valid(self):
|
||||
self.assertTrue(mac.is_valid("00:01:02:03:04:05"))
|
||||
self.assertTrue(mac.is_valid("00-01-02-03-04-05"))
|
||||
self.assertTrue(mac.is_valid("0001.0203.0405"))
|
||||
self.assertFalse(mac.is_valid("hoi"))
|
||||
|
||||
def test_is_local(self):
|
||||
self.assertTrue(mac.is_local("02:00:00:00:00:00"))
|
||||
self.assertFalse(mac.is_local("00:00:00:00:00:00"))
|
||||
|
||||
def test_is_multicast(self):
|
||||
self.assertTrue(mac.is_multicast("01:00:00:00:00:00"))
|
||||
self.assertFalse(mac.is_multicast("00:00:00:00:00:00"))
|
||||
|
||||
def test_is_unicast(self):
|
||||
self.assertFalse(mac.is_unicast("01:00:00:00:00:00"))
|
||||
self.assertTrue(mac.is_unicast("00:00:00:00:00:00"))
|
17
unittest/yaml/error-interface1.yaml
Normal file
17
unittest/yaml/error-interface1.yaml
Normal file
@ -0,0 +1,17 @@
|
||||
test:
|
||||
description: "Interface mac addresses cannot be multicast"
|
||||
errors:
|
||||
expected:
|
||||
- "interface .* MAC address .* cannot be multicast"
|
||||
count: 1
|
||||
---
|
||||
interfaces:
|
||||
GigabitEthernet3/0/0:
|
||||
description: "Cool, local MACs are fine"
|
||||
mac: 02:00:00:00:00:00
|
||||
GigabitEthernet3/0/1:
|
||||
description: "Cool, global unicast MACs are fine"
|
||||
mac: 04:00:00:00:00:00
|
||||
GigabitEthernet3/0/2:
|
||||
description: "Not cool, multicast MACs"
|
||||
mac: 01:00:00:00:00:00
|
Reference in New Issue
Block a user