⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c3eth.c

📁 这是交换机或路由器的交换软件部分
💻 C
📖 第 1 页 / 共 5 页
字号:
        // disable eth interrupt 
	    IAD_REG_AND(IAD_NP_REG_BASE_ADDR, IAD_NP_REG_INTR_STEERING1,
	                ~IAD_NP_INTR_STATUS_ETH0_MASK);
	    IAD_REG_AND(IAD_NP_REG_BASE_ADDR, IAD_NP_REG_INTR_STEERING1, 
	                ~IAD_NP_INTR_STATUS_ETH1_MASK);

        g_bEthPollMode = TRUE;
        aos_task_resume(g_ulEthPollTaskId);
        aos_printf(MPE_SYS," Ethernet Intr->Poll mode.");
    }
    else
    {
        // enable eth interrupt 
	    IAD_REG_OR(IAD_NP_REG_BASE_ADDR, IAD_NP_REG_INTR_STEERING1,
	                IAD_NP_INTR_STATUS_ETH0_MASK);
	    IAD_REG_OR(IAD_NP_REG_BASE_ADDR, IAD_NP_REG_INTR_STEERING1, 
	                IAD_NP_INTR_STATUS_ETH1_MASK);

        g_bEthPollMode = FALSE;
        aos_task_suspend(g_ulEthPollTaskId);

        aos_printf(MPE_SYS," Ethernet Poll->Intr mode.");        
    }
}

