blob: b77f470a02091bdf8add0c9b9f234f64bb62b6e5 [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>
30#include <osmocore/msgb.h>
31#include <osmocore/tlv.h>
32#include <osmocore/talloc.h>
33#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)"
63#define OM2K_OBJCLASS_VTY_HELP "FIXME"
64
65DEFUN(om2k_class_inst, om2k_class_inst_cmd,
66 "bts <0-255> om2000 class " OM2K_OBJCLASS_VTY
67 " <0-255> <0-255> <0-255>",
68 "BTS related commands\n" "BTS Number\n"
69 "Manipulate the OM2000 managed objects\n"
70 "Object Class\n" OM2K_OBJCLASS_VTY_HELP
71 "BTS Number\n" "Associated SO Instance\n" "Instance Number\n")
72{
73 struct gsm_bts *bts;
74 struct oml_node_state *oms;
75 int bts_nr = atoi(argv[0]);
76
77 bts = gsm_bts_num(bsc_gsmnet, bts_nr);
78 if (!bts) {
79 vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
80 return CMD_WARNING;
81 }
82
83 if (bts->type != GSM_BTS_TYPE_RBS2000) {
84 vty_out(vty, "%% BTS %d not an Ericsson RBS%s",
85 bts_nr, VTY_NEWLINE);
86 return CMD_WARNING;
87 }
88
89 oms = talloc_zero(tall_bsc_ctx, struct oml_node_state);
90 if (!oms)
91 return CMD_WARNING;
92
93 oms->bts = bts;
94 oms->mo.class = get_string_value(om2k_mo_class_short_vals, argv[1]);
95 oms->mo.bts = atoi(argv[2]);
96 oms->mo.assoc_so = atoi(argv[3]);
97 oms->mo.inst = atoi(argv[4]);
98
99 vty->index = oms;
100 vty->node = OM2K_NODE;
101
102 return CMD_SUCCESS;
103
104}
105
106DEFUN(om2k_classnum_inst, om2k_classnum_inst_cmd,
107 "bts <0-255> om2000 class <0-255> <0-255> <0-255> <0-255>",
108 "BTS related commands\n" "BTS Number\n"
109 "Manipulate the OML managed objects\n"
110 "Object Class\n" "Object Class\n"
111 "BTS Number\n" "Associated SO Instance\n" "Instance Number\n")
112{
113 struct gsm_bts *bts;
114 struct oml_node_state *oms;
115 int bts_nr = atoi(argv[0]);
116
117 bts = gsm_bts_num(bsc_gsmnet, bts_nr);
118 if (!bts) {
119 vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
120 return CMD_WARNING;
121 }
122
123 oms = talloc_zero(tall_bsc_ctx, struct oml_node_state);
124 if (!oms)
125 return CMD_WARNING;
126
127 oms->bts = bts;
128 oms->mo.class = atoi(argv[1]);
129 oms->mo.bts = atoi(argv[2]);
130 oms->mo.assoc_so = atoi(argv[3]);
131 oms->mo.inst = atoi(argv[4]);
132
133 vty->index = oms;
134 vty->node = OM2K_NODE;
135
136 return CMD_SUCCESS;
137}
138
139DEFUN(om2k_reset, om2k_reset_cmd,
140 "reset-command",
141 "Reset the MO\n")
142{
143 struct oml_node_state *oms = vty->index;
144
145 abis_om2k_tx_reset_cmd(oms->bts, &oms->mo);
146 return CMD_SUCCESS;
147}
148
149DEFUN(om2k_start, om2k_start_cmd,
150 "start-request",
151 "Start the MO\n")
152{
153 struct oml_node_state *oms = vty->index;
154
155 abis_om2k_tx_start_req(oms->bts, &oms->mo);
156 return CMD_SUCCESS;
157}
158
159DEFUN(om2k_status, om2k_status_cmd,
160 "status-request",
161 "Get the MO Status\n")
162{
163 struct oml_node_state *oms = vty->index;
164
165 abis_om2k_tx_status_req(oms->bts, &oms->mo);
166 return CMD_SUCCESS;
167}
168
Harald Welte6fec79d2011-02-12 14:57:17 +0100169DEFUN(om2k_connect, om2k_connect_cmd,
170 "connect-command",
171 "Connect the MO\n")
172{
173 struct oml_node_state *oms = vty->index;
174
175 abis_om2k_tx_connect_cmd(oms->bts, &oms->mo);
176 return CMD_SUCCESS;
177}
178
179DEFUN(om2k_disconnect, om2k_disconnect_cmd,
180 "disconnect-command",
181 "Disconnect the MO\n")
182{
183 struct oml_node_state *oms = vty->index;
184
185 abis_om2k_tx_disconnect_cmd(oms->bts, &oms->mo);
186 return CMD_SUCCESS;
187}
188
Harald Welte0741ffe2011-02-12 18:48:53 +0100189DEFUN(om2k_enable, om2k_enable_cmd,
190 "enable-request",
191 "Enable the MO\n")
192{
193 struct oml_node_state *oms = vty->index;
194
195 abis_om2k_tx_enable_req(oms->bts, &oms->mo);
196 return CMD_SUCCESS;
197}
198
199DEFUN(om2k_disable, om2k_disable_cmd,
200 "disable-request",
201 "Disable the MO\n")
202{
203 struct oml_node_state *oms = vty->index;
204
205 abis_om2k_tx_disable_req(oms->bts, &oms->mo);
206 return CMD_SUCCESS;
207}
208
Harald Welte6fec79d2011-02-12 14:57:17 +0100209DEFUN(om2k_op_info, om2k_op_info_cmd,
210 "operational-info <0-1>",
211 "Set operational information\n")
212{
213 struct oml_node_state *oms = vty->index;
214 int oper = atoi(argv[0]);
215
216 abis_om2k_tx_op_info(oms->bts, &oms->mo, oper);
217 return CMD_SUCCESS;
218}
219
Harald Welte8024d8f2011-02-12 15:07:30 +0100220DEFUN(om2k_test, om2k_test_cmd,
221 "test-request",
222 "Test the MO\n")
223{
224 struct oml_node_state *oms = vty->index;
225
226 abis_om2k_tx_test_req(oms->bts, &oms->mo);
227 return CMD_SUCCESS;
228}
229
Harald Weltea02085d2011-02-13 22:45:02 +0100230struct con_conn_group {
231 struct llist_head list;
232
233 uint8_t cg;
234 uint16_t ccp;
235 uint8_t tag;
236 uint8_t tei;
237};
238
239static void add_con_list(struct gsm_bts *bts, uint8_t cg, uint16_t ccp,
240 uint8_t tag, uint8_t tei)
241{
242 struct con_conn_group *ent = talloc_zero(bts, struct con_conn_group);
243
244 ent->cg = cg;
245 ent->ccp = ccp;
246 ent->tag = tag;
247 ent->tei = tei;
248
249 llist_add(&ent->list, &bts->rbs2000.con.conn_groups);
250}
251
252static int del_con_list(struct gsm_bts *bts, uint8_t cg, uint16_t ccp,
253 uint8_t tag, uint8_t tei)
254{
255 struct con_conn_group *grp, *grp2;
256
257 llist_for_each_entry_safe(grp, grp2, &bts->rbs2000.con.conn_groups, list) {
258 if (grp->cg == cg && grp->ccp == ccp && grp->tag == tag
259 && grp->tei == tei) {
260 llist_del(&grp->list);
261 talloc_free(grp);
262 return 0;
263 }
264 }
265 return -ENOENT;
266}
267
268#define CON_LIST_HELP "CON connetiton list\n" \
269 "Add entry to CON list\n" \
270 "Delete entry from CON list\n" \
271 "Connection Group Number\n" \
272 "CON Connection Point\n" \
273
274DEFUN(om2k_con_list_dec, om2k_con_list_dec_cmd,
275 "con-connection-list (add|del) <1-255> <0-1023> deconcentrated",
276 CON_LIST_HELP "De-concentrated in/outlet\n")
277{
278 struct oml_node_state *oms = vty->index;
279 struct gsm_bts *bts = oms->bts;
280 uint8_t cg = atoi(argv[1]);
281 uint16_t ccp = atoi(argv[2]);
282
283 if (!strcmp(argv[0], "add"))
284 add_con_list(bts, cg, ccp, 0, 0xff);
285 else {
286 if (del_con_list(bts, cg, ccp, 0, 0xff) < 0) {
287 vty_out(vty, "%% No matching CON list entry%s",
288 VTY_NEWLINE);
289 return CMD_WARNING;
290 }
291 }
292
293 return CMD_SUCCESS;
294}
295
296DEFUN(om2k_con_list_tei, om2k_con_list_tei_cmd,
297 "con-connection-list (add|del) <1-255> <0-1023> tei <0-63>",
298 CON_LIST_HELP "Concentrated in/outlet with TEI\n" "TEI Number\n")
299{
300 struct oml_node_state *oms = vty->index;
301 struct gsm_bts *bts = oms->bts;
302 uint8_t cg = atoi(argv[1]);
303 uint16_t ccp = atoi(argv[2]);
304 uint8_t tei = atoi(argv[3]);
305
306 if (!strcmp(argv[0], "add"))
307 add_con_list(bts, cg, ccp, cg, tei);
308 else {
309 if (del_con_list(bts, cg, ccp, cg, tei) < 0) {
310 vty_out(vty, "%% No matching CON list entry%s",
311 VTY_NEWLINE);
312 return CMD_WARNING;
313 }
314 }
315
316 return CMD_SUCCESS;
317}
318
Harald Welte8bcb1a02011-02-12 20:23:40 +0100319static void om2k_fill_is_conn_grp(struct om2k_is_conn_grp *grp, uint16_t icp1,
320 uint16_t icp2, uint8_t cont_idx)
321{
322 grp->icp1 = htons(icp1);
323 grp->icp2 = htons(icp2);
324 grp->cont_idx = cont_idx;
325}
326
Harald Weltea8e6a652011-02-13 22:13:28 +0100327struct is_conn_group {
328 struct llist_head list;
329 uint16_t icp1;
330 uint16_t icp2;
331 uint8_t ci;
332};
333
334DEFUN(om2k_is_conn_list, om2k_is_conn_list_cmd,
335 "is-connection-list (add|del) <0-2047> <0-2047> <0-255>",
336 "Interface Switch Connnection List\n"
337 "Add to IS list\n" "Delete from IS list\n"
338 "ICP1\n" "ICP2\n" "Contiguity Index\n")
Harald Welte8bcb1a02011-02-12 20:23:40 +0100339{
340 struct oml_node_state *oms = vty->index;
Harald Weltea8e6a652011-02-13 22:13:28 +0100341 struct gsm_bts *bts = oms->bts;
342 uint16_t icp1 = atoi(argv[1]);
343 uint16_t icp2 = atoi(argv[2]);
344 uint8_t ci = atoi(argv[3]);
345 struct is_conn_group *grp, *grp2;
Harald Welte8bcb1a02011-02-12 20:23:40 +0100346
Harald Weltea8e6a652011-02-13 22:13:28 +0100347 if (!strcmp(argv[0], "add")) {
348 grp = talloc_zero(bts, struct is_conn_group);
349 grp->icp1 = icp1;
350 grp->icp2 = icp2;
351 grp->ci = ci;
352 llist_add(&grp->list, &bts->rbs2000.is.conn_groups);
353 } else {
354 llist_for_each_entry_safe(grp, grp2, &bts->rbs2000.is.conn_groups, list) {
355 if (grp->icp1 == icp1 && grp->icp2 == icp2
356 && grp->ci == ci) {
357 llist_del(&grp->list);
358 talloc_free(grp);
359 return CMD_SUCCESS;
360 }
361 }
362 vty_out(vty, "%% No matching IS Conn Group found!%s",
363 VTY_NEWLINE);
364 return CMD_WARNING;
365 }
Harald Welte8bcb1a02011-02-12 20:23:40 +0100366
Harald Weltea8e6a652011-02-13 22:13:28 +0100367 return CMD_SUCCESS;
368}
369
370
371DEFUN(om2k_is_conf_req, om2k_is_conf_req_cmd,
372 "is-conf-req",
373 "Send IS Configuration Request\n")
374{
375 struct oml_node_state *oms = vty->index;
376 struct gsm_bts *bts = oms->bts;
377 struct is_conn_group *grp;
378 unsigned int num_grps = 0, i = 0;
379 struct om2k_is_conn_grp *o2grps;
380
381 /* count number of groups in linked list */
382 llist_for_each_entry(grp, &bts->rbs2000.is.conn_groups, list)
383 num_grps++;
384
385 if (!num_grps) {
386 vty_out(vty, "%% No IS connection groups configured!%s",
387 VTY_NEWLINE);
388 return CMD_WARNING;
389 }
390
391 /* allocate buffer for oml group array */
392 o2grps = talloc_zero_array(bts, struct om2k_is_conn_grp, num_grps);
393
394 /* fill array with data from linked list */
395 llist_for_each_entry(grp, &bts->rbs2000.is.conn_groups, list)
396 om2k_fill_is_conn_grp(&o2grps[i++], grp->icp1, grp->icp2, grp->ci);
397
398 /* send the actual OML request */
399 abis_om2k_tx_is_conf_req(oms->bts, o2grps, num_grps);
400
401 talloc_free(o2grps);
402
Harald Welte8bcb1a02011-02-12 20:23:40 +0100403 return CMD_SUCCESS;
404}
Harald Welte6fec79d2011-02-12 14:57:17 +0100405
Harald Welte51c82382011-02-12 14:44:16 +0100406int abis_om2k_vty_init(void)
407{
408 install_element(ENABLE_NODE, &om2k_class_inst_cmd);
409 install_element(ENABLE_NODE, &om2k_classnum_inst_cmd);
410 install_node(&om2k_node, dummy_config_write);
411
412 install_default(OM2K_NODE);
413 install_element(OM2K_NODE, &ournode_exit_cmd);
414 install_element(OM2K_NODE, &om2k_reset_cmd);
415 install_element(OM2K_NODE, &om2k_start_cmd);
416 install_element(OM2K_NODE, &om2k_status_cmd);
Harald Welte6fec79d2011-02-12 14:57:17 +0100417 install_element(OM2K_NODE, &om2k_connect_cmd);
418 install_element(OM2K_NODE, &om2k_disconnect_cmd);
Harald Welte0741ffe2011-02-12 18:48:53 +0100419 install_element(OM2K_NODE, &om2k_enable_cmd);
420 install_element(OM2K_NODE, &om2k_disable_cmd);
Harald Welte6fec79d2011-02-12 14:57:17 +0100421 install_element(OM2K_NODE, &om2k_op_info_cmd);
Harald Welte8024d8f2011-02-12 15:07:30 +0100422 install_element(OM2K_NODE, &om2k_test_cmd);
Harald Welte8bcb1a02011-02-12 20:23:40 +0100423 install_element(OM2K_NODE, &om2k_is_conf_req_cmd);
Harald Weltea8e6a652011-02-13 22:13:28 +0100424 install_element(OM2K_NODE, &om2k_is_conn_list_cmd);
Harald Weltea02085d2011-02-13 22:45:02 +0100425 install_element(OM2K_NODE, &om2k_con_list_dec_cmd);
426 install_element(OM2K_NODE, &om2k_con_list_tei_cmd);
Harald Welte51c82382011-02-12 14:44:16 +0100427
428 return 0;
429}