From d0389e5638d2e2838debd778bec391c8553dfb7b Mon Sep 17 00:00:00 2001 From: Pranav Jerry Date: Mon, 27 Sep 2021 12:43:09 +0530 Subject: [PATCH] set gateway mode automatically Added arg and config option to manually set gw_mode. When gateway_mode is auto, a temporary config will be added, and after a ten sec delay, naxalnet will check if systemd-networkd shows a 'routable' connection. If the connection is routable, gw_mode will be set to server; or client otherwise. --- naxalnet.conf.example | 9 +++++ naxalnet/__init__.py | 2 +- naxalnet/config.py | 6 ++++ naxalnet/default.py | 1 + naxalnet/network.py | 26 ++++++++++++-- naxalnet/scripts.py | 49 +++++++++++++++++++++++--- systemd-networkd/mesh.01-batman.netdev | 4 +-- 7 files changed, 87 insertions(+), 10 deletions(-) diff --git a/naxalnet.conf.example b/naxalnet.conf.example index cde3d4f..5373d61 100644 --- a/naxalnet.conf.example +++ b/naxalnet.conf.example @@ -12,9 +12,18 @@ confdir = /usr/share/naxalnet/networkd runtimedir = /run/systemd/network [device] +# These are better left this way +# Changing this won't do you any good, unless you have +# other network configs that would mess things up. batman=bat0 bridge=bridge0 +[gateway] +# This helps users choose the best network when multiple machines +# offer an internet connection, or to be more precise, a DHCP server +# Allowed values: auto, server, client or off +mode=auto + [adhoc] # All your nodes should have the same name name = NxMesh diff --git a/naxalnet/__init__.py b/naxalnet/__init__.py index ed843d0..78343da 100644 --- a/naxalnet/__init__.py +++ b/naxalnet/__init__.py @@ -35,4 +35,4 @@ See README.md for documentation. # # In case you forgot to change the version, skip the number # and put the next number in the next commit. -__version__ = "0.4.0a5.dev1" +__version__ = "0.4.0a5.dev2" diff --git a/naxalnet/config.py b/naxalnet/config.py index 434ea39..5983d85 100644 --- a/naxalnet/config.py +++ b/naxalnet/config.py @@ -170,6 +170,12 @@ def parse_args() -> Namespace: help="name of bridge interface", ) + parser.add_argument( + "--gateway-mode", + default=config["gateway"]["mode"], + help="auto, server, client, or off", + ) + parser.add_argument( "--version", "-V", diff --git a/naxalnet/default.py b/naxalnet/default.py index ac09674..9cbc599 100644 --- a/naxalnet/default.py +++ b/naxalnet/default.py @@ -34,6 +34,7 @@ CONFIG = { "device": {"batman": "bat0", "bridge": "bridge0"}, "adhoc": {"name": "NxMesh"}, "ap": {"ssid": "MeshWiFi", "passwd": "naxalnet256"}, + "gateway": {"mode": "auto"}, } # glob diff --git a/naxalnet/network.py b/naxalnet/network.py index 37b4101..bc5bdff 100644 --- a/naxalnet/network.py +++ b/naxalnet/network.py @@ -40,7 +40,10 @@ class NetworkD: self.variables = {} print(runtime_dir) self.runtime_path = Path(runtime_dir) - print(self.runtime_path) + # Create the runtime directory if it doesn't exist + self.runtime_path.mkdir(parents=True, exist_ok=True) + + # print(self.runtime_path) def set_vars(self, **variables): """set the variables to replace with str.format""" @@ -65,8 +68,27 @@ class NetworkD: print(self.runtime_path / name) destination.write_text(text, encoding="utf-8") self.reload() - self.files.append(name) + # This allows to delete all configs later + self.files.append(destination.name) def is_routable(self) -> bool: """returns true if any interface is routable""" return self.proxy.AddressState == "routable" + + def remove_config(self, name: str) -> None: + """ + remove the file called 'name' from the runtime dir and reload + """ + path = self.runtime_path / name + path.unlink() + self.reload() + + def remove_all_configs(self) -> None: + """ + Remove all configs added by add_config(). + The configs will be removed only if they were added in the same + instance of NetworkD, that is, only files in self.files will be + removed. + """ + for i in self.files: + self.remove_config(i) diff --git a/naxalnet/scripts.py b/naxalnet/scripts.py index 5a2b307..1390270 100644 --- a/naxalnet/scripts.py +++ b/naxalnet/scripts.py @@ -27,6 +27,7 @@ When run from the commandline, the function main() is called. """ import sys +import time from pathlib import Path from dasbus.error import DBusError from systemd.daemon import notify @@ -53,17 +54,39 @@ def get_sorted_glob(directory: str, glob: str): return sorted_list -def setup_mesh(): - """configure networkd to setup the mesh""" +def any_interface_is_routable(): + """returns true if any of the interfaces is routable""" + networkd = NetworkD(runtime_dir=args.networkd_runtime_dir) + + # First, add the temporary configs to networkd. + for i in get_sorted_glob(args.networkd_config_dir, TMP_NET_GLOB): + logger.debug("Adding temporary config %s", i) + networkd.add_config(i) + # Then, wait for some time to setup the network + time.sleep(10) + routable = networkd.is_routable() + networkd.remove_all_configs() + + return routable + + +def setup_mesh(gateway_mode: str = "off"): + """ + configure networkd to setup the mesh + + gateway_mode can be client, server, or off + """ try: notify("STATUS=Configuring the network...") logger.info("Copying network config files") dest = Path(args.networkd_runtime_dir) - # Create the volatile directory if it doesn't exist - dest.mkdir(parents=True, exist_ok=True) networkd = NetworkD(runtime_dir=args.networkd_runtime_dir) - networkd.set_vars(batdev=args.batman_device, bridgedev=args.bridge_device) + networkd.set_vars( + batdev=args.batman_device, + bridgedev=args.bridge_device, + gateway_mode=gateway_mode, + ) for i in get_sorted_glob(args.networkd_config_dir, MESH_GLOB): logger.debug("Adding network config %s", i) networkd.add_config(i) @@ -184,6 +207,22 @@ def main(): # Notify systemd that naxalnet is ready. # see man:sd_notify(3) notify("READY=1") + + if args.gateway_mode == "auto": + logger.info("Checking for internet connection") + notify("STATUS=Checking for internet") + # If any interface is routable, set gateway mode to server + if any_interface_is_routable(): + gateway_mode = "server" + else: + gateway_mode = "client" + logger.info("gateway_mode set to %s", gateway_mode) + elif args.gateway_mode in ["server", "client", "off"]: + gateway_mode = args.gateway_mode + else: + logger.error("gateway-mode has an illegal value") + exit(5) + setup_devices() setup_mesh() diff --git a/systemd-networkd/mesh.01-batman.netdev b/systemd-networkd/mesh.01-batman.netdev index 025e5da..fd09ba4 100644 --- a/systemd-networkd/mesh.01-batman.netdev +++ b/systemd-networkd/mesh.01-batman.netdev @@ -5,6 +5,6 @@ Name={batdev} Description=BATMAN interface Kind=batadv -# Use default settings. Uncomment to change # see man:systemd.netdev(5) ยง [BATMANADVANCED] SECTION OPTIONS -#[BatmanAdvanced] +[BatmanAdvanced] +GatewayMode={gateway_mode}