544 lines
14 KiB
C
544 lines
14 KiB
C
/*****************************************************************************/
|
|
/**
|
|
* Description: Implementations of 814 linklayer local record.
|
|
*
|
|
* Date: 2022-07-14 00:08
|
|
* LastEditors: Fan Hao
|
|
* LastEditTime: 2022-07-14 22:52
|
|
* Revisions: Rev 0.0
|
|
* History:
|
|
* [2022-07-14]: Initial version.
|
|
*
|
|
* Copyright(c) 2021 Beijing Institute of Technology.
|
|
* Lab of Communication and Networking
|
|
*
|
|
******************************************************************************/
|
|
|
|
/***************************** Include Files *********************************/
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include "linklayer814_types.h"
|
|
#include "node_list.h"
|
|
#include "../util/clist.h"
|
|
#include "../common.h"
|
|
#include "../error.h"
|
|
|
|
/***************** Macros (Inline Functions) Definitions *********************/
|
|
inline uint32_t L2_GetNodeListLen(NODE_LIST *list)
|
|
{
|
|
ASSERT(list != NULL);
|
|
return list->len;
|
|
}
|
|
/**************************** Type Definitions *******************************/
|
|
|
|
/************************** Variable Definitions *****************************/
|
|
static NODE_ENTRY util_entry;
|
|
/************************** Function Prototypes ******************************/
|
|
/**
|
|
* @brief helper function to free node entry.
|
|
*/
|
|
static void entry_free(void *val)
|
|
{
|
|
free(val);
|
|
}
|
|
|
|
/**
|
|
* @brief helper function to match node entries by nodeIds
|
|
*/
|
|
static int8_t entry_compare(void *a, void *b)
|
|
{
|
|
ASSERT(a != NULL);
|
|
ASSERT(b != NULL);
|
|
register uint8_t idA, idB;
|
|
idA = ((NODE_ENTRY *)a)->nodeInfo.nodeId;
|
|
idB = ((NODE_ENTRY *)b)->nodeInfo.nodeId;
|
|
if (idA == idB)
|
|
{
|
|
return 0;
|
|
}
|
|
else if (idA < idB)
|
|
{
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
/*****************************************************************************/
|
|
/**
|
|
* @brief Initialize node list
|
|
*
|
|
* @param list
|
|
*
|
|
* @return SUCCESS
|
|
* ENOMEM - not enough memory.
|
|
*
|
|
******************************************************************************/
|
|
int32_t L2_NodeList_Init(NODE_LIST **list)
|
|
{
|
|
(*list) = clist_new();
|
|
if (*list == NULL)
|
|
{
|
|
return ENOMEM;
|
|
}
|
|
(*list)->free = entry_free;
|
|
(*list)->compare = entry_compare;
|
|
return SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* @brief Clear all nodes in the node list, free allocated memory.
|
|
*
|
|
* @param list
|
|
*NONE
|
|
*
|
|
******************************************************************************/
|
|
void L2_NodeList_Clear(NODE_LIST *list)
|
|
{
|
|
ASSERT(list != NULL);
|
|
clist_clear(list);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* @brief Completely destroy node list.
|
|
*
|
|
* @param list
|
|
*
|
|
* @return NONE
|
|
*
|
|
******************************************************************************/
|
|
void L2_NodeList_Destroy(NODE_LIST *list)
|
|
{
|
|
clist_destroy(list);
|
|
}
|
|
/*****************************************************************************/
|
|
/**
|
|
* @brief Get node entry from node list base on node id.
|
|
*
|
|
* @param list
|
|
* @param nodeId
|
|
*
|
|
* @return Node entry
|
|
* NULL if node dose not exist.
|
|
*
|
|
******************************************************************************/
|
|
NODE_ENTRY *L2_GetNodeById(NODE_LIST *list, uint8_t nodeId)
|
|
{
|
|
ASSERT(list != NULL);
|
|
util_entry.nodeInfo.nodeId = nodeId;
|
|
clist_node_t *node = clist_find(list, &util_entry);
|
|
if (node == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
return ((NODE_ENTRY *)node->val);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* @brief Append a new node entry to the node list
|
|
*
|
|
* @param list
|
|
* @param nodeId
|
|
* @param nodeType
|
|
*
|
|
* @return SUCCESS Node was added successfully.
|
|
* Other Error occurred.(Node already exist, memory alloc error ect.)
|
|
*
|
|
******************************************************************************/
|
|
NODE_ENTRY *L2_AppendNode(NODE_LIST *list, uint8_t nodeId, L2_NODE_TYPE nodeType)
|
|
{
|
|
ASSERT(list != NULL);
|
|
if (L2_isNodeInList(list, nodeId))
|
|
{
|
|
DBG_WARNING("Node [%d] already exist.\n", nodeId);
|
|
return NULL;
|
|
}
|
|
DBG_INFO("Link layer appending node [%d] to node list.\n", nodeId);
|
|
NODE_ENTRY *nodeEntry = (NODE_ENTRY *)malloc(sizeof(NODE_ENTRY));
|
|
if (nodeEntry == NULL)
|
|
{
|
|
DBG_ERROR("Failed to allocated memory for nodeEntry.\n");
|
|
return NULL;
|
|
}
|
|
clist_node_t *node = clist_node_new(nodeEntry);
|
|
if (node == NULL)
|
|
{
|
|
DBG_ERROR("Failed to allocated memory for list node.\n");
|
|
free(nodeEntry);
|
|
return NULL;
|
|
}
|
|
nodeEntry->nodeInfo.nodeId = nodeId;
|
|
nodeEntry->nodeInfo.nodeType = (uint8_t)nodeType;
|
|
nodeEntry->nodeInfo.pos.x = 0;
|
|
nodeEntry->nodeInfo.pos.y = 0;
|
|
nodeEntry->nodeInfo.pos.z = 0;
|
|
nodeEntry->nodeInfo.speed.x = 0;
|
|
nodeEntry->nodeInfo.speed.y = 0;
|
|
nodeEntry->nodeInfo.speed.z = 0;
|
|
nodeEntry->nodeInfo.beamNo = 0;
|
|
nodeEntry->ttlCnt = 0;
|
|
clist_rpush(list, node);
|
|
return nodeEntry;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* @brief Delete a node in list based on node id.
|
|
*
|
|
* @param list
|
|
* @param nodeId
|
|
*
|
|
* @return SUCCESS Node has been successfully deleted.
|
|
* Other Node not exist.
|
|
*
|
|
******************************************************************************/
|
|
int32_t L2_DeleteNodeById(NODE_LIST *list, uint8_t nodeId)
|
|
{
|
|
ASSERT(list != NULL);
|
|
util_entry.nodeInfo.nodeId = nodeId;
|
|
clist_node_t *node = clist_find(list, &util_entry);
|
|
if (node == NULL)
|
|
{
|
|
DBG_WARNING("Node [%d] in not in node list, skip deleting process.\n", nodeId);
|
|
return SUCCESS;
|
|
}
|
|
DBG_INFO("Deleting node [%d].\n", nodeId);
|
|
clist_remove(list, node);
|
|
return SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* @brief Check whether the node is already in the node list.
|
|
*
|
|
* @param list
|
|
* @param nodeId
|
|
*
|
|
* @return true node in the list
|
|
* false node not in the list
|
|
*
|
|
******************************************************************************/
|
|
bool L2_isNodeInList(NODE_LIST *list, uint8_t nodeId)
|
|
{
|
|
ASSERT(list != NULL);
|
|
return (L2_GetNodeById(list, nodeId) != NULL);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* @brief Get the distance between me and the node.
|
|
*
|
|
* @param list
|
|
* @param nodeId
|
|
* @param dst A pointer to store distance.
|
|
*
|
|
* @return SUCCESS distance has been successfully store in dst
|
|
* FAILURE Node dose not exit.
|
|
*
|
|
******************************************************************************/
|
|
|
|
int32_t L2_GetDistance(NODE_LIST *list, COORD myCoord, uint8_t nodeId, double *dst)
|
|
{
|
|
ASSERT(list != NULL);
|
|
NODE_ENTRY *nodeEntry = L2_GetNodeById(list, nodeId);
|
|
if (nodeEntry == NULL)
|
|
{
|
|
return FAILURE;
|
|
}
|
|
else
|
|
{
|
|
*dst = Coord_Distance(myCoord, nodeEntry->nodeInfo.pos);
|
|
return SUCCESS;
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* @brief Update node positions information.
|
|
*
|
|
* @param list
|
|
* @param nodeId
|
|
* @param newPos A structure stores the corresponding node position info.
|
|
*
|
|
* @return SUCCESS update successfully.
|
|
* FAILURE node not exist.
|
|
*
|
|
******************************************************************************/
|
|
int32_t L2_UpdateNodePos(NODE_LIST *list, uint8_t nodeId, const COORD *newPos)
|
|
{
|
|
ASSERT(list != NULL);
|
|
NODE_ENTRY *nodeEntry = L2_GetNodeById(list, nodeId);
|
|
if (nodeEntry == NULL)
|
|
{
|
|
return FAILURE;
|
|
}
|
|
else
|
|
{
|
|
memcpy(&(nodeEntry->nodeInfo.pos), newPos, sizeof(COORD));
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* @brief Get node positions information.
|
|
*
|
|
* @param list
|
|
* @param nodeId
|
|
* @param newPos A structure stores the corresponding node position info.
|
|
*
|
|
* @return SUCCESS update successfully.
|
|
* FAILURE node not exist.
|
|
*
|
|
******************************************************************************/
|
|
int32_t L2_GetNodePos(NODE_LIST *list, uint8_t nodeId, COORD *pos)
|
|
{
|
|
ASSERT(list != NULL);
|
|
NODE_ENTRY *nodeEntry = L2_GetNodeById(list, nodeId);
|
|
if (nodeEntry == NULL)
|
|
{
|
|
return FAILURE;
|
|
}
|
|
else
|
|
{
|
|
memcpy(pos, &(nodeEntry->nodeInfo.pos), sizeof(COORD));
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* @brief Update node speed information.
|
|
*
|
|
* @param list
|
|
* @param nodeId
|
|
* @param newSpeed A structure stores the corresponding node speed info.
|
|
*
|
|
* @return SUCCESS update successfully.
|
|
* FAILURE node not exist.
|
|
*
|
|
******************************************************************************/
|
|
int32_t L2_UpdateNodeSpeed(NODE_LIST *list, uint8_t nodeId, const COORD *newSpeed)
|
|
{
|
|
ASSERT(list != NULL);
|
|
NODE_ENTRY *nodeEntry = L2_GetNodeById(list, nodeId);
|
|
if (nodeEntry == NULL)
|
|
{
|
|
return FAILURE;
|
|
}
|
|
else
|
|
{
|
|
memcpy(&(nodeEntry->nodeInfo.speed), newSpeed, sizeof(COORD));
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* @brief Get node speed information.
|
|
*
|
|
* @param list
|
|
* @param nodeId
|
|
* @param newSpeed A structure stores the corresponding node speed info.
|
|
*
|
|
* @return SUCCESS update successfully.
|
|
* FAILURE node not exist.
|
|
*
|
|
******************************************************************************/
|
|
int32_t L2_GetNodeSpeed(NODE_LIST *list, uint8_t nodeId, COORD *speed)
|
|
{
|
|
ASSERT(list != NULL);
|
|
NODE_ENTRY *nodeEntry = L2_GetNodeById(list, nodeId);
|
|
if (nodeEntry == NULL)
|
|
{
|
|
return FAILURE;
|
|
}
|
|
else
|
|
{
|
|
memcpy(speed, &(nodeEntry->nodeInfo.speed), sizeof(COORD));
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
/*****************************************************************************/
|
|
/**
|
|
* @brief Update node ACK status.
|
|
*
|
|
* @param list
|
|
* @param nodeId
|
|
* @param devi
|
|
*
|
|
* @return SUCCESS update successfully.
|
|
* FAILURE Node not exist.
|
|
*
|
|
******************************************************************************/
|
|
int32_t L2_UpdateNodeTimeDeviation(NODE_LIST *list, uint8_t nodeId, int32_t devi)
|
|
{
|
|
ASSERT(list != NULL);
|
|
NODE_ENTRY *nodeEntry = L2_GetNodeById(list, nodeId);
|
|
if (nodeEntry == NULL)
|
|
{
|
|
return FAILURE;
|
|
}
|
|
else
|
|
{
|
|
nodeEntry->timeDevi = devi;
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* @brief Increase TTL of specified node in the list.
|
|
*
|
|
* @param list
|
|
* @param inc cnt of slot to add
|
|
* @param nodeId
|
|
*
|
|
* @return NONE
|
|
*
|
|
******************************************************************************/
|
|
int32_t L2_IncNodeTTL(NODE_LIST *list, uint8_t nodeId, uint32_t inc)
|
|
{
|
|
ASSERT(list != NULL);
|
|
NODE_ENTRY *nodeEntry = L2_GetNodeById(list, nodeId);
|
|
if (nodeEntry == NULL)
|
|
{
|
|
return FAILURE;
|
|
}
|
|
else
|
|
{
|
|
nodeEntry->ttlCnt += inc;
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* @brief Reset node TTL based on node id.
|
|
*
|
|
* @param list
|
|
* @param nodeId
|
|
*
|
|
* @return SUCCESS TTL has been successfully cleared.
|
|
* FAILURE Node not exist.
|
|
*
|
|
******************************************************************************/
|
|
int32_t L2_RstNodeTTL(NODE_LIST *list, uint8_t nodeId)
|
|
{
|
|
ASSERT(list != NULL);
|
|
NODE_ENTRY *nodeEntry = L2_GetNodeById(list, nodeId);
|
|
if (nodeEntry == NULL)
|
|
{
|
|
return FAILURE;
|
|
}
|
|
else
|
|
{
|
|
nodeEntry->ttlCnt = 0;
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* @brief Get TTL of specified node in the list.
|
|
*
|
|
* @param list
|
|
* @param nodeId
|
|
* @param ttl
|
|
*
|
|
* @return NONE
|
|
*
|
|
******************************************************************************/
|
|
int32_t L2_GetNodeTTL(NODE_LIST *list, uint8_t nodeId, uint32_t *ttl)
|
|
{
|
|
ASSERT(list != NULL);
|
|
NODE_ENTRY *nodeEntry = L2_GetNodeById(list, nodeId);
|
|
if (nodeEntry == NULL)
|
|
{
|
|
return FAILURE;
|
|
}
|
|
else
|
|
{
|
|
*ttl = nodeEntry->ttlCnt;
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* @brief Implements a edit operations to each node.
|
|
*
|
|
* @param list
|
|
* @param param
|
|
* @param operation A pointer to a function handled "NODE_ENTRY*" as input
|
|
* which defines the operations need to be apply.
|
|
*
|
|
* @return SUCCESS Operations has been applied successfully to all nodes.
|
|
* Other Error occurred.
|
|
*
|
|
******************************************************************************/
|
|
int32_t L2_IterEditNode(NODE_LIST *list, const void *param, int32_t (*operation)(NODE_ENTRY *, const void *))
|
|
{
|
|
ASSERT(list != NULL);
|
|
int32_t Status;
|
|
clist_node_t *node;
|
|
clist_iterator_t *iter = clist_iterator_new(list, LIST_HEAD);
|
|
if (iter == NULL)
|
|
{
|
|
DBG_ERROR("Failed to initialize list iteration process.\n");
|
|
return EALLOC;
|
|
}
|
|
while ((node = clist_iterator_next(iter)))
|
|
{
|
|
Status = operation((NODE_ENTRY *)node->val, param);
|
|
if (Status != SUCCESS)
|
|
{
|
|
DBG_ERROR("Error occurred when iteratively edit node entry.\n");
|
|
break;
|
|
}
|
|
}
|
|
clist_iterator_destroy(iter);
|
|
return Status;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* @brief Filter all node, delete all the node not satisfied the condition.
|
|
*
|
|
* @param list
|
|
* @param condition A pointer to a function handled "NODE_ENTRY*" as input
|
|
* which defines the condition need to be verify.
|
|
*
|
|
* @return SUCCESS
|
|
*
|
|
******************************************************************************/
|
|
int32_t L2_IterDeleteNode(NODE_LIST *list, bool (*condition)(NODE_ENTRY *))
|
|
{
|
|
ASSERT(list != NULL);
|
|
clist_node_t *node;
|
|
clist_iterator_t *iter = clist_iterator_new(list, LIST_HEAD);
|
|
if (iter == NULL)
|
|
{
|
|
DBG_ERROR("Failed to initialize list iteration process.\n");
|
|
return EALLOC;
|
|
}
|
|
while ((node = clist_iterator_next(iter)))
|
|
{
|
|
if (condition((NODE_ENTRY *)node->val) == false)
|
|
{
|
|
clist_remove(list, node);
|
|
}
|
|
}
|
|
clist_iterator_destroy(iter);
|
|
return SUCCESS;
|
|
}
|