diff options
author | Sergey Matyukevich <sergey.matyukevich.os@quantenna.com> | 2019-07-26 12:39:32 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2019-07-29 10:23:13 -0400 |
commit | 3ab8227d3e7d1d2bf1829675d3197e3cb600e9f6 (patch) | |
tree | 59b3caf719a31d0f9a63086d636242894979f9e0 | |
parent | ae6fa4d5e94ea520506b691140ebcb5dc6bf0a17 (diff) |
cfg80211: refactor cfg80211_bss_update
This patch implements minor refactoring for cfg80211_bss_update function.
Code path for updating known BSS is extracted into dedicated
cfg80211_update_known_bss function.
Signed-off-by: Sergey Matyukevich <sergey.matyukevich.os@quantenna.com>
Link: https://lore.kernel.org/r/20190726163922.27509-2-sergey.matyukevich.os@quantenna.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r-- | net/wireless/scan.c | 171 |
1 files changed, 89 insertions, 82 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index a98dabab557a..9119f5ce3677 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -1091,6 +1091,93 @@ struct cfg80211_non_tx_bss { | |||
1091 | u8 bssid_index; | 1091 | u8 bssid_index; |
1092 | }; | 1092 | }; |
1093 | 1093 | ||
1094 | static bool | ||
1095 | cfg80211_update_known_bss(struct cfg80211_registered_device *rdev, | ||
1096 | struct cfg80211_internal_bss *known, | ||
1097 | struct cfg80211_internal_bss *new, | ||
1098 | bool signal_valid) | ||
1099 | { | ||
1100 | lockdep_assert_held(&rdev->bss_lock); | ||
1101 | |||
1102 | /* Update IEs */ | ||
1103 | if (rcu_access_pointer(new->pub.proberesp_ies)) { | ||
1104 | const struct cfg80211_bss_ies *old; | ||
1105 | |||
1106 | old = rcu_access_pointer(known->pub.proberesp_ies); | ||
1107 | |||
1108 | rcu_assign_pointer(known->pub.proberesp_ies, | ||
1109 | new->pub.proberesp_ies); | ||
1110 | /* Override possible earlier Beacon frame IEs */ | ||
1111 | rcu_assign_pointer(known->pub.ies, | ||
1112 | new->pub.proberesp_ies); | ||
1113 | if (old) | ||
1114 | kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head); | ||
1115 | } else if (rcu_access_pointer(new->pub.beacon_ies)) { | ||
1116 | const struct cfg80211_bss_ies *old; | ||
1117 | struct cfg80211_internal_bss *bss; | ||
1118 | |||
1119 | if (known->pub.hidden_beacon_bss && | ||
1120 | !list_empty(&known->hidden_list)) { | ||
1121 | const struct cfg80211_bss_ies *f; | ||
1122 | |||
1123 | /* The known BSS struct is one of the probe | ||
1124 | * response members of a group, but we're | ||
1125 | * receiving a beacon (beacon_ies in the new | ||
1126 | * bss is used). This can only mean that the | ||
1127 | * AP changed its beacon from not having an | ||
1128 | * SSID to showing it, which is confusing so | ||
1129 | * drop this information. | ||
1130 | */ | ||
1131 | |||
1132 | f = rcu_access_pointer(new->pub.beacon_ies); | ||
1133 | kfree_rcu((struct cfg80211_bss_ies *)f, rcu_head); | ||
1134 | return false; | ||
1135 | } | ||
1136 | |||
1137 | old = rcu_access_pointer(known->pub.beacon_ies); | ||
1138 | |||
1139 | rcu_assign_pointer(known->pub.beacon_ies, new->pub.beacon_ies); | ||
1140 | |||
1141 | /* Override IEs if they were from a beacon before */ | ||
1142 | if (old == rcu_access_pointer(known->pub.ies)) | ||
1143 | rcu_assign_pointer(known->pub.ies, new->pub.beacon_ies); | ||
1144 | |||
1145 | /* Assign beacon IEs to all sub entries */ | ||
1146 | list_for_each_entry(bss, &known->hidden_list, hidden_list) { | ||
1147 | const struct cfg80211_bss_ies *ies; | ||
1148 | |||
1149 | ies = rcu_access_pointer(bss->pub.beacon_ies); | ||
1150 | WARN_ON(ies != old); | ||
1151 | |||
1152 | rcu_assign_pointer(bss->pub.beacon_ies, | ||
1153 | new->pub.beacon_ies); | ||
1154 | } | ||
1155 | |||
1156 | if (old) | ||
1157 | kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head); | ||
1158 | } | ||
1159 | |||
1160 | known->pub.beacon_interval = new->pub.beacon_interval; | ||
1161 | |||
1162 | /* don't update the signal if beacon was heard on | ||
1163 | * adjacent channel. | ||
1164 | */ | ||
1165 | if (signal_valid) | ||
1166 | known->pub.signal = new->pub.signal; | ||
1167 | known->pub.capability = new->pub.capability; | ||
1168 | known->ts = new->ts; | ||
1169 | known->ts_boottime = new->ts_boottime; | ||
1170 | known->parent_tsf = new->parent_tsf; | ||
1171 | known->pub.chains = new->pub.chains; | ||
1172 | memcpy(known->pub.chain_signal, new->pub.chain_signal, | ||
1173 | IEEE80211_MAX_CHAINS); | ||
1174 | ether_addr_copy(known->parent_bssid, new->parent_bssid); | ||
1175 | known->pub.max_bssid_indicator = new->pub.max_bssid_indicator; | ||
1176 | known->pub.bssid_index = new->pub.bssid_index; | ||
1177 | |||
1178 | return true; | ||
1179 | } | ||
1180 | |||
1094 | /* Returned bss is reference counted and must be cleaned up appropriately. */ | 1181 | /* Returned bss is reference counted and must be cleaned up appropriately. */ |
1095 | struct cfg80211_internal_bss * | 1182 | struct cfg80211_internal_bss * |
1096 | cfg80211_bss_update(struct cfg80211_registered_device *rdev, | 1183 | cfg80211_bss_update(struct cfg80211_registered_device *rdev, |
@@ -1114,88 +1201,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev, | |||
1114 | found = rb_find_bss(rdev, tmp, BSS_CMP_REGULAR); | 1201 | found = rb_find_bss(rdev, tmp, BSS_CMP_REGULAR); |
1115 | 1202 | ||
1116 | if (found) { | 1203 | if (found) { |
1117 | /* Update IEs */ | 1204 | if (!cfg80211_update_known_bss(rdev, found, tmp, signal_valid)) |
1118 | if (rcu_access_pointer(tmp->pub.proberesp_ies)) { | 1205 | goto drop; |
1119 | const struct cfg80211_bss_ies *old; | ||
1120 | |||
1121 | old = rcu_access_pointer(found->pub.proberesp_ies); | ||
1122 | |||
1123 | rcu_assign_pointer(found->pub.proberesp_ies, | ||
1124 | tmp->pub.proberesp_ies); | ||
1125 | /* Override possible earlier Beacon frame IEs */ | ||
1126 | rcu_assign_pointer(found->pub.ies, | ||
1127 | tmp->pub.proberesp_ies); | ||
1128 | if (old) | ||
1129 | kfree_rcu((struct cfg80211_bss_ies *)old, | ||
1130 | rcu_head); | ||
1131 | } else if (rcu_access_pointer(tmp->pub.beacon_ies)) { | ||
1132 | const struct cfg80211_bss_ies *old; | ||
1133 | struct cfg80211_internal_bss *bss; | ||
1134 | |||
1135 | if (found->pub.hidden_beacon_bss && | ||
1136 | !list_empty(&found->hidden_list)) { | ||
1137 | const struct cfg80211_bss_ies *f; | ||
1138 | |||
1139 | /* | ||
1140 | * The found BSS struct is one of the probe | ||
1141 | * response members of a group, but we're | ||
1142 | * receiving a beacon (beacon_ies in the tmp | ||
1143 | * bss is used). This can only mean that the | ||
1144 | * AP changed its beacon from not having an | ||
1145 | * SSID to showing it, which is confusing so | ||
1146 | * drop this information. | ||
1147 | */ | ||
1148 | |||
1149 | f = rcu_access_pointer(tmp->pub.beacon_ies); | ||
1150 | kfree_rcu((struct cfg80211_bss_ies *)f, | ||
1151 | rcu_head); | ||
1152 | goto drop; | ||
1153 | } | ||
1154 | |||
1155 | old = rcu_access_pointer(found->pub.beacon_ies); | ||
1156 | |||
1157 | rcu_assign_pointer(found->pub.beacon_ies, | ||
1158 | tmp->pub.beacon_ies); | ||
1159 | |||
1160 | /* Override IEs if they were from a beacon before */ | ||
1161 | if (old == rcu_access_pointer(found->pub.ies)) | ||
1162 | rcu_assign_pointer(found->pub.ies, | ||
1163 | tmp->pub.beacon_ies); | ||
1164 | |||
1165 | /* Assign beacon IEs to all sub entries */ | ||
1166 | list_for_each_entry(bss, &found->hidden_list, | ||
1167 | hidden_list) { | ||
1168 | const struct cfg80211_bss_ies *ies; | ||
1169 | |||
1170 | ies = rcu_access_pointer(bss->pub.beacon_ies); | ||
1171 | WARN_ON(ies != old); | ||
1172 | |||
1173 | rcu_assign_pointer(bss->pub.beacon_ies, | ||
1174 | tmp->pub.beacon_ies); | ||
1175 | } | ||
1176 | |||
1177 | if (old) | ||
1178 | kfree_rcu((struct cfg80211_bss_ies *)old, | ||
1179 | rcu_head); | ||
1180 | } | ||
1181 | |||
1182 | found->pub.beacon_interval = tmp->pub.beacon_interval; | ||
1183 | /* | ||
1184 | * don't update the signal if beacon was heard on | ||
1185 | * adjacent channel. | ||
1186 | */ | ||
1187 | if (signal_valid) | ||
1188 | found->pub.signal = tmp->pub.signal; | ||
1189 | found->pub.capability = tmp->pub.capability; | ||
1190 | found->ts = tmp->ts; | ||
1191 | found->ts_boottime = tmp->ts_boottime; | ||
1192 | found->parent_tsf = tmp->parent_tsf; | ||
1193 | found->pub.chains = tmp->pub.chains; | ||
1194 | memcpy(found->pub.chain_signal, tmp->pub.chain_signal, | ||
1195 | IEEE80211_MAX_CHAINS); | ||
1196 | ether_addr_copy(found->parent_bssid, tmp->parent_bssid); | ||
1197 | found->pub.max_bssid_indicator = tmp->pub.max_bssid_indicator; | ||
1198 | found->pub.bssid_index = tmp->pub.bssid_index; | ||
1199 | } else { | 1206 | } else { |
1200 | struct cfg80211_internal_bss *new; | 1207 | struct cfg80211_internal_bss *new; |
1201 | struct cfg80211_internal_bss *hidden; | 1208 | struct cfg80211_internal_bss *hidden; |