Skip to content

Commit

Permalink
Merge branch 'route-offload-failure'
Browse files Browse the repository at this point in the history
net: Add support for route offload failure notifications

Ido Schimmel  says:

====================
This is a complementary series to the one merged in commit 389cb1e
("Merge branch 'add-notifications-when-route-hardware-flags-change'").

The previous series added RTM_NEWROUTE notifications to user space
whenever a route was successfully installed in hardware or when its
state in hardware changed. This allows routing daemons to delay
advertisement of routes until they are installed in hardware.

However, if route installation failed, a routing daemon will wait
indefinitely for a notification that will never come. The aim of this
series is to provide a failure notification via a new flag
(RTM_F_OFFLOAD_FAILED) in the RTM_NEWROUTE message. Upon such a
notification a routing daemon may decide to withdraw the route from the
FIB.

Series overview:

Patch #1 adds the new RTM_F_OFFLOAD_FAILED flag

Patches #2-#3 and #4-#5 add failure notifications to IPv4 and IPv6,
respectively

Patches #6-#8 teach netdevsim to fail route installation via a new knob
in debugfs

Patch #9 extends mlxsw to mark routes with the new flag

Patch #10 adds test cases for the new notification over netdevsim
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Feb 9, 2021
2 parents 08cbabb + 9ee53e3 commit 5ea3c72
Show file tree
Hide file tree
Showing 15 changed files with 372 additions and 40 deletions.
6 changes: 4 additions & 2 deletions Documentation/networking/ip-sysctl.rst
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ min_adv_mss - INTEGER

fib_notify_on_flag_change - INTEGER
Whether to emit RTM_NEWROUTE notifications whenever RTM_F_OFFLOAD/
RTM_F_TRAP flags are changed.
RTM_F_TRAP/RTM_F_OFFLOAD_FAILED flags are changed.

After installing a route to the kernel, user space receives an
acknowledgment, which means the route was installed in the kernel,
Expand All @@ -197,6 +197,7 @@ fib_notify_on_flag_change - INTEGER

- 0 - Do not emit notifications.
- 1 - Emit notifications.
- 2 - Emit notifications only for RTM_F_OFFLOAD_FAILED flag change.

IP Fragmentation:

Expand Down Expand Up @@ -1797,7 +1798,7 @@ nexthop_compat_mode - BOOLEAN

fib_notify_on_flag_change - INTEGER
Whether to emit RTM_NEWROUTE notifications whenever RTM_F_OFFLOAD/
RTM_F_TRAP flags are changed.
RTM_F_TRAP/RTM_F_OFFLOAD_FAILED flags are changed.

After installing a route to the kernel, user space receives an
acknowledgment, which means the route was installed in the kernel,
Expand All @@ -1814,6 +1815,7 @@ fib_notify_on_flag_change - INTEGER

- 0 - Do not emit notifications.
- 1 - Emit notifications.
- 2 - Emit notifications only for RTM_F_OFFLOAD_FAILED flag change.

IPv6 Fragmentation:

Expand Down
58 changes: 56 additions & 2 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
Original file line number Diff line number Diff line change
Expand Up @@ -4942,6 +4942,25 @@ mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group *nh_grp,
return NULL;
}

static void
mlxsw_sp_fib4_offload_failed_flag_set(struct mlxsw_sp *mlxsw_sp,
struct fib_entry_notifier_info *fen_info)
{
u32 *p_dst = (u32 *) &fen_info->dst;
struct fib_rt_info fri;

fri.fi = fen_info->fi;
fri.tb_id = fen_info->tb_id;
fri.dst = cpu_to_be32(*p_dst);
fri.dst_len = fen_info->dst_len;
fri.tos = fen_info->tos;
fri.type = fen_info->type;
fri.offload = false;
fri.trap = false;
fri.offload_failed = true;
fib_alias_hw_flags_set(mlxsw_sp_net(mlxsw_sp), &fri);
}

static void
mlxsw_sp_fib4_entry_hw_flags_set(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib_entry *fib_entry)
Expand All @@ -4963,6 +4982,7 @@ mlxsw_sp_fib4_entry_hw_flags_set(struct mlxsw_sp *mlxsw_sp,
fri.type = fib4_entry->type;
fri.offload = should_offload;
fri.trap = !should_offload;
fri.offload_failed = false;
fib_alias_hw_flags_set(mlxsw_sp_net(mlxsw_sp), &fri);
}

Expand All @@ -4985,9 +5005,34 @@ mlxsw_sp_fib4_entry_hw_flags_clear(struct mlxsw_sp *mlxsw_sp,
fri.type = fib4_entry->type;
fri.offload = false;
fri.trap = false;
fri.offload_failed = false;
fib_alias_hw_flags_set(mlxsw_sp_net(mlxsw_sp), &fri);
}

#if IS_ENABLED(CONFIG_IPV6)
static void
mlxsw_sp_fib6_offload_failed_flag_set(struct mlxsw_sp *mlxsw_sp,
struct fib6_info **rt_arr,
unsigned int nrt6)
{
int i;

/* In IPv6 a multipath route is represented using multiple routes, so
* we need to set the flags on all of them.
*/
for (i = 0; i < nrt6; i++)
fib6_info_hw_flags_set(mlxsw_sp_net(mlxsw_sp), rt_arr[i],
false, false, true);
}
#else
static void
mlxsw_sp_fib6_offload_failed_flag_set(struct mlxsw_sp *mlxsw_sp,
struct fib6_info **rt_arr,
unsigned int nrt6)
{
}
#endif

#if IS_ENABLED(CONFIG_IPV6)
static void
mlxsw_sp_fib6_entry_hw_flags_set(struct mlxsw_sp *mlxsw_sp,
Expand All @@ -5006,7 +5051,7 @@ mlxsw_sp_fib6_entry_hw_flags_set(struct mlxsw_sp *mlxsw_sp,
common);
list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list)
fib6_info_hw_flags_set(mlxsw_sp_net(mlxsw_sp), mlxsw_sp_rt6->rt,
should_offload, !should_offload);
should_offload, !should_offload, false);
}
#else
static void
Expand All @@ -5028,7 +5073,7 @@ mlxsw_sp_fib6_entry_hw_flags_clear(struct mlxsw_sp *mlxsw_sp,
common);
list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list)
fib6_info_hw_flags_set(mlxsw_sp_net(mlxsw_sp), mlxsw_sp_rt6->rt,
false, false);
false, false, false);
}
#else
static void
Expand Down Expand Up @@ -7021,6 +7066,8 @@ static void mlxsw_sp_router_fib4_event_process(struct mlxsw_sp *mlxsw_sp,
if (err) {
mlxsw_sp_fib_entry_op_ctx_priv_put_all(op_ctx);
mlxsw_sp_router_fib_abort(mlxsw_sp);
mlxsw_sp_fib4_offload_failed_flag_set(mlxsw_sp,
&fib_event->fen_info);
}
fib_info_put(fib_event->fen_info.fi);
break;
Expand All @@ -7042,6 +7089,7 @@ static void mlxsw_sp_router_fib6_event_process(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib_entry_op_ctx *op_ctx,
struct mlxsw_sp_fib_event *fib_event)
{
struct mlxsw_sp_fib6_event *fib6_event = &fib_event->fib6_event;
int err;

mlxsw_sp_span_respin(mlxsw_sp);
Expand All @@ -7053,6 +7101,9 @@ static void mlxsw_sp_router_fib6_event_process(struct mlxsw_sp *mlxsw_sp,
if (err) {
mlxsw_sp_fib_entry_op_ctx_priv_put_all(op_ctx);
mlxsw_sp_router_fib_abort(mlxsw_sp);
mlxsw_sp_fib6_offload_failed_flag_set(mlxsw_sp,
fib6_event->rt_arr,
fib6_event->nrt6);
}
mlxsw_sp_router_fib6_event_fini(&fib_event->fib6_event);
break;
Expand All @@ -7062,6 +7113,9 @@ static void mlxsw_sp_router_fib6_event_process(struct mlxsw_sp *mlxsw_sp,
if (err) {
mlxsw_sp_fib_entry_op_ctx_priv_put_all(op_ctx);
mlxsw_sp_router_fib_abort(mlxsw_sp);
mlxsw_sp_fib6_offload_failed_flag_set(mlxsw_sp,
fib6_event->rt_arr,
fib6_event->nrt6);
}
mlxsw_sp_router_fib6_event_fini(&fib_event->fib6_event);
break;
Expand Down
40 changes: 21 additions & 19 deletions drivers/net/netdevsim/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1012,23 +1012,25 @@ static int nsim_dev_reload_create(struct nsim_dev *nsim_dev,
nsim_dev->fw_update_status = true;
nsim_dev->fw_update_overwrite_mask = 0;

nsim_dev->fib_data = nsim_fib_create(devlink, extack);
if (IS_ERR(nsim_dev->fib_data))
return PTR_ERR(nsim_dev->fib_data);

nsim_devlink_param_load_driverinit_values(devlink);

err = nsim_dev_dummy_region_init(nsim_dev, devlink);
if (err)
goto err_fib_destroy;
return err;

err = nsim_dev_traps_init(devlink);
if (err)
goto err_dummy_region_exit;

nsim_dev->fib_data = nsim_fib_create(devlink, extack);
if (IS_ERR(nsim_dev->fib_data)) {
err = PTR_ERR(nsim_dev->fib_data);
goto err_traps_exit;
}

err = nsim_dev_health_init(nsim_dev, devlink);
if (err)
goto err_traps_exit;
goto err_fib_destroy;

err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count);
if (err)
Expand All @@ -1043,12 +1045,12 @@ static int nsim_dev_reload_create(struct nsim_dev *nsim_dev,

err_health_exit:
nsim_dev_health_exit(nsim_dev);
err_fib_destroy:
nsim_fib_destroy(devlink, nsim_dev->fib_data);
err_traps_exit:
nsim_dev_traps_exit(devlink);
err_dummy_region_exit:
nsim_dev_dummy_region_exit(nsim_dev);
err_fib_destroy:
nsim_fib_destroy(devlink, nsim_dev->fib_data);
return err;
}

Expand Down Expand Up @@ -1080,15 +1082,9 @@ int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev)
if (err)
goto err_devlink_free;

nsim_dev->fib_data = nsim_fib_create(devlink, NULL);
if (IS_ERR(nsim_dev->fib_data)) {
err = PTR_ERR(nsim_dev->fib_data);
goto err_resources_unregister;
}

err = devlink_register(devlink, &nsim_bus_dev->dev);
if (err)
goto err_fib_destroy;
goto err_resources_unregister;

err = devlink_params_register(devlink, nsim_devlink_params,
ARRAY_SIZE(nsim_devlink_params));
Expand All @@ -1108,9 +1104,15 @@ int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev)
if (err)
goto err_traps_exit;

nsim_dev->fib_data = nsim_fib_create(devlink, NULL);
if (IS_ERR(nsim_dev->fib_data)) {
err = PTR_ERR(nsim_dev->fib_data);
goto err_debugfs_exit;
}

err = nsim_dev_health_init(nsim_dev, devlink);
if (err)
goto err_debugfs_exit;
goto err_fib_destroy;

err = nsim_bpf_dev_init(nsim_dev);
if (err)
Expand All @@ -1128,6 +1130,8 @@ int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev)
nsim_bpf_dev_exit(nsim_dev);
err_health_exit:
nsim_dev_health_exit(nsim_dev);
err_fib_destroy:
nsim_fib_destroy(devlink, nsim_dev->fib_data);
err_debugfs_exit:
nsim_dev_debugfs_exit(nsim_dev);
err_traps_exit:
Expand All @@ -1139,8 +1143,6 @@ int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev)
ARRAY_SIZE(nsim_devlink_params));
err_dl_unregister:
devlink_unregister(devlink);
err_fib_destroy:
nsim_fib_destroy(devlink, nsim_dev->fib_data);
err_resources_unregister:
devlink_resources_unregister(devlink, NULL);
err_devlink_free:
Expand All @@ -1157,10 +1159,10 @@ static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev)
debugfs_remove(nsim_dev->take_snapshot);
nsim_dev_port_del_all(nsim_dev);
nsim_dev_health_exit(nsim_dev);
nsim_fib_destroy(devlink, nsim_dev->fib_data);
nsim_dev_traps_exit(devlink);
nsim_dev_dummy_region_exit(nsim_dev);
mutex_destroy(&nsim_dev->port_list_lock);
nsim_fib_destroy(devlink, nsim_dev->fib_data);
}

void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev)
Expand Down
Loading

0 comments on commit 5ea3c72

Please sign in to comment.