Change in osmo-pcu[master]: Support Neighbor Address Resolution over PCUIF IPA multiplex

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

pespin gerrit-no-reply at lists.osmocom.org
Mon Sep 13 13:31:57 UTC 2021


pespin has submitted this change. ( https://gerrit.osmocom.org/c/osmo-pcu/+/25404 )

Change subject: Support Neighbor Address Resolution over PCUIF IPA multiplex
......................................................................

Support Neighbor Address Resolution over PCUIF IPA multiplex

While NACC was initially developed, it became clear there was need for
a way to interact PCU<->BSC in order resolve ARFCN+BSIC into CGI-PS
for later RIM usage.
Hence, this resolution was first (until today) implemented using an out
of bands RPC system using the CTRL interface, which required specific
config to be written and matches in osmo-pcu and osmo-bsc VTY (ip+port
of the CTRL interface to use).
However, this has several shortcomings:
* As explained above, specific configuration is required
* Since recently, we do support BSC redundancy in osmo-bts. Hence the BTS
  may switch to a BSC other than first one. If that happened, that'd mean
  the CTRL interface would still point to the initially configured one,
  which may not be the same currently serving the PCU.

During recent development of ANR related features, a similar need for
PCU<->BSC was required, but this time it was decided to extend the IPA
multiplex of the Abis OML connection to pass PCUIF messages,
transparently forwarded to each side by the BTS.
This has the advantage that connection PCU<->BTS is handled by BTS and
both sides send messages transparently.

Let's switch by default to using this new interface, while still
maintaing the old way for a while (announcing them as deprecated) to
avoid breaking existing deployments until they are upgraded to new
versions of osmo-pcu and osmo-bsc.

Related: SYS#4971
Change-Id: I6ad33c7ab10202840cf804dea9ba595978d0e920
---
M doc/manuals/chapters/configuration.adoc
M include/osmocom/pcu/pcuif_proto.h
M src/gprs_pcu.c
M src/nacc_fsm.c
M src/nacc_fsm.h
M src/pcu_l1_if.cpp
M src/pcu_l1_if.h
M src/pcu_vty.c
8 files changed, 266 insertions(+), 73 deletions(-)

Approvals:
  Jenkins Builder: Verified
  osmith: Looks good to me, but someone else must approve
  pespin: Looks good to me, approved



diff --git a/doc/manuals/chapters/configuration.adoc b/doc/manuals/chapters/configuration.adoc
index d031ce6..d778929 100644
--- a/doc/manuals/chapters/configuration.adoc
+++ b/doc/manuals/chapters/configuration.adoc
@@ -252,8 +252,40 @@
 CGI-PS, since it actually equals to the Circuit Switch CGI + RAC.
 
 In order to apply this target cell identity translation, OsmoPCU uses the
-OsmoBSC Neighbor Resolution CTRL interface (see OsmoBSC User Manual), since the
-BSC is the node holding all the neighbor related information.
+OsmoBSC Neighbor Resolution Service. This service is nowadays provided by means
+of PCUIF container messages, which are transparently forwarded in both directions
+by the BTS using the IPA multiplex of the OML connection against the BSC. No
+specific configuration is required in any of the involved nodes, they should
+behave properly out of the box.
+
+These neighbor address resolutions (<ARFCN + BSIC> => <RAI + CI>) are by default
+cached for a while, in order to avoid querying the BSC frequently. As a result,
+the resolution time is also optimized.
+
+.Example: Configure Neighbor Resolution cache and timeouts
+----
+pcu
+ timer X1 500 <1>
+ timer X0 60 <2>
+----
+<1> Time out if the BSC doesn't answer our resolution request after 500 ms
+<2> Keep resolved neighbor addresses cached for 60 seconds
+
+===== OsmoBSC CTRL interface (deprecated)
+
+CAUTION: This interface is nowadays considered deprecated and should not be used
+anymore. Any related VTY options should be dropped from configuration files, to
+let OsmoPCU use the new interface instead. This section is kept here for a while
+as a reference for old deployments using old versions of the programs.
+
+This Neighbor Address Resolution Service was initially implemented by means of a
+separate CTRL interface (see OsmoBSC User Manual), where OsmoPCU would create a
+CTRL connection to the BSC each time an address resolution was required.
+
+Older versions of OsmoBSC may not support the current Neighbor Address
+Resolution Service over the IPA multiplex (see above). For those cases, OsmoPCU
+can be configured to use the old deprecated CTRL interface.
+
 By default, the use of this interface is not configured and hence disabled in
 OsmoPCU. As a result, until configured, the network won't be able to provide the
 System Information to the MS prior to allowing the change during NACC against
@@ -261,20 +293,12 @@
 to configure the interface, the OsmoBSC IP address and port to connect to must
 be configured in OsmoPCU VTY.
 
-These neighbor address resolutions (<ARFCN + BSIC> => <RAI + CI>) are by default
-cached for a while in order to avoid querying the BSC frequently and, as a
-result, optimizing the resolution time too.
-
 .Example: Configure Neighbor Resolution CTRL interface against OsmoBSC
 ----
 pcu
  neighbor resolution 172.18.13.10 4248 <1>
- timer X1 500 <2>
- timer X0 60 <3>
 ----
 <1> Port 4248 is the default and hence could be omitted in this case
-<2> Time out if the BSC doesn't answer our CTRL resolution request after 500 ms
-<3> Keep resolved neighbor addresses cached for 60 seconds
 
 ==== System Information Resolution
 
diff --git a/include/osmocom/pcu/pcuif_proto.h b/include/osmocom/pcu/pcuif_proto.h
index 23b7a2c..8e40a27 100644
--- a/include/osmocom/pcu/pcuif_proto.h
+++ b/include/osmocom/pcu/pcuif_proto.h
@@ -26,6 +26,10 @@
 #define PCU_IF_MSG_TXT_IND	0x70	/* Text indication for BTS */
 #define PCU_IF_MSG_CONTAINER	0x80	/* Transparent container message */
 
+/* msg_type coming from BSC (inside PCU_IF_MSG_CONTAINER) */
+#define PCU_IF_MSG_NEIGH_ADDR_REQ	0x81	/* Neighbor Address Resolution Request */
+#define PCU_IF_MSG_NEIGH_ADDR_CNF	0x82	/* Neighbor Address Resolution Confirmation */
+
 /* sapi */
 #define PCU_IF_SAPI_RACH	0x01	/* channel request on CCCH */
 #define PCU_IF_SAPI_AGCH	0x02	/* assignment on AGCH */
@@ -228,6 +232,30 @@
 	uint8_t		data[0];
 } __attribute__ ((packed));
 
