--- zzzz-none-000/linux-5.15.111/net/bridge/br_fdb.c 2023-05-11 14:00:40.000000000 +0000 +++ puma7-atom-6670-761/linux-5.15.111/net/bridge/br_fdb.c 2024-02-07 10:23:29.000000000 +0000 @@ -1,10 +1,24 @@ -// SPDX-License-Identifier: GPL-2.0-or-later /* - * Forwarding database - * Linux ethernet bridge + * Copyright (C) 2020-2022 MaxLinear, Inc. * - * Authors: - * Lennert Buytenhek + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see http://www.gnu.org/licenses/. + * + * SPDX-License-Identifier: GPL-2.0-only + */ + + /* + * Includes Maxlinear's changes dated: 2022. + * Changed portions - Copyright 2020-2022 MaxLinear, Inc. */ #include @@ -14,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +38,11 @@ #include #include #include "br_private.h" +#ifdef CONFIG_INTEL_MAX_BRIDGE_MACS_LIMIT +static int fdb_insert_cnt = 0; +#endif + +#include static const struct rhashtable_params br_fdb_rht_params = { .head_offset = offsetof(struct net_bridge_fdb_entry, rhnode), @@ -206,6 +226,11 @@ br_fdb_rht_params); fdb_notify(br, f, RTM_DELNEIGH, swdev_notify); call_rcu(&f->rcu, fdb_rcu_free); +#ifdef CONFIG_INTEL_MAX_BRIDGE_MACS_LIMIT + if (fdb_insert_cnt >= 1) { + fdb_insert_cnt--; + } +#endif } /* Delete a local entry if no other port had the same address. */ @@ -367,10 +392,23 @@ if (time_after(this_timer, now)) { work_delay = min(work_delay, this_timer - now); } else { +#ifdef CONFIG_TI_PACKET_PROCESSOR + if(!test_bit(BR_FDB_LOCAL, &f->flags)) + ti_hil_pp_event(TI_BRIDGE_FDB_TIMEOUT, (void*)f); + if (!(f->ti_pp_fdb_status & TI_PP_FDB_ACTIVE)){ + spin_lock_bh(&br->hash_lock); + if (!hlist_unhashed(&f->fdb_node)) + fdb_delete(br, f, true); + spin_unlock_bh(&br->hash_lock); + } + else + f->updated = jiffies; +#else spin_lock_bh(&br->hash_lock); if (!hlist_unhashed(&f->fdb_node)) fdb_delete(br, f, true); spin_unlock_bh(&br->hash_lock); +#endif } } rcu_read_unlock(); @@ -511,6 +549,12 @@ { struct net_bridge_fdb_entry *fdb; +#ifdef CONFIG_INTEL_MAX_BRIDGE_MACS_LIMIT + if (fdb_insert_cnt >= CONFIG_INTEL_MAX_BRIDGE_MACS) { + printk(KERN_WARNING "\n fdb_create reached max bridge macs limit \n"); + return 0; + } +#endif fdb = kmem_cache_alloc(br_fdb_cache, GFP_ATOMIC); if (fdb) { memcpy(fdb->key.addr.addr, addr, ETH_ALEN); @@ -518,6 +562,9 @@ fdb->key.vlan_id = vid; fdb->flags = flags; fdb->updated = fdb->used = jiffies; +#ifdef CONFIG_TI_PACKET_PROCESSOR + fdb->ti_pp_fdb_status = TI_PP_FDB_INACTIVE; +#endif if (rhashtable_lookup_insert_fast(&br->fdb_hash_tbl, &fdb->rhnode, br_fdb_rht_params)) { @@ -525,6 +572,13 @@ fdb = NULL; } else { hlist_add_head_rcu(&fdb->fdb_node, &br->fdb_list); +#ifdef CONFIG_TI_PACKET_PROCESSOR + if (!test_bit(BR_FDB_LOCAL, &fdb->flags)) + ti_hil_pp_event(TI_BRIDGE_FDB_CREATED, (void *)fdb); +#endif +#ifdef CONFIG_INTEL_MAX_BRIDGE_MACS_LIMIT + fdb_insert_cnt++; +#endif } } return fdb; @@ -623,6 +677,9 @@ trace_br_fdb_update(br, source, addr, vid, flags); fdb_notify(br, fdb, RTM_NEWNEIGH, true); } +#ifdef CONFIG_TI_PACKET_PROCESSOR + ti_hil_pp_event(TI_BRIDGE_FDB_CREATED, (void *)fdb); +#endif } } else { spin_lock(&br->hash_lock); @@ -797,6 +854,9 @@ if (swdev_notify) br_switchdev_fdb_notify(br, fdb, type); + /* fdb changed port or was deleted, must cancel any existing bypass. */ + avm_pa_flush_sessions_for_mac(fdb->key.addr.addr); + skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC); if (skb == NULL) goto errout; @@ -1162,6 +1222,33 @@ return err; } +#if IS_ENABLED(CONFIG_DIRECTCONNECT_DP_API) +int dc_dp_br_fdb_delete(struct net_device *dev, const unsigned char *addr) +{ + struct net_bridge_port *p; + int err = 0; + + if (!dev) + return -EINVAL; + + if (!netif_is_bridge_port(dev)) + return -EINVAL; + + rcu_read_lock(); + p = br_port_get_rcu(dev); + if (p) { + if (addr) + err = __br_fdb_delete(p->br, p, addr, 0); + else + br_fdb_delete_by_port(p->br, p, 0, 0); + } + rcu_read_unlock(); + + return err; +} +EXPORT_SYMBOL(dc_dp_br_fdb_delete); +#endif + /* Remove neighbor entry with RTM_DELNEIGH */ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *dev,