blob: 9be3e0fa2526d4dd18e01692ff1c94e277bd679a [file] [log] [blame]
/* FILE NAME: air_acl.c
* PURPOSE:
* Define the ACL function in AIR SDK.
*
* NOTES:
* None
*/
/* INCLUDE FILE DECLARATIONS
*/
#include "air.h"
/* NAMING CONSTANT DECLARATIONS
*/
/* MACRO FUNCTION DECLARATIONS
*/
#define ACL_DERIVE_TBL_MULTIFIELDS(data_buffer, offset, width, dst) \
({ \
UI32_T value = 0; \
_deriveTblMultiFields((data_buffer), (offset), (width), &value); \
dst = value; \
})
/* DATA TYPE DECLARATIONS
*/
/* GLOBAL VARIABLE DECLARATIONS
*/
/* LOCAL SUBPROGRAM DECLARATIONS
*/
/* STATIC VARIABLE DECLARATIONS
*/
/* LOCAL SUBPROGRAM BODIES
*/
static AIR_ERROR_NO_T
_checkDone(
const UI32_T unit,
const AIR_ACL_CHECK_TYPE_T type)
{
UI32_T check_bit = 0, i = 0, reg = 0, value = 0, offset = 0;
switch(type)
{
case AIR_ACL_CHECK_ACL:
check_bit = 1;
reg = ACL_MEM_CFG;
offset = ACL_MEM_CFG_DONE_OFFSET;
break;
case AIR_ACL_CHECK_UDF:
check_bit = 0;
reg = ACL_AUTC;
offset = ACL_UDF_ACC_OFFSET;
break;
case AIR_ACL_CHECK_TRTCM:
check_bit = 0;
reg = ACL_TRTCMA;
offset = ACL_TRTCM_BUSY_OFFSET;
break;
case AIR_ACL_CHECK_METER:
check_bit = 0;
reg = ACLRMC;
offset = ACL_RATE_BUSY_OFFSET;
break;
default:
return AIR_E_BAD_PARAMETER;
}
for(i=0; i < ACL_MAX_BUSY_TIME; i++)
{
aml_readReg(unit, reg, &value);
if (check_bit == (value >> offset))
{
break;
}
AIR_UDELAY(1);
}
if(i >= ACL_MAX_BUSY_TIME)
{
return AIR_E_TIMEOUT;
}
return AIR_E_OK;
}
static void
_convertToTCcell(
const UI32_T *data0,
const UI32_T *data1,
UI32_T *arr0,
UI32_T *arr1,
UI32_T size)
{
UI32_T i = 0;
for(i = 0; i < size; i++)
{
arr0[i] = data0[i] | (~data1[i]);
arr1[i] = (~data0[i]) | (~data1[i]);
}
}
static void
_parseFromTCcell(
const UI32_T *data0,
const UI32_T *data1,
UI32_T *arr0,
UI32_T *arr1,
UI32_T size)
{
UI32_T i = 0;
for(i = 0; i < size; i++)
{
arr1[i] = ~(data0[i] & data1[i]);
arr0[i] = data0[i] | (~arr1[i]);
}
}
static int
_fillTblMultiFields(
UI32_T *data_buffer,
UI32_T data_count,
const UI32_T offset,
const UI32_T width,
const UI32_T value)
{
UI32_T data_index = 0, bit_index = 0;
UI32_T extended_data[2] = {0};
UI32_T extended_mask[2] = {0};
UI32_T msk;
UI32_T val;
AIR_CHECK_PTR(data_buffer);
if((0 == data_count) || (0 == width) || (width > 32) || (offset+width > data_count*32))
{
return 0;
}
msk = ((1U<<(width-1U))<<1U)-1U;
val = value & msk;
data_index = offset / 32;
bit_index = offset % 32;
extended_data[0] = val << bit_index;
extended_data[1] = (val >> (31U-bit_index))>>1U;
extended_mask[0] = msk << bit_index;
extended_mask[1] = (msk >> (31U-bit_index))>>1U;
data_buffer[data_index] = (data_buffer[data_index] & ~extended_mask[0]) | extended_data[0];
if ((data_index+1)<data_count)
{
data_buffer[data_index+1] = (data_buffer[data_index+1] & ~extended_mask[1]) | extended_data[1];
}
return 0;
}
static int
_deriveTblMultiFields(
UI32_T *data_buffer,
const UI32_T offset,
const UI32_T width,
UI32_T *ptr_value)
{
UI32_T data_index = 0, bit_index = 0;
UI32_T extended_data[2] = {0};
UI32_T extended_mask[2] = {0};
UI32_T msk = 0;
AIR_CHECK_PTR(data_buffer);
AIR_CHECK_PTR(ptr_value);
if(width==0 || width>32)
{
return 0;
}
msk = ((1U<<(width-1U))<<1U)-1U;
data_index = offset / 32;
bit_index = offset % 32;
extended_mask[0] = msk << bit_index;
extended_mask[1] = (msk >> (31U-bit_index))>>1U;
extended_data[0] = (data_buffer[data_index] & extended_mask[0]) >> bit_index;
extended_data[1] = ((data_buffer[data_index+1] & extended_mask[1]) << (31U-bit_index))<<1U;
*ptr_value = extended_data[0] | extended_data[1];
return 0;
}
static void
_air_acl_setRuleTable(
const AIR_ACL_RULE_TYPE_T type,
const BOOL_T iskey,
const AIR_ACL_FIELD_T *ptr_field,
UI32_T *data)
{
UI32_T n = 0;
switch(type)
{
case AIR_ACL_RULE_TYPE_0:
if(TRUE == iskey)
{
_fillTblMultiFields(data, 12, RULE_TYPE0_OFFSET, RULE_TYPE0_WIDTH, 0);
}
else
{
_fillTblMultiFields(data, 12, RULE_TYPE0_OFFSET, RULE_TYPE0_WIDTH, 1);
}
for(n=0; n<6; n++)
{
_fillTblMultiFields(data, 12, DMAC_OFFSET + DMAC_WIDTH*(5-n), DMAC_WIDTH, ptr_field->dmac[n]);
}
for(n=0; n<6; n++)
{
_fillTblMultiFields(data, 12, SMAC_OFFSET + SMAC_WIDTH*(5-n), SMAC_WIDTH, ptr_field->smac[n]);
}
_fillTblMultiFields(data, 12, STAG_OFFSET, STAG_WIDTH, ptr_field->stag);
_fillTblMultiFields(data, 12, CTAG_OFFSET, CTAG_WIDTH, ptr_field->ctag);
_fillTblMultiFields(data, 12, ETYPE_OFFSET, ETYPE_WIDTH, ptr_field->etype);
_fillTblMultiFields(data, 12, DIP_OFFSET, DIP_WIDTH, ptr_field->dip[0]);
_fillTblMultiFields(data, 12, SIP_OFFSET, SIP_WIDTH, ptr_field->sip[0]);
_fillTblMultiFields(data, 12, DSCP_OFFSET, DSCP_WIDTH, ptr_field->dscp);
_fillTblMultiFields(data, 12, PROTOCOL_OFFSET, PROTOCOL_WIDTH, ptr_field->protocol);
_fillTblMultiFields(data, 12, DPORT_OFFSET, DPORT_WIDTH, ptr_field->dport);
_fillTblMultiFields(data, 12, SPORT_OFFSET, SPORT_WIDTH, ptr_field->sport);
_fillTblMultiFields(data, 12, UDF_OFFSET, UDF_WIDTH, ptr_field->udf);
_fillTblMultiFields(data, 12, FIELDMAP_OFFSET, FIELDMAP_WIDTH, ptr_field->fieldmap);
_fillTblMultiFields(data, 12, IS_IPV6_OFFSET, IS_IPV6_WIDTH, ptr_field->isipv6);
_fillTblMultiFields(data, 12, PORTMAP_OFFSET, PORTMAP_WIDTH, ptr_field->portmap);
break;
case AIR_ACL_RULE_TYPE_1:
_fillTblMultiFields(data, 12, RULE_TYPE1_OFFSET, RULE_TYPE1_WIDTH, 1);
for(n=1; n<4; n++)
{
_fillTblMultiFields(data, 12, DIP_IPV6_OFFSET + DIP_IPV6_WIDTH*(n-1), DIP_IPV6_WIDTH, ptr_field->dip[n]);
}
for(n=1; n<4; n++)
{
_fillTblMultiFields(data, 12, SIP_IPV6_OFFSET + SIP_IPV6_WIDTH*(n-1), SIP_IPV6_WIDTH, ptr_field->sip[n]);
}
_fillTblMultiFields(data, 12, FLOW_LABEL_OFFSET, FLOW_LABEL_WIDTH, ptr_field->flow_label);
break;
default:
return;
}
}
static void
_air_acl_getRuleTable(
const AIR_ACL_RULE_TYPE_T type,
UI32_T *data,
AIR_ACL_FIELD_T *ptr_field)
{
UI32_T n = 0;
switch(type)
{
case AIR_ACL_RULE_TYPE_0:
for(n=0; n<6; n++)
{
ACL_DERIVE_TBL_MULTIFIELDS(data, DMAC_OFFSET + DMAC_WIDTH*(5-n), DMAC_WIDTH, ptr_field->dmac[n]);
}
for(n=0; n<6; n++)
{
ACL_DERIVE_TBL_MULTIFIELDS(data, SMAC_OFFSET + SMAC_WIDTH*(5-n), SMAC_WIDTH, ptr_field->smac[n]);
}
ACL_DERIVE_TBL_MULTIFIELDS(data, STAG_OFFSET, STAG_WIDTH, ptr_field->stag);
ACL_DERIVE_TBL_MULTIFIELDS(data, CTAG_OFFSET, CTAG_WIDTH, ptr_field->ctag);
ACL_DERIVE_TBL_MULTIFIELDS(data, ETYPE_OFFSET, ETYPE_WIDTH, ptr_field->etype);
ACL_DERIVE_TBL_MULTIFIELDS(data, DIP_OFFSET, DIP_WIDTH, ptr_field->dip[0]);
ACL_DERIVE_TBL_MULTIFIELDS(data, SIP_OFFSET, SIP_WIDTH, ptr_field->sip[0]);
ACL_DERIVE_TBL_MULTIFIELDS(data, DSCP_OFFSET, DSCP_WIDTH, ptr_field->dscp);
ACL_DERIVE_TBL_MULTIFIELDS(data, PROTOCOL_OFFSET, PROTOCOL_WIDTH, ptr_field->protocol);
ACL_DERIVE_TBL_MULTIFIELDS(data, DPORT_OFFSET, DPORT_WIDTH, ptr_field->dport);
ACL_DERIVE_TBL_MULTIFIELDS(data, SPORT_OFFSET, SPORT_WIDTH, ptr_field->sport);
ACL_DERIVE_TBL_MULTIFIELDS(data, UDF_OFFSET, UDF_WIDTH, ptr_field->udf);
ACL_DERIVE_TBL_MULTIFIELDS(data, FIELDMAP_OFFSET, FIELDMAP_WIDTH, ptr_field->fieldmap);
ACL_DERIVE_TBL_MULTIFIELDS(data, IS_IPV6_OFFSET, IS_IPV6_WIDTH, ptr_field->isipv6);
ACL_DERIVE_TBL_MULTIFIELDS(data, PORTMAP_OFFSET, PORTMAP_WIDTH, ptr_field->portmap);
break;
case AIR_ACL_RULE_TYPE_1:
for(n=1; n<4; n++)
{
ACL_DERIVE_TBL_MULTIFIELDS(data, DIP_IPV6_OFFSET + DIP_IPV6_WIDTH*(n-1), DIP_IPV6_WIDTH, ptr_field->dip[n]);
}
for(n=1; n<4; n++)
{
ACL_DERIVE_TBL_MULTIFIELDS(data, SIP_IPV6_OFFSET + SIP_IPV6_WIDTH*(n-1), SIP_IPV6_WIDTH, ptr_field->sip[n]);
}
ACL_DERIVE_TBL_MULTIFIELDS(data, FLOW_LABEL_OFFSET, FLOW_LABEL_WIDTH, ptr_field->flow_label);
break;
default:
return;
}
}
static void
_air_acl_setActionTable(
const AIR_ACL_ACTION_T *ptr_action,
UI32_T *data)
{
int i = 0;
_fillTblMultiFields(data, 4, PORT_FORCE_OFFSET, PORT_FORCE_WIDTH, ptr_action->port_en);
_fillTblMultiFields(data, 4, VLAN_PORT_SWAP_OFFSET, VLAN_PORT_SWAP_WIDTH, ptr_action->vlan_port_sel);
_fillTblMultiFields(data, 4, DST_PORT_SWAP_OFFSET, DST_PORT_SWAP_WIDTH, ptr_action->dest_port_sel);
_fillTblMultiFields(data, 4, PORT_OFFSET, PORT_WIDTH, ptr_action->portmap);
_fillTblMultiFields(data, 4, ACL_MIB_EN_OFFSET, ACL_MIB_EN_WIDTH, ptr_action->cnt_en);
_fillTblMultiFields(data, 4, ACL_MIB_ID_OFFSET, ACL_MIB_ID_WIDTH, ptr_action->cnt_idx);
_fillTblMultiFields(data, 4, ATTACK_RATE_EN_OFFSET, ATTACK_RATE_EN_WIDTH, ptr_action->attack_en);
_fillTblMultiFields(data, 4, ATTACK_RATE_ID_OFFSET, ATTACK_RATE_ID_WIDTH, ptr_action->attack_idx);
_fillTblMultiFields(data, 4, RATE_EN_OFFSET, RATE_EN_WIDTH, ptr_action->rate_en);
_fillTblMultiFields(data, 4, RATE_INDEX_OFFSET, RATE_INDEX_WIDTH, ptr_action->rate_idx);
_fillTblMultiFields(data, 4, PORT_FW_EN_OFFSET, PORT_FW_EN_WIDTH, ptr_action->fwd_en);
_fillTblMultiFields(data, 4, FW_PORT_OFFSET, FW_PORT_WIDTH, ptr_action->fwd);
_fillTblMultiFields(data, 4, MIRROR_OFFSET, MIRROR_WIDTH, ptr_action->mirrormap);
_fillTblMultiFields(data, 4, PRI_USER_EN_OFFSET, PRI_USER_EN_WIDTH, ptr_action->pri_user_en);
_fillTblMultiFields(data, 4, PRI_USER_OFFSET, PRI_USER_WIDTH, ptr_action->pri_user);
_fillTblMultiFields(data, 4, EG_TAG_EN_OFFSET, EG_TAG_EN_WIDTH, ptr_action->egtag_en);
_fillTblMultiFields(data, 4, EG_TAG_OFFSET, EG_TAG_WIDTH, ptr_action->egtag);
_fillTblMultiFields(data, 4, LKY_VLAN_EN_OFFSET, LKY_VLAN_EN_WIDTH, ptr_action->lyvlan_en);
_fillTblMultiFields(data, 4, LKY_VLAN_OFFSET, LKY_VLAN_WIDTH, ptr_action->lyvlan);
_fillTblMultiFields(data, 4, BPDU_OFFSET, BPDU_WIDTH, ptr_action->bpdu);
_fillTblMultiFields(data, 4, ACL_MANG_OFFSET, ACL_MANG_WIDTH, ptr_action->mang);
_fillTblMultiFields(data, 4, TRTCM_EN_OFFSET, TRTCM_EN_WIDTH, ptr_action->trtcm_en);
_fillTblMultiFields(data, 4, DROP_PCD_SEL_OFFSET, DROP_PCD_SEL_WIDTH, ptr_action->trtcm.drop_pcd_sel);
_fillTblMultiFields(data, 4, ACL_DROP_PCD_R_OFFSET, ACL_DROP_PCD_R_WIDTH, ptr_action->trtcm.drop_pcd_r);
_fillTblMultiFields(data, 4, ACL_DROP_PCD_Y_OFFSET, ACL_DROP_PCD_Y_WIDTH, ptr_action->trtcm.drop_pcd_y);
_fillTblMultiFields(data, 4, ACL_DROP_PCD_G_OFFSET, ACL_DROP_PCD_G_WIDTH, ptr_action->trtcm.drop_pcd_g);
_fillTblMultiFields(data, 4, CLASS_SLR_SEL_OFFSET, CLASS_SLR_SEL_WIDTH, ptr_action->trtcm.cls_slr_sel);
_fillTblMultiFields(data, 4, CLASS_SLR_OFFSET, CLASS_SLR_WIDTH, ptr_action->trtcm.cls_slr);
_fillTblMultiFields(data, 4, ACL_TCM_SEL_OFFSET, ACL_TCM_SEL_WIDTH, ptr_action->trtcm.tcm_sel);
_fillTblMultiFields(data, 4, ACL_TCM_OFFSET, ACL_TCM_WIDTH, ptr_action->trtcm.usr_tcm);
_fillTblMultiFields(data, 4, ACL_CLASS_IDX_OFFSET, ACL_CLASS_IDX_WIDTH, ptr_action->trtcm.tcm_idx);
_fillTblMultiFields(data, 4, ACL_VLAN_HIT_OFFSET, ACL_VLAN_HIT_WIDTH, ptr_action->vlan_en);
_fillTblMultiFields(data, 4, ACL_VLAN_VID_OFFSET, ACL_VLAN_VID_WIDTH, ptr_action->vlan_idx);
}
static void
_air_acl_getActionTable(
UI32_T *data,
AIR_ACL_ACTION_T *ptr_action)
{
ACL_DERIVE_TBL_MULTIFIELDS(data, PORT_FORCE_OFFSET, PORT_FORCE_WIDTH, ptr_action->port_en);
ACL_DERIVE_TBL_MULTIFIELDS(data, VLAN_PORT_SWAP_OFFSET, VLAN_PORT_SWAP_WIDTH, ptr_action->vlan_port_sel);
ACL_DERIVE_TBL_MULTIFIELDS(data, DST_PORT_SWAP_OFFSET, DST_PORT_SWAP_WIDTH, ptr_action->dest_port_sel);
ACL_DERIVE_TBL_MULTIFIELDS(data, PORT_OFFSET, PORT_WIDTH, ptr_action->portmap);
ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_MIB_EN_OFFSET, ACL_MIB_EN_WIDTH, ptr_action->cnt_en);
ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_MIB_ID_OFFSET, ACL_MIB_ID_WIDTH, ptr_action->cnt_idx);
ACL_DERIVE_TBL_MULTIFIELDS(data, ATTACK_RATE_EN_OFFSET, ATTACK_RATE_EN_WIDTH, ptr_action->attack_en);
ACL_DERIVE_TBL_MULTIFIELDS(data, ATTACK_RATE_ID_OFFSET, ATTACK_RATE_ID_WIDTH, ptr_action->attack_idx);
ACL_DERIVE_TBL_MULTIFIELDS(data, RATE_EN_OFFSET, RATE_EN_WIDTH, ptr_action->rate_en);
ACL_DERIVE_TBL_MULTIFIELDS(data, RATE_INDEX_OFFSET, RATE_INDEX_WIDTH, ptr_action->rate_idx);
ACL_DERIVE_TBL_MULTIFIELDS(data, PORT_FW_EN_OFFSET, PORT_FW_EN_WIDTH, ptr_action->fwd_en);
ACL_DERIVE_TBL_MULTIFIELDS(data, FW_PORT_OFFSET, FW_PORT_WIDTH, ptr_action->fwd);
ACL_DERIVE_TBL_MULTIFIELDS(data, MIRROR_OFFSET, MIRROR_WIDTH, ptr_action->mirrormap);
ACL_DERIVE_TBL_MULTIFIELDS(data, PRI_USER_EN_OFFSET, PRI_USER_EN_WIDTH, ptr_action->pri_user_en);
ACL_DERIVE_TBL_MULTIFIELDS(data, PRI_USER_OFFSET, PRI_USER_WIDTH, ptr_action->pri_user);
ACL_DERIVE_TBL_MULTIFIELDS(data, EG_TAG_EN_OFFSET, EG_TAG_EN_WIDTH, ptr_action->egtag_en);
ACL_DERIVE_TBL_MULTIFIELDS(data, EG_TAG_OFFSET, EG_TAG_WIDTH, ptr_action->egtag);
ACL_DERIVE_TBL_MULTIFIELDS(data, LKY_VLAN_EN_OFFSET, LKY_VLAN_EN_WIDTH, ptr_action->lyvlan_en);
ACL_DERIVE_TBL_MULTIFIELDS(data, LKY_VLAN_OFFSET, LKY_VLAN_WIDTH, ptr_action->lyvlan);
ACL_DERIVE_TBL_MULTIFIELDS(data, BPDU_OFFSET, BPDU_WIDTH, ptr_action->bpdu);
ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_MANG_OFFSET, ACL_MANG_WIDTH, ptr_action->mang);
ACL_DERIVE_TBL_MULTIFIELDS(data, TRTCM_EN_OFFSET, TRTCM_EN_WIDTH, ptr_action->trtcm_en);
ACL_DERIVE_TBL_MULTIFIELDS(data, DROP_PCD_SEL_OFFSET, DROP_PCD_SEL_WIDTH, ptr_action->trtcm.drop_pcd_sel);
ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_DROP_PCD_R_OFFSET, ACL_DROP_PCD_R_WIDTH, ptr_action->trtcm.drop_pcd_r);
ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_DROP_PCD_Y_OFFSET, ACL_DROP_PCD_Y_WIDTH, ptr_action->trtcm.drop_pcd_y);
ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_DROP_PCD_G_OFFSET, ACL_DROP_PCD_G_WIDTH, ptr_action->trtcm.drop_pcd_g);
ACL_DERIVE_TBL_MULTIFIELDS(data, CLASS_SLR_SEL_OFFSET, CLASS_SLR_SEL_WIDTH, ptr_action->trtcm.cls_slr_sel);
ACL_DERIVE_TBL_MULTIFIELDS(data, CLASS_SLR_OFFSET, CLASS_SLR_WIDTH, ptr_action->trtcm.cls_slr);
ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_TCM_SEL_OFFSET, ACL_TCM_SEL_WIDTH, ptr_action->trtcm.tcm_sel);
ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_TCM_OFFSET, ACL_TCM_WIDTH, ptr_action->trtcm.usr_tcm);
ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_CLASS_IDX_OFFSET, ACL_CLASS_IDX_WIDTH, ptr_action->trtcm.tcm_idx);
ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_VLAN_HIT_OFFSET, ACL_VLAN_HIT_WIDTH, ptr_action->vlan_en);
ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_VLAN_VID_OFFSET, ACL_VLAN_VID_WIDTH, ptr_action->vlan_idx);
}
static AIR_ERROR_NO_T
_air_acl_writeReg(
const UI32_T unit,
const UI32_T rule_idx,
const UI32_T block_num,
const AIR_ACL_RULE_TCAM_T type,
const AIR_ACL_MEM_SEL_T sel,
const AIR_ACL_MEM_FUNC_T func,
const UI32_T *data)
{
UI32_T bn = 0, value = 0;
AIR_ERROR_NO_T ret = AIR_E_OK;
for (bn = 0; bn < block_num; bn++)
{
if(AIR_E_TIMEOUT == _checkDone(unit, AIR_ACL_CHECK_ACL))
{
return AIR_E_TIMEOUT;
}
aml_writeReg(unit, ACL_MEM_CFG_WDATA0, data[bn*4]);
aml_writeReg(unit, ACL_MEM_CFG_WDATA1, data[bn*4+1]);
aml_writeReg(unit, ACL_MEM_CFG_WDATA2, data[bn*4+2]);
aml_writeReg(unit, ACL_MEM_CFG_WDATA3, data[bn*4+3]);
value = (rule_idx << ACL_MEM_CFG_RULE_ID_OFFSET) | (type << ACL_MEM_CFG_TCAM_CELL_OFFSET) |
(bn << ACL_MEM_CFG_DATA_BN_OFFSET) | (sel << ACL_MEM_CFG_MEM_SEL_OFFSET) |
(func << ACL_MEM_CFG_FUNC_SEL_OFFSET) | ACL_MEM_CFG_EN;
if ((ret = aml_writeReg(unit, ACL_MEM_CFG, value)) != AIR_E_OK)
{
return ret;
}
}
return AIR_E_OK;
}
static AIR_ERROR_NO_T
_air_acl_readReg(
const UI32_T unit,
const UI32_T rule_idx,
const UI32_T block_num,
const AIR_ACL_RULE_TCAM_T type,
const AIR_ACL_MEM_SEL_T sel,
const AIR_ACL_MEM_FUNC_T func,
UI32_T *data)
{
UI32_T bn = 0, value = 0;
AIR_ERROR_NO_T ret = AIR_E_OK;
for (bn = 0; bn < block_num; bn++)
{
value = (rule_idx << ACL_MEM_CFG_RULE_ID_OFFSET) | (type << ACL_MEM_CFG_TCAM_CELL_OFFSET) |
(bn << ACL_MEM_CFG_DATA_BN_OFFSET) | (sel << ACL_MEM_CFG_MEM_SEL_OFFSET) |
(func << ACL_MEM_CFG_FUNC_SEL_OFFSET) | ACL_MEM_CFG_EN;
if ((ret = aml_writeReg(unit, ACL_MEM_CFG, value)) != AIR_E_OK)
{
return ret;
}
if(AIR_E_TIMEOUT == _checkDone(unit, AIR_ACL_CHECK_ACL))
{
return AIR_E_TIMEOUT;
}
aml_readReg(unit, ACL_MEM_CFG_RDATA0, data+bn*4);
aml_readReg(unit, ACL_MEM_CFG_RDATA1, data+bn*4+1);
aml_readReg(unit, ACL_MEM_CFG_RDATA2, data+bn*4+2);
aml_readReg(unit, ACL_MEM_CFG_RDATA3, data+bn*4+3);
}
return AIR_E_OK;
}
/* FUNCTION NAME: air_acl_setRuleCtrl
* PURPOSE:
* Set ACL rule control.
*
* INPUT:
* unit -- Device ID
* rule_idx -- Index of ACL rule entry
* ptr_rule -- Structure of ACL rule control
*
* OUTPUT:
* None
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* AIR_E_TIMEOUT
*
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_setRuleCtrl(
const UI32_T unit,
const UI32_T rule_idx,
AIR_ACL_CTRL_T *ptr_ctrl)
{
UI32_T data_en[4] = {0}, data_end[4] = {0}, data_rev[4] = {0};
if(TRUE == ptr_ctrl->rule_en)
{
_air_acl_readReg(unit, AIR_ACL_RULE_CONFIG_ENABLE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_READ, data_en);
data_en[rule_idx/32] |= (1 << (rule_idx%32));
_air_acl_writeReg(unit, AIR_ACL_RULE_CONFIG_ENABLE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_WRITE, data_en);
}
else
{
_air_acl_readReg(unit, AIR_ACL_RULE_CONFIG_ENABLE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_READ, data_en);
data_en[rule_idx/32] &= ~(1 << (rule_idx%32));
_air_acl_writeReg(unit, AIR_ACL_RULE_CONFIG_ENABLE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_WRITE, data_en);
}
if(TRUE == ptr_ctrl->end)
{
_air_acl_readReg(unit, AIR_ACL_RULE_CONFIG_END, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_READ, data_end);
data_end[rule_idx/32] |= (1 << (rule_idx%32));
_air_acl_writeReg(unit, AIR_ACL_RULE_CONFIG_END, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_WRITE, data_end);
}
else
{
_air_acl_readReg(unit, AIR_ACL_RULE_CONFIG_END, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_READ, data_end);
data_end[rule_idx/32] &= ~(1 << (rule_idx%32));
_air_acl_writeReg(unit, AIR_ACL_RULE_CONFIG_END, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_WRITE, data_end);
}
if(TRUE == ptr_ctrl->reverse)
{
_air_acl_readReg(unit, AIR_ACL_RULE_CONFIG_REVERSE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_READ, data_rev);
data_rev[rule_idx/32] |= (1 << (rule_idx%32));
_air_acl_writeReg(unit, AIR_ACL_RULE_CONFIG_REVERSE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_WRITE, data_rev);
}
else
{
_air_acl_readReg(unit, AIR_ACL_RULE_CONFIG_REVERSE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_READ, data_rev);
data_rev[rule_idx/32] &= ~(1 << (rule_idx%32));
_air_acl_writeReg(unit, AIR_ACL_RULE_CONFIG_REVERSE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_WRITE, data_rev);
}
return AIR_E_OK;
}
/* FUNCTION NAME: air_acl_getRuleCtrl
* PURPOSE:
* Get ACL rule control.
*
* INPUT:
* unit -- Device ID
* rule_idx -- Index of ACL rule entry
*
* OUTPUT:
* ptr_ctrl -- Structure of ACL rule control
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* AIR_E_TIMEOUT
*
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_getRuleCtrl(
const UI32_T unit,
const UI32_T rule_idx,
AIR_ACL_CTRL_T *ptr_ctrl)
{
UI32_T data_en[4] = {0}, data_end[4] = {0}, data_rev[4] = {0};
_air_acl_readReg(unit, AIR_ACL_RULE_CONFIG_ENABLE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_READ, data_en);
if(data_en[rule_idx/32] & (1 << (rule_idx%32)))
{
ptr_ctrl->rule_en = TRUE;
}
else
{
ptr_ctrl->rule_en = FALSE;
}
_air_acl_readReg(unit, AIR_ACL_RULE_CONFIG_END, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_READ, data_end);
if(data_end[rule_idx/32] & (1 << (rule_idx%32)))
{
ptr_ctrl->end = TRUE;
}
else
{
ptr_ctrl->end = FALSE;
}
_air_acl_readReg(unit, AIR_ACL_RULE_CONFIG_REVERSE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_READ, data_rev);
if(data_rev[rule_idx/32] & (1 << (rule_idx%32)))
{
ptr_ctrl->reverse = TRUE;
}
else
{
ptr_ctrl->reverse = FALSE;
}
return AIR_E_OK;
}
/* FUNCTION NAME: air_acl_setRule
* PURPOSE:
* Set ACL rule entry.
*
* INPUT:
* unit -- Device ID
* rule_idx -- Index of ACL rule entry
* rule -- Structure of ACL rule entry
*
* OUTPUT:
* None
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* AIR_E_TIMEOUT
*
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_setRule(
const UI32_T unit,
const UI32_T rule_idx,
AIR_ACL_RULE_T *rule)
{
UI32_T type0_key[12] = {0}, type0_mask[12] = {0};
UI32_T type1_key[12] = {0}, type1_mask[12] = {0};
UI32_T type0_t[12] = {0}, type0_c[12] = {0};
UI32_T type1_t[12] = {0}, type1_c[12] = {0};
AIR_ACL_CTRL_T ctrl;
/* Check parameter */
AIR_PARAM_CHK((rule_idx >= ACL_MAX_RULE_NUM), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((rule->key.flow_label > BITS_RANGE(0, FLOW_LABEL_WIDTH)), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((rule->key.fieldmap > BITS_RANGE(0, AIR_ACL_FIELD_TYPE_LAST)), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != rule->key.isipv6) && (FALSE != rule->key.isipv6), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((rule->key.portmap & (~AIR_ALL_PORT_BITMAP)), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != rule->ctrl.rule_en) && (FALSE != rule->ctrl.rule_en), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != rule->ctrl.reverse) && (FALSE != rule->ctrl.reverse), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != rule->ctrl.end) && (FALSE != rule->ctrl.end), AIR_E_BAD_PARAMETER);
memset(type0_key, 0, sizeof(type0_key));
memset(type0_mask, 0, sizeof(type0_mask));
memset(type1_key, 0, sizeof(type1_key));
memset(type1_mask, 0, sizeof(type1_mask));
memset(type0_t, 0, sizeof(type0_t));
memset(type0_c, 0, sizeof(type0_c));
memset(type1_t, 0, sizeof(type1_t));
memset(type1_c, 0, sizeof(type1_c));
/* Fill rule type table */
_air_acl_setRuleTable(AIR_ACL_RULE_TYPE_0, TRUE, &rule->key, type0_key);
_air_acl_setRuleTable(AIR_ACL_RULE_TYPE_0, FALSE, &rule->mask, type0_mask);
/* Calculate T/C cell */
_convertToTCcell(type0_key, type0_mask, type0_t, type0_c, 12);
/* Set T/C cell to reg */
_air_acl_writeReg(unit, rule_idx, 3, AIR_ACL_RULE_T_CELL, AIR_ACL_MEM_SEL_RULE, AIR_ACL_MEM_FUNC_WRITE, type0_t);
_air_acl_writeReg(unit, rule_idx, 3, AIR_ACL_RULE_C_CELL, AIR_ACL_MEM_SEL_RULE, AIR_ACL_MEM_FUNC_WRITE, type0_c);
/* If match ipv6 flow lable or dip/dip, set rule type 1 */
if ((1 == rule->key.isipv6) && (rule->key.fieldmap & ((1 << AIR_ACL_DIP) | (1 << AIR_ACL_SIP) | (1 << AIR_ACL_FLOW_LABEL))))
{
_air_acl_setRuleTable(AIR_ACL_RULE_TYPE_1, TRUE, &rule->key, type1_key);
_air_acl_setRuleTable(AIR_ACL_RULE_TYPE_1, FALSE, &rule->mask, type1_mask);
_convertToTCcell(type1_key, type1_mask, type1_t, type1_c, 12);
_air_acl_writeReg(unit, rule_idx+1, 3, AIR_ACL_RULE_T_CELL, AIR_ACL_MEM_SEL_RULE, AIR_ACL_MEM_FUNC_WRITE, type1_t);
_air_acl_writeReg(unit, rule_idx+1, 3, AIR_ACL_RULE_C_CELL, AIR_ACL_MEM_SEL_RULE, AIR_ACL_MEM_FUNC_WRITE, type1_c);
}
/* Config rule enable/end/rev */
memcpy(&ctrl, &rule->ctrl, sizeof(AIR_ACL_CTRL_T));
if ((1 == rule->key.isipv6) && (rule->key.fieldmap & ((1 << AIR_ACL_DIP) | (1 << AIR_ACL_SIP) | (1 << AIR_ACL_FLOW_LABEL))))
{
ctrl.end = 0;
air_acl_setRuleCtrl(unit, rule_idx, &ctrl);
air_acl_setRuleCtrl(unit, rule_idx+1, &rule->ctrl);
}
else
{
air_acl_setRuleCtrl(unit, rule_idx, &rule->ctrl);
}
return AIR_E_OK;
}
/* FUNCTION NAME: air_acl_delRule
* PURPOSE:
* Delete an ACL rule entry.
*
* INPUT:
* unit -- Device ID
* rule_idx -- Index of ACL rule entry
*
* OUTPUT:
* None
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* AIR_E_TIMEOUT
*
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_delRule(
const UI32_T unit,
const UI32_T rule_idx)
{
UI32_T type0_t[12]={0}, type0_c[12]={0}, type1_t[12]={0}, type1_c[12]={0};
AIR_ACL_CTRL_T ctrl={0};
/* Mistake proofing */
AIR_PARAM_CHK((rule_idx >= ACL_MAX_RULE_NUM), AIR_E_BAD_PARAMETER);
/* Delete the entry from ACL rule table */
_air_acl_writeReg(unit, rule_idx, 3, AIR_ACL_RULE_T_CELL, AIR_ACL_MEM_SEL_RULE, AIR_ACL_MEM_FUNC_WRITE, type0_t);
_air_acl_writeReg(unit, rule_idx, 3, AIR_ACL_RULE_C_CELL, AIR_ACL_MEM_SEL_RULE, AIR_ACL_MEM_FUNC_WRITE, type0_c);
air_acl_setRuleCtrl(unit, rule_idx, &ctrl);
return AIR_E_OK;
}
/* FUNCTION NAME: air_acl_clearRule
* PURPOSE:
* Clear all ACL rule entries.
*
* INPUT:
* unit -- Device ID
*
* OUTPUT:
* None
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* AIR_E_TIMEOUT
*
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_clearRule(
const UI32_T unit)
{
AIR_ERROR_NO_T ret = AIR_E_OK;
UI32_T value = 0;
UI32_T data[4]={0};
value = (AIR_ACL_MEM_FUNC_CLEAR << ACL_MEM_CFG_FUNC_SEL_OFFSET) | ACL_MEM_CFG_EN;
if ((ret = aml_writeReg(unit, ACL_MEM_CFG, value)) != AIR_E_OK)
{
return ret;
}
_air_acl_writeReg(unit, AIR_ACL_RULE_CONFIG_ENABLE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_WRITE, data);
_air_acl_writeReg(unit, AIR_ACL_RULE_CONFIG_END, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_WRITE, data);
_air_acl_writeReg(unit, AIR_ACL_RULE_CONFIG_REVERSE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_WRITE, data);
return AIR_E_OK;
}
/* FUNCTION NAME: air_acl_clearAction
* PURPOSE:
* Clear all ACL action entries.
*
* INPUT:
* unit -- Device ID
*
* OUTPUT:
* None
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* AIR_E_TIMEOUT
*
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_clearAction(
const UI32_T unit)
{
AIR_ERROR_NO_T ret = AIR_E_OK;
UI32_T value = 0;
UI32_T data[4]={0};
value = (AIR_ACL_MEM_SEL_ACTION << ACL_MEM_CFG_MEM_SEL_OFFSET) | (AIR_ACL_MEM_FUNC_CLEAR << ACL_MEM_CFG_FUNC_SEL_OFFSET) | ACL_MEM_CFG_EN;
if ((ret = aml_writeReg(unit, ACL_MEM_CFG, value)) != AIR_E_OK)
{
return ret;
}
return AIR_E_OK;
}
/* FUNCTION NAME: air_acl_getRule
* PURPOSE:
* Get ACL rule entry.
*
* INPUT:
* unit -- Device ID
* rule_idx -- Index of ACL rule entry
*
* OUTPUT:
* ptr_rule -- Structure of ACL rule entry
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* AIR_E_TIMEOUT
*
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_getRule(
const UI32_T unit,
const UI32_T rule_idx,
AIR_ACL_RULE_T *ptr_rule)
{
AIR_ERROR_NO_T ret = AIR_E_OK;
UI32_T bn = 0;
UI32_T value = 0, n = 0, idx = 0;
UI32_T type0_key[12] = {0}, type0_mask[12] = {0};
UI32_T type1_key[12] = {0}, type1_mask[12] = {0};
UI32_T type0_t[12] = {0}, type0_c[12] = {0};
UI32_T type1_t[12] = {0}, type1_c[12] = {0};
/* Mistake proofing */
AIR_PARAM_CHK((rule_idx >= ACL_MAX_RULE_NUM), AIR_E_BAD_PARAMETER);
AIR_CHECK_PTR(ptr_rule);
_air_acl_readReg(unit, rule_idx, 3, AIR_ACL_RULE_T_CELL, AIR_ACL_MEM_SEL_RULE, AIR_ACL_MEM_FUNC_READ, type0_t);
_air_acl_readReg(unit, rule_idx, 3, AIR_ACL_RULE_C_CELL, AIR_ACL_MEM_SEL_RULE, AIR_ACL_MEM_FUNC_READ, type0_c);
/* rule type 1 */
if(1 == (type0_t[0] & 0x1))
{
idx = rule_idx-1;
AIR_PRINT("This is the part of ipv6 rule, please get rule(%d)\n", idx);
return AIR_E_OK;
}
_parseFromTCcell(type0_t, type0_c, type0_key, type0_mask, 12);
_air_acl_getRuleTable(AIR_ACL_RULE_TYPE_0, type0_key, &ptr_rule->key);
_air_acl_getRuleTable(AIR_ACL_RULE_TYPE_0, type0_mask, &ptr_rule->mask);
if ((TRUE == ptr_rule->key.isipv6) && (ptr_rule->mask.fieldmap & ((1 << AIR_ACL_DIP) | (1 << AIR_ACL_SIP) | (1 << AIR_ACL_FLOW_LABEL))))
{
_air_acl_readReg(unit, rule_idx+1, 3, AIR_ACL_RULE_T_CELL, AIR_ACL_MEM_SEL_RULE, AIR_ACL_MEM_FUNC_READ, type1_t);
_air_acl_readReg(unit, rule_idx+1, 3, AIR_ACL_RULE_C_CELL, AIR_ACL_MEM_SEL_RULE, AIR_ACL_MEM_FUNC_READ, type1_c);
_parseFromTCcell(type1_t, type1_c, type1_key, type1_mask, 12);
_air_acl_getRuleTable(AIR_ACL_RULE_TYPE_1, type1_key, &ptr_rule->key);
_air_acl_getRuleTable(AIR_ACL_RULE_TYPE_1, type1_mask, &ptr_rule->mask);
}
if ((TRUE == ptr_rule->key.isipv6) && (ptr_rule->mask.fieldmap & ((1 << AIR_ACL_DIP) | (1 << AIR_ACL_SIP) | (1 << AIR_ACL_FLOW_LABEL))))
{
air_acl_getRuleCtrl(unit, rule_idx+1, &ptr_rule->ctrl);
}
else
{
air_acl_getRuleCtrl(unit, rule_idx, &ptr_rule->ctrl);
}
return AIR_E_OK;
}
/* FUNCTION NAME: air_acl_setAction
* PURPOSE:
* Set an ACL action entry.
*
* INPUT:
* unit -- Device ID
* act_idx -- Index of ACL action entry
* act -- Structure of ACL action entry
*
* OUTPUT:
* None
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* AIR_E_NOT_SUPPORT
* AIR_E_TIMEOUT
*
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_setAction(
const UI32_T unit,
const UI32_T act_idx,
const AIR_ACL_ACTION_T act)
{
AIR_ERROR_NO_T ret = AIR_E_OK;
UI32_T data[4] = {0};
/* Check parameter */
AIR_PARAM_CHK((act_idx >= ACL_MAX_ACTION_NUM), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != act.port_en) && (FALSE != act.port_en), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != act.dest_port_sel) && (FALSE != act.dest_port_sel), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != act.vlan_port_sel) && (FALSE != act.vlan_port_sel), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((act.portmap & (~AIR_ALL_PORT_BITMAP)), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != act.cnt_en) && (FALSE != act.cnt_en), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((act.cnt_idx >= ACL_MAX_MIB_NUM), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != act.attack_en) && (FALSE != act.attack_en), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((act.attack_idx >= ACL_MAX_ATTACK_RATE_NUM), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != act.rate_en) && (FALSE != act.rate_en), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((act.rate_idx >= ACL_MAX_METER_NUM), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != act.vlan_en) && (FALSE != act.vlan_en), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((act.vlan_idx >= ACL_MAX_VLAN_NUM), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((act.mirrormap > BITS_RANGE(0, ACL_MAX_MIR_SESSION_NUM)), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != act.pri_user_en) && (FALSE != act.pri_user_en), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((act.pri_user >= AIR_MAX_NUM_OF_QUEUE), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != act.lyvlan_en) && (FALSE != act.lyvlan_en), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != act.lyvlan) && (FALSE != act.lyvlan), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != act.mang) && (FALSE != act.mang), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != act.bpdu) && (FALSE != act.bpdu), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != act.fwd_en) && (FALSE != act.fwd_en), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((act.fwd >= AIR_ACL_ACT_FWD_LAST), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != act.egtag_en) && (FALSE != act.egtag_en), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((act.egtag >= AIR_ACL_ACT_EGTAG_LAST), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != act.trtcm_en) && (FALSE != act.trtcm_en), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != act.trtcm.cls_slr_sel) && (FALSE != act.trtcm.cls_slr), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((act.trtcm.cls_slr >= ACL_MAX_CLASS_SLR_NUM), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != act.trtcm.drop_pcd_sel) && (FALSE != act.trtcm.drop_pcd_sel), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((act.trtcm.drop_pcd_g >= ACL_MAX_DROP_PCD_NUM), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((act.trtcm.drop_pcd_y >= ACL_MAX_DROP_PCD_NUM), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((act.trtcm.drop_pcd_r >= ACL_MAX_DROP_PCD_NUM), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != act.trtcm.tcm_sel) && (FALSE != act.trtcm.tcm_sel), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((act.trtcm.usr_tcm >= AIR_ACL_ACT_USR_TCM_LAST), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((act.trtcm.tcm_idx >= ACL_MAX_TRTCM_NUM), AIR_E_BAD_PARAMETER);
_air_acl_setActionTable(&act, data);
_air_acl_writeReg(unit, act_idx, 1, 0, AIR_ACL_MEM_SEL_ACTION, AIR_ACL_MEM_FUNC_WRITE, data);
return ret;
}
/* FUNCTION NAME: air_acl_getAction
* PURPOSE:
* Get an ACL action entry with speficic index.
*
* INPUT:
* unit -- Device ID
* act_idx -- Index of ACL action entry
*
* OUTPUT:
* ptr_act -- Structure of ACL action entry
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* AIR_E_ENTRY_NOT_FOUND
* AIR_E_TIMEOUT
*
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_getAction(
const UI32_T unit,
const UI32_T act_idx,
AIR_ACL_ACTION_T *ptr_act)
{
AIR_ERROR_NO_T ret = AIR_E_OK;
UI32_T i = 0;
UI32_T data[4] = {0};
/* Mistake proofing */
AIR_PARAM_CHK((act_idx >= ACL_MAX_ACTION_NUM), AIR_E_BAD_PARAMETER);
AIR_CHECK_PTR(ptr_act);
_air_acl_readReg(unit, act_idx, 1, 0, AIR_ACL_MEM_SEL_ACTION, AIR_ACL_MEM_FUNC_READ, data);
_air_acl_getActionTable(data, ptr_act);
return AIR_E_OK;
}
/* FUNCTION NAME: air_acl_delAction
* PURPOSE:
* Delete an ACL action entry with specific index
*
* INPUT:
* unit -- Device ID
* act_idx -- Index of ACL action entry
*
* OUTPUT:
* None
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* AIR_E_ENTRY_NOT_FOUND
* AIR_E_TIMEOUT
*
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_delAction(
const UI32_T unit,
const UI32_T act_idx)
{
AIR_ERROR_NO_T ret = AIR_E_OK;
UI32_T value = 0;
UI32_T data[4] = {0};
/* Check parameter */
AIR_PARAM_CHK((act_idx >= ACL_MAX_ACTION_NUM), AIR_E_BAD_PARAMETER);
_air_acl_writeReg(unit, act_idx, 1, 0, AIR_ACL_MEM_SEL_ACTION, AIR_ACL_MEM_FUNC_WRITE, data);
return ret;
}
/* FUNCTION NAME: air_acl_setTrtcm
* PURPOSE:
* Set a trTCM entry with the specific index.
*
* INPUT:
* unit -- Device ID
* tcm_idx -- Index of trTCM entry
* tcm -- Structure of trTCM entry
*
* OUTPUT:
* None
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* AIR_E_TIMEOUT
*
* NOTES:
* Index 0 ~ 31 can be selected in tcm_idx.
*/
AIR_ERROR_NO_T
air_acl_setTrtcm(
const UI32_T unit,
const UI32_T tcm_idx,
const AIR_ACL_TRTCM_T tcm)
{
AIR_ERROR_NO_T ret = AIR_E_OK;
UI32_T value = 0;
/* Mistake proofing */
AIR_PARAM_CHK((tcm_idx >= ACL_MAX_TRTCM_NUM), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((tcm.cbs > ACL_MAX_CBS_NUM), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((tcm.cir > ACL_MAX_CIR_NUM), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((tcm.pbs > ACL_MAX_PBS_NUM), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((tcm.pir > ACL_MAX_PIR_NUM), AIR_E_BAD_PARAMETER);
if(AIR_E_TIMEOUT == _checkDone(unit, AIR_ACL_CHECK_TRTCM))
{
return AIR_E_TIMEOUT;
}
aml_writeReg(unit, ACL_TRTCMW_CBS, tcm.cbs & ACL_TRTCM_CBS_MASK);
aml_writeReg(unit, ACL_TRTCMW_EBS, tcm.pbs & ACL_TRTCM_EBS_MASK);
aml_writeReg(unit, ACL_TRTCMW_CIR, tcm.cir & ACL_TRTCM_CIR_MASK);
aml_writeReg(unit, ACL_TRTCMW_EIR, tcm.pir & ACL_TRTCM_EIR_MASK);
value = (1 << ACL_TRTCM_BUSY_OFFSET) | ACL_TRTCM_WRITE | ((tcm_idx & ACL_TRTCM_ID_MASK) << ACL_TRTCM_ID_OFFSET);
if ((ret = aml_writeReg(unit, ACL_TRTCMA, value)) != AIR_E_OK)
{
return ret;
}
return AIR_E_OK;
}
/* FUNCTION NAME: air_acl_delTrtcm
* PURPOSE:
* Delete an ACL trTCM entry.
*
* INPUT:
* unit -- Device ID
* trtcm_idx -- Index of ACL trTCM entry
*
* OUTPUT:
* None
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* AIR_E_TIMEOUT
*
* NOTES:
* Index 0 ~ 31 can be selected in tcm_idx.
*/
AIR_ERROR_NO_T
air_acl_delTrtcm(
const UI32_T unit,
const UI32_T tcm_idx)
{
AIR_ACL_TRTCM_T tcm;
/* Mistake proofing */
AIR_PARAM_CHK((tcm_idx >= ACL_MAX_TRTCM_NUM), AIR_E_BAD_PARAMETER);
/* Delete the entry from trTCM table */
memset(&tcm, 0, sizeof(tcm));
return air_acl_setTrtcm(unit, tcm_idx, tcm);
}
/* FUNCTION NAME: air_acl_clearTrtcm
* PURPOSE:
* Clear all ACL trTCM entries.
*
* INPUT:
* unit -- Device ID
*
* OUTPUT:
* None
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* AIR_E_TIMEOUT
*
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_clearTrtcm(
const UI32_T unit)
{
AIR_ERROR_NO_T ret = AIR_E_OK;
AIR_ACL_TRTCM_T tcm;
UI32_T i = 0;
/* Delete all entries from trTCM table */
memset(&tcm, 0, sizeof(tcm));
for(i=0; i < ACL_MAX_TRTCM_NUM; i++)
{
ret = air_acl_setTrtcm(unit, i, tcm);
if(AIR_E_OK != ret)
{
return ret;
}
}
return ret;
}
/* FUNCTION NAME: air_acl_getTrtcm
* PURPOSE:
* Get a trTCM entry with the specific index.
*
* INPUT:
* unit -- Device ID
* tcm_idx -- Index of trTCM entry
*
* OUTPUT:
* ptr_tcm -- Structure of trTCM entry
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* AIR_E_TIMEOUT
*
* NOTES:
* Index 0 ~ 31 can be selected in tcm_idx.
*/
AIR_ERROR_NO_T
air_acl_getTrtcm(
const UI32_T unit,
const UI32_T tcm_idx,
AIR_ACL_TRTCM_T *ptr_tcm)
{
AIR_ERROR_NO_T ret = AIR_E_OK;
UI32_T value = 0, trtcmr1 = 0, trtcmr2 = 0, trtcmr3 = 0, trtcmr4 = 0;
/* Mistake proofing */
AIR_PARAM_CHK((tcm_idx >= ACL_MAX_TRTCM_NUM), AIR_E_BAD_PARAMETER);
AIR_CHECK_PTR(ptr_tcm);
if(AIR_E_TIMEOUT == _checkDone(unit, AIR_ACL_CHECK_TRTCM))
{
return AIR_E_TIMEOUT;
}
value = (1 << ACL_TRTCM_BUSY_OFFSET) | ACL_TRTCM_READ | ((tcm_idx & ACL_TRTCM_ID_MASK) << ACL_TRTCM_ID_OFFSET);
if ((ret = aml_writeReg(unit, ACL_TRTCMA, value)) != AIR_E_OK)
{
return ret;
}
aml_readReg(unit, ACL_TRTCMR_CBS, &trtcmr1);
aml_readReg(unit, ACL_TRTCMR_EBS, &trtcmr2);
aml_readReg(unit, ACL_TRTCMR_CIR, &trtcmr3);
aml_readReg(unit, ACL_TRTCMR_EIR, &trtcmr4);
ptr_tcm->cbs = trtcmr1 & ACL_TRTCM_CBS_MASK;
ptr_tcm->pbs = trtcmr2 & ACL_TRTCM_EBS_MASK;
ptr_tcm->cir = trtcmr3 & ACL_TRTCM_CIR_MASK;
ptr_tcm->pir = trtcmr4 & ACL_TRTCM_EIR_MASK;
return AIR_E_OK;
}
/* FUNCTION NAME: air_acl_setTrtcmEnable
* PURPOSE:
* Set trTCM enable so the meter table will be updated based on PIR and CIR.
* The color marker will also be enabled when ACL is hit.
*
* INPUT:
* unit -- Device ID
* state -- FALSE:Disable
* TRUE: Enable
*
* OUTPUT:
* None
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
*
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_setTrtcmEnable(
const UI32_T unit,
const BOOL_T state)
{
UI32_T u32dat = 0;
/* Mistake proofing for port checking */
AIR_PARAM_CHK(((TRUE != state) && (FALSE != state)), AIR_E_BAD_PARAMETER);
/* Read data from register */
aml_readReg(unit, ACL_TRTCM, &u32dat);
if (TRUE == state)
{
u32dat |= (BIT(ACL_TRTCM_EN_OFFSET));
}
else
{
u32dat &= ~(BIT(ACL_TRTCM_EN_OFFSET));
}
/* Write data to register */
aml_writeReg(unit, ACL_TRTCM, u32dat);
return AIR_E_OK;
}
/* FUNCTION NAME: air_acl_getTrtcm
* PURPOSE:
* Get a trTCM enable state.
*
* INPUT:
* unit -- Device ID
*
* OUTPUT:
* ptr_state -- FALSE:Disable
* TRUE: Enable
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
*
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_getTrtcmEnable(
const UI32_T unit,
BOOL_T *const ptr_state)
{
UI32_T u32dat = 0;
/* Mistake proofing for port checking */
AIR_CHECK_PTR(ptr_state);
/* Read data from register */
aml_readReg(unit, ACL_TRTCM, &u32dat);
if (u32dat & BIT(ACL_TRTCM_EN_OFFSET))
{
(*ptr_state) = TRUE;
}
else
{
(*ptr_state) = FALSE;
}
return AIR_E_OK;
}
/* FUNCTION NAME: air_acl_setPortEnable
* PURPOSE:
* Set ACL state for a specific port.
*
* INPUT:
* unit -- Device ID
* port -- Index of port number
* state -- FALSE:Disable
* TRUE: Enable
* OUTPUT:
* None
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
*
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_setPortEnable(
const UI32_T unit,
const UI32_T port,
const BOOL_T state)
{
UI32_T u32dat = 0, value = 0;
/* Mistake proofing for port checking */
AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK(((TRUE != state) && (FALSE != state)), AIR_E_BAD_PARAMETER);
value = state ? 1 : 0;
aml_readReg(unit, ACL_PORT_EN, &u32dat);
u32dat = (u32dat & ~(ACL_EN_MASK << port)) | (value << port);
aml_writeReg(unit, ACL_PORT_EN, u32dat);
return AIR_E_OK;
}
/* FUNCTION NAME: air_acl_getPortEnable
* PURPOSE:
* Get ACL state for a specific port.
*
* INPUT:
* unit -- Device ID
* port -- Index of port number
*
* OUTPUT:
* ptr_state -- FALSE:Disable
* TRUE: Enable
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
*
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_getPortEnable(
const UI32_T unit,
const UI32_T port,
UI32_T *ptr_state)
{
UI32_T u32dat = 0;
/* Mistake proofing for port checking */
AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
/* Mistake proofing for state checking */
AIR_CHECK_PTR(ptr_state);
/* Read data from register */
aml_readReg(unit, ACL_PORT_EN, &u32dat);
(*ptr_state) = BITS_OFF_R(u32dat, port, ACL_EN_MASK);
return AIR_E_OK;
}
/* FUNCTION NAME: air_acl_setDropEnable
* PURPOSE:
* Set ACL drop precedence state
*
* INPUT:
* unit -- Device ID
* port -- Index of port number
* state -- FALSE:Disable
* TRUE: Enable
* OUTPUT:
* None
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
*
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_setDropEnable(
const UI32_T unit,
const UI32_T port,
const BOOL_T state)
{
UI32_T u32dat = 0;
/* Mistake proofing for port checking */
AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK(((TRUE != state) && (FALSE != state)), AIR_E_BAD_PARAMETER);
u32dat = state ? 1 : 0;
aml_writeReg(unit, DPCR_EN(port), u32dat);
return AIR_E_OK;
}
/* FUNCTION NAME: air_acl_getDropEnable
* PURPOSE:
* Get ACL drop precedence state
*
* INPUT:
* unit -- Device ID
* port -- Index of port number
*
* OUTPUT:
* ptr_state -- FALSE:Disable
* TRUE: Enable
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
*
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_getDropEnable(
const UI32_T unit,
const UI32_T port,
BOOL_T *ptr_state)
{
UI32_T u32dat = 0;
/* Mistake proofing for port checking */
AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
AIR_CHECK_PTR(ptr_state);
aml_readReg(unit, DPCR_EN(port), &u32dat);
*ptr_state = u32dat ? TRUE : FALSE;
return AIR_E_OK;
}
/* FUNCTION NAME: air_acl_setDropThreshold
* PURPOSE:
* Set ACL drop threshold.
*
* INPUT:
* unit -- Device ID
* port -- Index of port number
* color -- AIR_ACL_DP_COLOR_YELLOW: Yellow
* AIR_ACL_DP_COLOR_RED : Red
* queue -- Output queue number
* high -- High threshold
* low -- Low threshold
*
* OUTPUT:
* None
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
*
* NOTES:
* Key parameter include port, color, queue.
*/
AIR_ERROR_NO_T
air_acl_setDropThreshold(
const UI32_T unit,
const UI32_T port,
const AIR_ACL_DP_COLOR_T color,
const UI8_T queue,
const UI32_T high,
const UI32_T low)
{
UI32_T u32dat = 0;
/* Mistake proofing for port checking */
AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((color >= AIR_ACL_DP_COLOR_LAST), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((queue >= AIR_MAX_NUM_OF_QUEUE), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((high > BITS_RANGE(0, DPCR_HIGH_THRSH_WIDTH)), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((low > BITS_RANGE(0, DPCR_LOW_THRSH_WIDTH)), AIR_E_BAD_PARAMETER);
aml_readReg(unit, DPCR(port, color, queue), &u32dat);
u32dat = (u32dat & ~(DPCR_LOW_THRSH_MASK)) | low;
u32dat = (u32dat & ~(DPCR_HIGH_THRSH_MASK << DPCR_HIGH_THRSH_OFFSET)) | (high << DPCR_HIGH_THRSH_OFFSET);
aml_writeReg(unit, DPCR(port, color, queue), u32dat);
return AIR_E_OK;
}
/* FUNCTION NAME: air_acl_getDropThreshold
* PURPOSE:
* Get ACL drop threshold.
*
* INPUT:
* unit -- Device ID
* port -- Index of port number
* color -- AIR_ACL_DP_COLOR_YELLOW: Yellow
* AIR_ACL_DP_COLOR_RED : Red
* queue -- Output queue number
*
* OUTPUT:
* ptr_high -- High threshold
* ptr_low -- Low threshold
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
*
* NOTES:
* Key parameter include port, color, queue.
*/
AIR_ERROR_NO_T
air_acl_getDropThreshold(
const UI32_T unit,
const UI32_T port,
const AIR_ACL_DP_COLOR_T color,
const UI8_T queue,
UI32_T *ptr_high,
UI32_T *ptr_low)
{
UI32_T u32dat = 0;
/* Mistake proofing for port checking */
AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((color >= AIR_ACL_DP_COLOR_LAST), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((queue >= AIR_MAX_NUM_OF_QUEUE), AIR_E_BAD_PARAMETER);
AIR_CHECK_PTR(ptr_high);
AIR_CHECK_PTR(ptr_low);
aml_readReg(unit, DPCR(port, color, queue), &u32dat);
*ptr_low = u32dat & DPCR_LOW_THRSH_MASK;
*ptr_high = (u32dat >> DPCR_HIGH_THRSH_OFFSET) & DPCR_HIGH_THRSH_MASK;
return AIR_E_OK;
}
/* FUNCTION NAME: air_acl_setDropProbability
* PURPOSE:
* Set ACL drop probability.
*
* INPUT:
* unit -- Device ID
* port -- Index of port number
* color -- AIR_ACL_DP_COLOR_YELLOW: Yellow
* AIR_ACL_DP_COLOR_RED : Red
* queue -- Output queue number
* probability -- Drop probability (value:0 ~ 1023, unit:1/1023; eg: value-102 = 10% )
*
* OUTPUT:
* None
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
*
* NOTES:
* Key parameter include port, color, queue.
*/
AIR_ERROR_NO_T
air_acl_setDropProbability(
const UI32_T unit,
const UI32_T port,
const AIR_ACL_DP_COLOR_T color,
const UI8_T queue,
const UI32_T probability)
{
UI32_T u32dat = 0;
/* Mistake proofing for port checking */
AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((color >= AIR_ACL_DP_COLOR_LAST), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((queue >= AIR_MAX_NUM_OF_QUEUE), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((probability > BITS_RANGE(0, DPCR_PBB_WIDTH)), AIR_E_BAD_PARAMETER);
aml_readReg(unit, DPCR(port, color, queue), &u32dat);
u32dat = (u32dat & ~(DPCR_PBB_MASK << DPCR_PBB_OFFSET)) | (probability << DPCR_PBB_OFFSET);
aml_writeReg(unit, DPCR(port, color, queue), u32dat);
return AIR_E_OK;
}
/* FUNCTION NAME: air_acl_getDropProbability
* PURPOSE:
* Get ACL drop probability.
*
* INPUT:
* unit -- Device ID
* port -- Index of port number
* color -- AIR_ACL_DP_COLOR_YELLOW: Yellow
* AIR_ACL_DP_COLOR_RED : Red
* queue -- Output queue number
*
* OUTPUT:
* ptr_probability -- Drop probability (value:0 ~ 1023, unit:1/1023; eg: value-102 = 10% )
*
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
*
* NOTES:
* Key parameter include port, color, queue.
*/
AIR_ERROR_NO_T
air_acl_getDropProbability(
const UI32_T unit,
const UI32_T port,
const AIR_ACL_DP_COLOR_T color,
const UI8_T queue,
UI32_T *ptr_probability)
{
UI32_T u32dat = 0;
/* Mistake proofing for port checking */
AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((color >= AIR_ACL_DP_COLOR_LAST), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((queue >= AIR_MAX_NUM_OF_QUEUE), AIR_E_BAD_PARAMETER);
AIR_CHECK_PTR(ptr_probability);
/* Read data from register */
aml_readReg(unit, DPCR(port, color, queue), &u32dat);
(*ptr_probability) = BITS_OFF_R(u32dat, DPCR_PBB_OFFSET, DPCR_PBB_WIDTH);
return AIR_E_OK;
}
/* FUNCTION NAME:
* air_acl_setGlobalState
* PURPOSE:
* Set the ACL global enable state.
* INPUT:
* unit -- Device ID
* state -- Enable state of ACL
* OUTPUT:
* None
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_setGlobalState(
const UI32_T unit,
const BOOL_T state)
{
AIR_ERROR_NO_T ret = AIR_E_OK;
UI32_T value = 0, data = 0;
AIR_PARAM_CHK((TRUE != state) && (FALSE != state), AIR_E_BAD_PARAMETER);
value = state ? 1 : 0;
if ((ret = aml_readReg(unit, ACL_GLOBAL_CFG, &data)) != AIR_E_OK)
{
return ret;
}
data = (data & ~ACL_EN_MASK) | value;
if ((ret = aml_writeReg(unit, ACL_GLOBAL_CFG, data)) != AIR_E_OK)
{
return ret;
}
return AIR_E_OK;
}
/* FUNCTION NAME:
* air_acl_getGlobalState
* PURPOSE:
* Get the ACL global enable state.
* INPUT:
* unit -- Device ID
* OUTPUT:
* ptr_state -- Enable state
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_getGlobalState(
const UI32_T unit,
BOOL_T *ptr_state)
{
AIR_ERROR_NO_T ret = AIR_E_OK;
UI32_T value = 0;
AIR_CHECK_PTR(ptr_state);
if ((ret = aml_readReg(unit, ACL_GLOBAL_CFG, &value)) != AIR_E_OK)
{
return ret;
}
value &= ACL_EN_MASK;
*ptr_state = value ? TRUE : FALSE;
return AIR_E_OK;
}
/* FUNCTION NAME:
* air_acl_setUdfRule
* PURPOSE:
* Set ACL UDF rule of specified entry index.
* INPUT:
* unit -- Device ID
* rule_idx -- ACLUDF table entry index
* udf_rule -- Structure of ACL UDF rule entry
* OUTPUT:
* None
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_setUdfRule(
const UI32_T unit,
const UI32_T rule_idx,
AIR_ACL_UDF_RULE_T udf_rule)
{
AIR_ERROR_NO_T ret = AIR_E_OK;
UI32_T value = 0;
UI32_T data[3] = {0};
/* Check parameter */
AIR_PARAM_CHK((rule_idx >= ACL_MAX_UDF_NUM), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((TRUE != udf_rule.valid) && (FALSE != udf_rule.valid), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((udf_rule.offset_format >= AIR_ACL_RULE_OFS_FMT_LAST), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((udf_rule.offset >= ACL_MAX_WORD_OFST_NUM), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((udf_rule.cmp_sel >= AIR_ACL_RULE_CMP_SEL_LAST), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((udf_rule.pattern > ACL_MAX_CMP_PAT_NUM), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((udf_rule.mask > ACL_MAX_CMP_BIT_NUM), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((udf_rule.low_threshold > ACL_MAX_CMP_PAT_NUM), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((udf_rule.high_threshold > ACL_MAX_CMP_BIT_NUM), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((udf_rule.portmap & (~AIR_ALL_PORT_BITMAP)), AIR_E_BAD_PARAMETER);
_fillTblMultiFields(data, 3, PORT_BITMAP_OFFSET, PORT_BITMAP_WIDTH, udf_rule.portmap);
_fillTblMultiFields(data, 3, UDF_RULE_EN_OFFSET, UDF_RULE_EN_WIDTH, udf_rule.valid);
_fillTblMultiFields(data, 3, UDF_PKT_TYPE_OFFSET, UDF_PKT_TYPE_WIDTH, udf_rule.offset_format);
_fillTblMultiFields(data, 3, WORD_OFST_OFFSET, WORD_OFST_WIDTH, udf_rule.offset);
_fillTblMultiFields(data, 3, CMP_SEL_OFFSET, CMP_SEL_WIDTH, udf_rule.cmp_sel);
if(AIR_ACL_RULE_CMP_SEL_PATTERN == udf_rule.cmp_sel)
{
_fillTblMultiFields(data, 3, CMP_PAT_OFFSET, CMP_PAT_WIDTH, udf_rule.pattern);
_fillTblMultiFields(data, 3, CMP_MASK_OFFSET, CMP_MASK_WIDTH, udf_rule.mask);
}
else
{
_fillTblMultiFields(data, 3, CMP_PAT_OFFSET, CMP_PAT_WIDTH, udf_rule.low_threshold);
_fillTblMultiFields(data, 3, CMP_MASK_OFFSET, CMP_MASK_WIDTH, udf_rule.high_threshold);
}
if(AIR_E_TIMEOUT == _checkDone(unit, AIR_ACL_CHECK_UDF))
{
return AIR_E_TIMEOUT;
}
aml_writeReg(unit, ACL_AUTW0, data[0]);
aml_writeReg(unit, ACL_AUTW1, data[1]);
aml_writeReg(unit, ACL_AUTW2, data[2]);
value = (rule_idx & ACL_UDF_ADDR_MASK) | ACL_UDF_WRITE | (1U << ACL_UDF_ACC_OFFSET);
if ((ret = aml_writeReg(unit, ACL_AUTC, value)) != AIR_E_OK)
{
return ret;
}
return AIR_E_OK;
}
/* FUNCTION NAME:
* air_acl_getUdfRule
* PURPOSE:
* Get ACL UDF rule of specified entry index.
* INPUT:
* unit -- Device ID
* rule_idx -- ACLUDF table entry index
* OUTPUT:
* ptr_udf_rule -- Structure of ACL UDF rule entry
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_getUdfRule(
const UI32_T unit,
const UI8_T rule_idx,
AIR_ACL_UDF_RULE_T *ptr_udf_rule)
{
AIR_ERROR_NO_T ret = AIR_E_OK;
UI32_T value = 0;
UI32_T data[3] = {0};
/* Check parameter */
AIR_PARAM_CHK((rule_idx >= ACL_MAX_UDF_NUM), AIR_E_BAD_PARAMETER);
AIR_CHECK_PTR(ptr_udf_rule);
value = (rule_idx & ACL_UDF_ADDR_MASK) | ACL_UDF_READ | (1U << ACL_UDF_ACC_OFFSET);
if ((ret = aml_writeReg(unit, ACL_AUTC, value)) != AIR_E_OK)
{
return ret;
}
if(AIR_E_TIMEOUT == _checkDone(unit, AIR_ACL_CHECK_UDF))
{
return AIR_E_TIMEOUT;
}
aml_readReg(unit, ACL_AUTR0, data);
aml_readReg(unit, ACL_AUTR1, data+1);
aml_readReg(unit, ACL_AUTR2, data+2);
ACL_DERIVE_TBL_MULTIFIELDS(data, PORT_BITMAP_OFFSET, PORT_BITMAP_WIDTH, ptr_udf_rule->portmap);
ACL_DERIVE_TBL_MULTIFIELDS(data, UDF_RULE_EN_OFFSET, UDF_RULE_EN_WIDTH, ptr_udf_rule->valid);
ACL_DERIVE_TBL_MULTIFIELDS(data, UDF_PKT_TYPE_OFFSET, UDF_PKT_TYPE_WIDTH, ptr_udf_rule->offset_format);
ACL_DERIVE_TBL_MULTIFIELDS(data, WORD_OFST_OFFSET, WORD_OFST_WIDTH, ptr_udf_rule->offset);
ACL_DERIVE_TBL_MULTIFIELDS(data, CMP_SEL_OFFSET, CMP_SEL_WIDTH, ptr_udf_rule->cmp_sel);
if(AIR_ACL_RULE_CMP_SEL_PATTERN == ptr_udf_rule->cmp_sel)
{
ACL_DERIVE_TBL_MULTIFIELDS(data, CMP_PAT_OFFSET, CMP_PAT_WIDTH, ptr_udf_rule->pattern);
ACL_DERIVE_TBL_MULTIFIELDS(data, CMP_MASK_OFFSET, CMP_MASK_WIDTH, ptr_udf_rule->mask);
}
else
{
ACL_DERIVE_TBL_MULTIFIELDS(data, CMP_PAT_OFFSET, CMP_PAT_WIDTH, ptr_udf_rule->low_threshold);
ACL_DERIVE_TBL_MULTIFIELDS(data, CMP_MASK_OFFSET, CMP_MASK_WIDTH, ptr_udf_rule->high_threshold);
}
return AIR_E_OK;
}
/* FUNCTION NAME:
* air_acl_delUdfRule
* PURPOSE:
* Delete ACL UDF rule of specified entry index.
* INPUT:
* unit -- Device ID
* rule_idx -- ACLUDF table entry index
* OUTPUT:
* None
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_delUdfRule(
const UI32_T unit,
const UI8_T rule_idx)
{
AIR_ERROR_NO_T ret = AIR_E_OK;
UI32_T value = 0;
UI32_T data = 0;
/* Check parameter */
AIR_PARAM_CHK((rule_idx >= ACL_MAX_UDF_NUM), AIR_E_BAD_PARAMETER);
aml_writeReg(unit, ACL_AUTW0, data);
aml_writeReg(unit, ACL_AUTW1, data);
aml_writeReg(unit, ACL_AUTW2, data);
value = (rule_idx & ACL_UDF_ADDR_MASK) | ACL_UDF_WRITE | (1U << ACL_UDF_ACC_OFFSET);
if ((ret = aml_writeReg(unit, ACL_AUTC, value)) != AIR_E_OK)
{
return ret;
}
return AIR_E_OK;
}
/* FUNCTION NAME:
* air_acl_clearUdfRule
* PURPOSE:
* Clear acl all udf rule.
* INPUT:
* unit -- Device ID
* OUTPUT:
* None
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_clearUdfRule(
const UI32_T unit)
{
AIR_ERROR_NO_T ret = AIR_E_OK;
UI32_T value = 0;
value = ACL_UDF_CLEAR | (1U << ACL_UDF_ACC_OFFSET);
if ((ret = aml_writeReg(unit, ACL_AUTC, value)) != AIR_E_OK)
{
return ret;
}
return AIR_E_OK;
}
/* FUNCTION NAME:
* air_acl_setMeterTable
* PURPOSE:
* Set flow ingress rate limit by meter table.
* INPUT:
* unit -- Device ID
* meter_id -- Meter id
* enable -- Meter enable state
* rate -- Ratelimit(unit:64kbps)
* OUTPUT:
* None
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_setMeterTable(
const UI32_T unit,
const UI32_T meter_id,
const BOOL_T enable,
const UI32_T rate)
{
AIR_ERROR_NO_T ret = AIR_E_OK;
UI32_T value = 0;
/* Check parameter */
AIR_PARAM_CHK((meter_id >= ACL_MAX_METER_NUM), AIR_E_BAD_PARAMETER);
AIR_PARAM_CHK((rate > ACL_MAX_TOKEN_NUM), AIR_E_BAD_PARAMETER);
if(TRUE == enable)
{
value = (1 << ACL_RATE_BUSY_OFFSET) | ACL_RATE_WRITE | ((meter_id & ACL_RATE_ID_MASK) << ACL_RATE_ID_OFFSET) | ACL_RATE_EN |
(rate & ACL_RATE_TOKEN_MASK);
}
else if(FALSE == enable)
{
value = (1 << ACL_RATE_BUSY_OFFSET) | ACL_RATE_WRITE | ((meter_id & ACL_RATE_ID_MASK) << ACL_RATE_ID_OFFSET) | ACL_RATE_DIS;
}
else
{
return AIR_E_BAD_PARAMETER;
}
if(AIR_E_TIMEOUT == _checkDone(unit, AIR_ACL_CHECK_METER))
{
return AIR_E_TIMEOUT;
}
if ((ret = aml_writeReg(unit, ACLRMC, value)) != AIR_E_OK)
{
return ret;
}
return AIR_E_OK;
}
/* FUNCTION NAME:
* air_acl_getMeterTable
* PURPOSE:
* Get meter table configuration.
* INPUT:
* unit -- Device ID
* meter_id -- Meter id
* OUTPUT:
* ptr_enable -- Meter enable state
* ptr_rate -- Ratelimit(unit:64kbps)
* RETURN:
* AIR_E_OK
* AIR_E_BAD_PARAMETER
* NOTES:
* None
*/
AIR_ERROR_NO_T
air_acl_getMeterTable(
const UI32_T unit,
const UI32_T meter_id,
BOOL_T *ptr_enable,
UI32_T *ptr_rate)
{
AIR_ERROR_NO_T ret = AIR_E_OK;
UI32_T value = 0;
/* Check parameter */
AIR_PARAM_CHK((meter_id >= ACL_MAX_METER_NUM), AIR_E_BAD_PARAMETER);
AIR_CHECK_PTR(ptr_enable);
AIR_CHECK_PTR(ptr_rate);
if(AIR_E_TIMEOUT == _checkDone(unit, AIR_ACL_CHECK_METER))
{
return AIR_E_TIMEOUT;
}
value = (1 << ACL_RATE_BUSY_OFFSET) | ACL_RATE_READ | ((meter_id & ACL_RATE_ID_MASK) << ACL_RATE_ID_OFFSET) | ACL_RATE_EN;
if ((ret = aml_writeReg(unit, ACLRMC, value)) != AIR_E_OK)
{
return ret;
}
aml_readReg(unit, ACLRMD1, &value);
*ptr_enable = ((value >> ACL_RATE_EN_OFFSET) & 0x1) ? TRUE : FALSE;
*ptr_rate = value & ACL_RATE_TOKEN_MASK;
return AIR_E_OK;
}