aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2009-06-10 08:32:47 -0400
committerPatrick McHardy <kaber@trash.net>2009-06-10 08:32:47 -0400
commit440f0d588555892601cfe511728a0fc0c8204063 (patch)
tree1b98fe9ec8f7e7337f7eed09af2c36a43a9f92b8
parenta31e1ffd2231b8fdf7eda9ed750a4a0df9bcad4e (diff)
netfilter: nf_conntrack: use per-conntrack locks for protocol data
Introduce per-conntrack locks and use them instead of the global protocol locks to avoid contention. Especially tcp_lock shows up very high in profiles on larger machines. This will also allow to simplify the upcoming reliable event delivery patches. Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r--include/net/netfilter/nf_conntrack.h2
-rw-r--r--include/net/netfilter/nf_conntrack_l4proto.h4
-rw-r--r--net/netfilter/nf_conntrack_core.c1
-rw-r--r--net/netfilter/nf_conntrack_netlink.c4
-rw-r--r--net/netfilter/nf_conntrack_proto_dccp.c24
-rw-r--r--net/netfilter/nf_conntrack_proto_gre.c3
-rw-r--r--net/netfilter/nf_conntrack_proto_sctp.c27
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c39
8 files changed, 49 insertions, 55 deletions
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 2b877374242d..ecc79f959076 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -93,6 +93,8 @@ struct nf_conn {
93 plus 1 for any connection(s) we are `master' for */ 93 plus 1 for any connection(s) we are `master' for */
94 struct nf_conntrack ct_general; 94 struct nf_conntrack ct_general;
95 95
96 spinlock_t lock;
97
96 /* XXX should I move this to the tail ? - Y.K */ 98 /* XXX should I move this to the tail ? - Y.K */
97 /* These are my tuples; original and reply */ 99 /* These are my tuples; original and reply */
98 struct nf_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX]; 100 struct nf_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h
index ba32ed7bdabe..3767fb41e541 100644
--- a/include/net/netfilter/nf_conntrack_l4proto.h
+++ b/include/net/netfilter/nf_conntrack_l4proto.h
@@ -59,11 +59,11 @@ struct nf_conntrack_l4proto
59 const struct nf_conntrack_tuple *); 59 const struct nf_conntrack_tuple *);
60 60
61 /* Print out the private part of the conntrack. */ 61 /* Print out the private part of the conntrack. */
62 int (*print_conntrack)(struct seq_file *s, const struct nf_conn *); 62 int (*print_conntrack)(struct seq_file *s, struct nf_conn *);
63 63
64 /* convert protoinfo to nfnetink attributes */ 64 /* convert protoinfo to nfnetink attributes */
65 int (*to_nlattr)(struct sk_buff *skb, struct nlattr *nla, 65 int (*to_nlattr)(struct sk_buff *skb, struct nlattr *nla,
66 const struct nf_conn *ct); 66 struct nf_conn *ct);
67 /* Calculate protoinfo nlattr size */ 67 /* Calculate protoinfo nlattr size */
68 int (*nlattr_size)(void); 68 int (*nlattr_size)(void);
69 69
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index b54c23475e94..edf95695e0aa 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -519,6 +519,7 @@ struct nf_conn *nf_conntrack_alloc(struct net *net,
519 return ERR_PTR(-ENOMEM); 519 return ERR_PTR(-ENOMEM);
520 } 520 }
521 521
522 spin_lock_init(&ct->lock);
522 atomic_set(&ct->ct_general.use, 1); 523 atomic_set(&ct->ct_general.use, 1);
523 ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig; 524 ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig;
524 ct->tuplehash[IP_CT_DIR_REPLY].tuple = *repl; 525 ct->tuplehash[IP_CT_DIR_REPLY].tuple = *repl;
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 4448b062de0c..4e503ada5728 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -143,7 +143,7 @@ nla_put_failure:
143} 143}
144 144
145static inline int 145static inline int
146ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct nf_conn *ct) 146ctnetlink_dump_protoinfo(struct sk_buff *skb, struct nf_conn *ct)
147{ 147{
148 struct nf_conntrack_l4proto *l4proto; 148 struct nf_conntrack_l4proto *l4proto;
149 struct nlattr *nest_proto; 149 struct nlattr *nest_proto;
@@ -347,7 +347,7 @@ nla_put_failure:
347 347
348static int 348static int
349ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq, 349ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
350 int event, const struct nf_conn *ct) 350 int event, struct nf_conn *ct)
351{ 351{
352 struct nlmsghdr *nlh; 352 struct nlmsghdr *nlh;
353 struct nfgenmsg *nfmsg; 353 struct nfgenmsg *nfmsg;
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c
index 11801c43c8cf..6b08d3277965 100644
--- a/net/netfilter/nf_conntrack_proto_dccp.c
+++ b/net/netfilter/nf_conntrack_proto_dccp.c
@@ -24,8 +24,6 @@
24#include <net/netfilter/nf_conntrack_l4proto.h> 24#include <net/netfilter/nf_conntrack_l4proto.h>
25#include <net/netfilter/nf_log.h> 25#include <net/netfilter/nf_log.h>
26 26
27static DEFINE_RWLOCK(dccp_lock);
28
29/* Timeouts are based on values from RFC4340: 27/* Timeouts are based on values from RFC4340:
30 * 28 *
31 * - REQUEST: 29 * - REQUEST:
@@ -491,7 +489,7 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
491 return NF_ACCEPT; 489 return NF_ACCEPT;
492 } 490 }
493 491
494 write_lock_bh(&dccp_lock); 492 spin_lock_bh(&ct->lock);
495 493
496 role = ct->proto.dccp.role[dir]; 494 role = ct->proto.dccp.role[dir];
497 old_state = ct->proto.dccp.state; 495 old_state = ct->proto.dccp.state;
@@ -535,13 +533,13 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
535 ct->proto.dccp.last_dir = dir; 533 ct->proto.dccp.last_dir = dir;
536 ct->proto.dccp.last_pkt = type; 534 ct->proto.dccp.last_pkt = type;
537 535
538 write_unlock_bh(&dccp_lock); 536 spin_unlock_bh(&ct->lock);
539 if (LOG_INVALID(net, IPPROTO_DCCP)) 537 if (LOG_INVALID(net, IPPROTO_DCCP))
540 nf_log_packet(pf, 0, skb, NULL, NULL, NULL, 538 nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
541 "nf_ct_dccp: invalid packet ignored "); 539 "nf_ct_dccp: invalid packet ignored ");
542 return NF_ACCEPT; 540 return NF_ACCEPT;
543 case CT_DCCP_INVALID: 541 case CT_DCCP_INVALID:
544 write_unlock_bh(&dccp_lock); 542 spin_unlock_bh(&ct->lock);
545 if (LOG_INVALID(net, IPPROTO_DCCP)) 543 if (LOG_INVALID(net, IPPROTO_DCCP))
546 nf_log_packet(pf, 0, skb, NULL, NULL, NULL, 544 nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
547 "nf_ct_dccp: invalid state transition "); 545 "nf_ct_dccp: invalid state transition ");
@@ -551,7 +549,7 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
551 ct->proto.dccp.last_dir = dir; 549 ct->proto.dccp.last_dir = dir;
552 ct->proto.dccp.last_pkt = type; 550 ct->proto.dccp.last_pkt = type;
553 ct->proto.dccp.state = new_state; 551 ct->proto.dccp.state = new_state;
554 write_unlock_bh(&dccp_lock); 552 spin_unlock_bh(&ct->lock);
555 553
556 dn = dccp_pernet(net); 554 dn = dccp_pernet(net);
557 nf_ct_refresh_acct(ct, ctinfo, skb, dn->dccp_timeout[new_state]); 555 nf_ct_refresh_acct(ct, ctinfo, skb, dn->dccp_timeout[new_state]);
@@ -617,18 +615,18 @@ static int dccp_print_tuple(struct seq_file *s,
617 ntohs(tuple->dst.u.dccp.port)); 615 ntohs(tuple->dst.u.dccp.port));
618} 616}
619 617
620static int dccp_print_conntrack(struct seq_file *s, const struct nf_conn *ct) 618static int dccp_print_conntrack(struct seq_file *s, struct nf_conn *ct)
621{ 619{
622 return seq_printf(s, "%s ", dccp_state_names[ct->proto.dccp.state]); 620 return seq_printf(s, "%s ", dccp_state_names[ct->proto.dccp.state]);
623} 621}
624 622
625#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 623#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
626static int dccp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, 624static int dccp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
627 const struct nf_conn *ct) 625 struct nf_conn *ct)
628{ 626{
629 struct nlattr *nest_parms; 627 struct nlattr *nest_parms;
630 628
631 read_lock_bh(&dccp_lock); 629 spin_lock_bh(&ct->lock);
632 nest_parms = nla_nest_start(skb, CTA_PROTOINFO_DCCP | NLA_F_NESTED); 630 nest_parms = nla_nest_start(skb, CTA_PROTOINFO_DCCP | NLA_F_NESTED);
633 if (!nest_parms) 631 if (!nest_parms)
634 goto nla_put_failure; 632 goto nla_put_failure;
@@ -638,11 +636,11 @@ static int dccp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
638 NLA_PUT_BE64(skb, CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ, 636 NLA_PUT_BE64(skb, CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ,
639 cpu_to_be64(ct->proto.dccp.handshake_seq)); 637 cpu_to_be64(ct->proto.dccp.handshake_seq));
640 nla_nest_end(skb, nest_parms); 638 nla_nest_end(skb, nest_parms);
641 read_unlock_bh(&dccp_lock); 639 spin_unlock_bh(&ct->lock);
642 return 0; 640 return 0;
643 641
644nla_put_failure: 642nla_put_failure:
645 read_unlock_bh(&dccp_lock); 643 spin_unlock_bh(&ct->lock);
646 return -1; 644 return -1;
647} 645}
648 646
@@ -673,7 +671,7 @@ static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct)
673 return -EINVAL; 671 return -EINVAL;
674 } 672 }
675 673
676 write_lock_bh(&dccp_lock); 674 spin_lock_bh(&ct->lock);
677 ct->proto.dccp.state = nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]); 675 ct->proto.dccp.state = nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]);
678 if (nla_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]) == CT_DCCP_ROLE_CLIENT) { 676 if (nla_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]) == CT_DCCP_ROLE_CLIENT) {
679 ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_CLIENT; 677 ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_CLIENT;
@@ -686,7 +684,7 @@ static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct)
686 ct->proto.dccp.handshake_seq = 684 ct->proto.dccp.handshake_seq =
687 be64_to_cpu(nla_get_be64(tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ])); 685 be64_to_cpu(nla_get_be64(tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ]));
688 } 686 }
689 write_unlock_bh(&dccp_lock); 687 spin_unlock_bh(&ct->lock);
690 return 0; 688 return 0;
691} 689}
692 690
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
index 117b80112fcb..175a28c96168 100644
--- a/net/netfilter/nf_conntrack_proto_gre.c
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -219,8 +219,7 @@ static int gre_print_tuple(struct seq_file *s,
219} 219}
220 220
221/* print private data for conntrack */ 221/* print private data for conntrack */
222static int gre_print_conntrack(struct seq_file *s, 222static int gre_print_conntrack(struct seq_file *s, struct nf_conn *ct)
223 const struct nf_conn *ct)
224{ 223{
225 return seq_printf(s, "timeout=%u, stream_timeout=%u ", 224 return seq_printf(s, "timeout=%u, stream_timeout=%u ",
226 (ct->proto.gre.timeout / HZ), 225 (ct->proto.gre.timeout / HZ),
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 101b4ad9e817..c10e6f36e31e 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -25,9 +25,6 @@
25#include <net/netfilter/nf_conntrack_l4proto.h> 25#include <net/netfilter/nf_conntrack_l4proto.h>
26#include <net/netfilter/nf_conntrack_ecache.h> 26#include <net/netfilter/nf_conntrack_ecache.h>
27 27
28/* Protects ct->proto.sctp */
29static DEFINE_RWLOCK(sctp_lock);
30
31/* FIXME: Examine ipfilter's timeouts and conntrack transitions more 28/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
32 closely. They're more complex. --RR 29 closely. They're more complex. --RR
33 30
@@ -164,13 +161,13 @@ static int sctp_print_tuple(struct seq_file *s,
164} 161}
165 162
166/* Print out the private part of the conntrack. */ 163/* Print out the private part of the conntrack. */
167static int sctp_print_conntrack(struct seq_file *s, const struct nf_conn *ct) 164static int sctp_print_conntrack(struct seq_file *s, struct nf_conn *ct)
168{ 165{
169 enum sctp_conntrack state; 166 enum sctp_conntrack state;
170 167
171 read_lock_bh(&sctp_lock); 168 spin_lock_bh(&ct->lock);
172 state = ct->proto.sctp.state; 169 state = ct->proto.sctp.state;
173 read_unlock_bh(&sctp_lock); 170 spin_unlock_bh(&ct->lock);
174 171
175 return seq_printf(s, "%s ", sctp_conntrack_names[state]); 172 return seq_printf(s, "%s ", sctp_conntrack_names[state]);
176} 173}
@@ -318,7 +315,7 @@ static int sctp_packet(struct nf_conn *ct,
318 } 315 }
319 316
320 old_state = new_state = SCTP_CONNTRACK_NONE; 317 old_state = new_state = SCTP_CONNTRACK_NONE;
321 write_lock_bh(&sctp_lock); 318 spin_lock_bh(&ct->lock);
322 for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) { 319 for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
323 /* Special cases of Verification tag check (Sec 8.5.1) */ 320 /* Special cases of Verification tag check (Sec 8.5.1) */
324 if (sch->type == SCTP_CID_INIT) { 321 if (sch->type == SCTP_CID_INIT) {
@@ -371,7 +368,7 @@ static int sctp_packet(struct nf_conn *ct,
371 if (old_state != new_state) 368 if (old_state != new_state)
372 nf_conntrack_event_cache(IPCT_PROTOINFO, ct); 369 nf_conntrack_event_cache(IPCT_PROTOINFO, ct);
373 } 370 }
374 write_unlock_bh(&sctp_lock); 371 spin_unlock_bh(&ct->lock);
375 372
376 nf_ct_refresh_acct(ct, ctinfo, skb, sctp_timeouts[new_state]); 373 nf_ct_refresh_acct(ct, ctinfo, skb, sctp_timeouts[new_state]);
377 374
@@ -386,7 +383,7 @@ static int sctp_packet(struct nf_conn *ct,
386 return NF_ACCEPT; 383 return NF_ACCEPT;
387 384
388out_unlock: 385out_unlock:
389 write_unlock_bh(&sctp_lock); 386 spin_unlock_bh(&ct->lock);
390out: 387out:
391 return -NF_ACCEPT; 388 return -NF_ACCEPT;
392} 389}
@@ -469,11 +466,11 @@ static bool sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
469#include <linux/netfilter/nfnetlink_conntrack.h> 466#include <linux/netfilter/nfnetlink_conntrack.h>
470 467
471static int sctp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, 468static int sctp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
472 const struct nf_conn *ct) 469 struct nf_conn *ct)
473{ 470{
474 struct nlattr *nest_parms; 471 struct nlattr *nest_parms;
475 472
476 read_lock_bh(&sctp_lock); 473 spin_lock_bh(&ct->lock);
477 nest_parms = nla_nest_start(skb, CTA_PROTOINFO_SCTP | NLA_F_NESTED); 474 nest_parms = nla_nest_start(skb, CTA_PROTOINFO_SCTP | NLA_F_NESTED);
478 if (!nest_parms) 475 if (!nest_parms)
479 goto nla_put_failure; 476 goto nla_put_failure;
@@ -488,14 +485,14 @@ static int sctp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
488 CTA_PROTOINFO_SCTP_VTAG_REPLY, 485 CTA_PROTOINFO_SCTP_VTAG_REPLY,
489 ct->proto.sctp.vtag[IP_CT_DIR_REPLY]); 486 ct->proto.sctp.vtag[IP_CT_DIR_REPLY]);
490 487
491 read_unlock_bh(&sctp_lock); 488 spin_unlock_bh(&ct->lock);
492 489
493 nla_nest_end(skb, nest_parms); 490 nla_nest_end(skb, nest_parms);
494 491
495 return 0; 492 return 0;
496 493
497nla_put_failure: 494nla_put_failure:
498 read_unlock_bh(&sctp_lock); 495 spin_unlock_bh(&ct->lock);
499 return -1; 496 return -1;
500} 497}
501 498
@@ -527,13 +524,13 @@ static int nlattr_to_sctp(struct nlattr *cda[], struct nf_conn *ct)
527 !tb[CTA_PROTOINFO_SCTP_VTAG_REPLY]) 524 !tb[CTA_PROTOINFO_SCTP_VTAG_REPLY])
528 return -EINVAL; 525 return -EINVAL;
529 526
530 write_lock_bh(&sctp_lock); 527 spin_lock_bh(&ct->lock);
531 ct->proto.sctp.state = nla_get_u8(tb[CTA_PROTOINFO_SCTP_STATE]); 528 ct->proto.sctp.state = nla_get_u8(tb[CTA_PROTOINFO_SCTP_STATE]);
532 ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = 529 ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] =
533 nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL]); 530 nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL]);
534 ct->proto.sctp.vtag[IP_CT_DIR_REPLY] = 531 ct->proto.sctp.vtag[IP_CT_DIR_REPLY] =
535 nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_REPLY]); 532 nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_REPLY]);
536 write_unlock_bh(&sctp_lock); 533 spin_unlock_bh(&ct->lock);
537 534
538 return 0; 535 return 0;
539} 536}
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index b7e8a825efed..5c5739c741f1 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -29,9 +29,6 @@
29#include <net/netfilter/ipv4/nf_conntrack_ipv4.h> 29#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
30#include <net/netfilter/ipv6/nf_conntrack_ipv6.h> 30#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
31 31
32/* Protects ct->proto.tcp */
33static DEFINE_RWLOCK(tcp_lock);
34
35/* "Be conservative in what you do, 32/* "Be conservative in what you do,
36 be liberal in what you accept from others." 33 be liberal in what you accept from others."
37 If it's non-zero, we mark only out of window RST segments as INVALID. */ 34 If it's non-zero, we mark only out of window RST segments as INVALID. */
@@ -309,13 +306,13 @@ static int tcp_print_tuple(struct seq_file *s,
309} 306}
310 307
311/* Print out the private part of the conntrack. */ 308/* Print out the private part of the conntrack. */
312static int tcp_print_conntrack(struct seq_file *s, const struct nf_conn *ct) 309static int tcp_print_conntrack(struct seq_file *s, struct nf_conn *ct)
313{ 310{
314 enum tcp_conntrack state; 311 enum tcp_conntrack state;
315 312
316 read_lock_bh(&tcp_lock); 313 spin_lock_bh(&ct->lock);
317 state = ct->proto.tcp.state; 314 state = ct->proto.tcp.state;
318 read_unlock_bh(&tcp_lock); 315 spin_unlock_bh(&ct->lock);
319 316
320 return seq_printf(s, "%s ", tcp_conntrack_names[state]); 317 return seq_printf(s, "%s ", tcp_conntrack_names[state]);
321} 318}
@@ -725,14 +722,14 @@ void nf_conntrack_tcp_update(const struct sk_buff *skb,
725 722
726 end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, dataoff, tcph); 723 end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, dataoff, tcph);
727 724
728 write_lock_bh(&tcp_lock); 725 spin_lock_bh(&ct->lock);
729 /* 726 /*
730 * We have to worry for the ack in the reply packet only... 727 * We have to worry for the ack in the reply packet only...
731 */ 728 */
732 if (after(end, ct->proto.tcp.seen[dir].td_end)) 729 if (after(end, ct->proto.tcp.seen[dir].td_end))
733 ct->proto.tcp.seen[dir].td_end = end; 730 ct->proto.tcp.seen[dir].td_end = end;
734 ct->proto.tcp.last_end = end; 731 ct->proto.tcp.last_end = end;
735 write_unlock_bh(&tcp_lock); 732 spin_unlock_bh(&ct->lock);
736 pr_debug("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i " 733 pr_debug("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i "
737 "receiver end=%u maxend=%u maxwin=%u scale=%i\n", 734 "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
738 sender->td_end, sender->td_maxend, sender->td_maxwin, 735 sender->td_end, sender->td_maxend, sender->td_maxwin,
@@ -841,7 +838,7 @@ static int tcp_packet(struct nf_conn *ct,
841 th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph); 838 th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph);
842 BUG_ON(th == NULL); 839 BUG_ON(th == NULL);
843 840
844 write_lock_bh(&tcp_lock); 841 spin_lock_bh(&ct->lock);
845 old_state = ct->proto.tcp.state; 842 old_state = ct->proto.tcp.state;
846 dir = CTINFO2DIR(ctinfo); 843 dir = CTINFO2DIR(ctinfo);
847 index = get_conntrack_index(th); 844 index = get_conntrack_index(th);
@@ -871,7 +868,7 @@ static int tcp_packet(struct nf_conn *ct,
871 && ct->proto.tcp.last_index == TCP_RST_SET)) { 868 && ct->proto.tcp.last_index == TCP_RST_SET)) {
872 /* Attempt to reopen a closed/aborted connection. 869 /* Attempt to reopen a closed/aborted connection.
873 * Delete this connection and look up again. */ 870 * Delete this connection and look up again. */
874 write_unlock_bh(&tcp_lock); 871 spin_unlock_bh(&ct->lock);
875 872
876 /* Only repeat if we can actually remove the timer. 873 /* Only repeat if we can actually remove the timer.
877 * Destruction may already be in progress in process 874 * Destruction may already be in progress in process
@@ -907,7 +904,7 @@ static int tcp_packet(struct nf_conn *ct,
907 * that the client cannot but retransmit its SYN and 904 * that the client cannot but retransmit its SYN and
908 * thus initiate a clean new session. 905 * thus initiate a clean new session.
909 */ 906 */
910 write_unlock_bh(&tcp_lock); 907 spin_unlock_bh(&ct->lock);
911 if (LOG_INVALID(net, IPPROTO_TCP)) 908 if (LOG_INVALID(net, IPPROTO_TCP))
912 nf_log_packet(pf, 0, skb, NULL, NULL, NULL, 909 nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
913 "nf_ct_tcp: killing out of sync session "); 910 "nf_ct_tcp: killing out of sync session ");
@@ -920,7 +917,7 @@ static int tcp_packet(struct nf_conn *ct,
920 ct->proto.tcp.last_end = 917 ct->proto.tcp.last_end =
921 segment_seq_plus_len(ntohl(th->seq), skb->len, dataoff, th); 918 segment_seq_plus_len(ntohl(th->seq), skb->len, dataoff, th);
922 919
923 write_unlock_bh(&tcp_lock); 920 spin_unlock_bh(&ct->lock);
924 if (LOG_INVALID(net, IPPROTO_TCP)) 921 if (LOG_INVALID(net, IPPROTO_TCP))
925 nf_log_packet(pf, 0, skb, NULL, NULL, NULL, 922 nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
926 "nf_ct_tcp: invalid packet ignored "); 923 "nf_ct_tcp: invalid packet ignored ");
@@ -929,7 +926,7 @@ static int tcp_packet(struct nf_conn *ct,
929 /* Invalid packet */ 926 /* Invalid packet */
930 pr_debug("nf_ct_tcp: Invalid dir=%i index=%u ostate=%u\n", 927 pr_debug("nf_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
931 dir, get_conntrack_index(th), old_state); 928 dir, get_conntrack_index(th), old_state);
932 write_unlock_bh(&tcp_lock); 929 spin_unlock_bh(&ct->lock);
933 if (LOG_INVALID(net, IPPROTO_TCP)) 930 if (LOG_INVALID(net, IPPROTO_TCP))
934 nf_log_packet(pf, 0, skb, NULL, NULL, NULL, 931 nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
935 "nf_ct_tcp: invalid state "); 932 "nf_ct_tcp: invalid state ");
@@ -960,7 +957,7 @@ static int tcp_packet(struct nf_conn *ct,
960 957
961 if (!tcp_in_window(ct, &ct->proto.tcp, dir, index, 958 if (!tcp_in_window(ct, &ct->proto.tcp, dir, index,
962 skb, dataoff, th, pf)) { 959 skb, dataoff, th, pf)) {
963 write_unlock_bh(&tcp_lock); 960 spin_unlock_bh(&ct->lock);
964 return -NF_ACCEPT; 961 return -NF_ACCEPT;
965 } 962 }
966 in_window: 963 in_window:
@@ -989,7 +986,7 @@ static int tcp_packet(struct nf_conn *ct,
989 timeout = nf_ct_tcp_timeout_unacknowledged; 986 timeout = nf_ct_tcp_timeout_unacknowledged;
990 else 987 else
991 timeout = tcp_timeouts[new_state]; 988 timeout = tcp_timeouts[new_state];
992 write_unlock_bh(&tcp_lock); 989 spin_unlock_bh(&ct->lock);
993 990
994 if (new_state != old_state) 991 if (new_state != old_state)
995 nf_conntrack_event_cache(IPCT_PROTOINFO, ct); 992 nf_conntrack_event_cache(IPCT_PROTOINFO, ct);
@@ -1106,12 +1103,12 @@ static bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb,
1106#include <linux/netfilter/nfnetlink_conntrack.h> 1103#include <linux/netfilter/nfnetlink_conntrack.h>
1107 1104
1108static int tcp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, 1105static int tcp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
1109 const struct nf_conn *ct) 1106 struct nf_conn *ct)
1110{ 1107{
1111 struct nlattr *nest_parms; 1108 struct nlattr *nest_parms;
1112 struct nf_ct_tcp_flags tmp = {}; 1109 struct nf_ct_tcp_flags tmp = {};
1113 1110
1114 read_lock_bh(&tcp_lock); 1111 spin_lock_bh(&ct->lock);
1115 nest_parms = nla_nest_start(skb, CTA_PROTOINFO_TCP | NLA_F_NESTED); 1112 nest_parms = nla_nest_start(skb, CTA_PROTOINFO_TCP | NLA_F_NESTED);
1116 if (!nest_parms) 1113 if (!nest_parms)
1117 goto nla_put_failure; 1114 goto nla_put_failure;
@@ -1131,14 +1128,14 @@ static int tcp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
1131 tmp.flags = ct->proto.tcp.seen[1].flags; 1128 tmp.flags = ct->proto.tcp.seen[1].flags;
1132 NLA_PUT(skb, CTA_PROTOINFO_TCP_FLAGS_REPLY, 1129 NLA_PUT(skb, CTA_PROTOINFO_TCP_FLAGS_REPLY,
1133 sizeof(struct nf_ct_tcp_flags), &tmp); 1130 sizeof(struct nf_ct_tcp_flags), &tmp);
1134 read_unlock_bh(&tcp_lock); 1131 spin_unlock_bh(&ct->lock);
1135 1132
1136 nla_nest_end(skb, nest_parms); 1133 nla_nest_end(skb, nest_parms);
1137 1134
1138 return 0; 1135 return 0;
1139 1136
1140nla_put_failure: 1137nla_put_failure:
1141 read_unlock_bh(&tcp_lock); 1138 spin_unlock_bh(&ct->lock);
1142 return -1; 1139 return -1;
1143} 1140}
1144 1141
@@ -1169,7 +1166,7 @@ static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct)
1169 nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]) >= TCP_CONNTRACK_MAX) 1166 nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]) >= TCP_CONNTRACK_MAX)
1170 return -EINVAL; 1167 return -EINVAL;
1171 1168
1172 write_lock_bh(&tcp_lock); 1169 spin_lock_bh(&ct->lock);
1173 if (tb[CTA_PROTOINFO_TCP_STATE]) 1170 if (tb[CTA_PROTOINFO_TCP_STATE])
1174 ct->proto.tcp.state = nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]); 1171 ct->proto.tcp.state = nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]);
1175 1172
@@ -1196,7 +1193,7 @@ static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct)
1196 ct->proto.tcp.seen[1].td_scale = 1193 ct->proto.tcp.seen[1].td_scale =
1197 nla_get_u8(tb[CTA_PROTOINFO_TCP_WSCALE_REPLY]); 1194 nla_get_u8(tb[CTA_PROTOINFO_TCP_WSCALE_REPLY]);
1198 } 1195 }
1199 write_unlock_bh(&tcp_lock); 1196 spin_unlock_bh(&ct->lock);
1200 1197
1201 return 0; 1198 return 0;
1202} 1199}