Move timezone settings up to network level

Time zone used to be configurable per-BTS. In the upcoming MSC-split, no BTS
structures will be available on the MSC level. To simplify, drop the ability to
manage several time zones in a core network and place the time zone config on
the network VTY level, i.e. in gsm_network. If we are going to re-add fine
grained time zone settings, it should probably be tied to the LAC.

Adjust time zone VTY config code (to be moved to libcommon-cs in subsequent commit).

Adjust time zone Ctrl Interface code.

Change-Id: I69848887d92990f3d6f969be80f6ef91f6bdbbe8
This commit is contained in:
Neels Hofmeyr 2016-05-10 13:29:33 +02:00 committed by Harald Welte
parent 1a60644eb2
commit 7398395cc0
9 changed files with 98 additions and 99 deletions

View File

@ -273,6 +273,13 @@ enum gsm_auth_policy {
#define GSM_T3113_DEFAULT 60
#define GSM_T3122_DEFAULT 10
struct gsm_tz {
int override; /* if 0, use system's time zone instead. */
int hr; /* hour */
int mn; /* minute */
int dst; /* daylight savings */
};
struct gsm_network {
/* global parameters */
uint16_t country_code;
@ -367,6 +374,13 @@ struct gsm_network {
/* all active subscriber connections. */
struct llist_head subscr_conns;
/* if override is nonzero, this timezone data is used for all MM
* contexts. */
/* TODO: in OsmoNITB, tz-override used to be BTS-specific. To enable
* BTS|RNC specific timezone overrides for multi-tz networks in
* OsmoCSCN, this should be tied to the location area code (LAC). */
struct gsm_tz tz;
};
struct osmo_esme;

View File

@ -679,14 +679,6 @@ struct gsm_bts {
/* buffers where we put the pre-computed SI */
sysinfo_buf_t si_buf[_MAX_SYSINFO_TYPE];
/* TimeZone hours, mins, and bts specific */
struct {
int hr;
int mn;
int override;
int dst;
} tz;
/* ip.accesss Unit ID's have Site/BTS/TRX layout */
union {
struct {

View File

@ -554,14 +554,6 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
if (bts->dtxd)
vty_out(vty, " dtx downlink%s", VTY_NEWLINE);
vty_out(vty, " base_station_id_code %u%s", bts->bsic, VTY_NEWLINE);
if (bts->tz.override != 0) {
if (bts->tz.dst)
vty_out(vty, " timezone %d %d %d%s",
bts->tz.hr, bts->tz.mn, bts->tz.dst, VTY_NEWLINE);
else
vty_out(vty, " timezone %d %d%s",
bts->tz.hr, bts->tz.mn, VTY_NEWLINE);
}
vty_out(vty, " ms max power %u%s", bts->ms_max_power, VTY_NEWLINE);
vty_out(vty, " cell reselection hysteresis %u%s",
bts->si_common.cell_sel_par.cell_resel_hyst*2, VTY_NEWLINE);
@ -817,6 +809,15 @@ static int config_write_net(struct vty *vty)
vty_out(vty, " timer t3141 %u%s", gsmnet->T3141, VTY_NEWLINE);
vty_out(vty, " subscriber-keep-in-ram %d%s",
gsmnet->subscr_group->keep_subscr, VTY_NEWLINE);
if (gsmnet->tz.override != 0) {
if (gsmnet->tz.dst)
vty_out(vty, " timezone %d %d %d%s",
gsmnet->tz.hr, gsmnet->tz.mn, gsmnet->tz.dst,
VTY_NEWLINE);
else
vty_out(vty, " timezone %d %d%s",
gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE);
}
return CMD_SUCCESS;
}
@ -1735,10 +1736,10 @@ DEFUN(cfg_bts_bsic,
return CMD_SUCCESS;
}
DEFUN(cfg_bts_timezone,
cfg_bts_timezone_cmd,
DEFUN(cfg_net_timezone,
cfg_net_timezone_cmd,
"timezone <-19-19> (0|15|30|45)",
"Set the Timezone Offset of this BTS\n"
"Set the Timezone Offset of the network\n"
"Timezone offset (hours)\n"
"Timezone offset (00 minutes)\n"
"Timezone offset (15 minutes)\n"
@ -1746,22 +1747,22 @@ DEFUN(cfg_bts_timezone,
"Timezone offset (45 minutes)\n"
)
{
struct gsm_bts *bts = vty->index;
struct gsm_network *net = vty->index;
int tzhr = atoi(argv[0]);
int tzmn = atoi(argv[1]);
bts->tz.hr = tzhr;
bts->tz.mn = tzmn;
bts->tz.dst = 0;
bts->tz.override = 1;
net->tz.hr = tzhr;
net->tz.mn = tzmn;
net->tz.dst = 0;
net->tz.override = 1;
return CMD_SUCCESS;
}
DEFUN(cfg_bts_timezone_dst,
cfg_bts_timezone_dst_cmd,
DEFUN(cfg_net_timezone_dst,
cfg_net_timezone_dst_cmd,
"timezone <-19-19> (0|15|30|45) <0-2>",
"Set the Timezone Offset of this BTS\n"
"Set the Timezone Offset of the network\n"
"Timezone offset (hours)\n"
"Timezone offset (00 minutes)\n"
"Timezone offset (15 minutes)\n"
@ -1770,28 +1771,28 @@ DEFUN(cfg_bts_timezone_dst,
"DST offset (hours)\n"
)
{
struct gsm_bts *bts = vty->index;
struct gsm_network *net = vty->index;
int tzhr = atoi(argv[0]);
int tzmn = atoi(argv[1]);
int tzdst = atoi(argv[2]);
bts->tz.hr = tzhr;
bts->tz.mn = tzmn;
bts->tz.dst = tzdst;
bts->tz.override = 1;
net->tz.hr = tzhr;
net->tz.mn = tzmn;
net->tz.dst = tzdst;
net->tz.override = 1;
return CMD_SUCCESS;
}
DEFUN(cfg_bts_no_timezone,
cfg_bts_no_timezone_cmd,
DEFUN(cfg_net_no_timezone,
cfg_net_no_timezone_cmd,
"no timezone",
NO_STR
"Disable BTS specific timezone\n")
"Disable network timezone override, use system tz\n")
{
struct gsm_bts *bts = vty->index;
struct gsm_network *net = vty->index;
bts->tz.override = 0;
net->tz.override = 0;
return CMD_SUCCESS;
}
@ -3949,6 +3950,9 @@ int bsc_vty_init(const struct log_info *cat, struct gsm_network *network)
install_element(GSMNET_NODE, &cfg_net_T3141_cmd);
install_element(GSMNET_NODE, &cfg_net_dtx_cmd);
install_element(GSMNET_NODE, &cfg_net_pag_any_tch_cmd);
install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
install_element(GSMNET_NODE, &cfg_bts_cmd);
install_node(&bts_node, config_write_bts);
@ -3967,9 +3971,6 @@ int bsc_vty_init(const struct log_info *cat, struct gsm_network *network)
install_element(BTS_NODE, &cfg_bts_bsic_cmd);
install_element(BTS_NODE, &cfg_bts_unit_id_cmd);
install_element(BTS_NODE, &cfg_bts_rsl_ip_cmd);
install_element(BTS_NODE, &cfg_bts_timezone_cmd);
install_element(BTS_NODE, &cfg_bts_timezone_dst_cmd);
install_element(BTS_NODE, &cfg_bts_no_timezone_cmd);
install_element(BTS_NODE, &cfg_bts_nokia_site_skip_reset_cmd);
install_element(BTS_NODE, &cfg_bts_nokia_site_no_loc_rel_cnf_cmd);
install_element(BTS_NODE, &cfg_bts_nokia_site_bts_reset_timer_cnf_cmd);

View File

@ -733,7 +733,6 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn)
struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 MM INF");
struct gsm48_hdr *gh;
struct gsm_network *net = conn->network;
struct gsm_bts *bts = conn->bts;
uint8_t *ptr8;
int name_len, name_pad;
@ -821,23 +820,23 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn)
ptr8[5] = bcdify(gmt_time->tm_min);
ptr8[6] = bcdify(gmt_time->tm_sec);
if (bts->tz.override) {
if (net->tz.override) {
/* Convert tz.hr and tz.mn to units */
if (bts->tz.hr < 0) {
tzunits = ((bts->tz.hr/-1)*4);
tzunits = tzunits + (bts->tz.mn/15);
if (net->tz.hr < 0) {
tzunits = ((net->tz.hr/-1)*4);
tzunits = tzunits + (net->tz.mn/15);
ptr8[7] = bcdify(tzunits);
/* Set negative time */
ptr8[7] |= 0x08;
}
else {
tzunits = bts->tz.hr*4;
tzunits = tzunits + (bts->tz.mn/15);
tzunits = net->tz.hr*4;
tzunits = tzunits + (net->tz.mn/15);
ptr8[7] = bcdify(tzunits);
}
/* Convert DST value */
if (bts->tz.dst >= 0 && bts->tz.dst <= 2)
dst = bts->tz.dst;
if (net->tz.dst >= 0 && net->tz.dst <= 2)
dst = net->tz.dst;
}
else {
/* Need to get GSM offset and convert into 15 min units */

View File

@ -362,18 +362,15 @@ err:
return 1;
}
CTRL_CMD_DEFINE(bts_timezone, "timezone");
static int get_bts_timezone(struct ctrl_cmd *cmd, void *data)
CTRL_CMD_DEFINE(net_timezone, "timezone");
static int get_net_timezone(struct ctrl_cmd *cmd, void *data)
{
struct gsm_bts *bts = (struct gsm_bts *) cmd->node;
if (!bts) {
cmd->reply = "bts not found.";
return CTRL_CMD_ERROR;
}
struct gsm_network *net = (struct gsm_network*)cmd->node;
if (bts->tz.override)
struct gsm_tz *tz = &net->tz;
if (tz->override)
cmd->reply = talloc_asprintf(cmd, "%d,%d,%d",
bts->tz.hr, bts->tz.mn, bts->tz.dst);
tz->hr, tz->mn, tz->dst);
else
cmd->reply = talloc_asprintf(cmd, "off");
@ -385,16 +382,11 @@ static int get_bts_timezone(struct ctrl_cmd *cmd, void *data)
return CTRL_CMD_REPLY;
}
static int set_bts_timezone(struct ctrl_cmd *cmd, void *data)
static int set_net_timezone(struct ctrl_cmd *cmd, void *data)
{
char *saveptr, *hourstr, *minstr, *dststr, *tmp = 0;
int override;
struct gsm_bts *bts = (struct gsm_bts *) cmd->node;
if (!bts) {
cmd->reply = "bts not found.";
return CTRL_CMD_ERROR;
}
struct gsm_network *net = (struct gsm_network*)cmd->node;
tmp = talloc_strdup(cmd, cmd->value);
if (!tmp)
@ -409,25 +401,26 @@ static int set_bts_timezone(struct ctrl_cmd *cmd, void *data)
if (hourstr != NULL)
override = strcasecmp(hourstr, "off") != 0;
bts->tz.override = override;
struct gsm_tz *tz = &net->tz;
tz->override = override;
if (override) {
bts->tz.hr = hourstr ? atol(hourstr) : 0;
bts->tz.mn = minstr ? atol(minstr) : 0;
bts->tz.dst = dststr ? atol(dststr) : 0;
tz->hr = hourstr ? atol(hourstr) : 0;
tz->mn = minstr ? atol(minstr) : 0;
tz->dst = dststr ? atol(dststr) : 0;
}
talloc_free(tmp);
tmp = NULL;
return get_bts_timezone(cmd, data);
return get_net_timezone(cmd, data);
oom:
cmd->reply = "OOM";
return CTRL_CMD_ERROR;
}
static int verify_bts_timezone(struct ctrl_cmd *cmd, const char *value, void *data)
static int verify_net_timezone(struct ctrl_cmd *cmd, const char *value, void *data)
{
char *saveptr, *hourstr, *minstr, *dststr, *tmp;
int override, tz_hours, tz_mins, tz_dst;
@ -655,7 +648,7 @@ int bsc_ctrl_cmds_install(struct gsm_network *net)
rc = ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_loc);
if (rc)
goto end;
rc = ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_timezone);
rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_timezone);
if (rc)
goto end;
rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_msc_connection_status);

View File

@ -270,23 +270,24 @@ static int bsc_patch_mm_info(struct gsm_subscriber_connection *conn,
return 0;
/* Is TZ patching enabled? */
if (!bts->tz.override)
struct gsm_tz *tz = &bts->network->tz;
if (!tz->override)
return 0;
/* Convert tz.hr and tz.mn to units */
if (bts->tz.hr < 0) {
tzunits = -bts->tz.hr*4;
if (tz->hr < 0) {
tzunits = -tz->hr*4;
tzbsd |= 0x08;
} else
tzunits = bts->tz.hr*4;
tzunits = tz->hr*4;
tzunits = tzunits + (bts->tz.mn/15);
tzunits = tzunits + (tz->mn/15);
tzbsd |= (tzunits % 10)*0x10 + (tzunits / 10);
/* Convert DST value */
if (bts->tz.dst >= 0 && bts->tz.dst <= 2)
dst = bts->tz.dst;
if (tz->dst >= 0 && tz->dst <= 2)
dst = tz->dst;
if (TLVP_PRESENT(&tp, GSM48_IE_UTC)) {
LOGP(DMSC, LOGL_DEBUG,

View File

@ -147,10 +147,10 @@ static void test_scan(void)
struct msgb *msg = msgb_alloc(4096, "test-message");
int is_set = 0;
bts->tz.hr = get_int(test_def->params, test_def->n_params, "tz_hr", 0, &is_set);
bts->tz.mn = get_int(test_def->params, test_def->n_params, "tz_mn", 0, &is_set);
bts->tz.dst = get_int(test_def->params, test_def->n_params, "tz_dst", 0, &is_set);
bts->tz.override = 1;
net->tz.hr = get_int(test_def->params, test_def->n_params, "tz_hr", 0, &is_set);
net->tz.mn = get_int(test_def->params, test_def->n_params, "tz_mn", 0, &is_set);
net->tz.dst = get_int(test_def->params, test_def->n_params, "tz_dst", 0, &is_set);
net->tz.override = 1;
printf("Going to test item: %d\n", i);
msg->l3h = msgb_put(msg, test_def->length);

View File

@ -331,41 +331,41 @@ class TestCtrlBSC(TestCtrlBase):
self.assertEquals(r['value'], 'state=off,policy=on')
def testTimezone(self):
r = self.do_get('bts.0.timezone')
r = self.do_get('timezone')
self.assertEquals(r['mtype'], 'GET_REPLY')
self.assertEquals(r['var'], 'bts.0.timezone')
self.assertEquals(r['var'], 'timezone')
self.assertEquals(r['value'], 'off')
r = self.do_set('bts.0.timezone', '-2,15,2')
r = self.do_set('timezone', '-2,15,2')
self.assertEquals(r['mtype'], 'SET_REPLY')
self.assertEquals(r['var'], 'bts.0.timezone')
self.assertEquals(r['var'], 'timezone')
self.assertEquals(r['value'], '-2,15,2')
r = self.do_get('bts.0.timezone')
r = self.do_get('timezone')
self.assertEquals(r['mtype'], 'GET_REPLY')
self.assertEquals(r['var'], 'bts.0.timezone')
self.assertEquals(r['var'], 'timezone')
self.assertEquals(r['value'], '-2,15,2')
# Test invalid input
r = self.do_set('bts.0.timezone', '-2,15,2,5,6,7')
r = self.do_set('timezone', '-2,15,2,5,6,7')
self.assertEquals(r['mtype'], 'SET_REPLY')
self.assertEquals(r['var'], 'bts.0.timezone')
self.assertEquals(r['var'], 'timezone')
self.assertEquals(r['value'], '-2,15,2')
r = self.do_set('bts.0.timezone', '-2,15')
r = self.do_set('timezone', '-2,15')
self.assertEquals(r['mtype'], 'ERROR')
r = self.do_set('bts.0.timezone', '-2')
r = self.do_set('timezone', '-2')
self.assertEquals(r['mtype'], 'ERROR')
r = self.do_set('bts.0.timezone', '1')
r = self.do_set('timezone', '1')
r = self.do_set('bts.0.timezone', 'off')
r = self.do_set('timezone', 'off')
self.assertEquals(r['mtype'], 'SET_REPLY')
self.assertEquals(r['var'], 'bts.0.timezone')
self.assertEquals(r['var'], 'timezone')
self.assertEquals(r['value'], 'off')
r = self.do_get('bts.0.timezone')
r = self.do_get('timezone')
self.assertEquals(r['mtype'], 'GET_REPLY')
self.assertEquals(r['var'], 'bts.0.timezone')
self.assertEquals(r['var'], 'timezone')
self.assertEquals(r['value'], 'off')
def testMcc(self):

View File

@ -651,7 +651,6 @@ class TestVTYBSC(TestVTYGenericBSC):
self.vty.enable()
self.vty.verify("configure terminal", [''])
self.vty.verify("network", [''])
self.vty.verify("bts 0", [''])
# Test invalid input
self.vty.verify("timezone", ['% Command incomplete.'])