blob: cae8d2674c1f1983ecc2fd7624769144a10eadaa [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_epon.c
34 *
35 * @brief mac util interfaces definition used by Bal Core for EPON
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_epon.h>
47
48#if BAL_EPON_EXCLUDE
49#include <bcmolt_user_appl_epon_oam.h>
50#include <bal_oam_util.h>
51#include <bcmolt_eon.h>
52
53static bcmos_errno mac_util_indication_handle_for_epon_link (bcmolt_devid device_id, bcmolt_msg *p_msg);
54static bcmos_errno mac_util_indication_handle_for_epon_ni (bcmolt_devid device_id, bcmolt_msg *p_msg);
55
56
57/** @brief array stores the list of EPON related auto indications from Maple to subscribe */
58static mac_util_ind_obj_and_handlers mac_util_epon_ind_handlers[] =
59{
60 {BCMOLT_OBJ_ID_EPON_LINK, "BCMOLT_OBJ_ID_EPON_LINK", mac_util_indication_handle_for_epon_link},
61 {BCMOLT_OBJ_ID_EPON_NI, "BCMOLT_OBJ_ID_EPON_NI", mac_util_indication_handle_for_epon_ni}
62};
63
64
65/* epon onu entry structure */
66typedef enum
67{
68 OAM_PROVISION_STATE_IDLE = 0, /**< idle - did not start yet */
69 OAM_PROVISION_STATE_STARTED, /**< started - waiting to configure traffic cb to send bal core flow up indication */
70 OAM_PROVISION_STATE_COMPLETED, /**< completed successfully */
71 OAM_PROVISION_STATE_FAIL/**< failed to complete oam provision */
72} oam_provision_state;
73
74#define MAC_UTIL_MAX_WAITING_FLOWS_PER_MAC 16
75typedef struct epon_onu_list_entry epon_onu_list_entry;
76struct epon_onu_list_entry
77{
78 TAILQ_ENTRY(epon_onu_list_entry) next;
79 bcmbal_subscriber_terminal_key bal_onu_key; /* bal onu key */
80 bcmos_mac_address mac_address;
81 oam_provision_state oam_provision_state;
82 uint8_t waiting_flows_num;
83 bcmbal_flow_key flow_keys[MAC_UTIL_MAX_WAITING_FLOWS_PER_MAC];
84 uint32_t tunnel_id;
85};
86
87
88static TAILQ_HEAD(epon_onu_list_head_t, epon_onu_list_entry) epon_onu_list;
89
90
91/** @todo needs to be ported to the topology stub function */
92static bcmolt_devid maple_device_from_interface_get(uint16_t access_int_id)
93{
94 /* For now, all interfaces map to device 0 */
95 return (bcmolt_devid)0;
96
97}
98
99
100static void epon_onu_list_add(epon_onu_list_entry *epon_onu_entry);
101static epon_onu_list_entry *epon_onu_list_find_by_mac(const bcmos_mac_address *mac_address);
102static epon_onu_list_entry *epon_onu_list_find_by_key(bcmbal_subscriber_terminal_key *key);
103static void epon_onu_list_remove_by_key(bcmbal_subscriber_terminal_key *key);
104
105static void mac_util_configure_traffic_cb(void *context,
106 bcmolt_devid device_id,
107 bcmolt_epon_ni epon_ni,
108 const bcmos_mac_address *mac_address,
109 bcmos_errno result);
110
111static void mac_util_unconfigure_traffic_cb(void *context,
112 bcmolt_devid device_id,
113 bcmolt_epon_ni epon_ni,
114 const bcmos_mac_address *mac_address,
115 bcmos_errno result);
116
117
118#define _mac_addr_fmt_str "<%02x:%02x:%02x:%02x:%02x:%02x>"
119#define _mac_addr_data(mac) \
120 (mac).u8[0], \
121 (mac).u8[1], \
122 (mac).u8[2], \
123 (mac).u8[3], \
124 (mac).u8[4], \
125 (mac).u8[5]
126
127
128static void mac_util_oam_negotiation_cb(void *context, bcmolt_devid device_id, bcmolt_epon_ni epon_ni, const bcmos_mac_address *mac_address, bcmos_errno result)
129{
130
131 epon_onu_list_entry *p_onu_entry = context;
132 uint32_t logical_pon;
133 bcmos_errno rc;
134
135 do
136 {
137
138 rc = bcm_topo_pon_get_physical2logical(device_id, epon_ni, &logical_pon);
139 if (BCM_ERR_OK != rc)
140 {
141 BCM_LOG(ERROR, log_id_mac_util,
142 "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, epon_ni, bcmos_strerror(rc));
143 break;
144 }
145
146 BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(epon_ni),
147 "device_id=%u, epon_ni=%u, mac_address=" _mac_addr_fmt_str " result='%s'\n",
148 device_id, epon_ni, _mac_addr_data(*mac_address), result == BCM_ERR_OK ? "success" : "fail");
149
150
151 mac_util_report_sub_term_event(logical_pon,
152 p_onu_entry->bal_onu_key.sub_term_id,
153 (bcmolt_serial_number *)NULL,
154 BAL_UTIL_OPER_SUB_TERM_ADD,
155 result,
156 result == BCM_ERR_OK ? BCMOLT_RESULT_SUCCESS : BCMOLT_RESULT_FAIL,
157 BCMOLT_ACTIVATION_FAIL_REASON_NONE,
158 result == BCM_ERR_OK ? p_onu_entry->tunnel_id : BCMBAL_INVALID_TUNNEL_ID);
159
160 }
161 while(0);
162
163}
164
165/**
166 * @brief get string for the indication object type for epon
167 */
168static char *mac_util_indication_get_obj_type_str_for_epon (bcmolt_obj_id obj_type)
169{
170 return _mac_util_get_obj_type_str_for_indications (obj_type, mac_util_epon_ind_handlers, BCM_SIZEOFARRAY(mac_util_epon_ind_handlers));
171}
172
173/**
174 * @brief all the maple indication handlers for epon
175 *
176 * @param device_id the maple device id generating the current indication
177 * @param p_msg pointer to the maple indication message
178 *
179 */
180bcmos_errno mac_util_handle_all_olt_ind_for_epon (bcmolt_devid device_id, bcmolt_msg *p_msg)
181{
182 int i = 0;
183
184 BCM_LOG(DEBUG, log_id_mac_util,
185 "mac_util_indication_cb received indication obj=%d/%s group=%d subgroup=%d\n",
186 p_msg->obj_type, mac_util_indication_get_obj_type_str_for_epon(p_msg->obj_type),
187 p_msg->group, p_msg->subgroup);
188
189 for (i=0; i < BCM_SIZEOFARRAY(mac_util_epon_ind_handlers); i++)
190 {
191 if (p_msg->obj_type == mac_util_epon_ind_handlers[i].obj_type)
192 {
193 return mac_util_epon_ind_handlers[i].ind_handler (device_id, p_msg);
194 }
195 }
196
197 /* log an error if unhandled */
198 return BCM_ERR_INTERNAL;
199}
200
201
202/**
203 * @brief Handler function for Maple auto indications for EPON Link
204 *
205 * @param device_id the maple device id generating the current indication
206 * @param p_msg pointer to the maple indication message
207 *
208 * @return bcmos_errno
209 */
210static bcmos_errno mac_util_indication_handle_for_epon_link (bcmolt_devid device_id, bcmolt_msg *p_msg)
211{
212 bcmos_errno rc = BCM_ERR_OK;
213 uint32_t logical_pon;
214
215 do
216 {
217 if (BCMOLT_EPON_LINK_AUTO_ID_MPCP_DISCOVERED == p_msg->subgroup)
218 {
219 epon_onu_list_entry *p_onu_entry;
220 bcmolt_epon_link_mpcp_discovered * p_ind = (bcmolt_epon_link_mpcp_discovered*)p_msg;
221
222 rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.epon_ni, &logical_pon);
223 if (BCM_ERR_OK != rc)
224 {
225 BCM_LOG(ERROR, log_id_mac_util,
226 "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_ind->key.epon_ni, bcmos_strerror(rc));
227 break;
228 }
229
230 BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
231 "llid indication received obj=%d group=%d subgroup=%d err=%d; "
232 "link_status = %s (%d), llid = (0x%04x) tunnel_id = (0x%08x)\n",
233 p_msg->obj_type, p_msg->group, p_msg->subgroup, p_msg->err,
234 p_ind->data.link_info.link_status==BCMOLT_EPON_LINK_STATUS_DISCOVERED ? "Discovered" : "other",
235 p_ind->data.link_info.link_status,
236 p_ind->data.link_info.llid,
237 p_ind->data.link_info.tunnel_id);
238
239
240
241 if(NULL == (p_onu_entry = epon_onu_list_find_by_mac(&(p_ind->key.mac_address))))
242 {
243 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
244 "Failed to find epon onu related to received frame captured\n");
245 rc = BCM_ERR_INTERNAL;
246 }
247 else
248 {
249
250 p_onu_entry->tunnel_id = p_ind->data.link_info.tunnel_id;
251 bal_oam_start_oam_negotiation(device_id,
252 p_ind->key.epon_ni,
253 &p_ind->key.mac_address,
254 mac_util_oam_negotiation_cb,
255 p_onu_entry);
256 }
257 }
258 }
259 while(0);
260
261 return rc;
262}
263
264
265/**
266 * @brief Handler function for Maple auto indications for EPON NI
267 *
268 * @param device_id the maple device id generating the current indication
269 * @param p_msg pointer to the maple indication message
270 *
271 * @return bcmos_errno
272 */
273static bcmos_errno mac_util_indication_handle_for_epon_ni (bcmolt_devid device_id, bcmolt_msg *p_msg)
274{
275 bcmos_errno rc = BCM_ERR_OK;
276 uint32_t logical_pon;
277 do
278 {
279
280 if (BCMOLT_EPON_NI_AUTO_ID_STATE_CHANGE_COMPLETED == p_msg->subgroup)
281 {
282 bcmolt_epon_ni_state_change_completed * p_ind = (bcmolt_epon_ni_state_change_completed *)p_msg;
283 rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.epon_ni, &logical_pon);
284 if (BCM_ERR_OK != rc)
285 {
286 BCM_LOG(ERROR, log_id_mac_util,
287 "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_ind->key.epon_ni, bcmos_strerror(rc));
288 break;
289 }
290
291 BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon), "Pon if %d is %s.\n", logical_pon,
292 BCMOLT_EPON_NI_EN_STATE_ENABLED == p_ind->data.new_state ? "up" : "down");
293
294 mac_util_report_if_event(logical_pon, BCMBAL_INTF_TYPE_PON, p_msg->err,
295 BCMOLT_RESULT_SUCCESS, p_ind->data.new_state);
296 }
297 else
298 {
299 /* just get the pon key by typecasting to a dummy structure */
300 bcmolt_epon_ni_key *p_pon_key = &(((bcmolt_epon_ni_state_change_completed*)p_msg)->key);
301
302 rc = bcm_topo_pon_get_physical2logical(device_id, p_pon_key->epon_ni, &logical_pon);
303 if (BCM_ERR_OK != rc)
304 {
305 BCM_LOG(ERROR, log_id_mac_util,
306 "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_pon_key->epon_ni, bcmos_strerror(rc));
307 break;
308 }
309
310 BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
311 "Unhandled message indication for obj Epon_NI group %d "
312 "subgroup %d (Ignored)\n", p_msg->group, p_msg->subgroup);
313 }
314
315
316
317 }
318 while(0);
319 return rc;
320}
321
322
323/**
324 * @brief Maple auto indication register for specific EPON based indications
325 *
326 * @param p_rx_cfg handler config structure
327 * @param device_id specific device id (for multiple devices support)
328 * @return bcmos_errno
329 */
330bcmos_errno mac_util_register_for_epon_auto_indications (struct bcmolt_rx_cfg *p_rx_cfg, bcmolt_devid device_id)
331{
332 return _mac_util_register_for_auto_indications (p_rx_cfg, mac_util_epon_ind_handlers, BCM_SIZEOFARRAY(mac_util_epon_ind_handlers), device_id);
333}
334#endif /* BAL_EPON_EXCLUDE */
335
336static bcmos_errno mac_util_epon_access_terminal_set(
337 acc_term_inst *p_acc_term,
338 bal_util_oper_acc_term op_type,
339 bcmolt_devid device_id,
340 bcmolt_system_mode system_mode,
341 bcmolt_nni_speed nni_speed)
342{
343 bcmos_errno rc = BCM_ERR_OK;
344 bcmolt_device_key key = {};
345 bcmolt_device_nni_speed nni_speed_cfg;
346 bcmolt_device_cfg dev_cfg;
347
348 rc = maple_access_terminal_set_common(p_acc_term, op_type, device_id);
349 if (rc != BCM_ERR_OK)
350 return rc;
351
352 BCMOLT_CFG_INIT(&dev_cfg, device, key);
353 BCMOLT_CFG_PROP_SET(&dev_cfg, device, system_mode, system_mode);
354
355 nni_speed_cfg.first_half = nni_speed;
356 nni_speed_cfg.second_half = nni_speed;
357 BCMOLT_CFG_PROP_SET(&dev_cfg, device, nni_speed, nni_speed_cfg);
358
359 /** @todo with multiple devices the mechanism to configure acces term will change */
360 rc = bcmolt_cfg_set(device_id, &dev_cfg.hdr);
361 if (rc != BCM_ERR_OK)
362 return rc;
363
364 return maple_access_terminal_connect_common(device_id);
365}
366
367bcmos_errno mac_util_access_terminal_set_for_epon_8_tdma(
368 acc_term_inst *p_acc_term,
369 bal_util_oper_acc_term op_type,
370 bcmolt_devid device_id)
371{
372 return mac_util_epon_access_terminal_set(
373 p_acc_term,
374 op_type,
375 device_id,
376 BCMOLT_SYSTEM_MODE_EPON__8_X_COEXISTENCE_TDMA,
377 BCMOLT_NNI_SPEED_GBPS_12P5);
378}
379
380bcmos_errno mac_util_access_terminal_set_for_epon_4_tdma(
381 acc_term_inst *p_acc_term,
382 bal_util_oper_acc_term op_type,
383 bcmolt_devid device_id)
384{
385 return mac_util_epon_access_terminal_set(
386 p_acc_term,
387 op_type,
388 device_id,
389 BCMOLT_SYSTEM_MODE_EPON__4_X_COEXISTENCE_TDMA,
390 BCMOLT_NNI_SPEED_GBPS_12P5);
391}
392
393bcmos_errno mac_util_access_terminal_set_for_epon_16_1g(
394 acc_term_inst *p_acc_term,
395 bal_util_oper_acc_term op_type,
396 bcmolt_devid device_id)
397{
398 return mac_util_epon_access_terminal_set(
399 p_acc_term,
400 op_type,
401 device_id,
402 BCMOLT_SYSTEM_MODE_EPON__16_X,
403 BCMOLT_NNI_SPEED_GBPS_2P5);
404}
405
406bcmos_errno mac_util_access_terminal_set_for_epon_8_1g(
407 acc_term_inst *p_acc_term,
408 bal_util_oper_acc_term op_type,
409 bcmolt_devid device_id)
410{
411 return mac_util_epon_access_terminal_set(
412 p_acc_term,
413 op_type,
414 device_id,
415 BCMOLT_SYSTEM_MODE_EPON__8_X,
416 BCMOLT_NNI_SPEED_GBPS_2P5);
417}
418
419bcmos_errno mac_util_access_terminal_set_for_epon_4_1g(
420 acc_term_inst *p_acc_term,
421 bal_util_oper_acc_term op_type,
422 bcmolt_devid device_id)
423{
424 return mac_util_epon_access_terminal_set(
425 p_acc_term,
426 op_type,
427 device_id,
428 BCMOLT_SYSTEM_MODE_EPON__4_X,
429 BCMOLT_NNI_SPEED_GBPS_2P5);
430}
431
432bcmos_errno mac_util_access_terminal_set_for_epon_8_10g(
433 acc_term_inst *p_acc_term,
434 bal_util_oper_acc_term op_type,
435 bcmolt_devid device_id)
436{
437 return mac_util_epon_access_terminal_set(
438 p_acc_term,
439 op_type,
440 device_id,
441 BCMOLT_SYSTEM_MODE_EPON__8_X_10_G,
442 BCMOLT_NNI_SPEED_GBPS_12P5);
443}
444
445bcmos_errno mac_util_access_terminal_set_for_epon_4_10g(
446 acc_term_inst *p_acc_term,
447 bal_util_oper_acc_term op_type,
448 bcmolt_devid device_id)
449{
450 return mac_util_epon_access_terminal_set(
451 p_acc_term,
452 op_type,
453 device_id,
454 BCMOLT_SYSTEM_MODE_EPON__4_X_10_G,
455 BCMOLT_NNI_SPEED_GBPS_12P5);
456}
457
458bcmos_errno mac_util_access_terminal_set_for_epon_2_10g(
459 acc_term_inst *p_acc_term,
460 bal_util_oper_acc_term op_type,
461 bcmolt_devid device_id)
462{
463 return mac_util_epon_access_terminal_set(
464 p_acc_term,
465 op_type,
466 device_id,
467 BCMOLT_SYSTEM_MODE_EPON__2_X_10_G,
468 BCMOLT_NNI_SPEED_GBPS_12P5);
469}
470
471/**
472 * @brief Command Set setup routine for interface up to mac application for EPON
473 *
474 * This routine is called by if_fsm in the BAL core to initialize the command
475 * set to up the interface of the mac application. The cmdset actually
476 * consists of two commands, one is to send the if up request message to the mac
477 * App and handle the relevant response, the other is to handle the indication message
478 * from the mac APP when the operation is completed.
479 *
480 * @param p_interface_inst Pointer to interface instance
481 * @param op_type Operation type on access terminal/interface instance
482 *
483 * @return bcmos_errno
484 *
485 */
486bcmos_errno mac_util_interface_set_for_epon(acc_term_interface *p_interface_inst, bal_util_oper_if op_type)
487{
488 bcmos_errno rc = BCM_ERR_OK;
489 bcmbal_interface_key intf_key = p_interface_inst->api_req_int_obj_info.key;
490 bcmolt_devid device_id;
491 uint32_t physical_if_id;
492
493 /* get physical interface from logical interface */
494 rc = bcm_topo_pon_get_logical2physical(intf_key.intf_id, &device_id, &physical_if_id);
495 if (BCM_ERR_OK != rc)
496 {
497 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
498 "Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
499 return rc;
500 }
501
502 bcmolt_epon_ni_key key;
503 bcmolt_epon_ni_cfg cfg;
504 bcmolt_epon_ni_set_epon_ni_en_state oper;
505
506 key.epon_ni = physical_if_id;
507
508 BCMOLT_CFG_INIT(&cfg, epon_ni, key);
509
510 if (BAL_UTIL_OPER_IF_UP == op_type)
511 {
512 BCMOLT_CFG_PROP_SET(&cfg, epon_ni, registration_behavior, BCMOLT_REGISTRATION_BEHAVIOR_NOTIFY_UNKNOWN);
513
514 bcmolt_cfg_set(device_id, &cfg.hdr);
515 if (rc != BCM_ERR_OK)
516 {
517 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
518 "Failed to %s (set) pon interface (%d) - %s, err_text=%s\n",
519 (BAL_UTIL_OPER_IF_UP == op_type) ? "activate" : "deactivate",
520 rc, bcmos_strerror(rc), cfg.hdr.hdr.err_text);
521 return rc;
522 }
523 }
524
525 BCMOLT_OPER_INIT(&oper, epon_ni, set_epon_ni_en_state, key);
526 BCMOLT_OPER_PROP_SET(&oper, epon_ni, set_epon_ni_en_state, new_state,
527 (BAL_UTIL_OPER_IF_UP == op_type ?
528 BCMOLT_EPON_NI_EN_STATE_ENABLED : BCMOLT_EPON_NI_EN_STATE_DISABLED));
529
530 rc = bcmolt_oper_submit(device_id, &oper.hdr);
531
532 if (rc != BCM_ERR_OK)
533 {
534 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
535 "Failed to %s (submit) pon interface (%d) - %s, err_text=%s\n",
536 (BAL_UTIL_OPER_IF_UP == op_type) ? "activate" : "deactivate",
537 rc, bcmos_strerror(rc), oper.hdr.hdr.err_text);
538 }
539 else
540 {
541 BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
542 "Submitted INTERFACE-%s operation for IF %d\n",
543 (BAL_UTIL_OPER_IF_UP == op_type) ? "UP" : "DOWN", intf_key.intf_id);
544 }
545
546 return rc;
547}
548/*---------------------------------------------------------------------------------------------*/
549
550
551
552
553
554#if BAL_EPON_EXCLUDE
555/**
556 * @brief mac_util_validate_subscriber_terminal_info_for_epon
557 *
558 * This routine is used to validate all input attributes required for a sub term setting
559 * received from core for EPON
560 *
561 * @param p_sub_term_req A pointer to a subscriber terminal object
562 *
563 * @return bcmos_errno
564 */
565/*****************************************************************************/
566bcmos_errno mac_util_validate_subscriber_terminal_info_for_epon(const bcmbal_subscriber_terminal_cfg *p_sub_term_req)
567{
568 if(BCMBAL_STATE_UP == p_sub_term_req->data.admin_state)
569 {
570 if (!BCMBAL_CFG_PROP_IS_SET(p_sub_term_req, subscriber_terminal, mac_address))
571 {
572 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
573 "mac_address is a mandatory parameter for an epon subscriber terminal, and it is not set\n");
574 return BCM_ERR_MANDATORY_PARM_IS_MISSING;
575 }
576 }
577
578 return BCM_ERR_OK;
579}
580
581
582/**
583 * @brief Command Set setup routine for subscriber terminal connect to mac application for EPON
584 *
585 * This routine is called by sub_term_fsm in the BAL core to initialize the command
586 * set to connect the subscriber terminal of the mac application. The cmdset actually
587 * consists of two commands, one is to send the sub_term request message to the mac
588 * App and handle the relevant response, the other is to handle the indication message
589 * from the mac APP when the operation is completed.
590 *
591 * @param p_sub_term_inst A pointer to a subscriber terminal instance
592 * @param op_type Type of operation being performed on the subscriber terminal instance
593 * @param is_post_discovery This parameter is ignored for epon
594 *
595 * @return bcmos_errno
596 */
597bcmos_errno mac_util_subscriber_terminal_set_for_epon(sub_term_inst *p_sub_term_inst, bal_util_oper_sub_term op_type, bcmos_bool is_post_discovery)
598{
599 bcmos_errno rc = BCM_ERR_OK;
600
601 bcmbal_subscriber_terminal_cfg *p_sub_term_req = &p_sub_term_inst->api_req_sub_term_info;
602
603
604 BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
605 "IN : %s pon_id = %d onu_id= %d "
606 "omci_gem_port = %d\n",
607 __FUNCTION__,
608 p_sub_term_req->key.intf_id,
609 p_sub_term_req->key.sub_term_id, p_sub_term_req->data.svc_port_id);
610
611 if ((BAL_UTIL_OPER_SUB_TERM_ADD != op_type)
612 && (BAL_UTIL_OPER_SUB_TERM_REMOVE != op_type)
613 && (BAL_UTIL_OPER_SUB_TERM_CLEAR != op_type))
614 {
615 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
616 "Unsupported operation %d for sub_term %u\n",
617 op_type, p_sub_term_req->key.sub_term_id);
618 return BCM_ERR_NOT_SUPPORTED;
619 }
620
621 do
622 {
623 bcmolt_devid device_id;
624 uint32_t physical_if_id;
625
626 /* get physical interface from logical interface */
627 rc = bcm_topo_pon_get_logical2physical (p_sub_term_req->key.intf_id, &device_id, &physical_if_id);
628 if (BCM_ERR_OK != rc)
629 {
630 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
631 "Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
632 break;
633 }
634
635 epon_onu_list_entry * p_new_epon_onu_entry;
636 bcmolt_epon_ni_key key;
637 bcmolt_epon_ni_add_link oper;
638
639 key.epon_ni = physical_if_id;
640 BCMOLT_OPER_INIT(&oper, epon_ni, add_link, key);
641
642 if(BAL_UTIL_OPER_SUB_TERM_ADD == op_type)
643 {
644
645 BCMOLT_OPER_PROP_SET(&oper, epon_ni, add_link, mac_address, p_sub_term_req->data.mac_address);
646 BCMOLT_OPER_PROP_SET(&oper, epon_ni, add_link, rate, BCMOLT_EPON_LINK_RATE_TEN_TEN);
647 rc = bcmolt_oper_submit(device_id, &oper.hdr);
648
649 if (rc != BCM_ERR_OK)
650 {
651 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
652 "Failed to register epon onu epon_ni = %d mac : "_mac_addr_fmt_str" rc = %d (%s), err_text=%s\n",
653 key.epon_ni, _mac_addr_data(p_sub_term_req->data.mac_address), rc, bcmos_strerror(rc),
654 oper.hdr.hdr.err_text);
655 break;
656 }
657 /* add the new epon onu to the epon onu list to follow indications and oam sending */
658 p_new_epon_onu_entry = bcmos_calloc(sizeof(epon_onu_list_entry));
659 if (NULL == p_new_epon_onu_entry)
660 {
661 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
662 "Failed to allocate the epon onu entry\n");
663 rc = BCM_ERR_NOMEM;
664 break;
665 }
666
667 memcpy(&p_new_epon_onu_entry->bal_onu_key, &p_sub_term_req->key,
668 sizeof(bcmbal_subscriber_terminal_key));
669 p_new_epon_onu_entry->mac_address = p_sub_term_req->data.mac_address;
670 p_new_epon_onu_entry->oam_provision_state = OAM_PROVISION_STATE_IDLE;
671 p_new_epon_onu_entry->waiting_flows_num = 0;
672
673 epon_onu_list_add(p_new_epon_onu_entry);
674 }
675 else
676 {
677 mac_util_report_sub_term_event(p_sub_term_req->key.intf_id,
678 p_sub_term_req->key.sub_term_id,
679 (bcmolt_serial_number *)NULL,
680 BAL_UTIL_OPER_SUB_TERM_REMOVE,
681 BCM_ERR_OK, BCMOLT_RESULT_SUCCESS,
682 MAC_UTIL_DEACTIVATION_FAIL_REASON_NONE, BCMBAL_INVALID_TUNNEL_ID);
683
684 epon_onu_list_remove_by_key(&p_sub_term_req->key);
685
686 }
687 } while (0);
688
689 BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
690 "OUT : going out of %s rc = %s (%d)\n",
691 __FUNCTION__,
692 bcmos_strerror(rc), rc);
693
694
695 return rc;
696}
697
698
699
700
701
702static bcmos_errno maple_us_sla_configure_epon(bcmbal_flow_cfg *flow_entry, bcmos_mac_address *mac)
703{
704 bcmolt_epon_link_key epon_link_key;
705 bcmolt_epon_link_cfg epon_link_cfg;
706 bcmolt_upstream_bandwidth_distribution us_bw_dist = {};
707
708 bcmolt_devid device_id;
709 uint32_t physical_if_id;
710 bcmos_errno rc = BCM_ERR_OK;
711
712 /* get physical interface from logical interface */
713 rc = bcm_topo_pon_get_logical2physical (flow_entry->data.access_int_id, &device_id, &physical_if_id);
714 if (BCM_ERR_OK != rc)
715 {
716 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(flow_entry->data.access_int_id),
717 "Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
718 }
719 else
720 {
721
722 epon_link_key.epon_ni = physical_if_id;
723 epon_link_key.mac_address = *mac;
724 BCMOLT_CFG_INIT(&epon_link_cfg, epon_link, epon_link_key);
725
726 us_bw_dist.polling_interval_us = BCMOLT_POLLING_INTERVAL_AUTOMATIC;
727 if (BCMBAL_ATTRIBUTE_PROP_IS_SET(&flow_entry->data.sla, sla, min_rate))
728 {
729 us_bw_dist.min_schedulershaper.bandwidth_Kbps = flow_entry->data.sla.min_rate;
730 }
731 if (BCMBAL_ATTRIBUTE_PROP_IS_SET(&flow_entry->data.sla, sla, max_rate))
732 {
733 us_bw_dist.max_schedulershaper.bandwidth_Kbps = flow_entry->data.sla.max_rate;
734 }
735 else
736 {
737 us_bw_dist.max_schedulershaper.bandwidth_Kbps = 10000000;
738 }
739 us_bw_dist.max_schedulershaper.priority = 7;
740
741 BCMOLT_CFG_PROP_SET(&epon_link_cfg, epon_link, upstream_bandwidth, us_bw_dist);
742 return bcmolt_cfg_set(device_id, &epon_link_cfg.hdr);
743 }
744
745 return rc;
746}
747
748
749
750
751
752
753/**
754 * @brief flow set for EPON
755 *
756 * @param p_flow_req pointer to flow request structure from core
757 * @param op_type ADD, REMOVE or CLEAR
758 * @param p_flow_core local DB flow context passed as a cookie
759 *
760 * @return errno error
761 */
762bcmos_errno mac_util_flow_set_for_epon (bcmbal_flow_cfg *p_flow_req, bal_util_oper_flow op_type, flow_inst *p_flow_core)
763{
764 bcmos_errno rc = BCM_ERR_OK;
765
766 epon_onu_list_entry *p_onu_entry;
767 bcmos_mac_address mac;
768 bcmbal_subscriber_terminal_key key;
769
770
771 key.intf_id = p_flow_req->data.access_int_id;
772 key.sub_term_id = p_flow_req->data.sub_term_id;
773
774 if(NULL != (p_onu_entry = epon_onu_list_find_by_key(&key)))
775 {
776 mac = p_onu_entry->mac_address;
777 }
778 else
779 {
780 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id),
781 "failed to configure flow, "
782 "subscriber terminal if=%d sub-term id = %d was not found - no such device\n",
783 p_flow_req->data.access_int_id, p_flow_req->data.sub_term_id);
784
785 return BCM_ERR_NOENT;
786 }
787
788
789
790 if (BAL_UTIL_OPER_FLOW_ADD == op_type)
791 {
792
793 BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id), "add, context is %p\n", p_flow_context);
794
795 switch (p_onu_entry->oam_provision_state)
796 {
797 case OAM_PROVISION_STATE_IDLE:
798 {
799 p_onu_entry->flow_keys[p_onu_entry->waiting_flows_num++] = p_flow_req->key;
800
801 BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id),
802 "add p_onu_entry-> %p, waiting flows: %d context is %p\n",
803 p_onu_entry, p_onu_entry->waiting_flows_num, p_flow_context);
804
805 rc = maple_us_sla_configure_epon(p_flow_req, &mac);
806 if (rc != BCM_ERR_OK)
807 {
808 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id),
809 "Unable to configure EPON US SLA (%s)\n", bcmos_strerror(rc));
810
811 break;
812 }
813
814 p_onu_entry->oam_provision_state = OAM_PROVISION_STATE_STARTED;
815
816 bal_oam_configure_traffic(maple_device_from_interface_get(p_flow_req->data.access_int_id),
817 p_flow_req->data.access_int_id,
818 &mac,
819 BCMOS_TRUE,
820 mac_util_configure_traffic_cb, p_flow_context);
821 }
822 break;
823
824
825 case OAM_PROVISION_STATE_STARTED:
826 {
827 if (p_onu_entry->waiting_flows_num < MAC_UTIL_MAX_WAITING_FLOWS_PER_MAC)
828 {
829 p_onu_entry->flow_keys[p_onu_entry->waiting_flows_num++] = p_flow_req->key;
830 }
831 else
832 {
833 BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id),
834 "failed to configure flow for that mac, "
835 "too many flows already waiting for oam configuration\n");
836 rc = BCM_ERR_INSUFFICIENT_LIST_MEM;
837 }
838 }
839 break;
840
841
842 case OAM_PROVISION_STATE_COMPLETED:
843 {
844 mac_util_report_flow_add_success(p_flow_req->key, p_flow_req->data.access_int_id);
845 }
846 break;
847
848
849 case OAM_PROVISION_STATE_FAIL:
850 default:
851 {
852 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id),
853 "failed to configure oam traffic for that mac,\n"); /* currently no failure indications */
854 }
855 break;
856 }
857 }
858 else /* REMOVE or CLEAR FLOW */
859 {
860
861 BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id),
862 "delete p_onu_entry-> %p, waiting flows: %d, provisioned state is %d, context is %p\n",
863 p_onu_entry,
864 p_onu_entry->waiting_flows_num,
865 p_onu_entry->oam_provision_state,
866 p_flow_context);
867
868 switch (p_onu_entry->oam_provision_state)
869 {
870 case OAM_PROVISION_STATE_IDLE:
871 {
872 mac_util_report_flow_remove_success(p_flow_req->key, p_flow_req->data.access_int_id, op_type);
873 }
874 break;
875
876 case OAM_PROVISION_STATE_COMPLETED:
877 {
878 BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id),
879 "calling bal_oam_configure_traffic w/ \"Disable\" state\n");
880
881 bal_oam_configure_traffic(maple_device_from_interface_get(p_flow_req->data.access_int_id),
882 p_flow_req->data.access_int_id,
883 &mac,
884 BCMOS_FALSE,
885 mac_util_unconfigure_traffic_cb,
886 p_flow_context);
887 }
888 break;
889
890 case OAM_PROVISION_STATE_FAIL:
891 case OAM_PROVISION_STATE_STARTED:
892 default:
893 {
894 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id),
895 "failed to unconfigure oam traffic for that mac,\n"); /* currently no failure indications */
896 }
897 break;
898 }
899 }
900
901 return rc;
902}
903
904static void mac_util_configure_traffic_cb(void *context,
905 bcmolt_devid device_id,
906 bcmolt_epon_ni epon_ni,
907 const bcmos_mac_address *mac_address,
908 bcmos_errno result)
909{
910 epon_onu_list_entry *p_onu_entry;
911 int i;
912
913 BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(epon_ni),
914 "configure device_id=%u, epon_ni=%u, mac_address=" _mac_addr_fmt_str " result='%s'\n",
915 device_id, epon_ni, _mac_addr_data(*mac_address), result == BCM_ERR_OK ? "success" : "fail");
916
917
918 if(NULL == (p_onu_entry = epon_onu_list_find_by_mac(mac_address)))
919 {
920 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(epon_ni),
921 "FAIL - received configure traffic cb for mac that was not configured " _mac_addr_fmt_str "\n",
922 _mac_addr_data(*mac_address));
923 return;
924 }
925
926 if (OAM_PROVISION_STATE_STARTED != p_onu_entry->oam_provision_state)
927 {
928 BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(epon_ni),
929 "FAIL - received configure traffic cb for mac that is in the wrong state (%d)\n",
930 p_onu_entry->oam_provision_state);
931 return;
932 }
933
934 if (result == BCM_ERR_OK)
935 {
936 p_onu_entry->oam_provision_state = OAM_PROVISION_STATE_COMPLETED;
937
938 BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(epon_ni), "Moved ONU to OAM COMPLETED state\n");
939
940 for (i=0; i<p_onu_entry->waiting_flows_num; i++)
941 {
942 mac_util_report_flow_add_success(p_onu_entry->flow_keys[i], epon_ni);
943 }
944 }
945 else
946 {
947 p_onu_entry->oam_provision_state = OAM_PROVISION_STATE_FAIL;
948 }
949
950 p_onu_entry->waiting_flows_num = 0; /* currently we dont send fail indication */
951}
952
953/** EPON specific traffic unconfigure; Not used for GPON mode */
954static void mac_util_unconfigure_traffic_cb(void *context,
955 bcmolt_devid device_id,
956 bcmolt_epon_ni epon_ni,
957 const bcmos_mac_address *mac_address,
958 bcmos_errno result)
959{
960 flow_inst *p_flow_core = (flow_inst *)(context);
961 epon_onu_list_entry *p_onu_entry;
962
963 BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(epon_ni),
964 "unconfigure device_id=%u, epon_ni=%u, mac_address=" _mac_addr_fmt_str " result='%s'\n",
965 device_id,
966 epon_ni,
967 _mac_addr_data(*mac_address),
968 result == BCM_ERR_OK ? "success" : "fail");
969
970
971 /** @todo need to pass on the actual op type (REMOVE or CLEAR) */
972 mac_util_report_flow_remove_success(p_flow_core->current_flow_info.key, epon_ni, BAL_UTIL_OPER_FLOW_REMOVE);
973
974 if(NULL != (p_onu_entry = epon_onu_list_find_by_mac(mac_address)))
975 {
976 p_onu_entry->oam_provision_state = OAM_PROVISION_STATE_IDLE;
977 }
978}
979
980
981
982/**
983 * @brief used for epon oam message handling
984 *
985 * @param device_id bcm dev id
986 * @param p_msg oam msg pointer
987 */
988void bal_proxy_rx_cb_for_epon (bcmolt_devid device_id, bcmolt_msg *p_msg)
989{
990 bcmolt_proxy_rx *proxy_rx = (bcmolt_proxy_rx *)p_msg;
991
992 bcmolt_user_appl_eon_process_rx(device_id, proxy_rx);
993 bcmolt_user_appl_epon_oam_handle_rx(device_id, proxy_rx, bal_oam_proxy_rx_cb);
994
995 /** @note the free of p_msg is done in caller function */
996}
997
998
999/**
1000 * @brief init for epon oam and eon
1001 *
1002 */
1003static void mac_util_init_oam_for_epon (void)
1004{
1005 bcmolt_user_appl_epon_oam_init();
1006 bcmolt_user_appl_eon_init();
1007}
1008
1009
1010
1011
1012static void epon_onu_list_add(epon_onu_list_entry *epon_onu_entry)
1013{
1014 TAILQ_INSERT_HEAD(&epon_onu_list, epon_onu_entry, next);
1015 return;
1016}
1017
1018static void epon_onu_list_remove_by_key(bcmbal_subscriber_terminal_key *key)
1019{
1020 epon_onu_list_entry *p_onu_entry = NULL;
1021
1022 if(NULL != (p_onu_entry = epon_onu_list_find_by_key(key)))
1023 {
1024 TAILQ_REMOVE(&epon_onu_list, p_onu_entry, next);
1025 bcmos_free(p_onu_entry);
1026 }
1027
1028 return;
1029}
1030
1031static epon_onu_list_entry *epon_onu_list_find_by_mac(const bcmos_mac_address *mac_address)
1032{
1033 epon_onu_list_entry *p_onu_entry = NULL;
1034 epon_onu_list_entry *current_onu_entry;
1035
1036 TAILQ_FOREACH(current_onu_entry, &epon_onu_list, next)
1037 {
1038 if (memcmp(&current_onu_entry->mac_address, mac_address, sizeof(bcmos_mac_address))==0)
1039 {
1040 p_onu_entry = current_onu_entry;
1041 break;
1042 }
1043 }
1044
1045 return p_onu_entry;
1046}
1047
1048static epon_onu_list_entry *epon_onu_list_find_by_key(bcmbal_subscriber_terminal_key *key)
1049{
1050 epon_onu_list_entry *p_onu_entry = NULL;
1051 epon_onu_list_entry *current_onu_entry;
1052
1053 TAILQ_FOREACH(current_onu_entry, &epon_onu_list, next)
1054 {
1055 if ((current_onu_entry->bal_onu_key.intf_id == key->intf_id) &&
1056 (current_onu_entry->bal_onu_key.sub_term_id == key->sub_term_id))
1057 {
1058 p_onu_entry = current_onu_entry;
1059 break;
1060 }
1061 }
1062
1063 return p_onu_entry;
1064}
1065#endif /* BAL_EPON_EXCLUDE */
1066
1067/*@}*/