parent
af1f02d99d
commit
538356cdec
|
@ -14,7 +14,7 @@ if ("${GIT_TAG}" STREQUAL "")
|
|||
else ()
|
||||
STRING(REGEX REPLACE "\n$" "" GIT_TAG ${GIT_TAG})
|
||||
endif ()
|
||||
#
|
||||
|
||||
|
||||
MESSAGE("Version: " ${GIT_TAG})
|
||||
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
}
|
|
@ -481,8 +481,11 @@ 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"); \
|
||||
/* 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) {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/sendfile.h>
|
||||
#include <linux/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
#include "user_errno.h"
|
||||
#include "misc.h"
|
||||
|
@ -150,3 +153,83 @@ 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;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
// 设置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;
|
||||
}
|
|
@ -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
|
|
@ -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 <linux/if.h>
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -72,6 +72,8 @@ enum lwip_ieee_eth_type {
|
|||
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 */
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#define QINQ_802_1_AD (0x8100)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue