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.
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);
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 <number> for seconds or <number>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);
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 <delay> in seconds or <delay>ms in milliseconds",
NULL, cmd_store_env_value, "tx-interval"),
NEWLINE, "Set LLDP transmit delay",
NULL, cmd_txdelay, NULL);
}
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;
}
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",
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;
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);
}
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",
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);
}
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);
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;
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) {
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",
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:
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;
*/
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 */
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 */