[][Suppport MAPE binding HNAT]
[Description]
Fix software to support MAPE binding HNAT
[Release-log]
N/A
Change-Id: Ia47c403b42417641f7b719ebc717d4e60f200bac
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/5936389
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
index 69f1c21..d4b9b63 100644
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
@@ -1950,20 +1950,35 @@
size_t count, loff_t *data)
{
char buf = 0;
- int len = count;
-
- if (copy_from_user(&buf, buffer, len))
+ int i;
+ u32 ppe_cfg;
+
+ if ((count < 1) || copy_from_user(&buf, buffer, sizeof(buf)))
return -EFAULT;
- if (buf == '1' && !mape_toggle) {
+ if (buf == '1') {
pr_info("mape is going to be enabled, ds-lite is going to be disabled !\n");
mape_toggle = 1;
- } else if (buf == '0' && mape_toggle) {
+ } else if (buf == '0') {
pr_info("ds-lite is going to be enabled, mape is going to be disabled !\n");
mape_toggle = 0;
+ } else {
+ pr_info("Invalid parameter.\n");
+ return -EFAULT;
+ }
+
+ for (i = 0; i < CFG_PPE_NUM; i++) {
+ ppe_cfg = readl(hnat_priv->ppe_base[i] + PPE_FLOW_CFG);
+
+ if (mape_toggle)
+ ppe_cfg &= ~BIT_IPV4_DSL_EN;
+ else
+ ppe_cfg |= BIT_IPV4_DSL_EN;
+
+ writel(ppe_cfg, hnat_priv->ppe_base[i] + PPE_FLOW_CFG);
}
- return len;
+ return count;
}
static const struct file_operations hnat_mape_toggle_fops = {
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 2df6d14..794f55b 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
@@ -608,6 +608,13 @@
}
}
+static void ppe_fill_flow_lbl(struct foe_entry *entry, struct ipv6hdr *ip6h)
+{
+ entry->ipv4_dslite.flow_lbl[0] = ip6h->flow_lbl[2];
+ entry->ipv4_dslite.flow_lbl[1] = ip6h->flow_lbl[1];
+ entry->ipv4_dslite.flow_lbl[2] = ip6h->flow_lbl[0];
+}
+
unsigned int do_hnat_mape_w2l_fast(struct sk_buff *skb, const struct net_device *in,
const char *func)
{
@@ -660,6 +667,74 @@
return -1;
}
+unsigned int do_hnat_mape_wan2lan(struct sk_buff *skb, const struct net_device *in,
+ const char *func)
+{
+ struct ipv6hdr *ip6h = ipv6_hdr(skb);
+ struct iphdr _iphdr;
+ struct iphdr *iph;
+ struct foe_entry *entry;
+ struct tcpudphdr _ports;
+ const struct tcpudphdr *pptr;
+ int udp = 0;
+
+ /* WAN -> LAN/WLAN MapE learn info(include innner IPv4 header info). */
+ if (ip6h->nexthdr == NEXTHDR_IPIP) {
+ entry = &hnat_priv->foe_table_cpu[skb_hnat_ppe(skb)][skb_hnat_entry(skb)];
+
+ entry->ipv4_dslite.tunnel_sipv6_0 =
+ ntohl(ip6h->saddr.s6_addr32[0]);
+ entry->ipv4_dslite.tunnel_sipv6_1 =
+ ntohl(ip6h->saddr.s6_addr32[1]);
+ entry->ipv4_dslite.tunnel_sipv6_2 =
+ ntohl(ip6h->saddr.s6_addr32[2]);
+ entry->ipv4_dslite.tunnel_sipv6_3 =
+ ntohl(ip6h->saddr.s6_addr32[3]);
+
+ entry->ipv4_dslite.tunnel_dipv6_0 =
+ ntohl(ip6h->daddr.s6_addr32[0]);
+ entry->ipv4_dslite.tunnel_dipv6_1 =
+ ntohl(ip6h->daddr.s6_addr32[1]);
+ entry->ipv4_dslite.tunnel_dipv6_2 =
+ ntohl(ip6h->daddr.s6_addr32[2]);
+ entry->ipv4_dslite.tunnel_dipv6_3 =
+ ntohl(ip6h->daddr.s6_addr32[3]);
+
+ ppe_fill_flow_lbl(entry, ip6h);
+
+ iph = skb_header_pointer(skb, IPV6_HDR_LEN,
+ sizeof(_iphdr), &_iphdr);
+ if (unlikely(!iph))
+ return NF_ACCEPT;
+
+ switch (iph->protocol) {
+ case IPPROTO_UDP:
+ udp = 1;
+ case IPPROTO_TCP:
+ break;
+
+ default:
+ return NF_ACCEPT;
+ }
+
+ pptr = skb_header_pointer(skb, IPV6_HDR_LEN + iph->ihl * 4,
+ sizeof(_ports), &_ports);
+ if (unlikely(!pptr))
+ return NF_ACCEPT;
+
+ entry->bfib1.udp = udp;
+
+ entry->ipv4_dslite.new_sip = ntohl(iph->saddr);
+ entry->ipv4_dslite.new_dip = ntohl(iph->daddr);
+ entry->ipv4_dslite.new_sport = ntohs(pptr->src);
+ entry->ipv4_dslite.new_dport = ntohs(pptr->dst);
+
+ return 0;
+ }
+ return -1;
+}
+
+
static unsigned int is_ppe_support_type(struct sk_buff *skb)
{
struct ethhdr *eth = NULL;
@@ -744,10 +819,15 @@
/* MapE need remove ipv6 header and pingpong. */
if (do_mape_w2l_fast(state->in, skb)) {
+#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+ if (mape_toggle && do_hnat_mape_wan2lan(skb, state->in, __func__))
+ return NF_ACCEPT;
+#else
if (!do_hnat_mape_w2l_fast(skb, state->in, __func__))
return NF_STOLEN;
else
return NF_ACCEPT;
+#endif
}
if (is_from_mape(skb))
@@ -1079,13 +1159,6 @@
return entry;
}
-static void ppe_fill_flow_lbl(struct foe_entry *entry, struct ipv6hdr *ip6h)
-{
- entry->ipv4_dslite.flow_lbl[0] = ip6h->flow_lbl[2];
- entry->ipv4_dslite.flow_lbl[1] = ip6h->flow_lbl[1];
- entry->ipv4_dslite.flow_lbl[2] = ip6h->flow_lbl[0];
-}
-
static unsigned int skb_to_hnat_info(struct sk_buff *skb,
const struct net_device *dev,
struct foe_entry *foe,
@@ -1341,6 +1414,16 @@
entry.ipv4_dslite.vlan1 = hw_path->vlan_id;
if (hnat_priv->data->per_flow_accounting)
entry.ipv4_dslite.iblk2.mibf = 1;
+ /* Map-E LAN->WAN record inner IPv4 header info. */
+#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+ if (mape_toggle) {
+ entry.ipv4_dslite.iblk2.dscp = foe->ipv4_dslite.iblk2.dscp;
+ entry.ipv4_dslite.new_sip = foe->ipv4_dslite.new_sip;
+ entry.ipv4_dslite.new_dip = foe->ipv4_dslite.new_dip;
+ entry.ipv4_dslite.new_sport = foe->ipv4_dslite.new_sport;
+ entry.ipv4_dslite.new_dport = foe->ipv4_dslite.new_dport;
+ }
+#endif
} else if (mape_toggle &&
entry.bfib1.pkt_type == IPV4_HNAPT) {
/* MapE LAN -> WAN */
@@ -2025,6 +2108,7 @@
entry->bfib1.udp = udp;
+ /* Map-E LAN->WAN record inner IPv4 header info. */
#if defined(CONFIG_MEDIATEK_NETSYS_V2)
entry->bfib1.pkt_type = IPV4_MAP_E;
entry->ipv4_dslite.iblk2.dscp = iph->tos;
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_stag.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_stag.c
index 73de3e9..75c3a75 100644
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_stag.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_stag.c
@@ -40,7 +40,8 @@
switch (eth_proto) {
case ETH_P_IP:
- if (entry->ipv4_hnapt.bfib1.pkt_type == IPV4_DSLITE)
+ if (entry->ipv4_hnapt.bfib1.pkt_type == IPV4_DSLITE
+ || (entry->ipv4_hnapt.bfib1.pkt_type == IPV4_MAP_E))
entry->ipv4_dslite.etype = sp_tag;
else
entry->ipv4_hnapt.etype = sp_tag;