blob: e44a574d9f0a1855207ca95aa614832f0df538f0 [file] [log] [blame]
Shad Ansari2f7f9be2017-06-07 13:34:53 -07001/******************************************************************************
2 *
3 * <:copyright-BRCM:2016:DUAL/GPL:standard
4 *
5 * Copyright (c) 2016 Broadcom
6 * All Rights Reserved
7 *
8 * Unless you and Broadcom execute a separate written software license
9 * agreement governing use of this software, this software is licensed
10 * to you under the terms of the GNU General Public License version 2
11 * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
12 * with the following added to such license:
13 *
14 * As a special exception, the copyright holders of this software give
15 * you permission to link this software with independent modules, and
16 * to copy and distribute the resulting executable under terms of your
17 * choice, provided that you also meet, for each linked independent
18 * module, the terms and conditions of the license of that module.
19 * An independent module is a module which is not derived from this
20 * software. The special exception does not apply to any modifications
21 * of the software.
22 *
23 * Not withstanding the above, under no circumstances may you combine
24 * this software in any way with any other Broadcom software provided
25 * under a license other than the GPL, without Broadcom's express prior
26 * written consent.
27 *
28 * :>
29 *
30 *****************************************************************************/
31
32/**
33 * @file bal_mac_util_common_itu_pon.c
34 *
35 * @brief mac util interfaces definition used by Bal Core, for ITU PON flavors : GPON, XG-PON1, XGS-PON , NG-PON2
36 *
37 * This file expose the APIs to the core to configure the mac
38 * with regarding to the operation of access terminal, interface, subscriber terminal and flow.
39 *
40 * @addtogroup mac_util
41 */
42
43/*@{*/
44
45#include <bal_mac_util.h>
46#include <bal_mac_util_common_itu_pon.h>
47#include <bcm_topo.h>
48
49
50
51/**
52 * @brief get string for the indication object type
53 */
54char *mac_util_indication_get_obj_type_str(bcmolt_obj_id obj_type, mac_util_ind_obj_and_handlers handlers[], size_t handlers_size)
55{
56 return _mac_util_get_obj_type_str_for_indications(obj_type, handlers, handlers_size);
57}
58
59
60/**
61 * @brief handle indications for any PON ITU flavor.
62 */
63bcmos_errno mac_util_handle_indication(bcmolt_devid device_id, bcmolt_msg *p_msg, mac_util_ind_obj_and_handlers handlers[], size_t handlers_size)
64{
65 int i = 0;
66 for(i=0; i < handlers_size; i++)
67 {
68 if(p_msg->obj_type == handlers[i].obj_type)
69 {
70 if(NULL != handlers[i].ind_handler)
71 {
72 return handlers[i].ind_handler(device_id, p_msg);
73 }
74 }
75 }
76 /* log an error if unhandled */
77 return BCM_ERR_INTERNAL;
78}
79
80
81
82/**
83 * @brief checks if a gem port is configured in OLT already for the same PON If and ONU
84 *
85 * @param svc_port_id gem port
86 * @param if_id PON NI
87 * @param onu_id ONU Id
88 * @param is_config_required TRUE/FALSE
89 * @param is_wait_for_indication TRUE/FALSE
90 *
91 * @return bcmos_errno
92 *
93 * @todo with multi-thread support in future, the code from checking the maple object
94 * to the actual config will need to be atomic(i.e. using mutex). This, to avoid closely parallel threads
95 * from getting a state of gem slightly before a new config another thread would make on the same gem,
96 * before this thread could configure it. This applies to both gem and alloc id checks.
97 *
98 */
99static bcmos_errno maple_mac_check_gem_port_id_config(uint16_t svc_port_id, uint32_t if_id, uint32_t onu_id,
100 bcmos_bool *is_config_required, bcmos_bool *is_wait_for_indication)
101{
102 bcmos_errno rc = BCM_ERR_OK;
103 bcm_topo_pon_sub_family pon_sub_family;
104 bcmos_bool is_configured = BCMOS_FALSE, is_activated = BCMOS_FALSE;
105
106 /* assume config is not required, if there is an error */
107 *is_config_required = BCMOS_FALSE;
108 *is_wait_for_indication = BCMOS_FALSE;
109
110 pon_sub_family = bcm_topo_pon_get_pon_sub_family(if_id);
111 switch(pon_sub_family)
112 {
113 case BCM_TOPO_PON_SUB_FAMILY_GPON:
114 {
115 rc = maple_gpon_mac_check_gem_port_id(if_id, onu_id, svc_port_id, &is_configured, &is_activated);
116 }
117 break;
118
119 case BCM_TOPO_PON_SUB_FAMILY_XGPON:
120 {
121 rc = maple_xgpon_mac_check_gem_port_id(if_id, onu_id, svc_port_id, &is_configured, &is_activated);
122 }
123 break;
124
125 default:
126 {
127 rc = BCM_ERR_NOT_SUPPORTED;
128 }
129 }
130
131 if(BCM_ERR_OK != rc)
132 {
133 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
134 return rc;
135 }
136 *is_config_required = !is_configured;
137 *is_wait_for_indication = !is_activated;
138
139 if(BCMOS_FALSE == *is_config_required)
140 {
141 BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
142 "%s: gem port id is already configured: if_id = %d onu_id = %d svc_port_id = %d is_wait_for_indication = %s\n",
143 __FUNCTION__,
144 if_id, onu_id,svc_port_id,
145 (*is_wait_for_indication == BCMOS_TRUE ? "TRUE":"FALSE"));
146 }
147
148 return rc;
149}
150
151
152/**
153 * @brief Checks if a gem port needs to be actually deconfigured.
154 * This would be used during flow remove.
155 *
156 * @param svc_port_id gem port
157 * @param if_id PON NI
158 * @param onu_id ONU Id
159 * @param is_deconfig_required TRUE/FALSE
160 * @param is_wait_for_indication TRUE/FALSE
161 *
162 * @return bcmos_errno
163 */
164static bcmos_errno maple_mac_check_gem_port_id_deconfig(uint16_t svc_port_id, uint32_t if_id, uint32_t onu_id,
165 bcmos_bool *is_deconfig_required, bcmos_bool *is_wait_for_indication)
166{
167 bcmos_errno rc = BCM_ERR_OK;
168 uint32_t ref_count = 0;
169 bcm_topo_pon_mode pon_mode;
170 bcmos_bool is_configured = BCMOS_FALSE, is_activated = BCMOS_FALSE;
171
172 /* assume De-config not required, in case of an error */
173 *is_deconfig_required = BCMOS_FALSE;
174 *is_wait_for_indication = BCMOS_FALSE;
175
176 pon_mode = bcm_topo_pon_get_pon_mode(if_id);
177 if(pon_mode == BCM_TOPO_PON_MODE_GPON)
178 {
179 rc = maple_gpon_mac_check_gem_port_id(if_id, onu_id, svc_port_id, &is_configured, &is_activated);
180 }
181 else if(BCM_TOPO_PON_SUB_FAMILY_XGPON == bcm_topo_pon_get_pon_sub_family(if_id))
182 {
183 rc = maple_xgpon_mac_check_gem_port_id(if_id, onu_id, svc_port_id, &is_configured, &is_activated);
184 }
185 else
186 {
187 rc = BCM_ERR_NOT_SUPPORTED;
188 }
189
190 if(BCM_ERR_OK != rc)
191 {
192 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
193 return rc;
194 }
195
196 if(!is_configured)
197 {
198 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
199 "%s error in gpon gem port state: svc_port_id = %d if_id = %d onu_id = %d, gem state: NOT_CONFIGURED\n",
200 __FUNCTION__,
201 svc_port_id, if_id, onu_id);
202
203 return BCM_ERR_INTERNAL;
204 }
205
206
207 /** First: Check if gem deconfig is required:
208 * gem deconfig is not needed if other flows are still using the same gem, or it is already being deconfigured.
209 */
210#if RSRC_MGR_KEEPS_FLOW_LIST_PER_GEM
211 /** @todo the rsrc mgr ref count will not work for now since core fsm keeps the flow with admin down,
212 * though mac util does a clear on the gem.
213 */
214 /* get the ref count for the gem from rsc mgr */
215 rc = rsc_mgr_gem_lookup(if_id, svc_port_id, &ref_count);
216 if(BCM_ERR_OK != rc)
217 {
218 return BCM_ERR_PARM;
219 }
220#else
221 rc = _mac_util_db_flow_count_w_gem(if_id, svc_port_id, &ref_count);
222 if(BCM_ERR_OK != rc)
223 {
224 return rc;
225 }
226#endif
227
228 /* if more than 1 flow is using the gem in whatever state, skip deconfig */
229 if(1 < ref_count)
230 {
231 *is_deconfig_required = BCMOS_FALSE;
232 }
233 else
234 {
235 *is_deconfig_required = BCMOS_TRUE;
236 }
237
238 /* Gem port configuration indications are available on GPON only */
239 if(pon_mode == BCM_TOPO_PON_MODE_GPON)
240 {
241 /** Next: Check if need to wait for indication */
242 if(BCMOS_TRUE == *is_deconfig_required)
243 {
244 if(!is_activated)
245 {
246 *is_wait_for_indication = BCMOS_FALSE;
247 }
248 else
249 {
250 *is_wait_for_indication = BCMOS_TRUE;
251 }
252 }
253 else
254 {
255 *is_wait_for_indication = BCMOS_FALSE;
256
257 }
258 }
259 else
260 {
261 *is_wait_for_indication = BCMOS_FALSE;
262 }
263
264
265 if(BCMOS_FALSE == *is_deconfig_required)
266 {
267 BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
268 "Skip gem port deconfig: is_deconfig_required = %s, is_wait_for_indication = %s, svc_port_id = %d if_id = %d onu_id = %d, [ref_count=%d, gem_is configured=%d, gem_is_activated=%d]\n",
269 (*is_deconfig_required == BCMOS_TRUE ? "TRUE":"FALSE"),
270 (*is_wait_for_indication == BCMOS_TRUE ? "TRUE":"FALSE"),
271 svc_port_id, if_id, onu_id,
272 ref_count, is_configured, is_activated);
273 }
274
275 return rc;
276}
277
278
279/**
280 * @brief maple_gem_port_id_add
281 *
282 * This routine is used for configuring at maple a specific gem port id on a given pon interface
283 * and assign it to a given onu id
284 * currently all sla properties are hard coded
285 *
286 * @param svc_port_id the gem port id
287 * @param if_id the interface id
288 * @param onu_id the onu id it will assign to
289 *
290 * @return bcmos_errno
291 */
292static bcmos_errno maple_gem_port_id_add(uint16_t svc_port_id, uint32_t if_id, uint32_t onu_id)
293{
294 bcmos_errno rc = BCM_ERR_OK;
295 bcmolt_gem_port_configuration configuration = {};
296 bcm_topo_pon_mode pon_mode;
297
298 if(onu_id < MAC_UTIL_DUMMY_ONU_ID_FOR_MULTICAST_GEM)
299 {
300 configuration.direction = BCMOLT_GEM_PORT_DIRECTION_BIDIRECTIONAL;
301 configuration.type = BCMOLT_GEM_PORT_TYPE_UNICAST;
302 }
303 else
304 {
305 configuration.direction = BCMOLT_GEM_PORT_DIRECTION_DOWNSTREAM;
306 configuration.type = BCMOLT_GEM_PORT_TYPE_MULTICAST;
307 }
308
309 pon_mode = bcm_topo_pon_get_pon_mode(if_id);
310 if(pon_mode == BCM_TOPO_PON_MODE_GPON)
311 {
312 rc = maple_gpon_gem_port_id_add(if_id, svc_port_id, onu_id, &configuration);
313 }
314 else if(BCM_TOPO_PON_SUB_FAMILY_XGPON == bcm_topo_pon_get_pon_sub_family(if_id))
315 {
316 rc = maple_xgpon_gem_port_id_add(if_id, svc_port_id, onu_id, &configuration);
317 }
318 else
319 {
320 rc = BCM_ERR_NOT_SUPPORTED;
321 }
322
323 if(BCM_ERR_OK != rc)
324 {
325 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
326 }
327
328 return rc;
329}
330
331
332/**
333 * @brief maple_gem_port_id_remove
334 *
335 * This routine is used Clear a specific gem port id config in OLT on a given pon interface.
336 *
337 * @param svc_port_id the gem port id
338 * @param if_id the interface id
339 *
340 * @return bcmos_errno
341 *
342 * @todo do we need to fill in all parameters to disable GEM or just the gem key ?
343 */
344static bcmos_errno maple_gem_port_id_remove(uint16_t svc_port_id, uint32_t if_id)
345{
346 bcmos_errno rc = BCM_ERR_OK;
347 bcm_topo_pon_mode pon_mode;
348
349 pon_mode = bcm_topo_pon_get_pon_mode(if_id);
350 if(pon_mode == BCM_TOPO_PON_MODE_GPON)
351 {
352 rc = maple_gpon_gem_port_id_remove(if_id, svc_port_id);
353 }
354 else if(BCM_TOPO_PON_SUB_FAMILY_XGPON == bcm_topo_pon_get_pon_sub_family(if_id))
355 {
356 rc = maple_xgpon_gem_port_id_remove(if_id, svc_port_id);
357 }
358 else
359 {
360 rc = BCM_ERR_NOT_SUPPORTED;
361 }
362
363 if(BCM_ERR_OK != rc)
364 {
365 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
366 "Failed to clear gem port configuration(%s) in OLT\n",
367 bcmos_strerror(rc));
368 }
369
370 return rc;
371}
372
373
374/**
375 * @brief checks if a alloc id is configured in OLT already for the same PON If and ONU
376 *
377 * @param agg_id alloc id
378 * @param if_id PON NI
379 * @param onu_id ONU Id
380 * @param p_alloc_id_state alloc id current state
381 *
382 * @return bcmos_errno
383 */
384static bcmos_errno maple_mac_check_alloc_id_state(uint16_t agg_id, uint32_t if_id, uint32_t onu_id, bcmolt_alloc_state *p_alloc_id_state)
385{
386 bcmos_errno rc = BCM_ERR_OK;
387 bcm_topo_pon_mode pon_mode;
388
389 pon_mode = bcm_topo_pon_get_pon_mode(if_id);
390 if(pon_mode == BCM_TOPO_PON_MODE_GPON)
391 {
392 rc = maple_gpon_mac_get_alloc_id_config(if_id, onu_id, agg_id, p_alloc_id_state);
393 }
394 else if(BCM_TOPO_PON_SUB_FAMILY_XGPON == bcm_topo_pon_get_pon_sub_family(if_id))
395 {
396 rc = maple_xgpon_mac_get_alloc_id_config(if_id, onu_id, agg_id, p_alloc_id_state);
397 }
398 else
399 {
400 rc = BCM_ERR_NOT_SUPPORTED;
401 }
402
403 if(BCM_ERR_OK != rc)
404 {
405 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
406 return rc;
407 }
408
409 return rc;
410}
411
412
413
414static bcmos_errno maple_mac_check_alloc_id_config(uint16_t agg_id, uint32_t if_id, uint32_t onu_id)
415{
416 bcmos_errno rc;
417 bcmolt_alloc_state alloc_id_state;
418
419
420 rc = maple_mac_check_alloc_id_state(agg_id, if_id, onu_id, &alloc_id_state);
421 if(BCM_ERR_OK != rc)
422 {
423 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s failed with error %s\n",
424 __FUNCTION__, bcmos_strerror(rc));
425 return rc;
426 }
427 if(BCMOLT_ALLOC_STATE_NOT_CONFIGURED != alloc_id_state)
428 rc = BCM_ERR_PARM;
429 return rc;
430}
431static bcmos_errno maple_mac_check_alloc_id_active(uint16_t agg_id, uint32_t if_id, uint32_t onu_id, bcmos_bool *is_alloc_id_wait_for_ind)
432{
433 bcmos_errno rc;
434 bcmolt_alloc_state alloc_id_state;
435
436 rc = maple_mac_check_alloc_id_state(agg_id, if_id, onu_id, &alloc_id_state);
437 if(BCM_ERR_OK != rc)
438 {
439 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
440 return rc;
441 }
442 *is_alloc_id_wait_for_ind = BCMOLT_ALLOC_STATE_ACTIVE != alloc_id_state;
443 return rc;
444}
445
446/**
447 * @brief helper function to check flow with double tag and with action remove outer tag.
448 * Used for validation as well as flow config.
449 *
450 * @param p_flow_req A pointer to a flow object
451 *
452 * @return bcmos_errno
453 */
454bcmos_bool mac_util_check_flow_is_double_tag_remove_o_tag(const bcmbal_flow_cfg *p_flow_req)
455{
456 if(NULL != p_flow_req)
457 {
458 if(BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_req->key.flow_type &&
459 BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow_req, flow, action) &&
460 (p_flow_req->data.action.cmds_bitmask & BCMBAL_ACTION_CMD_ID_REMOVE_OUTER_TAG) &&
461 (p_flow_req->data.classifier.pkt_tag_type == BCMBAL_PKT_TAG_TYPE_DOUBLE_TAG))
462 {
463 return BCMOS_TRUE;
464 }
465 }
466
467 return BCMOS_FALSE;
468}
469
470
471/**
472 * @brief maple_mac_unicast_flow_add
473 *
474 * This routine is used to configure a flow at the internal flows list to
475 * handle incoming and outgoing relevant indications.
476 * the flow svc_port is defined using a single gem port by a base_gem_port
477 * and single pbit(=0 in case of pbit is not available)
478 * it will also configure gem port and alloc id at the device if required.
479 *
480 *
481 * @param if_id - the pon interface id
482 * @param onu_id - the onu id
483 * @param agg_id - the alloc id
484 * @param sla - the sla configuration of the alloc id
485 *
486 * @return bcmos_errno
487 */
488bcmos_errno maple_mac_agg_port_add(uint32_t if_id, uint32_t onu_id, uint16_t agg_id, bcmolt_pon_alloc_sla sla)
489{
490 bcmos_errno rc = BCM_ERR_OK;
491 bcm_topo_pon_mode pon_mode;
492 do
493 {
494 rc = maple_mac_check_alloc_id_config(agg_id, if_id, onu_id);
495
496 if(BCM_ERR_OK != rc)
497 {
498 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
499 "Failed to query alloc state\n");
500 break;
501 }
502
503 pon_mode = bcm_topo_pon_get_pon_mode(if_id);
504 if(pon_mode == BCM_TOPO_PON_MODE_GPON)
505 {
506 rc = maple_gpon_us_alloc_id_add(if_id, onu_id, agg_id, sla);
507 }
508 else if(BCM_TOPO_PON_SUB_FAMILY_XGPON == bcm_topo_pon_get_pon_sub_family(if_id))
509 {
510 rc = maple_xgpon_us_alloc_id_add(if_id, onu_id, agg_id, sla);
511 }
512 else
513 {
514 rc = BCM_ERR_NOT_SUPPORTED;
515 }
516
517 if(BCM_ERR_OK != rc)
518 {
519 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
520 }
521 }while(0);
522 return rc;
523}
524
525/**
526 * @brief maple_mac_agg_port_remove
527 *
528 * This routine is used for De-configuring at maple a specific alloc_id on a given pon interface
529 *
530 * @param if_id - the pon interface id
531 *
532 * @param agg_id - the alloc id
533 *
534 * @return bcmos_errno
535 */
536bcmos_errno maple_mac_agg_port_remove(uint32_t if_id, uint16_t agg_id)
537{
538 bcmos_errno rc = BCM_ERR_OK;
539 bcm_topo_pon_mode pon_mode;
540
541 pon_mode = bcm_topo_pon_get_pon_mode(if_id);
542 if(pon_mode == BCM_TOPO_PON_MODE_GPON)
543 {
544 rc = maple_gpon_us_alloc_id_remove(if_id, agg_id);
545 }
546 else if(BCM_TOPO_PON_SUB_FAMILY_XGPON == bcm_topo_pon_get_pon_sub_family(if_id))
547 {
548 rc = maple_xgpon_us_alloc_id_remove(if_id, agg_id);
549 }
550 else
551 {
552 rc = BCM_ERR_NOT_SUPPORTED;
553 }
554
555 if(BCM_ERR_OK != rc)
556 {
557 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
558 }
559
560 return rc;
561}
562
563bcmos_errno maple_mac_unicast_flow_add(bcmbal_flow_cfg *p_flow, uint16_t pbit, uint16_t per_flow_mode_vlan_id, bal_util_oper_flow op_type,
564 flow_list_entry **pp_mac_util_flow_entry)
565{
566 bcmos_errno rc = BCM_ERR_OK;
567 bcmos_bool is_gem_config_required = BCMOS_TRUE;
568 bcmos_bool is_gem_wait_for_ind = BCMOS_TRUE , is_alloc_id_wait_for_ind = BCMOS_TRUE;
569 flow_list_entry *p_new_flow_entry = NULL;
570
571
572 *pp_mac_util_flow_entry = NULL;
573 do
574 {
575 /* Allocate & add the new flow to the flow list to follow indications/gem reuse/alloc reuse */
576 p_new_flow_entry = _mac_util_db_flow_alloc();
577 if(NULL == p_new_flow_entry)
578 {
579 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
580 "Failed to allocate the flow entry\n");
581 rc = BCM_ERR_NOMEM;
582 break;
583 }
584
585 memcpy(&p_new_flow_entry->bal_flow_key, &p_flow->key,
586 sizeof(bcmbal_flow_key));
587 p_new_flow_entry->if_id = p_flow->data.access_int_id;
588 p_new_flow_entry->sub_term_id = p_flow->data.sub_term_id;
589 p_new_flow_entry->svc_port_id = p_flow->data.svc_port_id;
590 if(BCMBAL_FLOW_TYPE_UPSTREAM == p_flow->key.flow_type)
591 {
592 p_new_flow_entry->agg_id = p_flow->data.agg_port_id;
593 }
594 p_new_flow_entry->vlan_id = per_flow_mode_vlan_id;
595 p_new_flow_entry->is_waiting_for_svc_port_active = BCMOS_TRUE;
596 p_new_flow_entry->ind_sent = BAL_UTIL_FLOW_IND_SEND_NONE;
597 p_new_flow_entry->is_configuration_completed = BCMOS_FALSE;
598
599
600 /* save the operation type so as to report back the right indication type to core on an indication from Maple */
601 p_new_flow_entry->op_type = op_type;
602
603 /* check if gem configuration is required or it was already configured,
604 could happen in case of us flow configured after a ds flow(with the same flow_id)
605 and vise versus, or if that is a case of different flow sharing the same gem port id */
606 if(BCMOS_TRUE == is_gem_config_required)
607 {
608 rc = maple_mac_check_gem_port_id_config(p_new_flow_entry->svc_port_id,
609 p_new_flow_entry->if_id,
610 p_new_flow_entry->sub_term_id,
611 &is_gem_config_required,
612 &is_gem_wait_for_ind);
613 if(BCM_ERR_OK != rc)
614 {
615 /* free the flow entry */
616 _mac_util_db_flow_free(p_flow->data.access_int_id, p_new_flow_entry);
617 rc = BCM_ERR_PARM;
618 break;
619 }
620 /* set wait for ind flag */
621 p_new_flow_entry->is_waiting_for_svc_port_active = is_gem_wait_for_ind;
622 }
623
624 /* if that's an us flow, check if alloc configuration is required or it was already configured */
625 if(p_new_flow_entry->bal_flow_key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM)
626 {
627 rc = maple_mac_check_alloc_id_active(p_new_flow_entry->agg_id,
628 p_new_flow_entry->if_id,
629 p_new_flow_entry->sub_term_id,
630 &is_alloc_id_wait_for_ind);
631 if(BCM_ERR_OK != rc)
632 {
633 /* free the flow entry */
634 _mac_util_db_flow_free(p_flow->data.access_int_id, p_new_flow_entry);
635 rc = BCM_ERR_PARM;
636 break;
637 }
638 }
639
640 /* add the new flow to the flow DB */
641 rc = _mac_util_db_flow_add(p_flow->data.access_int_id, p_new_flow_entry);
642 if(BCM_ERR_OK != rc)
643 {
644 /* free the flow entry */
645 _mac_util_db_flow_free(p_flow->data.access_int_id, p_new_flow_entry);
646 break;
647 }
648
649 /* configure the gem port id if required */
650 if(BCMOS_TRUE == is_gem_config_required)
651 {
652 rc = maple_gem_port_id_add(p_new_flow_entry->svc_port_id, p_new_flow_entry->if_id, p_new_flow_entry->sub_term_id);
653 if(BCM_ERR_OK != rc)
654 {
655 break;
656 }
657 }
658
659 } while(0);
660
661 if(BCM_ERR_OK != rc)
662 {
663 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
664 "%s Failed: rc = %s(%d), flow Id/Type=%d/%d, pbit=%d, if_id=%d, sub_term_id=%d, "
665 "svc_port_id=%d, agg_id=%d, vlan_id=%d, op type=%s\n",
666 __FUNCTION__,
667 bcmos_strerror(rc), rc,
668 p_flow->key.flow_id, p_flow->key.flow_type, pbit,
669 p_flow->data.access_int_id, p_flow->data.sub_term_id,
670 p_flow->data.svc_port_id, p_flow->data.agg_port_id, per_flow_mode_vlan_id,
671 (BAL_UTIL_OPER_FLOW_ADD == op_type ? "FLOW_ADD":"INVALID"));
672 }
673
674 /* set the arg to return the local flow entry to caller */
675 *pp_mac_util_flow_entry = p_new_flow_entry;
676
677 return rc;
678}
679
680
681/**
682 * @brief utility routine to correctly assign the SLAs to new tm sched owned by agg port
683 * This routine adjusts the BW values to be aligned with 8KBytes/sec boundary. It also
684 * adjusts the difference between pbr & sbr to be at least 32KBytes/sec
685 *
686 * @param p_tm_sched_req new tm sched instance
687 * @param p_agg_sla pointer to the sla configuration
688 *
689 * @note For Maple to accept the sla config:
690 * (1) the sbr and pbr values from BAL user should be in increments of 256 KBits/sec.
691 * (2) Also, the sbr should be at least 256 Kbits/sec less than the pbr.
692 * (3) sbr value can be 0 or else at least 256 Kbits/sec
693 * (4) pbr value can be 256 Kbits/sec or above
694 *
695 * @note The SLA is used for the upstream alloc_id really, even though this is being called for downstream and upstream.
696 *
697 */
698void mac_util_assign_agg_port_sla(bcmbal_tm_sched_cfg *p_tm_sched_req, bcmolt_pon_alloc_sla *p_agg_sla)
699{
700
701 BUG_ON(NULL == p_tm_sched_req);
702
703 if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_tm_sched_req->data.rate,tm_shaping, sbr))
704 {
705 p_agg_sla->guaranteed_bw = KILOBITS_PER_SEC2BYTES_PER_SEC(p_tm_sched_req->data.rate.sbr);
706 /* Align the BW to 8KBytes granularity(always upward adjustment) */
707 p_agg_sla->guaranteed_bw = SLA_BW_NKBYTES_ALIGNED(p_agg_sla->guaranteed_bw, MAC_UTIL_PMDB(p_tm_sched_req->data.owner.u.agg_port.intf_id).sla_us_rate_factor);
708 if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_tm_sched_req->data.rate, tm_shaping, pbr))
709 {
710 p_agg_sla->maximum_bw = KILOBITS_PER_SEC2BYTES_PER_SEC(p_tm_sched_req->data.rate.pbr);
711 /* max rate should be bigger by 32KBytes/sec than guaranteed rate */
712 if(MAPLE_MIN_BYTES_PER_SEC_FOR_DEFAULT_ALLOC_ID >(p_agg_sla->maximum_bw - p_agg_sla->guaranteed_bw))
713 {
714 p_agg_sla->maximum_bw = p_agg_sla->guaranteed_bw + MAPLE_MIN_BYTES_PER_SEC_FOR_DEFAULT_ALLOC_ID;
715 }
716 else
717 {
718 /* Else, align the BW to 8KBytes granularity(always upward adjustment) */
719 p_agg_sla->maximum_bw = SLA_BW_NKBYTES_ALIGNED(p_agg_sla->maximum_bw, MAC_UTIL_PMDB(p_tm_sched_req->data.owner.u.agg_port.intf_id).sla_us_rate_factor);
720 }
721 }
722 else
723 {
724 /* max rate should be bigger by 32KBytes/sec than guaranteed rate */
725 p_agg_sla->maximum_bw = p_agg_sla->guaranteed_bw + MAPLE_MIN_BYTES_PER_SEC_FOR_DEFAULT_ALLOC_ID;
726 }
727 }
728 else if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_tm_sched_req->data.rate, tm_shaping, pbr))
729 {
730 p_agg_sla->maximum_bw = KILOBITS_PER_SEC2BYTES_PER_SEC(p_tm_sched_req->data.rate.pbr);
731
732 /* Align the BW to 8KBytes granularity(always upward adjustment) */
733 p_agg_sla->maximum_bw = SLA_BW_NKBYTES_ALIGNED(p_agg_sla->maximum_bw , MAC_UTIL_PMDB(p_tm_sched_req->data.owner.u.agg_port.intf_id).sla_us_rate_factor);
734 /* since only max_rate was specified, it is best effort, so set the min rate = 0 */
735 p_agg_sla->guaranteed_bw = 0;
736 }
737 else
738 {
739
740 /* Nothing is set, so assign the defaults(that suits GPON) times the SLA US rate factor(GPON=1, XG-PON1=2, XGS-PON,NG-PON2=8) */
741 p_agg_sla->guaranteed_bw = SLA_GUARANTEED_BW_DEFAULT_BYTES_PER_SEC * MAC_UTIL_PMDB(p_tm_sched_req->data.owner.u.agg_port.intf_id).sla_us_rate_factor;
742 p_agg_sla->maximum_bw = SLA_MAX_BW_DEFAULT_BYTES_PER_SEC * MAC_UTIL_PMDB(p_tm_sched_req->data.owner.u.agg_port.intf_id).sla_us_rate_factor;
743 }
744 if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_tm_sched_req->data.tcont_sla, tm_tcont_sla, nrt_cbr))
745 {
746 /* Align the BW to 8KBytes granularity(always upward adjustment) */
747 p_agg_sla->cbr_nrt_bw = SLA_BW_NKBYTES_ALIGNED(p_tm_sched_req->data.tcont_sla.nrt_cbr, MAC_UTIL_PMDB(p_tm_sched_req->data.owner.u.agg_port.intf_id).sla_us_rate_factor);
748 }
749 else
750 {
751 p_agg_sla->cbr_nrt_bw = 0;
752 }
753
754 if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_tm_sched_req->data.tcont_sla, tm_tcont_sla, rt_cbr))
755 {
756 /* Align the BW to 8KBytes granularity(always upward adjustment) */
757 p_agg_sla->cbr_rt_bw = SLA_BW_NKBYTES_ALIGNED(p_tm_sched_req->data.tcont_sla.rt_cbr, MAC_UTIL_PMDB(p_tm_sched_req->data.owner.u.agg_port.intf_id).sla_us_rate_factor);
758 }
759 else
760 {
761 p_agg_sla->cbr_rt_bw = 0;
762 }
763
764 if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_tm_sched_req->data.tcont_sla, tm_tcont_sla, extra_bw_elig))
765 {
766 p_agg_sla->additional_bw_eligibility = p_tm_sched_req->data.tcont_sla.extra_bw_elig;
767 }
768 else
769 {
770 p_agg_sla->additional_bw_eligibility = BCMOLT_ADDITIONAL_BW_ELIGIBILITY_BEST_EFFORT;
771 }
772
773 if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_tm_sched_req->data.tcont_sla, tm_tcont_sla, rt_profile))
774 {
775 p_agg_sla->cbr_rt_ap_index = p_tm_sched_req->data.tcont_sla.rt_profile;
776 }
777 else
778 {
779 p_agg_sla->cbr_rt_ap_index = 0;
780 }
781
782 if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_tm_sched_req->data.tcont_sla, tm_tcont_sla, nrt_profile))
783 {
784 p_agg_sla->cbr_nrt_ap_index = p_tm_sched_req->data.tcont_sla.nrt_profile;
785 }
786 else
787 {
788 p_agg_sla->cbr_nrt_ap_index = 0;
789 }
790
791 p_agg_sla->alloc_type = BCMOLT_ALLOC_TYPE_NSR;
792 p_agg_sla->cbr_rt_compensation = BCMOS_FALSE;
793 p_agg_sla->weight = 0;
794 p_agg_sla->priority = 0;
795
796}
797
798
799/**
800 * @brief mark_flow_config_complete
801 *
802 * This routine is used to mark all related flow entries, that the flow configuration requests to device was completed,
803 * meaning now it is ready to be checked for configuration completion indication from device, and to be indicated to core.
804 *
805 * @param p_flow_entry pointer to mac util flow instance
806 *
807 * @return void
808 */
809void mac_util_mark_flow_config_complete(flow_list_entry *p_flow_entry)
810{
811 if(NULL != p_flow_entry)
812 {
813 p_flow_entry->is_configuration_completed = BCMOS_TRUE;
814 }
815}
816
817
818/**
819 * @brief maple_mac_broadcast_flow_add
820 *
821 * This routine is used for setting required configuration for a new broadcast flow :
822 * gem port id, iwf ds flow and configure it as a miss fallback of its assigned interface.
823 * it will also create an entry for the new flow at the internal flows list to follow relevant indication
824 *
825 * @param p_flow A pointer to a flow object
826 * @param per_flow_mode_vlan_id vlan id used for GEM port mapping in per flow mode
827 * @param op_type flow "add" or "modify"
828 * @param pp_mac_util_flow_entry addr of pointer to flow entry in mac util DB
829 *
830 * @return bcmos_errno
831 */
832bcmos_errno maple_mac_broadcast_flow_add(bcmbal_flow_cfg *p_flow, uint16_t per_flow_mode_vlan_id, bal_util_oper_flow op_type,
833 flow_list_entry **pp_mac_util_flow_entry)
834{
835 bcmos_errno rc = BCM_ERR_PARM;
836 flow_list_entry *p_new_flow_entry = NULL;
837 bcmolt_gpon_iwf_ds_ingress_flow_key in_key;
838 bcmolt_gpon_iwf_ds_ingress_flow_cfg in_cfg;
839 bcmolt_gpon_iwf_ds_egress_flow_key egr_key;
840 bcmolt_gpon_iwf_ds_egress_flow_cfg egr_cfg;
841 bcmolt_gpon_iwf_key iwf_key;
842 bcmolt_gpon_iwf_cfg get_iwf_cfg, set_iwf_cfg;
843 bcmolt_mac_table_configuration mac_table_configuration;
844 bcmos_bool is_gem_config_required = BCMOS_TRUE;
845 bcmos_bool is_gem_wait_for_ind = BCMOS_TRUE;
846 bcmolt_devid device_id;
847 uint32_t physical_if_id;
848 bcm_topo_pon_mode pon_mode;
849
850 *pp_mac_util_flow_entry = NULL;
851
852 /* add the new flow to the flow list */
853 p_new_flow_entry = _mac_util_db_flow_alloc();
854 if(NULL == p_new_flow_entry)
855 {
856 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
857 "Failed to allocate the flow entry\n");
858 return BCM_ERR_NOMEM;
859 }
860
861 memcpy(&p_new_flow_entry->bal_flow_key, &p_flow->key, sizeof(bcmbal_flow_key));
862 p_new_flow_entry->if_id = p_flow->data.access_int_id;
863 p_new_flow_entry->sub_term_id = p_flow->data.sub_term_id;
864 p_new_flow_entry->svc_port_id = p_flow->data.svc_port_id;
865 /* broadcast gem are active by default once they are set, no indications */
866 p_new_flow_entry->is_waiting_for_svc_port_active = BCMOS_FALSE;
867 p_new_flow_entry->ind_sent = BAL_UTIL_FLOW_IND_SEND_NONE;
868 p_new_flow_entry->is_configuration_completed = BCMOS_FALSE;
869
870 /* make sure the broadcast gem port is not already configured / assigned to any onu on the if */
871 rc = maple_mac_check_gem_port_id_config(p_new_flow_entry->svc_port_id,
872 p_new_flow_entry->if_id,
873 p_new_flow_entry->sub_term_id,
874 &is_gem_config_required,
875 &is_gem_wait_for_ind);
876 if(BCM_ERR_OK != rc)
877 {
878 /* free the flow */
879 _mac_util_db_flow_free(p_flow->data.access_int_id, p_new_flow_entry);
880 return BCM_ERR_PARM;
881 }
882
883 if(BCMOS_FALSE == is_gem_config_required)
884 {
885 /* some error, can't have the broadcast flow already configured for the onu */
886 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
887 "Gem %d is already configured on if %d(assigned to onu_id %d)\n",
888 p_new_flow_entry->svc_port_id, p_new_flow_entry->if_id, p_new_flow_entry->sub_term_id);
889
890 /* free the flow */
891 _mac_util_db_flow_free(p_flow->data.access_int_id, p_new_flow_entry);
892 return BCM_ERR_PARM;
893 }
894
895 /* add the new flow to the local flows list */
896 rc = _mac_util_db_flow_add(p_flow->data.access_int_id, p_new_flow_entry);
897 if(BCM_ERR_OK != rc)
898 {
899 return rc;
900 }
901
902 /* a broadcast gem port is 'assigned' to the special MAC_UTIL_DUMMY_ONU_ID_FOR_MULTICAST_GEM onu id */
903 rc = maple_gem_port_id_add(p_new_flow_entry->svc_port_id, p_new_flow_entry->if_id, MAC_UTIL_DUMMY_ONU_ID_FOR_MULTICAST_GEM);
904 if(BCM_ERR_OK != rc)
905 {
906 return rc;
907 }
908
909 /* get physical interface from logical interface */
910 rc = bcm_topo_pon_get_logical2physical(p_flow->data.access_int_id, &device_id, &physical_if_id);
911 if(BCM_ERR_OK != rc)
912 {
913 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
914 "Failed to get physical if from logical if(%s)\n", bcmos_strerror(rc));
915 return rc;
916 }
917
918 /* Inter-working(IWF) stuff is relevant for GPON only */
919 pon_mode = bcm_topo_pon_get_pon_mode(p_flow->data.access_int_id);
920 if(pon_mode == BCM_TOPO_PON_MODE_GPON)
921 {
922 /* configure the ingress flow as default fallback ingress flow */
923 in_key.pon_ni = physical_if_id;
924 in_key.vlan_id = per_flow_mode_vlan_id;
925 BCMOLT_CFG_INIT(&in_cfg, gpon_iwf_ds_ingress_flow, in_key);
926 BCMOLT_CFG_PROP_SET(&in_cfg, gpon_iwf_ds_ingress_flow, mapping_method,
927 BCMOLT_VLAN_TO_FLOW_MAPPING_METHOD_MACPLUSVID);
928 BCMOLT_CFG_PROP_SET(&in_cfg, gpon_iwf_ds_ingress_flow, mapping_tag,
929 BCMOLT_MAPPING_TAG_METHOD_OUTER_VID);
930 BCMOLT_CFG_PROP_SET(&in_cfg, gpon_iwf_ds_ingress_flow, vlan_action, BCMOLT_DS_VLAN_ACTION_TRANSPARENT);
931
932
933 rc = bcmolt_cfg_set(device_id, &in_cfg.hdr);
934 if(BCM_ERR_OK != rc)
935 {
936 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
937 "Failed to configure ingress flow pon_ni = %d vlan_id = %d rc = %s(%d), err_text = %s\n",
938 in_key.pon_ni, in_key.vlan_id, bcmos_strerror(rc), rc, in_cfg.hdr.hdr.err_text);
939 return rc;
940 }
941
942 /* configure the egress flow as default fallback egress flow */
943 egr_key.pon_ni = physical_if_id;
944 egr_key.flow_id = p_flow->data.svc_port_id;
945
946 /* Configure DS egress handling: flow -> GEM */
947 BCMOLT_CFG_INIT(&egr_cfg, gpon_iwf_ds_egress_flow, egr_key);
948 BCMOLT_CFG_PROP_SET(&egr_cfg, gpon_iwf_ds_egress_flow, gem_port, p_flow->data.svc_port_id);
949 BCMOLT_CFG_PROP_SET(&egr_cfg, gpon_iwf_ds_egress_flow, pbit_control, BCMOS_FALSE);
950
951 rc = bcmolt_cfg_set(device_id, &egr_cfg.hdr);
952 if(BCM_ERR_OK != rc)
953 {
954 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
955 "Failed to configure egress flow pon_ni = %d, rc = %s(%d), err_text = %s\n",
956 egr_key.pon_ni, bcmos_strerror(rc), rc, egr_cfg.hdr.hdr.err_text);
957 return rc;
958 }
959
960 /* update the if miss fallback flow */
961 iwf_key.pon_ni = physical_if_id;
962 BCMOLT_CFG_INIT(&get_iwf_cfg, gpon_iwf, iwf_key);
963 BCMOLT_CFG_INIT(&set_iwf_cfg, gpon_iwf, iwf_key);
964
965 BCMOLT_CFG_PROP_GET(&get_iwf_cfg, gpon_iwf, all_properties);
966 rc = bcmolt_cfg_get(device_id, &get_iwf_cfg.hdr);
967 if(BCM_ERR_OK != rc)
968 {
969 return rc;
970 }
971
972 mac_table_configuration = get_iwf_cfg.data.mac_table_configuration;
973 mac_table_configuration.miss_fallback = BCMOLT_MAC_TABLE_MISS_FALLBACK_DEFAULT_FLOW;
974 mac_table_configuration.default_flow_id = egr_key.flow_id;
975 BCMOLT_CFG_PROP_SET(&set_iwf_cfg, gpon_iwf, mac_table_configuration, mac_table_configuration);
976
977 rc = bcmolt_cfg_set(device_id, &set_iwf_cfg.hdr);
978 if(BCM_ERR_OK != rc)
979 {
980 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
981 "Failed to configure iwf: pon_ni = %d, rc = %s(%d), err_text = %s\n",
982 iwf_key.pon_ni, bcmos_strerror(rc), rc, set_iwf_cfg.hdr.hdr.err_text);
983 return rc;
984 }
985 }
986
987 p_new_flow_entry->is_configuration_completed = BCMOS_TRUE;
988
989 if(BCM_ERR_OK != rc)
990 {
991 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
992 "%s Failed: rc = %s(%d), flow Id/Type=%d/%d, if_id=%d, sub_term_id=%d, "
993 "svc_port_id=%d, agg_id=%d, vlan_id=%d, op type=%s\n",
994 __FUNCTION__,
995 bcmos_strerror(rc), rc,
996 p_flow->key.flow_id, p_flow->key.flow_type,
997 p_flow->data.access_int_id, p_flow->data.sub_term_id,
998 p_flow->data.svc_port_id, p_flow->data.agg_port_id, per_flow_mode_vlan_id,
999 (BAL_UTIL_OPER_FLOW_ADD == op_type ? "FLOW_ADD": "INVALID"));
1000 }
1001
1002 /* set the arg to return the local flow entry to caller */
1003 *pp_mac_util_flow_entry = p_new_flow_entry;
1004
1005 return rc;
1006}
1007
1008
1009/**
1010 * @brief maple_mac_broadcast_flow_remove
1011 *
1012 * This routine is removes a broadcast flow from Maple
1013 *
1014 * @param p_flow A pointer to a flow object
1015 * @param per_flow_mode_vlan_id vlan id for per flow mode
1016 * @param op_type flow "remove" or "clear"
1017 * @param p_mac_util_flow_entry mac util flow entry
1018 *
1019 * @return bcmos_errno
1020 */
1021bcmos_errno maple_mac_broadcast_flow_remove(bcmbal_flow_cfg *p_flow, uint16_t per_flow_mode_vlan_id, bal_util_oper_flow op_type,
1022 flow_list_entry *p_mac_util_flow_entry)
1023{
1024 bcmos_errno rc = BCM_ERR_OK;
1025 flow_list_entry *p_target_flow_entry = NULL;
1026 bcmolt_gpon_iwf_ds_ingress_flow_key in_key;
1027 bcmolt_gpon_iwf_ds_ingress_flow_cfg in_cfg;
1028 bcmolt_gpon_iwf_ds_egress_flow_key egr_key;
1029 bcmolt_gpon_iwf_ds_egress_flow_cfg egr_cfg;
1030 bcmolt_gpon_iwf_key iwf_key;
1031 bcmolt_gpon_iwf_cfg set_iwf_cfg;
1032 bcmolt_devid device_id;
1033 uint32_t physical_if_id;
1034 bcm_topo_pon_mode pon_mode;
1035
1036 /* First find the flow in local database */
1037 p_target_flow_entry = _mac_util_db_flow_get_w_flow_key(p_flow->data.access_int_id, &(p_flow->key));
1038
1039 if(NULL == p_target_flow_entry)
1040 {
1041 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
1042 "%s: Failed to find the flow entry: flow id: %d, flow_type: %s\n",
1043 __FUNCTION__,
1044 p_flow->key.flow_id,
1045 (p_flow->key.flow_type == BCMBAL_FLOW_TYPE_BROADCAST ? "broadcast":"unicast/multicast"));
1046
1047 return BCM_ERR_NOENT;
1048 }
1049
1050
1051 /* broadcast gem are active by default once they are set, no indications */
1052 p_target_flow_entry->is_waiting_for_svc_port_active = BCMOS_FALSE;
1053 p_target_flow_entry->ind_sent = BAL_UTIL_FLOW_IND_SEND_NONE;
1054 p_target_flow_entry->is_configuration_completed = BCMOS_FALSE;
1055
1056
1057
1058 /* clear broadcast gem port */
1059 rc = maple_gem_port_id_remove(p_target_flow_entry->svc_port_id, p_target_flow_entry->if_id);
1060 if(BCM_ERR_OK != rc)
1061 {
1062 return rc;
1063 }
1064
1065 /* get physical interface from logical interface */
1066 rc = bcm_topo_pon_get_logical2physical(p_flow->data.access_int_id, &device_id, &physical_if_id);
1067 if(BCM_ERR_OK != rc)
1068 {
1069 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
1070 "Failed to get physical if from logical if(%s)\n", bcmos_strerror(rc));
1071 return rc;
1072 }
1073
1074 /* Inter-working(IWF) stuff is relevant for GPON only */
1075 pon_mode = bcm_topo_pon_get_pon_mode(p_flow->data.access_int_id);
1076 if(pon_mode == BCM_TOPO_PON_MODE_GPON)
1077 {
1078 /* clear the ingress flow as default fallback ingress flow */
1079 in_key.pon_ni = physical_if_id;
1080 in_key.vlan_id = per_flow_mode_vlan_id;
1081 BCMOLT_CFG_INIT(&in_cfg, gpon_iwf_ds_ingress_flow, in_key);
1082
1083 rc = bcmolt_cfg_clear(device_id, &in_cfg.hdr);
1084 if(BCM_ERR_OK != rc)
1085 {
1086 BCM_LOG(WARNING, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
1087 "Failed to clear ingress flow pon_ni = %d vlan_id = %d rc = %s(%d)\n",
1088 in_key.pon_ni, in_key.vlan_id, bcmos_strerror(rc), rc);
1089
1090 return rc;
1091 }
1092
1093 /* clear the egress flow as default fallback egress flow */
1094 egr_key.pon_ni = physical_if_id;
1095 egr_key.flow_id = p_flow->data.svc_port_id;
1096 /* Configure DS egress handling: flow -> GEM */
1097 BCMOLT_CFG_INIT(&egr_cfg, gpon_iwf_ds_egress_flow, egr_key);
1098
1099 rc = bcmolt_cfg_clear(device_id, &egr_cfg.hdr);
1100 if(BCM_ERR_OK != rc)
1101 {
1102 BCM_LOG(WARNING, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
1103 "Failed to clear egress flow pon_ni = %d gem port = %d rc = %s(%d)\n",
1104 egr_key.pon_ni, egr_key.flow_id, bcmos_strerror(rc), rc);
1105
1106 return rc;
1107 }
1108
1109 /* update the if miss fallback flow */
1110 iwf_key.pon_ni = physical_if_id;
1111 BCMOLT_CFG_INIT(&set_iwf_cfg, gpon_iwf, iwf_key);
1112
1113 rc = bcmolt_cfg_clear(device_id, &set_iwf_cfg.hdr);
1114 if(BCM_ERR_OK != rc)
1115 {
1116 BCM_LOG(WARNING, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
1117 "Failed to clear iwf flow pon_ni = %d rc = %s(%d)\n",
1118 iwf_key.pon_ni, bcmos_strerror(rc), rc);
1119
1120 return rc;
1121 }
1122 }
1123
1124 /* all De-config done */
1125 p_target_flow_entry->is_configuration_completed = BCMOS_TRUE;
1126
1127 if(BCM_ERR_OK != rc)
1128 {
1129 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
1130 "%s Failed: rc = %s(%d), flow Id/Type=%d/%d, if_id=%d, sub_term_id=%d, "
1131 "svc_port_id=%d, agg_id=%d, vlan_id=%d, op type=%s\n",
1132 __FUNCTION__,
1133 bcmos_strerror(rc), rc,
1134 p_flow->key.flow_id, p_flow->key.flow_type,
1135 p_flow->data.access_int_id, p_flow->data.sub_term_id,
1136 p_flow->data.svc_port_id, p_flow->data.agg_port_id, per_flow_mode_vlan_id,
1137 (BAL_UTIL_OPER_FLOW_REMOVE == op_type ? "FLOW_REMOVE":(BAL_UTIL_OPER_FLOW_CLEAR == op_type ? "FLOW_CLEAR":"INVALID")));
1138 }
1139
1140 return rc;
1141}
1142
1143
1144/**
1145 * @brief maple_mac_unicast_flow_remove
1146 *
1147 * This routine is used to De-configure a flow at the internal flows list to
1148 * handle incoming and outgoing relevant indications.
1149 * It will also De-configure gem port and alloc id at the device if required.
1150 *
1151 * @param p_flow Pointer to the flow info
1152 * @param op_type Flow operation type i.e. FLOW_REMOVE, FLOW_CLEAR
1153 * @param p_mac_util_flow_entry Pointer to mac util flow entry
1154 *
1155 * @return bcmos_errno
1156 */
1157bcmos_errno maple_mac_unicast_flow_remove(bcmbal_flow_cfg *p_flow, bal_util_oper_flow op_type,
1158 flow_list_entry *p_mac_util_flow_entry)
1159{
1160 bcmos_errno rc = BCM_ERR_OK;
1161 bcmos_bool is_gem_deconfig_required = BCMOS_TRUE;
1162 bcmos_bool is_gem_wait_for_ind = BCMOS_TRUE;
1163 flow_list_entry *p_target_flow_entry = NULL;
1164
1165 BUG_ON(NULL == p_mac_util_flow_entry);
1166
1167 do
1168 {
1169 p_target_flow_entry = p_mac_util_flow_entry;
1170 p_target_flow_entry->is_waiting_for_svc_port_active = BCMOS_TRUE;
1171 p_target_flow_entry->ind_sent = BAL_UTIL_FLOW_IND_SEND_NONE;
1172 p_target_flow_entry->is_configuration_completed = BCMOS_FALSE;
1173 /* save the operation type so as to report back the right indication type to core on an indication from Maple */
1174 p_target_flow_entry->op_type = op_type;
1175
1176 /* check if gem configuration is used by other flows still.
1177 could happen in case of us flow configured after a ds flow(with the same flow_id)
1178 and vice versa, or if that is a case of different flow sharing the same gem port id */
1179 if(BCMOS_TRUE == is_gem_deconfig_required)
1180 {
1181 rc = maple_mac_check_gem_port_id_deconfig(p_target_flow_entry->svc_port_id,
1182 p_target_flow_entry->if_id,
1183 p_target_flow_entry->sub_term_id,
1184 &is_gem_deconfig_required,
1185 &is_gem_wait_for_ind);
1186 /* set wait for ind flag */
1187 p_target_flow_entry->is_waiting_for_svc_port_active = is_gem_wait_for_ind;
1188
1189 if(BCM_ERR_OK != rc)
1190 {
1191 rc = BCM_ERR_PARM;
1192 break;
1193 }
1194 }
1195
1196 /* do not remove the flow entry from local flows list yet; wait for indication before removing */
1197 /* De-configure the gem port id if required */
1198 if(BCMOS_TRUE == is_gem_deconfig_required)
1199 {
1200 rc = maple_gem_port_id_remove(p_target_flow_entry->svc_port_id, p_target_flow_entry->if_id);
1201 if(BCM_ERR_OK != rc)
1202 {
1203 break;
1204 }
1205 }
1206 } while(0);
1207
1208 if(BCM_ERR_OK != rc)
1209 {
1210 if(!((BCM_ERR_NOENT == rc) &&(BAL_UTIL_OPER_FLOW_CLEAR == op_type)))
1211 {
1212 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
1213 "%s Failed: rc = %s(%d), flow Id/Type=%d/%d, if_id=%d, sub_term_id=%d, "
1214 "svc_port_id=%d, agg_id=%d, op type=%s\n",
1215 __FUNCTION__,
1216 bcmos_strerror(rc), rc,
1217 p_flow->key.flow_id, p_flow->key.flow_type,
1218 p_flow->data.access_int_id, p_flow->data.sub_term_id,
1219 p_flow->data.svc_port_id, p_flow->data.agg_port_id,
1220 (BAL_UTIL_OPER_FLOW_REMOVE == op_type ? "FLOW_REMOVE":(BAL_UTIL_OPER_FLOW_CLEAR == op_type ? "FLOW_CLEAR":"INVALID")));
1221 }
1222 }
1223
1224 return rc;
1225
1226}
1227bcmos_errno mac_util_update_flows_w_sub_term_update(uint32_t pon_if, uint32_t sub_term_id, maple_mac_check_gem_port_id check_gem_port_id_func, maple_mac_check_agg_port_id check_agg_port_id_func)
1228{
1229 flow_list_entry *p_current_entry = NULL;
1230 flow_list_entry *p_next_entry = NULL;
1231 bcmos_bool dummy;
1232 bcmos_bool is_gem_activated;
1233 bcmos_bool is_wait_for_gem_activated;
1234 bcmolt_alloc_state alloc_id_state;
1235 bcmos_errno rc = BCM_ERR_OK;
1236
1237 /*find all related flows, check their state and update if needed*/
1238 do
1239 {
1240 p_current_entry = _mac_util_db_flow_get_next_w_sub_term_id(pon_if, sub_term_id, p_current_entry, &p_next_entry);
1241 if(NULL == p_current_entry)
1242 break;
1243
1244 rc = check_gem_port_id_func(pon_if,sub_term_id, p_current_entry->svc_port_id, &dummy, &is_gem_activated);
1245 if(BCM_ERR_OK != rc)
1246 {
1247 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(pon_if), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
1248 continue;
1249 }
1250
1251 is_wait_for_gem_activated = !is_gem_activated;
1252
1253 if(p_current_entry->agg_id)
1254 {
1255 rc = check_agg_port_id_func(pon_if, sub_term_id, p_current_entry->agg_id, &alloc_id_state);
1256
1257 if(BCM_ERR_OK != rc)
1258 {
1259 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(pon_if), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
1260 continue;
1261 }
1262 }
1263
1264 /*if something was changed.....*/
1265 if(p_current_entry->is_waiting_for_svc_port_active != is_wait_for_gem_activated)
1266 {
1267 /*update current flow entry*/
1268 p_current_entry->is_waiting_for_svc_port_active = is_wait_for_gem_activated;
1269
1270 /*check if a flow became up*/
1271 if(p_current_entry->op_type == BAL_UTIL_OPER_FLOW_ADD
1272 &&(is_wait_for_gem_activated)
1273 && BAL_UTIL_FLOW_IND_SEND_FAIL != p_current_entry->ind_sent)
1274 {
1275 mac_util_report_flow_auto_ind(pon_if,p_current_entry->bal_flow_key,p_current_entry->op_type, BAL_UTIL_FLOW_IND_SEND_FAIL);
1276 p_current_entry->ind_sent = BAL_UTIL_FLOW_IND_SEND_FAIL;
1277 }
1278 /*check if a flow became down*/
1279 if(p_current_entry->op_type == BAL_UTIL_OPER_FLOW_ADD
1280 &&(!is_wait_for_gem_activated)
1281 &&(BAL_UTIL_FLOW_IND_SEND_SUCCESS != p_current_entry->ind_sent))
1282 {
1283 mac_util_report_flow_auto_ind(pon_if,p_current_entry->bal_flow_key,p_current_entry->op_type, BAL_UTIL_FLOW_IND_SEND_SUCCESS);
1284 p_current_entry->ind_sent = BAL_UTIL_FLOW_IND_SEND_SUCCESS;
1285 }
1286 }
1287 /* go through all flows(assigned with the given sub term) until break by
1288 _mac_util_db_flow_get_next_w_sub_term_id returning NULL*/
1289 }while(1);
1290
1291 return rc;
1292}
1293
1294/**
1295 * @brief agg_port set
1296 * @param p_tm_sched_req pointer to tm_sched request structure from core
1297 * @param op_type ADD, REMOVE or CLEAR
1298 * @param p_tm_sched_inst pointer to the core tm sched Object instance
1299 *
1300 * @return errno error
1301 *
1302 */
1303bcmos_errno maple_mac_util_agg_port_set(bcmbal_tm_sched_cfg *p_tm_sched_req, bal_util_oper_agg_port op_type, tm_sched_inst *p_tm_sched_inst)
1304{
1305 bcmos_errno ret = BCM_ERR_OK;
1306 do
1307 {
1308 /* Check the operation id */
1309 if((BAL_UTIL_OPER_AGG_PORT_ADD != op_type) &&
1310 (BAL_UTIL_OPER_AGG_PORT_REMOVE != op_type) &&
1311 (BAL_UTIL_OPER_AGG_PORT_REMOVE != op_type))
1312 {
1313 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_tm_sched_req->data.owner.u.agg_port.intf_id),
1314 "Unexpected mac_util agg port operation %d \n", op_type);
1315 ret = BCM_ERR_PARM;
1316 break;
1317 }
1318
1319 /* agg port Add or Modify */
1320 if(BAL_UTIL_OPER_AGG_PORT_ADD == op_type)
1321 {
1322 bcmolt_pon_alloc_sla agg_sla;
1323 mac_util_assign_agg_port_sla(p_tm_sched_req, &agg_sla);
1324 ret = maple_mac_agg_port_add(p_tm_sched_req->data.owner.u.agg_port.intf_id, p_tm_sched_req->data.owner.u.agg_port.sub_term_id, p_tm_sched_req->data.owner.u.agg_port.agg_port_id, agg_sla);
1325 }
1326 if(BAL_UTIL_OPER_AGG_PORT_REMOVE== op_type)
1327 {
1328 ret = maple_mac_agg_port_remove(p_tm_sched_req->data.owner.u.agg_port.intf_id, p_tm_sched_req->data.owner.u.agg_port.agg_port_id);
1329 }
1330
1331 }while(0);
1332 return ret;
1333
1334}
1335
1336/*@}*/