diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 7b03edf36..0554115d1 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -4551,6 +4551,26 @@ static int hostapd_config_fill(struct hostapd_config *conf,
 		}
 
 		bss->multi_ap = val;
+	} else if (os_strcmp(buf, "multi_ap_profile") == 0) {
+		int val = atoi(pos);
+
+		if (val < 1 || val > 2) {
+			wpa_printf(MSG_ERROR, "Line %d: Invalid multi_ap_profile '%s'",
+				   line, buf);
+			return -1;
+		}
+
+		bss->multi_ap_profile = val;
+	} else if (os_strcmp(buf, "multi_ap_primary_vlan_id") == 0) {
+		int val = atoi(pos);
+
+		if (val < 0 || val > MAX_VLAN_ID) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: Invalid multi_ap_primary_vlan_id %d (expected 0..%d)",
+				   line, val, MAX_VLAN_ID);
+			return 1;
+		}
+		bss->multi_ap_primary_vlan_id = val;
 	} else if (os_strcmp(buf, "rssi_reject_assoc_rssi") == 0) {
 		conf->rssi_reject_assoc_rssi = atoi(pos);
 	} else if (os_strcmp(buf, "rssi_reject_assoc_timeout") == 0) {
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 3ba368987..ed800a9e3 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -774,6 +774,8 @@ struct hostapd_bss_config {
 #define BACKHAUL_BSS 1
 #define FRONTHAUL_BSS 2
 	int multi_ap; /* bitmap of BACKHAUL_BSS, FRONTHAUL_BSS */
+	int multi_ap_profile;
+	int multi_ap_primary_vlan_id;
 
 #ifdef CONFIG_AIRTIME_POLICY
 	unsigned int airtime_weight;
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index 9f22e39a2..7a634352a 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -1290,6 +1290,10 @@ int hostapd_init_wps(struct hostapd_data *hapd,
 			cfg.multi_ap_backhaul_network_key_len = 2 * PMK_LEN;
 		}
 	}
+	if (conf->multi_ap) {
+		cfg.multi_ap_profile = conf->multi_ap_profile;
+		cfg.multi_ap_primary_vlan_id = conf->multi_ap_primary_vlan_id;
+	}
 
 	wps->ap_settings = conf->ap_settings;
 	wps->ap_settings_len = conf->ap_settings_len;
@@ -1418,7 +1422,9 @@ static int hostapd_wps_update_multi_ap(struct hostapd_data *hapd,
 		reg, conf->multi_ap_backhaul_ssid.ssid,
 		conf->multi_ap_backhaul_ssid.ssid_len,
 		multi_ap_backhaul_network_key,
-		multi_ap_backhaul_network_key_len);
+		multi_ap_backhaul_network_key_len,
+		conf->multi_ap_profile,
+		conf->multi_ap_primary_vlan_id);
 	os_free(multi_ap_backhaul_network_key);
 
 	return ret;
diff --git a/src/wps/wps.h b/src/wps/wps.h
index fed3e2848..5a99d3abd 100644
--- a/src/wps/wps.h
+++ b/src/wps/wps.h
@@ -437,6 +437,18 @@ struct wps_registrar_config {
 	 * multi_ap_backhaul_network_key in octets
 	 */
 	size_t multi_ap_backhaul_network_key_len;
+
+	/**
+	 * multi_ap_prorifle - This is parameter for
+	 * Multi-AP Profile subelement
+	 */
+	int multi_ap_profile;
+
+	/**
+	 * multi_ap_primary_vlan_id - This is parameter for
+	 * Default 8021Q Settings Subelement
+	 */
+	int multi_ap_primary_vlan_id;
 };
 
 
@@ -881,7 +893,9 @@ int wps_registrar_update_multi_ap(struct wps_registrar *reg,
 				  const u8 *multi_ap_backhaul_ssid,
 				  size_t multi_ap_backhaul_ssid_len,
 				  const u8 *multi_ap_backhaul_network_key,
-				  size_t multi_ap_backhaul_network_key_len);
+				  size_t multi_ap_backhaul_network_key_len,
+				  u8 multi_ap_profile,
+				  u16 multi_ap_primary_vlan_id);
 
 int wps_build_credential_wrap(struct wpabuf *msg,
 			      const struct wps_credential *cred);
