blob: 41d236126270562ac693bd5f9623b40e98efc7a3 [file] [log] [blame]
Holger Hans Peter Freytherf8c42192013-01-09 17:03:27 +01001/*
Holger Hans Peter Freyther4e13a8f2015-01-31 22:16:00 +01002 * (C) 2013-2015 by Holger Hans Peter Freyther
3 * (C) 2013-2015 by sysmocom s.f.m.c. GmbH
Holger Hans Peter Freytherf8c42192013-01-09 17:03:27 +01004 *
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
Harald Welteba874b82014-08-20 23:47:15 +020021#include <errno.h>
Holger Hans Peter Freyther349c40f2015-02-10 21:37:16 +010022#include <time.h>
Holger Hans Peter Freytherf8c42192013-01-09 17:03:27 +010023
Harald Welteba874b82014-08-20 23:47:15 +020024#include <osmocom/ctrl/control_cmd.h>
Neels Hofmeyrc0164792017-09-04 15:15:32 +020025#include <osmocom/bsc/ipaccess.h>
26#include <osmocom/bsc/gsm_data.h>
27#include <osmocom/bsc/abis_nm.h>
28#include <osmocom/bsc/debug.h>
29#include <osmocom/bsc/chan_alloc.h>
30#include <osmocom/bsc/osmo_bsc_rf.h>
31#include <osmocom/bsc/bsc_msc_data.h>
Holger Hans Peter Freytherf8c42192013-01-09 17:03:27 +010032
Holger Hans Peter Freytherf8c42192013-01-09 17:03:27 +010033CTRL_CMD_DEFINE_RANGE(net_mnc, "mnc", struct gsm_network, network_code, 0, 999);
34CTRL_CMD_DEFINE_RANGE(net_mcc, "mcc", struct gsm_network, country_code, 1, 999);
Holger Hans Peter Freytherf8c42192013-01-09 17:03:27 +010035
Holger Hans Peter Freyther6ca9f4f2013-01-09 17:30:11 +010036static int set_net_apply_config(struct ctrl_cmd *cmd, void *data)
37{
38 struct gsm_network *net = cmd->node;
39 struct gsm_bts *bts;
40
41 llist_for_each_entry(bts, &net->bts_list, list) {
42 if (!is_ipaccess_bts(bts))
43 continue;
44
Holger Hans Peter Freytherc6a65512016-03-16 15:27:38 +010045 /*
46 * The ip.access nanoBTS seems to be unrelaible on BSSGP
47 * so let's us just reboot it. For the sysmoBTS we can just
48 * restart the process as all state is gone.
49 */
50 if (!is_sysmobts_v2(bts) && strcmp(cmd->value, "restart") == 0) {
51 struct gsm_bts_trx *trx;
52 llist_for_each_entry_reverse(trx, &bts->trx_list, list)
53 abis_nm_ipaccess_restart(trx);
54 } else
55 ipaccess_drop_oml(bts);
Holger Hans Peter Freyther6ca9f4f2013-01-09 17:30:11 +010056 }
57
58 cmd->reply = "Tried to drop the BTS";
59 return CTRL_CMD_REPLY;
60}
61
Maxf6e51702017-01-11 18:37:55 +010062CTRL_CMD_DEFINE_WO_NOVRF(net_apply_config, "apply-configuration");
Holger Hans Peter Freyther6ca9f4f2013-01-09 17:30:11 +010063
Holger Hans Peter Freyther3adb7722014-03-04 17:16:58 +010064static int verify_net_mcc_mnc_apply(struct ctrl_cmd *cmd, const char *value, void *d)
65{
66 char *tmp, *saveptr, *mcc, *mnc;
67
68 tmp = talloc_strdup(cmd, value);
69 if (!tmp)
70 return 1;
71
72 mcc = strtok_r(tmp, ",", &saveptr);
73 mnc = strtok_r(NULL, ",", &saveptr);
74 talloc_free(tmp);
75
76 if (!mcc || !mnc)
77 return 1;
78 return 0;
79}
80
Holger Hans Peter Freyther3adb7722014-03-04 17:16:58 +010081static int set_net_mcc_mnc_apply(struct ctrl_cmd *cmd, void *data)
82{
83 struct gsm_network *net = cmd->node;
84 char *tmp, *saveptr, *mcc_str, *mnc_str;
85 int mcc, mnc;
86
87 tmp = talloc_strdup(cmd, cmd->value);
88 if (!tmp)
89 goto oom;
90
91
92 mcc_str = strtok_r(tmp, ",", &saveptr);
93 mnc_str = strtok_r(NULL, ",", &saveptr);
94
95 mcc = atoi(mcc_str);
96 mnc = atoi(mnc_str);
97
98 talloc_free(tmp);
99
100 if (net->network_code == mnc && net->country_code == mcc) {
101 cmd->reply = "Nothing changed";
102 return CTRL_CMD_REPLY;
103 }
104
105 net->network_code = mnc;
106 net->country_code = mcc;
107
108 return set_net_apply_config(cmd, data);
109
110oom:
111 cmd->reply = "OOM";
112 return CTRL_CMD_ERROR;
113}
Maxf6e51702017-01-11 18:37:55 +0100114CTRL_CMD_DEFINE_WO(net_mcc_mnc_apply, "mcc-mnc-apply");
Holger Hans Peter Freyther3adb7722014-03-04 17:16:58 +0100115
Holger Hans Peter Freyther054bc242014-11-10 11:41:03 +0100116/* BTS related commands below */
117CTRL_CMD_DEFINE_RANGE(bts_lac, "location-area-code", struct gsm_bts, location_area_code, 0, 65535);
Holger Hans Peter Freyther8a641412014-11-21 10:54:42 +0100118CTRL_CMD_DEFINE_RANGE(bts_ci, "cell-identity", struct gsm_bts, cell_identity, 0, 65535);
Holger Hans Peter Freyther054bc242014-11-10 11:41:03 +0100119
Holger Hans Peter Freytherb1461152014-11-21 10:20:29 +0100120static int set_bts_apply_config(struct ctrl_cmd *cmd, void *data)
121{
122 struct gsm_bts *bts = cmd->node;
123
124 if (!is_ipaccess_bts(bts)) {
125 cmd->reply = "BTS is not IP based";
126 return CTRL_CMD_ERROR;
127 }
128
129 ipaccess_drop_oml(bts);
130 cmd->reply = "Tried to drop the BTS";
131 return CTRL_CMD_REPLY;
132}
133
Maxf6e51702017-01-11 18:37:55 +0100134CTRL_CMD_DEFINE_WO_NOVRF(bts_apply_config, "apply-configuration");
Holger Hans Peter Freythera49b2c02014-11-21 11:18:45 +0100135
136static int set_bts_si(struct ctrl_cmd *cmd, void *data)
137{
138 struct gsm_bts *bts = cmd->node;
Alexander Chemerisc36a13b2015-05-30 14:40:54 -0400139 int rc;
Holger Hans Peter Freythera49b2c02014-11-21 11:18:45 +0100140
Alexander Chemerisc36a13b2015-05-30 14:40:54 -0400141 rc = gsm_bts_set_system_infos(bts);
142 if (rc != 0) {
143 cmd->reply = "Failed to generate SI";
144 return CTRL_CMD_ERROR;
Holger Hans Peter Freythera49b2c02014-11-21 11:18:45 +0100145 }
146
147 cmd->reply = "Generated new System Information";
148 return CTRL_CMD_REPLY;
149}
Maxf6e51702017-01-11 18:37:55 +0100150CTRL_CMD_DEFINE_WO_NOVRF(bts_si, "send-new-system-informations");
Holger Hans Peter Freyther5eebb7a2014-12-05 12:03:24 +0100151
152static int get_bts_chan_load(struct ctrl_cmd *cmd, void *data)
153{
154 int i;
155 struct pchan_load pl;
156 struct gsm_bts *bts;
157 const char *space = "";
158
159 bts = cmd->node;
160 memset(&pl, 0, sizeof(pl));
Neels Hofmeyr2afffd52016-09-25 17:01:20 +0200161 bts_chan_load(&pl, bts);
Holger Hans Peter Freyther5eebb7a2014-12-05 12:03:24 +0100162
163 cmd->reply = talloc_strdup(cmd, "");
164
165 for (i = 0; i < ARRAY_SIZE(pl.pchan); ++i) {
166 const struct load_counter *lc = &pl.pchan[i];
167
168 /* These can never have user load */
169 if (i == GSM_PCHAN_NONE)
170 continue;
171 if (i == GSM_PCHAN_CCCH)
172 continue;
173 if (i == GSM_PCHAN_PDCH)
174 continue;
Holger Hans Peter Freytherb8c204c2015-01-31 19:42:42 +0100175 if (i == GSM_PCHAN_UNKNOWN)
176 continue;
Holger Hans Peter Freyther5eebb7a2014-12-05 12:03:24 +0100177
178 cmd->reply = talloc_asprintf_append(cmd->reply,
179 "%s%s,%u,%u",
180 space, gsm_pchan_name(i), lc->used, lc->total);
181 if (!cmd->reply)
182 goto error;
183 space = " ";
184 }
185
186 return CTRL_CMD_REPLY;
187
188error:
189 cmd->reply = "Memory allocation failure";
190 return CTRL_CMD_ERROR;
191}
192
Maxf6e51702017-01-11 18:37:55 +0100193CTRL_CMD_DEFINE_RO(bts_chan_load, "channel-load");
Holger Hans Peter Freyther1f6cce72014-12-05 14:44:21 +0100194
195static int get_bts_oml_conn(struct ctrl_cmd *cmd, void *data)
196{
Max3d049d22017-10-09 17:12:53 +0200197 const struct gsm_bts *bts = cmd->node;
Holger Hans Peter Freyther1f6cce72014-12-05 14:44:21 +0100198
Max3d049d22017-10-09 17:12:53 +0200199 cmd->reply = get_model_oml_status(bts);
200
Holger Hans Peter Freyther1f6cce72014-12-05 14:44:21 +0100201 return CTRL_CMD_REPLY;
202}
203
Maxf6e51702017-01-11 18:37:55 +0100204CTRL_CMD_DEFINE_RO(bts_oml_conn, "oml-connection-state");
Holger Hans Peter Freyther1f6cce72014-12-05 14:44:21 +0100205
Max25cc4072017-10-10 14:50:35 +0200206static int get_bts_oml_up(struct ctrl_cmd *cmd, void *data)
207{
208 const struct gsm_bts *bts = cmd->node;
209
210 cmd->reply = talloc_asprintf(cmd, "%llu", bts_uptime(bts));
211 if (!cmd->reply) {
212 cmd->reply = "OOM";
213 return CTRL_CMD_ERROR;
214 }
215
216 return CTRL_CMD_REPLY;
217}
218
219CTRL_CMD_DEFINE_RO(bts_oml_up, "oml-uptime");
220
Holger Hans Peter Freyther4e13a8f2015-01-31 22:16:00 +0100221static int verify_bts_gprs_mode(struct ctrl_cmd *cmd, const char *value, void *_data)
222{
223 int valid;
224 enum bts_gprs_mode mode;
225 struct gsm_bts *bts = cmd->node;
226
227 mode = bts_gprs_mode_parse(value, &valid);
228 if (!valid) {
229 cmd->reply = "Mode is not known";
230 return 1;
231 }
232
233 if (!bts_gprs_mode_is_compat(bts, mode)) {
234 cmd->reply = "bts does not support this mode";
235 return 1;
236 }
237
238 return 0;
239}
240
241static int get_bts_gprs_mode(struct ctrl_cmd *cmd, void *data)
242{
243 struct gsm_bts *bts = cmd->node;
244
245 cmd->reply = talloc_strdup(cmd, bts_gprs_mode_name(bts->gprs.mode));
246 return CTRL_CMD_REPLY;
247}
248
249static int set_bts_gprs_mode(struct ctrl_cmd *cmd, void *data)
250{
251 struct gsm_bts *bts = cmd->node;
252
253 bts->gprs.mode = bts_gprs_mode_parse(cmd->value, NULL);
254 return get_bts_gprs_mode(cmd, data);
255}
256
257CTRL_CMD_DEFINE(bts_gprs_mode, "gprs-mode");
258
Holger Hans Peter Freyther349c40f2015-02-10 21:37:16 +0100259static int get_bts_rf_state(struct ctrl_cmd *cmd, void *data)
260{
261 const char *oper, *admin, *policy;
262 struct gsm_bts *bts = cmd->node;
263
264 if (!bts) {
265 cmd->reply = "bts not found.";
266 return CTRL_CMD_ERROR;
267 }
268
269 oper = osmo_bsc_rf_get_opstate_name(osmo_bsc_rf_get_opstate_by_bts(bts));
270 admin = osmo_bsc_rf_get_adminstate_name(osmo_bsc_rf_get_adminstate_by_bts(bts));
271 policy = osmo_bsc_rf_get_policy_name(osmo_bsc_rf_get_policy_by_bts(bts));
272
273 cmd->reply = talloc_asprintf(cmd, "%s,%s,%s", oper, admin, policy);
274 if (!cmd->reply) {
275 cmd->reply = "OOM.";
276 return CTRL_CMD_ERROR;
277 }
278
279 return CTRL_CMD_REPLY;
280}
281CTRL_CMD_DEFINE_RO(bts_rf_state, "rf_state");
282
283static int get_net_rf_lock(struct ctrl_cmd *cmd, void *data)
284{
Holger Hans Peter Freyther66105fd2015-02-10 23:03:25 +0100285 struct gsm_network *net = cmd->node;
286 struct gsm_bts *bts;
287 const char *policy_name;
288
289 policy_name = osmo_bsc_rf_get_policy_name(net->bsc_data->rf_ctrl->policy);
290
291 llist_for_each_entry(bts, &net->bts_list, list) {
292 struct gsm_bts_trx *trx;
293
294 /* Exclude the BTS from the global lock */
295 if (bts->excl_from_rf_lock)
296 continue;
297
298 llist_for_each_entry(trx, &bts->trx_list, list) {
299 if (trx->mo.nm_state.availability == NM_AVSTATE_OK &&
300 trx->mo.nm_state.operational != NM_OPSTATE_DISABLED) {
301 cmd->reply = talloc_asprintf(cmd,
302 "state=on,policy=%s,bts=%u,trx=%u",
303 policy_name, bts->nr, trx->nr);
304 return CTRL_CMD_REPLY;
305 }
306 }
307 }
308
309 cmd->reply = talloc_asprintf(cmd, "state=off,policy=%s",
310 policy_name);
311 return CTRL_CMD_REPLY;
Holger Hans Peter Freyther349c40f2015-02-10 21:37:16 +0100312}
313
314#define TIME_FORMAT_RFC2822 "%a, %d %b %Y %T %z"
315
316static int set_net_rf_lock(struct ctrl_cmd *cmd, void *data)
317{
318 int locked = atoi(cmd->value);
319 struct gsm_network *net = cmd->node;
320 time_t now = time(NULL);
321 char now_buf[64];
322 struct osmo_bsc_rf *rf;
323
324 if (!net) {
325 cmd->reply = "net not found.";
326 return CTRL_CMD_ERROR;
327 }
328
329 rf = net->bsc_data->rf_ctrl;
330
331 if (!rf) {
332 cmd->reply = "RF Ctrl is not enabled in the BSC Configuration";
333 return CTRL_CMD_ERROR;
334 }
335
336 talloc_free(rf->last_rf_lock_ctrl_command);
337 strftime(now_buf, sizeof(now_buf), TIME_FORMAT_RFC2822, gmtime(&now));
338 rf->last_rf_lock_ctrl_command =
339 talloc_asprintf(rf, "rf_locked %u (%s)", locked, now_buf);
340
341 osmo_bsc_rf_schedule_lock(rf, locked == 1 ? '0' : '1');
342
343 cmd->reply = talloc_asprintf(cmd, "%u", locked);
344 if (!cmd->reply) {
345 cmd->reply = "OOM.";
346 return CTRL_CMD_ERROR;
347 }
348
349 return CTRL_CMD_REPLY;
350}
351
352static int verify_net_rf_lock(struct ctrl_cmd *cmd, const char *value, void *data)
353{
354 int locked = atoi(cmd->value);
355
356 if ((locked != 0) && (locked != 1))
357 return 1;
358
359 return 0;
360}
361CTRL_CMD_DEFINE(net_rf_lock, "rf_locked");
Holger Hans Peter Freyther4e13a8f2015-01-31 22:16:00 +0100362
Holger Hans Peter Freytherca415192015-02-10 21:55:37 +0100363static int get_net_bts_num(struct ctrl_cmd *cmd, void *data)
364{
365 struct gsm_network *net = cmd->node;
366
367 cmd->reply = talloc_asprintf(cmd, "%u", net->num_bts);
368 return CTRL_CMD_REPLY;
369}
370CTRL_CMD_DEFINE_RO(net_bts_num, "number-of-bts");
371
Holger Hans Peter Freytherd092f482014-03-23 11:17:27 +0100372/* TRX related commands below here */
373CTRL_HELPER_GET_INT(trx_max_power, struct gsm_bts_trx, max_power_red);
Holger Hans Peter Freytherd092f482014-03-23 11:17:27 +0100374static int verify_trx_max_power(struct ctrl_cmd *cmd, const char *value, void *_data)
375{
376 int tmp = atoi(value);
377
378 if (tmp < 0 || tmp > 22) {
379 cmd->reply = "Value must be between 0 and 22";
380 return -1;
381 }
382
383 if (tmp & 1) {
384 cmd->reply = "Value must be even";
385 return -1;
386 }
387
388 return 0;
389}
Holger Hans Peter Freyther175a2402013-01-09 19:55:04 +0100390CTRL_CMD_DEFINE_RANGE(trx_arfcn, "arfcn", struct gsm_bts_trx, arfcn, 0, 1023);
Holger Hans Peter Freyther8a158bb2014-03-26 14:24:42 +0100391
392static int set_trx_max_power(struct ctrl_cmd *cmd, void *_data)
393{
394 struct gsm_bts_trx *trx = cmd->node;
395 int old_power;
396
397 /* remember the old value, set the new one */
398 old_power = trx->max_power_red;
399 trx->max_power_red = atoi(cmd->value);
400
401 /* Maybe update the value */
402 if (old_power != trx->max_power_red) {
403 LOGP(DCTRL, LOGL_NOTICE,
404 "%s updating max_pwr_red(%d)\n",
405 gsm_trx_name(trx), trx->max_power_red);
406 abis_nm_update_max_power_red(trx);
407 }
408
409 return get_trx_max_power(cmd, _data);
410}
Holger Hans Peter Freytherd092f482014-03-23 11:17:27 +0100411CTRL_CMD_DEFINE(trx_max_power, "max-power-reduction");
412
Holger Hans Peter Freytherf8c42192013-01-09 17:03:27 +0100413int bsc_base_ctrl_cmds_install(void)
414{
415 int rc = 0;
416 rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_mnc);
417 rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_mcc);
Holger Hans Peter Freyther6ca9f4f2013-01-09 17:30:11 +0100418 rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_apply_config);
Holger Hans Peter Freyther3adb7722014-03-04 17:16:58 +0100419 rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_mcc_mnc_apply);
Holger Hans Peter Freyther349c40f2015-02-10 21:37:16 +0100420 rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_rf_lock);
Holger Hans Peter Freytherca415192015-02-10 21:55:37 +0100421 rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_bts_num);
Holger Hans Peter Freytherf8c42192013-01-09 17:03:27 +0100422
Holger Hans Peter Freyther054bc242014-11-10 11:41:03 +0100423 rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_lac);
Holger Hans Peter Freyther8a641412014-11-21 10:54:42 +0100424 rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_ci);
Holger Hans Peter Freytherb1461152014-11-21 10:20:29 +0100425 rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_apply_config);
Holger Hans Peter Freythera49b2c02014-11-21 11:18:45 +0100426 rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_si);
Holger Hans Peter Freyther5eebb7a2014-12-05 12:03:24 +0100427 rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_chan_load);
Holger Hans Peter Freyther1f6cce72014-12-05 14:44:21 +0100428 rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_oml_conn);
Max25cc4072017-10-10 14:50:35 +0200429 rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_oml_up);
Holger Hans Peter Freyther4e13a8f2015-01-31 22:16:00 +0100430 rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_gprs_mode);
Holger Hans Peter Freyther349c40f2015-02-10 21:37:16 +0100431 rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_rf_state);
Holger Hans Peter Freyther054bc242014-11-10 11:41:03 +0100432
Holger Hans Peter Freytherd092f482014-03-23 11:17:27 +0100433 rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_trx_max_power);
Holger Hans Peter Freyther175a2402013-01-09 19:55:04 +0100434 rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_trx_arfcn);
435
Holger Hans Peter Freytherf8c42192013-01-09 17:03:27 +0100436 return rc;
437}