diff --git a/depend/system_libs.cmake b/depend/system_libs.cmake
index 648dd15..d8549ab 100644
--- a/depend/system_libs.cmake
+++ b/depend/system_libs.cmake
@@ -19,9 +19,9 @@ FUNCTION(LINUX_INSTALL_SYSTEM_PACKAGE)
 
         MESSAGE("Run this command to install system(${OS_DISTRIB_NAME}) dependencies libraries:")
         IF (${OS_DISTRIB_NAME} MATCHES "CentOS")
-            MESSAGE(FATAL_ERROR "$sudo yum -y install libcurl-devel czmq-devel openssl-devel")
+            MESSAGE(FATAL_ERROR "$sudo yum -y install libcurl-devel czmq-devel openssl-devel libjson-c-devel")
         ELSEIF (${OS_DISTRIB_NAME} MATCHES "Ubuntu")
-            MESSAGE(FATAL_ERROR "$sudo apt -y install libcurl4-openssl-dev libczmq-dev libssl-dev")
+            MESSAGE(FATAL_ERROR "$sudo apt -y install libcurl4-openssl-dev libczmq-dev libssl-dev libjson-c-dev")
         ENDIF ()
     ELSE ()
         MESSAGE(FATAL_ERROR "Run command to install system dependencies libraries [libcurl,libssl,libcrypto,libzmq] by yourself")
diff --git a/srcs/libs/include/misc.h b/srcs/libs/include/misc.h
index 6bd4c66..b791689 100644
--- a/srcs/libs/include/misc.h
+++ b/srcs/libs/include/misc.h
@@ -44,6 +44,7 @@ int                get_all_network_info(PSYS_NIC_INFO pInfo);
 const char        *u32_to_str_ip(unsigned int ip);
 unsigned short     udp_checksum(unsigned int saddr, unsigned int daddr, unsigned char *pUdp);
 unsigned short     ip_checksum(unsigned char *pIp);
+int                string_mac_to_bytes(const char *pStrMac, unsigned char macByte[6]);
 #ifdef __cplusplus
 }
 #endif
diff --git a/srcs/libs/misc/misc.c b/srcs/libs/misc/misc.c
index 303e269..e61cfdb 100644
--- a/srcs/libs/misc/misc.c
+++ b/srcs/libs/misc/misc.c
@@ -18,6 +18,7 @@
 #include "misc.h"
 #include "zlog_module.h"
 #include "common.h"
+#include "sds/sds.h"
 
 PSYS_NIC_INFO g_sysNicInfo = NULL;
 
@@ -309,7 +310,7 @@ int get_all_network_info(PSYS_NIC_INFO pInfo) {
         return -ERR_MALLOC_MEMORY;
     }
 
-    LOG_MOD(info, ZLOG_MOD_MISC, "Malloc memory size: %lu * %lu\n", sizeof(NIC_CTX), nicCnt);
+    LOG_MOD(trace, ZLOG_MOD_MISC, "Malloc memory size: %lu * %lu\n", sizeof(NIC_CTX), nicCnt);
 
     memset(pNicInfo->pNicCtx, 0, sizeof(NIC_CTX) * nicCnt);
 
@@ -415,4 +416,31 @@ unsigned short udp_checksum(unsigned int saddr, unsigned int daddr, unsigned cha
 
     csum = ((csum & 0xFFFF0000) >> 16) + (csum & 0xFFFF);
     return (unsigned short)(~csum);
+}
+
+int string_mac_to_bytes(const char *pStrMac, unsigned char macByte[6]) {
+    sds *tokens;
+    int  i, nCnt;
+
+    if (pStrMac == NULL || strlen(pStrMac) != strlen("00:00:00:00:00:00")) {
+        LOG_MOD(error, ZLOG_MOD_MISC, "Input params error\n");
+        return -ERR_INPUT_PARAMS;
+    }
+
+    tokens = sdssplitlen(pStrMac, (int)strlen(pStrMac), ":", 1, &nCnt);
+
+    if (nCnt != 6) {
+        LOG_MOD(error, ZLOG_MOD_MISC, "Input MAC[%s] error: %d\n", pStrMac, nCnt);
+        return -ERR_INPUT_PARAMS;
+    }
+
+    for (i = 0; i < nCnt; i++) {
+        macByte[i] = strtoul(tokens[i], NULL, 16);
+    }
+
+    if (tokens) {
+        sdsfreesplitres(tokens, nCnt);
+    }
+
+    return ERR_SUCCESS;
 }
