summaryrefslogtreecommitdiff
path: root/stack
diff options
context:
space:
mode:
authorQiuwen Lu <[email protected]>2016-10-25 17:19:59 +0800
committerQiuwen Lu <[email protected]>2016-10-25 17:19:59 +0800
commit287e3ee0fc3ea5256cd33aef0d7c5d2487b841cf (patch)
treecb0cb9469568b9d3d2a3e6092e2d55cae1cd242d /stack
parentc1002e8d6fe90c753b7e6198476391b22d14194a (diff)
增加协议栈实现,在Service中完成协议栈初始化流程。修改了mr_device的open方式,集中打开参数。
Diffstat (limited to 'stack')
-rw-r--r--stack/CMakeLists.txt12
-rw-r--r--stack/include/port_bitmap.h114
-rw-r--r--stack/include/sk_device.h124
-rw-r--r--stack/include/sk_neigh.h82
-rw-r--r--stack/include/sk_protocol_arp.h26
-rw-r--r--stack/include/sk_stack.h48
-rw-r--r--stack/src/arp.c67
-rw-r--r--stack/src/device.c193
-rw-r--r--stack/src/neigh.c230
-rw-r--r--stack/src/rxtx.c8
-rw-r--r--stack/src/stack.c33
-rw-r--r--stack/src/udp.c0
12 files changed, 937 insertions, 0 deletions
diff --git a/stack/CMakeLists.txt b/stack/CMakeLists.txt
new file mode 100644
index 0000000..fb4feb1
--- /dev/null
+++ b/stack/CMakeLists.txt
@@ -0,0 +1,12 @@
+find_package(DPDK REQUIRED)
+include_directories(${CMAKE_SOURCE_DIR}/include)
+include_directories(${CMAKE_SOURCE_DIR}/include/extern)
+include_directories(${CMAKE_SOURCE_DIR}/include/internal)
+include_directories(${DPDK_INCLUDE_DIR})
+
+add_definitions(${DPDK_C_PREDEFINED})
+include_directories(include)
+add_library(stack src/stack.c src/device.c src/neigh.c src/arp.c)
+target_link_libraries(stack MESA_prof_load_static mruntime core)
+target_link_libraries(stack rt pthread dl)
+target_include_directories(stack INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include/") \ No newline at end of file
diff --git a/stack/include/port_bitmap.h b/stack/include/port_bitmap.h
new file mode 100644
index 0000000..4391b76
--- /dev/null
+++ b/stack/include/port_bitmap.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ * 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.
+ *
+ */
+
+#ifndef _PORT_BITMAP_H_
+#define _PORT_BITMAP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <limits.h>
+#include <rte_common.h>
+
+/*
+ * Simple implementation of bitmap for all possible UDP ports [0-UINT16_MAX].
+ */
+
+#define MAX_PORT_NUM (UINT16_MAX + 1)
+
+#define PORT_BLK(p) ((p) / (sizeof(uint32_t) * CHAR_BIT))
+#define PORT_IDX(p) ((p) % (sizeof(uint32_t) * CHAR_BIT))
+
+#define MAX_PORT_BLK PORT_BLK(MAX_PORT_NUM)
+
+struct portmap
+{
+ uint32_t nb_set; /* number of bits set. */
+ uint32_t blk; /* last block with free entry. */
+ uint32_t bm[MAX_PORT_BLK];
+};
+
+static inline void portmap_init(struct portmap *pbm, uint32_t blk)
+{
+ pbm->bm[0] = 1;
+ pbm->nb_set = 1;
+ pbm->blk = blk;
+}
+
+static inline void portmap_set(struct portmap *pbm, uint16_t port)
+{
+ uint32_t i, b, v;
+
+ i = PORT_BLK(port);
+ b = 1 << PORT_IDX(port);
+ v = pbm->bm[i];
+ pbm->bm[i] = v | b;
+ pbm->nb_set += (v & b) == 0;
+}
+
+static inline void portmap_clear(struct portmap *pbm, uint16_t port)
+{
+ uint32_t i, b, v;
+
+ i = PORT_BLK(port);
+ b = 1 << PORT_IDX(port);
+ v = pbm->bm[i];
+ pbm->bm[i] = v & ~b;
+ pbm->nb_set -= (v & b) != 0;
+}
+
+
+static inline uint32_t portmap_check(const struct portmap *pbm, uint16_t port)
+{
+ uint32_t i, v;
+
+ i = PORT_BLK(port);
+ v = pbm->bm[i] >> PORT_IDX(port);
+ return v & 1;
+}
+
+static inline uint16_t portmap_find_range(struct portmap *pbm,
+ uint32_t start_blk, uint32_t end_blk)
+{
+ uint32_t i, v;
+ uint16_t p;
+
+ if (pbm->nb_set == MAX_PORT_NUM)
+ return 0;
+
+ p = 0;
+ for (i = start_blk; i != end_blk; i++) {
+ i %= RTE_DIM(pbm->bm);
+ v = pbm->bm[i];
+ if (v != UINT32_MAX) {
+ for (p = i * (sizeof(pbm->bm[0]) * CHAR_BIT);
+ (v & 1) != 0; v >>= 1, p++)
+ ;
+
+ pbm->blk = i;
+ break;
+ }
+ }
+ return p;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PORT_BITMAP_H_ */
diff --git a/stack/include/sk_device.h b/stack/include/sk_device.h
new file mode 100644
index 0000000..0af22e7
--- /dev/null
+++ b/stack/include/sk_device.h
@@ -0,0 +1,124 @@
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <mr_common.h>
+#include <sys/queue.h>
+#include <rte_ether.h>
+#include <mr_device.h>
+#include <netinet/in.h>
+
+struct sk_dev_param
+{
+ // �豸����
+ char symbol[MR_SYMBOL_MAX];
+ // MTU
+ unsigned int mtu;
+ // IP��ַ
+ struct in_addr in_addr;
+ // ��������
+ struct in_addr in_mask;
+ // ����
+ struct in_addr in_gateway;
+ // MAC��ַ
+ struct ether_addr mac_addr;
+ // RawЭ��ʹ��
+ unsigned int en_raw;
+ // TCPЭ��ʹ��
+ unsigned int en_tcp;
+ // UDPЭ��ʹ��
+ unsigned int en_udp;
+ // ARPЭ��ʹ��
+ unsigned int en_arp;
+ // ICMPЭ��ʹ��
+ unsigned int en_icmp;
+ // ��ѭ����������С
+ unsigned int sz_rx_loop_buffer;
+ // ��ѭ����������С
+ unsigned int sz_tx_loop_buffer;
+};
+
+// �豸������Ϣ
+struct sk_dev_info
+{
+ // Э��ջCTX
+ struct mr_stack_instance * instance_;
+ // �豸������һ��
+ TAILQ_ENTRY(sk_dev_info) next;
+ // �豸����
+ struct sk_dev_param param;
+ // �豸����
+ char symbol[MR_SYMBOL_MAX];
+ // �Ƿ�����
+ unsigned int enable;
+ // MTU��С
+ unsigned int mtu;
+ // �Ƿ����û���ģʽ
+ unsigned int promisc;
+ // ����IP��ַ
+ struct in_addr in_addr;
+ // ��������
+ struct in_addr in_mask;
+ // ����MAC��ַ
+ struct ether_addr mac_addr;
+};
+
+// �豸��������ӽ���ͨ�ã�
+struct sk_dev_desc
+{
+
+#define SK_DEV_MODE_SERV 0
+#define SK_DEV_MODE_APP 1
+
+ // ������һ��
+ TAILQ_ENTRY(sk_dev_desc) next;
+ // ģʽ�������̻�ӽ��̣�
+ unsigned int mode;
+ // �豸��Ϣ���
+ struct sk_dev_info * dev_info;
+ // ��ѭ�����Ļ��������ڷ����������д�����
+ struct rte_ring * rx_loop_buffer[MR_SID_MAX];
+ // ��ѭ�����Ļ����������ձ��������д�����
+ struct rte_ring * tx_loop_buffer[MR_SID_MAX];
+ // TCP�� Rt-Device Stream
+ struct mr_rtdev_stream * tcp_rtdev_stream[MR_SID_MAX];
+ // UDP�� Rt-Device Stream
+ struct mr_rtdev_stream * udp_rtdev_stream[MR_SID_MAX];
+};
+
+TAILQ_HEAD(sk_dev_info_list, sk_dev_info);
+TAILQ_HEAD(sk_dev_desc_list, sk_dev_desc);
+
+struct sk_dev_info * mr_stack_device_lookup(struct mr_stack_instance * instance, const char * symbol);
+
+// �豸��Ϣ������
+int mr_stack_device_iterate(struct mr_stack_instance * instance, struct sk_dev_info ** dev_info);
+
+// ����һ��Э��ջ�豸
+int mr_stack_device_create(struct mr_stack_instance * instance, struct sk_dev_param * param);
+
+// ����Э��ջ�豸
+int mr_stack_device_destory(struct sk_dev_info * devinfo);
+
+// ����Э��ջ��IP��ַ
+int mr_stack_device_set_inaddr(struct sk_dev_info * dev_info, struct in_addr in_addr,
+ struct in_addr in_mask);
+
+// ��ȡЭ��ջ�豸��IP��ַ
+int mr_stack_device_get_inaddr(struct sk_dev_info * devinfo,
+ struct in_addr * in_addr, struct in_addr * in_mask);
+
+// ����Э��ջ�豸��MTU
+int mr_stack_device_set_mtu(struct sk_dev_info * devinfo, unsigned int mtu);
+// ��ȡЭ��ջ�豸��MTU
+int mr_stack_device_get_mtu(struct sk_dev_info * devinfo);
+// �����豸
+int mr_stack_device_enable(struct sk_dev_info * devinfo);
+// �����豸
+int mr_stack_device_disable(struct sk_dev_info * devinfo);
+
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file
diff --git a/stack/include/sk_neigh.h b/stack/include/sk_neigh.h
new file mode 100644
index 0000000..934ac9e
--- /dev/null
+++ b/stack/include/sk_neigh.h
@@ -0,0 +1,82 @@
+#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
+}
+#endif \ No newline at end of file
diff --git a/stack/include/sk_protocol_arp.h b/stack/include/sk_protocol_arp.h
new file mode 100644
index 0000000..718a43c
--- /dev/null
+++ b/stack/include/sk_protocol_arp.h
@@ -0,0 +1,26 @@
+#pragma once
+
+int protocol_arp_init(struct mr_stack_instance * instance);
+
+int protocol_arp_deinit(struct mr_stack_instance * instance);
+
+int protocol_arp_slave_init(struct mr_stack_instance * instance,
+ struct mr_stack_slave_instance * slave_instance);
+
+int protocol_arp_slave_deinit(struct mr_stack_instance * instance,
+ struct mr_stack_slave_instance * slave_instance);
+
+int protocol_arp_dev_init(struct sk_dev_desc * dev);
+
+int protocol_arp_dev_deinit(struct sk_dev_desc * dev);
+
+int protocol_arp_slave_dev_init(struct sk_dev_desc * dev);
+
+int protocol_arp_slave_dev_deinit(struct sk_dev_desc * dev);
+
+// ARP���Ĵ�����ں�����������̴�����
+int protocol_arp_entry(struct stack_dev_handle * dev_handle,
+ struct rte_mbuf * in_pkt[], struct rte_mbuf * out_pkt[],
+ unsigned int nr_in_pkt, unsigned int * nr_left_pkt);
+
+int protocol_arp_request_send(struct sk_dev_desc * dev, struct in_addr in_addr); \ No newline at end of file
diff --git a/stack/include/sk_stack.h b/stack/include/sk_stack.h
new file mode 100644
index 0000000..8297502
--- /dev/null
+++ b/stack/include/sk_stack.h
@@ -0,0 +1,48 @@
+#pragma once
+#include <sk_device.h>
+
+#ifndef MR_STACK_DEFAULT_SZ_DELIVER_RING
+#define MR_STACK_DEFAULT_SZ_DELIVER_RING 1024
+#endif
+
+#ifndef MR_STACK_DEFAULT_SZ_DELIVER_BUFFER
+#define MR_STACK_DEFAULT_SZ_DELIVER_BUFFER 128
+#endif
+
+#ifndef MR_STACK_DEFAULT_SZ_LOOP_RING
+#define MR_STACK_DEFAULT_SZ_LOOP_RING 1024
+#endif
+
+struct mr_stack_param
+{
+ // ��������
+ char servsym[MR_SYMBOL_MAX];
+ // �����߳�����������ע��Э��ջ�̡߳���Э��ջȡ���ĵ��̣߳�
+ unsigned int nr_serv_thread;
+ // �ַ����д�С
+ unsigned int sz_deliver_ring;
+ // �ַ����л�������С
+ unsigned int sz_deliver_buffer;
+ // ��ѭ�����д�С
+ unsigned int sz_loop_ring;
+};
+
+struct mr_stack_instance
+{
+ // Э��ջ���в���
+ struct mr_stack_param param;
+ // Э��ջ�豸��Ϣ
+ struct sk_dev_info_list dev_info_list;
+ // Э��ջ�豸���
+ struct sk_dev_desc_list dev_desc_list;
+};
+
+struct mr_stack_slave_instance
+{
+ // Э��ջ�豸���
+ struct sk_dev_desc_list dev_desc_list;
+};
+
+struct mr_stack_instance * mr_stack_instance_create(struct mr_stack_param * param);
+
+struct mr_stack_slave_instance * mr_stack_slave_create(); \ No newline at end of file
diff --git a/stack/src/arp.c b/stack/src/arp.c
new file mode 100644
index 0000000..34131b8
--- /dev/null
+++ b/stack/src/arp.c
@@ -0,0 +1,67 @@
+/* \brief ��Э��ջARP/RARPЭ�鴦��ģ��
+*
+* ����ARP/RARPЭ�鱨������
+*
+* \author Lu Qiuwen<[email protected]>
+* \date 2016-10-21
+*/
+
+#include <mr_rtdev.h>
+#include <sk_stack.h>
+#include <sk_device.h>
+#include <rte_ip_frag.h>
+
+int protocol_arp_init(struct mr_stack_instance * instance)
+{
+ return 0;
+}
+
+int protocol_arp_deinit(struct mr_stack_instance * instance)
+{
+ return 0;
+}
+
+int protocol_arp_slave_init(struct mr_stack_instance * instance,
+ struct mr_stack_slave_instance * slave_instance)
+{
+ return 0;
+}
+
+int protocol_arp_slave_deinit(struct mr_stack_instance * instance,
+ struct mr_stack_slave_instance * slave_instance)
+{
+ return 0;
+}
+
+int protocol_arp_dev_init(struct sk_dev_desc * dev)
+{
+ return 0;
+}
+
+int protocol_arp_dev_deinit(struct sk_dev_desc * dev)
+{
+ return 0;
+}
+
+int protocol_arp_slave_dev_init(struct sk_dev_desc * dev)
+{
+ return 0;
+}
+
+int protocol_arp_slave_dev_deinit(struct sk_dev_desc * dev)
+{
+ return 0;
+}
+
+// ARP���Ĵ�����ں�����������̴�����
+int protocol_arp_entry(struct stack_dev_handle * dev_handle,
+ struct rte_mbuf * in_pkt[], struct rte_mbuf * out_pkt[],
+ unsigned int nr_in_pkt, unsigned int * nr_left_pkt)
+{
+ return 0;
+}
+
+int protocol_arp_request_send(struct sk_dev_desc * dev, struct in_addr in_addr)
+{
+ return 0;
+} \ No newline at end of file
diff --git a/stack/src/device.c b/stack/src/device.c
new file mode 100644
index 0000000..9b04d62
--- /dev/null
+++ b/stack/src/device.c
@@ -0,0 +1,193 @@
+/* 简单数据通信用户态协议栈——设备管理器
+*
+* 本模块提供协议栈使用的设备管理功能。负责管理真实(或虚拟)设备之:
+* A. IP地址、子网掩码、默认网关等网络层信息;
+* B. MTU、VLAN等数据链路层信息。
+*
+* \author Lu Qiuwen<[email protected]>
+* \date 2016-10-18
+*/
+
+#include <sys/queue.h>
+#include <rte_ether.h>
+#include <mr_rtdev.h>
+#include <mr_rawio.h>
+#include <rte_malloc.h>
+
+#include <sk_stack.h>
+#include <sk_device.h>
+#include <assert.h>
+
+
+struct sk_dev_info * mr_stack_device_lookup(struct mr_stack_instance * instance, const char * symbol)
+{
+ return NULL;
+}
+
+int mr_stack_device_iterate(struct mr_stack_instance * instance, struct sk_dev_info ** dev_info)
+{
+ // 迭代器为空,从头开始迭代,否则查找迭代器下一个对象
+ if(*dev_info == NULL)
+ {
+ *dev_info = TAILQ_FIRST(&instance->dev_info_list);
+ return 0;
+ }
+ else
+ {
+ *dev_info = TAILQ_NEXT(*dev_info, next);
+ }
+
+ // 迭代到尾部,返回错误码
+ if (*dev_info == NULL) return -ENOENT;
+ return 0;
+}
+
+// 创建一个协议栈设备
+int mr_stack_device_create(struct mr_stack_instance * instance, struct sk_dev_param * param)
+{
+ // 检查设备是否已经存在,不允许重复创建
+ struct sk_dev_info * devinfo = mr_stack_device_lookup(instance, param->symbol);
+ if(devinfo != NULL)
+ {
+ MR_LOG(INFO, STACK, "StackCreateDevice, StackDevice %s has been created. failed. \n",
+ param->symbol);
+ return -EEXIST;
+ }
+
+ // 申请Info结构体的空间
+ devinfo = rte_zmalloc(NULL, sizeof(struct sk_dev_info), 0);
+ if(unlikely(devinfo == NULL))
+ {
+ MR_LOG(WARNING, STACK, "StackCreateDevice, Cannot alloc memory for device info.\n");
+ return -ENOMEM;
+ }
+
+ // 写参数
+ snprintf(devinfo->symbol, sizeof(devinfo->symbol), "%s", param->symbol);
+ devinfo->param = *param;
+ devinfo->instance_ = instance;
+ devinfo->in_addr = param->in_addr;
+ devinfo->in_mask = param->in_mask;
+ devinfo->mac_addr = param->mac_addr;
+ devinfo->mtu = param->mtu;
+ devinfo->promisc = 0;
+
+ // 加入到协议栈设备链表中
+ TAILQ_INSERT_TAIL(&instance->dev_info_list, devinfo, next);
+ return 0;
+}
+
+// 销毁协议栈设备
+int mr_stack_device_destory(struct sk_dev_info * devinfo)
+{
+ assert(0);
+ return 0;
+}
+
+// 设置协议栈的IP地址
+int mr_stack_device_set_inaddr(struct sk_dev_info * dev_info, struct in_addr in_addr,
+ struct in_addr in_mask)
+{
+ dev_info->in_addr = in_addr;
+ dev_info->in_mask = in_mask;
+ return 0;
+}
+
+// 读取协议栈设备的IP地址
+int mr_stack_device_get_inaddr(struct sk_dev_info * devinfo,
+ struct in_addr * in_addr, struct in_addr * in_mask)
+{
+ *in_addr = devinfo->in_addr;
+ *in_mask = devinfo->in_mask;
+ return 0;
+}
+
+// 设置协议栈设备的MTU
+int mr_stack_device_set_mtu(struct sk_dev_info * devinfo, unsigned int mtu)
+{
+ devinfo->mtu = mtu;
+ return 0;
+}
+
+// 读取协议栈设备的MTU
+int mr_stack_device_get_mtu(struct sk_dev_info * devinfo)
+{
+ return devinfo->mtu;
+}
+
+// 启动设备
+int mr_stack_device_enable(struct sk_dev_info * devinfo)
+{
+ return 0;
+}
+
+// 禁用设备
+int mr_stack_device_disable(struct sk_dev_info * devinfo)
+{
+ return 0;
+}
+
+static struct sk_dev_desc * sk_dev_desc_new(struct sk_dev_info * dev_info, unsigned int mode)
+{
+ // 申请内存空间
+ struct sk_dev_desc * dev_desc = rte_zmalloc(NULL, sizeof(struct sk_dev_desc), 0);
+ if(unlikely(dev_desc == NULL))
+ {
+ MR_LOG(WARNING, STACK, "StackDevice, StackDeviceDescCreate, "
+ "Cannot alloc memory for device %s desc. Failed. \n", dev_info->symbol);
+ return NULL;
+ }
+
+ // 各线程使用的资源放在线程初始化流程中进行,这里不进行。
+ dev_desc->dev_info = dev_info;
+ return dev_desc;
+}
+
+static void sk_dev_desc_delete(struct sk_dev_desc * dev_desc)
+{
+ // TODO:stream的释放
+
+ // 释放RX侧自循环缓冲区
+ for(int i = 0; i < RTE_DIM(dev_desc->rx_loop_buffer); i++)
+ {
+ if (dev_desc->rx_loop_buffer[i] != NULL)
+ rte_ring_free(dev_desc->rx_loop_buffer[i]);
+ }
+
+ // 释放TX侧自循环缓冲区
+ for(int i = 0; i < RTE_DIM(dev_desc->tx_loop_buffer); i++)
+ {
+ if (dev_desc->tx_loop_buffer[i] != NULL)
+ rte_ring_free(dev_desc->tx_loop_buffer[i]);
+ }
+}
+
+/* 以下为内部初始化、注销处理流程。*/
+int stack_device_init(struct mr_stack_instance * instance)
+{
+ // 创建主应用设备句柄,插入到句柄链表中
+ struct sk_dev_info * dev_info_iter;
+ struct sk_dev_desc * dev_desc_iter;
+
+ TAILQ_FOREACH(dev_info_iter, &instance->dev_info_list, next)
+ {
+ struct sk_dev_desc * dev_desc = sk_dev_desc_new(dev_info_iter, SK_DEV_MODE_SERV);
+ if (unlikely(dev_desc == NULL)) goto errout;
+ TAILQ_INSERT_TAIL(&instance->dev_desc_list, dev_desc, next);
+ }
+
+ return 0;
+
+errout:
+ TAILQ_FOREACH(dev_desc_iter, &instance->dev_desc_list, next)
+ {
+ sk_dev_desc_delete(dev_desc_iter);
+ }
+ return -1;
+}
+
+int stack_device_slave_init(struct mr_stack_instance * instance,
+ struct mr_stack_slave_instance * slave_instance)
+{
+ return 0;
+} \ No newline at end of file
diff --git a/stack/src/neigh.c b/stack/src/neigh.c
new file mode 100644
index 0000000..ac2ef3c
--- /dev/null
+++ b/stack/src/neigh.c
@@ -0,0 +1,230 @@
+/* \brief ��Э��ջ�ھ���ϵͳ
+*
+* �����������ڽ�ͨ�ŵ��������Ϣ
+*
+* \author Lu Qiuwen<[email protected]>
+* \date 2016-10-21
+*/
+
+
+#include <rte_hash.h>
+#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 <sk_device.h>
+#include <sk_protocol_arp.h>
+#include <sk_neigh.h>
+#include <rte_cycles.h>
+#include <rte_hash_crc.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)
+{
+ 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)
+{
+ 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);
+}
+
+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;
+}
+
+static void neigh_destory(struct sk_neighbour * neigh)
+{
+ return;
+}
+
+static void neigh_probe(struct sk_neighbour * neigh)
+{
+ protocol_arp_request_send(neigh->dev, neigh->in_addr);
+}
+
+static inline void neigh_hold(struct sk_neighbour * neigh)
+{
+ rte_atomic16_add(&neigh->refcnt, 1);
+ return;
+}
+
+static inline void neigh_release(struct sk_neighbour * neigh)
+{
+ if (rte_atomic16_dec_and_test(&neigh->refcnt))
+ neigh_destory(neigh);
+ return;
+}
+
+static struct sk_neighbour * neigh_alloc(struct sk_neigh_table * tbl, struct sk_dev_desc * dev)
+{
+ struct sk_neighbour * neigh = rte_zmalloc(NULL, sizeof(struct sk_neighbour), 0);
+ if (unlikely(neigh == NULL))
+ {
+ MR_LOG(INFO, STACK, "NeighSystem, NeighCreate, "
+ "Cannot alloc memory for neighbor structure. \n");
+ 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;
+}
+
+
+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))
+ {
+ ether_addr_copy(lladdr, &neigh->ether_addr);
+ neigh_fill_destinfo(neigh);
+ neigh->dead = 0;
+ neigh->state = state;
+ }
+
+ if((old_state & NUD_INCOMPLETE ) && (state & NUD_REACHABLE))
+ {
+ ether_addr_copy(lladdr, &neigh->ether_addr);
+ neigh_fill_destinfo(neigh);
+ neigh->dead = 0;
+ neigh->state = state;
+ }
+
+ rte_rwlock_write_unlock(&neigh->rwlock);
+ return 0;
+}
+
+int neigh_event_send(struct sk_neighbour * neigh, struct rte_mbuf * mbuf)
+{
+ rte_rwlock_write_lock(&neigh->rwlock);
+
+ if (neigh->state & (NUD_REACHABLE))
+ goto out_unblock;
+
+ if(neigh->state & NUD_NONE)
+ {
+ neigh_probe(neigh);
+ goto out_unblock;
+ }
+
+ //TODO: ����״̬������
+
+out_unblock:
+ rte_rwlock_write_unlock(&neigh->rwlock);
+ return 0;
+}
+
+struct sk_neighbour * neigh_create(struct sk_neigh_table * tbl,
+ struct in_addr in_addr, struct sk_dev_desc * dev)
+{
+ 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);
+
+ // ���������¼�������ARP����
+ neigh_event_send(neigh, NULL);
+ neigh_hold(neigh);
+ return neigh;
+}
+
+struct sk_neighbour * neigh_lookup(struct sk_neigh_table * tbl,
+ const void * pkey, int hold)
+{
+ hash_t hash = *(uint32_t *)pkey;
+ struct sk_neighbour * neigh;
+
+ 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;
+
+ if (hold) neigh_hold(neigh);
+ return neigh;
+}
+
+int neigh_tbl_init(struct sk_neigh_table * tbl, const char * symbol, unsigned int nr_entries)
+{
+ 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,
+ };
+
+ tbl->neigh_tbl = rte_hash_create(&hash_params);
+ if (unlikely(tbl == NULL))
+ {
+ 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;
+ }
+
+ 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;
+} \ No newline at end of file
diff --git a/stack/src/rxtx.c b/stack/src/rxtx.c
new file mode 100644
index 0000000..6f3d376
--- /dev/null
+++ b/stack/src/rxtx.c
@@ -0,0 +1,8 @@
+/* \brief ��Э��ջԭʼ���Ĵ�������
+ *
+ * ģ�鴦������������Э��ջ�����ݱ��ĺ�׼���������������ݱ���
+ *
+ * \author Lu Qiuwen<[email protected]>
+ * \date 2016-10-21
+ */
+
diff --git a/stack/src/stack.c b/stack/src/stack.c
new file mode 100644
index 0000000..1197167
--- /dev/null
+++ b/stack/src/stack.c
@@ -0,0 +1,33 @@
+/* 简单数据通信用户态协议栈管理器
+ *
+ * \author Lu Qiuwen<[email protected]>
+ * \date 2016-10-18
+ */
+
+#include <sk_stack.h>
+#include <rte_ip_frag.h>
+
+struct mr_stack_instance * mr_stack_instance_create(struct mr_stack_param * param)
+{
+ struct mr_stack_instance * instance;
+
+ // 分配空间
+ instance = rte_zmalloc(NULL, sizeof(struct mr_stack_instance), 0);
+ if(unlikely(instance == NULL))
+ {
+ MR_LOG(INFO, STACK, "StackInstanceCreate, "
+ "Cannot alloc memory for stack instance. \n");
+ return NULL;
+ }
+
+ // 初始化参数
+ instance->param = *param;
+ TAILQ_INIT(&instance->dev_info_list);
+ TAILQ_INIT(&instance->dev_desc_list);
+ return instance;
+}
+
+struct mr_stack_slave_instance * mr_stack_slave_create()
+{
+ return NULL;
+} \ No newline at end of file
diff --git a/stack/src/udp.c b/stack/src/udp.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/stack/src/udp.c