From bfba92f590cb38789f8bffbfec340b286bf5ae16 Mon Sep 17 00:00:00 2001 From: Christian Hopps Date: Fri, 16 Jan 2026 22:40:34 +0000 Subject: [PATCH] munet: add `loopbacks-autonumber` config remove by default - The previous release included a NBC change that was auton-umbering loopback interfaces if the user configured `networks-autonumber: true`. Change this using a new `loopbacks-autonumber` config instead. Signed-off-by: Christian Hopps --- README.org | 10 ++++++++++ doc/source/config.rst | 9 ++++++--- munet/munet-schema.json | 3 +++ munet/native.py | 26 ++++++++++++++++++++------ pyproject.toml | 2 +- tests/basic/munet.yaml | 1 + tests/basic/test_basic_topology.py | 8 +++----- uv.lock | 2 +- 8 files changed, 45 insertions(+), 16 deletions(-) diff --git a/README.org b/README.org index 48eccf5..5d21f54 100644 --- a/README.org +++ b/README.org @@ -126,6 +126,7 @@ module: labn-munet-config | +--rw dns-network? -> ../networks/name | +--rw ipv6-enable? boolean | +--rw networks-autonumber? boolean + | +--rw loopbacks-autonumber? boolean | +--rw initial-setup-cmd? string | +--rw initial-setup-host-cmd? string | +--rw networks* [name] @@ -1084,11 +1085,20 @@ munet> leaf networks-autonumber { type boolean; + default false; description "Controls if networks and node connections are given IP addresses if not explicitly configured."; } + leaf loopbacks-autonumber { + type boolean; + default false; + description + "Controls if loopbacks are given IP addresses if not explicitly + configured."; + } + leaf initial-setup-cmd { type string; description diff --git a/doc/source/config.rst b/doc/source/config.rst index 5a52482..ab8edbe 100644 --- a/doc/source/config.rst +++ b/doc/source/config.rst @@ -84,9 +84,12 @@ along with a few global topology options. Tree diagram for topology config:: +--rw topology - | +--rw dns-network? -> ../networks/name - | +--rw ipv6-enable? boolean - | +--rw networks-autonumber? boolean + | +--rw dns-network? -> ../networks/name + | +--rw ipv6-enable? boolean + | +--rw networks-autonumber? boolean + | +--rw loopbacks-autonumber? boolean + | +--rw initial-setup-cmd? string + | +--rw initial-setup-host-cmd? string | +--rw networks* [name] | ... described in subsection | +--rw nodes* [name] diff --git a/munet/munet-schema.json b/munet/munet-schema.json index 5147c5e..b61ce5c 100644 --- a/munet/munet-schema.json +++ b/munet/munet-schema.json @@ -400,6 +400,9 @@ "networks-autonumber": { "type": "boolean" }, + "loopbacks-autonumber": { + "type": "boolean" + }, "initial-setup-cmd": { "type": "string" }, diff --git a/munet/native.py b/munet/native.py index 3d71d14..2eeabb3 100644 --- a/munet/native.py +++ b/munet/native.py @@ -55,6 +55,10 @@ from .watchlog import WatchLog +AUTO_LOOPBACK_IPV4_BASE = ipaddress.ip_interface("10.255.0.0/32") +AUTO_LOOPBACK_IPV6_BASE = ipaddress.ip_interface("fcfe::0/128") + + class L3ContainerNotRunningError(MunetError): """Exception if no running container exists.""" @@ -63,16 +67,14 @@ def get_loopback_ips(c, nid): ips = [] if ip := c.get("ip"): if ip == "auto": - assert nid < 0xFFFF # Limited to 10.255.0.0/16 block - ips.append(ipaddress.ip_interface("10.255.0.0/32") + nid) + ips.append(AUTO_LOOPBACK_IPV4_BASE + nid) elif isinstance(ip, str): ips.append(ipaddress.ip_interface(ip)) else: ips.extend([ipaddress.ip_interface(x) for x in ip]) if ipv6 := c.get("ipv6"): if ipv6 == "auto": - assert nid < 0xFFFF # Same limit as ipv4 for simplicity - ips.append(ipaddress.ip_interface(f"fcfe:ffff:{nid:02x}::1/128")) + ips.append(AUTO_LOOPBACK_IPV6_BASE + nid) elif isinstance(ip, str): ips.append(ipaddress.ip_interface(ipv6)) else: @@ -797,9 +799,13 @@ def __init__(self, *args, unet=None, **kwargs): ) self.next_p2p_network6 = ipaddress.ip_network(f"fcff:ffff:{self.id:02x}::/127") - if "ip" not in self.config and self.unet.autonumber: + if "ip" not in self.config and self.unet.autonumber_loopbacks: self.config["ip"] = "auto" - if "ipv6" not in self.config and self.unet.autonumber and self.unet.ipv6_enable: + if ( + "ipv6" not in self.config + and self.unet.autonumber_loopbacks + and self.unet.ipv6_enable + ): self.config["ipv6"] = "auto" self.loopback_ip = None self.loopback_ips = get_loopback_ips(self.config, self.id) @@ -3304,6 +3310,14 @@ def autonumber(self): def autonumber(self, value): self.topoconf["networks-autonumber"] = bool(value) + @property + def autonumber_loopbacks(self): + return self.topoconf.get("loopbacks-autonumber", False) + + @autonumber_loopbacks.setter + def autonumber_loopbacks(self, value): + self.topoconf["loopbacks-autonumber"] = bool(value) + async def add_dummy_link(self, node1, c1=None): c1 = {} if c1 is None else c1 diff --git a/pyproject.toml b/pyproject.toml index a689e87..6817fc8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "munet" -version = "0.17.0" +version = "0.17.1" description = "A package to facilitate network simulations" readme = {file = "README.org", content-type = "text/plain"} requires-python = ">=3.9" diff --git a/tests/basic/munet.yaml b/tests/basic/munet.yaml index 5e83cad..c6096f1 100644 --- a/tests/basic/munet.yaml +++ b/tests/basic/munet.yaml @@ -1,6 +1,7 @@ version: 1 topology: networks-autonumber: true + loopbacks-autonumber: true ipv6-enable: true networks: - name: net0 diff --git a/tests/basic/test_basic_topology.py b/tests/basic/test_basic_topology.py index 688426c..b4a1d46 100644 --- a/tests/basic/test_basic_topology.py +++ b/tests/basic/test_basic_topology.py @@ -77,16 +77,14 @@ async def test_autonumber_ping(unet_perfunc): o = await r2.async_cmd_raises("ping -w1 -c1 fcff:ffff:2::1") logging.debug("r2 ping r3 p2p (fcff:ffff:2::1) output: %s", o) - o = await r2.async_cmd_raises("ping -w1 -c1 fcfe:ffff:2::1") - logging.debug("r2 ping lo (fcfe:ffff:2::1) output: %s", o) + o = await r2.async_cmd_raises("ping -w1 -c1 fcfe::2") + logging.debug("r2 ping lo (fcfe::2) output: %s", o) o = await r1.async_cmd_nostatus("ip -6 neigh show") logging.info("ip -6 neigh show: %s", o) -@pytest.mark.parametrize( - "unet_perfunc", ["munet"], indirect=["unet_perfunc"] -) +@pytest.mark.parametrize("unet_perfunc", ["munet"], indirect=["unet_perfunc"]) async def test_basic_config(unet_perfunc): unet = unet_perfunc r3 = unet.hosts["r3"] diff --git a/uv.lock b/uv.lock index 777184d..1035da1 100644 --- a/uv.lock +++ b/uv.lock @@ -825,7 +825,7 @@ wheels = [ [[package]] name = "munet" -version = "0.17.0" +version = "0.17.1" source = { editable = "." } dependencies = [ { name = "deepdiff" },