summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQiuwen Lu <[email protected]>2016-11-04 19:36:40 +0800
committerQiuwen Lu <[email protected]>2016-11-04 19:36:40 +0800
commit753522085286884e281260fbed1ee0d13dc0b519 (patch)
treefcc1046ab066d7b553b0e4a667c58311a4c0ddb4
parentdf63f60821b8b2dd8416c92a932174f06b0b79f8 (diff)
重构邻居子系统实现,接口与MR3类似,增加对应的单元测试代码。
-rw-r--r--stack/include/sk_neigh.h128
-rw-r--r--stack/src/neigh.c348
-rw-r--r--test/CMakeLists.txt4
-rw-r--r--test/TestStackNeigh.cc93
4 files changed, 319 insertions, 254 deletions
diff --git a/stack/include/sk_neigh.h b/stack/include/sk_neigh.h
index 934ac9e..bb418f6 100644
--- a/stack/include/sk_neigh.h
+++ b/stack/include/sk_neigh.h
@@ -1,82 +1,48 @@
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <rte_rwlock.h>
-#include <rte_atomic.h>
-#include <rte_timer.h>
-#include <rte_ether.h>
-
-#define SK_NEIGH_MAX_HDR 0x60
-
-struct sk_neigh_table
-{
- struct rte_timer * event_timer;
- struct rte_hash * neigh_tbl;
- rte_rwlock_t neigh_tbl_lock;
-};
-
-struct sk_dest_info
-{
- uint16_t mtu;
- uint8_t l2_len;
- uint8_t l3_len;
- uint8_t hdr[SK_NEIGH_MAX_HDR];
-};
-
-#define NUD_INCOMPLETE 0x01
-#define NUD_REACHABLE 0x02
-#define NUD_STALE 0x04
-#define NUD_DELAY 0x08
-#define NUD_PROBE 0x10
-#define NUD_FAILED 0x20
-#define NUD_NOARP 0x40
-#define NUD_PERMANENT 0x80
-#define NUD_NONE 0x00
-
-#define NUD_IN_TIMER ( NUD_INCOMPLETE | NUD_REACHABLE | NUD_DELAY | NUD_PROBE )
-#define NUD_VALID ( NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE | NUD_PROBE | NUD_STALE | NUD_DELAY )
-#define NUD_CONNECTED ( NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE )
-
-struct sk_neighbour
-{
- // ���ü���
- rte_atomic16_t refcnt;
- // ������
- rte_rwlock_t rwlock;
- // ��ʱ��
- struct rte_timer timer;
- // ״̬
- unsigned int state;
- // ��Ч��־λ
- unsigned int dead;
- // ������ʱ��
- unsigned int update;
- // �����豸
- struct sk_dev_desc * dev;
- // ��ѯ����
- struct in_addr in_addr;
- // ��ѯ���
- struct ether_addr ether_addr;
- // ���������Ϣ
- struct sk_dest_info dest_info;
-};
-
-int neigh_update(struct sk_neighbour * neigh, const struct ether_addr * lladdr,
- uint8_t state, uint32_t flags);
-
-int neigh_event_send(struct sk_neighbour * neigh, struct rte_mbuf * mbuf);
-
-struct sk_neighbour * neigh_create(struct sk_neigh_table * tbl,
- struct in_addr in_addr, struct sk_dev_desc * dev);
-
-struct sk_neighbour * neigh_lookup(struct sk_neigh_table * tbl,
- const void * pkey, int hold);
-
-int neigh_tbl_init(struct sk_neigh_table * tbl, const char * symbol, unsigned int nr_entries);
-
-#ifdef __cplusplus
-}
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sk_device.h>
+
+struct neighbour;
+TAILQ_HEAD(neighbour_list, neighbour);
+
+struct neighbour_manager
+{
+ /* ��� */
+ rte_rwlock_t rwlock;
+ /* ��ѯ��ϣ�� */
+ struct rte_hash * table;
+ /* ����ѯ������� */
+ struct neighbour_list in_none_list;
+ /* ����ѯ������г��ȣ�����rwlock�ı����� */
+ rte_atomic16_t in_none_list_len;
+ /* ���������� */
+ unsigned int max_entries;
+ /* ������ѯ������ */
+ unsigned int max_queue_entries;
+ /* �����ϻ�ʱ�� */
+ unsigned short t_timeout;
+ /* ARP����Ƶ�� */
+ unsigned short t_arp_send;
+};
+
+int neighbour_mamanger_init(struct neighbour_manager * object,
+ const char * symbol, unsigned int max_entries, unsigned int max_queue_entries,
+ unsigned short t_timeout, unsigned int t_arp_send);
+
+int neighbour_mamanger_deinit(struct neighbour_manager * object);
+
+int neigh_create_or_update(struct neighbour_manager * object, struct in_addr in_addr,
+ struct ether_addr * eth_addr, struct sk_dev_info * devinfo, unsigned short en_permanent);
+
+int neigh_delete(struct neighbour_manager * object, struct in_addr in_addr);
+
+int neigh_query(struct neighbour_manager * object, struct in_addr in_addr,
+ struct ether_addr * out_ether_addr, struct sk_dev_info ** out_dev_info);
+
+#ifdef __cplusplus
+}
#endif \ No newline at end of file
diff --git a/stack/src/neigh.c b/stack/src/neigh.c
index ac2ef3c..35345b8 100644
--- a/stack/src/neigh.c
+++ b/stack/src/neigh.c
@@ -11,220 +11,242 @@
#include <rte_rwlock.h>
#include <rte_atomic.h>
#include <rte_ether.h>
-#include <rte_ip.h>
#include <rte_ip_frag.h>
#include <rte_timer.h>
-
+#include <mr_common.h>
#include <sk_device.h>
-#include <sk_protocol_arp.h>
-#include <sk_neigh.h>
-#include <rte_cycles.h>
#include <rte_hash_crc.h>
+#include <rte_errno.h>
+#include <errno.h>
+#include <assert.h>
+#include <sk_neigh.h>
-#define __IP_VERSION_IHL(version, len) (version << 4 | len << 0)
-#define __IP_TTL 75
-
-// �����㱨��ͷ
-static inline size_t __neigh_fill_ether_hdr(uint8_t * hdr, const struct ether_addr * src_addr,
- const struct ether_addr * dst_addr, const uint16_t next_layer_type)
+enum neigh_state
{
- struct ether_hdr * ether_hdr = (struct ether_hdr *)hdr;
- ether_addr_copy(src_addr, &ether_hdr->s_addr);
- ether_addr_copy(dst_addr, &ether_hdr->d_addr);
- ether_hdr->ether_type = htons(next_layer_type);
- return sizeof(struct ether_hdr);
-}
-
-// ������㱨��ͷ
-static inline size_t __neigh_fill_ipv4_hdr(uint8_t * hdr, const struct in_addr * src_addr,
- const struct in_addr * dst_addr, uint16_t total_len, uint16_t pid, uint8_t next_proto)
+ NEIGH_IN_NONE = 0,
+ NEIGH_IN_COMPLETE = 1,
+ NEIGH_IN_USE = 2,
+ NEIGH_IN_TIMEOUT = 3,
+ NEIGH_IN_DEAD = 4
+};
+
+/* Neighbour Table Object Rule */
+struct neighbour
{
- struct ipv4_hdr * ip_hdr = (struct ipv4_hdr *)hdr;
-
- ip_hdr->version_ihl = __IP_VERSION_IHL(4, sizeof(struct ipv4_hdr) / 4);
- ip_hdr->type_of_service = 0;
- ip_hdr->total_length = htons(total_len);
- ip_hdr->packet_id = htons(pid);
- ip_hdr->fragment_offset = 0;
- ip_hdr->time_to_live = __IP_TTL;
- ip_hdr->next_proto_id = next_proto;
- ip_hdr->hdr_checksum = 0;
-
- ip_hdr->src_addr = src_addr->s_addr;
- ip_hdr->dst_addr = dst_addr->s_addr;
- return sizeof(struct ipv4_hdr);
-}
+ /* ������ */
+ TAILQ_ENTRY(neighbour) next;
+ /* IP��ַ */
+ struct in_addr in_addr;
+ /* Ŀ��MAC��ַ */
+ struct ether_addr eth_addr;
+ /* �豸������ */
+ struct sk_dev_info * dev_info;
+ /* ����״̬ */
+ enum neigh_state state;
+ /* ת�뵱ǰ״̬��ʱ�� */
+ time_t t_start_state;
+ /* �ϴη���ARP�����ʱ�� */
+ time_t t_last_request;
+ /* �ϴ��յ�ARPӦ���ʱ�� */
+ time_t t_last_update;
+ /* ���ñ�־λ */
+ unsigned short en_permanent;
+};
+
+int neighbour_mamanger_init(struct neighbour_manager * object,
+ const char * symbol, unsigned int max_entries, unsigned int max_queue_entries,
+ unsigned short t_timeout, unsigned int t_arp_send)
+{
+ int ret = 0;
-static inline void neigh_fill_destinfo(struct sk_neighbour * neigh)
-{
- struct sk_dest_info * dest_info = &neigh->dest_info;
- size_t ret;
-
- ret = __neigh_fill_ether_hdr(dest_info->hdr,
- &neigh->dev->dev_info->mac_addr, &neigh->ether_addr,
- ETHER_TYPE_IPv4);
- neigh->dest_info.l2_len = ret;
-
- ret = __neigh_fill_ipv4_hdr(dest_info->hdr + ret,
- &neigh->dev->dev_info->in_addr,
- &neigh->in_addr, 0, 0, 0);
- neigh->dest_info.l3_len = ret;
- return;
-}
+ char tbsymbol[MR_SYMBOL_MAX];
+ snprintf(tbsymbol, sizeof(tbsymbol), "NEIGH_%s", symbol);
-static void neigh_destory(struct sk_neighbour * neigh)
-{
- return;
-}
+ struct rte_hash_parameters hash_params =
+ {
+ .name = tbsymbol,
+ .entries = max_entries,
+ .key_len = sizeof(struct in_addr),
+ .hash_func = NULL,
+ .hash_func_init_val = 0,
+ };
-static void neigh_probe(struct sk_neighbour * neigh)
-{
- protocol_arp_request_send(neigh->dev, neigh->in_addr);
+ object->table = rte_hash_create(&hash_params);
+ if (unlikely(object->table == NULL))
+ {
+ MR_LOG(WARNING, STACK, "NeighbourManagerInit,"
+ "Cannot create hash table for %s : %s", symbol, __str_errno());
+ ret = -1; goto errout;
+ }
+
+ TAILQ_INIT(&object->in_none_list);
+ rte_atomic16_init(&object->in_none_list_len);
+ rte_rwlock_init(&object->rwlock);
+ return 0;
+
+errout:
+ if (object->table != NULL) rte_hash_free(object->table);
+ return ret;
}
-static inline void neigh_hold(struct sk_neighbour * neigh)
+int neighbour_mamanger_deinit(struct neighbour_manager * object)
{
- rte_atomic16_add(&neigh->refcnt, 1);
- return;
+ rte_hash_free(object->table);
+ return 0;
}
-static inline void neigh_release(struct sk_neighbour * neigh)
+static void __change_neigh_state(struct neighbour * neigh, enum neigh_state target_state)
{
- if (rte_atomic16_dec_and_test(&neigh->refcnt))
- neigh_destory(neigh);
- return;
+ if (target_state != neigh->state)
+ {
+ neigh->state = target_state;
+ neigh->t_start_state = time(NULL);
+ }
}
-static struct sk_neighbour * neigh_alloc(struct sk_neigh_table * tbl, struct sk_dev_desc * dev)
+static struct neighbour * __neigh_create_and_join_hash(struct neighbour_manager * object,
+ struct in_addr in_addr, struct ether_addr * eth_addr,
+ struct sk_dev_info * devinfo, unsigned short en_permanent)
{
- struct sk_neighbour * neigh = rte_zmalloc(NULL, sizeof(struct sk_neighbour), 0);
+ struct neighbour * neigh = rte_zmalloc(NULL, sizeof(struct neighbour), 0);
if (unlikely(neigh == NULL))
{
- MR_LOG(INFO, STACK, "NeighSystem, NeighCreate, "
- "Cannot alloc memory for neighbor structure. \n");
+ MR_LOG(WARNING, STACK, "Neighbour, Cannot create neigh structure : %s", __str_errno());
return NULL;
}
- rte_rwlock_init(&neigh->rwlock);
- rte_atomic16_init(&neigh->refcnt);
- neigh->state = NUD_NONE;
- neigh->dead = 1;
- neigh->update = rte_rdtsc();
- neigh->dev = dev;
- return neigh;
-}
+ neigh->in_addr = in_addr;
+ neigh->dev_info = devinfo;
+ neigh->en_permanent = en_permanent;
+ neigh->t_last_update = 0;
+ neigh->t_last_request = 0;
+ neigh->state = NEIGH_IN_NONE;
-
-int neigh_update(struct sk_neighbour * neigh, const struct ether_addr * lladdr,
- uint8_t state, uint32_t flags)
-{
- rte_rwlock_write_lock(&neigh->rwlock);
- struct sk_dev_desc * dev = neigh->dev;
- uint8_t old_state = neigh->state;
-
- if((old_state & NUD_REACHABLE) && (state & NUD_REACHABLE))
+ if(eth_addr != NULL)
{
- ether_addr_copy(lladdr, &neigh->ether_addr);
- neigh_fill_destinfo(neigh);
- neigh->dead = 0;
- neigh->state = state;
+ ether_addr_copy(eth_addr, &neigh->eth_addr);
+ __change_neigh_state(neigh, NEIGH_IN_USE);
}
- if((old_state & NUD_INCOMPLETE ) && (state & NUD_REACHABLE))
+ if(en_permanent)
+ {
+ neigh->en_permanent = 1;
+ }
+
+ hash_sig_t hash = rte_hash_crc(&in_addr, sizeof(in_addr), 0);
+ int ret = rte_hash_add_key_with_hash_data(object->table, &in_addr, hash, neigh);
+ if (unlikely(ret < 0))
{
- ether_addr_copy(lladdr, &neigh->ether_addr);
- neigh_fill_destinfo(neigh);
- neigh->dead = 0;
- neigh->state = state;
+ MR_LOG(WARNING, STACK, "Neighbour, Insert neigh to hash table failed : %s",
+ __str_errno());
+ goto errout;
}
+
+ return neigh;
- rte_rwlock_write_unlock(&neigh->rwlock);
- return 0;
+errout:
+ if (neigh) rte_free(neigh);
+ return NULL;
}
-int neigh_event_send(struct sk_neighbour * neigh, struct rte_mbuf * mbuf)
+static void __neigh_update(struct neighbour * neigh, struct in_addr in_addr,
+ struct ether_addr * eth_addr, struct sk_dev_info * devinfo, unsigned short en_permanent)
{
- rte_rwlock_write_lock(&neigh->rwlock);
-
- if (neigh->state & (NUD_REACHABLE))
- goto out_unblock;
-
- if(neigh->state & NUD_NONE)
+ assert(neigh != NULL);
+ neigh->in_addr = in_addr;
+ neigh->en_permanent = en_permanent;
+ neigh->dev_info = devinfo;
+
+ if(eth_addr != NULL)
{
- neigh_probe(neigh);
- goto out_unblock;
+ ether_addr_copy(eth_addr, &neigh->eth_addr);
+ __change_neigh_state(neigh, NEIGH_IN_USE);
}
- //TODO: ����״̬������
-
-out_unblock:
- rte_rwlock_write_unlock(&neigh->rwlock);
- return 0;
+ return;
}
-struct sk_neighbour * neigh_create(struct sk_neigh_table * tbl,
- struct in_addr in_addr, struct sk_dev_desc * dev)
+int neigh_create_or_update(struct neighbour_manager * object, struct in_addr in_addr,
+ struct ether_addr * eth_addr, struct sk_dev_info * devinfo, unsigned short en_permanent)
{
- struct sk_neighbour * neigh = neigh_alloc(tbl, dev);
- if (unlikely(neigh == NULL)) return NULL;
-
- // Hashֵ��ΪIP��ַ������ֵ�����뵽Hash����
- hash_t hash = in_addr.s_addr;
- rte_rwlock_write_lock(&tbl->neigh_tbl_lock);
- rte_hash_add_key_with_hash(tbl->neigh_tbl, &hash, hash);
- rte_rwlock_write_unlock(&tbl->neigh_tbl_lock);
+ rte_rwlock_write_lock(&object->rwlock);
+ struct neighbour * neigh = NULL;
+ hash_sig_t hash = rte_hash_crc(&in_addr, sizeof(in_addr), 0);
+
+ int ret = rte_hash_lookup_with_hash_data(object->table, &in_addr, hash, (void **)&neigh);
+ if (ret < 0)
+ {
+ neigh = __neigh_create_and_join_hash(object, in_addr, eth_addr, devinfo, en_permanent);
+ }
+ else
+ {
+ __neigh_update(neigh, in_addr, eth_addr, devinfo, en_permanent);
+ }
+
+ if (unlikely(neigh == NULL)) return -1;
+ if (neigh->state == NEIGH_IN_NONE)
+ {
+ TAILQ_INSERT_TAIL(&object->in_none_list, neigh, next);
+ rte_atomic16_inc(&object->in_none_list_len);
+ }
+
+ ret = 0; goto exit;
- // ���������¼�������ARP����
- neigh_event_send(neigh, NULL);
- neigh_hold(neigh);
- return neigh;
+exit:
+ rte_rwlock_write_unlock(&object->rwlock);
+ return ret;
}
-struct sk_neighbour * neigh_lookup(struct sk_neigh_table * tbl,
- const void * pkey, int hold)
+int neigh_delete(struct neighbour_manager * object, struct in_addr in_addr)
{
- hash_t hash = *(uint32_t *)pkey;
- struct sk_neighbour * neigh;
+ rte_rwlock_write_lock(&object->rwlock);
+ struct neighbour * neigh = NULL;
- rte_rwlock_read_lock(&tbl->neigh_tbl_lock);
- rte_hash_lookup_with_hash_data(tbl->neigh_tbl, &hash, hash, (void **)&neigh);
- rte_rwlock_read_unlock(&tbl->neigh_tbl_lock);
-
- if (neigh == NULL) return NULL;
+ hash_sig_t hash = rte_hash_crc(&in_addr, sizeof(in_addr), 0);
+ int ret = rte_hash_lookup_with_hash_data(object->table, &in_addr, hash, (void **)&neigh);
+ if (ret < 0) goto exit;
- if (hold) neigh_hold(neigh);
- return neigh;
+ // ������IN_NONE״̬ʱ����IN_NONE�б����Ƴ�
+ if (neigh->state == NEIGH_IN_NONE)
+ {
+ TAILQ_REMOVE(&object->in_none_list,neigh, next);
+ rte_atomic16_dec(&object->in_none_list_len);
+ }
+
+ rte_hash_del_key_with_hash(object->table, &in_addr, hash);
+ rte_free(neigh);
+ ret = 0; goto exit;
+
+exit:
+ rte_rwlock_write_unlock(&object->rwlock);
+ return ret;
}
-int neigh_tbl_init(struct sk_neigh_table * tbl, const char * symbol, unsigned int nr_entries)
+int neigh_query(struct neighbour_manager * object, struct in_addr in_addr,
+ struct ether_addr * out_ether_addr, struct sk_dev_info ** out_dev_info)
{
- char hash_tbl_symbol[MR_SYMBOL_MAX];
- snprintf(hash_tbl_symbol, sizeof(hash_tbl_symbol), "NTB-%s", symbol);
-
- struct rte_hash_parameters hash_params =
- {
- .name = hash_tbl_symbol,
- .entries = nr_entries,
- .key_len = sizeof(uint32_t),
- .hash_func = rte_hash_crc,
- .hash_func_init_val = 0,
- };
+ struct neighbour * neigh = NULL;
+
+ rte_rwlock_read_lock(&object->rwlock);
+ hash_sig_t hash = rte_hash_crc(&in_addr, sizeof(in_addr), 0);
+ int ret = rte_hash_lookup_with_hash_data(object->table, &in_addr, hash, (void **)&neigh);
- tbl->neigh_tbl = rte_hash_create(&hash_params);
- if (unlikely(tbl == NULL))
+ // û�鵽
+ if (ret < 0) goto exit;
+
+ // ����״̬��Ϣ��ȫ���޷������ṩ��ѯ
+ if (neigh->state == NEIGH_IN_NONE ||
+ neigh->state == NEIGH_IN_COMPLETE ||
+ neigh->state == NEIGH_IN_DEAD)
{
- MR_LOG(WARNING, STACK, "NeighSystem, NeighTblInit, "
- "Create hash table %s failed(for NeighTable %s): %s. \n",
- hash_tbl_symbol, symbol, rte_strerror(rte_errno));
- return -1;
+ ret = -EFAULT; goto exit;
}
+
+ ether_addr_copy(&neigh->eth_addr, out_ether_addr);
+ *out_dev_info = neigh->dev_info;
+ ret = 0; goto exit;
- rte_rwlock_init(&tbl->neigh_tbl_lock);
- return 0;
-}
-
-int neigh_tbl_deinit(struct sk_neigh_table * tbl)
-{
- rte_hash_reset(tbl->neigh_tbl);
- return 0;
+exit:
+ rte_rwlock_read_unlock(&object->rwlock);
+ return ret;
} \ No newline at end of file
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 03898c5..8cf7596 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -30,5 +30,5 @@ set(TEST_LINK_LIBRARIES ${DPDK_LIBRARY} gtest)
# add_executable(TestVMan TestVMan.cc Unittest.cc)
# target_link_libraries(TestVMan ${TEST_LINK_LIBRARIES} core)
-# add_executable(TestNeigh TestStackNeigh.cc Unittest.cc)
-# target_link_libraries(TestNeigh ${TEST_LINK_LIBRARIES} stack) \ No newline at end of file
+add_executable(TestNeigh TestStackNeigh.cc Unittest.cc)
+target_link_libraries(TestNeigh ${TEST_LINK_LIBRARIES} stack) \ No newline at end of file
diff --git a/test/TestStackNeigh.cc b/test/TestStackNeigh.cc
index 36fab6d..711c101 100644
--- a/test/TestStackNeigh.cc
+++ b/test/TestStackNeigh.cc
@@ -1,30 +1,107 @@
#include <gtest/gtest.h>
#include <sk_device.h>
-#include <sk_neigh.h>
#include <netinet/in.h>
+#include <sk_neigh.h>
+#include <arpa/inet.h>
class TCStackNeigh : public ::testing::Test
{
protected:
- struct sk_neigh_table neigh_tbl_;
- struct sk_dev_desc neigh_dev_desc_;
+ struct neighbour_manager nbl_object_;
+ struct sk_dev_info dev_info_;
virtual void SetUp()
{
- int ret = neigh_tbl_init(&neigh_tbl_, "TestNeigh", 10000);
- neigh_dev_desc_.dev_info = new sk_dev_info;
+ int ret = neighbour_mamanger_init(&nbl_object_, "TestNeighbour",
+ 1024, 8, 0, 0);
ASSERT_EQ(ret, 0);
}
virtual void TearDown()
{
+ int ret = neighbour_mamanger_deinit(&nbl_object_);
+ ASSERT_EQ(ret, 0);
}
};
-TEST_F(TCStackNeigh, TestNeighCreate)
+TEST_F(TCStackNeigh, CreateAndQuery)
{
+ int ret = 0;
struct in_addr _in_addr;
- _in_addr.s_addr = 1000000;
- neigh_create(&neigh_tbl_, _in_addr, &neigh_dev_desc_);
+ inet_pton(AF_INET, "192.168.11.101", &_in_addr);
+ struct ether_addr _ether_addr = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
+
+ ret = neigh_create_or_update(&nbl_object_,
+ _in_addr, &_ether_addr, &dev_info_, 1);
+
+ ASSERT_EQ(ret, 0);
+
+ struct ether_addr _ether_addr_query;
+ struct sk_dev_info * _dev_info_query;
+
+ ret = neigh_query(&nbl_object_, _in_addr, &_ether_addr_query,
+ &_dev_info_query);
+
+ ASSERT_EQ(ret, 0);
+ EXPECT_EQ(is_same_ether_addr(&_ether_addr_query, &_ether_addr), 1);
+ EXPECT_EQ(_dev_info_query, &dev_info_);
+}
+
+TEST_F(TCStackNeigh, CreateAndUpdate)
+{
+ int ret = 0;
+ struct in_addr _in_addr;
+ inet_pton(AF_INET, "192.168.11.101", &_in_addr);
+ struct ether_addr _ether_addr = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
+
+ ret = neigh_create_or_update(&nbl_object_,
+ _in_addr, &_ether_addr, &dev_info_, 1);
+
+ ASSERT_EQ(ret, 0);
+
+ struct ether_addr _ether_addr_query;
+ struct sk_dev_info * _dev_info_query;
+
+ ret = neigh_query(&nbl_object_, _in_addr, &_ether_addr_query,
+ &_dev_info_query);
+
+ ASSERT_EQ(ret, 0);
+ EXPECT_EQ(is_same_ether_addr(&_ether_addr_query, &_ether_addr), 1);
+ EXPECT_EQ(_dev_info_query, &dev_info_);
+
+ struct ether_addr _ether_addr_update = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
+ ret = neigh_create_or_update(&nbl_object_, _in_addr, &_ether_addr_update,
+ &dev_info_, 1);
+
+ ASSERT_EQ(ret, 0);
+
+ ret = neigh_query(&nbl_object_, _in_addr, &_ether_addr_query, &_dev_info_query);
+ ASSERT_EQ(ret, 0);
+ EXPECT_EQ(is_same_ether_addr(&_ether_addr_query, &_ether_addr_update), 1);
+ EXPECT_EQ(_dev_info_query, &dev_info_);
+}
+
+TEST_F(TCStackNeigh, CreateAndDelete)
+{
+ int ret = 0;
+ struct in_addr _in_addr;
+ inet_pton(AF_INET, "192.168.11.101", &_in_addr);
+ struct ether_addr _ether_addr = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
+
+ ret = neigh_create_or_update(&nbl_object_,
+ _in_addr, &_ether_addr, &dev_info_, 1);
+
+ ASSERT_EQ(ret, 0);
+
+ ret = neigh_delete(&nbl_object_, _in_addr);
+ ASSERT_EQ(ret, 0);
+
+ struct ether_addr _ether_addr_query;
+ struct sk_dev_info * _dev_info_query;
+
+ ret = neigh_query(&nbl_object_, _in_addr, &_ether_addr_query,
+ &_dev_info_query);
+
+ ASSERT_LE(ret, 0);
} \ No newline at end of file