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

April 2023

  • 1 participants
  • 2252 discussions
[S] Change in osmocom-bb[master]: trxcon/l1sched: cosmetic: rename l1sched_find_lchan()
by fixeria 14 Apr '23

14 Apr '23
fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmocom-bb/+/32302 ) Change subject: trxcon/l1sched: cosmetic: rename l1sched_find_lchan() ...................................................................... trxcon/l1sched: cosmetic: rename l1sched_find_lchan() An upcoming patch will add a similar function taking chan_nr/link_id as the search criteria, so let's clarify the existing API first. Change-Id: Ib9f733c22d7fc6bd933219906ca680f246b07f4b Related: OS#5500 --- M src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h M src/host/trxcon/src/sched_trx.c 2 files changed, 23 insertions(+), 10 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/02/32302/1 diff --git a/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h b/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h index f9894a1..7f7e96d 100644 --- a/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h +++ b/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h @@ -436,8 +436,8 @@ uint8_t codecs_bitmask, uint8_t start_codec); int l1sched_activate_lchan(struct l1sched_ts *ts, enum l1sched_lchan_type chan); int l1sched_deactivate_lchan(struct l1sched_ts *ts, enum l1sched_lchan_type chan); -struct l1sched_lchan_state *l1sched_find_lchan(struct l1sched_ts *ts, - enum l1sched_lchan_type chan); +struct l1sched_lchan_state *l1sched_find_lchan_by_type(struct l1sched_ts *ts, + enum l1sched_lchan_type type); /* Primitive management functions */ struct l1sched_ts_prim *l1sched_prim_push(struct l1sched_state *sched, diff --git a/src/host/trxcon/src/sched_trx.c b/src/host/trxcon/src/sched_trx.c index be4331b..49dadd2 100644 --- a/src/host/trxcon/src/sched_trx.c +++ b/src/host/trxcon/src/sched_trx.c @@ -115,7 +115,7 @@ return; /* Make sure that lchan is allocated and active */ - lchan = l1sched_find_lchan(ts, chan); + lchan = l1sched_find_lchan_by_type(ts, chan); if (lchan == NULL || !lchan->active) return; @@ -413,13 +413,13 @@ return 0; } -struct l1sched_lchan_state *l1sched_find_lchan(struct l1sched_ts *ts, - enum l1sched_lchan_type chan) +struct l1sched_lchan_state *l1sched_find_lchan_by_type(struct l1sched_ts *ts, + enum l1sched_lchan_type type) { struct l1sched_lchan_state *lchan; llist_for_each_entry(lchan, &ts->lchans, list) - if (lchan->type == chan) + if (lchan->type == type) return lchan; return NULL; @@ -485,7 +485,7 @@ struct l1sched_lchan_state *lchan; /* Try to find requested logical channel */ - lchan = l1sched_find_lchan(ts, chan); + lchan = l1sched_find_lchan_by_type(ts, chan); if (lchan == NULL) return -EINVAL; @@ -572,7 +572,7 @@ struct l1sched_lchan_state *lchan; /* Try to find requested logical channel */ - lchan = l1sched_find_lchan(ts, chan); + lchan = l1sched_find_lchan_by_type(ts, chan); if (lchan == NULL) return -EINVAL; @@ -794,7 +794,7 @@ return -ENODEV; /* Find required channel state */ - lchan = l1sched_find_lchan(ts, chan); + lchan = l1sched_find_lchan_by_type(ts, chan); if (lchan == NULL) return -ENODEV; @@ -851,7 +851,7 @@ return -ENODEV; /* Find the appropriate logical channel */ - lchan = l1sched_find_lchan(ts, frame->dl_chan); + lchan = l1sched_find_lchan_by_type(ts, frame->dl_chan); if (lchan == NULL) return -ENODEV; -- To view, visit https://gerrit.osmocom.org/c/osmocom-bb/+/32302 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: Ib9f733c22d7fc6bd933219906ca680f246b07f4b Gerrit-Change-Number: 32302 Gerrit-PatchSet: 1 Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-MessageType: newchange
1 0
0 0
[S] Change in osmocom-bb[master]: trxcon: l1sched: fix copy-paste in LOGP_SCHEDD macro
by fixeria 14 Apr '23

14 Apr '23
fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmocom-bb/+/32300 ) Change subject: trxcon: l1sched: fix copy-paste in LOGP_SCHEDD macro ...................................................................... trxcon: l1sched: fix copy-paste in LOGP_SCHEDD macro Change-Id: I256578ae23e2f2d29a2751169c63d7a3df6d6f56 Related: OS#5500 --- M src/host/trxcon/include/osmocom/bb/l1sched/logging.h 1 file changed, 11 insertions(+), 1 deletion(-) git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/00/32300/1 diff --git a/src/host/trxcon/include/osmocom/bb/l1sched/logging.h b/src/host/trxcon/include/osmocom/bb/l1sched/logging.h index f88fe4c..21be995 100644 --- a/src/host/trxcon/include/osmocom/bb/l1sched/logging.h +++ b/src/host/trxcon/include/osmocom/bb/l1sched/logging.h @@ -16,7 +16,7 @@ /* Data messages using l1sched_state as the context */ #define LOGP_SCHEDD(sched, level, fmt, args...) \ - LOGP_SCHED_CAT(sched, common, level, fmt, ## args) + LOGP_SCHED_CAT(sched, data, level, fmt, ## args) #define LOGP_LCHAN_NAME_FMT "TS%u-%s" -- To view, visit https://gerrit.osmocom.org/c/osmocom-bb/+/32300 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: I256578ae23e2f2d29a2751169c63d7a3df6d6f56 Gerrit-Change-Number: 32300 Gerrit-PatchSet: 1 Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-MessageType: newchange
1 0
0 0
[M] Change in osmocom-bb[master]: trxcon/l1sched: rename l1sched[_lchan]_prim_drop()
by fixeria 14 Apr '23

14 Apr '23
fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmocom-bb/+/32301 ) Change subject: trxcon/l1sched: rename l1sched[_lchan]_prim_drop() ...................................................................... trxcon/l1sched: rename l1sched[_lchan]_prim_drop() Make it clear that this function operates on a logical channel. Also take a chance to remove redundant comments and ws. Change-Id: I0517bba2be5403d437d3879b2332196d872e11f2 Related: OS#5500 --- M src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h M src/host/trxcon/src/sched_lchan_pdtch.c M src/host/trxcon/src/sched_lchan_rach.c M src/host/trxcon/src/sched_lchan_tchf.c M src/host/trxcon/src/sched_lchan_tchh.c M src/host/trxcon/src/sched_lchan_xcch.c M src/host/trxcon/src/sched_prim.c M src/host/trxcon/src/sched_trx.c 8 files changed, 34 insertions(+), 41 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/01/32301/1 diff --git a/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h b/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h index 350294d..f9894a1 100644 --- a/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h +++ b/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h @@ -480,7 +480,7 @@ struct l1sched_ts_prim *l1sched_prim_dequeue(struct llist_head *queue, uint32_t fn, struct l1sched_lchan_state *lchan); int l1sched_prim_dummy(struct l1sched_lchan_state *lchan); -void l1sched_prim_drop(struct l1sched_lchan_state *lchan); +void l1sched_lchan_prim_drop(struct l1sched_lchan_state *lchan); void l1sched_prim_flush_queue(struct llist_head *list); int l1sched_handle_rx_burst(struct l1sched_state *sched, diff --git a/src/host/trxcon/src/sched_lchan_pdtch.c b/src/host/trxcon/src/sched_lchan_pdtch.c index a518d72..722800f 100644 --- a/src/host/trxcon/src/sched_lchan_pdtch.c +++ b/src/host/trxcon/src/sched_lchan_pdtch.c @@ -129,10 +129,7 @@ LOGP_LCHAND(lchan, LOGL_ERROR, "Failed to encode L2 payload (len=%zu): %s\n", lchan->prim->payload_len, osmo_hexdump(lchan->prim->payload, lchan->prim->payload_len)); - - /* Forget this primitive */ - l1sched_prim_drop(lchan); - + l1sched_lchan_prim_drop(lchan); return -EINVAL; } @@ -162,7 +159,7 @@ l1sched_handle_data_cnf(lchan, br->fn, L1SCHED_DT_PACKET_DATA); /* Forget processed primitive */ - l1sched_prim_drop(lchan); + l1sched_lchan_prim_drop(lchan); /* Reset mask */ *mask = 0x00; diff --git a/src/host/trxcon/src/sched_lchan_rach.c b/src/host/trxcon/src/sched_lchan_rach.c index e59c97d..7448d83 100644 --- a/src/host/trxcon/src/sched_lchan_rach.c +++ b/src/host/trxcon/src/sched_lchan_rach.c @@ -90,9 +90,7 @@ LOGP_LCHAND(lchan, LOGL_ERROR, "Unknown RACH synch. sequence=0x%02x\n", rach->synch_seq); - - /* Forget this primitive */ - l1sched_prim_drop(lchan); + l1sched_lchan_prim_drop(lchan); return -ENOTSUP; } @@ -102,9 +100,7 @@ LOGP_LCHAND(lchan, LOGL_ERROR, "Could not encode 11-bit RACH burst (ra=%u bsic=%u)\n", rach->ra, bsic); - - /* Forget this primitive */ - l1sched_prim_drop(lchan); + l1sched_lchan_prim_drop(lchan); return rc; } } else if (L1SCHED_PRIM_IS_RACH8(lchan->prim)) { @@ -116,16 +112,14 @@ LOGP_LCHAND(lchan, LOGL_ERROR, "Could not encode RACH burst (ra=%u bsic=%u)\n", rach->ra, bsic); - - /* Forget this primitive */ - l1sched_prim_drop(lchan); + l1sched_lchan_prim_drop(lchan); return rc; } } else { LOGP_LCHAND(lchan, LOGL_ERROR, "Primitive has unexpected type=0x%02x\n", lchan->prim->type); - l1sched_prim_drop(lchan); + l1sched_lchan_prim_drop(lchan); return -EINVAL; } @@ -154,7 +148,7 @@ l1sched_handle_data_cnf(lchan, br->fn, L1SCHED_DT_OTHER); /* Forget processed primitive */ - l1sched_prim_drop(lchan); + l1sched_lchan_prim_drop(lchan); return 0; } diff --git a/src/host/trxcon/src/sched_lchan_tchf.c b/src/host/trxcon/src/sched_lchan_tchf.c index af7695b..8cb996b 100644 --- a/src/host/trxcon/src/sched_lchan_tchf.c +++ b/src/host/trxcon/src/sched_lchan_tchf.c @@ -309,16 +309,14 @@ LOGP_LCHAND(lchan, LOGL_ERROR, "Invalid TCH mode: %u, dropping frame...\n", lchan->tch_mode); - /* Forget this primitive */ - l1sched_prim_drop(lchan); + l1sched_lchan_prim_drop(lchan); return -EINVAL; } if (lchan->prim->payload_len != l2_len) { LOGP_LCHAND(lchan, LOGL_ERROR, "Primitive has odd length %zu " "(expected %zu for TCH or %u for FACCH), so dropping...\n", lchan->prim->payload_len, l2_len, GSM_MACBLOCK_LEN); - - l1sched_prim_drop(lchan); + l1sched_lchan_prim_drop(lchan); return -EINVAL; } rc = gsm0503_tch_fr_encode(buffer, lchan->prim->payload, l2_len, 1); @@ -329,8 +327,7 @@ lchan->prim->payload_len, osmo_hexdump(lchan->prim->payload, lchan->prim->payload_len)); free_bad_msg: - /* Forget this primitive */ - l1sched_prim_drop(lchan); + l1sched_lchan_prim_drop(lchan); return -EINVAL; } @@ -362,7 +359,7 @@ l1sched_handle_data_cnf(lchan, br->fn, dt); /* Forget processed primitive */ - l1sched_prim_drop(lchan); + l1sched_lchan_prim_drop(lchan); /* Reset mask */ *mask = 0x00; diff --git a/src/host/trxcon/src/sched_lchan_tchh.c b/src/host/trxcon/src/sched_lchan_tchh.c index bebd6e3..7302351 100644 --- a/src/host/trxcon/src/sched_lchan_tchh.c +++ b/src/host/trxcon/src/sched_lchan_tchh.c @@ -529,16 +529,14 @@ LOGP_LCHAND(lchan, LOGL_ERROR, "Invalid TCH mode: %u, dropping frame...\n", lchan->tch_mode); - /* Forget this primitive */ - l1sched_prim_drop(lchan); + l1sched_lchan_prim_drop(lchan); return -EINVAL; } if (lchan->prim->payload_len != l2_len) { LOGP_LCHAND(lchan, LOGL_ERROR, "Primitive has odd length %zu " "(expected %zu for TCH or %u for FACCH), so dropping...\n", lchan->prim->payload_len, l2_len, GSM_MACBLOCK_LEN); - /* Forget this primitive */ - l1sched_prim_drop(lchan); + l1sched_lchan_prim_drop(lchan); return -EINVAL; } rc = gsm0503_tch_hr_encode(buffer, lchan->prim->payload, l2_len); @@ -549,8 +547,7 @@ lchan->prim->payload_len, osmo_hexdump(lchan->prim->payload, lchan->prim->payload_len)); free_bad_msg: - /* Forget this primitive */ - l1sched_prim_drop(lchan); + l1sched_lchan_prim_drop(lchan); return -EINVAL; } @@ -590,7 +587,7 @@ } /* Forget processed primitive */ - l1sched_prim_drop(lchan); + l1sched_lchan_prim_drop(lchan); } return 0; diff --git a/src/host/trxcon/src/sched_lchan_xcch.c b/src/host/trxcon/src/sched_lchan_xcch.c index 0f47ffe..936a899 100644 --- a/src/host/trxcon/src/sched_lchan_xcch.c +++ b/src/host/trxcon/src/sched_lchan_xcch.c @@ -124,8 +124,7 @@ LOGP_LCHAND(lchan, LOGL_ERROR, "Primitive has odd length %zu (expected %u), so dropping...\n", lchan->prim->payload_len, GSM_MACBLOCK_LEN); - - l1sched_prim_drop(lchan); + l1sched_lchan_prim_drop(lchan); return -EINVAL; } @@ -135,10 +134,7 @@ LOGP_LCHAND(lchan, LOGL_ERROR, "Failed to encode L2 payload (len=%zu): %s\n", lchan->prim->payload_len, osmo_hexdump(lchan->prim->payload, lchan->prim->payload_len)); - - /* Forget this primitive */ - l1sched_prim_drop(lchan); - + l1sched_lchan_prim_drop(lchan); return -EINVAL; } @@ -168,7 +164,7 @@ l1sched_handle_data_cnf(lchan, br->fn, L1SCHED_DT_SIGNALING); /* Forget processed primitive */ - l1sched_prim_drop(lchan); + l1sched_lchan_prim_drop(lchan); /* Reset mask */ *mask = 0x00; diff --git a/src/host/trxcon/src/sched_prim.c b/src/host/trxcon/src/sched_prim.c index 99c4d82..b7ebdeb 100644 --- a/src/host/trxcon/src/sched_prim.c +++ b/src/host/trxcon/src/sched_prim.c @@ -466,9 +466,8 @@ * * @param lchan a logical channel to drop prim from */ -void l1sched_prim_drop(struct l1sched_lchan_state *lchan) +void l1sched_lchan_prim_drop(struct l1sched_lchan_state *lchan) { - /* Forget this primitive */ talloc_free(lchan->prim); lchan->prim = NULL; } diff --git a/src/host/trxcon/src/sched_trx.c b/src/host/trxcon/src/sched_trx.c index ac55f92..be4331b 100644 --- a/src/host/trxcon/src/sched_trx.c +++ b/src/host/trxcon/src/sched_trx.c @@ -544,7 +544,7 @@ lchan->tx_bursts = NULL; /* Forget the current prim */ - l1sched_prim_drop(lchan); + l1sched_lchan_prim_drop(lchan); /* Channel specific stuff */ if (L1SCHED_CHAN_IS_TCH(lchan->type)) { -- To view, visit https://gerrit.osmocom.org/c/osmocom-bb/+/32301 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: I0517bba2be5403d437d3879b2332196d872e11f2 Gerrit-Change-Number: 32301 Gerrit-PatchSet: 1 Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-MessageType: newchange
1 0
0 0
[S] Change in osmocom-bb[master]: trxcon/l1sched: add l1sched_find_lchan_by_chan_nr()
by fixeria 14 Apr '23

14 Apr '23
fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmocom-bb/+/32303 ) Change subject: trxcon/l1sched: add l1sched_find_lchan_by_chan_nr() ...................................................................... trxcon/l1sched: add l1sched_find_lchan_by_chan_nr() Change-Id: I9917a932c9a4aeb4b3ef7053bd58066b3aa41edb Related: OS#5500 --- M src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h M src/host/trxcon/src/sched_trx.c 2 files changed, 34 insertions(+), 0 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/03/32303/1 diff --git a/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h b/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h index 7f7e96d..4728f41 100644 --- a/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h +++ b/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h @@ -438,6 +438,8 @@ int l1sched_deactivate_lchan(struct l1sched_ts *ts, enum l1sched_lchan_type chan); struct l1sched_lchan_state *l1sched_find_lchan_by_type(struct l1sched_ts *ts, enum l1sched_lchan_type type); +struct l1sched_lchan_state *l1sched_find_lchan_by_chan_nr(struct l1sched_state *sched, + uint8_t chan_nr, uint8_t link_id); /* Primitive management functions */ struct l1sched_ts_prim *l1sched_prim_push(struct l1sched_state *sched, diff --git a/src/host/trxcon/src/sched_trx.c b/src/host/trxcon/src/sched_trx.c index 49dadd2..c337661 100644 --- a/src/host/trxcon/src/sched_trx.c +++ b/src/host/trxcon/src/sched_trx.c @@ -425,6 +425,28 @@ return NULL; } +struct l1sched_lchan_state *l1sched_find_lchan_by_chan_nr(struct l1sched_state *sched, + uint8_t chan_nr, uint8_t link_id) +{ + const struct l1sched_ts *ts = sched->ts[chan_nr & 0x07]; + const struct l1sched_lchan_desc *lchan_desc; + struct l1sched_lchan_state *lchan; + + if (ts == NULL) + return NULL; + + llist_for_each_entry(lchan, &ts->lchans, list) { + lchan_desc = &l1sched_lchan_desc[lchan->type]; + if (lchan_desc->chan_nr != (chan_nr & 0xf8)) + continue; + if (lchan_desc->link_id != link_id) + continue; + return lchan; + } + + return NULL; +} + int l1sched_set_lchans(struct l1sched_ts *ts, uint8_t chan_nr, int active, uint8_t tch_mode, uint8_t tsc) { -- To view, visit https://gerrit.osmocom.org/c/osmocom-bb/+/32303 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: I9917a932c9a4aeb4b3ef7053bd58066b3aa41edb Gerrit-Change-Number: 32303 Gerrit-PatchSet: 1 Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-MessageType: newchange
1 0
0 0
[XL] Change in osmocom-bb[master]: trxcon/l1sched: rework the primitive API
by fixeria 14 Apr '23

14 Apr '23
fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmocom-bb/+/32304 ) Change subject: trxcon/l1sched: rework the primitive API ...................................................................... trxcon/l1sched: rework the primitive API Change-Id: I73576bd0ea10a5663ba6254283812c275cc3fa46 Related: OS#5500 --- M src/host/trxcon/include/osmocom/bb/l1sched/Makefile.am M src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h A src/host/trxcon/include/osmocom/bb/l1sched/prim.h M src/host/trxcon/src/sched_lchan_pdtch.c M src/host/trxcon/src/sched_lchan_rach.c M src/host/trxcon/src/sched_lchan_sch.c M src/host/trxcon/src/sched_lchan_tchf.c M src/host/trxcon/src/sched_lchan_tchh.c M src/host/trxcon/src/sched_lchan_xcch.c M src/host/trxcon/src/sched_prim.c M src/host/trxcon/src/sched_trx.c M src/host/trxcon/src/trxcon_fsm.c M src/host/trxcon/src/trxcon_shim.c 13 files changed, 698 insertions(+), 700 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/04/32304/1 diff --git a/src/host/trxcon/include/osmocom/bb/l1sched/Makefile.am b/src/host/trxcon/include/osmocom/bb/l1sched/Makefile.am index 76f54a7..39c32ba 100644 --- a/src/host/trxcon/include/osmocom/bb/l1sched/Makefile.am +++ b/src/host/trxcon/include/osmocom/bb/l1sched/Makefile.am @@ -1,4 +1,5 @@ noinst_HEADERS = \ l1sched.h \ logging.h \ + prim.h \ $(NULL) diff --git a/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h b/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h index 4728f41..c6360b8 100644 --- a/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h +++ b/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h @@ -14,6 +14,8 @@ #include <osmocom/core/linuxlist.h> #include <osmocom/core/timer.h> +#include <osmocom/bb/l1sched/prim.h> + #define GPRS_L2_MAX_LEN 54 #define EDGE_L2_MAX_LEN 155 @@ -49,12 +51,6 @@ L1SCHED_BURST_8PSK, }; -enum l1sched_ts_prim_type { - L1SCHED_PRIM_DATA, - L1SCHED_PRIM_RACH8, - L1SCHED_PRIM_RACH11, -}; - /** * These types define the different channels on a multiframe. * Each channel has queues and can be activated individually. @@ -103,29 +99,6 @@ _L1SCHED_CHAN_MAX }; -enum l1sched_data_type { - L1SCHED_DT_PACKET_DATA, - L1SCHED_DT_SIGNALING, - L1SCHED_DT_TRAFFIC, - L1SCHED_DT_OTHER, /* SCH and RACH */ -}; - -enum l1sched_config_type { - /*! Channel combination for a timeslot */ - L1SCHED_CFG_PCHAN_COMB, -}; - -/* Represents a (re)configuration request */ -struct l1sched_config_req { - enum l1sched_config_type type; - union { - struct { - uint8_t tn; - enum gsm_phys_chan_config pchan; - } pchan_comb; - }; -}; - /* Represents a burst to be transmitted */ struct l1sched_burst_req { uint32_t fn; @@ -259,8 +232,10 @@ /*! Burst buffer for TX */ ubit_t *tx_bursts; - /*! A primitive being sent */ - struct l1sched_ts_prim *prim; + /*! Queue of Tx primitives */ + struct llist_head tx_prims; + /*! Tx primitive being sent */ + struct msgb *prim; /*! Mode for TCH channels (see GSM48_CMODE_*) */ uint8_t tch_mode; @@ -340,38 +315,10 @@ const struct l1sched_tdma_multiframe *mf_layout; /*! Channel states for logical channels */ struct llist_head lchans; - /*! Queue primitives for TX */ - struct llist_head tx_prims; /*! Backpointer to the scheduler */ struct l1sched_state *sched; }; -/* Represents one TX primitive in the queue of l1sched_ts */ -struct l1sched_ts_prim { - /*! Link to queue of TS */ - struct llist_head list; - /*! Type of primitive */ - enum l1sched_ts_prim_type type; - /*! Logical channel type */ - enum l1sched_lchan_type chan; - /*! TDMA Fn for L1SCHED_{PDTCH,PTCCH} */ - uint32_t fn; - /*! Payload length */ - size_t payload_len; - /*! Payload */ - uint8_t payload[0]; -}; - -/*! Represents a RACH (8-bit or 11-bit) primitive */ -struct l1sched_ts_prim_rach { - /*! RA value */ - uint16_t ra; - /*! Training Sequence (only for 11-bit RA) */ - uint8_t synch_seq; - /*! Transmission offset (how many frames to skip) */ - uint8_t offset; -}; - /*! Scheduler configuration */ struct l1sched_cfg { /*! Logging context (used as prefix for messages) */ @@ -426,8 +373,6 @@ /* Logical channel management functions */ enum gsm_phys_chan_config l1sched_chan_nr2pchan_config(uint8_t chan_nr); -enum l1sched_lchan_type l1sched_chan_nr2lchan_type(uint8_t chan_nr, - uint8_t link_id); void l1sched_deactivate_all_lchans(struct l1sched_ts *ts); int l1sched_set_lchans(struct l1sched_ts *ts, uint8_t chan_nr, @@ -441,12 +386,6 @@ struct l1sched_lchan_state *l1sched_find_lchan_by_chan_nr(struct l1sched_state *sched, uint8_t chan_nr, uint8_t link_id); -/* Primitive management functions */ -struct l1sched_ts_prim *l1sched_prim_push(struct l1sched_state *sched, - enum l1sched_ts_prim_type type, - uint8_t chan_nr, uint8_t link_id, - const uint8_t *pl, size_t pl_len); - #define L1SCHED_TCH_MODE_IS_SPEECH(mode) \ (mode == GSM48_CMODE_SPEECH_V1 \ || mode == GSM48_CMODE_SPEECH_EFR \ @@ -464,31 +403,12 @@ #define L1SCHED_CHAN_IS_SACCH(chan) \ (l1sched_lchan_desc[chan].link_id & L1SCHED_CH_LID_SACCH) -#define L1SCHED_PRIM_IS_RACH11(prim) \ - (prim->type == L1SCHED_PRIM_RACH11) - -#define L1SCHED_PRIM_IS_RACH8(prim) \ - (prim->type == L1SCHED_PRIM_RACH8) - -#define L1SCHED_PRIM_IS_RACH(prim) \ - (L1SCHED_PRIM_IS_RACH8(prim) || L1SCHED_PRIM_IS_RACH11(prim)) - -#define L1SCHED_PRIM_IS_TCH(prim) \ - (L1SCHED_CHAN_IS_TCH(prim->chan) && prim->payload_len != GSM_MACBLOCK_LEN) - -#define L1SCHED_PRIM_IS_FACCH(prim) \ - (L1SCHED_CHAN_IS_TCH(prim->chan) && prim->payload_len == GSM_MACBLOCK_LEN) - -struct l1sched_ts_prim *l1sched_prim_dequeue(struct llist_head *queue, - uint32_t fn, struct l1sched_lchan_state *lchan); -int l1sched_prim_dummy(struct l1sched_lchan_state *lchan); -void l1sched_lchan_prim_drop(struct l1sched_lchan_state *lchan); -void l1sched_prim_flush_queue(struct llist_head *list); - int l1sched_handle_rx_burst(struct l1sched_state *sched, struct l1sched_burst_ind *bi); int l1sched_handle_rx_probe(struct l1sched_state *sched, struct l1sched_probe *probe); +int l1sched_handle_burst_req(struct l1sched_state *sched, + const struct l1sched_burst_req *br); /* Shared declarations for lchan handlers */ extern const uint8_t l1sched_nb_training_bits[8][26]; @@ -521,17 +441,3 @@ void l1sched_pull_burst(struct l1sched_state *sched, struct l1sched_burst_req *br); void l1sched_pull_send_frame(struct l1sched_state *sched); - -/* External L1 API, must be implemented by the API user */ -int l1sched_handle_config_req(struct l1sched_state *sched, - const struct l1sched_config_req *cr); -int l1sched_handle_burst_req(struct l1sched_state *sched, - const struct l1sched_burst_req *br); - -/* External L2 API, must be implemented by the API user */ -int l1sched_handle_data_ind(struct l1sched_lchan_state *lchan, - const uint8_t *data, size_t data_len, - int n_errors, int n_bits_total, - enum l1sched_data_type dt); -int l1sched_handle_data_cnf(struct l1sched_lchan_state *lchan, - uint32_t fn, enum l1sched_data_type dt); diff --git a/src/host/trxcon/include/osmocom/bb/l1sched/prim.h b/src/host/trxcon/include/osmocom/bb/l1sched/prim.h new file mode 100644 index 0000000..eb96b3b --- /dev/null +++ b/src/host/trxcon/include/osmocom/bb/l1sched/prim.h @@ -0,0 +1,126 @@ +#pragma once + +#include <stdint.h> +#include <stdbool.h> + +#include <osmocom/core/msgb.h> +#include <osmocom/core/prim.h> +#include <osmocom/core/utils.h> + +#define l1sched_prim_from_msgb(msg) \ + ((struct l1sched_prim *)(msg)->l1h) + +#define l1sched_prim_data_from_msgb(msg) \ + ((uint8_t *)msgb_l2(msg)) + +#define l1sched_prim_type_from_msgb(msg) \ + l1sched_prim_from_msgb(msg)->oph.primitive + +#define L1SCHED_PRIM_STR_FMT "%s.%s" +#define L1SCHED_PRIM_STR_ARGS(prim) \ + l1sched_prim_type_name((prim)->oph.primitive), \ + osmo_prim_operation_name((prim)->oph.operation) + +enum l1sched_prim_type { + L1SCHED_PRIM_T_DATA, /* Req | Ind | Cnf */ + L1SCHED_PRIM_T_RACH, /* Req | Cnf */ + L1SCHED_PRIM_T_SCH, /* Ind */ + L1SCHED_PRIM_T_PCHAN_COMB, /* Ind */ +}; + +extern const struct value_string l1sched_prim_type_names[]; +static inline const char *l1sched_prim_type_name(enum l1sched_prim_type val) +{ + return get_value_string(l1sched_prim_type_names, val); +} + +/*! Common header for L1SCHED_PRIM_T_{DATA,RACH} */ +struct l1sched_prim_chdr { + /*! TDMA Frame Number */ + uint32_t frame_nr; + /*! RSL Channel Number */ + uint8_t chan_nr; + /*! RSL Link Identifier */ + uint8_t link_id; + /*! Traffic or signalling */ + bool traffic; +}; + +/*! Payload of L1SCHED_PRIM_T_DATA | Ind */ +struct l1sched_prim_data_ind { + /*! Common sub-header */ + struct l1sched_prim_chdr chdr; + int16_t toa256; + int8_t rssi; + int n_errors; + int n_bits_total; +}; + +/*! Payload of L1SCHED_PRIM_T_RACH | {Req,Cnf} */ +struct l1sched_prim_rach { + /*! Common sub-header */ + struct l1sched_prim_chdr chdr; + /*! Training Sequence (only for 11-bit RA) */ + uint8_t synch_seq; + /*! Transmission offset (how many frames to skip) */ + uint8_t offset; + /*! RA value is 11 bit */ + bool is_11bit; + /*! RA value */ + uint16_t ra; +}; + +struct l1sched_prim { + /*! Primitive header */ + struct osmo_prim_hdr oph; + /*! Type specific header */ + union { + /*! L1SCHED_PRIM_T_DATA | Req */ + struct l1sched_prim_chdr data_req; + /*! L1SCHED_PRIM_T_DATA | Cnf */ + struct l1sched_prim_chdr data_cnf; + /*! L1SCHED_PRIM_T_DATA | Ind */ + struct l1sched_prim_data_ind data_ind; + + /*! L1SCHED_PRIM_T_RACH | Req */ + struct l1sched_prim_rach rach_req; + /*! L1SCHED_PRIM_T_RACH | Cnf */ + struct l1sched_prim_rach rach_cnf; + + /*! L1SCHED_PRIM_T_SCH | Ind */ + struct { + /*! TDMA frame number */ + uint32_t frame_nr; + /*! BSIC */ + uint8_t bsic; + } sch_ind; + + /*! L1SCHED_PRIM_T_PCHAN_COMB | Ind */ + struct { + /*! Timeslot number */ + uint8_t tn; + /*! Channel combination for a timeslot */ + enum gsm_phys_chan_config pchan; + } pchan_comb_ind; + }; +}; + + +struct l1sched_state; +struct l1sched_lchan_state; + +struct msgb *l1sched_prim_alloc(enum l1sched_prim_type type, + enum osmo_prim_operation op, + size_t extra_size); + +struct msgb *l1sched_lchan_prim_dequeue(struct l1sched_lchan_state *lchan, uint32_t fn); +void l1sched_lchan_prim_assign_dummy(struct l1sched_lchan_state *lchan); +void l1sched_lchan_prim_drop(struct l1sched_lchan_state *lchan); + +int l1sched_lchan_emit_data_ind(struct l1sched_lchan_state *lchan, + const uint8_t *data, size_t data_len, + int n_errors, int n_bits_total, bool traffic); +int l1sched_lchan_emit_data_cnf(struct l1sched_lchan_state *lchan, uint32_t fn); + +int l1sched_prim_from_user(struct l1sched_state *sched, struct msgb *msg); +int l1sched_prim_to_user(struct l1sched_state *sched, struct msgb *msg); diff --git a/src/host/trxcon/src/sched_lchan_pdtch.c b/src/host/trxcon/src/sched_lchan_pdtch.c index 722800f..6702d9d 100644 --- a/src/host/trxcon/src/sched_lchan_pdtch.c +++ b/src/host/trxcon/src/sched_lchan_pdtch.c @@ -96,7 +96,7 @@ l2_len = rc > 0 ? rc : 0; /* Send a L2 frame to the higher layers */ - l1sched_handle_data_ind(lchan, l2, l2_len, n_errors, n_bits_total, L1SCHED_DT_PACKET_DATA); + l1sched_lchan_emit_data_ind(lchan, l2, l2_len, n_errors, n_bits_total, true); return 0; } @@ -123,12 +123,10 @@ } /* Encode payload */ - rc = gsm0503_pdtch_encode(buffer, lchan->prim->payload, - lchan->prim->payload_len); + rc = gsm0503_pdtch_encode(buffer, msgb_l2(lchan->prim), msgb_l2len(lchan->prim)); if (rc < 0) { - LOGP_LCHAND(lchan, LOGL_ERROR, "Failed to encode L2 payload (len=%zu): %s\n", - lchan->prim->payload_len, osmo_hexdump(lchan->prim->payload, - lchan->prim->payload_len)); + LOGP_LCHAND(lchan, LOGL_ERROR, "Failed to encode L2 payload (len=%u): %s\n", + msgb_l2len(lchan->prim), msgb_hexdump_l2(lchan->prim)); l1sched_lchan_prim_drop(lchan); return -EINVAL; } @@ -155,11 +153,8 @@ /* If we have sent the last (4/4) burst */ if ((*mask & 0x0f) == 0x0f) { - /* Confirm data / traffic sending */ - l1sched_handle_data_cnf(lchan, br->fn, L1SCHED_DT_PACKET_DATA); - - /* Forget processed primitive */ - l1sched_lchan_prim_drop(lchan); + /* Confirm data / traffic sending (pass ownership of the prim) */ + l1sched_lchan_emit_data_cnf(lchan, br->fn); /* Reset mask */ *mask = 0x00; diff --git a/src/host/trxcon/src/sched_lchan_rach.c b/src/host/trxcon/src/sched_lchan_rach.c index 7448d83..109d100 100644 --- a/src/host/trxcon/src/sched_lchan_rach.c +++ b/src/host/trxcon/src/sched_lchan_rach.c @@ -73,56 +73,37 @@ struct l1sched_burst_req *br) { const uint8_t bsic = lchan->ts->sched->bsic; - struct l1sched_ts_prim_rach *rach; + struct l1sched_prim *prim; uint8_t *burst_ptr = br->burst; uint8_t payload[36]; int i, rc; - rach = (struct l1sched_ts_prim_rach *)lchan->prim->payload; + prim = l1sched_prim_from_msgb(lchan->prim); /* Delay sending according to offset value */ - if (rach->offset-- > 0) + if (prim->rach_req.offset-- > 0) return 0; - if (L1SCHED_PRIM_IS_RACH11(lchan->prim)) { - /* Check requested synch. sequence */ - if (rach->synch_seq >= RACH_SYNCH_SEQ_NUM) { - LOGP_LCHAND(lchan, LOGL_ERROR, - "Unknown RACH synch. sequence=0x%02x\n", - rach->synch_seq); - l1sched_lchan_prim_drop(lchan); - return -ENOTSUP; - } - - /* Encode 11-bit payload */ - rc = gsm0503_rach_ext_encode(payload, rach->ra, bsic, true); - if (rc) { - LOGP_LCHAND(lchan, LOGL_ERROR, - "Could not encode 11-bit RACH burst (ra=%u bsic=%u)\n", - rach->ra, bsic); - l1sched_lchan_prim_drop(lchan); - return rc; - } - } else if (L1SCHED_PRIM_IS_RACH8(lchan->prim)) { - rach->synch_seq = RACH_SYNCH_SEQ_TS0; - - /* Encode 8-bit payload */ - rc = gsm0503_rach_ext_encode(payload, rach->ra, bsic, false); - if (rc) { - LOGP_LCHAND(lchan, LOGL_ERROR, - "Could not encode RACH burst (ra=%u bsic=%u)\n", - rach->ra, bsic); - l1sched_lchan_prim_drop(lchan); - return rc; - } - } else { + /* Check requested synch. sequence */ + if (prim->rach_req.synch_seq >= RACH_SYNCH_SEQ_NUM) { LOGP_LCHAND(lchan, LOGL_ERROR, - "Primitive has unexpected type=0x%02x\n", - lchan->prim->type); + "Unknown RACH synch. sequence=0x%02x\n", + prim->rach_req.synch_seq); l1sched_lchan_prim_drop(lchan); - return -EINVAL; + return -ENOTSUP; } + /* Encode the payload */ + rc = gsm0503_rach_ext_encode(payload, prim->rach_req.ra, + bsic, prim->rach_req.is_11bit); + if (rc) { + LOGP_LCHAND(lchan, LOGL_ERROR, + "Could not encode %s-bit RACH burst (ra=%u bsic=%u)\n", + prim->rach_req.is_11bit ? "11" : "8", + prim->rach_req.ra, bsic); + l1sched_lchan_prim_drop(lchan); + return rc; + } /* BN0-7: extended tail bits */ memcpy(burst_ptr, rach_ext_tail_bits, RACH_EXT_TAIL_BITS_LEN); @@ -130,7 +111,7 @@ /* BN8-48: chosen synch. (training) sequence */ for (i = 0; i < RACH_SYNCH_SEQ_LEN; i++) - *(burst_ptr++) = rach_synch_seq_bits[rach->synch_seq][i] == '1'; + *(burst_ptr++) = rach_synch_seq_bits[prim->rach_req.synch_seq][i] == '1'; /* BN49-84: encrypted bits (the payload) */ memcpy(burst_ptr, payload, RACH_PAYLOAD_LEN); @@ -141,14 +122,11 @@ br->burst_len = GSM_NBITS_NB_GMSK_BURST; LOGP_LCHAND(lchan, LOGL_NOTICE, "Scheduled %s-bit RACH (%s) at fn=%u\n", - L1SCHED_PRIM_IS_RACH11(lchan->prim) ? "11" : "8", - get_value_string(rach_synch_seq_names, rach->synch_seq), br->fn); + prim->rach_req.is_11bit ? "11" : "8", + get_value_string(rach_synch_seq_names, prim->rach_req.synch_seq), br->fn); - /* Confirm RACH request */ - l1sched_handle_data_cnf(lchan, br->fn, L1SCHED_DT_OTHER); - - /* Forget processed primitive */ - l1sched_lchan_prim_drop(lchan); + /* Confirm RACH request (pass ownership of the prim) */ + l1sched_lchan_emit_data_cnf(lchan, br->fn); return 0; } diff --git a/src/host/trxcon/src/sched_lchan_sch.c b/src/host/trxcon/src/sched_lchan_sch.c index de665cb..f433de6 100644 --- a/src/host/trxcon/src/sched_lchan_sch.c +++ b/src/host/trxcon/src/sched_lchan_sch.c @@ -61,6 +61,21 @@ time->fn = gsm_gsmtime2fn(time); } +static int handle_sch_ind(struct l1sched_state *sched, uint32_t fn, uint8_t bsic) +{ + struct l1sched_prim *prim; + struct msgb *msg; + + msg = l1sched_prim_alloc(L1SCHED_PRIM_T_SCH, PRIM_OP_INDICATION, 0); + OSMO_ASSERT(msg != NULL); + + prim = l1sched_prim_from_msgb(msg); + prim->sch_ind.frame_nr = fn; + prim->sch_ind.bsic = bsic; + + return l1sched_prim_to_user(sched, msg); +} + int rx_sch_fn(struct l1sched_lchan_state *lchan, const struct l1sched_burst_ind *bi) { @@ -100,8 +115,5 @@ /* Update BSIC value in the scheduler state */ lchan->ts->sched->bsic = bsic; - l1sched_handle_data_ind(lchan, (const uint8_t *)&time, sizeof(time), - 0, 39 * 2, L1SCHED_DT_OTHER); - - return 0; + return handle_sch_ind(lchan->ts->sched, time.fn, bsic); } diff --git a/src/host/trxcon/src/sched_lchan_tchf.c b/src/host/trxcon/src/sched_lchan_tchf.c index 8cb996b..326713d 100644 --- a/src/host/trxcon/src/sched_lchan_tchf.c +++ b/src/host/trxcon/src/sched_lchan_tchf.c @@ -171,9 +171,8 @@ goto bfi; } else if (rc == GSM_MACBLOCK_LEN) { /* FACCH received, forward it to the higher layers */ - l1sched_handle_data_ind(lchan, l2 + amr, GSM_MACBLOCK_LEN, - n_errors, n_bits_total, - L1SCHED_DT_SIGNALING); + l1sched_lchan_emit_data_ind(lchan, l2 + amr, GSM_MACBLOCK_LEN, + n_errors, n_bits_total, false); /* Send BFI substituting a stolen TCH frame */ n_errors = -1; /* ensure fake measurements */ @@ -184,7 +183,8 @@ } /* Send a traffic frame to the higher layers */ - return l1sched_handle_data_ind(lchan, l2, l2_len, n_errors, n_bits_total, L1SCHED_DT_TRAFFIC); + return l1sched_lchan_emit_data_ind(lchan, l2, l2_len, + n_errors, n_bits_total, true); bfi: /* Didn't try to decode, fake measurements */ @@ -201,18 +201,16 @@ /* BFI is not applicable in signalling mode */ if (lchan->tch_mode == GSM48_CMODE_SIGN) { - return l1sched_handle_data_ind(lchan, NULL, 0, - n_errors, n_bits_total, - L1SCHED_DT_TRAFFIC); + return l1sched_lchan_emit_data_ind(lchan, NULL, 0, + n_errors, n_bits_total, false); } /* Bad frame indication */ l2_len = l1sched_bad_frame_ind(l2, lchan); /* Send a BFI frame to the higher layers */ - return l1sched_handle_data_ind(lchan, l2, l2_len, - n_errors, n_bits_total, - L1SCHED_DT_TRAFFIC); + return l1sched_lchan_emit_data_ind(lchan, l2, l2_len, + n_errors, n_bits_total, true); } int tx_tchf_fn(struct l1sched_lchan_state *lchan, @@ -240,9 +238,9 @@ memcpy(buffer, buffer + 464, 464); /* populate the buffer with bursts */ - if (L1SCHED_PRIM_IS_FACCH(lchan->prim)) { + if (msgb_l2len(lchan->prim) == GSM_MACBLOCK_LEN) { /* Encode payload */ - rc = gsm0503_tch_fr_encode(buffer, lchan->prim->payload, GSM_MACBLOCK_LEN, 1); + rc = gsm0503_tch_fr_encode(buffer, msgb_l2(lchan->prim), GSM_MACBLOCK_LEN, 1); } else if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR) { int len; uint8_t cmr_codec; @@ -256,12 +254,11 @@ */ amr_fn_is_cmr = !sched_tchf_ul_amr_cmi_map[br->fn % 26]; - len = osmo_amr_rtp_dec(lchan->prim->payload, lchan->prim->payload_len, - &cmr_codec, &cmi, &ft_codec, - &bfi, &sti); + len = osmo_amr_rtp_dec(msgb_l2(lchan->prim), msgb_l2len(lchan->prim), + &cmr_codec, &cmi, &ft_codec, &bfi, &sti); if (len < 0) { - LOGP_LCHAND(lchan, LOGL_ERROR, "Cannot send invalid AMR payload (%zu): %s\n", - lchan->prim->payload_len, osmo_hexdump(lchan->prim->payload, lchan->prim->payload_len)); + LOGP_LCHAND(lchan, LOGL_ERROR, "Cannot send invalid AMR payload (%u): %s\n", + msgb_l2len(lchan->prim), msgb_hexdump_l2(lchan->prim)); goto free_bad_msg; } ft = -1; @@ -290,11 +287,14 @@ } else { lchan->amr.ul_cmr = cmr; } - rc = gsm0503_tch_afs_encode(buffer, lchan->prim->payload + 2, - lchan->prim->payload_len - 2, amr_fn_is_cmr, - lchan->amr.codec, lchan->amr.codecs, - lchan->amr.ul_ft, - lchan->amr.ul_cmr); + rc = gsm0503_tch_afs_encode(buffer, + msgb_l2(lchan->prim) + 2, + msgb_l2len(lchan->prim) - 2, + amr_fn_is_cmr, + lchan->amr.codec, + lchan->amr.codecs, + lchan->amr.ul_ft, + lchan->amr.ul_cmr); } else { /* Determine and check the payload length */ switch (lchan->tch_mode) { @@ -312,20 +312,19 @@ l1sched_lchan_prim_drop(lchan); return -EINVAL; } - if (lchan->prim->payload_len != l2_len) { - LOGP_LCHAND(lchan, LOGL_ERROR, "Primitive has odd length %zu " + if (msgb_l2len(lchan->prim) != l2_len) { + LOGP_LCHAND(lchan, LOGL_ERROR, "Primitive has odd length %u " "(expected %zu for TCH or %u for FACCH), so dropping...\n", - lchan->prim->payload_len, l2_len, GSM_MACBLOCK_LEN); + msgb_l2len(lchan->prim), l2_len, GSM_MACBLOCK_LEN); l1sched_lchan_prim_drop(lchan); return -EINVAL; } - rc = gsm0503_tch_fr_encode(buffer, lchan->prim->payload, l2_len, 1); + rc = gsm0503_tch_fr_encode(buffer, msgb_l2(lchan->prim), l2_len, 1); } if (rc) { - LOGP_LCHAND(lchan, LOGL_ERROR, "Failed to encode L2 payload (len=%zu): %s\n", - lchan->prim->payload_len, osmo_hexdump(lchan->prim->payload, - lchan->prim->payload_len)); + LOGP_LCHAND(lchan, LOGL_ERROR, "Failed to encode L2 payload (len=%u): %s\n", + msgb_l2len(lchan->prim), msgb_hexdump_l2(lchan->prim)); free_bad_msg: l1sched_lchan_prim_drop(lchan); return -EINVAL; @@ -353,13 +352,8 @@ /* If we have sent the last (4/4) burst */ if (*mask == 0x0f) { - /* Confirm data / traffic sending */ - enum l1sched_data_type dt = L1SCHED_PRIM_IS_TCH(lchan->prim) ? - L1SCHED_DT_TRAFFIC : L1SCHED_DT_SIGNALING; - l1sched_handle_data_cnf(lchan, br->fn, dt); - - /* Forget processed primitive */ - l1sched_lchan_prim_drop(lchan); + /* Confirm data / traffic sending (pass ownership of the prim) */ + l1sched_lchan_emit_data_cnf(lchan, br->fn); /* Reset mask */ *mask = 0x00; diff --git a/src/host/trxcon/src/sched_lchan_tchh.c b/src/host/trxcon/src/sched_lchan_tchh.c index 7302351..34781d3 100644 --- a/src/host/trxcon/src/sched_lchan_tchh.c +++ b/src/host/trxcon/src/sched_lchan_tchh.c @@ -366,9 +366,8 @@ l1sched_lchan_meas_avg(lchan, 6); /* FACCH/H received, forward to the higher layers */ - l1sched_handle_data_ind(lchan, l2 + amr, GSM_MACBLOCK_LEN, - n_errors, n_bits_total, - L1SCHED_DT_SIGNALING); + l1sched_lchan_emit_data_ind(lchan, l2 + amr, GSM_MACBLOCK_LEN, + n_errors, n_bits_total, false); /* Send BFI substituting 1/2 stolen TCH frames */ n_errors = -1; /* ensure fake measurements */ @@ -382,9 +381,8 @@ } /* Send a traffic frame to the higher layers */ - return l1sched_handle_data_ind(lchan, l2, l2_len, - n_errors, n_bits_total, - L1SCHED_DT_TRAFFIC); + return l1sched_lchan_emit_data_ind(lchan, l2, l2_len, + n_errors, n_bits_total, true); bfi_shift: /* Shift buffer */ @@ -409,18 +407,16 @@ /* BFI is not applicable in signalling mode */ if (lchan->tch_mode == GSM48_CMODE_SIGN) { - return l1sched_handle_data_ind(lchan, NULL, 0, - n_errors, n_bits_total, - L1SCHED_DT_SIGNALING); + return l1sched_lchan_emit_data_ind(lchan, NULL, 0, + n_errors, n_bits_total, false); } /* Bad frame indication */ l2_len = l1sched_bad_frame_ind(l2, lchan); /* Send a BFI frame to the higher layers */ - return l1sched_handle_data_ind(lchan, l2, l2_len, - n_errors, n_bits_total, - L1SCHED_DT_TRAFFIC); + return l1sched_lchan_emit_data_ind(lchan, l2, l2_len, + n_errors, n_bits_total, true); } int tx_tchh_fn(struct l1sched_lchan_state *lchan, @@ -463,8 +459,8 @@ } /* populate the buffer with bursts */ - if (L1SCHED_PRIM_IS_FACCH(lchan->prim)) { - rc = gsm0503_tch_hr_encode(buffer, lchan->prim->payload, lchan->prim->payload_len); + if (msgb_l2len(lchan->prim) == GSM_MACBLOCK_LEN) { + rc = gsm0503_tch_hr_encode(buffer, msgb_l2(lchan->prim), GSM_MACBLOCK_LEN); lchan->ul_facch_blocks = 6; } else if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR) { int len; @@ -479,12 +475,11 @@ */ amr_fn_is_cmr = !sched_tchh_ul_amr_cmi_map[br->fn % 26]; - len = osmo_amr_rtp_dec(lchan->prim->payload, lchan->prim->payload_len, - &cmr_codec, &cmi, &ft_codec, - &bfi, &sti); + len = osmo_amr_rtp_dec(msgb_l2(lchan->prim), msgb_l2len(lchan->prim), + &cmr_codec, &cmi, &ft_codec, &bfi, &sti); if (len < 0) { - LOGP_LCHAND(lchan, LOGL_ERROR, "Cannot send invalid AMR payload (%zu): %s\n", - lchan->prim->payload_len, osmo_hexdump(lchan->prim->payload, lchan->prim->payload_len)); + LOGP_LCHAND(lchan, LOGL_ERROR, "Cannot send invalid AMR payload (%u): %s\n", + msgb_l2len(lchan->prim), msgb_hexdump_l2(lchan->prim)); goto free_bad_msg; } ft = -1; @@ -513,11 +508,14 @@ } else { lchan->amr.ul_cmr = cmr; } - rc = gsm0503_tch_ahs_encode(buffer, lchan->prim->payload + 2, - lchan->prim->payload_len - 2, amr_fn_is_cmr, - lchan->amr.codec, lchan->amr.codecs, - lchan->amr.ul_ft, - lchan->amr.ul_cmr); + rc = gsm0503_tch_ahs_encode(buffer, + msgb_l2(lchan->prim) + 2, + msgb_l2len(lchan->prim) - 2, + amr_fn_is_cmr, + lchan->amr.codec, + lchan->amr.codecs, + lchan->amr.ul_ft, + lchan->amr.ul_cmr); } else { /* Determine and check the payload length */ switch (lchan->tch_mode) { @@ -532,20 +530,19 @@ l1sched_lchan_prim_drop(lchan); return -EINVAL; } - if (lchan->prim->payload_len != l2_len) { - LOGP_LCHAND(lchan, LOGL_ERROR, "Primitive has odd length %zu " + if (msgb_l2len(lchan->prim) != l2_len) { + LOGP_LCHAND(lchan, LOGL_ERROR, "Primitive has odd length %u " "(expected %zu for TCH or %u for FACCH), so dropping...\n", - lchan->prim->payload_len, l2_len, GSM_MACBLOCK_LEN); + msgb_l2len(lchan->prim), l2_len, GSM_MACBLOCK_LEN); l1sched_lchan_prim_drop(lchan); return -EINVAL; } - rc = gsm0503_tch_hr_encode(buffer, lchan->prim->payload, l2_len); + rc = gsm0503_tch_hr_encode(buffer, msgb_l2(lchan->prim), l2_len); } if (rc) { - LOGP_LCHAND(lchan, LOGL_ERROR, "Failed to encode L2 payload (len=%zu): %s\n", - lchan->prim->payload_len, osmo_hexdump(lchan->prim->payload, - lchan->prim->payload_len)); + LOGP_LCHAND(lchan, LOGL_ERROR, "Failed to encode L2 payload (len=%u): %s\n", + msgb_l2len(lchan->prim), msgb_hexdump_l2(lchan->prim)); free_bad_msg: l1sched_lchan_prim_drop(lchan); return -EINVAL; @@ -576,18 +573,11 @@ lchan->ul_facch_blocks--; if ((*mask & 0x0f) == 0x0f) { - /** - * If no more FACCH/H blocks pending, - * confirm data / traffic sending - */ - if (!lchan->ul_facch_blocks) { - enum l1sched_data_type dt = L1SCHED_PRIM_IS_TCH(lchan->prim) ? - L1SCHED_DT_TRAFFIC : L1SCHED_DT_SIGNALING; - l1sched_handle_data_cnf(lchan, br->fn, dt); - } - - /* Forget processed primitive */ - l1sched_lchan_prim_drop(lchan); + /* Confirm data / traffic sending (pass ownership of the prim) */ + if (!lchan->ul_facch_blocks) + l1sched_lchan_emit_data_cnf(lchan, br->fn); + else /* do not confirm dropped prims */ + l1sched_lchan_prim_drop(lchan); } return 0; diff --git a/src/host/trxcon/src/sched_lchan_xcch.c b/src/host/trxcon/src/sched_lchan_xcch.c index 936a899..0dca098 100644 --- a/src/host/trxcon/src/sched_lchan_xcch.c +++ b/src/host/trxcon/src/sched_lchan_xcch.c @@ -94,9 +94,8 @@ } /* Send a L2 frame to the higher layers */ - return l1sched_handle_data_ind(lchan, l2, rc ? 0 : GSM_MACBLOCK_LEN, - n_errors, n_bits_total, - L1SCHED_DT_SIGNALING); + return l1sched_lchan_emit_data_ind(lchan, l2, rc ? 0 : GSM_MACBLOCK_LEN, + n_errors, n_bits_total, false); } int tx_data_fn(struct l1sched_lchan_state *lchan, @@ -120,20 +119,19 @@ } /* Check the prim payload length */ - if (lchan->prim->payload_len != GSM_MACBLOCK_LEN) { + if (msgb_l2len(lchan->prim) != GSM_MACBLOCK_LEN) { LOGP_LCHAND(lchan, LOGL_ERROR, - "Primitive has odd length %zu (expected %u), so dropping...\n", - lchan->prim->payload_len, GSM_MACBLOCK_LEN); + "Primitive has odd length %u (expected %u), so dropping...\n", + msgb_l2len(lchan->prim), GSM_MACBLOCK_LEN); l1sched_lchan_prim_drop(lchan); return -EINVAL; } /* Encode payload */ - rc = gsm0503_xcch_encode(buffer, lchan->prim->payload); + rc = gsm0503_xcch_encode(buffer, msgb_l2(lchan->prim)); if (rc) { - LOGP_LCHAND(lchan, LOGL_ERROR, "Failed to encode L2 payload (len=%zu): %s\n", - lchan->prim->payload_len, osmo_hexdump(lchan->prim->payload, - lchan->prim->payload_len)); + LOGP_LCHAND(lchan, LOGL_ERROR, "Failed to encode L2 payload (len=%u): %s\n", + msgb_l2len(lchan->prim), msgb_hexdump_l2(lchan->prim)); l1sched_lchan_prim_drop(lchan); return -EINVAL; } @@ -160,11 +158,8 @@ /* If we have sent the last (4/4) burst */ if ((*mask & 0x0f) == 0x0f) { - /* Confirm data sending */ - l1sched_handle_data_cnf(lchan, br->fn, L1SCHED_DT_SIGNALING); - - /* Forget processed primitive */ - l1sched_lchan_prim_drop(lchan); + /* Confirm data sending (pass ownership of the prim) */ + l1sched_lchan_emit_data_cnf(lchan, br->fn); /* Reset mask */ *mask = 0x00; diff --git a/src/host/trxcon/src/sched_prim.c b/src/host/trxcon/src/sched_prim.c index b7ebdeb..8602097 100644 --- a/src/host/trxcon/src/sched_prim.c +++ b/src/host/trxcon/src/sched_prim.c @@ -3,7 +3,7 @@ * TDMA scheduler: primitive management * * (C) 2017-2022 by Vadim Yanitskiy <axilirator(a)gmail.com> - * Contributions by sysmocom - s.f.m.c. GmbH + * (C) 2023 by sysmocom - s.f.m.c. GmbH <info(a)sysmocom.de> * * All Rights Reserved * @@ -25,6 +25,8 @@ #include <talloc.h> #include <osmocom/core/msgb.h> +#include <osmocom/core/prim.h> +#include <osmocom/core/utils.h> #include <osmocom/core/logging.h> #include <osmocom/core/linuxlist.h> @@ -33,86 +35,37 @@ #include <osmocom/bb/l1sched/l1sched.h> #include <osmocom/bb/l1sched/logging.h> -/** - * Initializes a new primitive by allocating memory - * and filling some meta-information (e.g. lchan type). - * - * @param ctx parent talloc context - * @param pl_len prim payload length - * @param type prim payload type - * @param chan_nr RSL channel description (used to set a proper chan) - * @param link_id RSL link description (used to set a proper chan) - * @return allocated primitive or NULL - */ -static struct l1sched_ts_prim *prim_alloc(void *ctx, size_t pl_len, - enum l1sched_ts_prim_type type, - uint8_t chan_nr, uint8_t link_id) +#define L1SCHED_PRIM_HEADROOM 128 + +osmo_static_assert(sizeof(struct l1sched_prim) <= L1SCHED_PRIM_HEADROOM, l1sched_prim_size); + +const struct value_string l1sched_prim_type_names[] = { + { L1SCHED_PRIM_T_DATA, "DATA" }, + { L1SCHED_PRIM_T_RACH, "RACH" }, + { L1SCHED_PRIM_T_SCH, "SCH" }, + { L1SCHED_PRIM_T_PCHAN_COMB, "PCHAN_COMB" }, + { 0, NULL }, +}; + +struct msgb *l1sched_prim_alloc(enum l1sched_prim_type type, + enum osmo_prim_operation op, + size_t extra_size) { - enum l1sched_lchan_type lchan_type; - struct l1sched_ts_prim *prim; + struct l1sched_prim *prim; + struct msgb *msg; - /* Determine lchan type */ - lchan_type = l1sched_chan_nr2lchan_type(chan_nr, link_id); - if (!lchan_type) { - /* TODO: use proper logging context */ - LOGP(DLGLOBAL, LOGL_ERROR, "Couldn't determine lchan type " - "for chan_nr=%02x and link_id=%02x\n", chan_nr, link_id); - return NULL; - } - - /* Allocate a new primitive */ - prim = talloc_zero_size(ctx, sizeof(*prim) + pl_len); - if (prim == NULL) + msg = msgb_alloc_headroom(L1SCHED_PRIM_HEADROOM + extra_size, + L1SCHED_PRIM_HEADROOM, "l1sched_prim"); + if (msg == NULL) return NULL; - /* Init primitive header */ - prim->payload_len = pl_len; - prim->chan = lchan_type; - prim->type = type; + msg->l2h = msg->data; + msg->l1h = msgb_push(msg, sizeof(*prim)); - return prim; -} + prim = l1sched_prim_from_msgb(msg); + osmo_prim_init(&prim->oph, 0, type, op, msg); -/** - * Adds a primitive to the end of transmit queue of a particular - * timeslot, whose index is parsed from chan_nr. - * - * @param sched scheduler instance - * @param chan_nr RSL channel description - * @param link_id RSL link description - * @param pl Payload data - * @param pl_len Payload length - * @return queued primitive or NULL - */ -struct l1sched_ts_prim *l1sched_prim_push(struct l1sched_state *sched, - enum l1sched_ts_prim_type type, - uint8_t chan_nr, uint8_t link_id, - const uint8_t *pl, size_t pl_len) -{ - struct l1sched_ts_prim *prim; - struct l1sched_ts *ts; - uint8_t tn; - - /* Determine TS index */ - tn = chan_nr & 0x7; - - /* Check whether required timeslot is allocated and configured */ - ts = sched->ts[tn]; - if (ts == NULL || ts->mf_layout == NULL) { - LOGP_SCHEDC(sched, LOGL_ERROR, "Timeslot %u isn't configured\n", tn); - return NULL; - } - - prim = prim_alloc(ts, pl_len, type, chan_nr, link_id); - if (prim == NULL) - return NULL; - - memcpy(&prim->payload[0], pl, pl_len); - - /* Add primitive to TS transmit queue */ - llist_add_tail(&prim->list, &ts->tx_prims); - - return prim; + return msg; } /** @@ -121,16 +74,21 @@ * @param lchan lchan to assign a primitive * @return SACCH primitive to be transmitted */ -static struct l1sched_ts_prim *prim_compose_mr(struct l1sched_lchan_state *lchan) +static struct msgb *prim_compose_mr(struct l1sched_lchan_state *lchan) { - struct l1sched_ts_prim *prim; + struct l1sched_prim *prim; + struct msgb *msg; bool cached; /* Allocate a new primitive */ - prim = prim_alloc(lchan, GSM_MACBLOCK_LEN, L1SCHED_PRIM_DATA, - l1sched_lchan_desc[lchan->type].chan_nr, - L1SCHED_CH_LID_SACCH); - OSMO_ASSERT(prim != NULL); + msg = l1sched_prim_alloc(L1SCHED_PRIM_T_DATA, PRIM_OP_REQUEST, GSM_MACBLOCK_LEN); + OSMO_ASSERT(msg != NULL); + + prim = l1sched_prim_from_msgb(msg); + prim->data_req = (struct l1sched_prim_chdr) { + .chan_nr = l1sched_lchan_desc[lchan->type].chan_nr, + .chan_nr = L1SCHED_CH_LID_SACCH, + }; /* Check if the MR cache is populated (verify LAPDm header) */ cached = (lchan->sacch.mr_cache[2] != 0x00 @@ -143,7 +101,9 @@ } /* Compose a new Measurement Report primitive */ - memcpy(&prim->payload[0], &lchan->sacch.mr_cache[0], GSM_MACBLOCK_LEN); + memcpy(msgb_put(msg, GSM_MACBLOCK_LEN), + &lchan->sacch.mr_cache[0], + GSM_MACBLOCK_LEN); /* Inform about the cache usage count */ if (++lchan->sacch.mr_cache_usage > 5) { @@ -155,7 +115,7 @@ LOGP_LCHAND(lchan, LOGL_NOTICE, "Using cached Measurement Report\n"); - return prim; + return msg; } /** @@ -180,140 +140,101 @@ * between two successive measurement result messages * shall not exceed one L2 frame. * - * @param queue transmit queue to take a prim from * @param lchan lchan to assign a primitive * @return SACCH primitive to be transmitted */ -static struct l1sched_ts_prim *prim_dequeue_sacch(struct llist_head *queue, - struct l1sched_lchan_state *lchan) +static struct msgb *prim_dequeue_sacch(struct l1sched_lchan_state *lchan) { - struct l1sched_ts_prim *prim_nmr = NULL; - struct l1sched_ts_prim *prim_mr = NULL; - struct l1sched_ts_prim *prim; + struct msgb *msg_nmr = NULL; + struct msgb *msg_mr = NULL; + struct msgb *msg; bool mr_now; /* Shall we transmit MR now? */ mr_now = !lchan->sacch.mr_tx_last; -#define PRIM_IS_MR(prim) \ - (prim->payload[5] == GSM48_PDISC_RR \ - && prim->payload[6] == GSM48_MT_RR_MEAS_REP) +#define PRIM_MSGB_IS_MR(msg) \ + (l1sched_prim_data_from_msgb(msg)[5] == GSM48_PDISC_RR && \ + l1sched_prim_data_from_msgb(msg)[6] == GSM48_MT_RR_MEAS_REP) /* Iterate over all primitives in the queue */ - llist_for_each_entry(prim, queue, list) { - /* We are looking for particular channel */ - if (prim->chan != lchan->type) - continue; - + llist_for_each_entry(msg, &lchan->tx_prims, list) { /* Look for a Measurement Report */ - if (!prim_mr && PRIM_IS_MR(prim)) - prim_mr = prim; + if (!msg_mr && PRIM_MSGB_IS_MR(msg)) + msg_mr = msg; /* Look for anything else */ - if (!prim_nmr && !PRIM_IS_MR(prim)) - prim_nmr = prim; + if (!msg_nmr && !PRIM_MSGB_IS_MR(msg)) + msg_nmr = msg; /* Should we look further? */ - if (mr_now && prim_mr) + if (mr_now && msg_mr) break; /* MR was found */ - else if (!mr_now && prim_nmr) + else if (!mr_now && msg_nmr) break; /* something else was found */ } LOGP_LCHAND(lchan, LOGL_DEBUG, - "SACCH MR selection: mr_tx_last=%d prim_mr=%p prim_nmr=%p\n", - lchan->sacch.mr_tx_last, prim_mr, prim_nmr); + "SACCH MR selection: mr_tx_last=%d msg_mr=%p msg_nmr=%p\n", + lchan->sacch.mr_tx_last, msg_mr, msg_nmr); /* Prioritize non-MR prim if possible */ - if (mr_now && prim_mr) - prim = prim_mr; - else if (!mr_now && prim_nmr) - prim = prim_nmr; - else if (!mr_now && prim_mr) - prim = prim_mr; + if (mr_now && msg_mr) + msg = msg_mr; + else if (!mr_now && msg_nmr) + msg = msg_nmr; + else if (!mr_now && msg_mr) + msg = msg_mr; else /* Nothing was found */ - prim = NULL; + msg = NULL; /* Have we found what we were looking for? */ - if (prim) /* Dequeue if so */ - llist_del(&prim->list); + if (msg) /* Dequeue if so */ + llist_del(&msg->list); else /* Otherwise compose a new MR */ - prim = prim_compose_mr(lchan); + msg = prim_compose_mr(lchan); /* Update the cached report */ - if (prim == prim_mr) { - memcpy(lchan->sacch.mr_cache, - prim->payload, GSM_MACBLOCK_LEN); + if (msg == msg_mr) { + memcpy(lchan->sacch.mr_cache, msgb_l2(msg), GSM_MACBLOCK_LEN); lchan->sacch.mr_cache_usage = 0; LOGP_LCHAND(lchan, LOGL_DEBUG, "SACCH MR cache has been updated\n"); } /* Update the MR transmission state */ - lchan->sacch.mr_tx_last = PRIM_IS_MR(prim); + lchan->sacch.mr_tx_last = PRIM_MSGB_IS_MR(msg); LOGP_LCHAND(lchan, LOGL_DEBUG, "SACCH decision: %s\n", - PRIM_IS_MR(prim) ? "Measurement Report" : "data frame"); + PRIM_MSGB_IS_MR(msg) ? "Measurement Report" : "data frame"); - return prim; -} - -/* Dequeues a primitive of a given channel type */ -static struct l1sched_ts_prim *prim_dequeue_one(struct llist_head *queue, - enum l1sched_lchan_type lchan_type) -{ - struct l1sched_ts_prim *prim; - - /** - * There is no need to use the 'safe' list iteration here - * as an item removal is immediately followed by return. - */ - llist_for_each_entry(prim, queue, list) { - if (prim->chan == lchan_type) { - llist_del(&prim->list); - return prim; - } - } - - return NULL; + return msg; } /** * Dequeues either a FACCH, or a speech TCH primitive * of a given channel type (Lm or Bm). * - * Note: we could avoid 'lchan_type' parameter and just - * check the prim's channel type using L1SCHED_CHAN_IS_TCH(), - * but the current approach is a bit more flexible, - * and allows one to have both sub-slots of TCH/H - * enabled on same timeslot e.g. for testing... - * - * @param queue transmit queue to take a prim from - * @param lchan_type required channel type of a primitive, - * e.g. L1SCHED_TCHF, L1SCHED_TCHH_0, or L1SCHED_TCHH_1 + * @param lchan logical channel state * @param facch FACCH (true) or speech (false) prim? * @return either a FACCH, or a TCH primitive if found, * otherwise NULL */ -static struct l1sched_ts_prim *prim_dequeue_tch(struct llist_head *queue, - enum l1sched_lchan_type lchan_type, bool facch) +static struct msgb *prim_dequeue_tch(struct l1sched_lchan_state *lchan, bool facch) { - struct l1sched_ts_prim *prim; + struct msgb *msg; /** * There is no need to use the 'safe' list iteration here * as an item removal is immediately followed by return. */ - llist_for_each_entry(prim, queue, list) { - if (prim->chan != lchan_type) + llist_for_each_entry(msg, &lchan->tx_prims, list) { + bool is_facch = msgb_l2len(msg) == GSM_MACBLOCK_LEN; + if (is_facch != facch) continue; - /* Either FACCH, or not FACCH */ - if (L1SCHED_PRIM_IS_FACCH(prim) != facch) - continue; - - llist_del(&prim->list); - return prim; + llist_del(&msg->list); + return msg; } return NULL; @@ -324,30 +245,30 @@ * If a FACCH/F prim is found, one TCH/F prim is being * dropped (i.e. replaced). * - * @param queue a transmit queue to take a prim from + * @param lchan logical channel state * @return either a FACCH/F, or a TCH/F primitive, * otherwise NULL */ -static struct l1sched_ts_prim *prim_dequeue_tch_f(struct llist_head *queue) +static struct msgb *prim_dequeue_tch_f(struct l1sched_lchan_state *lchan) { - struct l1sched_ts_prim *facch; - struct l1sched_ts_prim *tch; + struct msgb *facch; + struct msgb *tch; /* Attempt to find a pair of both FACCH/F and TCH/F frames */ - facch = prim_dequeue_tch(queue, L1SCHED_TCHF, true); - tch = prim_dequeue_tch(queue, L1SCHED_TCHF, false); + facch = prim_dequeue_tch(lchan, true); + tch = prim_dequeue_tch(lchan, false); /* Prioritize FACCH/F, if found */ if (facch) { /* One TCH/F prim is replaced */ if (tch) - talloc_free(tch); + msgb_free(tch); return facch; } else if (tch) { /* Only TCH/F prim was found */ return tch; } else { - /* Nothing was found, e.g. when only SACCH frames are in queue */ + /* Nothing was found */ return NULL; } } @@ -368,96 +289,95 @@ * * where the numbers within brackets are fn % 26. * - * @param queue transmit queue to take a prim from + * @param lchan logical channel state * @param fn the current frame number - * @param lchan_type required channel type of a primitive, * @return either a FACCH/H, or a TCH/H primitive, * otherwise NULL */ -static struct l1sched_ts_prim *prim_dequeue_tch_h(struct llist_head *queue, - uint32_t fn, enum l1sched_lchan_type lchan_type) +static struct msgb *prim_dequeue_tch_h(struct l1sched_lchan_state *lchan, uint32_t fn) { - struct l1sched_ts_prim *facch; - struct l1sched_ts_prim *tch; + struct msgb *facch; + struct msgb *tch; bool facch_now; /* May we initiate an UL FACCH/H frame transmission now? */ - facch_now = l1sched_tchh_facch_start(lchan_type, fn, true); + facch_now = l1sched_tchh_facch_start(lchan->type, fn, true); if (!facch_now) /* Just dequeue a TCH/H prim */ goto no_facch; /* If there are no FACCH/H prims in the queue */ - facch = prim_dequeue_tch(queue, lchan_type, true); + facch = prim_dequeue_tch(lchan, true); if (!facch) /* Just dequeue a TCH/H prim */ goto no_facch; /* FACCH/H prim replaces two TCH/F prims */ - tch = prim_dequeue_tch(queue, lchan_type, false); + tch = prim_dequeue_tch(lchan, false); if (tch) { /* At least one TCH/H prim is dropped */ - talloc_free(tch); + msgb_free(tch); /* Attempt to find another */ - tch = prim_dequeue_tch(queue, lchan_type, false); + tch = prim_dequeue_tch(lchan, false); if (tch) /* Drop the second TCH/H prim */ - talloc_free(tch); + msgb_free(tch); } return facch; no_facch: - return prim_dequeue_tch(queue, lchan_type, false); + return prim_dequeue_tch(lchan, false); } /** - * Dequeues a single primitive of required type - * from a specified transmit queue. + * Dequeues a primitive from the Tx queue of the given lchan. * - * @param queue a transmit queue to take a prim from - * @param fn the current frame number (used for FACCH/H) * @param lchan logical channel state + * @param fn the current frame number (used for FACCH/H) * @return a primitive or NULL if not found */ -struct l1sched_ts_prim *l1sched_prim_dequeue(struct llist_head *queue, - uint32_t fn, struct l1sched_lchan_state *lchan) +struct msgb *l1sched_lchan_prim_dequeue(struct l1sched_lchan_state *lchan, uint32_t fn) { - struct l1sched_ts_prim *prim; - /* SACCH is unorthodox, see 3GPP TS 04.08, section 3.4.1 */ if (L1SCHED_CHAN_IS_SACCH(lchan->type)) - return prim_dequeue_sacch(queue, lchan); + return prim_dequeue_sacch(lchan); /* There is nothing to dequeue */ - if (llist_empty(queue)) + if (llist_empty(&lchan->tx_prims)) return NULL; switch (lchan->type) { /* TCH/F requires FACCH/F prioritization */ case L1SCHED_TCHF: - return prim_dequeue_tch_f(queue); + return prim_dequeue_tch_f(lchan); /* FACCH/H prioritization is a bit more complex */ case L1SCHED_TCHH_0: case L1SCHED_TCHH_1: - return prim_dequeue_tch_h(queue, fn, lchan->type); + return prim_dequeue_tch_h(lchan, fn); /* PDCH is timing critical, we need to check TDMA Fn */ case L1SCHED_PDTCH: case L1SCHED_PTCCH: - prim = prim_dequeue_one(queue, lchan->type); - if (prim == NULL) + { + struct msgb *msg = msgb_dequeue(&lchan->tx_prims); + const struct l1sched_prim *prim; + + if (msg == NULL) return NULL; - if (OSMO_LIKELY(prim->fn == fn)) - return prim; + prim = l1sched_prim_from_msgb(msg); + + if (OSMO_LIKELY(prim->data_req.frame_nr == fn)) + return msg; LOGP_LCHAND(lchan, LOGL_ERROR, "%s(): dropping Tx primitive (current Fn=%u, prim Fn=%u)\n", - __func__, fn, prim->fn); - talloc_free(prim); + __func__, fn, prim->data_req.frame_nr); + msgb_free(msg); return NULL; + } /* Other kinds of logical channels */ default: - return prim_dequeue_one(queue, lchan->type); + return msgb_dequeue(&lchan->tx_prims); } } @@ -468,7 +388,7 @@ */ void l1sched_lchan_prim_drop(struct l1sched_lchan_state *lchan) { - talloc_free(lchan->prim); + msgb_free(lchan->prim); lchan->prim = NULL; } @@ -480,11 +400,13 @@ * @param lchan lchan to assign a primitive * @return zero in case of success, otherwise a error code */ -int l1sched_prim_dummy(struct l1sched_lchan_state *lchan) +void l1sched_lchan_prim_assign_dummy(struct l1sched_lchan_state *lchan) { + const struct l1sched_lchan_desc *lchan_desc; enum l1sched_lchan_type chan = lchan->type; uint8_t tch_mode = lchan->tch_mode; - struct l1sched_ts_prim *prim; + struct l1sched_prim *prim; + struct msgb *msg; uint8_t prim_buffer[40]; size_t prim_len = 0; int i; @@ -504,6 +426,8 @@ /* Not applicable for SACCH! */ OSMO_ASSERT(!L1SCHED_CHAN_IS_SACCH(lchan->type)); + lchan_desc = &l1sched_lchan_desc[lchan->type]; + /** * Determine what actually should be generated: * TCH in GSM48_CMODE_SIGN: LAPDm fill frame; @@ -515,7 +439,7 @@ prim_len = l1sched_bad_frame_ind(prim_buffer, lchan); } else if (L1SCHED_CHAN_IS_TCH(chan) && L1SCHED_TCH_MODE_IS_DATA(tch_mode)) { /* FIXME: should we do anything for CSD? */ - return 0; + return; } else { /* Copy LAPDm fill frame's header */ memcpy(prim_buffer, lapdm_fill_frame, sizeof(lapdm_fill_frame)); @@ -535,39 +459,137 @@ /* Nothing to allocate / assign */ if (!prim_len) - return 0; + return; - /* Allocate a new primitive */ - prim = talloc_zero_size(lchan, sizeof(struct l1sched_ts_prim) + prim_len); - if (prim == NULL) - return -ENOMEM; + msg = l1sched_prim_alloc(L1SCHED_PRIM_T_DATA, PRIM_OP_REQUEST, prim_len); + OSMO_ASSERT(msg != NULL); - /* Init primitive header */ - prim->payload_len = prim_len; - prim->chan = lchan->type; + prim = l1sched_prim_from_msgb(msg); + prim->data_req = (struct l1sched_prim_chdr) { + .frame_nr = 0, /* dummy */ + .chan_nr = lchan_desc->chan_nr | lchan->ts->index, + .link_id = lchan_desc->link_id, + }; - /* Fill in the payload */ - memcpy(prim->payload, prim_buffer, prim_len); + memcpy(msgb_put(msg, prim_len), &prim_buffer[0], prim_len); /* Assign the current prim */ - lchan->prim = prim; + lchan->prim = msg; LOGP_LCHAND(lchan, LOGL_DEBUG, "Transmitting a dummy / silence frame\n"); +} +int l1sched_lchan_emit_data_ind(struct l1sched_lchan_state *lchan, + const uint8_t *data, size_t data_len, + int n_errors, int n_bits_total, + bool traffic) +{ + const struct l1sched_meas_set *meas = &lchan->meas_avg; + const struct l1sched_lchan_desc *lchan_desc; + struct l1sched_prim *prim; + struct msgb *msg; + + lchan_desc = &l1sched_lchan_desc[lchan->type]; + + msg = l1sched_prim_alloc(L1SCHED_PRIM_T_DATA, PRIM_OP_INDICATION, data_len); + OSMO_ASSERT(msg != NULL); + + prim = l1sched_prim_from_msgb(msg); + prim->data_ind = (struct l1sched_prim_data_ind) { + .chdr = { + .frame_nr = meas->fn, + .chan_nr = lchan_desc->chan_nr | lchan->ts->index, + .link_id = lchan_desc->link_id, + .traffic = traffic, + }, + .toa256 = meas->toa256, + .rssi = meas->rssi, + .n_errors = n_errors, + .n_bits_total = n_bits_total, + }; + + if (data_len > 0) + memcpy(msgb_put(msg, data_len), data, data_len); + + return l1sched_prim_to_user(lchan->ts->sched, msg); +} + +int l1sched_lchan_emit_data_cnf(struct l1sched_lchan_state *lchan, uint32_t fn) +{ + struct l1sched_prim *prim; + struct msgb *msg; + + /* take ownership of the prim */ + OSMO_ASSERT(msg != NULL); + msg = lchan->prim; + lchan->prim = NULL; + + /* convert from DATA.req to DATA.cnf */ + prim = l1sched_prim_from_msgb(lchan->prim); + prim->oph.operation = PRIM_OP_CONFIRM; + + switch (prim->oph.primitive) { + case L1SCHED_PRIM_T_DATA: + prim->data_cnf.frame_nr = fn; + break; + case L1SCHED_PRIM_T_RACH: + prim->rach_cnf.chdr.frame_nr = fn; + break; + default: + /* shall not happen */ + OSMO_ASSERT(0); + } + + return l1sched_prim_to_user(lchan->ts->sched, msg); +} + +static int prim_enqeue(struct l1sched_state *sched, struct msgb *msg, + const struct l1sched_prim_chdr *chdr) +{ + const struct l1sched_prim *prim = l1sched_prim_from_msgb(msg); + struct l1sched_lchan_state *lchan; + + lchan = l1sched_find_lchan_by_chan_nr(sched, chdr->chan_nr, chdr->link_id); + if (OSMO_UNLIKELY(lchan == NULL || !lchan->active)) { + LOGP_SCHEDD(sched, LOGL_ERROR, + "No [active] lchan for primitive " L1SCHED_PRIM_STR_FMT " " + "(chan_nr=%02x, link_id=%02x, len=%u): %s\n", + L1SCHED_PRIM_STR_ARGS(prim), + chdr->chan_nr, chdr->link_id, + msgb_l2len(msg), msgb_hexdump_l2(msg)); + msgb_free(msg); + return -ENODEV; + } + + LOGP_LCHAND(lchan, LOGL_DEBUG, + "Enqueue primitive " L1SCHED_PRIM_STR_FMT " " + "(chan_nr=%02x, link_id=%02x, len=%u): %s\n", + L1SCHED_PRIM_STR_ARGS(prim), + chdr->chan_nr, chdr->link_id, + msgb_l2len(msg), msgb_hexdump_l2(msg)); + + msgb_enqueue(&lchan->tx_prims, msg); return 0; } -/** - * Flushes a queue of primitives - * - * @param list list of prims going to be flushed - */ -void l1sched_prim_flush_queue(struct llist_head *list) +int l1sched_prim_from_user(struct l1sched_state *sched, struct msgb *msg) { - struct l1sched_ts_prim *prim, *prim_next; + const struct l1sched_prim *prim = l1sched_prim_from_msgb(msg); - llist_for_each_entry_safe(prim, prim_next, list, list) { - llist_del(&prim->list); - talloc_free(prim); + LOGP_SCHEDD(sched, LOGL_DEBUG, + "%s(): Rx " L1SCHED_PRIM_STR_FMT "\n", + __func__, L1SCHED_PRIM_STR_ARGS(prim)); + + switch (OSMO_PRIM_HDR(&prim->oph)) { + case OSMO_PRIM(L1SCHED_PRIM_T_DATA, PRIM_OP_REQUEST): + return prim_enqeue(sched, msg, &prim->data_req); + case OSMO_PRIM(L1SCHED_PRIM_T_RACH, PRIM_OP_REQUEST): + return prim_enqeue(sched, msg, &prim->rach_req.chdr); + default: + LOGP_SCHEDD(sched, LOGL_ERROR, + "%s(): Unhandled primitive " L1SCHED_PRIM_STR_FMT "\n", + __func__, L1SCHED_PRIM_STR_ARGS(prim)); + msgb_free(msg); + return -ENOTSUP; } } diff --git a/src/host/trxcon/src/sched_trx.c b/src/host/trxcon/src/sched_trx.c index c337661..3bbf530 100644 --- a/src/host/trxcon/src/sched_trx.c +++ b/src/host/trxcon/src/sched_trx.c @@ -68,18 +68,20 @@ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; -static int l1sched_cfg_pchan_comb_req(struct l1sched_state *sched, +static int l1sched_cfg_pchan_comb_ind(struct l1sched_state *sched, uint8_t tn, enum gsm_phys_chan_config pchan) { - const struct l1sched_config_req cr = { - .type = L1SCHED_CFG_PCHAN_COMB, - .pchan_comb = { - .tn = tn, - .pchan = pchan, - }, - }; + struct l1sched_prim *prim; + struct msgb *msg; - return l1sched_handle_config_req(sched, &cr); + msg = l1sched_prim_alloc(L1SCHED_PRIM_T_PCHAN_COMB, PRIM_OP_INDICATION, 0); + OSMO_ASSERT(msg != NULL); + + prim = l1sched_prim_from_msgb(msg); + prim->pchan_comb_ind.tn = tn; + prim->pchan_comb_ind.pchan = pchan; + + return l1sched_prim_to_user(sched, msg); } static void l1sched_a5_burst_enc(struct l1sched_lchan_state *lchan, @@ -121,11 +123,11 @@ /* If no primitive is being processed, try obtaining one from Tx queue */ if (lchan->prim == NULL) - lchan->prim = l1sched_prim_dequeue(&ts->tx_prims, br->fn, lchan); + lchan->prim = l1sched_lchan_prim_dequeue(lchan, br->fn); if (lchan->prim == NULL) { /* If CBTX (Continuous Burst Transmission) is required */ if (l1sched_lchan_desc[chan].flags & L1SCHED_CH_FLAG_CBTX) - l1sched_prim_dummy(lchan); + l1sched_lchan_prim_assign_dummy(lchan); if (lchan->prim == NULL) return; } @@ -134,7 +136,8 @@ /* Handover RACH needs to be handled regardless of the * current channel type and the associated handler. */ - if (L1SCHED_PRIM_IS_RACH(lchan->prim) && lchan->prim->chan != L1SCHED_RACH) + if (l1sched_prim_type_from_msgb(lchan->prim) == L1SCHED_PRIM_T_RACH && + lchan->type != L1SCHED_RACH) handler = l1sched_lchan_desc[L1SCHED_RACH].tx_fn; /* Poke lchan handler */ @@ -272,15 +275,12 @@ talloc_free(lchan); } - /* Flush queue primitives for TX */ - l1sched_prim_flush_queue(&ts->tx_prims); - /* Remove ts from list and free memory */ sched->ts[tn] = NULL; talloc_free(ts); /* Notify transceiver about that */ - l1sched_cfg_pchan_comb_req(sched, tn, GSM_PCHAN_NONE); + l1sched_cfg_pchan_comb_ind(sched, tn, GSM_PCHAN_NONE); } #define LAYOUT_HAS_LCHAN(layout, lchan) \ @@ -316,8 +316,6 @@ "(Re)configure TDMA timeslot #%u as %s\n", tn, ts->mf_layout->name); - /* Init queue primitives for TX */ - INIT_LLIST_HEAD(&ts->tx_prims); /* Init logical channels list */ INIT_LLIST_HEAD(&ts->lchans); @@ -337,6 +335,9 @@ /* Set channel type */ lchan->type = type; + /* Init the Tx queue */ + INIT_LLIST_HEAD(&lchan->tx_prims); + /* Add to the list of channel states */ llist_add_tail(&lchan->list, &ts->lchans); @@ -346,7 +347,7 @@ } /* Notify transceiver about TS activation */ - l1sched_cfg_pchan_comb_req(sched, tn, config); + l1sched_cfg_pchan_comb_ind(sched, tn, config); return 0; } @@ -364,9 +365,6 @@ /* Undefine multiframe layout */ ts->mf_layout = NULL; - /* Flush queue primitives for TX */ - l1sched_prim_flush_queue(&ts->tx_prims); - /* Deactivate all logical channels */ l1sched_deactivate_all_lchans(ts); @@ -377,7 +375,7 @@ } /* Notify transceiver about that */ - l1sched_cfg_pchan_comb_req(sched, tn, GSM_PCHAN_NONE); + l1sched_cfg_pchan_comb_ind(sched, tn, GSM_PCHAN_NONE); return 0; } @@ -541,6 +539,8 @@ static void l1sched_reset_lchan(struct l1sched_lchan_state *lchan) { + struct msgb *msg; + /* Prevent NULL-pointer deference */ OSMO_ASSERT(lchan != NULL); @@ -568,6 +568,10 @@ /* Forget the current prim */ l1sched_lchan_prim_drop(lchan); + /* Flush the queue of pending Tx prims */ + while ((msg = msgb_dequeue(&lchan->tx_prims)) != NULL) + msgb_free(msg); + /* Channel specific stuff */ if (L1SCHED_CHAN_IS_TCH(lchan->type)) { lchan->dl_ongoing_facch = 0; @@ -657,20 +661,6 @@ return GSM_PCHAN_NONE; } -enum l1sched_lchan_type l1sched_chan_nr2lchan_type(uint8_t chan_nr, - uint8_t link_id) -{ - int i; - - /* Iterate over all known lchan types */ - for (i = 0; i < _L1SCHED_CHAN_MAX; i++) - if (l1sched_lchan_desc[i].chan_nr == (chan_nr & 0xf8)) - if (l1sched_lchan_desc[i].link_id == link_id) - return i; - - return L1SCHED_IDLE; -} - static void l1sched_a5_burst_dec(struct l1sched_lchan_state *lchan, struct l1sched_burst_ind *bi) { diff --git a/src/host/trxcon/src/trxcon_fsm.c b/src/host/trxcon/src/trxcon_fsm.c index 91c807a..74d1a66 100644 --- a/src/host/trxcon/src/trxcon_fsm.c +++ b/src/host/trxcon/src/trxcon_fsm.c @@ -283,21 +283,25 @@ const struct trxcon_param_tx_access_burst_req *req) { struct trxcon_inst *trxcon = fi->priv; - enum l1sched_ts_prim_type prim_type; - const struct l1sched_ts_prim *prim; + struct l1sched_prim *prim; + struct msgb *msg; - const struct l1sched_ts_prim_rach rach = { + msg = l1sched_prim_alloc(L1SCHED_PRIM_T_RACH, PRIM_OP_REQUEST, 0); + OSMO_ASSERT(msg != NULL); + + prim = l1sched_prim_from_msgb(msg); + prim->rach_req = (struct l1sched_prim_rach) { + .chdr = { + .chan_nr = req->chan_nr, + .link_id = req->link_id, + }, .synch_seq = req->synch_seq, .offset = req->offset, + .is_11bit = req->is_11bit, .ra = req->ra, }; - prim_type = req->is_11bit ? L1SCHED_PRIM_RACH11 : L1SCHED_PRIM_RACH8; - prim = l1sched_prim_push(trxcon->sched, prim_type, - req->chan_nr, req->link_id, - (const uint8_t *)&rach, sizeof(rach)); - if (prim == NULL) - LOGPFSML(fi, LOGL_ERROR, "Failed to enqueue a prim\n"); + l1sched_prim_to_user(trxcon->sched, msg); } static void handle_dch_est_req(struct osmo_fsm_inst *fi, @@ -485,15 +489,21 @@ case TRXCON_EV_TX_DATA_REQ: { const struct trxcon_param_tx_data_req *req = data; - struct l1sched_ts_prim *prim; + struct l1sched_prim *prim; + struct msgb *msg; - prim = l1sched_prim_push(trxcon->sched, L1SCHED_PRIM_DATA, - req->chan_nr, req->link_id, - req->data, req->data_len); - if (prim == NULL) { - LOGPFSML(fi, LOGL_ERROR, "Failed to enqueue a prim\n"); - return; - } + msg = l1sched_prim_alloc(L1SCHED_PRIM_T_DATA, PRIM_OP_REQUEST, req->data_len); + OSMO_ASSERT(msg != NULL); + + prim = l1sched_prim_from_msgb(msg); + prim->data_req = (struct l1sched_prim_chdr) { + .chan_nr = req->chan_nr, + .link_id = req->link_id, + .traffic = req->traffic, + }; + + memcpy(msgb_put(msg, req->data_len), req->data, req->data_len); + l1sched_prim_to_user(trxcon->sched, msg); break; } case TRXCON_EV_TX_DATA_CNF: @@ -547,21 +557,24 @@ 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; + struct l1sched_prim *prim; + struct msgb *msg = data; 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; - } + msg = l1sched_prim_alloc(L1SCHED_PRIM_T_DATA, PRIM_OP_REQUEST, block_req.data_len); + OSMO_ASSERT(msg != NULL); - prim->fn = block_req.hdr.fn; + prim = l1sched_prim_from_msgb(msg); + prim->data_req = (struct l1sched_prim_chdr) { + .frame_nr = block_req.hdr.fn, + .chan_nr = RSL_CHAN_OSMO_PDCH | block_req.hdr.tn, + .link_id = 0x00, + }; + + memcpy(msgb_put(msg, block_req.data_len), block_req.data, block_req.data_len); + l1sched_prim_to_user(trxcon->sched, msg); break; } case TRXCON_EV_RX_DATA_IND: diff --git a/src/host/trxcon/src/trxcon_shim.c b/src/host/trxcon/src/trxcon_shim.c index de3de91..4f56d85 100644 --- a/src/host/trxcon/src/trxcon_shim.c +++ b/src/host/trxcon/src/trxcon_shim.c @@ -1,7 +1,7 @@ /* * OsmocomBB <-> SDR connection bridge * - * (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 @@ -24,52 +24,33 @@ #include <osmocom/core/fsm.h> #include <osmocom/core/gsmtap_util.h> #include <osmocom/core/gsmtap.h> +#include <osmocom/gsm/rsl.h> #include <osmocom/bb/trxcon/trxcon.h> #include <osmocom/bb/trxcon/trxcon_fsm.h> #include <osmocom/bb/trxcon/phyif.h> #include <osmocom/bb/l1sched/l1sched.h> -static void trxcon_gsmtap_send(struct gsmtap_inst *gi, uint8_t chan_type, - uint32_t fn, uint8_t tn, uint8_t ss, - uint16_t band_arfcn, - int8_t signal_dbm, uint8_t snr, - const uint8_t *data, size_t data_len) +static void trxcon_gsmtap_send(struct trxcon_inst *trxcon, + const struct l1sched_prim_chdr *chdr, + const uint8_t *data, size_t data_len, + int8_t signal_dbm, uint8_t snr, bool uplink) { - /* Omit frames with unknown channel type */ - if (chan_type == GSMTAP_CHANNEL_UNKNOWN) - return; + uint16_t band_arfcn = trxcon->l1p.band_arfcn; + uint8_t chan_type, ss, tn; - /* TODO: distinguish GSMTAP_CHANNEL_PCH and GSMTAP_CHANNEL_AGCH */ - gsmtap_send(gi, band_arfcn, tn, chan_type, ss, fn, signal_dbm, snr, data, data_len); + if (uplink) + band_arfcn |= ARFCN_UPLINK; + if (rsl_dec_chan_nr(chdr->chan_nr, &chan_type, &ss, &tn) != 0) + return; + chan_type = chantype_rsl2gsmtap2(chan_type, chdr->link_id, chdr->traffic); + + gsmtap_send(trxcon->gsmtap, band_arfcn, tn, chan_type, ss, + chdr->frame_nr, signal_dbm, snr, + data, data_len); } /* External L1 API for the scheduler */ -int l1sched_handle_config_req(struct l1sched_state *sched, - const struct l1sched_config_req *cr) -{ - struct trxcon_inst *trxcon = sched->priv; - - switch (cr->type) { - case L1SCHED_CFG_PCHAN_COMB: - { - struct trxcon_param_set_phy_config_req req = { - .type = TRXCON_PHY_CFGT_PCHAN_COMB, - .pchan_comb = { - .tn = cr->pchan_comb.tn, - .pchan = cr->pchan_comb.pchan, - }, - }; - - return osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_SET_PHY_CONFIG_REQ, &req); - } - default: - LOGPFSML(trxcon->fi, LOGL_ERROR, - "Unhandled config request (type 0x%02x)\n", cr->type); - return -ENODEV; - } -} - int l1sched_handle_burst_req(struct l1sched_state *sched, const struct l1sched_burst_req *br) { @@ -86,137 +67,122 @@ } /* External L2 API for the scheduler */ -int l1sched_handle_data_ind(struct l1sched_lchan_state *lchan, - const uint8_t *data, size_t data_len, - int n_errors, int n_bits_total, - enum l1sched_data_type dt) +static int handle_prim_data_ind(struct trxcon_inst *trxcon, struct msgb *msg) { - const struct l1sched_meas_set *meas = &lchan->meas_avg; - const struct l1sched_lchan_desc *lchan_desc; - struct l1sched_state *sched = lchan->ts->sched; - struct trxcon_inst *trxcon = sched->priv; - int rc; - - lchan_desc = &l1sched_lchan_desc[lchan->type]; - + const struct l1sched_prim *prim = l1sched_prim_from_msgb(msg); struct trxcon_param_rx_data_ind ind = { - /* .traffic is set below */ - .chan_nr = lchan_desc->chan_nr | lchan->ts->index, - .link_id = lchan_desc->link_id, + .traffic = prim->data_ind.chdr.traffic, + .chan_nr = prim->data_ind.chdr.chan_nr, + .link_id = prim->data_ind.chdr.link_id, .band_arfcn = trxcon->l1p.band_arfcn, - .frame_nr = meas->fn, - .toa256 = meas->toa256, - .rssi = meas->rssi, - .n_errors = n_errors, - .n_bits_total = n_bits_total, - .data_len = data_len, - .data = data, + .frame_nr = prim->data_ind.chdr.frame_nr, + .toa256 = prim->data_ind.toa256, + .rssi = prim->data_ind.rssi, + .n_errors = prim->data_ind.n_errors, + .n_bits_total = prim->data_ind.n_bits_total, + .data_len = msgb_l2len(msg), + .data = msgb_l2(msg), }; - switch (dt) { - case L1SCHED_DT_PACKET_DATA: - case L1SCHED_DT_TRAFFIC: - ind.traffic = true; - /* fall-through */ - case L1SCHED_DT_SIGNALING: - rc = osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_RX_DATA_IND, &ind); - break; - case L1SCHED_DT_OTHER: - if (lchan->type == L1SCHED_SCH) { - if (trxcon->fi->state != TRXCON_ST_FBSB_SEARCH) - return 0; - rc = osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_FBSB_SEARCH_RES, NULL); - break; - } - /* fall through */ - default: - LOGPFSML(trxcon->fi, LOGL_ERROR, - "Unhandled L2 DATA.ind (type 0x%02x)\n", dt); - return -ENODEV; + if (trxcon->gsmtap != NULL && ind.data_len > 0) { + trxcon_gsmtap_send(trxcon, &prim->data_ind.chdr, + ind.data, ind.data_len, + ind.rssi, 0, false); } - if (trxcon->gsmtap != NULL && data != NULL && data_len > 0) { - trxcon_gsmtap_send(trxcon->gsmtap, lchan_desc->gsmtap_chan_type, - meas->fn, lchan->ts->index, lchan_desc->ss_nr, - trxcon->l1p.band_arfcn, meas->rssi, 0, - data, data_len); - } - - return rc; + return osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_RX_DATA_IND, &ind); } -int l1sched_handle_data_cnf(struct l1sched_lchan_state *lchan, - uint32_t fn, enum l1sched_data_type dt) +static int handle_prim_data_cnf(struct trxcon_inst *trxcon, struct msgb *msg) { - const struct l1sched_lchan_desc *lchan_desc; - struct l1sched_state *sched = lchan->ts->sched; - struct trxcon_inst *trxcon = sched->priv; - const uint8_t *data; - uint8_t ra_buf[2]; - size_t data_len; - int rc; - - lchan_desc = &l1sched_lchan_desc[lchan->type]; - - switch (dt) { - case L1SCHED_DT_PACKET_DATA: - data_len = lchan->prim->payload_len; - data = lchan->prim->payload; - rc = 0; - break; /* do not send DATA.cnf */ - case L1SCHED_DT_SIGNALING: - case L1SCHED_DT_TRAFFIC: - { - struct trxcon_param_tx_data_cnf cnf = { - .traffic = (dt == L1SCHED_DT_TRAFFIC), - .chan_nr = lchan_desc->chan_nr | lchan->ts->index, - .link_id = lchan_desc->link_id, - .band_arfcn = trxcon->l1p.band_arfcn, - .frame_nr = fn, - }; - - rc = osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_TX_DATA_CNF, &cnf); - data_len = lchan->prim->payload_len; - data = lchan->prim->payload; - break; - } - case L1SCHED_DT_OTHER: - if (L1SCHED_PRIM_IS_RACH(lchan->prim)) { - const struct l1sched_ts_prim_rach *rach; - struct trxcon_param_tx_access_burst_cnf cnf = { - .band_arfcn = trxcon->l1p.band_arfcn, - .frame_nr = fn, - }; - - rc = osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_TX_ACCESS_BURST_CNF, &cnf); - - rach = (struct l1sched_ts_prim_rach *)lchan->prim->payload; - if (lchan->prim->type == L1SCHED_PRIM_RACH11) { - ra_buf[0] = (uint8_t)(rach->ra >> 3); - ra_buf[1] = (uint8_t)(rach->ra & 0x07); - data = &ra_buf[0]; - data_len = 2; - } else { - ra_buf[0] = (uint8_t)(rach->ra); - data = &ra_buf[0]; - data_len = 1; - } - break; - } - /* fall through */ - default: - LOGPFSML(trxcon->fi, LOGL_ERROR, - "Unhandled L2 DATA.cnf (type 0x%02x)\n", dt); - return -ENODEV; - } + const struct l1sched_prim *prim = l1sched_prim_from_msgb(msg); + struct trxcon_param_tx_data_cnf cnf = { + .traffic = prim->data_cnf.traffic, + .chan_nr = prim->data_cnf.chan_nr, + .link_id = prim->data_cnf.link_id, + .band_arfcn = trxcon->l1p.band_arfcn, + .frame_nr = prim->data_cnf.frame_nr, + }; if (trxcon->gsmtap != NULL) { - trxcon_gsmtap_send(trxcon->gsmtap, lchan_desc->gsmtap_chan_type, - fn, lchan->ts->index, lchan_desc->ss_nr, - trxcon->l1p.band_arfcn | ARFCN_UPLINK, - 0, 0, data, data_len); + trxcon_gsmtap_send(trxcon, &prim->data_cnf, + msgb_l2(msg), msgb_l2len(msg), + 0, 0, true); } + /* XXX: do not send for L1SCHED_DT_PACKET_DATA */ + return osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_TX_DATA_CNF, &cnf); +} + +static int handle_prim_rach_cnf(struct trxcon_inst *trxcon, struct msgb *msg) +{ + const struct l1sched_prim *prim = l1sched_prim_from_msgb(msg); + struct trxcon_param_tx_access_burst_cnf cnf = { + .band_arfcn = trxcon->l1p.band_arfcn, + .frame_nr = prim->rach_cnf.chdr.frame_nr, + }; + + if (trxcon->gsmtap != NULL) { + if (prim->rach_cnf.is_11bit) { + msgb_put_u8(msg, (uint8_t)(prim->rach_cnf.ra >> 3)); + msgb_put_u8(msg, (uint8_t)(prim->rach_cnf.ra & 0x07)); + } else { + msgb_put_u8(msg, (uint8_t)(prim->rach_cnf.ra)); + } + + trxcon_gsmtap_send(trxcon, &prim->rach_cnf.chdr, + msgb_l2(msg), msgb_l2len(msg), + 0, 0, true); + } + + return osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_TX_ACCESS_BURST_CNF, &cnf); +} + +int l1sched_prim_to_user(struct l1sched_state *sched, struct msgb *msg) +{ + const struct l1sched_prim *prim = l1sched_prim_from_msgb(msg); + struct trxcon_inst *trxcon = sched->priv; + int rc = 0; + + LOGPFSML(trxcon->fi, LOGL_DEBUG, + "%s(): Rx " L1SCHED_PRIM_STR_FMT "\n", + __func__, L1SCHED_PRIM_STR_ARGS(prim)); + + switch (OSMO_PRIM_HDR(&prim->oph)) { + case OSMO_PRIM(L1SCHED_PRIM_T_DATA, PRIM_OP_INDICATION): + rc = handle_prim_data_ind(trxcon, msg); + break; + case OSMO_PRIM(L1SCHED_PRIM_T_DATA, PRIM_OP_CONFIRM): + rc = handle_prim_data_cnf(trxcon, msg); + break; + case OSMO_PRIM(L1SCHED_PRIM_T_RACH, PRIM_OP_CONFIRM): + rc = handle_prim_rach_cnf(trxcon, msg); + break; + case OSMO_PRIM(L1SCHED_PRIM_T_SCH, PRIM_OP_INDICATION): + if (trxcon->fi->state == TRXCON_ST_FBSB_SEARCH) + rc = osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_FBSB_SEARCH_RES, NULL); + break; + case OSMO_PRIM(L1SCHED_PRIM_T_PCHAN_COMB, PRIM_OP_INDICATION): + { + struct trxcon_param_set_phy_config_req req = { + .type = TRXCON_PHY_CFGT_PCHAN_COMB, + .pchan_comb = { + .tn = prim->pchan_comb_ind.tn, + .pchan = prim->pchan_comb_ind.pchan, + }, + }; + + rc = osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_SET_PHY_CONFIG_REQ, &req); + break; + } + default: + LOGPFSML(trxcon->fi, LOGL_ERROR, + "%s(): Unhandled primitive " L1SCHED_PRIM_STR_FMT "\n", + __func__, L1SCHED_PRIM_STR_ARGS(prim)); + rc = -ENOTSUP; + } + + msgb_free(msg); return rc; } -- To view, visit https://gerrit.osmocom.org/c/osmocom-bb/+/32304 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: I73576bd0ea10a5663ba6254283812c275cc3fa46 Gerrit-Change-Number: 32304 Gerrit-PatchSet: 1 Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-MessageType: newchange
1 0
0 0
[M] Change in libosmo-gprs[master]: sm: Start using SNSM SAP
by pespin 13 Apr '23

13 Apr '23
Attention is currently required from: pespin. Hello Jenkins Builder, I'd like you to reexamine a change. Please visit https://gerrit.osmocom.org/c/libosmo-gprs/+/32295 to look at the new patch set (#3). Change subject: sm: Start using SNSM SAP ...................................................................... sm: Start using SNSM SAP Related: OS#5501 Change-Id: Ic5525bfa92e2591757d999610c0d59849d022d8d --- M include/osmocom/gprs/sm/sm_ms_fsm.h M include/osmocom/gprs/sm/sm_prim.h M include/osmocom/gprs/sm/sm_private.h M libosmo-gprs-sm.pc.in M src/sm/Makefile.am M src/sm/sm.c M src/sm/sm_ms_fsm.c M src/sm/sm_prim.c M tests/sm/Makefile.am M tests/sm/sm_prim_test.c M tests/sm/sm_prim_test.err M tests/sm/sm_prim_test.ok 12 files changed, 216 insertions(+), 5 deletions(-) git pull ssh://gerrit.osmocom.org:29418/libosmo-gprs refs/changes/95/32295/3 -- To view, visit https://gerrit.osmocom.org/c/libosmo-gprs/+/32295 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmo-gprs Gerrit-Branch: master Gerrit-Change-Id: Ic5525bfa92e2591757d999610c0d59849d022d8d Gerrit-Change-Number: 32295 Gerrit-PatchSet: 3 Gerrit-Owner: pespin <pespin(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Attention: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: newpatchset
1 0
0 0
[S] Change in libosmo-sccp[master]: vty: Add new "show cs7 instance <0-15> point-codes" command
by laforge 13 Apr '23

13 Apr '23
laforge has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmo-sccp/+/32299 ) Change subject: vty: Add new "show cs7 instance <0-15> point-codes" command ...................................................................... vty: Add new "show cs7 instance <0-15> point-codes" command This is a comment supported on Cisco ITP. Change-Id: I2908dc5d9f18610352b7ed7ec8ca814ae3736359 --- M src/osmo_ss7_vty.c 1 file changed, 40 insertions(+), 0 deletions(-) git pull ssh://gerrit.osmocom.org:29418/libosmo-sccp refs/changes/99/32299/1 diff --git a/src/osmo_ss7_vty.c b/src/osmo_ss7_vty.c index acded2b..8504473 100644 --- a/src/osmo_ss7_vty.c +++ b/src/osmo_ss7_vty.c @@ -282,6 +282,34 @@ return CMD_SUCCESS; } +DEFUN(show_cs7_pc, show_cs7_pc_cmd, + "show cs7 instance <0-15> point-codes", + SHOW_STR CS7_STR INST_STR INST_STR "Point Codes we are responding to\n") +{ + int id = atoi(argv[0]); + struct osmo_ss7_instance *inst; + + inst = osmo_ss7_instance_find(id); + if (!inst) { + vty_out(vty, "No SS7 instance %d found%s", id, VTY_NEWLINE); + return CMD_WARNING; + } + + vty_out(vty, "CS7 Point Code Type Status%s", VTY_NEWLINE); + vty_out(vty, "-------------- ---------- ---------------%s", VTY_NEWLINE); + if (osmo_ss7_pc_is_valid(inst->cfg.primary_pc)) { + vty_out(vty, "%s %s %s%s", osmo_ss7_pointcode_print(inst, inst->cfg.primary_pc), + "local", "active", VTY_NEWLINE); + } + if (osmo_ss7_pc_is_valid(inst->cfg.secondary_pc)) { + vty_out(vty, "%s %s %s%s", osmo_ss7_pointcode_print(inst, inst->cfg.secondary_pc), + "secondary", "active", VTY_NEWLINE); + } + + return CMD_SUCCESS; +} + + /* TODO: Links + Linksets */ /*********************************************************************** @@ -2097,6 +2125,7 @@ NO_STR "Disable quirk to work around interop issues\n", "\n", "\n", 0); + install_lib_element_ve(&show_cs7_pc_cmd); install_lib_element_ve(&show_cs7_user_cmd); install_lib_element_ve(&show_cs7_xua_cmd); install_lib_element_ve(&show_cs7_config_cmd); -- To view, visit https://gerrit.osmocom.org/c/libosmo-sccp/+/32299 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmo-sccp Gerrit-Branch: master Gerrit-Change-Id: I2908dc5d9f18610352b7ed7ec8ca814ae3736359 Gerrit-Change-Number: 32299 Gerrit-PatchSet: 1 Gerrit-Owner: laforge <laforge(a)osmocom.org> Gerrit-MessageType: newchange
1 0
0 0
[S] Change in libosmo-sccp[master]: SS7: Support secondary point codes
by laforge 13 Apr '23

13 Apr '23
laforge has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmo-sccp/+/32298 ) Change subject: SS7: Support secondary point codes ...................................................................... SS7: Support secondary point codes osmo_ss7 so far only supported a single local point code per cs7 instance: The primary point code. Let's add support for a secondary point code, just like it is the case in Cisco ITP. Change-Id: I3c4c0d89d2a0ea36aa5df0887225d99a16b810f0 --- M TODO-RELEASE M include/osmocom/sigtran/osmo_ss7.h M src/osmo_ss7.c M src/osmo_ss7_vty.c 4 files changed, 42 insertions(+), 3 deletions(-) git pull ssh://gerrit.osmocom.org:29418/libosmo-sccp refs/changes/98/32298/1 diff --git a/TODO-RELEASE b/TODO-RELEASE index 05e12a6..a021219 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -8,3 +8,4 @@ # If any interfaces have been removed or changed since the last public release: c:r:0. #library what description / commit summary line libosmocore >1.8.0 uses new osmo_prim_operation_name() +libosmo-sigtran API change struct osmo_ss7_instance has new member 'secondary_pc' diff --git a/include/osmocom/sigtran/osmo_ss7.h b/include/osmocom/sigtran/osmo_ss7.h index cd1779c..0cb7a80 100644 --- a/include/osmocom/sigtran/osmo_ss7.h +++ b/include/osmocom/sigtran/osmo_ss7.h @@ -96,7 +96,7 @@ char *name; char *description; uint32_t primary_pc; - /* secondary PCs */ + uint32_t secondary_pc; /* capability PCs */ uint8_t network_indicator; struct osmo_ss7_pc_fmt pc_fmt; diff --git a/src/osmo_ss7.c b/src/osmo_ss7.c index 3dc0d51..0be23e9 100644 --- a/src/osmo_ss7.c +++ b/src/osmo_ss7.c @@ -382,6 +382,7 @@ return NULL; inst->cfg.primary_pc = OSMO_SS7_PC_INVALID; + inst->cfg.secondary_pc = OSMO_SS7_PC_INVALID; inst->cfg.id = id; LOGSS7(inst, LOGL_INFO, "Creating SS7 Instance\n"); @@ -2314,7 +2315,9 @@ OSMO_ASSERT(ss7_initialized); if (osmo_ss7_pc_is_valid(inst->cfg.primary_pc) && pc == inst->cfg.primary_pc) return true; - /* FIXME: Secondary and Capability Point Codes */ + if (osmo_ss7_pc_is_valid(inst->cfg.secondary_pc) && pc == inst->cfg.secondary_pc) + return true; + /* FIXME: Capability Point Codes */ return false; } diff --git a/src/osmo_ss7_vty.c b/src/osmo_ss7_vty.c index 7dffe02..acded2b 100644 --- a/src/osmo_ss7_vty.c +++ b/src/osmo_ss7_vty.c @@ -205,7 +205,23 @@ return CMD_SUCCESS; } -/* TODO: cs7 secondary-pc */ +DEFUN_ATTR(cs7_secondary_pc, cs7_secondary_pc_cmd, + "secondary-pc POINT_CODE", + "Configure the local Secondary Point Code\n" + "Point Code\n", + CMD_ATTR_IMMEDIATE) +{ + struct osmo_ss7_instance *inst = vty->index; + int pc = osmo_ss7_pointcode_parse(inst, argv[0]); + if (pc < 0 || !osmo_ss7_pc_is_valid((uint32_t)pc)) { + vty_out(vty, "Invalid point code (%s)%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + inst->cfg.secondary_pc = pc; + return CMD_SUCCESS; +} + /* TODO: cs7 capability-pc */ DEFUN_ATTR(cs7_permit_dyn_rkm, cs7_permit_dyn_rkm_cmd, "xua rkm routing-key-allocation (static-only|dynamic-permitted)", @@ -1929,6 +1945,11 @@ osmo_ss7_pointcode_print(inst, inst->cfg.primary_pc), VTY_NEWLINE); + if (osmo_ss7_pc_is_valid(inst->cfg.secondary_pc)) { + vty_out(vty, " secondary-pc %s%s", + osmo_ss7_pointcode_print(inst, inst->cfg.secondary_pc), VTY_NEWLINE); + } + if (inst->cfg.permit_dyn_rkm_alloc) vty_out(vty, " xua rkm routing-key-allocation dynamic-permitted%s", VTY_NEWLINE); @@ -2087,6 +2108,7 @@ install_lib_element(L_CS7_NODE, &cfg_description_cmd); install_lib_element(L_CS7_NODE, &cs7_net_ind_cmd); install_lib_element(L_CS7_NODE, &cs7_point_code_cmd); + install_lib_element(L_CS7_NODE, &cs7_secondary_pc_cmd); install_lib_element(L_CS7_NODE, &cs7_pc_format_cmd); install_lib_element(L_CS7_NODE, &cs7_pc_format_def_cmd); install_lib_element(L_CS7_NODE, &cs7_pc_delimiter_cmd); -- To view, visit https://gerrit.osmocom.org/c/libosmo-sccp/+/32298 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmo-sccp Gerrit-Branch: master Gerrit-Change-Id: I3c4c0d89d2a0ea36aa5df0887225d99a16b810f0 Gerrit-Change-Number: 32298 Gerrit-PatchSet: 1 Gerrit-Owner: laforge <laforge(a)osmocom.org> Gerrit-MessageType: newchange
1 0
0 0
[S] Change in pysim[master]: pySim-prog.py: fix SyntaxWarning: using is with a literal
by pespin 13 Apr '23

13 Apr '23
Attention is currently required from: fixeria. pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/pysim/+/32297 ) Change subject: pySim-prog.py: fix SyntaxWarning: using is with a literal ...................................................................... Patch Set 1: Code-Review+1 -- To view, visit https://gerrit.osmocom.org/c/pysim/+/32297 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: pysim Gerrit-Branch: master Gerrit-Change-Id: If9460bf827242a1dfc518213e3faa9137a21869a Gerrit-Change-Number: 32297 Gerrit-PatchSet: 1 Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-CC: Jenkins Builder Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Comment-Date: Thu, 13 Apr 2023 17:12:40 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1 0
0 0
[S] Change in pysim[master]: pySim-prog.py: fix SyntaxWarning: using is with a literal
by fixeria 13 Apr '23

13 Apr '23
fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/32297 ) Change subject: pySim-prog.py: fix SyntaxWarning: using is with a literal ...................................................................... pySim-prog.py: fix SyntaxWarning: using is with a literal Change-Id: If9460bf827242a1dfc518213e3faa9137a21869a --- M pySim-prog.py 1 file changed, 11 insertions(+), 2 deletions(-) git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/97/32297/1 diff --git a/pySim-prog.py b/pySim-prog.py index b3919ee..448f2a0 100755 --- a/pySim-prog.py +++ b/pySim-prog.py @@ -599,9 +599,9 @@ # commandline options we can use that info, otherwise we guess that # the length is 2, which is also the most common case. if opts.mnclen != "auto": - if opts.mnclen is "2": + if opts.mnclen == "2": row['mnc'] = row.get('mnc', mnc_from_imsi(row.get('imsi'), False)) - elif opts.mnclen is "3": + elif opts.mnclen == "3": row['mnc'] = row.get('mnc', mnc_from_imsi(row.get('imsi'), True)) else: raise ValueError("invalid parameter --mnclen, must be 2 or 3 or auto") -- To view, visit https://gerrit.osmocom.org/c/pysim/+/32297 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: pysim Gerrit-Branch: master Gerrit-Change-Id: If9460bf827242a1dfc518213e3faa9137a21869a Gerrit-Change-Number: 32297 Gerrit-PatchSet: 1 Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-MessageType: newchange
1 0
0 0
  • ← Newer
  • 1
  • ...
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • ...
  • 226
  • Older →

HyperKitty Powered by HyperKitty version 1.3.12.