From: Jouni Malinen Date: Thu, 11 Dec 2025 18:39:37 +0000 (+0200) Subject: proc_coord: Testing and example use of process coordination X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=00909128f3aa74ac9e96c7fda1f91e63bd3d459d;p=thirdparty%2Fhostap.git proc_coord: Testing and example use of process coordination Add hwsim testing for proc_coord to enable automated testing of this functionality. In addition, this shows a simple example on how the defined proc_coord API can be used. Signed-off-by: Jouni Malinen --- diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 4fa824b4a..67e84b6b2 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -40,6 +40,7 @@ #include "common/wpa_ctrl.h" #include "common/ptksa_cache.h" #include "common/nan_de.h" +#include "common/proc_coord.h" #include "crypto/tls.h" #include "drivers/driver.h" #include "eapol_auth/eapol_auth_sm.h" @@ -3873,6 +3874,69 @@ static int hostapd_ctrl_iface_sae_password_bind(struct hostapd_data *hapd, #endif /* CONFIG_SAE */ +#ifdef CONFIG_TESTING_OPTIONS +#ifdef CONFIG_PROCESS_COORDINATION + +static bool hapd_ctrl_proc_coord_cb(void *ctx, int src, + enum proc_coord_message_types msg_type, + enum proc_coord_commands cmd, + u32 seq, const struct wpabuf *msg) +{ + struct hostapd_data *hapd = ctx; + + if (cmd != PROC_COORD_CMD_TEST) + return false; + + wpa_msg(hapd->msg_ctx, MSG_INFO, + "PROC-COORD-TEST RX src=%u msg_type=%d seq=%u msg_len=%zu", + src, msg_type, seq, wpabuf_len(msg)); + + if (msg_type == PROC_COORD_MSG_REQUEST) + proc_coord_send_response(hapd->iface->interfaces->pc, + src, cmd, seq, msg); + return false; +} + + +static void hapd_ctrl_proc_coord_test_cb(void *ctx, int pid, + const struct wpabuf *msg) +{ + struct hostapd_data *hapd = ctx; + + wpa_msg(hapd->msg_ctx, MSG_INFO, + "PROC-COORD-TEST RX-RESP src=%u msg_len=%d", + pid, msg ? (int) wpabuf_len(msg) : -1); + +} + + +static int hostapd_ctrl_iface_proc_coord_test(struct hostapd_data *hapd, + const char *cmd) +{ + int res, dst; + struct wpabuf *msg; + + if (!hapd->iface->interfaces->pc) + return -1; + + dst = atoi(cmd); + + msg = wpabuf_alloc(1); + if (!msg) + return -1; + wpabuf_put_u8(msg, 123); + + res = proc_coord_send_request(hapd->iface->interfaces->pc, + dst, PROC_COORD_CMD_TEST, msg, 1000, + hapd_ctrl_proc_coord_test_cb, hapd); + wpabuf_free(msg); + return res < 0 ? -1 : 0; +} + +#endif /* CONFIG_PROCESS_COORDINATION */ +#endif /* CONFIG_TESTING_OPTIONS */ + + static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, char *buf, char *reply, int reply_size, @@ -4486,6 +4550,13 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, if (hostapd_ctrl_iface_sae_password_bind(hapd, buf + 18)) reply_len = -1; #endif /* CONFIG_SAE */ +#ifdef CONFIG_TESTING_OPTIONS +#ifdef CONFIG_PROCESS_COORDINATION + } else if (os_strncmp(buf, "PROC_COORD_TEST ", 16) == 0) { + if (hostapd_ctrl_iface_proc_coord_test(hapd, buf + 16)) + reply_len = -1; +#endif /* CONFIG_PROCESS_COORDINATION */ +#endif /* CONFIG_TESTING_OPTIONS */ } else { os_memcpy(reply, "UNKNOWN COMMAND\n", 16); reply_len = 16; @@ -5198,6 +5269,14 @@ fail: hapd->msg_ctx = hapd; wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); +#ifdef CONFIG_TESTING_OPTIONS +#ifdef CONFIG_PROCESS_COORDINATION + if (hapd->iface->interfaces->pc) + proc_coord_register_handler(hapd->iface->interfaces->pc, + hapd_ctrl_proc_coord_cb, hapd); +#endif /* CONFIG_PROCESS_COORDINATION */ +#endif /* CONFIG_TESTING_OPTIONS */ + return 0; fail: @@ -5253,6 +5332,14 @@ void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd) #ifdef CONFIG_TESTING_OPTIONS l2_packet_deinit(hapd->l2_test); hapd->l2_test = NULL; +#ifdef CONFIG_PROCESS_COORDINATION + if (hapd->iface->interfaces->pc) { + proc_coord_unregister_handler(hapd->iface->interfaces->pc, + hapd_ctrl_proc_coord_cb, hapd); + proc_coord_cancel_wait(hapd->iface->interfaces->pc, + hapd_ctrl_proc_coord_test_cb, hapd); + } +#endif /* CONFIG_PROCESS_COORDINATION */ #endif /* CONFIG_TESTING_OPTIONS */ } diff --git a/src/common/proc_coord.h b/src/common/proc_coord.h index 47b09c40b..8eae44344 100644 --- a/src/common/proc_coord.h +++ b/src/common/proc_coord.h @@ -21,6 +21,7 @@ enum proc_coord_commands { PROC_COORD_CMD_STARTING = 0, PROC_COORD_CMD_STOPPING = 1, PROC_COORD_CMD_PING = 2, + PROC_COORD_CMD_TEST = 3, }; /** diff --git a/tests/hwsim/example-hostapd.config b/tests/hwsim/example-hostapd.config index c75395c00..65e6d7e5e 100644 --- a/tests/hwsim/example-hostapd.config +++ b/tests/hwsim/example-hostapd.config @@ -124,3 +124,4 @@ CONFIG_PASN=y CONFIG_AIRTIME_POLICY=y CONFIG_IEEE80211BE=y CONFIG_NAN_USD=y +CONFIG_PROCESS_COORDINATION=y diff --git a/tests/hwsim/example-wpa_supplicant.config b/tests/hwsim/example-wpa_supplicant.config index a43bdc5ce..d9b26464c 100644 --- a/tests/hwsim/example-wpa_supplicant.config +++ b/tests/hwsim/example-wpa_supplicant.config @@ -169,3 +169,4 @@ CONFIG_PASN=y CONFIG_NAN_USD=y CONFIG_IEEE80211BE=y +CONFIG_PROCESS_COORDINATION=y diff --git a/tests/hwsim/test_proc_coord.py b/tests/hwsim/test_proc_coord.py new file mode 100644 index 000000000..beda15ad8 --- /dev/null +++ b/tests/hwsim/test_proc_coord.py @@ -0,0 +1,96 @@ +# Test cases for process coordination +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# +# This software may be distributed under the terms of the BSD license. +# See README for more details. + +import os +import stat +import subprocess +import tempfile + +from hwsim import HWSimRadio +from utils import * + +def test_proc_coord_hostapd(dev, apdev, params): + """Process coordination in hostapd""" + dir = "/tmp/hostapd-proc-coord" + os.mkdir(dir) + os.chmod(dir, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR) + + with HWSimRadio(use_mlo=True, n_channels=2) as (hapd_radio, hapd_iface): + hapd_iface2 = hapd_iface + '-2' + cmd = ['iw', 'phy' + str(hapd_radio), 'interface', 'add', + hapd_iface2, 'type', '__ap'] + proc = subprocess.Popen(cmd, stderr=subprocess.STDOUT, + stdout=subprocess.PIPE, shell=False) + out, err = proc.communicate() + logger.debug("iw output: " + out.decode()) + + fd, fname = tempfile.mkstemp(dir='/tmp', prefix='hostapd-cfg-') + f = os.fdopen(fd, 'w') + f.write("driver=nl80211\n") + f.write("ctrl_interface=/var/run/hostapd\n") + f.write("hw_mode=g\n") + f.write("channel=1\n") + f.write("ieee80211n=1\n") + f.write("ssid=foo\n") + f.close() + + pid1 = params['prefix'] + ".hostapd.pid-1" + cmd = ['../../hostapd/hostapd', '-ddKtB', '-P', pid1, '-f', + params['prefix'] + ".hostapd-log-1", + '-i', hapd_iface, + '-z', dir, + fname] + res = subprocess.check_call(cmd) + if res != 0: + raise Exception("Could not start hostapd: %s" % str(res)) + + pid2 = params['prefix'] + ".hostapd.pid-2" + cmd = ['../../hostapd/hostapd', '-ddKtB', '-P', pid2, '-f', + params['prefix'] + ".hostapd-log-2", + '-i', hapd_iface2, + '-z', dir, + fname] + res = subprocess.check_call(cmd) + if res != 0: + raise Exception("Could not start hostapd: %s" % str(res)) + + time.sleep(2) + for i in range(20): + if os.path.exists(pid1) and os.path.exists(pid2): + break + time.sleep(0.2) + + if not (os.path.exists(pid1) and os.path.exists(pid2)): + raise Exception("hostapd did not create PID file.") + + hapd1 = hostapd.Hostapd(hapd_iface) + hapd1.ping() + + hapd2 = hostapd.Hostapd(hapd_iface2) + hapd2.ping() + + if "OK" not in hapd1.request("PROC_COORD_TEST 0"): + raise Exception("PROC_COORD_TEST failed") + + ev = hapd1.wait_event(["PROC-COORD-TEST"], timeout=5) + if ev is None: + raise Exception("hapd1 did not report PROC-COORD-TEST") + if " RX-RESP " not in ev: + raise Exception("Unexpected hapd1 PROC-COORD-TEST contents") + if " msg_len=1" not in ev: + raise Exception("Unexpected hapd1 PROC-COORD-TEST msg_len") + + ev = hapd2.wait_event(["PROC-COORD-TEST"], timeout=5) + if ev is None: + raise Exception("hapd2 did not report PROC-COORD-TEST") + if " RX " not in ev: + raise Exception("Unexpected hapd2 PROC-COORD-TEST contents") + + hapd1.request("TERMINATE") + hapd2.request("TERMINATE") + time.sleep(1) + + os.rmdir(dir)