[Bugfix][API-1415] merge MTK hwnat patch

Only Configure: No
Affected branch: GSW3.0-No-Connman
Affected module: ethernet
Is it affected on both ZXIC and MTK: only MTK
Self-test: No
Doc Update: No

Change-Id: Ifda159aed9c922e459442d341dd6ccfe41cbafbf
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index aa4453b..709b7c9 100755
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -916,21 +916,8 @@
 	/* set the forward port */
 	fport = (mac->id + 1) << TX_DMA_FPORT_SHIFT;
 #if defined(CONFIG_HW_NAT)
-	if (IS_MAGIC_TAG_PROTECT_VALID_HEAD(skb)) {
-		if (FOE_MAGIC_TAG_HEAD(skb) == FOE_MAGIC_PPE) {
-			if (ppe_hook_rx_eth) {
-				fport = (3 << TX_DMA_FPORT_SHIFT);
-				FOE_MAGIC_TAG(skb) = 0;
-			}
-		}
-	} else if (IS_MAGIC_TAG_PROTECT_VALID_TAIL(skb)) {
-		if (FOE_MAGIC_TAG_TAIL(skb) == FOE_MAGIC_PPE) {
-			if (ppe_hook_rx_eth) {
-				fport = (3 << TX_DMA_FPORT_SHIFT);
-				FOE_MAGIC_TAG(skb) = 0;
-			}
-		}
-	}
+	if (ppe_hook_tx_eth_fport && ppe_hook_tx_eth_fport(skb))
+		fport = (3 << TX_DMA_FPORT_SHIFT);
 #endif
 	txd4 |= fport;
 
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 745ec1c..bcfe59c 100644
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -1180,6 +1180,7 @@
 #if defined(CONFIG_HW_NAT)
 extern int (*ppe_hook_rx_eth)(struct sk_buff *skb);
 extern int (*ppe_hook_tx_eth)(struct sk_buff *skb, int gmac_no);
+extern int (*ppe_hook_tx_eth_fport)(struct sk_buff *skb);
 extern void (*ppe_dev_register_hook)(struct net_device *dev);
 extern void (*ppe_dev_unregister_hook)(struct net_device *dev);
 #endif
diff --git a/src/kernel/linux/v4.19/include/net/ra_nat.h b/src/kernel/linux/v4.19/include/net/ra_nat.h
index 189e119..5b715e8 100644
--- a/src/kernel/linux/v4.19/include/net/ra_nat.h
+++ b/src/kernel/linux/v4.19/include/net/ra_nat.h
@@ -224,7 +224,9 @@
 #define FOE_MAGIC_EDMARX	    0x85
 #define FOE_MAGIC_RNDIS		    0x86
 #define FOE_MAGIC_SNPS		    0x87
-#define TAG_PROTECT                 0x6789
+#define FOE_MAGIC_VALID(num)	    ((num >= FOE_MAGIC_PCI) && (num <= FOE_MAGIC_SNPS))
+
+#define TAG_PROTECT                 0xDEAD
 #define USE_HEAD_ROOM               0
 #define USE_TAIL_ROOM               1
 #define USE_CB                      2
@@ -427,23 +429,7 @@
 	(FOE_MAGIC_TAG_CB(skb) == FOE_MAGIC_RNDIS))
 
 /* macros */
