diff --git a/plugin/business/traffic-mirror/src/entry.cpp b/plugin/business/traffic-mirror/src/entry.cpp index 23fa24a..6943df5 100644 --- a/plugin/business/traffic-mirror/src/entry.cpp +++ b/plugin/business/traffic-mirror/src/entry.cpp @@ -217,7 +217,7 @@ void profile_table_ex_data_new_cb(int table_id, const char * key, const char * t goto success; } - json_item = cJSON_GetObjectItem(json_item, "mac"); + json_item = cJSON_GetObjectItem(json_root, "mac"); if (json_item) { if (unlikely(!cJSON_IsArray(json_item))) diff --git a/plugin/business/traffic-mirror/src/rebuild.cpp b/plugin/business/traffic-mirror/src/rebuild.cpp index 9694d9e..fe856d9 100644 --- a/plugin/business/traffic-mirror/src/rebuild.cpp +++ b/plugin/business/traffic-mirror/src/rebuild.cpp @@ -43,6 +43,84 @@ struct tcp_hdr { #define TCP_FIN_FLAG 0x01 #define TCP_FLAG_ALL 0x3F +static inline uint32_t __rte_raw_cksum(const void *buf, size_t len, uint32_t sum) +{ + /* workaround gcc strict-aliasing warning */ + uintptr_t ptr = (uintptr_t) buf; + typedef uint16_t __attribute__((__may_alias__)) u16_p; + const u16_p * u16 = (const u16_p *) ptr; + + while (len >= (sizeof(*u16) * 4)) + { + sum += u16[0]; + sum += u16[1]; + sum += u16[2]; + sum += u16[3]; + len -= sizeof(*u16) * 4; + u16 += 4; + } + while (len >= sizeof(*u16)) + { + sum += *u16; + len -= sizeof(*u16); + u16 += 1; + } + + /* if length is in odd bytes */ + if (len == 1) + sum += *((const uint8_t *) u16); + + return sum; +} + +static inline uint16_t __rte_raw_cksum_reduce(uint32_t sum) +{ + sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff); + sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff); + return (uint16_t) sum; +} + +static inline uint16_t rte_raw_cksum(const void *buf, size_t len) +{ + uint32_t sum = __rte_raw_cksum(buf, len, 0); + return __rte_raw_cksum_reduce(sum); +} + +static inline uint16_t __ipv4_cksum(const struct iphdr * ipv4_hdr) +{ + uint16_t cksum = rte_raw_cksum(ipv4_hdr, sizeof(struct iphdr)); + 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) +{ + struct ipv4_psd_header + { + uint32_t src_addr; /* IP address of source host. */ + uint32_t dst_addr; /* IP address of destination host. */ + uint8_t zero; /* zero. */ + uint8_t proto; /* L4 protocol type. */ + uint16_t len; /* L4 length. */ + } psd_hdr; + + psd_hdr.src_addr = addr->tuple4_v4->saddr.s_addr; + psd_hdr.dst_addr = addr->tuple4_v4->daddr.s_addr; + psd_hdr.zero = 0; + psd_hdr.proto = IPPROTO_TCP; + psd_hdr.len = htons(l4_len); + + 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; + + return cksum; +} + 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) @@ -63,10 +141,13 @@ 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 seq, unsigned int ack, unsigned char flags, unsigned short win, unsigned short urg, + 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) { @@ -83,7 +164,23 @@ static int tcp_header_construct_by_stream_addr(struct tfe_stream_addr * addr, un assert(0); } - return tcp_header_construct(buf, sport, dport, seq, ack, flags, win, urg); + tcphdr_len = tcp_header_construct(buf, sport, dport, seq, ack, flags, win, urg); + if (addr->addrtype == TFE_ADDR_STREAM_TUPLE4_V4) + { + cksum = __tcpudp_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); + } + + struct tcp_hdr * tcp_hdr = (struct tcp_hdr *)buf; + tcp_hdr->cksum = cksum; + return tcphdr_len; } static int ipv4_header_construct(unsigned char *buf, unsigned short carry_layer_len, @@ -103,6 +200,8 @@ static int ipv4_header_construct(unsigned char *buf, unsigned short carry_layer_ ip_hdr->saddr = src; ip_hdr->daddr = dst; + /* checksum */ + ip_hdr->check = __ipv4_cksum(ip_hdr); return sizeof(struct iphdr); } @@ -197,7 +296,7 @@ static void tcp_segment_send_to_target_group(struct tfe_stream_addr * addr, stru 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); + 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,