From patchwork Thu Aug 25 09:28:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Casper Andersson X-Patchwork-Id: 12954426 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 043F4C04AA5 for ; Thu, 25 Aug 2022 09:29:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240221AbiHYJ3E (ORCPT ); Thu, 25 Aug 2022 05:29:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45086 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239801AbiHYJ2q (ORCPT ); Thu, 25 Aug 2022 05:28:46 -0400 Received: from mail-lf1-x12c.google.com (mail-lf1-x12c.google.com [IPv6:2a00:1450:4864:20::12c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E6DC1AA361 for ; Thu, 25 Aug 2022 02:28:41 -0700 (PDT) Received: by mail-lf1-x12c.google.com with SMTP id q7so23741473lfu.5 for ; Thu, 25 Aug 2022 02:28:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:organization:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc; bh=NFmp4r2urbPoTlr0LkARXhKrAhHH6AMgDgo8CtXnfZM=; b=o/cXCQ12PHnTt+UxltHztdLwkJ6jRPr84Yv/tHn24Ts8r4+CrE6Ohkqq8y1udOg6KU yAU9EypWnKL/eRi7q7U1un6TkIOXnqZK8H2JUgL75ziuCbbkQPf8NERlixHtUOsRHgvC xiNo0QK6hkGge84dsZi6reoBS+l1mI0m24p1PCjv2Z9DRGbj3qTb/ptusy1IGG9Mb6Od wbWz1NzSXPZMdrIJM6TdvGYc84I/Imm9L2u1jLuE3QVAn04xhiz3JBz5PWHNNQ43TZdd 1tzwN5Ns9QyxaijyJqfI5iyOzvyUHs8z62tfeTB9DrHzCNvCmRLdxrOzlZHuKaab34Lt zERA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:organization:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-message-state :from:to:cc; bh=NFmp4r2urbPoTlr0LkARXhKrAhHH6AMgDgo8CtXnfZM=; b=X8t4+H5vPrLHJ921x4NP5hdkjKdPeh7IFvLiK6uF4iLW1MHvgzKCk7t66vqO8xPuQf f/TBcSm8Joctbz5yEqj1mC3G841r1PsHhWe+dt8xZF/1J8OcC11XS/wa69hsFbUmQpZ9 /7XZm42Mni+m3Xq5DxsmRAZk07/l9ZrcIR/FXjMr6/b46LupSnb8CMQp39733kkfNNZp 2m2dqiFNTWoTFlQrFpa6blVs+jUeLmi58vVfDOu5K8wSfSXXmFoKyWuTkDlSO1Lu31Tt x+EHOEx5bKQiMxMVezC5BJEx3900aJzm8nHY+GEpZkpBL7VZ6WRjWM6zeUQtt+pZRzFj z6TQ== X-Gm-Message-State: ACgBeo02WIdydlbkcXef28VJq2cjMLoVrWyIVkIU8htZ0BwR1QqBbgUv XaymxKNq5bzTmMce9KBX/EQ= X-Google-Smtp-Source: AA6agR7QdkyIJTDLquJis+XO37O0MxVOiRVPs7SSGVbpPP3nTOiC/t4kfE2EiETSYA0GkimQ65duAg== X-Received: by 2002:a05:6512:31d0:b0:492:fe2e:7695 with SMTP id j16-20020a05651231d000b00492fe2e7695mr974847lfe.392.1661419720335; Thu, 25 Aug 2022 02:28:40 -0700 (PDT) Received: from wse-c0155.labs.westermo.se (static-193-12-47-89.cust.tele2.se. [193.12.47.89]) by smtp.gmail.com with ESMTPSA id g16-20020a19e050000000b00492c4d2fcbfsm398988lfj.115.2022.08.25.02.28.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Aug 2022 02:28:39 -0700 (PDT) From: Casper Andersson To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , netdev@vger.kernel.org Cc: Horatiu Vultur , Lars Povlsen , Steen Hegelund , UNGLinuxDriver@microchip.com Subject: [PATCH v2 net-next 1/3] ethernet: Add helpers to recognize addresses mapped to IP multicast Date: Thu, 25 Aug 2022 11:28:35 +0200 Message-Id: <20220825092837.907135-2-casper.casan@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220825092837.907135-1-casper.casan@gmail.com> References: <20220825092837.907135-1-casper.casan@gmail.com> MIME-Version: 1.0 Organization: Westermo Network Technologies AB Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org IP multicast must sometimes be discriminated from non-IP multicast, e.g. when determining the forwarding behavior of a given group in the presence of multicast router ports on an offloaded bridge. Therefore, provide helpers to identify these groups. Signed-off-by: Casper Andersson --- include/linux/etherdevice.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h index 92b10e67d5f8..a541f0c4f146 100644 --- a/include/linux/etherdevice.h +++ b/include/linux/etherdevice.h @@ -428,6 +428,28 @@ static inline bool ether_addr_equal_masked(const u8 *addr1, const u8 *addr2, return true; } +static inline bool ether_addr_is_ipv4_mcast(const u8 *addr) +{ + u8 base[ETH_ALEN] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; + u8 mask[ETH_ALEN] = { 0xff, 0xff, 0xff, 0x80, 0x00, 0x00 }; + + return ether_addr_equal_masked(addr, base, mask); +} + +static inline bool ether_addr_is_ipv6_mcast(const u8 *addr) +{ + u8 base[ETH_ALEN] = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 }; + u8 mask[ETH_ALEN] = { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }; + + return ether_addr_equal_masked(addr, base, mask); +} + +static inline bool ether_addr_is_ip_mcast(const u8 *addr) +{ + return ether_addr_is_ipv4_mcast(addr) || + ether_addr_is_ipv6_mcast(addr); +} + /** * ether_addr_to_u64 - Convert an Ethernet address into a u64 value. * @addr: Pointer to a six-byte array containing the Ethernet address From patchwork Thu Aug 25 09:28:36 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Casper Andersson X-Patchwork-Id: 12954427 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E1CD1C48BE4 for ; Thu, 25 Aug 2022 09:29:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235913AbiHYJ3F (ORCPT ); Thu, 25 Aug 2022 05:29:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45614 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240068AbiHYJ2q (ORCPT ); Thu, 25 Aug 2022 05:28:46 -0400 Received: from mail-lf1-x130.google.com (mail-lf1-x130.google.com [IPv6:2a00:1450:4864:20::130]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DFEA2AA370 for ; Thu, 25 Aug 2022 02:28:42 -0700 (PDT) Received: by mail-lf1-x130.google.com with SMTP id d23so23076980lfl.13 for ; Thu, 25 Aug 2022 02:28:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:organization:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc; bh=VNCCWBMwvLFZzxjsGLm4WFqKbVU6NGifOL7Tkg8Cizk=; b=KrFvcZj8Y6goA/MV42jMiHNpjG8e7taqsQwuQRs+M1ljt+PdRDB4C0j+u6Vxt/QM97 HgTLb4i9JZ+7MOIqQ41Zv8flkpQuaQObZdG0sF2f/YeYKvKAe1yXJa9VDjYRZyJvasLK 2UoYaVF7jGwf40rTojy8ojomiJTGy8MzZJhlYN5I8hJWa/84UL6CzPWiS2vpmlzzBuMn SxFGHbZA4lYX9HRkGK+fLFnisMUOY1XtskxvBxrugQOnL71CqelkSsOObleQ/KnKaqQg hBAPa4+HxXWA+TkKnITe72GqKzpLDN1MSWqPG9N6mBxRWNDHXFQQmw4KFh1HpdcHBXDk htkA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:organization:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-message-state :from:to:cc; bh=VNCCWBMwvLFZzxjsGLm4WFqKbVU6NGifOL7Tkg8Cizk=; b=I2mCwGh0VBWgTl3ykiqoBRCx+nfHCgFZtIGKl3YR5OtRHlTAZFiWXsN0ymMFYS7XPx iQbiEtQ2UbwTUtXDfxLIwYnqo+jzZzf5116I+Gn/Xj0tjxRyaGosouY3GD4T4Gqm6l/s IdSlp2mXn+CvjSVb24YGvZoDkTlwXWsCCSDQWdROtLvOOwoVXDenw1K4vnV1ulEwR3c3 x0e8eC2VR4qPb5qYryUIyDh5tTeMImBmLxWXzMNRm08oh+Bw2k+W/iU56eyzlYswQ2KA +hT0jvmAo6VyOBvINa1CEpS58LeR5qFcIyZCqtpsAlmXVWSFoEtf3ZcK3ZKyf2BRTezn /egg== X-Gm-Message-State: ACgBeo28oeyFFjdQQ2qQrbj884D8oQo+sMVVt4XAGKFEMEJku7siEony 3icJjR3w3cOkKHS6Um2FxXc= X-Google-Smtp-Source: AA6agR73P8cJ0NHFEo63uQ5SnL0XZGJQU9YztqXIJkljV4h6BGzMY4WeCf9tpXBmTHMl36caHy3Ryw== X-Received: by 2002:a05:6512:4025:b0:492:c165:ab3b with SMTP id br37-20020a056512402500b00492c165ab3bmr939195lfb.235.1661419721264; Thu, 25 Aug 2022 02:28:41 -0700 (PDT) Received: from wse-c0155.labs.westermo.se (static-193-12-47-89.cust.tele2.se. [193.12.47.89]) by smtp.gmail.com with ESMTPSA id g16-20020a19e050000000b00492c4d2fcbfsm398988lfj.115.2022.08.25.02.28.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Aug 2022 02:28:40 -0700 (PDT) From: Casper Andersson To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , netdev@vger.kernel.org Cc: Horatiu Vultur , Lars Povlsen , Steen Hegelund , UNGLinuxDriver@microchip.com Subject: [PATCH v2 net-next 2/3] net: sparx5: add list for mdb entries in driver Date: Thu, 25 Aug 2022 11:28:36 +0200 Message-Id: <20220825092837.907135-3-casper.casan@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220825092837.907135-1-casper.casan@gmail.com> References: <20220825092837.907135-1-casper.casan@gmail.com> MIME-Version: 1.0 Organization: Westermo Network Technologies AB Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Keep track of all mdb entries in software for easy access. Signed-off-by: Casper Andersson --- .../ethernet/microchip/sparx5/sparx5_main.c | 3 + .../ethernet/microchip/sparx5/sparx5_main.h | 13 ++ .../microchip/sparx5/sparx5_switchdev.c | 198 ++++++++++-------- 3 files changed, 132 insertions(+), 82 deletions(-) diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c index 01be7bd84181..ad598cf8ef44 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c @@ -661,6 +661,9 @@ static int sparx5_start(struct sparx5 *sparx5) queue_delayed_work(sparx5->mact_queue, &sparx5->mact_work, SPX5_MACT_PULL_DELAY); + mutex_init(&sparx5->mdb_lock); + INIT_LIST_HEAD(&sparx5->mdb_entries); + err = sparx5_register_netdevs(sparx5); if (err) return err; diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h index b197129044b5..3d9e3585eb28 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h @@ -215,6 +215,15 @@ struct sparx5_skb_cb { unsigned long jiffies; }; +struct sparx5_mdb_entry { + struct list_head list; + DECLARE_BITMAP(port_mask, SPX5_PORTS); + unsigned char addr[ETH_ALEN]; + bool cpu_copy; + u16 vid; + u16 pgid_idx; +}; + #define SPARX5_PTP_TIMEOUT msecs_to_jiffies(10) #define SPARX5_SKB_CB(skb) \ ((struct sparx5_skb_cb *)((skb)->cb)) @@ -256,6 +265,10 @@ struct sparx5 { struct list_head mact_entries; /* mac table list (mact_entries) mutex */ struct mutex mact_lock; + /* SW MDB table */ + struct list_head mdb_entries; + /* mdb list mutex */ + struct mutex mdb_lock; struct delayed_work mact_work; struct workqueue_struct *mact_queue; /* Board specifics */ diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c b/drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c index ec07f7d0528c..8ac71de9e935 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c @@ -386,16 +386,95 @@ static int sparx5_handle_port_vlan_add(struct net_device *dev, v->flags & BRIDGE_VLAN_INFO_UNTAGGED); } +static int sparx5_alloc_mdb_entry(struct sparx5 *sparx5, + const unsigned char *addr, + u16 vid, + struct sparx5_mdb_entry **entry_out) +{ + struct sparx5_mdb_entry *entry; + u16 pgid_idx; + int err; + + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + + err = sparx5_pgid_alloc_mcast(sparx5, &pgid_idx); + if (err) { + kfree(entry); + return err; + } + + memcpy(entry->addr, addr, ETH_ALEN); + entry->vid = vid; + entry->pgid_idx = pgid_idx; + + mutex_lock(&sparx5->mdb_lock); + list_add_tail(&entry->list, &sparx5->mdb_entries); + mutex_unlock(&sparx5->mdb_lock); + + *entry_out = entry; + return 0; +} + +static void sparx5_free_mdb_entry(struct sparx5 *sparx5, + const unsigned char *addr, + u16 vid) +{ + struct sparx5_mdb_entry *entry, *tmp; + + mutex_lock(&sparx5->mdb_lock); + list_for_each_entry_safe(entry, tmp, &sparx5->mdb_entries, list) { + if ((vid == 0 || entry->vid == vid) && + ether_addr_equal(addr, entry->addr)) { + list_del(&entry->list); + + sparx5_pgid_free(sparx5, entry->pgid_idx); + kfree(entry); + goto out; + } + } + +out: + mutex_unlock(&sparx5->mdb_lock); +} + +static struct sparx5_mdb_entry *sparx5_mdb_get_entry(struct sparx5 *sparx5, + const unsigned char *addr, + u16 vid) +{ + struct sparx5_mdb_entry *e, *found = NULL; + + mutex_lock(&sparx5->mdb_lock); + list_for_each_entry(e, &sparx5->mdb_entries, list) { + if (ether_addr_equal(e->addr, addr) && e->vid == vid) { + found = e; + goto out; + } + } + +out: + mutex_unlock(&sparx5->mdb_lock); + return found; +} + +static void sparx5_cpu_copy_ena(struct sparx5 *spx5, u16 pgid, bool enable) +{ + spx5_rmw(ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA_SET(enable), + ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA, spx5, + ANA_AC_PGID_MISC_CFG(pgid)); +} + static int sparx5_handle_port_mdb_add(struct net_device *dev, struct notifier_block *nb, const struct switchdev_obj_port_mdb *v) { struct sparx5_port *port = netdev_priv(dev); struct sparx5 *spx5 = port->sparx5; - u16 pgid_idx, vid; - u32 mact_entry; + struct sparx5_mdb_entry *entry; bool is_host; - int res, err; + int err; + u16 vid; if (!sparx5_netdevice_check(dev)) return -EOPNOTSUPP; @@ -410,66 +489,25 @@ static int sparx5_handle_port_mdb_add(struct net_device *dev, else vid = v->vid; - res = sparx5_mact_find(spx5, v->addr, vid, &mact_entry); - - if (res == 0) { - pgid_idx = LRN_MAC_ACCESS_CFG_2_MAC_ENTRY_ADDR_GET(mact_entry); - - /* MC_IDX starts after the port masks in the PGID table */ - pgid_idx += SPX5_PORTS; - - if (is_host) - spx5_rmw(ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA_SET(1), - ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA, spx5, - ANA_AC_PGID_MISC_CFG(pgid_idx)); - else - sparx5_pgid_update_mask(port, pgid_idx, true); - - } else { - err = sparx5_pgid_alloc_mcast(spx5, &pgid_idx); - if (err) { - netdev_warn(dev, "multicast pgid table full\n"); + entry = sparx5_mdb_get_entry(spx5, v->addr, vid); + if (!entry) { + err = sparx5_alloc_mdb_entry(spx5, v->addr, vid, &entry); + if (err) return err; - } - - if (is_host) - spx5_rmw(ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA_SET(1), - ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA, spx5, - ANA_AC_PGID_MISC_CFG(pgid_idx)); - else - sparx5_pgid_update_mask(port, pgid_idx, true); - - err = sparx5_mact_learn(spx5, pgid_idx, v->addr, vid); - - if (err) { - netdev_warn(dev, "could not learn mac address %pM\n", v->addr); - sparx5_pgid_free(spx5, pgid_idx); - sparx5_pgid_update_mask(port, pgid_idx, false); - return err; - } } - return 0; -} + mutex_lock(&spx5->mdb_lock); + if (is_host && !entry->cpu_copy) { + sparx5_cpu_copy_ena(spx5, entry->pgid_idx, true); + entry->cpu_copy = true; + } else if (!is_host) { + sparx5_pgid_update_mask(port, entry->pgid_idx, true); + set_bit(port->portno, entry->port_mask); + } + mutex_unlock(&spx5->mdb_lock); -static int sparx5_mdb_del_entry(struct net_device *dev, - struct sparx5 *spx5, - const unsigned char mac[ETH_ALEN], - const u16 vid, - u16 pgid_idx) -{ - int err; + sparx5_mact_learn(spx5, entry->pgid_idx, entry->addr, entry->vid); - err = sparx5_mact_forget(spx5, mac, vid); - if (err) { - netdev_warn(dev, "could not forget mac address %pM", mac); - return err; - } - err = sparx5_pgid_free(spx5, pgid_idx); - if (err) { - netdev_err(dev, "attempted to free already freed pgid\n"); - return err; - } return 0; } @@ -479,42 +517,38 @@ static int sparx5_handle_port_mdb_del(struct net_device *dev, { struct sparx5_port *port = netdev_priv(dev); struct sparx5 *spx5 = port->sparx5; - u16 pgid_idx, vid; - u32 mact_entry, res, pgid_entry[3], misc_cfg; - bool host_ena; + struct sparx5_mdb_entry *entry; + bool is_host; + u16 vid; if (!sparx5_netdevice_check(dev)) return -EOPNOTSUPP; + is_host = netif_is_bridge_master(v->obj.orig_dev); + if (!br_vlan_enabled(spx5->hw_bridge_dev)) vid = 1; else vid = v->vid; - res = sparx5_mact_find(spx5, v->addr, vid, &mact_entry); - - if (res == 0) { - pgid_idx = LRN_MAC_ACCESS_CFG_2_MAC_ENTRY_ADDR_GET(mact_entry); - - /* MC_IDX starts after the port masks in the PGID table */ - pgid_idx += SPX5_PORTS; - - if (netif_is_bridge_master(v->obj.orig_dev)) - spx5_rmw(ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA_SET(0), - ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA, spx5, - ANA_AC_PGID_MISC_CFG(pgid_idx)); - else - sparx5_pgid_update_mask(port, pgid_idx, false); - - misc_cfg = spx5_rd(spx5, ANA_AC_PGID_MISC_CFG(pgid_idx)); - host_ena = ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA_GET(misc_cfg); + entry = sparx5_mdb_get_entry(spx5, v->addr, vid); + if (!entry) + return 0; - sparx5_pgid_read_mask(spx5, pgid_idx, pgid_entry); - if (bitmap_empty((unsigned long *)pgid_entry, SPX5_PORTS) && !host_ena) - /* No ports or CPU are in MC group. Remove entry */ - return sparx5_mdb_del_entry(dev, spx5, v->addr, vid, pgid_idx); + mutex_lock(&spx5->mdb_lock); + if (is_host && entry->cpu_copy) { + sparx5_cpu_copy_ena(spx5, entry->pgid_idx, false); + entry->cpu_copy = false; + } else if (!is_host) { + clear_bit(port->portno, entry->port_mask); + sparx5_pgid_update_mask(port, entry->pgid_idx, false); } + mutex_unlock(&spx5->mdb_lock); + if (bitmap_empty(entry->port_mask, SPX5_PORTS) && !entry->cpu_copy) { + sparx5_mact_forget(spx5, entry->addr, entry->vid); + sparx5_free_mdb_entry(spx5, entry->addr, entry->vid); + } return 0; } From patchwork Thu Aug 25 09:28:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Casper Andersson X-Patchwork-Id: 12954428 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 435D2C28D13 for ; Thu, 25 Aug 2022 09:29:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240178AbiHYJ3H (ORCPT ); Thu, 25 Aug 2022 05:29:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45148 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239893AbiHYJ2r (ORCPT ); Thu, 25 Aug 2022 05:28:47 -0400 Received: from mail-lf1-x134.google.com (mail-lf1-x134.google.com [IPv6:2a00:1450:4864:20::134]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D4E39AA372 for ; Thu, 25 Aug 2022 02:28:43 -0700 (PDT) Received: by mail-lf1-x134.google.com with SMTP id q7so23741584lfu.5 for ; Thu, 25 Aug 2022 02:28:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:organization:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc; bh=oLL5EE4PiVh386UoKN/+HUxfcqfPponYSa1KW1LNAxs=; b=Pbas46L2ob/LRk6G9hYsdob8WvskxAUJSs4eYhLMW2ioOnB8nmdKl+qIuNxG3QfNMX KOkOosPVufO3Xdgrn1WCxcQndCi5mYzF5po6ncd8BHz8vEbCd8KDtEweRVrGzHkrh39x EyLStDVIX8Db4v67cFEm/f0sdsTpXY/fd16iV95tFUyfbX7RzAKAvgntsQFZXDYAfPLD koodHnpZjJAmxMjid8Z0w5ESrpvgUBvWH4+hC60bDt2yfkbLfaU6bEhUTsR/6xHH4TTR /LnD1qLgBUnQ+GAeiXQ4pL2haNFd73ONe+oPwpoV/65FwOK/Ii4DnXEhCJLCTkzIdB0l +WSQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:organization:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-message-state :from:to:cc; bh=oLL5EE4PiVh386UoKN/+HUxfcqfPponYSa1KW1LNAxs=; b=Y0bAJHZciZI/0RajO8vxpLOt8YEi7oE+ZeSHc0p+NrKN8WM0qrIIs0qADBBsTNXSBT aaNcCmmyBcqtIVf4n4aokokA1K97qc3AWREvYg7m0rWGGuhsVMCO3OtR1c3yj6UDMXcS 6Dzf8UCg0CrFjRfgEuLylxjH1hcyt6USYTzsHe/IIiKHKGISgXfNxO7upfmd8PojnNKH YvaCkEZYRtRREyhj5H4i4KKQdEHbnjkT8iAgf67gwOwvZYw1tjOVE5QAnDRc660Eqxa0 djBwRzPWAroHrbooevVNKDv8YdGHwEQb23HYYnCxIxmmVPG94f6kqHCe15uMVPsndDjl l2jA== X-Gm-Message-State: ACgBeo3ghs3+/eTWKuDUWM85qBQ5/el2a40XrFdZoI9MoF2oMVn8j/7D wB1e1Yqd4NolniL+/hnZXL8= X-Google-Smtp-Source: AA6agR7Zcftg+kX07BTs0a2C1EFfeCEYavwcxCD/EhAlVuIMxsK3QNhsML42mfr26LrpElKpmc6umQ== X-Received: by 2002:a05:6512:ba8:b0:492:e5e5:b0ea with SMTP id b40-20020a0565120ba800b00492e5e5b0eamr971289lfv.555.1661419722218; Thu, 25 Aug 2022 02:28:42 -0700 (PDT) Received: from wse-c0155.labs.westermo.se (static-193-12-47-89.cust.tele2.se. [193.12.47.89]) by smtp.gmail.com with ESMTPSA id g16-20020a19e050000000b00492c4d2fcbfsm398988lfj.115.2022.08.25.02.28.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Aug 2022 02:28:41 -0700 (PDT) From: Casper Andersson To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , netdev@vger.kernel.org Cc: Horatiu Vultur , Lars Povlsen , Steen Hegelund , UNGLinuxDriver@microchip.com Subject: [PATCH v2 net-next 3/3] net: sparx5: add support for mrouter ports Date: Thu, 25 Aug 2022 11:28:37 +0200 Message-Id: <20220825092837.907135-4-casper.casan@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220825092837.907135-1-casper.casan@gmail.com> References: <20220825092837.907135-1-casper.casan@gmail.com> MIME-Version: 1.0 Organization: Westermo Network Technologies AB Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org All multicast should be forwarded to mrouter ports. Mrouter ports must therefore be part of all active multicast groups, and override flooding from being disabled. Signed-off-by: Casper Andersson --- .../ethernet/microchip/sparx5/sparx5_main.c | 1 + .../ethernet/microchip/sparx5/sparx5_main.h | 2 + .../microchip/sparx5/sparx5_switchdev.c | 77 +++++++++++++++++-- .../ethernet/microchip/sparx5/sparx5_vlan.c | 7 ++ 4 files changed, 80 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c index ad598cf8ef44..bbe41734360e 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c @@ -277,6 +277,7 @@ static int sparx5_create_port(struct sparx5 *sparx5, spx5_port->custom_etype = 0x8880; /* Vitesse */ spx5_port->phylink_pcs.poll = true; spx5_port->phylink_pcs.ops = &sparx5_phylink_pcs_ops; + spx5_port->is_mrouter = false; sparx5->ports[config->portno] = spx5_port; err = sparx5_port_init(sparx5, spx5_port, &config->conf); diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h index 3d9e3585eb28..9b4395b7a9e4 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h @@ -190,6 +190,7 @@ struct sparx5_port { u8 ptp_cmd; u16 ts_id; struct sk_buff_head tx_skbs; + bool is_mrouter; }; enum sparx5_core_clockfreq { @@ -338,6 +339,7 @@ void sparx5_mact_init(struct sparx5 *sparx5); /* sparx5_vlan.c */ void sparx5_pgid_update_mask(struct sparx5_port *port, int pgid, bool enable); +void sparx5_pgid_clear(struct sparx5 *spx5, int pgid); void sparx5_pgid_read_mask(struct sparx5 *sparx5, int pgid, u32 portmask[3]); void sparx5_update_fwd(struct sparx5 *sparx5); void sparx5_vlan_init(struct sparx5 *sparx5); diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c b/drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c index 8ac71de9e935..4af85d108a06 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c @@ -29,14 +29,23 @@ static int sparx5_port_attr_pre_bridge_flags(struct sparx5_port *port, return 0; } +static void sparx5_port_update_mcast_ip_flood(struct sparx5_port *port, bool flood_flag) +{ + bool should_flood = flood_flag || port->is_mrouter; + int pgid; + + for (pgid = PGID_IPV4_MC_DATA; pgid <= PGID_IPV6_MC_CTRL; pgid++) + sparx5_pgid_update_mask(port, pgid, should_flood); +} + static void sparx5_port_attr_bridge_flags(struct sparx5_port *port, struct switchdev_brport_flags flags) { - int pgid; + if (flags.mask & BR_MCAST_FLOOD) { + sparx5_pgid_update_mask(port, PGID_MC_FLOOD, !!(flags.val & BR_MCAST_FLOOD)); + sparx5_port_update_mcast_ip_flood(port, !!(flags.val & BR_MCAST_FLOOD)); + } - if (flags.mask & BR_MCAST_FLOOD) - for (pgid = PGID_MC_FLOOD; pgid <= PGID_IPV6_MC_CTRL; pgid++) - sparx5_pgid_update_mask(port, pgid, !!(flags.val & BR_MCAST_FLOOD)); if (flags.mask & BR_FLOOD) sparx5_pgid_update_mask(port, PGID_UC_FLOOD, !!(flags.val & BR_FLOOD)); if (flags.mask & BR_BCAST_FLOOD) @@ -82,6 +91,37 @@ static void sparx5_port_attr_ageing_set(struct sparx5_port *port, sparx5_set_ageing(port->sparx5, ageing_time); } +static void sparx5_port_attr_mrouter_set(struct sparx5_port *port, + struct net_device *orig_dev, + bool enable) +{ + struct sparx5 *sparx5 = port->sparx5; + struct sparx5_mdb_entry *e; + bool flood_flag; + + if ((enable && port->is_mrouter) || (!enable && !port->is_mrouter)) + return; + + /* Add/del mrouter port on all active mdb entries in HW. + * Don't change entry port mask, since that represents + * ports that actually joined that group. + */ + mutex_lock(&sparx5->mdb_lock); + list_for_each_entry(e, &sparx5->mdb_entries, list) { + if (!test_bit(port->portno, e->port_mask) && + ether_addr_is_ip_mcast(e->addr)) + sparx5_pgid_update_mask(port, e->pgid_idx, enable); + } + mutex_unlock(&sparx5->mdb_lock); + + /* Enable/disable flooding depending on if port is mrouter port + * or if mcast flood is enabled. + */ + port->is_mrouter = enable; + flood_flag = br_port_flag_is_set(port->ndev, BR_MCAST_FLOOD); + sparx5_port_update_mcast_ip_flood(port, flood_flag); +} + static int sparx5_port_attr_set(struct net_device *dev, const void *ctx, const struct switchdev_attr *attr, struct netlink_ext_ack *extack) @@ -110,6 +150,11 @@ static int sparx5_port_attr_set(struct net_device *dev, const void *ctx, port->vlan_aware = attr->u.vlan_filtering; sparx5_vlan_port_apply(port->sparx5, port); break; + case SWITCHDEV_ATTR_ID_PORT_MROUTER: + sparx5_port_attr_mrouter_set(port, + attr->orig_dev, + attr->u.mrouter); + break; default: return -EOPNOTSUPP; } @@ -472,8 +517,8 @@ static int sparx5_handle_port_mdb_add(struct net_device *dev, struct sparx5_port *port = netdev_priv(dev); struct sparx5 *spx5 = port->sparx5; struct sparx5_mdb_entry *entry; - bool is_host; - int err; + bool is_host, is_new; + int err, i; u16 vid; if (!sparx5_netdevice_check(dev)) @@ -489,14 +534,25 @@ static int sparx5_handle_port_mdb_add(struct net_device *dev, else vid = v->vid; + is_new = false; entry = sparx5_mdb_get_entry(spx5, v->addr, vid); if (!entry) { err = sparx5_alloc_mdb_entry(spx5, v->addr, vid, &entry); + is_new = true; if (err) return err; } mutex_lock(&spx5->mdb_lock); + + /* Add any mrouter ports to the new entry */ + if (is_new && ether_addr_is_ip_mcast(v->addr)) + for (i = 0; i < SPX5_PORTS; i++) + if (spx5->ports[i] && spx5->ports[i]->is_mrouter) + sparx5_pgid_update_mask(spx5->ports[i], + entry->pgid_idx, + true); + if (is_host && !entry->cpu_copy) { sparx5_cpu_copy_ena(spx5, entry->pgid_idx, true); entry->cpu_copy = true; @@ -541,11 +597,18 @@ static int sparx5_handle_port_mdb_del(struct net_device *dev, entry->cpu_copy = false; } else if (!is_host) { clear_bit(port->portno, entry->port_mask); - sparx5_pgid_update_mask(port, entry->pgid_idx, false); + + /* Port not mrouter port or addr is L2 mcast, remove port from mask. */ + if (!port->is_mrouter || !ether_addr_is_ip_mcast(v->addr)) + sparx5_pgid_update_mask(port, entry->pgid_idx, false); } mutex_unlock(&spx5->mdb_lock); if (bitmap_empty(entry->port_mask, SPX5_PORTS) && !entry->cpu_copy) { + /* Clear pgid in case mrouter ports exists + * that are not part of the group. + */ + sparx5_pgid_clear(spx5, entry->pgid_idx); sparx5_mact_forget(spx5, entry->addr, entry->vid); sparx5_free_mdb_entry(spx5, entry->addr, entry->vid); } diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c b/drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c index 37e4ac965849..34f954bbf815 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c @@ -138,6 +138,13 @@ void sparx5_pgid_update_mask(struct sparx5_port *port, int pgid, bool enable) } } +void sparx5_pgid_clear(struct sparx5 *spx5, int pgid) +{ + spx5_wr(0, spx5, ANA_AC_PGID_CFG(pgid)); + spx5_wr(0, spx5, ANA_AC_PGID_CFG1(pgid)); + spx5_wr(0, spx5, ANA_AC_PGID_CFG2(pgid)); +} + void sparx5_pgid_read_mask(struct sparx5 *spx5, int pgid, u32 portmask[3]) { portmask[0] = spx5_rd(spx5, ANA_AC_PGID_CFG(pgid));