void eth_recv_packet(unsigned int ethnum)
{
    iad_eth_CfgBlk *p_ethCfgBlk;
    iad_pktDesc     pktDesc,pktDescCpy;
    BOOL_T          bUpPacket;
    iad_Error       ret; 
    U32             peereth;
    U8              *pbuf     = NULL;    
    unsigned int    i,count;
    L2_MAC_TABLE_S *pL2TableItem;
    U8             *pLocalMac,*pBufCopy;
    #ifdef ETH_PHP_ENABLE
    iad_phpPktDesc  phpDesc;
    #endif

    p_ethCfgBlk = &ethCfgBlk[ethnum];

    iad_queue_count(p_ethCfgBlk->ethResources.RxQHnd,&count);
    for( i=0; i<count; i++ )
    {
        #ifdef ETH_PHP_ENABLE
        ret = iad_php_pktRcv(p_ethCfgBlk->hAutoConnHnd,&phpDesc);
        if( ret ==  IAD_QUEUE_EMPTY )
        {
            // 正常情况
            break; 
        } 
        else if( ret != IAD_SUCCESS )
        {
            AOS_ASSERT(0);
            break;
        }  

        pktDesc = phpDesc.pktDesc;
        if( IAD_SUCCESS != iad_queue_put(g_hPhpFreeHnd,
                                         &(phpDesc.phpTDPtr),sizeof(void*)) )
        {
            AOS_ASSERT(0);
            break;
        } 
        #else
        // 接收完成的以太网报文从RxQueue硬件队列中读出来
        ret = iad_eth_pktRcv(p_ethCfgBlk->iadEthHnd,&pktDesc);
        if( ret ==  IAD_QUEUE_EMPTY )
        {
            // 正常情况
            break; 
        } 
        else if( ret != IAD_SUCCESS )
        {
            AOS_ASSERT(0);
            break;
        }  
        #endif
        /******
        if( p_ethCfgBlk->RxBuff[p_ethCfgBlk->RxBDIndex] !=
              pktDesc.pBase )
        {
            aos_printf(0," Rxbuff[%d]=0x%x pBase=0x%x pData=0x%x",
                         p_ethCfgBlk->RxBDIndex,
                         p_ethCfgBlk->RxBuff[p_ethCfgBlk->RxBDIndex],
                         pktDesc.pBase,
                         pktDesc.pData );
        }
        ******/
        
        // 必须先判断队列空间是否合法
        if( AOS_ADDR_INVALID(pktDesc.pBase) )
        {                    
            // Rx吊死,复位Rx
            aos_printf(0," Reset Eth=%d Rx Queue,pktDesc.pBase=0x%x ",
                        ethnum,pktDesc.pBase);  
            break;              
        }

        bUpPacket = TRUE;
        /*
        aos_printf(0,"eth=%d recv packet status=0x%x Base=0x%x Data=0x%x len=%d",
                      ethnum,pktDesc.aux_data.eth_data.status,
                      pktDesc.pBase,
                      pktDesc.pData,
                      pktDesc.len);
        debug_mem_show(0,(U32)pktDesc.pData,pktDesc.len);
        */
        
        // Table 4-44 Receive Status
        // 正常单播报文和广播报文
        if( (pktDesc.aux_data.eth_data.status == 0) ||
             (pktDesc.aux_data.eth_data.status&0x0100) )
        {
            p_ethCfgBlk->ethStatSum.ulRxTotalFrames++; 
            p_ethCfgBlk->ethStatSum.ulRxTotalBytes+=pktDesc.len;
                                   
            // Bit8 BroadCast Packet  
            if( pktDesc.aux_data.eth_data.status & 0x0100 )
            {
                p_ethCfgBlk->ethStatSum.ulPacketBcNum++;
            }

            if( g_bEthBridgeFlag && g_bSoftBirdgeFlag )
            {
                //软件桥接处理:
                // 1.本机MAC地址交上层协议栈
                // 2.广播或多播MAC地址交上层协议栈同时转发                        
                // 3.其余MAC报文转发给对应端口WAN<->LAN, LAN<->WAN  
                pLocalMac = ethCfgBlk[SERVICE_WAN_PORT].ethResources.szUniMac;
                if( 0 == aos_memcmp(pLocalMac,pktDesc.pData,6) )
                {
                    // 1.本机报文,继续...
                    bUpPacket = TRUE;
                }
                else if(0 == aos_memcmp( g_szBcastPacket,
                                         pktDesc.pData,6) )
                {   
                    // 2.广播MAC地址交上层协议栈同时转发
                    bUpPacket = TRUE;
                    //增加内存块引用索引,避免内存释放两次
                    //mem_buf_inc_ref(mem_obj_head(pktDesc.pBase));
                    // 另一种方法虽然开销大一点,拷贝一份更安全,luke                    
                    pBufCopy = (U8*)eth_get_aligned_buff();
                    if( pBufCopy )
                    {
                        peereth = ((ethnum==SERVICE_WAN_PORT)?SERVICE_LAN_PORT
                                    :SERVICE_WAN_PORT );
                        //pktDescCpy.pBase = pBufCopy;            
                        pktDescCpy.pData = pBufCopy+ETH_HEADER_RESERV_LEN;
                        pktDescCpy.len   = pktDesc.len;
                        aos_memcpy(pBufCopy+ETH_HEADER_RESERV_LEN,pktDesc.pData,pktDesc.len);
                        //eth_forward_packet(peereth, &pktDescCpy);
                        eth_send_packet(peereth,pktDescCpy.pData,pktDescCpy.len,ETH_FORWARD_SEND);
                    }
                }
                else
                {
                    // 3.其余MAC报文转发给对应端口
                    bUpPacket = FALSE;
                    peereth = ((ethnum==SERVICE_WAN_PORT)?SERVICE_LAN_PORT
                                :SERVICE_WAN_PORT );
                    //eth_forward_packet(peereth, &pktDesc);                            
                    eth_send_packet(peereth,pktDesc.pData,pktDesc.len,ETH_FORWARD_SEND);
                }

                // 4. L2MACTABLE srcMac地址学习,为了提高效率,地址写习限制在UP报文
                if( bUpPacket )
                {
                    pL2TableItem = eth_l2mac_hash_find(pktDesc.pData+6);
                    if( pL2TableItem )
                    {
                        // 已经存在此L2表项,刷新时间为缺省最大老化时间
                        pL2TableItem->port = ethnum; // 更新端口
                        pL2TableItem->time = L2MAC_AGE_TIME;
                    }
                    else
                    {
                        // 学习到新的L2表项
                        //先得到一个空闲的L2MAC表项
                        pL2TableItem = eth_get_idle_l2mac();
                        if( pL2TableItem )
                        {
                            aos_memcpy(pL2TableItem->mac,pktDesc.pData+6,6);
                            pL2TableItem->port = ethnum;
                            pL2TableItem->time = L2MAC_AGE_TIME;
                            pL2TableItem->flag = TRUE;
                            eth_l2mac_hash_add(pktDesc.pData+6,pL2TableItem);
                            /*
                            aos_printf(0,"L2 MAC Add MAC=%x-%x-%x-%x-%x-%x port=%d ",
                                      pL2TableItem->mac[0], pL2TableItem->mac[1],
                                      pL2TableItem->mac[2], pL2TableItem->mac[3],
                                      pL2TableItem->mac[4], pL2TableItem->mac[5],
                                      pL2TableItem->port );    
                            */          
                        }
                        else
                        {
                            aos_printf( MPE_ETH,"L2 MAC Table is FULL!");
                        }
                    }
                }
                
            }
            
            // 为RxFreeQueue补充一个空闲的以太网报文接收缓冲区
            pbuf = eth_get_aligned_buff();
            if( pbuf )
            {   
                if( IAD_SUCCESS != iad_queue_put(p_ethCfgBlk->ethResources.RxFreeQHnd,
                                                 &pbuf,sizeof(void*)) )
                {
                    AOS_ASSERT(0);
                } 
                else
                {
                    if( bUpPacket )
                    {
                        eth_stream_up(ethnum,pktDesc.pData,pktDesc.len);
                    }    
                    else
                    {                           
                        aos_dmem_free((S8*)mem_obj_head(pktDesc.pData));
                    }
                } 
                ///p_ethCfgBlk->RxBuff[p_ethCfgBlk->RxBDIndex] = pbuf;
            }
            else
            {
                // 内存不足,将原来的接收缓冲区继续放入RxFreeQueue
                iad_queue_put(p_ethCfgBlk->ethResources.RxFreeQHnd,
                              &(pktDesc.pBase),sizeof(void*));
                AOS_ASSERT(0);
            } 
            
        }
        else 
        {
            if( pktDesc.aux_data.eth_data.status & 0x0200 )
            {
                // Bit9 MultiCast Packet
                //目前,设备没有需要接收多播报文,丢弃
                p_ethCfgBlk->ethStatSum.ulPacketMcNum++;
            }

            if( pktDesc.aux_data.eth_data.status & 0x0080 )                
            {    // Bit7 Length Error,丢弃                  
                p_ethCfgBlk->ethStatSum.ulPacketLenErNum++;
            }
            
            if( pktDesc.aux_data.eth_data.status & 0x0040 )                
            {    // Bit6 CRC Packet,丢弃                  
                p_ethCfgBlk->ethStatSum.ulPacketCrcErNum++;
            }

            if( pktDesc.aux_data.eth_data.status & 0x0020 )                
            {    // Bit5 Short Runt Frame ,丢弃                  
                p_ethCfgBlk->ethStatSum.ulPacketShortFrameNum++;
            }

            if( pktDesc.aux_data.eth_data.status & 0x0010 )                
            {    // Bit4 Rx FIFO Overrun ,丢弃                  
                p_ethCfgBlk->ethStatSum.ulPacketOvRunNum++;
            }

            if( pktDesc.aux_data.eth_data.status & 0x0008 )                
            {    // Bit3 Rx Late Collision ,丢弃                  
                p_ethCfgBlk->ethStatSum.ulPacketColliNum++;
            }

            if( pktDesc.aux_data.eth_data.status & 0x0004 )                
            {    // Bit2 Frame Alignment Error,丢弃                  
                p_ethCfgBlk->ethStatSum.ulPacketNoAlignErNum++;
            }                                            

            // 接收一个无效的以太报文后,
            // 将当前接收缓冲区返回到RxFreeQue
            iad_queue_put(p_ethCfgBlk->ethResources.RxFreeQHnd,
                          &(pktDesc.pBase),sizeof(void*));
        }
    }
    
    /// debug 
    ///p_ethCfgBlk->RxBDIndex++;
    ///p_ethCfgBlk->RxBDIndex %= FREEQ_ACCESS_MAX_LIMIT;
    return;
}

// 以太网接收中断处理,中断模式接收响应速度快,但是当网口流量很大时,
// 由于频繁中断带来过大系统开销,将影响吞吐量,此时应该关闭中断模式
void eth_intr_proc(unsigned int ethnum)
{
    U32 intStatus;

    if( ethnum > 1 )
    {
        return;
    }

    if( ethnum )
    {
        intStatus = IAD_REG_RD_WORD(IAD_ETH2_REG_BASE_ADDR, IAD_ETH_REG_INTR_CLEAR);
        IAD_REG_WR(IAD_ETH2_REG_BASE_ADDR,IAD_ETH_REG_INTR_CLEAR,
                   intStatus );    
    }
    else
    {
        intStatus = IAD_REG_RD_WORD(IAD_ETH1_REG_BASE_ADDR, IAD_ETH_REG_INTR_CLEAR);
        IAD_REG_WR(IAD_ETH1_REG_BASE_ADDR,IAD_ETH_REG_INTR_CLEAR,
                   intStatus );    
    }               

    if( intStatus&IAD_RX_PACKET_DONE )
    {
        eth_recv_packet(ethnum);
    }    
        
}

// 10ms 以太网接收报文任务,轮询模式下系统开销小,当以太网口流量很大时,关闭
// 中断模式,进入轮询模式
void  eth_recv_poll(void )
{
    int ethnum;   
    
    while( 1 )
    {   
        if( FALSE == g_bEthPollMode )
        {
            aos_task_suspend(g_ulEthPollTaskId);
        }
    
        for( ethnum= SERVICE_WAN_PORT; ethnum >= SERVICE_LAN_PORT ; ethnum-- )   
        {   
            // 优先处理WAN口,然后处理LAN口,一次接收完硬件队列中的所有接收完成报文
            eth_recv_packet(ethnum);
        }

        // 10 ms Poll Task interval 
        aos_task_delay(10);                 
    }     
            
}

