blob: 97b0a4521adb29e09ed013c693329b663ac59b7a [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 group_fsm.c
34 * @brief Code to support the BAL group FSM
35 *
36 *
37 */
38
39/*@{*/
40
41#include <bcmos_system.h>
42#include <group_fsm.h>
43#include <bal_msg.h>
44#include <bal_osmsg.h>
45#include "bal_worker.h"
46#include "bal_mac_util.h"
47#include "bal_switch_util.h"
48#include "rsc_mgr.h"
49
50#include <bal_objs.h>
51#include <fsm_common.h>
52
53#ifdef ENABLE_LOG
54#include <bcm_dev_log.h>
55
56 /*
57 * @brief The logging device id for group
58 */
59static dev_log_id log_id_group;
60#endif
61
62/* local function declarations */
63static bcmos_errno group_fsm_create(group_inst *p_group_inst,
64 void *msg,
65 group_fsm_event *p_event);
66
67static bcmos_errno group_fsm_destroy(group_inst *p_group_inst,
68 void *msg,
69 group_fsm_event *p_event);
70
71static bcmos_errno group_fsm_add(group_inst *p_group_inst,
72 void *msg,
73 group_fsm_event *p_event);
74
75static bcmos_errno group_fsm_remove(group_inst *p_group_inst,
76 void *msg,
77 group_fsm_event *p_event);
78
79static bcmos_errno group_fsm_set(group_inst *p_group_inst,
80 void *msg,
81 group_fsm_event *p_event);
82
83static bcmos_errno group_fsm_configuring_util_msg(group_inst *p_group_inst,
84 void *msg,
85 group_fsm_event *p_event);
86
87static bcmos_errno group_fsm_deleting_util_msg(group_inst *p_group_inst,
88 void *msg,
89 group_fsm_event *p_event);
90
91static bcmos_errno group_fsm_ignore_api_msg(group_inst *p_group_inst,
92 void *msg,
93 group_fsm_event *p_event);
94
95static bcmos_errno group_fsm_state_err(group_inst *p_group_inst,
96 void *msg,
97 group_fsm_event *p_event);
98
99static bcmos_errno group_fsm_exec(group_inst *p_group_inst, group_fsm_event *p_event);
100
101static group_inst *group_inst_get(bcmbal_group_key *key, group_flag search_flag);
102
103static bcmos_errno group_free_by_entry(group_inst *p_entry);
104
105static bcmos_errno bcmbal_group_object_member_remove(bcmbal_group_cfg *p_req_group,
106 bcmbal_group_cfg *p_cur_group);
107
108static bcmos_errno bcmbal_group_object_member_add(bcmbal_group_cfg *p_req_group,
109 bcmbal_group_cfg *p_cur_group);
110
111static bcmos_errno bcmbal_group_object_member_replace(bcmbal_group_cfg *p_req_group,
112 bcmbal_group_cfg *p_cur_group);
113
114static bcmos_errno bcmbal_group_object_overlay(bcmbal_group_cfg *p_req_group,
115 bcmbal_group_cfg *p_cur_group);
116 /*
117 * @brief The Global group fsm context data structure
118 */
119static group_fsm_ctx g_group_fsm_group_list_ctx;
120
121/*
122 * Macros for group ctx access
123 */
124#define GROUP_FSM_GROUP_LIST_CTX (g_group_fsm_group_list_ctx)
125#define GROUP_FSM_GROUP_LIST_CTX_PTR (&g_group_fsm_group_list_ctx)
126
127/*
128 * @brief The definition of a group FSM state processing function
129 */
130typedef bcmos_errno (* group_fsm_state_processor)(group_inst *, void *, group_fsm_event *);
131
132/*
133 * @brief The Group FSM state processing array
134 */
135static group_fsm_state_processor group_states[GROUP_FSM_STATE__NUM_OF][GROUP_FSM_EVENT_TYPE__NUM_OF] =
136{
137
138 [GROUP_FSM_STATE_NULL] =
139 {
140 /*
141 * Next state: COMFIGURING
142 */
143 [GROUP_FSM_EVENT_TYPE_CREATE] = group_fsm_create,
144
145 /*
146 * Next state: NULL
147 */
148 [GROUP_FSM_EVENT_TYPE_DESTROY] = group_fsm_ignore_api_msg,
149
150 /*
151 * Next state: CONFIGURING
152 */
153 [GROUP_FSM_EVENT_TYPE_ADD] = group_fsm_add,
154
155 /*
156 * Next state: NULL
157 */
158 [GROUP_FSM_EVENT_TYPE_REMOVE] = group_fsm_ignore_api_msg,
159
160 /*
161 * Next state: CONFIGURING
162 */
163 [GROUP_FSM_EVENT_TYPE_SET] = group_fsm_set,
164
165 },
166 [GROUP_FSM_STATE_CONFIGURING] =
167 {
168 /*
169 * Next state: COMFIGURING
170 */
171 [GROUP_FSM_EVENT_TYPE_CREATE] = group_fsm_ignore_api_msg,
172
173 /*
174 * Next state: COMFIGURING
175 */
176 [GROUP_FSM_EVENT_TYPE_DESTROY] = group_fsm_ignore_api_msg,
177
178 /*
179 * Next state: CONFIGURING
180 */
181 [GROUP_FSM_EVENT_TYPE_ADD] = group_fsm_ignore_api_msg,
182
183 /*
184 * Next state: CONFIGURING
185 */
186 [GROUP_FSM_EVENT_TYPE_REMOVE] = group_fsm_ignore_api_msg,
187
188 /*
189 * Next state: CONFIGURING
190 */
191 [GROUP_FSM_EVENT_TYPE_SET] = group_fsm_ignore_api_msg,
192
193 /*
194 * Next state: CONFIGURED
195 */
196 [GROUP_FSM_EVENT_TYPE_UTIL_MSG] = group_fsm_configuring_util_msg,
197
198 },
199
200 [GROUP_FSM_STATE_CONFIGURED] =
201 {
202 /*
203 * Next state: COMFIGURING
204 */
205 [GROUP_FSM_EVENT_TYPE_CREATE] = group_fsm_ignore_api_msg,
206
207 /*
208 * Next state: DELETING
209 */
210 [GROUP_FSM_EVENT_TYPE_DESTROY] = group_fsm_destroy,
211
212 /*
213 * Next state: CONFIGURING
214 */
215 [GROUP_FSM_EVENT_TYPE_ADD] = group_fsm_add,
216
217 /*
218 * Next state: CONFIGURING
219 */
220 [GROUP_FSM_EVENT_TYPE_REMOVE] = group_fsm_remove,
221
222 /*
223 * Next state: CONFIGURING
224 */
225 [GROUP_FSM_EVENT_TYPE_SET] = group_fsm_set,
226
227 },
228
229 [GROUP_FSM_STATE_DELETING] =
230 {
231 /*
232 * Next state: DELETING
233 */
234 [GROUP_FSM_EVENT_TYPE_CREATE] = group_fsm_ignore_api_msg,
235
236 /*
237 * Next state: DELETING
238 */
239 [GROUP_FSM_EVENT_TYPE_DESTROY] = group_fsm_ignore_api_msg,
240
241 /*
242 * Next state: DELETING
243 */
244 [GROUP_FSM_EVENT_TYPE_ADD] = group_fsm_ignore_api_msg,
245
246 /*
247 * Next state: DELETING
248 */
249 [GROUP_FSM_EVENT_TYPE_REMOVE] = group_fsm_ignore_api_msg,
250
251 /*
252 * Next state: DELETING
253 */
254 [GROUP_FSM_EVENT_TYPE_SET] = group_fsm_ignore_api_msg,
255
256 /*
257 * Next state: NULL
258 */
259 [GROUP_FSM_EVENT_TYPE_UTIL_MSG] = group_fsm_deleting_util_msg,
260
261 },
262
263};
264
265static char *state_name_str[] =
266{
267 "GROUP_FSM_STATE_NULL",
268 "GROUP_FSM_STATE_CONFIGURING",
269 "GROUP_FSM_STATE_CONFIGURED",
270 "GROUP_FSM_STATE_DELETING",
271};
272
273/* Ensure that the name array size matches the associated enum */
274BAL_STATIC_ASSERT (GROUP_FSM_STATE__LAST == (sizeof (state_name_str) / sizeof (char *)), group_fsm_state);
275
276static char *group_state_name_get(group_fsm_state state)
277{
278 if(state < GROUP_FSM_STATE__LAST)
279 {
280 return state_name_str[state];
281 }
282 else
283 {
284 return "GROUP_UNKNOWN";
285 }
286}
287
288static char *event_name_str[] =
289{
290 "GROUP_FSM_CREATE_EVENT",
291 "GROUP_FSM_DESTROY_EVENT",
292 "GROUP_FSM_ADD_EVENT",
293 "GROUP_FSM_REMOVE_EVENT",
294 "GROUP_FSM_SET_EVENT",
295 "GROUP_FSM_UTIL_MSG_EVENT",
296};
297
298/* Ensure that the name array size matches the associated enum */
299BAL_STATIC_ASSERT (GROUP_FSM_EVENT_TYPE__LAST == (sizeof (event_name_str) / sizeof (char *)), group_fsm_event_type);
300
301static char *group_event_name_get(group_fsm_event_type event)
302{
303 if(event < GROUP_FSM_EVENT_TYPE__LAST)
304 {
305 return event_name_str[event];
306 }
307 else
308 {
309 return "GROUP_EVT_UNKNOWN";
310 }
311}
312
313/*****************************************************************************/
314/**
315 * @brief A function to initialize the current_group_info object of the
316 * supplied entry.
317 *
318 * @param p_entry A pointer to the entry to be initialized
319 *
320 *
321 * @returns void
322 *****************************************************************************/
323static void group_inst_entry_obj_init(group_inst *p_entry)
324{
325 /* The actual key content is irrelevant for free groups */
326 bcmbal_group_key key = { .group_id = 0 };
327
328 BCMBAL_CFG_INIT(&p_entry->current_group_info,
329 group,
330 key);
331
332 BCMBAL_OBJ_IN_PROGRESS_SET(&(p_entry->current_group_info), BCMOS_FALSE);
333}
334
335/*****************************************************************************/
336/**
337 * @brief A function to initialize the Group FSM infrastructure.
338 *
339 * NOTE: This is called once on startup and NOT for each FSM instance.
340 *
341 * @returns bcmos_errno
342 *****************************************************************************/
343bcmos_errno group_fsm_init(void)
344{
345 int ii;
346 group_inst *new_entry;
347 bcmos_errno ret = BCM_ERR_OK;
348
349#ifdef ENABLE_LOG
350 log_id_group = bcm_dev_log_id_register("GROUP", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
351 BUG_ON(log_id_group == DEV_LOG_INVALID_ID);
352#endif
353
354 /* Initialize all of the group queues */
355 TAILQ_INIT(&GROUP_FSM_GROUP_LIST_CTX_PTR->free_group_list);
356 TAILQ_INIT(&GROUP_FSM_GROUP_LIST_CTX_PTR->active_group_list);
357
358 /* Populate the free list with it's initial set of groups
359 */
360 for(ii=0; ii<GROUP_ALLOCATION_BLOCK_SIZE; ii++)
361 {
362
363 new_entry = bcmos_calloc(sizeof(group_inst));
364
365 if (NULL == new_entry)
366 {
367 BCM_LOG(FATAL, log_id_group, "Failed to initialize the group free list - FATAL\n");
368 ret = BCM_ERR_NOMEM;
369 break;
370 }
371
372 group_free_by_entry(new_entry);
373 }
374
375 return ret;
376}
377
378/*****************************************************************************/
379/**
380 * @brief A function to un-initialize the Group FSM infrastructure.
381 *
382 * NOTE: This is called once on shutdown and NOT for each FSM instance.
383 *
384 * @returns bcmos_errno
385 *****************************************************************************/
386bcmos_errno group_fsm_finish(void)
387{
388
389 group_inst *current_entry, *p_temp_entry;
390
391 /* Free all the entries on the active list */
392 TAILQ_FOREACH_SAFE(current_entry,
393 &GROUP_FSM_GROUP_LIST_CTX_PTR->active_group_list,
394 group_inst_next,
395 p_temp_entry)
396 {
397 /* free up the internal allocated member info */
398 if(current_entry->current_group_info.data.members.val)
399 {
400 bcmos_free(current_entry->current_group_info.data.members.val);
401 }
402 /* Remove it from the active list */
403 TAILQ_REMOVE(&GROUP_FSM_GROUP_LIST_CTX_PTR->active_group_list, current_entry, group_inst_next);
404
405 bcmos_free(current_entry);
406
407 }
408
409 /* Free all the entries on the free list */
410 TAILQ_FOREACH_SAFE(current_entry,
411 &GROUP_FSM_GROUP_LIST_CTX_PTR->free_group_list,
412 group_inst_next,
413 p_temp_entry)
414 {
415 /* Remove it from the active list */
416 TAILQ_REMOVE(&GROUP_FSM_GROUP_LIST_CTX_PTR->free_group_list, current_entry, group_inst_next);
417
418 bcmos_free(current_entry);
419 }
420
421 return BCM_ERR_OK;
422}
423
424/*****************************************************************************/
425/**
426 * @brief The Group FSM state processing executive function
427 *
428 * @param p_group_inst Pointer to a group instance
429 * @param p_event Pointer to a group event structure
430 *
431 * @returns bcmos_errno
432 *****************************************************************************/
433static bcmos_errno group_fsm_exec(group_inst *p_group_inst, group_fsm_event *p_event)
434{
435 bcmos_errno ret = BCM_ERR_OK;
436 group_fsm_state pre_state;
437 group_fsm_state_processor group_state_processor;
438
439 /* Parameter checks */
440 BUG_ON(NULL == p_group_inst);
441 BUG_ON(NULL == p_event);
442
443 /* Record the present state for debug printing
444 */
445 pre_state = p_group_inst->fsm_state;
446
447 /*
448 * Get the state processing function
449 */
450 group_state_processor = group_states[p_group_inst->fsm_state][p_event->event_type];
451
452 /*
453 * If there's a state processing function for this event and state, execute it.
454 * Otherwise, process a generic error.
455 */
456 if (group_state_processor)
457 {
458 ret = group_state_processor(p_group_inst, p_event->msg, p_event);
459 } else
460 {
461 group_fsm_state_err(p_group_inst, p_event->msg, p_event);
462 }
463
464 if(BCM_ERR_OK != ret)
465 {
466 BCM_LOG(ERROR, log_id_group, "*** Error detected during state processing\n");
467 p_group_inst->fsm_state = pre_state;
468 }
469
470 BCM_LOG(DEBUG, log_id_group, "*** Event %s, State: %s --> %s\n\n",
471 group_event_name_get(p_event->event_type),
472 group_state_name_get(pre_state),
473 group_state_name_get(p_group_inst->fsm_state));
474
475 return ret;
476}
477
478/*****************************************************************************/
479/**
480 * @brief The Group FSM state processing for a group create command received
481 * from the BAL Public API.
482 *
483 * @param p_group_inst Pointer to a group instance
484 * @param msg Pointer to a BAL message received from the BAL Public API
485 * @param p_event Pointer to a group event structure
486 *
487 * @returns bcmos_errno
488 *****************************************************************************/
489static bcmos_errno group_fsm_create(group_inst *p_group_inst,
490 void *msg,
491 group_fsm_event *p_event)
492{
493
494 bcmos_errno ret = BCM_ERR_OK;
495 group_fsm_state pre_fsm_state;
496
497 BCM_LOG(INFO, log_id_group, "Got SET request from BAL API - create group \n");
498
499 do
500 {
501 /* save the current state */
502 pre_fsm_state = p_group_inst->fsm_state;
503 /* change Group state to CONFIGURING */
504 p_group_inst->fsm_state = GROUP_FSM_STATE_CONFIGURING;
505
506 /*– Core calls Switch Utils to add applicable CMDs */
507 if(BCM_ERR_OK != (ret = sw_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_CREATE)))
508 {
509 BCM_LOG(ERROR, log_id_group, "error %s detected by switch util while create group\n", bcmos_strerror(ret));
510 break;
511 }
512
513 /*– Core calls Mac Utils create applicable CMDs */
514 if(BCM_ERR_OK != (ret = mac_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_CREATE, BCMOS_TRUE)))
515 {
516 BCM_LOG(ERROR, log_id_group, "error %s detected by mac util\n", bcmos_strerror(ret));
517
518 /* Reverse the (just create) group in the switch, otherwise the switch utils
519 * will be out of sync with Core and Mac. There's not
520 * much we can do about it if reversing this group fails.
521 */
522 if(BCM_ERR_OK != sw_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_DESTROY))
523 {
524 BCM_LOG(ERROR, log_id_group,
525 "error detected by switch util while reversing create group\n");
526 }
527 else
528 {
529 /* restore the original state */
530 p_group_inst->fsm_state = pre_fsm_state;
531 }
532
533 break;
534 }
535
536 /* The hardware has properly accepted the object info, so copy object to
537 * the current state.
538 */
539 bcmbal_group_object_overlay(&p_group_inst->api_req_group_info,
540 &p_group_inst->current_group_info);
541
542 BCMBAL_OBJ_IN_PROGRESS_SET(&(p_group_inst->current_group_info), BCMOS_TRUE);
543
544 }while(0);
545
546 /* If there were errors during processing, then report the error to the API */
547 if(BCM_ERR_OK != ret)
548 {
549 mgmt_msg_send_balapi_ind(ret,
550 msg,
551 log_id_group);
552 }
553
554 return ret;
555
556}
557
558/*****************************************************************************/
559/**
560 * @brief The Group FSM state processing for a group destroy command received
561 * from the BAL Public API.
562 *
563 * @param p_group_inst Pointer to a group instance
564 * @param msg Pointer to a BAL message received from the BAL Public API
565 * @param p_event Pointer to a group event structure
566 *
567 * @returns bcmos_errno
568 *****************************************************************************/
569static bcmos_errno group_fsm_destroy(group_inst *p_group_inst,
570 void *msg,
571 group_fsm_event *p_event)
572{
573
574 bcmos_errno ret = BCM_ERR_OK;
575 group_fsm_state sav_state = p_group_inst->fsm_state;
576 bcmbal_group_cfg *p_group_cfg;
577 int i;
578
579 BCM_LOG(INFO, log_id_group, "Got CLEAR request from BAL API - destroy group \n");
580
581 do
582 {
583 /* change Group state to CONFIGURING */
584 p_group_inst->fsm_state = GROUP_FSM_STATE_DELETING;
585
586 /* Destroy operation is best effort, as it is unlikely to fail */
587 /*– Core calls Switch Utils to add applicable CMDs */
588 if(BCM_ERR_OK != (ret = sw_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_DESTROY)))
589 {
590 BCM_LOG(ERROR, log_id_group, "error %s detected by switch util while destroy group\n", bcmos_strerror(ret));
591 /* if the group is busy, some flow still reference this group, skip the MAC and return error
592 no member has been clean up */
593 if(ret == BCM_ERR_INVALID_OP)
594 {
595 BCMBAL_OBJ_IN_PROGRESS_SET(&(p_group_inst->current_group_info), BCMOS_TRUE);
596 p_group_inst->fsm_state = sav_state;
597 mgmt_msg_send_balapi_ind(ret, msg, log_id_group);
598 return ret;
599 }
600 break;
601 }
602
603 /*– Core calls Mac Utils create applicable CMDs */
604 if(BCM_ERR_OK != (ret = mac_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_DESTROY, BCMOS_TRUE)))
605 {
606 BCM_LOG(ERROR, log_id_group, "error %s detected by mac util\n", bcmos_strerror(ret));
607 break;
608 }
609
610 /* The hardware has properly accepted the object info, so copy object to
611 * the current state.
612 */
613
614 BCMBAL_OBJ_IN_PROGRESS_SET(&(p_group_inst->current_group_info), BCMOS_TRUE);
615
616 }while(0);
617
618 /* If there were errors during processing, then report the error to the API */
619 if(BCM_ERR_OK != ret)
620 {
621 mgmt_msg_send_balapi_ind(ret,
622 msg,
623 log_id_group);
624 /* TBD, need logic to perform error recovery if SwitchUtil success and MacUtil failed */
625 }
626 else
627 {
628 /* update resource manager on svc_port_id usage - keep going as the Mac and Switch already clean up */
629 p_group_cfg = &p_group_inst->current_group_info;
630 for(i=0; i<p_group_cfg->data.members.len; i++)
631 {
632 if(BCM_ERR_OK != rsc_mgr_gem_free(p_group_cfg->data.members.val[i].intf_id,
633 p_group_cfg->data.members.val[i].svc_port_id,
634 NULL) )
635 {
636 BCM_LOG(ERROR, log_id_group,
637 " error encountered during destroy of group resources (gem_id: %d, intf_id:%d\n",
638 p_group_cfg->data.members.val[i].svc_port_id,
639 p_group_cfg->data.members.val[i].intf_id);
640 }
641 }
642 }
643
644 return ret;
645
646}
647/*****************************************************************************/
648/**
649 * @brief The Group FSM state processing for a group set command received
650 * from the BAL Public API.
651 *
652 * @param p_group_inst Pointer to a group instance
653 * @param msg Pointer to a BAL message received from the BAL Public API
654 * @param p_event Pointer to a group event structure
655 *
656 * @returns bcmos_errno
657 *****************************************************************************/
658static bcmos_errno group_fsm_set(group_inst *p_group_inst,
659 void *msg,
660 group_fsm_event *p_event)
661{
662
663 bcmos_errno ret = BCM_ERR_OK;
664 group_inst group_inst_rvt;
665 bcmbal_group_cfg *p_group_cfg;
666 int i;
667
668 BCM_LOG(INFO, log_id_group, "Got SET request from BAL API - replace group members\n");
669
670 do
671 {
672 /* save the current state */
673 group_inst_rvt.fsm_state = p_group_inst->fsm_state;
674 /* change Group state to CONFIGURING */
675 p_group_inst->fsm_state = GROUP_FSM_STATE_CONFIGURING;
676
677 /*– Core calls Switch Utils to add applicable CMDs */
678 if(BCM_ERR_OK != (ret = sw_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_SET)))
679 {
680 BCM_LOG(ERROR, log_id_group, "error %s detected by switch util while set group members\n", bcmos_strerror(ret));
681 break;
682 }
683
684 /*– Core calls Mac Utils add applicable CMDs */
685 if(BCM_ERR_OK != (ret = mac_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_SET, BCMOS_TRUE)))
686 {
687 BCM_LOG(ERROR, log_id_group, "error %s detected by mac util\n", bcmos_strerror(ret));
688
689 group_inst_rvt.current_group_info = p_group_inst->api_req_group_info;
690 group_inst_rvt.api_req_group_info = p_group_inst->current_group_info;
691 /* Reverse the (just set) group from the switch otherwise the switch utils
692 * will be out of sync with Core and Mac. There's not
693 * much we can do about it if reversing this group fails.
694 */
695 if(BCM_ERR_OK != sw_util_group_set(&group_inst_rvt, BAL_UTIL_OPER_GROUP_SET))
696 {
697 BCM_LOG(ERROR, log_id_group,
698 "error detected by switch util while reversing group\n");
699 }
700 else
701 {
702 /* restore the original state */
703 p_group_inst->fsm_state = group_inst_rvt.fsm_state;
704 }
705
706 break;
707 }
708 /* update resource manager on svc_port_id usage - free the gem on old members */
709 p_group_cfg = &p_group_inst->current_group_info;
710 for(i=0; i<p_group_cfg->data.members.len; i++)
711 {
712 if(BCM_ERR_OK != rsc_mgr_gem_free(p_group_cfg->data.members.val[i].intf_id,
713 p_group_cfg->data.members.val[i].svc_port_id,
714 NULL) )
715 {
716 BCM_LOG(ERROR, log_id_group,
717 " error encountered during release of group resources (gem_id: %d, intf_id:%d\n",
718 p_group_cfg->data.members.val[i].svc_port_id,
719 p_group_cfg->data.members.val[i].intf_id);
720 }
721 }
722
723 /* set operation can be made without CREATE, so fill in the non-member info */
724 bcmbal_group_object_overlay(&p_group_inst->api_req_group_info,
725 &p_group_inst->current_group_info);
726
727 /* The hardware has properly accepted the object info, so the request object becomes
728 * the current state.
729 */
730 bcmbal_group_object_member_replace(&p_group_inst->api_req_group_info,
731 &p_group_inst->current_group_info);
732
733 BCMBAL_OBJ_IN_PROGRESS_SET(&(p_group_inst->current_group_info), BCMOS_TRUE);
734
735 }while(0);
736
737 /* If there were errors during processing, then report the error to the API */
738 if(BCM_ERR_OK != ret)
739 {
740 mgmt_msg_send_balapi_ind(ret,
741 msg,
742 log_id_group);
743 }
744
745 return ret;
746
747}
748
749/*****************************************************************************/
750/**
751 * @brief The Group FSM state processing for a group add command received
752 * from the BAL Public API.
753 *
754 * @param p_group_inst Pointer to a group instance
755 * @param msg Pointer to a BAL message received from the BAL Public API
756 * @param p_event Pointer to a group event structure
757 *
758 * @returns bcmos_errno
759 *****************************************************************************/
760static bcmos_errno group_fsm_add(group_inst *p_group_inst,
761 void *msg,
762 group_fsm_event *p_event)
763{
764
765 bcmos_errno ret = BCM_ERR_OK;
766 group_fsm_state pre_fsm_state;
767
768 BCM_LOG(INFO, log_id_group, "Got SET request from BAL API - add group members\n");
769
770 do
771 {
772 /* save the current state */
773 pre_fsm_state = p_group_inst->fsm_state;
774 /* change Group state to CONFIGURING */
775 p_group_inst->fsm_state = GROUP_FSM_STATE_CONFIGURING;
776
777 /*– Core calls Switch Utils to add applicable CMDs */
778 if(BCM_ERR_OK != (ret = sw_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_ADD)))
779 {
780 BCM_LOG(ERROR, log_id_group, "error %s detected by switch util while add group members\n", bcmos_strerror(ret));
781 break;
782 }
783
784 /*– Core calls Mac Utils add applicable CMDs */
785 if(BCM_ERR_OK != (ret = mac_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_ADD, BCMOS_TRUE)))
786 {
787 BCM_LOG(ERROR, log_id_group, "error %s detected by mac util\n", bcmos_strerror(ret));
788
789 /* Reverse the (just add) group member from the switch, otherwise the switch utils
790 * will be out of sync with Core and Mac. There's not
791 * much we can do about it if reversing this group fails.
792 */
793 if(BCM_ERR_OK != sw_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_REMOVE))
794 {
795 BCM_LOG(ERROR, log_id_group,
796 "error detected by switch util while reversing add group\n");
797 }
798 else
799 {
800 /* restore the original state */
801 p_group_inst->fsm_state = pre_fsm_state;
802 }
803
804 break;
805 }
806
807 /* add operation can be made without CREATE, so fill in the non-member info */
808 bcmbal_group_object_overlay(&p_group_inst->api_req_group_info,
809 &p_group_inst->current_group_info);
810
811 /* The hardware has properly accepted the object info, so add object members to
812 * the current state.
813 */
814 bcmbal_group_object_member_add(&p_group_inst->api_req_group_info,
815 &p_group_inst->current_group_info);
816
817 BCMBAL_OBJ_IN_PROGRESS_SET(&(p_group_inst->current_group_info), BCMOS_TRUE);
818
819 }while(0);
820
821 /* If there were errors during processing, then report the error to the API */
822 if(BCM_ERR_OK != ret)
823 {
824 mgmt_msg_send_balapi_ind(ret,
825 msg,
826 log_id_group);
827 }
828
829 return ret;
830
831}
832
833/*****************************************************************************/
834/**
835 * @brief The Group FSM state processing for a group remove command received
836 * from the BAL Public API.
837 *
838 * @param p_group_inst Pointer to a group instance
839 * @param msg Pointer to a BAL message received from the BAL Public API
840 * @param p_event Pointer to a group event structure
841 *
842 * @returns bcmos_errno
843 *****************************************************************************/
844static bcmos_errno group_fsm_remove(group_inst *p_group_inst,
845 void *msg,
846 group_fsm_event *p_event)
847{
848
849 bcmos_errno ret = BCM_ERR_OK;
850 group_fsm_state pre_fsm_state;
851 bcmbal_group_cfg *p_group_cfg;
852 int i;
853
854 BCM_LOG(INFO, log_id_group, "Got SET request from BAL API - remove group members\n");
855
856 do
857 {
858 /* save the current state */
859 pre_fsm_state = p_group_inst->fsm_state;
860 /* change Group state to CONFIGURING */
861 p_group_inst->fsm_state = GROUP_FSM_STATE_CONFIGURING;
862
863 /*– Core calls Switch Utils to add applicable CMDs */
864 if(BCM_ERR_OK != (ret = sw_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_REMOVE)))
865 {
866 BCM_LOG(ERROR, log_id_group, "error %s detected by switch util while remove group members\n", bcmos_strerror(ret));
867 break;
868 }
869
870 /*– Core calls Mac Utils add applicable CMDs */
871 if(BCM_ERR_OK != (ret = mac_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_REMOVE, BCMOS_TRUE)))
872 {
873 BCM_LOG(ERROR, log_id_group, "error %s detected by mac util\n", bcmos_strerror(ret));
874
875 /* Reverse the (just remove) group member from the switch, otherwise the switch utils
876 * will be out of sync with Core and Mac. There's not
877 * much we can do about it if reversing this group fails.
878 */
879 if(BCM_ERR_OK != sw_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_ADD))
880 {
881 BCM_LOG(ERROR, log_id_group,
882 "error detected by switch util while reversing remove group\n");
883 }
884 else
885 {
886 /* restore the original state */
887 p_group_inst->fsm_state = pre_fsm_state;
888 }
889
890 break;
891 }
892
893 /* update resource manager on svc_port_id usage */
894 p_group_cfg = &p_group_inst->api_req_group_info;
895 for(i=0; i<p_group_cfg->data.members.len; i++)
896 {
897 /* if interface is not a member (e.g. already removed), skip it */
898 if(p_group_cfg->data.members.val[i].svc_port_id == 0)
899 {
900 continue;
901 }
902 if(BCM_ERR_OK != rsc_mgr_gem_free(p_group_cfg->data.members.val[i].intf_id,
903 p_group_cfg->data.members.val[i].svc_port_id,
904 NULL) )
905 {
906 BCM_LOG(ERROR, log_id_group,
907 " error encountered during release of group resources (gem_id: %d, intf_id:%d\n",
908 p_group_cfg->data.members.val[i].svc_port_id,
909 p_group_cfg->data.members.val[i].intf_id);
910 }
911 }
912
913 /* The hardware has properly accepted the object info, so remove object members from
914 * the current state.
915 */
916 bcmbal_group_object_member_remove(&p_group_inst->api_req_group_info,
917 &p_group_inst->current_group_info);
918
919 BCMBAL_OBJ_IN_PROGRESS_SET(&(p_group_inst->current_group_info), BCMOS_TRUE);
920
921 }while(0);
922
923 /* If there were errors during processing, then report the error to the API */
924 if(BCM_ERR_OK != ret)
925 {
926 mgmt_msg_send_balapi_ind(ret,
927 msg,
928 log_id_group);
929
930 }
931
932 return ret;
933
934}
935
936/*****************************************************************************/
937/**
938 * @brief The Group FSM state processing function to ignore a received message.
939 *
940 * @param p_group_inst Pointer to a group instance
941 * @param msg Pointer to a BAL message received from the BAL Public API
942 * @param p_event Pointer to a group event structure
943 *
944 * @returns bcmos_errno
945 *****************************************************************************/
946static bcmos_errno group_fsm_ignore_api_msg(group_inst *p_group_inst,
947 void *msg,
948 group_fsm_event *p_event)
949{
950 bcmos_errno ret = BCM_ERR_OK;
951
952 BCM_LOG(WARNING, log_id_group, "Ignoring message from BAL API when in %s state \n", group_state_name_get(p_group_inst->fsm_state));
953 return ret;
954}
955
956/*****************************************************************************/
957/**
958 * @brief The Group FSM state processing function to process a message from
959 * one of the BAL apps received when the specified group instance FSM
960 * is in the CONFIGURING state.
961 *
962 * @param p_group_inst Pointer to a group instance
963 * @param msg Pointer to a BAL message received from one of
964 * the BAL apps.
965 * @param p_event Pointer to a group event structure
966 *
967 * @returns bcmos_errno
968 *****************************************************************************/
969static bcmos_errno group_fsm_configuring_util_msg(group_inst *p_group_inst,
970 void *msg,
971 group_fsm_event *p_event)
972{
973 bcmos_errno ret;
974 bal_util_msg_ind *ind_msg;
975
976 /* Parameter checks */
977 BUG_ON(NULL == p_group_inst);
978 BUG_ON(NULL == msg);
979 BUG_ON(NULL == p_event);
980
981 ind_msg = (bal_util_msg_ind *)msg;
982
983 BCM_LOG(DEBUG, log_id_group,
984 " Received an IND message from BAL UTIL (%s) during CONFIGURING state\n",
985 subsystem_str[bcmbal_sender_get(msg)]);
986
987 BCM_LOG(DEBUG, log_id_group,
988 "%s, thread %s, module %d\n", __FUNCTION__, bcmos_task_current()->name, bcmos_module_current());
989
990 /* Handle indication */
991 ret = ind_msg->status;
992
993 /* Reflect the execution status in the object being returned in the indication
994 */
995 if(BCM_ERR_OK == ret)
996 {
997 /*
998 * The group has been successfully configured
999 */
1000 p_group_inst->fsm_state = GROUP_FSM_STATE_CONFIGURED;
1001
1002 }
1003 else
1004 {
1005 /* Error */
1006 BCM_LOG(ERROR, log_id_group, "Group %d: Failed in state %s. Error %s\n\n",
1007 p_group_inst->api_req_group_info.key.group_id,
1008 group_state_name_get(p_group_inst->fsm_state),
1009 bcmos_strerror(ret));
1010 }
1011
1012 BCMBAL_OBJ_IN_PROGRESS_SET(&(p_group_inst->current_group_info), BCMOS_FALSE);
1013 p_group_inst->current_group_info.hdr.hdr.status = ret;
1014
1015 /*
1016 * Send the indication back to the BAL public API here
1017 */
1018 mgmt_msg_send_balapi_ind(ret,
1019 &p_group_inst->current_group_info.hdr,
1020 log_id_group);
1021
1022 return ret;
1023}
1024
1025/*****************************************************************************/
1026/**
1027 * @brief The Group FSM state processing function to process a
1028 * message from one of the BAL apps received when the specified
1029 * group instance FSM is in the DELETING state.
1030 *
1031 * @param p_group_inst Pointer to an group instance
1032 * @param msg Pointer to a BAL message received from one of
1033 * the BAL apps.
1034 * @param p_event Pointer to a group event structure
1035 *
1036 * @returns bcmos_errno
1037 *****************************************************************************/
1038static bcmos_errno group_fsm_deleting_util_msg(group_inst *p_group_inst,
1039 void *msg,
1040 group_fsm_event *p_event)
1041{
1042 bcmos_errno ret = BCM_ERR_OK;
1043 bal_util_msg_ind *ind_msg;
1044
1045 /* Parameter checks */
1046 BUG_ON(NULL == p_group_inst);
1047 BUG_ON(NULL == msg);
1048 BUG_ON(NULL == p_event);
1049
1050 ind_msg = (bal_util_msg_ind *)msg;
1051
1052 BCM_LOG(DEBUG, log_id_group,
1053 " Received an IND message from BAL UTIL (%s) during DELETING state\n",
1054 subsystem_str[bcmbal_sender_get(msg)]);
1055
1056
1057 /* Handle indication */
1058 ret = ind_msg->status;
1059
1060 /* Reflect the execution status in the object being returned in the indication
1061 */
1062 if(BCM_ERR_OK == ret)
1063 {
1064 p_group_inst->current_group_info.hdr.hdr.status = ret;
1065
1066 /*
1067 * The group has been successfully destroy
1068 */
1069 p_group_inst->fsm_state = GROUP_FSM_STATE_NULL;
1070
1071 BCMBAL_OBJ_IN_PROGRESS_SET(&(p_group_inst->current_group_info), BCMOS_FALSE);
1072 /*
1073 * Send the indication back to the BAL public API
1074 */
1075 mgmt_msg_send_balapi_ind(ret,
1076 &p_group_inst->current_group_info.hdr,
1077 log_id_group);
1078
1079 /* free up the member memory */
1080 if( p_group_inst->current_group_info.data.members.val)
1081 {
1082 bcmos_free(p_group_inst->current_group_info.data.members.val);
1083 p_group_inst->current_group_info.data.members.val = NULL;
1084 p_group_inst->current_group_info.data.members.len = 0;
1085 }
1086
1087 /* Return the group to the free pool */
1088 group_free_by_entry(p_group_inst);
1089
1090 }
1091 else
1092 {
1093 /* Error */
1094 BCM_LOG(ERROR, log_id_group, "Group %d: Failed in state %s. Error %s\n\n",
1095 p_group_inst->current_group_info.key.group_id,
1096 group_state_name_get(p_group_inst->fsm_state),
1097 bcmos_strerror(ret));
1098 p_group_inst->fsm_state = GROUP_FSM_STATE_CONFIGURED;
1099
1100 }
1101
1102 return ret;
1103}
1104
1105/*****************************************************************************/
1106/**
1107 * @brief The Group FSM function which is executed when an error
1108 * is encountered during FSM processing.
1109 *
1110 * @param p_group_inst Pointer to a group instance
1111 * @param msg Pointer to a BAL message received from one of
1112 * the BAL apps.
1113 * @param p_event Pointer to a group event structure
1114 *
1115 * @returns bcmos_errno
1116 *****************************************************************************/
1117static bcmos_errno group_fsm_state_err(group_inst *p_group_inst,
1118 void *msg,
1119 group_fsm_event *p_event)
1120{
1121 bcmos_errno ret = BCM_ERR_INVALID_OP;
1122
1123 BCM_LOG(DEBUG, log_id_group,
1124 "Error encountered processing GROUP FSM"
1125 " - BAD EVENT ()\n");
1126
1127 return ret;
1128}
1129
1130/*****************************************************************************/
1131/**
1132 * @brief A function called by the core worker thread to process an
1133 * group object message (SET, GET, CLEAR, STATS) received
1134 * from the BAL Public API.
1135 *
1136 * @param msg_payload Pointer to a BAL message received from the
1137 * BAL Public API.
1138 *
1139 * @returns bcmos_errno
1140 *****************************************************************************/
1141bcmos_errno process_group_object(void *msg_payload)
1142{
1143 bcmos_errno ret = BCM_ERR_OK, rsp_ret = BCM_ERR_OK;
1144 bcmbal_group_cfg *p_group_cfg = (bcmbal_group_cfg *)msg_payload;
1145 group_inst *p_group_inst = NULL;
1146 group_fsm_event fsm_event;
1147 bcmbal_group_key *p_group_key;
1148 bcmbal_obj_msg_type oper_type;
1149 int i, j, num_svc_port_allocated = 0;
1150
1151 BUG_ON(NULL == msg_payload);
1152
1153 BCM_LOG(DEBUG, log_id_group, "Processing a group object\n");
1154
1155 p_group_key = &p_group_cfg->key;
1156
1157 oper_type = p_group_cfg->hdr.hdr.type;
1158
1159 /*
1160 * A message pointer may be passed inside the event structure.
1161 */
1162 fsm_event.msg = msg_payload;
1163
1164 /* SET or GET or CLEAR...? */
1165 switch (oper_type)
1166 {
1167 case (BCMBAL_OBJ_MSG_TYPE_SET):
1168 {
1169 bcmos_bool b_generate_event = BCMOS_FALSE;
1170
1171 BCM_LOG(DEBUG, log_id_group,
1172 "Processing a group SET REQ mgmt message\n");
1173
1174 do
1175 {
1176 if(BCMBAL_STATUS_UP != acc_term_status_get())
1177 {
1178 BCM_LOG(ERROR, log_id_group,
1179 "ERROR - Access-terminal is not UP. No further processing\n");
1180 ret = BCM_ERR_STATE;
1181 break;
1182 }
1183 /*
1184 * Find or create the specified group instance
1185 */
1186 p_group_inst = group_inst_get(p_group_key, GROUP_FLAG_ANY);
1187 if(NULL == p_group_inst)
1188 {
1189 /* This is a fatal error condition
1190 */
1191 BCM_LOG(ERROR, log_id_group,
1192 "ERROR - Group not found. No further processing\n");
1193 ret = BCM_ERR_NOMEM;
1194 break;
1195 }
1196
1197 /* If the state of this group is in flux, then reject the SET request */
1198 if(BCMOS_TRUE == BCMBAL_OBJ_IN_PROGRESS_GET(&(p_group_inst->current_group_info)))
1199 {
1200 ret = BCM_ERR_IN_PROGRESS;
1201 break;
1202 }
1203
1204 /* if needed, request/validate svc_port_id from resource manager - before validation */
1205 if (BCMBAL_CFG_PROP_IS_SET(p_group_cfg, group, members_cmd) )
1206 {
1207 if(p_group_cfg->data.members_cmd == BCMBAL_GROUP_MEMBER_CMD_REM_MEMBERS)
1208 {
1209 /* if service id is not specified, filled in with current config info */
1210 for(i=0; i<p_group_cfg->data.members.len; i++)
1211 {
1212 int req_intf = p_group_cfg->data.members.val[i].intf_id;
1213 if(p_group_cfg->data.members.val[i].svc_port_id == 0)
1214 {
1215 for(j=0; j<p_group_inst->current_group_info.data.members.len; j++)
1216 {
1217 int cur_intf = p_group_inst->current_group_info.data.members.val[j].intf_id;
1218 if( cur_intf == req_intf)
1219 {
1220 p_group_cfg->data.members.val[i].svc_port_id = p_group_inst->current_group_info.data.members.val[j].svc_port_id;
1221 break;
1222 }
1223 }
1224 }
1225 }
1226 }
1227 else
1228 {
1229 /* if the group already has owner, alloc the svc_port for addition or replacement members */
1230 if(BCMBAL_GROUP_OWNER_NONE != p_group_inst->current_group_info.data.owner )
1231 {
1232 /* copy the owner to the request */
1233 BCMBAL_CFG_PROP_SET(p_group_cfg, group, owner, p_group_inst->current_group_info.data.owner);
1234 /* allocate GEM */
1235 for(i=0; i<p_group_cfg->data.members.len; i++)
1236 {
1237 if (BCMBAL_GROUP_OWNER_MULTICAST != p_group_inst->current_group_info.data.owner)
1238 {
1239 ret = rsc_mgr_gem_alloc_multicast(p_group_cfg->data.members.val[i].intf_id,
1240 &p_group_cfg->data.members.val[i].svc_port_id,
1241 1, /* request gem range */
1242 NULL);
1243 }
1244 else if (BCMBAL_GROUP_OWNER_UNICAST != p_group_inst->current_group_info.data.owner)
1245 {
1246 ret = rsc_mgr_gem_alloc_broadcast(p_group_cfg->data.members.val[i].intf_id,
1247 &p_group_cfg->data.members.val[i].svc_port_id,
1248 1, /* request gem range */
1249 NULL);
1250 }
1251 else
1252 {
1253 ret = BCM_ERR_PARM;
1254 }
1255 if(BCM_ERR_OK != ret)
1256 {
1257 break;
1258 }
1259 }
1260 /* remember how many service port request been made to resource manager */
1261 num_svc_port_allocated = i;
1262 if(BCM_ERR_OK != ret)
1263 {
1264 BCM_LOG(ERROR, log_id_group,
1265 " error encountered during allocate of group resources (intf_id:%d)\n",
1266 p_group_cfg->data.members.val[i].intf_id);
1267 break;
1268 }
1269 }
1270
1271 }
1272 }
1273
1274 /*
1275 * Fill in the local group info data structure
1276 * Notice that any memory allocated in the request message will be free in
1277 * process_mgmt_msg() of worker thread. If needed, GROUP FSM need to clone any
1278 * request info into p_group_inst->current_group_info before return
1279 */
1280 p_group_inst->api_req_group_info = *p_group_cfg;
1281
1282 /*
1283 * Process the request
1284 */
1285
1286 /*
1287 * Perform the validation check(s) that the utils require
1288 */
1289 if(BCM_ERR_OK != (ret = mac_util_group_info_validate(&p_group_inst->api_req_group_info)))
1290 {
1291 BCM_LOG(ERROR, log_id_group, "Failed GROUP mac validation\n");
1292 break;
1293 }
1294
1295 if(BCM_ERR_OK != (ret = sw_util_group_info_validate(&p_group_inst->api_req_group_info)))
1296 {
1297 BCM_LOG(ERROR, log_id_group, "Failed switch group validation\n");
1298 break;
1299 }
1300
1301 /* set the event based on request command */
1302 b_generate_event = BCMOS_TRUE;
1303 if ( BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(&p_group_inst->api_req_group_info, group, members_cmd) )
1304 {
1305 switch(p_group_inst->api_req_group_info.data.members_cmd)
1306 {
1307 case BCMBAL_GROUP_MEMBER_CMD_ADD_MEMBERS:
1308 fsm_event.event_type = GROUP_FSM_EVENT_TYPE_ADD;
1309 break;
1310 case BCMBAL_GROUP_MEMBER_CMD_REM_MEMBERS:
1311 fsm_event.event_type = GROUP_FSM_EVENT_TYPE_REMOVE;
1312 break;
1313 case BCMBAL_GROUP_MEMBER_CMD_SET_MEMBERS:
1314 fsm_event.event_type = GROUP_FSM_EVENT_TYPE_SET;
1315 break;
1316 default:
1317 fsm_event.event_type = GROUP_FSM_EVENT_TYPE_NONE;
1318 b_generate_event = BCMOS_FALSE;
1319 break;
1320 }
1321 }
1322 else
1323 {
1324 fsm_event.event_type = GROUP_FSM_EVENT_TYPE_CREATE;
1325 }
1326
1327 }while(0);
1328
1329 /* if anything go wrong, inform resource manager to free up the service port */
1330 if (BCM_ERR_OK != ret &&
1331 BCMBAL_CFG_PROP_IS_SET(p_group_cfg, group, members_cmd) &&
1332 p_group_cfg->data.members_cmd != BCMBAL_GROUP_MEMBER_CMD_REM_MEMBERS)
1333 {
1334 for(i=0; i<num_svc_port_allocated; i++)
1335 {
1336 rsp_ret = rsc_mgr_gem_free(p_group_cfg->data.members.val[i].intf_id,
1337 p_group_cfg->data.members.val[i].svc_port_id,
1338 NULL);
1339
1340 /* best effort to free up */
1341 if(BCM_ERR_OK != rsp_ret)
1342 {
1343 BCM_LOG(ERROR, log_id_group,
1344 " error encountered during allocate of group resources (intf_id:%d)\n",
1345 p_group_cfg->data.members.val[i].intf_id);
1346 }
1347 }
1348 }
1349 /* We respond to the BAL public API backend with a result. We always
1350 * send a complete msg_payload back to the API, but the data portion
1351 * of the object is only relevant when a GET or GET-STATS has been requested.
1352 */
1353 rsp_ret = mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_group);
1354
1355 if(BCM_ERR_OK != rsp_ret || BCM_ERR_OK != ret)
1356 {
1357 /* the mgmt_msg_send_balapi_rsp function above logs any errors that occur there */
1358 ret = (BCM_ERR_OK != rsp_ret) ? rsp_ret : ret;
1359 break;
1360 }
1361
1362 /* If there was an event generated, call the state machine exec */
1363 if(BCMOS_TRUE == b_generate_event)
1364 {
1365 /*
1366 * Run the group FSM to process this event
1367 */
1368 ret = group_fsm_exec(p_group_inst, &fsm_event);
1369 }
1370 break;
1371 }
1372
1373 case (BCMBAL_OBJ_MSG_TYPE_GET):
1374 {
1375
1376 BCM_LOG(DEBUG, log_id_group, "Processing a group GET REQ mgmt message\n");
1377
1378 do
1379 {
1380 if(BCMBAL_STATUS_UP != acc_term_status_get())
1381 {
1382 BCM_LOG(ERROR, log_id_group,
1383 "ERROR - Access-terminal is not UP. No further processing\n");
1384 ret = BCM_ERR_STATE;
1385 }
1386 else
1387 {
1388 /*
1389 * Find the specified group instance
1390 */
1391 p_group_inst = group_inst_get(p_group_key, GROUP_FLAG_ACTIVE);
1392 }
1393
1394 if(NULL == p_group_inst)
1395 {
1396 if(BCM_ERR_STATE != ret)
1397 {
1398 /* This is not a fatal error condition
1399 */
1400 BCM_LOG(ERROR, log_id_group, "ERROR - Specified group (%d) not found\n",
1401 p_group_key->group_id);
1402
1403 ret = BCM_ERR_NOENT;
1404 }
1405
1406 break;
1407 }
1408
1409 /* We respond to the BAL public API backend with a result. We always
1410 * send a complete msg_payload back to the API, but the data portion
1411 * of the object is only relevant when a GET or GET-STATS has been requested.
1412 */
1413 p_group_inst->current_group_info.hdr.hdr.comm_hdr = ((bcmbal_obj *)msg_payload)->comm_hdr;
1414 *((bcmbal_group_cfg *)msg_payload) = p_group_inst->current_group_info;
1415
1416 } while (0);
1417
1418 mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_group);
1419
1420 }
1421 break;
1422
1423 case (BCMBAL_OBJ_MSG_TYPE_CLEAR):
1424 {
1425 BCM_LOG(DEBUG, log_id_group, "Processing a group CLEAR REQ mgmt message\n");
1426
1427 do
1428 {
1429 if(BCMBAL_STATUS_UP != acc_term_status_get())
1430 {
1431 BCM_LOG(ERROR, log_id_group,
1432 "ERROR - Access-terminal is not UP. No further processing\n");
1433 ret = BCM_ERR_STATE;
1434 break;
1435 }
1436
1437 /*
1438 * Find the specified group instance
1439 */
1440 p_group_inst = group_inst_get(p_group_key, GROUP_FLAG_ACTIVE);
1441
1442 if(NULL == p_group_inst)
1443 {
1444 /* This is a fatal error condition
1445 */
1446 BCM_LOG(ERROR, log_id_group, "ERROR - Specified group (%d: not found\n",
1447 p_group_key->group_id);
1448 ret = BCM_ERR_NOENT;
1449 break;
1450 }
1451 } while(0);
1452
1453 /* We respond to the BAL public API backend with a result. We always
1454 * send a complete msg_payload back to the API, but the data portion
1455 * of the object is only relevant when a GET or GET-STATS has been requested.
1456 */
1457 rsp_ret = mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_group);
1458
1459 if(BCM_ERR_OK != rsp_ret || BCM_ERR_OK != ret)
1460 {
1461 /* the mgmt_msg_send_balapi_rsp function above logs any errors that occur there */
1462 ret = (BCM_ERR_OK != rsp_ret) ? rsp_ret : ret;
1463 break;
1464 }
1465
1466 /*
1467 * Run the group FSM to process this event
1468 */
1469 if(BCM_ERR_OK == ret)
1470 {
1471 fsm_event.event_type = GROUP_FSM_EVENT_TYPE_DESTROY;
1472
1473 ret = group_fsm_exec(p_group_inst, &fsm_event);
1474 }
1475
1476 break;
1477 }
1478
1479 default:
1480 {
1481 BCM_LOG(ERROR, log_id_group, "Unsupported operation on group object (%d)\n",
1482 oper_type );
1483 ret = BCM_ERR_NOT_SUPPORTED;
1484
1485 /* We respond to the BAL public API backend with a result. We always
1486 * send a complete msg_payload back to the API, but the data portion
1487 * of the object is only relevant when a GET or GET-STATS has been requested.
1488 */
1489 mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_group);
1490
1491 break;
1492 }
1493 }
1494
1495 BCM_LOG(DEBUG, log_id_group, "%s returns\n", __FUNCTION__);
1496
1497 return ret;
1498}
1499
1500
1501/*****************************************************************************/
1502/**
1503 * @brief A function to process a group object event received
1504 * from one of the BAL apps.
1505 *
1506 * @param msg_payload A pointer to the util message
1507 *
1508 * @returns bcmos_errno
1509 *****************************************************************************/
1510bcmos_errno process_group_util_msg(void *msg_payload)
1511{
1512 bcmos_errno ret = BCM_ERR_OK;
1513 group_inst *p_group_inst;
1514 group_fsm_event fsm_event;
1515 bcmbal_msg_type type;
1516 bcmbal_group_key key;
1517
1518 type = bcmbal_type_minor_get(msg_payload);
1519
1520 BCM_LOG(DEBUG, log_id_group, "processing a group %s util message from %s\n",
1521 bcmbal_msg_t_str[type],
1522 subsystem_str[bcmbal_sender_get(msg_payload)]);
1523
1524 /* recover the key from the message */
1525 key = ((bal_util_msg_ind *)msg_payload)->obj_key.group_key;
1526
1527 do
1528 {
1529 BCM_LOG(DEBUG, log_id_group, "Got group key id (%d) from util message\n", key.group_id);
1530
1531 /*
1532 * Get the group instance that's being referenced
1533 */
1534 if(NULL == (p_group_inst = group_inst_get(&key, GROUP_FLAG_ACTIVE)))
1535 {
1536 BCM_LOG(ERROR, log_id_group, "invalid group (%d) found while processing a util message from %s\n",
1537 key.group_id,
1538 subsystem_str[bcmbal_sender_get(msg_payload)]);
1539
1540 ret = BCM_ERR_INTERNAL;
1541
1542 break;
1543 }
1544
1545 /*
1546 * Record the msg for further processing access
1547 */
1548 fsm_event.msg = msg_payload;
1549
1550 if (BAL_MSG_TYPE_IND == type)
1551 {
1552 fsm_event.event_type = GROUP_FSM_EVENT_TYPE_UTIL_MSG;
1553 }
1554 else
1555 {
1556 ret = BCM_ERR_NOT_SUPPORTED;
1557 BCM_LOG(ERROR, log_id_group,
1558 "Unknown message type received from the UTIL"
1559 " (not IND) (type:%d)\n",
1560 type);
1561 break;
1562 }
1563
1564 /*
1565 * Run the Group FSM to process this event
1566 */
1567 if(BCM_ERR_OK == ret)
1568 {
1569 ret = group_fsm_exec(p_group_inst, &fsm_event);
1570 }
1571 }
1572 while(0);
1573
1574 return ret;
1575}
1576
1577/*
1578 * Helper functions
1579 */
1580
1581/*****************************************************************************/
1582/**
1583 * @brief A function to retrieve a group instance of the specified
1584 * class.
1585 *
1586 * @param key A pointer to the key of the group being
1587 * referenced
1588 * @param search_flag A flag specifying the type of group
1589 * instance to be retrieved
1590 *
1591 * @returns group_inst_t* A pointer to the found group instance,
1592 * or NULL if one is not found
1593 *****************************************************************************/
1594static group_inst *group_inst_get(bcmbal_group_key *key, group_flag search_flag)
1595{
1596 group_inst *current_entry = NULL;
1597
1598 /*
1599 * First, check the active list if the caller has chosen to do so
1600 */
1601 if(GROUP_FLAG_ACTIVE & search_flag)
1602 {
1603 TAILQ_FOREACH(current_entry,
1604 &GROUP_FSM_GROUP_LIST_CTX_PTR->active_group_list,
1605 group_inst_next)
1606 {
1607
1608 if(current_entry->api_req_group_info.key.group_id == key->group_id)
1609 {
1610 BCM_LOG(DEBUG, log_id_group, "Found active group\n");
1611 /* The group instance pointer is in current_entry */
1612 break;
1613 }
1614 }
1615 }
1616
1617 /*
1618 * Next, check the free list if the caller has chosen to do so
1619 */
1620 if((GROUP_FLAG_FREE & search_flag) && (NULL == current_entry))
1621 {
1622 /* Now check the free list */
1623 if(!TAILQ_EMPTY(&GROUP_FSM_GROUP_LIST_CTX_PTR->free_group_list))
1624 {
1625 /* Just grab the first entry */
1626 current_entry = TAILQ_FIRST(&GROUP_FSM_GROUP_LIST_CTX_PTR->free_group_list);
1627
1628 /* Remove it from the free list */
1629 TAILQ_REMOVE(&GROUP_FSM_GROUP_LIST_CTX_PTR->free_group_list, current_entry, group_inst_next);
1630
1631 /* And add it to the active list */
1632 TAILQ_INSERT_TAIL(&GROUP_FSM_GROUP_LIST_CTX_PTR->active_group_list, current_entry, group_inst_next);
1633
1634 /*
1635 * Initialize the fsm state
1636 */
1637 current_entry->fsm_state = GROUP_FSM_STATE_NULL;
1638
1639 BCM_LOG(DEBUG, log_id_group, "Using new group\n");
1640
1641 }
1642 }
1643
1644 if((GROUP_FLAG_ANY & search_flag) && (NULL == current_entry))
1645 {
1646 /*A group was not found on either list*/
1647
1648 BCM_LOG(DEBUG, log_id_group, "************** ERROR: no group found\n");
1649 }
1650
1651 return current_entry;
1652}
1653
1654
1655#ifdef GET_GROUP_CFG_BY_KEY_SUPPORTED
1656/*****************************************************************************/
1657/**
1658 * @brief A function to retrieve the current group info for the specified
1659 * group instance.
1660 *
1661 * @param key A group key
1662 *
1663 * @returns bcmbal_group_cfg* A pointer to the current group info for the
1664 * specified group, or NULL if the group is not found
1665 *****************************************************************************/
1666static bcmbal_group_cfg *group_get_current_info_by_key(bcmbal_group_key key)
1667{
1668 group_inst *current_entry = NULL;
1669
1670 /*
1671 * Check the active list
1672 */
1673 TAILQ_FOREACH(current_entry,
1674 &GROUP_FSM_GROUP_LIST_CTX_PTR->active_group_list,
1675 group_inst_next)
1676 {
1677
1678 if(current_entry->current_group_info.key.group_id == key.group_id)
1679 {
1680 /* The group instance pointer is in current_entry */
1681 break;
1682 }
1683 }
1684
1685 if(current_entry)
1686 {
1687 return &(current_entry->current_group_info);
1688 }
1689 else
1690 {
1691 return NULL;
1692 }
1693}
1694#endif
1695
1696/*****************************************************************************/
1697/**
1698 * @brief A function to free a group instance specified by a the supplied
1699 * entry pointer.
1700 *
1701 * @param p_entry A pointer to the entry to be freed
1702 *
1703 *
1704 * @returns bcmos_errno
1705 *****************************************************************************/
1706static bcmos_errno group_free_by_entry(group_inst *p_entry)
1707{
1708 bcmos_errno ret = BCM_ERR_OK;
1709 group_inst *current_entry;
1710 group_inst *p_temp_entry;
1711
1712 /*
1713 * First, check the active list (an active group can be in the adding or removing state)
1714 */
1715 TAILQ_FOREACH_SAFE(current_entry,
1716 &GROUP_FSM_GROUP_LIST_CTX_PTR->active_group_list,
1717 group_inst_next,
1718 p_temp_entry)
1719 {
1720 if(current_entry == p_entry)
1721 {
1722 /* Remove it from the active list */
1723 TAILQ_REMOVE(&GROUP_FSM_GROUP_LIST_CTX_PTR->active_group_list, current_entry, group_inst_next);
1724 break;
1725 }
1726 }
1727
1728 /* And add it to the free list */
1729 p_entry->fsm_state = GROUP_FSM_STATE_NULL;
1730
1731 /* And initialize the current object in the group instance */
1732 group_inst_entry_obj_init(p_entry);
1733
1734 TAILQ_INSERT_TAIL(&GROUP_FSM_GROUP_LIST_CTX_PTR->free_group_list, p_entry, group_inst_next);
1735
1736 return ret;
1737}
1738
1739/*****************************************************************************/
1740/**
1741 * @brief A function to remove group members specified in a requested group
1742 * from a target group
1743 *
1744 * @param p_req_group A pointer to the group config that holds the members to be removed
1745 * @param p_cur_group A pointer to the group config that holds the current members
1746 *
1747 * @returns bcmos_errno
1748 *****************************************************************************/
1749static bcmos_errno bcmbal_group_object_member_remove(bcmbal_group_cfg *p_req_group,
1750 bcmbal_group_cfg *p_cur_group)
1751{
1752 int i, j, k, num_members, member_match;
1753 bcmbal_group_member_info *p_new_member_info;
1754 bcmbal_group_member_info_list_u16 new_members;
1755
1756 num_members = 0;
1757 /* first calculate the final number of members */
1758 for(i = 0; i < p_cur_group->data.members.len; i++)
1759 {
1760 member_match = 0;
1761 /* check if it is in the remove list */
1762 for(j = 0; j < p_req_group->data.members.len; j++)
1763 {
1764 if( p_cur_group->data.members.val[i].intf_id == p_req_group->data.members.val[j].intf_id)
1765 {
1766 member_match = 1;
1767 break;
1768 }
1769 }
1770 /* no match, we need to keep it */
1771 if(!member_match)
1772 {
1773 num_members++;
1774 }
1775 }
1776 /* if all requested members already been removed, no change, just return */
1777 if( num_members == p_cur_group->data.members.len)
1778 {
1779 return BCM_ERR_OK;
1780 }
1781 /* if no member left, just clean up and leave */
1782 if(num_members == 0)
1783 {
1784 bcmos_free(p_cur_group->data.members.val);
1785 BCMBAL_CFG_PROP_CLEAR(p_cur_group, group, members);
1786 return BCM_ERR_OK;
1787 }
1788
1789 /* alloc memory for new list */
1790 p_new_member_info = bcmos_calloc( num_members * sizeof(bcmbal_group_member_info));
1791 if(p_new_member_info == NULL)
1792 {
1793 BCM_LOG(ERROR, log_id_group, "calloc failed when remove members from group object\n");
1794 return BCM_ERR_NORES;
1795 }
1796
1797 /* fill in the new list */
1798 k=0;
1799 for(i = 0; i < p_cur_group->data.members.len; i++)
1800 {
1801 member_match = 0;
1802 /* check if it is in the remove list */
1803 for(j = 0; j < p_req_group->data.members.len; j++)
1804 {
1805 if( p_cur_group->data.members.val[i].intf_id == p_req_group->data.members.val[j].intf_id)
1806 {
1807 member_match = 1;
1808 break;
1809 }
1810 }
1811 /* no match, we need to keep it */
1812 if(!member_match)
1813 {
1814 p_new_member_info[k++] = p_cur_group->data.members.val[i];
1815 }
1816 }
1817
1818 /* free up the old list */
1819 bcmos_free(p_cur_group->data.members.val);
1820
1821 /* assign new list */
1822 new_members.val = p_new_member_info;
1823 new_members.len = num_members;
1824 BCMBAL_CFG_PROP_SET(p_cur_group, group, members, new_members);
1825
1826 return BCM_ERR_OK;
1827}
1828
1829/*****************************************************************************/
1830/**
1831 * @brief A function to add group members specified in a requested group
1832 * to a target group
1833 *
1834 * @param p_req_group A pointer to the group config that holds the members to be added
1835 * @param p_cur_group A pointer to the group config that holds the current members
1836 *
1837 * @returns bcmos_errno
1838 *****************************************************************************/
1839static bcmos_errno bcmbal_group_object_member_add(bcmbal_group_cfg *p_req_group,
1840 bcmbal_group_cfg *p_cur_group)
1841{
1842 int i, j, k, num_members, member_match;
1843 bcmbal_group_member_info *p_new_member_info;
1844 bcmbal_group_member_info_list_u16 new_members;
1845
1846 num_members = 0;
1847 /* first calculate the final number of members */
1848 for(i = 0; i < p_req_group->data.members.len; i++)
1849 {
1850 member_match = 0;
1851 /* check if it is in the current list */
1852 for(j = 0; j < p_cur_group->data.members.len; j++)
1853 {
1854 if( p_req_group->data.members.val[i].intf_id == p_cur_group->data.members.val[j].intf_id)
1855 {
1856 member_match = 1;
1857 break;
1858 }
1859 }
1860 /* no match, we need to add it */
1861 if(!member_match)
1862 {
1863 num_members++;
1864 }
1865 }
1866 /* if all requested members already in the list, no change, just return */
1867 if( num_members == 0)
1868 {
1869 return BCM_ERR_OK;
1870 }
1871 /* alloc memory for new list */
1872 p_new_member_info = bcmos_calloc( (num_members + p_cur_group->data.members.len) * sizeof(bcmbal_group_member_info) );
1873 if(p_new_member_info == NULL)
1874 {
1875 BCM_LOG(ERROR, log_id_group, "calloc failed when add members to group object\n");
1876 return BCM_ERR_NORES;
1877 }
1878
1879 /* fill in the new list */
1880 k=0;
1881 for(j = 0; j < p_cur_group->data.members.len; j++)
1882 {
1883 p_new_member_info[k++] = p_cur_group->data.members.val[j];
1884 }
1885
1886 for(i = 0; i < p_req_group->data.members.len; i++)
1887 {
1888 member_match = 0;
1889 /* check if it is in the current list */
1890 for(j = 0; j < p_cur_group->data.members.len; j++)
1891 {
1892 if( p_req_group->data.members.val[i].intf_id == p_cur_group->data.members.val[j].intf_id)
1893 {
1894 member_match = 1;
1895 break;
1896 }
1897 }
1898 /* no match, we need to add it */
1899 if(!member_match)
1900 {
1901 p_new_member_info[k++] = p_req_group->data.members.val[i];
1902 }
1903 }
1904
1905 /* free up the old list */
1906 bcmos_free(p_cur_group->data.members.val);
1907
1908 /* assign new list */
1909 new_members.val = p_new_member_info;
1910 new_members.len = k;
1911 BCMBAL_CFG_PROP_SET(p_cur_group, group, members, new_members);
1912
1913 return BCM_ERR_OK;
1914}
1915
1916/*****************************************************************************/
1917/**
1918 * @brief A function to replace group members specified in a targeted group
1919 * with a requested group
1920 *
1921 * @param p_req_group A pointer to the group config that holds the members to be replaced
1922 * @param p_cur_group A pointer to the group config that holds the current members
1923 *
1924 * @returns bcmos_errno
1925 *****************************************************************************/
1926static bcmos_errno bcmbal_group_object_member_replace(bcmbal_group_cfg *p_req_group,
1927 bcmbal_group_cfg *p_cur_group)
1928{
1929 int j, k;
1930 bcmbal_group_member_info *p_new_member_info;
1931 bcmbal_group_member_info_list_u16 new_members;
1932
1933 /* alloc memory for new list */
1934 p_new_member_info = bcmos_calloc( p_req_group->data.members.len * sizeof(bcmbal_group_member_info) );
1935 if(p_new_member_info == NULL)
1936 {
1937 BCM_LOG(ERROR, log_id_group, "calloc failed when replace members to group object\n");
1938 return BCM_ERR_NORES;
1939 }
1940
1941 /* fill in the new list */
1942 k=0;
1943 for(j = 0; j < p_req_group->data.members.len; j++)
1944 {
1945 p_new_member_info[k++] = p_req_group->data.members.val[j];
1946 }
1947
1948 /* free up the old list */
1949 bcmos_free(p_cur_group->data.members.val);
1950
1951 /* assign new list */
1952 new_members.val = p_new_member_info;
1953 new_members.len = k;
1954 BCMBAL_CFG_PROP_SET(p_cur_group, group, members, new_members);
1955
1956 return BCM_ERR_OK;
1957}
1958
1959/*****************************************************************************/
1960/**
1961 * @brief A function to overlay group info specified in a requested group
1962 * to a target group ( exclude the member info as it will be managed by
1963 bcmbal_group_object_member_xxx functions)
1964 *
1965 * @param p_req_group A pointer to the requested group config
1966 * @param p_cur_group A pointer to the group config that to be overlay
1967 *
1968 * @returns bcmos_errno
1969 *****************************************************************************/
1970static bcmos_errno bcmbal_group_object_overlay(bcmbal_group_cfg *p_req_group,
1971 bcmbal_group_cfg *p_cur_group)
1972{
1973 BUG_ON(NULL == p_cur_group);
1974 BUG_ON(NULL == p_req_group);
1975
1976 bcmbal_presence_mask cur_presence_mask;
1977
1978 /* First, copy the common object and keys in their entirety, except for preserving the presence_mask */
1979 cur_presence_mask = p_cur_group->hdr.hdr.presence_mask;
1980 p_cur_group->hdr = p_req_group->hdr;
1981 p_cur_group->key = p_req_group->key;
1982 p_cur_group->hdr.hdr.presence_mask = cur_presence_mask;
1983
1984 /* Now copy only the fields that have been specified in the request object */
1985 if(BCMBAL_CFG_PROP_IS_SET(p_req_group, group, members_cmd))
1986 {
1987 BCMBAL_CFG_PROP_SET(p_cur_group, group, members_cmd, p_req_group->data.members_cmd);
1988 }
1989
1990 if(BCMBAL_CFG_PROP_IS_SET(p_req_group, group, cookie))
1991 {
1992 BCMBAL_CFG_PROP_SET(p_cur_group, group, cookie, p_req_group->data.cookie);
1993 }
1994
1995 if(BCMBAL_CFG_PROP_IS_SET(p_req_group, group, owner))
1996 {
1997 BCMBAL_CFG_PROP_SET(p_cur_group, group, owner, p_req_group->data.owner);
1998 }
1999 return BCM_ERR_OK;
2000}
2001
2002/*****************************************************************************/
2003/**
2004 * @brief A function to test if the specified group is active
2005 *
2006 * @param p_group_key A pointer to the group key to be tested
2007 *
2008 * @returns bcmos_bool BCMOS_TRUE if specified group is active
2009 *****************************************************************************/
2010bcmos_bool group_is_active(bcmbal_group_key *p_group_key)
2011{
2012 return (NULL == group_inst_get(p_group_key, GROUP_FLAG_ACTIVE)) ? BCMOS_FALSE : BCMOS_TRUE;
2013}
2014
2015/*****************************************************************************/
2016/**
2017 * @brief A function to retrive the group owner
2018 *
2019 * @param group_key the group key
2020 * @param p_group_owner A pointer to store the retrieve owner
2021 *
2022 * @returns bcmos_errno
2023 *****************************************************************************/
2024bcmos_errno group_owner_get(bcmbal_group_key group_key, bcmbal_group_owner *p_group_owner)
2025{
2026 group_inst *p_group;
2027
2028 p_group = group_inst_get(&group_key, GROUP_FLAG_ACTIVE);
2029 if (p_group)
2030 {
2031 *p_group_owner = p_group->current_group_info.data.owner;
2032 return BCM_ERR_OK;
2033 }
2034 else
2035 {
2036 return BCM_ERR_NOENT;
2037 }
2038}
2039
2040/*****************************************************************************/
2041/**
2042 * @brief A function to set the group owner
2043 * When the owner is set, the service port of the member is also allocated
2044 *
2045 * @param group_key group key
2046 * @param grp_owner owner
2047 *
2048 * @returns bcmos_errno
2049 *****************************************************************************/
2050bcmos_errno group_owner_set(bcmbal_group_key group_key, bcmbal_group_owner grp_owner)
2051{
2052 bcmos_errno ret = BCM_ERR_OK;
2053
2054 /* if group has no owner, set the GROUP owner and allocate the GEM for each GROUP member
2055
2056 1. flip the current info with request info
2057 2. allocate GEM for each group member
2058 3. Call switch_util to update the group (SET with new GEM info)
2059 4. Call mac_util to update the group (SET with new GEM info)
2060 5. flip back the current info
2061 else
2062 do nothing and let util validate the group owner
2063 end-if
2064 later, follow the regular FLOW fsm to SET FLOW in switch_util and Mac_util
2065 */
2066
2067 group_inst *p_group;
2068
2069 p_group = group_inst_get(&group_key, GROUP_FLAG_ACTIVE);
2070
2071 if (p_group == NULL)
2072 {
2073 BCM_LOG(ERROR, log_id_group, "Failed to get group instance, group_id %d\n", group_key.group_id);
2074 return BCM_ERR_INTERNAL;
2075 }
2076 if ( BCMBAL_GROUP_OWNER_NONE == p_group->current_group_info.data.owner)
2077 {
2078 int i;
2079 bcmbal_group_cfg *p_group_req = &(p_group->api_req_group_info);
2080 bcmbal_group_cfg *p_group_cur = &(p_group->current_group_info);
2081
2082 do
2083 {
2084 /* step 1 */
2085 BCMBAL_CFG_PROP_SET(p_group_req, group, owner, grp_owner);
2086 BCMBAL_CFG_PROP_SET(p_group_req, group, members_cmd, BAL_UTIL_OPER_GROUP_SET);
2087 p_group_req->data.members.len = p_group_cur->data.members.len;
2088 p_group_req->data.members.val = p_group_cur->data.members.val;
2089
2090 p_group_cur->data.members.len = 0;
2091 p_group_cur->data.members.val = NULL;
2092
2093 /* step 2 */
2094 for(i=0; i<p_group_req->data.members.len; i++)
2095 {
2096 if(grp_owner == BCMBAL_GROUP_OWNER_UNICAST )
2097 {
2098 ret = rsc_mgr_gem_alloc_broadcast(p_group_req->data.members.val[i].intf_id,
2099 &p_group_req->data.members.val[i].svc_port_id,
2100 1, /* request gem range */
2101 NULL);
2102 }
2103 else if (grp_owner == BCMBAL_GROUP_OWNER_MULTICAST)
2104 {
2105 ret = rsc_mgr_gem_alloc_multicast(p_group_req->data.members.val[i].intf_id,
2106 &p_group_req->data.members.val[i].svc_port_id,
2107 1, /* request gem range */
2108 NULL);
2109 }
2110 else
2111 {
2112 ret = BCM_ERR_PARM;
2113 }
2114 if(BCM_ERR_OK != ret)
2115 {
2116 break;
2117 }
2118 }
2119 if(BCM_ERR_OK != ret)
2120 {
2121 BCM_LOG(ERROR, log_id_group, "Failed to alloc group GEM, interface=%d\n", p_group_req->data.members.val[i].intf_id);
2122 break;
2123 }
2124 /* step 3 */
2125 if(BCM_ERR_OK != (ret = sw_util_group_set(p_group, BAL_UTIL_OPER_GROUP_SET)))
2126 {
2127 BCM_LOG(ERROR, log_id_group,
2128 "error %s while updating group GEM in switch\n", bcmos_strerror(ret));
2129 break;
2130 }
2131 /* step 4 - request no indicaiton send back */
2132 if(BCM_ERR_OK != (ret = mac_util_group_set(p_group, BAL_UTIL_OPER_GROUP_SET, BCMOS_FALSE)))
2133 {
2134 BCM_LOG(ERROR, log_id_group,
2135 "error %s while updating group GEM in mac \n", bcmos_strerror(ret));
2136 break;
2137 }
2138 /* step 5 - flip back */
2139 BCMBAL_CFG_PROP_SET(p_group_cur, group, owner, grp_owner);
2140 BCMBAL_CFG_PROP_SET(p_group_cur, group, members_cmd, BAL_UTIL_OPER_GROUP_SET);
2141 p_group_cur->data.members.len = p_group_req->data.members.len;
2142 p_group_cur->data.members.val = p_group_req->data.members.val;
2143
2144 p_group_req->data.members.len = 0;
2145 p_group_req->data.members.val = NULL;
2146
2147 }while(0);
2148 }
2149 else
2150 {
2151 /* if GROUP already has owner , make sure it is the same type */
2152 if ( grp_owner != p_group->current_group_info.data.owner)
2153 {
2154 BCM_LOG(ERROR, log_id_group,
2155 " group already has owner %d, can not reassign to %d \n", p_group->current_group_info.data.owner, grp_owner);
2156 ret = BCM_ERR_INTERNAL;
2157 }
2158 }
2159
2160 return ret;
2161}
2162/*@}*/