Change in osmo-pcu[master]: WIP: Implement NACC

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

pespin gerrit-no-reply at lists.osmocom.org
Wed Dec 16 13:27:31 UTC 2020


pespin 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>


More information about the gerrit-log mailing list