blob: 6614b7c0b474c3ebf7c7821e9274eba8e6cf3565 [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.
*
* :>
*
*****************************************************************************/
/**
* @file bal_dpp_qos_map.c
* @brief BAL Switch Util QoS map management API
*
* This file contains the data structures and functions for
* configuring and managing the pcp bits translation services for
* DUNE Pack Processor (DPP).
*
* The pcp translation service is accomplished using ING ingress vlan translation API
* The API required a Qos map table for pcp translatin on a LIF.
* This file defines 15 pre-map tables for all known use cases.
*
* A set of utilities API are included for callers to determine which table to use
*
* ********************************************************************************
*
*/
/*@{*/
#ifndef TEST_SW_UTIL_LOOPBACK
#include <stdint.h>
#include "bcm_dev_log.h"
#include "bcmos_errno.h"
#include "bal_dpp_qos_map.h"
#include "bal_switch_util.h" /* for definition of log_id_sw_util */
#include "bcm/error.h"
#include "bcm/qos.h"
#define BAL_BCM_PCP_MAP_NUM 15
#define BAL_BCM_PCP_MAP_ENTRIES 8
#define BAL_BCM_MAX_PCP_VALUE 7
#define BAL_BCM_FIXED_PCP_MAP_NUM 8
const int g_bal_bcm_qos_pcp_map[BAL_BCM_PCP_MAP_NUM][BAL_BCM_PCP_MAP_ENTRIES] =
{
{0, 0, 0, 0, 0, 0, 0, 0}, /* 0-7 --> 0 */
{1, 1, 1, 1, 1, 1, 1, 1}, /* 0-7 --> 1 */
{2, 2, 2, 2, 2, 2, 2, 2}, /* 0-7 --> 2 */
{3, 3, 3, 3, 3, 3, 3, 3}, /* 0-7 --> 3 */
{4, 4, 4, 4, 4, 4, 4, 4}, /* 0-7 --> 4 */
{5, 5, 5, 5, 5, 5, 5, 5}, /* 0-7 --> 5 */
{6, 6, 6, 6, 6, 6, 6, 6}, /* 0-7 --> 6 */
{7, 7, 7, 7, 7, 7, 7, 7}, /* 0-7 --> 7 */
{1, 2, 3, 4, 5, 6, 7, 0}, /* 0-6 --> 1-7, 7 ->0 offset = 1 or -7 */
{2, 3, 4, 5, 6, 7, 0, 1}, /* 0-5 --> 2-7, 6-7->0-1 offset = 2 or -6 */
{3, 4, 5, 6, 7, 0, 1, 2}, /* 0-4 --> 3-7, 5-7->0-2 offset = 3 or -5 */
{4, 5, 6, 7, 0, 1, 2, 3}, /* 0-3 --> 4-7, 4-7->0-3 offset = 4 or -4 */
{5, 6, 7, 0, 1, 2, 3, 4}, /* 0-2 --> 5-7, 3-7->0-4 offset = 5 or -3 */
{6, 7, 0, 1, 2, 3, 4, 5}, /* 0-1 --> 6-7, 2-7->0-5 offset = 6 or -2 */
{7, 0, 1, 2, 3, 4, 5, 6}, /* 0 --> 7, 1-7->0-6 offset = 7 or -1 */
};
static int g_bal_bcm_pcp_remark_map_id[BAL_BCM_PCP_MAP_NUM];
/**************************************************************************/
/**
* @brief Create the PCP remark mapping tables
*
* This function creates the mapping from PCP bits in the
* frames received by DPP to the internal priority in
* DPP. The created map id are used in the ingress vlan translation API
* to perform PCP bits replacement.
*
*
* @param unit SDK unit number
*
* @return bcmos_errno
*
**************************************************************************/
bcmos_errno bal_sw_dpp_pcp_remark_maps_init(int unit)
{
bcm_error_t sdk_rc = BCM_E_NONE;
bcm_qos_map_t l2_in_map;
int map_id, pcp;
int32_t qos_map_id;
for(map_id=0; map_id < BAL_BCM_PCP_MAP_NUM; map_id++)
{
/* in case anything goes wrong */
g_bal_bcm_pcp_remark_map_id[map_id] = BAL_BCM_INVALID_PCP_MAP_ID;
/* Create a map object */
sdk_rc = bcm_qos_map_create(unit, BCM_QOS_MAP_INGRESS| BCM_QOS_MAP_L2_VLAN_PCP, &qos_map_id);
if (sdk_rc != BCM_E_NONE)
{
/* Error */
BCM_LOG(ERROR, log_id_sw_util,
"bcm_qos_map_create failed with %s\n",
bcm_errmsg(sdk_rc));
return BCM_ERR_INTERNAL;
}
/* Create a mapping for each PCP bits value. */
for (pcp = 0; pcp < BAL_BCM_PCP_MAP_ENTRIES; pcp++)
{
bcm_qos_map_t_init(&l2_in_map);
/* Ingress PCP/CoS value */
l2_in_map.pkt_pri = g_bal_bcm_qos_pcp_map[map_id][pcp];
/* Set internal priority for this ingress pri */
l2_in_map.int_pri = pcp;
/* Set color for this ingress Priority */
l2_in_map.color = bcmColorGreen;
sdk_rc = bcm_qos_map_add(unit, BCM_QOS_MAP_L2_OUTER_TAG|BCM_QOS_MAP_L2|BCM_QOS_MAP_L2_VLAN_PCP, &l2_in_map, qos_map_id);
if (sdk_rc != BCM_E_NONE)
{
/* Error */
BCM_LOG(ERROR, log_id_sw_util,
"bcm_qos_map_add failed with %s, for pcp %d\n",
bcm_errmsg(sdk_rc), pcp);
return BCM_ERR_INTERNAL;
}
}
g_bal_bcm_pcp_remark_map_id[map_id] = qos_map_id;
}
return BCM_ERR_OK;
}
/**************************************************************************/
/**
* @brief Retrieve PCP remark mapping table ID according to the translation
*
* This function retrieve the pre-created mapping table id associate with
* the translation.
* The created map id can be used in the ingress vlan translation API
* to perform PCP bits replacement.
*
* @param src_pcp the pcp value that need to be translated, or -1 for DONTCARE
* @param dst_pcp the translated pcp value
* @param p_map_id pointer for the retrieved id
*
* @return bcmos_errno
*
**************************************************************************/
bcmos_errno bal_sw_dpp_pcp_remark_map_get(int src_pcp, int dst_pcp, int *p_map_id)
{
int offset;
unsigned int indx;
if(dst_pcp < 0 || dst_pcp > BAL_BCM_MAX_PCP_VALUE)
{
BCM_LOG(ERROR, log_id_sw_util,
"%s(): invalid destination pcp = %d\n", __FUNCTION__, dst_pcp);
return BCM_ERR_PARM;
}
/* if source is DONTCARE, i.e map to a fixed PCP, use the first 8 map tables */
if(src_pcp == -1)
{
*p_map_id = g_bal_bcm_pcp_remark_map_id[dst_pcp];
}
else
{
if(src_pcp < 0 || src_pcp > BAL_BCM_MAX_PCP_VALUE)
{
BCM_LOG(ERROR, log_id_sw_util,
"%s(): invalid source pcp = %d\n", __FUNCTION__, src_pcp);
return BCM_ERR_PARM;
}
/* find out the offset between the src_pcp and dst_pcp */
offset = dst_pcp - src_pcp;
if (offset == 0)
{
BCM_LOG(ERROR, log_id_sw_util,
"%s(): source pcp %d == destination pcp %d\n", __FUNCTION__, src_pcp, dst_pcp);
return BCM_ERR_NOT_SUPPORTED;
}
if (offset < 0)
{
/* see comments in the above map tables */
offset += BAL_BCM_PCP_MAP_ENTRIES;
}
indx = offset + BAL_BCM_FIXED_PCP_MAP_NUM - 1;
if(indx >= BAL_BCM_PCP_MAP_NUM)
{
BCM_LOG(ERROR, log_id_sw_util,
"%s(): something is wrong, invalid map index = %d\n", __FUNCTION__, indx);
return BCM_ERR_INTERNAL;
}
/* index is 0 based */
*p_map_id = g_bal_bcm_pcp_remark_map_id[indx];
}
BCM_LOG(INFO, log_id_sw_util,
"%s(): pbits translate %d -> %d using bal qos map table %d, id 0x%x\n", __FUNCTION__, src_pcp, dst_pcp, indx, *p_map_id);
return BCM_ERR_OK;
}
#endif /* TEST_SW_UTIL_LOOPBACK */
/*@}*/