All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 0/9] Simplify IPv4 route offload API
@ 2019-12-10 17:23 Ido Schimmel
  2019-12-10 17:23 ` [PATCH net-next 1/9] net: fib_notifier: Add temporary events to the FIB notification chain Ido Schimmel
                   ` (8 more replies)
  0 siblings, 9 replies; 21+ messages in thread
From: Ido Schimmel @ 2019-12-10 17:23 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, roopa, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Motivation
==========

The aim of this patch set is to simplify the IPv4 route offload API by
making the stack a bit smarter about the notifications it is generating.
This allows driver authors to focus on programming the underlying device
instead of having to duplicate the IPv4 route insertion logic in their
driver, which is error-prone.

This is the first patch set out of a series of four. Subsequent patch
sets will simplify the IPv6 API, add offload/trap indication to routes
and add tests for all the code paths (including error paths). Available
here [1].

Details
=======

Today, whenever an IPv4 route is added or deleted a notification is sent
in the FIB notification chain and it is up to offload drivers to decide
if the route should be programmed to the hardware or not. This is not an
easy task as in hardware routes are keyed by {prefix, prefix length,
table id}, whereas the kernel can store multiple such routes that only
differ in metric / TOS / nexthop info.

This series makes sure that only routes that are actually used in the
data path are notified to offload drivers. This greatly simplifies the
work these drivers need to do, as they are now only concerned with
programming the hardware and do not need to replicate the IPv4 route
insertion logic and store multiple identical routes.

The route that is notified is the first FIB alias in the FIB node with
the given {prefix, prefix length, table ID}. In case the route is
deleted and there is another route with the same key, a replace
notification is emitted. Otherwise, a delete notification is emitted.

The above means that in the case of multiple routes with the same key,
but different TOS, only the route with the highest TOS is notified.
While the kernel can route a packet based on its TOS, this is not
supported by any hardware devices I am familiar with. Moreover, this is
not supported by IPv6 nor by BIRD/FRR from what I could see. Offload
drivers should therefore use the presence of a non-zero TOS as an
indication to trap packets matching the route and let the kernel route
them instead. mlxsw has been doing it for the past two years.

Testing
=======

To ensure there is no degradation in route insertion rates, I averaged
the insertion rate of 512k routes (/24 and /32) over 50 runs. Did not
observe any degradation.

Functional tests are available here [1]. They rely on route trap
indication, which is only added in the last patch set.

In addition, I have been running syzkaller for the past week with all
four patch sets and debug options enabled. Did not observe any problems.

Patch set overview
==================

Patches #1-#7 gradually introduce the new FIB notifications
Patch #8 converts mlxsw to use the new notifications
Patch #9 converts the remaining listeners and removes the old
notifications

RFC: https://patchwork.ozlabs.org/cover/1170530/

[1] https://github.com/idosch/linux/tree/fib-notifier

Ido Schimmel (9):
  net: fib_notifier: Add temporary events to the FIB notification chain
  ipv4: Notify route after insertion to the routing table
  ipv4: Notify route if replacing currently offloaded one
  ipv4: Notify newly added route if should be offloaded
  ipv4: Handle route deletion notification
  ipv4: Handle route deletion notification during flush
  ipv4: Only Replay routes of interest to new listeners
  mlxsw: spectrum_router: Start using new IPv4 route notifications
  ipv4: Remove old route notifications and convert listeners

 .../net/ethernet/mellanox/mlx5/core/lag_mp.c  |   4 -
 .../ethernet/mellanox/mlxsw/spectrum_router.c | 136 +++---------------
 drivers/net/ethernet/rocker/rocker_main.c     |   4 +-
 drivers/net/netdevsim/fib.c                   |   4 +-
 net/ipv4/fib_trie.c                           | 131 ++++++++++++-----
 5 files changed, 117 insertions(+), 162 deletions(-)

-- 
2.23.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH net-next 1/9] net: fib_notifier: Add temporary events to the FIB notification chain
  2019-12-10 17:23 [PATCH net-next 0/9] Simplify IPv4 route offload API Ido Schimmel
@ 2019-12-10 17:23 ` Ido Schimmel
  2019-12-10 17:23 ` [PATCH net-next 2/9] ipv4: Notify route after insertion to the routing table Ido Schimmel
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Ido Schimmel @ 2019-12-10 17:23 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, roopa, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Subsequent patches are going to simplify the IPv4 route offload API,
which will only use two events - replace and delete.

Introduce a temporary version of these two events in order to make the
conversion easier to review.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 include/net/fib_notifier.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/net/fib_notifier.h b/include/net/fib_notifier.h
index 6d59221ff05a..b3c54325caec 100644
--- a/include/net/fib_notifier.h
+++ b/include/net/fib_notifier.h
@@ -23,6 +23,8 @@ enum fib_event_type {
 	FIB_EVENT_NH_DEL,
 	FIB_EVENT_VIF_ADD,
 	FIB_EVENT_VIF_DEL,
+	FIB_EVENT_ENTRY_REPLACE_TMP,
+	FIB_EVENT_ENTRY_DEL_TMP,
 };
 
 struct fib_notifier_ops {
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH net-next 2/9] ipv4: Notify route after insertion to the routing table
  2019-12-10 17:23 [PATCH net-next 0/9] Simplify IPv4 route offload API Ido Schimmel
  2019-12-10 17:23 ` [PATCH net-next 1/9] net: fib_notifier: Add temporary events to the FIB notification chain Ido Schimmel
@ 2019-12-10 17:23 ` Ido Schimmel
  2019-12-11 17:34   ` David Ahern
  2019-12-10 17:23 ` [PATCH net-next 3/9] ipv4: Notify route if replacing currently offloaded one Ido Schimmel
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: Ido Schimmel @ 2019-12-10 17:23 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, roopa, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Currently, a new route is notified in the FIB notification chain before
it is inserted to the FIB alias list.

Subsequent patches will use the placement of the new route in the
ordered FIB alias list in order to determine if the route should be
notified or not.

As a preparatory step, change the order so that the route is first
inserted into the FIB alias list and only then notified.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 net/ipv4/fib_trie.c | 29 ++++++++++++++---------------
 1 file changed, 14 insertions(+), 15 deletions(-)

diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index b9df9c09b84e..9264d6628e9f 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1063,9 +1063,6 @@ static int fib_insert_node(struct trie *t, struct key_vector *tp,
 	return -ENOMEM;
 }
 
-/* fib notifier for ADD is sent before calling fib_insert_alias with
- * the expectation that the only possible failure ENOMEM
- */
 static int fib_insert_alias(struct trie *t, struct key_vector *tp,
 			    struct key_vector *l, struct fib_alias *new,
 			    struct fib_alias *fa, t_key key)
@@ -1118,6 +1115,9 @@ static bool fib_valid_key_len(u32 key, u8 plen, struct netlink_ext_ack *extack)
 	return true;
 }
 
+static void fib_remove_alias(struct trie *t, struct key_vector *tp,
+			     struct key_vector *l, struct fib_alias *old);
+
 /* Caller must hold RTNL. */
 int fib_table_insert(struct net *net, struct fib_table *tb,
 		     struct fib_config *cfg, struct netlink_ext_ack *extack)
