// ========== Copyright Header Begin ========================================== // // OpenSPARC T2 Processor File: fflp_model.vr // Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved // 4150 Network Circle, Santa Clara, California 95054, U.S.A. // // * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // For the avoidance of doubt, and except that if any non-GPL license // choice is available it will apply instead, Sun elects to use only // the General Public License version 2 (GPLv2) at this time for any // software where a choice of GPL license versions is made // available with the language indicating that GPLv2 or any later version // may be used, or where a choice of which version of the GPL is applied is // otherwise unspecified. // // Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, // CA 95054 USA or visit www.sun.com if you need additional information or // have any questions. // // ========== Copyright Header End ============================================ /*########################################################################### # Copyright (c) 2001 by Sun Microsystems Inc. # All rights reserved. No part of this design may be reproduced, stored # in a retrieval system, or transmitted, in any form or by any means, # electronic, mechanical, photocopying, recording, or otherwise, # without prior written permission from Sun Microsystems, Inc. # # Sun Proprietary/Confidential # File Name : fflp_model.vr # Author : Saranga Pogula # Date : 09-22-2005 # Description : FFLP Model for DMA Prediction for the end-checker based # environment for RX NIU/NEPTUNE. ###########################################################################*/ #include "pkt_configurator_defines.vri" #include "fflp_test_defines.vri" #include "pcg_defines.vri" #include "pcg_types.vri" #include "pack_db.vrh" #include "flow_db.vrh" #include "flow_db_tasks.vrh" #include "pg_top_pp.vrh" #include "pc_top_pp.vrh" #include "ip_util.vrh" #include "ip_ingress_db.vrh" #include "rxc_class.vrh" #include "pcg_token.vrh" #include "mbox_class.vrh" #define MAX_FFLP_FLOWCHART_NODES 40 #define MAX_L2_PATHS 6 #define MAX_L3_PATHS 17 extern Crxc rxc_cl; extern mbox_class mbox_id; class tcam_key_cl { bit tcam_disc; bit tcam_sel; bit tcam_ipaddr; bit [4:0] pkt_class; task new(integer class_num){ tcam_disc = 0; tcam_sel = 0; tcam_ipaddr = 0; pkt_class = class_num; } } class fflp_path { integer node [MAX_FFLP_FLOWCHART_NODES]; task new(){ integer i; for (i=0;iDISC, [9:8]->TRES, [7]->TCAM-Hit, [6:3]->RDC-Offset, [2:0]->RDC-Table function bit [10:0] predict_tcam_rdc_tblnum_offset(flow_desc flow, bit [2:0] l2_rdc, bit [1:0] mac_id); function bit [3:0] predict_flow_rdc_offset(flow_desc flow); function cntl_fifo predict_control_fifo(bit [1:0] mac_id, flow_desc flow); function bit [3:0] lookup_zcp_rdc_table(bit [2:0] rdc_tbl_num, bit [3:0] rdc_tbl_offset); function bit class_matched(integer class_num); function bit [4:0] find_class(integer class_num); function bit [4:0] eval_hash_offset(flow_desc flow, bit [1:0] mac_id); function bit [31:0] calculate_H1_hash (bit [383:0] flow_key); function bit isThisPktIPFrag (integer frame_class); task update_zcp_rdc_tbl_shadow(integer index, bit [3:0] dma_num); task update_mac_da_shadow(bit [1:0] port_num, integer index, bit [51:0] mac_entry); task update_vlan_shadow(integer index, bit [17:0] vlan_entry); task update_tcam_key_shadow(integer index, bit [199:0] tcam_entry); task update_tcam_mask_shadow(integer index, bit[199:0] mask); task update_tcam_assoc_data_shadow(integer index, bit [63:0] assoc_data); task update_tcam_reg_shadow(integer class_num, bit [2:0] cntl_info); task update_flow_key_cntl_shadow(integer class_num, bit [9:0] cntl_info); task update_initial_h1_poly(bit [31:0] init_h1_poly); function bit [199:0] get_tcam_entry(integer index); function bit[199:0] get_tcam_mask(integer index); } task fflp_model::update_initial_h1_poly(bit [31:0] init_h1_poly) { initial_h1_poly = {32'h0,init_h1_poly}; printf("fflp_model::update_initial_h1_poly init_h1_poly=0x%h\n", initial_h1_poly); } function bit[199:0] fflp_model::get_tcam_mask(integer index) { get_tcam_mask = tcam_mask[index]; printf("fflp_model::get_tcam_mask index=%0d tcam_mask=0x%h\n", index, tcam_mask[index]); } function bit [199:0] fflp_model::get_tcam_entry(integer index) { get_tcam_entry = tcam_entries[index]; printf("fflp_model::get_tcam_entry index=%0d, tcam_entry=0x%h\n", index,tcam_entries[index]); } task fflp_model::update_tcam_assoc_data_shadow(integer index, bit [63:0] assoc_data) { tcam_assoc_data[index] = assoc_data; printf("fflp_model::update_tcam_assoc_data_shadow index=%0d, tcam_entry=0x%h\n", index,tcam_assoc_data[index]); } task fflp_model::update_tcam_mask_shadow(integer index, bit[199:0] mask) { tcam_mask[index] = mask; printf("fflp_model::update_tcam_mask_shadow index=%0d mask=0x%h\n", index, tcam_mask[index]); } task fflp_model::update_tcam_key_shadow(integer index, bit [199:0] tcam_entry) { tcam_entries[index] = tcam_entry; printf("fflp_model::update_tcam_key_shadow index=%0d, tcam_entry=0x%h\n", index,tcam_entries[index]); } task fflp_model::update_tcam_reg_shadow(integer class_num, bit [2:0] cntl_info) { tcam_key_reg[class_num-4].tcam_disc = cntl_info[2]; tcam_key_reg[class_num-4].tcam_sel = cntl_info[1]; tcam_key_reg[class_num-4].tcam_ipaddr = cntl_info[0]; printf("fflp_model:: update_tcam_reg_shadow class=%0d, reg_data[2:0]=0x%h\n", class_num, cntl_info); } task fflp_model::update_flow_key_cntl_shadow(integer class_num, bit [9:0] cntl_info) { flow_cntl_reg[class_num-4].PORT = cntl_info[9]; flow_cntl_reg[class_num-4].L2DA = cntl_info[8]; flow_cntl_reg[class_num-4].VLAN = cntl_info[7]; flow_cntl_reg[class_num-4].IPSA = cntl_info[6]; flow_cntl_reg[class_num-4].IPDA = cntl_info[5]; flow_cntl_reg[class_num-4].PROTO = cntl_info[4]; flow_cntl_reg[class_num-4].L4_0 = cntl_info[3:2]; flow_cntl_reg[class_num-4].L4_1 = cntl_info[1:0]; printf("fflp_model:: update_flow_key_cntl_shadow class=%0d, reg_data[2:0]=0x%h\n", class_num,cntl_info); } function bit fflp_model::class_matched(integer class_num) { if ( (class_num == CL_TCP) || (class_num==CL_TCP_FRAG) || (class_num==CL_TCP_OPT) || (class_num == CL_UDP) || (class_num==CL_UDP_FRAG) || (class_num==CL_UDP_OPT) || (class_num == CL_IP_SEC_AH) || (class_num == CL_IP_SEC_ESP) || (class_num == CL_SCTP) || (class_num==CL_SCTP_FRAG) || (class_num==CL_SCTP_OPT) || (class_num == CL_TCP_IP_V6) || (class_num == CL_TCP_FRAG_IP_V6) || (class_num == CL_TCP_OPT_IP_V6) || (class_num == CL_UDP_IP_V6) || (class_num == CL_UDP_FRAG_IP_V6) || (class_num == CL_UDP_OPT_IP_V6) || (class_num == CL_IP_V6_SEC_AH) || (class_num == CL_IP_V6_SEC_ESP) || (class_num == CL_SCTP_IP_V6) || (class_num == CL_ARP) || (class_num == CL_RARP) ) class_matched = 1; else class_matched = 0; } function bit fflp_model::isThisPktIPFrag(integer frame_class) { isThisPktIPFrag = 0; if((frame_class==CL_TCP_FRAG) || (frame_class==CL_UDP_FRAG) || (frame_class==CL_SCTP_FRAG) || (frame_class==CL_IP_FRAG) ) isThisPktIPFrag = 1; } function bit [4:0] fflp_model::find_class(integer class_num) { case(class_num) { CL_TCP, CL_TCP_FRAG: find_class = 8; CL_UDP, CL_UDP_FRAG: find_class = 9; CL_IP_SEC_AH,CL_IP_SEC_ESP: find_class = 10; CL_SCTP, CL_SCTP_FRAG: find_class = 11; CL_TCP_IP_V6: find_class = 12; CL_UDP_IP_V6: find_class = 13; CL_IP_V6_SEC_AH,CL_IP_V6_SEC_ESP: find_class = 14; CL_SCTP_IP_V6: find_class = 15; CL_ARP: find_class = 16; CL_RARP: find_class =17; default : { find_class = 0; } } } function bit [2:0] fflp_model::predict_l2_rdc_tblnum(bit [1:0] mac_id, flow_desc flow) { bit [3:0] mac_ctl_word, vlan_ctl_word; bit [2:0] mac_rdc_tblnum; bit [2:0] vlan_rdc_tblnum; bit mpr, vpr; mac_ctl_word = predict_mac_rdc_tblnum_pri(mac_id, flow); mpr = mac_ctl_word[3]; mac_rdc_tblnum = mac_ctl_word[2:0]; if(flow.frame.frame_type[2]==1) { // VLAN Tagged // VLAN tagged /*========== FFLP_Path =========*/ path_class.node[index++] = 4; /*@@@@@@@@ Cntl Hdr Info @@@@@@@@*/ ctl_fifo.vlan = 1; /*@@@@@@@@ Cntl Fifo Info @@@@@@@*/ control_fifo_chkr.vlan = 1; vlan_ctl_word = predict_vlan_rdc_tblnum_pri(mac_id, flow); vpr = vlan_ctl_word[3]; vlan_rdc_tblnum = vlan_ctl_word[2:0]; case ({vpr,mpr}){ 2'b00: { predict_l2_rdc_tblnum = mac_rdc_tblnum; /*========== FFLP_Path =========*/ path_class.node[index++] = 8; /*========== FFLP_Path =========*/ path_class.node[index++] = 10; } 2'b01: { predict_l2_rdc_tblnum = mac_rdc_tblnum; /*========== FFLP_Path =========*/ path_class.node[index++] = 8; /*========== FFLP_Path =========*/ path_class.node[index++] = 9; } 2'b10: { predict_l2_rdc_tblnum = vlan_rdc_tblnum; /*========== FFLP_Path =========*/ path_class.node[index++] = 7; } 2'b11: { predict_l2_rdc_tblnum = vlan_rdc_tblnum; /*========== FFLP_Path =========*/ path_class.node[index++] = 7; } default: {} } } else { predict_l2_rdc_tblnum = mac_rdc_tblnum; // Untagged /*========== FFLP_Path =========*/ path_class.node[index++] = 3; } printf ("fflp_model::predict_l2_rdc_tblnum MAC=%0d mpr=%b vpr=%b mac_rdc=%0d vlan_rdc=%0d, final_l2_rdc=%0d\n", mac_id, mpr, vpr, mac_rdc_tblnum, vlan_rdc_tblnum, predict_l2_rdc_tblnum); } function cntl_fifo fflp_model::predict_control_fifo(bit [1:0] mac_id, flow_desc flow){ bit [2:0] l2_rdc, tcam_rdc; bit [10:0] tcam_result; bit [3:0] tcam_offset, flow_offset; bit [4:0] class_num; bit [47:0] mac_sa; bit [15:0] seq_id; bit tcam_match, ext_hash, asdata_disc; bit [1:0] TRES; bit [4:0] hash_offset; ctl_fifo = new; control_fifo_chkr = new; path_class = new; index = 0; master_path_class = new; master_index = 0; /*========== FFLP_Path =========*/ path_class.node[index++] = 0; mac_sa = flow.src_node.l2_addr; seq_id = mac_sa[15:0]; #define CLASS_4TO15 ((class_num>=4)&&(class_num<=15)) l2_rdc = predict_l2_rdc_tblnum(mac_id, flow); /*@@@@@@@@ Cntl Hdr Info @@@@@@@@*/ ctl_fifo.pkt_id = port_pkt_id[mac_id]; /*@@@@@@@@ Cntl Fifo Info @@@@@@@*/ control_fifo_chkr.pkt_id = port_pkt_id[mac_id]; port_pkt_id[mac_id] = (port_pkt_id[mac_id]+1)%16; pkt_id[mac_id]++; /*@@@@@@@@ Cntl Hdr Info @@@@@@@@*/ ctl_fifo.port_num = mac_id; /*@@@@@@@@ Cntl Fifo Info @@@@@@@*/ control_fifo_chkr.mac_prt = mac_id; if(flow.frame.frame_type[0]==1) { // LLC/SNAP packet /*@@@@@@@@ Cntl Hdr Info @@@@@@@@*/ ctl_fifo.llcsnap = 1; /*@@@@@@@@ Cntl Fifo Info @@@@@@@*/ control_fifo_chkr.llcsnap = 1; } printf("fflp_model: Algorithm: MAC%0d.%0d err code from pkt=%0d\n", mac_id, seq_id, flow.frame.error_code); if( (!class_matched(flow.frame.frame_class)) || ((flow.frame.error_code&PG_L4_PROTO_USER_MODE) == PG_L4_PROTO_USER_MODE)) { // no class matched ctl_fifo.final_zcp_rdc_tbl_num = l2_rdc; ctl_fifo.final_zcp_rdc_tbl_offset = 0; ctl_fifo.final_dma_chnl = lookup_zcp_rdc_table(ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_zcp_rdc_tbl_offset); /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 11; //printf("fflp_model: Algorithm: MAC%0d.%0d No class matched (or cksum err=%0d). l2_rdc = %0d, dma_num = %0d\n", printf("fflp_model: Algorithm: MAC%0d.%0d No class matched. l2_rdc = %0d, dma_num = %0d\n", mac_id, seq_id, ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_dma_chnl); } else { // class matched class_num = find_class(flow.frame.frame_class); /*@@@@@@@@ Cntl Hdr Info @@@@@@@@*/ ctl_fifo.packet_class = class_num; /*@@@@@@@@ Cntl Fifo Info @@@@@@@*/ control_fifo_chkr.packet_class = class_num; /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 12; if(CLASS_4TO15) { /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 14; if (isThisPktIPFrag(flow.frame.frame_class)) { // check for FRAG packets /*@@@@@@@@ Cntl Hdr Info @@@@@@@@*/ ctl_fifo.noport = 1; /*@@@@@@@@ Cntl Fifo Info @@@@@@@*/ control_fifo_chkr.noport = 1; } printf("fflp_model: Algorithm: MAC%0d.%0d class is 4-15. class_num = %0d\n", mac_id, seq_id, class_num); if (tcam_key_reg[class_num-4].tcam_disc) { // DISC bit set for this class /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 15; ctl_fifo.tcam_key_drop = 1; printf("fflp_model: Algorithm: MAC%0d.%0d DISC bit set for class_num = %0d\n", mac_id, seq_id, class_num); } else { // DISC bit not set for this class /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 16; if(tcam_key_reg[class_num-4].tcam_sel) { // tcam lookup required for this class /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 18; printf ("fflp_model: Algorithm: MAC%0d.%0d tcam lookup required class_num = %0d\n", mac_id, seq_id, class_num); tcam_result = predict_tcam_rdc_tblnum_offset(flow, l2_rdc, mac_id); tcam_rdc = tcam_result[2:0]; tcam_offset = tcam_result[6:3]; tcam_match = tcam_result[7]; TRES = tcam_result[9:8]; asdata_disc = tcam_result[10]; if (tcam_match) { /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 20; if (asdata_disc) /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 21; else /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 22; /*@@@@@@@@ Cntl Hdr Info @@@@@@@@*/ ctl_fifo.tcamhit = 1; /*@@@@@@@@ Cntl Fifo Info @@@@@@@*/ control_fifo_chkr.tcamhit = 1; /*@@@@@@@@ Cntl Hdr Info @@@@@@@@*/ ctl_fifo.tres = TRES; /*@@@@@@@@ Cntl Fifo Info @@@@@@@*/ control_fifo_chkr.tres = TRES; printf ("fflp_model: Algorithm: class %0d MAC%0d.%0d TCAM_hit=1, TRES=%b\n", class_num, mac_id, seq_id, TRES); if (TRES[1] == 1'b0) { // take L2 RDC number despite having a TCAM-Hit /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 23; if (TRES[0] == 1'b0) { // continue to flow lookup for OFFSET /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 25; if ((class_num>=8)&&(class_num<=15)) { // L3 class match, L2_RDC taken, and Hash1/Ext_hash evaluation has to be done if((flow_cntl_reg[class_num-4].PORT !== 0) || (flow_cntl_reg[class_num-4].L2DA !== 0) || (flow_cntl_reg[class_num-4].VLAN !== 0) || (flow_cntl_reg[class_num-4].IPSA !== 0) || (flow_cntl_reg[class_num-4].IPDA !== 0) || (flow_cntl_reg[class_num-4].PROTO !== 0) || (flow_cntl_reg[class_num-4].L4_0 !== 0) || (flow_cntl_reg[class_num-4].L4_1 !== 0) ) { hash_offset = eval_hash_offset(flow, mac_id); ctl_fifo.final_zcp_rdc_tbl_offset = hash_offset[3:0]; } else { ctl_fifo.final_zcp_rdc_tbl_offset = 0; } ctl_fifo.final_zcp_rdc_tbl_num = l2_rdc; ext_hash = hash_offset[4]; ctl_fifo.final_dma_chnl = lookup_zcp_rdc_table(ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_zcp_rdc_tbl_offset); printf("fflp_model: Algorithm: class %0d MAC%0d.%0d L3 class, hash done. Ext_Hash = %b, L2_RDC = %0d, Hash Offset evaluated %0d\n", class_num, mac_id, seq_id, ext_hash, ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_zcp_rdc_tbl_offset); } else { // No L3 class match, no hash required. Ending up with L2_RDC, Offset=0 despite tcam_hit=1 ctl_fifo.final_zcp_rdc_tbl_num = l2_rdc; ctl_fifo.final_zcp_rdc_tbl_offset = 0; ctl_fifo.final_dma_chnl = lookup_zcp_rdc_table(ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_zcp_rdc_tbl_offset); printf ("fflp_model: Algorithm: MAC%0d.%0d class %0d No L3 class match, no hash, RDC=L2_RDC %0d, Offset=0 despite tcam_hit=1\n", mac_id, seq_id, class_num, ctl_fifo.final_zcp_rdc_tbl_num); } } else { // TRES[0]==1 terminate the flow lookup and use L2_RDC/Offset=0 /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 26; printf ("fflp_model: Algorithm: MAC%0d.%0d TRES=01, use L2_RDC despite a TCAM hit, tcam_offset, NO flow , class %0d\n", mac_id, seq_id, class_num); ctl_fifo.final_zcp_rdc_tbl_num = l2_rdc; ctl_fifo.final_zcp_rdc_tbl_offset = tcam_offset; ctl_fifo.final_dma_chnl = lookup_zcp_rdc_table(ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_zcp_rdc_tbl_offset); } } else { // TRES[1]==1 /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 24; if (TRES[0] == 1'b0) { // Take Assoc_data RDC_TBL number and continue to flow lookup for OFFSET. TRES[0]==0 /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 25; if ((class_num>=8)&&(class_num<=15)) { // L3 class match, L2_RDC taken, and Hash1/Ext_hash evaluation has to be done if((flow_cntl_reg[class_num-4].PORT !== 0) || (flow_cntl_reg[class_num-4].L2DA !== 0) || (flow_cntl_reg[class_num-4].VLAN !== 0) || (flow_cntl_reg[class_num-4].IPSA !== 0) || (flow_cntl_reg[class_num-4].IPDA !== 0) || (flow_cntl_reg[class_num-4].PROTO !== 0) || (flow_cntl_reg[class_num-4].L4_0 !== 0) || (flow_cntl_reg[class_num-4].L4_1 !== 0) ) { hash_offset = eval_hash_offset(flow, mac_id); ctl_fifo.final_zcp_rdc_tbl_offset = hash_offset[3:0]; /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 28; } else { ctl_fifo.final_zcp_rdc_tbl_offset = 0; /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 27; } ctl_fifo.final_zcp_rdc_tbl_num = tcam_rdc; ext_hash = hash_offset[4]; ctl_fifo.final_dma_chnl = lookup_zcp_rdc_table(ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_zcp_rdc_tbl_offset); printf("fflp_model: Algorithm: class %0d MAC%0d.%0d L3 class, hash done. Ext_Hash = %b, L2_RDC = %0d, Hash Offset evaluated %0d\n", class_num, mac_id, seq_id, ext_hash, ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_zcp_rdc_tbl_offset); } else { // No L3 class match, no hash required. Ending up with L2_RDC, Offset=0 despite tcam_hit=1 ctl_fifo.final_zcp_rdc_tbl_num = l2_rdc; ctl_fifo.final_zcp_rdc_tbl_offset = 0; ctl_fifo.final_dma_chnl = lookup_zcp_rdc_table(ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_zcp_rdc_tbl_offset); printf ("fflp_model: Algorithm: MAC%0d.%0d class %0d No L3 class match, no hash, RDC=L2_RDC %0d, Offset=0 despite tcam_hit=1\n", mac_id, seq_id, class_num, ctl_fifo.final_zcp_rdc_tbl_num); } } else { // terminate the flow lookup and use Assoc_data RDC_TBL and OFFSET number /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 26; printf ("fflp_model: Algorithm: MAC%0d.%0d TRES[1:0]=11, use Assoc_data RDC_TBL and OFFSET, NO flow lookup, class %0d\n", mac_id, seq_id, class_num); ctl_fifo.final_zcp_rdc_tbl_num = tcam_rdc; ctl_fifo.final_zcp_rdc_tbl_offset = tcam_offset; ctl_fifo.final_dma_chnl = lookup_zcp_rdc_table(ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_zcp_rdc_tbl_offset); printf ("fflp_model: Algorithm: class %0d MAC%0d.%0d TCAM hit Found. Resulting in TCAM_rdc %0d, offset %0d dma_num %0d\n", class_num, mac_id, seq_id, ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_zcp_rdc_tbl_offset, ctl_fifo.final_dma_chnl); } } } else { // NO TCAM MATCH /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 19; if ((class_num>=8)&&(class_num<=15)) { // L3 class match, L2_RDC finalized, and Hash1/Ext_hash evaluation has to be done /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 30; /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 31; if ( (flow_cntl_reg[class_num-4].PORT !== 0) || (flow_cntl_reg[class_num-4].L2DA !== 0) || (flow_cntl_reg[class_num-4].VLAN !== 0) || (flow_cntl_reg[class_num-4].IPSA !== 0) || (flow_cntl_reg[class_num-4].IPDA !== 0) || (flow_cntl_reg[class_num-4].PROTO !== 0) || (flow_cntl_reg[class_num-4].L4_0 !== 0) || (flow_cntl_reg[class_num-4].L4_1 !== 0) ) { hash_offset = eval_hash_offset(flow, mac_id); ctl_fifo.final_zcp_rdc_tbl_offset = hash_offset[3:0]; /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 28; } else { ctl_fifo.final_zcp_rdc_tbl_offset = 0; /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 27; } ctl_fifo.final_zcp_rdc_tbl_num = l2_rdc; ext_hash = hash_offset[4]; ctl_fifo.final_dma_chnl = lookup_zcp_rdc_table(ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_zcp_rdc_tbl_offset); printf("fflp_model: Algorithm: class %0d MAC%0d.%0d No tcam_hit, L3 class, hash done. Ext_Hash %b, L2_RDC %0d, Hash Offset %0d\n", class_num, mac_id, seq_id, ext_hash, ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_zcp_rdc_tbl_offset); } else { // No L3 class match, No TCAM key required, so no hash required. Ending up with L2_RDC, Offset=0 /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 29; ctl_fifo.final_zcp_rdc_tbl_num = l2_rdc; ctl_fifo.final_zcp_rdc_tbl_offset = 0; ctl_fifo.final_dma_chnl = lookup_zcp_rdc_table(ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_zcp_rdc_tbl_offset); printf ("fflp_model: Algorithm: class %0d MAC%0d.%0d No tcam_hit, not an L3 class. Resulting in l2_rdc = %0d, dma_num = %0d\n", class_num, mac_id, seq_id, ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_dma_chnl); } } } else { // No tcam lookup required for this class /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 17; printf ("fflp_model: Algorithm: MAC%0d.%0d NO tcam lookup required for class_num = %0d\n", mac_id, seq_id, class_num); if ((class_num>=8)&&(class_num<=15)) { // L3 class match, L2_RDC finalized, and Hash1/Ext_hash evaluation has to be done /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 30; /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 31; if ( (flow_cntl_reg[class_num-4].PORT !== 0) || (flow_cntl_reg[class_num-4].L2DA !== 0) || (flow_cntl_reg[class_num-4].VLAN !== 0) || (flow_cntl_reg[class_num-4].IPSA !== 0) || (flow_cntl_reg[class_num-4].IPDA !== 0) || (flow_cntl_reg[class_num-4].PROTO !== 0) || (flow_cntl_reg[class_num-4].L4_0 !== 0) || (flow_cntl_reg[class_num-4].L4_1 !== 0) ) { hash_offset = eval_hash_offset(flow, mac_id); ctl_fifo.final_zcp_rdc_tbl_offset = hash_offset[3:0]; } else { ctl_fifo.final_zcp_rdc_tbl_offset = 0; } ctl_fifo.final_zcp_rdc_tbl_num = l2_rdc; ext_hash = hash_offset[4]; ctl_fifo.final_dma_chnl = lookup_zcp_rdc_table(ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_zcp_rdc_tbl_offset); printf("fflp_model: Algorithm: class %0d MAC%0d.%0d L3 class, hash done. Ext_Hash = %b, L2_RDC = %0d, Hash Offset evaluated %0d\n", class_num, mac_id, seq_id, ext_hash, ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_zcp_rdc_tbl_offset); } else { // No L3 class match, No TCAM key required, so no hash required. Ending up with L2_RDC, Offset=0 /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 29; ctl_fifo.final_zcp_rdc_tbl_num = l2_rdc; ctl_fifo.final_zcp_rdc_tbl_offset = 0; ctl_fifo.final_dma_chnl = lookup_zcp_rdc_table(ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_zcp_rdc_tbl_offset); printf("fflp_model: Algorithm: class %0d MAC%0d.%0d not an L3 class. L2_RDC = %0d, Offset = 0\n", class_num, mac_id, seq_id, ctl_fifo.final_zcp_rdc_tbl_num); } } } } else { // classes other than (4->15) will have an unconditional tcam search (ARP,RARP and 2 programmable ETHER classes) /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 13; printf("fflp_model: Algorithm: MAC%0d.%0d L2 class. Unconditional TCAM Search done for class %0d\n", mac_id, seq_id, class_num); tcam_result = predict_tcam_rdc_tblnum_offset(flow, l2_rdc, mac_id); tcam_rdc = tcam_result[2:0]; tcam_offset = tcam_result[6:3]; tcam_match = tcam_result[7]; TRES = tcam_result[9:8]; asdata_disc = tcam_result[10]; if (tcam_match) { /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 20; if (asdata_disc) /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 21; else /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 22; /*@@@@@@@@ Cntl Hdr Info @@@@@@@@*/ ctl_fifo.tcamhit = 1; /*@@@@@@@@ Cntl Fifo Info @@@@@@@*/ control_fifo_chkr.tcamhit = 1; /*@@@@@@@@ Cntl Hdr Info @@@@@@@@*/ ctl_fifo.tres = TRES; /*@@@@@@@@ Cntl Fifo Info @@@@@@@*/ control_fifo_chkr.tres = TRES; if (TRES[1] == 1'b0) { // take L2 RDC number despite having a TCAM-Hit /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 23; if (TRES[0] == 1'b0) { // continue to flow lookup for OFFSET /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 25; /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 27; printf ("fflp_model: Algorithm: MAC%0d.%0d TRES[1:0]=00, use L2_RDC despite having a TCAM hit, continue flow lookup, class %0d\n", mac_id, seq_id, class_num); } else { // terminate the flow lookup and use L2_RDC/Offset=0 /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 26; printf ("fflp_model: Algorithm: MAC%0d.%0d TRES[1:0]=01, use L2_RDC despite having a TCAM hit, NO flow lookup, class %0d\n", mac_id, seq_id, class_num); ctl_fifo.final_zcp_rdc_tbl_num = l2_rdc; ctl_fifo.final_zcp_rdc_tbl_offset = tcam_offset; ctl_fifo.final_dma_chnl = lookup_zcp_rdc_table(ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_zcp_rdc_tbl_offset); } } else { // TRES[1]==1 /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 24; if (TRES[0] == 1'b0) { // Take Assoc_data RDC_TBL number and continue to flow lookup for OFFSET /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 25; /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 27; printf ("fflp_model: Algorithm: MAC%0d.%0d TRES[1:0]=10, use Assoc_data RDC_TBL, continue flow lookup for OFFSET, class %0d\n", mac_id, seq_id, class_num); } else { // terminate the flow lookup and use Assoc_data RDC_TBL and OFFSET number /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 26; printf ("fflp_model: Algorithm: MAC%0d.%0d TRES[1:0]=11, use Assoc_data RDC_TBL and OFFSET, NO flow lookup, class %0d\n", mac_id, seq_id, class_num); ctl_fifo.final_zcp_rdc_tbl_num = tcam_rdc; ctl_fifo.final_zcp_rdc_tbl_offset = tcam_offset; ctl_fifo.final_dma_chnl = lookup_zcp_rdc_table(ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_zcp_rdc_tbl_offset); printf ("fflp_model: Algorithm: class %0d MAC%0d.%0d TCAM hit Found. Resulting in TCAM_rdc %0d, offset %0d dma_num %0d\n", class_num, mac_id, seq_id, ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_zcp_rdc_tbl_offset, ctl_fifo.final_dma_chnl); } } } else { /*========== FFLP_Path =========*/ master_path_class.node[master_index++] = 19; ctl_fifo.final_zcp_rdc_tbl_num = l2_rdc; ctl_fifo.final_zcp_rdc_tbl_offset = 0; ctl_fifo.final_dma_chnl = lookup_zcp_rdc_table(ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_zcp_rdc_tbl_offset); printf ("fflp_model: Algorithm: class %0d MAC%0d.%0d No tcam_hit. Resulting in l2_rdc = %0d, dma_num = %0d\n", class_num, mac_id, seq_id, ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_dma_chnl); } } // No L3 class match } if(flow.frame.error_code==PG_CHKSUM_ERR) { ctl_fifo.final_zcp_rdc_tbl_offset = 0; ctl_fifo.final_dma_chnl = lookup_zcp_rdc_table(ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_zcp_rdc_tbl_offset); printf("fflp_model: Algorithm: MAC%0d.%0d cksum err=%0d. offset=0 l2_rdc = %0d, dma_num = %0d\n", mac_id, seq_id, flow.frame.error_code, ctl_fifo.final_zcp_rdc_tbl_num, ctl_fifo.final_dma_chnl); } predict_control_fifo = ctl_fifo.object_copy(); path_class.print_path(mac_id, pkt_id[mac_id]); master_path_class.print_path(mac_id, pkt_id[mac_id]); path_analysis.update_l2_histogram(path_class); path_analysis.update_l3_histogram(master_path_class); // Send the modeled classification result to "control fifo checker", if enabled if (get_plus_arg(CHECK, "ENABLE_CTRL_FIFO_CHKR")) mailbox_put(mbox_id.cntl_chkr_mbox[mac_id], control_fifo_chkr); } function bit [4:0] fflp_model::eval_hash_offset(flow_desc flow, bit [1:0] mac_id) { bit [383:0] flow_entry, reverse_flow; bit [4:0] class_num; bit [31:0] hash1; bit [31:0] serial_hash1; bit [15:0] udp_length, ah_length; integer i; Cpkt_info packet_info; /* eval_hash_offset[4] = 0; // now, ext hash is not done. // do we need ext lookup? if (yes) { } else { */ class_num = find_class(flow.frame.frame_class); flow_entry = 384'h0; // Fields not found in the pkt will be 0 if (flow_cntl_reg[class_num-4].PORT) flow_entry[FLOW_KEY_PORT] = mac_id; if (flow_cntl_reg[class_num-4].L2DA) flow_entry[FLOW_KEY_MAC_DA] = flow.dst_node.l2_addr; if (flow.frame.frame_type[2] & flow_cntl_reg[class_num-4].VLAN) { flow_entry[FLOW_KEY_VLAN_ID] = flow.src_node.tci; flow_entry[FLOW_KEY_VLAN_VALID] = 4'b1111; } if (flow.frame.frame_type[3] && flow.frame.frame_type[1]) { // IPV6 if (flow_cntl_reg[class_num-4].IPSA) flow_entry[FLOW_KEY_IPV6_SA] = flow.src_node.ipv6_addr; if (flow_cntl_reg[class_num-4].IPDA) flow_entry[FLOW_KEY_IPV6_DA] = flow.dst_node.ipv6_addr; } else if (!flow.frame.frame_type[3] && flow.frame.frame_type[1]) { // IPV4 if (flow_cntl_reg[class_num-4].IPSA) flow_entry[FLOW_KEY_IPV4_SA] = flow.src_node.ip_addr; if (flow_cntl_reg[class_num-4].IPDA) flow_entry[FLOW_KEY_IPV4_DA] = flow.dst_node.ip_addr; } if ((flow.frame.frame_class == CL_UDP) || (flow.frame.frame_class==CL_UDP_FRAG) || (flow.frame.frame_class == CL_UDP_IP_V6)) { if (flow_cntl_reg[class_num-4].PROTO) flow_entry[FLOW_KEY_PID] = 8'h11; udp_length = 0; // TODO need to calculate exact UDP length case (flow_cntl_reg[class_num-4].L4_0) { 2'b00: {} 2'b10: flow_entry[FLOW_KEY_L4_0] = flow.tup.src_tcp_udp_port; //2'b11: flow_entry[FLOW_KEY_L4_0] = flow.tup.udp_length; default: printf("fflp_model::eval_hash_offset ERROR invalid programming into flow_cntl_reg[L4_0] - 0x%h class %0d", flow_cntl_reg[class_num-4].L4_0, class_num); } case (flow_cntl_reg[class_num-4].L4_1) { 2'b00: {} 2'b10: flow_entry[FLOW_KEY_L4_1] = flow.tup.dst_tcp_udp_port; //2'b11: flow_entry[FLOW_KEY_L4_1] = flow.tup.udp_checksum; // TODO It is very tough to do match on checksum default: printf("fflp_model::eval_hash_offset ERROR invalid programming into flow_cntl_reg[L4_1] - 0x%h class %0d", flow_cntl_reg[class_num-4].L4_1, class_num); } } else if ((flow.frame.frame_class == CL_TCP) || (flow.frame.frame_class==CL_TCP_FRAG) || (flow.frame.frame_class == CL_TCP_IP_V6)) { if (flow_cntl_reg[class_num-4].PROTO) flow_entry[FLOW_KEY_PID] = 8'h06; case (flow_cntl_reg[class_num-4].L4_0) { 2'b00: {} 2'b10: flow_entry[FLOW_KEY_L4_0] = flow.tup.src_tcp_udp_port; 2'b11: flow_entry[FLOW_KEY_L4_0] = flow.tup.tcp_seq_no[31:16]; default: printf("fflp_model::eval_hash_offset ERROR invalid programming into flow_cntl_reg[L4_0] - 0x%h class %0d", flow_cntl_reg[class_num-4].L4_0, class_num); } case (flow_cntl_reg[class_num-4].L4_1) { 2'b00: {} 2'b10: flow_entry[FLOW_KEY_L4_1] = flow.tup.dst_tcp_udp_port; 2'b11: flow_entry[FLOW_KEY_L4_1] = flow.tup.tcp_seq_no[15:0]; default: printf("fflp_model::eval_hash_offset ERROR invalid programming into flow_cntl_reg[L4_1] - 0x%h class %0d", flow_cntl_reg[class_num-4].L4_1, class_num); } } else if ((flow.frame.frame_class == CL_IP_SEC_AH) || (flow.frame.frame_class == CL_IP_V6_SEC_AH)) { //TODO if (flow_cntl_reg[class_num-4].PROTO) flow_entry[FLOW_KEY_PID] = 8'h33; ah_length = 0; // TODO need to calculate exact AH length case (flow_cntl_reg[class_num-4].L4_0) { 2'b00: {} //2'b10: flow_entry[FLOW_KEY_L4_0] = {ah_length, flow.src_node.nxthdr}; 2'b11: flow_entry[FLOW_KEY_L4_0] = flow.src_node.spi[31:16]; default: printf("fflp_model::eval_hash_offset ERROR invalid programming into flow_cntl_reg[L4_0] - 0x%h class %0d", flow_cntl_reg[class_num-4].L4_0, class_num); } case (flow_cntl_reg[class_num-4].L4_1) { 2'b00: {} 2'b10: flow_entry[FLOW_KEY_L4_1] = 0; 2'b11: flow_entry[FLOW_KEY_L4_1] = flow.src_node.spi[15:0]; default: printf("fflp_model::eval_hash_offset ERROR invalid programming into flow_cntl_reg[L4_1] - 0x%h class %0d", flow_cntl_reg[class_num-4].L4_1, class_num); } } else if ((flow.frame.frame_class == CL_IP_SEC_ESP) || (flow.frame.frame_class == CL_IP_V6_SEC_ESP)) { //TODO if (flow_cntl_reg[class_num-4].PROTO) flow_entry[FLOW_KEY_PID] = 8'h32; case (flow_cntl_reg[class_num-4].L4_0) { 2'b00: {} 2'b10: flow_entry[FLOW_KEY_L4_0] = flow.src_node.spi[31:16]; 2'b11: flow_entry[FLOW_KEY_L4_0] = flow.src_node.esp_ah_seq_no[31:16]; default: printf("fflp_model::eval_hash_offset ERROR invalid programming into flow_cntl_reg[L4_0] - 0x%h class %0d", flow_cntl_reg[class_num-4].L4_0, class_num); } case (flow_cntl_reg[class_num-4].L4_1) { 2'b00: {} 2'b10: flow_entry[FLOW_KEY_L4_1] = flow.src_node.spi[15:0]; 2'b11: flow_entry[FLOW_KEY_L4_1] = flow.src_node.esp_ah_seq_no[15:0]; default: printf("fflp_model::eval_hash_offset ERROR invalid programming into flow_cntl_reg[L4_1] - 0x%h class %0d", flow_cntl_reg[class_num-4].L4_1, class_num); } } else if ((flow.frame.frame_class == CL_SCTP) || (flow.frame.frame_class==CL_SCTP_FRAG) || (flow.frame.frame_class == CL_SCTP_IP_V6) ) { //TODO if (flow_cntl_reg[class_num-4].PROTO) flow_entry[FLOW_KEY_PID] = 8'h84; case (flow_cntl_reg[class_num-4].L4_0) { 2'b00: {} 2'b10: flow_entry[FLOW_KEY_L4_0] = flow.sctp.src_sctp_port; 2'b11: flow_entry[FLOW_KEY_L4_0] = flow.sctp.sctp_vtag[31:16]; default: printf("fflp_model::eval_hash_offset ERROR invalid programming into flow_cntl_reg[L4_0] - 0x%h class %0d", flow_cntl_reg[class_num-4].L4_0, class_num); } case (flow_cntl_reg[class_num-4].L4_1) { 2'b00: {} 2'b10: flow_entry[FLOW_KEY_L4_1] = flow.sctp.dst_sctp_port; 2'b11: flow_entry[FLOW_KEY_L4_1] = flow.sctp.sctp_vtag[15:0]; default: printf("fflp_model::eval_hash_offset ERROR invalid programming into flow_cntl_reg[L4_1] - 0x%h class %0d", flow_cntl_reg[class_num-4].L4_1, class_num); } } else { // NO L3 class match flow_entry[FLOW_KEY_L4_0] = 0; flow_entry[FLOW_KEY_L4_1] = 0; flow_entry[FLOW_KEY_PID] = 0; } // At this point, we have extracted all the fields of FLOW from the incoming Packet // Now, calculate the Hash1 (CRC-32) function for this 384 bit flow key //serial_hash1 = rxc_cl.setup_cam_ram_fcram_cl.calculate_H1(0, 3'h0, packet_info); hash1 = calculate_H1_hash(flow_entry); eval_hash_offset = {1'b0, hash1[3:0]}; // external hash is not supported now, 12/21/2005 printf("fflp_model::eval_hash_offset flow_entry=0x%h, hash1=0x%h, offset=0x%h\n", flow_entry, hash1, eval_hash_offset[3:0]); printf("Model FLOW_KEY: VLAN_VALID=0x%h DA=0x%h VLAN_ID=0x%h IPSA=0x%h IPDA=0x%h L4_0=0x%h L4_1=0x%h PID=0x%h PORT=%h\n", flow_entry[FLOW_KEY_VLAN_VALID], flow_entry[FLOW_KEY_MAC_DA], flow_entry[FLOW_KEY_VLAN_ID], flow_entry[FLOW_KEY_IPV4_SA], flow_entry[FLOW_KEY_IPV4_DA], flow_entry[FLOW_KEY_L4_0], flow_entry[FLOW_KEY_L4_1], flow_entry[FLOW_KEY_PID], flow_entry[FLOW_KEY_PORT]); } function bit [10:0] fflp_model::predict_tcam_rdc_tblnum_offset(flow_desc flow, bit [2:0] l2_rdc, bit [1:0] mac_id) { bit [199:0] pkt_tcam_key; bit [2:0] tcam_key_register; bit [4:0] fflp_class; bit [63:0] matched_assoc_data; integer i; bit [47:0] mac_sa; bit [15:0] seq_id; predict_tcam_rdc_tblnum_offset[7] = 0; // set the tcam_hit bit to 0 first. If there's a hit, it will be set to 1. predict_tcam_rdc_tblnum_offset[9:8] = 2'b11; // set the TRES to 2'b11 first, TCAM-Hit will overwrite it. predict_tcam_rdc_tblnum_offset[10] = 0; // DISC bit from assoc data in case of TCAM-Hit mac_sa = flow.src_node.l2_addr; seq_id = mac_sa[15:0]; pkt_tcam_key[TCAM_CLS_CODE] = find_class(flow.frame.frame_class); printf ("fflp_model::predict_tcam_rdc_tblnum_offset pkt_tcam_key[TCAM_CLS_CODE] = %0d\n", pkt_tcam_key[TCAM_CLS_CODE]); case (pkt_tcam_key[TCAM_CLS_CODE]) { 8,9,10,11: { pkt_tcam_key[194:192] = 0; // RESERVED pkt_tcam_key[185:112] = 0; // RESERVED pkt_tcam_key[IPV4_CAM_L2RDC_TBL_NUM] = l2_rdc; if(flow.frame.frame_class==CL_TCP_FRAG || flow.frame.frame_class==CL_UDP_FRAG || flow.frame.frame_class==CL_SCTP_FRAG) pkt_tcam_key[IPV4_CAM_NOPORT] = 1; else pkt_tcam_key[IPV4_CAM_NOPORT] = 0; pkt_tcam_key[IPV4_CAM_TOS] = flow.src_node.tos; if (pkt_tcam_key[TCAM_CLS_CODE] == 8) // TCP pkt_tcam_key[IPV4_CAM_PID] = 6; else if (pkt_tcam_key[TCAM_CLS_CODE] == 9) // UDP pkt_tcam_key[IPV4_CAM_PID] = 17; else if (pkt_tcam_key[TCAM_CLS_CODE] == 10) { if (flow.frame.frame_class == CL_IP_SEC_ESP) // ESP pkt_tcam_key[IPV4_CAM_PID] = 50; else if (flow.frame.frame_class == CL_IP_SEC_AH) // AH pkt_tcam_key[IPV4_CAM_PID] = 51; } else if (pkt_tcam_key[TCAM_CLS_CODE] == 11) // SCTP pkt_tcam_key[IPV4_CAM_PID] = 132; if((pkt_tcam_key[TCAM_CLS_CODE]==8)||(pkt_tcam_key[TCAM_CLS_CODE]==9)||(pkt_tcam_key[TCAM_CLS_CODE]==12)||(pkt_tcam_key[TCAM_CLS_CODE]==13)){ // TCP, UDP pkt_tcam_key[IPV4_CAM_L4_SRC_PORT] = flow.tup.src_tcp_udp_port; pkt_tcam_key[IPV4_CAM_L4_DST_PORT] = flow.tup.dst_tcp_udp_port; } else if ((pkt_tcam_key[TCAM_CLS_CODE]==11)||(pkt_tcam_key[TCAM_CLS_CODE]==15)){ // SCTP pkt_tcam_key[IPV4_CAM_L4_SRC_PORT] = flow.sctp.src_sctp_port; pkt_tcam_key[IPV4_CAM_L4_DST_PORT] = flow.sctp.dst_sctp_port; } else if ((pkt_tcam_key[TCAM_CLS_CODE]==10)||(pkt_tcam_key[TCAM_CLS_CODE]==14)){ // AH, ESP pkt_tcam_key[IPV4_CAM_L4PT_SPI] = flow.src_node.spi; } pkt_tcam_key[IPV4_CAM_IP_ADDR_SA] = flow.src_node.ip_addr; pkt_tcam_key[IPV4_CAM_IP_ADDR_DA] = flow.dst_node.ip_addr; printf("predict_tcam_rdc V4: MAC%0d.%0d class 0x%h l2_rdc 0x%h noport %b tos 0x%h pid 0x%h L4_src 0x%h L4_dst 0x%h IPSA 0x%h IPDA 0x%h \n", mac_id, seq_id, pkt_tcam_key[TCAM_CLS_CODE],l2_rdc,pkt_tcam_key[IPV4_CAM_NOPORT],flow.src_node.tos, pkt_tcam_key[IPV4_CAM_PID], flow.tup.src_tcp_udp_port,flow.tup.dst_tcp_udp_port, pkt_tcam_key[IPV4_CAM_IP_ADDR_SA], pkt_tcam_key[IPV4_CAM_IP_ADDR_DA]); printf ("fflp_model::predict_tcam_rdc class %0d IPV4-TCAM entry prepared from PKT 0x%h\n", pkt_tcam_key[TCAM_CLS_CODE], pkt_tcam_key); } 12,13,14,15: { pkt_tcam_key[194:192] = 0; // RESERVED pkt_tcam_key[186:176] = 0; // RESERVED pkt_tcam_key[IPV6_CAM_L2RDC_TBL_NUM] = l2_rdc; pkt_tcam_key[IPV6_CAM_TOS] = flow.src_node.tos; if (pkt_tcam_key[TCAM_CLS_CODE] == 12) // TCP pkt_tcam_key[IPV6_CAM_NXT_HDR] = 6; else if (pkt_tcam_key[TCAM_CLS_CODE] == 13) // UDP pkt_tcam_key[IPV6_CAM_NXT_HDR] = 17; else if (pkt_tcam_key[TCAM_CLS_CODE] == 14) { if (flow.frame.frame_class == CL_IP_V6_SEC_ESP) // ESP pkt_tcam_key[IPV6_CAM_NXT_HDR] = 50; else if (flow.frame.frame_class == CL_IP_V6_SEC_AH) // AH pkt_tcam_key[IPV6_CAM_NXT_HDR] = 51; } else if (pkt_tcam_key[TCAM_CLS_CODE] == 15) // SCTP pkt_tcam_key[IPV6_CAM_NXT_HDR] = 132; fflp_class = find_class(flow.frame.frame_class); tcam_key_register = tcam_key_reg[fflp_class-4].tcam_ipaddr; pkt_tcam_key[IPV6_CAM_L4_SRC_PORT] = flow.tup.src_tcp_udp_port; pkt_tcam_key[IPV6_CAM_L4_DST_PORT] = flow.tup.dst_tcp_udp_port; if (tcam_key_register[0]) // tcam_ipaddr pkt_tcam_key[IPV6_CAM_IP_ADDR] = flow.src_node.ipv6_addr; else pkt_tcam_key[IPV6_CAM_IP_ADDR] = flow.dst_node.ipv6_addr; printf("predict_tcam_rdc V6: MAC%0d.%0d class 0x%h l2_rdc 0x%h tos 0x%h next_hdr 0x%h L4_src 0x%h L4_dst 0x%h IPADDR 0x%h\n", mac_id, seq_id, pkt_tcam_key[TCAM_CLS_CODE],l2_rdc,flow.src_node.tos,pkt_tcam_key[IPV6_CAM_NXT_HDR], flow.tup.src_tcp_udp_port,flow.tup.dst_tcp_udp_port, pkt_tcam_key[IPV6_CAM_IP_ADDR]); printf ("fflp_model::predict_tcam_rdc class %0d IPV6-TCAM entry prepared from PKT 0x%h\n", pkt_tcam_key[TCAM_CLS_CODE], pkt_tcam_key); } 16,17: { /* // For reference of the field locations flow[n].arp.hw_type = 1; flow[n].arp.proto_type = 16'h0800; flow[n].arp.hlen = 6; flow[n].arp.plen = 4; flow[n].arp.operation = 1; flow[n].arp.src_hw_addr = 48'habcdef000000+n; flow[n].arp.src_proto_addr = 32'hcafe0000+n; flow[n].arp.dst_hw_addr = 48'h123456000000+n; flow[n].arp.dst_proto_addr = 32'h56780000+n; bit [15:0] hw_type=1; // Hardware type (e.g., Ethernet-0x0001, Packet Radio Net.) bit [15:0] proto_type=16'h0800; // Protocol type (e.g., IP - 0x0800) bit [7:0] hlen=6; // byte length of each hardware address bit [7:0] plen=4; // byte length of each protocol address bit [15:0] operation=1; // opcode (e.g. REQ or REPLY) bit [47:0] src_hw_addr=0; // Hardware address of sender of this packet bit [31:0] src_proto_addr=0; // Protocol address of the sender bit [47:0] dst_hw_addr=0; // Hardware address of target of this packet (if known) bit [31:0] dst_proto_addr=0; // Protocol address of the target */ pkt_tcam_key[103:0] = 0; // initialize all reserved fields to 0 pkt_tcam_key[194:192] = 0; // initialize all reserved fields to 0 pkt_tcam_key[ETHERTYPE_EFRAME] = { flow.arp.src_hw_addr[31:24], flow.arp.src_hw_addr[39:32], flow.arp.src_hw_addr[47:40], flow.arp.operation[7:0], flow.arp.operation[15:8], flow.arp.plen, flow.arp.hlen, flow.arp.proto_type[7:0], flow.arp.proto_type[15:8], flow.arp.hw_type[7:0], flow.arp.hw_type[15:8] }; printf ("fflp_model::predict_tcam_rdc class %0d ETHER-TCAM entry prepared from PKT 0x%h\n", pkt_tcam_key[TCAM_CLS_CODE], pkt_tcam_key); } } for (i=0;i=0;j--) { if (j === 63) { flow_keyb_tmp = flow_keyb[i]; } else { flow_keyb_tmp = flow_keyb_tmp; } shtol_h1poly = shtol_h1poly << 1; if (shtol_h1poly[32] ^ flow_keyb_tmp[j]) { shtol_h1poly = {1'b0,(shtol_h1poly[31:0] ^ H1_CRC_32C_POLY)}; } else { shtol_h1poly = {1'b0, shtol_h1poly[31:0]}; } } } calculate_H1_hash = shtol_h1poly[31:0]; printf("fflp_model::calculate_H1_hash() CALCULATED H1 HASH = %h.\n",calculate_H1_hash); }