netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate
@ 2019-06-18 15:12 Ido Schimmel
  2019-06-18 15:12 ` [PATCH net-next v2 01/16] netlink: Document all fields of 'struct nl_info' Ido Schimmel
                   ` (16 more replies)
  0 siblings, 17 replies; 20+ messages in thread
From: Ido Schimmel @ 2019-06-18 15:12 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, alexpe, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Unlike IPv4, an IPv6 multipath route in the kernel is composed from
multiple sibling routes, each representing a single nexthop.

Therefore, an addition of a multipath route with N nexthops translates
to N in-kernel notifications. This is inefficient for device drivers
that need to program the route to the underlying device. Each time a new
nexthop is appended, a new nexthop group needs to be constructed and the
old one deleted.

This patchset improves the situation by sending a single notification
for a multipath route addition / deletion instead of one per-nexthop.
When adding thousands of multipath routes with 16 nexthops, I measured
an improvement of about x10 in the insertion rate.

Patches #1-#3 add a flag that indicates that in-kernel notifications
need to be suppressed and extend the IPv6 FIB notification info with
information about the number of sibling routes that are being notified.

Patches #4-#5 adjust the two current listeners to these notifications to
ignore notifications about IPv6 multipath routes.

Patches #6-#7 adds add / delete notifications for IPv6 multipath routes.

Patches #8-#14 do the same for mlxsw.

Patch #15 finally removes the limitations added in patches #4-#5 and
stops the kernel from sending a notification for each added / deleted
nexthop.

Patch #16 adds test cases.

v2 (David Ahern):
* Remove patch adjusting netdevsim to consume resources for each
  fib6_info. Instead, consume one resource for the entire multipath
  route
* Remove 'multipath_rt' usage in patch #10
* Remove 'multipath_rt' from 'struct fib6_entry_notifier_info' in patch
  #15. The member is only removed in this patch to prevent drivers from
  processing multipath routes twice during the series

Ido Schimmel (16):
  netlink: Document all fields of 'struct nl_info'
  netlink: Add field to skip in-kernel notifications
  ipv6: Extend notifier info for multipath routes
  mlxsw: spectrum_router: Ignore IPv6 multipath notifications
  netdevsim: Ignore IPv6 multipath notifications
  ipv6: Add IPv6 multipath notifications for add / replace
  ipv6: Add IPv6 multipath notification for route delete
  mlxsw: spectrum_router: Remove processing of IPv6 append notifications
  mlxsw: spectrum_router: Prepare function to return errors
  mlxsw: spectrum_router: Pass multiple routes to work item
  mlxsw: spectrum_router: Adjust IPv6 replace logic to new notifications
  mlxsw: spectrum_router: Pass array of routes to route handling
    functions
  mlxsw: spectrum_router: Add / delete multiple IPv6 nexthops
  mlxsw: spectrum_router: Create IPv6 multipath routes in one go
  ipv6: Stop sending in-kernel notifications for each nexthop
  selftests: mlxsw: Add a test for FIB offload indication

 .../ethernet/mellanox/mlxsw/spectrum_router.c | 209 ++++++++---
 include/net/ip6_fib.h                         |   6 +
 include/net/netlink.h                         |   6 +-
 net/ipv6/ip6_fib.c                            |  44 ++-
 net/ipv6/route.c                              |  21 ++
 .../drivers/net/mlxsw/fib_offload.sh          | 349 ++++++++++++++++++
 6 files changed, 567 insertions(+), 68 deletions(-)
 create mode 100755 tools/testing/selftests/drivers/net/mlxsw/fib_offload.sh

-- 
2.20.1


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

