REM:
1. vxlan移除自动学习vxLan头功能,发送数据包时自动构建头部
This commit is contained in:
huangxin 2022-06-10 17:03:27 +08:00
parent af1f02d99d
commit 538356cdec
17 changed files with 617 additions and 50 deletions

View File

@ -14,7 +14,7 @@ if ("${GIT_TAG}" STREQUAL "")
else () else ()
STRING(REGEX REPLACE "\n$" "" GIT_TAG ${GIT_TAG}) STRING(REGEX REPLACE "\n$" "" GIT_TAG ${GIT_TAG})
endif () endif ()
#
MESSAGE("Version: " ${GIT_TAG}) MESSAGE("Version: " ${GIT_TAG})

View File

@ -48,11 +48,20 @@ application:
agent_port = 6279; # Agetn 通信端口 agent_port = 6279; # Agetn 通信端口
}; };
# 网络相关 # vxlan 相关
network: vxlan:
{ {
nic_card = "ens36"; # 收发数据使用的网卡名称 vxlan_enable = true; # 是否启动vxLan隧道封装
nic_mac = "00:0C:01:02:00:01"; # 收发数据使用的网卡Mac地址 vxlan_nic = "ens36"; # vxlan 物理网卡名称
vxlan_support = true; # 是否支持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";
} }
} }

View File

