Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion api/protos/WifiCore.proto
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,12 @@ message Dot11AccessPointConfiguration
Dot11MacAddress Bssid = 2;
Dot11PhyType PhyType = 3;
Dot11AuthenticationData AuthenticationData = 4;
Dot11AuthenticationDot1x AuthenticationDot1x = 9;
repeated Dot11AuthenticationAlgorithm AuthenticationAlgorithms = 5;
repeated Dot11CipherSuiteConfiguration PairwiseCipherSuites = 6;
repeated Dot11AkmSuite AkmSuites = 7;
repeated Dot11FrequencyBand FrequencyBands = 8;
Dot11AuthenticationDot1x AuthenticationDot1x = 9;
bool mldAp = 10;
}

message Dot11AccessPointCapabilities
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,15 @@ struct IAccessPointController
*/
virtual AccessPointOperationStatus
SetRadiusConfiguration(Ieee8021xRadiusConfiguration radiusConfiguration) noexcept = 0;

/**
* @brief Set whether the access point is a Multi-Link Device (MLD) AP.
*
* @param mldAp True if the access point is an MLD AP, false otherwise.
* @return AccessPointOperationStatus
*/
virtual AccessPointOperationStatus
SetMldAp(bool mldAp) noexcept = 0;
};

/**
Expand Down
36 changes: 36 additions & 0 deletions src/common/service/NetRemoteService.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,12 @@ NetRemoteService::WifiAccessPointEnableImpl(std::string_view accessPointId, cons
return wifiOperationStatus;
}
}

bool mldAp = dot11AccessPointConfiguration->mldap();
wifiOperationStatus = WifiAccessPointSetMldApImpl(accessPointId, mldAp, accessPointController);
if (wifiOperationStatus.code() != WifiAccessPointOperationStatusCode::WifiAccessPointOperationStatusCodeSucceeded) {
return wifiOperationStatus;
}
}

// Obtain current operational state.
Expand Down Expand Up @@ -1467,6 +1473,36 @@ NetRemoteService::WifiAccessPointSetAuthenticationDot1xImpl(std::string_view acc
return wifiOperationStatus;
}

WifiAccessPointOperationStatus
NetRemoteService::WifiAccessPointSetMldApImpl(std::string_view accessPointId, bool mldAp, std::shared_ptr<IAccessPointController> accessPointController)
{
WifiAccessPointOperationStatus wifiOperationStatus{};

AccessPointOperationStatus operationStatus{ accessPointId };

// Create an AP controller for the requested AP if one wasn't specified.
if (accessPointController == nullptr) {
operationStatus = TryGetAccessPointController(accessPointId, accessPointController);
if (!operationStatus.Succeeded() || accessPointController == nullptr) {
wifiOperationStatus.set_code(ToDot11AccessPointOperationStatusCode(operationStatus.Code));
wifiOperationStatus.set_message(std::format("Failed to create access point controller for access point {} - {}", accessPointId, operationStatus.ToString()));
return wifiOperationStatus;
}
}

// Attempt to set the MLD AP setting.
operationStatus = accessPointController->SetMldAp(mldAp);
if (!operationStatus.Succeeded()) {
wifiOperationStatus.set_code(ToDot11AccessPointOperationStatusCode(operationStatus.Code));
wifiOperationStatus.set_message(std::format("Failed to set MLD AP setting for access point {} - {}", accessPointId, operationStatus.ToString()));
return wifiOperationStatus;
}

wifiOperationStatus.set_code(WifiAccessPointOperationStatusCode::WifiAccessPointOperationStatusCodeSucceeded);

return wifiOperationStatus;
}

using google::protobuf::Map;

WifiAccessPointOperationStatus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,17 @@ protected:
Microsoft::Net::Remote::Wifi::WifiAccessPointOperationStatus
WifiAccessPointSetAuthenticationDot1xImpl(std::string_view accessPointId, const Microsoft::Net::Wifi::Dot11AuthenticationDot1x& dot11AuthenticationDot1x, std::shared_ptr<Microsoft::Net::Wifi::IAccessPointController> accessPointController = nullptr);

/**
* @brief Set whether the access point is a Multi-Link Device Access Point (MLD AP).
*
* @param accessPointId The access point identifier.
* @param mldAp True to configure the access point as an MLD AP, false otherwise.
* @param accessPointController The access point controller for the specified access point (optional).
* @return Microsoft::Net::Remote::Wifi::WifiAccessPointOperationStatus
*/
Microsoft::Net::Remote::Wifi::WifiAccessPointOperationStatus
WifiAccessPointSetMldApImpl(std::string_view accessPointId, bool mldAp, std::shared_ptr<Microsoft::Net::Wifi::IAccessPointController> accessPointController = nullptr);

