blob: f7ee71a4666d163e24e3c49725a36619f995e68c [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 flow_fsm.c
34 * @brief Code to support the BAL flow FSM
35 *
36 * @addtogroup flow
37 *
38 */
39
40/*@{*/
41
42#include <bcmos_system.h>
43#include <flow_fsm.h>
44#include <tm_sched_fsm.h>
45#include <tm_queue_fsm.h>
46
47
48#include <bal_msg.h>
49#include <bal_osmsg.h>
50#include "bal_worker.h"
51#include "bal_mac_util.h"
52#include "bal_switch_util.h"
53#include "rsc_mgr.h"
54
55#include <bal_objs.h>
56#include <fsm_common.h>
57#include <bal_switch_flow.h>
58
59#ifdef ENABLE_LOG
60#include <bcm_dev_log.h>
61
62 /*
63 * @brief The logging device id for flow
64 */
65static dev_log_id log_id_flow;
66#endif
67
68/* local function declarations */
69static bcmos_errno flow_fsm_admin_up_start(flow_inst *p_flow_inst,
70 void *msg,
71 flow_fsm_event *p_event);
72
73static bcmos_errno flow_fsm_admin_up_error(flow_inst *p_flow_inst,
74 void *msg,
75 flow_fsm_event *p_event);
76
77static bcmos_errno flow_fsm_admin_dn_start(flow_inst *p_flow_inst,
78 void *msg,
79 flow_fsm_event *p_event);
80
81static bcmos_errno flow_fsm_admin_dn_ok(flow_inst *p_flow_inst,
82 void *msg,
83 flow_fsm_event *p_event);
84
85static bcmos_errno flow_fsm_admin_dn_error(flow_inst *p_flow_inst,
86 void *msg,
87 flow_fsm_event *p_event);
88
89static bcmos_errno flow_fsm_ignore_util_msg(flow_inst *p_flow_inst,
90 void *msg,
91 flow_fsm_event *p_event);
92
93static bcmos_errno flow_fsm_removing_process_util_msg(flow_inst *p_flow_inst,
94 void *msg,
95 flow_fsm_event *p_event);
96
97static bcmos_errno flow_fsm_removing_process_util_auto_msg(flow_inst *p_flow_inst,
98 void *msg,
99 flow_fsm_event *p_event);
100
101static bcmos_errno flow_fsm_null_process_util_auto_msg(flow_inst *p_flow_inst,
102 void *msg,
103 flow_fsm_event *p_event);
104
105static bcmos_errno flow_fsm_process_util_msg(flow_inst *p_flow_inst,
106 void *msg,
107 flow_fsm_event *p_event);
108
109static bcmos_errno flow_fsm_process_util_auto_msg(flow_inst *p_flow_inst,
110 void *msg,
111 flow_fsm_event *p_event);
112
113static bcmos_errno flow_fsm_clear_start(flow_inst *p_flow_inst,
114 void *msg,
115 flow_fsm_event *p_event);
116
117
118static bcmos_errno flow_fsm_state_err(flow_inst *p_flow_inst,
119 void *msg,
120 flow_fsm_event *p_event);
121
122static bcmos_errno flow_fsm_exec(flow_inst *p_flow_inst, flow_fsm_event *p_event);
123
124static flow_inst *flow_inst_get(bcmbal_flow_key *key, flow_flag search_flag, bcmos_bool *is_new_flow);
125
126
127#ifdef FREE_FLOW_BY_KEY_SUPPORTED
128static bcmos_errno flow_free_by_key(bcmbal_flow_key *key);
129#endif
130static bcmos_errno flow_free_by_entry(flow_inst *p_entry);
131
132static bcmos_errno flow_tm_get(bcmbal_flow_cfg *p_flow_info, tm_sched_inst **p_tm_sched_inst);
133static bcmos_errno flow_queue_validate(bcmbal_flow_cfg *p_flow_cfg, tm_queue_inst **p_tm_queue_inst);
134
135
136/*
137 * @brief The Global flow fsm context data structure
138 */
139static flow_fsm_ctx g_flow_fsm_flow_list_ctx;
140
141/*
142 * Macros for flow ctx access
143 */
144#define FLOW_FSM_FLOW_LIST_CTX (g_flow_fsm_flow_list_ctx)
145#define FLOW_FSM_FLOW_LIST_CTX_PTR (&g_flow_fsm_flow_list_ctx)
146
147/*
148 * @brief The definition of a flow FSM state processing function
149 */
150typedef bcmos_errno (* flow_fsm_state_processor)(flow_inst *, void *, flow_fsm_event *);
151
152/*
153 * @brief The Flow FSM state processing array
154 */
155static flow_fsm_state_processor flow_states[FLOW_FSM_STATE__NUM_OF][FLOW_FSM_EVENT_TYPE__NUM_OF] =
156{
157
158 [FLOW_FSM_STATE_NULL] =
159 {
160 /*
161 * Next state: CONFIGURING
162 */
163 [FLOW_FSM_EVENT_TYPE_ADMIN_UP] = flow_fsm_admin_up_start,
164
165 /*
166 * Next state: NULL
167 */
168 [FLOW_FSM_EVENT_TYPE_ADMIN_DN] = flow_fsm_admin_dn_ok,
169
170 /*
171 * Next state: NULL
172 */
173 [FLOW_FSM_EVENT_TYPE_UTIL_MSG] = flow_fsm_ignore_util_msg,
174
175 /*
176 * Next state: NULL
177 */
178 [FLOW_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = flow_fsm_null_process_util_auto_msg,
179 },
180 [FLOW_FSM_STATE_CONFIGURING] =
181 {
182 /*
183 * Next state: CONFIGURING
184 */
185 [FLOW_FSM_EVENT_TYPE_ADMIN_UP] = flow_fsm_admin_up_start,
186
187 /*
188 * Next state: CONFIGURING
189 */
190 [FLOW_FSM_EVENT_TYPE_ADMIN_DN] = flow_fsm_admin_dn_start,
191
192 /*
193 * Next state: CONFIGURING | CONFIGURED
194 */
195 [FLOW_FSM_EVENT_TYPE_UTIL_MSG] = flow_fsm_process_util_msg,
196
197 /*
198 * Next state: REMOVING
199 */
200 [FLOW_FSM_EVENT_TYPE_REMOVE] = flow_fsm_clear_start,
201
202 /*
203 * Next state: CONFIGURING
204 */
205 [FLOW_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = flow_fsm_process_util_auto_msg,
206
207 },
208
209 [FLOW_FSM_STATE_CONFIGURED] =
210 {
211 /*
212 * Next state: CONFIGURED
213 */
214 [FLOW_FSM_EVENT_TYPE_ADMIN_UP] = flow_fsm_admin_up_start,
215
216 /*
217 * Next state: CONFIGURING
218 */
219 [FLOW_FSM_EVENT_TYPE_ADMIN_DN] = flow_fsm_admin_dn_start,
220
221 /*
222 * Next state: REMOVING
223 */
224 [FLOW_FSM_EVENT_TYPE_REMOVE] = flow_fsm_clear_start,
225
226 /*
227 * Next state: CONFIGURING
228 */
229 [FLOW_FSM_EVENT_TYPE_UTIL_MSG] = flow_fsm_process_util_msg,
230
231 /*
232 * Next state: CONFIGURED
233 */
234 [FLOW_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = flow_fsm_process_util_auto_msg,
235
236 },
237
238 [FLOW_FSM_STATE_REMOVING] =
239 {
240 /*
241 * Next state: REMOVING
242 */
243 [FLOW_FSM_EVENT_TYPE_ADMIN_UP] = flow_fsm_admin_up_error,
244
245 /*
246 * Next state: REMOVING
247 */
248 [FLOW_FSM_EVENT_TYPE_ADMIN_DN] = flow_fsm_admin_dn_error,
249
250 /*
251 * Next state: REMOVING | NULL
252 */
253 [FLOW_FSM_EVENT_TYPE_UTIL_MSG] = flow_fsm_removing_process_util_msg,
254
255 /*
256 * Next state: REMOVING
257 */
258 [FLOW_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = flow_fsm_removing_process_util_auto_msg,
259 },
260
261};
262
263static char *state_name_str[] =
264{
265 "FLOW_FSM_STATE_NULL",
266 "FLOW_FSM_STATE_CONFIGURING",
267 "FLOW_FSM_STATE_CONFIGURED",
268 "FLOW_FSM_STATE_REMOVING",
269};
270
271/* Ensure that the name array size matches the associated enum */
272BAL_STATIC_ASSERT (FLOW_FSM_STATE__LAST == (sizeof (state_name_str) / sizeof (char *)), flow_fsm_state);
273
274static char *flow_state_name_get(flow_fsm_state state)
275{
276 if(state < FLOW_FSM_STATE__LAST)
277 {
278 return state_name_str[state];
279 }
280 else
281 {
282 return "FLOW_UNKNOWN";
283 }
284}
285
286static char *event_name_str[] =
287{
288 "FLOW_FSM_ADMIN_UP_EVENT",
289 "FLOW_FSM_ADMIN_DN_EVENT",
290 "FLOW_FSM_REMOVE_EVENT",
291 "FLOW_FSM_UTIL_MSG_EVENT",
292 "FLOW_FSM_UTIL_AUTO_MSG_EVENT",
293};
294
295/* Ensure that the name array size matches the associated enum */
296BAL_STATIC_ASSERT (FLOW_FSM_EVENT_TYPE__LAST == (sizeof (event_name_str) / sizeof (char *)), flow_fsm_event_type);
297
298static char *flow_event_name_get(flow_fsm_event_type event)
299{
300 if(event < FLOW_FSM_EVENT_TYPE__LAST)
301 {
302 return event_name_str[event];
303 }
304 else
305 {
306 return "FLOW_EVT_UNKNOWN";
307 }
308}
309
310/*****************************************************************************/
311/**
312 * @brief A function to initialize the current_flow_info object of the
313 * supplied entry.
314 *
315 * @param p_entry A pointer to the entry to be initialized
316 *
317 *
318 * @returns void
319 *****************************************************************************/
320static void flow_inst_entry_obj_init(flow_inst *p_entry)
321{
322 /* The actual key content is irrelevant for free flows */
323 bcmbal_flow_key key = { .flow_id = 0, .flow_type = BCMBAL_FLOW_TYPE_DOWNSTREAM };
324
325 BCMBAL_CFG_INIT(&p_entry->current_flow_info,
326 flow,
327 key);
328
329 BCMBAL_CFG_PROP_SET(&p_entry->current_flow_info,
330 flow,
331 admin_state,
332 BCMBAL_STATE_DOWN);
333
334 BCMBAL_CFG_PROP_SET(&p_entry->current_flow_info,
335 flow,
336 oper_status,
337 BCMBAL_STATUS_DOWN);
338
339 BCMBAL_OBJ_IN_PROGRESS_SET(&(p_entry->current_flow_info), BCMOS_FALSE);
340
341}
342
343/*****************************************************************************/
344/**
345 * @brief A function to initialize the Flow FSM infrastructure.
346 *
347 * NOTE: This is called once on startup and NOT for each FSM instance.
348 *
349 * @returns bcmos_errno
350 *****************************************************************************/
351bcmos_errno flow_fsm_init(void)
352{
353 int ii;
354 flow_inst *new_entry;
355 bcmos_errno ret = BCM_ERR_OK;
356
357#ifdef ENABLE_LOG
358 log_id_flow = bcm_dev_log_id_register("FLOW", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
359 BUG_ON(log_id_flow == DEV_LOG_INVALID_ID);
360#endif
361
362 /* Initialize all of the flow queues */
363 TAILQ_INIT(&FLOW_FSM_FLOW_LIST_CTX_PTR->free_flow_list);
364 TAILQ_INIT(&FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list);
365
366 /* Populate the free list with it's initial set of flows
367 */
368 for(ii=0; ii<FLOW_ALLOCATION_BLOCK_SIZE; ii++)
369 {
370
371 new_entry = bcmos_calloc(sizeof(flow_inst));
372
373 if (NULL == new_entry)
374 {
375 BCM_LOG(FATAL, log_id_flow, "Failed to initialize the flow free list - FATAL\n");
376 ret = BCM_ERR_NOMEM;
377 break;
378 }
379
380 flow_free_by_entry(new_entry);
381 }
382
383 return ret;
384}
385
386/*****************************************************************************/
387/**
388 * @brief A function to un-initialize the Flow FSM infrastructure.
389 *
390 * NOTE: This is called once on shutdown and NOT for each FSM instance.
391 *
392 * @returns bcmos_errno
393 *****************************************************************************/
394bcmos_errno flow_fsm_finish(void)
395{
396
397 flow_inst *current_entry, *p_temp_entry;
398
399 /* Free all the entries on the active list */
400 TAILQ_FOREACH_SAFE(current_entry,
401 &FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list,
402 flow_inst_next,
403 p_temp_entry)
404 {
405 /* Remove it from the active list */
406 TAILQ_REMOVE(&FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list, current_entry, flow_inst_next);
407
408 bcmos_free(current_entry);
409
410 }
411
412 /* Free all the entries on the free list */
413 TAILQ_FOREACH_SAFE(current_entry,
414 &FLOW_FSM_FLOW_LIST_CTX_PTR->free_flow_list,
415 flow_inst_next,
416 p_temp_entry)
417 {
418 /* Remove it from the active list */
419 TAILQ_REMOVE(&FLOW_FSM_FLOW_LIST_CTX_PTR->free_flow_list, current_entry, flow_inst_next);
420
421 bcmos_free(current_entry);
422 }
423
424 return BCM_ERR_OK;
425}
426
427/*****************************************************************************/
428/**
429 * @brief The Flow FSM state processing executive function
430 *
431 * @param p_flow_inst Pointer to a flow instance
432 * @param p_event Pointer to a flow event structure
433 *
434 * @returns bcmos_errno
435 *****************************************************************************/
436static bcmos_errno flow_fsm_exec(flow_inst *p_flow_inst, flow_fsm_event *p_event)
437{
438 bcmos_errno ret = BCM_ERR_OK;
439 flow_fsm_state pre_state;
440 flow_fsm_state_processor flow_state_processor;
441
442 /* Parameter checks */
443 BUG_ON(NULL == p_flow_inst);
444 BUG_ON(NULL == p_event);
445
446 /* Record the present state for debug printing
447 */
448 pre_state = p_flow_inst->fsm_state;
449
450 /*
451 * Get the state processing function
452 */
453 flow_state_processor = flow_states[p_flow_inst->fsm_state][p_event->event_type];
454
455 /*
456 * If there's a state processing function for this event and state, execute it.
457 * Otherwise, process a generic error.
458 */
459 if (flow_state_processor)
460 {
461 ret = flow_state_processor(p_flow_inst, p_event->msg, p_event);
462 } else
463 {
464 flow_fsm_state_err(p_flow_inst, p_event->msg, p_event);
465 }
466
467 if(BCM_ERR_OK != ret)
468 {
469 BCM_LOG(ERROR, log_id_flow, "*** Error detected during state processing\n");
470 p_flow_inst->fsm_state = pre_state;
471 }
472
473 BCM_LOG(DEBUG, log_id_flow, "*** Event %s, State: %s --> %s\n\n",
474 flow_event_name_get(p_event->event_type),
475 flow_state_name_get(pre_state),
476 flow_state_name_get(p_flow_inst->fsm_state));
477
478 return ret;
479}
480
481
482
483
484/*****************************************************************************/
485/**
486 * @brief The Flow FSM state processing for a flow admin-up command received
487 * from the BAL Public API when the specified flow instance is in the
488 * admin-down state (i.e. when the flow instance FSM is in the NULL state).
489 *
490 * @param p_flow_inst Pointer to an flow instance
491 * @param msg Pointer to a BAL message received from the BAL Public API
492 * @param p_event Pointer to an flow event structure
493 *
494 * @returns bcmos_errno
495 *****************************************************************************/
496static bcmos_errno flow_fsm_admin_up_start(flow_inst *p_flow_inst,
497 void *msg,
498 flow_fsm_event *p_event)
499{
500
501 bcmos_errno ret = BCM_ERR_OK;
502 bcmos_bool is_ds_flow_to_host, is_ds_n_to_1;
503
504
505 BCM_LOG(INFO, log_id_flow, "Got admin UP request from BAL API - bringing up FLOW\n");
506
507 do
508 {
509 /* change Flow state to CONFIGURING */
510 p_flow_inst->fsm_state = FLOW_FSM_STATE_CONFIGURING;
511
512 /*– Core calls Switch Utils to add applicable CMDs */
513 if(BCM_ERR_OK != (ret = sw_util_flow_set(p_flow_inst, BAL_UTIL_OPER_FLOW_ADD)))
514 {
515 BCM_LOG(ERROR, log_id_flow, "error %s detected by switch util while adding flow\n", bcmos_strerror(ret));
516 break;
517 }
518
519 /*– Core calls Mac Utils add applicable CMDs */
520 if(BCM_ERR_OK != (ret = mac_util_flow_set(p_flow_inst, BAL_UTIL_OPER_FLOW_ADD)))
521 {
522 BCM_LOG(ERROR, log_id_flow, "error %s detected by mac util\n", bcmos_strerror(ret));
523
524 /* Remove the (just added) flow from the switch otherwise the switch utils
525 * will remember it and complain when this flow is added later. There's not
526 * much we can do about it if removing this flow fails.
527 */
528 if(BCM_ERR_OK != sw_util_flow_set(p_flow_inst, BAL_UTIL_OPER_FLOW_CLEAR))
529 {
530 BCM_LOG(ERROR, log_id_flow,
531 "error detected by switch util while removing flow\n");
532 }
533
534 break;
535 }
536
537 /* The hardware has properly accepted the object info, so the request object becomes
538 * the current state.
539 */
540 bcmbal_flow_object_overlay_w_src_priority(&p_flow_inst->current_flow_info,
541 &p_flow_inst->api_req_flow_info);
542
543 is_ds_flow_to_host = (BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_inst->api_req_flow_info.key.flow_type &&
544 (BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(&p_flow_inst->api_req_flow_info, flow, action) &&
545 (p_flow_inst->api_req_flow_info.data.action.cmds_bitmask &
546 BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST)));
547
548 is_ds_n_to_1 = ((BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_inst->api_req_flow_info.key.flow_type) &&
549 (BCMBAL_CFG_PROP_IS_SET(&p_flow_inst->api_req_flow_info, flow, group_id) ));
550
551
552 /* Add the svc_port_id record to the sub_term record for upstream flows,
553 * or for downstream flows that are not destined to the host
554 */
555 if(BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_inst->api_req_flow_info.key.flow_type ||
556 (BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_inst->api_req_flow_info.key.flow_type &&
557 !(is_ds_flow_to_host) && !(is_ds_n_to_1)))
558
559 {
560 bcmbal_sub_term_svc_port_id_list_entry_add(p_flow_inst->p_sub_term_inst,
561 p_flow_inst->api_req_flow_info.data.svc_port_id);
562 }
563
564 /* Add the agg_port_id to the sub_term record (only for upstream flows) */
565 if(BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_inst->api_req_flow_info.key.flow_type)
566 {
567 bcmbal_sub_term_agg_port_id_list_entry_add(p_flow_inst->p_sub_term_inst,
568 p_flow_inst->api_req_flow_info.data.agg_port_id);
569 }
570
571 BCMBAL_OBJ_IN_PROGRESS_SET(&(p_flow_inst->current_flow_info), BCMOS_TRUE);
572
573 }while(0);
574
575 /* If there were errors during processing, then report the error to the API and free the flow */
576 if(BCM_ERR_OK != ret)
577 {
578 mgmt_msg_send_balapi_ind(ret,
579 msg,
580 log_id_flow);
581
582 flow_free_by_entry(p_flow_inst);
583 }
584
585 return ret;
586
587}
588
589/*****************************************************************************/
590/**
591 * @brief The Flow FSM state processing for a flow admin-up command received
592 * from the BAL Public API when the specified flow FSM is already
593 * in the REMOVING state.
594 *
595 * @param p_flow_inst Pointer to a flow instance
596 * @param msg Pointer to a BAL message received from the BAL Public API
597 * @param p_event Pointer to an flow event structure
598 *
599 * @returns bcmos_errno
600 *****************************************************************************/
601static bcmos_errno flow_fsm_admin_up_error(flow_inst *p_flow_inst,
602 void *msg,
603 flow_fsm_event *p_event)
604{
605 bcmos_errno ret = BCM_ERR_STATE;
606
607 BCM_LOG(DEBUG, log_id_flow,
608 "Received an admin UP request from BAL API"
609 " - returning ERROR to the API - no further function\n");
610
611 return ret;
612}
613
614/*****************************************************************************/
615/**
616 * @brief The Flow FSM state processing for a flow admin-down command
617 * received from the BAL Public API when the specified flow is
618 * admin-up (i.e when the specified flow instance FSM is in the
619 * CONFIGURED state).
620 *
621 * @param p_flow_inst Pointer to a flow instance
622 * @param msg Pointer to a BAL message received from the BAL Public API
623 * @param p_event Pointer to a flow event structure
624 *
625 * @returns bcmos_errno
626 *****************************************************************************/
627static bcmos_errno flow_fsm_admin_dn_start(flow_inst *p_flow_inst,
628 void *msg,
629 flow_fsm_event *p_event)
630{
631 bcmos_errno ret = BCM_ERR_OK;
632
633 BCM_LOG(INFO, log_id_flow,
634 "Got admin DOWN request from BAL API - bringing down FLOW\n");
635
636 /* change Flow state to CONFIGURING */
637 p_flow_inst->fsm_state = FLOW_FSM_STATE_CONFIGURING;
638
639 do
640 {
641 /*– Core calls Switch Utils to remove applicable CMDs */
642 if(BCM_ERR_OK != (ret = sw_util_flow_set(p_flow_inst, BAL_UTIL_OPER_FLOW_REMOVE)))
643 {
644 BCM_LOG(ERROR, log_id_flow, "error %s detected by switch util\n", bcmos_strerror(ret));
645 break;
646 }
647
648 /*– Core calls Mac Utils remove applicable CMDs */
649 if(BCM_ERR_OK != (ret = mac_util_flow_set(p_flow_inst, BAL_UTIL_OPER_FLOW_REMOVE)))
650 {
651 BCM_LOG(ERROR, log_id_flow, "error %s detected by mac util\n", bcmos_strerror(ret));
652 break;
653 }
654
655 /* The hardware has properly accepted the object info but we do
656 * not overwrite the current flow data as there is nothing in the request
657 * that is relevant besides the admin_state
658 */
659 BCMBAL_OBJ_IN_PROGRESS_SET(&(p_flow_inst->current_flow_info), BCMOS_TRUE);
660
661 }while(0);
662 /* Report any error found to the API immediately */
663 if(BCM_ERR_OK != ret)
664 {
665 mgmt_msg_send_balapi_ind(ret,
666 msg,
667 log_id_flow);
668 }
669
670 return ret;
671}
672
673/*****************************************************************************/
674/**
675 * @brief The Flow FSM state processing for a flow clear command
676 * received from the BAL Public API.
677 *
678 * @param p_flow_inst Pointer to a flow instance
679 * @param msg Pointer to a BAL message received from the BAL Public API
680 * @param p_event Pointer to a flow event structure
681 *
682 * @returns bcmos_errno
683 *****************************************************************************/
684static bcmos_errno flow_fsm_clear_start(flow_inst *p_flow_inst,
685 void *msg,
686 flow_fsm_event *p_event)
687{
688 bcmos_errno ret = BCM_ERR_OK;
689 tm_sched_inst *p_tm_sched_inst;
690 uint32_t alloc_ref_count;
691 bcmos_bool b_flow_is_destined_to_host;
692 tm_queue_inst *p_tm_queue_inst = NULL;
693
694 BCM_LOG(INFO, log_id_flow,
695 "Got CLEAR request from BAL API - removing FLOW\n");
696
697 /* change Flow state to REMOVING */
698 p_flow_inst->fsm_state = FLOW_FSM_STATE_REMOVING;
699
700
701 b_flow_is_destined_to_host = ((BCMBAL_CFG_PROP_IS_SET(&(p_flow_inst->api_req_flow_info), flow, action) &&
702 (p_flow_inst->api_req_flow_info.data.action.cmds_bitmask &
703 BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST)) ? BCMOS_TRUE : BCMOS_FALSE);
704 do
705 {
706 /*Core calls Switch Utils to clear applicable CMDs */
707 if(BCM_ERR_OK != (ret = sw_util_flow_set(p_flow_inst, BAL_UTIL_OPER_FLOW_CLEAR)))
708 {
709 BCM_LOG(ERROR, log_id_flow, "error %s detected by switch util\n", bcmos_strerror(ret));
710 break;
711 }
712
713 /*Core calls Mac Utils clear applicable CMDs */
714 if(BCM_ERR_OK != (ret = mac_util_flow_set(p_flow_inst, BAL_UTIL_OPER_FLOW_CLEAR)))
715 {
716 /* if entry does not exist for a clear, that is fine, since anyway that would have been the end goal */
717 if (BCM_ERR_NOENT != ret)
718 {
719 BCM_LOG(ERROR, log_id_flow, "error %s detected by mac util\n", bcmos_strerror(ret));
720 break;
721 }
722 }
723
724 if(BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_inst->api_req_flow_info.key.flow_type)
725 {
726 /*handle the alloc id and alloc - tm sched*/
727 if(BCM_ERR_OK != rsc_mgr_alloc_id_free(p_flow_inst->api_req_flow_info.data.access_int_id,
728 p_flow_inst->api_req_flow_info.data.agg_port_id, p_flow_inst))
729 {
730 BCM_LOG(ERROR, log_id_flow,
731 " error encountered during release of flow resources (agg_port_id: %d, intf_id:%d\n",
732 p_flow_inst->api_req_flow_info.data.access_int_id,
733 p_flow_inst->api_req_flow_info.data.agg_port_id);
734 }
735 /*check if tm sched should be removed - ref count = 1 and tm sched is auto created*/
736 if(BCM_ERR_OK != (ret = flow_tm_get(&(p_flow_inst->api_req_flow_info), &p_tm_sched_inst)))
737 {
738
739 BCM_LOG(ERROR, log_id_flow,
740 " could not find tm sched for agg_port_id: %d, intf_id:%d\n",
741 p_flow_inst->api_req_flow_info.data.access_int_id,
742 p_flow_inst->api_req_flow_info.data.agg_port_id);
743 break;
744 }
745 ret = rsc_mgr_alloc_id_get_ref_count(p_flow_inst->api_req_flow_info.data.access_int_id,p_flow_inst->api_req_flow_info.data.agg_port_id, &alloc_ref_count);
746
747 if(BCM_ERR_OK == ret
748 && BCMBAL_TM_CREATION_MODE_AUTO == p_tm_sched_inst->req_tm_sched_info.data.creation_mode
749 && 1 == alloc_ref_count)
750 {
751 ret = bcmbal_tm_sched_fsm_active_destroy(p_tm_sched_inst);
752 }
753 }
754
755 /*if the flow is not a cpu flow (to host), should handle it sched/queue setting*/
756 if(!b_flow_is_destined_to_host)
757 {
758 /*remove the flow from the the tm queue list*/
759 /*find tm queue instance*/
760 ret = flow_queue_validate(&p_flow_inst->api_req_flow_info, &p_tm_queue_inst);
761
762 if (ret != BCM_ERR_OK)
763 {
764 ret = BCM_ERR_NOENT;
765 break;
766 }
767
768 ret = bcmbal_tm_queue_use_set(p_tm_queue_inst, BCMOS_FALSE);
769 if (ret != BCM_ERR_OK)
770 {
771 ret = BCM_ERR_INTERNAL;
772 break;
773 }
774 }
775
776 /* The hardware has properly accepted the object info, so the request object becomes
777 * the current state, except for the oper_status.
778 */
779 bcmbal_flow_object_overlay_w_src_priority(&p_flow_inst->current_flow_info,
780 &p_flow_inst->api_req_flow_info);
781
782 BCMBAL_OBJ_IN_PROGRESS_SET(&(p_flow_inst->current_flow_info), BCMOS_TRUE);
783
784 }while(0);
785
786 /* Report any error found to the API immediately */
787 if(BCM_ERR_OK != ret)
788 {
789 mgmt_msg_send_balapi_ind(ret,
790 msg,
791 log_id_flow);
792 }
793
794 return ret;
795
796}
797
798
799/*****************************************************************************/
800/**
801 * @brief The Flow FSM state processing for a flow admin-down command
802 * from the BAL Public API when the specified flow is already
803 * admin-down.
804 *
805 * @param p_flow_inst Pointer to a flow instance
806 * @param msg Pointer to a BAL message received from the BAL Public API
807 * @param p_event Pointer to an flow event structure
808 *
809 * @returns bcmos_errno
810 *****************************************************************************/
811static bcmos_errno flow_fsm_admin_dn_ok(flow_inst *p_flow_inst,
812 void *msg,
813 flow_fsm_event *p_event)
814{
815 bcmos_errno ret = BCM_ERR_OK;
816
817 BCM_LOG(DEBUG, log_id_flow,
818 "Received an admin DOWN request from BAL API"
819 " - returning OK to the API - no further function\n");
820
821 mgmt_msg_send_balapi_ind(ret,
822 msg,
823 log_id_flow);
824 return ret;
825}
826
827/*****************************************************************************/
828/**
829 * @brief The Flow FSM state processing for a flow admin-down command
830 * received from the BAL Public API when the specified flow FSM
831 * is in the CONFIGURING state.
832 *
833 * @param p_flow_inst Pointer to a flow instance
834 * @param msg Pointer to a BAL message received from the BAL Public API
835 * @param p_event Pointer to a flow event structure
836 *
837 * @returns bcmos_errno
838 *****************************************************************************/
839static bcmos_errno flow_fsm_admin_dn_error(flow_inst *p_flow_inst,
840 void *msg,
841 flow_fsm_event *p_event)
842{
843 bcmos_errno ret = BCM_ERR_STATE;
844
845 BCM_LOG(DEBUG, log_id_flow,
846 "Received an admin DOWN request from BAL API"
847 " - returning ERROR to the API - no further function\n");
848
849 return ret;
850}
851
852/*****************************************************************************/
853/**
854 * @brief The Flow FSM state processing function to ignore a received message.
855 *
856 * @param p_flow_inst Pointer to an flow instance
857 * @param msg Pointer to a BAL message received from the BAL utils
858 * @param p_event Pointer to an flow event structure
859 *
860 * @returns bcmos_errno
861 *****************************************************************************/
862static bcmos_errno flow_fsm_ignore_util_msg(flow_inst *p_flow_inst,
863 void *msg,
864 flow_fsm_event *p_event)
865{
866 bcmos_errno ret = BCM_ERR_OK;
867
868 BCM_LOG(DEBUG, log_id_flow, "Ignoring message from BAL utils\n");
869 return ret;
870}
871
872/*****************************************************************************/
873/**
874 * @brief The Flow FSM state processing function to process an AUTO IND
875 * message from one of the BAL apps.
876 *
877 * @param p_flow_inst Pointer to a flow instance
878 * @param msg Pointer to a BAL message received from one of
879 * the BAL apps.
880 * @param p_event Pointer to a flow event structure
881 *
882 * @returns bcmos_errno
883 *****************************************************************************/
884static bcmos_errno flow_fsm_null_process_util_auto_msg(flow_inst *p_flow_inst,
885 void *msg,
886 flow_fsm_event *p_event)
887{
888 bcmos_errno ret = BCM_ERR_OK;
889
890 /* Parameter checks */
891 BUG_ON(NULL == p_flow_inst);
892 BUG_ON(NULL == msg);
893 BUG_ON(NULL == p_event);
894
895 BCM_LOG(DEBUG, log_id_flow, "Received an AUTO IND in the NULL state\n");
896
897 return ret;
898}
899
900/*****************************************************************************/
901/**
902 * @brief The Flow FSM state processing function to process a message from
903 * one of the BAL apps received when the specified flow instance FSM
904 * is in the CONFIGURING state.
905 *
906 * @param p_flow_inst Pointer to a flow instance
907 * @param msg Pointer to a BAL message received from one of
908 * the BAL apps.
909 * @param p_event Pointer to an access terminal event structure
910 *
911 * @returns bcmos_errno
912 *****************************************************************************/
913static bcmos_errno flow_fsm_process_util_msg(flow_inst *p_flow_inst,
914 void *msg,
915 flow_fsm_event *p_event)
916{
917 bcmos_errno ret;
918 bal_util_msg_ind *ind_msg;
919
920 /* Parameter checks */
921 BUG_ON(NULL == p_flow_inst);
922 BUG_ON(NULL == msg);
923 BUG_ON(NULL == p_event);
924
925 ind_msg = (bal_util_msg_ind *)msg;
926
927 /*
928 * NOTE: AUTO_IND messages are not processed in this function,
929 * so there is no need to consider them in this logic.
930 */
931
932 BCM_LOG(DEBUG, log_id_flow,
933 " Received an IND message from BAL UTIL (%s) during %s state\n",
934 subsystem_str[bcmbal_sender_get(msg)],flow_state_name_get(p_flow_inst->fsm_state));
935
936 BCM_LOG(DEBUG, log_id_flow,
937 "%s, thread %s, module %d\n", __FUNCTION__, bcmos_task_current()->name, bcmos_module_current());
938
939 /* Handle indication */
940 ret = ind_msg->status;
941
942 /* Reflect the execution status in the object being returned in the indication
943 */
944 if(BCM_ERR_OK == ret)
945 {
946 p_flow_inst->current_flow_info.data.oper_status =
947 p_flow_inst->api_req_flow_info.data.oper_status;
948
949 /*
950 * The flow has been successfully configured
951 */
952 p_flow_inst->fsm_state = FLOW_FSM_STATE_CONFIGURED;
953 }
954 else
955 {
956 /* Error */
957 BCM_LOG(ERROR, log_id_flow, "Flow %d: Failed in state %s. Error %s\n",
958 p_flow_inst->api_req_flow_info.key.flow_id,
959 flow_state_name_get(p_flow_inst->fsm_state),
960 bcmos_strerror(ret));
961 }
962
963 BCMBAL_OBJ_IN_PROGRESS_SET(&(p_flow_inst->current_flow_info), BCMOS_FALSE);
964 p_flow_inst->current_flow_info.hdr.hdr.status = ret;
965
966 /*
967 * Send the indication back to the BAL public API here
968 */
969 mgmt_msg_send_balapi_ind(ret,
970 &p_flow_inst->current_flow_info.hdr,
971 log_id_flow);
972
973 return ret;
974}
975
976/*****************************************************************************/
977/**
978 * @brief The Flow FSM state processing function to process a message from
979 * one of the BAL apps received
980 *
981 * @param p_flow_inst Pointer to a flow instance
982 * @param msg Pointer to a BAL message received from one of
983 * the BAL apps.
984 * @param p_event Pointer to an access terminal event structure
985 *
986 * @returns bcmos_errno
987 *****************************************************************************/
988static bcmos_errno flow_fsm_process_util_auto_msg(flow_inst *p_flow_inst,
989 void *msg,
990 flow_fsm_event *p_event)
991{
992 bcmos_errno ret = BCM_ERR_OK;
993 bal_util_msg_auto_ind *ind_msg;
994
995
996 /* Parameter checks */
997 BUG_ON(NULL == p_flow_inst);
998 BUG_ON(NULL == msg);
999 BUG_ON(NULL == p_event);
1000
1001 BCM_LOG(DEBUG, log_id_flow,
1002 "Received an AUTO IND message in the %s state\n",
1003 flow_state_name_get(p_flow_inst->fsm_state));
1004
1005 ind_msg = (bal_util_msg_auto_ind *)msg;
1006
1007 /* Handle indication */
1008 ret = ind_msg->status;
1009
1010 if(BCM_ERR_OK == ret)
1011 {
1012 /* data reflects the new oper_status in the object being indicated */
1013 memcpy(&p_flow_inst->current_flow_info.data.oper_status, ind_msg->data, sizeof(bcmbal_status));
1014
1015 /*
1016 * Send the indication back to the BAL public API here
1017 */
1018 mgmt_msg_send_balapi_ind(ret,
1019 &p_flow_inst->current_flow_info.hdr,
1020 log_id_flow);
1021
1022
1023 p_flow_inst->fsm_state = FLOW_FSM_STATE_CONFIGURED;
1024
1025 }
1026
1027 return ret;
1028}
1029
1030/*****************************************************************************/
1031/**
1032 * @brief The Flow FSM state processing function to process a
1033 * message from one of the BAL apps received when the specified
1034 * flow instance FSM is in the REMOVING state.
1035 *
1036 * @param p_flow_inst Pointer to an flow instance
1037 * @param msg Pointer to a BAL message received from one of
1038 * the BAL apps.
1039 * @param p_event Pointer to an flow event structure
1040 *
1041 * @returns bcmos_errno
1042 *****************************************************************************/
1043static bcmos_errno flow_fsm_removing_process_util_msg(flow_inst *p_flow_inst,
1044 void *msg,
1045 flow_fsm_event *p_event)
1046{
1047 bcmos_errno ret = BCM_ERR_OK;
1048 bal_util_msg_ind *ind_msg;
1049 bcmos_bool is_ds_flow_to_host;
1050 /* Parameter checks */
1051 BUG_ON(NULL == p_flow_inst);
1052 BUG_ON(NULL == msg);
1053 BUG_ON(NULL == p_event);
1054
1055 ind_msg = (bal_util_msg_ind *)msg;
1056
1057 /*
1058 * NOTE: AUTO_IND messages are not processed in this function,
1059 * so there is no need to consider them in this logic.
1060 */
1061
1062 BCM_LOG(DEBUG, log_id_flow,
1063 " Received an IND message from BAL UTIL (%s) during REMOVING state\n",
1064 subsystem_str[bcmbal_sender_get(msg)]);
1065
1066 do{
1067
1068 /* Handle indication */
1069 ret = ind_msg->status;
1070
1071 /* Reflect the execution status in the object being returned in the indication
1072 */
1073 if(BCM_ERR_OK == ret)
1074 {
1075 if(BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_inst->api_req_flow_info.key.flow_type ||
1076 BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_inst->api_req_flow_info.key.flow_type)
1077 {
1078 is_ds_flow_to_host = (BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_inst->api_req_flow_info.key.flow_type &&
1079 (BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(&p_flow_inst->api_req_flow_info, flow, action) &&
1080 (p_flow_inst->api_req_flow_info.data.action.cmds_bitmask &
1081 BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST)));
1082
1083 if (bcm_topo_pon_get_pon_family(p_flow_inst->api_req_flow_info.data.access_int_id) == BCM_TOPO_PON_FAMILY_GPON)
1084 {
1085
1086 /* Don't attempt to release a GEM for a downstream flow that is TRAP_TO_HOST, because there
1087 * is no subscriber terminal involved in this flow (there was no GEM allocated for this flow).
1088 */
1089 if(BCMOS_FALSE == is_ds_flow_to_host)
1090 {
1091 if(BCM_ERR_OK != rsc_mgr_gem_free(p_flow_inst->api_req_flow_info.data.access_int_id,
1092 p_flow_inst->api_req_flow_info.data.svc_port_id, p_flow_inst))
1093 {
1094 BCM_LOG(ERROR, log_id_flow,
1095 " error encountered during release of flow resources (svc_port_id: %d, intf_id:%d\n",
1096 p_flow_inst->api_req_flow_info.data.svc_port_id,
1097 p_flow_inst->api_req_flow_info.data.access_int_id);
1098 }
1099 }
1100
1101
1102 }
1103
1104 /* Remove the svc_port_id record from the sub_term record for upstream flows,
1105 * or for downstream flows that are not destined to the host
1106 */
1107 if((BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_inst->api_req_flow_info.key.flow_type) ||
1108 ((BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_inst->api_req_flow_info.key.flow_type) &&
1109 !(is_ds_flow_to_host)))
1110 {
1111 bcmbal_sub_term_svc_port_id_list_entry_remove(p_flow_inst->p_sub_term_inst,
1112 p_flow_inst->current_flow_info.data.svc_port_id);
1113 }
1114
1115 /* Remove the agg_port_id from the sub_term record (only for upstream flows) */
1116 if(BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_inst->api_req_flow_info.key.flow_type)
1117 {
1118
1119 bcmbal_sub_term_agg_port_id_list_entry_remove(p_flow_inst->p_sub_term_inst,
1120 p_flow_inst->current_flow_info.data.agg_port_id);
1121 }
1122 }
1123
1124 p_flow_inst->current_flow_info.hdr.hdr.status = ret;
1125
1126 /* This is the proper state and status for the indication about to be sent */
1127 p_flow_inst->current_flow_info.data.admin_state = BCMBAL_STATE_DOWN;
1128 p_flow_inst->current_flow_info.data.oper_status = BCMBAL_STATUS_DOWN;
1129
1130 BCMBAL_OBJ_IN_PROGRESS_SET(&(p_flow_inst->current_flow_info), BCMOS_FALSE);
1131
1132 /*
1133 * Send the success indication back to the BAL public API here
1134 */
1135 mgmt_msg_send_balapi_ind(ret,
1136 &p_flow_inst->current_flow_info.hdr,
1137 log_id_flow);
1138
1139 /* Return the flow to the free pool regardless of the errors encountered above */
1140 flow_free_by_entry(p_flow_inst);
1141 }
1142 else
1143 {
1144 /*
1145 * Send the failure indication back to the BAL public API here
1146 */
1147 mgmt_msg_send_balapi_ind(ret,
1148 &p_flow_inst->current_flow_info.hdr,
1149 log_id_flow);
1150 }
1151 }while(0);
1152 return ret;
1153}
1154
1155/*****************************************************************************/
1156/**
1157 * @brief The Flow FSM state processing function to process a
1158 * AUTO IND message from one of the BAL apps received when the specified
1159 * flow instance FSM is in the REMOVING state.
1160 *
1161 * @param p_flow_inst Pointer to an flow instance
1162 * @param msg Pointer to a BAL message received from one of
1163 * the BAL apps.
1164 * @param p_event Pointer to an flow event structure
1165 *
1166 * @returns bcmos_errno
1167 *****************************************************************************/
1168static bcmos_errno flow_fsm_removing_process_util_auto_msg(flow_inst *p_flow_inst,
1169 void *msg,
1170 flow_fsm_event *p_event)
1171{
1172 bcmos_errno ret = BCM_ERR_OK;
1173
1174 /* Parameter checks */
1175 BUG_ON(NULL == p_flow_inst);
1176 BUG_ON(NULL == msg);
1177 BUG_ON(NULL == p_event);
1178
1179 BCM_LOG(DEBUG, log_id_flow,
1180 "Received an AUTO IND in the removing state"
1181 " - no further function\n");
1182
1183 return ret;
1184}
1185
1186/*****************************************************************************/
1187/**
1188 * @brief The Flow FSM function which is executed when an error
1189 * is encountered during FSM processing.
1190 *
1191 * @param p_flow_inst Pointer to an flow instance
1192 * @param msg Pointer to a BAL message received from one of
1193 * the BAL apps.
1194 * @param p_event Pointer to an flow event structure
1195 *
1196 * @returns bcmos_errno
1197 *****************************************************************************/
1198static bcmos_errno flow_fsm_state_err(flow_inst *p_flow_inst,
1199 void *msg,
1200 flow_fsm_event *p_event)
1201{
1202 bcmos_errno ret = BCM_ERR_INVALID_OP;
1203
1204 BCM_LOG(DEBUG, log_id_flow,
1205 "Error encountered processing FLOW FSM"
1206 " - BAD EVENT ()\n");
1207
1208 return ret;
1209}
1210static bcmos_errno flow_queue_validate(bcmbal_flow_cfg *p_flow_cfg, tm_queue_inst **p_tm_queue_inst)
1211{
1212 bcmos_errno ret = BCM_ERR_OK;
1213 bcmbal_interface_key intf_key;
1214 bcmbal_tm_sched_key tm_key;
1215 tm_sched_inst *p_tm_sched;
1216 bcmbal_tm_queue_key queue_key;
1217 bcmbal_tm_queue_ref queue_ref;
1218 bcmos_bool is_auto_set = BCMOS_TRUE;
1219
1220 do
1221 {
1222 if (BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_cfg->key.flow_type)
1223 {
1224 intf_key.intf_type = BCMBAL_INTF_TYPE_NNI;
1225 tm_key.dir = BCMBAL_TM_SCHED_DIR_US;
1226 intf_key.intf_id = p_flow_cfg->data.network_int_id;
1227 }
1228 else /*BCMBAL_FLOW_TYPE_DOWNSTREM or BCMBAL_FLOW_TYPE_MULTICAST */
1229 {
1230 intf_key.intf_type = BCMBAL_INTF_TYPE_PON;
1231 tm_key.dir = BCMBAL_TM_SCHED_DIR_DS;
1232 intf_key.intf_id = p_flow_cfg->data.access_int_id;
1233 }
1234
1235 if (BCMBAL_CFG_PROP_IS_SET(p_flow_cfg, flow, queue))
1236 {
1237 queue_ref = p_flow_cfg->data.queue;
1238 is_auto_set = BCMOS_FALSE;
1239 }
1240 else
1241 {
1242 /*look for the auto created tm sched and queue*/
1243 ret = bcmbal_interface_tm_get(intf_key, &tm_key.id);
1244 if (BCM_ERR_OK != ret)
1245 {
1246 BCM_LOG(ERROR, log_id_flow,
1247 "could not get interface instance"
1248 " to set flow queue reference intf_key.intf_type = %d,"
1249 " intf_key.intf_id = %d\n",
1250 intf_key.intf_type, intf_key.intf_id);
1251 break;
1252 }
1253 p_tm_sched = tm_sched_inst_get(tm_key, TM_SCHED_FLAG_ACTIVE);
1254 if (NULL == p_tm_sched)
1255 {
1256 BCM_LOG(ERROR, log_id_flow,
1257 "could not get tm sched instance to "
1258 "set flow queue reference intf_key.intf_type = %d,"
1259 " intf_key.intf_id = %d tm_key.dir = %s\n"
1260 ,intf_key.intf_type, intf_key.intf_id, TM_SCHED_DIR_TO_STR(tm_key.dir));
1261 ret = BCM_ERR_NOENT;
1262 break;
1263 }
1264
1265 if(BCMBAL_TM_CREATION_MODE_AUTO != p_tm_sched->current_tm_sched_info.data.creation_mode)
1266 {
1267 BCM_LOG(ERROR, log_id_flow,
1268 "can not set flow queue reference if the "
1269 "interface tm sched is not auto created. "
1270 "intf_key.intf_type = %d, intf_key.intf_id = %d tm_key.dir = %s\n",
1271 intf_key.intf_type, intf_key.intf_id, TM_SCHED_DIR_TO_STR(tm_key.dir));
1272 ret = BCM_ERR_PARM;
1273 break;
1274 }
1275
1276 /*if the tm sched exist and it is auto created, queue 0 should be there as well*/
1277 queue_ref.sched_id = tm_key.id;
1278 queue_ref.queue_id = 0;
1279 BCM_LOG(INFO, log_id_flow,
1280 "flow will be assign to queue: node id=%d "
1281 "node dir=%s queue id = %d\n",
1282 tm_key.id, TM_SCHED_DIR_TO_STR(tm_key.dir), queue_ref.queue_id);
1283
1284 BCMBAL_CFG_PROP_SET(p_flow_cfg, flow, queue, queue_ref);
1285 }
1286
1287 queue_key.id = queue_ref.queue_id;
1288 queue_key.sched_id = queue_ref.sched_id;
1289 queue_key.sched_dir = tm_key.dir;
1290
1291 /*validate a given tm queue exist and match flow type*/
1292 *p_tm_queue_inst = tm_queue_inst_get(queue_key, TM_QUEUE_FLAG_ACTIVE);
1293 if (NULL == *p_tm_queue_inst)
1294 {
1295 BCM_LOG(ERROR, log_id_flow,
1296 "could not find the queue to assign the flow to "
1297 ":tm sched dir = %s tm sched id = %d queue id = %d\n",
1298 TM_SCHED_DIR_TO_STR(queue_key.sched_dir), queue_key.sched_id,queue_key.id);
1299 ret = BCM_ERR_NOENT;
1300 break;
1301 }
1302 if (BCMOS_FALSE == is_auto_set)
1303 {
1304 /*should validate queue is related to the flow intf/sub_term/sub_term_uni*/
1305 tm_key.dir = queue_key.sched_dir;
1306 tm_key.id = queue_key.sched_id;
1307
1308 p_tm_sched = tm_sched_inst_get(tm_key, TM_SCHED_FLAG_ACTIVE);
1309 if (NULL == p_tm_sched)
1310 {
1311 BCM_LOG(ERROR, log_id_flow,
1312 "could not get tm sched instance to set flow queue "
1313 "reference intf_key.intf_type = %d, intf_key.intf_id = %d tm_key.dir = %s\n",
1314 intf_key.intf_type, intf_key.intf_id, TM_SCHED_DIR_TO_STR(tm_key.dir));
1315 ret = BCM_ERR_NOENT;
1316 break;
1317 }
1318
1319 if(BCMBAL_CFG_PROP_IS_SET(&p_tm_sched->req_tm_sched_info,tm_sched,owner))
1320 {
1321 switch(p_tm_sched->req_tm_sched_info.data.owner.type)
1322 {
1323 case BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE:
1324 {
1325 }
1326 break;
1327 case BCMBAL_TM_SCHED_OWNER_TYPE_SUB_TERM:
1328 {
1329 if (p_tm_sched->req_tm_sched_info.data.owner.u.sub_term.intf_id != p_flow_cfg->data.access_int_id
1330 || p_tm_sched->req_tm_sched_info.data.owner.u.sub_term.sub_term_id!= p_flow_cfg->data.sub_term_id)
1331 {
1332 BCM_LOG(ERROR, log_id_flow,
1333 "queue referenced by flow, attached to tm sched instance that is owned by "
1334 "sub term intf_id = %d sub_term_id = %d while flow is related to sub term"
1335 " intf_id = %d sub_term_id = %d therefor cannot be set as flow queue\n",
1336 p_tm_sched->req_tm_sched_info.data.owner.u.sub_term.intf_id,
1337 p_tm_sched->req_tm_sched_info.data.owner.u.sub_term.sub_term_id,
1338 p_flow_cfg->data.access_int_id,
1339 p_flow_cfg->data.sub_term_uni_idx);
1340 ret = BCM_ERR_PARM;
1341 break;
1342 }
1343 }
1344 break;
1345 case BCMBAL_TM_SCHED_OWNER_TYPE_UNI:
1346 {
1347 if (p_tm_sched->req_tm_sched_info.data.owner.u.uni.intf_id != p_flow_cfg->data.access_int_id
1348 || p_tm_sched->req_tm_sched_info.data.owner.u.uni.sub_term_id!= p_flow_cfg->data.sub_term_id
1349 || p_tm_sched->req_tm_sched_info.data.owner.u.uni.idx != p_flow_cfg->data.sub_term_uni_idx)
1350 {
1351 BCM_LOG(ERROR, log_id_flow,
1352 "queue referenced by flow , attached to tm sched "
1353 "instance that is owned by sub term uni intf_id = %d "
1354 "sub_term_id = %d uni = %d while flow is related to uni sub "
1355 "term intf_id = %d sub_term_id = %d uni = %d therefor cannot be "
1356 "set as flow queue\n",
1357 p_tm_sched->req_tm_sched_info.data.owner.u.uni.intf_id,
1358 p_tm_sched->req_tm_sched_info.data.owner.u.uni.sub_term_id,
1359 p_tm_sched->req_tm_sched_info.data.owner.u.uni.idx,
1360 p_flow_cfg->data.access_int_id,
1361 p_flow_cfg->data.sub_term_id,
1362 p_flow_cfg->data.sub_term_uni_idx);
1363 ret = BCM_ERR_PARM;
1364 }
1365 }
1366 break;
1367 default:
1368 BCM_LOG(ERROR, log_id_flow,
1369 "tm sched instance is owned by %d therefor "
1370 "cannot be set as flow queue\n",
1371 p_tm_sched->req_tm_sched_info.data.owner.type);
1372 ret = BCM_ERR_PARM;
1373 break;
1374 }
1375 }
1376 else
1377 {
1378 BCM_LOG(ERROR, log_id_flow,
1379 "tm sched instance is not set with an owner therefor "
1380 "cannot be set as flow queue intf_key.intf_type = %d, "
1381 "intf_key.intf_id = %d tm_key.dir = %s\n",
1382 intf_key.intf_type, intf_key.intf_id, TM_SCHED_DIR_TO_STR(tm_key.dir));
1383 ret = BCM_ERR_PARM;
1384 break;
1385 }
1386 }
1387 }while (0);
1388 return ret;
1389
1390}
1391
1392
1393/*****************************************************************************/
1394/**
1395 * @brief A function called by the core worker thread to process an
1396 * flow object message (SET, GET, CLEAR, STATS) received
1397 * from the BAL Public API.
1398 *
1399 * @param msg_payload Pointer to a BAL message received from the
1400 * BAL Public API.
1401 *
1402 * @returns bcmos_errno
1403 *****************************************************************************/
1404bcmos_errno process_flow_object(void *msg_payload)
1405{
1406 bcmos_errno ret = BCM_ERR_OK, rsp_ret = BCM_ERR_OK;
1407 bcmbal_flow_cfg *p_flow_cfg = (bcmbal_flow_cfg *)msg_payload;
1408 flow_inst *p_flow_inst = NULL;
1409 flow_fsm_event fsm_event;
1410 bcmbal_flow_key *p_flow_key;
1411 bcmbal_state admin_state_req;
1412 bcmos_bool b_flow_is_destined_to_host;
1413 bcmbal_obj_msg_type oper_type;
1414 bcmbal_subscriber_terminal_key sub_term_key;
1415 sub_term_inst *p_sub_term_inst = NULL;
1416 bcmos_bool is_multicast = BCMOS_FALSE;
1417 bcmos_bool is_unicast = BCMOS_FALSE;
1418
1419 bcmos_bool is_us_n_to_1 = BCMOS_FALSE;
1420 bcmos_bool is_ds_n_to_1 = BCMOS_FALSE;
1421
1422 tm_queue_inst *p_tm_queue_inst = NULL;
1423
1424 BUG_ON(NULL == msg_payload);
1425
1426 BCM_LOG(DEBUG, log_id_flow, "Processing a flow object\n");
1427
1428 p_flow_key = &p_flow_cfg->key;
1429
1430 oper_type = p_flow_cfg->hdr.hdr.type;
1431
1432 is_multicast = (BCMBAL_FLOW_TYPE_MULTICAST == p_flow_key->flow_type);
1433
1434 is_unicast = ((BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_key->flow_type) ||
1435 (BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_key->flow_type));
1436
1437 is_us_n_to_1 = ((BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_key->flow_type) &&
1438 (BCMBAL_CFG_PROP_IS_SET(p_flow_cfg, flow, group_id)));
1439
1440 is_ds_n_to_1 = ((BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_key->flow_type) &&
1441 (BCMBAL_CFG_PROP_IS_SET(p_flow_cfg, flow, group_id) ));
1442
1443
1444 /*
1445 * A message pointer may be passed inside the event structure.
1446 */
1447 fsm_event.msg = msg_payload;
1448
1449 /* SET or GET or CLEAR...? */
1450 switch (oper_type)
1451 {
1452 case (BCMBAL_OBJ_MSG_TYPE_SET):
1453 {
1454 bcmos_bool b_generate_event = BCMOS_FALSE;
1455 bcmos_bool found_new_flow = BCMOS_FALSE;
1456
1457 BCM_LOG(DEBUG, log_id_flow,
1458 "Processing a flow SET REQ mgmt message\n");
1459
1460 do
1461 {
1462 if(BCMBAL_STATUS_UP != acc_term_status_get())
1463 {
1464 BCM_LOG(ERROR, log_id_flow,
1465 "ERROR - Access-terminal is not UP. No further processing\n");
1466 ret = BCM_ERR_STATE;
1467 break;
1468 }
1469
1470 b_flow_is_destined_to_host = ((BCMBAL_CFG_PROP_IS_SET(p_flow_cfg, flow, action) &&
1471 (p_flow_cfg->data.action.cmds_bitmask &
1472 BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST)) ? BCMOS_TRUE : BCMOS_FALSE);
1473
1474 admin_state_req = p_flow_cfg->data.admin_state;
1475
1476 BCM_LOG(INFO, log_id_flow,
1477 "flow %d:%s request - admin state requested is %s\n",
1478 p_flow_key->flow_id,
1479 CORE_FSM_FLOW_TYPE_GET_STR(p_flow_key->flow_type),
1480 (BCMBAL_STATE_UP == admin_state_req) ? "UP" : "DOWN");
1481
1482 /*
1483 * Find or create the specified flow instance
1484 */
1485 p_flow_inst = flow_inst_get(p_flow_key, FLOW_FLAG_ANY, &found_new_flow);
1486 if(NULL == p_flow_inst)
1487 {
1488 /* This is a fatal error condition
1489 */
1490 BCM_LOG(ERROR, log_id_flow,
1491 "ERROR - Flow not found. No further processing\n");
1492 ret = BCM_ERR_NOMEM;
1493 break;
1494 }
1495
1496 /*
1497 * Fill in the local flow info data structure
1498 */
1499 p_flow_inst->api_req_flow_info = *p_flow_cfg;
1500
1501 /* For flows that have already been configured, merge the
1502 * requested flow data with the current flow data, and this results in the new request.
1503 */
1504 if((BCMOS_FALSE == found_new_flow) &&
1505 (p_flow_inst->api_req_flow_info.data.oper_status != p_flow_inst->current_flow_info.data.oper_status))
1506 {
1507 bcmbal_flow_object_overlay_w_dst_priority(&p_flow_inst->api_req_flow_info,
1508 &p_flow_inst->current_flow_info);
1509 }
1510
1511 BCM_LOG(INFO, log_id_flow,
1512 "flow access_int_id: %d, sub_term_id: %d\n",
1513 p_flow_inst->api_req_flow_info.data.access_int_id,
1514 p_flow_inst->api_req_flow_info.data.sub_term_id);
1515
1516 /* Next, find sub term instance, if is flow UP */
1517 if (BCMBAL_STATE_UP == admin_state_req)
1518 {
1519 sub_term_key.intf_id = p_flow_inst->api_req_flow_info.data.access_int_id;
1520 sub_term_key.sub_term_id = p_flow_inst->api_req_flow_info.data.sub_term_id;
1521
1522 p_sub_term_inst = sub_term_inst_get(&sub_term_key, SUB_TERM_FLAG_ACTIVE);
1523
1524 if (!p_sub_term_inst && !is_multicast && !is_ds_n_to_1 && !b_flow_is_destined_to_host)
1525 {
1526 BCM_LOG(ERROR, log_id_flow,
1527 "No active subscriber terminal with id=%u, and for flow type %s \n",
1528 sub_term_key.sub_term_id,
1529 CORE_FSM_FLOW_TYPE_GET_STR(p_flow_key->flow_type));
1530
1531 ret = BCM_ERR_NOENT;
1532 break;
1533 }
1534
1535 /*if the flow is not a cpu flow (to host), then we should validate/use the sched/queue setting*/
1536 if(!b_flow_is_destined_to_host)
1537 {
1538 /*find tm queue instance*/
1539 ret = flow_queue_validate(&(p_flow_inst->api_req_flow_info), &p_tm_queue_inst);
1540 if (ret != BCM_ERR_OK)
1541 {
1542 ret = BCM_ERR_NOENT;
1543 break;
1544 }
1545 ret = bcmbal_tm_queue_use_set(p_tm_queue_inst, BCMOS_TRUE);
1546 if (ret != BCM_ERR_OK)
1547 {
1548 ret = BCM_ERR_PARM;
1549 break;
1550 }
1551 }
1552 }
1553
1554 p_flow_inst->p_sub_term_inst = p_sub_term_inst;
1555
1556 /*
1557 * Process the request
1558 */
1559 if(((BCMBAL_STATE_UP == admin_state_req) || found_new_flow)
1560 && (BCMBAL_STATE_UP != p_flow_inst->current_flow_info.data.admin_state))
1561 {
1562 bcmbal_service_port_id svc_port_id = 0;
1563 flow_inst *p_peer_flow;
1564 uint8_t svc_port_id_range;
1565
1566 do
1567 {
1568 if (bcm_topo_pon_get_pon_family(p_flow_inst->api_req_flow_info.data.access_int_id) == BCM_TOPO_PON_FAMILY_GPON)
1569 {
1570 /* There's no need to do anything with the MAC in downstream flows that
1571 * that are destined to the host CPU (i.e. NNI->CPU)
1572 */
1573 if((BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_inst->api_req_flow_info.key.flow_type) ||
1574 !(b_flow_is_destined_to_host))
1575 {
1576
1577 /*
1578 * GEM resolution does not rely on the pbits in a packet, however,
1579 * we currently only support allocate a svc_port_id range of 1.
1580 */
1581 svc_port_id_range = 1;
1582
1583 /* Is there a peer flow configured already? (only upstream and downstream flows
1584 * can have a peer flow)
1585 * If not, look in the active list for a match. NOTE: It might not be there.
1586 */
1587 if( is_unicast && NULL == p_flow_inst->p_peer_flow_inst)
1588 {
1589 /*
1590 * See if we can find a peer flow (a peer flow is a flow that has
1591 * the same flow ID as this flow does, but has the opposite direction
1592 * in the key).
1593 */
1594
1595 /* Look for an active flow, but ignore the direction (BEWARE: we might
1596 * find ourself!!)
1597 */
1598 p_peer_flow = flow_inst_get(p_flow_key,
1599 FLOW_FLAG_ACTIVE | FLOW_FLAG_IGNORE_DIR,
1600 NULL);
1601
1602 /* If the flow that we found isn't us, then link it to our flow
1603 */
1604 if(p_peer_flow->api_req_flow_info.key.flow_type !=
1605 p_flow_inst->api_req_flow_info.key.flow_type)
1606 {
1607 p_flow_inst->p_peer_flow_inst = p_peer_flow;
1608 }
1609 }
1610
1611 /* If a peer flow exists, copy the GEM ID from the peer flow into this flow
1612 */
1613 if(NULL != p_flow_inst->p_peer_flow_inst)
1614 {
1615 svc_port_id =
1616 p_flow_inst->p_peer_flow_inst->current_flow_info.data.svc_port_id;
1617
1618 BCM_LOG(DEBUG, log_id_flow,
1619 "Using GEM ID from peer flow (%d) on access_id %d\n",
1620 svc_port_id,
1621 p_flow_inst->api_req_flow_info.data.access_int_id);
1622
1623 /* even though we have gem Id, get it allocated by rsrc mgr so that it can
1624 * manage ref counts.
1625 */
1626 ret = rsc_mgr_gem_alloc_unicast(
1627 p_flow_inst->api_req_flow_info.data.access_int_id,
1628 &svc_port_id,
1629 svc_port_id_range,
1630 p_flow_inst); /* A multicast flow cannot have a peer flow. So this means this is definitely not a multicast. */
1631 if (BCM_ERR_OK != ret)
1632 {
1633 /*
1634 * An error has occurred trying to get mandatory data
1635 */
1636
1637 BCM_LOG(ERROR, log_id_flow, "Failed to get base GEM from resource manager\n");
1638
1639 /*
1640 * @todo If the flow instance (that we got) is not active, then return it to the
1641 * free pool.
1642 */
1643
1644 break;
1645 }
1646 }
1647 else /* A peer flow does not exist */
1648 {
1649 /* needs single GEM for flows which is not multicast and not downstream N:1 service.
1650 In another words, all upstream flows and downstream flows which is not N:1 service needs one GEM */
1651 if(!is_multicast && !is_ds_n_to_1)
1652 {
1653 if(BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(&p_flow_inst->api_req_flow_info,
1654 flow,
1655 svc_port_id))
1656 {
1657 svc_port_id = p_flow_inst->api_req_flow_info.data.svc_port_id;
1658
1659
1660 BCM_LOG(DEBUG, log_id_flow,
1661 "Using the base GEM ID supplied by the user (%d) on access_id %d\n",
1662 svc_port_id,
1663 p_flow_inst->api_req_flow_info.data.access_int_id);
1664 }
1665 else
1666 {
1667 BCM_LOG(DEBUG, log_id_flow,
1668 "Getting a new base GEM ID on access_id %d from resource manager\n",
1669 p_flow_inst->api_req_flow_info.data.access_int_id);
1670 svc_port_id = 0; /* 0 is a magic number telling the resource manager that it should provide
1671 * the initial allocation of the base GEM */
1672 }
1673
1674 ret = rsc_mgr_gem_alloc_unicast(p_flow_inst->api_req_flow_info.data.access_int_id,
1675 &svc_port_id,
1676 svc_port_id_range,
1677 p_flow_inst);
1678
1679 if (BCM_ERR_OK != ret)
1680 {
1681 /*
1682 * An error has occurred trying to get mandatory data
1683 */
1684
1685 BCM_LOG(ERROR, log_id_flow, "Failed to get base GEM from resource manager\n");
1686
1687 /*
1688 * @todo If the flow instance (that we got) is not active, then return it to the
1689 * free pool.
1690 */
1691
1692 break;
1693 }
1694 }
1695 /* make sure the all members in the group assoficated with the flow has a GEM */
1696 if(BCMBAL_CFG_PROP_IS_SET(&p_flow_inst->api_req_flow_info, flow, group_id))
1697 {
1698 bcmbal_group_key group_key;
1699 bcmbal_group_owner group_owner;
1700
1701 group_key.group_id = p_flow_inst->api_req_flow_info.data.group_id;
1702 if(is_ds_n_to_1 || is_us_n_to_1 )
1703 {
1704 group_owner = BCMBAL_GROUP_OWNER_UNICAST;
1705 }
1706 else
1707 {
1708 group_owner = BCMBAL_GROUP_OWNER_MULTICAST;
1709 }
1710
1711 ret = group_owner_set(group_key, group_owner);
1712
1713 if(BCM_ERR_OK != ret)
1714 {
1715 BCM_LOG(ERROR, log_id_flow,
1716 "error %s while updating group owner\n", bcmos_strerror(ret));
1717 break;
1718 }
1719 }
1720 }
1721 /*
1722 * Set the GEM ID into the object being processed
1723 */
1724 if(svc_port_id)
1725 {
1726 BCMBAL_CFG_PROP_SET(&p_flow_inst->api_req_flow_info, flow, svc_port_id,svc_port_id);
1727 BCM_LOG(DEBUG, log_id_flow, "GEM %d being used\n", svc_port_id);
1728 }
1729 /*
1730 * alloc ID is only required on an UPSTREAM FLOW
1731 */
1732 if(BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_inst->api_req_flow_info.key.flow_type)
1733 {
1734 tm_sched_inst * dummy_p_tm_sched_inst;
1735 ret = flow_tm_get(&p_flow_inst->api_req_flow_info, &dummy_p_tm_sched_inst);
1736
1737 if (BCM_ERR_OK != ret)
1738 {
1739 /* An error has occurred trying to get mandatory data */
1740 BCM_LOG(ERROR, log_id_flow, "Failed to get required tm sched for agg port id\n");
1741 break;
1742 }
1743 ret = rsc_mgr_alloc_id_alloc( p_flow_inst->api_req_flow_info.data.access_int_id,
1744 &p_flow_inst->api_req_flow_info.data.agg_port_id, 1, p_flow_inst);
1745 if (BCM_ERR_OK != ret)
1746 {
1747 BCM_LOG(ERROR, log_id_flow, "Failed to get ALLOC ID from resource manager\n");
1748 break;
1749 }
1750
1751 BCM_LOG(DEBUG, log_id_flow, "ALLOC ID %d being used\n", p_flow_inst->api_req_flow_info.data.agg_port_id);
1752 }
1753
1754 /*
1755 * Perform the validation check(s) that the utils require
1756 */
1757 if(BCM_ERR_OK != (ret = mac_util_flow_info_validate(&p_flow_inst->api_req_flow_info)))
1758 {
1759 BCM_LOG(ERROR, log_id_flow, "Failed mac validation\n");
1760 break;
1761 }
1762 }
1763 }
1764 else if (bcm_topo_pon_get_pon_family(p_flow_inst->api_req_flow_info.data.access_int_id) == BCM_TOPO_PON_FAMILY_EPON)
1765 {
1766 /* There's no need to do anything with the MAC in downstream flows that
1767 * that are destined to the host CPU (i.e. NNI->CPU)
1768 */
1769 if((BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_inst->api_req_flow_info.key.flow_type) ||
1770 !(b_flow_is_destined_to_host))
1771 {
1772
1773 sub_term_key.intf_id = p_flow_inst->api_req_flow_info.data.access_int_id;
1774 sub_term_key.sub_term_id = p_flow_inst->api_req_flow_info.data.sub_term_id;
1775
1776 p_sub_term_inst = sub_term_inst_get(&sub_term_key, SUB_TERM_FLAG_ACTIVE);
1777
1778 if (!p_sub_term_inst)
1779 {
1780 BCM_LOG(ERROR, log_id_flow,
1781 "Failed to get subscriber terminal with id=%u\n",
1782 sub_term_key.sub_term_id);
1783 ret = BCM_ERR_NOENT;
1784 break;
1785 }
1786 /*
1787 * set svc_port to the subtunnel id.
1788 */
1789 BCMBAL_CFG_PROP_SET(&p_flow_inst->api_req_flow_info, flow,
1790 svc_port_id,p_sub_term_inst->current_sub_term_info.data.svc_port_id);
1791
1792 /*
1793 * Perform the validation check(s) that the utils require
1794 */
1795 if(BCM_ERR_OK != (ret = mac_util_flow_info_validate(&p_flow_inst->api_req_flow_info)))
1796 {
1797 BCM_LOG(ERROR, log_id_flow, "Failed mac validation\n");
1798 break;
1799 }
1800 }
1801 }
1802
1803 /* No need to do anything in the switch for upstream flows that
1804 * that are destined to the host CPU (i.e. PON->CPU), so no switch
1805 * validation is necessary.
1806 */
1807 if(!((BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_inst->api_req_flow_info.key.flow_type) &&
1808 b_flow_is_destined_to_host))
1809 {
1810 if(BCM_ERR_OK != (ret = sw_util_flow_info_validate(&p_flow_inst->api_req_flow_info)))
1811 {
1812 BCM_LOG(ERROR, log_id_flow, "Failed switch validation\n");
1813 break;
1814 }
1815 }
1816
1817 p_flow_inst->current_flow_info.data.admin_state = BCMBAL_STATE_UP;
1818
1819 /* Set the expected state of the oper_status upon success */
1820 p_flow_inst->api_req_flow_info.data.oper_status = BCMBAL_STATUS_UP;
1821
1822 fsm_event.event_type = FLOW_FSM_EVENT_TYPE_ADMIN_UP;
1823 b_generate_event = BCMOS_TRUE;
1824
1825 } while(0);
1826
1827 if(BCM_ERR_OK != ret)
1828 {
1829 flow_free_by_entry(p_flow_inst);
1830 break;
1831 }
1832 }
1833 /*
1834 * NOTE: This is not a complete implementation of the admin down processing.
1835 *
1836 * @todo - complete admin down processing
1837 */
1838 else if(((BCMBAL_STATE_DOWN == admin_state_req) || found_new_flow)
1839 && (BCMBAL_STATE_DOWN != p_flow_inst->current_flow_info.data.admin_state))
1840 {
1841 p_flow_inst->current_flow_info.data.admin_state = BCMBAL_STATE_DOWN;
1842
1843 /* Set the expected state of the oper_status upon success */
1844 p_flow_inst->api_req_flow_info.data.oper_status = BCMBAL_STATUS_DOWN;
1845
1846 fsm_event.event_type = FLOW_FSM_EVENT_TYPE_ADMIN_DN;
1847 b_generate_event = BCMOS_TRUE;
1848 }
1849 else
1850 {
1851 /* @todo implement a MODIFY here */
1852
1853 break; /* no state change detected - do nothing for now */
1854 }
1855
1856 }while(0);
1857
1858 /* We respond to the BAL public API backend with a result. We always
1859 * send a complete msg_payload back to the API, but the data portion
1860 * of the object is only relevant when a GET or GET-STATS has been requested.
1861 */
1862 rsp_ret = mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_flow);
1863
1864 if(BCM_ERR_OK != rsp_ret || BCM_ERR_OK != ret)
1865 {
1866 /* the mgmt_msg_send_balapi_rsp function above logs any errors that occur there */
1867 ret = (BCM_ERR_OK != rsp_ret) ? rsp_ret : ret;
1868 break;
1869 }
1870
1871 /* If there was an event generated, call the state machine exec */
1872 if(BCMOS_TRUE == b_generate_event)
1873 {
1874 /*
1875 * Run the flow FSM to process this event
1876 */
1877 ret = flow_fsm_exec(p_flow_inst, &fsm_event);
1878 }
1879 break;
1880 }
1881
1882 case (BCMBAL_OBJ_MSG_TYPE_GET):
1883 {
1884
1885 BCM_LOG(DEBUG, log_id_flow, "Processing a flow GET REQ mgmt message\n");
1886
1887 do
1888 {
1889 if(BCMBAL_STATUS_UP != acc_term_status_get())
1890 {
1891 BCM_LOG(ERROR, log_id_flow,
1892 "ERROR - Access-terminal is not UP. No further processing\n");
1893 ret = BCM_ERR_STATE;
1894 }
1895 else
1896 {
1897 /*
1898 * Find the specified flow instance
1899 */
1900 p_flow_inst = flow_inst_get(p_flow_key, FLOW_FLAG_ACTIVE, NULL);
1901 }
1902
1903 if(NULL == p_flow_inst)
1904 {
1905 if(BCM_ERR_STATE != ret)
1906 {
1907 /* This is not a fatal error condition
1908 */
1909 BCM_LOG(ERROR, log_id_flow, "ERROR - Specified flow (%d:%s) not found\n",
1910 p_flow_key->flow_id,
1911 CORE_FSM_FLOW_TYPE_GET_STR(p_flow_key->flow_type));
1912 ret = BCM_ERR_NOENT;
1913 }
1914
1915 break;
1916 }
1917
1918 /* We respond to the BAL public API backend with a result. We always
1919 * send a complete msg_payload back to the API, but the data portion
1920 * of the object is only relevant when a GET or GET-STATS has been requested.
1921 */
1922 p_flow_inst->current_flow_info.hdr.hdr.comm_hdr = ((bcmbal_obj *)msg_payload)->comm_hdr;
1923 *((bcmbal_flow_cfg *)msg_payload) = p_flow_inst->current_flow_info;
1924
1925 } while (0);
1926
1927 mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_flow);
1928
1929 }
1930 break;
1931
1932 case (BCMBAL_OBJ_MSG_TYPE_CLEAR):
1933 {
1934 BCM_LOG(DEBUG, log_id_flow, "Processing a flow CLEAR REQ mgmt message\n");
1935
1936 do
1937 {
1938 if(BCMBAL_STATUS_UP != acc_term_status_get())
1939 {
1940 BCM_LOG(ERROR, log_id_flow,
1941 "ERROR - Access-terminal is not UP. No further processing\n");
1942 ret = BCM_ERR_STATE;
1943 break;
1944 }
1945
1946 /*
1947 * Find the specified flow instance
1948 */
1949 p_flow_inst = flow_inst_get(p_flow_key, FLOW_FLAG_ACTIVE, NULL);
1950
1951 if(NULL == p_flow_inst)
1952 {
1953 /* This is a fatal error condition
1954 */
1955 BCM_LOG(ERROR, log_id_flow, "ERROR - Specified flow (%d:%s) not found\n",
1956 p_flow_key->flow_id,
1957 CORE_FSM_FLOW_TYPE_GET_STR(p_flow_key->flow_type));
1958 ret = BCM_ERR_NOENT;
1959 break;
1960 }
1961 } while(0);
1962
1963 /* We respond to the BAL public API backend with a result. We always
1964 * send a complete msg_payload back to the API, but the data portion
1965 * of the object is only relevant when a GET or GET-STATS has been requested.
1966 */
1967 rsp_ret = mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_flow);
1968
1969 if(BCM_ERR_OK != rsp_ret || BCM_ERR_OK != ret)
1970 {
1971 /* the mgmt_msg_send_balapi_rsp function above logs any errors that occur there */
1972 ret = (BCM_ERR_OK != rsp_ret) ? rsp_ret : ret;
1973 break;
1974 }
1975
1976 /* Merge the requested flow data with the current flow data,
1977 * and this is the new request.
1978 */
1979 bcmbal_flow_object_overlay_w_dst_priority(&p_flow_inst->api_req_flow_info,
1980 &p_flow_inst->current_flow_info);
1981 /*
1982 * Run the flow FSM to process this event
1983 */
1984 if(BCM_ERR_OK == ret)
1985 {
1986 fsm_event.event_type = FLOW_FSM_EVENT_TYPE_REMOVE;
1987
1988 ret = flow_fsm_exec(p_flow_inst, &fsm_event);
1989 }
1990
1991 break;
1992 }
1993
1994 default:
1995 {
1996 BCM_LOG(ERROR, log_id_flow, "Unsupported operation on flow object (%d)\n",
1997 oper_type );
1998 ret = BCM_ERR_NOT_SUPPORTED;
1999
2000 /* We respond to the BAL public API backend with a result. We always
2001 * send a complete msg_payload back to the API, but the data portion
2002 * of the object is only relevant when a GET or GET-STATS has been requested.
2003 */
2004 mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_flow);
2005
2006 break;
2007 }
2008 }
2009
2010 BCM_LOG(DEBUG, log_id_flow, "%s returns : %s\n", __FUNCTION__, bcmos_strerror(ret));
2011
2012 return ret;
2013}
2014
2015
2016/*****************************************************************************/
2017/**
2018 * @brief A function to process a flow object event received
2019 * from one of the BAL apps.
2020 *
2021 * @param msg_payload A pointer to the util message
2022 *
2023 * @returns bcmos_errno
2024 *****************************************************************************/
2025bcmos_errno process_flow_util_msg(void *msg_payload)
2026{
2027 bcmos_errno ret = BCM_ERR_OK;
2028 flow_inst *p_flow_inst;
2029 flow_fsm_event fsm_event;
2030 bcmbal_msg_type type;
2031 bcmbal_flow_key key;
2032
2033 type = bcmbal_type_minor_get(msg_payload);
2034
2035 BCM_LOG(DEBUG, log_id_flow, "processing a flow %s util message from %s\n",
2036 bcmbal_msg_t_str[type],
2037 subsystem_str[bcmbal_sender_get(msg_payload)]);
2038
2039 /* recover the key from the message */
2040 key = ((bal_util_msg_ind *)msg_payload)->obj_key.flow_key;
2041
2042 do
2043 {
2044 BCM_LOG(DEBUG, log_id_flow, "Got flow key id from util message (%d)\n", key.flow_id);
2045
2046 /*
2047 * Get the flow instance that's being referenced
2048 */
2049 if(NULL == (p_flow_inst = flow_inst_get(&key, FLOW_FLAG_ACTIVE, NULL)))
2050 {
2051 BCM_LOG(ERROR, log_id_flow, "invalid flow (%d, %s) found while processing a util message from %s\n",
2052 key.flow_id,
2053 CORE_FSM_FLOW_TYPE_GET_STR(key.flow_type),
2054 subsystem_str[bcmbal_sender_get(msg_payload)]);
2055
2056 ret = BCM_ERR_INTERNAL;
2057
2058 break;
2059 }
2060
2061 /*
2062 * Record the msg for further processing access
2063 */
2064 fsm_event.msg = msg_payload;
2065
2066 if (BAL_MSG_TYPE_IND == type)
2067 {
2068 fsm_event.event_type = FLOW_FSM_EVENT_TYPE_UTIL_MSG;
2069 }
2070 else if (BAL_MSG_TYPE_AUTO_IND == type)
2071 {
2072 fsm_event.event_type = FLOW_FSM_EVENT_TYPE_UTIL_AUTO_MSG;
2073 }
2074 else
2075 {
2076 ret = BCM_ERR_NOT_SUPPORTED;
2077 BCM_LOG(ERROR, log_id_flow,
2078 "Unknown message type received from the UTIL"
2079 " (not one of IND:AUTO_IND) (type:%d)\n",
2080 type);
2081 break;
2082 }
2083
2084 /*
2085 * Run the Flow FSM to process this event
2086 */
2087 if(BCM_ERR_OK == ret)
2088 {
2089 ret = flow_fsm_exec(p_flow_inst, &fsm_event);
2090 }
2091 }
2092 while(0);
2093
2094 return ret;
2095}
2096
2097/*
2098 * Helper functions
2099 */
2100
2101/*****************************************************************************/
2102/**
2103 * @brief A function to retrieve a flow instance of the specified
2104 * class.
2105 *
2106 * @param key A pointer to the key of the flow being
2107 * referenced
2108 * @param search_flag A flag specifying the type of flow
2109 * instance to be retrieved
2110 *
2111 * @param is_new_flow A returned value signifying whether a found flow was on the free list
2112 *
2113 * @returns flow_inst_t* A pointer to the found flow instance,
2114 * or NULL if one is not found
2115 *
2116 *****************************************************************************/
2117static flow_inst *flow_inst_get(bcmbal_flow_key *key, flow_flag search_flag, bcmos_bool *is_new_flow)
2118{
2119 flow_inst *current_entry = NULL;
2120
2121 if(NULL != is_new_flow)
2122 {
2123 *is_new_flow = BCMOS_FALSE;
2124 }
2125
2126 /*
2127 * First, check the active list if the caller has chosen to do so
2128 */
2129 if(FLOW_FLAG_ACTIVE & search_flag)
2130 {
2131 TAILQ_FOREACH(current_entry,
2132 &FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list,
2133 flow_inst_next)
2134 {
2135
2136 if((current_entry->api_req_flow_info.key.flow_id == key->flow_id)
2137 &&
2138 ((FLOW_FLAG_IGNORE_DIR & search_flag) ?
2139 1:(current_entry->api_req_flow_info.key.flow_type == key->flow_type)))
2140 {
2141 BCM_LOG(DEBUG, log_id_flow, "Found active flow\n");
2142 /* The flow instance pointer is in current_entry */
2143 break;
2144 }
2145 }
2146 }
2147
2148 /*
2149 * Next, check the free list if the caller has chosen to do so
2150 */
2151 if((FLOW_FLAG_FREE & search_flag) && (NULL == current_entry))
2152 {
2153 /* Now check the free list */
2154 if(!TAILQ_EMPTY(&FLOW_FSM_FLOW_LIST_CTX_PTR->free_flow_list))
2155 {
2156 /* Just grab the first entry */
2157 current_entry = TAILQ_FIRST(&FLOW_FSM_FLOW_LIST_CTX_PTR->free_flow_list);
2158
2159 /* Remove it from the free list */
2160 TAILQ_REMOVE(&FLOW_FSM_FLOW_LIST_CTX_PTR->free_flow_list, current_entry, flow_inst_next);
2161
2162 /* And add it to the active list */
2163 TAILQ_INSERT_TAIL(&FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list, current_entry, flow_inst_next);
2164
2165 /*
2166 * Initialize the fsm state and some of the fields
2167 */
2168 current_entry->fsm_state = FLOW_FSM_STATE_NULL;
2169 current_entry->p_peer_flow_inst = NULL;
2170
2171 if(NULL != is_new_flow)
2172 {
2173 *is_new_flow = BCMOS_TRUE;
2174 }
2175
2176 BCM_LOG(DEBUG, log_id_flow, "Using new flow\n");
2177
2178 }
2179 }
2180
2181 if((FLOW_FLAG_ANY & search_flag) && (NULL == current_entry))
2182 {
2183 /*A flow was not found on either list */
2184 BCM_LOG(DEBUG, log_id_flow, "************** ERROR: no flow found\n");
2185 }
2186
2187 return current_entry;
2188}
2189
2190
2191/*****************************************************************************/
2192/**
2193 * @brief A function to retrieve a flow instance by access_if_id and svc_port_id
2194 *
2195 * @param access_if_id access interface id of the flow being searched
2196 * @param type flow type (direction)
2197 * @param svc_port_id svc_port_id of the flow being searched
2198 *
2199 * @returns flow_inst_t* A pointer to the found flow instance,
2200 * or NULL if one is not found
2201 *****************************************************************************/
2202flow_inst *flow_get_by_svc_id(uint16_t access_if_id, bcmbal_flow_type type, bcmbal_service_port_id svc_port_id)
2203{
2204 flow_inst *current_entry = NULL;
2205
2206 /*
2207 * First, check the active list if the caller has chosen to do so
2208 */
2209 TAILQ_FOREACH(current_entry,
2210 &FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list,
2211 flow_inst_next)
2212 {
2213
2214 if((current_entry->api_req_flow_info.data.access_int_id == access_if_id)
2215 &&
2216 (current_entry->api_req_flow_info.key.flow_type == type)
2217 &&
2218 (current_entry->api_req_flow_info.data.svc_port_id == svc_port_id))
2219 {
2220 /* The flow instance pointer is in current_entry */
2221 break;
2222 }
2223 }
2224
2225 return current_entry;
2226}
2227
2228/*****************************************************************************/
2229/**
2230 * @brief A function to retrieve the current flow info for the specified
2231 * flow instance.
2232 *
2233 * @param key A flow key
2234 *
2235 * @returns bcmbal_flow_cfg* A pointer to the current flow info for the
2236 * specified flow, or NULL if the flow is not found
2237 *****************************************************************************/
2238bcmbal_flow_cfg *flow_get_current_info_by_key(bcmbal_flow_key key)
2239{
2240 flow_inst *current_entry = NULL;
2241
2242 /*
2243 * Check the active list
2244 */
2245 TAILQ_FOREACH(current_entry,
2246 &FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list,
2247 flow_inst_next)
2248 {
2249
2250 if((current_entry->current_flow_info.key.flow_id == key.flow_id)
2251 &&
2252 (current_entry->current_flow_info.key.flow_type == key.flow_type))
2253 {
2254 /* The flow instance pointer is in current_entry */
2255 break;
2256 }
2257 }
2258
2259 if(current_entry)
2260 {
2261 return &(current_entry->current_flow_info);
2262 }
2263 else
2264 {
2265 return NULL;
2266 }
2267}
2268
2269/*****************************************************************************/
2270/**
2271 * @brief A function to retrieve a flow instance by access_if_id and agg_port_id
2272 *
2273 * @param access_if_id access interface id of the flow being searched
2274 * @param agg_port_id svc_port_id of the flow being searched
2275 *
2276 * @returns flow_inst_t* A pointer to the found flow instance,
2277 * or NULL if one is not found
2278 *****************************************************************************/
2279flow_inst *flow_get_by_agg_id(uint16_t access_if_id, bcmbal_aggregation_port_id agg_port_id)
2280{
2281 flow_inst *current_entry = NULL;
2282
2283 /*
2284 * First, check the active list if the caller has chosen to do so
2285 */
2286 TAILQ_FOREACH(current_entry,
2287 &FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list,
2288 flow_inst_next)
2289 {
2290
2291 if((current_entry->current_flow_info.data.access_int_id == access_if_id)
2292 &&
2293 (current_entry->current_flow_info.key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM)
2294 &&
2295 (current_entry->current_flow_info.data.agg_port_id == agg_port_id))
2296 {
2297 /* The flow instance pointer is in current_entry */
2298 break;
2299 }
2300 }
2301
2302 return current_entry;
2303}
2304
2305
2306/*****************************************************************************/
2307/**
2308 * @brief A function to retrieve the first flow instance associated with
2309 * a subscriber terminal
2310 *
2311 * @param access_if_id access interface id of the flow being searched
2312 * @param type flow type (direction)
2313 * @param sub_term_id the subscriber terminal associated with the flow being
2314 * searched
2315 * @param sub_term_uni uni port on ONU
2316 *
2317 * @returns flow_inst_t* A pointer to the found flow instance,
2318 * or NULL if one is not found
2319 *****************************************************************************/
2320static flow_inst *flow_get_first_by_sub_term(uint16_t access_if_id,
2321 bcmbal_flow_type type,
2322 uint16_t sub_term_id,
2323 uint16_t sub_term_uni)
2324{
2325 flow_inst *current_entry = NULL;
2326 flow_inst *matched_entry = NULL;
2327
2328 /*
2329 * First, check the active list if the caller has chosen to do so
2330 */
2331 TAILQ_FOREACH(current_entry,
2332 &FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list,
2333 flow_inst_next)
2334 {
2335
2336 if((current_entry->current_flow_info.data.access_int_id == access_if_id)
2337 &&
2338 (current_entry->current_flow_info.key.flow_type == type)
2339 &&
2340 (current_entry->current_flow_info.data.sub_term_id == sub_term_id)
2341 &&
2342 (current_entry->current_flow_info.data.sub_term_uni_idx == sub_term_uni))
2343 {
2344 /* The flow instance pointer is in current_entry */
2345 matched_entry = current_entry;
2346 break;
2347 }
2348 else if((current_entry->current_flow_info.data.access_int_id == access_if_id)
2349 &&
2350 (current_entry->current_flow_info.key.flow_type == type)
2351 &&
2352 (current_entry->current_flow_info.data.sub_term_id == sub_term_id))
2353 {
2354 if(NULL == matched_entry)
2355 matched_entry = current_entry; /* store the first matched entry irrespective of uni port match */
2356 }
2357 }
2358
2359 return matched_entry;
2360}
2361
2362
2363bcmos_errno svc_port_id_for_sub_term_ds_flow_get(uint16_t access_if_id,
2364 uint16_t sub_term_id,
2365 uint16_t sub_term_uni,
2366 uint16_t *svc_port_id)
2367{
2368 flow_inst *p_flow_inst;
2369 bcmos_errno ret = BCM_ERR_OK;
2370
2371 if(NULL == (p_flow_inst = flow_get_first_by_sub_term(access_if_id,
2372 BCMBAL_FLOW_TYPE_DOWNSTREAM,
2373 sub_term_id,
2374 sub_term_uni)))
2375 {
2376 ret = BCM_ERR_NOENT;
2377 }
2378 else
2379 {
2380 *svc_port_id = p_flow_inst->current_flow_info.data.svc_port_id;
2381 }
2382
2383 return ret;
2384
2385}
2386
2387#ifdef FREE_FLOW_BY_KEY_SUPPORTED
2388/*****************************************************************************/
2389/**
2390 * @brief A function to free a flow instance specified by a supplied key.
2391 *
2392 *
2393 * @param key A pointer to the key of the subscriber terminal instance to be freed
2394 *
2395 *
2396 * @returns bcmos_errno
2397 *****************************************************************************/
2398static bcmos_errno flow_free_by_key(bcmbal_flow_key *key)
2399{
2400 bcmos_errno ret = BCM_ERR_OK;
2401 flow_inst *current_entry;
2402 flow_inst *p_temp_entry;
2403
2404 BUG_ON(NULL == key);
2405
2406 /*
2407 * First, check the active list (an active flow can be in the adding or removing state)
2408 */
2409 TAILQ_FOREACH_SAFE(current_entry,
2410 &FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list,
2411 flow_inst_next,
2412 p_temp_entry)
2413 {
2414 if((current_entry->api_req_flow_info.key.flow_id == key->flow_id) &&
2415 (current_entry->api_req_flow_info.key.flow_type == key->flow_type))
2416 {
2417
2418 /* Remove it from the active list */
2419 TAILQ_REMOVE(&FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list, current_entry, flow_inst_next);
2420
2421 /* And add it to the free list */
2422 current_entry->fsm_state = FLOW_FSM_STATE_NULL;
2423 current_entry->p_sub_term_fsm = NULL;
2424 TAILQ_INSERT_TAIL(&FLOW_FSM_FLOW_LIST_CTX_PTR->free_flow_list, current_entry, flow_inst_next);
2425 break;
2426 }
2427 }
2428
2429 return ret;
2430}
2431#endif
2432
2433/*****************************************************************************/
2434/**
2435 * @brief A function to free a flow instance specified by a the supplied
2436 * entry pointer.
2437 *
2438 * @param p_entry A pointer to the entry to be freed
2439 *
2440 *
2441 * @returns bcmos_errno
2442 *****************************************************************************/
2443static bcmos_errno flow_free_by_entry(flow_inst *p_entry)
2444{
2445 bcmos_errno ret = BCM_ERR_OK;
2446 flow_inst *current_entry;
2447 flow_inst *p_temp_entry;
2448
2449 /*
2450 * First, check the active list (an active flow can be in the adding or removing state)
2451 */
2452 TAILQ_FOREACH_SAFE(current_entry,
2453 &FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list,
2454 flow_inst_next,
2455 p_temp_entry)
2456 {
2457 if(current_entry == p_entry)
2458 {
2459 /* Remove it from the active list */
2460 TAILQ_REMOVE(&FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list, current_entry, flow_inst_next);
2461 break;
2462 }
2463 }
2464
2465 /* And add it to the free list */
2466 p_entry->fsm_state = FLOW_FSM_STATE_NULL;
2467
2468 /* And initialize the current object in the flow instance */
2469 flow_inst_entry_obj_init(p_entry);
2470
2471 TAILQ_INSERT_TAIL(&FLOW_FSM_FLOW_LIST_CTX_PTR->free_flow_list, p_entry, flow_inst_next);
2472
2473 return ret;
2474}
2475
2476static bcmos_errno flow_tm_auto_create(bcmbal_flow_cfg *p_flow_info, tm_sched_inst **p_tm_sched_inst)
2477{
2478 bcmos_errno ret = BCM_ERR_OK;
2479 bcmbal_tm_sched_cfg tm_sched_default_cfg;
2480 bcmbal_tm_sched_owner owner;
2481 bcmbal_tm_sched_key tm_sched_key;
2482 do
2483 {
2484 tm_sched_key.dir = BCMBAL_TM_SCHED_DIR_US;
2485 BCMBAL_CFG_INIT(&tm_sched_default_cfg, tm_sched, tm_sched_key);
2486 owner.type = BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT;
2487 owner.u.agg_port.intf_id = p_flow_info->data.access_int_id;
2488 owner.u.agg_port.sub_term_id = p_flow_info->data.sub_term_id;
2489 BCMBAL_CFG_PROP_SET(&tm_sched_default_cfg, tm_sched, owner, owner);
2490 BCMBAL_CFG_PROP_SET(&tm_sched_default_cfg, tm_sched, creation_mode, BCMBAL_TM_CREATION_MODE_AUTO);
2491 if(BCMBAL_CFG_PROP_IS_SET(p_flow_info,flow,sla))
2492 {
2493 BCMBAL_ATTRIBUTE_PROP_SET(&(tm_sched_default_cfg.data.rate),tm_shaping, sbr, p_flow_info->data.sla.min_rate);
2494 BCMBAL_ATTRIBUTE_PROP_SET(&(tm_sched_default_cfg.data.rate),tm_shaping, pbr, p_flow_info->data.sla.max_rate);
2495 }
2496 if (BCM_ERR_OK != (ret = bcmbal_tm_sched_auto_create(tm_sched_default_cfg, p_tm_sched_inst)))
2497 {
2498 BCM_LOG(ERROR, log_id_flow, "Could not create the auto tm sched\n");
2499 break;
2500 }
2501 }while(0);
2502 return ret;
2503}
2504
2505static bcmos_errno flow_tm_get(bcmbal_flow_cfg *p_flow_info, tm_sched_inst **p_tm_sched_inst)
2506{
2507 bcmos_errno ret = BCM_ERR_OK;
2508 do
2509 {
2510 if(BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow_info,
2511 flow,
2512 agg_port_id))
2513 {
2514 BCM_LOG(DEBUG, log_id_flow,
2515 "Using ALLOC ID supplied by the user (%d)\n",
2516 p_flow_info->data.agg_port_id );
2517
2518 *p_tm_sched_inst = tm_sched_find_agg_port_node(p_flow_info->data.access_int_id, p_flow_info->data.agg_port_id);
2519 if(NULL == *p_tm_sched_inst)
2520 {
2521 BCM_LOG(ERROR, log_id_flow,
2522 "agg port %d (intf id %d sub term id %d ) has no tm sched\n",
2523 p_flow_info->data.agg_port_id, p_flow_info->data.access_int_id, p_flow_info->data.sub_term_id);
2524 ret = BCM_ERR_PARM;
2525 break;
2526 }
2527 if(p_flow_info->data.sub_term_id != (*p_tm_sched_inst)->req_tm_sched_info.data.owner.u.agg_port.sub_term_id)
2528 {
2529 BCM_LOG(ERROR, log_id_flow,
2530 "agg port %d (intf id %d) is already assign to sub term %d (not %d) \n",
2531 p_flow_info->data.agg_port_id, p_flow_info->data.access_int_id,
2532 (*p_tm_sched_inst)->req_tm_sched_info.data.owner.u.agg_port.sub_term_id,
2533 p_flow_info->data.sub_term_id);
2534 ret = BCM_ERR_PARM;
2535 break;
2536 }
2537 }
2538 else
2539 {
2540 BCM_LOG(DEBUG, log_id_flow, "Getting a new ALLOC ID from resource manager\n");
2541 /*create a new agg port tm and allocate a new agg port id */
2542 ret = flow_tm_auto_create(p_flow_info, p_tm_sched_inst);
2543 if(BCM_ERR_OK != ret)
2544 {
2545 BCM_LOG(ERROR, log_id_flow,
2546 "could not create the auto tm sched for agg port %d (intf id %d)\n",
2547 p_flow_info->data.agg_port_id, p_flow_info->data.access_int_id);
2548 break;
2549 }
2550 BCMBAL_CFG_PROP_SET(p_flow_info, flow, agg_port_id,
2551 (*p_tm_sched_inst)->req_tm_sched_info.data.owner.u.agg_port.agg_port_id);
2552 }
2553 }while(0);
2554 return ret;
2555}
2556/*@}*/