diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 58d22e2b85fc..b6b79972b50b 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -982,6 +982,15 @@ static bool __fdb_mark_active(struct net_bridge_fdb_entry *fdb) test_and_clear_bit(BR_FDB_NOTIFY_INACTIVE, &fdb->flags)); } +static bool ratelimit_1hz(unsigned long *stamp) +{ + const unsigned long now = data_race(READ_ONCE(jiffies)); + const unsigned long prev = data_race(READ_ONCE(*stamp)); + + return !time_in_range_open(now, prev, prev + HZ) && + cmpxchg(stamp, prev, now) == prev; +} + void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, const unsigned char *addr, u16 vid, unsigned long flags) { @@ -995,7 +1004,9 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, if (likely(fdb)) { /* attempt to update an entry for a local interface */ if (unlikely(test_bit(BR_FDB_LOCAL, &fdb->flags))) { - if (net_ratelimit()) + static unsigned long stamp; + + if (ratelimit_1hz(&stamp)) br_warn(br, "received packet on %s with own address as source address (addr:%pM, vlan:%u)\n", source->dev->name, addr, vid); } else {