summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2008-12-21 19:39:39 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2008-12-21 19:39:39 +0100
commit7b3f57d5007dd2cf4127c2c3a9a7cd0f64d5d6e9 (patch)
treeaf5056d1a50fc62e640508c735114c3c4157ab0e
parentb666e6ebbd0c0ae7967ff8167790166858544297 (diff)
downloadconntrack-tools-7b3f57d5007dd2cf4127c2c3a9a7cd0f64d5d6e9.tar.gz
conntrack-tools-7b3f57d5007dd2cf4127c2c3a9a7cd0f64d5d6e9.zip
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 <pablo@netfilter.org>
-rw-r--r--conntrackd.85
-rw-r--r--include/conntrackd.h18
-rw-r--r--src/main.c20
-rw-r--r--src/network.c7
-rw-r--r--src/sync-ftfw.c4
-rw-r--r--src/sync-mode.c83
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);