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

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next

Pablo Neira Ayuso says:

====================
This is another batch containing Netfilter/IPVS updates for your net-next
tree, they are:

* Six patches to make the ipt_CLUSTERIP target support netnamespace,
from Gao feng.

* Two cleanups for the nf_conntrack_acct infrastructure, introducing
a new structure to encapsulate conntrack counters, from Holger
Eitzenberger.

* Fix missing verdict in SCTP support for IPVS, from Daniel Borkmann.

* Skip checksum recalculation in SCTP support for IPVS, also from
Daniel Borkmann.

* Fix behavioural change in xt_socket after IP early demux, from
Florian Westphal.

* Fix bogus large memory allocation in the bitmap port set type in ipset,
from Jozsef Kadlecsik.

* Fix possible compilation issues in the hash netnet set type in ipset,
also from Jozsef Kadlecsik.

* Define constants to identify netlink callback data in ipset dumps,
again from Jozsef Kadlecsik.

* Use sock_gen_put() in xt_socket to replace xt_socket_put_sk,
from Eric Dumazet.

* Improvements for the SH scheduler in IPVS, from Alexander Frolkin.

* Remove extra delay due to unneeded rcu barrier in IPVS net namespace
cleanup path, from Julian Anastasov.

* Save some cycles in ip6t_REJECT by skipping checksum validation in
packets leaving from our stack, from Stanislav Fomichev.

* Fix IPVS_CMD_ATTR_MAX definition in IPVS, larger that required, from
Julian Anastasov.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+306 -199
+10
include/linux/netfilter/ipset/ip_set.h
··· 316 316 atomic64_set(&(counter)->packets, (long long)(ext->packets)); 317 317 } 318 318 319 + /* Netlink CB args */ 320 + enum { 321 + IPSET_CB_NET = 0, 322 + IPSET_CB_DUMP, 323 + IPSET_CB_INDEX, 324 + IPSET_CB_ARG0, 325 + IPSET_CB_ARG1, 326 + IPSET_CB_ARG2, 327 + }; 328 + 319 329 /* register and unregister set references */ 320 330 extern ip_set_id_t ip_set_get_byname(struct net *net, 321 331 const char *name, struct ip_set **set);
+6
include/net/ip_vs.h
··· 1442 1442 atomic_dec(&dest->refcnt); 1443 1443 } 1444 1444 1445 + static inline void ip_vs_dest_put_and_free(struct ip_vs_dest *dest) 1446 + { 1447 + if (atomic_dec_return(&dest->refcnt) < 0) 1448 + kfree(dest); 1449 + } 1450 + 1445 1451 /* 1446 1452 * IPVS sync daemon data and function prototypes 1447 1453 * (from ip_vs_sync.c)
+7 -3
include/net/netfilter/nf_conntrack_acct.h
··· 19 19 atomic64_t bytes; 20 20 }; 21 21 22 + struct nf_conn_acct { 23 + struct nf_conn_counter counter[IP_CT_DIR_MAX]; 24 + }; 25 + 22 26 static inline 23 - struct nf_conn_counter *nf_conn_acct_find(const struct nf_conn *ct) 27 + struct nf_conn_acct *nf_conn_acct_find(const struct nf_conn *ct) 24 28 { 25 29 return nf_ct_ext_find(ct, NF_CT_EXT_ACCT); 26 30 } 27 31 28 32 static inline 29 - struct nf_conn_counter *nf_ct_acct_ext_add(struct nf_conn *ct, gfp_t gfp) 33 + struct nf_conn_acct *nf_ct_acct_ext_add(struct nf_conn *ct, gfp_t gfp) 30 34 { 31 35 struct net *net = nf_ct_net(ct); 32 - struct nf_conn_counter *acct; 36 + struct nf_conn_acct *acct; 33 37 34 38 if (!net->ct.sysctl_acct) 35 39 return NULL;
+1 -1
include/net/netfilter/nf_conntrack_extend.h
··· 36 36 #define NF_CT_EXT_HELPER_TYPE struct nf_conn_help 37 37 #define NF_CT_EXT_NAT_TYPE struct nf_conn_nat 38 38 #define NF_CT_EXT_SEQADJ_TYPE struct nf_conn_seqadj 39 - #define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter 39 + #define NF_CT_EXT_ACCT_TYPE struct nf_conn_acct 40 40 #define NF_CT_EXT_ECACHE_TYPE struct nf_conntrack_ecache 41 41 #define NF_CT_EXT_ZONE_TYPE struct nf_conntrack_zone 42 42 #define NF_CT_EXT_TSTAMP_TYPE struct nf_conn_tstamp
+1 -1
include/uapi/linux/ip_vs.h
··· 334 334 __IPVS_CMD_ATTR_MAX, 335 335 }; 336 336 337 - #define IPVS_CMD_ATTR_MAX (__IPVS_SVC_ATTR_MAX - 1) 337 + #define IPVS_CMD_ATTR_MAX (__IPVS_CMD_ATTR_MAX - 1) 338 338 339 339 /* 340 340 * Attributes used to describe a service
+2
net/bridge/br_netfilter.c
··· 559 559 else if (skb->protocol == htons(ETH_P_PPP_SES)) 560 560 nf_bridge->mask |= BRNF_PPPoE; 561 561 562 + /* Must drop socket now because of tproxy. */ 563 + skb_orphan(skb); 562 564 return skb->dev; 563 565 } 564 566
+76 -36
net/ipv4/netfilter/ipt_CLUSTERIP.c
··· 28 28 #include <linux/netfilter_ipv4/ipt_CLUSTERIP.h> 29 29 #include <net/netfilter/nf_conntrack.h> 30 30 #include <net/net_namespace.h> 31 + #include <net/netns/generic.h> 31 32 #include <net/checksum.h> 32 33 #include <net/ip.h> 33 34 ··· 58 57 struct rcu_head rcu; 59 58 }; 60 59 61 - static LIST_HEAD(clusterip_configs); 62 - 63 - /* clusterip_lock protects the clusterip_configs list */ 64 - static DEFINE_SPINLOCK(clusterip_lock); 65 - 66 60 #ifdef CONFIG_PROC_FS 67 61 static const struct file_operations clusterip_proc_fops; 68 - static struct proc_dir_entry *clusterip_procdir; 69 62 #endif 63 + 64 + static int clusterip_net_id __read_mostly; 65 + 66 + struct clusterip_net { 67 + struct list_head configs; 68 + /* lock protects the configs list */ 69 + spinlock_t lock; 70 + 71 + #ifdef CONFIG_PROC_FS 72 + struct proc_dir_entry *procdir; 73 + #endif 74 + }; 70 75 71 76 static inline void 72 77 clusterip_config_get(struct clusterip_config *c) ··· 99 92 static inline void 100 93 clusterip_config_entry_put(struct clusterip_config *c) 101 94 { 95 + struct net *net = dev_net(c->dev); 96 + struct clusterip_net *cn = net_generic(net, clusterip_net_id); 97 + 102 98 local_bh_disable(); 103 - if (atomic_dec_and_lock(&c->entries, &clusterip_lock)) { 99 + if (atomic_dec_and_lock(&c->entries, &cn->lock)) { 104 100 list_del_rcu(&c->list); 105 - spin_unlock(&clusterip_lock); 101 + spin_unlock(&cn->lock); 106 102 local_bh_enable(); 107 103 108 104 dev_mc_del(c->dev, c->clustermac); ··· 123 113 } 124 114 125 115 static struct clusterip_config * 126 - __clusterip_config_find(__be32 clusterip) 116 + __clusterip_config_find(struct net *net, __be32 clusterip) 127 117 { 128 118 struct clusterip_config *c; 119 + struct clusterip_net *cn = net_generic(net, clusterip_net_id); 129 120 130 - list_for_each_entry_rcu(c, &clusterip_configs, list) { 121 + list_for_each_entry_rcu(c, &cn->configs, list) { 131 122 if (c->clusterip == clusterip) 132 123 return c; 133 124 } ··· 137 126 } 138 127 139 128 static inline struct clusterip_config * 140 - clusterip_config_find_get(__be32 clusterip, int entry) 129 + clusterip_config_find_get(struct net *net, __be32 clusterip, int entry) 141 130 { 142 131 struct clusterip_config *c; 143 132 144 133 rcu_read_lock_bh(); 145 - c = __clusterip_config_find(clusterip); 134 + c = __clusterip_config_find(net, clusterip); 146 135 if (c) { 147 136 if (unlikely(!atomic_inc_not_zero(&c->refcount))) 148 137 c = NULL; ··· 169 158 struct net_device *dev) 170 159 { 171 160 struct clusterip_config *c; 161 + struct clusterip_net *cn = net_generic(dev_net(dev), clusterip_net_id); 172 162 173 163 c = kzalloc(sizeof(*c), GFP_ATOMIC); 174 164 if (!c) ··· 192 180 /* create proc dir entry */ 193 181 sprintf(buffer, "%pI4", &ip); 194 182 c->pde = proc_create_data(buffer, S_IWUSR|S_IRUSR, 195 - clusterip_procdir, 183 + cn->procdir, 196 184 &clusterip_proc_fops, c); 197 185 if (!c->pde) { 198 186 kfree(c); ··· 201 189 } 202 190 #endif 203 191 204 - spin_lock_bh(&clusterip_lock); 205 - list_add_rcu(&c->list, &clusterip_configs); 206 - spin_unlock_bh(&clusterip_lock); 192 + spin_lock_bh(&cn->lock); 193 + list_add_rcu(&c->list, &cn->configs); 194 + spin_unlock_bh(&cn->lock); 207 195 208 196 return c; 209 197 } ··· 382 370 383 371 /* FIXME: further sanity checks */ 384 372 385 - config = clusterip_config_find_get(e->ip.dst.s_addr, 1); 373 + config = clusterip_config_find_get(par->net, e->ip.dst.s_addr, 1); 386 374 if (!config) { 387 375 if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) { 388 376 pr_info("no config found for %pI4, need 'new'\n", ··· 396 384 return -EINVAL; 397 385 } 398 386 399 - dev = dev_get_by_name(&init_net, e->ip.iniface); 387 + dev = dev_get_by_name(par->net, e->ip.iniface); 400 388 if (!dev) { 401 389 pr_info("no such interface %s\n", 402 390 e->ip.iniface); ··· 504 492 struct arphdr *arp = arp_hdr(skb); 505 493 struct arp_payload *payload; 506 494 struct clusterip_config *c; 495 + struct net *net = dev_net(in ? in : out); 507 496 508 497 /* we don't care about non-ethernet and non-ipv4 ARP */ 509 498 if (arp->ar_hrd != htons(ARPHRD_ETHER) || ··· 521 508 522 509 /* if there is no clusterip configuration for the arp reply's 523 510 * source ip, we don't want to mangle it */ 524 - c = clusterip_config_find_get(payload->src_ip, 0); 511 + c = clusterip_config_find_get(net, payload->src_ip, 0); 525 512 if (!c) 526 513 return NF_ACCEPT; 527 514 ··· 711 698 712 699 #endif /* CONFIG_PROC_FS */ 713 700 701 + static int clusterip_net_init(struct net *net) 702 + { 703 + struct clusterip_net *cn = net_generic(net, clusterip_net_id); 704 + 705 + INIT_LIST_HEAD(&cn->configs); 706 + 707 + spin_lock_init(&cn->lock); 708 + 709 + #ifdef CONFIG_PROC_FS 710 + cn->procdir = proc_mkdir("ipt_CLUSTERIP", net->proc_net); 711 + if (!cn->procdir) { 712 + pr_err("Unable to proc dir entry\n"); 713 + return -ENOMEM; 714 + } 715 + #endif /* CONFIG_PROC_FS */ 716 + 717 + return 0; 718 + } 719 + 720 + static void clusterip_net_exit(struct net *net) 721 + { 722 + #ifdef CONFIG_PROC_FS 723 + struct clusterip_net *cn = net_generic(net, clusterip_net_id); 724 + proc_remove(cn->procdir); 725 + #endif 726 + } 727 + 728 + static struct pernet_operations clusterip_net_ops = { 729 + .init = clusterip_net_init, 730 + .exit = clusterip_net_exit, 731 + .id = &clusterip_net_id, 732 + .size = sizeof(struct clusterip_net), 733 + }; 734 + 714 735 static int __init clusterip_tg_init(void) 715 736 { 716 737 int ret; 717 738 718 - ret = xt_register_target(&clusterip_tg_reg); 739 + ret = register_pernet_subsys(&clusterip_net_ops); 719 740 if (ret < 0) 720 741 return ret; 742 + 743 + ret = xt_register_target(&clusterip_tg_reg); 744 + if (ret < 0) 745 + goto cleanup_subsys; 721 746 722 747 ret = nf_register_hook(&cip_arp_ops); 723 748 if (ret < 0) 724 749 goto cleanup_target; 725 750 726 - #ifdef CONFIG_PROC_FS 727 - clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", init_net.proc_net); 728 - if (!clusterip_procdir) { 729 - pr_err("Unable to proc dir entry\n"); 730 - ret = -ENOMEM; 731 - goto cleanup_hook; 732 - } 733 - #endif /* CONFIG_PROC_FS */ 734 - 735 751 pr_info("ClusterIP Version %s loaded successfully\n", 736 752 CLUSTERIP_VERSION); 753 + 737 754 return 0; 738 755 739 - #ifdef CONFIG_PROC_FS 740 - cleanup_hook: 741 - nf_unregister_hook(&cip_arp_ops); 742 - #endif /* CONFIG_PROC_FS */ 743 756 cleanup_target: 744 757 xt_unregister_target(&clusterip_tg_reg); 758 + cleanup_subsys: 759 + unregister_pernet_subsys(&clusterip_net_ops); 745 760 return ret; 746 761 } 747 762 748 763 static void __exit clusterip_tg_exit(void) 749 764 { 750 765 pr_info("ClusterIP Version %s unloading\n", CLUSTERIP_VERSION); 751 - #ifdef CONFIG_PROC_FS 752 - proc_remove(clusterip_procdir); 753 - #endif 766 + 754 767 nf_unregister_hook(&cip_arp_ops); 755 768 xt_unregister_target(&clusterip_tg_reg); 769 + unregister_pernet_subsys(&clusterip_net_ops); 756 770 757 771 /* Wait for completion of call_rcu_bh()'s (clusterip_config_rcu_free) */ 758 772 rcu_barrier_bh();
+3 -4
net/ipv6/netfilter/ip6t_REJECT.c
··· 39 39 MODULE_LICENSE("GPL"); 40 40 41 41 /* Send RST reply */ 42 - static void send_reset(struct net *net, struct sk_buff *oldskb) 42 + static void send_reset(struct net *net, struct sk_buff *oldskb, int hook) 43 43 { 44 44 struct sk_buff *nskb; 45 45 struct tcphdr otcph, *tcph; ··· 88 88 } 89 89 90 90 /* Check checksum. */ 91 - if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP, 92 - skb_checksum(oldskb, tcphoff, otcplen, 0))) { 91 + if (nf_ip6_checksum(oldskb, hook, tcphoff, IPPROTO_TCP)) { 93 92 pr_debug("TCP checksum is invalid\n"); 94 93 return; 95 94 } ··· 226 227 /* Do nothing */ 227 228 break; 228 229 case IP6T_TCP_RESET: 229 - send_reset(net, skb); 230 + send_reset(net, skb, par->hooknum); 230 231 break; 231 232 default: 232 233 net_info_ratelimited("case %u not handled yet\n", reject->with);
+6 -5
net/netfilter/ipset/ip_set_bitmap_gen.h
··· 198 198 struct mtype *map = set->data; 199 199 struct nlattr *adt, *nested; 200 200 void *x; 201 - u32 id, first = cb->args[2]; 201 + u32 id, first = cb->args[IPSET_CB_ARG0]; 202 202 203 203 adt = ipset_nest_start(skb, IPSET_ATTR_ADT); 204 204 if (!adt) 205 205 return -EMSGSIZE; 206 - for (; cb->args[2] < map->elements; cb->args[2]++) { 207 - id = cb->args[2]; 206 + for (; cb->args[IPSET_CB_ARG0] < map->elements; 207 + cb->args[IPSET_CB_ARG0]++) { 208 + id = cb->args[IPSET_CB_ARG0]; 208 209 x = get_ext(set, map, id); 209 210 if (!test_bit(id, map->members) || 210 211 (SET_WITH_TIMEOUT(set) && ··· 232 231 ipset_nest_end(skb, adt); 233 232 234 233 /* Set listing finished */ 235 - cb->args[2] = 0; 234 + cb->args[IPSET_CB_ARG0] = 0; 236 235 237 236 return 0; 238 237 239 238 nla_put_failure: 240 239 nla_nest_cancel(skb, nested); 241 240 if (unlikely(id == first)) { 242 - cb->args[2] = 0; 241 + cb->args[IPSET_CB_ARG0] = 0; 243 242 return -EMSGSIZE; 244 243 } 245 244 ipset_nest_end(skb, adt);
+1 -1
net/netfilter/ipset/ip_set_bitmap_port.c
··· 254 254 return -ENOMEM; 255 255 256 256 map->elements = last_port - first_port + 1; 257 - map->memsize = map->elements * sizeof(unsigned long); 257 + map->memsize = bitmap_bytes(0, map->elements); 258 258 set->variant = &bitmap_port; 259 259 set->dsize = ip_set_elem_len(set, tb, 0); 260 260 if (!init_map_port(set, map, first_port, last_port)) {
+35 -35
net/netfilter/ipset/ip_set_core.c
··· 1182 1182 static int 1183 1183 ip_set_dump_done(struct netlink_callback *cb) 1184 1184 { 1185 - struct ip_set_net *inst = (struct ip_set_net *)cb->data; 1186 - if (cb->args[2]) { 1187 - pr_debug("release set %s\n", nfnl_set(inst, cb->args[1])->name); 1188 - __ip_set_put_byindex(inst, (ip_set_id_t) cb->args[1]); 1185 + struct ip_set_net *inst = (struct ip_set_net *)cb->args[IPSET_CB_NET]; 1186 + if (cb->args[IPSET_CB_ARG0]) { 1187 + pr_debug("release set %s\n", 1188 + nfnl_set(inst, cb->args[IPSET_CB_INDEX])->name); 1189 + __ip_set_put_byindex(inst, 1190 + (ip_set_id_t) cb->args[IPSET_CB_INDEX]); 1189 1191 } 1190 1192 return 0; 1191 1193 } ··· 1205 1203 } 1206 1204 1207 1205 static int 1208 - dump_init(struct netlink_callback *cb) 1206 + dump_init(struct netlink_callback *cb, struct ip_set_net *inst) 1209 1207 { 1210 1208 struct nlmsghdr *nlh = nlmsg_hdr(cb->skb); 1211 1209 int min_len = nlmsg_total_size(sizeof(struct nfgenmsg)); ··· 1213 1211 struct nlattr *attr = (void *)nlh + min_len; 1214 1212 u32 dump_type; 1215 1213 ip_set_id_t index; 1216 - struct ip_set_net *inst = (struct ip_set_net *)cb->data; 1217 1214 1218 1215 /* Second pass, so parser can't fail */ 1219 1216 nla_parse(cda, IPSET_ATTR_CMD_MAX, 1220 1217 attr, nlh->nlmsg_len - min_len, ip_set_setname_policy); 1221 1218 1222 - /* cb->args[0] : dump single set/all sets 1223 - * [1] : set index 1224 - * [..]: type specific 1219 + /* cb->args[IPSET_CB_NET]: net namespace 1220 + * [IPSET_CB_DUMP]: dump single set/all sets 1221 + * [IPSET_CB_INDEX]: set index 1222 + * [IPSET_CB_ARG0]: type specific 1225 1223 */ 1226 1224 1227 1225 if (cda[IPSET_ATTR_SETNAME]) { ··· 1233 1231 return -ENOENT; 1234 1232 1235 1233 dump_type = DUMP_ONE; 1236 - cb->args[1] = index; 1234 + cb->args[IPSET_CB_INDEX] = index; 1237 1235 } else 1238 1236 dump_type = DUMP_ALL; 1239 1237 ··· 1241 1239 u32 f = ip_set_get_h32(cda[IPSET_ATTR_FLAGS]); 1242 1240 dump_type |= (f << 16); 1243 1241 } 1244 - cb->args[0] = dump_type; 1242 + cb->args[IPSET_CB_NET] = (unsigned long)inst; 1243 + cb->args[IPSET_CB_DUMP] = dump_type; 1245 1244 1246 1245 return 0; 1247 1246 } ··· 1254 1251 struct ip_set *set = NULL; 1255 1252 struct nlmsghdr *nlh = NULL; 1256 1253 unsigned int flags = NETLINK_CB(cb->skb).portid ? NLM_F_MULTI : 0; 1254 + struct ip_set_net *inst = ip_set_pernet(sock_net(skb->sk)); 1257 1255 u32 dump_type, dump_flags; 1258 1256 int ret = 0; 1259 - struct ip_set_net *inst = (struct ip_set_net *)cb->data; 1260 1257 1261 - if (!cb->args[0]) { 1262 - ret = dump_init(cb); 1258 + if (!cb->args[IPSET_CB_DUMP]) { 1259 + ret = dump_init(cb, inst); 1263 1260 if (ret < 0) { 1264 1261 nlh = nlmsg_hdr(cb->skb); 1265 1262 /* We have to create and send the error message ··· 1270 1267 } 1271 1268 } 1272 1269 1273 - if (cb->args[1] >= inst->ip_set_max) 1270 + if (cb->args[IPSET_CB_INDEX] >= inst->ip_set_max) 1274 1271 goto out; 1275 1272 1276 - dump_type = DUMP_TYPE(cb->args[0]); 1277 - dump_flags = DUMP_FLAGS(cb->args[0]); 1278 - max = dump_type == DUMP_ONE ? cb->args[1] + 1 : inst->ip_set_max; 1273 + dump_type = DUMP_TYPE(cb->args[IPSET_CB_DUMP]); 1274 + dump_flags = DUMP_FLAGS(cb->args[IPSET_CB_DUMP]); 1275 + max = dump_type == DUMP_ONE ? cb->args[IPSET_CB_INDEX] + 1 1276 + : inst->ip_set_max; 1279 1277 dump_last: 1280 - pr_debug("args[0]: %u %u args[1]: %ld\n", 1281 - dump_type, dump_flags, cb->args[1]); 1282 - for (; cb->args[1] < max; cb->args[1]++) { 1283 - index = (ip_set_id_t) cb->args[1]; 1278 + pr_debug("dump type, flag: %u %u index: %ld\n", 1279 + dump_type, dump_flags, cb->args[IPSET_CB_INDEX]); 1280 + for (; cb->args[IPSET_CB_INDEX] < max; cb->args[IPSET_CB_INDEX]++) { 1281 + index = (ip_set_id_t) cb->args[IPSET_CB_INDEX]; 1284 1282 set = nfnl_set(inst, index); 1285 1283 if (set == NULL) { 1286 1284 if (dump_type == DUMP_ONE) { ··· 1298 1294 !!(set->type->features & IPSET_DUMP_LAST))) 1299 1295 continue; 1300 1296 pr_debug("List set: %s\n", set->name); 1301 - if (!cb->args[2]) { 1297 + if (!cb->args[IPSET_CB_ARG0]) { 1302 1298 /* Start listing: make sure set won't be destroyed */ 1303 1299 pr_debug("reference set\n"); 1304 1300 __ip_set_get(set); ··· 1315 1311 goto nla_put_failure; 1316 1312 if (dump_flags & IPSET_FLAG_LIST_SETNAME) 1317 1313 goto next_set; 1318 - switch (cb->args[2]) { 1314 + switch (cb->args[IPSET_CB_ARG0]) { 1319 1315 case 0: 1320 1316 /* Core header data */ 1321 1317 if (nla_put_string(skb, IPSET_ATTR_TYPENAME, ··· 1335 1331 read_lock_bh(&set->lock); 1336 1332 ret = set->variant->list(set, skb, cb); 1337 1333 read_unlock_bh(&set->lock); 1338 - if (!cb->args[2]) 1334 + if (!cb->args[IPSET_CB_ARG0]) 1339 1335 /* Set is done, proceed with next one */ 1340 1336 goto next_set; 1341 1337 goto release_refcount; ··· 1344 1340 /* If we dump all sets, continue with dumping last ones */ 1345 1341 if (dump_type == DUMP_ALL) { 1346 1342 dump_type = DUMP_LAST; 1347 - cb->args[0] = dump_type | (dump_flags << 16); 1348 - cb->args[1] = 0; 1343 + cb->args[IPSET_CB_DUMP] = dump_type | (dump_flags << 16); 1344 + cb->args[IPSET_CB_INDEX] = 0; 1349 1345 goto dump_last; 1350 1346 } 1351 1347 goto out; ··· 1354 1350 ret = -EFAULT; 1355 1351 next_set: 1356 1352 if (dump_type == DUMP_ONE) 1357 - cb->args[1] = IPSET_INVALID_ID; 1353 + cb->args[IPSET_CB_INDEX] = IPSET_INVALID_ID; 1358 1354 else 1359 - cb->args[1]++; 1355 + cb->args[IPSET_CB_INDEX]++; 1360 1356 release_refcount: 1361 1357 /* If there was an error or set is done, release set */ 1362 - if (ret || !cb->args[2]) { 1358 + if (ret || !cb->args[IPSET_CB_ARG0]) { 1363 1359 pr_debug("release set %s\n", nfnl_set(inst, index)->name); 1364 1360 __ip_set_put_byindex(inst, index); 1365 - cb->args[2] = 0; 1361 + cb->args[IPSET_CB_ARG0] = 0; 1366 1362 } 1367 1363 out: 1368 1364 if (nlh) { ··· 1379 1375 const struct nlmsghdr *nlh, 1380 1376 const struct nlattr * const attr[]) 1381 1377 { 1382 - struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl)); 1383 - 1384 1378 if (unlikely(protocol_failed(attr))) 1385 1379 return -IPSET_ERR_PROTOCOL; 1386 1380 ··· 1386 1384 struct netlink_dump_control c = { 1387 1385 .dump = ip_set_dump_start, 1388 1386 .done = ip_set_dump_done, 1389 - .data = (void *)inst 1390 1387 }; 1391 1388 return netlink_dump_start(ctnl, skb, nlh, &c); 1392 1389 } ··· 1962 1961 ip_set_net_init(struct net *net) 1963 1962 { 1964 1963 struct ip_set_net *inst = ip_set_pernet(net); 1965 - 1966 1964 struct ip_set **list; 1967 1965 1968 1966 inst->ip_set_max = max_sets ? max_sets : CONFIG_IP_SET_MAX;
+11 -10
net/netfilter/ipset/ip_set_hash_gen.h
··· 234 234 #define mtype_uadt IPSET_TOKEN(MTYPE, _uadt) 235 235 #define mtype MTYPE 236 236 237 - #define mtype_elem IPSET_TOKEN(MTYPE, _elem) 238 237 #define mtype_add IPSET_TOKEN(MTYPE, _add) 239 238 #define mtype_del IPSET_TOKEN(MTYPE, _del) 240 239 #define mtype_test_cidrs IPSET_TOKEN(MTYPE, _test_cidrs) ··· 930 931 struct nlattr *atd, *nested; 931 932 const struct hbucket *n; 932 933 const struct mtype_elem *e; 933 - u32 first = cb->args[2]; 934 + u32 first = cb->args[IPSET_CB_ARG0]; 934 935 /* We assume that one hash bucket fills into one page */ 935 936 void *incomplete; 936 937 int i; ··· 939 940 if (!atd) 940 941 return -EMSGSIZE; 941 942 pr_debug("list hash set %s\n", set->name); 942 - for (; cb->args[2] < jhash_size(t->htable_bits); cb->args[2]++) { 943 + for (; cb->args[IPSET_CB_ARG0] < jhash_size(t->htable_bits); 944 + cb->args[IPSET_CB_ARG0]++) { 943 945 incomplete = skb_tail_pointer(skb); 944 - n = hbucket(t, cb->args[2]); 945 - pr_debug("cb->args[2]: %lu, t %p n %p\n", cb->args[2], t, n); 946 + n = hbucket(t, cb->args[IPSET_CB_ARG0]); 947 + pr_debug("cb->arg bucket: %lu, t %p n %p\n", 948 + cb->args[IPSET_CB_ARG0], t, n); 946 949 for (i = 0; i < n->pos; i++) { 947 950 e = ahash_data(n, i, set->dsize); 948 951 if (SET_WITH_TIMEOUT(set) && 949 952 ip_set_timeout_expired(ext_timeout(e, set))) 950 953 continue; 951 954 pr_debug("list hash %lu hbucket %p i %u, data %p\n", 952 - cb->args[2], n, i, e); 955 + cb->args[IPSET_CB_ARG0], n, i, e); 953 956 nested = ipset_nest_start(skb, IPSET_ATTR_DATA); 954 957 if (!nested) { 955 - if (cb->args[2] == first) { 958 + if (cb->args[IPSET_CB_ARG0] == first) { 956 959 nla_nest_cancel(skb, atd); 957 960 return -EMSGSIZE; 958 961 } else ··· 969 968 } 970 969 ipset_nest_end(skb, atd); 971 970 /* Set listing finished */ 972 - cb->args[2] = 0; 971 + cb->args[IPSET_CB_ARG0] = 0; 973 972 974 973 return 0; 975 974 976 975 nla_put_failure: 977 976 nlmsg_trim(skb, incomplete); 978 - if (unlikely(first == cb->args[2])) { 977 + if (unlikely(first == cb->args[IPSET_CB_ARG0])) { 979 978 pr_warning("Can't list set %s: one bucket does not fit into " 980 979 "a message. Please report it!\n", set->name); 981 - cb->args[2] = 0; 980 + cb->args[IPSET_CB_ARG0] = 0; 982 981 return -EMSGSIZE; 983 982 } 984 983 ipset_nest_end(skb, atd);
+10 -12
net/netfilter/ipset/ip_set_hash_netnet.c
··· 137 137 { 138 138 const struct hash_netnet *h = set->data; 139 139 ipset_adtfn adtfn = set->variant->adt[adt]; 140 - struct hash_netnet4_elem e = { 141 - .cidr[0] = h->nets[0].cidr[0] ? h->nets[0].cidr[0] : HOST_MASK, 142 - .cidr[1] = h->nets[0].cidr[1] ? h->nets[0].cidr[1] : HOST_MASK, 143 - }; 140 + struct hash_netnet4_elem e = { }; 144 141 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); 145 142 143 + e.cidr[0] = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK); 144 + e.cidr[1] = IP_SET_INIT_CIDR(h->nets[0].cidr[1], HOST_MASK); 146 145 if (adt == IPSET_TEST) 147 146 e.ccmp = (HOST_MASK << (sizeof(e.cidr[0]) * 8)) | HOST_MASK; 148 147 ··· 159 160 { 160 161 const struct hash_netnet *h = set->data; 161 162 ipset_adtfn adtfn = set->variant->adt[adt]; 162 - struct hash_netnet4_elem e = { .cidr[0] = HOST_MASK, 163 - .cidr[1] = HOST_MASK }; 163 + struct hash_netnet4_elem e = { }; 164 164 struct ip_set_ext ext = IP_SET_INIT_UEXT(set); 165 165 u32 ip = 0, ip_to = 0, last; 166 166 u32 ip2 = 0, ip2_from = 0, ip2_to = 0, last2; 167 167 u8 cidr, cidr2; 168 168 int ret; 169 169 170 + e.cidr[0] = e.cidr[1] = HOST_MASK; 170 171 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 171 172 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 172 173 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || ··· 363 364 { 364 365 const struct hash_netnet *h = set->data; 365 366 ipset_adtfn adtfn = set->variant->adt[adt]; 366 - struct hash_netnet6_elem e = { 367 - .cidr[0] = h->nets[0].cidr[0] ? h->nets[0].cidr[0] : HOST_MASK, 368 - .cidr[1] = h->nets[0].cidr[1] ? h->nets[0].cidr[1] : HOST_MASK 369 - }; 367 + struct hash_netnet6_elem e = { }; 370 368 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); 371 369 370 + e.cidr[0] = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK); 371 + e.cidr[1] = IP_SET_INIT_CIDR(h->nets[0].cidr[1], HOST_MASK); 372 372 if (adt == IPSET_TEST) 373 373 e.ccmp = (HOST_MASK << (sizeof(u8)*8)) | HOST_MASK; 374 374 ··· 384 386 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 385 387 { 386 388 ipset_adtfn adtfn = set->variant->adt[adt]; 387 - struct hash_netnet6_elem e = { .cidr[0] = HOST_MASK, 388 - .cidr[1] = HOST_MASK }; 389 + struct hash_netnet6_elem e = { }; 389 390 struct ip_set_ext ext = IP_SET_INIT_UEXT(set); 390 391 int ret; 391 392 393 + e.cidr[0] = e.cidr[1] = HOST_MASK; 392 394 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 393 395 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 394 396 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
+10 -12
net/netfilter/ipset/ip_set_hash_netportnet.c
··· 147 147 { 148 148 const struct hash_netportnet *h = set->data; 149 149 ipset_adtfn adtfn = set->variant->adt[adt]; 150 - struct hash_netportnet4_elem e = { 151 - .cidr[0] = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK), 152 - .cidr[1] = IP_SET_INIT_CIDR(h->nets[0].cidr[1], HOST_MASK), 153 - }; 150 + struct hash_netportnet4_elem e = { }; 154 151 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); 155 152 153 + e.cidr[0] = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK); 154 + e.cidr[1] = IP_SET_INIT_CIDR(h->nets[0].cidr[1], HOST_MASK); 156 155 if (adt == IPSET_TEST) 157 156 e.ccmp = (HOST_MASK << (sizeof(e.cidr[0]) * 8)) | HOST_MASK; 158 157 ··· 173 174 { 174 175 const struct hash_netportnet *h = set->data; 175 176 ipset_adtfn adtfn = set->variant->adt[adt]; 176 - struct hash_netportnet4_elem e = { .cidr[0] = HOST_MASK, 177 - .cidr[1] = HOST_MASK }; 177 + struct hash_netportnet4_elem e = { }; 178 178 struct ip_set_ext ext = IP_SET_INIT_UEXT(set); 179 179 u32 ip = 0, ip_to = 0, ip_last, p = 0, port, port_to; 180 180 u32 ip2_from = 0, ip2_to = 0, ip2_last, ip2; ··· 181 183 u8 cidr, cidr2; 182 184 int ret; 183 185 186 + e.cidr[0] = e.cidr[1] = HOST_MASK; 184 187 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 185 188 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 186 189 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || ··· 418 419 { 419 420 const struct hash_netportnet *h = set->data; 420 421 ipset_adtfn adtfn = set->variant->adt[adt]; 421 - struct hash_netportnet6_elem e = { 422 - .cidr[0] = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK), 423 - .cidr[1] = IP_SET_INIT_CIDR(h->nets[0].cidr[1], HOST_MASK), 424 - }; 422 + struct hash_netportnet6_elem e = { }; 425 423 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); 426 424 425 + e.cidr[0] = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK); 426 + e.cidr[1] = IP_SET_INIT_CIDR(h->nets[0].cidr[1], HOST_MASK); 427 427 if (adt == IPSET_TEST) 428 428 e.ccmp = (HOST_MASK << (sizeof(u8) * 8)) | HOST_MASK; 429 429 ··· 444 446 { 445 447 const struct hash_netportnet *h = set->data; 446 448 ipset_adtfn adtfn = set->variant->adt[adt]; 447 - struct hash_netportnet6_elem e = { .cidr[0] = HOST_MASK, 448 - .cidr[1] = HOST_MASK }; 449 + struct hash_netportnet6_elem e = { }; 449 450 struct ip_set_ext ext = IP_SET_INIT_UEXT(set); 450 451 u32 port, port_to; 451 452 bool with_ports = false; 452 453 int ret; 453 454 455 + e.cidr[0] = e.cidr[1] = HOST_MASK; 454 456 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 455 457 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 456 458 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
+6 -5
net/netfilter/ipset/ip_set_list_set.c
··· 490 490 { 491 491 const struct list_set *map = set->data; 492 492 struct nlattr *atd, *nested; 493 - u32 i, first = cb->args[2]; 493 + u32 i, first = cb->args[IPSET_CB_ARG0]; 494 494 const struct set_elem *e; 495 495 496 496 atd = ipset_nest_start(skb, IPSET_ATTR_ADT); 497 497 if (!atd) 498 498 return -EMSGSIZE; 499 - for (; cb->args[2] < map->size; cb->args[2]++) { 500 - i = cb->args[2]; 499 + for (; cb->args[IPSET_CB_ARG0] < map->size; 500 + cb->args[IPSET_CB_ARG0]++) { 501 + i = cb->args[IPSET_CB_ARG0]; 501 502 e = list_set_elem(set, map, i); 502 503 if (e->id == IPSET_INVALID_ID) 503 504 goto finish; ··· 523 522 finish: 524 523 ipset_nest_end(skb, atd); 525 524 /* Set listing finished */ 526 - cb->args[2] = 0; 525 + cb->args[IPSET_CB_ARG0] = 0; 527 526 return 0; 528 527 529 528 nla_put_failure: 530 529 nla_nest_cancel(skb, nested); 531 530 if (unlikely(i == first)) { 532 - cb->args[2] = 0; 531 + cb->args[IPSET_CB_ARG0] = 0; 533 532 return -EMSGSIZE; 534 533 } 535 534 ipset_nest_end(skb, atd);
+1 -5
net/netfilter/ipvs/ip_vs_ctl.c
··· 704 704 __ip_vs_dst_cache_reset(dest); 705 705 __ip_vs_svc_put(svc, false); 706 706 free_percpu(dest->stats.cpustats); 707 - kfree(dest); 707 + ip_vs_dest_put_and_free(dest); 708 708 } 709 709 710 710 /* ··· 3820 3820 { 3821 3821 struct netns_ipvs *ipvs = net_ipvs(net); 3822 3822 3823 - /* Some dest can be in grace period even before cleanup, we have to 3824 - * defer ip_vs_trash_cleanup until ip_vs_dest_wait_readers is called. 3825 - */ 3826 - rcu_barrier(); 3827 3823 ip_vs_trash_cleanup(net); 3828 3824 ip_vs_stop_estimator(net, &ipvs->tot_stats); 3829 3825 ip_vs_control_net_cleanup_sysctl(net);
+1 -1
net/netfilter/ipvs/ip_vs_lblc.c
··· 136 136 struct ip_vs_lblc_entry, 137 137 rcu_head); 138 138 139 - ip_vs_dest_put(en->dest); 139 + ip_vs_dest_put_and_free(en->dest); 140 140 kfree(en); 141 141 } 142 142
+1 -1
net/netfilter/ipvs/ip_vs_lblcr.c
··· 130 130 struct ip_vs_dest_set_elem *e; 131 131 132 132 e = container_of(head, struct ip_vs_dest_set_elem, rcu_head); 133 - ip_vs_dest_put(e->dest); 133 + ip_vs_dest_put_and_free(e->dest); 134 134 kfree(e); 135 135 } 136 136
+40 -8
net/netfilter/ipvs/ip_vs_proto_sctp.c
··· 20 20 sctp_sctphdr_t *sh, _sctph; 21 21 22 22 sh = skb_header_pointer(skb, iph->len, sizeof(_sctph), &_sctph); 23 - if (sh == NULL) 23 + if (sh == NULL) { 24 + *verdict = NF_DROP; 24 25 return 0; 26 + } 25 27 26 28 sch = skb_header_pointer(skb, iph->len + sizeof(sctp_sctphdr_t), 27 29 sizeof(_schunkh), &_schunkh); 28 - if (sch == NULL) 30 + if (sch == NULL) { 31 + *verdict = NF_DROP; 29 32 return 0; 33 + } 34 + 30 35 net = skb_net(skb); 31 36 ipvs = net_ipvs(net); 32 37 rcu_read_lock(); ··· 81 76 { 82 77 sctp_sctphdr_t *sctph; 83 78 unsigned int sctphoff = iph->len; 79 + bool payload_csum = false; 84 80 85 81 #ifdef CONFIG_IP_VS_IPV6 86 82 if (cp->af == AF_INET6 && iph->fragoffs) ··· 93 87 return 0; 94 88 95 89 if (unlikely(cp->app != NULL)) { 90 + int ret; 91 + 96 92 /* Some checks before mangling */ 97 93 if (pp->csum_check && !pp->csum_check(cp->af, skb, pp)) 98 94 return 0; 99 95 100 96 /* Call application helper if needed */ 101 - if (!ip_vs_app_pkt_out(cp, skb)) 97 + ret = ip_vs_app_pkt_out(cp, skb); 98 + if (ret == 0) 102 99 return 0; 100 + /* ret=2: csum update is needed after payload mangling */ 101 + if (ret == 2) 102 + payload_csum = true; 103 103 } 104 104 105 105 sctph = (void *) skb_network_header(skb) + sctphoff; 106 - sctph->source = cp->vport; 107 106 108 - sctp_nat_csum(skb, sctph, sctphoff); 107 + /* Only update csum if we really have to */ 108 + if (sctph->source != cp->vport || payload_csum || 109 + skb->ip_summed == CHECKSUM_PARTIAL) { 110 + sctph->source = cp->vport; 111 + sctp_nat_csum(skb, sctph, sctphoff); 112 + } else { 113 + skb->ip_summed = CHECKSUM_UNNECESSARY; 114 + } 109 115 110 116 return 1; 111 117 } ··· 128 110 { 129 111 sctp_sctphdr_t *sctph; 130 112 unsigned int sctphoff = iph->len; 113 + bool payload_csum = false; 131 114 132 115 #ifdef CONFIG_IP_VS_IPV6 133 116 if (cp->af == AF_INET6 && iph->fragoffs) ··· 140 121 return 0; 141 122 142 123 if (unlikely(cp->app != NULL)) { 124 + int ret; 125 + 143 126 /* Some checks before mangling */ 144 127 if (pp->csum_check && !pp->csum_check(cp->af, skb, pp)) 145 128 return 0; 146 129 147 130 /* Call application helper if needed */ 148 - if (!ip_vs_app_pkt_in(cp, skb)) 131 + ret = ip_vs_app_pkt_in(cp, skb); 132 + if (ret == 0) 149 133 return 0; 134 + /* ret=2: csum update is needed after payload mangling */ 135 + if (ret == 2) 136 + payload_csum = true; 150 137 } 151 138 152 139 sctph = (void *) skb_network_header(skb) + sctphoff; 153 - sctph->dest = cp->dport; 154 140 155 - sctp_nat_csum(skb, sctph, sctphoff); 141 + /* Only update csum if we really have to */ 142 + if (sctph->dest != cp->dport || payload_csum || 143 + (skb->ip_summed == CHECKSUM_PARTIAL && 144 + !(skb_dst(skb)->dev->features & NETIF_F_SCTP_CSUM))) { 145 + sctph->dest = cp->dport; 146 + sctp_nat_csum(skb, sctph, sctphoff); 147 + } else if (skb->ip_summed != CHECKSUM_PARTIAL) { 148 + skb->ip_summed = CHECKSUM_UNNECESSARY; 149 + } 156 150 157 151 return 1; 158 152 }
+29 -10
net/netfilter/ipvs/ip_vs_sh.c
··· 115 115 } 116 116 117 117 118 - /* As ip_vs_sh_get, but with fallback if selected server is unavailable */ 118 + /* As ip_vs_sh_get, but with fallback if selected server is unavailable 119 + * 120 + * The fallback strategy loops around the table starting from a "random" 121 + * point (in fact, it is chosen to be the original hash value to make the 122 + * algorithm deterministic) to find a new server. 123 + */ 119 124 static inline struct ip_vs_dest * 120 125 ip_vs_sh_get_fallback(struct ip_vs_service *svc, struct ip_vs_sh_state *s, 121 126 const union nf_inet_addr *addr, __be16 port) 122 127 { 123 - unsigned int offset; 124 - unsigned int hash; 128 + unsigned int offset, roffset; 129 + unsigned int hash, ihash; 125 130 struct ip_vs_dest *dest; 126 131 132 + /* first try the dest it's supposed to go to */ 133 + ihash = ip_vs_sh_hashkey(svc->af, addr, port, 0); 134 + dest = rcu_dereference(s->buckets[ihash].dest); 135 + if (!dest) 136 + return NULL; 137 + if (!is_unavailable(dest)) 138 + return dest; 139 + 140 + IP_VS_DBG_BUF(6, "SH: selected unavailable server %s:%d, reselecting", 141 + IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port)); 142 + 143 + /* if the original dest is unavailable, loop around the table 144 + * starting from ihash to find a new dest 145 + */ 127 146 for (offset = 0; offset < IP_VS_SH_TAB_SIZE; offset++) { 128 - hash = ip_vs_sh_hashkey(svc->af, addr, port, offset); 147 + roffset = (offset + ihash) % IP_VS_SH_TAB_SIZE; 148 + hash = ip_vs_sh_hashkey(svc->af, addr, port, roffset); 129 149 dest = rcu_dereference(s->buckets[hash].dest); 130 150 if (!dest) 131 151 break; 132 - if (is_unavailable(dest)) 133 - IP_VS_DBG_BUF(6, "SH: selected unavailable server " 134 - "%s:%d (offset %d)", 135 - IP_VS_DBG_ADDR(svc->af, &dest->addr), 136 - ntohs(dest->port), offset); 137 - else 152 + if (!is_unavailable(dest)) 138 153 return dest; 154 + IP_VS_DBG_BUF(6, "SH: selected unavailable " 155 + "server %s:%d (offset %d), reselecting", 156 + IP_VS_DBG_ADDR(svc->af, &dest->addr), 157 + ntohs(dest->port), roffset); 139 158 } 140 159 141 160 return NULL;
+7 -5
net/netfilter/nf_conntrack_acct.c
··· 39 39 unsigned int 40 40 seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir) 41 41 { 42 - struct nf_conn_counter *acct; 42 + struct nf_conn_acct *acct; 43 + struct nf_conn_counter *counter; 43 44 44 45 acct = nf_conn_acct_find(ct); 45 46 if (!acct) 46 47 return 0; 47 48 49 + counter = acct->counter; 48 50 return seq_printf(s, "packets=%llu bytes=%llu ", 49 - (unsigned long long)atomic64_read(&acct[dir].packets), 50 - (unsigned long long)atomic64_read(&acct[dir].bytes)); 51 + (unsigned long long)atomic64_read(&counter[dir].packets), 52 + (unsigned long long)atomic64_read(&counter[dir].bytes)); 51 53 }; 52 54 EXPORT_SYMBOL_GPL(seq_print_acct); 53 55 54 56 static struct nf_ct_ext_type acct_extend __read_mostly = { 55 - .len = sizeof(struct nf_conn_counter[IP_CT_DIR_MAX]), 56 - .align = __alignof__(struct nf_conn_counter[IP_CT_DIR_MAX]), 57 + .len = sizeof(struct nf_conn_acct), 58 + .align = __alignof__(struct nf_conn_acct), 57 59 .id = NF_CT_EXT_ACCT, 58 60 }; 59 61
+10 -6
net/netfilter/nf_conntrack_core.c
··· 1109 1109 1110 1110 acct: 1111 1111 if (do_acct) { 1112 - struct nf_conn_counter *acct; 1112 + struct nf_conn_acct *acct; 1113 1113 1114 1114 acct = nf_conn_acct_find(ct); 1115 1115 if (acct) { 1116 - atomic64_inc(&acct[CTINFO2DIR(ctinfo)].packets); 1117 - atomic64_add(skb->len, &acct[CTINFO2DIR(ctinfo)].bytes); 1116 + struct nf_conn_counter *counter = acct->counter; 1117 + 1118 + atomic64_inc(&counter[CTINFO2DIR(ctinfo)].packets); 1119 + atomic64_add(skb->len, &counter[CTINFO2DIR(ctinfo)].bytes); 1118 1120 } 1119 1121 } 1120 1122 } ··· 1128 1126 int do_acct) 1129 1127 { 1130 1128 if (do_acct) { 1131 - struct nf_conn_counter *acct; 1129 + struct nf_conn_acct *acct; 1132 1130 1133 1131 acct = nf_conn_acct_find(ct); 1134 1132 if (acct) { 1135 - atomic64_inc(&acct[CTINFO2DIR(ctinfo)].packets); 1133 + struct nf_conn_counter *counter = acct->counter; 1134 + 1135 + atomic64_inc(&counter[CTINFO2DIR(ctinfo)].packets); 1136 1136 atomic64_add(skb->len - skb_network_offset(skb), 1137 - &acct[CTINFO2DIR(ctinfo)].bytes); 1137 + &counter[CTINFO2DIR(ctinfo)].bytes); 1138 1138 } 1139 1139 } 1140 1140
+26 -25
net/netfilter/nf_conntrack_netlink.c
··· 211 211 } 212 212 213 213 static int 214 - dump_counters(struct sk_buff *skb, u64 pkts, u64 bytes, 215 - enum ip_conntrack_dir dir) 214 + dump_counters(struct sk_buff *skb, struct nf_conn_acct *acct, 215 + enum ip_conntrack_dir dir, int type) 216 216 { 217 - enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG; 217 + enum ctattr_type attr = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG; 218 + struct nf_conn_counter *counter = acct->counter; 218 219 struct nlattr *nest_count; 220 + u64 pkts, bytes; 219 221 220 - nest_count = nla_nest_start(skb, type | NLA_F_NESTED); 222 + if (type == IPCTNL_MSG_CT_GET_CTRZERO) { 223 + pkts = atomic64_xchg(&counter[dir].packets, 0); 224 + bytes = atomic64_xchg(&counter[dir].bytes, 0); 225 + } else { 226 + pkts = atomic64_read(&counter[dir].packets); 227 + bytes = atomic64_read(&counter[dir].bytes); 228 + } 229 + 230 + nest_count = nla_nest_start(skb, attr | NLA_F_NESTED); 221 231 if (!nest_count) 222 232 goto nla_put_failure; 223 233 ··· 244 234 } 245 235 246 236 static int 247 - ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct, 248 - enum ip_conntrack_dir dir, int type) 237 + ctnetlink_dump_acct(struct sk_buff *skb, const struct nf_conn *ct, int type) 249 238 { 250 - struct nf_conn_counter *acct; 251 - u64 pkts, bytes; 239 + struct nf_conn_acct *acct = nf_conn_acct_find(ct); 252 240 253 - acct = nf_conn_acct_find(ct); 254 241 if (!acct) 255 242 return 0; 256 243 257 - if (type == IPCTNL_MSG_CT_GET_CTRZERO) { 258 - pkts = atomic64_xchg(&acct[dir].packets, 0); 259 - bytes = atomic64_xchg(&acct[dir].bytes, 0); 260 - } else { 261 - pkts = atomic64_read(&acct[dir].packets); 262 - bytes = atomic64_read(&acct[dir].bytes); 263 - } 264 - return dump_counters(skb, pkts, bytes, dir); 244 + if (dump_counters(skb, acct, IP_CT_DIR_ORIGINAL, type) < 0) 245 + return -1; 246 + if (dump_counters(skb, acct, IP_CT_DIR_REPLY, type) < 0) 247 + return -1; 248 + 249 + return 0; 265 250 } 266 251 267 252 static int ··· 493 488 494 489 if (ctnetlink_dump_status(skb, ct) < 0 || 495 490 ctnetlink_dump_timeout(skb, ct) < 0 || 496 - ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL, type) < 0 || 497 - ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY, type) < 0 || 491 + ctnetlink_dump_acct(skb, ct, type) < 0 || 498 492 ctnetlink_dump_timestamp(skb, ct) < 0 || 499 493 ctnetlink_dump_protoinfo(skb, ct) < 0 || 500 494 ctnetlink_dump_helpinfo(skb, ct) < 0 || ··· 534 530 } 535 531 536 532 static inline size_t 537 - ctnetlink_counters_size(const struct nf_conn *ct) 533 + ctnetlink_acct_size(const struct nf_conn *ct) 538 534 { 539 535 if (!nf_ct_ext_exist(ct, NF_CT_EXT_ACCT)) 540 536 return 0; ··· 583 579 + 3 * nla_total_size(sizeof(u_int8_t)) /* CTA_PROTO_NUM */ 584 580 + nla_total_size(sizeof(u_int32_t)) /* CTA_ID */ 585 581 + nla_total_size(sizeof(u_int32_t)) /* CTA_STATUS */ 586 - + ctnetlink_counters_size(ct) 582 + + ctnetlink_acct_size(ct) 587 583 + ctnetlink_timestamp_size(ct) 588 584 + nla_total_size(sizeof(u_int32_t)) /* CTA_TIMEOUT */ 589 585 + nla_total_size(0) /* CTA_PROTOINFO */ ··· 677 673 goto nla_put_failure; 678 674 679 675 if (events & (1 << IPCT_DESTROY)) { 680 - if (ctnetlink_dump_counters(skb, ct, 681 - IP_CT_DIR_ORIGINAL, type) < 0 || 682 - ctnetlink_dump_counters(skb, ct, 683 - IP_CT_DIR_REPLY, type) < 0 || 676 + if (ctnetlink_dump_acct(skb, ct, type) < 0 || 684 677 ctnetlink_dump_timestamp(skb, ct) < 0) 685 678 goto nla_put_failure; 686 679 } else {
+4 -2
net/netfilter/xt_connbytes.c
··· 26 26 u_int64_t what = 0; /* initialize to make gcc happy */ 27 27 u_int64_t bytes = 0; 28 28 u_int64_t pkts = 0; 29 + const struct nf_conn_acct *acct; 29 30 const struct nf_conn_counter *counters; 30 31 31 32 ct = nf_ct_get(skb, &ctinfo); 32 33 if (!ct) 33 34 return false; 34 35 35 - counters = nf_conn_acct_find(ct); 36 - if (!counters) 36 + acct = nf_conn_acct_find(ct); 37 + if (!acct) 37 38 return false; 38 39 40 + counters = acct->counter; 39 41 switch (sinfo->what) { 40 42 case XT_CONNBYTES_PKTS: 41 43 switch (sinfo->direction) {
+2 -11
net/netfilter/xt_socket.c
··· 35 35 #include <net/netfilter/nf_conntrack.h> 36 36 #endif 37 37 38 - static void 39 - xt_socket_put_sk(struct sock *sk) 40 - { 41 - if (sk->sk_state == TCP_TIME_WAIT) 42 - inet_twsk_put(inet_twsk(sk)); 43 - else 44 - sock_put(sk); 45 - } 46 - 47 38 static int 48 39 extract_icmp4_fields(const struct sk_buff *skb, 49 40 u8 *protocol, ··· 207 216 inet_twsk(sk)->tw_transparent)); 208 217 209 218 if (sk != skb->sk) 210 - xt_socket_put_sk(sk); 219 + sock_gen_put(sk); 211 220 212 221 if (wildcard || !transparent) 213 222 sk = NULL; ··· 372 381 inet_twsk(sk)->tw_transparent)); 373 382 374 383 if (sk != skb->sk) 375 - xt_socket_put_sk(sk); 384 + sock_gen_put(sk); 376 385 377 386 if (wildcard || !transparent) 378 387 sk = NULL;