Commit d8eaa4fa authored by Ido Schimmel's avatar Ido Schimmel Committed by David S. Miller

netdevsim: Add support for resilient nexthop groups

Allow resilient nexthop groups to be programmed and account their
occupancy according to their number of buckets. The nexthop group itself
as well as its buckets are marked with hardware flags (i.e.,
'RTNH_F_TRAP').

Replacement of a single nexthop bucket can fail using the following
debugfs knob:

 # cat /sys/kernel/debug/netdevsim/netdevsim10/fib/fail_nexthop_bucket_replace
 N
 # echo 1 > /sys/kernel/debug/netdevsim/netdevsim10/fib/fail_nexthop_bucket_replace
 # cat /sys/kernel/debug/netdevsim/netdevsim10/fib/fail_nexthop_bucket_replace
 Y

Replacement of a resilient nexthop group can fail using the following
debugfs knob:

 # cat /sys/kernel/debug/netdevsim/netdevsim10/fib/fail_res_nexthop_group_replace
 N
 # echo 1 > /sys/kernel/debug/netdevsim/netdevsim10/fib/fail_res_nexthop_group_replace
 # cat /sys/kernel/debug/netdevsim/netdevsim10/fib/fail_res_nexthop_group_replace
 Y

This enables testing of various error paths.
Signed-off-by: default avatarIdo Schimmel <idosch@nvidia.com>
Reviewed-by: default avatarPetr Machata <petrm@nvidia.com>
Signed-off-by: default avatarPetr Machata <petrm@nvidia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 40ff8371
...@@ -57,6 +57,8 @@ struct nsim_fib_data { ...@@ -57,6 +57,8 @@ struct nsim_fib_data {
struct mutex nh_lock; /* Protects NH HT */ struct mutex nh_lock; /* Protects NH HT */
struct dentry *ddir; struct dentry *ddir;
bool fail_route_offload; bool fail_route_offload;
bool fail_res_nexthop_group_replace;
bool fail_nexthop_bucket_replace;
}; };
struct nsim_fib_rt_key { struct nsim_fib_rt_key {
...@@ -117,6 +119,7 @@ struct nsim_nexthop { ...@@ -117,6 +119,7 @@ struct nsim_nexthop {
struct rhash_head ht_node; struct rhash_head ht_node;
u64 occ; u64 occ;
u32 id; u32 id;
bool is_resilient;
}; };
static const struct rhashtable_params nsim_nexthop_ht_params = { static const struct rhashtable_params nsim_nexthop_ht_params = {
...@@ -1115,6 +1118,10 @@ static struct nsim_nexthop *nsim_nexthop_create(struct nsim_fib_data *data, ...@@ -1115,6 +1118,10 @@ static struct nsim_nexthop *nsim_nexthop_create(struct nsim_fib_data *data,
for (i = 0; i < info->nh_grp->num_nh; i++) for (i = 0; i < info->nh_grp->num_nh; i++)
occ += info->nh_grp->nh_entries[i].weight; occ += info->nh_grp->nh_entries[i].weight;
break; break;
case NH_NOTIFIER_INFO_TYPE_RES_TABLE:
occ = info->nh_res_table->num_nh_buckets;
nexthop->is_resilient = true;
break;
default: default:
NL_SET_ERR_MSG_MOD(info->extack, "Unsupported nexthop type"); NL_SET_ERR_MSG_MOD(info->extack, "Unsupported nexthop type");
kfree(nexthop); kfree(nexthop);
...@@ -1161,7 +1168,15 @@ static void nsim_nexthop_hw_flags_set(struct net *net, ...@@ -1161,7 +1168,15 @@ static void nsim_nexthop_hw_flags_set(struct net *net,
const struct nsim_nexthop *nexthop, const struct nsim_nexthop *nexthop,
bool trap) bool trap)
{ {
int i;
nexthop_set_hw_flags(net, nexthop->id, false, trap); nexthop_set_hw_flags(net, nexthop->id, false, trap);
if (!nexthop->is_resilient)
return;
for (i = 0; i < nexthop->occ; i++)
nexthop_bucket_set_hw_flags(net, nexthop->id, i, false, trap);
} }
static int nsim_nexthop_add(struct nsim_fib_data *data, static int nsim_nexthop_add(struct nsim_fib_data *data,
...@@ -1262,6 +1277,32 @@ static void nsim_nexthop_remove(struct nsim_fib_data *data, ...@@ -1262,6 +1277,32 @@ static void nsim_nexthop_remove(struct nsim_fib_data *data,
nsim_nexthop_destroy(nexthop); nsim_nexthop_destroy(nexthop);
} }
static int nsim_nexthop_res_table_pre_replace(struct nsim_fib_data *data,
struct nh_notifier_info *info)
{
if (data->fail_res_nexthop_group_replace) {
NL_SET_ERR_MSG_MOD(info->extack, "Failed to replace a resilient nexthop group");
return -EINVAL;
}
return 0;
}
static int nsim_nexthop_bucket_replace(struct nsim_fib_data *data,
struct nh_notifier_info *info)
{
if (data->fail_nexthop_bucket_replace) {
NL_SET_ERR_MSG_MOD(info->extack, "Failed to replace nexthop bucket");
return -EINVAL;
}
nexthop_bucket_set_hw_flags(info->net, info->id,
info->nh_res_bucket->bucket_index,
false, true);
return 0;
}
static int nsim_nexthop_event_nb(struct notifier_block *nb, unsigned long event, static int nsim_nexthop_event_nb(struct notifier_block *nb, unsigned long event,
void *ptr) void *ptr)
{ {
...@@ -1278,6 +1319,12 @@ static int nsim_nexthop_event_nb(struct notifier_block *nb, unsigned long event, ...@@ -1278,6 +1319,12 @@ static int nsim_nexthop_event_nb(struct notifier_block *nb, unsigned long event,
case NEXTHOP_EVENT_DEL: case NEXTHOP_EVENT_DEL:
nsim_nexthop_remove(data, info); nsim_nexthop_remove(data, info);
break; break;
case NEXTHOP_EVENT_RES_TABLE_PRE_REPLACE:
err = nsim_nexthop_res_table_pre_replace(data, info);
break;
case NEXTHOP_EVENT_BUCKET_REPLACE:
err = nsim_nexthop_bucket_replace(data, info);
break;
default: default:
break; break;
} }
...@@ -1387,6 +1434,14 @@ nsim_fib_debugfs_init(struct nsim_fib_data *data, struct nsim_dev *nsim_dev) ...@@ -1387,6 +1434,14 @@ nsim_fib_debugfs_init(struct nsim_fib_data *data, struct nsim_dev *nsim_dev)
data->fail_route_offload = false; data->fail_route_offload = false;
debugfs_create_bool("fail_route_offload", 0600, data->ddir, debugfs_create_bool("fail_route_offload", 0600, data->ddir,
&data->fail_route_offload); &data->fail_route_offload);
data->fail_res_nexthop_group_replace = false;
debugfs_create_bool("fail_res_nexthop_group_replace", 0600, data->ddir,
&data->fail_res_nexthop_group_replace);
data->fail_nexthop_bucket_replace = false;
debugfs_create_bool("fail_nexthop_bucket_replace", 0600, data->ddir,
&data->fail_nexthop_bucket_replace);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment