easymesh: add backhaul BSS support for WPS M8

Message ID 20181003013414.32234-1-igor.mitsyanko.os@quantenna.com
State Changes Requested
Headers show
Series
  • easymesh: add backhaul BSS support for WPS M8
Related show

Commit Message

Igor Mitsyanko Oct. 3, 2018, 1:34 a.m.
From: Ying Lu <ylu@quantenna.com>

This patch adds a feature similar to the existing “Additional
Credential attribute(s)” (extra_cred), relating to the requirements of
Wi-Fi Alliance Multi-AP Specification v1.0 (WFA EasyMesh). These specs
can be found at https://www.wi-fi.org/file/multi-ap-specification-v10.

They mandate that a “fronthaul” BSS, that is pairing a client that has
bit 7 of the Multi-AP Extension subelement in the Wi-Fi Alliance Vendor
Extension attribute in the WSC M1 message, shall configure such client
with credentials pertaining to the “backhaul” BSS. Therefore we introduce
two new configuration options (wps_cred_processing_easymesh and
easymesh_backhaul_ap_settings) that behave like the existing extra_cred,
except for the additional check on the content of M1.

Configuring these options will be done by a “MultiAP Agent”, an open-source
implementation of such agent is work in progress at
https://github.com/prplfoundation/prplMesh.

Signed-off-by: Davina Lu <ylu@quantenna.com>
Signed-off-by: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>
---
 hostapd/config_file.c    | 12 ++++++++++++
 hostapd/hostapd.conf     | 11 +++++++++++
 src/ap/ap_config.c       |  1 +
 src/ap/ap_config.h       |  3 +++
 src/wps/wps.h            | 36 ++++++++++++++++++++++++++++++++++++
 src/wps/wps_attr_parse.c | 10 ++++++++++
 src/wps/wps_attr_parse.h |  1 +
 src/wps/wps_defs.h       |  9 ++++++++-
 src/wps/wps_dev_attr.c   |  5 +++++
 src/wps/wps_dev_attr.h   |  1 +
 src/wps/wps_registrar.c  | 17 +++++++++++++++++
 11 files changed, 105 insertions(+), 1 deletion(-)

Comments

Marianna Carrera Nov. 16, 2018, 12:51 a.m. | #1
reviewed-by: Marianna Carrera <mcarrera@quantenna.com>


