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:
.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
.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 ,
#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 **);
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");
{
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;
case 'C':
configuration = 1;
break;
+ case 'N':
+ now = 1;
+ break;
default:
usage();
}
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) {
}
} 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);
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) */
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)
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 },
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)
{
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);
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);
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);
}
}
+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)
{
.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,
* 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 */
#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