forked from mirrors/linux
		
	ila: Flush netlink command to clear xlat table
Add ILA_CMD_FLUSH netlink command to clear the ILA translation table. Signed-off-by: Tom Herbert <tom@quantonium.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									ad68147ef2
								
							
						
					
					
						commit
						b6e71bdebb
					
				
					 4 changed files with 68 additions and 2 deletions
				
			
		| 
						 | 
					@ -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);
 | 
				
			||||||
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[] = {
 | 
				
			||||||
		.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)
 | 
				
			||||||
	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)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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)
 | 
				
			||||||
	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,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue