blob: 2a84cd0e5a62eb03e0744bfe9d54a8b5925f1aa1 [file] [log] [blame]
Shad Ansari2f7f9be2017-06-07 13:34:53 -07001/******************************************************************************
2 *
3 * <:copyright-BRCM:2016:DUAL/GPL:standard
4 *
5 * Copyright (c) 2016 Broadcom
6 * All Rights Reserved
7 *
8 * Unless you and Broadcom execute a separate written software license
9 * agreement governing use of this software, this software is licensed
10 * to you under the terms of the GNU General Public License version 2
11 * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
12 * with the following added to such license:
13 *
14 * As a special exception, the copyright holders of this software give
15 * you permission to link this software with independent modules, and
16 * to copy and distribute the resulting executable under terms of your
17 * choice, provided that you also meet, for each linked independent
18 * module, the terms and conditions of the license of that module.
19 * An independent module is a module which is not derived from this
20 * software. The special exception does not apply to any modifications
21 * of the software.
22 *
23 * Not withstanding the above, under no circumstances may you combine
24 * this software in any way with any other Broadcom software provided
25 * under a license other than the GPL, without Broadcom's express prior
26 * written consent.
27 *
28 * :>
29 *
30 *****************************************************************************/
31
32/**
33 * @file bal_mac_util_db_apis.c
34 *
35 * @brief This file has the wrapper functions and the calls to database API functions.
36 * These wrapper functions are called by mac util code for DB operations.
37 *
38 * @addtogroup mac_util
39 */
40
41/*@{*/
42
43#include <bal_mac_util.h>
44
45
46/**
47 * @brief flow DB macros
48 * */
49/** @brief max number of flow types stored in the DB.
50 * @details for now upstream & downstream unicast flows only are stored in the flow DB
51 * */
52#define MAC_UTIL_FLOW_DB_MAX_FLOW_TYPES 2
53
54/** @brief check if flow type key is valid */
55#define MAC_UTIL_FLOW_DB_FLOW_TYPE_IS_VALID(_flow_type) \
56 ((_flow_type) >= BCMBAL_FLOW_TYPE_UPSTREAM && \
57 (_flow_type) <= MAC_UTIL_FLOW_DB_MAX_FLOW_TYPES) \
58
59
60/**
61 * @brief maps {flow Id, flow_type} Key pair to an {Index, sub-Index} pair to access a flow entry in the Array DB.
62 * */
63#define MAC_UTIL_FLOW_DB_FLOW_ID_TYPE2ARR_INDEX_SUB_INDEX(_flow_id, _flow_type, _index, _sub_index) \
64 do \
65 { \
66 (_index) = (_sub_index) = 0; \
67 if(MAC_UTIL_FLOW_DB_FLOW_ID_IS_VALID(_flow_id)) \
68 { \
69 if(MAC_UTIL_FLOW_DB_FLOW_TYPE_IS_VALID(_flow_type)) \
70 { \
71 (_index) = (_flow_id) - mac_util_flow_id_start_val+1; \
72 (_sub_index) = (_flow_type) - 1; \
73 } \
74 } \
75 } while (0);
76
77
78/** @brief lookup an entry from the Array based on flow Id & type key pair */
79#define MAC_UTIL_FLOW_DB_ENTRY_GET(_flow_id, _flow_type, _flow_entry) \
80 do \
81 { \
82 (_flow_entry) = NULL; \
83 uint32_t _index, _sub_index; \
84 MAC_UTIL_FLOW_DB_FLOW_ID_TYPE2ARR_INDEX_SUB_INDEX((_flow_id), (_flow_type), (_index), (_sub_index)); \
85 if (!_index) \
86 break; \
87 _flow_entry = mac_util_db_flows_list[_index][_sub_index]; \
88 } while (0);
89
90
91/** @brief Get First non-NULL flow entry from the Array */
92#define MAC_UTIL_FLOW_DB_ENTRY_GET_FIRST(_p_first) \
93 do \
94 { \
95 int _i, _j; \
96 for (_i=1; _i<=BAL_ACC_TERM_MAX_FLOWS; _i++) \
97 { \
98 for (_j=0; _j<MAC_UTIL_FLOW_DB_MAX_FLOW_TYPES; _j++) \
99 { \
100 (_p_first) = mac_util_db_flows_list[_i][_j]; \
101 if (_p_first) \
102 break; \
103 } \
104 if (_p_first) \
105 break; \
106 } \
107 } while (0)
108
109
110/** @brief Get Next non-NULL flow entry from the Array */
111#define MAC_UTIL_FLOW_DB_ENTRY_GET_NEXT(_p_curr, _pp_next) \
112 do \
113 { \
114 uint32_t _i, _j, _curr_i, _curr_j; \
115 *(_pp_next) = NULL; \
116 if (_p_curr) \
117 { \
118 MAC_UTIL_FLOW_DB_FLOW_ID_TYPE2ARR_INDEX_SUB_INDEX(_p_curr->bal_flow_key.flow_id, _p_curr->bal_flow_key.flow_type, _curr_i, _curr_j);\
119 for (_i = (_curr_j<MAC_UTIL_FLOW_DB_MAX_FLOW_TYPES-1 ?_curr_i : _curr_i+1); \
120 _i<=BAL_ACC_TERM_MAX_FLOWS; \
121 _i++) \
122 { \
123 for (_j= (_curr_j<MAC_UTIL_FLOW_DB_MAX_FLOW_TYPES-1 ? _curr_j+1 : 0); \
124 _j<MAC_UTIL_FLOW_DB_MAX_FLOW_TYPES; \
125 _j++) \
126 { \
127 *(_pp_next) = mac_util_db_flows_list[_i][_j]; \
128 if (*(_pp_next)) \
129 break; \
130 } \
131 if (*(_pp_next)) \
132 break; \
133 } \
134 } \
135 else \
136 break; \
137 } while (0)
138
139
140/** @brief Set a flow entry in the Array */
141#define MAC_UTIL_FLOW_DB_ENTRY_SET(_flow_id, _flow_type, _flow_entry, _rc) \
142 do \
143 { \
144 uint32_t _index, _sub_index; \
145 MAC_UTIL_FLOW_DB_FLOW_ID_TYPE2ARR_INDEX_SUB_INDEX((_flow_id), (_flow_type), (_index), (_sub_index)); \
146 if (!_index) \
147 { \
148 (_rc) = BCM_ERR_NULL; \
149 break; \
150 } \
151 mac_util_db_flows_list[_index][_sub_index] = (_flow_entry); \
152 } while (0);
153
154
155/**
156 * @brief flow Id starting value that can used by SDN User application.
157 * @details By default the starting flow Id is assumed to be 1.
158 */
159uint32_t mac_util_flow_id_start_val = 1;
160
161/**
162 * @brief flow DB Array
163 * @details This Array is for upstream & downstream flows and can store BAL_ACC_TERM_MAX_FLOWS flows.
164 * This array is indexed by BAL flow Id.
165 *
166 * @note First entry starts at index 1; (0 is not used).
167 *
168 * @note Upstream & Downstream flow types of a pair may use the same Flow Id.Hence there is a sub-array
169 * of each of Flow Id entry. The sub array has upstream flow entry in index 0 and downstream at index 1.
170 * Hence, a flow entry is accessible by the key pair {flowId, flowtype}.
171 * */
172static flow_list_entry *mac_util_db_flows_list[BAL_ACC_TERM_MAX_FLOWS + 1][MAC_UTIL_FLOW_DB_MAX_FLOW_TYPES];
173
174
175/*****************************************************************************/
176/** Flow DB wrapper Functions */
177
178/** @todo in future with a new DB data structure, these wrapper functions would
179 * be migrated to call those DB apis.
180 */
181/*****************************************************************************/
182
183/**
184 * @brief Allocate a new flow
185 *
186 * @return flow_list_entry pointer to a new flow entry
187 */
188flow_list_entry *_mac_util_db_flow_alloc (void)
189{
190 flow_list_entry *p_flow = NULL;
191
192 p_flow = bcmos_calloc(sizeof(flow_list_entry));
193 /* bcmos_calloc already initializes the memory to 0 */
194
195 return p_flow;
196}
197
198/**
199 * @brief Free a flow (free the memory or return it to free pool)
200 *
201 * @param pon_if pon interface id
202 * @param p_entry pointer to a flow entry
203 *
204 * @returns bcmos_errno bcm errno
205 *
206 * @note it checks if the flow being freed is already removed from flow DB
207 */
208bcmos_errno _mac_util_db_flow_free (uint32_t pon_if, flow_list_entry *p_entry)
209{
210 bcmos_errno rc = BCM_ERR_OK;
211
212 if (!IS_VALID_PON_IF(pon_if))
213 {
214 return BCM_ERR_PARM;
215 }
216
217 if (NULL == p_entry)
218 {
219 return BCM_ERR_PARM;
220 }
221
222 /* free the memory */
223 bcmos_free(p_entry);
224
225 return rc;
226}
227
228/**
229 * @brief Add an already allocated flow to flow DB
230 *
231 * @param pon_if pon interface id
232 * @param p_entry pointer to a new flow entry
233 *
234 * @returns bcmos_errno bcm errno
235 *
236 * @todo in proper DB, it should check if the entry is already in the list or not
237 */
238bcmos_errno _mac_util_db_flow_add (uint32_t pon_if, flow_list_entry *p_entry)
239{
240 bcmos_errno rc = BCM_ERR_OK;
241
242 if (!IS_VALID_PON_IF(pon_if))
243 return BCM_ERR_PARM;
244
245 if (!p_entry)
246 return BCM_ERR_PARM;
247
248 MAC_UTIL_FLOW_DB_ENTRY_SET(p_entry->bal_flow_key.flow_id, p_entry->bal_flow_key.flow_type, p_entry, rc);
249
250 return rc;
251}
252
253/**
254 * @brief Remove a flow entry from flow DB
255 *
256 * @param pon_if pon interface id
257 * @param p_entry pointer to a flow entry
258 *
259 * @returns bcmos_errno bcm errno
260 *
261 * @todo this API will be ported to different DB when we have one
262 */
263bcmos_errno _mac_util_db_flow_remove (uint32_t pon_if, flow_list_entry *p_entry)
264{
265 bcmos_errno rc = BCM_ERR_OK;
266
267 if (!IS_VALID_PON_IF(pon_if))
268 return BCM_ERR_PARM;
269
270 if (!p_entry)
271 return BCM_ERR_PARM;
272
273 MAC_UTIL_FLOW_DB_ENTRY_SET(p_entry->bal_flow_key.flow_id, p_entry->bal_flow_key.flow_type, NULL, rc);
274
275 return rc;
276}
277
278/**
279 * @brief Lookup a flow based on a flow id and pon if
280 *
281 * @param pon_if pon interface id
282 * @param p_flow_key pointer to flow key
283 *
284 * @returns flow_list_entry pointer a flow entry in list
285 */
286flow_list_entry *_mac_util_db_flow_get_w_flow_key (uint32_t pon_if, bcmbal_flow_key *p_flow_key)
287{
288 flow_list_entry *p_flow = NULL;
289
290 if (!IS_VALID_PON_IF(pon_if))
291 {
292 return NULL;
293 }
294
295 MAC_UTIL_FLOW_DB_ENTRY_GET(p_flow_key->flow_id, p_flow_key->flow_type, p_flow);
296
297 return p_flow;
298}
299
300/**
301 * @brief get next flow based on flow id and pon_if
302 *
303 * @param pon_if pon interface id
304 * @param p_curr_entry pointer to current flow entry
305 * @param pp_next_entry double pointer to next flow entry
306 *
307 * @returns flow_list_entry pointer to next flow entry in DB
308 */
309flow_list_entry *_mac_util_db_flow_get_next_w_flow_key (uint32_t pon_if, flow_list_entry *p_curr_entry, flow_list_entry **pp_next_entry)
310{
311 flow_list_entry *p_tmp_entry = p_curr_entry;
312
313 if (!IS_VALID_PON_IF(pon_if))
314 {
315 BCM_LOG(ERROR,log_id_mac_util,"Invalid pon_if %d !", pon_if);
316 return NULL;
317 }
318
319 /** @note this while loop is to continue to iterate through the DB until an entry with matching pon If is found */
320 while (1)
321 {
322 if (NULL == p_tmp_entry)
323 {
324 /* get first flow */
325 MAC_UTIL_FLOW_DB_ENTRY_GET_FIRST(p_tmp_entry);
326 if (p_tmp_entry)
327 {
328 MAC_UTIL_FLOW_DB_ENTRY_GET_NEXT(p_tmp_entry, pp_next_entry);
329
330 if (p_tmp_entry && (pon_if == p_tmp_entry->if_id))
331 return p_tmp_entry;
332 }
333 else
334 break; /* at the end of list */
335 }
336 else
337 {
338 if (NULL != *pp_next_entry)
339 {
340 p_tmp_entry = *pp_next_entry;
341 MAC_UTIL_FLOW_DB_ENTRY_GET_NEXT(p_tmp_entry, pp_next_entry);
342
343 if (pon_if == p_tmp_entry->if_id)
344 return p_tmp_entry;
345 }
346 else
347 break; /* at the end of list */
348 }
349 }
350
351 return NULL;
352}
353
354
355/**
356 * @brief get next flow based on sub terminal id
357 *
358 * @param pon_if pon interface id
359 * @param sub_term_id sub term id as the key
360 * @param p_curr_entry pointer to current flow entry
361 * @param pp_next_entry double pointer to next flow entry
362 *
363 * @returns flow_list_entry pointer to next flow entry in DB
364 *
365 */
366flow_list_entry *_mac_util_db_flow_get_next_w_sub_term_id (uint32_t pon_if, uint32_t sub_term_id,
367 flow_list_entry *p_curr_entry, flow_list_entry **pp_next_entry)
368{
369 flow_list_entry *p_tmp_entry = NULL;
370
371 if (!IS_VALID_PON_IF(pon_if))
372 {
373 BCM_LOG(ERROR,log_id_mac_util,"Invalid pon_if %d !", pon_if);
374 return NULL;
375 }
376
377 p_tmp_entry = _mac_util_db_flow_get_next_w_flow_key (pon_if, p_curr_entry, pp_next_entry);
378
379 while (NULL != p_tmp_entry)
380 {
381 if (sub_term_id == p_tmp_entry->sub_term_id)
382 {
383 /* found sub_term match */
384 return p_tmp_entry;
385 }
386 /** @note passing tmp entry here because this is a getnext loop internal to this routine */
387 p_tmp_entry = _mac_util_db_flow_get_next_w_flow_key (pon_if, p_tmp_entry, pp_next_entry);
388 }
389
390 return NULL;
391}
392
393/**
394 * @brief count of flows using a gem port and pon_if
395 *
396 * @param pon_if pon interface id
397 * @param gem_port_id gem port id as the key
398 * @param p_count pointer to U32 to save count of flows using the same gem port
399 *
400 * @returns bcmos_errno bcm errno
401 *
402 */
403bcmos_errno _mac_util_db_flow_count_w_gem (uint32_t pon_if, uint16_t gem_port_id, uint32_t *p_count)
404{
405 uint32_t count = 0;
406 flow_list_entry *p_tmp_entry = NULL;
407 void *p_rsc_mgr_curr_entry = NULL;
408 void *p_rsc_mgr_next_entry = NULL;
409
410 BUG_ON(NULL == p_count);
411
412 if (!IS_VALID_PON_IF(pon_if))
413 {
414 BCM_LOG(ERROR,log_id_mac_util,"Invalid pon_if %d !", pon_if);
415 return BCM_ERR_PARM;
416 }
417
418 p_tmp_entry = _mac_util_db_flow_get_next_w_gem (pon_if, gem_port_id, &p_rsc_mgr_curr_entry, &p_rsc_mgr_next_entry);
419 while (NULL != p_tmp_entry)
420 {
421 count++;
422 p_tmp_entry = _mac_util_db_flow_get_next_w_gem (pon_if, gem_port_id, &p_rsc_mgr_curr_entry, &p_rsc_mgr_next_entry);
423 }
424
425 *p_count = count;
426 return BCM_ERR_OK;
427}
428
429
430/**
431 * @brief get next flow based on gem and pon if
432 *
433 * @param pon_if pon interface id
434 * @param gem_port_id gem port id as the key
435 * @param **pp_rsc_mgr_curr_entry double pointer to current entry in Rsrc Mgr Database
436 * @param **pp_rsc_mgr_next_entry double pointer to next entry in Rsrc Mgr Database
437 *
438 * @returns flow_list_entry pointer to next flow entry in DB
439 *
440 * @note this queries resource mgr DB
441 */
442flow_list_entry *_mac_util_db_flow_get_next_w_gem (uint32_t pon_if, uint16_t gem_port_id,
443 void **pp_rsc_mgr_curr_entry, void **pp_rsc_mgr_next_entry)
444{
445 flow_inst *p_core_flow_entry = NULL;
446 flow_list_entry *p_flow_entry = NULL;
447
448 if (!IS_VALID_PON_IF(pon_if))
449 {
450 BCM_LOG(ERROR,log_id_mac_util,"Invalid pon_if %d !", pon_if);
451 return NULL;
452 }
453
454 p_core_flow_entry = rsc_mgr_gem_get_next_user_data (pon_if, gem_port_id, pp_rsc_mgr_curr_entry, pp_rsc_mgr_next_entry);
455
456 while (NULL != p_core_flow_entry)
457 {
458 p_flow_entry = _mac_util_db_flow_get_w_flow_key(pon_if, &p_core_flow_entry->current_flow_info.key);
459 if (p_flow_entry)
460 {
461 /* found gem match */
462 return p_flow_entry;
463 }
464 p_core_flow_entry = rsc_mgr_gem_get_next_user_data (pon_if, gem_port_id, pp_rsc_mgr_curr_entry, pp_rsc_mgr_next_entry);
465 }
466
467 return NULL;
468}
469
470/**
471 * @brief count of flows using an alloc id and pon if
472 *
473 * @param pon_if pon interface id
474 * @param alloc_id alloc id as the key
475 * @param p_count pointer to U32 that save the count of flows using the same alloc id
476 *
477 * @returns bcmos_errno bcm errno
478 */
479bcmos_errno _mac_util_db_flow_count_w_alloc_id (uint32_t pon_if, uint16_t alloc_id, uint32_t *p_count)
480{
481 uint32_t count = 0;
482 flow_list_entry *p_tmp_entry = NULL;
483 void *p_rsc_mgr_curr_entry = NULL;
484 void *p_rsc_mgr_next_entry = NULL;
485
486 BUG_ON( NULL == p_count);
487
488 if (!IS_VALID_PON_IF(pon_if))
489 {
490 BCM_LOG(ERROR,log_id_mac_util,"Invalid pon_if %d !", pon_if);
491 return BCM_ERR_PARM;
492 }
493
494 p_tmp_entry = _mac_util_db_flow_get_next_w_alloc_id (pon_if, alloc_id, &p_rsc_mgr_curr_entry, &p_rsc_mgr_next_entry);
495 while (NULL != p_tmp_entry)
496 {
497 count++;
498 p_tmp_entry = _mac_util_db_flow_get_next_w_alloc_id (pon_if, alloc_id, &p_rsc_mgr_curr_entry, &p_rsc_mgr_next_entry);
499 }
500
501 *p_count = count;
502 return BCM_ERR_OK;
503}
504
505/**
506 * @brief get next flow based on upstream alloc id and pon if
507 *
508 * @param pon_if pon interface id
509 * @param alloc_id alloc id as the key
510 * @param **pp_rsc_mgr_curr_entry double pointer to current entry in Rsrc Mgr Database
511 * @param **pp_rsc_mgr_next_entry double pointer to next entry in Rsrc Mgr Database
512 *
513 * @returns flow_list_entry pointer to next flow entry in DB
514 *
515 * @note this queries resource mgr DB
516 */
517flow_list_entry *_mac_util_db_flow_get_next_w_alloc_id (uint32_t pon_if, uint16_t alloc_id,
518 void **pp_rsc_mgr_curr_entry, void **pp_rsc_mgr_next_entry)
519{
520 flow_inst *p_core_flow_entry = NULL;
521 flow_list_entry *p_flow_entry = NULL;
522
523 if (!IS_VALID_PON_IF(pon_if))
524 {
525 BCM_LOG(ERROR,log_id_mac_util,"Invalid pon_if %d !", pon_if);
526 return NULL;
527 }
528
529 p_core_flow_entry = rsc_mgr_alloc_id_get_next_user_data(pon_if, alloc_id, pp_rsc_mgr_curr_entry, pp_rsc_mgr_next_entry);
530
531 while (NULL != p_core_flow_entry)
532 {
533 p_flow_entry = _mac_util_db_flow_get_w_flow_key(pon_if, &p_core_flow_entry->current_flow_info.key);
534 if (p_flow_entry)
535 {
536 /* found alloc id match */
537 return p_flow_entry;
538 }
539 p_core_flow_entry = rsc_mgr_alloc_id_get_next_user_data(pon_if, alloc_id, pp_rsc_mgr_curr_entry, pp_rsc_mgr_next_entry);
540 }
541
542 return NULL;
543}
544
545/*@}*/