> From: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>
> Sent: Tuesday, October 2, 2018 6:34 PM
> To: hostap@lists.infradead.org
> Cc: Marianna Carrera; Davina (Ying) Lu; arnout@mind.be; wouter@e2big.org; Igor Mitsyanko OS
> Subject: [PATCH] easymesh: add backhaul BSS support for WPS M8
>
>
> From: Ying Lu <ylu@quantenna.com>
>
> This patch adds a feature similar to the existing “Additional
> Credential attribute(s)” (extra_cred), relating to the requirements of
> Wi-Fi Alliance Multi-AP Specification v1.0 (WFA EasyMesh). These specs
> can be found at https://www.wi-fi.org/file/multi-ap-specification-v10.
>
> They mandate that a “fronthaul” BSS, that is pairing a client that has
> bit 7 of the Multi-AP Extension subelement in the Wi-Fi Alliance Vendor
> Extension attribute in the WSC M1 message, shall configure such client
> with credentials pertaining to the “backhaul” BSS. Therefore we introduce
> two new configuration options (wps_cred_processing_easymesh and
> easymesh_backhaul_ap_settings) that behave like the existing extra_cred,
> except for the additional check on the content of M1.
>
> Configuring these options will be done by a “MultiAP Agent”, an open-source
> implementation of such agent is work in progress at
> https://github.com/prplfoundation/prplMesh.
>
> Signed-off-by: Davina Lu <ylu@quantenna.com>
> Signed-off-by: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>
> ---
>  hostapd/config_file.c    | 12 ++++++++++++
>  hostapd/hostapd.conf     | 11 +++++++++++
>  src/ap/ap_config.c       |  1 +
>  src/ap/ap_config.h       |  3 +++
>  src/wps/wps.h            | 36 ++++++++++++++++++++++++++++++++++++
>  src/wps/wps_attr_parse.c | 10 ++++++++++
>  src/wps/wps_attr_parse.h |  1 +
>  src/wps/wps_defs.h       |  9 ++++++++-
>  src/wps/wps_dev_attr.c   |  5 +++++
>  src/wps/wps_dev_attr.h   |  1 +
>  src/wps/wps_registrar.c  | 17 +++++++++++++++++
>  11 files changed, 105 insertions(+), 1 deletion(-)
>
> diff --git a/hostapd/config_file.c b/hostapd/config_file.c
> index b1ab13e..581c634 100644
> --- a/hostapd/config_file.c
> +++ b/hostapd/config_file.c
> @@ -3457,6 +3457,18 @@ static int hostapd_config_fill(struct hostapd_config *conf,
>                                     line, pos);
>                          return 1;
>                  }
> +       } else if (os_strcmp(buf, "easymesh_backhaul_ap_settings") == 0) {
> +               os_free(bss->easymesh_backhaul_ap_settings);
> +               bss->easymesh_backhaul_ap_settings =
> +                       (u8 *) os_readfile(pos, &bss->easymesh_backhaul_ap_settings_len);
> +               if (bss->easymesh_backhaul_ap_settings == NULL) {
> +                       wpa_printf(MSG_ERROR,
> +                                  "Line %d: couldn't read EASYMESH backhaul AP Settings from '%s'",
> +                                  line, pos);
> +                       return 1;
> +               }
> +       } else if (os_strcmp(buf, "wps_cred_processing_easymesh") == 0) {
> +               bss->wps_cred_processing_easymesh = atoi(pos);
>          } else if (os_strcmp(buf, "upnp_iface") == 0) {
>                  os_free(bss->upnp_iface);
>                  bss->upnp_iface = os_strdup(pos);
> diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
> index 70f9713..c7946e6 100644
> --- a/hostapd/hostapd.conf
> +++ b/hostapd/hostapd.conf
> @@ -1845,6 +1845,17 @@ own_ip_addr=127.0.0.1
>  # attribute.
>  #ap_settings=hostapd.ap_settings
>
> +# Easy mesh AP config
> +# when set to 1, hostapd uses the credentials in the file specified by
> +# easymesh_backhaul_ap_settings config, only for those STAs that advertise
> +# "backhaul STA" in M1's EASYMESH Extension subelement.
> +#wps_cred_processing_easymesh=0
> +
> +# Easy mesh AP backhaul BSS config
> +# Used when wps_cred_processing_easymesh is set. Contains "backhaul BSS"
> +# credentials.
> +#easymesh_backhaul_ap_settings=hostapd.easymesh_settings
> +
>  # WPS UPnP interface
>  # If set, support for external Registrars is enabled.
>  #upnp_iface=br0
> diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
> index 820cba9..197f229 100644
> --- a/src/ap/ap_config.c
> +++ b/src/ap/ap_config.c
> @@ -582,6 +582,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
>          os_free(conf->ap_pin);
>          os_free(conf->extra_cred);
>          os_free(conf->ap_settings);
> +       os_free(conf->easymesh_backhaul_ap_settings);
>          os_free(conf->upnp_iface);
>          os_free(conf->friendly_name);
>          os_free(conf->manufacturer_url);
> diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
> index 5b71126..c7b903d 100644
> --- a/src/ap/ap_config.h
> +++ b/src/ap/ap_config.h
> @@ -455,6 +455,9 @@ struct hostapd_bss_config {
>          int force_per_enrollee_psk;
>          u8 *ap_settings;
>          size_t ap_settings_len;
> +       u8 *easymesh_backhaul_ap_settings;
> +       size_t easymesh_backhaul_ap_settings_len;
> +       int wps_cred_processing_easymesh;
>          char *upnp_iface;
>          char *friendly_name;
>          char *manufacturer_url;
> diff --git a/src/wps/wps.h b/src/wps/wps.h
> index 2505d2d..2a685b2 100644
> --- a/src/wps/wps.h
> +++ b/src/wps/wps.h
> @@ -100,6 +100,7 @@ struct wps_device_data {
>          struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
>
>          int p2p;
> +       u8 easymesh_ext;
>  };
>
>  /**
> @@ -395,6 +396,16 @@ struct wps_registrar_config {
>           * PSK is set for a network.
>           */
>          int force_per_enrollee_psk;
> +
> +       /**
> +        * wps_cred_processing_easymesh: build credential with backhaul BSS
> +        *
> +        * This option can be used to disable internal code that builds
> +        * Credential attribute into M8 based on the current network
> +        * configuration and Enrollee capabilities. The extra_cred data will
> +        * then be used as the Credential(s).
> +        */
> +       int wps_cred_processing_easymesh;
>  };
>
>
> @@ -799,6 +810,31 @@ struct wps_context {
>          struct wpabuf *ap_nfc_dh_pubkey;
>          struct wpabuf *ap_nfc_dh_privkey;
>          struct wpabuf *ap_nfc_dev_pw;
> +
> +       /**
> +        * wps_cred_processing_easymesh: build credential with backhaul BSS
> +        *
> +        * This option can be used to disable internal code that builds
> +        * Credential attribute into M8 based on the current network
> +        * configuration and Enrollee capabilities. The extra_cred data will
> +        * then be used as the Credential(s).
> +        */
> +       int wps_cred_processing_easymesh;
> +
> +       /**
> +        * easymesh_backhaul_ap_settings: EASY mesh backhaul BSS config
> +        *
> +        * This optional data (set to NULL to disable) can be used to add
> +        * Credential attribute(s) for other networks into M8. If
> +        * wps_cred_processing_easymesh is set, this will also override the automatically
> +        * generated Credential attribute.
> +        */
> +       const u8 *easymesh_backhaul_ap_settings;
> +
> +       /**
> +        * easymesh_backhaul_ap_settings_len: Length of easymesh_backhaul_ap_settings in octets
> +        */
> +       size_t easymesh_backhaul_ap_settings_len;
>  };
>
>  struct wps_registrar *
> diff --git a/src/wps/wps_attr_parse.c b/src/wps/wps_attr_parse.c
> index 756d57e..4cb7db6 100644
> --- a/src/wps/wps_attr_parse.c
> +++ b/src/wps/wps_attr_parse.c
> @@ -67,6 +67,16 @@ static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr,
>                  }
>                  attr->registrar_configuration_methods = pos;
>                  break;
> +       case WFA_ELEM_EASYMESH_EXTENSION:
> +               if (len != 1) {
> +                       wpa_printf(MSG_DEBUG, "WPS: Invalid EASYMESH Extension length "
> +                                       "%u", len);
> +                       return -1;
> +               }
> +               attr->easymesh_ext = *pos;
> +               wpa_printf(MSG_DEBUG, "WPS: EASYMESH Extension "
> +                               "%x",  attr->easymesh_ext);
> +               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 8188fe9..a47fd62 100644
> --- a/src/wps/wps_attr_parse.h
> +++ b/src/wps/wps_attr_parse.h
> @@ -97,6 +97,7 @@ 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 easymesh_ext;
>  };
>
>  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 301864d..ef76571 100644
> --- a/src/wps/wps_defs.h
> +++ b/src/wps/wps_defs.h
> @@ -152,9 +152,16 @@ enum {
>          WFA_ELEM_NETWORK_KEY_SHAREABLE = 0x02,
>          WFA_ELEM_REQUEST_TO_ENROLL = 0x03,
>          WFA_ELEM_SETTINGS_DELAY_TIME = 0x04,
> -       WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS = 0x05
> +       WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS = 0x05,
> +       WFA_ELEM_EASYMESH_EXTENSION = 0x06
>  };
>
> +/*  Multi-AP extension subelement value */
> +#define EASYMESH_TEAR_DOWN             0x10
> +#define EASYMESH_FRONTHAUL_BSS 0x20
> +#define EASYMESH_BACKHAUL_BSS  0x40
> +#define EASYMESH_BACKHAUL_STA  0x80
> +
>  /* Device Password ID */
>  enum wps_dev_password_id {
>          DEV_PW_DEFAULT = 0x0000,
> diff --git a/src/wps/wps_dev_attr.c b/src/wps/wps_dev_attr.c
> index 0d01211..ccea68d 100644
> --- a/src/wps/wps_dev_attr.c
> +++ b/src/wps/wps_dev_attr.c
> @@ -389,6 +389,11 @@ int wps_process_os_version(struct wps_device_data *dev, const u8 *ver)
>          return 0;
>  }
>
> +void wps_process_vendor_ext_m1(struct wps_device_data *dev, const u8 ext)
> +{
> +       dev->easymesh_ext = ext;
> +       wpa_printf(MSG_DEBUG, "WPS: EASYMESH extension value %02x", dev->easymesh_ext);
> +}
>
>  int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands)
>  {
> diff --git a/src/wps/wps_dev_attr.h b/src/wps/wps_dev_attr.h
> index c9034ad..a4b4173 100644
> --- a/src/wps/wps_dev_attr.h
> +++ b/src/wps/wps_dev_attr.h
> @@ -29,6 +29,7 @@ int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg);
>  int wps_process_device_attrs(struct wps_device_data *dev,
>                               struct wps_parse_attr *attr);
>  int wps_process_os_version(struct wps_device_data *dev, const u8 *ver);
> +void wps_process_vendor_ext_m1(struct wps_device_data *dev, const u8 ext);
>  int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands);
>  void wps_device_data_free(struct wps_device_data *dev);
>  int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg);
> diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
> index 379925e..93e4b8a 100644
> --- a/src/wps/wps_registrar.c
> +++ b/src/wps/wps_registrar.c
> @@ -188,6 +188,7 @@ struct wps_registrar {
>  #ifdef WPS_WORKAROUNDS
>          struct os_reltime pbc_ignore_start;
>  #endif /* WPS_WORKAROUNDS */
> +       int wps_cred_processing_easymesh;
>  };
>
>
> @@ -666,6 +667,7 @@ wps_registrar_init(struct wps_context *wps,
>          reg->static_wep_only = cfg->static_wep_only;
>          reg->dualband = cfg->dualband;
>          reg->force_per_enrollee_psk = cfg->force_per_enrollee_psk;
> +       reg->wps_cred_processing_easymesh = cfg->wps_cred_processing_easymesh;
>
>          if (wps_set_ie(reg)) {
>                  wps_registrar_deinit(reg);
> @@ -1588,6 +1590,15 @@ int wps_build_credential_wrap(struct wpabuf *msg,
>          return 0;
>  }
>
> +static int wps_build_easymesh_backhual_ap_settings(struct wps_data *wps, struct wpabuf *msg)
> +{
> +       wpabuf_put_data(msg, wps->wps->easymesh_backhaul_ap_settings,
> +                       wps->wps->easymesh_backhaul_ap_settings_len);
> +       wpa_printf(MSG_DEBUG, "WPS: EASYMESH mesh backhaul BSS config len %lu=%lu\n",
> +                  wpabuf_len(msg),
> +                  wps->wps->easymesh_backhaul_ap_settings_len);
> +       return 0;
> +}
>
>  int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
>  {
> @@ -1596,6 +1607,11 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
>          if (wps->wps->registrar->skip_cred_build)
>                  goto skip_cred_build;
>
> +       if (wps->wps->registrar->wps_cred_processing_easymesh &&
> +           wps->peer_dev.easymesh_ext == EASYMESH_BACKHAUL_STA &&
> +           wps->wps->easymesh_backhaul_ap_settings)
> +               return wps_build_easymesh_backhual_ap_settings(wps, msg);
> +
>          wpa_printf(MSG_DEBUG, "WPS:  * Credential");
>          if (wps->use_cred) {
>                  os_memcpy(&wps->cred, wps->use_cred, sizeof(wps->cred));
> @@ -2705,6 +2721,7 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps,
>                  wps->use_psk_key = 1;
>          }
>  #endif /* WPS_WORKAROUNDS */
> +       wps_process_vendor_ext_m1(&wps->peer_dev, attr->easymesh_ext);
>
>          wps->state = SEND_M2;
>          return WPS_CONTINUE;
> --
> 2.9.5
Jouni Malinen Nov. 18, 2018, 10:30 p.m. | #2
On Tue, Oct 02, 2018 at 06:34:14PM -0700, Igor Mitsyanko wrote:
> This patch adds a feature similar to the existing “Additional
> Credential attribute(s)” (extra_cred), relating to the requirements of
> Wi-Fi Alliance Multi-AP Specification v1.0 (WFA EasyMesh). These specs
> can be found at https://www.wi-fi.org/file/multi-ap-specification-v10.
> 
> They mandate that a “fronthaul” BSS, that is pairing a client that has
> bit 7 of the Multi-AP Extension subelement in the Wi-Fi Alliance Vendor
> Extension attribute in the WSC M1 message, shall configure such client
> with credentials pertaining to the “backhaul” BSS. Therefore we introduce
> two new configuration options (wps_cred_processing_easymesh and
> easymesh_backhaul_ap_settings) that behave like the existing extra_cred,
> except for the additional check on the content of M1.
> 
> Configuring these options will be done by a “MultiAP Agent”, an open-source
> implementation of such agent is work in progress at
> https://github.com/prplfoundation/prplMesh.

Thanks for this and the later patch for wpa_supplicant. Unfortunately, I
have been inconveniently busy with other projects and travel for a while
and have not been able to review this earlier and coordinate with other
development efforts in this area.

I had couple of other patches waiting for review and sending out to the
list, but those got delayed as well. It would be good to see what kind
of combination of functionality from this set of patches would be best
for moving ahead with the Multi-AP functionality. The relevant patches
are here:

http://patchwork.ozlabs.org/patch/978101/
http://patchwork.ozlabs.org/patch/999135/

http://patchwork.ozlabs.org/patch/999588/
http://patchwork.ozlabs.org/patch/999587/

I'll try to go these in more detail over the coming week, so any
comments would be welcome. Based on a very quick review, there is some
common functionality and some additional functionality in each set, so
some kind of merge of the patches could be needed.

> diff --git a/hostapd/config_file.c b/hostapd/config_file.c

> +	} else if (os_strcmp(buf, "easymesh_backhaul_ap_settings") == 0) {
> +		os_free(bss->easymesh_backhaul_ap_settings);

As a quick comment on naming of the functionality, I'm somewhat hesitant
on using "EasyMesh" taken into account it being the name that WFA seems
to be explicitly trademarking as part of the certification program name.
Instead, I would follow the approach used in other cases of WFA
programs, i.e., using the name of the technical specification
(Multi-AP) in the implementation.
Arnout Vandecappelle Nov. 19, 2018, 10:05 a.m. | #3
On 18/11/2018 23:30, Jouni Malinen wrote:
> On Tue, Oct 02, 2018 at 06:34:14PM -0700, Igor Mitsyanko wrote:
>> This patch adds a feature similar to the existing “Additional
>> Credential attribute(s)” (extra_cred), relating to the requirements of
>> Wi-Fi Alliance Multi-AP Specification v1.0 (WFA EasyMesh). These specs
>> can be found at https://www.wi-fi.org/file/multi-ap-specification-v10.
>>
>> They mandate that a “fronthaul” BSS, that is pairing a client that has
>> bit 7 of the Multi-AP Extension subelement in the Wi-Fi Alliance Vendor
>> Extension attribute in the WSC M1 message, shall configure such client
>> with credentials pertaining to the “backhaul” BSS. Therefore we introduce
>> two new configuration options (wps_cred_processing_easymesh and
>> easymesh_backhaul_ap_settings) that behave like the existing extra_cred,
>> except for the additional check on the content of M1.
>>
>> Configuring these options will be done by a “MultiAP Agent”, an open-source
>> implementation of such agent is work in progress at
>> https://github.com/prplfoundation/prplMesh.
> 
> Thanks for this and the later patch for wpa_supplicant. Unfortunately, I
> have been inconveniently busy with other projects and travel for a while
> and have not been able to review this earlier and coordinate with other
> development efforts in this area.
> 
> I had couple of other patches waiting for review and sending out to the
> list, but those got delayed as well. It would be good to see what kind
> of combination of functionality from this set of patches would be best
> for moving ahead with the Multi-AP functionality. The relevant patches
> are here:
> 
> http://patchwork.ozlabs.org/patch/978101/
> http://patchwork.ozlabs.org/patch/999135/
> 
> http://patchwork.ozlabs.org/patch/999588/
> http://patchwork.ozlabs.org/patch/999587/
> 
> I'll try to go these in more detail over the coming week, so any
> comments would be welcome. Based on a very quick review, there is some
> common functionality and some additional functionality in each set, so
> some kind of merge of the patches could be needed.

 It sure looks like that. In particular, the hostapd.conf options are too much
overlapping I think.

> 
>> diff --git a/hostapd/config_file.c b/hostapd/config_file.c
> 
>> +	} else if (os_strcmp(buf, "easymesh_backhaul_ap_settings") == 0) {
>> +		os_free(bss->easymesh_backhaul_ap_settings);
> 
> As a quick comment on naming of the functionality, I'm somewhat hesitant
> on using "EasyMesh" taken into account it being the name that WFA seems
> to be explicitly trademarking as part of the certification program name.
> Instead, I would follow the approach used in other cases of WFA
> programs, i.e., using the name of the technical specification
> (Multi-AP) in the implementation.

 I agree with that, using multi_ap everywhere would be better.

 Jouni, will you be working on combining the patches in a single series?


 Regards,
 Arnout
Arnout Vandecappelle Nov. 19, 2018, 10:14 a.m. | #4
On 03/10/2018 03:34, Igor Mitsyanko wrote:
> +	if (wps->wps->registrar->wps_cred_processing_easymesh &&
> +	    wps->peer_dev.easymesh_ext == EASYMESH_BACKHAUL_STA &&
> +	    wps->wps->easymesh_backhaul_ap_settings)
> +		return wps_build_easymesh_backhual_ap_settings(wps, msg);

 Since the easymesh_backhaul_ap_settings file *must* exist if
wps_cred_processing_easymesh == 1, I don't think it makes sense to have two
separate config options for them. Just have one config option pointing to the
backhaul settings file.

 Note that the current Multi-AP specification implies that the backhaul BSS is
present on the same device, so we could derive the backhaul AP settings from the
hostapd configuration of that BSS. However, this might be a different hostapd
instance on a different radio, so it's not possible in general to work that way.

 Regards,
 Arnout
Jouni Malinen Nov. 19, 2018, 6:54 p.m. | #5
On Mon, Nov 19, 2018 at 11:14:35AM +0100, Arnout Vandecappelle wrote:
> 
> 
> On 03/10/2018 03:34, Igor Mitsyanko wrote:
> > +	if (wps->wps->registrar->wps_cred_processing_easymesh &&
> > +	    wps->peer_dev.easymesh_ext == EASYMESH_BACKHAUL_STA &&
> > +	    wps->wps->easymesh_backhaul_ap_settings)
> > +		return wps_build_easymesh_backhual_ap_settings(wps, msg);
> 
>  Since the easymesh_backhaul_ap_settings file *must* exist if
> wps_cred_processing_easymesh == 1, I don't think it makes sense to have two
> separate config options for them. Just have one config option pointing to the
> backhaul settings file.
> 
>  Note that the current Multi-AP specification implies that the backhaul BSS is
> present on the same device, so we could derive the backhaul AP settings from the
> hostapd configuration of that BSS. However, this might be a different hostapd
> instance on a different radio, so it's not possible in general to work that way.

I don't see how this would work with a hardcoded external file. The MAC
Address attribute within the Credential attribute is supposed to contain
the Enrollee's MAC address. The external entity generating this
hardcoded file cannot know that beforehand and the same payload cannot
be used with different Enrollees.

It would likely make most sense to provide means for configuring the
parameter values needed to allow hostapd to build the backhaul AP
credential. For example, point to an interface within the same hostapd
process (if that case is used) or alternatively, provide means for
setting the SSID/passphrase/PSK (or whatever the exact details are) for
an ESS that is not controlled by the same hostapd process. I used
similar design for OWE transition mode (see owe_transition_* parameters
in hostapd/hostapd.conf), but I have no issues with this being limited
to only that latter alternative (i.e., new parameters to provide the
needed data to construct the Credential regardless of whether the other
BSS is operated by this hostapd instance) to keep implementation
simpler.
Jouni Malinen Nov. 19, 2018, 11:23 p.m. | #6
On Mon, Nov 19, 2018 at 11:05:49AM +0100, Arnout Vandecappelle wrote:
> On 18/11/2018 23:30, Jouni Malinen wrote:
> > I had couple of other patches waiting for review and sending out to the
> > list, but those got delayed as well. It would be good to see what kind
> > of combination of functionality from this set of patches would be best
> > for moving ahead with the Multi-AP functionality. The relevant patches
> > are here:
> > 
> > http://patchwork.ozlabs.org/patch/978101/
> > http://patchwork.ozlabs.org/patch/999135/
> > 
> > http://patchwork.ozlabs.org/patch/999588/
> > http://patchwork.ozlabs.org/patch/999587/
> > 
> > I'll try to go these in more detail over the coming week, so any
> > comments would be welcome. Based on a very quick review, there is some
> > common functionality and some additional functionality in each set, so
> > some kind of merge of the patches could be needed.
> 
>  It sure looks like that. In particular, the hostapd.conf options are too much
> overlapping I think.

Actually, it looks like the duplicated functionality is pretty limited
in these patches and this is mainly focused in how the hostapd.conf and
wpa_supplicant.conf parameters are handled.

>  Jouni, will you be working on combining the patches in a single series?

Based on my review, quite a few changes beyond merging these together is
going to be needed, so it would probably be better if someone else (or
multiple people with some coordination) would volunteer to propose
updated patches with changes to address the comments. Other than the
configuration details, most of the changes look straightforward and also
the four patches are mostly independent in core functionality in areas
beyond those configuration parameters.

I would like to finally get version 2.7 released, so my main focus in
the near term is to go through the pending contributions and to merge in
clear bug fixes while leaving new functionality (like this Multi-AP) to
be post-2.7 items. If there are any issues in getting these Multi-AP
patch updates coordinated, I may try to find time to work on them myself
after that release, but that should really be considered a backup plan
rather than something that would result in getting these in any time
soon..

I'm including my notes from going through the four patches below. Please
let me know if you have any other comments or different views on the
comments/proposed changes listed below.


http://patchwork.ozlabs.org/patch/978101/
easymesh: add backhaul BSS support for WPS M8

functionality:
- adds hostapd configuration to use an externally generated file as a
  WPS Credential for backhaul BSS; this is added to WPS M8 conditionally
- parsing and processing of of Multi-AP extension from WPS M1

comments:
- rename "easymesh" to "Multi-AP"
- should not need wps_cred_processing_easymesh config parameter, i.e.,
  presence of easymesh_backhaul_ap_settings is sufficient to determine
  whether the feature is enabled
- cannot use hardcoded external file to build the Credential for
  backhaul STA since MAC Address attribute depends on the Enrollee's
  MAC address and changes for each device
  * configure needed SSID/passphrase/etc. parameters instead and allow
    hostapd to build this Credential dynamically when needed

http://patchwork.ozlabs.org/patch/999135/
easymesh: add a config option to enable EasyMesh backhaul STA

functionality:
- add Multi-AP extension into WPS M1
- adds global wpa_supplicant config parameter easymesh_backhaul_sta=0/1

comments:
- rename "easymesh" to "Multi-AP"
- wps_build_vendor_ext_m1_wfa() adds a new WFA vendor extension into M1
  even though wps_build_wfa_ext() has already done that for the other
  WFA vendor extensions; this does not look correct, i.e., there should
  be only a single WFA vendor extension attribute that would include the
  existing extensions (e.g., Version2) and the Multi-AP extension;
  wps_build_wfa_ext() would need to be extended instead of adding a new
  function
- the commit message talks about adding a Multi-AP IE into
  (Re)Association Request frames, but this patch does not do that
  * simply remove that comment from the commit message(?) (i.e., handle
    (Re)Association Request frame in a separate patch)

http://patchwork.ozlabs.org/patch/999588/
hostapd: Add Multi-AP protocol support

functionality:
- adds hostapd configuration parameter multi_ap_enabled
  (disabled, backhaul-BSS, fronthaul-BSS, both backhaul and
  fronthaul-BSS)
- adds Multi-AP IE into (Re)Association Response frames
- checks Multi-AP IE in (Re)Association Request frames
- configures STA for 4-address WDS mode based on Multi-AP capability

comments:
- struct multi_ap_ie is hardcoded to include a single Multi-AP Extension
  subelement
  * this is not ideal for subelement design
  * not acceptable for parsing received Multi-AP IE since there could
    be other subelements
- hostapd_validate_multi_ap_ie() does not check anything about the
  Multi-AP IE payload (i.e., would not handle unexpected subelement
  before the Multi-AP extension and does not check that the extension
  has an acceptable value); WLAN_STA_MULTI_AP flag should be added only
  if the contents is appropriate for backhaul STA

http://patchwork.ozlabs.org/patch/999587/
wpa_supplicant: Add Multi-AP protocol support to supplicant

functionality:
- set_multi_ap() driver wrapper to configure backhaul STA interface into
  4-address mode (including nl80211 interface implementation)
- multi_ap_enabled network profile parameter in wpa_supplicant
- add Multi-AP IE into (Re)Association Request frames
- validate Multi-AP IE in (Re)Association Response frames

comments:
- should consider renaming set_multi_ap()
- would be good to review high level sequence of backhaul STA addition
  and the needed driver configuration steps; including how the dynamic
  multi_ap_enabled config parameter changes are used (and if they are
  really needed)
- Multi-AP IE parsing needs to be aware of multiple possible subelements
- should not break non-Multi-AP case in association event processing
- should use a single helper function to build all different cases of
  Multi-AP IE contents
Arnout Vandecappelle Nov. 20, 2018, 2:54 p.m. | #7
Hi all,

 Ying Lu, Venkateswara, please note the call to action below.


On 20/11/2018 00:23, Jouni Malinen wrote:
[snip]
> Based on my review, quite a few changes beyond merging these together is
> going to be needed,

 I agree. In fact, it's likely that a few iterations will be needed.

> so it would probably be better if someone else (or
> multiple people with some coordination) would volunteer to propose
> updated patches with changes to address the comments.

 OK.

 Ying Lu and Venkateswara, is there any chance that either of you could combine
these patches and integrate the comments?


> Other than the
> configuration details, most of the changes look straightforward and also
> the four patches are mostly independent in core functionality in areas
> beyond those configuration parameters.
> 
> I would like to finally get version 2.7 released, so my main focus in
> the near term is to go through the pending contributions and to merge in
> clear bug fixes while leaving new functionality (like this Multi-AP) to
> be post-2.7 items.

 Indeed, this doesn't look mature enough to be integrated in 2.7.

> If there are any issues in getting these Multi-AP
> patch updates coordinated, I may try to find time to work on them myself
> after that release, but that should really be considered a backup plan
> rather than something that would result in getting these in any time
> soon..

 OK.


> I'm including my notes from going through the four patches below.

 Excellent, thank you for summarizing this!


> Please
> let me know if you have any other comments or different views on the
> comments/proposed changes listed below.
> 
> 
> http://patchwork.ozlabs.org/patch/978101/
> easymesh: add backhaul BSS support for WPS M8
> 
> functionality:
> - adds hostapd configuration to use an externally generated file as a
>   WPS Credential for backhaul BSS; this is added to WPS M8 conditionally
> - parsing and processing of of Multi-AP extension from WPS M1
> 
> comments:
> - rename "easymesh" to "Multi-AP"
> - should not need wps_cred_processing_easymesh config parameter, i.e.,
>   presence of easymesh_backhaul_ap_settings is sufficient to determine
>   whether the feature is enabled
> - cannot use hardcoded external file to build the Credential for
>   backhaul STA since MAC Address attribute depends on the Enrollee's
>   MAC address and changes for each device

 Actually that's not true: the MAC address attribute in M8's credentials is the
BSSID, not the enrollee MAC address. At least, that's how I understand it.

>   * configure needed SSID/passphrase/etc. parameters instead and allow
>     hostapd to build this Credential dynamically when needed
> 
> http://patchwork.ozlabs.org/patch/999135/
> easymesh: add a config option to enable EasyMesh backhaul STA
> 
> functionality:
> - add Multi-AP extension into WPS M1
> - adds global wpa_supplicant config parameter easymesh_backhaul_sta=0/1
> 
> comments:
> - rename "easymesh" to "Multi-AP"
> - wps_build_vendor_ext_m1_wfa() adds a new WFA vendor extension into M1
>   even though wps_build_wfa_ext() has already done that for the other
>   WFA vendor extensions; this does not look correct, i.e., there should
>   be only a single WFA vendor extension attribute that would include the
>   existing extensions (e.g., Version2) and the Multi-AP extension;
>   wps_build_wfa_ext() would need to be extended instead of adding a new
>   function
> - the commit message talks about adding a Multi-AP IE into
>   (Re)Association Request frames, but this patch does not do that
>   * simply remove that comment from the commit message(?) (i.e., handle
>     (Re)Association Request frame in a separate patch)

 That bit is actually done by patch 999587.

> 
> http://patchwork.ozlabs.org/patch/999588/
> hostapd: Add Multi-AP protocol support
> 
> functionality:
> - adds hostapd configuration parameter multi_ap_enabled
>   (disabled, backhaul-BSS, fronthaul-BSS, both backhaul and
>   fronthaul-BSS)
> - adds Multi-AP IE into (Re)Association Response frames
> - checks Multi-AP IE in (Re)Association Request frames
> - configures STA for 4-address WDS mode based on Multi-AP capability
> 
> comments:
> - struct multi_ap_ie is hardcoded to include a single Multi-AP Extension
>   subelement
>   * this is not ideal for subelement design
>   * not acceptable for parsing received Multi-AP IE since there could
>     be other subelements
> - hostapd_validate_multi_ap_ie() does not check anything about the
>   Multi-AP IE payload (i.e., would not handle unexpected subelement
>   before the Multi-AP extension and does not check that the extension
>   has an acceptable value); WLAN_STA_MULTI_AP flag should be added only
>   if the contents is appropriate for backhaul STA
> 
> http://patchwork.ozlabs.org/patch/999587/
> wpa_supplicant: Add Multi-AP protocol support to supplicant
> 
> functionality:
> - set_multi_ap() driver wrapper to configure backhaul STA interface into
>   4-address mode (including nl80211 interface implementation)
> - multi_ap_enabled network profile parameter in wpa_supplicant
> - add Multi-AP IE into (Re)Association Request frames
> - validate Multi-AP IE in (Re)Association Response frames
> 
> comments:
> - should consider renaming set_multi_ap()
> - would be good to review high level sequence of backhaul STA addition
>   and the needed driver configuration steps; including how the dynamic
>   multi_ap_enabled config parameter changes are used (and if they are
>   really needed)
> - Multi-AP IE parsing needs to be aware of multiple possible subelements
> - should not break non-Multi-AP case in association event processing
> - should use a single helper function to build all different cases of
>   Multi-AP IE contents


 What is clearly also missing is documentation of how it should all work. I
think there should be a README-MULTI-AP somewhere that explains it all. Here is
a start. Marianna, Wouter, Daniel, Jouni, please comment on it. Jouni, please
let me know if this clarifies sufficiently how the multi-ap support is supposed
to be used.

 Regards,
 Arnout

--------------------------------------------------------------------------------

The Multi-AP Specification is the technical specification for Wi-Fi CERTIFIED
EasyMesh(TM) [1], the Wi-Fi Alliance® certification program for Multi-AP. It
defines control protocols between Wi-Fi® access points (APs) to join them into a
network with centralized control and operation. It is targeted only at routers
(repeaters, gateways, ...), not at clients. Clients are not involved at all in
the protocols.

Most of the Multi-AP specification falls outside of the scope of
hostapd/wpa_supplicant. hostapd/wpa_supplicant is only involved for the items
summarized below. The rest of the protocol must be implemented by a separate
daemon, e.g. prplMesh [2].

The text below refers to "Multi-AP Specification v1.0" [3].

In a Multi-AP network, the central controller can configure the SSIDs on the
devices that are joined into the network. These are called fronthaul SSIDs. From
the point of view of hostapd, there is nothing special about these fronthaul SSIDs.

In addition to fronthaul SSIDs, the controller can also configure backhaul
links. A backhaul link is a link between two access point devices, giving
internet access to access point devices that don't have a wired link. The
Multi-AP specification doesn't dictate this, but typically the backhaul link
will be bridged into a LAN together with (one of) the fronthaul SSID(s).

A backhaul link must be treated specially by hostapd and wpa_supplicant. One
side of the backhaul link is configured by the Multi-AP protocol as the
"backhaul STA", i.e. the client side of the link. This is handled by
wpa_supplicant, but it must send an additional information element in each
(Re-)Association Request ([3], section 5.2, paragraph 4). In addition, it must
use 4-address mode for all frames sent over this link ([3], section 14). [Insert
here how to configure wpa_supplicant as a backhaul link.]

The AP side of the backhaul link is called a "backhaul SSID". Such an SSID must
be handled specially by hostapd, because it must add an additional information
element in each (Re-)Association Response, but only to stations that have
identified themselves as backhaul stations ([3], section 5.2, paragraph 5-6).
This is important because it is possible to use the same BSS and SSID for
fronthaul and backhaul at the same time. The additional information element must
only be used for frames sent to a backhaul STA, not to a normal STA. Also,
frames sent to a backhaul STA must use 4-address mode, while frames sent to a
normal STA must use 3-address mode.

[Insert here how to configure hostapd with a backhaul SSID, a fronthaul SSID,
and a backhaul+fronthaul SSID if that is actually supported.]

WPS requires more special handling. WPS must only be advertised on fronthaul
SSIDs, not on backhaul SSIDs, so WPS should not be enabled on the backhaul SSID
in hostapd.conf. The WPS configuration purely works on the fronthaul SSID. When
a WPS M1 message has an additional subelement that indicates a request for a
multi-AP backhaul link, hostapd must not respond with the normal fronthaul SSID
credentials; instead, it responds with the (potentially different) backhaul SSID
credentials. [Insert here how to configure this.] In addition to supplying the
backhaul SSID credentials, hostapd will also add an additional information
element to confirm that this is for a multi-AP backhaul link.

When wpa_supplicant initiates WPS, it can add the multi-AP backhaul subelement
in the M1 message. [Insert here how to configure wpa_supplicant to add the IE in
WPS.] If it then receives the M8 response with the multi-AP backhaul subelement,
it must treat the received credentials as a backhaul link, i.e. it must add the
additional information element in (Re-)Association Request frames and it must
4-address mode. [Insert here how wpa_supplicant saves the information.] If it
doesn't receive the multi-AP backhaul subelement in the WPS M8 response, it
treats the link as a normal link, without additional information elements.


[1] https://www.wi-fi.org/discover-wi-fi/wi-fi-easymesh
[2] https://github.com/prplfoundation/prplMesh
[3] https://www.wi-fi.org/file/multi-ap-specification-v10
    (requires registration)
Jouni Malinen Nov. 21, 2018, 10:59 a.m. | #8
On Tue, Nov 20, 2018 at 03:54:05PM +0100, Arnout Vandecappelle wrote:
> On 20/11/2018 00:23, Jouni Malinen wrote:
> > http://patchwork.ozlabs.org/patch/978101/
> > easymesh: add backhaul BSS support for WPS M8

> > - cannot use hardcoded external file to build the Credential for
> >   backhaul STA since MAC Address attribute depends on the Enrollee's
> >   MAC address and changes for each device
> 
>  Actually that's not true: the MAC address attribute in M8's credentials is the
> BSSID, not the enrollee MAC address. At least, that's how I understand it.

The WSC tech spec is not as clear on this detail as it could be for the
Registrar side functionality, but this attribute is supposed to contain
the Enrollee's MAC Address. It is documented as having "Member device's
MAC address" in the table that defined the Credential attributes.
Section 7.2.2 (Validation of Configuration Data) is much clearer on
that, though, with "the Enrollee shall verify that the MAC Address
attribute inside each Credential attribute ... matches with its own MAC
Address. If an address mismatch is found, the ConfigData shall not be
used and the protocol run shall be terminated with an error."

In other words, a compliant Enrollee implementation would reject that
Credential if it contained the BSSID (or well, any BSSID.. there may be
more than one BSS in the ESS). I don't really see how this requirement
could be met cleanly with a hardcoded external file.


>  What is clearly also missing is documentation of how it should all work. I
> think there should be a README-MULTI-AP somewhere that explains it all. Here is
> a start. Marianna, Wouter, Daniel, Jouni, please comment on it. Jouni, please
> let me know if this clarifies sufficiently how the multi-ap support is supposed
> to be used.

Thanks for the description. It would be useful to have such
documentation available somewhere (whether part of
hostapd/wpa_supplicant or the Multi-AP Agent).

> The AP side of the backhaul link is called a "backhaul SSID". Such an SSID must
> be handled specially by hostapd, because it must add an additional information
> element in each (Re-)Association Response, but only to stations that have
> identified themselves as backhaul stations ([3], section 5.2, paragraph 5-6).
> This is important because it is possible to use the same BSS and SSID for
> fronthaul and backhaul at the same time. The additional information element must
> only be used for frames sent to a backhaul STA, not to a normal STA. Also,
> frames sent to a backhaul STA must use 4-address mode, while frames sent to a
> normal STA must use 3-address mode.

That use of the same SSID/ESS does not sounds particularly secure unless
those backhaul links use a different passphrase/PSK or some other
protected mean of identifying the backhaul STAs.. The information
element added into (Re)Association Request frame is not protected, so
anyone with access to this same BSS could claim to be part of the
backhaul if that is the only thing protecting this.

> WPS requires more special handling. WPS must only be advertised on fronthaul
> SSIDs, not on backhaul SSIDs, so WPS should not be enabled on the backhaul SSID
> in hostapd.conf. The WPS configuration purely works on the fronthaul SSID. When
> a WPS M1 message has an additional subelement that indicates a request for a
> multi-AP backhaul link, hostapd must not respond with the normal fronthaul SSID
> credentials; instead, it responds with the (potentially different) backhaul SSID
> credentials. [Insert here how to configure this.] In addition to supplying the
> backhaul SSID credentials, hostapd will also add an additional information
> element to confirm that this is for a multi-AP backhaul link.
> 
> When wpa_supplicant initiates WPS, it can add the multi-AP backhaul subelement
> in the M1 message. [Insert here how to configure wpa_supplicant to add the IE in
> WPS.] If it then receives the M8 response with the multi-AP backhaul subelement,
> it must treat the received credentials as a backhaul link, i.e. it must add the
> additional information element in (Re-)Association Request frames and it must
> 4-address mode. [Insert here how wpa_supplicant saves the information.] If it
> doesn't receive the multi-AP backhaul subelement in the WPS M8 response, it
> treats the link as a normal link, without additional information elements.

This is the part that is relatively clear in the patches I've seen so
far. The part that is not, is the upper layer use of functionality,
i.e., those [Insert something] comments and the exact sequence on how
the operations might be completed (e.g., the question I had about
dynamically added netdev/vif for backhaul STA).
Arnout Vandecappelle Nov. 21, 2018, 1:12 p.m. | #9
On 21/11/2018 11:59, Jouni Malinen wrote:
> On Tue, Nov 20, 2018 at 03:54:05PM +0100, Arnout Vandecappelle wrote:
>> On 20/11/2018 00:23, Jouni Malinen wrote:
>>> http://patchwork.ozlabs.org/patch/978101/
>>> easymesh: add backhaul BSS support for WPS M8
> 
>>> - cannot use hardcoded external file to build the Credential for
>>>   backhaul STA since MAC Address attribute depends on the Enrollee's
>>>   MAC address and changes for each device
>>
>>  Actually that's not true: the MAC address attribute in M8's credentials is the
>> BSSID, not the enrollee MAC address. At least, that's how I understand it.
> 
> The WSC tech spec is not as clear on this detail as it could be for the
> Registrar side functionality, but this attribute is supposed to contain
> the Enrollee's MAC Address. It is documented as having "Member device's
> MAC address" in the table that defined the Credential attributes.
> Section 7.2.2 (Validation of Configuration Data) is much clearer on
> that, though, with "the Enrollee shall verify that the MAC Address
> attribute inside each Credential attribute ... matches with its own MAC
> Address. If an address mismatch is found, the ConfigData shall not be
> used and the protocol run shall be terminated with an error."

 You're right, sorry, I was confusing the M8 used in WPS with the M2 used in
IEEE 1905.1 AP Autoconfiguration. Totally different thing.


> In other words, a compliant Enrollee implementation would reject that
> Credential if it contained the BSSID (or well, any BSSID.. there may be
> more than one BSS in the ESS). I don't really see how this requirement
> could be met cleanly with a hardcoded external file.
> 
> 
>>  What is clearly also missing is documentation of how it should all work. I
>> think there should be a README-MULTI-AP somewhere that explains it all. Here is
>> a start. Marianna, Wouter, Daniel, Jouni, please comment on it. Jouni, please
>> let me know if this clarifies sufficiently how the multi-ap support is supposed
>> to be used.
> 
> Thanks for the description. It would be useful to have such
> documentation available somewhere (whether part of
> hostapd/wpa_supplicant or the Multi-AP Agent).

 I will rework the four patches and include this text in README-MULTI-AP. You
can delegate them to me (user arnout) on patchwork if you like.

> 
>> The AP side of the backhaul link is called a "backhaul SSID". Such an SSID must
>> be handled specially by hostapd, because it must add an additional information
>> element in each (Re-)Association Response, but only to stations that have
>> identified themselves as backhaul stations ([3], section 5.2, paragraph 5-6).
>> This is important because it is possible to use the same BSS and SSID for
>> fronthaul and backhaul at the same time. The additional information element must
>> only be used for frames sent to a backhaul STA, not to a normal STA. Also,
>> frames sent to a backhaul STA must use 4-address mode, while frames sent to a
>> normal STA must use 3-address mode.
> 
> That use of the same SSID/ESS does not sounds particularly secure unless
> those backhaul links use a different passphrase/PSK or some other
> protected mean of identifying the backhaul STAs.. The information
> element added into (Re)Association Request frame is not protected, so
> anyone with access to this same BSS could claim to be part of the
> backhaul if that is the only thing protecting this.

 Don't get me started on the security aspects of Multi-AP R1...

 Basically, unless all APs in the network take drastic measures (e.g. isolation
with ebtables), any device in the network can pretend to be an Multi-AP agent
(or even Multi-AP controller...) and get the backhaul credentials.


 Regards,
 Arnout

> 
>> WPS requires more special handling. WPS must only be advertised on fronthaul
>> SSIDs, not on backhaul SSIDs, so WPS should not be enabled on the backhaul SSID
>> in hostapd.conf. The WPS configuration purely works on the fronthaul SSID. When
>> a WPS M1 message has an additional subelement that indicates a request for a
>> multi-AP backhaul link, hostapd must not respond with the normal fronthaul SSID
>> credentials; instead, it responds with the (potentially different) backhaul SSID
>> credentials. [Insert here how to configure this.] In addition to supplying the
>> backhaul SSID credentials, hostapd will also add an additional information
>> element to confirm that this is for a multi-AP backhaul link.
>>
>> When wpa_supplicant initiates WPS, it can add the multi-AP backhaul subelement
>> in the M1 message. [Insert here how to configure wpa_supplicant to add the IE in
>> WPS.] If it then receives the M8 response with the multi-AP backhaul subelement,
>> it must treat the received credentials as a backhaul link, i.e. it must add the
>> additional information element in (Re-)Association Request frames and it must
>> 4-address mode. [Insert here how wpa_supplicant saves the information.] If it
>> doesn't receive the multi-AP backhaul subelement in the WPS M8 response, it
>> treats the link as a normal link, without additional information elements.
> 
> This is the part that is relatively clear in the patches I've seen so
> far. The part that is not, is the upper layer use of functionality,
> i.e., those [Insert something] comments and the exact sequence on how
> the operations might be completed (e.g., the question I had about
> dynamically added netdev/vif for backhaul STA).
>

Patch

diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index b1ab13e..581c634 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -3457,6 +3457,18 @@  static int hostapd_config_fill(struct hostapd_config *conf,
 				   line, pos);
 			return 1;
 		}
+	} else if (os_strcmp(buf, "easymesh_backhaul_ap_settings") == 0) {
+		os_free(bss->easymesh_backhaul_ap_settings);
+		bss->easymesh_backhaul_ap_settings =
+			(u8 *) os_readfile(pos, &bss->easymesh_backhaul_ap_settings_len);
+		if (bss->easymesh_backhaul_ap_settings == NULL) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: couldn't read EASYMESH backhaul AP Settings from '%s'",
+				   line, pos);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "wps_cred_processing_easymesh") == 0) {
+		bss->wps_cred_processing_easymesh = atoi(pos);
 	} else if (os_strcmp(buf, "upnp_iface") == 0) {
 		os_free(bss->upnp_iface);
 		bss->upnp_iface = os_strdup(pos);
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 70f9713..c7946e6 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -1845,6 +1845,17 @@  own_ip_addr=127.0.0.1
 # attribute.
 #ap_settings=hostapd.ap_settings
 
+# Easy mesh AP config
+# when set to 1, hostapd uses the credentials in the file specified by
+# easymesh_backhaul_ap_settings config, only for those STAs that advertise
+# "backhaul STA" in M1's EASYMESH Extension subelement.
+#wps_cred_processing_easymesh=0
+
+# Easy mesh AP backhaul BSS config
+# Used when wps_cred_processing_easymesh is set. Contains "backhaul BSS"
+# credentials.
+#easymesh_backhaul_ap_settings=hostapd.easymesh_settings
+
 # WPS UPnP interface
 # If set, support for external Registrars is enabled.
 #upnp_iface=br0
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 820cba9..197f229 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -582,6 +582,7 @@  void hostapd_config_free_bss(struct hostapd_bss_config *conf)
 	os_free(conf->ap_pin);
 	os_free(conf->extra_cred);
 	os_free(conf->ap_settings);
+	os_free(conf->easymesh_backhaul_ap_settings);
 	os_free(conf->upnp_iface);
 	os_free(conf->friendly_name);
 	os_free(conf->manufacturer_url);
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 5b71126..c7b903d 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -455,6 +455,9 @@  struct hostapd_bss_config {
 	int force_per_enrollee_psk;
 	u8 *ap_settings;
 	size_t ap_settings_len;
+	u8 *easymesh_backhaul_ap_settings;
+	size_t easymesh_backhaul_ap_settings_len;
+	int wps_cred_processing_easymesh;
 	char *upnp_iface;
 	char *friendly_name;
 	char *manufacturer_url;
diff --git a/src/wps/wps.h b/src/wps/wps.h
index 2505d2d..2a685b2 100644
--- a/src/wps/wps.h
+++ b/src/wps/wps.h
@@ -100,6 +100,7 @@  struct wps_device_data {
 	struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
 
 	int p2p;
+	u8 easymesh_ext;
 };
 
 /**
@@ -395,6 +396,16 @@  struct wps_registrar_config {
 	 * PSK is set for a network.
 	 */
 	int force_per_enrollee_psk;
+
+	/**
+	 * wps_cred_processing_easymesh: build credential with backhaul BSS
+	 *
+	 * This option can be used to disable internal code that builds
+	 * Credential attribute into M8 based on the current network
+	 * configuration and Enrollee capabilities. The extra_cred data will
+	 * then be used as the Credential(s).
+	 */
+	int wps_cred_processing_easymesh;
 };
 
 
@@ -799,6 +810,31 @@  struct wps_context {
 	struct wpabuf *ap_nfc_dh_pubkey;
 	struct wpabuf *ap_nfc_dh_privkey;
 	struct wpabuf *ap_nfc_dev_pw;
+
+	/**
+	 * wps_cred_processing_easymesh: build credential with backhaul BSS
+	 *
+	 * This option can be used to disable internal code that builds
+	 * Credential attribute into M8 based on the current network
+	 * configuration and Enrollee capabilities. The extra_cred data will
+	 * then be used as the Credential(s).
+	 */
+	int wps_cred_processing_easymesh;
+
+	/**
+	 * easymesh_backhaul_ap_settings: EASY mesh backhaul BSS config
+	 *
+	 * This optional data (set to NULL to disable) can be used to add
+	 * Credential attribute(s) for other networks into M8. If
+	 * wps_cred_processing_easymesh is set, this will also override the automatically
+	 * generated Credential attribute.
+	 */
+	const u8 *easymesh_backhaul_ap_settings;
+
+	/**
+	 * easymesh_backhaul_ap_settings_len: Length of easymesh_backhaul_ap_settings in octets
+	 */
+	size_t easymesh_backhaul_ap_settings_len;
 };
 
 struct wps_registrar *
diff --git a/src/wps/wps_attr_parse.c b/src/wps/wps_attr_parse.c
index 756d57e..4cb7db6 100644
--- a/src/wps/wps_attr_parse.c
+++ b/src/wps/wps_attr_parse.c
@@ -67,6 +67,16 @@  static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr,
 		}
 		attr->registrar_configuration_methods = pos;
 		break;
