Use rate_ctr for gsn_t available_counters

This way they can be inspected with regular osmocom means.

Change-Id: I529305b4f824600c6e733a3c0d2c2c6673f99faf
diff --git a/gtp/gsn.c b/gtp/gsn.c
index 8fb0fdb..2189725 100644
--- a/gtp/gsn.c
+++ b/gtp/gsn.c
@@ -25,6 +25,8 @@
 
 #include <osmocom/core/logging.h>
 #include <osmocom/core/utils.h>
+#include <osmocom/core/stats.h>
+#include <osmocom/core/rate_ctr.h>
 
 #if defined(__FreeBSD__)
 #include <sys/endian.h>
@@ -72,6 +74,37 @@
 		     inet_ntoa((addr).sin_addr), htons((addr).sin_port), \
 		     ##args);
 
+static const struct rate_ctr_desc gsn_ctr_description[] = {
+	[GSN_CTR_ERR_SOCKET] = { "err:socket", "Socket error" },
+	[GSN_CTR_ERR_READFROM] = { "err:readfrom", "readfrom() errors" },
+	[GSN_CTR_ERR_SENDTO] = { "err:sendto", "sendto() errors" },
+	[GSN_CTR_ERR_QUEUEFULL] = { "err:queuefull", "Failed to queue message because queue is full" },
+	[GSN_CTR_ERR_SEQ] = { "err:seq", "Sequence number out of range" },
+	[GSN_CTR_ERR_ADDRESS] = { "err:address", "GSN address conversion failed" },
+	[GSN_CTR_ERR_UNKNOWN_PDP] = { "err:unknown_pdp", "Failed looking up PDP context" },
+	[GSN_CTR_ERR_UNEXPECTED_CAUSE] = { "err:unexpected_cause", "Unexpected cause value received" },
+	[GSN_CTR_ERR_OUT_OF_PDP] = { "err:out_of_pdp", "Out of storage for PDP contexts" },
+	[GSN_CTR_PKT_EMPTY] = { "pkt:empty", "Empty packet received" },
+	[GSN_CTR_PKT_UNSUP] = { "pkt:unsupported", "Unsupported GTP version received" },
+	[GSN_CTR_PKT_TOOSHORT] = { "pkt:too_short", "Packet too short received" },
+	[GSN_CTR_PKT_UNKNOWN] = { "pkt:unknown", "Unknown packet type received" },
+	[GSN_CTR_PKT_UNEXPECT] = { "pkt:unexpected", "Unexpected packet type received" },
+	[GSN_CTR_PKT_DUPLICATE] = { "pkt:duplicate", "Duplicate or unsolicited packet received" },
+	[GSN_CTR_PKT_MISSING] = { "pkt:missing", "Missing IE in packet received" },
+	[GSN_CTR_PKT_INCORRECT] = { "pkt:incorrect", "Incorrect IE in packet received" },
+	[GSN_CTR_PKT_INVALID] = { "pkt:invalid", "Invalid format in packet received" },
+};
+
+static const struct rate_ctr_group_desc gsn_ctrg_desc = {
+	"gsn",
+	"GSN Statistics",
+	OSMO_STATS_CLASS_PEER,
+	ARRAY_SIZE(gsn_ctr_description),
+	gsn_ctr_description,
+};
+static unsigned int gsn_ctr_next_idx = 0;
+
+
 /* API Functions */
 
 /* Deprecated, use gtp_pdp_newpdp() instead */
@@ -226,7 +259,7 @@
 			if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
 				   (struct sockaddr *)&qmsg->peer,
 				   sizeof(struct sockaddr_in)) < 0) {
-				gsn->err_sendto++;
+				rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_SENDTO);
 				LOGP(DLGTP, LOGL_ERROR,
 					"Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s\n",
 					gsn->fd0, (unsigned long)&qmsg->p,
@@ -401,6 +434,9 @@
 	/* Initialize internal queue timer */
 	osmo_timer_setup(&(*gsn)->queue_timer, queue_timer_cb, *gsn);
 
+	/* Initialize counter group: */
+	(*gsn)->ctrg = rate_ctr_group_alloc(NULL, &gsn_ctrg_desc, gsn_ctr_next_idx++);
+
 	/* Initialise call back functions */
 	(*gsn)->cb_create_context_ind = 0;
 	(*gsn)->cb_delete_context = 0;
@@ -415,7 +451,7 @@
 
 	/* Create GTP version 0 socket */
 	if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-		(*gsn)->err_socket++;
+		rate_ctr_inc2((*gsn)->ctrg, GSN_CTR_ERR_SOCKET);
 		LOGP(DLGTP, LOGL_ERROR,
 		     "GTPv0 socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
 			AF_INET, SOCK_DGRAM, 0, strerror(errno));
@@ -431,7 +467,7 @@
 #endif
 
 	if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
-		(*gsn)->err_socket++;
+		rate_ctr_inc2((*gsn)->ctrg, GSN_CTR_ERR_SOCKET);
 		LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
 			       "bind(fd0=%d) failed: Error = %s\n",
 			       (*gsn)->fd0, strerror(errno));
