[statistics] Provide basic statistics for the NAT

Count number of SCCP connections, number of BSC reconnects,
number of calls. For most of them we have a per BSC and a
global count.

Right now all structs using the counters survive until the
end of the application so we do not need to free them.
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index 62e3c52..df64723 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -31,6 +31,7 @@
 #include <osmocore/msgb.h>
 #include <osmocore/timer.h>
 #include <osmocore/write_queue.h>
+#include <osmocore/statistics.h>
 
 #define DIR_BSC 1
 #define DIR_MSC 2
@@ -114,6 +115,20 @@
 };
 
 /**
+ * Stats per BSC
+ */
+struct bsc_config_stats {
+	struct {
+		struct counter *conn;
+		struct counter *calls;
+	} sccp;
+
+	struct {
+		struct counter *reconn;
+	} net;
+};
+
+/**
  * One BSC entry in the config
  */
 struct bsc_config {
@@ -124,6 +139,8 @@
 	int nr;
 
 	struct bsc_nat *nat;
+
+	struct bsc_config_stats stats;
 };
 
 /**
@@ -139,6 +156,25 @@
 };
 
 /**
+ * Statistic for the nat.
+ */
+struct bsc_nat_statistics {
+	struct {
+		struct counter *conn;
+		struct counter *calls;
+	} sccp;
+
+	struct {
+		struct counter *reconn;
+                struct counter *auth_fail;
+	} bsc;
+
+	struct {
+		struct counter *reconn;
+	} msc;
+};
+
+/**
  * the structure of the "nat" network
  */
 struct bsc_nat {
@@ -162,6 +198,9 @@
 	int first_contact;
 
 	struct bsc_endpoint *bsc_endpoints;
+
+	/* statistics */
+	struct bsc_nat_statistics stats;
 };
 
 /* create and init the structures */
diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c
index 8897cc3..e679a91 100644
--- a/openbsc/src/nat/bsc_nat.c
+++ b/openbsc/src/nat/bsc_nat.c
@@ -258,7 +258,10 @@
 		case SCCP_MSG_TYPE_IT:
 			con = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
 			if (parsed->gsm_type == BSS_MAP_MSG_ASSIGMENT_RQST) {
+				counter_inc(nat->stats.sccp.calls);
+
 				if (con) {
+					counter_inc(con->bsc->cfg->stats.sccp.conn);
 					if (bsc_mgcp_assign(con, msg) != 0)
 						LOGP(DNAT, LOGL_ERROR, "Failed to assign...\n");
 				} else
@@ -466,6 +469,7 @@
 
 	llist_for_each_entry(conf, &bsc->nat->bsc_configs, entry) {
 		if (strcmp(conf->token, token) == 0) {
+			counter_inc(conf->stats.net.reconn);
 			bsc->authenticated = 1;
 			bsc->cfg = conf;
 			bsc_del_timer(&bsc->id_timeout);
@@ -632,6 +636,9 @@
 		return ret;
 	}
 
+	/* count the reconnect */
+	counter_inc(nat->stats.bsc.reconn);
+
 	/*
 	 * if we are not connected to a msc... just close the socket
 	 */
diff --git a/openbsc/src/nat/bsc_nat_utils.c b/openbsc/src/nat/bsc_nat_utils.c
index 3307e68..36a64b7 100644
--- a/openbsc/src/nat/bsc_nat_utils.c
+++ b/openbsc/src/nat/bsc_nat_utils.c
@@ -45,6 +45,11 @@
 	INIT_LLIST_HEAD(&nat->sccp_connections);
 	INIT_LLIST_HEAD(&nat->bsc_connections);
 	INIT_LLIST_HEAD(&nat->bsc_configs);
+	nat->stats.sccp.conn = counter_alloc("nat.sccp.conn");
+	nat->stats.sccp.calls = counter_alloc("nat.sccp.calls");
+	nat->stats.bsc.reconn = counter_alloc("nat.bsc.conn");
+	nat->stats.bsc.auth_fail = counter_alloc("nat.bsc.auth_fail");
+	nat->stats.msc.reconn = counter_alloc("nat.msc.conn");
 	return nat;
 }
 
@@ -72,6 +77,10 @@
 	llist_add(&conf->entry, &nat->bsc_configs);
 	++nat->num_bsc;
 
+	conf->stats.sccp.conn = counter_alloc("nat.bsc.sccp.conn");
+	conf->stats.sccp.calls = counter_alloc("nat.bsc.sccp.calls");
+	conf->stats.net.reconn = counter_alloc("nat.bsc.net.reconnects");
+
 	return conf;
 }
 
diff --git a/openbsc/src/nat/bsc_sccp.c b/openbsc/src/nat/bsc_sccp.c
index 6e05a03..176f06a 100644
--- a/openbsc/src/nat/bsc_sccp.c
+++ b/openbsc/src/nat/bsc_sccp.c
@@ -100,6 +100,8 @@
 	}
 
 	llist_add(&conn->list_entry, &bsc->nat->sccp_connections);
+	counter_inc(bsc->cfg->stats.sccp.conn);
+	counter_inc(bsc->cfg->nat->stats.sccp.conn);
 
 	LOGP(DNAT, LOGL_DEBUG, "Created 0x%x <-> 0x%x mapping for con %p\n",
 	     sccp_src_ref_to_int(&conn->real_ref),