[MERGED] osmo-pcu[master]: Introduce GSMTAP categories

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Harald Welte gerrit-no-reply at lists.osmocom.org
Mon Jul 24 22:01:28 UTC 2017


Harald Welte has submitted this change and it was merged.

Change subject: Introduce GSMTAP categories
......................................................................


Introduce GSMTAP categories

When looking at GSMTAP output so far, one is easily overwhelmed by way
too much information being presented.  A lot of is consists of DUMMY
frames, which are probably of lowest interest, ever.

A concept similar to the "gsmtap-sapi" of OsmoBTS is introduced, by
which the user can configure which particular categories (uplink or
downlink control or data, gprs or egprs, ...) he actually wants to
see in his logs.

Change-Id: I297183690e98a7234dfc1608c18847d8981306e4
---
M src/bts.cpp
M src/bts.h
M src/gprs_rlcmac_sched.cpp
M src/osmo-bts-litecell15/lc15_l1_if.c
M src/osmo-bts-sysmo/sysmo_l1_if.c
M src/pcu_l1_if.cpp
M src/pcu_vty.c
7 files changed, 182 insertions(+), 48 deletions(-)

Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/src/bts.cpp b/src/bts.cpp
index 2d289d7..5d1a500 100644
--- a/src/bts.cpp
+++ b/src/bts.cpp
@@ -35,6 +35,7 @@
 	#include <osmocom/core/stats.h>
 	#include <osmocom/gsm/protocol/gsm_04_08.h>
 	#include <osmocom/gsm/gsm_utils.h>
+	#include <osmocom/core/gsmtap_util.h>
 }
 
 #include <arpa/inet.h>
@@ -360,6 +361,23 @@
 		LOGP(DRLCMAC, LOGL_INFO, "No paging, because no TBF\n");
 
 	return 0;
+}
+
+void BTS::send_gsmtap(enum pcu_gsmtap_category categ, bool uplink, uint8_t trx_no,
+		      uint8_t ts_no, uint8_t channel, uint32_t fn,
+		      const uint8_t *data, unsigned int len)
+{
+	uint16_t arfcn;
+
+	/* check if category is activated at all */
+	if (!(m_bts.gsmtap_categ_mask & (1 << categ)))
+		return;
+
+	arfcn = m_bts.trx[trx_no].arfcn;
+	if (uplink)
+		arfcn |= GSMTAP_ARFCN_F_UPLINK;
+
+	gsmtap_send(m_bts.gsmtap, arfcn, ts_no, channel, 0, fn, 0, 0, data, len);
 }
 
 gprs_rlcmac_dl_tbf *BTS::dl_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts)
@@ -1488,13 +1506,19 @@
 
 /* Received Uplink RLC control block. */
 int gprs_rlcmac_pdch::rcv_control_block(
-	bitvec *rlc_block, uint32_t fn)
+	const uint8_t *data, uint8_t data_len, bitvec *rlc_block, uint32_t fn)
 {
 	RlcMacUplink_t * ul_control_block = (RlcMacUplink_t *)talloc_zero(tall_pcu_ctx, RlcMacUplink_t);
 	LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++\n");
 	decode_gsm_rlcmac_uplink(rlc_block, ul_control_block);
 	LOGPC(DCSN1, LOGL_NOTICE, "\n");
 	LOGP(DRLCMAC, LOGL_DEBUG, "------------------------- RX : Uplink Control Block -------------------------\n");
+
+	if (ul_control_block->u.MESSAGE_TYPE == MT_PACKET_UPLINK_DUMMY_CONTROL_BLOCK)
+		bts()->send_gsmtap(PCU_GSMTAP_C_UL_DUMMY, true, trx_no(), ts_no, GSMTAP_CHANNEL_PACCH, fn, data, data_len);
+	else
+		bts()->send_gsmtap(PCU_GSMTAP_C_UL_CTRL, true, trx_no(), ts_no, GSMTAP_CHANNEL_PACCH, fn, data, data_len);
+
 	bts()->rlc_rcvd_control();
 	switch (ul_control_block->u.MESSAGE_TYPE) {
 	case MT_PACKET_CONTROL_ACK:
@@ -1544,10 +1568,10 @@
 		"length: %d (%d))\n", cs.name(), len, cs.usedSizeUL());
 
 	if (cs.isGprs())
-		return rcv_block_gprs(data, fn, meas, cs);
+		return rcv_block_gprs(data, len, fn, meas, cs);
 
 	if (cs.isEgprs())
-		return rcv_data_block(data, fn, meas, cs);
+		return rcv_data_block(data, len, fn, meas, cs);
 
 	bts()->decode_error();
 	LOGP(DRLCMACUL, LOGL_ERROR, "Unsupported coding scheme %s\n",
@@ -1556,7 +1580,7 @@
 }
 
 /*! \brief process egprs and gprs data blocks */
-int gprs_rlcmac_pdch::rcv_data_block(uint8_t *data, uint32_t fn,
+int gprs_rlcmac_pdch::rcv_data_block(uint8_t *data, uint8_t data_len, uint32_t fn,
 	struct pcu_l1_meas *meas, GprsCodingScheme cs)
 {
 	int rc;
@@ -1574,6 +1598,9 @@
 				cs.name());
 			return -EINVAL;
 		}
+		bts()->send_gsmtap(PCU_GSMTAP_C_UL_DATA_EGPRS, true, trx_no(), ts_no, GSMTAP_CHANNEL_PACCH, fn, data, data_len);
+	} else {
+		bts()->send_gsmtap(PCU_GSMTAP_C_UL_DATA_GPRS, true, trx_no(), ts_no, GSMTAP_CHANNEL_PACCH, fn, data, data_len);
 	}
 
 	LOGP(DRLCMACUL, LOGL_DEBUG, "  UL data: %s\n", osmo_hexdump(data, len));
@@ -1606,7 +1633,7 @@
 	return tbf->rcv_data_block_acknowledged(&rlc_dec, data, meas);
 }
 
-int gprs_rlcmac_pdch::rcv_block_gprs(uint8_t *data, uint32_t fn,
+int gprs_rlcmac_pdch::rcv_block_gprs(uint8_t *data, uint8_t data_len, uint32_t fn,
 	struct pcu_l1_meas *meas, GprsCodingScheme cs)
 {
 	unsigned payload = data[0] >> 6;
@@ -1616,14 +1643,14 @@
 
 	switch (payload) {
 	case GPRS_RLCMAC_DATA_BLOCK:
-		rc = rcv_data_block(data, fn, meas, cs);
+		rc = rcv_data_block(data, data_len, fn, meas, cs);
 		break;
 	case GPRS_RLCMAC_CONTROL_BLOCK:
 		block = bitvec_alloc(len, tall_pcu_ctx);
 		if (!block)
 			return -ENOMEM;
 		bitvec_unpack(block, data);
-		rc = rcv_control_block(block, fn);
+		rc = rcv_control_block(data, data_len, block, fn);
 		bitvec_free(block);
 		break;
 	case GPRS_RLCMAC_CONTROL_BLOCK_OPT:
diff --git a/src/bts.h b/src/bts.h
index 78ed002..66875f1 100644
--- a/src/bts.h
+++ b/src/bts.h
@@ -44,6 +44,20 @@
 #define LLC_CODEL_USE_DEFAULT (-1)
 #define MAX_GPRS_CS 9
 
+/* see bts->gsmtap_categ_mask */
+enum pcu_gsmtap_category {
+	PCU_GSMTAP_C_DL_UNKNOWN		= 0,	/* unknown or undecodable downlink blocks */
+	PCU_GSMTAP_C_DL_DUMMY		= 1, 	/* downlink dummy blocks */
+	PCU_GSMTAP_C_DL_CTRL		= 2,	/* downlink control blocks */
+	PCU_GSMTAP_C_DL_DATA_GPRS	= 3,	/* downlink GPRS data blocks */
+	PCU_GSMTAP_C_DL_DATA_EGPRS	= 4,	/* downlink EGPRS data blocks */
+
+	PCU_GSMTAP_C_UL_UNKNOWN		= 15,	/* unknown or undecodable uplink blocks */
+	PCU_GSMTAP_C_UL_DUMMY		= 16,	/* uplink dummy blocks */
+	PCU_GSMTAP_C_UL_CTRL		= 17,	/* uplink control blocks */
+	PCU_GSMTAP_C_UL_DATA_GPRS	= 18,	/* uplink GPRS data blocks */
+	PCU_GSMTAP_C_UL_DATA_EGPRS	= 19,	/* uplink EGPRS data blocks */
+};
 
 struct BTS;
 struct GprsMs;
@@ -68,9 +82,9 @@
 	/* dispatching of messages */
 	int rcv_block(uint8_t *data, uint8_t len, uint32_t fn,
 		struct pcu_l1_meas *meas);
-	int rcv_block_gprs(uint8_t *data, uint32_t fn,
+	int rcv_block_gprs(uint8_t *data, uint8_t data_len, uint32_t fn,
 		struct pcu_l1_meas *meas, GprsCodingScheme cs);
-	int rcv_data_block(uint8_t *data, uint32_t fn,
+	int rcv_data_block(uint8_t *data, uint8_t data_len, uint32_t fn,
 		struct pcu_l1_meas *meas, GprsCodingScheme cs);
 
 	gprs_rlcmac_bts *bts_data() const;
@@ -107,7 +121,7 @@
 
 #ifdef __cplusplus
 private:
-	int rcv_control_block(bitvec *rlc_block, uint32_t fn);
+	int rcv_control_block(const uint8_t *data, uint8_t data_len, bitvec *rlc_block, uint32_t fn);
 
 	void rcv_control_ack(Packet_Control_Acknowledgement_t *, uint32_t fn);
 	void rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *, uint32_t fn);
@@ -186,6 +200,7 @@
 	uint8_t n3103;
 	uint8_t n3105;
 	struct gsmtap_inst *gsmtap;
+	uint32_t gsmtap_categ_mask;
 	struct gprs_rlcmac_trx trx[8];
 	int (*alloc_algorithm)(struct gprs_rlcmac_bts *bts,
 		struct GprsMs *ms,
@@ -362,6 +377,10 @@
 	GprsMs *ms_by_imsi(const char *imsi);
 	GprsMs *ms_alloc(uint8_t ms_class, uint8_t egprs_ms_class = 0);
 
+	void send_gsmtap(enum pcu_gsmtap_category categ, bool uplink, uint8_t trx_no,
+			      uint8_t ts_no, uint8_t channel, uint32_t fn,
+			      const uint8_t *data, unsigned int len);
+
 	/*
 	 * Statistics
 	 */
diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp
index a21c023..e5c8ec8 100644
--- a/src/gprs_rlcmac_sched.cpp
+++ b/src/gprs_rlcmac_sched.cpp
@@ -356,22 +356,29 @@
 	/* Prio 1: select control message */
 	msg = sched_select_ctrl_msg(trx, ts, fn, block_nr, pdch, ul_ass_tbf,
 		dl_ass_tbf, ul_ack_tbf);
-	if (msg)
+	if (msg) {
 		bts->bts->rlc_sent_control();
+		bts->bts->send_gsmtap(PCU_GSMTAP_C_DL_CTRL, false, trx, ts, GSMTAP_CHANNEL_PACCH, fn, msg->data, msg->len);
+	}
 
 	/* Prio 2: select data message for downlink */
 	if (!msg) {
 		msg = sched_select_downlink(bts, trx, ts, fn, block_nr, pdch);
-		if (msg)
+		if (msg) {
 			bts->bts->rlc_sent();
+			/* FIXME: distinguish between GPRS and EGPRS */
+			bts->bts->send_gsmtap(PCU_GSMTAP_C_DL_DATA_GPRS, false, trx, ts, GSMTAP_CHANNEL_PACCH, fn, msg->data, msg->len);
+		}
 	}
 
 	/* Prio 3: send dummy contol message */
 	if (!msg) {
 		/* increase counter */
 		msg = sched_dummy();
-		if (msg)
+		if (msg) {
 			bts->bts->rlc_sent_dummy();
+			bts->bts->send_gsmtap(PCU_GSMTAP_C_DL_DUMMY, false, trx, ts, GSMTAP_CHANNEL_PACCH, fn, msg->data, msg->len);
+		}
 	}
 
 	if (!msg)
diff --git a/src/osmo-bts-litecell15/lc15_l1_if.c b/src/osmo-bts-litecell15/lc15_l1_if.c
index 12a977b..c82ddba 100644
--- a/src/osmo-bts-litecell15/lc15_l1_if.c
+++ b/src/osmo-bts-litecell15/lc15_l1_if.c
@@ -199,11 +199,6 @@
 	if (data_ind->msgUnitParam.u8Size == 0)
 		return -1;
 
-	gsmtap_send(fl1h->gsmtap, data_ind->u16Arfcn | GSMTAP_ARFCN_F_UPLINK,
-			data_ind->u8Tn, GSMTAP_CHANNEL_PACCH, 0,
-			data_ind->u32Fn, 0, 0, data_ind->msgUnitParam.u8Buffer+1,
-			data_ind->msgUnitParam.u8Size-1);
-
 	get_meas(&meas, &data_ind->measParam);
 	bts_update_tbf_ta("PH-DATA", data_ind->u32Fn, fl1h->trx_no,
 			  data_ind->u8Tn, qta2ta(meas.bto));
@@ -216,7 +211,7 @@
 			!= GsmL1_PdtchPlType_Full)
 			break;
 		/* PDTCH / PACCH frame handling */
-		pcu_rx_data_ind_pdtch(fl1h->trx_no, data_ind->u8Tn,
+		rc = pcu_rx_data_ind_pdtch(fl1h->trx_no, data_ind->u8Tn,
 			data_ind->msgUnitParam.u8Buffer + 1,
 			data_ind->msgUnitParam.u8Size - 1,
 			data_ind->u32Fn,
@@ -224,11 +219,19 @@
 		break;
 	case GsmL1_Sapi_Ptcch:
 		// FIXME
+		rc = -1;
 		break;
 	default:
 		LOGP(DL1IF, LOGL_NOTICE, "Rx PH-DATA.ind for unknown L1 SAPI %s\n",
 			get_value_string(lc15bts_l1sapi_names, data_ind->sapi));
 		break;
+	}
+
+	if (rc < 0) {
+		gsmtap_send(fl1h->gsmtap, data_ind->u16Arfcn | GSMTAP_ARFCN_F_UPLINK,
+				data_ind->u8Tn, GSMTAP_CHANNEL_PACCH, 0,
+				data_ind->u32Fn, 0, 0, data_ind->msgUnitParam.u8Buffer+1,
+				data_ind->msgUnitParam.u8Size-1);
 	}
 
 	return rc;
@@ -321,12 +324,6 @@
 	msu_param = &data_req->msgUnitParam;
 	msu_param->u8Size = len;
 	memcpy(msu_param->u8Buffer, data, len);
-
-	gsmtap_send(fl1h->gsmtap, arfcn, data_req->u8Tn, GSMTAP_CHANNEL_PACCH,
-			0, data_req->u32Fn, 0, 0,
-			data_req->msgUnitParam.u8Buffer,
-			data_req->msgUnitParam.u8Size);
-
 
 	/* transmit */
 	if (osmo_wqueue_enqueue(&fl1h->write_q[MQ_PDTCH_WRITE], msg) != 0) {
diff --git a/src/osmo-bts-sysmo/sysmo_l1_if.c b/src/osmo-bts-sysmo/sysmo_l1_if.c
index 8994ac3..9170972 100644
--- a/src/osmo-bts-sysmo/sysmo_l1_if.c
+++ b/src/osmo-bts-sysmo/sysmo_l1_if.c
@@ -184,11 +184,6 @@
 	if (data_ind->msgUnitParam.u8Size == 0)
 		return -1;
 
-	gsmtap_send(fl1h->gsmtap, data_ind->u16Arfcn | GSMTAP_ARFCN_F_UPLINK,
-			data_ind->u8Tn, GSMTAP_CHANNEL_PACCH, 0,
-			data_ind->u32Fn, 0, 0, data_ind->msgUnitParam.u8Buffer+1,
-			data_ind->msgUnitParam.u8Size-1);
-
 	get_meas(&meas, &data_ind->measParam);
 	bts_update_tbf_ta("PH-DATA", data_ind->u32Fn, fl1h->trx_no,
 			  data_ind->u8Tn, qta2ta(meas.bto));
@@ -209,11 +204,21 @@
 		break;
 	case GsmL1_Sapi_Ptcch:
 		// FIXME
+		rc = -1;
 		break;
 	default:
 		LOGP(DL1IF, LOGL_NOTICE, "Rx PH-DATA.ind for unknown L1 SAPI %s\n",
 			get_value_string(femtobts_l1sapi_names, data_ind->sapi));
+		rc = -1;
 		break;
+	}
+
+	if (rc < 0) {
+		gsmtap_send(fl1h->gsmtap, data_ind->u16Arfcn | GSMTAP_ARFCN_F_UPLINK,
+				data_ind->u8Tn, GSMTAP_CHANNEL_PACCH, 0,
+				data_ind->u32Fn, 0, 0, data_ind->msgUnitParam.u8Buffer+1,
+				data_ind->msgUnitParam.u8Size-1);
+		//send_gsmtap(PCU_GSMTAP_C_UL_UNKNOWN, true, 0, date_ind->u8Tn, GSMTAP_CHANNEL_PACCH, data_ind->u32Fn, data_ind->msgUnitParam.u8Buffer+1, data_ind->msgUnitParam.u8Size-1);
 	}
 
 	return rc;
@@ -308,12 +313,6 @@
 	msu_param = &data_req->msgUnitParam;
 	msu_param->u8Size = len;
 	memcpy(msu_param->u8Buffer, data, len);
-
-	gsmtap_send(fl1h->gsmtap, arfcn, data_req->u8Tn, GSMTAP_CHANNEL_PACCH,
-			0, data_req->u32Fn, 0, 0,
-			data_req->msgUnitParam.u8Buffer,
-			data_req->msgUnitParam.u8Size);
-
 
 	/* transmit */
 	if (osmo_wqueue_enqueue(&fl1h->write_q[MQ_PDTCH_WRITE], msg) != 0) {
diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp
index c2c6cc6..420bca0 100644
--- a/src/pcu_l1_if.cpp
+++ b/src/pcu_l1_if.cpp
@@ -165,7 +165,6 @@
 {
 	struct gprs_rlcmac_bts *bts = bts_main_data();
 
-	gsmtap_send(bts->gsmtap, arfcn, ts, GSMTAP_CHANNEL_PACCH, 0, fn, 0, 0, msg->data, msg->len);
 #ifdef ENABLE_DIRECT_PHY
 	if (bts->trx[trx].fl1h) {
 		l1if_pdch_req(bts->trx[trx].fl1h, ts, 0, fn, arfcn, block_nr,
@@ -245,8 +244,9 @@
 	return pdch->rcv_block(data, len, fn, meas);
 }
 
-static int pcu_rx_data_ind(struct gsm_pcu_if_data *data_ind, struct gsmtap_inst *gsmtap)
+static int pcu_rx_data_ind(struct gsm_pcu_if_data *data_ind)
 {
+	struct gprs_rlcmac_bts *bts = bts_main_data();
 	int rc;
 	pcu_l1_meas meas;
 	meas.set_rssi(data_ind->rssi);
@@ -264,13 +264,6 @@
 		data_ind->arfcn, data_ind->block_nr,
 		osmo_hexdump(data_ind->data, data_ind->len));
 
-	rc = gsmtap_send(gsmtap, data_ind->arfcn | GSMTAP_ARFCN_F_UPLINK, data_ind->ts_nr,
-			 GSMTAP_CHANNEL_PACCH, 0, data_ind->fn, 0, 0, data_ind->data, data_ind->len);
-	if (rc < 0)
-	    LOGP(DL1IF, LOGL_ERROR, "Sending RX data via GSMTAP failed: %d\n", rc);
-
-	rc = 0;
-
 	switch (data_ind->sapi) {
 	case PCU_IF_SAPI_PDTCH:
 		rc = pcu_rx_data_ind_pdtch(data_ind->trx_nr, data_ind->ts_nr,
@@ -281,6 +274,11 @@
 		LOGP(DL1IF, LOGL_ERROR, "Received PCU data indication with "
 			"unsupported sapi %d\n", data_ind->sapi);
 		rc = -EINVAL;
+	}
+
+	if (rc < 0 && (bts->gsmtap_categ_mask & PCU_GSMTAP_C_UL_UNKNOWN)) {
+		gsmtap_send(bts->gsmtap, data_ind->arfcn | GSMTAP_ARFCN_F_UPLINK, data_ind->ts_nr,
+			    GSMTAP_CHANNEL_PACCH, 0, data_ind->fn, 0, 0, data_ind->data, data_ind->len);
 	}
 
 	return rc;
@@ -568,11 +566,10 @@
 int pcu_rx(uint8_t msg_type, struct gsm_pcu_if *pcu_prim)
 {
 	int rc = 0;
-	struct gprs_rlcmac_bts *bts = bts_main_data();
 
 	switch (msg_type) {
 	case PCU_IF_MSG_DATA_IND:
-		rc = pcu_rx_data_ind(&pcu_prim->u.data_ind, bts->gsmtap);
+		rc = pcu_rx_data_ind(&pcu_prim->u.data_ind);
 		break;
 	case PCU_IF_MSG_DATA_CNF:
 		rc = pcu_rx_data_cnf(&pcu_prim->u.data_cnf);
@@ -597,6 +594,6 @@
 			msg_type);
 		rc = -EINVAL;
 	}
-
+;
 	return rc;
 }
diff --git a/src/pcu_vty.c b/src/pcu_vty.c
index 3b5996c..fc57a5f 100644
--- a/src/pcu_vty.c
+++ b/src/pcu_vty.c
@@ -16,6 +16,70 @@
 
 #include "pcu_vty_functions.h"
 
+extern void *tall_pcu_ctx;
+
+static const struct value_string pcu_gsmtap_categ_names[] = {
+	{ PCU_GSMTAP_C_DL_UNKNOWN,	"dl-unknown" },
+	{ PCU_GSMTAP_C_DL_DUMMY,	"dl-dummy" },
+	{ PCU_GSMTAP_C_DL_CTRL,		"dl-ctrl" },
+	{ PCU_GSMTAP_C_DL_DATA_GPRS,	"dl-data-gprs" },
+	{ PCU_GSMTAP_C_DL_DATA_EGPRS,	"dl-data-egprs" },
+
+	{ PCU_GSMTAP_C_UL_UNKNOWN,	"ul-unknown" },
+	{ PCU_GSMTAP_C_UL_DUMMY,	"ul-dummy" },
+	{ PCU_GSMTAP_C_UL_CTRL,		"ul-ctrl" },
+	{ PCU_GSMTAP_C_UL_DATA_GPRS,	"ul-data-gprs" },
+	{ PCU_GSMTAP_C_UL_DATA_EGPRS,	"ul-data-egprs" },
+
+	{ 0, NULL }
+};
+
+static const struct value_string pcu_gsmtap_categ_help[] = {
+	{ PCU_GSMTAP_C_DL_UNKNOWN,	"Unknown / Unparseable / Erroneous Downlink Blocks" },
+	{ PCU_GSMTAP_C_DL_DUMMY,	"Downlink Dummy Blocks" },
+	{ PCU_GSMTAP_C_DL_CTRL,		"Downlink Control Blocks" },
+	{ PCU_GSMTAP_C_DL_DATA_GPRS,	"Downlink Data Blocks (GPRS)" },
+	{ PCU_GSMTAP_C_DL_DATA_EGPRS,	"Downlink Data Blocks (EGPRS)" },
+
+	{ PCU_GSMTAP_C_UL_UNKNOWN,	"Unknown / Unparseable / Erroneous Downlink Blocks" },
+	{ PCU_GSMTAP_C_UL_DUMMY,	"Uplink Dummy Blocks" },
+	{ PCU_GSMTAP_C_UL_CTRL,		"Uplink Control Blocks" },
+	{ PCU_GSMTAP_C_UL_DATA_GPRS,	"Uplink Data Blocks (GPRS)" },
+	{ PCU_GSMTAP_C_UL_DATA_EGPRS,	"Uplink Data Blocks (EGPRS)" },
+
+	{ 0, NULL }
+};
+
+
+DEFUN(cfg_pcu_gsmtap_categ, cfg_pcu_gsmtap_categ_cmd, "HIDDEN", "HIDDEN")
+{
+	struct gprs_rlcmac_bts *bts = bts_main_data();
+	int categ;
+
+	categ = get_string_value(pcu_gsmtap_categ_names, argv[0]);
+	if (categ < 0)
+		return CMD_WARNING;
+
+	bts->gsmtap_categ_mask |= (1 << categ);
+
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_pcu_no_gsmtap_categ, cfg_pcu_no_gsmtap_categ_cmd, "HIDDEN", "HIDDEN")
+{
+	struct gprs_rlcmac_bts *bts = bts_main_data();
+	int categ;
+
+	categ = get_string_value(pcu_gsmtap_categ_names, argv[0]);
+	if (categ < 0)
+		return CMD_WARNING;
+
+	bts->gsmtap_categ_mask &= ~(1 << categ);
+
+	return CMD_SUCCESS;
+}
+
+
 int pcu_vty_go_parent(struct vty *vty)
 {
 	switch (vty->node) {
@@ -53,6 +117,7 @@
 static int config_write_pcu(struct vty *vty)
 {
 	struct gprs_rlcmac_bts *bts = bts_main_data();
+	unsigned int i;
 
 	vty_out(vty, "pcu%s", VTY_NEWLINE);
 	if (bts->egprs_enabled)
@@ -166,6 +231,14 @@
 	if (bts->dl_tbf_idle_msec)
 		vty_out(vty, " dl-tbf-idle-time %d%s", bts->dl_tbf_idle_msec,
 			VTY_NEWLINE);
+
+	for (i = 0; i < 32; i++) {
+		unsigned int cs = (1 << i);
+		if (bts->gsmtap_categ_mask & cs) {
+			vty_out(vty, " gsmtap-category %s%s",
+				get_value_string(pcu_gsmtap_categ_names, i), VTY_NEWLINE);
+		}
+	}
 
 	return pcu_vty_config_write_pcu_ext(vty);
 }
@@ -953,6 +1026,19 @@
 {
 //	install_element_ve(&show_pcu_cmd);
 
+	cfg_pcu_gsmtap_categ_cmd.string = vty_cmd_string_from_valstr(tall_pcu_ctx, pcu_gsmtap_categ_names,
+						"gsmtap-category (",
+						"|",")", VTY_DO_LOWER);
+	cfg_pcu_gsmtap_categ_cmd.doc = vty_cmd_string_from_valstr(tall_pcu_ctx, pcu_gsmtap_categ_help,
+						"GSMTAP Category\n",
+						"\n", "", 0);
+	cfg_pcu_no_gsmtap_categ_cmd.string = vty_cmd_string_from_valstr(tall_pcu_ctx, pcu_gsmtap_categ_names,
+						"no gsmtap-category (",
+						"|",")", VTY_DO_LOWER);
+	cfg_pcu_no_gsmtap_categ_cmd.doc = vty_cmd_string_from_valstr(tall_pcu_ctx, pcu_gsmtap_categ_help,
+						NO_STR "GSMTAP Category\n",
+						"\n", "", 0);
+
 	logging_vty_add_cmds(cat);
 	osmo_stats_vty_add_cmds(cat);
 
@@ -1006,6 +1092,8 @@
 	install_element(PCU_NODE, &cfg_pcu_no_dl_tbf_idle_time_cmd);
 	install_element(PCU_NODE, &cfg_pcu_ms_idle_time_cmd);
 	install_element(PCU_NODE, &cfg_pcu_no_ms_idle_time_cmd);
+	install_element(PCU_NODE, &cfg_pcu_gsmtap_categ_cmd);
+	install_element(PCU_NODE, &cfg_pcu_no_gsmtap_categ_cmd);
 
 	install_element_ve(&show_bts_stats_cmd);
 	install_element_ve(&show_tbf_cmd);

-- 
To view, visit https://gerrit.osmocom.org/3337
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I297183690e98a7234dfc1608c18847d8981306e4
Gerrit-PatchSet: 1
Gerrit-Project: osmo-pcu
Gerrit-Branch: master
Gerrit-Owner: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder



More information about the gerrit-log mailing list