Skip to content

Commit

Permalink
Merge branch 'resil-nhgroups-netdevsim-selftests'
Browse files Browse the repository at this point in the history
Petr Machata says:

====================
net: Resilient NH groups: netdevsim, selftests

Support for resilient next-hop groups was added in a previous patch set.
Resilient next hop groups add a layer of indirection between the SKB hash
and the next hop. Thus the hash is used to reference a hash table bucket,
which is then used to reference a particular next hop. This allows the
system more flexibility when assigning SKB hash space to next hops.
Previously, each next hop had to be assigned a continuous range of SKB hash
space. With a hash table as an intermediate layer, it is possible to
reassign next hops with a hash table bucket granularity. In turn, this
mends issues with traffic flow redirection resulting from next hop removal
or adjustments in next-hop weights.

This patch set introduces mock offloading of resilient next hop groups by
the netdevsim driver, and a suite of selftests.

- Patch #1 adds a netdevsim-specific lock to protect next-hop hashtable.
  Previously, netdevsim relied on RTNL to maintain mutual exclusion.
  Patch #2 extracts a helper to make the following patches clearer.

- Patch #3 implements the support for offloading of resilient next-hop
  groups.

- Patch #4 introduces a new debugfs interface to set activity on a selected
  next-hop bucket. This simulates how HW can periodically report bucket
  activity, and buckets thus marked are expected to be exempt from
  migration to new next hops when the group changes.

- Patches #5 and #6 clean up the fib_nexthop selftests.

- Patches #7, #8 and #9 add tests for resilient next hop groups. Patch #7
  adds resilient-hashing counterparts to fib_nexthops.sh. Patch #8 adds a
  new traffic test for resilient next-hop groups. Patch #9 adds a new
  traffic test for tunneling.

- Patch #10 actually leverages the netdevsim offload to implement a suite
  of algorithmic tests that verify how and when buckets are migrated under
  various simulated workload scenarios.

The overall plan is to contribute approximately the following patchsets:

1) Nexthop policy refactoring (already pushed)
2) Preparations for resilient next hop groups (already pushed)
3) Implementation of resilient next hop group (already pushed)
4) Netdevsim offload plus a suite of selftests (this patchset)
5) Preparations for mlxsw offload of resilient next-hop groups
6) mlxsw offload including selftests

Interested parties can look at the complete code at [2].

[1] https://tools.ietf.org/html/rfc2992
[2] https://github.com/idosch/linux/commits/submit/res_integ_v1
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 13, 2021
2 parents b202923 + b8a07c4 commit e9e90a7
Show file tree
Hide file tree
Showing 5 changed files with 2,059 additions and 10 deletions.
139 changes: 133 additions & 6 deletions drivers/net/netdevsim/fib.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
*/

#include <linux/bitmap.h>
#include <linux/in6.h>
#include <linux/kernel.h>
#include <linux/list.h>
Expand Down Expand Up @@ -47,15 +48,18 @@ struct nsim_fib_data {
struct nsim_fib_entry nexthops;
struct rhashtable fib_rt_ht;
struct list_head fib_rt_list;
struct mutex fib_lock; /* Protects hashtable and list */
struct mutex fib_lock; /* Protects FIB HT and list */
struct notifier_block nexthop_nb;
struct rhashtable nexthop_ht;
struct devlink *devlink;
struct work_struct fib_event_work;
struct list_head fib_event_queue;
spinlock_t fib_event_queue_lock; /* Protects fib event queue list */
struct mutex nh_lock; /* Protects NH HT */
struct dentry *ddir;
bool fail_route_offload;
bool fail_res_nexthop_group_replace;
bool fail_nexthop_bucket_replace;
};

