Skip to content

Conversation

@jrrech
Copy link

@jrrech jrrech commented Oct 17, 2025

Summary

This change enables a Commissioner to leverage the command-based control interface of hostapd for WiFi-PAF commissioning, as an alternative to the D-Bus interface, which is exclusive to wpa_supplicant. With this change, a Linux-based access point should be able to act as Commissioner or Commissioner Proxy with NAN-USD capabilities. OpenWRT is an example of a Linux distribution which could now take advantage of hostapd support for WiFi-PAF commissioning, since it doesn't normally run wpa_supplicant.

  • In order to accomodate for the two different implementations (D-Bus and control interface), a generic WiFiPAFDriver class was created, for providing a single interface to low-level WiFi-PAF methods to ConnectivityManagerImpl.

  • The D-Bus WiFi-PAF implementation by NXP was moved to the WiFiDriverDbus derived class.

  • A WiFiPAFDriverCtrlIface class implements WiFiPAFDriver using wpa_ctrl_* functions from hostap repository, which was added as a submodule. It's the same command interface used by the hostapd_cli application. See https://w1.fi/wpa_supplicant/devel/wpa__ctrl_8h.html for reference.

  • WiFiPAFDriver has private methods for logic that is shared by both WiFiPAFDbus and WiFiPAFCtrlIface.

  • Two build arguments have been added:

    • chip_device_config_enable_wifipaf_ctrl_iface: enables the build of WiFiDriverCtrlIface instead
      of WiFiDriverDbus. Defaults to "false".
    • chip_device_config_enable_wifipaf_hostapd: used for disabling Wi-Fi management by
      ConnectivityManagerImpl. Must be disabled when hostapd is managing Wi-Fi interfaces.
      Defaults to "false".
  • WiFiPAFDriverCtrlIface is compatible with both wpa_supplicant and hostapd:

  • Enable only chip_device_config_enable_wifipaf_ctrl_iface if running wpa_supplicant.

  • Enable both chip_device_config_enable_wifipaf_ctrl_iface and
    chip_device_config_enable_wifipaf_hostapd if running hostapd.

Testing

Environment:
AP: 8devices Habanero DVK running OpenWRT v24.10.0
Device: RPi 4b running Ubuntu 24.04 + Atheros AR9271 USB adapter

Steps:
AP:
$./chip-tool pairing wifipaf-wifi 1 TestSSID test-passphrase 20202021 3840 --freq 2412

Device:
$ sudo ./chip-all-clusters-app --wifi --wifipaf freq_list=2412

Expected result: the Raspberry Pi device should be successfully commissioned by the chip-tool commissioner running on the Access Point.

…t control interface

This change enables a Commissioner to leverage the command-based control interface of hostapd
for WiFi-PAF commissioning, as an alternative to the D-Bus interface, which is exclusive to
wpa_supplicant. With this change, a Linux-based access point should be able to act as Commissioner
or Commissioner Proxy with NAN-USD capabilities. OpenWRT is an example of a Linux distribution
which could now take advantage of hostapd support for WiFi-PAF commissioning, since it doesn't
normally run wpa_supplicant.

* In order to accomodate for the two different implementations (D-Bus and control interface), a
  generic WiFiPAFDriver class was created, for providing a single interface to low-level WiFi-PAF
  methods to ConnectivityManagerImpl.

* The D-Bus WiFi-PAF implementation by NXP was moved to the WiFiDriverDbus derived class.

* A WiFiPAFDriverCtrlIface class implements WiFiPAFDriver using wpa_ctrl_* functions from hostap
  repository, which was added as a submodule. It's the same command interface used by the
  hostapd_cli application. See https://w1.fi/wpa_supplicant/devel/wpa__ctrl_8h.html for reference.

* WiFiPAFDriver has private methods for logic that is shared by both WiFiPAFDbus and
  WiFiPAFCtrlIface.

* Two build arguments have been added:

** chip_device_config_enable_wifipaf_ctrl_iface: enables the build of WiFiDriverCtrlIface instead
   of WiFiDriverDbus. Defaults to "false".

** chip_device_config_enable_wifipaf_hostapd: used for disabling Wi-Fi management by
   ConnectivityManagerImpl. Must be disabled when hostapd is managing Wi-Fi interfaces.
   Defaults to "false".

* WiFiPAFDriverCtrlIface is compatible with both wpa_supplicant and hostapd:

** Enable only chip_device_config_enable_wifipaf_ctrl_iface if running wpa_supplicant.

** Enable both chip_device_config_enable_wifipaf_ctrl_iface and
   chip_device_config_enable_wifipaf_hostapd if running hostapd.
@CLAassistant
Copy link

