[][Update dscp for qos by keepalive]

[Description]
Add Update dscp for qos by keepalive
Some programs will change dscp or other field in skb runtime,
so we need use keepalive packet to trigger clear entry.
Then hnat learn the complete new information.
And we also need to clear the cache to maintain consistency.

[Release-log]
N/A

Change-Id: Ide74c3ff63e6d4ac3ac529fe94790fc7b8127ce1
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/5140635
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 9863f13..edc97b6 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
@@ -1809,6 +1809,37 @@
 	return 1;
 }
 
+static void mtk_hnat_dscp_update(struct sk_buff *skb, struct foe_entry *entry)
+{
+	struct iphdr *iph;
+	struct ethhdr *eth;
+	struct ipv6hdr *ip6h;
+	bool flag = false;
+
+	eth = eth_hdr(skb);
+	switch (ntohs(eth->h_proto)) {
+	case ETH_P_IP:
+		iph = ip_hdr(skb);
+		if (entry->ipv4_hnapt.iblk2.dscp != iph->tos)
+			flag = true;
+		break;
+	case ETH_P_IPV6:
+		ip6h = ipv6_hdr(skb);
+		if (entry->ipv6_5t_route.iblk2.dscp !=
+			(ip6h->priority << 4 |
+			 (ip6h->flow_lbl[0] >> 4)))
+			flag = true;
+		break;
+	default:
+		return;
+	}
+
+	if (flag) {
+		memset(entry, 0, sizeof(struct foe_entry));
+		hnat_cache_ebl(1);
+	}
+}
+
 static unsigned int mtk_hnat_nf_post_routing(
 	struct sk_buff *skb, const struct net_device *out,
 	unsigned int (*fn)(struct sk_buff *, const struct net_device *,
@@ -1857,6 +1888,9 @@
 		if (fn && !mtk_hnat_accel_type(skb))
 			break;
 
+		/* update dscp for qos */
+		mtk_hnat_dscp_update(skb, entry);
+
 		/* update mcast timestamp*/
 		if (hnat_priv->data->version == MTK_HNAT_V3 &&
 		    hnat_priv->data->mcast && entry->bfib1.sta == 1)