Change in osmo-pcu[master]: Rework NS configuration over the info indication

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/.

lynxis lazus gerrit-no-reply at lists.osmocom.org
Mon Oct 12 01:16:55 UTC 2020


lynxis lazus has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-pcu/+/20565 )


Change subject: Rework NS configuration over the info indication
......................................................................

Rework NS configuration over the info indication

Add support of the second NSVC in the info indication.
Add support to update a previous NS configuration.
Allow to update of a NS-VC while the NSE is still available over the
second.

Depends-on: I917f25ebd1239eae5855d973ced15b93731e33a0 (libosmocore)
Depends-on: I3a0cd305fd73b3cb9ec70246ec15ac70b83e57f2 (libosmocore)
Depends-on: I5a2bb95d05d06d909347e2fb084a446ead888cb3 (libosmocore)
Depends-on: I54f110acc3acccb362f6e554324d08cc42b7c328 (libosmocore)
Depends-on: Ia00753a64b7622a0864341f51ea49b6963543755 (libosmocore)
Depends-on: Ic8f6f8aca10da23a18fab8870be7806065a34b47 (libosmocore)
Depends-on: I5f67e6a9bf4cb322bd169061fee0a528012ed54d (libosmocore)
Change-Id: I589ebaa2a2b7de55b7e4e975d8fd6412dd5f214b
---
M include/osmocom/pcu/pcuif_proto.h
M src/gprs_bssgp_pcu.cpp
M src/gprs_bssgp_pcu.h
M src/pcu_l1_if.cpp
M tests/emu/pcu_emu.cpp
5 files changed, 207 insertions(+), 78 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-pcu refs/changes/65/20565/1

diff --git a/include/osmocom/pcu/pcuif_proto.h b/include/osmocom/pcu/pcuif_proto.h
index 82d761d..cdd73d9 100644
--- a/include/osmocom/pcu/pcuif_proto.h
+++ b/include/osmocom/pcu/pcuif_proto.h
@@ -56,6 +56,8 @@
 #define PCU_IF_ADDR_TYPE_IPV4	0x04	/* IPv4 address */
 #define PCU_IF_ADDR_TYPE_IPV6	0x29	/* IPv6 address */
 
+#define PCU_IF_NUM_NSVC 2
+
 enum gsm_pcu_if_text_type {
 	PCU_VERSION,
 	PCU_OML_ALERT,
@@ -167,14 +169,14 @@
 	uint8_t		initial_cs;
 	uint8_t		initial_mcs;
 	/* NSVC */
-	uint16_t	nsvci[2];
-	uint16_t	local_port[2];
-	uint16_t	remote_port[2];
-	uint8_t		address_type[2];
+	uint16_t	nsvci[PCU_IF_NUM_NSVC];
+	uint16_t	local_port[PCU_IF_NUM_NSVC];
+	uint16_t	remote_port[PCU_IF_NUM_NSVC];
+	uint8_t		address_type[PCU_IF_NUM_NSVC];
 	union {
 		struct in_addr v4;
 		struct in6_addr v6;
-	} remote_ip[2];
+	} remote_ip[PCU_IF_NUM_NSVC];
 } __attribute__ ((packed));
 
 struct gsm_pcu_if_act_req {
diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp
index e0cfc37..357df79 100644
--- a/src/gprs_bssgp_pcu.cpp
+++ b/src/gprs_bssgp_pcu.cpp
@@ -920,21 +920,37 @@
 	osmo_timer_schedule(&the_pcu.bvc_timer, the_pcu.bts->fc_interval, 0);
 }
 
-
-int gprs_nsvc_create_and_connect(struct gprs_rlcmac_bts *bts,
-				 const struct osmo_sockaddr *local,
-				 const struct osmo_sockaddr *sgsn,
-				 uint16_t nsei, uint16_t nsvci)
+static int ns_create_nsvc(struct gprs_rlcmac_bts *bts,
+			  uint16_t nsei,
+			  const struct osmo_sockaddr *local,
+			  const struct osmo_sockaddr *remote,
+			  const uint16_t *nsvci,
+			  int valid)
 {
+	int i, rc;
+	int binds = 0, nsvcs = 0;
 	struct gprs_ns2_vc *nsvc;
-	struct gprs_ns2_vc_bind *bind;
-	int rc;
+	struct gprs_ns2_vc_bind *bind[PCU_IF_NUM_NSVC] = { };
 
-	rc = gprs_ns2_ip_bind(bts->nsi, local, 0, &bind);
-	if (rc < 0) {
-		LOGP(DBSSGP, LOGL_ERROR, "Failed to create socket\n");
-		gprs_ns2_free(bts->nsi);
-		return 1;
+	if (!valid)
+		return -1;
+
+	for (i=0; i < PCU_IF_NUM_NSVC; i++) {
+		if (!(valid & (1 << i)))
+			continue;
+
+		rc = gprs_ns2_ip_bind(bts->nsi, &local[i], 0, &bind[i]);
+		if (rc < 0 && rc != -EBUSY) {
+			LOGP(DBSSGP, LOGL_ERROR, "Failed to bind to %s\n", osmo_sockaddr_to_str(&local[i]));
+			return 1;
+		}
+
+		binds |= 1 << i;
+	}
+
+	if (!binds) {
+		LOGP(DBSSGP, LOGL_ERROR, "Failed to bind to any NS-VC\n");
+		return -1;
 	}
 
 	bts->nse = gprs_ns2_nse_by_nsei(bts->nsi, nsei);
@@ -943,16 +959,119 @@
 
 	if (!bts->nse) {
 		LOGP(DBSSGP, LOGL_ERROR, "Failed to create NSE\n");
-		gprs_ns2_free_bind(bind);
+		gprs_ns2_free_binds(bts->nsi);
 		return 1;
 	}
 
-	if (bts->gb_dialect_sns) {
-		rc = gprs_ns2_ip_connect_sns(bind, sgsn, nsei);
+	for (i=0; i < PCU_IF_NUM_NSVC; i++) {
+		if (!(binds & (1 << i)))
+			continue;
+
+		/* FIXME: for SNS we just use the first successful NS-VC instead of all for the initial connect */
+		if (bts->gb_dialect_sns) {
+			rc = gprs_ns2_ip_connect_sns(bind[i], &remote[i], nsei);
+			if (!rc)
+				return rc;
+			else
+				LOGP(DBSSGP, LOGL_ERROR, "Failed to connect to (SNS) towards SGSN %s!\n", osmo_sockaddr_to_str(&remote[i]));
+		} else {
+			nsvc = gprs_ns2_ip_connect(bind[i], &remote[i], bts->nse, nsvci[i]);
+			if (nsvc)
+				nsvcs |= 1 << i;
+			else
+				LOGP(DBSSGP, LOGL_ERROR, "Failed to connect to towards SGSN %s!\n", osmo_sockaddr_to_str(&remote[i]));
+		}
+	}
+
+	return nsvc ? 0 : -1;
+}
+
+struct nsvc_cb {
+	const struct osmo_sockaddr *local;
+	const struct osmo_sockaddr *remote;
+	const uint16_t *nsvci;
+	/* [in] bitmask of valid nsvc in local/remote */
+	int valid;
+	/* [out] bitmask of found nsvcs */
+	int found;
+};
+
+static int ns_conf_vc_cb(struct gprs_ns2_vc *nsvc, void *ctx)
+{
+	struct nsvc_cb *data = (struct nsvc_cb *) ctx;
+
+	for (unsigned int i = 0; i < PCU_IF_NUM_NSVC; i++) {
+		if (!(data->valid & (1 << i)))
+			continue;
+		if (data->found & (1 << i))
+			continue;
+
+		if (gprs_ns2_ip_vc_equal(nsvc, &data->local[i],
+					 &data->remote[i],
+					 data->nsvci[i])) {
+			data->found |= 1 << i;
+			return 0;
+		}
+	}
+
+	/* Found an extra nsvc */
+	LOGP(DBSSGP, LOGL_DEBUG, " Removing NSVC %s\n", gprs_ns2_ll_str(nsvc));
+	gprs_ns2_free_nsvc(nsvc);
+
+	return 0;
+}
+
+int gprs_ns_config(struct gprs_rlcmac_bts *bts, uint16_t nsei,
+		   const struct osmo_sockaddr *local,
+		   const struct osmo_sockaddr *remote,
+		   uint16_t *nsvci, int valid)
+{
+	int rc = 0;
+	if (!bts->nse) {
+		/* there shouldn't any previous state. */
+		gprs_ns2_free_nses(bts->nsi);
+		gprs_ns2_free_binds(bts->nsi);
+		rc = ns_create_nsvc(bts, nsei, local, remote, nsvci, valid);
+	} else if (nsei != gprs_ns2_nse_nsei(bts->nse)) {
+		/* the NSEI has changed */
+		gprs_ns2_free_nses(bts->nsi);
+		gprs_ns2_free_binds(bts->nsi);
+		rc = ns_create_nsvc(bts, nsei, local, remote, nsvci, valid);
+	} else if (bts->gb_dialect_sns) {
+		/* SNS: check if the initial nsvc is the same, if not recreate it */
+		const struct osmo_sockaddr *initial = gprs_ns2_nse_sns_remote(bts->nse);
+		for (unsigned int i = 0; i < PCU_IF_NUM_NSVC; i++) {
+			if (!(valid & (1 << i)))
+				continue;
+
+			/* found the initial - everything should be fine */
+			if (!osmo_sockaddr_cmp(initial, &remote[i]))
+				return 0;
+		}
+
+		gprs_ns2_free_nses(bts->nsi);
+		gprs_ns2_free_binds(bts->nsi);
+		rc = ns_create_nsvc(bts, nsei, local, remote, nsvci, valid);
 	} else {
-		nsvc = gprs_ns2_ip_connect2(bind, sgsn, nsei, nsvci);
-		if (!nsvc)
-			rc = -1;
+		/* check if all NSVC are still the same. */
+		struct nsvc_cb data = {
+			.local = &local[0],
+			.remote = &remote[0],
+			.nsvci = &nsvci[0],
+			.valid = valid,
+			.found = 0,
+		};
+
+		/* search the current active nsvcs */
+		gprs_ns2_nse_foreach_nsvc(bts->nse, &ns_conf_vc_cb, &data);
+
+		/* we found all our valid nsvcs and might removed all other nsvcs */
+		if (valid == data.found)
+			return 0;
+
+		/* remove all found nsvcs from the valid field */
+		valid &= ~data.found;
+		rc = ns_create_nsvc(bts, nsei, local, remote, nsvci, valid);
 	}
 
 	if (rc)
diff --git a/src/gprs_bssgp_pcu.h b/src/gprs_bssgp_pcu.h
index 078f488..1bd0b43 100644
--- a/src/gprs_bssgp_pcu.h
+++ b/src/gprs_bssgp_pcu.h
@@ -81,10 +81,10 @@
 		uint16_t mcc, uint16_t mnc, bool mnc_3_digits,
 		uint16_t lac, uint16_t rac, uint16_t cell_id);
 
-int gprs_nsvc_create_and_connect(struct gprs_rlcmac_bts *bts,
-				 const struct osmo_sockaddr *local,
-				 const struct osmo_sockaddr *sgsn,
-				 uint16_t nsei, uint16_t nsvci);
+int gprs_ns_config(struct gprs_rlcmac_bts *bts, uint16_t nsei,
+		   const struct osmo_sockaddr *local,
+		   const struct osmo_sockaddr *remote,
+		   uint16_t *nsvci, int valid);
 
 int gprs_ns_prim_cb(struct osmo_prim_hdr *oph, void *ctx);
 int gprs_gp_send_cb(void *ctx, struct msgb *msg);
diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp
index 99d4a58..2f379f5 100644
--- a/src/pcu_l1_if.cpp
+++ b/src/pcu_l1_if.cpp
@@ -39,6 +39,7 @@
 #include <osmocom/core/sockaddr_str.h>
 #include <osmocom/core/logging.h>
 #include <osmocom/core/utils.h>
+#include <osmocom/gprs/gprs_ns2.h>
 #include <osmocom/gsm/l1sap.h>
 #include <osmocom/gsm/protocol/gsm_04_08.h>
 }
@@ -488,12 +489,64 @@
 	return rc;
 }
 
+static int pcu_info_ind_ns(struct gprs_rlcmac_bts *bts,
+			   const struct gsm_pcu_if_info_ind *info_ind)
+{
+	struct osmo_sockaddr remote[PCU_IF_NUM_NSVC] = { };
+	struct osmo_sockaddr local[PCU_IF_NUM_NSVC] = { };
+	uint16_t nsvci[PCU_IF_NUM_NSVC] = { };
+	int valid = 0;
+
+	for (unsigned int i = 0; i < PCU_IF_NUM_NSVC; i++) {
+		struct osmo_sockaddr_str sockstr;
+
+		switch (info_ind->address_type[i]) {
+		case PCU_IF_ADDR_TYPE_IPV4:
+			local[i].u.sin.sin_family = AF_INET;
+			local[i].u.sin.sin_addr.s_addr = INADDR_ANY;
+			local[i].u.sin.sin_port = htons(info_ind->local_port[i]);
+
+			remote[i].u.sin.sin_family = AF_INET;
+			remote[i].u.sin.sin_addr = info_ind->remote_ip[i].v4;
+			remote[i].u.sin.sin_port = htons(info_ind->remote_port[i]);
+			break;
+		case PCU_IF_ADDR_TYPE_IPV6:
+			local[i].u.sin6.sin6_family = AF_INET6;
+			local[i].u.sin6.sin6_addr = in6addr_any;
+			local[i].u.sin6.sin6_port = htons(info_ind->local_port[i]);
+
+			remote[i].u.sin6.sin6_family = AF_INET6;
+			remote[i].u.sin6.sin6_addr = info_ind->remote_ip[i].v6;
+			remote[i].u.sin6.sin6_port = htons(info_ind->remote_port[i]);
+			break;
+		default:
+			continue;
+		}
+		nsvci[i] = info_ind->nsvci[i];
+
+		LOGP(DL1IF, LOGL_DEBUG, " NS%u nsvci=%u\n", i, nsvci[i]);
+		if (osmo_sockaddr_str_from_sockaddr(&sockstr, &remote[i].u.sas))
+			strcpy(sockstr.ip, "invalid");
+
+		LOGP(DL1IF, LOGL_DEBUG, " NS%u address: r=%s:%u<->l=NULL:%u\n",
+		     i, sockstr.ip, sockstr.port, info_ind->local_port[i]);
+
+		valid |= 1 << i;
+	}
+
+	if (valid == 0) {
+		LOGP(DL1IF, LOGL_ERROR, "No NSVC available to connect to the SGSN!\n");
+		return -EINVAL;
+	}
+
+	return gprs_ns_config(bts, info_ind->nsei, local, remote, nsvci, valid);
+}
+
 static int pcu_rx_info_ind(const struct gsm_pcu_if_info_ind *info_ind)
 {
 	struct gprs_rlcmac_bts *bts = bts_main_data();
 	struct gprs_bssgp_pcu *pcu;
 	int rc = 0;
-	int good_nsvc = 0;
 	unsigned int trx_nr, ts_nr;
 	int i;
 
@@ -578,54 +631,8 @@
 		goto bssgp_failed;
 	}
 
-	for (unsigned int i = 0; i < ARRAY_SIZE(info_ind->nsvci); i++) {
-		struct osmo_sockaddr remote_sockaddr = { };
-		struct osmo_sockaddr local_sockaddr = { };
-		struct osmo_sockaddr_str sockstr;
-
-		switch (info_ind->address_type[i]) {
-		case PCU_IF_ADDR_TYPE_IPV4:
-			local_sockaddr.u.sin.sin_family = AF_INET;
-			local_sockaddr.u.sin.sin_addr.s_addr = INADDR_ANY;
-			local_sockaddr.u.sin.sin_port = htons(info_ind->local_port[i]);
-
-			remote_sockaddr.u.sin.sin_family = AF_INET;
-			remote_sockaddr.u.sin.sin_addr = info_ind->remote_ip[i].v4;
-			remote_sockaddr.u.sin.sin_port = htons(info_ind->remote_port[i]);
-			break;
-		case PCU_IF_ADDR_TYPE_IPV6:
-			local_sockaddr.u.sin6.sin6_family = AF_INET6;
-			local_sockaddr.u.sin6.sin6_addr = in6addr_any;
-			local_sockaddr.u.sin6.sin6_port = htons(info_ind->local_port[i]);
-
-			remote_sockaddr.u.sin6.sin6_family = AF_INET6;
-			remote_sockaddr.u.sin6.sin6_addr = info_ind->remote_ip[i].v6;
-			remote_sockaddr.u.sin6.sin6_port = htons(info_ind->remote_port[i]);
-			break;
-		default:
-			continue;
-		}
-
-		LOGP(DL1IF, LOGL_DEBUG, " NS%u nsvci=%u\n", i, info_ind->nsvci[i]);
-
-		if (osmo_sockaddr_str_from_sockaddr(&sockstr, &remote_sockaddr.u.sas))
-			strcpy(sockstr.ip, "invalid");
-
-		LOGP(DL1IF, LOGL_DEBUG, " NS%u address: r=%s:%u<->l=NULL:%u\n",
-		     i, sockstr.ip, sockstr.port, info_ind->local_port[i]);
-		rc = gprs_nsvc_create_and_connect(bts,
-						  &local_sockaddr, &remote_sockaddr,
-						  info_ind->nsei, info_ind->nsvci[i]);
-		if (rc) {
-			LOGP(DL1IF, LOGL_ERROR, "Failed to create NSVC connection to %s:%u!\n",
-			     sockstr.ip, sockstr.port);
-			continue;
-		}
-
-		good_nsvc++;
-	}
-
-	if (good_nsvc == 0) {
+	rc = pcu_info_ind_ns(pcu->bts, info_ind);
+	if (rc < 0) {
 		LOGP(DL1IF, LOGL_ERROR, "No NSVC available to connect to the SGSN!\n");
 		goto bssgp_failed;
 	}
diff --git a/tests/emu/pcu_emu.cpp b/tests/emu/pcu_emu.cpp
index 98da13e..853fcb9 100644
--- a/tests/emu/pcu_emu.cpp
+++ b/tests/emu/pcu_emu.cpp
@@ -94,6 +94,8 @@
 {
 	struct gprs_bssgp_pcu *pcu;
 	struct osmo_sockaddr local, remote;
+	uint16_t nsvci = 20;
+	uint16_t nsei = 20;
 
 	local.u.sin.sin_family = AF_INET;
 	local.u.sin.sin_addr.s_addr = 0;
@@ -104,8 +106,7 @@
 	remote.u.sin.sin_port = htons(sgsn_port);
 
 	pcu = gprs_bssgp_init(bts, 20, 20, 901, 99, false, 1, 0, 0);
-	gprs_nsvc_create_and_connect(bts, &local, &remote,
-				     20, 20);
+	gprs_ns_config(bts, nsei, &local, &remote, &nsvci, 1);
 
 	pcu->on_unblock_ack = bvci_unblocked;
 	pcu->on_dl_unit_data = bssgp_data;

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

Gerrit-Project: osmo-pcu
Gerrit-Branch: master
Gerrit-Change-Id: I589ebaa2a2b7de55b7e4e975d8fd6412dd5f214b
Gerrit-Change-Number: 20565
Gerrit-PatchSet: 1
Gerrit-Owner: lynxis lazus <lynxis at fe80.eu>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20201012/e665f6ac/attachment.htm>


More information about the gerrit-log mailing list