blob: 98f50bec53a04fd97f5f5f2354d9f128f03bb049 [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_worker.c
34 * @brief Initialization and message handler functions for the BAL Core
35 * worker thread including all core FSM initialization.
36 *
37 * @addtogroup ctrlr
38 */
39
40/*@{*/
41
42/* Project includes */
43#include <bcmos_system.h>
44#include <bal_api.h>
45#include <bal_msg.h>
46#include <bal_osmsg.h>
47#include "bal_worker.h"
48#include "acc_term_fsm.h"
49#include "flow_fsm.h"
50#include "group_fsm.h"
51#include "sub_term_fsm.h"
52#include "tm_sched_fsm.h"
53#include "tm_queue_fsm.h"
54#include "fsm_common.h"
55#include "bal_api_worker.h"
56#include "bal_obj_msg_pack_unpack.h"
57
58#include "bal_dpp_acc_term.h"
59#include "rsc_mgr.h"
60
61#include <arpa/inet.h>
62
63#ifdef ENABLE_LOG
64#include <bcm_dev_log.h>
65/*
66 * @brief The logging device id for the core
67 */
68extern dev_log_id log_id_core;
69#endif
70
71/* Local function declarations */
72static void core_mgmt_msg_handler(bcmos_module_id module_id, bcmos_msg *msg);
73static bcmos_errno process_mgmt_msg(void *msg_payload);
74static bcmos_errno process_util_msg(void *msg_payload);
75
76static int _bal_mgmt_rx_handler(long data);
77
78static bcmos_errno process_packet_object(void *msg_payload);
79
80/*
81 * @brief The BAL core management queue. These are the queues through which the core
82 * converses with the Public API. The remote endpoint of these queues are the
83 * BAL API backend.
84 */
85static bcmos_msg_queue core_mgmt_queue;
86static bcmos_msg_queue core_api_queue;
87static bcmos_msg_queue core_api_ind_queue;
88bcmos_msg_queue *p_bal_core_queue;
89bcmos_msg_queue *p_bal_core_to_api_queue;
90bcmos_msg_queue *p_bal_core_to_api_ind_queue;
91
92/*
93 * @brief The rx thread for management message reception
94 */
95static bcmos_task rx_mgmt_thread;
96
97/*****************************************************************************/
98/**
99 * @brief Initialize the worker thread
100 *
101 * A Worker module function that initializes all of the data structures and
102 * FSMs associated with the BAL core. This function called from bal_core_init
103 * during BAL core startup.
104 *
105 *****************************************************************************/
106void core_worker_thread_init(void)
107{
108 /*
109 * Initialize all of the worker thread hosted FSMs and the resource manager
110 */
111
112 rsc_mgr_init();
113
114 tm_queue_fsm_init();
115
116 tm_sched_fsm_init();
117
118 access_terminal_fsm_init();
119
120 flow_fsm_init();
121
122 sub_term_fsm_init();
123
124 group_fsm_init();
125
126
127 return;
128}
129
130/*****************************************************************************/
131/**
132 * @brief Finish the worker thread
133 *
134 * A Worker module function that un-initializes all of the data structures and
135 * FSMs associated with the BAL core. This function called from bal_core_init
136 * during BAL core cleanup on exit.
137 *
138 *****************************************************************************/
139void core_worker_thread_finish(void)
140{
141 /*
142 * Un-initialize the worker thread owned data structures. etc.
143 */
144 bcmos_msg_unregister(BCMBAL_MGMT_MSG, 0, BCMOS_MODULE_ID_WORKER_MGMT);
145
146 bcmos_msg_unregister(BCMBAL_MAC_UTIL_MSG, 0, BCMOS_MODULE_ID_WORKER_MGMT);
147
148 bcmos_task_destroy(&rx_mgmt_thread);
149
150 sub_term_fsm_finish();
151
152 flow_fsm_finish();
153
154 group_fsm_finish();
155
156 tm_sched_fsm_finish();
157
158 tm_queue_fsm_finish();
159
160 bcmos_msg_queue_destroy(&core_mgmt_queue);
161
162 if (p_bal_core_to_api_queue == &core_api_queue)
163 bcmos_msg_queue_destroy(p_bal_core_to_api_queue);
164
165 if (p_bal_core_to_api_ind_queue == &core_api_ind_queue)
166 bcmos_msg_queue_destroy(p_bal_core_to_api_ind_queue);
167
168 return;
169}
170
171
172/*****************************************************************************/
173/**
174 * @brief The BAL core management message queue init
175 *
176 * A initialization function for the worker module.
177 * It creates message queues for communication with API layer and UTILS
178 *
179 * @param mgmt_queue_info A pointer to the ip:port addresses required for the msg queues.
180 * The ip:port addresses can be NULL in BAL_MONOLITHIC mode. In this case
181 * inter-thread queues will be used for communication.
182 *
183 * @returns bcmos_errno
184 *
185 *****************************************************************************/
186bcmos_errno core_msg_queue_init(mgmt_queue_addr_ports *mgmt_queue_info)
187{
188 bcmos_msg_queue_parm msg_q_p = {};
189 bcmos_errno ret;
190
191 do
192 {
193 /* Create core queue. BAL core listens on this queue
194 * for public API calls and indications from the UTils
195 */
196 msg_q_p.name = "mgmt_rx_q";
197 if (NULL != mgmt_queue_info->core_mgmt_ip_port)
198 {
199 /* The queue allows sending from core_mgmt_ip_port and receiving at core_mgmt_ip_port */
200 msg_q_p.local_ep_address = mgmt_queue_info->core_mgmt_ip_port;
201 msg_q_p.remote_ep_address = mgmt_queue_info->core_mgmt_ip_port;
202 msg_q_p.ep_type = BCMOS_MSG_QUEUE_EP_UDP_SOCKET;
203 }
204 else
205 {
206 msg_q_p.ep_type = BCMOS_MSG_QUEUE_EP_LOCAL;
207 }
208 ret = bcmos_msg_queue_create(&core_mgmt_queue, &msg_q_p);
209 if (BCM_ERR_OK != ret)
210 {
211 BCM_LOG(ERROR, log_id_core, "Couldn't create rx mgmt queue\n");
212 break;
213 }
214 p_bal_core_queue = &core_mgmt_queue;
215#ifdef BAL_MONOLITHIC
216 if (NULL == mgmt_queue_info->core_mgmt_ip_port)
217 p_balapi_to_core_queue = p_bal_core_queue;
218#endif
219
220 /* Now create a TX queue for sending replies from the core to API.
221 * Only do it if using socket transport. In case of inter-thread queues
222 * it will be created by API layer
223 */
224 if (NULL != mgmt_queue_info->balapi_mgmt_ip_port)
225 {
226 uint16_t portnum;
227 char *p_portnum_str;
228 char balapi_ind_port_str[256];
229
230 msg_q_p.name = "mgmt_to_api_q";
231 msg_q_p.local_ep_address = NULL;
232 msg_q_p.remote_ep_address = mgmt_queue_info->balapi_mgmt_ip_port;
233 msg_q_p.ep_type = BCMOS_MSG_QUEUE_EP_UDP_SOCKET;
234 ret = bcmos_msg_queue_create(&core_api_queue, &msg_q_p);
235 if (BCM_ERR_OK != ret)
236 {
237 BCM_LOG(ERROR, log_id_core, "Couldn't create tx mgmt queue\n");
238 break;
239 }
240 p_bal_core_to_api_queue = &core_api_queue;
241
242 /*
243 * make a copy of the user chosen bal api mgmt port
244 */
245 strcpy(balapi_ind_port_str, mgmt_queue_info->balapi_mgmt_ip_port);
246
247 /* Find the port number */
248 p_portnum_str = strchr(balapi_ind_port_str, ':') + 1;
249
250 /* convert to an integer and increment it by one */
251 portnum = atoi(p_portnum_str) + 1;
252
253 /* create the new string defining the BAL API indication port */
254 sprintf(p_portnum_str,"%d", portnum);
255
256 /* Create core->API indication queue
257 */
258 msg_q_p.name = "mgmt_ind_q";
259
260 /* Set up the management IP:port access parameters to allow the core to send indications to
261 * the BAL public API - this is a TX queue only!.
262 */
263 msg_q_p.local_ep_address = NULL;
264 msg_q_p.remote_ep_address = balapi_ind_port_str;
265 msg_q_p.ep_type = BCMOS_MSG_QUEUE_EP_UDP_SOCKET;
266
267 ret = bcmos_msg_queue_create(&core_api_ind_queue, &msg_q_p);
268 if (BCM_ERR_OK != ret)
269 {
270 BCM_LOG(ERROR, log_id_core, "Couldn't create the core tx indication queue\n");
271 break;
272 }
273
274 BCM_LOG(DEBUG, log_id_core, "Created the core tx indication queue\n");
275
276 p_bal_core_to_api_ind_queue = &core_api_ind_queue;
277 }
278 } while (0);
279
280 return ret;
281}
282
283
284/*****************************************************************************/
285/**
286 * @brief The BAL core management worker module init
287 *
288 * A initialization function for the worker module.
289 * It registers for messages that this module is expected to process.
290 *
291 * @returns bcmos_errno
292 *
293 *****************************************************************************/
294bcmos_errno _bal_worker_mgmt_module_init(long data)
295{
296
297 bcmos_task_parm task_p = {};
298 bcmos_errno ret = BCM_ERR_OK;
299
300 do
301 {
302
303 /* Create Mgmt RX thread */
304 task_p.name = "mgmt_mgmt_rx";
305 task_p.priority = TASK_PRIORITY_IPC_RX;
306 task_p.handler = _bal_mgmt_rx_handler;
307 task_p.data = (long)p_bal_core_queue;
308
309 ret = bcmos_task_create(&rx_mgmt_thread, &task_p);
310 if (ret)
311 {
312 BCM_LOG(ERROR, log_id_core, "Couldn't create Mgmt RX thread\n");
313 break;
314 }
315
316 /* Register the message types to be handled by the mgmt module
317 */
318 bcmos_msg_register(BCMBAL_MGMT_MSG, 0, BCMOS_MODULE_ID_WORKER_MGMT, core_mgmt_msg_handler);
319 bcmos_msg_register(BCMBAL_MAC_UTIL_MSG, 0, BCMOS_MODULE_ID_WORKER_MGMT, core_util_msg_handler);
320 }
321 while(0);
322
323 return ret;
324}
325
326/*****************************************************************************/
327/**
328 * @brief Mgmt RX handler
329 *
330 * This handler is executed in the context of an RX thread. It's purpose
331 * is to dispatch the message received here to the module that has registered
332 * to process this message. The message is then processed in the context
333 * of the thread to which that module is attached.
334 *
335 * @param data A pointer to the received message
336 *
337 * @returns 0 on success, -EINVAL on failure
338 *
339 *****************************************************************************/
340static int _bal_mgmt_rx_handler(long data)
341{
342 bcmos_msg_queue *rxq = (bcmos_msg_queue *)data;
343 bcmos_task *my_task = bcmos_task_current();
344 void *payload;
345 bcmos_msg *msg;
346 bcmos_errno ret = BCM_ERR_OK;
347
348 while (!my_task->destroy_request)
349 {
350 payload = NULL;
351 ret = bcmbal_msg_recv(rxq, BCMOS_WAIT_FOREVER, &payload);
352 if (ret)
353 {
354 /* Unexpected failure */
355 BCM_LOG(ERROR, log_id_core, "bcmbal_msg_recv() -> %s\n", bcmos_strerror(ret));
356 continue;
357 }
358
359 /* Message received */
360 BCM_LOG(DEBUG, log_id_core, "bcmbal_msg_recv(%p) -> %s\n", payload, bcmos_strerror(ret));
361
362 /*
363 * Got a message, so now dispatch it. This will result in one
364 * of the modules (registered for the message being processed)
365 * executing its message callback handler.
366 *
367 */
368 msg = bcmbal_bcmos_hdr_get(payload);
369 ret = bcmos_msg_dispatch(msg, BCMOS_MSG_SEND_AUTO_FREE);
370 if (ret)
371 {
372 BCM_LOG(ERROR, log_id_core,
373 "Couldn't dispatch message %d:%d\n",
374 (int)msg->type, (int)msg->instance);
375 }
376 }
377
378 my_task->destroyed = BCMOS_TRUE;
379
380 return (BCM_ERR_OK == ret) ? 0 : -EINVAL;
381}
382
383/*****************************************************************************/
384/**
385 * @brief The BAL core management message handler
386 *
387 * A function that handlers messages received from the
388 * BAL public API via an RX thread.
389 *
390 * This function executes in the context of the worker thread.
391 *
392 * @param module_id The index of the module that this message handler
393 * is associated with.
394 *
395 * @param msg A pointer to the received message to be processed
396 *
397 *****************************************************************************/
398static void core_mgmt_msg_handler(bcmos_module_id module_id, bcmos_msg *msg)
399{
400
401 void *msg_payload;
402
403 /* Parameter checks */
404 BUG_ON(NULL == msg);
405
406 /*
407 * @to-do
408 * validate the message major and minor version is correct
409 */
410
411 /*
412 * Point to the message payload for further processing
413 */
414 msg_payload = bcmbal_payload_ptr_get(bcmbal_bal_hdr_get_by_bcmos_hdr(msg));
415
416 /*
417 * These are messages from the BAL Public API or the UTILS
418 *
419 * - call into appropriate FSM
420 *
421 */
422 BCM_LOG(DEBUG, log_id_core, "Received a mgmt message (payload at %p)\n", msg_payload);
423
424
425 if(BCMBAL_MGMT_MSG == bcmbal_type_major_get(msg_payload) &&
426 BAL_SUBSYSTEM_PUBLIC_API == bcmbal_sender_get(msg_payload))
427 {
428 /* Process the message */
429 process_mgmt_msg(msg_payload);
430 }
431 else
432 {
433 BCM_LOG(FATAL, log_id_core, "message received with wrong major type/subsystem combination (%d/\%d)\n",
434 bcmbal_type_major_get(msg_payload),
435 bcmbal_sender_get(msg_payload));
436
437 BUG_ON(BCMOS_TRUE);
438 }
439
440}
441
442/*****************************************************************************/
443/**
444 * @brief The BAL core management message processing function
445 *
446 * A Worker module function that handles messages received from the
447 * BAL public API or UTILs via an RX thread.
448 *
449 * This function executes in the context of the worker thread
450 *
451 * @param msg_payload A pointer to the message to be processed
452 *
453 * @returns bcmos_errno
454 *
455 *****************************************************************************/
456static bcmos_errno process_mgmt_msg(void *msg_payload)
457{
458
459 bcmos_errno ret = BCM_ERR_OK;
460 bcmbal_obj_id objtype;
461
462 BCM_LOG(DEBUG, log_id_core, "Processing a management message\n");
463
464 objtype = bcmbal_msg_id_obj_get(msg_payload);
465
466 /*
467 * Process the message based on the type of BAL object and sender
468 * in the message.
469 */
470 switch(objtype)
471 {
472 case BCMBAL_OBJ_ID_FLOW:
473 {
474 ret = process_flow_object(msg_payload);
475 break;
476 }
477
478 case BCMBAL_OBJ_ID_GROUP:
479 {
480 ret = process_group_object(msg_payload);
481 break;
482 }
483
484 case BCMBAL_OBJ_ID_ACCESS_TERMINAL:
485 {
486 ret = process_access_terminal_object(msg_payload);
487 break;
488 }
489
490 case BCMBAL_OBJ_ID_INTERFACE:
491 {
492 ret = process_interface_object(msg_payload);
493 break;
494 }
495
496 case BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL:
497 {
498 ret = process_subscriber_terminal_object(msg_payload);
499 break;
500 }
501
502 case BCMBAL_OBJ_ID_PACKET:
503 {
504
505 ret = process_packet_object(msg_payload);
506
507 /* We respond to the BAL public API backend with a result. We always
508 * send a complete msg_payload back to the API, but the data portion
509 * of the object is only relevant when a GET or GET-STATS has been requested.
510 */
511 mgmt_msg_send_balapi_rsp(ret, msg_payload, ((bcmbal_obj *)msg_payload)->type, log_id_core);
512
513 break;
514
515 }
516
517 case BCMBAL_OBJ_ID_TM_SCHED:
518 {
519 ret = process_tm_sched_object(msg_payload);
520 break;
521 }
522
523 case BCMBAL_OBJ_ID_TM_QUEUE:
524 {
525 ret = process_tm_queue_object(msg_payload);
526 break;
527 }
528
529 default:
530 {
531 BCM_LOG(ERROR, log_id_core,
532 "Unsupported object detected in management message\n");
533 ret = BCM_ERR_NOT_SUPPORTED;
534
535 /* We respond to the BAL public API backend with a result. We always
536 * send a complete msg_payload back to the API, but the data portion
537 * of the object is only relevant when a GET or GET-STATS has been requested.
538 */
539 mgmt_msg_send_balapi_rsp(ret, msg_payload, ((bcmbal_obj *)msg_payload)->type, log_id_core);
540
541 break;
542 }
543 }
544 bcmbal_msg_free(msg_payload);
545
546 return ret;
547}
548
549/*****************************************************************************/
550/**
551 * @brief The BAL core util message handler
552 *
553 * A function that handlers messages received from the
554 * BAL utils via an RX thread.
555 *
556 * This function executes in the context of the worker thread.
557 *
558 * @param module_id The index of the module that this message handler
559 * is associated with.
560 *
561 * @param msg A pointer to the received message to be processed
562 *
563 *****************************************************************************/
564void core_util_msg_handler(bcmos_module_id module_id, bcmos_msg *msg)
565{
566
567 void *msg_payload;
568
569 /* Parameter checks */
570 BUG_ON(NULL == msg);
571
572 /*
573 * @to-do
574 * validate the message major and minor version is correct
575 */
576
577 /*
578 * Point to the message payload for further processing
579 */
580 msg_payload = bcmbal_payload_ptr_get(bcmbal_bal_hdr_get_by_bcmos_hdr(msg));
581
582 /*
583 * These are messages from the BAL Utils
584 *
585 * - call into appropriate FSM
586 *
587 */
588 BCM_LOG(DEBUG, log_id_core, "Received a Util message (payload at %p)\n", msg_payload);
589
590 if(BCMBAL_MAC_UTIL_MSG == bcmbal_type_major_get(msg_payload) &&
591 BAL_SUBSYSTEM_MAC_UTIL == bcmbal_sender_get(msg_payload))
592 {
593 /* Process the message */
594 process_util_msg(msg_payload);
595
596 }
597 else
598 {
599 BCM_LOG(FATAL, log_id_core, "message received with wrong major type/subsystem combination (%d/\%d)\n",
600 bcmbal_type_major_get(msg_payload),
601 bcmbal_sender_get(msg_payload));
602
603 BUG_ON(BCMOS_TRUE);
604 }
605}
606
607/*****************************************************************************/
608/**
609 * @brief The BAL core util message processing function
610 *
611 * A Worker module function that handles messages received from the
612 * BAL utils via an RX thread.
613 *
614 * This function executes in the context of the worker thread
615 *
616 * @param msg_payload A pointer to the message to be processed
617 *
618 * @returns bcmos_errno
619 *
620 *****************************************************************************/
621static bcmos_errno process_util_msg(void *msg_payload)
622{
623
624 bcmos_errno ret = BCM_ERR_OK;
625 bcmbal_obj_id objtype;
626
627 BCM_LOG(DEBUG, log_id_core, "Processing a util message\n");
628
629 objtype = bcmbal_msg_id_obj_get(msg_payload);
630
631 /*
632 * Process the util message based on the type of BAL object
633 * in the message.
634 */
635 switch(objtype)
636 {
637 case BCMBAL_OBJ_ID_FLOW:
638 {
639 ret = process_flow_util_msg(msg_payload);
640 break;
641 }
642
643 case BCMBAL_OBJ_ID_GROUP:
644 {
645 ret = process_group_util_msg(msg_payload);
646 break;
647 }
648
649
650 case BCMBAL_OBJ_ID_ACCESS_TERMINAL:
651 {
652 ret = process_access_terminal_util_msg(msg_payload);
653 break;
654 }
655
656 case BCMBAL_OBJ_ID_INTERFACE:
657 {
658 ret = process_interface_util_msg(msg_payload);
659 break;
660 }
661
662 case BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL:
663 {
664 ret = process_subscriber_terminal_util_msg(msg_payload);
665 break;
666 }
667
668 case BCMBAL_OBJ_ID_TM_SCHED:
669 {
670 ret = process_tm_sched_util_msg(msg_payload);
671 break;
672 }
673
674 default:
675 {
676 BCM_LOG(ERROR, log_id_core,
677 "Unsupported object detected in message received from util\n");
678 ret = BCM_ERR_NOT_SUPPORTED;
679
680 break;
681 }
682 }
683 /*
684 * Free the message after processing
685 */
686 bcmbal_msg_free(msg_payload);
687
688 return ret;
689}
690
691/*****************************************************************************/
692/**
693 * @brief The BAL core "packet send" message processing function
694 *
695 * A Worker module function that handles packet send messages received from the
696 * BAL public API via an RX thread.
697 *
698 * This function executes in the context of the worker thread
699 *
700 * @param msg_payload A pointer to the message to be processed
701 *
702 * @returns bcmos_errno
703 *
704 *****************************************************************************/
705static bcmos_errno process_packet_object(void *msg_payload)
706{
707
708 bcmos_errno ret = BCM_ERR_OK;
709 uint8_t *p_user_pkt;
710 uint16_t user_pkt_len;
711 uint8_t dst_port_id;
712 bcmos_bool b_port_id_is_nni;
713 bcmbal_packet_cfg *p_packet_obj;
714 uint16_t tunnel_tag_vlan_id = 0;
715
716 BCM_LOG(DEBUG, log_id_core, "Processing a \"Packet send\" message\n");
717
718 p_packet_obj = (bcmbal_packet_cfg *)msg_payload;
719
720 /* Extract the length of the user packet to be proxied */
721 user_pkt_len = p_packet_obj->data.pkt.len;
722
723 /* Derive a pointer to the user packet */
724 p_user_pkt = p_packet_obj->data.pkt.val;
725
726 BCM_LOG(DEBUG, log_id_core, "user packet first 12 bytes %02X%02X%02X%02X%02X%02X %02X%02X%02X%02X%02X%02X\n",
727 p_user_pkt[0], p_user_pkt[1], p_user_pkt[2], p_user_pkt[3], p_user_pkt[4], p_user_pkt[5],
728 p_user_pkt[6], p_user_pkt[7], p_user_pkt[8], p_user_pkt[9], p_user_pkt[10], p_user_pkt[11]);
729
730 /* Is this packet destined to an NNI or PON port? */
731 b_port_id_is_nni = (BCMBAL_DEST_TYPE_NNI == p_packet_obj->key.packet_send_dest.type) ?
732 BCMOS_TRUE : BCMOS_FALSE;
733
734 /*
735 * Process the message based on the type of BAL object
736 * in the message.
737 */
738 switch(p_packet_obj->hdr.hdr.obj_type)
739 {
740 case BCMBAL_OBJ_ID_PACKET:
741 {
742
743 dst_port_id = (BCMOS_TRUE == b_port_id_is_nni) ?
744 (p_packet_obj->key.packet_send_dest.u.nni.int_id) :
745 (p_packet_obj->key.packet_send_dest.u.sub_term.int_id);
746 if(BCMOS_FALSE == b_port_id_is_nni)
747 {
748 /*
749 * Packets destined to a PON interface require a tunnel tag
750 *
751 * Get the svc_port_id for the first flow on the subscriber terminal (if there is one)
752 */
753 if(BCM_ERR_OK != svc_port_id_for_sub_term_ds_flow_get(p_packet_obj->key.packet_send_dest.u.sub_term.int_id,
754 p_packet_obj->key.packet_send_dest.u.sub_term.sub_term_id,
755 p_packet_obj->key.packet_send_dest.u.sub_term.sub_term_uni,
756 &tunnel_tag_vlan_id))
757 {
758 BCM_LOG(ERROR,
759 log_id_core,
760 "Packet send could not find any downstream FLOW to send packet for sub_term_id %d (PON %d)\n",
761 p_packet_obj->key.packet_send_dest.u.sub_term.sub_term_id,
762 p_packet_obj->key.packet_send_dest.u.sub_term.int_id);
763 ret = BCM_ERR_NOENT;
764 break;
765 }
766
767 }
768
769 ret = sw_util_pkt_send(dst_port_id,
770 (b_port_id_is_nni ? REASON_SEND_TO_NNI : REASON_SEND_TO_PON),
771 p_user_pkt,
772 user_pkt_len,
773 (int)tunnel_tag_vlan_id);
774 }
775 break;
776
777 default:
778 {
779 BCM_LOG(ERROR, log_id_core,
780 "Unsupported object detected in \"packet send\" message\n");
781 ret = BCM_ERR_NOT_SUPPORTED;
782 }
783 break;
784
785 }
786 /*
787 * NOTE: DO NOT free the message after processing here. It is freed in the calling function
788 */
789
790 return ret;
791}
792
793/*@}*/