diff --git a/src/wps/wps_attr_build.c b/src/wps/wps_attr_build.c
index f37225676..e231cb88e 100644
--- a/src/wps/wps_attr_build.c
+++ b/src/wps/wps_attr_build.c
@@ -248,6 +248,48 @@ int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll,
 				   MAC2STR(&auth_macs[i * ETH_ALEN]));
 	}
 
+	WPA_PUT_BE16(len, (u8 *) wpabuf_put(msg, 0) - len - 2);
+
+#ifdef CONFIG_WPS_TESTING
+	if (WPS_VERSION > 0x20) {
+		if (wpabuf_tailroom(msg) < 5)
+			return -1;
+		wpa_printf(MSG_DEBUG, "WPS:  * Extensibility Testing - extra "
+			   "attribute");
+		wpabuf_put_be16(msg, ATTR_EXTENSIBILITY_TEST);
+		wpabuf_put_be16(msg, 1);
+		wpabuf_put_u8(msg, 42);
+	}
+#endif /* CONFIG_WPS_TESTING */
+	return 0;
+}
+
+
+int wps_build_wfa_ext_multi_ap(struct wpabuf *msg, u8 multi_ap_subelem,
+			       u8 profile, u16 vlan_id)
+{
+	u8 *len;
+
+#ifdef CONFIG_WPS_TESTING
+	if (WPS_VERSION == 0x10)
+		return 0;
+#endif /* CONFIG_WPS_TESTING */
+
+	if (wpabuf_tailroom(msg) <
+	    7 + 3 +
+	    (multi_ap_subelem ? 3 : 0) +
+	    (profile ? 7 : 0))
+		return -1;
+
+	wpabuf_put_be16(msg, ATTR_VENDOR_EXT);
+	len = wpabuf_put(msg, 2); /* to be filled */
+	wpabuf_put_be24(msg, WPS_VENDOR_ID_WFA);
+
+	wpa_printf(MSG_INFO, "WPS:  * Version2 (0x%x)", WPS_VERSION);
+	wpabuf_put_u8(msg, WFA_ELEM_VERSION2);
+	wpabuf_put_u8(msg, 1);
+	wpabuf_put_u8(msg, WPS_VERSION);
+
 	if (multi_ap_subelem) {
 		wpa_printf(MSG_DEBUG, "WPS:  * Multi-AP (0x%x)",
 			   multi_ap_subelem);
@@ -256,6 +298,21 @@ int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll,
 		wpabuf_put_u8(msg, multi_ap_subelem);
 	}
 
+	if (profile) {
+		wpa_printf(MSG_DEBUG, "WPS:  * Multi-AP profile (%d)", profile);
+		wpabuf_put_u8(msg, WFA_ELEM_MULTI_AP_PROFILE);
+		wpabuf_put_u8(msg, 1); /* length */
+		wpabuf_put_u8(msg, profile);
+
+		if (vlan_id) {
+			wpa_printf(MSG_DEBUG, "WPS:  * Multi-AP vlan_id (%d)",
+				   vlan_id);
+			wpabuf_put_u8(msg, WFA_ELEM_MULTI_AP_8021Q);
+			wpabuf_put_u8(msg, 2); /* length */
+			wpabuf_put_le16(msg, vlan_id);
+		}
+	}
+
 	WPA_PUT_BE16(len, (u8 *) wpabuf_put(msg, 0) - len - 2);
 
 #ifdef CONFIG_WPS_TESTING
diff --git a/src/wps/wps_attr_parse.c b/src/wps/wps_attr_parse.c
index fd5163515..0cc41f026 100644
--- a/src/wps/wps_attr_parse.c
+++ b/src/wps/wps_attr_parse.c
@@ -78,6 +78,28 @@ static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr,
 		wpa_printf(MSG_DEBUG, "WPS: Multi-AP Extension 0x%02x",
 			   attr->multi_ap_ext);
 		break;
+	case WFA_ELEM_MULTI_AP_PROFILE:
+		if (len != 1) {
+			wpa_printf(MSG_DEBUG,
+				   "WPS: Invalid Multi-AP Profile length %u",
+				   len);
+			return -1;
+		}
+		attr->multi_ap_profile = *pos;
+		wpa_printf(MSG_DEBUG, "WPS: Multi-AP Profile %u",
+			   attr->multi_ap_profile);
+		break;
+	case WFA_ELEM_MULTI_AP_8021Q:
+		if (len != 2) {
+			wpa_printf(MSG_DEBUG,
+				   "WPS: Invalid Multi-AP Default 8021Q Settings length %u",
+				   len);
+			return -1;
+		}
+		attr->multi_ap_primary_vlan_id = WPA_GET_LE16(pos);
+		wpa_printf(MSG_DEBUG, "WPS: Multi-AP vlan_id %u",
+			   attr->multi_ap_primary_vlan_id);
+		break;
 	default:
 		wpa_printf(MSG_MSGDUMP, "WPS: Skipped unknown WFA Vendor "
 			   "Extension subelement %u", id);
diff --git a/src/wps/wps_attr_parse.h b/src/wps/wps_attr_parse.h
index 4de27b26d..4fc91aa59 100644
--- a/src/wps/wps_attr_parse.h
+++ b/src/wps/wps_attr_parse.h
@@ -97,7 +97,10 @@ struct wps_parse_attr {
 	const u8 *cred[MAX_CRED_COUNT];
 	const u8 *req_dev_type[MAX_REQ_DEV_TYPE_COUNT];
 	const u8 *vendor_ext[MAX_WPS_PARSE_VENDOR_EXT];
+
 	u8 multi_ap_ext;
+	u8 multi_ap_profile;
+	u16 multi_ap_primary_vlan_id;
 };
 
 int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr);
