Add NITZ (timezone) support as part of MM INFO
The UTC offset from the operating system will be used by default to calculate the NITZ in MM INFO. However, a "timezone" vty command is added at the BTS level, allowing BTS-specific overrides, e.g. in case BTSs are distributed accross multiple timezones.
This commit is contained in:
parent
6b8a56c365
commit
1c5dd2c9bb
|
@ -473,6 +473,11 @@ 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 */
|
||||
int tzhr;
|
||||
int tzmn;
|
||||
int tz_bts_specific;
|
||||
|
||||
/* ip.accesss Unit ID's have Site/BTS/TRX layout */
|
||||
union {
|
||||
struct {
|
||||
|
|
|
@ -448,6 +448,8 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
|
|||
VTY_NEWLINE);
|
||||
vty_out(vty, " training_sequence_code %u%s", bts->tsc, VTY_NEWLINE);
|
||||
vty_out(vty, " base_station_id_code %u%s", bts->bsic, VTY_NEWLINE);
|
||||
if (bts->tz_bts_specific != 0)
|
||||
vty_out(vty, " timezone %d %d%s", bts->tzhr, bts->tzmn, 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);
|
||||
|
@ -1495,6 +1497,31 @@ DEFUN(cfg_bts_bsic,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_timezone,
|
||||
cfg_bts_timezone_cmd,
|
||||
"timezone <-19-19> (0|15|30|45)",
|
||||
"Set the Timezone Offset of this BTS\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
int tzhr = atoi(argv[0]);
|
||||
int tzmn = atoi(argv[1]);
|
||||
|
||||
bts->tzhr = tzhr;
|
||||
bts->tzmn = tzmn;
|
||||
bts->tz_bts_specific=1;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_no_timezone,
|
||||
cfg_bts_no_timezone_cmd,
|
||||
"no timezone",
|
||||
"disable bts specific timezone\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
bts->tz_bts_specific=0;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_unit_id,
|
||||
cfg_bts_unit_id_cmd,
|
||||
|
@ -2691,6 +2718,8 @@ int bsc_vty_init(const struct log_info *cat)
|
|||
install_element(BTS_NODE, &cfg_bts_tsc_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_bsic_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_unit_id_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_timezone_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_no_timezone_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_serno_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_nokia_site_skip_reset_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_stream_id_cmd);
|
||||
|
|
|
@ -610,12 +610,17 @@ static int mm_rx_loc_upd_req(struct gsm_subscriber_connection *conn, struct msgb
|
|||
return gsm0408_authorize(conn, msg);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static uint8_t to_bcd8(uint8_t val)
|
||||
/* Turn int into semi-octet representation: 98 => 0x89 */
|
||||
static uint8_t bcdify(uint8_t value)
|
||||
{
|
||||
return ((val / 10) << 4) | (val % 10);
|
||||
uint8_t ret;
|
||||
|
||||
ret = value / 10;
|
||||
ret |= (value % 10) << 4;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Section 9.2.15a */
|
||||
int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn)
|
||||
|
@ -623,13 +628,14 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn)
|
|||
struct msgb *msg = gsm48_msgb_alloc();
|
||||
struct gsm48_hdr *gh;
|
||||
struct gsm_network *net = conn->bts->network;
|
||||
struct gsm_bts *bts = conn->bts;
|
||||
uint8_t *ptr8;
|
||||
int name_len, name_pad;
|
||||
#if 0
|
||||
|
||||
time_t cur_t;
|
||||
struct tm* cur_time;
|
||||
int tz15min;
|
||||
#endif
|
||||
struct tm* gmt_time;
|
||||
struct tm* local_time;
|
||||
int tzunits;
|
||||
|
||||
msg->lchan = conn->lchan;
|
||||
|
||||
|
@ -696,24 +702,48 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn)
|
|||
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Section 10.5.3.9 */
|
||||
cur_t = time(NULL);
|
||||
cur_time = gmtime(&cur_t);
|
||||
gmt_time = gmtime(&cur_t);
|
||||
|
||||
ptr8 = msgb_put(msg, 8);
|
||||
ptr8[0] = GSM48_IE_NET_TIME_TZ;
|
||||
ptr8[1] = to_bcd8(cur_time->tm_year % 100);
|
||||
ptr8[2] = to_bcd8(cur_time->tm_mon);
|
||||
ptr8[3] = to_bcd8(cur_time->tm_mday);
|
||||
ptr8[4] = to_bcd8(cur_time->tm_hour);
|
||||
ptr8[5] = to_bcd8(cur_time->tm_min);
|
||||
ptr8[6] = to_bcd8(cur_time->tm_sec);
|
||||
/* 02.42: coded as BCD encoded signed value in units of 15 minutes */
|
||||
tz15min = (cur_time->tm_gmtoff)/(60*15);
|
||||
ptr8[7] = to_bcd8(tz15min);
|
||||
if (tz15min < 0)
|
||||
ptr8[7] |= 0x80;
|
||||
#endif
|
||||
ptr8[1] = bcdify(gmt_time->tm_year % 100);
|
||||
ptr8[2] = bcdify(gmt_time->tm_mon + 1);
|
||||
ptr8[3] = bcdify(gmt_time->tm_mday);
|
||||
ptr8[4] = bcdify(gmt_time->tm_hour);
|
||||
ptr8[5] = bcdify(gmt_time->tm_min);
|
||||
ptr8[6] = bcdify(gmt_time->tm_sec);
|
||||
|
||||
if (bts->tz_bts_specific) {
|
||||
/* Convert tzhr and tzmn to units */
|
||||
if (bts->tzhr < 0) {
|
||||
tzunits = ((bts->tzhr/-1)*4);
|
||||
tzunits = tzunits + (bts->tzmn/15);
|
||||
ptr8[7] = bcdify(tzunits);
|
||||
/* Set negative time */
|
||||
ptr8[7] |= 0x08;
|
||||
}
|
||||
else {
|
||||
tzunits = bts->tzhr*4;
|
||||
tzunits = tzunits + (bts->tzmn/15);
|
||||
ptr8[7] = bcdify(tzunits);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Need to get GSM offset and convert into 15 min units */
|
||||
/* This probably breaks if gmtoff returns a value not evenly divisible by 15? */
|
||||
local_time = localtime(&cur_t);
|
||||
tzunits = (local_time->tm_gmtoff/60)/15;
|
||||
if (tzunits < 0) {
|
||||
tzunits = tzunits/-1;
|
||||
ptr8[7] = bcdify(tzunits);
|
||||
/* Flip it to negative */
|
||||
ptr8[7] |= 0x08;
|
||||
}
|
||||
else
|
||||
ptr8[7] = bcdify(tzunits);
|
||||
}
|
||||
|
||||
DEBUGP(DMM, "-> MM INFO\n");
|
||||
|
||||
|
|
Loading…
Reference in New Issue