blob: 2f33320ae6c56ca0511adad1b4f4a068e3a7844a [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_self_check.c
*
* DESCRIPTION:
* API definitions for TPM checks the hw and the db are synchronized or not
*
* DEPENDENCIES:
*
* FILE REVISION NUMBER:
*******************************************************************************/
#include "tpm_common.h"
#include "tpm_header.h"
#include "tpm_sysfs_utils.h"
#define IF_ERROR(ret) \
if (ret != TPM_OK) {\
TPM_OS_ERROR(TPM_TPM_LOG_MOD, " recvd ret_code(%d)\n", ret);\
return(ret);\
}
#define TPM_CHECK_DIV_BY_32(x) ((x) >> 5)
#define TPM_CHECK_MOD_32(x) ((x) & 0x1f)
extern char *tpm_db_api_type_str[TPM_MAX_API_TYPES];
extern char *opCodeOperationStr[30];
/*******************************************************************************
* pnc_mismatch_info_show - Show detailed difference between two tpm rule entry
*
* INPUT:
* tpm_pnc_all_t *entry1
* tpm_pnc_all_t *entry2
*
* OUTPUT:
* None
*
* RETURN:
*
* COMMENTS:
* None
*******************************************************************************/
static void pnc_mismatch_info_show(tpm_pnc_all_t *entry1, tpm_pnc_all_t *entry2)
{
if (entry1 == NULL || entry2 == NULL)
return;
printk("======================================================================================\n");
printk("Tcam mismatch element: ");
if (memcmp(&entry1->tcam_entry.lu_id, &entry2->tcam_entry.lu_id, sizeof(uint32_t)))
printk("Lookup ID, ");
if (memcmp(&entry1->tcam_entry.port_ids, &entry2->tcam_entry.port_ids, sizeof(tpm_gmac_bm_t)))
printk("Port ID, ");
if (memcmp(&entry1->tcam_entry.add_info_data, &entry2->tcam_entry.add_info_data, sizeof(uint32_t)))
printk("AddInfo data, ");
if (memcmp(&entry1->tcam_entry.add_info_mask, &entry2->tcam_entry.add_info_mask, sizeof(uint32_t)))
printk("AddInfo mask, ");
if (memcmp(&entry1->tcam_entry.pkt_data.pkt_byte[0], &entry2->tcam_entry.pkt_data.pkt_byte[0],
TPM_TCAM_PKT_WIDTH * sizeof(uint8_t)))
printk("Header data");
printk("\n");
printk("Sram mismatch element: ");
if (memcmp(&entry1->sram_entry.add_info_data, &entry2->sram_entry.add_info_data, sizeof(uint32_t)))
printk("Additional Info, ");
if (memcmp(&entry1->sram_entry.add_info_mask, &entry2->sram_entry.add_info_mask, sizeof(uint32_t)))
printk("Add Info Mask, ");
if (memcmp(&entry1->sram_entry.flowid_updt_mask, &entry2->sram_entry.flowid_updt_mask, sizeof(uint32_t)))
printk("FlowID_updt_mask, ");
if (memcmp(&entry1->sram_entry.flowid_val, &entry2->sram_entry.flowid_val, sizeof(uint32_t)))
printk("Flow ID, ");
if (memcmp(&entry1->sram_entry.lookup_done, &entry2->sram_entry.lookup_done, sizeof(uint32_t)))
printk("Lookup done, ");
if (memcmp(&entry1->sram_entry.next_lu_id, &entry2->sram_entry.next_lu_id, sizeof(uint32_t)))
printk("Next_lu_id, ");
if (memcmp(&entry1->sram_entry.next_lu_off_reg, &entry2->sram_entry.next_lu_off_reg, sizeof(uint32_t)))
printk("Next_lu_off_reg, ");
if (memcmp(&entry1->sram_entry.pnc_queue, &entry2->sram_entry.pnc_queue, sizeof(uint32_t)))
printk("Pnc queue, ");
if (memcmp(&entry1->sram_entry.res_info_15_0_data, &entry2->sram_entry.res_info_15_0_data, sizeof(uint32_t)))
printk("Res_info_15_0, ");
if (memcmp(&entry1->sram_entry.res_info_15_0_mask, &entry2->sram_entry.res_info_15_0_mask, sizeof(uint32_t)))
printk("Res_info_15_0 mask, ");
if (memcmp(&entry1->sram_entry.res_info_23_16_data, &entry2->sram_entry.res_info_23_16_data, sizeof(uint32_t)))
printk("Res_info_23_16, ");
if (memcmp(&entry1->sram_entry.res_info_23_16_mask, &entry2->sram_entry.res_info_23_16_mask, sizeof(uint32_t)))
printk("Res_info_23_16 mask, ");
if (memcmp(&entry1->sram_entry.shift_updt_reg, &entry2->sram_entry.shift_updt_reg, sizeof(uint32_t)))
printk("Shift_updt_reg, ");
if (memcmp(&entry1->sram_entry.shift_updt_val, &entry2->sram_entry.shift_updt_val, sizeof(uint32_t)))
printk("Shift_updt_val, ");
printk("\n======================================================================================\n\n");
}
/*******************************************************************************
* tran_tcam_entry_to_pnc_all_t - translate tcam_entry structure to tpm_pnc_all_t
*
* INPUT:
* in_tcam: source struct tcam_entry
* rule_action: rule action of pnc rule
* api_section: pnc rule belong to
*
* OUTPUT:
* out_pnc: target tpm_pnc_all_t structure
*
* RETURN:None
*******************************************************************************/
static void tran_tcam_entry_to_pnc_all_t(tpm_pnc_all_t *out_pnc,
struct tcam_entry *in_tcam,
tpm_rule_action_t *rule_action,
tpm_api_sections_t api_section)
{
unsigned int lookup_mask;
int tcam_off;
/*check parameters*/
if (out_pnc == NULL || in_tcam == NULL || rule_action == NULL) {
printk(KERN_ERR "NULL pointer\n");
return;
}
if (api_section > TPM_CNM_MAIN_ACL || api_section < TPM_CPU_LOOPBACK_ACL) {
printk(KERN_ERR "api_section out of range\n");
return;
}
/*get tcam entry*/
tcam_sw_get_lookup(in_tcam, &(out_pnc->tcam_entry.lu_id), &lookup_mask);
out_pnc->tcam_entry.port_ids = (~(in_tcam->mask.u.word[PORT_WORD] >> PORT_OFFS)) & PORT_MASK;
tcam_sw_get_ainfo(in_tcam,
&(out_pnc->tcam_entry.add_info_data),
&(out_pnc->tcam_entry.add_info_mask));
/* Get tcam packet data */
for (tcam_off = 0; tcam_off < TPM_TCAM_PKT_WIDTH; tcam_off++) {
out_pnc->tcam_entry.pkt_data.pkt_byte[tcam_off] = in_tcam->data.u.byte[tcam_off];
out_pnc->tcam_entry.pkt_mask.pkt_byte[tcam_off] = in_tcam->mask.u.byte[tcam_off];
}
/*Get sram entry*/
out_pnc->sram_entry.flowid_val = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(FLOW_VALUE_OFFS)] >>
TPM_CHECK_MOD_32(FLOW_VALUE_OFFS)) & FLOW_VALUE_MASK;
out_pnc->sram_entry.flowid_updt_mask = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(FLOW_CTRL_OFFS)] >>
TPM_CHECK_MOD_32(FLOW_CTRL_OFFS)) & FLOW_CTRL_MASK;
out_pnc->sram_entry.res_info_15_0_data = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(RI_VALUE_OFFS)] >>
TPM_CHECK_MOD_32(RI_VALUE_OFFS)) & RI_VALUE_15_0_MASK;
out_pnc->sram_entry.res_info_23_16_data = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(RI_VALUE_OFFS)] >>
(TPM_CHECK_MOD_32(RI_VALUE_OFFS) + 16)) & RI_VALUE_23_16_MASK;
out_pnc->sram_entry.res_info_15_0_mask = in_tcam->sram.word[TPM_CHECK_DIV_BY_32(RI_MASK_OFFS)] &
RI_VALUE_15_0_MASK;
out_pnc->sram_entry.res_info_23_16_mask = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(RI_MASK_OFFS)] >> 16) &
RI_VALUE_23_16_MASK;
out_pnc->sram_entry.res_info_15_0_data = out_pnc->sram_entry.res_info_15_0_data &
out_pnc->sram_entry.res_info_15_0_mask;
out_pnc->sram_entry.res_info_23_16_data = out_pnc->sram_entry.res_info_23_16_data &
out_pnc->sram_entry.res_info_23_16_mask;
out_pnc->sram_entry.shift_updt_val = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(SHIFT_VAL_OFFS)] >>
TPM_CHECK_MOD_32(SHIFT_VAL_OFFS)) & SHIFT_VAL_MASK;
out_pnc->sram_entry.shift_updt_reg = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(SHIFT_IDX_OFFS)] >>
TPM_CHECK_MOD_32(SHIFT_IDX_OFFS)) & SHIFT_IDX_MASK;
/*update target queue, supposed that API DB is always right, here to avoid error*/
if (SET_TARGET_QUEUE(rule_action->pkt_act) ||
(api_section == TPM_IPV4_MC) ||
(api_section == TPM_IPV6_MC_ACL))
out_pnc->sram_entry.pnc_queue = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(RXQ_QUEUE_OFFS)] >>
TPM_CHECK_MOD_32(RXQ_QUEUE_OFFS)) & RXQ_MASK;
else
out_pnc->sram_entry.pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
out_pnc->sram_entry.next_lu_off_reg = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(NEXT_LU_SHIFT_OFFS)] >>
TPM_CHECK_MOD_32(NEXT_LU_SHIFT_OFFS)) & NEXT_LU_SHIFT_MASK;
out_pnc->sram_entry.lookup_done = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(LU_DONE_OFFS)] >>
TPM_CHECK_MOD_32(LU_DONE_OFFS)) & LU_DONE_MASK;
out_pnc->sram_entry.add_info_data = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(AI_VALUE_OFFS)] >>
TPM_CHECK_MOD_32(AI_VALUE_OFFS)) & AI_MASK;
out_pnc->sram_entry.add_info_mask = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(AI_MASK_OFFS)] >>
TPM_CHECK_MOD_32(AI_MASK_OFFS)) & AI_MASK;
out_pnc->sram_entry.next_lu_id = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(LU_ID_OFFS)] >>
TPM_CHECK_MOD_32(LU_ID_OFFS)) & LU_MASK;
return;
}
/*******************************************************************************
* tpm_check_update_sram - update sram according to some special condition
* - packet drop, flowid_update_mask
* - just to avoid meaningless pnc check error
* INPUT:
* rule_action
* OUTPUT:
* sram_entry
* RETURN:None
*******************************************************************************/
static void tpm_check_update_sram(tpm_sram_all_t *sram_entry, tpm_rule_action_t *rule_action)
{
uint32_t mask = 0;
uint32_t loop;
if (NULL == sram_entry || NULL == rule_action)
return;
/*update flow id*/
for (loop = 0; loop < 8; loop++) {
if ((1 << loop) & sram_entry->flowid_updt_mask)
mask |= (0xF << (4 * loop));
}
sram_entry->flowid_val = sram_entry->flowid_val & mask;
/*update pnc queue, if rule action is drop, set pnc queue to 0xFFFF*/
if (PKT_DROP(rule_action->pkt_act))
sram_entry->pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
}
int32_t tpm_check_main_chain_type(tpm_gmacs_enum_t gmac_port, tpm_pkt_mod_bm_t mod_bm, tpm_pkt_mod_int_bm_t int_mod_bm,
uint16_t jump_idx, tpm_main_chain_check_type_t *result)
{
tpm_chain_type_t main_chain_type, db_main_chain_type, hw_main_chain_type;
uint16_t main_chain_entry, main_idx;
int32_t ret;
uint8_t error_db, error_hw;
error_db = 0;
error_hw = 0;
/* Get main chain type from mod_bm */
main_chain_type = tpm_mod2_parse_chain_type(mod_bm, int_mod_bm);
/*Get main chain type from db*/
ret = tpm_mod2_main_chain_index_get(gmac_port, jump_idx, &main_chain_entry, TPM_CHECK_MAIN_CHAIN_IDX_DB);
if (ret)
return TPM_FAIL;
ret = tpm_db_mod2_get_chain_id_by_pmt_entry(gmac_port, main_chain_entry, &db_main_chain_type, &main_idx);
if (ret)
return TPM_FAIL;
if (main_chain_type != db_main_chain_type)
error_db++;
/*Get main chain type from HW*/
ret = tpm_mod2_main_chain_index_get(gmac_port, jump_idx, &main_chain_entry, TPM_CHECK_MAIN_CHAIN_IDX_HW);
if (ret)
return TPM_FAIL;
ret = tpm_db_mod2_get_chain_id_by_pmt_entry(gmac_port, main_chain_entry, &hw_main_chain_type, &main_idx);
if (ret)
return TPM_FAIL;
if (main_chain_type != hw_main_chain_type)
error_hw++;
if (error_db && error_hw)
*result = TPMCHECK_BOTH_CHAIN_TYPE_MISMATCH;
else if (error_db)
*result = TPMCHECK_DB_CHAIN_TYPE_MISMATCH;
else if (error_hw)
*result = TPMCHECK_HW_CHAIN_TYPE_MISMATCH;
else
*result = TPMCHECK_CHAIN_TYPE_OK;
return TPM_OK;
}
static void tpm_check_pmt_mismatch_show_header(void)
{
printk("======================================================================================\n");
printk(" Info_Src Index OpCode Operation Data Last IPv4 L4 \n");
printk(" update update \n");
printk("======================================================================================\n");
}
/*******************************************************************************
* tpm_pmt_check - check PMT entries
*
* INPUT:
* tpm_gmacs_enum_t gmac_port
* tpm_mod_pattern_data_t *pattern_data
* tpm_self_check_enable_t check_with, check with DB or HW
*
* OUTPUT:
* tpm_self_check_result_t *result, record check result
*
*RETURN:
*
*COMMENTS:
*
*******************************************************************************/
static int32_t tpm_pmt_check(tpm_gmacs_enum_t gmac_port, tpm_mod_pattern_data_t *pattern_data,
tpm_error_code_t *result, tpm_self_check_enable_t check_with)
{
uint32_t set_id, line_id;
tpm_pattern_entry_t *entry_p = NULL;
uint16_t pmt_entry;
MV_NETA_PMT pEntry;
tpm_mod2_entry_t pattern_jump, pattern_chain;
/*error flag*/
int8_t modification_data = 0;
int8_t mod_command = 0;
int8_t up_ipv4_checksum = 0;
int8_t up_tcp_udp_checksum = 0;
int8_t last = 0;
int8_t hw_error_count, sw_error_count;
if (gmac_port >= TPM_MAX_NUM_GMACS) {
printk("Invalid parameter: port %d\n", gmac_port);
return TPM_FAIL;
}
if (NULL == pattern_data) {
TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
return TPM_FAIL;
}
hw_error_count = 0;
sw_error_count = 0;
for (set_id = 0; set_id < TPM_MOD2_MAX_PATTERN_SETS; set_id++) {
if (pattern_data->pattern_set[set_id].is_valid) {
entry_p = &(pattern_data->pattern_set[set_id]);
if (set_id == 0)
pmt_entry = entry_p->index;
else
pmt_entry = tpm_db_mod2_convert_chain_to_pmt_entry(entry_p->chain_type, entry_p->index);
for (line_id = 0; line_id < TPM_MOD2_MAX_PATTERN_ENTRIES && line_id < entry_p->line_num;
line_id++) {
if (check_with == TPM_CHECK_WITH_HW) {
/*read HW PMT table*/
if (tpm_mod2_neta_pmt_get(gmac_port, pmt_entry + line_id, &pEntry)) {
TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to get hw jump data\n");
return TPM_FAIL;
}
/*compare HW PMT*/
if ((pEntry.word & MV_NETA_PMT_DATA_MASK) != entry_p->line[line_id].data)
modification_data = 1;
if (((pEntry.word >> MV_NETA_PMT_CMD_OFFS) & (MV_NETA_PMT_CMD_ALL_MASK >>
MV_NETA_PMT_CMD_OFFS)) != entry_p->line[line_id].opcode)
mod_command = 1;
if (((pEntry.word >> MV_NETA_PMT_IP4_CSUM_BIT) & (MV_NETA_PMT_IP4_CSUM_MASK >>
MV_NETA_PMT_IP4_CSUM_BIT)) != entry_p->line[line_id].updt_ipv4)
up_ipv4_checksum = 1;
if (((pEntry.word >> MV_NETA_PMT_L4_CSUM_BIT) & (MV_NETA_PMT_L4_CSUM_MASK >>
MV_NETA_PMT_L4_CSUM_BIT)) != entry_p->line[line_id].updt_tcp)
up_tcp_udp_checksum = 1;
if (((pEntry.word >> MV_NETA_PMT_LAST_BIT) & (MV_NETA_PMT_LAST_MASK >>
MV_NETA_PMT_LAST_BIT)) != entry_p->line[line_id].last)
last = 1;
/*show HW error info*/
if (modification_data || mod_command || up_ipv4_checksum ||
up_tcp_udp_checksum || last) {
hw_error_count++;
printk("\nPMT Mismatch: [set %d] area_type %d, chain_type %d, "
"chain_index %d ,line_num %d\r\n",
set_id, entry_p->area_type, entry_p->chain_type,
entry_p->index, entry_p->line_num);
tpm_check_pmt_mismatch_show_header();
printk(" %5s %03d 0x%2x %15s 0x%4.4x %1d "
"%1d %1d\n",
"Build",
line_id,
entry_p->line[line_id].opcode,
opCodeOperationStr[entry_p->line[line_id].opcode],
entry_p->line[line_id].data, entry_p->line[line_id].last,
entry_p->line[line_id].updt_ipv4,
entry_p->line[line_id].updt_tcp);
printk(" %5s %03d 0x%2x %15s 0x%4.4x %1d "
"%1d %1d\n",
"HWPMT",
line_id,
((pEntry.word >> MV_NETA_PMT_CMD_OFFS) &
(MV_NETA_PMT_CMD_ALL_MASK >> MV_NETA_PMT_CMD_OFFS)),
opCodeOperationStr[((pEntry.word >> MV_NETA_PMT_CMD_OFFS) &
(MV_NETA_PMT_CMD_ALL_MASK >> MV_NETA_PMT_CMD_OFFS))],
(pEntry.word & MV_NETA_PMT_DATA_MASK),
((pEntry.word >> MV_NETA_PMT_LAST_BIT) &
(MV_NETA_PMT_LAST_MASK >> MV_NETA_PMT_LAST_BIT)),
((pEntry.word >> MV_NETA_PMT_IP4_CSUM_BIT) &
(MV_NETA_PMT_IP4_CSUM_MASK >> MV_NETA_PMT_IP4_CSUM_BIT)),
((pEntry.word >> MV_NETA_PMT_L4_CSUM_BIT) &
(MV_NETA_PMT_L4_CSUM_MASK >> MV_NETA_PMT_L4_CSUM_BIT)));
}
/*clear error flags*/
modification_data = 0;
mod_command = 0;
up_ipv4_checksum = 0;
up_tcp_udp_checksum = 0;
last = 0;
} else if (check_with == TPM_CHECK_WITH_DB) {
/*read PMT db info*/
if (set_id == 0) {
if (tpm_mod2_db_jump_pattern_data_get(gmac_port, entry_p->index,
&pattern_jump)) {
TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Get Jump pattern failed\n");
return TPM_FAIL;
}
} else {
if (tpm_mod2_db_chain_pattern_data_get(gmac_port, entry_p->chain_type,
entry_p->index, line_id, &pattern_chain)) {
TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Get Chain pattern failed\n");
return TPM_FAIL;
}
}
/*compare to db*/
if (set_id == 0) {
if (pattern_jump.data != entry_p->line[line_id].data)
modification_data = 1;
if (pattern_jump.opcode != entry_p->line[line_id].opcode)
mod_command = 1;
if (pattern_jump.updt_ipv4 != entry_p->line[line_id].updt_ipv4)
up_ipv4_checksum = 1;
if (pattern_jump.updt_tcp != entry_p->line[line_id].updt_tcp)
up_tcp_udp_checksum = 1;
if (pattern_jump.last != entry_p->line[line_id].last)
last = 1;
} else {
if (pattern_chain.data != entry_p->line[line_id].data)
modification_data = 1;
if (pattern_chain.opcode != entry_p->line[line_id].opcode)
mod_command = 1;
if (pattern_chain.updt_ipv4 != entry_p->line[line_id].updt_ipv4)
up_ipv4_checksum = 1;
if (pattern_chain.updt_tcp != entry_p->line[line_id].updt_tcp)
up_tcp_udp_checksum = 1;
if (pattern_chain.last != entry_p->line[line_id].last)
last = 1;
}
/*show SW error info*/
if (modification_data || mod_command || up_ipv4_checksum ||
up_tcp_udp_checksum || last) {
sw_error_count++;
printk("\nPMT Mismatch: [set %d] area_type %d, chain_type %d, "
"chain_index %d ,line_num %d\r\n",
set_id, entry_p->area_type, entry_p->chain_type,
entry_p->index, entry_p->line_num);
tpm_check_pmt_mismatch_show_header();
printk(" %5s %03d 0x%2x %15s 0x%4.4x "
"%1d %1d %1d\n",
"Build",
line_id,
entry_p->line[line_id].opcode,
opCodeOperationStr[entry_p->line[line_id].opcode],
entry_p->line[line_id].data, entry_p->line[line_id].last,
entry_p->line[line_id].updt_ipv4,
entry_p->line[line_id].updt_tcp);
if (set_id == 0) {
printk(" %5s %03d 0x%2x %15s 0x%4.4x "
"%1d %1d %1d\n",
"DB",
line_id,
pattern_jump.opcode,
opCodeOperationStr[pattern_jump.opcode],
pattern_jump.data, pattern_jump.last,
pattern_jump.updt_ipv4, pattern_jump.updt_tcp);
} else {
printk(" %5s %03d 0x%2x %15s 0x%4.4x "
"%1d %1d %1d\n",
"DB",
line_id,
pattern_chain.opcode,
opCodeOperationStr[pattern_chain.opcode],
pattern_chain.data, pattern_chain.last,
pattern_chain.updt_ipv4, pattern_chain.updt_tcp);
}
}
/*clear error flags*/
modification_data = 0;
mod_command = 0;
up_ipv4_checksum = 0;
up_tcp_udp_checksum = 0;
last = 0;
}
}
}
}
/*record check result*/
if (hw_error_count)
*result = ERR_TPMCHECK_PMT_HW_MISMATCH;
else if (sw_error_count)
*result = ERR_TPMCHECK_PMT_DB_MISMATCH;
else
*result = TPM_RC_OK;
return TPM_OK;
}
int32_t tpm_check_param_check(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
{
if (pon_type < TPM_EPON || pon_type > TPM_P2P) {
TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "PON type is invalid\n");
return TPM_FAIL;
}
if (tpm_rule == NULL ||
mod_con == NULL ||
api_ent_mem_area == NULL ||
pnc_data == NULL ||
mod_entry == NULL ||
pkt_mod == NULL ||
pkt_mod_bm == NULL ||
int_mod_bm == NULL ||
trg_port == NULL ||
rule_action == NULL) {
TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Pointer invalid (NULL)\n");
return TPM_FAIL;
}
return TPM_OK;
}
/*******************************************************************************
* api_data2pnc_data_l2 - translate L2 APi data to PNC data
*
* INPUT:
* pon_type
* tpm_rule
* mod_con
* api_ent_mem_area
*
* OUTPUT:
* pnc_data
* mod_entry
* pkt_mod
* pkt_mod_bm
* int_mod_bm
* trg_port
* rule_action
*RETURN:
*
*COMMENTS:
*
*******************************************************************************/
int32_t api_data2pnc_data_l2(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
{
tpm_src_port_type_t src_port;
tpm_parse_fields_t parse_rule_bm;
tpm_parse_flags_t parse_flags_bm;
tpm_l2_acl_key_t l2_key;
tpm_dir_t dir = 0;
tpm_pkt_frwd_t pkt_frwd;
uint32_t rule_num;
int32_t tpm_ret = 0;
/*params check*/
tpm_ret = tpm_check_param_check(pon_type, tpm_rule, mod_con, api_ent_mem_area, pnc_data, mod_entry,
pkt_mod, pkt_mod_bm, int_mod_bm, trg_port, rule_action);
IF_ERROR(tpm_ret);
src_port = tpm_rule->l2_prim_key.src_port;
memcpy(&l2_key, &(tpm_rule->l2_prim_key.l2_key), sizeof(tpm_l2_acl_key_t));
parse_rule_bm = tpm_rule->l2_prim_key.parse_rule_bm;
parse_flags_bm = tpm_rule->l2_prim_key.parse_flags_bm;
memcpy(&pkt_frwd, &(tpm_rule->l2_prim_key.pkt_frwd), sizeof(tpm_pkt_frwd_t));
memcpy(rule_action, &(tpm_rule->l2_prim_key.rule_action), sizeof(tpm_rule_action_t));
*mod_entry = mod_con->mod_cmd_ind;
*trg_port = tpm_rule->l2_prim_key.pkt_frwd.trg_port;
memcpy(pkt_mod, &(tpm_rule->l2_prim_key.pkt_mod), sizeof(tpm_pkt_mod_t));
*pkt_mod_bm = tpm_rule->l2_prim_key.pkt_mod_bm;
*int_mod_bm = 0;
rule_num = api_ent_mem_area->rule_idx;
/* Get direction */
tpm_ret = tpm_proc_src_port_dir_map(src_port, &dir);
IF_ERROR(tpm_ret);
/*******************generate PnC Rule Start********************/
/*generate tcam */
tpm_ret = tpm_proc_l2_tcam_build(src_port,
dir,
rule_num,
&l2_key,
parse_rule_bm,
parse_flags_bm,
&(pnc_data->pncl_tcam));
IF_ERROR(tpm_ret);
/*generate sram*/
tpm_ret = tpm_proc_l2_sram_build(src_port,
dir,
rule_num,
pon_type,
&pkt_frwd,
rule_action,
mod_con->mod_cmd_ind,
&(pnc_data->pncl_sram),
&l2_key,
&(tpm_rule->l2_prim_key.pkt_mod),
tpm_rule->l2_prim_key.pkt_mod_bm);
IF_ERROR(tpm_ret);
return TPM_OK;
}
/*******************************************************************************
* api_data2pnc_data_l3 - translate L3 APi data to PNC data
*
* INPUT:
* pon_type
* tpm_rule
* mod_con
* api_ent_mem_area
*
* OUTPUT:
* pnc_data
* mod_entry
* pkt_mod
* pkt_mod_bm
* int_mod_bm
* rule_action
*RETURN:
*
*COMMENTS:
*
*******************************************************************************/
int32_t api_data2pnc_data_l3(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
{
tpm_src_port_type_t src_port;
tpm_parse_fields_t parse_rule_bm;
tpm_parse_flags_t parse_flags_bm;
tpm_l3_type_key_t l3_key;
tpm_dir_t dir = 0;
tpm_pkt_frwd_t pkt_frwd;
uint8_t l3_is_pppoe = TPM_FALSE;
uint32_t rule_num;
int32_t tpm_ret = 0;
/*params check*/
tpm_ret = tpm_check_param_check(pon_type, tpm_rule, mod_con, api_ent_mem_area, pnc_data, mod_entry,
pkt_mod, pkt_mod_bm, int_mod_bm, trg_port, rule_action);
IF_ERROR(tpm_ret);
src_port = tpm_rule->l3_type_key.src_port;
memcpy(&l3_key, &(tpm_rule->l3_type_key.l3_key), sizeof(tpm_l3_type_key_t));
parse_rule_bm = tpm_rule->l3_type_key.parse_rule_bm;
parse_flags_bm = tpm_rule->l3_type_key.parse_flags_bm;
memcpy(&pkt_frwd, &(tpm_rule->l3_type_key.pkt_frwd), sizeof(tpm_pkt_frwd_t));
memcpy(rule_action, &(tpm_rule->l3_type_key.rule_action), sizeof(tpm_rule_action_t));
*mod_entry = mod_con->mod_cmd_ind;
rule_num = api_ent_mem_area->rule_idx;
/* Get direction */
tpm_ret = tpm_proc_src_port_dir_map(src_port, &dir);
IF_ERROR(tpm_ret);
/*******************generate PnC Rule Start********************/
/*generate tcam */
tpm_ret = tpm_proc_l3_tcam_build(src_port,
dir,
rule_num,
&l3_key,
parse_rule_bm,
parse_flags_bm,
rule_action,
&(pnc_data->pncl_tcam));
IF_ERROR(tpm_ret);
/*generate sram*/
if (pnc_data->pncl_tcam.pkt_key.l3_key.ether_type_key == ETH_P_PPP_SES)
l3_is_pppoe = TPM_TRUE;
tpm_ret = tpm_proc_l3_sram_build(src_port,
dir,
rule_num,
l3_is_pppoe,
pon_type,
&pkt_frwd,
rule_action,
parse_flags_bm,
&(pnc_data->pncl_sram));
IF_ERROR(tpm_ret);
return TPM_OK;
}
/*******************************************************************************
* api_data2pnc_data_ipv4 - translate IPV4 ACL API data to PNC data
*
* INPUT:
* pon_type
* tpm_rule
* mod_con
* api_ent_mem_area
*
* OUTPUT:
* pnc_data
* mod_entry
* pkt_mod
* pkt_mod_bm
* int_mod_bm
* rule_action
*RETURN:
*
*COMMENTS:
*
*******************************************************************************/
int32_t api_data2pnc_data_ipv4(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
{
tpm_src_port_type_t src_port;
tpm_parse_fields_t parse_rule_bm;
tpm_parse_flags_t parse_flags_bm;
tpm_ipv4_acl_key_t ipv4_acl_key;
tpm_dir_t dir = 0;
tpm_pkt_frwd_t pkt_frwd;
uint32_t rule_num;
int32_t tpm_ret = 0;
/*params check*/
tpm_ret = tpm_check_param_check(pon_type, tpm_rule, mod_con, api_ent_mem_area, pnc_data, mod_entry,
pkt_mod, pkt_mod_bm, int_mod_bm, trg_port, rule_action);
IF_ERROR(tpm_ret);
src_port = tpm_rule->ipv4_key.src_port;
memcpy(&ipv4_acl_key, &(tpm_rule->ipv4_key.ipv4_key), sizeof(tpm_ipv4_acl_key_t));
parse_rule_bm = tpm_rule->ipv4_key.parse_rule_bm;
parse_flags_bm = tpm_rule->ipv4_key.parse_flags_bm;
memcpy(&pkt_frwd, &(tpm_rule->ipv4_key.pkt_frwd), sizeof(tpm_pkt_frwd_t));
memcpy(rule_action, &(tpm_rule->ipv4_key.rule_action), sizeof(tpm_rule_action_t));
*mod_entry = mod_con->mod_cmd_ind;
*trg_port = tpm_rule->ipv4_key.pkt_frwd.trg_port;
memcpy(pkt_mod, &(tpm_rule->ipv4_key.pkt_mod), sizeof(tpm_pkt_mod_t));
*pkt_mod_bm = tpm_rule->ipv4_key.pkt_mod_bm;
*int_mod_bm = 0;
rule_num = api_ent_mem_area->rule_idx;
/* Get direction */
tpm_ret = tpm_proc_src_port_dir_map(src_port, &dir);
IF_ERROR(tpm_ret);
/*******************generate PnC Rule Start********************/
/*generate tcam */
tpm_ret = tpm_proc_ipv4_tcam_build(src_port,
dir,
rule_num,
&ipv4_acl_key,
parse_rule_bm,
parse_flags_bm,
rule_action,
&(tpm_rule->ipv4_key.pkt_mod),
tpm_rule->ipv4_key.pkt_mod_bm,
&(pnc_data->pncl_tcam));
IF_ERROR(tpm_ret);
/*generate sram*/
tpm_ret = tpm_proc_ipv4_sram_build(src_port,
dir,
rule_num,
pon_type,
&ipv4_acl_key,
pnc_data->pncl_tcam.ipv4_parse_bm,
parse_flags_bm,
&pkt_frwd,
rule_action,
mod_con->mod_cmd_ind,
tpm_rule->ipv4_key.pkt_mod_bm,
&(tpm_rule->ipv4_key.pkt_mod),
&(pnc_data->pncl_sram));
IF_ERROR(tpm_ret);
/*update L4 checksum*/
if (parse_rule_bm & TPM_IPv4_PARSE_PROTO) {
if (ipv4_acl_key.ipv4_proto == IPPROTO_TCP)
*int_mod_bm = TPM_INT_L4_TCP;
else if (ipv4_acl_key.ipv4_proto == IPPROTO_UDP) {
*int_mod_bm = TPM_INT_L4_UDP;
/* Set internal_bm according to API Action */
if (rule_action->pkt_act & TPM_ACTION_UDP_CHKSUM_CALC)
*int_mod_bm = TPM_INT_L4_UDP | TPM_INT_UDP_CHECKSUM;
}
}
return TPM_OK;
}
/*******************************************************************************
* api_data2pnc_data_ipv4_mc - translate IPV4 MC API data to PNC data
*
* INPUT:
* pon_type
* tpm_rule
* mod_con
* api_ent_mem_area
*
* OUTPUT:
* pnc_data
* mod_entry
* pkt_mod
* pkt_mod_bm
* int_mod_bm
*
*RETURN:
*
*COMMENTS:
*
*******************************************************************************/
int32_t api_data2pnc_data_ipv4_mc(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
{
tpm_db_mc_stream_entry_t mc_stream_entry;
tpm_mc_filter_mode_t filter_mode;
uint8_t mc_stream_pppoe, ignore_ipv4_src, ipv4_src_add[4], ipv4_dst_add[4];
uint16_t mc_vid;
uint32_t stream_num, igmp_mode, dest_port_bm;
int32_t tpm_ret = 0;
/*params check*/
tpm_ret = tpm_check_param_check(pon_type, tpm_rule, mod_con, api_ent_mem_area, pnc_data, mod_entry,
pkt_mod, pkt_mod_bm, int_mod_bm, trg_port, rule_action);
IF_ERROR(tpm_ret);
filter_mode = tpm_db_get_mc_filter_mode();
stream_num = api_ent_mem_area->rule_num;
tpm_ret = tpm_db_get_mc_stream_entry(stream_num, &mc_stream_entry);
IF_ERROR(tpm_ret);
mc_stream_pppoe = mc_stream_entry.mc_stream_pppoe;
igmp_mode = mc_stream_entry.igmp_mode;
dest_port_bm = mc_stream_entry.dest_port_bm;
memcpy(ipv4_src_add, tpm_rule->ipv4_mc_key.ipv4_src_add, sizeof(ipv4_src_add));
memcpy(ipv4_dst_add, tpm_rule->ipv4_mc_key.ipv4_dest_add, sizeof(ipv4_dst_add));
rule_action->pkt_act = 0;
mc_vid = tpm_rule->ipv4_mc_key.vid;
ignore_ipv4_src = tpm_rule->ipv4_mc_key.ignore_ipv4_src;
*mod_entry = mod_con->mod_cmd_ind;
/*******************generate PnC Rule Start********************/
/*generate tcam entry*/
tpm_ret = tpm_proc_ipv4_mc_tcam_build(filter_mode,
stream_num,
mc_vid,
mc_stream_pppoe,
ipv4_src_add,
ipv4_dst_add,
ignore_ipv4_src,
&(pnc_data->pncl_tcam));
IF_ERROR(tpm_ret);
/* Build SRAM Entry */
tpm_ret = tpm_proc_ipv4_mc_sram_build(filter_mode,
igmp_mode,
dest_port_bm,
mod_con->mod_cmd_ind,
&(pnc_data->pncl_sram));
IF_ERROR(tpm_ret);
return TPM_OK;
}
/*******************************************************************************
* api_data2pnc_data_ipv6_gen - translate IPV6 GEN API data to PNC data
*
* INPUT:
* pon_type
* tpm_rule
* mod_con
* api_ent_mem_area
*
* OUTPUT:
* pnc_data
* mod_entry
* pkt_mod
* pkt_mod_bm
* int_mod_bm
* rule_action
*RETURN:
*
*COMMENTS:
*
*******************************************************************************/
int32_t api_data2pnc_data_ipv6_gen(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
{
tpm_src_port_type_t src_port;
tpm_parse_fields_t parse_rule_bm;
tpm_parse_flags_t parse_flags_bm;
tpm_dir_t dir = 0;
tpm_pkt_frwd_t pkt_frwd;
tpm_rule_ipv6_gen_key_t ipv6_gen_acl_key;
tpm_init_ipv6_5t_enable_t ipv6_5t_enable = TPM_IPV6_5T_DISABLED;
long long int_pkt_act = 0;
uint32_t subflow_bm, subflow_id, protocol = 0;
uint32_t rule_num;
int32_t tpm_ret = 0;
/*params check*/
tpm_ret = tpm_check_param_check(pon_type, tpm_rule, mod_con, api_ent_mem_area, pnc_data, mod_entry,
pkt_mod, pkt_mod_bm, int_mod_bm, trg_port, rule_action);
IF_ERROR(tpm_ret);
src_port = tpm_rule->ipv6_gen_key.src_port;
memcpy(&ipv6_gen_acl_key, &(tpm_rule->ipv6_gen_key), sizeof(tpm_rule_ipv6_gen_key_t));
parse_rule_bm = tpm_rule->ipv6_gen_key.parse_rule_bm;
parse_flags_bm = tpm_rule->ipv6_gen_key.parse_flags_bm;
memcpy(&pkt_frwd, &(tpm_rule->ipv6_gen_key.pkt_frwd), sizeof(tpm_pkt_frwd_t));
memcpy(rule_action, &(tpm_rule->ipv6_gen_key.rule_action), sizeof(tpm_rule_action_t));
*mod_entry = mod_con->mod_cmd_ind;
*trg_port = tpm_rule->ipv6_gen_key.pkt_frwd.trg_port;
memcpy(pkt_mod, &(tpm_rule->ipv6_gen_key.pkt_mod), sizeof(tpm_pkt_mod_t));
*pkt_mod_bm = tpm_rule->ipv6_gen_key.pkt_mod_bm;
*int_mod_bm = 0;
rule_num = api_ent_mem_area->rule_idx;
/*check ipv6_5t is enable or not*/
tpm_ret = tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
IF_ERROR(tpm_ret);
/* Get direction */
tpm_ret = tpm_proc_src_port_dir_map(src_port, &dir);
IF_ERROR(tpm_ret);
/*******************generate PnC Rule Start********************/
if (ipv6_5t_enable == TPM_IPV6_5T_DISABLED) {
/*generate tcam */
tpm_ret = tpm_proc_ipv6_gen_tcam_build(src_port,
dir,
rule_num,
&ipv6_gen_acl_key.ipv6_gen_key,
parse_rule_bm,
parse_flags_bm,
pkt_mod,
*pkt_mod_bm,
&(pnc_data->pncl_tcam));
IF_ERROR(tpm_ret);
/*generate sram*/
tpm_ret = tpm_proc_ipv6_gen_sram_build(src_port,
dir,
rule_num,
pon_type,
&pkt_frwd,
rule_action,
mod_con->mod_cmd_ind,
&(pnc_data->pncl_sram));
IF_ERROR(tpm_ret);
} else {
/*********** Get Subflow Info **********/
subflow_bm = parse_rule_bm & TPM_DB_IPV6_GEN_SUBFLOW_PARSE_BM_MASK;
if ((parse_flags_bm & TPM_PARSE_FLAG_L4P_MASK) != 0) {
if ((parse_flags_bm & TPM_PARSE_FLAG_L4_TCP) != 0)
protocol = IPPROTO_TCP;
else
protocol = IPPROTO_UDP;
subflow_bm |= TPM_IPv6_PARSE_NH;
}
subflow_id = TPM_DB_INVALID_IPV6_FLOW_ID;
if (subflow_bm != 0 && rule_action->next_phase != STAGE_DONE) {
int_pkt_act |= TPM_ACTION_SET_IPV6_SUBFLOW;
subflow_id = tpm_db_find_matched_ipv6_gen_subflow(dir,
subflow_bm,
protocol,
&ipv6_gen_acl_key.l4_key,
&ipv6_gen_acl_key.ipv6_gen_key);
if (subflow_id == TPM_DB_INVALID_IPV6_FLOW_ID) {
printk("Subflow_id get Failed\n");
return TPM_FAIL;
}
} else {
int_pkt_act |= TPM_ACTION_UNSET_IPV6_SUBFLOW;
}
/*generate tcam */
tpm_ret = tpm_proc_ipv6_gen_5t_tcam_build(dir,
rule_num,
&ipv6_gen_acl_key.l4_key,
&ipv6_gen_acl_key.ipv6_gen_key,
parse_rule_bm,
parse_flags_bm,
rule_action,
pkt_mod,
*pkt_mod_bm,
&(pnc_data->pncl_tcam));
IF_ERROR(tpm_ret);
/*generate sram*/
tpm_ret = tpm_proc_ipv6_gen_5t_sram_build(dir,
rule_num,
pon_type,
subflow_id,
&pkt_frwd,
rule_action,
int_pkt_act,
pkt_mod,
mod_con->mod_cmd_ind,
&(pnc_data->pncl_sram));
IF_ERROR(tpm_ret);
}
return TPM_OK;
}
/*******************************************************************************
* api_data2pnc_data_ipv6_dip - translate IPV6 DIP API data to PNC data
*
* INPUT:
* pon_type
* tpm_rule
* mod_con
* api_ent_mem_area
*
* OUTPUT:
* pnc_data
* mod_entry
* pkt_mod
* pkt_mod_bm
* int_mod_bm
* rule_action
*RETURN:
*
*COMMENTS:
*
*******************************************************************************/
int32_t api_data2pnc_data_ipv6_dip(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
{
tpm_src_port_type_t src_port;
tpm_parse_fields_t parse_rule_bm;
tpm_parse_flags_t parse_flags_bm;
tpm_dir_t dir = 0;
tpm_pkt_frwd_t pkt_frwd;
tpm_rule_ipv6_gen_key_t ipv6_gen_acl_key;
tpm_rule_ipv6_dip_key_t ipv6_dip_key;
tpm_init_ipv6_5t_enable_t ipv6_5t_enable = TPM_IPV6_5T_DISABLED;
long long int_pkt_act = 0;
uint32_t rule_num;
int32_t tpm_ret = 0;
/*params check*/
tpm_ret = tpm_check_param_check(pon_type, tpm_rule, mod_con, api_ent_mem_area, pnc_data, mod_entry,
pkt_mod, pkt_mod_bm, int_mod_bm, trg_port, rule_action);
IF_ERROR(tpm_ret);
src_port = tpm_rule->ipv6_dip_key.src_port;
memcpy(&ipv6_dip_key, &(tpm_rule->ipv6_dip_key), sizeof(tpm_rule_ipv6_dip_key_t));
parse_rule_bm = tpm_rule->ipv6_dip_key.parse_rule_bm;
parse_flags_bm = tpm_rule->ipv6_dip_key.parse_flags_bm;
memcpy(&pkt_frwd, &(tpm_rule->ipv6_dip_key.pkt_frwd), sizeof(tpm_pkt_frwd_t));
memcpy(rule_action, &(tpm_rule->ipv6_dip_key.rule_action), sizeof(tpm_rule_action_t));
*mod_entry = mod_con->mod_cmd_ind;
*trg_port = tpm_rule->ipv6_dip_key.pkt_frwd.trg_port;
memcpy(pkt_mod, &(tpm_rule->ipv6_dip_key.pkt_mod), sizeof(tpm_pkt_mod_t));
*pkt_mod_bm = tpm_rule->ipv6_dip_key.pkt_mod_bm;
*int_mod_bm = 0;
rule_num = api_ent_mem_area->rule_idx;
/*check ipv6_5t is enable or not*/
tpm_ret = tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
IF_ERROR(tpm_ret);
/* Get direction */
tpm_ret = tpm_proc_src_port_dir_map(src_port, &dir);
IF_ERROR(tpm_ret);
/*******************generate PnC Rule Start********************/
if (ipv6_5t_enable == TPM_IPV6_5T_DISABLED) {
/*generate tcam */
tpm_ret = tpm_proc_ipv6_dip_tcam_build(src_port,
dir,
rule_num,
&ipv6_dip_key.ipv6_dipkey,
parse_rule_bm,
parse_flags_bm,
pkt_mod,
*pkt_mod_bm,
&(pnc_data->pncl_tcam));
IF_ERROR(tpm_ret);
/*generate sram*/
tpm_ret = tpm_proc_ipv6_dip_sram_build(src_port,
dir,
rule_num,
pon_type,
&pkt_frwd,
rule_action,
mod_con->mod_cmd_ind,
&(pnc_data->pncl_sram));
IF_ERROR(tpm_ret);
} else {
int_pkt_act |= TPM_ACTION_UNSET_IPV6_SUBFLOW;
/*generate tcam */
memcpy(&ipv6_gen_acl_key, &(tpm_rule->ipv6_gen_key), sizeof(tpm_rule_ipv6_gen_key_t));
tpm_ret = tpm_proc_ipv6_dip_5t_tcam_build(dir,
rule_num,
&ipv6_dip_key.l4_key,
&ipv6_gen_acl_key.ipv6_gen_key,
&ipv6_dip_key.ipv6_dipkey,
parse_rule_bm,
parse_flags_bm,
rule_action,
pkt_mod,
*pkt_mod_bm,
&(pnc_data->pncl_tcam));
IF_ERROR(tpm_ret);
/*generate sram*/
tpm_ret = tpm_proc_ipv6_dip_5t_sram_build(dir,
rule_num,
pon_type,
&pkt_frwd,
rule_action,
int_pkt_act,
pkt_mod,
mod_con->mod_cmd_ind,
&(pnc_data->pncl_sram));
IF_ERROR(tpm_ret);
}
return TPM_OK;
}
/*******************************************************************************
* api_data2pnc_data_ipv6_mc - translate IPV6 MC API data to PNC data
*
* INPUT:
* pon_type
* tpm_rule
* mod_con
* api_ent_mem_area
*
* OUTPUT:
* pnc_data
* mod_entry
* pkt_mod
* pkt_mod_bm
* int_mod_bm
*
*RETURN:
*
*COMMENTS:
*
*******************************************************************************/
int32_t api_data2pnc_data_ipv6_mc(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
{
tpm_mc_filter_mode_t filter_mode;
uint8_t mc_stream_pppoe;
uint16_t mc_vid;
uint32_t stream_num, igmp_mode, dest_port_bm;
tpm_db_ipv6_mc_stream_entry_t ipv6_mc_stream_entry;
uint8_t ipv6_dst_add[16];
int32_t tpm_ret = 0;
uint8_t sip_index = 0;
/*params check*/
tpm_ret = tpm_check_param_check(pon_type, tpm_rule, mod_con, api_ent_mem_area, pnc_data, mod_entry,
pkt_mod, pkt_mod_bm, int_mod_bm, trg_port, rule_action);
IF_ERROR(tpm_ret);
filter_mode = tpm_db_get_mc_filter_mode();
stream_num = api_ent_mem_area->rule_num;
tpm_ret = tpm_db_get_ipv6_mc_stream_entry(stream_num, &ipv6_mc_stream_entry);
IF_ERROR(tpm_ret);
mc_stream_pppoe = ipv6_mc_stream_entry.mc_stream_pppoe;
igmp_mode = ipv6_mc_stream_entry.igmp_mode;
dest_port_bm = ipv6_mc_stream_entry.dest_port_bm;
memcpy(ipv6_dst_add, tpm_rule->ipv6_mc_key.ipv6_dest_add, sizeof(ipv6_dst_add));
rule_action->pkt_act = 0;
mc_vid = tpm_rule->ipv6_mc_key.vid;
*mod_entry = mod_con->mod_cmd_ind;
/* get sip_index */
if (0 == ipv6_mc_stream_entry.ignore_src_addr) {
/* get index of this IPv6 MC SIP */
sip_index = tpm_db_ipv6_mc_sip_index_get(ipv6_mc_stream_entry.src_addr);
if (0 == sip_index) {
/* SIP is not in DB, error */
TPM_OS_ERROR(TPM_TPM_LOG_MOD, "get index of IPv6 MC SIP failed!\n");
return(ERR_IPV6_MC_SRC_IP_INVALID);
}
}
/*generate tcam entry*/
tpm_ret = tpm_proc_ipv6_mc_tcam_build(filter_mode,
stream_num,
mc_vid,
mc_stream_pppoe,
ipv6_dst_add,
sip_index,
ipv6_mc_stream_entry.ignore_src_addr,
&(pnc_data->pncl_tcam));
IF_ERROR(tpm_ret);
/*generate sram*/
tpm_ret = tpm_proc_ipv6_mc_sram_build(filter_mode,
igmp_mode,
dest_port_bm,
mod_con->mod_cmd_ind,
&(pnc_data->pncl_sram));
IF_ERROR(tpm_ret);
return TPM_OK;
}
/*******************************************************************************
* api_data2pnc_data_ipv6_nh - translate IPV6 NH API data to PNC data
*
* INPUT:
* pon_type
* tpm_rule
* mod_con
* api_ent_mem_area
*
* OUTPUT:
* pnc_data
* mod_entry
* pkt_mod
* pkt_mod_bm
* int_mod_bm
* rule_action
*RETURN:
*
*COMMENTS:
*
*******************************************************************************/
int32_t api_data2pnc_data_ipv6_nh(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
{
tpm_parse_fields_t parse_rule_bm;
tpm_parse_flags_t parse_flags_bm;
tpm_pkt_frwd_t pkt_frwd;
tpm_rule_ipv6_nh_key_t ipv6_nh_key;
tpm_nh_iter_t nh_iter;
uint32_t rule_num;
uint32_t nh;
int32_t tpm_ret = 0;
/*params check*/
tpm_ret = tpm_check_param_check(pon_type, tpm_rule, mod_con, api_ent_mem_area, pnc_data, mod_entry,
pkt_mod, pkt_mod_bm, int_mod_bm, trg_port, rule_action);
IF_ERROR(tpm_ret);
memcpy(&ipv6_nh_key, &(tpm_rule->ipv6_nh_key), sizeof(tpm_rule_ipv6_nh_key_t));
parse_rule_bm = ipv6_nh_key.parse_rule_bm;
parse_flags_bm = ipv6_nh_key.parse_flags_bm;
nh = ipv6_nh_key.nh;
nh_iter = ipv6_nh_key.nh_iter;
memcpy(&pkt_frwd, &(ipv6_nh_key.pkt_frwd), sizeof(tpm_pkt_frwd_t));
memcpy(rule_action, &(ipv6_nh_key.rule_action), sizeof(tpm_rule_action_t));
*mod_entry = mod_con->mod_cmd_ind;
rule_num = api_ent_mem_area->rule_idx;
/*******************generate PnC Rule Start********************/
/*generate tcam */
tpm_ret = tpm_proc_ipv6_nh_tcam_build(rule_num,
nh_iter,
nh,
parse_flags_bm,
rule_action,
&(pnc_data->pncl_tcam));
IF_ERROR(tpm_ret);
/*generate sram*/
tpm_ret = tpm_proc_ipv6_nh_sram_build(rule_num,
nh_iter,
nh,
pon_type,
&pkt_frwd,
rule_action,
&(pnc_data->pncl_sram));
IF_ERROR(tpm_ret);
return TPM_OK;
}
/*******************************************************************************
* api_data2pnc_data_ipv6_l4 - translate IPV6 L4 API data to PNC data
*
* INPUT:
* pon_type
* tpm_rule
* mod_con
* api_ent_mem_area
*
* OUTPUT:
* pnc_data
* mod_entry
* pkt_mod
* pkt_mod_bm
* int_mod_bm
* rule_action
*RETURN:
*
*COMMENTS:
*
*******************************************************************************/
int32_t api_data2pnc_data_ipv6_l4(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
{
tpm_src_port_type_t src_port;
tpm_parse_fields_t parse_rule_bm;
tpm_parse_flags_t parse_flags_bm;
tpm_dir_t dir = 0;
tpm_pkt_frwd_t pkt_frwd;
tpm_rule_ipv6_l4_key_t ipv6_l4_key;
tpm_init_ipv6_5t_enable_t ipv6_5t_enable = TPM_IPV6_5T_DISABLED;
long long int_pkt_act = 0;
uint32_t subflow_bm, subflow_id, protocol = 0;
uint32_t rule_num;
int32_t tpm_ret = 0;
/*params check*/
tpm_ret = tpm_check_param_check(pon_type, tpm_rule, mod_con, api_ent_mem_area, pnc_data, mod_entry,
pkt_mod, pkt_mod_bm, int_mod_bm, trg_port, rule_action);
IF_ERROR(tpm_ret);
src_port = tpm_rule->ipv6_l4_key.src_port;
memcpy(&ipv6_l4_key, &(tpm_rule->ipv6_l4_key), sizeof(tpm_rule_ipv6_l4_key_t));
parse_rule_bm = tpm_rule->ipv6_l4_key.parse_rule_bm;
parse_flags_bm = tpm_rule->ipv6_l4_key.parse_flags_bm;
memcpy(&pkt_frwd, &(tpm_rule->ipv6_l4_key.pkt_frwd), sizeof(tpm_pkt_frwd_t));
memcpy(rule_action, &(tpm_rule->ipv6_l4_key.rule_action), sizeof(tpm_rule_action_t));
*mod_entry = mod_con->mod_cmd_ind;
*trg_port = tpm_rule->ipv6_l4_key.pkt_frwd.trg_port;
memcpy(pkt_mod, &(tpm_rule->ipv6_l4_key.pkt_mod), sizeof(tpm_pkt_mod_t));
*pkt_mod_bm = tpm_rule->ipv6_l4_key.pkt_mod_bm;
*int_mod_bm = 0;
rule_num = api_ent_mem_area->rule_idx;
/*check ipv6_5t is enable or not*/
tpm_ret = tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
IF_ERROR(tpm_ret);
/* Get direction */
tpm_ret = tpm_proc_src_port_dir_map(src_port, &dir);
IF_ERROR(tpm_ret);
if (ipv6_5t_enable == TPM_IPV6_5T_DISABLED) {
/*generate tcam */
tpm_ret = tpm_proc_ipv6_l4ports_tcam_build(src_port,
dir,
rule_num,
&ipv6_l4_key.l4_key,
parse_rule_bm,
parse_flags_bm,
rule_action,
pkt_mod,
*pkt_mod_bm,
&(pnc_data->pncl_tcam));
IF_ERROR(tpm_ret);
/*generate sram*/
tpm_ret = tpm_proc_ipv6_l4ports_sram_build(src_port,
dir,
rule_num,
pon_type,
&pkt_frwd,
rule_action,
mod_con->mod_cmd_ind,
&(pnc_data->pncl_sram));
IF_ERROR(tpm_ret);
} else {
/*********** Get Subflow Info **********/
subflow_bm = parse_rule_bm & TPM_DB_IPV6_L4_SUBFLOW_PARSE_BM_MASK;
if ((parse_flags_bm & TPM_PARSE_FLAG_L4P_MASK) != 0) {
if ((parse_flags_bm & TPM_PARSE_FLAG_L4_TCP) != 0)
protocol = IPPROTO_TCP;
else
protocol = IPPROTO_UDP;
subflow_bm |= TPM_IPv6_PARSE_NH;
}
subflow_id = TPM_DB_INVALID_IPV6_FLOW_ID;
if (subflow_bm != 0 && rule_action->next_phase != STAGE_DONE) {
int_pkt_act |= TPM_ACTION_SET_IPV6_SUBFLOW;
subflow_id = tpm_db_find_matched_ipv6_l4_subflow(dir,
subflow_bm,
protocol,
&ipv6_l4_key.l4_key);
if (subflow_id == TPM_DB_INVALID_IPV6_FLOW_ID) {
printk("Subflow_id get Failed\n");
return TPM_FAIL;
}
} else {
int_pkt_act |= TPM_ACTION_UNSET_IPV6_SUBFLOW;
}
/*generate tcam */
tpm_ret = tpm_proc_ipv6_l4_ports_5t_tcam_build(dir,
rule_num,
&ipv6_l4_key.l4_key,
parse_rule_bm,
parse_flags_bm,
rule_action,
pkt_mod,
*pkt_mod_bm,
&(pnc_data->pncl_tcam));
IF_ERROR(tpm_ret);
tpm_ret = tpm_proc_ipv6_l4_ports_5t_sram_build(dir,
rule_num,
pon_type,
subflow_id,
&pkt_frwd,
rule_action,
int_pkt_act,
pkt_mod,
mod_con->mod_cmd_ind,
&(pnc_data->pncl_sram));
IF_ERROR(tpm_ret);
}
return TPM_OK;
}
/*******************************************************************************
* api_data2pnc_data_ipv4_cnm - translate IPV4 CnM API data to PNC data
*
* INPUT:
* pon_type
* tpm_rule
* mod_con
* api_ent_mem_area
*
* OUTPUT:
* pnc_data
* mod_entry
* pkt_mod
* pkt_mod_bm
* int_mod_bm
* rule_action
*RETURN:
*
*COMMENTS:
*
*******************************************************************************/
int32_t api_data2pnc_data_ipv4_cnm(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
{
tpm_src_port_type_t src_port;
tpm_parse_fields_t l2_parse_rule_bm;
tpm_parse_fields_t ipv4_parse_rule_bm;
tpm_pkt_frwd_t pkt_frwd;
tpm_l2_acl_key_t l2_key;
tpm_ipv4_acl_key_t ipv4_key;
tpm_pkt_action_t pkt_act;
tpm_db_ctc_cm_rule_entry_t cnm_rule;
uint32_t jump_idx = 0;
uint32_t precedence = 0;
uint32_t rule_num, pbits;
uint32_t ipv4_pre_key_idx = TPM_CNM_INVALID_IPV4_PRE_FILTER_KEY_ID;
int32_t tpm_ret = 0;
/*params check*/
tpm_ret = tpm_check_param_check(pon_type, tpm_rule, mod_con, api_ent_mem_area, pnc_data, mod_entry,
pkt_mod, pkt_mod_bm, int_mod_bm, trg_port, rule_action);
IF_ERROR(tpm_ret);
/*get params from API db*/
src_port = tpm_rule->cnm_key.src_port;
ipv4_parse_rule_bm = tpm_rule->cnm_key.ipv4_parse_rule_bm;
pkt_act = tpm_rule->cnm_key.pkt_act;
pbits = tpm_rule->cnm_key.pbits;
l2_parse_rule_bm = tpm_rule->cnm_key.l2_parse_rule_bm;
memcpy(&l2_key, &(tpm_rule->cnm_key.l2_key), sizeof(tpm_l2_acl_key_t));
memcpy(&ipv4_key, &(tpm_rule->cnm_key.ipv4_key), sizeof(tpm_ipv4_acl_key_t));
memcpy(&pkt_frwd, &(tpm_rule->cnm_key.pkt_frwd), sizeof(tpm_pkt_frwd_t));
memcpy(&rule_action->pkt_act, &(tpm_rule->cnm_key.pkt_act), sizeof(tpm_pkt_action_t));
*mod_entry = mod_con->mod_cmd_ind;
*trg_port = tpm_rule->cnm_key.pkt_frwd.trg_port;
*pkt_mod_bm = 0;
*int_mod_bm = 0;
rule_num = api_ent_mem_area->rule_num;
/*check whether CnM_MAIN_L2 or CnM_MAIN_IPv4*/
/*get rule precedence*/
tpm_ret = tpm_proc_calc_cnm_precedence(src_port, rule_num, &precedence);
IF_ERROR(tpm_ret);
/*get cnm rule*/
tpm_ret = tpm_db_ctc_cm_rule_get(src_port, precedence, &cnm_rule);
IF_ERROR(tpm_ret);
/* Get split modification update */
if (SET_MOD(pkt_act)) {
if (tpm_db_split_mod_get_enable() == TPM_SPLIT_MOD_ENABLED) {
/* get mod index from p-bit value */
tpm_ret = tpm_db_split_mod_get_index_by_p_bits(pbits, &jump_idx);
IF_ERROR(tpm_ret);
/* skip first PMT for p-bit AS-IS */
jump_idx++;
} else {
printk("split mod is not active\n");
return TPM_FAIL;
}
}
/*check l2_parse_rule_bm*/
if (cnm_rule.l2_parse_rule_bm) {
/*is CnM L2*/
/*get ipv4 pre key index for comb rule if it is*/
tpm_ret = tpm_db_find_ipv4_pre_filter_key(src_port,
cnm_rule.ipv4_parse_rule_bm,
&cnm_rule.ipv4_key,
&ipv4_pre_key_idx);
/*rebuild tcam*/
tpm_ret = tpm_proc_cnm_l2_tcam_build(src_port,
l2_parse_rule_bm,
&l2_key,
ipv4_pre_key_idx,
&pnc_data->pncl_tcam);
IF_ERROR(tpm_ret);
/*rebuild sram*/
tpm_ret = tpm_proc_cnm_l2_sram_build(precedence,
&pkt_frwd,
pkt_act,
jump_idx,
&pnc_data->pncl_sram);
IF_ERROR(tpm_ret);
} else if ((cnm_rule.ipv4_parse_rule_bm) && (!cnm_rule.l2_parse_rule_bm)) {
/*is CnM IPV4*/
/*rebuild tcam*/
tpm_ret = tpm_proc_cnm_ipv4_tcam_build(src_port,
precedence,
ipv4_parse_rule_bm,
&ipv4_key,
&pnc_data->pncl_tcam);
IF_ERROR(tpm_ret);
/*rebuild sram*/
tpm_ret = tpm_proc_cnm_ipv4_sram_build(&pkt_frwd,
pkt_act,
jump_idx,
&pnc_data->pncl_sram);
IF_ERROR(tpm_ret);
} else {
/*error*/
printk("Invalid CnM parse rule bm!\n");
tpm_ret = TPM_FAIL;
IF_ERROR(tpm_ret);
}
return TPM_OK;
}
/*pnc rebuild functions array*/
static tpm_check_rebuild_pnc_t tpm_check_rebuild_pnc_array[TPM_MAX_NUM_API_SECTIONS] = {
tpm_check_param_check,
api_data2pnc_data_l2,
api_data2pnc_data_l3,
api_data2pnc_data_ipv4,
api_data2pnc_data_ipv4_mc,
api_data2pnc_data_ipv6_gen,
api_data2pnc_data_ipv6_dip,
api_data2pnc_data_ipv6_mc,
api_data2pnc_data_ipv6_nh,
api_data2pnc_data_ipv6_l4,
api_data2pnc_data_ipv4_cnm};
/*******************************************************************************
* tpm_pmt_rebuild_and_check()
*
* DESCRIPTION: The API is to rebuild mod pattern data and check it with HW PMT and DB.
*
* INPUTS: api_type - the rule to check belong to
* rule_index - the rule index in rule's API range
* trg_port - targe port
* pkt_mod_bm - set of flags described which fields in the packet
* to be changed
* int_mod_bm - set of internal flags
* mod_data - modification entry data
* mod_entry - start entry number which has been set for this
* modification <j>
*
* OUTPUTS:
* pmt_hw_error_count - check result for HW
* pmt_sw_error_count - check result for SW
*
* RETURNS:
* TPM_OK or TPM_FAIL
*
* COMMENTS:
* None
*
*******************************************************************************/
int32_t tpm_pmt_rebuild_and_check(tpm_api_type_t api_type,
uint32_t rule_index,
tpm_trg_port_type_t trg_port,
tpm_pkt_mod_bm_t pkt_mod_bm,
tpm_pkt_mod_int_bm_t int_mod_bm,
tpm_pkt_mod_t *pkt_mod,
uint32_t *mod_entry,
uint32_t *pmt_hw_error_count,
uint32_t *pmt_sw_error_count)
{
tpm_gmacs_enum_t trg_gmac;
tpm_mod_pattern_data_t pattern_data;
tpm_main_chain_check_type_t main_chain_check;
tpm_error_code_t pmt_check_result;
int32_t tpm_ret = 0;
tpm_ret = tpm_proc_trg_port_gmac_map(trg_port, &trg_gmac);
IF_ERROR(tpm_ret);
/*check main chain type*/
if (tpm_check_main_chain_type(trg_gmac, pkt_mod_bm, int_mod_bm, *mod_entry,
&main_chain_check)) {
printk("(Warn) main chain type check failed, API: %s, PnC index %d\n",
tpm_db_api_type_str[api_type], rule_index);
} else if (main_chain_check) {
printk("main chain type mismatch, API: %s, PnC index %d\n",
tpm_db_api_type_str[api_type], rule_index);
}
/*clear structure*/
memset(&pattern_data, 0, sizeof(tpm_mod_pattern_data_t));
/*build internal mod pattern data*/
tpm_ret = tpm_mod2_fill_in_pattern(trg_gmac,
pkt_mod_bm,
int_mod_bm,
pkt_mod,
mod_entry,
&pattern_data,
TPM_CHECK_MAIN_CHAIN_IDX_DB);
IF_ERROR(tpm_ret);
/*check with DB*/
if (tpm_pmt_check(trg_gmac, &pattern_data, &pmt_check_result,
TPM_CHECK_WITH_DB)) {
printk("SW PMT check error, API type: %s, PnC rule index %d\n",
tpm_db_api_type_str[api_type], rule_index);
} else if (pmt_check_result) {
*pmt_sw_error_count = *pmt_sw_error_count + 1;
printk("SW PMT mismatch, API type: %s, PnC rule index %d\n",
tpm_db_api_type_str[api_type], rule_index);
}
/*clear structure*/
memset(&pattern_data, 0, sizeof(tpm_mod_pattern_data_t));
/*build internal mod pattern data*/
tpm_ret = tpm_mod2_fill_in_pattern(trg_gmac,
pkt_mod_bm,
int_mod_bm,
pkt_mod,
mod_entry,
&pattern_data,
TPM_CHECK_MAIN_CHAIN_IDX_HW);
IF_ERROR(tpm_ret);
/*check with HW*/
if (tpm_pmt_check(trg_gmac, &pattern_data, &pmt_check_result,
TPM_CHECK_WITH_HW)) {
printk("HW PMT check error, API type: %s, PnC rule index %d\n",
tpm_db_api_type_str[api_type], rule_index);
} else if (pmt_check_result) {
*pmt_hw_error_count = *pmt_hw_error_count + 1;
printk("HW PMT mismatch, API type: %s, PnC rule index %d\n",
tpm_db_api_type_str[api_type], rule_index);
}
return TPM_OK;
}
/*******************************************************************************
* tpm_self_check - Check existed TPM rules and PMT table
*
* INPUT:
* owner_id
* check_level, 0--only check, 1--if there's error in HW table,
* it will try to correct it, done later
*
* OUTPUT:
* None
*
* RETURN:
* On success, the function returns TPM_RC_OK. On error different types are returned
* according to the case - see tpm_error_code_t.
*
* COMMENTS:
* It is APIs caller responsibility to maintain the correct number of each rule.
*******************************************************************************/
tpm_error_code_t tpm_self_check(uint32_t owner_id, tpm_self_check_level_enum_t check_level)
{
tpm_api_type_t api_type;
tpm_db_api_entry_t api_ent_mem_area;
tpm_pncl_pnc_full_t pnc_data;
tpm_pnc_all_t pnc_out;
tpm_rule_entry_t tpm_rule;
tpm_api_sections_t api_section;
tpm_db_mod_conn_t mod_con;
tpm_db_pnc_conn_t pnc_con;
tpm_pkt_mod_int_bm_t int_mod_bm = 0;
tpm_pkt_mod_bm_t pkt_mod_bm = 0;
tpm_rule_action_t rule_action;
tpm_db_pon_type_t pon_type = 0;
struct tcam_entry hw_te;
tpm_pnc_all_t read_pnc;
tpm_pnc_all_t shadow_pnc;
tpm_trg_port_type_t trg_port = 0;
tpm_pkt_mod_t pkt_mod;
tpm_vlan_key_t *vlan_out = NULL;
tpm_db_ctc_cm_enable_t ctc_cm_enable = TPM_CTC_CM_DISABLED;
uint8_t p_bits_tpm;
uint32_t loop;
uint32_t rule_num, rule_index, bi_dir;
int32_t apisec_last_valid_index;
uint32_t mod_entry = 0;
uint32_t valid_entry_num = 0;
uint32_t shadow_ent_valid;
uint32_t hw_jump_idx, shadow_jump_idx;
uint32_t p_bits_nums;
/*error statisc*/
uint32_t pnc_hw_error_count = 0;
uint32_t pnc_sw_error_count = 0;
uint32_t pmt_hw_error_count = 0;
uint32_t pmt_sw_error_count = 0;
uint32_t unnormal_end_count = 0;
uint32_t section_valid_entry_count = 0;/*the count of api section with valid entry*/
int32_t tpm_ret = 0;
/* Get pon_type */
if (tpm_db_pon_type_get(&pon_type))
return ERR_GENERAL;
/* get ctc cm enable status */
if (tpm_db_ctc_cm_enable_get(&ctc_cm_enable))
return ERR_GENERAL;
for (api_type = TPM_API_L2_PRIM; api_type <= TPM_API_CNM; api_type++) {
/*check whether CnM is enable or not*/
if ((api_type == TPM_API_CNM) && (TPM_CTC_CM_DISABLED == ctc_cm_enable))
continue;
/* Get the api_section */
tpm_ret = tpm_db_api_section_get_from_api_type(api_type, &api_section);
if (tpm_ret != TPM_RC_OK) {
printk("Get API_SECTION Failed-%s\n", tpm_db_api_type_str[api_type]);
continue;
}
valid_entry_num = 0;
if (tpm_db_api_section_num_entries_get(api_section, &valid_entry_num))
continue;
if (valid_entry_num == 0)
continue;
section_valid_entry_count++;
/*get the last valid rule index in the api_section*/
if (tpm_db_api_section_lastentry_get(api_section, &apisec_last_valid_index))
continue;
/* Get the rulenum index */
for (rule_index = 0; rule_index <= apisec_last_valid_index; rule_index++) {
/*clear structure*/
memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
memset(&pnc_out, 0, sizeof(tpm_pnc_all_t));
memset(&hw_te, 0, sizeof(struct tcam_entry));
memset(&read_pnc, 0, sizeof(tpm_pnc_all_t));
memset(&shadow_pnc, 0, sizeof(tpm_pnc_all_t));
memset(&tpm_rule, 0, sizeof(tpm_rule_entry_t));
memset(&rule_action, 0, sizeof(tpm_rule_action_t));
memset(&mod_con, 0, sizeof(tpm_db_mod_conn_t));
memset(&pnc_con, 0, sizeof(tpm_db_pnc_conn_t));
memset(&api_ent_mem_area, 0, sizeof(tpm_db_api_entry_t));
/*get api section table entry*/
if (tpm_db_api_section_ent_tbl_get(api_section, &api_ent_mem_area, rule_index))
break;
if (api_ent_mem_area.valid == TPM_DB_VALID) {
/*get tpm_rule*/
memcpy(&tpm_rule, &(api_ent_mem_area.api_rule_data),
sizeof(tpm_rule_entry_t));
memcpy(&mod_con, &(api_ent_mem_area.mod_tbl_conn),
sizeof(tpm_db_mod_conn_t));
memcpy(&pnc_con, &(api_ent_mem_area.pnc_tbl_conn), sizeof(tpm_db_pnc_conn_t));
bi_dir = api_ent_mem_area.bi_dir;
rule_num = api_ent_mem_area.rule_idx;
tpm_ret = tpm_check_rebuild_pnc_array[api_section](pon_type,
&tpm_rule,
&mod_con,
&api_ent_mem_area,
&pnc_data,
&mod_entry,
&pkt_mod,
&pkt_mod_bm,
&int_mod_bm,
&trg_port,
&rule_action);
if (tpm_ret) {
printk("API type: %s, the %d th PnC Rule Rebuild Failed\n",
tpm_db_api_type_str[api_type], rule_index);
unnormal_end_count++;
break;
}
/* TCAM map to tpm_tcam_all_t of tpm_pnc_all_t */
tpm_ret = tpm_pncl_tcam_map(&(pnc_data.pncl_tcam), &(pnc_out.tcam_entry));
IF_ERROR(tpm_ret);
/* SRAM map to tpm_sram_all_t of tpm_pnc_all_t */
tpm_ret = tpm_pncl_sram_map(&(pnc_data.pncl_sram),
&(pnc_out.sram_entry),
&(pnc_data.pncl_tcam));
IF_ERROR(tpm_ret);
/*read Pnc from HW table*/
tpm_ret = tcam_hw_read(&hw_te, pnc_con.pnc_conn_tbl[0].pnc_index);
IF_ERROR(tpm_ret);
/*translate tcam_entry to tpm_pnc_all_t*/
tran_tcam_entry_to_pnc_all_t(&read_pnc, &hw_te, &rule_action, api_section);
/*read PnC from PnC shadow table*/
tpm_ret = tpm_db_pnc_shdw_ent_get(pnc_con.pnc_conn_tbl[0].pnc_index,
&shadow_ent_valid,
&shadow_pnc);
IF_ERROR(tpm_ret);
/*check PNC*/
tpm_check_update_sram(&pnc_out.sram_entry, &rule_action);
tpm_check_update_sram(&shadow_pnc.sram_entry, &rule_action);
if (memcmp(&pnc_out, &read_pnc, sizeof(tpm_pnc_all_t))) {
printk("HW PNC mismatch, API type: %s, PnC rule index %d\n",
tpm_db_api_type_str[api_type], rule_index);
pnc_mismatch_info_show(&pnc_out, &read_pnc);
pnc_hw_error_count++;
/*correct the bad tpm rule, TODO done in future*/
/*if (check_level == TPM_SELF_CHECK_LEVEL1)*/
}
if (memcmp(&pnc_out, &shadow_pnc, sizeof(tpm_pnc_all_t))) {
printk("SW PNC mismatch, API type: %s, PnC rule index %d\n",
tpm_db_api_type_str[api_type], rule_index);
pnc_mismatch_info_show(&pnc_out, &shadow_pnc);
pnc_sw_error_count++;
}
/*******************check PMT if necessary********************/
/*check precondition: SET_MOD, jump_entry index is same in API DB, TPM DB and HW*/
/*get HW JUPM Index*/
hw_jump_idx = read_pnc.sram_entry.flowid_val & 0xFFF;
/*get shadow JUPM Index*/
shadow_jump_idx = shadow_pnc.sram_entry.flowid_val & 0xFFF;
if (SET_MOD(rule_action.pkt_act) &&
(hw_jump_idx == shadow_jump_idx) &&
(hw_jump_idx == mod_entry)) {
/*only modify VLAN and VLAN OP is NOOP, do not check*/
if (TPM_VLAN_MOD == pkt_mod_bm && VLANOP_NOOP == pkt_mod.vlan_mod.vlan_op)
continue;
if ((TPM_API_L2_PRIM == api_type) &&
tpm_split_mod_stage1_check(pkt_mod_bm, &pkt_mod, &rule_action, false)) {
int_mod_bm = TPM_INT_SPLIT_MOD;
p_bits_nums = TPM_DB_SPLIT_MOD_P_BIT_NUM_MAX;
/* VLANOP_EXT_TAG_MOD_INS mod insert VLAN p_bit */
if (VLANOP_EXT_TAG_MOD_INS == pkt_mod.vlan_mod.vlan_op)
vlan_out = &pkt_mod.vlan_mod.vlan2_out;
else
vlan_out = &pkt_mod.vlan_mod.vlan1_out;
/* AS-IS pmt check */
vlan_out->pbit_mask = 0;
mod_entry = mod_entry / 16;
mod_entry *= 16;
tpm_ret = tpm_pmt_rebuild_and_check(api_type,
rule_index,
trg_port,
pkt_mod_bm,
int_mod_bm,
&pkt_mod,
&mod_entry,
&pmt_hw_error_count,
&pmt_sw_error_count);
IF_ERROR(tpm_ret);
/* supported pbits pmt check */
vlan_out->pbit_mask = 0xFF;
for (loop = 0; loop < p_bits_nums; loop++) {
tpm_ret = tpm_db_split_mod_get_p_bits_by_index(loop, &p_bits_tpm);
IF_ERROR(tpm_ret);
vlan_out->pbit = p_bits_tpm;
mod_entry++;
tpm_ret = tpm_pmt_rebuild_and_check(api_type,
rule_index,
trg_port,
pkt_mod_bm,
int_mod_bm,
&pkt_mod,
&mod_entry,
&pmt_hw_error_count,
&pmt_sw_error_count);
IF_ERROR(tpm_ret);
}
} else {
/* Normal PMT check */
tpm_ret = tpm_pmt_rebuild_and_check(api_type,
rule_index,
trg_port,
pkt_mod_bm,
int_mod_bm,
&pkt_mod,
&mod_entry,
&pmt_hw_error_count,
&pmt_sw_error_count);
IF_ERROR(tpm_ret);
}
}
}
}
}
if (section_valid_entry_count) {
if (unnormal_end_count) {
if ((pnc_hw_error_count == 0) && (pnc_sw_error_count == 0))
printk("\nPartly PNC Check, OK\n");
if ((pmt_hw_error_count == 0) && (pmt_sw_error_count == 0))
printk("Partly PMT Check, OK\n");
} else {
if ((pnc_hw_error_count == 0) && (pnc_sw_error_count == 0))
printk("\nPNC Check, OK\n");
if ((pmt_hw_error_count == 0) && (pmt_sw_error_count == 0))
printk("PMT Check, OK\n");
}
} else {
printk("(Warn)No Valid Rule exist, Nothing to check\n");
}
return TPM_RC_OK;
}