mirror of
https://dev.iopsys.eu/feed/iopsys.git
synced 2026-01-28 01:47:19 +01:00
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
567 lines
12 KiB
Markdown
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
|