@ -481,8 +481,11 @@ do {
/* ZeroMq配置 */ \ /* 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_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_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"); \ /* vxLan 隧道配置 */ \
ADD_CFG_ITEM(CFG_VXLAN_SUPPORT, "application.network.vxlan_support", VALUE_TYPE_BOOL, "1", "Is support vxLan tune"); \ 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 } while (0)// clang-format on
int init_config_system(const char *pCfgFile, const char *pKey) { int init_config_system(const char *pCfgFile, const char *pKey) {

View File

@ -3,8 +3,16 @@
// //
#include "config.h" #include "config.h"
const char* config_get_nic_name() { const char*config_get_vxlan_nic_name() {
return cfg_get_string_value(CFG_NIC_CARD_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() { int cfg_get_support_vxlan() {

View File

@ -42,9 +42,10 @@ typedef enum {
CFG_DB_MYSQL_DB_NAME = 20, CFG_DB_MYSQL_DB_NAME = 20,
CFG_MQ_SVR_PORT = 21, CFG_MQ_SVR_PORT = 21,
CFG_MQ_DATA_CH = 22, CFG_MQ_DATA_CH = 22,
CFG_NIC_CARD_NAME = 23, CFG_VXLAN_NIC_NAME = 23,
CFG_VXLAN_SUPPORT = 24, CFG_VXLAN_SUPPORT = 24,
CFG_VXLAN_PEER_IP = 25,
CFG_VXLAN_PEER_MAC = 26,
CONFIG_ITEM_ID_MAX CONFIG_ITEM_ID_MAX
} CONFIG_ITEM_ID; } 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_key(const char *pKeygen);
const char *get_config_keygen(); const char *get_config_keygen();
int cfg_get_support_vxlan(); 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 #ifdef __cplusplus
} }
#endif #endif

View File

@ -36,6 +36,9 @@ extern "C" {
#define FALSE (0) #define FALSE (0)
#endif #endif
#define VERIFY_STRING(s) (((s) != NULL) && (strlen(s) > 0))
#define PRINTABLE_STRING(s) ((s) == NULL ? "NULL" : (s))
int file_exists(const char *pPath); int file_exists(const char *pPath);
const char *basename_v2(const char *path); const char *basename_v2(const char *path);
int dirname_v2(const char *path, char *dir); 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); int copy_file(const char *pSrc, const char *pDest);
char *bin2hex(char *p, const unsigned char *cp, unsigned int count); char *bin2hex(char *p, const unsigned char *cp, unsigned int count);
int shell_with_output(const char *pCmd, char **pResult); 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 #ifdef __cplusplus
} }
#endif #endif

View File

@ -74,6 +74,13 @@ typedef enum {
ERR_CREATE_PPPOE_NETIF = 2501, ERR_CREATE_PPPOE_NETIF = 2501,
ERR_CREATE_PPP_SESSION = 2502, 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; } USER_ERRNO;
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -8,6 +8,9 @@
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/sendfile.h> #include <sys/sendfile.h>
#include <linux/if.h>
#include <sys/ioctl.h>
#include <linux/if_ether.h>
#include "user_errno.h" #include "user_errno.h"
#include "misc.h" #include "misc.h"
@ -150,3 +153,83 @@ const char *get_cur_process_dir() {
return (const char *)g_exePath; 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;
}

View File

@ -11,6 +11,7 @@
set(lwipcontribportunix_SRCS set(lwipcontribportunix_SRCS
${LWIP_DIR}/src/arch_linux/sys_arch.c ${LWIP_DIR}/src/arch_linux/sys_arch.c
${LWIP_DIR}/src/arch_linux/perf.c ${LWIP_DIR}/src/arch_linux/perf.c
${LWIP_DIR}/src/arch_linux/core/vxlan_pkg.c
) )
set(lwipcontribportunixnetifs_SRCS set(lwipcontribportunixnetifs_SRCS

View File

@ -0,0 +1,330 @@
//
// Created by xajhuang on 2022/6/9.
//
#include <uthash/uthash.h>
#include <zlog.h>
#include <uv.h>
#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);
// 设置IPUDP头部数据长度字段
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;
}

View File

@ -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

View File

@ -64,6 +64,7 @@
#include "user_info.h" #include "user_info.h"
#include "lwip/prot/ip.h" #include "lwip/prot/ip.h"
#include "lwip/inet_chksum.h" #include "lwip/inet_chksum.h"
#include "vxlan_pkg.h"
#if defined(LWIP_UNIX_LINUX) #if defined(LWIP_UNIX_LINUX)
#include <linux/if.h> #include <linux/if.h>
@ -78,6 +79,7 @@
#endif #endif
#define USED_ENUMER_VXLAN (0) #define USED_ENUMER_VXLAN (0)
#define AUTO_LEARN_VXLAN (0)
#define DEFAULT_GW_IPADDR (0xC0A80001) #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) { static err_t low_level_output(struct netif *netif, struct pbuf *p) {
unsigned char sndBuf[1518]; unsigned char sndBuf[1518];
unsigned char buf[1518]; /* max packet size including VLAN excluding CRC */ unsigned char buf[1518]; /* max packet size including VLAN excluding CRC */
ssize_t written; ssize_t written = 0;
struct sockaddr_ll dstAddr; struct sockaddr_ll dstAddr;
struct rawif *rawif = (struct rawif *)netif->state; struct rawif *rawif = (struct rawif *)netif->state;
PUSER_INFO_CONTEXT pUser = (PUSER_INFO_CONTEXT)p->extra; 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 // 网卡支持vxlan
if (rawif->vxlan_support) { if (rawif->vxlan_support) {
#if AUTO_LEARN_VXLAN
PVXLAN_BUF pvxlanBuf; PVXLAN_BUF pvxlanBuf;
uv_rwlock_rdlock(&rawif->lock_vxlan); uv_rwlock_rdlock(&rawif->lock_vxlan);
HASH_FIND_INT(rawif->pvxLan, &pUser->vxlan.vni, pvxlanBuf); HASH_FIND_INT(rawif->pvxLan, &pUser->vxlan.vni, pvxlanBuf);
uv_rwlock_rdunlock(&rawif->lock_vxlan); uv_rwlock_rdunlock(&rawif->lock_vxlan);
if (pvxlanBuf) { if (pvxlanBuf) {
unsigned short checksum; unsigned short checksum;
unsigned int dataSize = p->tot_len - sizeof(struct eth_hdr); unsigned int dataSize = p->tot_len - sizeof(struct eth_hdr);
struct eth_hdr *eth = (struct eth_hdr *)buf; 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)); 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)); 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; return written == (total_len) ? ERR_OK : ERR_IF;
} else { } else {
/* signal that packet should be sent(); */ /* signal that packet should be sent(); */
written = sendto(rawif->fd, buf, p->tot_len, 0, (struct sockaddr *)&dstAddr, sizeof(dstAddr)); 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 { } else {
/* signal that packet should be sent(); */ /* signal that packet should be sent(); */
written = sendto(rawif->fd, buf, p->tot_len, 0, (struct sockaddr *)&dstAddr, sizeof(dstAddr)); written = sendto(rawif->fd, buf, p->tot_len, 0, (struct sockaddr *)&dstAddr, sizeof(dstAddr));
@ -543,6 +583,7 @@ static err_t netif_input_data(struct pbuf *p, struct netif *inp) {
// UDP xvLan 数据包 // UDP xvLan 数据包
if (is_vxlan_package((const unsigned char *)p->payload)) { if (is_vxlan_package((const unsigned char *)p->payload)) {
#if AUTO_LEARN_VXLAN
VXLAN_TAG tag; VXLAN_TAG tag;
PUSER_INFO_CONTEXT pContext; PUSER_INFO_CONTEXT pContext;
PVXLAN_BUF pvxlanBuf; PVXLAN_BUF pvxlanBuf;
@ -650,6 +691,42 @@ static err_t netif_input_data(struct pbuf *p, struct netif *inp) {
} else { } else {
dzlog_error("Not found: %u, %u, %u\n", tag.vni, tag.q1, tag.q2); 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 { } else {
NETIF_FOREACH(netif) { NETIF_FOREACH(netif) {
@ -685,6 +762,11 @@ struct netif *bind_rawsocket_if(const char *eth_name) {
rawif->eth_name = 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(&gw);
ip4_addr_set_zero(&ipaddr); ip4_addr_set_zero(&ipaddr);
ip4_addr_set_zero(&netmask); ip4_addr_set_zero(&netmask);

View File

@ -44,6 +44,10 @@
extern "C" { extern "C" {
#endif #endif
#ifndef ETH_NAME_MAX
#define ETH_NAME_MAX 32
#endif
#ifndef ETH_HWADDR_LEN #ifndef ETH_HWADDR_LEN
#ifdef ETHARP_HWADDR_LEN #ifdef ETHARP_HWADDR_LEN
#define ETH_HWADDR_LEN ETHARP_HWADDR_LEN /* compatibility mode */ #define ETH_HWADDR_LEN ETHARP_HWADDR_LEN /* compatibility mode */

View File

@ -72,6 +72,8 @@ enum lwip_ieee_eth_type {
ETHTYPE_PROFINET = 0x8892U, ETHTYPE_PROFINET = 0x8892U,
/** Ethernet for control automation technology */ /** Ethernet for control automation technology */
ETHTYPE_ETHERCAT = 0x88A4U, ETHTYPE_ETHERCAT = 0x88A4U,
/** Q-in-Q 802.1ad provider bridge network */
ETHTYPE_QINQ_BRG = 0x88A8U,
/** Link layer discovery protocol */ /** Link layer discovery protocol */
ETHTYPE_LLDP = 0x88CCU, ETHTYPE_LLDP = 0x88CCU,
/** Serial real-time communication system */ /** Serial real-time communication system */

View File

@ -9,6 +9,8 @@
#include "lwip/arch.h" #include "lwip/arch.h"
#define QINQ_802_1_AD (0x8100)
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif

View File

@ -17,6 +17,8 @@
extern "C" { extern "C" {
#endif #endif
#define VXLAN_UDP_PORT (4789)
typedef struct eth_hdr eth_hdr_t; typedef struct eth_hdr eth_hdr_t;
typedef struct ip_hdr ip_hdr_t; typedef struct ip_hdr ip_hdr_t;
typedef struct udp_hdr udp_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(x) ((x) >> 8)
#define VXLAN_VIN_ID_PACK(x) ((x) << 8) #define VXLAN_VIN_ID_PACK(x) ((x) << 8)
#define VXLAN_HEAD_SIZE (sizeof(struct vxlan_package))
PACK_STRUCT_BEGIN PACK_STRUCT_BEGIN
struct vxlan_hdr { struct vxlan_hdr {
PACK_STRUCT_FLD_8(u8_t flags); PACK_STRUCT_FLD_8(u8_t flags);

View File

@ -16,6 +16,7 @@
#include "netif/ppp/pppapi.h" #include "netif/ppp/pppapi.h"
#include "config.h" #include "config.h"
#include "msg_queue.h" #include "msg_queue.h"
#include "vxlan_pkg.h"
typedef struct PPPOE_CACHE { typedef struct PPPOE_CACHE {
PPPPOE_SESSION_DATA pSessionData; PPPPOE_SESSION_DATA pSessionData;
@ -145,6 +146,7 @@ _Noreturn void sessionCalcCb(void *UNUSED(pArg)) {
case STATUS_TASK_INIT: case STATUS_TASK_INIT:
if (pppoe_session_create(pUser) == ERR_SUCCESS) { if (pppoe_session_create(pUser) == ERR_SUCCESS) {
dzlog_debug("User(%05d:%s) init pppoe session\n", pUser->userid, pUser->user_info.pppoe_user); 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; pSession->status = STATUS_TASK_DIAL;
} }
break; break;
@ -257,7 +259,7 @@ int pppoe_session_init() {
static uv_thread_t uvThread, cacheThread; static uv_thread_t uvThread, cacheThread;
uv_rwlock_init(&g_cacheLock); 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) { if (g_rawSocketIf) {
dzlog_info("Create Raw Socket netif: <%p>\n", (void *)g_rawSocketIf); dzlog_info("Create Raw Socket netif: <%p>\n", (void *)g_rawSocketIf);