blob: fb1be7bd3915d489d3a11ceba9e8dba8518fc59c [file] [log] [blame]
/******************************************************************************
*
* <:copyright-BRCM:2016:DUAL/GPL:standard
*
* Copyright (c) 2016 Broadcom
* All Rights Reserved
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed
* to you under the terms of the GNU General Public License version 2
* (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
* with the following added to such license:
*
* As a special exception, the copyright holders of this software give
* you permission to link this software with independent modules, and
* to copy and distribute the resulting executable under terms of your
* choice, provided that you also meet, for each linked independent
* module, the terms and conditions of the license of that module.
* An independent module is a module which is not derived from this
* software. The special exception does not apply to any modifications
* of the software.
*
* Not withstanding the above, under no circumstances may you combine
* this software in any way with any other Broadcom software provided
* under a license other than the GPL, without Broadcom's express prior
* written consent.
*
* :>
*
*****************************************************************************/
#include <bal_common.h>
#include <bcm_dev_log.h>
#include <bal_msg.h>
#include "bal_switch_util.h"
#include "bal_switch_acc_term.h"
#include "bal_switch_flow.h"
#include <bal_worker.h>
/* declare ENV so that the bcm/rx.h in the bal_dpp_acc_term.h can create the correct bcm_pkt_t structure */
#ifdef ESW_SWITCH
#define BCM_ESW_SUPPORT 1
#else
#define BCM_DNX_SUPPORT 1
#endif
#include "esw/bal_esw_acc_term.h"
#include "dpp/bal_dpp_acc_term.h"
/* Below local functions are used for real logic only */
#ifndef TEST_SW_UTIL_LOOPBACK
#include <arpa/inet.h>
#include <bcm/init.h>
#include <bcm/types.h>
#include <bcm/port.h>
#include <appl/diag/shell.h> /* for .soc loading */
extern int socdiag_main(int argc, char *argv[]);
/**
* @file bal_switch_acc_term.c
* @brief BAL Switch util functions that handle access terminal requests
* @addtogroup sw_util
*
*/
/*@{*/
/* forward declaration */
static void sw_util_bcm_rx_cb (int unit, int port, int reason, unsigned char *p_payload, int payload_len);
/* define a customized dpp packetIn receive registration function.
* This function will be called when the HW trap a CPU bound packet
*/
static bcm_rx_t dpp_rx_cb_register(int unit, bcm_pkt_t *pkt, void *cookie)
{
int src_port, reason_code, payload_len;
unsigned char *p_payload;
/* extract trap code, ingress port and payload info */
src_port = pkt->src_port & 0xff;
reason_code = pkt->rx_trap_data;
p_payload = pkt->_pkt_data.data + (pkt->tot_len - pkt->pkt_len);
payload_len = pkt->pkt_len;
/* call sw_util_bcm_rx_cb to send packet to the BAL client */
sw_util_bcm_rx_cb(unit, src_port, reason_code, p_payload, payload_len);
return BCM_RX_HANDLED;
}
/* The default switch device the switch app is managed */
#ifdef CONFIG_SWITCH_RPC
static uint32_t g_dft_dev_id = 2;
#else
static uint32_t g_dft_dev_id = 0;
#endif
static uint32_t g_iwf_mode = 0;
static uint32_t g_l2_age_time = 300;
/* flag to determine if we need RPC for switch communication */
#ifdef CONFIG_SWITCH_RPC
static uint32_t g_use_rpc = 1;
#else
static uint32_t g_use_rpc = 0;
#endif
/* Socket to be connected to the switch driver msg receiving UDP port */
bcmos_bool g_pkt_send_is_initialized = BCMOS_FALSE;
static trap_target s_target_device;
/* Index to determine which interface mapping table should be used.
* The mapping table is HW specific and depend on how physical wires are lay out
* Any customized board may need a different table entry to reflect the connections
*/
static bal_swapp_port_map_indx g_intf_maptable = BAL_SWAPP_PORT_MAP_GPON;
/* the logical interface to KT2 port mapping table
the tables is index by technology then logical interface number that used in the BAL CLI
the data is the switch port-bit-map number and device number
*/
/* table with gpon technology
based on KT2 port config option 4 - see page 22 on KT2 data sheet */
/* gpon network interface mapping -
* KT2 is for Broadcom experiment purpose - not all function will work */
bal_swapp_port net_inf_map_gpon[] = {
{ 27, /* xe0 */ 0},
{ 28, /* xe1 */ 0},
{ 30, /* xe2 */ 0},
{ 33, /* xe3 */ 0},
{ 40, /* ge24 */ 0},
{ -1, /* end */ 0}
};
/* ARAD temp mapping xe128 - xe131 as nni ports */
/* ARAD is for Broadcom experiment purpose - not all function will work */
bal_swapp_port net_inf_map_exp[] = {
{ 128, /* xe128 */ 0},
{ 129, /* xe129 */ 0},
{ 130, /* xe130 */ 0},
{ 131, /* xe131 */ 0},
{ -1, /* end */ 0}
};
/* QAX temp mapping xe128-132 as nni ports 0-4 */
bal_swapp_port net_inf_map_exp2[] = {
{ 128, /* xe128 */ 0},
{ 129, /* xe129 */ 0},
{ 130, /* xe130 */ 0},
{ 131, /* xe131 */ 0},
{ 132, /* xe132 */ 0},
{ -1, /* end */ 0}
};
/* svk4 mapping xe128-133 as nni ports 0-5 */
bal_swapp_port net_inf_map_svk4[] = {
{ 128, /* xe128 */ 0},
{ 129, /* xe129 */ 0},
{ 130, /* xe130 */ 0},
{ 131, /* xe131 */ 0},
{ 132, /* xe132 */ 0},
{ 133, /* xe133 */ 0},
{ -1, /* end */ 0}
};
/* epon 10g-capable mapping xe128-135 as nni ports 0-7 (best guess - needs to be tested) */
bal_swapp_port net_inf_map_epon_tdma_10g[] = {
{ 128, /* xe128 */ 0},
{ 129, /* xe129 */ 0},
{ 130, /* xe130 */ 0},
{ 131, /* xe131 */ 0},
{ 132, /* xe132 */ 0},
{ 133, /* xe133 */ 0},
{ 134, /* xe134 */ 0},
{ 135, /* xe135 */ 0},
{ -1, /* end */ 0}
};
/* epon 1g only mapping - copied from gpon KT2 example above (best guess - needs to be tested) */
bal_swapp_port net_inf_map_epon_1g[] = {
{ 27, /* xe0 */ 0},
{ 28, /* xe1 */ 0},
{ 30, /* xe2 */ 0},
{ 33, /* xe3 */ 0},
{ 40, /* ge24 */ 0},
{ -1, /* end */ 0}
};
/* gpon pon interface mapping */
bal_swapp_port pon_inf_map_gpon[] = {
{ 5, /* ge4 */ 0},
{ 6, /* ge5 */ 0},
{ 2, /* ge1 */ 0},
{ 1, /* ge0 */ 0},
{ 8, /* ge7 */ 0},
{ 7, /* ge6 */ 0},
{ 4, /* ge3 */ 0},
{ 3, /* ge2 */ 0},
{ 12, /* ge11 */ 0},
{ 19, /* ge18 */ 0},
{ 10, /* ge9 */ 0},
{ 15, /* ge14 */ 0},
{ 11, /* ge10 */ 0},
{ 17, /* ge16 */ 0},
{ 9, /* ge8 */ 0},
{ 13, /* ge12 */ 0},
{ -1, /* end */ 0}
};
bal_swapp_port pon_inf_map_gpon_v3[] = {
{ 8, /* ge7 */ 0},
{ 7, /* ge6 */ 0},
{ 4, /* ge3 */ 0},
{ 3, /* ge2 */ 0},
{ 6, /* ge5 */ 0},
{ 5, /* ge4 */ 0},
{ 2, /* ge1 */ 0},
{ 1, /* ge0 */ 0},
{ 15, /* ge14 */ 0},
{ 16, /* ge15 */ 0},
{ 11, /* ge10 */ 0},
{ 12, /* ge11 */ 0},
{ 13, /* ge12 */ 0},
{ 14, /* ge13 */ 0},
{ 9, /* ge8 */ 0},
{ 10, /* ge9 */ 0},
{ -1, /* end */ 0}
};
/* ARAD temp mapping xe0 - xe3 as PON ports */
bal_swapp_port pon_inf_map_exp[] = {
{ 0, /* xe0 */ 0},
{ 1, /* xe1 */ 0},
{ 2, /* xe2 */ 0},
{ 3, /* xe3 */ 0},
{ -1, /* end */ 0}
};
/* QAX temp mapping xe1-6, as PON ports 0-5 */
bal_swapp_port pon_inf_map_exp2[] = {
{ 1, /* xe1 */ 0},
{ 2, /* xe2 */ 0},
{ 3, /* xe3 */ 0},
{ 4, /* xe4 */ 0},
{ 5, /* xe5 */ 0},
{ 6, /* xe6 */ 0},
{ -1, /* end */ 0}
};
/* svk4 mapping xe1-4, as PON ports 0-3 */
bal_swapp_port pon_inf_map_svk4[] = {
{ 1, /* xe1 */ 0},
{ 2, /* xe2 */ 0},
{ 3, /* xe3 */ 0},
{ 4, /* xe4 */ 0},
{ -1, /* end */ 0}
};
/* epon 10g-capable mapping xe1-8, as PON ports 0-7 (best guess - untested) */
bal_swapp_port pon_inf_map_epon_tdma_10g[] = {
{ 1, /* xe1 */ 0},
{ 2, /* xe2 */ 0},
{ 3, /* xe3 */ 0},
{ 4, /* xe4 */ 0},
{ 5, /* xe5 */ 0},
{ 6, /* xe6 */ 0},
{ 7, /* xe7 */ 0},
{ 8, /* xe8 */ 0},
{ -1, /* end */ 0}
};
/* epon 1g mapping xe1-16, as PON ports 0-15 (best guess - untested) */
bal_swapp_port pon_inf_map_epon_1g[] = {
{ 1, /* xe1 */ 0},
{ 2, /* xe2 */ 0},
{ 3, /* xe3 */ 0},
{ 4, /* xe4 */ 0},
{ 5, /* xe5 */ 0},
{ 6, /* xe6 */ 0},
{ 7, /* xe7 */ 0},
{ 8, /* xe8 */ 0},
{ 9, /* xe9 */ 0},
{ 10, /* xe10 */ 0},
{ 11, /* xe11 */ 0},
{ 12, /* xe12 */ 0},
{ 13, /* xe13 */ 0},
{ 14, /* xe14 */ 0},
{ 15, /* xe15 */ 0},
{ 16, /* xe16 */ 0},
{ -1, /* end */ 0}
};
/* network interface mapping table */
bal_swapp_port *g_net_inf_map_table[BAL_SWAPP_PORT_MAP__NUM_OF] = {
net_inf_map_gpon, /* BAL_SWAPP_PORT_MAP_GPON */
net_inf_map_gpon, /* BAL_SWAPP_PORT_MAP_GPON_V3 */
net_inf_map_exp, /* BAL_SWAPP_PORT_MAP_EXP */
net_inf_map_exp2, /* BAL_SWAPP_PORT_MAP_EXP2 */
net_inf_map_svk4, /* BAL_SWAPP_PORT_MAP_SVK4 */
net_inf_map_epon_tdma_10g, /* BAL_SWAPP_PORT_MAP_EPON_TDMA */
net_inf_map_epon_1g, /* BAL_SWAPP_PORT_MAP_EPON_1G */
net_inf_map_epon_tdma_10g, /* BAL_SWAPP_PORT_MAP_EPON_10G */
};
/* pon interface mapping table */
bal_swapp_port *g_pon_inf_map_table[BAL_SWAPP_PORT_MAP__NUM_OF] = {
pon_inf_map_gpon, /* BAL_SWAPP_PORT_MAP_GPON */
pon_inf_map_gpon_v3, /* BAL_SWAPP_PORT_MAP_GPON_V3 */
pon_inf_map_exp, /* BAL_SWAPP_PORT_MAP_EXP */
pon_inf_map_exp2, /* BAL_SWAPP_PORT_MAP_EXP2 */
pon_inf_map_svk4, /* BAL_SWAPP_PORT_MAP_SVK4 */
pon_inf_map_epon_tdma_10g, /* BAL_SWAPP_PORT_MAP_EPON_TDMA */
pon_inf_map_epon_1g, /* BAL_SWAPP_PORT_MAP_EPON_1G */
pon_inf_map_epon_tdma_10g, /* BAL_SWAPP_PORT_MAP_EPON_10G */
};
/* network interface mapping table size */
int g_net_inf_map_table_size[BAL_SWAPP_PORT_MAP__NUM_OF] = {
sizeof(net_inf_map_gpon)/sizeof(net_inf_map_gpon[0]), /* BAL_SWAPP_PORT_MAP_GPON */
sizeof(net_inf_map_gpon)/sizeof(net_inf_map_gpon[0]), /* BAL_SWAPP_PORT_MAP_GPON_V3 */
sizeof(net_inf_map_exp)/sizeof(net_inf_map_exp[0]), /* BAL_SWAPP_PORT_MAP_EXP */
sizeof(net_inf_map_exp2)/sizeof(net_inf_map_exp2[0]), /* BAL_SWAPP_PORT_MAP_EXP2 */
sizeof(net_inf_map_svk4)/sizeof(net_inf_map_svk4[0]), /* BAL_SWAPP_PORT_MAP_SVK4 */
sizeof(net_inf_map_epon_tdma_10g)/sizeof(net_inf_map_epon_tdma_10g[0]), /* BAL_SWAPP_PORT_MAP_EPON_TDMA */
sizeof(net_inf_map_epon_1g)/sizeof(net_inf_map_epon_1g[0]), /* BAL_SWAPP_PORT_MAP_EPON_1G */
sizeof(net_inf_map_epon_tdma_10g)/sizeof(net_inf_map_epon_tdma_10g[0]), /* BAL_SWAPP_PORT_MAP_EPON_10G */
};
/* pon interface mapping table size */
int g_pon_inf_map_table_size[BAL_SWAPP_PORT_MAP__NUM_OF] = {
sizeof(pon_inf_map_gpon)/sizeof(pon_inf_map_gpon[0]), /* BAL_SWAPP_PORT_MAP_GPON */
sizeof(pon_inf_map_gpon_v3)/sizeof(pon_inf_map_gpon_v3[0]), /* BAL_SWAPP_PORT_MAP_GPON_V3 */
sizeof(pon_inf_map_exp)/sizeof(pon_inf_map_exp[0]), /* BAL_SWAPP_PORT_MAP_EXP */
sizeof(pon_inf_map_exp2)/sizeof(pon_inf_map_exp2[0]), /* BAL_SWAPP_PORT_MAP_EXP2 */
sizeof(pon_inf_map_svk4)/sizeof(pon_inf_map_svk4[0]), /* BAL_SWAPP_PORT_MAP_SVK4 */
sizeof(pon_inf_map_epon_tdma_10g)/sizeof(pon_inf_map_epon_tdma_10g[0]), /* BAL_SWAPP_PORT_MAP_EPON_TDMA */
sizeof(pon_inf_map_epon_1g)/sizeof(pon_inf_map_epon_1g[0]), /* BAL_SWAPP_PORT_MAP_EPON_1G */
sizeof(pon_inf_map_epon_tdma_10g)/sizeof(pon_inf_map_epon_tdma_10g[0]), /* BAL_SWAPP_PORT_MAP_EPON_10G */
};
/**
* @brief get the number of valid network interface
* @return num_nni number of nni interfaces
*/
int bal_bcm_net_inf_map_size_get()
{
return g_net_inf_map_table_size[g_intf_maptable];
};
/**
* @brief get the number of valid pon interface
* @return num_nni number of pon interfaces
*/
int bal_bcm_pon_inf_map_size_get()
{
return g_pon_inf_map_table_size[g_intf_maptable];
};
/**
* @brief get KT2 PBM of a network interface from current mapping table
*
* @param net_inf_id logical nni interface number from CLI
*
* @return pbm PortBitMap that will be used in bcm api calls
*/
uint32_t bal_bcm_net_inf_pbm_get(uint32_t net_inf_id)
{
bal_swapp_port *port = (g_net_inf_map_table[g_intf_maptable] + net_inf_id);
return port->pbm_id;
};
/**
* @brief get bal nni port number (index of the mapping table) of a physical nni interface
*
* @param nni_id physical nni interface in the switch
*
* @return index index to PortBitMap that contains the physical interface number
*/
int bal_bcm_net_inf_idx_get(uint32_t nni_id)
{
int indx;
bal_swapp_port *port = g_net_inf_map_table[g_intf_maptable];
for( indx = 0; port->pbm_id != -1; indx++)
{
if (port->pbm_id == nni_id)
{
break;
}
port++;
}
if (port->pbm_id == -1)
{
return -1;
}
else
{
return indx;
}
}
/**
* @brief get KT2 device id of a network interface from current mapping table
*
* @param net_inf_id logical nni interface number from CLI
*
* @return pbm device number that will be used in bcm api calls
*/
int bal_bcm_net_inf_dev_get(uint32_t net_inf_id)
{
if(net_inf_id > sizeof(g_net_inf_map_table))
{
return bal_bcm_dft_dev_get();
}
else
{
bal_swapp_port *port = (g_net_inf_map_table[g_intf_maptable] + net_inf_id);
return port->device_id;
}
};
/**
* @brief get KT2 PBM of a pon interface from current mapping table
*
* @param pon_inf_id logical pon interface number from CLI
*
* @return pbm PortBitMap that will be used in bcm api calls
*/
uint32_t bal_bcm_pon_inf_pbm_get(uint32_t pon_inf_id)
{
bal_swapp_port *port = (g_pon_inf_map_table[g_intf_maptable] + pon_inf_id);
return port->pbm_id;
};
/**
* @brief get bal pon port number (index of the mapping table) of a physical pon interface
*
* @param pon_id physical pon interface in the switch
*
* @return index index to PortBitMap that contains the physical interface number
*/
int bal_bcm_pon_inf_idx_get(uint32_t pon_id)
{
int indx;
bal_swapp_port *port = g_pon_inf_map_table[g_intf_maptable];
for( indx = 0; port->pbm_id != -1; indx++)
{
if (port->pbm_id == pon_id)
{
break;
}
port++;
}
if (port->pbm_id == -1)
{
return -1;
}
else
{
return indx;
}
}
/**
* @brief get KT2 device number of a pon interface from current mapping table
*
* @param pon_inf_id logical pon interface number from CLI
*
* @return pbm device number that will be used in bcm api calls
*/
int bal_bcm_pon_inf_dev_get(uint32_t pon_inf_id)
{
if(pon_inf_id > sizeof(g_pon_inf_map_table))
{
return bal_bcm_dft_dev_get();
}
else
{
bal_swapp_port *port = (g_pon_inf_map_table[g_intf_maptable] + pon_inf_id);
return port->device_id;
}
};
/**
* @brief setting the local default device id
*/
void bal_bcm_dft_dev_set(uint32_t id)
{
g_dft_dev_id = (int)id;
}
/**
* @brief getting the local default device id
*/
uint32_t bal_bcm_dft_dev_get()
{
return g_dft_dev_id;
}
/**
* @brief setting the L2 table aging time (seconds)
*/
void bal_bcm_l2_age_time_set(uint32_t age_time)
{
g_l2_age_time = age_time;
}
/**
* @brief getting current L2 table aging time value
*/
uint32_t bal_bcm_l2_age_time_get()
{
return g_l2_age_time;
}
/**
* @brief getting the device type
*/
uint32_t bal_bcm_dev_type_get(uint32_t id)
{
int rc;
bcm_info_t dev_info;
rc = bcm_info_get(id, &dev_info);
if (rc)
{
return 0;
}
return dev_info.device;
}
/**
* @brief getting the iwf mode of an access terminal
*/
uint32_t bal_bcm_iwf_mode_get()
{
/* currently only support one access terminal */
BCM_LOG(DEBUG, log_id_sw_util, " Get iwf mode for acc_term\n");
return g_iwf_mode;
}
/**
* @brief setting the use of RPC (remote) or not (local)
*/
void bal_bcm_use_rpc_set(uint32_t use_rpc)
{
g_use_rpc = (int)use_rpc;
}
/**
* @brief getting the use of RPC (remote) or not (local)
*/
bcmos_bool bal_bcm_use_rpc_get(void)
{
if (g_use_rpc)
{
return BCMOS_TRUE;
}
else
{
return BCMOS_FALSE;
}
}
static void sw_util_bcm_rx_cb (int unit, int port, int reason, unsigned char *p_payload, int payload_len)
{
int i, len, obj_len;
unsigned char *payload;
char bytestr[32];
char *p_bytestr = bytestr;
BCM_LOG(INFO, log_id_sw_util, "BAL: Captured packet from datapath (len: %d bytes)\n", payload_len);
BCM_LOG(DEBUG, log_id_sw_util, " ingress port %d\n", port);
BCM_LOG(DEBUG, log_id_sw_util, " rcv reason 0x%x\n", reason);
len = (payload_len > 64)? 64 : payload_len;
/* dump out the captured packet */
payload = p_payload;
BCM_LOG(DEBUG, log_id_sw_util, " payload: (first %d bytes shown)", len);
for(i=0; i<len; i++)
{
if ( i%8 == 0)
{
sprintf(p_bytestr, "\n");
BCM_LOG(DEBUG, log_id_sw_util, "%s", bytestr);
p_bytestr = bytestr;
}
sprintf(p_bytestr, " %02x", *payload++);
p_bytestr += 3;
}
/* Log the string being crafted when the loop terminated */
sprintf(p_bytestr, "\n");
BCM_LOG(DEBUG, log_id_sw_util, "%s", bytestr);
/* Send Auto Indication */
if ( p_bal_core_to_api_ind_queue )
{
bcmbal_packet_cfg *p_ind_msg = NULL;
bcmbal_packet_key key;
bal_sw_flow *p_flow_elm;
int tmp_port;
/* find the flow info corresponding to this trap REASON */
p_flow_elm = bal_sw_util_flow_list_get_by_trap_code(reason);
if(p_flow_elm == NULL)
{
BCM_LOG(WARNING, log_id_sw_util, " TrapCallBack: Can't match trap code 0x%x to element in flow list\n", reason);
return;
}
/* The packet indication object contains the bcmbal_packet_cfg structure plus the captured packet
* content
*/
obj_len = payload_len + sizeof(bcmbal_packet_cfg);
p_ind_msg = bcmbal_msg_calloc(obj_len);
if(p_ind_msg == NULL)
{
BCM_LOG(ERROR, log_id_sw_util, " TrapCallBack: No memory to send indication\n");
return;
}
key.packet_send_dest.type = BCMBAL_DEST_TYPE_HOST;
BCMBAL_CFG_INIT(p_ind_msg, packet, key);
BCMBAL_CFG_PROP_SET(p_ind_msg, packet, flow_id, p_flow_elm->id);
BCMBAL_CFG_PROP_SET(p_ind_msg, packet, svc_port, p_flow_elm->svc_port);
BCMBAL_CFG_PROP_SET(p_ind_msg, packet, flow_cookie, p_flow_elm->flow_cookie);
/* first search the PON table */
tmp_port = bal_bcm_pon_inf_idx_get(port);
if( tmp_port != -1)
{
BCMBAL_CFG_PROP_SET(p_ind_msg, packet, flow_type, BCMBAL_FLOW_TYPE_UPSTREAM);
BCMBAL_CFG_PROP_SET(p_ind_msg, packet, intf_id, tmp_port);
BCMBAL_CFG_PROP_SET(p_ind_msg, packet, intf_type, BCMBAL_INTF_TYPE_PON);
}
else /* if failed, search for NNI table */
{
tmp_port = bal_bcm_net_inf_idx_get(port);
if( tmp_port != -1)
{
BCMBAL_CFG_PROP_SET(p_ind_msg, packet, flow_type, BCMBAL_FLOW_TYPE_DOWNSTREAM);
BCMBAL_CFG_PROP_SET(p_ind_msg, packet, intf_id, tmp_port);
BCMBAL_CFG_PROP_SET(p_ind_msg, packet, intf_type, BCMBAL_INTF_TYPE_NNI);
}
}
/* if both failed, return */
if(tmp_port == -1)
{
/* something went wrong, free up the message */
bcmbal_msg_free(p_ind_msg);
BCM_LOG(ERROR, log_id_sw_util, " TrapCallBack: can't match ingress port to bal port tables\n");
return;
}
((bcmbal_obj *)p_ind_msg)->status = BCM_ERR_OK;
((bcmbal_obj *)p_ind_msg)->obj_type = BCMBAL_OBJ_ID_PACKET;
((bcmbal_obj *)p_ind_msg)->group = BCMBAL_MGT_GROUP_AUTO;
/* now copy the contents of the packet */
p_ind_msg->data.pkt.val = (uint8_t *)(p_ind_msg + 1);
memcpy(p_ind_msg->data.pkt.val, p_payload, payload_len);
/* and record the length of the captured packet */
p_ind_msg->data.pkt.len = payload_len;
BCMBAL_PROP_SET_PRESENT(p_ind_msg, packet, _cfg, pkt);
BCM_LOG(INFO, log_id_sw_util, " TrapCallBack: Flow id = %d, type=%d, Interface id = %d, type=%d, svc_port=%d\n",
p_ind_msg->data.flow_id, p_ind_msg->data.flow_type,
p_ind_msg->data.intf_id, p_ind_msg->data.intf_type,
p_ind_msg->data.svc_port);
/* Send this indication straight to the API client
*/
bcmbal_msg_hdr_set(p_ind_msg,
BCMBAL_MGMT_API_IND_MSG,
BAL_MSG_TYPE_AUTO_IND,
BAL_SUBSYSTEM_CORE,
BCMBAL_OBJ_ID_PACKET,
0, /* operation code */
0); /* exchange id */
if(BCM_ERR_OK != bcmbal_msg_send(p_bal_core_to_api_ind_queue,
p_ind_msg,
BCMOS_MSG_SEND_AUTO_FREE))
{
BCM_LOG(ERROR, log_id_sw_util, " TrapCallBack: send auto indication failed\n");
}
else
{
BCM_LOG(DEBUG, log_id_sw_util, " TrapCallBack: auto indication sent\n");
}
}
else
{
BCM_LOG(ERROR, log_id_sw_util, " TrapCallBack: no auto indication queue\n");
}
return;
}
/**
* @brief Connect access terminal
*
* This routine is called by acc_term_fsm in the BAL core
* Upon receiving the request from the core, this function
* assign the device number that each logical nni or pon interface belong
* and restrict the egress ports of each interface. This mapping is highly
* topology dependent and should be customized according to the actual hardware
* layout.
* @param p_acc_term Pointer to access terminal instance
*
* @return bcmos_errno
*/
static bcmos_errno sw_util_access_terminal_connect(acc_term_inst *p_acc_term)
{
bcmos_errno ret = BCM_ERR_INTERNAL;
int rc;
bal_swapp_port *port;
char *argv[] = { "socdiag", NULL };
uint32_t dev_type;
BCM_LOG(INFO, log_id_sw_util, " Got a access terminal SET\n");
/* make sure the abstraction layer is initialized - no harm to initialize multiple time */
bcmos_init();
/* Initialize SDK */
rc = socdiag_main(1, argv);
if (rc)
{
BCM_LOG(ERROR, log_id_sw_util, " Init BCM SDK failed - %d\n", rc);
return BCM_ERR_INTERNAL;
}
BCM_LOG(INFO, log_id_sw_util, " %s RPC\n", (1 == g_use_rpc) ? "Using" : "Not using" );
/* use a soc script to establish rpc connection if switch is remotely located */
if (bal_bcm_use_rpc_get())
{
sleep(3); /* allow remote device to settle */
BCM_LOG(INFO, log_id_sw_util, " starting RPC connection\n");
rc = sh_rcload_file(-1, NULL, "rpc.soc", 0);
if (rc)
{
BCM_LOG(ERROR, log_id_sw_util, " start RPC connection failed\n");
return BCM_ERR_INTERNAL;
}
}
BCM_LOG(INFO, log_id_sw_util, " Using interface table: %d Device: %d\n", g_intf_maptable, g_dft_dev_id );
/* setup the device ID - This is very hardware specific */
port = g_net_inf_map_table[g_intf_maptable];
/* -1 indicate end of table */
while(port->pbm_id != -1)
{
port->device_id = g_dft_dev_id;
port++;
}
port = g_pon_inf_map_table[g_intf_maptable];
while(port->pbm_id != -1)
{
port->device_id = g_dft_dev_id;
port++;
}
/* get the switch model from the chip */
dev_type = bal_bcm_dev_type_get(g_dft_dev_id);
if (dev_type == 0)
{
BCM_LOG(ERROR, log_id_sw_util, " Error retrieving device type on access-terminal connect: 0x%x\n", dev_type);
return BCM_ERR_INTERNAL;
}
/* set up the valid egress ports for net/pon facing ports */
if (dev_type == BCM_DEVICE_KT2)
{
ret = sw_util_esw_acc_term_connect(g_net_inf_map_table[g_intf_maptable], g_pon_inf_map_table[g_intf_maptable]);
}
else if (dev_type == BCM_DEVICE_ARAD || dev_type == BCM_DEVICE_ARAD_PLUS || dev_type == BCM_DEVICE_QAX)
{
/* for rpc case, dpp use a special api to register rx callback.
for non-rpc use case, use bcm_rx_register() to register the rx callback
*/
if (bal_bcm_use_rpc_get())
{
/* if the trap receive udp port in bal_config.ini is not zero, start a receiving thread */
if(bal_bcm_trap_rcv_port_get())
{
sw_util_dpp_rx_cb_register(bal_bcm_dft_dev_get(), sw_util_bcm_rx_cb);
}
else
{
BCM_LOG(ERROR, log_id_sw_util, "Missing UDP port number for RPC packet In receiver \n");
return BCM_ERR_INTERNAL;
}
}
else
{
bcm_rx_register(bal_bcm_dft_dev_get(), "Bal Cpu Traps", dpp_rx_cb_register, 50, NULL, BCM_RCO_F_ALL_COS);
}
ret = sw_util_dpp_acc_term_connect(g_net_inf_map_table[g_intf_maptable], g_pon_inf_map_table[g_intf_maptable]);
}
BCM_LOG(INFO, log_id_sw_util, " Return access terminal connect request with %d on device 0x%x\n", ret, dev_type );
/* for now, only support one iwf */
g_iwf_mode = (uint32_t)p_acc_term->api_req_acc_term_obj_info.data.iwf_mode;
return ret;
}
/**
* @brief getting the interface mapping table that applied to the HW connections
*/
bal_swapp_port_map_indx bal_bcm_intf_maptable_get()
{
return g_intf_maptable;
}
/**
* @brief SWITCH module: internal packet_send function
*
* This routine distribute the SEND function to supported switch family
*
* @param dst_port_id Switch port id the packet is going to be sent out
* @param reason REASON_SEND_TO_NNI or REASON_SEND_TO_PON
* @param payload pointer to the data
* @param payload_len the length of the data
* @param tunnel_id pon port tunnel id if REASON_SEND_TO_PON
*
* @return bcmos_errno
*/
static bcmos_errno sw_util_pkt_send_intl(int dst_port_id,
int reason,
unsigned char *payload,
int payload_len,
int tunnel_id)
{
uint32_t dev_type;
bcmos_errno ret = BCM_ERR_OK;
/* get the switch chip type from default device id
TBD - in the future, the device id should be obtained from port mapping table */
dev_type = bal_bcm_dev_type_get(g_dft_dev_id);
if (dev_type == 0)
{
BCM_LOG(ERROR, log_id_sw_util, " Error retrieving device type on pkt send: 0x%x\n", dev_type);
return BCM_ERR_INTERNAL;
}
/* set up the valid egress ports for net/pon facing ports */
if (dev_type == BCM_DEVICE_KT2)
{
return BCM_ERR_NOT_SUPPORTED;
}
else if (dev_type == BCM_DEVICE_ARAD || dev_type == BCM_DEVICE_ARAD_PLUS || dev_type == BCM_DEVICE_QAX)
{
ret = sw_util_dpp_pkt_send(dst_port_id, reason, payload, payload_len, s_target_device, tunnel_id);
}
else
{
ret = BCM_ERR_NOT_SUPPORTED;
}
BCM_LOG(INFO, log_id_sw_util, " Return access terminal connect request with %d on device 0x%x\n", ret, dev_type );
return ret;
}
#endif /* #ifndef TEST_SW_UTIL_LOOPBACK */
/* the listening UDP port that the switch will send the trapped messages */
static uint32_t g_trap_rcv_port = 0;
/**
* @brief set the receiving UDP port for trap packets - from config file
*/
uint32_t bal_bcm_trap_rcv_port_set(uint32_t udp_port)
{
g_trap_rcv_port = udp_port;
return 0;
}
/**
* @brief getting the receiving UDP port for trap packets
*/
uint32_t bal_bcm_trap_rcv_port_get()
{
return g_trap_rcv_port;
}
/* the global portChannel DownStream Max rate scheduling mode */
static uint32_t g_ds_sched_mode = 0; /* default to strict priority */
/**
* @brief set the DS max rate scheduling mode - from config file
*/
uint32_t bal_bcm_ds_sched_mode_set(uint32_t sched_mode)
{
g_ds_sched_mode = sched_mode;
return 0;
}
/**
* @brief getting the DS max rate scheduling mode
*/
uint32_t bal_bcm_ds_sched_mode_get()
{
return g_ds_sched_mode;
}
/**
* @brief SWITCH module: access terminal SET handler
*
* This routine is called by acc_term_fsm in the BAL core upon
* SET request for acc_terminal object.
*
* @param p_acc_term Pointer to access terminal instance
* @param opt_type Operation type on access terminal instance
*
* @return bcmos_errno
*/
bcmos_errno sw_util_access_terminal_set(acc_term_inst *p_acc_term,
bal_util_oper_acc_term opt_type)
{
bcmos_errno ret = BCM_ERR_OK;
if (opt_type != BAL_UTIL_OPER_ACC_TERM_CONNECT)
{
BCM_LOG(ERROR, log_id_sw_util, " Access terminal currently supports only CONNECT request\n");
return BCM_ERR_NOT_SUPPORTED;
}
#ifndef TEST_SW_UTIL_LOOPBACK
ret = sw_util_access_terminal_connect(p_acc_term);
#else
BCM_LOG(INFO, log_id_sw_util, " dummy SUCCESS\n");
#endif
return ret;
}
/**
* @brief setting the interface mapping table that applied to the HW connections
*/
int bal_bcm_intf_maptable_set(uint32_t intf_maptable)
{
int ret = 0;
#ifndef TEST_SW_UTIL_LOOPBACK
switch(intf_maptable)
{
case 0:
g_intf_maptable = BAL_SWAPP_PORT_MAP_GPON;
break;
case 1:
g_intf_maptable = BAL_SWAPP_PORT_MAP_GPON_V3;
break;
case 2:
g_intf_maptable = BAL_SWAPP_PORT_MAP_EXP;
break;
case 3:
g_intf_maptable = BAL_SWAPP_PORT_MAP_EXP2;
break;
case 4:
g_intf_maptable = BAL_SWAPP_PORT_MAP_SVK4;
break;
case 5:
g_intf_maptable = BAL_SWAPP_PORT_MAP_EPON_TDMA;
break;
case 6:
g_intf_maptable = BAL_SWAPP_PORT_MAP_EPON_1G;
break;
case 7:
g_intf_maptable = BAL_SWAPP_PORT_MAP_EPON_10G;
break;
default:
BCM_LOG(ERROR, log_id_sw_util, " Mapping Table Id %d is not supported\n", intf_maptable);
ret = BCM_ERR_NOT_SUPPORTED;
break;
}
#endif
return ret;
}
/**
* @brief SWITCH module: packet_send
*
* This routine is called by work thread in the BAL core upon
* user request to send a raw packet out of a switch port.
*
* @param dst_port_id Switch port id the packet is going to be sent out
* @param reason REASON_SEND_TO_NNI or REASON_SEND_TO_PON
* @param payload pointer to the data
* @param payload_len the length of the data
* @param tunnel_id pon tunnel_id
*
* @return bcmos_errno
*/
bcmos_errno sw_util_pkt_send(int dst_port_id,
int reason,
unsigned char *payload,
int payload_len,
int tunnel_id)
{
bcmos_errno ret = BCM_ERR_OK;
if ( reason != REASON_SEND_TO_NNI && reason != REASON_SEND_TO_PON)
{
BCM_LOG(ERROR, log_id_sw_util, " pkt_send currently does not support reason %d\n", reason);
return BCM_ERR_NOT_SUPPORTED;
}
if ( reason == REASON_SEND_TO_NNI && BCMOS_FALSE == bcm_topo_nni_is_valid(dst_port_id))
{
BCM_LOG(ERROR, log_id_sw_util, " pkt_send to invalid nni port %d\n", dst_port_id);
return BCM_ERR_PARM;
}
#ifndef TEST_SW_UTIL_LOOPBACK
ret = sw_util_pkt_send_intl(dst_port_id, reason, payload, payload_len, tunnel_id);
#else
BCM_LOG(INFO, log_id_sw_util, " dummy SUCCESS\n");
#endif
return ret;
}
/*
* Called from bal_core to set up the packet out server IP:port (i.e. the bcm_user process location)
* when Switch is on the same board where the core is run, there is no RPC and this init function should not be called
*/
bcmos_errno sw_util_pkt_send_init(const char *pkt_send_server_ip, uint16_t pkt_send_server_listen_port)
{
bcmos_errno ret = BCM_ERR_OK;
#ifndef TEST_SW_UTIL_LOOPBACK
do
{
/* If the packet_out interface has already been initialized, just return OK */
if(g_pkt_send_is_initialized == BCMOS_FALSE)
{
#ifdef CONFIG_SWITCH_RPC
/*
* Set up the socket to be used for sending "packet send" messages
* to the bcm.user server
*/
if((s_target_device.socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
{
ret = BCM_ERR_NORES;
break;
}
s_target_device.addr.sin_family = AF_INET;
inet_pton(s_target_device.addr.sin_family, pkt_send_server_ip, &s_target_device.addr.sin_addr.s_addr);
s_target_device.addr.sin_port = htons(pkt_send_server_listen_port);
#endif /* CONFIG_SWITCH_RPC */
g_pkt_send_is_initialized = BCMOS_TRUE;
}
}
while(0);
#endif /*TEST_SW_UTIL_LOOPBACK*/
return ret;
}
/*@}*/