// 老化处理每L2_AGING_PERIOD秒被调用一次
void eth_l2mac_aging(U32 ulTimerName, U32 ulPara )
{
    U32 i;

    if( g_bSoftBirdgeFlag == FALSE )
        return;
        
    for(i=0; i< L2MAC_HASH_MAX_NUM; i++ )
    {
        if( !g_L2MacTable[i].flag )
            continue;

        g_L2MacTable[i].time -= L2_AGING_PERIOD;
        if( g_L2MacTable[i].time < 0)
        {
           //清除关联的HASH索引表
           eth_l2mac_hash_remove(&g_L2MacTable[i]);
        
           //需要清除此项目
           /*
           aos_printf(0,"L2 MAC Aging MAC=%x-%x-%x-%x-%x-%x port=%d ",
                      g_L2MacTable[i].mac[0], g_L2MacTable[i].mac[1],
                      g_L2MacTable[i].mac[2], g_L2MacTable[i].mac[3],
                      g_L2MacTable[i].mac[4], g_L2MacTable[i].mac[5],
                      g_L2MacTable[i].port );
           */           
           aos_memset(&g_L2MacTable[i],0,sizeof(L2_MAC_TABLE_S));
        }
    }    
    
}


U32 eth_forward_packet(U32 peereth, iad_pktDesc *p_pktDesc )
{
    iad_eth_CfgBlk *p_ethCfgBlk;    
    U32 ret,i,ulLen;
    unsigned int count=0;
    char *pBuf,*pBufSent;
    iad_pktQBlk PktSent;
    
    p_ethCfgBlk = &ethCfgBlk[peereth];
    
    pBuf  = p_pktDesc->pData;
    ulLen = p_pktDesc->len;

    // 待发送的报文的地址压入SentQue软件队列,因为C3的硬件入队列非2048对齐的报文
    // 入TxFreeQHnd可能出错!! luke
    iad_queue_put(p_ethCfgBlk->ethResources.SentQHnd,
                  (iad_pktQBlk*)&pBuf,
                  sizeof(iad_pktQBlk));    

    if( IAD_SUCCESS == iad_eth_pktSend(p_ethCfgBlk->iadEthHnd,p_pktDesc) )
    {
        ret = iad_queue_count(p_ethCfgBlk->ethResources.TxFreeQHnd,
                              &count);
        if (ret != IAD_SUCCESS )
        {
            AOS_ASSERT(0);
        }                              

        //将已经发送完成的缓冲区释放
        for(i=0; i<count; i++)
        {
            ret= iad_queue_get( p_ethCfgBlk->ethResources.TxFreeQHnd,
                                &pBuf,sizeof(void*));
            if (ret != IAD_SUCCESS )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -