aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/rocker
diff options
context:
space:
mode:
authorIdo Schimmel <idosch@mellanox.com>2016-12-03 16:45:07 +0100
committerDavid S. Miller <davem@davemloft.net>2016-12-03 19:29:35 -0500
commitc3852ef7f2f8f75a9f85a864bec1f6f5a3068eea (patch)
tree65da87ee804eacc4e5f6535e1d9bb8927cba244d /drivers/net/ethernet/rocker
parentipv4: fib: Allow for consistent FIB dumping (diff)
downloadlinux-dev-c3852ef7f2f8f75a9f85a864bec1f6f5a3068eea.tar.xz
linux-dev-c3852ef7f2f8f75a9f85a864bec1f6f5a3068eea.zip
ipv4: fib: Replay events when registering FIB notifier
Commit b90eb7549499 ("fib: introduce FIB notification infrastructure") introduced a new notification chain to notify listeners (f.e., switchdev drivers) about addition and deletion of routes. However, upon registration to the chain the FIB tables can already be populated, which means potential listeners will have an incomplete view of the tables. Solve that by dumping the FIB tables and replaying the events to the passed notification block. The dump itself is done using RCU in order not to starve consumers that need RTNL to make progress. The integrity of the dump is ensured by reading the FIB change sequence counter before and after the dump under RTNL. This allows us to avoid the problematic situation in which the dumping process sends a ENTRY_ADD notification following ENTRY_DEL generated by another process holding RTNL. Callers of the registration function may pass a callback that is executed in case the dump was inconsistent with current FIB tables. The number of retries until a consistent dump is achieved is set to a fixed number to prevent callers from looping for long periods of time. In case current limit proves to be problematic in the future, it can be easily converted to be configurable using a sysctl. Signed-off-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/rocker')
-rw-r--r--drivers/net/ethernet/rocker/rocker_main.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index 8c9c90ae8962..7c450b5a1138 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -2804,8 +2804,13 @@ static int rocker_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_alloc_ordered_workqueue;
}
+ /* Only FIBs pointing to our own netdevs are programmed into
+ * the device, so no need to pass a callback.
+ */
rocker->fib_nb.notifier_call = rocker_router_fib_event;
- register_fib_notifier(&rocker->fib_nb);
+ err = register_fib_notifier(&rocker->fib_nb, NULL);
+ if (err)
+ goto err_register_fib_notifier;
rocker->hw.id = rocker_read64(rocker, SWITCH_ID);
@@ -2822,6 +2827,7 @@ static int rocker_probe(struct pci_dev *pdev, const struct pci_device_id *id)
err_probe_ports:
unregister_fib_notifier(&rocker->fib_nb);
+err_register_fib_notifier:
destroy_workqueue(rocker->rocker_owq);
err_alloc_ordered_workqueue:
free_irq(rocker_msix_vector(rocker, ROCKER_MSIX_VEC_EVENT), rocker);