[][kernel][mt7987][hnat][Add L2 BRIDGE HNAT support for the NETSYSv3.1]
[Description]
Add L2 BRIDGE HNAT support for MT7987
- Add l2br_toggle in debugfs to control function of L2 BRIDGE.
echo 0 > /sys/kernel/debug/hnat/l2br_toggle
* Disable L2 HNAT functions.
echo 1 > /sys/kernel/debug/hnat/l2br_toggle
* Enable L2_BRIDGE HNAT learning mode.
* PPE automatically learns and creates new L2_BRIDGE entries.
echo 2 > /sys/kernel/debug/hnat/l2br_toggle
* Enable L2_BRIDGE HNAT look-up mode.
* For L2 packet, PPE only checks existing L2_BRIDGE entries
without creating new ones.
* Normally for static entry usage.
- Add support in debugfs to dump L2_BRIDGE HNAT info
- Add support in debugfs to add L2_BRIDGE static entry
[Release-log]
N/A
Change-Id: I129c3196304318a8be9f806701de64d39c0c3b80
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/9750534
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
index e9508eb..40d2aec 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
@@ -119,7 +119,7 @@
mod_timer(&hnat_priv->hnat_reset_timestamp_timer, jiffies + 14400 * HZ);
}
-static void cr_set_bits(void __iomem *reg, u32 bs)
+void cr_set_bits(void __iomem *reg, u32 bs)
{
u32 val = readl(reg);
@@ -127,7 +127,7 @@
writel(val, reg);
}
-static void cr_clr_bits(void __iomem *reg, u32 bs)
+void cr_clr_bits(void __iomem *reg, u32 bs)
{
u32 val = readl(reg);
@@ -581,6 +581,7 @@
if (hnat_priv->data->version == MTK_HNAT_V3)
cr_set_bits(hnat_priv->ppe_base[ppe_id] + PPE_FLOW_CFG,
+ BIT_L2_HASH_VID | BIT_L2_HASH_ETH |
BIT_IPV6_NAT_EN | BIT_IPV6_NAPT_EN |
BIT_CS0_RM_ALL_IP6_IP_EN);
@@ -785,6 +786,7 @@
if (hnat_priv->data->version == MTK_HNAT_V3)
cr_clr_bits(hnat_priv->ppe_base[ppe_id] + PPE_FLOW_CFG,
+ BIT_L2_HASH_VID | BIT_L2_HASH_ETH |
BIT_IPV6_NAT_EN | BIT_IPV6_NAPT_EN |
BIT_CS0_RM_ALL_IP6_IP_EN);
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 0393c10..422c83a 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
@@ -337,6 +337,48 @@
u32 dscp : 8; /* DSCP value */
} __packed;
+struct hnat_l2_bridge {
+ union {
+ struct hnat_bind_info_blk bfib1;
+ struct hnat_unbind_info_blk udib1;
+ u32 info_blk1;
+ };
+ u32 dmac_hi;
+ u16 smac_lo;
+ u16 dmac_lo;
+ u32 smac_hi;
+ u16 etype;
+ u16 hph; /* hash placeholder */
+ u16 vlan1;
+ u16 vlan2;
+ u32 resv1;
+ u32 resv2;
+ union {
+ struct hnat_info_blk2 iblk2;
+ struct hnat_info_blk2_whnat iblk2w;
+ u32 info_blk2;
+ };
+ u32 resv3;
+ u32 resv4 : 24;
+ u32 act_dp : 8; /* UDF */
+ u16 new_vlan1;
+ u16 sp_tag;
+ u32 new_dmac_hi;
+ u16 new_vlan2;
+ u16 new_dmac_lo;
+ u32 new_smac_hi;
+ u16 resv5;
+ u16 new_smac_lo;
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+ u32 resv6;
+ struct hnat_winfo winfo;
+ struct hnat_winfo_pao winfo_pao;
+#elif defined(CONFIG_MEDIATEK_NETSYS_V2)
+ u16 minfo;
+ struct hnat_winfo winfo;
+#endif
+} __packed;
+
struct hnat_ipv4_hnapt {
union {
struct hnat_bind_info_blk bfib1;
@@ -369,7 +411,7 @@
#endif
u32 act_dp : 8; /* UDF */
u16 vlan1;
- u16 etype;
+ u16 sp_tag;
u32 dmac_hi;
union {
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -438,7 +480,7 @@
};
u16 vlan1;
- u16 etype;
+ u16 sp_tag;
u32 dmac_hi;
union {
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -507,7 +549,7 @@
};
u16 vlan1;
- u16 etype;
+ u16 sp_tag;
u32 dmac_hi;
union {
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -579,7 +621,7 @@
u32 info_blk2;
};
u16 vlan1;
- u16 etype;
+ u16 sp_tag;
u32 dmac_hi;
union {
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -644,7 +686,7 @@
};
u16 vlan1;
- u16 etype;
+ u16 sp_tag;
u32 dmac_hi;
union {
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -717,7 +759,7 @@
};
u16 vlan1;
- u16 etype;
+ u16 sp_tag;
u32 dmac_hi;
union {
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -779,7 +821,7 @@
};
u16 vlan1;
- u16 etype;
+ u16 sp_tag;
u32 dmac_hi;
u16 vlan2;
u16 dmac_lo;
@@ -815,6 +857,7 @@
union {
struct hnat_unbind_info_blk udib1;
struct hnat_bind_info_blk bfib1;
+ struct hnat_l2_bridge l2_bridge;
struct hnat_ipv4_hnapt ipv4_hnapt;
struct hnat_ipv4_dslite ipv4_dslite;
struct hnat_ipv4_mape ipv4_mape;
@@ -955,6 +998,7 @@
enum FoeIpAct {
IPV4_HNAPT = 0,
IPV4_HNAT = 1,
+ L2_BRIDGE = 2,
IPV4_DSLITE = 3,
IPV6_3T_ROUTE = 4,
IPV6_5T_ROUTE = 5,
@@ -1003,6 +1047,7 @@
#define BIT_IPV4_NAT_EN BIT(12)
#define BIT_IPV4_NAPT_EN BIT(13)
#define BIT_IPV4_DSL_EN BIT(14)
+#define BIT_L2_BRG_EN BIT(15)
#define BIT_MIB_BUSY BIT(16)
#define BIT_IPV4_NAT_FRAG_EN BIT(17)
#define BIT_IPV4_HASH_GREK BIT(19)
@@ -1012,6 +1057,9 @@
#define BIT_IPV6_NAT_EN BIT(23)
#define BIT_IPV6_NAPT_EN BIT(24)
#define BIT_CS0_RM_ALL_IP6_IP_EN BIT(25)
+#define BIT_L2_HASH_ETH BIT(29)
+#define BIT_L2_HASH_VID BIT(30)
+#define BIT_L2_LRN_EN BIT(31)
/*GDMA_FWD_CFG value*/
#define BITS_GDM_UFRC_P_PPE (NR_PPE0_PORT << 12)
@@ -1151,6 +1199,7 @@
(get_wifi_hook_if_index_from_dev(dev) != 0)) ? 1 : 0)
#define IS_EXT(dev) ((get_index_from_dev(dev) != 0) ? 1 : 0)
#define IS_PPD(dev) (!strcmp(dev->name, hnat_priv->ppd))
+#define IS_L2_BRIDGE(x) (((x)->bfib1.pkt_type == L2_BRIDGE) ? 1 : 0)
#define IS_IPV4_HNAPT(x) (((x)->bfib1.pkt_type == IPV4_HNAPT) ? 1 : 0)
#define IS_IPV4_HNAT(x) (((x)->bfib1.pkt_type == IPV4_HNAT) ? 1 : 0)
#define IS_IPV4_GRP(x) (IS_IPV4_HNAPT(x) | IS_IPV4_HNAT(x))
@@ -1237,7 +1286,7 @@
{
u32 udf = 0;
- if (IS_IPV4_GRP(entry))
+ if (IS_IPV4_GRP(entry) || IS_L2_BRIDGE(entry))
udf = entry->ipv4_hnapt.act_dp;
else
udf = entry->ipv6_5t_route.act_dp;
@@ -1247,7 +1296,7 @@
static inline void hnat_set_entry_lock(struct foe_entry *entry, bool locked)
{
- if (IS_IPV4_GRP(entry)) {
+ if (IS_IPV4_GRP(entry) || IS_L2_BRIDGE(entry)) {
if (locked)
entry->ipv4_hnapt.act_dp |= UDF_HNAT_ENTRY_LOCKED;
else
@@ -1300,6 +1349,7 @@
extern int hook_toggle;
extern int mape_toggle;
extern int qos_toggle;
+extern int l2br_toggle;
extern int tnl_toggle;
extern int (*mtk_tnl_encap_offload)(struct sk_buff *skb, struct ethhdr *eth);
extern int (*mtk_tnl_decap_offload)(struct sk_buff *skb);
@@ -1310,6 +1360,8 @@
int fill_inner_info);
int ext_if_add(struct extdev_entry *ext_entry);
int ext_if_del(struct extdev_entry *ext_entry);
+void cr_set_bits(void __iomem *reg, u32 bs);
+void cr_clr_bits(void __iomem *reg, u32 bs);
void cr_set_field(void __iomem *reg, u32 field, u32 val);
int mtk_sw_nat_hook_tx(struct sk_buff *skb, int gmac_no);
int mtk_sw_nat_hook_rx(struct sk_buff *skb);
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
index 38838a4..20141da 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
@@ -39,13 +39,14 @@
int qos_ul_toggle = 1;
int tnl_toggle;
int xlat_toggle;
+int l2br_toggle;
struct hnat_desc headroom[DEF_ETRY_NUM];
unsigned int dbg_cpu_reason_cnt[MAX_CRSN_NUM];
static const char * const entry_state[] = { "INVALID", "UNBIND", "BIND", "FIN" };
static const char * const packet_type[] = {
- "IPV4_HNAPT", "IPV4_HNAT", "IPV6_1T_ROUTE", "IPV4_DSLITE",
+ "IPV4_HNAPT", "IPV4_HNAT", "L2_BRIDGE", "IPV4_DSLITE",
"IPV6_3T_ROUTE", "IPV6_5T_ROUTE", "REV", "IPV6_6RD",
"IPV4_MAP_T", "IPV4_MAP_E", "IPV6_HNAPT", "IPV6_HNAT",
};
@@ -371,6 +372,8 @@
u32 print_cnt;
unsigned char h_dest[ETH_ALEN];
unsigned char h_source[ETH_ALEN];
+ unsigned char new_h_dest[ETH_ALEN];
+ unsigned char new_h_source[ETH_ALEN];
__be32 saddr, daddr, nsaddr, ndaddr;
if (ppe_id >= CFG_PPE_NUM)
@@ -588,6 +591,13 @@
entry->ipv6_hnapt.new_ipv6_ip2,
entry->ipv6_hnapt.new_ipv6_ip3);
}
+ } else if (IS_L2_BRIDGE(entry)) {
+ pr_info("Information Block 2: %08X (FP=%d FQOS=%d QID=%d)",
+ entry->l2_bridge.info_blk2,
+ entry->l2_bridge.iblk2.dp,
+ entry->l2_bridge.iblk2.fqos,
+ entry->l2_bridge.iblk2.qid);
+ pr_info("Create L2 BRIDGE entry\n");
#endif
}
@@ -603,8 +613,8 @@
"BIND" : entry->bfib1.state == 3 ?
"FIN" : "Unknown");
pr_info("Vlan_Layer = %u, ", entry->bfib1.vlan_layer);
- pr_info("Eth_type = 0x%x, Vid1 = 0x%x, Vid2 = 0x%x\n",
- entry->ipv4_hnapt.etype, entry->ipv4_hnapt.vlan1,
+ pr_info("SP_TAG = 0x%x, Vid1 = 0x%x, Vid2 = 0x%x\n",
+ entry->ipv4_hnapt.sp_tag, entry->ipv4_hnapt.vlan1,
entry->ipv4_hnapt.vlan2);
pr_info("multicast = %d, pppoe = %d, proto = %s\n",
entry->ipv4_hnapt.iblk2.mcast,
@@ -628,6 +638,32 @@
entry->ipv4_hnapt.winfo_pao.is_sp);
#endif
pr_info("=========================================\n\n");
+ } else if (IS_L2_BRIDGE(entry)) {
+ *((u32 *)h_source) = swab32(entry->l2_bridge.smac_hi);
+ *((u16 *)&h_source[4]) = swab16(entry->l2_bridge.smac_lo);
+ *((u32 *)h_dest) = swab32(entry->l2_bridge.dmac_hi);
+ *((u16 *)&h_dest[4]) = swab16(entry->l2_bridge.dmac_lo);
+ *((u32 *)new_h_source) = swab32(entry->l2_bridge.new_smac_hi);
+ *((u16 *)&new_h_source[4]) = swab16(entry->l2_bridge.new_smac_lo);
+ *((u32 *)new_h_dest) = swab32(entry->l2_bridge.new_dmac_hi);
+ *((u16 *)&new_h_dest[4]) = swab16(entry->l2_bridge.new_dmac_lo);
+ pr_info("Org SMAC=%pM => DMAC=%pM\n", h_source, h_dest);
+ pr_info("New SMAC=%pM => DMAC=%pM\n", new_h_source, new_h_dest);
+ pr_info("Eth_type = 0x%04x, Vid1 = 0x%x, Vid2 = 0x%x\n",
+ entry->l2_bridge.etype, entry->l2_bridge.vlan1,
+ entry->l2_bridge.vlan2);
+ pr_info("State = %s, ", entry->bfib1.state == 0 ?
+ "Invalid" : entry->bfib1.state == 1 ?
+ "Unbind" : entry->bfib1.state == 2 ?
+ "BIND" : entry->bfib1.state == 3 ?
+ "FIN" : "Unknown");
+ pr_info("DR_IDX = %x\n", entry->l2_bridge.iblk2.rxid);
+ pr_info("Vlan_Layer = %u, ", entry->bfib1.vlan_layer);
+ pr_info("SP_TAG = 0x%04x, New_Vid1 = 0x%x, New_Vid2 = 0x%x\n",
+ entry->l2_bridge.sp_tag, entry->l2_bridge.new_vlan1,
+ entry->l2_bridge.new_vlan2);
+ pr_info("multicast = %d\n", entry->l2_bridge.iblk2.mcast);
+ pr_info("=========================================\n\n");
} else {
*((u32 *)h_source) = swab32(entry->ipv6_5t_route.smac_hi);
*((u16 *)&h_source[4]) = swab16(entry->ipv6_5t_route.smac_lo);
@@ -641,8 +677,8 @@
"FIN" : "Unknown");
pr_info("Vlan_Layer = %u, ", entry->bfib1.vlan_layer);
- pr_info("Eth_type = 0x%x, Vid1 = 0x%x, Vid2 = 0x%x\n",
- entry->ipv6_5t_route.etype, entry->ipv6_5t_route.vlan1,
+ pr_info("SP_TAG = 0x%x, Vid1 = 0x%x, Vid2 = 0x%x\n",
+ entry->ipv6_5t_route.sp_tag, entry->ipv6_5t_route.vlan1,
entry->ipv6_5t_route.vlan2);
pr_info("multicast = %d, pppoe = %d, proto = %s\n",
entry->ipv6_5t_route.iblk2.mcast,
@@ -1185,14 +1221,14 @@
swab16(entry->ipv4_hnapt.dmac_lo);
PRINT_COUNT(m, acct);
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|%pI4:%d->%pI4:%d=>%pI4:%d->%pI4:%d|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|%pI4:%d->%pI4:%d=>%pI4:%d->%pI4:%d|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
entry, ppe_id, ei(entry, end),
es(entry), pt(entry), &saddr,
entry->ipv4_hnapt.sport, &daddr,
entry->ipv4_hnapt.dport, &nsaddr,
entry->ipv4_hnapt.new_sport, &ndaddr,
entry->ipv4_hnapt.new_dport, h_source, h_dest,
- ntohs(entry->ipv4_hnapt.etype),
+ ntohs(entry->ipv4_hnapt.sp_tag),
entry->ipv4_hnapt.info_blk1,
entry->ipv4_hnapt.info_blk2,
entry->ipv4_hnapt.vlan1,
@@ -1211,11 +1247,11 @@
swab16(entry->ipv4_hnapt.dmac_lo);
PRINT_COUNT(m, acct);
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|%pI4->%pI4=>%pI4->%pI4|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|%pI4->%pI4=>%pI4->%pI4|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
entry, ppe_id, ei(entry, end),
es(entry), pt(entry), &saddr,
&daddr, &nsaddr, &ndaddr, h_source, h_dest,
- ntohs(entry->ipv4_hnapt.etype),
+ ntohs(entry->ipv4_hnapt.sp_tag),
entry->ipv4_hnapt.info_blk1,
entry->ipv4_hnapt.info_blk2,
entry->ipv4_hnapt.vlan1,
@@ -1239,13 +1275,13 @@
swab16(entry->ipv6_5t_route.dmac_lo);
PRINT_COUNT(m, acct);
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x\n",
entry, ppe_id, ei(entry, end), es(entry), pt(entry), ipv6_sip0,
ipv6_sip1, ipv6_sip2, ipv6_sip3,
entry->ipv6_5t_route.sport, ipv6_dip0,
ipv6_dip1, ipv6_dip2, ipv6_dip3,
entry->ipv6_5t_route.dport, h_source, h_dest,
- ntohs(entry->ipv6_5t_route.etype),
+ ntohs(entry->ipv6_5t_route.sp_tag),
entry->ipv6_5t_route.info_blk1,
entry->ipv6_5t_route.info_blk2);
} else if (IS_IPV6_3T_ROUTE(entry)) {
@@ -1267,12 +1303,12 @@
swab16(entry->ipv6_5t_route.dmac_lo);
PRINT_COUNT(m, acct);
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x->DIP=%08x:%08x:%08x:%08x|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x->DIP=%08x:%08x:%08x:%08x|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x\n",
entry, ppe_id, ei(entry, end),
es(entry), pt(entry), ipv6_sip0,
ipv6_sip1, ipv6_sip2, ipv6_sip3, ipv6_dip0,
ipv6_dip1, ipv6_dip2, ipv6_dip3, h_source,
- h_dest, ntohs(entry->ipv6_5t_route.etype),
+ h_dest, ntohs(entry->ipv6_5t_route.sp_tag),
entry->ipv6_5t_route.info_blk1,
entry->ipv6_5t_route.info_blk2);
} else if (IS_IPV6_6RD(entry)) {
@@ -1296,7 +1332,7 @@
swab16(entry->ipv6_5t_route.dmac_lo);
PRINT_COUNT(m, acct);
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|TSIP=%pI4->TDIP=%pI4|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|TSIP=%pI4->TDIP=%pI4|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x\n",
entry, ppe_id, ei(entry, end),
es(entry), pt(entry), ipv6_sip0,
ipv6_sip1, ipv6_sip2, ipv6_sip3,
@@ -1304,7 +1340,7 @@
ipv6_dip1, ipv6_dip2, ipv6_dip3,
entry->ipv6_5t_route.dport, &tsaddr, &tdaddr,
h_source, h_dest,
- ntohs(entry->ipv6_5t_route.etype),
+ ntohs(entry->ipv6_5t_route.sp_tag),
entry->ipv6_5t_route.info_blk1,
entry->ipv6_5t_route.info_blk2);
#if defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -1332,7 +1368,7 @@
if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_SNAT) {
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|NEW_SIP=%08x:%08x:%08x:%08x(sp=%d)->NEW_DIP=%08x:%08x:%08x:%08x(dp=%d)|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|NEW_SIP=%08x:%08x:%08x:%08x(sp=%d)->NEW_DIP=%08x:%08x:%08x:%08x(dp=%d)|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
entry, ppe_id, ei(entry, end),
es(entry), pt(entry),
ipv6_sip0, ipv6_sip1,
@@ -1348,14 +1384,14 @@
ipv6_dip2, ipv6_dip3,
entry->ipv6_hnapt.new_dport,
h_source, h_dest,
- ntohs(entry->ipv6_hnapt.etype),
+ ntohs(entry->ipv6_hnapt.sp_tag),
entry->ipv6_hnapt.info_blk1,
entry->ipv6_hnapt.info_blk2,
entry->ipv6_hnapt.vlan1,
entry->ipv6_hnapt.vlan2);
} else if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_DNAT) {
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|NEW_SIP=%08x:%08x:%08x:%08x(sp=%d)->NEW_DIP=%08x:%08x:%08x:%08x(dp=%d)|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|NEW_SIP=%08x:%08x:%08x:%08x(sp=%d)->NEW_DIP=%08x:%08x:%08x:%08x(dp=%d)|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
entry, ppe_id, ei(entry, end),
es(entry), pt(entry),
ipv6_sip0, ipv6_sip1,
@@ -1371,7 +1407,7 @@
new_ipv6_ip2, new_ipv6_ip3,
entry->ipv6_hnapt.new_dport,
h_source, h_dest,
- ntohs(entry->ipv6_hnapt.etype),
+ ntohs(entry->ipv6_hnapt.sp_tag),
entry->ipv6_hnapt.info_blk1,
entry->ipv6_hnapt.info_blk2,
entry->ipv6_hnapt.vlan1,
@@ -1401,7 +1437,7 @@
if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_SNAT) {
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x->DIP=%08x:%08x:%08x:%08x|NEW_SIP=%08x:%08x:%08x:%08x->NEW_DIP=%08x:%08x:%08x:%08x|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x->DIP=%08x:%08x:%08x:%08x|NEW_SIP=%08x:%08x:%08x:%08x->NEW_DIP=%08x:%08x:%08x:%08x|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
entry, ppe_id, ei(entry, end),
es(entry), pt(entry),
ipv6_sip0, ipv6_sip1,
@@ -1413,14 +1449,14 @@
ipv6_dip0, ipv6_dip1,
ipv6_dip2, ipv6_dip3,
h_source, h_dest,
- ntohs(entry->ipv6_hnapt.etype),
+ ntohs(entry->ipv6_hnapt.sp_tag),
entry->ipv6_hnapt.info_blk1,
entry->ipv6_hnapt.info_blk2,
entry->ipv6_hnapt.vlan1,
entry->ipv6_hnapt.vlan2);
} else if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_DNAT) {
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x->DIP=%08x:%08x:%08x:%08x|NEW_SIP=%08x:%08x:%08x:%08x->NEW_DIP=%08x:%08x:%08x:%08x|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x->DIP=%08x:%08x:%08x:%08x|NEW_SIP=%08x:%08x:%08x:%08x->NEW_DIP=%08x:%08x:%08x:%08x|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
entry, ppe_id, ei(entry, end),
es(entry), pt(entry),
ipv6_sip0, ipv6_sip1,
@@ -1432,12 +1468,44 @@
new_ipv6_ip0, new_ipv6_ip1,
new_ipv6_ip2, new_ipv6_ip3,
h_source, h_dest,
- ntohs(entry->ipv6_hnapt.etype),
+ ntohs(entry->ipv6_hnapt.sp_tag),
entry->ipv6_hnapt.info_blk1,
entry->ipv6_hnapt.info_blk2,
entry->ipv6_hnapt.vlan1,
entry->ipv6_hnapt.vlan2);
}
+ } else if (IS_L2_BRIDGE(entry)) {
+ unsigned char new_h_dest[ETH_ALEN];
+ unsigned char new_h_source[ETH_ALEN];
+
+ *((u32 *)h_source) = swab32(entry->l2_bridge.smac_hi);
+ *((u16 *)&h_source[4]) =
+ swab16(entry->l2_bridge.smac_lo);
+ *((u32 *)h_dest) = swab32(entry->l2_bridge.dmac_hi);
+ *((u16 *)&h_dest[4]) =
+ swab16(entry->l2_bridge.dmac_lo);
+
+ *((u32 *)new_h_source) = swab32(entry->l2_bridge.new_smac_hi);
+ *((u16 *)&new_h_source[4]) =
+ swab16(entry->l2_bridge.new_smac_lo);
+ *((u32 *)new_h_dest) = swab32(entry->l2_bridge.new_dmac_hi);
+ *((u16 *)&new_h_dest[4]) =
+ swab16(entry->l2_bridge.new_dmac_lo);
+
+ PRINT_COUNT(m, acct);
+ seq_printf(m,
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|%pM->%pM=>%pM->%pM|eth=0x%04x|sp_tag=%04x|info1=0x%x|info2=0x%x|vlan1=%d=>%d|vlan2=%d=>%d\n",
+ entry, ppe_id, ei(entry, end),
+ es(entry), pt(entry),
+ h_source, h_dest, new_h_source, new_h_dest,
+ entry->l2_bridge.etype,
+ entry->l2_bridge.sp_tag,
+ entry->l2_bridge.info_blk1,
+ entry->l2_bridge.info_blk2,
+ entry->l2_bridge.vlan1,
+ entry->l2_bridge.new_vlan1,
+ entry->l2_bridge.vlan2,
+ entry->l2_bridge.new_vlan2);
#endif
} else if (IS_IPV4_DSLITE(entry)) {
__be32 saddr = htonl(entry->ipv4_hnapt.sip);
@@ -1459,13 +1527,13 @@
swab16(entry->ipv4_dslite.dmac_lo);
PRINT_COUNT(m, acct);
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%pI4->DIP=%pI4|TSIP=%08x:%08x:%08x:%08x->TDIP=%08x:%08x:%08x:%08x|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%pI4->DIP=%pI4|TSIP=%08x:%08x:%08x:%08x->TDIP=%08x:%08x:%08x:%08x|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x\n",
entry, ppe_id, ei(entry, end),
es(entry), pt(entry), &saddr,
&daddr, ipv6_tsip0, ipv6_tsip1, ipv6_tsip2,
ipv6_tsip3, ipv6_tdip0, ipv6_tdip1, ipv6_tdip2,
ipv6_tdip3, h_source, h_dest,
- ntohs(entry->ipv6_5t_route.etype),
+ ntohs(entry->ipv6_5t_route.sp_tag),
entry->ipv6_5t_route.info_blk1,
entry->ipv6_5t_route.info_blk2);
#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -1491,7 +1559,7 @@
swab16(entry->ipv4_dslite.dmac_lo);
PRINT_COUNT(m, acct);
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%pI4:%d->DIP=%pI4:%d|NSIP=%pI4:%d->NDIP=%pI4:%d|TSIP=%08x:%08x:%08x:%08x->TDIP=%08x:%08x:%08x:%08x|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%pI4:%d->DIP=%pI4:%d|NSIP=%pI4:%d->NDIP=%pI4:%d|TSIP=%08x:%08x:%08x:%08x->TDIP=%08x:%08x:%08x:%08x|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x\n",
entry, ppe_id, ei(entry, end),
es(entry), pt(entry),
&saddr, entry->ipv4_dslite.sport,
@@ -1501,7 +1569,7 @@
ipv6_tsip0, ipv6_tsip1, ipv6_tsip2,
ipv6_tsip3, ipv6_tdip0, ipv6_tdip1,
ipv6_tdip2, ipv6_tdip3, h_source, h_dest,
- ntohs(entry->ipv6_5t_route.etype),
+ ntohs(entry->ipv6_5t_route.sp_tag),
entry->ipv6_5t_route.info_blk1,
entry->ipv6_5t_route.info_blk2);
#endif
@@ -1897,6 +1965,28 @@
entry->ipv6_hnapt.new_ipv6_ip2,
entry->ipv6_hnapt.new_ipv6_ip3);
}
+ } else if (IS_L2_BRIDGE(entry)) {
+ unsigned char h_dest[ETH_ALEN];
+ unsigned char h_source[ETH_ALEN];
+ unsigned char new_h_dest[ETH_ALEN];
+ unsigned char new_h_source[ETH_ALEN];
+
+ *((u32 *)h_source) = swab32(entry->l2_bridge.smac_hi);
+ *((u16 *)&h_source[4]) =
+ swab16(entry->l2_bridge.smac_lo);
+ *((u32 *)h_dest) = swab32(entry->l2_bridge.dmac_hi);
+ *((u16 *)&h_dest[4]) =
+ swab16(entry->l2_bridge.dmac_lo);
+
+ *((u32 *)new_h_source) = swab32(entry->l2_bridge.new_smac_hi);
+ *((u16 *)&new_h_source[4]) =
+ swab16(entry->l2_bridge.new_smac_lo);
+ *((u32 *)new_h_dest) = swab32(entry->l2_bridge.new_dmac_hi);
+ *((u16 *)&new_h_dest[4]) =
+ swab16(entry->l2_bridge.new_dmac_lo);
+ seq_printf(m,
+ "L2_BRIDGE(%d): %pM->%pM => %pM -> %pM\n",
+ index, h_source, h_dest, new_h_source, new_h_dest);
#endif
}
}
@@ -2753,6 +2843,95 @@
.release = single_release,
};
+static void hnat_l2br_toggle_usage(void)
+{
+ pr_info("\n*** L2_BRIDGE HNAT is only supported on MT7987 platform ***\n");
+ pr_info("-------------------- Usage --------------------\n");
+ pr_info("Show L2_BRIDGE HNAT mode:\n");
+ pr_info(" cat /sys/kernel/debug/hnat/l2br_toggle\n");
+ pr_info("Disable L2_BRIDGE HNAT:\n");
+ pr_info(" echo 0 > /sys/kernel/debug/hnat/l2br_toggle\n");
+ pr_info("Enable L2_BRIDGE HNAT learning mode:\n");
+ pr_info(" echo 1 > /sys/kernel/debug/hnat/l2br_toggle\n");
+ pr_info("Enable L2_BRIDGE HNAT look-up mode:\n");
+ pr_info(" echo 2 > /sys/kernel/debug/hnat/l2br_toggle\n");
+ pr_info("Show L2_BRIDGE toggle usage:\n");
+ pr_info(" echo 3 > /sys/kernel/debug/hnat/l2br_toggle\n");
+ pr_info("-------------------- Details ------------------\n");
+ pr_info("Learning mode: PPE automatically learns and creates new L2_BRIDGE entries\n");
+ pr_info("Look-up mode : For L2 packets, PPE only checks existing entries without creating new ones\n");
+}
+
+static int hnat_l2br_toggle_read(struct seq_file *m, void *private)
+{
+ if (l2br_toggle == 0)
+ pr_info("L2_BRIDGE HNAT is disabled now!\n");
+ else if (l2br_toggle == 1)
+ pr_info("L2_BRIDGE HNAT learning mode is enabled now!\n");
+ else if (l2br_toggle == 2)
+ pr_info("L2_BRIDGE HNAT look up mode is enabled now!\n");
+
+ return 0;
+}
+
+static int hnat_l2br_toggle_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, hnat_l2br_toggle_read, file->private_data);
+}
+
+static ssize_t hnat_l2br_toggle_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *data)
+{
+ char buf[32] = {0};
+ int len = count;
+ u32 i, ppe_cfg = 0;
+
+ if (len >= sizeof(buf))
+ return -EFAULT;
+
+ if (copy_from_user(buf, buffer, len))
+ return -EFAULT;
+
+ buf[len] = '\0';
+
+ if (buf[0] == '0') {
+ pr_info("L2_BRIDGE HNAT is going to be disabled!\n");
+ l2br_toggle = 0;
+ } else if (buf[0] == '1') {
+ pr_info("L2_BRIDGE HNAT learning mode is going to be enabled!\n");
+ l2br_toggle = 1;
+ ppe_cfg = BIT_L2_BRG_EN | BIT_L2_LRN_EN;
+ } else if (buf[0] == '2') {
+ pr_info("L2_BRIDGE HNAT look-up mode is going to be enabled!\n");
+ l2br_toggle = 2;
+ ppe_cfg = BIT_L2_BRG_EN;
+ } else if (buf[0] == '3') {
+ hnat_l2br_toggle_usage();
+ goto skip_ppe_cfg;
+ } else {
+ pr_err("Input error!\n");
+ hnat_l2br_toggle_usage();
+ goto skip_ppe_cfg;
+ }
+
+ for (i = 0; i < CFG_PPE_NUM; i++) {
+ cr_clr_bits(hnat_priv->ppe_base[i] + PPE_FLOW_CFG,
+ BIT_L2_BRG_EN | BIT_L2_LRN_EN);
+ cr_set_bits(hnat_priv->ppe_base[i] + PPE_FLOW_CFG, ppe_cfg);
+ }
+
+skip_ppe_cfg:
+ return len;
+}
+
+static const struct file_operations hnat_l2br_toggle_fops = {
+ .open = hnat_l2br_toggle_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .write = hnat_l2br_toggle_write,
+ .release = single_release,
+};
+
static int hnat_version_read(struct seq_file *m, void *private)
{
pr_info("HNAT SW version : %s\nHNAT HW version : %d\n", HNAT_SW_VER, hnat_priv->data->version);
@@ -2777,6 +2956,13 @@
u32 hv1 = 0, hv2 = 0, hv3 = 0, hash = 0;
switch (entry->bfib1.pkt_type) {
+ case L2_BRIDGE:
+ hv1 = (entry->l2_bridge.etype << 16) |
+ (entry->l2_bridge.vlan2 ^ entry->l2_bridge.vlan1);
+ hv2 = 0x5a5a |
+ ((entry->l2_bridge.smac_lo ^ entry->l2_bridge.dmac_lo) << 16);
+ hv3 = entry->l2_bridge.dmac_hi ^ entry->l2_bridge.smac_hi;
+ break;
case IPV4_HNAPT:
case IPV4_HNAT:
case IPV4_DSLITE:
@@ -2858,6 +3044,7 @@
{
struct foe_entry *foe, entry = { 0 };
char buf[256], dmac_str[18], smac_str[18], dmac[6], smac[6];
+ char new_dmac_str[18], new_smac_str[18], new_dmac[6], new_smac[6];
int len = count, hash, coll = 0;
u32 ppe_id = 0;
#if defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -2877,7 +3064,7 @@
return -EFAULT;
}
- if (entry.ipv4_hnapt.bfib1.pkt_type == IPV4_HNAPT) {
+ if (entry.bfib1.pkt_type == IPV4_HNAPT) {
#if defined(CONFIG_MEDIATEK_NETSYS_V3)
if (sscanf(buf,
"%5d %8x %8x %8x %hx %hx %8x %8x %8x %hx %hx %18s %18s %4x %4x %4x",
@@ -2928,7 +3115,7 @@
return -EFAULT;
}
#endif
- } else if (entry.ipv4_hnapt.bfib1.pkt_type == IPV6_5T_ROUTE) {
+ } else if (entry.bfib1.pkt_type == IPV6_5T_ROUTE) {
#if defined(CONFIG_MEDIATEK_NETSYS_V3)
if (sscanf(buf,
"%5d %8x %8x%8x%8x%8x %8x%8x%8x%8x %hx %hx %8x %18s %18s %4x %4x %4x",
@@ -2983,6 +3170,31 @@
return -EFAULT;
}
#endif
+ } else if (entry.bfib1.pkt_type == L2_BRIDGE) {
+ if (sscanf(buf,
+ "%5d %8x %18s %18s %hx %hx %hx %8x %18s %18s %hx %hx",
+ &hash,
+ &entry.l2_bridge.info_blk1,
+ dmac_str,
+ smac_str,
+ &entry.l2_bridge.etype,
+ &entry.l2_bridge.vlan1,
+ &entry.l2_bridge.vlan2,
+ &entry.l2_bridge.info_blk2,
+ new_dmac_str,
+ new_smac_str,
+ &entry.l2_bridge.new_vlan1,
+ &entry.l2_bridge.new_vlan2) != 12)
+ return -EFAULT;
+
+ if ((hash >= (int)hnat_priv->foe_etry_num) || (hash < -1)) {
+ hnat_static_entry_help();
+ return -EFAULT;
+ }
+
+ entry.l2_bridge.hph = 0xa5a5;
+ hnat_parse_mac(new_smac_str, new_smac);
+ hnat_parse_mac(new_dmac_str, new_dmac);
} else {
pr_info("Unknown packet type!\n");
return -EFAULT;
@@ -2991,16 +3203,25 @@
hnat_parse_mac(smac_str, smac);
hnat_parse_mac(dmac_str, dmac);
- if (entry.ipv4_hnapt.bfib1.pkt_type == IPV4_HNAPT) {
+ if (entry.bfib1.pkt_type == IPV4_HNAPT) {
entry.ipv4_hnapt.dmac_hi = swab32(*((u32 *)dmac));
entry.ipv4_hnapt.dmac_lo = swab16(*((u16 *)&dmac[4]));
entry.ipv4_hnapt.smac_hi = swab32(*((u32 *)smac));
entry.ipv4_hnapt.smac_lo = swab16(*((u16 *)&smac[4]));
- } else if (entry.ipv4_hnapt.bfib1.pkt_type == IPV6_5T_ROUTE) {
+ } else if (entry.bfib1.pkt_type == IPV6_5T_ROUTE) {
entry.ipv6_5t_route.dmac_hi = swab32(*((u32 *)dmac));
entry.ipv6_5t_route.dmac_lo = swab16(*((u16 *)&dmac[4]));
entry.ipv6_5t_route.smac_hi = swab32(*((u32 *)smac));
entry.ipv6_5t_route.smac_lo = swab16(*((u16 *)&smac[4]));
+ } else if (entry.bfib1.pkt_type == L2_BRIDGE) {
+ entry.l2_bridge.dmac_hi = swab32(*((u32 *)dmac));
+ entry.l2_bridge.dmac_lo = swab16(*((u16 *)&dmac[4]));
+ entry.l2_bridge.smac_hi = swab32(*((u32 *)smac));
+ entry.l2_bridge.smac_lo = swab16(*((u16 *)&smac[4]));
+ entry.l2_bridge.new_dmac_hi = swab32(*((u32 *)new_dmac));
+ entry.l2_bridge.new_dmac_lo = swab16(*((u16 *)&new_dmac[4]));
+ entry.l2_bridge.new_smac_hi = swab32(*((u32 *)new_smac));
+ entry.l2_bridge.new_smac_lo = swab16(*((u16 *)&new_smac[4]));
}
if (hash == -1)
@@ -3210,6 +3431,8 @@
&hnat_xlat_toggle_fops);
debugfs_create_file("xlat_cfg", 0444, root, h,
&hnat_xlat_cfg_fops);
+ debugfs_create_file("l2br_toggle", 0444, root, h,
+ &hnat_l2br_toggle_fops);
for (i = 0; i < hnat_priv->data->num_of_sch; i++) {
ret = snprintf(name, sizeof(name), "qdma_sch%ld", i);
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 72df937..0a5be88 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
@@ -231,8 +231,8 @@
entry->ipv6_5t_route.vlan1 == dsa_tag;
} else {
match_dev = (IS_IPV4_GRP(entry)) ?
- !!(entry->ipv4_hnapt.etype & dsa_tag) :
- !!(entry->ipv6_5t_route.etype & dsa_tag);
+ !!(entry->ipv4_hnapt.sp_tag & dsa_tag) :
+ !!(entry->ipv6_5t_route.sp_tag & dsa_tag);
}
}
@@ -861,6 +861,10 @@
break;
case ETH_P_8021Q:
return 1;
+ default:
+ if (l2br_toggle == 1)
+ return 1;
+ break;
}
return 0;
@@ -1256,6 +1260,12 @@
struct flow_offload_hw_path *hw_path)
{
switch ((int)entry.bfib1.pkt_type) {
+ case L2_BRIDGE:
+ entry.l2_bridge.new_dmac_hi = swab32(*((u32 *)hw_path->eth_dest));
+ entry.l2_bridge.new_dmac_lo = swab16(*((u16 *)&hw_path->eth_dest[4]));
+ entry.l2_bridge.new_smac_hi = swab32(*((u32 *)hw_path->eth_src));
+ entry.l2_bridge.new_smac_lo = swab16(*((u16 *)&hw_path->eth_src[4]));
+ break;
case IPV4_HNAPT:
case IPV4_HNAT:
entry.ipv4_hnapt.dmac_hi = swab32(*((u32 *)hw_path->eth_dest));
@@ -1294,6 +1304,15 @@
readl(hnat_priv->fe_base + 0x0010) & (0x7FFF);
switch ((int)entry.bfib1.pkt_type) {
+ case L2_BRIDGE:
+ if (hnat_priv->data->mcast &&
+ is_multicast_ether_addr(&hw_path->eth_dest[0]))
+ entry.l2_bridge.iblk2.mcast = 1;
+ else
+ entry.l2_bridge.iblk2.mcast = 0;
+
+ entry.l2_bridge.iblk2.port_ag = 0xf;
+ break;
case IPV4_HNAPT:
case IPV4_HNAT:
if (hnat_priv->data->mcast &&
@@ -1479,7 +1498,7 @@
udp = 1;
/* fallthrough */
case IPPROTO_TCP:
- entry.ipv4_hnapt.etype = htons(ETH_P_IP);
+ entry.ipv4_hnapt.sp_tag = htons(ETH_P_IP);
if (IS_IPV4_GRP(&entry)) {
entry.ipv4_hnapt.iblk2.dscp = iph->tos;
if (hnat_priv->data->per_flow_accounting)
@@ -1656,7 +1675,7 @@
udp = 1;
/* fallthrough */
case IPPROTO_TCP:
- entry.ipv4_hnapt.etype = htons(ETH_P_IP);
+ entry.ipv4_hnapt.sp_tag = htons(ETH_P_IP);
/* DS-Lite WAN->LAN */
if (IS_IPV4_DSLITE(&entry) || IS_IPV4_MAPE(&entry)) {
@@ -1819,7 +1838,7 @@
udp = 1;
/* fallthrough */
case NEXTHDR_TCP: /* IPv6-5T or IPv6-3T */
- entry.ipv6_5t_route.etype = htons(ETH_P_IPV6);
+ entry.ipv6_5t_route.sp_tag = htons(ETH_P_IPV6);
entry.ipv6_5t_route.vlan1 = hw_path->vlan_id;
@@ -2013,7 +2032,7 @@
foe->ipv4_hnapt.new_sip;
entry.ipv4_hnapt.new_dip =
foe->ipv4_hnapt.new_dip;
- entry.ipv4_hnapt.etype = htons(ETH_P_IP);
+ entry.ipv4_hnapt.sp_tag = htons(ETH_P_IP);
if (IS_HQOS_MODE) {
entry.ipv4_hnapt.iblk2.qid =
@@ -2062,6 +2081,33 @@
break;
default:
+ if (IS_L2_BRIDGE(&entry)) {
+ entry.l2_bridge.dmac_hi = foe->l2_bridge.dmac_hi;
+ entry.l2_bridge.dmac_lo = foe->l2_bridge.dmac_lo;
+ entry.l2_bridge.smac_hi = foe->l2_bridge.smac_hi;
+ entry.l2_bridge.smac_lo = foe->l2_bridge.smac_lo;
+ entry.l2_bridge.etype = foe->l2_bridge.etype;
+ entry.l2_bridge.hph = foe->l2_bridge.hph;
+ entry.l2_bridge.vlan1 = foe->l2_bridge.vlan1;
+ entry.l2_bridge.vlan2 = foe->l2_bridge.vlan2;
+ entry.l2_bridge.sp_tag = htons(h_proto);
+
+ if (hnat_priv->data->per_flow_accounting)
+ entry.l2_bridge.iblk2.mibf = 1;
+
+ entry.l2_bridge.new_vlan1 = hw_path->vlan_id;
+ if (skb_vlan_tagged(skb)) {
+ entry.bfib1.vlan_layer += 1;
+
+ if (entry.l2_bridge.new_vlan1)
+ entry.l2_bridge.new_vlan2 =
+ skb->vlan_tci;
+ else
+ entry.l2_bridge.new_vlan1 =
+ skb->vlan_tci;
+ }
+ break;
+ }
return -1;
}
@@ -2133,7 +2179,7 @@
* Current setting is PDMA RX.
*/
gmac = NR_PDMA_PORT;
- if (IS_IPV4_GRP(foe)) {
+ if (IS_IPV4_GRP(foe) || IS_L2_BRIDGE(foe)) {
entry.ipv4_hnapt.act_dp &= ~UDF_PINGPONG_IFIDX;
entry.ipv4_hnapt.act_dp |= dev->ifindex & UDF_PINGPONG_IFIDX;
} else {
@@ -2205,7 +2251,7 @@
FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb))) ||
((mape_toggle && mape == 1) && !FROM_EXT(skb))) &&
(!whnat)) {
- entry.ipv4_hnapt.etype = htons(HQOS_MAGIC_TAG);
+ entry.ipv4_hnapt.sp_tag = htons(HQOS_MAGIC_TAG);
entry.ipv4_hnapt.vlan1 = skb_hnat_entry(skb);
entry.bfib1.vlan_layer = 1;
}
@@ -2223,6 +2269,18 @@
} else {
entry.ipv4_hnapt.iblk2.fqos = 0;
}
+ } else if (IS_L2_BRIDGE(&entry)) {
+ entry.l2_bridge.iblk2.dp = gmac;
+ entry.l2_bridge.iblk2.port_mg = 0;
+ if (qos_toggle) {
+ entry.l2_bridge.iblk2.qid = qid & 0x7f;
+ if (FROM_EXT(skb) || skb_hnat_sport(skb) == NR_QDMA_PORT)
+ entry.l2_bridge.iblk2.fqos = 0;
+ else
+ entry.l2_bridge.iblk2.fqos = HQOS_FLAG(dev, skb, qid) ? 1 : 0;
+ } else {
+ entry.l2_bridge.iblk2.fqos = 0;
+ }
} else {
entry.ipv6_5t_route.iblk2.dp = gmac & 0xf;
#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -2246,7 +2304,7 @@
if (IS_EXT(dev) && (FROM_GE_LAN_GRP(skb) ||
FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb)) &&
(!whnat)) {
- entry.ipv6_5t_route.etype = htons(HQOS_MAGIC_TAG);
+ entry.ipv6_5t_route.sp_tag = htons(HQOS_MAGIC_TAG);
entry.ipv6_5t_route.vlan1 = skb_hnat_entry(skb);
entry.bfib1.vlan_layer = 1;
}
@@ -2413,7 +2471,9 @@
if (is_multicast_ether_addr(eth->h_dest))
goto check_release_entry_lock;
- if (IS_IPV4_GRP(&entry))
+ if (IS_L2_BRIDGE(&entry))
+ entry.l2_bridge.iblk2.mcast = 0;
+ else if (IS_IPV4_GRP(&entry))
entry.ipv4_hnapt.iblk2.mcast = 0;
else
entry.ipv6_5t_route.iblk2.mcast = 0;
@@ -2439,6 +2499,7 @@
* will change the smac for specail purpose.
*/
switch ((int)entry.bfib1.pkt_type) {
+ case L2_BRIDGE:
case IPV4_HNAPT:
case IPV4_HNAT:
/*
@@ -2465,11 +2526,11 @@
if (skb_vlan_tagged(skb)) {
entry.bfib1.vlan_layer = 1;
entry.bfib1.vpm = 1;
- if (IS_IPV4_GRP(&entry)) {
- entry.ipv4_hnapt.etype = htons(ETH_P_8021Q);
+ if (IS_IPV4_GRP(&entry) || IS_L2_BRIDGE(&entry)) {
+ entry.ipv4_hnapt.sp_tag = htons(ETH_P_8021Q);
entry.ipv4_hnapt.vlan1 = skb->vlan_tci;
} else if (IS_IPV6_GRP(&entry)) {
- entry.ipv6_5t_route.etype = htons(ETH_P_8021Q);
+ entry.ipv6_5t_route.sp_tag = htons(ETH_P_8021Q);
entry.ipv6_5t_route.vlan1 = skb->vlan_tci;
}
} else {
@@ -2525,7 +2586,7 @@
(FROM_GE_LAN_GRP(skb) || FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb))) {
entry.bfib1.vpm = 0;
entry.bfib1.vlan_layer = 1;
- entry.ipv4_hnapt.etype = htons(HQOS_MAGIC_TAG);
+ entry.ipv4_hnapt.sp_tag = htons(HQOS_MAGIC_TAG);
entry.ipv4_hnapt.vlan1 = skb_hnat_entry(skb);
entry.ipv4_hnapt.iblk2.fqos = 1;
}
@@ -2548,6 +2609,22 @@
entry.ipv6_hnapt.winfo_pao.hf = skb_hnat_hf(skb);
entry.ipv6_hnapt.winfo_pao.amsdu = skb_hnat_amsdu(skb);
entry.ipv6_hnapt.tport_id = IS_HQOS_DL_MODE ? NR_QDMA_TPORT : 0;
+ } else if (IS_L2_BRIDGE(&entry)) {
+ entry.l2_bridge.iblk2.dp = gmac_no;
+ entry.l2_bridge.iblk2.rxid = skb_hnat_rx_id(skb);
+ entry.l2_bridge.iblk2.winfoi = 1;
+
+ entry.l2_bridge.winfo.bssid = skb_hnat_bss_id(skb);
+ entry.l2_bridge.winfo.wcid = skb_hnat_wc_id(skb);
+ entry.l2_bridge.winfo_pao.usr_info =
+ skb_hnat_usr_info(skb);
+ entry.l2_bridge.winfo_pao.tid = skb_hnat_tid(skb);
+ entry.l2_bridge.winfo_pao.is_fixedrate =
+ skb_hnat_is_fixedrate(skb);
+ entry.l2_bridge.winfo_pao.is_prior = skb_hnat_is_prior(skb);
+ entry.l2_bridge.winfo_pao.is_sp = skb_hnat_is_sp(skb);
+ entry.l2_bridge.winfo_pao.hf = skb_hnat_hf(skb);
+ entry.l2_bridge.winfo_pao.amsdu = skb_hnat_amsdu(skb);
#endif
} else {
entry.ipv6_5t_route.iblk2.fqos = 0;
@@ -2630,7 +2707,7 @@
(FROM_GE_LAN_GRP(skb) || FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb))) {
entry.bfib1.vpm = 0;
entry.bfib1.vlan_layer = 1;
- entry.ipv6_5t_route.etype = htons(HQOS_MAGIC_TAG);
+ entry.ipv6_5t_route.sp_tag = htons(HQOS_MAGIC_TAG);
entry.ipv6_5t_route.vlan1 = skb_hnat_entry(skb);
entry.ipv6_5t_route.iblk2.fqos = 1;
}
@@ -3094,7 +3171,7 @@
u16 sp_tag;
if (l2w)
- entry->ipv4_dslite.etype = ETH_P_IP;
+ entry->ipv4_dslite.sp_tag = ETH_P_IP;
else {
if (IS_DSA_LAN(dev)) {
port_reg = of_get_property(dev->dev.of_node,
@@ -3107,9 +3184,9 @@
entry->bfib1.vlan_layer = 1;
entry->bfib1.vpm = 0;
- entry->ipv6_6rd.etype = sp_tag;
+ entry->ipv6_6rd.sp_tag = sp_tag;
} else
- entry->ipv6_6rd.etype = ETH_P_IPV6;
+ entry->ipv6_6rd.sp_tag = ETH_P_IPV6;
}
if (mtk_464xlat_fill_mac(entry, skb, dev, l2w))
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 d48175f..5f64105 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
@@ -99,9 +99,11 @@
dsa_tag |= BIT(8);
if (IS_IPV4_GRP(entry))
- entry->ipv4_hnapt.etype = dsa_tag;
- else
- entry->ipv6_5t_route.etype = dsa_tag;
+ entry->ipv4_hnapt.sp_tag = dsa_tag;
+ else if (IS_IPV6_GRP(entry))
+ entry->ipv6_5t_route.sp_tag = dsa_tag;
+ else if (IS_L2_BRIDGE(entry))
+ entry->l2_bridge.sp_tag = dsa_tag;
entry->bfib1.vpm = 0;
}