diff options
author | Johannes Berg <johannes.berg@intel.com> | 2013-01-29 18:40:20 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-02-04 12:57:41 -0500 |
commit | 3af6341c5378d1ed0905614575ee9ee2e5522c81 (patch) | |
tree | 876cbc80cc25a62a485f1b2582627b0cf996c71a /net/wireless/scan.c | |
parent | 4593c4cbe1c96b3995727dc42f6aa103f4ff5afc (diff) |
cfg80211: simplify mesh BSS comparison
Instead of first checking if a BSS is an MBSS
and then doing the comparisons, inline it all
into the BSS comparison function. This avoids
doing the IE searches twice and is also a lot
less code.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless/scan.c')
-rw-r--r-- | net/wireless/scan.c | 120 |
1 files changed, 39 insertions, 81 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index d4fe065eeb11..1435b97b1ca2 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -288,26 +288,6 @@ const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type, | |||
288 | } | 288 | } |
289 | EXPORT_SYMBOL(cfg80211_find_vendor_ie); | 289 | EXPORT_SYMBOL(cfg80211_find_vendor_ie); |
290 | 290 | ||
291 | static int cmp_ies(u8 num, const u8 *ies1, int len1, const u8 *ies2, int len2) | ||
292 | { | ||
293 | const u8 *ie1 = cfg80211_find_ie(num, ies1, len1); | ||
294 | const u8 *ie2 = cfg80211_find_ie(num, ies2, len2); | ||
295 | |||
296 | /* equal if both missing */ | ||
297 | if (!ie1 && !ie2) | ||
298 | return 0; | ||
299 | /* sort missing IE before (left of) present IE */ | ||
300 | if (!ie1) | ||
301 | return -1; | ||
302 | if (!ie2) | ||
303 | return 1; | ||
304 | |||
305 | /* sort by length first, then by contents */ | ||
306 | if (ie1[1] != ie2[1]) | ||
307 | return ie2[1] - ie1[1]; | ||
308 | return memcmp(ie1 + 2, ie2 + 2, ie1[1]); | ||
309 | } | ||
310 | |||
311 | static bool is_bss(struct cfg80211_bss *a, const u8 *bssid, | 291 | static bool is_bss(struct cfg80211_bss *a, const u8 *bssid, |
312 | const u8 *ssid, size_t ssid_len) | 292 | const u8 *ssid, size_t ssid_len) |
313 | { | 293 | { |
@@ -331,29 +311,6 @@ static bool is_bss(struct cfg80211_bss *a, const u8 *bssid, | |||
331 | return memcmp(ssidie + 2, ssid, ssid_len) == 0; | 311 | return memcmp(ssidie + 2, ssid, ssid_len) == 0; |
332 | } | 312 | } |
333 | 313 | ||
334 | static bool is_mesh_bss(struct cfg80211_bss *a) | ||
335 | { | ||
336 | const struct cfg80211_bss_ies *ies; | ||
337 | const u8 *ie; | ||
338 | |||
339 | if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability)) | ||
340 | return false; | ||
341 | |||
342 | ies = rcu_access_pointer(a->ies); | ||
343 | if (!ies) | ||
344 | return false; | ||
345 | |||
346 | ie = cfg80211_find_ie(WLAN_EID_MESH_ID, ies->data, ies->len); | ||
347 | if (!ie) | ||
348 | return false; | ||
349 | |||
350 | ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, ies->data, ies->len); | ||
351 | if (!ie) | ||
352 | return false; | ||
353 | |||
354 | return true; | ||
355 | } | ||
356 | |||
357 | static bool is_mesh(struct cfg80211_bss *a, | 314 | static bool is_mesh(struct cfg80211_bss *a, |
358 | const u8 *meshid, size_t meshidlen, | 315 | const u8 *meshid, size_t meshidlen, |
359 | const u8 *meshcfg) | 316 | const u8 *meshcfg) |
@@ -391,39 +348,6 @@ static bool is_mesh(struct cfg80211_bss *a, | |||
391 | sizeof(struct ieee80211_meshconf_ie) - 2) == 0; | 348 | sizeof(struct ieee80211_meshconf_ie) - 2) == 0; |
392 | } | 349 | } |
393 | 350 | ||
394 | static int cmp_bss_core(struct cfg80211_bss *a, struct cfg80211_bss *b) | ||
395 | { | ||
396 | const struct cfg80211_bss_ies *a_ies, *b_ies; | ||
397 | int r; | ||
398 | |||
399 | if (a->channel != b->channel) | ||
400 | return b->channel->center_freq - a->channel->center_freq; | ||
401 | |||
402 | if (is_mesh_bss(a) && is_mesh_bss(b)) { | ||
403 | a_ies = rcu_access_pointer(a->ies); | ||
404 | if (!a_ies) | ||
405 | return -1; | ||
406 | b_ies = rcu_access_pointer(b->ies); | ||
407 | if (!b_ies) | ||
408 | return 1; | ||
409 | |||
410 | r = cmp_ies(WLAN_EID_MESH_ID, | ||
411 | a_ies->data, a_ies->len, | ||
412 | b_ies->data, b_ies->len); | ||
413 | if (r) | ||
414 | return r; | ||
415 | return cmp_ies(WLAN_EID_MESH_CONFIG, | ||
416 | a_ies->data, a_ies->len, | ||
417 | b_ies->data, b_ies->len); | ||
418 | } | ||
419 | |||
420 | /* | ||
421 | * we can't use compare_ether_addr here since we need a < > operator. | ||
422 | * The binary return value of compare_ether_addr isn't enough | ||
423 | */ | ||
424 | return memcmp(a->bssid, b->bssid, sizeof(a->bssid)); | ||
425 | } | ||
426 | |||
427 | /** | 351 | /** |
428 | * enum bss_compare_mode - BSS compare mode | 352 | * enum bss_compare_mode - BSS compare mode |
429 | * @BSS_CMP_REGULAR: regular compare mode (for insertion and normal find) | 353 | * @BSS_CMP_REGULAR: regular compare mode (for insertion and normal find) |
@@ -441,13 +365,12 @@ static int cmp_bss(struct cfg80211_bss *a, | |||
441 | enum bss_compare_mode mode) | 365 | enum bss_compare_mode mode) |
442 | { | 366 | { |
443 | const struct cfg80211_bss_ies *a_ies, *b_ies; | 367 | const struct cfg80211_bss_ies *a_ies, *b_ies; |
444 | const u8 *ie1; | 368 | const u8 *ie1 = NULL; |
445 | const u8 *ie2; | 369 | const u8 *ie2 = NULL; |
446 | int i, r; | 370 | int i, r; |
447 | 371 | ||
448 | r = cmp_bss_core(a, b); | 372 | if (a->channel != b->channel) |
449 | if (r) | 373 | return b->channel->center_freq - a->channel->center_freq; |
450 | return r; | ||
451 | 374 | ||
452 | a_ies = rcu_access_pointer(a->ies); | 375 | a_ies = rcu_access_pointer(a->ies); |
453 | if (!a_ies) | 376 | if (!a_ies) |
@@ -456,6 +379,41 @@ static int cmp_bss(struct cfg80211_bss *a, | |||
456 | if (!b_ies) | 379 | if (!b_ies) |
457 | return 1; | 380 | return 1; |
458 | 381 | ||
382 | if (WLAN_CAPABILITY_IS_STA_BSS(a->capability)) | ||
383 | ie1 = cfg80211_find_ie(WLAN_EID_MESH_ID, | ||
384 | a_ies->data, a_ies->len); | ||
385 | if (WLAN_CAPABILITY_IS_STA_BSS(b->capability)) | ||
386 | ie2 = cfg80211_find_ie(WLAN_EID_MESH_ID, | ||
387 | b_ies->data, b_ies->len); | ||
388 | if (ie1 && ie2) { | ||
389 | int mesh_id_cmp; | ||
390 | |||
391 | if (ie1[1] == ie2[1]) | ||
392 | mesh_id_cmp = memcmp(ie1 + 2, ie2 + 2, ie1[1]); | ||
393 | else | ||
394 | mesh_id_cmp = ie2[1] - ie1[1]; | ||
395 | |||
396 | ie1 = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, | ||
397 | a_ies->data, a_ies->len); | ||
398 | ie2 = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, | ||
399 | b_ies->data, b_ies->len); | ||
400 | if (ie1 && ie2) { | ||
401 | if (mesh_id_cmp) | ||
402 | return mesh_id_cmp; | ||
403 | if (ie1[1] != ie2[1]) | ||
404 | return ie2[1] - ie1[1]; | ||
405 | return memcmp(ie1 + 2, ie2 + 2, ie1[1]); | ||
406 | } | ||
407 | } | ||
408 | |||
409 | /* | ||
410 | * we can't use compare_ether_addr here since we need a < > operator. | ||
411 | * The binary return value of compare_ether_addr isn't enough | ||
412 | */ | ||
413 | r = memcmp(a->bssid, b->bssid, sizeof(a->bssid)); | ||
414 | if (r) | ||
415 | return r; | ||
416 | |||
459 | ie1 = cfg80211_find_ie(WLAN_EID_SSID, a_ies->data, a_ies->len); | 417 | ie1 = cfg80211_find_ie(WLAN_EID_SSID, a_ies->data, a_ies->len); |
460 | ie2 = cfg80211_find_ie(WLAN_EID_SSID, b_ies->data, b_ies->len); | 418 | ie2 = cfg80211_find_ie(WLAN_EID_SSID, b_ies->data, b_ies->len); |
461 | 419 | ||