+	case WFA_ELEM_EASYMESH_EXTENSION:
+		if (len != 1) {
+			wpa_printf(MSG_DEBUG, "WPS: Invalid EASYMESH Extension length "
+					"%u", len);
+			return -1;
+		}
+		attr->easymesh_ext = *pos;
+		wpa_printf(MSG_DEBUG, "WPS: EASYMESH Extension "
+				"%x",  attr->easymesh_ext);
+		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 8188fe9..a47fd62 100644
--- a/src/wps/wps_attr_parse.h
+++ b/src/wps/wps_attr_parse.h
@@ -97,6 +97,7 @@  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 easymesh_ext;
 };
 
 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 301864d..ef76571 100644
--- a/src/wps/wps_defs.h
+++ b/src/wps/wps_defs.h
@@ -152,9 +152,16 @@  enum {
 	WFA_ELEM_NETWORK_KEY_SHAREABLE = 0x02,
 	WFA_ELEM_REQUEST_TO_ENROLL = 0x03,
 	WFA_ELEM_SETTINGS_DELAY_TIME = 0x04,
-	WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS = 0x05
+	WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS = 0x05,
+	WFA_ELEM_EASYMESH_EXTENSION = 0x06
 };
 
+/*  Multi-AP extension subelement value */
+#define EASYMESH_TEAR_DOWN		0x10
+#define EASYMESH_FRONTHAUL_BSS	0x20
+#define EASYMESH_BACKHAUL_BSS	0x40
+#define EASYMESH_BACKHAUL_STA	0x80
+
 /* Device Password ID */
 enum wps_dev_password_id {
 	DEV_PW_DEFAULT = 0x0000,
diff --git a/src/wps/wps_dev_attr.c b/src/wps/wps_dev_attr.c
index 0d01211..ccea68d 100644
--- a/src/wps/wps_dev_attr.c
+++ b/src/wps/wps_dev_attr.c
@@ -389,6 +389,11 @@  int wps_process_os_version(struct wps_device_data *dev, const u8 *ver)
 	return 0;
 }
 
