TSG-17749 tsg-service-chaining-engine更改VXLAN Frame源端口的计算方式
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
add_library(common src/session_table.cpp src/packet.cpp src/control_packet.cpp src/bfd.cpp src/utils.cpp src/g_vxlan.cpp src/log.cpp src/timestamp.cpp src/mpack.cpp)
|
||||
add_library(common src/session_table.cpp src/packet.cpp src/control_packet.cpp src/bfd.cpp src/utils.cpp src/vxlan.cpp src/log.cpp src/timestamp.cpp src/mpack.cpp)
|
||||
target_link_libraries(common PUBLIC cjson)
|
||||
target_link_libraries(common PUBLIC MESA_handle_logger)
|
||||
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
#ifndef _G_VXLAN_H
|
||||
#define _G_VXLAN_H
|
||||
|
||||
#ifdef __cpluscplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
struct g_vxlan
|
||||
{
|
||||
unsigned char flags;
|
||||
unsigned char reserved[3];
|
||||
|
||||
// VNI 3 Bytes
|
||||
unsigned char vlan_id_half_high;
|
||||
|
||||
unsigned char link_layer_type : 4; // 二层报文封装格式
|
||||
unsigned char vlan_id_half_low : 4;
|
||||
|
||||
unsigned int dir_is_e2i : 1;
|
||||
unsigned int traffic_is_decrypted : 1;
|
||||
unsigned int sf_index : 5; // max value 32
|
||||
unsigned int online_test : 1;
|
||||
|
||||
// Reserved 1 Bytes
|
||||
unsigned int r7 : 1;
|
||||
unsigned int r6 : 1;
|
||||
unsigned int r5 : 1;
|
||||
unsigned int r4 : 1;
|
||||
unsigned int vni_flag : 1;
|
||||
unsigned int r2 : 1;
|
||||
unsigned int r1 : 1;
|
||||
unsigned int r0 : 1;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
void g_vxlan_set_packet_dir(struct g_vxlan *hdr, int dir_is_e2i);
|
||||
void g_vxlan_set_sf_index(struct g_vxlan *hdr, int sf_index);
|
||||
void g_vxlan_set_traffic_type(struct g_vxlan *hdr, int traffic_is_decrypted);
|
||||
|
||||
int g_vxlan_get_packet_dir(struct g_vxlan *hdr);
|
||||
int g_vxlan_get_sf_index(struct g_vxlan *hdr);
|
||||
int g_vxlan_get_traffic_type(struct g_vxlan *hdr);
|
||||
|
||||
// return 0 : success
|
||||
// return -1 : error
|
||||
int g_vxlan_decode(struct g_vxlan **g_vxlan_hd, const char *raw_data, int raw_len);
|
||||
|
||||
#ifdef __cpluscplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -10,6 +10,8 @@ extern "C"
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "uthash.h"
|
||||
|
||||
enum address_type
|
||||
{
|
||||
ADDR_TYPE_IPV4,
|
||||
@@ -349,6 +351,13 @@ inline char *four_tuple_tostring(const struct four_tuple *tuple)
|
||||
return str_ret;
|
||||
}
|
||||
|
||||
inline uint64_t four_tuple_hash(const struct four_tuple *tuple)
|
||||
{
|
||||
uint64_t hash_value = 0;
|
||||
HASH_VALUE(tuple, sizeof(struct four_tuple), hash_value);
|
||||
return hash_value;
|
||||
}
|
||||
|
||||
#ifdef __cpluscplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -22,7 +22,6 @@ extern "C"
|
||||
|
||||
#define ATOMIC_INC(x) __atomic_fetch_add(x, 1, __ATOMIC_RELAXED)
|
||||
#define ATOMIC_DEC(x) __atomic_fetch_sub(x, 1, __ATOMIC_RELAXED)
|
||||
//#define ATOMIC_READ(x) __atomic_fetch_add(x, 0, __ATOMIC_RELAXED)
|
||||
#define ATOMIC_READ(x) __atomic_load_n(x, __ATOMIC_RELAXED)
|
||||
#define ATOMIC_ZERO(x) __atomic_fetch_and(x, 0, __ATOMIC_RELAXED)
|
||||
#define ATOMIC_ADD(x, y) __atomic_fetch_add(x, y, __ATOMIC_RELAXED)
|
||||
@@ -95,22 +94,6 @@ struct throughput_metrics
|
||||
|
||||
void throughput_metrics_inc(struct throughput_metrics *iterm, uint64_t n_pkts, uint64_t n_bytes);
|
||||
|
||||
/******************************************************************************
|
||||
* protocol
|
||||
******************************************************************************/
|
||||
|
||||
struct udp_hdr
|
||||
{
|
||||
uint16_t uh_sport; /* source port */
|
||||
uint16_t uh_dport; /* destination port */
|
||||
uint16_t uh_ulen; /* udp length */
|
||||
uint16_t uh_sum; /* udp checksum */
|
||||
} __attribute__((__packed__));
|
||||
|
||||
void build_udp_header(const char *l3_hdr, int l3_hdr_len, struct udp_hdr *udp_hdr, uint16_t udp_sport, uint16_t udp_dport, int payload_len);
|
||||
void build_ip_header(struct ip *ip_hdr, uint8_t next_protocol, uint16_t ipid, const in_addr_t src_ip, const in_addr_t dst_ip, uint16_t payload_len);
|
||||
void build_ether_header(struct ethhdr *eth_hdr, uint16_t next_protocol, const u_char src_mac[], const u_char dst_mac[]);
|
||||
|
||||
/******************************************************************************
|
||||
* device
|
||||
******************************************************************************/
|
||||
@@ -119,10 +102,6 @@ int get_ip_by_device_name(const char *dev_name, char *ip_str);
|
||||
int get_mac_by_device_name(const char *dev_name, char *mac_str);
|
||||
int str_to_mac(const char *mac_str, u_char mac[]);
|
||||
|
||||
#define CHECKSUM_CARRY(x) (x = (x >> 16) + (x & 0xffff), (~(x + (x >> 16)) & 0xffff))
|
||||
|
||||
int checksum(uint16_t *addr, int len);
|
||||
|
||||
#ifdef __cpluscplus
|
||||
}
|
||||
#endif
|
||||
|
||||
89
common/include/vxlan.h
Normal file
89
common/include/vxlan.h
Normal file
@@ -0,0 +1,89 @@
|
||||
#ifndef _VXLAN_H
|
||||
#define _VXLAN_H
|
||||
|
||||
#ifdef __cpluscplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define __FAVOR_BSD 1
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#include "tuple.h"
|
||||
|
||||
/*
|
||||
* 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 |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | VXLAN Network Identifier (VNI) | Reserved |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*
|
||||
* Flags (8 bits):
|
||||
* where the I flag MUST be set to 1 for a valid VXLAN Network ID (VNI).
|
||||
* The other 7 bits (designated "R") are reserved fields and MUST be set
|
||||
* 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.
|
||||
*/
|
||||
|
||||
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;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
enum vni_opt
|
||||
{
|
||||
VNI_OPT_DIR = 0x80,
|
||||
VNI_OPT_TRAFFIC = 0x40,
|
||||
VNI_OPT_SFINDEX = 0x3f,
|
||||
};
|
||||
|
||||
#define VXLAN_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))
|
||||
|
||||
void vxlan_set_opt(struct vxlan_hdr *hdr, enum vni_opt opt, uint8_t val);
|
||||
uint8_t vxlan_get_opt(struct vxlan_hdr *hdr, enum vni_opt opt);
|
||||
|
||||
// return 0 : success
|
||||
// return -1 : error
|
||||
int vxlan_frame_decode(struct vxlan_hdr **vxlan_hdr, const char *data, uint16_t 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);
|
||||
|
||||
uint16_t calculate_vxlan_source_port(struct four_tuple *innermost_tuple4);
|
||||
|
||||
#ifdef __cpluscplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,67 +0,0 @@
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ether.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "g_vxlan.h"
|
||||
|
||||
void g_vxlan_set_packet_dir(struct g_vxlan *hdr, int dir_is_e2i)
|
||||
{
|
||||
hdr->dir_is_e2i = (!!dir_is_e2i);
|
||||
}
|
||||
|
||||
void g_vxlan_set_sf_index(struct g_vxlan *hdr, int sf_index)
|
||||
{
|
||||
hdr->sf_index = (0x1f & sf_index);
|
||||
}
|
||||
|
||||
void g_vxlan_set_traffic_type(struct g_vxlan *hdr, int traffic_is_decrypted)
|
||||
{
|
||||
hdr->traffic_is_decrypted = (!!traffic_is_decrypted);
|
||||
}
|
||||
|
||||
int g_vxlan_get_packet_dir(struct g_vxlan *hdr)
|
||||
{
|
||||
return (!!hdr->dir_is_e2i);
|
||||
}
|
||||
|
||||
int g_vxlan_get_sf_index(struct g_vxlan *hdr)
|
||||
{
|
||||
return hdr->sf_index;
|
||||
}
|
||||
|
||||
int g_vxlan_get_traffic_type(struct g_vxlan *hdr)
|
||||
{
|
||||
return (!!hdr->traffic_is_decrypted);
|
||||
}
|
||||
|
||||
// return 0 : success
|
||||
// return -1 : error
|
||||
int g_vxlan_decode(struct g_vxlan **g_vxlan_hdr, const char *raw_data, int raw_len)
|
||||
{
|
||||
if (raw_len <= (int)(sizeof(struct ethhdr) + sizeof(struct ip) + sizeof(struct udp_hdr) + sizeof(struct g_vxlan)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct ethhdr *eth_hdr = (struct ethhdr *)raw_data;
|
||||
if (eth_hdr->h_proto != htons(ETH_P_IP))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct ip *ip_hdr = (struct ip *)((char *)eth_hdr + sizeof(struct ethhdr));
|
||||
if (ip_hdr->ip_p != IPPROTO_UDP)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct udp_hdr *udp_hdr = (struct udp_hdr *)((char *)ip_hdr + sizeof(struct ip));
|
||||
if (udp_hdr->uh_dport != htons(4789))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
*g_vxlan_hdr = (struct g_vxlan *)((char *)udp_hdr + sizeof(struct udp_hdr));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <netinet/ip6.h>
|
||||
#define __FAVOR_BSD 1
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/ether.h>
|
||||
#include <linux/ppp_defs.h>
|
||||
|
||||
@@ -26,14 +27,6 @@
|
||||
LOG_PACKET, (tag), (next_proto)); \
|
||||
}
|
||||
|
||||
struct udp_hdr
|
||||
{
|
||||
uint16_t uh_sport; /* source port */
|
||||
uint16_t uh_dport; /* destination port */
|
||||
uint16_t uh_ulen; /* udp length */
|
||||
uint16_t uh_sum; /* udp checksum */
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/******************************************************************************
|
||||
* Static API
|
||||
******************************************************************************/
|
||||
@@ -349,7 +342,7 @@ static inline void set_four_tuple(const char *data, enum layer_type type, struct
|
||||
const struct ip *ipv4 = NULL;
|
||||
const struct ip6_hdr *ipv6 = NULL;
|
||||
const struct tcphdr *tcp = NULL;
|
||||
const struct udp_hdr *udp = NULL;
|
||||
const struct udphdr *udp = NULL;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
@@ -358,7 +351,7 @@ static inline void set_four_tuple(const char *data, enum layer_type type, struct
|
||||
four_tuple_set_port(tuple, tcp->th_sport, tcp->th_dport);
|
||||
break;
|
||||
case LAYER_TYPE_UDP:
|
||||
udp = (const struct udp_hdr *)data;
|
||||
udp = (const struct udphdr *)data;
|
||||
four_tuple_set_port(tuple, udp->uh_sport, udp->uh_dport);
|
||||
break;
|
||||
case LAYER_TYPE_IPV4:
|
||||
@@ -856,7 +849,7 @@ static inline const char *parse_gre(struct packet *handler, const char *data, ui
|
||||
|
||||
static inline const char *parse_udp(struct packet *handler, const char *data, uint16_t len)
|
||||
{
|
||||
if (unlikely(len < sizeof(struct udp_hdr)))
|
||||
if (unlikely(len < sizeof(struct udphdr)))
|
||||
{
|
||||
PACKET_LOG_DATA_INSUFFICIENCY(LAYER_TYPE_UDP);
|
||||
return data;
|
||||
@@ -867,8 +860,8 @@ static inline const char *parse_udp(struct packet *handler, const char *data, ui
|
||||
{
|
||||
return data;
|
||||
}
|
||||
struct udp_hdr *hdr = (struct udp_hdr *)data;
|
||||
SET_LAYER(handler, layer, LAYER_TYPE_UDP, sizeof(struct udp_hdr), data, len);
|
||||
struct udphdr *hdr = (struct udphdr *)data;
|
||||
SET_LAYER(handler, layer, LAYER_TYPE_UDP, sizeof(struct udphdr), data, len);
|
||||
|
||||
switch (ntohs(hdr->uh_dport))
|
||||
{
|
||||
|
||||
@@ -153,79 +153,6 @@ void throughput_metrics_inc(struct throughput_metrics *iterm, uint64_t n_pkts, u
|
||||
iterm->n_pkts += n_pkts;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* protocol
|
||||
******************************************************************************/
|
||||
int checksum(uint16_t *addr, int len)
|
||||
{
|
||||
int sum = 0;
|
||||
int nleft = len;
|
||||
uint16_t ans = 0;
|
||||
uint16_t *w = addr;
|
||||
|
||||
while (nleft > 1)
|
||||
{
|
||||
sum += *w++;
|
||||
nleft -= 2;
|
||||
}
|
||||
|
||||
if (nleft == 1)
|
||||
{
|
||||
*(char *)(&ans) = *(char *)w;
|
||||
sum += ans;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
void build_udp_header(const char *l3_hdr, int l3_hdr_len, struct udp_hdr *udp_hdr, uint16_t udp_sport, uint16_t udp_dport, int payload_len)
|
||||
{
|
||||
memset(udp_hdr, 0, sizeof(struct udp_hdr));
|
||||
|
||||
int udp_hlen = sizeof(struct udp_hdr) + payload_len;
|
||||
|
||||
udp_hdr->uh_sport = htons(udp_sport);
|
||||
udp_hdr->uh_dport = htons(udp_dport);
|
||||
|
||||
udp_hdr->uh_ulen = htons(udp_hlen);
|
||||
udp_hdr->uh_sum = 0;
|
||||
|
||||
int sum = checksum((uint16_t *)l3_hdr, l3_hdr_len);
|
||||
sum += ntohs(IPPROTO_UDP + udp_hlen);
|
||||
sum += checksum((uint16_t *)udp_hdr, udp_hlen);
|
||||
udp_hdr->uh_sum = CHECKSUM_CARRY(sum);
|
||||
}
|
||||
|
||||
void build_ip_header(struct ip *ip_hdr, uint8_t next_protocol, uint16_t ipid, const in_addr_t src_ip, const in_addr_t dst_ip, uint16_t payload_len)
|
||||
{
|
||||
memset(ip_hdr, 0, sizeof(struct ip));
|
||||
|
||||
ip_hdr->ip_hl = 5; /* 20 byte header */
|
||||
ip_hdr->ip_v = 4; /* version 4 */
|
||||
ip_hdr->ip_tos = 0; /* IP tos */
|
||||
ip_hdr->ip_id = htons(ipid); /* IP ID */
|
||||
ip_hdr->ip_ttl = 80; /* time to live */
|
||||
ip_hdr->ip_p = next_protocol; /* transport protocol */
|
||||
ip_hdr->ip_src.s_addr = src_ip;
|
||||
ip_hdr->ip_dst.s_addr = dst_ip;
|
||||
ip_hdr->ip_len = htons(sizeof(struct ip) + payload_len); /* total length */
|
||||
ip_hdr->ip_off = htons(0); /* fragmentation flags */
|
||||
ip_hdr->ip_sum = 0; /* do this later */
|
||||
|
||||
int sum = checksum((uint16_t *)ip_hdr, 20);
|
||||
ip_hdr->ip_sum = CHECKSUM_CARRY(sum);
|
||||
}
|
||||
|
||||
// l3_protocol: ETH_P_IPV6/ETH_P_IP
|
||||
void build_ether_header(struct ethhdr *eth_hdr, uint16_t next_protocol, const u_char src_mac[], const u_char dst_mac[])
|
||||
{
|
||||
memset(eth_hdr, 0, sizeof(struct ethhdr));
|
||||
|
||||
memcpy(eth_hdr->h_source, src_mac, ETH_ALEN);
|
||||
memcpy(eth_hdr->h_dest, dst_mac, ETH_ALEN);
|
||||
eth_hdr->h_proto = htons(next_protocol);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* device
|
||||
******************************************************************************/
|
||||
|
||||
169
common/src/vxlan.cpp
Normal file
169
common/src/vxlan.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
#include <string.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ether.h>
|
||||
|
||||
#include "vxlan.h"
|
||||
|
||||
#define CHECKSUM_CARRY(x) (x = (x >> 16) + (x & 0xffff), (~(x + (x >> 16)) & 0xffff))
|
||||
static inline int checksum(uint16_t *data, int len)
|
||||
{
|
||||
int sum = 0;
|
||||
int nleft = len;
|
||||
uint16_t ans = 0;
|
||||
uint16_t *w = data;
|
||||
|
||||
while (nleft > 1)
|
||||
{
|
||||
sum += *w++;
|
||||
nleft -= 2;
|
||||
}
|
||||
|
||||
if (nleft == 1)
|
||||
{
|
||||
*(char *)(&ans) = *(char *)w;
|
||||
sum += ans;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
static inline void eth_header_encode(struct ethhdr *eth_hdr, const u_char src_mac[], const u_char dst_mac[], uint16_t proto)
|
||||
{
|
||||
memcpy(eth_hdr->h_source, src_mac, ETH_ALEN);
|
||||
memcpy(eth_hdr->h_dest, dst_mac, ETH_ALEN);
|
||||
eth_hdr->h_proto = htons(proto);
|
||||
}
|
||||
|
||||
static inline void ip_header_encode(struct ip *ip_hdr, const in_addr_t src_ip, const in_addr_t dst_ip, uint16_t ipid, uint8_t proto, uint16_t pld_len)
|
||||
{
|
||||
ip_hdr->ip_v = 4; /* version 4 */
|
||||
ip_hdr->ip_hl = 5; /* 20 byte header */
|
||||
ip_hdr->ip_tos = 0; /* IP tos */
|
||||
ip_hdr->ip_len = htons(sizeof(struct ip) + pld_len); /* total length */
|
||||
ip_hdr->ip_id = htons(ipid); /* IP ID */
|
||||
ip_hdr->ip_off = htons(0); /* fragmentation flags */
|
||||
ip_hdr->ip_ttl = 80; /* time to live */
|
||||
ip_hdr->ip_p = proto; /* transport protocol */
|
||||
ip_hdr->ip_sum = 0; /* do this later */
|
||||
ip_hdr->ip_src.s_addr = src_ip;
|
||||
ip_hdr->ip_dst.s_addr = dst_ip;
|
||||
|
||||
int sum = checksum((uint16_t *)ip_hdr, 20);
|
||||
ip_hdr->ip_sum = CHECKSUM_CARRY(sum);
|
||||
}
|
||||
|
||||
static inline void udp_header_encode(struct udphdr *udp_hdr, uint16_t udp_sport, uint16_t udp_dport, uint16_t pld_len)
|
||||
{
|
||||
int udp_hlen = sizeof(struct udphdr) + pld_len;
|
||||
|
||||
udp_hdr->uh_sport = htons(udp_sport);
|
||||
udp_hdr->uh_dport = htons(udp_dport);
|
||||
udp_hdr->uh_ulen = htons(udp_hlen);
|
||||
/*
|
||||
* UDP Checksum: It SHOULD be transmitted as zero
|
||||
* https://datatracker.ietf.org/doc/html/rfc7348#section-5
|
||||
*/
|
||||
udp_hdr->uh_sum = 0;
|
||||
}
|
||||
|
||||
void vxlan_set_opt(struct vxlan_hdr *hdr, enum vni_opt opt, uint8_t val)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t vxlan_get_opt(struct vxlan_hdr *hdr, enum vni_opt opt)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// return 0 : success
|
||||
// return -1 : error
|
||||
int vxlan_frame_decode(struct vxlan_hdr **vxlan_hdr, const char *data, uint16_t len)
|
||||
{
|
||||
if (len < VXLAN_FRAME_HDR_LEN)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct ethhdr *eth_hdr = (struct ethhdr *)data;
|
||||
if (eth_hdr->h_proto != htons(ETH_P_IP))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct ip *ip_hdr = (struct ip *)((char *)eth_hdr + sizeof(struct ethhdr));
|
||||
if (ip_hdr->ip_p != IPPROTO_UDP)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct udphdr *udp_hdr = (struct udphdr *)((char *)ip_hdr + sizeof(struct ip));
|
||||
if (udp_hdr->uh_dport != htons(4789))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
*vxlan_hdr = (struct vxlan_hdr *)((char *)udp_hdr + sizeof(struct udphdr));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct ethhdr *eth_hdr = (struct ethhdr *)buff;
|
||||
struct ip *ip_hdr = (struct ip *)((char *)eth_hdr + sizeof(struct ethhdr));
|
||||
struct udphdr *udp_hdr = (struct udphdr *)((char *)ip_hdr + sizeof(struct ip));
|
||||
struct vxlan_hdr *vxlan_hdr = (struct vxlan_hdr *)((char *)udp_hdr + sizeof(struct udphdr));
|
||||
|
||||
// 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);
|
||||
|
||||
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);
|
||||
udp_header_encode(udp_hdr, udp_src_port, VXLAN_DST_PORT, sizeof(struct vxlan_hdr) + udp_pld_len);
|
||||
}
|
||||
|
||||
uint16_t calculate_vxlan_source_port(struct four_tuple *innermost_tuple4)
|
||||
{
|
||||
/*
|
||||
* When calculating the UDP source port number in this manner, it
|
||||
* is RECOMMENDED that the value be in the dynamic/private port
|
||||
* range 49152-65535 [RFC6335].
|
||||
*/
|
||||
uint64_t hash = four_tuple_hash(innermost_tuple4);
|
||||
uint16_t port = (uint16_t)(hash % (65535 - 49152) + 49152);
|
||||
|
||||
return port;
|
||||
}
|
||||
@@ -35,7 +35,7 @@ struct device_metrics
|
||||
struct throughput_metrics endpoint_vlan_drop; // 累计值
|
||||
};
|
||||
|
||||
// data_pkt_metrics 不包含 g_vxlan 所占的字节
|
||||
// data_pkt_metrics 不包含 vxlan frame 所占的字节
|
||||
struct data_pkt_metrics
|
||||
{
|
||||
struct throughput_metrics mirr_bypass; // 累计值
|
||||
|
||||
@@ -74,6 +74,7 @@ struct session_ctx
|
||||
{
|
||||
uint64_t session_id;
|
||||
char *session_addr;
|
||||
uint16_t vxlan_src_port;
|
||||
|
||||
struct four_tuple inner_tuple4;
|
||||
struct mutable_array rule_ids;
|
||||
|
||||
@@ -161,6 +161,29 @@ static int health_check_method_table_add(struct session_table_addr *table, char
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CHECKSUM_CARRY(x) (x = (x >> 16) + (x & 0xffff), (~(x + (x >> 16)) & 0xffff))
|
||||
static inline int checksum(uint16_t *data, int len)
|
||||
{
|
||||
int sum = 0;
|
||||
int nleft = len;
|
||||
uint16_t ans = 0;
|
||||
uint16_t *w = data;
|
||||
|
||||
while (nleft > 1)
|
||||
{
|
||||
sum += *w++;
|
||||
nleft -= 2;
|
||||
}
|
||||
|
||||
if (nleft == 1)
|
||||
{
|
||||
*(char *)(&ans) = *(char *)w;
|
||||
sum += ans;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
static int send_icmp_pkt(char *addr)
|
||||
{
|
||||
int sockfd;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "log.h"
|
||||
#include "sce.h"
|
||||
#include "utils.h"
|
||||
#include "g_vxlan.h"
|
||||
#include "vxlan.h"
|
||||
#include "packet_io.h"
|
||||
#include "sf_metrics.h"
|
||||
#include "control_packet.h"
|
||||
@@ -322,7 +322,7 @@ static int is_uplink_keepalive_packet(marsio_buff_t *rx_buff)
|
||||
{
|
||||
int raw_len = marsio_buff_datalen(rx_buff);
|
||||
char *raw_data = marsio_buff_mtod(rx_buff);
|
||||
if (raw_data == NULL || raw_len < (int)(sizeof(struct ethhdr) + sizeof(struct ip) + sizeof(struct udp_hdr)))
|
||||
if (raw_data == NULL || raw_len < (int)(sizeof(struct ethhdr) + sizeof(struct ip) + sizeof(struct udphdr)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -339,7 +339,7 @@ static int is_uplink_keepalive_packet(marsio_buff_t *rx_buff)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct udp_hdr *udp_hdr = (struct udp_hdr *)((char *)ip_hdr + sizeof(struct ip));
|
||||
struct udphdr *udp_hdr = (struct udphdr *)((char *)ip_hdr + sizeof(struct ip));
|
||||
if (udp_hdr->uh_dport != htons(3784))
|
||||
{
|
||||
return 0;
|
||||
@@ -408,26 +408,6 @@ static struct session_ctx *inject_packet_search_session(struct session_table *ta
|
||||
* action bypass/block/forward
|
||||
******************************************************************************/
|
||||
|
||||
static void vxlan_encapsulate(marsio_buff_t *mbuff,
|
||||
const u_char src_mac[], const u_char dst_mac[],
|
||||
const in_addr_t src_ip, const in_addr_t dst_ip, uint16_t ipid,
|
||||
uint16_t src_port, int payload_len, int is_e2i, int is_decrypted, int sf_index)
|
||||
{
|
||||
struct ethhdr *eth_hdr = (struct ethhdr *)marsio_buff_prepend(mbuff, sizeof(struct ethhdr) + sizeof(struct ip) + sizeof(struct udp_hdr) + sizeof(struct g_vxlan));
|
||||
struct ip *ip_hdr = (struct ip *)((char *)eth_hdr + sizeof(struct ethhdr));
|
||||
struct udp_hdr *udp_hdr = (struct udp_hdr *)((char *)ip_hdr + sizeof(struct ip));
|
||||
struct g_vxlan *g_vxlan_hdr = (struct g_vxlan *)((char *)udp_hdr + sizeof(struct udp_hdr));
|
||||
|
||||
memset(g_vxlan_hdr, 0, sizeof(struct g_vxlan));
|
||||
g_vxlan_set_packet_dir(g_vxlan_hdr, is_e2i);
|
||||
g_vxlan_set_sf_index(g_vxlan_hdr, sf_index);
|
||||
g_vxlan_set_traffic_type(g_vxlan_hdr, is_decrypted);
|
||||
|
||||
build_ether_header(eth_hdr, ETH_P_IP, src_mac, dst_mac);
|
||||
build_ip_header(ip_hdr, IPPROTO_UDP, ipid, src_ip, dst_ip, sizeof(struct udp_hdr) + sizeof(struct g_vxlan) + payload_len);
|
||||
build_udp_header((const char *)&ip_hdr->ip_src, 8, udp_hdr, src_port, 4789, sizeof(struct g_vxlan) + payload_len);
|
||||
}
|
||||
|
||||
struct vlan_hdr
|
||||
{
|
||||
uint16_t vlan_cfi;
|
||||
@@ -507,10 +487,11 @@ void vlan_encapsulate(marsio_buff_t *mbuff, int vlan_id, int replace_orig_vlan_h
|
||||
}
|
||||
}
|
||||
|
||||
static int send_packet_to_sf(marsio_buff_t *mbuff, struct metadata *meta, struct selected_sf *sf, struct thread_ctx *thread_ctx)
|
||||
static int send_packet_to_sf(struct session_ctx *session_ctx, marsio_buff_t *mbuff, struct metadata *meta, struct selected_sf *sf, struct thread_ctx *thread_ctx)
|
||||
{
|
||||
thread_ctx->tx_packets_ipid++;
|
||||
int nsend = 0;
|
||||
char *buffer = NULL;
|
||||
struct packet_io *packet_io = thread_ctx->ref_io;
|
||||
struct thread_metrics *thread_metrics = &thread_ctx->thread_metrics;
|
||||
|
||||
@@ -518,9 +499,12 @@ static int send_packet_to_sf(marsio_buff_t *mbuff, struct metadata *meta, struct
|
||||
switch (sf->sf_connectivity.method)
|
||||
{
|
||||
case ENCAPSULATE_METHOD_VXLAN_G:
|
||||
vxlan_encapsulate(mbuff, packet_io->config.dev_endpoint_l3_mac, sf->sf_dst_mac,
|
||||
packet_io->config.dev_endpoint_l3_ip, sf->sf_dst_ip, thread_ctx->tx_packets_ipid % 65535,
|
||||
meta->session_id % (65535 - 49152) + 49152, meta->raw_len, meta->is_e2i_dir, meta->is_decrypted, sf->sf_index);
|
||||
buffer = marsio_buff_prepend(mbuff, VXLAN_FRAME_HDR_LEN);
|
||||
vxlan_frame_encode(buffer,
|
||||
packet_io->config.dev_endpoint_l3_mac, sf->sf_dst_mac,
|
||||
packet_io->config.dev_endpoint_l3_ip, sf->sf_dst_ip, thread_ctx->tx_packets_ipid % 65535,
|
||||
session_ctx->vxlan_src_port, meta->raw_len,
|
||||
meta->is_e2i_dir, meta->is_decrypted, sf->sf_index);
|
||||
nsend = marsio_buff_datalen(mbuff);
|
||||
marsio_send_burst_with_options(packet_io->dev_endpoint_l3.mr_path, thread_ctx->thread_index, &mbuff, 1, MARSIO_SEND_OPT_REHASH);
|
||||
throughput_metrics_inc(&(thread_metrics->device.endpoint_vxlan_tx), 1, nsend);
|
||||
@@ -603,7 +587,7 @@ static void action_mirr_block(marsio_buff_t *rx_buff, struct metadata *meta, str
|
||||
throughput_metrics_inc(&(thread_metrics->data_pkt.mirr_block), 1, raw_len);
|
||||
}
|
||||
|
||||
static void action_mirr_forward(marsio_buff_t *rx_buff, struct metadata *meta, struct selected_sf *sf, struct thread_ctx *thread_ctx)
|
||||
static void action_mirr_forward(struct session_ctx *session_ctx, marsio_buff_t *rx_buff, struct metadata *meta, struct selected_sf *sf, struct thread_ctx *thread_ctx)
|
||||
{
|
||||
struct thread_metrics *thread_metrics = &thread_ctx->thread_metrics;
|
||||
struct packet_io *packet_io = thread_ctx->ref_io;
|
||||
@@ -622,7 +606,7 @@ static void action_mirr_forward(marsio_buff_t *rx_buff, struct metadata *meta, s
|
||||
char *copy_ptr = marsio_buff_append(new_buff, raw_len);
|
||||
memcpy(copy_ptr, raw_data, raw_len);
|
||||
|
||||
int nsend = send_packet_to_sf(new_buff, meta, sf, thread_ctx);
|
||||
int nsend = send_packet_to_sf(session_ctx, new_buff, meta, sf, thread_ctx);
|
||||
throughput_metrics_inc(&(thread_metrics->data_pkt.mirr_tx), 1, raw_len);
|
||||
throughput_metrics_inc(&sf->tx, 1, nsend);
|
||||
sf_metrics_inc(thread_ctx->sf_metrics, sf->rule_vsys_id, sf->rule_id, sf->sff_profile_id, sf->sf_profile_id, 0, 0, 1, nsend);
|
||||
@@ -647,12 +631,12 @@ static void action_stee_block(marsio_buff_t *rx_buff, struct metadata *meta, str
|
||||
marsio_buff_free(packet_io->instance, &rx_buff, 1, 0, thread_index);
|
||||
}
|
||||
|
||||
static void action_stee_forward(marsio_buff_t *rx_buff, struct metadata *meta, struct selected_sf *sf, struct thread_ctx *thread_ctx)
|
||||
static void action_stee_forward(struct session_ctx *session_ctx, marsio_buff_t *rx_buff, struct metadata *meta, struct selected_sf *sf, struct thread_ctx *thread_ctx)
|
||||
{
|
||||
struct thread_metrics *thread_metrics = &thread_ctx->thread_metrics;
|
||||
|
||||
int raw_len = marsio_buff_datalen(rx_buff);
|
||||
int nsend = send_packet_to_sf(rx_buff, meta, sf, thread_ctx);
|
||||
int nsend = send_packet_to_sf(session_ctx, rx_buff, meta, sf, thread_ctx);
|
||||
throughput_metrics_inc(&(thread_metrics->data_pkt.stee_tx), 1, raw_len);
|
||||
throughput_metrics_inc(&sf->tx, 1, nsend);
|
||||
sf_metrics_inc(thread_ctx->sf_metrics, sf->rule_vsys_id, sf->rule_id, sf->sff_profile_id, sf->sf_profile_id, 0, 0, 1, nsend);
|
||||
@@ -707,12 +691,12 @@ static void action_sf_chaining(struct thread_ctx *thread_ctx, struct session_ctx
|
||||
|
||||
if (sf->sff_forward_type == FORWARD_TYPE_STEERING)
|
||||
{
|
||||
action_stee_forward(rx_buff, meta, sf, thread_ctx);
|
||||
action_stee_forward(session_ctx, rx_buff, meta, sf, thread_ctx);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
action_mirr_forward(rx_buff, meta, sf, thread_ctx);
|
||||
action_mirr_forward(session_ctx, rx_buff, meta, sf, thread_ctx);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -962,6 +946,7 @@ static void handle_session_opening(struct metadata *meta, struct control_packet
|
||||
struct session_ctx *session_ctx = session_ctx_new();
|
||||
session_ctx->session_id = meta->session_id;
|
||||
session_ctx->session_addr = four_tuple_tostring(&inner_tuple4);
|
||||
session_ctx->vxlan_src_port = calculate_vxlan_source_port(&inner_tuple4);
|
||||
four_tuple_copy(&session_ctx->inner_tuple4, &inner_tuple4);
|
||||
metadata_deep_copy(session_ctx->ctrl_meta, meta);
|
||||
session_ctx->chainings.chaining_raw = selected_chaining_create(chaining_size, session_ctx->session_id, session_ctx->session_addr);
|
||||
@@ -1164,7 +1149,7 @@ static void handle_inject_vxlan_packet(marsio_buff_t *rx_buff, struct thread_ctx
|
||||
struct thread_metrics *thread_metrics = &thread_ctx->thread_metrics;
|
||||
|
||||
struct metadata meta;
|
||||
struct g_vxlan *g_vxlan_hdr = NULL;
|
||||
struct vxlan_hdr *vxlan_hdr = NULL;
|
||||
struct session_ctx *session_ctx = NULL;
|
||||
struct selected_chaining *chaining = NULL;
|
||||
memset(&meta, 0, sizeof(struct metadata));
|
||||
@@ -1172,20 +1157,20 @@ static void handle_inject_vxlan_packet(marsio_buff_t *rx_buff, struct thread_ctx
|
||||
int sf_index = 0;
|
||||
int raw_len = marsio_buff_datalen(rx_buff);
|
||||
char *raw_data = marsio_buff_mtod(rx_buff);
|
||||
if (g_vxlan_decode(&g_vxlan_hdr, raw_data, raw_len) == -1)
|
||||
if (vxlan_frame_decode(&vxlan_hdr, raw_data, raw_len) == -1)
|
||||
{
|
||||
throughput_metrics_inc(&(thread_metrics->device.endpoint_vxlan_drop), 1, raw_len);
|
||||
action_err_block(rx_buff, &meta, NULL, thread_ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
meta.raw_data = (char *)g_vxlan_hdr + sizeof(struct g_vxlan);
|
||||
meta.raw_len = raw_len - sizeof(struct ethhdr) - sizeof(struct ip) - sizeof(struct udp_hdr) - sizeof(struct g_vxlan);
|
||||
meta.raw_data = (char *)vxlan_hdr + sizeof(struct vxlan_hdr);
|
||||
meta.raw_len = raw_len - VXLAN_FRAME_HDR_LEN;
|
||||
meta.l7offset = 0;
|
||||
meta.is_e2i_dir = g_vxlan_get_packet_dir(g_vxlan_hdr);
|
||||
meta.is_ctrl_pkt = 0;
|
||||
meta.is_decrypted = g_vxlan_get_traffic_type(g_vxlan_hdr);
|
||||
sf_index = g_vxlan_get_sf_index(g_vxlan_hdr);
|
||||
sf_index = vxlan_get_opt(vxlan_hdr, VNI_OPT_SFINDEX);
|
||||
meta.is_e2i_dir = vxlan_get_opt(vxlan_hdr, VNI_OPT_DIR);
|
||||
meta.is_decrypted = vxlan_get_opt(vxlan_hdr, VNI_OPT_TRAFFIC);
|
||||
|
||||
session_ctx = inject_packet_search_session(session_table, meta.raw_data, meta.raw_len);
|
||||
if (session_ctx == NULL)
|
||||
|
||||
@@ -12,7 +12,7 @@ extern "C"
|
||||
#include "sce.h"
|
||||
#include "log.h"
|
||||
#include "marsio.h"
|
||||
#include "g_vxlan.h"
|
||||
#include "vxlan.h"
|
||||
#include "packet_io.h"
|
||||
#include "sf_metrics.h"
|
||||
#include "health_check.h"
|
||||
@@ -206,7 +206,7 @@ inline void gtest_frame_log(struct gtest_frame *instance)
|
||||
|
||||
inline int mbuff_cmp_payload(marsio_buff_t *buff, marsio_buff_t *vxlan_pkt)
|
||||
{
|
||||
struct g_vxlan *g_vxlan_hdr = NULL;
|
||||
struct vxlan_hdr *vxlan_hdr = NULL;
|
||||
int buff_len = marsio_buff_datalen(buff);
|
||||
char *buff_data = marsio_buff_mtod(buff);
|
||||
|
||||
@@ -218,7 +218,7 @@ inline int mbuff_cmp_payload(marsio_buff_t *buff, marsio_buff_t *vxlan_pkt)
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if (g_vxlan_decode(&g_vxlan_hdr, vxlan_pkt_data, vxlan_pkt_len) != 0)
|
||||
if (vxlan_frame_decode(&vxlan_hdr, vxlan_pkt_data, vxlan_pkt_len) != 0)
|
||||
{
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user