@@ -440,7 +476,7 @@
 
 	/* Create GTP version 1 control plane socket */
 	if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-		(*gsn)->err_socket++;
+		rate_ctr_inc2((*gsn)->ctrg, GSN_CTR_ERR_SOCKET);
 		LOGP(DLGTP, LOGL_ERROR,
 		     "GTPv1 control plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
 			AF_INET, SOCK_DGRAM, 0, strerror(errno));
@@ -456,7 +492,7 @@
 #endif
 
 	if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
-		(*gsn)->err_socket++;
+		rate_ctr_inc2((*gsn)->ctrg, GSN_CTR_ERR_SOCKET);
 		LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
 				"bind(fd1c=%d) failed: Error = %s\n",
 				(*gsn)->fd1c, strerror(errno));
@@ -465,7 +501,7 @@
 
 	/* Create GTP version 1 user plane socket */
 	if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-		(*gsn)->err_socket++;
+		rate_ctr_inc2((*gsn)->ctrg, GSN_CTR_ERR_SOCKET);
 		LOGP(DLGTP, LOGL_ERROR,
 		     "GTPv1 user plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
 			AF_INET, SOCK_DGRAM, 0, strerror(errno));
@@ -481,7 +517,7 @@
 #endif
 
 	if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
-		(*gsn)->err_socket++;
+		rate_ctr_inc2((*gsn)->ctrg, GSN_CTR_ERR_SOCKET);
 		LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
 			"bind(fd1u=%d) failed: Error = %s\n",
 			(*gsn)->fd1u, strerror(errno));
@@ -508,6 +544,8 @@
 	close(gsn->fd1c);
 	close(gsn->fd1u);
 
+	rate_ctr_group_free(gsn->ctrg);
+
 	free(gsn);
 	return 0;
 }
diff --git a/gtp/gsn.h b/gtp/gsn.h
index 18a6d58..cbe5b27 100644
--- a/gtp/gsn.h
+++ b/gtp/gsn.h
@@ -15,6 +15,7 @@
 #include <osmocom/core/utils.h>
 #include <osmocom/core/defs.h>
 #include <osmocom/core/timer.h>
+#include <osmocom/core/rate_ctr.h>
 
 #include "pdp.h"
 
@@ -38,6 +39,27 @@
  * each pdp context. This is stored in another struct.
  *************************************************************/
 
+enum gsn_rate_ctr_keys {
+	GSN_CTR_ERR_SOCKET,
+	GSN_CTR_ERR_READFROM,	/* Number of readfrom errors */
+	GSN_CTR_ERR_SENDTO,	/* Number of sendto errors */
+	GSN_CTR_ERR_QUEUEFULL,	/* Number of times queue was full */
+	GSN_CTR_ERR_SEQ,	/* Number of seq out of range */
+	GSN_CTR_ERR_ADDRESS,	/* GSN address conversion failed */
+	GSN_CTR_ERR_UNKNOWN_PDP,	/* GSN address conversion failed */
+	GSN_CTR_ERR_UNEXPECTED_CAUSE,	/* Unexpected cause value received */
+	GSN_CTR_ERR_OUT_OF_PDP,	/* Out of storage for PDP contexts */
+	GSN_CTR_PKT_EMPTY,		/* Number of empty packets */
+	GSN_CTR_PKT_UNSUP,		/* Number of unsupported version 29.60 11.1.1 */
+	GSN_CTR_PKT_TOOSHORT,	/* Number of too short headers 29.60 11.1.2 */
+	GSN_CTR_PKT_UNKNOWN,	/* Number of unknown messages 29.60 11.1.3 */
+	GSN_CTR_PKT_UNEXPECT,	/* Number of unexpected messages 29.60 11.1.4 */
+	GSN_CTR_PKT_DUPLICATE,	/* Number of duplicate or unsolicited replies */
+	GSN_CTR_PKT_MISSING,	/* Number of missing information field messages */
+	GSN_CTR_PKT_INCORRECT,	/* Number of incorrect information field messages */
+	GSN_CTR_PKT_INVALID,	/* Number of invalid message format messages */
+};
+
 struct gsn_t {
 	/* Parameters related to the network interface */
 
@@ -77,28 +99,7 @@
 	int (*cb_recovery3) (struct gsn_t *gsn, struct sockaddr_in *peer, struct pdp_t *pdp, uint8_t recovery);
 
 	/* Counters */
-
-	uint64_t err_socket;	/* Number of socket errors */
-	uint64_t err_readfrom;	/* Number of readfrom errors */
-	uint64_t err_sendto;	/* Number of sendto errors */
-	uint64_t err_memcpy;	/* Number of memcpy */
-	uint64_t err_queuefull;	/* Number of times queue was full */
-	uint64_t err_seq;	/* Number of seq out of range */
-	uint64_t err_address;	/* GSN address conversion failed */
-	uint64_t err_unknownpdp;	/* GSN address conversion failed */
-	uint64_t err_unknowntid;	/* Application supplied unknown imsi+nsapi */
-	uint64_t err_cause;	/* Unexpected cause value received */
-	uint64_t err_outofpdp;	/* Out of storage for PDP contexts */
-
-	uint64_t empty;		/* Number of empty packets */
-	uint64_t unsup;		/* Number of unsupported version 29.60 11.1.1 */
-	uint64_t tooshort;	/* Number of too short headers 29.60 11.1.2 */
-	uint64_t unknown;	/* Number of unknown messages 29.60 11.1.3 */
-	uint64_t unexpect;	/* Number of unexpected messages 29.60 11.1.4 */
-	uint64_t duplicate;	/* Number of duplicate or unsolicited replies */
-	uint64_t missing;	/* Number of missing information field messages */
-	uint64_t incorrect;	/* Number of incorrect information field messages */
-	uint64_t invalid;	/* Number of invalid message format messages */
+	struct rate_ctr_group *ctrg;
 };
 
 /* External API functions */