-#define magic_tag_set_zero(skb) \
-{ \
-	if ((FOE_MAGIC_TAG_HEAD(skb) == FOE_MAGIC_PCI) || \
-	    (FOE_MAGIC_TAG_HEAD(skb) == FOE_MAGIC_WLAN) || \
-	    (FOE_MAGIC_TAG_HEAD(skb) == FOE_MAGIC_RNDIS) || \
-	    (FOE_MAGIC_TAG_HEAD(skb) == FOE_MAGIC_GE)) { \
-		if (IS_SPACE_AVAILABLE_HEAD(skb)) \
-			FOE_MAGIC_TAG_HEAD(skb) = 0; \
-	} \
-	if ((FOE_MAGIC_TAG_TAIL(skb) == FOE_MAGIC_PCI) || \
-	    (FOE_MAGIC_TAG_TAIL(skb) == FOE_MAGIC_WLAN) || \
-	    (FOE_MAGIC_TAG_TAIL(skb) == FOE_MAGIC_RNDIS) || \
-	    (FOE_MAGIC_TAG_TAIL(skb) == FOE_MAGIC_GE)) { \
-		if (IS_SPACE_AVAILABLE_TAIL(skb)) \
-			FOE_MAGIC_TAG_TAIL(skb) = 0; \
-	} \
-}
+#define magic_tag_set_zero(skb) hwnat_magic_tag_set_zero(skb)
 
 static inline void hwnat_set_l2tp_unhit(struct iphdr *iph, struct sk_buff *skb)
 {
diff --git a/src/kernel/linux/v4.19/net/nat/foe_hook/hook_ext.c b/src/kernel/linux/v4.19/net/nat/foe_hook/hook_ext.c
index 85a3482..5fad032 100644
--- a/src/kernel/linux/v4.19/net/nat/foe_hook/hook_ext.c
+++ b/src/kernel/linux/v4.19/net/nat/foe_hook/hook_ext.c
@@ -41,6 +41,8 @@
 EXPORT_SYMBOL(ppe_hook_rx_eth);
 int (*ppe_hook_tx_eth)(struct sk_buff *skb, int gmac_no) = NULL;
 EXPORT_SYMBOL(ppe_hook_tx_eth);
+int (*ppe_hook_tx_eth_fport)(struct sk_buff *skb) = NULL;
+EXPORT_SYMBOL(ppe_hook_tx_eth_fport);
 
 int (*ppe_hook_rx_ext)(struct sk_buff *skb) = NULL;
 EXPORT_SYMBOL(ppe_hook_rx_ext);
@@ -76,16 +78,26 @@
 	if ((FOE_MAGIC_TAG_HEAD(skb) == FOE_MAGIC_PCI) ||
 	    (FOE_MAGIC_TAG_HEAD(skb) == FOE_MAGIC_WLAN) ||
 	    (FOE_MAGIC_TAG_HEAD(skb) == FOE_MAGIC_GE) ||
+	    (FOE_MAGIC_TAG_HEAD(skb) == FOE_MAGIC_WED0) ||
+	    (FOE_MAGIC_TAG_HEAD(skb) == FOE_MAGIC_WED1) ||
+	    (FOE_MAGIC_TAG_HEAD(skb) == FOE_MAGIC_MED) ||
 	    (FOE_MAGIC_TAG_HEAD(skb) == FOE_MAGIC_RNDIS)) {
-		if (IS_SPACE_AVAILABLE_HEAD(skb))
+		if (IS_SPACE_AVAILABLE_HEAD(skb)) {
 			FOE_MAGIC_TAG_HEAD(skb) = 0;
+			FOE_TAG_PROTECT_HEAD(skb) = 0;
+		}
 	}
 	if ((FOE_MAGIC_TAG_TAIL(skb) == FOE_MAGIC_PCI) ||
 	    (FOE_MAGIC_TAG_TAIL(skb) == FOE_MAGIC_WLAN) ||
 	    (FOE_MAGIC_TAG_TAIL(skb) == FOE_MAGIC_GE) ||
+	    (FOE_MAGIC_TAG_TAIL(skb) == FOE_MAGIC_WED0) ||
+	    (FOE_MAGIC_TAG_TAIL(skb) == FOE_MAGIC_WED1) ||
+	    (FOE_MAGIC_TAG_TAIL(skb) == FOE_MAGIC_MED) ||
 	    (FOE_MAGIC_TAG_TAIL(skb) == FOE_MAGIC_RNDIS)) {
-		if (IS_SPACE_AVAILABLE_TAIL(skb))
+		if (IS_SPACE_AVAILABLE_TAIL(skb)) {
 			FOE_MAGIC_TAG_TAIL(skb) = 0;
+			FOE_TAG_PROTECT_TAIL(skb) = 0;
+		}
 	}
 }
 EXPORT_SYMBOL(hwnat_magic_tag_set_zero);
