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

📄 c3eth.c

📁 这是交换机或路由器的交换软件部分
💻 C
📖 第 1 页 / 共 5 页
字号:
    }
    
    eth_sync_phy(EthNum);
        
    eth_add_freeq_buff(EthNum);
    
    return AOS_SUCC;
}

U32 eth_init(U16 usEthNum)
{
    void *pBuf;
    int Qid;
    iad_queueHnd qHandle;
    iad_ethHnd iadEthHnd;
    iad_Error errCode = IAD_SUCCESS;
    iad_queueReqPar qParam;
    iad_eth_CfgBlk  *p_ethCfgBlk;

    p_ethCfgBlk = &ethCfgBlk[usEthNum];
    
    //分配的硬件队列内存必须按Queue Size内存对齐,硬件队列的长度为1024,2048,4096,....

    // 发送后的报文缓冲软件队列,解决C3 MAC的一个BUG ,luke
    pBuf = eth_get_aligned_quebuf();
    if( pBuf == NULL )
    {
        AOS_ASSERT(0);
        return AOS_FAIL;
    }
    qParam.qType = IAD_QUEUE_SW;
    qParam.qBase = pBuf;
    qParam.qLen  = ALIGN_SIZE;
    qParam.elmLen= sizeof(iad_pktQBlk);
    if( (errCode = iad_queue_request( &qParam, &qHandle)) != IAD_SUCCESS )
    {
        aos_printf(MPE_SYS,"c3eth Sent sw queue error=0x%x",errCode);
        AOS_ASSERT(0);
        return AOS_FAIL;
    }
    else
    {
        p_ethCfgBlk->ethResources.SentQHnd   = qHandle;
    }
    iad_queue_setMinMax(p_ethCfgBlk->ethResources.SentQHnd,
                        0, 
                        128 );

    // requesting transmit queue
    pBuf = eth_get_aligned_quebuf();
    if( pBuf == NULL )
    {
        AOS_ASSERT(0);
        return AOS_FAIL;
    }
    p_ethCfgBlk->ethResources.pTxQMem = pBuf;
    qParam.qType = IAD_QUEUE_HW;
    qParam.qBase = pBuf;
    qParam.qLen  = ALIGN_SIZE;
    qParam.elmLen= sizeof(iad_pktQBlk);
    if( (errCode = iad_queue_request( &qParam, &qHandle)) != IAD_SUCCESS )
    {
        aos_printf(MPE_SYS,"c3eth tx hardware queue error=0x%x",errCode);
        AOS_ASSERT(0);
        return AOS_FAIL;
    }
    else
    {
        iad_queue_id(qHandle, &Qid);
        p_ethCfgBlk->ethResources.TxQHnd   = qHandle;
        p_ethCfgBlk->ethResources.TxQid    = Qid;
    }
    iad_queue_setMinMax(p_ethCfgBlk->ethResources.TxQHnd,
                        ETH_TX_MIN_Q_COUNT, 
                        ETH_TX_MAX_Q_COUNT );

    // 分配的硬件队列内存必须按Queue Size内存对齐,硬件队列的长度为1024,2048,4096,...
    pBuf = eth_get_aligned_quebuf();
    if( pBuf == NULL )
    {
        AOS_ASSERT(0);   
        return AOS_FAIL;
    }

    // requesting receive queue 
    p_ethCfgBlk->ethResources.pRxQMem = pBuf;
    qParam.qType  = IAD_QUEUE_HW;
    qParam.qBase  = pBuf;
    qParam.qLen   = ALIGN_SIZE;
    qParam.elmLen = sizeof(iad_pktQBlk);   
    if ( (errCode = iad_queue_request(&qParam, &qHandle))!= IAD_SUCCESS )
    {
        aos_printf(MPE_SYS,"c3eth rx hardware queue error=0x%x",errCode);    
        AOS_ASSERT(0);        
        return errCode;
    }
    else
    {
        iad_queue_id(qHandle, &Qid);
        p_ethCfgBlk->ethResources.RxQHnd   = qHandle;
        p_ethCfgBlk->ethResources.RxQid    = Qid;
    }

    iad_queue_setMinMax(p_ethCfgBlk->ethResources.RxQHnd,
                        ETH_RX_MIN_Q_COUNT, 
                        ETH_RX_MAX_Q_COUNT );


    // requesting receive free queue 
    pBuf = eth_get_aligned_quebuf();
    if( pBuf == NULL )
    {
        AOS_ASSERT(0);
        return AOS_FAIL;
    }

    p_ethCfgBlk->ethResources.pRxFreeQMem = (U8*)pBuf;
    qParam.qType  = IAD_QUEUE_HW;
    qParam.qBase  = pBuf;
    qParam.qLen   = ALIGN_SIZE;
    qParam.elmLen = sizeof(void*);
    if ( (errCode = iad_queue_request( &qParam,&qHandle))!= IAD_SUCCESS )
    {
        aos_printf(MPE_SYS,"c3eth free hardware queue error=0x%x",errCode);    
        AOS_ASSERT(0);
        return AOS_FAIL;
    }
    else
    {
        iad_queue_id(qHandle, &Qid);
        p_ethCfgBlk->ethResources.RxFreeQHnd   = qHandle;
        p_ethCfgBlk->ethResources.RxFreeQid    = Qid;
    }

    iad_queue_setMinMax(p_ethCfgBlk->ethResources.RxFreeQHnd,
                        FREEQ_ACCESS_MIN_LIMIT, 
                        FREEQ_ACCESS_MAX_LIMIT );

    // requesting transmit free queue 
    pBuf = eth_get_aligned_quebuf();
    if( pBuf == NULL )
    {
        AOS_ASSERT(0);
        return AOS_FAIL;
    }
    p_ethCfgBlk->ethResources.pTxFreeQMem = pBuf;
    qParam.qType  = IAD_QUEUE_HW;
    qParam.qBase  = pBuf;
    qParam.qLen   = ALIGN_SIZE;
    qParam.elmLen = sizeof(void*);
    if ( (errCode = iad_queue_request( &qParam,&qHandle))!= IAD_SUCCESS )
    {
        aos_printf(MPE_SYS,"c3eth free tx hardware queue error=0x%x",errCode);    
        AOS_ASSERT(0);
        return AOS_FAIL;
    }
    else
    {
        iad_queue_id(qHandle, &Qid);
        p_ethCfgBlk->ethResources.TxFreeQHnd   = qHandle;
        p_ethCfgBlk->ethResources.TxFreeQid    = Qid;        
    }
    
    if( IAD_SUCCESS != iad_eth_init_rmii( usEthNum,
                                          p_ethCfgBlk->ethResources.TxQHnd,
                                          p_ethCfgBlk->ethResources.RxQHnd,
                                          p_ethCfgBlk->ethResources.TxFreeQHnd,
                                          p_ethCfgBlk->ethResources.RxFreeQHnd,
                                          &iadEthHnd) )
    {

        AOS_ASSERT(0);
        return AOS_FAIL;
    }
    else
    {
        p_ethCfgBlk->iadEthHnd = iadEthHnd;
    }    

    return AOS_SUCC;
    
}

/*L2 MAC hash表处理*/

// 目前方式效率低,对小规模网络问题不大,如果使用空闲队列可以提高效率
L2_MAC_TABLE_S *eth_get_idle_l2mac(void)
{
    U32 i;
    
    for(i=0; i< L2MAC_HASH_MAX_NUM; i++ )
    {
        if( g_L2MacTable[i].flag )
            continue;

        return (g_L2MacTable+i);
    }
    
    return NULL;
}

void eth_l2mac_hash_add(U8 * pMac,L2_MAC_TABLE_S *pL2MacTableItem )
{
    U32 ulHashVal;
    HASH_NODE_S * pstHashNode;
        
    ulHashVal = L2MAC_HASH_GET_VAL(pMac);
    
    //先找到控制块
    pstHashNode = (HASH_NODE_S *)aos_dmem_alloc(MPE_ETH,SID_ETH_L2MAC,sizeof(HASH_NODE_S));
    if (AOS_ADDR_INVALID(pstHashNode))
    {
        AOS_ASSERT(0);
        return;
    }

    pstHashNode->ulHandle = (U32)pL2MacTableItem;
    
    //加入到hash中去
    hash_add_node(g_pstL2MacHashTbl, pstHashNode, ulHashVal, NULL);
	
    return;

}

S32 eth_l2mac_hash_match(VOID *pstData, HASH_NODE_S *pstHash)
{
    L2_MAC_TABLE_S *pL2MacTable;
    
    if(AOS_ADDR_INVALID(pstData)
    || AOS_ADDR_INVALID(pstHash))
    {
        return -1;
    }

    pL2MacTable = (L2_MAC_TABLE_S *)pstHash->ulHandle;

    if( 0 == aos_memcmp( pL2MacTable->mac, (U8*)pstData,6 ) )
    {
        return 0;
    }

    return -1;
}

void eth_l2mac_hash_remove(L2_MAC_TABLE_S *pL2MacItem)
{
    U32 ulHashVal;
    HASH_NODE_S * pstHashNode;

    if (AOS_ADDR_INVALID(pL2MacItem))
    {
        return;
    }

    ulHashVal = L2MAC_HASH_GET_VAL(pL2MacItem->mac);
    
    //先找到控制块
    pstHashNode = hash_find_node( g_pstL2MacHashTbl, ulHashVal, 
                                  (VOID *)pL2MacItem->mac, eth_l2mac_hash_match);

    if (AOS_ADDR_INVALID(pstHashNode))
    {
        return;
    }

    //这里只是简单的从hash表中去除,并不释放,在外面释放
    hash_delete_node(g_pstL2MacHashTbl, pstHashNode, ulHashVal);
	
    aos_dmem_free(pstHashNode);
    
    return ;
}

L2_MAC_TABLE_S * eth_l2mac_hash_find(U8 *pMac)
{
    HASH_NODE_S    *pstHashNode;
    U32            ulHashVal;
    L2_MAC_TABLE_S *pstL2MacItem;

    ulHashVal = L2MAC_HASH_GET_VAL(pMac);
    
    //先找到控制块
    pstHashNode = hash_find_node(g_pstL2MacHashTbl, ulHashVal, 
                                (VOID *)pMac, eth_l2mac_hash_match);
    if (AOS_ADDR_INVALID(pstHashNode))
    {
        return NULL;
    }

    pstL2MacItem = (L2_MAC_TABLE_S *)pstHashNode->ulHandle;
    if(AOS_ADDR_INVALID(pstL2MacItem))
    {
        return NULL;
    }
    
    return pstL2MacItem;
}

//根据报文的dstMac查找L2_MAC_TABLE的hash索引表,得到此报文的输出端口
U32 eth_get_l2_dstport(U8 *dstmac, U32 *pDstport )
{
    L2_MAC_TABLE_S *pstL2MacItem;

    // 广播地址的报文需要在两个出口都发送,查找肯定失败
    if( 0 == aos_memcmp( g_szBcastPacket,dstmac,6) )
    {
        return AOS_FAIL;
    }

    pstL2MacItem = eth_l2mac_hash_find(dstmac);
    if( pstL2MacItem == NULL )
    {
        return AOS_FAIL;    
    }
    
    *pDstport = pstL2MacItem->port;

    if( *pDstport > SERVICE_WAN_PORT )
    {
        AOS_ASSERT(0);
        *pDstport = SERVICE_LAN_PORT;
    }
    return AOS_SUCC;
}

void eth_send_packet( U32 dstport,U8 *pBuf,U32 ulLen,U32 bFlag )
{
    iad_eth_CfgBlk *p_ethCfgBlk;
    iad_pktDesc    pktDesc;
    unsigned int   count=0;
    U32            ret,i;
    U8             *pBufSent;
    iad_pktQBlk    PktSent;
        
    p_ethCfgBlk = &ethCfgBlk[dstport];
        
    pktDesc.pBase = pBuf;
    pktDesc.pData = pBuf;
    pktDesc.len   = ulLen;
    //aos_printf(0,"send a packet base=0x%x data=0x%x len=%d",
    //               pktDesc.pBase,pktDesc.pData,pktDesc.len);

    // 待发送的报文的地址压入SentQue软件队列,因为C3的硬件入队列非2048对齐的报文
    // 入TxFreeQHnd可能出错!! luke
    iad_queue_put(p_ethCfgBlk->ethResources.SentQHnd,
                  (iad_pktQBlk*)&pktDesc.pData,
                  sizeof(iad_pktQBlk));
    
    if( IAD_SUCCESS == iad_eth_pktSend(p_ethCfgBlk->iadEthHnd,&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 )
            {
                //AOS_ASSERT(0);
                break;
            }

            ret= iad_queue_get( p_ethCfgBlk->ethResources.SentQHnd,
                                &PktSent,sizeof(iad_pktQBlk));
            if (ret != IAD_SUCCESS )
            {
                //AOS_ASSERT(0);
                break;
            }

            pBufSent = PktSent.pData;
            if( AOS_ADDR_VALID(pBufSent) )
            {
                aos_dmem_free((S8*)mem_obj_head(pBufSent));
            }
            else
            {
                aos_printf(0,"Tx Free Queue Pointer=0x%x",pBufSent);
            }    
        }

        if( bFlag == ETH_NORMAL_SEND )
        {
            p_ethCfgBlk->ethStatSum.ulTxTotalFrames++;
            p_ethCfgBlk->ethStatSum.ulTxTotalBytes+=ulLen;        
        }
        else if( bFlag == ETH_FORWARD_SEND )
        {
            p_ethCfgBlk->ethStatSum.ulForwardFrames++;
            p_ethCfgBlk->ethStatSum.ulForwardBytes+=ulLen;  
        }
        return;
    }

    // 队列满时跳转到这里 
    // 队列满的时候,避免内存吊死,应该主动释放
    p_ethCfgBlk->ethStatSum.ulPacketTxBDFull++;
    aos_dmem_free(mem_obj_head(pBuf));    
    
    return;
}

U32 eth_send_mbuf_packet(U32 dstport,MBUF_S *pMBuf)
{
    U8 *pBuf,*pBufCopy;
    U32 ulLen;

⌨️ 快捷键说明

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