CLAassistant commented Oct 17, 2025

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ jrrech
❌ jonatasrech
You have signed the CLA already but the status is still pending? Let us recheck it.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a significant and well-structured refactoring to support WiFi-PAF commissioning over the hostapd/wpa_supplicant control interface, in addition to the existing D-Bus interface. The abstraction of WiFi-PAF operations into a WiFiPAFDriver base class with two separate implementations is a clean approach. My review has identified a critical issue in the shutdown logic of the new control interface driver that could lead to resource leaks and incorrect behavior, a high-severity issue regarding data-endianness that could cause interoperability problems, and a medium-severity suggestion to improve performance in data serialization. Overall, this is a valuable addition that extends WiFi-PAF support to more platforms.

Comment on lines +509 to +510
wpa_ctrl_close(ctrl);
wpa_ctrl_close(cmd_ctrl);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The wpa_ctrl handles ctrl and cmd_ctrl are closed here, but they are shared for the lifetime of the WiFiPAFDriverCtrlIface instance. Closing them in Shutdown will cause subsequent operations to fail. These handles should be closed in the destructor of WiFiPAFDriverCtrlIface instead. Please also add a destructor to WiFiPAFDriverCtrlIface in WiFiPAFDriverCtrlIface.h to handle this, for example:
~WiFiPAFDriverCtrlIface() override
{
if (ctrl) wpa_ctrl_close(ctrl);
if (cmd_ctrl) wpa_ctrl_close(cmd_ctrl);
}

~WiFiPAFDriverCtrlIface() override
{
    if (ctrl) wpa_ctrl_close(ctrl);
    if (cmd_ctrl) wpa_ctrl_close(cmd_ctrl);
}

Comment on lines +210 to +211
<< std::setw(2) << static_cast<int>(PafPublish_ssi.DevOpCode) << std::setw(4) << htons(PafPublish_ssi.DevInfo)
<< std::setw(4) << htons(PafPublish_ssi.ProductId) << std::setw(4) << htons(PafPublish_ssi.VendorId) << " freq_list=";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The use of htons() here to convert uint16_t fields to network byte order before creating the hex string for the SSI (Service Specific Information) is inconsistent with the D-Bus implementation (WiFiPAFDriverDbus.cpp), which directly uses the struct's memory layout. On little-endian systems, this will result in different byte orders for the SSI between the two implementations, leading to interoperability issues. Please ensure the byte order is consistent across both implementations. If network byte order (big-endian) is required by the wpa_supplicant/hostapd control interface, then the D-Bus implementation should also be updated to ensure data is sent in network byte order.

Comment on lines +475 to +480
std::ostringstream oss_ssi;
for (size_t i = 0; i < msgBuf->DataLength(); ++i)
{
oss_ssi << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(msgBuf->Start()[i]);
}
auto ssi_str = oss_ssi.str();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This loop for converting the message buffer to a hex string using std::ostringstream is inefficient. The Matter codebase provides a more performant utility chip::Encoding::BytesToHex for this purpose. Using it would improve performance and maintain consistency with the rest of the codebase.

For example, you could replace these lines with:
std::vector ssi_hex_buffer(msgBuf->DataLength() * 2 + 1);
ReturnErrorOnFailure(chip::Encoding::BytesToHex(msgBuf->Start(), msgBuf->DataLength(), ssi_hex_buffer.data(), ssi_hex_buffer.size()));
auto ssi_str = std::string(ssi_hex_buffer.data());

std::vector<char> ssi_hex_buffer(msgBuf->DataLength() * 2 + 1);
ReturnErrorOnFailure(chip::Encoding::BytesToHex(msgBuf->Start(), msgBuf->DataLength(), ssi_hex_buffer.data(), ssi_hex_buffer.size()));
auto ssi_str = std::string(ssi_hex_buffer.data());

.gitmodules Outdated
recursive = true
[submodule "third_party/hostap/repo"]
path = third_party/hostap/repo
url = https://w1.fi/hostap.git
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to give a 404 to me.
This should probably have a platforms guard to linux.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also wondering who w1.fi actually is ... why is this not some github project ? https://who.is/whois/w1.fi does not make it very clear....

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably this has to be added by a git submodule add as well as our CI seems to complain that checkout does not work

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your comments @andy31415 , indeed I had not committed the actual submodule. About the repo URL, it is valid for git clone, but not suitable for loading with a web browser.

"SystemPlatformConfig.h",
"SystemTimeSupport.cpp",
"WiFiPAFDriver.h",
"WiFiPAFDriver.cpp",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be conditional on some "enable WiFi PAF" setting instead? Do we expect every linux distribution to support this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, this should be guarded somehow. Will fix it.

}

include_dirs = [
"${chip_root}/third_party/hostap/repo/src/common",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be done via dependencies: if you depend on hostap, this include should be added in.

}
}

source_set("wpa_ctrl") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be inside the hostap BUILD.gn, so that I can depend on hostap and not have a separate source set here.

Copy link
Contributor

