411 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			411 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/****************************************************************************
 | 
						|
 | 
						|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
 | 
						|
 | 
						|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
 | 
						|
be copied by any method or incorporated into another program without
 | 
						|
the express written consent of Aerospace C.Power. This Information or any portion
 | 
						|
thereof remains the property of Aerospace C.Power. The Information contained herein
 | 
						|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
 | 
						|
liability for its use in any way and conveys no license or title under
 | 
						|
any patent or copyright and makes no representation or warranty that this
 | 
						|
Information is free from patent or copyright infringement.
 | 
						|
 | 
						|
****************************************************************************/
 | 
						|
#include "mac_peer.h"
 | 
						|
#include "plc_peer_api.h"
 | 
						|
#include "mac_pdev.h"
 | 
						|
#include "mac_vdev.h"
 | 
						|
#include "mac_desc_engine.h"
 | 
						|
#include "iot_errno.h"
 | 
						|
#include "mac_stream.h"
 | 
						|
#include "iot_queue.h"
 | 
						|
#include "hash_table.h"
 | 
						|
#include "rate_control.h"
 | 
						|
#include "plc_protocol.h"
 | 
						|
#include "iot_io.h"
 | 
						|
#include "os_utils_api.h"
 | 
						|
#include "rf_rate_control.h"
 | 
						|
 | 
						|
mac_peer_t *peer_hash_tbl[peer_tbl_sz] = { 0 };
 | 
						|
 | 
						|
 | 
						|
uint32_t plc_create_peer(pdevid_t pid, vdevid_t vid, tei_t tei)
 | 
						|
{
 | 
						|
    (void)pid;
 | 
						|
    (void)vid;
 | 
						|
    (void)tei;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t plc_free_peer(pdevid_t pid, vdevid_t vid, tei_t tei)
 | 
						|
{
 | 
						|
    (void)pid;
 | 
						|
    (void)vid;
 | 
						|
    (void)tei;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t mac_peer_alloc(mac_vdev_t *vdev, tei_t tei,
 | 
						|
    uint32_t is_self, uint32_t is_direct_conn, \
 | 
						|
    uint32_t is_sub_peer, uint32_t is_proxy_peer, mac_peer_t **peer)
 | 
						|
{
 | 
						|
    mac_peer_t *tmp;
 | 
						|
    (void)is_direct_conn;
 | 
						|
    uint32_t ret = mac_desc_get(&g_mac_desc_eng, \
 | 
						|
        PLC_MAC_PEER_POOL, (void **)&tmp);
 | 
						|
    if (ret) {
 | 
						|
        mac_vdev_del_overflow_peer(vdev);
 | 
						|
        ret = mac_desc_get(&g_mac_desc_eng, \
 | 
						|
            PLC_MAC_PEER_POOL, (void **)&tmp);
 | 
						|
    }
 | 
						|
    if (ret) {
 | 
						|
        mac_peer_stream_overflow_cnt_dbglog();
 | 
						|
        return ERR_NOMEM;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        /* init peer */
 | 
						|
        os_mem_set(tmp, 0, sizeof(mac_peer_t));
 | 
						|
        tmp->pdev_id = vdev->ref_pdev_id;
 | 
						|
        tmp->vdev_id = vdev->vdev_id;
 | 
						|
        tmp->tei = tei;
 | 
						|
        tmp->is_self_peer = is_self & 0x1;
 | 
						|
        if (tei == PLC_TEI_BCAST) {
 | 
						|
            /* if bcast, should not be self peer */
 | 
						|
            IOT_ASSERT(is_self == 0);
 | 
						|
            tmp->is_bcast_peer = 1;
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            tmp->is_bcast_peer = 0;
 | 
						|
        }
 | 
						|
        tmp->next = NULL;
 | 
						|
        if (mac_tei_map_is_set((mac_tei_map_t *)vdev->sub_peer_bitmap, tei)) {
 | 
						|
            tmp->is_sub_peer = 1;
 | 
						|
        } else {
 | 
						|
            tmp->is_sub_peer = !!is_sub_peer;
 | 
						|
        }
 | 
						|
        tmp->is_proxy_peer = !!is_proxy_peer;
 | 
						|
        iot_list_init(&tmp->vdev_node);
 | 
						|
        /* add into vdev peer list */
 | 
						|
        vdev_add_peer(vdev, tmp);
 | 
						|
        /* add into peer hash table */
 | 
						|
        peer_hash_tbl_add(tmp);
 | 
						|
 | 
						|
        /* rate info init */
 | 
						|
        mac_rate_ctxt_init(tmp);
 | 
						|
        /* rf rate info init */
 | 
						|
        mac_rf_rate_ctxt_init(tmp);
 | 
						|
 | 
						|
        /* perr cnt ++*/
 | 
						|
        vdev->peer_cnt++;
 | 
						|
 | 
						|
        if (tmp->is_proxy_peer) {
 | 
						|
            vdev->proxy_peer_cnt++;
 | 
						|
        }
 | 
						|
 | 
						|
        /* return value for the new peer */
 | 
						|
        *peer = tmp;
 | 
						|
    }
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
mac_peer_t * IRAM_ATTR find_peer(mac_vdev_t *vdev,
 | 
						|
    nid_t nid, tei_t tei)
 | 
						|
{
 | 
						|
    mac_peer_t *tmp;
 | 
						|
    peer_hash_src_t hash;
 | 
						|
    hash.vid = vdev->vdev_id;
 | 
						|
    hash.nid = nid;
 | 
						|
    hash.tei = tei;
 | 
						|
    nid_t tmp_nid;
 | 
						|
 | 
						|
    if (!vdev->mac_vdev_cfg.is_reduced_vdev
 | 
						|
        && (ERR_OK == vdev_get_nid(vdev, &tmp_nid))) {
 | 
						|
        if (nid != tmp_nid) {
 | 
						|
            return NULL;
 | 
						|
        }
 | 
						|
        uint32_t hash_code = peer_get_hash(hash);
 | 
						|
        mac_peer_t **tmp_entry_addr = \
 | 
						|
            &peer_hash_tbl[hash_code];
 | 
						|
        for (tmp = *tmp_entry_addr; tmp; tmp = tmp->next)
 | 
						|
        {
 | 
						|
            if (tmp->tei == tei) {
 | 
						|
                return tmp;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        return vdev->self_peer;
 | 
						|
    }
 | 
						|
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/* @return - 0 for successful
 | 
						|
*           other for failed
 | 
						|
*/
 | 
						|
uint32_t peer_hash_tbl_add(mac_peer_t *peer)
 | 
						|
{
 | 
						|
    nid_t nid;
 | 
						|
 | 
						|
    if (!peer) {
 | 
						|
        return ERR_INVAL;
 | 
						|
    }
 | 
						|
    mac_vdev_t *vdev = get_vdev_ptr(peer->pdev_id, peer->vdev_id);
 | 
						|
    if (!vdev) {
 | 
						|
        return ERR_INVAL;
 | 
						|
    }
 | 
						|
 | 
						|
    peer_hash_src_t hash = { 0 };
 | 
						|
    hash.vid = vdev->vdev_id;
 | 
						|
    hash.tei = (tei_t)peer->tei;
 | 
						|
    if (ERR_OK != vdev_get_nid(vdev, &nid)) {
 | 
						|
        if (peer->is_bcast_peer || peer->is_self_peer) {
 | 
						|
            nid = (nid_t)PLC_NID_INVALID;
 | 
						|
        } else {
 | 
						|
            IOT_ASSERT(0);
 | 
						|
            return ERR_INVAL;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    hash.nid = nid;
 | 
						|
 | 
						|
    if (find_peer(vdev, \
 | 
						|
        hash.nid, hash.tei)) {
 | 
						|
        /* if already exist */
 | 
						|
        return ERR_EXIST;
 | 
						|
    }
 | 
						|
    uint32_t hash_code = peer_get_hash(hash);
 | 
						|
    mac_peer_t **peer_entry = \
 | 
						|
        &peer_hash_tbl[hash_code];
 | 
						|
    if ( *peer_entry == NULL)
 | 
						|
    {
 | 
						|
        *peer_entry = peer;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        peer->next = *peer_entry;
 | 
						|
        *peer_entry = peer;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t peer_hash_tbl_del(mac_peer_t *peer)
 | 
						|
{
 | 
						|
    uint32_t hash_code;
 | 
						|
    peer_hash_src_t hash = { 0 };
 | 
						|
    mac_vdev_t *vdev = get_vdev_ptr(peer->pdev_id, peer->vdev_id);
 | 
						|
    mac_peer_t *entry = NULL;
 | 
						|
    nid_t nid;
 | 
						|
 | 
						|
    hash.vid = vdev->vdev_id;
 | 
						|
    hash.tei = (tei_t)peer->tei;
 | 
						|
    if (ERR_OK != vdev_get_nid(vdev, &nid)) {
 | 
						|
        if (peer->is_bcast_peer || peer->is_self_peer) {
 | 
						|
            nid = (nid_t)PLC_NID_INVALID;
 | 
						|
        } else {
 | 
						|
            IOT_ASSERT(0);
 | 
						|
            return ERR_INVAL;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    hash.nid = nid;
 | 
						|
    hash_code = peer_get_hash(hash);
 | 
						|
    for(mac_peer_t **cur = &peer_hash_tbl[hash_code]; *cur;){
 | 
						|
        entry = *cur;
 | 
						|
        if(peer == entry){
 | 
						|
            *cur = entry->next;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        else{
 | 
						|
            cur = &entry->next;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    if(peer != entry){
 | 
						|
        hash.tei = 0;
 | 
						|
        hash_code = peer_get_hash(hash);
 | 
						|
        for(mac_peer_t **cur = &peer_hash_tbl[hash_code]; *cur;){
 | 
						|
            entry = *cur;
 | 
						|
            if(peer == entry){
 | 
						|
                *cur = entry->next;
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            else{
 | 
						|
                cur = &entry->next;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    if(peer != entry){
 | 
						|
        hash.tei = 0;
 | 
						|
        hash.nid = 0;
 | 
						|
        hash_code = peer_get_hash(hash);
 | 
						|
        for(mac_peer_t **cur = &peer_hash_tbl[hash_code]; *cur;){
 | 
						|
            entry = *cur;
 | 
						|
            if(peer == entry){
 | 
						|
                *cur = entry->next;
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            else{
 | 
						|
                cur = &entry->next;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (peer != entry) {
 | 
						|
        iot_printf("peer:0x%x not found.\n", peer);
 | 
						|
        IOT_ASSERT(0);
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
 | 
						|
    return ERR_OK;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/* return 0 for success, else for failed */
 | 
						|
uint32_t peer_add_stream(mac_peer_t *peer, void *stream)
 | 
						|
{
 | 
						|
    if (!peer || !stream)
 | 
						|
    {
 | 
						|
        return ERR_INVAL;
 | 
						|
    }
 | 
						|
    mac_stream_t *str = (mac_stream_t *)stream;
 | 
						|
    if (!str->is_tx) {
 | 
						|
        peer->rate_info.last_rx_ts = os_boot_time32();
 | 
						|
    }
 | 
						|
    iot_single_list_add(&str->peer_node, &peer->data_stream_list);
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t peer_del_stream(mac_peer_t *peer, void *stream)
 | 
						|
{
 | 
						|
    mac_stream_t *str = (mac_stream_t*)stream;
 | 
						|
    IOT_ASSERT(str->peer == peer);
 | 
						|
 | 
						|
    /* delete from peer streamlist */
 | 
						|
    iot_single_list_del(&str->peer_node, &peer->data_stream_list);
 | 
						|
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t peer_del_all_stream(mac_peer_t *peer, uint32_t del_tx_rx_stream)
 | 
						|
{
 | 
						|
    uint32_t i = 0;
 | 
						|
    mac_stream_t *stream;
 | 
						|
    iot_single_list_head_t *tmp;
 | 
						|
 | 
						|
again:
 | 
						|
    tmp = peer->data_stream_list;
 | 
						|
    while (tmp) {
 | 
						|
        stream = iot_list_entry(tmp, mac_stream_t, peer_node);
 | 
						|
        if ((del_tx_rx_stream == DEL_TX_STREAM && !stream->is_tx)
 | 
						|
            || (del_tx_rx_stream == DEL_RX_STREAM && stream->is_tx)) {
 | 
						|
            tmp = tmp->next;
 | 
						|
            continue;
 | 
						|
        }
 | 
						|
        mac_stream_free(peer, stream);
 | 
						|
        i++;
 | 
						|
        goto again;
 | 
						|
    }
 | 
						|
    return i;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t mac_peer_free(mac_vdev_t *vdev, mac_peer_t *peer)
 | 
						|
{
 | 
						|
    mac_peer_t *tmp = peer;
 | 
						|
 | 
						|
    /* del peer from vdev */
 | 
						|
    vdev_del_peer(vdev, tmp);
 | 
						|
    /* del peer from hash table */
 | 
						|
    if(tmp->is_self_peer == 0 &&\
 | 
						|
        tmp->is_bcast_peer == 0){
 | 
						|
        /* if not self or bcast peer,
 | 
						|
         * del this peer in hash table
 | 
						|
         */
 | 
						|
        peer_hash_tbl_del(tmp);
 | 
						|
    }
 | 
						|
 | 
						|
    peer_del_all_stream(tmp, DEL_ALL_STREAM);
 | 
						|
 | 
						|
    /* destroy peer */
 | 
						|
    if(tmp->is_self_peer == 0 && \
 | 
						|
        tmp->is_bcast_peer == 0){
 | 
						|
        /* if not self or bcast peer
 | 
						|
         * free the peer
 | 
						|
         */
 | 
						|
        mac_desc_free(&g_mac_desc_eng, PLC_MAC_PEER_POOL, tmp);
 | 
						|
        /* peer cnt --*/
 | 
						|
        vdev->peer_cnt--;
 | 
						|
 | 
						|
        if (tmp->is_proxy_peer) {
 | 
						|
            vdev->proxy_peer_cnt--;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t is_peer_empty(mac_peer_t *peer)
 | 
						|
{
 | 
						|
    mac_stream_t *stream;
 | 
						|
    iot_single_list_head_t *tmp;
 | 
						|
 | 
						|
    tmp = peer->data_stream_list;
 | 
						|
    while (tmp) {
 | 
						|
        stream = iot_list_entry(tmp, mac_stream_t, peer_node);
 | 
						|
        if (is_stream_empty(stream) == 0) {
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
        tmp = tmp->next;
 | 
						|
    }
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t mac_peer_del_temp_peer(mac_peer_t *peer)
 | 
						|
{
 | 
						|
    IOT_ASSERT(peer);
 | 
						|
    mac_vdev_t *vdev = get_vdev_ptr(peer->pdev_id, peer->vdev_id);
 | 
						|
    IOT_ASSERT(vdev);
 | 
						|
    if ((mac_vdev_cfg_get_node_role(vdev) != PLC_DEV_ROLE_CCO) && \
 | 
						|
        peer->is_self_peer == 0 && peer->is_bcast_peer == 0 && \
 | 
						|
        peer->is_sub_peer == 0 && peer->is_proxy_peer == 0 && \
 | 
						|
        is_peer_empty(peer) == 1) {
 | 
						|
        iot_printf("DEL none sub peer 0x%x:tei=%d\n", \
 | 
						|
            peer, peer->tei);
 | 
						|
        mac_peer_free(vdev, peer);
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t mac_peer_del_overflow_peer(mac_peer_t *peer)
 | 
						|
{
 | 
						|
    if (!peer) {
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
    mac_vdev_t *vdev = get_vdev_ptr(peer->pdev_id, peer->vdev_id);
 | 
						|
    IOT_ASSERT(vdev);
 | 
						|
    if ((peer->is_self_peer == 0) && (peer->is_bcast_peer == 0) &&
 | 
						|
        (peer->is_proxy_peer == 0)) {
 | 
						|
        if (peer->is_sub_peer) {
 | 
						|
            mac_add_overflow_peer_del_cnt(PEER_SUB);
 | 
						|
        } else {
 | 
						|
            mac_add_overflow_peer_del_cnt(PEER_TMP);
 | 
						|
        }
 | 
						|
        mac_peer_free(vdev, peer);
 | 
						|
        return ERR_OK;
 | 
						|
    }
 | 
						|
    return ERR_FAIL;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t mac_peer_rx_ts_update(mac_peer_t *peer, uint32_t cur_ts)
 | 
						|
{
 | 
						|
    IOT_ASSERT(peer);
 | 
						|
    if(peer->is_bcast_peer || peer->is_self_peer)
 | 
						|
        return 1;
 | 
						|
    peer->rate_info.last_rx_ts = cur_ts;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 |