Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3af6341c authored by Johannes Berg's avatar Johannes Berg
Browse files

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: default avatarJohannes Berg <johannes.berg@intel.com>
parent 4593c4cb
Loading
Loading
Loading
Loading
+39 −81
Original line number Diff line number Diff line
@@ -288,26 +288,6 @@ const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type,
}
EXPORT_SYMBOL(cfg80211_find_vendor_ie);

static int cmp_ies(u8 num, const u8 *ies1, int len1, const u8 *ies2, int len2)
{
	const u8 *ie1 = cfg80211_find_ie(num, ies1, len1);
	const u8 *ie2 = cfg80211_find_ie(num, ies2, len2);

	/* equal if both missing */
	if (!ie1 && !ie2)
		return 0;
	/* sort missing IE before (left of) present IE */
	if (!ie1)
		return -1;
	if (!ie2)
		return 1;

	/* sort by length first, then by contents */
	if (ie1[1] != ie2[1])
		return ie2[1] - ie1[1];
	return memcmp(ie1 + 2, ie2 + 2, ie1[1]);
}

static bool is_bss(struct cfg80211_bss *a, const u8 *bssid,
		   const u8 *ssid, size_t ssid_len)
{
@@ -331,29 +311,6 @@ static bool is_bss(struct cfg80211_bss *a, const u8 *bssid,
	return memcmp(ssidie + 2, ssid, ssid_len) == 0;
}

static bool is_mesh_bss(struct cfg80211_bss *a)
{
	const struct cfg80211_bss_ies *ies;
	const u8 *ie;

	if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability))
		return false;

	ies = rcu_access_pointer(a->ies);
	if (!ies)
		return false;

	ie = cfg80211_find_ie(WLAN_EID_MESH_ID, ies->data, ies->len);
	if (!ie)
		return false;

	ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, ies->data, ies->len);
	if (!ie)
		return false;

	return true;
}

static bool is_mesh(struct cfg80211_bss *a,
		    const u8 *meshid, size_t meshidlen,
		    const u8 *meshcfg)
@@ -391,39 +348,6 @@ static bool is_mesh(struct cfg80211_bss *a,
		      sizeof(struct ieee80211_meshconf_ie) - 2) == 0;
}

static int cmp_bss_core(struct cfg80211_bss *a, struct cfg80211_bss *b)
{
	const struct cfg80211_bss_ies *a_ies, *b_ies;
	int r;

	if (a->channel != b->channel)
		return b->channel->center_freq - a->channel->center_freq;

	if (is_mesh_bss(a) && is_mesh_bss(b)) {
		a_ies = rcu_access_pointer(a->ies);
		if (!a_ies)
			return -1;
		b_ies = rcu_access_pointer(b->ies);
		if (!b_ies)
			return 1;

		r = cmp_ies(WLAN_EID_MESH_ID,
			    a_ies->data, a_ies->len,
			    b_ies->data, b_ies->len);
		if (r)
			return r;
		return cmp_ies(WLAN_EID_MESH_CONFIG,
			       a_ies->data, a_ies->len,
			       b_ies->data, b_ies->len);
	}

	/*
	 * we can't use compare_ether_addr here since we need a < > operator.
	 * The binary return value of compare_ether_addr isn't enough
	 */
	return memcmp(a->bssid, b->bssid, sizeof(a->bssid));
}

/**
 * enum bss_compare_mode - BSS compare mode
 * @BSS_CMP_REGULAR: regular compare mode (for insertion and normal find)
@@ -441,13 +365,12 @@ static int cmp_bss(struct cfg80211_bss *a,
		   enum bss_compare_mode mode)
{
	const struct cfg80211_bss_ies *a_ies, *b_ies;
	const u8 *ie1;
	const u8 *ie2;
	const u8 *ie1 = NULL;
	const u8 *ie2 = NULL;
	int i, r;

	r = cmp_bss_core(a, b);
	if (r)
		return r;
	if (a->channel != b->channel)
		return b->channel->center_freq - a->channel->center_freq;

	a_ies = rcu_access_pointer(a->ies);
	if (!a_ies)
@@ -456,6 +379,41 @@ static int cmp_bss(struct cfg80211_bss *a,
	if (!b_ies)
		return 1;

	if (WLAN_CAPABILITY_IS_STA_BSS(a->capability))
		ie1 = cfg80211_find_ie(WLAN_EID_MESH_ID,
				       a_ies->data, a_ies->len);
	if (WLAN_CAPABILITY_IS_STA_BSS(b->capability))
		ie2 = cfg80211_find_ie(WLAN_EID_MESH_ID,
				       b_ies->data, b_ies->len);
	if (ie1 && ie2) {
		int mesh_id_cmp;

		if (ie1[1] == ie2[1])
			mesh_id_cmp = memcmp(ie1 + 2, ie2 + 2, ie1[1]);
		else
			mesh_id_cmp = ie2[1] - ie1[1];

		ie1 = cfg80211_find_ie(WLAN_EID_MESH_CONFIG,
				       a_ies->data, a_ies->len);
		ie2 = cfg80211_find_ie(WLAN_EID_MESH_CONFIG,
				       b_ies->data, b_ies->len);
		if (ie1 && ie2) {
			if (mesh_id_cmp)
				return mesh_id_cmp;
			if (ie1[1] != ie2[1])
				return ie2[1] - ie1[1];
			return memcmp(ie1 + 2, ie2 + 2, ie1[1]);
		}
	}

	/*
	 * we can't use compare_ether_addr here since we need a < > operator.
	 * The binary return value of compare_ether_addr isn't enough
	 */
	r = memcmp(a->bssid, b->bssid, sizeof(a->bssid));
	if (r)
		return r;

	ie1 = cfg80211_find_ie(WLAN_EID_SSID, a_ies->data, a_ies->len);
	ie2 = cfg80211_find_ie(WLAN_EID_SSID, b_ies->data, b_ies->len);