diff --git a/CMakeLists.txt b/CMakeLists.txt index c35055c..fbce2a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ if ("${GIT_TAG}" STREQUAL "") else () STRING(REGEX REPLACE "\n$" "" GIT_TAG ${GIT_TAG}) endif () -# + MESSAGE("Version: " ${GIT_TAG}) diff --git a/srcs/libs/config/agent.cfg b/srcs/libs/config/agent.cfg index 4cc15b6..dee39fb 100644 --- a/srcs/libs/config/agent.cfg +++ b/srcs/libs/config/agent.cfg @@ -48,11 +48,20 @@ application: agent_port = 6279; # Agetn 通信端口 }; - # 网络相关 - network: + # vxlan 相关 + vxlan: { - nic_card = "ens36"; # 收发数据使用的网卡名称 - nic_mac = "00:0C:01:02:00:01"; # 收发数据使用的网卡Mac地址 - vxlan_support = true; # 是否支持vxLan封装 + vxlan_enable = true; # 是否启动vxLan隧道封装 + vxlan_nic = "ens36"; # vxlan 物理网卡名称 + vxlan_peer_ip = "192.168.20.112"; # vxlan 对端IP + vxlan_peer_mac = "00:0C:29:49:CB:27"; # vxlan 对端 MAC 地址 + }; + + # vcpe 本地服务网络接口配置 + local_eth: + { + local_ip = "192.168.100.1"; + local_netmast = "255.255.0.0"; + local_gw = "192.168.100.1"; } } \ No newline at end of file diff --git a/srcs/libs/configure/config.c b/srcs/libs/configure/config.c index 59f82b1..e76b991 100644 --- a/srcs/libs/configure/config.c +++ b/srcs/libs/configure/config.c @@ -480,9 +480,12 @@ do { /* 消息队列相配置 */ \ /* ZeroMq配置 */ \ ADD_CFG_ITEM(CFG_MQ_SVR_PORT, "application.zero_mq.svr_port", VALUE_TYPE_INTEGRAL, "6278", "ZeroMQ server port"); \ - ADD_CFG_ITEM(CFG_MQ_DATA_CH, "application.zero_mq.agent_port", VALUE_TYPE_INTEGRAL, "6279", "ZeroMQ Agent server port"); \ - ADD_CFG_ITEM(CFG_NIC_CARD_NAME, "application.network.nic_card", 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"); \ + ADD_CFG_ITEM(CFG_MQ_DATA_CH, "application.zero_mq.agent_port", VALUE_TYPE_INTEGRAL, "6279", "ZeroMQ Agent server port"); \ + /* vxLan 隧道配置 */ \ + ADD_CFG_ITEM(CFG_VXLAN_NIC_NAME, "application.vxlan.vxlan_nic", VALUE_TYPE_STRING, "", "Network card name to send data"); \ + ADD_CFG_ITEM(CFG_VXLAN_SUPPORT, "application.vxlan.vxlan_enable", VALUE_TYPE_BOOL, "1", "Is support vxLan tune"); \ + ADD_CFG_ITEM(CFG_VXLAN_PEER_IP, "application.vxlan.vxlan_peer_ip", VALUE_TYPE_STRING, "", "vxLan peer ip address"); \ + ADD_CFG_ITEM(CFG_VXLAN_PEER_MAC, "application.vxlan.vxlan_peer_mac", VALUE_TYPE_STRING, "", "vxLan peer mac address"); \ } 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 62f1fb4..1a8cf74 100644 --- a/srcs/libs/configure/config_help.c +++ b/srcs/libs/configure/config_help.c @@ -3,8 +3,16 @@ // #include "config.h" -const char* config_get_nic_name() { - return cfg_get_string_value(CFG_NIC_CARD_NAME); +const char*config_get_vxlan_nic_name() { + return cfg_get_string_value(CFG_VXLAN_NIC_NAME); +} + +const char*config_get_vxlan_peer_ip() { + return cfg_get_string_value(CFG_VXLAN_PEER_IP); +} + +const char*config_get_vxlan_peer_mac() { + return cfg_get_string_value(CFG_VXLAN_PEER_MAC); } int cfg_get_support_vxlan() { diff --git a/srcs/libs/include/config.h b/srcs/libs/include/config.h index d7b8720..fe8eec0 100644 --- a/srcs/libs/include/config.h +++ b/srcs/libs/include/config.h @@ -42,9 +42,10 @@ typedef enum { CFG_DB_MYSQL_DB_NAME = 20, CFG_MQ_SVR_PORT = 21, CFG_MQ_DATA_CH = 22, - CFG_NIC_CARD_NAME = 23, + CFG_VXLAN_NIC_NAME = 23, CFG_VXLAN_SUPPORT = 24, - + CFG_VXLAN_PEER_IP = 25, + CFG_VXLAN_PEER_MAC = 26, CONFIG_ITEM_ID_MAX } CONFIG_ITEM_ID; @@ -84,7 +85,9 @@ 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(); +const char *config_get_vxlan_nic_name(); +const char *config_get_vxlan_peer_mac(); +const char *config_get_vxlan_peer_ip(); #ifdef __cplusplus } #endif diff --git a/srcs/libs/include/misc.h b/srcs/libs/include/misc.h index d8e4794..90a66cd 100644 --- a/srcs/libs/include/misc.h +++ b/srcs/libs/include/misc.h @@ -36,6 +36,9 @@ extern "C" { #define FALSE (0) #endif +#define VERIFY_STRING(s) (((s) != NULL) && (strlen(s) > 0)) +#define PRINTABLE_STRING(s) ((s) == NULL ? "NULL" : (s)) + int file_exists(const char *pPath); const char *basename_v2(const char *path); int dirname_v2(const char *path, char *dir); @@ -43,6 +46,10 @@ unsigned long long get_partition_free_size(const char *pPartPath); int copy_file(const char *pSrc, const char *pDest); char *bin2hex(char *p, const unsigned char *cp, unsigned int count); int shell_with_output(const char *pCmd, char **pResult); +int str_to_mac(const char *str, unsigned char mac[6]); +int get_nic_info(const char *pName, unsigned int *pIp, unsigned int *pNetmask, unsigned int *pGateway, + unsigned char *pMac); +int str_to_ipaddr(const char *pIp, unsigned int *ipAddr); #ifdef __cplusplus } #endif diff --git a/srcs/libs/include/user_errno.h b/srcs/libs/include/user_errno.h index a9452bc..29d17d1 100644 --- a/srcs/libs/include/user_errno.h +++ b/srcs/libs/include/user_errno.h @@ -74,6 +74,13 @@ typedef enum { ERR_CREATE_PPPOE_NETIF = 2501, ERR_CREATE_PPP_SESSION = 2502, + // MISC 相关 + ERR_MISC_GET_IPADDR = 2600, + ERR_MISC_GET_NETMASK = 2601, + ERR_MISC_GET_GATEWAY = 2602, + ERR_MISC_GET_MACADDR = 2603, + + } USER_ERRNO; #ifdef __cplusplus diff --git a/srcs/libs/misc/misc.c b/srcs/libs/misc/misc.c index 190da24..d8934d8 100644 --- a/srcs/libs/misc/misc.c +++ b/srcs/libs/misc/misc.c @@ -8,6 +8,9 @@ #include #include #include +#include +#include +#include #include "user_errno.h" #include "misc.h" @@ -149,4 +152,84 @@ const char *get_cur_process_dir() { } return (const char *)g_exePath; +} + +int str_to_mac(const char *str, unsigned char mac[6]) { + int i; + char *s, *e; + + if ((mac == NULL) || (str == NULL)) { + return -ERR_INPUT_PARAMS; + } + + s = (char *)str; + for (i = 0; i < 6; ++i) { + mac[i] = s ? strtoul(s, &e, 16) : 0; + if (s) { + s = (*e) ? e + 1 : e; + } + } + return ERR_SUCCESS; +} + +int str_to_ipaddr(const char *pIp, unsigned int *ipAddr) { + struct in_addr addr; + int ret = inet_aton(pIp, &addr); + + if (ret != 0) { + *ipAddr = addr.s_addr; + } + + return ret; +} + +int get_nic_info(const char *pName, unsigned int *pIp, unsigned int *pNetmask, unsigned int *pGateway, + unsigned char *pMac) { + int sock; + struct ifreq ifr; + int err = ERR_SUCCESS; + sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + + if (sock < 0) { + dzlog_error("Get local NIC information failed\n"); + return -ERR_SYS_INIT; + } + + memset(&ifr, 0, sizeof(ifr)); + strcpy(ifr.ifr_name, pName); + + if (pIp) { + if (ioctl(sock, SIOCGIFADDR, &ifr) != 0) { + err = ERR_MISC_GET_IPADDR; + } else { + *pIp = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; + } + } + + if (pNetmask) { + if (ioctl(sock, SIOCGIFNETMASK, &ifr) == 0) { + *pNetmask = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; + } else { + err = ERR_MISC_GET_NETMASK; + } + } + + if (pGateway) { + if (ioctl(sock, SIOCGIFBRDADDR, &ifr) == 0) { + *pGateway = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; + } else { + err = ERR_MISC_GET_GATEWAY; + } + } + + if (pMac) { + if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) { + memcpy(pMac, ifr.ifr_hwaddr.sa_data, ETH_ALEN); + } else { + err = ERR_MISC_GET_MACADDR; + } + } + + close(sock); + return err; } \ No newline at end of file diff --git a/srcs/lwip/src/arch_linux/Filelists.cmake b/srcs/lwip/src/arch_linux/Filelists.cmake index 84e4921..e89c888 100644 --- a/srcs/lwip/src/arch_linux/Filelists.cmake +++ b/srcs/lwip/src/arch_linux/Filelists.cmake @@ -11,6 +11,7 @@ set(lwipcontribportunix_SRCS ${LWIP_DIR}/src/arch_linux/sys_arch.c ${LWIP_DIR}/src/arch_linux/perf.c + ${LWIP_DIR}/src/arch_linux/core/vxlan_pkg.c ) set(lwipcontribportunixnetifs_SRCS diff --git a/srcs/lwip/src/arch_linux/core/vxlan_pkg.c b/srcs/lwip/src/arch_linux/core/vxlan_pkg.c new file mode 100644 index 0000000..2fd40f2 --- /dev/null +++ b/srcs/lwip/src/arch_linux/core/vxlan_pkg.c @@ -0,0 +1,330 @@ +// +// Created by xajhuang on 2022/6/9. +// + +#include +#include +#include + +#include "lwip/opt.h" +#include "lwip/vxlan.h" + +#include "misc.h" +#include "user_errno.h" + +#include "vxlan_pkg.h" +#include "lwip/prot/ip.h" +#include "lwip/inet_chksum.h" + +typedef struct { + char ethName[ETH_NAME_MAX]; + unsigned char mac[ETH_HWADDR_LEN]; + unsigned int ip_addr; + unsigned int ip_mask; + unsigned int ip_gw; +} NIC_INFO, *PNIC_INFO; + +typedef struct { + unsigned int vni; + unsigned char peerMac[ETH_HWADDR_LEN]; + unsigned int peerIp; + unsigned char snd_pkg_head[VXLAN_HEAD_SIZE]; + UT_hash_handle hh; +} VXLAN_PEER, *PVXLAN_PEER; + +typedef struct { + NIC_INFO nic_info; + PVXLAN_PEER vxlan_peer; + uv_rwlock_t lock_peer; +} VXLAN_LINK_CONFIG, *PVXLAN_LINK_CONFIG; + +static VXLAN_LINK_CONFIG g_vxLanLinks; +static PVXLAN_PEER g_pAllvxLanPeers = NULL; + +static struct pbuf *vxlan_pkg_recombine(const unsigned char *pBuf, unsigned short size) { + struct pbuf *q; + unsigned char buf[1500]; + const struct vxlan_package *pkg = (const struct vxlan_package *)pBuf; + int eth_len = +sizeof(struct eth_hdr); + unsigned int pkgsize = (size + eth_len) - VXLAN_HEAD_SIZE; + + memcpy(buf, &pkg->eth_pkg, sizeof(struct eth_hdr)); + memcpy(buf + eth_len - 2, pkg->data - 2, pkgsize - eth_len + 2); + + /* We allocate a pbuf chain of pbufs from the pool. */ + q = pbuf_alloc(PBUF_RAW, pkgsize, PBUF_RAM); + + if (q != NULL) { + pbuf_take(q, buf, pkgsize); + } + + return q; +} + +int vxlan_pkg_decode(const struct pbuf *pIn, struct pbuf **pOut, PVXLAN_TAG pTag) { + const struct vxlan_package *pkg = (const struct vxlan_package *)pIn; + + if (pIn == NULL || pOut == NULL || pTag == NULL) { + return -ERR_INPUT_PARAMS; + } + + pTag->vni = VXLAN_VIN_ID(lwip_htonl(pkg->vxlan_head.vni_reserved)); + pTag->q1 = lwip_ntohs(pkg->qinq_head.out_priority_cfi_and_id); + pTag->q2 = lwip_ntohs(pkg->qinq_head.in_priority_cfi_and_id); + + *pOut = vxlan_pkg_recombine((const unsigned char *)pIn->payload, pIn->tot_len); + + if (*pOut == NULL) { + return ERR_MALLOC_MEMORY; + } + + return ERR_SUCCESS; +} + +static unsigned short udp_checksum(unsigned char *pNetPacket, unsigned int uLen) { + unsigned int iLen = uLen - sizeof(struct eth_hdr) - sizeof(struct ip_hdr) + 12; + unsigned short sum = 0; + unsigned char *pData = (unsigned char *)malloc(iLen + 12); + + struct vxlan_package *pNetHead = (struct vxlan_package *)pNetPacket; + + if (pData) { + memset(pData, 0, iLen); + memcpy(pData, &pNetHead->ip_head.src.addr, 4); + memcpy(pData + 4, &pNetHead->ip_head.dest.addr, 4); + pData[9] = 0x11; + memcpy(pData + 10, &pNetHead->udp_head.len, 2); + + pNetHead->udp_head.chksum = 0; + memcpy(pData + 12, &pNetHead->udp_head, iLen - 12); + + sum = inet_chksum(pData, iLen); + + free(pData); + } + + if (sum == 0) { + sum = 0xFFFF; + } + return sum; +} + +unsigned char *vxlan_pkg_encode(const unsigned char *pInBuf, int inSize, PVXLAN_TAG pTag, unsigned int *outSize) { + unsigned short checksum; + unsigned char *pBuf; + struct vxlan_package *pkg; + const struct eth_hdr *eth = (const struct eth_hdr *)pInBuf; + unsigned int dataSize = inSize - sizeof(eth_hdr_t); + unsigned short udp_len = inSize + sizeof(vxlan_hdr_t) + sizeof(qinq_hdr_t) + sizeof(udp_hdr_t); + unsigned short ip_len = udp_len + 20; + unsigned int total_len = ip_len + sizeof(struct eth_hdr); + PVXLAN_PEER pvxlanBuf; + + uv_rwlock_rdlock(&g_vxLanLinks.lock_peer); + HASH_FIND_INT(g_pAllvxLanPeers, &pTag->vni, pvxlanBuf); + uv_rwlock_rdunlock(&g_vxLanLinks.lock_peer); + + if (pvxlanBuf == NULL || outSize == NULL) { + return NULL; + } + + *outSize = 0; + + pBuf = (unsigned char *)malloc(total_len); + + if (pBuf == NULL) { + return NULL; + } + + pkg = (struct vxlan_package *)pBuf; + + // 复制优先构造好的头部数据 + memcpy(pBuf, pvxlanBuf->snd_pkg_head, VXLAN_HEAD_SIZE); + // 设置VNI ID + pkg->vxlan_head.vni_reserved = lwip_htonl(VXLAN_VIN_ID_PACK(pTag->vni)); + + // 构造内存ETH包 MAC地址 + memcpy(pkg->eth_pkg.dest.addr, eth->dest.addr, ETH_HWADDR_LEN); + memcpy(pkg->eth_pkg.src.addr, eth->src.addr, ETH_HWADDR_LEN); + + // 构造内存Q-in-Q头部数据 + pkg->qinq_head.out_priority_cfi_and_id = lwip_htons(pTag->q1); + pkg->qinq_head.in_priority_cfi_and_id = lwip_htons(pTag->q2); + pkg->qinq_head.origin_type = eth->type; + + // 复制载荷数据到内存数据部分 + memcpy(pkg->data, pInBuf + sizeof(eth_hdr_t), dataSize); + + // 设置IP,UDP头部数据长度字段 + pkg->udp_head.len = lwip_htons(udp_len); + pkg->ip_head._len = lwip_htons(ip_len); + + // 计算校验和前校验和置零 + pkg->ip_head._chksum = 0x0000; + pkg->udp_head.chksum = 0x0000; + + checksum = udp_checksum(pBuf, total_len); + pkg->udp_head.chksum = checksum; + IPH_CHKSUM_SET(&pkg->ip_head, inet_chksum(&pkg->ip_head, 20)); + + *outSize = total_len; + + return pBuf; +} + +static void vxlan_pkg_head_init(PVXLAN_PEER pvxLan) { + struct vxlan_package *pkg = (struct vxlan_package *)pvxLan->snd_pkg_head; + + // 设置目的Mac + memcpy(pkg->eth_head.dest.addr, pvxLan->peerMac, ETH_HWADDR_LEN); + // 设置源Mac + memcpy(pkg->eth_head.src.addr, g_vxLanLinks.nic_info.mac, ETH_HWADDR_LEN); + // 设置 ETH 包类型 + pkg->eth_head.type = lwip_htons(ETHTYPE_IP); + + // 设置IP头部 + IPH_VHL_SET(&pkg->ip_head, 4, IP_HLEN / 4); + IPH_TOS_SET(&pkg->ip_head, 0x05); + // IP 头长度置为0, 后续实际发包的时候重新计算 + IPH_LEN_SET(&pkg->ip_head, 0); + IPH_ID_SET(&pkg->ip_head, 0); + IPH_OFFSET_SET(&pkg->ip_head, 0); + // TTL 设置为64 + IPH_TTL_SET(&pkg->ip_head, 64); + // vxLan隧道协议为UDP + IPH_PROTO_SET(&pkg->ip_head, IP_PROTO_UDP); + // 校验和初始化为0 + IPH_CHKSUM_SET(&pkg->ip_head, 0); + pkg->ip_head.src.addr = g_vxLanLinks.nic_info.ip_addr; + pkg->ip_head.dest.addr = lwip_htonl(pvxLan->peerIp); + + // 设置UDP头部 + // 设置UDP端口为vxLan 4789 端口 + pkg->udp_head.dest = lwip_htons(VXLAN_UDP_PORT); + pkg->udp_head.src = lwip_htons(VXLAN_UDP_PORT); + // 校验和初始化为0 + pkg->udp_head.chksum = 0; + + // 设置vxlan隧道头部 + pkg->vxlan_head.flags = 0x08; + pkg->vxlan_head.res1 = 0x00; + pkg->vxlan_head.res2 = 0x00; + pkg->vxlan_head.res3 = 0x00; + pkg->vxlan_head.vni_reserved = lwip_htonl(VXLAN_VIN_ID_PACK(pvxLan->vni)); + + // 设置内层ETH头部 + // 设置内层报文类型 + pkg->eth_pkg.type = lwip_htons(ETHTYPE_QINQ_BRG); + + // 设置QinQ头部 + pkg->qinq_head.in_type = lwip_htons(QINQ_802_1_AD); +} + +int vxlan_peer_add(unsigned int vni, const char* pIp, const char* pMac) { + PVXLAN_PEER vxlan_peer; + + if (!VERIFY_STRING(pIp) || !VERIFY_STRING(pMac)) { + dzlog_error("Input parameters error: %s, %s\n", + PRINTABLE_STRING(pIp), + PRINTABLE_STRING(pMac)); + return -ERR_INPUT_PARAMS; + } + + uv_rwlock_rdlock(&g_vxLanLinks.lock_peer); + HASH_FIND_INT(g_pAllvxLanPeers, &vni, vxlan_peer); + uv_rwlock_rdunlock(&g_vxLanLinks.lock_peer); + + if (vxlan_peer == NULL) { + unsigned int peerIp; + unsigned char peerMac[6]; + + str_to_mac(pMac, peerMac); + + if (str_to_ipaddr(pIp, &peerIp) == 0) { + dzlog_error("Get vxLan peer ip address failed: %s\n", pIp); + return -ERR_SYS_INIT; + } + + vxlan_peer = (PVXLAN_PEER)malloc(sizeof(VXLAN_PEER)); + + if (vxlan_peer == NULL) { + return -ERR_MALLOC_MEMORY; + } + + memset(vxlan_peer, 0, sizeof(VXLAN_PEER)); + + vxlan_peer->vni = vni; + vxlan_peer->peerIp = lwip_htonl(peerIp); + memcpy(vxlan_peer->peerMac, peerMac, ETH_HWADDR_LEN); + // 对发送报文的头部进行初始化 + vxlan_pkg_head_init(vxlan_peer); + + uv_rwlock_wrlock(&g_vxLanLinks.lock_peer); + HASH_ADD_INT(g_pAllvxLanPeers, vni, vxlan_peer); + uv_rwlock_wrunlock(&g_vxLanLinks.lock_peer); + } + + return ERR_SUCCESS; +} + +int vxlan_link_init(const char *pEthName) { + if (!VERIFY_STRING(pEthName)) { + dzlog_error("Input parameters error: %s\n", PRINTABLE_STRING(pEthName)); + return -ERR_INPUT_PARAMS; + } + + memset(&g_vxLanLinks, 0, sizeof(VXLAN_LINK_CONFIG)); + + uv_rwlock_init(&g_vxLanLinks.lock_peer); + g_vxLanLinks.vxlan_peer = g_pAllvxLanPeers; + + strncpy(g_vxLanLinks.nic_info.ethName, pEthName, ETH_NAME_MAX); + + if (get_nic_info(pEthName, + &g_vxLanLinks.nic_info.ip_addr, + &g_vxLanLinks.nic_info.ip_mask, + &g_vxLanLinks.nic_info.ip_gw, + g_vxLanLinks.nic_info.mac) + != ERR_SUCCESS) { + dzlog_error("Get NIC information failed\n"); + return -ERR_SYS_INIT; + } + +#if 0 + PVXLAN_LINK pvxLan; + + if (!VERIFY_STRING(pEthName) || !VERIFY_STRING(pPeerIp) || !VERIFY_STRING(pPeerMac)) { + dzlog_error("Input parameters error: %s, %s, %s\n", + PRINTABLE_STRING(pEthName), + PRINTABLE_STRING(pPeerIp), + PRINTABLE_STRING(pPeerMac)); + return -ERR_INPUT_PARAMS; + } + + pvxLan = (PVXLAN_LINK)malloc(sizeof(VXLAN_LINK)); + + if (pvxLan == NULL) { + dzlog_error("Create vxLan link error: %lu\n", sizeof(VXLAN_LINK)); + return -ERR_MALLOC_MEMORY; + } + + memset(pvxLan, 0, sizeof(VXLAN_LINK)); + + strncpy(pvxLan->vxlan_configure.ethName, pEthName, ETH_NAME_MAX); + str_to_mac(pPeerMac, pvxLan->vxlan_configure.ourMac); + + if (str_to_ipaddr(pPeerIp, &pvxLan->vxlan_configure.peerIp) == 0) { + dzlog_error("Get vxLan peer ip address failed: %s\n", pPeerIp); + return -ERR_SYS_INIT; + } + + if (get_nic_info(pEthName, &pvxLan->vxlan_configure.outIp, NULL, NULL, pvxLan->vxlan_configure.ourMac) + != ERR_SUCCESS) { + dzlog_error("Get NIC information failed\n"); + return -ERR_SYS_INIT; + } + + HASH_ADD_INT() +#endif + return ERR_SUCCESS; +} diff --git a/srcs/lwip/src/arch_linux/include/vxlan_pkg.h b/srcs/lwip/src/arch_linux/include/vxlan_pkg.h new file mode 100644 index 0000000..ba252c4 --- /dev/null +++ b/srcs/lwip/src/arch_linux/include/vxlan_pkg.h @@ -0,0 +1,20 @@ +// +// Created by xajhuang on 2022/6/9. +// + +#ifndef VCPE_PROJECT_VXLAN_PKG_H +#define VCPE_PROJECT_VXLAN_PKG_H +#ifdef __cplusplus +extern "C" { +#endif +#include "lwip/prot/ethernet.h" +#include "pppoe_info.h" + +int vxlan_link_init(const char *pEthName); +int vxlan_pkg_decode(const struct pbuf *p, struct pbuf **pOut, PVXLAN_TAG pTag); +int vxlan_peer_add(unsigned int vni, const char* pIp, const char* pMac); +unsigned char *vxlan_pkg_encode(const unsigned char *pInBuf, int inSize, PVXLAN_TAG pTag, unsigned int *outSize); +#ifdef __cplusplus +} +#endif +#endif//VCPE_PROJECT_VXLAN_PKG_H diff --git a/srcs/lwip/src/arch_linux/netif/rawif.c b/srcs/lwip/src/arch_linux/netif/rawif.c index db95356..06d4602 100644 --- a/srcs/lwip/src/arch_linux/netif/rawif.c +++ b/srcs/lwip/src/arch_linux/netif/rawif.c @@ -64,6 +64,7 @@ #include "user_info.h" #include "lwip/prot/ip.h" #include "lwip/inet_chksum.h" +#include "vxlan_pkg.h" #if defined(LWIP_UNIX_LINUX) #include @@ -78,6 +79,7 @@ #endif #define USED_ENUMER_VXLAN (0) +#define AUTO_LEARN_VXLAN (0) #define DEFAULT_GW_IPADDR (0xC0A80001) @@ -247,7 +249,7 @@ static unsigned short udp_checksum(unsigned char *pNetPacket, unsigned int uLen) static err_t low_level_output(struct netif *netif, struct pbuf *p) { unsigned char sndBuf[1518]; unsigned char buf[1518]; /* max packet size including VLAN excluding CRC */ - ssize_t written; + ssize_t written = 0; struct sockaddr_ll dstAddr; struct rawif *rawif = (struct rawif *)netif->state; PUSER_INFO_CONTEXT pUser = (PUSER_INFO_CONTEXT)p->extra; @@ -267,12 +269,14 @@ static err_t low_level_output(struct netif *netif, struct pbuf *p) { // 网卡支持vxlan if (rawif->vxlan_support) { +#if AUTO_LEARN_VXLAN PVXLAN_BUF pvxlanBuf; uv_rwlock_rdlock(&rawif->lock_vxlan); HASH_FIND_INT(rawif->pvxLan, &pUser->vxlan.vni, pvxlanBuf); uv_rwlock_rdunlock(&rawif->lock_vxlan); if (pvxlanBuf) { + unsigned short checksum; unsigned int dataSize = p->tot_len - sizeof(struct eth_hdr); struct eth_hdr *eth = (struct eth_hdr *)buf; @@ -306,11 +310,47 @@ static err_t low_level_output(struct netif *netif, struct pbuf *p) { IPH_CHKSUM_SET(&pkg->ip_head, inet_chksum(&pkg->ip_head, 20)); written = sendto(rawif->fd, sndBuf, total_len, 0, (struct sockaddr *)&dstAddr, sizeof(dstAddr)); + + + + if(memcmp(buf, p->payload, p->tot_len) != 0) { + dzlog_debug("INPKG +++++\n"); + hdzlog_debug(p->payload, p->tot_len); + printf("\n"); + dzlog_debug("INPKG -----\n"); + + dzlog_debug("BUF +++++\n"); + hdzlog_debug(buf, p->tot_len); + printf("\n"); + dzlog_debug("BUF -----\n"); + } + +#if 0 + dzlog_debug("OUTPKG +++++\n"); + hdzlog_debug(sndBuf, total_len); + printf("\n"); + dzlog_debug("INPKG -----\n"); +#endif + dzlog_debug("In %u, out %u, send %zd\n", p->tot_len, total_len, written); + return written == (total_len) ? ERR_OK : ERR_IF; + + + } else { /* signal that packet should be sent(); */ written = sendto(rawif->fd, buf, p->tot_len, 0, (struct sockaddr *)&dstAddr, sizeof(dstAddr)); } +#else + unsigned int outSize = 0; + unsigned char *pBuf = vxlan_pkg_encode(buf, p->tot_len, &pUser->vxlan, &outSize); + + if (pBuf && outSize != 0) { + written = sendto(rawif->fd, pBuf, outSize, 0, (struct sockaddr *)&dstAddr, sizeof(dstAddr)); + } + + return written == (outSize) ? ERR_OK : ERR_IF; +#endif } else { /* signal that packet should be sent(); */ written = sendto(rawif->fd, buf, p->tot_len, 0, (struct sockaddr *)&dstAddr, sizeof(dstAddr)); @@ -345,8 +385,8 @@ static struct pbuf *low_level_input(struct netif *netif) { return NULL; } - if(rawif->vxlan_support) { - if(!is_vxlan_package(buf)) { + if (rawif->vxlan_support) { + if (!is_vxlan_package(buf)) { return NULL; } } else { @@ -543,6 +583,7 @@ static err_t netif_input_data(struct pbuf *p, struct netif *inp) { // UDP xvLan 数据包 if (is_vxlan_package((const unsigned char *)p->payload)) { +#if AUTO_LEARN_VXLAN VXLAN_TAG tag; PUSER_INFO_CONTEXT pContext; PVXLAN_BUF pvxlanBuf; @@ -650,6 +691,42 @@ static err_t netif_input_data(struct pbuf *p, struct netif *inp) { } else { dzlog_error("Not found: %u, %u, %u\n", tag.vni, tag.q1, tag.q2); } +#else + VXLAN_TAG tag; + struct pbuf *ebuf = NULL; + PUSER_INFO_CONTEXT pContext; + tag.vni = VXLAN_VIN_ID(lwip_htonl(pkg->vxlan_head.vni_reserved)); + tag.q1 = lwip_ntohs(pkg->qinq_head.out_priority_cfi_and_id); + tag.q2 = lwip_ntohs(pkg->qinq_head.in_priority_cfi_and_id); + + HASH_FIND(hh_vxlan, get_all_user_by_tag(), &tag, sizeof(VXLAN_TAG), pContext); + + if (pContext && pContext->session.pppif) { + if (strlen(pContext->session.data.svrBaseMac) == 0) { + sprintf(pContext->session.data.svrBaseMac, + "%02X:%02X:%02X:%02X:%02X:%02X", + pBuf[6], + pBuf[7], + pBuf[8], + pBuf[9], + pBuf[10], + pBuf[11]); + } + vxlan_pkg_decode(p, &ebuf, &tag); + + if (ebuf == NULL) { + return ERR_IF; + } + + if ((err = pContext->session.nicif->input(ebuf, pContext->session.nicif)) != ERR_OK) { + dzlog_debug("\n"); + LWIP_DEBUGF(NETIF_DEBUG, ("pppoeif_input: netif input error\n")); + } + + pbuf_free(p); + return err; + } +#endif } } else { NETIF_FOREACH(netif) { @@ -685,6 +762,11 @@ struct netif *bind_rawsocket_if(const char *eth_name) { rawif->eth_name = eth_name; } + if (vxlan_link_init(eth_name) != ERR_OK) { + dzlog_error("bind_rawsocket_if: Get local nic info failed\n"); + return NULL; + } + ip4_addr_set_zero(&gw); ip4_addr_set_zero(&ipaddr); ip4_addr_set_zero(&netmask); diff --git a/srcs/lwip/src/include/lwip/prot/ethernet.h b/srcs/lwip/src/include/lwip/prot/ethernet.h index 309e574..719b4c9 100644 --- a/srcs/lwip/src/include/lwip/prot/ethernet.h +++ b/srcs/lwip/src/include/lwip/prot/ethernet.h @@ -44,6 +44,10 @@ extern "C" { #endif +#ifndef ETH_NAME_MAX +#define ETH_NAME_MAX 32 +#endif + #ifndef ETH_HWADDR_LEN #ifdef ETHARP_HWADDR_LEN #define ETH_HWADDR_LEN ETHARP_HWADDR_LEN /* compatibility mode */ diff --git a/srcs/lwip/src/include/lwip/prot/ieee.h b/srcs/lwip/src/include/lwip/prot/ieee.h index abbb9e3..f1b42a5 100644 --- a/srcs/lwip/src/include/lwip/prot/ieee.h +++ b/srcs/lwip/src/include/lwip/prot/ieee.h @@ -50,38 +50,40 @@ extern "C" { * A list of often ethtypes (although lwIP does not use all of them). */ enum lwip_ieee_eth_type { - /** Internet protocol v4 */ - ETHTYPE_IP = 0x0800U, - /** Address resolution protocol */ - ETHTYPE_ARP = 0x0806U, - /** Wake on lan */ - ETHTYPE_WOL = 0x0842U, - /** RARP */ - ETHTYPE_RARP = 0x8035U, - /** Virtual local area network */ - ETHTYPE_VLAN = 0x8100U, - /** Internet protocol v6 */ - ETHTYPE_IPV6 = 0x86DDU, - /** PPP Over Ethernet Discovery Stage */ - ETHTYPE_PPPOEDISC = 0x8863U, - /** PPP Over Ethernet Session Stage */ - ETHTYPE_PPPOE = 0x8864U, - /** Jumbo Frames */ - ETHTYPE_JUMBO = 0x8870U, - /** Process field network */ - ETHTYPE_PROFINET = 0x8892U, - /** Ethernet for control automation technology */ - ETHTYPE_ETHERCAT = 0x88A4U, - /** Link layer discovery protocol */ - ETHTYPE_LLDP = 0x88CCU, - /** Serial real-time communication system */ - ETHTYPE_SERCOS = 0x88CDU, - /** Media redundancy protocol */ - ETHTYPE_MRP = 0x88E3U, - /** Precision time protocol */ - ETHTYPE_PTP = 0x88F7U, - /** Q-in-Q, 802.1ad */ - ETHTYPE_QINQ = 0x9100U + /** Internet protocol v4 */ + ETHTYPE_IP = 0x0800U, + /** Address resolution protocol */ + ETHTYPE_ARP = 0x0806U, + /** Wake on lan */ + ETHTYPE_WOL = 0x0842U, + /** RARP */ + ETHTYPE_RARP = 0x8035U, + /** Virtual local area network */ + ETHTYPE_VLAN = 0x8100U, + /** Internet protocol v6 */ + ETHTYPE_IPV6 = 0x86DDU, + /** PPP Over Ethernet Discovery Stage */ + ETHTYPE_PPPOEDISC = 0x8863U, + /** PPP Over Ethernet Session Stage */ + ETHTYPE_PPPOE = 0x8864U, + /** Jumbo Frames */ + ETHTYPE_JUMBO = 0x8870U, + /** Process field network */ + ETHTYPE_PROFINET = 0x8892U, + /** Ethernet for control automation technology */ + ETHTYPE_ETHERCAT = 0x88A4U, + /** Q-in-Q 802.1ad provider bridge network */ + ETHTYPE_QINQ_BRG = 0x88A8U, + /** Link layer discovery protocol */ + ETHTYPE_LLDP = 0x88CCU, + /** Serial real-time communication system */ + ETHTYPE_SERCOS = 0x88CDU, + /** Media redundancy protocol */ + ETHTYPE_MRP = 0x88E3U, + /** Precision time protocol */ + ETHTYPE_PTP = 0x88F7U, + /** Q-in-Q, 802.1ad */ + ETHTYPE_QINQ = 0x9100U }; #ifdef __cplusplus diff --git a/srcs/lwip/src/include/lwip/qinq.h b/srcs/lwip/src/include/lwip/qinq.h index b6cc80c..4edd02e 100644 --- a/srcs/lwip/src/include/lwip/qinq.h +++ b/srcs/lwip/src/include/lwip/qinq.h @@ -9,6 +9,8 @@ #include "lwip/arch.h" +#define QINQ_802_1_AD (0x8100) + #ifdef __cplusplus extern "C" { #endif diff --git a/srcs/lwip/src/include/lwip/vxlan.h b/srcs/lwip/src/include/lwip/vxlan.h index 48a43e8..aa2efef 100644 --- a/srcs/lwip/src/include/lwip/vxlan.h +++ b/srcs/lwip/src/include/lwip/vxlan.h @@ -17,6 +17,8 @@ extern "C" { #endif +#define VXLAN_UDP_PORT (4789) + typedef struct eth_hdr eth_hdr_t; typedef struct ip_hdr ip_hdr_t; typedef struct udp_hdr udp_hdr_t; @@ -26,6 +28,8 @@ typedef struct qinq_hdr qinq_hdr_t; #define VXLAN_VIN_ID(x) ((x) >> 8) #define VXLAN_VIN_ID_PACK(x) ((x) << 8) +#define VXLAN_HEAD_SIZE (sizeof(struct vxlan_package)) + PACK_STRUCT_BEGIN struct vxlan_hdr { PACK_STRUCT_FLD_8(u8_t flags); diff --git a/srcs/pppoe/vcpe_pppoe.c b/srcs/pppoe/vcpe_pppoe.c index 6728c3f..844bb1c 100644 --- a/srcs/pppoe/vcpe_pppoe.c +++ b/srcs/pppoe/vcpe_pppoe.c @@ -16,6 +16,7 @@ #include "netif/ppp/pppapi.h" #include "config.h" #include "msg_queue.h" +#include "vxlan_pkg.h" typedef struct PPPOE_CACHE { PPPPOE_SESSION_DATA pSessionData; @@ -145,6 +146,7 @@ _Noreturn void sessionCalcCb(void *UNUSED(pArg)) { 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); + vxlan_peer_add(pUser->vxlan.vni, config_get_vxlan_peer_ip(), config_get_vxlan_peer_mac()); pSession->status = STATUS_TASK_DIAL; } break; @@ -257,7 +259,7 @@ int pppoe_session_init() { static uv_thread_t uvThread, cacheThread; uv_rwlock_init(&g_cacheLock); - g_rawSocketIf = bind_rawsocket_if(config_get_nic_name()); + g_rawSocketIf = bind_rawsocket_if(config_get_vxlan_nic_name()); if (g_rawSocketIf) { dzlog_info("Create Raw Socket netif: <%p>\n", (void *)g_rawSocketIf);