diff --git a/srcs/include/pppoe_info.h b/srcs/include/pppoe_info.h
new file mode 100644
index 0000000..19963b6
--- /dev/null
+++ b/srcs/include/pppoe_info.h
@@ -0,0 +1,72 @@
+//
+// Created by xajhuang on 2022/5/31.
+//
+
+#ifndef VCPE_PROJECT_PPPOE_INFO_H
+#define VCPE_PROJECT_PPPOE_INFO_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <uthash/uthash.h>
+#include "netif/ppp/ppp.h"
+
+#define PPPOE_MAX_TIMEOUT   (30)
+
+typedef enum {
+    STATUS_TASK_INIT,
+    STATUS_TASK_DIAL,
+    STATUS_TASK_CONNECTED,
+    STATUS_TASK_ERROR,
+    STATUS_TASK_DISCONNECTED,
+    STATUS_TASK_DELETE,
+    STATUS_PPPOE_UPDATE,
+} PPPOE_TASK;
+
+typedef enum {
+    STATUS_USER_NEW,
+    STATUS_USER_DELETE,
+    STATUS_USER_MODIFY,
+    STATUS_USER_NORMAL,
+} USER_STATUS;
+
+typedef struct {
+    unsigned int  timeout;
+    unsigned int  count;
+} RETRY_WORK;
+
+typedef struct {
+    unsigned int  userid;
+    struct netif *nicif;
+    struct netif *pppif;
+    ppp_pcb      *ppp;
+
+    RETRY_WORK   retry;
+
+    PPPOE_TASK   status;
+} PPPOE_SESSION, *PPPPOE_SESSION;
+
+typedef struct {
+    unsigned short qinq_tag1;
+    unsigned short qinq_tag2;
+    unsigned char  mac_addr[6];
+    const char    *pppoe_user;
+    const char    *pppoe_passwd;
+    USER_STATUS    user_status;
+} USER_INFO, *PUSER_INFO;
+
+typedef struct {
+    unsigned int  userid;
+    USER_INFO     user_info;
+    PPPOE_SESSION session;
+
+    UT_hash_handle hh;
+} USER_INFO_CONTEXT, *PUSER_INFO_CONTEXT;
+
+int           pppoe_session_create(PUSER_INFO_CONTEXT pUser);
+int           pppoe_session_init();
+struct netif *get_rawsocket_if(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif//VCPE_PROJECT_PPPOE_INFO_H
diff --git a/srcs/include/pppoe_session.h b/srcs/include/pppoe_session.h
index 3c3390b..11e9ff6 100644
--- a/srcs/include/pppoe_session.h
+++ b/srcs/include/pppoe_session.h
@@ -13,17 +13,9 @@ extern "C" {
 
 #include "user_info.h"
 
-typedef struct {
-    unsigned int  userid;
-    struct netif *nicif;
-    struct netif *pppif;
-    USER_INFO     user_info;
 
-    UT_hash_handle hh;
-} PPPOE_SESSION, *PPPPOE_SESSION;
 
-int pppoe_session_init();
-struct netif* get_rawsocket_if(void);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/srcs/include/user_info.h b/srcs/include/user_info.h
index 48a29ba..e16b51c 100644
--- a/srcs/include/user_info.h
+++ b/srcs/include/user_info.h
@@ -7,29 +7,17 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
+#include <uv.h>
+#include "pppoe_info.h"
 
-#include <uthash/uthash.h>
-
-typedef struct {
-    unsigned short qinq_tag1;
-    unsigned short qinq_tag2;
-    unsigned char  mac_addr[6];
-    const char    *pppoe_user;
-    const char    *pppoe_passwd;
-} USER_INFO, *PUSER_INFO;
-
-typedef struct {
-    unsigned int userid;
-    USER_INFO    user_info;
-
-    UT_hash_handle hh;
-} USER_INFO_LIST, *PUSER_INFO_LIST;
-
-void            user_info_init();
-int             user_info_add(unsigned int userid, PUSER_INFO pInfo);
-void            user_info_remove(unsigned int userid);
-PUSER_INFO      user_info_get_by_userid(unsigned int userid);
-PUSER_INFO_LIST user_info_getall();
+void               user_info_init();
+int                user_info_add(unsigned int userid, PUSER_INFO pInfo);
+void               user_info_remove(unsigned int userid);
+void               user_info_delete(unsigned int userid);
+PUSER_INFO         user_info_get_by_userid(unsigned int userid);
+void               user_info_change_status(PUSER_INFO pInfo, USER_STATUS status);
+PUSER_INFO_CONTEXT get_all_user();
+uv_rwlock_t*       get_user_lock();
 #ifdef __cplusplus
 }
 #endif
diff --git a/srcs/libs/config/agent.cfg b/srcs/libs/config/agent.cfg
index 84f1438..9bdc289 100644
--- a/srcs/libs/config/agent.cfg
+++ b/srcs/libs/config/agent.cfg
@@ -46,4 +46,12 @@ application:
     {
         svr_port = 6278;                    # ZeroMQ 服务器端口
     };
+
+    # 网络相关
+    network:
+    {
+        nic_card = "ens160"                 # 收发数据使用的网卡名称
+        nic_mac = "00:0C:01:02:00:01"       # 收发数据使用的网卡Mac地址
+        vxlan_support = true;               # 是否支持vxLan封装
+    }
 }
\ No newline at end of file
diff --git a/srcs/libs/configure/config.c b/srcs/libs/configure/config.c
index c4feb34..2dfaf40 100644
--- a/srcs/libs/configure/config.c
+++ b/srcs/libs/configure/config.c
@@ -79,7 +79,8 @@ static const char *load_string_value(const char *pKeyName) {
                 return NULL;
             }
 
