[][[Kernel][common][hnat][Fix the way of recording SMAC and DMAC in get_nexthop API]]

[Description]
Fix the way of recording SMAC and DMAC in get_nexthop API.
1: After tunnel encapsulation or decapsulation,
MAC header of the skb no longer points to the correct location.
Filling SMAC/DMAC in the skb at this point may cause packet loss.
2: Filling Ethernet header should be handled by the kernel.
HNAT should avoid modifying the skb to prevent anomalies.

[Release-log]
NA


Change-Id: I45385710a31b2f80001cb1ffd02d26ea15e5cfd8
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/9682828
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
index 05f28e9..6286310 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
@@ -1163,23 +1163,9 @@
 	const struct in6_addr *ipv6_nexthop;
 	struct neighbour *neigh = NULL;
 	struct dst_entry *dst = skb_dst(skb);
-	struct ethhdr *eth;
-	u16 eth_pppoe_hlen = ETH_HLEN + PPPOE_SES_HLEN;
-
-	if (hw_path->flags & FLOW_OFFLOAD_PATH_PPPOE) {
-		if (ipv6_hdr(skb)->nexthdr == NEXTHDR_IPIP) {
-			eth = (struct ethhdr *)(skb->data - eth_pppoe_hlen);
-			eth->h_proto = skb->protocol;
-			ether_addr_copy(eth->h_dest, hw_path->eth_dest);
-			ether_addr_copy(eth->h_source,  hw_path->eth_src);
-		} else {
-			eth = eth_hdr(skb);
-			memcpy(eth->h_source, hw_path->eth_src, ETH_ALEN);
-			memcpy(eth->h_dest, hw_path->eth_dest, ETH_ALEN);
-		}
 
+	if (hw_path->flags & FLOW_OFFLOAD_PATH_PPPOE)
 		return 0;
-	}
 
 	rcu_read_lock_bh();
 	ipv6_nexthop =
@@ -1198,16 +1184,8 @@
 		return -1;
 	}
 
-	if (ipv6_hdr(skb)->nexthdr == NEXTHDR_IPIP) {
-		/*copy ether type for DS-Lite and MapE */
-		eth = (struct ethhdr *)(skb->data - ETH_HLEN);
-		eth->h_proto = skb->protocol;
-	} else {
-		eth = eth_hdr(skb);
-	}
-
-	ether_addr_copy(eth->h_dest, neigh->ha);
-	ether_addr_copy(eth->h_source, out->dev_addr);
+	ether_addr_copy(hw_path->eth_dest, neigh->ha);
+	ether_addr_copy(hw_path->eth_src, out->dev_addr);
 
 	rcu_read_unlock_bh();
 
@@ -1223,15 +1201,9 @@
 	struct dst_entry *dst = skb_dst(skb);
 	struct rtable *rt = (struct rtable *)dst;
 	struct net_device *dev = (__force struct net_device *)out;
-	struct ethhdr *eth;
 
-	if (hw_path->flags & FLOW_OFFLOAD_PATH_PPPOE) {
-		rcu_read_lock_bh();
-		memcpy(eth_hdr(skb)->h_source, hw_path->eth_src, ETH_ALEN);
-		memcpy(eth_hdr(skb)->h_dest, hw_path->eth_dest, ETH_ALEN);
-		rcu_read_unlock_bh();
+	if (hw_path->flags & FLOW_OFFLOAD_PATH_PPPOE)
 		return 0;
-	}
 
 	if (!skb_hnat_cdrt(skb) && dst && dst_xfrm(dst))
 		return 0;
@@ -1263,15 +1235,8 @@
 		skb_reset_mac_header(skb);
 	}
 
-	if (ip_hdr(skb)->protocol == IPPROTO_IPV6)
-		/* 6RD LAN->WAN(6to4) */
-		eth = (struct ethhdr *)(skb->data - ETH_HLEN);
-	else
-		eth = eth_hdr(skb);
-
-	memcpy(eth->h_dest, neigh->ha, ETH_ALEN);
-	memcpy(eth->h_source, out->dev_addr, ETH_ALEN);
-	eth->h_proto = htons(ETH_P_IP);
+	memcpy(hw_path->eth_dest, neigh->ha, ETH_ALEN);
+	memcpy(hw_path->eth_src, out->dev_addr, ETH_ALEN);
 
 	if ((skb_hnat_tops(skb) && skb_hnat_is_encap(skb)) ||
 	    (skb_hnat_cdrt(skb) && skb_hnat_is_encrypt(skb)))
@@ -1302,16 +1267,16 @@
 	return chksum_base;
 }
 
-struct foe_entry ppe_fill_L2_info(struct ethhdr *eth, struct foe_entry entry,
+struct foe_entry ppe_fill_L2_info(struct foe_entry entry,
 				  struct flow_offload_hw_path *hw_path)
 {
 	switch ((int)entry.bfib1.pkt_type) {
 	case IPV4_HNAPT:
 	case IPV4_HNAT:
-		entry.ipv4_hnapt.dmac_hi = swab32(*((u32 *)eth->h_dest));
-		entry.ipv4_hnapt.dmac_lo = swab16(*((u16 *)&eth->h_dest[4]));
-		entry.ipv4_hnapt.smac_hi = swab32(*((u32 *)eth->h_source));
-		entry.ipv4_hnapt.smac_lo = swab16(*((u16 *)&eth->h_source[4]));
+		entry.ipv4_hnapt.dmac_hi = swab32(*((u32 *)hw_path->eth_dest));
+		entry.ipv4_hnapt.dmac_lo = swab16(*((u16 *)&hw_path->eth_dest[4]));
+		entry.ipv4_hnapt.smac_hi = swab32(*((u32 *)hw_path->eth_src));
+		entry.ipv4_hnapt.smac_lo = swab16(*((u16 *)&hw_path->eth_src[4]));
 		entry.ipv4_hnapt.pppoe_id = hw_path->pppoe_sid;
 		break;
 	case IPV4_DSLITE:
@@ -1321,18 +1286,17 @@
 	case IPV6_3T_ROUTE:
 	case IPV6_HNAPT:
 	case IPV6_HNAT:
-		entry.ipv6_5t_route.dmac_hi = swab32(*((u32 *)eth->h_dest));
-		entry.ipv6_5t_route.dmac_lo = swab16(*((u16 *)&eth->h_dest[4]));
-		entry.ipv6_5t_route.smac_hi = swab32(*((u32 *)eth->h_source));
-		entry.ipv6_5t_route.smac_lo =
-			swab16(*((u16 *)&eth->h_source[4]));
+		entry.ipv6_5t_route.dmac_hi = swab32(*((u32 *)hw_path->eth_dest));
+		entry.ipv6_5t_route.dmac_lo = swab16(*((u16 *)&hw_path->eth_dest[4]));
+		entry.ipv6_5t_route.smac_hi = swab32(*((u32 *)hw_path->eth_src));
+		entry.ipv6_5t_route.smac_lo = swab16(*((u16 *)&hw_path->eth_src[4]));
 		entry.ipv6_5t_route.pppoe_id = hw_path->pppoe_sid;
 		break;
 	}
 	return entry;
 }
 
-struct foe_entry ppe_fill_info_blk(struct ethhdr *eth, struct foe_entry entry,
+struct foe_entry ppe_fill_info_blk(struct foe_entry entry,
 				   struct flow_offload_hw_path *hw_path)
 {
 	entry.bfib1.psn = (hw_path->flags & FLOW_OFFLOAD_PATH_PPPOE) ? 1 : 0;
@@ -1348,7 +1312,7 @@
 	case IPV4_HNAPT:
 	case IPV4_HNAT:
 		if (hnat_priv->data->mcast &&
-		    is_multicast_ether_addr(&eth->h_dest[0])) {
+		    is_multicast_ether_addr(&hw_path->eth_dest[0])) {
 			entry.ipv4_hnapt.iblk2.mcast = 1;
 			if (hnat_priv->data->version == MTK_HNAT_V1_3) {
 				entry.bfib1.sta = 1;
@@ -1371,7 +1335,7 @@
 	case IPV6_HNAPT:
 	case IPV6_HNAT:
 		if (hnat_priv->data->mcast &&
-		    is_multicast_ether_addr(&eth->h_dest[0])) {
+		    is_multicast_ether_addr(&hw_path->eth_dest[0])) {
 			entry.ipv6_5t_route.iblk2.mcast = 1;
 			if (hnat_priv->data->version == MTK_HNAT_V1_3) {
 				entry.bfib1.sta = 1;
@@ -1391,20 +1355,6 @@
 	return entry;
 }
 
-static struct ethhdr *get_ipv6_ipip_ethhdr(struct sk_buff *skb,
-					   struct flow_offload_hw_path *hw_path)
-{
-	struct ethhdr *eth;
-	u16 eth_pppoe_hlen = ETH_HLEN + PPPOE_SES_HLEN;
-
-	if (hw_path->flags & FLOW_OFFLOAD_PATH_PPPOE)
-		eth = (struct ethhdr *)(skb->data - eth_pppoe_hlen);
-	else
-		eth = (struct ethhdr *)(skb->data - ETH_HLEN);
-
-	return eth;
-}
-
 static inline void hnat_get_filled_unbind_entry(struct sk_buff *skb,
 						struct foe_entry *entry)
 {
@@ -1663,7 +1613,6 @@
 	struct list_head *iter;
 	struct foe_entry entry = { 0 };
 	struct mtk_mac *mac;
-	struct ethhdr *eth;
 	struct iphdr *iph;
 	struct ipv6hdr *ip6h;
 	struct tcpudphdr _ports;
@@ -1679,18 +1628,10 @@
 	int mape = 0;
 	int ret;
 	int i = 0;
-
-	if (ipv6_hdr(skb)->nexthdr == NEXTHDR_IPIP)
-		/* point to ethernet header for DS-Lite and MapE */
-		eth = get_ipv6_ipip_ethhdr(skb, hw_path);
-	else if (ip_hdr(skb)->protocol == IPPROTO_IPV6)
-		/* 6RD LAN->WAN(6to4) */
-		eth = (struct ethhdr *)(skb->data - ETH_HLEN);
-	else
-		eth = eth_hdr(skb);
+	u16 h_proto = 0;
 
 	/*do not bind multicast if PPE mcast not enable*/
-	if (!hnat_priv->data->mcast && is_multicast_ether_addr(eth->h_dest))
+	if (!hnat_priv->data->mcast && is_multicast_ether_addr(hw_path->eth_dest))
 		return 0;
 
 	ret = hnat_offload_engine_done(skb, hw_path);
@@ -1711,7 +1652,14 @@
 	entry.bfib1.sp = foe->udib1.sp;
 #endif
 
-	switch (ntohs(eth->h_proto)) {
+	if (ip_hdr(skb)->version == IPVERSION_V4)
+		h_proto = ETH_P_IP;
+	else if (ip_hdr(skb)->version == IPVERSION_V6)
+		h_proto = ETH_P_IPV6;
+	else
+		return 0;
+
+	switch (h_proto) {
 	case ETH_P_IP:
 		iph = ip_hdr(skb);
 		/* Do not bind if pkt is fragmented */
@@ -2133,7 +2081,7 @@
 	}
 
 	/* Fill Layer2 Info.*/
-	entry = ppe_fill_L2_info(eth, entry, hw_path);
+	entry = ppe_fill_L2_info(entry, hw_path);
 
 	if ((skb_hnat_tops(skb) && hw_path->flags & FLOW_OFFLOAD_PATH_TNL) ||
 	    (!skb_hnat_cdrt(skb) && skb_hnat_is_encrypt(skb) &&
@@ -2142,7 +2090,7 @@
 
 hnat_entry_bind:
 	/* Fill Info Blk*/
-	entry = ppe_fill_info_blk(eth, entry, hw_path);
+	entry = ppe_fill_info_blk(entry, hw_path);
 
 	if (IS_LAN_GRP(dev) || IS_WAN(dev)) { /* Forward to GMAC Ports */
 		if (IS_BOND(dev)) {
@@ -2168,7 +2116,7 @@
 		port_id = hnat_dsa_get_port(&master_dev);
 		if (port_id >= 0) {
 			if (hnat_dsa_fill_stag(dev, &entry, hw_path,
-					       ntohs(eth->h_proto), mape) < 0)
+					       h_proto, mape) < 0)
 				return 0;
 		}
 
@@ -2226,7 +2174,7 @@
 		qid = 0;
 
 	if (IS_PPPQ_MODE && IS_PPPQ_PATH(dev, skb)) {
-		if (ntohs(eth->h_proto) == ETH_P_IP) {
+		if (h_proto == ETH_P_IP) {
 			iph = ip_hdr(skb);
 			if (iph->protocol == IPPROTO_TCP) {
 				skb_set_transport_header(skb, sizeof(struct iphdr));
@@ -2236,7 +2184,7 @@
 				if (payload_len == 0)
 					qid += 6;
 			}
-		} else if (ntohs(eth->h_proto) == ETH_P_IPV6) {
+		} else if (h_proto == ETH_P_IPV6) {
 			ip6h = ipv6_hdr(skb);
 			if (ip6h->nexthdr == NEXTHDR_TCP) {
 				skb_set_transport_header(skb, sizeof(struct ipv6hdr));
@@ -3318,9 +3266,14 @@
 		if (fn && !mtk_hnat_accel_type(skb))
 			break;
 
-		if (!is_virt_dev && fn && fn(skb, arp_dev, &hw_path))
-			break;
-
+		if (!is_virt_dev) {
+			if (!fn) {
+				memcpy(hw_path.eth_dest, eth_hdr(skb)->h_dest, ETH_ALEN);
+				memcpy(hw_path.eth_src, eth_hdr(skb)->h_source, ETH_ALEN);
+			} else if (fn(skb, arp_dev, &hw_path)) {
+				break;
+			}
+		}
 		/* skb_hnat_tops(skb) is updated in mtk_tnl_offload() */
 		if (skb_hnat_tops(skb)) {
 			if (skb_hnat_is_encap(skb) && !is_virt_dev &&
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
index 4d12010..21212b7 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
@@ -193,6 +193,8 @@
 #define HIT_PRE_BIND 0x1A
 #define HIT_BIND_PACKET_SAMPLING 0x1B
 #define HIT_BIND_EXCEED_MTU 0x1C
+#define IPVERSION_V4 0x04
+#define IPVERSION_V6 0x06
 
 #define TPORT_ID(x) ((x) & GENMASK(3, 0))
 #define TOPS_ENTRY(x) ((x) & GENMASK(5, 0))