diff --git a/gtp/gtp.c b/gtp/gtp.c
index 5585256..7e1a03f 100644
--- a/gtp/gtp.c
+++ b/gtp/gtp.c
@@ -388,7 +388,7 @@
 
 	if (sendto(fd, packet, len, 0,
 		   (struct sockaddr *)&addr, sizeof(addr)) < 0) {
-		gsn->err_sendto++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_SENDTO);
 		LOGP(DLGTP, LOGL_ERROR, "Sendto(fd=%d, msg=%lx, len=%d, dst=%s) failed: Error = %s\n", fd,
 		     (unsigned long)&packet, len, inet_ntoa(addr.sin_addr), strerror(errno));
 		return -1;
@@ -396,7 +396,7 @@
 
 	/* Use new queue structure */
 	if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
-		gsn->err_queuefull++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_QUEUEFULL);
 		LOGP(DLGTP, LOGL_ERROR, "Retransmit req queue is full (seq=%" PRIu16 ")\n",
 		     gsn->seq_next);
 	} else {
@@ -444,7 +444,7 @@
 		    "Freeing seq=%" PRIu16 " from retransmit req queue\n",
 		    seq);
 	if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
-		gsn->err_seq++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_SEQ);
 		GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
 			    "Confirmation packet not found in retransmit req queue (seq=%"
 			    PRIu16 ")\n", seq);
@@ -489,7 +489,7 @@
 
 	if (sendto(fd, packet, len, 0,
 		   (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
-		gsn->err_sendto++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_SENDTO);
 		LOGP(DLGTP, LOGL_ERROR,
 			"Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
 			(unsigned long)&packet, len, strerror(errno));
@@ -498,7 +498,7 @@
 
 	/* Use new queue structure */
 	if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
-		gsn->err_queuefull++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_QUEUEFULL);
 		LOGP(DLGTP, LOGL_ERROR, "Retransmit resp queue is full (seq=%" PRIu16 ")\n",
 		     seq);
 	} else {
@@ -558,7 +558,7 @@
 
 	if (sendto(fd, packet, len, 0,
 		   (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
-		gsn->err_sendto++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_SENDTO);
 		LOGP(DLGTP, LOGL_ERROR,
 			"Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
 			(unsigned long)&packet, len, strerror(errno));
@@ -582,6 +582,7 @@
 	inet_ntop(AF_INET, &peer->sin_addr, buf, sizeof(buf));
 	LOGP(DLGTP, LOGL_INFO,
 		"Rx duplicate seq=%" PRIu16 " from %s, retrans resp\n", seq, buf);
+	rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_DUPLICATE);
 
 	if (fcntl(qmsg->fd, F_SETFL, 0)) {
 		LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
@@ -590,7 +591,7 @@
 
 	if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
 		   (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
-		gsn->err_sendto++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_SENDTO);
 		LOGP(DLGTP, LOGL_ERROR,
 			"Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n",
 			qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
@@ -678,7 +679,7 @@
 
 	/* Extract information elements into a pointer array */
 	if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
-		gsn->invalid++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_INVALID);
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 			    "Invalid message format\n");
 		if (gsn->cb_conf)
@@ -687,7 +688,7 @@
 	}
 
 	if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
-		gsn->missing++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 			    "Missing mandatory field\n");
 		if (gsn->cb_conf)
@@ -785,7 +786,7 @@
 
 	/* Decode information elements */
 	if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
-		gsn->invalid++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_INVALID);
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 			    "Invalid message format (AN Information Relay)\n");
 		return -EINVAL;
@@ -1097,7 +1098,7 @@
 
 	/* Decode information elements */
 	if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
-		gsn->invalid++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_INVALID);
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 			    "Invalid message format\n");
 		if (0 == version)
