From 47287a61f1abf381adf022cd4e08f3099b043986 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Fri, 31 Aug 2012 18:43:05 +0200 Subject: [PATCH] lldpctl: add the possibility to force lldpd to start the main loop now --- NEWS | 3 +++ man/lldpctl.8 | 10 ++++++++-- src/client/client.h | 2 +- src/client/lldpctl.c | 28 +++++++++++++++++++++++----- src/ctl.h | 1 + src/daemon/client.c | 29 +++++++++++++++++++++++++++++ src/daemon/event.c | 8 +++++++- src/daemon/lldpd.c | 1 + src/daemon/lldpd.h | 1 + src/lib/atom-private.c | 33 ++++++++++++++++++++++++++++++++- src/lib/lldpctl.h | 2 +- src/lib/private.h | 2 ++ 12 files changed, 109 insertions(+), 11 deletions(-) diff --git a/NEWS b/NEWS index f83d4044..e572b2c5 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,9 @@ lldpd (0.6.1) which contains all the exported functions. + Make lldpctl uses liblldpctl.so. + Add a "watch" option to lldpctl to monitor neighbor changes. + + Add the possibility to display the current configuration of + lldpd with lldpctl. Also add the possibility to reset the + current transmit delay. lldpd (0.6) * Features: diff --git a/man/lldpctl.8 b/man/lldpctl.8 index efd305e1..9fb2d9a3 100644 --- a/man/lldpctl.8 +++ b/man/lldpctl.8 @@ -21,7 +21,7 @@ .Nd control LLDP daemon .Sh SYNOPSIS .Nm -.Op Fl advwC +.Op Fl advwCN .Op Fl L Ar location .Op Fl P Ar policy .Op Fl O Ar poe @@ -53,7 +53,13 @@ Display all remote ports, including those hidden by the smart filter. .It Fl w Monitor neighbor changes. Each changed neighbor will be displayed. .It Fl C -Display global configuration of lldpd daemon. +Display global configuration of +.Em lldpd +daemon. +.It Fl N +Make +.Em lldpd +update its information and send new LLDP PDU on all interfaces. .It Fl f Ar format Choose the output format. Currently .Em plain , diff --git a/src/client/client.h b/src/client/client.h index 0e0e4ba8..5ffa1b76 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -26,7 +26,7 @@ #include "../lldp-const.h" #include "writer.h" -#define LLDPCTL_ARGS "hdvaf:L:P:O:o:wC" +#define LLDPCTL_ARGS "hdvaf:L:P:O:o:wCN" /* display.c */ void display_interfaces(lldpctl_conn_t *, struct writer *, int, int, char **); diff --git a/src/client/lldpctl.c b/src/client/lldpctl.c index f1e13d2e..e0236fc8 100644 --- a/src/client/lldpctl.c +++ b/src/client/lldpctl.c @@ -50,6 +50,7 @@ usage(void) fprintf(stderr, "-a Display all remote ports, including hidden ones.\n"); fprintf(stderr, "-w Watch for changes.\n"); fprintf(stderr, "-C Display global configuration of lldpd.\n"); + fprintf(stderr, "-N Make lldpd transmit LLDP PDU now.\n"); fprintf(stderr, "-f format Choose output format (plain, keyvalue or xml).\n"); fprintf(stderr, "-L location Enable the transmission of LLDP-MED location TLV for the\n"); fprintf(stderr, " given interfaces. Can be repeated to enable the transmission\n"); @@ -115,7 +116,7 @@ main(int argc, char *argv[]) { int ch, debug = 1; char *fmt = "plain"; - int action = 0, hidden = 0, watch = 0, configuration = 0; + int action = 0, hidden = 0, watch = 0, configuration = 0, now = 0; lldpctl_conn_t *conn; struct cbargs args; @@ -150,6 +151,9 @@ main(int argc, char *argv[]) case 'C': configuration = 1; break; + case 'N': + now = 1; + break; default: usage(); } @@ -190,10 +194,7 @@ main(int argc, char *argv[]) args.w = txt_init(stdout); } - if (!watch && !action && !configuration) { - display_interfaces(conn, args.w, - hidden, argc, argv); - } else if (action) { + if (action) { modify_interfaces(conn, argc, argv, optind); } else if (watch) { if (lldpctl_watch(conn) < 0) { @@ -203,6 +204,23 @@ main(int argc, char *argv[]) } } else if (configuration) { display_configuration(conn, args.w); + } else if (now) { + lldpctl_atom_t *config = lldpctl_get_configuration(conn); + if (config == NULL) { + LLOG_WARNX("unable to get configuration from lldpd. %s", + lldpctl_last_strerror(conn)); + } else { + if (lldpctl_atom_set_int(config, + lldpctl_k_config_delay, -1) == NULL) { + LLOG_WARNX("unable to ask lldpd for immediate retransmission. %s", + lldpctl_last_strerror(conn)); + } else + LLOG_INFO("immediate retransmission requested successfuly"); + lldpctl_atom_dec_ref(config); + } + } else { + display_interfaces(conn, args.w, + hidden, argc, argv); } args.w->finish(args.w); } while (watch); diff --git a/src/ctl.h b/src/ctl.h index 5b47efd1..0bf8fee9 100644 --- a/src/ctl.h +++ b/src/ctl.h @@ -26,6 +26,7 @@ enum hmsg_type { NONE, GET_CONFIG, /* Get global configuration */ + SET_CONFIG, /* Change global configuration */ GET_INTERFACES, /* Get list of interfaces */ GET_INTERFACE, /* Get all information related to an interface */ SET_PORT, /* Set port-related information (location, power, policy) */ diff --git a/src/daemon/client.c b/src/daemon/client.c index d060d2fe..0ca28a73 100644 --- a/src/daemon/client.c +++ b/src/daemon/client.c @@ -40,6 +40,34 @@ client_handle_get_configuration(struct lldpd *cfg, enum hmsg_type *type, return output_len; } +/* Change the global configuration */ +static int +client_handle_set_configuration(struct lldpd *cfg, enum hmsg_type *type, + void *input, int input_len, void **output, int *subscribed) +{ + struct lldpd_config *config; + + /* Get the proposed configuration. */ + if (marshal_unserialize(lldpd_config, input, input_len, &config) <= 0) { + *type = NONE; + return 0; + } + + /* What needs to be done? Currently, we only support setting the + * transmit delay. */ + if (config->c_delay > 0) { + cfg->g_config.c_delay = config->c_delay; + } + if (config->c_delay < 0) { + LLOG_DEBUG("client asked for immediate retransmission"); + levent_send_now(cfg); + } + + lldpd_config_cleanup(config); + + return 0; +} + /* Return the list of interfaces. Input: nothing. Output: list of interface names (lldpd_interface_list) @@ -233,6 +261,7 @@ struct client_handle { static struct client_handle client_handles[] = { { NONE, client_handle_none }, { GET_CONFIG, client_handle_get_configuration }, + { SET_CONFIG, client_handle_set_configuration }, { GET_INTERFACES, client_handle_get_interfaces }, { GET_INTERFACE, client_handle_get_interface }, { SET_PORT, client_handle_set_port }, diff --git a/src/daemon/event.c b/src/daemon/event.c index 4fb60169..76d3c9d7 100644 --- a/src/daemon/event.c +++ b/src/daemon/event.c @@ -398,6 +398,12 @@ levent_update_and_send(evutil_socket_t fd, short what, void *arg) event_add(cfg->g_main_loop, &tv); } +void +levent_send_now(struct lldpd *cfg) +{ + event_active(cfg->g_main_loop, EV_TIMEOUT, 1); +} + static void levent_init(struct lldpd *cfg) { @@ -430,7 +436,7 @@ levent_init(struct lldpd *cfg) levent_update_and_send, cfg))) fatalx("unable to setup main timer"); - event_active(cfg->g_main_loop, EV_TIMEOUT, 1); + levent_send_now(cfg); /* Setup unix socket */ TAILQ_INIT(&lldpd_clients); diff --git a/src/daemon/lldpd.c b/src/daemon/lldpd.c index 2dcf9867..ee002fd9 100644 --- a/src/daemon/lldpd.c +++ b/src/daemon/lldpd.c @@ -847,6 +847,7 @@ lldpd_loop(struct lldpd *cfg) 4. Send packets 5. Update events */ + LLOG_DEBUG("start new loop"); LOCAL_CHASSIS(cfg)->c_cap_enabled = 0; lldpd_update_localports(cfg); lldpd_cleanup(cfg); diff --git a/src/daemon/lldpd.h b/src/daemon/lldpd.h index 82ab1c94..042f59b5 100644 --- a/src/daemon/lldpd.h +++ b/src/daemon/lldpd.h @@ -146,6 +146,7 @@ void levent_hardware_init(struct lldpd_hardware *); void levent_hardware_add_fd(struct lldpd_hardware *, int); void levent_hardware_release(struct lldpd_hardware *); void levent_ctl_notify(char *, int, struct lldpd_port *); +void levent_send_now(struct lldpd *); /* lldp.c */ int lldp_send(PROTO_SEND_SIG); diff --git a/src/lib/atom-private.c b/src/lib/atom-private.c index 4959db33..0b083431 100644 --- a/src/lib/atom-private.c +++ b/src/lib/atom-private.c @@ -356,6 +356,36 @@ _lldpctl_atom_get_int_config(lldpctl_atom_t *atom, lldpctl_key_t key) } } +static lldpctl_atom_t* +_lldpctl_atom_set_int_config(lldpctl_atom_t *atom, lldpctl_key_t key, + long int value) +{ + int rc; + struct _lldpctl_atom_config_t *c = + (struct _lldpctl_atom_config_t *)atom; + struct lldpd_config config; + memset(&config, 0, sizeof(struct lldpd_config)); + + switch (key) { + case lldpctl_k_config_delay: + config.c_delay = value; + if (value > 0) c->config->c_delay = value; + break; + default: + SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST); + return NULL; + } + + rc = _lldpctl_do_something(atom->conn, + CONN_STATE_SET_CONFIG_SEND, CONN_STATE_SET_CONFIG_RECV, + NULL, + SET_CONFIG, &config, &MARSHAL_INFO(lldpd_config), + NULL, NULL); + if (rc == 0) return atom; + return NULL; + return atom; +} + static int _lldpctl_atom_new_interfaces_list(lldpctl_atom_t *atom, va_list ap) { @@ -2346,7 +2376,8 @@ struct atom_builder builders[] = { .init = _lldpctl_atom_new_config, .free = _lldpctl_atom_free_config, .get_str = _lldpctl_atom_get_str_config, - .get_int = _lldpctl_atom_get_int_config }, + .get_int = _lldpctl_atom_get_int_config, + .set_int = _lldpctl_atom_set_int_config }, { atom_interfaces_list, sizeof(struct _lldpctl_atom_interfaces_list_t), .init = _lldpctl_atom_new_interfaces_list, .free = _lldpctl_atom_free_interfaces_list, diff --git a/src/lib/lldpctl.h b/src/lib/lldpctl.h index 7d5e43f7..994d486a 100644 --- a/src/lib/lldpctl.h +++ b/src/lib/lldpctl.h @@ -447,7 +447,7 @@ lldpctl_atom_t *lldpctl_get_port(lldpctl_atom_t *port); * first write to a (A,W), then to a (A,WO)). */ typedef enum { - lldpctl_k_config_delay, /* (I) Transmit delay */ + lldpctl_k_config_delay, /* (I,WO) Transmit delay. When set to -1, it is meant to transmit now. */ lldpctl_k_config_receiveonly, /* (I) Receive only mode */ lldpctl_k_config_mgmt_pattern, /* (S) Pattern to choose the management address */ lldpctl_k_config_iface_pattern, /* (S) Pattern of enabled interfaces */ diff --git a/src/lib/private.h b/src/lib/private.h index c06fbe9e..4308f707 100644 --- a/src/lib/private.h +++ b/src/lib/private.h @@ -44,6 +44,8 @@ struct lldpctl_conn_t { #define CONN_STATE_SET_WATCH_RECV 8 #define CONN_STATE_GET_CONFIG_SEND 9 #define CONN_STATE_GET_CONFIG_RECV 9 +#define CONN_STATE_SET_CONFIG_SEND 10 +#define CONN_STATE_SET_CONFIG_RECV 11 int state; /* Current state */ void *state_data; /* Data attached to the state. It is used to * check that we are using the same data as a -- 2.39.5