net/sched: act_pedit: Add size check for TCA_PEDIT_PARMS_EX
[platform/kernel/linux-starfive.git] / net / sched / act_mirred.c
index b8ad6ae..36395e5 100644 (file)
@@ -28,8 +28,8 @@
 static LIST_HEAD(mirred_list);
 static DEFINE_SPINLOCK(mirred_list_lock);
 
-#define MIRRED_RECURSION_LIMIT    4
-static DEFINE_PER_CPU(unsigned int, mirred_rec_level);
+#define MIRRED_NEST_LIMIT    4
+static DEFINE_PER_CPU(unsigned int, mirred_nest_level);
 
 static bool tcf_mirred_is_act_redirect(int action)
 {
@@ -205,12 +205,19 @@ release_idr:
        return err;
 }
 
+static bool is_mirred_nested(void)
+{
+       return unlikely(__this_cpu_read(mirred_nest_level) > 1);
+}
+
 static int tcf_mirred_forward(bool want_ingress, struct sk_buff *skb)
 {
        int err;
 
        if (!want_ingress)
                err = tcf_dev_queue_xmit(skb, dev_queue_xmit);
+       else if (is_mirred_nested())
+               err = netif_rx(skb);
        else
                err = netif_receive_skb(skb);
 
@@ -224,7 +231,7 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a,
        struct sk_buff *skb2 = skb;
        bool m_mac_header_xmit;
        struct net_device *dev;
-       unsigned int rec_level;
+       unsigned int nest_level;
        int retval, err = 0;
        bool use_reinsert;
        bool want_ingress;
@@ -235,11 +242,11 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a,
        int mac_len;
        bool at_nh;
 
-       rec_level = __this_cpu_inc_return(mirred_rec_level);
-       if (unlikely(rec_level > MIRRED_RECURSION_LIMIT)) {
+       nest_level = __this_cpu_inc_return(mirred_nest_level);
+       if (unlikely(nest_level > MIRRED_NEST_LIMIT)) {
                net_warn_ratelimited("Packet exceeded mirred recursion limit on dev %s\n",
                                     netdev_name(skb->dev));
-               __this_cpu_dec(mirred_rec_level);
+               __this_cpu_dec(mirred_nest_level);
                return TC_ACT_SHOT;
        }
 
@@ -255,7 +262,7 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a,
                goto out;
        }
 
-       if (unlikely(!(dev->flags & IFF_UP))) {
+       if (unlikely(!(dev->flags & IFF_UP)) || !netif_carrier_ok(dev)) {
                net_notice_ratelimited("tc mirred to Houston: device %s is down\n",
                                       dev->name);
                goto out;
@@ -308,7 +315,7 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a,
                        err = tcf_mirred_forward(want_ingress, skb);
                        if (err)
                                tcf_action_inc_overlimit_qstats(&m->common);
-                       __this_cpu_dec(mirred_rec_level);
+                       __this_cpu_dec(mirred_nest_level);
                        return TC_ACT_CONSUMED;
                }
        }
@@ -320,7 +327,7 @@ out:
                if (tcf_mirred_is_act_redirect(m_eaction))
                        retval = TC_ACT_SHOT;
        }
-       __this_cpu_dec(mirred_rec_level);
+       __this_cpu_dec(mirred_nest_level);
 
        return retval;
 }