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
This commit is contained in:
Pau Espin 2021-09-07 14:09:50 +02:00
parent 35d51ca4e3
commit 5557c0af80
8 changed files with 266 additions and 73 deletions

View File

@ -252,8 +252,40 @@ composed of <RAI + Cell Identity>. This key is also named conveniently as
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 @@ remote cells, which means the cell change will take longer to complete. In order
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

View File

@ -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 @@ struct gsm_pcu_if_container {
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 */

View File

@ -114,7 +114,7 @@ struct gprs_pcu *gprs_pcu_alloc(void *ctx)
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;

View File

@ -361,14 +361,72 @@ static void st_initial(struct osmo_fsm_inst *fi, uint32_t event, void *data)
}
}
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 @@ static void st_wait_resolve_rac_ci_on_enter(struct osmo_fsm_inst *fi, uint32_t p
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 @@ static void st_wait_resolve_rac_ci(struct osmo_fsm_inst *fi, uint32_t event, voi
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 @@ void nacc_fsm_ctrl_reply_cb(struct ctrl_handle *ctrl, struct ctrl_cmd *cmd, void
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 @@ void nacc_fsm_ctrl_reply_cb(struct ctrl_handle *ctrl, struct ctrl_cmd *cmd, void
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 @@ struct nacc_fsm_ctx *nacc_fsm_alloc(struct GprsMs* ms)
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);
}

View File

@ -29,7 +29,7 @@ struct gprs_rlcmac_tbf;
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_ev_create_rlcmac_msg_ctx {
};
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);

View File

@ -44,6 +44,8 @@ extern "C" {
#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 @@ uint16_t imsi2paging_group(const char* imsi)
* 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 @@ struct msgb *pcu_msgb_alloc(uint8_t msg_type, uint8_t bts_nr)
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 @@ void pcu_l1if_tx_pch(struct gprs_rlcmac_bts *bts, bitvec * block, int plen, uint
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 @@ static int pcu_rx_app_info_req(struct gprs_rlcmac_bts *bts, struct gsm_pcu_if_ap
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);

View File

@ -160,6 +160,8 @@ extern "C" {
#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);

View File

@ -1067,6 +1067,10 @@ DEFUN(cfg_neighbor_resolution, cfg_neighbor_resolution_cmd,
"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]);