@andy31415 andy31415 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Build system updates are odd, needs fixing (have hostap as a stand-alone linux source set that can be dependend on)
  • figure out the repository source. w1.fi looks strange to me

@github-actions
Copy link

PR #41522: Size comparison from c87ece5 to 24944dd

Full report (1 build for stm32)
platform target config section c87ece5 24944dd change % change
stm32 light STM32WB5MM-DK FLASH 469772 469772 0 0.0
RAM 141248 141248 0 0.0

@github-actions
Copy link

github-actions bot commented Oct 17, 2025

PR #41522: Size comparison from c87ece5 to f2a6a96

Full report (37 builds for bl602, bl702, bl702l, cc13x4_26x4, cc32xx, efr32, esp32, nrfconnect, nxp, psoc6, qpg, realtek, stm32, telink)
platform target config section c87ece5 f2a6a96 change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1106314 1106314 0 0.0
RAM 178802 178802 0 0.0
bl702 lighting-app bl702+eth FLASH 660904 660904 0 0.0
RAM 134881 134881 0 0.0
bl702+wifi FLASH 837016 837016 0 0.0
RAM 124349 124349 0 0.0
bl706+mfd+rpc+littlefs FLASH 1069984 1069984 0 0.0
RAM 117189 117189 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 898826 898826 0 0.0
RAM 105468 105468 0 0.0
lighting-app bl702l+mfd+littlefs FLASH 983002 983002 0 0.0
RAM 109676 109676 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 770324 770324 0 0.0
RAM 103240 103240 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 782080 782080 0 0.0
RAM 108400 108400 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 727900 727900 0 0.0
RAM 97308 97308 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 712344 712344 0 0.0
RAM 97508 97508 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 554026 554026 0 0.0
RAM 205504 205504 0 0.0
lock CC3235SF_LAUNCHXL FLASH 587278 587278 0 0.0
RAM 205768 205768 0 0.0
efr32 lock-app BRD4187C FLASH 962880 962880 0 0.0
RAM 126268 126268 0 0.0
BRD4338a FLASH 756080 756080 0 0.0
RAM 256888 256888 0 0.0
window-app BRD4187C FLASH 1057812 1057804 -8 -0.0
RAM 122464 122464 0 0.0
esp32 all-clusters-app c3devkit DRAM 103192 103192 0 0.0
FLASH 1795828 1795828 0 0.0
IRAM 83862 83862 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 932776 932776 0 0.0
RAM 161069 161069 0 0.0
nxp contact mcxw71+release FLASH 691360 691360 0 0.0
RAM 61424 61424 0 0.0
lighting mcxw71+release FLASH 722856 722856 0 0.0
RAM 68084 68084 0 0.0
lock mcxw71+release FLASH 773128 773128 0 0.0
RAM 61868 61868 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1675932 1675932 0 0.0
RAM 213660 213660 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1592540 1592540 0 0.0
RAM 210956 210956 0 0.0
light cy8ckit_062s2_43012 FLASH 1459156 1459156 0 0.0
RAM 197656 197656 0 0.0
lock cy8ckit_062s2_43012 FLASH 1491708 1491708 0 0.0
RAM 225376 225376 0 0.0
qpg lighting-app qpg6200+debug FLASH 836520 836520 0 0.0
RAM 127644 127644 0 0.0
lock-app qpg6200+debug FLASH 773220 773220 0 0.0
RAM 118620 118620 0 0.0
realtek light-switch-app rtl8777g FLASH 706208 706208 0 0.0
RAM 106800 106800 0 0.0
lighting-app rtl8777g FLASH 757304 757304 0 0.0
RAM 127164 127164 0 0.0
stm32 light STM32WB5MM-DK FLASH 469772 469772 0 0.0
RAM 141248 141248 0 0.0
telink bridge-app tl7218x FLASH 710402 710402 0 0.0
RAM 90436 90436 0 0.0
light-app-ota-compress-lzma-shell-factory-data tl3218x FLASH 796788 796788 0 0.0
RAM 40936 40936 0 0.0
light-app-ota-shell-factory-data tl7218x FLASH 787988 787988 0 0.0
RAM 93580 93580 0 0.0
light-switch-app-ota-compress-lzma-factory-data tl7218x_retention FLASH 714914 714914 0 0.0
RAM 51736 51736 0 0.0
light-switch-app-ota-compress-lzma-shell-factory-data tlsr9528a FLASH 748218 748218 0 0.0
RAM 70784 70784 0 0.0
light-switch-app-ota-factory-data tl3218x_retention FLASH 725066 725066 0 0.0
RAM 34484 34484 0 0.0
lighting-app-ota-factory-data tlsr9118bdk40d FLASH 602304 602304 0 0.0
RAM 108628 108628 0 0.0
lighting-app-ota-rpc-factory-data-4mb tlsr9518adk80d FLASH 820608 820612 4 0.0
RAM 91976 91976 0 0.0