@@ -94,7 +106,7 @@
 {
 	if (IS_SPACE_AVAILABLE_HEAD(skb)) {
 		FOE_MAGIC_TAG_HEAD(skb) = 0;
-		FOE_AI_HEAD(skb) = UN_HIT;
+		FOE_AI(skb) = UN_HIT;
 	}
 	if (IS_SPACE_AVAILABLE_TAIL(skb)) {
 		FOE_MAGIC_TAG_TAIL(skb) = 0;
diff --git a/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_common.c b/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_common.c
index e988c6d..6757f3d 100755
--- a/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_common.c
+++ b/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_common.c
@@ -886,6 +886,46 @@
 		return 0;
 }
 
+int32_t ppe_tx_eth_fport_handler(struct sk_buff *skb)
+{
+	int ret = 0;
+	struct ethhdr *eth = (struct ethhdr *)skb_mac_header(skb);
+
+	/* PPE can only handle IPv4/IPv6/PPP packets */
+	if (((skb->protocol != htons(ETH_P_8021Q)) &&
+	    (skb->protocol != htons(ETH_P_IP)) && (skb->protocol != htons(ETH_P_IPV6)) &&
+	    (skb->protocol != htons(ETH_P_PPP_SES)) && (skb->protocol != htons(ETH_P_PPP_DISC))) ||
+		is_multicast_ether_addr(&eth->h_dest[0])) {
+
+		hwnat_magic_tag_set_zero(skb);
+
+		if (debug_level >= 10)
+			pr_notice("%s not support, skb->protocol = 0x%x, multicast:%d\n",
+				__func__, skb->protocol, is_multicast_ether_addr(&eth->h_dest[0]));
+	} else {
+		if (IS_MAGIC_TAG_PROTECT_VALID_HEAD(skb)) {
+			if (FOE_MAGIC_TAG_HEAD(skb) == FOE_MAGIC_PPE && FOE_AI(skb) == UN_HIT) {
+				if (ppe_hook_rx_eth) {
+					ret = 1;
+					FOE_MAGIC_TAG(skb) = 0;
+				}
+			}
+		} else if (IS_MAGIC_TAG_PROTECT_VALID_TAIL(skb)) {
+			if (FOE_MAGIC_TAG_TAIL(skb) == FOE_MAGIC_PPE && FOE_AI_TAIL(skb) == UN_HIT) {
+				if (ppe_hook_rx_eth) {
+					ret = 1;
+					FOE_MAGIC_TAG(skb) = 0;
+				}
+			}
+		}
+	}
+
+	if (debug_level >= 10)
+		pr_info("%s end, ret:%d\n", __func__, ret);
+
+	return ret;
+}
+
 /* push different VID for WiFi pseudo interface or USB external NIC */
 uint32_t ppe_extif_rx_handler(struct sk_buff *skb)
 {
@@ -901,8 +941,11 @@
 	    (skb->protocol != htons(ETH_P_PPP_SES)) && (skb->protocol != htons(ETH_P_PPP_DISC))) ||
 		is_multicast_ether_addr(&eth->h_dest[0])) {
 
+		hwnat_magic_tag_set_zero(skb);
+
 		if (debug_level >= 10)
 			pr_notice("%s not support, skb->protocol = 0x%x, multicast:%d\n", __func__, skb->protocol, is_multicast_ether_addr(&eth->h_dest[0]));
+
 		return 1;
 	}
 
@@ -4310,7 +4353,7 @@
 		//pr_notice(" which_region = %d\n", which_region);
 
 	if (which_region == ALL_INFO_ERROR) {
-		if (debug_level >= 7)
+		if (debug_level >= 10)
 			pr_notice("ppe_tx_handler : ALL_INFO_ERROR\n");
 		return 1;
 	}
@@ -4323,7 +4366,15 @@
 
 int check_magic_tag_valid(struct sk_buff *skb)
 {
-	if(is_magic_tag_protect_valid(skb))
+	if (FOE_MAGIC_VALID(FOE_MAGIC_TAG(skb)))
+		return 0;
+	else
+		return 1;
+}
+
+int check_rx_idx_valid(struct sk_buff *skb)
+{
+	if (dst_port[FOE_IF_IDX(skb)])
 		return 0;
 	else
 		return 1;
@@ -4833,6 +4884,8 @@
 	struct foe_entry *entry;
 
 	entry = decide_which_ppe(skb);
+	if (entry == NULL)
+		return;
 
 	if (debug_level >= 7) {
 		hnat_cpu_reason_cnt(skb);
@@ -4860,6 +4913,8 @@
 
 	entry = decide_which_ppe(skb);
 
+	if (entry == NULL)
+		return 1;
 
 	if (FOE_AI(skb) == HIT_BIND_FORCE_TO_CPU ||
 	    FOE_AI(skb) == PACKET_FORWARD_PATH_WITHOUT_PPE) {
@@ -4902,6 +4957,8 @@
 	/*struct ethhdr *eth = (struct ethhdr *)(skb->data - ETH_HLEN);*/
 
 	entry = decide_which_ppe(skb);
+	if (entry == NULL)
+		return 1;
 
 	if (FOE_AI(skb) == HIT_BIND_KEEPALIVE_DUP_OLD_HDR) {
 		if (debug_level >= 3)
@@ -4948,6 +5005,8 @@
 			pr_notice("%s, HIT_BIND_FORCE_TO_CPU, FOE_SP(skb):%d\n", __func__, FOE_SP(skb));
 		}
 		entry = decide_which_ppe(skb);
+		if (entry == NULL)
+			return 1;
 
 		return hitbind_force_to_cpu_handler(skb, entry);
 
@@ -5115,7 +5174,7 @@
 			&ppe1_foe_base[FOE_ENTRY_NUM(skb)] : // MDMA
 			&ppe_foe_base[FOE_ENTRY_NUM(skb)];
 	} else {
-		entry = &ppe_foe_base[FOE_ENTRY_NUM(skb)];
+		//entry = &ppe_foe_base[FOE_ENTRY_NUM(skb)];
 		if (debug_level >= 3) {
 			/* [MAGIC is PPE] extif -> eth_tx (pse port is uninitialized) -> eth rx -> pingpong */
 			/* [MAGIC is WLAN] rx wifi (pse port is uninitialized) */
@@ -5124,6 +5183,7 @@
 				pr_notice("%s, SP port error = %d, %s\n", __func__, FOE_SP(skb), skb->dev->name);
 			}
 		}
+		return NULL;
 	}
 	set_rxif_idx(entry, FOE_IF_IDX(skb));
 
diff --git a/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_common.h b/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_common.h
index 3be3d84..858b3b5 100755
--- a/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_common.h
+++ b/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_common.h
@@ -75,6 +75,7 @@
 uint32_t hnat_cpu_reason_cnt(struct sk_buff *skb);
 uint32_t foe_dump_pkt(struct sk_buff *skb, struct foe_entry *entry);
 int hitbind_force_to_cpu_handler(struct sk_buff *skb, struct foe_entry *entry);
+int32_t ppe_tx_eth_fport_handler(struct sk_buff *skb);
 uint32_t ppe_extif_rx_handler(struct sk_buff *skb);
 uint32_t ppe_extif_pingpong_handler(struct sk_buff *skb);
 uint32_t keep_alive_handler(struct sk_buff *skb, struct foe_entry *entry);
@@ -112,6 +113,7 @@
 int ppe_common_ext(struct sk_buff *skb, struct foe_entry *entry, int gmac_no,
 				    struct pkt_parse_result *ppe_parse_result);
 int check_magic_tag_valid(struct sk_buff *skb);
+int check_rx_idx_valid(struct sk_buff *skb);
 int set_pre_bind(struct sk_buff *skb,struct foe_entry *entry);
 int tx_cpu_handler_wifi(struct sk_buff *skb, struct foe_entry *entry, int gmac_no);
 int tx_cpu_handler_eth(struct sk_buff *skb, struct foe_entry *entry, int gmac_no);
diff --git a/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_define.h b/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_define.h
index b69017b..0e0cb88 100644
--- a/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_define.h
+++ b/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_define.h
@@ -86,6 +86,7 @@
 extern int (*ppe_hook_tx_rndis)(struct sk_buff *skb);
 extern int (*ppe_hook_rx_eth)(struct sk_buff *skb);
 extern int (*ppe_hook_tx_eth)(struct sk_buff *skb, int gmac_no);
+extern int (*ppe_hook_tx_eth_fport)(struct sk_buff *skb);
 extern int (*ppe_hook_rx_ext)(struct sk_buff *skb);
 extern int (*ppe_hook_tx_ext)(struct sk_buff *skb, int gmac_no);
 extern int (*ppe_hook_rx_snps)(struct sk_buff *skb);
diff --git a/src/kernel/modules/netsys_driver/nat/hw_nat/ra_nat.c b/src/kernel/modules/netsys_driver/nat/hw_nat/ra_nat.c
index 2c64392..70e8b2b 100644
--- a/src/kernel/modules/netsys_driver/nat/hw_nat/ra_nat.c
+++ b/src/kernel/modules/netsys_driver/nat/hw_nat/ra_nat.c
@@ -254,6 +254,8 @@
 
 	//decide which ppe0/ppe1
 	entry = decide_which_ppe(skb);
+	if (entry == NULL)
+		return 1;
 
 	ret = tx_cpu_handler_modem(skb, entry, MDMA_PSE_PORT);
 
@@ -341,6 +343,8 @@
 
 	//decide which ppe0/ppe1
 	entry = decide_which_ppe(skb);
+	if (entry == NULL)
+		return 1;
 
 	ret = tx_cpu_handler_rndis(skb, entry, ADMA_PSE_PORT);
 
@@ -378,6 +382,8 @@
 
 	//decide which ppe0/ppe1
 	entry = decide_which_ppe(skb);
+	if (entry == NULL)
+		return 1;
 
 	ret = tx_cpu_handler_wifi(skb, entry, gmac_no);
 
@@ -406,16 +412,28 @@
 	int ret;
 
 	ret = check_whitelist(skb);
-
 	if (ret)
 		return 1;
+
+	/* check TAG_PROTECT & FOE_ENTRY_NUM */
 	ret = check_entry_region(skb);
-
 	if (ret)
 		return 1;
 
-	//decide which ppe0/ppe1
+	/* check MAGIC_TAG */
+	ret = check_magic_tag_valid(skb);
+	if (ret)
+		return 1;
+
+	/* check IF_IDX */
+	ret = check_rx_idx_valid(skb);
+	if (ret)
+		return 1;
+
+	/* check SP */
 	entry = decide_which_ppe(skb);
+	if (entry == NULL)
+		return 1;
 
 	ret = tx_cpu_handler_eth(skb, entry, gmac_no);
 
@@ -462,6 +480,8 @@
 
 	//decide which ppe0/ppe1
 	entry = decide_which_ppe(skb);
+	if (entry == NULL)
+		return 1;
 
 	ret = tx_cpu_handler_ext(skb, entry, gmac_no);
 
@@ -495,6 +515,8 @@
 
 	//decide which ppe0/ppe1
 	entry = decide_which_ppe(skb);
+	if (entry == NULL)
+		return 1;
 
 	ret = tx_cpu_handler_snps(skb, entry, ADMA_PSE_PORT);
 
@@ -541,6 +563,7 @@
 		ppe_hook_rx_eth = ppe_rx_eth_handler;
 		ppe_hook_tx_eth = ppe_tx_eth_handler;
 #endif
+		ppe_hook_tx_eth_fport = ppe_tx_eth_fport_handler;
 		ppe_hook_rx_ext = ppe_rx_ext_handler;
 		/* EDIA TX fast path is not ready */
 		ppe_hook_tx_ext = NULL;
@@ -573,6 +596,7 @@
 		ppe_hook_rx_eth = NULL;
 		ppe_hook_tx_eth = NULL;
 #endif
+		ppe_hook_tx_eth_fport = NULL;
 		ppe_hook_rx_ext = NULL;
 		/* EDIA TX fast path is not ready */
 		ppe_hook_tx_ext = NULL;
@@ -836,6 +860,7 @@
 		ppe_hook_rx_eth = ppe_rx_eth_handler;
 		ppe_hook_tx_eth = ppe_tx_eth_handler;
 #endif
+		ppe_hook_tx_eth_fport = ppe_tx_eth_fport_handler;
 		ppe_hook_rx_ext = ppe_rx_ext_handler;
 		/* EDIA TX fast path is not ready */
 		ppe_hook_tx_ext = NULL;
@@ -898,6 +923,7 @@
 	ppe_hook_tx_rndis = NULL;
 	ppe_hook_rx_eth = NULL;
 	ppe_hook_tx_eth = NULL;
+	ppe_hook_tx_eth_fport = NULL;
 	ppe_hook_rx_ext = NULL;
 	ppe_hook_tx_ext = NULL;
 	ppe_dev_register_hook = NULL;
diff --git a/src/kernel/modules/netsys_driver/nat/hw_nat/ra_nat.h b/src/kernel/modules/netsys_driver/nat/hw_nat/ra_nat.h
index 1ae61c7..661008c 100644
--- a/src/kernel/modules/netsys_driver/nat/hw_nat/ra_nat.h
+++ b/src/kernel/modules/netsys_driver/nat/hw_nat/ra_nat.h
@@ -317,7 +317,9 @@
 #define FOE_MAGIC_EDMARX	    0x85
 #define FOE_MAGIC_RNDIS		    0x86
 #define FOE_MAGIC_SNPS		    0x87
-#define TAG_PROTECT                 0x6789
+#define FOE_MAGIC_VALID(num)	    ((num >= FOE_MAGIC_PCI) && (num <= FOE_MAGIC_SNPS))
+
+#define TAG_PROTECT                 0xDEAD
 #define USE_HEAD_ROOM               0
 #define USE_TAIL_ROOM               1
 #define USE_CB                      2
@@ -534,23 +536,7 @@
 	(FOE_MAGIC_TAG_CB(skb) == FOE_MAGIC_RNDIS))
 
 /* macros */
