iopsys-feed/netmode/docs/ADVANCED_MODE_IMPLEMENTATION.md
Mohd Husaam Mehdi 40240a7152 netmode: update handling of direct interfaces
the idea is to make them similar to route interface, to avoid
confusion

* they can be also be mgmt/inet/iptv
* they will have default proto set to dhcp
* syntax is now direct:vlan:100 or direct:transparent
2026-01-23 18:34:10 +05:30

567 lines
12 KiB
Markdown

# Advanced Mode - Implementation Summary
## Overview
The **advanced** mode is a unified network configuration mode that consolidates and extends the functionality of the previous `bridged` and `routed-multi-service` modes into a single, flexible interface.
## Design Rationale
### Problems with Old Approach
1. **Mode Fragmentation**: Separate modes for bridged and routed scenarios
2. **Limited Flexibility**: Couldn't mix bridges and routed interfaces
3. **Confusing Naming**: "bridged" mode actually supported standalone interfaces too
4. **Parameter Proliferation**: routed-multi-service had 6+ parameters for just 3 services
5. **No Scalability**: Adding new services required new parameters
### New Unified Approach
The advanced mode uses a **declarative, array-based configuration**:
```
interface_names: wan, iptv, mgmt
interface_types: route:vlan:100, bridge:tagged:200, direct:vlan:300
ports: WAN, LAN1-LAN2-WAN, WAN
```
**Benefits**:
- ✅ Single mode for all scenarios
- ✅ Scalable (add N interfaces without new parameters)
- ✅ Flexible (mix bridge/route/standalone)
- ✅ Intuitive syntax
- ✅ Self-documenting configuration
## Architecture
### File Structure
```
netmode/
├── files/
│ ├── etc/netmodes/advanced/
│ │ └── scripts/
│ │ └── 10-advanced # Main mode script
│ ├── lib/netmode/
│ │ └── advanced_helper.sh # Helper library
│ └── etc/netmodes/supported_modes.json
└── docs/
├── ADVANCED_MODE_GUIDE.md # Complete guide
└── ADVANCED_MODE_QUICK_REFERENCE.md
```
### Components
#### 1. advanced_helper.sh
**Purpose**: Core library for interface creation
**Key Functions**:
- `parse_interface_type()` - Parse interface type specifications
- `create_bridge()` - Create bridge interfaces with VLAN/QinQ
- `create_routed_interface()` - Create routed interfaces with VLAN/MACVLAN
- `create_standalone_interface()` - Create direct VLAN interfaces
- `parse_port_list()` - Resolve port macros to device names
- `resolve_device_name()` - Resolve LAN1/WAN to actual device names
- `cleanup_interfaces()` - Clean up all interfaces before applying new config
#### 2. 10-advanced Script
**Purpose**: Main mode script
**Flow**:
1. Parse environment variables (NETMODE_*)
2. Split comma-separated values
3. Loop through each interface
4. Parse interface type
5. Call appropriate creation function (bridge/route/direct)
6. Configure multicast, DHCP, firewall
7. Update service dependencies
#### 3. supported_modes.json
**Purpose**: Mode definition for UCI import
**Configuration**:
```json
{
"name": "advanced",
"description": "Advanced Mode - Unified configuration...",
"supported_args": [
{
"name": "interface_names",
"description": "Interface names (comma-separated...)",
"type": "string"
},
...
]
}
```
## Interface Type Syntax
### Design Philosophy
**Format**: `MODE:SUBTYPE[:PARAMS][:MODIFIERS]`
Examples:
- `bridge:transparent` - Mode=bridge, Subtype=transparent
- `bridge:tagged:100` - Mode=bridge, Subtype=tagged, Param=VID
- `route:vlan:100:AA:BB:CC:DD:EE:FF` - Mode=route, Subtype=vlan, Params=VID+MAC
- `direct:vlan:2501-n` - Mode=direct, Param=VID, Modifier=proto_none
### Parsing Logic
The `parse_interface_type()` function:
1. **Extract modifiers** (-n, -d)
2. **Parse mode prefix** (bridge:/route:/direct:)
3. **Parse subtype** (transparent/tagged/vlan/macvlan)
4. **Parse parameters** (VID, SVID, MAC address)
5. **Export to environment variables** for caller
## UCI Device Resolution
### Problem
Port macros (LAN1, LAN2, WAN) are logical names that need to be mapped to actual hardware interfaces.
### Solution
```bash
resolve_device_name() {
local device_id="$1"
local resolved_name=""
# Try UCI device section
resolved_name="$(uci -q get network.${device_id}.name)"
# Fallback to input
if [ -z "$resolved_name" ]; then
resolved_name="$device_id"
fi
echo "$resolved_name"
}
```
**Example**:
```
LAN1 → uci get network.LAN1.name → eth1
WAN → uci get network.WAN.name → ae_wan
```
### Port List Resolution
The `parse_port_list()` function:
1. **Check for "ALL"** → Resolve all LAN1-8 + WAN
2. **Parse dash-separated** → LAN1-LAN2-WAN → resolve each
3. **Return space-separated** → "eth1 eth2 ae_wan"
## VLAN Device Creation
### 802.1Q (C-tag)
```bash
create_vlan_device "eth0" "100" "8021q"
```
Creates:
```
config device 'eth0__100'
option type '8021q'
option enabled '1'
option vid '100'
option ifname 'eth0'
option name 'eth0.100'
```
### 802.1ad (S-tag)
```bash
create_vlan_device "eth0" "300" "8021ad"
```
Creates:
```
config device 'eth0__300'
option type '8021ad'
option enabled '1'
option vid '300'
option ifname 'eth0'
option name 'eth0.300'
```
### QinQ (Double Tagging)
For `bridge:qinq:100:300`:
```bash
# Create S-tag first
svlan=$(create_vlan_device "eth0" "300" "8021ad") # eth0.300
# Create C-tag on top of S-tag
cvlan=$(create_vlan_device "$svlan" "100" "8021q") # eth0.300.100
```
Result: `eth0.300.100` (S-tag 300, C-tag 100)
## MACVLAN Device Creation
For `route:macvlan:AA:BB:CC:DD:EE:FF`:
```bash
create_macvlan_device "ae_wan" "AA:BB:CC:DD:EE:FF" "iptv"
```
Creates:
```
config device 'iptv_macvlan'
option type 'macvlan'
option enabled '1'
option ifname 'ae_wan'
option name 'iptv_macvlan'
option macaddr 'AA:BB:CC:DD:EE:FF'
option mode 'passthru'
```
## Bridge Creation
### Transparent Bridge
For `bridge:transparent` with `ports='ALL'`:
```bash
create_bridge "wan" "bridge:transparent" "ALL"
```
Creates:
```
config interface 'wan'
option proto 'dhcp'
option device 'br-wan'
config device 'br_wan'
option name 'br-wan'
option type 'bridge'
option bridge_empty '1'
list ports 'eth1'
list ports 'eth2'
list ports 'ae_wan'
```
### VLAN-Tagged Bridge
For `bridge:tagged:100` with `ports='ALL'`:
Creates VLAN devices on all ports first, then adds to bridge:
```
config device 'br_mgmt'
option name 'br-mgmt'
option type 'bridge'
list ports 'eth1.100'
list ports 'eth2.100'
list ports 'ae_wan.100'
```
## Routed Interface Creation
For `route:vlan:100`:
```bash
create_routed_interface "wan" "vlan" "100" "" "dhcp" "ae_wan" "0"
```
Creates:
```
config device 'ae_wan__100'
option type '8021q'
option vid '100'
option ifname 'ae_wan'
option name 'ae_wan.100'
config interface 'wan'
option proto 'dhcp'
option device 'ae_wan.100'
```
## Firewall Logic
The advanced mode has **intelligent firewall handling**:
```bash
configure_firewall() {
local has_routed=0
# Check if ANY interface is routed
for if_type in $interface_types; do
if echo "$if_type" | grep -q "^route:"; then
has_routed=1
break
fi
done
if [ "$has_routed" = "1" ]; then
uci set firewall.globals.enabled="1" # Enable for routed
else
uci set firewall.globals.enabled="0" # Disable for bridge-only
fi
}
```
**Logic**:
- If **any** interface is routed → Enable firewall
- If **all** interfaces are bridges → Disable firewall
## Environment Variable Flow
### Input (UCI → Environment)
```bash
# In netmode init script
export NETMODE_interface_names="wan,iptv,mgmt"
export NETMODE_interface_types="route:vlan:100,route:vlan:200,route:vlan:300"
export NETMODE_ports="WAN,WAN,WAN"
```
### Parsing (Script)
```bash
# In 10-advanced script
local interface_names="${NETMODE_interface_names:-wan}"
local interface_types="${NETMODE_interface_types:-bridge:transparent}"
local ports="${NETMODE_ports:-ALL}"
# Split by comma
IFS=','
for name in $interface_names; do
names_arr="$names_arr $name"
done
```
### Output (UCI Network Config)
```
config interface 'wan'
option proto 'dhcp'
option device 'ae_wan.100'
config interface 'iptv'
option proto 'dhcp'
option device 'ae_wan.200'
...
```
## Cleanup Strategy
Before applying new configuration, all existing interfaces are cleaned up:
```bash
cleanup_interfaces() {
# Delete VLAN devices (8021q and 8021ad)
for vlandev_sec in $(uci show network | grep -E "\.type='(8021q|8021ad)'" ...); do
uci delete "$vlandev_sec"
done
# Delete MACVLAN devices
for macvlandev_sec in $(uci show network | grep "\.type='macvlan'" ...); do
uci delete "$macvlandev_sec"
done
# Delete bridge devices
for brdev_sec in $(uci show network | grep "\.type='bridge'" ...); do
uci delete "$brdev_sec"
done
# Delete standard interfaces
uci delete network.lan
uci delete network.wan
uci delete network.wan6
}
```
This ensures a clean slate for the new configuration.
## Migration Path
### From bridged Mode
**Before**:
```bash
mode='bridged'
interface_names='wan,lan100'
interface_types='transparent,tagged:100'
ports='ALL,LAN1-LAN2'
```
**After**:
```bash
mode='advanced'
interface_names='wan,lan100'
interface_types='bridge:transparent,bridge:tagged:100'
ports='ALL,LAN1-LAN2'
```
**Change**: Add `bridge:` prefix to types.
### From routed-multi-service Mode
**Before**:
```bash
mode='routed-multi-service'
inet_vlanid='100'
iptv_vlanid='200'
mgmt_vlanid='300'
```
**After**:
```bash
mode='advanced'
interface_names='wan,iptv,mgmt'
interface_types='route:vlan:100,route:vlan:200,route:vlan:300'
ports='WAN,WAN,WAN'
```
**Change**: Explicit interface names and unified syntax.
## Testing Approach
### Unit Testing
Test individual helper functions:
```bash
# Test device resolution
resolve_device_name "LAN1" # Should return eth1
# Test port parsing
parse_port_list "LAN1-LAN2-WAN" # Should return "eth1 eth2 ae_wan"
# Test type parsing
parse_interface_type "bridge:qinq:100:300-n"
# Should set: mode=bridge, vlan_type=qinq, cvid=100, svid=300, proto=none
```
### Integration Testing
Test complete scenarios:
```bash
# Test transparent bridge
uci set netmode.global.mode='advanced'
uci set netmode.@supported_args[0].value='wan'
uci set netmode.@supported_args[1].value='bridge:transparent'
uci set netmode.@supported_args[2].value='ALL'
uci commit netmode
service netmode restart
# Verify
brctl show | grep br-wan
```
### Validation
```bash
# Check UCI output
uci show network
# Check actual interfaces
ip addr show
brctl show
ip -d link show type vlan
# Check logs
logread | grep netmode-advanced
```
## Performance Considerations
### Comma Splitting Optimization
The script uses efficient IFS-based splitting:
```bash
local OLD_IFS="$IFS"
IFS=','
for name in $interface_names; do
names_arr="$names_arr $name"
done
IFS="$OLD_IFS"
```
This is faster than using `cut` or `awk` in loops.
### UCI Batching
All UCI commands are batched, with a single `uci commit` at the end:
```bash
# Multiple uci set commands
uci set ...
uci set ...
uci set ...
# Single commit
uci commit network
```
### Logging
Logging is selective - info level for major steps, debug for details:
```bash
_log "Creating interface $idx/$total_interfaces" # Info
logger -s -p user.debug -t "$_log_prefix" "Adding port: $port" # Debug
```
## Security Considerations
### Input Validation
- VLANs IDs: 1-4094
- MAC addresses: Validated format
- Port names: Resolved through UCI (trusted source)
### Privilege Separation
- Script runs as root (required for network config)
- No user input directly executed
- Environment variables sanitized through UCI
## Future Enhancements
Possible future additions:
1. **Static IP support**: `route:vlan:100:static:192.168.1.1`
2. **Port roles**: `ports='LAN1(tagged),LAN2(untagged)'`
3. **Bridge STP**: `bridge:transparent:stp`
4. **IPv6 specific**: `route:vlan:100:ipv6`
5. **Validation**: Pre-flight checks for VLAN conflicts
## Backward Compatibility
**Status**: ⚠️ Breaking change by design
The old `bridged` and `routed-multi-service` modes are **replaced** by advanced mode. This is acceptable because:
1. This is the **first deployment** of advanced features
2. No existing production deployments use old syntax
3. Cleaner architecture without legacy baggage
4. Documentation focuses on new syntax only
## Summary
The advanced mode represents a significant architectural improvement:
-**Unified**: One mode for all scenarios
-**Scalable**: Array-based configuration
-**Flexible**: Mix bridges, routed, standalone
-**Intuitive**: Self-documenting syntax
-**Powerful**: VLAN, QinQ, MACVLAN support
-**Clean**: No backward compatibility burden
---
**Implementation Version**: 1.0
**Date**: 2024-12-12
**Status**: Production Ready