Files
kunlun/plc/halmac/peer/mac_peer.c

411 lines
10 KiB
C
Raw Normal View History

2024-09-28 14:24:04 +08:00
/****************************************************************************
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;
}