[][Add hnat monitor bridge netlink event]
[Description]
Add hnat monitor bridge netlink event.
When sta roaming,
hnat deletes related entries by monitoring the bridge netlink event.
[Release-log]
N/A
Change-Id: Ic33dadc99ac0e2f298c18edf3f7de656945c8302
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/5019890
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
index c0794e3..adaa63f 100644
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
@@ -19,11 +19,15 @@
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
+#include <linux/rtnetlink.h>
+#include <net/netlink.h>
#include "nf_hnat_mtk.h"
#include "hnat.h"
struct mtk_hnat *hnat_priv;
+static struct socket *_hnat_roam_sock;
+static struct work_struct _hnat_roam_work;
int (*ra_sw_nat_hook_rx)(struct sk_buff *skb) = NULL;
EXPORT_SYMBOL(ra_sw_nat_hook_rx);
@@ -147,6 +151,143 @@
BITS_GDM_ALL_FRC_P_CPU_PDMA);
}
+static int entry_mac_cmp(struct foe_entry *entry, u8 *mac)
+{
+ int i, ret = 0;
+
+ if(IS_IPV4_GRP(entry)) {
+ if(((swab32(entry->ipv4_hnapt.dmac_hi) == *(u32 *)mac) &&
+ (swab16(entry->ipv4_hnapt.dmac_lo) == *(u16 *)&mac[4])) ||
+ ((swab32(entry->ipv4_hnapt.smac_hi) == *(u32 *)mac) &&
+ (swab16(entry->ipv4_hnapt.smac_lo) == *(u16 *)&mac[4])))
+ ret = 1;
+ } else {
+ if(((swab32(entry->ipv6_5t_route.dmac_hi) == *(u32 *)mac) &&
+ (swab16(entry->ipv6_5t_route.dmac_lo) == *(u16 *)&mac[4])) ||
+ ((swab32(entry->ipv6_5t_route.smac_hi) == *(u32 *)mac) &&
+ (swab16(entry->ipv6_5t_route.smac_lo) == *(u16 *)&mac[4])))
+ ret = 1;
+ }
+
+ if(ret){
+ pr_info("mac:");
+ for(i = 0; i < ETH_ALEN - 1; i++)
+ pr_info("%2x:", mac[i]);
+ pr_info("%2x\n", mac[i]);
+ }
+
+ return ret;
+}
+
+int entry_delete_by_mac(u8 *mac)
+{
+ 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_mac_cmp(entry, mac)) {
+ memset(entry, 0, sizeof(*entry));
+ hnat_cache_ebl(1);
+ pr_info("delete entry idx = %d\n", index);
+ ret++;
+ }
+ }
+ }
+
+ if(!ret && debug_level >= 2)
+ pr_info("entry not found\n");
+
+ return ret;
+}
+EXPORT_SYMBOL(entry_delete_by_mac);
+
+static void hnat_roam_handler(struct work_struct *work)
+{
+ struct kvec iov;
+ struct msghdr msg;
+ struct nlmsghdr *nlh;
+ struct ndmsg *ndm;
+ struct nlattr *nla;
+ u8 rcv_buf[512];
+ int len;
+
+ if (!_hnat_roam_sock)
+ return;
+
+ iov.iov_base = rcv_buf;
+ iov.iov_len = sizeof(rcv_buf);
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_namelen = sizeof(struct sockaddr_nl);
+
+ len = kernel_recvmsg(_hnat_roam_sock, &msg, &iov, 1, iov.iov_len, 0);
+ if (len <= 0)
+ goto out;
+
+ nlh = (struct nlmsghdr*)rcv_buf;
+ if (!NLMSG_OK(nlh, len) || nlh->nlmsg_type != RTM_NEWNEIGH)
+ goto out;
+
+ len = nlh->nlmsg_len - NLMSG_HDRLEN;
+ ndm = (struct ndmsg *)NLMSG_DATA(nlh);
+ if (ndm->ndm_family != PF_BRIDGE)
+ goto out;
+
+ nla = (struct nlattr *)((u8 *)ndm + sizeof(struct ndmsg));
+ len -= NLMSG_LENGTH(sizeof(struct ndmsg));
+ while (nla_ok(nla, len)) {
+ if (nla_type(nla) == NDA_LLADDR) {
+ entry_delete_by_mac(nla_data(nla));
+ }
+ nla = nla_next(nla, &len);
+ }
+
+out:
+ schedule_work(&_hnat_roam_work);
+}
+
+static int hnat_roaming_enable(void)
+{
+ struct socket *sock = NULL;
+ struct sockaddr_nl addr;
+ int ret;
+
+ INIT_WORK(&_hnat_roam_work, hnat_roam_handler);
+
+ ret = sock_create_kern(&init_net, AF_NETLINK, SOCK_RAW, NETLINK_ROUTE, &sock);
+ if (ret < 0)
+ goto out;
+
+ _hnat_roam_sock = sock;
+
+ addr.nl_family = AF_NETLINK;
+ addr.nl_pad = 0;
+ addr.nl_pid = 65534;
+ addr.nl_groups = 1 << (RTNLGRP_NEIGH - 1);
+ ret = kernel_bind(sock, (struct sockaddr *)&addr, sizeof(addr));
+ if (ret < 0)
+ goto out;
+
+ schedule_work(&_hnat_roam_work);
+ pr_info("hnat roaming work enable\n");
+
+ return 0;
+out:
+ if (sock)
+ sock_release(sock);
+
+ return ret;
+}
+
+static void hnat_roaming_disable(void)
+{
+ if (_hnat_roam_sock)
+ sock_release(_hnat_roam_sock);
+ _hnat_roam_sock = NULL;
+ pr_info("hnat roaming work disable\n");
+}
+
static int hnat_start(int ppe_id)
{
u32 foe_table_sz;
@@ -610,6 +751,9 @@
if (IS_GMAC1_MODE)
dev_add_pack(&mtk_pack_type);
#endif
+ err = hnat_roaming_enable();
+ if (err)
+ pr_info("hnat roaming work fail\n");
return 0;
@@ -630,6 +774,7 @@
{
int i;
+ hnat_roaming_disable();
unregister_netdevice_notifier(&nf_hnat_netdevice_nb);
unregister_netevent_notifier(&nf_hnat_netevent_nb);
hnat_disable_hook();
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
index c99b1ef..d5b4c8d 100644
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
@@ -938,6 +938,7 @@
void hnat_cache_ebl(int enable);
void set_gmac_ppe_fwd(int gmac_no, int enable);
int entry_detail(int ppe_id, int index);
+int entry_delete_by_mac(u8 *mac);
int entry_delete(int ppe_id, int index);
static inline u16 foe_timestamp(struct mtk_hnat *h)