# 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