Split PCU global PCU object from BTS object

Currently the BTS object (and gprs_rlcmac_bts struct) are used to hold
both PCU global fields and BTS specific fields, all mangled together.
The BTS is even accessed in lots of places by means of a singleton.

This patch introduces a new struct gprs_pcu object aimed at holding all
global state, and several fields are already moved from BTS to it. The
new object can be accessed as global variable "the_pcu", reusing and
including an already exisitng "the_pcu" global variable only used for
bssgp related purposes so far.

This is only a first step towards having a complete split global pcu and
BTS, some fields are still kept in BTS and will be moved over follow-up
smaller patches in the future (since this patch is already quite big).
So far, the code still only supports one BTS, which can be accessed
using the_pcu->bts. In the future that field will be replaced with a
list, and the BTS singletons will be removed.

The cur_fn output changes in TbfTest are actually a side effect fix,
since the singleton main_bts() now points internally to the_pcu->bts,
hence the same we allocate and assign in the test. Beforehand, "the_bts"
was allocated in the stack while main_bts() still returned an unrelated
singleton BTS object instance.

Related: OS#4935
Change-Id: I88e3c6471b80245ce3798223f1a61190f14aa840
This commit is contained in:
Pau Espin 2021-01-13 18:54:38 +01:00 committed by pespin
parent 695ce77167
commit ac3fd12026
24 changed files with 1005 additions and 787 deletions

View File

@ -49,6 +49,7 @@ libgprs_la_SOURCES = \
gprs_rlcmac_ts_alloc.cpp \ gprs_rlcmac_ts_alloc.cpp \
gprs_ms.c \ gprs_ms.c \
gprs_ms_storage.cpp \ gprs_ms_storage.cpp \
gprs_pcu.c \
gsm_timer.cpp \ gsm_timer.cpp \
pcu_l1_if.cpp \ pcu_l1_if.cpp \
pcu_vty.c \ pcu_vty.c \
@ -84,6 +85,7 @@ noinst_HEADERS = \
gprs_rlcmac.h \ gprs_rlcmac.h \
gprs_ms.h \ gprs_ms.h \
gprs_ms_storage.h \ gprs_ms_storage.h \
gprs_pcu.h \
pcu_l1_if.h \ pcu_l1_if.h \
gsm_timer.h \ gsm_timer.h \
pcu_vty.h \ pcu_vty.h \

View File

