From: roopa Date: Tue, 16 Apr 2013 18:54:16 +0000 (-0700) Subject: lldpcli: Add support to display lldp stats X-Git-Tag: 0.7.2~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=78356144eeabc2481774674d8572d857a1414bae;p=thirdparty%2Flldpd.git lldpcli: Add support to display lldp stats This patch adds a new lldpcli command and required server code to display per interface lldp stats Sample output: #lldpcli show statistics ports eth0 --------------------------------------------------- LLDP statistics: --------------------------------------------------- Interface: eth0 tx_cnt: 2 rx_cnt: 2 rx_discarded_cnt: 0 rx_unrecognized_cnt: 0 ageout_cnt: insert_cnt: delete_cnt: 0 --------------------------------------------------- Signed-off-by: Roopa Prabhu --- diff --git a/src/client/client.h b/src/client/client.h index 459e4049..c58db51e 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -111,6 +111,12 @@ void display_interfaces(lldpctl_conn_t *, struct writer *, void display_interface(lldpctl_conn_t *, struct writer *, int, lldpctl_atom_t *, lldpctl_atom_t *, int); void display_configuration(lldpctl_conn_t *, struct writer *); +void display_interfaces_stats(lldpctl_conn_t *, struct writer *, + struct cmd_env *); +void display_interface_stats(lldpctl_conn_t *, struct writer *, + lldpctl_atom_t *); + + /* show.c */ void register_commands_show(struct cmd_node *); diff --git a/src/client/display.c b/src/client/display.c index f2c7dd2e..11108e32 100644 --- a/src/client/display.c +++ b/src/client/display.c @@ -566,6 +566,85 @@ display_interfaces(lldpctl_conn_t *conn, struct writer *w, tag_end(w); } +void +display_interface_stats(lldpctl_conn_t *conn, struct writer *w, + lldpctl_atom_t *port) +{ + char buf[20]; + + tag_start(w, "interface", "Interface"); + tag_attr(w, "name", "", + lldpctl_atom_get_str(port, lldpctl_k_port_name)); + + tag_start(w, "tx", "tx_cnt"); + memset(buf, 0, sizeof(buf)); + snprintf(buf, sizeof(buf), "%lu", lldpctl_atom_get_int(port, lldpctl_k_tx_cnt)); + tag_attr(w, "tx", "", buf); + tag_end(w); + + tag_start(w, "rx", "rx_cnt"); + memset(buf, 0, sizeof(buf)); + snprintf(buf, sizeof(buf), "%lu", lldpctl_atom_get_int(port, lldpctl_k_rx_cnt)); + tag_attr(w, "rx", "", buf); + tag_end(w); + + tag_start(w, "rx_discarded_cnt", "rx_discarded_cnt"); + memset(buf, 0, sizeof(buf)); + snprintf(buf, sizeof(buf), "%lu", lldpctl_atom_get_int(port, lldpctl_k_rx_discarded_cnt)); + tag_attr(w, "rx_discarded_cnt", "", buf); + tag_end(w); + + tag_start(w, "rx_unrecognized_cnt", "rx_unrecognized_cnt"); + memset(buf, 0, sizeof(buf)); + snprintf(buf, sizeof(buf), "%lu", lldpctl_atom_get_int(port, lldpctl_k_rx_unrecognized_cnt)); + tag_attr(w, "rx_unrecognized_cnt", "", buf); + tag_end(w); + + tag_start(w, "ageout_cnt", "ageout_cnt"); + snprintf(buf, sizeof(buf), "%lu", lldpctl_atom_get_int(port, lldpctl_k_ageout_cnt)); + memset(buf, 0, sizeof(buf)); + tag_attr(w, "ageout_cnt", "", buf); + tag_end(w); + + tag_start(w, "insert_cnt", "insert_cnt"); + snprintf(buf, sizeof(buf), "%lu", lldpctl_atom_get_int(port, lldpctl_k_insert_cnt)); + memset(buf, 0, sizeof(buf)); + tag_attr(w, "insert_cnt", "", buf); + tag_end(w); + + tag_start(w, "delete_cnt", "delete_cnt"); + memset(buf, 0, sizeof(buf)); + snprintf(buf, sizeof(buf), "%lu", lldpctl_atom_get_int(port, lldpctl_k_delete_cnt)); + tag_attr(w, "delete_cnt", "", buf); + tag_end(w); + + tag_end(w); +} + +/** + * Display interface stats + * + * @param conn Connection to lldpd. + * @param w Writer. + * @param hidden Whatever to show hidden ports. + * @param env Environment from which we may find the list of ports. + * @param details Level of details we need (DISPLAY_*). + */ +void +display_interfaces_stats(lldpctl_conn_t *conn, struct writer *w, + struct cmd_env *env) +{ + lldpctl_atom_t *iface; + + tag_start(w, "lldp", "LLDP statistics"); + while ((iface = cmd_iterate_on_interfaces(conn, env))) { + lldpctl_atom_t *port; + port = lldpctl_get_port(iface); + display_interface_stats(conn, w, port); + } + tag_end(w); +} + static const char * N(const char *str) { if (str == NULL || strlen(str) == 0) return "(none)"; diff --git a/src/client/show.c b/src/client/show.c index 581c7134..22f5f365 100644 --- a/src/client/show.c +++ b/src/client/show.c @@ -46,6 +46,26 @@ cmd_show_neighbors(struct lldpctl_conn_t *conn, struct writer *w, return 1; } +/** + * Show stats. + * + * The environment will contain the following keys: + * - C{ports} list of ports we want to restrict showing. + */ +static int +cmd_show_interface_stats(struct lldpctl_conn_t *conn, struct writer *w, + struct cmd_env *env, void *arg) +{ + log_debug("lldpctl", "show stats data"); + if (cmdenv_get(env, "ports")) + log_debug("lldpctl", "restrict to the following ports: %s", + cmdenv_get(env, "ports")); + + display_interfaces_stats(conn, w, env); + + return 1; +} + static int cmd_check_no_detailed_nor_summary(struct cmd_env *env, void *arg) { @@ -156,6 +176,23 @@ register_common_commands(struct cmd_node *root) cmd_restrict_ports(root); } +/** + * Register sub command ports + */ +void +register_ports_command(struct cmd_node *root) +{ + /* Some specific port */ + commands_new( + commands_new(root, + "ports", + "Restrict to some ports", + cmd_check_no_env, NULL, "ports"), + NULL, + "Restrict to neighbors on those ports (comma-separated list)", + NULL, cmd_store_env_value_and_pop2, "ports"); +} + /** * Register subcommands to `show` * @@ -175,6 +212,12 @@ register_commands_show(struct cmd_node *root) "Show neighbors data", NULL, NULL, NULL); + struct cmd_node *stats = commands_new( + show, + "statistics", + "Show statistics", + NULL, NULL, NULL); + /* Neighbors data */ commands_new(neighbors, NEWLINE, @@ -183,6 +226,14 @@ register_commands_show(struct cmd_node *root) register_common_commands(neighbors); + /* Stats data */ + commands_new(stats, + NEWLINE, + "Show stats data", + NULL, cmd_show_interface_stats, NULL); + + register_ports_command(stats); + /* Register "show configuration" and "show running-configuration" */ commands_new( commands_new(show, diff --git a/src/lib/atom-private.c b/src/lib/atom-private.c index a754896b..b732ce83 100644 --- a/src/lib/atom-private.c +++ b/src/lib/atom-private.c @@ -883,6 +883,20 @@ _lldpctl_atom_get_int_port(lldpctl_atom_t *atom, lldpctl_key_t key) switch (key) { case lldpctl_k_port_index: return hardware->h_ifindex; + case lldpctl_k_tx_cnt: + return hardware->h_tx_cnt; + case lldpctl_k_rx_cnt: + return hardware->h_rx_cnt; + case lldpctl_k_rx_discarded_cnt: + return hardware->h_rx_discarded_cnt; + case lldpctl_k_rx_unrecognized_cnt: + return hardware->h_rx_unrecognized_cnt; + case lldpctl_k_ageout_cnt: + return hardware->h_ageout_cnt; + case lldpctl_k_insert_cnt: + return hardware->h_insert_cnt; + case lldpctl_k_delete_cnt: + return hardware->h_delete_cnt; default: break; } } diff --git a/src/lib/lldpctl.h b/src/lib/lldpctl.h index 70f60b0b..3dbff3b0 100644 --- a/src/lib/lldpctl.h +++ b/src/lib/lldpctl.h @@ -696,6 +696,14 @@ typedef enum { lldpctl_k_med_power_val, /**< `(I,W)` LLDP MED power value */ lldpctl_k_mgmt_ip, /**< `(S)` IP address */ + + lldpctl_k_tx_cnt, /**< `(I)` tx cnt. Only works for a local port. */ + lldpctl_k_rx_cnt, /**< `(I)` rx cnt. Only works for a local port. */ + lldpctl_k_rx_discarded_cnt, /**< `(I)` discarded cnt. Only works for a local port. */ + lldpctl_k_rx_unrecognized_cnt, /**< `(I)` unrecognized cnt. Only works for a local port. */ + lldpctl_k_ageout_cnt, /**< `(I)` ageout cnt. Only works for a local port. */ + lldpctl_k_insert_cnt, /**< `(I)` insert cnt. Only works for a local port. */ + lldpctl_k_delete_cnt, /**< `(I)` delete cnt. Only works for a local port. */ } lldpctl_key_t; /** diff --git a/src/lib/private.h b/src/lib/private.h index 077f228c..274caca0 100644 --- a/src/lib/private.h +++ b/src/lib/private.h @@ -86,6 +86,7 @@ typedef enum { atom_config, atom_interfaces_list, atom_interface, + atom_hardware, atom_ports_list, atom_port, atom_mgmts_list, @@ -110,6 +111,7 @@ typedef enum { atom_med_caelement, atom_med_power, #endif + atom_interface_stats, } atom_t; void *_lldpctl_alloc_in_atom(lldpctl_atom_t *, size_t); @@ -163,6 +165,18 @@ struct _lldpctl_atom_interface_t { char *name; }; +struct _lldpctl_atom_hardware_t { + lldpctl_atom_t base; + char *name; + u_int64_t h_tx_cnt; + u_int64_t h_rx_cnt; + u_int64_t h_rx_discarded_cnt; + u_int64_t h_rx_unrecognized_cnt; + u_int64_t h_ageout_cnt; + u_int64_t h_insert_cnt; + u_int64_t h_delete_cnt; +}; + struct _lldpctl_atom_port_t { lldpctl_atom_t base; struct lldpd_hardware *hardware; /* Local port only */