@@ -1117,7 +1118,7 @@
 
 			/* Find the primary PDP context */
 			if (gtp_pdp_getgtp1(gsn, &linked_pdp, get_tei(pack))) {
-				gsn->incorrect++;
+				rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_INCORRECT);
 				GTP_LOGPKG(LOGL_ERROR, peer,
 					    pack, len,
 					    "Incorrect optional information field\n");
@@ -1127,7 +1128,7 @@
 
 			/* Check that the primary PDP context matches linked nsapi */
 			if (linked_pdp->nsapi != linked_nsapi) {
-				gsn->incorrect++;
+				rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_INCORRECT);
 				GTP_LOGPKG(LOGL_ERROR, peer,
 					    pack, len,
 					    "Incorrect optional information field\n");
@@ -1152,7 +1153,7 @@
 			   included in the message. */
 			if (gtpie_gettv0
 			    (ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
-				gsn->missing++;
+				rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 				GTP_LOGPKG(LOGL_ERROR, peer, pack,
 					    len, "Missing IMSI not supported\n");
 				return gtp_create_pdp_resp(gsn, version, pdp,
@@ -1162,7 +1163,7 @@
 
 		/* TEID (mandatory) */
 		if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len, "Missing mandatory information field\n");
 			return gtp_create_pdp_resp(gsn, version, pdp,
@@ -1171,7 +1172,7 @@
 		/* TEIC (conditional) */
 		if (!linked_pdp) {	/* Not Secondary PDP Context Activation Procedure */
 			if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
-				gsn->missing++;
+				rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 				GTP_LOGPKG(LOGL_ERROR, peer,
 					    pack, len,
 					    "Missing mandatory information field\n");
@@ -1181,7 +1182,7 @@
 		}
 		/* NSAPI (mandatory) */
 		if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len, "Missing mandatory information field\n");
 			return gtp_create_pdp_resp(gsn, version, pdp,
@@ -1190,7 +1191,7 @@
 		/* QoS (mandatory) */
 		if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
 				 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len, "Missing mandatory information field\n");
 			return gtp_create_pdp_resp(gsn, version, pdp,
@@ -1205,21 +1206,21 @@
 	case 0:
 		if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
 				 pdp->qos_req0, sizeof(pdp->qos_req0))) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len, "Missing mandatory information field\n");
 			return gtp_create_pdp_resp(gsn, version, pdp,
 						   GTPCAUSE_MAN_IE_MISSING);
 		}
 		if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len, "Missing mandatory information field\n");
 			return gtp_create_pdp_resp(gsn, version, pdp,
 						   GTPCAUSE_MAN_IE_MISSING);
 		}
 		if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len, "Missing mandatory information field\n");
 			return gtp_create_pdp_resp(gsn, version, pdp,
@@ -1231,7 +1232,7 @@
 	/* SGSN address for signalling (mandatory) */
 	if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
 			 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
-		gsn->missing++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 			    "Missing mandatory information field\n");
 		return gtp_create_pdp_resp(gsn, version, pdp,
@@ -1241,7 +1242,7 @@
 	/* SGSN address for user traffic (mandatory) */
 	if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
 			 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
-		gsn->missing++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 			    "Missing mandatory information field\n");
 		return gtp_create_pdp_resp(gsn, version, pdp,
@@ -1257,7 +1258,7 @@
 		/* Selection mode (conditional) */
 		if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
 				 &pdp->selmode, sizeof(pdp->selmode))) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len, "Missing mandatory information field\n");
 			return gtp_create_pdp_resp(gsn, version, pdp,
@@ -1266,7 +1267,7 @@
 		/* End User Address (conditional) */
 		if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
 				 &pdp->eua.v, sizeof(pdp->eua.v))) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len, "Missing mandatory information field\n");
 			return gtp_create_pdp_resp(gsn, version, pdp,
@@ -1275,7 +1276,7 @@
 		/* APN */
 		if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
 				 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len, "Missing mandatory information field\n");
 			return gtp_create_pdp_resp(gsn, version, pdp,
@@ -1288,7 +1289,7 @@
 		/* MSISDN (conditional) */
 		if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
 				 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len, "Missing mandatory information field\n");
 			return gtp_create_pdp_resp(gsn, version, pdp,
@@ -1406,7 +1407,7 @@
 
 	/* Find the context in question */
 	if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
-		gsn->err_unknownpdp++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_UNKNOWN_PDP);
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 			    "Unknown PDP context: %u\n", get_tei(pack));
 		if (gsn->cb_conf)
@@ -1416,7 +1417,7 @@
 
 	/* Decode information elements */
 	if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
-		gsn->invalid++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_INVALID);
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 			    "Invalid message format\n");
 		if (gsn->cb_conf)
@@ -1426,7 +1427,7 @@
 
 	/* Extract cause value (mandatory) */
 	if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
-		gsn->missing++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 			    "Missing mandatory information field\n");
 		if (gsn->cb_conf)