@ -68,8 +68,6 @@ extern "C" {
} }
} }
static BTS s_bts;
static struct osmo_tdef T_defs_bts[] = { static struct osmo_tdef T_defs_bts[] = {
{ .T=3142, .default_val=20, .unit=OSMO_TDEF_S, .desc="timer (s)", .val=0 }, { .T=3142, .default_val=20, .unit=OSMO_TDEF_S, .desc="timer (s)", .val=0 },
{ .T=3169, .default_val=5, .unit=OSMO_TDEF_S, .desc="Reuse of USF and TFI(s) after the MS uplink TBF assignment is invalid (s)", .val=0 }, { .T=3169, .default_val=5, .unit=OSMO_TDEF_S, .desc="Reuse of USF and TFI(s) after the MS uplink TBF assignment is invalid (s)", .val=0 },
@ -218,10 +216,6 @@ static void bts_init(struct gprs_rlcmac_bts *bts, BTS* bts_obj)
bts->cs_adj_enabled = 1; bts->cs_adj_enabled = 1;
bts->cs_adj_upper_limit = 33; /* Decrease CS if the error rate is above */ bts->cs_adj_upper_limit = 33; /* Decrease CS if the error rate is above */
bts->cs_adj_lower_limit = 10; /* Increase CS if the error rate is below */ bts->cs_adj_lower_limit = 10; /* Increase CS if the error rate is below */
bts->vty.max_cs_ul = MAX_GPRS_CS;
bts->vty.max_cs_dl = MAX_GPRS_CS;
bts->vty.max_mcs_ul = MAX_EDGE_MCS;
bts->vty.max_mcs_dl = MAX_EDGE_MCS;
/* CS-1 to CS-4 */ /* CS-1 to CS-4 */
bts->cs_lqual_ranges[0].low = -256; bts->cs_lqual_ranges[0].low = -256;
bts->cs_lqual_ranges[0].high = 6; bts->cs_lqual_ranges[0].high = 6;
@ -294,7 +288,7 @@ static void bts_init(struct gprs_rlcmac_bts *bts, BTS* bts_obj)
BTS* BTS::main_bts() BTS* BTS::main_bts()
{ {
return &s_bts; return the_pcu->bts;
} }
struct gprs_rlcmac_bts *BTS::bts_data() struct gprs_rlcmac_bts *BTS::bts_data()
@ -317,8 +311,9 @@ struct rate_ctr_group *bts_main_data_stats()
return BTS::main_bts()->rate_counters(); return BTS::main_bts()->rate_counters();
} }
BTS::BTS() BTS::BTS(struct gprs_pcu *pcu)
: m_cur_fn(0) : pcu(pcu)
, m_cur_fn(0)
, m_cur_blk_fn(-1) , m_cur_blk_fn(-1)
, m_max_cs_dl(MAX_GPRS_CS) , m_max_cs_dl(MAX_GPRS_CS)
, m_max_cs_ul(MAX_GPRS_CS) , m_max_cs_ul(MAX_GPRS_CS)
@ -540,7 +535,7 @@ void BTS::send_gsmtap_meas(enum pcu_gsmtap_category categ, bool uplink, uint8_t
uint16_t arfcn; uint16_t arfcn;
/* check if category is activated at all */ /* check if category is activated at all */
if (!(m_bts.gsmtap_categ_mask & (1 << categ))) if (!(pcu->gsmtap_categ_mask & (1 << categ)))
return; return;
arfcn = m_bts.trx[trx_no].arfcn; arfcn = m_bts.trx[trx_no].arfcn;
@ -550,7 +545,7 @@ void BTS::send_gsmtap_meas(enum pcu_gsmtap_category categ, bool uplink, uint8_t
/* GSMTAP needs the SNR here, but we only have C/I (meas->link_qual). /* GSMTAP needs the SNR here, but we only have C/I (meas->link_qual).
Those are not the same, but there is no known way to convert them, Those are not the same, but there is no known way to convert them,
let's pass C/I instead of nothing */ let's pass C/I instead of nothing */
gsmtap_send(m_bts.gsmtap, arfcn, ts_no, channel, 0, fn, gsmtap_send(pcu->gsmtap, arfcn, ts_no, channel, 0, fn,
meas->rssi, meas->link_qual, data, len); meas->rssi, meas->link_qual, data, len);
} }
@ -1147,6 +1142,24 @@ GprsMs *BTS::ms_alloc(uint8_t ms_class, uint8_t egprs_ms_class)
return ms; return ms;
} }
static int bts_talloc_destructor(struct BTS* bts)
{
bts->~BTS();
return 0;
}
struct BTS* bts_alloc(struct gprs_pcu *pcu)
{
struct BTS* bts;
bts = talloc(pcu, struct BTS);
if (!bts)
return bts;
talloc_set_destructor(bts, bts_talloc_destructor);
new (bts) BTS(pcu);
return bts;
}
/* update TA based on TA provided by PH-DATA-IND */ /* update TA based on TA provided by PH-DATA-IND */
void update_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, int8_t ta_delta) void update_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, int8_t ta_delta)
{ {
@ -1224,22 +1237,22 @@ void bts_trx_unreserve_slots(struct gprs_rlcmac_trx *trx, enum gprs_rlcmac_tbf_d
trx->pdch[i].unreserve(dir); trx->pdch[i].unreserve(dir);
} }
void bts_set_max_cs(struct gprs_rlcmac_bts *bts, uint8_t cs_dl, uint8_t cs_ul) void bts_recalc_max_cs(struct gprs_rlcmac_bts *bts)
{ {
int i; int i;
uint8_t cs_dl, cs_ul;
struct gprs_pcu *pcu = bts->bts->pcu;
bts->vty.max_cs_dl = cs_dl;
cs_dl = 0; cs_dl = 0;
for (i = bts->vty.max_cs_dl - 1; i >= 0; i--) { for (i = pcu->vty.max_cs_dl - 1; i >= 0; i--) {
if (bts->cs_mask & (1 << i)) { if (bts->cs_mask & (1 << i)) {
cs_dl = i + 1; cs_dl = i + 1;
break; break;
} }
} }
bts->vty.max_cs_ul = cs_ul;
cs_ul = 0; cs_ul = 0;
for (i = bts->vty.max_cs_ul - 1; i >= 0; i--) { for (i = pcu->vty.max_cs_ul - 1; i >= 0; i--) {
if (bts->cs_mask & (1 << i)) { if (bts->cs_mask & (1 << i)) {
cs_ul = i + 1; cs_ul = i + 1;
break; break;
@ -1251,22 +1264,22 @@ void bts_set_max_cs(struct gprs_rlcmac_bts *bts, uint8_t cs_dl, uint8_t cs_ul)
bts->bts->set_max_cs_ul(cs_ul); bts->bts->set_max_cs_ul(cs_ul);
} }
void bts_set_max_mcs(struct gprs_rlcmac_bts *bts, uint8_t mcs_dl, uint8_t mcs_ul) void bts_recalc_max_mcs(struct gprs_rlcmac_bts *bts)
{ {
int i; int i;
uint8_t mcs_dl, mcs_ul;
struct gprs_pcu *pcu = bts->bts->pcu;
bts->vty.max_mcs_dl = mcs_dl;
mcs_dl = 0; mcs_dl = 0;
for (i = bts->vty.max_mcs_dl - 1; i >= 0; i--) { for (i = pcu->vty.max_mcs_dl - 1; i >= 0; i--) {
if (bts->mcs_mask & (1 << i)) { if (bts->mcs_mask & (1 << i)) {
mcs_dl = i + 1; mcs_dl = i + 1;
break; break;
} }
} }
bts->vty.max_mcs_ul = mcs_ul;
mcs_ul = 0; mcs_ul = 0;
for (i = bts->vty.max_mcs_ul - 1; i >= 0; i--) { for (i = pcu->vty.max_mcs_ul - 1; i >= 0; i--) {
if (bts->mcs_mask & (1 << i)) { if (bts->mcs_mask & (1 << i)) {
mcs_ul = i + 1; mcs_ul = i + 1;
break; break;

View File

@ -35,6 +35,7 @@ extern "C" {
#include <osmocom/gsm/gsm48.h> #include <osmocom/gsm/gsm48.h>
#include "mslot_class.h" #include "mslot_class.h"
#include "gsm_rlcmac.h" #include "gsm_rlcmac.h"
#include "gprs_pcu.h"
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
@ -52,32 +53,6 @@ extern "C" {
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#define LLC_CODEL_DISABLE 0
#define LLC_CODEL_USE_DEFAULT (-1)
#define MAX_EDGE_MCS 9
#define MAX_GPRS_CS 4
/* see bts->gsmtap_categ_mask */
enum pcu_gsmtap_category {
PCU_GSMTAP_C_DL_UNKNOWN = 0, /* unknown or undecodable downlink blocks */
PCU_GSMTAP_C_DL_DUMMY = 1, /* downlink dummy blocks */
PCU_GSMTAP_C_DL_CTRL = 2, /* downlink control blocks */
PCU_GSMTAP_C_DL_DATA_GPRS = 3, /* downlink GPRS data blocks */
PCU_GSMTAP_C_DL_DATA_EGPRS = 4, /* downlink EGPRS data blocks */
PCU_GSMTAP_C_DL_PTCCH = 5, /* downlink PTCCH blocks */
PCU_GSMTAP_C_DL_AGCH = 6, /* downlink AGCH blocks */
PCU_GSMTAP_C_DL_PCH = 7, /* downlink PCH blocks */
PCU_GSMTAP_C_UL_UNKNOWN = 15, /* unknown or undecodable uplink blocks */
PCU_GSMTAP_C_UL_DUMMY = 16, /* uplink dummy blocks */
PCU_GSMTAP_C_UL_CTRL = 17, /* uplink control blocks */
PCU_GSMTAP_C_UL_DATA_GPRS = 18, /* uplink GPRS data blocks */
PCU_GSMTAP_C_UL_DATA_EGPRS = 19, /* uplink EGPRS data blocks */
PCU_GSMTAP_C_UL_RACH = 20, /* uplink RACH bursts */
PCU_GSMTAP_C_UL_PTCCH = 21, /* uplink PTCCH bursts */
};
struct BTS; struct BTS;
struct GprsMs; struct GprsMs;
@ -120,12 +95,6 @@ struct gprs_rlcmac_bts {
uint16_t mcs_mask; /* Allowed MCS mask from BTS */ uint16_t mcs_mask; /* Allowed MCS mask from BTS */
uint8_t initial_cs_dl, initial_cs_ul; uint8_t initial_cs_dl, initial_cs_ul;
uint8_t initial_mcs_dl, initial_mcs_ul; uint8_t initial_mcs_dl, initial_mcs_ul;
struct { /* Config Values set by VTY */
bool force_initial_cs; /* false=use from BTS true=use from VTY */
bool force_initial_mcs; /* false=use from BTS true=use from VTY */
uint8_t max_cs_dl, max_cs_ul;
uint8_t max_mcs_dl, max_mcs_ul;
} vty;
uint16_t force_llc_lifetime; /* overrides lifetime from SGSN */ uint16_t force_llc_lifetime; /* overrides lifetime from SGSN */
uint32_t llc_discard_csec; uint32_t llc_discard_csec;
uint32_t llc_idle_ack_csec; uint32_t llc_idle_ack_csec;
@ -136,11 +105,7 @@ struct gprs_rlcmac_bts {
uint8_t n3101; uint8_t n3101;
uint8_t n3103; uint8_t n3103;
uint8_t n3105; uint8_t n3105;
struct gsmtap_inst *gsmtap;
uint32_t gsmtap_categ_mask;
struct gprs_rlcmac_trx trx[8]; struct gprs_rlcmac_trx trx[8];
int (*alloc_algorithm)(struct gprs_rlcmac_bts *bts, struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf,
bool single, int8_t use_tbf);
uint8_t force_two_phase; uint8_t force_two_phase;
uint8_t alpha, gamma; uint8_t alpha, gamma;
@ -171,9 +136,6 @@ struct gprs_rlcmac_bts {
*/ */
struct BTS *bts; struct BTS *bts;
/* Path to be used for the pcu-bts socket */
char *pcu_sock_path;
/* Are we talking Gb with IP-SNS (true) or classic Gb? */ /* Are we talking Gb with IP-SNS (true) or classic Gb? */
enum gprs_ns2_dialect ns_dialect; enum gprs_ns2_dialect ns_dialect;
@ -182,7 +144,6 @@ struct gprs_rlcmac_bts {
struct msgb *app_info; struct msgb *app_info;
uint32_t app_info_pending; /* Count of MS with active TBF, to which we did not send app_info yet */ uint32_t app_info_pending; /* Count of MS with active TBF, to which we did not send app_info yet */
struct gprs_ns2_inst *nsi;
/* main nsei */ /* main nsei */
struct gprs_ns2_nse *nse; struct gprs_ns2_nse *nse;
}; };
@ -304,7 +265,7 @@ struct chan_req_params {
*/ */
struct BTS { struct BTS {
public: public:
BTS(); BTS(struct gprs_pcu *pcu);
~BTS(); ~BTS();
void cleanup(); void cleanup();
@ -373,7 +334,11 @@ public:
LListHead<gprs_rlcmac_tbf>& dl_tbfs(); LListHead<gprs_rlcmac_tbf>& dl_tbfs();
struct gprs_rlcmac_bts m_bts; struct gprs_rlcmac_bts m_bts;
/* back pointer to PCU object */
struct gprs_pcu *pcu;
private: private:
int m_cur_fn; int m_cur_fn;
int m_cur_blk_fn; int m_cur_blk_fn;
uint8_t m_max_cs_dl, m_max_cs_ul; uint8_t m_max_cs_dl, m_max_cs_ul;
@ -453,6 +418,8 @@ inline void BTS::stat_item_add(unsigned int stat_id, int inc) {
osmo_stat_item_set(m_statg->items[stat_id], val + inc); osmo_stat_item_set(m_statg->items[stat_id], val + inc);
} }
struct gprs_pcu;
struct BTS* bts_alloc(struct gprs_pcu *pcu);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
@ -463,8 +430,8 @@ extern "C" {
struct gprs_rlcmac_bts *bts_main_data(); struct gprs_rlcmac_bts *bts_main_data();
struct rate_ctr_group *bts_main_data_stats(); struct rate_ctr_group *bts_main_data_stats();
struct osmo_stat_item_group *bts_main_data_stat_items(); struct osmo_stat_item_group *bts_main_data_stat_items();
void bts_set_max_cs(struct gprs_rlcmac_bts *bts, uint8_t cs_dl, uint8_t cs_ul); void bts_recalc_max_cs(struct gprs_rlcmac_bts *bts);
void bts_set_max_mcs(struct gprs_rlcmac_bts *bts, uint8_t mcs_dl, uint8_t mcs_ul); void bts_recalc_max_mcs(struct gprs_rlcmac_bts *bts);
struct GprsMs *bts_ms_by_imsi(struct BTS *bts, const char *imsi); struct GprsMs *bts_ms_by_imsi(struct BTS *bts, const char *imsi);
uint8_t bts_max_cs_dl(const struct BTS *bts); uint8_t bts_max_cs_dl(const struct BTS *bts);
uint8_t bts_max_cs_ul(const struct BTS *bts); uint8_t bts_max_cs_ul(const struct BTS *bts);

View File

@ -46,8 +46,6 @@ extern "C" {
#define FC_MAX_BUCKET_LEAK_RATE (6553500 / 8) /* Byte/s */ #define FC_MAX_BUCKET_LEAK_RATE (6553500 / 8) /* Byte/s */
#define FC_MAX_BUCKET_SIZE 6553500 /* Octets */ #define FC_MAX_BUCKET_SIZE 6553500 /* Octets */
static struct gprs_bssgp_pcu the_pcu = { 0, };
extern void *tall_pcu_ctx; extern void *tall_pcu_ctx;
extern uint16_t spoof_mcc, spoof_mnc; extern uint16_t spoof_mcc, spoof_mnc;
extern bool spoof_mnc_3_digits; extern bool spoof_mnc_3_digits;
@ -167,7 +165,7 @@ static int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
LOGP(DBSSGP, LOGL_INFO, "LLC [SGSN -> PCU] = TLLI: 0x%08x IMSI: %s len: %d\n", tlli, mi_imsi.imsi, len); LOGP(DBSSGP, LOGL_INFO, "LLC [SGSN -> PCU] = TLLI: 0x%08x IMSI: %s len: %d\n", tlli, mi_imsi.imsi, len);
return gprs_rlcmac_dl_tbf::handle(the_pcu.bts, tlli, tlli_old, mi_imsi.imsi, return gprs_rlcmac_dl_tbf::handle(the_pcu->bssgp.bts, tlli, tlli_old, mi_imsi.imsi,
ms_class, egprs_ms_class, delay_csec, data, len); ms_class, egprs_ms_class, delay_csec, data, len);
} }
@ -270,8 +268,8 @@ static int gprs_bssgp_pcu_rx_ptp(struct msgb *msg, struct tlv_parsed *tp, struct
break; break;
case BSSGP_PDUT_DL_UNITDATA: case BSSGP_PDUT_DL_UNITDATA:
LOGP(DBSSGP, LOGL_DEBUG, "Rx BSSGP BVCI=%d (PTP) DL_UNITDATA\n", bvci); LOGP(DBSSGP, LOGL_DEBUG, "Rx BSSGP BVCI=%d (PTP) DL_UNITDATA\n", bvci);
if (the_pcu.on_dl_unit_data) if (the_pcu->bssgp.on_dl_unit_data)
the_pcu.on_dl_unit_data(&the_pcu, msg, tp); the_pcu->bssgp.on_dl_unit_data(&the_pcu->bssgp, msg, tp);
gprs_bssgp_pcu_rx_dl_ud(msg, tp); gprs_bssgp_pcu_rx_dl_ud(msg, tp);
break; break;
case BSSGP_PDUT_FLOW_CONTROL_BVC_ACK: case BSSGP_PDUT_FLOW_CONTROL_BVC_ACK:
@ -340,10 +338,10 @@ static int gprs_bssgp_pcu_rx_sign(struct msgb *msg, struct tlv_parsed *tp, struc
break; break;
case BSSGP_PDUT_BVC_RESET_ACK: case BSSGP_PDUT_BVC_RESET_ACK:
LOGP(DBSSGP, LOGL_NOTICE, "Rx BSSGP BVCI=%d (SIGN) BVC_RESET_ACK\n", bvci); LOGP(DBSSGP, LOGL_NOTICE, "Rx BSSGP BVCI=%d (SIGN) BVC_RESET_ACK\n", bvci);
if (!the_pcu.bvc_sig_reset) if (!the_pcu->bssgp.bvc_sig_reset)
the_pcu.bvc_sig_reset = 1; the_pcu->bssgp.bvc_sig_reset = 1;
else else
the_pcu.bvc_reset = 1; the_pcu->bssgp.bvc_reset = 1;
bvc_timeout(NULL); bvc_timeout(NULL);
break; break;
case BSSGP_PDUT_PAGING_CS: case BSSGP_PDUT_PAGING_CS:
@ -354,9 +352,9 @@ static int gprs_bssgp_pcu_rx_sign(struct msgb *msg, struct tlv_parsed *tp, struc
break; break;
case BSSGP_PDUT_BVC_UNBLOCK_ACK: case BSSGP_PDUT_BVC_UNBLOCK_ACK:
LOGP(DBSSGP, LOGL_NOTICE, "Rx BSSGP BVCI=%d (SIGN) BVC_UNBLOCK_ACK\n", bvci); LOGP(DBSSGP, LOGL_NOTICE, "Rx BSSGP BVCI=%d (SIGN) BVC_UNBLOCK_ACK\n", bvci);
the_pcu.bvc_unblocked = 1; the_pcu->bssgp.bvc_unblocked = 1;
if (the_pcu.on_unblock_ack) if (the_pcu->bssgp.on_unblock_ack)
the_pcu.on_unblock_ack(&the_pcu); the_pcu->bssgp.on_unblock_ack(&the_pcu->bssgp);
bvc_timeout(NULL); bvc_timeout(NULL);
break; break;
case BSSGP_PDUT_SUSPEND_NACK: case BSSGP_PDUT_SUSPEND_NACK:
@ -516,15 +514,15 @@ static void handle_nm_status(struct osmo_bssgp_prim *bp)
switch (cause) { switch (cause) {
case BSSGP_CAUSE_BVCI_BLOCKED: case BSSGP_CAUSE_BVCI_BLOCKED:
if (the_pcu.bvc_unblocked) { if (the_pcu->bssgp.bvc_unblocked) {
the_pcu.bvc_unblocked = 0; the_pcu->bssgp.bvc_unblocked = 0;
bvc_timeout(NULL); bvc_timeout(NULL);
} }
break; break;
case BSSGP_CAUSE_UNKNOWN_BVCI: case BSSGP_CAUSE_UNKNOWN_BVCI:
if (the_pcu.bvc_reset) { if (the_pcu->bssgp.bvc_reset) {
the_pcu.bvc_reset = 0; the_pcu->bssgp.bvc_reset = 0;
bvc_timeout(NULL); bvc_timeout(NULL);
} }
break; break;
@ -557,21 +555,21 @@ void gprs_ns_prim_status_cb(struct osmo_gprs_ns2_prim *nsp)
break; break;
case NS_AFF_CAUSE_RECOVERY: case NS_AFF_CAUSE_RECOVERY:
LOGP(DPCU, LOGL_NOTICE, "NS-NSE %d became available\n", nsp->nsei); LOGP(DPCU, LOGL_NOTICE, "NS-NSE %d became available\n", nsp->nsei);
if (!the_pcu.nsvc_unblocked) { if (!the_pcu->bssgp.nsvc_unblocked) {
the_pcu.bvc_sig_reset = 0; the_pcu->bssgp.bvc_sig_reset = 0;
the_pcu.bvc_reset = 0; the_pcu->bssgp.bvc_reset = 0;
the_pcu.nsvc_unblocked = 1; the_pcu->bssgp.nsvc_unblocked = 1;
bvc_timeout(NULL); bvc_timeout(NULL);
} }
break; break;
case NS_AFF_CAUSE_FAILURE: case NS_AFF_CAUSE_FAILURE:
LOGP(DPCU, LOGL_NOTICE, "NS-NSE %d became unavailable\n", nsp->nsei); LOGP(DPCU, LOGL_NOTICE, "NS-NSE %d became unavailable\n", nsp->nsei);
if (the_pcu.nsvc_unblocked) { if (the_pcu->bssgp.nsvc_unblocked) {
the_pcu.nsvc_unblocked = 0; the_pcu->bssgp.nsvc_unblocked = 0;
osmo_timer_del(&the_pcu.bvc_timer); osmo_timer_del(&the_pcu->bssgp.bvc_timer);
the_pcu.bvc_sig_reset = 0; the_pcu->bssgp.bvc_sig_reset = 0;
the_pcu.bvc_reset = 0; the_pcu->bssgp.bvc_reset = 0;
the_pcu.bvc_unblocked = 0; the_pcu->bssgp.bvc_unblocked = 0;
} }
break; break;
case NS_AFF_CAUSE_SNS_FAILURE: case NS_AFF_CAUSE_SNS_FAILURE:
@ -700,17 +698,17 @@ static uint32_t compute_bucket_size(struct gprs_rlcmac_bts *bts,
static uint32_t get_and_reset_avg_queue_delay(void) static uint32_t get_and_reset_avg_queue_delay(void)
{ {
struct timespec *delay_sum = &the_pcu.queue_delay_sum; struct timespec *delay_sum = &the_pcu->bssgp.queue_delay_sum;
uint32_t delay_sum_ms = delay_sum->tv_sec * 1000 + uint32_t delay_sum_ms = delay_sum->tv_sec * 1000 +
delay_sum->tv_nsec / 1000000000; delay_sum->tv_nsec / 1000000000;
uint32_t avg_delay_ms = 0; uint32_t avg_delay_ms = 0;
if (the_pcu.queue_delay_count > 0) if (the_pcu->bssgp.queue_delay_count > 0)
avg_delay_ms = delay_sum_ms / the_pcu.queue_delay_count; avg_delay_ms = delay_sum_ms / the_pcu->bssgp.queue_delay_count;
/* Reset accumulator */ /* Reset accumulator */
delay_sum->tv_sec = delay_sum->tv_nsec = 0; delay_sum->tv_sec = delay_sum->tv_nsec = 0;
the_pcu.queue_delay_count = 0; the_pcu->bssgp.queue_delay_count = 0;
return avg_delay_ms; return avg_delay_ms;
} }
@ -719,24 +717,24 @@ static int get_and_reset_measured_leak_rate(int *usage_by_1000, unsigned num_pdc
{ {
int rate; /* byte per second */ int rate; /* byte per second */
if (the_pcu.queue_frames_sent == 0) if (the_pcu->bssgp.queue_frames_sent == 0)
return -1; return -1;
if (the_pcu.queue_frames_recv == 0) if (the_pcu->bssgp.queue_frames_recv == 0)
return -1; return -1;
*usage_by_1000 = the_pcu.queue_frames_recv * 1000 / *usage_by_1000 = the_pcu->bssgp.queue_frames_recv * 1000 /
the_pcu.queue_frames_sent; the_pcu->bssgp.queue_frames_sent;
/* 20ms/num_pdch is the average RLC block duration, so the rate is /* 20ms/num_pdch is the average RLC block duration, so the rate is
* calculated as: * calculated as:
* rate = bytes_recv / (block_dur * block_count) */ * rate = bytes_recv / (block_dur * block_count) */
rate = the_pcu.queue_bytes_recv * 1000 * num_pdch / rate = the_pcu->bssgp.queue_bytes_recv * 1000 * num_pdch /
(20 * the_pcu.queue_frames_recv); (20 * the_pcu->bssgp.queue_frames_recv);
the_pcu.queue_frames_sent = 0; the_pcu->bssgp.queue_frames_sent = 0;
the_pcu.queue_bytes_recv = 0; the_pcu->bssgp.queue_bytes_recv = 0;
the_pcu.queue_frames_recv = 0; the_pcu->bssgp.queue_frames_recv = 0;
return rate; return rate;
} }
@ -805,7 +803,7 @@ static int gprs_bssgp_tx_fc_bvc(void)
int num_pdch = -1; int num_pdch = -1;
enum CodingScheme max_cs_dl; enum CodingScheme max_cs_dl;
if (!the_pcu.bctx) { if (!the_pcu->bssgp.bctx) {
LOGP(DBSSGP, LOGL_ERROR, "No bctx\n"); LOGP(DBSSGP, LOGL_ERROR, "No bctx\n");
return -EIO; return -EIO;
} }
@ -896,7 +894,7 @@ static int gprs_bssgp_tx_fc_bvc(void)
avg_delay_ms = get_and_reset_avg_queue_delay(); avg_delay_ms = get_and_reset_avg_queue_delay();
/* Update tag */ /* Update tag */
the_pcu.fc_tag += 1; the_pcu->bssgp.fc_tag += 1;
LOGP(DBSSGP, LOGL_DEBUG, LOGP(DBSSGP, LOGL_DEBUG,
"Sending FLOW CONTROL BVC, Bmax = %d, R = %d, Bmax_MS = %d, " "Sending FLOW CONTROL BVC, Bmax = %d, R = %d, Bmax_MS = %d, "
@ -904,7 +902,7 @@ static int gprs_bssgp_tx_fc_bvc(void)
bucket_size, leak_rate, ms_bucket_size, ms_leak_rate, bucket_size, leak_rate, ms_bucket_size, ms_leak_rate,
avg_delay_ms); avg_delay_ms);
return bssgp_tx_fc_bvc(the_pcu.bctx, the_pcu.fc_tag, return bssgp_tx_fc_bvc(the_pcu->bssgp.bctx, the_pcu->bssgp.fc_tag,
bucket_size, leak_rate, bucket_size, leak_rate,
ms_bucket_size, ms_leak_rate, ms_bucket_size, ms_leak_rate,
NULL, &avg_delay_ms); NULL, &avg_delay_ms);
@ -913,36 +911,36 @@ static int gprs_bssgp_tx_fc_bvc(void)
static void bvc_timeout(void *_priv) static void bvc_timeout(void *_priv)
{ {
unsigned long secs; unsigned long secs;
if (!the_pcu.bvc_sig_reset) { if (!the_pcu->bssgp.bvc_sig_reset) {
LOGP(DBSSGP, LOGL_INFO, "Sending reset on BVCI 0\n"); LOGP(DBSSGP, LOGL_INFO, "Sending reset on BVCI 0\n");
bssgp_tx_bvc_reset(the_pcu.bctx, 0, BSSGP_CAUSE_OML_INTERV); bssgp_tx_bvc_reset(the_pcu->bssgp.bctx, 0, BSSGP_CAUSE_OML_INTERV);
secs = osmo_tdef_get(the_pcu.bts->T_defs_pcu, 2, OSMO_TDEF_S, -1); secs = osmo_tdef_get(the_pcu->bssgp.bts->T_defs_pcu, 2, OSMO_TDEF_S, -1);
osmo_timer_schedule(&the_pcu.bvc_timer, secs, 0); osmo_timer_schedule(&the_pcu->bssgp.bvc_timer, secs, 0);
return; return;
} }
if (!the_pcu.bvc_reset) { if (!the_pcu->bssgp.bvc_reset) {
LOGP(DBSSGP, LOGL_INFO, "Sending reset on BVCI %d\n", LOGP(DBSSGP, LOGL_INFO, "Sending reset on BVCI %d\n",
the_pcu.bctx->bvci); the_pcu->bssgp.bctx->bvci);
bssgp_tx_bvc_reset(the_pcu.bctx, the_pcu.bctx->bvci, BSSGP_CAUSE_OML_INTERV); bssgp_tx_bvc_reset(the_pcu->bssgp.bctx, the_pcu->bssgp.bctx->bvci, BSSGP_CAUSE_OML_INTERV);
secs = osmo_tdef_get(the_pcu.bts->T_defs_pcu, 2, OSMO_TDEF_S, -1); secs = osmo_tdef_get(the_pcu->bssgp.bts->T_defs_pcu, 2, OSMO_TDEF_S, -1);
osmo_timer_schedule(&the_pcu.bvc_timer, secs, 0); osmo_timer_schedule(&the_pcu->bssgp.bvc_timer, secs, 0);
return; return;
} }
if (!the_pcu.bvc_unblocked) { if (!the_pcu->bssgp.bvc_unblocked) {
LOGP(DBSSGP, LOGL_INFO, "Sending unblock on BVCI %d\n", LOGP(DBSSGP, LOGL_INFO, "Sending unblock on BVCI %d\n",
the_pcu.bctx->bvci); the_pcu->bssgp.bctx->bvci);
bssgp_tx_bvc_unblock(the_pcu.bctx); bssgp_tx_bvc_unblock(the_pcu->bssgp.bctx);
secs = osmo_tdef_get(the_pcu.bts->T_defs_pcu, 1, OSMO_TDEF_S, -1); secs = osmo_tdef_get(the_pcu->bssgp.bts->T_defs_pcu, 1, OSMO_TDEF_S, -1);
osmo_timer_schedule(&the_pcu.bvc_timer, secs, 0); osmo_timer_schedule(&the_pcu->bssgp.bvc_timer, secs, 0);
return; return;
} }
LOGP(DBSSGP, LOGL_DEBUG, "Sending flow control info on BVCI %d\n", LOGP(DBSSGP, LOGL_DEBUG, "Sending flow control info on BVCI %d\n",
the_pcu.bctx->bvci); the_pcu->bssgp.bctx->bvci);
gprs_bssgp_tx_fc_bvc(); gprs_bssgp_tx_fc_bvc();
osmo_timer_schedule(&the_pcu.bvc_timer, the_pcu.bts->fc_interval, 0); osmo_timer_schedule(&the_pcu->bssgp.bvc_timer, the_pcu->bssgp.bts->fc_interval, 0);
} }
static int ns_create_nsvc(struct gprs_rlcmac_bts *bts, static int ns_create_nsvc(struct gprs_rlcmac_bts *bts,
@ -966,9 +964,9 @@ static int ns_create_nsvc(struct gprs_rlcmac_bts *bts,
if (!(valid & (1 << i))) if (!(valid & (1 << i)))
continue; continue;
if (!gprs_ns2_ip_bind_by_sockaddr(bts->nsi, &local[i])) { if (!gprs_ns2_ip_bind_by_sockaddr(the_pcu->nsi, &local[i])) {
snprintf(name, sizeof(name), "pcu%d", i); snprintf(name, sizeof(name), "pcu%d", i);
rc = gprs_ns2_ip_bind(bts->nsi, name, &local[i], 0, &bind[i]); rc = gprs_ns2_ip_bind(the_pcu->nsi, name, &local[i], 0, &bind[i]);
if (rc < 0) { if (rc < 0) {
LOGP(DBSSGP, LOGL_ERROR, "Failed to bind to %s\n", osmo_sockaddr_to_str(&local[i])); LOGP(DBSSGP, LOGL_ERROR, "Failed to bind to %s\n", osmo_sockaddr_to_str(&local[i]));
continue; continue;
@ -983,14 +981,14 @@ static int ns_create_nsvc(struct gprs_rlcmac_bts *bts,
return -1; return -1;
} }
bts->nse = gprs_ns2_nse_by_nsei(bts->nsi, nsei); bts->nse = gprs_ns2_nse_by_nsei(the_pcu->nsi, nsei);
if (!bts->nse) if (!bts->nse)
bts->nse = gprs_ns2_create_nse(bts->nsi, nsei, bts->nse = gprs_ns2_create_nse(the_pcu->nsi, nsei,
GPRS_NS2_LL_UDP, bts->ns_dialect); GPRS_NS2_LL_UDP, bts->ns_dialect);
if (!bts->nse) { if (!bts->nse) {
LOGP(DBSSGP, LOGL_ERROR, "Failed to create NSE\n"); LOGP(DBSSGP, LOGL_ERROR, "Failed to create NSE\n");
gprs_ns2_free_binds(bts->nsi); gprs_ns2_free_binds(the_pcu->nsi);
return 1; return 1;
} }
@ -1060,13 +1058,13 @@ int gprs_ns_config(struct gprs_rlcmac_bts *bts, uint16_t nsei,
int rc = 0; int rc = 0;
if (!bts->nse) { if (!bts->nse) {
/* there shouldn't any previous state. */ /* there shouldn't any previous state. */
gprs_ns2_free_nses(bts->nsi); gprs_ns2_free_nses(the_pcu->nsi);
gprs_ns2_free_binds(bts->nsi); gprs_ns2_free_binds(the_pcu->nsi);
rc = ns_create_nsvc(bts, nsei, local, remote, nsvci, valid); rc = ns_create_nsvc(bts, nsei, local, remote, nsvci, valid);
} else if (nsei != gprs_ns2_nse_nsei(bts->nse)) { } else if (nsei != gprs_ns2_nse_nsei(bts->nse)) {
/* the NSEI has changed */ /* the NSEI has changed */
gprs_ns2_free_nses(bts->nsi); gprs_ns2_free_nses(the_pcu->nsi);
gprs_ns2_free_binds(bts->nsi); gprs_ns2_free_binds(the_pcu->nsi);
rc = ns_create_nsvc(bts, nsei, local, remote, nsvci, valid); rc = ns_create_nsvc(bts, nsei, local, remote, nsvci, valid);
} else if (bts->ns_dialect == NS2_DIALECT_SNS) { } else if (bts->ns_dialect == NS2_DIALECT_SNS) {
/* SNS: check if the initial nsvc is the same, if not recreate it */ /* SNS: check if the initial nsvc is the same, if not recreate it */
@ -1080,8 +1078,8 @@ int gprs_ns_config(struct gprs_rlcmac_bts *bts, uint16_t nsei,
return 0; return 0;
} }
gprs_ns2_free_nses(bts->nsi); gprs_ns2_free_nses(the_pcu->nsi);
gprs_ns2_free_binds(bts->nsi); gprs_ns2_free_binds(the_pcu->nsi);
rc = ns_create_nsvc(bts, nsei, local, remote, nsvci, valid); rc = ns_create_nsvc(bts, nsei, local, remote, nsvci, valid);
} else { } else {
/* check if all NSVC are still the same. */ /* check if all NSVC are still the same. */
@ -1119,75 +1117,75 @@ struct gprs_bssgp_pcu *gprs_bssgp_init(
{ {
/* if already created... return the current address */ /* if already created... return the current address */
if (the_pcu.bctx) if (the_pcu->bssgp.bctx)
return &the_pcu; return &the_pcu->bssgp;
the_pcu.bts = bts; the_pcu->bssgp.bts = bts;
the_pcu.bctx = btsctx_alloc(bvci, nsei); the_pcu->bssgp.bctx = btsctx_alloc(bvci, nsei);
if (!the_pcu.bctx) { if (!the_pcu->bssgp.bctx) {
LOGP(DBSSGP, LOGL_ERROR, "Failed to create BSSGP context\n"); LOGP(DBSSGP, LOGL_ERROR, "Failed to create BSSGP context\n");
the_pcu.bts->nse = NULL; the_pcu->bssgp.bts->nse = NULL;
return NULL; return NULL;
} }
the_pcu.bctx->ra_id.mcc = spoof_mcc ? : mcc; the_pcu->bssgp.bctx->ra_id.mcc = spoof_mcc ? : mcc;
if (spoof_mnc) { if (spoof_mnc) {
the_pcu.bctx->ra_id.mnc = spoof_mnc; the_pcu->bssgp.bctx->ra_id.mnc = spoof_mnc;
the_pcu.bctx->ra_id.mnc_3_digits = spoof_mnc_3_digits; the_pcu->bssgp.bctx->ra_id.mnc_3_digits = spoof_mnc_3_digits;
} else { } else {
the_pcu.bctx->ra_id.mnc = mnc; the_pcu->bssgp.bctx->ra_id.mnc = mnc;
the_pcu.bctx->ra_id.mnc_3_digits = mnc_3_digits; the_pcu->bssgp.bctx->ra_id.mnc_3_digits = mnc_3_digits;
} }
the_pcu.bctx->ra_id.lac = lac; the_pcu->bssgp.bctx->ra_id.lac = lac;
the_pcu.bctx->ra_id.rac = rac; the_pcu->bssgp.bctx->ra_id.rac = rac;
the_pcu.bctx->cell_id = cell_id; the_pcu->bssgp.bctx->cell_id = cell_id;
osmo_timer_setup(&the_pcu.bvc_timer, bvc_timeout, bts); osmo_timer_setup(&the_pcu->bssgp.bvc_timer, bvc_timeout, bts);
return &the_pcu; return &the_pcu->bssgp;
} }
void gprs_bssgp_destroy(struct gprs_rlcmac_bts *bts) void gprs_bssgp_destroy(struct gprs_rlcmac_bts *bts)
{ {
osmo_timer_del(&the_pcu.bvc_timer); osmo_timer_del(&the_pcu->bssgp.bvc_timer);
/* FIXME: blocking... */ /* FIXME: blocking... */
the_pcu.nsvc_unblocked = 0; the_pcu->bssgp.nsvc_unblocked = 0;
the_pcu.bvc_sig_reset = 0; the_pcu->bssgp.bvc_sig_reset = 0;
the_pcu.bvc_reset = 0; the_pcu->bssgp.bvc_reset = 0;
the_pcu.bvc_unblocked = 0; the_pcu->bssgp.bvc_unblocked = 0;
bssgp_bvc_ctx_free(the_pcu.bctx); bssgp_bvc_ctx_free(the_pcu->bssgp.bctx);
the_pcu.bctx = NULL; the_pcu->bssgp.bctx = NULL;
gprs_ns2_free(bts->nsi); gprs_ns2_free(the_pcu->nsi);
bts->nsi = NULL; the_pcu->nsi = NULL;
bts->nse = NULL; bts->nse = NULL;
} }
struct bssgp_bvc_ctx *gprs_bssgp_pcu_current_bctx(void) struct bssgp_bvc_ctx *gprs_bssgp_pcu_current_bctx(void)
{ {
return the_pcu.bctx; return the_pcu->bssgp.bctx;
} }
void gprs_bssgp_update_frames_sent() void gprs_bssgp_update_frames_sent()
{ {
the_pcu.queue_frames_sent += 1; the_pcu->bssgp.queue_frames_sent += 1;
} }
void gprs_bssgp_update_bytes_received(unsigned bytes_recv, unsigned frames_recv) void gprs_bssgp_update_bytes_received(unsigned bytes_recv, unsigned frames_recv)
{ {
the_pcu.queue_bytes_recv += bytes_recv; the_pcu->bssgp.queue_bytes_recv += bytes_recv;
the_pcu.queue_frames_recv += frames_recv; the_pcu->bssgp.queue_frames_recv += frames_recv;
} }
void gprs_bssgp_update_queue_delay(const struct timespec *tv_recv, void gprs_bssgp_update_queue_delay(const struct timespec *tv_recv,
const struct timespec *tv_now) const struct timespec *tv_now)
{ {
struct timespec *delay_sum = &the_pcu.queue_delay_sum; struct timespec *delay_sum = &the_pcu->bssgp.queue_delay_sum;
struct timespec tv_delay; struct timespec tv_delay;
timespecsub(tv_now, tv_recv, &tv_delay); timespecsub(tv_now, tv_recv, &tv_delay);
timespecadd(delay_sum, &tv_delay, delay_sum); timespecadd(delay_sum, &tv_delay, delay_sum);
the_pcu.queue_delay_count += 1; the_pcu->bssgp.queue_delay_count += 1;
} }

View File

@ -22,7 +22,9 @@
#define GPRS_BSSGP_PCU_H #define GPRS_BSSGP_PCU_H
#ifdef __cplusplus
extern "C" { extern "C" {
#endif
#include <osmocom/core/talloc.h> #include <osmocom/core/talloc.h>
#include <osmocom/core/rate_ctr.h> #include <osmocom/core/rate_ctr.h>
#include <osmocom/core/logging.h> #include <osmocom/core/logging.h>
@ -34,7 +36,7 @@ extern "C" {
#include <osmocom/gprs/gprs_msgb.h> #include <osmocom/gprs/gprs_msgb.h>
struct bssgp_bvc_ctx *btsctx_alloc(uint16_t bvci, uint16_t nsei); struct bssgp_bvc_ctx *btsctx_alloc(uint16_t bvci, uint16_t nsei);
}
#include <gprs_debug.h> #include <gprs_debug.h>
#include <time.h> #include <time.h>
@ -75,6 +77,14 @@ struct gprs_bssgp_pcu {
struct tlv_parsed *tp); struct tlv_parsed *tp);
}; };
int gprs_gp_send_cb(void *ctx, struct msgb *msg);
struct bssgp_bvc_ctx *gprs_bssgp_pcu_current_bctx(void);
int gprs_ns_prim_cb(struct osmo_prim_hdr *oph, void *ctx);
void gprs_bssgp_update_queue_delay(const struct timespec *tv_recv,
const struct timespec *tv_now);
void gprs_bssgp_update_frames_sent();
void gprs_bssgp_update_bytes_received(unsigned bytes_recv, unsigned frames_recv);
struct gprs_bssgp_pcu *gprs_bssgp_init( struct gprs_bssgp_pcu *gprs_bssgp_init(
struct gprs_rlcmac_bts *bts, struct gprs_rlcmac_bts *bts,
uint16_t nsei, uint16_t bvci, uint16_t nsei, uint16_t bvci,
@ -86,16 +96,10 @@ int gprs_ns_config(struct gprs_rlcmac_bts *bts, uint16_t nsei,
const struct osmo_sockaddr *remote, const struct osmo_sockaddr *remote,
uint16_t *nsvci, uint16_t valid); uint16_t *nsvci, uint16_t valid);
int gprs_ns_prim_cb(struct osmo_prim_hdr *oph, void *ctx);
int gprs_gp_send_cb(void *ctx, struct msgb *msg);
void gprs_bssgp_destroy(struct gprs_rlcmac_bts *bts); void gprs_bssgp_destroy(struct gprs_rlcmac_bts *bts);
struct bssgp_bvc_ctx *gprs_bssgp_pcu_current_bctx(void); #ifdef __cplusplus
}
void gprs_bssgp_update_queue_delay(const struct timespec *tv_recv, #endif
const struct timespec *tv_now);
void gprs_bssgp_update_frames_sent();
void gprs_bssgp_update_bytes_received(unsigned bytes_recv, unsigned frames_recv);
#endif // GPRS_BSSGP_PCU_H #endif // GPRS_BSSGP_PCU_H

61
src/gprs_pcu.c Normal file
View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2013 by Holger Hans Peter Freyther
* Copyright (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* Author: Pau Espin Pedrol <pespin@sysmocom.de>
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <osmocom/core/utils.h>
#include "gprs_pcu.h"
#include "bts.h"
struct gprs_pcu *the_pcu;
struct gprs_pcu *gprs_pcu_alloc(void *ctx)
{
struct gprs_pcu *pcu;
pcu = (struct gprs_pcu *)talloc_zero(ctx, struct gprs_pcu);
OSMO_ASSERT(pcu);
pcu->vty.max_cs_ul = MAX_GPRS_CS;
pcu->vty.max_cs_dl = MAX_GPRS_CS;
pcu->vty.max_mcs_ul = MAX_EDGE_MCS;
pcu->vty.max_mcs_dl = MAX_EDGE_MCS;
return pcu;
}
void gprs_pcu_set_max_cs(struct gprs_pcu *pcu, uint8_t cs_dl, uint8_t cs_ul)
{
the_pcu->vty.max_cs_dl = cs_dl;
the_pcu->vty.max_cs_ul = cs_ul;
/*TODO: once we support multiple bts, foreach(bts) apply */
struct gprs_rlcmac_bts *bts = bts_data(pcu->bts);
bts_recalc_max_cs(bts);
}
void gprs_pcu_set_max_mcs(struct gprs_pcu *pcu, uint8_t mcs_dl, uint8_t mcs_ul)
{
the_pcu->vty.max_mcs_dl = mcs_dl;
the_pcu->vty.max_mcs_ul = mcs_ul;
/* TODO: once we support multiple bts, foreach(bts) apply */
struct gprs_rlcmac_bts *bts = bts_data(pcu->bts);
bts_recalc_max_mcs(bts);
}

97
src/gprs_pcu.h Normal file
View File

@ -0,0 +1,97 @@
/*
* Copyright (C) 2013 by Holger Hans Peter Freyther
* Copyright (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* Author: Pau Espin Pedrol <pespin@sysmocom.de>
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <osmocom/core/gsmtap_util.h>
#include "gprs_bssgp_pcu.h"
#define LLC_CODEL_DISABLE 0
#define LLC_CODEL_USE_DEFAULT (-1)
#define MAX_EDGE_MCS 9
#define MAX_GPRS_CS 4
/* see bts->gsmtap_categ_mask */
enum pcu_gsmtap_category {
PCU_GSMTAP_C_DL_UNKNOWN = 0, /* unknown or undecodable downlink blocks */
PCU_GSMTAP_C_DL_DUMMY = 1, /* downlink dummy blocks */
PCU_GSMTAP_C_DL_CTRL = 2, /* downlink control blocks */
PCU_GSMTAP_C_DL_DATA_GPRS = 3, /* downlink GPRS data blocks */
PCU_GSMTAP_C_DL_DATA_EGPRS = 4, /* downlink EGPRS data blocks */
PCU_GSMTAP_C_DL_PTCCH = 5, /* downlink PTCCH blocks */
PCU_GSMTAP_C_DL_AGCH = 6, /* downlink AGCH blocks */
PCU_GSMTAP_C_DL_PCH = 7, /* downlink PCH blocks */
PCU_GSMTAP_C_UL_UNKNOWN = 15, /* unknown or undecodable uplink blocks */
PCU_GSMTAP_C_UL_DUMMY = 16, /* uplink dummy blocks */
PCU_GSMTAP_C_UL_CTRL = 17, /* uplink control blocks */
PCU_GSMTAP_C_UL_DATA_GPRS = 18, /* uplink GPRS data blocks */
PCU_GSMTAP_C_UL_DATA_EGPRS = 19, /* uplink EGPRS data blocks */
PCU_GSMTAP_C_UL_RACH = 20, /* uplink RACH bursts */
PCU_GSMTAP_C_UL_PTCCH = 21, /* uplink PTCCH bursts */
};
struct BTS;
struct gprs_rlcmac_bts;
struct GprsMs;
struct gprs_rlcmac_tbf;
typedef int (*alloc_algorithm_func_t)(struct gprs_rlcmac_bts *bts,
struct GprsMs *ms,
struct gprs_rlcmac_tbf *tbf,
bool single, int8_t use_tbf);
struct gprs_pcu {
/* Path to be used for the pcu-bts socket */
char *pcu_sock_path;
struct { /* Config Values set by VTY */
bool force_initial_cs; /* false=use from BTS true=use from VTY */
bool force_initial_mcs; /* false=use from BTS true=use from VTY */
uint8_t max_cs_dl, max_cs_ul;
uint8_t max_mcs_dl, max_mcs_ul;
} vty;
struct gsmtap_inst *gsmtap;
uint32_t gsmtap_categ_mask;
struct BTS *bts;
struct gprs_ns2_inst *nsi;
alloc_algorithm_func_t alloc_algorithm;
struct gprs_bssgp_pcu bssgp;
};
extern struct gprs_pcu *the_pcu;
struct gprs_pcu *gprs_pcu_alloc(void *ctx);
void gprs_pcu_set_max_cs(struct gprs_pcu *pcu, uint8_t cs_dl, uint8_t cs_ul);
void gprs_pcu_set_max_mcs(struct gprs_pcu *pcu, uint8_t mcs_dl, uint8_t mcs_ul);

View File

@ -1018,7 +1018,7 @@ int gprs_alloc_max_dl_slots_per_ms(const struct gprs_rlcmac_bts *bts, uint8_t ms
if (rx == MS_NA) if (rx == MS_NA)
rx = 4; rx = 4;
if (bts->alloc_algorithm == alloc_algorithm_a) if (the_pcu->alloc_algorithm == alloc_algorithm_a)
return 1; return 1;
if (bts->multislot_disabled) if (bts->multislot_disabled)

View File

@ -206,18 +206,16 @@ static int pcu_sock_cb(struct osmo_fd *bfd, unsigned int flags)
int pcu_l1if_open(void) int pcu_l1if_open(void)
{ {
int rc; int rc;
struct gprs_rlcmac_bts *bts = bts_main_data();
LOGP(DL1IF, LOGL_INFO, "Opening OsmoPCU L1 interface to OsmoBTS\n"); LOGP(DL1IF, LOGL_INFO, "Opening OsmoPCU L1 interface to OsmoBTS\n");
memset(&pcu_sock_state, 0x00, sizeof(pcu_sock_state)); memset(&pcu_sock_state, 0x00, sizeof(pcu_sock_state));
INIT_LLIST_HEAD(&pcu_sock_state.upqueue); INIT_LLIST_HEAD(&pcu_sock_state.upqueue);
rc = osmo_sock_unix_init_ofd(&pcu_sock_state.conn_bfd, SOCK_SEQPACKET, 0, rc = osmo_sock_unix_init_ofd(&pcu_sock_state.conn_bfd, SOCK_SEQPACKET, 0,
bts->pcu_sock_path, OSMO_SOCK_F_CONNECT); the_pcu->pcu_sock_path, OSMO_SOCK_F_CONNECT);
if (rc < 0) { if (rc < 0) {
LOGP(DL1IF, LOGL_ERROR, "Failed to connect to the BTS (%s). " LOGP(DL1IF, LOGL_ERROR, "Failed to connect to the BTS (%s). "
"Retrying...\n", bts->pcu_sock_path); "Retrying...\n", the_pcu->pcu_sock_path);
osmo_timer_setup(&pcu_sock_state.timer, pcu_sock_timeout, NULL); osmo_timer_setup(&pcu_sock_state.timer, pcu_sock_timeout, NULL);
osmo_timer_schedule(&pcu_sock_state.timer, 5, 0); osmo_timer_schedule(&pcu_sock_state.timer, 5, 0);
return 0; return 0;
@ -227,7 +225,7 @@ int pcu_l1if_open(void)
pcu_sock_state.conn_bfd.data = NULL; pcu_sock_state.conn_bfd.data = NULL;
LOGP(DL1IF, LOGL_NOTICE, "osmo-bts PCU socket %s has been connected\n", LOGP(DL1IF, LOGL_NOTICE, "osmo-bts PCU socket %s has been connected\n",
bts->pcu_sock_path); the_pcu->pcu_sock_path);
pcu_tx_txt_ind(PCU_VERSION, "%s", PACKAGE_VERSION); pcu_tx_txt_ind(PCU_VERSION, "%s", PACKAGE_VERSION);

View File

@ -214,14 +214,13 @@ void pcu_l1if_tx_pdtch(msgb *msg, uint8_t trx, uint8_t ts, uint16_t arfcn,
msgb_free(msg); msgb_free(msg);
} }
void pcu_l1if_tx_ptcch(uint8_t trx, uint8_t ts, uint16_t arfcn, void pcu_l1if_tx_ptcch(struct gprs_rlcmac_bts *bts,
uint8_t trx, uint8_t ts, uint16_t arfcn,
uint32_t fn, uint8_t block_nr, uint32_t fn, uint8_t block_nr,
uint8_t *data, size_t data_len) uint8_t *data, size_t data_len)
{ {
struct gprs_rlcmac_bts *bts = bts_main_data(); if (the_pcu->gsmtap_categ_mask & (1 << PCU_GSMTAP_C_DL_PTCCH))
gsmtap_send(the_pcu->gsmtap, arfcn, ts, GSMTAP_CHANNEL_PTCCH, 0, fn, 0, 0, data, data_len);
if (bts->gsmtap_categ_mask & (1 << PCU_GSMTAP_C_DL_PTCCH))
gsmtap_send(bts->gsmtap, arfcn, ts, GSMTAP_CHANNEL_PTCCH, 0, fn, 0, 0, data, data_len);
#ifdef ENABLE_DIRECT_PHY #ifdef ENABLE_DIRECT_PHY
if (bts->trx[trx].fl1h) { if (bts->trx[trx].fl1h) {
l1if_pdch_req(bts->trx[trx].fl1h, ts, 1, fn, arfcn, block_nr, data, data_len); l1if_pdch_req(bts->trx[trx].fl1h, ts, 1, fn, arfcn, block_nr, data, data_len);
@ -233,22 +232,20 @@ void pcu_l1if_tx_ptcch(uint8_t trx, uint8_t ts, uint16_t arfcn,
void pcu_l1if_tx_agch(bitvec * block, int plen) void pcu_l1if_tx_agch(bitvec * block, int plen)
{ {
struct gprs_rlcmac_bts *bts = bts_main_data();
uint8_t data[GSM_MACBLOCK_LEN]; /* prefix PLEN */ uint8_t data[GSM_MACBLOCK_LEN]; /* prefix PLEN */
/* FIXME: why does OpenBTS has no PLEN and no fill in message? */ /* FIXME: why does OpenBTS has no PLEN and no fill in message? */
bitvec_pack(block, data + 1); bitvec_pack(block, data + 1);
data[0] = (plen << 2) | 0x01; data[0] = (plen << 2) | 0x01;
if (bts->gsmtap_categ_mask & (1 << PCU_GSMTAP_C_DL_AGCH)) if (the_pcu->gsmtap_categ_mask & (1 << PCU_GSMTAP_C_DL_AGCH))
gsmtap_send(bts->gsmtap, 0, 0, GSMTAP_CHANNEL_AGCH, 0, 0, 0, 0, data, GSM_MACBLOCK_LEN); gsmtap_send(the_pcu->gsmtap, 0, 0, GSMTAP_CHANNEL_AGCH, 0, 0, 0, 0, data, GSM_MACBLOCK_LEN);
pcu_tx_data_req(0, 0, PCU_IF_SAPI_AGCH, 0, 0, 0, data, GSM_MACBLOCK_LEN); pcu_tx_data_req(0, 0, PCU_IF_SAPI_AGCH, 0, 0, 0, data, GSM_MACBLOCK_LEN);
} }
void pcu_l1if_tx_pch(bitvec * block, int plen, uint16_t pgroup) void pcu_l1if_tx_pch(bitvec * block, int plen, uint16_t pgroup)
{ {
struct gprs_rlcmac_bts *bts = bts_main_data();
uint8_t data[PAGING_GROUP_LEN + GSM_MACBLOCK_LEN]; uint8_t data[PAGING_GROUP_LEN + GSM_MACBLOCK_LEN];
int i; int i;
@ -266,8 +263,8 @@ void pcu_l1if_tx_pch(bitvec * block, int plen, uint16_t pgroup)
data[3] = (plen << 2) | 0x01; data[3] = (plen << 2) | 0x01;
bitvec_pack(block, data + PAGING_GROUP_LEN + 1); bitvec_pack(block, data + PAGING_GROUP_LEN + 1);
if (bts->gsmtap_categ_mask & (1 << PCU_GSMTAP_C_DL_PCH)) if (the_pcu->gsmtap_categ_mask & (1 << PCU_GSMTAP_C_DL_PCH))
gsmtap_send(bts->gsmtap, 0, 0, GSMTAP_CHANNEL_PCH, 0, 0, 0, 0, data + 3, GSM_MACBLOCK_LEN); gsmtap_send(the_pcu->gsmtap, 0, 0, GSMTAP_CHANNEL_PCH, 0, 0, 0, 0, data + 3, GSM_MACBLOCK_LEN);
pcu_tx_data_req(0, 0, PCU_IF_SAPI_PCH, 0, 0, 0, data, PAGING_GROUP_LEN + GSM_MACBLOCK_LEN); pcu_tx_data_req(0, 0, PCU_IF_SAPI_PCH, 0, 0, 0, data, PAGING_GROUP_LEN + GSM_MACBLOCK_LEN);
} }
@ -315,7 +312,6 @@ static int pcu_rx_data_ind_bcch(uint8_t *data, uint8_t len)
static int pcu_rx_data_ind(struct gsm_pcu_if_data *data_ind) static int pcu_rx_data_ind(struct gsm_pcu_if_data *data_ind)
{ {
struct gprs_rlcmac_bts *bts = bts_main_data();
int rc; int rc;
int current_fn = get_current_fn(); int current_fn = get_current_fn();
struct pcu_l1_meas meas = {0}; struct pcu_l1_meas meas = {0};
@ -353,8 +349,8 @@ static int pcu_rx_data_ind(struct gsm_pcu_if_data *data_ind)
gsmtap_chantype = GSMTAP_CHANNEL_UNKNOWN; gsmtap_chantype = GSMTAP_CHANNEL_UNKNOWN;
} }
if (rc < 0 && (bts->gsmtap_categ_mask & (1 <<PCU_GSMTAP_C_UL_UNKNOWN))) { if (rc < 0 && (the_pcu->gsmtap_categ_mask & (1 <<PCU_GSMTAP_C_UL_UNKNOWN))) {
gsmtap_send(bts->gsmtap, data_ind->arfcn | GSMTAP_ARFCN_F_UPLINK, data_ind->ts_nr, gsmtap_send(the_pcu->gsmtap, data_ind->arfcn | GSMTAP_ARFCN_F_UPLINK, data_ind->ts_nr,
gsmtap_chantype, 0, data_ind->fn, meas.rssi, meas.link_qual, data_ind->data, data_ind->len); gsmtap_chantype, 0, data_ind->fn, meas.rssi, meas.link_qual, data_ind->data, data_ind->len);
} }
@ -405,7 +401,7 @@ extern "C" int pcu_rx_rts_req_ptcch(uint8_t trx, uint8_t ts,
if (!pdch->m_is_enabled) if (!pdch->m_is_enabled)
return -EAGAIN; return -EAGAIN;
pcu_l1if_tx_ptcch(trx, ts, bts->trx[trx].arfcn, fn, block_nr, pcu_l1if_tx_ptcch(bts, trx, ts, bts->trx[trx].arfcn, fn, block_nr,
pdch->ptcch_msg, GSM_MACBLOCK_LEN); pdch->ptcch_msg, GSM_MACBLOCK_LEN);
return 0; return 0;
} }
@ -621,7 +617,7 @@ bssgp_failed:
if (allowed) if (allowed)
LOGP(DL1IF, LOGL_DEBUG, " Use CS%d\n", i + 1); LOGP(DL1IF, LOGL_DEBUG, " Use CS%d\n", i + 1);
} }
bts_set_max_cs(bts, bts->vty.max_cs_dl, bts->vty.max_cs_ul); /* recalc max CS values */ bts_recalc_max_cs(bts);
bts->mcs_mask = 0; bts->mcs_mask = 0;
for (i = 0; i < 9; i++) { for (i = 0; i < 9; i++) {
@ -631,11 +627,11 @@ bssgp_failed:
LOGP(DL1IF, LOGL_DEBUG, " Use MCS%d\n", i + 1); LOGP(DL1IF, LOGL_DEBUG, " Use MCS%d\n", i + 1);
} }
bts_set_max_mcs(bts, bts->vty.max_mcs_dl, bts->vty.max_mcs_ul); /* recalc max MCS values */ bts_recalc_max_mcs(bts);
LOGP(DL1IF, LOGL_DEBUG, " initial_cs=%u%s\n", info_ind->initial_cs, LOGP(DL1IF, LOGL_DEBUG, " initial_cs=%u%s\n", info_ind->initial_cs,
bts->vty.force_initial_cs ? " (VTY forced, ignoring)" : ""); the_pcu->vty.force_initial_cs ? " (VTY forced, ignoring)" : "");
if (!bts->vty.force_initial_cs) { if (!the_pcu->vty.force_initial_cs) {
if (info_ind->initial_cs > bts->bts->max_cs_dl()) { if (info_ind->initial_cs > bts->bts->max_cs_dl()) {
LOGP(DL1IF, LOGL_DEBUG, " downgrading initial_cs_dl to %d\n", bts->bts->max_cs_dl()); LOGP(DL1IF, LOGL_DEBUG, " downgrading initial_cs_dl to %d\n", bts->bts->max_cs_dl());
bts->initial_cs_dl = bts->bts->max_cs_dl(); bts->initial_cs_dl = bts->bts->max_cs_dl();
@ -651,8 +647,8 @@ bssgp_failed:
} }
LOGP(DL1IF, LOGL_DEBUG, " initial_mcs=%u%s\n", info_ind->initial_mcs, LOGP(DL1IF, LOGL_DEBUG, " initial_mcs=%u%s\n", info_ind->initial_mcs,
bts->vty.force_initial_mcs ? " (VTY forced, ignoring)" : ""); the_pcu->vty.force_initial_mcs ? " (VTY forced, ignoring)" : "");
if (!bts->vty.force_initial_mcs) { if (!the_pcu->vty.force_initial_mcs) {
if (info_ind->initial_mcs > bts->bts->max_mcs_dl()) { if (info_ind->initial_mcs > bts->bts->max_mcs_dl()) {
LOGP(DL1IF, LOGL_DEBUG, " downgrading initial_mcs_dl to %d\n", bts->bts->max_mcs_dl()); LOGP(DL1IF, LOGL_DEBUG, " downgrading initial_mcs_dl to %d\n", bts->bts->max_mcs_dl());
bts->initial_mcs_dl = bts->bts->max_mcs_dl(); bts->initial_mcs_dl = bts->bts->max_mcs_dl();
@ -705,7 +701,7 @@ bssgp_failed:
bts->trx[trx_nr].fl1h = l1if_open_pdch( bts->trx[trx_nr].fl1h = l1if_open_pdch(
trx_nr, trx_nr,
info_ind->trx[trx_nr].hlayer1, info_ind->trx[trx_nr].hlayer1,
bts->gsmtap); the_pcu->gsmtap);
if (!bts->trx[trx_nr].fl1h) { if (!bts->trx[trx_nr].fl1h) {
LOGP(DL1IF, LOGL_FATAL, "Failed to open direct " LOGP(DL1IF, LOGL_FATAL, "Failed to open direct "
"DSP access for PDCH.\n"); "DSP access for PDCH.\n");

View File

@ -143,7 +143,8 @@ static inline void pcu_l1_meas_set_ms_i_level(struct pcu_l1_meas *m, size_t idx,
#ifdef __cplusplus #ifdef __cplusplus
void pcu_l1if_tx_pdtch(msgb *msg, uint8_t trx, uint8_t ts, uint16_t arfcn, void pcu_l1if_tx_pdtch(msgb *msg, uint8_t trx, uint8_t ts, uint16_t arfcn,
uint32_t fn, uint8_t block_nr); uint32_t fn, uint8_t block_nr);
void pcu_l1if_tx_ptcch(uint8_t trx, uint8_t ts, uint16_t arfcn, void pcu_l1if_tx_ptcch(struct gprs_rlcmac_bts *bts,
uint8_t trx, uint8_t ts, uint16_t arfcn,
uint32_t fn, uint8_t block_nr, uint32_t fn, uint8_t block_nr,
uint8_t *data, size_t data_len); uint8_t *data, size_t data_len);
void pcu_l1if_tx_agch(bitvec * block, int len); void pcu_l1if_tx_agch(bitvec * block, int len);

View File

@ -224,7 +224,7 @@ void sighandler(int sigset)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
struct sched_param param; struct sched_param param;
struct gprs_rlcmac_bts *bts; struct gprs_pcu *pcu;
int rc; int rc;
/* tall_pcu_ctx may already have been initialized in bts.cpp during early_init(). */ /* tall_pcu_ctx may already have been initialized in bts.cpp during early_init(). */
@ -235,9 +235,12 @@ int main(int argc, char *argv[])
osmo_init_logging2(tall_pcu_ctx, &gprs_log_info); osmo_init_logging2(tall_pcu_ctx, &gprs_log_info);
} }
bts = bts_main_data(); pcu = gprs_pcu_alloc(tall_pcu_ctx);
the_pcu = pcu; /* globally avaialable object */
bts->pcu_sock_path = talloc_strdup(tall_pcu_ctx, PCU_SOCK_DEFAULT); pcu->bts = bts_alloc(pcu);
pcu->pcu_sock_path = talloc_strdup(tall_pcu_ctx, PCU_SOCK_DEFAULT);
msgb_talloc_ctx_init(tall_pcu_ctx, 0); msgb_talloc_ctx_init(tall_pcu_ctx, 0);
@ -257,20 +260,20 @@ int main(int argc, char *argv[])
exit(0); exit(0);
} }
bts->gsmtap = gsmtap_source_init(gsmtap_addr, GSMTAP_UDP_PORT, 1); pcu->gsmtap = gsmtap_source_init(gsmtap_addr, GSMTAP_UDP_PORT, 1);
if (bts->gsmtap) if (pcu->gsmtap)
gsmtap_source_add_sink(bts->gsmtap); gsmtap_source_add_sink(pcu->gsmtap);
else else
fprintf(stderr, "Failed to initialize GSMTAP for %s\n", gsmtap_addr); fprintf(stderr, "Failed to initialize GSMTAP for %s\n", gsmtap_addr);
bts->nsi = gprs_ns2_instantiate(tall_pcu_ctx, gprs_ns_prim_cb, NULL); pcu->nsi = gprs_ns2_instantiate(tall_pcu_ctx, gprs_ns_prim_cb, NULL);
if (!bts->nsi) { if (!pcu->nsi) {
LOGP(DBSSGP, LOGL_ERROR, "Failed to create NS instance\n"); LOGP(DBSSGP, LOGL_ERROR, "Failed to create NS instance\n");
exit(1); exit(1);
} }
bssgp_set_bssgp_callback(gprs_gp_send_cb, bts->nsi); bssgp_set_bssgp_callback(gprs_gp_send_cb, pcu->nsi);
gprs_ns2_vty_init(bts->nsi, NULL); gprs_ns2_vty_init(pcu->nsi, NULL);
rc = vty_read_config_file(config_file, NULL); rc = vty_read_config_file(config_file, NULL);
if (rc < 0 && config_given) { if (rc < 0 && config_given) {
@ -291,8 +294,8 @@ int main(int argc, char *argv[])
exit(1); exit(1);
} }
if (!bts->alloc_algorithm) if (!pcu->alloc_algorithm)
bts->alloc_algorithm = alloc_algorithm_dynamic; pcu->alloc_algorithm = alloc_algorithm_dynamic;
rc = pcu_l1if_open(); rc = pcu_l1if_open();

View File

@ -70,28 +70,26 @@ static const struct value_string pcu_gsmtap_categ_help[] = {
DEFUN(cfg_pcu_gsmtap_categ, cfg_pcu_gsmtap_categ_cmd, "HIDDEN", "HIDDEN") DEFUN(cfg_pcu_gsmtap_categ, cfg_pcu_gsmtap_categ_cmd, "HIDDEN", "HIDDEN")
{ {
struct gprs_rlcmac_bts *bts = bts_main_data();
int categ; int categ;
categ = get_string_value(pcu_gsmtap_categ_names, argv[0]); categ = get_string_value(pcu_gsmtap_categ_names, argv[0]);
if (categ < 0) if (categ < 0)
return CMD_WARNING; return CMD_WARNING;
bts->gsmtap_categ_mask |= (1 << categ); the_pcu->gsmtap_categ_mask |= (1 << categ);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN(cfg_pcu_no_gsmtap_categ, cfg_pcu_no_gsmtap_categ_cmd, "HIDDEN", "HIDDEN") DEFUN(cfg_pcu_no_gsmtap_categ, cfg_pcu_no_gsmtap_categ_cmd, "HIDDEN", "HIDDEN")
{ {
struct gprs_rlcmac_bts *bts = bts_main_data();
int categ; int categ;
categ = get_string_value(pcu_gsmtap_categ_names, argv[0]); categ = get_string_value(pcu_gsmtap_categ_names, argv[0]);
if (categ < 0) if (categ < 0)
return CMD_WARNING; return CMD_WARNING;
bts->gsmtap_categ_mask &= ~(1 << categ); the_pcu->gsmtap_categ_mask &= ~(1 << categ);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -122,7 +120,7 @@ static int config_write_pcu(struct vty *vty)
if (bts->fc_ms_leak_rate) if (bts->fc_ms_leak_rate)
vty_out(vty, " flow-control force-ms-leak-rate %d%s", vty_out(vty, " flow-control force-ms-leak-rate %d%s",
bts->fc_ms_leak_rate, VTY_NEWLINE); bts->fc_ms_leak_rate, VTY_NEWLINE);
if (bts->vty.force_initial_cs) { if (the_pcu->vty.force_initial_cs) {
if (bts->initial_cs_ul == bts->initial_cs_dl) if (bts->initial_cs_ul == bts->initial_cs_dl)
vty_out(vty, " cs %d%s", bts->initial_cs_dl, vty_out(vty, " cs %d%s", bts->initial_cs_dl,
VTY_NEWLINE); VTY_NEWLINE);
@ -130,13 +128,13 @@ static int config_write_pcu(struct vty *vty)
vty_out(vty, " cs %d %d%s", bts->initial_cs_dl, vty_out(vty, " cs %d %d%s", bts->initial_cs_dl,
bts->initial_cs_ul, VTY_NEWLINE); bts->initial_cs_ul, VTY_NEWLINE);
} }
if (bts->vty.max_cs_dl && bts->vty.max_cs_ul) { if (the_pcu->vty.max_cs_dl && the_pcu->vty.max_cs_ul) {
if (bts->vty.max_cs_ul == bts->vty.max_cs_dl) if (the_pcu->vty.max_cs_ul == the_pcu->vty.max_cs_dl)
vty_out(vty, " cs max %d%s", bts->vty.max_cs_dl, vty_out(vty, " cs max %d%s", the_pcu->vty.max_cs_dl,
VTY_NEWLINE); VTY_NEWLINE);
else else
vty_out(vty, " cs max %d %d%s", bts->vty.max_cs_dl, vty_out(vty, " cs max %d %d%s", the_pcu->vty.max_cs_dl,
bts->vty.max_cs_ul, VTY_NEWLINE); the_pcu->vty.max_cs_ul, VTY_NEWLINE);
} }
if (bts->cs_adj_enabled) if (bts->cs_adj_enabled)
vty_out(vty, " cs threshold %d %d%s", vty_out(vty, " cs threshold %d %d%s",
@ -179,7 +177,7 @@ static int config_write_pcu(struct vty *vty)
bts->mcs_lqual_ranges[8].low, bts->mcs_lqual_ranges[8].low,
VTY_NEWLINE); VTY_NEWLINE);
if (bts->vty.force_initial_mcs) { if (the_pcu->vty.force_initial_mcs) {
if (bts->initial_mcs_ul == bts->initial_mcs_dl) if (bts->initial_mcs_ul == bts->initial_mcs_dl)
vty_out(vty, " mcs %d%s", bts->initial_mcs_dl, vty_out(vty, " mcs %d%s", bts->initial_mcs_dl,
VTY_NEWLINE); VTY_NEWLINE);
@ -188,13 +186,13 @@ static int config_write_pcu(struct vty *vty)
bts->initial_mcs_ul, VTY_NEWLINE); bts->initial_mcs_ul, VTY_NEWLINE);
} }
if (bts->vty.max_mcs_dl && bts->vty.max_mcs_ul) { if (the_pcu->vty.max_mcs_dl && the_pcu->vty.max_mcs_ul) {
if (bts->vty.max_mcs_ul == bts->vty.max_mcs_dl) if (the_pcu->vty.max_mcs_ul == the_pcu->vty.max_mcs_dl)
vty_out(vty, " mcs max %d%s", bts->vty.max_mcs_dl, vty_out(vty, " mcs max %d%s", the_pcu->vty.max_mcs_dl,
VTY_NEWLINE); VTY_NEWLINE);
else else
vty_out(vty, " mcs max %d %d%s", bts->vty.max_mcs_dl, vty_out(vty, " mcs max %d %d%s", the_pcu->vty.max_mcs_dl,
bts->vty.max_mcs_ul, VTY_NEWLINE); the_pcu->vty.max_mcs_ul, VTY_NEWLINE);
} }
vty_out(vty, " window-size %d %d%s", bts->ws_base, bts->ws_pdch, vty_out(vty, " window-size %d %d%s", bts->ws_base, bts->ws_pdch,
@ -223,11 +221,11 @@ static int config_write_pcu(struct vty *vty)
vty_out(vty, " queue codel interval %d%s", vty_out(vty, " queue codel interval %d%s",
bts->llc_codel_interval_msec/10, VTY_NEWLINE); bts->llc_codel_interval_msec/10, VTY_NEWLINE);
if (bts->alloc_algorithm == alloc_algorithm_a) if (the_pcu->alloc_algorithm == alloc_algorithm_a)
vty_out(vty, " alloc-algorithm a%s", VTY_NEWLINE); vty_out(vty, " alloc-algorithm a%s", VTY_NEWLINE);
if (bts->alloc_algorithm == alloc_algorithm_b) if (the_pcu->alloc_algorithm == alloc_algorithm_b)
vty_out(vty, " alloc-algorithm b%s", VTY_NEWLINE); vty_out(vty, " alloc-algorithm b%s", VTY_NEWLINE);
if (bts->alloc_algorithm == alloc_algorithm_dynamic) if (the_pcu->alloc_algorithm == alloc_algorithm_dynamic)
vty_out(vty, " alloc-algorithm dynamic%s", VTY_NEWLINE); vty_out(vty, " alloc-algorithm dynamic%s", VTY_NEWLINE);
if (bts->force_two_phase) if (bts->force_two_phase)
vty_out(vty, " two-phase-access%s", VTY_NEWLINE); vty_out(vty, " two-phase-access%s", VTY_NEWLINE);
@ -235,12 +233,12 @@ static int config_write_pcu(struct vty *vty)
vty_out(vty, " gamma %d%s", bts->gamma * 2, VTY_NEWLINE); vty_out(vty, " gamma %d%s", bts->gamma * 2, VTY_NEWLINE);
if (!bts->dl_tbf_preemptive_retransmission) if (!bts->dl_tbf_preemptive_retransmission)
vty_out(vty, " no dl-tbf-preemptive-retransmission%s", VTY_NEWLINE); vty_out(vty, " no dl-tbf-preemptive-retransmission%s", VTY_NEWLINE);
if (strcmp(bts->pcu_sock_path, PCU_SOCK_DEFAULT)) if (strcmp(the_pcu->pcu_sock_path, PCU_SOCK_DEFAULT))
vty_out(vty, " pcu-socket %s%s", bts->pcu_sock_path, VTY_NEWLINE); vty_out(vty, " pcu-socket %s%s", the_pcu->pcu_sock_path, VTY_NEWLINE);
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
unsigned int cs = (1 << i); unsigned int cs = (1 << i);
if (bts->gsmtap_categ_mask & cs) { if (the_pcu->gsmtap_categ_mask & cs) {
vty_out(vty, " gsmtap-category %s%s", vty_out(vty, " gsmtap-category %s%s",
get_value_string(pcu_gsmtap_categ_names, i), VTY_NEWLINE); get_value_string(pcu_gsmtap_categ_names, i), VTY_NEWLINE);
} }
@ -449,7 +447,7 @@ DEFUN_ATTR(cfg_pcu_cs,
struct gprs_rlcmac_bts *bts = bts_main_data(); struct gprs_rlcmac_bts *bts = bts_main_data();
uint8_t cs = atoi(argv[0]); uint8_t cs = atoi(argv[0]);
bts->vty.force_initial_cs = true; the_pcu->vty.force_initial_cs = true;
bts->initial_cs_dl = cs; bts->initial_cs_dl = cs;
if (argc > 1) if (argc > 1)
bts->initial_cs_ul = atoi(argv[1]); bts->initial_cs_ul = atoi(argv[1]);
@ -465,9 +463,7 @@ DEFUN_ATTR(cfg_pcu_no_cs,
NO_STR CS_STR, NO_STR CS_STR,
CMD_ATTR_IMMEDIATE) CMD_ATTR_IMMEDIATE)
{ {
struct gprs_rlcmac_bts *bts = bts_main_data(); the_pcu->vty.force_initial_cs = false;
bts->vty.force_initial_cs = false;
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -482,7 +478,6 @@ DEFUN_ATTR(cfg_pcu_cs_max,
"Use a different maximum CS value for the uplink", "Use a different maximum CS value for the uplink",
CMD_ATTR_IMMEDIATE) CMD_ATTR_IMMEDIATE)
{ {
struct gprs_rlcmac_bts *bts = bts_main_data();
uint8_t cs_dl = atoi(argv[0]); uint8_t cs_dl = atoi(argv[0]);
uint8_t cs_ul; uint8_t cs_ul;
@ -491,7 +486,7 @@ DEFUN_ATTR(cfg_pcu_cs_max,
else else
cs_ul = cs_dl; cs_ul = cs_dl;
bts_set_max_cs(bts, cs_dl, cs_ul); gprs_pcu_set_max_cs(the_pcu, cs_dl, cs_ul);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -501,9 +496,7 @@ DEFUN_ATTR(cfg_pcu_no_cs_max,
NO_STR CS_STR CS_MAX_STR, NO_STR CS_STR CS_MAX_STR,
CMD_ATTR_IMMEDIATE) CMD_ATTR_IMMEDIATE)
{ {
struct gprs_rlcmac_bts *bts = bts_main_data(); gprs_pcu_set_max_cs(the_pcu, 0, 0);
bts_set_max_cs(bts, 0, 0);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -519,7 +512,7 @@ DEFUN_ATTR(cfg_pcu_mcs,
struct gprs_rlcmac_bts *bts = bts_main_data(); struct gprs_rlcmac_bts *bts = bts_main_data();
uint8_t mcs = atoi(argv[0]); uint8_t mcs = atoi(argv[0]);
bts->vty.force_initial_mcs = true; the_pcu->vty.force_initial_mcs = true;
bts->initial_mcs_dl = mcs; bts->initial_mcs_dl = mcs;
if (argc > 1) if (argc > 1)
bts->initial_mcs_ul = atoi(argv[1]); bts->initial_mcs_ul = atoi(argv[1]);
@ -535,9 +528,7 @@ DEFUN_ATTR(cfg_pcu_no_mcs,
NO_STR MCS_STR, NO_STR MCS_STR,
CMD_ATTR_IMMEDIATE) CMD_ATTR_IMMEDIATE)
{ {
struct gprs_rlcmac_bts *bts = bts_main_data(); the_pcu->vty.force_initial_mcs = false;
bts->vty.force_initial_mcs = false;
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -551,7 +542,6 @@ DEFUN_ATTR(cfg_pcu_mcs_max,
"Use a different maximum MCS value for the uplink", "Use a different maximum MCS value for the uplink",
CMD_ATTR_IMMEDIATE) CMD_ATTR_IMMEDIATE)
{ {
struct gprs_rlcmac_bts *bts = bts_main_data();
uint8_t mcs_dl = atoi(argv[0]); uint8_t mcs_dl = atoi(argv[0]);
uint8_t mcs_ul; uint8_t mcs_ul;
@ -560,7 +550,7 @@ DEFUN_ATTR(cfg_pcu_mcs_max,
else else
mcs_ul = mcs_dl; mcs_ul = mcs_dl;
bts_set_max_mcs(bts, mcs_dl, mcs_ul); gprs_pcu_set_max_mcs(the_pcu, mcs_dl, mcs_ul);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -570,9 +560,7 @@ DEFUN_ATTR(cfg_pcu_no_mcs_max,
NO_STR MCS_STR CS_MAX_STR, NO_STR MCS_STR CS_MAX_STR,
CMD_ATTR_IMMEDIATE) CMD_ATTR_IMMEDIATE)
{ {
struct gprs_rlcmac_bts *bts = bts_main_data(); gprs_pcu_set_max_mcs(the_pcu, 0, 0);
bts_set_max_mcs(bts, 0, 0);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -773,17 +761,15 @@ DEFUN_ATTR(cfg_pcu_alloc,
"Dynamically select the algorithm based on the system state\n", "Dynamically select the algorithm based on the system state\n",
CMD_ATTR_IMMEDIATE) CMD_ATTR_IMMEDIATE)
{ {
struct gprs_rlcmac_bts *bts = bts_main_data();
switch (argv[0][0]) { switch (argv[0][0]) {
case 'a': case 'a':
bts->alloc_algorithm = alloc_algorithm_a; the_pcu->alloc_algorithm = alloc_algorithm_a;
break; break;
case 'b': case 'b':
bts->alloc_algorithm = alloc_algorithm_b; the_pcu->alloc_algorithm = alloc_algorithm_b;
break; break;
default: default:
bts->alloc_algorithm = alloc_algorithm_dynamic; the_pcu->alloc_algorithm = alloc_algorithm_dynamic;
break; break;
} }
@ -1110,12 +1096,10 @@ DEFUN(cfg_pcu_sock,
"Configure the osmo-bts PCU socket file/path name\n" "Configure the osmo-bts PCU socket file/path name\n"
"Path of the socket to connect to\n") "Path of the socket to connect to\n")
{ {
struct gprs_rlcmac_bts *bts = bts_main_data();
if (vty->type != VTY_FILE) if (vty->type != VTY_FILE)
vty_out(vty, "Changing PCU socket path at run-time has no effect%s", VTY_NEWLINE); vty_out(vty, "Changing PCU socket path at run-time has no effect%s", VTY_NEWLINE);
osmo_talloc_replace_string(tall_pcu_ctx, &bts->pcu_sock_path, argv[0]); osmo_talloc_replace_string(tall_pcu_ctx, &the_pcu->pcu_sock_path, argv[0]);
return CMD_SUCCESS; return CMD_SUCCESS;
} }

View File

@ -335,7 +335,7 @@ int gprs_rlcmac_tbf::update()
LOGP(DTBF, LOGL_DEBUG, "********** DL-TBF update **********\n"); LOGP(DTBF, LOGL_DEBUG, "********** DL-TBF update **********\n");
tbf_unlink_pdch(this); tbf_unlink_pdch(this);
rc = bts_data->alloc_algorithm(bts_data, ms(), this, false, -1); rc = the_pcu->alloc_algorithm(bts_data, ms(), this, false, -1);
/* if no resource */ /* if no resource */
if (rc < 0) { if (rc < 0) {
LOGPTBF(this, LOGL_ERROR, "No resource after update???\n"); LOGPTBF(this, LOGL_ERROR, "No resource after update???\n");
@ -744,7 +744,7 @@ int gprs_rlcmac_tbf::setup(int8_t use_trx, bool single_slot)
m_created_ts = time(NULL); m_created_ts = time(NULL);
/* select algorithm */ /* select algorithm */
rc = bts_data->alloc_algorithm(bts_data, m_ms, this, single_slot, use_trx); rc = the_pcu->alloc_algorithm(bts_data, m_ms, this, single_slot, use_trx);
/* if no resource */ /* if no resource */
if (rc < 0) { if (rc < 0) {
return -1; return -1;

View File

@ -112,7 +112,7 @@ static void test_alloc_a(gprs_rlcmac_tbf_direction dir,
int tfi; int tfi;
int i; int i;
uint8_t used_trx, tmp_trx; uint8_t used_trx, tmp_trx;
BTS the_bts; BTS the_bts(the_pcu);
GprsMs *ms; GprsMs *ms;
struct gprs_rlcmac_bts *bts; struct gprs_rlcmac_bts *bts;
struct gprs_rlcmac_tbf *tbfs[32*8+1] = { 0, }; struct gprs_rlcmac_tbf *tbfs[32*8+1] = { 0, };
@ -120,7 +120,7 @@ static void test_alloc_a(gprs_rlcmac_tbf_direction dir,
printf("Testing alloc_a direction(%d)\n", dir); printf("Testing alloc_a direction(%d)\n", dir);
bts = the_bts.bts_data(); bts = the_bts.bts_data();
bts->alloc_algorithm = alloc_algorithm_a; the_pcu->alloc_algorithm = alloc_algorithm_a;
struct gprs_rlcmac_trx *trx = &bts->trx[0]; struct gprs_rlcmac_trx *trx = &bts->trx[0];
for (i = 0; i < 8; i += 1) for (i = 0; i < 8; i += 1)
@ -205,7 +205,7 @@ static inline void enable_ts_on_bts(struct gprs_rlcmac_bts *bts,
static inline bool test_alloc_b_ul_dl(bool ts0, bool ts1, bool ts2, bool ts3, bool ts4, bool ts5, bool ts6, bool ts7, static inline bool test_alloc_b_ul_dl(bool ts0, bool ts1, bool ts2, bool ts3, bool ts4, bool ts5, bool ts6, bool ts7,
uint8_t ms_class, bool verbose) uint8_t ms_class, bool verbose)
{ {
BTS the_bts; BTS the_bts(the_pcu);
struct gprs_rlcmac_bts *bts = the_bts.bts_data(); struct gprs_rlcmac_bts *bts = the_bts.bts_data();
GprsMs *ms; GprsMs *ms;
gprs_rlcmac_ul_tbf *ul_tbf; gprs_rlcmac_ul_tbf *ul_tbf;
@ -214,7 +214,7 @@ static inline bool test_alloc_b_ul_dl(bool ts0, bool ts1, bool ts2, bool ts3, bo
if (verbose) if (verbose)
printf("Testing UL then DL assignment.\n"); printf("Testing UL then DL assignment.\n");
bts->alloc_algorithm = alloc_algorithm_b; the_pcu->alloc_algorithm = alloc_algorithm_b;
enable_ts_on_bts(bts, ts0, ts1, ts2, ts3, ts4, ts5, ts6, ts7); enable_ts_on_bts(bts, ts0, ts1, ts2, ts3, ts4, ts5, ts6, ts7);
@ -250,7 +250,7 @@ static inline bool test_alloc_b_ul_dl(bool ts0, bool ts1, bool ts2, bool ts3, bo
static inline bool test_alloc_b_dl_ul(bool ts0, bool ts1, bool ts2, bool ts3, bool ts4, bool ts5, bool ts6, bool ts7, static inline bool test_alloc_b_dl_ul(bool ts0, bool ts1, bool ts2, bool ts3, bool ts4, bool ts5, bool ts6, bool ts7,
uint8_t ms_class, bool verbose) uint8_t ms_class, bool verbose)
{ {
BTS the_bts; BTS the_bts(the_pcu);
struct gprs_rlcmac_bts *bts = the_bts.bts_data(); struct gprs_rlcmac_bts *bts = the_bts.bts_data();
GprsMs *ms; GprsMs *ms;
gprs_rlcmac_ul_tbf *ul_tbf; gprs_rlcmac_ul_tbf *ul_tbf;
@ -259,7 +259,7 @@ static inline bool test_alloc_b_dl_ul(bool ts0, bool ts1, bool ts2, bool ts3, bo
if (verbose) if (verbose)
printf("Testing DL then UL assignment followed by update\n"); printf("Testing DL then UL assignment followed by update\n");
bts->alloc_algorithm = alloc_algorithm_b; the_pcu->alloc_algorithm = alloc_algorithm_b;
enable_ts_on_bts(bts, ts0, ts1, ts2, ts3, ts4, ts5, ts6, ts7); enable_ts_on_bts(bts, ts0, ts1, ts2, ts3, ts4, ts5, ts6, ts7);
@ -302,7 +302,7 @@ static inline bool test_alloc_b_dl_ul(bool ts0, bool ts1, bool ts2, bool ts3, bo
static inline bool test_alloc_b_jolly(uint8_t ms_class) static inline bool test_alloc_b_jolly(uint8_t ms_class)
{ {
BTS the_bts; BTS the_bts(the_pcu);
struct gprs_rlcmac_bts *bts = the_bts.bts_data(); struct gprs_rlcmac_bts *bts = the_bts.bts_data();
GprsMs *ms; GprsMs *ms;
int tfi; int tfi;
@ -311,7 +311,7 @@ static inline bool test_alloc_b_jolly(uint8_t ms_class)
printf("Testing jolly example\n"); printf("Testing jolly example\n");
bts->alloc_algorithm = alloc_algorithm_b; the_pcu->alloc_algorithm = alloc_algorithm_b;
enable_ts_on_bts(bts, false, true, true, true, true, false, false, false); enable_ts_on_bts(bts, false, true, true, true, true, false, false, false);
@ -649,7 +649,7 @@ static void test_successive_allocation(algo_t algo, unsigned min_class,
unsigned max_class, enum test_mode mode, unsigned max_class, enum test_mode mode,
unsigned expect_num, const char *text) unsigned expect_num, const char *text)
{ {
BTS the_bts; BTS the_bts(the_pcu);
struct gprs_rlcmac_bts *bts; struct gprs_rlcmac_bts *bts;
struct gprs_rlcmac_trx *trx; struct gprs_rlcmac_trx *trx;
unsigned counter; unsigned counter;
@ -658,7 +658,7 @@ static void test_successive_allocation(algo_t algo, unsigned min_class,
text, min_class, max_class, test_mode_descr(mode)); text, min_class, max_class, test_mode_descr(mode));
bts = the_bts.bts_data(); bts = the_bts.bts_data();
bts->alloc_algorithm = algo; the_pcu->alloc_algorithm = algo;
trx = &bts->trx[0]; trx = &bts->trx[0];
trx->pdch[3].enable(); trx->pdch[3].enable();
@ -683,7 +683,7 @@ static void test_successive_allocation(algo_t algo, unsigned min_class,
static void test_many_connections(algo_t algo, unsigned expect_num, static void test_many_connections(algo_t algo, unsigned expect_num,
const char *text) const char *text)
{ {
BTS the_bts; BTS the_bts(the_pcu);
struct gprs_rlcmac_bts *bts; struct gprs_rlcmac_bts *bts;
struct gprs_rlcmac_trx *trx; struct gprs_rlcmac_trx *trx;
int counter1, counter2 = -1; int counter1, counter2 = -1;
@ -698,7 +698,7 @@ static void test_many_connections(algo_t algo, unsigned expect_num,
printf("Going to test assignment with many connections, algorithm %s\n", text); printf("Going to test assignment with many connections, algorithm %s\n", text);
bts = the_bts.bts_data(); bts = the_bts.bts_data();
bts->alloc_algorithm = algo; the_pcu->alloc_algorithm = algo;
trx = &bts->trx[0]; trx = &bts->trx[0];
trx->pdch[3].enable(); trx->pdch[3].enable();
@ -761,7 +761,7 @@ static void test_successive_allocations()
static void test_2_consecutive_dl_tbfs() static void test_2_consecutive_dl_tbfs()
{ {
BTS the_bts; BTS the_bts(the_pcu);
GprsMs *ms; GprsMs *ms;
struct gprs_rlcmac_bts *bts; struct gprs_rlcmac_bts *bts;
struct gprs_rlcmac_trx *trx; struct gprs_rlcmac_trx *trx;
@ -773,7 +773,7 @@ static void test_2_consecutive_dl_tbfs()
printf("Testing DL TS allocation for Multi UEs\n"); printf("Testing DL TS allocation for Multi UEs\n");
bts = the_bts.bts_data(); bts = the_bts.bts_data();
bts->alloc_algorithm = alloc_algorithm_b; the_pcu->alloc_algorithm = alloc_algorithm_b;
trx = &bts->trx[0]; trx = &bts->trx[0];
trx->pdch[4].enable(); trx->pdch[4].enable();
@ -826,6 +826,8 @@ int main(int argc, char **argv)
if (getenv("LOGL_DEBUG")) if (getenv("LOGL_DEBUG"))
log_set_log_level(osmo_stderr_target, LOGL_DEBUG); log_set_log_level(osmo_stderr_target, LOGL_DEBUG);
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
test_alloc_a(); test_alloc_a();
test_alloc_b(); test_alloc_b();
test_successive_allocations(); test_successive_allocations();
@ -833,6 +835,8 @@ int main(int argc, char **argv)
test_many_connections(alloc_algorithm_b, 32, "B"); test_many_connections(alloc_algorithm_b, 32, "B");
test_many_connections(alloc_algorithm_dynamic, 160, "dynamic"); test_many_connections(alloc_algorithm_dynamic, 160, "dynamic");
test_2_consecutive_dl_tbfs(); test_2_consecutive_dl_tbfs();
talloc_free(the_pcu);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -62,7 +62,7 @@ static inline void test_all_classes(struct gprs_rlcmac_trx *trx, bool clear_mask
static inline void test_multislot_total_ascending(bool seq) static inline void test_multislot_total_ascending(bool seq)
{ {
BTS the_bts; BTS the_bts(the_pcu);
struct gprs_rlcmac_bts *bts; struct gprs_rlcmac_bts *bts;
struct gprs_rlcmac_trx *trx; struct gprs_rlcmac_trx *trx;
int i; int i;
@ -83,7 +83,7 @@ static inline void test_multislot_total_ascending(bool seq)
static inline void test_multislot_total_descending(bool seq) static inline void test_multislot_total_descending(bool seq)
{ {
BTS the_bts; BTS the_bts(the_pcu);
struct gprs_rlcmac_bts *bts; struct gprs_rlcmac_bts *bts;
struct gprs_rlcmac_trx *trx; struct gprs_rlcmac_trx *trx;
int i; int i;
@ -104,7 +104,7 @@ static inline void test_multislot_total_descending(bool seq)
static inline void test_multislot_middle(bool seq) static inline void test_multislot_middle(bool seq)
{ {
BTS the_bts; BTS the_bts(the_pcu);
struct gprs_rlcmac_bts *bts; struct gprs_rlcmac_bts *bts;
struct gprs_rlcmac_trx *trx; struct gprs_rlcmac_trx *trx;
@ -123,7 +123,7 @@ static inline void test_multislot_middle(bool seq)
static inline void test_multislot_ends(bool seq) static inline void test_multislot_ends(bool seq)
{ {
BTS the_bts; BTS the_bts(the_pcu);
struct gprs_rlcmac_bts *bts; struct gprs_rlcmac_bts *bts;
struct gprs_rlcmac_trx *trx; struct gprs_rlcmac_trx *trx;
@ -160,6 +160,8 @@ int main(int argc, char **argv)
log_set_print_filename(osmo_stderr_target, 0); log_set_print_filename(osmo_stderr_target, 0);
log_set_log_level(osmo_stderr_target, LOGL_DEBUG); log_set_log_level(osmo_stderr_target, LOGL_DEBUG);
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
test_multislot_total_ascending(true); test_multislot_total_ascending(true);
test_multislot_total_ascending(false); test_multislot_total_ascending(false);
@ -174,6 +176,8 @@ int main(int argc, char **argv)
test_window_wrapper(); test_window_wrapper();
talloc_free(the_pcu);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -84,7 +84,7 @@ void prepare_bts_with_two_dl_tbf_subscr()
fprintf(stderr, "--- %s ---\n", __func__); fprintf(stderr, "--- %s ---\n", __func__);
bts_data = bts->bts_data(); bts_data = bts->bts_data();
bts_data->alloc_algorithm = alloc_algorithm_b; the_pcu->alloc_algorithm = alloc_algorithm_b;
trx = bts_data->trx; trx = bts_data->trx;
trx->pdch[4].enable(); trx->pdch[4].enable();
@ -157,6 +157,7 @@ void cleanup()
BTS::main_bts()->cleanup(); BTS::main_bts()->cleanup();
/* FIXME: talloc report disabled, because bts->ms_alloc() in prepare_bts_with_two_dl_tbf_subscr() causes leak */ /* FIXME: talloc report disabled, because bts->ms_alloc() in prepare_bts_with_two_dl_tbf_subscr() causes leak */
/* talloc_report_full(tall_pcu_ctx, stderr); */ /* talloc_report_full(tall_pcu_ctx, stderr); */
talloc_free(the_pcu);
talloc_free(tall_pcu_ctx); talloc_free(tall_pcu_ctx);
} }
@ -172,6 +173,9 @@ int main(int argc, char *argv[])
log_set_print_filename(osmo_stderr_target, 0); log_set_print_filename(osmo_stderr_target, 0);
log_parse_category_mask(osmo_stderr_target, "DL1IF,1:DRLCMAC,3:DRLCMACSCHED,1"); log_parse_category_mask(osmo_stderr_target, "DL1IF,1:DRLCMAC,3:DRLCMACSCHED,1");
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
the_pcu->bts = bts_alloc(the_pcu);
test_enc_zero_len(); test_enc_zero_len();
test_enc(&req); test_enc(&req);
test_pcu_rx_no_subscr_with_active_tbf(); test_pcu_rx_no_subscr_with_active_tbf();

View File

@ -1157,7 +1157,7 @@ static void setup_bts(BTS *the_bts, uint8_t ts_no, uint8_t cs = 1)
gprs_rlcmac_trx *trx; gprs_rlcmac_trx *trx;
bts = the_bts->bts_data(); bts = the_bts->bts_data();
bts->alloc_algorithm = alloc_algorithm_a; the_pcu->alloc_algorithm = alloc_algorithm_a;
bts->initial_cs_dl = cs; bts->initial_cs_dl = cs;
bts->initial_cs_ul = cs; bts->initial_cs_ul = cs;
trx = &bts->trx[0]; trx = &bts->trx[0];
@ -1254,7 +1254,7 @@ static void uplink_header_type_2_parsing_test(BTS *the_bts,
static void uplink_header_type2_test(void) static void uplink_header_type2_test(void)
{ {
BTS the_bts; BTS the_bts(the_pcu);
int ts_no = 7; int ts_no = 7;
uint32_t fn = 2654218; uint32_t fn = 2654218;
uint16_t qta = 31; uint16_t qta = 31;
@ -1371,7 +1371,7 @@ static void uplink_header_type_1_parsing_test(BTS *the_bts,
void uplink_header_type1_test(void) void uplink_header_type1_test(void)
{ {
BTS the_bts; BTS the_bts(the_pcu);
int ts_no = 7; int ts_no = 7;
uint32_t fn = 2654218; uint32_t fn = 2654218;
uint16_t qta = 31; uint16_t qta = 31;
@ -1398,6 +1398,8 @@ int main(int argc, char **argv)
log_set_use_color(osmo_stderr_target, 0); log_set_use_color(osmo_stderr_target, 0);
log_set_print_filename(osmo_stderr_target, 0); log_set_print_filename(osmo_stderr_target, 0);
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
vty_init(&pcu_vty_info); vty_init(&pcu_vty_info);
pcu_vty_init(); pcu_vty_init();
@ -1412,6 +1414,8 @@ int main(int argc, char **argv)
if (getenv("TALLOC_REPORT_FULL")) if (getenv("TALLOC_REPORT_FULL"))
talloc_report_full(tall_pcu_ctx, stderr); talloc_report_full(tall_pcu_ctx, stderr);
talloc_free(the_pcu);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -73,9 +73,12 @@ static void init_main_bts()
bts->n3103 = 4; bts->n3103 = 4;
bts->n3105 = 8; bts->n3105 = 8;
bts->alpha = 0; /* a = 0.0 */ bts->alpha = 0; /* a = 0.0 */
}
if (!bts->alloc_algorithm) static void init_pcu(struct gprs_pcu *pcu)
bts->alloc_algorithm = alloc_algorithm_b; {
if (!pcu->alloc_algorithm)
pcu->alloc_algorithm = alloc_algorithm_b;
} }
static void bvci_unblocked(struct gprs_bssgp_pcu *pcu) static void bvci_unblocked(struct gprs_bssgp_pcu *pcu)
@ -114,7 +117,9 @@ void create_and_connect_bssgp(struct gprs_rlcmac_bts *bts,
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct gprs_rlcmac_bts *bts = bts_main_data(); struct gprs_pcu *pcu = gprs_pcu_alloc(tall_pcu_ctx);
the_pcu = pcu; /* globally avaialable object */
pcu->bts = bts_alloc(pcu);
tall_pcu_ctx = talloc_named_const(NULL, 1, "moiji-mobile Emu-PCU context"); tall_pcu_ctx = talloc_named_const(NULL, 1, "moiji-mobile Emu-PCU context");
if (!tall_pcu_ctx) if (!tall_pcu_ctx)
@ -123,8 +128,8 @@ int main(int argc, char **argv)
msgb_talloc_ctx_init(tall_pcu_ctx, 0); msgb_talloc_ctx_init(tall_pcu_ctx, 0);
osmo_init_logging2(tall_pcu_ctx, &gprs_log_info); osmo_init_logging2(tall_pcu_ctx, &gprs_log_info);
bts->nsi = gprs_ns2_instantiate(tall_pcu_ctx, &gprs_ns_prim_cb, NULL); pcu->nsi = gprs_ns2_instantiate(tall_pcu_ctx, &gprs_ns_prim_cb, NULL);
if (!bts->nsi) { if (!pcu->nsi) {
LOGP(DBSSGP, LOGL_ERROR, "Failed to create NS instance\n"); LOGP(DBSSGP, LOGL_ERROR, "Failed to create NS instance\n");
abort(); abort();
} }
@ -134,9 +139,10 @@ int main(int argc, char **argv)
current_test = 0; current_test = 0;
init_pcu(pcu);
init_main_bts(); init_main_bts();
bssgp_set_bssgp_callback(gprs_gp_send_cb, bts->nsi); bssgp_set_bssgp_callback(gprs_gp_send_cb, pcu->nsi);
create_and_connect_bssgp(bts, INADDR_LOOPBACK, 23000); create_and_connect_bssgp(bts_data(pcu->bts), INADDR_LOOPBACK, 23000);
for (;;) for (;;)
osmo_select_main(0); osmo_select_main(0);

View File

@ -53,7 +53,7 @@ static void set_fn(BTS * bts, uint32_t fn)
static void run_test() static void run_test()
{ {
BTS bts; BTS bts(the_pcu);
uint32_t fn; uint32_t fn;
printf("RFN_MODULUS=%i\n",RFN_MODULUS); printf("RFN_MODULUS=%i\n",RFN_MODULUS);
@ -154,7 +154,11 @@ int main(int argc, char **argv)
log_set_print_filename(osmo_stderr_target, 0); log_set_print_filename(osmo_stderr_target, 0);
log_set_log_level(osmo_stderr_target, LOGL_DEBUG); log_set_log_level(osmo_stderr_target, LOGL_DEBUG);
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
run_test(); run_test();
talloc_free(the_pcu);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -51,7 +51,7 @@ static void test_ms_state()
uint32_t tlli = 0xffeeddbb; uint32_t tlli = 0xffeeddbb;
gprs_rlcmac_dl_tbf *dl_tbf; gprs_rlcmac_dl_tbf *dl_tbf;
gprs_rlcmac_ul_tbf *ul_tbf; gprs_rlcmac_ul_tbf *ul_tbf;
BTS the_bts; BTS the_bts(the_pcu);
GprsMs *ms; GprsMs *ms;
printf("=== start %s ===\n", __func__); printf("=== start %s ===\n", __func__);
@ -114,7 +114,7 @@ static void test_ms_callback()
uint32_t tlli = 0xffeeddbb; uint32_t tlli = 0xffeeddbb;
gprs_rlcmac_dl_tbf *dl_tbf; gprs_rlcmac_dl_tbf *dl_tbf;
gprs_rlcmac_ul_tbf *ul_tbf; gprs_rlcmac_ul_tbf *ul_tbf;
BTS the_bts; BTS the_bts(the_pcu);
GprsMs *ms; GprsMs *ms;
last_cb = CB_UNKNOWN; last_cb = CB_UNKNOWN;
@ -188,7 +188,7 @@ static void test_ms_replace_tbf()
uint32_t tlli = 0xffeeddbb; uint32_t tlli = 0xffeeddbb;
gprs_rlcmac_dl_tbf *dl_tbf[2]; gprs_rlcmac_dl_tbf *dl_tbf[2];
gprs_rlcmac_ul_tbf *ul_tbf; gprs_rlcmac_ul_tbf *ul_tbf;
BTS the_bts; BTS the_bts(the_pcu);
GprsMs *ms; GprsMs *ms;
printf("=== start %s ===\n", __func__); printf("=== start %s ===\n", __func__);
@ -262,7 +262,7 @@ static void test_ms_change_tlli()
uint32_t start_tlli = 0xaa000000; uint32_t start_tlli = 0xaa000000;
uint32_t new_ms_tlli = 0xff001111; uint32_t new_ms_tlli = 0xff001111;
uint32_t other_sgsn_tlli = 0xff00eeee; uint32_t other_sgsn_tlli = 0xff00eeee;
BTS the_bts; BTS the_bts(the_pcu);
GprsMs *ms; GprsMs *ms;
printf("=== start %s ===\n", __func__); printf("=== start %s ===\n", __func__);
@ -374,7 +374,7 @@ static void test_ms_storage()
const char *imsi2 = "001001987654322"; const char *imsi2 = "001001987654322";
gprs_rlcmac_ul_tbf *ul_tbf; gprs_rlcmac_ul_tbf *ul_tbf;
BTS the_bts; BTS the_bts(the_pcu);
GprsMs *ms, *ms_tmp; GprsMs *ms, *ms_tmp;
GprsMsStorage store(&the_bts); GprsMsStorage store(&the_bts);
@ -446,7 +446,7 @@ static void test_ms_timeout()
uint32_t tlli = 0xffeeddbb; uint32_t tlli = 0xffeeddbb;
gprs_rlcmac_dl_tbf *dl_tbf; gprs_rlcmac_dl_tbf *dl_tbf;
gprs_rlcmac_ul_tbf *ul_tbf; gprs_rlcmac_ul_tbf *ul_tbf;
BTS the_bts; BTS the_bts(the_pcu);
GprsMs *ms; GprsMs *ms;
last_cb = CB_UNKNOWN; last_cb = CB_UNKNOWN;
@ -499,7 +499,7 @@ static void test_ms_timeout()
static void test_ms_cs_selection() static void test_ms_cs_selection()
{ {
BTS the_bts; BTS the_bts(the_pcu);
gprs_rlcmac_bts *bts = the_bts.bts_data(); gprs_rlcmac_bts *bts = the_bts.bts_data();
uint32_t tlli = 0xffeeddbb; uint32_t tlli = 0xffeeddbb;
@ -545,7 +545,7 @@ static void dump_ms(const GprsMs *ms, const char *pref)
static void test_ms_mcs_mode() static void test_ms_mcs_mode()
{ {
BTS the_bts; BTS the_bts(the_pcu);
gprs_rlcmac_bts *bts = the_bts.bts_data(); gprs_rlcmac_bts *bts = the_bts.bts_data();
uint32_t tlli = 0xdeadbeef; uint32_t tlli = 0xdeadbeef;
@ -618,6 +618,8 @@ int main(int argc, char **argv)
log_set_log_level(osmo_stderr_target, LOGL_INFO); log_set_log_level(osmo_stderr_target, LOGL_INFO);
log_parse_category_mask(osmo_stderr_target, "DPCU,3:DRLCMAC,3"); log_parse_category_mask(osmo_stderr_target, "DPCU,3:DRLCMAC,3");
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
vty_init(&pcu_vty_info); vty_init(&pcu_vty_info);
pcu_vty_init(); pcu_vty_init();
@ -630,6 +632,8 @@ int main(int argc, char **argv)
test_ms_cs_selection(); test_ms_cs_selection();
test_ms_mcs_mode(); test_ms_mcs_mode();
talloc_free(the_pcu);
if (getenv("TALLOC_REPORT_FULL")) if (getenv("TALLOC_REPORT_FULL"))
talloc_report_full(tall_pcu_ctx, stderr); talloc_report_full(tall_pcu_ctx, stderr);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -352,7 +352,7 @@ static void test_rlc_dl_ul_basic()
uint16_t lost = 0, recv = 0; uint16_t lost = 0, recv = 0;
char show_rbb[65]; char show_rbb[65];
uint8_t bits_data[8]; uint8_t bits_data[8];
BTS dummy_bts; BTS dummy_bts(the_pcu);
gprs_rlc_dl_window dl_win; gprs_rlc_dl_window dl_win;
bitvec bits; bitvec bits;
int bsn_begin, bsn_end, num_blocks; int bsn_begin, bsn_end, num_blocks;
@ -669,8 +669,8 @@ static void test_egprs_ul_ack_nack()
fprintf(stderr, "############## test_egprs_ul_ack_nack\n"); fprintf(stderr, "############## test_egprs_ul_ack_nack\n");
BTS the_bts; BTS the_bts(the_pcu);
the_bts.bts_data()->alloc_algorithm = alloc_algorithm_a; the_pcu->alloc_algorithm = alloc_algorithm_a;
the_bts.bts_data()->trx[0].pdch[4].enable(); the_bts.bts_data()->trx[0].pdch[4].enable();
GprsMs *ms = the_bts.ms_alloc(1, 1); GprsMs *ms = the_bts.ms_alloc(1, 1);
@ -759,8 +759,8 @@ static void check_imm_ass(struct gprs_rlcmac_tbf *tbf, bool dl, enum ph_burst_ty
void test_immediate_assign_dl() void test_immediate_assign_dl()
{ {
BTS the_bts; BTS the_bts(the_pcu);
the_bts.bts_data()->alloc_algorithm = alloc_algorithm_a; the_pcu->alloc_algorithm = alloc_algorithm_a;
the_bts.bts_data()->trx[0].pdch[2].enable(); the_bts.bts_data()->trx[0].pdch[2].enable();
the_bts.bts_data()->trx[0].pdch[3].enable(); the_bts.bts_data()->trx[0].pdch[3].enable();
GprsMs *ms = the_bts.ms_alloc(1, 0); GprsMs *ms = the_bts.ms_alloc(1, 0);
@ -783,8 +783,8 @@ void test_immediate_assign_dl()
void test_immediate_assign_ul0m() void test_immediate_assign_ul0m()
{ {
BTS the_bts; BTS the_bts(the_pcu);
the_bts.bts_data()->alloc_algorithm = alloc_algorithm_a; the_pcu->alloc_algorithm = alloc_algorithm_a;
the_bts.bts_data()->trx[0].pdch[4].enable(); the_bts.bts_data()->trx[0].pdch[4].enable();
the_bts.bts_data()->trx[0].pdch[5].enable(); the_bts.bts_data()->trx[0].pdch[5].enable();
@ -824,8 +824,8 @@ void test_immediate_assign_ul0s()
void test_immediate_assign_ul1s() void test_immediate_assign_ul1s()
{ {
BTS the_bts; BTS the_bts(the_pcu);
the_bts.bts_data()->alloc_algorithm = alloc_algorithm_a; the_pcu->alloc_algorithm = alloc_algorithm_a;
the_bts.bts_data()->trx[0].pdch[1].enable(); the_bts.bts_data()->trx[0].pdch[1].enable();
the_bts.bts_data()->trx[0].pdch[2].enable(); the_bts.bts_data()->trx[0].pdch[2].enable();
@ -925,6 +925,8 @@ int main(int argc, char **argv)
log_set_category_filter(osmo_stderr_target, DTBF, 1, LOGL_INFO); log_set_category_filter(osmo_stderr_target, DTBF, 1, LOGL_INFO);
log_set_category_filter(osmo_stderr_target, DTBFUL, 1, LOGL_INFO); log_set_category_filter(osmo_stderr_target, DTBFUL, 1, LOGL_INFO);
the_pcu = gprs_pcu_alloc(tall_pcu_ctx);
printf("Making some basic type testing.\n"); printf("Making some basic type testing.\n");
test_llc(); test_llc();
@ -941,6 +943,8 @@ int main(int argc, char **argv)
test_lsb(); test_lsb();
test_egprs_ul_ack_nack(); test_egprs_ul_ack_nack();
talloc_free(the_pcu);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }