blob: a6bc4c78cb14a61c0701464114f0498da1726ebb [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
Harald Welteeae68292016-11-11 19:41:59 +010051static struct cmd_node om2k_con_group_node = {
52 OM2K_CON_GROUP_NODE,
53 "%s(om2k-con-group)# ",
54 1,
55};
56
57struct con_group;
58
Harald Welte51c82382011-02-12 14:44:16 +010059struct oml_node_state {
60 struct gsm_bts *bts;
61 struct abis_om2k_mo mo;
Harald Welteeae68292016-11-11 19:41:59 +010062 struct con_group *cg;
Harald Welte51c82382011-02-12 14:44:16 +010063};
64
65static int dummy_config_write(struct vty *v)
66{
67 return CMD_SUCCESS;
68}
69
70/* FIXME: auto-generate those strings from the value_string lists */
71#define OM2K_OBJCLASS_VTY "(trxc|ts|tf|is|con|dp|cf|tx|rx)"
Harald Welte9c0958b2011-02-13 22:51:03 +010072#define OM2K_OBJCLASS_VTY_HELP "TRX Controller\n" \
73 "Timeslot\n" \
74 "Timing Function\n" \
75 "Interface Switch\n" \
76 "Abis Concentrator\n" \
77 "Digital Path\n" \
78 "Central Function\n" \
79 "Transmitter\n" \
80 "Receiver\n"
Harald Welte51c82382011-02-12 14:44:16 +010081
82DEFUN(om2k_class_inst, om2k_class_inst_cmd,
83 "bts <0-255> om2000 class " OM2K_OBJCLASS_VTY
84 " <0-255> <0-255> <0-255>",
85 "BTS related commands\n" "BTS Number\n"
86 "Manipulate the OM2000 managed objects\n"
87 "Object Class\n" OM2K_OBJCLASS_VTY_HELP
88 "BTS Number\n" "Associated SO Instance\n" "Instance Number\n")
89{
90 struct gsm_bts *bts;
91 struct oml_node_state *oms;
92 int bts_nr = atoi(argv[0]);
93
Neels Hofmeyr663debc2016-05-09 21:18:08 +020094 bts = gsm_bts_num(gsmnet_from_vty(vty), bts_nr);
Harald Welte51c82382011-02-12 14:44:16 +010095 if (!bts) {
96 vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
97 return CMD_WARNING;
98 }
99
100 if (bts->type != GSM_BTS_TYPE_RBS2000) {
101 vty_out(vty, "%% BTS %d not an Ericsson RBS%s",
102 bts_nr, VTY_NEWLINE);
103 return CMD_WARNING;
104 }
105
106 oms = talloc_zero(tall_bsc_ctx, struct oml_node_state);
107 if (!oms)
108 return CMD_WARNING;
109
110 oms->bts = bts;
111 oms->mo.class = get_string_value(om2k_mo_class_short_vals, argv[1]);
112 oms->mo.bts = atoi(argv[2]);
113 oms->mo.assoc_so = atoi(argv[3]);
114 oms->mo.inst = atoi(argv[4]);
115
116 vty->index = oms;
117 vty->node = OM2K_NODE;
118
119 return CMD_SUCCESS;
120
121}
122
123DEFUN(om2k_classnum_inst, om2k_classnum_inst_cmd,
124 "bts <0-255> om2000 class <0-255> <0-255> <0-255> <0-255>",
125 "BTS related commands\n" "BTS Number\n"
126 "Manipulate the OML managed objects\n"
127 "Object Class\n" "Object Class\n"
128 "BTS Number\n" "Associated SO Instance\n" "Instance Number\n")
129{
130 struct gsm_bts *bts;
131 struct oml_node_state *oms;
132 int bts_nr = atoi(argv[0]);
133
Neels Hofmeyr663debc2016-05-09 21:18:08 +0200134 bts = gsm_bts_num(gsmnet_from_vty(vty), bts_nr);
Harald Welte51c82382011-02-12 14:44:16 +0100135 if (!bts) {
136 vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
137 return CMD_WARNING;
138 }
139
140 oms = talloc_zero(tall_bsc_ctx, struct oml_node_state);
141 if (!oms)
142 return CMD_WARNING;
143
144 oms->bts = bts;
145 oms->mo.class = atoi(argv[1]);
146 oms->mo.bts = atoi(argv[2]);
147 oms->mo.assoc_so = atoi(argv[3]);
148 oms->mo.inst = atoi(argv[4]);
149
150 vty->index = oms;
151 vty->node = OM2K_NODE;
152
153 return CMD_SUCCESS;
154}
155
156DEFUN(om2k_reset, om2k_reset_cmd,
157 "reset-command",
158 "Reset the MO\n")
159{
160 struct oml_node_state *oms = vty->index;
161
162 abis_om2k_tx_reset_cmd(oms->bts, &oms->mo);
163 return CMD_SUCCESS;
164}
165
166DEFUN(om2k_start, om2k_start_cmd,
167 "start-request",
168 "Start the MO\n")
169{
170 struct oml_node_state *oms = vty->index;
171
172 abis_om2k_tx_start_req(oms->bts, &oms->mo);
173 return CMD_SUCCESS;
174}
175
176DEFUN(om2k_status, om2k_status_cmd,
177 "status-request",
178 "Get the MO Status\n")
179{
180 struct oml_node_state *oms = vty->index;
181
182 abis_om2k_tx_status_req(oms->bts, &oms->mo);
183 return CMD_SUCCESS;
184}
185
Harald Welte6fec79d2011-02-12 14:57:17 +0100186DEFUN(om2k_connect, om2k_connect_cmd,
187 "connect-command",
188 "Connect the MO\n")
189{
190 struct oml_node_state *oms = vty->index;
191
192 abis_om2k_tx_connect_cmd(oms->bts, &oms->mo);
193 return CMD_SUCCESS;
194}
195
196DEFUN(om2k_disconnect, om2k_disconnect_cmd,
197 "disconnect-command",
198 "Disconnect the MO\n")
199{
200 struct oml_node_state *oms = vty->index;
201
202 abis_om2k_tx_disconnect_cmd(oms->bts, &oms->mo);
203 return CMD_SUCCESS;
204}
205
Harald Welte0741ffe2011-02-12 18:48:53 +0100206DEFUN(om2k_enable, om2k_enable_cmd,
207 "enable-request",
208 "Enable the MO\n")
209{
210 struct oml_node_state *oms = vty->index;
211
212 abis_om2k_tx_enable_req(oms->bts, &oms->mo);
213 return CMD_SUCCESS;
214}
215
216DEFUN(om2k_disable, om2k_disable_cmd,
217 "disable-request",
218 "Disable the MO\n")
219{
220 struct oml_node_state *oms = vty->index;
221
222 abis_om2k_tx_disable_req(oms->bts, &oms->mo);
223 return CMD_SUCCESS;
224}
225
Harald Welte6fec79d2011-02-12 14:57:17 +0100226DEFUN(om2k_op_info, om2k_op_info_cmd,
227 "operational-info <0-1>",
Harald Weltecfaabbb2012-08-16 23:23:50 +0200228 "Set operational information\n"
Harald Welted13e0cd2012-08-17 09:52:03 +0200229 "Set operational info to 0 or 1\n")
Harald Welte6fec79d2011-02-12 14:57:17 +0100230{
231 struct oml_node_state *oms = vty->index;
232 int oper = atoi(argv[0]);
233
234 abis_om2k_tx_op_info(oms->bts, &oms->mo, oper);
235 return CMD_SUCCESS;
236}
237
Harald Welte8024d8f2011-02-12 15:07:30 +0100238DEFUN(om2k_test, om2k_test_cmd,
239 "test-request",
240 "Test the MO\n")
241{
242 struct oml_node_state *oms = vty->index;
243
244 abis_om2k_tx_test_req(oms->bts, &oms->mo);
245 return CMD_SUCCESS;
246}
247
root45799782016-10-15 21:24:57 +0200248DEFUN(om2k_cap_req, om2k_cap_req_cmd,
249 "capabilities-request",
250 "Request MO capabilities\n")
251{
252 struct oml_node_state *oms = vty->index;
253
254 abis_om2k_tx_cap_req(oms->bts, &oms->mo);
255 return CMD_SUCCESS;
256}
257
Harald Welteeae68292016-11-11 19:41:59 +0100258static struct con_group *con_group_find_or_create(struct gsm_bts *bts, uint8_t cg)
Harald Weltea02085d2011-02-13 22:45:02 +0100259{
Harald Welteeae68292016-11-11 19:41:59 +0100260 struct con_group *ent;
Harald Weltea02085d2011-02-13 22:45:02 +0100261
Harald Welteeae68292016-11-11 19:41:59 +0100262 llist_for_each_entry(ent, &bts->rbs2000.con.conn_groups, list) {
263 if (ent->cg == cg)
264 return ent;
265 }
266
267 ent = talloc_zero(bts, struct con_group);
268 ent->bts = bts;
Harald Weltea02085d2011-02-13 22:45:02 +0100269 ent->cg = cg;
Harald Welteeae68292016-11-11 19:41:59 +0100270 INIT_LLIST_HEAD(&ent->paths);
Harald Welteda871542011-02-14 16:32:44 +0100271 llist_add_tail(&ent->list, &bts->rbs2000.con.conn_groups);
Harald Welteeae68292016-11-11 19:41:59 +0100272
273 return ent;
Harald Weltea02085d2011-02-13 22:45:02 +0100274}
275
Harald Welteeae68292016-11-11 19:41:59 +0100276static int con_group_del(struct gsm_bts *bts, uint8_t cg_id)
Harald Weltea02085d2011-02-13 22:45:02 +0100277{
Harald Welteeae68292016-11-11 19:41:59 +0100278 struct con_group *cg, *cg2;
Harald Weltea02085d2011-02-13 22:45:02 +0100279
Harald Welteeae68292016-11-11 19:41:59 +0100280 llist_for_each_entry_safe(cg, cg2, &bts->rbs2000.con.conn_groups, list) {
281 if (cg->cg == cg_id) {
282 llist_del(&cg->list);
283 talloc_free(cg);
284 return 0;
285 };
286 }
287 return -ENOENT;
288}
289
290static void con_group_add_path(struct con_group *cg, uint16_t ccp,
291 uint8_t ci, uint8_t tag, uint8_t tei)
292{
293 struct con_path *cp = talloc_zero(cg, struct con_path);
294
295 cp->ccp = ccp;
296 cp->ci = ci;
297 cp->tag = tag;
298 cp->tei = tei;
299 llist_add(&cp->list, &cg->paths);
300}
301
302static int con_group_del_path(struct con_group *cg, uint16_t ccp,
303 uint8_t ci, uint8_t tag, uint8_t tei)
304{
305 struct con_path *cp, *cp2;
306 llist_for_each_entry_safe(cp, cp2, &cg->paths, list) {
307 if (cp->ccp == ccp && cp->ci == ci && cp->tag == tag &&
308 cp->tei == tei) {
309 llist_del(&cp->list);
310 talloc_free(cp);
Harald Weltea02085d2011-02-13 22:45:02 +0100311 return 0;
312 }
313 }
314 return -ENOENT;
315}
316
Harald Welteeae68292016-11-11 19:41:59 +0100317DEFUN(cfg_om2k_con_group, cfg_om2k_con_group_cmd,
318 "con-connection-group <1-31>",
319 "Configure a CON (Concentrator) Connection Group\n"
320 "CON Connection Group Number\n")
Harald Weltea02085d2011-02-13 22:45:02 +0100321{
Harald Welteeae68292016-11-11 19:41:59 +0100322 struct gsm_bts *bts = vty->index;
323 struct con_group *cg;
324 uint8_t cgid = atoi(argv[0]);
325
326 if (bts->type != GSM_BTS_TYPE_RBS2000) {
327 vty_out(vty, "%% CON MO only exists in RBS2000%s",
328 VTY_NEWLINE);
329 return CMD_WARNING;
330 }
331
332 cg = con_group_find_or_create(bts, cgid);
333 if (!cg) {
334 vty_out(vty, "%% Cannot create CON Group%s",
335 VTY_NEWLINE);
336 return CMD_WARNING;
337 }
338
339 vty->node = OM2K_CON_GROUP_NODE;
340 vty->index = cg;
341
342 return CMD_SUCCESS;
343}
344
Philipp Maiere1f8b922017-02-03 17:02:50 +0100345DEFUN(del_om2k_con_group, del_om2k_con_group_cmd,
346 "del-connection-group <1-31>",
347 "Delete a CON (Concentrator) Connection Group\n"
348 "CON Connection Group Number\n")
349{
350 struct gsm_bts *bts = vty->index;
351 int rc;
352 uint8_t cgid = atoi(argv[0]);
353
354 if (bts->type != GSM_BTS_TYPE_RBS2000) {
355 vty_out(vty, "%% CON MO only exists in RBS2000%s",
356 VTY_NEWLINE);
357 return CMD_WARNING;
358 }
359
360 rc = con_group_del(bts, cgid);
361 if (rc != 0) {
362 vty_out(vty, "%% Cannot delete CON Group%s",
363 VTY_NEWLINE);
364 return CMD_WARNING;
365 }
366
367 return CMD_SUCCESS;
368}
369
Harald Welteeae68292016-11-11 19:41:59 +0100370#define CON_PATH_HELP "CON Path (In/Out)\n" \
371 "Add CON Path to Concentration Group\n" \
372 "Delete CON Path from Concentration Group\n" \
373 "CON Conection Point\n" \
374 "Contiguity Index\n" \
375
376DEFUN(cfg_om2k_con_path_dec, cfg_om2k_con_path_dec_cmd,
Harald Welte58273f42016-11-11 23:46:14 +0100377 "con-path (add|del) <0-2047> <0-255> deconcentrated <0-63>",
Harald Welteeae68292016-11-11 19:41:59 +0100378 CON_PATH_HELP "De-concentrated in/outlet\n" "TEI Value\n")
379{
380 struct con_group *cg = vty->index;
381 uint16_t ccp = atoi(argv[1]);
382 uint8_t ci = atoi(argv[2]);
383 uint8_t tei = atoi(argv[3]);
Harald Weltea02085d2011-02-13 22:45:02 +0100384
385 if (!strcmp(argv[0], "add"))
Harald Welteeae68292016-11-11 19:41:59 +0100386 con_group_add_path(cg, ccp, ci, 0, tei);
Harald Weltea02085d2011-02-13 22:45:02 +0100387 else {
Harald Welteeae68292016-11-11 19:41:59 +0100388 if (con_group_del_path(cg, ccp, ci, 0, tei) < 0) {
389 vty_out(vty, "%% No matching CON Path%s",
Harald Weltea02085d2011-02-13 22:45:02 +0100390 VTY_NEWLINE);
391 return CMD_WARNING;
392 }
393 }
394
395 return CMD_SUCCESS;
396}
397
Harald Welteeae68292016-11-11 19:41:59 +0100398DEFUN(cfg_om2k_con_path_conc, cfg_om2k_con_path_conc_cmd,
Harald Welte58273f42016-11-11 23:46:14 +0100399 "con-path (add|del) <0-2047> <0-255> concentrated <1-16>",
Harald Welteeae68292016-11-11 19:41:59 +0100400 CON_PATH_HELP "Concentrated in/outlet\n" "Tag Number\n")
Harald Weltea02085d2011-02-13 22:45:02 +0100401{
Harald Welteeae68292016-11-11 19:41:59 +0100402 struct con_group *cg = vty->index;
403 uint16_t ccp = atoi(argv[1]);
404 uint8_t ci = atoi(argv[2]);
405 uint8_t tag = atoi(argv[3]);
Harald Weltea02085d2011-02-13 22:45:02 +0100406
407 if (!strcmp(argv[0], "add"))
Harald Welteeae68292016-11-11 19:41:59 +0100408 con_group_add_path(cg, ccp, ci, tag, 0xff);
Harald Weltea02085d2011-02-13 22:45:02 +0100409 else {
Harald Welteeae68292016-11-11 19:41:59 +0100410 if (con_group_del_path(cg, ccp, ci, tag, 0xff) < 0) {
Harald Weltea02085d2011-02-13 22:45:02 +0100411 vty_out(vty, "%% No matching CON list entry%s",
412 VTY_NEWLINE);
413 return CMD_WARNING;
414 }
415 }
416
417 return CMD_SUCCESS;
418}
419
Harald Weltece492582016-11-15 22:59:24 +0100420DEFUN(cfg_bts_alt_mode, cfg_bts_alt_mode_cmd,
421 "abis-lower-transport (single-timeslot|super-channel)",
422 "Configure thee Abis Lower Transport\n"
423 "Single Timeslot (classic Abis)\n"
424 "SuperChannel (Packet Abis)\n")
425{
426 struct gsm_bts *bts = vty->index;
427 struct con_group *cg;
428
429 if (bts->type != GSM_BTS_TYPE_RBS2000) {
430 vty_out(vty, "%% Command only works for RBS2000%s",
431 VTY_NEWLINE);
432 return CMD_WARNING;
433 }
434
435 if (!strcmp(argv[0], "super-channel"))
436 bts->rbs2000.use_superchannel = 1;
437 else
438 bts->rbs2000.use_superchannel = 0;
439
440 return CMD_SUCCESS;
441}
442
Harald Welte59eee422011-02-14 16:17:49 +0100443DEFUN(cfg_bts_is_conn_list, cfg_bts_is_conn_list_cmd,
Harald Weltea8e6a652011-02-13 22:13:28 +0100444 "is-connection-list (add|del) <0-2047> <0-2047> <0-255>",
Ruben Undheim59d57da2016-12-20 17:38:31 +0100445 "Interface Switch Connection List\n"
Harald Weltea8e6a652011-02-13 22:13:28 +0100446 "Add to IS list\n" "Delete from IS list\n"
447 "ICP1\n" "ICP2\n" "Contiguity Index\n")
Harald Welte8bcb1a02011-02-12 20:23:40 +0100448{
Harald Welte59eee422011-02-14 16:17:49 +0100449 struct gsm_bts *bts = vty->index;
Harald Weltea8e6a652011-02-13 22:13:28 +0100450 uint16_t icp1 = atoi(argv[1]);
451 uint16_t icp2 = atoi(argv[2]);
452 uint8_t ci = atoi(argv[3]);
453 struct is_conn_group *grp, *grp2;
Harald Welte8bcb1a02011-02-12 20:23:40 +0100454
Harald Weltefe7be8d2016-11-11 19:44:10 +0100455 if (bts->type != GSM_BTS_TYPE_RBS2000) {
456 vty_out(vty, "%% IS MO only exists in RBS2000%s",
457 VTY_NEWLINE);
458 return CMD_WARNING;
459 }
460
Harald Weltea8e6a652011-02-13 22:13:28 +0100461 if (!strcmp(argv[0], "add")) {
462 grp = talloc_zero(bts, struct is_conn_group);
463 grp->icp1 = icp1;
464 grp->icp2 = icp2;
465 grp->ci = ci;
Harald Welteda871542011-02-14 16:32:44 +0100466 llist_add_tail(&grp->list, &bts->rbs2000.is.conn_groups);
Harald Weltea8e6a652011-02-13 22:13:28 +0100467 } else {
468 llist_for_each_entry_safe(grp, grp2, &bts->rbs2000.is.conn_groups, list) {
469 if (grp->icp1 == icp1 && grp->icp2 == icp2
470 && grp->ci == ci) {
471 llist_del(&grp->list);
472 talloc_free(grp);
473 return CMD_SUCCESS;
474 }
475 }
476 vty_out(vty, "%% No matching IS Conn Group found!%s",
477 VTY_NEWLINE);
478 return CMD_WARNING;
479 }
Harald Welte8bcb1a02011-02-12 20:23:40 +0100480
Harald Weltea8e6a652011-02-13 22:13:28 +0100481 return CMD_SUCCESS;
482}
483
484
Harald Weltea0ce3492011-03-05 14:13:14 +0100485DEFUN(om2k_conf_req, om2k_conf_req_cmd,
486 "configuration-request",
487 "Send the configuration request for current MO\n")
488{
489 struct oml_node_state *oms = vty->index;
490 struct gsm_bts *bts = oms->bts;
491 struct gsm_bts_trx *trx = NULL;
492 struct gsm_bts_trx_ts *ts = NULL;
493
494 switch (oms->mo.class) {
Harald Welte217c6b62011-03-06 19:46:15 +0100495 case OM2K_MO_CLS_IS:
Harald Welted529db62011-03-06 21:49:21 +0100496 abis_om2k_tx_is_conf_req(bts);
Harald Welte217c6b62011-03-06 19:46:15 +0100497 break;
Harald Weltea0ce3492011-03-05 14:13:14 +0100498 case OM2K_MO_CLS_TS:
499 trx = gsm_bts_trx_by_nr(bts, oms->mo.assoc_so);
500 if (!trx) {
501 vty_out(vty, "%% BTS %u has no TRX %u%s", bts->nr,
502 oms->mo.assoc_so, VTY_NEWLINE);
503 return CMD_WARNING;
504 }
505 if (oms->mo.inst >= ARRAY_SIZE(trx->ts)) {
506 vty_out(vty, "%% Timeslot %u out of range%s",
507 oms->mo.inst, VTY_NEWLINE);
508 return CMD_WARNING;
509 }
510 ts = &trx->ts[oms->mo.inst];
511 abis_om2k_tx_ts_conf_req(ts);
512 break;
513 case OM2K_MO_CLS_RX:
514 case OM2K_MO_CLS_TX:
515 case OM2K_MO_CLS_TRXC:
516 trx = gsm_bts_trx_by_nr(bts, oms->mo.inst);
517 if (!trx) {
518 vty_out(vty, "%% BTS %u has no TRX %u%s", bts->nr,
519 oms->mo.inst, VTY_NEWLINE);
520 return CMD_WARNING;
521 }
522 switch (oms->mo.class) {
523 case OM2K_MO_CLS_RX:
524 abis_om2k_tx_rx_conf_req(trx);
525 break;
526 case OM2K_MO_CLS_TX:
Harald Welte52af3ae2011-03-05 16:14:34 +0100527 abis_om2k_tx_tx_conf_req(trx);
Harald Weltea0ce3492011-03-05 14:13:14 +0100528 break;
529 default:
530 break;
531 }
532 break;
Harald Weltef9cf9612011-03-05 14:36:47 +0100533 case OM2K_MO_CLS_TF:
534 abis_om2k_tx_tf_conf_req(bts);
535 break;
Harald Weltea0ce3492011-03-05 14:13:14 +0100536 default:
537 vty_out(vty, "%% Don't know how to configure MO%s",
538 VTY_NEWLINE);
539 }
540
541 return CMD_SUCCESS;
542}
543
Harald Welteeae68292016-11-11 19:41:59 +0100544static void dump_con_group(struct vty *vty, struct con_group *cg)
545{
546 struct con_path *cp;
547
548 llist_for_each_entry(cp, &cg->paths, list) {
549 vty_out(vty, " con-path add %u %u ", cp->ccp, cp->ci);
550 if (cp->tei == 0xff) {
551 vty_out(vty, "concentrated %u%s", cp->tag,
552 VTY_NEWLINE);
553 } else {
554 vty_out(vty, "deconcentrated %u%s", cp->tei,
555 VTY_NEWLINE);
556 }
557 }
558}
559
Harald Welte59eee422011-02-14 16:17:49 +0100560void abis_om2k_config_write_bts(struct vty *vty, struct gsm_bts *bts)
561{
562 struct is_conn_group *igrp;
Harald Welteeae68292016-11-11 19:41:59 +0100563 struct con_group *cgrp;
Harald Welte59eee422011-02-14 16:17:49 +0100564
565 llist_for_each_entry(igrp, &bts->rbs2000.is.conn_groups, list)
566 vty_out(vty, " is-connection-list add %u %u %u%s",
567 igrp->icp1, igrp->icp2, igrp->ci, VTY_NEWLINE);
568
569 llist_for_each_entry(cgrp, &bts->rbs2000.con.conn_groups, list) {
Harald Welteeae68292016-11-11 19:41:59 +0100570 vty_out(vty, " con-connection-group %u%s", cgrp->cg,
571 VTY_NEWLINE);
572 dump_con_group(vty, cgrp);
Harald Welte59eee422011-02-14 16:17:49 +0100573 }
Harald Weltece492582016-11-15 22:59:24 +0100574 if (bts->rbs2000.use_superchannel)
575 vty_out(vty, " abis-lower-transport super-channel%s",
576 VTY_NEWLINE);
Harald Welte59eee422011-02-14 16:17:49 +0100577}
578
Harald Welte51c82382011-02-12 14:44:16 +0100579int abis_om2k_vty_init(void)
580{
581 install_element(ENABLE_NODE, &om2k_class_inst_cmd);
582 install_element(ENABLE_NODE, &om2k_classnum_inst_cmd);
583 install_node(&om2k_node, dummy_config_write);
584
Jacob Erlbeck36722e12013-10-29 09:30:30 +0100585 vty_install_default(OM2K_NODE);
Harald Welte51c82382011-02-12 14:44:16 +0100586 install_element(OM2K_NODE, &om2k_reset_cmd);
587 install_element(OM2K_NODE, &om2k_start_cmd);
588 install_element(OM2K_NODE, &om2k_status_cmd);
Harald Welte6fec79d2011-02-12 14:57:17 +0100589 install_element(OM2K_NODE, &om2k_connect_cmd);
590 install_element(OM2K_NODE, &om2k_disconnect_cmd);
Harald Welte0741ffe2011-02-12 18:48:53 +0100591 install_element(OM2K_NODE, &om2k_enable_cmd);
592 install_element(OM2K_NODE, &om2k_disable_cmd);
Harald Welte6fec79d2011-02-12 14:57:17 +0100593 install_element(OM2K_NODE, &om2k_op_info_cmd);
Harald Welte8024d8f2011-02-12 15:07:30 +0100594 install_element(OM2K_NODE, &om2k_test_cmd);
root45799782016-10-15 21:24:57 +0200595 install_element(OM2K_NODE, &om2k_cap_req_cmd);
Harald Weltea0ce3492011-03-05 14:13:14 +0100596 install_element(OM2K_NODE, &om2k_conf_req_cmd);
Harald Welteeae68292016-11-11 19:41:59 +0100597
598 install_node(&om2k_con_group_node, dummy_config_write);
599 vty_install_default(OM2K_CON_GROUP_NODE);
600 install_element(OM2K_CON_GROUP_NODE, &cfg_om2k_con_path_dec_cmd);
601 install_element(OM2K_CON_GROUP_NODE, &cfg_om2k_con_path_conc_cmd);
Harald Welte51c82382011-02-12 14:44:16 +0100602
Harald Welte59eee422011-02-14 16:17:49 +0100603 install_element(BTS_NODE, &cfg_bts_is_conn_list_cmd);
Harald Weltece492582016-11-15 22:59:24 +0100604 install_element(BTS_NODE, &cfg_bts_alt_mode_cmd);
Harald Welteeae68292016-11-11 19:41:59 +0100605 install_element(BTS_NODE, &cfg_om2k_con_group_cmd);
Philipp Maiere1f8b922017-02-03 17:02:50 +0100606 install_element(BTS_NODE, &del_om2k_con_group_cmd);
Harald Welte59eee422011-02-14 16:17:49 +0100607
Harald Welte51c82382011-02-12 14:44:16 +0100608 return 0;
609}