I'm asking for help setting up vlan trunks via 802.11s. At the moment I have a router and 2 repeaters. They are connected via PLC. I want to make a backup connection to them via 5+2 GHz, and also connect two more repeaters with swconfig at 2 GHz without a cable. @bluewavenet suggested that this can be done using vxlan, but I have not found similar examples of how to do this. At the moment, I have made a script that creates nftables rules to protect against loops in the bridges, assigned mesh_hwmp_rootmode 4/0, mesh_gate_annuncements 1/0 to the router and repeaters, created 802.11s access points, but did not attach them to any network. The current network configurations is as follows:
#router network
config interface 'loopback'
option device 'lo'
option proto 'static'
option ipaddr '127.0.0.1'
option netmask '255.0.0.0'
config globals 'globals'
option ula_prefix 'fdef:7753:fd90::/48'
option packet_steering '1'
config device
option name 'br-lan'
option type 'bridge'
list ports 'lan1'
list ports 'lan2'
list ports 'lan3'
config interface 'lan'
option device 'br-lan.1'
option proto 'static'
option ipaddr '192.168.1.1'
option netmask '255.255.255.0'
option ip6assign '60'
config interface 'wan'
option device 'wan'
option proto 'dhcp'
config interface 'wan6'
option device 'wan'
option proto 'dhcpv6'
config interface 'wwan'
option proto 'qmi'
option device '/dev/cdc-wdm0'
option auth 'none'
option pdptype 'ipv4'
config bridge-vlan
option device 'br-lan'
option vlan '1'
list ports 'lan1'
list ports 'lan2'
list ports 'lan3'
config bridge-vlan
option device 'br-lan'
option vlan '3'
list ports 'lan1:t'
list ports 'lan2:t'
list ports 'lan3:t'
config interface 'gosti'
option proto 'static'
option device 'br-lan.3'
option ipaddr '192.168.3.1'
option netmask '255.255.255.0'
option ip6assign '60'
#repeater1 network
config interface 'loopback'
option device 'lo'
option proto 'static'
option ipaddr '127.0.0.1'
option netmask '255.0.0.0'
config globals 'globals'
option ula_prefix 'fd42:93d2:5a22::/48'
option packet_steering '1'
config device
option name 'br-lan'
option type 'bridge'
list ports 'lan1'
list ports 'lan2'
list ports 'lan3'
list ports 'lan4'
config interface 'lan'
option device 'br-lan.1'
option proto 'static'
option ipaddr '192.168.1.2'
option netmask '255.255.255.0'
option gateway '192.168.1.1'
list dns '192.168.1.1'
option delegate '0'
config interface 'wan'
option device 'wan'
option proto 'dhcp'
config bridge-vlan
option device 'br-lan'
option vlan '1'
list ports 'lan1'
list ports 'lan2'
list ports 'lan3'
list ports 'lan4'
config bridge-vlan
option device 'br-lan'
option vlan '3'
list ports 'lan1:t'
list ports 'lan2:t'
list ports 'lan3:t'
list ports 'lan4:t'
config interface 'gosti'
option proto 'none'
option device 'br-lan.3'
config interface 'wan6'
option proto 'dhcpv6'
option device 'wan'
option reqaddress 'try'
option reqprefix 'auto'
option norelease '1'
I think I figured out how to do it. For now, at least, everything is working. All I had to do was get up at 4 a.m. That's what I got. I installed the luci-proto-vxlan, ip-full (not sure if it was needed), kmod-nft-bridge packages. I created the vxlan interface for the guest network, disabled vlan filtering on the bridge, enabled stp and igmp snooping, created a new bridge for the guest network, added the vxlan interface of the guest network to it. 802.11s tied to the lan.
#router
config interface 'loopback'
option device 'lo'
option proto 'static'
option ipaddr '127.0.0.1'
option netmask '255.0.0.0'
config globals 'globals'
option ula_prefix 'fdef:7753:fd90::/48'
option packet_steering '1'
config device
option name 'br-lan'
option type 'bridge'
list ports 'lan1'
list ports 'lan2'
list ports 'lan3'
option stp '1'
option hello_time '4'
option igmp_snooping '1'
config interface 'lan'
option device 'br-lan'
option proto 'static'
option ipaddr '192.168.1.1'
option netmask '255.255.255.0'
option ip6assign '60'
config interface 'wan'
option device 'wan'
option proto 'dhcp'
config interface 'wan6'
option device 'wan'
option proto 'dhcpv6'
config interface 'wwan'
option proto 'qmi'
option device '/dev/cdc-wdm0'
option auth 'none'
option pdptype 'ipv4'
config interface 'gosti'
option proto 'static'
option device 'br-gosti'
option ipaddr '192.168.3.1'
option netmask '255.255.255.0'
option ip6assign '60'
config interface 'vxlan3_gosti'
option proto 'vxlan'
option peeraddr '239.1.3.1'
option port '4789'
option vid '3'
option tunlink 'lan'
config device
option type 'bridge'
option name 'br-gosti'
list ports 'vxlan3_gosti'
option bridge_empty '1'
option stp '1'
option hello_time '4'
option igmp_snooping '1'
#repeater1
config interface 'loopback'
option device 'lo'
option proto 'static'
option ipaddr '127.0.0.1'
option netmask '255.0.0.0'
config globals 'globals'
option ula_prefix 'fd42:93d2:5a22::/48'
option packet_steering '1'
config device
option name 'br-lan'
option type 'bridge'
list ports 'lan1'
list ports 'lan2'
list ports 'lan3'
list ports 'lan4'
option stp '1'
option hello_time '4'
option igmp_snooping '1'
config interface 'lan'
option device 'br-lan'
option proto 'static'
option ipaddr '192.168.1.2'
option netmask '255.255.255.0'
option gateway '192.168.1.1'
list dns '192.168.1.1'
option delegate '0'
config interface 'wan'
option device 'wan'
option proto 'dhcp'
config interface 'gosti'
option proto 'none'
option device 'br-gosti'
config interface 'wan6'
option proto 'dhcpv6'
option device 'wan'
option reqaddress 'try'
option reqprefix 'auto'
option norelease '1'
config interface 'vxlan3_gosti'
option proto 'vxlan'
option peeraddr '239.1.3.1'
option port '4789'
option vid '3'
option tunlink 'lan'
config device
option type 'bridge'
option name 'br-gosti'
list ports 'vxlan3_gosti'
option bridge_empty '1'
option stp '1'
option hello_time '4'
option igmp_snooping '1'
Cool! I am guessing you read the code in mesh11sd then
You need the loop protection if you have any cabled segments in the backhaul.
Any particular reason for setting mesh path cost to 181?
Normally you would set it to a very high value to prioritise using the cable segment over a possible mesh link. Likewise a very low value to prioritise using the mesh link.
You also might need to enable VLAN Aggregation, aka mac forced forwarding, aka proxy_arp_pvlan, for ipv4 on the mesh interface, otherwise you can end up with tcp links breaking etc
Yes, it all started with studying the code. When I started using mesh11d, I came across the fact that 2 wifi bands cannot be used simultaneously. This was the reason why I started studying the code and configuring it manually.
I calculated this as the default path cost phy0-mesh 100 + (default path cost phy0-mesh 100 - default path cost ethernet 100mbps 19). I have not found information about what default values different interfaces can take under different conditions in order to more accurately select this value.
To be clear, this is two mesh interfaces on separate bands at the same time.
To want more than one mesh interface is pretty much an edge case. Mesh11sd detects mesh capable hardware but stops short of enabling any more than one, based on its config.
If you do have more than one mesh interface on the backhaul, you WILL have loop problems unless you have the nft bridge rules and STP config in place to prevent it.
Note: STP by itself id not sufficient because the loop occurs through the mesh interface at kernel level, before STP has a chance to do anything.
It is planned in a future version to enable multiple separate backhaul support in mesh11sd, allowing bridging between two or more independent backhauls. This functionality will be very convenient in large Community or WISP deployments, particularly from the point of view of traffic partitioning, resilience etc., but it is worth noting that in most regions, use of 5GHz channels outdoors is severely restricted.
As you have gone to the effort of doing some reverse engineering of the code, you are welcome to contribute to the project if you wish. Feature requests and PRs welcome:
#!/bin/sh
# Function to get the MAC address of the bridge
get_bridge_mac() {
local device="$1"
ip link show dev "$device" | grep "link/ether" | awk '{printf "%s", $2}'
}
# Function to get the list of interfaces in the bridge
get_bridge_interfaces() {
local device="$1"
brctl showstp "$device" | grep -B 1 -w "port id" | grep "(" | awk '{printf "%s ", $1}'
}
# Function to add nftables rules for the bridge
configure_bridge_loop_protect() {
local device="$1"
local mac=$(get_bridge_mac "$device")
# Check if the MAC address was obtained
if [ -z "$mac" ]; then
echo "Error: Failed to get MAC address for bridge $device"
return 1
fi
nft add table bridge "backhaul_loop_protect" 2>/dev/null
nft add chain bridge "backhaul_loop_protect" "backhaul_loop_protect_prerouting" { type filter hook prerouting priority -350\; } 2>/dev/null
# Add rules for each interface in the bridge
for interface in $(get_bridge_interfaces "$device"); do
nft add rule bridge "backhaul_loop_protect" "backhaul_loop_protect_prerouting" meta iifname "$interface" ether saddr "$mac" counter drop 2>/dev/null
nft add rule bridge "backhaul_loop_protect" "backhaul_loop_protect_prerouting" meta iifname "$interface" counter accept 2>/dev/null
echo "Rules added for interface $interface in bridge $device"
done
}
# Find all bridge interfaces (assuming names contain "br-")
for device in $(brctl show | awk 'NR>1 {print $1}' | grep '^br-'); do
echo "Configuring loop protection for bridge $device"
configure_bridge_loop_protect "$device"
done
exit 0
Thank you, but it's not easy for me. I'm not ready for that yet.