Andriud13 hostapd addAccessPoint流程

在WifiService的startSoftAp流程中我们分析了HAL层以上的流程,最终framework层会调用IHostapd的addAccessPoint方法,IHostapd为AIDL接口,由hostapd HAL的addAccessPoint实现,我们继续分析hostapd HAL流程:

wpa_supplicant/hostapd/hostapd.cpp
::ndk::ScopedAStatus Hostapd::addAccessPoint(
	const IfaceParams& iface_params, const NetworkParams& nw_params)
{
	return addAccessPointInternal(iface_params, nw_params);
}


::ndk::ScopedAStatus Hostapd::addAccessPointInternal(
	const IfaceParams& iface_params,
	const NetworkParams& nw_params)
{
	int channelParamsSize = iface_params.channelParams.size();
	if (channelParamsSize == 1) {
		// Single AP
		wpa_printf(MSG_INFO, "AddSingleAccessPoint, iface=%s",
			iface_params.name.c_str());
		return addSingleAccessPoint(iface_params, iface_params.channelParams[0],
		    nw_params, "", ""); //添加单个接入点
	} else if (channelParamsSize == 2) {
		// Concurrent APs
		wpa_printf(MSG_INFO, "AddDualAccessPoint, iface=%s",
			iface_params.name.c_str());
		return addConcurrentAccessPoints(iface_params, nw_params); //添加并发接入点
	}
	return createStatus(HostapdStatusCode::FAILURE_ARGS_INVALID);
}

addAccessPoint会调用addAccessPointInternal,addAccessPointInternal根据channelParamsSize调用addSingleAccessPoint或addConcurrentAccessPoints来添加接入点,我们来分析addSingleAccessPoint的情况:

