diff --git a/src/common/defs.h b/src/common/defs.h index ffe4fecf7..f15c5cc32 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -389,4 +389,7 @@ enum eap_proxy_sim_state { SIM_STATE_ERROR, }; +#define OCE_STA BIT(0) +#define OCE_STA_CFON BIT(1) + #endif /* DEFS_H */ diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 4bad31f2d..37489f716 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -3857,6 +3857,7 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, config->mbo_cell_capa = DEFAULT_MBO_CELL_CAPA; config->disassoc_imminent_rssi_threshold = DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD; + config->oce = DEFAULT_OCE_SUPPORT; #endif /* CONFIG_MBO */ if (ctrl_interface) @@ -4571,6 +4572,7 @@ static const struct global_parse_data global_fields[] = { { INT_RANGE(mbo_cell_capa, MBO_CELL_CAPA_AVAILABLE, MBO_CELL_CAPA_NOT_SUPPORTED), 0 }, { INT_RANGE(disassoc_imminent_rssi_threshold, -120, 0), 0 }, + { INT_RANGE(oce, 0, 3), 0 }, #endif /* CONFIG_MBO */ { INT(gas_address3), 0 }, { INT_RANGE(ftm_responder, 0, 1), 0 }, diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 6388a832b..6a2c8028d 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -42,6 +42,7 @@ #define DEFAULT_WPA_RSC_RELAXATION 1 #define DEFAULT_MBO_CELL_CAPA MBO_CELL_CAPA_NOT_SUPPORTED #define DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD -75 +#define DEFAULT_OCE_SUPPORT OCE_STA #include "config_ssid.h" #include "wps/wps.h" @@ -1314,6 +1315,13 @@ struct wpa_config { * when disassociation imminent is set. */ int disassoc_imminent_rssi_threshold; + + /** + * oce - Enable OCE in STA and/or STA-CFON mode + * - Set BIT(0) to enable OCE in non-AP STA mode + * - Set BIT(1) to enable OCE in STA-CFON mode + */ + unsigned int oce; #endif /* CONFIG_MBO */ /** diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 6558a1b76..692b2005c 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -1430,6 +1430,8 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD) fprintf(f, "disassoc_imminent_rssi_threshold=%d\n", config->disassoc_imminent_rssi_threshold); + if (config->oce != DEFAULT_OCE_SUPPORT) + fprintf(f, "oce=%u\n", config->oce); #endif /* CONFIG_MBO */ if (config->gas_address3) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index a438f6799..863dc992f 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -669,6 +669,24 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, } } else if (os_strcasecmp(cmd, "mbo_cell_capa") == 0) { wpas_mbo_update_cell_capa(wpa_s, atoi(value)); + } else if (os_strcasecmp(cmd, "oce") == 0) { + wpa_s->conf->oce = atoi(value); + if (wpa_s->conf->oce) { + if ((wpa_s->conf->oce & OCE_STA) && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA)) + wpa_s->enable_oce = OCE_STA; + + if ((wpa_s->conf->oce & OCE_STA_CFON) && + (wpa_s->drv_flags & + WPA_DRIVER_FLAGS_OCE_STA_CFON)) { + /* TODO: Need to add STA-CFON support */ + wpa_printf(MSG_ERROR, + "OCE STA-CFON feature is not yet supported"); + return -1; + } + } else { + wpa_s->enable_oce = 0; + } #endif /* CONFIG_MBO */ } else if (os_strcasecmp(cmd, "lci") == 0) { ret = wpas_ctrl_iface_set_lci(wpa_s, value); diff --git a/wpa_supplicant/mbo.c b/wpa_supplicant/mbo.c index 4bf227dca..129d20545 100644 --- a/wpa_supplicant/mbo.c +++ b/wpa_supplicant/mbo.c @@ -154,7 +154,8 @@ int wpas_mbo_ie(struct wpa_supplicant *wpa_s, u8 *buf, size_t len) struct wpabuf *mbo; int res; - if (len < MBO_IE_HEADER + 3 + 7) + if (len < MBO_IE_HEADER + 3 + 7 + + ((wpa_s->enable_oce & OCE_STA) ? 3 : 0)) return 0; /* Leave room for the MBO IE header */ @@ -173,9 +174,16 @@ int wpas_mbo_ie(struct wpa_supplicant *wpa_s, u8 *buf, size_t len) wpabuf_put_u8(mbo, 1); wpabuf_put_u8(mbo, wpa_s->conf->mbo_cell_capa); + /* Add OCE capability indication attribute if OCE is enabled */ + if (wpa_s->enable_oce & OCE_STA) { + wpabuf_put_u8(mbo, OCE_ATTR_ID_CAPA_IND); + wpabuf_put_u8(mbo, 1); + wpabuf_put_u8(mbo, OCE_RELEASE); + } + res = mbo_add_ie(buf, len, wpabuf_head_u8(mbo), wpabuf_len(mbo)); if (!res) - wpa_printf(MSG_ERROR, "Failed to add MBO IE"); + wpa_printf(MSG_ERROR, "Failed to add MBO/OCE IE"); wpabuf_free(mbo); return res; @@ -368,14 +376,23 @@ fail: void wpas_mbo_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ie) { + u8 *len; + wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); - wpabuf_put_u8(ie, 7); + len = wpabuf_put(ie, 1); + wpabuf_put_be24(ie, OUI_WFA); wpabuf_put_u8(ie, MBO_OUI_TYPE); wpabuf_put_u8(ie, MBO_ATTR_ID_CELL_DATA_CAPA); wpabuf_put_u8(ie, 1); wpabuf_put_u8(ie, wpa_s->conf->mbo_cell_capa); + if (wpa_s->enable_oce & OCE_STA) { + wpabuf_put_u8(ie, OCE_ATTR_ID_CAPA_IND); + wpabuf_put_u8(ie, 1); + wpabuf_put_u8(ie, OCE_RELEASE); + } + *len = (u8 *) wpabuf_put(ie, 0) - len - 1; } diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 85b732f93..964adba54 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -471,8 +471,8 @@ void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s) wpabuf_put_data(default_ies, ext_capab, ext_capab_len); #ifdef CONFIG_MBO - /* Send cellular capabilities for potential MBO STAs */ - if (wpabuf_resize(&default_ies, 9) == 0) + /* Send MBO and OCE capabilities */ + if (wpabuf_resize(&default_ies, 12) == 0) wpas_mbo_scan_ie(wpa_s, default_ies); #endif /* CONFIG_MBO */ @@ -553,8 +553,8 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s) #endif /* CONFIG_FST */ #ifdef CONFIG_MBO - /* Send cellular capabilities for potential MBO STAs */ - if (wpabuf_resize(&extra_ie, 9) == 0) + /* Send MBO and OCE capabilities */ + if (wpabuf_resize(&extra_ie, 12) == 0) wpas_mbo_scan_ie(wpa_s, extra_ie); #endif /* CONFIG_MBO */ diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 9263d8a14..be4478747 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -5323,6 +5323,17 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, hs20_init(wpa_s); #endif /* CONFIG_HS20 */ #ifdef CONFIG_MBO + if (wpa_s->conf->oce) { + if ((wpa_s->conf->oce & OCE_STA) && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA)) + wpa_s->enable_oce = OCE_STA; + if ((wpa_s->conf->oce & OCE_STA_CFON) && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) { + /* TODO: Need to add STA-CFON support */ + wpa_printf(MSG_ERROR, + "OCE STA-CFON feature is not yet supported"); + } + } wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan); #endif /* CONFIG_MBO */ diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index c07badbde..f69c74eed 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -702,6 +702,13 @@ fast_reauth=1 # 3 = Not cellular capable (default) #mbo_cell_capa=3 +# Optimized Connectivity Experience (OCE) +# oce: Enable OCE features (bitmap) +# Set BIT(0) to Enable OCE in non-AP STA mode (default; disabled if the driver +# does not indicate support for OCE in STA mode) +# Set BIT(1) to Enable OCE in STA-CFON mode +#oce=1 + # network block # # Each network (usually AP's sharing the same SSID) is configured as a separate diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index a2b331fb7..31c992114 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1101,6 +1101,14 @@ struct wpa_supplicant { } *non_pref_chan; size_t non_pref_chan_num; u8 mbo_wnm_token; + /** + * enable_oce - Enable OCE if it is enabled by user and device also + * supports OCE. + * User can enable OCE with wpa_config's 'oce' parameter as follows - + * - Set BIT(0) to enable OCE in non-AP STA mode. + * - Set BIT(1) to enable OCE in STA-CFON mode. + */ + u8 enable_oce; #endif /* CONFIG_MBO */ /*