Jenkins Builder has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-pcu/+/31176 )
Change subject: support for Ericsson RBS E1 CCU
......................................................................
Patch Set 14:
(2 comments)
File src/ericsson-rbs/er_ccu_l1_if.c:
Robot Comment from checkpatch (run ID jenkins-gerrit-lint-4116):
https://gerrit.osmocom.org/c/osmo-pcu/+/31176/comment/f0155c85_07b95af8
PS14, Line 241: "afn_ul=%u (computed) != afn_ul=%u (sync-ind) => delta=%u \n", afn_ul,
unnecessary whitespace before a quoted newline
Robot Comment from checkpatch (run ID jenkins-gerrit-lint-4116):
https://gerrit.osmocom.org/c/osmo-pcu/+/31176/comment/452b4156_b709cc25
PS14, Line 246: "afn_dl=%u (computed) != afn_dl=%u (sync-ind) => delta=%u \n", afn_dl,
unnecessary whitespace before a quoted newline
--
To view, visit https://gerrit.osmocom.org/c/osmo-pcu/+/31176
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-pcu
Gerrit-Branch: master
Gerrit-Change-Id: I5c0a76667339ca984a12cbd2052f5d9e5b0f9c4d
Gerrit-Change-Number: 31176
Gerrit-PatchSet: 14
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-CC: neels <nhofmeyr(a)sysmocom.de>
Gerrit-Comment-Date: Mon, 27 Feb 2023 19:50:59 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Gerrit-MessageType: comment
Hello Jenkins Builder,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-pcu/+/31176
to look at the new patch set (#14).
Change subject: support for Ericsson RBS E1 CCU
......................................................................
support for Ericsson RBS E1 CCU
Ericsson RBS series BTSs do not have a built in PCU. Rather than having
the PCU on board the PCU is co-located to the BTS in those cases. Just
like the MGW the PCU would connect to the CCU (Channel Coding Unit) via
E1 line. The PCU is connected via an unix domain socket (pcu_sock) to
the BSC to receive RACH requests and to control Paging and TBF assignment.
This patch adds all the required functionality to fun an Ercisson RBS in
GPRS/EGPRS mode. It supports 16k I.460 E1 subslots and full 64k E1
timeslots (recommended)
Change-Id: I5c0a76667339ca984a12cbd2052f5d9e5b0f9c4d
Related: OS#5198
---
M configure.ac
M src/Makefile.am
A src/ericsson-rbs/er_ccu_descr.h
A src/ericsson-rbs/er_ccu_if.c
A src/ericsson-rbs/er_ccu_if.h
A src/ericsson-rbs/er_ccu_l1_if.c
A src/ericsson-rbs/er_ccu_l1_if.h
M src/gprs_debug.c
M src/gprs_debug.h
M src/pcu_l1_if.cpp
M src/pcu_l1_if.h
11 files changed, 1,142 insertions(+), 1 deletion(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-pcu refs/changes/76/31176/14
--
To view, visit https://gerrit.osmocom.org/c/osmo-pcu/+/31176
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-pcu
Gerrit-Branch: master
Gerrit-Change-Id: I5c0a76667339ca984a12cbd2052f5d9e5b0f9c4d
Gerrit-Change-Number: 31176
Gerrit-PatchSet: 14
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-CC: neels <nhofmeyr(a)sysmocom.de>
Gerrit-MessageType: newpatchset
Attention is currently required from: neels, pespin, fixeria.
Hello Jenkins Builder, laforge, fixeria, pespin,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-pcu/+/31145
to look at the new patch set (#17).
Change subject: bts: add IMMEDIATE ASSIGNMENT via PCH transmission
......................................................................
bts: add IMMEDIATE ASSIGNMENT via PCH transmission
In situations where the PCU is co-located to the BSC, the IMMEDIATE ASSIGNMENT
for downlink TBFs must be sent via RSL and the BSC also must instruct the BTS
to transmit the IMMEDIATE ASSIGNMENT via PCH instead of AGCH. Eventually the
BSC must sent a confirmation message (follow-up patch) where the TLLI is used
as an identifer.
Change-Id: I2a78651593323e8b9627c39918d949a33497b70f
Related: OS#5198
---
M include/osmocom/pcu/pcuif_proto.h
M src/bts.cpp
M src/bts.h
M src/pcu_l1_if.cpp
M src/pcu_l1_if.h
5 files changed, 65 insertions(+), 2 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-pcu refs/changes/45/31145/17
--
To view, visit https://gerrit.osmocom.org/c/osmo-pcu/+/31145
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-pcu
Gerrit-Branch: master
Gerrit-Change-Id: I2a78651593323e8b9627c39918d949a33497b70f
Gerrit-Change-Number: 31145
Gerrit-PatchSet: 17
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-CC: neels <nhofmeyr(a)sysmocom.de>
Gerrit-Attention: neels <nhofmeyr(a)sysmocom.de>
Gerrit-Attention: pespin <pespin(a)sysmocom.de>
Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-MessageType: newpatchset
Attention is currently required from: neels, pespin, fixeria.
dexter has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-pcu/+/31145 )
Change subject: bts: add IMMEDIATE ASSIGNMENT via PCH transmission
......................................................................
Patch Set 17:
(2 comments)
File src/bts.h:
https://gerrit.osmocom.org/c/osmo-pcu/+/31145/comment/16bc6db8_9db56f2e
PS16, Line 284: bool use_dt_confirm;
> what does "dt" mean?
DT stands für "Direct TLLI" that refers to a way where we directly transfer the TLLI instead of using a payload that just contains the TLLI.
File src/pcu_l1_if.cpp:
https://gerrit.osmocom.org/c/osmo-pcu/+/31145/comment/360a633d_44477aac
PS5, Line 320: data[sizeof(tlli) + (PAGING_GROUP_LEN - 1 - i)]
> i also dislike the pattern of unreadable encoding magic, especially in the middle of flow control an […]
Ye have discussed this today. I will add a struct for that.
--
To view, visit https://gerrit.osmocom.org/c/osmo-pcu/+/31145
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-pcu
Gerrit-Branch: master
Gerrit-Change-Id: I2a78651593323e8b9627c39918d949a33497b70f
Gerrit-Change-Number: 31145
Gerrit-PatchSet: 17
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-CC: neels <nhofmeyr(a)sysmocom.de>
Gerrit-Attention: neels <nhofmeyr(a)sysmocom.de>
Gerrit-Attention: pespin <pespin(a)sysmocom.de>
Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Comment-Date: Mon, 27 Feb 2023 19:50:23 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: neels <nhofmeyr(a)sysmocom.de>
Comment-In-Reply-To: fixeria <vyanitskiy(a)sysmocom.de>
Comment-In-Reply-To: dexter <pmaier(a)sysmocom.de>
Gerrit-MessageType: comment
dexter has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-pcu/+/31176 )
Change subject: support for Ericsson RBS E1 CCU
......................................................................
Patch Set 13:
(1 comment)
Patchset:
PS13:
@neels Thanks for reviewing this. I will get to your comments tomorrow. Since there were some changes in patches below I had to update a few code pathes. I will post those changes now.
--
To view, visit https://gerrit.osmocom.org/c/osmo-pcu/+/31176
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-pcu
Gerrit-Branch: master
Gerrit-Change-Id: I5c0a76667339ca984a12cbd2052f5d9e5b0f9c4d
Gerrit-Change-Number: 31176
Gerrit-PatchSet: 13
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-CC: neels <nhofmeyr(a)sysmocom.de>
Gerrit-Comment-Date: Mon, 27 Feb 2023 19:49:32 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Gerrit-MessageType: comment
Jenkins Builder has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-bsc/+/31578 )
Change subject: pcu_sock: use struct to transfer IMMEDIATE ASSIGNMENT for PCH
......................................................................
Patch Set 1:
(1 comment)
File src/osmo-bsc/pcu_sock.c:
Robot Comment from checkpatch (run ID jenkins-gerrit-lint-4113):
https://gerrit.osmocom.org/c/osmo-bsc/+/31578/comment/08cff42f_354c01ac
PS1, Line 575: pch_dt = (struct gsm_pcu_if_pch_dt*)data_req->data;
"(foo*)" should be "(foo *)"
--
To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/31578
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: Id6acbd243adf26169e5e8319dd66bb68dd6a3c22
Gerrit-Change-Number: 31578
Gerrit-PatchSet: 1
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-CC: Jenkins Builder
Gerrit-Comment-Date: Mon, 27 Feb 2023 19:47:53 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Gerrit-MessageType: comment
dexter has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-bsc/+/31577 )
Change subject: abis_rsl: assert maximum length
......................................................................
abis_rsl: assert maximum length
The length parameter in rsl_imm_assign_cmd_common() may cause a buffer
overflow when it is chosen larger than GSM_MACBLOCK_LEN. This should be
asserted.
Change-Id: I9417b35fb8c0517f2555e17059bf8ac60fa59791
---
M src/osmo-bsc/abis_rsl.c
1 file changed, 14 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/77/31577/1
diff --git a/src/osmo-bsc/abis_rsl.c b/src/osmo-bsc/abis_rsl.c
index ee2e2d3..410f08e 100644
--- a/src/osmo-bsc/abis_rsl.c
+++ b/src/osmo-bsc/abis_rsl.c
@@ -944,6 +944,7 @@
break;
default:
/* If phase 2, construct a FULL_IMM_ASS_INFO */
+ OSMO_ASSERT(len <= sizeof(buf));
pad_macblock(buf, val, len);
msgb_tlv_put(msg, RSL_IE_FULL_IMM_ASS_INFO, GSM_MACBLOCK_LEN,
buf);
--
To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/31577
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: I9417b35fb8c0517f2555e17059bf8ac60fa59791
Gerrit-Change-Number: 31577
Gerrit-PatchSet: 1
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-MessageType: newchange
dexter has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-bsc/+/31578 )
Change subject: pcu_sock: use struct to transfer IMMEDIATE ASSIGNMENT for PCH
......................................................................
pcu_sock: use struct to transfer IMMEDIATE ASSIGNMENT for PCH
When the IMMEDIATE ASSIGNMENT is sent from the PCU to the BSC using the
"direct TLLI" method, the TLLI (and the paging group) is premended to
the MAC block. Currently we are taking the fields apart manually using
offsets. The code for this is difficult to read and the method is error
prone. Lets define a struct that we can just overlay to access the
fields directly.
Change-Id: Id6acbd243adf26169e5e8319dd66bb68dd6a3c22
Related: OS#5198
---
M include/osmocom/bsc/pcuif_proto.h
M src/osmo-bsc/pcu_sock.c
2 files changed, 39 insertions(+), 11 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/78/31578/1
diff --git a/include/osmocom/bsc/pcuif_proto.h b/include/osmocom/bsc/pcuif_proto.h
index 7e13b5c..1d12f50 100644
--- a/include/osmocom/bsc/pcuif_proto.h
+++ b/include/osmocom/bsc/pcuif_proto.h
@@ -3,6 +3,7 @@
#include <osmocom/gsm/l1sap.h>
#include <arpa/inet.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
#define PCU_SOCK_DEFAULT "/tmp/pcu_bts"
@@ -270,6 +271,17 @@
} cgi_ps;
} __attribute__ ((packed));
+/* Container to send a (confirmed) IMMEDIATE ASSIGNMENT message via PCH. The struct is send as a data request
+ * (data_req) under SAPI PCU_IF_SAPI_PCH_DT. */
+struct gsm_pcu_if_pch_dt {
+ /* TLLI as reference for confirmation */
+ uint32_t tlli;
+ /* Paging group */
+ uint8_t pgroup[3];
+ /* GSM mac-block (with immediate assignment message) */
+ uint8_t data[GSM_MACBLOCK_LEN];
+} __attribute__((packed));
+
struct gsm_pcu_if {
/* context based information */
uint8_t msg_type; /* message type */
diff --git a/src/osmo-bsc/pcu_sock.c b/src/osmo-bsc/pcu_sock.c
index 0d84781..8286f68 100644
--- a/src/osmo-bsc/pcu_sock.c
+++ b/src/osmo-bsc/pcu_sock.c
@@ -533,9 +533,9 @@
struct gsm_pcu_if_data *data_req)
{
struct msgb *msg;
- uint32_t tlli = -1;
uint8_t pag_grp;
int rc = 0;
+ struct gsm_pcu_if_pch_dt *pch_dt;
LOGP(DPCU, LOGL_DEBUG, "Data request received: sapi=%s arfcn=%d "
"block=%d data=%s\n", sapi_string[data_req->sapi],
@@ -566,34 +566,33 @@
/* DT = direct TLLI. A tlli is prefixed so that the BSC/BTS can confirm the sending of the downlink
* IMMEDIATE ASSIGNMENT towards the PCU using this TLLI as a reference. */
- if (data_req->len < 8) {
+ if (data_req->len < sizeof(struct gsm_pcu_if_pch_dt)) {
LOGP(DPCU, LOGL_ERROR, "Received PCU data request with invalid/small length %d\n",
data_req->len);
break;
}
- /* Extract 4 byte TLLI */
- memcpy(&tlli, data_req->data, 4);
+ pch_dt = (struct gsm_pcu_if_pch_dt*)data_req->data;
- /* Extract 3 byte paging group */
- pag_grp = extract_paging_group(bts, data_req->data + 4);
+ pag_grp = extract_paging_group(bts, pch_dt->pgroup);
LOGP(DPCU, LOGL_DEBUG, "PCU Sends immediate assignment via PCH (tlli=0x%08x, pag_grp=0x%02x)\n",
- tlli, pag_grp);
- msg = msgb_alloc(data_req->len - 7, "pcu_pch");
+ pch_dt->tlli, pag_grp);
+ msg = msgb_alloc(sizeof(pch_dt->data), "pcu_pch");
if (!msg) {
rc = -ENOMEM;
break;
}
- msg->l3h = msgb_put(msg, data_req->len - 7);
- memcpy(msg->l3h, data_req->data + 7, data_req->len - 7);
+
+ msg->l3h = msgb_put(msg, sizeof(pch_dt->data));
+ memcpy(msg->l3h, pch_dt->data, sizeof(pch_dt->data));
/* NOTE: Sending an IMMEDIATE ASSIGNMENT via PCH became necessary with GPRS in order to be able to
* assign downlink TBFs directly through the paging channel. However, this method never became part
* of the RSL specs. This means that each BTS vendor has to come up with a proprietary method. At
* the moment we only support Ericsson RBS here. */
if (bts->type == GSM_BTS_TYPE_RBS2000) {
- rc = rsl_ericsson_imm_assign_cmd(bts, tlli, msg->len, msg->data, pag_grp);
+ rc = rsl_ericsson_imm_assign_cmd(bts, pch_dt->tlli, msg->len, msg->data, pag_grp);
} else {
LOGP(DPCU, LOGL_ERROR, "BTS model does not support sending immediate assignment via PCH!\n");
rc = -ENOTSUP;
--
To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/31578
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: Id6acbd243adf26169e5e8319dd66bb68dd6a3c22
Gerrit-Change-Number: 31578
Gerrit-PatchSet: 1
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-MessageType: newchange
Attention is currently required from: pespin, fixeria.
Hello Jenkins Builder, fixeria,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-bsc/+/31499
to look at the new patch set (#3).
Change subject: pcu_sock: print OML alerts from PCU
......................................................................
pcu_sock: print OML alerts from PCU
The PCU is able to send OML alerts via the BTS to the BSC. When the PCU
operates in co-location to the BSC we just print the alerts in the log
directly
Change-Id: Id32553556356c2affe32e47ae1c3ae6a514efdce
Related: OS#5198
---
M src/osmo-bsc/pcu_sock.c
1 file changed, 17 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/99/31499/3
--
To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/31499
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: Id32553556356c2affe32e47ae1c3ae6a514efdce
Gerrit-Change-Number: 31499
Gerrit-PatchSet: 3
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-CC: pespin <pespin(a)sysmocom.de>
Gerrit-Attention: pespin <pespin(a)sysmocom.de>
Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-MessageType: newpatchset
Attention is currently required from: neels, fixeria.
dexter has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-bsc/+/31497 )
Change subject: pcu_sock: activate/deactivate PDCH on pcu reconnect
......................................................................
Patch Set 3:
(9 comments)
Commit Message:
https://gerrit.osmocom.org/c/osmo-bsc/+/31497/comment/a0d8dcdf_350f924a
PS2, Line 10: po
> typo
Done
File doc/timeslot.msc:
https://gerrit.osmocom.org/c/osmo-bsc/+/31497/comment/692f83cc_73d3c2ba
PS2, Line 95: bsc_ts abox bsc_ts [label="UNUSED"];
> a timeslot FSM cannot transition from ST_PDCH directly to ST_UNUSED. […]
Thats true, Can we shorten this since the mechanism is already explained above. I have now added some dots in the graph to indicate that there is something in between.
https://gerrit.osmocom.org/c/osmo-bsc/+/31497/comment/872f8b9d_933f3141
PS2, Line 98: "
> \nfor all timeslots in state UNUSED:"
Done
https://gerrit.osmocom.org/c/osmo-bsc/+/31497/comment/61358273_1c43b7c9
PS2, Line 99: PDCH
> UNUSED
Done
https://gerrit.osmocom.org/c/osmo-bsc/+/31497/comment/5f4e20a2_893985a0
PS2, Line 100: bsc_ts <- pcu_sock [label="TS_EV_PDCH_ACT"];
> bsc_ts abox bsc_ts [label="WAIT_PDCH_ACT (4s, T23001)"]; […]
(see above: this can't be shortened.)
File include/osmocom/bsc/timeslot_fsm.h:
https://gerrit.osmocom.org/c/osmo-bsc/+/31497/comment/c1b8d803_179120eb
PS2, Line 38: TS_EV_LCHAN_UNUSED,
> Would be nice to add comments to clarify how the "TS_EV_PDCH_*" are fundamentally different: […]
Done
https://gerrit.osmocom.org/c/osmo-bsc/+/31497/comment/2230b651_6106dd49
PS2, Line 42: TS_EV_PDCH_DEACT_NACK,
> /* An Ericsson PCU has disconnected from OsmoBSC, deactivate PDCH: */
Done
https://gerrit.osmocom.org/c/osmo-bsc/+/31497/comment/8bf192c0_9df3612f
PS2, Line 43: TS_EV_PDCH_DEACT,
> /* An Ericsson PCU has reconnected to OsmoBSC, re-activate PDCH: */
Done
File src/osmo-bsc/pcu_sock.c:
https://gerrit.osmocom.org/c/osmo-bsc/+/31497/comment/c5e97d03_1deb1545
PS2, Line 940: /* FIXME: allow multiple BTS */
> i understand now, so far the entire pcu_sock. […]
That is correct. Thats also a limitation of the the PCU itsself. At some day we will have to resolve that but for the moment I think that no one will run an osmo-bsc setup with multiple ericsson BTS attached. Since the BTS is hooked up via an E1 line each site will likely get its own BSC on site, so I think there is no immediate pressure to fix this.
--
To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/31497
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: I9ea0c53a5e68a51c781ef43bae71f947cdb95678
Gerrit-Change-Number: 31497
Gerrit-PatchSet: 3
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: neels <nhofmeyr(a)sysmocom.de>
Gerrit-CC: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Attention: neels <nhofmeyr(a)sysmocom.de>
Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Comment-Date: Mon, 27 Feb 2023 19:46:25 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: neels <nhofmeyr(a)sysmocom.de>
Gerrit-MessageType: comment
Attention is currently required from: neels, fixeria.
Hello Jenkins Builder, neels,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-bsc/+/31497
to look at the new patch set (#3).
Change subject: pcu_sock: activate/deactivate PDCH on pcu reconnect
......................................................................
pcu_sock: activate/deactivate PDCH on pcu reconnect
When the PCU is disconnected while the BSC keeps running the PDCH should
be closed. Also the PDCH should be reopened when the PCU is
reconnected.
Change-Id: I9ea0c53a5e68a51c781ef43bae71f947cdb95678
Related: OS#5198
---
M doc/timeslot.msc
M include/osmocom/bsc/timeslot_fsm.h
M src/osmo-bsc/pcu_sock.c
M src/osmo-bsc/timeslot_fsm.c
4 files changed, 112 insertions(+), 18 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/97/31497/3
--
To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/31497
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: I9ea0c53a5e68a51c781ef43bae71f947cdb95678
Gerrit-Change-Number: 31497
Gerrit-PatchSet: 3
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: neels <nhofmeyr(a)sysmocom.de>
Gerrit-CC: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Attention: neels <nhofmeyr(a)sysmocom.de>
Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-MessageType: newpatchset
Attention is currently required from: osmith, laforge.
fixeria has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/31556 )
Change subject: library/RSL_Types: RSL_SpeechAlgo: support CSD
......................................................................
Patch Set 2:
(1 comment)
File library/RSL_Types.ttcn:
https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/31556/comment/40f271a0_d49c…
PS2, Line 389: RSL_SpeechAlgoDataRate
I am currently looking at 3GPP TS 48.058 section 9.3.6, and I see the following:
If octet 4 indicates speech, then octet 6 is coded as follows:
0000 0001 - GSM speech coding algorithm version 1
...
0000 1101 - GSM speech coding algorithm version 6
All other values are reserved.
Then below I see:
If octet 4 indicates data, then octet 6 is coded as follows:
So the encoding of octet 6 depends on the value of octet 4.
The octet 6 itself is defined as follows:
Speech coding algor./data rate + transp ind
AFAIU, the '/' means either speech or data.
I don't think mixing up all encoding variants in one enumerated type is a good idea. I would rather have several enums grouped into a union.
--
To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/31556
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: Ief2d95c7e9d71afb26fa74da755294226c8e158d
Gerrit-Change-Number: 31556
Gerrit-PatchSet: 2
Gerrit-Owner: osmith <osmith(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-CC: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Attention: osmith <osmith(a)sysmocom.de>
Gerrit-Attention: laforge <laforge(a)osmocom.org>
Gerrit-Comment-Date: Mon, 27 Feb 2023 18:43:03 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Gerrit-MessageType: comment
Attention is currently required from: pespin.
fixeria has posted comments on this change. ( https://gerrit.osmocom.org/c/osmocom-bb/+/31572 )
Change subject: modem: route L1CTL prims to/from libosmo-gprs-rlcmac
......................................................................
Patch Set 1:
(1 comment)
File src/host/layer23/src/modem/rlcmac.c:
https://gerrit.osmocom.org/c/osmocom-bb/+/31572/comment/f5cab026_e6d0747c
PS1, Line 173: rlcmac_prim_l1ctl_alloc
> Nothing really prevents you from filling the struct with a designated initializer like you are doing […]
... the need to pass dummy arguments to `osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_data_ind()` which will then be overwritten by designated initializer. I can go for that, but I really like this approach.
--
To view, visit https://gerrit.osmocom.org/c/osmocom-bb/+/31572
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmocom-bb
Gerrit-Branch: master
Gerrit-Change-Id: I38e9a686f8edc3fe55f961d75e68602c33bbbaaf
Gerrit-Change-Number: 31572
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-Attention: pespin <pespin(a)sysmocom.de>
Gerrit-Comment-Date: Mon, 27 Feb 2023 17:27:13 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: pespin <pespin(a)sysmocom.de>
Comment-In-Reply-To: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-MessageType: comment
Attention is currently required from: fixeria.
pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmocom-bb/+/31572 )
Change subject: modem: route L1CTL prims to/from libosmo-gprs-rlcmac
......................................................................
Patch Set 1:
(1 comment)
File src/host/layer23/src/modem/rlcmac.c:
https://gerrit.osmocom.org/c/osmocom-bb/+/31572/comment/eec15140_d6e25384
PS1, Line 173: rlcmac_prim_l1ctl_alloc
> > I see no real need to expose it […]
Nothing really prevents you from filling the struct with a designated initializer like you are doing here after using the existing API.
I'm no against exposing the other API but I really see why is this really blocking your here now.
--
To view, visit https://gerrit.osmocom.org/c/osmocom-bb/+/31572
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmocom-bb
Gerrit-Branch: master
Gerrit-Change-Id: I38e9a686f8edc3fe55f961d75e68602c33bbbaaf
Gerrit-Change-Number: 31572
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Comment-Date: Mon, 27 Feb 2023 17:23:04 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: fixeria <vyanitskiy(a)sysmocom.de>
Comment-In-Reply-To: pespin <pespin(a)sysmocom.de>
Gerrit-MessageType: comment
neels has submitted this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/31431 )
Change subject: context map: introduce RUA and SCCP FSMs to fix leaks
......................................................................
context map: introduce RUA and SCCP FSMs to fix leaks
Refactor the entire RUA <-> SCCP connection-oriented message forwarding:
- conquer confusion about hnbgw_context_map release behavior, and
- eradicate SCCP connection leaks.
Finer points:
== Context map state ==
So far, we had a single context map state and some flags to keep track
of both the RUA and the SCCP connections. It was easy to miss connection
cleanup steps, especially on the SCCP side.
Instead, the two FSMs clearly define the RUA and SCCP conn states
separately, and each side takes care of its own release needs for all
possible scenarios.
- When both RUA and SCCP are released, the context map is discarded.
- A context map can stay around to wait for proper SCCP release, even if
the RUA side has lost the HNB connection.
- Completely drop the async "context mapper garbage collection", because
the FSMs clarify the release and free steps, synchronously.
- We still keep a (simplified) enum for global context map state, but
this is only used so that VTY reporting remains mostly unchanged.
== Context map cleanup confusion ==
The function context_map_hnb_released() was the general cleanup function
for a context map. Instead, add separate context_map_free().
== Free context maps separately from HNB ==
When a HNB releases, talloc_steal() the context maps out of the HNB
specific hnb_ctx, so that they are not freed along with the HNB state,
possibly leaving SCCP connections afloat.
(It is still nice to normally keep context maps as talloc children of
their respective hnb_ctx, so talloc reports show which belongs to
which.)
So far, context map handling found the global hnb_gw pointer via
map->hnb_ctx->gw. But in fact, a HNB may disappear at any point in time.
Instead, use a separate hnb_gw pointer in map->gw.
== RUA procedure codes vs. SCCP prims ==
So far, the RUA rx side composed SCCP prims to pass on:
RUA rx ---SCCP-prim--> RANAP handling ---SCCP-prim--> SCCP tx
That is a source of confusion: a RUA procedure code should not translate
1:1 to SCCP prims, especially for RUA id-Disconnect (see release charts
below).
Instead, move SCCP prim composition over to the SCCP side, using FSM
events to forward:
RUA rx --event--> RUA FSM --event--> SCCP FSM --SCCP-prim--> SCCP tx
+RANAP +RANAP +RANAP
RUA tx <--RUA---- RUA FSM <--event-- SCCP FSM <--event-- SCCP rx
+RANAP +RANAP +RANAP
Hence choose the correct prim according to the SCCP FSM state.
- in hnbgw_rua.c, use RUA procedure codes, not prim types.
- via the new FSM events' data args, pass msgb containing RANAP PDUs.
== Fix SCCP Release behavior ==
So far, the normal conn release behavior was
HNB HNBGW CN
| --id-Disconnect--> | ---SCCP-Released--> | Iu-ReleaseComplete
| | <--SCCP-RLC-------- | (no data)
Instead, the SCCP release is now in accordance with 3GPP TS 48.006 9.2
'Connection release':
The MSC sends a SCCP released message. This message shall not contain
any user data field.
i.e.:
HNB HNBGW CN
| --id-Disconnect--> | ---Data-Form-1(!)--> | Iu-ReleaseComplete
| | <--SCCP-Released---- | (no data)
| | ---SCCP-RLC--------> | (no data)
(Side note, the final SCCP Release Confirm step is taken care of
implicitly by libosmo-sigtran's sccp_scoc.c FSM.)
If the CN fails to respond with SCCP-Released, on new X31 timeout,
osmo-hnbgw will send an SCCP Released to the CN as fallback.
== Memory model for message dispatch ==
So far, an osmo_scu_prim aka "oph" was passed between RUA and SCCP
handling code, and the final dispatch freed it. Every error path had to
take care not to leak any oph.
Instead, use a much easier and much more leakage proof memory model,
inspired by fixeria:
- on rx, dispatch RANAP msgb that live in OTC_SELECT.
- no code path needs to msgb_free() -- the msgb is discarded via
OTC_SELECT when handling is done, error or no error.
- any code path may also choose to store the msgb for async dispatch,
using talloc_steal(). The user plane mapping via MGW and UPF do that.
- if any code path does msgb_free(), that would be no problem either
(but none do so now, for simplicity).
== Layer separation ==
Dispatch *all* connection-oriented RUA tx via the RUA FSM and SCCP tx
via the SCCP FSM, do not call rua_tx_dt() or osmo_sccp_user_sap_down()
directly.
== Memory model for decoded ranap_message IEs ==
Use a talloc destructor to make sure that the ranap_message IEs are
always implicitly freed upon talloc_free(), so that no code path can
possibly forget to do so.
== Implicit cleanup by talloc ==
Use talloc scoping to remove a bunch of explicit cleanup code. For
example, make a chached message a talloc child of its handler:
talloc_steal(mgw_fsm_priv, message);
mgw_fsm_priv->ranap_rab_ass_req_message = message;
and later implicitly free 'message' by only freeing the handler:
talloc_free(mgw_fsm_priv)
Related: SYS#6297
Change-Id: I6ff7e36532ff57c6f2d3e7e419dd22ef27dafd19
---
M include/osmocom/hnbgw/context_map.h
M include/osmocom/hnbgw/hnbgw.h
M include/osmocom/hnbgw/hnbgw_cn.h
M include/osmocom/hnbgw/mgw_fsm.h
M include/osmocom/hnbgw/ps_rab_ass_fsm.h
M include/osmocom/hnbgw/tdefs.h
M src/osmo-hnbgw/Makefile.am
M src/osmo-hnbgw/context_map.c
A src/osmo-hnbgw/context_map_rua.c
A src/osmo-hnbgw/context_map_sccp.c
M src/osmo-hnbgw/hnbgw.c
M src/osmo-hnbgw/hnbgw_cn.c
M src/osmo-hnbgw/hnbgw_rua.c
M src/osmo-hnbgw/hnbgw_vty.c
M src/osmo-hnbgw/mgw_fsm.c
M src/osmo-hnbgw/ps_rab_ass_fsm.c
M src/osmo-hnbgw/ps_rab_fsm.c
M src/osmo-hnbgw/tdefs.c
18 files changed, 1,397 insertions(+), 375 deletions(-)
Approvals:
Jenkins Builder: Verified
pespin: Looks good to me, but someone else must approve
laforge: Looks good to me, approved
diff --git a/include/osmocom/hnbgw/context_map.h b/include/osmocom/hnbgw/context_map.h
index 7bcdf57..b64358a 100644
--- a/include/osmocom/hnbgw/context_map.h
+++ b/include/osmocom/hnbgw/context_map.h
@@ -2,6 +2,7 @@
#include <stdint.h>
#include <osmocom/core/linuxlist.h>
+#include <osmocom/hnbgw/hnbgw.h>
#define LOG_MAP(HNB_CTX_MAP, SUBSYS, LEVEL, FMT, ARGS...) \
LOGHNB((HNB_CTX_MAP) ? (HNB_CTX_MAP)->hnb_ctx : NULL, \
@@ -10,12 +11,56 @@
(HNB_CTX_MAP) ? ((HNB_CTX_MAP)->is_ps ? "PS" : "CS") : "NULL", \
##ARGS)
+/* All these events' data argument may either be NULL, or point to a RANAP msgb.
+ * - The msgb shall be in the OTC_SELECT talloc pool, so that they will be deallocated automatically. Some events
+ * processing will store the msgb for later, in which case it will take over ownership of the msgb by means of
+ * talloc_steal().
+ * - For events that may send a RANAP message towards CN via SCCP, the msgb shall have reserved headroom to fit a struct
+ * osmo_scu_prim. These are: MAP_RUA_EV_RX_*.
+ * - The RANAP message shall be at msgb_l2().
+ */
+enum map_rua_fsm_event {
+ /* Receiving a RUA Connect from HNB. */
+ MAP_RUA_EV_RX_CONNECT,
+ /* Receiving some data from HNB via RUA, to forward via SCCP to CN. */
+ MAP_RUA_EV_RX_DIRECT_TRANSFER,
+ /* Receiving a RUA Disconnect from HNB. */
+ MAP_RUA_EV_RX_DISCONNECT,
+ /* SCCP has received some data from CN to forward via RUA to HNB. */
+ MAP_RUA_EV_TX_DIRECT_TRANSFER,
+ /* The CN side is disconnected (e.g. received an SCCP Released), that means we are going gracefully disconnect
+ * RUA, too. */
+ MAP_RUA_EV_CN_DISC,
+ /* All of a sudden, there is no RUA link. For example, HNB vanished / restarted, or SCTP SHUTDOWN on the RUA
+ * link. Skip RUA disconnect. */
+ MAP_RUA_EV_HNB_LINK_LOST,
+};
+
+/* All these events' data argument is identical to enum map_rua_fsm_event, with this specialisation:
+ * - The events that may send a RANAP message towards CN via SCCP and hence require a headroom for an osmo_scu_prim are:
+ * MAP_SCCP_EV_TX_DATA_REQUEST, MAP_SCCP_EV_RAN_DISC.
+ */
+enum map_sccp_fsm_event {
+ /* Receiving an SCCP CC from CN. */
+ MAP_SCCP_EV_RX_CONNECTION_CONFIRM,
+ /* Receiving some data from CN via SCCP, to forward via RUA to HNB. */
+ MAP_SCCP_EV_RX_DATA_INDICATION,
+ /* RUA has received some data from HNB to forward via SCCP to CN. */
+ MAP_SCCP_EV_TX_DATA_REQUEST,
+ /* The RAN side received a Disconnect, that means we are going to expect SCCP to disconnect too.
+ * CN should have received an Iu-ReleaseComplete with or before this, give CN a chance to send an SCCP RLSD;
+ * after a timeout we will send a non-standard RLSD to the CN instead. */
+ MAP_SCCP_EV_RAN_DISC,
+ /* Receiving an SCCP RLSD from CN, or libosmo-sigtran tells us about SCCP connection timeout. All done. */
+ MAP_SCCP_EV_RX_RELEASED,
+};
+
+/* For context_map_get_state(), to combine the RUA and SCCP states, for VTY reporting only. */
enum hnbgw_context_map_state {
- MAP_S_NULL,
- MAP_S_ACTIVE, /* currently active map */
- MAP_S_RESERVED1, /* just disconnected, still resrved */
- MAP_S_RESERVED2, /* still reserved */
- MAP_S_NUM_STATES /* Number of states, keep this at the end */
+ MAP_S_CONNECTING, /* not active yet; effectively waiting for SCCP CC */
+ MAP_S_ACTIVE, /* both RUA and SCCP are connected */
+ MAP_S_DISCONNECTING, /* not active anymore; effectively waiting for SCCP RLSD */
+ MAP_S_NUM_STATES /* Number of states, keep this at the end */
};
extern const struct value_string hnbgw_context_map_state_names[];
@@ -28,27 +73,36 @@
struct hnbgw_context_map {
/* entry in the per-CN list of mappings */
struct llist_head cn_list;
- /* entry in the per-HNB list of mappings. */
+ /* entry in the per-HNB list of mappings. If hnb_ctx == NULL, then this llist entry has been llist_del()eted and
+ * must not be used. */
struct llist_head hnb_list;
- /* Pointer to HNB for this map, to transceive RUA. */
+ /* Backpointer to global hnb_gw. */
+ struct hnb_gw *gw;
+
+ /* Pointer to HNB for this map, to transceive RUA. If the HNB has disconnected without releasing the RUA
+ * context, this is NULL. */
struct hnb_context *hnb_ctx;
/* RUA context ID used in RUA messages to/from the hnb_gw. */
uint32_t rua_ctx_id;
+ /* FSM handling the RUA state for rua_ctx_id. */
+ struct osmo_fsm_inst *rua_fi;
/* Pointer to CN, to transceive SCCP. */
struct hnbgw_cnlink *cn_link;
/* SCCP User SAP connection ID used in SCCP messages to/from the cn_link. */
uint32_t scu_conn_id;
- /* Set to true on SCCP Conn Conf, set to false when an OSMO_SCU_PRIM_N_DISCONNECT has been sent for the SCCP
- * User SAP conn. Useful to avoid leaking SCCP connections: guarantee that an OSMO_SCU_PRIM_N_DISCONNECT gets
- * sent, even when RUA fails to gracefully disconnect. */
- bool scu_conn_active;
+ /* FSM handling the SCCP state for scu_conn_id. */
+ struct osmo_fsm_inst *sccp_fi;
/* False for CS, true for PS */
bool is_ps;
- enum hnbgw_context_map_state state;
+ /* When an FSM is asked to disconnect but must still wait for a response, it may set this flag, to continue to
+ * disconnect once the response is in. In particular, when SCCP is asked to disconnect after an SCCP Connection
+ * Request was already sent and while waiting for a Connection Confirmed, we should still wait for the SCCP CC
+ * and immediately release it after that, to not leak the connection. */
+ bool please_disconnect;
/* FSM instance for the MGW, handles the async MGCP communication necessary to intercept CS RAB Assignment and
* redirect the RTP via the MGW. */
@@ -71,17 +125,40 @@
/* All PS RABs and their GTP tunnel mappings. list of struct ps_rab. Each ps_rab FSM handles the PFCP
* communication for one particular RAB ID. */
struct llist_head ps_rabs;
+
+ /* Flag to prevent calling context_map_free() from cleanup code paths triggered by context_map_free() itself. */
+ bool deallocating;
};
+enum hnbgw_context_map_state context_map_get_state(struct hnbgw_context_map *map);
+enum hnbgw_context_map_state map_rua_get_state(struct hnbgw_context_map *map);
+enum hnbgw_context_map_state map_sccp_get_state(struct hnbgw_context_map *map);
struct hnbgw_context_map *
context_map_alloc_by_hnb(struct hnb_context *hnb, uint32_t rua_ctx_id,
bool is_ps,
struct hnbgw_cnlink *cn_if_new);
+void map_rua_fsm_alloc(struct hnbgw_context_map *map);
+void map_sccp_fsm_alloc(struct hnbgw_context_map *map);
+
struct hnbgw_context_map *
context_map_by_cn(struct hnbgw_cnlink *cn, uint32_t scu_conn_id);
void context_map_hnb_released(struct hnbgw_context_map *map);
-int context_map_init(struct hnb_gw *gw);
+#define map_rua_dispatch(MAP, EVENT, MSGB) \
+ _map_rua_dispatch(MAP, EVENT, MSGB, __FILE__, __LINE__)
+int _map_rua_dispatch(struct hnbgw_context_map *map, uint32_t event, struct msgb *ranap_msg,
+ const char *file, int line);
+
+#define map_sccp_dispatch(MAP, EVENT, MSGB) \
+ _map_sccp_dispatch(MAP, EVENT, MSGB, __FILE__, __LINE__)
+int _map_sccp_dispatch(struct hnbgw_context_map *map, uint32_t event, struct msgb *ranap_msg,
+ const char *file, int line);
+
+bool map_rua_is_active(struct hnbgw_context_map *map);
+bool map_sccp_is_active(struct hnbgw_context_map *map);
+void context_map_check_released(struct hnbgw_context_map *map);
+
+unsigned int msg_has_l2_data(const struct msgb *msg);
diff --git a/include/osmocom/hnbgw/hnbgw.h b/include/osmocom/hnbgw/hnbgw.h
index f1b107e..96a2ef3 100644
--- a/include/osmocom/hnbgw/hnbgw.h
+++ b/include/osmocom/hnbgw/hnbgw.h
@@ -19,6 +19,8 @@
DRUA,
DRANAP,
DMGW,
+ DHNB,
+ DCN,
};
#define LOGHNB(HNB_CTX, ss, lvl, fmt, args ...) \
@@ -201,3 +203,5 @@
{
return gw->config.pfcp.remote_addr != NULL;
}
+
+struct msgb *hnbgw_ranap_msg_alloc(const char *name);
diff --git a/include/osmocom/hnbgw/hnbgw_cn.h b/include/osmocom/hnbgw/hnbgw_cn.h
index b481a69..0df2716 100644
--- a/include/osmocom/hnbgw/hnbgw_cn.h
+++ b/include/osmocom/hnbgw/hnbgw_cn.h
@@ -3,3 +3,5 @@
#include <osmocom/hnbgw/hnbgw.h>
int hnbgw_cnlink_init(struct hnb_gw *gw, const char *stp_host, uint16_t stp_port, const char *local_ip);
+
+const struct osmo_sccp_addr *hnbgw_cn_get_remote_addr(struct hnb_gw *gw, bool is_ps);
diff --git a/include/osmocom/hnbgw/mgw_fsm.h b/include/osmocom/hnbgw/mgw_fsm.h
index 8b14eaa..d4e989d 100644
--- a/include/osmocom/hnbgw/mgw_fsm.h
+++ b/include/osmocom/hnbgw/mgw_fsm.h
@@ -2,6 +2,6 @@
#include <osmocom/ranap/ranap_ies_defs.h>
-int handle_rab_ass_req(struct hnbgw_context_map *map, struct osmo_prim_hdr *oph, ranap_message *message);
-int mgw_fsm_handle_rab_ass_resp(struct hnbgw_context_map *map, struct osmo_prim_hdr *oph, ranap_message *message);
+int handle_rab_ass_req(struct hnbgw_context_map *map, struct msgb *ranap_msg, ranap_message *message);
+int mgw_fsm_handle_rab_ass_resp(struct hnbgw_context_map *map, struct msgb *ranap_msg, ranap_message *message);
int mgw_fsm_release(struct hnbgw_context_map *map);
diff --git a/include/osmocom/hnbgw/ps_rab_ass_fsm.h b/include/osmocom/hnbgw/ps_rab_ass_fsm.h
index 775d73a..0728b0d 100644
--- a/include/osmocom/hnbgw/ps_rab_ass_fsm.h
+++ b/include/osmocom/hnbgw/ps_rab_ass_fsm.h
@@ -9,6 +9,6 @@
PS_RAB_ASS_EV_RAB_FAIL,
};
-int hnbgw_gtpmap_rx_rab_ass_req(struct hnbgw_context_map *map, struct osmo_prim_hdr *oph, ranap_message *message);
-int hnbgw_gtpmap_rx_rab_ass_resp(struct hnbgw_context_map *map, struct osmo_prim_hdr *oph, ranap_message *message);
+int hnbgw_gtpmap_rx_rab_ass_req(struct hnbgw_context_map *map, struct msgb *ranap_msg, ranap_message *message);
+int hnbgw_gtpmap_rx_rab_ass_resp(struct hnbgw_context_map *map, struct msgb *ranap_msg, ranap_message *message);
void hnbgw_gtpmap_release(struct hnbgw_context_map *map);
diff --git a/include/osmocom/hnbgw/tdefs.h b/include/osmocom/hnbgw/tdefs.h
index 8ae1c97..6fee79b 100644
--- a/include/osmocom/hnbgw/tdefs.h
+++ b/include/osmocom/hnbgw/tdefs.h
@@ -4,4 +4,5 @@
extern struct osmo_tdef mgw_fsm_T_defs[];
extern struct osmo_tdef ps_T_defs[];
+extern struct osmo_tdef cmap_T_defs[];
extern struct osmo_tdef_group hnbgw_tdef_group[];
diff --git a/src/osmo-hnbgw/Makefile.am b/src/osmo-hnbgw/Makefile.am
index a6cf5ea..d1179e4 100644
--- a/src/osmo-hnbgw/Makefile.am
+++ b/src/osmo-hnbgw/Makefile.am
@@ -37,6 +37,8 @@
hnbgw_ranap.c \
hnbgw_vty.c \
context_map.c \
+ context_map_rua.c \
+ context_map_sccp.c \
hnbgw_cn.c \
ranap_rab_ass.c \
mgw_fsm.c \
diff --git a/src/osmo-hnbgw/context_map.c b/src/osmo-hnbgw/context_map.c
index 9816918..31f635d 100644
--- a/src/osmo-hnbgw/context_map.c
+++ b/src/osmo-hnbgw/context_map.c
@@ -34,13 +34,24 @@
#include <osmocom/hnbgw/ps_rab_ass_fsm.h>
const struct value_string hnbgw_context_map_state_names[] = {
- {MAP_S_NULL , "not-initialized"},
- {MAP_S_ACTIVE , "active"},
- {MAP_S_RESERVED1, "inactive-reserved"},
- {MAP_S_RESERVED2, "inactive-discard"},
- {0, NULL}
+ { MAP_S_CONNECTING, "connecting" },
+ { MAP_S_ACTIVE, "active" },
+ { MAP_S_DISCONNECTING, "disconnecting" },
+ {}
};
+/* Combine the RUA and SCCP states, for VTY reporting only. */
+enum hnbgw_context_map_state context_map_get_state(struct hnbgw_context_map *map)
+{
+ enum hnbgw_context_map_state rua = map_rua_get_state(map);
+ enum hnbgw_context_map_state sccp = map_sccp_get_state(map);
+ if (rua == MAP_S_ACTIVE && sccp == MAP_S_ACTIVE)
+ return MAP_S_ACTIVE;
+ if (rua == MAP_S_DISCONNECTING || sccp == MAP_S_DISCONNECTING)
+ return MAP_S_DISCONNECTING;
+ return MAP_S_CONNECTING;
+}
+
/* is a given SCCP USER SAP Connection ID in use for a given CN link? */
static int cn_id_in_use(struct hnbgw_cnlink *cn, uint32_t id)
{
@@ -92,11 +103,15 @@
uint32_t new_scu_conn_id;
llist_for_each_entry(map, &hnb->map_list, hnb_list) {
- if (map->state != MAP_S_ACTIVE)
+ if (map->cn_link != cn_if_new)
continue;
- if (map->cn_link != cn_if_new) {
+
+ /* Matching on RUA context id -- only match for RUA context that has not been disconnected yet. If an
+ * inactive context map for a rua_ctx_id is still around, we may have two entries for the same
+ * rua_ctx_id around at the same time. That should only stay until its SCCP side is done releasing. */
+ if (!map_rua_is_active(map))
continue;
- }
+
if (map->rua_ctx_id == rua_ctx_id
&& map->is_ps == is_ps) {
return map;
@@ -113,7 +128,7 @@
/* allocate a new map entry. */
map = talloc_zero(hnb, struct hnbgw_context_map);
- map->state = MAP_S_NULL;
+ map->gw = hnb->gw;
map->cn_link = cn_if_new;
map->hnb_ctx = hnb;
map->rua_ctx_id = rua_ctx_id;
@@ -122,14 +137,43 @@
INIT_LLIST_HEAD(&map->ps_rab_ass);
INIT_LLIST_HEAD(&map->ps_rabs);
+ map_rua_fsm_alloc(map);
+ map_sccp_fsm_alloc(map);
+
/* put it into both lists */
llist_add_tail(&map->hnb_list, &hnb->map_list);
llist_add_tail(&map->cn_list, &cn_if_new->map_list);
- map->state = MAP_S_ACTIVE;
return map;
}
+int _map_rua_dispatch(struct hnbgw_context_map *map, uint32_t event, struct msgb *ranap_msg,
+ const char *file, int line)
+{
+ OSMO_ASSERT(map);
+ if (!map->rua_fi) {
+ LOG_MAP(map, DRUA, LOGL_ERROR, "not ready to receive RUA events\n");
+ return -EINVAL;
+ }
+ return _osmo_fsm_inst_dispatch(map->rua_fi, event, ranap_msg, file, line);
+}
+
+int _map_sccp_dispatch(struct hnbgw_context_map *map, uint32_t event, struct msgb *ranap_msg,
+ const char *file, int line)
+{
+ OSMO_ASSERT(map);
+ if (!map->sccp_fi) {
+ LOG_MAP(map, DRUA, LOGL_ERROR, "not ready to receive SCCP events\n");
+ return -EINVAL;
+ }
+ return _osmo_fsm_inst_dispatch(map->sccp_fi, event, ranap_msg, file, line);
+}
+
+unsigned int msg_has_l2_data(const struct msgb *msg)
+{
+ return msg && msgb_l2(msg) ? msgb_l2len(msg) : 0;
+}
+
/* Map from a CN + Connection ID to HNB + Context ID */
struct hnbgw_context_map *
context_map_by_cn(struct hnbgw_cnlink *cn, uint32_t scu_conn_id)
@@ -137,8 +181,12 @@
struct hnbgw_context_map *map;
llist_for_each_entry(map, &cn->map_list, cn_list) {
- if (map->state != MAP_S_ACTIVE)
+ /* Matching on SCCP conn id -- only match for SCCP conn that has not been disconnected yet. If an
+ * inactive context map for an scu_conn_id is still around, we may have two entries for the same
+ * scu_conn_id around at the same time. That should only stay until its RUA side is done releasing. */
+ if (!map_sccp_is_active(map))
continue;
+
if (map->scu_conn_id == scu_conn_id) {
return map;
}
@@ -152,23 +200,37 @@
void context_map_hnb_released(struct hnbgw_context_map *map)
{
- LOG_MAP(map, DMAIN, LOGL_INFO, "Deactivating\n");
+ /* When a HNB disconnects from RUA, the hnb_context will be freed. This hnbgw_context_map was allocated as a
+ * child of the hnb_context and would also be deallocated along with the hnb_context. However, the SCCP side for
+ * this hnbgw_context_map may still be waiting for a graceful release (SCCP RLC). Move this hnbgw_context_map to
+ * the global hnb_gw talloc ctx, so it can stay around for graceful release / for SCCP timeout.
+ *
+ * We could also always allocate hnbgw_context_map under hnb_gw, but it is nice to see which hnb_context owns
+ * which hnbgw_context_map in a talloc report.
+ */
+ talloc_steal(map->gw, map);
- /* set the state to reserved. We still show up in the list and
- * avoid re-allocation of the context-id until we are cleaned up
- * by the context_map garbage collector timer */
+ /* Tell RUA that the HNB is gone. SCCP release will follow via FSM events. */
+ map_rua_dispatch(map, MAP_RUA_EV_HNB_LINK_LOST, NULL);
+}
- if (map->state != MAP_S_RESERVED2)
- map->state = MAP_S_RESERVED1;
-
- /* Is SCCP still active and needs to be disconnected ungracefully? */
- if (map->scu_conn_active) {
- osmo_sccp_tx_disconn(map->hnb_ctx->gw->sccp.cnlink->sccp_user, map->scu_conn_id, NULL, 0);
- map->scu_conn_active = false;
+void context_map_free(struct hnbgw_context_map *map)
+{
+ /* guard against FSM termination infinitely looping back here */
+ if (map->deallocating) {
+ LOG_MAP(map, DMAIN, LOGL_DEBUG, "context_map_free(): already deallocating\n");
+ return;
}
+ map->deallocating = true;
- /* a possibly still existing MGW FSM must be terminated when the context
- * map is deactivated. (this is a cornercase) */
+ if (map->rua_fi)
+ osmo_fsm_inst_term(map->rua_fi, OSMO_FSM_TERM_REGULAR, NULL);
+ OSMO_ASSERT(map->rua_fi == NULL);
+
+ if (map->sccp_fi)
+ osmo_fsm_inst_term(map->sccp_fi, OSMO_FSM_TERM_REGULAR, NULL);
+ OSMO_ASSERT(map->sccp_fi == NULL);
+
if (map->mgw_fi) {
mgw_fsm_release(map);
OSMO_ASSERT(map->mgw_fi == NULL);
@@ -177,46 +239,21 @@
#if ENABLE_PFCP
hnbgw_gtpmap_release(map);
#endif
+
+ if (map->cn_link)
+ llist_del(&map->cn_list);
+ if (map->hnb_ctx)
+ llist_del(&map->hnb_list);
+
+ LOG_MAP(map, DMAIN, LOGL_INFO, "Deallocating\n");
+ talloc_free(map);
}
-static struct osmo_timer_list context_map_tmr;
-
-static void context_map_tmr_cb(void *data)
+void context_map_check_released(struct hnbgw_context_map *map)
{
- struct hnb_gw *gw = data;
- struct hnbgw_cnlink *cn = gw->sccp.cnlink;
- struct hnbgw_context_map *map, *next_map;
-
- DEBUGP(DMAIN, "Running context mapper garbage collection\n");
- llist_for_each_entry_safe(map, next_map, &cn->map_list, cn_list) {
- switch (map->state) {
- case MAP_S_RESERVED1:
- /* first time we see this reserved
- * entry: mark it for stage 2 */
- map->state = MAP_S_RESERVED2;
- break;
- case MAP_S_RESERVED2:
- /* second time we see this reserved
- * entry: remove it */
- LOG_MAP(map, DMAIN, LOGL_INFO, "Deallocating\n");
- map->state = MAP_S_NULL;
- llist_del(&map->cn_list);
- llist_del(&map->hnb_list);
- talloc_free(map);
- break;
- default:
- break;
- }
+ if (map_rua_is_active(map) || map_sccp_is_active(map)) {
+ /* still active, do not release yet. */
+ return;
}
- /* re-schedule this timer */
- osmo_timer_schedule(&context_map_tmr, EXPIRY_TIMER_SECS, 0);
-}
-
-int context_map_init(struct hnb_gw *gw)
-{
- context_map_tmr.cb = context_map_tmr_cb;
- context_map_tmr.data = gw;
- osmo_timer_schedule(&context_map_tmr, EXPIRY_TIMER_SECS, 0);
-
- return 0;
+ context_map_free(map);
}
diff --git a/src/osmo-hnbgw/context_map_rua.c b/src/osmo-hnbgw/context_map_rua.c
new file mode 100644
index 0000000..25304d9
--- /dev/null
+++ b/src/osmo-hnbgw/context_map_rua.c
@@ -0,0 +1,361 @@
+/* RUA side FSM of hnbgw_context_map */
+/* (C) 2023 by sysmocom - s.m.f.c. GmbH <info(a)sysmocom.de>
+ * All Rights Reserved
+ *
+ * SPDX-License-Identifier: AGPL-3.0+
+ *
+ * Author: Neels Hofmeyr
+ *
+ * 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 <osmocom/core/utils.h>
+#include <osmocom/core/fsm.h>
+
+#include <osmocom/ranap/ranap_common_cn.h>
+
+#include <osmocom/hnbgw/context_map.h>
+#include <osmocom/hnbgw/tdefs.h>
+#include <osmocom/hnbgw/hnbgw_rua.h>
+#include <osmocom/hnbgw/mgw_fsm.h>
+
+enum map_rua_fsm_state {
+ MAP_RUA_ST_INIT,
+ MAP_RUA_ST_CONNECTED,
+ MAP_RUA_ST_DISCONNECTED,
+};
+
+static const struct value_string map_rua_fsm_event_names[] = {
+ OSMO_VALUE_STRING(MAP_RUA_EV_RX_CONNECT),
+ OSMO_VALUE_STRING(MAP_RUA_EV_RX_DIRECT_TRANSFER),
+ OSMO_VALUE_STRING(MAP_RUA_EV_RX_DISCONNECT),
+ OSMO_VALUE_STRING(MAP_RUA_EV_TX_DIRECT_TRANSFER),
+ OSMO_VALUE_STRING(MAP_RUA_EV_CN_DISC),
+ OSMO_VALUE_STRING(MAP_RUA_EV_HNB_LINK_LOST),
+ {}
+};
+
+static struct osmo_fsm map_rua_fsm;
+
+static const struct osmo_tdef_state_timeout map_rua_fsm_timeouts[32] = {
+ [MAP_RUA_ST_INIT] = { .T = -31 },
+ [MAP_RUA_ST_DISCONNECTED] = { .T = -31 },
+};
+
+/* Transition to a state, using the T timer defined in map_rua_fsm_timeouts.
+ * Assumes local variable fi exists. */
+#define map_rua_fsm_state_chg(state) \
+ OSMO_ASSERT(osmo_tdef_fsm_inst_state_chg(fi, state, \
+ map_rua_fsm_timeouts, \
+ cmap_T_defs, \
+ 5) == 0)
+
+void map_rua_fsm_alloc(struct hnbgw_context_map *map)
+{
+ struct osmo_fsm_inst *fi = osmo_fsm_inst_alloc(&map_rua_fsm, map, map, LOGL_DEBUG, NULL);
+ OSMO_ASSERT(fi);
+ osmo_fsm_inst_update_id_f_sanitize(fi, '-', "%s-RUA-%u", hnb_context_name(map->hnb_ctx), map->rua_ctx_id);
+
+ OSMO_ASSERT(map->rua_fi == NULL);
+ map->rua_fi = fi;
+
+ /* trigger the timeout */
+ map_rua_fsm_state_chg(MAP_RUA_ST_INIT);
+}
+
+enum hnbgw_context_map_state map_rua_get_state(struct hnbgw_context_map *map)
+{
+ if (!map || !map->rua_fi)
+ return MAP_S_DISCONNECTING;
+ switch (map->rua_fi->state) {
+ case MAP_RUA_ST_INIT:
+ return MAP_S_CONNECTING;
+ case MAP_RUA_ST_CONNECTED:
+ return MAP_S_ACTIVE;
+ default:
+ case MAP_RUA_ST_DISCONNECTED:
+ return MAP_S_DISCONNECTING;
+ }
+}
+
+bool map_rua_is_active(struct hnbgw_context_map *map)
+{
+ if (!map || !map->rua_fi)
+ return false;
+ switch (map->rua_fi->state) {
+ case MAP_RUA_ST_DISCONNECTED:
+ return false;
+ default:
+ return true;
+ }
+}
+
+static int map_rua_fsm_timer_cb(struct osmo_fsm_inst *fi)
+{
+ /* Return 1 to terminate FSM instance, 0 to keep running */
+ switch (fi->state) {
+ default:
+ map_rua_fsm_state_chg(MAP_RUA_ST_DISCONNECTED);
+ return 0;
+
+ case MAP_RUA_ST_DISCONNECTED:
+ return 1;
+ }
+}
+
+static int destruct_ranap_cn_rx_co_ies(ranap_message *ranap_message_p)
+{
+ ranap_cn_rx_co_free(ranap_message_p);
+ return 0;
+}
+
+/* Dispatch RANAP message to SCCP, if any. */
+static int handle_rx_rua(struct hnbgw_context_map *map, struct msgb *ranap_msg)
+{
+ int rc;
+ if (!msg_has_l2_data(ranap_msg))
+ return 0;
+
+ /* See if it is a RAB Assignment Response message from RUA to SCCP, where we need to change the user plane
+ * information, for RTP mapping via MGW, or GTP mapping via UPF. */
+ if (!map->is_ps) {
+ ranap_message *message = talloc_zero(OTC_SELECT, ranap_message);
+ rc = ranap_cn_rx_co_decode2(message, msgb_l2(ranap_msg), msgb_l2len(ranap_msg));
+ if (rc == 0) {
+ talloc_set_destructor(message, destruct_ranap_cn_rx_co_ies);
+
+ switch (message->procedureCode) {
+ case RANAP_ProcedureCode_id_RAB_Assignment:
+ /* mgw_fsm_handle_rab_ass_resp() takes ownership of prim->oph and (ranap) message */
+ return mgw_fsm_handle_rab_ass_resp(map, ranap_msg, message);
+ }
+ }
+#if ENABLE_PFCP
+ } else if (hnb_gw_is_gtp_mapping_enabled(map->hnb_gw)) {
+ /* map->is_ps == true and PFCP is enabled in osmo-hnbgw.cfg */
+ ranap_message *message = talloc_zero(OTC_SELECT, ranap_message);
+ rc = ranap_cn_rx_co_decode2(message, msgb_l2(ranap_msg), msgb_l2len(ranap_msg));
+ if (rc == 0) {
+ talloc_set_destructor(message, destruct_ranap_cn_rx_co_ies);
+
+ switch (message->procedureCode) {
+ case RANAP_ProcedureCode_id_RAB_Assignment:
+ /* ps_rab_ass_fsm takes ownership of prim->oph and RANAP message */
+ return hnbgw_gtpmap_rx_rab_ass_resp(map, ranap_msg, message);
+ }
+ }
+#endif
+ }
+
+ /* It was not a RAB Assignment Response that needed to be intercepted. Forward as-is to SCCP. */
+ return map_sccp_dispatch(map, MAP_SCCP_EV_TX_DATA_REQUEST, ranap_msg);
+}
+
+static int forward_ranap_to_rua(struct hnbgw_context_map *map, struct msgb *ranap_msg)
+{
+ int rc;
+
+ if (!msg_has_l2_data(ranap_msg))
+ return 0;
+
+ if (!map->hnb_ctx) {
+ LOGPFSML(map->rua_fi, LOGL_ERROR, "Cannot transmit RUA DirectTransfer: HNB has disconnected\n");
+ return -ENOTCONN;
+ }
+
+ rc = rua_tx_dt(map->hnb_ctx, map->is_ps, map->rua_ctx_id, msgb_l2(ranap_msg), msgb_l2len(ranap_msg));
+ if (rc)
+ LOGPFSML(map->rua_fi, LOGL_ERROR, "Failed to transmit RUA DirectTransfer to HNB\n");
+ return rc;
+}
+
+static void map_rua_init_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ struct hnbgw_context_map *map = fi->priv;
+ struct msgb *ranap_msg = data;
+
+ switch (event) {
+
+ case MAP_RUA_EV_RX_CONNECT:
+ map_rua_fsm_state_chg(MAP_RUA_ST_CONNECTED);
+ /* The Connect will never be a RAB Assignment response, so no need for handle_rx_rua() (which decodes
+ * the RANAP message to detect a RAB Assignment response). Just forward to SCCP as is. */
+ map_sccp_dispatch(map, MAP_SCCP_EV_TX_DATA_REQUEST, ranap_msg);
+ return;
+
+ case MAP_RUA_EV_RX_DISCONNECT:
+ case MAP_RUA_EV_CN_DISC:
+ case MAP_RUA_EV_HNB_LINK_LOST:
+ /* Unlikely that SCCP is active, but let the SCCP FSM decide about that. */
+ handle_rx_rua(map, ranap_msg);
+ /* There is a reason to shut down this RUA connection. Super unlikely, we haven't even processed the
+ * MAP_RUA_EV_RX_CONNECT that created this FSM. Semantically, RUA is not connected, so we can
+ * directly go to MAP_RUA_ST_DISCONNECTED. */
+ map_rua_fsm_state_chg(MAP_RUA_ST_DISCONNECTED);
+ break;
+
+ default:
+ OSMO_ASSERT(false);
+ }
+}
+
+static void map_rua_tx_disconnect(struct osmo_fsm_inst *fi)
+{
+ struct hnbgw_context_map *map = fi->priv;
+ RUA_Cause_t rua_cause;
+
+ if (!map->hnb_ctx || !map->hnb_ctx->conn) {
+ /* HNB already disconnected, nothing to do. */
+ LOGPFSML(fi, LOGL_NOTICE, "HNB vanished, this RUA context cannot disconnect gracefully\n");
+ return;
+ }
+
+ /* Send Disconnect to RUA without RANAP data. */
+ rua_cause = (RUA_Cause_t){
+ .present = RUA_Cause_PR_radioNetwork,
+ .choice.radioNetwork = RUA_CauseRadioNetwork_network_release,
+ };
+ if (rua_tx_disc(map->hnb_ctx, map->is_ps, map->rua_ctx_id, &rua_cause, NULL, 0))
+ LOGPFSML(fi, LOGL_ERROR, "Failed to send Disconnect to RUA\n");
+}
+
+static void map_rua_connected_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ struct hnbgw_context_map *map = fi->priv;
+ struct msgb *ranap_msg = data;
+
+ switch (event) {
+
+ case MAP_RUA_EV_RX_DIRECT_TRANSFER:
+ /* received DirectTransfer from RUA, forward to SCCP */
+ handle_rx_rua(map, ranap_msg);
+ return;
+
+ case MAP_RUA_EV_TX_DIRECT_TRANSFER:
+ /* Someone (usually the SCCP side) wants us to send a RANAP payload to HNB via RUA */
+ forward_ranap_to_rua(map, ranap_msg);
+ return;
+
+ case MAP_RUA_EV_RX_DISCONNECT:
+ /* received Disconnect from RUA. forward any payload to SCCP, and change state. */
+ if (!map_sccp_is_active(map)) {
+ /* If, unlikely, the SCCP is already gone, changing to MAP_RUA_ST_DISCONNECTED frees the
+ * hnbgw_context_map. Avoid a use-after-free. */
+ map_rua_fsm_state_chg(MAP_RUA_ST_DISCONNECTED);
+ return;
+ }
+ map_rua_fsm_state_chg(MAP_RUA_ST_DISCONNECTED);
+ handle_rx_rua(map, ranap_msg);
+ return;
+
+ case MAP_RUA_EV_HNB_LINK_LOST:
+ /* The HNB is gone. Cannot gracefully cleanup the RUA connection, just be gone. */
+ map_rua_fsm_state_chg(MAP_RUA_ST_DISCONNECTED);
+ return;
+
+ case MAP_RUA_EV_CN_DISC:
+ /* There is a disruptive reason to shut down this RUA connection, HNB is still there */
+ OSMO_ASSERT(data == NULL);
+ map_rua_tx_disconnect(fi);
+ map_rua_fsm_state_chg(MAP_RUA_ST_DISCONNECTED);
+ return;
+
+ default:
+ OSMO_ASSERT(false);
+ }
+}
+
+static void map_rua_disconnected_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct hnbgw_context_map *map = fi->priv;
+ /* For sanity, always tell SCCP to disconnect, if it hasn't done so. Dispatching MAP_SCCP_EV_RAN_DISC may send
+ * SCCP into MAP_RUA_ST_DISCONNECTED, which calls context_map_check_released() and frees the hnbgw_context_map,
+ * so don't free it a second time. If SCCP stays active, calling context_map_check_released() has no effect. */
+ if (map_sccp_is_active(map))
+ map_sccp_dispatch(map, MAP_SCCP_EV_RAN_DISC, NULL);
+ else
+ context_map_check_released(map);
+}
+
+static void map_rua_disconnected_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ struct msgb *ranap_msg = data;
+ if (msg_has_l2_data(ranap_msg))
+ LOGPFSML(fi, LOGL_ERROR, "RUA not connected, cannot dispatch RANAP message\n");
+}
+
+void map_rua_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause)
+{
+ struct hnbgw_context_map *map = fi->priv;
+ map->rua_fi = NULL;
+ context_map_check_released(map);
+}
+
+#define S(x) (1 << (x))
+
+static const struct osmo_fsm_state map_rua_fsm_states[] = {
+ [MAP_RUA_ST_INIT] = {
+ .name = "init",
+ .in_event_mask = 0
+ | S(MAP_RUA_EV_RX_CONNECT)
+ | S(MAP_RUA_EV_RX_DISCONNECT)
+ | S(MAP_RUA_EV_CN_DISC)
+ | S(MAP_RUA_EV_HNB_LINK_LOST)
+ ,
+ .out_state_mask = 0
+ | S(MAP_RUA_ST_INIT)
+ | S(MAP_RUA_ST_CONNECTED)
+ | S(MAP_RUA_ST_DISCONNECTED)
+ ,
+ .action = map_rua_init_action,
+ },
+ [MAP_RUA_ST_CONNECTED] = {
+ .name = "connected",
+ .in_event_mask = 0
+ | S(MAP_RUA_EV_RX_DIRECT_TRANSFER)
+ | S(MAP_RUA_EV_TX_DIRECT_TRANSFER)
+ | S(MAP_RUA_EV_RX_DISCONNECT)
+ | S(MAP_RUA_EV_CN_DISC)
+ | S(MAP_RUA_EV_HNB_LINK_LOST)
+ ,
+ .out_state_mask = 0
+ | S(MAP_RUA_ST_DISCONNECTED)
+ ,
+ .action = map_rua_connected_action,
+ },
+ [MAP_RUA_ST_DISCONNECTED] = {
+ .name = "disconnected",
+ .in_event_mask = 0
+ | S(MAP_RUA_EV_CN_DISC)
+ | S(MAP_RUA_EV_HNB_LINK_LOST)
+ ,
+ .onenter = map_rua_disconnected_onenter,
+ .action = map_rua_disconnected_action,
+ },
+};
+
+static struct osmo_fsm map_rua_fsm = {
+ .name = "map_rua",
+ .states = map_rua_fsm_states,
+ .num_states = ARRAY_SIZE(map_rua_fsm_states),
+ .log_subsys = DHNB,
+ .event_names = map_rua_fsm_event_names,
+ .timer_cb = map_rua_fsm_timer_cb,
+ .cleanup = map_rua_fsm_cleanup,
+};
+
+static __attribute__((constructor)) void map_rua_fsm_register(void)
+{
+ OSMO_ASSERT(osmo_fsm_register(&map_rua_fsm) == 0);
+}
diff --git a/src/osmo-hnbgw/context_map_sccp.c b/src/osmo-hnbgw/context_map_sccp.c
new file mode 100644
index 0000000..3042636
--- /dev/null
+++ b/src/osmo-hnbgw/context_map_sccp.c
@@ -0,0 +1,546 @@
+/* SCCP side FSM of hnbgw_context_map */
+/* (C) 2023 by sysmocom - s.m.f.c. GmbH <info(a)sysmocom.de>
+ * All Rights Reserved
+ *
+ * SPDX-License-Identifier: AGPL-3.0+
+ *
+ * Author: Neels Hofmeyr
+ *
+ * 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 <osmocom/core/utils.h>
+#include <osmocom/core/fsm.h>
+
+#include <osmocom/sigtran/sccp_helpers.h>
+
+#include <osmocom/ranap/ranap_common_ran.h>
+
+#include <osmocom/hnbgw/hnbgw_cn.h>
+#include <osmocom/hnbgw/context_map.h>
+#include <osmocom/hnbgw/tdefs.h>
+#include <osmocom/hnbgw/mgw_fsm.h>
+
+enum map_sccp_fsm_state {
+ MAP_SCCP_ST_INIT,
+ MAP_SCCP_ST_WAIT_CC,
+ MAP_SCCP_ST_CONNECTED,
+ MAP_SCCP_ST_WAIT_RLSD,
+ MAP_SCCP_ST_DISCONNECTED,
+};
+
+static const struct value_string map_sccp_fsm_event_names[] = {
+ OSMO_VALUE_STRING(MAP_SCCP_EV_RX_CONNECTION_CONFIRM),
+ OSMO_VALUE_STRING(MAP_SCCP_EV_RX_DATA_INDICATION),
+ OSMO_VALUE_STRING(MAP_SCCP_EV_TX_DATA_REQUEST),
+ OSMO_VALUE_STRING(MAP_SCCP_EV_RAN_DISC),
+ OSMO_VALUE_STRING(MAP_SCCP_EV_RX_RELEASED),
+ {}
+};
+
+static struct osmo_fsm map_sccp_fsm;
+
+static const struct osmo_tdef_state_timeout map_sccp_fsm_timeouts[32] = {
+ [MAP_SCCP_ST_INIT] = { .T = -31 },
+ [MAP_SCCP_ST_WAIT_CC] = { .T = -31 },
+ [MAP_SCCP_ST_CONNECTED] = { .T = 0 },
+ [MAP_SCCP_ST_WAIT_RLSD] = { .T = -31 },
+ [MAP_SCCP_ST_DISCONNECTED] = { .T = -31 },
+};
+
+/* Transition to a state, using the T timer defined in map_sccp_fsm_timeouts.
+ * Assumes local variable fi exists. */
+#define map_sccp_fsm_state_chg(state) \
+ OSMO_ASSERT(osmo_tdef_fsm_inst_state_chg(fi, state, \
+ map_sccp_fsm_timeouts, \
+ cmap_T_defs, \
+ 5) == 0)
+
+void map_sccp_fsm_alloc(struct hnbgw_context_map *map)
+{
+ struct osmo_fsm_inst *fi = osmo_fsm_inst_alloc(&map_sccp_fsm, map, map, LOGL_DEBUG, NULL);
+ OSMO_ASSERT(fi);
+ osmo_fsm_inst_update_id_f_sanitize(fi, '-', "%s-SCCP-%u", hnb_context_name(map->hnb_ctx), map->scu_conn_id);
+
+ OSMO_ASSERT(map->sccp_fi == NULL);
+ map->sccp_fi = fi;
+
+ /* trigger the timeout */
+ map_sccp_fsm_state_chg(MAP_SCCP_ST_INIT);
+}
+
+enum hnbgw_context_map_state map_sccp_get_state(struct hnbgw_context_map *map)
+{
+ if (!map || !map->sccp_fi)
+ return MAP_S_DISCONNECTING;
+ switch (map->sccp_fi->state) {
+ case MAP_SCCP_ST_INIT:
+ case MAP_SCCP_ST_WAIT_CC:
+ return MAP_S_CONNECTING;
+ case MAP_SCCP_ST_CONNECTED:
+ return MAP_S_ACTIVE;
+ default:
+ case MAP_SCCP_ST_WAIT_RLSD:
+ case MAP_SCCP_ST_DISCONNECTED:
+ return MAP_S_DISCONNECTING;
+ }
+}
+
+bool map_sccp_is_active(struct hnbgw_context_map *map)
+{
+ if (!map || !map->sccp_fi)
+ return false;
+ switch (map->sccp_fi->state) {
+ case MAP_SCCP_ST_DISCONNECTED:
+ return false;
+ default:
+ return true;
+ }
+}
+
+static int tx_sccp_cr(struct osmo_fsm_inst *fi, struct msgb *ranap_msg)
+{
+ struct hnbgw_context_map *map = fi->priv;
+ struct osmo_scu_prim *prim;
+ int rc;
+
+ if (!ranap_msg) {
+ /* prepare a msgb to send an empty N-Connect prim (but this should never happen in practice) */
+ ranap_msg = hnbgw_ranap_msg_alloc("SCCP-CR-empty");
+ }
+
+ prim = (struct osmo_scu_prim *)msgb_push(ranap_msg, sizeof(*prim));
+ osmo_prim_init(&prim->oph, SCCP_SAP_USER, OSMO_SCU_PRIM_N_CONNECT, PRIM_OP_REQUEST, ranap_msg);
+ prim->u.connect.called_addr = *hnbgw_cn_get_remote_addr(map->gw, map->is_ps);
+ prim->u.connect.calling_addr = map->gw->sccp.local_addr;
+ prim->u.connect.sccp_class = 2;
+ prim->u.connect.conn_id = map->scu_conn_id;
+
+ rc = osmo_sccp_user_sap_down_nofree(map->cn_link->sccp_user, &prim->oph);
+ if (rc)
+ LOGPFSML(fi, LOGL_ERROR, "Failed to forward SCCP Connectoin Request to CN\n");
+ return rc;
+}
+
+static int tx_sccp_df1(struct osmo_fsm_inst *fi, struct msgb *ranap_msg)
+{
+ struct hnbgw_context_map *map = fi->priv;
+ struct osmo_scu_prim *prim;
+ int rc;
+
+ if (!msg_has_l2_data(ranap_msg))
+ return 0;
+
+ prim = (struct osmo_scu_prim *)msgb_push(ranap_msg, sizeof(*prim));
+ osmo_prim_init(&prim->oph, SCCP_SAP_USER, OSMO_SCU_PRIM_N_DATA, PRIM_OP_REQUEST, ranap_msg);
+ prim->u.data.conn_id = map->scu_conn_id;
+
+ rc = osmo_sccp_user_sap_down_nofree(map->cn_link->sccp_user, &prim->oph);
+ if (rc)
+ LOGPFSML(fi, LOGL_ERROR, "Failed to forward SCCP Data Form 1 to CN\n");
+ return rc;
+}
+
+static int tx_sccp_rlsd(struct osmo_fsm_inst *fi)
+{
+ struct hnbgw_context_map *map = fi->priv;
+ return osmo_sccp_tx_disconn(map->cn_link->sccp_user, map->scu_conn_id, NULL, 0);
+}
+
+static int destruct_ranap_ran_rx_co_ies(ranap_message *ranap_message_p)
+{
+ ranap_ran_rx_co_free(ranap_message_p);
+ return 0;
+}
+
+static int handle_rx_sccp(struct osmo_fsm_inst *fi, struct msgb *ranap_msg)
+{
+ struct hnbgw_context_map *map = fi->priv;
+ int rc;
+
+ /* When there was no message received along with the received event, then there is nothing to forward to RUA. */
+ if (!msg_has_l2_data(ranap_msg))
+ return 0;
+
+ /* See if it is a RAB Assignment Request message from SCCP to RUA, where we need to change the user plane
+ * information, for RTP mapping via MGW, or GTP mapping via UPF. */
+ if (!map->is_ps) {
+ ranap_message *message;
+ /* Circuit-Switched. Set up mapping of RTP ports via MGW */
+ message = talloc_zero(OTC_SELECT, ranap_message);
+ rc = ranap_ran_rx_co_decode(message, message, msgb_l2(ranap_msg), msgb_l2len(ranap_msg));
+
+ if (rc == 0) {
+ talloc_set_destructor(message, destruct_ranap_ran_rx_co_ies);
+
+ switch (message->procedureCode) {
+ case RANAP_ProcedureCode_id_RAB_Assignment:
+ /* mgw_fsm_alloc_and_handle_rab_ass_req() takes ownership of (ranap) message */
+ return handle_rab_ass_req(map, ranap_msg, message);
+ case RANAP_ProcedureCode_id_Iu_Release:
+ /* Any IU Release will terminate the MGW FSM, the message itsself is not passed to the
+ * FSM code. It is just forwarded normally by map_rua_tx_dt() below. */
+ mgw_fsm_release(map);
+ break;
+ }
+ }
+#if ENABLE_PFCP
+ } else {
+ ranap_message *message;
+ struct hnb_gw *hnb_gw = cnlink->gw;
+ /* Packet-Switched. Set up mapping of GTP ports via UPF */
+ message = talloc_zero(OTC_SELECT, ranap_message);
+ rc = ranap_ran_rx_co_decode(message, message, msgb_l2(ranap_msg), msgb_l2len(ranap_msg));
+
+ if (rc == 0) {
+ talloc_set_destructor(message, destruct_ranap_ran_rx_co_ies);
+
+ switch (message->procedureCode) {
+
+ case RANAP_ProcedureCode_id_RAB_Assignment:
+ /* If a UPF is configured, handle the RAB Assignment via ps_rab_ass_fsm, and replace the
+ * GTP F-TEIDs in the RAB Assignment message before passing it on to RUA. */
+ if (hnb_gw_is_gtp_mapping_enabled(hnb_gw)) {
+ LOGP(DMAIN, LOGL_DEBUG,
+ "RAB Assignment: setting up GTP tunnel mapping via UPF %s\n",
+ osmo_sockaddr_to_str_c(OTC_SELECT, &hnb_gw->pfcp.cp_peer->remote_addr));
+ return hnbgw_gtpmap_rx_rab_ass_req(map, ranap_msg, message);
+ }
+ /* If no UPF is configured, directly forward the message as-is (no GTP mapping). */
+ LOGP(DMAIN, LOGL_DEBUG, "RAB Assignment: no UPF configured, forwarding as-is\n");
+ break;
+
+ case RANAP_ProcedureCode_id_Iu_Release:
+ /* Any IU Release will terminate the MGW FSM, the message itsself is not passed to the
+ * FSM code. It is just forwarded normally by map_rua_tx_dt() below. */
+ hnbgw_gtpmap_release(map);
+ break;
+ }
+ }
+#endif
+ }
+
+ /* It was not a RAB Assignment Request that needed to be intercepted. Forward as-is to RUA. */
+ return map_rua_dispatch(map, MAP_RUA_EV_TX_DIRECT_TRANSFER, ranap_msg);
+}
+
+static void map_sccp_init_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ struct hnbgw_context_map *map = fi->priv;
+ struct msgb *ranap_msg = data;
+
+ switch (event) {
+
+ case MAP_SCCP_EV_TX_DATA_REQUEST:
+ /* In the INIT state, the first MAP_SCCP_EV_TX_DATA_REQUEST will be the RANAP message received from the
+ * RUA Connect message. Send the SCCP CR and transition to WAIT_CC. */
+ if (tx_sccp_cr(fi, ranap_msg) == 0)
+ map_sccp_fsm_state_chg(MAP_SCCP_ST_WAIT_CC);
+ return;
+
+ case MAP_SCCP_EV_RAN_DISC:
+ /* No CR has been sent yet, just go to disconnected state. */
+ if (msg_has_l2_data(ranap_msg))
+ LOG_MAP(map, DLSCCP, LOGL_ERROR, "SCCP not connected, cannot dispatch RANAP message\n");
+ map_sccp_fsm_state_chg(MAP_SCCP_ST_DISCONNECTED);
+ return;
+
+ case MAP_SCCP_EV_RX_RELEASED:
+ /* SCCP RLSD received from CN. This will never happen since we haven't even asked for a connection, but
+ * for completeness: */
+ map_sccp_fsm_state_chg(MAP_SCCP_ST_DISCONNECTED);
+ return;
+
+ default:
+ OSMO_ASSERT(false);
+ }
+}
+
+static void map_sccp_wait_cc_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ struct hnbgw_context_map *map = fi->priv;
+ struct msgb *ranap_msg = data;
+
+ switch (event) {
+
+ case MAP_SCCP_EV_RX_CONNECTION_CONFIRM:
+ map_sccp_fsm_state_chg(MAP_SCCP_ST_CONNECTED);
+ /* Usually doesn't but if the SCCP CC contained data, forward it to RUA */
+ handle_rx_sccp(fi, ranap_msg);
+ return;
+
+ case MAP_SCCP_EV_TX_DATA_REQUEST:
+ LOGPFSML(fi, LOGL_ERROR, "Connection not yet confirmed, cannot forward RANAP to CN\n");
+ return;
+
+ case MAP_SCCP_EV_RAN_DISC:
+ /* RUA connection was terminated. First wait for the CC before releasing the SCCP conn. */
+ if (msg_has_l2_data(ranap_msg))
+ LOGPFSML(fi, LOGL_ERROR, "Connection not yet confirmed, cannot forward RANAP to CN\n");
+ map->please_disconnect = true;
+ return;
+
+ case MAP_SCCP_EV_RX_RELEASED:
+ /* SCCP RLSD received from CN. This will never happen since we haven't even received a Connection
+ * Confirmed, but for completeness: */
+ handle_rx_sccp(fi, ranap_msg);
+ map_sccp_fsm_state_chg(MAP_SCCP_ST_DISCONNECTED);
+ return;
+
+ default:
+ OSMO_ASSERT(false);
+ }
+}
+
+static void map_sccp_connected_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct hnbgw_context_map *map = fi->priv;
+ if (map->please_disconnect) {
+ /* SCCP has already been asked to disconnect, so disconnect now that the CC has been received. Send RLSD
+ * to SCCP (without RANAP data) */
+ tx_sccp_rlsd(fi);
+ map_sccp_fsm_state_chg(MAP_SCCP_ST_DISCONNECTED);
+ }
+}
+
+static void map_sccp_connected_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ struct msgb *ranap_msg = data;
+
+ switch (event) {
+
+ case MAP_SCCP_EV_RX_DATA_INDICATION:
+ /* forward RANAP from SCCP to RUA */
+ handle_rx_sccp(fi, ranap_msg);
+ return;
+
+ case MAP_SCCP_EV_TX_DATA_REQUEST:
+ /* Someone (usually the RUA side) wants us to send a RANAP payload to CN via SCCP */
+ tx_sccp_df1(fi, ranap_msg);
+ return;
+
+ case MAP_SCCP_EV_RAN_DISC:
+ /* RUA has disconnected, and usually has sent an Iu-ReleaseComplete along with its RUA Disconnect. On
+ * SCCP, the Iu-ReleaseComplete should still be forwarded as N-Data (SCCP Data Form 1), and we will
+ * expect the CN to send an SCCP RLSD soon. */
+ map_sccp_fsm_state_chg(MAP_SCCP_ST_WAIT_RLSD);
+ tx_sccp_df1(fi, ranap_msg);
+ return;
+
+ case MAP_SCCP_EV_RX_RELEASED:
+ /* The CN sends an N-Disconnect (SCCP Released) out of the usual sequence. Not what we expected, but
+ * handle it. */
+ LOGPFSML(fi, LOGL_ERROR, "CN sends SCCP Released sooner than expected\n");
+ handle_rx_sccp(fi, ranap_msg);
+ map_sccp_fsm_state_chg(MAP_SCCP_ST_DISCONNECTED);
+ return;
+
+ case MAP_SCCP_EV_RX_CONNECTION_CONFIRM:
+ /* Already connected. Unusual, but if there is data just forward it. */
+ LOGPFSML(fi, LOGL_ERROR, "Already connected, but received SCCP CC again\n");
+ handle_rx_sccp(fi, ranap_msg);
+ return;
+
+ default:
+ OSMO_ASSERT(false);
+ }
+}
+
+static void map_sccp_wait_rlsd_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct hnbgw_context_map *map = fi->priv;
+ /* For sanity, always tell RUA to disconnect, if it hasn't done so. */
+ if (map_rua_is_active(map))
+ map_rua_dispatch(map, MAP_RUA_EV_CN_DISC, NULL);
+}
+
+static void map_sccp_wait_rlsd_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ struct msgb *ranap_msg = data;
+
+ switch (event) {
+
+ case MAP_SCCP_EV_RX_RELEASED:
+ /* The CN sends the expected SCCP RLSD.
+ * Usually there is no data, but if there is just forward it.
+ * Usually RUA is already disconnected, but let the RUA FSM decide about that. */
+ handle_rx_sccp(fi, ranap_msg);
+ map_sccp_fsm_state_chg(MAP_SCCP_ST_DISCONNECTED);
+ return;
+
+ case MAP_SCCP_EV_RX_DATA_INDICATION:
+ /* RUA is probably already disconnected, but let the RUA FSM decide about that. */
+ handle_rx_sccp(fi, ranap_msg);
+ return;
+
+ case MAP_SCCP_EV_TX_DATA_REQUEST:
+ case MAP_SCCP_EV_RAN_DISC:
+ /* Normally, RUA would already disconnected, but since SCCP is officially still connected, we can still
+ * forward messages there. Already waiting for CN to send the SCCP RLSD. If there is a message, forward
+ * it, and just continue to time out on the SCCP RLSD. */
+ tx_sccp_df1(fi, ranap_msg);
+ return;
+
+ case MAP_SCCP_EV_RX_CONNECTION_CONFIRM:
+ /* Already connected. Unusual, but if there is data just forward it. */
+ LOGPFSML(fi, LOGL_ERROR, "Already connected, but received SCCP CC\n");
+ handle_rx_sccp(fi, ranap_msg);
+ return;
+
+ default:
+ OSMO_ASSERT(false);
+ }
+}
+
+static void map_sccp_disconnected_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct hnbgw_context_map *map = fi->priv;
+ /* For sanity, always tell RUA to disconnect, if it hasn't done so. Dispatching MAP_RUA_EV_CN_DISC may send
+ * RUA into MAP_RUA_ST_DISCONNECTED, which calls context_map_check_released() and frees the hnbgw_context_map,
+ * so don't free it a second time. If RUA stays active, calling context_map_check_released() has no effect. */
+ if (map_rua_is_active(map))
+ map_rua_dispatch(map, MAP_RUA_EV_CN_DISC, NULL);
+ else
+ context_map_check_released(map);
+}
+
+static void map_sccp_disconnected_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ struct msgb *ranap_msg = data;
+
+ if (msg_has_l2_data(ranap_msg))
+ LOGPFSML(fi, LOGL_ERROR, "SCCP not connected, cannot dispatch RANAP message\n");
+}
+
+static int map_sccp_fsm_timer_cb(struct osmo_fsm_inst *fi)
+{
+ struct hnbgw_context_map *map = fi->priv;
+
+ /* Return 1 to terminate FSM instance, 0 to keep running */
+ switch (fi->state) {
+ case MAP_SCCP_ST_INIT:
+ case MAP_SCCP_ST_WAIT_CC:
+ /* cannot sent SCCP RLSD, because the other side hasn't responded with the remote reference. */
+ map_sccp_fsm_state_chg(MAP_SCCP_ST_DISCONNECTED);
+ return 0;
+
+ case MAP_SCCP_ST_CONNECTED:
+ case MAP_SCCP_ST_WAIT_RLSD:
+ /* send SCCP RLSD. libosmo-sigtran/sccp_scoc.c will do the SCCP connection cleanup.
+ * (It will repeatedly send SCCP RLSD until the peer responded with SCCP RLC, or until the
+ * sccp_connection->t_int timer expires, and the sccp_connection is freed.) */
+ if (map->cn_link && map->cn_link->sccp_user)
+ tx_sccp_rlsd(fi);
+ map_sccp_fsm_state_chg(MAP_SCCP_ST_DISCONNECTED);
+ return 0;
+
+ default:
+ case MAP_SCCP_ST_DISCONNECTED:
+ return 1;
+ }
+}
+
+void map_sccp_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause)
+{
+ struct hnbgw_context_map *map = fi->priv;
+ map->sccp_fi = NULL;
+}
+
+#define S(x) (1 << (x))
+
+static const struct osmo_fsm_state map_sccp_fsm_states[] = {
+ [MAP_SCCP_ST_INIT] = {
+ .name = "init",
+ .in_event_mask = 0
+ | S(MAP_SCCP_EV_TX_DATA_REQUEST)
+ | S(MAP_SCCP_EV_RAN_DISC)
+ | S(MAP_SCCP_EV_RX_RELEASED)
+ ,
+ .out_state_mask = 0
+ | S(MAP_SCCP_ST_INIT)
+ | S(MAP_SCCP_ST_WAIT_CC)
+ | S(MAP_SCCP_ST_DISCONNECTED)
+ ,
+ .action = map_sccp_init_action,
+ },
+ [MAP_SCCP_ST_WAIT_CC] = {
+ .name = "wait_cc",
+ .in_event_mask = 0
+ | S(MAP_SCCP_EV_RX_CONNECTION_CONFIRM)
+ | S(MAP_SCCP_EV_TX_DATA_REQUEST)
+ | S(MAP_SCCP_EV_RAN_DISC)
+ | S(MAP_SCCP_EV_RX_RELEASED)
+ ,
+ .out_state_mask = 0
+ | S(MAP_SCCP_ST_CONNECTED)
+ | S(MAP_SCCP_ST_DISCONNECTED)
+ ,
+ .action = map_sccp_wait_cc_action,
+ },
+ [MAP_SCCP_ST_CONNECTED] = {
+ .name = "connected",
+ .in_event_mask = 0
+ | S(MAP_SCCP_EV_RX_DATA_INDICATION)
+ | S(MAP_SCCP_EV_TX_DATA_REQUEST)
+ | S(MAP_SCCP_EV_RAN_DISC)
+ | S(MAP_SCCP_EV_RX_RELEASED)
+ | S(MAP_SCCP_EV_RX_CONNECTION_CONFIRM)
+ ,
+ .out_state_mask = 0
+ | S(MAP_SCCP_ST_WAIT_RLSD)
+ | S(MAP_SCCP_ST_DISCONNECTED)
+ ,
+ .onenter = map_sccp_connected_onenter,
+ .action = map_sccp_connected_action,
+ },
+ [MAP_SCCP_ST_WAIT_RLSD] = {
+ .name = "wait_rlsd",
+ .in_event_mask = 0
+ | S(MAP_SCCP_EV_RX_RELEASED)
+ | S(MAP_SCCP_EV_RX_DATA_INDICATION)
+ | S(MAP_SCCP_EV_TX_DATA_REQUEST)
+ | S(MAP_SCCP_EV_RAN_DISC)
+ | S(MAP_SCCP_EV_RX_CONNECTION_CONFIRM)
+ ,
+ .out_state_mask = 0
+ | S(MAP_SCCP_ST_DISCONNECTED)
+ ,
+ .onenter = map_sccp_wait_rlsd_onenter,
+ .action = map_sccp_wait_rlsd_action,
+ },
+ [MAP_SCCP_ST_DISCONNECTED] = {
+ .name = "disconnected",
+ .in_event_mask = 0
+ | S(MAP_SCCP_EV_TX_DATA_REQUEST)
+ | S(MAP_SCCP_EV_RAN_DISC)
+ ,
+ .onenter = map_sccp_disconnected_onenter,
+ .action = map_sccp_disconnected_action,
+ },
+};
+
+static struct osmo_fsm map_sccp_fsm = {
+ .name = "map_sccp",
+ .states = map_sccp_fsm_states,
+ .num_states = ARRAY_SIZE(map_sccp_fsm_states),
+ .log_subsys = DCN,
+ .event_names = map_sccp_fsm_event_names,
+ .timer_cb = map_sccp_fsm_timer_cb,
+ .cleanup = map_sccp_fsm_cleanup,
+};
+
+static __attribute__((constructor)) void map_sccp_fsm_register(void)
+{
+ OSMO_ASSERT(osmo_fsm_register(&map_sccp_fsm) == 0);
+}
diff --git a/src/osmo-hnbgw/hnbgw.c b/src/osmo-hnbgw/hnbgw.c
index 322dabe..ce82282 100644
--- a/src/osmo-hnbgw/hnbgw.c
+++ b/src/osmo-hnbgw/hnbgw.c
@@ -98,8 +98,6 @@
INIT_LLIST_HEAD(&gw->hnb_list);
INIT_LLIST_HEAD(&gw->ue_list);
- context_map_init(gw);
-
gw->mgw_pool = mgcp_client_pool_alloc(gw);
gw->config.mgcp_client = talloc_zero(tall_hnb_ctx, struct mgcp_client_conf);
mgcp_client_conf_init(gw->config.mgcp_client);
@@ -397,18 +395,16 @@
/* deactivate all context maps */
llist_for_each_entry_safe(map, map2, &ctx->map_list, hnb_list) {
- /* remove it from list, as HNB context will soon be
- * gone. Let's hope the second osmo_llist_del in the
- * map garbage collector works fine? */
- llist_del(&map->hnb_list);
- llist_del(&map->cn_list);
context_map_hnb_released(map);
+ /* hnbgw_context_map will remove itself from lists when it is ready. */
}
ue_context_free_by_hnb(ctx->gw, ctx);
}
void hnb_context_release(struct hnb_context *ctx)
{
+ struct hnbgw_context_map *map;
+
LOGHNB(ctx, DMAIN, LOGL_INFO, "Releasing HNB context\n");
/* remove from the list of HNB contexts */
@@ -424,6 +420,14 @@
osmo_stream_srv_destroy(ctx->conn);
} /* else: we are called from closed_cb, so conn is being freed separately */
+ /* hnbgw_context_map are still listed in ctx->map_list, but we are freeing ctx. Remove all entries from the
+ * list, but keep the hnbgw_context_map around for graceful release. They are also listed under
+ * hnbgw_cnlink->map_list, and will remove themselves when ready. */
+ while ((map = llist_first_entry_or_null(&ctx->map_list, struct hnbgw_context_map, hnb_list))) {
+ llist_del(&map->hnb_list);
+ map->hnb_ctx = NULL;
+ }
+
talloc_free(ctx);
}
@@ -469,6 +473,16 @@
.color = "\033[1;33m",
.description = "Media Gateway",
},
+ [DHNB] = {
+ .name = "DHNB", .loglevel = LOGL_NOTICE, .enabled = 1,
+ .color = OSMO_LOGCOLOR_CYAN,
+ .description = "HNB side (via RUA)",
+ },
+ [DCN] = {
+ .name = "DCN", .loglevel = LOGL_NOTICE, .enabled = 1,
+ .color = OSMO_LOGCOLOR_DARKYELLOW,
+ .description = "Core Network side (via SCCP)",
+ },
};
static const struct log_info hnbgw_log_info = {
@@ -841,3 +855,12 @@
/* not reached */
exit(0);
}
+
+struct msgb *hnbgw_ranap_msg_alloc(const char *name)
+{
+ struct msgb *ranap_msg;
+ ranap_msg = msgb_alloc_c(OTC_SELECT, sizeof(struct osmo_scu_prim) + 1500, name);
+ msgb_reserve(ranap_msg, sizeof(struct osmo_scu_prim));
+ ranap_msg->l2h = ranap_msg->data;
+ return ranap_msg;
+}
diff --git a/src/osmo-hnbgw/hnbgw_cn.c b/src/osmo-hnbgw/hnbgw_cn.c
index 4c0e685..731c758 100644
--- a/src/osmo-hnbgw/hnbgw_cn.c
+++ b/src/osmo-hnbgw/hnbgw_cn.c
@@ -345,16 +345,13 @@
osmo_sccp_addr_to_str_c(OTC_SELECT, ss7, ¶m->calling_addr),
osmo_sccp_addr_to_str_c(OTC_SELECT, ss7, ¶m->responding_addr));
- /* Nothing needs to happen for RUA, RUA towards the HNB doesn't seem to know any confirmations to its CONNECT
- * operation. */
-
map = context_map_by_cn(cnlink, param->conn_id);
- if (!map)
+ if (!map) {
+ /* We have no such SCCP connection. Ignore. */
return 0;
+ }
- /* SCCP connection is confirmed. Mark conn as active, i.e. requires a DISCONNECT to clean up the SCCP
- * connection. */
- map->scu_conn_active = true;
+ map_sccp_dispatch(map, MAP_SCCP_EV_RX_CONNECTION_CONFIRM, oph->msg);
return 0;
}
@@ -363,79 +360,14 @@
struct osmo_prim_hdr *oph)
{
struct hnbgw_context_map *map;
- ranap_message *message;
- int rc;
-
- /* Usually connection-oriented data is always passed transparently towards the specific HNB, via a RUA
- * connection identified by conn_id. An exception is made for RANAP RAB AssignmentRequest and
- * RANAP RAB AssignmentResponse, since those messages contain transport layer information (RTP stream IP/Port),
- * which is rewritten by the FSM that controls the co-located media gateway. */
map = context_map_by_cn(cnlink, param->conn_id);
if (!map) {
- /* FIXME: Return an error / released primitive */
+ /* We have no such SCCP connection. Ignore. */
return 0;
}
- /* Intercept RAB Assignment Request, to map RTP and GTP between access and core */
- if (!map->is_ps) {
- /* Circuit-Switched. Set up mapping of RTP ports via MGW */
- message = talloc_zero(map, ranap_message);
- rc = ranap_ran_rx_co_decode(map, message, msgb_l2(oph->msg), msgb_l2len(oph->msg));
-
- if (rc == 0) {
- switch (message->procedureCode) {
- case RANAP_ProcedureCode_id_RAB_Assignment:
- /* mgw_fsm_alloc_and_handle_rab_ass_req() takes ownership of (ranap) message */
- return handle_rab_ass_req(map, oph, message);
- case RANAP_ProcedureCode_id_Iu_Release:
- /* Any IU Release will terminate the MGW FSM, the message itsself is not passed to the
- * FSM code. It is just forwarded normally by the rua_tx_dt() call below. */
- mgw_fsm_release(map);
- break;
- }
- ranap_ran_rx_co_free(message);
- }
-
- talloc_free(message);
-#if ENABLE_PFCP
- } else {
- struct hnb_gw *hnb_gw = cnlink->gw;
- /* Packet-Switched. Set up mapping of GTP ports via UPF */
- message = talloc_zero(map, ranap_message);
- rc = ranap_ran_rx_co_decode(map, message, msgb_l2(oph->msg), msgb_l2len(oph->msg));
-
- if (rc == 0) {
- switch (message->procedureCode) {
-
- case RANAP_ProcedureCode_id_RAB_Assignment:
- /* If a UPF is configured, handle the RAB Assignment via ps_rab_ass_fsm, and replace the
- * GTP F-TEIDs in the RAB Assignment message before passing it on to RUA. */
- if (hnb_gw_is_gtp_mapping_enabled(hnb_gw)) {
- LOGP(DMAIN, LOGL_DEBUG,
- "RAB Assignment: setting up GTP tunnel mapping via UPF %s\n",
- osmo_sockaddr_to_str_c(OTC_SELECT, &hnb_gw->pfcp.cp_peer->remote_addr));
- return hnbgw_gtpmap_rx_rab_ass_req(map, oph, message);
- }
- /* If no UPF is configured, directly forward the message as-is (no GTP mapping). */
- LOGP(DMAIN, LOGL_DEBUG, "RAB Assignment: no UPF configured, forwarding as-is\n");
- break;
-
- case RANAP_ProcedureCode_id_Iu_Release:
- /* Any IU Release will terminate the MGW FSM, the message itsself is not passed to the
- * FSM code. It is just forwarded normally by the rua_tx_dt() call below. */
- hnbgw_gtpmap_release(map);
- break;
- }
- ranap_ran_rx_co_free(message);
- }
-
- talloc_free(message);
-#endif
- }
-
- return rua_tx_dt(map->hnb_ctx, map->is_ps, map->rua_ctx_id,
- msgb_l2(oph->msg), msgb_l2len(oph->msg));
+ return map_sccp_dispatch(map, MAP_SCCP_EV_RX_DATA_INDICATION, oph->msg);
}
static int handle_cn_disc_ind(struct hnbgw_cnlink *cnlink,
@@ -449,22 +381,13 @@
LOGP(DMAIN, LOGL_DEBUG, "handle_cn_disc_ind() responding_addr=%s\n",
inet_ntoa(param->responding_addr.ip.v4));
- RUA_Cause_t rua_cause = {
- .present = RUA_Cause_PR_NOTHING,
- /* FIXME: Convert incoming SCCP cause to RUA cause */
- };
-
- /* we need to notify the HNB associated with this connection via
- * a RUA DISCONNECT */
-
map = context_map_by_cn(cnlink, param->conn_id);
if (!map) {
- /* FIXME: Return an error / released primitive */
+ /* We have no connection. Ignore. */
return 0;
}
- return rua_tx_disc(map->hnb_ctx, map->is_ps, map->rua_ctx_id,
- &rua_cause, msgb_l2(oph->msg), msgb_l2len(oph->msg));
+ return map_sccp_dispatch(map, MAP_SCCP_EV_RX_RELEASED, oph->msg);
}
/* Entry point for primitives coming up from SCCP User SAP */
@@ -492,6 +415,8 @@
return -1;
}
+ talloc_steal(OTC_SELECT, oph->msg);
+
switch (OSMO_PRIM_HDR(oph)) {
case OSMO_PRIM(OSMO_SCU_PRIM_N_UNITDATA, PRIM_OP_INDICATION):
rc = handle_cn_unitdata(cnlink, &prim->u.unitdata, oph);
@@ -512,8 +437,6 @@
break;
}
- msgb_free(oph->msg);
-
return rc;
}
@@ -637,3 +560,8 @@
return 0;
}
+
+const struct osmo_sccp_addr *hnbgw_cn_get_remote_addr(struct hnb_gw *gw, bool is_ps)
+{
+ return is_ps ? &gw->sccp.iups_remote_addr : &gw->sccp.iucs_remote_addr;
+}
diff --git a/src/osmo-hnbgw/hnbgw_rua.c b/src/osmo-hnbgw/hnbgw_rua.c
index 97ced4a..db7fdbb 100644
--- a/src/osmo-hnbgw/hnbgw_rua.c
+++ b/src/osmo-hnbgw/hnbgw_rua.c
@@ -62,6 +62,11 @@
if (!msg)
return -EINVAL;
+ if (!ctx || !ctx->conn) {
+ LOGHNB(ctx, DRUA, LOGL_ERROR, "RUA context to this HNB is not connected, cannot transmit message\n");
+ return -ENOTCONN;
+ }
+
msgb_sctp_ppid(msg) = IUH_PPI_RUA;
osmo_stream_srv_send(ctx->conn, msg);
@@ -198,23 +203,16 @@
uint32_t context_id, uint32_t cause,
const uint8_t *data, unsigned int len)
{
- struct msgb *msg;
- struct osmo_scu_prim *prim;
+ struct msgb *ranap_msg = NULL;
struct hnbgw_context_map *map = NULL;
struct hnbgw_cnlink *cn = hnb->gw->sccp.cnlink;
- struct osmo_sccp_addr *remote_addr;
bool is_ps;
- bool release_context_map = false;
- ranap_message *message;
- int rc;
switch (cN_DomainIndicator) {
case RUA_CN_DomainIndicator_cs_domain:
- remote_addr = &hnb->gw->sccp.iucs_remote_addr;
is_ps = false;
break;
case RUA_CN_DomainIndicator_ps_domain:
- remote_addr = &hnb->gw->sccp.iups_remote_addr;
is_ps = true;
break;
default:
@@ -227,9 +225,15 @@
return 0;
}
- msg = msgb_alloc(1500, "rua_to_sccp");
-
- prim = (struct osmo_scu_prim *) msgb_put(msg, sizeof(*prim));
+ /* If there is RANAP data, include it in the msgb. In RUA there is always data in practice, but theoretically it
+ * could be an empty Connect or Disconnect. */
+ if (data && len) {
+ /* According to API doc of map_rua_fsm_event: allocate msgb for RANAP data from OTC_SELECT, reserve
+ * headroom for an osmo_scu_prim. Point l2h at the RANAP data. */
+ ranap_msg = hnbgw_ranap_msg_alloc("RANAP_from_RUA");
+ ranap_msg->l2h = msgb_put(ranap_msg, len);
+ memcpy(ranap_msg->l2h, data, len);
+ }
map = context_map_alloc_by_hnb(hnb, context_id, is_ps, cn);
OSMO_ASSERT(map);
@@ -237,91 +241,21 @@
LOG_MAP(map, DRUA, LOGL_DEBUG, "rx RUA %s with %u bytes RANAP data\n",
rua_procedure_code_name(rua_procedure), data ? len : 0);
- /* add primitive header */
switch (rua_procedure) {
case RUA_ProcedureCode_id_Connect:
- osmo_prim_init(&prim->oph, SCCP_SAP_USER, OSMO_SCU_PRIM_N_CONNECT, PRIM_OP_REQUEST, msg);
- prim->u.connect.called_addr = *remote_addr;
- prim->u.connect.calling_addr = cn->gw->sccp.local_addr;
- prim->u.connect.sccp_class = 2;
- prim->u.connect.conn_id = map->scu_conn_id;
- /* Two separate logs because of osmo_sccp_addr_dump(). */
- LOGHNB(hnb, DRUA, LOGL_DEBUG, "RUA to SCCP N_CONNECT: called_addr:%s\n",
- osmo_sccp_addr_dump(&prim->u.connect.called_addr));
- LOGHNB(hnb, DRUA, LOGL_DEBUG, "RUA to SCCP N_CONNECT: calling_addr:%s\n",
- osmo_sccp_addr_dump(&prim->u.connect.calling_addr));
- break;
+ return map_rua_dispatch(map, MAP_RUA_EV_RX_CONNECT, ranap_msg);
case RUA_ProcedureCode_id_DirectTransfer:
- osmo_prim_init(&prim->oph, SCCP_SAP_USER, OSMO_SCU_PRIM_N_DATA, PRIM_OP_REQUEST, msg);
- prim->u.data.conn_id = map->scu_conn_id;
- break;
+ return map_rua_dispatch(map, MAP_RUA_EV_RX_DIRECT_TRANSFER, ranap_msg);
case RUA_ProcedureCode_id_Disconnect:
- osmo_prim_init(&prim->oph, SCCP_SAP_USER, OSMO_SCU_PRIM_N_DISCONNECT, PRIM_OP_REQUEST, msg);
- prim->u.disconnect.conn_id = map->scu_conn_id;
- prim->u.disconnect.cause = cause;
- release_context_map = true;
- /* Mark SCCP conn as gracefully disconnected */
- map->scu_conn_active = false;
- break;
+ return map_rua_dispatch(map, MAP_RUA_EV_RX_DISCONNECT, ranap_msg);
default:
/* No caller may ever pass a different RUA procedure code */
OSMO_ASSERT(false);
}
-
- /* If there is RANAP data, include it in the msgb. Usually there is data, but this could also be an SCCP CR
- * a.k.a. OSMO_SCU_PRIM_N_CONNECT without RANAP payload. */
- if (data && len) {
- msg->l2h = msgb_put(msg, len);
- memcpy(msg->l2h, data, len);
- }
-
- /* If there is data, see if it is a RAB Assignment message where we need to change the user plane information,
- * for RTP mapping via MGW (soon also GTP mapping via UPF). */
- if (data && len && map && !release_context_map) {
- if (!map->is_ps) {
- message = talloc_zero(map, ranap_message);
- rc = ranap_cn_rx_co_decode2(message, msgb_l2(prim->oph.msg), msgb_l2len(prim->oph.msg));
-
- if (rc == 0) {
- switch (message->procedureCode) {
- case RANAP_ProcedureCode_id_RAB_Assignment:
- /* mgw_fsm_handle_rab_ass_resp() takes ownership of prim->oph and (ranap) message */
- return mgw_fsm_handle_rab_ass_resp(map, &prim->oph, message);
- }
- ranap_cn_rx_co_free(message);
- }
-
- talloc_free(message);
-#if ENABLE_PFCP
- } else if (hnb_gw_is_gtp_mapping_enabled(hnb->gw)) {
- /* map->is_ps == true and PFCP is enabled in osmo-hnbgw.cfg */
- message = talloc_zero(map, ranap_message);
- rc = ranap_cn_rx_co_decode2(message, msgb_l2(prim->oph.msg), msgb_l2len(prim->oph.msg));
-
- if (rc == 0) {
- switch (message->procedureCode) {
- case RANAP_ProcedureCode_id_RAB_Assignment:
- /* ps_rab_ass_fsm takes ownership of prim->oph and RANAP message */
- return hnbgw_gtpmap_rx_rab_ass_resp(map, &prim->oph, message);
- }
- ranap_cn_rx_co_free(message);
- }
-
- talloc_free(message);
-#endif
- }
- }
-
- rc = osmo_sccp_user_sap_down(cn->sccp_user, &prim->oph);
-
- if (map && release_context_map)
- context_map_hnb_released(map);
-
- return rc;
}
static uint32_t rua_to_scu_cause(RUA_Cause_t *in)
diff --git a/src/osmo-hnbgw/hnbgw_vty.c b/src/osmo-hnbgw/hnbgw_vty.c
index abddc79..7f79b82 100644
--- a/src/osmo-hnbgw/hnbgw_vty.c
+++ b/src/osmo-hnbgw/hnbgw_vty.c
@@ -208,10 +208,8 @@
hnb->hnbap_stream, hnb->rua_stream, VTY_NEWLINE);
llist_for_each_entry(map, &hnb->map_list, hnb_list) {
- map_count[map->is_ps? 1 : 0]++;
- state_count[map->is_ps? 1 : 0]
- [(map->state >= 0 && map->state < MAP_S_NUM_STATES)?
- map->state : MAP_S_NUM_STATES]++;
+ map_count[map->is_ps ? 1 : 0]++;
+ state_count[map->is_ps ? 1 : 0][context_map_get_state(map)]++;
}
vty_dump_hnb_info__map_states(vty, "IuCS", map_count[0], state_count[0]);
vty_dump_hnb_info__map_states(vty, "IuPS", map_count[1], state_count[1]);
diff --git a/src/osmo-hnbgw/mgw_fsm.c b/src/osmo-hnbgw/mgw_fsm.c
index fe1e227..cddc64e 100644
--- a/src/osmo-hnbgw/mgw_fsm.c
+++ b/src/osmo-hnbgw/mgw_fsm.c
@@ -52,10 +52,7 @@
/* Send Iu Release Request, this is done in erroneous cases from which we cannot recover */
static void tx_release_req(struct hnbgw_context_map *map)
{
- struct hnb_context *hnb = map->hnb_ctx;
- struct hnbgw_cnlink *cn = hnb->gw->sccp.cnlink;
struct msgb *msg;
- struct osmo_scu_prim *prim;
static const struct RANAP_Cause cause = {
.present = RANAP_Cause_PR_transmissionNetwork,
.choice.transmissionNetwork =
@@ -64,11 +61,8 @@
msg = ranap_new_msg_iu_rel_req(&cause);
msg->l2h = msg->data;
-
- prim = (struct osmo_scu_prim *)msgb_push(msg, sizeof(*prim));
- prim->u.data.conn_id = map->scu_conn_id;
- osmo_prim_init(&prim->oph, SCCP_SAP_USER, OSMO_SCU_PRIM_N_DATA, PRIM_OP_REQUEST, msg);
- osmo_sccp_user_sap_down(cn->sccp_user, &prim->oph);
+ talloc_steal(OTC_SELECT, msg);
+ map_sccp_dispatch(map, MAP_SCCP_EV_TX_DATA_REQUEST, msg);
}
#define S(x) (1 << (x))
@@ -112,7 +106,7 @@
/* Pointers to messages and prim header we take ownership of */
ranap_message *ranap_rab_ass_req_message;
ranap_message *ranap_rab_ass_resp_message;
- struct osmo_prim_hdr *ranap_rab_ass_resp_oph;
+ struct msgb *ranap_rab_ass_resp_msgb;
/* MGW context */
struct mgcp_client *mgcpc;
@@ -173,7 +167,7 @@
mgw_info.codecs[0] = CODEC_IUFP;
mgw_info.codecs_len = 1;
- mgw_fsm_priv->mgcpc = mgcp_client_pool_get(map->hnb_ctx->gw->mgw_pool);
+ mgw_fsm_priv->mgcpc = mgcp_client_pool_get(map->gw->mgw_pool);
if (!mgw_fsm_priv->mgcpc) {
LOGPFSML(fi, LOGL_ERROR,
"cannot ensure MGW endpoint -- no MGW configured, check configuration!\n");
@@ -255,8 +249,9 @@
}
LOGPFSML(fi, LOGL_DEBUG, "forwarding modified RAB-AssignmentRequest to HNB\n");
- rua_tx_dt(map->hnb_ctx, map->is_ps, map->rua_ctx_id, msg->data, msg->len);
- msgb_free(msg);
+ msg->l2h = msg->data;
+ talloc_steal(OTC_SELECT, msg);
+ map_rua_dispatch(map, MAP_RUA_EV_TX_DIRECT_TRANSFER, msg);
}
static void mgw_fsm_assign(struct osmo_fsm_inst *fi, uint32_t event, void *data)
@@ -274,8 +269,6 @@
{
struct mgw_fsm_priv *mgw_fsm_priv = fi->priv;
struct hnbgw_context_map *map = mgw_fsm_priv->map;
- struct hnb_context *hnb = map->hnb_ctx;
- struct hnbgw_cnlink *cn = hnb->gw->sccp.cnlink;
struct mgcp_conn_peer mgw_info;
struct osmo_sockaddr addr;
struct osmo_sockaddr_str addr_str;
@@ -298,6 +291,8 @@
if (rc < 0) {
rab_failed_at_hnb = ranap_rab_ass_resp_ies_check_failure(ies, mgw_fsm_priv->rab_id);
if (rab_failed_at_hnb) {
+ struct msgb *msg;
+
LOGPFSML(fi, LOGL_ERROR,
"The RAB-AssignmentResponse contains a RAB-FailedList, RAB-Assignment (%u) failed.\n",
mgw_fsm_priv->rab_id);
@@ -305,8 +300,12 @@
/* Forward the RAB-AssignmentResponse transparently. This will ensure that the MSC is informed
* about the problem. */
LOGPFSML(fi, LOGL_DEBUG, "forwarding unmodified RAB-AssignmentResponse to MSC\n");
- rc = osmo_sccp_user_sap_down(cn->sccp_user, mgw_fsm_priv->ranap_rab_ass_resp_oph);
- mgw_fsm_priv->ranap_rab_ass_resp_oph = NULL;
+
+ msg = mgw_fsm_priv->ranap_rab_ass_resp_msgb;
+ mgw_fsm_priv->ranap_rab_ass_resp_msgb = NULL;
+ talloc_steal(OTC_SELECT, msg);
+
+ rc = map_sccp_dispatch(map, MAP_SCCP_EV_TX_DATA_REQUEST, msg);
if (rc < 0) {
LOGPFSML(fi, LOGL_DEBUG, "failed to forward RAB-AssignmentResponse message\n");
osmo_fsm_inst_state_chg(fi, MGW_ST_FAILURE, 0, 0);
@@ -431,15 +430,15 @@
* the original message. Ensure that there is enough room in l2h to grow. (The current implementation
* should yield a message with the same size, but there is no guarantee for that) */
msg_max_len =
- msgb_l2len(mgw_fsm_priv->ranap_rab_ass_resp_oph->msg) +
- msgb_tailroom(mgw_fsm_priv->ranap_rab_ass_resp_oph->msg);
- rc = msgb_resize_area(mgw_fsm_priv->ranap_rab_ass_resp_oph->msg,
- mgw_fsm_priv->ranap_rab_ass_resp_oph->msg->l2h,
- msgb_l2len(mgw_fsm_priv->ranap_rab_ass_resp_oph->msg), msg_max_len);
+ msgb_l2len(mgw_fsm_priv->ranap_rab_ass_resp_msgb) +
+ msgb_tailroom(mgw_fsm_priv->ranap_rab_ass_resp_msgb);
+ rc = msgb_resize_area(mgw_fsm_priv->ranap_rab_ass_resp_msgb,
+ mgw_fsm_priv->ranap_rab_ass_resp_msgb->l2h,
+ msgb_l2len(mgw_fsm_priv->ranap_rab_ass_resp_msgb), msg_max_len);
OSMO_ASSERT(rc == 0);
- rc = ranap_rab_ass_resp_encode(msgb_l2(mgw_fsm_priv->ranap_rab_ass_resp_oph->msg),
- msgb_l2len(mgw_fsm_priv->ranap_rab_ass_resp_oph->msg), ies);
+ rc = ranap_rab_ass_resp_encode(msgb_l2(mgw_fsm_priv->ranap_rab_ass_resp_msgb),
+ msgb_l2len(mgw_fsm_priv->ranap_rab_ass_resp_msgb), ies);
if (rc < 0) {
LOGPFSML(fi, LOGL_ERROR, "failed to re-encode RAB-AssignmentResponse message\n");
osmo_fsm_inst_state_chg(fi, MGW_ST_FAILURE, 0, 0);
@@ -447,9 +446,9 @@
}
/* Resize l2h back to the actual message length */
- rc = msgb_resize_area(mgw_fsm_priv->ranap_rab_ass_resp_oph->msg,
- mgw_fsm_priv->ranap_rab_ass_resp_oph->msg->l2h,
- msgb_l2len(mgw_fsm_priv->ranap_rab_ass_resp_oph->msg), rc);
+ rc = msgb_resize_area(mgw_fsm_priv->ranap_rab_ass_resp_msgb,
+ mgw_fsm_priv->ranap_rab_ass_resp_msgb->l2h,
+ msgb_l2len(mgw_fsm_priv->ranap_rab_ass_resp_msgb), rc);
OSMO_ASSERT(rc == 0);
/* When the established state is entered, the modified RAB AssignmentResponse is forwarded to the MSC.
@@ -466,14 +465,16 @@
{
struct mgw_fsm_priv *mgw_fsm_priv = fi->priv;
struct hnbgw_context_map *map = mgw_fsm_priv->map;
- struct osmo_prim_hdr *oph = mgw_fsm_priv->ranap_rab_ass_resp_oph;
- struct hnb_context *hnb = map->hnb_ctx;
- struct hnbgw_cnlink *cn = hnb->gw->sccp.cnlink;
+ struct msgb *ranap_msg;
int rc;
LOGPFSML(fi, LOGL_DEBUG, "forwarding modified RAB-AssignmentResponse to MSC\n");
- rc = osmo_sccp_user_sap_down(cn->sccp_user, oph);
- mgw_fsm_priv->ranap_rab_ass_resp_oph = NULL;
+
+ ranap_msg = mgw_fsm_priv->ranap_rab_ass_resp_msgb;
+ mgw_fsm_priv->ranap_rab_ass_resp_msgb = NULL;
+ talloc_steal(OTC_SELECT, ranap_msg);
+
+ rc = map_sccp_dispatch(map, MAP_SCCP_EV_TX_DATA_REQUEST, ranap_msg);
if (rc < 0) {
LOGPFSML(fi, LOGL_DEBUG, "failed to forward RAB-AssignmentResponse message\n");
osmo_fsm_inst_state_chg(fi, MGW_ST_FAILURE, 0, 0);
@@ -530,28 +531,6 @@
static void mgw_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause)
{
struct mgw_fsm_priv *mgw_fsm_priv = fi->priv;
- struct osmo_scu_prim *scu_prim;
- struct msgb *scu_msg;
-
- if (mgw_fsm_priv->ranap_rab_ass_req_message) {
- ranap_ran_rx_co_free(mgw_fsm_priv->ranap_rab_ass_req_message);
- talloc_free(mgw_fsm_priv->ranap_rab_ass_req_message);
- mgw_fsm_priv->ranap_rab_ass_req_message = NULL;
- }
-
- if (mgw_fsm_priv->ranap_rab_ass_resp_message) {
- ranap_cn_rx_co_free(mgw_fsm_priv->ranap_rab_ass_resp_message);
- talloc_free(mgw_fsm_priv->ranap_rab_ass_resp_message);
- mgw_fsm_priv->ranap_rab_ass_resp_message = NULL;
- }
-
- if (mgw_fsm_priv->ranap_rab_ass_resp_oph) {
- scu_prim = (struct osmo_scu_prim *)mgw_fsm_priv->ranap_rab_ass_resp_oph;
- scu_msg = scu_prim->oph.msg;
- msgb_free(scu_msg);
- mgw_fsm_priv->ranap_rab_ass_resp_oph = NULL;
- }
-
talloc_free(mgw_fsm_priv);
}
@@ -654,7 +633,7 @@
};
/* The MSC may ask to release a specific RAB within a RAB-AssignmentRequest */
-static int handle_rab_release(struct hnbgw_context_map *map, struct osmo_prim_hdr *oph, ranap_message *message)
+static int handle_rab_release(struct hnbgw_context_map *map, struct msgb *ranap_msg, ranap_message *message)
{
bool rab_release_req;
struct osmo_fsm_inst *fi = map->mgw_fi;
@@ -672,7 +651,7 @@
/* Forward the unmodifed RAB-AssignmentRequest to HNB, so that the HNB is informed about the RAB release as
* well */
LOGPFSML(fi, LOGL_DEBUG, "forwarding unmodified RAB-AssignmentRequest to HNB\n");
- rc = rua_tx_dt(map->hnb_ctx, map->is_ps, map->rua_ctx_id, msgb_l2(oph->msg), msgb_l2len(oph->msg));
+ rc = map_rua_dispatch(map, MAP_RUA_EV_TX_DIRECT_TRANSFER, ranap_msg);
/* Release the FSM normally */
osmo_fsm_inst_state_chg(fi, MGW_ST_RELEASE, 0, 0);
@@ -680,12 +659,14 @@
return rc;
}
-/*! Allocate MGW FSM and handle RANAP RAB AssignmentRequest).
- * \ptmap[in] map hanbgw context map that is responsible for this call.
- * \ptmap[in] oph osmo prim header with RANAP RAB AssignmentResponse (function takes no ownership).
- * \ptmap[in] message ranap message container (function takes ownership).
+/*! Allocate MGW FSM and handle RANAP RAB AssignmentRequest.
+ * \param[in] map hnbgw context map that is responsible for this call.
+ * \param[in] ranap_msg msgb containing RANAP RAB AssignmentRequest at msgb_l2(), allocated in OTC_SELECT.
+ * This function may talloc_steal(ranap_msg) to keep it for later.
+ * \param[in] message decoded RANAP message container, allocated in OTC_SELECT.
+ * This function may talloc_steal(message) to keep it for later.
* \returns 0 on success; negative on error. */
-int handle_rab_ass_req(struct hnbgw_context_map *map, struct osmo_prim_hdr *oph, ranap_message *message)
+int handle_rab_ass_req(struct hnbgw_context_map *map, struct msgb *ranap_msg, ranap_message *message)
{
static bool initialized = false;
struct mgw_fsm_priv *mgw_fsm_priv;
@@ -703,7 +684,7 @@
* a ReleaseList. In this case an FSM will already be present. */
if (map->mgw_fi) {
/* A RAB Release might be in progress, handle it */
- rc = handle_rab_release(map, oph, message);
+ rc = handle_rab_release(map, ranap_msg, message);
if (rc >= 0)
return rc;
@@ -726,6 +707,8 @@
mgw_fsm_priv = talloc_zero(map, struct mgw_fsm_priv);
mgw_fsm_priv->map = map;
+
+ talloc_steal(mgw_fsm_priv, message);
mgw_fsm_priv->ranap_rab_ass_req_message = message;
/* Allocate FSM */
@@ -738,17 +721,17 @@
}
/*! Handlie RANAP RAB AssignmentResponse (deliver message, complete RTP stream switching).
- * \ptmap[in] map hanbgw context map that is responsible for this call.
- * \ptmap[in] oph osmo prim header with RANAP RAB AssignmentResponse (function takes ownership).
- * \ptmap[in] message ranap message container with decoded ranap message (function takes ownership).
+ * \param[in] map hnbgw context map that is responsible for this call.
+ * \param[in] ranap_msg msgb containing RANAP RAB AssignmentResponse at msgb_l2(), allocated in OTC_SELECT.
+ * This function may talloc_steal(ranap_msg) to keep it for later.
+ * \param[in] message decoded RANAP message container, allocated in OTC_SELECT.
+ * This function may talloc_steal(message) to keep it for later.
* \returns 0 on success; negative on error. */
-int mgw_fsm_handle_rab_ass_resp(struct hnbgw_context_map *map, struct osmo_prim_hdr *oph, ranap_message *message)
+int mgw_fsm_handle_rab_ass_resp(struct hnbgw_context_map *map, struct msgb *ranap_msg, ranap_message *message)
{
struct mgw_fsm_priv *mgw_fsm_priv;
- struct osmo_scu_prim *prim;
- struct msgb *msg;
- OSMO_ASSERT(oph);
+ OSMO_ASSERT(ranap_msg);
if (!map->mgw_fi) {
/* NOTE: This situation is a corner-case. We may end up here when the co-located MGW caused a problem
@@ -758,23 +741,19 @@
"mgw_fsm_handle_rab_ass_resp() rua_ctx_id=%d, no MGW fsm -- sending Iu-Release-Request!\n",
map->rua_ctx_id);
- /* Cleanup ranap message */
- ranap_cn_rx_co_free(message);
- talloc_free(message);
-
- /* Toss RAB-AssignmentResponse */
- prim = (struct osmo_scu_prim *)oph;
- msg = prim->oph.msg;
- msgb_free(msg);
-
/* Send a release request, to make sure that the MSC is aware of the problem. */
tx_release_req(map);
return -1;
}
mgw_fsm_priv = map->mgw_fi->priv;
- mgw_fsm_priv->ranap_rab_ass_resp_oph = oph;
+
+ talloc_steal(mgw_fsm_priv, ranap_msg);
+ mgw_fsm_priv->ranap_rab_ass_resp_msgb = ranap_msg;
+
+ talloc_steal(mgw_fsm_priv, message);
mgw_fsm_priv->ranap_rab_ass_resp_message = message;
+
osmo_fsm_inst_dispatch(map->mgw_fi, MGW_EV_RAB_ASS_RESP, NULL);
return 0;
}
diff --git a/src/osmo-hnbgw/ps_rab_ass_fsm.c b/src/osmo-hnbgw/ps_rab_ass_fsm.c
index e232de8..65a6116 100644
--- a/src/osmo-hnbgw/ps_rab_ass_fsm.c
+++ b/src/osmo-hnbgw/ps_rab_ass_fsm.c
@@ -110,7 +110,7 @@
ranap_message *ranap_rab_ass_req_message;
ranap_message *ranap_rab_ass_resp_message;
- struct osmo_prim_hdr *ranap_rab_ass_resp_oph;
+ struct msgb *ranap_rab_ass_resp_msgb;
/* A RAB Assignment may contain more than one RAB. Each RAB sets up a distinct ps_rab_fsm (aka PFCP session) and
* reports back about local F-TEIDs assigned by the UPF. This gives the nr of RAB events we expect from
@@ -214,16 +214,25 @@
return rc;
}
-int hnbgw_gtpmap_rx_rab_ass_req(struct hnbgw_context_map *map, struct osmo_prim_hdr *oph, ranap_message *message)
+/*! Allocate ps_rab_ass_fsm and handle PS RANAP RAB AssignmentRequest.
+ * \param[in] map hnbgw context map that is responsible for this conn.
+ * \param[in] ranap_msg msgb containing RANAP RAB AssignmentRequest at msgb_l2(), allocated in OTC_SELECT.
+ * This function may talloc_steal(ranap_msg) to keep it for later.
+ * \param[in] message decoded RANAP message container, allocated in OTC_SELECT.
+ * This function may talloc_steal(message) to keep it for later.
+ * \returns 0 on success; negative on error. */
+int hnbgw_gtpmap_rx_rab_ass_req(struct hnbgw_context_map *map, struct msgb *ranap_msg, ranap_message *message)
{
RANAP_RAB_AssignmentRequestIEs_t *ies = &message->msg.raB_AssignmentRequestIEs;
int i;
- struct hnb_gw *hnb_gw = map->hnb_ctx->gw;
+ struct hnb_gw *hnb_gw = map->gw;
struct ps_rab_ass *rab_ass;
struct osmo_fsm_inst *fi;
rab_ass = ps_rab_ass_alloc(map);
+
+ talloc_steal(rab_ass, message);
rab_ass->ranap_rab_ass_req_message = message;
/* Now rab_ass owns message and will clean it up */
@@ -351,8 +360,10 @@
ps_rab_ass_failure(rab_ass);
return;
}
- rua_tx_dt(rab_ass->map->hnb_ctx, rab_ass->map->is_ps, rab_ass->map->rua_ctx_id, msg->data, msg->len);
- msgb_free(msg);
+ talloc_steal(OTC_SELECT, msg);
+ msg->l2h = msg->data;
+ map_rua_dispatch(rab->map, MAP_RUA_EV_TX_DIRECT_TRANSFER, msg);
+
/* The request message has been forwarded. The response will be handled by a new FSM instance.
* We are done. */
osmo_fsm_inst_term(rab_ass->fi, OSMO_FSM_TERM_REGULAR, NULL);
@@ -385,7 +396,7 @@
return ps_rab_rx_access_remote_f_teid(map, rab_id, &args);
}
-int hnbgw_gtpmap_rx_rab_ass_resp(struct hnbgw_context_map *map, struct osmo_prim_hdr *oph, ranap_message *message)
+int hnbgw_gtpmap_rx_rab_ass_resp(struct hnbgw_context_map *map, struct msgb *ranap_msg, ranap_message *message)
{
/* hNodeB responds with its own F-TEIDs. Need to tell the UPF about those to complete the GTP mapping.
* 1. here, extract the F-TEIDs (one per RAB),
@@ -408,7 +419,7 @@
struct ps_rab_ass *rab_ass;
struct osmo_fsm_inst *fi;
RANAP_RAB_AssignmentResponseIEs_t *ies;
- struct hnb_gw *hnb_gw = map->hnb_ctx->gw;
+ struct hnb_gw *hnb_gw = map->gw;
/* Make sure we indeed deal with a setup-or-modify list */
ies = &message->msg.raB_AssignmentResponseIEs;
@@ -418,8 +429,12 @@
}
rab_ass = ps_rab_ass_alloc(map);
+
+ talloc_steal(rab_ass, message);
rab_ass->ranap_rab_ass_resp_message = message;
- rab_ass->ranap_rab_ass_resp_oph = oph;
+
+ talloc_steal(rab_ass, ranap_msg);
+ rab_ass->ranap_rab_ass_resp_msgb = ranap_msg;
/* Now rab_ass owns message and will clean it up */
if (!osmo_pfcp_cp_peer_is_associated(hnb_gw->pfcp.cp_peer)) {
@@ -494,8 +509,8 @@
{
int i;
int rc;
- struct hnbgw_cnlink *cn = rab_ass->map->cn_link;
RANAP_RAB_AssignmentResponseIEs_t *ies = &rab_ass->ranap_rab_ass_resp_message->msg.raB_AssignmentResponseIEs;
+ struct msgb *msg;
/* Go through all RABs in the RAB Assignment Response message and replace with the F-TEID that the UPF assigned,
* verifying that instructing the UPF has succeeded. */
@@ -565,10 +580,13 @@
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifiedItem, &item_ies);
}
+ msg = rab_ass->ranap_rab_ass_resp_msgb;
+ rab_ass->ranap_rab_ass_resp_msgb = NULL;
+ talloc_steal(OTC_SELECT, msg);
+
/* Replaced all the GTP info, re-encode the message. Since we are replacing data 1:1, taking care to use the
* same IP address encoding, the resulting message size must be identical to the original message size. */
- rc = ranap_rab_ass_resp_encode(msgb_l2(rab_ass->ranap_rab_ass_resp_oph->msg),
- msgb_l2len(rab_ass->ranap_rab_ass_resp_oph->msg), ies);
+ rc = ranap_rab_ass_resp_encode(msgb_l2(msg), msgb_l2len(msg), ies);
if (rc < 0) {
LOG_PS_RAB_ASS(rab_ass, LOGL_ERROR, "Re-encoding RANAP PS RAB-AssignmentResponse failed\n");
ps_rab_ass_failure(rab_ass);
@@ -576,8 +594,8 @@
}
LOG_PS_RAB_ASS(rab_ass, LOGL_NOTICE, "Sending RANAP PS RAB-AssignmentResponse with mapped GTP info\n");
- rc = osmo_sccp_user_sap_down(cn->sccp_user, rab_ass->ranap_rab_ass_resp_oph);
- rab_ass->ranap_rab_ass_resp_oph = NULL;
+
+ rc = map_sccp_dispatch(rab_ass->map, MAP_SCCP_EV_TX_DATA_REQUEST, msg);
if (rc < 0) {
LOG_PS_RAB_ASS(rab_ass, LOGL_ERROR, "Sending RANAP PS RAB-AssignmentResponse failed\n");
ps_rab_ass_failure(rab_ass);
@@ -590,29 +608,8 @@
static void ps_rab_ass_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause)
{
struct ps_rab_ass *rab_ass = fi->priv;
- struct osmo_scu_prim *scu_prim;
- struct msgb *scu_msg;
struct ps_rab *rab;
- if (rab_ass->ranap_rab_ass_req_message) {
- ranap_ran_rx_co_free(rab_ass->ranap_rab_ass_req_message);
- talloc_free(rab_ass->ranap_rab_ass_req_message);
- rab_ass->ranap_rab_ass_req_message = NULL;
- }
-
- if (rab_ass->ranap_rab_ass_resp_message) {
- ranap_cn_rx_co_free(rab_ass->ranap_rab_ass_resp_message);
- talloc_free(rab_ass->ranap_rab_ass_resp_message);
- rab_ass->ranap_rab_ass_resp_message = NULL;
- }
-
- if (rab_ass->ranap_rab_ass_resp_oph) {
- scu_prim = (struct osmo_scu_prim *)rab_ass->ranap_rab_ass_resp_oph;
- scu_msg = scu_prim->oph.msg;
- msgb_free(scu_msg);
- rab_ass->ranap_rab_ass_resp_oph = NULL;
- }
-
llist_for_each_entry(rab, &rab_ass->map->ps_rabs, entry) {
if (rab->req_fi == fi)
rab->req_fi = NULL;
diff --git a/src/osmo-hnbgw/ps_rab_fsm.c b/src/osmo-hnbgw/ps_rab_fsm.c
index dcc18ca..f4a1f12 100644
--- a/src/osmo-hnbgw/ps_rab_fsm.c
+++ b/src/osmo-hnbgw/ps_rab_fsm.c
@@ -87,7 +87,7 @@
/* Allocate with the global hnb_gw, so that we can gracefully handle PFCP release even if a hnb_ctx gets
* deallocated. */
- fi = osmo_fsm_inst_alloc(&ps_rab_fsm, map->hnb_ctx->gw, NULL, LOGL_DEBUG, NULL);
+ fi = osmo_fsm_inst_alloc(&ps_rab_fsm, map->gw, NULL, LOGL_DEBUG, NULL);
OSMO_ASSERT(fi);
osmo_fsm_inst_update_id_f_sanitize(fi, '-', "%s-RUA-%u-RAB-%u", hnb_context_name(map->hnb_ctx), map->rua_ctx_id,
rab_id);
@@ -96,7 +96,7 @@
OSMO_ASSERT(rab);
*rab = (struct ps_rab){
.fi = fi,
- .hnb_gw = map->hnb_ctx->gw,
+ .hnb_gw = map->gw,
.map = map,
.rab_id = rab_id,
.use_count = {
@@ -683,6 +683,7 @@
static void ps_rab_forget_map(struct ps_rab *rab)
{
+ /* remove from map->ps_rabs */
if (rab->map)
llist_del(&rab->entry);
rab->map = NULL;
diff --git a/src/osmo-hnbgw/tdefs.c b/src/osmo-hnbgw/tdefs.c
index d798345..7af292d 100644
--- a/src/osmo-hnbgw/tdefs.c
+++ b/src/osmo-hnbgw/tdefs.c
@@ -36,9 +36,15 @@
{ }
};
+struct osmo_tdef cmap_T_defs[] = {
+ {.T = -31, .default_val = 5, .desc = "Timeout for discarding a partially released context map (RUA <-> SCCP)" },
+ { }
+};
+
struct osmo_tdef_group hnbgw_tdef_group[] = {
{.name = "mgw", .tdefs = mgw_fsm_T_defs, .desc = "MGW (Media Gateway) interface" },
{.name = "ps", .tdefs = ps_T_defs, .desc = "timers for Packet Switched domain" },
+ {.name = "cmap", .tdefs = cmap_T_defs, .desc = "timers for context maps (RUA <-> SCCP)" },
#if ENABLE_PFCP
{.name = "pfcp", .tdefs = osmo_pfcp_tdefs, .desc = "PFCP timers" },
#endif
--
To view, visit https://gerrit.osmocom.org/c/osmo-hnbgw/+/31431
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-hnbgw
Gerrit-Branch: master
Gerrit-Change-Id: I6ff7e36532ff57c6f2d3e7e419dd22ef27dafd19
Gerrit-Change-Number: 31431
Gerrit-PatchSet: 7
Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: neels <nhofmeyr(a)sysmocom.de>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-CC: msuraev <msuraev(a)sysmocom.de>
Gerrit-MessageType: merged
Attention is currently required from: osmith.
pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-bsc/+/31550 )
Change subject: bssmap_handle_ass_req_tp_codec_list: tweak log msg
......................................................................
Patch Set 1:
(1 comment)
Commit Message:
https://gerrit.osmocom.org/c/osmo-bsc/+/31550/comment/005fd846_82b7e708
PS1, Line 9: Remove "speech mode" from the log message, as it is relevant for CSD
as it is not relevant?
--
To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/31550
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: Idfab0b7f6e97a6b67d140f967ddfe9b29818586e
Gerrit-Change-Number: 31550
Gerrit-PatchSet: 1
Gerrit-Owner: osmith <osmith(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-CC: pespin <pespin(a)sysmocom.de>
Gerrit-Attention: osmith <osmith(a)sysmocom.de>
Gerrit-Comment-Date: Mon, 27 Feb 2023 17:16:15 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Gerrit-MessageType: comment
Attention is currently required from: pespin.
fixeria has posted comments on this change. ( https://gerrit.osmocom.org/c/osmocom-bb/+/31572 )
Change subject: modem: route L1CTL prims to/from libosmo-gprs-rlcmac
......................................................................
Patch Set 1:
(1 comment)
File src/host/layer23/src/modem/rlcmac.c:
https://gerrit.osmocom.org/c/osmocom-bb/+/31572/comment/95f1298e_5086dbe9
PS1, Line 173: rlcmac_prim_l1ctl_alloc
> I see no real need to expose it
Somehow I expected this answer :/ Sad.
> you can simply use the existing API and still fill it afterwards
I want to fill it once in one place. And I like using designated initializer for that.
> Some of those alloc APIs doesn't really even let you set all the params
This is another argument to expose the alloc API: limitations of your template functions.
--
To view, visit https://gerrit.osmocom.org/c/osmocom-bb/+/31572
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmocom-bb
Gerrit-Branch: master
Gerrit-Change-Id: I38e9a686f8edc3fe55f961d75e68602c33bbbaaf
Gerrit-Change-Number: 31572
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-Attention: pespin <pespin(a)sysmocom.de>
Gerrit-Comment-Date: Mon, 27 Feb 2023 17:15:38 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: pespin <pespin(a)sysmocom.de>
Comment-In-Reply-To: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-MessageType: comment
Attention is currently required from: osmith.
pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-bsc/+/31549 )
Change subject: rsl_tx_ipacc_crcx/mdcx: omit speech mode for CSD
......................................................................
Patch Set 1:
(1 comment)
File src/osmo-bsc/abis_rsl.c:
https://gerrit.osmocom.org/c/osmo-bsc/+/31549/comment/27e67f91_3ac1fbaa
PS1, Line 2747: if (lchan->abis_ip.rtp_payload == RTP_PT_CSDATA)
match {} with else below.
--
To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/31549
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: I6641b713177276bcf798f08123e1dd2e88ffdce6
Gerrit-Change-Number: 31549
Gerrit-PatchSet: 1
Gerrit-Owner: osmith <osmith(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-CC: pespin <pespin(a)sysmocom.de>
Gerrit-Attention: osmith <osmith(a)sysmocom.de>
Gerrit-Comment-Date: Mon, 27 Feb 2023 17:14:27 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Gerrit-MessageType: comment
Attention is currently required from: osmith.
pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-bsc/+/31544 )
Change subject: codec_pref: split test_codec_support_bts_rate
......................................................................
Patch Set 1:
(1 comment)
File src/osmo-bsc/codec_pref.c:
https://gerrit.osmocom.org/c/osmo-bsc/+/31544/comment/7d7596b4_cb1af3b7
PS1, Line 211: if (rc < 0 || !test_codec_support_bts_rate(bts, full_rate))
this looks a bit weird/condensed, you could split it into 2 ifs like it was before.
--
To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/31544
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: Iea8a23ef3c66ed556110038fe9f3bc7f6eef3e96
Gerrit-Change-Number: 31544
Gerrit-PatchSet: 1
Gerrit-Owner: osmith <osmith(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-CC: pespin <pespin(a)sysmocom.de>
Gerrit-Attention: osmith <osmith(a)sysmocom.de>
Gerrit-Comment-Date: Mon, 27 Feb 2023 17:05:05 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Gerrit-MessageType: comment
Attention is currently required from: osmith.
pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-bsc/+/31547 )
Change subject: bssmap_handle_ass_req_ct_data: implement
......................................................................
Patch Set 1:
(1 comment)
File include/osmocom/bsc/codec_pref.h:
https://gerrit.osmocom.org/c/osmo-bsc/+/31547/comment/2371e5e3_3a7ca2c7
PS1, Line 22: const bool full_rate);
I wonder why is enum rate_pref rate_pref not used here.
--
To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/31547
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: I350bea15fd2158eb6edc9bc92f2dca48930736e9
Gerrit-Change-Number: 31547
Gerrit-PatchSet: 1
Gerrit-Owner: osmith <osmith(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-CC: pespin <pespin(a)sysmocom.de>
Gerrit-Attention: osmith <osmith(a)sysmocom.de>
Gerrit-Comment-Date: Mon, 27 Feb 2023 16:58:13 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Gerrit-MessageType: comment
Attention is currently required from: fixeria, dexter.
pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-pcu/+/31574 )
Change subject: pcu_l1_if_phy: add new PHY API function to initialize PHY
......................................................................
Patch Set 1: Code-Review+1
--
To view, visit https://gerrit.osmocom.org/c/osmo-pcu/+/31574
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-pcu
Gerrit-Branch: master
Gerrit-Change-Id: Ibf2a3a058c826f6ee5b740eee72d5be94d460517
Gerrit-Change-Number: 31574
Gerrit-PatchSet: 1
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Attention: dexter <pmaier(a)sysmocom.de>
Gerrit-Comment-Date: Mon, 27 Feb 2023 16:48:27 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
Gerrit-MessageType: comment
Attention is currently required from: fixeria.
pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmocom-bb/+/31572 )
Change subject: modem: route L1CTL prims to/from libosmo-gprs-rlcmac
......................................................................
Patch Set 1:
(1 comment)
File src/host/layer23/src/modem/rlcmac.c:
https://gerrit.osmocom.org/c/osmocom-bb/+/31572/comment/480729a8_eb12055e
PS1, Line 173: rlcmac_prim_l1ctl_alloc
> > ... which alone takes almost the entire line on my screen […]
I see no real need to expose it, you can simply use the existing API and still fill it afterwards as you please. Some of those alloc APIs doesn't really even let you set all the params, just a few most relevant ones.
Passing multiple arguments: use multiple lines.
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_data_ind({1,2,3,...});
rlcmac_prim->l1ctl = ....
--
To view, visit https://gerrit.osmocom.org/c/osmocom-bb/+/31572
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmocom-bb
Gerrit-Branch: master
Gerrit-Change-Id: I38e9a686f8edc3fe55f961d75e68602c33bbbaaf
Gerrit-Change-Number: 31572
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Comment-Date: Mon, 27 Feb 2023 16:47:19 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-MessageType: comment