vserver 1.9.5.x5
[linux-2.6.git] / net / ipv4 / ip_fragment.c
index df083de..7f68e27 100644 (file)
@@ -73,6 +73,7 @@ struct ipfrag_skb_cb
 struct ipq {
        struct ipq      *next;          /* linked list pointers                 */
        struct list_head lru_list;      /* lru list member                      */
+       u32             user;
        u32             saddr;
        u32             daddr;
        u16             id;
@@ -99,7 +100,7 @@ struct ipq {
 
 /* Per-bucket lock is easy to add now. */
 static struct ipq *ipq_hash[IPQ_HASHSZ];
-static rwlock_t ipfrag_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(ipfrag_lock);
 static u32 ipfrag_hash_rnd;
 static LIST_HEAD(ipq_lru_list);
 int ip_frag_nqueues = 0;
@@ -243,13 +244,13 @@ static void ipq_kill(struct ipq *ipq)
 /* Memory limiting on fragments.  Evictor trashes the oldest 
  * fragment queue until we are back under the threshold.
  */
-static void __ip_evictor(int threshold)
+static void ip_evictor(void)
 {
        struct ipq *qp;
        struct list_head *tmp;
        int work;
 
-       work = atomic_read(&ip_frag_mem) - threshold;
+       work = atomic_read(&ip_frag_mem) - sysctl_ipfrag_low_thresh;
        if (work <= 0)
                return;
 
@@ -274,11 +275,6 @@ static void __ip_evictor(int threshold)
        }
 }
 
-static inline void ip_evictor(void)
-{
-       __ip_evictor(sysctl_ipfrag_low_thresh);
-}
-
 /*
  * Oops, a fragment queue timed out.  Kill it and send an ICMP reply.
  */
@@ -325,7 +321,8 @@ static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in)
                if(qp->id == qp_in->id          &&
                   qp->saddr == qp_in->saddr    &&
                   qp->daddr == qp_in->daddr    &&
-                  qp->protocol == qp_in->protocol) {
+                  qp->protocol == qp_in->protocol &&
+                  qp->user == qp_in->user) {
                        atomic_inc(&qp->refcnt);
                        write_unlock(&ipfrag_lock);
                        qp_in->last_in |= COMPLETE;
@@ -352,7 +349,7 @@ static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in)
 }
 
 /* Add an entry to the 'ipq' queue for a newly received IP datagram. */
-static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph)
+static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user)
 {
        struct ipq *qp;
 
@@ -364,6 +361,7 @@ static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph)
        qp->id = iph->id;
        qp->saddr = iph->saddr;
        qp->daddr = iph->daddr;
+       qp->user = user;
        qp->len = 0;
        qp->meat = 0;
        qp->fragments = NULL;
@@ -373,7 +371,7 @@ static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph)
        init_timer(&qp->timer);
        qp->timer.data = (unsigned long) qp;    /* pointer to queue     */
        qp->timer.function = ip_expire;         /* expire function      */
-       qp->lock = SPIN_LOCK_UNLOCKED;
+       spin_lock_init(&qp->lock);
        atomic_set(&qp->refcnt, 1);
 
        return ip_frag_intern(hash, qp);
@@ -386,7 +384,7 @@ out_nomem:
 /* Find the correct entry in the "incomplete datagrams" queue for
  * this IP datagram, and create new one, if nothing is found.
  */
-static inline struct ipq *ip_find(struct iphdr *iph)
+static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
 {
        __u16 id = iph->id;
        __u32 saddr = iph->saddr;
@@ -400,7 +398,8 @@ static inline struct ipq *ip_find(struct iphdr *iph)
                if(qp->id == id         &&
                   qp->saddr == saddr   &&
                   qp->daddr == daddr   &&
-                  qp->protocol == protocol) {
+                  qp->protocol == protocol &&
+                  qp->user == user) {
                        atomic_inc(&qp->refcnt);
                        read_unlock(&ipfrag_lock);
                        return qp;
@@ -408,7 +407,7 @@ static inline struct ipq *ip_find(struct iphdr *iph)
        }
        read_unlock(&ipfrag_lock);
 
-       return ip_frag_create(hash, iph);
+       return ip_frag_create(hash, iph, user);
 }
 
 /* Add new segment to existing queue. */
@@ -642,7 +641,7 @@ out_fail:
 }
 
 /* Process an incoming IP datagram fragment. */
-struct sk_buff *ip_defrag(struct sk_buff *skb)
+struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user)
 {
        struct iphdr *iph = skb->nh.iph;
        struct ipq *qp;
@@ -657,7 +656,7 @@ struct sk_buff *ip_defrag(struct sk_buff *skb)
        dev = skb->dev;
 
        /* Lookup (or create) queue header */
-       if ((qp = ip_find(iph)) != NULL) {
+       if ((qp = ip_find(iph, user)) != NULL) {
                struct sk_buff *ret = NULL;
 
                spin_lock(&qp->lock);
@@ -689,10 +688,4 @@ void ipfrag_init(void)
        add_timer(&ipfrag_secret_timer);
 }
 
-void ipfrag_flush(void)
-{
-       __ip_evictor(0);
-}
-
 EXPORT_SYMBOL(ip_defrag);
-EXPORT_SYMBOL(ipfrag_flush);