summaryrefslogtreecommitdiffstats
path: root/src/framework/rd/nstack_rd_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/framework/rd/nstack_rd_api.c')
-rw-r--r--src/framework/rd/nstack_rd_api.c766
1 files changed, 766 insertions, 0 deletions
diff --git a/src/framework/rd/nstack_rd_api.c b/src/framework/rd/nstack_rd_api.c
new file mode 100644
index 0000000..e791e04
--- /dev/null
+++ b/src/framework/rd/nstack_rd_api.c
@@ -0,0 +1,766 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include "nstack_rd_api.h"
+#include "nstack_rd_data.h"
+#include "nsfw_mem_api.h"
+#include "nsfw_recycle_api.h"
+#include "nstack_log.h"
+#include "nstack_securec.h"
+#include "nsfw_common_defs.h"
+#include "nstack_ip_addr.h"
+
+#define RD_AGE_MAX_TIME 3
+
+rd_route_table *g_rd_table_handle[NSTACK_MAX_MODULE_NUM];
+
+void *nstack_rd_malloc(const char *name)
+{
+ void *p = NULL;
+
+ if (!name)
+ {
+ NSSOC_LOGERR("NULL pointer is not allowed!");
+ return NULL;
+ }
+ if (strlen(name) >= NSFW_MEM_NAME_LENTH)
+ {
+ NSSOC_LOGERR("name length overflow!");
+ return NULL;
+ }
+
+ nsfw_mem_zone zone = {
+ {NSFW_SHMEM, NSFW_PROC_APP, {0}
+ }
+ ,
+ sizeof(rd_route_table),
+ NSFW_SOCKET_ANY,
+ 0
+ };
+
+ if (EOK != strcpy_s(zone.stname.aname, NSFW_MEM_NAME_LENTH, name))
+ {
+ NSSOC_LOGERR("strcpy_s failed!");
+ return NULL;
+ }
+
+ p = nsfw_mem_zone_create(&zone);
+ if (!p)
+ {
+ NSSOC_LOGERR("nstack_rd_malloc failed!");
+ return NULL;
+ }
+
+ nstack_rd_table_clear(p);
+
+ return p;
+}
+
+void *nstack_local_rd_malloc(void)
+{
+ void *p;
+
+ p = malloc(sizeof(rd_route_table));
+ if (!p)
+ {
+ return NULL;
+ }
+ nstack_rd_table_clear(p);
+ return p;
+}
+
+void nstack_local_rd_free(void *p)
+{
+ if (p)
+ free(p);
+}
+
+int nstack_rd_free(const char *name)
+{
+ if (!name)
+ {
+ NSSOC_LOGERR("NULL pointer is not allowed!");
+ return -1;
+ }
+ if (strlen(name) >= NSFW_MEM_NAME_LENTH)
+ {
+ NSSOC_LOGERR("name length overflow!");
+ return -1;
+ }
+
+ nsfw_mem_name pname = {
+ NSFW_SHMEM,
+ NSFW_PROC_APP,
+ {0}
+ };
+
+ if (EOK != strcpy_s(pname.aname, NSFW_MEM_NAME_LENTH, name))
+ {
+ NSSOC_LOGERR("strcpy_s failed!");
+ return -1;
+ }
+
+ return nsfw_mem_zone_release(&pname);
+}
+
+void nstack_rd_table_clear(void *p)
+{
+ rd_route_table *table = (rd_route_table *) p;
+
+ (void) memset_s(table, sizeof(rd_route_table), 0, sizeof(rd_route_table));
+ table->size = NSTACK_RD_DATA_MAX;
+ table->icnt = 0;
+ table->rdtbl_ver = 0;
+ DMM_SPINLOCK_MALLOC(table->rd_lock, 1);
+}
+
+/*****************************************************************************
+* Prototype : nstack_rd_ip_node_insert
+* Description : insert a rd_ip_data into list
+* Input : char *name
+* rd_ip_data *data
+* Output : None
+* Return Value : int
+* Calls :
+* Called By : daemon-stack
+*****************************************************************************/
+int nstack_rd_ip_node_insert(const char *name, rd_ip_data * data, void *table)
+{
+ rd_route_table *handle = (rd_route_table *) table;
+ if (!handle)
+ {
+ NSSOC_LOGERR("nstack rd mng not inited");
+ return -1;
+ }
+ int iindex = 0;
+ rd_route_node *pnode = NULL;
+ int agetime = 0;
+ int ageindex = -1;
+ int freeindex = -1;
+ int repeatflag = 0;
+
+ for (iindex = 0; iindex < NSTACK_RD_DATA_MAX; iindex++)
+ {
+ pnode = &(handle->node[iindex]);
+ /*record the index of first free element */
+ if (RD_NODE_USELESS == pnode->flag)
+ {
+ if (-1 == freeindex)
+ {
+ freeindex = iindex;
+ NSSOC_LOGINF("nstack rd ip free element index:%d was found",
+ iindex);
+ }
+ continue;
+ }
+
+ /*if is using, and repeat just set flag */
+ if (RD_NODE_USING == pnode->flag)
+ {
+ if (MASK_V(pnode->data.ipdata.addr, pnode->data.ipdata.masklen)
+ == MASK_V(data->addr, data->masklen))
+ {
+ NSSOC_LOGWAR
+ ("stack=%s, ip addr=*.*.%u.%u, masklen:%u was repeat",
+ name, FUZZY_IP_VAR(&data->addr), data->masklen);
+ repeatflag = 1;
+ }
+ continue;
+ }
+
+ /*if flag is deleting, just update the age time, if agetime is on, just set flag to free */
+ if (RD_NODE_DELETING == pnode->flag)
+ {
+ pnode->agetime++;
+ if (pnode->agetime >= RD_AGE_MAX_TIME)
+ {
+ pnode->flag = RD_NODE_USELESS;
+ NSSOC_LOGINF
+ ("nstack rd ip element index=%d,addr=*.*.%u.%u,masklen=%u was delete and set to free",
+ iindex, FUZZY_IP_VAR(&pnode->data.ipdata.addr),
+ pnode->data.ipdata.masklen);
+ }
+ /*record delete time */
+ if (agetime < pnode->agetime)
+ {
+ agetime = pnode->agetime;
+ ageindex = iindex;
+ }
+ continue;
+ }
+ }
+
+ /*if repeat, just return */
+ if (1 == repeatflag)
+ {
+ return 0;
+ }
+ if (-1 == freeindex)
+ {
+ if (-1 != ageindex)
+ {
+ freeindex = ageindex;
+ }
+ else
+ {
+ NSSOC_LOGERR
+ ("the rd table is full,nstack=%s, rd addr=*.*.%u.%u, masklen=%u can't be inserted",
+ name, FUZZY_IP_VAR(&data->addr), data->masklen);
+ return -1;
+ }
+ }
+ pnode = &(handle->node[freeindex]);
+ /*if no free found, just reuse the big agetime */
+ dmm_spin_lock_with_pid(&handle->rd_lock);
+ if (EOK != strcpy_s(pnode->data.stack_name, RD_PLANE_NAMELEN, name))
+ {
+ NSSOC_LOGERR("strcpy_s failed]copy_name=%s", name);
+ }
+ pnode->data.type = RD_DATA_TYPE_IP;
+ pnode->agetime = 0;
+ pnode->data.ipdata.addr = data->addr;
+ pnode->data.ipdata.masklen = data->masklen;
+ pnode->data.ipdata.resev[0] = 0;
+ pnode->data.ipdata.resev[1] = 0;
+ pnode->flag = RD_NODE_USING; /*last set */
+ handle->icnt++;
+ __sync_fetch_and_add(&handle->rdtbl_ver, 1); /*[MISRA 2004 Rule 14.2] */
+ dmm_spin_unlock(&handle->rd_lock);
+ NSSOC_LOGINF
+ ("nstack=%s, rd addr=*.*.%u.%u, masklen=%u index was inserted", name,
+ FUZZY_IP_VAR(&data->addr), data->masklen);
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : nstack_rd_ip_node_delete
+* Description : rd data delete
+* Input : rd_ip_data *data
+* Output : None
+* Return Value : int
+* Calls :
+* Called By : daemon-stack
+*****************************************************************************/
+int nstack_rd_ip_node_delete(rd_ip_data * data, void *table)
+{
+ int iindex = 0;
+ rd_route_table *handle = (rd_route_table *) table;
+ rd_route_node *pnode = NULL;
+
+ if (!handle)
+ {
+ NSSOC_LOGERR("nstack rd mng not inited");
+ return -1;
+ }
+
+ for (iindex = 0; iindex < NSTACK_RD_DATA_MAX; iindex++)
+ {
+ pnode = &(handle->node[iindex]);
+ if ((RD_NODE_USING == pnode->flag)
+ && (MASK_V(pnode->data.ipdata.addr, pnode->data.ipdata.masklen)
+ == MASK_V(data->addr, data->masklen)))
+ {
+ dmm_spin_lock_with_pid(&handle->rd_lock);
+ pnode->flag = RD_NODE_DELETING; /*just set deleting state */
+ pnode->agetime = 0;
+ handle->icnt--;
+ NSSOC_LOGINF
+ ("nstack rd delete:%s, addr=*.*.%u.%u, masklen=%u index:%d was delete",
+ pnode->data.stack_name, FUZZY_IP_VAR(&data->addr),
+ data->masklen, iindex);
+ __sync_fetch_and_add(&handle->rdtbl_ver, 1);
+ dmm_spin_unlock(&handle->rd_lock);
+ NSSOC_LOGINF
+ ("nstack rd delete:%s, addr:0x%x, masklen:%u index:%d was delete",
+ pnode->data.stack_name, ntohl(data->addr), data->masklen,
+ iindex);
+ return 0;
+ }
+ }
+ NSSOC_LOGINF
+ ("nstack rd delete, addr=*.*.%u.%u, masklen=%u index was not found",
+ FUZZY_IP_VAR(&data->addr), data->masklen);
+ return 0;
+}
+
+char *ipv6_ntop(ip6_addr_t host_addr)
+{
+ static char buf[INET6_ADDRSTRLEN];
+ ip6_addr_t net_addr;
+
+ net_addr = host_addr;
+ if (inet_ntop(AF_INET6, &net_addr.addr32, buf, INET6_ADDRSTRLEN) == NULL)
+ {
+ return "invalid IPv6 address";
+ }
+ return buf;
+}
+
+/*****************************************************************************
+* Description : insert a rd_ip6_data into list
+* Called By : daemon-stack
+* Notice : the IP insert is in network order byte
+*****************************************************************************/
+int nstack_rd_ip6_node_insert(const char *name, rd_ip6_data * data,
+ void *table)
+{
+ rd_route_table *handle = (rd_route_table *) table;
+ if (!handle)
+ {
+ NSSOC_LOGERR("nstack rd mng not inited");
+ return -1;
+ }
+ int iindex = 0;
+ rd_route_node *pnode = NULL;
+ int agetime = 0;
+ int ageindex = -1;
+ int freeindex = -1;
+ int repeatflag = 0;
+
+ for (iindex = 0; iindex < NSTACK_RD_DATA_MAX; iindex++)
+ {
+ pnode = &(handle->node[iindex]);
+ /*record the index of first free element */
+ if (RD_NODE_USELESS == pnode->flag)
+ {
+ if (-1 == freeindex)
+ {
+ freeindex = iindex;
+ NSSOC_LOGINF("nstack rd ip free element index:%d was found",
+ iindex);
+ }
+ continue;
+ }
+
+ /*if is using, and repeat just set flag */
+ if (RD_NODE_USING == pnode->flag)
+ {
+ if (ip6_addr_match
+ (&pnode->data.ip6data.addr, &data->addr, data->masklen))
+ {
+ NSSOC_LOGWAR
+ ("nstack:%s, index:%d, old_addr:%s, masklen:%u was repeat",
+ name, iindex, ipv6_ntop(pnode->data.ip6data.addr),
+ data->masklen);
+ repeatflag = 1;
+ }
+ continue;
+ }
+
+ /*if flag is deleting, just update the age time, if agetime is on, just set flag to free */
+ if (RD_NODE_DELETING == pnode->flag)
+ {
+ pnode->agetime++;
+ if (pnode->agetime >= RD_AGE_MAX_TIME)
+ {
+ pnode->flag = RD_NODE_USELESS;
+ NSSOC_LOGINF
+ ("nstack rd ip element index:%d addr:%s, masklen:%u was delete and set to free",
+ iindex, ipv6_ntop(pnode->data.ip6data.addr),
+ pnode->data.ipdata.masklen);
+ }
+ /*record delete time */
+ if (agetime < pnode->agetime)
+ {
+ agetime = pnode->agetime;
+ ageindex = iindex;
+ }
+ continue;
+ }
+ }
+
+ /*if repeat, just return */
+ if (1 == repeatflag)
+ {
+ return 0;
+ }
+ if (-1 == freeindex)
+ {
+ if (-1 != ageindex)
+ {
+ freeindex = ageindex;
+ }
+ else
+ {
+ NSSOC_LOGERR
+ ("the rd table is full,nstack:%s, rd addr:%s, masklen:%u can't be inserted",
+ name, ipv6_ntop(data->addr), data->masklen);
+ return -1;
+ }
+ }
+ pnode = &(handle->node[freeindex]);
+ /*if no free found, just reuse the big agetime */
+ dmm_spin_lock_with_pid(&handle->rd_lock);
+ if (EOK != strcpy_s(pnode->data.stack_name, RD_PLANE_NAMELEN, name))
+ {
+ NSSOC_LOGERR("strcpy_s failed]copy_name=%s", name);
+ }
+ pnode->data.type = RD_DATA_TYPE_IP6;
+ pnode->agetime = 0;
+ pnode->data.ip6data.addr.addr32[0] = data->addr.addr32[0];
+ pnode->data.ip6data.addr.addr32[1] = data->addr.addr32[1];
+ pnode->data.ip6data.addr.addr32[2] = data->addr.addr32[2];
+ pnode->data.ip6data.addr.addr32[3] = data->addr.addr32[3];
+ pnode->data.ip6data.masklen = data->masklen;
+ pnode->flag = RD_NODE_USING; /*last set */
+ handle->icnt++;
+ __sync_fetch_and_add(&handle->rdtbl_ver, 1);
+ dmm_spin_unlock(&handle->rd_lock);
+ NSSOC_LOGINF("nstack:%s, rd addr:%s, masklen:%u index was inserted",
+ name, ipv6_ntop(data->addr), data->masklen);
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : nstack_rd_ip6_node_delete
+* Description : rd data delete, only set flag
+* Called By : daemon-stack
+* Notice : the IP delete is in network order byte
+*****************************************************************************/
+int nstack_rd_ip6_node_delete(rd_ip6_data * data, void *table)
+{
+ int iindex = 0;
+ rd_route_table *handle = (rd_route_table *) table;
+ rd_route_node *pnode = NULL;
+
+ if (!handle)
+ {
+ NSSOC_LOGERR("nstack rd mng not inited");
+ return -1;
+ }
+
+ for (iindex = 0; iindex < NSTACK_RD_DATA_MAX; iindex++)
+ {
+ pnode = &(handle->node[iindex]);
+ if ((RD_NODE_USING == pnode->flag)
+ &&
+ (ip6_addr_match
+ (&pnode->data.ip6data.addr, &data->addr, data->masklen)))
+ {
+ dmm_spin_lock_with_pid(&handle->rd_lock);
+ pnode->flag = RD_NODE_DELETING; /*just set deleting state */
+ pnode->agetime = 0;
+ handle->icnt--;
+ __sync_fetch_and_add(&handle->rdtbl_ver, 1);
+ dmm_spin_unlock(&handle->rd_lock);
+ NSSOC_LOGINF
+ ("nstack rd delete:%s, addr:%s, masklen:%u index:%d was delete",
+ pnode->data.stack_name, ipv6_ntop(data->addr),
+ data->masklen, iindex);
+ return 0;
+ }
+ }
+ NSSOC_LOGINF("nstack rd delete, addr:%s, masklen:%u index was not found",
+ ipv6_ntop(data->addr), data->masklen);
+ return 0;
+}
+
+NSTACK_STATIC nsfw_rcc_stat rd_recyle_lock(u32 pid, void *pdata, u16 rec_type)
+{
+ int i;
+
+ for (i = 0; i < NSTACK_MAX_MODULE_NUM; i++)
+ {
+ if (g_rd_table_handle[i] && pid == g_rd_table_handle[i]->rd_lock.lock)
+ {
+ (void)
+ __sync_bool_compare_and_swap(&g_rd_table_handle[i]->rd_lock.
+ lock, pid, 0);
+ NSFW_LOGWAR("rd locked]pid=%u", pid);
+ }
+ }
+
+ return NSFW_RCC_CONTINUE;
+}
+
+REGIST_RECYCLE_LOCK_REL(rd_recyle_lock, NULL, NSFW_PROC_NULL)
+ int nstack_rd_type_node_insert(const char *name, rd_type_data * data,
+ void *table)
+{
+ rd_route_table *handle = (rd_route_table *) table;
+ if (!handle || !data)
+ {
+ NSSOC_LOGERR("invalid parameters!");
+ return -1;
+ }
+ int iindex = 0;
+ rd_route_node *pnode = NULL;
+ int agetime = 0;
+ int ageindex = -1;
+ int freeindex = -1;
+ int repeatflag = 0;
+
+ for (iindex = 0; iindex < NSTACK_RD_DATA_MAX; iindex++)
+ {
+ pnode = &(handle->node[iindex]);
+ /*record the index of first free element */
+ if (RD_NODE_USELESS == pnode->flag)
+ {
+ if (-1 == freeindex)
+ {
+ freeindex = iindex;
+ NSSOC_LOGINF("free element index:%d was found", iindex);
+ }
+ continue;
+ }
+
+ /*if is using, and repeat just set flag */
+ if (RD_NODE_USING == pnode->flag)
+ {
+ if (pnode->data.type_data.value == data->value
+ && pnode->data.type_data.attr == data->attr)
+ {
+ NSSOC_LOGWAR("find duplicate node, type:%u", data->value);
+ repeatflag = 1;
+ }
+ continue;
+ }
+
+ /*if flag is deleting, just update the age time, if agetime is on, just set flag to free */
+ if (RD_NODE_DELETING == pnode->flag)
+ {
+ pnode->agetime++;
+ if (pnode->agetime >= RD_AGE_MAX_TIME)
+ {
+ pnode->flag = RD_NODE_USELESS;
+ NSSOC_LOGINF("goint to free node at index:%d", iindex);
+ }
+ /*record delete time */
+ if (agetime < pnode->agetime)
+ {
+ agetime = pnode->agetime;
+ ageindex = iindex;
+ }
+ continue;
+ }
+ }
+
+ /*if repeat, just return */
+ if (1 == repeatflag)
+ {
+ return 0;
+ }
+ if (-1 == freeindex)
+ {
+ if (-1 != ageindex)
+ {
+ freeindex = ageindex;
+ }
+ else
+ {
+ NSSOC_LOGERR("the rd route table:%p is full", handle);
+ return -1;
+ }
+ }
+ pnode = &(handle->node[freeindex]);
+ /*if no free found, just reuse the big agetime */
+ dmm_spin_lock_with_pid(&handle->rd_lock);
+ if (EOK != strcpy_s(pnode->data.stack_name, RD_PLANE_NAMELEN, name))
+ {
+ NSSOC_LOGERR("strcpy_s failed]copy_name=%s", name);
+ }
+ pnode->data.type = RD_DATA_TYPE_TYPE;
+ pnode->data.type_data.value = data->value;
+ pnode->data.type_data.attr = data->attr;
+ pnode->data.type_data.reserved[0] = data->reserved[0];
+ pnode->data.type_data.reserved[1] = data->reserved[1];
+ pnode->data.type_data.reserved[2] = data->reserved[2];
+ pnode->data.type_data.reserved[3] = data->reserved[3];
+ pnode->flag = RD_NODE_USING; /*last set */
+ handle->icnt++;
+ __sync_fetch_and_add(&handle->rdtbl_ver, 1); /*[MISRA 2004 Rule 14.2] */
+ dmm_spin_unlock(&handle->rd_lock);
+ NSSOC_LOGINF("nstack=%s, type:%u attr:%u was inserted", name,
+ data->value, data->attr);
+ return 0;
+}
+
+int nstack_rd_type_node_delete(rd_type_data * data, void *table)
+{
+ int iindex = 0;
+ rd_route_table *handle = (rd_route_table *) table;
+ rd_route_node *pnode = NULL;
+
+ if (!handle || !data)
+ {
+ NSSOC_LOGERR("invalid parameters");
+ return -1;
+ }
+
+ for (iindex = 0; iindex < NSTACK_RD_DATA_MAX; iindex++)
+ {
+ pnode = &(handle->node[iindex]);
+ if ((RD_NODE_USING == pnode->flag)
+ && pnode->data.type_data.value == data->value
+ && pnode->data.type_data.attr == data->attr)
+ {
+ dmm_spin_lock_with_pid(&handle->rd_lock);
+ pnode->flag = RD_NODE_DELETING; /*just set deleting state */
+ pnode->agetime = 0;
+ handle->icnt--;
+ NSSOC_LOGINF
+ ("nstack rd:%s, type:%u, attr:%u at index:%d will be deleted",
+ pnode->data.stack_name, data->value, data->attr, iindex);
+ __sync_fetch_and_add(&handle->rdtbl_ver, 1);
+ dmm_spin_unlock(&handle->rd_lock);
+ NSSOC_LOGINF
+ ("nstack rd:%s, type:%u, attr:%u at index:%d was deleted",
+ pnode->data.stack_name, data->value, data->attr, iindex);
+ return 0;
+ }
+ }
+ NSSOC_LOGINF("nstack rd delete, type:%u attr:%u was not found",
+ data->value, data->attr);
+ return 0;
+}
+
+int nstack_rd_proto_node_insert(const char *name, rd_proto_data * data,
+ void *table)
+{
+ rd_route_table *handle = (rd_route_table *) table;
+ if (!handle || !data)
+ {
+ NSSOC_LOGERR("invalid parameters!");
+ return -1;
+ }
+ int iindex = 0;
+ rd_route_node *pnode = NULL;
+ int agetime = 0;
+ int ageindex = -1;
+ int freeindex = -1;
+ int repeatflag = 0;
+
+ for (iindex = 0; iindex < NSTACK_RD_DATA_MAX; iindex++)
+ {
+ pnode = &(handle->node[iindex]);
+ /*record the index of first free element */
+ if (RD_NODE_USELESS == pnode->flag)
+ {
+ if (-1 == freeindex)
+ {
+ freeindex = iindex;
+ NSSOC_LOGINF("free element index:%d was found", iindex);
+ }
+ continue;
+ }
+
+ /*if is using, and repeat just set flag */
+ if (RD_NODE_USING == pnode->flag)
+ {
+ if (pnode->data.proto_data.value == data->value
+ && pnode->data.proto_data.attr == data->attr)
+ {
+ NSSOC_LOGWAR("find duplicate node, proto:%u", data->value);
+ repeatflag = 1;
+ }
+ continue;
+ }
+
+ /*if flag is deleting, just update the age time, if agetime is on, just set flag to free */
+ if (RD_NODE_DELETING == pnode->flag)
+ {
+ pnode->agetime++;
+ if (pnode->agetime >= RD_AGE_MAX_TIME)
+ {
+ pnode->flag = RD_NODE_USELESS;
+ NSSOC_LOGINF("goint to free node at index:%d", iindex);
+ }
+ /*record delete time */
+ if (agetime < pnode->agetime)
+ {
+ agetime = pnode->agetime;
+ ageindex = iindex;
+ }
+ continue;
+ }
+ }
+
+ /*if repeat, just return */
+ if (1 == repeatflag)
+ {
+ return 0;
+ }
+ if (-1 == freeindex)
+ {
+ if (-1 != ageindex)
+ {
+ freeindex = ageindex;
+ }
+ else
+ {
+ NSSOC_LOGERR("the rd route table:%p is full", handle);
+ return -1;
+ }
+ }
+ pnode = &(handle->node[freeindex]);
+ /*if no free found, just reuse the big agetime */
+ dmm_spin_lock_with_pid(&handle->rd_lock);
+ if (EOK != strcpy_s(pnode->data.stack_name, RD_PLANE_NAMELEN, name))
+ {
+ NSSOC_LOGERR("strcpy_s failed]copy_name=%s", name);
+ }
+ pnode->data.type = RD_DATA_TYPE_PROTO;
+ pnode->data.proto_data.value = data->value;
+ pnode->data.proto_data.attr = data->attr;
+ pnode->flag = RD_NODE_USING; /*last set */
+ handle->icnt++;
+ __sync_fetch_and_add(&handle->rdtbl_ver, 1);
+ dmm_spin_unlock(&handle->rd_lock);
+ NSSOC_LOGINF("nstack=%s, proto:%u attr:%u was inserted", name,
+ data->value, data->attr);
+ return 0;
+}
+
+int nstack_rd_proto_node_delete(rd_proto_data * data, void *table)
+{
+ int iindex = 0;
+ rd_route_table *handle = (rd_route_table *) table;
+ rd_route_node *pnode = NULL;
+
+ if (!handle || !data)
+ {
+ NSSOC_LOGERR("invalid parameters");
+ return -1;
+ }
+
+ for (iindex = 0; iindex < NSTACK_RD_DATA_MAX; iindex++)
+ {
+ pnode = &(handle->node[iindex]);
+ if ((RD_NODE_USING == pnode->flag)
+ && pnode->data.proto_data.value == data->value
+ && pnode->data.proto_data.attr == data->attr)
+ {
+ dmm_spin_lock_with_pid(&handle->rd_lock);
+ pnode->flag = RD_NODE_DELETING; /*just set deleting state */
+ pnode->agetime = 0;
+ handle->icnt--;
+ NSSOC_LOGINF
+ ("nstack rd:%s, proto:%u, attr:%u at index:%d will be deleted",
+ pnode->data.stack_name, data->value, data->attr, iindex);
+ __sync_fetch_and_add(&handle->rdtbl_ver, 1);
+ dmm_spin_unlock(&handle->rd_lock);
+ NSSOC_LOGINF
+ ("nstack rd:%s, proto:%u, attr:%u at index:%d was deleted",
+ pnode->data.stack_name, data->value, data->attr, iindex);
+ return 0;
+ }
+ }
+ NSSOC_LOGINF("nstack rd delete, proto:%u attr:%u was not found",
+ data->value, data->attr);
+ return 0;
+}