diff --git a/doc/manuals/chapters/configuration.adoc b/doc/manuals/chapters/configuration.adoc index d031ce6a..d7789297 100644 --- a/doc/manuals/chapters/configuration.adoc +++ b/doc/manuals/chapters/configuration.adoc @@ -252,8 +252,40 @@ composed of . 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 ( => ) 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 ( => ) 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 23b7a2cb..8e40a270 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 @@ 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 */ diff --git a/src/gprs_pcu.c b/src/gprs_pcu.c index a7bab8d4..5ed9d7d6 100644 --- a/src/gprs_pcu.c +++ b/src/gprs_pcu.c @@ -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; diff --git a/src/nacc_fsm.c b/src/nacc_fsm.c index 738b2c58..ca226acb 100644 --- a/src/nacc_fsm.c +++ b/src/nacc_fsm.c @@ -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); +} diff --git a/src/nacc_fsm.h b/src/nacc_fsm.h index 7b0adfd0..04c9ba4e 100644 --- a/src/nacc_fsm.h +++ b/src/nacc_fsm.h @@ -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); diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp index 4530e1a5..25c19333 100644 --- a/src/pcu_l1_if.cpp +++ b/src/pcu_l1_if.cpp @@ -44,6 +44,8 @@ extern "C" { #include #include #include + +#include } #include @@ -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); diff --git a/src/pcu_l1_if.h b/src/pcu_l1_if.h index 2a4f0ead..7d48febe 100644 --- a/src/pcu_l1_if.h +++ b/src/pcu_l1_if.h @@ -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); diff --git a/src/pcu_vty.c b/src/pcu_vty.c index 1ca63761..c85e324b 100644 --- a/src/pcu_vty.c +++ b/src/pcu_vty.c @@ -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]);