diff options
author | Sara Sharon <sara.sharon@intel.com> | 2019-01-16 11:22:56 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2019-02-08 07:56:37 -0500 |
commit | 78ac51f81532c1e361a31ac112c1fea470ea9036 (patch) | |
tree | 902a6460da1d4ee980bba2220151b931b520a6a9 /net/mac80211/mlme.c | |
parent | 0cd01efb03396c5368b1a32eed0ccb2aa453bdc8 (diff) |
mac80211: support multi-bssid
Add support for multi-bssid.
This includes:
- Parsing multi-bssid element
- Overriding DTIM values
- Taking into account in various places the inner BSSID instead of
transmitter BSSID
- Save aside some multi-bssid properties needed by drivers
Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 125 |
1 files changed, 88 insertions, 37 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 1f41f760bd22..64b6ddb67456 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -3308,6 +3308,14 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
3308 | /* TODO: OPEN: what happens if BSS color disable is set? */ | 3308 | /* TODO: OPEN: what happens if BSS color disable is set? */ |
3309 | } | 3309 | } |
3310 | 3310 | ||
3311 | if (cbss->transmitted_bss) { | ||
3312 | bss_conf->nontransmitted = true; | ||
3313 | ether_addr_copy(bss_conf->transmitter_bssid, | ||
3314 | cbss->transmitted_bss->bssid); | ||
3315 | bss_conf->bssid_indicator = cbss->max_bssid_indicator; | ||
3316 | bss_conf->bssid_index = cbss->bssid_index; | ||
3317 | } | ||
3318 | |||
3311 | /* | 3319 | /* |
3312 | * Some APs, e.g. Netgear WNDR3700, report invalid HT operation data | 3320 | * Some APs, e.g. Netgear WNDR3700, report invalid HT operation data |
3313 | * in their association response, so ignore that data for our own | 3321 | * in their association response, so ignore that data for our own |
@@ -3692,6 +3700,16 @@ static void ieee80211_handle_beacon_sig(struct ieee80211_sub_if_data *sdata, | |||
3692 | } | 3700 | } |
3693 | } | 3701 | } |
3694 | 3702 | ||
3703 | static bool ieee80211_rx_our_beacon(const u8 *tx_bssid, | ||
3704 | struct cfg80211_bss *bss) | ||
3705 | { | ||
3706 | if (ether_addr_equal(tx_bssid, bss->bssid)) | ||
3707 | return true; | ||
3708 | if (!bss->transmitted_bss) | ||
3709 | return false; | ||
3710 | return ether_addr_equal(tx_bssid, bss->transmitted_bss->bssid); | ||
3711 | } | ||
3712 | |||
3695 | static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | 3713 | static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, |
3696 | struct ieee80211_mgmt *mgmt, size_t len, | 3714 | struct ieee80211_mgmt *mgmt, size_t len, |
3697 | struct ieee80211_rx_status *rx_status) | 3715 | struct ieee80211_rx_status *rx_status) |
@@ -3733,17 +3751,16 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
3733 | rcu_read_unlock(); | 3751 | rcu_read_unlock(); |
3734 | 3752 | ||
3735 | if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon && | 3753 | if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon && |
3736 | ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) { | 3754 | ieee80211_rx_our_beacon(mgmt->bssid, ifmgd->assoc_data->bss)) { |
3737 | ieee802_11_parse_elems(mgmt->u.beacon.variable, | 3755 | ieee802_11_parse_elems(mgmt->u.beacon.variable, |
3738 | len - baselen, false, &elems, | 3756 | len - baselen, false, &elems, |
3739 | mgmt->bssid, | 3757 | mgmt->bssid, |
3740 | ifmgd->assoc_data->bss->bssid); | 3758 | ifmgd->assoc_data->bss->bssid); |
3741 | 3759 | ||
3742 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status); | 3760 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status); |
3743 | if (elems.tim && !elems.parse_error) { | 3761 | |
3744 | const struct ieee80211_tim_ie *tim_ie = elems.tim; | 3762 | if (elems.dtim_period) |
3745 | ifmgd->dtim_period = tim_ie->dtim_period; | 3763 | ifmgd->dtim_period = elems.dtim_period; |
3746 | } | ||
3747 | ifmgd->have_beacon = true; | 3764 | ifmgd->have_beacon = true; |
3748 | ifmgd->assoc_data->need_beacon = false; | 3765 | ifmgd->assoc_data->need_beacon = false; |
3749 | if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) { | 3766 | if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) { |
@@ -3751,12 +3768,17 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
3751 | le64_to_cpu(mgmt->u.beacon.timestamp); | 3768 | le64_to_cpu(mgmt->u.beacon.timestamp); |
3752 | sdata->vif.bss_conf.sync_device_ts = | 3769 | sdata->vif.bss_conf.sync_device_ts = |
3753 | rx_status->device_timestamp; | 3770 | rx_status->device_timestamp; |
3754 | if (elems.tim) | 3771 | sdata->vif.bss_conf.sync_dtim_count = elems.dtim_count; |
3755 | sdata->vif.bss_conf.sync_dtim_count = | ||
3756 | elems.tim->dtim_count; | ||
3757 | else | ||
3758 | sdata->vif.bss_conf.sync_dtim_count = 0; | ||
3759 | } | 3772 | } |
3773 | |||
3774 | if (elems.mbssid_config_ie) | ||
3775 | bss_conf->profile_periodicity = | ||
3776 | elems.mbssid_config_ie->profile_periodicity; | ||
3777 | |||
3778 | if (elems.ext_capab_len >= 11 && | ||
3779 | (elems.ext_capab[10] & WLAN_EXT_CAPA11_EMA_SUPPORT)) | ||
3780 | bss_conf->ema_ap = true; | ||
3781 | |||
3760 | /* continue assoc process */ | 3782 | /* continue assoc process */ |
3761 | ifmgd->assoc_data->timeout = jiffies; | 3783 | ifmgd->assoc_data->timeout = jiffies; |
3762 | ifmgd->assoc_data->timeout_started = true; | 3784 | ifmgd->assoc_data->timeout_started = true; |
@@ -3765,7 +3787,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
3765 | } | 3787 | } |
3766 | 3788 | ||
3767 | if (!ifmgd->associated || | 3789 | if (!ifmgd->associated || |
3768 | !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) | 3790 | !ieee80211_rx_our_beacon(mgmt->bssid, ifmgd->associated)) |
3769 | return; | 3791 | return; |
3770 | bssid = ifmgd->associated->bssid; | 3792 | bssid = ifmgd->associated->bssid; |
3771 | 3793 | ||
@@ -3861,11 +3883,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
3861 | le64_to_cpu(mgmt->u.beacon.timestamp); | 3883 | le64_to_cpu(mgmt->u.beacon.timestamp); |
3862 | sdata->vif.bss_conf.sync_device_ts = | 3884 | sdata->vif.bss_conf.sync_device_ts = |
3863 | rx_status->device_timestamp; | 3885 | rx_status->device_timestamp; |
3864 | if (elems.tim) | 3886 | sdata->vif.bss_conf.sync_dtim_count = elems.dtim_count; |
3865 | sdata->vif.bss_conf.sync_dtim_count = | ||
3866 | elems.tim->dtim_count; | ||
3867 | else | ||
3868 | sdata->vif.bss_conf.sync_dtim_count = 0; | ||
3869 | } | 3887 | } |
3870 | 3888 | ||
3871 | if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid) | 3889 | if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid) |
@@ -3891,10 +3909,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
3891 | */ | 3909 | */ |
3892 | if (!ifmgd->have_beacon) { | 3910 | if (!ifmgd->have_beacon) { |
3893 | /* a few bogus AP send dtim_period = 0 or no TIM IE */ | 3911 | /* a few bogus AP send dtim_period = 0 or no TIM IE */ |
3894 | if (elems.tim) | 3912 | bss_conf->dtim_period = elems.dtim_period ?: 1; |
3895 | bss_conf->dtim_period = elems.tim->dtim_period ?: 1; | ||
3896 | else | ||
3897 | bss_conf->dtim_period = 1; | ||
3898 | 3913 | ||
3899 | changed |= BSS_CHANGED_BEACON_INFO; | 3914 | changed |= BSS_CHANGED_BEACON_INFO; |
3900 | ifmgd->have_beacon = true; | 3915 | ifmgd->have_beacon = true; |
@@ -4761,6 +4776,40 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
4761 | return ret; | 4776 | return ret; |
4762 | } | 4777 | } |
4763 | 4778 | ||
4779 | static bool ieee80211_get_dtim(const struct cfg80211_bss_ies *ies, | ||
4780 | u8 *dtim_count, u8 *dtim_period) | ||
4781 | { | ||
4782 | const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM, ies->data, ies->len); | ||
4783 | const u8 *idx_ie = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX, ies->data, | ||
4784 | ies->len); | ||
4785 | const struct ieee80211_tim_ie *tim = NULL; | ||
4786 | const struct ieee80211_bssid_index *idx; | ||
4787 | bool valid = tim_ie && tim_ie[1] >= 2; | ||
4788 | |||
4789 | if (valid) | ||
4790 | tim = (void *)(tim_ie + 2); | ||
4791 | |||
4792 | if (dtim_count) | ||
4793 | *dtim_count = valid ? tim->dtim_count : 0; | ||
4794 | |||
4795 | if (dtim_period) | ||
4796 | *dtim_period = valid ? tim->dtim_period : 0; | ||
4797 | |||
4798 | /* Check if value is overridden by non-transmitted profile */ | ||
4799 | if (!idx_ie || idx_ie[1] < 3) | ||
4800 | return valid; | ||
4801 | |||
4802 | idx = (void *)(idx_ie + 2); | ||
4803 | |||
4804 | if (dtim_count) | ||
4805 | *dtim_count = idx->dtim_count; | ||
4806 | |||
4807 | if (dtim_period) | ||
4808 | *dtim_period = idx->dtim_period; | ||
4809 | |||
4810 | return true; | ||
4811 | } | ||
4812 | |||
4764 | static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | 4813 | static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, |
4765 | struct cfg80211_bss *cbss, bool assoc, | 4814 | struct cfg80211_bss *cbss, bool assoc, |
4766 | bool override) | 4815 | bool override) |
@@ -4852,17 +4901,13 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
4852 | rcu_read_lock(); | 4901 | rcu_read_lock(); |
4853 | ies = rcu_dereference(cbss->beacon_ies); | 4902 | ies = rcu_dereference(cbss->beacon_ies); |
4854 | if (ies) { | 4903 | if (ies) { |
4855 | const u8 *tim_ie; | ||
4856 | |||
4857 | sdata->vif.bss_conf.sync_tsf = ies->tsf; | 4904 | sdata->vif.bss_conf.sync_tsf = ies->tsf; |
4858 | sdata->vif.bss_conf.sync_device_ts = | 4905 | sdata->vif.bss_conf.sync_device_ts = |
4859 | bss->device_ts_beacon; | 4906 | bss->device_ts_beacon; |
4860 | tim_ie = cfg80211_find_ie(WLAN_EID_TIM, | 4907 | |
4861 | ies->data, ies->len); | 4908 | ieee80211_get_dtim(ies, |
4862 | if (tim_ie && tim_ie[1] >= 2) | 4909 | &sdata->vif.bss_conf.sync_dtim_count, |
4863 | sdata->vif.bss_conf.sync_dtim_count = tim_ie[2]; | 4910 | NULL); |
4864 | else | ||
4865 | sdata->vif.bss_conf.sync_dtim_count = 0; | ||
4866 | } else if (!ieee80211_hw_check(&sdata->local->hw, | 4911 | } else if (!ieee80211_hw_check(&sdata->local->hw, |
4867 | TIMING_BEACON_ONLY)) { | 4912 | TIMING_BEACON_ONLY)) { |
4868 | ies = rcu_dereference(cbss->proberesp_ies); | 4913 | ies = rcu_dereference(cbss->proberesp_ies); |
@@ -5332,17 +5377,12 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
5332 | assoc_data->timeout_started = true; | 5377 | assoc_data->timeout_started = true; |
5333 | assoc_data->need_beacon = true; | 5378 | assoc_data->need_beacon = true; |
5334 | } else if (beacon_ies) { | 5379 | } else if (beacon_ies) { |
5335 | const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM, | 5380 | const u8 *ie; |
5336 | beacon_ies->data, | ||
5337 | beacon_ies->len); | ||
5338 | u8 dtim_count = 0; | 5381 | u8 dtim_count = 0; |
5339 | 5382 | ||
5340 | if (tim_ie && tim_ie[1] >= sizeof(struct ieee80211_tim_ie)) { | 5383 | ieee80211_get_dtim(beacon_ies, &dtim_count, |
5341 | const struct ieee80211_tim_ie *tim; | 5384 | &ifmgd->dtim_period); |
5342 | tim = (void *)(tim_ie + 2); | 5385 | |
5343 | ifmgd->dtim_period = tim->dtim_period; | ||
5344 | dtim_count = tim->dtim_count; | ||
5345 | } | ||
5346 | ifmgd->have_beacon = true; | 5386 | ifmgd->have_beacon = true; |
5347 | assoc_data->timeout = jiffies; | 5387 | assoc_data->timeout = jiffies; |
5348 | assoc_data->timeout_started = true; | 5388 | assoc_data->timeout_started = true; |
@@ -5353,6 +5393,17 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
5353 | bss->device_ts_beacon; | 5393 | bss->device_ts_beacon; |
5354 | sdata->vif.bss_conf.sync_dtim_count = dtim_count; | 5394 | sdata->vif.bss_conf.sync_dtim_count = dtim_count; |
5355 | } | 5395 | } |
5396 | |||
5397 | ie = cfg80211_find_ext_ie(WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION, | ||
5398 | beacon_ies->data, beacon_ies->len); | ||
5399 | if (ie && ie[1] >= 3) | ||
5400 | sdata->vif.bss_conf.profile_periodicity = ie[4]; | ||
5401 | |||
5402 | ie = cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY, | ||
5403 | beacon_ies->data, beacon_ies->len); | ||
5404 | if (ie && ie[1] >= 11 && | ||
5405 | (ie[10] & WLAN_EXT_CAPA11_EMA_SUPPORT)) | ||
5406 | sdata->vif.bss_conf.ema_ap = true; | ||
5356 | } else { | 5407 | } else { |
5357 | assoc_data->timeout = jiffies; | 5408 | assoc_data->timeout = jiffies; |
5358 | assoc_data->timeout_started = true; | 5409 | assoc_data->timeout_started = true; |