Harald Welte | 51c8238 | 2011-02-12 14:44:16 +0100 | [diff] [blame] | 1 | /* 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 Ayuso | 136f453 | 2011-03-22 16:47:59 +0100 | [diff] [blame] | 30 | #include <osmocom/core/msgb.h> |
| 31 | #include <osmocom/gsm/tlv.h> |
| 32 | #include <osmocom/core/talloc.h> |
Harald Welte | 51c8238 | 2011-02-12 14:44:16 +0100 | [diff] [blame] | 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 | |
| 43 | extern struct gsm_network *bsc_gsmnet; |
| 44 | |
| 45 | static struct cmd_node om2k_node = { |
| 46 | OM2K_NODE, |
Harald Welte | b0ec9e3 | 2011-02-12 20:50:58 +0100 | [diff] [blame] | 47 | "%s(om2k)# ", |
Harald Welte | 51c8238 | 2011-02-12 14:44:16 +0100 | [diff] [blame] | 48 | 1, |
| 49 | }; |
| 50 | |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 51 | static struct cmd_node om2k_con_group_node = { |
| 52 | OM2K_CON_GROUP_NODE, |
| 53 | "%s(om2k-con-group)# ", |
| 54 | 1, |
| 55 | }; |
| 56 | |
| 57 | struct con_group; |
| 58 | |
Harald Welte | 51c8238 | 2011-02-12 14:44:16 +0100 | [diff] [blame] | 59 | struct oml_node_state { |
| 60 | struct gsm_bts *bts; |
| 61 | struct abis_om2k_mo mo; |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 62 | struct con_group *cg; |
Harald Welte | 51c8238 | 2011-02-12 14:44:16 +0100 | [diff] [blame] | 63 | }; |
| 64 | |
| 65 | static 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 Welte | 9c0958b | 2011-02-13 22:51:03 +0100 | [diff] [blame] | 72 | #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 Welte | 51c8238 | 2011-02-12 14:44:16 +0100 | [diff] [blame] | 81 | |
| 82 | DEFUN(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 Hofmeyr | 663debc | 2016-05-09 21:18:08 +0200 | [diff] [blame] | 94 | bts = gsm_bts_num(gsmnet_from_vty(vty), bts_nr); |
Harald Welte | 51c8238 | 2011-02-12 14:44:16 +0100 | [diff] [blame] | 95 | 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 | |
| 123 | DEFUN(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 Hofmeyr | 663debc | 2016-05-09 21:18:08 +0200 | [diff] [blame] | 134 | bts = gsm_bts_num(gsmnet_from_vty(vty), bts_nr); |
Harald Welte | 51c8238 | 2011-02-12 14:44:16 +0100 | [diff] [blame] | 135 | 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 | |
| 156 | DEFUN(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 | |
| 166 | DEFUN(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 | |
| 176 | DEFUN(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 Welte | 6fec79d | 2011-02-12 14:57:17 +0100 | [diff] [blame] | 186 | DEFUN(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 | |
| 196 | DEFUN(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 Welte | 0741ffe | 2011-02-12 18:48:53 +0100 | [diff] [blame] | 206 | DEFUN(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 | |
| 216 | DEFUN(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 Welte | 6fec79d | 2011-02-12 14:57:17 +0100 | [diff] [blame] | 226 | DEFUN(om2k_op_info, om2k_op_info_cmd, |
| 227 | "operational-info <0-1>", |
Harald Welte | cfaabbb | 2012-08-16 23:23:50 +0200 | [diff] [blame] | 228 | "Set operational information\n" |
Harald Welte | d13e0cd | 2012-08-17 09:52:03 +0200 | [diff] [blame] | 229 | "Set operational info to 0 or 1\n") |
Harald Welte | 6fec79d | 2011-02-12 14:57:17 +0100 | [diff] [blame] | 230 | { |
| 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 Welte | 8024d8f | 2011-02-12 15:07:30 +0100 | [diff] [blame] | 238 | DEFUN(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 | |
root | 4579978 | 2016-10-15 21:24:57 +0200 | [diff] [blame] | 248 | DEFUN(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 Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 258 | static struct con_group *con_group_find_or_create(struct gsm_bts *bts, uint8_t cg) |
Harald Welte | a02085d | 2011-02-13 22:45:02 +0100 | [diff] [blame] | 259 | { |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 260 | struct con_group *ent; |
Harald Welte | a02085d | 2011-02-13 22:45:02 +0100 | [diff] [blame] | 261 | |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 262 | 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 Welte | a02085d | 2011-02-13 22:45:02 +0100 | [diff] [blame] | 269 | ent->cg = cg; |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 270 | INIT_LLIST_HEAD(&ent->paths); |
Harald Welte | da87154 | 2011-02-14 16:32:44 +0100 | [diff] [blame] | 271 | llist_add_tail(&ent->list, &bts->rbs2000.con.conn_groups); |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 272 | |
| 273 | return ent; |
Harald Welte | a02085d | 2011-02-13 22:45:02 +0100 | [diff] [blame] | 274 | } |
| 275 | |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 276 | static int con_group_del(struct gsm_bts *bts, uint8_t cg_id) |
Harald Welte | a02085d | 2011-02-13 22:45:02 +0100 | [diff] [blame] | 277 | { |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 278 | struct con_group *cg, *cg2; |
Harald Welte | a02085d | 2011-02-13 22:45:02 +0100 | [diff] [blame] | 279 | |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 280 | 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 | |
| 290 | static 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 | |
| 302 | static 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 Welte | a02085d | 2011-02-13 22:45:02 +0100 | [diff] [blame] | 311 | return 0; |
| 312 | } |
| 313 | } |
| 314 | return -ENOENT; |
| 315 | } |
| 316 | |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 317 | DEFUN(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 Welte | a02085d | 2011-02-13 22:45:02 +0100 | [diff] [blame] | 321 | { |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 322 | 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 Maier | e1f8b92 | 2017-02-03 17:02:50 +0100 | [diff] [blame] | 345 | DEFUN(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 Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 370 | #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 | |
| 376 | DEFUN(cfg_om2k_con_path_dec, cfg_om2k_con_path_dec_cmd, |
Harald Welte | 58273f4 | 2016-11-11 23:46:14 +0100 | [diff] [blame] | 377 | "con-path (add|del) <0-2047> <0-255> deconcentrated <0-63>", |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 378 | 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 Welte | a02085d | 2011-02-13 22:45:02 +0100 | [diff] [blame] | 384 | |
| 385 | if (!strcmp(argv[0], "add")) |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 386 | con_group_add_path(cg, ccp, ci, 0, tei); |
Harald Welte | a02085d | 2011-02-13 22:45:02 +0100 | [diff] [blame] | 387 | else { |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 388 | if (con_group_del_path(cg, ccp, ci, 0, tei) < 0) { |
| 389 | vty_out(vty, "%% No matching CON Path%s", |
Harald Welte | a02085d | 2011-02-13 22:45:02 +0100 | [diff] [blame] | 390 | VTY_NEWLINE); |
| 391 | return CMD_WARNING; |
| 392 | } |
| 393 | } |
| 394 | |
| 395 | return CMD_SUCCESS; |
| 396 | } |
| 397 | |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 398 | DEFUN(cfg_om2k_con_path_conc, cfg_om2k_con_path_conc_cmd, |
Harald Welte | 58273f4 | 2016-11-11 23:46:14 +0100 | [diff] [blame] | 399 | "con-path (add|del) <0-2047> <0-255> concentrated <1-16>", |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 400 | CON_PATH_HELP "Concentrated in/outlet\n" "Tag Number\n") |
Harald Welte | a02085d | 2011-02-13 22:45:02 +0100 | [diff] [blame] | 401 | { |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 402 | 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 Welte | a02085d | 2011-02-13 22:45:02 +0100 | [diff] [blame] | 406 | |
| 407 | if (!strcmp(argv[0], "add")) |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 408 | con_group_add_path(cg, ccp, ci, tag, 0xff); |
Harald Welte | a02085d | 2011-02-13 22:45:02 +0100 | [diff] [blame] | 409 | else { |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 410 | if (con_group_del_path(cg, ccp, ci, tag, 0xff) < 0) { |
Harald Welte | a02085d | 2011-02-13 22:45:02 +0100 | [diff] [blame] | 411 | 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 Welte | ce49258 | 2016-11-15 22:59:24 +0100 | [diff] [blame] | 420 | DEFUN(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 Welte | 59eee42 | 2011-02-14 16:17:49 +0100 | [diff] [blame] | 443 | DEFUN(cfg_bts_is_conn_list, cfg_bts_is_conn_list_cmd, |
Harald Welte | a8e6a65 | 2011-02-13 22:13:28 +0100 | [diff] [blame] | 444 | "is-connection-list (add|del) <0-2047> <0-2047> <0-255>", |
Ruben Undheim | 59d57da | 2016-12-20 17:38:31 +0100 | [diff] [blame] | 445 | "Interface Switch Connection List\n" |
Harald Welte | a8e6a65 | 2011-02-13 22:13:28 +0100 | [diff] [blame] | 446 | "Add to IS list\n" "Delete from IS list\n" |
| 447 | "ICP1\n" "ICP2\n" "Contiguity Index\n") |
Harald Welte | 8bcb1a0 | 2011-02-12 20:23:40 +0100 | [diff] [blame] | 448 | { |
Harald Welte | 59eee42 | 2011-02-14 16:17:49 +0100 | [diff] [blame] | 449 | struct gsm_bts *bts = vty->index; |
Harald Welte | a8e6a65 | 2011-02-13 22:13:28 +0100 | [diff] [blame] | 450 | 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 Welte | 8bcb1a0 | 2011-02-12 20:23:40 +0100 | [diff] [blame] | 454 | |
Harald Welte | fe7be8d | 2016-11-11 19:44:10 +0100 | [diff] [blame] | 455 | 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 Welte | a8e6a65 | 2011-02-13 22:13:28 +0100 | [diff] [blame] | 461 | 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 Welte | da87154 | 2011-02-14 16:32:44 +0100 | [diff] [blame] | 466 | llist_add_tail(&grp->list, &bts->rbs2000.is.conn_groups); |
Harald Welte | a8e6a65 | 2011-02-13 22:13:28 +0100 | [diff] [blame] | 467 | } 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 Welte | 8bcb1a0 | 2011-02-12 20:23:40 +0100 | [diff] [blame] | 480 | |
Harald Welte | a8e6a65 | 2011-02-13 22:13:28 +0100 | [diff] [blame] | 481 | return CMD_SUCCESS; |
| 482 | } |
| 483 | |
| 484 | |
Harald Welte | a0ce349 | 2011-03-05 14:13:14 +0100 | [diff] [blame] | 485 | DEFUN(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 Welte | 217c6b6 | 2011-03-06 19:46:15 +0100 | [diff] [blame] | 495 | case OM2K_MO_CLS_IS: |
Harald Welte | d529db6 | 2011-03-06 21:49:21 +0100 | [diff] [blame] | 496 | abis_om2k_tx_is_conf_req(bts); |
Harald Welte | 217c6b6 | 2011-03-06 19:46:15 +0100 | [diff] [blame] | 497 | break; |
Harald Welte | a0ce349 | 2011-03-05 14:13:14 +0100 | [diff] [blame] | 498 | 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 Welte | 52af3ae | 2011-03-05 16:14:34 +0100 | [diff] [blame] | 527 | abis_om2k_tx_tx_conf_req(trx); |
Harald Welte | a0ce349 | 2011-03-05 14:13:14 +0100 | [diff] [blame] | 528 | break; |
| 529 | default: |
| 530 | break; |
| 531 | } |
| 532 | break; |
Harald Welte | f9cf961 | 2011-03-05 14:36:47 +0100 | [diff] [blame] | 533 | case OM2K_MO_CLS_TF: |
| 534 | abis_om2k_tx_tf_conf_req(bts); |
| 535 | break; |
Harald Welte | a0ce349 | 2011-03-05 14:13:14 +0100 | [diff] [blame] | 536 | 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 Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 544 | static 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 Welte | 59eee42 | 2011-02-14 16:17:49 +0100 | [diff] [blame] | 560 | void abis_om2k_config_write_bts(struct vty *vty, struct gsm_bts *bts) |
| 561 | { |
| 562 | struct is_conn_group *igrp; |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 563 | struct con_group *cgrp; |
Harald Welte | 59eee42 | 2011-02-14 16:17:49 +0100 | [diff] [blame] | 564 | |
| 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 Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 570 | vty_out(vty, " con-connection-group %u%s", cgrp->cg, |
| 571 | VTY_NEWLINE); |
| 572 | dump_con_group(vty, cgrp); |
Harald Welte | 59eee42 | 2011-02-14 16:17:49 +0100 | [diff] [blame] | 573 | } |
Harald Welte | ce49258 | 2016-11-15 22:59:24 +0100 | [diff] [blame] | 574 | if (bts->rbs2000.use_superchannel) |
| 575 | vty_out(vty, " abis-lower-transport super-channel%s", |
| 576 | VTY_NEWLINE); |
Harald Welte | 59eee42 | 2011-02-14 16:17:49 +0100 | [diff] [blame] | 577 | } |
| 578 | |
Harald Welte | 51c8238 | 2011-02-12 14:44:16 +0100 | [diff] [blame] | 579 | int 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 Erlbeck | 36722e1 | 2013-10-29 09:30:30 +0100 | [diff] [blame] | 585 | vty_install_default(OM2K_NODE); |
Harald Welte | 51c8238 | 2011-02-12 14:44:16 +0100 | [diff] [blame] | 586 | install_element(OM2K_NODE, &om2k_reset_cmd); |
| 587 | install_element(OM2K_NODE, &om2k_start_cmd); |
| 588 | install_element(OM2K_NODE, &om2k_status_cmd); |
Harald Welte | 6fec79d | 2011-02-12 14:57:17 +0100 | [diff] [blame] | 589 | install_element(OM2K_NODE, &om2k_connect_cmd); |
| 590 | install_element(OM2K_NODE, &om2k_disconnect_cmd); |
Harald Welte | 0741ffe | 2011-02-12 18:48:53 +0100 | [diff] [blame] | 591 | install_element(OM2K_NODE, &om2k_enable_cmd); |
| 592 | install_element(OM2K_NODE, &om2k_disable_cmd); |
Harald Welte | 6fec79d | 2011-02-12 14:57:17 +0100 | [diff] [blame] | 593 | install_element(OM2K_NODE, &om2k_op_info_cmd); |
Harald Welte | 8024d8f | 2011-02-12 15:07:30 +0100 | [diff] [blame] | 594 | install_element(OM2K_NODE, &om2k_test_cmd); |
root | 4579978 | 2016-10-15 21:24:57 +0200 | [diff] [blame] | 595 | install_element(OM2K_NODE, &om2k_cap_req_cmd); |
Harald Welte | a0ce349 | 2011-03-05 14:13:14 +0100 | [diff] [blame] | 596 | install_element(OM2K_NODE, &om2k_conf_req_cmd); |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 597 | |
| 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 Welte | 51c8238 | 2011-02-12 14:44:16 +0100 | [diff] [blame] | 602 | |
Harald Welte | 59eee42 | 2011-02-14 16:17:49 +0100 | [diff] [blame] | 603 | install_element(BTS_NODE, &cfg_bts_is_conn_list_cmd); |
Harald Welte | ce49258 | 2016-11-15 22:59:24 +0100 | [diff] [blame] | 604 | install_element(BTS_NODE, &cfg_bts_alt_mode_cmd); |
Harald Welte | eae6829 | 2016-11-11 19:41:59 +0100 | [diff] [blame] | 605 | install_element(BTS_NODE, &cfg_om2k_con_group_cmd); |
Philipp Maier | e1f8b92 | 2017-02-03 17:02:50 +0100 | [diff] [blame] | 606 | install_element(BTS_NODE, &del_om2k_con_group_cmd); |
Harald Welte | 59eee42 | 2011-02-14 16:17:49 +0100 | [diff] [blame] | 607 | |
Harald Welte | 51c8238 | 2011-02-12 14:44:16 +0100 | [diff] [blame] | 608 | return 0; |
| 609 | } |