/****************************************** * File: nt_bridge.c * Purpose: netcp bridge offload prototypes. ************************************************************** * FILE: nt_bench.c * * DESCRIPTION: netapi user space transport * library test application : benchmarks * * REVISION HISTORY: rev 0.0.1 * * Copyright (c) Texas Instruments Incorporated 2013-2014 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************/ #include #include #include #include #include #include #include #include "trie.h" #include "string.h" #include "netapi.h" #include "pktio.h" #include #include "net_test_sa_utils.h" #include "net_test_utils.h" #include "net_test_thread_utils.h" #include "fdb.h" #if defined(DEVICE_K2H) #include #include #elif defined (DEVICE_K2K) #include #include #elif defined (DEVICE_K2L) #include #include #elif defined (DEVICE_K2E) #include #include #else /*Default */ #include #include #endif /* Device */ #define netapi_timing_start hplib_mUtilGetPmuCCNT extern Rm_ServiceHandle *rmClientServiceHandle; static int scnt=0; static int QUIT=0; static int XMIT=0; static int CAP=0; volatile int RESET=0; //to reset stats volatile int MAC=0; volatile int FAST=1; uint16_t num_learned_macs = 0; uint16_t num_configured_interfaces = 0; static ntBridgeCfgFile_T config_file[MAX_INTERFACES]; NETCP_CFG_ROUTE_T test_route[MAX_INTERFACES]; static ntBridgeAleCfgFile_T ale_config_file; FDB_ENTRY_T ale_cfg[32]; //*********************for checksum test unsigned short checksum(unsigned short *p, int len) { unsigned short s=0; int i; for(i=0;idscpMap[i].flowOffset =(uint16_t)strtol(input_str_flow, NULL, 0); pQosShapperCfg->dscpMap[i].queueOffset = (uint16_t)strtol(input_str_queue, NULL, 0); } } } void parse_dscp_entry(ntBridgeCfgFile_T *pConfig, paEQosModeConfig_t* pQosShapperCfg) { int i; for(i=0;idscpMapF[i][0]) && (pConfig->dscpMapQ[i][0])) { pQosShapperCfg->dscpMap[i].flowOffset =atoi(&pConfig->dscpMapF[i][0]); pQosShapperCfg->dscpMap[i].queueOffset = atoi(&pConfig->dscpMapQ[i][0]); printf("parse_dsp_entry[%d]: flowOffset: %d, queueOffset: %d\n", i, pQosShapperCfg->dscpMap[i].flowOffset, pQosShapperCfg->dscpMap[i].queueOffset); } else { pQosShapperCfg->dscpMap[i].flowOffset =0; pQosShapperCfg->dscpMap[i].queueOffset = 0; } } } unsigned char ntUtilHex2Dec(char *p_s) { int val; sscanf(p_s,"%x",&val); return val&0xff; } void parse_pbit_entry_default(char* input_str_queue, char* input_str_flow, paEQosModeConfig_t* pQosShapperCfg) { int i; if (strlen(input_str_queue) && strlen(input_str_flow)) { for(i=0;ipbitMap[i].flowOffset =(uint16_t)strtol(input_str_flow, NULL, 0); pQosShapperCfg->pbitMap[i].queueOffset = (uint16_t)strtol(input_str_queue, NULL, 0); } } } void parse_pbit_entry(ntBridgeCfgFile_T *pConfig, paEQosModeConfig_t* pQosShapperCfg) { int i; for(i=0;ipbitMapF[i][0]) && (pConfig->pbitMapQ[i][0])) { pQosShapperCfg->pbitMap[i].flowOffset =atoi(&pConfig->pbitMapF[i][0]); pQosShapperCfg->pbitMap[i].queueOffset = atoi(&pConfig->pbitMapQ[i][0]); printf("parse_pbit_entry[%d]: flowOffset: %d, queueOffset: %d\n", i, pQosShapperCfg->pbitMap[i].flowOffset, pQosShapperCfg->pbitMap[i].queueOffset); } else { pQosShapperCfg->pbitMap[i].flowOffset =0; pQosShapperCfg->pbitMap[i].queueOffset = 0; } } } void parseOneMac(char * p_mac_str, uint8_t *p_mac) { int index = 0; int i; if (strlen(&p_mac_str[0])) { char *pch = strtok (&(p_mac_str[0]),":"); while (pch != NULL) { p_mac[index] = ntUtilHex2Dec(pch); index++; pch = strtok (NULL,":"); } //printf("parseOneMac: 0x%x: 0x%x: 0x%x: 0x%x: 0x%x:0x%x\n", //p_mac[0],p_mac[1],p_mac[2],p_mac[3],p_mac[4],p_mac[5]); } } void parseMac(ntBridgeAleCfgFile_T *pConfig, FDB_ENTRY_T *pAleCfg) { int i; int port = 0; FDB_ENTRY_T *tmp = pAleCfg; for(i=0;i<32;i++) { if (strlen(&pConfig->mac[i][0])) { parseOneMac((char*)&pConfig->mac[i][0], (uint8_t*)&tmp->mac_addr); sscanf(&pConfig->switch_port[i][0],"swp%d",&tmp->switch_port); tmp++; num_learned_macs++; /* check port to be 1 or 2 */ //printf("parseMac: port: %d\n", tmp->switch_port); } } } void parseMode(ntBridgeCfgFile_T *pConfig, paEQosModeConfig_t* pQosShapperCfg) { if (strlen(&pConfig->ctrlBitMap[0])) { printf("parseMode: mode: %s\n", &pConfig->ctrlBitMap[0]); if (strcmp(pConfig->ctrlBitMap, "dscp") == 0) { pQosShapperCfg->ctrlBitMap = 0; pa_IF_EQoS_ROUTE_DP_BIT_MODE; } else if (strcmp(pConfig->ctrlBitMap, "pbit") == 0) { pQosShapperCfg->ctrlBitMap = pa_IF_EQoS_ROUTE_DP_BIT_MODE; } else { netapi_Log("parseMode(), invalid QOS Mode in config file \n"); } } } paEQosModeConfig_t netTestQosShapperCfg[MAX_INTERFACES]; /* Default Qos Shapper configuration for eth0 and eth1 */ paEQosModeConfig_t netTestQosShapperCfg1 = { pa_IF_EQoS_ROUTE_DP_BIT_MODE, {0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7}, {0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7}, 1, 0, 0, 0, 0 }; paEQosModeConfig_t netTestQosShapperCfg2 = { pa_IF_EQoS_ROUTE_DP_BIT_MODE, {0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7}, {0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7}, 2, 0, 0, 0, 0 }; void ntBrideProcessCfgFile(FILE * fpr, ntBridgeCfgFile_T *pConfig) { char line[MAX_LINE_LENGTH + 1]; int i; static int sa_count = 0; char *key, *ep; char * d1, *d2, *d3; char tokens[] = " :=;\n"; char temp_str[TEMP_STR_LEN]; memset(line, 0, MAX_LINE_LENGTH + 1); //memset(pConfig, 0, sizeof(netTestConfigFile_t)); while (fgets(line, MAX_LINE_LENGTH + 1, fpr)) { if(line[0]=='#') continue; //skip comment key = (char *)strtok(line, tokens); d1 = (char *)strtok(NULL, tokens); if (!key) continue; if (!d1) continue; if(strlen(d1) == 0) { continue; } d2 = (char *)strtok(NULL, tokens); CHECK_SET_PARAM(ntBridge_INIT_CONFIG_FLOW_BASE,&(pConfig->flowBase[0])); CHECK_SET_PARAM(ntBridge_INIT_CONFIG_QUEUE_BASE,&(pConfig->queueBase[0])); CHECK_SET_PARAM(ntBridge_INIT_CONFIG_VLAN_ID,&(pConfig->vlanId[0])); CHECK_SET_PARAM(ntBridge_INIT_CONFIG_PORT,&(pConfig->port[0])); CHECK_SET_PARAM(ntBridge_INIT_CONFIG_INGRESS_DEF_PRI,&(pConfig->ingressDefPri[0])); CHECK_SET_PARAM(ntBridge_INIT_CONFIG_QOS_MODE,&(pConfig->ctrlBitMap[0])); CHECK_SET_PARAM2(ntBridge_INIT_CONFIG_DSCP_MAP_DEFAULT,&pConfig->dscpMapFDefault[0],&pConfig->dscpMapQDefault[0]); CHECK_SET_PARAM2(ntBridge_INIT_CONFIG_PBIT_MAP_DEFAULT,&pConfig->pbitMapFDefault[0],&pConfig->pbitMapQDefault[0]); for(i=0;idscpMapF[i][0],&pConfig->dscpMapQ[i][0]); } for(i=0;i< MAX_PBIT_ENTRIES;i++) { snprintf(temp_str,TEMP_STR_LEN-1,"pbit_map_%d",i); CHECK_SET_PARAM2(temp_str,&pConfig->pbitMapF[i][0],&pConfig->pbitMapQ[i][0]); } } } void ntBrideProcessAleCfgFile(FILE * fpr, ntBridgeAleCfgFile_T *pConfig) { char line[MAX_LINE_LENGTH + 1]; int i; static int sa_count = 0; char *key, *ep; char * d1, *d2, *d3; char tokens[] = " =;\n"; char temp_str[TEMP_STR_LEN]; memset(line, 0, MAX_LINE_LENGTH + 1); //memset(pConfig, 0, sizeof(netTestConfigFile_t)); while (fgets(line, MAX_LINE_LENGTH + 1, fpr)) { if(line[0]=='#') continue; //skip comment key = (char *)strtok(line, tokens); d1 = (char *)strtok(NULL, tokens); if (!key) continue; if (!d1) continue; if(strlen(d1) == 0) { continue; } d2 = (char *)strtok(NULL, tokens); for(i=0;i< 32;i++) { snprintf(temp_str,TEMP_STR_LEN-1,"mac%d",i); CHECK_SET_PARAM2(temp_str,&pConfig->mac[i][0],&pConfig->switch_port[i][0]); } } } //sig handler void netTest_utilMySig(int x) { QUIT=1; scnt+=1; printf(">ifdma-test: recv'd signal %d cnt=%d\n",x,scnt); if (scnt > 10) {printf(">ifdma-test: WARNING EXITING WITH PROPER SHUTDOWN, LUTS LEFT ACTIVE\n");exit(1);} } void recv_cb_net(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[], PKTIO_METADATA_T meta[], int n_pkts, uint64_t ts ); /*************debug********************/ void netTest_utilDumpDescr(unsigned long *p, int n) { printf("--------dump of descriptor %d %x\n", n, (int) p); printf("> %x %x %x %x %x %x %x %x\n",p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7]); printf("> %x %x %x %x %x %x %x %x\n",p[8],p[9],p[10],p[11],p[12],p[13],p[14],p[15]); printf("-----------------------------\n"); } void netTest_utilDumpHeader(unsigned long *p, int n, int a, int r) { printf("--------dump of header %d %x appID=%x flag1=%x\n", n, (int) p,a,r); printf("> %0x %0x %0x %0x %0x %0x %0x %0x\n", ntohl(p[0]),ntohl(p[1]),ntohl(p[2]),ntohl(p[3]), ntohl(p[4]),ntohl(p[5]),ntohl(p[6]),ntohl(p[7]) ); printf("-----------------------------\n"); } /*****************************************/ unsigned long long CALIB=0; unsigned long long calibrate_idle(void) { volatile unsigned long long at1; volatile unsigned long long at2; volatile unsigned long pt1; volatile unsigned long pt2; unsigned long long calib; at1 = hplib_mUtilGetTimestamp(); pt1=netapi_timing_start(); for(;;) { pt2=netapi_timing_start() ; if ((pt2-pt1) >= 100000) break; } at2 = hplib_mUtilGetTimestamp(); calib = ((unsigned long long) (pt2-pt1))/(at2-at1); printf("calibrate: arm time=%lld -> arm cycles=%d calib=%lld\n", at2-at1, pt2-pt1, calib); return calib; } /******************************************* *************NETAPI OBJECTS*************** *****************************************/ static NETAPI_CFG_T our_netapi_default_cfg= { TUNE_NETAPI_PERM_MEM_SZ, 128, //start of packet offset for hw to place data on rx for default flow TUNE_NETAPI_QM_CONFIG_MAX_DESC_NUM, //max number of descriptors in system TUNE_NETAPI_NUM_GLOBAL_DESC, //total we will use TUNE_NETAPI_DEFAULT_NUM_BUFFERS*2, //#descriptors+buffers in default heap 64, //#descriptors w/o buffers in default heap TUNE_NETAPI_DEFAULT_BUFFER_SIZE+128+128, //size of buffers in default heap 128, //tail room 256, //extra room, 0, NULL, 18, 0x2000 }; Pktlib_HeapHandle OurHeap; //default heap, used by producer PKTIO_CFG_T netcp_rx_cfg={PKTIO_RX, PKTIO_NA, PKTIO_NA, 8}; PKTIO_CFG_T netcp_tx_cfg={PKTIO_TX, PKTIO_NA, PKTIO_NA, 12}; PKTIO_HANDLE_T * netcp_rx_chan; PKTIO_HANDLE_T * netcp_tx_chan; NETAPI_T netapi_handle; PKTIO_CONTROL_T zap_channel_control={PKTIO_CLEAR, NULL}; PKTIO_CONTROL_T poll_cannel_control={PKTIO_SET_POLL_FLAGS, NULL, nwal_POLL_DEFAULT_GLOB_PKT_Q}; //template for fast path nwalTxPktInfo_t txPktInfoNoCrypto = { NULL, /* p_pkt */ NWAL_TX_FLAG1_META_DATA_VALID, /* txFlags */ 0, /* lpbackPass */ 0, /* enetport */ 0, /* msuSize */ 0, /* startOffset */ 0, /* saOffBytes */ 0, /* saPayLoadLen */ 0, /* saAhIcvOffBytes */ 0, /* saAhMacSize */ 0, /* etherLenOffBytes */ netTest_MAC_HEADER_LEN, /* ipOffBytes */ netTest_MAC_HEADER_LEN +netTest_IP_HEADER_LEN, /* l4OffBytes */ netTest_UDP_HEADER_LEN, /* l4HdrLen */ 0, /* pseudoHdrChecksum */ 0 /* pLoadLen */ }; NETCP_CFG_ROUTE_T test_route1 = { 0, NULL, NULL, 0, 1, 0, 1 }; NETCP_CFG_ROUTE_T test_route2 = { 0, NULL, NULL, 0, 2, 0, 1 }; //#define WITH_QOS #ifdef WITH_QOS //send to qos input queue, set in device tree (6409) //#define QOSQ 6410 /* for wrr */ #define QOSQ 6409 /* for SP */ PKTIO_CFG_T direct_to_cpsw_cfg={PKTIO_TX, PKTIO_GLOBAL, QOSQ, 8}; #else //send direct to 648, the CPSW input queue PKTIO_CFG_T direct_to_cpsw_cfg={PKTIO_TX, PKTIO_GLOBAL, 648, 8}; #endif PKTIO_HANDLE_T * cpsw_tx_chan[MAX_INTERFACES]; //NETCP_CFG_FLOW_T flow; /*************************END NETAPI OBJECTS***********************/ static unsigned char all_mac[]={0,0,0,0,0,0}; static unsigned char test_mac0[]={0,0,0,0,0,0xf}; static unsigned char test_mac1[]={0,0,0,0,0,0xff}; static unsigned char test_mac2[]={0xd4,0xbe,0xd9,0,0xd3,0x7e}; static unsigned char test_mac3[]={0,0x15,0x60,0xa1,0xf7,0xbe}; static unsigned char test_mac4[]={0xff,0xff,0xff,0x00,0x00,0x00}; //static unsigned char test_mac0[]={0xd4,0xbe,0xd9,0x00,0xd3,0x7e}; int test_port0 = 1; //static unsigned char test_mac1[]={0x00,0x15,0x60,0xa1,0xf7,0xbe}; int test_port1 = 2; static unsigned long last_header[32/sizeof(unsigned long)]; //stats int pkt_rx=0; int pkt_tx=0; unsigned long long pkt_rx_cycles=0L; unsigned long long pkt_tx_cycles=0L; unsigned long long pkt_cb_cycles=0L; unsigned long long idle_cycles=0L; volatile unsigned long long start_time; unsigned long long end_time; paSysStats_t netcp_stats; void netTest_utilStatsCbMt(NETAPI_T h, paSysStats_t* pPaStats) { if(pPaStats) { memcpy(&netcp_stats,pPaStats, sizeof(paSysStats_t)); } } void netTest_utilsStatsCb(NETAPI_T h, paSysStats_t* pPaStats) { if(pPaStats) { printf("C1 number of packets: %d\n", pPaStats->classify1.nPackets); printf("C1 number IPv4 packets: %d\n", pPaStats->classify1.nIpv4Packets); printf("C1 number IPv6 packets: %d\n", pPaStats->classify1.nIpv6Packets); printf("C1 number Custom packets: %d\n", pPaStats->classify1.nCustomPackets); printf("C1 number SRIO packets: %d\n", pPaStats->classify1.nSrioPackets); printf("C1 number LLC/SNAP Fail packets: %d\n", pPaStats->classify1.nLlcSnapFail); printf("C1 number table matched: %d\n", pPaStats->classify1.nTableMatch); printf("C1 number failed table matched: %d\n", pPaStats->classify1.nNoTableMatch); printf("C1 number IP Fragmented packets: %d\n", pPaStats->classify1.nIpFrag); printf("C1 number IP Depth Overflow: %d\n", pPaStats->classify1.nIpDepthOverflow); printf("C1 number VLAN Depth Overflow: %d\n", pPaStats->classify1.nVlanDepthOverflow); printf("C1 number GRE Depth Overflow: %d\n", pPaStats->classify1.nGreDepthOverflow); printf("C1 number MPLS Packets: %d\n", pPaStats->classify1.nMplsPackets); printf ("C1 number of parse fail: %d\n",pPaStats->classify1.nParseFail); printf("C1 number of Invalid IPv6 Opt: %d\n", pPaStats->classify1.nInvalidIPv6Opt); printf("C1 number of TX IP Fragments: %d\n", pPaStats->classify1.nTxIpFrag); printf ("C1 number of silent discard: %d\n",pPaStats->classify1.nSilentDiscard); printf("C1 number of invalid control: %d\n", pPaStats->classify1.nInvalidControl); printf ("C1 number of invalid states: %d\n",pPaStats->classify1.nInvalidState); printf ("C1 number of system fails: %d\n",pPaStats->classify1.nSystemFail); printf ("C2 number Packets : %d\n",pPaStats->classify2.nPackets); printf ("C2 number udp : %d\n",pPaStats->classify2.nUdp); printf ("C2 number tcp : %d\n",pPaStats->classify2.nTcp); printf ("C2 number Custom : %d\n",pPaStats->classify2.nCustom); printf ("C2 number silent drop : %d\n",pPaStats->classify2.nSilentDiscard); printf ("C2 number invalid cntrl : %d\n\n",pPaStats->classify2.nInvalidControl); printf ("C2 number Modify Stats Cmd Fail : %d\n\n",pPaStats->modify.nCommandFail); } } //********************************** //producer thread //********************************* void producer_thread(int coreid) { int err; int i; Ti_Pkt * tip; unsigned char * pData; int len; PKTIO_METADATA_T meta = {PKTIO_META_IFDMA_TX,{0},0}; int np; cpu_set_t cpu_set; unsigned long t1; unsigned long t2; CPU_ZERO( &cpu_set); CPU_SET( coreid, &cpu_set); hplib_utilSetupThread(coreid, &cpu_set, hplib_spinLock_Type_LOL); start_time = hplib_mUtilGetTimestamp(); /* Poll the default pktio channel for pkts from network */ for(i=0;!((volatile int) QUIT);i++) { if (FAST) { //netapi_netcpCfgReqStats(netapi_handle, netTest_utilStatsCbMt, 0,&err); sleep(2); continue; } t1 = netapi_timing_start(); np = netapi_pktioPoll(netcp_rx_chan,NULL,&err); t2 = netapi_timing_start(); pkt_rx+=np; if (np) { pkt_rx_cycles += (t2-t1); } else { idle_cycles += (t2-t1); } if (RESET) { idle_cycles=0LL; start_time = hplib_mUtilGetTimestamp(); pkt_rx=pkt_tx=0; pkt_rx_cycles=pkt_tx_cycles=0LL; pkt_cb_cycles=0LL; RESET=0; } } end_time = hplib_mUtilGetTimestamp(); printf("nt-bench: receiver DONE %d pkts rx, pkt poll cycles=% u; pkt rx cycle=%u pkt tx cycles=%u idle cycles=%lld duration=%lld ticks idle pct= %lld\n", pkt_rx, (unsigned)(pkt_rx ? (pkt_rx_cycles - pkt_cb_cycles)/pkt_rx : 0), (unsigned) (pkt_rx ? (pkt_rx_cycles) /pkt_rx : 0), (unsigned) (pkt_tx ? (pkt_tx_cycles) /pkt_tx : 0), idle_cycles, (end_time-start_time), (idle_cycles*100) /( CALIB* (end_time-start_time)) ); printf("Leaving producer_thread\n"); } void nt_setupQosShapper(NETAPI_T h, paEQosModeConfig_t *pqosCfg) { int i; paEmacPortConfig_t ctrl; nwalLocCxtInfo_t info; NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h; memset(&info, 0, sizeof(nwalLocCxtInfo_t)); memset(&ctrl, 0, sizeof(paEmacPortConfig_t)); ctrl.cfgType = pa_EMAC_PORT_CFG_EQoS_MODE; ctrl.numEntries = 1; ctrl.u.eQoSModeCfg = pqosCfg; if(pqosCfg->flowBase) { printf("nt_setupQosShapper: flowBase from config file: %d\n", pqosCfg->flowBase); ctrl.u.eQoSModeCfg->flowBase = pqosCfg->flowBase; } else { nwal_getLocCxtInfo(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, &info); printf("nt_setupQosShapper: flowBase from nwal: %d\n", info.rxPktFlowId); ctrl.u.eQoSModeCfg->flowBase = info.rxPktFlowId; } nwal_emacPortCfg(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, &ctrl); } //****************************** // main program //***************************** int main(int argc, char **argv) { int err,i; int32_t errCode; Pktlib_HeapIfTable* pPktifTable; Pktlib_HeapCfg heapCfg; long t1, t2 ; cpu_set_t cpu_set; FILE* fpr[MAX_INTERFACES]; //install signal handler for ^c signal(SIGINT,netTest_utilMySig); for(i=0; i < MAX_INTERFACES; i++) { fpr[i] = NULL; } memset(&config_file[0], 0, sizeof(ntBridgeCfgFile_T)*MAX_INTERFACES); memset(&netTestQosShapperCfg[0], 0, sizeof(paEQosModeConfig_t)*MAX_INTERFACES); memset(&ale_cfg, 0, sizeof(ntBridgeAleCfg_T)); memset(&ale_cfg, 0, sizeof(FDB_ENTRY_T)*32); /* USE defautl Qos Shapper Configuration for 2 ports unless config files provided */ memcpy(&netTestQosShapperCfg[0], &netTestQosShapperCfg1, sizeof(paEQosModeConfig_t)); memcpy(&netTestQosShapperCfg[1], &netTestQosShapperCfg2, sizeof(paEQosModeConfig_t)); if (argc == 2) { fpr[0] = fopen(argv[1], "r"); num_configured_interfaces = 1; } else if (argc == 3) { fpr[0] = fopen(argv[1], "r"); fpr[1] = fopen(argv[2], "r"); num_configured_interfaces = 2; } else { printf("No qos shapper input files, using default settings\n"); num_configured_interfaces = 2; } for (i=0;i< num_configured_interfaces;i++) { if (fpr[i]) { ntBrideProcessCfgFile(fpr[i], &config_file[i]); parse_dscp_entry_default((char*)&config_file[i].dscpMapQDefault, (char*)&config_file[i].dscpMapFDefault, &netTestQosShapperCfg[i]); parse_pbit_entry_default((char*)&config_file[i].pbitMapQDefault, (char*)&config_file[i].pbitMapFDefault, &netTestQosShapperCfg[i]); parse_simple_param_u16((char*)&config_file[i].queueBase, &netTestQosShapperCfg[i].queueBase); printf("main: netTestQos Cfg: queueBase: %d\n",netTestQosShapperCfg[i].queueBase); parse_simple_param_u8((char*)&config_file[i].flowBase, &netTestQosShapperCfg[i].flowBase); printf("main: netTestQos Cfg: flowBase: %d\n",netTestQosShapperCfg[i].flowBase); parse_simple_param_u16((char*)&config_file[i].vlanId, &netTestQosShapperCfg[i].vlanId); printf("main: netTestQos Cfg: vlanId: %d\n",netTestQosShapperCfg[i].vlanId); parse_simple_param_u8((char*)&config_file[i].port, &netTestQosShapperCfg[i].port); printf("main: netTestQos Cfg: port: %d\n",netTestQosShapperCfg[i].port); parse_simple_param_u8((char*)&config_file[i].ingressDefPri, &netTestQosShapperCfg[i].ingressDefPri); printf("main: netTestQos Cfg: ingressDefPri: %d\n",netTestQosShapperCfg[i].ingressDefPri); parse_dscp_entry(&config_file[i], &netTestQosShapperCfg[i]); parse_pbit_entry(&config_file[i], &netTestQosShapperCfg[i]); parseMode(&config_file[i], &netTestQosShapperCfg[i]); } } #if 0 if (initRm()) { printf("main: initRm() returned error\n"); exit(1); } #endif CPU_ZERO( &cpu_set); CPU_SET( 0, &cpu_set); hplib_utilSetupThread(0, &cpu_set, hplib_spinLock_Type_LOL); /*******************************************/ /*************NETAPI STARTUP****************/ /*******************************************/ /* create netapi */ our_netapi_default_cfg.rmHandle = rmClientServiceHandle; netapi_handle = netapi_init(NETAPI_SYS_MASTER, &our_netapi_default_cfg); if (netapi_handle == NULL) { printf("main: netapi_init failure, exiting\n"); exit(1); } /* open the main heap */ OurHeap = Pktlib_findHeapByName("netapi"); if (!OurHeap) {printf("findheapbyname fail\n"); exit(1);} for(i = 0; i < MAX_INTERFACES; i++) { char temp_str[PKTIO_MAX_NAME] = {0}; direct_to_cpsw_cfg.qnum = netTestQosShapperCfg[i].queueBase; snprintf(temp_str, PKTIO_MAX_NAME, "cpsw_tx%d",i); cpsw_tx_chan[i]= netapi_pktioCreate(netapi_handle,&temp_str[0],NULL, &direct_to_cpsw_cfg, &err); if (!cpsw_tx_chan[i]) { printf("pktio open %s failed err=%d\n", &temp_str[0], err); exit(1); } } #if 0 direct_to_cpsw_cfg.qnum = netTestQosShapperCfg2.queueBase; cpsw_tx_chan2= netapi_pktioCreate(netapi_handle,"cpsw_tx2",NULL, &direct_to_cpsw_cfg, &err); if (!cpsw_tx_chan2){printf("pktio open CPSW TX2 failed err=%d\n",err); exit(1);} #endif //if we want to relay network packets, we create a handle to the //default netcp receive queue here netcp_rx_chan= netapi_pktioOpen(netapi_handle, NETCP_RX, (PKTIO_CB) recv_cb_net, &netcp_rx_cfg, &err); if (!netcp_rx_chan) {printf("pktio open RX failed err=%d\n",err); exit(1);} netcp_tx_chan= netapi_pktioOpen(netapi_handle, NETCP_TX, (PKTIO_CB) NULL, &netcp_tx_cfg, &err); if (!netcp_tx_chan) {printf("pktio open TX failed err=%d\n",err); exit(1);} else //install a fast path template into the NETCP TX channel { PKTIO_CONTROL_T control2; control2.op = PKTIO_UPDATE_FAST_PATH; PKTIO_CFG_T cfg2; cfg2.fast_path_cfg.fp_send_option = PKTIO_FP_NO_CRYPTO_NO_CKSUM_PORT; cfg2.fast_path_cfg.txPktInfo= &txPktInfoNoCrypto; netapi_pktioControl(netcp_tx_chan, NULL, &cfg2, &control2, &err); } //build route for cpsw NETCP_CFG_FLOW_T flow; flow.dma_engine = 1; for (i = 0; i < MAX_INTERFACES;i++) { if(netTestQosShapperCfg[i].flowBase) { flow.dma_engine = 1; flow.flowid = netTestQosShapperCfg[i].flowBase; test_route[i].p_flow = &flow; } else { test_route[i].p_flow =NETCP_DEFAULT_FLOW; } test_route[i].egress_swith_port = netTestQosShapperCfg[i].port; test_route[i].routeType = NWAL_ROUTE_PKTTYPE_EQOS; test_route[i].valid_params = NETCP_CFG_VALID_PARAM_ROUTE_TYPE; test_route[i].p_dest_q = cpsw_tx_chan[i]; } /*********************************************/ /*****************end NETAPI STARTUP**********/ /*********************************************/ //calibrate idle CALIB = calibrate_idle(); ntoff_start(); ntoff_add_do_perm(&test_mac0[0],test_port0); ntoff_add_do_perm(&test_mac1[0],test_port1); //ntoff_add_do_perm(&test_mac2[0],test_port0); //ntoff_add_do_perm(&test_mac3[0],test_port1); //ntoff_add_do_perm(&test_mac4[0],test_port0); //************************************** //Create a worked thread //*************************************** { pthread_t *thrs; int procs =1; int c; thrs = malloc( sizeof( pthread_t ) * procs ); if (thrs == NULL) { perror( "malloc" ); return -1; } printf( "net_test_bridge: Starting %d threads...\n", procs ); if (pthread_create( &thrs[0], NULL, (void*)producer_thread, (void *)1 )) { perror( "pthread_create" ); exit(1); } //this thread of execution (main) now just waits on user input for(;;) { printf(">"); c=getchar(); if (c=='c') {CAP=!CAP; printf("CAPTURE= %d\n", CAP); } else if (c=='t') {XMIT=!XMIT; printf("XMIT= %d\n", XMIT); } else if (c=='l') { FILE* fprAle = NULL; system("/etc/transportnetlib/test/parse_ale.sh"); fprAle = fopen("ale_table.txt","r"); if (fprAle) { ntBrideProcessAleCfgFile(fprAle, &ale_config_file); //for(i=0;i<32;i++) parseMac(&ale_config_file, &ale_cfg[0]); for(i=0;iNT_BENCH STATS: %d received %d xmitted, %lld idle cycles, %lld duration ticks idle=%lld\n", pkt_rx,pkt_tx, idle_cycles, (et-start_time), (idle_cycles*100)/(CALIB*(et-start_time)) ); Pktlib_HeapStats pktLibHeapStats; Pktlib_getHeapStats(OurHeap, &pktLibHeapStats); printf("main heap stats> #free=%d #zb=%d #garbage=%d\n", pktLibHeapStats.numFreeDataPackets, pktLibHeapStats.numZeroBufferPackets, pktLibHeapStats.numPacketsinGarbage); } else if (c=='S') { system("/usr/bin/dumpqos.sh"); } else if (c=='r') { RESET=1; } else if (c=='h') { printf("> 'q' to quit, 's' for Heap stats, 'S' for QOS stats \n"); printf(" 'c' to toggle capture, 'd' to dump capture, 'r' to reset idle counters\n"); printf(" 'm' to add macs, 'n' to remove macs 'l' to learn macs\n"); printf(" 'f' toggle s/w or netcp offload, '!' shell, 'S' Chksum Stats, 'h' for help\n"); } else if (c=='d') { netTest_utilDumpHeader(&last_header[0], 0,0,0); } else if (c == 'z') { nwalCtlInfo_t nwalCtrl; NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) netapi_handle; memset(&nwalCtrl, 0, sizeof(nwalCtlInfo_t)); nwalCtrl.pktCtl= NWAL_CTRL_CFG_EMAC_IF_EGRESS_EQOS_MODE; nwalCtrl.matchAction = NWAL_MATCH_ACTION_HOST; nwalCtrl.appRxPktFlowId = NWAL_FLOW_NOT_SPECIFIED; nwalCtrl.appRxPktQueue = NWAL_QUEUE_NOT_SPECIFIED; for (i=0; i < MAX_INTERFACES;i++) { nt_setupQosShapper(netapi_handle,(paEQosModeConfig_t*)&netTestQosShapperCfg[i]); } nwal_control(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, &nwalCtrl); } else if (c=='q') { nwalCtlInfo_t nwalCtrl; NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) netapi_handle; memset(&nwalCtrl, 0, sizeof(nwalCtlInfo_t)); nwalCtrl.pktCtl = NWAL_CTRL_CFG_EMAC_IF_EGRESS_EQOS_MODE; nwalCtrl.matchAction = NWAL_MATCH_ACTION_DISCARD; nwal_control(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, &nwalCtrl); QUIT=1; break; } } //wait for completion printf("main task now pending on thread completion\n"); for (i = 0; i < procs; i++) pthread_join( thrs[i], NULL ); free( thrs); } /************************************************* ************CLEAN UP**************************** ************************************************/ //get rid of rule, in the case that we are relaying packets //also close our netcp rx channel if (MAC) { ntoff_del_macs(netapi_handle); #if 0 netapi_netcpCfgDelMac(netapi_handle,0,&err); netapi_netcpCfgDelMac(netapi_handle,1,&err); #endif } ntoff_stop(); netapi_pktioClose(netcp_rx_chan,&err); netapi_pktioClose(netcp_tx_chan,&err); for(i=0;i < MAX_INTERFACES; i++) { netapi_pktioDelete(cpsw_tx_chan[i],&err); } //done netapi_shutdown(netapi_handle); //!finished! } static inline void sendit(Ti_Pkt *tip, int len, int out_port) { int err=0; PKTIO_METADATA_T meta2 = {PKTIO_META_TX,{0},0}; nwalTxPktInfo_t meta_tx2={0}; if (len<60) { unsigned int templen; char * p_pkt; len=60; Pktlib_getDataBuffer(tip,(uint8_t**)&p_pkt,&templen);//ignore templen Cppi_setData (Cppi_DescType_HOST, (Cppi_Desc *) tip, p_pkt,len); } Pktlib_setPacketLen(tip,len); meta_tx2.txFlag1 = NWAL_TX_FLAG1_META_DATA_VALID ; meta_tx2.ploadLen = len ; meta_tx2.enetPort=out_port; meta2.u.tx_meta=&meta_tx2; netapi_pktioSend(netcp_tx_chan,tip,&meta2,&err); } //receive callback for packets from net (for consumer) void recv_cb_net(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[], PKTIO_METADATA_T meta[], int n_pkts, uint64_t ts ) { int i; Ti_Pkt * tip; int len; unsigned long t1; unsigned long t2; unsigned long t3; unsigned long t4; pasahoLongInfo_t* protoInfo; int ifno; int out_port; t1= netapi_timing_start(); for(i=0;i= NCSUM)? NCSUM-1: len; csum_num[templen]+=1; csum_val[templen]+=val; csum_tim[templen]+= (unsigned long long) (cs2-cs1); } if (XMIT) { protoInfo=nwal_mGetProtoInfo(tip); ifno = nwal_mGetRxEmacPort( protoInfo); //---------------------------------------------------- //very trivial bridging -> just output to other port! //---------------------------------------------------- if (ifno ==1) out_port=2; else out_port=1; t3= netapi_timing_start(); sendit(tip,len,out_port); pkt_tx+=1; t4= netapi_timing_start(); pkt_tx_cycles += (t4-t3); } else { Pktlib_freePacket((Ti_Pkt*)tip); } } t2 = netapi_timing_start(); pkt_cb_cycles += (t2-t1); }