Change in osmo-bts[master]: Support forwarding proto IPAC_PROTO_EXT_PCU BSC<->PCU

laforge gerrit-no-reply at lists.osmocom.org
Wed Jun 30 08:13:22 UTC 2021


laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-bts/+/24619 )

Change subject: Support forwarding proto IPAC_PROTO_EXT_PCU BSC<->PCU
......................................................................

Support forwarding proto IPAC_PROTO_EXT_PCU BSC<->PCU

This new extension protocol is used to forward Osmocom PCUIF messages
BSC<->BTS<->PCU.
It will be sent re-using the IPA multiplex of the OML link between
BSC and BTS. BTS is responsible for forwarding the message over the unix
socket to the PCU.

PCUIF existing RX path needs to be reworked in order to accept
variable-size messages, in order to be able to transparently forward
messages without knowing about them (the new container message is
variable-length).

Related: SYS#5303
Change-Id: I73fdb17107494ade9263a62d1f729e67303fce87
---
M include/osmo-bts/Makefile.am
A include/osmo-bts/abis_osmo.h
M include/osmo-bts/bts.h
M include/osmo-bts/pcu_if.h
M src/common/Makefile.am
M src/common/abis.c
A src/common/abis_osmo.c
M src/common/bts.c
M src/common/pcu_sock.c
9 files changed, 201 insertions(+), 10 deletions(-)

Approvals:
  laforge: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/include/osmo-bts/Makefile.am b/include/osmo-bts/Makefile.am
index 84dc667..d52c9aa 100644
--- a/include/osmo-bts/Makefile.am
+++ b/include/osmo-bts/Makefile.am
@@ -1,5 +1,6 @@
 noinst_HEADERS = \
 	abis.h \
+	abis_osmo.h \
 	bts.h \
 	bts_model.h \
 	bts_shutdown_fsm.h \
diff --git a/include/osmo-bts/abis_osmo.h b/include/osmo-bts/abis_osmo.h
new file mode 100644
index 0000000..be2817f
--- /dev/null
+++ b/include/osmo-bts/abis_osmo.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include <osmocom/core/msgb.h>
+#include <osmo-bts/pcuif_proto.h>
+
+struct gsm_bts;
+
+int down_osmo(struct gsm_bts *bts, struct msgb *msg);
+
+int abis_osmo_pcu_tx_container(struct gsm_bts *bts, const struct gsm_pcu_if_container *container);
diff --git a/include/osmo-bts/bts.h b/include/osmo-bts/bts.h
index 978a548..a891fb7 100644
--- a/include/osmo-bts/bts.h
+++ b/include/osmo-bts/bts.h
@@ -167,6 +167,8 @@
 	/* how do we talk OML with this TRX? */
 	struct e1inp_sign_link *oml_link;
 	struct timespec oml_conn_established_timestamp;
+	/* OSMO extenion link associated to same line as oml_link: */
+	struct e1inp_sign_link *osmo_link;
 
 	/* Abis network management O&M handle */
 	struct gsm_abis_mo mo;
diff --git a/include/osmo-bts/pcu_if.h b/include/osmo-bts/pcu_if.h
index 6ef8dc5..12a8abc 100644
--- a/include/osmo-bts/pcu_if.h
+++ b/include/osmo-bts/pcu_if.h
@@ -1,8 +1,12 @@
 #ifndef _PCU_IF_H
 #define _PCU_IF_H
 
+#include <osmo-bts/pcuif_proto.h>
+
 extern int pcu_direct;
 
+#define PCUIF_HDR_SIZE ( sizeof(struct gsm_pcu_if) - sizeof(((struct gsm_pcu_if *)0)->u) )
+
 int pcu_tx_info_ind(void);
 int pcu_tx_si(const struct gsm_bts *bts, enum osmo_sysinfo_type si_type, bool enable);
 int pcu_tx_app_info_req(struct gsm_bts *bts, uint8_t app_type, uint8_t len, const uint8_t *app_data);
@@ -20,6 +24,7 @@
 int pcu_tx_pag_req(const uint8_t *identity_lv, uint8_t chan_needed);
 int pcu_tx_pch_data_cnf(uint32_t fn, uint8_t *data, uint8_t len);
 int pcu_tx_susp_req(struct gsm_lchan *lchan, uint32_t tlli, const uint8_t *ra_id, uint8_t cause);
+int pcu_sock_send(struct gsm_network *net, struct msgb *msg);
 
 int pcu_sock_init(const char *path);
 void pcu_sock_exit(void);
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index d979bc0..72438c6 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -12,6 +12,7 @@
 	sysinfo.c \
 	logging.c \
 	abis.c \
+	abis_osmo.c \
 	oml.c \
 	bts.c \
 	bts_trx.c \
