Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 197 additions & 0 deletions docs/source/backends/openwrt.rst
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,8 @@ There are 4 main types of interfaces:
- **bridge interfaces**: must be of type ``bridge``
- **dialup interfaces**: must be of type ``dialup``
- **modem manager interfaces**: must be of type ``modem-manager``
- **mesh interfaces**: must be of type ``mesh`` or ``batadv_hardif``
- **batman-adv interfaces**: must be of type ``batadv``

Interface object extensions
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -3244,6 +3246,201 @@ Will be rendered as follows:
option public_key '94a+MnZSdzHCzOy5y2K+0+Xe7lQzaa4v7lEiBZ7elVE='
option route_allowed_ips '1'

BATMAN-adv (Better Approach To Mobile Ad-hoc Networking)
---------------------------------------------------------

``OpenWrt`` backend includes support for BATMAN-adv, a mesh networking protocol
that operates on Layer 2. BATMAN-adv is designed to provide decentralized mesh
networking capabilities with automatic route optimization.

BATMAN-adv Interface Settings
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The main BATMAN-adv interface (``batadv`` type) represents the virtual mesh
interface and supports the following settings:

====================== ======= ============== =====================================
key name type default allowed values
====================== ======= ============== =====================================
``type`` string ``batadv`` ``batadv``
``proto`` string ``batadv`` ``batadv``
``name`` string required interface name (e.g., ``bat0``)
``routing_algo`` string ``BATMAN_IV`` ``BATMAN_IV``, ``BATMAN_V``
``bridge_loop_avoid.`` boolean ``True`` enable bridge loop avoidance
``gw_mode`` string ``off`` ``off``, ``client``, ``server``
``hop_penalty`` integer ``30`` penalty for each hop (0-255)
``mtu`` integer ``1500`` Maximum Transmission Unit
``fragmentation`` boolean ``True`` enable fragmentation
====================== ======= ============== =====================================

.. note::
**bridge_loop_avoidance** is shortened as ``bridge_loop_avoid.`` in the
table above due to space constraints. Use the full name
``bridge_loop_avoidance`` in your configuration.

BATMAN-adv Hard Interface Settings
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Hard interfaces (``batadv_hardif`` or ``mesh`` type) are the physical or
wireless interfaces that participate in the BATMAN-adv mesh network:

============ ====== ========= =============================================
key name type default description
============ ====== ========= =============================================
``type`` string required ``batadv_hardif`` or ``mesh``
``proto`` string required ``batadv_hardif``
``name`` string required logical interface name
``device`` string required physical device name (e.g., ``phy1-mesh0``)
``master`` string ``bat0`` name of the BATMAN-adv master interface
============ ====== ========= =============================================

.. note::
The ``mesh`` type is a convenience alias for ``batadv_hardif`` and is
typically used with 802.11s wireless mesh interfaces. Both types are
converted to the same ``batadv_hardif`` protocol in the OpenWrt
configuration.

BATMAN-adv Interface Example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The following *configuration dictionary*:

.. code-block:: python

{
"interfaces": [
{
"type": "batadv",
"proto": "batadv",
"name": "bat0",
"routing_algo": "BATMAN_V",
"bridge_loop_avoidance": True,
"gw_mode": "server",
"hop_penalty": 30,
"mtu": 1500,
"fragmentation": True,
}
]
}

Will be rendered as follows:

::

package network

config interface 'bat0'
option bridge_loop_avoidance '1'
option fragmentation '1'
option gw_mode 'server'
option hop_penalty '30'
option mtu '1500'
option proto 'batadv'
option routing_algo 'BATMAN_V'

BATMAN-adv Hard Interface Example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The following *configuration dictionary*:

.. code-block:: python

{
"interfaces": [
{
"type": "batadv_hardif",
"proto": "batadv_hardif",
"name": "batmesh",
"device": "phy1-mesh0",
"master": "bat0",
}
]
}

Will be rendered as follows:

::

package network

config interface 'batmesh'
option device 'phy1-mesh0'
option master 'bat0'
option proto 'batadv_hardif'

Mesh Interface (802.11s) Example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

For wireless mesh interfaces using 802.11s, you can use the ``mesh`` type as
a convenient alias:

.. code-block:: python

{
"interfaces": [
{
"type": "mesh",
"proto": "batadv_hardif",
"name": "batmesh",
"device": "phy1-mesh0",
"master": "bat0",
}
]
}

