[MERGED] openbsc[master]: 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
Sun Nov 13 20:41:50 UTC 2016


Harald Welte has submitted this change and it was merged.

Change subject: Support configuration of CON MO Groups/Paths from VTY
......................................................................


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
---
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, 237 insertions(+), 71 deletions(-)

Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified



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..2a89d49 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,113 @@
 	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"	\
+			"CON Conection Point\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 +370,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 +493,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 +543,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: merged
Gerrit-Change-Id: I56dc1b5e35adef3a2078bcf9536537eb0f454192
Gerrit-PatchSet: 4
Gerrit-Project: openbsc
Gerrit-Branch: master
Gerrit-Owner: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder



More information about the gerrit-log mailing list