diff --git a/src/common/abis.c b/src/common/abis.c
index 17a244c..abef826 100644
--- a/src/common/abis.c
+++ b/src/common/abis.c
@@ -48,6 +48,7 @@
 #include <osmo-bts/bts.h>
 #include <osmo-bts/rsl.h>
 #include <osmo-bts/oml.h>
+#include <osmo-bts/abis_osmo.h>
 #include <osmo-bts/bts_model.h>
 #include <osmo-bts/bts_trx.h>
 
@@ -113,6 +114,8 @@
 		if (clock_gettime(CLOCK_MONOTONIC, &g_bts->oml_conn_established_timestamp) != 0)
 			memset(&g_bts->oml_conn_established_timestamp, 0,
 			       sizeof(g_bts->oml_conn_established_timestamp));
+		g_bts->osmo_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_OSMO,
+							  g_bts->c0, IPAC_PROTO_OSMO, 0);
 		drain_oml_queue(g_bts);
 		bts_link_estab(g_bts);
 		return g_bts->oml_link;
@@ -158,10 +161,15 @@
 			"A common error is a mismatch between unit_id configuration parameters of BTS and BSC.\n",
 			(uint64_t)(now.tv_sec - g_bts->oml_conn_established_timestamp.tv_sec));
 		}
+		g_bts->oml_link = NULL;
 	}
-	g_bts->oml_link = NULL;
 	memset(&g_bts->oml_conn_established_timestamp, 0, sizeof(g_bts->oml_conn_established_timestamp));
 
+	if (g_bts->osmo_link) {
+		e1inp_sign_link_destroy(g_bts->osmo_link);
+		g_bts->osmo_link = NULL;
+	}
+
 	/* Then iterate over the RSL signalling links */
 	llist_for_each_entry(trx, &g_bts->trx_list, list) {
 		if (trx->rsl_link) {
@@ -191,6 +199,9 @@
 	case E1INP_SIGN_RSL:
 		down_rsl(link->trx, msg);
 		break;
+	case E1INP_SIGN_OSMO:
+		down_osmo(link->trx->bts, msg);
+		break;
 	default:
 		msgb_free(msg);
 		break;
diff --git a/src/common/abis_osmo.c b/src/common/abis_osmo.c
new file mode 100644
index 0000000..46dc5fa
--- /dev/null
+++ b/src/common/abis_osmo.c
@@ -0,0 +1,136 @@
+/* OSMO extenion link associated to same line as oml_link: */
+
+/* (C) 2021 by sysmocom - s.m.f.c. GmbH <info at sysmocom.de>
+ * Author: Pau Espin Pedrol <pespin at sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <errno.h>
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/ipa.h>
+#include <osmocom/gsm/protocol/ipaccess.h>
+
+#include <osmo-bts/bts.h>
+#include <osmo-bts/logging.h>
+#include <osmo-bts/pcu_if.h>
+#include <osmo-bts/pcuif_proto.h>
+
+extern struct gsm_network bts_gsmnet;
+
+#define OM_HEADROOM_SIZE	128
+
+////////////////////////////////////////
+// OSMO ABIS extensions (PCU)
+///////////////////////////////////////
+
+static struct msgb *abis_osmo_pcu_msgb_alloc(uint8_t msg_type, uint8_t bts_nr, size_t extra_size)
+{
+	struct msgb *msg;
+	struct gsm_pcu_if *pcu_prim;
+	msg = msgb_alloc_headroom(OM_HEADROOM_SIZE + sizeof(struct gsm_pcu_if) + extra_size,
+				  OM_HEADROOM_SIZE, "IPA/ABIS/OSMO");
+	/* Only header is filled, caller is responible for reserving + filling
+	 * message type specific contents: */
+	msgb_put(msg, PCUIF_HDR_SIZE);
+	pcu_prim = (struct gsm_pcu_if *) msgb_data(msg);
+	pcu_prim->msg_type = msg_type;
+	pcu_prim->bts_nr = bts_nr;
+	return msg;
+}
+
+/* Send a OML NM Message from BSC to BTS */
+int abis_osmo_sendmsg(struct gsm_bts *bts, struct msgb *msg)
+{
+	msg->dst = bts->osmo_link;
+	msg->l2h = msg->data;
+	return abis_sendmsg(msg);
+}
+
+
+/* Send IPA/OSMO/PCU extension Abis message from PCU to BSC */
+static int abis_osmo_pcu_sendmsg(struct gsm_bts *bts, struct msgb *msg)
+{
+	ipa_prepend_header_ext(msg, IPAC_PROTO_EXT_PCU);
+	return abis_osmo_sendmsg(bts, msg);
+}
+
+int abis_osmo_pcu_tx_container(struct gsm_bts *bts, const struct gsm_pcu_if_container *container)
+{
+	uint16_t data_length = osmo_load16be(&container->length);
+	struct msgb *msg = abis_osmo_pcu_msgb_alloc(PCU_IF_MSG_CONTAINER, bts->nr, data_length);
+	struct gsm_pcu_if *pcu_prim = (struct gsm_pcu_if *) msgb_data(msg);
+	struct gsm_pcu_if_container *tx_cont = &pcu_prim->u.container;
+
+	msgb_put(msg, sizeof(*tx_cont) + data_length);
+	tx_cont->msg_type = container->msg_type;
+	tx_cont->length = container->length;
+	if (data_length)
+		memcpy(tx_cont->data, container->data, data_length);
+
+	return abis_osmo_pcu_sendmsg(bts, msg);
+}
+
+
+/* incoming IPA/OSMOEXT/PCU Abis message from BSC */
+static int rx_down_osmo_pcu(struct gsm_bts *bts, struct msgb *msg)
+{
+	struct gsm_pcu_if *pcu_prim;
+	if (msgb_l2len(msg) < PCUIF_HDR_SIZE) {
+		LOGP(DPCU, LOGL_ERROR, "ABIS_OSMO_PCU message too short\n");
+		oml_tx_failure_event_rep(&bts->mo, NM_SEVER_MAJOR, OSMO_EVT_MAJ_UKWN_MSG,
+					 "ABIS_OSMO_PCU message too short\n");
+		msgb_free(msg);
+		return -EIO;
+	}
+	pcu_prim = msgb_l2(msg);
+	LOGP(DPCU, LOGL_INFO, "Rx BSC->BTS%d ABIS_OSMO_PCU msg type %u\n",
+	     pcu_prim->bts_nr, pcu_prim->msg_type);
+	/* we patch the bts_nr received from BTS with the bts_nr we used to set up in the local PCU */
+	pcu_prim->bts_nr = bts->nr;
+	/* Trim Abis lower layers: */
+	msgb_pull_to_l2(msg);
+	/* we simply forward it to PCUIF: */
+	return pcu_sock_send(&bts_gsmnet, msg);
+}
+
+/* incoming IPA/OSMO extension Abis message from BSC */
+int down_osmo(struct gsm_bts *bts, struct msgb *msg)
+{
+	uint8_t *type;
+
+	if (msgb_l2len(msg) < 1) {
+		oml_tx_failure_event_rep(&bts->mo, NM_SEVER_MAJOR, OSMO_EVT_MAJ_UKWN_MSG,
+					 "OSMO message too short\n");
+		msgb_free(msg);
+		return -EIO;
+	}
+
+	type = msgb_l2(msg);
+	msg->l2h = type + 1;
+
+	switch (*type) {
+	case IPAC_PROTO_EXT_PCU:
+		return rx_down_osmo_pcu(bts, msg);
+	default:
+		oml_tx_failure_event_rep(&bts->mo, NM_SEVER_MAJOR, OSMO_EVT_MAJ_UKWN_MSG,
+					 "OSMO message unknown extension %u\n", *type);
+		msgb_free(msg);
+		return -EIO;
+	}
+}
diff --git a/src/common/bts.c b/src/common/bts.c
index bf29113..7d5732b 100644
--- a/src/common/bts.c
+++ b/src/common/bts.c
@@ -371,6 +371,7 @@
 	/* features implemented in 'common', available for all models */
 	osmo_bts_set_feature(bts->features, BTS_FEAT_ETWS_PN);
 	osmo_bts_set_feature(bts->features, BTS_FEAT_IPV6_NSVC);
+	osmo_bts_set_feature(bts->features, BTS_FEAT_ABIS_OSMO_PCU);
 
 	rc = bts_model_init(bts);
 	if (rc < 0) {
diff --git a/src/common/pcu_sock.c b/src/common/pcu_sock.c
index 5a04bf0..f40dd42 100644
--- a/src/common/pcu_sock.c
+++ b/src/common/pcu_sock.c
@@ -45,6 +45,7 @@
 #include <osmo-bts/signal.h>
 #include <osmo-bts/l1sap.h>
 #include <osmo-bts/oml.h>
+#include <osmo-bts/abis_osmo.h>
 
 uint32_t trx_get_hlayer1(const struct gsm_bts_trx *trx);
 
@@ -62,8 +63,6 @@
 	[PCU_IF_SAPI_PTCCH] = 	"PTCCH",
 };
 
-static int pcu_sock_send(struct gsm_network *net, struct msgb *msg);
-
 /*
  * PCU messages
  */
@@ -884,11 +883,21 @@
 	return 0;
 }
 
+#define CHECK_IF_MSG_SIZE(prim_len, prim_msg) \
+	do { \
+		size_t _len = PCUIF_HDR_SIZE + sizeof(prim_msg); \
+		if (prim_len < _len) { \
+			LOGP(DPCU, LOGL_ERROR, "Received %zu bytes on PCU Socket, but primitive %s " \
+			     "size is %zu, discarding\n", prim_len, #prim_msg, _len); \
+			return -EINVAL; \
+		} \
+	} while(0);
 static int pcu_rx(struct gsm_network *net, uint8_t msg_type,
-	struct gsm_pcu_if *pcu_prim)
+	struct gsm_pcu_if *pcu_prim, size_t prim_len)
 {
 	int rc = 0;
 	struct gsm_bts *bts;
+	size_t exp_len;
 
 	if ((bts = gsm_bts_num(net, pcu_prim->bts_nr)) == NULL) {
 		LOGP(DPCU, LOGL_ERROR, "Received PCU Prim for non-existent BTS %u\n", pcu_prim->bts_nr);
@@ -897,17 +906,32 @@
 
 	switch (msg_type) {
 	case PCU_IF_MSG_DATA_REQ:
+		CHECK_IF_MSG_SIZE(prim_len, pcu_prim->u.data_req);
 		rc = pcu_rx_data_req(bts, msg_type, &pcu_prim->u.data_req);
 		break;
 	case PCU_IF_MSG_PAG_REQ:
+		CHECK_IF_MSG_SIZE(prim_len, pcu_prim->u.pag_req);
 		rc = pcu_rx_pag_req(bts, msg_type, &pcu_prim->u.pag_req);
 		break;
 	case PCU_IF_MSG_ACT_REQ:
+		CHECK_IF_MSG_SIZE(prim_len, pcu_prim->u.act_req);
 		rc = pcu_rx_act_req(bts, &pcu_prim->u.act_req);
 		break;
 	case PCU_IF_MSG_TXT_IND:
+		CHECK_IF_MSG_SIZE(prim_len, pcu_prim->u.txt_ind);
 		rc = pcu_rx_txt_ind(bts, &pcu_prim->u.txt_ind);
 		break;
+	case PCU_IF_MSG_CONTAINER:
+		CHECK_IF_MSG_SIZE(prim_len, pcu_prim->u.container);
+		/* ^ check if we can access container fields, v check with container data length */
+		exp_len = PCUIF_HDR_SIZE + sizeof(pcu_prim->u.container) + osmo_load16be(&pcu_prim->u.container.length);
+		if (prim_len < exp_len) {
+			LOGP(DPCU, LOGL_ERROR, "Received %zu bytes on PCU Socket, but primitive "
+			     "container size is %zu, discarding\n", prim_len, exp_len);
+			return -EINVAL;
+		}
+		rc = abis_osmo_pcu_tx_container(bts, &pcu_prim->u.container);
+		break;
 	default:
 		LOGP(DPCU, LOGL_ERROR, "Received unknown PCU msg type %d\n",
 			msg_type);
@@ -928,7 +952,7 @@
 	struct llist_head upqueue;	/* queue for sending messages */
 };
 
-static int pcu_sock_send(struct gsm_network *net, struct msgb *msg)
+int pcu_sock_send(struct gsm_network *net, struct msgb *msg)
 {
 	struct pcu_sock_state *state = net->pcu_state;
 	struct osmo_fd *conn_bfd;
@@ -1019,7 +1043,7 @@
 	struct msgb *msg;
 	int rc;
 
-	msg = msgb_alloc(sizeof(*pcu_prim), "pcu_sock_rx");
+	msg = msgb_alloc(sizeof(*pcu_prim) + 1000, "pcu_sock_rx");
 	if (!msg)
 		return -ENOMEM;
 
@@ -1037,14 +1061,14 @@
 		goto close;
 	}
 
-	if (rc < sizeof(*pcu_prim)) {
-		LOGP(DPCU, LOGL_ERROR, "Received %d bytes on PCU Socket, but primitive size "
-		     "is %zu, discarding\n", rc, sizeof(*pcu_prim));
+	if (rc < PCUIF_HDR_SIZE) {
+		LOGP(DPCU, LOGL_ERROR, "Received %d bytes on PCU Socket, but primitive hdr size "
+		     "is %zu, discarding\n", rc, PCUIF_HDR_SIZE);
 		msgb_free(msg);
 		return 0;
 	}
 
-	rc = pcu_rx(state->net, pcu_prim->msg_type, pcu_prim);
+	rc = pcu_rx(state->net, pcu_prim->msg_type, pcu_prim, rc);
 
 	/* as we always synchronously process the message in pcu_rx() and
 	 * its callbacks, we can free the message here. */

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-bts/+/24619
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Change-Id: I73fdb17107494ade9263a62d1f729e67303fce87
Gerrit-Change-Number: 24619
Gerrit-PatchSet: 7
Gerrit-Owner: pespin <pespin at sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210630/7d0ec905/attachment.htm>


More information about the gerrit-log mailing list