laforge submitted this change.

View Change


Approvals: Jenkins Builder: Verified pespin: Looks good to me, but someone else must approve laforge: Looks good to me, approved fixeria: Looks good to me, but someone else must approve
RAB activation/modification/release statistics

Add rate_ctr based statistics for RAB activation, deactivation and
failures. This requires us to parse RANAP in both uplink and downlink
and to iterate deep into the setup/modify/release/failure lists.

Given the way how the protocol works, the only way to distinguish an
activation from a modification is because sender and recipient know
whether a given RAB is already active at the time of the message. So we
also need to track the activation state of each RAB.

Depends: osmo-iuh.git Change-Id I328819c650fc6cefe735093a846277b4f03e6b29
Change-Id: I198fa37699e22380909764de6a0522ac79aa1d39
---
M include/osmocom/hnbgw/Makefile.am
M include/osmocom/hnbgw/context_map.h
M include/osmocom/hnbgw/hnbgw.h
A include/osmocom/hnbgw/kpi.h
M src/osmo-hnbgw/Makefile.am
M src/osmo-hnbgw/context_map_rua.c
M src/osmo-hnbgw/context_map_sccp.c
M src/osmo-hnbgw/hnbgw.c
A src/osmo-hnbgw/kpi_ranap.c
9 files changed, 504 insertions(+), 0 deletions(-)

diff --git a/include/osmocom/hnbgw/Makefile.am b/include/osmocom/hnbgw/Makefile.am
index b6824b3..6338e4e 100644
--- a/include/osmocom/hnbgw/Makefile.am
+++ b/include/osmocom/hnbgw/Makefile.am
@@ -2,6 +2,7 @@
vty.h \
context_map.h hnbgw.h hnbgw_cn.h \
hnbgw_hnbap.h hnbgw_rua.h hnbgw_ranap.h \
+ kpi.h \
ranap_rab_ass.h mgw_fsm.h tdefs.h \
hnbgw_pfcp.h \
ps_rab_ass_fsm.h \
diff --git a/include/osmocom/hnbgw/context_map.h b/include/osmocom/hnbgw/context_map.h
index d401635..1e23777 100644
--- a/include/osmocom/hnbgw/context_map.h
+++ b/include/osmocom/hnbgw/context_map.h
@@ -101,6 +101,14 @@
bool from_other_plmn;
};

+/* used in hnbgw_context_map.rab_state[] */
+enum rab_state {
+ RAB_STATE_INACTIVE,
+ RAB_STATE_ACT_REQ,
+ RAB_STATE_ACTIVE,
+ RAB_STATE_REL_REQ,
+};
+
struct hnbgw_context_map {
/* entry in the per-CN list of mappings */
struct llist_head hnbgw_cnlink_entry;
@@ -160,6 +168,9 @@
* communication for one particular RAB ID. */
struct llist_head ps_rabs;

+ /* RAB state tracking. As RAB-ID is an 8-bit integer, we need 256 elements in the array */
+ uint8_t rab_state[256];
+
/* Flag to prevent calling context_map_free() from cleanup code paths triggered by context_map_free() itself. */
bool deallocating;
};
diff --git a/include/osmocom/hnbgw/hnbgw.h b/include/osmocom/hnbgw/hnbgw.h
index bd8a853..b3ba3b2 100644
--- a/include/osmocom/hnbgw/hnbgw.h
+++ b/include/osmocom/hnbgw/hnbgw.h
@@ -80,6 +80,36 @@
HNB_CTR_RANAP_PS_RESET_REQ_UL,
HNB_CTR_RANAP_CS_RESET_REQ_UL,

+ HNB_CTR_RANAP_PS_RAB_ACT_REQ,
+ HNB_CTR_RANAP_CS_RAB_ACT_REQ,
+
+ HNB_CTR_RANAP_PS_RAB_ACT_CNF,
+ HNB_CTR_RANAP_CS_RAB_ACT_CNF,
+
+ HNB_CTR_RANAP_PS_RAB_ACT_FAIL,
+ HNB_CTR_RANAP_CS_RAB_ACT_FAIL,
+
+ HNB_CTR_RANAP_PS_RAB_MOD_REQ,
+ HNB_CTR_RANAP_CS_RAB_MOD_REQ,
+
+ HNB_CTR_RANAP_PS_RAB_MOD_CNF,
+ HNB_CTR_RANAP_CS_RAB_MOD_CNF,
+
+ HNB_CTR_RANAP_PS_RAB_MOD_FAIL,
+ HNB_CTR_RANAP_CS_RAB_MOD_FAIL,
+
+ HNB_CTR_RANAP_PS_RAB_REL_REQ,
+ HNB_CTR_RANAP_CS_RAB_REL_REQ,
+
+ HNB_CTR_RANAP_PS_RAB_REL_CNF,
+ HNB_CTR_RANAP_CS_RAB_REL_CNF,
+
+ HNB_CTR_RANAP_PS_RAB_REL_FAIL,
+ HNB_CTR_RANAP_CS_RAB_REL_FAIL,
+
+ HNB_CTR_RANAP_PS_RAB_REL_IMPLICIT,
+ HNB_CTR_RANAP_CS_RAB_REL_IMPLICIT,
+
HNB_CTR_RUA_ERR_IND,

HNB_CTR_RUA_PS_CONNECT_UL,
@@ -301,6 +331,7 @@

#define HNBP_CTR(hnbp, x) rate_ctr_group_get_ctr((hnbp)->ctrs, x)
#define HNBP_CTR_INC(hnbp, x) rate_ctr_inc(HNBP_CTR(hnbp, x))
+#define HNBP_CTR_ADD(hnbp, x, y) rate_ctr_add2((hnbp)->ctrs, x, y)

#define HNBP_STAT(hbp, x) osmo_stat_item_group_get_item((hnbp)->statg, x)
#define HNBP_STAT_SET(hnbp, x, val) osmo_stat_item_set(HNBP_STAT(hnbp, x), val)
diff --git a/include/osmocom/hnbgw/kpi.h b/include/osmocom/hnbgw/kpi.h
new file mode 100644
index 0000000..63f3477
--- /dev/null
+++ b/include/osmocom/hnbgw/kpi.h
@@ -0,0 +1,8 @@
+#pragma once
+
+#include <osmocom/ranap/ranap_ies_defs.h>
+
+#include <osmocom/hnbgw/hnbgw.h>
+
+void kpi_ranap_process_ul(struct hnbgw_context_map *map, ranap_message *ranap);
+void kpi_ranap_process_dl(struct hnbgw_context_map *map, ranap_message *ranap);
diff --git a/src/osmo-hnbgw/Makefile.am b/src/osmo-hnbgw/Makefile.am
index 910fdda..0727f30 100644
--- a/src/osmo-hnbgw/Makefile.am
+++ b/src/osmo-hnbgw/Makefile.am
@@ -44,6 +44,7 @@
cnlink.c \
ranap_rab_ass.c \
mgw_fsm.c \
+ kpi_ranap.c \
tdefs.c \
$(NULL)

diff --git a/src/osmo-hnbgw/context_map_rua.c b/src/osmo-hnbgw/context_map_rua.c
index 2263792..a943a64 100644
--- a/src/osmo-hnbgw/context_map_rua.c
+++ b/src/osmo-hnbgw/context_map_rua.c
@@ -36,6 +36,7 @@
#include <osmocom/hnbgw/hnbgw_rua.h>
#include <osmocom/hnbgw/mgw_fsm.h>
#include <osmocom/hnbgw/ps_rab_ass_fsm.h>
+#include <osmocom/hnbgw/kpi.h>

enum map_rua_fsm_state {
MAP_RUA_ST_INIT,
@@ -168,6 +169,8 @@
LOGPFSML(fi, LOGL_DEBUG, "rx from RUA: RANAP %s\n",
get_value_string(ranap_procedure_code_vals, message->procedureCode));

+ kpi_ranap_process_ul(map, message);
+
switch (message->procedureCode) {
case RANAP_ProcedureCode_id_RAB_Assignment:
/* mgw_fsm_handle_rab_ass_resp() takes ownership of prim->oph and (ranap) message */
@@ -182,6 +185,8 @@
LOGPFSML(fi, LOGL_DEBUG, "rx from RUA: RANAP %s\n",
get_value_string(ranap_procedure_code_vals, message->procedureCode));

+ kpi_ranap_process_ul(map, message);
+
switch (message->procedureCode) {
case RANAP_ProcedureCode_id_RAB_Assignment:
/* ps_rab_ass_fsm takes ownership of prim->oph and RANAP message */
diff --git a/src/osmo-hnbgw/context_map_sccp.c b/src/osmo-hnbgw/context_map_sccp.c
index 5eb97e2..e7e27b6 100644
--- a/src/osmo-hnbgw/context_map_sccp.c
+++ b/src/osmo-hnbgw/context_map_sccp.c
@@ -38,6 +38,7 @@
#include <osmocom/hnbgw/tdefs.h>
#include <osmocom/hnbgw/mgw_fsm.h>
#include <osmocom/hnbgw/ps_rab_ass_fsm.h>
+#include <osmocom/hnbgw/kpi.h>

enum map_sccp_fsm_state {
MAP_SCCP_ST_INIT,
@@ -215,6 +216,8 @@
LOGPFSML(fi, LOGL_DEBUG, "rx from SCCP: RANAP %s\n",
get_value_string(ranap_procedure_code_vals, message->procedureCode));

+ kpi_ranap_process_dl(map, message);
+
switch (message->procedureCode) {
case RANAP_ProcedureCode_id_RAB_Assignment:
/* mgw_fsm_alloc_and_handle_rab_ass_req() takes ownership of (ranap) message */
@@ -239,6 +242,8 @@
LOGPFSML(fi, LOGL_DEBUG, "rx from SCCP: RANAP %s\n",
get_value_string(ranap_procedure_code_vals, message->procedureCode));

+ kpi_ranap_process_dl(map, message);
+
switch (message->procedureCode) {

case RANAP_ProcedureCode_id_RAB_Assignment:
diff --git a/src/osmo-hnbgw/hnbgw.c b/src/osmo-hnbgw/hnbgw.c
index e1bac5f..fff900a 100644
--- a/src/osmo-hnbgw/hnbgw.c
+++ b/src/osmo-hnbgw/hnbgw.c
@@ -364,6 +364,59 @@
[HNB_CTR_RANAP_CS_RESET_REQ_UL] = {
"ranap:cs:reset_req:ul", "Received RESET Requests in Uplink (CS Domain)" },

+
+ [HNB_CTR_RANAP_PS_RAB_ACT_REQ] = {
+ "ranap:ps:rab_act:req", "PS RAB Activations requested" },
+ [HNB_CTR_RANAP_CS_RAB_ACT_REQ] = {
+ "ranap:cs:rab_act:req", "CS RAB Activations requested" },
+
+ [HNB_CTR_RANAP_PS_RAB_ACT_CNF] = {
+ "ranap:ps:rab_act:cnf", "PS RAB Activations confirmed" },
+ [HNB_CTR_RANAP_CS_RAB_ACT_CNF] = {
+ "ranap:cs:rab_act:cnf", "CS RAB Activations confirmed" },
+
+ [HNB_CTR_RANAP_PS_RAB_ACT_FAIL] = {
+ "ranap:ps:rab_act:fail", "PS RAB Activations failed" },
+ [HNB_CTR_RANAP_CS_RAB_ACT_FAIL] = {
+ "ranap:cs:rab_act:fail", "CS RAB Activations failed" },
+
+
+ [HNB_CTR_RANAP_PS_RAB_MOD_REQ] = {
+ "ranap:ps:rab_mod:req", "PS RAB Modifications requested" },
+ [HNB_CTR_RANAP_CS_RAB_MOD_REQ] = {
+ "ranap:cs:rab_mod:req", "CS RAB Modifications requested" },
+
+ [HNB_CTR_RANAP_PS_RAB_MOD_CNF] = {
+ "ranap:ps:rab_mod:cnf", "PS RAB Modifications confirmed" },
+ [HNB_CTR_RANAP_CS_RAB_MOD_CNF] = {
+ "ranap:cs:rab_mod:cnf", "CS RAB Modifications confirmed" },
+
+ [HNB_CTR_RANAP_PS_RAB_MOD_FAIL] = {
+ "ranap:ps:rab_mod:fail", "PS RAB Modifications failed" },
+ [HNB_CTR_RANAP_CS_RAB_MOD_FAIL] = {
+ "ranap:cs:rab_mod:fail", "CS RAB Modifications failed" },
+
+
+ [HNB_CTR_RANAP_PS_RAB_REL_REQ] = {
+ "ranap:ps:rab_rel:req", "PS RAB Release requested" },
+ [HNB_CTR_RANAP_CS_RAB_REL_REQ] = {
+ "ranap:cs:rab_rel:req", "CS RAB Release requested" },
+
+ [HNB_CTR_RANAP_PS_RAB_REL_CNF] = {
+ "ranap:ps:rab_rel:cnf", "PS RAB Release confirmed" },
+ [HNB_CTR_RANAP_CS_RAB_REL_CNF] = {
+ "ranap:cs:rab_rel:cnf", "CS RAB Release confirmed" },
+
+ [HNB_CTR_RANAP_PS_RAB_REL_FAIL] = {
+ "ranap:ps:rab_rel:fail", "PS RAB Release failed" },
+ [HNB_CTR_RANAP_CS_RAB_REL_FAIL] = {
+ "ranap:cs:rab_rel:fail", "CS RAB Release failed" },
+
+ [HNB_CTR_RANAP_PS_RAB_REL_IMPLICIT] = {
+ "ranap:ps:rab_rel:implicit", "PS RAB Release implicit (during Iu Release)" },
+ [HNB_CTR_RANAP_CS_RAB_REL_IMPLICIT] = {
+ "ranap:cs:rab_rel:implicit", "CS RAB Release implicit (during Iu Release)" },
+
[HNB_CTR_RUA_ERR_IND] = {
"rua:error_ind", "Received RUA Error Indications" },

diff --git a/src/osmo-hnbgw/kpi_ranap.c b/src/osmo-hnbgw/kpi_ranap.c
new file mode 100644
index 0000000..76f6e22
--- /dev/null
+++ b/src/osmo-hnbgw/kpi_ranap.c
@@ -0,0 +1,370 @@
+/* KPI (statistics, counters) at RANAP level */
+/* (C) 2024 by Harald Welte <laforge@osmocom.org>
+ * All Rights Reserved
+ *
+ * SPDX-License-Identifier: AGPL-3.0+
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <osmocom/core/utils.h>
+
+#include <osmocom/ranap/ranap_common_ran.h>
+
+#include <osmocom/hnbgw/hnbgw_cn.h>
+#include <osmocom/hnbgw/context_map.h>
+#include <osmocom/hnbgw/kpi.h>
+
+
+/***********************************************************************
+ * DOWNLINK messages
+ ***********************************************************************/
+
+static void kpi_ranap_process_dl_iu_rel_cmd(struct hnbgw_context_map *map, const ranap_message *ranap)
+{
+ struct hnb_persistent *hnbp = map->hnb_ctx->persistent;
+
+ OSMO_ASSERT(ranap->procedureCode == RANAP_ProcedureCode_id_Iu_Release);
+
+ /* When Iu is released, all RABs are released implicitly */
+ for (unsigned int i = 0; i < ARRAY_SIZE(map->rab_state); i++) {
+ switch (map->rab_state[i]) {
+ case RAB_STATE_ACTIVE:
+ HNBP_CTR_INC(hnbp, map->is_ps ? HNB_CTR_RANAP_PS_RAB_REL_IMPLICIT : HNB_CTR_RANAP_CS_RAB_REL_IMPLICIT);
+ break;
+ }
+ }
+ /* clear all RAB state */
+ memset(map->rab_state, 0, sizeof(map->rab_state));
+}
+
+static void kpi_ranap_process_dl_rab_ass_req(struct hnbgw_context_map *map, ranap_message *ranap)
+{
+ struct hnb_persistent *hnbp = map->hnb_ctx->persistent;
+ RANAP_RAB_AssignmentRequestIEs_t *ies;
+ int rc;
+
+ OSMO_ASSERT(ranap->procedureCode == RANAP_ProcedureCode_id_RAB_Assignment);
+
+ ies = &ranap->msg.raB_AssignmentRequestIEs;
+
+ if (ies->presenceMask & RAB_ASSIGNMENTREQUESTIES_RANAP_RAB_SETUPORMODIFYLIST_PRESENT) {
+ RANAP_RAB_SetupOrModifyList_t *som_list = &ies->raB_SetupOrModifyList;
+ for (unsigned int i = 0; i < som_list->list.count; i++) {
+ RANAP_ProtocolIE_ContainerPair_t *container_pair = som_list->list.array[i];
+ RANAP_ProtocolIE_FieldPair_t *field_pair = container_pair->list.array[0];
+ RANAP_RAB_SetupOrModifyItemFirst_t _rab_setup_or_modify_item_first = {};
+ RANAP_RAB_SetupOrModifyItemFirst_t *rab_setup_or_modify_item_first = &_rab_setup_or_modify_item_first;
+ uint8_t rab_id;
+
+ if (!field_pair)
+ continue;
+
+ if (field_pair->id != RANAP_ProtocolIE_ID_id_RAB_SetupOrModifyItem)
+ continue;
+
+ rc = ranap_decode_rab_setupormodifyitemfirst(rab_setup_or_modify_item_first, &field_pair->firstValue);
+ if (rc < 0)
+ continue;
+
+ /* RAB-ID is an 8-bit bit-string, so it's the first byte */
+ rab_id = rab_setup_or_modify_item_first->rAB_ID.buf[0];
+
+ /* the only way to distinguish a "setup" from a "modify" is to know which RABs are
+ * already established. If it's already established, it is a modification; if it's
+ * new, it is a setup */
+ switch (map->rab_state[rab_id]) {
+ case RAB_STATE_ACTIVE:
+ HNBP_CTR_INC(hnbp, map->is_ps ? HNB_CTR_RANAP_PS_RAB_MOD_REQ : HNB_CTR_RANAP_CS_RAB_MOD_REQ);
+ break;
+ case RAB_STATE_INACTIVE:
+ HNBP_CTR_INC(hnbp, map->is_ps ? HNB_CTR_RANAP_PS_RAB_ACT_REQ : HNB_CTR_RANAP_CS_RAB_ACT_REQ);
+ map->rab_state[rab_id] = RAB_STATE_ACT_REQ;
+ break;
+ default:
+ LOG_MAP(map, DRANAP, LOGL_NOTICE,
+ "Unexpected RAB Activation/Modification Req for RAB in state %u\n", map->rab_state[rab_id]);
+ break;
+ }
+
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyItemFirst, rab_setup_or_modify_item_first);
+ }
+ }
+
+ if (ies->presenceMask & RAB_ASSIGNMENTREQUESTIES_RANAP_RAB_RELEASELIST_PRESENT) {
+ RANAP_RAB_ReleaseList_t *r_list = &ies->raB_ReleaseList;
+ /* increment number of released RABs, we don't need to do that individually during iteration */
+ HNBP_CTR_ADD(hnbp, map->is_ps ? HNB_CTR_RANAP_PS_RAB_REL_REQ : HNB_CTR_RANAP_CS_RAB_REL_REQ,
+ r_list->raB_ReleaseList_ies.list.count);
+
+ for (unsigned int i = 0; i < r_list->raB_ReleaseList_ies.list.count; i++) {
+ RANAP_IE_t *release_list_ie = r_list->raB_ReleaseList_ies.list.array[i];
+ RANAP_RAB_ReleaseItemIEs_t _rab_rel_item_ies = {};
+ RANAP_RAB_ReleaseItemIEs_t *rab_rel_item_ies = &_rab_rel_item_ies;
+ RANAP_RAB_ReleaseItem_t *rab_rel_item;
+ uint8_t rab_id;
+
+ if (!release_list_ie)
+ continue;
+
+ if (release_list_ie->id != RANAP_ProtocolIE_ID_id_RAB_ReleaseItem)
+ continue;
+
+ rc = ranap_decode_rab_releaseitemies_fromlist(rab_rel_item_ies, &release_list_ie->value);
+ if (rc < 0)
+ continue;
+
+ rab_rel_item = &rab_rel_item_ies->raB_ReleaseItem;
+ /* RAB-ID is an 8-bit bit-string, so it's the first byte */
+ rab_id = rab_rel_item->rAB_ID.buf[0];
+
+ switch (map->rab_state[rab_id]) {
+ case RAB_STATE_ACTIVE:
+ break;
+ default:
+ LOG_MAP(map, DRANAP, LOGL_NOTICE,
+ "Unexpected RAB Release Req in state %u\n", map->rab_state[rab_id]);
+ break;
+ }
+ /* mark that RAB as release requested */
+ map->rab_state[rab_id] = RAB_STATE_REL_REQ;
+
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_ReleaseItem, rab_rel_item_ies);
+ }
+ }
+}
+
+void kpi_ranap_process_dl(struct hnbgw_context_map *map, ranap_message *ranap)
+{
+ switch (ranap->procedureCode) {
+ case RANAP_ProcedureCode_id_RAB_Assignment: /* RAB ASSIGNMENT REQ (8.2) */
+ kpi_ranap_process_dl_rab_ass_req(map, ranap);
+ break;
+ case RANAP_ProcedureCode_id_Iu_Release:
+ kpi_ranap_process_dl_iu_rel_cmd(map, ranap); /* IU RELEASE CMD (8.5) */
+ break;
+ default:
+ break;
+ }
+}
+
+/***********************************************************************
+ * UPLINK messages
+ ***********************************************************************/
+
+static void kpi_ranap_process_ul_rab_ass_resp(struct hnbgw_context_map *map, ranap_message *ranap)
+{
+ struct hnb_persistent *hnbp = map->hnb_ctx->persistent;
+ RANAP_RAB_AssignmentResponseIEs_t *ies;
+ int rc;
+
+ OSMO_ASSERT(ranap->procedureCode == RANAP_ProcedureCode_id_RAB_Assignment);
+
+ ies = &ranap->msg.raB_AssignmentResponseIEs;
+
+ if (ies->presenceMask & RAB_ASSIGNMENTRESPONSEIES_RANAP_RAB_SETUPORMODIFIEDLIST_PRESENT) {
+ RANAP_RAB_SetupOrModifiedList_t *som_list = &ies->raB_SetupOrModifiedList;
+ for (unsigned int i = 0; i < som_list->raB_SetupOrModifiedList_ies.list.count; i++) {
+ RANAP_IE_t *som_list_ie = som_list->raB_SetupOrModifiedList_ies.list.array[i];
+ RANAP_RAB_SetupOrModifiedItemIEs_t _rab_som_item_ies = {};
+ RANAP_RAB_SetupOrModifiedItemIEs_t *rab_som_item_ies = &_rab_som_item_ies;
+ RANAP_RAB_SetupOrModifiedItem_t *rab_som_item;
+ uint8_t rab_id;
+
+ if (!som_list_ie)
+ continue;
+
+ if (som_list_ie->id != RANAP_ProtocolIE_ID_id_RAB_SetupOrModifiedItem)
+ continue;
+
+ rc = ranap_decode_rab_setupormodifieditemies_fromlist(rab_som_item_ies, &som_list_ie->value);
+ if (rc < 0)
+ continue;
+
+ rab_som_item = &rab_som_item_ies->raB_SetupOrModifiedItem;
+ /* RAB-ID is an 8-bit bit-string, so it's the first byte */
+ rab_id = rab_som_item->rAB_ID.buf[0];
+
+ /* differentiate modify / activate */
+ switch (map->rab_state[rab_id]) {
+ case RAB_STATE_ACT_REQ:
+ HNBP_CTR_INC(hnbp, map->is_ps ? HNB_CTR_RANAP_PS_RAB_ACT_CNF : HNB_CTR_RANAP_CS_RAB_ACT_CNF);
+ map->rab_state[rab_id] = RAB_STATE_ACTIVE;
+ break;
+ case RAB_STATE_ACTIVE:
+ HNBP_CTR_INC(hnbp, map->is_ps ? HNB_CTR_RANAP_PS_RAB_MOD_CNF : HNB_CTR_RANAP_CS_RAB_MOD_CNF);
+ break;
+ default:
+ LOG_MAP(map, DRANAP, LOGL_NOTICE,
+ "Unexpected RAB Activation/Modification Conf for RAB in state %u\n", map->rab_state[rab_id]);
+ break;
+ }
+
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifiedItem, rab_som_item_ies);
+ }
+ }
+
+ if (ies->presenceMask & RAB_ASSIGNMENTRESPONSEIES_RANAP_RAB_RELEASEDLIST_PRESENT) {
+ RANAP_RAB_ReleasedList_t *r_list = &ies->raB_ReleasedList;
+ /* increment number of released RABs, we don't need to do that individually during iteration */
+ HNBP_CTR_ADD(hnbp, map->is_ps ? HNB_CTR_RANAP_PS_RAB_REL_CNF : HNB_CTR_RANAP_CS_RAB_REL_CNF,
+ r_list->raB_ReleasedList_ies.list.count);
+ for (unsigned int i = 0; i < r_list->raB_ReleasedList_ies.list.count; i++) {
+ RANAP_IE_t *released_list_ie = r_list->raB_ReleasedList_ies.list.array[i];
+ RANAP_RAB_ReleasedItemIEs_t _rab_rel_item_ies = {};
+ RANAP_RAB_ReleasedItemIEs_t *rab_rel_item_ies = &_rab_rel_item_ies;
+ RANAP_RAB_ReleasedItem_t *rab_rel_item;
+ uint8_t rab_id;
+
+ if (!released_list_ie)
+ continue;
+
+ if (released_list_ie->id != RANAP_ProtocolIE_ID_id_RAB_ReleasedItem)
+ continue;
+
+ rc = ranap_decode_rab_releaseditemies_fromlist(rab_rel_item_ies, &released_list_ie->value);
+ if (rc < 0)
+ continue;
+
+ rab_rel_item = &rab_rel_item_ies->raB_ReleasedItem;
+ /* RAB-ID is an 8-bit bit-string, so it's the first byte */
+ rab_id = rab_rel_item->rAB_ID.buf[0];
+
+ switch (map->rab_state[rab_id]) {
+ case RAB_STATE_REL_REQ:
+ break;
+ default:
+ LOG_MAP(map, DRANAP, LOGL_NOTICE,
+ "Unexpected RAB Release Conf for RAB in state %u\n", map->rab_state[rab_id]);
+ break;
+ }
+ /* mark that RAB as released */
+ map->rab_state[rab_id] = RAB_STATE_INACTIVE;
+
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_ReleasedItem, rab_rel_item_ies);
+ }
+ }
+
+ if (ies->presenceMask & RAB_ASSIGNMENTRESPONSEIES_RANAP_RAB_QUEUEDLIST_PRESENT)
+ LOG_MAP(map, DRANAP, LOGL_NOTICE, "RAB Activation has been queued; we don't support KPIs for this\n");
+
+ if (ies->presenceMask & RAB_ASSIGNMENTRESPONSEIES_RANAP_RAB_FAILEDLIST_PRESENT) {
+ RANAP_RAB_FailedList_t *f_list = &ies->raB_FailedList;
+ for (unsigned int i = 0; i < f_list->raB_FailedList_ies.list.count; i++) {
+ RANAP_IE_t *failed_list_ie = f_list->raB_FailedList_ies.list.array[i];
+ RANAP_RAB_FailedItemIEs_t _rab_failed_item_ies = {};
+ RANAP_RAB_FailedItemIEs_t *rab_failed_item_ies = &_rab_failed_item_ies;
+ RANAP_RAB_FailedItem_t *rab_failed_item;
+ uint8_t rab_id;
+
+ if (!failed_list_ie)
+ continue;
+
+ if (failed_list_ie->id != RANAP_ProtocolIE_ID_id_RAB_FailedItem)
+ continue;
+
+ rc = ranap_decode_rab_faileditemies_fromlist(rab_failed_item_ies, &failed_list_ie->value);
+ if (rc < 0)
+ continue;
+
+ rab_failed_item = &rab_failed_item_ies->raB_FailedItem;
+ /* RAB-ID is an 8-bit bit-string, so it's the first byte */
+ rab_id = rab_failed_item->rAB_ID.buf[0];
+
+ /* differentiate modify / activate */
+ switch (map->rab_state[rab_id]) {
+ case RAB_STATE_ACT_REQ:
+ HNBP_CTR_INC(hnbp, map->is_ps ? HNB_CTR_RANAP_PS_RAB_ACT_FAIL : HNB_CTR_RANAP_CS_RAB_ACT_FAIL);
+ map->rab_state[rab_id] = RAB_STATE_INACTIVE;
+ break;
+ case RAB_STATE_ACTIVE:
+ HNBP_CTR_INC(hnbp, map->is_ps ? HNB_CTR_RANAP_PS_RAB_MOD_FAIL : HNB_CTR_RANAP_CS_RAB_MOD_FAIL);
+ // FIXME: does it remain active after modification failure?
+ break;
+ default:
+ LOG_MAP(map, DRANAP, LOGL_NOTICE,
+ "Unexpected RAB Activation/Modification Failed for RAB in state %u\n", map->rab_state[rab_id]);
+ break;
+ }
+
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_FailedItem, rab_failed_item_ies);
+ }
+ }
+
+ if (ies->presenceMask & RAB_ASSIGNMENTRESPONSEIES_RANAP_RAB_RELEASEFAILEDLIST_PRESENT) {
+ RANAP_RAB_ReleaseFailedList_t *rf_list = &ies->raB_ReleaseFailedList;
+ /* increment number of released RABs, we don't need to do that individually during iteration */
+ HNBP_CTR_ADD(hnbp, map->is_ps ? HNB_CTR_RANAP_PS_RAB_REL_FAIL : HNB_CTR_RANAP_CS_RAB_REL_FAIL,
+ rf_list->raB_FailedList_ies.list.count);
+ for (unsigned int i = 0; i < rf_list->raB_FailedList_ies.list.count; i++) {
+ RANAP_IE_t *failed_list_ie = rf_list->raB_FailedList_ies.list.array[i];
+ RANAP_RAB_FailedItemIEs_t _rab_failed_item_ies = {};
+ RANAP_RAB_FailedItemIEs_t *rab_failed_item_ies = &_rab_failed_item_ies;
+ RANAP_RAB_FailedItem_t *rab_failed_item;
+ uint8_t rab_id;
+
+ if (!failed_list_ie)
+ continue;
+
+ if (failed_list_ie->id != RANAP_ProtocolIE_ID_id_RAB_FailedItem)
+ continue;
+
+ rc = ranap_decode_rab_faileditemies_fromlist(rab_failed_item_ies, &failed_list_ie->value);
+ if (rc < 0)
+ continue;
+
+ rab_failed_item = &rab_failed_item_ies->raB_FailedItem;
+ /* RAB-ID is an 8-bit bit-string, so it's the first byte */
+ rab_id = rab_failed_item->rAB_ID.buf[0];
+
+ /* differentiate modify / activate */
+ switch (map->rab_state[rab_id]) {
+ case RAB_STATE_ACT_REQ:
+ HNBP_CTR_INC(hnbp, map->is_ps ? HNB_CTR_RANAP_PS_RAB_ACT_FAIL : HNB_CTR_RANAP_CS_RAB_ACT_FAIL);
+ map->rab_state[rab_id] = RAB_STATE_INACTIVE;
+ break;
+ case RAB_STATE_ACTIVE:
+ HNBP_CTR_INC(hnbp, map->is_ps ? HNB_CTR_RANAP_PS_RAB_MOD_FAIL : HNB_CTR_RANAP_CS_RAB_MOD_FAIL);
+ // FIXME: does it remain active after modification failure?
+ break;
+ default:
+ LOG_MAP(map, DRANAP, LOGL_NOTICE,
+ "Unexpected RAB Release Failed for RAB in state %u\n", map->rab_state[rab_id]);
+ break;
+ }
+
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_FailedItem, rab_failed_item_ies);
+
+ }
+ }
+}
+
+void kpi_ranap_process_ul(struct hnbgw_context_map *map, ranap_message *ranap)
+{
+ switch (ranap->procedureCode) {
+ case RANAP_ProcedureCode_id_RAB_Assignment: /* RAB ASSIGNMENT REQ (8.2) */
+ kpi_ranap_process_ul_rab_ass_resp(map, ranap);
+ break;
+ case RANAP_ProcedureCode_id_Iu_Release:
+ /* TODO: We might want to parse the list of released RABs here and then mark each of those as
+ * released. For now we simply assume that all RABs are released in IU RELEASE during
+ * processing of the downlink Iu Release Command. It's not like the RNC/HNB has any way to
+ * refuse the release anyway. */
+ break;
+ default:
+ break;
+ }
+}

To view, visit change 36311. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: osmo-hnbgw
Gerrit-Branch: master
Gerrit-Change-Id: I198fa37699e22380909764de6a0522ac79aa1d39
Gerrit-Change-Number: 36311
Gerrit-PatchSet: 3
Gerrit-Owner: laforge <laforge@osmocom.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: dexter <pmaier@sysmocom.de>
Gerrit-Reviewer: fixeria <vyanitskiy@sysmocom.de>
Gerrit-Reviewer: laforge <laforge@osmocom.org>
Gerrit-Reviewer: pespin <pespin@sysmocom.de>
Gerrit-MessageType: merged