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
diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp
index f966a79..2c9073b 100644
--- a/src/gprs_bssgp_pcu.cpp
+++ b/src/gprs_bssgp_pcu.cpp
@@ -46,8 +46,6 @@
#define FC_MAX_BUCKET_LEAK_RATE (6553500 / 8) /* Byte/s */
#define FC_MAX_BUCKET_SIZE 6553500 /* Octets */
-static struct gprs_bssgp_pcu the_pcu = { 0, };
-
extern void *tall_pcu_ctx;
extern uint16_t spoof_mcc, spoof_mnc;
extern bool spoof_mnc_3_digits;
@@ -167,7 +165,7 @@
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);
}
@@ -270,8 +268,8 @@
break;
case BSSGP_PDUT_DL_UNITDATA:
LOGP(DBSSGP, LOGL_DEBUG, "Rx BSSGP BVCI=%d (PTP) DL_UNITDATA\n", bvci);
- if (the_pcu.on_dl_unit_data)
- the_pcu.on_dl_unit_data(&the_pcu, msg, tp);
+ if (the_pcu->bssgp.on_dl_unit_data)
+ the_pcu->bssgp.on_dl_unit_data(&the_pcu->bssgp, msg, tp);
gprs_bssgp_pcu_rx_dl_ud(msg, tp);
break;
case BSSGP_PDUT_FLOW_CONTROL_BVC_ACK:
@@ -340,10 +338,10 @@
break;
case BSSGP_PDUT_BVC_RESET_ACK:
LOGP(DBSSGP, LOGL_NOTICE, "Rx BSSGP BVCI=%d (SIGN) BVC_RESET_ACK\n", bvci);
- if (!the_pcu.bvc_sig_reset)
- the_pcu.bvc_sig_reset = 1;
+ if (!the_pcu->bssgp.bvc_sig_reset)
+ the_pcu->bssgp.bvc_sig_reset = 1;
else
- the_pcu.bvc_reset = 1;
+ the_pcu->bssgp.bvc_reset = 1;
bvc_timeout(NULL);
break;
case BSSGP_PDUT_PAGING_CS:
@@ -354,9 +352,9 @@
break;
case BSSGP_PDUT_BVC_UNBLOCK_ACK:
LOGP(DBSSGP, LOGL_NOTICE, "Rx BSSGP BVCI=%d (SIGN) BVC_UNBLOCK_ACK\n", bvci);
- the_pcu.bvc_unblocked = 1;
- if (the_pcu.on_unblock_ack)
- the_pcu.on_unblock_ack(&the_pcu);
+ the_pcu->bssgp.bvc_unblocked = 1;
+ if (the_pcu->bssgp.on_unblock_ack)
+ the_pcu->bssgp.on_unblock_ack(&the_pcu->bssgp);
bvc_timeout(NULL);
break;
case BSSGP_PDUT_SUSPEND_NACK:
@@ -516,15 +514,15 @@
switch (cause) {
case BSSGP_CAUSE_BVCI_BLOCKED:
- if (the_pcu.bvc_unblocked) {
- the_pcu.bvc_unblocked = 0;
+ if (the_pcu->bssgp.bvc_unblocked) {
+ the_pcu->bssgp.bvc_unblocked = 0;
bvc_timeout(NULL);
}
break;
case BSSGP_CAUSE_UNKNOWN_BVCI:
- if (the_pcu.bvc_reset) {
- the_pcu.bvc_reset = 0;
+ if (the_pcu->bssgp.bvc_reset) {
+ the_pcu->bssgp.bvc_reset = 0;
bvc_timeout(NULL);
}
break;
@@ -557,21 +555,21 @@
break;
case NS_AFF_CAUSE_RECOVERY:
LOGP(DPCU, LOGL_NOTICE, "NS-NSE %d became available\n", nsp->nsei);
- if (!the_pcu.nsvc_unblocked) {
- the_pcu.bvc_sig_reset = 0;
- the_pcu.bvc_reset = 0;
- the_pcu.nsvc_unblocked = 1;
+ if (!the_pcu->bssgp.nsvc_unblocked) {
+ the_pcu->bssgp.bvc_sig_reset = 0;
+ the_pcu->bssgp.bvc_reset = 0;
+ the_pcu->bssgp.nsvc_unblocked = 1;
bvc_timeout(NULL);
}
break;
case NS_AFF_CAUSE_FAILURE:
LOGP(DPCU, LOGL_NOTICE, "NS-NSE %d became unavailable\n", nsp->nsei);
- if (the_pcu.nsvc_unblocked) {
- the_pcu.nsvc_unblocked = 0;
- osmo_timer_del(&the_pcu.bvc_timer);
- the_pcu.bvc_sig_reset = 0;
- the_pcu.bvc_reset = 0;
- the_pcu.bvc_unblocked = 0;
+ if (the_pcu->bssgp.nsvc_unblocked) {
+ the_pcu->bssgp.nsvc_unblocked = 0;
+ osmo_timer_del(&the_pcu->bssgp.bvc_timer);
+ the_pcu->bssgp.bvc_sig_reset = 0;
+ the_pcu->bssgp.bvc_reset = 0;
+ the_pcu->bssgp.bvc_unblocked = 0;
}
break;
case NS_AFF_CAUSE_SNS_FAILURE:
@@ -700,17 +698,17 @@
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 +
delay_sum->tv_nsec / 1000000000;
uint32_t avg_delay_ms = 0;
- if (the_pcu.queue_delay_count > 0)
- avg_delay_ms = delay_sum_ms / the_pcu.queue_delay_count;
+ if (the_pcu->bssgp.queue_delay_count > 0)
+ avg_delay_ms = delay_sum_ms / the_pcu->bssgp.queue_delay_count;
/* Reset accumulator */
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;
}
@@ -719,24 +717,24 @@
{
int rate; /* byte per second */
- if (the_pcu.queue_frames_sent == 0)
+ if (the_pcu->bssgp.queue_frames_sent == 0)
return -1;
- if (the_pcu.queue_frames_recv == 0)
+ if (the_pcu->bssgp.queue_frames_recv == 0)
return -1;
- *usage_by_1000 = the_pcu.queue_frames_recv * 1000 /
- the_pcu.queue_frames_sent;
+ *usage_by_1000 = the_pcu->bssgp.queue_frames_recv * 1000 /
+ the_pcu->bssgp.queue_frames_sent;
/* 20ms/num_pdch is the average RLC block duration, so the rate is
* calculated as:
* rate = bytes_recv / (block_dur * block_count) */
- rate = the_pcu.queue_bytes_recv * 1000 * num_pdch /
- (20 * the_pcu.queue_frames_recv);
+ rate = the_pcu->bssgp.queue_bytes_recv * 1000 * num_pdch /
+ (20 * the_pcu->bssgp.queue_frames_recv);
- the_pcu.queue_frames_sent = 0;
- the_pcu.queue_bytes_recv = 0;
- the_pcu.queue_frames_recv = 0;
+ the_pcu->bssgp.queue_frames_sent = 0;
+ the_pcu->bssgp.queue_bytes_recv = 0;
+ the_pcu->bssgp.queue_frames_recv = 0;
return rate;
}
@@ -805,7 +803,7 @@
int num_pdch = -1;
enum CodingScheme max_cs_dl;
- if (!the_pcu.bctx) {
+ if (!the_pcu->bssgp.bctx) {
LOGP(DBSSGP, LOGL_ERROR, "No bctx\n");
return -EIO;
}
@@ -896,7 +894,7 @@
avg_delay_ms = get_and_reset_avg_queue_delay();
/* Update tag */
- the_pcu.fc_tag += 1;
+ the_pcu->bssgp.fc_tag += 1;
LOGP(DBSSGP, LOGL_DEBUG,
"Sending FLOW CONTROL BVC, Bmax = %d, R = %d, Bmax_MS = %d, "
@@ -904,7 +902,7 @@
bucket_size, leak_rate, ms_bucket_size, ms_leak_rate,
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,
ms_bucket_size, ms_leak_rate,
NULL, &avg_delay_ms);
@@ -913,36 +911,36 @@
static void bvc_timeout(void *_priv)
{
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");
- bssgp_tx_bvc_reset(the_pcu.bctx, 0, BSSGP_CAUSE_OML_INTERV);
- secs = osmo_tdef_get(the_pcu.bts->T_defs_pcu, 2, OSMO_TDEF_S, -1);
- osmo_timer_schedule(&the_pcu.bvc_timer, secs, 0);
+ bssgp_tx_bvc_reset(the_pcu->bssgp.bctx, 0, BSSGP_CAUSE_OML_INTERV);
+ secs = osmo_tdef_get(the_pcu->bssgp.bts->T_defs_pcu, 2, OSMO_TDEF_S, -1);
+ osmo_timer_schedule(&the_pcu->bssgp.bvc_timer, secs, 0);
return;
}
- if (!the_pcu.bvc_reset) {
+ if (!the_pcu->bssgp.bvc_reset) {
LOGP(DBSSGP, LOGL_INFO, "Sending reset on BVCI %d\n",
- the_pcu.bctx->bvci);
- bssgp_tx_bvc_reset(the_pcu.bctx, the_pcu.bctx->bvci, BSSGP_CAUSE_OML_INTERV);
- secs = osmo_tdef_get(the_pcu.bts->T_defs_pcu, 2, OSMO_TDEF_S, -1);
- osmo_timer_schedule(&the_pcu.bvc_timer, secs, 0);
+ the_pcu->bssgp.bctx->bvci);
+ bssgp_tx_bvc_reset(the_pcu->bssgp.bctx, the_pcu->bssgp.bctx->bvci, BSSGP_CAUSE_OML_INTERV);
+ secs = osmo_tdef_get(the_pcu->bssgp.bts->T_defs_pcu, 2, OSMO_TDEF_S, -1);
+ osmo_timer_schedule(&the_pcu->bssgp.bvc_timer, secs, 0);
return;
}
- if (!the_pcu.bvc_unblocked) {
+ if (!the_pcu->bssgp.bvc_unblocked) {
LOGP(DBSSGP, LOGL_INFO, "Sending unblock on BVCI %d\n",
- the_pcu.bctx->bvci);
- bssgp_tx_bvc_unblock(the_pcu.bctx);
- secs = osmo_tdef_get(the_pcu.bts->T_defs_pcu, 1, OSMO_TDEF_S, -1);
- osmo_timer_schedule(&the_pcu.bvc_timer, secs, 0);
+ the_pcu->bssgp.bctx->bvci);
+ bssgp_tx_bvc_unblock(the_pcu->bssgp.bctx);
+ secs = osmo_tdef_get(the_pcu->bssgp.bts->T_defs_pcu, 1, OSMO_TDEF_S, -1);
+ osmo_timer_schedule(&the_pcu->bssgp.bvc_timer, secs, 0);
return;
}
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();
- 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,
@@ -966,9 +964,9 @@
if (!(valid & (1 << i)))
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);
- 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) {
LOGP(DBSSGP, LOGL_ERROR, "Failed to bind to %s\n", osmo_sockaddr_to_str(&local[i]));
continue;
@@ -983,14 +981,14 @@
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)
- 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);
if (!bts->nse) {
LOGP(DBSSGP, LOGL_ERROR, "Failed to create NSE\n");
- gprs_ns2_free_binds(bts->nsi);
+ gprs_ns2_free_binds(the_pcu->nsi);
return 1;
}
@@ -1060,13 +1058,13 @@
int rc = 0;
if (!bts->nse) {
/* there shouldn't any previous state. */
- gprs_ns2_free_nses(bts->nsi);
- gprs_ns2_free_binds(bts->nsi);
+ gprs_ns2_free_nses(the_pcu->nsi);
+ gprs_ns2_free_binds(the_pcu->nsi);
rc = ns_create_nsvc(bts, nsei, local, remote, nsvci, valid);
} else if (nsei != gprs_ns2_nse_nsei(bts->nse)) {
/* the NSEI has changed */
- gprs_ns2_free_nses(bts->nsi);
- gprs_ns2_free_binds(bts->nsi);
+ gprs_ns2_free_nses(the_pcu->nsi);
+ gprs_ns2_free_binds(the_pcu->nsi);
rc = ns_create_nsvc(bts, nsei, local, remote, nsvci, valid);
} else if (bts->ns_dialect == NS2_DIALECT_SNS) {
/* SNS: check if the initial nsvc is the same, if not recreate it */
@@ -1080,8 +1078,8 @@
return 0;
}
- gprs_ns2_free_nses(bts->nsi);
- gprs_ns2_free_binds(bts->nsi);
+ gprs_ns2_free_nses(the_pcu->nsi);
+ gprs_ns2_free_binds(the_pcu->nsi);
rc = ns_create_nsvc(bts, nsei, local, remote, nsvci, valid);
} else {
/* check if all NSVC are still the same. */
@@ -1119,75 +1117,75 @@
{
/* if already created... return the current address */
- if (the_pcu.bctx)
- return &the_pcu;
+ if (the_pcu->bssgp.bctx)
+ return &the_pcu->bssgp;
- the_pcu.bts = bts;
- the_pcu.bctx = btsctx_alloc(bvci, nsei);
- if (!the_pcu.bctx) {
+ the_pcu->bssgp.bts = bts;
+ the_pcu->bssgp.bctx = btsctx_alloc(bvci, nsei);
+ if (!the_pcu->bssgp.bctx) {
LOGP(DBSSGP, LOGL_ERROR, "Failed to create BSSGP context\n");
- the_pcu.bts->nse = NULL;
+ the_pcu->bssgp.bts->nse = 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) {
- the_pcu.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 = spoof_mnc;
+ the_pcu->bssgp.bctx->ra_id.mnc_3_digits = spoof_mnc_3_digits;
} else {
- the_pcu.bctx->ra_id.mnc = mnc;
- the_pcu.bctx->ra_id.mnc_3_digits = mnc_3_digits;
+ the_pcu->bssgp.bctx->ra_id.mnc = mnc;
+ the_pcu->bssgp.bctx->ra_id.mnc_3_digits = mnc_3_digits;
}
- the_pcu.bctx->ra_id.lac = lac;
- the_pcu.bctx->ra_id.rac = rac;
- the_pcu.bctx->cell_id = cell_id;
+ the_pcu->bssgp.bctx->ra_id.lac = lac;
+ the_pcu->bssgp.bctx->ra_id.rac = rac;
+ 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)
{
- osmo_timer_del(&the_pcu.bvc_timer);
+ osmo_timer_del(&the_pcu->bssgp.bvc_timer);
/* FIXME: blocking... */
- the_pcu.nsvc_unblocked = 0;
- the_pcu.bvc_sig_reset = 0;
- the_pcu.bvc_reset = 0;
- the_pcu.bvc_unblocked = 0;
+ the_pcu->bssgp.nsvc_unblocked = 0;
+ the_pcu->bssgp.bvc_sig_reset = 0;
+ the_pcu->bssgp.bvc_reset = 0;
+ the_pcu->bssgp.bvc_unblocked = 0;
- bssgp_bvc_ctx_free(the_pcu.bctx);
- the_pcu.bctx = NULL;
+ bssgp_bvc_ctx_free(the_pcu->bssgp.bctx);
+ the_pcu->bssgp.bctx = NULL;
- gprs_ns2_free(bts->nsi);
- bts->nsi = NULL;
+ gprs_ns2_free(the_pcu->nsi);
+ the_pcu->nsi = NULL;
bts->nse = NULL;
}
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()
{
- 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)
{
- the_pcu.queue_bytes_recv += bytes_recv;
- the_pcu.queue_frames_recv += frames_recv;
+ the_pcu->bssgp.queue_bytes_recv += bytes_recv;
+ the_pcu->bssgp.queue_frames_recv += frames_recv;
}
void gprs_bssgp_update_queue_delay(const struct timespec *tv_recv,
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;
timespecsub(tv_now, tv_recv, &tv_delay);
timespecadd(delay_sum, &tv_delay, delay_sum);
- the_pcu.queue_delay_count += 1;
+ the_pcu->bssgp.queue_delay_count += 1;
}