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/+/22338 ) Change subject: WIP: Introduce NACC support ...................................................................... WIP: Introduce NACC support Change-Id: Ife6e4a086d58d49676d12b6984f63079ec472e79 --- M configure.ac M src/Makefile.am M src/bts.cpp M src/bts.h M src/encoding.cpp M src/encoding.h M src/gprs_bssgp_pcu.c M src/gprs_debug.cpp M src/gprs_debug.h M src/gprs_ms.c M src/gprs_ms.h M src/gprs_pcu.c M src/gprs_pcu.h M src/gprs_rlcmac_sched.cpp A src/nacc_fsm.c A src/nacc_fsm.h M src/pcu_vty.c M src/pdch.cpp M src/pdch.h M src/tbf.cpp M src/tbf.h M tests/Makefile.am 22 files changed, 826 insertions(+), 4 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-pcu refs/changes/38/22338/1 diff --git a/configure.ac b/configure.ac index 2e99a15..11de328 100644 --- a/configure.ac +++ b/configure.ac @@ -84,6 +84,7 @@ dnl checks for libraries PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.4.0) PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.4.0) +PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.4.0) PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.4.0) PKG_CHECK_MODULES(LIBOSMOGB, libosmogb >= 1.4.0) diff --git a/src/Makefile.am b/src/Makefile.am index de924a6..2228aee 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,7 +19,7 @@ # AUTOMAKE_OPTIONS = subdir-objects -AM_CPPFLAGS = -I$(top_srcdir)/include $(STD_DEFINES_AND_INCLUDES) $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGB_CFLAGS) $(LIBOSMOGSM_CFLAGS) +AM_CPPFLAGS = -I$(top_srcdir)/include $(STD_DEFINES_AND_INCLUDES) $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGB_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOGSM_CFLAGS) if ENABLE_SYSMODSP AM_CPPFLAGS += -DENABLE_DIRECT_PHY @@ -54,6 +54,7 @@ pcu_vty.c \ pcu_vty_functions.cpp \ mslot_class.c \ + nacc_fsm.c \ 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 \ @@ -141,6 +143,7 @@ libgprs.la \ $(LIBOSMOGB_LIBS) \ $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOCTRL_LIBS) \ $(LIBOSMOGSM_LIBS) \ $(COMMON_LA) endif @@ -189,6 +192,7 @@ libgprs.la \ $(LIBOSMOGB_LIBS) \ $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOCTRL_LIBS) \ $(LIBOSMOGSM_LIBS) \ $(COMMON_LA) diff --git a/src/bts.cpp b/src/bts.cpp index b5bb3a2..eb4bdd9 100644 --- a/src/bts.cpp +++ b/src/bts.cpp @@ -140,6 +140,9 @@ { "pkt:ul_assignment", "Packet UL Assignment "}, { "pkt:access_reject", "Packet Access Reject "}, { "pkt:dl_assignment", "Packet DL Assignment "}, + { "pkt:cell_chg_notification", "Packet Cell Change Notification"}, + { "pkt:cell_chg_continue", "Packet Cell Change Continue"}, + { "pkt:neigh_cell_data", "Packet Neighbour Cell Data"}, { "ul:control", "UL control Block "}, { "ul:assignment_poll_timeout", "UL Assign Timeout "}, { "ul:assignment_failed", "UL Assign Failed "}, diff --git a/src/bts.h b/src/bts.h index 7f437e3..cf16e66 100644 --- a/src/bts.h +++ b/src/bts.h @@ -2,6 +2,7 @@ * * Copyright (C) 2012 Ivan Klyuchnikov * Copyright (C) 2013 by Holger Hans Peter Freyther + * Copyright (C) 2021 by sysmocom - s.f.m.c. GmbH <info at sysmocom.de * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -125,6 +126,9 @@ CTR_PKT_UL_ASSIGNMENT, CTR_PKT_ACCESS_REJ, CTR_PKT_DL_ASSIGNMENT, + CTR_PKT_CELL_CHG_NOTIFICATION, + CTR_PKT_CELL_CHG_CONTINUE, + CTR_PKT_NEIGH_CELL_DATA, CTR_RLC_RECV_CONTROL, CTR_PUA_POLL_TIMEDOUT, CTR_PUA_POLL_FAILED, diff --git a/src/encoding.cpp b/src/encoding.cpp index f605ca2..24e1d68 100644 --- a/src/encoding.cpp +++ b/src/encoding.cpp @@ -1731,3 +1731,56 @@ bitvec_write_field(dest, &wp, 5, 8); // WAIT_INDICATION value bitvec_write_field(dest, &wp, 0, 1); // WAIT_INDICATION size in seconds } + +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) +{ + + 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; +} + +void write_packet_cell_change_continue(RlcMacDownlink_t *block, + bool tfi_is_dl, uint8_t tfi, bool exist_id, + uint16_t arfcn, uint8_t bsic, uint8_t container_id) +{ + + 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_Cell_Change_Continue.MESSAGE_TYPE = MT_PACKET_CELL_CHANGE_CONTINUE; + block->u.Packet_Cell_Change_Continue.PAGE_MODE = 0x0; // Normal Paging + + block->u.Packet_Cell_Change_Continue.Global_TFI.UnionType = tfi_is_dl; // 0=UPLINK TFI, 1=DL TFI + if (tfi_is_dl) { + block->u.Packet_Cell_Change_Continue.Global_TFI.u.DOWNLINK_TFI = tfi; + } else { + block->u.Packet_Cell_Change_Continue.Global_TFI.u.UPLINK_TFI = tfi; + } + + block->u.Packet_Cell_Change_Continue.Exist_ID = exist_id; + if (exist_id) { + block->u.Packet_Cell_Change_Continue.ARFCN = arfcn; + block->u.Packet_Cell_Change_Continue.BSIC = bsic; + } + block->u.Packet_Cell_Change_Continue.CONTAINER_ID = container_id; +} diff --git a/src/encoding.h b/src/encoding.h index da63a61..4ebfa35 100644 --- a/src/encoding.h +++ b/src/encoding.h @@ -22,17 +22,22 @@ #include <stdint.h> +#ifdef __cplusplus extern "C" { +#endif #include <osmocom/gsm/l1sap.h> #include "coding_scheme.h" #include "gsm_rlcmac.h" +#ifdef __cplusplus } +#endif struct gprs_rlcmac_tbf; struct bitvec; struct gprs_llc; struct gprs_rlc_data_block_info; +#ifdef __cplusplus /** * I help with encoding data into CSN1 messages. * TODO: Nobody can remember a function signature like this. One should @@ -108,3 +113,21 @@ const struct gprs_rlc_data_block_info *rdbi, int *offset, int *num_chunks, uint8_t *data_block); }; + +#endif /* ifdef __cplusplus */ + +#ifdef __cplusplus +extern "C" { +#endif + +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); + +void write_packet_cell_change_continue(RlcMacDownlink_t *block, + bool tfi_is_dl, uint8_t tfi, bool exist_id, + uint16_t arfcn, uint8_t bsic, uint8_t container_id); + +#ifdef __cplusplus +} +#endif diff --git a/src/gprs_bssgp_pcu.c b/src/gprs_bssgp_pcu.c index 956fb66..9c05639 100644 --- a/src/gprs_bssgp_pcu.c +++ b/src/gprs_bssgp_pcu.c @@ -419,10 +419,22 @@ int rc = 0; struct bssgp_bvc_ctx *bctx; - if (pdu_type == BSSGP_PDUT_STATUS) + switch (pdu_type) { + case BSSGP_PDUT_STATUS: /* Pass the message to the generic BSSGP parser, which handles * STATUS and RESET messages in either direction. */ + case BSSGP_PDUT_RAN_INFO: + case BSSGP_PDUT_RAN_INFO_REQ: + case BSSGP_PDUT_RAN_INFO_ACK: + case BSSGP_PDUT_RAN_INFO_ERROR: + case BSSGP_PDUT_RAN_INFO_APP_ERROR: + /* Also pass all RIM related messages to the generic BSSGP + * parser so that it can deliver primitive to the RIM SAP + * (SAP_BSSGP_RIM) */ return bssgp_rcvmsg(msg); + default: + break; + } /* Identifiers from DOWN: NSEI, BVCI (both in msg->cb) */ @@ -542,6 +554,15 @@ } } +static void handle_rim(struct osmo_bssgp_prim *bp) +{ + /* TODO: handle RIM messages here. for RAN-INFORMATION answer, we + somehow need to match the RAN-INFORMATION-REQUEST that triggered it, + or feed it to all active FSMs and see if that matches internally and + can go forward. That's probably the best: fill into a cache and then + signal all existing NACC FSMs. */ +} + int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx) { struct osmo_bssgp_prim *bp; @@ -551,6 +572,8 @@ case SAP_BSSGP_NM: if (oph->primitive == PRIM_NM_STATUS) handle_nm_status(bp); + case SAP_BSSGP_RIM: + handle_rim(bp); break; default: break; 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.c b/src/gprs_ms.c index ea497a3..5d7afa1 100644 --- a/src/gprs_ms.c +++ b/src/gprs_ms.c @@ -26,6 +26,7 @@ #include "gprs_debug.h" #include "gprs_codel.h" #include "pcu_utils.h" +#include "nacc_fsm.h" #include <time.h> @@ -902,3 +903,36 @@ return NULL; } + +int ms_nacc_start(struct GprsMs *ms, Packet_Cell_Change_Notification_t *notif) +{ + if (!ms->nacc) + ms->nacc = nacc_fsm_alloc(ms); + if (!ms->nacc) + return -EINVAL; + return osmo_fsm_inst_dispatch(ms->nacc->fi, NACC_EV_CELL_CHG_NOTIFICATION, notif); +} + +bool ms_nacc_rts(const struct GprsMs *ms) +{ + if (!ms->nacc) + return false; + if (ms->nacc->fi->state == NACC_ST_TX_NEIGHBOUR_DATA || + ms->nacc->fi->state == NACC_ST_TX_CELL_CHG_CONTINUE) + return true; + return false; +} + +struct msgb *ms_nacc_create_rlcmac_msg(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf) +{ + int rc; + struct nacc_ev_create_rlcmac_msg_ctx data_ctx; + + data_ctx.tbf = tbf; + data_ctx.msg = NULL; + + rc = osmo_fsm_inst_dispatch(ms->nacc->fi, NACC_EV_CREATE_RLCMAC_MSG, &data_ctx); + if (rc != 0 || !data_ctx.msg) + return NULL; + return data_ctx.msg; +} diff --git a/src/gprs_ms.h b/src/gprs_ms.h index 12809f1..6587231 100644 --- a/src/gprs_ms.h +++ b/src/gprs_ms.h @@ -40,6 +40,7 @@ #include <osmocom/gsm/gsm48.h> #include "coding_scheme.h" +#include <gsm_rlcmac.h> #include <stdint.h> #include <stddef.h> @@ -100,6 +101,7 @@ enum mcs_kind mode; struct rate_ctr_group *ctrs; + struct nacc_fsm_ctx *nacc; }; struct GprsMs *ms_alloc(struct gprs_rlcmac_bts *bts, uint32_t tlli); @@ -140,6 +142,10 @@ void ms_set_callback(struct GprsMs *ms, struct gpr_ms_callback *cb); +int ms_nacc_start(struct GprsMs *ms, Packet_Cell_Change_Notification_t *notif); +bool ms_nacc_rts(const struct GprsMs *ms); +struct msgb *ms_nacc_create_rlcmac_msg(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf); + static inline bool ms_is_idle(const struct GprsMs *ms) { return !ms->ul_tbf && !ms->dl_tbf && !ms->ref && llist_empty(&ms->old_tbfs); diff --git a/src/gprs_pcu.c b/src/gprs_pcu.c index d291e71..19fbf7d 100644 --- a/src/gprs_pcu.c +++ b/src/gprs_pcu.c @@ -22,6 +22,7 @@ #include <osmocom/core/utils.h> #include <osmocom/core/linuxlist.h> +#include <osmocom/ctrl/ports.h> #include "gprs_pcu.h" #include "bts.h" @@ -97,6 +98,8 @@ 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_port = OSMO_CTRL_PORT_BSC_NEIGH; pcu->T_defs = T_defs_pcu; osmo_tdefs_reset(pcu->T_defs); diff --git a/src/gprs_pcu.h b/src/gprs_pcu.h index 058d102..f9f9893 100644 --- a/src/gprs_pcu.h +++ b/src/gprs_pcu.h @@ -102,6 +102,9 @@ uint32_t llc_discard_csec; uint32_t llc_idle_ack_csec; uint32_t llc_codel_interval_msec; /* 0=disabled, -1=use default interval */ + /* Remote BSS resolution sevice (CTRL iface) */ + char *neigh_ctrl_addr; + uint16_t neigh_ctrl_port; } vty; struct gsmtap_inst *gsmtap; diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp index 5640158..66e9c6b 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; struct gprs_rlcmac_ul_tbf *ul_ack; }; @@ -71,6 +72,9 @@ 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; + /* NACC ready to send */ + if (ms_nacc_rts(ul_tbf->ms())) + tbf_cand->nacc = ul_tbf; /* 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 +92,9 @@ 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; + /* NACC ready to send */ + if (ms_nacc_rts(dl_tbf->ms())) + tbf_cand->nacc = dl_tbf; } return poll_fn; @@ -166,7 +173,8 @@ struct gprs_rlcmac_tbf *tbf = NULL; struct gprs_rlcmac_tbf *next_list[] = { tbfs->ul_ass, tbfs->dl_ass, - tbfs->ul_ack }; + tbfs->ul_ack, + tbfs->nacc }; /* Send Packet Application Information first (ETWS primary notifications) */ msg = sched_app_info(tbfs->dl_ass); @@ -194,6 +202,9 @@ msg = tbfs->dl_ass->create_dl_ass(fn, ts); else if (tbf == tbfs->ul_ack) msg = tbfs->ul_ack->create_ul_ack(fn, ts); + else if (tbf == tbfs->nacc) { + msg = ms_nacc_create_rlcmac_msg(tbf->ms(), tbf); + } /* else: if tbf/ms is pending to send tx_neigbhourData or tx_CellchangeContinue, send it */ if (!msg) { diff --git a/src/nacc_fsm.c b/src/nacc_fsm.c new file mode 100644 index 0000000..1ae417d --- /dev/null +++ b/src/nacc_fsm.c @@ -0,0 +1,538 @@ +#include <unistd.h> + +#include <talloc.h> + +#include <osmocom/core/rate_ctr.h> +#include <osmocom/ctrl/control_cmd.h> +#include <osmocom/ctrl/control_if.h> + +#include <osmocom/gsm/gsm48.h> +#include <osmocom/gprs/gprs_bssgp.h> +#include <osmocom/gprs/gprs_bssgp_rim.h> + +#include <nacc_fsm.h> +#include <gprs_rlcmac.h> +#include <gprs_debug.h> +#include <gprs_ms.h> +#include <encoding.h> +#include <bts.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_RX_RESOLVE_RAC_CI, "RX_RESOLVE_RAC_CI" }, + { NACC_EV_SI_INFO_RECEIVED, "SI_INFO_RECEIVED" }, + { NACC_EV_CREATE_RLCMAC_MSG, "CREATE_RLCMAC_MSG" }, + { 0, NULL } +}; + +static struct msgb *create_packet_neighbour_cell_data(struct nacc_fsm_ctx *ctx, struct gprs_rlcmac_tbf *tbf) +{ + struct msgb *msg; + int rc; + RlcMacDownlink_t *mac_control_block; + struct GprsMs *ms = tbf_ms(tbf); + + 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. */ + struct bitvec bv = { + .data = msgb_put(msg, GSM_MACBLOCK_LEN), + .data_len = GSM_MACBLOCK_LEN, + }; + bitvec_unhex(&bv, DUMMY_VEC); + + mac_control_block = (RlcMacDownlink_t *)talloc_zero(ctx->ms, RlcMacDownlink_t); + + OSMO_ASSERT(tbf_is_tfi_assigned(tbf)); + uint8_t tfi_is_dl = tbf_direction(tbf) == GPRS_RLCMAC_DL_TBF; + uint8_t tfi = tbf_tfi(tbf); + 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_bsic; + write_packet_neighbour_cell_data(mac_control_block, + tfi_is_dl, tfi, container_id, + container_idx, &container); + LOGP(DNACC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Neighbour Cell Data +++++++++++++++++++++++++\n"); + rc = encode_gsm_rlcmac_downlink(&bv, mac_control_block); + if (rc < 0) { + LOGP(DTBF, LOGL_ERROR, "Encoding of Packet Neighbour Cell Data failed (%d)\n", rc); + goto free_ret; + } + LOGP(DNACC, LOGL_DEBUG, "------------------------- TX : Packet Neighbour Cell Data -------------------------\n"); + rate_ctr_inc(&bts_rate_counters(ms->bts)->ctr[CTR_PKT_NEIGH_CELL_DATA]); + talloc_free(mac_control_block); + return msg; + +free_ret: + talloc_free(mac_control_block); + msgb_free(msg); + return NULL; +} + +static struct msgb *create_packet_cell_chg_continue(struct nacc_fsm_ctx *ctx, struct gprs_rlcmac_tbf *tbf) +{ + struct msgb *msg; + int rc; + RlcMacDownlink_t *mac_control_block; + struct GprsMs *ms = tbf_ms(tbf); + + msg = msgb_alloc(GSM_MACBLOCK_LEN, "pkt_cell_chg_continue"); + if (!msg) + return NULL; + + /* Initialize a bit vector that uses allocated msgb as the data buffer. */ + struct bitvec bv = { + .data = msgb_put(msg, GSM_MACBLOCK_LEN), + .data_len = GSM_MACBLOCK_LEN, + }; + bitvec_unhex(&bv, DUMMY_VEC); + + mac_control_block = (RlcMacDownlink_t *)talloc_zero(ctx->ms, RlcMacDownlink_t); + + OSMO_ASSERT(tbf_is_tfi_assigned(tbf)); + uint8_t tfi_is_dl = tbf_direction(tbf) == GPRS_RLCMAC_DL_TBF; + uint8_t tfi = tbf_tfi(tbf); + uint8_t container_id = 0; /* FIXME: don't hardcode */ + write_packet_cell_change_continue(mac_control_block, tfi_is_dl, tfi, true, + ctx->req_arfcn, ctx->req_bsic, container_id); + LOGP(DNACC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Cell Change Continue +++++++++++++++++++++++++\n"); + rc = encode_gsm_rlcmac_downlink(&bv, mac_control_block); + if (rc < 0) { + LOGP(DTBF, LOGL_ERROR, "Encoding of Packet Cell Change Continue failed (%d)\n", rc); + goto free_ret; + } + LOGP(DNACC, LOGL_DEBUG, "------------------------- TX : Packet Cell Change Continue -------------------------\n"); + rate_ctr_inc(&bts_rate_counters(ms->bts)->ctr[CTR_PKT_CELL_CHG_CONTINUE]); + talloc_free(mac_control_block); + return msg; + +free_ret: + talloc_free(mac_control_block); + msgb_free(msg); + return 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; + /* TODO: look up in resolution table whether we already have RAC+CI for ARFCN+BSIC */ + nacc_fsm_state_chg(fi, NACC_ST_WAIT_RESOLVE_RAC_CI); + break; + default: + LOGPFSML(fi, LOGL_NOTICE, "TargetCell type=0x%x not supported\n", + notif->Target_Cell.UnionType); + return; + } + break; + default: + OSMO_ASSERT(0); + } +} + +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 ctrl_cmd *cmd; + int rc; + + cmd = ctrl_cmd_create(ctx, CTRL_TYPE_GET); + if (!cmd) { + LOGPFSML(fi, LOGL_ERROR, "CTRL msg creation failed\n"); + return; + } + + cmd->id = talloc_asprintf(cmd, "1"); + cmd->variable = talloc_asprintf(cmd, "neighbor_resolve_cgi_ps_from_lac_ci.%d.%d.%d.%d", + bts->cgi_ps.rai.lac.lac, bts->cgi_ps.cell_identity, + ctx->req_arfcn, ctx->req_bsic); + //rep->value = 0; + rc = ctrl_cmd_send(&ctx->neigh_ctrl_conn->write_queue, cmd); + if (rc) + LOGPFSML(fi, LOGL_ERROR, "CTRL msg sent failed: %d\n", rc); + talloc_free(cmd); +} + + +static void st_wait_resolve_rac_ci(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + //struct nacc_fsm_ctx *ctx = (struct nacc_fsm_ctx *)fi->priv; + + switch (event) { + case NACC_EV_CELL_CHG_NOTIFICATION: + break; + case NACC_EV_RX_RESOLVE_RAC_CI: + nacc_fsm_state_chg(fi, NACC_ST_WAIT_REQUEST_SI); + break; + default: + OSMO_ASSERT(0); + } +} + +static int fill_rim_ran_info_req(struct nacc_fsm_ctx *ctx, struct bssgp_ran_information_pdu *pdu) +{ + struct gprs_rlcmac_bts *bts = ctx->ms->bts; + + *pdu = (struct bssgp_ran_information_pdu){ + .routing_info_dest = { + .discr = BSSGP_RIM_ROUTING_INFO_GERAN, + .geran = { + .raid = { + .mcc = ctx->cgi_ps.rai.lac.plmn.mcc, + .mnc = ctx->cgi_ps.rai.lac.plmn.mnc, + .mnc_3_digits = ctx->cgi_ps.rai.lac.plmn.mnc_3_digits, + .lac = ctx->cgi_ps.rai.lac.lac, + .rac = ctx->cgi_ps.rai.rac, + }, + .cid = ctx->cgi_ps.cell_identity, + }, + }, + .routing_info_src = { + .discr = BSSGP_RIM_ROUTING_INFO_GERAN, + .geran = { + .raid = { /* TODO: fill properly */ + .mcc = bts->cgi_ps.rai.lac.plmn.mcc, + .mnc = bts->cgi_ps.rai.lac.plmn.mnc, + .mnc_3_digits = bts->cgi_ps.rai.lac.plmn.mnc_3_digits, + .lac = bts->cgi_ps.rai.lac.lac, + .rac = bts->cgi_ps.rai.rac, + }, + .cid = bts->cgi_ps.cell_identity, + }, + }, + .rim_cont_iei = BSSGP_IE_RI_REQ_RIM_CONTAINER, + .decoded_present = true, + .decoded = { + .req_rim_cont = { + .app_id = BSSGP_RAN_INF_APP_ID_NACC, + .seq_num = 1, + .pdu_ind = { + .ack_requested = 0, + .pdu_type_ext = 1, + }, + .prot_ver = 1, + .son_trans_app_id = NULL, + .son_trans_app_id_len = 0, + .u = { + .app_cont_nacc = { + .reprt_cell = ctx->cgi_ps, + }, + }, + }, + }, + }; + + return 0; +} + +/* At this point, we expect correct tgt cell info to be already in ctx->cgi_ps */ +static void st_wait_request_si_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state) +{ + struct nacc_fsm_ctx *ctx = (struct nacc_fsm_ctx *)fi->priv; + struct bssgp_ran_information_pdu pdu; + int rc; + + if (fill_rim_ran_info_req(ctx, &pdu) < 0) { + osmo_fsm_inst_term(fi, OSMO_FSM_TERM_ERROR, NULL); + return; + } + + rc = bssgp_tx_rim(&pdu, gprs_ns2_nse_nsei(ctx->ms->bts->nse)); + if (rc < 0) { + LOGPFSML(fi, LOGL_ERROR, "Failed transmitting RIM PDU: %d\n", rc); + osmo_fsm_inst_term(fi, OSMO_FSM_TERM_ERROR, NULL); + return; + } + + osmo_fsm_inst_dispatch(fi, NACC_EV_SI_INFO_RECEIVED, NULL); +} + + +static void st_wait_request_si(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + //struct nacc_fsm_ctx *ctx = (struct nacc_fsm_ctx *)fi->priv; + + switch (event) { + case NACC_EV_SI_INFO_RECEIVED: + /* TODO: In here we'll parse RIM response */ + + /* Tell the PCU scheduler we are ready to go, from here one we + * are polled/driven by the scheduler */ + nacc_fsm_state_chg(fi, NACC_ST_TX_NEIGHBOUR_DATA); + break; + default: + OSMO_ASSERT(0); + } +} + + +static void st_tx_neighbour_data_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state) +{ + /* At this point, we already received all required RIM messages or we + have them cached. We now wait for scheduler to ask us to construct + RLCMAC DL CTRL messages to move FSM states forward */ +} + +static void st_tx_neighbour_data(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct nacc_fsm_ctx *ctx = (struct nacc_fsm_ctx *)fi->priv; + struct nacc_ev_create_rlcmac_msg_ctx *data_ctx; + + switch (event) { + case NACC_EV_CREATE_RLCMAC_MSG: + data_ctx = (struct nacc_ev_create_rlcmac_msg_ctx *)data; + data_ctx->msg = create_packet_neighbour_cell_data(ctx, data_ctx->tbf); + /* TODO: logic if no more Neighbour cell data messages need to be send, then: */ + nacc_fsm_state_chg(fi, NACC_ST_TX_CELL_CHG_CONTINUE); + break; + default: + OSMO_ASSERT(0); + } +} + +static void st_cell_cgh_continue_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state) +{ + /* At this point, we already sent all Pkt Cell Neighbour Change rlcmac + blocks, and we only need to wait to be scheduled again to send PKT + CELL CHANGE NOTIFICATION */ +} + +static void st_cell_cgh_continue(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct nacc_fsm_ctx *ctx = (struct nacc_fsm_ctx *)fi->priv; + struct nacc_ev_create_rlcmac_msg_ctx *data_ctx; + + switch (event) { + case NACC_EV_CREATE_RLCMAC_MSG: + data_ctx = (struct nacc_ev_create_rlcmac_msg_ctx *)data; + data_ctx->msg = create_packet_cell_chg_continue(ctx, data_ctx->tbf); + /* TODO: logic if no more Neighbour cell data messages need to be send, then: */ + nacc_fsm_state_chg(fi, NACC_ST_DONE); + break; + default: + OSMO_ASSERT(0); + } +} + + +static void st_done_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state) +{ + osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL); +} + +static void nacc_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause) +{ + struct nacc_fsm_ctx *ctx = (struct nacc_fsm_ctx *)fi->priv; + /* afte rcleanup() finishes, FSM termination calls osmo_fsm_inst_free, + so we need to avoid double-freeing it during ctx talloc free + destructor */ + //talloc_reparent(ctx, ctx->ms, ctx->fi); + ctx->fi = NULL; + + /* remove references from owning MS and free entire ctx */ + ctx->ms->nacc = NULL; + talloc_free(ctx); +} + +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_WAIT_RESOLVE_RAC_CI) | + X(NACC_ST_WAIT_REQUEST_SI) | + X(NACC_ST_TX_NEIGHBOUR_DATA), + .name = "INITIAL", + //.onenter = st_initial_on_enter, + .action = st_initial, + }, + [NACC_ST_WAIT_RESOLVE_RAC_CI] = { + .in_event_mask = + X(NACC_EV_RX_RESOLVE_RAC_CI), + .out_state_mask = + X(NACC_ST_WAIT_REQUEST_SI) | + X(NACC_ST_TX_CELL_CHG_CONTINUE), + .name = "WAIT_RESOLVE_RAC_CI", + .onenter = st_wait_resolve_rac_ci_on_enter, + .action = st_wait_resolve_rac_ci, + }, + [NACC_ST_WAIT_REQUEST_SI] = { + .in_event_mask = + X(NACC_EV_CELL_CHG_NOTIFICATION) | + X(NACC_EV_SI_INFO_RECEIVED), + .out_state_mask = + X(NACC_ST_TX_NEIGHBOUR_DATA), + .name = "WAIT_REQUEST_SI", + .onenter = st_wait_request_si_on_enter, + .action = st_wait_request_si, + }, + [NACC_ST_TX_NEIGHBOUR_DATA] = { + .in_event_mask = + X(NACC_EV_CELL_CHG_NOTIFICATION) | + X(NACC_EV_SI_INFO_RECEIVED) | + X(NACC_EV_CREATE_RLCMAC_MSG), + .out_state_mask = + X(NACC_ST_TX_CELL_CHG_CONTINUE), + .name = "TX_NEIGHBOUR_DATA", + .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) | + X(NACC_EV_CREATE_RLCMAC_MSG), + .out_state_mask = + X(NACC_ST_DONE), + .name = "TX_CELL_CHG_CONTINUE", + .onenter = st_cell_cgh_continue_on_enter, + .action = st_cell_cgh_continue, + }, + [NACC_ST_DONE] = { + .in_event_mask = 0, + .out_state_mask = 0, + .name = "DONE", + .onenter = st_done_on_enter, + }, +}; + +static struct osmo_fsm nacc_fsm = { + .name = "NACC", + .states = nacc_fsm_states, + .num_states = ARRAY_SIZE(nacc_fsm_states), + .cleanup = nacc_fsm_cleanup, + .log_subsys = DNACC, + .event_names = nacc_fsm_event_names, +}; + +static __attribute__((constructor)) void nacc_fsm_init(void) +{ + OSMO_ASSERT(osmo_fsm_register(&nacc_fsm) == 0); +} + +void nacc_fsm_ctrl_reply_cb(struct ctrl_handle *ctrl, struct ctrl_cmd *cmd, void *data) +{ + struct nacc_fsm_ctx *ctx = (struct nacc_fsm_ctx *)data; + char *tmp = NULL, *tok, *saveptr; + + LOGPFSML(ctx->fi, LOGL_NOTICE, "Received CTRL message: type=%d %s: %s\n", + cmd->type, cmd->variable, osmo_escape_str(cmd->reply, -1)); + + if (cmd->type != CTRL_TYPE_GET_REPLY || !cmd->reply) { + osmo_fsm_inst_term(ctx->fi, OSMO_FSM_TERM_ERROR, NULL); + return; + } + + /* TODO: Potentially validate cmd->variable contains same params as we + sent, and that cmd->id matches the original set. We may want to keep + the original cmd around by setting cmd->defer=1 when sending it. */ + + tmp = talloc_strdup(cmd, cmd->reply); + if (!tmp) + goto free_ret; + + if (!(tok = strtok_r(tmp, "-", &saveptr))) + goto free_ret; + ctx->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); + + if (!(tok = strtok_r(NULL, "-", &saveptr))) + goto free_ret; + ctx->cgi_ps.rai.lac.lac = atoi(tok); + + if (!(tok = strtok_r(NULL, "-", &saveptr))) + goto free_ret; + ctx->cgi_ps.rai.rac = atoi(tok); + + if (!(tok = strtok_r(NULL, "\0", &saveptr))) + goto free_ret; + ctx->cgi_ps.cell_identity = atoi(tok); + + // TODO: cache the cgi_ps so we can avoid requesting again same resolution + + osmo_fsm_inst_dispatch(ctx->fi, NACC_EV_RX_RESOLVE_RAC_CI, NULL); + return; + +free_ret: + talloc_free(tmp); + osmo_fsm_inst_term(ctx->fi, OSMO_FSM_TERM_ERROR, NULL); + return; +} + +static int nacc_fsm_ctx_talloc_destructor(struct nacc_fsm_ctx *ctx) +{ + if (ctx->fi) { + osmo_fsm_inst_free(ctx->fi); + ctx->fi = NULL; + } + + if (ctx->neigh_ctrl_conn) { + if (ctx->neigh_ctrl_conn->write_queue.bfd.fd != -1) { + close(ctx->neigh_ctrl_conn->write_queue.bfd.fd); + ctx->neigh_ctrl_conn->write_queue.bfd.fd = -1; + } + } + + return 0; +} + +struct nacc_fsm_ctx *nacc_fsm_alloc(struct GprsMs* ms) +{ + struct gprs_rlcmac_bts *bts = ms->bts; + struct gprs_pcu *pcu = bts->pcu; + struct nacc_fsm_ctx *ctx = talloc_zero(ms, struct nacc_fsm_ctx); + char buf[64]; + int rc; + + talloc_set_destructor(ctx, nacc_fsm_ctx_talloc_destructor); + + ctx->ms = ms; + + snprintf(buf, sizeof(buf), "TLLI-0x%08x", ms_tlli(ms)); + ctx->fi = osmo_fsm_inst_alloc(&nacc_fsm, ctx, ctx, LOGL_INFO, buf); + 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; + + 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) { + LOGP(DNACC, LOGL_ERROR, "Can't connect to CTRL @ %s:%u\n", + pcu->vty.neigh_ctrl_addr, pcu->vty.neigh_ctrl_port); + goto free_ret; + } + + return ctx; +free_ret: + talloc_free(ctx); + return NULL; +} diff --git a/src/nacc_fsm.h b/src/nacc_fsm.h new file mode 100644 index 0000000..21c22ce --- /dev/null +++ b/src/nacc_fsm.h @@ -0,0 +1,41 @@ +#pragma once + +#include <osmocom/core/fsm.h> +#include <osmocom/gsm/gsm23003.h> + +struct GprsMs; +struct gprs_rlcmac_tbf; + +enum nacc_fsm_event { + NACC_EV_CELL_CHG_NOTIFICATION, /* data: Packet_Cell_Change_Notification_t* */ + NACC_EV_RX_RESOLVE_RAC_CI, /* data: ctrl msg resp */ + NACC_EV_SI_INFO_RECEIVED, + NACC_EV_CREATE_RLCMAC_MSG, +}; + +enum nacc_fsm_states { + NACC_ST_INITIAL, + NACC_ST_WAIT_RESOLVE_RAC_CI, + NACC_ST_WAIT_REQUEST_SI, + NACC_ST_TX_NEIGHBOUR_DATA, + NACC_ST_TX_CELL_CHG_CONTINUE, + NACC_ST_DONE, +}; + +struct nacc_fsm_ctx { + struct osmo_fsm_inst *fi; + struct GprsMs* ms; /* back pointer */ + struct ctrl_handle *neigh_ctrl; + struct ctrl_connection *neigh_ctrl_conn; + uint16_t req_arfcn; + uint8_t req_bsic; + struct osmo_cell_global_id_ps cgi_ps; /* target SGSN, resolved from req_{arfcn+bsic} */ +}; + +/* passed as data in NACC_EV_CREATE_RLCMAC_MSG */ +struct nacc_ev_create_rlcmac_msg_ctx { + struct gprs_rlcmac_tbf *tbf; /* target tbf to create messages for */ + struct msgb *msg; /* to be filled by FSM duringe event processing */ +}; + +struct nacc_fsm_ctx *nacc_fsm_alloc(struct GprsMs* ms); diff --git a/src/pcu_vty.c b/src/pcu_vty.c index 288f241..b7021c8 100644 --- a/src/pcu_vty.c +++ b/src/pcu_vty.c @@ -14,6 +14,7 @@ #include <osmocom/vty/misc.h> #include <osmocom/core/linuxlist.h> #include <osmocom/core/rate_ctr.h> +#include <osmocom/ctrl/ports.h> #include <osmocom/pcu/pcuif_proto.h> #include <osmocom/gprs/gprs_ns2.h> #include "pcu_vty.h" @@ -1018,6 +1019,22 @@ return CMD_SUCCESS; } +DEFUN(cfg_neighbor_resolution, cfg_neighbor_resolution_cmd, + "neighbor resolution " VTY_IPV46_CMD " [<0-65535>]", + "Manage local and remote-BSS neighbor cells\n" + "Connect to Neighbor Resolution Service (CTRL interface) to given ip and port\n" + "IPv4 address to connect to\n" "IPv6 address to connect to\n" + "Port to connect to (default 4248)\n") +{ + 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]); + else + the_pcu->vty.neigh_ctrl_port = OSMO_CTRL_PORT_BSC_NEIGH; + return CMD_SUCCESS; +} + + DEFUN(show_bts_timer, show_bts_timer_cmd, "show bts-timer " OSMO_TDEF_VTY_ARG_T_OPTIONAL, SHOW_STR "Show BTS controlled timers\n" @@ -1220,6 +1237,7 @@ install_element(PCU_NODE, &cfg_pcu_no_gsmtap_categ_cmd); install_element(PCU_NODE, &cfg_pcu_sock_cmd); install_element(PCU_NODE, &cfg_pcu_gb_dialect_cmd); + install_element(PCU_NODE, &cfg_neighbor_resolution_cmd); install_element(PCU_NODE, &cfg_pcu_timer_cmd); install_element_ve(&show_bts_stats_cmd); diff --git a/src/pdch.cpp b/src/pdch.cpp index 5a329f3..2028ba2 100644 --- a/src/pdch.cpp +++ b/src/pdch.cpp @@ -685,6 +685,33 @@ 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; + + bts_do_rate_ctr_inc(bts(), CTR_PKT_CELL_CHG_NOTIFICATION); + + 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(ms, meas); + ms_nacc_start(ms, 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) @@ -734,6 +761,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(bts(), CTR_DECODE_ERRORS); LOGP(DRLCMAC, LOGL_NOTICE, diff --git a/src/pdch.h b/src/pdch.h index 8871986..d596531 100644 --- a/src/pdch.h +++ b/src/pdch.h @@ -139,6 +139,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); diff --git a/src/tbf.cpp b/src/tbf.cpp index 37af21f..5b2fe3d 100644 --- a/src/tbf.cpp +++ b/src/tbf.cpp @@ -1197,3 +1197,8 @@ { return tbf->is_tfi_assigned(); } + +uint8_t tbf_tfi(const struct gprs_rlcmac_tbf *tbf) +{ + return tbf->tfi(); +} diff --git a/src/tbf.h b/src/tbf.h index d616076..815d254 100644 --- a/src/tbf.h +++ b/src/tbf.h @@ -204,6 +204,7 @@ uint8_t tbf_dl_slots(const struct gprs_rlcmac_tbf *tbf); uint8_t tbf_ul_slots(const struct gprs_rlcmac_tbf *tbf); bool tbf_is_tfi_assigned(const struct gprs_rlcmac_tbf *tbf); +uint8_t tbf_tfi(const struct gprs_rlcmac_tbf *tbf); int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf); #ifdef __cplusplus } diff --git a/tests/Makefile.am b/tests/Makefile.am index c599636..a7771b9 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,4 +1,4 @@ -AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGB_CFLAGS) $(LIBOSMOGSM_CFLAGS) -I$(top_srcdir)/src/ -I$(top_srcdir)/include/ +AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOGB_CFLAGS) $(LIBOSMOGSM_CFLAGS) -I$(top_srcdir)/src/ -I$(top_srcdir)/include/ AM_LDFLAGS = -lrt -no-install check_PROGRAMS = rlcmac/RLCMACTest alloc/AllocTest alloc/MslotTest tbf/TbfTest types/TypesTest ms/MsTest llist/LListTest llc/LlcTest codel/codel_test edge/EdgeTest bitcomp/BitcompTest fn/FnTest app_info/AppInfoTest @@ -15,6 +15,7 @@ $(top_builddir)/src/libgprs.la \ $(LIBOSMOGB_LIBS) \ $(LIBOSMOGSM_LIBS) \ + $(LIBOSMOCTRL_LIBS) \ $(LIBOSMOCORE_LIBS) \ $(COMMON_LA) @@ -23,6 +24,7 @@ $(top_builddir)/src/libgprs.la \ $(LIBOSMOGB_LIBS) \ $(LIBOSMOGSM_LIBS) \ + $(LIBOSMOCTRL_LIBS) \ $(LIBOSMOCORE_LIBS) \ $(COMMON_LA) @@ -31,6 +33,7 @@ $(top_builddir)/src/libgprs.la \ $(LIBOSMOGB_LIBS) \ $(LIBOSMOGSM_LIBS) \ + $(LIBOSMOCTRL_LIBS) \ $(LIBOSMOCORE_LIBS) \ $(COMMON_LA) tbf_TbfTest_LDFLAGS = -Wl,--wrap=pcu_sock_send @@ -38,6 +41,7 @@ bitcomp_BitcompTest_SOURCES = bitcomp/BitcompTest.cpp ../src/egprs_rlc_compression.cpp bitcomp_BitcompTest_LDADD = \ $(top_builddir)/src/libgprs.la \ + $(LIBOSMOCTRL_LIBS) \ $(LIBOSMOCORE_LIBS) \ $(COMMON_LA) @@ -46,6 +50,7 @@ $(top_builddir)/src/libgprs.la \ $(LIBOSMOGB_LIBS) \ $(LIBOSMOGSM_LIBS) \ + $(LIBOSMOCTRL_LIBS) \ $(LIBOSMOCORE_LIBS) \ $(COMMON_LA) @@ -56,6 +61,7 @@ $(top_builddir)/src/libgprs.la \ $(LIBOSMOGB_LIBS) \ $(LIBOSMOGSM_LIBS) \ + $(LIBOSMOCTRL_LIBS) \ $(LIBOSMOCORE_LIBS) \ $(COMMON_LA) @@ -64,6 +70,7 @@ $(top_builddir)/src/libgprs.la \ $(LIBOSMOGB_LIBS) \ $(LIBOSMOGSM_LIBS) \ + $(LIBOSMOCTRL_LIBS) \ $(LIBOSMOCORE_LIBS) \ $(COMMON_LA) @@ -72,6 +79,7 @@ $(top_builddir)/src/libgprs.la \ $(LIBOSMOGB_LIBS) \ $(LIBOSMOGSM_LIBS) \ + $(LIBOSMOCTRL_LIBS) \ $(LIBOSMOCORE_LIBS) \ $(COMMON_LA) @@ -83,6 +91,7 @@ $(top_builddir)/src/libgprs.la \ $(LIBOSMOGB_LIBS) \ $(LIBOSMOGSM_LIBS) \ + $(LIBOSMOCTRL_LIBS) \ $(LIBOSMOCORE_LIBS) \ $(COMMON_LA) @@ -97,6 +106,7 @@ codel_codel_test_SOURCES = codel/codel_test.c codel_codel_test_LDADD = \ $(top_builddir)/src/libgprs.la \ + $(LIBOSMOCTRL_LIBS) \ $(LIBOSMOCORE_LIBS) \ $(COMMON_LA) @@ -105,6 +115,7 @@ $(top_builddir)/src/libgprs.la \ $(LIBOSMOGB_LIBS) \ $(LIBOSMOGSM_LIBS) \ + $(LIBOSMOCTRL_LIBS) \ $(LIBOSMOCORE_LIBS) \ $(COMMON_LA) @@ -113,6 +124,7 @@ $(top_builddir)/src/libgprs.la \ $(LIBOSMOGB_LIBS) \ $(LIBOSMOGSM_LIBS) \ + $(LIBOSMOCTRL_LIBS) \ $(LIBOSMOCORE_LIBS) \ $(COMMON_LA) -- To view, visit https://gerrit.osmocom.org/c/osmo-pcu/+/22338 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-pcu Gerrit-Branch: master Gerrit-Change-Id: Ife6e4a086d58d49676d12b6984f63079ec472e79 Gerrit-Change-Number: 22338 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/20210120/8618b4d2/attachment.htm>