forked from Minki/linux
netdevsim: fib: Add debugfs to debug route offload failure
Add "fail_route_offload" flag to disallow offloading routes. It is needed to test "offload failed" notifications. Create the flag as part of nsim_fib_create() under fib directory and set it to false by default. When FIB_EVENT_ENTRY_{REPLACE, APPEND} are triggered and "fail_route_offload" value is true, set the appropriate hardware flag to make the kernel emit RTM_NEWROUTE notification with RTM_F_OFFLOAD_FAILED flag. Signed-off-by: Amit Cohen <amcohen@nvidia.com> Signed-off-by: Ido Schimmel <idosch@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
f57ab5b75f
commit
134c753242
@ -26,6 +26,7 @@
|
||||
#include <net/fib_rules.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include <net/nexthop.h>
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
#include "netdevsim.h"
|
||||
|
||||
@ -53,6 +54,8 @@ struct nsim_fib_data {
|
||||
struct work_struct fib_event_work;
|
||||
struct list_head fib_event_queue;
|
||||
spinlock_t fib_event_queue_lock; /* Protects fib event queue list */
|
||||
struct dentry *ddir;
|
||||
bool fail_route_offload;
|
||||
};
|
||||
|
||||
struct nsim_fib_rt_key {
|
||||
@ -303,6 +306,25 @@ nsim_fib4_rt_lookup(struct rhashtable *fib_rt_ht,
|
||||
return container_of(fib_rt, struct nsim_fib4_rt, common);
|
||||
}
|
||||
|
||||
static void
|
||||
nsim_fib4_rt_offload_failed_flag_set(struct net *net,
|
||||
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(net, &fri);
|
||||
}
|
||||
|
||||
static void nsim_fib4_rt_hw_flags_set(struct net *net,
|
||||
const struct nsim_fib4_rt *fib4_rt,
|
||||
bool trap)
|
||||
@ -384,6 +406,15 @@ static int nsim_fib4_rt_insert(struct nsim_fib_data *data,
|
||||
struct nsim_fib4_rt *fib4_rt, *fib4_rt_old;
|
||||
int err;
|
||||
|
||||
if (data->fail_route_offload) {
|
||||
/* For testing purposes, user set debugfs fail_route_offload
|
||||
* value to true. Simulate hardware programming latency and then
|
||||
* fail.
|
||||
*/
|
||||
msleep(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fib4_rt = nsim_fib4_rt_create(data, fen_info);
|
||||
if (!fib4_rt)
|
||||
return -ENOMEM;
|
||||
@ -423,6 +454,11 @@ static int nsim_fib4_event(struct nsim_fib_data *data,
|
||||
switch (event) {
|
||||
case FIB_EVENT_ENTRY_REPLACE:
|
||||
err = nsim_fib4_rt_insert(data, fen_info);
|
||||
if (err) {
|
||||
struct net *net = devlink_net(data->devlink);
|
||||
|
||||
nsim_fib4_rt_offload_failed_flag_set(net, fen_info);
|
||||
}
|
||||
break;
|
||||
case FIB_EVENT_ENTRY_DEL:
|
||||
nsim_fib4_rt_remove(data, fen_info);
|
||||
@ -564,6 +600,15 @@ static int nsim_fib6_rt_append(struct nsim_fib_data *data,
|
||||
struct nsim_fib6_rt *fib6_rt;
|
||||
int i, err;
|
||||
|
||||
if (data->fail_route_offload) {
|
||||
/* For testing purposes, user set debugfs fail_route_offload
|
||||
* value to true. Simulate hardware programming latency and then
|
||||
* fail.
|
||||
*/
|
||||
msleep(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fib6_rt = nsim_fib6_rt_lookup(&data->fib_rt_ht, rt);
|
||||
if (!fib6_rt)
|
||||
return -EINVAL;
|
||||
@ -586,6 +631,26 @@ err_fib6_rt_nh_del:
|
||||
return err;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
static void nsim_fib6_rt_offload_failed_flag_set(struct nsim_fib_data *data,
|
||||
struct fib6_info **rt_arr,
|
||||
unsigned int nrt6)
|
||||
|
||||
{
|
||||
struct net *net = devlink_net(data->devlink);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nrt6; i++)
|
||||
fib6_info_hw_flags_set(net, rt_arr[i], false, false, true);
|
||||
}
|
||||
#else
|
||||
static void nsim_fib6_rt_offload_failed_flag_set(struct nsim_fib_data *data,
|
||||
struct fib6_info **rt_arr,
|
||||
unsigned int nrt6)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
static void nsim_fib6_rt_hw_flags_set(struct nsim_fib_data *data,
|
||||
const struct nsim_fib6_rt *fib6_rt,
|
||||
@ -667,6 +732,15 @@ static int nsim_fib6_rt_insert(struct nsim_fib_data *data,
|
||||
struct nsim_fib6_rt *fib6_rt, *fib6_rt_old;
|
||||
int err;
|
||||
|
||||
if (data->fail_route_offload) {
|
||||
/* For testing purposes, user set debugfs fail_route_offload
|
||||
* value to true. Simulate hardware programming latency and then
|
||||
* fail.
|
||||
*/
|
||||
msleep(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fib6_rt = nsim_fib6_rt_create(data, fib6_event->rt_arr,
|
||||
fib6_event->nrt6);
|
||||
if (IS_ERR(fib6_rt))
|
||||
@ -764,7 +838,7 @@ static int nsim_fib6_event(struct nsim_fib_data *data,
|
||||
struct nsim_fib6_event *fib6_event,
|
||||
unsigned long event)
|
||||
{
|
||||
int err = 0;
|
||||
int err;
|
||||
|
||||
if (fib6_event->rt_arr[0]->fib6_src.plen)
|
||||
return 0;
|
||||
@ -772,9 +846,13 @@ static int nsim_fib6_event(struct nsim_fib_data *data,
|
||||
switch (event) {
|
||||
case FIB_EVENT_ENTRY_REPLACE:
|
||||
err = nsim_fib6_rt_insert(data, fib6_event);
|
||||
if (err)
|
||||
goto err_rt_offload_failed_flag_set;
|
||||
break;
|
||||
case FIB_EVENT_ENTRY_APPEND:
|
||||
err = nsim_fib6_rt_append(data, fib6_event);
|
||||
if (err)
|
||||
goto err_rt_offload_failed_flag_set;
|
||||
break;
|
||||
case FIB_EVENT_ENTRY_DEL:
|
||||
nsim_fib6_rt_remove(data, fib6_event);
|
||||
@ -783,6 +861,11 @@ static int nsim_fib6_event(struct nsim_fib_data *data,
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_rt_offload_failed_flag_set:
|
||||
nsim_fib6_rt_offload_failed_flag_set(data, fib6_event->rt_arr,
|
||||
fib6_event->nrt6);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1290,10 +1373,29 @@ static void nsim_fib_event_work(struct work_struct *work)
|
||||
mutex_unlock(&data->fib_lock);
|
||||
}
|
||||
|
||||
static int
|
||||
nsim_fib_debugfs_init(struct nsim_fib_data *data, struct nsim_dev *nsim_dev)
|
||||
{
|
||||
data->ddir = debugfs_create_dir("fib", nsim_dev->ddir);
|
||||
if (IS_ERR(data->ddir))
|
||||
return PTR_ERR(data->ddir);
|
||||
|
||||
data->fail_route_offload = false;
|
||||
debugfs_create_bool("fail_route_offload", 0600, data->ddir,
|
||||
&data->fail_route_offload);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nsim_fib_debugfs_exit(struct nsim_fib_data *data)
|
||||
{
|
||||
debugfs_remove_recursive(data->ddir);
|
||||
}
|
||||
|
||||
struct nsim_fib_data *nsim_fib_create(struct devlink *devlink,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct nsim_fib_data *data;
|
||||
struct nsim_dev *nsim_dev;
|
||||
int err;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
@ -1301,10 +1403,15 @@ struct nsim_fib_data *nsim_fib_create(struct devlink *devlink,
|
||||
return ERR_PTR(-ENOMEM);
|
||||
data->devlink = devlink;
|
||||
|
||||
err = rhashtable_init(&data->nexthop_ht, &nsim_nexthop_ht_params);
|
||||
nsim_dev = devlink_priv(devlink);
|
||||
err = nsim_fib_debugfs_init(data, nsim_dev);
|
||||
if (err)
|
||||
goto err_data_free;
|
||||
|
||||
err = rhashtable_init(&data->nexthop_ht, &nsim_nexthop_ht_params);
|
||||
if (err)
|
||||
goto err_debugfs_exit;
|
||||
|
||||
mutex_init(&data->fib_lock);
|
||||
INIT_LIST_HEAD(&data->fib_rt_list);
|
||||
err = rhashtable_init(&data->fib_rt_ht, &nsim_fib_rt_ht_params);
|
||||
@ -1365,6 +1472,8 @@ err_rhashtable_nexthop_destroy:
|
||||
rhashtable_free_and_destroy(&data->nexthop_ht, nsim_nexthop_free,
|
||||
data);
|
||||
mutex_destroy(&data->fib_lock);
|
||||
err_debugfs_exit:
|
||||
nsim_fib_debugfs_exit(data);
|
||||
err_data_free:
|
||||
kfree(data);
|
||||
return ERR_PTR(err);
|
||||
@ -1392,5 +1501,6 @@ void nsim_fib_destroy(struct devlink *devlink, struct nsim_fib_data *data)
|
||||
WARN_ON_ONCE(!list_empty(&data->fib_event_queue));
|
||||
WARN_ON_ONCE(!list_empty(&data->fib_rt_list));
|
||||
mutex_destroy(&data->fib_lock);
|
||||
nsim_fib_debugfs_exit(data);
|
||||
kfree(data);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user