diff --git a/src/wps/wps_defs.h b/src/wps/wps_defs.h
index ddaeda56d..d19f66e23 100644
--- a/src/wps/wps_defs.h
+++ b/src/wps/wps_defs.h
@@ -153,7 +153,9 @@ enum {
 	WFA_ELEM_REQUEST_TO_ENROLL = 0x03,
 	WFA_ELEM_SETTINGS_DELAY_TIME = 0x04,
 	WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS = 0x05,
-	WFA_ELEM_MULTI_AP = 0x06
+	WFA_ELEM_MULTI_AP = 0x06,
+	WFA_ELEM_MULTI_AP_PROFILE = 0x07,
+	WFA_ELEM_MULTI_AP_8021Q = 0x08
 };
 
 /* Device Password ID */
diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c
index 819cd43f6..d0106e6d9 100644
--- a/src/wps/wps_enrollee.c
+++ b/src/wps/wps_enrollee.c
@@ -156,7 +156,9 @@ static struct wpabuf * wps_build_m1(struct wps_data *wps)
 	    wps_build_dev_password_id(msg, wps->dev_pw_id) ||
 	    wps_build_config_error(msg, WPS_CFG_NO_ERROR) ||
 	    wps_build_os_version(&wps->wps->dev, msg) ||
-	    wps_build_wfa_ext(msg, 0, NULL, 0, multi_ap_backhaul_sta) ||
+	    (multi_ap_backhaul_sta ?
+	     wps_build_wfa_ext_multi_ap(msg, multi_ap_backhaul_sta, 0, 0) :
+	     wps_build_wfa_ext(msg, 0, NULL, 0, 0)) ||
 	    wps_build_vendor_ext_m1(&wps->wps->dev, msg)) {
 		wpabuf_free(msg);
 		return NULL;
diff --git a/src/wps/wps_i.h b/src/wps/wps_i.h
index 2cf22d4b7..527cfe06a 100644
--- a/src/wps/wps_i.h
+++ b/src/wps/wps_i.h
@@ -167,6 +167,8 @@ int wps_build_version(struct wpabuf *msg);
 int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll,
 		      const u8 *auth_macs, size_t auth_macs_count,
 		      u8 multi_ap_subelem);