/**
* @brief Get the sttaic attributes of the specified access point.
*
Expand Down
23 changes: 23 additions & 0 deletions src/linux/net/wifi/core/AccessPointControllerLinux.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,29 @@ AccessPointControllerLinux::SetRadiusConfiguration(Ieee8021xRadiusConfiguration
return status;
}

AccessPointOperationStatus
AccessPointControllerLinux::SetMldAp(bool mldAp) noexcept
{
AccessPointOperationStatus status{ GetInterfaceName() };
const AccessPointOperationStatusLogOnExit logStatusOnExit(&status);

AUDITD << std::format("Attempting to set MLD AP for AP {} to {}", status.AccessPointId, mldAp ? "enabled" : "disabled");

std::string_view propertyValueToSet = mldAp ? Wpa::ProtocolHostapd::PropertyEnabled : Wpa::ProtocolHostapd::PropertyDisabled;

// Set the hostapd "mld_ap" property.
try {
m_hostapd.SetProperty(Wpa::ProtocolHostapd::PropertyNameMldAp, propertyValueToSet, EnforceConfigurationChange::Now);
} catch (const Wpa::HostapdException& ex) {
status.Code = AccessPointOperationStatusCode::InternalError;
status.Details = std::format("failed to set hostapd property '{}' to '{}' - {}", Wpa::ProtocolHostapd::PropertyNameMldAp, propertyValueToSet, ex.what());
return status;
}

status.Code = AccessPointOperationStatusCode::Succeeded;
return status;
}

std::unique_ptr<IAccessPointController>
AccessPointControllerLinuxFactory::Create(std::string_view interfaceName)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,15 @@ struct AccessPointControllerLinux :
AccessPointOperationStatus
SetRadiusConfiguration(Microsoft::Net::Ieee8021xRadiusConfiguration radiusConfiguration) noexcept override;

/**
* @brief Set whether the access point is a Multi-Link Device (MLD) AP.
*
* @param mldAp True if the access point is an MLD AP, false otherwise.
* @return AccessPointOperationStatus
*/
AccessPointOperationStatus
SetMldAp(bool mldAp) noexcept override;

private:
Wpa::Hostapd m_hostapd;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,9 @@ struct ProtocolHostapd :
static constexpr auto PropertyValueSaePasswordClearAll = "";
static constexpr auto PropertyValueSaeKeyValueSeparator = "|";

// Wi-Fi 7 (IEEE 802.11be) properties.
static constexpr auto PropertyNameMldAp = "mld_ap";

// Property names for "GET_CONFIG" command.
static constexpr auto PropertyNameKeyManagement = "key_mgmt";
static constexpr auto PropertyNameGroupCipher = "group_cipher";
Expand Down
42 changes: 42 additions & 0 deletions tests/unit/TestNetRemoteServiceClient.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,48 @@ TEST_CASE("WifiAccessPointEnable API", "[basic][rpc][client][remote]")
REQUIRE(result.has_status());
REQUIRE(result.status().code() == WifiAccessPointOperationStatusCode::WifiAccessPointOperationStatusCodeSucceeded);
}

SECTION("Enable MLD AP")
{
// Enable the MLD AP flag via the configuration and verify it sticks.
Dot11AccessPointConfiguration apConfiguration{};
apConfiguration.set_mldap(true);

WifiAccessPointEnableRequest request{};
request.set_accesspointid(InterfaceName1);
*request.mutable_configuration() = std::move(apConfiguration);

WifiAccessPointEnableResult result{};
grpc::ClientContext clientContext{};

auto status = client->WifiAccessPointEnable(&clientContext, request, &result);
REQUIRE(status.ok());
REQUIRE(result.accesspointid() == request.accesspointid());
REQUIRE(result.has_status());
REQUIRE(result.status().code() == WifiAccessPointOperationStatusCode::WifiAccessPointOperationStatusCodeSucceeded);
REQUIRE(apTest1->MldAp == true);
}

SECTION("Disable MLD AP")
{
// Disable the MLD AP flag via the configuration and verify it sticks.
Dot11AccessPointConfiguration apConfiguration{};
apConfiguration.set_mldap(false);

WifiAccessPointEnableRequest request{};
request.set_accesspointid(InterfaceName2);
*request.mutable_configuration() = std::move(apConfiguration);

WifiAccessPointEnableResult result{};
grpc::ClientContext clientContext{};

auto status = client->WifiAccessPointEnable(&clientContext, request, &result);
REQUIRE(status.ok());
REQUIRE(result.accesspointid() == request.accesspointid());
REQUIRE(result.has_status());
REQUIRE(result.status().code() == WifiAccessPointOperationStatusCode::WifiAccessPointOperationStatusCodeSucceeded);
REQUIRE(apTest2->MldAp == false);
}
}

TEST_CASE("WifiAccessPointDisable API", "[basic][rpc][client][remote]")
Expand Down
12 changes: 12 additions & 0 deletions tests/unit/net/wifi/helpers/AccessPointControllerTest.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,18 @@ AccessPointControllerTest::SetRadiusConfiguration(Ieee8021xRadiusConfiguration r
return AccessPointOperationStatus::MakeSucceeded(AccessPoint->InterfaceName);
}

AccessPointOperationStatus
AccessPointControllerTest::SetMldAp(bool mldAp) noexcept
{
assert(AccessPoint != nullptr);
if (AccessPoint == nullptr) {
return AccessPointOperationStatus::InvalidAccessPoint("null AccessPoint");
}

AccessPoint->MldAp = mldAp;
return AccessPointOperationStatus::MakeSucceeded(AccessPoint->InterfaceName);
}

AccessPointControllerFactoryTest::AccessPointControllerFactoryTest(AccessPointTest *accessPoint) :
AccessPoint(accessPoint)
{}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,15 @@ struct AccessPointControllerTest final :
*/
AccessPointOperationStatus
SetRadiusConfiguration(Ieee8021xRadiusConfiguration radiusConfiguration) noexcept override;

/**
* @brief Set whether the access point is a Multi-Link Device (MLD) AP.
*
* @param mldAp True if the access point is an MLD AP, false otherwise.
* @return AccessPointOperationStatus
*/
AccessPointOperationStatus
SetMldAp(bool mldAp) noexcept override;
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct AccessPointTest final :
std::unordered_map<Ieee80211SecurityProtocol, std::vector<Ieee80211CipherSuite>> CipherSuites;
AccessPointOperationalState OperationalState{ AccessPointOperationalState::Disabled };
AccessPointAttributes Attributes{};
bool MldAp{ false };

/**
* @brief Construct a new AccessPointTest object with the given interface name and capabilities.
Expand Down
Loading