+void wps_process_vendor_ext_m1(struct wps_device_data *dev, const u8 ext)
+{
+	dev->easymesh_ext = ext;
+	wpa_printf(MSG_DEBUG, "WPS: EASYMESH extension value %02x", dev->easymesh_ext);
+}
 
 int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands)
 {
diff --git a/src/wps/wps_dev_attr.h b/src/wps/wps_dev_attr.h
index c9034ad..a4b4173 100644
--- a/src/wps/wps_dev_attr.h
+++ b/src/wps/wps_dev_attr.h
@@ -29,6 +29,7 @@  int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg);
 int wps_process_device_attrs(struct wps_device_data *dev,
 			     struct wps_parse_attr *attr);
 int wps_process_os_version(struct wps_device_data *dev, const u8 *ver);
+void wps_process_vendor_ext_m1(struct wps_device_data *dev, const u8 ext);
 int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands);
 void wps_device_data_free(struct wps_device_data *dev);
 int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg);
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index 379925e..93e4b8a 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -188,6 +188,7 @@  struct wps_registrar {
 #ifdef WPS_WORKAROUNDS
 	struct os_reltime pbc_ignore_start;
 #endif /* WPS_WORKAROUNDS */
+	int wps_cred_processing_easymesh;
 };
 
 
@@ -666,6 +667,7 @@  wps_registrar_init(struct wps_context *wps,
 	reg->static_wep_only = cfg->static_wep_only;
 	reg->dualband = cfg->dualband;
 	reg->force_per_enrollee_psk = cfg->force_per_enrollee_psk;
+	reg->wps_cred_processing_easymesh = cfg->wps_cred_processing_easymesh;
 
 	if (wps_set_ie(reg)) {
 		wps_registrar_deinit(reg);
@@ -1588,6 +1590,15 @@  int wps_build_credential_wrap(struct wpabuf *msg,
 	return 0;
 }
 
+static int wps_build_easymesh_backhual_ap_settings(struct wps_data *wps, struct wpabuf *msg)
+{
+	wpabuf_put_data(msg, wps->wps->easymesh_backhaul_ap_settings,
+			wps->wps->easymesh_backhaul_ap_settings_len);
+	wpa_printf(MSG_DEBUG, "WPS: EASYMESH mesh backhaul BSS config len %lu=%lu\n",
+		   wpabuf_len(msg),
+		   wps->wps->easymesh_backhaul_ap_settings_len);
+	return 0;
+}
 
 int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
 {
@@ -1596,6 +1607,11 @@  int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
 	if (wps->wps->registrar->skip_cred_build)
 		goto skip_cred_build;
 
+	if (wps->wps->registrar->wps_cred_processing_easymesh &&
+	    wps->peer_dev.easymesh_ext == EASYMESH_BACKHAUL_STA &&
+	    wps->wps->easymesh_backhaul_ap_settings)
+		return wps_build_easymesh_backhual_ap_settings(wps, msg);
+
 	wpa_printf(MSG_DEBUG, "WPS:  * Credential");
 	if (wps->use_cred) {
 		os_memcpy(&wps->cred, wps->use_cred, sizeof(wps->cred));
@@ -2705,6 +2721,7 @@  static enum wps_process_res wps_process_m1(struct wps_data *wps,
 		wps->use_psk_key = 1;
 	}
 #endif /* WPS_WORKAROUNDS */
+	wps_process_vendor_ext_m1(&wps->peer_dev, attr->easymesh_ext);
 
 	wps->state = SEND_M2;
 	return WPS_CONTINUE;