Commit ea8fbe8f authored by Changli Gao's avatar Changli Gao Committed by Patrick McHardy

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: default avatarChangli Gao <xiaosuo@gmail.com>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
parent 39827be2
...@@ -269,6 +269,11 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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;
......
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