Skip to content

Commit 4ecbb1c

Browse files
edumazetkuba-moo
authored andcommitted
net: dropreason: add SKB_DROP_REASON_DUP_FRAG
This is used to track when a duplicate segment received by various reassembly units is dropped. Signed-off-by: Eric Dumazet <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 511a3ed commit 4ecbb1c

File tree

4 files changed

+22
-9
lines changed

4 files changed

+22
-9
lines changed

include/net/dropreason.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
FN(IP_INADDRERRORS) \
6969
FN(IP_INNOROUTES) \
7070
FN(PKT_TOO_BIG) \
71+
FN(DUP_FRAG) \
7172
FNe(MAX)
7273

7374
/**
@@ -300,6 +301,8 @@ enum skb_drop_reason {
300301
* MTU)
301302
*/
302303
SKB_DROP_REASON_PKT_TOO_BIG,
304+
/** @SKB_DROP_REASON_DUP_FRAG: duplicate fragment */
305+
SKB_DROP_REASON_DUP_FRAG,
303306
/**
304307
* @SKB_DROP_REASON_MAX: the maximum of drop reason, which shouldn't be
305308
* used as a real 'reason'

net/ipv4/ip_fragment.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,10 +278,14 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
278278
struct net_device *dev;
279279
unsigned int fragsize;
280280
int err = -ENOENT;
281+
SKB_DR(reason);
281282
u8 ecn;
282283

283-
if (qp->q.flags & INET_FRAG_COMPLETE)
284+
/* If reassembly is already done, @skb must be a duplicate frag. */
285+
if (qp->q.flags & INET_FRAG_COMPLETE) {
286+
SKB_DR_SET(reason, DUP_FRAG);
284287
goto err;
288+
}
285289

286290
if (!(IPCB(skb)->flags & IPSKB_FRAG_COMPLETE) &&
287291
unlikely(ip_frag_too_far(qp)) &&
@@ -382,16 +386,17 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
382386

383387
insert_error:
384388
if (err == IPFRAG_DUP) {
385-
kfree_skb(skb);
386-
return -EINVAL;
389+
SKB_DR_SET(reason, DUP_FRAG);
390+
err = -EINVAL;
391+
goto err;
387392
}
388393
err = -EINVAL;
389394
__IP_INC_STATS(net, IPSTATS_MIB_REASM_OVERLAPS);
390395
discard_qp:
391396
inet_frag_kill(&qp->q);
392397
__IP_INC_STATS(net, IPSTATS_MIB_REASMFAILS);
393398
err:
394-
kfree_skb(skb);
399+
kfree_skb_reason(skb, reason);
395400
return err;
396401
}
397402

net/ipv6/netfilter/nf_conntrack_reasm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ static int nf_ct_frag6_queue(struct frag_queue *fq, struct sk_buff *skb,
253253
if (err) {
254254
if (err == IPFRAG_DUP) {
255255
/* No error for duplicates, pretend they got queued. */
256-
kfree_skb(skb);
256+
kfree_skb_reason(skb, SKB_DROP_REASON_DUP_FRAG);
257257
return -EINPROGRESS;
258258
}
259259
goto insert_error;

net/ipv6/reassembly.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,14 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
112112
struct sk_buff *prev_tail;
113113
struct net_device *dev;
114114
int err = -ENOENT;
115+
SKB_DR(reason);
115116
u8 ecn;
116117

117-
if (fq->q.flags & INET_FRAG_COMPLETE)
118+
/* If reassembly is already done, @skb must be a duplicate frag. */
119+
if (fq->q.flags & INET_FRAG_COMPLETE) {
120+
SKB_DR_SET(reason, DUP_FRAG);
118121
goto err;
122+
}
119123

120124
err = -EINVAL;
121125
offset = ntohs(fhdr->frag_off) & ~0x7;
@@ -226,8 +230,9 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
226230

227231
insert_error:
228232
if (err == IPFRAG_DUP) {
229-
kfree_skb(skb);
230-
return -EINVAL;
233+
SKB_DR_SET(reason, DUP_FRAG);
234+
err = -EINVAL;
235+
goto err;
231236
}
232237
err = -EINVAL;
233238
__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
@@ -237,7 +242,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
237242
__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
238243
IPSTATS_MIB_REASMFAILS);
239244
err:
240-
kfree_skb(skb);
245+
kfree_skb_reason(skb, reason);
241246
return err;
242247
}
243248

0 commit comments

Comments
 (0)