blob: 42a9e9588b770bb1775f67d7e5d7c06c51b24d0d [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#ifndef TEST_SW_UTIL_LOOPBACK
33
34#include <bal_common.h>
35#include <bcm_dev_log.h>
36#include <bal_msg.h>
37#include "bal_switch_util.h"
38#include "bal_switch_acc_term.h"
39#include "bal_dpp_acc_term.h"
40#include "bal_dpp_qos.h"
41#include "bal_dpp_qos_map.h"
42
43#include <bcm/types.h>
44#include <bcm/port.h>
45#include <bcm/rx.h> /* for dpp rpc rx register callback */
46#include <bcm/switch.h>
47#include <bcm/l2.h>
48
49/**
50 * @file bal_dpp_acc_term.c
51 * @brief BAL Switch util functions that handle access terminal requests on DUNE PACKET PROCESSOR
52 * @addtogroup sw_util
53 *
54 */
55
56/*@{*/
57
58 /* @brief L2 Table Operation Control
59 *
60 * This routine set the HW L2 learning and aging
61 *
62 * @param unit The device id
63 * @param flags Operation flags
64 * BCM_L2_LEARN_CPU 0x20
65 * BCM_L2_INGRESS_DIST 0x02
66 * BCM_L2_INGRESS_CENT 0x01
67 * @param age_seconds L2 entry age out time in seconds
68 * @return BCM error code
69 */
70static int sw_util_dpp_l2_entry_control_set(int unit, int flags, int age_seconds)
71{
72 int rv = 0;
73
74 rv = bcm_switch_control_set(unit, bcmSwitchL2LearnMode, flags);
75 if (rv)
76 {
77 BCM_LOG(ERROR, log_id_sw_util, " bcm_switch_control_set failed ret = %d\n", rv);
78 return rv;
79 }
80
81 /* set aging time */
82 rv = bcm_l2_age_timer_set(unit, age_seconds);
83 if (rv)
84 {
85 BCM_LOG(ERROR, log_id_sw_util, " bcm_l2_age_timer_set failed ret = %d\n", rv);
86 return rv;
87 }
88 else
89 {
90 BCM_LOG(INFO, log_id_sw_util, " Set L2 table aging time to %d seconds\n", age_seconds);
91 }
92
93 return rv;
94
95}
96
97
98/**
99 * @brief L2 Table event handler
100 *
101 * This routine is a callback triggered by HW L2 Table events
102 *
103 * @param unit The device id
104 * @param p_l2addr Pointer to the L2 entry where the event is happen
105 * @param operation The type of event
106 * @param userdata Pointer to a user provided data when the handler is registered
107 */
108static void sw_util_dpp_l2_entry_event_handler(int unit, bcm_l2_addr_t *p_l2addr, int operation, void *userdata)
109{
110
111 if (p_l2addr == NULL)
112 {
113 BCM_LOG(ERROR, log_id_sw_util, " L2 entry callback with NULL L2 address, op = %d\n", operation);
114 return;
115 }
116 if (operation == BCM_L2_CALLBACK_LEARN_EVENT)
117 {
118 BCM_LOG(DEBUG, log_id_sw_util, " BCM_L2_CALLBACK_LEARN_EVENT handler\n");
119 }
120 else if (operation == BCM_L2_CALLBACK_MOVE_EVENT)
121 {
122 BCM_LOG(DEBUG, log_id_sw_util, " BCM_L2_CALLBACK_MOVE_EVENT handler\n");
123 }
124 else if (operation == BCM_L2_CALLBACK_AGE_EVENT)
125 {
126 BCM_LOG(DEBUG, log_id_sw_util, " BCM_L2_CALLBACK_AGE_EVENT handler\n");
127 }
128 else
129 {
130 BCM_LOG(DEBUG, log_id_sw_util, " BCM_L2_CALLBACK_OPERATION %d handler\n", operation);
131 }
132
133 BCM_LOG(DEBUG, log_id_sw_util, " MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
134 (0xff & p_l2addr->mac[0]),
135 (0xff & p_l2addr->mac[1]),
136 (0xff & p_l2addr->mac[2]),
137 (0xff & p_l2addr->mac[3]),
138 (0xff & p_l2addr->mac[4]),
139 (0xff & p_l2addr->mac[5]) );
140
141 if(!(p_l2addr->flags & BCM_L2_MCAST))
142 {
143 BCM_LOG(DEBUG, log_id_sw_util, " UC VID=0x%x| PORT=0x%08x\n", p_l2addr->vid, p_l2addr->port);
144 /* print_gport_part - p_l2addr->port */
145 {
146 int a = -1, b = 0;
147 char* type = "";
148 if (a==-1){
149 a=BCM_GPORT_LOCAL_GET(p_l2addr->port);
150 type ="local";
151 }
152 if (a==-1){
153 a=BCM_GPORT_MODPORT_MODID_GET(p_l2addr->port);
154 b=BCM_GPORT_MODPORT_PORT_GET(p_l2addr->port);
155 type ="modport";
156 }
157 if (a==-1){
158 a=BCM_GPORT_TRUNK_GET(p_l2addr->port);
159 type ="trunk";
160 }
161 if (a==-1){
162 a=BCM_GPORT_MCAST_GET(p_l2addr->port);
163 type ="mact";
164 }
165 if (a==-1){
166 a=BCM_GPORT_MPLS_PORT_ID_GET(p_l2addr->port);
167 type ="mpls_port";
168 }
169 if (a==-1){
170 a=BCM_GPORT_VLAN_PORT_ID_GET(p_l2addr->port);
171 type ="vlan_port";
172 }
173 if (a==-1){
174 a=BCM_GPORT_SYSTEM_PORT_ID_GET(p_l2addr->port);
175 type ="sys_port";
176 }
177 if (a==-1){
178 a=BCM_GPORT_MIRROR_GET(p_l2addr->port);
179 }
180 BCM_LOG(DEBUG, log_id_sw_util, " GPORT %s <0x%x,%d>\n", type, a, b);
181 }
182 }
183 else
184 {
185 BCM_LOG(DEBUG, log_id_sw_util, " MC 0x%08x\n",p_l2addr->l2mc_group);
186 }
187 BCM_LOG(DEBUG, log_id_sw_util, " static %d|\n", (p_l2addr->flags & BCM_L2_STATIC)!=0 );
188
189}
190
191/**
192 * @brief Connect access terminal with DPP as part of the components
193 *
194 * This routine is called by sw_util_access_terminal_connect in the BAL core
195 * to execute DPP specific API for access_terminal_connect request
196 *
197 * @param p_net_map Pointer to the net ports mapping from logical numbrer to physical number
198 * @param p_pon_map Pointer to the pon ports mapping from logical numbrer to physical number
199 * @return bcmos_errno
200 */
201bcmos_errno sw_util_dpp_acc_term_connect(bal_swapp_port *p_net_map, bal_swapp_port *p_pon_map )
202{
203 bcmos_errno ret = BCM_ERR_OK;
204 int rc = 0;
205 bal_swapp_port *port;
206
207 BCM_LOG(INFO, log_id_sw_util, " DPP - Got a access terminal CONNECT\n");
208
209 do
210 {
211 /* setup the device ID - This is very hardware specific */
212 port = p_net_map;
213 /* -1 indicate the end of table */
214 while(port->pbm_id != -1)
215 {
216
217 /* the default TPID is 0x8100, add 0x88a8 to the allow TPID */
218
219 rc = bcm_port_tpid_delete_all(port->device_id, port->pbm_id);
220 if (rc)
221 {
222 BCM_LOG(ERROR, log_id_sw_util, " DPP - fail to clear the nni TPID list on interface %d\n", port->pbm_id);
223 ret = BCM_ERR_INTERNAL;
224 }
225 rc = bcm_port_tpid_add(port->device_id, port->pbm_id, 0x8100, 0);
226 if (rc)
227 {
228 BCM_LOG(ERROR, log_id_sw_util, " DPP - fail to add 0x8100 to the nni TPID list on interface %d\n", port->pbm_id);
229 ret = BCM_ERR_INTERNAL;
230 }
231 rc = bcm_port_tpid_add(port->device_id, port->pbm_id, 0x88a8, 0);
232 if (rc)
233 {
234 BCM_LOG(ERROR, log_id_sw_util, " DPP - fail to add 0x88a8 to the nni TPID list on interface %d\n", port->pbm_id);
235 ret = BCM_ERR_INTERNAL;
236 }
237
238 port++;
239 }
240
241 port = p_pon_map;
242 while(port->pbm_id != -1)
243 {
244
245 /* the default TPID is 0x8100, add 0x88a8 to the allow TPID */
246
247 rc = bcm_port_tpid_delete_all(port->device_id, port->pbm_id);
248 if (rc)
249 {
250 BCM_LOG(ERROR, log_id_sw_util, " DPP - fail to clear the pon TPID list on interface %d\n", port->pbm_id);
251 ret = BCM_ERR_INTERNAL;
252 }
253 rc = bcm_port_tpid_add(port->device_id, port->pbm_id, 0x8100, 0);
254 if (rc)
255 {
256 BCM_LOG(ERROR, log_id_sw_util, " DPP - fail to add 0x8100 to the pon TPID list on interface %d\n", port->pbm_id);
257 ret = BCM_ERR_INTERNAL;
258 }
259 rc = bcm_port_tpid_add(port->device_id, port->pbm_id, 0x88a8, 0);
260 if (rc)
261 {
262 BCM_LOG(ERROR, log_id_sw_util, " DPP - fail to add 0x88a8 to the pon TPID list on interface %d\n", port->pbm_id);
263 ret = BCM_ERR_INTERNAL;
264 }
265
266 port++;
267 }
268
269 if(ret != BCM_ERR_OK)
270 {
271 /* exit if port init failed */
272 break;
273 }
274
275 /* Remove all ports from VLAN 1, so the L2 broadcast won't send to CPU port by default */
276 bcm_vlan_gport_delete_all(bal_bcm_dft_dev_get(), 1);
277
278 /* configure all qos map tables */
279 ret = bal_sw_dpp_pcp_remark_maps_init(bal_bcm_dft_dev_get());
280 if (ret)
281 {
282 BCM_LOG(WARNING, log_id_sw_util, " DPP - fail to init qos map tables\n");
283 break;
284 }
285
286 /* init the DS QOS hierarchical scheduling - ignore error if HW dos not support QOS */
287 ret =bal_sw_dpp_qos_init(bal_bcm_dft_dev_get(), bal_bcm_intf_maptable_get());
288 if (ret)
289 {
290 BCM_LOG(WARNING, log_id_sw_util, " DPP - fail to init qos HR scheduler\n");
291 break;
292 }
293
294 rc = bcm_l2_addr_register(bal_bcm_dft_dev_get(), sw_util_dpp_l2_entry_event_handler, NULL);
295 if (rc)
296 {
297 BCM_LOG(WARNING, log_id_sw_util, " DPP - fail to register l2_addr callback \n");
298 ret = BCM_ERR_INTERNAL;
299 break;
300 }
301
302 rc = sw_util_dpp_l2_entry_control_set(bal_bcm_dft_dev_get(), BCM_L2_LEARN_CPU|BCM_L2_INGRESS_DIST, bal_bcm_l2_age_time_get());
303 if (rc)
304 {
305 BCM_LOG(WARNING, log_id_sw_util, " DPP - fail to set l2_addr control \n");
306 ret = BCM_ERR_INTERNAL;
307 break;
308 }
309 }while(0);
310 return ret;
311}
312
313/* internal structure used by the trap receiving thread */
314typedef struct
315{
316 int udp_port;
317 pthread_t threadid;
318 dpp_rx_cb_f callback;
319} trap_context;
320
321static trap_context g_trap_ctx = {0};
322
323/* the adjustment needed for ING trap packet header */
324#define DEFAULT_SOP_ADJ 2
325#define DEFAULT_REASON_ADJ 4
326/* compiler restirct the total local variables size < 16384 */
327#define DEFAULT_TRAP_BUF_SIZE (10 *1024)
328/*
329 the listener thread that wait for the trap packet_in message from the switch
330*/
331static void *trap_receive(void *p_user_data)
332{
333 int rc;
334 int sUDPSocket;
335 unsigned char cBuffer[DEFAULT_TRAP_BUF_SIZE];
336 int nBytesRecv = 0;
337 int nBufSize = DEFAULT_TRAP_BUF_SIZE;
338 socklen_t nReceiveAddrSize = 0;
339 int maxfd;
340 fd_set read_fds;
341 struct timeval tv;
342 uint16_t tmp_src_port, src_port;
343 trap_context *p_trap_ctx = (trap_context *)p_user_data;
344 uint32_t tmp_reason, reason;
345 /* Create a connectionless socket */
346 sUDPSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
347 /* Check to see if we have a valid socket */
348 if(sUDPSocket < 0)
349 {
350 BCM_LOG(ERROR, log_id_sw_util, " DPP - trap_receive:create socket failed\n");
351 return NULL;
352 }
353
354 // Setup a bind on the socket, telling us what port and
355 // adapter to receive datagrams on.
356 struct sockaddr_in sReceiveFromAddr;
357 memset(&sReceiveFromAddr, 0, sizeof(struct sockaddr_in));
358
359 sReceiveFromAddr.sin_family = AF_INET;
360 sReceiveFromAddr.sin_port = htons(p_trap_ctx->udp_port);
361 sReceiveFromAddr.sin_addr.s_addr = htonl(INADDR_ANY);
362
363 rc = bind(sUDPSocket, (struct sockaddr *)&sReceiveFromAddr,
364 sizeof(struct sockaddr_in));
365 if (rc < 0)
366 {
367 BCM_LOG(ERROR, log_id_sw_util, " DPP - trap_receive:bind failed\n");
368 return NULL;
369 }
370
371 BCM_LOG(INFO, log_id_sw_util, " DPP - trap_receive start listen at %d\n", p_trap_ctx->udp_port);
372
373 // Receive a datagram from another device
374 while(1)
375 {
376 FD_ZERO(&read_fds);
377 FD_SET(sUDPSocket, &read_fds);
378 maxfd = sUDPSocket;
379 /* Set the timeout */
380 tv.tv_sec = 3;
381 tv.tv_usec = 0; /* 3 seconds */
382 rc = select(maxfd + 1, &read_fds, NULL, NULL, &tv);
383
384 if (rc < 0)
385 {
386 BCM_LOG(ERROR, log_id_sw_util, " DPP - trap_receive:select failed err = %d\n", rc);
387 break;
388 }
389 if (rc == 0) /* timeout */
390 {
391 continue;
392 }
393 // Get the datagrama
394 nBytesRecv = recvfrom(sUDPSocket, cBuffer, nBufSize, 0,
395 (struct sockaddr *) &sReceiveFromAddr,
396 &nReceiveAddrSize);
397 BCM_LOG(INFO, log_id_sw_util, " DPP - Got %d bytes message \n", nBytesRecv);
398
399 /* the first 4 bytes are reason */
400 /* compiler generate cast-align warning -> p_reason = (uint32_t *)(cBuffer); */
401 memcpy(&tmp_reason, cBuffer, sizeof(uint32_t) );
402 reason = ntohl(tmp_reason);
403 /* the next 2 bytes are srouce port */
404 /* compiler generate cast-align warning -> p_src_port = (uint16 *)(cBuffer + DEFAULT_REASON_ADJ); */
405 memcpy(&tmp_src_port, cBuffer + DEFAULT_REASON_ADJ, sizeof(uint16_t));
406 src_port = ntohs(tmp_src_port);
407
408 /* call the register callback here - set unit to 0 as it is don't care */
409 if(p_trap_ctx->callback)
410 {
411 p_trap_ctx->callback(0, src_port, reason, cBuffer+DEFAULT_SOP_ADJ+DEFAULT_REASON_ADJ, nBytesRecv-DEFAULT_SOP_ADJ-DEFAULT_REASON_ADJ);
412 }
413 }
414 close(sUDPSocket);
415
416 return NULL;
417}
418
419/**
420 * @brief Start a receiving thread and add the callbck to process CPU trapped packets
421 *
422 * This routine is called by sw_util_access_terminal_connect in the BAL core
423 * to execute DPP specific API for process the trapping packets
424 *
425 * @param unit the switch device number the callback applied
426 * @param cb_f a callback function that process the trapped packets
427 * @return bcmos_errno
428 */
429bcmos_errno sw_util_dpp_rx_cb_register(uint32_t unit, dpp_rx_cb_f cb_f)
430{
431 int ret;
432
433 /* if the receiving thread already started, return error */
434 if (g_trap_ctx.threadid)
435 {
436 BCM_LOG(ERROR, log_id_sw_util, " DPP - There is an existing trap receiving thread\n");
437 return BCM_ERR_INTERNAL;
438 }
439
440 g_trap_ctx.udp_port = bal_bcm_trap_rcv_port_get();
441 g_trap_ctx.callback = cb_f;
442
443 /* use default attribute to create the thread */
444 ret = pthread_create(&g_trap_ctx.threadid, NULL, &trap_receive, &g_trap_ctx);
445
446 if(ret)
447 {
448 BCM_LOG(ERROR, log_id_sw_util, " DPP - fail to create trap receiving thread - %d\n", ret);
449 return BCM_ERR_INTERNAL;
450 }
451
452 return BCM_ERR_OK;
453}
454
455/* To make compiler happy when build with ESW switch only */
456#ifdef ESW_SWITCH
457void dpp_dft_rx_cb(int unit, int dst_port, int reason, unsigned char *payload, int payload_len)
458{
459 return;
460}
461#else
462extern void dpp_dft_rx_cb(int unit, int dst_port, int reason, unsigned char *payload, int payload_len);
463#endif
464
465#define L2_HEADER_SIZE (12) /* bytes */
466
467#define TUNNEL_TAG_TPID_LEN (2) /* bytes - TPID (2 bytes) */
468#define TUNNEL_TAG_PBITS_CFI_VLAN_ID_LEN (2) /* PBITS+CFI+VLAN ID (2 bytes) */
469#define TUNNEL_TAG_SIZE (TUNNEL_TAG_TPID_LEN + TUNNEL_TAG_PBITS_CFI_VLAN_ID_LEN)
470
471bcmos_errno sw_util_dpp_pkt_send(int target_port_id,
472 int reason,
473 unsigned char *p_user_pkt,
474 int user_pkt_len,
475 trap_target target_device,
476 int target_tunnel_id)
477{
478 bcmos_errno ret = BCM_ERR_OK;
479 char *p_pktout_msg;
480 uint8_t dst_port_id;
481 int dst_device_id;
482 char *p_pktout_ptr;
483 uint32_t total_msg_size;
484 uint32_t uint32_num;
485 uint16_t uint16_num;
486
487 /*
488 * Allocate a message to be sent to the bcm.user instance. This will contain
489 * the packet to be sent out of the switch, as well has header metadata.
490 */
491 p_pktout_msg = bcmos_calloc(user_pkt_len +
492 DEFAULT_SOP_ADJ +
493 DEFAULT_REASON_ADJ +
494 TUNNEL_TAG_SIZE);
495
496 if(NULL == p_pktout_msg)
497 {
498 return BCM_ERR_NOMEM;
499 }
500
501 /* translate the output port to the bcm.user's mapping */
502 switch(reason)
503 {
504 case REASON_SEND_TO_NNI:
505 dst_port_id = bal_bcm_net_inf_pbm_get(target_port_id);
506 dst_device_id = bal_bcm_net_inf_dev_get(target_port_id);
507 break;
508 case REASON_SEND_TO_PON:
509 dst_port_id = bal_bcm_pon_inf_pbm_get(target_port_id);
510 dst_device_id = bal_bcm_pon_inf_dev_get(target_port_id);
511 break;
512 default:
513 return BCM_ERR_PARM;
514 break;
515 }
516
517 /* Format of the message to the bcm.user instance is:
518 *
519 * reason code: 4 bytes
520 * dst_port: 2 bytes
521 * user packet: pkt_size bytes
522 */
523
524 /* Insert the 4 bytes with reason code */
525 uint32_num = (htonl(reason));
526 memcpy(p_pktout_msg, &uint32_num, sizeof(uint32_num));
527
528 /* Replace 2 bytes with packet_out destination port info. This is the bcm.user's
529 * mapping of output port (NNI or PON) to BCM SDK port mapping */
530 uint16_num = htons(dst_port_id & 0xff); /* dst_port contents is actually only 1 byte */
531 memcpy(&p_pktout_msg[DEFAULT_REASON_ADJ], &uint16_num, sizeof(uint16_num));
532
533 /* Copy in the user packet to send to the bcm.user for transmission out of the switch.
534 * Remember to insert the proper tunnel tag in the message for out_ports that are
535 * associated with the PON
536 */
537 p_pktout_ptr = p_pktout_msg + DEFAULT_REASON_ADJ + DEFAULT_SOP_ADJ;
538 total_msg_size = user_pkt_len + DEFAULT_REASON_ADJ + DEFAULT_SOP_ADJ;
539
540 if(reason == REASON_SEND_TO_NNI)
541 {
542 /* Copy in the entire packet as-is */
543 memcpy(p_pktout_ptr, p_user_pkt, user_pkt_len);
544 }
545 else
546 {
547 uint16_t pktout_offset = 0;
548
549 /* Copy in the L2 header (MAC DA/SA) */
550 memcpy(&p_pktout_ptr[pktout_offset], p_user_pkt, L2_HEADER_SIZE);
551
552 /* Point to the tunnel tag area in the outgoing message */
553 pktout_offset += L2_HEADER_SIZE;
554
555 /* Insert the TPID in the tag for the output destination */
556 uint16_num = htons(0x8100);
557 memcpy(&p_pktout_ptr[pktout_offset], &uint16_num, sizeof(uint16_num));
558
559 /* Point to the remainder of the outgoing message */
560 pktout_offset += TUNNEL_TAG_TPID_LEN;
561 /* Insert the tunnel tag vlan ID for the output destination */
562 uint16_num = htons(target_tunnel_id);
563 memcpy(&p_pktout_ptr[pktout_offset], &uint16_num, sizeof(uint16_num));
564
565 /* Point to the remainder of the outgoing message */
566 pktout_offset += TUNNEL_TAG_PBITS_CFI_VLAN_ID_LEN;
567
568 /* Copy in the rest of the message */
569 memcpy(&p_pktout_ptr[pktout_offset],
570 (p_user_pkt + L2_HEADER_SIZE),
571 (user_pkt_len - L2_HEADER_SIZE));
572
573 total_msg_size += TUNNEL_TAG_SIZE;
574 }
575
576
577 BCM_LOG(DEBUG, log_id_sw_util, "Packet send (user pkt_size:%d) destined for %s port %d\n",
578 user_pkt_len,
579 (reason == REASON_SEND_TO_PON) ? "PON" : "NNI",
580 dst_port_id);
581
582 if(reason == REASON_SEND_TO_PON)
583 {
584 BCM_LOG(DEBUG, log_id_sw_util, "Sending via GEM %d\n", target_tunnel_id);
585 }
586
587 if (bal_bcm_use_rpc_get())
588 {
589 /* On systems where BAL runs remotely from the switch hardware, we
590 * send the packet out message to the remote bcm.user process.
591 * That process then sends the attached user packet to the specified switch port.
592 */
593
594 sendto(target_device.socket,
595 p_pktout_msg,
596 total_msg_size, 0,
597 (struct sockaddr *) &(target_device.addr),
598 sizeof(struct sockaddr_in));
599
600 }
601 else
602 {
603 /* On systems where BAL runs on the CPU co-located with the switch hardware,
604 * we send the attached user packet to the specified switch port directly.
605 */
606
607 total_msg_size = total_msg_size - ( DEFAULT_REASON_ADJ + DEFAULT_SOP_ADJ );
608 dpp_dft_tx_cb(dst_device_id,
609 dst_port_id,
610 reason,
611 (unsigned char *)p_pktout_ptr,
612 total_msg_size);
613 }
614
615 bcmos_free(p_pktout_msg);
616
617 BCM_LOG(INFO, log_id_sw_util, "CPU packet msg sent to bcm.user for packet with msg size of %d (payload size: %d)\n",
618 total_msg_size, user_pkt_len);
619
620 return ret;
621}
622
623/*@}*/
624#endif /* #ifndef TEST_SW_UTIL_LOOPBACK */