From 04e8b9ab62755a6fe33aac5c2c4abef5dbc92e7d Mon Sep 17 00:00:00 2001
From: Jakob Olsson <jakob.olsson@iopsys.eu>
Date: Mon, 25 Nov 2024 15:33:28 +0100
Subject: [PATCH] invalidate AP entries with same SSID as an MLD without being
 a part of it

---
 src/config.c | 108 ++++++++++++++++++++++++++++++++++++++-------------
 src/config.h |   3 +-
 2 files changed, 82 insertions(+), 29 deletions(-)

diff --git a/src/config.c b/src/config.c
index dc1c1065..678c6558 100644
--- a/src/config.c
+++ b/src/config.c
@@ -1972,8 +1972,19 @@ static void config_map_ap_to_mld(struct controller_config *cfg)
 	list_for_each_entry_safe(cred, tmp, &cfg->aplist, list) {
 		struct mld_credential *mld;
 
-		if (cred->mld_id == 0)
+		if (cred->mld_id == 0) {
+			if (cntlr_config_get_mld_by_ssid(cfg, (char *)cred->cred.ssid)) {
+				/** AP must not have same SSID as an MLD without
+				 *  being a part of it, discard entry
+				 **/
+				cfg->num_bss--;
+				clean_vendor_ies(cred);
+				list_del(&cred->list);
+				free(cred);
+			}
+
 			continue;
+		}
 
 		mld = cntlr_config_get_mld_by_id(cfg, cred->mld_id);
 		if (mld) {
@@ -2051,13 +2062,13 @@ uint8_t cntlr_policy_lists_diff(struct list_head *prev_policylist,
 	return diff;
 }
 
-uint8_t cntlr_vendor_ies_diff(struct list_head *prev_credslist,
-		struct list_head *curr_credslist)
+uint8_t cntlr_vendor_ies_diff(struct controller_config *pcfg,
+			      struct controller_config *ccfg)
 {
 	struct iface_credential *prev, *curr;
 	uint8_t diff = 0;
 
-	list_for_multiple_entry(prev, curr, prev_credslist, curr_credslist, list, list) {
+	list_for_multiple_entry(prev, curr, &pcfg->aplist, &pcfg->aplist, list, list) {
 		if (prev->num_ven_ies != curr->num_ven_ies) {
 			dbg("num of vendor ies differ\n");
 			diff |= CONFIG_DIFF_CREDENTIALS;
@@ -2091,10 +2102,28 @@ uint8_t cntlr_creds_diff(struct controller_config *cfg,
 {
 	uint8_t diff = 0;
 
+
 	/* credentials diff */
 	if (prev->num_bss != cfg->num_bss) {
+#if (EASYMESH_VERSION >= 6)
+		int prev_num_affaps = 0;
+		int curr_num_affaps = 0;
+		struct mld_credential *mld;
+
+		list_for_each_entry(mld, &prev->mldlist, list)
+			prev_num_affaps += mld->num_affiliated_aps;
+		list_for_each_entry(mld, &cfg->mldlist, list)
+			curr_num_affaps += mld->num_affiliated_aps;
+
+		/** if only affiliated APs are different, then handle via
+		 *  AP/BSTA MLD Config Request messages
+		 */
+		if ((prev->num_bss - cfg->num_bss) != (prev_num_affaps - curr_num_affaps))
+			diff |= CONFIG_DIFF_CREDENTIALS;
+#else
 		dbg("|%s:%d| number of credentials differed\n", __func__, __LINE__);
 		diff |= CONFIG_DIFF_CREDENTIALS;
+#endif
 	} else if (list_memcmp(&prev->aplist, &cfg->aplist,
 			       struct iface_credential,
 			       offsetof(struct iface_credential, list)
@@ -2115,27 +2144,57 @@ uint8_t cntlr_creds_diff(struct controller_config *cfg,
 #endif
 	else {
 		/* compare vendor ie list */
-		diff |= cntlr_vendor_ies_diff(&prev->aplist, &cfg->aplist);
+		diff |= cntlr_vendor_ies_diff(prev, cfg);
 	}
 
 	return diff;
 }
 
 #if (EASYMESH_VERSION >= 6)
-uint8_t cntlr_mld_id_diff(struct list_head *prev_credslist,
-		struct list_head *curr_credslist)
+uint8_t cntlr_mld_id_diff(struct controller_config *curr,
+		struct controller_config *prev)
 {
-	struct iface_credential *prev, *curr;
+	struct iface_credential *prev_ap = NULL, *curr_ap = NULL;
+	struct mld_credential *prev_mld = NULL, *curr_mld = NULL;
+	uint8_t multi_ap = 0;
 	uint8_t diff = 0;
 
-	list_for_multiple_entry(prev, curr, prev_credslist, curr_credslist, list, list) {
-		if (prev->mld_id != curr->mld_id) {
-			dbg("mld_id differ\n");
-			if (curr->multi_ap & 0x02)
-				diff |= CONFIG_DIFF_AP_MLD;
-			else if (curr->multi_ap & 0x01)
+	list_for_multiple_entry(prev_mld, curr_mld, &prev->mldlist, &curr->mldlist, list, list) {
+		if (prev_mld->multi_ap != curr_mld->multi_ap)
+			continue;
+
+		if (prev_mld->num_affiliated_aps != curr_mld->num_affiliated_aps) {
+			if (curr_mld->multi_ap & 0x01) {
 				diff |= CONFIG_DIFF_BSTA_MLD;
-			break;
+				diff |= CONFIG_DIFF_AP_MLD;
+				multi_ap |= 0x01;
+			} else if (curr_mld->multi_ap & 0x02) {
+				diff |= CONFIG_DIFF_AP_MLD;
+				multi_ap |= 0x02;
+			}
+		}
+	}
+
+	if (diff == 0) {
+		/** TODO: if REMOVE an affiliated FBSS from MLD and MOVE
+		 *  affiliated BBSS from one MLD to another, DIFF_BSTA_MLD *MAY*
+		 *  not get set
+		 **/
+		list_for_multiple_entry(prev_ap, curr_ap, &prev->aplist, &curr->aplist, list, list) {
+			/* skip mld type which had changed num affiliated APs */
+			if (prev_ap->multi_ap & multi_ap)
+				continue;
+
+			if (prev_ap->mld_id != curr_ap->mld_id) {
+				dbg("mld_id differ\n");
+				if (curr_ap->multi_ap & 0x02)
+					diff |= CONFIG_DIFF_AP_MLD;
+				else if (curr_ap->multi_ap & 0x01) {
+					diff |= CONFIG_DIFF_BSTA_MLD;
+					diff |= CONFIG_DIFF_AP_MLD;
+				}
+				break;
+			}
 		}
 	}
 
@@ -2147,19 +2206,12 @@ uint8_t cntlr_mld_diff(struct controller_config *cfg,
 {
 	uint8_t diff = 0;
 
-	/* Check ap sections for mld_id change */
-	diff |= cntlr_mld_id_diff(&prev->aplist, &cfg->aplist);
-
-	/* TODO: revisit below checks */
-	//if (prev->num_mlds != cfg->num_mlds) {
-	//	dbg("|%s:%d| number of MLD credentials differed\n", __func__, __LINE__);
-	//	diff |= CONFIG_DIFF_MLD;
-	//} else if (list_memcmp(&prev->mldlist, &cfg->mldlist,
-	//	   struct mld_credential,
-	//	   offsetof(struct mld_credential, list))) {
-	//	dbg("|%s:%d| MLD credentials have changed\n", __func__, __LINE__);
-	//	diff |= CONFIG_DIFF_MLD;
-	//}
+	if (prev->num_mlds != cfg->num_mlds)
+		diff |= CONFIG_DIFF_CREDENTIALS;
+	else {
+		/* Check ap sections for mld_id change */
+		diff |= cntlr_mld_id_diff(cfg, prev);
+	}
 
 	return diff;
 }
diff --git a/src/config.h b/src/config.h
index 05bc5076..6f7d8ff1 100644
--- a/src/config.h
+++ b/src/config.h
@@ -73,8 +73,9 @@ struct mld_credential {
 	uint16_t vlanid;
 	uint8_t multi_ap;
 	bool enabled;
-	uint8_t num_affiliated_aps;
 	struct list_head list;
+
+	uint8_t num_affiliated_aps;
 };
 #endif
 
-- 
GitLab