diff options
-rw-r--r-- | include/net/inet_frag.h | 2 | ||||
-rw-r--r-- | net/ipv4/inet_fragment.c | 9 | ||||
-rw-r--r-- | net/ipv4/ip_fragment.c | 5 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_reasm.c | 8 | ||||
-rw-r--r-- | net/ipv6/reassembly.c | 16 |
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); | |||
61 | void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f); | 61 | void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f); |
62 | void inet_frag_destroy(struct inet_frag_queue *q, | 62 | void inet_frag_destroy(struct inet_frag_queue *q, |
63 | struct inet_frags *f, int *work); | 63 | struct inet_frags *f, int *work); |
64 | int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f); | 64 | int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f, bool force); |
65 | struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, | 65 | struct 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 | } |
95 | EXPORT_SYMBOL(inet_frags_exit_net); | 95 | EXPORT_SYMBOL(inet_frags_exit_net); |
@@ -158,11 +158,16 @@ void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f, | |||
158 | } | 158 | } |
159 | EXPORT_SYMBOL(inet_frag_destroy); | 159 | EXPORT_SYMBOL(inet_frag_destroy); |
160 | 160 | ||
161 | int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f) | 161 | int 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 | } |
132 | EXPORT_SYMBOL(ip6_frag_init); | 132 | EXPORT_SYMBOL(ip6_frag_init); |
133 | 133 | ||
134 | static 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 | |||
143 | void ip6_expire_frag_queue(struct net *net, struct frag_queue *fq, | 134 | void 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) { |