REM:
1. 增加VXLan Hash查找用户功能
2. 增加获取BASE服务器PPPoE服务端MAC地址功能
3. LWIP支持vxLan数据包收发功能
4. LWIP支持QinQ数据包解析与收发功能
This commit is contained in:
huangxin 2022-06-07 11:29:05 +08:00
parent a3644c46aa
commit b1bcff4d96
13 changed files with 313 additions and 31 deletions

2
.gitignore vendored
View File

@ -1,3 +1,5 @@
/cmake-build-debug/
/.idea/
*/__init__.py
/cmake-build-debug-ubuntuefc/
/cmake-build-debug-vswith_dev/

View File

@ -42,7 +42,7 @@ typedef struct {
char clientGw[MAX_IP_V4_STR];
char clientMask[MAX_IP_V4_STR];
char clientMac[MAX_MAC_ADDR_STR];
char localMac[MAX_MAC_ADDR_STR];
char svrBaseMac[MAX_MAC_ADDR_STR];
} PPPOE_SESSION_DATA, *PPPPOE_SESSION_DATA;
typedef struct {

View File

@ -16,8 +16,9 @@ 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_CONTEXT pInfo, USER_STATUS status);
PUSER_INFO_CONTEXT get_all_user();
uv_rwlock_t* get_user_lock();
PUSER_INFO_CONTEXT get_all_user_by_id();
PUSER_INFO_CONTEXT get_all_user_by_tag();
uv_rwlock_t *get_user_lock();
#ifdef __cplusplus
}
#endif

View File

@ -11,6 +11,7 @@
#include "config.h"
#include "user_errno.h"
#include "misc.h"
#include "task_manager.h"
static void *g_pDataCh = NULL;
static DATACHNNELCB g_pDataChCb = NULL;
@ -45,7 +46,7 @@ int mq_data_send_msg(const char *pMsg) {
zmq_msg_t msg;
if (pMsg) {
dzlog_debug("Send PPPoE Session:\n%s\n", pMsg);
dzlog_debug("Send PPPoE Session: %s\n", pMsg);
zmq_msg_init_size(&msg, strlen(pMsg) + 1);
memcpy(zmq_msg_data(&msg), pMsg, strlen(pMsg));
zmq_msg_send(&msg, g_pDataCh, 0);

View File

@ -425,6 +425,9 @@
#define PPPOE_SUPPORT 1
#define PPPOS_SUPPORT 0
#define VXLAN_SUPPORT 1
#define QINQ_SUPPORT 1
/*
---------------------------------------
---------- Threading options ----------
@ -448,6 +451,8 @@
#define MEMP_NUM_PPPOE_INTERFACES (10)
#define LWIP_PBUF_CUSTOM_DATA void* extra;
#if !NO_SYS
void sys_check_core_locking(void);
#define LWIP_ASSERT_CORE_LOCKED() sys_check_core_locking()

View File

@ -125,8 +125,8 @@ static void low_level_init(struct netif *netif) {
/*-----------------------------------------------------------------------------------*/
static err_t low_level_output(struct netif *netif, struct pbuf *p) {
LWIP_UNUSED_ARG(netif);
struct netif *rs_if = get_rawsocket_if();
p->extra = netif->state;
return rawif_output(rs_if, p);
}

View File

@ -44,6 +44,8 @@
#include "lwip/tcpip.h"
#include "lwip/debug.h"
#include "lwip/def.h"
#include "lwip/vxlan.h"
#include "lwip/qinq.h"
#include "lwip/mem.h"
@ -57,6 +59,10 @@
#include "lwip/prot/udp.h"
#include "config.h"
#include "pppoe_info.h"
#include "user_info.h"
#include "lwip/prot/ip.h"
#include "lwip/inet_chksum.h"
#if defined(LWIP_UNIX_LINUX)
#include <linux/if.h>
@ -116,8 +122,6 @@ 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));
@ -199,12 +203,41 @@ static void low_level_init(struct netif *netif) {
*
*/
/*-----------------------------------------------------------------------------------*/
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;
}
static err_t low_level_output(struct netif *netif, struct pbuf *p) {
char buf[1518]; /* max packet size including VLAN excluding CRC */
unsigned char sndBuf[1518];
unsigned char buf[1518]; /* max packet size including VLAN excluding CRC */
ssize_t written;
struct sockaddr_ll dstAddr;
struct rawif *rawif = (struct rawif *)netif->state;
PUSER_INFO_CONTEXT pUser = (PUSER_INFO_CONTEXT)p->extra;
if (p->tot_len > sizeof(buf)) {
MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
@ -219,6 +252,45 @@ static err_t low_level_output(struct netif *netif, struct pbuf *p) {
dstAddr.sll_ifindex = rawif->if_index;
dstAddr.sll_family = PF_PACKET;
// 网卡支持vxlan
if (rawif->vxlan_support && rawif->vxlan_buf.output_head) {
unsigned short checksum = 0;
int dataSize = p->tot_len - sizeof(struct eth_hdr);
struct eth_hdr *eth = (struct eth_hdr *)buf;
struct vxlan_package *pkg = (struct vxlan_package *)sndBuf;
unsigned short udp_len = p->tot_len + sizeof(struct vxlan_hdr) + sizeof(struct qinq_hdr);
unsigned short ip_len = udp_len + 20;
memcpy(sndBuf, rawif->vxlan_buf.output_head, sizeof(struct vxlan_package));
pkg->vxlan_head.vni_reserved = lwip_htonl(VXLAN_VIN_ID_PACK(pUser->vxlan.vni));
memcpy(pkg->eth_pkg.dest.addr, eth->dest.addr, ETH_HWADDR_LEN);
memcpy(pkg->eth_pkg.src.addr, eth->src.addr, ETH_HWADDR_LEN);
pkg->qinq_head.out_priority_cfi_and_id = lwip_htons(pUser->vxlan.q1);
pkg->qinq_head.in_priority_cfi_and_id = lwip_htons(pUser->vxlan.q2);
pkg->qinq_head.origin_type = eth->type;
memcpy(pkg->data, &buf[sizeof(struct eth_hdr)], dataSize);
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(sndBuf, ip_len + sizeof(struct eth_hdr));
pkg->udp_head.chksum = lwip_htons(checksum);
IPH_CHKSUM_SET(&pkg->ip_head, inet_chksum(&pkg->ip_head, 20));
#if 0
written = sendto(rawif->fd,
sndBuf,
pkg->ip_head._len + sizeof(struct eth_hdr),
0,
(struct sockaddr *)&dstAddr,
sizeof(dstAddr));
#endif
}
/* signal that packet should be sent(); */
written = sendto(rawif->fd, buf, p->tot_len, 0, (struct sockaddr *)&dstAddr, sizeof(dstAddr));
@ -252,7 +324,7 @@ static struct pbuf *low_level_input(struct netif *netif) {
int addrSize;
ssize_t readlen;
unsigned char bmac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
unsigned char buf[1518]; /* max packet size including VLAN excluding CRC */
unsigned char buf[1518] = {0}; /* max packet size including VLAN excluding CRC */
struct sockaddr from;
struct rawif *rawif = (struct rawif *)netif->state;
@ -407,32 +479,125 @@ static void link_callback(struct netif *state_netif) {
#endif /* LWIP_NETIF_LINK_CALLBACK */
static err_t netif_input_data(struct pbuf *p, struct netif *inp) {
struct netif *netif;
struct rawif *rawif = (struct rawif *)inp->state;
unsigned char buf[1500];
unsigned char *payload = (unsigned char *)p->payload;
err_t err;
//struct netif *netif;
const unsigned char buf_test[] = {
0x00, 0x0c, 0x29, 0x07, 0xcb, 0x55, 0x00, 0x0c, 0x29, 0x49, 0xcb, 0x27, 0x08, 0x00, 0x45, 0x00, 0x00, 0x4a,
0x00, 0x00, 0x00, 0x00, 0xfd, 0x11, 0x13, 0x6f, 0xc0, 0xa8, 0x14, 0x70, 0xc0, 0xa8, 0x14, 0x73, 0x67, 0x3b,
0x12, 0xb5, 0x00, 0x36, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x5a, 0xfd, 0x0e, 0xac,
0x3e, 0x95, 0x5a, 0x17, 0xaf, 0x64, 0xe8, 0xba, 0x88, 0xa8, 0x00, 0x18, 0x81, 0x00, 0x01, 0x73, 0x88, 0x64,
0x11, 0x00, 0x00, 0x02, 0x00, 0x0a, 0xc0, 0x21, 0x09, 0xfc, 0x00, 0x08, 0x66, 0x33, 0x48, 0x73};
struct rawif *rawif = (struct rawif *)inp->state;
//unsigned char buf[1500];
const unsigned char *pBuf = (const unsigned char *)p->payload;
const unsigned char *payload = buf_test;
LWIP_ASSERT_CORE_LOCKED();
// 网卡支持vxlan
if (rawif->vxlan_support) {
const struct eth_hdr *ethhdr = (const struct eth_hdr *)payload;
const struct ip_hdr *iphdr = (const struct ip_hdr *)(payload + SIZEOF_ETH_HDR);
const struct udp_hdr *udphdr = (const struct udp_hdr *)(payload + SIZEOF_ETH_HDR + IPH_HL_BYTES(iphdr));
const struct vxlan_package *pkg = (const struct vxlan_package *)payload;
// UDP xvLan 数据包
if (udphdr->dest == VXLAN_PORT_NET_ORDER) {
if (pkg->ip_head._proto == IP_PROTO_UDP && lwip_ntohs(pkg->udp_head.dest) == VXLAN_PORT_NET_ORDER) {
VXLAN_TAG tag;
PUSER_INFO_CONTEXT pContext;
// 首包
if (rawif->vxlan_buf.input_head == NULL) {
// 缓存第一包头部数据
rawif->vxlan_buf.input_head = (unsigned char *)mem_malloc(sizeof(struct vxlan_package));
if (rawif->vxlan_buf.input_head) {
memcpy(rawif->vxlan_buf.input_head, payload, sizeof(struct vxlan_package));
}
//hdzlog_debug(rawif->vxlan_buf.input_head, sizeof(struct vxlan_package));
}
// 学习vxLan相关内容
if (rawif->vxlan_buf.output_head == NULL) {
unsigned char *pOutBuf = (unsigned char *)mem_malloc(sizeof(struct vxlan_package));
// 缓存第一包头部数据
if (pOutBuf) {
struct vxlan_package *vxlanHead = (struct vxlan_package *)pOutBuf;
memset(pOutBuf, 0, sizeof(struct vxlan_package));
// ETH 头部
memcpy(vxlanHead->eth_head.src.addr, pkg->eth_head.dest.addr, ETH_HWADDR_LEN);
memcpy(vxlanHead->eth_head.dest.addr, pkg->eth_head.src.addr, ETH_HWADDR_LEN);
vxlanHead->eth_head.type = pkg->eth_head.type;
// IP 头部
vxlanHead->ip_head._v_hl = pkg->ip_head._v_hl;
vxlanHead->ip_head._tos = pkg->ip_head._tos;
vxlanHead->ip_head._ttl = 64;
vxlanHead->ip_head._proto = IP_PROTO_UDP;
vxlanHead->ip_head.src.addr = pkg->ip_head.dest.addr;
vxlanHead->ip_head.dest.addr = pkg->ip_head.src.addr;
// UDP 头部
vxlanHead->udp_head.src = lwip_htons(4789);
vxlanHead->udp_head.dest = lwip_htons(4789);
// vxlan 头部
vxlanHead->vxlan_head.flags = pkg->vxlan_head.flags;
// inside ETH 头部
vxlanHead->eth_pkg.type = pkg->eth_pkg.type;
// QinQ 头部
vxlanHead->qinq_head.in_type = pkg->qinq_head.in_type;
rawif->vxlan_buf.output_head = pOutBuf;
}
}
if (pBuf[4] == 0 && pBuf[5] == 0x02) {
tag.vni = 300;//VXLAN_VIN_ID(lwip_htonl(pkg->vxlan_head.vni_reserved));
tag.q1 = 16; //lwip_ntohs(pkg->qinq_head.out_priority_cfi_and_id);
tag.q2 = 12; //lwip_ntohs(pkg->qinq_head.in_priority_cfi_and_id);
} else if (pBuf[4] == 0 && pBuf[5] == 0x03) {
tag.vni = 400;//VXLAN_VIN_ID(lwip_htonl(pkg->vxlan_head.vni_reserved));
tag.q1 = 24; //lwip_ntohs(pkg->qinq_head.out_priority_cfi_and_id);
tag.q2 = 371;//lwip_ntohs(pkg->qinq_head.in_priority_cfi_and_id);
} else if (pBuf[4] == 0 && pBuf[5] == 0x04) {
tag.vni = 300;//VXLAN_VIN_ID(lwip_htonl(pkg->vxlan_head.vni_reserved));
tag.q1 = 14; //lwip_ntohs(pkg->qinq_head.out_priority_cfi_and_id);
tag.q2 = 15; //lwip_ntohs(pkg->qinq_head.in_priority_cfi_and_id);
} else {
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]);
}
if ((err = pContext->session.nicif->input(p, pContext->session.nicif)) != ERR_OK) {
LWIP_DEBUGF(NETIF_DEBUG, ("pppoeif_input: netif input error\n"));
pbuf_free(p);
}
return err;
}
}
}
#if 0
NETIF_FOREACH(netif) {
err_t err;
unsigned char *pMac = (unsigned char *)p->payload;
if (netif->hwaddr_len == 6 && memcmp(pMac, netif->hwaddr, netif->hwaddr_len) == 0) {
@ -452,6 +617,7 @@ static err_t netif_input_data(struct pbuf *p, struct netif *inp) {
return err;
}
}
#endif
return tcpip_input(p, inp);
}

View File

@ -750,7 +750,12 @@ 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);
//LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
if(p->ref == 0) {
return 0;
}
/* decrease reference count (number of pointers to pbuf) */
ref = --(p->ref);
SYS_ARCH_UNPROTECT(old_level);

View File

@ -1897,6 +1897,14 @@
#define LWIP_NETCONN 1
#endif
#if !defined VXLAN_SUPPORT || defined __DOXYGEN__
#define VXLAN_SUPPORT 0
#endif
#if !defined QINQ_SUPPORT || defined __DOXYGEN__
#define QINQ_SUPPORT 0
#endif
/** LWIP_TCPIP_TIMEOUT==1: Enable tcpip_timeout/tcpip_untimeout to create
* timers running in tcpip_thread from another thread.
*/

View File

@ -0,0 +1,30 @@
//
// Created by xajhuang on 2022/6/6.
//
#ifndef VCPE_PROJECT_QINQ_H
#define VCPE_PROJECT_QINQ_H
#if QINQ_SUPPORT
#include "lwip/arch.h"
#ifdef __cplusplus
extern "C" {
#endif
PACK_STRUCT_BEGIN
struct qinq_hdr {
PACK_STRUCT_FIELD(u16_t out_priority_cfi_and_id);
/* inner type for qinq, 0x8100*/
PACK_STRUCT_FIELD(u16_t in_type);
PACK_STRUCT_FIELD(u16_t in_priority_cfi_and_id);
/* out type for origin, like IP、ARP*/
PACK_STRUCT_FIELD(u16_t origin_type);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef __cplusplus
}
#endif
#endif // QINQ_SUPPORT
#endif//VCPE_PROJECT_QINQ_H

View File

@ -0,0 +1,57 @@
//
// Created by xajhuang on 2022/6/6.
//
#ifndef VCPE_PROJECT_VXLAN_H
#define VCPE_PROJECT_VXLAN_H
#if VXLAN_SUPPORT
#include "lwip/arch.h"
#include "lwip/prot/ethernet.h"
#include "lwip/prot/ip4.h"
#include "lwip/prot/udp.h"
#include "qinq.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct eth_hdr eth_hdr_t;
typedef struct ip_hdr ip_hdr_t;
typedef struct udp_hdr udp_hdr_t;
typedef struct vxlan_hdr vxlan_hdr_t;
typedef struct qinq_hdr qinq_hdr_t;
#define VXLAN_VIN_ID(x) ((x) >> 8)
#define VXLAN_VIN_ID_PACK(x) ((x) << 8)
PACK_STRUCT_BEGIN
struct vxlan_hdr {
PACK_STRUCT_FLD_8(u8_t flags);
PACK_STRUCT_FLD_8(u8_t res1);
PACK_STRUCT_FLD_8(u8_t res2);
PACK_STRUCT_FLD_8(u8_t res3);
PACK_STRUCT_FIELD(u32_t vni_reserved);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
PACK_STRUCT_BEGIN
struct vxlan_package {
PACK_STRUCT_FLD_S(eth_hdr_t eth_head);
PACK_STRUCT_FLD_S(ip_hdr_t ip_head);
PACK_STRUCT_FLD_S(udp_hdr_t udp_head);
PACK_STRUCT_FLD_S(vxlan_hdr_t vxlan_head);
PACK_STRUCT_FLD_S(eth_hdr_t eth_pkg);
#if QINQ_SUPPORT
PACK_STRUCT_FLD_S(qinq_hdr_t qinq_head);
#endif
char data[];
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef __cplusplus
}
#endif
#endif//VXLAN_SUPPORT
#endif//VCPE_PROJECT_VXLAN_H

View File

@ -133,7 +133,7 @@ static void pppLinkStatusCallback(ppp_pcb *pcb, int errCode, void *ctx) {
}
_Noreturn void sessionCalcCb(void *UNUSED(pArg)) {
PUSER_INFO_CONTEXT pUserList = get_all_user();
PUSER_INFO_CONTEXT pUserList = get_all_user_by_id();
do {
PUSER_INFO_CONTEXT pUser, pTmp;
@ -223,8 +223,9 @@ _Noreturn void cacheCalcCb(void *UNUSED(pArg)) {
uv_rwlock_rdunlock(&g_cacheLock);
if (count > 0) {
cJSON *pRoot = cJSON_CreateObject();
cJSON *pSession = cJSON_CreateArray();
const char *pJsonString;
cJSON *pRoot = cJSON_CreateObject();
cJSON *pSession = cJSON_CreateArray();
cJSON_AddStringToObject(pRoot, "message", "add-ywg-pppoe");
uv_rwlock_wrlock(&g_cacheLock);
@ -235,15 +236,17 @@ _Noreturn void cacheCalcCb(void *UNUSED(pArg)) {
cJSON_AddStringToObject(pItem, "clientGw", pCache->pSessionData->clientGw);
cJSON_AddStringToObject(pItem, "clientMask", pCache->pSessionData->clientMask);
cJSON_AddStringToObject(pItem, "clientMac", pCache->pSessionData->clientMac);
cJSON_AddStringToObject(pItem, "localMac", pCache->pSessionData->localMac);
cJSON_AddStringToObject(pItem, "localMac", pCache->pSessionData->svrBaseMac);
cJSON_AddItemToArray(pSession, pItem);
LL_DELETE(g_pPPPCache, pCache);
free(pCache);
}
uv_rwlock_wrunlock(&g_cacheLock);
cJSON_AddItemToObject(pRoot, "params", pSession);
mq_data_send_msg(cJSON_Print(pRoot));
pJsonString = cJSON_PrintUnformatted(pRoot);
mq_data_send_msg(pJsonString);
cJSON_Delete(pRoot);
free((void*)pJsonString);
}
uv_sleep(1000);

View File

@ -10,9 +10,9 @@ static PUSER_INFO_CONTEXT g_pUserByTagsList = NULL;
static uv_rwlock_t g_userLock;
static USER_PARAMS g_userInfo[] = {
{0, 100, 16, 12, {0x00, 0x0C, 0x01, 0x02, 0x00, 0x02}, "xajhuang3", "aaaHuang1"},
{1, 200, 24, 371, {0x00, 0x0C, 0x01, 0x02, 0x00, 0x03}, "xajhuang1", "aaaHuang1"},
{2, 300, 14, 15, {0x00, 0x0C, 0x01, 0x02, 0x00, 0x04}, "xajhuang2", "aaaHuang1"},
{0, 300, 16, 12, {0x00, 0x0C, 0x01, 0x02, 0x00, 0x02}, "xajhuang3", "aaaHuang1"},
{1, 400, 24, 371, {0x00, 0x0C, 0x01, 0x02, 0x00, 0x03}, "xajhuang2", "aaaHuang1"},
{2, 300, 14, 15, {0x00, 0x0C, 0x01, 0x02, 0x00, 0x04}, "xajhuang1", "aaaHuang1"},
};
void user_info_init() {
@ -141,10 +141,14 @@ PUSER_INFO user_info_get_by_userid(unsigned int userid) {
return NULL;
}
PUSER_INFO_CONTEXT get_all_user() {
PUSER_INFO_CONTEXT get_all_user_by_id() {
return g_pUserByIdList;
}
PUSER_INFO_CONTEXT get_all_user_by_tag() {
return g_pUserByTagsList;
}
uv_rwlock_t *get_user_lock() {
return &g_userLock;
}