[PATCH] openbsc[master]: WIP: Support configuration of CON MO Groups/Paths from VTY

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.org
Fri Nov 11 20:21:22 UTC 2016


Review 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>



More information about the gerrit-log mailing list