+/*** Used inside container: NOTE: values must be network byte order here! ***/
+/* Neighbor Address Resolution Request */
+struct gsm_pcu_if_neigh_addr_req {
+	uint16_t	local_lac;
+	uint16_t	local_ci;
+	uint16_t	tgt_arfcn;
+	uint8_t		tgt_bsic;
+} __attribute__ ((packed));
+
+/* Neighbor Address Resolution Confirmation */
+struct gsm_pcu_if_neigh_addr_cnf {
+	struct gsm_pcu_if_neigh_addr_req orig_req;
+	uint8_t		err_code; /* 0 success, !0 failed & below unset */
+	/* RAI + CI (CGI-PS): */
+	struct __attribute__ ((packed)) {
+		uint16_t	mcc;
+		uint16_t	mnc;
+		uint8_t		mnc_3_digits;
+		uint16_t	lac;
+		uint8_t		rac;
+		uint16_t	cell_identity;
+	} cgi_ps;
+} __attribute__ ((packed));
+
 struct gsm_pcu_if {
 	/* context based information */
 	uint8_t		msg_type;	/* message type */
diff --git a/src/gprs_pcu.c b/src/gprs_pcu.c
index a7bab8d..5ed9d7d 100644
--- a/src/gprs_pcu.c
+++ b/src/gprs_pcu.c
@@ -114,7 +114,7 @@
 	pcu->vty.ws_pdch = 0;
 	pcu->vty.llc_codel_interval_msec = LLC_CODEL_USE_DEFAULT;
 	pcu->vty.llc_idle_ack_csec = 10;
-	pcu->vty.neigh_ctrl_addr = talloc_strdup(pcu, "127.0.0.1");
+	pcu->vty.neigh_ctrl_addr = NULL; /* don't use CTRL iface for Neigh Addr Resolution */
 	pcu->vty.neigh_ctrl_port = OSMO_CTRL_PORT_BSC_NEIGH;
 
 	pcu->T_defs = T_defs_pcu;
diff --git a/src/nacc_fsm.c b/src/nacc_fsm.c
index 738b2c5..ca226ac 100644
--- a/src/nacc_fsm.c
+++ b/src/nacc_fsm.c
@@ -361,14 +361,72 @@
 	}
 }
 
+static int send_neigh_addr_req_ctrl_iface(struct nacc_fsm_ctx *ctx)
+{
+	struct gprs_rlcmac_bts *bts = ctx->ms->bts;
+	struct gprs_pcu *pcu = bts->pcu;
+	struct ctrl_cmd *cmd = NULL;
+	int rc;
+
+	/* We may have changed to this state previously (eg: we are handling
+	 * another Pkt cell Change Notify with different target). Avoid
+	 * re-creating the socket in that case. */
+	if (ctx->neigh_ctrl_conn->write_queue.bfd.fd == -1) {
+		rc = osmo_sock_init2_ofd(&ctx->neigh_ctrl_conn->write_queue.bfd,
+					 AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP,
+					 NULL, 0, pcu->vty.neigh_ctrl_addr, pcu->vty.neigh_ctrl_port,
+					 OSMO_SOCK_F_CONNECT);
+		if (rc < 0) {
+			LOGPFSML(ctx->fi, LOGL_ERROR,
+				"Failed to establish CTRL (neighbor resolution) connection to BSC r=%s:%u\n\n",
+				pcu->vty.neigh_ctrl_addr, pcu->vty.neigh_ctrl_port);
+			goto err_term;
+		}
+	}
+
+	cmd = ctrl_cmd_create(ctx, CTRL_TYPE_GET);
+	if (!cmd) {
+		LOGPFSML(ctx->fi, LOGL_ERROR, "CTRL msg creation failed\n");
+		goto err_term;
+	}
+
+	cmd->id = talloc_asprintf(cmd, "%u", arfcn_bsic_2_ctrl_id(ctx->neigh_key.tgt_arfcn,
+								  ctx->neigh_key.tgt_bsic));
+	cmd->variable = talloc_asprintf(cmd, "neighbor_resolve_cgi_ps_from_lac_ci.%d.%d.%d.%d",
+					ctx->neigh_key.local_lac, ctx->neigh_key.local_ci,
+					ctx->neigh_key.tgt_arfcn, ctx->neigh_key.tgt_bsic);
+	rc = ctrl_cmd_send(&ctx->neigh_ctrl_conn->write_queue, cmd);
+	if (rc) {
+		LOGPFSML(ctx->fi, LOGL_ERROR, "CTRL msg sent failed: %d\n", rc);
+		goto err_term;
+	}
+
+	talloc_free(cmd);
+	return 0;
+
+err_term:
+	talloc_free(cmd);
+	return -1;
+}
+
+static int send_neigh_addr_req(struct nacc_fsm_ctx *ctx)
+{
+	struct gprs_rlcmac_bts *bts = ctx->ms->bts;
+
+	/* If PCU was configured to use the old CTRL interface, use it: */
+	if (ctx->neigh_ctrl_conn)
+		return send_neigh_addr_req_ctrl_iface(ctx);
+
+	/* Otherwise, by default the new PCUIF over IPA Abis multiplex proto should be used: */
+	return pcu_tx_neigh_addr_res_req(bts, &ctx->neigh_key);
+}
+
 static void st_wait_resolve_rac_ci_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
 {
 	struct nacc_fsm_ctx *ctx = (struct nacc_fsm_ctx *)fi->priv;
 	struct gprs_rlcmac_bts *bts = ctx->ms->bts;
 	struct gprs_pcu *pcu = bts->pcu;
 	const struct osmo_cell_global_id_ps *cgi_ps;
-	struct ctrl_cmd *cmd = NULL;
-	int rc;
 
 	/* First try to find the value in the cache */
 	cgi_ps = neigh_cache_lookup_value(pcu->neigh_cache, &ctx->neigh_key);
@@ -383,45 +441,8 @@
 	LOGPFSML(fi, LOGL_DEBUG, "No CGI-PS found in cache, resolving " NEIGH_CACHE_ENTRY_KEY_FMT "...\n",
 		 NEIGH_CACHE_ENTRY_KEY_ARGS(&ctx->neigh_key));
 
-	/* We may have changed to this state previously (eg: we are handling
-	 * another Pkt cell Change Notify with different target). Avoid
-	 * re-creating the socket in that case. */
-	if (ctx->neigh_ctrl_conn->write_queue.bfd.fd == -1) {
-		rc = osmo_sock_init2_ofd(&ctx->neigh_ctrl_conn->write_queue.bfd,
-					 AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP,
-					 NULL, 0, pcu->vty.neigh_ctrl_addr, pcu->vty.neigh_ctrl_port,
-					 OSMO_SOCK_F_CONNECT);
-		if (rc < 0) {
-			LOGPFSML(fi, LOGL_ERROR,
-				"Failed to establish CTRL (neighbor resolution) connection to BSC r=%s:%u\n\n",
-				pcu->vty.neigh_ctrl_addr, pcu->vty.neigh_ctrl_port);
-			goto err_term;
-		}
-	}
-
-	cmd = ctrl_cmd_create(ctx, CTRL_TYPE_GET);
-	if (!cmd) {
-		LOGPFSML(fi, LOGL_ERROR, "CTRL msg creation failed\n");
-		goto err_term;
-	}
-
-	cmd->id = talloc_asprintf(cmd, "%u", arfcn_bsic_2_ctrl_id(ctx->neigh_key.tgt_arfcn,
-								  ctx->neigh_key.tgt_bsic));
-	cmd->variable = talloc_asprintf(cmd, "neighbor_resolve_cgi_ps_from_lac_ci.%d.%d.%d.%d",
-					ctx->neigh_key.local_lac, ctx->neigh_key.local_ci,
-					ctx->neigh_key.tgt_arfcn, ctx->neigh_key.tgt_bsic);
-	rc = ctrl_cmd_send(&ctx->neigh_ctrl_conn->write_queue, cmd);
-	if (rc) {
-		LOGPFSML(fi, LOGL_ERROR, "CTRL msg sent failed: %d\n", rc);
-		goto err_term;
-	}
-
-	talloc_free(cmd);
-	return;
-
-err_term:
-	talloc_free(cmd);
-	nacc_fsm_state_chg(fi, NACC_ST_TX_CELL_CHG_CONTINUE);
+	if (send_neigh_addr_req(ctx) < 0)
+		nacc_fsm_state_chg(fi, NACC_ST_TX_CELL_CHG_CONTINUE);
 }
 
 static void st_wait_resolve_rac_ci(struct osmo_fsm_inst *fi, uint32_t event, void *data)
@@ -435,8 +456,13 @@
 		handle_retrans_pkt_cell_chg_notif(ctx, notif);
 		break;
 	case NACC_EV_RX_RAC_CI:
-		/* Assumption: ctx->cgi_ps has been filled by caller of the event */
-		nacc_fsm_state_chg(fi, NACC_ST_WAIT_REQUEST_SI);
+		/* data is NULL upon failure */
+		if (data) {
+			ctx->cgi_ps = *(struct osmo_cell_global_id_ps *)data;
+			nacc_fsm_state_chg(fi, NACC_ST_WAIT_REQUEST_SI);
+		} else {
+			nacc_fsm_state_chg(fi, NACC_ST_TX_CELL_CHG_CONTINUE);
+		}
 		break;
 	default:
 		OSMO_ASSERT(0);
@@ -740,12 +766,13 @@
 	struct nacc_fsm_ctx *ctx = (struct nacc_fsm_ctx *)data;
 	char *tmp = NULL, *tok, *saveptr;
 	unsigned int exp_id;
+	struct osmo_cell_global_id_ps cgi_ps;
 
 	LOGPFSML(ctx->fi, LOGL_NOTICE, "Received CTRL message: type=%d %s %s: %s\n",
 		 cmd->type, cmd->variable, cmd->id, osmo_escape_str(cmd->reply, -1));
 
 	if (cmd->type != CTRL_TYPE_GET_REPLY || !cmd->reply) {
-		nacc_fsm_state_chg(ctx->fi, NACC_ST_TX_CELL_CHG_CONTINUE);
+		osmo_fsm_inst_dispatch(ctx->fi, NACC_EV_RX_RAC_CI, NULL);
 		return;
 	}
 
@@ -771,33 +798,33 @@
 
 	if (!(tok = strtok_r(tmp, "-", &saveptr)))
 		goto free_ret;
-	ctx->cgi_ps.rai.lac.plmn.mcc = atoi(tok);
+	cgi_ps.rai.lac.plmn.mcc = atoi(tok);
 
 	if (!(tok = strtok_r(NULL, "-", &saveptr)))
 		goto free_ret;
-	ctx->cgi_ps.rai.lac.plmn.mnc = atoi(tok);
+	cgi_ps.rai.lac.plmn.mnc = atoi(tok);
 
 	if (!(tok = strtok_r(NULL, "-", &saveptr)))
 		goto free_ret;
-	ctx->cgi_ps.rai.lac.lac = atoi(tok);
+	cgi_ps.rai.lac.lac = atoi(tok);
 
 	if (!(tok = strtok_r(NULL, "-", &saveptr)))
 		goto free_ret;
-	ctx->cgi_ps.rai.rac = atoi(tok);
+	cgi_ps.rai.rac = atoi(tok);
 
 	if (!(tok = strtok_r(NULL, "\0", &saveptr)))
 		goto free_ret;
-	ctx->cgi_ps.cell_identity = atoi(tok);
+	cgi_ps.cell_identity = atoi(tok);
 
 	/* Cache the cgi_ps so we can avoid requesting again same resolution for a while */
-	neigh_cache_add(ctx->ms->bts->pcu->neigh_cache, &ctx->neigh_key, &ctx->cgi_ps);
+	neigh_cache_add(ctx->ms->bts->pcu->neigh_cache, &ctx->neigh_key, &cgi_ps);
 
-	osmo_fsm_inst_dispatch(ctx->fi, NACC_EV_RX_RAC_CI, NULL);
+	osmo_fsm_inst_dispatch(ctx->fi, NACC_EV_RX_RAC_CI, &cgi_ps);
 	return;
 
 free_ret:
 	talloc_free(tmp);
-	nacc_fsm_state_chg(ctx->fi, NACC_ST_TX_CELL_CHG_CONTINUE);
+	osmo_fsm_inst_dispatch(ctx->fi, NACC_EV_RX_RAC_CI, NULL);
 	return;
 }
 
@@ -834,18 +861,29 @@
 	if (!ctx->fi)
 		goto free_ret;
 
-	ctx->neigh_ctrl = ctrl_handle_alloc(ctx, ctx, NULL);
-	ctx->neigh_ctrl->reply_cb = nacc_fsm_ctrl_reply_cb;
-	ctx->neigh_ctrl_conn = osmo_ctrl_conn_alloc(ctx, ctx->neigh_ctrl);
-	if (!ctx->neigh_ctrl_conn)
-		goto free_ret;
-	/* Older versions of osmo_ctrl_conn_alloc didn't properly initialize fd to -1,
-	 * so make sure to do it here otherwise fd may be valid fd 0 and cause trouble */
-	ctx->neigh_ctrl_conn->write_queue.bfd.fd = -1;
-	llist_add(&ctx->neigh_ctrl_conn->list_entry, &ctx->neigh_ctrl->ccon_list);
+	/* If CTRL ip present, use the old CTRL interface for neighbor resolution */
+	if (ms->bts->pcu->vty.neigh_ctrl_addr) {
+		ctx->neigh_ctrl = ctrl_handle_alloc(ctx, ctx, NULL);
+		ctx->neigh_ctrl->reply_cb = nacc_fsm_ctrl_reply_cb;
+		ctx->neigh_ctrl_conn = osmo_ctrl_conn_alloc(ctx, ctx->neigh_ctrl);
+		if (!ctx->neigh_ctrl_conn)
+			goto free_ret;
+		/* Older versions of osmo_ctrl_conn_alloc didn't properly initialize fd to -1,
+		 * so make sure to do it here otherwise fd may be valid fd 0 and cause trouble */
+		ctx->neigh_ctrl_conn->write_queue.bfd.fd = -1;
+		llist_add(&ctx->neigh_ctrl_conn->list_entry, &ctx->neigh_ctrl->ccon_list);
+	}
 
 	return ctx;
 free_ret:
 	talloc_free(ctx);
 	return NULL;
 }
+
+bool nacc_fsm_is_waiting_addr_resolution(const struct nacc_fsm_ctx *ctx,
+					 const struct neigh_cache_entry_key *neigh_key)
+{
+	if (ctx->fi->state != NACC_ST_WAIT_RESOLVE_RAC_CI)
+		return false;
+	return neigh_cache_entry_key_eq(&ctx->neigh_key, neigh_key);
+}
diff --git a/src/nacc_fsm.h b/src/nacc_fsm.h
index 7b0adfd..04c9ba4 100644
--- a/src/nacc_fsm.h
+++ b/src/nacc_fsm.h
@@ -29,7 +29,7 @@
 
 enum nacc_fsm_event {
 	NACC_EV_RX_CELL_CHG_NOTIFICATION, /* data: Packet_Cell_Change_Notification_t* */
-	NACC_EV_RX_RAC_CI, /* no data passed, RAC_CI became available in neigh_cache */
+	NACC_EV_RX_RAC_CI, /* RAC_CI became available in neigh_cache. NULL on failure, pointer to ctx->cgi_ps on success */
 	NACC_EV_RX_SI, /* data: struct si_cache_entry* */
 	NACC_EV_CREATE_RLCMAC_MSG, /* data: struct nacc_ev_create_rlcmac_msg_ctx* */
 	NACC_EV_RX_CELL_CHG_CONTINUE_ACK,
@@ -69,3 +69,6 @@
 };
 
 struct nacc_fsm_ctx *nacc_fsm_alloc(struct GprsMs* ms);
+
+bool nacc_fsm_is_waiting_addr_resolution(const struct nacc_fsm_ctx *ctx,
+					 const struct neigh_cache_entry_key *neigh_key);
diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp
index 4530e1a..25c1933 100644
--- a/src/pcu_l1_if.cpp
+++ b/src/pcu_l1_if.cpp
@@ -44,6 +44,8 @@
 #include <osmocom/gsm/protocol/gsm_04_08.h>
 #include <osmocom/gsm/gsm48_rest_octets.h>
 #include <osmocom/gsm/sysinfo.h>
+
+#include <nacc_fsm.h>
 }
 
 #include <gprs_rlcmac.h>
@@ -95,6 +97,7 @@
  * PCU messages
  */
 
+/* Can be used to allocate message with non-variable size */
 struct msgb *pcu_msgb_alloc(uint8_t msg_type, uint8_t bts_nr)
 {
 	struct msgb *msg;
@@ -111,6 +114,21 @@
 	return msg;
 }
 
+/* Allocate message with extra size, only reserve pcuif msg hdr */
+static struct msgb *pcu_msgb_alloc_ext_size(uint8_t msg_type, uint8_t bts_nr, size_t extra_size)
+{
+	struct msgb *msg;
+	struct gsm_pcu_if *pcu_prim;
+	msg = msgb_alloc(sizeof(struct gsm_pcu_if) + extra_size, "pcu_sock_tx");
+	/* 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;
+}
+
 const struct value_string gsm_pcu_if_text_type_names[] = {
 	OSMO_VALUE_STRING(PCU_VERSION),
 	OSMO_VALUE_STRING(PCU_OML_ALERT),
@@ -271,6 +289,33 @@
 	pcu_tx_data_req(bts, 0, 0, PCU_IF_SAPI_PCH, 0, 0, 0, data, PAGING_GROUP_LEN + GSM_MACBLOCK_LEN);
 }
 
+int pcu_tx_neigh_addr_res_req(struct gprs_rlcmac_bts *bts, const struct neigh_cache_entry_key *neigh_key)
+{
+	struct msgb *msg;
+	struct gsm_pcu_if *pcu_prim;
+	struct gsm_pcu_if_neigh_addr_req *naddr_req;
+
+	LOGP(DL1IF, LOGL_DEBUG, "(bts=%u) Tx Neighbor Address Resolution Request: " NEIGH_CACHE_ENTRY_KEY_FMT "\n",
+	     bts->nr, NEIGH_CACHE_ENTRY_KEY_ARGS(neigh_key));
+
+	msg = pcu_msgb_alloc_ext_size(PCU_IF_MSG_CONTAINER, bts->nr, sizeof(struct gsm_pcu_if_neigh_addr_req));
+	if (!msg)
+		return -ENOMEM;
+	pcu_prim = (struct gsm_pcu_if *) msgb_data(msg);
+	naddr_req = (struct gsm_pcu_if_neigh_addr_req *)&pcu_prim->u.container.data[0];
+
+	msgb_put(msg, sizeof(pcu_prim->u.container) + sizeof(struct gsm_pcu_if_neigh_addr_req));
+	pcu_prim->u.container.msg_type = PCU_IF_MSG_NEIGH_ADDR_REQ;
+	osmo_store16be(sizeof(struct gsm_pcu_if_neigh_addr_req), &pcu_prim->u.container.length);
+
+	osmo_store16be(neigh_key->local_lac, &naddr_req->local_lac);
+	osmo_store16be(neigh_key->local_ci, &naddr_req->local_ci);
+	osmo_store16be(neigh_key->tgt_arfcn, &naddr_req->tgt_arfcn);
+	naddr_req->tgt_bsic = neigh_key->tgt_bsic;
+
+	return pcu_sock_send(msg);
+}
+
 void pcu_rx_block_time(struct gprs_rlcmac_bts *bts, uint16_t arfcn, uint32_t fn, uint8_t ts_no)
 {
 	bts_set_current_block_frame_number(bts, fn);
@@ -955,11 +1000,60 @@
 	return 0;
 }
 
+static int pcu_rx_neigh_addr_cnf(struct gprs_rlcmac_bts *bts, struct gsm_pcu_if_neigh_addr_cnf *naddr_cnf)
+{
+	struct llist_head *tmp;
+	struct osmo_cell_global_id_ps cgi_ps;
+	struct osmo_cell_global_id_ps *cgi_ps_ptr = &cgi_ps;
+
+	struct neigh_cache_entry_key neigh_key = {
+		.local_lac = osmo_load16be(&naddr_cnf->orig_req.local_lac),
+		.local_ci = osmo_load16be(&naddr_cnf->orig_req.local_ci),
+		.tgt_arfcn = osmo_load16be(&naddr_cnf->orig_req.tgt_arfcn),
+		.tgt_bsic = naddr_cnf->orig_req.tgt_bsic,
+	};
+
+	if (naddr_cnf->err_code == 0) {
+		cgi_ps.rai.lac.plmn.mcc = osmo_load16be(&naddr_cnf->cgi_ps.mcc);
+		cgi_ps.rai.lac.plmn.mnc = osmo_load16be(&naddr_cnf->cgi_ps.mnc);
+		cgi_ps.rai.lac.plmn.mnc_3_digits = naddr_cnf->cgi_ps.mnc_3_digits;
+		cgi_ps.rai.lac.lac = osmo_load16be(&naddr_cnf->cgi_ps.lac);
+		cgi_ps.rai.rac = naddr_cnf->cgi_ps.rac;
+		cgi_ps.cell_identity = osmo_load16be(&naddr_cnf->cgi_ps.cell_identity);
+
+		LOGP(DL1IF, LOGL_INFO, "Rx Neighbor Address Resolution Confirmation for " NEIGH_CACHE_ENTRY_KEY_FMT ": %s\n",
+		     NEIGH_CACHE_ENTRY_KEY_ARGS(&neigh_key), osmo_cgi_ps_name(&cgi_ps));
+
+		/* Cache the cgi_ps so we can avoid requesting again same resolution for a while */
+		neigh_cache_add(bts->pcu->neigh_cache, &neigh_key, &cgi_ps);
+	} else {
+		cgi_ps_ptr = NULL;
+		LOGP(DL1IF, LOGL_INFO, "Rx Neighbor Address Resolution Confirmation for " NEIGH_CACHE_ENTRY_KEY_FMT ": failed with err_code=%u\n",
+		     NEIGH_CACHE_ENTRY_KEY_ARGS(&neigh_key), naddr_cnf->err_code);
+	}
+
+	llist_for_each(tmp, bts_ms_store(bts)->ms_list()) {
+		GprsMs *ms = llist_entry(tmp, typeof(*ms), list);
+		if (ms->nacc && nacc_fsm_is_waiting_addr_resolution(ms->nacc, &neigh_key))
+			osmo_fsm_inst_dispatch(ms->nacc->fi, NACC_EV_RX_RAC_CI, cgi_ps_ptr);
+	}
+	return 0;
+}
+
 static int pcu_rx_container(struct gprs_rlcmac_bts *bts, struct gsm_pcu_if_container *container)
 {
 	int rc;
+	uint16_t data_length = osmo_load16be(&container->length);
 
 	switch (container->msg_type) {
+	case PCU_IF_MSG_NEIGH_ADDR_CNF:
+		if (data_length < sizeof(struct gsm_pcu_if_neigh_addr_cnf)) {
+			LOGP(DL1IF, LOGL_ERROR, "Rx container(NEIGH_ADDR_CNF) message too short: %u vs exp %zu\n",
+			     data_length, sizeof(struct gsm_pcu_if_neigh_addr_cnf));
+			return -EINVAL;
+		}
+		rc = pcu_rx_neigh_addr_cnf(bts, (struct gsm_pcu_if_neigh_addr_cnf*)&container->data);
+		break;
 	default:
 		LOGP(DL1IF, LOGL_NOTICE, "(bts=%d) Rx unexpected msg type (%u) inside container!\n",
 		     bts->nr, container->msg_type);
diff --git a/src/pcu_l1_if.h b/src/pcu_l1_if.h
index 2a4f0ea..7d48feb 100644
--- a/src/pcu_l1_if.h
+++ b/src/pcu_l1_if.h
@@ -160,6 +160,8 @@
 #endif
 struct gprs_rlcmac_bts;
 
+int pcu_tx_neigh_addr_res_req(struct gprs_rlcmac_bts *bts, const struct neigh_cache_entry_key *neigh_key);
+
 int pcu_rx(struct gsm_pcu_if *pcu_prim, size_t pcu_prim_length);
 int pcu_l1if_open(void);
 void pcu_l1if_close(void);
diff --git a/src/pcu_vty.c b/src/pcu_vty.c
index 1ca6376..c85e324 100644
--- a/src/pcu_vty.c
+++ b/src/pcu_vty.c
@@ -1067,6 +1067,10 @@
        "IPv4 address to connect to\n" "IPv6 address to connect to\n"
        "Port to connect to (default 4248)\n")
 {
+	vty_out(vty, "%% Warning: The CTRL interface for Neighbor Address Resolution is now deprecated."
+		"Upgrade osmo-bsc and drop the 'neighbor resolution " VTY_IPV46_CMD " [<0-65535>]' VTY "
+		"option in order to let osmo-pcu use the new resoluton method using the PCUIF over IPA "
+		"multiplex, which will work out of the box without required configuration.%s", VTY_NEWLINE);
 	osmo_talloc_replace_string(the_pcu, &the_pcu->vty.neigh_ctrl_addr, argv[0]);
 	if (argc > 1)
 		the_pcu->vty.neigh_ctrl_port = atoi(argv[1]);

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

Gerrit-Project: osmo-pcu
Gerrit-Branch: master
Gerrit-Change-Id: I6ad33c7ab10202840cf804dea9ba595978d0e920
Gerrit-Change-Number: 25404
Gerrit-PatchSet: 4
Gerrit-Owner: pespin <pespin at sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-Reviewer: osmith <osmith at sysmocom.de>
Gerrit-Reviewer: pespin <pespin at sysmocom.de>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210913/fa127e25/attachment.htm>


More information about the gerrit-log mailing list