@@ -1451,7 +1452,7 @@
 			if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
 					 &pdp->qos_neg0,
 					 sizeof(pdp->qos_neg0))) {
-				gsn->missing++;
+				rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 				GTP_LOGPKG(LOGL_ERROR, peer,
 					    pack, len,
 					    "Missing conditional information field\n");
@@ -1462,7 +1463,7 @@
 		}
 
 		if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len,
 				    "Missing conditional information field\n");
@@ -1473,7 +1474,7 @@
 
 		if (version == 0) {
 			if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
-				gsn->missing++;
+				rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 				GTP_LOGPKG(LOGL_ERROR, peer,
 					    pack, len,
 					    "Missing conditional information field\n");
@@ -1483,7 +1484,7 @@
 			}
 
 			if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
-				gsn->missing++;
+				rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 				GTP_LOGPKG(LOGL_ERROR, peer,
 					    pack, len,
 					    "Missing conditional information field\n");
@@ -1495,7 +1496,7 @@
 
 		if (version == 1) {
 			if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
-				gsn->missing++;
+				rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 				GTP_LOGPKG(LOGL_ERROR, peer,
 					    pack, len,
 					    "Missing conditional information field\n");
@@ -1505,7 +1506,7 @@
 			}
 
 			if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
-				gsn->missing++;
+				rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 				GTP_LOGPKG(LOGL_ERROR, peer,
 					    pack, len,
 					    "Missing conditional information field\n");
@@ -1518,7 +1519,7 @@
 		}
 
 		if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len,
 				    "Missing conditional information field\n");
@@ -1528,7 +1529,7 @@
 
 		if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
 				 &pdp->eua.v, sizeof(pdp->eua.v))) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len,
 				    "Missing conditional information field\n");
@@ -1539,7 +1540,7 @@
 
 		if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
 				 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len,
 				    "Missing conditional information field\n");
@@ -1550,7 +1551,7 @@
 
 		if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
 				 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len,
 				    "Missing conditional information field\n");
@@ -1563,7 +1564,7 @@
 			if (gtpie_gettlv
 			    (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
 			     &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
-				gsn->missing++;
+				rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 				GTP_LOGPKG(LOGL_ERROR, peer,
 					    pack, len,
 					    "Missing conditional information field\n");
@@ -1739,7 +1740,7 @@
 
 	/* Decode information elements */
 	if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
-		gsn->invalid++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_INVALID);
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 			    "Invalid message format\n");
 		if (0 == version)
@@ -1757,7 +1758,7 @@
 	if (version == 0) {
 		/* Find the context in question */
 		if (gtp_pdp_tidget(gsn, &pdp, get_tid(pack))) {
-			gsn->err_unknownpdp++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_UNKNOWN_PDP);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 				   "Unknown PDP context: TID=0x%" PRIx64 "\n",
 				   get_tid(pack));
@@ -1771,7 +1772,7 @@
 	} else if (version == 1) {
 		/* NSAPI (mandatory) */
 		if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len, "Missing mandatory information field\n");
 			return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
@@ -1783,7 +1784,7 @@
 		if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
 			/* Find the context in question */
 			if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
-				gsn->err_unknownpdp++;
+				rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_UNKNOWN_PDP);
 				GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 					   "Unknown PDP context: TEI=0x%" PRIx32 "\n",
 					   get_tei(pack));
@@ -1794,7 +1795,7 @@
 		} else {
 			/* Find the context in question */
 			if (gtp_pdp_getimsi(gsn, &pdp, imsi, nsapi)) {
-				gsn->err_unknownpdp++;
+				rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_UNKNOWN_PDP);
 				GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 					   "Unknown PDP context: IMSI=0x%" PRIx64
 					   " NSAPI=%" PRIu8 "\n", imsi, nsapi);
@@ -1814,7 +1815,7 @@
 	if (version == 0) {
 		if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
 				 pdp->qos_req0, sizeof(pdp->qos_req0))) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len, "Missing mandatory information field\n");
 			memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
@@ -1831,7 +1832,7 @@
 
 	if (version == 0) {
 		if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len, "Missing mandatory information field\n");
 			memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
@@ -1841,7 +1842,7 @@
 		}
 
 		if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len, "Missing mandatory information field\n");
 			memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
@@ -1854,7 +1855,7 @@
 	if (version == 1) {
 		/* TEID (mandatory) */
 		if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len, "Missing mandatory information field\n");
 			memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
@@ -1871,7 +1872,7 @@
 
 		/* NSAPI (mandatory) */
 		if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len, "Missing mandatory information field\n");
 			memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
@@ -1887,7 +1888,7 @@
 	/* End User Address (conditional) TODO: GGSN Initiated
 	   if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
 	   &pdp->eua.v, sizeof(pdp->eua.v))) {
-	   gsn->missing++;
+	   rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 	   GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 	   "Missing mandatory information field");
 	   memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
@@ -1899,7 +1900,7 @@
 	/* It is weird that this is mandatory when TEIC is conditional */
 	if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
 			 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
-		gsn->missing++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 			    "Missing mandatory information field\n");
 		memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
@@ -1910,7 +1911,7 @@
 	/* SGSN address for user traffic (mandatory) */
 	if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
 			 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
-		gsn->missing++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 			    "Missing mandatory information field\n");
 		memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
@@ -1922,7 +1923,7 @@
 		/* QoS (mandatory) */
 		if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
 				 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len, "Missing mandatory information field\n");
 			memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
@@ -1964,7 +1965,7 @@
 
 	/* Decode information elements */
 	if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
-		gsn->invalid++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_INVALID);
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 			    "Invalid message format\n");
 		goto err_out;
@@ -1988,7 +1989,7 @@
 	if (cause != GTPCAUSE_NON_EXIST && cause != GTPCAUSE_CONTEXT_NOT_FOUND) {
 		/* Find the context in question */
 		if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
-			gsn->err_unknownpdp++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_UNKNOWN_PDP);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 				   "Unknown PDP context: TEI=0x%" PRIx32 "\n", get_tei(pack));
 			goto err_out;
@@ -2057,7 +2058,7 @@
 	return rc;	/* Succes */
 
 err_missing:
-	gsn->missing++;
+	rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 	GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 		    "Missing information field\n");
 err_out:
@@ -2123,7 +2124,7 @@
 	int count;
 
 	if (gsna2in_addr(&addr, &pdp->gsnrc)) {
-		gsn->err_address++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_ADDRESS);
 		LOGP(DLGTP, LOGL_ERROR, "GSN address (len=%u) conversion failed\n", pdp->gsnrc.l);
 		return EOF;
 	}
@@ -2225,7 +2226,7 @@
 
 	/* Find the linked context in question */
 	if (gtp_pdp_getgtp1(gsn, &linked_pdp, get_tei(pack))) {
-		gsn->err_unknownpdp++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_UNKNOWN_PDP);
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 			   "Unknown PDP context: TEI=0x%" PRIx32 "\n", get_tei(pack));
 		return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
@@ -2239,7 +2240,7 @@
 
 	/* Decode information elements */
 	if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
-		gsn->invalid++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_INVALID);
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 			    "Invalid message format\n");
 		if (0 == version)
@@ -2254,7 +2255,7 @@
 	if (version == 1) {
 		/* NSAPI (mandatory) */
 		if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				   len, "Missing mandatory information field\n");
 			return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
@@ -2265,7 +2266,7 @@
 
 		/* Find the context in question */
 		if (gtp_pdp_getgtp1(gsn, &pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
-			gsn->err_unknownpdp++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_UNKNOWN_PDP);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 				   "Unknown PDP context: Secondary TEI=0x%" PRIx32 "\n",
 				   linked_pdp->secondary_tei[nsapi & 0x0f]);
@@ -2319,7 +2320,7 @@
 	/* Find the context in question. It may not be available if gtp_delete_context_req
 	 * was used and as a result the PDP ctx was already freed */
 	if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
-		gsn->err_unknownpdp++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_UNKNOWN_PDP);
 		GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
 			   "Unknown PDP context: TEI=0x%" PRIx32 " (expected if "
 			   "gtp_delete_context_req is used or pdp ctx was freed "
@@ -2331,7 +2332,7 @@
 
 	/* Decode information elements */
 	if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
-		gsn->invalid++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_INVALID);
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 			    "Invalid message format\n");
 		if (gsn->cb_conf)
@@ -2341,7 +2342,7 @@
 
 	/* Extract cause value (mandatory) */
 	if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
-		gsn->missing++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 			    "Missing mandatory information field\n");
 		if (gsn->cb_conf)
@@ -2351,7 +2352,7 @@
 
 	/* Check the cause value (again) */
 	if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
-		gsn->err_cause++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_UNEXPECTED_CAUSE);
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 			    "Unexpected cause value received: %d\n", cause);
 		if (gsn->cb_conf)
@@ -2398,7 +2399,7 @@
 	/* Find the context in question */
 	if (version == 0) {
 		if (gtp_pdp_tidget(gsn, &pdp, get_tid(pack))) {
-			gsn->err_unknownpdp++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_UNKNOWN_PDP);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 				   "Unknown PDP context: TID=0x%" PRIx64 "\n",
 				   get_tid(pack));
@@ -2411,21 +2412,21 @@
 
 		/* Decode information elements */
 		if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
-			gsn->invalid++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_INVALID);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 				    "Invalid message format\n");
 			return EOF;
 		}
 
 		if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &teid_gn)) {
-			gsn->missing++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 				    "Missing mandatory information field\n");
 			return EOF;
 		}
 
 		if (gtp_pdp_getgtp1_peer_d(gsn, &pdp, peer, teid_gn)) {
-			gsn->err_unknownpdp++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_UNKNOWN_PDP);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 				   "Unknown PDP context: Peer TEID=0x%" PRIx32 "\n",
 				   teid_gn);
@@ -2460,7 +2461,7 @@
 	switch (version) {
 	case 0:
 		if (gtp_pdp_getgtp0(gsn, &pdp, get_tei(pack))) {
-			gsn->err_unknownpdp++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_UNKNOWN_PDP);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 				   "Unknown PDP context: TEI=0x%" PRIx32 "\n",
 				   get_tei(pack));
@@ -2471,7 +2472,7 @@
 		break;
 	case 1:
 		if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
-			gsn->err_unknownpdp++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_UNKNOWN_PDP);
 			GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 				   "Unknown PDP context: TEI=0x%" PRIx32 "\n",
 				   get_tei(pack));
@@ -2493,7 +2494,7 @@
 
 	/* If the GPDU was not from the peer GSN tell him to delete context */
 	if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) {	/* TODO Range? */
-		gsn->err_unknownpdp++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_UNKNOWN_PDP);
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown GSN peer %s\n", inet_ntoa(peer->sin_addr));
 		return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
 	}
@@ -2535,7 +2536,7 @@
 			      (struct sockaddr *)&peer, &peerlen)) < 0) {
 			if (errno == EAGAIN)
 				return 0;
-			gsn->err_readfrom++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_READFROM);
 			LOGP(DLGTP, LOGL_ERROR,
 				"recvfrom(fd0=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
 				gsn->fd0, (unsigned long)buffer, sizeof(buffer),
@@ -2545,7 +2546,7 @@
 
 		/* Need at least 1 byte in order to check version */
 		if (status < (1)) {
-			gsn->empty++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_EMPTY);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
 				    status, "Discarding packet - too small\n");
 			continue;
@@ -2561,7 +2562,7 @@
 		/* only support version 0, implying that this is the only version */
 		/* supported on this port */
 		if (version > 0) {
-			gsn->unsup++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_UNSUP);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
 				"Unsupported GTP version %"PRIu8"\n", version);
 			gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status);	/* 29.60: 11.1.1 */
@@ -2570,7 +2571,7 @@
 
 		/* Check length of gtp0 packet */
 		if (status < GTP0_HEADER_SIZE) {
-			gsn->tooshort++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_TOOSHORT);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
 				    status, "GTP0 packet too short\n");
 			continue;	/* Silently discard 29.60: 11.1.2 */
@@ -2578,7 +2579,7 @@
 
 		/* Check packet length field versus length of packet */
 		if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
-			gsn->tooshort++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_TOOSHORT);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
 				    status,
 				    "GTP packet length field does not match actual length\n");
@@ -2588,7 +2589,7 @@
 		if ((gsn->mode == GTP_MODE_GGSN) &&
 		    ((pheader->type == GTP_CREATE_PDP_RSP) ||
 		     (pheader->type == GTP_UPDATE_PDP_RSP))) {
-			gsn->unexpect++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_UNEXPECT);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
 				    status,
 				    "Unexpected GTPv0 Signalling Message '%s'\n",
@@ -2599,7 +2600,7 @@
 		if ((gsn->mode == GTP_MODE_SGSN) &&
 		    ((pheader->type == GTP_CREATE_PDP_REQ) ||
 		     (pheader->type == GTP_UPDATE_PDP_REQ))) {
-			gsn->unexpect++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_UNEXPECT);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
 				    status,
 				    "Unexpected GTPv0 Signalling Message '%s'\n",
@@ -2648,7 +2649,7 @@
 			gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
 			break;
 		default:
-			gsn->unknown++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_UNKNOWN);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
 				"Unknown GTP message type received: %d\n",
 				pheader->type);
@@ -2682,7 +2683,7 @@
 			      (struct sockaddr *)&peer, &peerlen)) < 0) {
 			if (errno == EAGAIN)
 				return 0;
-			gsn->err_readfrom++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_READFROM);
 			LOGP(DLGTP, LOGL_ERROR,
 				"recvfrom(fd=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
 				fd, (unsigned long)buffer, sizeof(buffer),
@@ -2692,7 +2693,7 @@
 
 		/* Need at least 1 byte in order to check version */
 		if (status < (1)) {
-			gsn->empty++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_EMPTY);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
 				    status, "Discarding packet - too small\n");
 			continue;
@@ -2704,7 +2705,7 @@
 
 		/* Version must be no larger than GTP 1 */
 		if (version > 1) {
-			gsn->unsup++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_UNSUP);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
 				"Unsupported GTP version %"PRIu8"\n", version);
 			gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
@@ -2717,7 +2718,7 @@
 		/* GTP 1 messages. If GTP 0 message is received we silently discard */
 		/* the message */
 		if (version < 1) {
-			gsn->unsup++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_UNSUP);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
 				"Unsupported GTP version %"PRIu8"\n", version);
 			continue;
@@ -2725,7 +2726,7 @@
 
 		/* Check packet flag field */
 		if (((pheader->flags & 0xf7) != 0x32)) {
-			gsn->unsup++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_UNSUP);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
 				    status, "Unsupported packet flags: 0x%02x\n", pheader->flags);
 			continue;
@@ -2733,7 +2734,7 @@
 
 		/* Check length of packet */
 		if (status < GTP1_HEADER_SIZE_LONG) {
-			gsn->tooshort++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_TOOSHORT);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
 				    status, "GTP packet too short\n");
 			continue;	/* Silently discard 29.60: 11.1.2 */
@@ -2742,7 +2743,7 @@
 		/* Check packet length field versus length of packet */
 		if (status !=
 		    (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
-			gsn->tooshort++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_TOOSHORT);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
 				    status,
 				    "GTP packet length field does not match actual length\n");
@@ -2753,7 +2754,7 @@
 		/* TODO: We really should cycle through the headers and determine */
 		/* if any have the comprehension required flag set */
 		if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
-			gsn->unsup++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_UNSUP);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
 				    status, "Unsupported extension header\n");
 			gtp_extheader_req(gsn, version, &peer, fd, buffer,
@@ -2765,7 +2766,7 @@
 		if ((gsn->mode == GTP_MODE_GGSN) &&
 		    ((pheader->type == GTP_CREATE_PDP_RSP) ||
 		     (pheader->type == GTP_UPDATE_PDP_RSP))) {
-			gsn->unexpect++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_UNEXPECT);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
 				    status,
 				    "Unexpected GTPv1 Signalling Message '%s'\n",
@@ -2776,7 +2777,7 @@
 		if ((gsn->mode == GTP_MODE_SGSN) &&
 		    ((pheader->type == GTP_CREATE_PDP_REQ) ||
 		     (pheader->type == GTP_UPDATE_PDP_REQ))) {
-			gsn->unexpect++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_UNEXPECT);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
 				    status,
 				    "Unexpected GTPv1 Signalling Message '%s'\n",
@@ -2828,7 +2829,7 @@
 			gtp_ran_info_relay_ind(gsn, version, &peer, buffer, status);
 			break;
 		default:
-			gsn->unknown++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_UNKNOWN);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
 				"Unknown GTP message type received: %u\n",
 				pheader->type);
@@ -2862,7 +2863,7 @@
 			      (struct sockaddr *)&peer, &peerlen)) < 0) {
 			if (errno == EAGAIN)
 				return 0;
-			gsn->err_readfrom++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_READFROM);
 			LOGP(DLGTP, LOGL_ERROR,
 				"recvfrom(fd1u=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
 				gsn->fd1u, (unsigned long)buffer,
@@ -2873,7 +2874,7 @@
 
 		/* Need at least 1 byte in order to check version */
 		if (status < (1)) {
-			gsn->empty++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_EMPTY);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
 				    status, "Discarding packet - too small\n");
 			continue;
@@ -2885,7 +2886,7 @@
 
 		/* Version must be no larger than GTP 1 */
 		if (version > 1) {
-			gsn->unsup++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_UNSUP);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
 				"Unsupported GTP version %"PRIu8"\n", version);
 			gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status);	/*29.60: 11.1.1 */
@@ -2897,7 +2898,7 @@
 		/* GTP 1 messages. If GTP 0 message is received we silently discard */
 		/* the message */
 		if (version < 1) {
-			gsn->unsup++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_UNSUP);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
 				"Unsupported GTP version %"PRIu8"\n", version);
 			continue;
@@ -2905,7 +2906,7 @@
 
 		/* Check packet flag field (allow both with and without sequence number) */
 		if (((pheader->flags & 0xf5) != 0x30)) {
-			gsn->unsup++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_UNSUP);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
 				    status, "Unsupported packet flags 0x%02x\n", pheader->flags);
 			continue;
@@ -2913,7 +2914,7 @@
 
 		/* Check length of packet */
 		if (status < GTP1_HEADER_SIZE_SHORT) {
-			gsn->tooshort++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_TOOSHORT);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
 				    status, "GTP packet too short\n");
 			continue;	/* Silently discard 29.60: 11.1.2 */
@@ -2922,7 +2923,7 @@
 		/* Check packet length field versus length of packet */
 		if (status !=
 		    (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
-			gsn->tooshort++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_TOOSHORT);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
 				    status,
 				    "GTP packet length field does not match actual length\n");
@@ -2933,7 +2934,7 @@
 		/* TODO: We really should cycle through the headers and determine */
 		/* if any have the comprehension required flag set */
 		if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
-			gsn->unsup++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_UNSUP);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
 				    status, "Unsupported extension header\n");
 			gtp_extheader_req(gsn, version, &peer, fd, buffer,
@@ -2960,7 +2961,7 @@
 			gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
 			break;
 		default:
-			gsn->unknown++;
+			rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_UNKNOWN);
 			GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
 				"Unknown GTP message type received: %u\n",
 				pheader->type);
@@ -3041,7 +3042,7 @@
 	}
 
 	if (sendmsg(fd, &msgh, 0) < 0) {
-		gsn->err_sendto++;
+		rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_SENDTO);
 		LOGP(DLGTP, LOGL_ERROR,
 			"sendmsg(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
 			(unsigned long)&packet, GTP0_HEADER_SIZE + len,