--- zzzz-none-000/linux-2.6.39.4/net/bridge/br_fdb.c 2011-08-03 19:43:28.000000000 +0000 +++ puma6-arm-6490-729/linux-2.6.39.4/net/bridge/br_fdb.c 2021-11-10 13:23:11.000000000 +0000 @@ -10,6 +10,10 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ +/* + * Includes Intel Corporation's changes/modifications dated: [11/07/2011]. +* Changed/modified portions - Copyright © [2011], Intel Corporation. +*/ #include #include @@ -18,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +30,11 @@ #include #include "br_private.h" + +#ifdef CONFIG_INTEL_MAX_BRIDGE_MACS_LIMIT +static int fdb_insert_cnt = 0; +#endif + static struct kmem_cache *br_fdb_cache __read_mostly; static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, const unsigned char *addr); @@ -82,7 +92,20 @@ static inline void fdb_delete(struct net_bridge_fdb_entry *f) { hlist_del_rcu(&f->hlist); + +#ifdef CONFIG_AVM_PA + /* fdb changed port or was deleted, must cancel any existing bypass. */ + avm_pa_flush_sessions_for_mac(f->addr.addr); +#endif + call_rcu(&f->rcu, fdb_rcu_free); + +#ifdef CONFIG_INTEL_MAX_BRIDGE_MACS_LIMIT + if (fdb_insert_cnt >= 1) + { + fdb_insert_cnt--; + } +#endif } void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) @@ -142,7 +165,24 @@ continue; this_timer = f->ageing_timer + delay; if (time_before_eq(this_timer, jiffies)) - fdb_delete(f); + { +#ifdef CONFIG_TI_PACKET_PROCESSOR + /* Generate a HIL Packet Processor event indicating that the FDB entry + * is being deleted. Notifications are sent only for non-local FDB + * entries as local traffic is not accelerated through PP. */ + if(!f->is_local) + ti_hil_pp_event(TI_BRIDGE_FDB_DELETED, (void*)f); + + + /* Check if the PP has a session alive for this FDB entry + * ACTIVE - DONT delete the FDB entry. + * NOT ACTIVE - Delete the FDB entry. */ + if (!(f->ti_pp_fdb_status & TI_PP_FDB_ACTIVE)) + fdb_delete(f); +#else + fdb_delete(f); +#endif + } else if (time_before(this_timer, next_timer)) next_timer = this_timer; } @@ -214,6 +254,27 @@ spin_unlock_bh(&br->hash_lock); } +void br_fdb_delete_by_mac_if_local_without_port(struct net_bridge *br, unsigned char *addr) +{ + int i; + + spin_lock_bh(&br->hash_lock); + for (i = 0; i < BR_HASH_SIZE; i++) { + struct hlist_node *h, *g; + + hlist_for_each_safe(h, g, &br->hash[i]) { + struct net_bridge_fdb_entry *f + = hlist_entry(h, struct net_bridge_fdb_entry, hlist); + if (0 == f->dst && f->is_local && !compare_ether_addr(f->addr.addr, addr)) { + fdb_delete(f); + goto end; + } + } + } +end: + spin_unlock_bh(&br->hash_lock); +} + /* No locking or refcounting, assumes caller has rcu_read_lock */ struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br, const unsigned char *addr) @@ -247,7 +308,7 @@ ret = 0; else { fdb = __br_fdb_get(port->br, addr); - ret = fdb && fdb->dst->dev != dev && + ret = fdb && fdb->dst && fdb->dst->dev != dev && fdb->dst->state == BR_STATE_FORWARDING; } rcu_read_unlock(); @@ -279,6 +340,10 @@ if (has_expired(br, f)) continue; + /* ignore pseudo entry for local MAC address */ + if (!f->dst) + continue; + if (skip) { --skip; continue; @@ -325,15 +390,45 @@ { 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->addr.addr, addr, ETH_ALEN); - fdb->dst = source; + fdb->dst = source; /* AVM: note that source may be 0 if is_local */ fdb->is_local = is_local; fdb->is_static = is_local; fdb->ageing_timer = jiffies; - +#ifdef CONFIG_TI_PACKET_PROCESSOR + /* Initialize the Status flag to INACTIVE by default. If + * the event TI_BRIDGE_FDB_CREATED is indeed handled, then + * this flag must be set to TI_PP_FDB_ACTIVE so that it + * can be synced up with PP when FDB entry expires in the + * bridge. If the status flag is not set active, it is assumed + * that the TI_BRIDGE_FDB_* events are not handled and thus + * bridge takes complete control over the fdb entry deletion */ + fdb->ti_pp_fdb_status = TI_PP_FDB_INACTIVE; +#endif hlist_add_head_rcu(&fdb->hlist, head); +#ifdef CONFIG_TI_PACKET_PROCESSOR + /* Indicate to the HIL layer that a non-local FDB entry has been created. */ + if (!fdb->is_local) + ti_hil_pp_event(TI_BRIDGE_FDB_CREATED, (void *)fdb); +#endif + +#ifdef CONFIG_INTEL_MAX_BRIDGE_MACS_LIMIT + fdb_insert_cnt++; +#endif + +#ifdef CONFIG_AVM_PA + /* fdb changed port or was deleted, must cancel any existing bypass. */ + avm_pa_flush_sessions_for_mac(addr); +#endif } return fdb; } @@ -356,7 +451,7 @@ return 0; br_warn(br, "adding interface %s with same address " "as a received packet\n", - source->dev->name); + source ? source->dev->name : ""); fdb_delete(fdb); } @@ -402,8 +497,17 @@ source->dev->name); } else { /* fastpath: update of existing entry */ +#ifdef CONFIG_AVM_PA + /* fdb changed port or was deleted, must cancel any existing bypass. */ + if (fdb->dst != source) + avm_pa_flush_sessions_for_mac(addr); +#endif fdb->dst = source; fdb->ageing_timer = jiffies; +#ifdef CONFIG_TI_PACKET_PROCESSOR + /* Indicate to the HIL layer that an FDB entry has been updated. */ + ti_hil_pp_event(TI_BRIDGE_FDB_CREATED, (void *)fdb); +#endif } } else { spin_lock(&br->hash_lock);