blob: e87c85fa747f38f32c7832bf27495c2e5458014e [file] [log] [blame]
/*******************************************************************************
Copyright (C) Marvell International Ltd. and its affiliates
This software file (the "File") is owned and distributed by Marvell
International Ltd. and/or its affiliates ("Marvell") under the following
alternative licensing terms. Once you have made an election to distribute the
File under one of the following license alternatives, please (i) delete this
introductory statement regarding license alternatives, (ii) delete the two
license alternatives that you have not elected to use and (iii) preserve the
Marvell copyright notice above.
********************************************************************************
Marvell Commercial License Option
If you received this File from Marvell and you have entered into a commercial
license agreement (a "Commercial License") with Marvell, the File is licensed
to you under the terms of the applicable Commercial License.
********************************************************************************
Marvell GPL License Option
If you received this File from Marvell, you may opt to use, redistribute and/or
modify this File in accordance with the terms and conditions of the General
Public License Version 2, June 1991 (the "GPL License"), a copy of which is
available along with the File in the license.txt file or by writing to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
DISCLAIMED. The GPL License provides additional details about this warranty
disclaimer.
********************************************************************************
Marvell BSD License Option
If you received this File from Marvell, you may opt to use, redistribute and/or
modify this File under the following licensing terms.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Marvell nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
/*******************************************************************************
* tpm_ctc_cm.c
*
*
* MODULE : TPM
*
* DESCRIPTION : This file config CTC CnM rule
*
* MODIFICATION HISTORY:
* 7Feb12 jinghua - initial version created.
*
* FILE REVISION NUMBER:
* Revision: 1.12
*******************************************************************************/
#include "tpm_common.h"
#include "tpm_header.h"
#include "tpm_ctc_cm.h"
#include "tpm_pkt_proc_logic.h"
#define IF_ERROR(ret) \
if (ret != TPM_OK) {\
TPM_OS_ERROR(TPM_CTC_CM_MOD, " recvd ret_code(%d)\n", ret);\
return(ret);\
}
/*******************************************************************************
* tpm_ctc_cm_rule_add()
*
* DESCRIPTION: Main function for adding CnM API rule.
*
* INPUTS:
* ipv4_key_idx - key for IPv4 sub pattern.
* Other inputs/outputs are same as API call
*
* OUTPUTS:
* rule_index - CTC CnM rule index
*
* RETURNS:
* On success, the function returns TPM_RC_OK. On error different types are returned
* according to the case - see tpm_db_err_t.
*
* COMMENTS:
*
*******************************************************************************/
tpm_error_code_t tpm_ctc_cm_rule_add(uint32_t owner_id,
tpm_src_port_type_t src_port,
uint32_t precedence,
tpm_parse_fields_t l2_parse_rule_bm,
tpm_parse_fields_t ipv4_parse_rule_bm,
tpm_parse_fields_t ipv6_parse_rule_bm,
tpm_l2_acl_key_t *l2_key,
tpm_ipv4_acl_key_t *ipv4_key,
tpm_ipv6_acl_key_t *ipv6_key,
tpm_pkt_frwd_t *pkt_frwd,
tpm_pkt_action_t pkt_act,
uint32_t pbits,
uint32_t ipv4_key_idx,
uint32_t *rule_index)
{
tpm_error_code_t ret_code = ERR_GENERAL;
if (l2_parse_rule_bm)
ret_code = tpm_proc_add_l2_cnm_rule(owner_id, src_port, precedence, l2_parse_rule_bm, l2_key,
ipv4_key_idx, pkt_frwd, pkt_act, pbits, rule_index);
else if (ipv4_parse_rule_bm)
ret_code = tpm_proc_add_ipv4_cnm_rule(owner_id, src_port, precedence, ipv4_parse_rule_bm,
ipv4_key, pkt_frwd, pkt_act, pbits, rule_index);
else if (ipv6_parse_rule_bm)
ret_code = tpm_proc_add_ipv6_cnm_rule(owner_id, src_port, precedence, ipv6_parse_rule_bm,
ipv6_key, pkt_frwd, pkt_act, pbits, rule_index);
return ret_code;
}
/*******************************************************************************
* tpm_ctc_cm_acl_rule_del()
*
* DESCRIPTION: Main function for deleting CnM API rule.
*
* INPUTS:
*
* owner_id - APP owner id should be used for all API calls.
* cm_rule - CTC CnM rule data pointer
*
* OUTPUTS:
*
* RETURNS:
* On success, the function returns TPM_RC_OK. On error different types are returned
* according to the case - see tpm_db_err_t.
*
* COMMENTS:
*
*******************************************************************************/
tpm_error_code_t tpm_ctc_cm_rule_del(uint32_t owner_id, tpm_db_ctc_cm_rule_entry_t *cm_rule)
{
tpm_error_code_t ret_code = ERR_GENERAL;
if ((cm_rule)->l2_parse_rule_bm)
ret_code = tpm_proc_del_l2_cnm_rule(owner_id, cm_rule->cm_main_rule_index);
else if ((cm_rule)->ipv4_parse_rule_bm)
ret_code = tpm_proc_del_ipv4_cnm_rule(owner_id, cm_rule->cm_main_rule_index);
else if ((cm_rule)->ipv6_parse_rule_bm)
ret_code = tpm_proc_del_ipv4_cnm_rule(owner_id, cm_rule->cm_main_rule_index);
return ret_code;
}
/*******************************************************************************
* tpm_ctc_cm_add_rule_check()
*
* DESCRIPTION: The function checks consistency of the tpm_ctc_cm_acl_rule_add params.
*
* INPUTS:
* - See tpm_ctc_cm_acl_rule_add
*
* RETURNS:
* On success, the function returns TPM_RC_OK. On error different types are returned
* according to the case - see tpm_db_err_t.
*
* COMMENTS:
*
*******************************************************************************/
tpm_error_code_t tpm_ctc_cm_add_rule_check(uint32_t owner_id,
tpm_src_port_type_t src_port,
uint32_t precedence,
tpm_parse_fields_t l2_parse_rule_bm,
tpm_parse_fields_t ipv4_parse_rule_bm,
tpm_parse_fields_t ipv6_parse_rule_bm,
tpm_l2_acl_key_t *l2_key,
tpm_ipv4_acl_key_t *ipv4_key,
tpm_ipv6_acl_key_t *ipv6_key,
tpm_pkt_frwd_t *pkt_frwd,
tpm_pkt_action_t pkt_act,
uint32_t pbits)
{
int32_t int_ret_code;
uint32_t num_rules, dummy_entry = 0;
uint8_t is_range_full;
tpm_db_ctc_cm_enable_t ctc_cm_enable = TPM_CTC_CM_DISABLED;
tpm_db_ctc_cm_ipv6_parse_win_t ctc_cm_ipv6_parse_win;
tpm_db_ctc_cm_enable_get(&ctc_cm_enable);
/* if CTC CnM enabled */
if (ctc_cm_enable == TPM_CTC_CM_DISABLED) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "CTC CnM is disabled!\n");
return(ERR_GENERAL);
}
if (src_port < TPM_SRC_PORT_UNI_0 || src_port > TPM_SRC_PORT_UNI_VIRT) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "src_port (%d) illegal!\n", src_port);
return(ERR_SRC_PORT_INVALID);
}
if (!tpm_db_eth_port_valid(src_port)) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "src_port (%d) illegal!\n", src_port);
return(ERR_SRC_PORT_INVALID);
}
if (precedence >= TPM_MAX_NUM_CTC_PRECEDENCE) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "precedence (%d) illegal!\n", precedence);
return(ERR_CTC_CM_PREC_INVALID);
}
num_rules = tpm_db_ctc_cm_get_num_rules(src_port);
if (precedence > num_rules) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "precedence (%d) must be continous!\n", precedence);
return(ERR_CTC_CM_PREC_INVALID);
}
if (!l2_parse_rule_bm && !ipv4_parse_rule_bm && !ipv6_parse_rule_bm) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "both l2_parse_rule_bm and ipv4_parse_rule_bm are Zero!\n");
return(ERR_PARSE_MAP_INVALID);
}
if (l2_parse_rule_bm & ~(TPM_L2_PARSE_MAC_DA | TPM_L2_PARSE_MAC_SA | TPM_L2_PARSE_ONE_VLAN_TAG |
TPM_L2_PARSE_ETYPE)) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "l2_parse_rule_bm (%d) is invalid!\n", l2_parse_rule_bm);
return(ERR_PARSE_MAP_INVALID);
}
if (ipv4_parse_rule_bm & ~(TPM_IPv4_PARSE_SIP | TPM_IPv4_PARSE_DIP | TPM_IPv4_PARSE_DSCP |
TPM_IPv4_PARSE_PROTO | TPM_PARSE_L4_SRC | TPM_PARSE_L4_DST)) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "ipv4_parse_rule_bm (%d) is invalid!\n", ipv4_parse_rule_bm);
return(ERR_PARSE_MAP_INVALID);
}
/* ipv6_parse_rule_bm depends on ipv6 CnM parse window */
tpm_db_ctc_cm_ipv6_parse_win_get(&ctc_cm_ipv6_parse_win);
if(TPM_CTC_CM_IPv6_FIRST_24B == ctc_cm_ipv6_parse_win) {
if (ipv6_parse_rule_bm & ~(TPM_IPv6_PARSE_SIP | TPM_IPv6_PARSE_DSCP | TPM_IPv6_PARSE_NH |
TPM_IPv6_PARSE_HOPL)) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "ipv6_parse_rule_bm (%d) is invalid!\n", ipv6_parse_rule_bm);
return(ERR_PARSE_MAP_INVALID);
}
} else {
if (ipv6_parse_rule_bm & ~(TPM_IPv6_PARSE_DIP | TPM_PARSE_L4_SRC | TPM_PARSE_L4_DST)) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "ipv6_parse_rule_bm (%d) is invalid!\n", ipv6_parse_rule_bm);
return(ERR_PARSE_MAP_INVALID);
}
}
if (l2_parse_rule_bm && (NULL == l2_key)) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "l2_key can not be NULL!\n");
return(ERR_NULL_POINTER);
}
if (ipv4_parse_rule_bm && (NULL == ipv4_key)) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "ipv4_key can not be NULL!\n");
return(ERR_NULL_POINTER);
}
if (ipv6_parse_rule_bm && (NULL == ipv6_key)) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "ipv6_key can not be NULL!\n");
return(ERR_NULL_POINTER);
}
if (!pkt_act) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "pkt_act is Zero!\n");
return(ERR_ACTION_INVALID);
}
if ((pkt_act & (TPM_ACTION_SET_TARGET_PORT | TPM_ACTION_SET_TARGET_QUEUE)) &&
(NULL == pkt_frwd)) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "pkt_frwd is NULL when TPM_ACTION_SET_TARGET_PORT or"
" TPM_ACTION_SET_TARGET_QUEUE!\n");
return(ERR_NULL_POINTER);
}
if (pkt_frwd->trg_port < TPM_TRG_PORT_WAN || pkt_frwd->trg_port > TPM_TRG_LLID_7) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "trg_port (%d) is invalid!\n", pkt_frwd->trg_port);
return(ERR_FRWD_INVALID);
}
if (pkt_act & ~(TPM_ACTION_SET_TARGET_PORT | TPM_ACTION_SET_TARGET_QUEUE | TPM_ACTION_SET_PKT_MOD)) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "pkt_act (%d) is invalid!\n", pkt_act);
return(ERR_ACTION_INVALID);
}
if (pkt_act & TPM_ACTION_SET_PKT_MOD) {
if (pbits > 7) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "pbits (%d) is invalid!\n", pbits);
return(ERR_L2_KEY_INVALID);
}
int_ret_code = tpm_db_split_mod_get_index_by_p_bits(pbits, &dummy_entry);
if (int_ret_code != TPM_DB_OK) {
TPM_OS_ERROR(TPM_TPM_LOG_MOD, " unsupported p-bit value: %d\n", pbits);
return(ERR_MOD_INVALID);
}
}
if (l2_parse_rule_bm && ipv4_parse_rule_bm) {
is_range_full = tpm_proc_if_ipv4_pre_range_is_full(src_port, ipv4_parse_rule_bm, ipv4_key);
if (is_range_full != TPM_FALSE) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "not enough room for new ipv4 pre-filter key!\n");
return(ERR_OUT_OF_RESOURCES);
}
}
is_range_full = tpm_proc_if_cnm_main_range_is_full(src_port, precedence);
if (is_range_full != TPM_FALSE) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "not enough room for new cnm rule!\n");
return(ERR_OUT_OF_RESOURCES);
}
return TPM_RC_OK;
}
/*******************************************************************************
* tpm_ctc_cm_acl_rule_add()
*
* DESCRIPTION: Main function for adding CnM API rule.
*
* INPUTS:
* All inputs/outputs are same as API call
*
* OUTPUTS:
*
* RETURNS:
* On success, the function returns TPM_RC_OK. On error different types are returned
* according to the case - see tpm_db_err_t.
*
* COMMENTS:
*
*******************************************************************************/
tpm_error_code_t tpm_ctc_cm_acl_rule_add(uint32_t owner_id,
tpm_src_port_type_t src_port,
uint32_t precedence,
tpm_parse_fields_t l2_parse_rule_bm,
tpm_parse_fields_t ipv4_parse_rule_bm,
tpm_parse_fields_t ipv6_parse_rule_bm,
tpm_l2_acl_key_t *l2_key,
tpm_ipv4_acl_key_t *ipv4_key,
tpm_ipv6_acl_key_t *ipv6_key,
tpm_pkt_frwd_t *pkt_frwd,
tpm_pkt_action_t pkt_act,
uint32_t pbits)
{
tpm_error_code_t ret_code;
tpm_db_error_t db_ret;
tpm_db_ctc_cm_rule_entry_t cm_rule;
uint32_t ipv4_sub_pattern_key_idx = TPM_CNM_INVALID_IPV4_PRE_FILTER_KEY_ID;
uint32_t rule_index;
uint32_t rule_index_tmp;
uint32_t num_prec;
int32_t loop;
int32_t prece_tmp;
/* Check parameters */
ret_code = tpm_ctc_cm_add_rule_check(owner_id, src_port, precedence, l2_parse_rule_bm, ipv4_parse_rule_bm,
ipv6_parse_rule_bm, l2_key, ipv4_key, ipv6_key, pkt_frwd, pkt_act, pbits);
IF_ERROR(ret_code);
/* add IPv4_Pre of Combo rule */
if (l2_parse_rule_bm && ipv4_parse_rule_bm) {
ret_code = tpm_proc_add_cnm_ipv4_pre_filter_key(owner_id, src_port, ipv4_parse_rule_bm, ipv4_key,
&ipv4_sub_pattern_key_idx);
IF_ERROR(ret_code);
}
/* insert new rule */
ret_code = tpm_ctc_cm_rule_add(owner_id, src_port, precedence, l2_parse_rule_bm, ipv4_parse_rule_bm,
ipv6_parse_rule_bm, l2_key, ipv4_key, ipv6_key, pkt_frwd, pkt_act, pbits,
ipv4_sub_pattern_key_idx, &rule_index);
IF_ERROR(ret_code);
/* update existing rules if needed */
num_prec = tpm_db_ctc_cm_get_num_rules(src_port);
/* from the lowest precedence to current precedence, decreased by 1 */
for (loop = num_prec; loop > precedence; loop--) {
prece_tmp = loop - 1;
db_ret = tpm_db_ctc_cm_rule_get(src_port, prece_tmp, &cm_rule);
if (TPM_DB_OK != db_ret) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, " DB failed, recvd ret_code(%d)\n", db_ret);
return ERR_CTC_CM_DB_ERR;
}
/* first remvoe the old one, then add the new one */
ret_code = tpm_ctc_cm_rule_del(owner_id, &cm_rule);
IF_ERROR(ret_code);
/* last prece is 7, do not need to add the rule which has just
* been remvoed.
*/
if ((TPM_MAX_NUM_CTC_PRECEDENCE - 1) == prece_tmp)
continue;
/* add this rule with prece++ */
ret_code = tpm_ctc_cm_rule_add(owner_id, src_port, prece_tmp + 1, cm_rule.l2_parse_rule_bm,
cm_rule.ipv4_parse_rule_bm, cm_rule.ipv6_parse_rule_bm,
&(cm_rule.l2_key), &(cm_rule.ipv4_key), &(cm_rule.ipv6_key),
&(cm_rule.pkt_frwd), (cm_rule.pkt_act), cm_rule.pbits,
cm_rule.ipv4_sub_pattern_key, &rule_index_tmp);
IF_ERROR(ret_code);
/* overwrite DB entry of lower precedence */
db_ret = tpm_db_ctc_cm_rule_set(src_port, prece_tmp + 1, cm_rule.l2_parse_rule_bm,
cm_rule.ipv4_parse_rule_bm, cm_rule.ipv6_parse_rule_bm,
&(cm_rule.l2_key), &(cm_rule.ipv4_key), &(cm_rule.ipv6_key),
&(cm_rule.pkt_frwd), (cm_rule.pkt_act),
cm_rule.pbits, cm_rule.ipv4_sub_pattern_key, rule_index_tmp);
if (TPM_DB_OK != db_ret) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, " DB failed, recvd ret_code(%d)\n", db_ret);
return ERR_CTC_CM_DB_ERR;
}
}
/* set db of this CnM rule */
db_ret = tpm_db_ctc_cm_rule_set(src_port, precedence, l2_parse_rule_bm, ipv4_parse_rule_bm,
ipv6_parse_rule_bm, l2_key, ipv4_key,
ipv6_key, pkt_frwd, pkt_act, pbits,
ipv4_sub_pattern_key_idx, rule_index);
if (TPM_DB_OK != db_ret) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, " DB failed, recvd ret_code(%d)\n", db_ret);
return ERR_CTC_CM_DB_ERR;
}
return TPM_RC_OK;
}
/*******************************************************************************
* tpm_ctc_cm_del_rule_check()
*
* DESCRIPTION: The function checks consistency of the tpm_ctc_cm_del_rule_check params.
*
* INPUTS:
* - See tpm_ctc_cm_del_rule_check
*
* RETURNS:
* On success, the function returns TPM_RC_OK. On error different types are returned
* according to the case - see tpm_db_err_t.
*
* COMMENTS:
*
*******************************************************************************/
tpm_error_code_t tpm_ctc_cm_del_rule_check(uint32_t owner_id,
tpm_src_port_type_t src_port,
uint32_t precedence)
{
tpm_db_error_t db_ret;
tpm_db_ctc_cm_rule_entry_t cm_rule;
tpm_db_ctc_cm_enable_t ctc_cm_enable = TPM_CTC_CM_DISABLED;
tpm_db_ctc_cm_enable_get(&ctc_cm_enable);
/* if CTC CnM enabled */
if (ctc_cm_enable == TPM_CTC_CM_DISABLED) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "CTC CnM is disabled!\n");
return(ERR_GENERAL);
}
if (src_port < TPM_SRC_PORT_UNI_0 || src_port > TPM_SRC_PORT_UNI_VIRT) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "src_port (%d) illegal!\n", src_port);
return(ERR_SRC_PORT_INVALID);
}
if (precedence >= TPM_MAX_NUM_CTC_PRECEDENCE) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "precedence (%d) illegal!\n", precedence);
return(ERR_CTC_CM_PREC_INVALID);
}
db_ret = tpm_db_ctc_cm_rule_get(src_port, precedence, &cm_rule);
if (TPM_DB_OK != db_ret) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "get DB failed, ret_code: (%d), src_port: (%d), precedence: (%d)\n",
db_ret, src_port, precedence);
return(ERR_CTC_CM_DB_ERR);
}
return TPM_RC_OK;
}
/*******************************************************************************
* tpm_ctc_cm_acl_rule_del()
*
* DESCRIPTION: Main function for deleting CnM API rule.
*
* INPUTS:
* All inputs/outputs are same as API call
*
* OUTPUTS:
*
* RETURNS:
* On success, the function returns TPM_RC_OK. On error different types are returned
* according to the case - see tpm_db_err_t.
*
* COMMENTS:
*
*******************************************************************************/
tpm_error_code_t tpm_ctc_cm_acl_rule_del(uint32_t owner_id,
tpm_src_port_type_t src_port,
uint32_t precedence)
{
tpm_error_code_t ret_code;
tpm_db_error_t db_ret;
tpm_db_ctc_cm_rule_entry_t cm_rule;
uint32_t rule_index;
uint32_t num_prec;
uint32_t loop;
/* Check parameters */
ret_code = tpm_ctc_cm_del_rule_check(owner_id, src_port, precedence);
IF_ERROR(ret_code);
db_ret = tpm_db_ctc_cm_rule_get(src_port, precedence, &cm_rule);
if (TPM_DB_OK != db_ret) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "get DB failed, ret_code: (%d), src_port: (%d), precedence: (%d)\n",
db_ret, src_port, precedence);
return(ERR_CTC_CM_DB_ERR);
}
/* remove rule */
ret_code = tpm_ctc_cm_rule_del(owner_id, &cm_rule);
IF_ERROR(ret_code);
/* remove IPv4_Pre of Combo rule */
if (cm_rule.l2_parse_rule_bm && cm_rule.ipv4_parse_rule_bm) {
ret_code = tpm_proc_del_cnm_ipv4_pre_filter_key(owner_id, src_port, cm_rule.ipv4_sub_pattern_key);
IF_ERROR(ret_code);
}
/* update existing rules if needed */
num_prec = tpm_db_ctc_cm_get_num_rules(src_port);
/* from the next lower-to current precedence to the lowest precedence, increased by 1 */
for (loop = precedence + 1; loop < num_prec; loop++) {
db_ret = tpm_db_ctc_cm_rule_get(src_port, loop, &cm_rule);
if (TPM_DB_OK != db_ret) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, " DB failed, recvd ret_code(%d)\n", db_ret);
return ERR_CTC_CM_DB_ERR;
}
/* add this rule with prece++ */
ret_code = tpm_ctc_cm_rule_add(owner_id, src_port, loop - 1, cm_rule.l2_parse_rule_bm, cm_rule.ipv4_parse_rule_bm,
cm_rule.ipv6_parse_rule_bm, &(cm_rule.l2_key), &(cm_rule.ipv4_key),
&(cm_rule.ipv6_key), &(cm_rule.pkt_frwd),
cm_rule.pkt_act, cm_rule.pbits, cm_rule.ipv4_sub_pattern_key, &rule_index);
IF_ERROR(ret_code);
/* overwrite DB entry of higher precedence */
db_ret = tpm_db_ctc_cm_rule_set(src_port, loop - 1, cm_rule.l2_parse_rule_bm, cm_rule.ipv4_parse_rule_bm,
cm_rule.ipv6_parse_rule_bm, &(cm_rule.l2_key),
&(cm_rule.ipv4_key), &(cm_rule.ipv6_key),
&(cm_rule.pkt_frwd), cm_rule.pkt_act,
cm_rule.pbits, cm_rule.ipv4_sub_pattern_key, rule_index);
if (TPM_DB_OK != db_ret) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, " DB failed, recvd ret_code(%d)\n", db_ret);
return ERR_CTC_CM_DB_ERR;
}
/* remove the old one */
ret_code = tpm_ctc_cm_rule_del(owner_id, &cm_rule);
IF_ERROR(ret_code);
}
/* reset the db of last rule */
db_ret = tpm_db_ctc_cm_rule_delete(src_port, num_prec - 1);
if (TPM_DB_OK != db_ret) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, " DB failed, recvd ret_code(%d)\n", db_ret);
return ERR_CTC_CM_DB_ERR;
}
return ret_code;
}
/*******************************************************************************
* tpm_ctc_cm_ipv4_rule2cm()
*
* DESCRIPTION: check if this rule can goto CnM stage from IPv4 stage.
*
* INPUTS:
* parse_flags_bm - Bitmap containing the significant flags result of the primary ACL filtering.
* pkt_act - Action associated to the rule
*
* OUTPUTS:
*
* RETURNS:
* On success, the function returns true. On error returns false.
*
* COMMENTS:
*
*******************************************************************************/
bool tpm_ctc_cm_ipv4_rule2cm(tpm_parse_flags_t parse_flags_bm, tpm_rule_action_t *rule_action)
{
tpm_db_ctc_cm_enable_t ctc_cm_enable = TPM_CTC_CM_DISABLED;
tpm_db_ctc_cm_enable_get(&ctc_cm_enable);
if (ctc_cm_enable == TPM_CTC_CM_DISABLED) {
/* CTC CnM is disabled */
return false;
}
/* not MTM, not to CPU */
if ( (parse_flags_bm & TPM_PARSE_FLAG_MTM_FALSE)
&& !(rule_action->pkt_act & TPM_ACTION_TO_CPU))
return true;
else
return false;
}
/*******************************************************************************
* tpm_ctc_cm_l3_rule2cm_sram()
*
* DESCRIPTION: check if this rule can goto CnM stage from ETH stage when building sram of ETH rule.
*
* INPUTS:
* parse_flags_bm - Bitmap containing the significant flags result of the primary ACL filtering.
* pkt_act - Action associated to the rule
*
* OUTPUTS:
*
* RETURNS:
* On success, the function returns true. On error returns false.
*
* COMMENTS:
*
*******************************************************************************/
bool tpm_ctc_cm_l3_rule2cm_sram(tpm_parse_flags_t parse_flags_bm, tpm_rule_action_t *rule_action)
{
tpm_db_ctc_cm_enable_t ctc_cm_enable = TPM_CTC_CM_DISABLED;
tpm_db_ctc_cm_enable_get(&ctc_cm_enable);
if (ctc_cm_enable == TPM_CTC_CM_DISABLED) {
/* CTC CnM is disabled */
return false;
}
/* [!mac-to-me] */
if (parse_flags_bm & TPM_PARSE_FLAG_MTM_FALSE)
return true;
else
return false;
}
/*******************************************************************************
* tpm_ctc_cm_l3_rule2cm_sram()
*
* DESCRIPTION: check if this rule can goto CnM stage from ETH stage when building tcam of ETH rule.
*
* INPUTS:
* parse_flags_bm - Bitmap containing the significant flags result of the primary ACL filtering.
* l3_key - Structure for PPPoE proto or ether type. In order to define a rule for
* any ether type, the ether type value should be set to 0xFFFF
* rule_action -used to get the next_stage of this rule
* OUTPUTS:
*
* RETURNS:
* On success, the function returns true. On error returns false.
*
* COMMENTS:
*
*******************************************************************************/
bool tpm_ctc_cm_l3_rule2cm_tcam(tpm_parse_flags_t parse_flags_bm, tpm_l3_type_key_t *l3_key, tpm_rule_action_t *rule_action)
{
tpm_db_ctc_cm_enable_t ctc_cm_enable = TPM_CTC_CM_DISABLED;
tpm_db_ctc_cm_enable_get(&ctc_cm_enable);
if (ctc_cm_enable == TPM_CTC_CM_DISABLED) {
/* CTC CnM is disabled */
return false;
}
/* not ipv4/6 or pppoe and [!mac-to-me] */
if ( (0x0800 != l3_key->ether_type_key)
&& (0x86dd != l3_key->ether_type_key)
&& (ETH_P_PPP_SES != l3_key->ether_type_key)
&& (parse_flags_bm & TPM_PARSE_FLAG_MTM_FALSE)
&& (STAGE_CTC_CM == rule_action->next_phase))
return true;
else
return false;
}
/*******************************************************************************
* tpm_ctc_cm_ipv6_acl_rule_add()
*
* DESCRIPTION: Main function for adding CnM API rule.
*
* INPUTS:
* All inputs/outputs are same as API call
*
* OUTPUTS:
*
* RETURNS:
* On success, the function returns TPM_RC_OK. On error different types are returned
* according to the case - see tpm_db_err_t.
*
* COMMENTS:
*
*******************************************************************************/
tpm_error_code_t tpm_ctc_cm_ipv6_acl_rule_add(uint32_t owner_id,
tpm_src_port_type_t src_port,
uint32_t precedence,
tpm_parse_fields_t ipv6_parse_rule_bm,
tpm_ipv6_acl_key_t *ipv6_key,
tpm_pkt_frwd_t *pkt_frwd,
tpm_pkt_action_t pkt_act,
uint32_t pbits)
{
tpm_error_code_t ret_code;
tpm_parse_fields_t ipv4_parse_rule_bm = 0;
tpm_parse_fields_t l2_parse_rule_bm = 0;
tpm_l2_acl_key_t l2_key;
tpm_ipv4_acl_key_t ipv4_key;
ret_code = tpm_ctc_cm_acl_rule_add(owner_id, src_port, precedence, l2_parse_rule_bm,
ipv4_parse_rule_bm, ipv6_parse_rule_bm, &l2_key,
&ipv4_key, ipv6_key, pkt_frwd, pkt_act, pbits);
IF_ERROR(ret_code);
return TPM_RC_OK;
}
/*******************************************************************************
* tpm_ctc_cm_set_ipv6_parse_win()
*
* DESCRIPTION: Main function for adding CnM API rule.
*
* INPUTS:
* All inputs/outputs are same as API call
*
* OUTPUTS:
*
* RETURNS:
* On success, the function returns TPM_RC_OK. On error different types are returned
* according to the case - see tpm_db_err_t.
*
* COMMENTS:
*
*******************************************************************************/
tpm_error_code_t tpm_ctc_cm_set_ipv6_parse_win(uint32_t owner_id, tpm_ctc_cm_ipv6_parse_win_t ipv6_parse_window)
{
uint32_t entry_id;
uint32_t ipv6_rule_nums;
int32_t ret_code = TPM_OK;
tpm_db_ctc_cm_ipv6_parse_win_t ipv6_parse_win_orig;
tpm_db_ctc_cm_ipv6_parse_win_get(&ipv6_parse_win_orig);
if (ipv6_parse_window == ipv6_parse_win_orig) {
TPM_OS_INFO(TPM_CTC_CM_MOD, "ipv6 parse win remains the same\n");
return TPM_OK;
}
/* if there is still IPv6 CnM rule exist, reture error */
ipv6_rule_nums = tpm_db_ctc_cm_get_ipv6_num_rules();
if (0 != ipv6_rule_nums) {
TPM_OS_ERROR(TPM_CTC_CM_MOD, "there is still IPv6 CnM rule exist, remove first!\n");
return ERR_CTC_CM_DB_ERR;
}
/* get ipv6_ety_rule_num */
tpm_db_ctc_cm_ipv6_ety_rule_num_get(&entry_id);
ret_code = tpm_pncl_init_cnm_main_ety_ipv6(entry_id, ipv6_parse_window);
IF_ERROR(ret_code);
/* set new ipv6 parse window */
tpm_db_ctc_cm_ipv6_parse_win_set(ipv6_parse_window);
return TPM_RC_OK;
}