-#define magic_tag_set_zero(skb) \
-{ \
-	if ((FOE_MAGIC_TAG_HEAD(skb) == FOE_MAGIC_PCI) || \
-	    (FOE_MAGIC_TAG_HEAD(skb) == FOE_MAGIC_WLAN) || \
-	    (FOE_MAGIC_TAG_HEAD(skb) == FOE_MAGIC_RNDIS) || \
-	    (FOE_MAGIC_TAG_HEAD(skb) == FOE_MAGIC_GE)) { \
-		if (IS_SPACE_AVAILABLE_HEAD(skb)) \
-			FOE_MAGIC_TAG_HEAD(skb) = 0; \
-	} \
-	if ((FOE_MAGIC_TAG_TAIL(skb) == FOE_MAGIC_PCI) || \
-	    (FOE_MAGIC_TAG_TAIL(skb) == FOE_MAGIC_WLAN) || \
-	    (FOE_MAGIC_TAG_TAIL(skb) == FOE_MAGIC_RNDIS) || \
-	    (FOE_MAGIC_TAG_TAIL(skb) == FOE_MAGIC_GE)) { \
-		if (IS_SPACE_AVAILABLE_TAIL(skb)) \
-			FOE_MAGIC_TAG_TAIL(skb) = 0; \
-	} \
-}
+#define magic_tag_set_zero(skb) hwnat_magic_tag_set_zero(skb)
 
 static inline void hwnat_set_l2tp_unhit(struct iphdr *iph, struct sk_buff *skb)
 {