aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/scan.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-01-29 18:40:20 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-02-04 12:57:41 -0500
commit3af6341c5378d1ed0905614575ee9ee2e5522c81 (patch)
tree876cbc80cc25a62a485f1b2582627b0cf996c71a /net/wireless/scan.c
parent4593c4cbe1c96b3995727dc42f6aa103f4ff5afc (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.c120
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}
289EXPORT_SYMBOL(cfg80211_find_vendor_ie); 289EXPORT_SYMBOL(cfg80211_find_vendor_ie);
290 290
291static 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
311static bool is_bss(struct cfg80211_bss *a, const u8 *bssid, 291static 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
334static 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
357static bool is_mesh(struct cfg80211_bss *a, 314static 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
394static 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