解密流量转发功能适配MARSIOv4
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user