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.orgpespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-pcu/+/21745 ) Change subject: WIP: Implement NACC ...................................................................... WIP: Implement NACC Change-Id: Icac5cfe93bcad0e18e5c9380d4e82233856633aa --- M src/Makefile.am M src/encoding.cpp M src/encoding.h M src/gprs_debug.cpp M src/gprs_debug.h M src/gprs_ms.cpp M src/gprs_ms.h M src/gprs_rlcmac_sched.cpp A src/nacc_fsm.cpp A src/nacc_fsm.h M src/pdch.cpp M src/pdch.h 12 files changed, 317 insertions(+), 0 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-pcu refs/changes/45/21745/1 diff --git a/src/Makefile.am b/src/Makefile.am index ece372d..ab6abf2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -54,6 +54,7 @@ pcu_vty.c \ pcu_vty_functions.cpp \ mslot_class.c \ + nacc_fsm.cpp \ tbf.cpp \ tbf_ul.cpp \ tbf_dl.cpp \ @@ -89,6 +90,7 @@ pcu_vty.h \ pcu_vty_functions.h \ mslot_class.h \ + nacc_fsm.h \ tbf.h \ tbf_ul.h \ tbf_dl.h \ diff --git a/src/encoding.cpp b/src/encoding.cpp index a16962a..8c5aabc 100644 --- a/src/encoding.cpp +++ b/src/encoding.cpp @@ -804,6 +804,31 @@ pda_r99->Exist_COMPACT_ReducedMA = 0; } +void Encoding::write_packet_neighbour_cell_data(RlcMacDownlink_t *block, + bool tfi_is_dl, uint8_t tfi, uint8_t container_id, + uint8_t container_idx, PNCDContainer_t *container) +{ + + block->PAYLOAD_TYPE = 0x1; // RLC/MAC control block that does not include the optional octets of the RLC/MAC control header + block->RRBP = 0; // 0: N+13 + block->SP = 0; // RRBP field is valid + block->USF = 0x0; // Uplink state flag + + block->u.Packet_Neighbour_Cell_Data.MESSAGE_TYPE = MT_PACKET_NEIGHBOUR_CELL_DATA; + block->u.Packet_Neighbour_Cell_Data.PAGE_MODE = 0x0; // Normal Paging + + block->u.Packet_Neighbour_Cell_Data.Global_TFI.UnionType = tfi_is_dl; // 0=UPLINK TFI, 1=DL TFI + if (tfi_is_dl) { + block->u.Packet_Neighbour_Cell_Data.Global_TFI.u.DOWNLINK_TFI = tfi; + } else { + block->u.Packet_Neighbour_Cell_Data.Global_TFI.u.UPLINK_TFI = tfi; + } + block->u.Packet_Neighbour_Cell_Data.CONTAINER_ID = container_id; + block->u.Packet_Neighbour_Cell_Data.spare = 0; + block->u.Packet_Neighbour_Cell_Data.CONTAINER_INDEX = container_idx; + block->u.Packet_Neighbour_Cell_Data.Container = *container; +} + /* Generate paging request. See 44.018, sections 10 and 9.1.22 */ int Encoding::write_paging_request(bitvec * dest, const struct osmo_mobile_identity *mi) { diff --git a/src/encoding.h b/src/encoding.h index da63a61..98320a7 100644 --- a/src/encoding.h +++ b/src/encoding.h @@ -70,6 +70,10 @@ uint8_t alpha, uint8_t gamma, int8_t ta_idx, uint8_t ta_ts, bool use_egprs); + static void write_packet_neighbour_cell_data(RlcMacDownlink_t * block, + bool tfi_is_dl, uint8_t tfi, uint8_t container_id, + uint8_t container_idx, PNCDContainer_t *container); + static void encode_rbb(const char *show_rbb, uint8_t *rbb); static void write_packet_access_reject( diff --git a/src/gprs_debug.cpp b/src/gprs_debug.cpp index a790e3f..1cefa9b 100644 --- a/src/gprs_debug.cpp +++ b/src/gprs_debug.cpp @@ -119,6 +119,13 @@ .loglevel = LOGL_NOTICE, .enabled = 1, }, + [DNACC] = { + .name = "DNACC", + .color = "\033[1;37m", + .description = "Network Assisted Cell Change (NACC)", + .loglevel = LOGL_NOTICE, + .enabled = 1, + }, }; static int filter_fn(const struct log_context *ctx, diff --git a/src/gprs_debug.h b/src/gprs_debug.h index 84a0a07..23ea44d 100644 --- a/src/gprs_debug.h +++ b/src/gprs_debug.h @@ -46,6 +46,7 @@ DTBFUL, DNS, DPCU, + DNACC, aDebug_LastEntry }; diff --git a/src/gprs_ms.cpp b/src/gprs_ms.cpp index c891cdf..e52585b 100644 --- a/src/gprs_ms.cpp +++ b/src/gprs_ms.cpp @@ -26,6 +26,7 @@ #include "gprs_debug.h" #include "gprs_codel.h" #include "pcu_utils.h" +#include "nacc_fsm.h" #include <time.h> @@ -898,3 +899,10 @@ return NULL; } + +int GprsMs::start_nacc(Packet_Cell_Change_Notification_t *notif) +{ + if (!nacc) + nacc = nacc_fsm_alloc(this); + return osmo_fsm_inst_dispatch(nacc->fi, NACC_EV_CELL_CHG_NOTIFICATION, notif); +} diff --git a/src/gprs_ms.h b/src/gprs_ms.h index 8b8940b..0836d07 100644 --- a/src/gprs_ms.h +++ b/src/gprs_ms.h @@ -43,6 +43,8 @@ #include <stddef.h> #include <inttypes.h> +#include <gsm_rlcmac.h> + struct BTS; struct gprs_rlcmac_trx; @@ -139,6 +141,8 @@ unsigned dl_ctrl_msg() const; void update_dl_ctrl_msg(); + int start_nacc(Packet_Cell_Change_Notification_t *notif); + /* internal use */ static void timeout(void *priv_); @@ -193,6 +197,8 @@ enum mcs_kind m_mode; unsigned m_dl_ctrl_msg; + + struct nacc_fsm_ctx *nacc; }; inline bool GprsMs::is_idle() const diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp index e6f7176..5170bb6 100644 --- a/src/gprs_rlcmac_sched.cpp +++ b/src/gprs_rlcmac_sched.cpp @@ -38,6 +38,7 @@ struct gprs_rlcmac_tbf *poll; struct gprs_rlcmac_tbf *ul_ass; struct gprs_rlcmac_tbf *dl_ass; + struct gprs_rlcmac_tbf *nacc_tbf; struct gprs_rlcmac_ul_tbf *ul_ack; }; @@ -71,6 +72,7 @@ if (ul_tbf->ul_ass_state_is(GPRS_RLCMAC_UL_ASS_SEND_ASS) || ul_tbf->ul_ass_state_is(GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ)) tbf_cand->ul_ass = ul_tbf; + /* TODO: if ul_tbf has NeighbourCellData or CellChangeContinue pending to send, select */ /* FIXME: Is this supposed to be fair? The last TBF for each wins? Maybe use llist_add_tail and skip once we have all states? */ } @@ -88,6 +90,7 @@ if (dl_tbf->ul_ass_state_is(GPRS_RLCMAC_UL_ASS_SEND_ASS) || dl_tbf->ul_ass_state_is(GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ)) tbf_cand->ul_ass = dl_tbf; + /* TODO: if dl_tbf has NeighbourCellData or CellChangeContinue pending to send, select */ } return poll_fn; diff --git a/src/nacc_fsm.cpp b/src/nacc_fsm.cpp new file mode 100644 index 0000000..2a6dec4 --- /dev/null +++ b/src/nacc_fsm.cpp @@ -0,0 +1,204 @@ +#include <talloc.h> + +#include <nacc_fsm.h> +#include <gprs_rlcmac.h> +#include <gprs_debug.h> +#include <gprs_ms.h> +#include <encoding.h> + +#define X(s) (1 << (s)) + +#define nacc_fsm_state_chg(fi, NEXT_STATE) \ + osmo_fsm_inst_state_chg(fi, NEXT_STATE, 0, 0) + +const struct value_string nacc_fsm_event_names[] = { + { NACC_EV_CELL_CHG_NOTIFICATION, "CELL_CHG_NOTIFICATION" }, + { NACC_EV_SI_INFO_RECEIVED, "SI_INFO_RECEIVED" }, + { 0, NULL } +}; + + +static void st_initial(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct nacc_fsm_ctx *ctx = (struct nacc_fsm_ctx *)fi->priv; + Packet_Cell_Change_Notification_t *notif; + + switch (event) { + case NACC_EV_CELL_CHG_NOTIFICATION: + notif = (Packet_Cell_Change_Notification_t *)data; + switch (notif->Target_Cell.UnionType) { + case 0: /* GSM */ + ctx->req_arfcn = notif->Target_Cell.u.Target_Cell_GSM_Notif.ARFCN; + ctx->req_bsic = notif->Target_Cell.u.Target_Cell_GSM_Notif.BSIC; + /* Here we'll do RIM requested whenver we support it, and jump to st NACC_ST_REQUESTING_SI */ + nacc_fsm_state_chg(fi, NACC_ST_TX_NEIGHBOUR_DATA); + break; + default: + LOGPFSML(fi, LOGL_NOTICE, "TargetCell type=0x%x not supported\n", + notif->Target_Cell.UnionType); + return; + } + break; + default: + OSMO_ASSERT(0); + } +} + +extern void *tall_pcu_ctx; +static struct msgb *create_packet_neighbour_cell_data(struct nacc_fsm_ctx *ctx) +{ + struct msgb *msg; + RlcMacDownlink_t *mac_control_block = NULL; + + msg = msgb_alloc(GSM_MACBLOCK_LEN, "neighbour_cell_data"); + if (!msg) + return NULL; + + /* Initialize a bit vector that uses allocated msgb as the data buffer. + * Old G++ does not support non-trivial designated initializers. Sigh. */ + struct bitvec bv = { }; + bv.data = msgb_put(msg, GSM_MACBLOCK_LEN); + bv.data_len = GSM_MACBLOCK_LEN; + bitvec_unhex(&bv, DUMMY_VEC); + + mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t); + + uint8_t tfi_is_dl = 0; /* FIXME: get from any tbf from MS */ + uint8_t tfi = 0; /* FIXME: get from any tbf from MS */ + uint8_t container_id = 0; /* FIXME: don't hardcode */ + uint8_t container_idx = 0; /* FIXME: don't hardcode */ + PNCDContainer_t container; + memset(&container, 0, sizeof(container)); + container.UnionType = 1; /* with ID */ + container.u.PNCD_Container_With_ID.ARFCN = ctx->req_arfcn; + container.u.PNCD_Container_With_ID.BSIC = ctx->req_arfcn; + Encoding::write_packet_neighbour_cell_data(mac_control_block, + tfi_is_dl, tfi, container_id, + container_idx, &container); + talloc_free(mac_control_block); + return msg; +} + +static void st_tx_neighbour_data_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state) +{ + struct nacc_fsm_ctx *ctx = (struct nacc_fsm_ctx *)fi->priv; + struct msgb *msg = create_packet_neighbour_cell_data(ctx); + (void)msg; + + /* TODO: submit RIM message to obtain real SI info of {req_arfcn+req_bsic} */ + + /* TODO: flag MS/TBF somehow that we have data to send so that it gets + selected in sched_select_ctrl_msg */ + + nacc_fsm_state_chg(fi, NACC_ST_TX_CELL_CHG_CONTINUE); +} + +static void st_cell_cgh_continue_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state) +{ + //struct nacc_fsm_ctx *ctx = (struct nacc_fsm_ctx *)fi->priv; + + /* send fake CELL_CGH_CONTINUE message to MS for req_arfcn req_bsic */ + + nacc_fsm_state_chg(fi, NAC_ST_DONE); + /* TODO: terminate FSM somehow and free it? */ +} + + +static void st_done_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state) +{ + nacc_fsm_state_chg(fi, NACC_ST_INITIAL); + /* TODO: terminate FSM somehow and free it? */ +} + +extern "C" { +static struct osmo_fsm_state nacc_fsm_states[] = { + [NACC_ST_INITIAL] = { + .in_event_mask = + X(NACC_EV_CELL_CHG_NOTIFICATION), + .out_state_mask = + X(NACC_ST_REQUESTING_SI) | + X(NAC_ST_DONE), + .name = "INITIAL", + //.onenter = st_initial_on_enter, + .action = st_initial, + }, + [NACC_ST_REQUESTING_SI] = { + .in_event_mask = + X(NACC_EV_CELL_CHG_NOTIFICATION) | + X(NACC_EV_SI_INFO_RECEIVED), + .out_state_mask = + X(NACC_ST_TX_CELL_CHG_CONTINUE), + .name = "REQUESTING_SI", + //.onenter = st_requesting_si_on_enter, + //.action = st_requesting_si, + }, + [NACC_ST_TX_NEIGHBOUR_DATA] = { + .in_event_mask = + X(NACC_EV_CELL_CHG_NOTIFICATION) | + X(NACC_EV_SI_INFO_RECEIVED), + .out_state_mask = + X(NACC_ST_REQUESTING_SI) | + X(NACC_ST_TX_CELL_CHG_CONTINUE), + .name = "DISABLED_DEPENDENCY", + .onenter = st_tx_neighbour_data_on_enter, + //.action = st_tx_neighbour_data, + }, + [NACC_ST_TX_CELL_CHG_CONTINUE] = { + .in_event_mask = + X(NACC_EV_CELL_CHG_NOTIFICATION) | + X(NACC_EV_SI_INFO_RECEIVED), + .out_state_mask = + X(NAC_ST_DONE), + .name = "CELL_CHG_CONTINUE", + .onenter = st_cell_cgh_continue_on_enter, + //.action = st_cell_cgh_continue, + }, + [NAC_ST_DONE] = { + .in_event_mask = 0, + .out_state_mask = + X(NACC_ST_INITIAL), + .name = "DONE", + .onenter = st_done_on_enter, + //.action = st_done, + }, +}; + +} + +/* Structure fields set at runtime in constructor in order to avoid g++ < 8: + * "sorry, unimplemented: non-trivial designated initializers not supported" */ +static struct osmo_fsm nacc_fsm; +static __attribute__((constructor)) void nacc_fsm_init(void) +{ + nacc_fsm.name = "NACC"; + nacc_fsm.states = nacc_fsm_states; + nacc_fsm.num_states = ARRAY_SIZE(nacc_fsm_states); + nacc_fsm.log_subsys = DNACC; + nacc_fsm.event_names = nacc_fsm_event_names; + OSMO_ASSERT(osmo_fsm_register(&nacc_fsm) == 0); +} + +static int nacc_fsm_ctx_talloc_destructor(struct nacc_fsm_ctx *ctx) +{ + if (ctx->fi) { + osmo_fsm_inst_free(ctx->fi); + ctx->fi = NULL; + } + + return 0; +} + +struct nacc_fsm_ctx *nacc_fsm_alloc(GprsMs* ms) +{ + struct nacc_fsm_ctx *ctx = talloc_zero(ms, struct nacc_fsm_ctx); + char buf[64]; + + talloc_set_destructor(ctx, nacc_fsm_ctx_talloc_destructor); + + ctx->ms = ms; + + snprintf(buf, sizeof(buf), "TLLI-0x%08x", ms->tlli()); + ctx->fi = osmo_fsm_inst_alloc(&nacc_fsm, ctx, ctx, LOGL_INFO, buf); + + return ctx; +} diff --git a/src/nacc_fsm.h b/src/nacc_fsm.h new file mode 100644 index 0000000..a1dc1f0 --- /dev/null +++ b/src/nacc_fsm.h @@ -0,0 +1,28 @@ +#pragma once +extern "C" { +#include <osmocom/core/fsm.h> +} + +class GprsMs; + +enum nacc_fsm_event { + NACC_EV_CELL_CHG_NOTIFICATION, /* data: Packet_Cell_Change_Notification_t* */ + NACC_EV_SI_INFO_RECEIVED, +}; + +enum nacc_fsm_states { + NACC_ST_INITIAL, + NACC_ST_REQUESTING_SI, + NACC_ST_TX_NEIGHBOUR_DATA, + NACC_ST_TX_CELL_CHG_CONTINUE, + NAC_ST_DONE, +}; + +struct nacc_fsm_ctx { + struct osmo_fsm_inst *fi; + GprsMs* ms; /* back pointer */ + uint16_t req_arfcn; + uint8_t req_bsic; +}; + +struct nacc_fsm_ctx *nacc_fsm_alloc(GprsMs* ms); diff --git a/src/pdch.cpp b/src/pdch.cpp index 4a0ff06..a0d53d4 100644 --- a/src/pdch.cpp +++ b/src/pdch.cpp @@ -683,6 +683,31 @@ gprs_rlcmac_meas_rep(ms, report); } +void gprs_rlcmac_pdch::rcv_cell_change_notification(Packet_Cell_Change_Notification_t *notif, + uint32_t fn, struct pcu_l1_meas *meas) +{ + GprsMs *ms; + + if (notif->Global_TFI.UnionType == 0) { + struct gprs_rlcmac_ul_tbf *ul_tbf = ul_tbf_by_tfi(notif->Global_TFI.u.UPLINK_TFI); + if (!ul_tbf) { + LOGP(DRLCMAC, LOGL_NOTICE, "UL TBF TFI=0x%2x not found\n", notif->Global_TFI.u.UPLINK_TFI); + return; + } + ms = ul_tbf->ms(); + } else if (notif->Global_TFI.UnionType == 1) { + struct gprs_rlcmac_dl_tbf *dl_tbf = dl_tbf_by_tfi(notif->Global_TFI.u.DOWNLINK_TFI); + if (!dl_tbf) { + LOGP(DRLCMAC, LOGL_NOTICE, "DL TBF TFI=0x%2x not found\n", notif->Global_TFI.u.DOWNLINK_TFI); + return; + } + ms = dl_tbf->ms(); + } else { OSMO_ASSERT(0); } + + ms->update_l1_meas(meas); + ms->start_nacc(notif); +} + /* Received Uplink RLC control block. */ int gprs_rlcmac_pdch::rcv_control_block(const uint8_t *data, uint8_t data_len, uint32_t fn, struct pcu_l1_meas *meas, enum CodingScheme cs) @@ -732,6 +757,9 @@ case MT_PACKET_UPLINK_DUMMY_CONTROL_BLOCK: /* ignoring it. change the SI to not force sending these? */ break; + case MT_PACKET_CELL_CHANGE_NOTIFICATION: + rcv_cell_change_notification(&ul_control_block->u.Packet_Cell_Change_Notification, fn, meas); + break; default: bts()->do_rate_ctr_inc(CTR_DECODE_ERRORS); LOGP(DRLCMAC, LOGL_NOTICE, diff --git a/src/pdch.h b/src/pdch.h index 5185045..4515439 100644 --- a/src/pdch.h +++ b/src/pdch.h @@ -140,6 +140,7 @@ void rcv_control_egprs_dl_ack_nack(EGPRS_PD_AckNack_t *, uint32_t fn, struct pcu_l1_meas *meas); void rcv_resource_request(Packet_Resource_Request_t *t, uint32_t fn, struct pcu_l1_meas *meas); void rcv_measurement_report(Packet_Measurement_Report_t *t, uint32_t fn); + void rcv_cell_change_notification(Packet_Cell_Change_Notification_t *, uint32_t fn, struct pcu_l1_meas *meas); gprs_rlcmac_tbf *tbf_from_list_by_tfi( LListHead<gprs_rlcmac_tbf> *tbf_list, uint8_t tfi, enum gprs_rlcmac_tbf_direction dir); -- To view, visit https://gerrit.osmocom.org/c/osmo-pcu/+/21745 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-pcu Gerrit-Branch: master Gerrit-Change-Id: Icac5cfe93bcad0e18e5c9380d4e82233856633aa Gerrit-Change-Number: 21745 Gerrit-PatchSet: 1 Gerrit-Owner: pespin <pespin at sysmocom.de> Gerrit-MessageType: newchange -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20201216/a65570df/attachment.htm>