// ========== Copyright Header Begin ========================================== // // OpenSPARC T2 Processor File: pg_top_pp.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 ============================================ #include #include "pcg_defines.vri" #include "pcg_ports.vri" #include "pack_db.vrh" #include "flow_db.vrh" #include "flow_db_tasks.vrh" #include "mbox_class.vrh" #include "get_mbox_id.vrh" #include "cPgIf.vrh" #include "pcg_token.vrh" #include "cMesg.vrh" extern Mesg be_msg; // extern pack_db_entry pack_db[]; extern flow_db_entry flow_db[]; extern mbox_class mbox_id; extern integer quiet_on; extern class pg; extern pg ptr_to_first_pg; extern pg pack_gen[16]; extern "C" task InitpgSeed(integer seed); extern "C" function bit[31:0] pgRand(); class CpgRandom { bit[31:0] seed; task new(integer i) { InitpgSeed(i); } function bit[7:0] nextdata() { bit [31:0] d; d = pgRand(); nextdata = d[7:0]; } } class pg { local integer warning_count=0; local integer pg_done =0; local integer error_count=0; bit [3:0] port_type; local bit [63:0] clock_counter; local integer my_port; l3_class_desc l3_class[61]; l3_class_mask l3_mask[40]; local integer pckt_num= -1; local integer new_flow=0; local integer order_seq=0; local integer mb_q; local integer pkt_gen_sync; local integer queue_lock; static bit[19:0] pg_used_ports=0; bit [31:0] cfg_reg[CFG_LAST_ENTRY]; local bit [15:0] ifedx_control; local bit [63:0] last_tx_time; local bit [63:0] prev_current_time=0; //hummer local integer port_speed ; local integer mac_speed ; // local event pkt_gen_lock ; integer pkt_gen_lock; local integer tx_done=0; local integer wait_send_fake; local integer rxdv_set=0; local event pg_random_event; integer tx_err_start=-1; integer tx_err_len; integer debug_xgmii = 0; integer debug_gmii = 0; integer debug_mii = 0; integer debug_fa = 0; integer debug_mii_rx = 0; integer debug_mii_tx = 0; integer debug_xgmii_tx = 1; integer debug_xgmii_rx = 0; integer debug_gmii_rx = 0; integer debug_rx = 0; integer debug_dg = 0; integer debug_db_in = 0; integer debug_db_out = 0; integer debug_checker = 0; integer debug_out_token = 1; task config(integer what, bit [31:0] data) ; task print_warn() ; task print_err() ; task gen_buf( pack_db_entry pack_db, byte_array buf, var integer ptr ) ; function byte_array new_gen_buf(pack_db_entry pack_db, var bit[31:0] pkt_fields[*]); task pkt_gen( flow_desc flow, integer data_length, integer ttl, var CpgToken pgToken, ( bit[63:0] options=0) ); task pkt_auto_tx() ; task data_gen(integer type, integer seed, integer len, byte_array buf, var integer offset, bit[63:0] options,pg my_root, integer tagged, integer ifedx); task display_buf( byte_array buf, integer hwlen, (integer ifedx=0)) ; task display_class(byte_array buf, var integer ptr) ; task display_class_ipv6(byte_array buf, var integer ptr) ; task display_data(byte_array buf, var integer ptr, integer len) ; task display_id(bit [79:0] id) ; task display_db(pack_db_entry pack_db) ; task display_flow(integer flow_id) ; task send_packet(bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) ; task assert_col_tx (mii_def port_bind, bit [63:0] options) ; task assert_mii_err (mii_def port_bind ) ; task send_packet_mii (mii_def port_bind, bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) ; task assert_gmii_err (gmii_def port_bind) ; task send_packet_gmii (gmii_def port_bind, bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) ; task assert_xgmii_err (xgmii_def port_bind) ; task send_packet_xgmii (xgmii_def port_bind,bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) ; task wait_clk(integer count) ; task count_clock() ; task wait_tx_clk(integer count) ; task wait_tx_clk_if ( mii_def port_bind, integer count) ; task wait_rx_clk(integer count) ; task wait_rx_clk_if ( mii_def port_bind, integer count) ; task config_tx (mii_def port_bind, integer mac_speed ) ; task status() ; task new(integer my_porti, (bit [3:0] ptype=0)) ; task build_frame (integer itoken, pack_db_entry pack_db, byte_array buf, var integer len,(integer header_id=-1),(integer new_crc=0)); function bit [15:0] ipv4_cksum( byte_array m, integer len) ; function bit [15:0] ip_datagram_chksum(byte_array d, integer start, integer len); function bit [15:0] tcp_chksum( pack_db_entry pack_db, byte_array d, integer start, integer len, integer pkt_type,integer chk_sum_location ); function bit [31:0] crc_gen(byte_array p, integer start, integer len) ; local function bit [31:0] crc32_add(bit [7:0] data, bit [31:0] crc) ; function integer check_option(bit [63:0] option, bit [63:0] flag) ; function bit [7:0] class_mask(integer funct, bit[7:0] a, bit[7:0] b) ; function bit[15:0] partial_cksum(byte_array packet, integer start_offset, integer pkt_len); } task pg::gen_buf( pack_db_entry pack_db, byte_array buf, var integer ptr ) { integer len = -1; integer n; integer he; integer flow_id; integer ipv4_ptr; integer ipv6_ptr; integer tcp_hdr_start; integer udp_hdr_start; integer ip_hdr_start; integer extra_tcp_hdr=0; integer tcp_seg_len; bit [15:0] tcp_length; bit [15:0] udp_length; bit [15:0] ip_length; bit [15:0] ipv6_length; bit [15:0] l2_length; bit [31:0] tmp32, mask; bit [15:0] tmp16 ; bit [15:0] tmp16_ipck ; bit [15:0] tmp16_tcpck ; bit [15:0] tmp16_udpck ; bit [15:0] tmp16_ipdck ; bit [31:0] isn_tmp; bit [47:0] da_tmp; bit [95:0] tcp_psu_hdr; bit [95:0] udp_psu_hdr; bit [15:0] ipv4_hdr[10]; integer tagged = 0; bit [32:0] addr; bit dv; integer header_len_w_options; // List of inputs to this function passed through a struct bit[47:0] l2_da,l2_sa; bit [4:0] frame_type; integer tpid; bit [15:0] tci; integer frame_class; integer data_length; integer class_funct; integer frame_class_mask; integer header_length; integer ttl; bit [31:0] spi; bit [7:0] nxthdr; bit [7:0] tos; integer type; bit [128:0] src_ipv6_addr,dst_ipv6_addr; bit [31:0] src_ip_addr,dst_ip_addr; bit [15:0] src_port,dst_port; bit [5:0] tcp_flags; bit [31:0] rcv_isn; bit [31:0] last_seqno; integer data_type; integer data_seed; integer gId; integer chk_sum_location; bit [63:0] options; bit[15:0] llc_length; integer LLC_HACK= 1; // Assign the inputs here TMP only flow_id = pack_db.flow.flow_no; l2_da = pack_db.dst_node.l2_addr; l2_sa = pack_db.src_node.l2_addr; frame_type = pack_db.frame.frame_type; tpid = pack_db.frame.tpid; tci = pack_db.src_node.tci; frame_class = pack_db.frame.frame_class; data_length = pack_db.data_length; class_funct = pack_db.frame.class_funct; frame_class_mask = pack_db.frame.class_mask; header_length = pack_db.frame.header_length ; ttl = pack_db.ttl; spi = pack_db.src_node.spi; nxthdr = pack_db.src_node.nxthdr; tos = pack_db.src_node.tos; type = pack_db.frame.type; src_ipv6_addr = pack_db.src_node.ipv6_addr; dst_ipv6_addr = pack_db.dst_node.ipv6_addr; src_ip_addr = pack_db.src_node.ip_addr; dst_ip_addr = pack_db.dst_node.ip_addr; src_port = pack_db.tup.src_tcp_udp_port; dst_port = pack_db.tup.dst_tcp_udp_port; tcp_flags = pack_db.fl_state.tcp_flags; rcv_isn = pack_db.rx_param.rcv_isn; //last_seqno = flow_db[flow_id].tx_param.last_seqno; data_type = pack_db.frame.data_type; data_seed = pack_db.frame.data_seed; gId = pack_db.gId; options = pack_db.options; // DONE Assign the inputs here ptr=0; // L2 address '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = l2_da; '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = l2_sa; if( frame_type[2] ) { // 802.1Q 18 bytes long header tagged = 1; if( tpid != -1) // '{ buf.val[ptr++], buf.val[ptr++]} = tpid; else '{ buf.val[ptr++], buf.val[ptr++]} = TPID_8021Q; '{ buf.val[ptr++], buf.val[ptr++]} = tci; } if((frame_type[1] == 1) || (frame_type[4] == 1)) { // include ip header or tunneling options if( frame_type[0] == 1) { // if LLC SNAP IP Header len = ptr; ptr = ptr+2; if( check_option( pack_db.options, O_CUSTOM_LS) ) { tmp32 = cfg_reg[CFG_CUST_LS]; '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} = tmp32[23:0]; } else '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} = LLC_SNAP; buf.val[ptr++] = H_UNDEF; buf.val[ptr++] = H_UNDEF; buf.val[ptr++] = H_UNDEF; } else { len = - 1; } if( frame_type[3] == 1 && frame_class < CL_TCP_OPT ) // IPV6 Header frame_class += DELTA; if( frame_type[3] == 0 ) { // IPV4 Header if ( (frame_type[0] == 1 ) && (frame_type[2] == 1 )) { // LLC_SNAP and 802.1Q Tagged l2_length = 26; } else if (frame_type[2] == 1 ) { // ONLY 802.1Q Tagged l2_length = 18; } else if (frame_type[0] == 1 ) { // ONLY LLC_SNAP l2_length = 22; } else{ // NONE of the above l2_length = 14; } ip_length = data_length -4 -(l2_length) ; pack_db.ipp.ip_hdr_len = ip_length; printf("pg::gen_buf The IP length is %0h , ptr - %d \n", ip_length,ptr); for( n=0; n<2; n++) { buf.val[ptr++] = class_mask( class_funct, l3_class[frame_class].val[n], l3_mask[frame_class_mask].val[n] ); } // add header option field here buf.val[ptr] = class_mask( class_funct, l3_class[frame_class].val[2], l3_mask[frame_class_mask].val[2] ); if((buf.val[ptr] & 8'h40) == 8'h40) { // if IPV4 buf.val[ptr++] = 8'h40 | ( header_length & 4'hf) ; } buf.val[ptr++] = tos; buf.val[ptr++] = ip_length[15:8]; buf.val[ptr++] = ip_length[7:0]; for( n=6; n<12; n++) { // Fill in rest of the header bytes buf.val[ptr++] = class_mask( class_funct, l3_class[frame_class].val[n], l3_mask[frame_class_mask].val[n] ); } // This appears to be programmed by the user to override the automatically generated type field if(type != -1) // This should be moved up? .... '{buf.val[ptr-14], buf.val[ptr-13]} = type; // This should be moved up? .... if(ttl != -1) buf.val[ptr-2] = ttl; '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000; // 0s for header checksum '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = src_ip_addr; '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = dst_ip_addr; // Add options here header_len_w_options = ( (buf.val[ptr -20 /*14*/ ] & 8'h40 )== 8'h40) ? header_length : 0; printf(" DEBUG-- header_len_w_options - %d buf value - %x \n",header_len_w_options,buf.val[ptr -20 /*14*/ ] ); for(n=0;n< (4*header_len_w_options - 20); n++) { buf.val[ptr++] = 8'ha0 + n; // printf(" DEBUG-- ptr - %d val - %x \n",ptr,buf.val[ptr -1]); } tmp16_ipck = ipv4_cksum(buf,ptr); // Write back computed checksum '{buf.val[ptr-10 - (4*header_len_w_options - 20) ],buf.val[ptr-9 - (4*header_len_w_options - 20) ]} = tmp16_ipck; if( frame_class == CL_IP_SEC_ESP) { '{buf.val[ptr++],buf.val[ptr++],buf.val[ptr++],buf.val[ptr++]} = spi; '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000; '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000; '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000; '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000; } if( frame_class == CL_IP_SEC_AH) { //buf.val[ptr++] = 8'h06;//Assumes TCP buf.val[ptr++] = nxthdr; buf.val[ptr++] = 8'h03;//LenHdr-2 (32bit Words) '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000; '{buf.val[ptr++],buf.val[ptr++],buf.val[ptr++],buf.val[ptr++]} = spi; '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000; '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000; } } // endif IPV4 packet else if ( frame_type[3] == 1 ) { // IPV6 Packet // printf("pcg_fa.vr: Bulding IPv6 Packet \n"); if( (frame_type[2] == 1 ) && (frame_type[0] == 1)) { l2_length = 26; } else if (frame_type[2] == 1 ) { l2_length = 18; } else if (frame_type[0] == 1 ) { l2_length = 22; } else{ l2_length = 14; } ipv6_length = data_length - 40 -4 -(l2_length); pack_db.ipp.ip_hdr_len = ipv6_length; printf("pg::gen_buf The val of ip_length is %0d\n",ipv6_length); for( n=0; n<2; n++) buf.val[ptr++] = class_mask( class_funct, l3_class[frame_class].val[n], l3_mask[frame_class_mask].val[n] ); buf.val[ptr++] = {4'h6,tos[7:4]}; buf.val[ptr++] = {tos[3:0],4'h0}; for( n=4; n<6; n++) buf.val[ptr++] = class_mask( class_funct, l3_class[frame_class].val[n], l3_mask[frame_class_mask].val[n] ); buf.val[ptr++] = ipv6_length[15:8]; buf.val[ptr++] = ipv6_length[7:0]; for( n=8; n<10; n++) buf.val[ptr++] = class_mask( class_funct, l3_class[frame_class].val[n], l3_mask[frame_class_mask].val[n] ); if(type != -1) '{buf.val[ptr-10], buf.val[ptr-9]} = type; if(ttl != -1) buf.val[ptr-1] = ttl; '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = src_ipv6_addr; '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = dst_ipv6_addr; if( frame_class == CL_IP_V6_SEC_ESP) { '{buf.val[ptr++],buf.val[ptr++],buf.val[ptr++],buf.val[ptr++]} = spi; '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000; '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000; '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000; '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000; } if( frame_class == CL_IP_V6_SEC_AH) { buf.val[ptr++] = 8'h06;//Assumes TCP buf.val[ptr++] = 8'h03;//LenHdr-2 (32bit Words) '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000; '{buf.val[ptr++],buf.val[ptr++],buf.val[ptr++],buf.val[ptr++]} = spi; '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000; '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000; } } // endif IPV6 printf("pg::gen_buf : Frame_class: %d frame_type - %x \n" , frame_class,frame_type ); if( frame_class == CL_UDP | frame_class == CL_UDP_OPT | frame_class == CL_UDP_FRAG | frame_class == CL_UDP_IP_V6 | frame_class == CL_UDP_OPT_IP_V6 | frame_class == CL_UDP_FRAG_IP_V6 ) { if ( frame_type[3] == 1 ) { // IPV6 udp_length = data_length - 40 -4 -(l2_length); } if( frame_type[3] == 0 ) { // IPV4 udp_length = data_length - (4*header_len_w_options) -4 -(l2_length); // printf("DEBUG udp length - %d \n",udp_length); } udp_psu_hdr = {src_ip_addr, dst_ip_addr, 8'h00,8'h17,udp_length}; udp_hdr_start = ptr ; pack_db.psu_hdr= (udp_psu_hdr); '{ buf.val[ptr++], buf.val[ptr++] } = src_port; '{ buf.val[ptr++], buf.val[ptr++] } = dst_port; buf.val[ptr++] = udp_length[15:8]; buf.val[ptr++] = udp_length[7:0]; '{ buf.val[ptr++], buf.val[ptr++] } = 16'h00; }/*endif CL_UDP*/ else if ( frame_class == CL_TCP | frame_class == CL_TCP_OPT | frame_class == CL_TCP_FRAG | frame_class == CL_TCP_IP_V6 | frame_class == CL_TCP_OPT_IP_V6 | frame_class == CL_TCP_FRAG_IP_V6 ) { //printf("pcg_fa.vr: Adding TCP Header \n"); tcp_psu_hdr = {src_ip_addr, dst_ip_addr, 8'h00,8'h06,16'h0000}; pack_db.psu_hdr= (tcp_psu_hdr); tcp_hdr_start = ptr ; '{ buf.val[ptr++], buf.val[ptr++] } = src_port; '{ buf.val[ptr++], buf.val[ptr++] } = dst_port; if( tcp_flags == 2'h2 ) { '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = rcv_isn; } else { '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = flow_db[flow_id].tx_param.last_seqno; flow_db[flow_id].rx_param.rcv_isn = flow_db[flow_id].tx_param.last_seqno; } if(frame_class != CL_TCP_OPT & frame_class != CL_TCP_OPT_IP_V6) { cfg_reg[CFG_TCP_LEN] = 4'b0101; } '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = cfg_reg[CFG_TCP_ACK]; tmp32[15:0] = {cfg_reg[CFG_TCP_LEN], 6'b000000, tcp_flags} ; '{ buf.val[ptr++], buf.val[ptr++] } = tmp32[15:0]; tmp32 = cfg_reg[CFG_TCP_WIN]; '{ buf.val[ptr++], buf.val[ptr++] } = tmp32[15:0]; '{ buf.val[ptr++], buf.val[ptr++] } = 16'h00; tmp32 = cfg_reg[CFG_TCP_URG]; '{ buf.val[ptr++], buf.val[ptr++] } = tmp32[15:0]; //TCP option if ( (cfg_reg[CFG_TCP_LEN] ) > 5 ) { extra_tcp_hdr = (cfg_reg[CFG_TCP_LEN] - 5 ) * 4; pack_db.mac.extra_tcp_hdr = extra_tcp_hdr; for ( n =0; n< extra_tcp_hdr; n++) { buf.val[ptr++] = 8'ha5; } } else { extra_tcp_hdr = 0; pack_db.mac.extra_tcp_hdr = extra_tcp_hdr; } } // endif CL_TCP* } // endif include ip header or tunneling option else { printf("pg::gen_buf : No L3 header selected\n"); if( frame_type[0] == 1) { // LLC_SNAP len = ptr; ptr = ptr+2; if( check_option( pack_db.options, O_CUSTOM_LS) ) { tmp32 = cfg_reg[CFG_CUST_LS]; '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} = tmp32[23:0]; } else '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} = LLC_SNAP; buf.val[ptr++] = H_UNDEF; buf.val[ptr++] = H_UNDEF; buf.val[ptr++] = H_UNDEF; '{buf.val[ptr++],buf.val[ptr++]} = 16'h0008; } else { len = ptr; ptr = ptr+2; } } // endif else of include ip header he = ptr-1; // header length tcp_length = data_length -he -4; tcp_seg_len = data_length - ptr - 4; if(data_type != DAT_FC_PAUSE) '{buf.val[ptr++], buf.val[ptr++]} = gId; if(LLC_HACK & ( (pack_db.frame.frame_type== 5'h3 )| (pack_db.frame.frame_type== 5'h7) )) { printf("gen_buf LLC_HACK!!! data_len - %d \n",pack_db.data_length); if(pack_db.flow.frame.frame_type== 5'h3) { llc_length = pack_db.data_length - 4/*CRC*/ - 12/*L2HEADERS*/ -2/*Type/Length*/ ; buf.val[12] = llc_length[15:8]; buf.val[13] = llc_length[7:0]; } else { llc_length = pack_db.data_length - 4/*CRC*/ - 12/*L2HEADERS*/ -4/*VLAN ID*/ -2/*Type/Length*/ ; buf.val[16] = llc_length[15:8]; buf.val[17] = llc_length[7:0]; } } /* Generate data payload */ data_gen(data_type, data_seed, data_length, buf, ptr, pack_db.options, this, tagged, INTER_FEDX); // printf("DEBUG--- After data_gen len - %d \n",len); // printf("DEBUG---type - %d %d %d \n",type,ptr, he); // Add L2 Length here if( len > 0 ) { if( check_option( pack_db.options, O_FRM_LEN_ERR1) ) '{buf.val[len], buf.val[len+1] } = cfg_reg[CFG_FRM_LEN]; else { if(type == -1) { '{buf.val[len], buf.val[len+1] } = ptr - (he+1); } else '{buf.val[len], buf.val[len+1] } = type; } } if( frame_class == CL_TCP | frame_class == CL_TCP_OPT | frame_class == CL_TCP_FRAG | frame_class == CL_TCP_IP_V6 | frame_class == CL_TCP_OPT_IP_V6 | frame_class == CL_TCP_FRAG_IP_V6 ) { // Calculate TCP checksum flow_db[flow_id].data_length = tcp_seg_len; flow_db[flow_id].tx_param.last_seqno = (flow_db[flow_id].rx_param.rcv_isn) + flow_db[flow_id].data_length; chk_sum_location = he-extra_tcp_hdr-3; tmp16_tcpck = tcp_chksum(pack_db,buf,tcp_hdr_start,ptr,1, chk_sum_location ); printf("gen_buf-- tcp_chksum - %x tcp_hdr_start - %d chk_sum_location - %d \n",tmp16_tcpck,tcp_hdr_start,chk_sum_location); if( check_option( pack_db.options, O_TCPCKSUM_ERR) ){ tmp16_tcpck = tmp16_tcpck ^ cfg_reg[CFG_TCPCKSUM_MASK]; } '{buf.val[he-extra_tcp_hdr-3],buf.val[he-extra_tcp_hdr-2]} = tmp16_tcpck; pack_db.ipp.tcp_cksum = tmp16_tcpck; } // C if(frame_class == CL_UDP | frame_class == CL_UDP_OPT | frame_class == CL_UDP_FRAG | frame_class == CL_UDP_IP_V6 | frame_class == CL_UDP_OPT_IP_V6 | frame_class == CL_UDP_FRAG_IP_V6 ) { // Calculate UDP checksum chk_sum_location = he -1; tmp16_udpck = tcp_chksum(pack_db,buf,udp_hdr_start,ptr,0,chk_sum_location); printf("gen_buf-- udp_chksum - %x udp_hdr_start - %d chk_sum_location - %d \n",tmp16_udpck,udp_hdr_start,chk_sum_location); '{buf.val[he-1],buf.val[he-0]} = tmp16_udpck; } ip_hdr_start = l2_length ; if (frame_type[1] == 1) { // IPV4 tmp16_ipdck =ip_datagram_chksum(buf,ip_hdr_start,ptr); pack_db.ipp.ip_datagram_cksum = tmp16_ipdck; } pack_db.add_header(buf,0,he); if(LLC_HACK & ( (pack_db.frame.frame_type== 5'h3 )| (pack_db.frame.frame_type== 5'h7) )) { printf("LLC_HACK!!! \n"); if(pack_db.flow.frame.frame_type== 5'h3) { llc_length = pack_db.data_length - 4/*CRC*/ - 12/*L2HEADERS*/ -2/*Type/Length*/ ; buf.val[12] = llc_length[15:8]; buf.val[13] = llc_length[7:0]; } else { llc_length = pack_db.data_length - 4/*CRC*/ - 12/*L2HEADERS*/ -4/*VLAN ID*/ -2/*Type/Length*/ ; buf.val[16] = llc_length[15:8]; buf.val[17] = llc_length[7:0]; } } tmp32 = crc_gen(buf, 0, ptr); if( check_option( pack_db.options, O_CRC_ERR) ) tmp32 = tmp32 ^ cfg_reg[CFG_CRC_MASK]; '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = tmp32; pack_db.pack_crc = tmp32; pack_db.frame_len = ptr; // printf(" end of gen_buf - ptr - %d \n",ptr); } function bit [15:0] pg::ipv4_cksum( byte_array m, integer len){ integer i,j; bit [15:0] tmp[]; bit [31:0] cksum; j = len -20; cksum = 0; printf ("pg::ipv4_cksum: The val of len is %d\n",len); for ( i=j; i< (j+20); i=i+2) { tmp[i] = {m.val[i], m.val[(i+1)]}; // printf("The val of buffer is %0h\n",tmp[i]); cksum = cksum + tmp[i]; if (cksum[16] ==1) { cksum = cksum[15:0] + 1; } } ipv4_cksum = ~cksum; printf(" pg::ipv4_cksum: chksum - %x \n",ipv4_cksum); } function bit [15:0] pg::ip_datagram_chksum( byte_array d, \ integer start, integer len){ integer i,j,k; bit [15:0] tmp[]; bit [31:0] ipsum; integer ip_len; integer pad; ip_len = len - start; ipsum = 0; printf ("pg::ip_datagram_chksum: The val of ip hdr start and len is %0d and %0d\n", start,len); if (ip_len %2 != 0) { pad =1; }else { pad = 0; } for (i=start;i 15 ) { printf("pg::pkt_gen: WARNING: PG: Port %0d is invalid (only used to satisfy fflp testsuite).\n",my_port); printf("pg::pkt_gen: No action is taken.\n"); return; } pckt_num++; token = pckt_num; // TOADS if (flow.fl_state.tcp_flags == 6'h02) new_flow++; case({ check_option(options, O_ORDER_START), check_option(options, O_ORDER_CONT), check_option(options, O_ORDER_END) }) { 3'b100: order_seq = 0; 3'b010: order_seq++; 3'b001: order_seq++; } if(flow.src_node.src_port[my_port] != 1) { print_warn(); printf("pg::pkt_gen PG: Specified src_node may not be used as source for this port. Continuing anyway ...\n"); } pack_db = new(pckt_num ); pack_db.preamble_cnt = flow.preamble_cnt; pack_db.sfd = flow.sfd; // printf("DEBUG pack_db.options - %x preamble_cnt - %d sfd - %d \n",pack_db.options,pack_db.preamble_cnt,pack_db.sfd); pg_done = 0; id = pack_db.add(my_port, flow, flow.frame, flow.src_node, flow.dst_node, flow.tup, flow.rx_param, flow.tx_param, flow.fl_state, data_length,ttl, options | flow.options , order_seq, pckt_num, ifedx_control); pack_db.port_type = port_type; if( pack_db.fl_state.tcp_flags == 2'h2 ) { // TOADS flow_db_add_entry( my_port, data_length, flow, flow.tup, flow.rx_param, flow.tx_param, flow.fl_state, options, current_flow_num ); } if(debug_db_in) display_db(pack_db); wait_send_fake=0; // TOADS--- printf("Before mailbox_put mb_q - time - %d \n",{get_time(HI),get_time(LO)}); mailbox_put(mb_q, pack_db); printf("pg::pkt_gen: Waiting for packet to go out ...(port type: %h), token# %0d\n",port_type, token); printf("pg::pkt_gen: Waiting for packet to go out wait_send_fake - %d Time - %d \n",wait_send_fake,{get_time(HI),get_time(LO)}); printf("pg::pkt_gen: Waiting for packet to go oui options - %d Time - %d \n", pack_db.options,{get_time(HI),get_time(LO)}); if( check_option( pack_db.options, O_WAIT_SEND_FAKE) ) { while(wait_send_fake==0) @(posedge CLOCK); } if( check_option( pack_db.options, O_WAIT_SEND) ) { fork while(time_out<10000) { wait_rx_clk(1); time_out++; } while(pg_done!=1) @(posedge CLOCK); join any printf("pg::pkt_gen: before terminate timeout - %d pg_done - %d \n",time_out,pg_done); terminate; if(pg_done!=1) { pg_done=1; print_warn(); printf("PG: Timed out waiting for done bit (waited %0d cycles)...\n",time_out); printf(" This only happens with fake ports when we wait for someone\n"); printf(" to acknowladge that the packet was processed (Port: %0d).\n",my_port); printf(" Token: %0d, Time: %0d\n",token,{get_time(HI),get_time(LO)}); } } pgToken = new (id); pgToken.pack_db = new pack_db; pgToken.port_id = my_port; mailbox_get(WAIT,pkt_gen_sync,tmpbuf); pgToken.buf = new tmpbuf; // display_buf(pgToken.buf,data_length); // printf(" in pkt_gen -- length - %d \n", pack_db.header_len[0]); printf("pg::pkt_gen: Waiting End of pkt_gen !!! Time - %d \n",{get_time(HI),get_time(LO)}); // trigger(ON,pkt_gen_lock); semaphore_put(pkt_gen_lock,1); } function byte_array pg::new_gen_buf(pack_db_entry pack_db, var bit[31:0] pkt_fields[*]){ bit [7:0] payload[*]; integer i,size; CPgIf cPg; integer len; byte_array buf; cPg = new(); len = pack_db.data_length; printf("byte_array pg::new_gen_buf function id - %d !! Time - %d \n",my_port,{get_time(HI),get_time(LO)}); cPg.genPacket(0,len, pack_db.flow, payload,pkt_fields); buf = new(); for( i = 0; i < len + pack_db.flow.frame.l2_pad_length;i++) { buf.val[i] = payload[i] & 8'hff; // printf(" PKT buf - %x index - %d \n", buf.val[i],i); } new_gen_buf = buf; } task pg::pkt_auto_tx() { integer len; byte_array buf; integer token; pack_db_entry pack_db; event lock_send_packet; CpgToken pgToken; byte_array tmpbuf; bit[31:0] pkt_fields[*] ; integer i; trigger(ON,lock_send_packet); while(1) { sync(ALL,lock_send_packet); trigger(OFF,lock_send_packet); printf(" Before mailbox_get mb_q Time - %d \n",{get_time(HI),get_time(LO)} ); mailbox_get(WAIT, mb_q, pack_db); printf(" After mailbox_get mb_q Time - %d \n",{get_time(HI),get_time(LO)} ); if(debug_db_out) display_db(pack_db); buf = new(); // gen_buf( pack_db, buf, len ); len = pack_db.data_length + pack_db.flow.frame.l2_pad_length; buf = new_gen_buf(pack_db,pkt_fields); wait_send_fake=1; pgToken = new (pack_db.gId); pgToken.pack_db = new pack_db; pgToken.port_id = my_port; pgToken.pkt_fields = new[SIZE_OF_PKT_FIELDS]; for(i=0;i16) adj_len += 6; if(pack_db.org_port>16 & my_port<17) adj_len -= 6; if(debug) printf("DEBUG: build_frame: adj_len: %0d\n",adj_len); if( pack_db.frame.frame_type[2] ) tagged = 1; if(debug) printf("DEBUG: build_frame: (3)ptr: DAT_LEN_EXACT: %0d\n", check_option(pack_db.frame.data_type, DAT_LEN_EXACT) ); if(pack_db.data_length<0) { case(pack_db.data_length) { -1: pack_db.data_length = 64; -2: pack_db.data_length = 128; -3: pack_db.data_length = 256; -4: pack_db.data_length = 512; -5: pack_db.data_length = 1024; -6: pack_db.data_length = (tagged) ? 1522 : 1518; -7: { // pack_db.data_length = random(pack_db.frame.data_seed); // Vera supports only one random pack_db.data_length = random(); min = 64; max = (tagged) ? 1522 : 1518; while(pack_db.data_lengthmax) pack_db.data_length = random(); } -8: pack_db.data_length = 63; -9: pack_db.data_length = 65; -10: pack_db.data_length = (tagged) ? 1521 : 1517; -11: pack_db.data_length = (tagged) ? 1523 : 1519; } pack_db.frame.data_type = pack_db.frame.data_type | DAT_LEN_EXACT; } if( check_option(pack_db.frame.data_type, DAT_LEN_EXACT) ) { // Convert exact length to actual data length, clear exact flag and use that data length from now on. // data_len = pack_db.data_length + header_len - pack_db.header_len[0] + adj_len; data_len = pack_db.data_length - header_len - 4; // data_len - header_len - crc_len if(INTER_FEDX) data_len = data_len - 6; pack_db.data_length = data_len; pack_db.frame.data_type = pack_db.frame.data_type & DAT_TYPE_MASK; } else data_len = pack_db.data_length; if(debug) printf("DEBUG: build_frame: (3)ptr: %0d\n",ptr); if(debug) printf("DEBUG: build_frame: data_len: %0d\n",data_len); if(LLC_HACK & ( (pack_db.frame.frame_type== 5'h3 )| (pack_db.frame.frame_type== 5'h7) )) { printf(" build_frame LLC_HACK!!! data_len - %d \n",pack_db.data_length); if(pack_db.flow.frame.frame_type== 5'h3) { llc_length = ( pack_db.data_length + header_len + 4) - 4/*CRC*/ - 12/*L2HEADERS*/ -2/*Type/Length*/ ; buf.val[12] = llc_length[15:8]; buf.val[13] = llc_length[7:0]; } else { llc_length = ( pack_db.data_length + header_len + 4) - 4/*CRC*/ - 12/*L2HEADERS*/ -4/*VLAN ID*/ -2/*Type/Length*/ ; buf.val[16] = llc_length[15:8]; buf.val[17] = llc_length[7:0]; } } if( pack_db.frame.frame_type[2] ) tagged = 1; data_gen( pack_db.frame.data_type, pack_db.frame.data_seed, data_len, buf, ptr, pack_db.options, this, tagged, INTER_FEDX); if(debug) printf("DEBUG: build_frame: (4)ptr: %0d\n",ptr); if(INTER_FEDX) tmp32 = crc_gen(buf, 2, ptr); // Skip Interfedx Control Word else tmp32 = crc_gen(buf, 0, ptr); if( check_option( pack_db.options, O_CRC_ERR) ) tmp32 = tmp32 ^ cfg_reg[CFG_CRC_MASK]; if(!new_crc) '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = pack_db.pack_crc; else { if ( (org_port==17) | (org_port==18) ) { if(INTER_FEDX) { '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = pack_db.pack_crc; } else { tx_status = pack_db.mac.tx_status; if(tx_status[14]) '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = pack_db.pack_crc; else '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = tmp32; } } //end of if ( (org_port==17) | (org_port==18) ) else { if(INTER_FEDX) '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = pack_db.pack_crc; else '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = tmp32; } } if(debug) printf("DEBUG: build_frame: (5)ptr: %0d\n",ptr); if(debug) printf("DEBUG: build_frame: Done.\n"); len = ptr; // display_buf( buf,len); } task pg::data_gen(integer type, integer seed, integer len, byte_array buf, var integer offset, bit[63:0] options, pg my_root, integer tagged, integer ifedx) { integer min,max,n,o,b,l; bit [15:0] tmp16; bit [7:0] tmp8,s; integer exact_len; CpgRandom pg_random; integer debug_dg = 0; if(debug_dg) printf("DEBUG: pg::data_gen: input: type: %0d (%h), len: %0d, offset: %0d, tagged: %0d, ifedx: %0d\n", type,type,len,offset,tagged,ifedx); exact_len = (type & DAT_LEN_EXACT) ? 1 : 0; exact_len = ptr_to_first_pg.check_option(type, DAT_LEN_EXACT); type = type & DAT_TYPE_MASK; if(len<0) exact_len = 1; case(len) { -1: len = 64; -2: len = 128; -3: len = 256; -4: len = 512; -5: len = 1024; -6: len = (tagged) ? 1522 : 1518; -7: { // len = random(seed); len = random(); min = 64; max = (tagged) ? 1522 : 1518; while(lenmax) len = random(); } -8: len = 63-offset-4; -9: len = 65-offset-4; -10: len = (tagged) ? 1521 : 1517; -11: len = (tagged) ? 1523 : 1519; } if(exact_len) { len = len-offset-4; if(ifedx) len = len - 4; } else len = len - 2; if(len<0) { len = 0; if(!quiet_on) printf("PG[%0d]: WARNING: Data length (payload) is zero.\n",my_port); be_msg.print(e_mesg_error, "pg::date_gen", "", "PG[%0d]: Data length (payload) is zero TESTBENCH ERROR \n", my_port); } o=offset; b = seed; if( my_root != null & check_option(options, O_FRM_LEN_ERR2) ) len = cfg_reg[CFG_FRM_LEN] - offset -4; if(debug_dg) printf("DEBUG: pg::data_gen: offset: %0d, len: %0d type: %0d\n",o,len,type); l = 1; case(type) { DAT_RAND:{ sync(ALL,pg_random_event); trigger(OFF,pg_random_event); pg_random = new(seed); for(n=0;n7) tmp8[15-b++] = 1; } if(b>15) b = 0; buf.val[offset++] = tmp8; } DAT_W0: for(n=0;n7) tmp8[15-b++] = 0; } if(b>15) b = 0; buf.val[offset++] = tmp8; } DAT_FC_PAUSE: { len = 64-offset-4; o = offset; for(n=0;n 64'h0) check_option = 1; else check_option = 0; } function bit [7:0] pg::class_mask(integer funct, bit[7:0] a, bit[7:0] b) { case(funct) { CLF_SRC: class_mask = a; CLF_DST: class_mask = b; CLF_OR: class_mask = a && b; CLF_AND: class_mask = a || b; default: class_mask = 8'h00; } } task pg::send_packet(bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) { integer n; case(my_port) { 0: { if (port_speed == 4) send_packet_xgmii (xgm0,ptype, buf, len, options); else if (port_speed == 3) send_packet_gmii (gm0, ptype, buf, len, options); else send_packet_mii (m0,ptype, buf, len, options); } 1: { if (port_speed == 4) send_packet_xgmii (xgm1,ptype, buf, len, options); else if (port_speed == 3) send_packet_gmii (gm1, ptype, buf, len, options); else send_packet_mii (m1, ptype, buf, len, options); } 2: { if (port_speed == 3) send_packet_gmii (gm2, ptype, buf, len, options); else send_packet_mii (m2, ptype, buf, len, options); } 3: { if (port_speed == 3) send_packet_gmii (gm3, ptype, buf, len, options); else send_packet_mii (m3, ptype, buf, len, options); } } } task pg::assert_col_tx (mii_def port_bind, bit [63:0] options) { integer itmp; while(rxdv_set == 0) @(posedge port_bind.$rxclk); if( check_option( options, O_RX_COL) & cfg_reg[CFG_COL_LEN]>0 & !tx_done ) { itmp = cfg_reg[CFG_COL_DEL]; while(itmp>0 & !tx_done) { itmp--; @(posedge port_bind.$rxclk); } port_bind.$rxcol = 1 async; itmp = cfg_reg[CFG_COL_LEN]; while(itmp>0 & !tx_done) { itmp--; @(posedge port_bind.$rxclk); } port_bind.$rxcol = 0 async; } } task pg::assert_mii_err (mii_def port_bind ) { integer cnt=0; if(tx_err_start==-1) return; if(tx_err_len<1) { printf("PG: WARNING: tx_err injection length to short. (Start: %0d, Length: %0d)\n", tx_err_start,tx_err_len); return; } while(cnt++ < tx_err_start & !tx_done) @(posedge port_bind.$rxclk); if(!tx_done) { port_bind.$rxerr = 1; cnt=0; while(cnt++ < tx_err_len & !tx_done) @(posedge port_bind.$rxclk); port_bind.$rxerr = 0; } else printf("PG: WARNING: Packet was sent before tx_err could be assrted.(Start: %0d, Length: %0d)\n", tx_err_start,tx_err_len); tx_err_start = -1; } task pg::send_packet_mii (mii_def port_bind, bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) { integer n, cnt; bit [7:0] tmp; bit [63:0] current_time; bit [63:0] min_gap, time_tmp; tx_done = 0; if(debug_mii==1) printf("DEBUG: PG low tx started: current_time: %0d\n", {get_time(HI),get_time(LO)} ); current_time = {get_time(HI),get_time(LO)}; if(port_speed==1) min_gap = 800 * MII_IP_GAP; else min_gap = 80 * MII_IP_GAP; time_tmp = current_time - last_tx_time; if(debug_mii_tx) printf("DEBUG: PG low tx: last_time: %0d, current_time: %0d, diff: %0d\n", last_tx_time,current_time,time_tmp); if((time_tmp < min_gap) & !check_option(options, O_NO_IP_GAP_FIX) & !check_option(options, O_CUSTOM_IP_GAP) ) { time_tmp = min_gap - time_tmp; if(debug_mii_tx) printf("DEBUG: PG low tx: Min_gap: %0d, gap_diff: %0d\n",min_gap,time_tmp); if(port_speed==1) time_tmp = time_tmp / 400; else time_tmp = time_tmp / 40; if(debug_mii_tx) printf("DEBUG: PG low tx: waiting additional %0d cycles\n",time_tmp); repeat(time_tmp) @(posedge port_bind.$rxclk); } else if( check_option(options, O_CUSTOM_IP_GAP) ) { repeat(cfg_reg[CFG_IP_GAP]) @(posedge port_bind.$rxclk); } fork { // assert_mii_err (get_bind( port_bind )); assert_mii_err ( port_bind ); } join none port_bind.$rxdv = 1; rxdv_set = 1; if( check_option(options, O_PREAMB_ERR) ) cnt = cfg_reg[CFG_PRAMB_CNT]; else cnt = 7; for(n=0;n>>>>>>>>>>>>>>> //first calculate where the align point is? align_cycles = 4-(((current_time-prev_current_time))%4); //see if the align point is beyond IPG //if so, lets move the IPG to align point if(align_cycles >= ipg_clock_diffs) { ipg_clock_diffs = align_cycles; need_extra_clocks = 1; } else //if align is before IPG, we need to go to next align point //this next align point is 4-(difference of the current align-ipg) if(align_cycles < ipg_clock_diffs) { //also make sure the IPG is not a multiple of next align if((ipg_clock_diffs-align_cycles)%4) ipg_clock_diffs += 4-(ipg_clock_diffs-align_cycles)%4; } //////////////////align logic<<<<<<<<<<<<<<<< if(debug_mii_tx) printf("DEBUG: PG low tx: last_time: %0d, current_time: %0d, diff: %0d\n", last_tx_time,current_time,time_tmp); if( !check_option(options, O_NO_IP_GAP_FIX) & !check_option(options, O_CUSTOM_IP_GAP) & need_extra_clocks ) { repeat(ipg_clock_diffs) @(posedge port_bind.$rxclk); } else if( check_option(options, O_CUSTOM_IP_GAP) ) { repeat(cfg_reg[CFG_IP_GAP]) @(posedge port_bind.$rxclk); } fork // assert_gmii_err (get_bind( port_bind)); assert_gmii_err ( port_bind); join none prev_current_time = clock_counter; //port_bind.$rxd = XGMII_SOP; port_bind.$rxdv = 1; /* @(posedge port_bind.$rxclk); */ if( check_option(options, O_PREAMB_ERR) ) cnt = cfg_reg[CFG_PRAMB_CNT]; else cnt = 7; for(n=0;n>>>>>>>>>>>>>>> //first calculate where the align point is? align_cycles = 4-(((current_time-prev_current_time))%4); //see if the align point is beyond IPG //if so, lets move the IPG to align point if(align_cycles >= ipg_clock_diffs) { ipg_clock_diffs = align_cycles; need_extra_clocks = 1; } else //if align is before IPG, we need to go to next align point //this next align point is 4-(difference of the current align-ipg) if(align_cycles < ipg_clock_diffs) { //also make sure the IPG is not a multiple of next align if((ipg_clock_diffs-align_cycles)%4) ipg_clock_diffs += 4-(ipg_clock_diffs-align_cycles)%4; } //////////////////align logic<<<<<<<<<<<<<<<< printf("pg::send_packet_xgmii: DEBUG--len - %d \n",len); printf("pg::send_packet_xgmii: DEBUG--IPG ipg_diff - %d ipg_clock_diffs - %d need_extra_clocks - %d \n",ipg_diffs,ipg_clock_diffs,need_extra_clocks); if(debug_xgmii_tx) printf("DEBUG: PG low tx: last_time: %0d, current_time: %0d, diff: %0d options = %x \n", last_tx_time,current_time,time_tmp,options); if( !check_option(options, O_NO_IP_GAP_FIX) & !check_option(options, O_CUSTOM_IP_GAP) & need_extra_clocks ) { repeat(ipg_clock_diffs) @(posedge port_bind.$rxclk_int); } else if( check_option(options, O_CUSTOM_IP_GAP) ) { repeat(cfg_reg[CFG_IP_GAP]) @(posedge port_bind.$rxclk_int); } fork // assert_xgmii_err (get_bind( port_bind ) ); assert_xgmii_err (port_bind ); join none port_bind.$rxdv = 1; // prev_current_time = {get_time(HI),get_time(LO)}; //hummer prev_current_time = clock_counter; port_bind.$rxd = XGMII_SOP; port_bind.$rxdv = 1; @(posedge port_bind.$rxclk_int); if( check_option(options, O_PREAMB_ERR) ) cnt = cfg_reg[CFG_PRAMB_CNT]; else cnt = 6; for(n=0;n15) { printf("PG: INIT: Warning: Port %0d is invalid or out of range.\n", my_port); } if(!quiet_on) printf("INFO: Packet Generator attaching to port %0d\n",my_port); if(pg_used_ports[my_port] == 1) { printf("PG: INIT: Port %0d already in use.\n", my_port); terminate; } pg_used_ports[my_port] = 1; for(n=0;n<60;n++) { l3_class[n] = new; } for(n=0;n<40;n++) { l3_mask[n] = new; } queue_lock = alloc(SEMAPHORE,0,1,1); if(queue_lock == 0) { printf("PG: INIT: Could not allocate spaphore queue_lock.\n"); } mb_q = alloc(MAILBOX, 0, 1); pkt_gen_sync = alloc(MAILBOX, 0, 1); if(mb_q == 0) { printf("PG: INIT: Could not allocate mailbox mb_q.\n"); } mbox_id.pg_mb[my_port] = alloc(MAILBOX, 0, 1); if(mbox_id.pg_mb[my_port] == 0) { printf("PG: INIT: Could not allocate mailbox mbox_id.pg_mb[%0d].\n",my_port); } fork pkt_auto_tx(); join none if(ptr_to_first_pg==null) ptr_to_first_pg = this; last_tx_time = {get_time(HI),get_time(LO)}; for(n=0;n5)) { ipv4_header_length = (buf.val[ptr] & 8'hf); token = { buf.val[ptr + ( (4*ipv4_header_length) -20 ) ], buf.val[ptr + ( (4*ipv4_header_length) -20 ) +1] }; } else token = { buf.val[ptr], buf.val[ptr+1] }; printf(" DEBUG- token - %d \n",token); if((len>16'h0600 & len != CNTL_FRAME) || ((len == RARP_FRAME) &(len != CNTL_FRAME))){ len = -1; // ptr here points to the first byte of ip datagram if((buf.val[ptr - 2 ] == 8'h08 ) || (( buf.val[ptr-2] == 8'h80) && (buf.val[ptr-1] == 8'h35))) { // IP datagram or RARP if( buf.val[ptr + 9] == AH_PROTO) { printf("+-------------------------------------\n"); printf(" L3 Header-- Type: IPv4, IPSec: AH\n"); printf("+--------------------------------------\n"); ah_transp_ipv4 = 1; } else if( buf.val[ptr + 9] == ESP_PROTO) { printf("+-------------------------------------\n"); printf(" L3 Header-- Type: IPv4, IPSec: ESP\n"); printf("+--------------------------------------\n"); esp_transp_ipv4 = 1; } else if( buf.val[ptr + 9] == IP_V4_PROTO) { printf("+-------------------------------------\n"); printf(" L3 Header-- Type: Tunnel (IPv4/IPv4)\n"); printf("+--------------------------------------\n"); printf("| IP Header Tunnel Layer 1: IPv4\n| \n"); tunneling_ipv4 = 1; } else if( buf.val[ptr + 9] == IP_V6_PROTO) { printf("+-------------------------------------\n"); printf(" L3 Header-- Type: Tunnel (IPv4/IPv6)\n"); printf("+--------------------------------------\n"); printf("| IP Header Tunnel Layer 1: IPv4\n| \n"); tunneling_ipv6 = 1; } else { printf("+-------------------------------------\n"); printf(" L3 Header-- Type: IPv4\n"); printf("+--------------------------------------\n"); } ipv4_header_length = (buf.val[ptr] & 8'hf); // printf("DEBUG- ipv4_header_length - %d \n",ipv4_header_length); ptr--; ptr--; //ptr here points to type/len field display_class(buf, ptr); // looks like display class increments the ptr to the beginning of IP src address.. printf("| IPV4 Payload Len: %h%h\n", buf.val[ptr-10], buf.val[ptr-9] ); printf("| IPV4 Checksum: %h%h\n", buf.val[ptr-2], buf.val[ptr-1] ); if(ipv4_header_length>5) { printf("| IPV4 Header Length: %d \n", ipv4_header_length); } printf("| IP SRC Address: %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] ); printf("| IP DST Address: %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] ); for(i=0;i< (ipv4_header_length -5); i ++) { printf("| IP Options: %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] ); } if (esp_transp_ipv4) { printf("| ESP SPI : %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] ); } if (ah_transp_ipv4) { ptr += 4; printf("| AH SPI : %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] ); } if( tunneling_ipv4 ) { printf("| ----------- \n|\n"); printf("| IP Header Tunnel Layer 2: IPv4:\n"); printf("| \n"); ptr--; ptr--; display_class(buf, ptr); printf("| IP SRC Address: %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] ); printf("| IP DST Address: %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] ); } else if( tunneling_ipv6) { printf("| ----------- \n|\n"); printf("| IP Header Tunnel Layer 2: IPv6:\n"); printf("| \n"); ptr--; ptr--; display_class_ipv6(buf, ptr); printf("| Payload Len: 0x%h(%d)\n", buf.val[ptr++], buf.val[ptr++]); printf("| Next Header: 0x%h\n", buf.val[ptr++]); printf("| Hop Limit : 0x%h\n", buf.val[ptr++]); printf("| IP SRC Address: %h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] ); printf("| IP DST Address: %h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] ); } if( tunneling_ipv6 ) buf_shift = 34; else buf_shift = 11 + 4*(ipv4_header_length -5) ; if( buf.val[ptr - buf_shift ] == UDP_PROTO) { printf("+-------------------------------------\n"); printf(" L4 Header-- Type: UDP \n"); printf("+--------------------------------------\n"); printf("| UDP SRC Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} ); printf("| UDP DST Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} ); printf("| UDP LEN : %h\n", {buf.val[ptr++], buf.val[ptr++]} ); printf("| UDP Chksum : %h\n", {buf.val[ptr++], buf.val[ptr++]} ); // - ptr here is the first byte of UDP data token = { buf.val[ptr + 0], buf.val[ptr + 1] }; printf(" DEBUG- UDP token - %d \n",token); } else if( buf.val[ptr - buf_shift ] == TCP_PROTO) { printf("+-------------------------------------\n"); printf(" L4 Header-- Type: TCP\n"); printf("+--------------------------------------\n"); printf("| TCP SRC Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} ); printf("| TCP DST Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} ); printf("| TCP Sequence #: %h\n", {buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} ); printf("| TCP ACK #: %h\n", {buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} ); ptr += 1; flag_bit = buf.val[ptr++]; printf("| TCP Flag bits: URG:%b ACK:%b PSH:%b RST:%b SYN:%b FIN:%b\n", flag_bit[5], flag_bit[4], flag_bit[3], flag_bit[2], flag_bit[1], flag_bit[0]); printf("| Window Size: %h\n", {buf.val[ptr++], buf.val[ptr++]}); printf("| TCP Checksum: %h\n", {buf.val[ptr++], buf.val[ptr++]}); if(cfg_reg[CFG_TCP_LEN] > 5 ) { // printf("| TCP Option : "); ptr = ptr + 2; for(n=0; n<(cfg_reg[CFG_TCP_LEN]-5); n++) { printf("%h%h%h%h ", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]); } printf("\n"); ptr = ptr - 2; } // end if checking option value printf("+---------------\n"); // - ptr here is the first byte of TCP data token = { buf.val[ptr + 2], buf.val[ptr+3] }; printf(" DEBUG- TCP token ptr - %d - %d \n",token,ptr); } else if (esp_transp_ipv4) { ptr += 8; token = { buf.val[ptr], buf.val[ptr+1] }; } else if (ah_transp_ipv4) { ptr += 4; token = { buf.val[ptr], buf.val[ptr+1] }; } else { token = { buf.val[ptr], buf.val[ptr+1] }; } } /*endif IP datagram or RARP*/ else { /*IPV6*/ if( buf.val[ptr + 6] == AH_PROTO) { printf("+-------------------------------------\n"); printf(" L3 Header-- Type: IPv6, IPSec: AH\n"); printf("+--------------------------------------\n"); ah_transp_ipv6 = 1; } else if( buf.val[ptr + 6] == ESP_PROTO) { printf("+-------------------------------------\n"); printf(" L3 Header-- Type: IPv6, IPSec: ESP\n"); printf("+--------------------------------------\n"); esp_transp_ipv6 = 1; } else if( buf.val[ptr + 6] == IP_V4_PROTO) { printf("+-------------------------------------\n"); printf(" L3 Header-- Type: Tunnel (IPv6/IPv4)\n"); printf("+--------------------------------------\n"); printf("| IP Header Tunnel Layer 1: IPv6\n"); printf("| \n"); tunneling_ipv4 = 1; } else if( buf.val[ptr + 6] == IP_V6_PROTO) { printf("+-------------------------------------\n"); printf(" L3 Header-- Type: Tunnel (IPv6/IPv6)\n"); printf("+--------------------------------------\n"); printf("| IP Header Tunnel Layer 1: IPv6\n"); printf("| \n"); tunneling_ipv6 = 1; } else { printf("+-------------------------------------\n"); printf(" L3 Header-- Type: IPv6\n"); printf("+--------------------------------------\n"); } ptr--; ptr--; display_class_ipv6(buf, ptr); printf("| Payload Len: 0x%h(%d)\n", buf.val[ptr++], buf.val[ptr++]); printf("| Next Header: 0x%h\n", buf.val[ptr++]); printf("| Hop Limit : 0x%h\n", buf.val[ptr++]); printf("| IP SRC Address: %h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] ); printf("| IP DST Address: %h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] ); if (esp_transp_ipv6) { printf("| ESP SPI : %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] ); } if (ah_transp_ipv6) { ptr += 4; printf("| AH SPI : %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] ); } if( tunneling_ipv4 ) { printf("| ----------- \n|\n"); printf("| IP Header Tunnel Layer 2: IPv4:\n"); printf("| \n"); ptr--; ptr--; display_class(buf, ptr); printf("| IP SRC Address: %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] ); printf("| IP DST Address: %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] ); } else if( tunneling_ipv6) { printf("| ----------- \n|\n"); printf("| IP Header Tunnel Layer 2: IPv6:\n"); printf("| \n"); ptr--; ptr--; display_class_ipv6(buf, ptr); printf("| Payload Len: 0x%h(%d)\n", buf.val[ptr++], buf.val[ptr++]); printf("| Next Header: 0x%h\n", buf.val[ptr++]); printf("| Hop Limit : 0x%h\n", buf.val[ptr++]); printf("| IP SRC Address: %h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] ); printf("| IP DST Address: %h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] ); } if( tunneling_ipv4 ) buf_shift = 11 + 4*(ipv4_header_length -5) ; // buf_shift = 11; else buf_shift = 34; if( buf.val[ptr - buf_shift ] == UDP_PROTO) { printf("+-------------------------------------\n"); printf(" L4 Header-- Type: UDP \n"); printf("+--------------------------------------\n"); printf("| UDP SRC Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} ); printf("| UDP DST Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} ); printf("| UDP LEN : %h\n", {buf.val[ptr++], buf.val[ptr++]} ); printf("| UDP Chksum : %h\n", {buf.val[ptr++], buf.val[ptr++]} ); token = { buf.val[ptr + 0], buf.val[ptr + 1] }; } else if( buf.val[ptr - buf_shift ] == TCP_PROTO) { printf("+-------------------------------------\n"); printf(" L4 Header-- Type: TCP\n"); printf("+--------------------------------------\n"); printf("| TCP SRC Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} ); printf("| TCP DST Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} ); printf("| TCP Sequence #: %h\n", {buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} ); printf("| TCP ACK #: %h\n", {buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} ); ptr += 1; flag_bit = buf.val[ptr++]; printf("| TCP Flag bits: URG:%b ACK:%b PSH:%b RST:%b SYN:%b FIN:%b\n", flag_bit[5], flag_bit[4], flag_bit[3], flag_bit[2], flag_bit[1], flag_bit[0]); printf("| Window Size: %h\n", {buf.val[ptr++], buf.val[ptr++]}); printf("| TCP Checksum: %h\n", {buf.val[ptr++], buf.val[ptr++]}); if(cfg_reg[CFG_TCP_LEN] > 5 ) { printf("| TCP Option : "); ptr = ptr + 2; for(n=0; n<(cfg_reg[CFG_TCP_LEN]-5); n++) { printf("%h%h%h%h ", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]); } printf("\n"); ptr = ptr - 2; } printf("+---------------\n"); token = { buf.val[ptr + 2], buf.val[ptr+3] }; } else if (esp_transp_ipv6) { ptr += 8; token = { buf.val[ptr], buf.val[ptr+1] }; } else if (ah_transp_ipv6) { ptr += 4; token = { buf.val[ptr], buf.val[ptr+1] }; } else { token = { buf.val[ptr], buf.val[ptr+1] }; } } } /*end if((len>16'h0600 & len != CNTL_FRAME) || ((len == RARP_FRAME) &(len != CNTL_FRAME))) */ if(len<0) len = hwlen; printf("\npg::display_buf Time: %0d\n",{get_time(HI),get_time(LO)}); printf("Token: %0d\n", token); printf("\n"); display_data(buf, ptr, hwlen-ptr-4 ); printf("\n"); printf("CRC: %h\n", { buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } ); printf("\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); printf("--------------------------------------------------------------\n\n"); } task pg::display_class(byte_array buf, var integer ptr) { integer n,last; last = ptr+14; printf("| Class: "); for(n=0;n<14;n++) printf("%h ", buf.val[ptr+n] ); printf("\n"); if( {buf.val[ptr], buf.val[ptr+1]} < 16'h0600) printf("| Length: %0d\n|\n", {buf.val[ptr++], buf.val[ptr++]} ); else printf("| Type: %0h\n|\n", {buf.val[ptr++], buf.val[ptr++]} ); ptr=last; } task pg::display_class_ipv6(byte_array buf, var integer ptr) { integer n,last; last = ptr+6; printf("| Class: "); for(n=0;n<10;n++) printf("%h ", buf.val[ptr+n] ); printf("\n"); if( {buf.val[ptr], buf.val[ptr+1]} < 16'h0600) printf("| Length: %0d\n|\n", {buf.val[ptr++], buf.val[ptr++]} ); else printf("| Type: %0h\n|\n", {buf.val[ptr++], buf.val[ptr++]} ); ptr=last; } task pg::display_data(byte_array buf, var integer ptr, integer len) { integer n; printf(" Data:\n"); printf("+---------------"); if(len<1) printf("\n| No Payload ..."); else for(n=0;n< len ;n++) { if( !(n % 16) ) printf("\n| %d: ",n); printf("%h ", buf.val[ptr++]); } printf("\n+---------------\n"); } task pg::display_id(bit [79:0] id) { printf(" ID Tags:\n"); printf("+---------------\n"); printf("| Src port: %0d\n", id[79:75] ); printf("| Dst port: %0h\n", id[74:35] ); printf("| Order Type: %0h\n", id[34:33] ); printf("| Order Sequnce: %0d\n", id[32:27] ); printf("| Packet number: %0d\n", id[26:11] ); printf("| Data Type: %0d\n", id[10:8] ); printf("| Data Seed: %0d\n", id[7:0] ); printf("+---------------\n"); } task pg::display_db(pack_db_entry pack_db ) { printf("\n========== Display DB Entry %0d ========== \n",pack_db.gId); if(pack_db == null) { printf("This entry is not allocated ...\n"); } else { printf("\tframe.frame_type: %h\n",pack_db.frame.frame_type); printf("\tframe.frame_class: %h\n",pack_db.frame.frame_class); printf("\tframe.class_mask: %h\n",pack_db.frame.class_mask); printf("\tframe.class_funct: %h\n",pack_db.frame.class_funct); printf("\tframe.data_type: %h\n",pack_db.frame.data_type); printf("\tframe.data_seed: %h\n",pack_db.frame.data_seed); printf("\tframe.data_length: %h\n",pack_db.data_length); printf("\n"); printf("\tsrc_node.l2_addr: %h\n",pack_db.src_node.l2_addr); printf("\tsrc_node.tci: %h\n",pack_db.src_node.tci); printf("\tsrc_node.ip_addr: %h\n",pack_db.src_node.ip_addr); printf("\tsrc_node.ipv6_addr: %h\n",pack_db.src_node.ipv6_addr); printf("\n"); printf("\tdst_node.l2_addr: %h\n",pack_db.dst_node.l2_addr); printf("\tdst_node.tci: %h\n",pack_db.dst_node.tci); printf("\tdst_node.ip_addr: %h\n",pack_db.dst_node.ip_addr); printf("\tdst_node.ipv6_addr: %h\n",pack_db.dst_node.ipv6_addr); printf("\n"); printf("\ttup.src_tcp_udp_port: %h\n",pack_db.tup.src_tcp_udp_port); printf("\ttup.dst_tcp_udp_port: %h\n",pack_db.tup.dst_tcp_udp_port); printf("\n"); printf("\trcv_isn: %0h\n",pack_db.rx_param.rcv_isn); printf("\tlast_ackno: %0h\n",pack_db.rx_param.last_ackno); printf("\tadv_isn: %0h\n",pack_db.tx_param.adv_isn); printf("\tlast_seqno: %0h\n",pack_db.tx_param.last_seqno); printf("\n"); printf("\torg_port: %0d\n",pack_db.org_port); printf("\torder_seq: %0d\n",pack_db.order_seq); printf("\tpckt_num: %0d\n",pack_db.pckt_num); printf("\toptions: %h\n",pack_db.options); } printf("========================================== \n\n"); } task pg::display_flow(integer flow_id) { printf("\n========== Display FLOW DB Entry %0d ========== \n",flow_id); if(flow_db[flow_id] == null) { printf("This entry is not allocated ...\n"); } else { printf("\tframe.data_length: %h\n",flow_db[flow_id].data_length); printf("\n"); printf("\ttup.src_tcp_udp_port: %h\n",flow_db[flow_id].tup.src_tcp_udp_port); printf("\ttup.dst_tcp_udp_port: %h\n",flow_db[flow_id].tup.dst_tcp_udp_port); printf("\n"); printf("\torg_port: %0d\n",flow_db[flow_id].org_port); printf("\trcv_isn: %0h\n",flow_db[flow_id].rx_param.rcv_isn); printf("\tlast_ackno: %0h\n",flow_db[flow_id].rx_param.last_ackno); printf("\tadv_isn: %0h\n",flow_db[flow_id].tx_param.adv_isn); printf("\tlast_seqno: %0h\n",flow_db[flow_id].tx_param.last_seqno); } printf("========================================== \n\n"); } function bit[15:0] pg::partial_cksum(byte_array packet, integer start_offset, integer pkt_len) { integer i; bit [16:0] chksum_tmp = 0; for(i = start_offset; i < pkt_len;) { if(i == pkt_len - 1) { chksum_tmp = chksum_tmp + {packet.val[i],8'h0}; chksum_tmp = chksum_tmp + chksum_tmp[16]; chksum_tmp[16] = 1'b0; } else { chksum_tmp = chksum_tmp + {packet.val[i],packet.val[i+1]}; chksum_tmp = chksum_tmp + chksum_tmp[16]; chksum_tmp[16] = 1'b0; } i = i+2; } partial_cksum = chksum_tmp[15:0]; }