blob: d48ff9562fb4b15a2d0cf4ba2c5723a75e7ec68c [file] [log] [blame]
Harald Welte51c82382011-02-12 14:44:16 +01001/* VTY interface for A-bis OM2000 */
2
3/* (C) 2010-2011 by Harald Welte <laforge@gnumonks.org>
4 *
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 */
21
22#include <stdlib.h>
23#include <unistd.h>
24#include <errno.h>
25#include <stdint.h>
26
27#include <arpa/inet.h>
28
29#include <openbsc/gsm_data.h>
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010030#include <osmocom/core/msgb.h>
31#include <osmocom/gsm/tlv.h>
32#include <osmocom/core/talloc.h>
Harald Welte51c82382011-02-12 14:44:16 +010033#include <openbsc/debug.h>
34#include <openbsc/signal.h>
35#include <openbsc/abis_om2000.h>
36#include <openbsc/vty.h>
37
38#include <osmocom/vty/vty.h>
39#include <osmocom/vty/command.h>
40#include <osmocom/vty/logging.h>
41#include <osmocom/vty/telnet_interface.h>
42
43extern struct gsm_network *bsc_gsmnet;
44
45static struct cmd_node om2k_node = {
46 OM2K_NODE,
Harald Welteb0ec9e32011-02-12 20:50:58 +010047 "%s(om2k)# ",
Harald Welte51c82382011-02-12 14:44:16 +010048 1,
49};
50
51struct oml_node_state {
52 struct gsm_bts *bts;
53 struct abis_om2k_mo mo;
54};
55
56static int dummy_config_write(struct vty *v)
57{
58 return CMD_SUCCESS;
59}
60
61/* FIXME: auto-generate those strings from the value_string lists */
62#define OM2K_OBJCLASS_VTY "(trxc|ts|tf|is|con|dp|cf|tx|rx)"
Harald Welte9c0958b2011-02-13 22:51:03 +010063#define OM2K_OBJCLASS_VTY_HELP "TRX Controller\n" \
64 "Timeslot\n" \
65 "Timing Function\n" \
66 "Interface Switch\n" \
67 "Abis Concentrator\n" \
68 "Digital Path\n" \
69 "Central Function\n" \
70 "Transmitter\n" \
71 "Receiver\n"
Harald Welte51c82382011-02-12 14:44:16 +010072
73DEFUN(om2k_class_inst, om2k_class_inst_cmd,
74 "bts <0-255> om2000 class " OM2K_OBJCLASS_VTY
75 " <0-255> <0-255> <0-255>",
76 "BTS related commands\n" "BTS Number\n"
77 "Manipulate the OM2000 managed objects\n"
78 "Object Class\n" OM2K_OBJCLASS_VTY_HELP
79 "BTS Number\n" "Associated SO Instance\n" "Instance Number\n")
80{
81 struct gsm_bts *bts;
82 struct oml_node_state *oms;
83 int bts_nr = atoi(argv[0]);
84
Neels Hofmeyr663debc2016-05-09 21:18:08 +020085 bts = gsm_bts_num(gsmnet_from_vty(vty), bts_nr);
Harald Welte51c82382011-02-12 14:44:16 +010086 if (!bts) {
87 vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
88 return CMD_WARNING;
89 }
90
91 if (bts->type != GSM_BTS_TYPE_RBS2000) {
92 vty_out(vty, "%% BTS %d not an Ericsson RBS%s",
93 bts_nr, VTY_NEWLINE);
94 return CMD_WARNING;
95 }
96
97 oms = talloc_zero(tall_bsc_ctx, struct oml_node_state);
98 if (!oms)
99 return CMD_WARNING;
100
101 oms->bts = bts;
102 oms->mo.class = get_string_value(om2k_mo_class_short_vals, argv[1]);
103 oms->mo.bts = atoi(argv[2]);
104 oms->mo.assoc_so = atoi(argv[3]);
105 oms->mo.inst = atoi(argv[4]);
106
107 vty->index = oms;
108 vty->node = OM2K_NODE;
109
110 return CMD_SUCCESS;
111
112}
113
114DEFUN(om2k_classnum_inst, om2k_classnum_inst_cmd,
115 "bts <0-255> om2000 class <0-255> <0-255> <0-255> <0-255>",
116 "BTS related commands\n" "BTS Number\n"
117 "Manipulate the OML managed objects\n"
118 "Object Class\n" "Object Class\n"
119 "BTS Number\n" "Associated SO Instance\n" "Instance Number\n")
120{
121 struct gsm_bts *bts;
122 struct oml_node_state *oms;
123 int bts_nr = atoi(argv[0]);
124
Neels Hofmeyr663debc2016-05-09 21:18:08 +0200125 bts = gsm_bts_num(gsmnet_from_vty(vty), bts_nr);
Harald Welte51c82382011-02-12 14:44:16 +0100126 if (!bts) {
127 vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
128 return CMD_WARNING;
129 }
130
131 oms = talloc_zero(tall_bsc_ctx, struct oml_node_state);
132 if (!oms)
133 return CMD_WARNING;
134
135 oms->bts = bts;
136 oms->mo.class = atoi(argv[1]);
137 oms->mo.bts = atoi(argv[2]);
138 oms->mo.assoc_so = atoi(argv[3]);
139 oms->mo.inst = atoi(argv[4]);
140
141 vty->index = oms;
142 vty->node = OM2K_NODE;
143
144 return CMD_SUCCESS;
145}
146
147DEFUN(om2k_reset, om2k_reset_cmd,
148 "reset-command",
149 "Reset the MO\n")
150{
151 struct oml_node_state *oms = vty->index;
152
153 abis_om2k_tx_reset_cmd(oms->bts, &oms->mo);
154 return CMD_SUCCESS;
155}
156
157DEFUN(om2k_start, om2k_start_cmd,
158 "start-request",
159 "Start the MO\n")
160{
161 struct oml_node_state *oms = vty->index;
162
163 abis_om2k_tx_start_req(oms->bts, &oms->mo);
164 return CMD_SUCCESS;
165}
166
167DEFUN(om2k_status, om2k_status_cmd,
168 "status-request",
169 "Get the MO Status\n")
170{
171 struct oml_node_state *oms = vty->index;
172
173 abis_om2k_tx_status_req(oms->bts, &oms->mo);
174 return CMD_SUCCESS;
175}
176
Harald Welte6fec79d2011-02-12 14:57:17 +0100177DEFUN(om2k_connect, om2k_connect_cmd,
178 "connect-command",
179 "Connect the MO\n")
180{
181 struct oml_node_state *oms = vty->index;
182
183 abis_om2k_tx_connect_cmd(oms->bts, &oms->mo);
184 return CMD_SUCCESS;
185}
186
187DEFUN(om2k_disconnect, om2k_disconnect_cmd,
188 "disconnect-command",
189 "Disconnect the MO\n")
190{
191 struct oml_node_state *oms = vty->index;
192
193 abis_om2k_tx_disconnect_cmd(oms->bts, &oms->mo);
194 return CMD_SUCCESS;
195}
196
Harald Welte0741ffe2011-02-12 18:48:53 +0100197DEFUN(om2k_enable, om2k_enable_cmd,
198 "enable-request",
199 "Enable the MO\n")
200{
201 struct oml_node_state *oms = vty->index;
202
203 abis_om2k_tx_enable_req(oms->bts, &oms->mo);
204 return CMD_SUCCESS;
205}
206
207DEFUN(om2k_disable, om2k_disable_cmd,
208 "disable-request",
209 "Disable the MO\n")
210{
211 struct oml_node_state *oms = vty->index;
212
213 abis_om2k_tx_disable_req(oms->bts, &oms->mo);
214 return CMD_SUCCESS;
215}
216
Harald Welte6fec79d2011-02-12 14:57:17 +0100217DEFUN(om2k_op_info, om2k_op_info_cmd,
218 "operational-info <0-1>",
Harald Weltecfaabbb2012-08-16 23:23:50 +0200219 "Set operational information\n"
Harald Welted13e0cd2012-08-17 09:52:03 +0200220 "Set operational info to 0 or 1\n")
Harald Welte6fec79d2011-02-12 14:57:17 +0100221{
222 struct oml_node_state *oms = vty->index;
223 int oper = atoi(argv[0]);
224
225 abis_om2k_tx_op_info(oms->bts, &oms->mo, oper);
226 return CMD_SUCCESS;
227}
228
Harald Welte8024d8f2011-02-12 15:07:30 +0100229DEFUN(om2k_test, om2k_test_cmd,
230 "test-request",
231 "Test the MO\n")
232{
233 struct oml_node_state *oms = vty->index;
234
235 abis_om2k_tx_test_req(oms->bts, &oms->mo);
236 return CMD_SUCCESS;
237}
238
root45799782016-10-15 21:24:57 +0200239DEFUN(om2k_cap_req, om2k_cap_req_cmd,
240 "capabilities-request",
241 "Request MO capabilities\n")
242{
243 struct oml_node_state *oms = vty->index;
244
245 abis_om2k_tx_cap_req(oms->bts, &oms->mo);
246 return CMD_SUCCESS;
247}
248
249
Harald Weltea02085d2011-02-13 22:45:02 +0100250struct con_conn_group {
251 struct llist_head list;
252
253 uint8_t cg;
254 uint16_t ccp;
255 uint8_t tag;
256 uint8_t tei;
257};
258
259static void add_con_list(struct gsm_bts *bts, uint8_t cg, uint16_t ccp,
260 uint8_t tag, uint8_t tei)
261{
262 struct con_conn_group *ent = talloc_zero(bts, struct con_conn_group);
263
264 ent->cg = cg;
265 ent->ccp = ccp;
266 ent->tag = tag;
267 ent->tei = tei;
268
Harald Welteda871542011-02-14 16:32:44 +0100269 llist_add_tail(&ent->list, &bts->rbs2000.con.conn_groups);
Harald Weltea02085d2011-02-13 22:45:02 +0100270}
271
272static int del_con_list(struct gsm_bts *bts, uint8_t cg, uint16_t ccp,
273 uint8_t tag, uint8_t tei)
274{
275 struct con_conn_group *grp, *grp2;
276
277 llist_for_each_entry_safe(grp, grp2, &bts->rbs2000.con.conn_groups, list) {
278 if (grp->cg == cg && grp->ccp == ccp && grp->tag == tag
279 && grp->tei == tei) {
280 llist_del(&grp->list);
281 talloc_free(grp);
282 return 0;
283 }
284 }
285 return -ENOENT;
286}
287
288#define CON_LIST_HELP "CON connetiton list\n" \
289 "Add entry to CON list\n" \
290 "Delete entry from CON list\n" \
291 "Connection Group Number\n" \
292 "CON Connection Point\n" \
293
294DEFUN(om2k_con_list_dec, om2k_con_list_dec_cmd,
295 "con-connection-list (add|del) <1-255> <0-1023> deconcentrated",
296 CON_LIST_HELP "De-concentrated in/outlet\n")
297{
298 struct oml_node_state *oms = vty->index;
299 struct gsm_bts *bts = oms->bts;
300 uint8_t cg = atoi(argv[1]);
301 uint16_t ccp = atoi(argv[2]);
302
303 if (!strcmp(argv[0], "add"))
304 add_con_list(bts, cg, ccp, 0, 0xff);
305 else {
306 if (del_con_list(bts, cg, ccp, 0, 0xff) < 0) {
307 vty_out(vty, "%% No matching CON list entry%s",
308 VTY_NEWLINE);
309 return CMD_WARNING;
310 }
311 }
312
313 return CMD_SUCCESS;
314}
315
316DEFUN(om2k_con_list_tei, om2k_con_list_tei_cmd,
317 "con-connection-list (add|del) <1-255> <0-1023> tei <0-63>",
318 CON_LIST_HELP "Concentrated in/outlet with TEI\n" "TEI Number\n")
319{
320 struct oml_node_state *oms = vty->index;
321 struct gsm_bts *bts = oms->bts;
322 uint8_t cg = atoi(argv[1]);
323 uint16_t ccp = atoi(argv[2]);
324 uint8_t tei = atoi(argv[3]);
325
326 if (!strcmp(argv[0], "add"))
327 add_con_list(bts, cg, ccp, cg, tei);
328 else {
329 if (del_con_list(bts, cg, ccp, cg, tei) < 0) {
330 vty_out(vty, "%% No matching CON list entry%s",
331 VTY_NEWLINE);
332 return CMD_WARNING;
333 }
334 }
335
336 return CMD_SUCCESS;
337}
338
Harald Welte59eee422011-02-14 16:17:49 +0100339DEFUN(cfg_bts_is_conn_list, cfg_bts_is_conn_list_cmd,
Harald Weltea8e6a652011-02-13 22:13:28 +0100340 "is-connection-list (add|del) <0-2047> <0-2047> <0-255>",
341 "Interface Switch Connnection List\n"
342 "Add to IS list\n" "Delete from IS list\n"
343 "ICP1\n" "ICP2\n" "Contiguity Index\n")
Harald Welte8bcb1a02011-02-12 20:23:40 +0100344{
Harald Welte59eee422011-02-14 16:17:49 +0100345 struct gsm_bts *bts = vty->index;
Harald Weltea8e6a652011-02-13 22:13:28 +0100346 uint16_t icp1 = atoi(argv[1]);
347 uint16_t icp2 = atoi(argv[2]);
348 uint8_t ci = atoi(argv[3]);
349 struct is_conn_group *grp, *grp2;
Harald Welte8bcb1a02011-02-12 20:23:40 +0100350
Harald Weltea8e6a652011-02-13 22:13:28 +0100351 if (!strcmp(argv[0], "add")) {
352 grp = talloc_zero(bts, struct is_conn_group);
353 grp->icp1 = icp1;
354 grp->icp2 = icp2;
355 grp->ci = ci;
Harald Welteda871542011-02-14 16:32:44 +0100356 llist_add_tail(&grp->list, &bts->rbs2000.is.conn_groups);
Harald Weltea8e6a652011-02-13 22:13:28 +0100357 } else {
358 llist_for_each_entry_safe(grp, grp2, &bts->rbs2000.is.conn_groups, list) {
359 if (grp->icp1 == icp1 && grp->icp2 == icp2
360 && grp->ci == ci) {
361 llist_del(&grp->list);
362 talloc_free(grp);
363 return CMD_SUCCESS;
364 }
365 }
366 vty_out(vty, "%% No matching IS Conn Group found!%s",
367 VTY_NEWLINE);
368 return CMD_WARNING;
369 }
Harald Welte8bcb1a02011-02-12 20:23:40 +0100370
Harald Weltea8e6a652011-02-13 22:13:28 +0100371 return CMD_SUCCESS;
372}
373
374
Harald Weltea0ce3492011-03-05 14:13:14 +0100375DEFUN(om2k_conf_req, om2k_conf_req_cmd,
376 "configuration-request",
377 "Send the configuration request for current MO\n")
378{
379 struct oml_node_state *oms = vty->index;
380 struct gsm_bts *bts = oms->bts;
381 struct gsm_bts_trx *trx = NULL;
382 struct gsm_bts_trx_ts *ts = NULL;
383
384 switch (oms->mo.class) {
Harald Welte217c6b62011-03-06 19:46:15 +0100385 case OM2K_MO_CLS_IS:
Harald Welted529db62011-03-06 21:49:21 +0100386 abis_om2k_tx_is_conf_req(bts);
Harald Welte217c6b62011-03-06 19:46:15 +0100387 break;
Harald Weltea0ce3492011-03-05 14:13:14 +0100388 case OM2K_MO_CLS_TS:
389 trx = gsm_bts_trx_by_nr(bts, oms->mo.assoc_so);
390 if (!trx) {
391 vty_out(vty, "%% BTS %u has no TRX %u%s", bts->nr,
392 oms->mo.assoc_so, VTY_NEWLINE);
393 return CMD_WARNING;
394 }
395 if (oms->mo.inst >= ARRAY_SIZE(trx->ts)) {
396 vty_out(vty, "%% Timeslot %u out of range%s",
397 oms->mo.inst, VTY_NEWLINE);
398 return CMD_WARNING;
399 }
400 ts = &trx->ts[oms->mo.inst];
401 abis_om2k_tx_ts_conf_req(ts);
402 break;
403 case OM2K_MO_CLS_RX:
404 case OM2K_MO_CLS_TX:
405 case OM2K_MO_CLS_TRXC:
406 trx = gsm_bts_trx_by_nr(bts, oms->mo.inst);
407 if (!trx) {
408 vty_out(vty, "%% BTS %u has no TRX %u%s", bts->nr,
409 oms->mo.inst, VTY_NEWLINE);
410 return CMD_WARNING;
411 }
412 switch (oms->mo.class) {
413 case OM2K_MO_CLS_RX:
414 abis_om2k_tx_rx_conf_req(trx);
415 break;
416 case OM2K_MO_CLS_TX:
Harald Welte52af3ae2011-03-05 16:14:34 +0100417 abis_om2k_tx_tx_conf_req(trx);
Harald Weltea0ce3492011-03-05 14:13:14 +0100418 break;
419 default:
420 break;
421 }
422 break;
Harald Weltef9cf9612011-03-05 14:36:47 +0100423 case OM2K_MO_CLS_TF:
424 abis_om2k_tx_tf_conf_req(bts);
425 break;
Harald Weltea0ce3492011-03-05 14:13:14 +0100426 default:
427 vty_out(vty, "%% Don't know how to configure MO%s",
428 VTY_NEWLINE);
429 }
430
431 return CMD_SUCCESS;
432}
433
Harald Welte59eee422011-02-14 16:17:49 +0100434void abis_om2k_config_write_bts(struct vty *vty, struct gsm_bts *bts)
435{
436 struct is_conn_group *igrp;
437 struct con_conn_group *cgrp;
438
439 llist_for_each_entry(igrp, &bts->rbs2000.is.conn_groups, list)
440 vty_out(vty, " is-connection-list add %u %u %u%s",
441 igrp->icp1, igrp->icp2, igrp->ci, VTY_NEWLINE);
442
443 llist_for_each_entry(cgrp, &bts->rbs2000.con.conn_groups, list) {
444 vty_out(vty, " con-connection-list add %u %u ",
445 cgrp->cg, cgrp->ccp);
446 if (cgrp->tei == 0xff)
447 vty_out(vty, "deconcentrated%s", VTY_NEWLINE);
448 else
449 vty_out(vty, "tei %u%s", cgrp->tei, VTY_NEWLINE);
450 }
451}
452
Harald Welte51c82382011-02-12 14:44:16 +0100453int abis_om2k_vty_init(void)
454{
455 install_element(ENABLE_NODE, &om2k_class_inst_cmd);
456 install_element(ENABLE_NODE, &om2k_classnum_inst_cmd);
457 install_node(&om2k_node, dummy_config_write);
458
Jacob Erlbeck36722e12013-10-29 09:30:30 +0100459 vty_install_default(OM2K_NODE);
Harald Welte51c82382011-02-12 14:44:16 +0100460 install_element(OM2K_NODE, &om2k_reset_cmd);
461 install_element(OM2K_NODE, &om2k_start_cmd);
462 install_element(OM2K_NODE, &om2k_status_cmd);
Harald Welte6fec79d2011-02-12 14:57:17 +0100463 install_element(OM2K_NODE, &om2k_connect_cmd);
464 install_element(OM2K_NODE, &om2k_disconnect_cmd);
Harald Welte0741ffe2011-02-12 18:48:53 +0100465 install_element(OM2K_NODE, &om2k_enable_cmd);
466 install_element(OM2K_NODE, &om2k_disable_cmd);
Harald Welte6fec79d2011-02-12 14:57:17 +0100467 install_element(OM2K_NODE, &om2k_op_info_cmd);
Harald Welte8024d8f2011-02-12 15:07:30 +0100468 install_element(OM2K_NODE, &om2k_test_cmd);
root45799782016-10-15 21:24:57 +0200469 install_element(OM2K_NODE, &om2k_cap_req_cmd);
Harald Weltea0ce3492011-03-05 14:13:14 +0100470 install_element(OM2K_NODE, &om2k_conf_req_cmd);
Harald Weltea02085d2011-02-13 22:45:02 +0100471 install_element(OM2K_NODE, &om2k_con_list_dec_cmd);
472 install_element(OM2K_NODE, &om2k_con_list_tei_cmd);
Harald Welte51c82382011-02-12 14:44:16 +0100473
Harald Welte59eee422011-02-14 16:17:49 +0100474 install_element(BTS_NODE, &cfg_bts_is_conn_list_cmd);
475
Harald Welte51c82382011-02-12 14:44:16 +0100476 return 0;
477}