1 #ifndef _IP_SET_COUNTER_H
2 #define _IP_SET_COUNTER_H
3 
4 /* Copyright (C) 2015 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10 
11 #ifdef __KERNEL__
12 
13 static inline void
ip_set_add_bytes(u64 bytes,struct ip_set_counter * counter)14 ip_set_add_bytes(u64 bytes, struct ip_set_counter *counter)
15 {
16 	atomic64_add((long long)bytes, &(counter)->bytes);
17 }
18 
19 static inline void
ip_set_add_packets(u64 packets,struct ip_set_counter * counter)20 ip_set_add_packets(u64 packets, struct ip_set_counter *counter)
21 {
22 	atomic64_add((long long)packets, &(counter)->packets);
23 }
24 
25 static inline u64
ip_set_get_bytes(const struct ip_set_counter * counter)26 ip_set_get_bytes(const struct ip_set_counter *counter)
27 {
28 	return (u64)atomic64_read(&(counter)->bytes);
29 }
30 
31 static inline u64
ip_set_get_packets(const struct ip_set_counter * counter)32 ip_set_get_packets(const struct ip_set_counter *counter)
33 {
34 	return (u64)atomic64_read(&(counter)->packets);
35 }
36 
37 static inline bool
ip_set_match_counter(u64 counter,u64 match,u8 op)38 ip_set_match_counter(u64 counter, u64 match, u8 op)
39 {
40 	switch (op) {
41 	case IPSET_COUNTER_NONE:
42 		return true;
43 	case IPSET_COUNTER_EQ:
44 		return counter == match;
45 	case IPSET_COUNTER_NE:
46 		return counter != match;
47 	case IPSET_COUNTER_LT:
48 		return counter < match;
49 	case IPSET_COUNTER_GT:
50 		return counter > match;
51 	}
52 	return false;
53 }
54 
55 static inline void
ip_set_update_counter(struct ip_set_counter * counter,const struct ip_set_ext * ext,u32 flags)56 ip_set_update_counter(struct ip_set_counter *counter,
57 		      const struct ip_set_ext *ext, u32 flags)
58 {
59 	if (ext->packets != ULLONG_MAX &&
60 	    !(flags & IPSET_FLAG_SKIP_COUNTER_UPDATE)) {
61 		ip_set_add_bytes(ext->bytes, counter);
62 		ip_set_add_packets(ext->packets, counter);
63 	}
64 }
65 
66 static inline bool
ip_set_put_counter(struct sk_buff * skb,const struct ip_set_counter * counter)67 ip_set_put_counter(struct sk_buff *skb, const struct ip_set_counter *counter)
68 {
69 	return nla_put_net64(skb, IPSET_ATTR_BYTES,
70 			     cpu_to_be64(ip_set_get_bytes(counter)),
71 			     IPSET_ATTR_PAD) ||
72 	       nla_put_net64(skb, IPSET_ATTR_PACKETS,
73 			     cpu_to_be64(ip_set_get_packets(counter)),
74 			     IPSET_ATTR_PAD);
75 }
76 
77 static inline void
ip_set_init_counter(struct ip_set_counter * counter,const struct ip_set_ext * ext)78 ip_set_init_counter(struct ip_set_counter *counter,
79 		    const struct ip_set_ext *ext)
80 {
81 	if (ext->bytes != ULLONG_MAX)
82 		atomic64_set(&(counter)->bytes, (long long)(ext->bytes));
83 	if (ext->packets != ULLONG_MAX)
84 		atomic64_set(&(counter)->packets, (long long)(ext->packets));
85 }
86 
87 #endif /* __KERNEL__ */
88 #endif /* _IP_SET_COUNTER_H */
89