This will produce the same output as the previous example.

Complete BATMAN-adv Mesh Network Example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Here's a complete example showing a BATMAN-adv mesh network with a main
interface and a hard interface:

.. code-block:: python

{
"interfaces": [
{
"type": "batadv",
"proto": "batadv",
"name": "bat0",
"routing_algo": "BATMAN_V",
"bridge_loop_avoidance": True,
"gw_mode": "off",
"hop_penalty": 30,
"mtu": 1500,
"fragmentation": True,
},
{
"type": "mesh",
"proto": "batadv_hardif",
"name": "batmesh",
"device": "phy1-mesh0",
"master": "bat0",
}
]
}

Will be rendered as follows:

::

package network

config interface 'bat0'
option bridge_loop_avoidance '1'
option fragmentation '1'
option gw_mode 'off'
option hop_penalty '30'
option mtu '1500'
option proto 'batadv'
option routing_algo 'BATMAN_V'

config interface 'batmesh'
option device 'phy1-mesh0'
option master 'bat0'
option proto 'batadv_hardif'

All the other settings
----------------------

Expand Down
58 changes: 58 additions & 0 deletions netjsonconfig/backends/openwrt/converters/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,32 @@ def _intermediate_vxlan(self, interface):
interface["vid"] = interface.pop("vni")
return interface

def _intermediate_batadv(self, interface):
interface["proto"] = "batadv"
interface.setdefault("routing_algo", "BATMAN_IV")
interface["bridge_loop_avoidance"] = int(
interface.get("bridge_loop_avoidance", True)
)
interface.setdefault("gw_mode", "off")
interface.setdefault("hop_penalty", 30)
interface.setdefault("mtu", 1500)
interface["fragmentation"] = int(interface.get("fragmentation", True))
interface.pop("ifname", None)
return interface

def _intermediate_batadv_hardif(self, interface):
interface["proto"] = "batadv_hardif"
interface["device"] = interface.pop("device", interface.get("ifname", None))
interface.setdefault("master", "bat0")
interface.pop("enabled", None)
interface.pop("ifname", None)
return interface

def _intermediate_mesh(self, interface):
interface = self._intermediate_batadv_hardif(interface)
interface["proto"] = "batadv_hardif"
return interface

def _intermediate_8021_vlan(self, interface):
interface["name"] = "{}.{}".format(interface["ifname"], interface["vid"])
interface[".name"] = interface.get("network") or "vlan_{}_{}".format(
Expand Down Expand Up @@ -931,6 +957,38 @@ def _netjson_vxlan(self, interface):
interface["port"] = interface["port"]
return self.type_cast(interface, schema=self._vxlan_schema)

def _netjson_batadv(self, interface):
interface["type"] = "batadv"
# Convert numeric values back to booleans/ints for schema compliance
interface["bridge_loop_avoidance"] = bool(
int(interface.get("bridge_loop_avoidance", 1))
)
interface["fragmentation"] = bool(int(interface.get("fragmentation", 1)))
return interface

def _netjson_batadv_hardif(self, interface):
interface["type"] = "batadv_hardif"
# Ensure proto is set
if "proto" not in interface:
interface["proto"] = "batadv_hardif"
# Move device from name to device field
if "name" in interface and "device" not in interface:
interface["device"] = interface["name"]
interface["name"] = interface.get(
"network", interface.get("ifname", "batmesh")
)
if "enabled" in interface:
interface["enabled"] = bool(int(interface["enabled"]))
# Remove network if it's same as name
if interface.get("network") == interface.get("name"):
interface.pop("network", None)
return interface

def _netjson_mesh(self, block):
data = self._netjson_batadv_hardif(block)
data["type"] = "mesh"
return data

def __netjson_address(self, address, interface):
ip = ip_interface(address)
family = "ipv{0}".format(ip.version)
Expand Down
7 changes: 7 additions & 0 deletions netjsonconfig/backends/openwrt/converters/wireguard_peers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ class WireguardPeers(OpenWrtConverter):
# wireguard OpenWRT package, this is unpredictable
_uci_types = None

def should_skip_block(self, block):
"""
Override should_skip_block to only process blocks with .type starting with 'wireguard_'
"""
_type = block.get(".type", "")
return not _type.startswith("wireguard_")

def to_intermediate_loop(self, block, result, index=None):
result.setdefault("network", [])
result["network"].append(self.__intermediate_peer(block, index))
Expand Down
Loading