TSG-20717 Service Chaining增加全局链路号以支持无历史状态发包

This commit is contained in:
luwenpeng
2024-04-20 11:40:00 +08:00
parent 6b03470739
commit a0f1eca0ce
25 changed files with 314 additions and 109 deletions

View File

@@ -12,7 +12,9 @@ extern "C"
#include "tuple.h"
/*
* VXLAN Header:
******************************************************************************
* Standard VXLAN Header:
******************************************************************************
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@@ -28,87 +30,123 @@ extern "C"
* to zero on transmission and ignored on receipt.
* Reserved fields (24 bits and 8 bits):
* MUST be set to zero on transmission and ignored on receipt.
*
******************************************************************************
* SCE VXLAN Header:
******************************************************************************
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |R|R|R|R|I|R|R|R| Reserved |S| Traffic Link ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | high | type | low |D|T|SF index |T| Reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Flags : 8 bits
* Reserved : 7 bits
* S (StateLess) : 1 bit
*
* Traffic Link ID : 16 bits
*
* vlan_id_half_high : 8 bits
* link_layer_type : 4 bits // 二层报文封装格式
* vlan_id_half_low : 4 bits
*
* dir : 1 bit
* traffic : 1 bit
* sf_index : 5 bits // max value 32
* online_test : 1 bit
*
* Reserved : 8 bit
*/
struct vxlan_hdr
{
uint8_t flags;
uint8_t reserved[3];
// VNI 3 Bytes
uint8_t vlan_id_half_high;
uint8_t link_layer_type : 4; // 二层报文封装格式
uint8_t vlan_id_half_low : 4;
uint8_t dir : 1;
uint8_t traffic : 1;
uint8_t sf_index : 5; // max value 32
uint8_t online_test : 1;
// Reserved 1 Bytes
uint8_t r7 : 1;
uint8_t r6 : 1;
uint8_t r5 : 1;
uint8_t r4 : 1;
uint8_t vni_flag : 1;
uint8_t r2 : 1;
uint8_t r1 : 1;
uint8_t r0 : 1;
uint16_t flags_reserved;
uint16_t link_id;
uint16_t vlan_id;
uint16_t user_ctx;
} __attribute__((__packed__));
enum vni_opt
{
VNI_OPT_DIR = 0x80,
VNI_OPT_TRAFFIC = 0x40,
VNI_OPT_SFINDEX = 0x3f,
};
#define VXLAN_FLAGS 0x8
#define VXLAN_DEFAULT_FLAGS 0x8
#define VXLAN_DST_PORT 4789
#define VXLAN_FRAME_HDR_LEN (sizeof(struct ethhdr) + sizeof(struct ip) + sizeof(struct udphdr) + sizeof(struct vxlan_hdr))
#define VXLAN_FRAME_HDR_LEN ((int)(sizeof(struct ethhdr) + sizeof(struct ip) + sizeof(struct udphdr) + sizeof(struct vxlan_hdr)))
static inline void vxlan_set_opt(struct vxlan_hdr *hdr, enum vni_opt opt, uint8_t val)
#define VXLAN_FLAGS_MASK 0xFF00
#define VXLAN_STATELESS_MASK 0x0001
#define VXLAN_DIR_MASK 0x8000
#define VXLAN_TRAFFIC_MASK 0x4000
#define VXLAN_SF_INDEX_MASK 0x3E00
static inline void vxlan_set_flags(struct vxlan_hdr *hdr, uint8_t flags)
{
switch (opt)
{
case VNI_OPT_DIR:
hdr->dir = (!!val);
break;
case VNI_OPT_TRAFFIC:
hdr->traffic = (!!val);
break;
case VNI_OPT_SFINDEX:
hdr->sf_index = (0x1f & val);
break;
default:
break;
}
hdr->flags_reserved = htons((ntohs(hdr->flags_reserved) & ~VXLAN_FLAGS_MASK) | (flags << 8));
}
static inline uint8_t vxlan_get_opt(struct vxlan_hdr *hdr, enum vni_opt opt)
static inline void vxlan_set_dir(struct vxlan_hdr *hdr, uint8_t val)
{
switch (opt)
{
case VNI_OPT_DIR:
return hdr->dir;
case VNI_OPT_TRAFFIC:
return hdr->traffic;
case VNI_OPT_SFINDEX:
return hdr->sf_index;
default:
return 0;
}
hdr->user_ctx = htons((ntohs(hdr->user_ctx) & ~VXLAN_DIR_MASK) | ((!!val) << 15));
}
static inline void vxlan_set_traffic(struct vxlan_hdr *hdr, uint8_t val)
{
hdr->user_ctx = htons((ntohs(hdr->user_ctx) & ~VXLAN_TRAFFIC_MASK) | ((!!val) << 14));
}
static inline void vxlan_set_sf_index(struct vxlan_hdr *hdr, uint8_t val)
{
hdr->user_ctx = htons((ntohs(hdr->user_ctx) & ~VXLAN_SF_INDEX_MASK) | ((val & 0x1F) << 9));
}
static inline void vxlan_set_link_id(struct vxlan_hdr *hdr, uint16_t val)
{
hdr->link_id = htons(val);
}
static inline void vxlan_set_stateless(struct vxlan_hdr *hdr, uint8_t val)
{
hdr->flags_reserved = htons((ntohs(hdr->flags_reserved) & ~VXLAN_STATELESS_MASK) | (!!val));
}
static inline uint8_t vxlan_get_flags(struct vxlan_hdr *hdr)
{
return ((ntohs(hdr->flags_reserved) & VXLAN_FLAGS_MASK) >> 8);
}
static inline uint8_t vxlan_get_dir(struct vxlan_hdr *hdr)
{
return ((ntohs(hdr->user_ctx) & VXLAN_DIR_MASK) >> 15);
}
static inline uint8_t vxlan_get_traffic(struct vxlan_hdr *hdr)
{
return ((ntohs(hdr->user_ctx) & VXLAN_TRAFFIC_MASK) >> 14);
}
static inline uint8_t vxlan_get_sf_index(struct vxlan_hdr *hdr)
{
return ((ntohs(hdr->user_ctx) & VXLAN_SF_INDEX_MASK) >> 9);
}
static inline uint16_t vxlan_get_link_id(struct vxlan_hdr *hdr)
{
return ntohs(hdr->link_id);
}
static inline uint8_t vxlan_get_stateless(struct vxlan_hdr *hdr)
{
return ntohs(hdr->flags_reserved) & VXLAN_STATELESS_MASK;
}
// return 0 : success
// return -1 : error
int vxlan_frame_decode(struct vxlan_hdr **vxlan_hdr, const char *data, uint16_t len);
int vxlan_frame_decode(struct vxlan_hdr **vxlan_hdr, const char *data, int len);
void vxlan_frame_encode(char *buff,
const u_char eth_src_mac[], const u_char eth_dst_mac[],
const in_addr_t ip_src_addr, const in_addr_t ip_dst_addr, uint16_t ip_id,
uint16_t udp_src_port, uint16_t udp_pld_len,
uint8_t vni_opt_dir, uint8_t vni_opt_traffic, uint8_t vni_opt_sf_index);
uint8_t dir, uint8_t traffic, uint8_t sf_index, uint16_t link_id);
uint16_t calculate_vxlan_source_port(struct four_tuple *innermost_tuple4);