struct nsim_fib_rt_key {
Expand Down Expand Up @@ -116,6 +120,7 @@ struct nsim_nexthop {
struct rhash_head ht_node;
u64 occ;
u32 id;
bool is_resilient;
};

static const struct rhashtable_params nsim_nexthop_ht_params = {
Expand Down Expand Up @@ -1114,6 +1119,10 @@ static struct nsim_nexthop *nsim_nexthop_create(struct nsim_fib_data *data,
for (i = 0; i < info->nh_grp->num_nh; i++)
occ += info->nh_grp->nh_entries[i].weight;
break;
case NH_NOTIFIER_INFO_TYPE_RES_TABLE:
occ = info->nh_res_table->num_nh_buckets;
nexthop->is_resilient = true;
break;
default:
NL_SET_ERR_MSG_MOD(info->extack, "Unsupported nexthop type");
kfree(nexthop);
Expand Down Expand Up @@ -1156,6 +1165,21 @@ static int nsim_nexthop_account(struct nsim_fib_data *data, u64 occ,

}

static void nsim_nexthop_hw_flags_set(struct net *net,
const struct nsim_nexthop *nexthop,
bool trap)
{
int i;

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,
struct nsim_nexthop *nexthop,
struct netlink_ext_ack *extack)
Expand All @@ -1174,7 +1198,7 @@ static int nsim_nexthop_add(struct nsim_fib_data *data,
goto err_nexthop_dismiss;
}

nexthop_set_hw_flags(net, nexthop->id, false, true);
nsim_nexthop_hw_flags_set(net, nexthop, true);

return 0;

Expand Down Expand Up @@ -1203,7 +1227,7 @@ static int nsim_nexthop_replace(struct nsim_fib_data *data,
goto err_nexthop_dismiss;
}

nexthop_set_hw_flags(net, nexthop->id, false, true);
nsim_nexthop_hw_flags_set(net, nexthop, true);
nsim_nexthop_account(data, nexthop_old->occ, false, extack);
nsim_nexthop_destroy(nexthop_old);

Expand Down Expand Up @@ -1254,6 +1278,32 @@ static void nsim_nexthop_remove(struct nsim_fib_data *data,
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,
void *ptr)
{
Expand All @@ -1262,19 +1312,25 @@ static int nsim_nexthop_event_nb(struct notifier_block *nb, unsigned long event,
struct nh_notifier_info *info = ptr;
int err = 0;

ASSERT_RTNL();

mutex_lock(&data->nh_lock);
switch (event) {
case NEXTHOP_EVENT_REPLACE:
err = nsim_nexthop_insert(data, info);
break;
case NEXTHOP_EVENT_DEL:
nsim_nexthop_remove(data, info);
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:
break;
}

mutex_unlock(&data->nh_lock);
return notifier_from_errno(err);
}

Expand All @@ -1285,11 +1341,68 @@ static void nsim_nexthop_free(void *ptr, void *arg)
struct net *net;

net = devlink_net(data->devlink);
nexthop_set_hw_flags(net, nexthop->id, false, false);
nsim_nexthop_hw_flags_set(net, nexthop, false);
nsim_nexthop_account(data, nexthop->occ, false, NULL);
nsim_nexthop_destroy(nexthop);
}

static ssize_t nsim_nexthop_bucket_activity_write(struct file *file,
const char __user *user_buf,
size_t size, loff_t *ppos)
{
struct nsim_fib_data *data = file->private_data;
struct net *net = devlink_net(data->devlink);
struct nsim_nexthop *nexthop;
unsigned long *activity;
loff_t pos = *ppos;
u16 bucket_index;
char buf[128];
int err = 0;
u32 nhid;

if (pos != 0)
return -EINVAL;
if (size > sizeof(buf))
return -EINVAL;
if (copy_from_user(buf, user_buf, size))
return -EFAULT;
if (sscanf(buf, "%u %hu", &nhid, &bucket_index) != 2)
return -EINVAL;

rtnl_lock();

nexthop = rhashtable_lookup_fast(&data->nexthop_ht, &nhid,
nsim_nexthop_ht_params);
if (!nexthop || !nexthop->is_resilient ||
bucket_index >= nexthop->occ) {
err = -EINVAL;
goto out;
}

activity = bitmap_zalloc(nexthop->occ, GFP_KERNEL);
if (!activity) {
err = -ENOMEM;
goto out;
}

bitmap_set(activity, bucket_index, 1);
nexthop_res_grp_activity_update(net, nhid, nexthop->occ, activity);
bitmap_free(activity);

out:
rtnl_unlock();

*ppos = size;
return err ?: size;
}

static const struct file_operations nsim_nexthop_bucket_activity_fops = {
.open = simple_open,
.write = nsim_nexthop_bucket_activity_write,
.llseek = no_llseek,
.owner = THIS_MODULE,
};

static u64 nsim_fib_ipv4_resource_occ_get(void *priv)
{
struct nsim_fib_data *data = priv;
Expand Down Expand Up @@ -1379,6 +1492,17 @@ nsim_fib_debugfs_init(struct nsim_fib_data *data, struct nsim_dev *nsim_dev)
data->fail_route_offload = false;
debugfs_create_bool("fail_route_offload", 0600, data->ddir,
&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);

debugfs_create_file("nexthop_bucket_activity", 0200, data->ddir,
data, &nsim_nexthop_bucket_activity_fops);
return 0;
}

Expand All @@ -1404,6 +1528,7 @@ struct nsim_fib_data *nsim_fib_create(struct devlink *devlink,
if (err)
goto err_data_free;

mutex_init(&data->nh_lock);
err = rhashtable_init(&data->nexthop_ht, &nsim_nexthop_ht_params);
if (err)
goto err_debugfs_exit;
Expand Down Expand Up @@ -1469,6 +1594,7 @@ struct nsim_fib_data *nsim_fib_create(struct devlink *devlink,
data);
mutex_destroy(&data->fib_lock);
err_debugfs_exit:
mutex_destroy(&data->nh_lock);
nsim_fib_debugfs_exit(data);
err_data_free:
kfree(data);
Expand Down Expand Up @@ -1497,6 +1623,7 @@ 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);
mutex_destroy(&data->nh_lock);
nsim_fib_debugfs_exit(data);
kfree(data);
}
Loading

0 comments on commit e9e90a7

Please sign in to comment.