@@ -1269,14 +1269,19 @@ int fib_table_insert(struct net *net, struct fib_table *tb,
 	new_fa->tb_id = tb->tb_id;
 	new_fa->fa_default = -1;
 
-	err = call_fib_entry_notifiers(net, event, key, plen, new_fa, extack);
+	/* Insert new entry to the list. */
+	err = fib_insert_alias(t, tp, l, new_fa, fa, key);
 	if (err)
 		goto out_free_new_fa;
 
-	/* Insert new entry to the list. */
-	err = fib_insert_alias(t, tp, l, new_fa, fa, key);
+	/* The alias was already inserted, so the node must exist. */
+	l = l ? l : fib_find_node(t, &tp, key);
+	if (WARN_ON_ONCE(!l))
+		goto out_free_new_fa;
+
+	err = call_fib_entry_notifiers(net, event, key, plen, new_fa, extack);
 	if (err)
-		goto out_fib_notif;
+		goto out_remove_new_fa;
 
 	if (!plen)
 		tb->tb_num_default++;
@@ -1287,14 +1292,8 @@ int fib_table_insert(struct net *net, struct fib_table *tb,
 succeeded:
 	return 0;
 
-out_fib_notif:
-	/* notifier was sent that entry would be added to trie, but
-	 * the add failed and need to recover. Only failure for
-	 * fib_insert_alias is ENOMEM.
-	 */
-	NL_SET_ERR_MSG(extack, "Failed to insert route into trie");
-	call_fib_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, key,
-				 plen, new_fa, NULL);
+out_remove_new_fa:
+	fib_remove_alias(t, tp, l, new_fa);
 out_free_new_fa:
 	kmem_cache_free(fn_alias_kmem, new_fa);
 out:
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH net-next 3/9] ipv4: Notify route if replacing currently offloaded one
  2019-12-10 17:23 [PATCH net-next 0/9] Simplify IPv4 route offload API Ido Schimmel
  2019-12-10 17:23 ` [PATCH net-next 1/9] net: fib_notifier: Add temporary events to the FIB notification chain Ido Schimmel
  2019-12-10 17:23 ` [PATCH net-next 2/9] ipv4: Notify route after insertion to the routing table Ido Schimmel
@ 2019-12-10 17:23 ` Ido Schimmel
  2019-12-11 17:40   ` David Ahern
  2019-12-10 17:23 ` [PATCH net-next 4/9] ipv4: Notify newly added route if should be offloaded Ido Schimmel
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: Ido Schimmel @ 2019-12-10 17:23 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, roopa, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

When replacing a route, its replacement should only be notified in case
the replaced route is of any interest to listeners. In other words, if
the replaced route is currently used in the data path, which means it is
the first route in the FIB alias list with the given {prefix, prefix
length, table ID}.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 net/ipv4/fib_trie.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 9264d6628e9f..6822aa90657a 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -978,6 +978,27 @@ static struct key_vector *fib_find_node(struct trie *t,
 	return n;
 }
 
+/* Return the first fib alias matching prefix length and table ID. */
+static struct fib_alias *fib_find_first_alias(struct hlist_head *fah, u8 slen,
+					      u32 tb_id)
+{
+	struct fib_alias *fa;
+
+	hlist_for_each_entry(fa, fah, fa_list) {
+		if (fa->fa_slen < slen)
+			continue;
+		if (fa->fa_slen != slen)
+			break;
+		if (fa->tb_id > tb_id)
+			continue;
+		if (fa->tb_id != tb_id)
+			break;
+		return fa;
+	}
+
+	return NULL;
+}
+
 /* Return the first fib alias matching TOS with
  * priority less than or equal to PRIO.
  */
@@ -1217,6 +1238,17 @@ int fib_table_insert(struct net *net, struct fib_table *tb,
 			new_fa->tb_id = tb->tb_id;
 			new_fa->fa_default = -1;
 
+			if (fib_find_first_alias(&l->leaf, fa->fa_slen,
+						 tb->tb_id) == fa) {
+				enum fib_event_type fib_event;
+
+				fib_event = FIB_EVENT_ENTRY_REPLACE_TMP;
+				err = call_fib_entry_notifiers(net, fib_event,
+							       key, plen,
+							       new_fa, extack);
+				if (err)
+					goto out_free_new_fa;
+			}
 			err = call_fib_entry_notifiers(net,
 						       FIB_EVENT_ENTRY_REPLACE,
 						       key, plen, new_fa,
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH net-next 4/9] ipv4: Notify newly added route if should be offloaded
  2019-12-10 17:23 [PATCH net-next 0/9] Simplify IPv4 route offload API Ido Schimmel
                   ` (2 preceding siblings ...)
  2019-12-10 17:23 ` [PATCH net-next 3/9] ipv4: Notify route if replacing currently offloaded one Ido Schimmel
@ 2019-12-10 17:23 ` Ido Schimmel
  2019-12-10 17:23 ` [PATCH net-next 5/9] ipv4: Handle route deletion notification Ido Schimmel
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Ido Schimmel @ 2019-12-10 17:23 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, roopa, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

When a route is added, it should only be notified in case it is the
first route in the FIB alias list with the given {prefix, prefix length,
table ID}. Otherwise, it is not used in the data path and should not be
considered by switch drivers.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 net/ipv4/fib_trie.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 6822aa90657a..66c7926d027d 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1311,6 +1311,16 @@ int fib_table_insert(struct net *net, struct fib_table *tb,
 	if (WARN_ON_ONCE(!l))
 		goto out_free_new_fa;
 
+	if (fib_find_first_alias(&l->leaf, new_fa->fa_slen, tb->tb_id) ==
+	    new_fa) {
+		enum fib_event_type fib_event;
+
+		fib_event = FIB_EVENT_ENTRY_REPLACE_TMP;
+		err = call_fib_entry_notifiers(net, fib_event, key, plen,
+					       new_fa, extack);
+		if (err)
+			goto out_remove_new_fa;
+	}
 	err = call_fib_entry_notifiers(net, event, key, plen, new_fa, extack);
 	if (err)
 		goto out_remove_new_fa;
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH net-next 5/9] ipv4: Handle route deletion notification
  2019-12-10 17:23 [PATCH net-next 0/9] Simplify IPv4 route offload API Ido Schimmel
                   ` (3 preceding siblings ...)
  2019-12-10 17:23 ` [PATCH net-next 4/9] ipv4: Notify newly added route if should be offloaded Ido Schimmel
@ 2019-12-10 17:23 ` Ido Schimmel
  2019-12-11 17:44   ` David Ahern
  2019-12-10 17:23 ` [PATCH net-next 6/9] ipv4: Handle route deletion notification during flush Ido Schimmel
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: Ido Schimmel @ 2019-12-10 17:23 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, roopa, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

When a route is deleted we potentially need to promote the next route in
the FIB alias list (e.g., with an higher metric). In case we find such a
route, a replace notification is emitted. Otherwise, a delete
notification for the deleted route.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 net/ipv4/fib_trie.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 66c7926d027d..2d338469d4f2 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1586,6 +1586,36 @@ static void fib_remove_alias(struct trie *t, struct key_vector *tp,
 	node_pull_suffix(tp, fa->fa_slen);
 }
 
+static void fib_notify_alias_delete(struct net *net, u32 key,
+				    struct hlist_head *fah,
+				    struct fib_alias *fa_to_delete,
+				    struct netlink_ext_ack *extack)
+{
+	struct fib_alias *fa_next, *fa_to_notify;
+	u32 tb_id = fa_to_delete->tb_id;
+	u8 slen = fa_to_delete->fa_slen;
+	enum fib_event_type fib_event;
+
+	/* Do not notify if we do not care about the route. */
+	if (fib_find_first_alias(fah, slen, tb_id) != fa_to_delete)
+		return;
+
+	/* Determine if the route should be replaced by the next route in the
+	 * list.
+	 */
+	fa_next = hlist_entry_safe(fa_to_delete->fa_list.next,
+				   struct fib_alias, fa_list);
+	if (fa_next && fa_next->fa_slen == slen && fa_next->tb_id == tb_id) {
+		fib_event = FIB_EVENT_ENTRY_REPLACE_TMP;
+		fa_to_notify = fa_next;
+	} else {
+		fib_event = FIB_EVENT_ENTRY_DEL_TMP;
+		fa_to_notify = fa_to_delete;
+	}
+	call_fib_entry_notifiers(net, fib_event, key, KEYLENGTH - slen,
+				 fa_to_notify, extack);
+}
+
 /* Caller must hold RTNL. */
 int fib_table_delete(struct net *net, struct fib_table *tb,
 		     struct fib_config *cfg, struct netlink_ext_ack *extack)
@@ -1639,6 +1669,7 @@ int fib_table_delete(struct net *net, struct fib_table *tb,
 	if (!fa_to_delete)
 		return -ESRCH;
 
+	fib_notify_alias_delete(net, key, &l->leaf, fa_to_delete, extack);
 	call_fib_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, key, plen,
 				 fa_to_delete, extack);
 	rtmsg_fib(RTM_DELROUTE, htonl(key), fa_to_delete, plen, tb->tb_id,
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH net-next 6/9] ipv4: Handle route deletion notification during flush
  2019-12-10 17:23 [PATCH net-next 0/9] Simplify IPv4 route offload API Ido Schimmel
                   ` (4 preceding siblings ...)
  2019-12-10 17:23 ` [PATCH net-next 5/9] ipv4: Handle route deletion notification Ido Schimmel
@ 2019-12-10 17:23 ` Ido Schimmel
  2019-12-11 17:46   ` David Ahern
  2019-12-11 17:52   ` David Ahern
  2019-12-10 17:24 ` [PATCH net-next 7/9] ipv4: Only Replay routes of interest to new listeners Ido Schimmel
                   ` (2 subsequent siblings)
  8 siblings, 2 replies; 21+ messages in thread
From: Ido Schimmel @ 2019-12-10 17:23 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, roopa, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

In a similar fashion to previous patch, when a route is deleted as part
of table flushing, promote the next route in the list, if exists.
Otherwise, simply emit a delete notification.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 net/ipv4/fib_trie.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 2d338469d4f2..60947a44d363 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1995,6 +1995,8 @@ int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all)
 				continue;
 			}
 
+			fib_notify_alias_delete(net, n->key, &n->leaf, fa,
+						NULL);
 			call_fib_entry_notifiers(net, FIB_EVENT_ENTRY_DEL,
 						 n->key,
 						 KEYLENGTH - fa->fa_slen, fa,
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH net-next 7/9] ipv4: Only Replay routes of interest to new listeners
  2019-12-10 17:23 [PATCH net-next 0/9] Simplify IPv4 route offload API Ido Schimmel
                   ` (5 preceding siblings ...)
  2019-12-10 17:23 ` [PATCH net-next 6/9] ipv4: Handle route deletion notification during flush Ido Schimmel
@ 2019-12-10 17:24 ` Ido Schimmel
  2019-12-11 17:57   ` David Ahern
  2019-12-10 17:24 ` [PATCH net-next 8/9] mlxsw: spectrum_router: Start using new IPv4 route notifications Ido Schimmel
  2019-12-10 17:24 ` [PATCH net-next 9/9] ipv4: Remove old route notifications and convert listeners Ido Schimmel
  8 siblings, 1 reply; 21+ messages in thread
From: Ido Schimmel @ 2019-12-10 17:24 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, roopa, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

When a new listener is registered to the FIB notification chain it
receives a dump of all the available routes in the system. Instead, make
sure to only replay the IPv4 routes that are actually used in the data
path and are of any interest to the new listener.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 net/ipv4/fib_trie.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 60947a44d363..eff45e7795ba 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -2096,6 +2096,7 @@ static int fib_leaf_notify(struct key_vector *l, struct fib_table *tb,
 			   struct netlink_ext_ack *extack)
 {
 	struct fib_alias *fa;
+	int last_slen = -1;
 	int err;
 
 	hlist_for_each_entry_rcu(fa, &l->leaf, fa_list) {
@@ -2115,6 +2116,16 @@ static int fib_leaf_notify(struct key_vector *l, struct fib_table *tb,
 					      fa, extack);
 		if (err)
 			return err;
+
+		if (fa->fa_slen == last_slen)
+			continue;
+
+		last_slen = fa->fa_slen;
+		err = call_fib_entry_notifier(nb, FIB_EVENT_ENTRY_REPLACE_TMP,
+					      l->key, KEYLENGTH - fa->fa_slen,
+					      fa, extack);
+		if (err)
+			return err;
 	}
 	return 0;
 }
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH net-next 8/9] mlxsw: spectrum_router: Start using new IPv4 route notifications
  2019-12-10 17:23 [PATCH net-next 0/9] Simplify IPv4 route offload API Ido Schimmel
                   ` (6 preceding siblings ...)
  2019-12-10 17:24 ` [PATCH net-next 7/9] ipv4: Only Replay routes of interest to new listeners Ido Schimmel
@ 2019-12-10 17:24 ` Ido Schimmel
  2019-12-11 17:58   ` David Ahern
  2019-12-10 17:24 ` [PATCH net-next 9/9] ipv4: Remove old route notifications and convert listeners Ido Schimmel
  8 siblings, 1 reply; 21+ messages in thread
From: Ido Schimmel @ 2019-12-10 17:24 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, roopa, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

With the new notifications mlxsw does not need to handle identical
routes itself, as this is taken care of by the core IPv4 code.

Instead, mlxsw only needs to take care of inserting and removing routes
from the device.

Convert mlxsw to use the new IPv4 route notifications and simplify the
code.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_router.c | 141 +++---------------
 1 file changed, 20 insertions(+), 121 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 30bfe3880faf..396b27b9cdb4 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -3845,7 +3845,7 @@ static void mlxsw_sp_nexthop4_event(struct mlxsw_sp *mlxsw_sp,
 
 	key.fib_nh = fib_nh;
 	nh = mlxsw_sp_nexthop_lookup(mlxsw_sp, key);
-	if (WARN_ON_ONCE(!nh))
+	if (!nh)
 		return;
 
 	switch (event) {
@@ -4780,95 +4780,6 @@ static void mlxsw_sp_fib_node_put(struct mlxsw_sp *mlxsw_sp,
 	mlxsw_sp_vr_put(mlxsw_sp, vr);
 }
 
-static struct mlxsw_sp_fib4_entry *
-mlxsw_sp_fib4_node_entry_find(const struct mlxsw_sp_fib_node *fib_node,
-			      const struct mlxsw_sp_fib4_entry *new4_entry)
-{
-	struct mlxsw_sp_fib4_entry *fib4_entry;
-
-	list_for_each_entry(fib4_entry, &fib_node->entry_list, common.list) {
-		if (fib4_entry->tb_id > new4_entry->tb_id)
-			continue;
-		if (fib4_entry->tb_id != new4_entry->tb_id)
-			break;
-		if (fib4_entry->tos > new4_entry->tos)
-			continue;
-		if (fib4_entry->prio >= new4_entry->prio ||
-		    fib4_entry->tos < new4_entry->tos)
-			return fib4_entry;
-	}
-
-	return NULL;
-}
-
-static int
-mlxsw_sp_fib4_node_list_append(struct mlxsw_sp_fib4_entry *fib4_entry,
-			       struct mlxsw_sp_fib4_entry *new4_entry)
-{
-	struct mlxsw_sp_fib_node *fib_node;
-
-	if (WARN_ON(!fib4_entry))
-		return -EINVAL;
-
-	fib_node = fib4_entry->common.fib_node;
-	list_for_each_entry_from(fib4_entry, &fib_node->entry_list,
-				 common.list) {
-		if (fib4_entry->tb_id != new4_entry->tb_id ||
-		    fib4_entry->tos != new4_entry->tos ||
-		    fib4_entry->prio != new4_entry->prio)
-			break;
-	}
-
-	list_add_tail(&new4_entry->common.list, &fib4_entry->common.list);
-	return 0;
-}
-
-static int
-mlxsw_sp_fib4_node_list_insert(struct mlxsw_sp_fib4_entry *new4_entry,
-			       bool replace, bool append)
-{
-	struct mlxsw_sp_fib_node *fib_node = new4_entry->common.fib_node;
-	struct mlxsw_sp_fib4_entry *fib4_entry;
-
-	fib4_entry = mlxsw_sp_fib4_node_entry_find(fib_node, new4_entry);
-
-	if (append)
-		return mlxsw_sp_fib4_node_list_append(fib4_entry, new4_entry);
-	if (replace && WARN_ON(!fib4_entry))
-		return -EINVAL;
-
-	/* Insert new entry before replaced one, so that we can later
-	 * remove the second.
-	 */
-	if (fib4_entry) {
-		list_add_tail(&new4_entry->common.list,
-			      &fib4_entry->common.list);
-	} else {
-		struct mlxsw_sp_fib4_entry *last;
-
-		list_for_each_entry(last, &fib_node->entry_list, common.list) {
-			if (new4_entry->tb_id > last->tb_id)
-				break;
-			fib4_entry = last;
-		}
-
-		if (fib4_entry)
-			list_add(&new4_entry->common.list,
-				 &fib4_entry->common.list);
-		else
-			list_add(&new4_entry->common.list,
-				 &fib_node->entry_list);
-	}
-
-	return 0;
-}
-
-static void
-mlxsw_sp_fib4_node_list_remove(struct mlxsw_sp_fib4_entry *fib4_entry)
-{
-	list_del(&fib4_entry->common.list);
-}
-
 static int mlxsw_sp_fib_node_entry_add(struct mlxsw_sp *mlxsw_sp,
 				       struct mlxsw_sp_fib_entry *fib_entry)
 {
@@ -4912,14 +4823,12 @@ static void mlxsw_sp_fib_node_entry_del(struct mlxsw_sp *mlxsw_sp,
 }
 
 static int mlxsw_sp_fib4_node_entry_link(struct mlxsw_sp *mlxsw_sp,
-					 struct mlxsw_sp_fib4_entry *fib4_entry,
-					 bool replace, bool append)
+					 struct mlxsw_sp_fib4_entry *fib4_entry)
 {
+	struct mlxsw_sp_fib_node *fib_node = fib4_entry->common.fib_node;
 	int err;
 
-	err = mlxsw_sp_fib4_node_list_insert(fib4_entry, replace, append);
-	if (err)
-		return err;
+	list_add(&fib4_entry->common.list, &fib_node->entry_list);
 
 	err = mlxsw_sp_fib_node_entry_add(mlxsw_sp, &fib4_entry->common);
 	if (err)
@@ -4928,7 +4837,7 @@ static int mlxsw_sp_fib4_node_entry_link(struct mlxsw_sp *mlxsw_sp,
 	return 0;
 
 err_fib_node_entry_add:
-	mlxsw_sp_fib4_node_list_remove(fib4_entry);
+	list_del(&fib4_entry->common.list);
 	return err;
 }
 
@@ -4937,20 +4846,19 @@ mlxsw_sp_fib4_node_entry_unlink(struct mlxsw_sp *mlxsw_sp,
 				struct mlxsw_sp_fib4_entry *fib4_entry)
 {
 	mlxsw_sp_fib_node_entry_del(mlxsw_sp, &fib4_entry->common);
-	mlxsw_sp_fib4_node_list_remove(fib4_entry);
+	list_del(&fib4_entry->common.list);
 
 	if (fib4_entry->common.type == MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP)
 		mlxsw_sp_fib_entry_decap_fini(mlxsw_sp, &fib4_entry->common);
 }
 
 static void mlxsw_sp_fib4_entry_replace(struct mlxsw_sp *mlxsw_sp,
-					struct mlxsw_sp_fib4_entry *fib4_entry,
-					bool replace)
+					struct mlxsw_sp_fib4_entry *fib4_entry)
 {
 	struct mlxsw_sp_fib_node *fib_node = fib4_entry->common.fib_node;
 	struct mlxsw_sp_fib4_entry *replaced;
 
-	if (!replace)
+	if (list_is_singular(&fib_node->entry_list))
 		return;
 
 	/* We inserted the new entry before replaced one */
@@ -4962,9 +4870,8 @@ static void mlxsw_sp_fib4_entry_replace(struct mlxsw_sp *mlxsw_sp,
 }
 
 static int
-mlxsw_sp_router_fib4_add(struct mlxsw_sp *mlxsw_sp,
-			 const struct fib_entry_notifier_info *fen_info,
-			 bool replace, bool append)
+mlxsw_sp_router_fib4_replace(struct mlxsw_sp *mlxsw_sp,
+			     const struct fib_entry_notifier_info *fen_info)
 {
 	struct mlxsw_sp_fib4_entry *fib4_entry;
 	struct mlxsw_sp_fib_node *fib_node;
@@ -4989,14 +4896,13 @@ mlxsw_sp_router_fib4_add(struct mlxsw_sp *mlxsw_sp,
 		goto err_fib4_entry_create;
 	}
 
-	err = mlxsw_sp_fib4_node_entry_link(mlxsw_sp, fib4_entry, replace,
-					    append);
+	err = mlxsw_sp_fib4_node_entry_link(mlxsw_sp, fib4_entry);
 	if (err) {
 		dev_warn(mlxsw_sp->bus_info->dev, "Failed to link FIB entry to node\n");
 		goto err_fib4_node_entry_link;
 	}
 
-	mlxsw_sp_fib4_entry_replace(mlxsw_sp, fib4_entry, replace);
+	mlxsw_sp_fib4_entry_replace(mlxsw_sp, fib4_entry);
 
 	return 0;
 
@@ -6094,7 +6000,6 @@ static void mlxsw_sp_router_fib4_event_work(struct work_struct *work)
 	struct mlxsw_sp_fib_event_work *fib_work =
 		container_of(work, struct mlxsw_sp_fib_event_work, work);
 	struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
-	bool replace, append;
 	int err;
 
 	/* Protect internal structures from changes */
@@ -6102,18 +6007,14 @@ static void mlxsw_sp_router_fib4_event_work(struct work_struct *work)
 	mlxsw_sp_span_respin(mlxsw_sp);
 
 	switch (fib_work->event) {
-	case FIB_EVENT_ENTRY_REPLACE: /* fall through */
-	case FIB_EVENT_ENTRY_APPEND: /* fall through */
-	case FIB_EVENT_ENTRY_ADD:
-		replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE;
-		append = fib_work->event == FIB_EVENT_ENTRY_APPEND;
-		err = mlxsw_sp_router_fib4_add(mlxsw_sp, &fib_work->fen_info,
-					       replace, append);
+	case FIB_EVENT_ENTRY_REPLACE_TMP:
+		err = mlxsw_sp_router_fib4_replace(mlxsw_sp,
+						   &fib_work->fen_info);
 		if (err)
 			mlxsw_sp_router_fib_abort(mlxsw_sp);
 		fib_info_put(fib_work->fen_info.fi);
 		break;
-	case FIB_EVENT_ENTRY_DEL:
+	case FIB_EVENT_ENTRY_DEL_TMP:
 		mlxsw_sp_router_fib4_del(mlxsw_sp, &fib_work->fen_info);
 		fib_info_put(fib_work->fen_info.fi);
 		break;
@@ -6210,10 +6111,8 @@ static void mlxsw_sp_router_fib4_event(struct mlxsw_sp_fib_event_work *fib_work,
 	struct fib_nh_notifier_info *fnh_info;
 
 	switch (fib_work->event) {
-	case FIB_EVENT_ENTRY_REPLACE: /* fall through */
-	case FIB_EVENT_ENTRY_APPEND: /* fall through */
-	case FIB_EVENT_ENTRY_ADD: /* fall through */
-	case FIB_EVENT_ENTRY_DEL:
+	case FIB_EVENT_ENTRY_REPLACE_TMP: /* fall through */
+	case FIB_EVENT_ENTRY_DEL_TMP:
 		fen_info = container_of(info, struct fib_entry_notifier_info,
 					info);
 		fib_work->fen_info = *fen_info;
@@ -6343,9 +6242,9 @@ static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
 		err = mlxsw_sp_router_fib_rule_event(event, info,
 						     router->mlxsw_sp);
 		return notifier_from_errno(err);
-	case FIB_EVENT_ENTRY_ADD:
+	case FIB_EVENT_ENTRY_ADD: /* fall through */
 	case FIB_EVENT_ENTRY_REPLACE: /* fall through */
-	case FIB_EVENT_ENTRY_APPEND:  /* fall through */
+	case FIB_EVENT_ENTRY_REPLACE_TMP:
 		if (router->aborted) {
 			NL_SET_ERR_MSG_MOD(info->extack, "FIB offload was aborted. Not configuring route");
 			return notifier_from_errno(-EINVAL);
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH net-next 9/9] ipv4: Remove old route notifications and convert listeners
  2019-12-10 17:23 [PATCH net-next 0/9] Simplify IPv4 route offload API Ido Schimmel
                   ` (7 preceding siblings ...)
  2019-12-10 17:24 ` [PATCH net-next 8/9] mlxsw: spectrum_router: Start using new IPv4 route notifications Ido Schimmel
@ 2019-12-10 17:24 ` Ido Schimmel
  8 siblings, 0 replies; 21+ messages in thread
From: Ido Schimmel @ 2019-12-10 17:24 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, roopa, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Unlike mlxsw, the other listeners to the FIB notification chain do not
require any special modifications as they never considered multiple
identical routes.

This patch removes the old route notifications and converts all the
listeners to use the new replace / delete notifications.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../net/ethernet/mellanox/mlx5/core/lag_mp.c  |  4 --
 .../ethernet/mellanox/mlxsw/spectrum_router.c | 11 +++---
 drivers/net/ethernet/rocker/rocker_main.c     |  4 +-
 drivers/net/netdevsim/fib.c                   |  4 +-
 include/net/fib_notifier.h                    |  2 -
 net/ipv4/fib_trie.c                           | 38 ++++---------------
 6 files changed, 16 insertions(+), 47 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c b/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c
index b70afa310ad2..416676c35b1f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c
@@ -200,8 +200,6 @@ static void mlx5_lag_fib_update(struct work_struct *work)
 	rtnl_lock();
 	switch (fib_work->event) {
 	case FIB_EVENT_ENTRY_REPLACE: /* fall through */
-	case FIB_EVENT_ENTRY_APPEND: /* fall through */
-	case FIB_EVENT_ENTRY_ADD: /* fall through */
 	case FIB_EVENT_ENTRY_DEL:
 		mlx5_lag_fib_route_event(ldev, fib_work->event,
 					 fib_work->fen_info.fi);
@@ -259,8 +257,6 @@ static int mlx5_lag_fib_event(struct notifier_block *nb,
 
 	switch (event) {
 	case FIB_EVENT_ENTRY_REPLACE: /* fall through */
-	case FIB_EVENT_ENTRY_APPEND: /* fall through */
-	case FIB_EVENT_ENTRY_ADD: /* fall through */
 	case FIB_EVENT_ENTRY_DEL:
 		fen_info = container_of(info, struct fib_entry_notifier_info,
 					info);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 396b27b9cdb4..bba1c8215d06 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -6007,14 +6007,14 @@ static void mlxsw_sp_router_fib4_event_work(struct work_struct *work)
 	mlxsw_sp_span_respin(mlxsw_sp);
 
 	switch (fib_work->event) {
-	case FIB_EVENT_ENTRY_REPLACE_TMP:
+	case FIB_EVENT_ENTRY_REPLACE:
 		err = mlxsw_sp_router_fib4_replace(mlxsw_sp,
 						   &fib_work->fen_info);
 		if (err)
 			mlxsw_sp_router_fib_abort(mlxsw_sp);
 		fib_info_put(fib_work->fen_info.fi);
 		break;
-	case FIB_EVENT_ENTRY_DEL_TMP:
+	case FIB_EVENT_ENTRY_DEL:
 		mlxsw_sp_router_fib4_del(mlxsw_sp, &fib_work->fen_info);
 		fib_info_put(fib_work->fen_info.fi);
 		break;
@@ -6111,8 +6111,8 @@ static void mlxsw_sp_router_fib4_event(struct mlxsw_sp_fib_event_work *fib_work,
 	struct fib_nh_notifier_info *fnh_info;
 
 	switch (fib_work->event) {
-	case FIB_EVENT_ENTRY_REPLACE_TMP: /* fall through */
-	case FIB_EVENT_ENTRY_DEL_TMP:
+	case FIB_EVENT_ENTRY_REPLACE: /* fall through */
+	case FIB_EVENT_ENTRY_DEL:
 		fen_info = container_of(info, struct fib_entry_notifier_info,
 					info);
 		fib_work->fen_info = *fen_info;
@@ -6243,8 +6243,7 @@ static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
 						     router->mlxsw_sp);
 		return notifier_from_errno(err);
 	case FIB_EVENT_ENTRY_ADD: /* fall through */
-	case FIB_EVENT_ENTRY_REPLACE: /* fall through */
-	case FIB_EVENT_ENTRY_REPLACE_TMP:
+	case FIB_EVENT_ENTRY_REPLACE:
 		if (router->aborted) {
 			NL_SET_ERR_MSG_MOD(info->extack, "FIB offload was aborted. Not configuring route");
 			return notifier_from_errno(-EINVAL);
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index bc4f951315da..7585cd2270ba 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -2159,7 +2159,7 @@ static void rocker_router_fib_event_work(struct work_struct *work)
 	/* Protect internal structures from changes */
 	rtnl_lock();
 	switch (fib_work->event) {
-	case FIB_EVENT_ENTRY_ADD:
+	case FIB_EVENT_ENTRY_REPLACE:
 		err = rocker_world_fib4_add(rocker, &fib_work->fen_info);
 		if (err)
 			rocker_world_fib4_abort(rocker);
@@ -2201,7 +2201,7 @@ static int rocker_router_fib_event(struct notifier_block *nb,
 	fib_work->event = event;
 
 	switch (event) {
-	case FIB_EVENT_ENTRY_ADD: /* fall through */
+	case FIB_EVENT_ENTRY_REPLACE: /* fall through */
 	case FIB_EVENT_ENTRY_DEL:
 		if (info->family == AF_INET) {
 			struct fib_entry_notifier_info *fen_info = ptr;
diff --git a/drivers/net/netdevsim/fib.c b/drivers/net/netdevsim/fib.c
index 13540dee7364..4e02a4231fcb 100644
--- a/drivers/net/netdevsim/fib.c
+++ b/drivers/net/netdevsim/fib.c
@@ -177,10 +177,10 @@ static int nsim_fib_event_nb(struct notifier_block *nb, unsigned long event,
 					  event == FIB_EVENT_RULE_ADD);
 		break;
 
+	case FIB_EVENT_ENTRY_REPLACE:  /* fall through */
 	case FIB_EVENT_ENTRY_ADD:  /* fall through */
 	case FIB_EVENT_ENTRY_DEL:
-		err = nsim_fib_event(data, info,
-				     event == FIB_EVENT_ENTRY_ADD);
+		err = nsim_fib_event(data, info, event != FIB_EVENT_ENTRY_DEL);
 		break;
 	}
 
diff --git a/include/net/fib_notifier.h b/include/net/fib_notifier.h
index b3c54325caec..6d59221ff05a 100644
--- a/include/net/fib_notifier.h
+++ b/include/net/fib_notifier.h
@@ -23,8 +23,6 @@ enum fib_event_type {
 	FIB_EVENT_NH_DEL,
 	FIB_EVENT_VIF_ADD,
 	FIB_EVENT_VIF_DEL,
-	FIB_EVENT_ENTRY_REPLACE_TMP,
-	FIB_EVENT_ENTRY_DEL_TMP,
 };
 
 struct fib_notifier_ops {
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index eff45e7795ba..ed9141d4725a 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1143,7 +1143,6 @@ static void fib_remove_alias(struct trie *t, struct key_vector *tp,
 int fib_table_insert(struct net *net, struct fib_table *tb,
 		     struct fib_config *cfg, struct netlink_ext_ack *extack)
 {
-	enum fib_event_type event = FIB_EVENT_ENTRY_ADD;
 	struct trie *t = (struct trie *)tb->tb_data;
 	struct fib_alias *fa, *new_fa;
 	struct key_vector *l, *tp;
@@ -1242,19 +1241,13 @@ int fib_table_insert(struct net *net, struct fib_table *tb,
 						 tb->tb_id) == fa) {
 				enum fib_event_type fib_event;
 
-				fib_event = FIB_EVENT_ENTRY_REPLACE_TMP;
+				fib_event = FIB_EVENT_ENTRY_REPLACE;
 				err = call_fib_entry_notifiers(net, fib_event,
 							       key, plen,
 							       new_fa, extack);
 				if (err)
 					goto out_free_new_fa;
 			}
-			err = call_fib_entry_notifiers(net,
-						       FIB_EVENT_ENTRY_REPLACE,
-						       key, plen, new_fa,
-						       extack);
-			if (err)
-				goto out_free_new_fa;
 
 			rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen,
 				  tb->tb_id, &cfg->fc_nlinfo, nlflags);
@@ -1276,12 +1269,10 @@ int fib_table_insert(struct net *net, struct fib_table *tb,
 		if (fa_match)
 			goto out;
 
-		if (cfg->fc_nlflags & NLM_F_APPEND) {
-			event = FIB_EVENT_ENTRY_APPEND;
+		if (cfg->fc_nlflags & NLM_F_APPEND)
 			nlflags |= NLM_F_APPEND;
-		} else {
+		else
 			fa = fa_first;
-		}
 	}
 	err = -ENOENT;
 	if (!(cfg->fc_nlflags & NLM_F_CREATE))
@@ -1315,15 +1306,12 @@ int fib_table_insert(struct net *net, struct fib_table *tb,
 	    new_fa) {
 		enum fib_event_type fib_event;
 
-		fib_event = FIB_EVENT_ENTRY_REPLACE_TMP;
+		fib_event = FIB_EVENT_ENTRY_REPLACE;
 		err = call_fib_entry_notifiers(net, fib_event, key, plen,
 					       new_fa, extack);
 		if (err)
 			goto out_remove_new_fa;
 	}
-	err = call_fib_entry_notifiers(net, event, key, plen, new_fa, extack);
-	if (err)
-		goto out_remove_new_fa;
 
 	if (!plen)
 		tb->tb_num_default++;
@@ -1606,10 +1594,10 @@ static void fib_notify_alias_delete(struct net *net, u32 key,
 	fa_next = hlist_entry_safe(fa_to_delete->fa_list.next,
 				   struct fib_alias, fa_list);
 	if (fa_next && fa_next->fa_slen == slen && fa_next->tb_id == tb_id) {
-		fib_event = FIB_EVENT_ENTRY_REPLACE_TMP;
+		fib_event = FIB_EVENT_ENTRY_REPLACE;
 		fa_to_notify = fa_next;
 	} else {
-		fib_event = FIB_EVENT_ENTRY_DEL_TMP;
+		fib_event = FIB_EVENT_ENTRY_DEL;
 		fa_to_notify = fa_to_delete;
 	}
 	call_fib_entry_notifiers(net, fib_event, key, KEYLENGTH - slen,
@@ -1670,8 +1658,6 @@ int fib_table_delete(struct net *net, struct fib_table *tb,
 		return -ESRCH;
 
 	fib_notify_alias_delete(net, key, &l->leaf, fa_to_delete, extack);
-	call_fib_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, key, plen,
-				 fa_to_delete, extack);
 	rtmsg_fib(RTM_DELROUTE, htonl(key), fa_to_delete, plen, tb->tb_id,
 		  &cfg->fc_nlinfo, 0);
 
@@ -1997,10 +1983,6 @@ int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all)
 
 			fib_notify_alias_delete(net, n->key, &n->leaf, fa,
 						NULL);
-			call_fib_entry_notifiers(net, FIB_EVENT_ENTRY_DEL,
-						 n->key,
-						 KEYLENGTH - fa->fa_slen, fa,
-						 NULL);
 			hlist_del_rcu(&fa->fa_list);
 			fib_release_info(fa->fa_info);
 			alias_free_mem_rcu(fa);
@@ -2111,17 +2093,11 @@ static int fib_leaf_notify(struct key_vector *l, struct fib_table *tb,
 		if (tb->tb_id != fa->tb_id)
 			continue;
 
-		err = call_fib_entry_notifier(nb, FIB_EVENT_ENTRY_ADD, l->key,
-					      KEYLENGTH - fa->fa_slen,
-					      fa, extack);
-		if (err)
-			return err;
-
 		if (fa->fa_slen == last_slen)
 			continue;
 
 		last_slen = fa->fa_slen;
-		err = call_fib_entry_notifier(nb, FIB_EVENT_ENTRY_REPLACE_TMP,
+		err = call_fib_entry_notifier(nb, FIB_EVENT_ENTRY_REPLACE,
 					      l->key, KEYLENGTH - fa->fa_slen,
 					      fa, extack);
 		if (err)
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next 2/9] ipv4: Notify route after insertion to the routing table
  2019-12-10 17:23 ` [PATCH net-next 2/9] ipv4: Notify route after insertion to the routing table Ido Schimmel
@ 2019-12-11 17:34   ` David Ahern
  0 siblings, 0 replies; 21+ messages in thread
From: David Ahern @ 2019-12-11 17:34 UTC (permalink / raw)
  To: Ido Schimmel, netdev; +Cc: davem, jiri, roopa, mlxsw, Ido Schimmel

On 12/10/19 10:23 AM, Ido Schimmel wrote:
> From: Ido Schimmel <idosch@mellanox.com>
> 
> Currently, a new route is notified in the FIB notification chain before
> it is inserted to the FIB alias list.
> 
> Subsequent patches will use the placement of the new route in the
> ordered FIB alias list in order to determine if the route should be
> notified or not.
> 
> As a preparatory step, change the order so that the route is first
> inserted into the FIB alias list and only then notified.
> 
> Signed-off-by: Ido Schimmel <idosch@mellanox.com>
> ---
>  net/ipv4/fib_trie.c | 29 ++++++++++++++---------------
>  1 file changed, 14 insertions(+), 15 deletions(-)
> 

Reviewed-by: David Ahern <dsahern@gmail.com>



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next 3/9] ipv4: Notify route if replacing currently offloaded one
  2019-12-10 17:23 ` [PATCH net-next 3/9] ipv4: Notify route if replacing currently offloaded one Ido Schimmel
@ 2019-12-11 17:40   ` David Ahern
  2019-12-11 19:47     ` Ido Schimmel
  0 siblings, 1 reply; 21+ messages in thread
From: David Ahern @ 2019-12-11 17:40 UTC (permalink / raw)
  To: Ido Schimmel, netdev; +Cc: davem, jiri, roopa, mlxsw, Ido Schimmel

On 12/10/19 10:23 AM, Ido Schimmel wrote:
> From: Ido Schimmel <idosch@mellanox.com>
> 
> When replacing a route, its replacement should only be notified in case
> the replaced route is of any interest to listeners. In other words, if
> the replaced route is currently used in the data path, which means it is
> the first route in the FIB alias list with the given {prefix, prefix
> length, table ID}.
> 
> Signed-off-by: Ido Schimmel <idosch@mellanox.com>
> ---
>  net/ipv4/fib_trie.c | 32 ++++++++++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
> 
> diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
> index 9264d6628e9f..6822aa90657a 100644
> --- a/net/ipv4/fib_trie.c
> +++ b/net/ipv4/fib_trie.c
> @@ -978,6 +978,27 @@ static struct key_vector *fib_find_node(struct trie *t,
>  	return n;
>  }
>  
> +/* Return the first fib alias matching prefix length and table ID. */
> +static struct fib_alias *fib_find_first_alias(struct hlist_head *fah, u8 slen,
> +					      u32 tb_id)
> +{
> +	struct fib_alias *fa;
> +
> +	hlist_for_each_entry(fa, fah, fa_list) {
> +		if (fa->fa_slen < slen)
> +			continue;
> +		if (fa->fa_slen != slen)
> +			break;
> +		if (fa->tb_id > tb_id)
> +			continue;
> +		if (fa->tb_id != tb_id)
> +			break;
> +		return fa;

Rather than duplicating fib_find_alias, how about adding a 'bool
find_first' argument and bail on it:

		if (find_first)
			return fa;

		continue to tos and priority compares.

> +	}
> +
> +	return NULL;
> +}
> +
>  /* Return the first fib alias matching TOS with
>   * priority less than or equal to PRIO.
>   */
> @@ -1217,6 +1238,17 @@ int fib_table_insert(struct net *net, struct fib_table *tb,
>  			new_fa->tb_id = tb->tb_id;
>  			new_fa->fa_default = -1;
>  
> +			if (fib_find_first_alias(&l->leaf, fa->fa_slen,
> +						 tb->tb_id) == fa) {
> +				enum fib_event_type fib_event;
> +
> +				fib_event = FIB_EVENT_ENTRY_REPLACE_TMP;
> +				err = call_fib_entry_notifiers(net, fib_event,
> +							       key, plen,
> +							       new_fa, extack);
> +				if (err)
> +					goto out_free_new_fa;
> +			}
>  			err = call_fib_entry_notifiers(net,
>  						       FIB_EVENT_ENTRY_REPLACE,
>  						       key, plen, new_fa,
> 


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next 5/9] ipv4: Handle route deletion notification
  2019-12-10 17:23 ` [PATCH net-next 5/9] ipv4: Handle route deletion notification Ido Schimmel
@ 2019-12-11 17:44   ` David Ahern
  0 siblings, 0 replies; 21+ messages in thread
From: David Ahern @ 2019-12-11 17:44 UTC (permalink / raw)
  To: Ido Schimmel, netdev; +Cc: davem, jiri, roopa, mlxsw, Ido Schimmel

On 12/10/19 10:23 AM, Ido Schimmel wrote:
> From: Ido Schimmel <idosch@mellanox.com>
> 
> When a route is deleted we potentially need to promote the next route in
> the FIB alias list (e.g., with an higher metric). In case we find such a
> route, a replace notification is emitted. Otherwise, a delete
> notification for the deleted route.
> 
> Signed-off-by: Ido Schimmel <idosch@mellanox.com>
> ---
>  net/ipv4/fib_trie.c | 31 +++++++++++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
> 

Reviewed-by: David Ahern <dsahern@gmail.com>



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next 6/9] ipv4: Handle route deletion notification during flush
  2019-12-10 17:23 ` [PATCH net-next 6/9] ipv4: Handle route deletion notification during flush Ido Schimmel
@ 2019-12-11 17:46   ` David Ahern
  2019-12-11 17:52     ` David Ahern
  2019-12-11 17:52   ` David Ahern
  1 sibling, 1 reply; 21+ messages in thread
From: David Ahern @ 2019-12-11 17:46 UTC (permalink / raw)
  To: Ido Schimmel, netdev; +Cc: davem, jiri, roopa, mlxsw, Ido Schimmel

On 12/10/19 10:23 AM, Ido Schimmel wrote:
> From: Ido Schimmel <idosch@mellanox.com>
> 
> In a similar fashion to previous patch, when a route is deleted as part
> of table flushing, promote the next route in the list, if exists.
> Otherwise, simply emit a delete notification.

I am not following your point on a flush. If all routes are getting
deleted, why do you need to promote the next one in the list?

> 
> Signed-off-by: Ido Schimmel <idosch@mellanox.com>
> ---
>  net/ipv4/fib_trie.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
> index 2d338469d4f2..60947a44d363 100644
> --- a/net/ipv4/fib_trie.c
> +++ b/net/ipv4/fib_trie.c
> @@ -1995,6 +1995,8 @@ int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all)
>  				continue;
>  			}
>  
> +			fib_notify_alias_delete(net, n->key, &n->leaf, fa,
> +						NULL);
>  			call_fib_entry_notifiers(net, FIB_EVENT_ENTRY_DEL,
>  						 n->key,
>  						 KEYLENGTH - fa->fa_slen, fa,
> 


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next 6/9] ipv4: Handle route deletion notification during flush
  2019-12-11 17:46   ` David Ahern
@ 2019-12-11 17:52     ` David Ahern
  0 siblings, 0 replies; 21+ messages in thread
From: David Ahern @ 2019-12-11 17:52 UTC (permalink / raw)
  To: Ido Schimmel, netdev; +Cc: davem, jiri, roopa, mlxsw, Ido Schimmel

On 12/11/19 10:46 AM, David Ahern wrote:
> On 12/10/19 10:23 AM, Ido Schimmel wrote:
>> From: Ido Schimmel <idosch@mellanox.com>
>>
>> In a similar fashion to previous patch, when a route is deleted as part
>> of table flushing, promote the next route in the list, if exists.
>> Otherwise, simply emit a delete notification.
> 
> I am not following your point on a flush. If all routes are getting
> deleted, why do you need to promote the next one in the list?

never mind. I see. The second notifier gets deleted in patch 9 and the
new notifier is needed to remove the offloaded route.

> 
>>
>> Signed-off-by: Ido Schimmel <idosch@mellanox.com>
>> ---
>>  net/ipv4/fib_trie.c | 2 ++
>>  1 file changed, 2 insertions(+)
>>
>> diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
>> index 2d338469d4f2..60947a44d363 100644
>> --- a/net/ipv4/fib_trie.c
>> +++ b/net/ipv4/fib_trie.c
>> @@ -1995,6 +1995,8 @@ int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all)
>>  				continue;
>>  			}
>>  
>> +			fib_notify_alias_delete(net, n->key, &n->leaf, fa,
>> +						NULL);
>>  			call_fib_entry_notifiers(net, FIB_EVENT_ENTRY_DEL,
>>  						 n->key,
>>  						 KEYLENGTH - fa->fa_slen, fa,
>>
> 


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next 6/9] ipv4: Handle route deletion notification during flush
  2019-12-10 17:23 ` [PATCH net-next 6/9] ipv4: Handle route deletion notification during flush Ido Schimmel
  2019-12-11 17:46   ` David Ahern
@ 2019-12-11 17:52   ` David Ahern
  1 sibling, 0 replies; 21+ messages in thread
From: David Ahern @ 2019-12-11 17:52 UTC (permalink / raw)
  To: Ido Schimmel, netdev; +Cc: davem, jiri, roopa, mlxsw, Ido Schimmel

On 12/10/19 10:23 AM, Ido Schimmel wrote:
> From: Ido Schimmel <idosch@mellanox.com>
> 
> In a similar fashion to previous patch, when a route is deleted as part
> of table flushing, promote the next route in the list, if exists.
> Otherwise, simply emit a delete notification.
> 
> Signed-off-by: Ido Schimmel <idosch@mellanox.com>
> ---
>  net/ipv4/fib_trie.c | 2 ++
>  1 file changed, 2 insertions(+)
> 

Reviewed-by: David Ahern <dsahern@gmail.com>



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next 7/9] ipv4: Only Replay routes of interest to new listeners
  2019-12-10 17:24 ` [PATCH net-next 7/9] ipv4: Only Replay routes of interest to new listeners Ido Schimmel
@ 2019-12-11 17:57   ` David Ahern
  0 siblings, 0 replies; 21+ messages in thread
From: David Ahern @ 2019-12-11 17:57 UTC (permalink / raw)
  To: Ido Schimmel, netdev; +Cc: davem, jiri, roopa, mlxsw, Ido Schimmel

On 12/10/19 10:24 AM, Ido Schimmel wrote:
> From: Ido Schimmel <idosch@mellanox.com>
> 
> When a new listener is registered to the FIB notification chain it
> receives a dump of all the available routes in the system. Instead, make
> sure to only replay the IPv4 routes that are actually used in the data
> path and are of any interest to the new listener.
> 
> Signed-off-by: Ido Schimmel <idosch@mellanox.com>
> ---
>  net/ipv4/fib_trie.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 

Reviewed-by: David Ahern <dsahern@gmail.com>



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next 8/9] mlxsw: spectrum_router: Start using new IPv4 route notifications
  2019-12-10 17:24 ` [PATCH net-next 8/9] mlxsw: spectrum_router: Start using new IPv4 route notifications Ido Schimmel
@ 2019-12-11 17:58   ` David Ahern
  0 siblings, 0 replies; 21+ messages in thread
From: David Ahern @ 2019-12-11 17:58 UTC (permalink / raw)
  To: Ido Schimmel, netdev; +Cc: davem, jiri, roopa, mlxsw, Ido Schimmel

On 12/10/19 10:24 AM, Ido Schimmel wrote:
>  .../ethernet/mellanox/mlxsw/spectrum_router.c | 141 +++---------------
>  1 file changed, 20 insertions(+), 121 deletions(-)
> 
>

that's a good stat line.


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next 3/9] ipv4: Notify route if replacing currently offloaded one
  2019-12-11 17:40   ` David Ahern
@ 2019-12-11 19:47     ` Ido Schimmel
  0 siblings, 0 replies; 21+ messages in thread
From: Ido Schimmel @ 2019-12-11 19:47 UTC (permalink / raw)
  To: David Ahern; +Cc: netdev, davem, jiri, roopa, mlxsw, Ido Schimmel

On Wed, Dec 11, 2019 at 10:40:09AM -0700, David Ahern wrote:
> On 12/10/19 10:23 AM, Ido Schimmel wrote:
> > +/* Return the first fib alias matching prefix length and table ID. */
> > +static struct fib_alias *fib_find_first_alias(struct hlist_head *fah, u8 slen,
> > +					      u32 tb_id)
> > +{
> > +	struct fib_alias *fa;
> > +
> > +	hlist_for_each_entry(fa, fah, fa_list) {
> > +		if (fa->fa_slen < slen)
> > +			continue;
> > +		if (fa->fa_slen != slen)
> > +			break;
> > +		if (fa->tb_id > tb_id)
> > +			continue;
> > +		if (fa->tb_id != tb_id)
> > +			break;
> > +		return fa;
> 
> Rather than duplicating fib_find_alias, how about adding a 'bool
> find_first' argument and bail on it:
> 
> 		if (find_first)
> 			return fa;
> 
> 		continue to tos and priority compares.

Sure, I'll change this tomorrow morning.

Thanks, David!

> 
> > +	}
> > +
> > +	return NULL;
> > +}

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next 1/9] net: fib_notifier: Add temporary events to the FIB notification chain
  2019-12-23 13:28 ` [PATCH net-next 1/9] net: fib_notifier: Add temporary events to the FIB notification chain Ido Schimmel
@ 2019-12-24 16:40   ` David Ahern
  0 siblings, 0 replies; 21+ messages in thread
From: David Ahern @ 2019-12-24 16:40 UTC (permalink / raw)
  To: Ido Schimmel, netdev; +Cc: davem, roopa, jakub.kicinski, jiri, Ido Schimmel

On 12/23/19 6:28 AM, Ido Schimmel wrote:
> From: Ido Schimmel <idosch@mellanox.com>
> 
> Subsequent patches are going to simplify the IPv6 route offload API,
> which will only use three events - replace, delete and append.
> 
> Introduce a temporary version of replace and delete in order to make the
> conversion easier to review. Note that append does not need a temporary
> version, as it is currently not used.
> 
> Signed-off-by: Ido Schimmel <idosch@mellanox.com>
> Reviewed-by: Jiri Pirko <jiri@mellanox.com>
> ---
>  include/net/fib_notifier.h | 2 ++
>  1 file changed, 2 insertions(+)
> 

Reviewed-by: David Ahern <dsahern@gmail.com>



^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH net-next 1/9] net: fib_notifier: Add temporary events to the FIB notification chain
  2019-12-23 13:28 [PATCH net-next 0/9] Simplify IPv6 route offload API Ido Schimmel
@ 2019-12-23 13:28 ` Ido Schimmel
  2019-12-24 16:40   ` David Ahern
  0 siblings, 1 reply; 21+ messages in thread
From: Ido Schimmel @ 2019-12-23 13:28 UTC (permalink / raw)
  To: netdev; +Cc: davem, dsahern, roopa, jakub.kicinski, jiri, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Subsequent patches are going to simplify the IPv6 route offload API,
which will only use three events - replace, delete and append.

Introduce a temporary version of replace and delete in order to make the
conversion easier to review. Note that append does not need a temporary
version, as it is currently not used.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
---
 include/net/fib_notifier.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/net/fib_notifier.h b/include/net/fib_notifier.h
index 6d59221ff05a..b3c54325caec 100644
--- a/include/net/fib_notifier.h
+++ b/include/net/fib_notifier.h
@@ -23,6 +23,8 @@ enum fib_event_type {
 	FIB_EVENT_NH_DEL,
 	FIB_EVENT_VIF_ADD,
 	FIB_EVENT_VIF_DEL,
+	FIB_EVENT_ENTRY_REPLACE_TMP,
+	FIB_EVENT_ENTRY_DEL_TMP,
 };
 
 struct fib_notifier_ops {
-- 
2.24.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2019-12-24 16:40 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-10 17:23 [PATCH net-next 0/9] Simplify IPv4 route offload API Ido Schimmel
2019-12-10 17:23 ` [PATCH net-next 1/9] net: fib_notifier: Add temporary events to the FIB notification chain Ido Schimmel
2019-12-10 17:23 ` [PATCH net-next 2/9] ipv4: Notify route after insertion to the routing table Ido Schimmel
2019-12-11 17:34   ` David Ahern
2019-12-10 17:23 ` [PATCH net-next 3/9] ipv4: Notify route if replacing currently offloaded one Ido Schimmel
2019-12-11 17:40   ` David Ahern
2019-12-11 19:47     ` Ido Schimmel
2019-12-10 17:23 ` [PATCH net-next 4/9] ipv4: Notify newly added route if should be offloaded Ido Schimmel
2019-12-10 17:23 ` [PATCH net-next 5/9] ipv4: Handle route deletion notification Ido Schimmel
2019-12-11 17:44   ` David Ahern
2019-12-10 17:23 ` [PATCH net-next 6/9] ipv4: Handle route deletion notification during flush Ido Schimmel
2019-12-11 17:46   ` David Ahern
2019-12-11 17:52     ` David Ahern
2019-12-11 17:52   ` David Ahern
2019-12-10 17:24 ` [PATCH net-next 7/9] ipv4: Only Replay routes of interest to new listeners Ido Schimmel
2019-12-11 17:57   ` David Ahern
2019-12-10 17:24 ` [PATCH net-next 8/9] mlxsw: spectrum_router: Start using new IPv4 route notifications Ido Schimmel
2019-12-11 17:58   ` David Ahern
2019-12-10 17:24 ` [PATCH net-next 9/9] ipv4: Remove old route notifications and convert listeners Ido Schimmel
2019-12-23 13:28 [PATCH net-next 0/9] Simplify IPv6 route offload API Ido Schimmel
2019-12-23 13:28 ` [PATCH net-next 1/9] net: fib_notifier: Add temporary events to the FIB notification chain Ido Schimmel
2019-12-24 16:40   ` David Ahern

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.