ipv6: unify fragment thresh handling code
Cc: Herbert Xu <herbert@gondor.apana.org.au> Cc: Michal Kubeček <mkubecek@suse.cz> Cc: David Miller <davem@davemloft.net> Signed-off-by: Cong Wang <amwang@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
d4915c087f
commit
6b102865e7
|
@ -61,7 +61,7 @@ void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f);
|
||||||
void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f);
|
void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f);
|
||||||
void inet_frag_destroy(struct inet_frag_queue *q,
|
void inet_frag_destroy(struct inet_frag_queue *q,
|
||||||
struct inet_frags *f, int *work);
|
struct inet_frags *f, int *work);
|
||||||
int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f);
|
int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f, bool force);
|
||||||
struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
|
struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
|
||||||
struct inet_frags *f, void *key, unsigned int hash)
|
struct inet_frags *f, void *key, unsigned int hash)
|
||||||
__releases(&f->lock);
|
__releases(&f->lock);
|
||||||
|
|
|
@ -89,7 +89,7 @@ void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f)
|
||||||
nf->low_thresh = 0;
|
nf->low_thresh = 0;
|
||||||
|
|
||||||
local_bh_disable();
|
local_bh_disable();
|
||||||
inet_frag_evictor(nf, f);
|
inet_frag_evictor(nf, f, true);
|
||||||
local_bh_enable();
|
local_bh_enable();
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(inet_frags_exit_net);
|
EXPORT_SYMBOL(inet_frags_exit_net);
|
||||||
|
@ -158,11 +158,16 @@ void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(inet_frag_destroy);
|
EXPORT_SYMBOL(inet_frag_destroy);
|
||||||
|
|
||||||
int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f)
|
int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f, bool force)
|
||||||
{
|
{
|
||||||
struct inet_frag_queue *q;
|
struct inet_frag_queue *q;
|
||||||
int work, evicted = 0;
|
int work, evicted = 0;
|
||||||
|
|
||||||
|
if (!force) {
|
||||||
|
if (atomic_read(&nf->mem) <= nf->high_thresh)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
work = atomic_read(&nf->mem) - nf->low_thresh;
|
work = atomic_read(&nf->mem) - nf->low_thresh;
|
||||||
while (work > 0) {
|
while (work > 0) {
|
||||||
read_lock(&f->lock);
|
read_lock(&f->lock);
|
||||||
|
|
|
@ -219,7 +219,7 @@ static void ip_evictor(struct net *net)
|
||||||
{
|
{
|
||||||
int evicted;
|
int evicted;
|
||||||
|
|
||||||
evicted = inet_frag_evictor(&net->ipv4.frags, &ip4_frags);
|
evicted = inet_frag_evictor(&net->ipv4.frags, &ip4_frags, false);
|
||||||
if (evicted)
|
if (evicted)
|
||||||
IP_ADD_STATS_BH(net, IPSTATS_MIB_REASMFAILS, evicted);
|
IP_ADD_STATS_BH(net, IPSTATS_MIB_REASMFAILS, evicted);
|
||||||
}
|
}
|
||||||
|
@ -684,8 +684,7 @@ int ip_defrag(struct sk_buff *skb, u32 user)
|
||||||
IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS);
|
IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS);
|
||||||
|
|
||||||
/* Start by cleaning up the memory. */
|
/* Start by cleaning up the memory. */
|
||||||
if (atomic_read(&net->ipv4.frags.mem) > net->ipv4.frags.high_thresh)
|
ip_evictor(net);
|
||||||
ip_evictor(net);
|
|
||||||
|
|
||||||
/* Lookup (or create) queue header */
|
/* Lookup (or create) queue header */
|
||||||
if ((qp = ip_find(net, ip_hdr(skb), user)) != NULL) {
|
if ((qp = ip_find(net, ip_hdr(skb), user)) != NULL) {
|
||||||
|
|
|
@ -566,11 +566,9 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user)
|
||||||
hdr = ipv6_hdr(clone);
|
hdr = ipv6_hdr(clone);
|
||||||
fhdr = (struct frag_hdr *)skb_transport_header(clone);
|
fhdr = (struct frag_hdr *)skb_transport_header(clone);
|
||||||
|
|
||||||
if (atomic_read(&net->nf_frag.frags.mem) > net->nf_frag.frags.high_thresh) {
|
local_bh_disable();
|
||||||
local_bh_disable();
|
inet_frag_evictor(&net->nf_frag.frags, &nf_frags, false);
|
||||||
inet_frag_evictor(&net->nf_frag.frags, &nf_frags);
|
local_bh_enable();
|
||||||
local_bh_enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
fq = fq_find(net, fhdr->identification, user, &hdr->saddr, &hdr->daddr);
|
fq = fq_find(net, fhdr->identification, user, &hdr->saddr, &hdr->daddr);
|
||||||
if (fq == NULL) {
|
if (fq == NULL) {
|
||||||
|
|
|
@ -131,15 +131,6 @@ void ip6_frag_init(struct inet_frag_queue *q, void *a)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ip6_frag_init);
|
EXPORT_SYMBOL(ip6_frag_init);
|
||||||
|
|
||||||
static void ip6_evictor(struct net *net, struct inet6_dev *idev)
|
|
||||||
{
|
|
||||||
int evicted;
|
|
||||||
|
|
||||||
evicted = inet_frag_evictor(&net->ipv6.frags, &ip6_frags);
|
|
||||||
if (evicted)
|
|
||||||
IP6_ADD_STATS_BH(net, idev, IPSTATS_MIB_REASMFAILS, evicted);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ip6_expire_frag_queue(struct net *net, struct frag_queue *fq,
|
void ip6_expire_frag_queue(struct net *net, struct frag_queue *fq,
|
||||||
struct inet_frags *frags)
|
struct inet_frags *frags)
|
||||||
{
|
{
|
||||||
|
@ -515,6 +506,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
|
||||||
struct frag_queue *fq;
|
struct frag_queue *fq;
|
||||||
const struct ipv6hdr *hdr = ipv6_hdr(skb);
|
const struct ipv6hdr *hdr = ipv6_hdr(skb);
|
||||||
struct net *net = dev_net(skb_dst(skb)->dev);
|
struct net *net = dev_net(skb_dst(skb)->dev);
|
||||||
|
int evicted;
|
||||||
|
|
||||||
IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMREQDS);
|
IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMREQDS);
|
||||||
|
|
||||||
|
@ -539,8 +531,10 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atomic_read(&net->ipv6.frags.mem) > net->ipv6.frags.high_thresh)
|
evicted = inet_frag_evictor(&net->ipv6.frags, &ip6_frags, false);
|
||||||
ip6_evictor(net, ip6_dst_idev(skb_dst(skb)));
|
if (evicted)
|
||||||
|
IP6_ADD_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
|
||||||
|
IPSTATS_MIB_REASMFAILS, evicted);
|
||||||
|
|
||||||
fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr);
|
fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr);
|
||||||
if (fq != NULL) {
|
if (fq != NULL) {
|
||||||
|
|
Reference in New Issue