From 4e122dc5cf6e2d0fa17a93c05ca01ad758097e19 Mon Sep 17 00:00:00 2001 From: Rameshkumar Sundaram Date: Wed, 1 Nov 2023 22:55:24 +0530 Subject: [PATCH 2/2] hostapd: add links to bridge fdb for FT roaming During FT, RRB message is getting dropped at bridge since bridge doesn't know all the link address, so roaming gets failed. Add link address to the bridge fdb, so that RRB pkts gets forwarded through bridge to hostapd. Co-developed-by: Karthikeyan Kathirvel Signed-off-by: Karthikeyan Kathirvel Signed-off-by: Rameshkumar Sundaram --- src/drivers/driver_nl80211.c | 71 ++++++++++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 7 deletions(-) --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -3082,9 +3082,6 @@ static void wpa_driver_nl80211_deinit(st 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) @@ -3104,6 +3101,9 @@ static void wpa_driver_nl80211_deinit(st 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); @@ -5873,13 +5873,17 @@ 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, + /* 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; @@ -5900,11 +5904,12 @@ static void rtnl_neigh_delete_fdb_entry( 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: @@ -5912,6 +5917,49 @@ errout: } +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) + goto errout; + + if (nla_put(msg, NDA_LLADDR, ETH_ALEN, (void *)addr)) + goto errout; + + if (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: + nlmsg_free(msg); +} + static int wpa_driver_nl80211_sta_remove(struct i802_bss *bss, const u8 *addr, int deauth, u16 reason_code) { @@ -5939,7 +5987,7 @@ static int wpa_driver_nl80211_sta_remove 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; @@ -9395,6 +9443,7 @@ static int nl80211_remove_link(struct i8 struct i802_link *link = NULL; struct nl_msg *msg; int i, ret; + u8 link_addr[ETH_ALEN]; wpa_printf(MSG_DEBUG, "nl80211: Remove link (ifindex=%d)", bss->ifindex); wpa_printf(MSG_DEBUG, "nl80211: MLD: remove link_id=%u", link_id); @@ -9418,6 +9467,7 @@ static int nl80211_remove_link(struct i8 return 0; } + os_memcpy(link_addr, link->addr, ETH_ALEN); /* First remove the link locally. In order to remove a link[i] from links[], * shift left next all links[j] where j >= i + 1 to max size */ @@ -9450,6 +9500,8 @@ static int nl80211_remove_link(struct i8 "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; } @@ -13822,6 +13874,11 @@ static int nl80211_link_add(void *priv, bss->n_links = idx + 1; wpa_printf(MSG_DEBUG, "nl80211: MLD: n_links=%zu ifidx %d", bss->n_links, drv->ifindex); + + /* ToDo, check if ml address is the link address + if (drv->rtnl_sk && os_memcmp(bss->mld_addr, addr, ETH_ALEN)) */ + if (drv->rtnl_sk) + rtnl_neigh_add_fdb_entry(bss, addr, true); return 0; }