Page MenuHomeVyOS Platform

ethernet: disable-flow-control rejected on i40e/ice since T3871 flow-control denylist change — existing configs fail to load after upgrade
Open, HighPublicBUG

Description

Affected version

Rolling since vyos-1x commit 02471a8b8 ("ethtool: T3871: honor the unsupported-driver
denylist for flow-control too", 2026-08-06, part of PR #5350). The code is unchanged on
rolling HEAD as of 2026-11-11 (python/vyos/ethtool.py).

Seen on a self-built image from the rolling tree (2026.09.15), kernel 6.18.57,
Intel X710 (i40e out-of-tree driver 2.30.18, firmware 9.20 0x8000d8c5), bare metal.

Regression information

  • Last known working: VyOS 2026.03 (circinus, kernel 6.6.128). The same disable-flow-control config on the same X710 ports passed verification and committed cleanly for months.
  • First broken: any rolling build that contains 02471a8b8. (Builds between T4297, 2022, and T6083, 2024-03, behaved the same way; see Cause.)

Steps to reproduce

On any system with an i40e (or ice) port:

set interfaces ethernet eth0 disable-flow-control
commit
[ interfaces ethernet eth0 ]
Adapter does not support changing flow-control settings!

The driver supports changing pause parameters. On the same port, on the same image:

$ sudo ethtool -a eth0
Pause parameters for eth0:
Autonegotiate:    off
RX:        off
TX:        off

The driver accepts pause changes from ethtool -A (shown on an unused, unlinked X710 port):

$ sudo ethtool -A eth1 rx on tx on; echo "on rc=$?"
on rc=0
$ sudo ethtool -A eth1 rx off tx off; echo "off rc=$?"
off rc=0

The request reaches the driver's pause handler, which logs:

i40e 0000:02:00.1 eth1: Autoneg did not complete so changing settings may not res

(That port has no link, so the ethtool -a read-back stays off even after a 3
is what the driver message says. It shows the driver accepts and processes pause changes,
not the resulting state on a live link. Drivers that really can't change pause pa
return Operation not supported here, as in T3802.)

Before 02471a8b8, VyOS's own live probe (self._flow_control, from ethtool --json -a)
reported these ports as supporting flow control.

Impact on upgrade

A config that already has disable-flow-control on an i40e port fails verify()
boot config load. The whole interfaces ethernet ethX node is then missing from the running
config. Here that lost the hw-id, the offload settings and disable on an unus
the port came up admin-up. From the journal:

vyos-configd[1091]: Received message: {"type": "node", "last": false, "data": "VYlibexec/vyos/conf_mode/interfaces_ethernet.py"}
vyos-configd[1091]: [interfaces_ethernet] Adapter does not support changing flow-control settings!
vyos-configd[1091]: Sending reply: ERROR_COMMIT with output
vyos-configd[1091]: Received message: {"type": "node", "last": false, "data": "VYOS_TAGNODE_VALUE=eth1/usr/libexec/vyos/conf_mode/interfaces_ethernet.py"}
vyos-configd[1091]: [interfaces_ethernet] Adapter does not support changing flow-
vyos-configd[1091]: Sending reply: ERROR_COMMIT with output

The only way to get the config to load again is to delete disable-flow-control.
drivers that works only by accident: without the node, EthernetIf.update() requ
on, and set_flow_control() skips that only because the driver is on the lis
list is fixed later, pause frames get enabled on everyone who removed the node to work around
this.

Cause

02471a8b8 made Ethtool.check_flow_control() return False for every driver in
_drivers_without_speed_duplex_flow:

_drivers_without_speed_duplex_flow = ['vmxnet3', 'virtio_net', 'xen_netfront',
                                      'iavf', 'ice', 'i40e', 'hv_netvsc', 'veth', 'ixgbevf',
                                      'tun', 'vif']

History of i40e on that list:

  • 2022, T4297 / PR #1245 (rVYOSONEX2894b5245431): iavf, ice and i40e were added, and the list was applied to both speed/duplex and flow control. The task is about speed/duplex on ice/ia reporter added i40e because its README has the same speed/duplex limitation and wrote "I have tested ice, but i can't test i40e easily". The only "Operation not support pause in that task is from the iavf VF.
  • 2024, T6083 (rVYOSONEX5ee89f460966, JSON refactor): the list check was dropped from check_flow_control(), so i40e/ice fell back to the live probe and flow contro
  • 2026, 02471a8b8: the check was re-added for flow control, with virtio_net as the motivation.

So the flow-control entry for i40e/ice was never based on evidence about those drivers.
They are on the list only because they can't force link speed/duplex. As physical
drivers they implement .set_pauseparam (i40e_set_pauseparam(), ice_set_pauseparam()),
so flow control can be changed. The commit message targets paravirtualized driver
(virtio_net and similar), which can read pause parameters but not set them. For t
change is correct. The VF drivers (iavf, ixgbevf) are also correctly excluded.

Proposed fix

Give flow-control its own list and leave i40e and ice out of it:

_drivers_without_flow_control = ['vmxnet3', 'virtio_net', 'xen_netfront', 'hv_netvsc',
                                 'veth', 'tun', 'vif', 'iavf', 'ixgbevf']

def check_flow_control(self):
    if self.get_driver_name() in _drivers_without_flow_control:
        return False
    return bool(self._flow_control)

The live probe (self._flow_control) still applies to everything else, which was
behaviour before 02471a8b8. The paired smoketest change in the same commit would
same split.

Optional, in the spirit of T9228: where the driver can't change flow control, a warning in
verify_flow_control() instead of a ConfigError would make configs portable be
hardware and images instead of failing to load.

Note on compatibility: with this fix, i40e/ice ports that do NOT have disable-flow-control
set go back to VyOS's default of requesting pause on (autoneg/rx/tx on), as the
02471a8b8. Systems installed since then will see pause enabled on those ports after upgrading.

Details

Version
Rolling
Is it a breaking change?
Behavior change
Issue type
Bug (incorrect behavior)

Event Timeline

The task description above was truncated when I pasted it (the ends of long lines were cut off). I can't edit the description (edit policy), so here is the complete text. Please use this instead of the description.

Affected version

Rolling since vyos-1x commit 02471a8b8 ("ethtool: T3871: honor the unsupported-driver denylist for flow-control too", 2026-08-06, part of PR #5350). The code is unchanged on rolling HEAD as of 2026-11-11 (python/vyos/ethtool.py).

Seen on a self-built image from the rolling tree (2026.09.15), kernel 6.18.57, Intel X710 (i40e out-of-tree driver 2.30.18, firmware 9.20 0x8000d8c5), bare metal.

Regression information

  • Last known working: VyOS 2026.03 (circinus, kernel 6.6.128). The same disable-flow-control config on the same X710 ports passed verification and committed cleanly for months.
  • First broken: any rolling build that contains 02471a8b8. (Builds between T4297, 2022, and T6083, 2024-03, behaved the same way; see Cause.)

Steps to reproduce

On any system with an i40e (or ice) port:

set interfaces ethernet eth0 disable-flow-control
commit
[ interfaces ethernet eth0 ]
Adapter does not support changing flow-control settings!

The driver supports changing pause parameters. On the same port, on the same image:

$ sudo ethtool -a eth0
Pause parameters for eth0:
Autonegotiate:    off
RX:        off
TX:        off

The driver accepts pause changes from ethtool -A (shown on an unused, unlinked X710 port):

$ sudo ethtool -A eth1 rx on tx on; echo "on rc=$?"
on rc=0
$ sudo ethtool -A eth1 rx off tx off; echo "off rc=$?"
off rc=0

The request reaches the driver's pause handler, which logs:

i40e 0000:02:00.1 eth1: Autoneg did not complete so changing settings may not result in an actual change.

(That port has no link, so the ethtool -a read-back stays off even after a 3 s wait, which is what the driver message says. It shows the driver accepts and processes pause changes, not the resulting state on a live link. Drivers that really can't change pause parameters return Operation not supported here, as in T3802.)

Before 02471a8b8, VyOS's own live probe (self._flow_control, from ethtool --json -a) reported these ports as supporting flow control.

Impact on upgrade

A config that already has disable-flow-control on an i40e port fails verify() during the boot config load. The whole interfaces ethernet ethX node is then missing from the running config. Here that lost the hw-id, the offload settings and disable on an unused port, so the port came up admin-up. From the journal:

vyos-configd[1091]: Received message: {"type": "node", "last": false, "data": "VYOS_TAGNODE_VALUE=eth0/usr/libexec/vyos/conf_mode/interfaces_ethernet.py"}
vyos-configd[1091]: [interfaces_ethernet] Adapter does not support changing flow-control settings!
vyos-configd[1091]: Sending reply: ERROR_COMMIT with output
vyos-configd[1091]: Received message: {"type": "node", "last": false, "data": "VYOS_TAGNODE_VALUE=eth1/usr/libexec/vyos/conf_mode/interfaces_ethernet.py"}
vyos-configd[1091]: [interfaces_ethernet] Adapter does not support changing flow-control settings!
vyos-configd[1091]: Sending reply: ERROR_COMMIT with output

The only way to get the config to load again is to delete disable-flow-control. On these drivers that works only by accident: without the node, EthernetIf.update() requests pause on, and set_flow_control() skips that only because the driver is on the list. If the list is fixed later, pause frames get enabled on everyone who removed the node to work around this.

Cause

02471a8b8 made Ethtool.check_flow_control() return False for every driver in _drivers_without_speed_duplex_flow:

_drivers_without_speed_duplex_flow = ['vmxnet3', 'virtio_net', 'xen_netfront',
                                      'iavf', 'ice', 'i40e', 'hv_netvsc', 'veth', 'ixgbevf',
                                      'tun', 'vif']

History of i40e on that list:

  • 2022, T4297 / PR #1245 (rVYOSONEX2894b5245431): iavf, ice and i40e were added, and the list was applied to both speed/duplex and flow control. The task is about speed/duplex on ice/iavf. The reporter added i40e because its README has the same speed/duplex limitation and wrote "I have tested ice, but i can't test i40e easily". The only "Operation not supported" for pause in that task is from the iavf VF.
  • 2024, T6083 (rVYOSONEX5ee89f460966, JSON refactor): the list check was dropped from check_flow_control(), so i40e/ice fell back to the live probe and flow control worked.
  • 2026, 02471a8b8: the check was re-added for flow control, with virtio_net as the motivation.

So the flow-control entry for i40e/ice was never based on evidence about those drivers. They are on the list only because they can't force link speed/duplex. As physical-function drivers they implement .set_pauseparam (i40e_set_pauseparam(), ice_set_pauseparam()), so flow control can be changed. The commit message targets paravirtualized drivers (virtio_net and similar), which can read pause parameters but not set them. For those the change is correct. The VF drivers (iavf, ixgbevf) are also correctly excluded.

Proposed fix

Give flow-control its own list and leave i40e and ice out of it:

_drivers_without_flow_control = ['vmxnet3', 'virtio_net', 'xen_netfront', 'hv_netvsc',
                                 'veth', 'tun', 'vif', 'iavf', 'ixgbevf']

def check_flow_control(self):
    if self.get_driver_name() in _drivers_without_flow_control:
        return False
    return bool(self._flow_control)

The live probe (self._flow_control) still applies to everything else, which was the behaviour before 02471a8b8. The paired smoketest change in the same commit would need the same split.

Optional, in the spirit of T9228: where the driver can't change flow control, a warning in verify_flow_control() instead of a ConfigError would make configs portable between hardware and images instead of failing to load.

Note on compatibility: with this fix, i40e/ice ports that do NOT have disable-flow-control set go back to VyOS's default of requesting pause on (autoneg/rx/tx on), as they did before 02471a8b8. Systems installed since then will see pause enabled on those ports after upgrading.