summaryrefslogtreecommitdiffstats
path: root/openbsc/src/libbsc/abis_om2000.c
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2016-11-11 19:41:59 +0100
committerHarald Welte <laforge@gnumonks.org>2016-11-13 21:22:29 +0100
commiteae68292bdd3906950260ac307081af4b3acf3e5 (patch)
tree64cdf96a013125db0f7f59c6c5fe836338501c2f /openbsc/src/libbsc/abis_om2000.c
parentfe7be8ddd0563ee98ca2ee9879983384d2491306 (diff)
Support configuration of CON MO Groups/Paths from VTY
The code for supporting the configuration of the OM2000 CON (LAPD Concentrator) MO was so far incomplete and not used from the OM2000 FSM initialization. This patch adds * VTY commands for configuration of CON Groups and Paths * The FSM integration to actually configure the CON MO Change-Id: I56dc1b5e35adef3a2078bcf9536537eb0f454192
Diffstat (limited to 'openbsc/src/libbsc/abis_om2000.c')
-rw-r--r--openbsc/src/libbsc/abis_om2000.c71
1 files changed, 60 insertions, 11 deletions
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 @@ int abis_om2k_tx_is_conf_req(struct gsm_bts *bts)
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));
- fill_om2k_hdr(o2k, &bts->rbs2000.con.om2k_mo.addr,
- OM2K_MSGT_CON_CONF_REQ);
+ /* count number of groups in linked list */
+ llist_for_each_entry(grp, &bts->rbs2000.con.conn_groups, list)
+ num_grps++;
- msgb_tv_put(msg, OM2K_DEI_LIST_NR, 1);
- msgb_tv_put(msg, OM2K_DEI_END_LIST_NR, 1);
+ 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);
- msgb_tlv_put(msg, OM2K_DEI_CON_CONN_LIST, len, data);
+ /* 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);
DEBUGP(DNM, "Tx MO=%s %s\n",
om2k_mo_name(&bts->rbs2000.con.om2k_mo.addr),
@@ -1566,8 +1594,7 @@ static void om2k_mo_st_wait_start_res(struct osmo_fsm_inst *fi, uint32_t event,
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 @@ enum om2k_bts_event {
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 @@ static const struct value_string om2k_bts_events[] = {
{ 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 @@ enum om2k_bts_state {
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 @@ static void om2k_bts_s_wait_is(struct osmo_fsm_inst *fi, uint32_t event, void *d
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 @@ static const struct osmo_fsm_state om2k_bts_states[] = {
[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) |