]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
lldpctl: add the possibility to force lldpd to start the main loop now
authorVincent Bernat <bernat@luffy.cx>
Fri, 31 Aug 2012 16:43:05 +0000 (18:43 +0200)
committerVincent Bernat <bernat@luffy.cx>
Fri, 31 Aug 2012 16:43:05 +0000 (18:43 +0200)
12 files changed:
NEWS
man/lldpctl.8
src/client/client.h
src/client/lldpctl.c
src/ctl.h
src/daemon/client.c
src/daemon/event.c
src/daemon/lldpd.c
src/daemon/lldpd.h
src/lib/atom-private.c
src/lib/lldpctl.h
src/lib/private.h

diff --git a/NEWS b/NEWS
index f83d404495a8616a082e389ec4d9c320dbc0e1eb..e572b2c51b7960181645f67582e8604e73f97991 100644 (file)
--- 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:
index efd305e1edb924f67a94c98ee6181fc0f406155b..9fb2d9a3c912667bc83bbc8c830a3df4e7bec611 100644 (file)
@@ -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 ,
index 0e0e4ba8b2facb4e8254552c1379c3e64826e65f..5ffa1b76d0526e34a68754fd8e1db5c474239d5d 100644 (file)
@@ -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 **);
index f1e13d2e93820334653f2a06aa1b2579356a4ccf..e0236fc8b9ccf071a1eaaafe7d847d3f1258afb6 100644 (file)
@@ -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);
index 5b47efd1cbfe2c661858c7e4ba51d1d08188ff50..0bf8fee954aa030ebfd12e3e23f7a87680a303e9 100644 (file)
--- 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) */
index d060d2fe7e73b8c5489f2351b85c0676afc8a908..0ca28a73d014aa974ea147586883067f1e1702c5 100644 (file)
@@ -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 },
index 4fb6016958a59dc6b1a92c9e8212c237bcfeff33..76d3c9d79cd0d16f8003380b16526b00fa2a6293 100644 (file)
@@ -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);
index 2dcf9867b1c526fe924e0a75664802ea8e4bcb65..ee002fd9f88c28b313bd27f5cd7cc224e5a1b927 100644 (file)
@@ -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);
index 82ab1c94958f66cea316f7970326809adfde880d..042f59b50edefac314062d0766f91d2fd7a720f0 100644 (file)
@@ -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);
index 4959db33e820b76fcff799c260a433ce00393d56..0b0834311e28fb3bc5d7d23c7533900186285813 100644 (file)
@@ -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,
index 7d5e43f77e2857bab553d7619226928626057893..994d486a22a4a34a5d91bccbf4968d48637b58ae 100644 (file)
@@ -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 */
index c06fbe9e0d629b33b216775e894563c23332369b..4308f7079c2b3f5a14f0f5804853355a1eecad25 100644 (file)
@@ -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