diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index a0e3319..5f6ff2e 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -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) diff --git a/common/include/g_vxlan.h b/common/include/g_vxlan.h deleted file mode 100644 index 1cd852e..0000000 --- a/common/include/g_vxlan.h +++ /dev/null @@ -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 diff --git a/common/include/tuple.h b/common/include/tuple.h index 0f88798..0905c7a 100644 --- a/common/include/tuple.h +++ b/common/include/tuple.h @@ -10,6 +10,8 @@ extern "C" #include #include +#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 diff --git a/common/include/utils.h b/common/include/utils.h index 8e114bb..9d3ee80 100644 --- a/common/include/utils.h +++ b/common/include/utils.h @@ -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 diff --git a/common/include/vxlan.h b/common/include/vxlan.h new file mode 100644 index 0000000..97b439a --- /dev/null +++ b/common/include/vxlan.h @@ -0,0 +1,89 @@ +#ifndef _VXLAN_H +#define _VXLAN_H + +#ifdef __cpluscplus +extern "C" +{ +#endif + +#define __FAVOR_BSD 1 +#include + +#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 diff --git a/common/src/g_vxlan.cpp b/common/src/g_vxlan.cpp deleted file mode 100644 index 22aa3a2..0000000 --- a/common/src/g_vxlan.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include - -#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; -} \ No newline at end of file diff --git a/common/src/packet.cpp b/common/src/packet.cpp index 84dc5b0..a176ca5 100644 --- a/common/src/packet.cpp +++ b/common/src/packet.cpp @@ -4,6 +4,7 @@ #include #define __FAVOR_BSD 1 #include +#include #include #include @@ -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)) { diff --git a/common/src/utils.cpp b/common/src/utils.cpp index 5a661a2..d139e53 100644 --- a/common/src/utils.cpp +++ b/common/src/utils.cpp @@ -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 ******************************************************************************/ diff --git a/common/src/vxlan.cpp b/common/src/vxlan.cpp new file mode 100644 index 0000000..ad214b4 --- /dev/null +++ b/common/src/vxlan.cpp @@ -0,0 +1,169 @@ +#include +#include +#include +#include + +#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; +} \ No newline at end of file diff --git a/platform/include/global_metrics.h b/platform/include/global_metrics.h index 410fa1a..8b34261 100644 --- a/platform/include/global_metrics.h +++ b/platform/include/global_metrics.h @@ -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; // 累计值 diff --git a/platform/include/sce.h b/platform/include/sce.h index 311204b..866bfca 100644 --- a/platform/include/sce.h +++ b/platform/include/sce.h @@ -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; diff --git a/platform/src/health_check.cpp b/platform/src/health_check.cpp index f283e62..7096eae 100644 --- a/platform/src/health_check.cpp +++ b/platform/src/health_check.cpp @@ -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; diff --git a/platform/src/packet_io.cpp b/platform/src/packet_io.cpp index f582d27..a1effe0 100644 --- a/platform/src/packet_io.cpp +++ b/platform/src/packet_io.cpp @@ -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) diff --git a/test/gtest_utils.h b/test/gtest_utils.h index e1eef9d..1ccbac5 100644 --- a/test/gtest_utils.h +++ b/test/gtest_utils.h @@ -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; }