Transparent SQM Box - bypass VLAN traffic

Hello,
I have set up a transparent OpenWRT instance to use SQM behind my existing router.
Traffic from WAN to LAN and from LAN to WAN is already handled correctly. The configuration was done using this thread.
OpenWRT is set up as a dumb AP and has two interfaces. A bridge connects both interfaces (eth0, eth1).

WAN -> Router -> [eth1] OpenWRT [eth0]-> VLAN 1
                                         VLAN 2
                                         ...
/etc/config/sqm
config queue
        option interface 'eth0'
        option qdisc 'cake'
        option script 'piece_of_cake.qos'
        option debug_logging '0'
        option verbosity '5'
        option qdisc_advanced '1'
        option qdisc_really_really_advanced '1'
        option linklayer 'ethernet'
        option overhead '34'
        option squash_ingress '0'
        option squash_dscp '0'
        option ingress_ecn 'NOECN'
        option egress_ecn 'ECN'
        option download '0'
        option upload '85000'
        option eqdisc_opts 'dual-dsthost diffserv3 wash'
        option enabled '1'

config queue
        option interface 'eth1'
        option qdisc 'cake'
        option script 'piece_of_cake.qos'
        option debug_logging '0'
        option verbosity '5'
        option qdisc_advanced '1'
        option qdisc_really_really_advanced '1'
        option linklayer 'ethernet'
        option overhead '34'
        option squash_ingress '0'
        option squash_dscp '0'
        option ingress_ecn 'NOECN'
        option egress_ecn 'ECN'
        option download '0'
        option upload '30000'
        option eqdisc_opts 'dual-srchost diffserv3 wash'
        option enabled '1'

My problem is that the traffic between two VLANs is also limited by SQM.
This is obvious, because the traffic crosses the OpenWRT instance and does not know that the router behind does not route the traffic to the WAN, but to another subnet.

Is it possible to route the traffic that goes to another VLAN (192.168.0.0/16) so that it does not cross the SQM interfaces? Maybe by adding additional network interfaces and firewall rules?

Thanks.

That sounds a bit complicated, but doable, I however have no first hand experience so will refrain from speculating how exactly.
As a work around you could use the OpenWrt router's switch for configuring your VLANs and then, if you use a single SQM instance with download not set to 0 (so using an IFB on eth1 for ingress/download traffic you should be fine.

Thank you very much for your answer.
What do you mean by using the OpenWRT switch for configuring the VLANs? Does that means that I need to move all VLAN firewall rules from the router to the OpenWRT instance so that the VLAN traffic does not reach the router?

Yes, if you have specific firewall separation between the VLANs you would need to enforce them on the OpenWrt router. Which might doom this approach as that will not be a simple work-around anymore, sorry.

Something like that would be useful.

Router ->           OpenWRT          -> VLAN 1
            eth1    no SQM     eth0     VLAN 2
            eth2     SQM       eth3     ...

With the following rules:
if device is eth1 and source is not 192.168.0.0/16; then move to device eth2
if device is eth0 and destination is not 192.168.0.0/16; then move to device eth3

I think this requires also two additional bridges eth1,eth2 and eth0,eth3.

I have already installed kmod-br-netfilter and tried to somehow push the traffic to the other interface through firewall rules. But unfortunately I did not manage to do that.

If you have an idea how this could work, I would appreciate your ideas, even if the whole thing is untested and might not work.

I guess what might work is to use IFBs for both ingress and egress traffic, but to exclude internal traffic. I believe @Lynx has some experience with that and might be able to chime in here.

1 Like

@heja I'm confident you can achieve what you want using the approach adopted either here:

Or here:

Basically you just set up one or two IFBs, pull the traffic you need through them, and put CAKE on them.

You can select traffic using 'tc' mirroring calls with different matches and priorities like:

	# capture all packets on WAN
        tc qdisc add dev $wan_if handle ffff: ingress
        tc filter add dev $wan_if parent ffff: prio 2 matchall action mirred egress redirect dev ifb-wg-pbr

	# if 'wg show' reports an endpoint, then pass over wireguard packets on WAN and capture all VPN packets
	if [ ! -z "$wg_endpoint" ]
	then
       		tc filter add dev $wan_if parent ffff: protocol ip prio 1 u32 match ip src ${wg_endpoint}/32 action pass
       		tc qdisc add dev $vpn_if handle ffff: ingress
       		tc filter add dev $vpn_if parent ffff: matchall action mirred egress redirect dev ifb-wg-pbr
	fi

