[][kernel][mt7988][hnat][add L2TP iface flow offload check]
[Description]
Add l2tp interface flow offload check
[Release-log]
N/A
Change-Id: I90a636db0120c908bb53db8adf7093fb568ca174
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7596212
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
index 95e5e3c..ef6946f 100644
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
@@ -825,6 +825,9 @@
mtk_hnat_ipv4_nf_pre_routing(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
+ struct flow_offload_hw_path hw_path = { .dev = skb->dev,
+ .virt_dev = skb->dev };
+
if (!skb)
goto drop;
@@ -835,6 +838,19 @@
hnat_set_head_frags(state, skb, -1, hnat_set_iif);
+ /*
+ * Avoid mistakenly binding of outer IP, ports in SW L2TP decap flow.
+ * In pre-routing, if dev is virtual iface, TOPS module is not loaded,
+ * and it's L2TP flow, then do not bind.
+ */
+ if (skb_hnat_iface(skb) == FOE_MAGIC_GE_VIRTUAL
+ && skb->dev->netdev_ops->ndo_flow_offload_check) {
+ skb->dev->netdev_ops->ndo_flow_offload_check(&hw_path);
+
+ if (hw_path.flags & FLOW_OFFLOAD_PATH_TNL)
+ skb_hnat_alg(skb) = 1;
+ }
+
pre_routing_print(skb, state->in, state->out, __func__);
/* packets from external devices -> xxx ,step 1 , learning stage & bound stage*/
diff --git a/target/linux/mediatek/patches-5.4/999-2726-mtkhnat-tnl-interface-offload-check.patch b/target/linux/mediatek/patches-5.4/999-2726-mtkhnat-tnl-interface-offload-check.patch
new file mode 100644
index 0000000..e94185f
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/999-2726-mtkhnat-tnl-interface-offload-check.patch
@@ -0,0 +1,62 @@
+--- a/include/net/netfilter/nf_flow_table.h
++++ b/include/net/netfilter/nf_flow_table.h
+@@ -96,6 +96,7 @@ struct flow_offload {
+ #define FLOW_OFFLOAD_PATH_DSA BIT(3)
+ #define FLOW_OFFLOAD_PATH_DSLITE BIT(4)
+ #define FLOW_OFFLOAD_PATH_6RD BIT(5)
++#define FLOW_OFFLOAD_PATH_TNL BIT(6)
+
+ struct flow_offload_hw_path {
+ struct net_device *dev;
+--- a/net/l2tp/l2tp_ppp.c
++++ b/net/l2tp/l2tp_ppp.c
+@@ -89,6 +89,7 @@
+ #include <linux/nsproxy.h>
+ #include <net/net_namespace.h>
+ #include <net/netns/generic.h>
++#include <net/netfilter/nf_flow_table.h>
+ #include <net/ip.h>
+ #include <net/udp.h>
+ #include <net/inet_common.h>
+@@ -124,9 +125,14 @@ struct pppol2tp_session {
+ };
+
+ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb);
++static int l2tp_ppp_flow_offload_check(struct ppp_channel *chan,
++ struct flow_offload_hw_path *path);
+
+ static const struct ppp_channel_ops pppol2tp_chan_ops = {
+ .start_xmit = pppol2tp_xmit,
++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
++ .flow_offload_check = l2tp_ppp_flow_offload_check,
++#endif /* IS_ENABLED(CONFIG_NF_FLOW_TABLE) */
+ };
+
+ static const struct proto_ops pppol2tp_ops;
+@@ -335,6 +341,26 @@ error:
+ return error;
+ }
+
++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
++static int l2tp_ppp_flow_offload_check(struct ppp_channel *chan,
++ struct flow_offload_hw_path *path)
++{
++ struct sock *sk = (struct sock *)chan->private;
++ struct l2tp_session *session;
++
++ if (path->flags & FLOW_OFFLOAD_PATH_TNL)
++ return -EEXIST;
++
++ session = pppol2tp_sock_to_session(sk);
++ if (!session)
++ return -EINVAL;
++
++ path->flags |= FLOW_OFFLOAD_PATH_TNL;
++
++ return 0;
++}
++#endif /* IS_ENABLED(CONFIG_NF_FLOW_TABLE) */
++
+ /* Transmit function called by generic PPP driver. Sends PPP frame
+ * over PPPoL2TP socket.
+ *