Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b6e71bde authored by Tom Herbert's avatar Tom Herbert Committed by David S. Miller
Browse files

ila: Flush netlink command to clear xlat table



Add ILA_CMD_FLUSH netlink command to clear the ILA translation table.

Signed-off-by: default avatarTom Herbert <tom@quantonium.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ad68147e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ enum {
	ILA_CMD_ADD,
	ILA_CMD_DEL,
	ILA_CMD_GET,
	ILA_CMD_FLUSH,

	__ILA_CMD_MAX,
};
+1 −0
Original line number Diff line number Diff line
@@ -123,6 +123,7 @@ void ila_xlat_exit_net(struct net *net);
int ila_xlat_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info);
int ila_xlat_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info);
int ila_xlat_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info);
int ila_xlat_nl_cmd_flush(struct sk_buff *skb, struct genl_info *info);
int ila_xlat_nl_dump_start(struct netlink_callback *cb);
int ila_xlat_nl_dump_done(struct netlink_callback *cb);
int ila_xlat_nl_dump(struct sk_buff *skb, struct netlink_callback *cb);
+6 −0
Original line number Diff line number Diff line
@@ -26,6 +26,12 @@ static const struct genl_ops ila_nl_ops[] = {
		.policy = ila_nl_policy,
		.flags = GENL_ADMIN_PERM,
	},
	{
		.cmd = ILA_CMD_FLUSH,
		.doit = ila_xlat_nl_cmd_flush,
		.policy = ila_nl_policy,
		.flags = GENL_ADMIN_PERM,
	},
	{
		.cmd = ILA_CMD_GET,
		.doit = ila_xlat_nl_cmd_get_mapping,
+60 −2
Original line number Diff line number Diff line
@@ -164,9 +164,9 @@ static inline void ila_release(struct ila_map *ila)
	kfree_rcu(ila, rcu);
}

static void ila_free_cb(void *ptr, void *arg)
static void ila_free_node(struct ila_map *ila)
{
	struct ila_map *ila = (struct ila_map *)ptr, *next;
	struct ila_map *next;

	/* Assume rcu_readlock held */
	while (ila) {
@@ -176,6 +176,11 @@ static void ila_free_cb(void *ptr, void *arg)
	}
}

static void ila_free_cb(void *ptr, void *arg)
{
	ila_free_node((struct ila_map *)ptr);
}

static int ila_xlat_addr(struct sk_buff *skb, bool sir2ila);

static unsigned int
@@ -365,6 +370,59 @@ int ila_xlat_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info)
	return 0;
}

static inline spinlock_t *lock_from_ila_map(struct ila_net *ilan,
					    struct ila_map *ila)
{
	return ila_get_lock(ilan, ila->xp.ip.locator_match);
}

int ila_xlat_nl_cmd_flush(struct sk_buff *skb, struct genl_info *info)
{
	struct net *net = genl_info_net(info);
	struct ila_net *ilan = net_generic(net, ila_net_id);
	struct rhashtable_iter iter;
	struct ila_map *ila;
	spinlock_t *lock;
	int ret;

	ret = rhashtable_walk_init(&ilan->xlat.rhash_table, &iter, GFP_KERNEL);
	if (ret)
		goto done;

	rhashtable_walk_start(&iter);

	for (;;) {
		ila = rhashtable_walk_next(&iter);

		if (IS_ERR(ila)) {
			if (PTR_ERR(ila) == -EAGAIN)
				continue;
			ret = PTR_ERR(ila);
			goto done;
		} else if (!ila) {
			break;
		}

		lock = lock_from_ila_map(ilan, ila);

		spin_lock(lock);

		ret = rhashtable_remove_fast(&ilan->xlat.rhash_table,
					     &ila->node, rht_params);
		if (!ret)
			ila_free_node(ila);

		spin_unlock(lock);

		if (ret)
			break;
	}

done:
	rhashtable_walk_stop(&iter);
	return ret;
}

static int ila_fill_info(struct ila_map *ila, struct sk_buff *msg)
{
	if (nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR,