]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
lldpcli: Add support to display lldp stats
authorroopa <roopa@cumulusnetworks.com>
Tue, 16 Apr 2013 18:54:16 +0000 (11:54 -0700)
committerVincent Bernat <bernat@luffy.cx>
Tue, 16 Apr 2013 21:23:48 +0000 (23:23 +0200)
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 <roopa@cumulusnetworks.com>
src/client/client.h
src/client/display.c
src/client/show.c
src/lib/atom-private.c
src/lib/lldpctl.h
src/lib/private.h

index 459e40496b23acd453c92dd17fea3de317caf9a3..c58db51e911cd497020775e397a3e19957e46b41 100644 (file)
@@ -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 *);
index f2c7dd2eac6efc296a9456b6e0de03f19357f60e..11108e32a324e7a2caf39531cb945cfb9cda643b 100644 (file)
@@ -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)";
index 581c7134bb04a3deae12dfd2403e67d92528ac8a..22f5f365fd8b10c4f7a536c7da42957d531a088d 100644 (file)
@@ -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,
index a754896bc086d145292a7267d22825cb6f68d1aa..b732ce83f4bb66e410fa80024a65ed076924f66f 100644 (file)
@@ -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;
                }
        }
index 70f60b0b575ef9f392735f4ddeeb766720f0ecab..3dbff3b0076da87fb621b24e6cfa6d41c0f43224 100644 (file)
@@ -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;
 
 /**
index 077f228c4d2ea51b67473b3f425d624ccb75696e..274caca0f51ae65db0099e4bf564251f184703f9 100644 (file)
@@ -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 */