netfilter: nf_tables: add set timeout API support
Add set timeout support to the netlink API. Sets with timeout support enabled can have a default timeout value and garbage collection interval specified. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Родитель
9911674fcf
Коммит
761da2935d
|
@ -258,6 +258,8 @@ void nft_unregister_set(struct nft_set_ops *ops);
|
||||||
* @dtype: data type (verdict or numeric type defined by userspace)
|
* @dtype: data type (verdict or numeric type defined by userspace)
|
||||||
* @size: maximum set size
|
* @size: maximum set size
|
||||||
* @nelems: number of elements
|
* @nelems: number of elements
|
||||||
|
* @timeout: default timeout value in msecs
|
||||||
|
* @gc_int: garbage collection interval in msecs
|
||||||
* @policy: set parameterization (see enum nft_set_policies)
|
* @policy: set parameterization (see enum nft_set_policies)
|
||||||
* @ops: set ops
|
* @ops: set ops
|
||||||
* @pnet: network namespace
|
* @pnet: network namespace
|
||||||
|
@ -274,6 +276,8 @@ struct nft_set {
|
||||||
u32 dtype;
|
u32 dtype;
|
||||||
u32 size;
|
u32 size;
|
||||||
u32 nelems;
|
u32 nelems;
|
||||||
|
u64 timeout;
|
||||||
|
u32 gc_int;
|
||||||
u16 policy;
|
u16 policy;
|
||||||
/* runtime data below here */
|
/* runtime data below here */
|
||||||
const struct nft_set_ops *ops ____cacheline_aligned;
|
const struct nft_set_ops *ops ____cacheline_aligned;
|
||||||
|
@ -295,6 +299,11 @@ struct nft_set *nf_tables_set_lookup(const struct nft_table *table,
|
||||||
struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
|
struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
|
||||||
const struct nlattr *nla);
|
const struct nlattr *nla);
|
||||||
|
|
||||||
|
static inline unsigned long nft_set_gc_interval(const struct nft_set *set)
|
||||||
|
{
|
||||||
|
return set->gc_int ? msecs_to_jiffies(set->gc_int) : HZ;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct nft_set_binding - nf_tables set binding
|
* struct nft_set_binding - nf_tables set binding
|
||||||
*
|
*
|
||||||
|
|
|
@ -208,12 +208,14 @@ enum nft_rule_compat_attributes {
|
||||||
* @NFT_SET_CONSTANT: set contents may not change while bound
|
* @NFT_SET_CONSTANT: set contents may not change while bound
|
||||||
* @NFT_SET_INTERVAL: set contains intervals
|
* @NFT_SET_INTERVAL: set contains intervals
|
||||||
* @NFT_SET_MAP: set is used as a dictionary
|
* @NFT_SET_MAP: set is used as a dictionary
|
||||||
|
* @NFT_SET_TIMEOUT: set uses timeouts
|
||||||
*/
|
*/
|
||||||
enum nft_set_flags {
|
enum nft_set_flags {
|
||||||
NFT_SET_ANONYMOUS = 0x1,
|
NFT_SET_ANONYMOUS = 0x1,
|
||||||
NFT_SET_CONSTANT = 0x2,
|
NFT_SET_CONSTANT = 0x2,
|
||||||
NFT_SET_INTERVAL = 0x4,
|
NFT_SET_INTERVAL = 0x4,
|
||||||
NFT_SET_MAP = 0x8,
|
NFT_SET_MAP = 0x8,
|
||||||
|
NFT_SET_TIMEOUT = 0x10,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -252,6 +254,8 @@ enum nft_set_desc_attributes {
|
||||||
* @NFTA_SET_POLICY: selection policy (NLA_U32)
|
* @NFTA_SET_POLICY: selection policy (NLA_U32)
|
||||||
* @NFTA_SET_DESC: set description (NLA_NESTED)
|
* @NFTA_SET_DESC: set description (NLA_NESTED)
|
||||||
* @NFTA_SET_ID: uniquely identifies a set in a transaction (NLA_U32)
|
* @NFTA_SET_ID: uniquely identifies a set in a transaction (NLA_U32)
|
||||||
|
* @NFTA_SET_TIMEOUT: default timeout value (NLA_U64)
|
||||||
|
* @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32)
|
||||||
*/
|
*/
|
||||||
enum nft_set_attributes {
|
enum nft_set_attributes {
|
||||||
NFTA_SET_UNSPEC,
|
NFTA_SET_UNSPEC,
|
||||||
|
@ -265,6 +269,8 @@ enum nft_set_attributes {
|
||||||
NFTA_SET_POLICY,
|
NFTA_SET_POLICY,
|
||||||
NFTA_SET_DESC,
|
NFTA_SET_DESC,
|
||||||
NFTA_SET_ID,
|
NFTA_SET_ID,
|
||||||
|
NFTA_SET_TIMEOUT,
|
||||||
|
NFTA_SET_GC_INTERVAL,
|
||||||
__NFTA_SET_MAX
|
__NFTA_SET_MAX
|
||||||
};
|
};
|
||||||
#define NFTA_SET_MAX (__NFTA_SET_MAX - 1)
|
#define NFTA_SET_MAX (__NFTA_SET_MAX - 1)
|
||||||
|
|
|
@ -2216,6 +2216,8 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
|
||||||
[NFTA_SET_POLICY] = { .type = NLA_U32 },
|
[NFTA_SET_POLICY] = { .type = NLA_U32 },
|
||||||
[NFTA_SET_DESC] = { .type = NLA_NESTED },
|
[NFTA_SET_DESC] = { .type = NLA_NESTED },
|
||||||
[NFTA_SET_ID] = { .type = NLA_U32 },
|
[NFTA_SET_ID] = { .type = NLA_U32 },
|
||||||
|
[NFTA_SET_TIMEOUT] = { .type = NLA_U64 },
|
||||||
|
[NFTA_SET_GC_INTERVAL] = { .type = NLA_U32 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = {
|
static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = {
|
||||||
|
@ -2366,6 +2368,13 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (set->timeout &&
|
||||||
|
nla_put_be64(skb, NFTA_SET_TIMEOUT, cpu_to_be64(set->timeout)))
|
||||||
|
goto nla_put_failure;
|
||||||
|
if (set->gc_int &&
|
||||||
|
nla_put_be32(skb, NFTA_SET_GC_INTERVAL, htonl(set->gc_int)))
|
||||||
|
goto nla_put_failure;
|
||||||
|
|
||||||
if (set->policy != NFT_SET_POL_PERFORMANCE) {
|
if (set->policy != NFT_SET_POL_PERFORMANCE) {
|
||||||
if (nla_put_be32(skb, NFTA_SET_POLICY, htonl(set->policy)))
|
if (nla_put_be32(skb, NFTA_SET_POLICY, htonl(set->policy)))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
@ -2578,7 +2587,8 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
|
||||||
char name[IFNAMSIZ];
|
char name[IFNAMSIZ];
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
bool create;
|
bool create;
|
||||||
u32 ktype, dtype, flags, policy;
|
u64 timeout;
|
||||||
|
u32 ktype, dtype, flags, policy, gc_int;
|
||||||
struct nft_set_desc desc;
|
struct nft_set_desc desc;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -2605,7 +2615,8 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
|
||||||
if (nla[NFTA_SET_FLAGS] != NULL) {
|
if (nla[NFTA_SET_FLAGS] != NULL) {
|
||||||
flags = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS]));
|
flags = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS]));
|
||||||
if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT |
|
if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT |
|
||||||
NFT_SET_INTERVAL | NFT_SET_MAP))
|
NFT_SET_INTERVAL | NFT_SET_MAP |
|
||||||
|
NFT_SET_TIMEOUT))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2631,6 +2642,19 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
|
||||||
} else if (flags & NFT_SET_MAP)
|
} else if (flags & NFT_SET_MAP)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
timeout = 0;
|
||||||
|
if (nla[NFTA_SET_TIMEOUT] != NULL) {
|
||||||
|
if (!(flags & NFT_SET_TIMEOUT))
|
||||||
|
return -EINVAL;
|
||||||
|
timeout = be64_to_cpu(nla_get_be64(nla[NFTA_SET_TIMEOUT]));
|
||||||
|
}
|
||||||
|
gc_int = 0;
|
||||||
|
if (nla[NFTA_SET_GC_INTERVAL] != NULL) {
|
||||||
|
if (!(flags & NFT_SET_TIMEOUT))
|
||||||
|
return -EINVAL;
|
||||||
|
gc_int = ntohl(nla_get_be32(nla[NFTA_SET_GC_INTERVAL]));
|
||||||
|
}
|
||||||
|
|
||||||
policy = NFT_SET_POL_PERFORMANCE;
|
policy = NFT_SET_POL_PERFORMANCE;
|
||||||
if (nla[NFTA_SET_POLICY] != NULL)
|
if (nla[NFTA_SET_POLICY] != NULL)
|
||||||
policy = ntohl(nla_get_be32(nla[NFTA_SET_POLICY]));
|
policy = ntohl(nla_get_be32(nla[NFTA_SET_POLICY]));
|
||||||
|
@ -2699,6 +2723,8 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
|
||||||
set->flags = flags;
|
set->flags = flags;
|
||||||
set->size = desc.size;
|
set->size = desc.size;
|
||||||
set->policy = policy;
|
set->policy = policy;
|
||||||
|
set->timeout = timeout;
|
||||||
|
set->gc_int = gc_int;
|
||||||
|
|
||||||
err = ops->init(set, &desc, nla);
|
err = ops->init(set, &desc, nla);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче