From patchwork Sat Mar 20 22:34:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 406052 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 64327C433FB for ; Sat, 20 Mar 2021 22:37:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 45FDD61933 for ; Sat, 20 Mar 2021 22:37:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230159AbhCTWgS (ORCPT ); Sat, 20 Mar 2021 18:36:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44124 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230001AbhCTWfg (ORCPT ); Sat, 20 Mar 2021 18:35:36 -0400 Received: from mail-ej1-x62b.google.com (mail-ej1-x62b.google.com [IPv6:2a00:1450:4864:20::62b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D767AC061762; Sat, 20 Mar 2021 15:35:34 -0700 (PDT) Received: by mail-ej1-x62b.google.com with SMTP id hq27so15290994ejc.9; Sat, 20 Mar 2021 15:35:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=SoiJi9I8+4T7GzSieCrgTmk0ey5FdI/Q8mWfB1Ye++w=; b=UnW4cJHToksyV98Tyk1saDsRdTk2upOzwgjGjPSagA8F+cBmKTMBT315m9Lc93Mupr f91ZUIXknIOvlxpdIYzCRFqJps6oWl1/OSFAQP7lTEIhOHe7acuiUqv5L+tH/XHNA5Lk VB+mO2Xo48RZTmmIaiUsYak19WlumxKzaG9VfMTt+HBcZDoqmSxstyJsFmmwy4zMfz1L Gq08B4hAQ6K00FpWkrYRakavT65B332VERVZPjgqi7Abfap4ltpabjEN6unkN3NZFZ2J bBUDTookXurLZjYjDROcZPAM8QZR1BGRIF183beVq1Gb2RI//nSBCWIy01sB/C2bL+iQ mOcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=SoiJi9I8+4T7GzSieCrgTmk0ey5FdI/Q8mWfB1Ye++w=; b=NU+1tBcM7E92Y0bzVwbI45nlmyME8Bx/jsy8QTGzWwMmeFAU/bp4QP5CiHDrmF/VpT B945AOdTA85qMrrNHYJnF6Ilot2J8iuqFTUXwz2vOD4t1MM0wvk9njYKiMutwxdwuMSR sLQdKOZFiafFC2S3ks7nxHVei4WCoIEVFPlGucZPdm3LDezRCK0rsyZzNEXYKdp5a5so gfDpJus/x5n5waG3sgl1v6erbNUbxdSdv0MkF4OEiZomv+iZ73wMrIy6p6WsxcPVzhIw us3d+pYC6WkrEZrDCbiomkgg1agBEf2TEpp9UaOodvT9Ps8xg+NjigmuPBbzJFBHUlkR jeEA== X-Gm-Message-State: AOAM5300nOTe2Coj+eLcTh9JT8M41ti2DOuFnzFz8TjLFc81I1ldamJG kqZlRVmq8vH9PmvzmMAdq6Q= X-Google-Smtp-Source: ABdhPJz+0ZiFFy9XNFb1oGGwhYDjnkw39hzlLyf5EdDFjVQK9YRucWN4mcsc3ueFuPi4mQvf1dz1gQ== X-Received: by 2002:a17:906:7f01:: with SMTP id d1mr11913739ejr.136.1616279733638; Sat, 20 Mar 2021 15:35:33 -0700 (PDT) Received: from localhost.localdomain (5-12-16-165.residential.rdsnet.ro. [5.12.16.165]) by smtp.gmail.com with ESMTPSA id n2sm6090850ejl.1.2021.03.20.15.35.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 20 Mar 2021 15:35:33 -0700 (PDT) From: Vladimir Oltean To: Jakub Kicinski , "David S. Miller" Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Tobias Waldekranz , Claudiu Manoil , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Roopa Prabhu , Nikolay Aleksandrov , Jiri Pirko , Ido Schimmel , Alexandre Belloni , UNGLinuxDriver@microchip.com, Ivan Vecera , linux-omap@vger.kernel.org, Vladimir Oltean Subject: [PATCH v3 net-next 11/12] net: ocelot: call ocelot_netdevice_bridge_join when joining a bridged LAG Date: Sun, 21 Mar 2021 00:34:47 +0200 Message-Id: <20210320223448.2452869-12-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210320223448.2452869-1-olteanv@gmail.com> References: <20210320223448.2452869-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean Similar to the DSA situation, ocelot supports LAG offload but treats this scenario improperly: ip link add br0 type bridge ip link add bond0 type bond ip link set bond0 master br0 ip link set swp0 master bond0 We do the same thing as we do there, which is to simulate a 'bridge join' on 'lag join', if we detect that the bonding upper has a bridge upper. Again, same as DSA, ocelot supports software fallback for LAG, and in that case, we should avoid calling ocelot_netdevice_changeupper. Signed-off-by: Vladimir Oltean --- Changes in v3: None. drivers/net/ethernet/mscc/ocelot_net.c | 111 +++++++++++++++++++------ 1 file changed, 86 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index c08164cd88f4..d1376f7b34fd 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -1117,10 +1117,15 @@ static int ocelot_port_obj_del(struct net_device *dev, return ret; } -static int ocelot_netdevice_bridge_join(struct ocelot *ocelot, int port, - struct net_device *bridge) +static int ocelot_netdevice_bridge_join(struct net_device *dev, + struct net_device *bridge, + struct netlink_ext_ack *extack) { + struct ocelot_port_private *priv = netdev_priv(dev); + struct ocelot_port *ocelot_port = &priv->port; + struct ocelot *ocelot = ocelot_port->ocelot; struct switchdev_brport_flags flags; + int port = priv->chip_port; int err; flags.mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD; @@ -1135,10 +1140,14 @@ static int ocelot_netdevice_bridge_join(struct ocelot *ocelot, int port, return 0; } -static int ocelot_netdevice_bridge_leave(struct ocelot *ocelot, int port, +static int ocelot_netdevice_bridge_leave(struct net_device *dev, struct net_device *bridge) { + struct ocelot_port_private *priv = netdev_priv(dev); + struct ocelot_port *ocelot_port = &priv->port; + struct ocelot *ocelot = ocelot_port->ocelot; struct switchdev_brport_flags flags; + int port = priv->chip_port; int err; flags.mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD; @@ -1151,43 +1160,89 @@ static int ocelot_netdevice_bridge_leave(struct ocelot *ocelot, int port, return err; } -static int ocelot_netdevice_changeupper(struct net_device *dev, - struct netdev_notifier_changeupper_info *info) +static int ocelot_netdevice_lag_join(struct net_device *dev, + struct net_device *bond, + struct netdev_lag_upper_info *info, + struct netlink_ext_ack *extack) { struct ocelot_port_private *priv = netdev_priv(dev); struct ocelot_port *ocelot_port = &priv->port; struct ocelot *ocelot = ocelot_port->ocelot; + struct net_device *bridge_dev; int port = priv->chip_port; + int err; + + err = ocelot_port_lag_join(ocelot, port, bond, info); + if (err == -EOPNOTSUPP) { + NL_SET_ERR_MSG_MOD(extack, "Offloading not supported"); + return 0; + } + + bridge_dev = netdev_master_upper_dev_get(bond); + if (!bridge_dev || !netif_is_bridge_master(bridge_dev)) + return 0; + + err = ocelot_netdevice_bridge_join(dev, bridge_dev, extack); + if (err) + goto err_bridge_join; + + return 0; + +err_bridge_join: + ocelot_port_lag_leave(ocelot, port, bond); + return err; +} + +static int ocelot_netdevice_lag_leave(struct net_device *dev, + struct net_device *bond) +{ + struct ocelot_port_private *priv = netdev_priv(dev); + struct ocelot_port *ocelot_port = &priv->port; + struct ocelot *ocelot = ocelot_port->ocelot; + struct net_device *bridge_dev; + int port = priv->chip_port; + + ocelot_port_lag_leave(ocelot, port, bond); + + bridge_dev = netdev_master_upper_dev_get(bond); + if (!bridge_dev || !netif_is_bridge_master(bridge_dev)) + return 0; + + return ocelot_netdevice_bridge_leave(dev, bridge_dev); +} + +static int ocelot_netdevice_changeupper(struct net_device *dev, + struct netdev_notifier_changeupper_info *info) +{ + struct netlink_ext_ack *extack; int err = 0; + extack = netdev_notifier_info_to_extack(&info->info); + if (netif_is_bridge_master(info->upper_dev)) { - if (info->linking) { - err = ocelot_netdevice_bridge_join(ocelot, port, - info->upper_dev); - } else { - err = ocelot_netdevice_bridge_leave(ocelot, port, - info->upper_dev); - } + if (info->linking) + err = ocelot_netdevice_bridge_join(dev, info->upper_dev, + extack); + else + err = ocelot_netdevice_bridge_leave(dev, info->upper_dev); } if (netif_is_lag_master(info->upper_dev)) { - if (info->linking) { - err = ocelot_port_lag_join(ocelot, port, - info->upper_dev, - info->upper_info); - if (err == -EOPNOTSUPP) { - NL_SET_ERR_MSG_MOD(info->info.extack, - "Offloading not supported"); - err = 0; - } - } else { - ocelot_port_lag_leave(ocelot, port, - info->upper_dev); - } + if (info->linking) + err = ocelot_netdevice_lag_join(dev, info->upper_dev, + info->upper_info, extack); + else + ocelot_netdevice_lag_leave(dev, info->upper_dev); } return notifier_from_errno(err); } +/* Treat CHANGEUPPER events on an offloaded LAG as individual CHANGEUPPER + * events for the lower physical ports of the LAG. + * If the LAG upper isn't offloaded, ignore its CHANGEUPPER events. + * In case the LAG joined a bridge, notify that we are offloading it and can do + * forwarding in hardware towards it. + */ static int ocelot_netdevice_lag_changeupper(struct net_device *dev, struct netdev_notifier_changeupper_info *info) @@ -1197,6 +1252,12 @@ ocelot_netdevice_lag_changeupper(struct net_device *dev, int err = NOTIFY_DONE; netdev_for_each_lower_dev(dev, lower, iter) { + struct ocelot_port_private *priv = netdev_priv(lower); + struct ocelot_port *ocelot_port = &priv->port; + + if (ocelot_port->bond != dev) + return NOTIFY_OK; + err = ocelot_netdevice_changeupper(lower, info); if (err) return notifier_from_errno(err);