[][openwrt][mt7988][tops][tnl-offload: support with crypto-eip]

[Description]
Add tunnel offload with crypto-eip support.

Tunnel parameter now records CDRT index to provide help for tunnel
decapsulation and encapsulation offload setup flow.

For decapsulation, If skb already carried with CDRT information, it means
that packet is already decrypted by HW offload engine crypto-eip and there
is already a CLS rule setup for that packet. Therefore, we should not
modify the exist CLS rule. Instead, we just need to update the TPORT to
that CLS entry.

For encapsulation, there is nothing more need to do.

[Release-log]
N/A

Change-Id: Ib4ff408836fa0ed16895fc486c5ebdee90cfa0b6
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7923905
diff --git a/target/linux/mediatek/patches-5.4/999-4103-mtk-tunnel-crypto-offload-support.patch b/target/linux/mediatek/patches-5.4/999-4103-mtk-tunnel-crypto-offload-support.patch
new file mode 100644
index 0000000..8dd7b19
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/999-4103-mtk-tunnel-crypto-offload-support.patch
@@ -0,0 +1,214 @@
+--- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
++++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
+@@ -1091,6 +1091,8 @@ enum FoeIpAct {
+ #define NR_EIP197_QDMA_TPORT 3
+ #define NR_TDMA_TPORT 4
+ #define NR_TDMA_QDMA_TPORT 5
++#define NR_TDMA_EIP197_TPORT 8
++#define NR_TDMA_EIP197_QDMA_TPORT 9
+ #define LAN_DEV_NAME hnat_priv->lan
+ #define LAN2_DEV_NAME hnat_priv->lan2
+ #define IS_WAN(dev)                                                            \
+--- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
++++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
+@@ -1100,7 +1100,8 @@ static unsigned int hnat_ipv4_get_nextho
+ 	 * outer header, we must update its outer mac header pointer
+ 	 * before filling outer mac or it may screw up inner mac
+ 	 */
+-	if ((skb_hnat_tops(skb) && skb_hnat_is_encap(skb)) || skb_hnat_cdrt(skb)) {
++	if ((skb_hnat_tops(skb) && skb_hnat_is_encap(skb))
++	    || (skb_hnat_cdrt(skb) && skb_hnat_is_encrypt(skb))) {
+ 		skb_push(skb, sizeof(struct ethhdr));
+ 		skb_reset_mac_header(skb);
+ 	}
+@@ -1108,7 +1109,8 @@ static unsigned int hnat_ipv4_get_nextho
+ 	memcpy(eth_hdr(skb)->h_dest, neigh->ha, ETH_ALEN);
+ 	memcpy(eth_hdr(skb)->h_source, out->dev_addr, ETH_ALEN);
+ 
+-	if ((skb_hnat_tops(skb) && skb_hnat_is_encap(skb)) || skb_hnat_cdrt(skb))
++	if ((skb_hnat_tops(skb) && skb_hnat_is_encap(skb))
++	    || (skb_hnat_cdrt(skb) && skb_hnat_is_encrypt(skb)))
+ 		skb_pull(skb, sizeof(struct ethhdr));
+ 
+ 	rcu_read_unlock_bh();
+@@ -1256,6 +1258,38 @@ static inline void hnat_get_filled_unbin
+ 	entry->bfib1.ps = 0;
+ }
+ 
++/*
++ * check offload engine data is prepared
++ * return 0 for packets not related to offload engine
++ * return positive value for offload engine prepared data done
++ * return negative value for data is still constructing
++ */
++static inline int hnat_offload_engine_done(struct sk_buff *skb,
++					   struct flow_offload_hw_path *hw_path)
++{
++	struct dst_entry *dst = skb_dst(skb);
++
++	if ((skb_hnat_tops(skb) && !(hw_path->flags & FLOW_OFFLOAD_PATH_TNL))) {
++		/* tunnel encap'ed */
++		if (dst && dst_xfrm(dst))
++			/*
++			 * skb not ready to bind since it is still needs
++			 * to be encrypted
++			 */
++			return -1;
++
++		/* nothing need to be done further for this skb */
++		return 1;
++	}
++
++	if (skb_hnat_cdrt(skb) && skb_hnat_is_encrypt(skb) && dst && !dst_xfrm(dst))
++		/* crypto encrypted done */
++		return 1;
++
++	/* no need for tunnel encapsulation or crypto encryption */
++	return 0;
++}
++
+ static inline void hnat_qos_tnl(u32 id, const struct net_device *dev)
+ {
+ 	u32 cfg;
+@@ -1300,9 +1334,15 @@ static inline void hnat_fill_offload_eng
+ 		 * we fill in hnat tport and tops_entry for tunnel encapsulation
+ 		 * offloading
+ 		 */
+-		entry->ipv4_hnapt.tport_id = NR_TDMA_QDMA_TPORT;
++		if (skb_hnat_cdrt(skb) && skb_hnat_is_encrypt(skb)) {
++			entry->ipv4_hnapt.tport_id = NR_TDMA_EIP197_QDMA_TPORT;
++			entry->ipv4_hnapt.cdrt_id = skb_hnat_cdrt(skb);
++		} else {
++			entry->ipv4_hnapt.tport_id = NR_TDMA_QDMA_TPORT;
++		}
+ 		entry->ipv4_hnapt.tops_entry = skb_hnat_tops(skb);
+-	} else if (skb_hnat_cdrt(skb)) {
++
++	} else if (skb_hnat_cdrt(skb) && skb_hnat_is_encrypt(skb)) {
+ 		entry->ipv4_hnapt.tport_id = NR_EIP197_QDMA_TPORT;
+ 		entry->ipv4_hnapt.cdrt_id = skb_hnat_cdrt(skb);
+ 	} else {
+@@ -1334,6 +1374,7 @@ static unsigned int skb_to_hnat_info(str
+ 	u32 port_id = 0;
+ 	u32 payload_len = 0;
+ 	int mape = 0;
++	int ret;
+ 
+ 	ct = nf_ct_get(skb, &ctinfo);
+ 
+@@ -1350,10 +1391,12 @@ static unsigned int skb_to_hnat_info(str
+ 	if (whnat && is_hnat_pre_filled(foe))
+ 		return 0;
+ 
+-	if ((skb_hnat_tops(skb) && !(hw_path->flags & FLOW_OFFLOAD_PATH_TNL))
+-	    || (skb_hnat_cdrt(skb) && skb_dst(skb) && !dst_xfrm(skb_dst(skb)))) {
++	ret = hnat_offload_engine_done(skb, hw_path);
++	if (ret == 1) {
+ 		hnat_get_filled_unbind_entry(skb, &entry);
+ 		goto hnat_entry_bind;
++	} else if (ret == -1) {
++		return 0;
+ 	}
+ 
+ 	entry.bfib1.pkt_type = foe->udib1.pkt_type; /* Get packte type state*/
+@@ -1752,7 +1795,8 @@ static unsigned int skb_to_hnat_info(str
+ 	entry = ppe_fill_L2_info(eth, entry, hw_path);
+ 
+ 	if ((skb_hnat_tops(skb) && hw_path->flags & FLOW_OFFLOAD_PATH_TNL)
+-	    || (!skb_hnat_cdrt(skb) && skb_dst(skb) && dst_xfrm(skb_dst(skb))))
++	    || (!skb_hnat_cdrt(skb) && skb_hnat_is_encrypt(skb)
++	        && skb_dst(skb) && dst_xfrm(skb_dst(skb))))
+ 		goto hnat_entry_skip_bind;
+ 
+ hnat_entry_bind:
+@@ -1958,7 +2002,7 @@ hnat_entry_bind:
+ 
+ #if defined(CONFIG_MEDIATEK_NETSYS_V3)
+ 	hnat_fill_offload_engine_entry(skb, &entry, dev);
+-	if (skb_hnat_cdrt(skb))
++	if (skb_hnat_cdrt(skb) && skb_hnat_is_encrypt(skb))
+ 		entry = ppe_fill_L2_info(eth, entry, hw_path);
+ #endif
+ 
+@@ -2238,6 +2282,7 @@ int mtk_sw_nat_hook_rx(struct sk_buff *s
+ 	skb_hnat_alg(skb) = 0;
+ 	skb_hnat_set_tops(skb, 0);
+ 	skb_hnat_set_cdrt(skb, 0);
++	skb_hnat_set_is_decrypt(skb, 0);
+ 	skb_hnat_magic_tag(skb) = HNAT_MAGIC_TAG;
+ 
+ 	if (skb_hnat_iface(skb) == FOE_MAGIC_WED0)
+@@ -3018,7 +3063,8 @@ mtk_hnat_ipv4_nf_local_out(void *priv, s
+ 		entry->udib1.pkt_type = IPV6_6RD;
+ 		hnat_set_head_frags(state, skb, 0, hnat_set_alg);
+ 	} else if (is_magic_tag_valid(skb)
+-		   && (skb_hnat_cdrt(skb) || skb_hnat_tops(skb))) {
++		   && ((skb_hnat_cdrt(skb) && skb_hnat_is_encrypt(skb))
++		       || skb_hnat_tops(skb))) {
+ 		hnat_set_head_frags(state, skb, 0, hnat_set_alg);
+ 	} else {
+ 		hnat_set_head_frags(state, skb, 1, hnat_set_alg);
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -2316,11 +2316,14 @@ static int mtk_poll_rx(struct napi_struc
+ 
+ 		skb_hnat_alg(skb) = 0;
+ 		skb_hnat_filled(skb) = 0;
+-		skb_hnat_set_cdrt(skb, 0);
++		skb_hnat_set_cdrt(skb, RX_DMA_GET_CDRT(trxd.rxd7));
+ 		skb_hnat_magic_tag(skb) = HNAT_MAGIC_TAG;
+ 		skb_hnat_set_tops(skb, 0);
+ 		skb_hnat_set_is_decap(skb, 0);
+ 
++		if (skb_hnat_cdrt(skb))
++			skb_hnat_set_is_decrypt(skb, 1);
++
+ 		if (skb_hnat_reason(skb) == HIT_BIND_FORCE_TO_CPU) {
+ 			trace_printk("[%s] reason=0x%x(force to CPU) from WAN to Ext\n",
+ 				     __func__, skb_hnat_reason(skb));
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -640,6 +640,9 @@
+ #define RX_DMA_GET_AGG_CNT_V2(_x)	(((_x) >> 16) & 0xff)
+ #define RX_DMA_GET_TOPS_CRSN(_x)	(((_x) >> 24) & 0xff)
+ 
++/* PDMA V2 descriptor rxd7 */
++#define RX_DMA_GET_CDRT(_x)		(((_x) >> 8) & 0xff)
++
+ /* PHY Polling and SMI Master Control registers */
+ #define MTK_PPSC		0x10000
+ #define PPSC_MDC_CFG		GENMASK(29, 24)
+--- a/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
++++ b/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
+@@ -47,7 +47,8 @@ struct hnat_desc {
+ 	u32 tops : 6;
+ 	u32 is_decap : 1;
+ 	u32 cdrt : 8;
+-	u32 resv3 : 4;
++	u32 is_decrypt : 1;
++	u32 resv3 : 3;
+ 	u32 magic_tag_protect : 16;
+ } __packed;
+ #elif defined(CONFIG_MEDIATEK_NETSYS_RX_V2)
+@@ -101,7 +102,10 @@ struct hnat_desc {
+ #define skb_hnat_set_tops(skb, tops) ((skb_hnat_tops(skb)) = (tops))
+ #define skb_hnat_set_is_decap(skb, is_decap) ((skb_hnat_is_decap(skb)) = (is_decap))
+ #define skb_hnat_cdrt(skb) (((struct hnat_desc *)((skb)->head))->cdrt)
++#define skb_hnat_is_decrypt(skb) (((struct hnat_desc *)((skb)->head))->is_decrypt)
++#define skb_hnat_is_encrypt(skb) (!skb_hnat_is_decrypt(skb))
+ #define skb_hnat_set_cdrt(skb, cdrt) ((skb_hnat_cdrt(skb)) = (cdrt))
++#define skb_hnat_set_is_decrypt(skb, is_dec) ((skb_hnat_is_decrypt(skb)) = is_dec)
+ #else /* !defined(CONFIG_MEDIATEK_NETSYS_V3) */
+ #define skb_hnat_tops(skb) (0)
+ #define skb_hnat_is_decap(skb) (0)
+@@ -109,7 +113,10 @@ struct hnat_desc {
+ #define skb_hnat_set_tops(skb, tops)
+ #define skb_hnat_set_is_decap(skb, is_decap)
+ #define skb_hnat_cdrt(skb) (0)
++#define skb_hnat_is_decrypt(skb) (0)
++#define skb_hnat_is_encrypt(skb) (0)
+ #define skb_hnat_set_cdrt(skb, cdrt)
++#define skb_hnat_set_is_decrypt(skb, is_dec)
+ #endif /* defined(CONFIG_MEDIATEK_NETSYS_V3) */
+ #define skb_hnat_magic(skb) (((struct hnat_desc *)(skb->head))->magic)
+ #define skb_hnat_reason(skb) (((struct hnat_desc *)(skb->head))->crsn)