blob: e1bbe39f63cef5a9f7c03e863b0f2bc0755466ac [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
2 * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/*
29 *
30 * This file dph_hash_table.cc implements the member functions of
31 * DPH hash table class.
32 *
33 * Author: Sandesh Goel
34 * Date: 02/25/02
35 * History:-
36 * Date Modified by Modification Information
37 * --------------------------------------------------------------------
38 *
39 */
40#include "cds_api.h"
41#include "cfg_api.h"
42#include "sch_api.h"
43#include "dph_global.h"
44#include "lim_debug.h"
45
46#include "wma_if.h"
47
48/* --------------------------------------------------------------------- */
49/**
50 * dphHashTableClass()
51 *
52 * FUNCTION:
53 * Constructor function
54 *
55 * LOGIC:
56 *
57 * ASSUMPTIONS:
58 *
59 * NOTE:
60 *
61 * @param None
62 * @return None
63 */
64
65void dph_hash_table_class_init(tpAniSirGlobal pMac,
66 dphHashTableClass *pDphHashTable)
67{
68 uint16_t i;
69
70 for (i = 0; i < pDphHashTable->size; i++) {
71 pDphHashTable->pHashTable[i] = 0;
72 }
73
74 for (i = 0; i < pDphHashTable->size; i++) {
75 pDphHashTable->pDphNodeArray[i].valid = 0;
76 pDphHashTable->pDphNodeArray[i].added = 0;
77 pDphHashTable->pDphNodeArray[i].assocId = i;
78 }
79
80}
81
82/* --------------------------------------------------------------------- */
83/**
84 * hash_function
85 *
86 * FUNCTION:
87 * Hashing function
88 *
89 * LOGIC:
90 *
91 * ASSUMPTIONS:
92 *
93 * NOTE:
94 *
95 * @param staAddr MAC address of the station
96 * @return None
97 */
98
99uint16_t hash_function(tpAniSirGlobal pMac, uint8_t staAddr[], uint16_t numSta)
100{
101 int i;
102 uint16_t sum = 0;
103
104 for (i = 0; i < 6; i++)
105 sum += staAddr[i];
106
107 return (sum % numSta);
108}
109
110/* --------------------------------------------------------------------- */
111/**
112 * dph_lookup_hash_entry
113 *
114 * FUNCTION:
115 * Look up an entry in hash table
116 *
117 * LOGIC:
118 *
119 * ASSUMPTIONS:
120 *
121 * NOTE:
122 *
123 * @param staAddr MAC address of the station
124 * @param pStaId pointer to the Station ID assigned to the station
125 * @return pointer to STA hash entry if lookup was a success \n
126 * NULL if lookup was a failure
127 */
128
129tpDphHashNode dph_lookup_hash_entry(tpAniSirGlobal pMac, uint8_t staAddr[],
130 uint16_t *pAssocId,
131 dphHashTableClass *pDphHashTable)
132{
133 tpDphHashNode ptr = NULL;
134 uint16_t index = hash_function(pMac, staAddr, pDphHashTable->size);
135
136 for (ptr = pDphHashTable->pHashTable[index]; ptr; ptr = ptr->next) {
137 if (dph_compare_mac_addr(staAddr, ptr->staAddr)) {
138 *pAssocId = ptr->assocId;
139 break;
140 }
141 }
142 return ptr;
143}
144
145/* --------------------------------------------------------------------- */
146/**
147 * dph_get_hash_entry
148 *
149 * FUNCTION:
150 * Get a pointer to the hash node
151 *
152 * LOGIC:
153 *
154 * ASSUMPTIONS:
155 *
156 * NOTE:
157 *
158 * @param staId Station ID
159 * @return pointer to STA hash entry if lookup was a success \n
160 * NULL if lookup was a failure
161 */
162
163tpDphHashNode dph_get_hash_entry(tpAniSirGlobal pMac, uint16_t peerIdx,
164 dphHashTableClass *pDphHashTable)
165{
166 if (peerIdx < pDphHashTable->size) {
167 if (pDphHashTable->pDphNodeArray[peerIdx].added)
168 return &pDphHashTable->pDphNodeArray[peerIdx];
169 else
170 return NULL;
171 } else
172 return NULL;
173
174}
175
176static inline tpDphHashNode get_node(tpAniSirGlobal pMac, uint8_t assocId,
177 dphHashTableClass *pDphHashTable)
178{
179 return &pDphHashTable->pDphNodeArray[assocId];
180}
181
182/* --------------------------------------------------------------------- */
183/**
184 * dph_lookup_assoc_id
185 *
186 * FUNCTION:
187 * This function looks up assocID given the station Id. It traverses the complete table to do this.
188 * Need to find an efficient way to do this.
189 * LOGIC:
190 *
191 * ASSUMPTIONS:
192 *
193 * NOTE:
194 *
195 * @param pMac pointer to global Mac structure.
196 * @param staIdx station ID
197 * @param *assocId pointer to associd to be returned by this function.
198 * @return pointer to the dph node.
199 */
200tpDphHashNode dph_lookup_assoc_id(tpAniSirGlobal pMac, uint16_t staIdx,
201 uint16_t *assocId,
202 dphHashTableClass *pDphHashTable)
203{
204 uint8_t i;
205
206 for (i = 0; i < pDphHashTable->size; i++) {
207 if ((pDphHashTable->pDphNodeArray[i].added) &&
208 (pDphHashTable->pDphNodeArray[i].staIndex == staIdx)) {
209 *assocId = i;
210 break;
211 }
212
213 }
214 if (i == pDphHashTable->size)
215 return NULL;
216 return &pDphHashTable->pDphNodeArray[i];
217
218}
219
220/** -------------------------------------------------------------
221 \fn dph_init_sta_state
222 \brief Initialize STA state. this function saves the staId from the current entry in the DPH table with given assocId
223 \ if validStaIdx flag is set. Otherwise it sets the staId to invalid.
224 \param tpAniSirGlobal pMac
225 \param tSirMacAddr staAddr
226 \param uint16_t assocId
227 \param uint8_t validStaIdx - true ==> the staId in the DPH entry with given assocId is valid and restore it back.
228 \ false ==> set the staId to invalid.
229 \return tpDphHashNode - DPH hash node if found.
230 -------------------------------------------------------------*/
231
232tpDphHashNode dph_init_sta_state(tpAniSirGlobal pMac, tSirMacAddr staAddr,
233 uint16_t assocId, uint8_t validStaIdx,
234 dphHashTableClass *pDphHashTable)
235{
236 uint32_t val;
237
238 tpDphHashNode pStaDs;
239 uint16_t staIdx = STA_INVALID_IDX;
240
241 if (assocId >= pDphHashTable->size) {
242 PELOGE(lim_log(pMac, LOGE, FL("Invalid Assoc Id %d"), assocId);)
243 return NULL;
244 }
245
246 pStaDs = get_node(pMac, (uint8_t) assocId, pDphHashTable);
247 staIdx = pStaDs->staIndex;
248
249 PELOG1(lim_log
250 (pMac, LOG1, FL("Assoc Id %d, Addr %08X"), assocId, pStaDs);
251 )
252 /* Clear the STA node except for the next pointer (last 4 bytes) */
253 cdf_mem_set((uint8_t *) pStaDs,
254 sizeof(tDphHashNode) - sizeof(tpDphHashNode), 0);
255
256 /* Initialize the assocId */
257 pStaDs->assocId = assocId;
258 if (true == validStaIdx)
259 pStaDs->staIndex = staIdx;
260 else
261 pStaDs->staIndex = STA_INVALID_IDX;
262
263 /* Initialize STA mac address */
264 cdf_mem_copy(pStaDs->staAddr, staAddr, sizeof(tSirMacAddr));
265
266 /* Initialize fragmentation threshold */
267 if (wlan_cfg_get_int(pMac, WNI_CFG_FRAGMENTATION_THRESHOLD, &val) !=
268 eSIR_SUCCESS)
269 lim_log(pMac, LOGP,
270 FL("could not retrieve fragmentation threshold"));
271 else
272 pStaDs->fragSize = (uint16_t) val;
273
274 pStaDs->added = 1;
275 pStaDs->encPolicy = ENC_POLICY_NULL;
276 pStaDs->is_disassoc_deauth_in_progress = 0;
277#ifdef WLAN_FEATURE_11W
278 pStaDs->last_assoc_received_time = 0;
279#endif
280 pStaDs->valid = 1;
281 return pStaDs;
282}
283
284/* --------------------------------------------------------------------- */
285/**
286 * dph_add_hash_entry
287 *
288 * FUNCTION:
289 * Add entry to hash table
290 *
291 * LOGIC:
292 *
293 * ASSUMPTIONS:
294 *
295 * NOTE:
296 *
297 * @param staAddr MAC address of the station
298 * @param staId Station ID assigned to the station
299 * @return Pointer to STA hash entry
300 */
301
302tpDphHashNode dph_add_hash_entry(tpAniSirGlobal pMac, tSirMacAddr staAddr,
303 uint16_t assocId,
304 dphHashTableClass *pDphHashTable)
305{
306 tpDphHashNode ptr, node;
307 uint16_t index = hash_function(pMac, staAddr, pDphHashTable->size);
308
309 PELOG1(lim_log(pMac, LOG1, FL("assocId %d index %d STA addr"),
310 assocId, index); dph_print_mac_addr(pMac, staAddr, LOG1);
311 )
312
313 if (assocId >= pDphHashTable->size) {
314 PELOGE(lim_log(pMac, LOGE, FL("invalid STA id %d"), assocId);)
315 return NULL;
316 }
317
318 if (pDphHashTable->pDphNodeArray[assocId].added) {
319 PELOGE(lim_log(pMac, LOGE, FL("already added STA %d"), assocId);)
320 return NULL;
321 }
322
323 for (ptr = pDphHashTable->pHashTable[index]; ptr; ptr = ptr->next) {
324 if (ptr == ptr->next) {
325 PELOGE(lim_log(pMac, LOGE, FL("Infinite Loop"));)
326 return NULL;
327 }
328
329 if (dph_compare_mac_addr(staAddr, ptr->staAddr)
330 || ptr->assocId == assocId)
331 break;
332 }
333
334 if (ptr) {
335 /* Duplicate entry */
336 lim_log(pMac, LOGE, FL("assocId %d hashIndex %d entry exists"),
337 assocId, index);
338 return NULL;
339 } else {
340 if (dph_init_sta_state
341 (pMac, staAddr, assocId, false, pDphHashTable) == NULL) {
342 PELOGE(lim_log
343 (pMac, LOGE, FL("could not Init STAid=%d"),
344 assocId);
345 )
346 return NULL;
347 }
348 /* Add the node to the link list */
349 pDphHashTable->pDphNodeArray[assocId].next =
350 pDphHashTable->pHashTable[index];
351 pDphHashTable->pHashTable[index] =
352 &pDphHashTable->pDphNodeArray[assocId];
353
354 node = pDphHashTable->pHashTable[index];
355 return node;
356 }
357}
358
359/* --------------------------------------------------------------------- */
360/**
361 * dph_delete_hash_entry
362 *
363 * FUNCTION:
364 * Delete entry from hash table
365 *
366 * LOGIC:
367 *
368 * ASSUMPTIONS:
369 *
370 * NOTE:
371 *
372 * @param staAddr MAC address of the station
373 * @param staId Station ID assigned to the station
374 * @return eSIR_SUCCESS if successful,\n
375 * eSIR_FAILURE otherwise
376 */
377
378tSirRetStatus dph_delete_hash_entry(tpAniSirGlobal pMac, tSirMacAddr staAddr,
379 uint16_t assocId,
380 dphHashTableClass *pDphHashTable)
381{
382 tpDphHashNode ptr, prev;
383 uint16_t index = hash_function(pMac, staAddr, pDphHashTable->size);
384
385 PELOG1(lim_log(pMac, LOG1, FL("assocId %d index %d STA addr"),
386 assocId, index); dph_print_mac_addr(pMac, staAddr, LOG1);
387 )
388
389 if (assocId >= pDphHashTable->size) {
390 PELOGE(lim_log(pMac, LOGE, FL("invalid STA id %d"), assocId);)
391 return eSIR_FAILURE;
392 }
393
394 if (pDphHashTable->pDphNodeArray[assocId].added == 0) {
395 PELOGE(lim_log(pMac, LOGE, FL("STA %d never added"), assocId);)
396 return eSIR_FAILURE;
397 }
398
399 for (prev = 0, ptr = pDphHashTable->pHashTable[index];
400 ptr; prev = ptr, ptr = ptr->next) {
401 if (dph_compare_mac_addr(staAddr, ptr->staAddr))
402 break;
403 if (prev == ptr) {
404 PELOGE(lim_log(pMac, LOGE, FL("Infinite Loop"));)
405 return eSIR_FAILURE;
406 }
407 }
408
409 if (ptr) {
410 /* / Delete the entry after invalidating it */
411 ptr->valid = 0;
412 memset(ptr->staAddr, 0, sizeof(ptr->staAddr));
413 if (prev == 0)
414 pDphHashTable->pHashTable[index] = ptr->next;
415 else
416 prev->next = ptr->next;
417 ptr->added = 0;
418 ptr->is_disassoc_deauth_in_progress = 0;
419#ifdef WLAN_FEATURE_11W
420 ptr->last_assoc_received_time = 0;
421#endif
422 ptr->next = 0;
423 } else {
424 /* / Entry not present */
425 PELOGE(lim_log(pMac, LOGE, FL("Entry not present STA addr"));
426 dph_print_mac_addr(pMac, staAddr, LOGE);
427 )
428 return eSIR_FAILURE;
429 }
430
431 return eSIR_SUCCESS;
432}
433
434/* --------------------------------------------------------------------- */
435/**
436 * dph_print_mac_addr
437 *
438 * FUNCTION:
439 * Print a MAC address
440 *
441 * LOGIC:
442 *
443 * ASSUMPTIONS:
444 *
445 * NOTE:
446 *
447 * @param addr MAC address
448 * @return None
449 */
450
451void dph_print_mac_addr(tpAniSirGlobal pMac, uint8_t addr[], uint32_t level)
452{
453 lim_log(pMac, (uint16_t) level, FL("MAC ADDR = %d:%d:%d:%d:%d:%d"),
454 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
455}
456
457/* --------------------------------------------------------------------- */
458
459