netfilter: nf_conntrack_reasm: add fast path for in-order fragments

As the fragments are sent in order in most of OSes, such as Windows, Darwin and
FreeBSD, it is likely the new fragments are at the end of the inet_frag_queue.
In the fast path, we check if the skb at the end of the inet_frag_queue is the
prev we expect.

Signed-off-by: Changli Gao <xiaosuo@gmail.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
This commit is contained in:
Changli Gao
2010-07-05 10:38:23 +02:00
committed by Patrick McHardy
parent 39827be26b
commit ea8fbe8f19

View File

@@ -269,6 +269,11 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
* in the chain of fragments so far. We must know where to put * in the chain of fragments so far. We must know where to put
* this fragment, right? * this fragment, right?
*/ */
prev = fq->q.fragments_tail;
if (!prev || NFCT_FRAG6_CB(prev)->offset < offset) {
next = NULL;
goto found;
}
prev = NULL; prev = NULL;
for (next = fq->q.fragments; next != NULL; next = next->next) { for (next = fq->q.fragments; next != NULL; next = next->next) {
if (NFCT_FRAG6_CB(next)->offset >= offset) if (NFCT_FRAG6_CB(next)->offset >= offset)
@@ -276,6 +281,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
prev = next; prev = next;
} }
found:
/* We found where to put this one. Check for overlap with /* We found where to put this one. Check for overlap with
* preceding fragment, and, if needed, align things so that * preceding fragment, and, if needed, align things so that
* any overlaps are eliminated. * any overlaps are eliminated.
@@ -341,6 +347,8 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
/* Insert this fragment in the chain of fragments. */ /* Insert this fragment in the chain of fragments. */
skb->next = next; skb->next = next;
if (!next)
fq->q.fragments_tail = skb;
if (prev) if (prev)
prev->next = skb; prev->next = skb;
else else
@@ -464,6 +472,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev)
head->csum); head->csum);
fq->q.fragments = NULL; fq->q.fragments = NULL;
fq->q.fragments_tail = NULL;
/* all original skbs are linked into the NFCT_FRAG6_CB(head).orig */ /* all original skbs are linked into the NFCT_FRAG6_CB(head).orig */
fp = skb_shinfo(head)->frag_list; fp = skb_shinfo(head)->frag_list;