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>