--- /dev/null
+From 2c64605b590edadb3fb46d1ec6badb49e940b479 Mon Sep 17 00:00:00 2001
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+Date: Wed, 25 Mar 2020 13:47:18 +0100
+Subject: net: Fix CONFIG_NET_CLS_ACT=n and CONFIG_NFT_FWD_NETDEV={y, m} build
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+commit 2c64605b590edadb3fb46d1ec6badb49e940b479 upstream.
+
+net/netfilter/nft_fwd_netdev.c: In function ‘nft_fwd_netdev_eval’:
+ net/netfilter/nft_fwd_netdev.c:32:10: error: ‘struct sk_buff’ has no member named ‘tc_redirected’
+ pkt->skb->tc_redirected = 1;
+ ^~
+ net/netfilter/nft_fwd_netdev.c:33:10: error: ‘struct sk_buff’ has no member named ‘tc_from_ingress’
+ pkt->skb->tc_from_ingress = 1;
+ ^~
+
+To avoid a direct dependency with tc actions from netfilter, wrap the
+redirect bits around CONFIG_NET_REDIRECT and move helpers to
+include/linux/skbuff.h. Turn on this toggle from the ifb driver, the
+only existing client of these bits in the tree.
+
+This patch adds skb_set_redirected() that sets on the redirected bit
+on the skbuff, it specifies if the packet was redirect from ingress
+and resets the timestamp (timestamp reset was originally missing in the
+netfilter bugfix).
+
+Fixes: bcfabee1afd99484 ("netfilter: nft_fwd_netdev: allow to redirect to ifb via ingress")
+Reported-by: noreply@ellerman.id.au
+Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/Kconfig | 1 +
+ drivers/net/ifb.c | 6 +++---
+ include/linux/skbuff.h | 36 ++++++++++++++++++++++++++++++++----
+ include/net/sch_generic.h | 16 ----------------
+ net/Kconfig | 3 +++
+ net/core/dev.c | 4 ++--
+ net/core/pktgen.c | 2 +-
+ net/netfilter/nft_fwd_netdev.c | 5 ++---
+ net/sched/act_mirred.c | 3 +--
+ 9 files changed, 45 insertions(+), 31 deletions(-)
+
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -105,6 +105,7 @@ config NET_FC
+ config IFB
+ tristate "Intermediate Functional Block support"
+ depends on NET_CLS_ACT
++ select NET_REDIRECT
+ ---help---
+ This is an intermediate driver that allows sharing of
+ resources.
+--- a/drivers/net/ifb.c
++++ b/drivers/net/ifb.c
+@@ -78,7 +78,7 @@ static void ifb_ri_tasklet(unsigned long
+ }
+
+ while ((skb = __skb_dequeue(&txp->tq)) != NULL) {
+- skb->tc_redirected = 0;
++ skb->redirected = 0;
+ skb->tc_skip_classify = 1;
+
+ u64_stats_update_begin(&txp->tsync);
+@@ -99,7 +99,7 @@ static void ifb_ri_tasklet(unsigned long
+ rcu_read_unlock();
+ skb->skb_iif = txp->dev->ifindex;
+
+- if (!skb->tc_from_ingress) {
++ if (!skb->from_ingress) {
+ dev_queue_xmit(skb);
+ } else {
+ skb_pull_rcsum(skb, skb->mac_len);
+@@ -246,7 +246,7 @@ static netdev_tx_t ifb_xmit(struct sk_bu
+ txp->rx_bytes += skb->len;
+ u64_stats_update_end(&txp->rsync);
+
+- if (!skb->tc_redirected || !skb->skb_iif) {
++ if (!skb->redirected || !skb->skb_iif) {
+ dev_kfree_skb(skb);
+ dev->stats.rx_dropped++;
+ return NETDEV_TX_OK;
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -615,8 +615,8 @@ typedef unsigned char *sk_buff_data_t;
+ * @ipvs_property: skbuff is owned by ipvs
+ * @tc_skip_classify: do not classify packet. set by IFB device
+ * @tc_at_ingress: used within tc_classify to distinguish in/egress
+- * @tc_redirected: packet was redirected by a tc action
+- * @tc_from_ingress: if tc_redirected, tc_at_ingress at time of redirect
++ * @redirected: packet was redirected by packet classifier
++ * @from_ingress: packet was redirected from the ingress path
+ * @peeked: this packet has been seen already, so stats have been
+ * done for it, don't do them again
+ * @nf_trace: netfilter packet trace flag
+@@ -793,8 +793,10 @@ struct sk_buff {
+ #ifdef CONFIG_NET_CLS_ACT
+ __u8 tc_skip_classify:1;
+ __u8 tc_at_ingress:1;
+- __u8 tc_redirected:1;
+- __u8 tc_from_ingress:1;
++#endif
++#ifdef CONFIG_NET_REDIRECT
++ __u8 redirected:1;
++ __u8 from_ingress:1;
+ #endif
+ #ifdef CONFIG_TLS_DEVICE
+ __u8 decrypted:1;
+@@ -4220,5 +4222,31 @@ static inline __wsum lco_csum(struct sk_
+ return csum_partial(l4_hdr, csum_start - l4_hdr, partial);
+ }
+
++static inline bool skb_is_redirected(const struct sk_buff *skb)
++{
++#ifdef CONFIG_NET_REDIRECT
++ return skb->redirected;
++#else
++ return false;
++#endif
++}
++
++static inline void skb_set_redirected(struct sk_buff *skb, bool from_ingress)
++{
++#ifdef CONFIG_NET_REDIRECT
++ skb->redirected = 1;
++ skb->from_ingress = from_ingress;
++ if (skb->from_ingress)
++ skb->tstamp = 0;
++#endif
++}
++
++static inline void skb_reset_redirect(struct sk_buff *skb)
++{
++#ifdef CONFIG_NET_REDIRECT
++ skb->redirected = 0;
++#endif
++}
++
+ #endif /* __KERNEL__ */
+ #endif /* _LINUX_SKBUFF_H */
+--- a/include/net/sch_generic.h
++++ b/include/net/sch_generic.h
+@@ -569,22 +569,6 @@ void __qdisc_calculate_pkt_len(struct sk
+ const struct qdisc_size_table *stab);
+ int skb_do_redirect(struct sk_buff *);
+
+-static inline void skb_reset_tc(struct sk_buff *skb)
+-{
+-#ifdef CONFIG_NET_CLS_ACT
+- skb->tc_redirected = 0;
+-#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
+--- a/net/Kconfig
++++ b/net/Kconfig
+@@ -51,6 +51,9 @@ config NET_INGRESS
+ config NET_EGRESS
+ bool
+
++config NET_REDIRECT
++ bool
++
+ menu "Networking options"
+
+ source "net/packet/Kconfig"
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -4306,7 +4306,7 @@ static u32 netif_receive_generic_xdp(str
+ /* Reinjected packets coming from act_mirred or similar should
+ * not get XDP generic processing.
+ */
+- if (skb_is_tc_redirected(skb))
++ if (skb_is_redirected(skb))
+ return XDP_PASS;
+
+ /* XDP packets must be linear and must have sufficient headroom
+@@ -4851,7 +4851,7 @@ skip_taps:
+ goto out;
+ }
+ #endif
+- skb_reset_tc(skb);
++ skb_reset_redirect(skb);
+ skip_classify:
+ if (pfmemalloc && !skb_pfmemalloc_protocol(skb))
+ goto drop;
+--- a/net/core/pktgen.c
++++ b/net/core/pktgen.c
+@@ -3368,7 +3368,7 @@ static void pktgen_xmit(struct pktgen_de
+ /* skb was 'freed' by stack, so clean few
+ * bits and reuse it
+ */
+- skb_reset_tc(skb);
++ skb_reset_redirect(skb);
+ } while (--burst > 0);
+ goto out; /* Skips xmit_mode M_START_XMIT */
+ } else if (pkt_dev->xmit_mode == M_QUEUE_XMIT) {
+--- a/net/netfilter/nft_fwd_netdev.c
++++ b/net/netfilter/nft_fwd_netdev.c
+@@ -30,9 +30,8 @@ static void nft_fwd_netdev_eval(const st
+ struct nft_fwd_netdev *priv = nft_expr_priv(expr);
+ int oif = regs->data[priv->sreg_dev];
+
+- /* These are used by ifb only. */
+- pkt->skb->tc_redirected = 1;
+- pkt->skb->tc_from_ingress = 1;
++ /* This is used by ifb only. */
++ skb_set_redirected(pkt->skb, true);
+
+ nf_fwd_netdev_egress(pkt, oif);
+ regs->verdict.code = NF_STOLEN;
+--- a/net/sched/act_mirred.c
++++ b/net/sched/act_mirred.c
+@@ -260,8 +260,7 @@ static int tcf_mirred_act(struct sk_buff
+
+ /* mirror is always swallowed */
+ if (is_redirect) {
+- skb2->tc_redirected = 1;
+- skb2->tc_from_ingress = skb2->tc_at_ingress;
++ skb_set_redirected(skb2, skb2->tc_at_ingress);
+
+ /* let's the caller reinsert the packet, if possible */
+ if (use_reinsert) {