TSG-17749 tsg-service-chaining-engine更改VXLAN Frame源端口的计算方式
This commit is contained in:
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user