* [PATCH net-next v2 01/16] netlink: Document all fields of 'struct nl_info'
  2019-06-18 15:12 [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate Ido Schimmel
@ 2019-06-18 15:12 ` Ido Schimmel
  2019-06-18 15:12 ` [PATCH net-next v2 02/16] netlink: Add field to skip in-kernel notifications Ido Schimmel
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Ido Schimmel @ 2019-06-18 15:12 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, alexpe, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Some fields were not documented. Add documentation.

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

diff --git a/include/net/netlink.h b/include/net/netlink.h
index 28ece67f5312..ce66e43b9b6a 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -378,7 +378,9 @@ struct nla_policy {
 /**
  * struct nl_info - netlink source information
  * @nlh: Netlink message header of original request
+ * @nl_net: Network namespace
  * @portid: Netlink PORTID of requesting application
+ * @skip_notify: Skip netlink notifications to user space
  */
 struct nl_info {
 	struct nlmsghdr		*nlh;
-- 
2.20.1


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

* [PATCH net-next v2 02/16] netlink: Add field to skip in-kernel notifications
  2019-06-18 15:12 [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate Ido Schimmel
  2019-06-18 15:12 ` [PATCH net-next v2 01/16] netlink: Document all fields of 'struct nl_info' Ido Schimmel
@ 2019-06-18 15:12 ` Ido Schimmel
  2019-06-18 15:12 ` [PATCH net-next v2 03/16] ipv6: Extend notifier info for multipath routes Ido Schimmel
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Ido Schimmel @ 2019-06-18 15:12 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, alexpe, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

The struct includes a 'skip_notify' flag that indicates if netlink
notifications to user space should be suppressed. As explained in commit
3b1137fe7482 ("net: ipv6: Change notifications for multipath add to
RTA_MULTIPATH"), this is useful to suppress per-nexthop RTM_NEWROUTE
notifications when an IPv6 multipath route is added / deleted. Instead,
one notification is sent for the entire multipath route.

This concept is also useful for in-kernel notifications. Sending one
in-kernel notification for the addition / deletion of an IPv6 multipath
route - instead of one per-nexthop - provides a significant increase in
the insertion / deletion rate to underlying devices.

Add a 'skip_notify_kernel' flag to suppress in-kernel notifications.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Reviewed-by: David Ahern <dsahern@gmail.com>
---
 include/net/netlink.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/include/net/netlink.h b/include/net/netlink.h
index ce66e43b9b6a..e4650e5b64a1 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -381,12 +381,14 @@ struct nla_policy {
  * @nl_net: Network namespace
  * @portid: Netlink PORTID of requesting application
  * @skip_notify: Skip netlink notifications to user space
+ * @skip_notify_kernel: Skip selected in-kernel notifications
  */
 struct nl_info {
 	struct nlmsghdr		*nlh;
 	struct net		*nl_net;
 	u32			portid;
-	bool			skip_notify;
+	u8			skip_notify:1,
+				skip_notify_kernel:1;
 };
 
 /**
-- 
2.20.1


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

* [PATCH net-next v2 03/16] ipv6: Extend notifier info for multipath routes
  2019-06-18 15:12 [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate Ido Schimmel
  2019-06-18 15:12 ` [PATCH net-next v2 01/16] netlink: Document all fields of 'struct nl_info' Ido Schimmel
  2019-06-18 15:12 ` [PATCH net-next v2 02/16] netlink: Add field to skip in-kernel notifications Ido Schimmel
@ 2019-06-18 15:12 ` Ido Schimmel
  2019-06-18 15:26   ` David Ahern
  2019-06-18 15:12 ` [PATCH net-next v2 04/16] mlxsw: spectrum_router: Ignore IPv6 multipath notifications Ido Schimmel
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 20+ messages in thread
From: Ido Schimmel @ 2019-06-18 15:12 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, alexpe, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Extend the IPv6 FIB notifier info with number of sibling routes being
notified.

This will later allow listeners to process one notification for a
multipath routes instead of N, where N is the number of nexthops.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 include/net/ip6_fib.h |  7 +++++++
 net/ipv6/ip6_fib.c    | 17 +++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 1e92f1500b87..7c3d5ab05879 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -377,6 +377,8 @@ typedef struct rt6_info *(*pol_lookup_t)(struct net *,
 struct fib6_entry_notifier_info {
 	struct fib_notifier_info info; /* must be first */
 	struct fib6_info *rt;
+	unsigned int nsiblings;
+	bool multipath_rt;
 };
 
 /*
@@ -450,6 +452,11 @@ int call_fib6_entry_notifiers(struct net *net,
 			      enum fib_event_type event_type,
 			      struct fib6_info *rt,
 			      struct netlink_ext_ack *extack);
+int call_fib6_multipath_entry_notifiers(struct net *net,
+					enum fib_event_type event_type,
+					struct fib6_info *rt,
+					unsigned int nsiblings,
+					struct netlink_ext_ack *extack);
 void fib6_rt_update(struct net *net, struct fib6_info *rt,
 		    struct nl_info *info);
 void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info,
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 1cce2082279c..df08ba8fe6fc 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -381,6 +381,23 @@ int call_fib6_entry_notifiers(struct net *net,
 	return call_fib6_notifiers(net, event_type, &info.info);
 }
 
+int call_fib6_multipath_entry_notifiers(struct net *net,
+					enum fib_event_type event_type,
+					struct fib6_info *rt,
+					unsigned int nsiblings,
+					struct netlink_ext_ack *extack)
+{
+	struct fib6_entry_notifier_info info = {
+		.info.extack = extack,
+		.rt = rt,
+		.nsiblings = nsiblings,
+		.multipath_rt = true,
+	};
+
+	rt->fib6_table->fib_seq++;
+	return call_fib6_notifiers(net, event_type, &info.info);
+}
+
 struct fib6_dump_arg {
 	struct net *net;
 	struct notifier_block *nb;
-- 
2.20.1


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

* [PATCH net-next v2 04/16] mlxsw: spectrum_router: Ignore IPv6 multipath notifications
  2019-06-18 15:12 [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate Ido Schimmel
                   ` (2 preceding siblings ...)
  2019-06-18 15:12 ` [PATCH net-next v2 03/16] ipv6: Extend notifier info for multipath routes Ido Schimmel
@ 2019-06-18 15:12 ` Ido Schimmel
  2019-06-18 15:12 ` [PATCH net-next v2 05/16] netdevsim: " Ido Schimmel
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Ido Schimmel @ 2019-06-18 15:12 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, alexpe, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

IPv6 multipath notifications are about to be sent, but mlxsw is not
ready to process them, so ignore them.

The limitation will be lifted by a subsequent patch which will also stop
the kernel from sending a notification for each nexthop.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index a6055107c5f2..ca47aa74e5d5 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -6203,6 +6203,8 @@ static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
 				NL_SET_ERR_MSG_MOD(info->extack, "IPv6 route with nexthop objects is not supported");
 				return notifier_from_errno(-EINVAL);
 			}
+			if (fen6_info->multipath_rt)
+				return NOTIFY_DONE;
 		}
 		break;
 	}
-- 
2.20.1


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

* [PATCH net-next v2 05/16] netdevsim: Ignore IPv6 multipath notifications
  2019-06-18 15:12 [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate Ido Schimmel
                   ` (3 preceding siblings ...)
  2019-06-18 15:12 ` [PATCH net-next v2 04/16] mlxsw: spectrum_router: Ignore IPv6 multipath notifications Ido Schimmel
@ 2019-06-18 15:12 ` Ido Schimmel
  2019-06-18 15:12 ` [PATCH net-next v2 06/16] ipv6: Add IPv6 multipath notifications for add / replace Ido Schimmel
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Ido Schimmel @ 2019-06-18 15:12 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, alexpe, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

In a similar fashion to previous patch, have netdevsim ignore IPv6
multipath notifications for now.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/netdevsim/fib.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/net/netdevsim/fib.c b/drivers/net/netdevsim/fib.c
index 8c57ba747772..83ba5113210d 100644
--- a/drivers/net/netdevsim/fib.c
+++ b/drivers/net/netdevsim/fib.c
@@ -190,6 +190,13 @@ static int nsim_fib_event_nb(struct notifier_block *nb, unsigned long event,
 
 	case FIB_EVENT_ENTRY_ADD:  /* fall through */
 	case FIB_EVENT_ENTRY_DEL:
+		if (info->family == AF_INET6) {
+			struct fib6_entry_notifier_info *fen6_info = ptr;
+
+			if (fen6_info->multipath_rt)
+				return NOTIFY_DONE;
+		}
+
 		err = nsim_fib_event(data, info,
 				     event == FIB_EVENT_ENTRY_ADD);
 		break;
-- 
2.20.1


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

* [PATCH net-next v2 06/16] ipv6: Add IPv6 multipath notifications for add / replace
  2019-06-18 15:12 [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate Ido Schimmel
                   ` (4 preceding siblings ...)
  2019-06-18 15:12 ` [PATCH net-next v2 05/16] netdevsim: " Ido Schimmel
@ 2019-06-18 15:12 ` Ido Schimmel
  2019-06-18 15:12 ` [PATCH net-next v2 07/16] ipv6: Add IPv6 multipath notification for route delete Ido Schimmel
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Ido Schimmel @ 2019-06-18 15:12 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, alexpe, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Emit a notification when a multipath routes is added or replace.

Note that unlike the replace notifications sent from fib6_add_rt2node(),
it is possible we are sending a 'FIB_EVENT_ENTRY_REPLACE' when a route
was merely added and not replaced.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Reviewed-by: David Ahern <dsahern@gmail.com>
---
 net/ipv6/route.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index f7257a56072a..da504d36ce54 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -4965,6 +4965,7 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
 {
 	struct fib6_info *rt_notif = NULL, *rt_last = NULL;
 	struct nl_info *info = &cfg->fc_nlinfo;
+	enum fib_event_type event_type;
 	struct fib6_config r_cfg;
 	struct rtnexthop *rtnh;
 	struct fib6_info *rt;
@@ -5042,6 +5043,11 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
 	 */
 	info->skip_notify = 1;
 
+	/* For add and replace, send one notification with all nexthops. For
+	 * append, send one notification with all appended nexthops.
+	 */
+	info->skip_notify_kernel = 1;
+
 	err_nh = NULL;
 	list_for_each_entry(nh, &rt6_nh_list, next) {
 		err = __ip6_ins_rt(nh->fib6_info, info, extack);
@@ -5078,6 +5084,15 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
 		nhn++;
 	}
 
+	event_type = replace ? FIB_EVENT_ENTRY_REPLACE : FIB_EVENT_ENTRY_ADD;
+	err = call_fib6_multipath_entry_notifiers(info->nl_net, event_type,
+						  rt_notif, nhn - 1, extack);
+	if (err) {
+		/* Delete all the siblings that were just added */
+		err_nh = NULL;
+		goto add_errout;
+	}
+
 	/* success ... tell user about new route */
 	ip6_route_mpath_notify(rt_notif, rt_last, info, nlflags);
 	goto cleanup;
-- 
2.20.1


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

* [PATCH net-next v2 07/16] ipv6: Add IPv6 multipath notification for route delete
  2019-06-18 15:12 [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate Ido Schimmel
                   ` (5 preceding siblings ...)
  2019-06-18 15:12 ` [PATCH net-next v2 06/16] ipv6: Add IPv6 multipath notifications for add / replace Ido Schimmel
@ 2019-06-18 15:12 ` Ido Schimmel
  2019-06-18 15:12 ` [PATCH net-next v2 08/16] mlxsw: spectrum_router: Remove processing of IPv6 append notifications Ido Schimmel
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Ido Schimmel @ 2019-06-18 15:12 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, alexpe, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

If all the nexthops of a multipath route are being deleted, send one
notification for the entire route, instead of one per-nexthop.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Reviewed-by: David Ahern <dsahern@gmail.com>
---
 net/ipv6/route.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index da504d36ce54..c4d285fe0adc 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -3718,6 +3718,12 @@ static int __ip6_del_rt_siblings(struct fib6_info *rt, struct fib6_config *cfg)
 				info->skip_notify = 1;
 		}
 
+		info->skip_notify_kernel = 1;
+		call_fib6_multipath_entry_notifiers(net,
+						    FIB_EVENT_ENTRY_DEL,
+						    rt,
+						    rt->fib6_nsiblings,
+						    NULL);
 		list_for_each_entry_safe(sibling, next_sibling,
 					 &rt->fib6_siblings,
 					 fib6_siblings) {
-- 
2.20.1


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

* [PATCH net-next v2 08/16] mlxsw: spectrum_router: Remove processing of IPv6 append notifications
  2019-06-18 15:12 [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate Ido Schimmel
                   ` (6 preceding siblings ...)
  2019-06-18 15:12 ` [PATCH net-next v2 07/16] ipv6: Add IPv6 multipath notification for route delete Ido Schimmel
@ 2019-06-18 15:12 ` Ido Schimmel
  2019-06-18 15:12 ` [PATCH net-next v2 09/16] mlxsw: spectrum_router: Prepare function to return errors Ido Schimmel
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Ido Schimmel @ 2019-06-18 15:12 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, alexpe, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

No such notifications are sent by the IPv6 code, so remove them.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index ca47aa74e5d5..8bfd53a1497b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -5965,7 +5965,6 @@ static void mlxsw_sp_router_fib6_event_work(struct work_struct *work)
 
 	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;
 		err = mlxsw_sp_router_fib6_add(mlxsw_sp,
@@ -6072,7 +6071,6 @@ static void mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work *fib_work,
 
 	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:
 		fen6_info = container_of(info, struct fib6_entry_notifier_info,
-- 
2.20.1


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

* [PATCH net-next v2 09/16] mlxsw: spectrum_router: Prepare function to return errors
  2019-06-18 15:12 [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate Ido Schimmel
                   ` (7 preceding siblings ...)
  2019-06-18 15:12 ` [PATCH net-next v2 08/16] mlxsw: spectrum_router: Remove processing of IPv6 append notifications Ido Schimmel
@ 2019-06-18 15:12 ` Ido Schimmel
  2019-06-18 15:12 ` [PATCH net-next v2 10/16] mlxsw: spectrum_router: Pass multiple routes to work item Ido Schimmel
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Ido Schimmel @ 2019-06-18 15:12 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, alexpe, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

The function mlxsw_sp_router_fib6_event() takes care of preparing the
needed information for the work item that actually inserts the route
into the device.

When processing an IPv6 multipath route, the function will need to
allocate an array to store pointers to all the sibling routes.

Change the function's signature to return an error code and adjust the
single call site.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum_router.c  | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 8bfd53a1497b..3e2e8be753a4 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -6064,8 +6064,8 @@ static void mlxsw_sp_router_fib4_event(struct mlxsw_sp_fib_event_work *fib_work,
 	}
 }
 
-static void mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work *fib_work,
-				       struct fib_notifier_info *info)
+static int mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work *fib_work,
+				      struct fib_notifier_info *info)
 {
 	struct fib6_entry_notifier_info *fen6_info;
 
@@ -6079,6 +6079,8 @@ static void mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work *fib_work,
 		fib6_info_hold(fib_work->fen6_info.rt);
 		break;
 	}
+
+	return 0;
 }
 
 static void
@@ -6221,7 +6223,9 @@ static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
 		break;
 	case AF_INET6:
 		INIT_WORK(&fib_work->work, mlxsw_sp_router_fib6_event_work);
-		mlxsw_sp_router_fib6_event(fib_work, info);
+		err = mlxsw_sp_router_fib6_event(fib_work, info);
+		if (err)
+			goto err_fib_event;
 		break;
 	case RTNL_FAMILY_IP6MR:
 	case RTNL_FAMILY_IPMR:
@@ -6233,6 +6237,10 @@ static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
 	mlxsw_core_schedule_work(&fib_work->work);
 
 	return NOTIFY_DONE;
+
+err_fib_event:
+	kfree(fib_work);
+	return NOTIFY_BAD;
 }
 
 struct mlxsw_sp_rif *
-- 
2.20.1


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

* [PATCH net-next v2 10/16] mlxsw: spectrum_router: Pass multiple routes to work item
  2019-06-18 15:12 [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate Ido Schimmel
                   ` (8 preceding siblings ...)
  2019-06-18 15:12 ` [PATCH net-next v2 09/16] mlxsw: spectrum_router: Prepare function to return errors Ido Schimmel
@ 2019-06-18 15:12 ` Ido Schimmel
  2019-06-18 15:12 ` [PATCH net-next v2 11/16] mlxsw: spectrum_router: Adjust IPv6 replace logic to new notifications Ido Schimmel
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Ido Schimmel @ 2019-06-18 15:12 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, alexpe, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Prepare the driver to process IPv6 multipath notifications by passing an
array of 'struct fib6_info' instead of just one route.

A reference is taken on each sibling route in order to prevent them from
being freed until they are processed by the workqueue.

v2:
* Remove 'multipath_rt' usage

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_router.c | 72 +++++++++++++++++--
 1 file changed, 65 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 3e2e8be753a4..42e0e9677b91 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -5893,10 +5893,15 @@ static void mlxsw_sp_router_fib_abort(struct mlxsw_sp *mlxsw_sp)
 		dev_warn(mlxsw_sp->bus_info->dev, "Failed to set abort trap.\n");
 }
 
+struct mlxsw_sp_fib6_event_work {
+	struct fib6_info **rt_arr;
+	unsigned int nrt6;
+};
+
 struct mlxsw_sp_fib_event_work {
 	struct work_struct work;
 	union {
-		struct fib6_entry_notifier_info fen6_info;
+		struct mlxsw_sp_fib6_event_work fib6_work;
 		struct fib_entry_notifier_info fen_info;
 		struct fib_rule_notifier_info fr_info;
 		struct fib_nh_notifier_info fnh_info;
@@ -5907,6 +5912,54 @@ struct mlxsw_sp_fib_event_work {
 	unsigned long event;
 };
 
+static int
+mlxsw_sp_router_fib6_work_init(struct mlxsw_sp_fib6_event_work *fib6_work,
+			       struct fib6_entry_notifier_info *fen6_info)
+{
+	struct fib6_info *rt = fen6_info->rt;
+	struct fib6_info **rt_arr;
+	struct fib6_info *iter;
+	unsigned int nrt6;
+	int i = 0;
+
+	nrt6 = fen6_info->nsiblings + 1;
+
+	rt_arr = kcalloc(nrt6, sizeof(struct fib6_info *), GFP_ATOMIC);
+	if (!rt_arr)
+		return -ENOMEM;
+
+	fib6_work->rt_arr = rt_arr;
+	fib6_work->nrt6 = nrt6;
+
+	rt_arr[0] = rt;
+	fib6_info_hold(rt);
+
+	if (!fen6_info->nsiblings)
+		return 0;
+
+	list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings) {
+		if (i == fen6_info->nsiblings)
+			break;
+
+		rt_arr[i + 1] = iter;
+		fib6_info_hold(iter);
+		i++;
+	}
+	WARN_ON_ONCE(i != fen6_info->nsiblings);
+
+	return 0;
+}
+
+static void
+mlxsw_sp_router_fib6_work_fini(struct mlxsw_sp_fib6_event_work *fib6_work)
+{
+	int i;
+
+	for (i = 0; i < fib6_work->nrt6; i++)
+		mlxsw_sp_rt6_release(fib6_work->rt_arr[i]);
+	kfree(fib6_work->rt_arr);
+}
+
 static void mlxsw_sp_router_fib4_event_work(struct work_struct *work)
 {
 	struct mlxsw_sp_fib_event_work *fib_work =
@@ -5968,14 +6021,16 @@ static void mlxsw_sp_router_fib6_event_work(struct work_struct *work)
 	case FIB_EVENT_ENTRY_ADD:
 		replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE;
 		err = mlxsw_sp_router_fib6_add(mlxsw_sp,
-					       fib_work->fen6_info.rt, replace);
+					       fib_work->fib6_work.rt_arr[0],
+					       replace);
 		if (err)
 			mlxsw_sp_router_fib_abort(mlxsw_sp);
-		mlxsw_sp_rt6_release(fib_work->fen6_info.rt);
+		mlxsw_sp_router_fib6_work_fini(&fib_work->fib6_work);
 		break;
 	case FIB_EVENT_ENTRY_DEL:
-		mlxsw_sp_router_fib6_del(mlxsw_sp, fib_work->fen6_info.rt);
-		mlxsw_sp_rt6_release(fib_work->fen6_info.rt);
+		mlxsw_sp_router_fib6_del(mlxsw_sp,
+					 fib_work->fib6_work.rt_arr[0]);
+		mlxsw_sp_router_fib6_work_fini(&fib_work->fib6_work);
 		break;
 	case FIB_EVENT_RULE_ADD:
 		/* if we get here, a rule was added that we do not support.
@@ -6068,6 +6123,7 @@ static int mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work *fib_work,
 				      struct fib_notifier_info *info)
 {
 	struct fib6_entry_notifier_info *fen6_info;
+	int err;
 
 	switch (fib_work->event) {
 	case FIB_EVENT_ENTRY_REPLACE: /* fall through */
@@ -6075,8 +6131,10 @@ static int mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work *fib_work,
 	case FIB_EVENT_ENTRY_DEL:
 		fen6_info = container_of(info, struct fib6_entry_notifier_info,
 					 info);
-		fib_work->fen6_info = *fen6_info;
-		fib6_info_hold(fib_work->fen6_info.rt);
+		err = mlxsw_sp_router_fib6_work_init(&fib_work->fib6_work,
+						     fen6_info);
+		if (err)
+			return err;
 		break;
 	}
 
-- 
2.20.1


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

* [PATCH net-next v2 11/16] mlxsw: spectrum_router: Adjust IPv6 replace logic to new notifications
  2019-06-18 15:12 [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate Ido Schimmel
                   ` (9 preceding siblings ...)
  2019-06-18 15:12 ` [PATCH net-next v2 10/16] mlxsw: spectrum_router: Pass multiple routes to work item Ido Schimmel
@ 2019-06-18 15:12 ` Ido Schimmel
  2019-06-18 15:12 ` [PATCH net-next v2 12/16] mlxsw: spectrum_router: Pass array of routes to route handling functions Ido Schimmel
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Ido Schimmel @ 2019-06-18 15:12 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, alexpe, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Previously, IPv6 replace notifications were only sent from
fib6_add_rt2node(). The function only emitted such notifications if a
route actually replaced another route.

A previous patch added another call site in ip6_route_multipath_add()
from which such notification can be emitted even if a route was merely
added and did not replace another route.

Adjust the driver to take this into account and potentially set the
'replace' flag to 'false' if the notified route did not replace an
existing route.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum_router.c  | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 42e0e9677b91..dff96d1b0970 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -5435,16 +5435,16 @@ mlxsw_sp_fib6_node_entry_find(const struct mlxsw_sp_fib_node *fib_node,
 
 static int
 mlxsw_sp_fib6_node_list_insert(struct mlxsw_sp_fib6_entry *new6_entry,
-			       bool replace)
+			       bool *p_replace)
 {
 	struct mlxsw_sp_fib_node *fib_node = new6_entry->common.fib_node;
 	struct fib6_info *nrt = mlxsw_sp_fib6_entry_rt(new6_entry);
 	struct mlxsw_sp_fib6_entry *fib6_entry;
 
-	fib6_entry = mlxsw_sp_fib6_node_entry_find(fib_node, nrt, replace);
+	fib6_entry = mlxsw_sp_fib6_node_entry_find(fib_node, nrt, *p_replace);
 
-	if (replace && WARN_ON(!fib6_entry))
-		return -EINVAL;
+	if (*p_replace && !fib6_entry)
+		*p_replace = false;
 
 	if (fib6_entry) {
 		list_add_tail(&new6_entry->common.list,
@@ -5479,11 +5479,11 @@ mlxsw_sp_fib6_node_list_remove(struct mlxsw_sp_fib6_entry *fib6_entry)
 
 static int mlxsw_sp_fib6_node_entry_link(struct mlxsw_sp *mlxsw_sp,
 					 struct mlxsw_sp_fib6_entry *fib6_entry,
-					 bool replace)
+					 bool *p_replace)
 {
 	int err;
 
-	err = mlxsw_sp_fib6_node_list_insert(fib6_entry, replace);
+	err = mlxsw_sp_fib6_node_list_insert(fib6_entry, p_replace);
 	if (err)
 		return err;
 
@@ -5596,7 +5596,7 @@ static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
 		goto err_fib6_entry_create;
 	}
 
-	err = mlxsw_sp_fib6_node_entry_link(mlxsw_sp, fib6_entry, replace);
+	err = mlxsw_sp_fib6_node_entry_link(mlxsw_sp, fib6_entry, &replace);
 	if (err)
 		goto err_fib6_node_entry_link;
 
-- 
2.20.1


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

* [PATCH net-next v2 12/16] mlxsw: spectrum_router: Pass array of routes to route handling functions
  2019-06-18 15:12 [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate Ido Schimmel
                   ` (10 preceding siblings ...)
  2019-06-18 15:12 ` [PATCH net-next v2 11/16] mlxsw: spectrum_router: Adjust IPv6 replace logic to new notifications Ido Schimmel
@ 2019-06-18 15:12 ` Ido Schimmel
  2019-06-18 15:12 ` [PATCH net-next v2 13/16] mlxsw: spectrum_router: Add / delete multiple IPv6 nexthops Ido Schimmel
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Ido Schimmel @ 2019-06-18 15:12 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, alexpe, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Prepare the driver to handle multiple routes in a single notification by
passing an array of routes to the functions that actually add / delete a
route.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum_router.c  | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index dff96d1b0970..f0332d54aea1 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -5556,10 +5556,12 @@ static void mlxsw_sp_fib6_entry_replace(struct mlxsw_sp *mlxsw_sp,
 }
 
 static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
-				    struct fib6_info *rt, bool replace)
+				    struct fib6_info **rt_arr,
+				    unsigned int nrt6, bool replace)
 {
 	struct mlxsw_sp_fib6_entry *fib6_entry;
 	struct mlxsw_sp_fib_node *fib_node;
+	struct fib6_info *rt = rt_arr[0];
 	int err;
 
 	if (mlxsw_sp->router->aborted)
@@ -5613,10 +5615,12 @@ static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
 }
 
 static void mlxsw_sp_router_fib6_del(struct mlxsw_sp *mlxsw_sp,
-				     struct fib6_info *rt)
+				     struct fib6_info **rt_arr,
+				     unsigned int nrt6)
 {
 	struct mlxsw_sp_fib6_entry *fib6_entry;
 	struct mlxsw_sp_fib_node *fib_node;
+	struct fib6_info *rt = rt_arr[0];
 
 	if (mlxsw_sp->router->aborted)
 		return;
@@ -6021,7 +6025,8 @@ static void mlxsw_sp_router_fib6_event_work(struct work_struct *work)
 	case FIB_EVENT_ENTRY_ADD:
 		replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE;
 		err = mlxsw_sp_router_fib6_add(mlxsw_sp,
-					       fib_work->fib6_work.rt_arr[0],
+					       fib_work->fib6_work.rt_arr,
+					       fib_work->fib6_work.nrt6,
 					       replace);
 		if (err)
 			mlxsw_sp_router_fib_abort(mlxsw_sp);
@@ -6029,7 +6034,8 @@ static void mlxsw_sp_router_fib6_event_work(struct work_struct *work)
 		break;
 	case FIB_EVENT_ENTRY_DEL:
 		mlxsw_sp_router_fib6_del(mlxsw_sp,
-					 fib_work->fib6_work.rt_arr[0]);
+					 fib_work->fib6_work.rt_arr,
+					 fib_work->fib6_work.nrt6);
 		mlxsw_sp_router_fib6_work_fini(&fib_work->fib6_work);
 		break;
 	case FIB_EVENT_RULE_ADD:
-- 
2.20.1


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

* [PATCH net-next v2 13/16] mlxsw: spectrum_router: Add / delete multiple IPv6 nexthops
  2019-06-18 15:12 [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate Ido Schimmel
                   ` (11 preceding siblings ...)
  2019-06-18 15:12 ` [PATCH net-next v2 12/16] mlxsw: spectrum_router: Pass array of routes to route handling functions Ido Schimmel
@ 2019-06-18 15:12 ` Ido Schimmel
  2019-06-18 15:12 ` [PATCH net-next v2 14/16] mlxsw: spectrum_router: Create IPv6 multipath routes in one go Ido Schimmel
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Ido Schimmel @ 2019-06-18 15:12 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, alexpe, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Currently, the functions that take care of populating IPv6 nexthop
groups only add / delete a single nexthop.

Prepare them to handle multiple routes in one notification by passing an
array of routes and adding / deleting all of them.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_router.c | 61 ++++++++++++-------
 1 file changed, 39 insertions(+), 22 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index f0332d54aea1..98fd3c582a60 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -5278,17 +5278,21 @@ mlxsw_sp_nexthop6_group_update(struct mlxsw_sp *mlxsw_sp,
 static int
 mlxsw_sp_fib6_entry_nexthop_add(struct mlxsw_sp *mlxsw_sp,
 				struct mlxsw_sp_fib6_entry *fib6_entry,
-				struct fib6_info *rt)
+				struct fib6_info **rt_arr, unsigned int nrt6)
 {
 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
-	int err;
+	int err, i;
 
-	mlxsw_sp_rt6 = mlxsw_sp_rt6_create(rt);
-	if (IS_ERR(mlxsw_sp_rt6))
-		return PTR_ERR(mlxsw_sp_rt6);
+	for (i = 0; i < nrt6; i++) {
+		mlxsw_sp_rt6 = mlxsw_sp_rt6_create(rt_arr[i]);
+		if (IS_ERR(mlxsw_sp_rt6)) {
+			err = PTR_ERR(mlxsw_sp_rt6);
+			goto err_rt6_create;
+		}
 
-	list_add_tail(&mlxsw_sp_rt6->list, &fib6_entry->rt6_list);
-	fib6_entry->nrt6++;
+		list_add_tail(&mlxsw_sp_rt6->list, &fib6_entry->rt6_list);
+		fib6_entry->nrt6++;
+	}
 
 	err = mlxsw_sp_nexthop6_group_update(mlxsw_sp, fib6_entry);
 	if (err)
@@ -5297,27 +5301,38 @@ mlxsw_sp_fib6_entry_nexthop_add(struct mlxsw_sp *mlxsw_sp,
 	return 0;
 
 err_nexthop6_group_update:
-	fib6_entry->nrt6--;
-	list_del(&mlxsw_sp_rt6->list);
-	mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
+	i = nrt6;
+err_rt6_create:
+	for (i--; i >= 0; i--) {
+		fib6_entry->nrt6--;
+		mlxsw_sp_rt6 = list_last_entry(&fib6_entry->rt6_list,
+					       struct mlxsw_sp_rt6, list);
+		list_del(&mlxsw_sp_rt6->list);
+		mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
+	}
 	return err;
 }
 
 static void
 mlxsw_sp_fib6_entry_nexthop_del(struct mlxsw_sp *mlxsw_sp,
 				struct mlxsw_sp_fib6_entry *fib6_entry,
-				struct fib6_info *rt)
+				struct fib6_info **rt_arr, unsigned int nrt6)
 {
 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
+	int i;
 
-	mlxsw_sp_rt6 = mlxsw_sp_fib6_entry_rt_find(fib6_entry, rt);
-	if (WARN_ON(!mlxsw_sp_rt6))
-		return;
+	for (i = 0; i < nrt6; i++) {
+		mlxsw_sp_rt6 = mlxsw_sp_fib6_entry_rt_find(fib6_entry,
+							   rt_arr[i]);
+		if (WARN_ON_ONCE(!mlxsw_sp_rt6))
+			continue;
+
+		fib6_entry->nrt6--;
+		list_del(&mlxsw_sp_rt6->list);
+		mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
+	}
 
-	fib6_entry->nrt6--;
-	list_del(&mlxsw_sp_rt6->list);
 	mlxsw_sp_nexthop6_group_update(mlxsw_sp, fib6_entry);
-	mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
 }
 
 static void mlxsw_sp_fib6_entry_type_set(struct mlxsw_sp *mlxsw_sp,
@@ -5586,7 +5601,8 @@ static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
 	 */
 	fib6_entry = mlxsw_sp_fib6_node_mp_entry_find(fib_node, rt, replace);
 	if (fib6_entry) {
-		err = mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp, fib6_entry, rt);
+		err = mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp, fib6_entry,
+						      rt_arr, nrt6);
 		if (err)
 			goto err_fib6_entry_nexthop_add;
 		return 0;
@@ -5632,11 +5648,12 @@ static void mlxsw_sp_router_fib6_del(struct mlxsw_sp *mlxsw_sp,
 	if (WARN_ON(!fib6_entry))
 		return;
 
-	/* If route is part of a multipath entry, but not the last one
-	 * removed, then only reduce its nexthop group.
+	/* If not all the nexthops are deleted, then only reduce the nexthop
+	 * group.
 	 */
-	if (!list_is_singular(&fib6_entry->rt6_list)) {
-		mlxsw_sp_fib6_entry_nexthop_del(mlxsw_sp, fib6_entry, rt);
+	if (nrt6 != fib6_entry->nrt6) {
+		mlxsw_sp_fib6_entry_nexthop_del(mlxsw_sp, fib6_entry, rt_arr,
+						nrt6);
 		return;
 	}
 
-- 
2.20.1


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

* [PATCH net-next v2 14/16] mlxsw: spectrum_router: Create IPv6 multipath routes in one go
  2019-06-18 15:12 [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate Ido Schimmel
                   ` (12 preceding siblings ...)
  2019-06-18 15:12 ` [PATCH net-next v2 13/16] mlxsw: spectrum_router: Add / delete multiple IPv6 nexthops Ido Schimmel
@ 2019-06-18 15:12 ` Ido Schimmel
  2019-06-18 15:12 ` [PATCH net-next v2 15/16] ipv6: Stop sending in-kernel notifications for each nexthop Ido Schimmel
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Ido Schimmel @ 2019-06-18 15:12 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, alexpe, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Allow the driver to create an IPv6 multipath route in one go by passing
an array of sibling routes and iterating over them.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_router.c | 36 ++++++++++++-------
 1 file changed, 23 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 98fd3c582a60..92ec65188e9a 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -5373,29 +5373,32 @@ mlxsw_sp_fib6_entry_rt_destroy_all(struct mlxsw_sp_fib6_entry *fib6_entry)
 static struct mlxsw_sp_fib6_entry *
 mlxsw_sp_fib6_entry_create(struct mlxsw_sp *mlxsw_sp,
 			   struct mlxsw_sp_fib_node *fib_node,
-			   struct fib6_info *rt)
+			   struct fib6_info **rt_arr, unsigned int nrt6)
 {
 	struct mlxsw_sp_fib6_entry *fib6_entry;
 	struct mlxsw_sp_fib_entry *fib_entry;
 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
-	int err;
+	int err, i;
 
 	fib6_entry = kzalloc(sizeof(*fib6_entry), GFP_KERNEL);
 	if (!fib6_entry)
 		return ERR_PTR(-ENOMEM);
 	fib_entry = &fib6_entry->common;
 
-	mlxsw_sp_rt6 = mlxsw_sp_rt6_create(rt);
-	if (IS_ERR(mlxsw_sp_rt6)) {
-		err = PTR_ERR(mlxsw_sp_rt6);
-		goto err_rt6_create;
+	INIT_LIST_HEAD(&fib6_entry->rt6_list);
+
+	for (i = 0; i < nrt6; i++) {
+		mlxsw_sp_rt6 = mlxsw_sp_rt6_create(rt_arr[i]);
+		if (IS_ERR(mlxsw_sp_rt6)) {
+			err = PTR_ERR(mlxsw_sp_rt6);
+			goto err_rt6_create;
+		}
+		list_add_tail(&mlxsw_sp_rt6->list, &fib6_entry->rt6_list);
+		fib6_entry->nrt6++;
 	}
 
-	mlxsw_sp_fib6_entry_type_set(mlxsw_sp, fib_entry, mlxsw_sp_rt6->rt);
+	mlxsw_sp_fib6_entry_type_set(mlxsw_sp, fib_entry, rt_arr[0]);
 
-	INIT_LIST_HEAD(&fib6_entry->rt6_list);
-	list_add_tail(&mlxsw_sp_rt6->list, &fib6_entry->rt6_list);
-	fib6_entry->nrt6 = 1;
 	err = mlxsw_sp_nexthop6_group_get(mlxsw_sp, fib6_entry);
 	if (err)
 		goto err_nexthop6_group_get;
@@ -5405,9 +5408,15 @@ mlxsw_sp_fib6_entry_create(struct mlxsw_sp *mlxsw_sp,
 	return fib6_entry;
 
 err_nexthop6_group_get:
-	list_del(&mlxsw_sp_rt6->list);
-	mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
+	i = nrt6;
 err_rt6_create:
+	for (i--; i >= 0; i--) {
+		fib6_entry->nrt6--;
+		mlxsw_sp_rt6 = list_last_entry(&fib6_entry->rt6_list,
+					       struct mlxsw_sp_rt6, list);
+		list_del(&mlxsw_sp_rt6->list);
+		mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
+	}
 	kfree(fib6_entry);
 	return ERR_PTR(err);
 }
@@ -5608,7 +5617,8 @@ static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
 		return 0;
 	}
 
-	fib6_entry = mlxsw_sp_fib6_entry_create(mlxsw_sp, fib_node, rt);
+	fib6_entry = mlxsw_sp_fib6_entry_create(mlxsw_sp, fib_node, rt_arr,
+						nrt6);
 	if (IS_ERR(fib6_entry)) {
 		err = PTR_ERR(fib6_entry);
 		goto err_fib6_entry_create;
-- 
2.20.1


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

* [PATCH net-next v2 15/16] ipv6: Stop sending in-kernel notifications for each nexthop
  2019-06-18 15:12 [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate Ido Schimmel
                   ` (13 preceding siblings ...)
  2019-06-18 15:12 ` [PATCH net-next v2 14/16] mlxsw: spectrum_router: Create IPv6 multipath routes in one go Ido Schimmel
@ 2019-06-18 15:12 ` Ido Schimmel
  2019-06-18 15:28   ` David Ahern
  2019-06-18 15:12 ` [PATCH net-next v2 16/16] selftests: mlxsw: Add a test for FIB offload indication Ido Schimmel
  2019-06-18 16:46 ` [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate David Miller
  16 siblings, 1 reply; 20+ messages in thread
From: Ido Schimmel @ 2019-06-18 15:12 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, alexpe, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Both listeners - mlxsw and netdevsim - of IPv6 FIB notifications are now
ready to handle IPv6 multipath notifications.

Therefore, stop ignoring such notifications in both drivers and stop
sending notification for each added / deleted nexthop.

v2:
* Remove 'multipath_rt' from 'struct fib6_entry_notifier_info'

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_router.c |  2 --
 drivers/net/netdevsim/fib.c                   |  7 -----
 include/net/ip6_fib.h                         |  1 -
 net/ipv6/ip6_fib.c                            | 29 +++++++++++--------
 4 files changed, 17 insertions(+), 22 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 92ec65188e9a..e618be7ce6c6 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -6294,8 +6294,6 @@ static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
 				NL_SET_ERR_MSG_MOD(info->extack, "IPv6 route with nexthop objects is not supported");
 				return notifier_from_errno(-EINVAL);
 			}
-			if (fen6_info->multipath_rt)
-				return NOTIFY_DONE;
 		}
 		break;
 	}
diff --git a/drivers/net/netdevsim/fib.c b/drivers/net/netdevsim/fib.c
index 83ba5113210d..8c57ba747772 100644
--- a/drivers/net/netdevsim/fib.c
+++ b/drivers/net/netdevsim/fib.c
@@ -190,13 +190,6 @@ static int nsim_fib_event_nb(struct notifier_block *nb, unsigned long event,
 
 	case FIB_EVENT_ENTRY_ADD:  /* fall through */
 	case FIB_EVENT_ENTRY_DEL:
-		if (info->family == AF_INET6) {
-			struct fib6_entry_notifier_info *fen6_info = ptr;
-
-			if (fen6_info->multipath_rt)
-				return NOTIFY_DONE;
-		}
-
 		err = nsim_fib_event(data, info,
 				     event == FIB_EVENT_ENTRY_ADD);
 		break;
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 7c3d5ab05879..87331f2c4af0 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -378,7 +378,6 @@ struct fib6_entry_notifier_info {
 	struct fib_notifier_info info; /* must be first */
 	struct fib6_info *rt;
 	unsigned int nsiblings;
-	bool multipath_rt;
 };
 
 /*
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index df08ba8fe6fc..1d16a01eccf5 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -391,7 +391,6 @@ int call_fib6_multipath_entry_notifiers(struct net *net,
 		.info.extack = extack,
 		.rt = rt,
 		.nsiblings = nsiblings,
-		.multipath_rt = true,
 	};
 
 	rt->fib6_table->fib_seq++;
@@ -1140,11 +1139,13 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
 add:
 		nlflags |= NLM_F_CREATE;
 
-		err = call_fib6_entry_notifiers(info->nl_net,
-						FIB_EVENT_ENTRY_ADD,
-						rt, extack);
-		if (err)
-			return err;
+		if (!info->skip_notify_kernel) {
+			err = call_fib6_entry_notifiers(info->nl_net,
+							FIB_EVENT_ENTRY_ADD,
+							rt, extack);
+			if (err)
+				return err;
+		}
 
 		rcu_assign_pointer(rt->fib6_next, iter);
 		fib6_info_hold(rt);
@@ -1169,11 +1170,13 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
 			return -ENOENT;
 		}
 
-		err = call_fib6_entry_notifiers(info->nl_net,
-						FIB_EVENT_ENTRY_REPLACE,
-						rt, extack);
-		if (err)
-			return err;
+		if (!info->skip_notify_kernel) {
+			err = call_fib6_entry_notifiers(info->nl_net,
+							FIB_EVENT_ENTRY_REPLACE,
+							rt, extack);
+			if (err)
+				return err;
+		}
 
 		fib6_info_hold(rt);
 		rcu_assign_pointer(rt->fib6_node, fn);
@@ -1856,9 +1859,11 @@ static void fib6_del_route(struct fib6_table *table, struct fib6_node *fn,
 
 	fib6_purge_rt(rt, fn, net);
 
-	call_fib6_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, rt, NULL);
+	if (!info->skip_notify_kernel)
+		call_fib6_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, rt, NULL);
 	if (!info->skip_notify)
 		inet6_rt_notify(RTM_DELROUTE, rt, info, 0);
+
 	fib6_info_release(rt);
 }
 
-- 
2.20.1


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

* [PATCH net-next v2 16/16] selftests: mlxsw: Add a test for FIB offload indication
  2019-06-18 15:12 [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate Ido Schimmel
                   ` (14 preceding siblings ...)
  2019-06-18 15:12 ` [PATCH net-next v2 15/16] ipv6: Stop sending in-kernel notifications for each nexthop Ido Schimmel
@ 2019-06-18 15:12 ` Ido Schimmel
  2019-06-18 16:46 ` [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate David Miller
  16 siblings, 0 replies; 20+ messages in thread
From: Ido Schimmel @ 2019-06-18 15:12 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, dsahern, alexpe, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Test that the offload indication for unicast routes is correctly set in
different scenarios. IPv4 support will be added in the future.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../drivers/net/mlxsw/fib_offload.sh          | 349 ++++++++++++++++++
 1 file changed, 349 insertions(+)
 create mode 100755 tools/testing/selftests/drivers/net/mlxsw/fib_offload.sh

diff --git a/tools/testing/selftests/drivers/net/mlxsw/fib_offload.sh b/tools/testing/selftests/drivers/net/mlxsw/fib_offload.sh
new file mode 100755
index 000000000000..e99ae500f387
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/mlxsw/fib_offload.sh
@@ -0,0 +1,349 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Test unicast FIB offload indication.
+
+lib_dir=$(dirname $0)/../../../net/forwarding
+
+ALL_TESTS="
+	ipv6_route_add
+	ipv6_route_replace
+	ipv6_route_nexthop_group_share
+	ipv6_route_rate
+"
+NUM_NETIFS=4
+source $lib_dir/lib.sh
+source $lib_dir/devlink_lib.sh
+
+tor1_create()
+{
+	simple_if_init $tor1_p1 2001:db8:1::2/128 2001:db8:1::3/128
+}
+
+tor1_destroy()
+{
+	simple_if_fini $tor1_p1 2001:db8:1::2/128 2001:db8:1::3/128
+}
+
+tor2_create()
+{
+	simple_if_init $tor2_p1 2001:db8:2::2/128 2001:db8:2::3/128
+}
+
+tor2_destroy()
+{
+	simple_if_fini $tor2_p1 2001:db8:2::2/128 2001:db8:2::3/128
+}
+
+spine_create()
+{
+	ip link set dev $spine_p1 up
+	ip link set dev $spine_p2 up
+
+	__addr_add_del $spine_p1 add 2001:db8:1::1/64
+	__addr_add_del $spine_p2 add 2001:db8:2::1/64
+}
+
+spine_destroy()
+{
+	__addr_add_del $spine_p2 del 2001:db8:2::1/64
+	__addr_add_del $spine_p1 del 2001:db8:1::1/64
+
+	ip link set dev $spine_p2 down
+	ip link set dev $spine_p1 down
+}
+
+ipv6_offload_check()
+{
+	local pfx="$1"; shift
+	local expected_num=$1; shift
+	local num
+
+	# Try to avoid races with route offload
+	sleep .1
+
+	num=$(ip -6 route show match ${pfx} | grep "offload" | wc -l)
+
+	if [ $num -eq $expected_num ]; then
+		return 0
+	fi
+
+	return 1
+}
+
+ipv6_route_add_prefix()
+{
+	RET=0
+
+	# Add a prefix route and check that it is offloaded.
+	ip -6 route add 2001:db8:3::/64 dev $spine_p1 metric 100
+	ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 100" 1
+	check_err $? "prefix route not offloaded"
+
+	# Append an identical prefix route with an higher metric and check that
+	# offload indication did not change.
+	ip -6 route append 2001:db8:3::/64 dev $spine_p1 metric 200
+	ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 100" 1
+	check_err $? "lowest metric not offloaded after append"
+	ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 200" 0
+	check_err $? "highest metric offloaded when should not"
+
+	# Prepend an identical prefix route with lower metric and check that
+	# it is offloaded and the others are not.
+	ip -6 route append 2001:db8:3::/64 dev $spine_p1 metric 10
+	ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 10" 1
+	check_err $? "lowest metric not offloaded after prepend"
+	ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 100" 0
+	check_err $? "mid metric offloaded when should not"
+	ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 200" 0
+	check_err $? "highest metric offloaded when should not"
+
+	# Delete the routes and add the same route with a different nexthop
+	# device. Check that it is offloaded.
+	ip -6 route flush 2001:db8:3::/64 dev $spine_p1
+	ip -6 route add 2001:db8:3::/64 dev $spine_p2
+	ipv6_offload_check "2001:db8:3::/64 dev $spine_p2" 1
+
+	log_test "IPv6 prefix route add"
+
+	ip -6 route flush 2001:db8:3::/64
+}
+
+ipv6_route_add_mpath()
+{
+	RET=0
+
+	# Add a multipath route and check that it is offloaded.
+	ip -6 route add 2001:db8:3::/64 metric 100 \
+		nexthop via 2001:db8:1::2 dev $spine_p1 \
+		nexthop via 2001:db8:2::2 dev $spine_p2
+	ipv6_offload_check "2001:db8:3::/64 metric 100" 2
+	check_err $? "multipath route not offloaded when should"
+
+	# Append another nexthop and check that it is offloaded as well.
+	ip -6 route append 2001:db8:3::/64 metric 100 \
+		nexthop via 2001:db8:1::3 dev $spine_p1
+	ipv6_offload_check "2001:db8:3::/64 metric 100" 3
+	check_err $? "appended nexthop not offloaded when should"
+
+	# Mimic route replace by removing the route and adding it back with
+	# only two nexthops.
+	ip -6 route del 2001:db8:3::/64
+	ip -6 route add 2001:db8:3::/64 metric 100 \
+		nexthop via 2001:db8:1::2 dev $spine_p1 \
+		nexthop via 2001:db8:2::2 dev $spine_p2
+	ipv6_offload_check "2001:db8:3::/64 metric 100" 2
+	check_err $? "multipath route not offloaded after delete & add"
+
+	# Append a nexthop with an higher metric and check that the offload
+	# indication did not change.
+	ip -6 route append 2001:db8:3::/64 metric 200 \
+		nexthop via 2001:db8:1::3 dev $spine_p1
+	ipv6_offload_check "2001:db8:3::/64 metric 100" 2
+	check_err $? "lowest metric not offloaded after append"
+	ipv6_offload_check "2001:db8:3::/64 metric 200" 0
+	check_err $? "highest metric offloaded when should not"
+
+	# Prepend a nexthop with a lower metric and check that it is offloaded
+	# and the others are not.
+	ip -6 route append 2001:db8:3::/64 metric 10 \
+		nexthop via 2001:db8:1::3 dev $spine_p1
+	ipv6_offload_check "2001:db8:3::/64 metric 10" 1
+	check_err $? "lowest metric not offloaded after prepend"
+	ipv6_offload_check "2001:db8:3::/64 metric 100" 0
+	check_err $? "mid metric offloaded when should not"
+	ipv6_offload_check "2001:db8:3::/64 metric 200" 0
+	check_err $? "highest metric offloaded when should not"
+
+	log_test "IPv6 multipath route add"
+
+	ip -6 route flush 2001:db8:3::/64
+}
+
+ipv6_route_add()
+{
+	ipv6_route_add_prefix
+	ipv6_route_add_mpath
+}
+
+ipv6_route_replace()
+{
+	RET=0
+
+	# Replace prefix route with prefix route.
+	ip -6 route add 2001:db8:3::/64 metric 100 dev $spine_p1
+	ipv6_offload_check "2001:db8:3::/64 metric 100" 1
+	check_err $? "prefix route not offloaded when should"
+	ip -6 route replace 2001:db8:3::/64 metric 100 dev $spine_p2
+	ipv6_offload_check "2001:db8:3::/64 metric 100" 1
+	check_err $? "prefix route not offloaded after replace"
+
+	# Replace prefix route with multipath route.
+	ip -6 route replace 2001:db8:3::/64 metric 100 \
+		nexthop via 2001:db8:1::2 dev $spine_p1 \
+		nexthop via 2001:db8:2::2 dev $spine_p2
+	ipv6_offload_check "2001:db8:3::/64 metric 100" 2
+	check_err $? "multipath route not offloaded after replace"
+
+	# Replace multipath route with prefix route. A prefix route cannot
+	# replace a multipath route, so it is appended.
+	ip -6 route replace 2001:db8:3::/64 metric 100 dev $spine_p1
+	ipv6_offload_check "2001:db8:3::/64 metric 100 dev $spine_p1" 0
+	check_err $? "prefix route offloaded after 'replacing' multipath route"
+	ipv6_offload_check "2001:db8:3::/64 metric 100" 2
+	check_err $? "multipath route not offloaded after being 'replaced' by prefix route"
+
+	# Replace multipath route with multipath route.
+	ip -6 route replace 2001:db8:3::/64 metric 100 \
+		nexthop via 2001:db8:1::3 dev $spine_p1 \
+		nexthop via 2001:db8:2::3 dev $spine_p2
+	ipv6_offload_check "2001:db8:3::/64 metric 100" 2
+	check_err $? "multipath route not offloaded after replacing multipath route"
+
+	# Replace a non-existing multipath route with a multipath route and
+	# check that it is appended and not offloaded.
+	ip -6 route replace 2001:db8:3::/64 metric 200 \
+		nexthop via 2001:db8:1::3 dev $spine_p1 \
+		nexthop via 2001:db8:2::3 dev $spine_p2
+	ipv6_offload_check "2001:db8:3::/64 metric 100" 2
+	check_err $? "multipath route not offloaded after non-existing route was 'replaced'"
+	ipv6_offload_check "2001:db8:3::/64 metric 200" 0
+	check_err $? "multipath route offloaded after 'replacing' non-existing route"
+
+	log_test "IPv6 route replace"
+
+	ip -6 route flush 2001:db8:3::/64
+}
+
+ipv6_route_nexthop_group_share()
+{
+	RET=0
+
+	# The driver consolidates identical nexthop groups in order to reduce
+	# the resource usage in its adjacency table. Check that the deletion
+	# of one multipath route using the group does not affect the other.
+	ip -6 route add 2001:db8:3::/64 \
+		nexthop via 2001:db8:1::2 dev $spine_p1 \
+		nexthop via 2001:db8:2::2 dev $spine_p2
+	ip -6 route add 2001:db8:4::/64 \
+		nexthop via 2001:db8:1::2 dev $spine_p1 \
+		nexthop via 2001:db8:2::2 dev $spine_p2
+	ipv6_offload_check "2001:db8:3::/64" 2
+	check_err $? "multipath route not offloaded when should"
+	ipv6_offload_check "2001:db8:4::/64" 2
+	check_err $? "multipath route not offloaded when should"
+	ip -6 route del 2001:db8:3::/64
+	ipv6_offload_check "2001:db8:4::/64" 2
+	check_err $? "multipath route not offloaded after deletion of route sharing the nexthop group"
+
+	# Check that after unsharing a nexthop group the routes are still
+	# marked as offloaded.
+	ip -6 route add 2001:db8:3::/64 \
+		nexthop via 2001:db8:1::2 dev $spine_p1 \
+		nexthop via 2001:db8:2::2 dev $spine_p2
+	ip -6 route del 2001:db8:4::/64 \
+		nexthop via 2001:db8:1::2 dev $spine_p1
+	ipv6_offload_check "2001:db8:4::/64" 1
+	check_err $? "singlepath route not offloaded after unsharing the nexthop group"
+	ipv6_offload_check "2001:db8:3::/64" 2
+	check_err $? "multipath route not offloaded after unsharing the nexthop group"
+
+	log_test "IPv6 nexthop group sharing"
+
+	ip -6 route flush 2001:db8:3::/64
+	ip -6 route flush 2001:db8:4::/64
+}
+
+ipv6_route_rate()
+{
+	local batch_dir=$(mktemp -d)
+	local num_rts=$((40 * 1024))
+	local num_nhs=16
+	local total
+	local start
+	local diff
+	local end
+	local nhs
+	local i
+
+	RET=0
+
+	# Prepare 40K /64 multipath routes with 16 nexthops each and check how
+	# long it takes to add them. A limit of 60 seconds is set. It is much
+	# higher than insertion should take and meant to flag a serious
+	# regression.
+	total=$((nums_nhs * num_rts))
+
+	for i in $(seq 1 $num_nhs); do
+		ip -6 address add 2001:db8:1::10:$i/128 dev $tor1_p1
+		nexthops+=" nexthop via 2001:db8:1::10:$i dev $spine_p1"
+	done
+
+	for i in $(seq 1 $num_rts); do
+		echo "route add 2001:db8:8:$(printf "%x" $i)::/64$nexthops" \
+			>> $batch_dir/add.batch
+		echo "route del 2001:db8:8:$(printf "%x" $i)::/64$nexthops" \
+			>> $batch_dir/del.batch
+	done
+
+	start=$(date +%s.%N)
+
+	ip -batch $batch_dir/add.batch
+	count=$(ip -6 route show | grep offload | wc -l)
+	while [ $count -lt $total ]; do
+		sleep .01
+		count=$(ip -6 route show | grep offload | wc -l)
+	done
+
+	end=$(date +%s.%N)
+
+	diff=$(echo "$end - $start" | bc -l)
+	test "$(echo "$diff > 60" | bc -l)" -eq 0
+	check_err $? "route insertion took too long"
+	log_info "inserted $num_rts routes in $diff seconds"
+
+	log_test "IPv6 routes insertion rate"
+
+	ip -batch $batch_dir/del.batch
+	for i in $(seq 1 $num_nhs); do
+		ip -6 address del 2001:db8:1::10:$i/128 dev $tor1_p1
+	done
+	rm -rf $batch_dir
+}
+
+setup_prepare()
+{
+	spine_p1=${NETIFS[p1]}
+	tor1_p1=${NETIFS[p2]}
+
+	spine_p2=${NETIFS[p3]}
+	tor2_p1=${NETIFS[p4]}
+
+	vrf_prepare
+	forwarding_enable
+
+	tor1_create
+	tor2_create
+	spine_create
+}
+
+cleanup()
+{
+	pre_cleanup
+
+	spine_destroy
+	tor2_destroy
+	tor1_destroy
+
+	forwarding_restore
+	vrf_cleanup
+}
+
+trap cleanup EXIT
+
+setup_prepare
+setup_wait
+
+tests_run
+
+exit $EXIT_STATUS
-- 
2.20.1


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

* Re: [PATCH net-next v2 03/16] ipv6: Extend notifier info for multipath routes
  2019-06-18 15:12 ` [PATCH net-next v2 03/16] ipv6: Extend notifier info for multipath routes Ido Schimmel
@ 2019-06-18 15:26   ` David Ahern
  0 siblings, 0 replies; 20+ messages in thread
From: David Ahern @ 2019-06-18 15:26 UTC (permalink / raw)
  To: Ido Schimmel, netdev; +Cc: davem, jiri, alexpe, mlxsw, Ido Schimmel

On 6/18/19 9:12 AM, Ido Schimmel wrote:
> From: Ido Schimmel <idosch@mellanox.com>
> 
> Extend the IPv6 FIB notifier info with number of sibling routes being
> notified.
> 
> This will later allow listeners to process one notification for a
> multipath routes instead of N, where N is the number of nexthops.
> 
> Signed-off-by: Ido Schimmel <idosch@mellanox.com>
> Acked-by: Jiri Pirko <jiri@mellanox.com>
> ---
>  include/net/ip6_fib.h |  7 +++++++
>  net/ipv6/ip6_fib.c    | 17 +++++++++++++++++
>  2 files changed, 24 insertions(+)
> 

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



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

* Re: [PATCH net-next v2 15/16] ipv6: Stop sending in-kernel notifications for each nexthop
  2019-06-18 15:12 ` [PATCH net-next v2 15/16] ipv6: Stop sending in-kernel notifications for each nexthop Ido Schimmel
@ 2019-06-18 15:28   ` David Ahern
  0 siblings, 0 replies; 20+ messages in thread
From: David Ahern @ 2019-06-18 15:28 UTC (permalink / raw)
  To: Ido Schimmel, netdev; +Cc: davem, jiri, alexpe, mlxsw, Ido Schimmel

On 6/18/19 9:12 AM, Ido Schimmel wrote:
> From: Ido Schimmel <idosch@mellanox.com>
> 
> Both listeners - mlxsw and netdevsim - of IPv6 FIB notifications are now
> ready to handle IPv6 multipath notifications.
> 
> Therefore, stop ignoring such notifications in both drivers and stop
> sending notification for each added / deleted nexthop.
> 
> v2:
> * Remove 'multipath_rt' from 'struct fib6_entry_notifier_info'
> 
> Signed-off-by: Ido Schimmel <idosch@mellanox.com>
> Acked-by: Jiri Pirko <jiri@mellanox.com>
> ---
>  .../ethernet/mellanox/mlxsw/spectrum_router.c |  2 --
>  drivers/net/netdevsim/fib.c                   |  7 -----
>  include/net/ip6_fib.h                         |  1 -
>  net/ipv6/ip6_fib.c                            | 29 +++++++++++--------
>  4 files changed, 17 insertions(+), 22 deletions(-)
> 

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



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

* Re: [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate
  2019-06-18 15:12 [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate Ido Schimmel
                   ` (15 preceding siblings ...)
  2019-06-18 15:12 ` [PATCH net-next v2 16/16] selftests: mlxsw: Add a test for FIB offload indication Ido Schimmel
@ 2019-06-18 16:46 ` David Miller
  16 siblings, 0 replies; 20+ messages in thread
From: David Miller @ 2019-06-18 16:46 UTC (permalink / raw)
  To: idosch; +Cc: netdev, jiri, dsahern, alexpe, mlxsw, idosch

From: Ido Schimmel <idosch@idosch.org>
Date: Tue, 18 Jun 2019 18:12:42 +0300

> Unlike IPv4, an IPv6 multipath route in the kernel is composed from
> multiple sibling routes, each representing a single nexthop.
> 
> Therefore, an addition of a multipath route with N nexthops translates
> to N in-kernel notifications. This is inefficient for device drivers
> that need to program the route to the underlying device. Each time a new
> nexthop is appended, a new nexthop group needs to be constructed and the
> old one deleted.
> 
> This patchset improves the situation by sending a single notification
> for a multipath route addition / deletion instead of one per-nexthop.
> When adding thousands of multipath routes with 16 nexthops, I measured
> an improvement of about x10 in the insertion rate.
 ...

Series applied, thanks everyone.

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

end of thread, other threads:[~2019-06-18 16:46 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-18 15:12 [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate Ido Schimmel
2019-06-18 15:12 ` [PATCH net-next v2 01/16] netlink: Document all fields of 'struct nl_info' Ido Schimmel
2019-06-18 15:12 ` [PATCH net-next v2 02/16] netlink: Add field to skip in-kernel notifications Ido Schimmel
2019-06-18 15:12 ` [PATCH net-next v2 03/16] ipv6: Extend notifier info for multipath routes Ido Schimmel
2019-06-18 15:26   ` David Ahern
2019-06-18 15:12 ` [PATCH net-next v2 04/16] mlxsw: spectrum_router: Ignore IPv6 multipath notifications Ido Schimmel
2019-06-18 15:12 ` [PATCH net-next v2 05/16] netdevsim: " Ido Schimmel
2019-06-18 15:12 ` [PATCH net-next v2 06/16] ipv6: Add IPv6 multipath notifications for add / replace Ido Schimmel
2019-06-18 15:12 ` [PATCH net-next v2 07/16] ipv6: Add IPv6 multipath notification for route delete Ido Schimmel
2019-06-18 15:12 ` [PATCH net-next v2 08/16] mlxsw: spectrum_router: Remove processing of IPv6 append notifications Ido Schimmel
2019-06-18 15:12 ` [PATCH net-next v2 09/16] mlxsw: spectrum_router: Prepare function to return errors Ido Schimmel
2019-06-18 15:12 ` [PATCH net-next v2 10/16] mlxsw: spectrum_router: Pass multiple routes to work item Ido Schimmel
2019-06-18 15:12 ` [PATCH net-next v2 11/16] mlxsw: spectrum_router: Adjust IPv6 replace logic to new notifications Ido Schimmel
2019-06-18 15:12 ` [PATCH net-next v2 12/16] mlxsw: spectrum_router: Pass array of routes to route handling functions Ido Schimmel
2019-06-18 15:12 ` [PATCH net-next v2 13/16] mlxsw: spectrum_router: Add / delete multiple IPv6 nexthops Ido Schimmel
2019-06-18 15:12 ` [PATCH net-next v2 14/16] mlxsw: spectrum_router: Create IPv6 multipath routes in one go Ido Schimmel
2019-06-18 15:12 ` [PATCH net-next v2 15/16] ipv6: Stop sending in-kernel notifications for each nexthop Ido Schimmel
2019-06-18 15:28   ` David Ahern
2019-06-18 15:12 ` [PATCH net-next v2 16/16] selftests: mlxsw: Add a test for FIB offload indication Ido Schimmel
2019-06-18 16:46 ` [PATCH net-next v2 00/16] mlxsw: Improve IPv6 route insertion rate David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).