View File

@@ -69,7 +69,7 @@ static inline void udp_header_encode(struct udphdr *udp_hdr, uint16_t udp_sport,
// return 0 : success
// return -1 : error
int vxlan_frame_decode(struct vxlan_hdr **vxlan_hdr, const char *data, uint16_t len)
int vxlan_frame_decode(struct vxlan_hdr **vxlan_hdr, const char *data, int len)
{
if (len < VXLAN_FRAME_HDR_LEN)
{
@@ -103,7 +103,7 @@ void vxlan_frame_encode(char *buff,
const u_char eth_src_mac[], const u_char eth_dst_mac[],
const in_addr_t ip_src_addr, const in_addr_t ip_dst_addr, uint16_t ip_id,
uint16_t udp_src_port, uint16_t udp_pld_len,
uint8_t vni_opt_dir, uint8_t vni_opt_traffic, uint8_t vni_opt_sf_index)
uint8_t dir, uint8_t traffic, uint8_t sf_index, uint16_t link_id)
{
struct ethhdr *eth_hdr = (struct ethhdr *)buff;
struct ip *ip_hdr = (struct ip *)((char *)eth_hdr + sizeof(struct ethhdr));
@@ -112,10 +112,11 @@ void vxlan_frame_encode(char *buff,
// MUST be set to zero
memset(vxlan_hdr, 0, sizeof(struct vxlan_hdr));
vxlan_hdr->flags = VXLAN_FLAGS;
vxlan_set_opt(vxlan_hdr, VNI_OPT_DIR, vni_opt_dir);
vxlan_set_opt(vxlan_hdr, VNI_OPT_TRAFFIC, vni_opt_traffic);
vxlan_set_opt(vxlan_hdr, VNI_OPT_SFINDEX, vni_opt_sf_index);
vxlan_set_flags(vxlan_hdr, VXLAN_DEFAULT_FLAGS);
vxlan_set_dir(vxlan_hdr, dir);
vxlan_set_traffic(vxlan_hdr, traffic);
vxlan_set_sf_index(vxlan_hdr, sf_index);
vxlan_set_link_id(vxlan_hdr, link_id);
eth_header_encode(eth_hdr, eth_src_mac, eth_dst_mac, ETH_P_IP);
ip_header_encode(ip_hdr, ip_src_addr, ip_dst_addr, ip_id, IPPROTO_UDP, sizeof(struct udphdr) + sizeof(struct vxlan_hdr) + udp_pld_len);

View File

@@ -30,6 +30,14 @@ add_executable(gtest_utils gtest_utils.cpp)
target_include_directories(gtest_utils PUBLIC ${CMAKE_SOURCE_DIR}/common/include)
target_link_libraries(gtest_utils common gtest)
###############################################################################
# gtest_vxlan
###############################################################################
add_executable(gtest_vxlan gtest_vxlan.cpp)
target_include_directories(gtest_vxlan PUBLIC ${CMAKE_SOURCE_DIR}/common/include)
target_link_libraries(gtest_vxlan common gtest)
###############################################################################
# gtest_health_check_table
###############################################################################
@@ -47,4 +55,5 @@ gtest_discover_tests(gtest_session_table)
gtest_discover_tests(gtest_control_packet)
gtest_discover_tests(gtest_packet)
gtest_discover_tests(gtest_utils)
gtest_discover_tests(gtest_vxlan)
gtest_discover_tests(gtest_health_check_table)

View File

@@ -0,0 +1,84 @@
#include <gtest/gtest.h>
#include "vxlan.h"
static inline void hexdump(const char *data, int len)
{
for (int i = 0; i < len; i++)
{
printf("%02x ", data[i]);
}
printf("\n");
}
TEST(VXLAN, TEST1)
{
char buff[8] = {0};
struct vxlan_hdr *hdr = (struct vxlan_hdr *)buff;
vxlan_set_flags(hdr, VXLAN_DEFAULT_FLAGS);
vxlan_set_dir(hdr, 0);
vxlan_set_traffic(hdr, 0);
vxlan_set_sf_index(hdr, 0);
vxlan_set_link_id(hdr, 0);
vxlan_set_stateless(hdr, 0);
EXPECT_TRUE(vxlan_get_flags(hdr) == VXLAN_DEFAULT_FLAGS);
EXPECT_TRUE(vxlan_get_dir(hdr) == 0);
EXPECT_TRUE(vxlan_get_traffic(hdr) == 0);
EXPECT_TRUE(vxlan_get_sf_index(hdr) == 0);
EXPECT_TRUE(vxlan_get_link_id(hdr) == 0);
EXPECT_TRUE(vxlan_get_stateless(hdr) == 0);
hexdump(buff, 8);
}
TEST(VXLAN, TEST2)
{
char buff[8] = {0};
struct vxlan_hdr *hdr = (struct vxlan_hdr *)buff;
vxlan_set_flags(hdr, VXLAN_DEFAULT_FLAGS);
vxlan_set_dir(hdr, 1);
vxlan_set_traffic(hdr, 1);
vxlan_set_sf_index(hdr, 1);
vxlan_set_link_id(hdr, 1);
vxlan_set_stateless(hdr, 1);
EXPECT_TRUE(vxlan_get_flags(hdr) == VXLAN_DEFAULT_FLAGS);
EXPECT_TRUE(vxlan_get_dir(hdr) == 1);
EXPECT_TRUE(vxlan_get_traffic(hdr) == 1);
EXPECT_TRUE(vxlan_get_sf_index(hdr) == 1);
EXPECT_TRUE(vxlan_get_link_id(hdr) == 1);
EXPECT_TRUE(vxlan_get_stateless(hdr) == 1);
hexdump(buff, 8);
}
TEST(VXLAN, TEST3)
{
char buff[8] = {0};
struct vxlan_hdr *hdr = (struct vxlan_hdr *)buff;
vxlan_set_flags(hdr, VXLAN_DEFAULT_FLAGS);
vxlan_set_dir(hdr, 1);
vxlan_set_traffic(hdr, 1);
vxlan_set_sf_index(hdr, 31);
vxlan_set_link_id(hdr, 65535);
vxlan_set_stateless(hdr, 1);
EXPECT_TRUE(vxlan_get_flags(hdr) == VXLAN_DEFAULT_FLAGS);
EXPECT_TRUE(vxlan_get_dir(hdr) == 1);
EXPECT_TRUE(vxlan_get_traffic(hdr) == 1);
EXPECT_TRUE(vxlan_get_sf_index(hdr) == 31);
EXPECT_TRUE(vxlan_get_link_id(hdr) == 65535);
EXPECT_TRUE(vxlan_get_stateless(hdr) == 1);
hexdump(buff, 8);
}
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}