Attention is currently required from: fixeria, laforge, osmith, pespin.
Hello Jenkins Builder, fixeria, laforge, osmith,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/libosmo-pfcp/+/38622?usp=email
to look at the new patch set (#3).
The following approvals got outdated and were removed:
Code-Review+1 by laforge
Change subject: pfcp: Add APIs to access struct osmo_pfcp_cp_peer
......................................................................
pfcp: Add APIs to access struct osmo_pfcp_cp_peer
Provide APIs so that users don't need to know the struct layout.
Change-Id: Ic8a5d5ec4237aa8520d426252c924c9617d1d08a
---
M TODO-RELEASE
M include/osmocom/pfcp/pfcp_cp_peer.h
M src/libosmo-pfcp/pfcp_cp_peer.c
3 files changed, 28 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-pfcp refs/changes/22/38622/3
--
To view, visit https://gerrit.osmocom.org/c/libosmo-pfcp/+/38622?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newpatchset
Gerrit-Project: libosmo-pfcp
Gerrit-Branch: master
Gerrit-Change-Id: Ic8a5d5ec4237aa8520d426252c924c9617d1d08a
Gerrit-Change-Number: 38622
Gerrit-PatchSet: 3
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: osmith <osmith(a)sysmocom.de>
Gerrit-Attention: osmith <osmith(a)sysmocom.de>
Gerrit-Attention: laforge <laforge(a)osmocom.org>
Gerrit-Attention: pespin <pespin(a)sysmocom.de>
Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de>
Attention is currently required from: fixeria, laforge, osmith, pespin.
Hello Jenkins Builder, fixeria, laforge, osmith,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/libosmo-pfcp/+/38612?usp=email
to look at the new patch set (#5).
The following approvals got outdated and were removed:
Code-Review+1 by laforge
Change subject: pfcp: Make struct osmo_pfcp_cp_peer private
......................................................................
pfcp: Make struct osmo_pfcp_cp_peer private
Only user of this lib so far, osmo-hnbgw, will get patches so that
it doesn't access the struct.
Make it private before anybody else starts using it.
Change-Id: I7f79ce239cb3c57bae2cf5846edf71e1aa03fa95
---
M TODO-RELEASE
M include/osmocom/pfcp/Makefile.am
M include/osmocom/pfcp/pfcp_cp_peer.h
A include/osmocom/pfcp/pfcp_cp_peer_private.h
M src/libosmo-pfcp/pfcp_cp_peer.c
5 files changed, 57 insertions(+), 18 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-pfcp refs/changes/12/38612/5
--
To view, visit https://gerrit.osmocom.org/c/libosmo-pfcp/+/38612?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newpatchset
Gerrit-Project: libosmo-pfcp
Gerrit-Branch: master
Gerrit-Change-Id: I7f79ce239cb3c57bae2cf5846edf71e1aa03fa95
Gerrit-Change-Number: 38612
Gerrit-PatchSet: 5
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: osmith <osmith(a)sysmocom.de>
Gerrit-Attention: osmith <osmith(a)sysmocom.de>
Gerrit-Attention: laforge <laforge(a)osmocom.org>
Gerrit-Attention: pespin <pespin(a)sysmocom.de>
Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de>
laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-bts/+/38558?usp=email )
(
1 is the latest approved patch-set.
No files were changed between the latest approved patch-set and the submitted one.
)Change subject: cosmetic: eliminate else-after-return in gsmtap_csd_rlp_process()
......................................................................
cosmetic: eliminate else-after-return in gsmtap_csd_rlp_process()
The code in this function used else-after-return constructs, which
are now rejected by the linter for newly committed code. This
function needs to be moved to a new source file, which will cause
it to be treated as new code by the linter - hence fix this code
style issue first.
Change-Id: Ide00e819222bb0173eca42ee3714db7f7e1a6d1e
---
M src/common/l1sap.c
1 file changed, 4 insertions(+), 6 deletions(-)
Approvals:
Jenkins Builder: Verified
pespin: Looks good to me, but someone else must approve
fixeria: Looks good to me, approved
diff --git a/src/common/l1sap.c b/src/common/l1sap.c
index 1abc409..fdbd4bc 100644
--- a/src/common/l1sap.c
+++ b/src/common/l1sap.c
@@ -1977,10 +1977,9 @@
if (e7 == 0) {
osmo_ubit2pbit_ext(rlp_buf, 0, data, 0, data_len, 1);
return;
- } else {
- osmo_ubit2pbit_ext(rlp_buf, 120, data, 0, data_len, 1);
- byte_len = 240/8;
}
+ osmo_ubit2pbit_ext(rlp_buf, 120, data, 0, data_len, 1);
+ byte_len = 240/8;
} else if (lchan->type == GSM_LCHAN_TCH_F && lchan->tch_mode == GSM48_CMODE_DATA_14k5) {
/* in this mode we have 290bit MAC blocks containing M1, M2 and 288 data bits;
* two of them need to be concatenated to render a
@@ -1991,10 +1990,9 @@
if (m1 == 0) {
osmo_ubit2pbit_ext(rlp_buf, 0, data, 2, data_len, 1);
return;
- } else {
- osmo_ubit2pbit_ext(rlp_buf, 288, data, 2, data_len, 1);
- byte_len = 576/8;
}
+ osmo_ubit2pbit_ext(rlp_buf, 288, data, 2, data_len, 1);
+ byte_len = 576/8;
} else {
byte_len = osmo_ubit2pbit_ext(rlp_buf, 0, data, 0, data_len, 1);
}
--
To view, visit https://gerrit.osmocom.org/c/osmo-bts/+/38558?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: merged
Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Change-Id: Ide00e819222bb0173eca42ee3714db7f7e1a6d1e
Gerrit-Change-Number: 38558
Gerrit-PatchSet: 2
Gerrit-Owner: falconia <falcon(a)freecalypso.org>
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>
laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-bts/+/38559?usp=email )
(
1 is the latest approved patch-set.
No files were changed between the latest approved patch-set and the submitted one.
)Change subject: cosmetic: move gsmtap_csd_rlp_process() to csd_rlp.c
......................................................................
cosmetic: move gsmtap_csd_rlp_process() to csd_rlp.c
The next patch in the series will add code for alignment of downlink
RLP frames in CSD NT modes; that code will go into new file csd_rlp.c.
RLP GSMTAP code logically belongs in the same place - hence move it
there in preparation.
Change-Id: I824ce6614c8591cccc5f6bcdde767fe49d551378
---
M include/osmo-bts/Makefile.am
A include/osmo-bts/csd_rlp.h
M src/common/Makefile.am
A src/common/csd_rlp.c
M src/common/l1sap.c
5 files changed, 137 insertions(+), 76 deletions(-)
Approvals:
fixeria: Looks good to me, approved
Jenkins Builder: Verified
pespin: Looks good to me, but someone else must approve
diff --git a/include/osmo-bts/Makefile.am b/include/osmo-bts/Makefile.am
index cbd0fc3..1922f0d 100644
--- a/include/osmo-bts/Makefile.am
+++ b/include/osmo-bts/Makefile.am
@@ -24,6 +24,7 @@
tx_power.h \
control_if.h \
cbch.h \
+ csd_rlp.h \
csd_v110.h \
l1sap.h \
lchan.h \
diff --git a/include/osmo-bts/csd_rlp.h b/include/osmo-bts/csd_rlp.h
new file mode 100644
index 0000000..fd4c6e7
--- /dev/null
+++ b/include/osmo-bts/csd_rlp.h
@@ -0,0 +1,16 @@
+/*
+ * Declarations for functions in csd_rlp.c: alignment of downlink RLP frames
+ * and RLP GSMTAP mechanism for CSD NT modes.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <osmocom/core/bits.h>
+#include <osmocom/gsm/l1sap.h>
+#include <osmo-bts/lchan.h>
+
+void gsmtap_csd_rlp_process(struct gsm_lchan *lchan, bool is_uplink,
+ const struct ph_tch_param *tch_ind,
+ const ubit_t *data, unsigned int data_len);
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index d13415d..1a62e8e 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -51,6 +51,7 @@
bts_ctrl_commands.c \
bts_ctrl_lookup.c \
bts_shutdown_fsm.c \
+ csd_rlp.c \
csd_v110.c \
l1sap.c \
cbch.c \
diff --git a/src/common/csd_rlp.c b/src/common/csd_rlp.c
new file mode 100644
index 0000000..aa4fdd9
--- /dev/null
+++ b/src/common/csd_rlp.c
@@ -0,0 +1,118 @@
+/* This module has been split from l1sap.c; original header comments preserved:
+ *
+ * (C) 2011 by Harald Welte <laforge(a)gnumonks.org>
+ * (C) 2013 by Andreas Eversberg <jolly(a)eversberg.eu>
+ *
+ * All Rights Reserved
+ *
+ * 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 <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/l1sap.h>
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/gsm/rsl.h>
+#include <osmocom/gsm/rlp.h>
+#include <osmocom/gsm/rtp_extensions.h>
+#include <osmocom/core/gsmtap.h>
+#include <osmocom/core/gsmtap_util.h>
+#include <osmocom/core/utils.h>
+
+#include <osmo-bts/logging.h>
+#include <osmo-bts/gsm_data.h>
+#include <osmo-bts/lchan.h>
+#include <osmo-bts/bts.h>
+#include <osmo-bts/csd_rlp.h>
+
+/* process one MAC block of unpacked bits of a non-transparent CSD channel */
+void gsmtap_csd_rlp_process(struct gsm_lchan *lchan, bool is_uplink,
+ const struct ph_tch_param *tch_ind,
+ const ubit_t *data, unsigned int data_len)
+{
+ struct gsm_bts_trx *trx = lchan->ts->trx;
+ struct gsmtap_inst *inst = trx->bts->gsmtap.inst;
+ pbit_t *rlp_buf;
+ uint16_t arfcn;
+ int byte_len;
+
+ if (!inst || !trx->bts->gsmtap.rlp)
+ return;
+
+ if (lchan->csd_mode != LCHAN_CSD_M_NT)
+ return;
+
+ if (is_uplink)
+ rlp_buf = lchan->tch.csd.rlp_buf_ul;
+ else
+ rlp_buf = lchan->tch.csd.rlp_buf_dl;
+
+ /* TCH/F 9.6: 4x60bit block => 240bit RLP frame
+ * TCH/F 4.8: 2x 2x60bit blocks starting at B0/B2/B4 => 240bit RLP frame
+ * TCH/H 4.8: 4x60bit block => 240bit RLP frame
+ * TCH/F 2.4: 2x36bit blocks => transparent only
+ * TCH/H 2.4: 4x36bit blocks => transparent only
+ * TCH/F 14.4: 2x 290 bit block (starting with M1=0) => 576-bit RLP frame
+ */
+
+ if (lchan->type == GSM_LCHAN_TCH_F && lchan->tch_mode == GSM48_CMODE_DATA_6k0) {
+ /* in this mode we have 120bit MAC blocks; two of them need to be concatenated
+ * to render a 240-bit RLP frame. The fist block is present in B0/B2/B4.
+ * The E7 bit is used to indicate the Frame MF0a */
+ OSMO_ASSERT(data_len == 120);
+ ubit_t e7 = data[4*7+3];
+ if (e7 == 0) {
+ osmo_ubit2pbit_ext(rlp_buf, 0, data, 0, data_len, 1);
+ return;
+ }
+ osmo_ubit2pbit_ext(rlp_buf, 120, data, 0, data_len, 1);
+ byte_len = 240/8;
+ } else if (lchan->type == GSM_LCHAN_TCH_F && lchan->tch_mode == GSM48_CMODE_DATA_14k5) {
+ /* in this mode we have 290bit MAC blocks containing M1, M2 and 288 data bits;
+ * two of them need to be concatenated to render a
+ * 576-bit RLP frame. The start of a RLP frame is
+ * denoted by a block with M1-bit set to 0. */
+ OSMO_ASSERT(data_len == 290);
+ ubit_t m1 = data[0];
+ if (m1 == 0) {
+ osmo_ubit2pbit_ext(rlp_buf, 0, data, 2, data_len, 1);
+ return;
+ }
+ osmo_ubit2pbit_ext(rlp_buf, 288, data, 2, data_len, 1);
+ byte_len = 576/8;
+ } else {
+ byte_len = osmo_ubit2pbit_ext(rlp_buf, 0, data, 0, data_len, 1);
+ }
+
+ if (trx->bts->gsmtap.rlp_skip_null) {
+ struct osmo_rlp_frame_decoded rlpf;
+ int rc = osmo_rlp_decode(&rlpf, 0, rlp_buf, byte_len);
+ if (rc == 0 && rlpf.ftype == OSMO_RLP_FT_U && rlpf.u_ftype == OSMO_RLP_U_FT_NULL)
+ return;
+ }
+
+ arfcn = trx->arfcn;
+ if (is_uplink)
+ arfcn |= GSMTAP_ARFCN_F_UPLINK;
+
+ gsmtap_send_ex(inst, GSMTAP_TYPE_GSM_RLP, arfcn, lchan->ts->nr,
+ lchan->type == GSM_LCHAN_TCH_H ? GSMTAP_CHANNEL_VOICE_H : GSMTAP_CHANNEL_VOICE_F,
+ lchan->nr, tch_ind->fn, tch_ind->rssi, 0, rlp_buf, byte_len);
+
+}
diff --git a/src/common/l1sap.c b/src/common/l1sap.c
index fdbd4bc..aab69c5 100644
--- a/src/common/l1sap.c
+++ b/src/common/l1sap.c
@@ -60,6 +60,7 @@
#include <osmo-bts/pcuif_proto.h>
#include <osmo-bts/cbch.h>
#include <osmo-bts/asci.h>
+#include <osmo-bts/csd_rlp.h>
#include <osmo-bts/csd_v110.h>
/* determine the CCCH block number based on the frame number */
@@ -1938,82 +1939,6 @@
return 1;
}
-/* process one MAC block of unpacked bits of a non-transparent CSD channel */
-static void gsmtap_csd_rlp_process(struct gsm_lchan *lchan, bool is_uplink,
- const struct ph_tch_param *tch_ind,
- const uint8_t *data, unsigned int data_len)
-{
- struct gsm_bts_trx *trx = lchan->ts->trx;
- struct gsmtap_inst *inst = trx->bts->gsmtap.inst;
- pbit_t *rlp_buf;
- uint16_t arfcn;
- int byte_len;
-
- if (!inst || !trx->bts->gsmtap.rlp)
- return;
-
- if (lchan->csd_mode != LCHAN_CSD_M_NT)
- return;
-
- if (is_uplink)
- rlp_buf = lchan->tch.csd.rlp_buf_ul;
- else
- rlp_buf = lchan->tch.csd.rlp_buf_dl;
-
- /* TCH/F 9.6: 4x60bit block => 240bit RLP frame
- * TCH/F 4.8: 2x 2x60bit blocks starting at B0/B2/B4 => 240bit RLP frame
- * TCH/H 4.8: 4x60bit block => 240bit RLP frame
- * TCH/F 2.4: 2x36bit blocks => transparent only
- * TCH/H 2.4: 4x36bit blocks => transparent only
- * TCH/F 14.4: 2x 290 bit block (starting with M1=0) => 576-bit RLP frame
- */
-
- if (lchan->type == GSM_LCHAN_TCH_F && lchan->tch_mode == GSM48_CMODE_DATA_6k0) {
- /* in this mode we have 120bit MAC blocks; two of them need to be concatenated
- * to render a 240-bit RLP frame. The fist block is present in B0/B2/B4.
- * The E7 bit is used to indicate the Frame MF0a */
- OSMO_ASSERT(data_len == 120);
- ubit_t e7 = data[4*7+3];
- if (e7 == 0) {
- osmo_ubit2pbit_ext(rlp_buf, 0, data, 0, data_len, 1);
- return;
- }
- osmo_ubit2pbit_ext(rlp_buf, 120, data, 0, data_len, 1);
- byte_len = 240/8;
- } else if (lchan->type == GSM_LCHAN_TCH_F && lchan->tch_mode == GSM48_CMODE_DATA_14k5) {
- /* in this mode we have 290bit MAC blocks containing M1, M2 and 288 data bits;
- * two of them need to be concatenated to render a
- * 576-bit RLP frame. The start of a RLP frame is
- * denoted by a block with M1-bit set to 0. */
- OSMO_ASSERT(data_len == 290);
- ubit_t m1 = data[0];
- if (m1 == 0) {
- osmo_ubit2pbit_ext(rlp_buf, 0, data, 2, data_len, 1);
- return;
- }
- osmo_ubit2pbit_ext(rlp_buf, 288, data, 2, data_len, 1);
- byte_len = 576/8;
- } else {
- byte_len = osmo_ubit2pbit_ext(rlp_buf, 0, data, 0, data_len, 1);
- }
-
- if (trx->bts->gsmtap.rlp_skip_null) {
- struct osmo_rlp_frame_decoded rlpf;
- int rc = osmo_rlp_decode(&rlpf, 0, rlp_buf, byte_len);
- if (rc == 0 && rlpf.ftype == OSMO_RLP_FT_U && rlpf.u_ftype == OSMO_RLP_U_FT_NULL)
- return;
- }
-
- arfcn = trx->arfcn;
- if (is_uplink)
- arfcn |= GSMTAP_ARFCN_F_UPLINK;
-
- gsmtap_send_ex(inst, GSMTAP_TYPE_GSM_RLP, arfcn, lchan->ts->nr,
- lchan->type == GSM_LCHAN_TCH_H ? GSMTAP_CHANNEL_VOICE_H : GSMTAP_CHANNEL_VOICE_F,
- lchan->nr, tch_ind->fn, tch_ind->rssi, 0, rlp_buf, byte_len);
-
-}
-
/* a helper function for the logic in l1sap_tch_ind() */
static void send_ul_rtp_packet(struct gsm_lchan *lchan, uint32_t fn,
const uint8_t *rtp_pl, uint16_t rtp_pl_len)
--
To view, visit https://gerrit.osmocom.org/c/osmo-bts/+/38559?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: merged
Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Change-Id: I824ce6614c8591cccc5f6bcdde767fe49d551378
Gerrit-Change-Number: 38559
Gerrit-PatchSet: 2
Gerrit-Owner: falconia <falcon(a)freecalypso.org>
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>
laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-bts/+/38557?usp=email )
Change subject: CSD NT modes: transmit properly aligned RLP frames on DL
......................................................................
CSD NT modes: transmit properly aligned RLP frames on DL
There are two levels of alignment inside clearmode RTP packets
carrying CSData per TS 48.103 section 5.6:
1) Alignment of 2 or 4 V.110 (T) or pseudo-V.110 (NT) frames within
one RTP packet of 160 octets of an imaginary ISDN B channel;
2) For NT modes only, alignment of 4 pseudo-V.110 frames to form
a single 240-bit RLP frame.
Per previous patch, alignment 1 is to be treated as mandatory for
RTP transport inside an Osmocom network. Alignment 2 _could_ be
made mandatory for TCH/F9.6 NT, but the same is not possible for
TCH/[FH]4.8 NT: in the best case of half-alignment, alternating
RTP packets will carry alternating halves of RLP frames.
Implemented solution: allow arbitrary state of alignment 2
(aligned or misaligned) in the incoming RTP stream for all CSD NT
modes, and perform the necessary alignment internally.
This approach is consistent with the world of E1 BTS: a TRAU in
data mode is responsible for alignment 1 (with 20 ms TRAU frames
taking the place of our clearmode RTP packets), but only the BTS can
perform alignment 2, as the TRAU is agnostic to T vs NT distinction.
Related: OS#6579
Change-Id: Idaebfce6da13b23ba265a197502712d83991873e
---
M include/osmo-bts/csd_rlp.h
M include/osmo-bts/lchan.h
M src/common/csd_rlp.c
M src/common/l1sap.c
4 files changed, 301 insertions(+), 29 deletions(-)
Approvals:
Jenkins Builder: Verified
pespin: Looks good to me, but someone else must approve
laforge: Looks good to me, but someone else must approve
fixeria: Looks good to me, approved
diff --git a/include/osmo-bts/csd_rlp.h b/include/osmo-bts/csd_rlp.h
index fd4c6e7..94fa3d2 100644
--- a/include/osmo-bts/csd_rlp.h
+++ b/include/osmo-bts/csd_rlp.h
@@ -11,6 +11,26 @@
#include <osmocom/gsm/l1sap.h>
#include <osmo-bts/lchan.h>
+extern const uint8_t csd_tchf48_nt_e2_map[26];
+
+/* Per TS 48.020 section 15.1, the cadence of E2+E3 bits in a properly
+ * aligned sequence of pseudo-V.110 frames forming a single RLP frame
+ * is 00-01-10-11. The following constant captures this bit sequence
+ * in hex, for comparison against align_bits output from
+ * csd_v110_rtp_decode() or against rlpdl_align_bits accumulator
+ * in CSD NT lchan state.
+ */
+#define NTCSD_ALIGNED_EBITS 0x1B
+
+void ntcsd_dl_reset(struct gsm_lchan *lchan);
+void ntcsd_dl_input_48(struct gsm_lchan *lchan, const ubit_t *data_bits,
+ uint8_t align_bits);
+void ntcsd_dl_input_96(struct gsm_lchan *lchan, const ubit_t *data_bits,
+ uint8_t align_bits);
+bool ntcsd_dl_output(struct gsm_lchan *lchan, ubit_t *rlp_frame_out);
+
void gsmtap_csd_rlp_process(struct gsm_lchan *lchan, bool is_uplink,
const struct ph_tch_param *tch_ind,
const ubit_t *data, unsigned int data_len);
+void gsmtap_csd_rlp_dl(struct gsm_lchan *lchan, uint32_t fn,
+ const ubit_t *data, unsigned int data_len);
diff --git a/include/osmo-bts/lchan.h b/include/osmo-bts/lchan.h
index df2f4fa..5c34015 100644
--- a/include/osmo-bts/lchan.h
+++ b/include/osmo-bts/lchan.h
@@ -4,6 +4,7 @@
#include <stdint.h>
#include <netinet/in.h>
+#include <osmocom/core/bits.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/logging.h>
@@ -295,9 +296,14 @@
uint8_t last_cmr;
uint32_t last_fn;
struct {
- /* buffers to re-combine RLP frame from multiple Um blocks */
+ /* RLP GSMTAP mechanism */
uint8_t rlp_buf_ul[576/8]; /* maximum size of RLP frame */
uint8_t rlp_buf_dl[576/8]; /* maximum size of RLP frame */
+ /* alignment of RLP frames in DL for NT modes */
+ ubit_t rlpdl_data_bits[60 * 7];
+ uint16_t rlpdl_align_bits;
+ uint8_t rlpdl_fill_level;
+ ubit_t tchf48_nt_2ndhalf[120];
} csd;
} tch;
diff --git a/src/common/csd_rlp.c b/src/common/csd_rlp.c
index aa4fdd9..349094c 100644
--- a/src/common/csd_rlp.c
+++ b/src/common/csd_rlp.c
@@ -41,6 +41,102 @@
#include <osmo-bts/bts.h>
#include <osmo-bts/csd_rlp.h>
+/* In the case of TCH/F4.8 NT, each 240-bit RLP frame is split between
+ * two channel-coding blocks of 120 bits each. We need to know which
+ * frame numbers correspond to which half: in the UL-to-RTP path we have
+ * to set bit E2 based on the TDMA frame number at which we received the
+ * block in question, and in the DL direction we have to transmit the
+ * right half at the right time.
+ *
+ * See GSM 05.03 section 3.4.1 and the mapping tables of GSM 05.02;
+ * having "e2_map" in the array name shall serve as a mnemonic as to
+ * the sense of this array: 0 means 1st half and 1 means 2nd half,
+ * exactly as the value of bit E2 per TS 48.020 section 15.1.
+ */
+const uint8_t csd_tchf48_nt_e2_map[26] = {
+ [4] = 1, /* B1 position */
+ [13] = 1, /* B3 position */
+ [21] = 1, /* B5 position */
+};
+
+/* This function resets (clears) the state of the DL alignment buffer.
+ * It needs to be called when we encounter a gap (packet loss, invalid
+ * packets, etc) in our RTP input stream. */
+void ntcsd_dl_reset(struct gsm_lchan *lchan)
+{
+ lchan->tch.csd.rlpdl_fill_level = 0;
+}
+
+/* This function is to be called with the decoded content of a single
+ * incoming RTP packet (data and alignment bits) for TCH/[FH]4.8 NT. */
+void ntcsd_dl_input_48(struct gsm_lchan *lchan, const ubit_t *data_bits,
+ uint8_t align_bits)
+{
+ memmove(lchan->tch.csd.rlpdl_data_bits,
+ lchan->tch.csd.rlpdl_data_bits + 60 * 2, 60 * 5);
+ memcpy(lchan->tch.csd.rlpdl_data_bits + 60 * 5, data_bits, 60 * 2);
+ lchan->tch.csd.rlpdl_align_bits <<= 4;
+ lchan->tch.csd.rlpdl_align_bits |= (align_bits & 0xF);
+ lchan->tch.csd.rlpdl_fill_level += 2;
+ if (lchan->tch.csd.rlpdl_fill_level > 7)
+ lchan->tch.csd.rlpdl_fill_level = 7;
+}
+
+/* This function is to be called with the decoded content of a single
+ * incoming RTP packet (data and alignment bits) for TCH/F9.6 NT. */
+void ntcsd_dl_input_96(struct gsm_lchan *lchan, const ubit_t *data_bits,
+ uint8_t align_bits)
+{
+ memmove(lchan->tch.csd.rlpdl_data_bits,
+ lchan->tch.csd.rlpdl_data_bits + 60 * 4, 60 * 3);
+ memcpy(lchan->tch.csd.rlpdl_data_bits + 60 * 3, data_bits, 60 * 4);
+ lchan->tch.csd.rlpdl_align_bits <<= 8;
+ lchan->tch.csd.rlpdl_align_bits |= (align_bits & 0xFF);
+ lchan->tch.csd.rlpdl_fill_level += 4;
+ if (lchan->tch.csd.rlpdl_fill_level > 7)
+ lchan->tch.csd.rlpdl_fill_level = 7;
+}
+
+/* This function is to be called to obtain a complete RLP frame for
+ * downlink transmission. It will provide either a properly aligned
+ * frame (return value true) or a filler (return value false). */
+bool ntcsd_dl_output(struct gsm_lchan *lchan, ubit_t *rlp_frame_out)
+{
+ if (lchan->tch.csd.rlpdl_fill_level < 4)
+ goto no_frame_out;
+ if (((lchan->tch.csd.rlpdl_align_bits >> 0) & 0xFF) == NTCSD_ALIGNED_EBITS) {
+ memcpy(rlp_frame_out, lchan->tch.csd.rlpdl_data_bits + 60 * 3,
+ 60 * 4);
+ return true;
+ }
+ if (lchan->tch.csd.rlpdl_fill_level < 5)
+ goto no_frame_out;
+ if (((lchan->tch.csd.rlpdl_align_bits >> 2) & 0xFF) == NTCSD_ALIGNED_EBITS) {
+ memcpy(rlp_frame_out, lchan->tch.csd.rlpdl_data_bits + 60 * 2,
+ 60 * 4);
+ return true;
+ }
+ if (lchan->tch.csd.rlpdl_fill_level < 6)
+ goto no_frame_out;
+ if (((lchan->tch.csd.rlpdl_align_bits >> 4) & 0xFF) == NTCSD_ALIGNED_EBITS) {
+ memcpy(rlp_frame_out, lchan->tch.csd.rlpdl_data_bits + 60 * 1,
+ 60 * 4);
+ return true;
+ }
+ if (lchan->tch.csd.rlpdl_fill_level < 7)
+ goto no_frame_out;
+ if (((lchan->tch.csd.rlpdl_align_bits >> 6) & 0xFF) == NTCSD_ALIGNED_EBITS) {
+ memcpy(rlp_frame_out, lchan->tch.csd.rlpdl_data_bits, 60 * 4);
+ return true;
+ }
+no_frame_out:
+ /* TS 44.021 section 12.1 says that a missing/unavailable 240-bit
+ * RLP frame is to be filled with 0 bits, unlike ones-fill
+ * used everywhere else in the world of V.110 and CSD. */
+ memset(rlp_frame_out, 0, 60 * 4);
+ return false;
+}
+
/* process one MAC block of unpacked bits of a non-transparent CSD channel */
void gsmtap_csd_rlp_process(struct gsm_lchan *lchan, bool is_uplink,
const struct ph_tch_param *tch_ind,
@@ -71,13 +167,17 @@
* TCH/F 14.4: 2x 290 bit block (starting with M1=0) => 576-bit RLP frame
*/
- if (lchan->type == GSM_LCHAN_TCH_F && lchan->tch_mode == GSM48_CMODE_DATA_6k0) {
- /* in this mode we have 120bit MAC blocks; two of them need to be concatenated
- * to render a 240-bit RLP frame. The fist block is present in B0/B2/B4.
- * The E7 bit is used to indicate the Frame MF0a */
+ if (lchan->type == GSM_LCHAN_TCH_F &&
+ lchan->tch_mode == GSM48_CMODE_DATA_6k0 && is_uplink) {
+ /* In this mode we have 120-bit MAC blocks; two of them need
+ * to be concatenated to render a 240-bit RLP frame. The first
+ * block is present in B0/B2/B4, and we have to use FN to
+ * detect this position.
+ * This code path is only for UL: in the case of DL,
+ * alignment logic elsewhere in the code will present us
+ * with a fully assembled RLP frame. */
OSMO_ASSERT(data_len == 120);
- ubit_t e7 = data[4*7+3];
- if (e7 == 0) {
+ if (csd_tchf48_nt_e2_map[tch_ind->fn % 26] == 0) {
osmo_ubit2pbit_ext(rlp_buf, 0, data, 0, data_len, 1);
return;
}
@@ -116,3 +216,13 @@
lchan->nr, tch_ind->fn, tch_ind->rssi, 0, rlp_buf, byte_len);
}
+
+/* wrapper for downlink path */
+void gsmtap_csd_rlp_dl(struct gsm_lchan *lchan, uint32_t fn,
+ const ubit_t *data, unsigned int data_len)
+{
+ /* 'fake' tch_ind containing all-zero so gsmtap code can be shared
+ * between UL and DL */
+ const struct ph_tch_param fake_tch_ind = { .fn = fn };
+ gsmtap_csd_rlp_process(lchan, false, &fake_tch_ind, data, data_len);
+}
diff --git a/src/common/l1sap.c b/src/common/l1sap.c
index aab69c5..06ab051 100644
--- a/src/common/l1sap.c
+++ b/src/common/l1sap.c
@@ -1540,17 +1540,37 @@
&lchan->dl_tch_queue_len);
}
+ if (lchan->csd_mode == LCHAN_CSD_M_NT) {
+ for (i = 0; i < ARRAY_SIZE(input_msg); i++) {
+ if (input_msg[i]) {
+ ntcsd_dl_input_48(lchan, input_msg[i]->data,
+ rtpmsg_csd_align_bits(input_msg[i]));
+ } else {
+ ntcsd_dl_reset(lchan);
+ }
+ }
+ }
+
phy_msg = l1sap_msgb_alloc(bits_per_20ms * 2);
if (phy_msg) {
resp_l1sap = msgb_l1sap_prim(phy_msg);
phy_msg->l2h = phy_msg->tail;
- for (i = 0; i < ARRAY_SIZE(input_msg); i++) {
- phy_data = msgb_put(phy_msg, bits_per_20ms);
- if (input_msg[i]) {
- memcpy(phy_data, input_msg[i]->data, bits_per_20ms);
- } else {
- /* IDLE frame, filled with 1 bits */
- memset(phy_data, 0x01, bits_per_20ms);
+ if (lchan->csd_mode == LCHAN_CSD_M_NT) {
+ bool good_rlp;
+ phy_data = msgb_put(phy_msg, 240); /* RLP frame */
+ good_rlp = ntcsd_dl_output(lchan, phy_data);
+ if (good_rlp)
+ gsmtap_csd_rlp_dl(lchan, fn, phy_data, 240);
+ } else {
+ for (i = 0; i < ARRAY_SIZE(input_msg); i++) {
+ phy_data = msgb_put(phy_msg, bits_per_20ms);
+ if (input_msg[i]) {
+ memcpy(phy_data, input_msg[i]->data,
+ bits_per_20ms);
+ } else {
+ /* IDLE frame, filled with 1 bits */
+ memset(phy_data, 0x01, bits_per_20ms);
+ }
}
}
} else {
@@ -1576,6 +1596,111 @@
return 0;
}
+/* The case of TCH/F4.8 NT also requires special processing that is
+ * somewhat similar to half-rate CSD. We have to produce an RLP frame
+ * for DL every 40 ms, thus it makes the most sense for us to poll
+ * the Rx jitter buffer every 40 ms just like with CSD-HR. However,
+ * we need to send TCH.req to the PHY every 20 ms, sending either
+ * the first half or the second half of the RLP frame we put together
+ * every 40 ms. */
+static int tch_rts_ind_tchf48_nt(struct gsm_bts_trx *trx,
+ struct gsm_lchan *lchan,
+ struct ph_tch_param *rts_ind)
+{
+ uint8_t chan_nr = rts_ind->chan_nr;
+ uint32_t fn = rts_ind->fn;
+ struct msgb *input_msg, *phy_msg;
+ struct osmo_phsap_prim *resp_l1sap, empty_l1sap;
+ ubit_t rlp_frame[240];
+ bool good_rlp;
+ struct gsm_time g_time;
+ int i;
+
+ gsm_fn2gsmtime(&g_time, fn);
+
+ /* Input processing happens every 40 ms */
+ if (csd_tchf48_nt_e2_map[fn % 26] == 0) {
+ for (i = 0; i < 2; i++) {
+ if (!lchan->loopback && lchan->abis_ip.rtp_socket) {
+ osmo_rtp_socket_poll(lchan->abis_ip.rtp_socket);
+ lchan->abis_ip.rtp_socket->rx_user_ts += GSM_RTP_DURATION;
+ }
+ input_msg = msgb_dequeue_count(&lchan->dl_tch_queue,
+ &lchan->dl_tch_queue_len);
+ if (input_msg) {
+ ntcsd_dl_input_48(lchan, input_msg->data,
+ rtpmsg_csd_align_bits(input_msg));
+ msgb_free(input_msg);
+ } else {
+ ntcsd_dl_reset(lchan);
+ }
+ }
+ good_rlp = ntcsd_dl_output(lchan, rlp_frame);
+ if (good_rlp)
+ gsmtap_csd_rlp_dl(lchan, fn, rlp_frame, 240);
+ memcpy(lchan->tch.csd.tchf48_nt_2ndhalf, rlp_frame+120, 120);
+ }
+
+ /* back to every 20 ms code path */
+ phy_msg = l1sap_msgb_alloc(120); /* half of RLP frame */
+ if (phy_msg) {
+ resp_l1sap = msgb_l1sap_prim(phy_msg);
+ phy_msg->l2h = msgb_put(phy_msg, 120);
+ if (csd_tchf48_nt_e2_map[fn % 26] == 0)
+ memcpy(phy_msg->l2h, rlp_frame, 120);
+ else
+ memcpy(phy_msg->l2h, lchan->tch.csd.tchf48_nt_2ndhalf, 120);
+ } else {
+ resp_l1sap = &empty_l1sap;
+ }
+
+ memset(resp_l1sap, 0, sizeof(*resp_l1sap));
+ osmo_prim_init(&resp_l1sap->oph, SAP_GSM_PH, PRIM_TCH, PRIM_OP_REQUEST,
+ phy_msg);
+ resp_l1sap->u.tch.chan_nr = chan_nr;
+ resp_l1sap->u.tch.fn = fn;
+ resp_l1sap->u.tch.marker = 0; /* M bit is undefined for clearmode */
+
+ LOGPLCGT(lchan, &g_time, DL1P, LOGL_DEBUG, "Tx TCH.req\n");
+
+ l1sap_down(trx, resp_l1sap);
+
+ return 0;
+}
+
+/* For TCH/F9.6 NT we need much less special processing than for TCH/F4.8 NT
+ * or for CSD-HR, but we still need to handle the possibility of misaligned
+ * RTP input, i.e., pseudo-V.110 frames aligned in the packet, but not
+ * forming proper RLP frame alignment via E2 & E3 bits. */
+static void tchf96_nt_dl_alignment(struct gsm_lchan *lchan, struct msgb *msg,
+ uint32_t fn)
+{
+ bool good_rlp;
+
+ if (!msg) {
+ ntcsd_dl_reset(lchan);
+ /* FIXME: do we really need to generate a PHY packet filled
+ * with 0 bits to satisfy TS 44.021 section 12.1, or can we
+ * get by with letting the PHY fill in ones like it does
+ * for all other CSD modes? */
+ return;
+ }
+ /* Fast path: handle the good case of already proper alignment */
+ if ((rtpmsg_csd_align_bits(msg) & 0xFF) == NTCSD_ALIGNED_EBITS) {
+ /* clear the buffer in case we have to do misaligned packets
+ * later, but otherwise let it go! */
+ ntcsd_dl_reset(lchan);
+ gsmtap_csd_rlp_dl(lchan, fn, msgb_l2(msg), msgb_l2len(msg));
+ return;
+ }
+ /* Slow path: realign like in other NT modes */
+ OSMO_ASSERT(msgb_l2len(msg) == 240);
+ ntcsd_dl_input_96(lchan, msgb_l2(msg), rtpmsg_csd_align_bits(msg));
+ good_rlp = ntcsd_dl_output(lchan, msgb_l2(msg));
+ if (good_rlp)
+ gsmtap_csd_rlp_dl(lchan, fn, msgb_l2(msg), msgb_l2len(msg));
+}
+
/* TCH-RTS-IND prim received from bts model */
static int l1sap_tch_rts_ind(struct gsm_bts_trx *trx,
struct osmo_phsap_prim *l1sap, struct ph_tch_param *rts_ind)
@@ -1601,8 +1726,14 @@
LOGPLCGT(lchan, &g_time, DL1P, LOGL_DEBUG, "Rx TCH-RTS.ind\n");
}
- if (lchan->rsl_cmode == RSL_CMOD_SPD_DATA && lchan->type == GSM_LCHAN_TCH_H)
+ /* CSD-HR requires special processing */
+ if (lchan->rsl_cmode == RSL_CMOD_SPD_DATA &&
+ lchan->type == GSM_LCHAN_TCH_H)
return tch_rts_ind_csd_hr(trx, lchan, rts_ind);
+ /* so does TCH/F4.8 NT mode */
+ if (lchan->tch_mode == GSM48_CMODE_DATA_6k0 &&
+ lchan->csd_mode == LCHAN_CSD_M_NT)
+ return tch_rts_ind_tchf48_nt(trx, lchan, rts_ind);
if (!lchan->loopback && lchan->abis_ip.rtp_socket) {
osmo_rtp_socket_poll(lchan->abis_ip.rtp_socket);
@@ -1650,6 +1781,24 @@
&resp_l1sap, &empty_l1sap);
}
+ /* minimal extra handling for the remaining CSD NT modes */
+ if (lchan->rsl_cmode == RSL_CMOD_SPD_DATA &&
+ lchan->csd_mode == LCHAN_CSD_M_NT) {
+ switch (lchan->tch_mode) {
+ case GSM48_CMODE_DATA_12k0:
+ tchf96_nt_dl_alignment(lchan, resp_msg, fn);
+ break;
+ case GSM48_CMODE_DATA_14k5:
+ gsmtap_csd_rlp_dl(lchan, fn, msgb_l2(resp_msg),
+ msgb_l2len(resp_msg));
+ break;
+ default:
+ LOGPLCGT(lchan, &g_time, DL1P, LOGL_ERROR,
+ "Invalid TCH mode in TCH-RTS.ind under CSD NT\n");
+ break;
+ }
+ }
+
memset(resp_l1sap, 0, sizeof(*resp_l1sap));
osmo_prim_init(&resp_l1sap->oph, SAP_GSM_PH, PRIM_TCH, PRIM_OP_REQUEST,
resp_msg);
@@ -1979,20 +2128,11 @@
lchan->rtp_tx_marker = false;
}
-/* In the case of TCH/F4.8 NT, we have to set bit E2 based on the TDMA
- * frame number at which we received the block in question. See
- * GSM 05.03 section 3.4.1 and the mapping tables of GSM 05.02. */
-static const uint8_t tchf48_nt_e2_map[26] = {
- [4] = 1, /* B1 position */
- [13] = 1, /* B3 position */
- [21] = 1, /* B5 position */
-};
-
static void handle_tch_ind_csd_fr(struct gsm_lchan *lchan, const struct ph_tch_param *tch_ind,
const uint8_t *data, uint16_t data_len)
{
uint8_t rtp_pl[RFC4040_RTP_PLEN];
- uint8_t tchf48_half = tchf48_nt_e2_map[tch_ind->fn % 26];
+ uint8_t tchf48_half = csd_tchf48_nt_e2_map[tch_ind->fn % 26];
int rc;
gsmtap_csd_rlp_process(lchan, true, tch_ind, data, data_len);
@@ -2558,10 +2698,6 @@
int rc = csd_v110_rtp_decode(lchan, msg->tail, &csd_align_bits,
rtp_pl, rtp_pl_len);
if (rc > 0) {
- /* 'fake' tch_ind containing all-zero so gsmtap code can be shared
- * between UL and DL */
- static const struct ph_tch_param fake_tch_ind = {};
- gsmtap_csd_rlp_process(lchan, false, &fake_tch_ind, msg->tail, rc);
msgb_put(msg, rc);
} else {
rate_ctr_inc2(bts->ctrs, BTS_CTR_RTP_RX_DROP_V110_DEC);
--
To view, visit https://gerrit.osmocom.org/c/osmo-bts/+/38557?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: merged
Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Change-Id: Idaebfce6da13b23ba265a197502712d83991873e
Gerrit-Change-Number: 38557
Gerrit-PatchSet: 4
Gerrit-Owner: falconia <falcon(a)freecalypso.org>
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>
laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-bts/+/38555?usp=email )
(
3 is the latest approved patch-set.
No files were changed between the latest approved patch-set and the submitted one.
)Change subject: CSD RTP: verify alignment of V.110 frames
......................................................................
CSD RTP: verify alignment of V.110 frames
Since the beginning of CSD implementation, OsmoBTS has operated
with an implicit (unstated) policy that V.110 frames must be
perfectly aligned within received clearmode RTP packets - a requirement
which is NOT set anywhere in TS 48.103 or any of the other specs
it references. This design policy is sensible from the standpoint
of implementation complexity (both OsmoBTS and osmo_trau2rtp emit
such perfectly aligned packets; if someone is building a gateway
between an Osmocom GSM network and ISDN-style external networks,
that gateway can act as the aligner), but it should be explicit
rather than implicit.
Check V.110 frame alignment in received clearmode RTP packets,
and reject packets that fail this alignment check.
Change-Id: Icd704dc7fa02e60074efc8a29ad7e42ebdf63783
---
M src/common/csd_v110.c
1 file changed, 20 insertions(+), 0 deletions(-)
Approvals:
pespin: Looks good to me, but someone else must approve
fixeria: Looks good to me, approved
Jenkins Builder: Verified
diff --git a/src/common/csd_v110.c b/src/common/csd_v110.c
index cbbb83b..b2d2b42 100644
--- a/src/common/csd_v110.c
+++ b/src/common/csd_v110.c
@@ -20,6 +20,7 @@
*/
#include <stdint.h>
+#include <stdbool.h>
#include <errno.h>
#include <osmocom/core/bits.h>
@@ -150,6 +151,20 @@
return RFC4040_RTP_PLEN;
}
+static bool check_v110_align(const ubit_t *ra_bits)
+{
+ int i;
+ ubit_t bit0 = 0, bit1 = 1;
+
+ /* The weird code structure is for performance optimization,
+ * to avoid conditionals inside loops. */
+ for (i = 0; i < 8; i++)
+ bit0 |= ra_bits[i];
+ for (i = 1; i < 10; i++)
+ bit1 &= ra_bits[i * 8];
+ return (bit0 == 0) && (bit1 == 1);
+}
+
int csd_v110_rtp_decode(const struct gsm_lchan *lchan, uint8_t *data,
const uint8_t *rtp, size_t rtp_len)
{
@@ -181,6 +196,11 @@
for (unsigned int i = 0; i < desc->num_blocks; i++) {
struct osmo_v110_decoded_frame df;
+ /* We require our RTP input to consist of aligned V.110
+ * frames. If we get misaligned input, let's catch it
+ * explicitly, rather than send garbage downstream. */
+ if (!check_v110_align(&ra_bits[i * 80]))
+ return -EINVAL;
/* convert a V.110 80-bit frame to a V.110 36-/60-bit frame */
osmo_v110_decode_frame(&df, &ra_bits[i * 80], 80);
if (desc->num_bits == 60)
--
To view, visit https://gerrit.osmocom.org/c/osmo-bts/+/38555?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: merged
Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Change-Id: Icd704dc7fa02e60074efc8a29ad7e42ebdf63783
Gerrit-Change-Number: 38555
Gerrit-PatchSet: 4
Gerrit-Owner: falconia <falcon(a)freecalypso.org>
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>
laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-bts/+/38554?usp=email )
(
3 is the latest approved patch-set.
No files were changed between the latest approved patch-set and the submitted one.
)Change subject: csd_v110: set E2 bit correctly for TCH/[FH]4.8 NT
......................................................................
csd_v110: set E2 bit correctly for TCH/[FH]4.8 NT
In all classic NT modes below 14.5 kbit/s, V.110 frame bits E2 and E3
are repurposed to indicate the alignment whereby a single 240-bit RLP
frame is composed of 4 pseudo-V.110 frames in switching transport.
(TS 48.020 section 15.1.) In the case of TCH/F9.6, setting both E2
and E3 is easy because all 4 pseudo-V.110 frames go out in the same
clearmode RTP packet as a result of a single channel decoding
operation. However, in the case of TCH/F4.8 there are two separate
channel decoding operations producing two separate RTP packets
20 ms apart. Furthermore, GSM 05.03 section 3.4.1 specifies which
TDMA frame positions hold which half of the RLP frame - therefore,
the correct emission of bit E2 needs to be based on the TDMA frame
number at which the block was received.
A similar situation occurs with TCH/H4.8 NT: we receive a single
block from the 05.03 decoder every 40 ms, containing a full RLP frame,
but we emit it as two separate RTP packets, each carrying 20 ms worth
of bits. These RTP packets also require correct setting of E2 bit.
Related: OS#6579
Change-Id: I485af5e01ea87c1721a298a486cd344a17884200
---
M include/osmo-bts/csd_v110.h
M src/common/csd_v110.c
M src/common/l1sap.c
M tests/csd/csd_test.c
4 files changed, 30 insertions(+), 10 deletions(-)
Approvals:
Jenkins Builder: Verified
fixeria: Looks good to me, approved
pespin: Looks good to me, but someone else must approve
diff --git a/include/osmo-bts/csd_v110.h b/include/osmo-bts/csd_v110.h
index de868ae..a7c3a1b 100644
--- a/include/osmo-bts/csd_v110.h
+++ b/include/osmo-bts/csd_v110.h
@@ -14,6 +14,7 @@
extern const struct csd_v110_lchan_desc csd_v110_lchan_desc[256];
int csd_v110_rtp_encode(const struct gsm_lchan *lchan, uint8_t *rtp,
- const uint8_t *data, size_t data_len);
+ const uint8_t *data, size_t data_len,
+ uint8_t nt48_half_num);
int csd_v110_rtp_decode(const struct gsm_lchan *lchan, uint8_t *data,
const uint8_t *rtp, size_t rtp_len);
diff --git a/src/common/csd_v110.c b/src/common/csd_v110.c
index 7254d2d..cbbb83b 100644
--- a/src/common/csd_v110.c
+++ b/src/common/csd_v110.c
@@ -78,7 +78,8 @@
};
int csd_v110_rtp_encode(const struct gsm_lchan *lchan, uint8_t *rtp,
- const uint8_t *data, size_t data_len)
+ const uint8_t *data, size_t data_len,
+ uint8_t nt48_half_num)
{
const struct csd_v110_lchan_desc *desc;
ubit_t ra_bits[80 * 4];
@@ -110,9 +111,15 @@
/* E1 .. E3 must set by out-of-band knowledge */
if (lchan->csd_mode == LCHAN_CSD_M_NT) {
/* non-transparent: as per 3GPP TS 48.020, Table 7 */
- df.e_bits[0] = 0; /* E1: as per 15.1.2, shall be set to 0 (for BSS-MSC) */
- df.e_bits[1] = (i >> 1) & 0x01; /* E2: 0 for Q1/Q2, 1 for Q3/Q4 */
- df.e_bits[2] = (i >> 0) & 0x01; /* E3: 0 for Q1/Q3, 1 for Q2/Q4 */
+ /* E1: as per 15.1.2, shall be set to 0 (for BSS-MSC) */
+ df.e_bits[0] = 0;
+ /* E2: 0 for Q1/Q2, 1 for Q3/Q4 */
+ if (desc->num_blocks == 4)
+ df.e_bits[1] = (i >> 1) & 0x01;
+ else
+ df.e_bits[1] = nt48_half_num;
+ /* E3: 0 for Q1/Q3, 1 for Q2/Q4 */
+ df.e_bits[2] = (i >> 0) & 0x01;
} else {
/* transparent: as per 3GPP TS 44.021, Figure 4 */
df.e_bits[0] = e1e2e3_map[lchan->csd_mode][0]; /* E1 */
diff --git a/src/common/l1sap.c b/src/common/l1sap.c
index 749598e..65ebf35 100644
--- a/src/common/l1sap.c
+++ b/src/common/l1sap.c
@@ -2056,15 +2056,27 @@
lchan->rtp_tx_marker = false;
}
+/* In the case of TCH/F4.8 NT, we have to set bit E2 based on the TDMA
+ * frame number at which we received the block in question. See
+ * GSM 05.03 section 3.4.1 and the mapping tables of GSM 05.02. */
+static const uint8_t tchf48_nt_e2_map[26] = {
+ [4] = 1, /* B1 position */
+ [13] = 1, /* B3 position */
+ [21] = 1, /* B5 position */
+};
+
static void handle_tch_ind_csd_fr(struct gsm_lchan *lchan, const struct ph_tch_param *tch_ind,
const uint8_t *data, uint16_t data_len)
{
uint8_t rtp_pl[RFC4040_RTP_PLEN];
+ uint8_t tchf48_half = tchf48_nt_e2_map[tch_ind->fn % 26];
int rc;
gsmtap_csd_rlp_process(lchan, true, tch_ind, data, data_len);
- rc = csd_v110_rtp_encode(lchan, rtp_pl, data, data_len);
+ /* the last argument matters only for TCH/F4.8 NT mode,
+ * ignored in all other cases. */
+ rc = csd_v110_rtp_encode(lchan, rtp_pl, data, data_len, tchf48_half);
if (rc < 0)
return;
@@ -2076,7 +2088,7 @@
uint8_t rtp_pl[RFC4040_RTP_PLEN];
int rc, i;
- rc = csd_v110_rtp_encode(lchan, rtp_pl, NULL, 0);
+ rc = csd_v110_rtp_encode(lchan, rtp_pl, NULL, 0, 0);
if (rc < 0)
return;
@@ -2105,7 +2117,7 @@
for (i = 0; i < 2; i++) {
rc = csd_v110_rtp_encode(lchan, rtp_pl,
data + i * bits_per_20ms,
- bits_per_20ms);
+ bits_per_20ms, i);
if (rc < 0)
return;
send_ul_rtp_packet_hrdata(lchan, rtp_pl, sizeof(rtp_pl));
diff --git a/tests/csd/csd_test.c b/tests/csd/csd_test.c
index b6edec9..15ee84f 100644
--- a/tests/csd/csd_test.c
+++ b/tests/csd/csd_test.c
@@ -124,7 +124,7 @@
data_enc[i] = i & 0x01;
/* encode an RTP frame and print it */
- rc = csd_v110_rtp_encode(&lchan, &rtp[0], &data_enc[0], bit_num);
+ rc = csd_v110_rtp_encode(&lchan, &rtp[0], &data_enc[0], bit_num, 0);
fprintf(stderr, "[i] csd_v110_rtp_encode() returns %d\n", rc);
if (rc != RFC4040_RTP_PLEN)
return;
@@ -148,7 +148,7 @@
fprintf(stderr, "[i] Testing '%s' (IDLE)\n", tc->name);
/* encode an idle RTP frame and print it */
- rc = csd_v110_rtp_encode(&lchan, &rtp[0], &data_enc[0], 0);
+ rc = csd_v110_rtp_encode(&lchan, &rtp[0], &data_enc[0], 0, 0);
fprintf(stderr, "[i] csd_v110_rtp_encode() returns %d\n", rc);
if (rc != RFC4040_RTP_PLEN)
return;
--
To view, visit https://gerrit.osmocom.org/c/osmo-bts/+/38554?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: merged
Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Change-Id: I485af5e01ea87c1721a298a486cd344a17884200
Gerrit-Change-Number: 38554
Gerrit-PatchSet: 4
Gerrit-Owner: falconia <falcon(a)freecalypso.org>
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>