[][kernel][common][hnat][Refactor entry fp and special tag assignment for handling DSA device]
[Description]
Refactor entry fp and special tag assignment for handling DSA device.
With this patch, driver would try to check if the netdevice
is a DSA slave device through linux kernel function rather than
using the device name "lan" as condition, can better support different
type of switch DSA.
[Release-log]
N/A
Change-Id: Ie171739d239b08134632266d69070d0350868a9f
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/9337220
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
index 4985dd7..c59e97e 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
@@ -17,6 +17,7 @@
#include <linux/string.h>
#include <linux/if.h>
#include <linux/if_ether.h>
+#include <net/dsa.h>
#include <net/netevent.h>
#include <net/netfilter/nf_conntrack_zones.h>
#include <linux/mod_devicetable.h>
@@ -1287,30 +1288,19 @@
hnat_set_entry_lock(entry, false);
}
-#if defined(CONFIG_NET_DSA_MT7530)
-u32 hnat_dsa_fill_stag(const struct net_device *netdev,
+int hnat_dsa_fill_stag(const struct net_device *netdev,
struct foe_entry *entry,
struct flow_offload_hw_path *hw_path,
u16 eth_proto, int mape);
-
+int hnat_dsa_get_port(struct net_device **dev);
static inline bool hnat_dsa_is_enable(struct mtk_hnat *priv)
{
+#if defined(CONFIG_NET_DSA)
return (priv->wan_dsa_port != NONE_DSA_PORT);
-}
#else
-static inline u32 hnat_dsa_fill_stag(const struct net_device *netdev,
- struct foe_entry *entry,
- struct flow_offload_hw_path *hw_path,
- u16 eth_proto, int mape)
-{
- return 0;
-}
-
-static inline bool hnat_dsa_is_enable(struct mtk_hnat *priv)
-{
return false;
-}
#endif
+}
void hnat_deinit_debugfs(struct mtk_hnat *h);
int hnat_init_debugfs(struct mtk_hnat *h);
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 e28b349..6960462 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
@@ -1234,8 +1234,10 @@
struct foe_entry *foe,
struct flow_offload_hw_path *hw_path)
{
+ struct net_device *master_dev = (struct net_device *)dev;
struct foe_entry entry = { 0 };
int whnat = IS_WHNAT(dev);
+ struct mtk_mac *mac;
struct ethhdr *eth;
struct iphdr *iph;
struct ipv6hdr *ip6h;
@@ -1245,11 +1247,10 @@
enum ip_conntrack_info ctinfo;
int gmac = NR_DISCARD;
int udp = 0;
+ int port_id = 0;
u32 qid = 0;
- u32 port_id = 0;
u32 payload_len = 0;
int mape = 0;
- struct mtk_mac *mac = netdev_priv(dev);
if (ipv6_hdr(skb)->nexthdr == NEXTHDR_IPIP)
/* point to ethernet header for DS-Lite and MapE */
@@ -1700,33 +1701,25 @@
/* Fill Info Blk*/
entry = ppe_fill_info_blk(eth, entry, hw_path);
- if (IS_LAN(dev)) {
- if (IS_BOND_MODE) {
- gmac = ((skb_hnat_entry(skb) >> 1) % hnat_priv->gmac_num) ?
- NR_GMAC2_PORT : NR_GMAC1_PORT;
- } else if (IS_DSA_LAN(dev)) {
- port_id = hnat_dsa_fill_stag(dev, &entry, hw_path,
- ntohs(eth->h_proto),
- mape);
- gmac = NR_GMAC1_PORT;
- } else {
- gmac = HNAT_GMAC_FP(mac->id);
+ if (IS_LAN_GRP(dev) || IS_WAN(dev)) { /* Forward to GMAC Ports */
+ 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)
+ return 0;
}
- } else if (IS_LAN2(dev)) {
+
+ mac = netdev_priv(master_dev);
gmac = HNAT_GMAC_FP(mac->id);
- } else if (IS_WAN(dev)) {
- if (mape_toggle && mape == 1) {
+
+ if (IS_LAN(dev) && IS_BOND_MODE) {
+ gmac = ((skb_hnat_entry(skb) >> 1) % hnat_priv->gmac_num) ?
+ NR_GMAC2_PORT : NR_GMAC1_PORT;
+ } else if (IS_WAN(dev) && mape_toggle && mape == 1) {
gmac = NR_PDMA_PORT;
/* Set act_dp = wan_dev */
entry.ipv4_hnapt.act_dp &= ~UDF_PINGPONG_IFIDX;
entry.ipv4_hnapt.act_dp |= dev->ifindex & UDF_PINGPONG_IFIDX;
- } else if (IS_DSA_WAN(dev)) {
- port_id = hnat_dsa_fill_stag(dev, &entry, hw_path,
- ntohs(eth->h_proto),
- mape);
- gmac = NR_GMAC1_PORT;
- } else {
- gmac = HNAT_GMAC_FP(mac->id);
}
} else if (IS_EXT(dev) && (FROM_GE_PPD(skb) || FROM_GE_LAN_GRP(skb) ||
FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb) || FROM_WED(skb))) {
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_stag.c b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_stag.c
index 75c3a75..d8e5709 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_stag.c
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_stag.c
@@ -6,58 +6,77 @@
#include <linux/of_device.h>
#include <net/netfilter/nf_flow_table.h>
+
#include "hnat.h"
+int hnat_dsa_get_port(struct net_device **dev)
+{
+#if defined(CONFIG_NET_DSA)
+ struct dsa_port *dp;
+
+ dp = dsa_port_from_netdev(*dev);
+ if (IS_ERR(dp))
+ return -ENODEV;
+
+ *dev = dp->cpu_dp->master;
+
+ return dp->index;
+#else
+ return -ENODEV;
+#endif
+}
+
-u32 hnat_dsa_fill_stag(const struct net_device *netdev,
+int hnat_dsa_fill_stag(const struct net_device *netdev,
struct foe_entry *entry,
struct flow_offload_hw_path *hw_path,
u16 eth_proto,
int mape)
{
- const struct net_device *ndev;
+#if defined(CONFIG_NET_DSA)
const unsigned int *port_reg;
+ const struct dsa_port *dp;
+ struct net_device *ndev;
int port_index;
- u16 sp_tag;
+ u16 dsa_tag;
if (hw_path->flags & FLOW_OFFLOAD_PATH_VLAN)
ndev = hw_path->dev;
else
- ndev = netdev;
+ ndev = (struct net_device *)netdev;
port_reg = of_get_property(ndev->dev.of_node, "reg", NULL);
if (unlikely(!port_reg))
return -EINVAL;
port_index = be32_to_cpup(port_reg);
- sp_tag = BIT(port_index);
+
+ /* In the case MAPE LAN --> WAN, binding entry is to CPU.
+ * Do not add special tag.
+ */
+ if (IS_WAN(ndev) && mape)
+ return port_index;
+
+ dp = dsa_port_from_netdev(ndev);
+ if (IS_ERR(dp))
+ return -ENODEV;
+
+ dsa_tag = BIT(port_index);
if (!entry->bfib1.vlan_layer)
entry->bfib1.vlan_layer = 1;
else
/* VLAN existence indicator */
- sp_tag |= BIT(8);
- entry->bfib1.vpm = 0;
+ dsa_tag |= BIT(8);
- switch (eth_proto) {
- case ETH_P_IP:
- 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;
- break;
- case ETH_P_IPV6:
- /* In the case MAPE LAN --> WAN, binding entry is to CPU.
- * Do not add special tag.
- */
- if (!mape)
- /* etype offset of ipv6 entries are the same. */
- entry->ipv6_5t_route.etype = sp_tag;
+ if (IS_IPV4_GRP(entry))
+ entry->ipv4_hnapt.etype = dsa_tag;
+ else
+ entry->ipv6_5t_route.etype = dsa_tag;
- break;
- default:
- pr_info("DSA + HNAT unsupport protocol\n");
- }
+ entry->bfib1.vpm = 0;
return port_index;
+#else
+ return -EINVAL;
+#endif
}