lists.osmocom.org
Sign In Sign Up
Manage this list Sign In Sign Up

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

gerrit-log

Thread Start a new thread
Download
Threads by month
  • ----- 2026 -----
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2025 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2024 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2023 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2022 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
gerrit-log@lists.osmocom.org

March 2023

  • 1 participants
  • 3642 discussions
[S] Change in osmo-ttcn3-hacks[master]: Limit maximum number of open file descriptors to overcome titan bug
by pespin 17 Mar '23

17 Mar '23
pespin has submitted this change. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/31944 ) Change subject: Limit maximum number of open file descriptors to overcome titan bug ...................................................................... Limit maximum number of open file descriptors to overcome titan bug Without this, titan tries to allocate too much memory and triggers OOM under some systems (happening here with 16GB of RAM). Related: https://gitlab.eclipse.org/eclipse/titan/titan.core/-/issues/690 Change-Id: Iafa8cfa769386e63e1d879d8cce6e24b244d9a6f --- M start-testsuite.sh 1 file changed, 17 insertions(+), 0 deletions(-) Approvals: Jenkins Builder: Verified fixeria: Looks good to me, but someone else must approve osmith: Looks good to me, but someone else must approve laforge: Looks good to me, approved diff --git a/start-testsuite.sh b/start-testsuite.sh index a1e753d..4b88501 100755 --- a/start-testsuite.sh +++ b/start-testsuite.sh @@ -45,6 +45,10 @@ #TITAN_LIBRARY_PATH="$TTCN3_DIR/lib" #TTCN3_BIN_DIR="$TTCN3_DIR/bin" +# Limit max num of open file descriptors to workaround titan.core bug: +# https://gitlab.eclipse.org/eclipse/titan/titan.core/-/issues/690 +ulimit -n 100000 + # below is for the debian packages TTCN3_BIN_DIR="${TTCN3_BIN_DIR:-/usr/bin}" TITAN_LIBRARY_PATH="${TITAN_LIBRARY_PATH:-/usr/lib/titan:/usr/ttcn3/lib}" -- To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/31944 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: Iafa8cfa769386e63e1d879d8cce6e24b244d9a6f Gerrit-Change-Number: 31944 Gerrit-PatchSet: 1 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-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: merged
1 0
0 0
[S] Change in osmo-ttcn3-hacks[master]: Limit maximum number of open file descriptors to overcome titan bug
by laforge 17 Mar '23

17 Mar '23
Attention is currently required from: pespin. laforge has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/31944 ) Change subject: Limit maximum number of open file descriptors to overcome titan bug ...................................................................... Patch Set 1: Code-Review+2 -- To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/31944 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: Iafa8cfa769386e63e1d879d8cce6e24b244d9a6f Gerrit-Change-Number: 31944 Gerrit-PatchSet: 1 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: pespin <pespin(a)sysmocom.de> Gerrit-Comment-Date: Fri, 17 Mar 2023 12:17:58 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1 0
0 0
[S] Change in osmo-ttcn3-hacks[master]: Limit maximum number of open file descriptors to overcome titan bug
by osmith 17 Mar '23

17 Mar '23
Attention is currently required from: laforge, pespin. osmith has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/31944 ) Change subject: Limit maximum number of open file descriptors to overcome titan bug ...................................................................... Patch Set 1: Code-Review+1 -- To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/31944 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: Iafa8cfa769386e63e1d879d8cce6e24b244d9a6f Gerrit-Change-Number: 31944 Gerrit-PatchSet: 1 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: laforge <laforge(a)osmocom.org> Gerrit-Attention: pespin <pespin(a)sysmocom.de> Gerrit-Comment-Date: Fri, 17 Mar 2023 12:16:21 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1 0
0 0
[M] Change in osmo-bsc[master]: Fix Lb/A SCCP conn lookup after recent regression in optimization patch
by pespin 17 Mar '23

17 Mar '23
Attention is currently required from: neels, laforge, daniel. pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-bsc/+/31940 ) Change subject: Fix Lb/A SCCP conn lookup after recent regression in optimization patch ...................................................................... Patch Set 2: (1 comment) Patchset: PS2: > I would think it is safer to revert the SCCP optimiziation untill all of this is resolved, rather th […] Let me try to fix this today, otherwise I'll merge a revert. -- To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/31940 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-bsc Gerrit-Branch: master Gerrit-Change-Id: If42d93adee71d646766929a09bc01ae92b734ef3 Gerrit-Change-Number: 31940 Gerrit-PatchSet: 2 Gerrit-Owner: pespin <pespin(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: daniel <dwillmann(a)sysmocom.de> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: neels <nhofmeyr(a)sysmocom.de> Gerrit-Reviewer: osmith <osmith(a)sysmocom.de> Gerrit-Attention: neels <nhofmeyr(a)sysmocom.de> Gerrit-Attention: laforge <laforge(a)osmocom.org> Gerrit-Attention: daniel <dwillmann(a)sysmocom.de> Gerrit-Comment-Date: Fri, 17 Mar 2023 12:15:37 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Comment-In-Reply-To: laforge <laforge(a)osmocom.org> Comment-In-Reply-To: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: comment
1 0
0 0
[XL] Change in osmocom-bb[master]: {trxcon,virt_phy}: shared GPRS L1 (MAC) implementation
by fixeria 17 Mar '23

17 Mar '23
fixeria has submitted this change. ( https://gerrit.osmocom.org/c/osmocom-bb/+/30743 ) Change subject: {trxcon,virt_phy}: shared GPRS L1 (MAC) implementation ...................................................................... {trxcon,virt_phy}: shared GPRS L1 (MAC) implementation Change-Id: I9567d64f9d00262e36147e8d7e541e5e246bda5f Related: OS#5500 --- M include/l1ctl_proto.h A include/l1gprs.h M src/host/trxcon/include/osmocom/bb/Makefile.am A src/host/trxcon/include/osmocom/bb/l1gprs.h M src/host/trxcon/include/osmocom/bb/trxcon/logging.h M src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h M src/host/trxcon/include/osmocom/bb/trxcon/trxcon_fsm.h M src/host/trxcon/src/Makefile.am M src/host/trxcon/src/l1ctl.c A src/host/trxcon/src/l1gprs.c M src/host/trxcon/src/logging.c M src/host/trxcon/src/trxcon_fsm.c M src/host/trxcon/src/trxcon_inst.c M src/host/virt_phy/include/osmocom/bb/Makefile.am A src/host/virt_phy/include/osmocom/bb/l1gprs.h M src/host/virt_phy/include/osmocom/bb/virtphy/l1ctl_sap.h M src/host/virt_phy/include/osmocom/bb/virtphy/logging.h M src/host/virt_phy/include/osmocom/bb/virtphy/virt_l1_model.h M src/host/virt_phy/src/Makefile.am M src/host/virt_phy/src/gsmtapl1_if.c M src/host/virt_phy/src/l1ctl_sap.c A src/host/virt_phy/src/l1gprs.c M src/host/virt_phy/src/logging.c A src/host/virt_phy/src/virt_prim_pdch.c M src/host/virt_phy/src/virtphy.c A src/shared/l1gprs.c 26 files changed, 868 insertions(+), 292 deletions(-) Approvals: laforge: Looks good to me, but someone else must approve fixeria: Looks good to me, approved pespin: Looks good to me, but someone else must approve Jenkins Builder: Verified diff --git a/include/l1ctl_proto.h b/include/l1ctl_proto.h index 7e415e9..9bf40d2 100644 --- a/include/l1ctl_proto.h +++ b/include/l1ctl_proto.h @@ -53,11 +53,10 @@ L1CTL_TRAFFIC_CONF = 0x1d, L1CTL_TRAFFIC_IND = 0x1e, L1CTL_BURST_IND = 0x1f, - /* configure TBF for uplink/downlink */ - L1CTL_TBF_CFG_REQ = 0x20, - L1CTL_TBF_CFG_CONF = 0x21, - L1CTL_DATA_TBF_REQ = 0x22, - L1CTL_DATA_TBF_CONF = 0x23, + L1CTL_GPRS_UL_TBF_CFG_REQ = 0x20, + L1CTL_GPRS_DL_TBF_CFG_REQ = 0x21, + L1CTL_GPRS_UL_BLOCK_REQ = 0x22, + L1CTL_GPRS_DL_BLOCK_IND = 0x23, /* Extended (11-bit) RACH (see 3GPP TS 05.02, section 5.2.7) */ L1CTL_EXT_RACH_REQ = 0x24, }; @@ -75,23 +74,6 @@ NEIGH_MODE_SB, }; -enum l1ctl_coding_scheme { - L1CTL_CS_NONE, - L1CTL_CS1, - L1CTL_CS2, - L1CTL_CS3, - L1CTL_CS4, - L1CTL_MCS1, - L1CTL_MCS2, - L1CTL_MCS3, - L1CTL_MCS4, - L1CTL_MCS5, - L1CTL_MCS6, - L1CTL_MCS7, - L1CTL_MCS8, - L1CTL_MCS9, -}; - /* * NOTE: struct size. We do add manual padding out of the believe * that it will avoid some unaligned access. @@ -188,15 +170,6 @@ uint8_t payload[0]; } __attribute__((packed)); -struct l1ctl_info_ul_tbf { - /* references l1ctl_tbf_cfg_req.tbf_nr */ - uint8_t tbf_nr; - uint8_t coding_scheme; - uint8_t padding[2]; - /* RLC/MAC block, size determines CS */ - uint8_t payload[0]; -} __attribute__((packed)); - /* * msg for FBSB_REQ * the l1_info_ul header is in front @@ -372,15 +345,44 @@ uint8_t data[0]; } __attribute__((packed)); -struct l1ctl_tbf_cfg_req { - /* future support for multiple concurrent TBFs. 0 for now */ - uint8_t tbf_nr; - /* is this about an UL TBF (1) or DL (0) */ - uint8_t is_uplink; +/* payload of L1CTL_GPRS_UL_TBF_CFG_REQ */ +struct l1ctl_gprs_ul_tbf_cfg_req { + uint8_t tbf_ref; + uint8_t slotmask; uint8_t padding[2]; +} __attribute__((packed)); - /* one USF for each TN, or 255 for invalid/unused */ - uint8_t usf[8]; +/* payload of L1CTL_GPRS_DL_TBF_CFG_REQ */ +struct l1ctl_gprs_dl_tbf_cfg_req { + uint8_t tbf_ref; + uint8_t slotmask; + uint8_t dl_tfi; + uint8_t padding[1]; +} __attribute__((packed)); + +/* part of L1CTL_GPRS_{UL,DL}_BLOCK_{REQ,IND} */ +struct l1ctl_gprs_block_hdr { + uint32_t fn; + uint8_t tn; + uint8_t padding[3]; +} __attribute__((packed)); + +/* payload of L1CTL_GPRS_UL_BLOCK_REQ */ +struct l1ctl_gprs_ul_block_req { + struct l1ctl_gprs_block_hdr hdr; + uint8_t data[0]; +} __attribute__((packed)); + +/* payload of L1CTL_GPRS_DL_BLOCK_IND */ +struct l1ctl_gprs_dl_block_ind { + struct l1ctl_gprs_block_hdr hdr; + struct { + uint16_t ber10k; /* Bit Error Rate */ + int16_t ci_cb; /* C/I in centiBels */ + uint8_t rx_lev; /* RxLev 0..63 */ + } meas; + uint8_t usf; + uint8_t data[0]; } __attribute__((packed)); #endif /* __L1CTL_PROTO_H__ */ diff --git a/include/l1gprs.h b/include/l1gprs.h new file mode 100644 index 0000000..dbeaf2c --- /dev/null +++ b/include/l1gprs.h @@ -0,0 +1,80 @@ +#pragma once + +#include <osmocom/core/linuxlist.h> + +#include <stdint.h> + +struct l1gprs_state; +struct msgb; + +struct l1gprs_tbf { + /*! Item in l1gprs_state->tbf_list */ + struct llist_head list; + /*! Uplink or Downlink */ + bool uplink; + /*! TBF reference number (not index) */ + uint8_t tbf_ref; + /*! PDCH timeslots used by this TBF */ + uint8_t slotmask; + /*! (Downlink only) DL TFI (Temporary Flow Indentity): 0..31 */ + uint8_t dl_tfi; +}; + +struct l1gprs_pdch { + /*! Timeslot number */ + uint8_t tn; + /*! Backpointer to l1gprs_state we belong to */ + struct l1gprs_state *gprs; + /*! UL TBF count */ + uint8_t ul_tbf_count; + /*! DL TBF count */ + uint8_t dl_tbf_count; + /*! DL TFI mask */ + uint32_t dl_tfi_mask; +}; + +struct l1gprs_state { + /*! PDCH state for each timeslot */ + struct l1gprs_pdch pdch[8]; + /*! Uplink and Downlink TBFs */ + struct llist_head tbf_list; + /*! Logging context (used as prefix for messages) */ + char *log_prefix; + /*! Some private data for API user */ + void *priv; +}; + +void l1gprs_logging_init(int logc); +struct l1gprs_state *l1gprs_state_alloc(void *ctx, const char *log_prefix, void *priv); +void l1gprs_state_free(struct l1gprs_state *gprs); + +int l1gprs_handle_ul_tbf_cfg_req(struct l1gprs_state *gprs, const struct msgb *msg); +int l1gprs_handle_dl_tbf_cfg_req(struct l1gprs_state *gprs, const struct msgb *msg); + +struct l1gprs_prim_block_hdr { + uint32_t fn; + uint8_t tn; +}; + +struct l1gprs_prim_ul_block_req { + struct l1gprs_prim_block_hdr hdr; + size_t data_len; + const uint8_t *data; +}; + +struct l1gprs_prim_dl_block_ind { + struct l1gprs_prim_block_hdr hdr; + struct { + uint16_t ber10k; + int16_t ci_cb; + uint8_t rx_lev; + } meas; + size_t data_len; + const uint8_t *data; +}; + +int l1gprs_handle_ul_block_req(struct l1gprs_state *gprs, + struct l1gprs_prim_ul_block_req *req, + const struct msgb *msg); +struct msgb *l1gprs_handle_dl_block_ind(struct l1gprs_state *gprs, + const struct l1gprs_prim_dl_block_ind *ind); diff --git a/src/host/trxcon/include/osmocom/bb/Makefile.am b/src/host/trxcon/include/osmocom/bb/Makefile.am index 127a2c7..4a575ff 100644 --- a/src/host/trxcon/include/osmocom/bb/Makefile.am +++ b/src/host/trxcon/include/osmocom/bb/Makefile.am @@ -5,4 +5,5 @@ noinst_HEADERS = \ l1ctl_proto.h \ + l1gprs.h \ $(NULL) diff --git a/src/host/trxcon/include/osmocom/bb/l1gprs.h b/src/host/trxcon/include/osmocom/bb/l1gprs.h new file mode 120000 index 0000000..3bf8517 --- /dev/null +++ b/src/host/trxcon/include/osmocom/bb/l1gprs.h @@ -0,0 +1 @@ +../../../../../../include/l1gprs.h \ No newline at end of file diff --git a/src/host/trxcon/include/osmocom/bb/trxcon/logging.h b/src/host/trxcon/include/osmocom/bb/trxcon/logging.h index f8521a0..ce14992 100644 --- a/src/host/trxcon/include/osmocom/bb/trxcon/logging.h +++ b/src/host/trxcon/include/osmocom/bb/trxcon/logging.h @@ -10,6 +10,7 @@ DTRXD, DSCH, DSCHD, + DGPRS, }; int trxcon_logging_init(void *tall_ctx, const char *category_mask); diff --git a/src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h b/src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h index 15e63f7..1d012de 100644 --- a/src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h +++ b/src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h @@ -4,6 +4,7 @@ struct osmo_fsm_inst; struct l1sched_state; +struct l1gprs_state; struct msgb; struct trxcon_inst { @@ -18,6 +19,9 @@ /* The L1 scheduler */ struct l1sched_state *sched; + /* GPRS state (MAC layer) */ + struct l1gprs_state *gprs; + /* PHY interface (e.g. TRXC/TRXD) */ void *phyif; /* L2 interface (e.g. L1CTL) */ @@ -46,6 +50,7 @@ TRXCON_LOGC_L1D, /* L1CTL data */ TRXCON_LOGC_SCHC, /* l1sched control */ TRXCON_LOGC_SCHD, /* l1sched data */ + TRXCON_LOGC_GPRS, /* l1gprs logging */ }; void trxcon_set_log_cfg(const int *logc, unsigned int logc_num); diff --git a/src/host/trxcon/include/osmocom/bb/trxcon/trxcon_fsm.h b/src/host/trxcon/include/osmocom/bb/trxcon/trxcon_fsm.h index 49b5e3a..bbb4eb5 100644 --- a/src/host/trxcon/include/osmocom/bb/trxcon/trxcon_fsm.h +++ b/src/host/trxcon/include/osmocom/bb/trxcon/trxcon_fsm.h @@ -37,6 +37,9 @@ TRXCON_EV_TX_DATA_CNF, TRXCON_EV_RX_DATA_IND, TRXCON_EV_CRYPTO_REQ, + TRXCON_EV_GPRS_UL_TBF_CFG_REQ, /* param: L1CTL msgb */ + TRXCON_EV_GPRS_DL_TBF_CFG_REQ, /* param: L1CTL msgb */ + TRXCON_EV_GPRS_UL_BLOCK_REQ, /* param: L1CTL msgb */ }; /* param of TRXCON_EV_FULL_POWER_SCAN_REQ */ diff --git a/src/host/trxcon/src/Makefile.am b/src/host/trxcon/src/Makefile.am index a286f2a..c96949a 100644 --- a/src/host/trxcon/src/Makefile.am +++ b/src/host/trxcon/src/Makefile.am @@ -29,6 +29,13 @@ $(NULL) +noinst_LTLIBRARIES += libl1gprs.la + +libl1gprs_la_SOURCES = \ + l1gprs.c \ + $(NULL) + + noinst_LTLIBRARIES += libtrxcon.la libtrxcon_la_SOURCES = \ @@ -51,6 +58,7 @@ trxcon_LDADD = \ libtrxcon.la \ libl1sched.la \ + libl1gprs.la \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOCODING_LIBS) \ $(LIBOSMOGSM_LIBS) \ diff --git a/src/host/trxcon/src/l1ctl.c b/src/host/trxcon/src/l1ctl.c index ec98f82..a45bc2c 100644 --- a/src/host/trxcon/src/l1ctl.c +++ b/src/host/trxcon/src/l1ctl.c @@ -785,6 +785,7 @@ int trxcon_l1ctl_receive(struct trxcon_inst *trxcon, struct msgb *msg) { const struct l1ctl_hdr *l1h; + int rc; l1h = (const struct l1ctl_hdr *)msg->l1h; msg->l1h = (uint8_t *)l1h->data; @@ -818,11 +819,20 @@ return l1ctl_rx_tch_mode_req(trxcon, msg); case L1CTL_CRYPTO_REQ: return l1ctl_rx_crypto_req(trxcon, msg); - + case L1CTL_GPRS_UL_TBF_CFG_REQ: + rc = osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_GPRS_UL_TBF_CFG_REQ, msg); + msgb_free(msg); + return rc; + case L1CTL_GPRS_DL_TBF_CFG_REQ: + rc = osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_GPRS_DL_TBF_CFG_REQ, msg); + msgb_free(msg); + return rc; + case L1CTL_GPRS_UL_BLOCK_REQ: + rc = osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_GPRS_UL_BLOCK_REQ, msg); + msgb_free(msg); + return rc; /* Not (yet) handled messages */ case L1CTL_NEIGH_PM_REQ: - case L1CTL_DATA_TBF_REQ: - case L1CTL_TBF_CFG_REQ: case L1CTL_DM_FREQ_REQ: case L1CTL_SIM_REQ: LOGPFSMSL(trxcon->fi, g_logc_l1c, LOGL_NOTICE, diff --git a/src/host/trxcon/src/l1gprs.c b/src/host/trxcon/src/l1gprs.c new file mode 120000 index 0000000..0185f68 --- /dev/null +++ b/src/host/trxcon/src/l1gprs.c @@ -0,0 +1 @@ +../../../shared/l1gprs.c \ No newline at end of file diff --git a/src/host/trxcon/src/logging.c b/src/host/trxcon/src/logging.c index 2222577..e94ad2d 100644 --- a/src/host/trxcon/src/logging.c +++ b/src/host/trxcon/src/logging.c @@ -67,6 +67,12 @@ .color = "\033[1;36m", .enabled = 1, .loglevel = LOGL_NOTICE, }, + [DGPRS] = { + .name = "DGPRS", + .description = "L1 GPRS (MAC layer)", + .color = "\033[1;36m", + .enabled = 1, .loglevel = LOGL_DEBUG, + }, }; static const struct log_info trxcon_log_info = { @@ -80,6 +86,7 @@ [TRXCON_LOGC_L1D] = DL1D, [TRXCON_LOGC_SCHC] = DSCH, [TRXCON_LOGC_SCHD] = DSCHD, + [TRXCON_LOGC_GPRS] = DGPRS, }; int trxcon_logging_init(void *tall_ctx, const char *category_mask) diff --git a/src/host/trxcon/src/trxcon_fsm.c b/src/host/trxcon/src/trxcon_fsm.c index 186c04b..053ca2f 100644 --- a/src/host/trxcon/src/trxcon_fsm.c +++ b/src/host/trxcon/src/trxcon_fsm.c @@ -2,7 +2,7 @@ * OsmocomBB <-> SDR connection bridge * The trxcon state machine (see 3GPP TS 44.004, section 5.1) * - * (C) 2022 by sysmocom - s.f.m.c. GmbH <info(a)sysmocom.de> + * (C) 2022-2023 by sysmocom - s.f.m.c. GmbH <info(a)sysmocom.de> * Author: Vadim Yanitskiy <vyanitskiy(a)sysmocom.de> * * All Rights Reserved @@ -29,12 +29,14 @@ #include <osmocom/core/talloc.h> #include <osmocom/core/logging.h> #include <osmocom/gsm/gsm0502.h> +#include <osmocom/gsm/protocol/gsm_08_58.h> #include <osmocom/bb/trxcon/trxcon.h> #include <osmocom/bb/trxcon/trxcon_fsm.h> #include <osmocom/bb/trxcon/phyif.h> #include <osmocom/bb/trxcon/l1ctl.h> #include <osmocom/bb/l1sched/l1sched.h> +#include <osmocom/bb/l1gprs.h> #define S(x) (1 << (x)) @@ -505,6 +507,25 @@ } } +static void trxcon_st_packet_data_onenter(struct osmo_fsm_inst *fi, + uint32_t prev_state) +{ + struct trxcon_inst *trxcon = fi->priv; + + OSMO_ASSERT(trxcon->gprs == NULL); + trxcon->gprs = l1gprs_state_alloc(trxcon, trxcon->log_prefix, trxcon); + OSMO_ASSERT(trxcon->gprs != NULL); +} + +static void trxcon_st_packet_data_onleave(struct osmo_fsm_inst *fi, + uint32_t next_state) +{ + struct trxcon_inst *trxcon = fi->priv; + + l1gprs_state_free(trxcon->gprs); + trxcon->gprs = NULL; +} + static void trxcon_st_packet_data_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) { @@ -517,14 +538,58 @@ case TRXCON_EV_TX_ACCESS_BURST_CNF: l1ctl_tx_rach_conf(trxcon, (const struct trxcon_param_tx_access_burst_cnf *)data); break; + case TRXCON_EV_GPRS_UL_TBF_CFG_REQ: + l1gprs_handle_ul_tbf_cfg_req(trxcon->gprs, (struct msgb *)data); + break; + case TRXCON_EV_GPRS_DL_TBF_CFG_REQ: + l1gprs_handle_dl_tbf_cfg_req(trxcon->gprs, (struct msgb *)data); + break; + case TRXCON_EV_GPRS_UL_BLOCK_REQ: + { + struct l1gprs_prim_ul_block_req block_req; + const struct msgb *msg = data; + struct l1sched_ts_prim *prim; + + if (l1gprs_handle_ul_block_req(trxcon->gprs, &block_req, msg) != 0) + return; + + prim = l1sched_prim_push(trxcon->sched, L1SCHED_PRIM_DATA, + RSL_CHAN_OSMO_PDCH | block_req.hdr.tn, 0x00, + block_req.data, block_req.data_len); + if (prim == NULL) { + LOGPFSML(fi, LOGL_ERROR, "Failed to enqueue a prim\n"); + return; + } + break; + } case TRXCON_EV_RX_DATA_IND: { const struct trxcon_param_rx_data_ind *ind = data; + struct l1gprs_prim_dl_block_ind block_ind; + struct msgb *msg; - if (ind->link_id == 0x00) - LOGPFSML(fi, LOGL_NOTICE, "Rx PDTCH/D message\n"); + block_ind = (struct l1gprs_prim_dl_block_ind) { + .hdr = { + .fn = ind->frame_nr, + .tn = ind->chan_nr & 0x07, + }, + .meas = { + /* .ber10k is set below */ + .ci_cb = 180, /* 18 dB */ + .rx_lev = dbm2rxlev(ind->rssi), + }, + .data_len = ind->data_len, + .data = ind->data, + }; + + if (ind->n_bits_total == 0) + block_ind.meas.ber10k = 10000; else - LOGPFSML(fi, LOGL_NOTICE, "Rx PTCCH/D message\n"); + block_ind.meas.ber10k = 10000 * ind->n_errors / ind->n_bits_total; + + msg = l1gprs_handle_dl_block_ind(trxcon->gprs, &block_ind); + if (msg != NULL) + trxcon_l1ctl_send(trxcon, msg); break; } case TRXCON_EV_DCH_EST_REQ: @@ -550,6 +615,9 @@ /* Shutdown the scheduler */ if (trxcon->sched != NULL) l1sched_free(trxcon->sched); + /* Clean up GPRS L1 state */ + l1gprs_state_free(trxcon->gprs); + /* Close active connections */ if (trxcon->l2if != NULL) trxcon_l1ctl_close(trxcon); @@ -625,7 +693,12 @@ | S(TRXCON_EV_DCH_EST_REQ) | S(TRXCON_EV_TX_ACCESS_BURST_REQ) | S(TRXCON_EV_TX_ACCESS_BURST_CNF) + | S(TRXCON_EV_GPRS_UL_TBF_CFG_REQ) + | S(TRXCON_EV_GPRS_DL_TBF_CFG_REQ) + | S(TRXCON_EV_GPRS_UL_BLOCK_REQ) | S(TRXCON_EV_RX_DATA_IND), + .onenter = &trxcon_st_packet_data_onenter, + .onleave = &trxcon_st_packet_data_onleave, .action = &trxcon_st_packet_data_action, }, }; @@ -651,6 +724,9 @@ OSMO_VALUE_STRING(TRXCON_EV_TX_DATA_CNF), OSMO_VALUE_STRING(TRXCON_EV_RX_DATA_IND), OSMO_VALUE_STRING(TRXCON_EV_CRYPTO_REQ), + OSMO_VALUE_STRING(TRXCON_EV_GPRS_UL_TBF_CFG_REQ), + OSMO_VALUE_STRING(TRXCON_EV_GPRS_DL_TBF_CFG_REQ), + OSMO_VALUE_STRING(TRXCON_EV_GPRS_UL_BLOCK_REQ), { 0, NULL } }; diff --git a/src/host/trxcon/src/trxcon_inst.c b/src/host/trxcon/src/trxcon_inst.c index da4d618..65e63b3 100644 --- a/src/host/trxcon/src/trxcon_inst.c +++ b/src/host/trxcon/src/trxcon_inst.c @@ -27,6 +27,7 @@ #include <osmocom/bb/trxcon/trxcon_fsm.h> #include <osmocom/bb/l1sched/l1sched.h> #include <osmocom/bb/l1sched/logging.h> +#include <osmocom/bb/l1gprs.h> extern int g_logc_l1c; extern int g_logc_l1d; @@ -53,6 +54,9 @@ case TRXCON_LOGC_SCHD: schd = logc[i]; break; + case TRXCON_LOGC_GPRS: + l1gprs_logging_init(logc[i]); + break; } } diff --git a/src/host/virt_phy/include/osmocom/bb/Makefile.am b/src/host/virt_phy/include/osmocom/bb/Makefile.am index c52fb93..9a4b939 100644 --- a/src/host/virt_phy/include/osmocom/bb/Makefile.am +++ b/src/host/virt_phy/include/osmocom/bb/Makefile.am @@ -4,4 +4,5 @@ noinst_HEADERS = \ l1ctl_proto.h \ + l1gprs.h \ $(NULL) diff --git a/src/host/virt_phy/include/osmocom/bb/l1gprs.h b/src/host/virt_phy/include/osmocom/bb/l1gprs.h new file mode 120000 index 0000000..3bf8517 --- /dev/null +++ b/src/host/virt_phy/include/osmocom/bb/l1gprs.h @@ -0,0 +1 @@ +../../../../../../include/l1gprs.h \ No newline at end of file diff --git a/src/host/virt_phy/include/osmocom/bb/virtphy/l1ctl_sap.h b/src/host/virt_phy/include/osmocom/bb/virtphy/l1ctl_sap.h index 724d238..e756c14 100644 --- a/src/host/virt_phy/include/osmocom/bb/virtphy/l1ctl_sap.h +++ b/src/host/virt_phy/include/osmocom/bb/virtphy/l1ctl_sap.h @@ -57,6 +57,8 @@ void l1ctl_rx_neigh_pm_req(struct l1_model_ms *ms, struct msgb *msg); void l1ctl_rx_traffic_req(struct l1_model_ms *ms, struct msgb *msg); void l1ctl_rx_sim_req(struct l1_model_ms *ms, struct msgb *msg); +void l1ctl_rx_gprs_uldl_tbf_cfg_req(struct l1_model_ms *ms, struct msgb *msg); +void l1ctl_rx_gprs_ul_block_req(struct l1_model_ms *ms, struct msgb *msg); /* transmit routines */ void l1ctl_tx_reset(struct l1_model_ms *ms, uint8_t msg_type, uint8_t reset_type); @@ -75,6 +77,8 @@ void l1ctl_tx_fbsb_conf(struct l1_model_ms *ms, uint8_t res, uint16_t arfcn); void l1ctl_tx_ccch_mode_conf(struct l1_model_ms *ms, uint8_t ccch_mode); void l1ctl_tx_tch_mode_conf(struct l1_model_ms *ms, uint8_t tch_mode, uint8_t audio_mode); +void l1ctl_tx_gprs_dl_block_ind(struct l1_model_ms *ms, const struct msgb *msg, + uint32_t fn, uint8_t tn, uint8_t rxlev); /* scheduler functions */ uint32_t sched_fn_ul(struct gsm_time cur_time, uint8_t chan_nr, diff --git a/src/host/virt_phy/include/osmocom/bb/virtphy/logging.h b/src/host/virt_phy/include/osmocom/bb/virtphy/logging.h index b22db99..48f7ed5 100644 --- a/src/host/virt_phy/include/osmocom/bb/virtphy/logging.h +++ b/src/host/virt_phy/include/osmocom/bb/virtphy/logging.h @@ -7,6 +7,7 @@ DL1C, DL1P, DVIRPHY, + DGPRS, DMAIN }; diff --git a/src/host/virt_phy/include/osmocom/bb/virtphy/virt_l1_model.h b/src/host/virt_phy/include/osmocom/bb/virtphy/virt_l1_model.h index b729c44..94581f6 100644 --- a/src/host/virt_phy/include/osmocom/bb/virtphy/virt_l1_model.h +++ b/src/host/virt_phy/include/osmocom/bb/virtphy/virt_l1_model.h @@ -16,7 +16,6 @@ MS_STATE_IDLE_SYNCING, MS_STATE_IDLE_CAMPING, MS_STATE_DEDICATED, - MS_STATE_TBF }; @@ -77,15 +76,6 @@ uint8_t tsc; // training sequence code (unused in virtual um) uint8_t h; // hopping enabled flag (unused in virtual um) } dedicated; - struct { - struct { - uint8_t usf[8]; - struct llist_head tx_queue; - } ul; - struct { - uint8_t tfi[8]; - } dl; - } tbf; /* fbsb state */ struct { @@ -116,6 +106,8 @@ struct l1ctl_sock_client *lsc; /* pointer to the (shared) GSMTAP/VirtUM socket to talk to BTS(s) */ struct virt_um_inst *vui; + /* GPRS state (MAC layer) */ + struct l1gprs_state *gprs; /* actual per-MS state */ struct l1_state_ms state; }; diff --git a/src/host/virt_phy/src/Makefile.am b/src/host/virt_phy/src/Makefile.am index 902284d..f10639f 100644 --- a/src/host/virt_phy/src/Makefile.am +++ b/src/host/virt_phy/src/Makefile.am @@ -5,6 +5,7 @@ virtphy_SOURCES = \ virtphy.c \ + l1gprs.c \ logging.c \ gsmtapl1_if.c \ l1ctl_sock.c \ @@ -13,6 +14,7 @@ virt_prim_fbsb.c \ virt_prim_rach.c \ virt_prim_data.c \ + virt_prim_pdch.c \ virt_prim_traffic.c \ virt_l1_sched_simple.c \ virt_l1_model.c \ diff --git a/src/host/virt_phy/src/gsmtapl1_if.c b/src/host/virt_phy/src/gsmtapl1_if.c index f5c49af..ef8d684 100644 --- a/src/host/virt_phy/src/gsmtapl1_if.c +++ b/src/host/virt_phy/src/gsmtapl1_if.c @@ -94,23 +94,16 @@ uint8_t timeslot; /* tdma timeslot to send in (0-7) */ uint8_t gsmtap_chan; /* the gsmtap channel */ - switch (ms->state.state) { - case MS_STATE_DEDICATED: - case MS_STATE_TBF: + if (ms->state.state == MS_STATE_DEDICATED) arfcn = ms->state.dedicated.band_arfcn; - break; - default: + else arfcn = ms->state.serving_cell.arfcn; - break; - } switch (l1h->msg_type) { - case L1CTL_DATA_TBF_REQ: - ul = NULL; - rsl_chantype = RSL_CHAN_OSMO_PDCH; + case L1CTL_GPRS_UL_BLOCK_REQ: + gsmtap_chan = GSMTAP_CHANNEL_PDCH; timeslot = tn; subslot = 0; - gsmtap_chan = chantype_rsl2gsmtap2(rsl_chantype, 0, false); break; case L1CTL_TRAFFIC_REQ: ul = (struct l1ctl_info_ul *)l1h->data; @@ -165,77 +158,6 @@ */ extern uint16_t prim_pm_set_sig_strength(struct l1_model_ms *ms, uint16_t arfcn, int16_t sig_lev); -/* determine if a received Downlink RLC/MAC block matches the current MS configuration */ -static bool gprs_dl_block_matches_ms(struct l1_model_ms *ms, struct msgb *msg, uint8_t timeslot) -{ - uint8_t payload_type; - uint8_t tfi; - - if (msgb_length(msg) < 1) - return false; - - /* FIXME: Ensure this will also work for EGPRS! */ - payload_type = msg->data[0] >> 6; - switch (payload_type) { - case 0: /* RLC Data Block */ - /* forward all RLD Data Blocks destined for TFI of MS */ - tfi = (msg->data[1] >> 1) & 0x1f; - if (ms->state.state == MS_STATE_TBF && ms->state.tbf.dl.tfi[timeslot] == tfi) - return true; - break; - case 1: /* RLC/MAC Control without optional octets */ - /* forward all RLC/MAC control blocks without optional octets, i.e. not addressed - * to a specific TFI */ - return true; - case 2: /* RLC/MAC with optional control octets */ - /* forward all RLD Control Blocks destined for TFI of MS */ - tfi = (msg->data[2] >> 1) & 0x1f; - if (ms->state.state == MS_STATE_TBF && ms->state.tbf.dl.tfi[timeslot] == tfi) - return true; - break; - default: - break; - } - return false; -} - -/* determine if given USF at given timeslot is relevant to given MS or not */ -static bool usf_matches_ms(struct l1_model_ms *ms, uint8_t usf, uint8_t timeslot) -{ - if (ms->state.state == MS_STATE_TBF && ms->state.tbf.ul.usf[timeslot] == usf) - return true; - - return false; -} - -/* extract USF from (E)GPRS RLC/MAC block */ -static uint8_t get_usf_from_block(struct msgb *msg) -{ - /* FIXME: Ensure this will also work for EGPRS! */ - return msg->data[0] & 0x7; -} - -/* MS is authorized to transmit a block in uplink for given USF on timeslot+arfcn at FN */ -static void ms_ul_tbf_may_transmit(struct l1_model_ms *ms, uint16_t arfcn, uint8_t timeslot, - uint32_t fn, uint8_t usf) -{ - struct msgb *msg; - - /* If USF is not for us, bail out */ - if (!usf_matches_ms(ms, usf, timeslot)) - return; - - /* attempt to de-queue pending msgb for this UL TBF and transmit it */ - msg = msgb_dequeue(&ms->state.tbf.ul.tx_queue); - if (!msg) { - printf("FN=%u, TN=%u, USF=%u: empty tx_queue, not transmitting\n", fn, timeslot, usf); - /* FIXME: send some dummy control frame? */ - } else { - printf("FN=%u, TN=%u, USF=%u: transmitting queued msg\n", fn, timeslot, usf); - gsmtapl1_tx_to_virt_um_inst(ms, fn, timeslot, msg); - } -} - static void l1ctl_from_virt_um(struct l1ctl_sock_client *lsc, struct msgb *msg, uint32_t fn, uint16_t arfcn, uint8_t timeslot, uint8_t subslot, uint8_t gsmtap_chantype, uint8_t chan_nr, uint8_t link_id, @@ -243,7 +165,6 @@ { struct l1_model_ms *ms = lsc->priv; uint8_t rxlev = dbm2rxlev(prim_pm_set_sig_strength(ms, arfcn & GSMTAP_ARFCN_MASK, MAX_SIG_LEV_DBM)); - uint8_t usf; gsm_fn2gsmtime(&ms->state.downlink_time, fn); @@ -310,16 +231,13 @@ case GSMTAP_CHANNEL_RACH: LOGPMS(DVIRPHY, LOGL_NOTICE, ms, "Ignoring unexpected RACH in downlink ?!?\n"); break; + case GSMTAP_CHANNEL_PTCCH: case GSMTAP_CHANNEL_PACCH: case GSMTAP_CHANNEL_PDCH: - if (gprs_dl_block_matches_ms(ms, msg, timeslot)) - l1ctl_tx_data_ind(ms, msg, arfcn, link_id, chan_nr, fn, snr_db, rxlev, 0, 0); - usf = get_usf_from_block(msg); - ms_ul_tbf_may_transmit(ms, arfcn, timeslot, fn, usf); + l1ctl_tx_gprs_dl_block_ind(ms, msg, fn, timeslot, rxlev); break; case GSMTAP_CHANNEL_SDCCH: case GSMTAP_CHANNEL_CCCH: - case GSMTAP_CHANNEL_PTCCH: LOGPMS(DVIRPHY, LOGL_NOTICE, ms, "Ignoring unsupported channel type %s\n", get_value_string(gsmtap_gsm_channel_names, gsmtap_chantype)); break; diff --git a/src/host/virt_phy/src/l1ctl_sap.c b/src/host/virt_phy/src/l1ctl_sap.c index ab917c6..7e4540d 100644 --- a/src/host/virt_phy/src/l1ctl_sap.c +++ b/src/host/virt_phy/src/l1ctl_sap.c @@ -30,7 +30,6 @@ #include <osmocom/gsm/protocol/gsm_08_58.h> #include <osmocom/gsm/protocol/gsm_04_08.h> #include <osmocom/gsm/rsl.h> -#include <osmocom/gprs/gprs_rlc.h> #include <osmocom/bb/virtphy/virtual_um.h> #include <osmocom/bb/virtphy/l1ctl_sock.h> @@ -40,9 +39,7 @@ #include <osmocom/bb/virtphy/logging.h> #include <osmocom/bb/virtphy/virt_l1_sched.h> #include <osmocom/bb/l1ctl_proto.h> - -static void l1ctl_rx_tbf_cfg_req(struct l1_model_ms *ms, struct msgb *msg); -static void l1ctl_rx_data_tbf_req(struct l1_model_ms *ms, struct msgb *msg); +#include <osmocom/bb/l1gprs.h> static void l1_model_tch_mode_set(struct l1_model_ms *ms, uint8_t tch_mode) { @@ -60,7 +57,6 @@ void l1ctl_sap_init(struct l1_model_ms *model) { INIT_LLIST_HEAD(&model->state.sched.mframe_items); - INIT_LLIST_HEAD(&model->state.tbf.ul.tx_queue); prim_pm_init(model); } @@ -163,8 +159,8 @@ switch (msg_type) { case L1CTL_DATA_REQ: case L1CTL_DATA_CONF: - case L1CTL_DATA_TBF_REQ: - case L1CTL_DATA_TBF_CONF: + case L1CTL_GPRS_UL_BLOCK_REQ: + case L1CTL_GPRS_DL_BLOCK_IND: case L1CTL_TRAFFIC_REQ: case L1CTL_TRAFFIC_CONF: case L1CTL_TRAFFIC_IND: @@ -247,11 +243,12 @@ case L1CTL_SIM_REQ: l1ctl_rx_sim_req(ms, msg); break; - case L1CTL_TBF_CFG_REQ: - l1ctl_rx_tbf_cfg_req(ms, msg); + case L1CTL_GPRS_UL_TBF_CFG_REQ: + case L1CTL_GPRS_DL_TBF_CFG_REQ: + l1ctl_rx_gprs_uldl_tbf_cfg_req(ms, msg); break; - case L1CTL_DATA_TBF_REQ: - l1ctl_rx_data_tbf_req(ms, msg); + case L1CTL_GPRS_UL_BLOCK_REQ: + l1ctl_rx_gprs_ul_block_req(ms, msg); goto exit_nofree; } @@ -297,6 +294,12 @@ ms->state.dedicated.subslot = subslot; ms->state.state = MS_STATE_DEDICATED; + if (rsl_chantype == RSL_CHAN_OSMO_PDCH) { + OSMO_ASSERT(ms->gprs == NULL); + ms->gprs = l1gprs_state_alloc(ms, NULL, ms); + OSMO_ASSERT(ms->gprs != NULL); + } + /* TCH config */ if (rsl_chantype == RSL_CHAN_Bm_ACCHs || rsl_chantype == RSL_CHAN_Lm_ACCHs) { ms->state.tch_mode = est_req->tch_mode; @@ -381,6 +384,9 @@ ms->state.tch_mode = GSM48_CMODE_SIGN; ms->state.state = MS_STATE_IDLE_CAMPING; + l1gprs_state_free(ms->gprs); + ms->gprs = NULL; + /* TODO: disable ciphering */ /* TODO: disable audio recording / playing */ } @@ -429,6 +435,8 @@ DEBUGPMS(DL1C, ms, "Rx L1CTL_RESET_REQ (type=FULL)\n"); ms->state.state = MS_STATE_IDLE_SEARCHING; virt_l1_sched_stop(ms); + l1gprs_state_free(ms->gprs); + ms->gprs = NULL; l1ctl_tx_reset(ms, L1CTL_RESET_CONF, reset_req->type); break; case L1CTL_RES_T_SCHED: @@ -547,145 +555,12 @@ } -static void l1ctl_tx_tbf_cfg_conf(struct l1_model_ms *ms, const struct l1ctl_tbf_cfg_req *in); - -static void l1ctl_rx_tbf_cfg_req(struct l1_model_ms *ms, struct msgb *msg) -{ - struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data; - struct l1ctl_tbf_cfg_req *cfg_req = (struct l1ctl_tbf_cfg_req *) l1h->data; - unsigned int i; - - LOGPMS(DL1C, LOGL_INFO, ms, "Rx L1CTL_TBF_CFG_REQ (tbf_id=%u, dir=%s, " - "usf=[%d,%d,%d,%d,%d,%d,%d,%d]\n", cfg_req->tbf_nr, - cfg_req->is_uplink ? "UL" : "DL", cfg_req->usf[0], cfg_req->usf[1], - cfg_req->usf[2], cfg_req->usf[3], cfg_req->usf[4], cfg_req->usf[5], - cfg_req->usf[6], cfg_req->usf[7]); - - if (cfg_req->tbf_nr != 0) { - LOGPMS(DL1C, LOGL_ERROR, ms, "TBF_NR != 0 not supported yet!\n"); - return; - } - - if (ms->state.state == MS_STATE_DEDICATED) - LOGPMS(DL1C, LOGL_NOTICE, ms, "Hard termination of DEDICATED mode, fix L23!\n"); - - if (cfg_req->is_uplink) { - for (i = 0; i < 8; i++) - ms->state.tbf.ul.usf[i] = cfg_req->usf[i]; - } else { - for (i = 0; i < 8; i++) - ms->state.tbf.dl.tfi[i] = cfg_req->usf[i]; - } - ms->state.state = MS_STATE_TBF; - - l1ctl_tx_tbf_cfg_conf(ms, cfg_req); -} - -#if 0 -static const enum osmo_gprs_cs osmo_cs_by_l1ctl[] = { - [L1CTL_CS_NONE] = OSMO_GPRS_CS_NONE, - [L1CTL_CS1] = OSMO_GPRS_CS1, - [L1CTL_CS2] = OSMO_GPRS_CS2, - [L1CTL_CS3] = OSMO_GPRS_CS3, - [L1CTL_CS4] = OSMO_GPRS_CS4, - [L1CTL_MCS1] = OSMO_GPRS_MCS1, - [L1CTL_MCS2] = OSMO_GPRS_MCS2, - [L1CTL_MCS3] = OSMO_GPRS_MCS3, - [L1CTL_MCS4] = OSMO_GPRS_MCS4, - [L1CTL_MCS5] = OSMO_GPRS_MCS5, - [L1CTL_MCS6] = OSMO_GPRS_MCS6, - [L1CTL_MCS7] = OSMO_GPRS_MCS7, - [L1CTL_MCS8] = OSMO_GPRS_MCS8, - [L1CTL_MCS9] = OSMO_GPRS_MCS9, -}; - -static int get_osmo_cs_by_l1ctl(enum l1ctl_coding_scheme l1) -{ - if (l1 >= ARRAY_SIZE(osmo_cs_by_l1ctl)) - return -1; - return osmo_cs_by_l1ctl[l1]; -} -#endif - -static const enum l1ctl_coding_scheme l1ctl_cs_by_osmo[] = { - [OSMO_GPRS_CS_NONE] = L1CTL_CS_NONE, - [OSMO_GPRS_CS1] = L1CTL_CS1, - [OSMO_GPRS_CS2] = L1CTL_CS2, - [OSMO_GPRS_CS3] = L1CTL_CS3, - [OSMO_GPRS_CS4] = L1CTL_CS4, - [OSMO_GPRS_MCS1] = L1CTL_MCS1, - [OSMO_GPRS_MCS2] = L1CTL_MCS2, - [OSMO_GPRS_MCS3] = L1CTL_MCS3, - [OSMO_GPRS_MCS4] = L1CTL_MCS4, - [OSMO_GPRS_MCS5] = L1CTL_MCS5, - [OSMO_GPRS_MCS6] = L1CTL_MCS6, - [OSMO_GPRS_MCS7] = L1CTL_MCS7, - [OSMO_GPRS_MCS8] = L1CTL_MCS8, - [OSMO_GPRS_MCS9] = L1CTL_MCS9, -}; - -static int get_l1ctl_cs_by_osmo(enum osmo_gprs_cs in) -{ - if (in >= ARRAY_SIZE(l1ctl_cs_by_osmo)) - return -1; - return l1ctl_cs_by_osmo[in]; -} - -static void l1ctl_rx_data_tbf_req(struct l1_model_ms *ms, struct msgb *msg) -{ - struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data; - struct l1ctl_info_ul_tbf *udt = (struct l1ctl_info_ul_tbf *) l1h->data; - enum osmo_gprs_cs osmo_cs; - int block_size; - - msg->l2h = udt->payload; - - LOGPMS(DL1P, LOGL_ERROR, ms, "Rx L1CTL_DATA_TBF_REQ (tbf_id=%d, data=%s)\n", - udt->tbf_nr, osmo_hexdump(msg->l2h, msgb_l2len(msg))); - if (udt->tbf_nr != 0) { - LOGPMS(DL1C, LOGL_ERROR, ms, "TBF_NR != 0 not supported yet!\n"); - return; - } - - if (ms->state.state != MS_STATE_TBF) { - LOGPMS(DL1P, LOGL_ERROR, ms, "DATA_TBF_REQ in state != TBF\n"); - return; - } - - osmo_cs = get_l1ctl_cs_by_osmo(udt->coding_scheme); - if (osmo_cs < 0) { - LOGPMS(DL1P, LOGL_ERROR, ms, "DATA_RBF_REQ with invalid CS\n"); - return; - } - block_size = osmo_gprs_ul_block_size_bytes(osmo_cs); - - if (msgb_l2len(msg) < block_size) { - int pad_len = block_size - msgb_l2len(msg); - uint8_t *pad = msgb_put(msg, pad_len); - memset(pad, GSM_MACBLOCK_PADDING, pad_len); - } - - msgb_enqueue(&ms->state.tbf.ul.tx_queue, msg); -} - /*************************************************************** * L1CTL TX ROUTINES ******************************************* * For more routines check the respective handler classes ****** * like virt_prim_rach.c *************************************** ***************************************************************/ -static void l1ctl_tx_tbf_cfg_conf(struct l1_model_ms *ms, const struct l1ctl_tbf_cfg_req *in) -{ - struct msgb *msg = l1ctl_msgb_alloc(L1CTL_TBF_CFG_CONF); - struct l1ctl_tbf_cfg_req *out; - - /* copy over the data from the request */ - out = (struct l1ctl_tbf_cfg_req *) msgb_put(msg, sizeof(*out)); - *out = *in; - - l1ctl_sap_tx_to_l23_inst(ms, msg); -} - /** * @brief Transmit L1CTL_RESET_IND or L1CTL_RESET_CONF to layer 23. * diff --git a/src/host/virt_phy/src/l1gprs.c b/src/host/virt_phy/src/l1gprs.c new file mode 120000 index 0000000..0185f68 --- /dev/null +++ b/src/host/virt_phy/src/l1gprs.c @@ -0,0 +1 @@ +../../../shared/l1gprs.c \ No newline at end of file diff --git a/src/host/virt_phy/src/logging.c b/src/host/virt_phy/src/logging.c index 04667d1..0a1b2a4 100644 --- a/src/host/virt_phy/src/logging.c +++ b/src/host/virt_phy/src/logging.c @@ -54,10 +54,10 @@ "L1CTL_TRAFFIC_CONF", "L1CTL_TRAFFIC_IND", "L1CTL_BURST_IND", - "L1CTL_TBF_CFG_REQ", - "L1CTL_TBF_CFG_CONF", - "L1CTL_DATA_TBF_REQ", - "L1CTL_DATA_TBF_CONF" + "L1CTL_GPRS_UL_TBF_CFG_REQ", + "L1CTL_GPRS_DL_TBF_CFG_REQ", + "L1CTL_GPRS_UL_BLOCK_REQ", + "L1CTL_GPRS_DL_BLOCK_IND", }; static const struct log_info_cat default_categories[] = { @@ -82,6 +82,13 @@ .enabled = 1, .loglevel = LOGL_NOTICE, }, + [DGPRS] = { + .name = "DGPRS", + .description = "L1 GPRS (MAC leyer)", + .color = "\033[1;31m", + .enabled = 1, + .loglevel = LOGL_NOTICE, + }, [DMAIN] = { .name = "DMAIN", .description = "Main Program / Data Structures", diff --git a/src/host/virt_phy/src/virt_prim_pdch.c b/src/host/virt_phy/src/virt_prim_pdch.c new file mode 100644 index 0000000..7125a70 --- /dev/null +++ b/src/host/virt_phy/src/virt_prim_pdch.c @@ -0,0 +1,106 @@ +/* + * (C) 2023 by sysmocom - s.f.m.c. GmbH <info(a)sysmocom.de> + * Author: Vadim Yanitskiy <vyanitskiy(a)sysmocom.de> + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + */ + +#include <stdint.h> + +#include <osmocom/core/msgb.h> +#include <osmocom/core/utils.h> +#include <osmocom/gsm/gsm_utils.h> +#include <osmocom/gsm/protocol/gsm_08_58.h> + +#include <osmocom/bb/virtphy/l1ctl_sap.h> +#include <osmocom/bb/virtphy/virt_l1_sched.h> +#include <osmocom/bb/virtphy/gsmtapl1_if.h> +#include <osmocom/bb/virtphy/logging.h> + +#include <osmocom/bb/l1ctl_proto.h> +#include <osmocom/bb/l1gprs.h> + +void l1ctl_rx_gprs_uldl_tbf_cfg_req(struct l1_model_ms *ms, struct msgb *msg) +{ + const struct l1ctl_hdr *l1h = (struct l1ctl_hdr *)msg->data; + + if (OSMO_UNLIKELY(ms->gprs == NULL)) { + LOGPMS(DL1C, LOGL_ERROR, ms, "l1gprs is not initialized\n"); + return; + } + + msg->l1h = msgb_pull(msg, sizeof(*l1h)); + + if (l1h->msg_type == L1CTL_GPRS_UL_TBF_CFG_REQ) + l1gprs_handle_ul_tbf_cfg_req(ms->gprs, msg); + else + l1gprs_handle_dl_tbf_cfg_req(ms->gprs, msg); +} + +void l1ctl_rx_gprs_ul_block_req(struct l1_model_ms *ms, struct msgb *msg) +{ + const struct l1ctl_hdr *l1h = (struct l1ctl_hdr *)msg->data; + struct l1gprs_prim_ul_block_req req; + uint32_t fn_sched; + + if (OSMO_UNLIKELY(ms->gprs == NULL)) { + LOGPMS(DL1P, LOGL_ERROR, ms, "l1gprs is not initialized\n"); + return; + } + + msg->l1h = (void *)l1h->data; + if (l1gprs_handle_ul_block_req(ms->gprs, &req, msg) != 0) + return; + msg->l2h = (void *)&req.data[0]; + + fn_sched = sched_fn_ul(ms->state.current_time, + RSL_CHAN_OSMO_PDCH | req.hdr.tn, 0x00); + if (OSMO_UNLIKELY(fn_sched != req.hdr.fn)) { + LOGPMS(DL1P, LOGL_ERROR, ms, + "GPRS UL BLOCK.req: fn_sched(%u) != fn_req(%u)\n", + fn_sched, req.hdr.fn); + /* FIXME: return; */ + } + + virt_l1_sched_schedule(ms, msg, fn_sched, req.hdr.tn, + &gsmtapl1_tx_to_virt_um_inst); +} + +void l1ctl_tx_gprs_dl_block_ind(struct l1_model_ms *ms, const struct msgb *msg, + uint32_t fn, uint8_t tn, uint8_t rxlev) +{ + struct l1gprs_prim_dl_block_ind ind; + struct msgb *nmsg; + + if (ms->gprs == NULL) + return; + + ind = (struct l1gprs_prim_dl_block_ind) { + .hdr = { + .fn = fn, + .tn = tn, + }, + .meas = { + .ber10k = 0, /* perfect Um, no errors */ + .ci_cb = 180, /* 18 dB */ + .rx_lev = rxlev, + }, + .data = msgb_data(msg), + .data_len = msgb_length(msg), + }; + + nmsg = l1gprs_handle_dl_block_ind(ms->gprs, &ind); + if (nmsg != NULL) + l1ctl_sap_tx_to_l23_inst(ms, nmsg); +} diff --git a/src/host/virt_phy/src/virtphy.c b/src/host/virt_phy/src/virtphy.c index ad09a53..005ae2d 100644 --- a/src/host/virt_phy/src/virtphy.c +++ b/src/host/virt_phy/src/virtphy.c @@ -40,8 +40,9 @@ #include <osmocom/bb/virtphy/gsmtapl1_if.h> #include <osmocom/bb/virtphy/logging.h> #include <osmocom/bb/virtphy/virt_l1_sched.h> +#include <osmocom/bb/l1gprs.h> -#define DEFAULT_LOG_MASK "DL1C,2:DL1P,2:DVIRPHY,2:DMAIN,1" +#define DEFAULT_LOG_MASK "DL1C,2:DL1P,2:DVIRPHY,2:DGPRS,1:DMAIN,1" /* this exists once in the program, and contains the state that we * only keep once: L1CTL server socket, GSMTAP/VirtUM socket */ @@ -242,6 +243,7 @@ handle_options(argc, argv); ms_log_init(log_mask); + l1gprs_logging_init(DGPRS); LOGP(DVIRPHY, LOGL_INFO, "Virtual physical layer starting up...\n"); diff --git a/src/shared/l1gprs.c b/src/shared/l1gprs.c new file mode 100644 index 0000000..3babd2b --- /dev/null +++ b/src/shared/l1gprs.c @@ -0,0 +1,457 @@ +/* + * l1gprs - GPRS layer 1 implementation + * + * (C) 2022-2023 by sysmocom - s.f.m.c. GmbH <info(a)sysmocom.de> + * Author: Vadim Yanitskiy <vyanitskiy(a)sysmocom.de> + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + */ + +#include <errno.h> +#include <stdint.h> +#include <stdbool.h> + +#include <arpa/inet.h> + +#include <osmocom/core/logging.h> +#include <osmocom/core/talloc.h> +#include <osmocom/core/utils.h> +#include <osmocom/core/msgb.h> + +#include <osmocom/gsm/protocol/gsm_04_08.h> +#include <osmocom/gsm/protocol/gsm_44_060.h> + +#include <osmocom/bb/l1ctl_proto.h> +#include <osmocom/bb/l1gprs.h> + +#define LOGP_GPRS(gprs, level, fmt, args...) \ + LOGP(l1gprs_log_cat, level, "%s" fmt, \ + (gprs)->log_prefix, ## args) + +#define LOGP_PDCH(pdch, level, fmt, args...) \ + LOGP_GPRS((pdch)->gprs, level, "(PDCH-%u) " fmt, \ + (pdch)->tn, ## args) + +#define LOG_TBF_FMT "%cL-TBF#%03d" +#define LOG_TBF_ARGS(tbf) \ + (tbf)->uplink ? 'U' : 'D', tbf->tbf_ref + +static int l1gprs_log_cat = DLGLOBAL; + +enum gprs_rlcmac_block_type { + GPRS_RLCMAC_DATA_BLOCK = 0x00, + GPRS_RLCMAC_CONTROL_BLOCK = 0x01, + GPRS_RLCMAC_CONTROL_BLOCK_OPT = 0x02, + GPRS_RLCMAC_RESERVED = 0x03, +}; + +static struct l1gprs_tbf *l1gprs_tbf_alloc(struct l1gprs_state *gprs, + bool uplink, uint8_t tbf_ref, + uint8_t slotmask) +{ + struct l1gprs_tbf *tbf; + + tbf = talloc(gprs, struct l1gprs_tbf); + OSMO_ASSERT(tbf != NULL); + + tbf->uplink = uplink; + tbf->tbf_ref = tbf_ref; + tbf->slotmask = slotmask; + + return tbf; +} + +static void l1gprs_tbf_free(struct l1gprs_tbf *tbf) +{ + if (tbf == NULL) + return; + llist_del(&tbf->list); + talloc_free(tbf); +} + +static struct l1gprs_tbf *l1gprs_find_tbf(struct l1gprs_state *gprs, + bool uplink, uint8_t tbf_ref) +{ + struct l1gprs_tbf *tbf; + + llist_for_each_entry(tbf, &gprs->tbf_list, list) { + if (tbf->uplink != uplink) + continue; + if (tbf->tbf_ref != tbf_ref) + continue; + return tbf; + } + + return NULL; +} + +static void l1gprs_register_tbf(struct l1gprs_state *gprs, + struct l1gprs_tbf *tbf) +{ + OSMO_ASSERT(tbf->slotmask != 0x00); + + /* Update the PDCH states */ + for (unsigned int tn = 0; tn < ARRAY_SIZE(gprs->pdch); tn++) { + struct l1gprs_pdch *pdch = &gprs->pdch[tn]; + + if (~tbf->slotmask & (1 << pdch->tn)) + continue; + + if (tbf->uplink) { + pdch->ul_tbf_count++; + } else { + pdch->dl_tbf_count++; + pdch->dl_tfi_mask |= (1 << tbf->dl_tfi); + } + + LOGP_PDCH(pdch, LOGL_DEBUG, + "Linked " LOG_TBF_FMT "\n", + LOG_TBF_ARGS(tbf)); + } + + llist_add_tail(&tbf->list, &gprs->tbf_list); + + LOGP_GPRS(gprs, LOGL_INFO, + LOG_TBF_FMT " is registered\n", + LOG_TBF_ARGS(tbf)); +} + +static void l1gprs_unregister_tbf(struct l1gprs_state *gprs, + bool uplink, uint8_t tbf_ref) +{ + struct l1gprs_tbf *tbf; + + tbf = l1gprs_find_tbf(gprs, uplink, tbf_ref); + if (tbf == NULL) { + LOGP_GPRS(gprs, LOGL_ERROR, + "%s(): " LOG_TBF_FMT " not found\n", + __func__, LOG_TBF_ARGS(tbf)); + return; + } + + /* Update the PDCH states */ + for (unsigned int tn = 0; tn < ARRAY_SIZE(gprs->pdch); tn++) { + struct l1gprs_pdch *pdch = &gprs->pdch[tn]; + + if (~tbf->slotmask & (1 << pdch->tn)) + continue; + + if (tbf->uplink) { + OSMO_ASSERT(pdch->ul_tbf_count > 0); + pdch->ul_tbf_count--; + } else { + OSMO_ASSERT(pdch->dl_tbf_count > 0); + pdch->dl_tbf_count--; + pdch->dl_tfi_mask &= ~(1 << tbf->dl_tfi); + } + + LOGP_PDCH(pdch, LOGL_DEBUG, + "Unlinked " LOG_TBF_FMT "\n", + LOG_TBF_ARGS(tbf)); + } + + LOGP_GPRS(gprs, LOGL_INFO, + LOG_TBF_FMT " is unregistered and free()d\n", + LOG_TBF_ARGS(tbf)); + + l1gprs_tbf_free(tbf); +} + +#define L1GPRS_L1CTL_MSGB_SIZE 256 +#define L1GPRS_L1CTL_MSGB_HEADROOM 32 + +static struct msgb *l1gprs_l1ctl_msgb_alloc(uint8_t msg_type) +{ + struct l1ctl_hdr *l1h; + struct msgb *msg; + + msg = msgb_alloc_headroom(L1GPRS_L1CTL_MSGB_SIZE, + L1GPRS_L1CTL_MSGB_HEADROOM, + "l1gprs_l1ctl_msg"); + if (msg == NULL) + return NULL; + + msg->l1h = msgb_put(msg, sizeof(*l1h)); + l1h = (struct l1ctl_hdr *)msg->l1h; + l1h->msg_type = msg_type; + + return msg; +} + +static bool l1gprs_pdch_filter_dl_block(const struct l1gprs_pdch *pdch, + const uint8_t *data) +{ + enum gprs_rlcmac_block_type block_type = data[0] >> 6; + uint8_t dl_tfi; + + switch (block_type) { + case GPRS_RLCMAC_DATA_BLOCK: + /* see 3GPP TS 44.060, section 10.2.1 */ + dl_tfi = (data[1] >> 1) & 0x1f; + break; + case GPRS_RLCMAC_CONTROL_BLOCK_OPT: + /* see 3GPP TS 44.060, section 10.3.1 */ + dl_tfi = (data[2] >> 1) & 0x1f; + break; + case GPRS_RLCMAC_CONTROL_BLOCK: + /* no optional octets */ + return true; + default: + LOGP_PDCH(pdch, LOGL_NOTICE, + "Rx Downlink block with unknown payload (0x%0x)\n", + block_type); + return false; + } + + if (pdch->dl_tfi_mask & (1 << dl_tfi)) + return true; + return false; +} + +/////////////////////////////////////////////////////////////////////////////////// + +void l1gprs_logging_init(int logc) +{ + l1gprs_log_cat = logc; +} + +struct l1gprs_state *l1gprs_state_alloc(void *ctx, const char *log_prefix, void *priv) +{ + struct l1gprs_state *gprs; + + gprs = talloc_zero(ctx, struct l1gprs_state); + if (gprs == NULL) + return NULL; + + for (unsigned int tn = 0; tn < ARRAY_SIZE(gprs->pdch); tn++) { + struct l1gprs_pdch *pdch = &gprs->pdch[tn]; + + pdch->tn = tn; + pdch->gprs = gprs; + } + + INIT_LLIST_HEAD(&gprs->tbf_list); + + if (log_prefix == NULL) + gprs->log_prefix = talloc_asprintf(gprs, "l1gprs[0x%p]: ", gprs); + else + gprs->log_prefix = talloc_strdup(gprs, log_prefix); + gprs->priv = priv; + + return gprs; +} + +void l1gprs_state_free(struct l1gprs_state *gprs) +{ + if (gprs == NULL) + return; + + while (!llist_empty(&gprs->tbf_list)) { + struct l1gprs_tbf *tbf; + + tbf = llist_first_entry(&gprs->tbf_list, struct l1gprs_tbf, list); + LOGP_GPRS(gprs, LOGL_DEBUG, + "%s(): " LOG_TBF_FMT " is free()d\n", + __func__, LOG_TBF_ARGS(tbf)); + l1gprs_tbf_free(tbf); + } + + talloc_free(gprs->log_prefix); + talloc_free(gprs); +} + +int l1gprs_handle_ul_tbf_cfg_req(struct l1gprs_state *gprs, const struct msgb *msg) +{ + const struct l1ctl_gprs_ul_tbf_cfg_req *req = (void *)msg->l1h; + struct l1gprs_tbf *tbf = NULL; + + OSMO_ASSERT(req != NULL); + + if (msgb_l1len(msg) < sizeof(*req)) { + LOGP_GPRS(gprs, LOGL_ERROR, + "Rx malformed Uplink TBF config (len=%u < %zu)\n", + msgb_l1len(msg), sizeof(*req)); + return -EINVAL; + } + + LOGP_GPRS(gprs, LOGL_INFO, + "Rx Uplink TBF config: tbf_ref=%u, slotmask=0x%02x\n", + req->tbf_ref, req->slotmask); + + if (req->slotmask != 0x00) { + tbf = l1gprs_tbf_alloc(gprs, true, req->tbf_ref, req->slotmask); + l1gprs_register_tbf(gprs, tbf); + } else { + l1gprs_unregister_tbf(gprs, true, req->tbf_ref); + } + + return 0; +} + +int l1gprs_handle_dl_tbf_cfg_req(struct l1gprs_state *gprs, const struct msgb *msg) +{ + const struct l1ctl_gprs_dl_tbf_cfg_req *req = (void *)msg->l1h; + struct l1gprs_tbf *tbf = NULL; + + OSMO_ASSERT(req != NULL); + + if (msgb_l1len(msg) < sizeof(*req)) { + LOGP_GPRS(gprs, LOGL_ERROR, + "Rx malformed Downlink TBF config (len=%u < %zu)\n", + msgb_l1len(msg), sizeof(*req)); + return -EINVAL; + } + + LOGP_GPRS(gprs, LOGL_INFO, + "Rx Downlink TBF config: tbf_ref=%u, slotmask=0x%02x, dl_tfi=%u\n", + req->tbf_ref, req->slotmask, req->dl_tfi); + + if (req->dl_tfi > 31) { + LOGP_GPRS(gprs, LOGL_ERROR, + "Invalid DL TFI %u (shall be in range 0..31)\n", + req->dl_tfi); + return -EINVAL; + } + + if (req->slotmask != 0x00) { + tbf = l1gprs_tbf_alloc(gprs, false, req->tbf_ref, req->slotmask); + tbf->dl_tfi = req->dl_tfi; + l1gprs_register_tbf(gprs, tbf); + } else { + l1gprs_unregister_tbf(gprs, false, req->tbf_ref); + } + + return 0; +} + +int l1gprs_handle_ul_block_req(struct l1gprs_state *gprs, + struct l1gprs_prim_ul_block_req *req, + const struct msgb *msg) +{ + const struct l1ctl_gprs_ul_block_req *l1br = (void *)msg->l1h; + const struct l1gprs_pdch *pdch = NULL; + size_t data_len; + + OSMO_ASSERT(l1br != NULL); + + if (OSMO_UNLIKELY(msgb_l1len(msg) < sizeof(*l1br))) { + LOGP_GPRS(gprs, LOGL_ERROR, + "Rx malformed UL BLOCK.req (len=%u < %zu)\n", + msgb_l1len(msg), sizeof(*l1br)); + return -EINVAL; + } + if (OSMO_UNLIKELY(l1br->hdr.tn >= ARRAY_SIZE(gprs->pdch))) { + LOGP_GPRS(gprs, LOGL_ERROR, + "Rx malformed UL BLOCK.req (tn=%u)\n", + l1br->hdr.tn); + return -EINVAL; + } + + pdch = &gprs->pdch[l1br->hdr.tn]; + data_len = msgb_l1len(msg) - sizeof(*l1br); + + LOGP_PDCH(pdch, LOGL_DEBUG, + "Rx UL BLOCK.req (fn=%u, len=%zu): %s\n", + ntohl(l1br->hdr.fn), data_len, osmo_hexdump(l1br->data, data_len)); + + if ((pdch->ul_tbf_count == 0) && (pdch->dl_tbf_count == 0)) { + LOGP_PDCH(pdch, LOGL_ERROR, + "Rx UL BLOCK.req, but this PDCH has no configured TBFs\n"); + return -EINVAL; + } + + *req = (struct l1gprs_prim_ul_block_req) { + .hdr = { + .fn = ntohl(l1br->hdr.fn), + .tn = l1br->hdr.tn, + }, + .data = &l1br->data[0], + .data_len = data_len, + }; + + return 0; +} + +struct msgb *l1gprs_handle_dl_block_ind(struct l1gprs_state *gprs, + const struct l1gprs_prim_dl_block_ind *ind) +{ + const struct l1gprs_pdch *pdch = NULL; + struct l1ctl_gprs_dl_block_ind *l1bi; + enum osmo_gprs_cs cs; + struct msgb *msg; + + if (OSMO_UNLIKELY(ind->hdr.tn >= ARRAY_SIZE(gprs->pdch))) { + LOGP_GPRS(gprs, LOGL_ERROR, + "Rx malformed DL BLOCK.ind (tn=%u)\n", + ind->hdr.tn); + return NULL; + } + + pdch = &gprs->pdch[ind->hdr.tn]; + + LOGP_PDCH(pdch, LOGL_DEBUG, + "Rx DL BLOCK.ind (fn=%u, len=%zu): %s\n", + ind->hdr.fn, ind->data_len, osmo_hexdump(ind->data, ind->data_len)); + + if ((pdch->ul_tbf_count == 0) && (pdch->dl_tbf_count == 0)) { + LOGP_PDCH(pdch, LOGL_ERROR, + "Rx DL BLOCK.ind, but this PDCH has no configured TBFs\n"); + return NULL; + } + + msg = l1gprs_l1ctl_msgb_alloc(L1CTL_GPRS_DL_BLOCK_IND); + if (OSMO_UNLIKELY(msg == NULL)) { + LOGP_GPRS(gprs, LOGL_ERROR, "l1gprs_l1ctl_msgb_alloc() failed\n"); + return NULL; + } + + l1bi = (void *)msgb_put(msg, sizeof(*l1bi)); + *l1bi = (struct l1ctl_gprs_dl_block_ind) { + .hdr = { + .fn = htonl(ind->hdr.fn), + .tn = ind->hdr.tn, + }, + .meas = { + .ber10k = htons(ind->meas.ber10k), + .ci_cb = htons(ind->meas.ci_cb), + .rx_lev = ind->meas.rx_lev, + }, + .usf = 0xff, + }; + + if (ind->data_len == 0) + return msg; + + cs = osmo_gprs_dl_cs_by_block_bytes(ind->data_len); + switch (cs) { + case OSMO_GPRS_CS1: + case OSMO_GPRS_CS2: + case OSMO_GPRS_CS3: + case OSMO_GPRS_CS4: + l1bi->usf = ind->data[0] & 0x07; + /* Determine whether to include the payload or not */ + if (l1gprs_pdch_filter_dl_block(pdch, ind->data)) + memcpy(msgb_put(msg, ind->data_len), ind->data, ind->data_len); + break; + case OSMO_GPRS_CS_NONE: + LOGP_PDCH(pdch, LOGL_ERROR, + "Failed to determine Coding Scheme (len=%zu)\n", ind->data_len); + break; + default: + LOGP_PDCH(pdch, LOGL_NOTICE, "Coding Scheme %d is not supported\n", cs); + break; + } + + return msg; +} -- To view, visit https://gerrit.osmocom.org/c/osmocom-bb/+/30743 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: I9567d64f9d00262e36147e8d7e541e5e246bda5f Gerrit-Change-Number: 30743 Gerrit-PatchSet: 12 Gerrit-Owner: fixeria <vyanitskiy(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-MessageType: merged
1 0
0 0
[M] Change in osmocom-bb[master]: modem: route L1CTL prims to/from libosmo-gprs-rlcmac
by fixeria 17 Mar '23

17 Mar '23
fixeria has submitted this change. ( https://gerrit.osmocom.org/c/osmocom-bb/+/31572 ) Change subject: modem: route L1CTL prims to/from libosmo-gprs-rlcmac ...................................................................... modem: route L1CTL prims to/from libosmo-gprs-rlcmac Change-Id: I38e9a686f8edc3fe55f961d75e68602c33bbbaaf Related: OS#5500 --- M src/host/layer23/src/modem/rlcmac.c 1 file changed, 77 insertions(+), 5 deletions(-) Approvals: laforge: Looks good to me, approved pespin: Looks good to me, but someone else must approve Jenkins Builder: Verified diff --git a/src/host/layer23/src/modem/rlcmac.c b/src/host/layer23/src/modem/rlcmac.c index 7cd1ba4..6e39273 100644 --- a/src/host/layer23/src/modem/rlcmac.c +++ b/src/host/layer23/src/modem/rlcmac.c @@ -30,13 +30,19 @@ #include <osmocom/core/logging.h> #include <osmocom/gsm/gsm_utils.h> +#include <osmocom/gsm/gsm0502.h> + #include <osmocom/gprs/rlcmac/rlcmac_prim.h> #include <osmocom/gprs/rlcmac/rlcmac.h> #include <osmocom/gprs/llc/llc_prim.h> #include <osmocom/bb/common/logging.h> +#include <osmocom/bb/common/l1ctl.h> #include <osmocom/bb/common/ms.h> #include <osmocom/bb/modem/rlcmac.h> +#include <osmocom/bb/modem/grr.h> + +#include <l1ctl_proto.h> static int modem_rlcmac_handle_grr(struct osmo_gprs_rlcmac_prim *rlcmac_prim) { @@ -108,17 +114,70 @@ return rc; } -static int modem_rlcmac_prim_down_cb(struct osmo_gprs_rlcmac_prim *rlcmac_prim, void *user_data) +static int modem_rlcmac_prim_down_cb(struct osmo_gprs_rlcmac_prim *prim, void *user_data) { - const char *pdu_name = osmo_gprs_rlcmac_prim_name(rlcmac_prim); - int rc = 0; + const struct osmo_gprs_rlcmac_l1ctl_prim *lp = &prim->l1ctl; + const char *pdu_name = osmo_gprs_rlcmac_prim_name(prim); + struct osmocom_ms *ms = user_data; - switch (rlcmac_prim->oph.sap) { + switch (OSMO_PRIM_HDR(&prim->oph)) { + case OSMO_PRIM(OSMO_GPRS_RLCMAC_L1CTL_RACH, PRIM_OP_REQUEST): + if (lp->rach_req.is_11bit) { + LOGP(DRLCMAC, LOGL_NOTICE, + "%s(): 11-bit RACH is not supported\n", __func__); + return -ENOTSUP; + } + return modem_grr_tx_chan_req(ms, lp->rach_req.ra); + case OSMO_PRIM(OSMO_GPRS_RLCMAC_L1CTL_PDCH_DATA, PRIM_OP_REQUEST): + return l1ctl_tx_gprs_ul_block_req(ms, + lp->pdch_data_req.fn, + lp->pdch_data_req.ts_nr, + lp->pdch_data_req.data, + lp->pdch_data_req.data_len); + case OSMO_PRIM(OSMO_GPRS_RLCMAC_L1CTL_CFG_UL_TBF, PRIM_OP_REQUEST): + return l1ctl_tx_gprs_ul_tbf_cfg_req(ms, + lp->cfg_ul_tbf_req.ul_tbf_nr, + lp->cfg_ul_tbf_req.ul_slotmask); + case OSMO_PRIM(OSMO_GPRS_RLCMAC_L1CTL_CFG_DL_TBF, PRIM_OP_REQUEST): + return l1ctl_tx_gprs_dl_tbf_cfg_req(ms, + lp->cfg_dl_tbf_req.dl_tbf_nr, + lp->cfg_dl_tbf_req.dl_slotmask, + lp->cfg_dl_tbf_req.dl_tfi); default: LOGP(DRLCMAC, LOGL_DEBUG, "%s(): Unexpected Rx %s\n", __func__, pdu_name); OSMO_ASSERT(0); } - return rc; +} + +static int l1ctl_dl_block_cb(struct osmocom_ms *ms, struct msgb *msg) +{ + const struct l1ctl_gprs_dl_block_ind *ind = (void *)msg->l1h; + const uint32_t fn = osmo_load32be(&ind->hdr.fn); + struct osmo_gprs_rlcmac_prim *prim; + + /* FIXME: sadly, rlcmac_prim_l1ctl_alloc() is not exposed */ + prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_data_ind(0, 0, 0, 0, 0, NULL, 0); + prim->l1ctl = (struct osmo_gprs_rlcmac_l1ctl_prim) { + .pdch_data_ind = { + .fn = fn, + .ts_nr = ind->hdr.tn, + .rx_lev = ind->meas.rx_lev, + .ber10k = osmo_load16be(&ind->meas.ber10k), + .ci_cb = osmo_load16be(&ind->meas.ci_cb), + .data_len = msgb_l2len(msg), + .data = msgb_l2(msg), + } + }; + osmo_gprs_rlcmac_prim_lower_up(prim); + + /* Every fn % 13 == 12 we have either a PTCCH or an IDLE slot, thus + * every fn % 13 == 8 we add 5 frames, or 4 frames othrwise. The + * resulting value is first fn of the next block. */ + const uint32_t rts_fn = GSM_TDMA_FN_SUM(fn, (fn % 13 == 8) ? 5 : 4); + prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(ind->hdr.tn, rts_fn, ind->usf); + osmo_gprs_rlcmac_prim_lower_up(prim); + + return 0; } int modem_rlcmac_init(struct osmocom_ms *ms) @@ -132,5 +191,8 @@ osmo_gprs_rlcmac_prim_set_up_cb(modem_rlcmac_prim_up_cb, ms); osmo_gprs_rlcmac_prim_set_down_cb(modem_rlcmac_prim_down_cb, ms); + + ms->l1_entity.l1_gprs_dl_block_ind = &l1ctl_dl_block_cb; + return rc; } -- 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: 9 Gerrit-Owner: fixeria <vyanitskiy(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-MessageType: merged
1 0
0 0
[M] Change in osmocom-bb[master]: layer23: implement Rx/Tx API for GPRS related messages
by fixeria 17 Mar '23

17 Mar '23
fixeria has submitted this change. ( https://gerrit.osmocom.org/c/osmocom-bb/+/31571 ) Change subject: layer23: implement Rx/Tx API for GPRS related messages ...................................................................... layer23: implement Rx/Tx API for GPRS related messages Change-Id: I87950e893ef96ff8328f43f1548111aa9f66439b Related: OS#5500 --- M src/host/layer23/include/osmocom/bb/common/l1ctl.h M src/host/layer23/include/osmocom/bb/common/ms.h M src/host/layer23/src/common/l1ctl.c 3 files changed, 127 insertions(+), 0 deletions(-) Approvals: laforge: Looks good to me, but someone else must approve fixeria: Looks good to me, approved pespin: Looks good to me, but someone else must approve Jenkins Builder: Verified diff --git a/src/host/layer23/include/osmocom/bb/common/l1ctl.h b/src/host/layer23/include/osmocom/bb/common/l1ctl.h index 5b20506..25bc6e8 100644 --- a/src/host/layer23/include/osmocom/bb/common/l1ctl.h +++ b/src/host/layer23/include/osmocom/bb/common/l1ctl.h @@ -75,4 +75,16 @@ /* Transmit L1CTL_NEIGH_PM_REQ */ int l1ctl_tx_neigh_pm_req(struct osmocom_ms *ms, int num, uint16_t *arfcn); +/* Transmit L1CTL_GPRS_UL_BLOCK_REQ */ +int l1ctl_tx_gprs_ul_block_req(struct osmocom_ms *ms, uint32_t fn, uint8_t tn, + const uint8_t *data, size_t data_len); + +/* Transmit L1CTL_GPRS_UL_TBF_CFG_REQ */ +int l1ctl_tx_gprs_ul_tbf_cfg_req(struct osmocom_ms *ms, uint8_t tbf_ref, + uint8_t slotmask); + +/* Transmit L1CTL_GPRS_DL_TBF_CFG_REQ */ +int l1ctl_tx_gprs_dl_tbf_cfg_req(struct osmocom_ms *ms, uint8_t tbf_ref, + uint8_t slotmask, uint8_t dl_tfi); + #endif diff --git a/src/host/layer23/include/osmocom/bb/common/ms.h b/src/host/layer23/include/osmocom/bb/common/ms.h index 30bb514..e4888a7 100644 --- a/src/host/layer23/include/osmocom/bb/common/ms.h +++ b/src/host/layer23/include/osmocom/bb/common/ms.h @@ -36,6 +36,7 @@ struct osmol1_entity { int (*l1_traffic_ind)(struct osmocom_ms *ms, struct msgb *msg); + int (*l1_gprs_dl_block_ind)(struct osmocom_ms *ms, struct msgb *msg); }; struct osmomncc_entity { diff --git a/src/host/layer23/src/common/l1ctl.c b/src/host/layer23/src/common/l1ctl.c index 34051fd..8e55b7b 100644 --- a/src/host/layer23/src/common/l1ctl.c +++ b/src/host/layer23/src/common/l1ctl.c @@ -978,6 +978,107 @@ return 0; } +/* Receive L1CTL_GPRS_DL_BLOCK_IND */ +static int rx_l1_gprs_dl_block_ind(struct osmocom_ms *ms, struct msgb *msg) +{ + const struct l1ctl_gprs_dl_block_ind *ind = (void *)msg->l1h; + + if (msgb_l1len(msg) < sizeof(*ind)) { + LOGP(DL1C, LOGL_ERROR, + "Rx malformed GPRS DL BLOCK.ind (len=%u < %zu)\n", + msgb_l1len(msg), sizeof(*ind)); + return -EINVAL; + } + if (OSMO_UNLIKELY(ind->hdr.tn >= 8)) { + LOGP(DL1C, LOGL_ERROR, + "Rx malformed GPRS DL BLOCK.ind (tn=%u)\n", + ind->hdr.tn); + return -EINVAL; + } + + msg->l2h = (void *)&ind->data[0]; + + DEBUGP(DL1C, "Rx GPRS DL block (fn=%u, tn=%u, len=%u): %s\n", + ntohl(ind->hdr.fn), ind->hdr.tn, msgb_l2len(msg), msgb_hexdump_l2(msg)); + + /* distribute or drop */ + if (ms->l1_entity.l1_gprs_dl_block_ind) + return ms->l1_entity.l1_gprs_dl_block_ind(ms, msg); + + msgb_free(msg); + return 0; +} + +/* Transmit L1CTL_GPRS_UL_BLOCK_REQ */ +int l1ctl_tx_gprs_ul_block_req(struct osmocom_ms *ms, uint32_t fn, uint8_t tn, + const uint8_t *data, size_t data_len) +{ + struct l1ctl_gprs_ul_block_req *req; + struct msgb *msg; + + msg = osmo_l1_alloc(L1CTL_GPRS_UL_BLOCK_REQ); + if (!msg) + return -ENOMEM; + + req = (void *)msgb_put(msg, sizeof(*req)); + req->hdr.fn = htonl(fn); + req->hdr.tn = tn; + if (data_len > 0) + memcpy(msgb_put(msg, data_len), data, data_len); + + DEBUGP(DL1C, "Tx GPRS UL block (fn=%u, tn=%u, len=%zu): %s\n", + fn, tn, data_len, osmo_hexdump(data, data_len)); + + return osmo_send_l1(ms, msg); +} + +/* Transmit L1CTL_GPRS_UL_TBF_CFG_REQ */ +int l1ctl_tx_gprs_ul_tbf_cfg_req(struct osmocom_ms *ms, uint8_t tbf_ref, + uint8_t slotmask) +{ + struct l1ctl_gprs_ul_tbf_cfg_req *req; + struct msgb *msg; + + msg = osmo_l1_alloc(L1CTL_GPRS_UL_TBF_CFG_REQ); + if (!msg) + return -ENOMEM; + + req = (void *)msgb_put(msg, sizeof(*req)); + *req = (struct l1ctl_gprs_ul_tbf_cfg_req) { + .tbf_ref = tbf_ref, + .slotmask = slotmask, + }; + + DEBUGP(DL1C, "Tx GPRS UL TBF CFG (tbf_ref=%u, slotmask=0x%02x)\n", + tbf_ref, slotmask); + + return osmo_send_l1(ms, msg); +} + +/* Transmit L1CTL_GPRS_DL_TBF_CFG_REQ */ +int l1ctl_tx_gprs_dl_tbf_cfg_req(struct osmocom_ms *ms, uint8_t tbf_ref, + uint8_t slotmask, uint8_t dl_tfi) +{ + struct l1ctl_gprs_dl_tbf_cfg_req *req; + struct msgb *msg; + + msg = osmo_l1_alloc(L1CTL_GPRS_DL_TBF_CFG_REQ); + if (!msg) + return -ENOMEM; + + req = (void *)msgb_put(msg, sizeof(*req)); + *req = (struct l1ctl_gprs_dl_tbf_cfg_req) { + .tbf_ref = tbf_ref, + .slotmask = slotmask, + .dl_tfi = dl_tfi, + }; + + DEBUGP(DL1C, "Tx GPRS DL TBF CFG (tbf_ref=%u, slotmask=0x%02x, dl_tfi=%u)\n", + tbf_ref, slotmask, dl_tfi); + + return osmo_send_l1(ms, msg); +} + /* Receive incoming data from L1 using L1CTL format */ int l1ctl_recv(struct osmocom_ms *ms, struct msgb *msg) { @@ -1046,6 +1147,9 @@ case L1CTL_TRAFFIC_CONF: msgb_free(msg); break; + case L1CTL_GPRS_DL_BLOCK_IND: + rc = rx_l1_gprs_dl_block_ind(ms, msg); + break; default: LOGP(DL1C, LOGL_ERROR, "Unknown MSG: %u\n", hdr->msg_type); msgb_free(msg); -- To view, visit https://gerrit.osmocom.org/c/osmocom-bb/+/31571 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: I87950e893ef96ff8328f43f1548111aa9f66439b Gerrit-Change-Number: 31571 Gerrit-PatchSet: 8 Gerrit-Owner: fixeria <vyanitskiy(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-MessageType: merged
1 0
0 0
[M] Change in osmocom-bb[master]: layer23: implement Rx/Tx API for GPRS related messages
by fixeria 17 Mar '23

17 Mar '23
fixeria has posted comments on this change. ( https://gerrit.osmocom.org/c/osmocom-bb/+/31571 ) Change subject: layer23: implement Rx/Tx API for GPRS related messages ...................................................................... Patch Set 7: Code-Review+2 -- To view, visit https://gerrit.osmocom.org/c/osmocom-bb/+/31571 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: I87950e893ef96ff8328f43f1548111aa9f66439b Gerrit-Change-Number: 31571 Gerrit-PatchSet: 7 Gerrit-Owner: fixeria <vyanitskiy(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-Comment-Date: Fri, 17 Mar 2023 12:15:19 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1 0
0 0
[XL] Change in osmocom-bb[master]: {trxcon,virt_phy}: shared GPRS L1 (MAC) implementation
by fixeria 17 Mar '23

17 Mar '23
Attention is currently required from: pespin. fixeria has posted comments on this change. ( https://gerrit.osmocom.org/c/osmocom-bb/+/30743 ) Change subject: {trxcon,virt_phy}: shared GPRS L1 (MAC) implementation ...................................................................... Patch Set 11: Code-Review+2 -- To view, visit https://gerrit.osmocom.org/c/osmocom-bb/+/30743 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: I9567d64f9d00262e36147e8d7e541e5e246bda5f Gerrit-Change-Number: 30743 Gerrit-PatchSet: 11 Gerrit-Owner: fixeria <vyanitskiy(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-Attention: pespin <pespin(a)sysmocom.de> Gerrit-Comment-Date: Fri, 17 Mar 2023 12:15:13 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1 0
0 0
[M] Change in osmo-bsc[master]: Fix Lb/A SCCP conn lookup after recent regression in optimization patch
by laforge 17 Mar '23

17 Mar '23
Attention is currently required from: neels, pespin, daniel. laforge has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-bsc/+/31940 ) Change subject: Fix Lb/A SCCP conn lookup after recent regression in optimization patch ...................................................................... Patch Set 2: (1 comment) Patchset: PS2: > With patchset version 2, these ones are still failing, I'll check tomorrow: […] I would think it is safer to revert the SCCP optimiziation untill all of this is resolved, rather than having broken master for yet another day (and potentially over the weekend). As we know, there are users of master. -- To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/31940 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-bsc Gerrit-Branch: master Gerrit-Change-Id: If42d93adee71d646766929a09bc01ae92b734ef3 Gerrit-Change-Number: 31940 Gerrit-PatchSet: 2 Gerrit-Owner: pespin <pespin(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: daniel <dwillmann(a)sysmocom.de> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: neels <nhofmeyr(a)sysmocom.de> Gerrit-Reviewer: osmith <osmith(a)sysmocom.de> Gerrit-Attention: neels <nhofmeyr(a)sysmocom.de> Gerrit-Attention: pespin <pespin(a)sysmocom.de> Gerrit-Attention: daniel <dwillmann(a)sysmocom.de> Gerrit-Comment-Date: Fri, 17 Mar 2023 12:14:08 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Comment-In-Reply-To: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: comment
1 0
0 0
  • ← Newer
  • 1
  • ...
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • ...
  • 365
  • Older →

HyperKitty Powered by HyperKitty version 1.3.12.