@github-actions
Copy link

PR #41522: Size comparison from 63df482 to b6d0b32

Full report (1 build for stm32)
platform target config section 63df482 b6d0b32 change % change
stm32 light STM32WB5MM-DK FLASH 470092 470092 0 0.0
RAM 141304 141304 0 0.0

@github-actions
Copy link

github-actions bot commented Oct 24, 2025

PR #41522: Size comparison from 63df482 to 4e7aebf

Full report (37 builds for bl602, bl702, bl702l, cc13x4_26x4, cc32xx, efr32, esp32, nrfconnect, nxp, psoc6, qpg, realtek, stm32, telink)
platform target config section 63df482 4e7aebf change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1106622 1106622 0 0.0
RAM 178874 178874 0 0.0
bl702 lighting-app bl702+eth FLASH 661198 661198 0 0.0
RAM 134969 134969 0 0.0
bl702+wifi FLASH 837310 837310 0 0.0
RAM 124405 124405 0 0.0
bl706+mfd+rpc+littlefs FLASH 1070278 1070278 0 0.0
RAM 117261 117261 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 899730 899730 0 0.0
RAM 105524 105524 0 0.0
lighting-app bl702l+mfd+littlefs FLASH 983040 983040 0 0.0
RAM 109740 109740 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 770652 770652 0 0.0
RAM 103304 103304 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 782384 782384 0 0.0
RAM 108472 108472 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 728212 728212 0 0.0
RAM 97364 97364 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 712672 712672 0 0.0
RAM 97580 97580 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 554226 554226 0 0.0
RAM 205736 205736 0 0.0
lock CC3235SF_LAUNCHXL FLASH 587474 587474 0 0.0
RAM 205832 205832 0 0.0
efr32 lock-app BRD4187C FLASH 963160 963160 0 0.0
RAM 123512 123512 0 0.0
BRD4338a FLASH 756744 756744 0 0.0
RAM 254136 254136 0 0.0
window-app BRD4187C FLASH 1058492 1058484 -8 -0.0
RAM 119740 119740 0 0.0
esp32 all-clusters-app c3devkit DRAM 102516 102516 0 0.0
FLASH 1827430 1827430 0 0.0
IRAM 93540 93540 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 933076 933076 0 0.0
RAM 161313 161313 0 0.0
nxp contact mcxw71+release FLASH 691904 691904 0 0.0
RAM 61496 61496 0 0.0
lighting mcxw71+release FLASH 723408 723408 0 0.0
RAM 68140 68140 0 0.0
lock mcxw71+release FLASH 773672 773672 0 0.0
RAM 61932 61932 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1676564 1676564 0 0.0
RAM 213900 213900 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1593180 1593180 0 0.0
RAM 211108 211108 0 0.0
light cy8ckit_062s2_43012 FLASH 1459724 1459724 0 0.0
RAM 197728 197728 0 0.0
lock cy8ckit_062s2_43012 FLASH 1492276 1492276 0 0.0
RAM 225440 225440 0 0.0
qpg lighting-app qpg6200+debug FLASH 837104 837104 0 0.0
RAM 127708 127708 0 0.0
lock-app qpg6200+debug FLASH 773884 773884 0 0.0
RAM 118684 118684 0 0.0
realtek light-switch-app rtl8777g FLASH 706624 706624 0 0.0
RAM 106904 106904 0 0.0
lighting-app rtl8777g FLASH 757712 757712 0 0.0
RAM 127236 127236 0 0.0
stm32 light STM32WB5MM-DK FLASH 470092 470092 0 0.0
RAM 141304 141304 0 0.0
telink bridge-app tl7218x FLASH 710570 710570 0 0.0
RAM 90544 90544 0 0.0
light-app-ota-compress-lzma-shell-factory-data tl3218x FLASH 796924 796924 0 0.0
RAM 41000 41000 0 0.0
light-app-ota-shell-factory-data tl7218x FLASH 788124 788124 0 0.0
RAM 93644 93644 0 0.0
light-switch-app-ota-compress-lzma-factory-data tl7218x_retention FLASH 715002 715002 0 0.0
RAM 51844 51844 0 0.0
light-switch-app-ota-compress-lzma-shell-factory-data tlsr9528a FLASH 748298 748298 0 0.0
RAM 70892 70892 0 0.0
light-switch-app-ota-factory-data tl3218x_retention FLASH 725154 725154 0 0.0
RAM 34592 34592 0 0.0
lighting-app-ota-factory-data tlsr9118bdk40d FLASH 602398 602398 0 0.0
RAM 108904 108904 0 0.0
lighting-app-ota-rpc-factory-data-4mb tlsr9518adk80d FLASH 820728 820732 4 0.0
RAM 92040 92040 0 0.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants