bridge/bond: User permanent MAC address for Interface.COPY_MAC_FROM
Use permanent MAC address when possible for `Interface.COPY_MAC_FROM`. Integration test case added by require real NIC to test using. Example: sudo env TEST_REAL_NIC="enp7s0" pytest -k \ test_create_linux_bridge_with_copy_mac_from_permanent_mac Tested on e100e in RHEL 8.4 VM. Signed-off-by: Gris Ge <fge@redhat.com>
This commit is contained in:
parent
1ea97bfddc
commit
e87349169d
@ -130,6 +130,7 @@ class BaseIface:
|
||||
ROUTE_RULES_METADATA = "_route_rules"
|
||||
RULE_CHANGED_METADATA = "_changed"
|
||||
ROUTE_CHANGED_METADATA = "_changed"
|
||||
PERMANENT_MAC_ADDRESS_METADATA = "_permanent_mac_address"
|
||||
|
||||
def __init__(self, info, save_to_disk=True):
|
||||
self._origin_info = deepcopy(info)
|
||||
@ -215,6 +216,10 @@ class BaseIface:
|
||||
def original_dict(self):
|
||||
return self._origin_info
|
||||
|
||||
@property
|
||||
def permanent_mac_address(self):
|
||||
return self._info.get(BaseIface.PERMANENT_MAC_ADDRESS_METADATA)
|
||||
|
||||
def ip_state(self, family):
|
||||
return IPState(family, self._info.get(family, {}))
|
||||
|
||||
|
@ -194,8 +194,10 @@ class Ifaces:
|
||||
f"{Interface.COPY_MAC_FROM} property "
|
||||
f"as the port {iface.copy_mac_from} does not exists yet"
|
||||
)
|
||||
|
||||
iface.apply_copy_mac_from(port_iface.mac)
|
||||
if port_iface.permanent_mac_address:
|
||||
iface.apply_copy_mac_from(port_iface.permanent_mac_address)
|
||||
else:
|
||||
iface.apply_copy_mac_from(port_iface.mac)
|
||||
|
||||
def _create_virtual_port(self):
|
||||
"""
|
||||
|
@ -20,6 +20,7 @@
|
||||
import logging
|
||||
from operator import attrgetter
|
||||
|
||||
from libnmstate.ifaces import BaseIface
|
||||
from libnmstate.schema import Interface
|
||||
from libnmstate.schema import InterfaceIP
|
||||
from libnmstate.schema import InterfaceIPv6
|
||||
@ -91,6 +92,10 @@ class NisporPluginBaseIface:
|
||||
Interface.MAC: self.mac,
|
||||
Interface.ACCEPT_ALL_MAC_ADDRESSES: self.accept_all_mac_addresses,
|
||||
}
|
||||
if self._np_iface.permanent_mac_address:
|
||||
iface_info[
|
||||
BaseIface.PERMANENT_MAC_ADDRESS_METADATA
|
||||
] = self._np_iface.permanent_mac_address
|
||||
if self.mtu:
|
||||
iface_info[Interface.MTU] = self.mtu
|
||||
ip_info = self._ip_info(config_only)
|
||||
|
@ -103,7 +103,7 @@ def _logging_setup():
|
||||
|
||||
|
||||
def _ethx_init():
|
||||
""" Remove any existing definitions on the ethX interfaces. """
|
||||
"""Remove any existing definitions on the ethX interfaces."""
|
||||
ifacelib.ifaces_init("eth1", "eth2")
|
||||
|
||||
|
||||
|
@ -18,10 +18,12 @@
|
||||
#
|
||||
from contextlib import contextmanager
|
||||
from copy import deepcopy
|
||||
|
||||
import os
|
||||
import time
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
import json
|
||||
|
||||
import libnmstate
|
||||
from libnmstate.error import NmstateKernelIntegerRoundedError
|
||||
@ -56,6 +58,8 @@ from .testlib.vlan import vlan_interface
|
||||
TEST_BRIDGE0 = "linux-br0"
|
||||
TEST_TAP0 = "tap0"
|
||||
ETH1 = "eth1"
|
||||
# RFC 7042 reserved EUI-48 MAC range for document
|
||||
TEST_MAC_ADDRESS = "00:00:5E:00:53:01"
|
||||
|
||||
BRIDGE_OPTIONS_YAML = """
|
||||
options:
|
||||
@ -813,6 +817,60 @@ def test_create_linux_bridge_with_copy_mac_from(eth1_up, eth2_up):
|
||||
assert_mac_address(current_state, eth2_mac)
|
||||
|
||||
|
||||
def _get_permanent_mac(iface_name):
|
||||
np_iface = json.loads(exec_cmd(f"npc {iface_name} --json".split())[1])
|
||||
return np_iface[0].get("permanent_mac_address")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def real_nic_with_mac_differ_from_permanent():
|
||||
test_nic = os.environ.get("TEST_REAL_NIC")
|
||||
permanent_mac = _get_permanent_mac(test_nic)
|
||||
assert permanent_mac
|
||||
libnmstate.apply(
|
||||
{
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: test_nic,
|
||||
Interface.MAC: TEST_MAC_ADDRESS,
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
yield permanent_mac
|
||||
libnmstate.apply(
|
||||
{
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: test_nic,
|
||||
Interface.STATE: InterfaceState.ABSENT,
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not os.environ.get("TEST_REAL_NIC"),
|
||||
reason="Need to define TEST_REAL_NIC for SR-IOV test",
|
||||
)
|
||||
def test_create_linux_bridge_with_copy_mac_from_permanent_mac(
|
||||
real_nic_with_mac_differ_from_permanent,
|
||||
):
|
||||
permanent_mac = real_nic_with_mac_differ_from_permanent
|
||||
test_nic = os.environ.get("TEST_REAL_NIC")
|
||||
|
||||
# Create bridge use this nic
|
||||
bridge_state = _create_bridge_subtree_config([test_nic])
|
||||
with linux_bridge(
|
||||
TEST_BRIDGE0,
|
||||
bridge_state,
|
||||
extra_iface_state={Interface.COPY_MAC_FROM: test_nic},
|
||||
):
|
||||
current_state = show_only((TEST_BRIDGE0,))
|
||||
assert_mac_address(current_state, permanent_mac)
|
||||
|
||||
|
||||
@pytest.mark.tier1
|
||||
@pytest.mark.skipif(
|
||||
nm_major_minor_version() < 1.31,
|
||||
|
@ -31,6 +31,7 @@ from libnmstate.schema import InterfaceState
|
||||
from libnmstate.schema import InterfaceType
|
||||
|
||||
from libnmstate.ifaces.ifaces import Ifaces
|
||||
from libnmstate.ifaces.ifaces import BaseIface
|
||||
from libnmstate.ifaces.ifaces import OvsBridgeIface
|
||||
from libnmstate.state import state_match
|
||||
|
||||
@ -39,6 +40,7 @@ from .testlib.bridgelib import PORT1_IFACE_NAME
|
||||
from .testlib.bridgelib import PORT2_IFACE_NAME
|
||||
from .testlib.bridgelib import gen_bridge_iface_info
|
||||
from .testlib.constants import MAC_ADDRESS1
|
||||
from .testlib.constants import MAC_ADDRESS2
|
||||
from .testlib.ifacelib import gen_foo_iface_info_static_ip
|
||||
from .testlib.ifacelib import gen_foo_iface_info
|
||||
from .testlib.ovslib import OVS_BRIDGE_IFACE_NAME
|
||||
@ -454,6 +456,49 @@ class TestIfaces:
|
||||
ifaces = Ifaces(des_iface_infos, cur_iface_infos)
|
||||
ifaces.verify(cur_iface_infos)
|
||||
|
||||
def test_copy_mac_from_permanent_mac_address(self):
|
||||
cur_iface_infos = [gen_foo_iface_info(), gen_foo_iface_info()]
|
||||
cur_iface_infos[0][Interface.NAME] = PORT1_IFACE_NAME
|
||||
cur_iface_infos[1][Interface.NAME] = PORT2_IFACE_NAME
|
||||
cur_iface_infos[1][Interface.MAC] = MAC_ADDRESS1
|
||||
cur_iface_infos[1][
|
||||
BaseIface.PERMANENT_MAC_ADDRESS_METADATA
|
||||
] = MAC_ADDRESS2
|
||||
cur_iface_infos.append(gen_bridge_iface_info())
|
||||
des_iface_infos = [gen_foo_iface_info(), gen_foo_iface_info()]
|
||||
des_iface_infos[0][Interface.NAME] = PORT1_IFACE_NAME
|
||||
des_iface_infos[1][Interface.NAME] = PORT2_IFACE_NAME
|
||||
des_bridge_info = gen_bridge_iface_info()
|
||||
des_bridge_info[Interface.NAME] = LINUX_BRIDGE_IFACE_NAME
|
||||
des_bridge_info[Interface.COPY_MAC_FROM] = PORT2_IFACE_NAME
|
||||
des_iface_infos.append(des_bridge_info)
|
||||
|
||||
ifaces = Ifaces(des_iface_infos, cur_iface_infos)
|
||||
assert (
|
||||
ifaces.all_kernel_ifaces[LINUX_BRIDGE_IFACE_NAME].mac
|
||||
== MAC_ADDRESS2
|
||||
)
|
||||
|
||||
def test_copy_mac_from(self):
|
||||
cur_iface_infos = [gen_foo_iface_info(), gen_foo_iface_info()]
|
||||
cur_iface_infos[0][Interface.NAME] = PORT1_IFACE_NAME
|
||||
cur_iface_infos[1][Interface.NAME] = PORT2_IFACE_NAME
|
||||
cur_iface_infos[1][Interface.MAC] = MAC_ADDRESS1
|
||||
cur_iface_infos.append(gen_bridge_iface_info())
|
||||
des_iface_infos = [gen_foo_iface_info(), gen_foo_iface_info()]
|
||||
des_iface_infos[0][Interface.NAME] = PORT1_IFACE_NAME
|
||||
des_iface_infos[1][Interface.NAME] = PORT2_IFACE_NAME
|
||||
des_bridge_info = gen_bridge_iface_info()
|
||||
des_bridge_info[Interface.NAME] = LINUX_BRIDGE_IFACE_NAME
|
||||
des_bridge_info[Interface.COPY_MAC_FROM] = PORT2_IFACE_NAME
|
||||
des_iface_infos.append(des_bridge_info)
|
||||
|
||||
ifaces = Ifaces(des_iface_infos, cur_iface_infos)
|
||||
assert (
|
||||
ifaces.all_kernel_ifaces[LINUX_BRIDGE_IFACE_NAME].mac
|
||||
== MAC_ADDRESS1
|
||||
)
|
||||
|
||||
|
||||
class TestIfacesSriov:
|
||||
def test_vf_been_auto_include_as_desired(self):
|
||||
|
@ -21,6 +21,7 @@ from libnmstate.schema import InterfaceIP
|
||||
|
||||
FOO_IFACE_NAME = "foo"
|
||||
MAC_ADDRESS1 = "01:23:45:67:89:AB"
|
||||
MAC_ADDRESS2 = "01:23:45:67:89:AC"
|
||||
|
||||
IPV6_ADDRESS1 = "2001:db8:1::1"
|
||||
IPV6_ADDRESS1_FULL = "2001:db8:1:0:0:0:0:1"
|
||||
|
Loading…
x
Reference in New Issue
Block a user