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

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
...@@ -30,6 +30,7 @@ enum { ...@@ -30,6 +30,7 @@ enum {
ILA_CMD_ADD, ILA_CMD_ADD,
ILA_CMD_DEL, ILA_CMD_DEL,
ILA_CMD_GET, ILA_CMD_GET,
ILA_CMD_FLUSH,
__ILA_CMD_MAX, __ILA_CMD_MAX,
}; };
......
...@@ -123,6 +123,7 @@ void ila_xlat_exit_net(struct net *net); ...@@ -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_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_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_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_start(struct netlink_callback *cb);
int ila_xlat_nl_dump_done(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); int ila_xlat_nl_dump(struct sk_buff *skb, struct netlink_callback *cb);
......
...@@ -26,6 +26,12 @@ static const struct genl_ops ila_nl_ops[] = { ...@@ -26,6 +26,12 @@ static const struct genl_ops ila_nl_ops[] = {
.policy = ila_nl_policy, .policy = ila_nl_policy,
.flags = GENL_ADMIN_PERM, .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, .cmd = ILA_CMD_GET,
.doit = ila_xlat_nl_cmd_get_mapping, .doit = ila_xlat_nl_cmd_get_mapping,
......
...@@ -164,9 +164,9 @@ static inline void ila_release(struct ila_map *ila) ...@@ -164,9 +164,9 @@ static inline void ila_release(struct ila_map *ila)
kfree_rcu(ila, rcu); 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 */ /* Assume rcu_readlock held */
while (ila) { while (ila) {
...@@ -176,6 +176,11 @@ static void ila_free_cb(void *ptr, void *arg) ...@@ -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 int ila_xlat_addr(struct sk_buff *skb, bool sir2ila);
static unsigned int static unsigned int
...@@ -365,6 +370,59 @@ int ila_xlat_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info) ...@@ -365,6 +370,59 @@ int ila_xlat_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info)
return 0; 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) static int ila_fill_info(struct ila_map *ila, struct sk_buff *msg)
{ {
if (nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR, if (nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR,
......
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