Omar Ramadan has uploaded this change for review. ( 
https://gerrit.osmocom.org/12814


Change subject: VTY: add command show asciidoc ctrl
......................................................................

VTY: add command show asciidoc ctrl

Builds on the asciidoc VTY feature to list out all of the registered CTRL
commands for a particular project. This will help with documentation generation
efforts, and serve as a quick way to know which CTRL parameters are registered

CTRL command access mode indicator

Adds an explicit access mode enum type, ctrl_cmd_mode to ctrl_cmd_element
which provides a programatic way to detect whether a CTRL command is RO/WO/RW
Also associates the access mode with the "show asciidoc ctrl" VTY command

Change-Id: I16f59bfca72a7dd9c268bc64499b26d82a2115d2
---
M include/osmocom/ctrl/control_cmd.h
M src/ctrl/control_cmd.c
M src/ctrl/control_vty.c
3 files changed, 122 insertions(+), 7 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/14/12814/1

diff --git a/include/osmocom/ctrl/control_cmd.h 
b/include/osmocom/ctrl/control_cmd.h
index 276a7de..045bc2c 100644
--- a/include/osmocom/ctrl/control_cmd.h
+++ b/include/osmocom/ctrl/control_cmd.h
@@ -38,6 +38,13 @@
        CTRL_TYPE_ERROR
 };

+/*! Ctrl command modes (RO, WO, RW) */
+enum ctrl_cmd_mode {
+       CTRL_MODE_RO,
+       CTRL_MODE_WO,
+       CTRL_MODE_RW
+};
+
 /*! human-readable string names for \ref ctrl_type */
 extern const struct value_string ctrl_type_vals[];

@@ -96,6 +103,8 @@
        /*! textual name/id of the CTRL command */
        const char *name;
        struct ctrl_cmd_struct strcmd;
+       /*! read/write mode of the CTRL command */
+       enum ctrl_cmd_mode mode;
        /*! call-back function implementing the SET operation */
        int (*set)(struct ctrl_cmd *cmd, void *data);
        /*! call-back function implementing the GET operation */
@@ -125,6 +134,8 @@
 int ctrl_cmd_install(enum ctrl_node_type node, struct ctrl_cmd_element *cmd);
 int ctrl_cmd_send(struct osmo_wqueue *queue, struct ctrl_cmd *cmd);
 int ctrl_cmd_send_to_all(struct ctrl_handle *ctrl, struct ctrl_cmd *cmd);
+int ctrl_cmds_for_each(int (*handle_ctrl_cmd)(struct ctrl_cmd_element *, void 
*),
+                                                       enum ctrl_node_type 
node, void *data);
 struct ctrl_cmd *ctrl_cmd_parse3(void *ctx, struct msgb *msg, bool 
*parse_failed);
 struct ctrl_cmd *ctrl_cmd_parse2(void *ctx, struct msgb *msg);
 struct ctrl_cmd *ctrl_cmd_parse(void *ctx, struct msgb *msg);
@@ -136,10 +147,12 @@
 /*! Helper to generate static struct ctrl_cmd_element
  *  \param[in] cmdname symbol name of the command related functions/structures
  *  \param[in] cmdstr string name exposed on CTRL
+ *  \param[in] cmdmode access mode of CTRL command
  *  \param[in] verify_name full symbol name of verification function */
-#define CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_name) \
+#define CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, cmdmode, verify_name) \
 static struct ctrl_cmd_element cmd_##cmdname = { \
        .name = cmdstr, \
+       .mode = cmdmode, \
        .get = &get_##cmdname, \
        .set = &set_##cmdname, \
        .verify = verify_name, \
@@ -200,7 +213,7 @@
        CTRL_HELPER_GET_INT(cmdname, dtype, element) \
        CTRL_HELPER_SET_INT(cmdname, dtype, element) \
        CTRL_HELPER_VERIFY_RANGE(cmdname, min, max) \
-CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_##cmdname)
+CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, CTRL_MODE_RW, verify_##cmdname)

 /*! Helper to generate static GET function for string
  *  \param[in] cmdname symbol name of the command related function
@@ -240,7 +253,7 @@
 #define CTRL_CMD_DEFINE_STRING(cmdname, cmdstr, dtype, element) \
        CTRL_HELPER_GET_STRING(cmdname, dtype, element) \
        CTRL_HELPER_SET_STRING(cmdname, dtype, element) \
-CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, NULL)
+CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, CTRL_MODE_RW, NULL)

 /*! Declare a read-write attribute. Declares get, set, verify.
  *  \param[in] cmdname symbol name of the command related functions/structures
@@ -249,7 +262,7 @@
 static int get_##cmdname(struct ctrl_cmd *cmd, void *data); \
 static int set_##cmdname(struct ctrl_cmd *cmd, void *data); \
 static int verify_##cmdname(struct ctrl_cmd *cmd, const char *value, void 
*data); \
-CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_##cmdname)
+CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, CTRL_MODE_RW, verify_##cmdname)

 /*! Define a read-only attribute. Declares get, implements set+verify
  *  \param[in] cmdname symbol name of the command related functions/structures
@@ -266,7 +279,7 @@
        cmd->reply = "Read Only attribute";                             \
        return 1;                                                       \
 }                                                                      \
-CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_##cmdname)
+CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, CTRL_MODE_RO, verify_##cmdname)

 /*! Define a write-only attribute. Declares set+verify, implements read 
call-back
  *  \param[in] cmdname symbol name of the command related functions/structures
@@ -279,7 +292,7 @@
        return CTRL_CMD_ERROR;                                                  
\
 }                                                                              
\
 static int verify_##cmdname(struct ctrl_cmd *cmd, const char *val, void 
*data);        \
-CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_##cmdname)
+CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, CTRL_MODE_WO, verify_##cmdname)

 /*! Define a write-only attribute without verify. Declares set, implements 
read+verify
  *  \param[in] cmdname symbol name of the command related functions/structures
@@ -295,6 +308,6 @@
 {                                                                              
\
        return 0;                                                               
\
 }                                                                              
\
-CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, verify_##cmdname)
+CTRL_CMD_DEFINE_STRUCT(cmdname, cmdstr, CTRL_MODE_WO, verify_##cmdname)

 struct gsm_network;
diff --git a/src/ctrl/control_cmd.c b/src/ctrl/control_cmd.c
index 33496bd..31144ee 100644
--- a/src/ctrl/control_cmd.c
+++ b/src/ctrl/control_cmd.c
@@ -58,6 +58,32 @@
 /* Functions from libosmocom */
 extern vector cmd_make_descvec(const char *string, const char *descstr);

+/*! Iterate over all control commands; call \a handle_ctrl_cmd call-back for 
each.
+ *  \param[in] handle_ctrl_cmd Call-back to be called for each control 
command; aborts if rc < 0
+ *  \param[in] node CTRL node type from which to iterate
+ *  \param[in] data Opaque data passed through to \a handle_ctrl_cmd function
+ *  \returns 0 if all \a handle_ctrl_cmd calls successful; negative on error */
+int ctrl_cmds_for_each(int (*handle_ctrl_cmd)(struct ctrl_cmd_element *, void 
*),
+                          enum ctrl_node_type node, void *data)
+{
+       int rc = 0;
+       int index;
+       struct ctrl_cmd_element *cmd_el;
+       vector cmds_vec;
+
+       if ((cmds_vec = vector_lookup_ensure(ctrl_node_vec, node))) {
+               for (index = 0; index < vector_active(cmds_vec); index++) {
+                       if ((cmd_el = vector_slot(cmds_vec, index))) {
+                               rc = handle_ctrl_cmd(cmd_el, data);
+                               if (rc < 0)
+                                       return rc;
+                       }
+               }
+       }
+
+       return rc;
+}
+
 /* Get the ctrl_cmd_element that matches this command */
 static struct ctrl_cmd_element *ctrl_cmd_get_element_match(vector vline, 
vector node)
 {
@@ -143,6 +169,8 @@
                ret = cmd_el->get(command, data);
                goto out;
        }
+
+
 out:
        if (ret == CTRL_CMD_REPLY) {
                if (command->type == CTRL_TYPE_SET) {
diff --git a/src/ctrl/control_vty.c b/src/ctrl/control_vty.c
index ef98889..c0a1ebb 100644
--- a/src/ctrl/control_vty.c
+++ b/src/ctrl/control_vty.c
@@ -26,8 +26,12 @@
 #include <stdlib.h>
 #include <osmocom/core/talloc.h>
 #include <osmocom/ctrl/control_vty.h>
+#include <osmocom/ctrl/control_cmd.h>
 #include <osmocom/vty/command.h>

+/* containing version info */
+extern struct host host;
+
 static void *ctrl_vty_ctx = NULL;
 static const char *ctrl_vty_bind_addr = NULL;

@@ -66,6 +70,75 @@
        return CMD_SUCCESS;
 }

+static int asciidoc_handle_ctrl_cmd(struct ctrl_cmd_element *cmd_el, void 
*sctx_)
+{
+       struct vty *vty = sctx_;
+       struct ctrl_cmd_struct *cmd_desc = &cmd_el->strcmd;
+       char *name = osmo_asciidoc_escape(cmd_el->name);
+       char *word, *mode;
+       int i;
+
+       /* | name | commands | mode | */
+       vty_out(vty, "| %s |", name);
+       for (i=0; i < cmd_desc->nr_commands; i++){
+               word = osmo_asciidoc_escape(cmd_desc->command[i]);
+               vty_out(vty, " %s", word);
+               talloc_free(word);
+       }
+
+       switch(cmd_el->mode){
+               case CTRL_MODE_RO:
+                       mode = "RO";
+                       break;
+               case CTRL_MODE_WO:
+                       mode = "WO";
+                       break;
+               case CTRL_MODE_RW:
+                       mode = "RW";
+                       break;
+        default:
+            mode = "";
+       }
+       vty_out(vty, " | %s |%s", mode, VTY_NEWLINE);
+
+       talloc_free(name);
+
+       return 0;
+}
+
+DEFUN(show_ctrl_asciidoc_table,
+               show_ctrl_asciidoc_table_cmd,
+"show asciidoc ctrl",
+SHOW_STR "Asciidoc generation\n" "Generate table of all registered ctrl 
configurations\n")
+{
+vty_out(vty, "// autogenerated by show asciidoc crtl%s", VTY_NEWLINE);
+vty_out(vty, "These configurations and their description based on %s %s 
(%s).%s%s",
+host.app_info->name,
+host.app_info->version,
+host.app_info->name ? host.app_info->name : "", VTY_NEWLINE, VTY_NEWLINE);
+/* 2x VTY_NEWLINE are intentional otherwise it would interpret the first table 
header
+ * as usual text*/
+vty_out(vty, "=== Root commands%s%s", VTY_NEWLINE, VTY_NEWLINE);
+vty_out(vty, "// generating tables for CTRL_NODE_ROOT%s", VTY_NEWLINE);
+ctrl_cmds_for_each(asciidoc_handle_ctrl_cmd, CTRL_NODE_ROOT, vty);
+vty_out(vty, "=== BTS commands (net.btsN.) %s%s", VTY_NEWLINE, VTY_NEWLINE);
+vty_out(vty, "// generating tables for CTRL_NODE_BTS%s", VTY_NEWLINE);
+ctrl_cmds_for_each(asciidoc_handle_ctrl_cmd, CTRL_NODE_BTS, vty);
+vty_out(vty, "=== TRX commands (net.btsN.trxM.) %s%s", VTY_NEWLINE, 
VTY_NEWLINE);
+vty_out(vty, "// generating tables for CTRL_NODE_TRX%s", VTY_NEWLINE);
+ctrl_cmds_for_each(asciidoc_handle_ctrl_cmd, CTRL_NODE_TRX, vty);
+vty_out(vty, "=== Timeslot commands (net.btsN.trxM.tsI.) %s%s", VTY_NEWLINE, 
VTY_NEWLINE);
+vty_out(vty, "// generating tables for CTRL_NODE_TS%s", VTY_NEWLINE);
+ctrl_cmds_for_each(asciidoc_handle_ctrl_cmd, CTRL_NODE_TS, vty);
+vty_out(vty, "=== FSM commands (description) %s%s", VTY_NEWLINE, VTY_NEWLINE);
+vty_out(vty, "// generating tables for CTRL_NODE_FSM%s", VTY_NEWLINE);
+ctrl_cmds_for_each(asciidoc_handle_ctrl_cmd, CTRL_NODE_FSM, vty);
+vty_out(vty, "=== FSM commands (instance) %s%s", VTY_NEWLINE, VTY_NEWLINE);
+vty_out(vty, "// generating tables for CTRL_NODE_FSM_INST%s", VTY_NEWLINE);
+ctrl_cmds_for_each(asciidoc_handle_ctrl_cmd, CTRL_NODE_FSM_INST, vty);
+return CMD_SUCCESS;
+}
+
 static int config_write_ctrl(struct vty *vty)
 {
        /* So far there's only one element. Omit the entire section if the bind
@@ -86,6 +159,7 @@
        install_node(&ctrl_node, config_write_ctrl);

        install_element(L_CTRL_NODE, &cfg_ctrl_bind_addr_cmd);
+       install_element_ve(&show_ctrl_asciidoc_table_cmd);
        return 0;
 }


--
To view, visit https://gerrit.osmocom.org/12814
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I16f59bfca72a7dd9c268bc64499b26d82a2115d2
Gerrit-Change-Number: 12814
Gerrit-PatchSet: 1
Gerrit-Owner: Omar Ramadan <omar.ramada...@gmail.com>

Reply via email to