This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
Harald Welte gerrit-no-reply at lists.osmocom.orgReview at https://gerrit.osmocom.org/1240 WIP: Support configuration of CON MO Groups/Paths from VTY Change-Id: I56dc1b5e35adef3a2078bcf9536537eb0f454192 --- M openbsc/include/openbsc/abis_om2000.h M openbsc/include/openbsc/vty.h M openbsc/src/libbsc/abis_om2000.c M openbsc/src/libbsc/abis_om2000_vty.c M openbsc/src/libcommon/common_vty.c 5 files changed, 236 insertions(+), 71 deletions(-) git pull ssh://gerrit.osmocom.org:29418/openbsc refs/changes/40/1240/1 diff --git a/openbsc/include/openbsc/abis_om2000.h b/openbsc/include/openbsc/abis_om2000.h index c745112..b093a03 100644 --- a/openbsc/include/openbsc/abis_om2000.h +++ b/openbsc/include/openbsc/abis_om2000.h @@ -56,6 +56,39 @@ uint8_t ci; }; +/* on-wire format for CON Path */ +struct om2k_con_path { + uint16_t ccp; + uint8_t ci; + uint8_t tag; + uint8_t tei; +} __attribute__ ((packed)); + +/* internal data format for CON group */ +struct con_group { + /* links list of CON groups in BTS */ + struct llist_head list; + struct gsm_bts *bts; + /* CON Group ID */ + uint8_t cg; + /* list of CON paths in this group */ + struct llist_head paths; +}; + +/* internal data format for CON path */ +struct con_path { + /* links with con_group.paths */ + struct llist_head list; + /* CON Connection Point */ + uint16_t ccp; + /* Contiguity Index */ + uint8_t ci; + /* Tag */ + uint8_t tag; + /* TEI */ + uint8_t tei; +}; + extern const struct abis_om2k_mo om2k_mo_cf; extern const struct abis_om2k_mo om2k_mo_is; extern const struct abis_om2k_mo om2k_mo_con; diff --git a/openbsc/include/openbsc/vty.h b/openbsc/include/openbsc/vty.h index 315db0d..ad2cd2a 100644 --- a/openbsc/include/openbsc/vty.h +++ b/openbsc/include/openbsc/vty.h @@ -29,6 +29,7 @@ NAT_BSC_NODE, MSC_NODE, OM2K_NODE, + OM2K_CON_GROUP_NODE, TRUNK_NODE, PGROUP_NODE, MNCC_INT_NODE, diff --git a/openbsc/src/libbsc/abis_om2000.c b/openbsc/src/libbsc/abis_om2000.c index 8c4bfb3..2733a90 100644 --- a/openbsc/src/libbsc/abis_om2000.c +++ b/openbsc/src/libbsc/abis_om2000.c @@ -1132,20 +1132,48 @@ return abis_om2k_sendmsg(bts, msg); } -int abis_om2k_tx_con_conf_req(struct gsm_bts *bts, uint8_t *data, - unsigned int len) +int abis_om2k_tx_con_conf_req(struct gsm_bts *bts) { struct msgb *msg = om2k_msgb_alloc(); struct abis_om2k_hdr *o2k; + struct con_group *grp; + unsigned int num_grps = 0; - o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k)); + /* count number of groups in linked list */ + llist_for_each_entry(grp, &bts->rbs2000.con.conn_groups, list) + num_grps++; + + if (!num_grps) + return -EINVAL; + + /* first build the value part of the OM2K_DEI_CON_CONN_LIST DEI */ + msgb_put_u8(msg, num_grps); + llist_for_each_entry(grp, &bts->rbs2000.con.conn_groups, list) { + struct con_path *cp; + unsigned int num_paths = 0; + llist_for_each_entry(cp, &grp->paths, list) + num_paths++; + msgb_put_u8(msg, num_paths); + llist_for_each_entry(cp, &grp->paths, list) { + struct om2k_con_path *om2k_cp; + om2k_cp = (struct om2k_con_path *) msgb_put(msg, sizeof(*om2k_cp)); + om2k_cp->ccp = htons(cp->ccp); + om2k_cp->ci = cp->ci; + om2k_cp->tag = cp->tag; + om2k_cp->tei = cp->tei; + } + } + msgb_push_u8(msg, msgb_length(msg)); + msgb_push_u8(msg, OM2K_DEI_CON_CONN_LIST); + + /* pre-pend the list number DEIs */ + msgb_tv_push(msg, OM2K_DEI_END_LIST_NR, 1); + msgb_tv_push(msg, OM2K_DEI_LIST_NR, 1); + + /* pre-pend the OM2K header */ + o2k = (struct abis_om2k_hdr *) msgb_push(msg, sizeof(*o2k)); fill_om2k_hdr(o2k, &bts->rbs2000.con.om2k_mo.addr, OM2K_MSGT_CON_CONF_REQ); - - msgb_tv_put(msg, OM2K_DEI_LIST_NR, 1); - msgb_tv_put(msg, OM2K_DEI_END_LIST_NR, 1); - - msgb_tlv_put(msg, OM2K_DEI_CON_CONN_LIST, len, data); DEBUGP(DNM, "Tx MO=%s %s\n", om2k_mo_name(&bts->rbs2000.con.om2k_mo.addr), @@ -1566,8 +1594,7 @@ abis_om2k_tx_is_conf_req(omfp->trx->bts); break; case OM2K_MO_CLS_CON: - /* TODO */ - //abis_om2k_tx_con_conf_req(omfp->trx->bts, data, len); + abis_om2k_tx_con_conf_req(omfp->trx->bts); break; case OM2K_MO_CLS_TX: abis_om2k_tx_tx_conf_req(omfp->trx); @@ -2061,6 +2088,7 @@ OM2K_BTS_EVT_START, OM2K_BTS_EVT_CF_DONE, OM2K_BTS_EVT_IS_DONE, + OM2K_BTS_EVT_CON_DONE, OM2K_BTS_EVT_TF_DONE, OM2K_BTS_EVT_TRX_DONE, OM2K_BTS_EVT_STOP, @@ -2070,6 +2098,7 @@ { OM2K_BTS_EVT_START, "START" }, { OM2K_BTS_EVT_CF_DONE, "CF-DONE" }, { OM2K_BTS_EVT_IS_DONE, "IS-DONE" }, + { OM2K_BTS_EVT_CON_DONE, "CON-DONE" }, { OM2K_BTS_EVT_TF_DONE, "TF-DONE" }, { OM2K_BTS_EVT_TRX_DONE, "TRX-DONE" }, { OM2K_BTS_EVT_STOP, "STOP" }, @@ -2080,6 +2109,7 @@ OM2K_BTS_S_INIT, OM2K_BTS_S_WAIT_CF, OM2K_BTS_S_WAIT_IS, + OM2K_BTS_S_WAIT_CON, OM2K_BTS_S_WAIT_TF, OM2K_BTS_S_WAIT_TRX, OM2K_BTS_S_DONE, @@ -2121,6 +2151,18 @@ struct gsm_bts *bts = obfp->bts; OSMO_ASSERT(event == OM2K_BTS_EVT_IS_DONE); + osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_WAIT_CON, + BTS_FSM_TIMEOUT, 0); + om2k_mo_fsm_start(fi, OM2K_BTS_EVT_CON_DONE, bts->c0, + &bts->rbs2000.con.om2k_mo); +} + +static void om2k_bts_s_wait_con(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct om2k_bts_fsm_priv *obfp = fi->priv; + struct gsm_bts *bts = obfp->bts; + + OSMO_ASSERT(event == OM2K_BTS_EVT_CON_DONE); /* TF can take a long time to initialize, wait for 10min */ osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_WAIT_TF, 600, 0); om2k_mo_fsm_start(fi, OM2K_BTS_EVT_TF_DONE, bts->c0, @@ -2178,10 +2220,17 @@ [OM2K_BTS_S_WAIT_IS] = { .in_event_mask = S(OM2K_BTS_EVT_IS_DONE), .out_state_mask = S(OM2K_BTS_S_ERROR) | - S(OM2K_BTS_S_WAIT_TF), + S(OM2K_BTS_S_WAIT_CON), .name = "WAIT-IS", .action = om2k_bts_s_wait_is, }, + [OM2K_BTS_S_WAIT_CON] = { + .in_event_mask = S(OM2K_BTS_EVT_CON_DONE), + .out_state_mask = S(OM2K_BTS_S_ERROR) | + S(OM2K_BTS_S_WAIT_TF), + .name = "WAIT-CON", + .action = om2k_bts_s_wait_con, + }, [OM2K_BTS_S_WAIT_TF] = { .in_event_mask = S(OM2K_BTS_EVT_TF_DONE), .out_state_mask = S(OM2K_BTS_S_ERROR) | diff --git a/openbsc/src/libbsc/abis_om2000_vty.c b/openbsc/src/libbsc/abis_om2000_vty.c index 64d205c..b68a8ea 100644 --- a/openbsc/src/libbsc/abis_om2000_vty.c +++ b/openbsc/src/libbsc/abis_om2000_vty.c @@ -48,9 +48,18 @@ 1, }; +static struct cmd_node om2k_con_group_node = { + OM2K_CON_GROUP_NODE, + "%s(om2k-con-group)# ", + 1, +}; + +struct con_group; + struct oml_node_state { struct gsm_bts *bts; struct abis_om2k_mo mo; + struct con_group *cg; }; static int dummy_config_write(struct vty *v) @@ -246,65 +255,112 @@ return CMD_SUCCESS; } - -struct con_conn_group { - struct llist_head list; - - uint8_t cg; - uint16_t ccp; - uint8_t tag; - uint8_t tei; -}; - -static void add_con_list(struct gsm_bts *bts, uint8_t cg, uint16_t ccp, - uint8_t tag, uint8_t tei) +static struct con_group *con_group_find_or_create(struct gsm_bts *bts, uint8_t cg) { - struct con_conn_group *ent = talloc_zero(bts, struct con_conn_group); + struct con_group *ent; + llist_for_each_entry(ent, &bts->rbs2000.con.conn_groups, list) { + if (ent->cg == cg) + return ent; + } + + ent = talloc_zero(bts, struct con_group); + ent->bts = bts; ent->cg = cg; - ent->ccp = ccp; - ent->tag = tag; - ent->tei = tei; - + INIT_LLIST_HEAD(&ent->paths); llist_add_tail(&ent->list, &bts->rbs2000.con.conn_groups); + + return ent; } -static int del_con_list(struct gsm_bts *bts, uint8_t cg, uint16_t ccp, - uint8_t tag, uint8_t tei) +static int con_group_del(struct gsm_bts *bts, uint8_t cg_id) { - struct con_conn_group *grp, *grp2; + struct con_group *cg, *cg2; - llist_for_each_entry_safe(grp, grp2, &bts->rbs2000.con.conn_groups, list) { - if (grp->cg == cg && grp->ccp == ccp && grp->tag == tag - && grp->tei == tei) { - llist_del(&grp->list); - talloc_free(grp); + llist_for_each_entry_safe(cg, cg2, &bts->rbs2000.con.conn_groups, list) { + if (cg->cg == cg_id) { + llist_del(&cg->list); + talloc_free(cg); + return 0; + }; + } + return -ENOENT; +} + +static void con_group_add_path(struct con_group *cg, uint16_t ccp, + uint8_t ci, uint8_t tag, uint8_t tei) +{ + struct con_path *cp = talloc_zero(cg, struct con_path); + + cp->ccp = ccp; + cp->ci = ci; + cp->tag = tag; + cp->tei = tei; + llist_add(&cp->list, &cg->paths); +} + +static int con_group_del_path(struct con_group *cg, uint16_t ccp, + uint8_t ci, uint8_t tag, uint8_t tei) +{ + struct con_path *cp, *cp2; + llist_for_each_entry_safe(cp, cp2, &cg->paths, list) { + if (cp->ccp == ccp && cp->ci == ci && cp->tag == tag && + cp->tei == tei) { + llist_del(&cp->list); + talloc_free(cp); return 0; } } return -ENOENT; } -#define CON_LIST_HELP "CON connetiton list\n" \ - "Add entry to CON list\n" \ - "Delete entry from CON list\n" \ - "Connection Group Number\n" \ - "CON Connection Point\n" \ - -DEFUN(om2k_con_list_dec, om2k_con_list_dec_cmd, - "con-connection-list (add|del) <1-255> <0-1023> deconcentrated", - CON_LIST_HELP "De-concentrated in/outlet\n") +DEFUN(cfg_om2k_con_group, cfg_om2k_con_group_cmd, + "con-connection-group <1-31>", + "Configure a CON (Concentrator) Connection Group\n" + "CON Connection Group Number\n") { - struct oml_node_state *oms = vty->index; - struct gsm_bts *bts = oms->bts; - uint8_t cg = atoi(argv[1]); - uint16_t ccp = atoi(argv[2]); + struct gsm_bts *bts = vty->index; + struct con_group *cg; + uint8_t cgid = atoi(argv[0]); + + if (bts->type != GSM_BTS_TYPE_RBS2000) { + vty_out(vty, "%% CON MO only exists in RBS2000%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + cg = con_group_find_or_create(bts, cgid); + if (!cg) { + vty_out(vty, "%% Cannot create CON Group%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + vty->node = OM2K_CON_GROUP_NODE; + vty->index = cg; + + return CMD_SUCCESS; +} + +#define CON_PATH_HELP "CON Path (In/Out)\n" \ + "Add CON Path to Concentration Group\n" \ + "Delete CON Path from Concentration Group\n" \ + "Contiguity Index\n" \ + +DEFUN(cfg_om2k_con_path_dec, cfg_om2k_con_path_dec_cmd, + "con-path (add|del) <0-1023> <0-7> deconcentrated <0-63>", + CON_PATH_HELP "De-concentrated in/outlet\n" "TEI Value\n") +{ + struct con_group *cg = vty->index; + uint16_t ccp = atoi(argv[1]); + uint8_t ci = atoi(argv[2]); + uint8_t tei = atoi(argv[3]); if (!strcmp(argv[0], "add")) - add_con_list(bts, cg, ccp, 0, 0xff); + con_group_add_path(cg, ccp, ci, 0, tei); else { - if (del_con_list(bts, cg, ccp, 0, 0xff) < 0) { - vty_out(vty, "%% No matching CON list entry%s", + if (con_group_del_path(cg, ccp, ci, 0, tei) < 0) { + vty_out(vty, "%% No matching CON Path%s", VTY_NEWLINE); return CMD_WARNING; } @@ -313,20 +369,19 @@ return CMD_SUCCESS; } -DEFUN(om2k_con_list_tei, om2k_con_list_tei_cmd, - "con-connection-list (add|del) <1-255> <0-1023> tei <0-63>", - CON_LIST_HELP "Concentrated in/outlet with TEI\n" "TEI Number\n") +DEFUN(cfg_om2k_con_path_conc, cfg_om2k_con_path_conc_cmd, + "con-path (add|del) <0-1023> <0-7> concentrated <1-16>", + CON_PATH_HELP "Concentrated in/outlet\n" "Tag Number\n") { - struct oml_node_state *oms = vty->index; - struct gsm_bts *bts = oms->bts; - uint8_t cg = atoi(argv[1]); - uint16_t ccp = atoi(argv[2]); - uint8_t tei = atoi(argv[3]); + struct con_group *cg = vty->index; + uint16_t ccp = atoi(argv[1]); + uint8_t ci = atoi(argv[2]); + uint8_t tag = atoi(argv[3]); if (!strcmp(argv[0], "add")) - add_con_list(bts, cg, ccp, cg, tei); + con_group_add_path(cg, ccp, ci, tag, 0xff); else { - if (del_con_list(bts, cg, ccp, cg, tei) < 0) { + if (con_group_del_path(cg, ccp, ci, tag, 0xff) < 0) { vty_out(vty, "%% No matching CON list entry%s", VTY_NEWLINE); return CMD_WARNING; @@ -437,22 +492,35 @@ return CMD_SUCCESS; } +static void dump_con_group(struct vty *vty, struct con_group *cg) +{ + struct con_path *cp; + + llist_for_each_entry(cp, &cg->paths, list) { + vty_out(vty, " con-path add %u %u ", cp->ccp, cp->ci); + if (cp->tei == 0xff) { + vty_out(vty, "concentrated %u%s", cp->tag, + VTY_NEWLINE); + } else { + vty_out(vty, "deconcentrated %u%s", cp->tei, + VTY_NEWLINE); + } + } +} + void abis_om2k_config_write_bts(struct vty *vty, struct gsm_bts *bts) { struct is_conn_group *igrp; - struct con_conn_group *cgrp; + struct con_group *cgrp; llist_for_each_entry(igrp, &bts->rbs2000.is.conn_groups, list) vty_out(vty, " is-connection-list add %u %u %u%s", igrp->icp1, igrp->icp2, igrp->ci, VTY_NEWLINE); llist_for_each_entry(cgrp, &bts->rbs2000.con.conn_groups, list) { - vty_out(vty, " con-connection-list add %u %u ", - cgrp->cg, cgrp->ccp); - if (cgrp->tei == 0xff) - vty_out(vty, "deconcentrated%s", VTY_NEWLINE); - else - vty_out(vty, "tei %u%s", cgrp->tei, VTY_NEWLINE); + vty_out(vty, " con-connection-group %u%s", cgrp->cg, + VTY_NEWLINE); + dump_con_group(vty, cgrp); } } @@ -474,10 +542,14 @@ install_element(OM2K_NODE, &om2k_test_cmd); install_element(OM2K_NODE, &om2k_cap_req_cmd); install_element(OM2K_NODE, &om2k_conf_req_cmd); - install_element(OM2K_NODE, &om2k_con_list_dec_cmd); - install_element(OM2K_NODE, &om2k_con_list_tei_cmd); + + install_node(&om2k_con_group_node, dummy_config_write); + vty_install_default(OM2K_CON_GROUP_NODE); + install_element(OM2K_CON_GROUP_NODE, &cfg_om2k_con_path_dec_cmd); + install_element(OM2K_CON_GROUP_NODE, &cfg_om2k_con_path_conc_cmd); install_element(BTS_NODE, &cfg_bts_is_conn_list_cmd); + install_element(BTS_NODE, &cfg_om2k_con_group_cmd); return 0; } diff --git a/openbsc/src/libcommon/common_vty.c b/openbsc/src/libcommon/common_vty.c index a0674f0..834da51 100644 --- a/openbsc/src/libcommon/common_vty.c +++ b/openbsc/src/libcommon/common_vty.c @@ -28,6 +28,7 @@ #include <openbsc/debug.h> #include <openbsc/gsm_subscriber.h> #include <openbsc/bsc_nat.h> +#include <openbsc/abis_om2000.h> #include <osmocom/vty/telnet_interface.h> #include <osmocom/vty/command.h> @@ -79,6 +80,15 @@ talloc_free(vty->index); vty->index = NULL; break; + case OM2K_CON_GROUP_NODE: + vty->node = BTS_NODE; + { + struct con_group *cg = vty->index; + struct gsm_bts *bts = cg->bts; + vty->index = bts; + vty->index_sub = &bts->description; + } + break; case NAT_BSC_NODE: vty->node = NAT_NODE; { -- To view, visit https://gerrit.osmocom.org/1240 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I56dc1b5e35adef3a2078bcf9536537eb0f454192 Gerrit-PatchSet: 1 Gerrit-Project: openbsc Gerrit-Branch: master Gerrit-Owner: Harald Welte <laforge at gnumonks.org>