netfilter: ipset: Introduce the counter extension in the core

Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Jozsef Kadlecsik 2013-04-27 14:38:56 +02:00 committed by Pablo Neira Ayuso
parent 7d47d972b5
commit 34d666d489
3 changed files with 86 additions and 4 deletions

View file

@ -52,18 +52,24 @@ enum ip_set_extension {
IPSET_EXT_NONE = 0,
IPSET_EXT_BIT_TIMEOUT = 1,
IPSET_EXT_TIMEOUT = (1 << IPSET_EXT_BIT_TIMEOUT),
IPSET_EXT_BIT_COUNTER = 2,
IPSET_EXT_COUNTER = (1 << IPSET_EXT_BIT_COUNTER),
};
/* Extension offsets */
enum ip_set_offset {
IPSET_OFFSET_TIMEOUT = 0,
IPSET_OFFSET_COUNTER,
IPSET_OFFSET_MAX,
};
#define SET_WITH_TIMEOUT(s) ((s)->extensions & IPSET_EXT_TIMEOUT)
#define SET_WITH_COUNTER(s) ((s)->extensions & IPSET_EXT_COUNTER)
struct ip_set_ext {
unsigned long timeout;
u64 packets;
u64 bytes;
};
struct ip_set;
@ -177,6 +183,65 @@ struct ip_set {
void *data;
};
struct ip_set_counter {
atomic64_t bytes;
atomic64_t packets;
};
static inline void
ip_set_add_bytes(u64 bytes, struct ip_set_counter *counter)
{
atomic64_add((long long)bytes, &(counter)->bytes);
}
static inline void
ip_set_add_packets(u64 packets, struct ip_set_counter *counter)
{
atomic64_add((long long)packets, &(counter)->packets);
}
static inline u64
ip_set_get_bytes(const struct ip_set_counter *counter)
{
return (u64)atomic64_read(&(counter)->bytes);
}
static inline u64
ip_set_get_packets(const struct ip_set_counter *counter)
{
return (u64)atomic64_read(&(counter)->packets);
}
static inline void
ip_set_update_counter(struct ip_set_counter *counter,
const struct ip_set_ext *ext,
struct ip_set_ext *mext, u32 flags)
{
if (ext->packets != ULLONG_MAX) {
ip_set_add_bytes(ext->bytes, counter);
ip_set_add_packets(ext->packets, counter);
}
}
static inline bool
ip_set_put_counter(struct sk_buff *skb, struct ip_set_counter *counter)
{
return nla_put_net64(skb, IPSET_ATTR_BYTES,
cpu_to_be64(ip_set_get_bytes(counter))) ||
nla_put_net64(skb, IPSET_ATTR_PACKETS,
cpu_to_be64(ip_set_get_packets(counter)));
}
static inline void
ip_set_init_counter(struct ip_set_counter *counter,
const struct ip_set_ext *ext)
{
if (ext->bytes != ULLONG_MAX)
atomic64_set(&(counter)->bytes, (long long)(ext->bytes));
if (ext->packets != ULLONG_MAX)
atomic64_set(&(counter)->packets, (long long)(ext->packets));
}
/* register and unregister set references */
extern ip_set_id_t ip_set_get_byname(const char *name, struct ip_set **set);
extern void ip_set_put_byindex(ip_set_id_t index);
@ -318,10 +383,12 @@ bitmap_bytes(u32 a, u32 b)
#include <linux/netfilter/ipset/ip_set_timeout.h>
#define IP_SET_INIT_KEXT(skb, opt, map) \
{ .timeout = ip_set_adt_opt_timeout(opt, map) }
#define IP_SET_INIT_KEXT(skb, opt, map) \
{ .bytes = (skb)->len, .packets = 1, \
.timeout = ip_set_adt_opt_timeout(opt, map) }
#define IP_SET_INIT_UEXT(map) \
{ .timeout = (map)->timeout }
#define IP_SET_INIT_UEXT(map) \
{ .bytes = ULLONG_MAX, .packets = ULLONG_MAX, \
.timeout = (map)->timeout }
#endif /*_IP_SET_H */