+int wps_build_wfa_ext_multi_ap(struct wpabuf *msg, u8 multi_ap_subelem,
+			       u8 profile, u16 vlan_id);
 int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type);
 int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg);
 int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg);
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index 9587293d0..43285cba0 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -220,6 +220,18 @@ struct wps_registrar {
 	 * multi_ap_backhaul_network_key in octets
 	 */
 	size_t multi_ap_backhaul_network_key_len;
+
+	/**
+	 * multi_ap_primary - This is parameter for
+	 * Multi-AP Profile subelement
+	 */
+	int multi_ap_profile;
+
+	/**
+	 * multi_ap_primary_vlan_id - This is parameter for
+	 * Default 8021Q Settings Subelement
+	 */
+	int multi_ap_primary_vlan_id;
 };
 
 
@@ -714,6 +726,8 @@ wps_registrar_init(struct wps_context *wps,
 			reg->multi_ap_backhaul_network_key_len =
 				cfg->multi_ap_backhaul_network_key_len;
 	}
+	reg->multi_ap_profile = cfg->multi_ap_profile;
+	reg->multi_ap_primary_vlan_id = cfg->multi_ap_primary_vlan_id;
 
 	if (wps_set_ie(reg)) {
 		wps_registrar_deinit(reg);
@@ -2064,7 +2078,11 @@ static struct wpabuf * wps_build_m6(struct wps_data *wps)
 
 static struct wpabuf * wps_build_m8(struct wps_data *wps)
 {
+	struct wps_registrar *reg = wps->wps->registrar;
 	struct wpabuf *msg, *plain;
+	u8 multi_ap_ext = 0;
+	u8 profile = 0;
+	u16 vlan_id = 0;
 
 	wpa_printf(MSG_DEBUG, "WPS: Building Message M8");
 
@@ -2078,6 +2096,14 @@ static struct wpabuf * wps_build_m8(struct wps_data *wps)
 		return NULL;
 	}
 
+
+	if (wps->peer_dev.multi_ap_ext == MULTI_AP_BACKHAUL_STA) {
+		multi_ap_ext = MULTI_AP_BACKHAUL_BSS |
+			       MULTI_AP_FRONTHAUL_BSS;
+		profile = reg->multi_ap_profile;
+		vlan_id = reg->multi_ap_primary_vlan_id;
+	}
+
 	if (wps_build_version(msg) ||
 	    wps_build_msg_type(msg, WPS_M8) ||
 	    wps_build_enrollee_nonce(wps, msg) ||
@@ -2085,7 +2111,9 @@ static struct wpabuf * wps_build_m8(struct wps_data *wps)
 	    (!wps->wps->ap && !wps->er && wps_build_ap_settings(wps, plain)) ||
 	    wps_build_key_wrap_auth(wps, plain) ||
 	    wps_build_encr_settings(wps, msg, plain) ||
-	    wps_build_wfa_ext(msg, 0, NULL, 0, 0) ||
+	    (multi_ap_ext ?
+	     wps_build_wfa_ext_multi_ap(msg, multi_ap_ext, profile, vlan_id) :
+	     wps_build_wfa_ext(msg, 0, NULL, 0, 0)) ||
 	    wps_build_authenticator(wps, msg)) {
 		wpabuf_clear_free(plain);
 		wpabuf_clear_free(msg);
@@ -3663,7 +3691,9 @@ int wps_registrar_update_multi_ap(struct wps_registrar *reg,
 				  const u8 *multi_ap_backhaul_ssid,
 				  size_t multi_ap_backhaul_ssid_len,
 				  const u8 *multi_ap_backhaul_network_key,
-				  size_t multi_ap_backhaul_network_key_len)
+				  size_t multi_ap_backhaul_network_key_len,
+				  u8 multi_ap_profile,
+				  u16 multi_ap_primary_vlan_id)
 {
 	if (multi_ap_backhaul_ssid) {
 		os_memcpy(reg->multi_ap_backhaul_ssid,
@@ -3683,6 +3713,8 @@ int wps_registrar_update_multi_ap(struct wps_registrar *reg,
 		reg->multi_ap_backhaul_network_key_len =
 			multi_ap_backhaul_network_key_len;
 	}
+	reg->multi_ap_profile = multi_ap_profile;
+	reg->multi_ap_primary_vlan_id = multi_ap_primary_vlan_id;
 
 	return 0;
 }
