Multi link stations are represented in the kernel using a single station with multiple links and the first ADD_STA command also creates the first link. Subsequent links should be added with LINK_ADD commands. Implement this logic and provide the required MLD information per station/link. Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@xxxxxxxxx> --- src/ap/ap_drv_ops.c | 1 + src/drivers/driver.h | 4 +++ src/drivers/driver_nl80211.c | 59 +++++++++++++++++++++++++++++++----- wpa_supplicant/driver_i.h | 5 ++- 4 files changed, 61 insertions(+), 8 deletions(-) diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index bd2cf7cea5..cd509c90a9 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -459,6 +459,7 @@ int hostapd_sta_add(struct hostapd_data *hapd, params.qosinfo = qosinfo; params.support_p2p_ps = supp_p2p_ps; params.set = set; + params.mld_link_id = -1; return hapd->driver->sta_add(hapd->drv_priv, ¶ms); } diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 0f225929ab..38722f5db4 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -2416,6 +2416,10 @@ struct hostapd_sta_add_params { const u8 *supp_oper_classes; size_t supp_oper_classes_len; int support_p2p_ps; + + bool mld_link_sta; + s8 mld_link_id; + const u8 *mld_link_addr; }; struct mac_address { diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 456556e100..0987f11677 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -5385,16 +5385,29 @@ static int wpa_driver_nl80211_sta_add(void *priv, struct nl_msg *msg; struct nl80211_sta_flag_update upd; int ret = -ENOBUFS; + u8 cmd; + const char *cmd_string; if ((params->flags & WPA_STA_TDLS_PEER) && !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT)) return -EOPNOTSUPP; + if (params->mld_link_sta) { + cmd = params->set ? NL80211_CMD_MODIFY_LINK_STA : + NL80211_CMD_ADD_LINK_STA; + cmd_string = params->set ? "NL80211_CMD_MODIFY_LINK_STA" : + "NL80211_CMD_ADD_LINK_STA"; + } else { + cmd = params->set ? NL80211_CMD_SET_STATION : + NL80211_CMD_NEW_STATION; + cmd_string = params->set ? "NL80211_CMD_SET_STATION" : + "NL80211_CMD_NEW_STATION"; + } + wpa_printf(MSG_DEBUG, "nl80211: %s STA " MACSTR, - params->set ? "Set" : "Add", MAC2STR(params->addr)); - msg = nl80211_bss_msg(bss, 0, params->set ? NL80211_CMD_SET_STATION : - NL80211_CMD_NEW_STATION); - if (!msg || nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr)) + cmd_string, MAC2STR(params->addr)); + msg = nl80211_bss_msg(bss, 0, cmd); + if (!msg) goto fail; /* @@ -5612,12 +5625,44 @@ static int wpa_driver_nl80211_sta_add(void *priv, nla_nest_end(msg, wme); } + /* In case the AP is an MLD AP need to always specify the link ID */ + if (params->mld_link_id >= 0) { + wpa_printf(MSG_DEBUG, " * mld_link_id=%d", + params->mld_link_id); + if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, + params->mld_link_id)) + goto fail; + + /* + * If the link address is specified the station is a non MLD AP + * station and thus need to provide the MLD address as the + * station address, and the non MLD AP link address as the link + * address + */ + if (params->mld_link_addr) { + wpa_printf(MSG_DEBUG, " * mld_link_addr=" MACSTR, + MAC2STR(params->mld_link_addr)); + + if (nla_put(msg, NL80211_ATTR_MLD_ADDR, + ETH_ALEN, params->addr) || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, + params->mld_link_addr)) + goto fail; + } else { + if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, + params->addr)) + goto fail; + } + } else { + if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr)) + goto fail; + } + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) - wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_%s_STATION " - "result: %d (%s)", params->set ? "SET" : "NEW", ret, - strerror(-ret)); + wpa_printf(MSG_DEBUG, "nl80211: %s result: %d (%s)", + cmd_string, ret, strerror(-ret)); if (ret == -EEXIST) ret = 0; fail: diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index 7fc9b270a8..dd9858d59e 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -353,8 +353,11 @@ static inline int wpa_drv_set_ap(struct wpa_supplicant *wpa_s, static inline int wpa_drv_sta_add(struct wpa_supplicant *wpa_s, struct hostapd_sta_add_params *params) { - if (wpa_s->driver->sta_add) + if (wpa_s->driver->sta_add) { + /* Set link_id to -1 as it's needed for AP only */ + params->mld_link_id = -1; return wpa_s->driver->sta_add(wpa_s->drv_priv, params); + } return -1; } -- 2.38.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap