Commit 5a0b77dc authored by Michal Kubecek's avatar Michal Kubecek Committed by Willy Tarreau

net: disable fragment reassembly if high_thresh is set to zero

commit 30759219 upstream.

Before commit 6d7b857d ("net: use lib/percpu_counter API for
fragmentation mem accounting"), setting high threshold to 0 prevented
fragment reassembly as first fragment would be always evicted before
second could be added to the queue. While inefficient, some users
apparently relied on it.

Since the commit mentioned above, a percpu counter is used for
reassembly memory accounting and high batch size avoids taking slow path
in most common scenarios. As a result, a whole full sized packet can be
reassembled without the percpu counter's main counter changing its
value so that even with high_thresh set to 0, fragmented packets can be
still reassembled and processed.

Add explicit checks preventing reassembly if high threshold is zero.

[mk] backport to 3.12
Signed-off-by: default avatarMichal Kubecek <mkubecek@suse.cz>
Signed-off-by: default avatarJiri Slaby <jslaby@suse.cz>
Signed-off-by: default avatarWilly Tarreau <w@1wt.eu>
parent eec89a77
......@@ -656,6 +656,9 @@ int ip_defrag(struct sk_buff *skb, u32 user)
net = skb->dev ? dev_net(skb->dev) : dev_net(skb_dst(skb)->dev);
IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS);
if (!net->ipv4.frags.high_thresh)
goto fail;
/* Start by cleaning up the memory. */
ip_evictor(net);
......@@ -672,6 +675,7 @@ int ip_defrag(struct sk_buff *skb, u32 user)
return ret;
}
fail:
IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS);
kfree_skb(skb);
return -ENOMEM;
......
......@@ -569,6 +569,9 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user)
if (find_prev_fhdr(skb, &prevhdr, &nhoff, &fhoff) < 0)
return skb;
if (!net->nf_frag.frags.high_thresh)
return skb;
clone = skb_clone(skb, GFP_ATOMIC);
if (clone == NULL) {
pr_debug("Can't clone skb\n");
......
......@@ -556,6 +556,9 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
return 1;
}
if (!net->ipv6.frags.high_thresh)
goto fail_mem;
evicted = inet_frag_evictor(&net->ipv6.frags, &ip6_frags, false);
if (evicted)
IP6_ADD_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
......@@ -575,6 +578,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
return ret;
}
fail_mem:
IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMFAILS);
kfree_skb(skb);
return -1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment