Skip to content

Commit

Permalink
Merge branch 'ip-Use-rb-trees-for-IP-frag-queue'
Browse files Browse the repository at this point in the history
Peter Oskolkov says:

====================
ip: Use rb trees for IP frag queue.

This patchset
 * changes IPv4 defrag behavior to match that of IPv6: overlapping
   fragments now cause the whole IP datagram to be discarded (suggested
   by David Miller): there are no legitimate use cases for overlapping
   fragments;
 * changes IPv4 defrag queue from a list to a rb tree (suggested
   by Eric Dumazet): this change removes a potential attach vector.

Upcoming patches will contain similar changes for IPv6 frag queue,
as well as a comprehensive IP defrag self-test (temporarily delayed).
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Aug 6, 2018
2 parents cfb4099 + fa0f527 commit c30f1fc
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 140 deletions.
11 changes: 7 additions & 4 deletions include/linux/skbuff.h
Original file line number Diff line number Diff line change
Expand Up @@ -676,13 +676,16 @@ struct sk_buff {
* UDP receive path is one user.
*/
unsigned long dev_scratch;
int ip_defrag_offset;
};
};
struct rb_node rbnode; /* used in netem & tcp stack */
struct rb_node rbnode; /* used in netem, ip4 defrag, and tcp stack */
struct list_head list;
};
struct sock *sk;

union {
struct sock *sk;
int ip_defrag_offset;
};

union {
ktime_t tstamp;
Expand Down Expand Up @@ -2585,7 +2588,7 @@ static inline void __skb_queue_purge(struct sk_buff_head *list)
kfree_skb(skb);
}

void skb_rbtree_purge(struct rb_root *root);
unsigned int skb_rbtree_purge(struct rb_root *root);

void *netdev_alloc_frag(unsigned int fragsz);

Expand Down
3 changes: 2 additions & 1 deletion include/net/inet_frag.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ struct inet_frag_queue {
struct timer_list timer;
spinlock_t lock;
refcount_t refcnt;
struct sk_buff *fragments;
struct sk_buff *fragments; /* Used in IPv6. */
struct rb_root rb_fragments; /* Used in IPv4. */
struct sk_buff *fragments_tail;
ktime_t stamp;
int len;
Expand Down
1 change: 1 addition & 0 deletions include/uapi/linux/snmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ enum
IPSTATS_MIB_ECT1PKTS, /* InECT1Pkts */
IPSTATS_MIB_ECT0PKTS, /* InECT0Pkts */
IPSTATS_MIB_CEPKTS, /* InCEPkts */
IPSTATS_MIB_REASM_OVERLAPS, /* ReasmOverlaps */
__IPSTATS_MIB_MAX
};

Expand Down
6 changes: 5 additions & 1 deletion net/core/skbuff.c
Original file line number Diff line number Diff line change
Expand Up @@ -2858,23 +2858,27 @@ EXPORT_SYMBOL(skb_queue_purge);
/**
* skb_rbtree_purge - empty a skb rbtree
* @root: root of the rbtree to empty
* Return value: the sum of truesizes of all purged skbs.
*
* Delete all buffers on an &sk_buff rbtree. Each buffer is removed from
* the list and one reference dropped. This function does not take
* any lock. Synchronization should be handled by the caller (e.g., TCP
* out-of-order queue is protected by the socket lock).
*/
void skb_rbtree_purge(struct rb_root *root)
unsigned int skb_rbtree_purge(struct rb_root *root)
{
struct rb_node *p = rb_first(root);
unsigned int sum = 0;

while (p) {
struct sk_buff *skb = rb_entry(p, struct sk_buff, rbnode);

p = rb_next(p);
rb_erase(&skb->rbnode, root);
sum += skb->truesize;
kfree_skb(skb);
}
return sum;
}

/**
Expand Down
16 changes: 10 additions & 6 deletions net/ipv4/inet_fragment.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,16 @@ void inet_frag_destroy(struct inet_frag_queue *q)
fp = q->fragments;
nf = q->net;
f = nf->f;
while (fp) {
struct sk_buff *xp = fp->next;

sum_truesize += fp->truesize;
kfree_skb(fp);
fp = xp;
if (fp) {
do {
struct sk_buff *xp = fp->next;

sum_truesize += fp->truesize;
kfree_skb(fp);
fp = xp;
} while (fp);
} else {
sum_truesize = skb_rbtree_purge(&q->rb_fragments);
}
sum = sum_truesize + f->qsize;

Expand Down
Loading

0 comments on commit c30f1fc

Please sign in to comment.