From 74f55c2e029da5211642dd886856eac6d3301cd7 Mon Sep 17 00:00:00 2001 From: Jean-Pierre Tosoni Date: Wed, 15 Jan 2020 18:56:08 +0100 Subject: [PATCH] Allow configuring tx-interval in milliseconds This is a prerequisite for TTDP support. Usage: add "ms" suffix to the delay value to force interpretation as a milliseconds value: lldpcli configure lldp tx-interval 200ms When computing a TTL (TTL = tx-interval * tx-hold), the result is rounded up to the next second, as LLDP frames need a value in seconds. A new tx-interval-ms item is added to the json output. The old tx-interval is kept in seconds (rounded up) for compatibility. --- src/client/conf-lldp.c | 26 +++++++++++++++++++++++--- src/client/display.c | 8 ++++++-- src/daemon/agent.c | 4 ++-- src/daemon/client.c | 4 +++- src/daemon/event.c | 14 ++++++++++---- src/daemon/lldpd.c | 3 ++- src/daemon/protocols/edp.c | 1 + src/daemon/protocols/sonmp.c | 1 + src/lib/atoms/config.c | 8 +++++++- src/lib/lldpctl.h | 1 + src/lldpd-structs.h | 2 +- 11 files changed, 57 insertions(+), 15 deletions(-) diff --git a/src/client/conf-lldp.c b/src/client/conf-lldp.c index 8523f3cc..f82f2ec7 100644 --- a/src/client/conf-lldp.c +++ b/src/client/conf-lldp.c @@ -26,6 +26,11 @@ static int cmd_txdelay(struct lldpctl_conn_t *conn, struct writer *w, struct cmd_env *env, void *arg) { + const char *interval; + char interval_ms[8]; /* less than 2.5 hours */ + lldpctl_key_t key; + int arglen; + log_debug("lldpctl", "set transmit delay"); lldpctl_atom_t *config = lldpctl_get_configuration(conn); @@ -34,8 +39,23 @@ cmd_txdelay(struct lldpctl_conn_t *conn, struct writer *w, lldpctl_last_strerror(conn)); return 0; } - if (lldpctl_atom_set_str(config, - lldpctl_k_config_tx_interval, cmdenv_get(env, "tx-interval")) == NULL) { + interval = cmdenv_get(env, "tx-interval"); + key = lldpctl_k_config_tx_interval; + /* interval is either for seconds or ms for milliseconds */ + if (interval) { + arglen = strlen(interval); + /* room for "ms" in interval, room for interval in interval_ms */ + if (arglen >= 2 && arglen-2 < sizeof(interval_ms) && + strcmp("ms", interval+arglen-2) == 0) { + /* remove "ms" suffix */ + memcpy(interval_ms, interval, arglen-2); + interval_ms[arglen-2] = '\0'; + /* substitute key and value */ + key = lldpctl_k_config_tx_interval_ms; + interval = interval_ms; + } + } + if (lldpctl_atom_set_str(config, key, interval) == NULL) { log_warnx("lldpctl", "unable to set transmit delay. %s", lldpctl_last_strerror(conn)); lldpctl_atom_dec_ref(config); @@ -521,7 +541,7 @@ register_commands_configure_lldp(struct cmd_node *configure, commands_new(configure_lldp, "tx-interval", "Set LLDP transmit delay", cmd_check_no_env, NULL, "ports"), - NULL, "LLDP transmit delay in seconds", + NULL, "LLDP transmit in seconds or ms in milliseconds", NULL, cmd_store_env_value, "tx-interval"), NEWLINE, "Set LLDP transmit delay", NULL, cmd_txdelay, NULL); diff --git a/src/client/display.c b/src/client/display.c index 396478ef..faaa8b15 100644 --- a/src/client/display.c +++ b/src/client/display.c @@ -553,9 +553,11 @@ display_local_ttl(struct writer *w, lldpctl_conn_t *conn, int details) } tx_hold = lldpctl_atom_get_int(configuration, lldpctl_k_config_tx_hold); - tx_interval = lldpctl_atom_get_int(configuration, lldpctl_k_config_tx_interval); + tx_interval = lldpctl_atom_get_int(configuration, lldpctl_k_config_tx_interval_ms); - if (asprintf(&ttl, "%lu", tx_hold*tx_interval) == -1) { + tx_interval = (tx_interval * tx_hold + 999) / 1000; + + if (asprintf(&ttl, "%lu", tx_interval) == -1) { log_warnx("lldpctl", "not enough memory to build TTL."); goto end; } @@ -949,6 +951,8 @@ display_configuration(lldpctl_conn_t *conn, struct writer *w) tag_datatag(w, "tx-delay", "Transmit delay", lldpctl_atom_get_str(configuration, lldpctl_k_config_tx_interval)); + tag_datatag(w, "tx-delay-ms", "Transmit delay in milliseconds", + lldpctl_atom_get_str(configuration, lldpctl_k_config_tx_interval_ms)); tag_datatag(w, "tx-hold", "Transmit hold", lldpctl_atom_get_str(configuration, lldpctl_k_config_tx_hold)); tag_datatag(w, "max-neighbors", "Maximum number of neighbors", diff --git a/src/daemon/agent.c b/src/daemon/agent.c index cd33c78e..39560c26 100644 --- a/src/daemon/agent.c +++ b/src/daemon/agent.c @@ -639,10 +639,10 @@ agent_h_scalars(struct variable *vp, oid *name, size_t *length, switch (vp->magic) { case LLDP_SNMP_TXINTERVAL: - long_ret = scfg->g_config.c_tx_interval; + long_ret = (scfg->g_config.c_tx_interval+999) / 1000; return (u_char *)&long_ret; case LLDP_SNMP_TXMULTIPLIER: - long_ret = scfg->g_config.c_ttl / scfg->g_config.c_tx_interval; + long_ret = scfg->g_config.c_tx_hold; return (u_char *)&long_ret; case LLDP_SNMP_REINITDELAY: long_ret = 1; diff --git a/src/daemon/client.c b/src/daemon/client.c index a95de9c1..c5aa1cee 100644 --- a/src/daemon/client.c +++ b/src/daemon/client.c @@ -72,11 +72,12 @@ client_handle_set_configuration(struct lldpd *cfg, enum hmsg_type *type, if (config->c_tx_interval < 0) { log_debug("rpc", "client asked for immediate retransmission"); } else { - log_debug("rpc", "client change transmit interval to %d", + log_debug("rpc", "client change transmit interval to %d ms", config->c_tx_interval); cfg->g_config.c_tx_interval = config->c_tx_interval; cfg->g_config.c_ttl = cfg->g_config.c_tx_interval * cfg->g_config.c_tx_hold; + cfg->g_config.c_ttl = (cfg->g_config.c_ttl + 999) / 1000; } levent_send_now(cfg); } @@ -86,6 +87,7 @@ client_handle_set_configuration(struct lldpd *cfg, enum hmsg_type *type, cfg->g_config.c_tx_hold = config->c_tx_hold; cfg->g_config.c_ttl = cfg->g_config.c_tx_interval * cfg->g_config.c_tx_hold; + cfg->g_config.c_ttl = (cfg->g_config.c_ttl + 999) / 1000; } if (CHANGED(c_max_neighbors) && config->c_max_neighbors > 0) { log_debug("rpc", "client change maximum neighbors to %d", diff --git a/src/daemon/event.c b/src/daemon/event.c index c42bc3fa..c9bf04ab 100644 --- a/src/daemon/event.c +++ b/src/daemon/event.c @@ -476,11 +476,15 @@ static void levent_update_and_send(evutil_socket_t fd, short what, void *arg) { struct lldpd *cfg = arg; - struct timeval tv = { cfg->g_config.c_tx_interval, 0 }; + struct timeval tv; + long interval_ms = cfg->g_config.c_tx_interval; + (void)fd; (void)what; lldpd_loop(cfg); if (cfg->g_iface_event != NULL) - tv.tv_sec *= 20; + interval_ms *= 20; + tv.tv_sec = interval_ms / 1000; + tv.tv_usec = (interval_ms % 1000) * 1000; event_add(cfg->g_main_loop, &tv); } @@ -844,10 +848,12 @@ levent_send_pdu(evutil_socket_t fd, short what, void *arg) hardware->h_tx_fast--; if (hardware->h_tx_fast > 0) - tx_interval = hardware->h_cfg->g_config.c_tx_fast_interval; + tx_interval = hardware->h_cfg->g_config.c_tx_fast_interval * 1000; #endif - struct timeval tv = { tx_interval, 0 }; + struct timeval tv; + tv.tv_sec = tx_interval / 1000; + tv.tv_usec = (tx_interval % 1000) * 1000; if (event_add(hardware->h_timer, &tv) == -1) { log_warnx("event", "unable to re-register timer event for port %s", hardware->h_ifname); diff --git a/src/daemon/lldpd.c b/src/daemon/lldpd.c index dfe71523..db4e24a5 100644 --- a/src/daemon/lldpd.c +++ b/src/daemon/lldpd.c @@ -1862,9 +1862,10 @@ lldpd_main(int argc, char *argv[], char *envp[]) if (lldpcli) cfg->g_config.c_paused = 1; cfg->g_config.c_receiveonly = receiveonly; - cfg->g_config.c_tx_interval = LLDPD_TX_INTERVAL; + cfg->g_config.c_tx_interval = LLDPD_TX_INTERVAL * 1000; cfg->g_config.c_tx_hold = LLDPD_TX_HOLD; cfg->g_config.c_ttl = cfg->g_config.c_tx_interval * cfg->g_config.c_tx_hold; + cfg->g_config.c_ttl = (cfg->g_config.c_ttl + 999) / 1000; cfg->g_config.c_max_neighbors = LLDPD_MAX_NEIGHBORS; #ifdef ENABLE_LLDPMED cfg->g_config.c_enable_fast_start = enable_fast_start; diff --git a/src/daemon/protocols/edp.c b/src/daemon/protocols/edp.c index 9cd55f6a..bda77786 100644 --- a/src/daemon/protocols/edp.c +++ b/src/daemon/protocols/edp.c @@ -308,6 +308,7 @@ edp_decode(struct lldpd *cfg, char *frame, int s, goto malformed; } port->p_ttl = cfg?cfg->g_config.c_tx_interval * cfg->g_config.c_tx_hold:0; + port->p_ttl = (port->p_ttl + 999) / 1000; chassis->c_id_subtype = LLDP_CHASSISID_SUBTYPE_LLADDR; chassis->c_id_len = ETHER_ADDR_LEN; if ((chassis->c_id = (char *)malloc(ETHER_ADDR_LEN)) == NULL) { diff --git a/src/daemon/protocols/sonmp.c b/src/daemon/protocols/sonmp.c index faa00208..d2eed157 100644 --- a/src/daemon/protocols/sonmp.c +++ b/src/daemon/protocols/sonmp.c @@ -367,6 +367,7 @@ sonmp_decode(struct lldpd *cfg, char *frame, int s, TAILQ_INSERT_TAIL(&chassis->c_mgmt, mgmt, m_entries); port->p_ttl = cfg?(cfg->g_config.c_tx_interval * cfg->g_config.c_tx_hold): LLDPD_TTL; + port->p_ttl = (port->p_ttl + 999) / 1000; port->p_id_subtype = LLDP_PORTID_SUBTYPE_LOCAL; if (asprintf(&port->p_id, "%02x-%02x-%02x", diff --git a/src/lib/atoms/config.c b/src/lib/atoms/config.c index 66374c69..f8216648 100644 --- a/src/lib/atoms/config.c +++ b/src/lib/atoms/config.c @@ -221,7 +221,9 @@ _lldpctl_atom_get_int_config(lldpctl_atom_t *atom, lldpctl_key_t key) case lldpctl_k_config_paused: return c->config->c_paused; case lldpctl_k_config_tx_interval: - return c->config->c_tx_interval; + return (c->config->c_tx_interval+999)/1000; /* s units */ + case lldpctl_k_config_tx_interval_ms: + return c->config->c_tx_interval; /* ms units */ case lldpctl_k_config_receiveonly: return c->config->c_receiveonly; case lldpctl_k_config_advertise_version: @@ -267,6 +269,10 @@ _lldpctl_atom_set_int_config(lldpctl_atom_t *atom, lldpctl_key_t key, config.c_paused = c->config->c_paused = value; break; case lldpctl_k_config_tx_interval: + config.c_tx_interval = value * 1000; + if (value > 0) c->config->c_tx_interval = value * 1000; + break; + case lldpctl_k_config_tx_interval_ms: config.c_tx_interval = value; if (value > 0) c->config->c_tx_interval = value; break; diff --git a/src/lib/lldpctl.h b/src/lib/lldpctl.h index 9d656f16..4c46a904 100644 --- a/src/lib/lldpctl.h +++ b/src/lib/lldpctl.h @@ -652,6 +652,7 @@ lldpctl_atom_t *lldpctl_get_default_port(lldpctl_conn_t *conn); */ typedef enum { lldpctl_k_config_tx_interval, /**< `(I,WO)` Transmit interval. When set to -1, it is meant to transmit now. */ + lldpctl_k_config_tx_interval_ms, /**< `(I,WO)` Transmit interval in milliseconds. Set to -1 to transmit now. */ lldpctl_k_config_receiveonly, /**< `(I)` Receive only mode */ lldpctl_k_config_mgmt_pattern, /**< `(S,WON)` Pattern to choose the management address */ lldpctl_k_config_iface_pattern, /**< `(S,WON)` Pattern of enabled interfaces */ diff --git a/src/lldpd-structs.h b/src/lldpd-structs.h index 93cde031..31daef13 100644 --- a/src/lldpd-structs.h +++ b/src/lldpd-structs.h @@ -388,7 +388,7 @@ MARSHAL_END(lldpd_port_set); struct lldpd_config { int c_paused; /* lldpd is paused */ - int c_tx_interval; /* Transmit interval */ + int c_tx_interval; /* Transmit interval (in ms) */ int c_ttl; /* TTL */ int c_smart; /* Bitmask for smart configuration (see SMART_*) */ int c_receiveonly; /* Receive only mode */ -- 2.39.5