diff --git a/srcs/include/service/dhcpd.h b/srcs/include/service/dhcpd.h index cec581a..7ccb24d 100644 --- a/srcs/include/service/dhcpd.h +++ b/srcs/include/service/dhcpd.h @@ -81,21 +81,6 @@ typedef struct { U8 options[0]; } DHCP_PROTO, *PDHCP_PROTO; -typedef struct { - U8 flags; - U8 res1; - U8 res2; - U8 res3; - U32 vni; -} VXLAN_HDR, *PVXLAN_HDR; - -typedef struct { - U16 out_priority_cfi_and_id; - U16 in_type; - U16 in_priority_cfi_and_id; - U16 origin_type; -} QINQ_HDR, *PQINQ_HDR; - #pragma pack(pop) int dhcpd_init(); diff --git a/srcs/libs/CMakeLists.txt b/srcs/libs/CMakeLists.txt index de99927..6b14d7b 100644 --- a/srcs/libs/CMakeLists.txt +++ b/srcs/libs/CMakeLists.txt @@ -5,9 +5,9 @@ PROJECT(${LIB_PROJECT_TARGET} VERSION 1.1.0) STRING(REPLACE ";" ", " BUILD_CONFIG_INFO "${COMMON_DEFINE}") CONFIGURE_FILE(lib_config.h.in lib_config.h) -INCLUDE_DIRECTORIES(include ../opendhcp183 ./mongoose +INCLUDE_DIRECTORIES(include ../opendhcp183 mongoose ./ ./include ../lwip/src/include ../lwip/src/arch_linux/include ../include) -FILE(GLOB C_HEADS include/*.h include/uthash/*.h include/s2j/*.h vector/*.h ${CMAKE_BINARY_DIR}/*.h ${PROJECT_BINARY_DIR}/*.h) +FILE(GLOB C_HEADS ./include/network/*.h include/*.h include/uthash/*.h include/s2j/*.h vector/*.h ${CMAKE_BINARY_DIR}/*.h ${PROJECT_BINARY_DIR}/*.h) AUX_SOURCE_DIRECTORY(json C_SRC) AUX_SOURCE_DIRECTORY(args C_SRC) diff --git a/srcs/libs/include/network/vlan.h b/srcs/libs/include/network/vlan.h new file mode 100644 index 0000000..d435ea7 --- /dev/null +++ b/srcs/libs/include/network/vlan.h @@ -0,0 +1,37 @@ +// +// Created by xajhuang on 2023/3/18. +// + +#ifndef VCPE_VLAN_H +#define VCPE_VLAN_H +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include "common.h" + +#pragma pack(push) +#pragma pack(1) + +#define VXLAN_VIN_ID_PACK(x) ((ntohs(x)) & 0xFFF) + +typedef struct vlan_hdr { + U16 id; + U16 type; +} VLAN_HDR, *PVLAN_HDR; + +typedef struct { + struct ethhdr eth; + struct vlan_hdr vlan; + struct iphdr ip; + struct udphdr udp; +} VLAN_PKG_HDR, *PVLAN_PKG_HDR; + +#pragma pack(pop) +#ifdef __cplusplus +} +#endif +#endif //VCPE_VLAN_H diff --git a/srcs/libs/include/network/vxlan.h b/srcs/libs/include/network/vxlan.h index bc931e8..00938a1 100644 --- a/srcs/libs/include/network/vxlan.h +++ b/srcs/libs/include/network/vxlan.h @@ -4,5 +4,52 @@ #ifndef VCPE_VXLAN_H #define VCPE_VXLAN_H +#ifdef __cplusplus +extern "C" { +#endif +#include +#include +#include +#include "common.h" + +#pragma pack(push) +#pragma pack(1) + +typedef struct vxlan_hdr { + U8 flags; + U8 res1; + U8 res2; + U8 res3; + U32 vni; +} VXLAN_HDR, *PVXLAN_HDR; + +typedef struct qinq_hdr { +#if __BYTE_ORDER == __LITTLE_ENDIAN + U32 priority : 3; + U32 dei : 1; + U32 id : 12; +#elif __BYTE_ORDER == __BIG_ENDIAN + U32 id : 12; + U32 dei : 1; + U32 priority : 3; +#else +#error "Please fix " +#endif +} QINQ_HDR, *PQINQ_HDR; + +typedef struct { + struct ethhdr eth; + struct iphdr ip; + struct udphdr udp; + struct vxlan_hdr vxlan; + struct ethhdr eth_in; + struct qinq_hdr qinq; +} VXLAN_PKG_HDR, *PVXLAN_PKG_HDR; + +#pragma pack(pop) + +#ifdef __cplusplus +} +#endif #endif //VCPE_VXLAN_H diff --git a/srcs/libs/include/user_errno.h b/srcs/libs/include/user_errno.h index bbf69b1..7ef0fd8 100644 --- a/srcs/libs/include/user_errno.h +++ b/srcs/libs/include/user_errno.h @@ -23,48 +23,49 @@ extern "C" { ERR_CODE(ERR_GET_FILE_SIZE, 11, "获取文件大小失败") \ ERR_CODE(ERR_COPY_FILE, 12, "复制文件失败") \ ERR_CODE(ERR_MALLOC_MEMORY, 13, "分配内存失败") \ - ERR_CODE(ERR_EVP_KEY_SIZE, 14, "秘钥大小不正确") \ - ERR_CODE(ERR_UNSUP_EVP_TYPE, 15, "不支持的加解密算法") \ - ERR_CODE(ERR_EVP_INIT_KEY, 16, "初始化秘钥失败") \ - ERR_CODE(ERR_EVP_UPDATE, 17, "加解密数据失败") \ - ERR_CODE(ERR_EVP_FINALE, 18, "错误的加解密结果") \ - ERR_CODE(ERR_EVP_CREATE_CTX, 19, "初始化加解密失败") \ - ERR_CODE(ERR_AES_KEYGEN, 20, "AES秘钥失败") \ - ERR_CODE(ERR_EVP_ENCRYPTION, 21, "加密失败") \ - ERR_CODE(ERR_EVP_DECRYPTION, 22, "解密失败") \ - ERR_CODE(ERR_CONFIG_INIT, 23, "配置文件初始化失败") \ - ERR_CODE(ERR_UNCOMPATIBILITY_TYPE, 24, "未兼容的类型") \ - ERR_CODE(ERR_STRING_TO_NUMBER, 25, "字符串转数字失败") \ - ERR_CODE(ERR_UNKNOWN_CFG_ID, 26, "未识别的配置项") \ - ERR_CODE(ERR_ZLOG_INIT, 27, "日志系统初始化失败") \ - ERR_CODE(ERR_SYS_GET_CPU_INFO, 28, "获取CPU信息失败") \ - ERR_CODE(ERR_SYS_NOT_FOUND_CPU, 29, "找不到CPU信息") \ - ERR_CODE(ERR_SYS_DISK_GET_INFO, 30, "获取磁盘空间占用信息失败") \ - ERR_CODE(ERR_SYS_IPMI_UNSUP, 31, "服务器IPMI接口不支持") \ - ERR_CODE(ERR_SYS_SENSOR_GET_INFO, 32, "获取传感器信息失败") \ - ERR_CODE(ERR_DB_CONNECT, 33, "数据库连接失败") \ - ERR_CODE(ERR_MQ_CREATE_MQ, 34, "创建消息队列失败") \ - ERR_CODE(ERR_MQ_CREATE_REP, 35, "创建REP消息队列失败") \ - ERR_CODE(ERR_MQ_BIND_SOCKET, 36, "消息队列BIND Socket失败") \ - ERR_CODE(ERR_MQ_CONN_SERVER, 37, "消息队列连接服务器失败") \ - ERR_CODE(ERR_MQ_SEND_MSG, 38, "消息队列发送消息失败") \ - ERR_CODE(ERR_JSON_CREAT_OBJ, 39, "创建JSON对象失败") \ - ERR_CODE(ERR_JSON_PARSE_OBJ, 40, "解析JSON对象失败") \ - ERR_CODE(ERR_JSON_VALID_SCH, 41, "JSON数据验证失败") \ - ERR_CODE(ERR_CREATE_NETIF, 42, "创建网络接口失败") \ - ERR_CODE(ERR_CREATE_PPPOE_NETIF, 43, "创建PPPoE网络接口失败") \ - ERR_CODE(ERR_CREATE_PPP_SESSION, 44, "创建PPP连接失败") \ - ERR_CODE(ERR_MISC_GET_IPADDR, 45, "获取网卡IP地址失败") \ - ERR_CODE(ERR_MISC_GET_NETMASK, 46, "获取网卡子网掩码失败") \ - ERR_CODE(ERR_MISC_GET_GATEWAY, 47, "获取网卡网关地址失败") \ - ERR_CODE(ERR_MISC_GET_MACADDR, 48, "获取网卡MAC地址失败") \ - ERR_CODE(ERR_MENU_EXIT, 49, "菜单执行完后自动退出") \ - ERR_CODE(ERR_HTTP_UNSUP_METHOD, 50, "不支持的 HTTP 请求方法") \ - ERR_CODE(ERR_HTTP_UNSUP_PAGE, 51, "找不到 HTTP 服务") \ - ERR_CODE(ERR_PROTO_DECODE, 52, "HTTP 协议解析失败") \ - ERR_CODE(ERR_MSG_CONTENT, 53, "msgContent内容不正确") \ - ERR_CODE(ERR_SOCK_CREATE, 54, "创建套接字失败") \ - ERR_CODE(ERR_SOCK_SETOPT, 55, "设置套接字参数失败") + ERR_CODE(ERR_MMAP_MEMORY, 14, "共享内存失败") \ + ERR_CODE(ERR_EVP_KEY_SIZE, 15, "秘钥大小不正确") \ + ERR_CODE(ERR_UNSUP_EVP_TYPE, 16, "不支持的加解密算法") \ + ERR_CODE(ERR_EVP_INIT_KEY, 17, "初始化秘钥失败") \ + ERR_CODE(ERR_EVP_UPDATE, 18, "加解密数据失败") \ + ERR_CODE(ERR_EVP_FINALE, 19, "错误的加解密结果") \ + ERR_CODE(ERR_EVP_CREATE_CTX, 20, "初始化加解密失败") \ + ERR_CODE(ERR_AES_KEYGEN, 21, "AES秘钥失败") \ + ERR_CODE(ERR_EVP_ENCRYPTION, 22, "加密失败") \ + ERR_CODE(ERR_EVP_DECRYPTION, 23, "解密失败") \ + ERR_CODE(ERR_CONFIG_INIT, 24, "配置文件初始化失败") \ + ERR_CODE(ERR_UNCOMPATIBILITY_TYPE, 25, "未兼容的类型") \ + ERR_CODE(ERR_STRING_TO_NUMBER, 26, "字符串转数字失败") \ + ERR_CODE(ERR_UNKNOWN_CFG_ID, 27, "未识别的配置项") \ + ERR_CODE(ERR_ZLOG_INIT, 28, "日志系统初始化失败") \ + ERR_CODE(ERR_SYS_GET_CPU_INFO, 29, "获取CPU信息失败") \ + ERR_CODE(ERR_SYS_NOT_FOUND_CPU, 30, "找不到CPU信息") \ + ERR_CODE(ERR_SYS_DISK_GET_INFO, 31, "获取磁盘空间占用信息失败") \ + ERR_CODE(ERR_SYS_IPMI_UNSUP, 32, "服务器IPMI接口不支持") \ + ERR_CODE(ERR_SYS_SENSOR_GET_INFO, 33, "获取传感器信息失败") \ + ERR_CODE(ERR_DB_CONNECT, 34, "数据库连接失败") \ + ERR_CODE(ERR_MQ_CREATE_MQ, 35, "创建消息队列失败") \ + ERR_CODE(ERR_MQ_CREATE_REP, 36, "创建REP消息队列失败") \ + ERR_CODE(ERR_MQ_BIND_SOCKET, 37, "消息队列BIND Socket失败") \ + ERR_CODE(ERR_MQ_CONN_SERVER, 38, "消息队列连接服务器失败") \ + ERR_CODE(ERR_MQ_SEND_MSG, 39, "消息队列发送消息失败") \ + ERR_CODE(ERR_JSON_CREAT_OBJ, 40, "创建JSON对象失败") \ + ERR_CODE(ERR_JSON_PARSE_OBJ, 41, "解析JSON对象失败") \ + ERR_CODE(ERR_JSON_VALID_SCH, 42, "JSON数据验证失败") \ + ERR_CODE(ERR_CREATE_NETIF, 43, "创建网络接口失败") \ + ERR_CODE(ERR_CREATE_PPPOE_NETIF, 44, "创建PPPoE网络接口失败") \ + ERR_CODE(ERR_CREATE_PPP_SESSION, 45, "创建PPP连接失败") \ + ERR_CODE(ERR_MISC_GET_IPADDR, 46, "获取网卡IP地址失败") \ + ERR_CODE(ERR_MISC_GET_NETMASK, 47, "获取网卡子网掩码失败") \ + ERR_CODE(ERR_MISC_GET_GATEWAY, 48, "获取网卡网关地址失败") \ + ERR_CODE(ERR_MISC_GET_MACADDR, 49, "获取网卡MAC地址失败") \ + ERR_CODE(ERR_MENU_EXIT, 50, "菜单执行完后自动退出") \ + ERR_CODE(ERR_HTTP_UNSUP_METHOD, 51, "不支持的 HTTP 请求方法") \ + ERR_CODE(ERR_HTTP_UNSUP_PAGE, 52, "找不到 HTTP 服务") \ + ERR_CODE(ERR_PROTO_DECODE, 53, "HTTP 协议解析失败") \ + ERR_CODE(ERR_MSG_CONTENT, 54, "msgContent内容不正确") \ + ERR_CODE(ERR_SOCK_CREATE, 55, "创建套接字失败") \ + ERR_CODE(ERR_SOCK_SETOPT, 56, "设置套接字参数失败") #define GENERATE_ENUM(ENUM, no, x) ENUM, diff --git a/srcs/libs/include/zlog_module.h b/srcs/libs/include/zlog_module.h index 27c7ff8..423eb4f 100644 --- a/srcs/libs/include/zlog_module.h +++ b/srcs/libs/include/zlog_module.h @@ -79,6 +79,7 @@ typedef enum { zlog_put_mdc("vni", zlog_vni_tag_get()); \ } \ hzlog_##level(zlog_get_mod_cat((mod)), format, ##__VA_ARGS__); \ + printf("\n"); \ } \ } while (0) diff --git a/srcs/libs/mongoose/mongoose.c b/srcs/libs/mongoose/mongoose.c index 667aaf2..0c25fb0 100644 --- a/srcs/libs/mongoose/mongoose.c +++ b/srcs/libs/mongoose/mongoose.c @@ -7712,7 +7712,7 @@ static void rx_dhcp_server(struct mip_if *ifp, struct pkt *pkt) { if (end < (uint8_t *)(pkt->dhcp + 1)) { return; } - // struct dhcp *req = pkt->dhcp; + // struct dhcp *recv_req = pkt->dhcp; struct dhcp res = {2, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, {0}, 0, {0}}; res.yiaddr = ifp->ip; ((uint8_t *)(&res.yiaddr))[3]++; // Offer our IP + 1 diff --git a/srcs/service/dhcpd/dhcpd_network.c b/srcs/service/dhcpd/dhcpd_network.c index 26ce8ea..85814d0 100644 --- a/srcs/service/dhcpd/dhcpd_network.c +++ b/srcs/service/dhcpd/dhcpd_network.c @@ -6,35 +6,59 @@ #include #include -#include -#include -#include -#include -#include #include +#include +#include +#include #include "service/dhcpd.h" #include "user_errno.h" #include "task_manager.h" #include "zlog_module.h" +#include "network/vlan.h" + +#define PKG_MMAP_BLOCKSIZ (1 << 22) +#define PKG_MMAP_FRAMESIZ (1 << 11) +#define PKG_MMAP_BLOCKNUM (64) + +typedef struct { + struct iovec *rd; + uint8_t *map; + struct tpacket_req3 req; +} PACKET_MMAP_RING, *PPACKET_MMAP_RING; + +struct block_desc { + uint32_t version; + uint32_t offset_to_priv; + struct tpacket_hdr_v1 h1; +}; #pragma pack(1) typedef struct { - struct ethhdr eth; - struct iphdr ip; - struct udphdr udp; - DHCP_PROTO dhcp; + VLAN_PKG_HDR vlan_hdr; + DHCP_PROTO dhcp; } DHCP_PACKAGE, *PDHCP_PACKAGE; -#pragma pack() +typedef struct { + uv_work_t uvWork; + unsigned short nSize; + unsigned char *pPkgBase; + void *pData; +} PKG_PROCESS_INFO, *PPKG_PROCESS_INFO; typedef struct { - unsigned int vni; - unsigned short q1; - unsigned short q2; -} VXLAN_TAG, *PVXLAN_TAG; + unsigned int nf; + PPKG_PROCESS_INFO pPkgInfo; +} PKG_MSG, *PPKG_MSG; +#pragma pack() +/* +TORs (Top of Rack switch) at Facebook run DHCP relayers, these relayers are +responsible for relaying broadcast DHCP traffic (DISCOVERY and SOLICIT +messages) originating within their racks to anycast VIPs, one DHCPv4 and one +for DHCPv6. +*/ static struct sock_filter g_filterCode[] = { #ifdef UDP_DHCP_FILTER // create by: tcpdump "udp and port 67 and port 68" -dd {0x28, 0, 0, 0x0000000c}, @@ -64,6 +88,7 @@ static struct sock_filter g_filterCode[] = { {0x6, 0, 0, 0x00040000}, {0x6, 0, 0, 0x00000000}, #endif +#if 0 // create by: tcpdump "vxlan" -dd {0x28, 0, 0, 0x0000000c}, {0x15, 2, 0, 0x00008100}, @@ -71,102 +96,204 @@ static struct sock_filter g_filterCode[] = { {0x15, 0, 1, 0x00009100}, {0x6, 0, 0, 0x00040000}, {0x6, 0, 0, 0x00000000}, +#endif + // create by: tcpdump "vlan" -dd + {0x30, 0, 0, 0xfffff030}, + {0x15, 4, 0, 0x00000001}, + {0x28, 0, 0, 0x0000000c}, + {0x15, 2, 0, 0x00008100}, + {0x15, 1, 0, 0x000088a8}, + {0x15, 0, 1, 0x00009100}, + {0x6, 0, 0, 0x00040000}, + {0x6, 0, 0, 0x00000000}, }; +static PACKET_MMAP_RING g_pkgRing; + static struct sock_fprog bpf = { .len = sizeof(g_filterCode) / (sizeof(struct sock_filter)), .filter = g_filterCode, }; -static void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) { - *buf = uv_buf_init(malloc(suggested_size), suggested_size); +static void on_sock_recv(uv_work_t *req) { + PPKG_PROCESS_INFO pWork = (PPKG_PROCESS_INFO)req->data; + PDHCP_PACKAGE pkg = (PDHCP_PACKAGE)pWork->pPkgBase; + + //LOG_MSG_HEX(debug, pkg, pWork->nSize); +#if 0 + LOG_MOD(info, ZLOG_MOD_OPENDHCPD, "vlan = %u\n", VXLAN_VIN_ID_PACK(pkg->vlan_hdr.vlan.id)); + LOG_MSG(info, "xid: 0x%08X\n", ntohl(pkg->dhcp.xid)); + LOG_MSG(info, + "dest mac: %02X:%02X:%02X:%02X:%02X:%02X\n", + pkg->vlan_hdr.eth.h_dest[0], + pkg->vlan_hdr.eth.h_dest[1], + pkg->vlan_hdr.eth.h_dest[2], + pkg->vlan_hdr.eth.h_dest[3], + pkg->vlan_hdr.eth.h_dest[4], + pkg->vlan_hdr.eth.h_dest[5]); + LOG_MSG(info, + "client mac: %02X:%02X:%02X:%02X:%02X:%02X\n", + pkg->dhcp.chaddr[0], + pkg->dhcp.chaddr[1], + pkg->dhcp.chaddr[2], + pkg->dhcp.chaddr[3], + pkg->dhcp.chaddr[4], + pkg->dhcp.chaddr[5]); +#endif } -static void package_process(uv_work_t *req) { - PDHCP_PACKAGE pkg = (PDHCP_PACKAGE)req->data; +static void after_msg_recv(uv_work_t *req, int status) { + PPKG_PROCESS_INFO pInfo = (PPKG_PROCESS_INFO)req->data; + PPKG_MSG pMsg = (PPKG_MSG)pInfo->pData; + + pMsg->nf -= 1; + if (pMsg->nf <= 0) { + LOG_MOD(debug, ZLOG_MOD_OPENDHCPD, "Free all resources: %p\n", pMsg); + free(pMsg->pPkgInfo); + free(pMsg); + } } -static void on_read(uv_udp_t *req, ssize_t nread, const uv_buf_t *buf, const struct sockaddr *addr, unsigned flags) { - if (nread > 0) { - uv_work_t *pWork = (uv_work_t *)malloc(sizeof(uv_work_t)); +void raw_sock_recv_cb(uv_poll_t *handle, int status, int events) { + static unsigned int block_num = 0; - if (!pWork) { - free(buf->base); - LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "Malloc %lu memory error\n", sizeof(uv_work_t)); - return; + if (status >= 0) { + struct block_desc *pbd = (struct block_desc *)g_pkgRing.rd[block_num].iov_base; + + if ((pbd->h1.block_status & TP_STATUS_USER) != 0) { + int i; + unsigned int num_pkts = pbd->h1.num_pkts; + struct tpacket3_hdr *ppd; + uv_loop_t *pLoop = get_task_manager(); + + if (num_pkts > 0) { + unsigned int memSize = sizeof(PKG_PROCESS_INFO) * num_pkts; + PPKG_MSG pMsg = (PPKG_MSG)malloc(sizeof(PKG_MSG)); + + if (pMsg == NULL) { + LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "Malloc memory error: %lu\n", sizeof(PKG_MSG)); + return; + } + + memset(pMsg, 0, sizeof(PKG_MSG)); + pMsg->pPkgInfo = (PPKG_PROCESS_INFO)malloc(memSize); + + if (pMsg->pPkgInfo == NULL) { + LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "Malloc memory error: %u\n", memSize); + free(pMsg); + return; + } + + memset(pMsg->pPkgInfo, 0, memSize); + + pMsg->nf = num_pkts; + ppd = (struct tpacket3_hdr *)((uint8_t *)pbd + pbd->h1.offset_to_first_pkt); + for (i = 0; i < num_pkts; i++) { + pMsg->pPkgInfo[i].pPkgBase = ((uint8_t *)ppd + ppd->tp_mac); + pMsg->pPkgInfo[i].nSize = ppd->tp_snaplen; + pMsg->pPkgInfo[i].uvWork.data = &pMsg->pPkgInfo[i]; + pMsg->pPkgInfo[i].pData = pMsg; + + uv_queue_work(get_task_manager(), &(pMsg->pPkgInfo[i].uvWork), on_sock_recv, after_msg_recv); + ppd = (struct tpacket3_hdr *)((uint8_t *)ppd + ppd->tp_next_offset); + } + } } - pWork->data = (void *)buf; - uv_queue_work(get_task_manager(), pWork, package_process, NULL); - - PDHCP_PACKAGE pkg = (PDHCP_PACKAGE)buf->base; - LOG_MSG(info, "xid: 0x%08X\n", ntohl(pkg->dhcp.xid)); - LOG_MSG(info, - "client mac: %02X:%02X:%02X:%02X:%02X:%02X\n", - pkg->dhcp.chaddr[0], - pkg->dhcp.chaddr[1], - pkg->dhcp.chaddr[2], - pkg->dhcp.chaddr[3], - pkg->dhcp.chaddr[4], - pkg->dhcp.chaddr[5]); - //LOG_MSG_HEX(debug, buf->base, nread); + pbd->h1.block_status = TP_STATUS_KERNEL; + block_num = (block_num + 1) % PKG_MMAP_BLOCKNUM; } - - free(buf->base); } static int create_udp_socket() { + int i; + int err; + int v = TPACKET_V3; + struct sockaddr_ll addr; // 1. create socket int sock_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (sock_fd < 0) { - perror("socket created failure"); + LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "Socket created failure\n"); return -ERR_SOCK_CREATE; } + // 2. attach filter (no need to call bind) + if ((err = setsockopt(sock_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf))) < 0) { + LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "Attaching filter failed: %d\n", err); + return -ERR_SOCK_SETOPT; + } +#if 1 + // 3. set PACKET_MMAP version + if ((err = setsockopt(sock_fd, SOL_PACKET, PACKET_VERSION, &v, sizeof(v))) < 0) { + LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "Set PACKET_VERSION option failed: %d\n", err); + return -ERR_SOCK_SETOPT; + } + + // 4. setup PAKCET_MMAP ring + memset(&g_pkgRing.req, 0, sizeof(g_pkgRing.req)); + g_pkgRing.req.tp_block_size = PKG_MMAP_BLOCKSIZ; + g_pkgRing.req.tp_frame_size = PKG_MMAP_FRAMESIZ; + g_pkgRing.req.tp_block_nr = PKG_MMAP_BLOCKNUM; + g_pkgRing.req.tp_frame_nr = (PKG_MMAP_BLOCKSIZ * PKG_MMAP_BLOCKNUM) / PKG_MMAP_FRAMESIZ; + g_pkgRing.req.tp_retire_blk_tov = 60; + g_pkgRing.req.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH; + + if ((err = setsockopt(sock_fd, SOL_PACKET, PACKET_RX_RING, &g_pkgRing.req, sizeof(g_pkgRing.req))) < 0) { + LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "Set PACKET_RX_RING option failed: %d\n", err); + return -ERR_SOCK_SETOPT; + } + + g_pkgRing.map = mmap(NULL, + g_pkgRing.req.tp_block_size * g_pkgRing.req.tp_block_nr, + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_LOCKED, + sock_fd, + 0); + + if (g_pkgRing.map == MAP_FAILED) { + LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "MMAP socket ring failed\n"); + return -ERR_MMAP_MEMORY; + } + + // 5. malloc read buffer + g_pkgRing.rd = malloc(g_pkgRing.req.tp_block_nr * sizeof(struct iovec)); + + if (g_pkgRing.rd == NULL) { + LOG_MOD(error, + ZLOG_MOD_OPENDHCPD, + "Malloc memory failed: %lu\n", + g_pkgRing.req.tp_block_nr * sizeof(struct iovec)); + return -ERR_MMAP_MEMORY; + } + + for (i = 0; i < g_pkgRing.req.tp_block_nr; ++i) { + g_pkgRing.rd[i].iov_base = g_pkgRing.map + (i * g_pkgRing.req.tp_block_size); + g_pkgRing.rd[i].iov_len = g_pkgRing.req.tp_block_size; + } +#endif + // 6. bind socket const char *iface_name = "ens192"; memset(&addr, 0, sizeof(addr)); addr.sll_ifindex = (int)if_nametoindex(iface_name); addr.sll_family = AF_PACKET; addr.sll_protocol = htons(ETH_P_ALL); + addr.sll_hatype = 0; + addr.sll_pkttype = 0; + addr.sll_halen = 0; - // 2. attach filter (no need to call bind) - if (setsockopt(sock_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf)) < 0) { - perror("attaching filter failed"); + if ((err = bind(sock_fd, (struct sockaddr *)&addr, sizeof(addr))) < 0) { + LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "Bind raw socket failed: %d\n", err); return -ERR_SOCK_SETOPT; } return sock_fd; } -#if 0 -#define MAX_DATE_ITEMS (64) - -void fib(uv_work_t *req) { - int cnt = 3; - fprintf(stderr, "Task %ld\n", (long)(req->data)); - while (cnt--) { - uv_sleep(1000); - } -} - -void after_fib(uv_work_t *req, int status) { - fprintf(stderr, "Finish Task %ld\n", (long)(req->data)); -} -#endif int dhcpd_init() { - static uv_udp_t uvRaw; -#if 0 - static unsigned int data[MAX_DATE_ITEMS]; - static uv_work_t req[MAX_DATE_ITEMS]; - int i; - - for (i = 0; i < MAX_DATE_ITEMS; i++) { - req[i].data = (void *)(intptr_t)i; - uv_queue_work(get_task_manager(), &req[i], fib, after_fib); - } -#endif + static uv_udp_t uvRaw; + static uv_poll_t uvSocket; int sock = create_udp_socket(); @@ -174,12 +301,13 @@ int dhcpd_init() { return sock; } - LOG_MSG(info, "sizeof DHCP_PACKAGE = %lu\n", sizeof(DHCP_PACKAGE)); + //LOG_MSG(info, "sizeof DHCP_PACKAGE = %lu\n", sizeof(DHCP_PACKAGE)); uv_udp_init(get_task_manager(), &uvRaw); uv_udp_open(&uvRaw, sock); - uv_udp_recv_start(&uvRaw, alloc_buffer, on_read); + uv_poll_init_socket(get_task_manager(), &uvSocket, sock); + uv_poll_start(&uvSocket, UV_READABLE, raw_sock_recv_cb); return ERR_SUCCESS; } \ No newline at end of file