Implements tcp packet stats for hosts, ases, networks in interface views

This commit is contained in:
Simone Mainardi 2019-08-27 11:16:20 +02:00
parent eb3542d7e7
commit af61cfd483
4 changed files with 123 additions and 88 deletions

View file

@ -33,6 +33,10 @@ typedef struct {
u_int64_t last, next;
} TCPPacketStats;
typedef struct {
u_int64_t last, next;
} TCPSeqNum;
typedef struct {
struct timeval lastTime;
u_int64_t total_delta_ms;
@ -47,6 +51,7 @@ typedef struct {
u_int32_t cli2srv_packets, srv2cli_packets;
u_int64_t cli2srv_bytes, srv2cli_bytes;
u_int64_t cli2srv_goodput_bytes, srv2cli_goodput_bytes;
TCPPacketStats tcp_stats_s2d, tcp_stats_d2s;
} FlowTrafficStats;
class Flow : public GenericHashEntry {
@ -154,7 +159,7 @@ class Flow : public GenericHashEntry {
IPPacketStats ip_stats_s2d, ip_stats_d2s;
/* TCP stats */
TCPPacketStats tcp_stats_s2d, tcp_stats_d2s;
TCPSeqNum tcp_seq_s2d, tcp_seq_d2s;
u_int16_t cli2srv_window, srv2cli_window;
time_t doNotExpireBefore; /*
@ -294,8 +299,11 @@ class Flow : public GenericHashEntry {
void setTcpFlags(u_int8_t flags, bool src2dst_direction);
void updateTcpFlags(const struct bpf_timeval *when,
u_int8_t flags, bool src2dst_direction);
void incTcpBadStats(bool src2dst_direction,
u_int32_t ooo_pkts, u_int32_t retr_pkts, u_int32_t lost_pkts, u_int32_t keep_alive_pkts);
static void incTcpBadStats(bool src2dst_direction,
FlowTrafficStats *fts,
Host *cli, Host *srv,
u_int32_t ooo_pkts, u_int32_t retr_pkts,
u_int32_t lost_pkts, u_int32_t keep_alive_pkts);
void updateTcpSeqNum(const struct bpf_timeval *when,
u_int32_t seq_num, u_int32_t ack_seq_num,
@ -355,6 +363,7 @@ class Flow : public GenericHashEntry {
inline u_int64_t get_partial_packets_cli2srv() const { return last_db_dump.delta.cli2srv_packets; };
inline u_int64_t get_partial_packets_srv2cli() const { return last_db_dump.delta.srv2cli_packets; };
bool get_partial_traffic_stats_view(FlowTrafficStats *delta, bool *first_partial);
inline FlowTrafficStats * getFlowTrafficStats() { return &stats; };
bool update_partial_traffic_stats_db_dump();
inline float get_bytes_thpt() const { return(bytes_thpt); };
inline float get_goodput_bytes_thpt() const { return(goodput_bytes_thpt); };

View file

@ -143,7 +143,7 @@ Flow::Flow(NetworkInterface *_iface,
rttSec = 0, cli2srv_window = srv2cli_window = 0,
c2sFirstGoodputTime.tv_sec = c2sFirstGoodputTime.tv_usec = 0;
memset(&ip_stats_s2d, 0, sizeof(ip_stats_s2d)), memset(&ip_stats_d2s, 0, sizeof(ip_stats_d2s));
memset(&tcp_stats_s2d, 0, sizeof(tcp_stats_s2d)), memset(&tcp_stats_d2s, 0, sizeof(tcp_stats_d2s));
memset(&tcp_seq_s2d, 0, sizeof(tcp_seq_s2d)), memset(&tcp_seq_d2s, 0, sizeof(tcp_seq_d2s));
memset(&clientNwLatency, 0, sizeof(clientNwLatency)), memset(&serverNwLatency, 0, sizeof(serverNwLatency));
if(!iface->isPacketInterface())
@ -893,21 +893,21 @@ char* Flow::print(char *buf, u_int buf_len) const {
if(protocol == IPPROTO_TCP) {
int len = 0;
if((tcp_stats_s2d.pktOOO+tcp_stats_d2s.pktOOO) > 0)
if((stats.tcp_stats_s2d.pktOOO+stats.tcp_stats_d2s.pktOOO) > 0)
len += snprintf(&tcp_buf[len], sizeof(tcp_buf)-len, "[OOO=%u/%u]",
tcp_stats_s2d.pktOOO, tcp_stats_d2s.pktOOO);
stats.tcp_stats_s2d.pktOOO, stats.tcp_stats_d2s.pktOOO);
if((tcp_stats_s2d.pktLost+tcp_stats_d2s.pktLost) > 0)
if((stats.tcp_stats_s2d.pktLost+stats.tcp_stats_d2s.pktLost) > 0)
len += snprintf(&tcp_buf[len], sizeof(tcp_buf)-len, "[Lost=%u/%u]",
tcp_stats_s2d.pktLost, tcp_stats_d2s.pktLost);
stats.tcp_stats_s2d.pktLost, stats.tcp_stats_d2s.pktLost);
if((tcp_stats_s2d.pktRetr+tcp_stats_d2s.pktRetr) > 0)
if((stats.tcp_stats_s2d.pktRetr+stats.tcp_stats_d2s.pktRetr) > 0)
len += snprintf(&tcp_buf[len], sizeof(tcp_buf)-len, "[Retr=%u/%u]",
tcp_stats_s2d.pktRetr, tcp_stats_d2s.pktRetr);
stats.tcp_stats_s2d.pktRetr, stats.tcp_stats_d2s.pktRetr);
if((tcp_stats_s2d.pktKeepAlive+tcp_stats_d2s.pktKeepAlive) > 0)
if((stats.tcp_stats_s2d.pktKeepAlive+stats.tcp_stats_d2s.pktKeepAlive) > 0)
len += snprintf(&tcp_buf[len], sizeof(tcp_buf)-len, "[KeepAlive=%u/%u]",
tcp_stats_s2d.pktKeepAlive, tcp_stats_d2s.pktKeepAlive);
stats.tcp_stats_s2d.pktKeepAlive, stats.tcp_stats_d2s.pktKeepAlive);
}
snprintf(buf, buf_len,
@ -1846,14 +1846,14 @@ void Flow::lua(lua_State* vm, AddressTree * ptree,
if(protocol == IPPROTO_TCP) {
lua_push_bool_table_entry(vm, "tcp.seq_problems",
(tcp_stats_s2d.pktRetr
| tcp_stats_s2d.pktOOO
| tcp_stats_s2d.pktLost
| tcp_stats_s2d.pktKeepAlive
| tcp_stats_d2s.pktRetr
| tcp_stats_d2s.pktOOO
| tcp_stats_d2s.pktLost
| tcp_stats_d2s.pktKeepAlive) ? true : false);
(stats.tcp_stats_s2d.pktRetr
| stats.tcp_stats_s2d.pktOOO
| stats.tcp_stats_s2d.pktLost
| stats.tcp_stats_s2d.pktKeepAlive
| stats.tcp_stats_d2s.pktRetr
| stats.tcp_stats_d2s.pktOOO
| stats.tcp_stats_d2s.pktLost
| stats.tcp_stats_d2s.pktKeepAlive) ? true : false);
lua_push_float_table_entry(vm, "tcp.nw_latency.client", toMs(&clientNwLatency));
lua_push_float_table_entry(vm, "tcp.nw_latency.server", toMs(&serverNwLatency));
@ -1861,14 +1861,14 @@ void Flow::lua(lua_State* vm, AddressTree * ptree,
lua_push_float_table_entry(vm, "tcp.max_thpt.cli2srv", getCli2SrvMaxThpt());
lua_push_float_table_entry(vm, "tcp.max_thpt.srv2cli", getSrv2CliMaxThpt());
lua_push_uint64_table_entry(vm, "cli2srv.retransmissions", tcp_stats_s2d.pktRetr);
lua_push_uint64_table_entry(vm, "cli2srv.out_of_order", tcp_stats_s2d.pktOOO);
lua_push_uint64_table_entry(vm, "cli2srv.lost", tcp_stats_s2d.pktLost);
lua_push_uint64_table_entry(vm, "cli2srv.keep_alive", tcp_stats_s2d.pktKeepAlive);
lua_push_uint64_table_entry(vm, "srv2cli.retransmissions", tcp_stats_d2s.pktRetr);
lua_push_uint64_table_entry(vm, "srv2cli.out_of_order", tcp_stats_d2s.pktOOO);
lua_push_uint64_table_entry(vm, "srv2cli.lost", tcp_stats_d2s.pktLost);
lua_push_uint64_table_entry(vm, "srv2cli.keep_alive", tcp_stats_d2s.pktKeepAlive);
lua_push_uint64_table_entry(vm, "cli2srv.retransmissions", stats.tcp_stats_s2d.pktRetr);
lua_push_uint64_table_entry(vm, "cli2srv.out_of_order", stats.tcp_stats_s2d.pktOOO);
lua_push_uint64_table_entry(vm, "cli2srv.lost", stats.tcp_stats_s2d.pktLost);
lua_push_uint64_table_entry(vm, "cli2srv.keep_alive", stats.tcp_stats_s2d.pktKeepAlive);
lua_push_uint64_table_entry(vm, "srv2cli.retransmissions", stats.tcp_stats_d2s.pktRetr);
lua_push_uint64_table_entry(vm, "srv2cli.out_of_order", stats.tcp_stats_d2s.pktOOO);
lua_push_uint64_table_entry(vm, "srv2cli.lost", stats.tcp_stats_d2s.pktLost);
lua_push_uint64_table_entry(vm, "srv2cli.keep_alive", stats.tcp_stats_d2s.pktKeepAlive);
lua_push_uint64_table_entry(vm, "cli2srv.tcp_flags", src2dst_tcp_flags);
lua_push_uint64_table_entry(vm, "srv2cli.tcp_flags", dst2src_tcp_flags);
@ -2500,6 +2500,16 @@ bool Flow::get_partial_traffic_stats(FlowTrafficStats **dst, FlowTrafficStats *f
fts->cli2srv_goodput_bytes = tmp.cli2srv_goodput_bytes - (*dst)->cli2srv_goodput_bytes;
fts->srv2cli_goodput_bytes = tmp.srv2cli_goodput_bytes - (*dst)->srv2cli_goodput_bytes;
fts->tcp_stats_s2d.pktRetr = tmp.tcp_stats_s2d.pktRetr - (*dst)->tcp_stats_s2d.pktRetr,
fts->tcp_stats_s2d.pktOOO = tmp.tcp_stats_s2d.pktOOO - (*dst)->tcp_stats_s2d.pktOOO,
fts->tcp_stats_s2d.pktLost = tmp.tcp_stats_s2d.pktLost - (*dst)->tcp_stats_s2d.pktLost,
fts->tcp_stats_s2d.pktKeepAlive = tmp.tcp_stats_s2d.pktKeepAlive - (*dst)->tcp_stats_s2d.pktKeepAlive;
fts->tcp_stats_d2s.pktRetr = tmp.tcp_stats_d2s.pktRetr - (*dst)->tcp_stats_d2s.pktRetr,
fts->tcp_stats_d2s.pktOOO = tmp.tcp_stats_d2s.pktOOO - (*dst)->tcp_stats_d2s.pktOOO,
fts->tcp_stats_d2s.pktLost = tmp.tcp_stats_d2s.pktLost - (*dst)->tcp_stats_d2s.pktLost,
fts->tcp_stats_d2s.pktKeepAlive = tmp.tcp_stats_d2s.pktKeepAlive - (*dst)->tcp_stats_d2s.pktKeepAlive;
memcpy(*dst, &tmp, sizeof(tmp));
return true;
@ -2860,6 +2870,8 @@ u_int32_t Flow::getNextTcpSeq ( u_int8_t tcpFlags,
/* *************************************** */
void Flow::incTcpBadStats(bool src2dst_direction,
FlowTrafficStats *fts,
Host *cli, Host *srv,
u_int32_t ooo_pkts,
u_int32_t retr_pkts,
u_int32_t lost_pkts,
@ -2867,46 +2879,48 @@ void Flow::incTcpBadStats(bool src2dst_direction,
#ifdef HAVE_NEDGE
return;
#endif
TCPPacketStats * stats;
int16_t cli_network_id = -1, srv_network_id = -1;
u_int32_t cli_asn = (u_int32_t)-1, srv_asn = (u_int32_t)-1;
AutonomousSystem *cli_as = NULL, *srv_as = NULL;
NetworkStats *cli_network_stats = NULL, *srv_network_stats = NULL;
bool cli_and_srv_in_same_subnet = false, cli_and_srv_in_same_as = false;
if(src2dst_direction)
stats = &tcp_stats_s2d;
else
stats = &tcp_stats_d2s;
stats->pktKeepAlive += keep_alive_pkts;
stats->pktRetr += retr_pkts;
stats->pktOOO += ooo_pkts;
stats->pktLost += lost_pkts;
if(cli_host) {
cli_network_id = cli_host->get_local_network_id();
cli_network_stats = cli_host->getNetworkStats(cli_network_id);
cli_asn = cli_host->get_asn();
cli_as = cli_host->get_as();
if(fts) {
TCPPacketStats * cur_stats;
if(src2dst_direction)
cli_host->incSentTcp(ooo_pkts, retr_pkts, lost_pkts, keep_alive_pkts);
cur_stats = &fts->tcp_stats_s2d;
else
cli_host->incRcvdTcp(ooo_pkts, retr_pkts, lost_pkts, keep_alive_pkts);
cur_stats = &fts->tcp_stats_d2s;
cur_stats->pktKeepAlive += keep_alive_pkts;
cur_stats->pktRetr += retr_pkts;
cur_stats->pktOOO += ooo_pkts;
cur_stats->pktLost += lost_pkts;
}
if(srv_host) {
srv_network_id = srv_host->get_local_network_id();
srv_network_stats = srv_host->getNetworkStats(srv_network_id);
srv_asn = srv_host->get_asn();
srv_as = srv_host->get_as();
if(cli) {
cli_network_id = cli->get_local_network_id();
cli_network_stats = cli->getNetworkStats(cli_network_id);
cli_asn = cli->get_asn();
cli_as = cli->get_as();
if(src2dst_direction)
srv_host->incRcvdTcp(ooo_pkts, retr_pkts, lost_pkts, keep_alive_pkts);
cli->incSentTcp(ooo_pkts, retr_pkts, lost_pkts, keep_alive_pkts);
else
srv_host->incSentTcp(ooo_pkts, retr_pkts, lost_pkts, keep_alive_pkts);
cli->incRcvdTcp(ooo_pkts, retr_pkts, lost_pkts, keep_alive_pkts);
}
if(srv) {
srv_network_id = srv->get_local_network_id();
srv_network_stats = srv->getNetworkStats(srv_network_id);
srv_asn = srv->get_asn();
srv_as = srv->get_as();
if(src2dst_direction)
srv->incRcvdTcp(ooo_pkts, retr_pkts, lost_pkts, keep_alive_pkts);
else
srv->incSentTcp(ooo_pkts, retr_pkts, lost_pkts, keep_alive_pkts);
}
if(cli_network_id >= 0 && (cli_network_id == srv_network_id))
@ -2976,73 +2990,73 @@ void Flow::updateTcpSeqNum(const struct bpf_timeval *when,
payload_Len);
if(src2dst_direction) {
if(debug) ntop->getTrace()->traceEvent(TRACE_WARNING, "[src2dst][last: %u][next: %u]", tcp_stats_s2d.last, tcp_stats_s2d.next);
if(debug) ntop->getTrace()->traceEvent(TRACE_WARNING, "[src2dst][last: %u][next: %u]", tcp_seq_s2d.last, tcp_seq_s2d.next);
if(window > 0) srv2cli_window = window; /* Note the window is reverted */
if(tcp_stats_s2d.next > 0) {
if((tcp_stats_s2d.next != seq_num) /* If equal, seq_num is the expected seq_num as determined with prev. segment */
&& (tcp_stats_s2d.next != (seq_num - 1))) {
if((seq_num == tcp_stats_s2d.next - 1)
if(tcp_seq_s2d.next > 0) {
if((tcp_seq_s2d.next != seq_num) /* If equal, seq_num is the expected seq_num as determined with prev. segment */
&& (tcp_seq_s2d.next != (seq_num - 1))) {
if((seq_num == tcp_seq_s2d.next - 1)
&& (payload_Len == 0 || payload_Len == 1)
&& ((flags & (TH_SYN|TH_FIN|TH_RST)) == 0)) {
if(debug) ntop->getTrace()->traceEvent(TRACE_WARNING, "[src2dst] Packet KeepAlive");
cnt_keep_alive++;
} else if(tcp_stats_s2d.last == seq_num) {
if (tcp_stats_s2d.next != tcp_stats_s2d.last) {
} else if(tcp_seq_s2d.last == seq_num) {
if (tcp_seq_s2d.next != tcp_seq_s2d.last) {
cnt_retx++;
if(debug) ntop->getTrace()->traceEvent(TRACE_WARNING, "[src2dst] Packet retransmission");
}
} else if((tcp_stats_s2d.last > seq_num)
&& (seq_num < tcp_stats_s2d.next)) {
} else if((tcp_seq_s2d.last > seq_num)
&& (seq_num < tcp_seq_s2d.next)) {
cnt_lost++;
if(debug) ntop->getTrace()->traceEvent(TRACE_WARNING, "[src2dst] Packet lost [last: %u][act: %u]", tcp_stats_s2d.last, seq_num);
if(debug) ntop->getTrace()->traceEvent(TRACE_WARNING, "[src2dst] Packet lost [last: %u][act: %u]", tcp_seq_s2d.last, seq_num);
} else {
cnt_ooo++;
update_last_seqnum = ((seq_num - 1) > tcp_stats_s2d.last) ? true : false;
if(debug) ntop->getTrace()->traceEvent(TRACE_WARNING, "[src2dst] Packet OOO [last: %u][act: %u]", tcp_stats_s2d.last, seq_num);
update_last_seqnum = ((seq_num - 1) > tcp_seq_s2d.last) ? true : false;
if(debug) ntop->getTrace()->traceEvent(TRACE_WARNING, "[src2dst] Packet OOO [last: %u][act: %u]", tcp_seq_s2d.last, seq_num);
}
}
}
tcp_stats_s2d.next = next_seq_num;
if(update_last_seqnum) tcp_stats_s2d.last = seq_num;
tcp_seq_s2d.next = next_seq_num;
if(update_last_seqnum) tcp_seq_s2d.last = seq_num;
} else {
if(debug) ntop->getTrace()->traceEvent(TRACE_WARNING, "[dst2src][last: %u][next: %u]", tcp_stats_d2s.last, tcp_stats_d2s.next);
if(debug) ntop->getTrace()->traceEvent(TRACE_WARNING, "[dst2src][last: %u][next: %u]", tcp_seq_d2s.last, tcp_seq_d2s.next);
if(window > 0) cli2srv_window = window; /* Note the window is reverted */
if(tcp_stats_d2s.next > 0) {
if((tcp_stats_d2s.next != seq_num)
&& (tcp_stats_d2s.next != (seq_num-1))) {
if((seq_num == tcp_stats_d2s.next - 1)
if(tcp_seq_d2s.next > 0) {
if((tcp_seq_d2s.next != seq_num)
&& (tcp_seq_d2s.next != (seq_num-1))) {
if((seq_num == tcp_seq_d2s.next - 1)
&& (payload_Len == 0 || payload_Len == 1)
&& ((flags & (TH_SYN|TH_FIN|TH_RST)) == 0)) {
if(debug) ntop->getTrace()->traceEvent(TRACE_WARNING, "[dst2src] Packet KeepAlive");
cnt_keep_alive++;
} else if(tcp_stats_d2s.last == seq_num) {
if (tcp_stats_d2s.next != tcp_stats_d2s.last) {
} else if(tcp_seq_d2s.last == seq_num) {
if (tcp_seq_d2s.next != tcp_seq_d2s.last) {
cnt_retx++;
if(debug) ntop->getTrace()->traceEvent(TRACE_WARNING, "[dst2src] Packet retransmission");
}
// bytes
} else if((tcp_stats_d2s.last > seq_num)
&& (seq_num < tcp_stats_d2s.next)) {
} else if((tcp_seq_d2s.last > seq_num)
&& (seq_num < tcp_seq_d2s.next)) {
cnt_lost++;
if(debug) ntop->getTrace()->traceEvent(TRACE_WARNING, "[dst2src] Packet lost [last: %u][act: %u]", tcp_stats_d2s.last, seq_num);
if(debug) ntop->getTrace()->traceEvent(TRACE_WARNING, "[dst2src] Packet lost [last: %u][act: %u]", tcp_seq_d2s.last, seq_num);
} else {
cnt_ooo++;
update_last_seqnum = ((seq_num - 1) > tcp_stats_d2s.last) ? true : false;
if(debug) ntop->getTrace()->traceEvent(TRACE_WARNING, "[dst2src] [last: %u][next: %u]", tcp_stats_d2s.last, tcp_stats_d2s.next);
if(debug) ntop->getTrace()->traceEvent(TRACE_WARNING, "[dst2src] Packet OOO [last: %u][act: %u]", tcp_stats_d2s.last, seq_num);
update_last_seqnum = ((seq_num - 1) > tcp_seq_d2s.last) ? true : false;
if(debug) ntop->getTrace()->traceEvent(TRACE_WARNING, "[dst2src] [last: %u][next: %u]", tcp_seq_d2s.last, tcp_seq_d2s.next);
if(debug) ntop->getTrace()->traceEvent(TRACE_WARNING, "[dst2src] Packet OOO [last: %u][act: %u]", tcp_seq_d2s.last, seq_num);
}
}
}
tcp_stats_d2s.next = next_seq_num;
if(update_last_seqnum) tcp_stats_d2s.last = seq_num;
tcp_seq_d2s.next = next_seq_num;
if(update_last_seqnum) tcp_seq_d2s.last = seq_num;
}
if(cnt_keep_alive || cnt_lost || cnt_ooo || cnt_retx)
incTcpBadStats(src2dst_direction, cnt_ooo, cnt_retx, cnt_lost, cnt_keep_alive);
incTcpBadStats(src2dst_direction, getFlowTrafficStats(), get_cli_host(), get_srv_host(), cnt_ooo, cnt_retx, cnt_lost, cnt_keep_alive);
}
/* *************************************** */
@ -3744,7 +3758,7 @@ FlowStatus Flow::getFlowStatus() {
#ifndef HAVE_NEDGE
/* All flows */
issues_count = tcp_stats_s2d.pktRetr + tcp_stats_s2d.pktOOO + tcp_stats_s2d.pktLost;
issues_count = stats.tcp_stats_s2d.pktRetr + stats.tcp_stats_s2d.pktOOO + stats.tcp_stats_s2d.pktLost;
if(issues_count > CONST_TCP_CHECK_ISSUES_THRESHOLD) {
if(issues_count > (stats.cli2srv_packets / CONST_TCP_CHECK_SEVERE_ISSUES_RATIO))
return status_tcp_severe_connection_issues;
@ -3752,7 +3766,7 @@ FlowStatus Flow::getFlowStatus() {
return status_tcp_connection_issues;
}
issues_count = tcp_stats_d2s.pktRetr + tcp_stats_d2s.pktOOO + tcp_stats_d2s.pktLost;
issues_count = stats.tcp_stats_d2s.pktRetr + stats.tcp_stats_d2s.pktOOO + stats.tcp_stats_d2s.pktLost;
if(issues_count > CONST_TCP_CHECK_ISSUES_THRESHOLD) {
if(issues_count > (stats.srv2cli_packets / CONST_TCP_CHECK_SEVERE_ISSUES_RATIO))
return status_tcp_severe_connection_issues;

View file

@ -1333,10 +1333,14 @@ void NetworkInterface::processFlow(ParsedFlow *zflow, bool zmq_flow) {
/* TCP flags are cumulated client + server */
flow->setTcpFlags(zflow->tcp.tcp_flags, src2dst_direction);
flow->incTcpBadStats(true,
Flow::incTcpBadStats(true,
flow->getFlowTrafficStats(),
flow->get_cli_host(), flow->get_srv_host(),
zflow->tcp.ooo_in_pkts, zflow->tcp.retr_in_pkts,
zflow->tcp.lost_in_pkts, 0 /* TODO: add keepalive */);
flow->incTcpBadStats(false,
Flow::incTcpBadStats(false,
flow->getFlowTrafficStats(),
flow->get_cli_host(), flow->get_srv_host(),
zflow->tcp.ooo_out_pkts, zflow->tcp.retr_out_pkts,
zflow->tcp.lost_out_pkts, 0 /* TODO: add keepalive */);
}

View file

@ -302,6 +302,14 @@ static bool viewed_flows_walker(GenericHashEntry *flow, void *user_data, bool *m
partials.srv2cli_bytes + partials.cli2srv_bytes,
partials.srv2cli_packets + partials.cli2srv_packets,
24 /* 8 Preamble + 4 CRC + 12 IFG */ + 14 /* Ethernet header */);
Flow::incTcpBadStats(true /* src2dst */, NULL, cli_host, srv_host,
partials.tcp_stats_s2d.pktOOO, partials.tcp_stats_s2d.pktRetr,
partials.tcp_stats_s2d.pktLost, partials.tcp_stats_s2d.pktKeepAlive);
Flow::incTcpBadStats(false /* dst2src */, NULL, cli_host, srv_host,
partials.tcp_stats_d2s.pktOOO, partials.tcp_stats_d2s.pktRetr,
partials.tcp_stats_d2s.pktLost, partials.tcp_stats_d2s.pktKeepAlive);
}
}