From 7b3f57d5007dd2cf4127c2c3a9a7cd0f64d5d6e9 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sun, 21 Dec 2008 19:39:39 +0100 Subject: src: add network statistics via `-s network' This patch adds networks statistics that you can check via `conntrackd -s network'. This information is useful for trouble-shooting. This patch replaces several log messages that can be triggered in runtime. The idea behind this patch is to avoid log message flooding under errors. Signed-off-by: Pablo Neira Ayuso --- conntrackd.8 | 5 ++-- include/conntrackd.h | 18 ++++++++++-- src/main.c | 20 +++++++++++-- src/network.c | 7 +++-- src/sync-ftfw.c | 4 +-- src/sync-mode.c | 83 +++++++++++++++++++++++++++++++++++++++------------- 6 files changed, 104 insertions(+), 33 deletions(-) diff --git a/conntrackd.8 b/conntrackd.8 index 2d7b228..ab834fb 100644 --- a/conntrackd.8 +++ b/conntrackd.8 @@ -44,8 +44,9 @@ option will not flush your internal and external cache). .BI "-k " Kill the daemon .TP -.BI "-s " -Dump statistics +.BI "-s " "[|network]" +Dump statistics. If no parameter is passed, it displays the general statistics. +If "network" is passed as parameter it displays the networking statistics. .TP .BI "-R " Force a resync against the kernel connection tracking table diff --git a/include/conntrackd.h b/include/conntrackd.h index 3b5620e..7199985 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -26,6 +26,7 @@ #define DUMP_EXT_XML 25 /* dump external cache in XML */ #define RESET_TIMERS 26 /* reset kernel timers */ #define DEBUG_INFO 27 /* show debug info (if any) */ +#define STATS_NETWORK 28 /* extended network stats */ #define DEFAULT_CONFIGFILE "/etc/conntrackd/conntrackd.conf" #define DEFAULT_LOCKFILE "/var/lock/conntrackd.lock" @@ -109,7 +110,6 @@ struct ct_general_state { struct fds *fds; /* statistics */ - uint64_t malformed; uint64_t bytes[NFCT_DIR_MAX]; uint64_t packets[NFCT_DIR_MAX]; }; @@ -126,10 +126,22 @@ struct ct_sync_state { struct sync_mode *sync; /* sync mode */ + /* statistics */ + struct { + uint64_t msg_rcv_malformed; + uint32_t msg_rcv_bad_version; + uint32_t msg_rcv_bad_payload; + uint32_t msg_rcv_bad_header; + uint32_t msg_rcv_bad_type; + uint32_t msg_rcv_truncated; + uint32_t msg_rcv_bad_size; + uint32_t msg_snd_malformed; + uint64_t msg_rcv_lost; + uint64_t msg_rcv_before; + } error; + uint32_t last_seq_sent; /* last sequence number sent */ uint32_t last_seq_recv; /* last sequence number recv */ - uint64_t packets_replayed; /* number of replayed packets */ - uint64_t packets_lost; /* lost packets: sequence tracking */ }; #define STATE_STATS(x) state.stats->x diff --git a/src/main.c b/src/main.c index f811acf..022915d 100644 --- a/src/main.c +++ b/src/main.c @@ -43,7 +43,7 @@ static const char usage_client_commands[] = " -i, display content of the internal cache\n" " -e, display the content of the external cache\n" " -k, kill conntrack daemon\n" - " -s, dump statistics\n" + " -s [|network], dump statistics\n" " -R, resync with kernel conntrack table\n" " -n, request resync with other node (only FT-FW and NOTRACK modes)\n" " -x, dump cache in XML format (requires -i or -e)" @@ -155,7 +155,23 @@ int main(int argc, char *argv[]) break; case 's': set_operation_mode(&type, REQUEST, argv); - action = STATS; + /* we've got a parameter */ + if (i+1 < argc && argv[i+1][0] != '-') { + if (strncmp(argv[i+1], "network", + strlen(argv[i+1])) == 0) { + action = STATS_NETWORK; + i++; + } else { + fprintf(stderr, "ERROR: unknown " + "parameter `%s' for " + "option `-s'\n", + argv[i+1]); + exit(EXIT_FAILURE); + } + } else { + /* default to general statistics */ + action = STATS; + } break; case 'S': fprintf(stderr, "WARNING: -S option is obsolete. " diff --git a/src/network.c b/src/network.c index 090dec8..598195f 100644 --- a/src/network.c +++ b/src/network.c @@ -147,14 +147,17 @@ int mcast_track_seq(uint32_t seq, uint32_t *exp_seq) /* out of sequence: some messages got lost */ if (after(seq, STATE_SYNC(last_seq_recv)+1)) { - STATE_SYNC(packets_lost) += seq-STATE_SYNC(last_seq_recv)+1; + STATE_SYNC(error).msg_rcv_lost += + seq - STATE_SYNC(last_seq_recv) + 1; ret = SEQ_AFTER; goto out; } /* out of sequence: replayed/delayed packet? */ - if (before(seq, STATE_SYNC(last_seq_recv)+1)) + if (before(seq, STATE_SYNC(last_seq_recv)+1)) { + STATE_SYNC(error).msg_rcv_before++; ret = SEQ_BEFORE; + } out: *exp_seq = STATE_SYNC(last_seq_recv)+1; diff --git a/src/sync-ftfw.c b/src/sync-ftfw.c index 4758710..44e8f2f 100644 --- a/src/sync-ftfw.c +++ b/src/sync-ftfw.c @@ -441,8 +441,6 @@ static int ftfw_recv(const struct nethdr *net) case SEQ_BEFORE: /* we don't accept delayed packets */ - dlog(LOG_WARNING, "Received seq=%u before expected seq=%u", - net->seq, exp_seq); ret = MSG_DROP; break; @@ -521,7 +519,7 @@ static int tx_queue_xmit(void *data1, const void *data2) } else if (IS_ALIVE(net)) { nethdr_set_ctl(net); } else { - dlog(LOG_ERR, "sending unknown control message?"); + STATE_SYNC(error).msg_snd_malformed++; return 0; } HDR_HOST2NETWORK(net); diff --git a/src/sync-mode.c b/src/sync-mode.c index 6aad8f7..e7b9359 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -41,8 +41,8 @@ static void do_mcast_handler_step(struct nethdr *net, size_t remain) struct us_conntrack *u; if (net->version != CONNTRACKD_PROTOCOL_VERSION) { - STATE(malformed)++; - dlog(LOG_WARNING, "wrong protocol version `%u'", net->version); + STATE_SYNC(error).msg_rcv_malformed++; + STATE_SYNC(error).msg_rcv_bad_version++; return; } @@ -53,22 +53,23 @@ static void do_mcast_handler_step(struct nethdr *net, size_t remain) case MSG_CTL: return; case MSG_BAD: - STATE(malformed)++; + STATE_SYNC(error).msg_rcv_malformed++; + STATE_SYNC(error).msg_rcv_bad_header++; return; default: break; } if (net->type > NET_T_STATE_MAX) { - STATE(malformed)++; - dlog(LOG_ERR, "bad state message type"); + STATE_SYNC(error).msg_rcv_malformed++; + STATE_SYNC(error).msg_rcv_bad_type++; return; } memset(ct, 0, sizeof(__ct)); if (parse_payload(ct, net, remain) == -1) { - STATE(malformed)++; - dlog(LOG_ERR, "parsing failed: malformed message"); + STATE_SYNC(error).msg_rcv_malformed++; + STATE_SYNC(error).msg_rcv_bad_payload++; return; } @@ -103,8 +104,8 @@ retry: debug_ct(ct, "can't destroy"); break; default: - STATE(malformed)++; - dlog(LOG_ERR, "mcast unknown query %d\n", net->type); + STATE_SYNC(error).msg_rcv_malformed++; + STATE_SYNC(error).msg_rcv_bad_type++; break; } } @@ -125,31 +126,31 @@ static void mcast_handler(void) struct nethdr *net = (struct nethdr *) ptr; if (remain < NETHDR_SIZ) { - STATE(malformed)++; - dlog(LOG_WARNING, "no room for header"); + STATE_SYNC(error).msg_rcv_malformed++; + STATE_SYNC(error).msg_rcv_truncated++; break; } if (ntohs(net->len) > remain) { - STATE(malformed)++; - dlog(LOG_WARNING, "fragmented message"); + STATE_SYNC(error).msg_rcv_malformed++; + STATE_SYNC(error).msg_rcv_bad_size++; break; } if (IS_ACK(net) || IS_NACK(net) || IS_RESYNC(net)) { if (remain < NETHDR_ACK_SIZ) { - STATE(malformed)++; - dlog(LOG_WARNING, "no room for ctl message"); + STATE_SYNC(error).msg_rcv_malformed++; + STATE_SYNC(error).msg_rcv_truncated++; } if (ntohs(net->len) < NETHDR_ACK_SIZ) { - STATE(malformed)++; - dlog(LOG_WARNING, "ctl header too small"); + STATE_SYNC(error).msg_rcv_malformed++; + STATE_SYNC(error).msg_rcv_bad_size++; } } else { if (ntohs(net->len) < NETHDR_SIZ) { - STATE(malformed)++; - dlog(LOG_WARNING, "header too small"); + STATE_SYNC(error).msg_rcv_malformed++; + STATE_SYNC(error).msg_rcv_bad_size++; } } @@ -304,8 +305,43 @@ static void dump_stats_sync(int fd) size = sprintf(buf, "multicast sequence tracking:\n" "%20llu Pckts mfrm " "%20llu Pckts lost\n\n", - (unsigned long long)STATE(malformed), - (unsigned long long)STATE_SYNC(packets_lost)); + (unsigned long long)STATE_SYNC(error).msg_rcv_malformed, + (unsigned long long)STATE_SYNC(error).msg_rcv_lost); + + send(fd, buf, size, 0); +} + +static void dump_stats_sync_extended(int fd) +{ + char buf[512]; + int size; + + size = snprintf(buf, sizeof(buf), + "network statistics:\n" + "\trecv:\n" + "\t\tMalformed messages:\t%20llu\n" + "\t\tWrong protocol version:\t%20u\n" + "\t\tMalformed header:\t%20u\n" + "\t\tMalformed payload:\t%20u\n" + "\t\tBad message type:\t%20u\n" + "\t\tTruncated message:\t%20u\n" + "\t\tBad message size:\t%20u\n" + "\tsend:\n" + "\t\tMalformed messages:\t%20u\n\n" + "sequence tracking statistics:\n" + "\trecv:\n" + "\t\tPackets lost:\t\t%20llu\n" + "\t\tPackets before:\t\t%20llu\n\n", + (unsigned long long)STATE_SYNC(error).msg_rcv_malformed, + STATE_SYNC(error).msg_rcv_bad_version, + STATE_SYNC(error).msg_rcv_bad_header, + STATE_SYNC(error).msg_rcv_bad_payload, + STATE_SYNC(error).msg_rcv_bad_type, + STATE_SYNC(error).msg_rcv_truncated, + STATE_SYNC(error).msg_rcv_bad_size, + STATE_SYNC(error).msg_snd_malformed, + (unsigned long long)STATE_SYNC(error).msg_rcv_lost, + (unsigned long long)STATE_SYNC(error).msg_rcv_before); send(fd, buf, size, 0); } @@ -377,6 +413,11 @@ static int local_handler_sync(int fd, int type, void *data) STATE_SYNC(mcast_server)); dump_stats_sync(fd); break; + case STATS_NETWORK: + dump_stats_sync_extended(fd); + mcast_dump_stats(fd, STATE_SYNC(mcast_client), + STATE_SYNC(mcast_server)); + break; default: if (STATE_SYNC(sync)->local) ret = STATE_SYNC(sync)->local(fd, type, data); -- cgit v1.2.3