]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
net/tc: introduce TC_ACT_REINSERT.
authorPaolo Abeni <pabeni@redhat.com>
Mon, 30 Jul 2018 12:30:44 +0000 (14:30 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 30 Jul 2018 16:31:14 +0000 (09:31 -0700)
This is similar TC_ACT_REDIRECT, but with a slightly different
semantic:
- on ingress the mirred skbs are passed to the target device
network stack without any additional check not scrubbing.
- the rcu-protected stats provided via the tcf_result struct
  are updated on error conditions.

This new tcfa_action value is not exposed to the user-space
and can be used only internally by clsact.

v1 -> v2: do not touch TC_ACT_REDIRECT code path, introduce
 a new action type instead
v2 -> v3:
 - rename the new action value TC_ACT_REINJECT, update the
   helper accordingly
 - take care of uncloned reinjected packets in XDP generic
   hook
v3 -> v4:
 - renamed again the new action value (JiriP)
v4 -> v5:
 - fix build error with !NET_CLS_ACT (kbuild bot)

Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/pkt_cls.h
include/net/sch_generic.h
net/core/dev.c

index 6d02f31abba86cf407d1f0b41acf8b09f0cd2f6d..22bfc3a13c254f704c5d305ee05fec61737804e5 100644 (file)
@@ -7,6 +7,9 @@
 #include <net/sch_generic.h>
 #include <net/act_api.h>
 
+/* TC action not accessible from user space */
+#define TC_ACT_REINSERT                (TC_ACT_VALUE_MAX + 1)
+
 /* Basic packet classifier frontend definitions. */
 
 struct tcf_walker {
index bcae181c1857d4b456adbda97ee13d2052dcc726..a6d00093f35e70d9b5da920be22ae4fd1db0bb6a 100644 (file)
@@ -235,6 +235,12 @@ struct tcf_result {
                        u32             classid;
                };
                const struct tcf_proto *goto_tp;
+
+               /* used by the TC_ACT_REINSERT action */
+               struct {
+                       bool            ingress;
+                       struct gnet_stats_queue *qstats;
+               };
        };
 };
 
@@ -569,6 +575,15 @@ static inline void skb_reset_tc(struct sk_buff *skb)
 #endif
 }
 
+static inline bool skb_is_tc_redirected(const struct sk_buff *skb)
+{
+#ifdef CONFIG_NET_CLS_ACT
+       return skb->tc_redirected;
+#else
+       return false;
+#endif
+}
+
 static inline bool skb_at_tc_ingress(const struct sk_buff *skb)
 {
 #ifdef CONFIG_NET_CLS_ACT
@@ -1108,4 +1123,17 @@ void mini_qdisc_pair_swap(struct mini_Qdisc_pair *miniqp,
 void mini_qdisc_pair_init(struct mini_Qdisc_pair *miniqp, struct Qdisc *qdisc,
                          struct mini_Qdisc __rcu **p_miniq);
 
+static inline void skb_tc_reinsert(struct sk_buff *skb, struct tcf_result *res)
+{
+       struct gnet_stats_queue *stats = res->qstats;
+       int ret;
+
+       if (res->ingress)
+               ret = netif_receive_skb(skb);
+       else
+               ret = dev_queue_xmit(skb);
+       if (ret && stats)
+               qstats_overlimit_inc(res->qstats);
+}
+
 #endif
index 89031b5fef9f720a99ac25cec8010894a5e76d88..38b0c414d780697dc8ce57547146248a442d4aea 100644 (file)
@@ -4252,7 +4252,7 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb,
        /* Reinjected packets coming from act_mirred or similar should
         * not get XDP generic processing.
         */
-       if (skb_cloned(skb))
+       if (skb_cloned(skb) || skb_is_tc_redirected(skb))
                return XDP_PASS;
 
        /* XDP packets must be linear and must have sufficient headroom
@@ -4602,6 +4602,10 @@ sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret,
                __skb_push(skb, skb->mac_len);
                skb_do_redirect(skb);
                return NULL;
+       case TC_ACT_REINSERT:
+               /* this does not scrub the packet, and updates stats on error */
+               skb_tc_reinsert(skb, &cl_res);
+               return NULL;
        default:
                break;
        }