Page MenuHomeVyOS Platform

Adjust-mss not working on VLAN-aware bridge
Open, NormalPublicBUG

Description

Minimal configuration:

set interfaces bridge br0 enable-vlan
set interfaces bridge br0 ip adjust-mss '1377'
set interfaces bridge br0 member interface eth0 allowed-vlan '2'
set interfaces bridge br0 member interface eth1 allowed-vlan '2'

On connections passing through the router, mss is not changed:

vyos@br:~$ sudo tcpdump -ni any tcp and port 22
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes

19:57:26.972589 eth1  P   IP 10.2.2.33.58870 > 10.2.2.22.22: Flags [S], seq 2012243087, win 32120, options [mss 1460,sackOK,TS val 4271284820 ecr 0,nop,wscale 7], length 0
19:57:26.972623 eth0  Out IP 10.2.2.33.58870 > 10.2.2.22.22: Flags [S], seq 2012243087, win 32120, options [mss 1460,sackOK,TS val 4271284820 ecr 0,nop,wscale 7], length 0

Adding rules at bridge level using custom nft rules do the trick:

sudo nft add table bridge vyos_filter
sudo nft add chain bridge vyos_filter bridge_prerouting { type filter hook prerouting priority -200 \; }
sudo nft add rule bridge vyos_filter bridge_prerouting tcp flags syn counter tcp option maxseg size set 1355

And tcpdump:

vyos@br# sudo tcpdump -ni any tcp and port 22
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes

20:06:22.693778 eth1  P   IP 10.2.2.33.53818 > 10.2.2.22.22: Flags [S], seq 3036941485, win 32120, options [mss 1460,sackOK,TS val 4271820541 ecr 0,nop,wscale 7], length 0
20:06:22.693921 eth0  Out IP 10.2.2.33.53818 > 10.2.2.22.22: Flags [S], seq 3036941485, win 32120, options [mss 1355,sackOK,TS val 4271820541 ecr 0,nop,wscale 7], length 0

Details

Version
1.4.2
Is it a breaking change?
Perfectly compatible
Issue type
Bug (incorrect behavior)

Event Timeline

Need to check with the latest rolling release, as we have more flexibility in the bridge firewall. But command set interfaces bridge br0 ip adjust-mss '1377', with no extra config, most probably won't have desired effect.

Viacheslav triaged this task as Normal priority.Jun 6 2025, 6:25 AM
Viacheslav edited projects, added VyOS 1.4 Sagitta (1.4.3); removed VyOS 1.4 Sagitta.
dmbaturin changed Is it a breaking change? from Unspecified (possibly destroys the router) to Perfectly compatible.
dmbaturin renamed this task from adjust-mss not working on vlan aware bridge to Adjust-mss not working on VLAN-aware bridge.Jul 14 2025, 6:55 PM

@dmbaturin, @c-po, @jestabro and @n.fort

As far as I can see, the set interfaces bridge br0 ip adjust-mss '1350' command generates the following code for nftables:

...
table ip raw {
        chain VYOS_TCP_MSS {
                type filter hook forward priority raw; policy accept;
                oifname "br0" tcp flags syn / syn,rst counter packets 0 bytes 0 tcp option maxseg size 1351-65535 tcp option maxseg size set 1350
        }
...

This does not work because the bridge table is not used for this rule, unlike the provided manual configuration:

...
table bridge vyos_filter {           # <------- main difference 
        chain bridge_prerouting {
                type filter hook prerouting priority filter; policy accept;
                tcp flags syn counter packets 0 bytes 0 tcp option maxseg size set 1355
        }
}
...

@Viacheslav and @zsdc pointed me to the set firewall bridge prerouting filter rule 10 set tcp-mss 1350 command which do the same:

table bridge vyos_filter {
...
        chain VYOS_PREROUTING_filter {
                type filter hook prerouting priority filter; policy accept;
                counter packets 6 bytes 212 tcp option maxseg size set 1350 accept comment "bri-PRE-filter-10"
        }
...
}

Given the above, I have several open questions:

  1. What actually should do set interfaces bridge br0 ip adjust-mss command?
  2. VyOS 1.4 doesn't have set firewall bridge prerouting filter rule 10 set tcp-mss command. How should this work for this version of VyOS?
  3. During debugging I see that oifname "br0" does not work and it is possible to filter only by physical interface: oifname "eth0". If it is necessary to generate a rule for the bridge table, should we implement filtering in this way?

@o.kuchmystyi look slike we now have three places to clamp the MSS:

  1. set interfaces bridge br0 ip adjust-mss
  2. set firewall bridge prerouting filter rule 10 set tcp-mss
  3. set policy route foo rule 10 set tcp-mss

The 1st was an addition by me to overcome old limitations and iptables bugs for the implemention of number 3.

I would advise to change the generating code for nftables to detect if the interface is a bridge interface or not - and use the appropriate table to do so.

My opinion: the problem is not technical but rather lies in the documentation. Any attempts to change the behavior of set interfaces bridge br0 ip adjust-mss will result in losing important capabilities.

Most likely, the confusion arose because of:

  1. Lack of details about how operations with different families work in nftables and which nftables capabilities should be used in this context.
  2. Lack of relevant features in iptables—old habits from iptables may still lead users to assume something is wrong, even though nftables has already addressed many of iptables' limitations.

Explanation

Let’s take a bridge as an example:

bridge_mss.png (644×1 px, 55 KB)

In nftables, there is a clear delimitation between L2 and L3 layers and operations—a distinction that was missing in iptables. What is important, for ip/ip6/inet families, the outgoing interface for traffic is br1. However, for the bridge family (bridged traffic that never reaches the L3 decision layer), the outgoing interface is the physical interface name (e.g., eth2, eth5 in the example). This provides precise control.

The current command's behavior applies MSS adjustments at the L3 layer, targeting routed traffic that has passed the routing stage. This is consistent with how the command works for any other interface type in VyOS, and the behavior is clear and predictable.

For L2 operations, the bridge family must be used. This family was not available before and was specifically introduced and integrated into the CLI for such scenarios.

Consequences of Changing the Current Behavior

If we attempt to modify the command to also affect L2 traffic:

  1. There will be no way to apply MSS clamping to routed traffic (red path) without also affecting bridged traffic (purple/orange paths).
  2. There will be conflicting and confusing CLI configurations: set interfaces bridge ... vs. set firewall bridge ..., where the former would offer fewer capabilities and a worse understanding of what is actually happening (this case is a clear example).

Correct Approach

  • Bridged traffic: MSS clamping should be configured only via set firewall bridge ....
  • Routed traffic: The current method (set interfaces bridge ...) should remain unchanged, as it works correctly.
  • The real issue is documentation clarity.
  • While set firewall bridge ... set tcp-mss is not available in VyOS 1.4, this should not justify breaking a fully functional feature. Instead, we should either backport the missing functionality or clearly document that full support requires VyOS 1.5+.