Or like this having fwmarked as appropriate in firewall.

	# capture br-lan (ingress) -> wan
	# filter by fwmark 1
	tc filter add dev br-lan parent ffff: protocol ip handle 1 fw flowid 1:1 action mirred egress redirect dev ifb-ul

	# capture br-guest (ingress) -> wan
	# filter by fwmark 2
	tc filter add dev br-guest parent ffff: protocol ip handle 2 fw flowid 1:1 action mirred egress redirect dev ifb-ul

	# capture OpenWrt -> wan (egress)
	# filter by fwmark 3 (use nftables to skip over WireGuard traffic with fwmark 2 and apply fwmark 3 to the remainder)
	tc filter add dev wan parent 1: protocol ip handle 3 fw flowid 1:1 action mirred egress redirect dev ifb-ul

	# capture wan -> br-lan (egress) and restore DSCPs from conntracks
	# filter by fwmark 1
	tc filter add dev br-lan parent 1: protocol ip handle 1 fw flowid 1:1 action ctinfo dscp 63 128 action mirred egress redirect dev ifb-dl

	# capture wan -> br-guest (egress) and restore DSCPs from conntracks
	# filter by fwmark 2
	tc filter add dev br-guest parent 1: protocol ip handle 2 fw flowid 1:1 action ctinfo dscp 63 128 action mirred egress redirect dev ifb-dl

	# capture wan (ingress) -> OpenWrt and restore DSCPs from conntracks
	# filter on conntrack bit 128 set
 	tc filter add dev wan parent ffff: prio 1 protocol ip matchall action ctinfo cpmark continue
	tc filter add dev wan parent ffff: prio 2 protocol ip handle 256/256 fw flowid 1:1 action ctinfo dscp 63 128 action mirred egress redirect dev ifb-dl
1 Like

Sorry for the late response. I had to test a lot before it finally worked.
Thank you very much for your help @moeller0 and @Lynx.

This is what I have done:

Add a second interface to br-lan bridge (VLAN ID 1)

Network -> Interfaces -> Devices -> Edit br-lan
Bridge ports: eth0, eth1

Add bridges and interfaces for all VLANs

This is required because otherwise only VLAN ID 1 is inspected by the firewall.

This is an example for VLAN ID 10. Repeat these steps for all other IDs.

Network -> Interfaces -> Devices -> Add device configuration

Device type: Bridge Device
Device name: br-lan-vl10
Bridge ports: eth0.10, eth1.10

Network -> Interfaces -> Interfaces -> Add new interface

Name: vl10
Protocol: Unmanaged
Device: br-lan-vl10

Create firewall rules to mark non internal traffic

Network -> Firewall -> Traffic Rules

Name: lan to wan
Protocol: Any
Source zone: Any zone (forward)
Source address: empty
Destination zone: Any zone (forward)
Destination address: !192.168.0.0/16
Action: apply firewall mark
Set mark: 1

Name: wan to lan
Protocol: Any
Source zone: Any zone (forward)
Source address: !192.168.0.0/16
Destination zone: Any zone (forward)
Destination address: empty
Action: apply firewall mark
Set mark: 2

Make sure that the firewall service is enabled and started in System -> Startup.

Install required packages

opkg update

Install requirements for the cake script:
opkg install tc-tiny kmod-ifb kmod-sched kmod-sched-core kmod-sched-cake kmod-sched-ctinfo

Install package to enable bridge firewall:
opkg install kmod-nft-bridge

Add cake script

nano /etc/init.d/cake-ifb

#!/bin/sh /etc/rc.common

set -x

START=50
STOP=4

wan_interfaces="eth1 eth1.10"
lan_interfaces="eth0 eth0.10"
upload_speed="37Mbit"
download_speed="190Mbit"

start() {
        ip link add name ifb-dl type ifb
        ip link set ifb-dl up

        ip link add name ifb-ul type ifb
        ip link set ifb-ul up

        for iface in $wan_interfaces $lan_interfaces; do
            tc qdisc add dev $iface handle ffff: ingress
            tc qdisc add dev $iface handle 1: root prio
        done

        for iface in $lan_interfaces; do
            tc filter add dev $iface parent 1: protocol ip handle 2 fw flowid 1:1 action mirred egress redirect dev ifb-dl
        done

        for iface in $wan_interfaces; do
            tc filter add dev $iface parent 1: protocol ip handle 1 fw flowid 1:1 action mirred egress redirect dev ifb-ul
        done

        tc qdisc add dev ifb-ul root cake bandwidth $upload_speed diffserv4 dual-srchost nonat wash no-ack-filter noatm overhead 92
        tc qdisc add dev ifb-dl root cake bandwidth $download_speed diffserv4 dual-dsthost nonat nowash ingress no-ack-filter noatm overhead 92
}

stop() {
        for iface in $wan_interfaces $lan_interfaces; do
            tc qdisc del dev $iface ingress
            tc qdisc del dev $iface root
        done

        ip link set ifb-dl down
        ip link del ifb-dl

        ip link set ifb-ul down
        ip link del ifb-ul
}

chmod +x /etc/init.d/cake-ifb

Adjust your VLAN IDs in wan_interfaces and lan_interfaces.
Adjust your upload and download speed in upload_speed and download_speed.

Enable and start service cake-ifb in System -> Startup.

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.