diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2009-03-31 15:36:36 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2009-03-31 15:36:36 +0200 |
commit | ff1768673f093c2bfc8e271513b20fc4aa4efeb3 (patch) | |
tree | 88a61508bd859988b6aad847f69fb990d25dd9b0 | |
parent | 70744136608e3ee38f15c994fc2633cf5e3c9fa2 (diff) | |
download | conntrack-tools-ff1768673f093c2bfc8e271513b20fc4aa4efeb3.tar.gz conntrack-tools-ff1768673f093c2bfc8e271513b20fc4aa4efeb3.zip |
conntrack: add `-S' command to display kernel statistics
This patch adds `-S' command to display kernel statistics. Using
raw `cat' on /proc and the hexadecimal output is not very handy.
This option parses the /proc entry and display the information
is a more human friendly way.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r-- | conntrack.8 | 5 | ||||
-rw-r--r-- | include/conntrack.h | 5 | ||||
-rw-r--r-- | src/conntrack.c | 87 |
3 files changed, 92 insertions, 5 deletions
diff --git a/conntrack.8 b/conntrack.8 index 280af9c..208f7a2 100644 --- a/conntrack.8 +++ b/conntrack.8 @@ -21,6 +21,8 @@ conntrack \- command line interface for netfilter connection tracking .BR "conntrack -F [table]" .br .BR "conntrack -C [table]" +.br +.BR "conntrack -S " .SH DESCRIPTION .B conntrack provides a full featured userspace interface to the netfilter connection tracking system that is intended to replace the old /proc/net/ip_conntrack interface. This tool can be used to search, list, inspect and maintain the connection tracking subsystem of the Linux kernel. @@ -77,6 +79,9 @@ Flush the whole given table .TP .BI "-C, --count " Show the table counter. +.TP +.BI "-S, --stats " +Show the in-kernel connection tracking system statistics. .SS PARAMETERS .TP .BI "-z, --zero " diff --git a/include/conntrack.h b/include/conntrack.h index 87a262d..e1f8d0a 100644 --- a/include/conntrack.h +++ b/include/conntrack.h @@ -65,8 +65,11 @@ enum action { EXP_COUNT_BIT = 16, EXP_COUNT = (1 << EXP_COUNT_BIT), + + X_STATS_BIT = 17, + X_STATS = (1 << X_STATS_BIT), }; -#define NUMBER_OF_CMD 17 +#define NUMBER_OF_CMD 18 enum options { CT_OPT_ORIG_SRC_BIT = 0, diff --git a/src/conntrack.c b/src/conntrack.c index 2764d80..9c5e69b 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -59,10 +59,10 @@ #include <libnetfilter_conntrack/libnetfilter_conntrack.h> static const char cmdflags[NUMBER_OF_CMD] -= {'L','I','U','D','G','F','E','V','h','L','I','D','G','F','E','C','C'}; += {'L','I','U','D','G','F','E','V','h','L','I','D','G','F','E','C','C','S'}; static const char cmd_need_param[NUMBER_OF_CMD] -= { 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2}; += { 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2}; static const char *optflags[NUMBER_OF_OPT] = { "src","dst","reply-src","reply-dst","protonum","timeout","status","zero", @@ -78,6 +78,7 @@ static struct option original_opts[] = { {"flush", 1, 0, 'F'}, {"event", 1, 0, 'E'}, {"counter", 2, 0, 'C'}, + {"stats", 0, 0, 'S'}, {"version", 0, 0, 'V'}, {"help", 0, 0, 'h'}, {"orig-src", 1, 0, 's'}, @@ -143,6 +144,7 @@ static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] = /*EXP_EVENT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*CT_COUNT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*EXP_COUNT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*X_STATS*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, }; static LIST_HEAD(proto_list); @@ -556,7 +558,8 @@ static const char usage_commands[] = " -U [table] parameters\t\tUpdate a conntrack\n" " -E [table] [options]\t\tShow events\n" " -F [table]\t\t\tFlush table\n" - " -C [table]\t\t\tShow counter\n"; + " -C [table]\t\t\tShow counter\n" + " -S\t\t\t\tShow statistics\n"; static const char usage_tables[] = "Tables: conntrack, expect\n"; @@ -872,6 +875,75 @@ static int count_exp_cb(enum nf_conntrack_msg_type type, return NFCT_CB_CONTINUE; } +#ifndef CT_STATS_PROC +#define CT_STATS_PROC "/proc/net/stat/nf_conntrack" +#endif + +/* As of 2.6.29, we have 16 entries, this is enough */ +#ifndef CT_STATS_ENTRIES_MAX +#define CT_STATS_ENTRIES_MAX 64 +#endif + +/* maximum string length currently is 13 characters */ +#ifndef CT_STATS_STRING_MAX +#define CT_STATS_STRING_MAX 64 +#endif + +static int display_proc_conntrack_stats(void) +{ + int ret = 0; + FILE *fd; + char buf[4096], *token, *nl; + char output[CT_STATS_ENTRIES_MAX][CT_STATS_STRING_MAX]; + unsigned int value[CT_STATS_ENTRIES_MAX], i, max; + + fd = fopen(CT_STATS_PROC, "r"); + if (fd == NULL) + return -1; + + if (fgets(buf, sizeof(buf), fd) == NULL) { + ret = -1; + goto out_err; + } + + /* trim off trailing \n */ + nl = strchr(buf, '\n'); + if (nl != NULL) { + *nl = '\0'; + nl = strchr(buf, '\n'); + } + token = strtok(buf, " "); + for (i=0; token != NULL && i<CT_STATS_ENTRIES_MAX; i++) { + strncpy(output[i], token, CT_STATS_STRING_MAX); + output[i][CT_STATS_STRING_MAX-1]='\0'; + token = strtok(NULL, " "); + } + max = i; + + if (fgets(buf, sizeof(buf), fd) == NULL) { + ret = -1; + goto out_err; + } + + nl = strchr(buf, '\n'); + while (nl != NULL) { + *nl = '\0'; + nl = strchr(buf, '\n'); + } + token = strtok(buf, " "); + for (i=0; token != NULL && i<CT_STATS_ENTRIES_MAX; i++) { + value[i] = (unsigned int) strtol(token, (char**) NULL, 16); + token = strtok(NULL, " "); + } + + for (i=0; i<max; i++) + printf("%-10s\t\t%-8u\n", output[i], value[i]); + +out_err: + fclose(fd); + return ret; +} + static struct ctproto_handler *h; static const int cmd2type[][2] = { @@ -970,7 +1042,7 @@ int main(int argc, char *argv[]) while ((c = getopt_long(argc, argv, "L::I::U::D::G::E::F::hVs:d:r:q:" "p:t:u:e:a:z[:]:{:}:m:i:f:o:n::" - "g::c:b:C::", + "g::c:b:C::S", opts, NULL)) != -1) { switch(c) { /* commands */ @@ -994,6 +1066,9 @@ int main(int argc, char *argv[]) exit_error(PARAMETER_PROBLEM, "Can't update expectations"); break; + case 'S': + add_command(&command, X_STATS); + break; /* options */ case 's': case 'd': @@ -1366,6 +1441,10 @@ int main(int argc, char *argv[]) nfct_close(cth); printf("%d\n", counter); break; + case X_STATS: + if (display_proc_conntrack_stats() < 0) + exit_error(OTHER_PROBLEM, "Can't open /proc interface"); + break; case CT_VERSION: printf("%s v%s (conntrack-tools)\n", PROGNAME, VERSION); break; |