-            if (symmetric_decrypto(AES128_ECB_PKCS7PADDING_SHA1PRNG, pBuf, bufSize, &buf, &outSize, pKey) != ERR_SUCCESS) {
+            if (symmetric_decrypto(AES128_ECB_PKCS7PADDING_SHA1PRNG, pBuf, bufSize, &buf, &outSize, pKey)
+                != ERR_SUCCESS) {
                 free((void *)pKey);
                 free(pBuf);
                 return NULL;
@@ -479,6 +480,9 @@ do {
     /* 消息队列相配置 */                                                                                                                                        \
     /* ZeroMq配置 */                                                                                                                                           \
     ADD_CFG_ITEM(CFG_MQ_SVR_PORT, "application.zero_mq.svr_port", VALUE_TYPE_INTEGRAL, "6378", "ZeroMQ server port");                                          \
+    /* 网络相关配置 */                                                                                                                                            \
+    ADD_CFG_ITEM(CFG_NIC_CARD_NAME, "application.network.svr_port", VALUE_TYPE_STRING, "ens160", "Network card name to send data");                            \
+    ADD_CFG_ITEM(CFG_VXLAN_SUPPORT, "application.network.vxlan_support", VALUE_TYPE_BOOL, "1", "Is support vxLan tune");                                       \
 } while (0)// clang-format on
 
 int init_config_system(const char *pCfgFile, const char *pKey) {
diff --git a/srcs/libs/configure/config_help.c b/srcs/libs/configure/config_help.c
index cb75835..fa54ec5 100644
--- a/srcs/libs/configure/config_help.c
+++ b/srcs/libs/configure/config_help.c
@@ -3,6 +3,14 @@
 //
 #include "config.h"
 
+const char* config_get_nic_name() {
+    return cfg_get_string_value(CFG_NIC_CARD_NAME);
+}
+
+int cfg_get_support_vxlan() {
+    return cfg_get_bool_value(CFG_VXLAN_SUPPORT);
+}
+
 const char *config_get_ssl_ca_path() {
     return cfg_get_string_value(CFG_CURL_CA_PATH);
 }
diff --git a/srcs/libs/include/config.h b/srcs/libs/include/config.h
index 5172416..e2eacdb 100644
--- a/srcs/libs/include/config.h
+++ b/srcs/libs/include/config.h
@@ -41,6 +41,8 @@ typedef enum {
     CFG_DB_MYSQL_PASSWD  = 19,
     CFG_DB_MYSQL_DB_NAME = 20,
     CFG_MQ_SVR_PORT      = 21,
+    CFG_NIC_CARD_NAME    = 22,
+    CFG_VXLAN_SUPPORT    = 23,
 
     CONFIG_ITEM_ID_MAX
 } CONFIG_ITEM_ID;
@@ -79,7 +81,8 @@ void        config_item_dump(const char *titleMessage);
 const char *config_item_dump_fmt(const char *titleMessage);
 const char *get_config_key(const char *pKeygen);
 const char *get_config_keygen();
-
+int         cfg_get_support_vxlan();
+const char *config_get_nic_name();
 #ifdef __cplusplus
 }
 #endif
diff --git a/srcs/lwip/src/arch_linux/include/lwipopts.h b/srcs/lwip/src/arch_linux/include/lwipopts.h
index c681f5a..79218c1 100644
--- a/srcs/lwip/src/arch_linux/include/lwipopts.h
+++ b/srcs/lwip/src/arch_linux/include/lwipopts.h
@@ -462,52 +462,50 @@ void sys_unlock_tcpip_core(void);
 #endif
 #endif
 
-#define MEMP_OVERFLOW_CHECK             1
-
 #define PPP_USE_PBUF_RAM                1
 
-#define LWIP_DEBUG                      1
+//#define LWIP_DEBUG                      1
 
-#define LWIP_DBG_MIN_LEVEL              LWIP_DBG_LEVEL_OFF
+//#define LWIP_DBG_MIN_LEVEL              LWIP_DBG_LEVEL_OFF
 //#define LWIP_DBG_MIN_LEVEL              LWIP_DBG_LEVEL_WARNING
 //#define LWIP_DBG_MIN_LEVEL              LWIP_DBG_LEVEL_SERIOUS
 //#define LWIP_DBG_MIN_LEVEL              LWIP_DBG_LEVEL_SEVERE
 
 //#define LWIP_DBG_TYPES_ON               LWIP_DBG_ON
-#define LWIP_DBG_TYPES_ON               (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH)
+//#define LWIP_DBG_TYPES_ON               (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH)
 
-//#define ETHARP_DEBUG                    LWIP_DBG_ON
-//#define NETIF_DEBUG                     LWIP_DBG_ON
-//#define PBUF_DEBUG                      LWIP_DBG_ON
-//#define API_LIB_DEBUG                   LWIP_DBG_ON
-//#define API_MSG_DEBUG                   LWIP_DBG_ON
-//#define SOCKETS_DEBUG                   LWIP_DBG_ON
-//#define ICMP_DEBUG                      LWIP_DBG_ON
-//#define IGMP_DEBUG                      LWIP_DBG_ON
-//#define INET_DEBUG                      LWIP_DBG_ON
-//#define IP_DEBUG                        LWIP_DBG_ON
-//#define IP_REASS_DEBUG                  LWIP_DBG_ON
-//#define RAW_DEBUG                       LWIP_DBG_ON
-//#define MEM_DEBUG                       LWIP_DBG_ON
-//#define MEMP_DEBUG                      LWIP_DBG_ON
-//#define SYS_DEBUG                       LWIP_DBG_ON
-//#define TCP_DEBUG                       LWIP_DBG_ON
-//#define TCP_INPUT_DEBUG                 LWIP_DBG_ON
-//#define TCP_FR_DEBUG                    LWIP_DBG_ON
-//#define TCP_RTO_DEBUG                   LWIP_DBG_ON
-//#define TCP_CWND_DEBUG                  LWIP_DBG_ON
-//#define TCP_WND_DEBUG                   LWIP_DBG_ON
-//#define TCP_OUTPUT_DEBUG                LWIP_DBG_ON
-//#define TCP_RST_DEBUG                   LWIP_DBG_ON
-//#define TCP_QLEN_DEBUG                  LWIP_DBG_ON
-//#define UDP_DEBUG                       LWIP_DBG_ON
-//#define TCPIP_DEBUG                     LWIP_DBG_ON
-//#define PPP_DEBUG                       LWIP_DBG_ON
-//#define SLIP_DEBUG                      LWIP_DBG_ON
-//#define DHCP_DEBUG                      LWIP_DBG_ON
-//#define AUTOIP_DEBUG                    LWIP_DBG_ON
-//#define SNMP_MSG_DEBUG                  LWIP_DBG_ON
-//#define SNMP_MIB_DEBUG                  LWIP_DBG_ON
-//#define DNS_DEBUG                       LWIP_DBG_ON
+#define ETHARP_DEBUG                    LWIP_DBG_OFF
+#define NETIF_DEBUG                     LWIP_DBG_OFF
+#define PBUF_DEBUG                      LWIP_DBG_OFF
+#define API_LIB_DEBUG                   LWIP_DBG_OFF
+#define API_MSG_DEBUG                   LWIP_DBG_OFF
+#define SOCKETS_DEBUG                   LWIP_DBG_OFF
+#define ICMP_DEBUG                      LWIP_DBG_OFF
+#define IGMP_DEBUG                      LWIP_DBG_OFF
+#define INET_DEBUG                      LWIP_DBG_OFF
+#define IP_DEBUG                        LWIP_DBG_OFF
+#define IP_REASS_DEBUG                  LWIP_DBG_OFF
+#define RAW_DEBUG                       LWIP_DBG_OFF
+#define MEM_DEBUG                       LWIP_DBG_OFF
+#define MEMP_DEBUG                      LWIP_DBG_OFF
+#define SYS_DEBUG                       LWIP_DBG_OFF
+#define TCP_DEBUG                       LWIP_DBG_OFF
+#define TCP_INPUT_DEBUG                 LWIP_DBG_OFF
+#define TCP_FR_DEBUG                    LWIP_DBG_OFF
+#define TCP_RTO_DEBUG                   LWIP_DBG_OFF
+#define TCP_CWND_DEBUG                  LWIP_DBG_OFF
+#define TCP_WND_DEBUG                   LWIP_DBG_OFF
+#define TCP_OUTPUT_DEBUG                LWIP_DBG_OFF
+#define TCP_RST_DEBUG                   LWIP_DBG_OFF
+#define TCP_QLEN_DEBUG                  LWIP_DBG_OFF
+#define UDP_DEBUG                       LWIP_DBG_OFF
+#define TCPIP_DEBUG                     LWIP_DBG_OFF
+#define PPP_DEBUG                       LWIP_DBG_OFF
+#define SLIP_DEBUG                      LWIP_DBG_OFF
+#define DHCP_DEBUG                      LWIP_DBG_OFF
+#define AUTOIP_DEBUG                    LWIP_DBG_OFF
+#define SNMP_MSG_DEBUG                  LWIP_DBG_OFF
+#define SNMP_MIB_DEBUG                  LWIP_DBG_OFF
+#define DNS_DEBUG                       LWIP_DBG_OFF
 
 #endif /* LWIP_LWIPOPTS_H */
diff --git a/srcs/lwip/src/arch_linux/include/netif/pppoeif.h b/srcs/lwip/src/arch_linux/include/netif/pppoeif.h
index 48f5b49..2f70f77 100644
--- a/srcs/lwip/src/arch_linux/include/netif/pppoeif.h
+++ b/srcs/lwip/src/arch_linux/include/netif/pppoeif.h
@@ -39,7 +39,7 @@
 extern "C" {
 #endif
 err_t         pppoeif_init(struct netif *netif);
-struct netif *create_pppoe_if(PPPPOE_SESSION pSession);
+struct netif *create_pppoe_if(PUSER_INFO_CONTEXT pUser);
 #ifdef __cplusplus
 }
 #endif
diff --git a/srcs/lwip/src/arch_linux/netif/pppoe_if.c b/srcs/lwip/src/arch_linux/netif/pppoe_if.c
index 6eb3403..9429525 100644
--- a/srcs/lwip/src/arch_linux/netif/pppoe_if.c
+++ b/srcs/lwip/src/arch_linux/netif/pppoe_if.c
@@ -95,17 +95,17 @@ int pppoeif_select(struct netif *netif) {
 
 /*-----------------------------------------------------------------------------------*/
 static void low_level_init(struct netif *netif) {
-    PPPPOE_SESSION pSession = (PPPPOE_SESSION)netif->state;
+    PUSER_INFO_CONTEXT pUser = (PUSER_INFO_CONTEXT)netif->state;
 
-    LWIP_DEBUGF(PPPOEIF_DEBUG, ("<%p>pppoeif_init\n", (void *)pSession));
+    LWIP_DEBUGF(PPPOEIF_DEBUG, ("<%p>pppoeif_init\n", (void *)pUser));
 
     /* Obtain MAC address from network interface. */
-    netif->hwaddr[0]  = pSession->user_info.mac_addr[0];
-    netif->hwaddr[1]  = pSession->user_info.mac_addr[1];
-    netif->hwaddr[2]  = pSession->user_info.mac_addr[2];
-    netif->hwaddr[3]  = pSession->user_info.mac_addr[3];
-    netif->hwaddr[4]  = pSession->user_info.mac_addr[4];
-    netif->hwaddr[5]  = pSession->user_info.mac_addr[5];
+    netif->hwaddr[0]  = pUser->user_info.mac_addr[0];
+    netif->hwaddr[1]  = pUser->user_info.mac_addr[1];
+    netif->hwaddr[2]  = pUser->user_info.mac_addr[2];
+    netif->hwaddr[3]  = pUser->user_info.mac_addr[3];
+    netif->hwaddr[4]  = pUser->user_info.mac_addr[4];
+    netif->hwaddr[5]  = pUser->user_info.mac_addr[5];
     netif->hwaddr_len = 6;
 
     /* device capabilities */
@@ -182,7 +182,7 @@ static void link_callback(struct netif *state_netif) {
 }
 #endif /* LWIP_NETIF_LINK_CALLBACK */
 
-struct netif *create_pppoe_if(PPPPOE_SESSION pSession) {
+struct netif *create_pppoe_if(PUSER_INFO_CONTEXT pUser) {
     struct netif *netif;
     ip4_addr_t    ipaddr, netmask, gw;
 
@@ -211,7 +211,7 @@ struct netif *create_pppoe_if(PPPPOE_SESSION pSession) {
         return NULL;
     }
 
-    netif_add(netif, &ipaddr, &netmask, &gw, pSession, pppoeif_init, tcpip_input);
+    netif_add(netif, &ipaddr, &netmask, &gw, pUser, pppoeif_init, tcpip_input);
 
 #if LWIP_NETIF_STATUS_CALLBACK
     netif_set_status_callback(netif, status_callback);
diff --git a/srcs/lwip/src/arch_linux/netif/rawif.c b/srcs/lwip/src/arch_linux/netif/rawif.c
index beb835a..0d67a29 100644
--- a/srcs/lwip/src/arch_linux/netif/rawif.c
+++ b/srcs/lwip/src/arch_linux/netif/rawif.c
@@ -54,7 +54,7 @@
 #include "netif/etharp.h"
 
 #include "netif/rawif.h"
-
+#include "config.h"
 
 #if defined(LWIP_UNIX_LINUX)
 #include <linux/if.h>
@@ -80,17 +80,23 @@ struct sockaddr_ll {
     unsigned char      sll_addr[8];
 };
 
+typedef struct {
+    unsigned char *output_head;
+    unsigned char *input_head;
+} VXLAN_BUF, *PVXLAN_BUF;
+
 struct rawif {
     /* Add whatever per-interface state that is needed here. */
     int           fd;
     int           if_index;
     const char   *eth_name;
+    int           vxlan_support;
     unsigned char mac_addr[6];
+
+    VXLAN_BUF vxlan_buf;
 };
 
-static unsigned char g_macAddr[6];
-static char         *g_ethName;
-static unsigned int  g_localIpAddrBegin = DEFAULT_GW_IPADDR + 1;
+static unsigned int g_localIpAddrBegin = DEFAULT_GW_IPADDR + 1;
 
 /* Forward declarations. */
 static void rawif_input(struct netif *netif);
@@ -106,6 +112,8 @@ static void low_level_init(struct netif *netif) {
 
     rawif = (struct rawif *)netif->state;
 
+    dzlog_debug("++++++++++++rawif<%p>\n", (void *)rawif);
+
     rawif->fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
 
     LWIP_DEBUGF(RAWIF_DEBUG, ("rawif_init: fd %d\n", rawif->fd));
@@ -165,13 +173,7 @@ static void low_level_init(struct netif *netif) {
 #endif
 
     /* Obtain MAC address from network interface. */
-
-    netif->hwaddr[0]  = 0x00;
-    netif->hwaddr[1]  = 0x0C;
-    netif->hwaddr[2]  = 0x01;
-    netif->hwaddr[3]  = 0x02;
-    netif->hwaddr[4]  = 0x00;
-    netif->hwaddr[5]  = 0x01;
+    memcpy(netif->hwaddr, rawif->mac_addr, 6);
     netif->hwaddr_len = 6;
 
     /* device capabilities */
@@ -260,34 +262,30 @@ static struct pbuf *low_level_input(struct netif *netif) {
     }
     len = (u16_t)readlen;
 
-    //{0x00, 0x0C, 0x01, 0x02, 0x00, 0x01}
+    if ((buf[0] == 0x00 && buf[1] == 0x0C && buf[2] == 0x01 && buf[3] == 0x02)
+        || memcmp(buf, bmac, 6) == 0) {
+        MIB2_STATS_NETIF_ADD(netif, ifinoctets, len);
 
-    if((buf[0] != 0x00 && buf[1] != 0x0C && buf[2] != 0x01 && buf[3] != 0x02) &&
-        memcmp(buf, bmac, 6) != 0) {
+        /* We allocate a pbuf chain of pbufs from the pool. */
+        p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM);
+        if (p != NULL) {
+            pbuf_take(p, buf, len);
+            /* acknowledge that packet has been read(); */
+        } else {
+            /* drop packet(); */
+            MIB2_STATS_NETIF_INC(netif, ifindiscards);
+            LWIP_DEBUGF(NETIF_DEBUG, ("rawif_input: could not allocate pbuf\n"));
+        }
+        return p;
+    } else {
         return NULL;
     }
-
-    MIB2_STATS_NETIF_ADD(netif, ifinoctets, len);
-
-    /* We allocate a pbuf chain of pbufs from the pool. */
-    p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM);
-    if (p != NULL) {
-        pbuf_take(p, buf, len);
-        /* acknowledge that packet has been read(); */
-    } else {
-        /* drop packet(); */
-        MIB2_STATS_NETIF_INC(netif, ifindiscards);
-        LWIP_DEBUGF(NETIF_DEBUG, ("rawif_input: could not allocate pbuf\n"));
-    }
-
-    return p;
 }
 
 err_t rawif_output(struct netif *netif, struct pbuf *p) {
     return low_level_output(netif, p);
 }
 
-
 /*-----------------------------------------------------------------------------------*/
 /*
  * rawif_input():
@@ -326,14 +324,15 @@ static void rawif_input(struct netif *netif) {
  */
 /*-----------------------------------------------------------------------------------*/
 err_t rawif_init(struct netif *netif) {
-    struct ifreq        ifr;
-    struct rawif       *rawif  = (struct rawif *)mem_malloc(sizeof(struct rawif));
+    struct rawif *rawif = (struct rawif *)netif->state;
+
+    dzlog_debug("++++++++++++rawif<%p>\n", (void *)rawif);
 
     if (rawif == NULL) {
         LWIP_DEBUGF(NETIF_DEBUG, ("rawif_init: out of memory for rawif\n"));
         return ERR_MEM;
     }
-    netif->state = rawif;
+
     MIB2_INIT_NETIF(netif, snmp_ifType_other, 100000000);
 
     netif->name[0] = 'r';
@@ -347,12 +346,6 @@ err_t rawif_init(struct netif *netif) {
     netif->linkoutput = low_level_output;
     netif->mtu        = 1500;
 
-    rawif->eth_name = g_ethName;
-    memcpy(rawif->mac_addr, g_macAddr, 6);
-
-    memset(&ifr, 0, sizeof(ifr));
-    strcpy(ifr.ifr_name, rawif->eth_name);
-
     low_level_init(netif);
 
     return ERR_OK;
@@ -363,37 +356,11 @@ void rawif_poll(struct netif *netif) {
     rawif_input(netif);
 }
 
-#if NO_SYS
-
-int rawif_select(struct netif *netif) {
-    fd_set         fdset;
-    int            ret;
-    struct timeval tv;
-    struct rawif  *rawif;
-    u32_t          msecs = sys_timeouts_sleeptime();
-
-    rawif = (struct rawif *)netif->state;
-
-    tv.tv_sec  = msecs / 1000;
-    tv.tv_usec = (msecs % 1000) * 1000;
-
-    FD_ZERO(&fdset);
-    FD_SET(rawif->fd, &fdset);
-
-    ret = select(rawif->fd + 1, &fdset, NULL, NULL, &tv);
-    if (ret > 0) {
-        rawif_input(netif);
-    }
-    return ret;
-}
-
-#else  /* NO_SYS */
-
 _Noreturn static void rawif_thread(void *arg) {
     struct netif *netif;
     struct rawif *rawif;
-    fd_set fdset;
-    int ret;
+    fd_set        fdset;
+    int           ret;
 
     netif = (struct netif *)arg;
     rawif = (struct rawif *)netif->state;
@@ -413,7 +380,6 @@ _Noreturn static void rawif_thread(void *arg) {
         }
     }
 }
-#endif /* NO_SYS */
 
 #if LWIP_NETIF_STATUS_CALLBACK
 static void status_callback(struct netif *state_netif) {
@@ -444,13 +410,18 @@ static err_t netif_input_data(struct pbuf *p, struct netif *inp) {
 
     LWIP_ASSERT_CORE_LOCKED();
     NETIF_FOREACH(netif) {
-        err_t err;
-        unsigned char* pMac = (unsigned char*)p->payload;
+        err_t          err;
+        unsigned char *pMac = (unsigned char *)p->payload;
 
-        if(memcmp(pMac, netif->hwaddr, netif->hwaddr_len) == 0) {
-//            printf("++++++receive %02X:%02X:%02X:%02X:%02X:%02X\n",
-//                   pMac[0], pMac[1], pMac[2], pMac[3], pMac[4], pMac[5]);
+        if (netif->hwaddr_len == 6 && memcmp(pMac, netif->hwaddr, netif->hwaddr_len) == 0) {
+#if 0
+            printf("++++++receive %02X:%02X:%02X:%02X:%02X:%02X\n",
+                   pMac[0], pMac[1], pMac[2], pMac[3], pMac[4], pMac[5]);
 
+            printf("---- Call netif(%c%c:%d) <%p>, input = <%p>, %02X:%02X\n",
+                   netif->name[0], netif->name[1], netif->num,
+                   (void*)netif, (void*)netif->input, netif->hwaddr[4], netif->hwaddr[5]);
+#endif
             if ((err = netif->input(p, netif)) != ERR_OK) {
                 LWIP_DEBUGF(NETIF_DEBUG, ("pppoeif_input: netif input error\n"));
                 pbuf_free(p);
@@ -465,10 +436,19 @@ static err_t netif_input_data(struct pbuf *p, struct netif *inp) {
 
 struct netif *bind_rawsocket_if(const char *eth_name) {
     struct netif *netif;
+    struct ifreq  ifr;
     ip4_addr_t    ipaddr, netmask, gw;
+    struct rawif *rawif = (struct rawif *)mem_malloc(sizeof(struct rawif));
 
-    if (eth_name) {
-        g_ethName = strdup(eth_name);
+    if (rawif == NULL) {
+        dzlog_error("bind_rawsocket_if: out of memory for rawif\n");
+        return NULL;
+    }
+
+    memset(rawif, 0, sizeof(struct rawif));
+
+    if (eth_name && strlen(eth_name) > 0) {
+        rawif->eth_name = eth_name;
     }
 
     ip4_addr_set_zero(&gw);
@@ -489,14 +469,26 @@ struct netif *bind_rawsocket_if(const char *eth_name) {
              (g_localIpAddrBegin & 0xFF));
     g_localIpAddrBegin++;
 
+    rawif->vxlan_support = cfg_get_support_vxlan();
+    rawif->mac_addr[0]   = 0x00;
+    rawif->mac_addr[1]   = 0x0C;
+    rawif->mac_addr[2]   = 0x01;
+    rawif->mac_addr[3]   = 0x02;
+    rawif->mac_addr[4]   = 0x00;
+    rawif->mac_addr[5]   = 0x01;
+    memset(&ifr, 0, sizeof(ifr));
+    strcpy(ifr.ifr_name, rawif->eth_name);
+
     netif = (struct netif *)mem_malloc(sizeof(struct netif));
 
     if (!netif) {
+        mem_free(rawif);
         dzlog_error("Create netif error\n");
         return NULL;
     }
 
-    netif_add(netif, &ipaddr, &netmask, &gw, NULL, rawif_init, netif_input_data);
+    dzlog_debug("++++++++++++rawif<%p>\n", (void *)rawif);
+    netif_add(netif, &ipaddr, &netmask, &gw, rawif, rawif_init, netif_input_data);
 
 #if LWIP_NETIF_STATUS_CALLBACK
     netif_set_status_callback(netif, status_callback);
diff --git a/srcs/lwip/src/core/pbuf.c b/srcs/lwip/src/core/pbuf.c
index 5d6ca20..7638dfd 100644
--- a/srcs/lwip/src/core/pbuf.c
+++ b/srcs/lwip/src/core/pbuf.c
@@ -750,11 +750,7 @@ pbuf_free(struct pbuf *p)
      * further protection. */
     SYS_ARCH_PROTECT(old_level);
     /* all pbufs in a chain are referenced at least once */
-    //LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
-    if(p->ref == 0) {
-        return 1;
-    }
-
+    LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
     /* decrease reference count (number of pointers to pbuf) */
     ref = --(p->ref);
     SYS_ARCH_UNPROTECT(old_level);
diff --git a/srcs/pppoe/vcpe_pppoe.c b/srcs/pppoe/vcpe_pppoe.c
index 679a94d..346ae29 100644
--- a/srcs/pppoe/vcpe_pppoe.c
+++ b/srcs/pppoe/vcpe_pppoe.c
@@ -2,24 +2,49 @@
 // Created by xajhuang on 2022/5/10.
 //
 #include <zlog.h>
+#include <uv/unix.h>
+#include <uv.h>
 #include "pppoe_session.h"
 #include "netif/rawif.h"
 #include "netif/ppp/ppp.h"
 #include "netif/ppp/pppoe.h"
 #include "netif/pppoeif.h"
+#include "misc.h"
+#include "user_errno.h"
+#include "netif/ppp/pppapi.h"
+#include "config.h"
 
-static PPPPOE_SESSION g_pSessionList = NULL;
+struct PPPOE_ERR_INFO_ {
+    int         errid;
+    const char *errmsg;
+} g_pppoeErr[] = {
+    {PPPERR_NONE, "No error"},
+    {PPPERR_PARAM, "Invalid parameter"},
+    {PPPERR_OPEN, "Unable to open PPP session"},
+    {PPPERR_DEVICE, "Invalid I/O device for PPP"},
+    {PPPERR_ALLOC, "Unable to allocate resources"},
+    {PPPERR_USER, "User interrupt"},
+    {PPPERR_CONNECT, "Connection lost"},
+    {PPPERR_AUTHFAIL, "Failed authentication challenge"},
+    {PPPERR_PROTOCOL, "Failed to meet protocol"},
+    {PPPERR_PEERDEAD, "Connection timeout"},
+    {PPPERR_IDLETIMEOUT, "Idle Timeout"},
+    {PPPERR_CONNECTTIME, "Max connect time reach max time"},
+    {PPPERR_LOOPBACK, "Loopback detect"},
+};
+
+static struct netif *g_rawSocketIf = NULL;
 
 static void pppLinkStatusCallback(ppp_pcb *pcb, int errCode, void *ctx) {
     struct netif       *pppif = ppp_netif(pcb);
     struct pppoe_softc *sc    = (struct pppoe_softc *)pcb->link_ctx_cb;
-
-    LWIP_UNUSED_ARG(ctx);
+    PUSER_INFO_CONTEXT  pUser = (PUSER_INFO_CONTEXT)ctx;
 
     switch (errCode) {
         case PPPERR_NONE: { /* No error. */
-            dzlog_info("<%p> pppLinkStatusCallback: PPPERR_NONE(%08X), Session: %04X\n",
+            dzlog_info("<%p> PPPoE user(%05d:%s) connect server succeeded[%08X], Session: %04X\n",
                        pcb,
+                       pUser->userid, pUser->user_info.pppoe_user,
                        pcb->lcp_gotoptions.magicnumber,
                        sc->sc_session);
 #if LWIP_IPV4
@@ -34,56 +59,39 @@ static void pppLinkStatusCallback(ppp_pcb *pcb, int errCode, void *ctx) {
 #if PPP_IPV6_SUPPORT
             dzlog_info("   our6_ipaddr = %s\n", ip6addr_ntoa(netif_ip6_addr(pppif, 0)));
 #endif /* PPP_IPV6_SUPPORT */
+            pUser->session.status = STATUS_TASK_CONNECTED;
             break;
         }
-        case PPPERR_PARAM: { /* Invalid parameter. */
-            printf("<%p> pppLinkStatusCallback: PPPERR_PARAM\n", pcb);
+        case PPPERR_PARAM:
+        case PPPERR_AUTHFAIL:
+        case PPPERR_PROTOCOL:
+            dzlog_error("<%p> pppLinkStatusCallback: %s(%d)",
+                        pcb,
+                        g_pppoeErr[errCode].errmsg,
+                        g_pppoeErr[errCode].errid);
+            if (pUser->session.status != STATUS_TASK_DELETE) {
+                pUser->session.status = STATUS_TASK_ERROR;
+            }
             break;
-        }
-        case PPPERR_OPEN: { /* Unable to open PPP session. */
-            printf("<%p> pppLinkStatusCallback: PPPERR_OPEN\n", pcb);
+        case PPPERR_USER:
+            dzlog_info("User(%05d:%s) disconnect\n", pUser->userid, pUser->user_info.pppoe_user);
             break;
-        }
-        case PPPERR_DEVICE: { /* Invalid I/O device for PPP. */
-            printf("<%p> pppLinkStatusCallback: PPPERR_DEVICE\n", pcb);
+        case PPPERR_OPEN:
+        case PPPERR_DEVICE:
+        case PPPERR_ALLOC:
+        case PPPERR_CONNECT:
+        case PPPERR_PEERDEAD:
+        case PPPERR_IDLETIMEOUT:
+        case PPPERR_CONNECTTIME:
+        case PPPERR_LOOPBACK:
+            dzlog_error("<%p> pppLinkStatusCallback: %s(%d)\n",
+                        pcb,
+                        g_pppoeErr[errCode].errmsg,
+                        g_pppoeErr[errCode].errid);
+            if (pUser->session.status != STATUS_TASK_DELETE) {
+                pUser->session.status = STATUS_TASK_DISCONNECTED;
+            }
             break;
-        }
-        case PPPERR_ALLOC: { /* Unable to allocate resources. */
-            printf("<%p> pppLinkStatusCallback: PPPERR_ALLOC\n", pcb);
-            break;
-        }
-        case PPPERR_USER: { /* User interrupt. */
-            printf("<%p> pppLinkStatusCallback: PPPERR_USER\n", pcb);
-            break;
-        }
-        case PPPERR_CONNECT: { /* Connection lost. */
-            printf("<%p> pppLinkStatusCallback: PPPERR_CONNECT\n", pcb);
-            break;
-        }
-        case PPPERR_AUTHFAIL: { /* Failed authentication challenge. */
-            printf("<%p> pppLinkStatusCallback: PPPERR_AUTHFAIL\n", pcb);
-            break;
-        }
-        case PPPERR_PROTOCOL: { /* Failed to meet protocol. */
-            printf("<%p> pppLinkStatusCallback: PPPERR_PROTOCOL\n", pcb);
-            break;
-        }
-        case PPPERR_PEERDEAD: { /* Connection timeout */
-            printf("<%p> pppLinkStatusCallback: PPPERR_PEERDEAD\n", pcb);
-            break;
-        }
-        case PPPERR_IDLETIMEOUT: { /* Idle Timeout */
-            printf("<%p> pppLinkStatusCallback: PPPERR_IDLETIMEOUT\n", pcb);
-            break;
-        }
-        case PPPERR_CONNECTTIME: { /* Max connect time reached */
-            printf("<%p> pppLinkStatusCallback: PPPERR_CONNECTTIME\n", pcb);
-            break;
-        }
-        case PPPERR_LOOPBACK: { /* Loopback detected */
-            printf("<%p> pppLinkStatusCallback: PPPERR_LOOPBACK\n", pcb);
-            break;
-        }
         default: {
             printf("<%p> pppLinkStatusCallback: unknown errCode %d\n", pcb, errCode);
             break;
@@ -91,78 +99,147 @@ static void pppLinkStatusCallback(ppp_pcb *pcb, int errCode, void *ctx) {
     }
 }
 
-static struct netif* g_rawSocketIf = NULL;
+_Noreturn void sessionCalcCb(void *UNUSED(pArg)) {
+    PUSER_INFO_CONTEXT pUserList = get_all_user();
 
-struct netif* get_rawsocket_if(void) {
-    return g_rawSocketIf;
+    do {
+        PUSER_INFO_CONTEXT pUser, pTmp;
+
+        uv_rwlock_rdlock(get_user_lock());
+        HASH_ITER(hh, pUserList, pUser, pTmp) {
+            PPPPOE_SESSION pSession = &pUser->session;
+
+            switch (pSession->status) {
+                case STATUS_TASK_INIT:
+                    if (pppoe_session_create(pUser) == ERR_SUCCESS) {
+                        dzlog_debug("User(%05d:%s) init pppoe session\n", pUser->userid, pUser->user_info.pppoe_user);
+                        pSession->status = STATUS_TASK_DIAL;
+                    }
+                    break;
+                case STATUS_TASK_DIAL:
+                    if (pUser->session.retry.timeout == 0) {
+                        dzlog_debug("User(%05d:%s) connect PPPoE server\n", pUser->userid, pUser->user_info.pppoe_user);
+                        pppapi_connect(pSession->ppp, 0);
+                        pUser->session.retry.timeout = time(NULL) + PPPOE_MAX_TIMEOUT;
+                    } else if (time(NULL) > pUser->session.retry.timeout) {
+                        pUser->session.retry.timeout = 0;
+                    }
+                    break;
+                case STATUS_TASK_ERROR:
+                    if (pUser->session.retry.timeout == 0) {
+                        dzlog_error("User(%05d:%s) PPPoE dial error Invalid parameter\n",
+                                    pUser->userid,
+                                    pUser->user_info.pppoe_user);
+                        // 10秒后尝试重新拨号
+                        pUser->session.retry.timeout = time(NULL) + (PPPOE_MAX_TIMEOUT / 2);
+                        pUser->session.retry.count   = 0;
+                    } else if (time(NULL) > pUser->session.retry.timeout) {
+                        dzlog_warn("User(%05d:%s) retry dial %u times\n",
+                                   pUser->userid,
+                                   pUser->user_info.pppoe_user,
+                                   pUser->session.retry.count);
+                        pUser->session.retry.timeout = 0;
+                        pUser->session.retry.count++;
+
+                        // 下次重新拨号
+                        pSession->status = STATUS_TASK_DIAL;
+                    }
+                    break;
+
+                case STATUS_TASK_DISCONNECTED:
+                    // 自动重新拨号
+                    pSession->status = STATUS_TASK_DIAL;
+                    break;
+
+                case STATUS_TASK_DELETE:
+                    if (pUser->session.retry.timeout == 0) {
+                        dzlog_debug("User(%05d:%s) PPPoE deleted\n", pUser->userid, pUser->user_info.pppoe_user);
+                        pUser->session.retry.timeout = time(NULL);
+                        pppapi_free(pUser->session.ppp);
+                    }
+                    break;
+#if 0
+                case STATUS_TASK_CONNECTED:
+                    if (pUser->session.retry.timeout == 0) {
+                        pUser->session.retry.timeout = time(NULL) + 30;
+                    } else if (time(NULL) > pUser->session.retry.timeout) {
+                        dzlog_debug("User(%05d:%s) PPPoE disconnected\n", pUser->userid, pUser->user_info.pppoe_user);
+                        pSession->status = STATUS_TASK_DELETE;
+                        pppapi_close(pUser->session.ppp, 0);
+                        pUser->session.retry.timeout = 0;
+                    }
+                    break;
+#endif
+                default:
+                    break;
+            }
+        }
+        uv_rwlock_rdunlock(get_user_lock());
+        uv_sleep(1000);
+    } while (TRUE);
 }
 
 int pppoe_session_init() {
-    PUSER_INFO_LIST pList, pTmp;
-    PUSER_INFO_LIST pUserList = user_info_getall();
+    static uv_thread_t uvThread;
 
-    g_rawSocketIf = bind_rawsocket_if("ens160");
+    g_rawSocketIf = bind_rawsocket_if(config_get_nic_name());
 
-    if(g_rawSocketIf) {
-        dzlog_info("Create Raw Socket netif: <%p>\n", (void*)g_rawSocketIf);
+    if (g_rawSocketIf) {
+        dzlog_info("Create Raw Socket netif: <%p>\n", (void *)g_rawSocketIf);
     }
 
-    HASH_ITER(hh, pUserList, pList, pTmp) {
-        PPPPOE_SESSION pSession = (PPPPOE_SESSION)malloc(sizeof(PPPOE_SESSION));
+    // 启动Session状态机线程
+    uv_thread_create(&uvThread, sessionCalcCb, NULL);
+    return ERR_SUCCESS;
+}
 
-        if (pSession) {
-            struct netif *ppp_netif;
-            memset(pSession, 0, sizeof(PPPOE_SESSION));
+int pppoe_session_create(PUSER_INFO_CONTEXT pUser) {
+    ppp_pcb      *ppp;
+    struct netif *netif;
+    struct netif *ppp_netif = (struct netif *)malloc(sizeof(struct netif));
 
-            ppp_netif = (struct netif *)malloc(sizeof(struct netif));
-
-            if (ppp_netif) {
-                struct netif *netif;
-
-                pSession->userid = pList->userid;
-                memcpy(&pSession->user_info, &pList->user_info, sizeof(USER_INFO));
-
-                netif = create_pppoe_if(pSession);
-
-                if (netif == NULL) {
-                    free(pSession);
-                    free(ppp_netif);
-                    dzlog_error("Create PPPoE netif error: %u\n", pList->userid);
-                } else {
-                    ppp_pcb *ppp;
-
-                    pSession->nicif  = netif;
-                    pSession->pppif  = ppp_netif;
-
-                    ppp = pppoe_create(pSession->pppif, pSession->nicif, NULL, NULL, pppLinkStatusCallback, NULL);
-
-                    if (ppp == NULL) {
-                        netif_remove(netif);
-                        free(pSession);
-                        free(ppp_netif);
-                        dzlog_error("Create PPPoE netif error: %u\n", pList->userid);
-                    } else {
-
-                        ppp_set_auth(ppp,
-                                     PPPAUTHTYPE_ANY,
-                                     pSession->user_info.pppoe_user,
-                                     pSession->user_info.pppoe_passwd);
-                        ppp_connect(ppp, 0);
-
-                        dzlog_info("Create PPPoE netif %p: %u(%c%c:%d, %c%c:%d)\n",
-                                   ppp,
-                                   pList->userid,
-                                   ppp_netif->name[0],
-                                   ppp_netif->name[1],
-                                   ppp_netif->num,
-                                   netif->name[0],
-                                   netif->name[1],
-                                   netif->num);
-                        HASH_ADD_INT(g_pSessionList, userid, pSession);
-                    }
-                }
-            }
-        }
+    if (ppp_netif == NULL) {
+        dzlog_error("Malloc %lu bytes memory error\n", sizeof(struct netif));
+        return -ERR_MALLOC_MEMORY;
     }
-    return ERR_OK;
+
+    netif = create_pppoe_if(pUser);
+
+    if (netif == NULL) {
+        dzlog_error("Create PPPoE netif error: %u\n", pUser->userid);
+        free((void *)ppp_netif);
+        return -ERR_CREATE_PPPOE_NETIF;
+    }
+
+    pUser->session.nicif = netif;
+    pUser->session.pppif = ppp_netif;
+
+    ppp = pppapi_pppoe_create(pUser->session.pppif, pUser->session.nicif, NULL, NULL, pppLinkStatusCallback, pUser);
+
+    if (ppp == NULL) {
+        dzlog_error("Create PPPoE session error: %u\n", pUser->userid);
+        netif_remove(netif);
+        free((void *)ppp_netif);
+        return -ERR_CREATE_PPP_SESSION;
+    }
+
+    pUser->session.ppp = ppp;
+
+    ppp_set_auth(ppp, PPPAUTHTYPE_ANY, pUser->user_info.pppoe_user, pUser->user_info.pppoe_passwd);
+
+    dzlog_debug("Create PPPoE netif %p: %u(%c%c:%d, %c%c:%d)\n",
+                ppp,
+                pUser->userid,
+                ppp_netif->name[0],
+                ppp_netif->name[1],
+                ppp_netif->num,
+                netif->name[0],
+                netif->name[1],
+                netif->num);
+
+    return ERR_SUCCESS;
+}
+
+struct netif *get_rawsocket_if(void) {
+    return g_rawSocketIf;
 }
\ No newline at end of file
diff --git a/srcs/user/user_info.c b/srcs/user/user_info.c
index 596863c..5abc052 100644
--- a/srcs/user/user_info.c
+++ b/srcs/user/user_info.c
@@ -1,56 +1,132 @@
 //
 // Created by xajhuang on 2022/5/11.
 //
+#include <misc.h>
 #include "user_info.h"
 #include "user_errno.h"
 
-static PUSER_INFO_LIST g_pUserList = NULL;
+static PUSER_INFO_CONTEXT g_pUserList = NULL;
+static uv_rwlock_t     g_userLock;
 
 static USER_INFO g_userInfo[] = {
-    {0, 1, {0x00, 0x0C, 0x01, 0x02, 0x00, 0x02}, "xajhuang", "aaaHuang1"},
-    {1, 2, {0x00, 0x0C, 0x01, 0x02, 0x00, 0x03}, "xajhuang1", "aaaHuang1"},
-    {3, 4, {0x00, 0x0C, 0x01, 0x02, 0x00, 0x04}, "xajhuang2", "aaaHuang1"},
+    {0, 1, {0x00, 0x0C, 0x01, 0x02, 0x00, 0x02}, "xajhuang3", "aaaHuang1", STATUS_USER_NEW},
+    {1, 2, {0x00, 0x0C, 0x01, 0x02, 0x00, 0x03}, "xajhuang1", "aaaHuang1", STATUS_USER_NEW},
+    {3, 4, {0x00, 0x0C, 0x01, 0x02, 0x00, 0x04}, "xajhuang2", "aaaHuang1", STATUS_USER_NEW},
 };
 
 void user_info_init() {
+    uv_rwlock_init(&g_userLock);
+
     user_info_add(0, &g_userInfo[0]);
     user_info_add(1, &g_userInfo[1]);
     user_info_add(2, &g_userInfo[2]);
 }
 
+void user_info_change_status(PUSER_INFO pInfo, USER_STATUS status) {
+    pInfo->user_status = status;
+}
+
 int user_info_add(unsigned int userid, PUSER_INFO pInfo) {
+    PUSER_INFO_CONTEXT pUser;
+
+    uv_rwlock_rdlock(&g_userLock);
+    HASH_FIND_INT(g_pUserList, &userid, pUser);
+    uv_rwlock_rdunlock(&g_userLock);
+
+    if(pUser != NULL) {
+        return -ERR_ITEM_EXISTS;
+    }
+
     if (pInfo) {
-        PUSER_INFO_LIST pList = (PUSER_INFO_LIST)malloc(sizeof(USER_INFO_LIST));
+        PUSER_INFO_CONTEXT pList = (PUSER_INFO_CONTEXT)malloc(sizeof(USER_INFO_CONTEXT));
 
         if (!pList) {
             return ERR_MALLOC_MEMORY;
         }
 
+        memset(pList, 0, sizeof(USER_INFO_CONTEXT));
+
         pList->userid                 = userid;
         pList->user_info.qinq_tag1    = pInfo->qinq_tag1;
         pList->user_info.qinq_tag2    = pInfo->qinq_tag2;
         pList->user_info.pppoe_user   = strdup(pInfo->pppoe_user);
         pList->user_info.pppoe_passwd = strdup(pInfo->pppoe_passwd);
+        pList->user_info.user_status  = STATUS_USER_NEW;
         memcpy(pList->user_info.mac_addr, pInfo->mac_addr, 6);
 
+        pList->session.status = STATUS_TASK_INIT;
+
+        uv_rwlock_wrlock(&g_userLock);
         HASH_ADD_INT(g_pUserList, userid, pList);
+        uv_rwlock_wrunlock(&g_userLock);
     }
 
-    return ERR_OK;
+    return ERR_SUCCESS;
 }
 
 void user_info_remove(unsigned int userid) {
-    PUSER_INFO_LIST pInfo;
+    PUSER_INFO_CONTEXT pInfo;
 
+    uv_rwlock_rdlock(&g_userLock);
     HASH_FIND_INT(g_pUserList, &userid, pInfo);
+    uv_rwlock_rdunlock(&g_userLock);
+
+    if (pInfo) {
+        pInfo->user_info.user_status = STATUS_USER_DELETE;
+    }
+}
+
+void user_info_delete(unsigned int userid) {
+    PUSER_INFO_CONTEXT pInfo;
+
+    uv_rwlock_rdlock(&g_userLock);
+    HASH_FIND_INT(g_pUserList, &userid, pInfo);
+    uv_rwlock_rdunlock(&g_userLock);
 
     if (pInfo) {
         HASH_DEL(g_pUserList, pInfo);
     }
 }
 
+int user_info_modify(unsigned int userid, PUSER_INFO pUser) {
+    PUSER_INFO_CONTEXT pInfo;
+
+    uv_rwlock_rdlock(&g_userLock);
+    HASH_FIND_INT(g_pUserList, &userid, pInfo);
+    uv_rwlock_rdunlock(&g_userLock);
+
+    if (pInfo) {
+        int isUpgrade = FALSE;
+
+        if (memcmp(pInfo->user_info.mac_addr, pUser->mac_addr, 6) != 0) {
+            memcpy(pInfo->user_info.mac_addr, pUser->mac_addr, 6);
+            isUpgrade = TRUE;
+        }
+
+        if (strcmp(pInfo->user_info.pppoe_user, pUser->pppoe_user) != 0) {
+            free((void*)pInfo->user_info.pppoe_user);
+            pInfo->user_info.pppoe_user = strdup(pUser->pppoe_user);
+            isUpgrade                   = TRUE;
+        }
+
+        if (strcmp(pInfo->user_info.pppoe_passwd, pUser->pppoe_passwd) != 0) {
+            free((void*)pInfo->user_info.pppoe_passwd);
+            pInfo->user_info.pppoe_passwd = strdup(pUser->pppoe_passwd);
+            isUpgrade                     = TRUE;
+        }
+
+        if (isUpgrade) {
+            pInfo->user_info.user_status = STATUS_USER_MODIFY;
+        }
+
+        return ERR_SUCCESS;
+    } else {
+        return -ERR_ITEM_UNEXISTS;
+    }
+}
+
 PUSER_INFO user_info_get_by_userid(unsigned int userid) {
-    PUSER_INFO_LIST pInfo;
+    PUSER_INFO_CONTEXT pInfo;
 
     HASH_FIND_INT(g_pUserList, &userid, pInfo);
 
@@ -61,6 +137,10 @@ PUSER_INFO user_info_get_by_userid(unsigned int userid) {
     return NULL;
 }
 
-PUSER_INFO_LIST user_info_getall() {
+PUSER_INFO_CONTEXT get_all_user() {
     return g_pUserList;
+}
+
+uv_rwlock_t* get_user_lock() {
+    return &g_userLock;
 }
\ No newline at end of file
diff --git a/srcs/vcpe_main.c b/srcs/vcpe_main.c
index a880df2..e778847 100644
--- a/srcs/vcpe_main.c
+++ b/srcs/vcpe_main.c
@@ -2,6 +2,7 @@
 // Created by xajhu on 2021/6/29 0029.
 //
 #include <uv.h>
+#include <zlog.h>
 
 #include "cmdline.h"
 #include "task_manager.h"
@@ -10,6 +11,7 @@
 #include "pppoe_session.h"
 #include "lwip/sys.h"
 #include "lwip/tcpip.h"
+#include "netif/rawif.h"
 
 static void test_init(void *arg) { /* remove compiler warning */
     sys_sem_t *init_sem;
@@ -42,7 +44,7 @@ int main(int argc, char **argv) {
 
     lwip_init_env();
     user_info_init();
-    pppoe_session_init();
+    pppoe_session_init(NULL);
 
     task_manager_run();
     user_uninit();