Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[NETFILTER]: Use only 32bit counters for CONNTRACK_ACCT

Initially we used 64bit counters for conntrack-based accounting, since we
had no event mechanism to tell userspace that our counters are about to
overflow. With nfnetlink_conntrack, we now have such a event mechanism and
thus can save 16bytes per connection.

Signed-off-by: Harald Welte <laforge@netfilter.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Harald Welte and committed by
David S. Miller
a051a8f7 d4875b04

+22 -13
+6 -2
include/linux/netfilter_ipv4/ip_conntrack.h
··· 117 117 /* NAT info */ 118 118 IPCT_NATINFO_BIT = 10, 119 119 IPCT_NATINFO = (1 << IPCT_NATINFO_BIT), 120 + 121 + /* Counter highest bit has been set */ 122 + IPCT_COUNTER_FILLING_BIT = 11, 123 + IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT), 120 124 }; 121 125 122 126 enum ip_conntrack_expect_events { ··· 196 192 197 193 struct ip_conntrack_counter 198 194 { 199 - u_int64_t packets; 200 - u_int64_t bytes; 195 + u_int32_t packets; 196 + u_int32_t bytes; 201 197 }; 202 198 203 199 struct ip_conntrack_helper;
+8 -5
net/ipv4/netfilter/ip_conntrack_core.c
··· 1119 1119 unsigned long extra_jiffies, 1120 1120 int do_acct) 1121 1121 { 1122 - int do_event = 0; 1122 + int event = 0; 1123 1123 1124 1124 IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct); 1125 1125 IP_NF_ASSERT(skb); ··· 1129 1129 /* If not in hash table, timer will not be active yet */ 1130 1130 if (!is_confirmed(ct)) { 1131 1131 ct->timeout.expires = extra_jiffies; 1132 - do_event = 1; 1132 + event = IPCT_REFRESH; 1133 1133 } else { 1134 1134 /* Need del_timer for race avoidance (may already be dying). */ 1135 1135 if (del_timer(&ct->timeout)) { 1136 1136 ct->timeout.expires = jiffies + extra_jiffies; 1137 1137 add_timer(&ct->timeout); 1138 - do_event = 1; 1138 + event = IPCT_REFRESH; 1139 1139 } 1140 1140 } 1141 1141 ··· 1144 1144 ct->counters[CTINFO2DIR(ctinfo)].packets++; 1145 1145 ct->counters[CTINFO2DIR(ctinfo)].bytes += 1146 1146 ntohs(skb->nh.iph->tot_len); 1147 + if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000) 1148 + || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000)) 1149 + event |= IPCT_COUNTER_FILLING; 1147 1150 } 1148 1151 #endif 1149 1152 1150 1153 write_unlock_bh(&ip_conntrack_lock); 1151 1154 1152 1155 /* must be unlocked when calling event cache */ 1153 - if (do_event) 1154 - ip_conntrack_event_cache(IPCT_REFRESH, skb); 1156 + if (event) 1157 + ip_conntrack_event_cache(event, skb); 1155 1158 } 1156 1159 1157 1160 #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+4 -4
net/ipv4/netfilter/ip_conntrack_netlink.c
··· 177 177 struct nfattr *nest_count = NFA_NEST(skb, type); 178 178 u_int64_t tmp; 179 179 180 - tmp = cpu_to_be64(ct->counters[dir].packets); 181 - NFA_PUT(skb, CTA_COUNTERS_PACKETS, sizeof(u_int64_t), &tmp); 180 + tmp = htonl(ct->counters[dir].packets); 181 + NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp); 182 182 183 - tmp = cpu_to_be64(ct->counters[dir].bytes); 184 - NFA_PUT(skb, CTA_COUNTERS_BYTES, sizeof(u_int64_t), &tmp); 183 + tmp = htonl(ct->counters[dir].bytes); 184 + NFA_PUT(skb, CTA_COUNTERS32_BYTES, sizeof(u_int32_t), &tmp); 185 185 186 186 NFA_NEST_END(skb, nest_count); 187 187