\ No newline at end of file
diff --git a/srcs/service/dhcpd/dhcp_option.c b/srcs/service/dhcpd/dhcp_option.c
index 6c24088..bd60423 100644
--- a/srcs/service/dhcpd/dhcp_option.c
+++ b/srcs/service/dhcpd/dhcp_option.c
@@ -5,7 +5,6 @@
 #include "common.h"
 #include "dhcp_options.h"
 #include "user_errno.h"
-#include "zlog_module.h"
 
 static const DHCP_OPTION_CFG g_opCfg[] = {
   // region DHCP optinos configure table
diff --git a/srcs/service/dhcpd/dhcpd_network.c b/srcs/service/dhcpd/dhcpd_network.c
index 8d4cf50..c28abf7 100644
--- a/srcs/service/dhcpd/dhcpd_network.c
+++ b/srcs/service/dhcpd/dhcpd_network.c
@@ -1,96 +1,27 @@
 //
 // Created by xajhuang on 2023/3/16.
 //
-#include <uv.h>
 #include <stdlib.h>
 #include <string.h>
-
 #include <linux/filter.h>
-#include <linux/if_packet.h>
 #include <net/if.h>
 #include <sys/socket.h>
 #include <sys/mman.h>
 #include <pcap/pcap.h>
+#include <unistd.h>
 
-#include "service/dhcpd.h"
 #include "user_errno.h"
 #include "task_manager.h"
 #include "zlog_module.h"
-#include "network/vlan.h"
+
 #include "dhcp_options.h"
 #include "config.h"
 #include "misc.h"
 #include "user_mgr.h"
+#include "rfc2131.h"
+#include "dhcp_network.h"
 
-#define DHCP_COOKIE_VAL   (0x63825363)
-#define PKG_MMAP_BLOCKSIZ (1 << 22)
-#define PKG_MMAP_FRAMESIZ (1 << 11)
-#define PKG_MMAP_BLOCKNUM (64)
-#define MAX_DHCP_PKG_SIZE (512)
-#define VLAN_VNI_ID(x)    ntohs((x))
-#define DHCP_XID(x)       ntohl((x))
-#define MAXIMUM_SNAPLEN	  (262144)
-
-#define MAC_TO_STR(mac, str) \
-    sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])
-
-typedef struct {
-    U8   unicast;
-    U8   cliMac[ETH_ALEN];
-    U32  xid;
-    U32  reqIpAddr;
-    U32  leaseTime;
-    char clientId[256];
-    char vendorClassId[256];
-    char hostName[256];
-} DHCP_REQ, *PDHCP_REQ;
-
-typedef struct {
-    int                 sock;
-    struct sockaddr_ll  addr;
-    struct iovec       *rx;
-    struct iovec       *tx;
-    uint8_t            *map_recv;
-    uint8_t            *map_send;
-    struct tpacket_req3 recv;
-    struct tpacket_req3 send;
-    unsigned int        index;
-} PACKET_MMAP_RING, *PPACKET_MMAP_RING;
-
-typedef struct {
-    char *pIfName;
-    U32   ipAddr;
-    U32   netmask;
-    U8    macAddr[ETH_ALEN];
-    S8    hostname[MAX_PATH];
-} NIC_INFO, *PNIC_INFO;
-
-struct block_desc {
-    uint32_t              version;
-    uint32_t              offset_to_priv;
-    struct tpacket_hdr_v1 h1;
-};
-
-#pragma pack(1)
-
-typedef struct {
-    VLAN_PKG_HDR vlan_hdr;
-    DHCP_PROTO   dhcp;
-} DHCP_PACKAGE, *PDHCP_PACKAGE;
-
-typedef struct {
-    uv_work_t      uvWork;
-    unsigned short nSize;
-    unsigned char *pPkgBase;
-    void          *pData;
-} PKG_PROCESS_INFO, *PPKG_PROCESS_INFO;
-
-typedef struct {
-    unsigned int      nf;
-    PPKG_PROCESS_INFO pPkgInfo;
-} PKG_MSG, *PPKG_MSG;
-
-#pragma pack()
+#define MAXIMUM_SNAPLEN (262144)
 
 /*
 TORs (Top of Rack switch) at Facebook run DHCP relayers, these relayers are
@@ -219,7 +150,7 @@ static PACKET_MMAP_RING  g_pkgRing;
 static NIC_INFO          g_nicInfo;
 static uv_udp_t          g_uvRawSockReq;
 
-void *get_pkg_memory() {
+void *get_pkg_free_buf() {
     int                  i;
     ssize_t              ret;
     struct tpacket3_hdr *hdr;
@@ -250,7 +181,7 @@ static int dhcp_resp_offer(PDHCP_PACKAGE pReq, PIPPOOL_INFO pIpInfo, U32 ip) {
     U8           *pOpt;
     U16           csum;
     int           tolSize;
-    PDHCP_PACKAGE pRsp = get_pkg_memory();
+    PDHCP_PACKAGE pRsp = get_pkg_free_buf();
 
     if (pRsp == NULL) {
         LOG_MOD(error, ZLOG_MOD_DHCPD, "Malloc memory error: %u\n", MAX_DHCP_PKG_SIZE);
@@ -510,6 +441,7 @@ static void after_msg_recv(uv_work_t *req, int status) {
 
 void raw_sock_recv_cb(uv_poll_t *handle, int status, int events) {
     static unsigned int block_num = 0;
+    PRECV_CB_DATA       pCbData   = handle->data;
 
     if (status >= 0 && (events & UV_READABLE)) {
         struct block_desc *pbd = (struct block_desc *)g_pkgRing.rx[block_num].iov_base;
@@ -546,7 +478,15 @@ void raw_sock_recv_cb(uv_poll_t *handle, int status, int events) {
                 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);
+                if (pCbData) {
+                    uv_queue_work(get_task_manager(),
+                                  &(pMsg->pPkgInfo[i].uvWork),
+                                  pCbData->work_cb ? pCbData->work_cb : on_sock_recv,
+                                  pCbData->after_work_cb ? pCbData->after_work_cb : after_msg_recv);
+                } else {
+                    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);
             }
         }
@@ -556,7 +496,7 @@ void raw_sock_recv_cb(uv_poll_t *handle, int status, int events) {
     }
 }
 
-static int create_udp_socket() {
+int create_udp_raw_socket(const char *pNicName) {
     struct sockaddr_ll addr;
     unsigned int       size;
     int                i;
@@ -660,7 +600,7 @@ static int create_udp_socket() {
 
     // 9. bind socket
     memset(&addr, 0, sizeof(struct sockaddr_ll));
-    addr.sll_ifindex  = (int)if_nametoindex(g_nicInfo.pIfName);
+    addr.sll_ifindex  = (int)if_nametoindex(pNicName);
     addr.sll_family   = PF_PACKET;
     addr.sll_protocol = htons(ETH_P_ALL);
     addr.sll_hatype   = 0;
@@ -677,7 +617,7 @@ static int create_udp_socket() {
     return ERR_SUCCESS;
 }
 
-static void socket_send_task(uv_timer_t *UNUSED(pArg)) {
+void socket_send_task(uv_timer_t *UNUSED(pArg)) {
     int                  i;
     struct tpacket3_hdr *hdr;
 
@@ -694,21 +634,20 @@ static void socket_send_task(uv_timer_t *UNUSED(pArg)) {
     }
 }
 
-void init_filter() {
+void init_filter(const char *pNetFilter) {
 #ifdef USED_DEFAULT_BPF
     bpf.len    = sizeof(g_filterCode) / (sizeof(struct sock_filter));
     bpf.filter = g_filterCode;
 #else
     static pcap_t *pd;
     pd = pcap_open_dead(DLT_EN10MB, MAXIMUM_SNAPLEN);
-
     struct bpf_program fcode;
-    char *cmd_buf = "vlan and udp and port 67 and port 68";
-    pcap_compile(pd, &fcode, cmd_buf, 1, 0);
+    //char              *cmd_buf = "vlan and udp and port 67 and port 68";
+    pcap_compile(pd, &fcode, pNetFilter, 1, 0);
 
-    struct bpf_insn *insn = fcode.bf_insns;
-    struct sock_filter *g_filters = (struct sock_filter *)malloc(fcode.bf_len * sizeof (struct sock_filter));
-    for (int i = 0; i < fcode.bf_len; ++insn, ++i){
+    struct bpf_insn    *insn      = fcode.bf_insns;
+    struct sock_filter *g_filters = (struct sock_filter *)malloc(fcode.bf_len * sizeof(struct sock_filter));
+    for (int i = 0; i < fcode.bf_len; ++insn, ++i) {
         g_filters[i].code = insn->code;
         g_filters[i].jt   = insn->jt;
         g_filters[i].jf   = insn->jf;
@@ -723,11 +662,28 @@ void init_filter() {
 #endif
 }
 
+void init_raw_socket_poll(void *pRecv, void *pClean) {
+    static RECV_CB_DATA rcData;
+    static uv_poll_t    uvSocket;
+    static uv_timer_t   uvTm;
+
+    uv_udp_init(get_task_manager(), &g_uvRawSockReq);
+    uv_udp_open(&g_uvRawSockReq, g_pkgRing.sock);
+
+    uv_poll_init_socket(get_task_manager(), &uvSocket, g_pkgRing.sock);
+    rcData.work_cb       = pRecv;
+    rcData.after_work_cb = pClean;
+    uvSocket.data        = &rcData;
+
+    uv_poll_start(&uvSocket, UV_READABLE, raw_sock_recv_cb);
+
+    uv_timer_init(get_task_manager(), &uvTm);
+    uv_timer_start(&uvTm, socket_send_task, 3000, 100);
+}
+
 int dhcpd_init() {
-    static uv_poll_t  uvSocket;
-    static uv_timer_t uvTm;
-    int               ret;
-    size_t            size = MAX_PATH;
+    int    ret;
+    size_t size = MAX_PATH;
 
     memset(&g_nicInfo, 0, sizeof(NIC_INFO));
     g_nicInfo.pIfName = (char *)config_get_dhcp_nic_name();
@@ -735,11 +691,11 @@ int dhcpd_init() {
 
     get_nic_info(g_nicInfo.pIfName, &g_nicInfo.ipAddr, &g_nicInfo.netmask, NULL, g_nicInfo.macAddr);
 
-    init_filter();
+    init_filter("vlan and udp and port 67 and port 68");
 
-    ret = create_udp_socket();
+    ret = create_udp_raw_socket(g_nicInfo.pIfName);
     if (ret != ERR_SUCCESS) {
-        LOG_MOD(error, ZLOG_MOD_DHCPD, "Create receive RAW Socket Error\n");
+        LOG_MOD(error, ZLOG_MOD_DHCPD, "Create receive RAW Socket Error: %s(%d)\n", getErrorEnumNameString(-ret), ret);
         return ret;
     }
 
@@ -747,14 +703,25 @@ int dhcpd_init() {
     dhcp_option_cfg_init();
     dhcp_lease_init();
 
-    uv_udp_init(get_task_manager(), &g_uvRawSockReq);
-    uv_udp_open(&g_uvRawSockReq, g_pkgRing.sock);
+    init_raw_socket_poll(NULL, NULL);
 
-    uv_poll_init_socket(get_task_manager(), &uvSocket, g_pkgRing.sock);
-    uv_poll_start(&uvSocket, UV_READABLE, raw_sock_recv_cb);
+    return ERR_SUCCESS;
+}
 
-    uv_timer_init(get_task_manager(), &uvTm);
-    uv_timer_start(&uvTm, socket_send_task, 3000, 100);
+int dhcp_uninit() {
+    unsigned int size = g_pkgRing.recv.tp_block_size * g_pkgRing.recv.tp_block_nr +
+        g_pkgRing.send.tp_block_size * g_pkgRing.send.tp_block_nr;
+    close(g_pkgRing.sock);
+    g_pkgRing.sock = -1;
+    if (g_pkgRing.tx) {
+        free(g_pkgRing.tx);
+    }
+
+    if (g_pkgRing.rx) {
+        free(g_pkgRing.rx);
+    }
+
+    munmap(g_pkgRing.map_recv, size);
 
     return ERR_SUCCESS;
 }
\ No newline at end of file
diff --git a/srcs/service/dhcpd/include/dhcp_network.h b/srcs/service/dhcpd/include/dhcp_network.h
new file mode 100644
index 0000000..544ec4d
--- /dev/null
+++ b/srcs/service/dhcpd/include/dhcp_network.h
@@ -0,0 +1,84 @@
+//
+// Created by xajhuang on 2023/4/20.
+//
+
+#ifndef VCPE_DHCP_NETWORK_H
+#define VCPE_DHCP_NETWORK_H
+#include <uv.h>
+#include <linux/if_packet.h>
+#include "network/vlan.h"
+#include "service/dhcpd.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define MAC_TO_STR(mac, str) \
+    sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])
+
+#define PKG_MMAP_BLOCKSIZ (1 << 22)
+#define PKG_MMAP_FRAMESIZ (1 << 11)
+#define PKG_MMAP_BLOCKNUM (64)
+
+typedef struct {
+    int                 sock;
+    struct sockaddr_ll  addr;
+    struct iovec       *rx;
+    struct iovec       *tx;
+    uint8_t            *map_recv;
+    uint8_t            *map_send;
+    struct tpacket_req3 recv;
+    struct tpacket_req3 send;
+    unsigned int        index;
+} PACKET_MMAP_RING, *PPACKET_MMAP_RING;
+
+typedef struct {
+    char *pIfName;
+    U32   ipAddr;
+    U32   netmask;
+    U8    macAddr[ETH_ALEN];
+    S8    hostname[MAX_PATH];
+} NIC_INFO, *PNIC_INFO;
+
+struct block_desc {
+    uint32_t              version;
+    uint32_t              offset_to_priv;
+    struct tpacket_hdr_v1 h1;
+};
+
+typedef struct {
+    uv_work_cb       work_cb;
+    uv_after_work_cb after_work_cb;
+} RECV_CB_DATA, *PRECV_CB_DATA;
+
+#pragma pack(1)
+
+typedef struct {
+    VLAN_PKG_HDR vlan_hdr;
+    DHCP_PROTO   dhcp;
+} DHCP_PACKAGE, *PDHCP_PACKAGE;
+
+typedef struct {
+    uv_work_t      uvWork;
+    unsigned short nSize;
+    unsigned char *pPkgBase;
+    void          *pData;
+} PKG_PROCESS_INFO, *PPKG_PROCESS_INFO;
+
+typedef struct {
+    unsigned int      nf;
+    PPKG_PROCESS_INFO pPkgInfo;
+} PKG_MSG, *PPKG_MSG;
+
+#pragma pack()
+
+void  raw_sock_recv_cb(uv_poll_t *handle, int status, int events);
+void  socket_send_task(uv_timer_t *UNUSED(pArg));
+void  init_raw_socket_poll(void *pRecv, void *pClean);
+int   create_udp_raw_socket(const char *pNicName);
+void  init_filter(const char *pNetFilter);
+void *get_pkg_free_buf();
+U32   pkg_mmap_tx(U8 *pData, U32 nBytes);
+int   dhcp_uninit();
+#ifdef __cplusplus
+}
+#endif
+#endif    //VCPE_DHCP_NETWORK_H
diff --git a/srcs/service/dhcpd/include/dhcp_options.h b/srcs/service/dhcpd/include/dhcp_options.h
index d5457ce..9efb73b 100644
--- a/srcs/service/dhcpd/include/dhcp_options.h
+++ b/srcs/service/dhcpd/include/dhcp_options.h
@@ -4,6 +4,7 @@
 
 #ifndef VCPE_DHCP_OPTIONS_H
 #define VCPE_DHCP_OPTIONS_H
+#include "common.h"
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/srcs/service/dhcpd/include/rfc2131.h b/srcs/service/dhcpd/include/rfc2131.h
new file mode 100644
index 0000000..99cf2e6
--- /dev/null
+++ b/srcs/service/dhcpd/include/rfc2131.h
@@ -0,0 +1,35 @@
+//
+// Created by xajhuang on 2023/4/20.
+//
+
+#ifndef VCPE_RFC2131_H
+#define VCPE_RFC2131_H
+#include <linux/if_ether.h>
+#include "common.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DHCP_COOKIE_VAL   (0x63825363)
+#define MAX_DHCP_PKG_SIZE (512)
+#define VLAN_VNI_ID(x)    ntohs((x))
+#define DHCP_XID(x)       ntohl((x))
+
+#define DHCP_CLI_PORT     (68)
+#define DHCP_SVR_PORT     (67)
+
+typedef struct {
+    U8   unicast;
+    U8   cliMac[ETH_ALEN];
+    U32  xid;
+    U32  reqIpAddr;
+    U32  leaseTime;
+    char clientId[256];
+    char vendorClassId[256];
+    char hostName[256];
+} DHCP_REQ, *PDHCP_REQ;
+
+#ifdef __cplusplus
+}
+#endif
+#endif    //VCPE_RFC2131_H