aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/inet_frag.h2
-rw-r--r--net/ipv4/inet_fragment.c9
-rw-r--r--net/ipv4/ip_fragment.c5
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c8
-rw-r--r--net/ipv6/reassembly.c16
5 files changed, 18 insertions, 22 deletions
diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h
index 5098ee7b7e0e..32786a044718 100644
--- a/include/net/inet_frag.h
+++ b/include/net/inet_frag.h
@@ -61,7 +61,7 @@ void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f);
61void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f); 61void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f);
62void inet_frag_destroy(struct inet_frag_queue *q, 62void inet_frag_destroy(struct inet_frag_queue *q,
63 struct inet_frags *f, int *work); 63 struct inet_frags *f, int *work);
64int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f); 64int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f, bool force);
65struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, 65struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
66 struct inet_frags *f, void *key, unsigned int hash) 66 struct inet_frags *f, void *key, unsigned int hash)
67 __releases(&f->lock); 67 __releases(&f->lock);
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
index 85190e69297b..4750d2b74d79 100644
--- a/net/ipv4/inet_fragment.c
+++ b/net/ipv4/inet_fragment.c
@@ -89,7 +89,7 @@ void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f)
89 nf->low_thresh = 0; 89 nf->low_thresh = 0;
90 90
91 local_bh_disable(); 91 local_bh_disable();
92 inet_frag_evictor(nf, f); 92 inet_frag_evictor(nf, f, true);
93 local_bh_enable(); 93 local_bh_enable();
94} 94}
95EXPORT_SYMBOL(inet_frags_exit_net); 95EXPORT_SYMBOL(inet_frags_exit_net);
@@ -158,11 +158,16 @@ void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f,
158} 158}
159EXPORT_SYMBOL(inet_frag_destroy); 159EXPORT_SYMBOL(inet_frag_destroy);
160 160
161int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f) 161int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f, bool force)
162{ 162{
163 struct inet_frag_queue *q; 163 struct inet_frag_queue *q;
164 int work, evicted = 0; 164 int work, evicted = 0;
165 165
166 if (!force) {
167 if (atomic_read(&nf->mem) <= nf->high_thresh)
168 return 0;
169 }
170
166 work = atomic_read(&nf->mem) - nf->low_thresh; 171 work = atomic_read(&nf->mem) - nf->low_thresh;
167 while (work > 0) { 172 while (work > 0) {
168 read_lock(&f->lock); 173 read_lock(&f->lock);
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index fa6a12c51066..448e68546827 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -219,7 +219,7 @@ static void ip_evictor(struct net *net)
219{ 219{
220 int evicted; 220 int evicted;
221 221
222 evicted = inet_frag_evictor(&net->ipv4.frags, &ip4_frags); 222 evicted = inet_frag_evictor(&net->ipv4.frags, &ip4_frags, false);
223 if (evicted) 223 if (evicted)
224 IP_ADD_STATS_BH(net, IPSTATS_MIB_REASMFAILS, evicted); 224 IP_ADD_STATS_BH(net, IPSTATS_MIB_REASMFAILS, evicted);
225} 225}
@@ -684,8 +684,7 @@ int ip_defrag(struct sk_buff *skb, u32 user)
684 IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS); 684 IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS);
685 685
686 /* Start by cleaning up the memory. */ 686 /* Start by cleaning up the memory. */
687 if (atomic_read(&net->ipv4.frags.mem) > net->ipv4.frags.high_thresh) 687 ip_evictor(net);
688 ip_evictor(net);
689 688
690 /* Lookup (or create) queue header */ 689 /* Lookup (or create) queue header */
691 if ((qp = ip_find(net, ip_hdr(skb), user)) != NULL) { 690 if ((qp = ip_find(net, ip_hdr(skb), user)) != NULL) {
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 54274c33a0b1..1af12fde08df 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -566,11 +566,9 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user)
566 hdr = ipv6_hdr(clone); 566 hdr = ipv6_hdr(clone);
567 fhdr = (struct frag_hdr *)skb_transport_header(clone); 567 fhdr = (struct frag_hdr *)skb_transport_header(clone);
568 568
569 if (atomic_read(&net->nf_frag.frags.mem) > net->nf_frag.frags.high_thresh) { 569 local_bh_disable();
570 local_bh_disable(); 570 inet_frag_evictor(&net->nf_frag.frags, &nf_frags, false);
571 inet_frag_evictor(&net->nf_frag.frags, &nf_frags); 571 local_bh_enable();
572 local_bh_enable();
573 }
574 572
575 fq = fq_find(net, fhdr->identification, user, &hdr->saddr, &hdr->daddr); 573 fq = fq_find(net, fhdr->identification, user, &hdr->saddr, &hdr->daddr);
576 if (fq == NULL) { 574 if (fq == NULL) {
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index cf74f4e79356..da8a4e301b1b 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -131,15 +131,6 @@ void ip6_frag_init(struct inet_frag_queue *q, void *a)
131} 131}
132EXPORT_SYMBOL(ip6_frag_init); 132EXPORT_SYMBOL(ip6_frag_init);
133 133
134static void ip6_evictor(struct net *net, struct inet6_dev *idev)
135{
136 int evicted;
137
138 evicted = inet_frag_evictor(&net->ipv6.frags, &ip6_frags);
139 if (evicted)
140 IP6_ADD_STATS_BH(net, idev, IPSTATS_MIB_REASMFAILS, evicted);
141}
142
143void ip6_expire_frag_queue(struct net *net, struct frag_queue *fq, 134void ip6_expire_frag_queue(struct net *net, struct frag_queue *fq,
144 struct inet_frags *frags) 135 struct inet_frags *frags)
145{ 136{
@@ -515,6 +506,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
515 struct frag_queue *fq; 506 struct frag_queue *fq;
516 const struct ipv6hdr *hdr = ipv6_hdr(skb); 507 const struct ipv6hdr *hdr = ipv6_hdr(skb);
517 struct net *net = dev_net(skb_dst(skb)->dev); 508 struct net *net = dev_net(skb_dst(skb)->dev);
509 int evicted;
518 510
519 IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMREQDS); 511 IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMREQDS);
520 512
@@ -539,8 +531,10 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
539 return 1; 531 return 1;
540 } 532 }
541 533
542 if (atomic_read(&net->ipv6.frags.mem) > net->ipv6.frags.high_thresh) 534 evicted = inet_frag_evictor(&net->ipv6.frags, &ip6_frags, false);
543 ip6_evictor(net, ip6_dst_idev(skb_dst(skb))); 535 if (evicted)
536 IP6_ADD_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
537 IPSTATS_MIB_REASMFAILS, evicted);
544 538
545 fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr); 539 fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr);
546 if (fq != NULL) { 540 if (fq != NULL) {