1, add new drop reason FRAG_FAILED/FRAG_OUTPUT_FAILED 2, use drop reasons in ip_fragment Signed-off-by: Yonglong Li --- include/net/dropreason-core.h | 6 ++++++ net/ipv4/ip_output.c | 17 ++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/include/net/dropreason-core.h b/include/net/dropreason-core.h index 58d91cc..4ae042e 100644 --- a/include/net/dropreason-core.h +++ b/include/net/dropreason-core.h @@ -99,6 +99,8 @@ FN(DUP_FRAG) \ FN(FRAG_REASM_TIMEOUT) \ FN(FRAG_TOO_FAR) \ + FN(FRAG_FAILED) \ + FN(FRAG_OUTPUT_FAILED) \ FN(TCP_MINTTL) \ FN(IPV6_BAD_EXTHDR) \ FN(IPV6_NDISC_FRAG) \ @@ -500,6 +502,10 @@ enum skb_drop_reason { * (/proc/sys/net/ipv4/ipfrag_max_dist) */ SKB_DROP_REASON_FRAG_TOO_FAR, + /* do ip/ip6 fragment failed */ + SKB_DROP_REASON_FRAG_FAILED, + /* ip/ip6 fragment output failed */ + SKB_DROP_REASON_FRAG_OUTPUT_FAILED, /** * @SKB_DROP_REASON_TCP_MINTTL: ipv4 ttl or ipv6 hoplimit below * the threshold (IP_MINTTL or IPV6_MINHOPCOUNT). diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index ff11d3a..2eab175 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -588,7 +588,7 @@ static int ip_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, IP_INC_STATS(net, IPSTATS_MIB_FRAGFAILS); icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); - kfree_skb(skb); + kfree_skb_reason(skb, SKB_DROP_REASON_PKT_TOO_BIG); return -EMSGSIZE; } @@ -765,6 +765,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, struct sk_buff *skb2; u8 tstamp_type = skb->tstamp_type; struct rtable *rt = skb_rtable(skb); + SKB_DR_INIT(reason, FRAG_FAILED); unsigned int mtu, hlen, ll_rs; struct ip_fraglist_iter iter; ktime_t tstamp = skb->tstamp; @@ -773,8 +774,10 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, /* for offloaded checksums cleanup checksum before fragmentation */ if (skb->ip_summed == CHECKSUM_PARTIAL && - (err = skb_checksum_help(skb))) + (err = skb_checksum_help(skb))) { + SKB_DR_SET(reason, SKB_CSUM); goto fail; + } /* * Point into the IP datagram header. @@ -860,6 +863,8 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, if (!err) IP_INC_STATS(net, IPSTATS_MIB_FRAGCREATES); + else + SKB_DR_SET(reason, FRAG_OUTPUT_FAILED); if (err || !iter.frag) break; @@ -871,7 +876,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, return 0; } - kfree_skb_list(iter.frag); + kfree_skb_list_reason(iter.frag, reason); IP_INC_STATS(net, IPSTATS_MIB_FRAGFAILS); return err; @@ -913,8 +918,10 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, */ skb_set_delivery_time(skb2, tstamp, tstamp_type); err = output(net, sk, skb2); - if (err) + if (err) { + SKB_DR_SET(reason, FRAG_OUTPUT_FAILED); goto fail; + } IP_INC_STATS(net, IPSTATS_MIB_FRAGCREATES); } @@ -923,7 +930,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, return err; fail: - kfree_skb(skb); + kfree_skb_reason(skb, reason); IP_INC_STATS(net, IPSTATS_MIB_FRAGFAILS); return err; } -- 1.8.3.1