From 7e7e43d6b376c909a1dfaab8659728165a36c5d8 Mon Sep 17 00:00:00 2001 From: Karthikeyan Kathirvel Date: Tue, 9 Apr 2024 22:53:46 +0530 Subject: [PATCH] AP MLD: Add links to bridge FDB for FT roaming During FT, RRB messages are getting dropped at bridge on an AP MLD since bridge doesn't know all the link address, so roaming gets failed. Add AP MLD's each link address to the bridge FDB, so that RRB frames get forwarded through bridge to hostapd. Co-developed-by: Rameshkumar Sundaram Signed-off-by: Rameshkumar Sundaram Signed-off-by: Karthikeyan Kathirvel --- src/drivers/driver_nl80211.c | 81 +++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 10 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index cfca5b9f9..b8b747d8b 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -3151,9 +3151,6 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss) bss->ifname, bss->brname, strerror(errno)); } - if (drv->rtnl_sk) - nl_socket_free(drv->rtnl_sk); - if (bss->added_bridge) { if (linux_set_iface_flags(drv->global->ioctl_sock, bss->brname, 0) < 0) @@ -3173,6 +3170,9 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss) nl80211_remove_links(bss); } + if (drv->rtnl_sk) + nl_socket_free(drv->rtnl_sk); + if (drv->eapol_sock >= 0) { eloop_unregister_read_sock(drv->eapol_sock); close(drv->eapol_sock); @@ -5881,13 +5881,15 @@ fail: } -static void rtnl_neigh_delete_fdb_entry(struct i802_bss *bss, const u8 *addr) +static void rtnl_neigh_delete_fdb_entry(struct i802_bss *bss, const u8 *addr, + bool is_bridge) { struct wpa_driver_nl80211_data *drv = bss->drv; struct ndmsg nhdr = { .ndm_state = NUD_PERMANENT, - .ndm_ifindex = bss->ifindex, + .ndm_ifindex = is_bridge ? bss->br_ifindex : bss->ifindex, .ndm_family = AF_BRIDGE, + .ndm_type = is_bridge ? NTF_SELF : 0, }; struct nl_msg *msg; int err; @@ -5904,11 +5906,61 @@ static void rtnl_neigh_delete_fdb_entry(struct i802_bss *bss, const u8 *addr) err = nl_wait_for_ack(drv->rtnl_sk); if (err < 0) { wpa_printf(MSG_DEBUG, "nl80211: bridge FDB entry delete for " - MACSTR " ifindex=%d failed: %s", MAC2STR(addr), - bss->ifindex, nl_geterror(err)); + MACSTR " ifindex=%d ifname %s failed: %s", + MAC2STR(addr), + is_bridge ? bss->br_ifindex : bss->ifindex, + is_bridge ? bss->brname : bss->ifname, + nl_geterror(err)); } else { - wpa_printf(MSG_DEBUG, "nl80211: deleted bridge FDB entry for " - MACSTR, MAC2STR(addr)); + wpa_printf(MSG_DEBUG, "nl80211: deleted bridge FDB entry " + MACSTR " from %s", + MAC2STR(addr), + is_bridge ? bss->brname : bss->ifname); + } + +errout: + nlmsg_free(msg); +} + + +static void rtnl_neigh_add_fdb_entry(struct i802_bss *bss, const u8 *addr, + bool is_bridge) +{ + struct wpa_driver_nl80211_data *drv = bss->drv; + struct ndmsg nhdr = { + .ndm_state = NUD_PERMANENT, + .ndm_ifindex = is_bridge ? bss->br_ifindex : bss->ifindex, + .ndm_family = AF_BRIDGE, + /* TODO: remove this check if this flag needs to be used, + * for other interfaces type. + */ + .ndm_flags = is_bridge ? NTF_SELF : 0, + }; + struct nl_msg *msg; + int err; + + msg = nlmsg_alloc_simple(RTM_NEWNEIGH, NLM_F_CREATE); + if (!msg) + return; + + if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0 || + nla_put(msg, NDA_LLADDR, ETH_ALEN, (void *) addr) || + nl_send_auto_complete(drv->rtnl_sk, msg) < 0) + goto errout; + + err = nl_wait_for_ack(drv->rtnl_sk); + if (err < 0) { + wpa_printf(MSG_DEBUG, "nl80211: bridge FDB entry addition for " + MACSTR " ifindex=%d ifname %s failed: %s", + MAC2STR(addr), + is_bridge ? bss->br_ifindex : bss->ifindex, + is_bridge ? bss->brname : bss->ifname, + nl_geterror(err)); + } else { + wpa_printf(MSG_DEBUG, "nl80211: added bridge FDB entry " MACSTR + " to %s", + MAC2STR(addr), + is_bridge ? bss->brname : bss->ifname); } errout: @@ -5943,7 +5995,7 @@ static int wpa_driver_nl80211_sta_remove(struct i802_bss *bss, const u8 *addr, bss->ifname, MAC2STR(addr), ret, strerror(-ret)); if (drv->rtnl_sk) - rtnl_neigh_delete_fdb_entry(bss, addr); + rtnl_neigh_delete_fdb_entry(bss, addr, false); if (ret == -ENOENT) return 0; @@ -9465,6 +9517,7 @@ int nl80211_remove_link(struct i802_bss *bss, int link_id) struct nl_msg *msg; size_t i; int ret; + u8 link_addr[ETH_ALEN]; wpa_printf(MSG_DEBUG, "nl80211: Remove link (ifindex=%d link_id=%u)", bss->ifindex, link_id); @@ -9479,6 +9532,7 @@ int nl80211_remove_link(struct i802_bss *bss, int link_id) wpa_driver_nl80211_del_beacon(bss, link_id); + os_memcpy(link_addr, link->addr, ETH_ALEN); /* First remove the link locally */ bss->valid_links &= ~BIT(link_id); os_memset(link->addr, 0, ETH_ALEN); @@ -9516,6 +9570,9 @@ int nl80211_remove_link(struct i802_bss *bss, int link_id) "nl80211: remove link (%d) failed. ret=%d (%s)", link_id, ret, strerror(-ret)); + if (drv->rtnl_sk) + rtnl_neigh_delete_fdb_entry(bss, link_addr, true); + return ret; } @@ -13957,6 +14014,10 @@ static int nl80211_link_add(void *priv, u8 link_id, const u8 *addr, wpa_printf(MSG_DEBUG, "nl80211: MLD: valid_links=0x%04x on %s", bss->valid_links, bss->ifname); + + if (drv->rtnl_sk) + rtnl_neigh_add_fdb_entry(bss, addr, true); + return 0; }