wpa_supplicant/hostapd/hostapd.cpp
::ndk::ScopedAStatus Hostapd::addSingleAccessPoint(
	const IfaceParams& iface_params,
	const ChannelParams& channelParams,
	const NetworkParams& nw_params,
	const std::string br_name,
	const std::string owe_transition_ifname)
{
	if (hostapd_get_iface(interfaces_, iface_params.name.c_str())) {
		wpa_printf(
			MSG_ERROR, "Interface %s already present",
			iface_params.name.c_str());
		return createStatus(HostapdStatusCode::FAILURE_IFACE_EXISTS);
	}
	const auto conf_params = CreateHostapdConfig(iface_params, channelParams, nw_params,
					br_name, owe_transition_ifname);
	if (conf_params.empty()) {
		wpa_printf(MSG_ERROR, "Failed to create config params");
		return createStatus(HostapdStatusCode::FAILURE_ARGS_INVALID);
	}
	const auto conf_file_path =
		WriteHostapdConfig(iface_params.name, conf_params);
	if (conf_file_path.empty()) {
		wpa_printf(MSG_ERROR, "Failed to write config file");
		return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
	}
	std::string add_iface_param_str = StringPrintf(
		"%s config=%s", iface_params.name.c_str(),
		conf_file_path.c_str());
	std::vector<char> add_iface_param_vec(
		add_iface_param_str.begin(), add_iface_param_str.end() + 1);
	if (hostapd_add_iface(interfaces_, add_iface_param_vec.data()) < 0) {
		wpa_printf(
			MSG_ERROR, "Adding interface %s failed",
			add_iface_param_str.c_str());
		return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
	}
	struct hostapd_data* iface_hapd =
	    hostapd_get_iface(interfaces_, iface_params.name.c_str());
	WPA_ASSERT(iface_hapd != nullptr && iface_hapd->iface != nullptr);
	// Register the setup complete callbacks
	on_setup_complete_internal_callback =
		[this](struct hostapd_data* iface_hapd) {
			wpa_printf(
			MSG_INFO, "AP interface setup completed - state %s",
			hostapd_state_text(iface_hapd->iface->state));
			if (iface_hapd->iface->state == HAPD_IFACE_DISABLED) {
				// Invoke the failure callback on all registered
				// clients.
				for (const auto& callback : callbacks_) {
					callback->onFailure(strlen(iface_hapd->conf->bridge) > 0 ?
						iface_hapd->conf->bridge : iface_hapd->conf->iface,
							    iface_hapd->conf->iface);
				}
			}
		};


	// Register for new client connect/disconnect indication.
	on_sta_authorized_internal_callback =
		[this](struct hostapd_data* iface_hapd, const u8 *mac_addr,
			int authorized, const u8 *p2p_dev_addr) {
		wpa_printf(MSG_DEBUG, "notify client " MACSTR " %s",
				MAC2STR(mac_addr),
				(authorized) ? "Connected" : "Disconnected");
		ClientInfo info;
		info.ifaceName = strlen(iface_hapd->conf->bridge) > 0 ?
			iface_hapd->conf->bridge : iface_hapd->conf->iface;
		info.apIfaceInstance = iface_hapd->conf->iface;
		info.clientAddress.assign(mac_addr, mac_addr + ETH_ALEN);
		info.isConnected = authorized;
		for (const auto &callback : callbacks_) {
			callback->onConnectedClientsChanged(info);
		}
		};


	// Register for wpa_event which used to get channel switch event
	on_wpa_msg_internal_callback =
		[this](struct hostapd_data* iface_hapd, int level,
			enum wpa_msg_type type, const char *txt,
			size_t len) {
		wpa_printf(MSG_DEBUG, "Receive wpa msg : %s", txt);
		if (os_strncmp(txt, AP_EVENT_ENABLED,
					strlen(AP_EVENT_ENABLED)) == 0 ||
			os_strncmp(txt, WPA_EVENT_CHANNEL_SWITCH,
					strlen(WPA_EVENT_CHANNEL_SWITCH)) == 0) {
			ApInfo info;
			info.ifaceName = strlen(iface_hapd->conf->bridge) > 0 ?
				iface_hapd->conf->bridge : iface_hapd->conf->iface,
			info.apIfaceInstance = iface_hapd->conf->iface;
			info.freqMhz = iface_hapd->iface->freq;
			info.channelBandwidth = getChannelBandwidth(iface_hapd->iconf);
			info.generation = getGeneration(iface_hapd->iface->current_mode);
			info.apIfaceInstanceMacAddress.assign(iface_hapd->own_addr,
				iface_hapd->own_addr + ETH_ALEN);
			for (const auto &callback : callbacks_) {
				callback->onApInstanceInfoChanged(info);
			}
		} else if (os_strncmp(txt, AP_EVENT_DISABLED, strlen(AP_EVENT_DISABLED)) == 0
                           || os_strncmp(txt, INTERFACE_DISABLED, strlen(INTERFACE_DISABLED)) == 0)
		{
			// Invoke the failure callback on all registered clients.
			for (const auto& callback : callbacks_) {
				callback->onFailure(strlen(iface_hapd->conf->bridge) > 0 ?
					iface_hapd->conf->bridge : iface_hapd->conf->iface,
						    iface_hapd->conf->iface);
			}
		}
	};


	// Setup callback
	iface_hapd->setup_complete_cb = onAsyncSetupCompleteCb;
	iface_hapd->setup_complete_cb_ctx = iface_hapd;
	iface_hapd->sta_authorized_cb = onAsyncStaAuthorizedCb;
	iface_hapd->sta_authorized_cb_ctx = iface_hapd;
	wpa_msg_register_cb(onAsyncWpaEventCb);


	if (hostapd_enable_iface(iface_hapd->iface) < 0) {
		wpa_printf(
			MSG_ERROR, "Enabling interface %s failed",
			iface_params.name.c_str());
		return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
	}
	return ndk::ScopedAStatus::ok();
}

这个函数主要调用如下几个函数:

hostapd_get_iface:获取接口

hostapd_add_iface:增加接口

hostapd_enable_iface:使能接口 其中hostapd_enable_iface的代码如下:

wpa_supplicant/hostapd/hostapd.cpp
int hostapd_enable_iface(struct hostapd_iface *hapd_iface)
{
	size_t j;


	if (!hapd_iface)
		return -1;


	if (hapd_iface->enable_iface_cb)
		return hapd_iface->enable_iface_cb(hapd_iface); //调用hapd_iface的enable_iface_cb


	if (hapd_iface->bss[0]->drv_priv != NULL) {
		wpa_printf(MSG_ERROR, "Interface %s already enabled",
			   hapd_iface->conf->bss[0]->iface);
		return -1;
	}


	wpa_printf(MSG_DEBUG, "Enable interface %s",
		   hapd_iface->conf->bss[0]->iface);


	for (j = 0; j < hapd_iface->num_bss; j++)
		hostapd_set_security_params(hapd_iface->conf->bss[j], 1);
	if (hostapd_config_check(hapd_iface->conf, 1) < 0) {
		wpa_printf(MSG_INFO, "Invalid configuration - cannot enable");
		return -1;
	}


	if (hapd_iface->interfaces == NULL ||
	    hapd_iface->interfaces->driver_init == NULL ||
	    hapd_iface->interfaces->driver_init(hapd_iface))
		return -1;


	if (hostapd_setup_interface(hapd_iface)) {
		hostapd_deinit_driver(hapd_iface->bss[0]->driver,
				      hapd_iface->bss[0]->drv_priv,
				      hapd_iface);
		return -1;
	}


	return 0;
}

调用hapd_iface的enable_iface_cb函数,hapd_iface->enable_iface_cb在初始化赋值为wpa_supplicant_mesh_enable_iface_cb,因此会调用wpa_supplicant_mesh_enable_iface_cb函数:

wpa_supplicant_8/wpa_supplicant/mesh.c
static int wpa_supplicant_mesh_enable_iface_cb(struct hostapd_iface *ifmsh)
{
	struct wpa_supplicant *wpa_s = ifmsh->owner;
	struct hostapd_data *bss;


	ifmsh->mconf = mesh_config_create(wpa_s, wpa_s->current_ssid);


	bss = ifmsh->bss[0];
	bss->msg_ctx = wpa_s;
	os_memcpy(bss->own_addr, wpa_s->own_addr, ETH_ALEN);
	bss->driver = wpa_s->driver;
	bss->drv_priv = wpa_s->drv_priv;
	bss->iface = ifmsh;
	bss->mesh_sta_free_cb = mesh_mpm_free_sta;
	bss->setup_complete_cb = wpas_mesh_complete_cb;
	bss->setup_complete_cb_ctx = wpa_s;


	bss->conf->start_disabled = 1;
	bss->conf->mesh = MESH_ENABLED;
	bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity;


	if (wpa_drv_init_mesh(wpa_s)) {
		wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver");
		return -1;
	}


	if (hostapd_setup_interface(ifmsh)) { //调用hostapd_setup_interface
		wpa_printf(MSG_ERROR,
			   "Failed to initialize hostapd interface for mesh");
		return -1;
	}


	return 0;
}

调用hostapd_setup_interface函数:

wpa_supplicant/hostapd/hostapd.cpp
int hostapd_setup_interface(struct hostapd_iface *iface)
{
	int ret;


	if (!iface->conf)
		return -1;
	ret = setup_interface(iface);
	if (ret) {
		wpa_printf(MSG_ERROR, "%s: Unable to setup interface.",
			   iface->conf->bss[0]->iface);
		return -1;
	}


	return 0;
}

调用setup_interface函数:

wpa_supplicant/hostapd/hostapd.cpp
static int setup_interface(struct hostapd_iface *iface)
{
	struct hostapd_data *hapd = iface->bss[0];
	size_t i;


	/*
	 * It is possible that setup_interface() is called after the interface
	 * was disabled etc., in which case driver_ap_teardown is possibly set
	 * to 1. Clear it here so any other key/station deletion, which is not
	 * part of a teardown flow, would also call the relevant driver
	 * callbacks.
	 */
	iface->driver_ap_teardown = 0;


	if (!iface->phy[0]) {
		const char *phy = hostapd_drv_get_radio_name(hapd);
		if (phy) {
			wpa_printf(MSG_DEBUG, "phy: %s", phy);
			os_strlcpy(iface->phy, phy, sizeof(iface->phy));
		}
	}


	/*
	 * Make sure that all BSSes get configured with a pointer to the same
	 * driver interface.
	 */
	for (i = 1; i < iface->num_bss; i++) {
		iface->bss[i]->driver = hapd->driver;
		iface->bss[i]->drv_priv = hapd->drv_priv;
	}


	if (hostapd_validate_bssid_configuration(iface))
		return -1;


	/*
	 * Initialize control interfaces early to allow external monitoring of
	 * channel setup operations that may take considerable amount of time
	 * especially for DFS cases.
	 */
	if (start_ctrl_iface(iface))
		return -1;


	if (hapd->iconf->country[0] && hapd->iconf->country[1]) {
		char country[4], previous_country[4];


		hostapd_set_state(iface, HAPD_IFACE_COUNTRY_UPDATE);
		if (hostapd_get_country(hapd, previous_country) < 0)
			previous_country[0] = '\0';


		os_memcpy(country, hapd->iconf->country, 3);
		country[3] = '\0';
		if (hostapd_set_country(hapd, country) < 0) {
			wpa_printf(MSG_ERROR, "Failed to set country code");
			return -1;
		}


		wpa_printf(MSG_DEBUG, "Previous country code %s, new country code %s",
			   previous_country, country);


		if (os_strncmp(previous_country, country, 2) != 0) {
			wpa_printf(MSG_DEBUG, "Continue interface setup after channel list update");
			iface->wait_channel_update = 1;
			eloop_register_timeout(5, 0,
					       channel_list_update_timeout,
					       iface, NULL);
			return 0;
		}
	}


	return setup_interface2(iface); //调用setup_interface2
}

调用setup_interface2函数:

wpa_supplicant/hostapd/hostapd.cpp
static int setup_interface2(struct hostapd_iface *iface)
{
	iface->wait_channel_update = 0;


	if (hostapd_get_hw_features(iface)) {
		/* Not all drivers support this yet, so continue without hw
		 * feature data. */
	} else {
		int ret;


		ret = configured_fixed_chan_to_freq(iface);
		if (ret < 0)
			goto fail;


		if (iface->conf->op_class) {
			int ch_width;


			ch_width = op_class_to_ch_width(iface->conf->op_class);
			hostapd_set_oper_chwidth(iface->conf, ch_width);
			hostapd_set_6ghz_sec_chan(iface);
		}


		ret = hostapd_select_hw_mode(iface);
		if (ret < 0) {
			wpa_printf(MSG_ERROR, "Could not select hw_mode and "
				   "channel. (%d)", ret);
			goto fail;
		}
		if (ret == 1) {
			wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback (ACS)");
			return 0;
		}
		ret = hostapd_check_edmg_capab(iface);
		if (ret < 0)
			goto fail;
		ret = hostapd_check_he_6ghz_capab(iface);
		if (ret < 0)
			goto fail;
		ret = hostapd_check_ht_capab(iface);
		if (ret < 0)
			goto fail;
		if (ret == 1) {
			wpa_printf(MSG_DEBUG, "Interface initialization will "
				   "be completed in a callback");
			return 0;
		}


		if (iface->conf->ieee80211h)
			wpa_printf(MSG_DEBUG, "DFS support is enabled");
	}
	return hostapd_setup_interface_complete(iface, 0); //调用hostapd_setup_interface_complete函数


fail:
	hostapd_set_state(iface, HAPD_IFACE_DISABLED);
	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
	if (iface->interfaces && iface->interfaces->terminate_on_error)
		eloop_terminate();
	return -1;
}

在setup_interface2中会检查一些参数,然后调用hostapd_setup_interface_complete函数:

wpa_supplicant/hostapd/hostapd.cpp
int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
{
	struct hapd_interfaces *interfaces = iface->interfaces;
	struct hostapd_data *hapd = iface->bss[0];
	unsigned int i;
	int not_ready_in_sync_ifaces = 0;


	if (!iface->need_to_start_in_sync)
		return hostapd_setup_interface_complete_sync(iface, err);


	if (err) {
		wpa_printf(MSG_ERROR, "Interface initialization failed");
		hostapd_set_state(iface, HAPD_IFACE_DISABLED);
		iface->need_to_start_in_sync = 0;
		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
		if (interfaces && interfaces->terminate_on_error)
			eloop_terminate();
		return -1;
	}


	if (iface->ready_to_start_in_sync) {
		/* Already in ready and waiting. should never happpen */
		return 0;
	}


	for (i = 0; i < interfaces->count; i++) {
		if (interfaces->iface[i]->need_to_start_in_sync &&
		    !interfaces->iface[i]->ready_to_start_in_sync)
			not_ready_in_sync_ifaces++;
	}


	/*
	 * Check if this is the last interface, if yes then start all the other
	 * waiting interfaces. If not, add this interface to the waiting list.
	 */
	if (not_ready_in_sync_ifaces > 1 && iface->state == HAPD_IFACE_DFS) {
		/*
		 * If this interface went through CAC, do not synchronize, just
		 * start immediately.
		 */
		iface->need_to_start_in_sync = 0;
		wpa_printf(MSG_INFO,
			   "%s: Finished CAC - bypass sync and start interface",
			   iface->bss[0]->conf->iface);
		return hostapd_setup_interface_complete_sync(iface, err);
	}


	if (not_ready_in_sync_ifaces > 1) {
		/* need to wait as there are other interfaces still coming up */
		iface->ready_to_start_in_sync = 1;
		wpa_printf(MSG_INFO,
			   "%s: Interface waiting to sync with other interfaces",
			   iface->bss[0]->conf->iface);
		return 0;
	}


	wpa_printf(MSG_INFO,
		   "%s: Last interface to sync - starting all interfaces",
		   iface->bss[0]->conf->iface);
	iface->need_to_start_in_sync = 0;
	hostapd_setup_interface_complete_sync(iface, err);
	for (i = 0; i < interfaces->count; i++) {
		if (interfaces->iface[i]->need_to_start_in_sync &&
		    interfaces->iface[i]->ready_to_start_in_sync) {
			hostapd_setup_interface_complete_sync(
				interfaces->iface[i], 0);
			/* Only once the interfaces are sync started */
			interfaces->iface[i]->need_to_start_in_sync = 0;
		}
	}


	return 0;
}

调用hostapd_setup_interface_complete_sync函数:

wpa_supplicant/hostapd/hostapd.cpp
static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
						 int err)
{
	struct hostapd_data *hapd = iface->bss[0];
	size_t j;
	u8 *prev_addr;
	int delay_apply_cfg = 0;
	int res_dfs_offload = 0;


	if (err)
		goto fail;


	wpa_printf(MSG_DEBUG, "Completing interface initialization");
	if (iface->freq) {
#ifdef NEED_AP_MLME
		int res;
#endif /* NEED_AP_MLME */


		wpa_printf(MSG_DEBUG, "Mode: %s  Channel: %d  "
			   "Frequency: %d MHz",
			   hostapd_hw_mode_txt(iface->conf->hw_mode),
			   iface->conf->channel, iface->freq);


#ifdef NEED_AP_MLME
		/* Handle DFS only if it is not offloaded to the driver */
		if (!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)) {
			/* Check DFS */
			res = hostapd_handle_dfs(iface);
			if (res <= 0) {
				if (res < 0)
					goto fail;
				return res;
			}
		} else {
			/* If DFS is offloaded to the driver */
			res_dfs_offload = hostapd_handle_dfs_offload(iface);
			if (res_dfs_offload <= 0) {
				if (res_dfs_offload < 0)
					goto fail;
			} else {
				wpa_printf(MSG_DEBUG,
					   "Proceed with AP/channel setup");
				/*
				 * If this is a DFS channel, move to completing
				 * AP setup.
				 */
				if (res_dfs_offload == 1)
					goto dfs_offload;
				/* Otherwise fall through. */
			}
		}
#endif /* NEED_AP_MLME */


#ifdef CONFIG_MESH
		if (iface->mconf != NULL) {
			wpa_printf(MSG_DEBUG,
				   "%s: Mesh configuration will be applied while joining the mesh network",
				   iface->bss[0]->conf->iface);
			delay_apply_cfg = 1;
		}
#endif /* CONFIG_MESH */


		if (!delay_apply_cfg &&
		    hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq,
				     hapd->iconf->channel,
				     hapd->iconf->enable_edmg,
				     hapd->iconf->edmg_channel,
				     hapd->iconf->ieee80211n,
				     hapd->iconf->ieee80211ac,
				     hapd->iconf->ieee80211ax,
				     hapd->iconf->secondary_channel,
				     hostapd_get_oper_chwidth(hapd->iconf),
				     hostapd_get_oper_centr_freq_seg0_idx(
					     hapd->iconf),
				     hostapd_get_oper_centr_freq_seg1_idx(
					     hapd->iconf))) {
			wpa_printf(MSG_ERROR, "Could not set channel for "
				   "kernel driver");
			goto fail;
		}
	}


	if (iface->current_mode) {
		if (hostapd_prepare_rates(iface, iface->current_mode)) {
			wpa_printf(MSG_ERROR, "Failed to prepare rates "
				   "table.");
			hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
				       HOSTAPD_LEVEL_WARNING,
				       "Failed to prepare rates table.");
			goto fail;
		}
	}


	if (hapd->iconf->rts_threshold >= -1 &&
	    hostapd_set_rts(hapd, hapd->iconf->rts_threshold) &&
	    hapd->iconf->rts_threshold >= -1) {
		wpa_printf(MSG_ERROR, "Could not set RTS threshold for "
			   "kernel driver");
		goto fail;
	}


	if (hapd->iconf->fragm_threshold >= -1 &&
	    hostapd_set_frag(hapd, hapd->iconf->fragm_threshold) &&
	    hapd->iconf->fragm_threshold != -1) {
		wpa_printf(MSG_ERROR, "Could not set fragmentation threshold "
			   "for kernel driver");
		goto fail;
	}


	prev_addr = hapd->own_addr;


	for (j = 0; j < iface->num_bss; j++) {
		hapd = iface->bss[j];
		if (j)
			os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
		if (hostapd_setup_bss(hapd, j == 0)) {
			for (;;) {
				hapd = iface->bss[j];
				hostapd_bss_deinit_no_free(hapd);
				hostapd_free_hapd_data(hapd);
				if (j == 0)
					break;
				j--;
			}
			goto fail;
		}
		if (is_zero_ether_addr(hapd->conf->bssid))
			prev_addr = hapd->own_addr;
	}
	hapd = iface->bss[0];


	hostapd_tx_queue_params(iface);


	ap_list_init(iface);


	hostapd_set_acl(hapd);


	if (hostapd_driver_commit(hapd) < 0) {
		wpa_printf(MSG_ERROR, "%s: Failed to commit driver "
			   "configuration", __func__);
		goto fail;
	}


	/*
	 * WPS UPnP module can be initialized only when the "upnp_iface" is up.
	 * If "interface" and "upnp_iface" are the same (e.g., non-bridge
	 * mode), the interface is up only after driver_commit, so initialize
	 * WPS after driver_commit.
	 */
	for (j = 0; j < iface->num_bss; j++) {
		if (hostapd_init_wps_complete(iface->bss[j]))
			goto fail;
	}


	if ((iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
	    !res_dfs_offload) {
		/*
		 * If freq is DFS, and DFS is offloaded to the driver, then wait
		 * for CAC to complete.
		 */
		wpa_printf(MSG_DEBUG, "%s: Wait for CAC to complete", __func__);
		return res_dfs_offload;
	}


#ifdef NEED_AP_MLME
dfs_offload:
#endif /* NEED_AP_MLME */


#ifdef CONFIG_FST
	if (hapd->iconf->fst_cfg.group_id[0]) {
		struct fst_wpa_obj iface_obj;


		fst_hostapd_fill_iface_obj(hapd, &iface_obj);
		iface->fst = fst_attach(hapd->conf->iface, hapd->own_addr,
					&iface_obj, &hapd->iconf->fst_cfg);
		if (!iface->fst) {
			wpa_printf(MSG_ERROR, "Could not attach to FST %s",
				   hapd->iconf->fst_cfg.group_id);
			goto fail;
		}
	}
#endif /* CONFIG_FST */


	hostapd_set_state(iface, HAPD_IFACE_ENABLED);
	hostapd_owe_update_trans(iface);
	airtime_policy_update_init(iface);
	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_ENABLED);
	if (hapd->setup_complete_cb)
		hapd->setup_complete_cb(hapd->setup_complete_cb_ctx);


#ifdef CONFIG_MESH
	if (delay_apply_cfg && !iface->mconf) {
		wpa_printf(MSG_ERROR, "Error while completing mesh init");
		goto fail;
	}
#endif /* CONFIG_MESH */


	wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
		   iface->bss[0]->conf->iface);
	if (iface->interfaces && iface->interfaces->terminate_on_error > 0)
		iface->interfaces->terminate_on_error--;


	for (j = 0; j < iface->num_bss; j++)
		hostapd_neighbor_set_own_report(iface->bss[j]);


	return 0;


fail:
	wpa_printf(MSG_ERROR, "Interface initialization failed");
	hostapd_set_state(iface, HAPD_IFACE_DISABLED);
	wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
#ifdef CONFIG_FST
	if (iface->fst) {
		fst_detach(iface->fst);
		iface->fst = NULL;
	}
#endif /* CONFIG_FST */


	if (iface->interfaces && iface->interfaces->terminate_on_error) {
		eloop_terminate();
	} else if (hapd->setup_complete_cb) {
		/*
		 * Calling hapd->setup_complete_cb directly may cause iface
		 * deinitialization which may be accessed later by the caller.
		 */
		eloop_register_timeout(0, 0,
				       hostapd_interface_setup_failure_handler,
				       iface, NULL);
	}


	return -1;
}

hostapd_setup_interface_complete_sync函数主要调用了如下函数:

hostapd_set_freq

hostapd_prepare_rates

hostapd_set_rts

hostapd_set_frag

hostapd_setup_bss

hostapd_tx_queue_params

hostapd_set_acl

hostapd_driver_commit

hostapd_owe_update_trans

我们看一下hostapd_set_freq的处理:

wpa_supplicant/srv/ap/ap_drv_ops.c
int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
		     int freq, int channel, int edmg, u8 edmg_channel,
		     int ht_enabled, int vht_enabled,
		     int he_enabled,
		     int sec_channel_offset, int oper_chwidth,
		     int center_segment0, int center_segment1)
{
	struct hostapd_freq_params data;
	struct hostapd_hw_modes *cmode = hapd->iface->current_mode;


	if (hostapd_set_freq_params(&data, mode, freq, channel, edmg,
				    edmg_channel, ht_enabled,
				    vht_enabled, he_enabled, sec_channel_offset,
				    oper_chwidth,
				    center_segment0, center_segment1,
				    cmode ? cmode->vht_capab : 0,
				    cmode ?
				    &cmode->he_capab[IEEE80211_MODE_AP] : NULL)) //设置freq参数
		return -1;


	if (hapd->driver == NULL)
		return 0;
	if (hapd->driver->set_freq == NULL)
		return 0;
	return hapd->driver->set_freq(hapd->drv_priv, &data); //调用driver的set_freq方法设置freq
}

hostapd_set_freq设置freq参数,将参数数据整合到data中,然后调用hapd->driver->set_freq到kernel驱动,通过搜索代码得知hapd->driver->set_freq的指向为bsd_set_freq:

wpa_supplicant_8/wpa_supplicant/driver/driver_bsd.c
static int bsd_set_freq(void *priv, struct hostapd_freq_params *freq)
{
	struct bsd_driver_data *drv = priv;
#ifdef SIOCS80211CHANNEL
	struct ieee80211chanreq creq;
#endif /* SIOCS80211CHANNEL */
	u32 mode;
	int channel = freq->channel;


	if (channel < 14) {
		mode =
			freq->ht_enabled ? IFM_IEEE80211_11NG :
			IFM_IEEE80211_11G;
	} else if (channel == 14) {
		mode = IFM_IEEE80211_11B;
	} else {
		mode =
			freq->ht_enabled ? IFM_IEEE80211_11NA :
			IFM_IEEE80211_11A;
	}
	if (bsd_set_mediaopt(drv, IFM_MMASK, mode) < 0) {
		wpa_printf(MSG_ERROR, "%s: failed to set modulation mode",
			   __func__);
		return -1;
	}


#ifdef SIOCS80211CHANNEL
	os_memset(&creq, 0, sizeof(creq));
	os_strlcpy(creq.i_name, drv->ifname, sizeof(creq.i_name));
	creq.i_channel = (u_int16_t)channel;
	return ioctl(drv->global->sock, SIOCS80211CHANNEL, &creq);
#else /* SIOCS80211CHANNEL */
	return set80211param(priv, IEEE80211_IOC_CHANNEL, channel); //调用set80211param函数
#endif /* SIOCS80211CHANNEL */
}

调用set80211param函数:

static int set80211param(struct bsd_driver_data *drv, int op, int arg)
{
	return bsd_set80211(drv, op, arg, NULL, 0);
}


static int bsd_set80211(void *priv, int op, int val, const void *arg, int arg_len)
{
	struct bsd_driver_data *drv = priv;
	struct ieee80211req ireq;


	if (drv->ifindex == 0 || drv->if_removed)
		return -1;


	os_memset(&ireq, 0, sizeof(ireq));
	os_strlcpy(ireq.i_name, drv->ifname, sizeof(ireq.i_name));
	ireq.i_type = op;
	ireq.i_val = val;
	ireq.i_data = (void *) arg;
	ireq.i_len = arg_len;


	if (ioctl(drv->global->sock, SIOCS80211, &ireq) < 0) { //通过ioctl向SIOCS80211发消息
		wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, val=%u, "
			   "arg_len=%u]: %s", op, val, arg_len,
			   strerror(errno));
		return -1;
	}
	return 0;
}
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值