]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/netfilter/nf_conntrack_proto_tcp.c
netfilter: nf_conntrack: use per-conntrack locks for protocol data
[net-next-2.6.git] / net / netfilter / nf_conntrack_proto_tcp.c
index b7e8a825efed451f84320df913356034be932150..5c5739c741f1b2e8c6f9ae737b5a9eca61e6671f 100644 (file)
@@ -29,9 +29,6 @@
 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
 #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
 
-/* Protects ct->proto.tcp */
-static DEFINE_RWLOCK(tcp_lock);
-
 /* "Be conservative in what you do,
     be liberal in what you accept from others."
     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,
 }
 
 /* Print out the private part of the conntrack. */
-static int tcp_print_conntrack(struct seq_file *s, const struct nf_conn *ct)
+static int tcp_print_conntrack(struct seq_file *s, struct nf_conn *ct)
 {
        enum tcp_conntrack state;
 
-       read_lock_bh(&tcp_lock);
+       spin_lock_bh(&ct->lock);
        state = ct->proto.tcp.state;
-       read_unlock_bh(&tcp_lock);
+       spin_unlock_bh(&ct->lock);
 
        return seq_printf(s, "%s ", tcp_conntrack_names[state]);
 }
@@ -725,14 +722,14 @@ void nf_conntrack_tcp_update(const struct sk_buff *skb,
 
        end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, dataoff, tcph);
 
-       write_lock_bh(&tcp_lock);
+       spin_lock_bh(&ct->lock);
        /*
         * We have to worry for the ack in the reply packet only...
         */
        if (after(end, ct->proto.tcp.seen[dir].td_end))
                ct->proto.tcp.seen[dir].td_end = end;
        ct->proto.tcp.last_end = end;
-       write_unlock_bh(&tcp_lock);
+       spin_unlock_bh(&ct->lock);
        pr_debug("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i "
                 "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
                 sender->td_end, sender->td_maxend, sender->td_maxwin,
@@ -841,7 +838,7 @@ static int tcp_packet(struct nf_conn *ct,
        th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph);
        BUG_ON(th == NULL);
 
-       write_lock_bh(&tcp_lock);
+       spin_lock_bh(&ct->lock);
        old_state = ct->proto.tcp.state;
        dir = CTINFO2DIR(ctinfo);
        index = get_conntrack_index(th);
@@ -871,7 +868,7 @@ static int tcp_packet(struct nf_conn *ct,
                        && ct->proto.tcp.last_index == TCP_RST_SET)) {
                        /* Attempt to reopen a closed/aborted connection.
                         * Delete this connection and look up again. */
-                       write_unlock_bh(&tcp_lock);
+                       spin_unlock_bh(&ct->lock);
 
                        /* Only repeat if we can actually remove the timer.
                         * Destruction may already be in progress in process
@@ -907,7 +904,7 @@ static int tcp_packet(struct nf_conn *ct,
                         * that the client cannot but retransmit its SYN and
                         * thus initiate a clean new session.
                         */
-                       write_unlock_bh(&tcp_lock);
+                       spin_unlock_bh(&ct->lock);
                        if (LOG_INVALID(net, IPPROTO_TCP))
                                nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
                                          "nf_ct_tcp: killing out of sync session ");
@@ -920,7 +917,7 @@ static int tcp_packet(struct nf_conn *ct,
                ct->proto.tcp.last_end =
                    segment_seq_plus_len(ntohl(th->seq), skb->len, dataoff, th);
 
-               write_unlock_bh(&tcp_lock);
+               spin_unlock_bh(&ct->lock);
                if (LOG_INVALID(net, IPPROTO_TCP))
                        nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
                                  "nf_ct_tcp: invalid packet ignored ");
@@ -929,7 +926,7 @@ static int tcp_packet(struct nf_conn *ct,
                /* Invalid packet */
                pr_debug("nf_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
                         dir, get_conntrack_index(th), old_state);
-               write_unlock_bh(&tcp_lock);
+               spin_unlock_bh(&ct->lock);
                if (LOG_INVALID(net, IPPROTO_TCP))
                        nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
                                  "nf_ct_tcp: invalid state ");
@@ -960,7 +957,7 @@ static int tcp_packet(struct nf_conn *ct,
 
        if (!tcp_in_window(ct, &ct->proto.tcp, dir, index,
                           skb, dataoff, th, pf)) {
-               write_unlock_bh(&tcp_lock);
+               spin_unlock_bh(&ct->lock);
                return -NF_ACCEPT;
        }
      in_window:
@@ -989,7 +986,7 @@ static int tcp_packet(struct nf_conn *ct,
                timeout = nf_ct_tcp_timeout_unacknowledged;
        else
                timeout = tcp_timeouts[new_state];
-       write_unlock_bh(&tcp_lock);
+       spin_unlock_bh(&ct->lock);
 
        if (new_state != old_state)
                nf_conntrack_event_cache(IPCT_PROTOINFO, ct);
@@ -1106,12 +1103,12 @@ static bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb,
 #include <linux/netfilter/nfnetlink_conntrack.h>
 
 static int tcp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
-                        const struct nf_conn *ct)
+                        struct nf_conn *ct)
 {
        struct nlattr *nest_parms;
        struct nf_ct_tcp_flags tmp = {};
 
-       read_lock_bh(&tcp_lock);
+       spin_lock_bh(&ct->lock);
        nest_parms = nla_nest_start(skb, CTA_PROTOINFO_TCP | NLA_F_NESTED);
        if (!nest_parms)
                goto nla_put_failure;
@@ -1131,14 +1128,14 @@ static int tcp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
        tmp.flags = ct->proto.tcp.seen[1].flags;
        NLA_PUT(skb, CTA_PROTOINFO_TCP_FLAGS_REPLY,
                sizeof(struct nf_ct_tcp_flags), &tmp);
-       read_unlock_bh(&tcp_lock);
+       spin_unlock_bh(&ct->lock);
 
        nla_nest_end(skb, nest_parms);
 
        return 0;
 
 nla_put_failure:
-       read_unlock_bh(&tcp_lock);
+       spin_unlock_bh(&ct->lock);
        return -1;
 }
 
@@ -1169,7 +1166,7 @@ static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct)
            nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]) >= TCP_CONNTRACK_MAX)
                return -EINVAL;
 
-       write_lock_bh(&tcp_lock);
+       spin_lock_bh(&ct->lock);
        if (tb[CTA_PROTOINFO_TCP_STATE])
                ct->proto.tcp.state = nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]);
 
@@ -1196,7 +1193,7 @@ static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct)
                ct->proto.tcp.seen[1].td_scale =
                        nla_get_u8(tb[CTA_PROTOINFO_TCP_WSCALE_REPLY]);
        }
-       write_unlock_bh(&tcp_lock);
+       spin_unlock_bh(&ct->lock);
 
        return 0;
 }