Browse Source

Replace sta_aid array with bitfield

The actual pointer to struct sta_info was not really used and it is
enough to use a single bit to indicate whether an AID is allocated. This
makes the BSS data take less memory while making the allocation routine
faster and removing the arbitrary MAX_AID_TABLE_SIZE limit of 128 STAs.
Jouni Malinen 16 years ago
parent
commit
2991469cd1
4 changed files with 27 additions and 19 deletions
  1. 0 8
      hostapd/ap.h
  2. 8 4
      hostapd/hostapd.h
  3. 17 6
      hostapd/ieee802_11.c
  4. 2 1
      hostapd/sta_info.c

+ 0 - 8
hostapd/ap.h

@@ -113,14 +113,6 @@ struct sta_info {
 };
 
 
-/* Maximum number of AIDs to use for STAs; must be 2007 or lower
- * (8802.11 limitation) */
-#define MAX_AID_TABLE_SIZE 128
-
-#define STA_HASH_SIZE 256
-#define STA_HASH(sta) (sta[5])
-
-
 /* Default value for maximum station inactivity. After AP_MAX_INACTIVITY has
  * passed since last received frame from the station, a nullfunc data frame is
  * sent to the station. If this frame is not acknowledged and no other frames

+ 8 - 4
hostapd/hostapd.h

@@ -44,13 +44,17 @@ struct hostapd_data {
 
 	int num_sta; /* number of entries in sta_list */
 	struct sta_info *sta_list; /* STA info list head */
+#define STA_HASH_SIZE 256
+#define STA_HASH(sta) (sta[5])
 	struct sta_info *sta_hash[STA_HASH_SIZE];
 
-	/* pointers to STA info; based on allocated AID or NULL if AID free
-	 * AID is in the range 1-2007, so sta_aid[0] corresponders to AID 1
-	 * and so on
+	/*
+	 * Bitfield for indicating which AIDs are allocated. Only AID values
+	 * 1-2007 are used and as such, the bit at index 0 corresponds to AID
+	 * 1.
 	 */
-	struct sta_info *sta_aid[MAX_AID_TABLE_SIZE];
+#define AID_WORDS ((2008 + 31) / 32)
+	u32 sta_aid[AID_WORDS];
 
 	const struct wpa_driver_ops *driver;
 	void *drv_priv;

+ 17 - 6
hostapd/ieee802_11.c

@@ -667,21 +667,32 @@ static void handle_auth(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
 
 static int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
 {
+	int i, j = 32, aid;
+
 	/* get a unique AID */
 	if (sta->aid > 0) {
 		wpa_printf(MSG_DEBUG, "  old AID %d", sta->aid);
 		return 0;
 	}
 
-	for (sta->aid = 1; sta->aid <= MAX_AID_TABLE_SIZE; sta->aid++)
-		if (hapd->sta_aid[sta->aid - 1] == NULL)
+	for (i = 0; i < AID_WORDS; i++) {
+		if (hapd->sta_aid[i] == (u32) -1)
+			continue;
+		for (j = 0; j < 32; j++) {
+			if (!(hapd->sta_aid[i] & BIT(j)))
+				break;
+		}
+		if (j < 32)
 			break;
-	if (sta->aid > MAX_AID_TABLE_SIZE) {
-		sta->aid = 0;
-		return -1;
 	}
+	if (j == 32)
+		return -1;
+	aid = i * 32 + j + 1;
+	if (aid > 2007)
+		return -1;
 
-	hapd->sta_aid[sta->aid - 1] = sta;
+	sta->aid = aid;
+	hapd->sta_aid[i] |= BIT(j);
 	wpa_printf(MSG_DEBUG, "  new AID %d", sta->aid);
 	return 0;
 }

+ 2 - 1
hostapd/sta_info.c

@@ -128,7 +128,8 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
 	ap_sta_list_del(hapd, sta);
 
 	if (sta->aid > 0)
-		hapd->sta_aid[sta->aid - 1] = NULL;
+		hapd->sta_aid[(sta->aid - 1) / 32] &=
+			~BIT((sta->aid - 1) % 32);
 
 	hapd->num_sta--;
 	if (sta->nonerp_set) {