]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: vxlan: add skb drop reasons to vxlan_rcv()
authorMenglong Dong <menglong8.dong@gmail.com>
Wed, 9 Oct 2024 02:28:22 +0000 (10:28 +0800)
committerDavid S. Miller <davem@davemloft.net>
Sun, 13 Oct 2024 10:33:08 +0000 (11:33 +0100)
Introduce skb drop reasons to the function vxlan_rcv(). Following new
drop reasons are added:

  SKB_DROP_REASON_VXLAN_INVALID_HDR
  SKB_DROP_REASON_VXLAN_VNI_NOT_FOUND
  SKB_DROP_REASON_IP_TUNNEL_ECN

Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/vxlan/vxlan_core.c
include/net/dropreason-core.h

index 916c3880832e0b11349b62afebc5b75391fe7e95..40111d05d18e487878e80af3aa5ebc4a2ea2609c 100644 (file)
@@ -1671,13 +1671,15 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
        struct vxlan_metadata _md;
        struct vxlan_metadata *md = &_md;
        __be16 protocol = htons(ETH_P_TEB);
+       enum skb_drop_reason reason;
        bool raw_proto = false;
        void *oiph;
        __be32 vni = 0;
        int nh;
 
        /* Need UDP and VXLAN header to be present */
-       if (!pskb_may_pull(skb, VXLAN_HLEN))
+       reason = pskb_may_pull_reason(skb, VXLAN_HLEN);
+       if (reason)
                goto drop;
 
        unparsed = *vxlan_hdr(skb);
@@ -1686,6 +1688,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
                netdev_dbg(skb->dev, "invalid vxlan flags=%#x vni=%#x\n",
                           ntohl(vxlan_hdr(skb)->vx_flags),
                           ntohl(vxlan_hdr(skb)->vx_vni));
+               reason = SKB_DROP_REASON_VXLAN_INVALID_HDR;
                /* Return non vxlan pkt */
                goto drop;
        }
@@ -1699,8 +1702,10 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
        vni = vxlan_vni(vxlan_hdr(skb)->vx_vni);
 
        vxlan = vxlan_vs_find_vni(vs, skb->dev->ifindex, vni, &vninode);
-       if (!vxlan)
+       if (!vxlan) {
+               reason = SKB_DROP_REASON_VXLAN_VNI_NOT_FOUND;
                goto drop;
+       }
 
        /* For backwards compatibility, only allow reserved fields to be
         * used by VXLAN extensions if explicitly requested.
@@ -1713,8 +1718,10 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
        }
 
        if (__iptunnel_pull_header(skb, VXLAN_HLEN, protocol, raw_proto,
-                                  !net_eq(vxlan->net, dev_net(vxlan->dev))))
+                                  !net_eq(vxlan->net, dev_net(vxlan->dev)))) {
+               reason = SKB_DROP_REASON_NOMEM;
                goto drop;
+       }
 
        if (vs->flags & VXLAN_F_REMCSUM_RX)
                if (unlikely(!vxlan_remcsum(&unparsed, skb, vs->flags)))
@@ -1728,8 +1735,10 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
                tun_dst = udp_tun_rx_dst(skb, vxlan_get_sk_family(vs), flags,
                                         key32_to_tunnel_id(vni), sizeof(*md));
 
-               if (!tun_dst)
+               if (!tun_dst) {
+                       reason = SKB_DROP_REASON_NOMEM;
                        goto drop;
+               }
 
                md = ip_tunnel_info_opts(&tun_dst->u.tun_info);
 
@@ -1753,6 +1762,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
                 * is more robust and provides a little more security in
                 * adding extensions to VXLAN.
                 */
+               reason = SKB_DROP_REASON_VXLAN_INVALID_HDR;
                goto drop;
        }
 
@@ -1773,7 +1783,8 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
 
        skb_reset_network_header(skb);
 
-       if (!pskb_inet_may_pull(skb)) {
+       reason = pskb_inet_may_pull_reason(skb);
+       if (reason) {
                DEV_STATS_INC(vxlan->dev, rx_length_errors);
                DEV_STATS_INC(vxlan->dev, rx_errors);
                vxlan_vnifilter_count(vxlan, vni, vninode,
@@ -1785,6 +1796,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
        oiph = skb->head + nh;
 
        if (!vxlan_ecn_decapsulate(vs, oiph, skb)) {
+               reason = SKB_DROP_REASON_IP_TUNNEL_ECN;
                DEV_STATS_INC(vxlan->dev, rx_frame_errors);
                DEV_STATS_INC(vxlan->dev, rx_errors);
                vxlan_vnifilter_count(vxlan, vni, vninode,
@@ -1799,6 +1811,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
                dev_core_stats_rx_dropped_inc(vxlan->dev);
                vxlan_vnifilter_count(vxlan, vni, vninode,
                                      VXLAN_VNI_STATS_RX_DROPS, 0);
+               reason = SKB_DROP_REASON_DEV_READY;
                goto drop;
        }
 
@@ -1811,8 +1824,9 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
        return 0;
 
 drop:
+       reason = reason ?: SKB_DROP_REASON_NOT_SPECIFIED;
        /* Consume bad packet */
-       kfree_skb(skb);
+       kfree_skb_reason(skb, reason);
        return 0;
 }
 
index 4748680e8c88ee1b0089a2217a057865aa9de612..98259d2b3e92604404cc016b07759398841f9eb1 100644 (file)
@@ -92,6 +92,9 @@
        FN(PACKET_SOCK_ERROR)           \
        FN(TC_CHAIN_NOTFOUND)           \
        FN(TC_RECLASSIFY_LOOP)          \
+       FN(VXLAN_INVALID_HDR)           \
+       FN(VXLAN_VNI_NOT_FOUND)         \
+       FN(IP_TUNNEL_ECN)               \
        FNe(MAX)
 
 /**
@@ -418,6 +421,19 @@ enum skb_drop_reason {
         * iterations.
         */
        SKB_DROP_REASON_TC_RECLASSIFY_LOOP,
+       /**
+        * @SKB_DROP_REASON_VXLAN_INVALID_HDR: VXLAN header is invalid. E.g.:
+        * 1) reserved fields are not zero
+        * 2) "I" flag is not set
+        */
+       SKB_DROP_REASON_VXLAN_INVALID_HDR,
+       /** @SKB_DROP_REASON_VXLAN_VNI_NOT_FOUND: no VXLAN device found for VNI */
+       SKB_DROP_REASON_VXLAN_VNI_NOT_FOUND,
+       /**
+        * @SKB_DROP_REASON_IP_TUNNEL_ECN: skb is dropped according to
+        * RFC 6040 4.2, see __INET_ECN_decapsulate() for detail.
+        */
+       SKB_DROP_REASON_IP_TUNNEL_ECN,
        /**
         * @SKB_DROP_REASON_MAX: the maximum of core drop reasons, which
         * shouldn't be used as a real 'reason' - only for tracing code gen