解密流量转发功能适配MARSIOv4

This commit is contained in:
luqiuwen
2019-06-13 17:11:08 +08:00
parent 43f4788c33
commit d3e6be283e
6 changed files with 384 additions and 126 deletions

View File

@@ -3,13 +3,16 @@
#include <tfe_utils.h>
#include <tfe_types.h>
#include <traffic_mirror.h>
#include <marsio.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
struct traffic_mirror_rebuild
{
struct tfe_stream_addr * c_s_addr;
struct tfe_stream_addr * s_c_addr;
struct profile_table_ex_data * target;
struct traffic_mirror_rebuild_target * target;
struct traffic_mirror_ethdev * ethdev;
uint32_t c_seq;
@@ -35,6 +38,8 @@ struct tcp_hdr {
uint16_t tcp_urp; /**< TCP urgent pointer, if any. */
} __attribute__((__packed__));
#define TCP_URG_FLAG 0x20
#define TCP_ACK_FLAG 0x10
#define TCP_PSH_FLAG 0x08
@@ -75,8 +80,8 @@ static inline uint32_t __rte_raw_cksum(const void *buf, size_t len, uint32_t sum
static inline uint16_t __rte_raw_cksum_reduce(uint32_t sum)
{
sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff);
sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff);
sum = ((sum & 0xffff0000U) >> 16) + (sum & 0xffffU);
sum = ((sum & 0xffff0000U) >> 16) + (sum & 0xffffU);
return (uint16_t) sum;
}
@@ -92,8 +97,8 @@ static inline uint16_t __ipv4_cksum(const struct iphdr * ipv4_hdr)
return (cksum == 0xffff) ? cksum : ~cksum;
}
static inline uint16_t __tcpudp_cksum_by_stream_addr_v4(const struct tfe_stream_addr * addr,
const void *l4_hdr, unsigned int l4_len)
static inline uint16_t __tcp_cksum_by_stream_addr_v4(const struct tfe_stream_addr * addr,
const void * l4_hdr, unsigned int l4_len)
{
struct ipv4_psd_header
{
@@ -113,14 +118,32 @@ static inline uint16_t __tcpudp_cksum_by_stream_addr_v4(const struct tfe_stream_
uint32_t cksum = rte_raw_cksum(l4_hdr, l4_len);
cksum += rte_raw_cksum(&psd_hdr, sizeof(psd_hdr));
cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff);
cksum = (~cksum) & 0xffff;
if (cksum == 0)
cksum = 0xffff;
cksum = ((cksum & 0xffff0000U) >> 16U) + (cksum & 0xffffU);
cksum = (~cksum) & 0xffffU;
if (cksum == 0) cksum = 0xffff;
return cksum;
}
static inline uint16_t __tcp_cksum_by_stream_addr_v6(const struct tfe_stream_addr * addr,
const void * l4_hdr, unsigned int l4_len)
{
uint32_t sum;
struct
{
uint32_t len; /* L4 length. */
uint32_t proto; /* L4 protocol - top 3 bytes must be zero */
} psd_hdr
{
.len = l4_len,
.proto =(uint32_t)(IPPROTO_TCP << 24U)
};
sum = __rte_raw_cksum(&addr->tuple4_v6->saddr, sizeof(addr->tuple4_v6->saddr), 0);
sum = __rte_raw_cksum(&addr->tuple4_v6->daddr, sizeof(addr->tuple4_v6->daddr), sum);
sum = __rte_raw_cksum(&psd_hdr, sizeof(psd_hdr), sum);
return __rte_raw_cksum_reduce(sum);
}
static int tcp_header_construct(unsigned char *buf, unsigned short sp,
unsigned short dp, unsigned int seq, unsigned int ack,
unsigned char flags, unsigned short win, unsigned short urg)
@@ -142,12 +165,11 @@ static int tcp_header_construct(unsigned char *buf, unsigned short sp,
static int tcp_header_construct_by_stream_addr(struct tfe_stream_addr * addr, unsigned char *buf,
unsigned int seq, unsigned int ack, unsigned char flags, unsigned short win, unsigned short urg,
unsigned int payload_len)
unsigned char * payload, unsigned int payload_len)
{
unsigned short sport;
unsigned short dport;
unsigned short cksum;
unsigned int tcphdr_len;
if (addr->addrtype == TFE_ADDR_STREAM_TUPLE4_V4)
{
@@ -164,23 +186,21 @@ static int tcp_header_construct_by_stream_addr(struct tfe_stream_addr * addr, un
assert(0);
}
tcphdr_len = tcp_header_construct(buf, sport, dport, seq, ack, flags, win, urg);
unsigned int tcphdr_len = tcp_header_construct(buf, sport, dport, seq, ack, flags, win, urg);
memcpy(buf + tcphdr_len, payload, payload_len);
if (addr->addrtype == TFE_ADDR_STREAM_TUPLE4_V4)
{
cksum = __tcpudp_cksum_by_stream_addr_v4(addr, (void *)buf, tcphdr_len + payload_len);
cksum = __tcp_cksum_by_stream_addr_v4(addr, (void *) buf, tcphdr_len + payload_len);
}
else if (addr->addrtype == TFE_ADDR_STREAM_TUPLE4_V6)
{
assert(0);
}
else
{
assert(0);
cksum = __tcp_cksum_by_stream_addr_v6(addr, (void *)buf, tcphdr_len + payload_len);
}
struct tcp_hdr * tcp_hdr = (struct tcp_hdr *)buf;
tcp_hdr->cksum = cksum;
return tcphdr_len;
return tcphdr_len + payload_len;
}
static int ipv4_header_construct(unsigned char *buf, unsigned short carry_layer_len,
@@ -205,6 +225,22 @@ static int ipv4_header_construct(unsigned char *buf, unsigned short carry_layer_
return sizeof(struct iphdr);
}
static int ipv6_header_construct(unsigned char *buf, unsigned short carry_layer_len,
unsigned char ttl, unsigned char protocol, struct in6_addr * src, struct in6_addr * dst)
{
struct ip6_hdr * ip6_hdr = (struct ip6_hdr *) buf;
ip6_hdr->ip6_vfc = ntohl(0x60000000U);
ip6_hdr->ip6_flow = 0;
ip6_hdr->ip6_plen = htons(carry_layer_len);
ip6_hdr->ip6_nxt = protocol;
ip6_hdr->ip6_hlim = 128;
ip6_hdr->ip6_src = *src;
ip6_hdr->ip6_dst = *dst;
return sizeof(ip6_hdr);
}
static int ip_header_construct_by_stream_addr(struct tfe_stream_addr * addr,
unsigned char *buf, unsigned short carry_layer_len, unsigned char tos,
unsigned short id, unsigned short frag, unsigned char ttl, unsigned char protocol)
@@ -216,12 +252,8 @@ static int ip_header_construct_by_stream_addr(struct tfe_stream_addr * addr,
}
else if (addr->addrtype == TFE_ADDR_STREAM_TUPLE4_V6)
{
/* TODO: IPv6 */
assert(0);
}
else
{
assert(0);
return ipv6_header_construct(buf, carry_layer_len, ttl, protocol,
&addr->tuple4_v6->saddr, &addr->tuple4_v6->daddr);
}
assert(0);
@@ -244,79 +276,78 @@ static void vlan_tag_construct(unsigned char *buf, unsigned short tci, unsigned
vlan_hdr->eth_proto = htons(type);
}
static void l2_send_to_target(struct traffic_mirror_ethdev * ethdev,
unsigned char * snd_buffer, unsigned int l3_data_offset, unsigned int l3_data_len,
static int ether_header_construct(struct traffic_mirror_ethdev * ethdev, char * buffer,
struct ether_addr * target_addr, unsigned int vlan_tci, unsigned l3_protocol)
{
assert(l3_data_offset >= (sizeof(struct ethhdr) + sizeof(struct vlan_hdr)));
unsigned int header_offset = l3_data_offset;
unsigned int header_len = 0;
unsigned int eth_protocol = vlan_tci > 0 ? ETH_P_8021Q : l3_protocol;
ether_header_construct((unsigned char *)buffer + header_len,
(unsigned char *)target_addr->ether_addr_octet,
(unsigned char *)ethdev->local_ether_addr, eth_protocol);
header_len += sizeof(struct ethhdr);
/* need to construct vlan header */
if (vlan_tci > 0)
{
header_offset -= sizeof(struct vlan_hdr);
header_len += sizeof(struct vlan_hdr);
vlan_tag_construct(snd_buffer + header_offset, vlan_tci, l3_protocol);
vlan_tag_construct((unsigned char *)buffer + header_len, vlan_tci, l3_protocol);
}
unsigned int eth_protocol = vlan_tci > 0 ? ETH_P_8021Q : l3_protocol;
header_offset -= sizeof(struct ethhdr);
header_len += sizeof(struct ethhdr);
ether_header_construct(snd_buffer + header_offset, (unsigned char *)target_addr->ether_addr_octet,
(unsigned char *)ethdev->local_ether_addr, eth_protocol);
traffic_mirror_ethdev_inject(ethdev, (char *)snd_buffer + header_offset, header_len + l3_data_len);
return header_len;
}
static void l2_send_to_target_group(struct traffic_mirror_ethdev * ethdev, struct profile_table_ex_data * t_group,
unsigned char * snd_buffer, unsigned int l3_data_offset, unsigned int l3_data_len, unsigned l3_protocol)
static void tcp_segment_send_to_target_group(struct tfe_stream_addr * addr,
struct traffic_mirror_ethdev * ethdev, struct traffic_mirror_rebuild_target * target,
unsigned int tid, const char * payload, unsigned int payload_len,
unsigned int seq, unsigned int ack, char flags)
{
for(unsigned int i = 0; i < t_group->nr_targets; i++)
char * pkt_buffer = ethdev->fn_send_prepare(ethdev, tid);
assert(pkt_buffer != NULL);
unsigned int l3_protocol = 0;
switch(addr->addrtype)
{
l2_send_to_target(ethdev, snd_buffer, l3_data_offset, l3_data_len,
&t_group->ether_addrs[i], t_group->vlans[i], l3_protocol);
case TFE_ADDR_STREAM_TUPLE4_V4: { l3_protocol = ETH_P_IP; break;}
case TFE_ADDR_STREAM_TUPLE4_V6: { l3_protocol = ETH_P_IPV6; break;}
default: assert(0);
}
unsigned int pkt_len = 0;
/* Ethernet and VLAN header */
pkt_len += ether_header_construct(ethdev, pkt_buffer, &target->ether_addr, target->vlan_tci, l3_protocol);
/* IPv4/IPv6 Header */
pkt_len += ip_header_construct_by_stream_addr(addr,
(unsigned char *)pkt_buffer + pkt_len,
payload_len + sizeof(struct tcphdr), 0, 0x1000, 0, 128, IPPROTO_TCP);
/* TCP header and payload */
pkt_len += tcp_header_construct_by_stream_addr(addr,
(unsigned char *)pkt_buffer + pkt_len, seq, ack, flags, 0xffff, 0,
(unsigned char *)payload, payload_len);
int ret = traffic_mirror_ethdev_finish(ethdev, tid, pkt_len);
if (unlikely(ret < 0))
{
//TODO: 统计计数
return;
}
}
static void tcp_segment_send_to_target_group(struct tfe_stream_addr * addr, struct traffic_mirror_ethdev * ethdev,
struct profile_table_ex_data * t_group, const char * payload, unsigned int payload_len,
unsigned int seq, unsigned int ack, char flags)
{
char pkt[ETHER_MAX_LEN];
unsigned sz_pkt_prepend = sizeof(struct ethhdr) + sizeof(struct vlan_hdr) +
sizeof(struct iphdr) + sizeof(struct tcphdr);
unsigned header_len = 0;
assert(sizeof(pkt) - sz_pkt_prepend >= payload_len);
memcpy(pkt + sz_pkt_prepend, payload, payload_len);
sz_pkt_prepend -= sizeof(struct tcp_hdr);
header_len += tcp_header_construct_by_stream_addr(addr, (unsigned char *)pkt + sz_pkt_prepend,
seq, ack, flags, 0xffff, 0, payload_len);
sz_pkt_prepend -= sizeof(struct iphdr);
header_len += ip_header_construct_by_stream_addr(addr, (unsigned char *)pkt + sz_pkt_prepend,
header_len + payload_len, 0, 0x1000, 0, 128, IPPROTO_TCP);
l2_send_to_target_group(ethdev, t_group, (unsigned char *)pkt, sz_pkt_prepend,
header_len + payload_len, ETHERTYPE_IP);
}
static void tcp_send_to_target_group(struct tfe_stream_addr * addr, struct traffic_mirror_ethdev * ethdev,
struct profile_table_ex_data * t_group, const char * payload,
unsigned int payload_len, unsigned int seq, unsigned int ack, char flags)
static void tcp_send_to_target(struct tfe_stream_addr * addr, struct traffic_mirror_ethdev * ethdev,
struct traffic_mirror_rebuild_target * target, unsigned int tid, const char * payload,
unsigned int payload_len, unsigned int seq, unsigned int ack, char flags)
{
unsigned int payload_offset = 0;
unsigned mss = ethdev->mtu - (sizeof(struct iphdr) + sizeof(struct tcphdr));
unsigned mss = ethdev->mtu - (MAX(sizeof(struct iphdr), sizeof(struct ip6_hdr)) + sizeof(struct tcphdr));
/* Handshake or farewall */
/* handshake or farewell */
if (payload == NULL || payload_len == 0)
{
tcp_segment_send_to_target_group(addr, ethdev, t_group, NULL, 0, seq, ack, flags);
tcp_segment_send_to_target_group(addr, ethdev, target, tid, NULL, 0, seq, ack, flags);
return;
}
@@ -325,14 +356,14 @@ static void tcp_send_to_target_group(struct tfe_stream_addr * addr, struct traff
unsigned int payload_sz_seg = MIN(payload_len - payload_offset, mss);
const char * payload_ptr_seg = payload + payload_offset;
tcp_segment_send_to_target_group(addr, ethdev, t_group, payload_ptr_seg, payload_sz_seg, seq, ack, flags);
tcp_segment_send_to_target_group(addr, ethdev, target, tid, payload_ptr_seg, payload_sz_seg, seq, ack, flags);
seq += payload_sz_seg;
payload_offset += payload_sz_seg;
}
}
struct traffic_mirror_rebuild * traffic_mirror_rebuild_create(struct tfe_stream_addr * addr,
struct profile_table_ex_data * target, struct traffic_mirror_ethdev * ethdev)
struct traffic_mirror_rebuild_target * target, struct traffic_mirror_ethdev * ethdev)
{
struct traffic_mirror_rebuild * instance = ALLOC(struct traffic_mirror_rebuild, 1);
instance->c_s_addr = addr;
@@ -353,22 +384,22 @@ void traffic_mirror_rebuild_destroy(struct traffic_mirror_rebuild * instance)
free(instance);
}
void traffic_mirror_rebuild_handshake(struct traffic_mirror_rebuild * instance)
void traffic_mirror_rebuild_handshake(struct traffic_mirror_rebuild * instance, unsigned int tid)
{
tcp_send_to_target_group(instance->c_s_addr, instance->ethdev, instance->target,
tcp_send_to_target(instance->c_s_addr, instance->ethdev, instance->target, tid,
NULL, 0, instance->c_seq, 0, TCP_SYN_FLAG);
tcp_send_to_target_group(instance->s_c_addr, instance->ethdev, instance->target,
tcp_send_to_target(instance->s_c_addr, instance->ethdev, instance->target, tid,
NULL, 0, instance->s_seq, instance->c_seq + 1, TCP_SYN_FLAG | TCP_ACK_FLAG);
tcp_send_to_target_group(instance->c_s_addr, instance->ethdev, instance->target,
tcp_send_to_target(instance->c_s_addr, instance->ethdev, instance->target, tid,
NULL, 0, instance->c_seq + 1, instance->s_seq + 1, TCP_ACK_FLAG);
instance->s_seq++;
instance->c_seq++;
}
void traffic_mirror_rebuild_data(struct traffic_mirror_rebuild * instance,
void traffic_mirror_rebuild_data(struct traffic_mirror_rebuild * instance, unsigned int tid,
const char * data, unsigned int datalen, enum tfe_conn_dir dir)
{
if (data == NULL || datalen == 0)
@@ -378,36 +409,36 @@ void traffic_mirror_rebuild_data(struct traffic_mirror_rebuild * instance,
if (dir == CONN_DIR_DOWNSTREAM)
{
tcp_send_to_target_group(instance->c_s_addr, instance->ethdev, instance->target,
tcp_send_to_target(instance->c_s_addr, instance->ethdev, instance->target, tid,
data, datalen, instance->c_seq, instance->s_seq, TCP_ACK_FLAG);
instance->c_seq += datalen;
}
else
{
tcp_send_to_target_group(instance->s_c_addr, instance->ethdev, instance->target,
tcp_send_to_target(instance->s_c_addr, instance->ethdev, instance->target, tid,
data, datalen, instance->s_seq, instance->c_seq, TCP_ACK_FLAG);
instance->s_seq += datalen;
}
}
void traffic_mirror_rebuild_farewell(struct traffic_mirror_rebuild * instance)
void traffic_mirror_rebuild_farewell(struct traffic_mirror_rebuild * instance, unsigned int tid)
{
/* C->S FIN */
tcp_send_to_target_group(instance->c_s_addr, instance->ethdev, instance->target,
tcp_send_to_target(instance->c_s_addr, instance->ethdev, instance->target, tid,
NULL, 0, instance->c_seq, instance->s_seq, TCP_FIN_FLAG | TCP_ACK_FLAG);
/* C->S FIN, ACK */
tcp_send_to_target_group(instance->s_c_addr, instance->ethdev, instance->target,
tcp_send_to_target(instance->s_c_addr, instance->ethdev, instance->target, tid,
NULL, 0, instance->s_seq, instance->c_seq + 1, TCP_ACK_FLAG);
instance->c_seq += 1;
/* S->C FIN */
tcp_send_to_target_group(instance->s_c_addr, instance->ethdev, instance->target,
tcp_send_to_target(instance->s_c_addr, instance->ethdev, instance->target, tid,
NULL, 0, instance->s_seq, instance->c_seq, TCP_FIN_FLAG | TCP_ACK_FLAG);
/* C->S FIN, ACK */
tcp_send_to_target_group(instance->c_s_addr, instance->ethdev, instance->target,
tcp_send_to_target(instance->c_s_addr, instance->ethdev, instance->target, tid,
NULL, 0, instance->c_seq, instance->s_seq + 1, TCP_ACK_FLAG);
instance->s_seq += 1;