--- src/client/client.h | 2 + src/client/display.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/client/show.c | 44 ++++++++++++++++++++++++++++++++++++++ src/lib/atoms/port.c | 7 ++++++ src/lib/lldpctl.h | 1 5 files changed, 112 insertions(+), 1 deletion(-) --- a/src/client/client.h +++ b/src/client/client.h @@ -115,6 +115,8 @@ char* totag(const char *); #define DISPLAY_DETAILS 3 void display_interfaces(lldpctl_conn_t *, struct writer *, struct cmd_env *, int, int); +void display_local_interfaces(lldpctl_conn_t *, struct writer *, + struct cmd_env *, int, int); void display_interface(lldpctl_conn_t *, struct writer *, int, lldpctl_atom_t *, lldpctl_atom_t *, int, int); void display_local_chassis(lldpctl_conn_t *, struct writer *, --- a/src/client/display.c +++ b/src/client/display.c @@ -344,12 +344,23 @@ display_port(struct writer *w, lldpctl_a tag_datatag(w, "descr", "PortDescr", lldpctl_atom_get_str(port, lldpctl_k_port_descr)); + tag_datatag(w, "ttl", "Ttl", + lldpctl_atom_get_str(port, lldpctl_k_port_ttl)); + /* Dot3 */ if (details == DISPLAY_DETAILS) { tag_datatag(w, "mfs", "MFS", lldpctl_atom_get_str(port, lldpctl_k_port_dot3_mfs)); - tag_datatag(w, "aggregation", "Port is aggregated. PortAggregID", + + long int lag_id = lldpctl_atom_get_int(port, + lldpctl_k_port_dot3_aggregid); + tag_start(w, "link-aggregation", "LinkAgg"); + tag_attr(w, "supported", "supported", "yes"); + tag_attr(w, "enabled", "enabled", + (lag_id > 0)?"yes":"no"); + tag_datatag(w, "aggregation", "PortAggregID", lldpctl_atom_get_str(port, lldpctl_k_port_dot3_aggregid)); + tag_end(w); long int autoneg_support, autoneg_enabled, autoneg_advertised; autoneg_support = lldpctl_atom_get_int(port, @@ -663,6 +674,52 @@ display_interfaces(lldpctl_conn_t *conn, lldpctl_atom_dec_ref(port); } tag_end(w); +} + +/** + * Display information about local interfaces. + * + * @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_local_interfaces(lldpctl_conn_t *conn, struct writer *w, + struct cmd_env *env, + int hidden, int details) +{ + lldpctl_atom_t *iface; + int protocol = LLDPD_MODE_MAX; + const char *proto_str; + + /* user might have specified protocol to filter display results */ + proto_str = cmdenv_get(env, "protocol"); + + if (proto_str) { + log_debug("display", "filter protocol: %s ", proto_str); + + protocol = 0; + for (lldpctl_map_t *protocol_map = + lldpctl_key_get_map(lldpctl_k_port_protocol); + protocol_map->string; + protocol_map++) { + if (!strcasecmp(proto_str, protocol_map->string)) { + protocol = protocol_map->value; + break; + } + } + } + + tag_start(w, "lldp", "LLDP interfaces"); + while ((iface = cmd_iterate_on_interfaces(conn, env))) { + lldpctl_atom_t *port; + port = lldpctl_get_port(iface); + display_interface(conn, w, hidden, iface, port, details, protocol); + lldpctl_atom_dec_ref(port); + } + tag_end(w); } void --- a/src/client/show.c +++ b/src/client/show.c @@ -48,6 +48,35 @@ cmd_show_neighbors(struct lldpctl_conn_t } /** + * Show interfaces. + * + * The environment will contain the following keys: + * - C{ports} list of ports we want to restrict showing. + * - C{hidden} if we should show hidden ports. + * - C{summary} if we want to show only a summary + * - C{detailed} for a detailed overview + */ +static int +cmd_show_interfaces(struct lldpctl_conn_t *conn, struct writer *w, + struct cmd_env *env, void *arg) +{ + log_debug("lldpctl", "show interfaces data (%s) %s hidden interfaces", + cmdenv_get(env, "summary")?"summary": + cmdenv_get(env, "detailed")?"detailed": + "normal", cmdenv_get(env, "hidden")?"with":"without"); + if (cmdenv_get(env, "ports")) + log_debug("lldpctl", "restrict to the following ports: %s", + cmdenv_get(env, "ports")); + + display_local_interfaces(conn, w, env, !!cmdenv_get(env, "hidden"), + cmdenv_get(env, "summary")?DISPLAY_BRIEF: + cmdenv_get(env, "detailed")?DISPLAY_DETAILS: + DISPLAY_NORMAL); + + return 1; +} + +/** * Show chassis. * * The environment will contain the following keys: @@ -269,6 +298,12 @@ register_commands_show(struct cmd_node * "Show neighbors data", NULL, NULL, NULL); + struct cmd_node *interfaces = commands_new( + show, + "interfaces", + "Show interfaces data", + NULL, NULL, NULL); + struct cmd_node *chassis = commands_new( show, "chassis", @@ -289,6 +324,15 @@ register_commands_show(struct cmd_node * register_common_commands(neighbors, 1); + /* Interfaces data */ + commands_new(interfaces, + NEWLINE, + "Show interfaces data", + NULL, cmd_show_interfaces, NULL); + + cmd_restrict_ports(interfaces); + register_common_commands(interfaces, 0); + /* Chassis data */ commands_new(chassis, NEWLINE, --- a/src/lib/atoms/port.c +++ b/src/lib/atoms/port.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "lldpctl.h" #include "../log.h" @@ -544,6 +545,7 @@ _lldpctl_atom_get_int_port(lldpctl_atom_ (struct _lldpctl_atom_port_t *)atom; struct lldpd_port *port = p->port; struct lldpd_hardware *hardware = p->hardware; + time_t now = time(NULL); /* Local port only */ if (hardware != NULL) { @@ -585,6 +587,11 @@ _lldpctl_atom_get_int_port(lldpctl_atom_ return port->p_id_subtype; case lldpctl_k_port_hidden: return port->p_hidden_in; + case lldpctl_k_port_ttl: + if (port->p_lastupdate > 0) + return (port->p_chassis->c_ttl - (now - port->p_lastupdate)); + else + return port->p_chassis->c_ttl; #ifdef ENABLE_DOT3 case lldpctl_k_port_dot3_mfs: if (port->p_mfs > 0) --- a/src/lib/lldpctl.h +++ b/src/lib/lldpctl.h @@ -674,6 +674,7 @@ typedef enum { lldpctl_k_port_hidden, /**< `(I)` Is this port hidden (or should it be displayed?)? */ lldpctl_k_port_status, /**< `(IS,WO)` Operational status of this (local) port */ lldpctl_k_port_chassis, /**< `(A)` Chassis associated to the port */ + lldpctl_k_port_ttl, /**< `(I)` The port ttl. */ lldpctl_k_port_dot3_mfs = 1300, /**< `(I)` MFS */ lldpctl_k_port_dot3_aggregid, /**< `(I)` Port aggregation ID */