📄 c3eth.c
字号:
U32 anotherport;
if( NULL == pMBuf )
{
AOS_ASSERT(0);
return AOS_FAIL;
}
if ( dstport > CPU_ETH_PORT_NUM )
{
AOS_ASSERT(0);
mbuf_destroy(pMBuf);
return AOS_FAIL;
}
pBuf = MBUF_MTOD(pMBuf,U8*);
ulLen = MBUF_GET_TOTAL_DATA_LENGTH(pMBuf);
/***********
pBuf2 =eth_get_aligned_buff();
if( pBuf2 )
{
pBuf2 += ETH_HEADER_RESERV_LEN;
aos_memcpy(pBuf2,pBuf,ulLen);
aos_dmem_free(pBuf);
pBuf = pBuf2;
}
**************/
if( g_bEthBridgeFlag )
{
if( g_bSoftBirdgeFlag )
{
// 只有WAN口和LAN口同时UP的时候才激活 g_bSoftBirdgeFlag
// 软件桥模式下,需要模拟以太交换网的功能,发出的报文需要确定出口
//根据报文目的MAC地址在L2 HASH表查找,确定报文的最终出口(0 or 1?)
if( AOS_FAIL == eth_get_l2_dstport(pBuf,&dstport) )
{
//如果查找结果为空,需要Flooding报文,将报文向两个出口发送
//这个报文需要发送两次,增加内存块引用索引,避免内存释放两次
#if 0
mem_buf_inc_ref(mem_obj_head(pBuf));
anotherport = ((dstport==0)?1:0);
///eth_send_packet(anotherport,pBuf,ulLen);
pktDesc.pBase = pBufCopy;
pktDesc.pData = pBufCopy+ETH_HEADER_RESERV_LEN;
pktDesc.len = ulLen;
iad_eth_pktSend(ethCfgBlk[anotherport].iadEthHnd,
&pktDesc);
#else
// 另一种方法虽然开销大一点,拷贝一份,但更安全
pBufCopy = (U8*)eth_get_aligned_buff();
if( pBufCopy )
{
aos_memcpy(pBufCopy+ETH_HEADER_RESERV_LEN,pBuf,ulLen);
anotherport = ((dstport==0)?1:0);
eth_send_packet( anotherport,
pBufCopy+ETH_HEADER_RESERV_LEN,
ulLen,
ETH_COPY_SEND );
}
else
{
AOS_ASSERT(0);
}
#endif
}
}
else
{
//对双口网关,桥接模式下缺省网口为WAN口,当WAN口LinkDown的时候从LAN口发送
if( !g_ulWanLinkStatus )
{
dstport = SERVICE_LAN_PORT;
}
}
}
//释放mbuf控制头
aos_dmem_free(pMBuf);
eth_send_packet(dstport,pBuf,ulLen,ETH_NORMAL_SEND);
return AOS_SUCC;
}
U32 eth_send(U32 if_ulPhyLink, MBUF_S *pMBuf)
{
U32 ulRet = 0;
U32 ulBlockNum;
U32 EthNum;
EthNum=((ETH_DRV_IF *)if_ulPhyLink)->chan_usPort;
if ( EthNum >= CPU_ETH_PORT_NUM )
{
AOS_ASSERT(0);
return AOS_FAIL;
}
if( NULL == pMBuf )
{
AOS_ASSERT(0);
return AOS_FAIL;
}
// 网口未启动时,丢弃发送报文
if( !ethCfgBlk[EthNum].initCfgDone )
{
mbuf_destroy(pMBuf);
return AOS_FAIL;
}
if( (g_ulWanLinkStatus == FALSE) &&
(g_ulLanLinkStatus == FALSE) )
{
mbuf_destroy(pMBuf);
return AOS_FAIL;
}
ulBlockNum = MBUF_GET_DATA_BLOCK_NUMBER(pMBuf);
if( ulBlockNum > 1 )
{
MBUF_COMPRESS(pMBuf, 1, MPE_ETH, ulRet );
if( AOS_SUCC != ulRet )
{
AOS_ASSERT(0);
mbuf_destroy( pMBuf);
return AOS_FAIL;
}
}
eth_send_mbuf_packet(EthNum,pMBuf);
return AOS_SUCC;
}
#ifdef ETH_PHP_ENABLE
U32 eth_php_init(void)
{
iad_phpInitPar InitPar;
iad_queueReqPar qParam;
U8 *pBuf;
iad_Error errCode = IAD_SUCCESS;
U32 i;
// PHP使用了4个硬件队列,分别为PhpFreeQue,OverflowQue,TaskQue,ResultQue
pBuf = aos_dmem_alloc( MPE_ETH, SID_ETH_PHP, ALIGN_SIZE*5);
if( pBuf == NULL )
{
AOS_ASSERT(0);
return AOS_FAIL;
}
if( (U32)pBuf%ALIGN_SIZE )
{
// not alligned 补齐
(U32)pBuf &=(~(ALIGN_SIZE-1));
}
//为php申请FreeQue硬件队列空间
qParam.qType = IAD_QUEUE_HW;
qParam.qBase = pBuf;
qParam.qLen = ALIGN_SIZE;
qParam.elmLen= sizeof(unsigned int);
if( (errCode = iad_queue_request( &qParam, &g_hPhpFreeHnd)) != IAD_SUCCESS )
{
aos_printf(MPE_SYS,"c3eth php free hardware queue error=0x%x",errCode);
return AOS_FAIL;
}
//为php申请OverFlowQue硬件队列空间
pBuf += ALIGN_SIZE;
qParam.qType = IAD_QUEUE_HW;
qParam.qBase = pBuf;
qParam.qLen = ALIGN_SIZE;
qParam.elmLen= sizeof(unsigned int);
if( (errCode = iad_queue_request( &qParam, &g_hPhpOverHnd)) != IAD_SUCCESS )
{
aos_printf(MPE_SYS,"c3eth php overflow queue error=0x%x",errCode);
AOS_ASSERT(0);
return AOS_FAIL;
}
pBuf += ALIGN_SIZE;
qParam.qBase = pBuf;
qParam.qLen = ALIGN_SIZE;
qParam.elmLen= sizeof(unsigned int);
if( (errCode = iad_queue_request( &qParam, &g_hPhpTaskHnd)) != IAD_SUCCESS )
{
aos_printf(MPE_SYS,"c3eth php Task queue error=0x%x",errCode);
return AOS_FAIL;
}
pBuf += ALIGN_SIZE;
qParam.qBase = pBuf;
qParam.qLen = ALIGN_SIZE;
qParam.elmLen= sizeof(unsigned int);
if( (errCode = iad_queue_request( &qParam, &g_hResultHnd)) != IAD_SUCCESS )
{
aos_printf(MPE_SYS,"c3eth php result queue error=0x%x",errCode);
return AOS_FAIL;
}
//The PHP freeQ is a pointer
//queue where the pointer is pointing to a 64-byte PHP TD (task descriptor)
InitPar.phpMode = IAD_PHP_AUTO_INGRESS_ONLY;
InitPar.phpFreeQHnd = g_hPhpFreeHnd;
InitPar.phpFreeQMin = 1;
InitPar.phpFreeQMax = N_PHP_TD_NUM;
InitPar.phpOverflowQHnd = g_hPhpOverHnd;
InitPar.phpTaskQHnd = g_hPhpTaskHnd;
InitPar.systemFreeQHnd = g_hPhpFreeHnd;
errCode = iad_php_init(&InitPar);
if( errCode != IAD_SUCCESS )
{
aos_printf( MPE_SYS, "c3eth php init error=0x%x",errCode);
return AOS_FAIL;
}
pBuf = aos_dmem_alloc( MPE_ETH, SID_ETH_PHPTD, IAD_PHP_TASK_DESC_LEN*N_PHP_TD_NUM );
if( pBuf == NULL )
{
AOS_ASSERT(0);
return AOS_FAIL;
}
for( i=0; i< N_PHP_TD_NUM; i++)
{
if( IAD_SUCCESS != iad_queue_put(g_hPhpFreeHnd,
&pBuf,sizeof(void*)) )
{
AOS_ASSERT(0);
return AOS_FAIL;
}
pBuf += IAD_PHP_TASK_DESC_LEN;
}
return AOS_SUCC;
}
#endif
U32 eth_end( void )
{
iad_eth_setEnableTx(ethCfgBlk[0].iadEthHnd, TRUE);
iad_eth_setEnableRx(ethCfgBlk[1].iadEthHnd, TRUE);
return AOS_SUCC;
}
/*******************************************************************************
*
* EthStart - start the device
*
* This function connect interrupts and start the
* device running in interrupt mode.
*
* RETURNS: OK or AOS_FAIL
*
*/
U32 eth_start( U32 ethnum)
{
iad_eth_CfgBlk *p_ethCfgBlk;
static BOOL_T bInit = FALSE;
U32 ulRet;
p_ethCfgBlk = ðCfgBlk[ethnum];
if( bInit == FALSE )
{
bInit = TRUE;
// Poll任务只创建一次
ulRet = aos_task_create("ethpoll",
10240,
TASK_PRIO_HIGHEST,
AOS_TASK_NOPREEMPT,
eth_recv_poll,
NULL,
&g_ulEthPollTaskId );
if( AOS_SUCC != ulRet)
{
AOS_ASSERT(0);
return AOS_FAIL;
}
// DMA Burst size 32bytes
//IAD_REG_WR(IAD_ETH1_REG_BASE_ADDR,IAD_ETH_REG_DMA_BURST_SZ,0);
//IAD_REG_WR(IAD_ETH2_REG_BASE_ADDR,IAD_ETH_REG_DMA_BURST_SZ,0);
// 中断模式启动可以减少延时,但是流量很大的时候开销急剧增加
IAD_REG_WR(IAD_ETH1_REG_BASE_ADDR,IAD_ETH_REG_INTR_ENABLE,
IAD_RX_PACKET_DONE);
IAD_REG_WR(IAD_ETH2_REG_BASE_ADDR,IAD_ETH_REG_INTR_ENABLE,
IAD_RX_PACKET_DONE);
iad_interrupt_hook(IAD_IV_ETH0, (VOIDFUNCTIONPTR)eth_intr_proc, SERVICE_LAN_PORT);
iad_interrupt_hook(IAD_IV_ETH1, (VOIDFUNCTIONPTR)eth_intr_proc, SERVICE_WAN_PORT);
if( FALSE == g_bEthPollMode )
{
iad_enable_interrupt(IAD_IV_ETH0);
iad_enable_interrupt(IAD_IV_ETH1);
}
if( g_bEthBridgeFlag )
{
g_pstL2MacHashTbl = hash_create_table(L2MAC_HASH_MAX_NUM , NULL);
if(AOS_ADDR_INVALID(g_pstL2MacHashTbl))
{
AOS_ASSERT(0);
return AOS_FAIL;
}
// 启动周期定时器老化
aos_callbacktimer_start(&g_L2AgeTmr, MPE_ETH, L2_AGING_PERIOD*1000,
0,(U32)NULL, eth_l2mac_aging, AOS_TIMER_LOOP);
}
#ifdef ETH_PHP_ENABLE
if( eth_php_init()!= AOS_SUCC )
{
AOS_ASSERT(0);
return AOS_FAIL;
}
#endif
}
{
U32 ethmode;
if( ethnum == SERVICE_WAN_PORT )
cfm_get_parameter(CMD_WAN_ETH_MODE, (VOID*)ðmode, sizeof(U32));
else
cfm_get_parameter(CMD_LAN_ETH_MODE, (VOID*)ðmode, sizeof(U32));
//设置以太网工作模式
eth_set_workmode( ethnum, ethmode);
}
#ifdef ETH_PHP_ENABLE
{
iad_phpConnPar ConnPar;
iad_phpConnHnd ConnHnd;
// eth PHP AutoIngress Connection
// ConnHnd用于轮询任务里面的iad_php_pktRcv() AutoIngress Mode
// iad_php_get() Manual Mode
ConnPar.connMode = IAD_PHP_AUTO_INGRESS_ONLY;
ConnPar.ingress.autoI.inPortType = IAD_PHP_ETH;
ConnPar.ingress.autoI.port.ethHnd = p_ethCfgBlk->iadEthHnd;
ConnPar.ingress.autoI.uCodeSel = IAD_PHP_ETH_TCPIPCHKSUM_N_TCPHASH;
ConnPar.resultQHnd = g_hResultHnd;
ulRet = iad_php_connSetup( &ConnPar, &ConnHnd );
if( IAD_SUCCESS != ulRet )
{
aos_printf(MPE_SYS,"c3eth php autoingress conn error=0x%x",ulRet);
return AOS_FAIL;
}
p_ethCfgBlk->hAutoConnHnd = ConnHnd;
//aos_printf(MPE_SYS,"c3eth php autoingress conn id=%d",ConnHnd);
}
#endif
/* Now, enable Tx and RX */
iad_eth_setEnableTx(p_ethCfgBlk->iadEthHnd, TRUE);
iad_eth_setEnableRx(p_ethCfgBlk->iadEthHnd, TRUE);
p_ethCfgBlk->initCfgDone = TRUE;
return AOS_SUCC;
}
//每秒计算一次网口流速
void eth_packet_rate_proc(void)
{
static U32 ulOrgCnt=0;
U32 delta;
// 对网关一个网口不可能产生高流速,所以采用WAN口为基准计算网口的流速
if( ethCfgBlk[SERVICE_WAN_PORT].ethStatSum.ulRxTotalFrames >= ulOrgCnt )
{
delta=ethCfgBlk[SERVICE_WAN_PORT].ethStatSum.ulRxTotalFrames-ulOrgCnt;
}
else
{
// 32位翻转
delta= 0xFFFFFFFF-ulOrgCnt+ethCfgBlk[SERVICE_WAN_PORT].ethStatSum.ulRxTotalFrames;
}
ulOrgCnt = ethCfgBlk[SERVICE_WAN_PORT].ethStatSum.ulRxTotalFrames;
//aos_printf(0,"eth wan delta=%d",delta);
if( delta > g_ulEthHiRate )
{
if( FALSE == g_bEthPollMode )
eth_recv_mode_switch(TRUE);
}
else if( delta < g_ulEthLowRate )
{
if( TRUE == g_bEthPollMode )
eth_recv_mode_switch(FALSE);
}
//此次计算以太网接收模式不变化
return;
}
void eth_recv_mode_switch(U32 bPollMode)
{
if( bPollMode )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -