Skip to content

Commit

Permalink
rocker: add FDB cleanup timer
Browse files Browse the repository at this point in the history
Add a timer to each rocker switch to do FDB entry cleanup by ageing out
expired entries.  The timer scheduling algo is copied from the bridge
driver, for the most part, to keep the firing of the timer to a minimum.

Signed-off-by: Scott Feldman <[email protected]>
Acked-by: Jiri Pirko <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
scottfeldman authored and davem330 committed Sep 23, 2015
1 parent e733570 commit 52fe3e2
Showing 1 changed file with 42 additions and 0 deletions.
42 changes: 42 additions & 0 deletions drivers/net/ethernet/rocker/rocker.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ struct rocker {
u64 flow_tbl_next_cookie;
DECLARE_HASHTABLE(group_tbl, 16);
spinlock_t group_tbl_lock; /* for group tbl accesses */
struct timer_list fdb_cleanup_timer;
DECLARE_HASHTABLE(fdb_tbl, 16);
spinlock_t fdb_tbl_lock; /* for fdb tbl accesses */
unsigned long internal_vlan_bitmap[ROCKER_INTERNAL_VLAN_BITMAP_LEN];
Expand Down Expand Up @@ -3706,6 +3707,41 @@ static int rocker_port_fdb_flush(struct rocker_port *rocker_port,
return err;
}

static void rocker_fdb_cleanup(unsigned long data)
{
struct rocker *rocker = (struct rocker *)data;
struct rocker_port *rocker_port;
struct rocker_fdb_tbl_entry *entry;
struct hlist_node *tmp;
unsigned long next_timer = jiffies + BR_MIN_AGEING_TIME;
unsigned long expires;
unsigned long lock_flags;
int flags = ROCKER_OP_FLAG_NOWAIT | ROCKER_OP_FLAG_REMOVE |
ROCKER_OP_FLAG_LEARNED;
int bkt;

spin_lock_irqsave(&rocker->fdb_tbl_lock, lock_flags);

hash_for_each_safe(rocker->fdb_tbl, bkt, tmp, entry, entry) {
if (!entry->learned)
continue;
rocker_port = entry->key.rocker_port;
expires = entry->touched + rocker_port->ageing_time;
if (time_before_eq(expires, jiffies)) {
rocker_port_fdb_learn(rocker_port, SWITCHDEV_TRANS_NONE,
flags, entry->key.addr,
entry->key.vlan_id);
hash_del(&entry->entry);
} else if (time_before(expires, next_timer)) {
next_timer = expires;
}
}

spin_unlock_irqrestore(&rocker->fdb_tbl_lock, lock_flags);

mod_timer(&rocker->fdb_cleanup_timer, round_jiffies_up(next_timer));
}

static int rocker_port_router_mac(struct rocker_port *rocker_port,
enum switchdev_trans trans, int flags,
__be16 vlan_id)
Expand Down Expand Up @@ -5191,6 +5227,10 @@ static int rocker_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_init_tbls;
}

setup_timer(&rocker->fdb_cleanup_timer, rocker_fdb_cleanup,
(unsigned long) rocker);
mod_timer(&rocker->fdb_cleanup_timer, jiffies);

err = rocker_probe_ports(rocker);
if (err) {
dev_err(&pdev->dev, "failed to probe ports\n");
Expand All @@ -5203,6 +5243,7 @@ static int rocker_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return 0;

err_probe_ports:
del_timer_sync(&rocker->fdb_cleanup_timer);
rocker_free_tbls(rocker);
err_init_tbls:
free_irq(rocker_msix_vector(rocker, ROCKER_MSIX_VEC_EVENT), rocker);
Expand Down Expand Up @@ -5230,6 +5271,7 @@ static void rocker_remove(struct pci_dev *pdev)
{
struct rocker *rocker = pci_get_drvdata(pdev);

del_timer_sync(&rocker->fdb_cleanup_timer);
rocker_free_tbls(rocker);
rocker_write32(rocker, CONTROL, ROCKER_CONTROL_RESET);
rocker_remove_ports(rocker);
Expand Down

0 comments on commit 52fe3e2

Please sign in to comment.