[PATCH 3/6] vty: Generalize ournode_exit() and ournode_end()

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/OpenBSC@lists.osmocom.org/.

Jacob Erlbeck jerlbeck at sysmocom.de
Fri Aug 30 16:34:00 UTC 2013


ournode_exit() duplicates most of bsc_vty_go_parent(). This patch
fixes the inconsistencies of both functions within
bsc_vty_go_parent() and replaces the implementation of
ournode_exit() by a call to it. This makes 'exit' behave exactly
like ^D in all openbsc nodes.

ournode_end() has been changed to walk through the intermediate
nodes until one of the top nodes is reached. This allows for
cleanups to be done on the way.

Note that in config mode if the tree is searched along the nodes
toward the config node and a command is not found this way, a
rollback is done by just replacing the vty's node and index member
variable by the saved old values which might break the whole thing, when
there has been a free() on the way.
---
 openbsc/src/libcommon/common_vty.c |  140 ++++++++++--------------------------
 openbsc/tests/vty_test_runner.py   |   65 +++++++++--------
 2 files changed, 68 insertions(+), 137 deletions(-)

diff --git a/openbsc/src/libcommon/common_vty.c b/openbsc/src/libcommon/common_vty.c
index 7342f14..948bd49 100644
--- a/openbsc/src/libcommon/common_vty.c
+++ b/openbsc/src/libcommon/common_vty.c
@@ -48,6 +48,7 @@ enum node_type bsc_vty_go_parent(struct vty *vty)
 			/* set vty->index correctly ! */
 			struct gsm_bts *bts = vty->index;
 			vty->index = bts->network;
+			vty->index_sub = NULL;
 		}
 		break;
 	case TRX_NODE:
@@ -56,6 +57,7 @@ enum node_type bsc_vty_go_parent(struct vty *vty)
 			/* set vty->index correctly ! */
 			struct gsm_bts_trx *trx = vty->index;
 			vty->index = trx->bts;
+			vty->index_sub = &trx->bts->description;
 		}
 		break;
 	case TS_NODE:
@@ -64,18 +66,19 @@ enum node_type bsc_vty_go_parent(struct vty *vty)
 			/* set vty->index correctly ! */
 			struct gsm_bts_trx_ts *ts = vty->index;
 			vty->index = ts->trx;
+			vty->index_sub = &ts->trx->description;
 		}
 		break;
 	case OML_NODE:
 	case OM2K_NODE:
 		vty->node = ENABLE_NODE;
+		/* NOTE: this only works because it's not part of the config
+		 * tree, where outer commands are searched via vty_go_parent()
+		 * and only (!) executed when a matching one is found.
+		 */
 		talloc_free(vty->index);
 		vty->index = NULL;
 		break;
-	case NAT_NODE:
-		vty->node = CONFIG_NODE;
-		vty->index = NULL;
-		break;
 	case NAT_BSC_NODE:
 		vty->node = NAT_NODE;
 		{
@@ -85,19 +88,31 @@ enum node_type bsc_vty_go_parent(struct vty *vty)
 		break;
 	case PGROUP_NODE:
 		vty->node = NAT_NODE;
+		vty->index = NULL;
 		break;
 	case TRUNK_NODE:
 		vty->node = MGCP_NODE;
+		vty->index = NULL;
 		break;
 	case SMPP_ESME_NODE:
 		vty->node = SMPP_NODE;
 		vty->index = NULL;
 		break;
 	case SMPP_NODE:
+	case MGCP_NODE:
+	case GBPROXY_NODE:
+	case SGSN_NODE:
+	case NAT_NODE:
+	case BSC_NODE:
 	case MSC_NODE:
 	case MNCC_INT_NODE:
 	default:
-		vty->node = CONFIG_NODE;
+		if (bsc_vty_is_config_node(vty, vty->node))
+			vty->node = CONFIG_NODE;
+		else
+			vty->node = ENABLE_NODE;
+
+		vty->index = NULL;
 	}
 
 	return vty->node;
@@ -107,78 +122,7 @@ enum node_type bsc_vty_go_parent(struct vty *vty)
 gDEFUN(ournode_exit,
        ournode_exit_cmd, "exit", "Exit current mode and down to previous mode\n")
 {
-	switch (vty->node) {
-	case GSMNET_NODE:
-		vty->node = CONFIG_NODE;
-		vty->index = NULL;
-		break;
-	case BTS_NODE:
-		vty->node = GSMNET_NODE;
-		{
-			/* set vty->index correctly ! */
-			struct gsm_bts *bts = vty->index;
-			vty->index = bts->network;
-			vty->index_sub = NULL;
-		}
-		break;
-	case TRX_NODE:
-		vty->node = BTS_NODE;
-		{
-			/* set vty->index correctly ! */
-			struct gsm_bts_trx *trx = vty->index;
-			vty->index = trx->bts;
-			vty->index_sub = &trx->bts->description;
-		}
-		break;
-	case TS_NODE:
-		vty->node = TRX_NODE;
-		{
-			/* set vty->index correctly ! */
-			struct gsm_bts_trx_ts *ts = vty->index;
-			vty->index = ts->trx;
-			vty->index_sub = &ts->trx->description;
-		}
-		break;
-	case NAT_BSC_NODE:
-		vty->node = NAT_NODE;
-		{
-			struct bsc_config *bsc_config = vty->index;
-			vty->index = bsc_config->nat;
-		}
-		break;
-	case PGROUP_NODE:
-		vty->node = NAT_NODE;
-		break;
-	case SMPP_ESME_NODE:
-		vty->node = SMPP_NODE;
-		vty->index = NULL;
-		break;
-	case SMPP_NODE:
-	case MGCP_NODE:
-	case GBPROXY_NODE:
-	case SGSN_NODE:
-	case NAT_NODE:
-	case BSC_NODE:
-		vty->node = CONFIG_NODE;
-		vty->index = NULL;
-		break;
-	case OML_NODE:
-	case OM2K_NODE:
-		vty->node = ENABLE_NODE;
-		talloc_free(vty->index);
-		vty->index = NULL;
-		break;
-	case MSC_NODE:
-	case MNCC_INT_NODE:
-		vty->node = CONFIG_NODE;
-		break;
-	case TRUNK_NODE:
-		vty->node = MGCP_NODE;
-		vty->index = NULL;
-		break;
-	default:
-		break;
-	}
+	bsc_vty_go_parent (vty);
 	return CMD_SUCCESS;
 }
 
@@ -186,36 +130,24 @@ gDEFUN(ournode_exit,
 gDEFUN(ournode_end,
        ournode_end_cmd, "end", "End current mode and change to enable mode.")
 {
-	switch (vty->node) {
-	case VIEW_NODE:
-	case ENABLE_NODE:
-		/* Nothing to do. */
-		break;
-	case CONFIG_NODE:
-	case GSMNET_NODE:
-	case BTS_NODE:
-	case TRX_NODE:
-	case TS_NODE:
-	case MGCP_NODE:
-	case TRUNK_NODE:
-	case GBPROXY_NODE:
-	case SGSN_NODE:
-	case VTY_NODE:
-	case NAT_NODE:
-	case NAT_BSC_NODE:
-	case PGROUP_NODE:
-	case MSC_NODE:
-	case MNCC_INT_NODE:
-	case SMPP_NODE:
-	case SMPP_ESME_NODE:
-	case BSC_NODE:
+	enum node_type last_node = CONFIG_NODE;
+	
+	if (vty->node >= CONFIG_NODE) {
+		/* Repeatedly call go_parent until a top node is reached. */
+		while (vty->node > CONFIG_NODE) {
+			if (vty->node == last_node) {
+				/* Ensure termination, this shouldn't happen. */
+				break;
+			}
+			last_node = vty->node;
+			bsc_vty_go_parent(vty);
+		}
+
 		vty_config_unlock(vty);
-		vty->node = ENABLE_NODE;
+		if (vty->node > ENABLE_NODE)
+			vty->node = ENABLE_NODE;
 		vty->index = NULL;
 		vty->index_sub = NULL;
-		break;
-	default:
-		break;
 	}
 	return CMD_SUCCESS;
 }
diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py
index 7b8498b..4426860 100644
--- a/openbsc/tests/vty_test_runner.py
+++ b/openbsc/tests/vty_test_runner.py
@@ -81,25 +81,25 @@ class TestVTYGenericBTS(TestVTYBase):
 
     def _testConfigNetworkTree(self):
         self.vty.enable()
-        self.vty.verify("configure terminal",[''])
+        self.assertTrue(self.vty.verify("configure terminal",['']))
         self.assertEquals(self.vty.node(), 'config')
         # self.checkForEndAndExit()
-        self.vty.verify("network",[''])
+        self.assertTrue(self.vty.verify("network",['']))
         self.assertEquals(self.vty.node(), 'config-net')
         self.checkForEndAndExit()
-        self.vty.verify("bts 0",[''])
+        self.assertTrue(self.vty.verify("bts 0",['']))
         self.assertEquals(self.vty.node(), 'config-net-bts')
         self.checkForEndAndExit()
-        self.vty.verify("trx 0",[''])
+        self.assertTrue(self.vty.verify("trx 0",['']))
         self.assertEquals(self.vty.node(), 'config-net-bts-trx')
         self.checkForEndAndExit()
-        self.vty.verify("exit",[''])
+        self.assertTrue(self.vty.verify("exit",['']))
         self.assertEquals(self.vty.node(), 'config-net-bts')
-        self.vty.verify("exit",[''])
+        self.assertTrue(self.vty.verify("exit",['']))
         self.assertEquals(self.vty.node(), 'config-net')
-        self.vty.verify("exit",[''])
+        self.assertTrue(self.vty.verify("exit",['']))
         self.assertEquals(self.vty.node(), 'config')
-        self.vty.verify("exit",[''])
+        self.assertTrue(self.vty.verify("exit",['']))
         self.assertTrue(self.vty.node() is None)
 
 class TestVTYNITB(TestVTYGenericBTS):
@@ -116,24 +116,23 @@ class TestVTYNITB(TestVTYGenericBTS):
 
     def testVtyTree(self):
         self.vty.enable()
-        self.vty.verify("configure terminal", [''])
+        self.assertTrue(self.vty.verify("configure terminal", ['']))
         self.assertEquals(self.vty.node(), 'config')
         self.ignoredCheckForEndAndExit()
-        self.vty.verify('mncc-int', [''])
+        self.assertTrue(self.vty.verify('mncc-int', ['']))
         self.assertEquals(self.vty.node(), 'config-mncc-int')
         self.checkForEndAndExit()
-        if self.notIgnoredTest():
-            self.vty.verify('exit', [''])
-            self.assertEquals(self.vty.node(), 'config')
-        else:
-            self.vty.verify("configure terminal", [''])
-        self.vty.verify('smpp', [''])
+        self.assertTrue(self.vty.verify('exit', ['']))
+        self.assertEquals(self.vty.node(), 'config')
+        self.assertTrue(self.vty.verify('smpp', ['']))
         self.assertEquals(self.vty.node(), 'config-smpp')
         self.ignoredCheckForEndAndExit()
-        self.vty.verify("exit", [''])
+        self.assertTrue(self.vty.verify("exit", ['']))
         if self.notIgnoredTest():
             self.assertEquals(self.vty.node(), 'config')
-            self.vty.verify("exit", [''])
+        else:
+            self.assertTrue(self.vty.verify("configure terminal", ['']))
+        self.assertTrue(self.vty.verify("exit", ['']))
         self.assertTrue(self.vty.node() is None)
 
         # Check searching for outer node's commands
@@ -181,26 +180,26 @@ class TestVTYBSC(TestVTYGenericBTS):
 
     def testVtyTree(self):
         self.vty.enable()
-        self.vty.verify("configure terminal", [''])
+        self.assertTrue(self.vty.verify("configure terminal", ['']))
         self.assertEquals(self.vty.node(), 'config')
         # self.ignoredCheckForEndAndExit()
-        self.vty.verify("msc 0", [''])
+        self.assertTrue(self.vty.verify("msc 0", ['']))
         self.assertEquals(self.vty.node(), 'config-msc')
         # self.ignoredCheckForEndAndExit()
-        self.vty.verify("exit", [''])
+        self.assertTrue(self.vty.verify("exit", ['']))
         if self.notIgnoredTest():
             self.assertEquals(self.vty.node(), 'config')
         else:
-            self.vty.verify("configure terminal", [''])
+            self.assertTrue(self.vty.verify("configure terminal", ['']))
         self.vty.command("bsc")
         self.assertEquals(self.vty.node(), 'config-bsc')
         self.ignoredCheckForEndAndExit()
-        self.vty.verify("exit", [''])
+        self.assertTrue(self.vty.verify("exit", ['']))
         if self.notIgnoredTest():
             self.assertEquals(self.vty.node(), 'config')
         else:
-            self.vty.verify("configure terminal", [''])
-        self.vty.verify("exit", [''])
+            self.assertTrue(self.vty.verify("configure terminal", ['']))
+        self.assertTrue(self.vty.verify("exit", ['']))
         self.assertTrue(self.vty.node() is None)
 
         # Check searching for outer node's commands
@@ -253,25 +252,25 @@ class TestVTYNAT(TestVTYGenericBTS):
 
     def testVtyTree(self):
         self.vty.enable()
-        self.vty.verify('configure terminal', [''])
+        self.assertTrue(self.vty.verify('configure terminal', ['']))
         self.assertEquals(self.vty.node(), 'config')
         # self.checkForEndAndExit()
-        self.vty.verify('mgcp', [''])
+        self.assertTrue(self.vty.verify('mgcp', ['']))
         self.assertEquals(self.vty.node(), 'config-mgcp')
         self.checkForEndAndExit()
-        self.vty.verify('exit', [''])
+        self.assertTrue(self.vty.verify('exit', ['']))
         self.assertEquals(self.vty.node(), 'config')
-        self.vty.verify('nat', [''])
+        self.assertTrue(self.vty.verify('nat', ['']))
         self.assertEquals(self.vty.node(), 'config-nat')
         self.checkForEndAndExit()
-        self.vty.verify('bsc 0', [''])
+        self.assertTrue(self.vty.verify('bsc 0', ['']))
         self.assertEquals(self.vty.node(), 'config-nat-bsc')
         self.checkForEndAndExit()
-        self.vty.verify('exit', [''])
+        self.assertTrue(self.vty.verify('exit', ['']))
         self.assertEquals(self.vty.node(), 'config-nat')
-        self.vty.verify('exit', [''])
+        self.assertTrue(self.vty.verify('exit', ['']))
         self.assertEquals(self.vty.node(), 'config')
-        self.vty.verify('exit', [''])
+        self.assertTrue(self.vty.verify('exit', ['']))
         self.assertTrue(self.vty.node() is None)
 
         # Check searching for outer node's commands
-- 
1.7.9.5





More information about the OpenBSC mailing list