blob: 368d0e7c6d7cf2a97a5db05504315db0bf569e15 [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 Freytherf8c42192013-01-09 17:03:27 +010022
Harald Welteba874b82014-08-20 23:47:15 +020023#include <osmocom/ctrl/control_cmd.h>
Holger Hans Peter Freyther6ca9f4f2013-01-09 17:30:11 +010024#include <openbsc/ipaccess.h>
Holger Hans Peter Freytherf8c42192013-01-09 17:03:27 +010025#include <openbsc/gsm_data.h>
Holger Hans Peter Freyther8a158bb2014-03-26 14:24:42 +010026#include <openbsc/abis_nm.h>
27#include <openbsc/debug.h>
Holger Hans Peter Freyther5eebb7a2014-12-05 12:03:24 +010028#include <openbsc/chan_alloc.h>
Holger Hans Peter Freytherf8c42192013-01-09 17:03:27 +010029
30#define CTRL_CMD_VTY_STRING(cmdname, cmdstr, dtype, element) \
31 CTRL_HELPER_GET_STRING(cmdname, dtype, element) \
32 CTRL_HELPER_SET_STRING(cmdname, dtype, element) \
33static struct ctrl_cmd_element cmd_##cmdname = { \
34 .name = cmdstr, \
Holger Hans Peter Freytherf8c42192013-01-09 17:03:27 +010035 .get = get_##cmdname, \
36 .set = set_##cmdname, \
37 .verify = verify_vty_description_string, \
38}
39
40/**
41 * Check that there are no newlines or comments or other things
42 * that could make the VTY configuration unparsable.
43 */
44static int verify_vty_description_string(struct ctrl_cmd *cmd,
45 const char *value, void *data)
46{
47 int i;
48 const size_t len = strlen(value);
49
50 for (i = 0; i < len; ++i) {
51 switch(value[i]) {
52 case '#':
53 case '\n':
54 case '\r':
55 cmd->reply = "String includes illegal character";
56 return -1;
57 default:
58 break;
59 }
60 }
61
62 return 0;
63}
64
65CTRL_CMD_DEFINE_RANGE(net_mnc, "mnc", struct gsm_network, network_code, 0, 999);
66CTRL_CMD_DEFINE_RANGE(net_mcc, "mcc", struct gsm_network, country_code, 1, 999);
67CTRL_CMD_VTY_STRING(net_short_name, "short-name", struct gsm_network, name_short);
68CTRL_CMD_VTY_STRING(net_long_name, "long-name", struct gsm_network, name_long);
69
Holger Hans Peter Freyther6ca9f4f2013-01-09 17:30:11 +010070static int verify_net_apply_config(struct ctrl_cmd *cmd, const char *v, void *d)
71{
72 return 0;
73}
74
75static int get_net_apply_config(struct ctrl_cmd *cmd, void *data)
76{
77 cmd->reply = "Write only attribute";
78 return CTRL_CMD_ERROR;
79}
80
81static int set_net_apply_config(struct ctrl_cmd *cmd, void *data)
82{
83 struct gsm_network *net = cmd->node;
84 struct gsm_bts *bts;
85
86 llist_for_each_entry(bts, &net->bts_list, list) {
87 if (!is_ipaccess_bts(bts))
88 continue;
89
90 ipaccess_drop_oml(bts);
91 }
92
93 cmd->reply = "Tried to drop the BTS";
94 return CTRL_CMD_REPLY;
95}
96
97CTRL_CMD_DEFINE(net_apply_config, "apply-configuration");
98
Holger Hans Peter Freyther3adb7722014-03-04 17:16:58 +010099static int verify_net_mcc_mnc_apply(struct ctrl_cmd *cmd, const char *value, void *d)
100{
101 char *tmp, *saveptr, *mcc, *mnc;
102
103 tmp = talloc_strdup(cmd, value);
104 if (!tmp)
105 return 1;
106
107 mcc = strtok_r(tmp, ",", &saveptr);
108 mnc = strtok_r(NULL, ",", &saveptr);
109 talloc_free(tmp);
110
111 if (!mcc || !mnc)
112 return 1;
113 return 0;
114}
115
116static int get_net_mcc_mnc_apply(struct ctrl_cmd *cmd, void *data)
117{
118 cmd->reply = "Write only attribute";
119 return CTRL_CMD_ERROR;
120}
121
122static int set_net_mcc_mnc_apply(struct ctrl_cmd *cmd, void *data)
123{
124 struct gsm_network *net = cmd->node;
125 char *tmp, *saveptr, *mcc_str, *mnc_str;
126 int mcc, mnc;
127
128 tmp = talloc_strdup(cmd, cmd->value);
129 if (!tmp)
130 goto oom;
131
132
133 mcc_str = strtok_r(tmp, ",", &saveptr);
134 mnc_str = strtok_r(NULL, ",", &saveptr);
135
136 mcc = atoi(mcc_str);
137 mnc = atoi(mnc_str);
138
139 talloc_free(tmp);
140
141 if (net->network_code == mnc && net->country_code == mcc) {
142 cmd->reply = "Nothing changed";
143 return CTRL_CMD_REPLY;
144 }
145
146 net->network_code = mnc;
147 net->country_code = mcc;
148
149 return set_net_apply_config(cmd, data);
150
151oom:
152 cmd->reply = "OOM";
153 return CTRL_CMD_ERROR;
154}
155CTRL_CMD_DEFINE(net_mcc_mnc_apply, "mcc-mnc-apply");
156
Holger Hans Peter Freyther054bc242014-11-10 11:41:03 +0100157/* BTS related commands below */
158CTRL_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 +0100159CTRL_CMD_DEFINE_RANGE(bts_ci, "cell-identity", struct gsm_bts, cell_identity, 0, 65535);
Holger Hans Peter Freyther054bc242014-11-10 11:41:03 +0100160
Holger Hans Peter Freytherb1461152014-11-21 10:20:29 +0100161static int verify_bts_apply_config(struct ctrl_cmd *cmd, const char *v, void *d)
162{
163 return 0;
164}
165
166static int get_bts_apply_config(struct ctrl_cmd *cmd, void *data)
167{
168 cmd->reply = "Write only attribute";
169 return CTRL_CMD_ERROR;
170}
171
172static int set_bts_apply_config(struct ctrl_cmd *cmd, void *data)
173{
174 struct gsm_bts *bts = cmd->node;
175
176 if (!is_ipaccess_bts(bts)) {
177 cmd->reply = "BTS is not IP based";
178 return CTRL_CMD_ERROR;
179 }
180
181 ipaccess_drop_oml(bts);
182 cmd->reply = "Tried to drop the BTS";
183 return CTRL_CMD_REPLY;
184}
185
186CTRL_CMD_DEFINE(bts_apply_config, "apply-configuration");
187
Holger Hans Peter Freythera49b2c02014-11-21 11:18:45 +0100188static int verify_bts_si(struct ctrl_cmd *cmd, const char *v, void *d)
189{
190 return 0;
191}
192
193static int get_bts_si(struct ctrl_cmd *cmd, void *data)
194{
195 cmd->reply = "Write only attribute";
196 return CTRL_CMD_ERROR;
197}
198
199static int set_bts_si(struct ctrl_cmd *cmd, void *data)
200{
201 struct gsm_bts *bts = cmd->node;
202 struct gsm_bts_trx *trx;
203
204 /* Generate a new ID */
205 bts->bcch_change_mark += 1;
206 bts->bcch_change_mark %= 0x7;
207
208 llist_for_each_entry(trx, &bts->trx_list, list) {
209 int rc;
210
211 rc = gsm_bts_trx_set_system_infos(trx);
212 if (rc != 0) {
213 cmd->reply = "Failed to generate SI";
214 return CTRL_CMD_ERROR;
215 }
216 }
217
218 cmd->reply = "Generated new System Information";
219 return CTRL_CMD_REPLY;
220}
221CTRL_CMD_DEFINE(bts_si, "send-new-system-informations");
222
Holger Hans Peter Freyther5eebb7a2014-12-05 12:03:24 +0100223static int verify_bts_chan_load(struct ctrl_cmd *cmd, const char *v, void *d)
224{
225 return 0;
226}
227
228static int get_bts_chan_load(struct ctrl_cmd *cmd, void *data)
229{
230 int i;
231 struct pchan_load pl;
232 struct gsm_bts *bts;
233 const char *space = "";
234
235 bts = cmd->node;
236 memset(&pl, 0, sizeof(pl));
237 bts_chan_load(&pl, bts);
238
239 cmd->reply = talloc_strdup(cmd, "");
240
241 for (i = 0; i < ARRAY_SIZE(pl.pchan); ++i) {
242 const struct load_counter *lc = &pl.pchan[i];
243
244 /* These can never have user load */
245 if (i == GSM_PCHAN_NONE)
246 continue;
247 if (i == GSM_PCHAN_CCCH)
248 continue;
249 if (i == GSM_PCHAN_PDCH)
250 continue;
Holger Hans Peter Freytherb8c204c2015-01-31 19:42:42 +0100251 if (i == GSM_PCHAN_UNKNOWN)
252 continue;
Holger Hans Peter Freyther5eebb7a2014-12-05 12:03:24 +0100253
254 cmd->reply = talloc_asprintf_append(cmd->reply,
255 "%s%s,%u,%u",
256 space, gsm_pchan_name(i), lc->used, lc->total);
257 if (!cmd->reply)
258 goto error;
259 space = " ";
260 }
261
262 return CTRL_CMD_REPLY;
263
264error:
265 cmd->reply = "Memory allocation failure";
266 return CTRL_CMD_ERROR;
267}
268
269static int set_bts_chan_load(struct ctrl_cmd *cmd, void *data)
270{
271 cmd->reply = "Read only attribute";
272 return CTRL_CMD_ERROR;
273}
274CTRL_CMD_DEFINE(bts_chan_load, "channel-load");
275
Holger Hans Peter Freyther1f6cce72014-12-05 14:44:21 +0100276static int verify_bts_oml_conn(struct ctrl_cmd *cmd, const char *value, void *_data)
277{
278 struct gsm_bts *bts = cmd->node;
279
280 if (!is_ipaccess_bts(bts)) {
281 cmd->reply = "";
282 return -1;
283 }
284 return 0;
285}
286
287static int get_bts_oml_conn(struct ctrl_cmd *cmd, void *data)
288{
289 struct gsm_bts *bts = cmd->node;
290
291 cmd->reply = bts->oml_link ? "connected" : "disconnected";
292 return CTRL_CMD_REPLY;
293}
294
295static int set_bts_oml_conn(struct ctrl_cmd *cmd, void *data)
296{
297 cmd->reply = "Read only attribute";
298 return CTRL_CMD_ERROR;
299}
300CTRL_CMD_DEFINE(bts_oml_conn, "oml-connection-state");
301
Holger Hans Peter Freyther4e13a8f2015-01-31 22:16:00 +0100302static int verify_bts_gprs_mode(struct ctrl_cmd *cmd, const char *value, void *_data)
303{
304 int valid;
305 enum bts_gprs_mode mode;
306 struct gsm_bts *bts = cmd->node;
307
308 mode = bts_gprs_mode_parse(value, &valid);
309 if (!valid) {
310 cmd->reply = "Mode is not known";
311 return 1;
312 }
313
314 if (!bts_gprs_mode_is_compat(bts, mode)) {
315 cmd->reply = "bts does not support this mode";
316 return 1;
317 }
318
319 return 0;
320}
321
322static int get_bts_gprs_mode(struct ctrl_cmd *cmd, void *data)
323{
324 struct gsm_bts *bts = cmd->node;
325
326 cmd->reply = talloc_strdup(cmd, bts_gprs_mode_name(bts->gprs.mode));
327 return CTRL_CMD_REPLY;
328}
329
330static int set_bts_gprs_mode(struct ctrl_cmd *cmd, void *data)
331{
332 struct gsm_bts *bts = cmd->node;
333
334 bts->gprs.mode = bts_gprs_mode_parse(cmd->value, NULL);
335 return get_bts_gprs_mode(cmd, data);
336}
337
338CTRL_CMD_DEFINE(bts_gprs_mode, "gprs-mode");
339
340
Holger Hans Peter Freytherd092f482014-03-23 11:17:27 +0100341/* TRX related commands below here */
342CTRL_HELPER_GET_INT(trx_max_power, struct gsm_bts_trx, max_power_red);
Holger Hans Peter Freytherd092f482014-03-23 11:17:27 +0100343static int verify_trx_max_power(struct ctrl_cmd *cmd, const char *value, void *_data)
344{
345 int tmp = atoi(value);
346
347 if (tmp < 0 || tmp > 22) {
348 cmd->reply = "Value must be between 0 and 22";
349 return -1;
350 }
351
352 if (tmp & 1) {
353 cmd->reply = "Value must be even";
354 return -1;
355 }
356
357 return 0;
358}
Holger Hans Peter Freyther175a2402013-01-09 19:55:04 +0100359CTRL_CMD_DEFINE_RANGE(trx_arfcn, "arfcn", struct gsm_bts_trx, arfcn, 0, 1023);
Holger Hans Peter Freyther8a158bb2014-03-26 14:24:42 +0100360
361static int set_trx_max_power(struct ctrl_cmd *cmd, void *_data)
362{
363 struct gsm_bts_trx *trx = cmd->node;
364 int old_power;
365
366 /* remember the old value, set the new one */
367 old_power = trx->max_power_red;
368 trx->max_power_red = atoi(cmd->value);
369
370 /* Maybe update the value */
371 if (old_power != trx->max_power_red) {
372 LOGP(DCTRL, LOGL_NOTICE,
373 "%s updating max_pwr_red(%d)\n",
374 gsm_trx_name(trx), trx->max_power_red);
375 abis_nm_update_max_power_red(trx);
376 }
377
378 return get_trx_max_power(cmd, _data);
379}
Holger Hans Peter Freytherd092f482014-03-23 11:17:27 +0100380CTRL_CMD_DEFINE(trx_max_power, "max-power-reduction");
381
Holger Hans Peter Freytherf8c42192013-01-09 17:03:27 +0100382int bsc_base_ctrl_cmds_install(void)
383{
384 int rc = 0;
385 rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_mnc);
386 rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_mcc);
387 rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_short_name);
388 rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_long_name);
Holger Hans Peter Freyther6ca9f4f2013-01-09 17:30:11 +0100389 rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_apply_config);
Holger Hans Peter Freyther3adb7722014-03-04 17:16:58 +0100390 rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_mcc_mnc_apply);
Holger Hans Peter Freytherf8c42192013-01-09 17:03:27 +0100391
Holger Hans Peter Freyther054bc242014-11-10 11:41:03 +0100392 rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_lac);
Holger Hans Peter Freyther8a641412014-11-21 10:54:42 +0100393 rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_ci);
Holger Hans Peter Freytherb1461152014-11-21 10:20:29 +0100394 rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_apply_config);
Holger Hans Peter Freythera49b2c02014-11-21 11:18:45 +0100395 rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_si);
Holger Hans Peter Freyther5eebb7a2014-12-05 12:03:24 +0100396 rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_chan_load);
Holger Hans Peter Freyther1f6cce72014-12-05 14:44:21 +0100397 rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_oml_conn);
Holger Hans Peter Freyther4e13a8f2015-01-31 22:16:00 +0100398 rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_gprs_mode);
Holger Hans Peter Freyther054bc242014-11-10 11:41:03 +0100399
Holger Hans Peter Freytherd092f482014-03-23 11:17:27 +0100400 rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_trx_max_power);
Holger Hans Peter Freyther175a2402013-01-09 19:55:04 +0100401 rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_trx_arfcn);
402
Holger Hans Peter Freytherf8c42192013-01-09 17:03:27 +0100403 return rc;
404}