Commit 9f0f187a91 for frr

commit 9f0f187a91c85c17c2399c72cc818b2835cc60dd
Author: Donald Sharp <sharpd@nvidia.com>
Date:   Thu Oct 1 17:40:19 2026 -0400

    tests: Add a create_address_on_interface to handle X OS systems

    Add a create_address_on_interface that works on freebsd or linux.

    Signed-off-by: Donald Sharp <sharpd@nvidia.com>

diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py
index 387da60acf..a93fa9f530 100644
--- a/tests/topotests/lib/common_config.py
+++ b/tests/topotests/lib/common_config.py
@@ -1578,6 +1578,31 @@ def create_interface_in_kernel(
         create_interface_in_kernel_linux(tgen, dut, name, ip_addr, vrf, netmask, create)


+def create_address_on_interface(tgen, dut, name, ip_addr, vrf=None, netmask=None):
+    """
+    Add an IP address to an existing kernel interface.
+
+    The interface must already exist. Addresses already configured on it are
+    left in place. Link state is not changed.
+
+    Parameters
+    ----------
+    * `tgen` : Topogen object
+    * `dut` : Device whose interface receives the address
+    * `name` : interface name
+    * `ip_addr` : ip address to add. Include the prefix length unless
+                  ``netmask`` is set.
+    * `vrf` : VRF name, to which interface will be associated.
+              Applied on Linux only.
+    * `netmask` : netmask value, default is None
+    """
+
+    if sys.platform.startswith("freebsd"):
+        create_address_on_interface_freebsd(tgen, dut, name, ip_addr, vrf, netmask)
+    else:
+        create_address_on_interface_linux(tgen, dut, name, ip_addr, vrf, netmask)
+
+
 def _kernel_interface_address(ip_addr, netmask):
     """Return an ipaddress interface for ip_addr and an optional netmask."""
     if not netmask:
@@ -1620,6 +1645,23 @@ def create_interface_in_kernel_linux(
         rnode.run(cmd)


+def create_address_on_interface_linux(
+    tgen, dut, name, ip_addr, vrf=None, netmask=None
+):
+    """Add an IP address to an existing Linux interface."""
+
+    rnode = tgen.gears[dut]
+    ifaddr = _kernel_interface_address(ip_addr, netmask)
+    cmd = "ip -{0} a add {1} dev {2}".format(ifaddr.version, ifaddr, name)
+    logger.debug("[DUT: %s]: Running command: %s", dut, cmd)
+    rnode.run(cmd)
+
+    if vrf:
+        cmd = "ip link set {} master {}".format(name, vrf)
+        logger.debug("[DUT: %s]: Running command: %s", dut, cmd)
+        rnode.run(cmd)
+
+
 def _freebsd_run(rnode, dut, args):
     """Run an ifconfig argv inside the router and log it."""
     logger.debug("[DUT: %s]: Running command: %s", dut, " ".join(args))
@@ -1698,6 +1740,22 @@ def create_interface_in_kernel_freebsd(
         logger.debug("[DUT: %s]: %s stays in the base FIB (vrf %s)", dut, name, vrf)


+def create_address_on_interface_freebsd(
+    tgen, dut, name, ip_addr, vrf=None, netmask=None
+):
+    """Add an IP address to an existing FreeBSD interface."""
+
+    rnode = tgen.gears[dut]
+    ifaddr = _kernel_interface_address(ip_addr, netmask)
+    family = "inet6" if ifaddr.version == 6 else "inet"
+    if ifaddr.version == 6:
+        _freebsd_run(rnode, dut, ["/sbin/ifconfig", name, "inet6", "-ifdisabled"])
+    _freebsd_run(rnode, dut, ["/sbin/ifconfig", name, family, str(ifaddr), "alias"])
+
+    if vrf:
+        logger.debug("[DUT: %s]: %s stays in the base FIB (vrf %s)", dut, name, vrf)
+
+
 def shutdown_bringup_interface_in_kernel(tgen, dut, intf_name, ifaceaction=False):
     """
     Cretae interfaces in kernel for ipv4/ipv6