Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 361484
b: refs/heads/master
c: 5a3da1f
h: refs/heads/master
v: v3
  • Loading branch information
Hannes Frederic Sowa authored and David S. Miller committed Mar 19, 2013
1 parent 3c3938d commit bea5f39
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 17 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 271648b4c610eed540daaf9ff366209825757565
refs/heads/master: 5a3da1fe9561828d0ca7eca664b16ec2b9bf0055
9 changes: 9 additions & 0 deletions trunk/include/net/inet_frag.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ struct inet_frag_queue {

#define INETFRAGS_HASHSZ 64

/* averaged:
* max_depth = default ipfrag_high_thresh / INETFRAGS_HASHSZ /
* rounded up (SKB_TRUELEN(0) + sizeof(struct ipq or
* struct frag_queue))
*/
#define INETFRAGS_MAXDEPTH 128

struct inet_frags {
struct hlist_head hash[INETFRAGS_HASHSZ];
/* This rwlock is a global lock (seperate per IPv4, IPv6 and
Expand Down Expand Up @@ -76,6 +83,8 @@ 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_frags *f, void *key, unsigned int hash)
__releases(&f->lock);
void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q,
const char *prefix);

static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f)
{
Expand Down
20 changes: 19 additions & 1 deletion trunk/net/ipv4/inet_fragment.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <linux/rtnetlink.h>
#include <linux/slab.h>

#include <net/sock.h>
#include <net/inet_frag.h>

static void inet_frag_secret_rebuild(unsigned long dummy)
Expand Down Expand Up @@ -277,16 +278,33 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
__releases(&f->lock)
{
struct inet_frag_queue *q;
int depth = 0;

hlist_for_each_entry(q, &f->hash[hash], list) {
if (q->net == nf && f->match(q, key)) {
atomic_inc(&q->refcnt);
read_unlock(&f->lock);
return q;
}
depth++;
}
read_unlock(&f->lock);

return inet_frag_create(nf, f, key);
if (depth <= INETFRAGS_MAXDEPTH)
return inet_frag_create(nf, f, key);
else
return ERR_PTR(-ENOBUFS);
}
EXPORT_SYMBOL(inet_frag_find);

void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q,
const char *prefix)
{
static const char msg[] = "inet_frag_find: Fragment hash bucket"
" list length grew over limit " __stringify(INETFRAGS_MAXDEPTH)
". Dropping fragment.\n";

if (PTR_ERR(q) == -ENOBUFS)
LIMIT_NETDEBUG(KERN_WARNING "%s%s", prefix, msg);
}
EXPORT_SYMBOL(inet_frag_maybe_warn_overflow);
11 changes: 4 additions & 7 deletions trunk/net/ipv4/ip_fragment.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,14 +292,11 @@ static inline struct ipq *ip_find(struct net *net, struct iphdr *iph, u32 user)
hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol);

q = inet_frag_find(&net->ipv4.frags, &ip4_frags, &arg, hash);
if (q == NULL)
goto out_nomem;

if (IS_ERR_OR_NULL(q)) {
inet_frag_maybe_warn_overflow(q, pr_fmt());
return NULL;
}
return container_of(q, struct ipq, q);

out_nomem:
LIMIT_NETDEBUG(KERN_ERR pr_fmt("ip_frag_create: no memory left !\n"));
return NULL;
}

/* Is the fragment too far ahead to be part of ipq? */
Expand Down
12 changes: 6 additions & 6 deletions trunk/net/ipv6/netfilter/nf_conntrack_reasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
* 2 of the License, or (at your option) any later version.
*/

#define pr_fmt(fmt) "IPv6-nf: " fmt

#include <linux/errno.h>
#include <linux/types.h>
#include <linux/string.h>
Expand Down Expand Up @@ -180,13 +182,11 @@ static inline struct frag_queue *fq_find(struct net *net, __be32 id,

q = inet_frag_find(&net->nf_frag.frags, &nf_frags, &arg, hash);
local_bh_enable();
if (q == NULL)
goto oom;

if (IS_ERR_OR_NULL(q)) {
inet_frag_maybe_warn_overflow(q, pr_fmt());
return NULL;
}
return container_of(q, struct frag_queue, q);

oom:
return NULL;
}


Expand Down
8 changes: 6 additions & 2 deletions trunk/net/ipv6/reassembly.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
* YOSHIFUJI,H. @USAGI Always remove fragment header to
* calculate ICV correctly.
*/

#define pr_fmt(fmt) "IPv6: " fmt

#include <linux/errno.h>
#include <linux/types.h>
#include <linux/string.h>
Expand Down Expand Up @@ -185,9 +188,10 @@ fq_find(struct net *net, __be32 id, const struct in6_addr *src, const struct in6
hash = inet6_hash_frag(id, src, dst, ip6_frags.rnd);

q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash);
if (q == NULL)
if (IS_ERR_OR_NULL(q)) {
inet_frag_maybe_warn_overflow(q, pr_fmt());
return NULL;

}
return container_of(q, struct frag_queue, q);
}

Expand Down

0 comments on commit bea5f39

Please sign in to comment.