On 2018-12-22 8:29 p.m., Robert Hancock wrote:
I have a device using a KSZ9897 switch
(CONFIG_MICROCHIP_KSZ_SPI_DRIVER=y) using a 4.19.9 kernel, where I am
trying to enable a bridge on some of the ports using systemd-networkd.
However, it seems to be getting an error when it tries to configure the
ports to be part of the bridge. systemd-networkd complains with:

lan1: Set link
lan1: Could not join netdev: Operation not supported
lan1: Failed

and the kernel complains:

lan: bridge flag offload is not supported 4(lan1)

That message is coming from br_switchdev_set_port_flag in
net/bridge/br_switchdev.c. Adding some more output to that statement
tells me:

lan: bridge flag offload is not supported, flags 18656 mask 64 support
0, 4(lan1)

which appears to mean something is trying to enable BR_BCAST_FLOOD,
BR_MCAST_FLOOD, BR_PROMISC, BR_FLOOD, BR_LEARNING on the port, but it is
failing to enable BR_FLOOD because brport_flags_support is 0. I am just
using the default bridge settings in systemd-networkd, so that is
nothing that I am specifying explicitly.

However, if I look at brctl, it appears that the devices have in fact
been added to the bridge, but obviously systemd-networkd still treats
this as a failure.

I'm not sure what that means.. is this a kernel problem?
systemd-networkd problem? Are we somehow trying to do something
unsupported on this hardware? Any advice would be appreciated.


Looking at this a bit further, it seems like the problem is in the code in net/bridge/br_switchdev.c around where the message is printed:

    err = switchdev_port_attr_get(p->dev, &attr);
    if (err == -EOPNOTSUPP)
        return 0;
    if (err)
        return err;

    /* Check if specific bridge flag attribute offload is supported */
    if (!(attr.u.brport_flags_support & mask)) {
        br_warn(p->br, "bridge flag offload is not supported %u(%s)\n",
            (unsigned int)p->port_no, p->dev->name);
        return -EOPNOTSUPP;
    }

If the port doesn't support the switchdev_port_attr_get operation at all, we just ignore it and return 0. However, if it does support that operation (as DSA does), but doesn't have the particular bridge flag supported in brport_flags_support (which it won't here, since brport_flags_support is always set to 0 for DSA), we complain and return -EOPNOTSUPP. That return value propagates all the way back to userspace and fails the entire netlink operation that it was trying to do, causing systemd-networkd to fail the bridge startup.

Shouldn't this code just be returning 0 in this case?

Reply via email to