[][[Kernel][common][hnat][Add delete entry by IP command]
[Description]
Add delete entry by IP
Delete downlink and uplink HNAT entry according to the STA IP.
[Release-log]
NA
Change-Id: I4894e594a74cb1defbeeb61f09c8917b10d36222
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/9404592
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 24f7e7d..892bd61 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
@@ -44,6 +44,9 @@
int (*ppe_del_entry_by_mac)(unsigned char *mac) = NULL;
EXPORT_SYMBOL(ppe_del_entry_by_mac);
+int (*ppe_del_entry_by_ip)(bool is_ipv4, void *addr) = NULL;
+EXPORT_SYMBOL(ppe_del_entry_by_ip);
+
void (*ppe_dev_register_hook)(struct net_device *dev) = NULL;
EXPORT_SYMBOL(ppe_dev_register_hook);
void (*ppe_dev_unregister_hook)(struct net_device *dev) = NULL;
@@ -260,6 +263,79 @@
return ret;
}
+static int entry_ip_cmp(struct foe_entry *entry, bool is_ipv4, void *addr)
+{
+ u32 *tmp_ipv4, *sipv6_0, *dipv6_0, ipv4;
+ struct in6_addr *tmp_ipv6, ipv6;
+ struct in6_addr foe_sipv6, foe_dipv6;
+ int ret = 0;
+
+ if (is_ipv4) {
+ tmp_ipv4 = (u32 *)addr;
+ ipv4 = ntohl(*tmp_ipv4);
+
+ switch ((int)entry->bfib1.pkt_type) {
+ case IPV4_HNAPT:
+ case IPV4_HNAT:
+ if (entry->ipv4_hnapt.sip == ipv4 ||
+ entry->ipv4_hnapt.new_dip == ipv4)
+ ret = 1;
+ break;
+ case IPV4_DSLITE:
+ case IPV4_MAP_E:
+ if (entry->ipv4_dslite.sip == ipv4 ||
+ entry->ipv4_dslite.dip == ipv4)
+ ret = 1;
+ break;
+ default:
+ break;
+ }
+ } else {
+ memset(&foe_sipv6, 0, sizeof(struct in6_addr));
+ memset(&foe_dipv6, 0, sizeof(struct in6_addr));
+ memset(&ipv6, 0, sizeof(struct in6_addr));
+
+ tmp_ipv6 = (struct in6_addr *)addr;
+ ipv6.s6_addr32[0] = ntohl(tmp_ipv6->s6_addr32[0]);
+ ipv6.s6_addr32[1] = ntohl(tmp_ipv6->s6_addr32[1]);
+ ipv6.s6_addr32[2] = ntohl(tmp_ipv6->s6_addr32[2]);
+ ipv6.s6_addr32[3] = ntohl(tmp_ipv6->s6_addr32[3]);
+
+ switch ((int)entry->bfib1.pkt_type) {
+ case IPV6_3T_ROUTE:
+ case IPV6_5T_ROUTE:
+ case IPV6_6RD:
+ sipv6_0 = &(entry->ipv6_3t_route.ipv6_sip0);
+ dipv6_0 = &(entry->ipv6_3t_route.ipv6_dip0);
+ break;
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+ case IPV6_HNAT:
+ case IPV6_HNAPT:
+ sipv6_0 = &(entry->ipv6_hnapt.ipv6_sip0);
+ dipv6_0 = &(entry->ipv6_hnapt.new_ipv6_ip0);
+ break;
+#endif
+ default:
+ break;
+ }
+
+ memcpy(&foe_sipv6, sipv6_0, sizeof(struct in6_addr));
+ memcpy(&foe_dipv6, dipv6_0, sizeof(struct in6_addr));
+ if (!memcmp(&foe_sipv6, &ipv6, sizeof(struct in6_addr)) ||
+ !memcmp(&foe_dipv6, &ipv6, sizeof(struct in6_addr)))
+ ret = 1;
+ }
+
+ if (ret && debug_level >= 2) {
+ if (is_ipv4)
+ pr_info("ipv4=%pI4\n", tmp_ipv4);
+ else
+ pr_info("ipv6=%pI6\n", tmp_ipv6);
+ }
+
+ return ret;
+}
+
int entry_delete_by_mac(u8 *mac)
{
struct foe_entry *entry = NULL;
@@ -284,6 +360,30 @@
return ret;
}
+int entry_delete_by_ip(bool is_ipv4, void *addr)
+{
+ struct foe_entry *entry = NULL;
+ int index, i, ret = 0;
+
+ for (i = 0; i < CFG_PPE_NUM; i++) {
+ entry = hnat_priv->foe_table_cpu[i];
+ for (index = 0; index < DEF_ETRY_NUM; entry++, index++) {
+ if (entry->bfib1.state == BIND && entry_ip_cmp(entry, is_ipv4, addr)) {
+ memset(entry, 0, sizeof(*entry));
+ hnat_cache_ebl(1);
+ if (debug_level >= 2)
+ pr_info("delete entry idx = %d\n", index);
+ ret++;
+ }
+ }
+ }
+
+ if (!ret && debug_level >= 2)
+ pr_info("entry not found\n");
+
+ return ret;
+}
+
static void hnat_roam_handler(struct work_struct *work)
{
struct kvec iov;
@@ -687,6 +787,7 @@
return -1;
ppe_del_entry_by_mac = entry_delete_by_mac;
+ ppe_del_entry_by_ip = entry_delete_by_ip;
hook_toggle = 1;
return 0;
@@ -724,6 +825,7 @@
mod_timer(&hnat_priv->hnat_sma_build_entry_timer, jiffies + 3 * HZ);
ppe_del_entry_by_mac = NULL;
+ ppe_del_entry_by_ip = NULL;
hook_toggle = 0;
return 0;
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 f7ca61c..6413de6 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
@@ -1350,6 +1350,7 @@
void set_gmac_ppe_fwd(int gmac_no, int enable);
int entry_detail(u32 ppe_id, int index);
int entry_delete_by_mac(u8 *mac);
+int entry_delete_by_ip(bool is_ipv4, void *addr);
int entry_delete(u32 ppe_id, int index);
int hnat_warm_init(void);
u32 hnat_get_ppe_hash(struct foe_entry *entry);
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 a5da044..53f4d10 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
@@ -325,6 +325,8 @@
pr_info(" 7 <entry_idx> Delete PPE2 specific foe entry of assigned <entry_idx>\n");
pr_info(" When entry_idx is -1, clear all entries\n");
pr_info(" 8 <mac> Delete all PPEs foe entry of assinged smac and dmac\n");
+ pr_info(" 9 <ip> Delete all PPEs foe entry of assinged IP(DL and UL)\n");
+ pr_info(" 10 <ipV6> Delete all PPEs foe entry of assinged IPv6(DL and UL)\n");
return 0;
}
@@ -779,6 +781,31 @@
return 0;
}
+int delete_entry_by_ip(bool is_ipv4, char *str)
+{
+ struct in6_addr ipv6;
+ void *addr = NULL;
+ u32 ipv4;
+
+ if (is_ipv4) {
+ if (!in4_pton(str, -1, (u8 *)&ipv4, -1, NULL)) {
+ pr_info("Invalid IPv4 address.\n");
+ return -EINVAL;
+ }
+ addr = (void *)(&ipv4);
+ } else {
+ if (!in6_pton(str, -1, (u8 *)&ipv6, -1, NULL)) {
+ pr_info("Invalid IPv6 address.\n");
+ return -EINVAL;
+ }
+ addr = (void *)(&ipv6);
+ }
+
+ entry_delete_by_ip(is_ipv4, addr);
+
+ return 0;
+}
+
int cr_set_usage(int level)
{
debug_level = level;
@@ -1929,6 +1956,7 @@
char *p_token = NULL;
char *p_delimiter = " \t";
int ret;
+ bool is_ipv4 = true;
if (len >= sizeof(buf)) {
pr_info("input handling fail!\n");
@@ -1966,12 +1994,21 @@
break;
case 8:
p_token = strsep(&p_buf, p_delimiter);
-
if (!p_token)
break;
delete_entry_by_mac(p_token);
break;
+ case 9:
+ case 10:
+ p_token = strsep(&p_buf, p_delimiter);
+ if (!p_token)
+ break;
+
+ if (arg0 == 10)
+ is_ipv4 = false;
+ delete_entry_by_ip(is_ipv4, p_token);
+ break;
default:
pr_info("no handler defined for command id(0x%08lx)\n\r", arg0);
entry_set_usage(debug_level);