]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
client: Added support to override system capabilities
authorIgnacio Sanchez Navarro <igsanchez@github.com>
Mon, 1 Aug 2022 17:22:40 +0000 (13:22 -0400)
committerVincent Bernat <vincent@bernat.ch>
Thu, 11 Aug 2022 10:30:34 +0000 (12:30 +0200)
1) configure system capabilities enabled <capability_0,capability_1,...>

    Override system capabilities with the provided value instead of using kernel information. Several capabilities can be specified separated by commas. Only available capabilities can be enabled. Valid capabilities are:

        other
        repeater
        bridge
        wlan
        router
        telephone
        docsis
        station

    Here is an example of use:

        lldpcli configure system capabilities enabled bridge,router

2) unconfigure system capabilities enabled

    Do not override capabilities and use the kernel information. This option undoes the previous one.

Ignacio Sanchez Navarro (Ignacio.Sanchez@uws.ac.uk) - University of the West of Scotland - Supported by H2020-ICT-2020-2/101017226 6G-BRAINS

-------------------------------------------------------------------------------
Modified files

lldpd-structs.h
    - Added new attribute "c_cap_override" to "lldpd_config" struct

conf-system.c
    - Added new function "cmd_capability" for new command to override the chassis capabilities
    - Added new function "register_commands_capabilities" to registers new commands to override the chassis capabilities
    - Added call to "register_commands_capabilities" in "register_commands_configure_system"

chassis.c
    - Added new function "_lldpctl_atom_st_int_chassis" to set "int" type vars in chassis
    - Added assignation of ".set_int" function in "chassis" var build

config.c
    - Added case for "lldpctl_k_config_chassis_cap_override" to get value of "c_cap_override" in "_lldpctl_atom_get_int_config" function
    - Added case for "lldpctl_k_config_chassis_cap_override" to set value of "c_cap_override" in "_lldpctl_atom_set_int_config" function

client.c
    - Added changes check for "c_cap_override" var in "client_handle_set_configuration" function
    - Added changes check for "c_cap_enabled" var in "client_handle_set_local_chassis" function

lldpctl.h
    - Added new enum values un "lldpctl_key_t" enum : "lldpctl_k_chassis_cap_enabled" and "lldpctl_k_config_chassis_cap_override"
    - Corrected some typos in previous comments

lldpd.c
    - Added check of capabilities override before setting new values in "lldpd_update_localchassis" function
    - Added check of capabilities override before setting initial value of "c_cap_enabled" to 0 in "lldpd_loop" function
    - Added initial set of "cfg->g_config.c_cap_override" to 0 in "lldpd_main" function

interfaces.c
    - Added check of capabilities override before setting new values in "interfaces_helper_chassis" function

display.c
    - Added new line to display the status of capabilities override in "show configration" command

lldpcli.8.in
    - Added new commands and descriptions to man file

12 files changed:
NEWS
src/client/conf-system.c
src/client/display.c
src/client/lldpcli.8.in
src/daemon/client.c
src/daemon/interfaces.c
src/daemon/lldpd.c
src/lib/atoms/chassis.c
src/lib/atoms/config.c
src/lib/lldpctl.h
src/lldpd-structs.h
tests/integration/test_lldpcli.py

diff --git a/NEWS b/NEWS
index 1380b0c4aeefba2c8b8c0da20cefd2c1799cb9b8..ff529f4692473a1987c7eb0c702bfc0f6c7d9ba9 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,6 @@
 lldpd (1.0.15)
+ * Changes
+   + Add configure command to override system capabilities (#526)
  * Fix:
    + Really don't send VLANs when there are too many (#520)
    + Ignore temporary IPv6 addresses (#521)
index 9524d0dba22c45bd12b5826d09a91fee860e99f6..b91e95d39a9cbbeb58356169f63374362ea79f25 100644 (file)
@@ -227,6 +227,87 @@ cmd_hostname(struct lldpctl_conn_t *conn, struct writer *w,
        return 1;
 }
 
+static int
+cmd_capability(struct lldpctl_conn_t *conn, struct writer *w,
+    struct cmd_env *env, void *arg)
+{
+       log_debug("lldpctl", "set capabilities");
+
+       int ret = 0;
+       lldpctl_atom_t *config = lldpctl_get_configuration(conn);
+       lldpctl_atom_t *chassis = NULL;
+       if (config == NULL) {
+               log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
+                   lldpctl_last_strerror(conn));
+               goto cmd_capability_end;
+       }
+
+       if (!strcmp(arg, "configure")) {
+
+               const char *s = cmdenv_get(env, "capabilities");
+               if (s) {
+                       chassis = lldpctl_get_local_chassis(conn);
+                       if (chassis == NULL) {
+                               log_warnx("lldpctl", "unable to get local chassis from lldpd. %s",
+                                   lldpctl_last_strerror(conn));
+                               goto cmd_capability_end;
+                       }
+                       u_int16_t value = 0;
+                       const char delim[] = ",";
+                       char *s_copy = strdup(s);
+                       char *token = strtok(s_copy, delim);
+                       while (token != NULL) {
+                               if (!strcmp(token, "other")) {
+                                       value |= LLDP_CAP_OTHER;
+                               } else if (!strcmp(token, "repeater")) {
+                                       value |= LLDP_CAP_REPEATER;
+                               } else if (!strcmp(token, "bridge")) {
+                                       value |= LLDP_CAP_BRIDGE;
+                               } else if (!strcmp(token, "wlan")) {
+                                       value |= LLDP_CAP_WLAN;
+                               } else if (!strcmp(token, "router")) {
+                                       value |= LLDP_CAP_ROUTER;
+                               } else if (!strcmp(token, "telephone")) {
+                                       value |= LLDP_CAP_TELEPHONE;
+                               } else if (!strcmp(token, "docsis")) {
+                                       value |= LLDP_CAP_DOCSIS;
+                               } else if (!strcmp(token, "station")) {
+                                       value |= LLDP_CAP_STATION;
+                               } else {
+                                       log_warnx("lldpctl", "capability %s not found", token);
+                               }
+                               token = strtok(NULL, delim);
+                       }
+                       free(s_copy);
+
+                       if (lldpctl_atom_set_int(chassis, lldpctl_k_chassis_cap_enabled, value) == NULL) {
+                               log_warnx("lldpctl", "unable to set system capabilities. %s",
+                                   lldpctl_last_strerror(conn));
+                               goto cmd_capability_end;
+                       }
+                       if (lldpctl_atom_set_int(config, lldpctl_k_config_chassis_cap_override, 1) == NULL) {
+                               log_warnx("lldpctl", "unable to set system capabilities override. %s",
+                                   lldpctl_last_strerror(conn));
+                               goto cmd_capability_end;
+                       }
+                       log_debug("lldpctl", "system capabilities set to new value %d",
+                           value);
+               }
+       } else {
+               if (lldpctl_atom_set_int(config, lldpctl_k_config_chassis_cap_override, 0) == NULL) {
+                       log_warnx("lldpctl", "unable to set system capabilities to not override. %s",
+                           lldpctl_last_strerror(conn));
+                       goto cmd_capability_end;
+               }
+       }
+
+       ret = 1;
+ cmd_capability_end:
+       lldpctl_atom_dec_ref(chassis);
+       lldpctl_atom_dec_ref(config);
+       return ret;
+}
+
 static int
 cmd_update_descriptions(struct lldpctl_conn_t *conn, struct writer *w,
     struct cmd_env *env, void *arg)
@@ -376,6 +457,38 @@ register_commands_srcmac_type(struct cmd_node *configure)
        }
 }
 
+static void
+register_commands_capabilities(struct cmd_node *configure, struct cmd_node *unconfigure)
+{
+       struct cmd_node *configure_capability = commands_new(
+           configure,
+           "capabilities", "Capabilities configuration",
+           cmd_check_no_env, NULL, "ports");
+       struct cmd_node *unconfigure_capability = commands_new(
+           unconfigure,
+           "capabilities", "Capabilities configuration",
+           cmd_check_no_env, NULL, "ports");
+
+       /* Override */
+       commands_new(
+           commands_new(
+           commands_new(configure_capability,
+           "enabled", "Override capabilities",
+           NULL, NULL, NULL),
+           NULL, " Set of capabilities separated by commas",
+           NULL, cmd_store_env_value, "capabilities"),
+           NEWLINE, "Override capabilities",
+           NULL, cmd_capability, "configure");
+
+       /* Do not override */
+       commands_new(
+           commands_new(unconfigure_capability,
+           "enabled", "Do not override capabilities",
+           NULL, NULL, NULL),
+           NEWLINE, "Do not override capabilities",
+           NULL, cmd_capability, "unconfigure");
+}
+
 /**
  * Register `configure system` commands.
  *
@@ -562,6 +675,7 @@ register_commands_configure_system(struct cmd_node *configure,
                NEWLINE, "Don't enable promiscuous mode on managed interfaces",
                NULL, cmd_iface_promisc, NULL);
 
+       register_commands_capabilities(configure_system, unconfigure_system);
        register_commands_srcmac_type(configure_system);
 }
 
index b21ff028d7647a6253c76e63db8343094f42baeb..8465d2db120d6564cc25d41b66650b363e4bb6c8 100644 (file)
@@ -992,6 +992,9 @@ display_configuration(lldpctl_conn_t *conn, struct writer *w)
            N(lldpctl_atom_get_str(configuration, lldpctl_k_config_platform)));
        tag_datatag(w, "hostname", "Override system name with",
            N(lldpctl_atom_get_str(configuration, lldpctl_k_config_hostname)));
+       tag_datatag(w, "capabilities", "Override system capabilities",
+           lldpctl_atom_get_int(configuration, lldpctl_k_config_chassis_cap_override)?
+           "yes":"no");
        tag_datatag(w, "advertise-version", "Advertise version",
            lldpctl_atom_get_int(configuration, lldpctl_k_config_advertise_version)?
            "yes":"no");
index dd458d16e22cf1801baee66d28522495008a422c..1dc75a0e52cc829ed2993c47513af3e337d72dac 100644 (file)
@@ -267,6 +267,34 @@ Do not override platform description and use the kernel name. This
 option undoes the previous one.
 .Ed
 
+.Cd configure
+.Cd system capabilities enabled Ar capabilities
+.Bd -ragged -offset XXXXXX
+Override system capabilities with the provided value instead of using
+kernel information. Several capabilities can be specified separated by
+commas. Only available capabilities can be enabled. Valid capabilities are:
+.Bl -tag -width "XXX." -compact -offset XX
+.It Sy other
+.It Sy repeater
+.It Sy bridge
+.It Sy wlan
+.It Sy router
+.It Sy telephone
+.It Sy docsis
+.It Sy station
+.El
+Here is an example of use:
+.D1 configure system capabilities enabled bridge,router
+.Pp
+.Ed
+
+.Cd unconfigure
+.Cd system capabilities enabled
+.Bd -ragged -offset XXXXXX
+Do not override capabilities and use the kernel information. This option
+undoes the previous one.
+.Ed
+
 .Cd configure
 .Cd system interface pattern Ar pattern
 .Bd -ragged -offset XXXXXX
index 56e57590148a0e8f5799e8167df5ba028ff8f50a..654dbefd42733b727b7f8c26d276ef7708f1a8c8 100644 (file)
@@ -18,9 +18,7 @@
 #include "lldpd.h"
 #include "trace.h"
 
-#ifdef ENABLE_LLDPMED
 #include <sys/utsname.h>
-#endif
 
 static ssize_t
 client_handle_none(struct lldpd *cfg, enum hmsg_type *type,
@@ -207,6 +205,12 @@ client_handle_set_configuration(struct lldpd *cfg, enum hmsg_type *type,
                cfg->g_config.c_cap_advertise = config->c_cap_advertise;
                levent_update_now(cfg);
        }
+       if (CHANGED(c_cap_override)) {
+               log_debug("rpc", "%s chassis capabilities override",
+                   config->c_cap_override?"enable":"disable");
+               cfg->g_config.c_cap_override = config->c_cap_override;
+               levent_update_now(cfg);
+       }
        if (CHANGED(c_mgmt_advertise)) {
                log_debug("rpc", "%s management addresses advertisement",
                    config->c_mgmt_advertise?"enable":"disable");
@@ -277,9 +281,8 @@ client_handle_get_interfaces(struct lldpd *cfg, enum hmsg_type *type,
        return output_len;
 }
 
-#ifdef ENABLE_LLDPMED
 /**
- * Set local chassis inventory info
+ * Set local chassis info
  * Input: chassis object
  * Output: updated chassis object
  */
@@ -289,7 +292,9 @@ client_handle_set_local_chassis(struct lldpd *cfg, enum hmsg_type *type,
 {
        struct lldpd_chassis *chassis = NULL;
        struct lldpd_chassis *local_chassis = NULL;
+#ifdef ENABLE_LLDPMED
        struct utsname un;
+#endif
 
        log_debug("rpc", "client request a change in chassis configuration");
        if (lldpd_chassis_unserialize(input, input_len, &chassis) <= 0) {
@@ -299,6 +304,7 @@ client_handle_set_local_chassis(struct lldpd *cfg, enum hmsg_type *type,
 
        local_chassis = LOCAL_CHASSIS(cfg);
 
+#ifdef ENABLE_LLDPMED
        free(local_chassis->c_med_hw);
        local_chassis->c_med_hw = (!chassis->c_med_hw) ? dmi_hw() : strdup(chassis->c_med_hw);
 
@@ -332,7 +338,14 @@ client_handle_set_local_chassis(struct lldpd *cfg, enum hmsg_type *type,
 
        free(local_chassis->c_med_asset);
        local_chassis->c_med_asset = (!chassis->c_med_asset) ? dmi_asset() : strdup(chassis->c_med_asset);
+#endif
+
+       if(chassis->c_cap_enabled != local_chassis->c_cap_enabled){
+               local_chassis->c_cap_enabled = chassis->c_cap_enabled;
+               log_debug("rpc", "change capabilities enabled to: %d", local_chassis->c_cap_enabled);
+       }
 
+#ifdef ENABLE_LLDPMED
        log_debug("rpc", "change hardware-revision to: %s", local_chassis->c_med_hw);
        log_debug("rpc", "change software-revision to: %s", local_chassis->c_med_sw);
        log_debug("rpc", "change firmware-revision to: %s", local_chassis->c_med_fw);
@@ -340,6 +353,7 @@ client_handle_set_local_chassis(struct lldpd *cfg, enum hmsg_type *type,
        log_debug("rpc", "change manufacturer to: %s", local_chassis->c_med_manuf);
        log_debug("rpc", "change model to: %s", local_chassis->c_med_model);
        log_debug("rpc", "change asset to: %s", local_chassis->c_med_asset);
+#endif
 
        lldpd_chassis_cleanup(chassis, 1);
 
@@ -351,7 +365,6 @@ client_handle_set_local_chassis(struct lldpd *cfg, enum hmsg_type *type,
 
        return output_len;
 }
-#endif /* ENABLE_LLDPMED */
 
 /* Return the local chassis.
    Input:  nothing.
@@ -652,9 +665,7 @@ static struct client_handle client_handles[] = {
        { GET_INTERFACES,       "Get interfaces",    client_handle_get_interfaces },
        { GET_INTERFACE,        "Get interface",     client_handle_get_interface },
        { GET_DEFAULT_PORT,     "Get default port",  client_handle_get_default_port },
-#ifdef ENABLE_LLDPMED
        { SET_CHASSIS,          "Set local chassis", client_handle_set_local_chassis },
-#endif
        { GET_CHASSIS,          "Get local chassis", client_handle_get_local_chassis },
        { SET_PORT,             "Set port",          client_handle_set_port },
        { SUBSCRIBE,            "Subscribe",         client_handle_subscribe },
index 4cd600dfc5854053bbfbc294fea4a71990ba7e0e..a59b6afd0642470ca35d8a25499f9727885a88e2 100644 (file)
@@ -351,17 +351,19 @@ interfaces_helper_chassis(struct lldpd *cfg,
        struct lldpd_hardware *hardware;
        char *name = NULL;
 
-       LOCAL_CHASSIS(cfg)->c_cap_enabled &=
-                           ~(LLDP_CAP_BRIDGE | LLDP_CAP_WLAN | LLDP_CAP_STATION);
-       TAILQ_FOREACH(iface, interfaces, next) {
-               if (iface->type & IFACE_BRIDGE_T)
-                       LOCAL_CHASSIS(cfg)->c_cap_enabled |= LLDP_CAP_BRIDGE;
-               if (iface->type & IFACE_WIRELESS_T)
-                       LOCAL_CHASSIS(cfg)->c_cap_enabled |= LLDP_CAP_WLAN;
+       if (!cfg->g_config.c_cap_override) {
+               LOCAL_CHASSIS(cfg)->c_cap_enabled &=
+                   ~(LLDP_CAP_BRIDGE | LLDP_CAP_WLAN | LLDP_CAP_STATION);
+               TAILQ_FOREACH(iface, interfaces, next) {
+                       if (iface->type & IFACE_BRIDGE_T)
+                               LOCAL_CHASSIS(cfg)->c_cap_enabled |= LLDP_CAP_BRIDGE;
+                       if (iface->type & IFACE_WIRELESS_T)
+                               LOCAL_CHASSIS(cfg)->c_cap_enabled |= LLDP_CAP_WLAN;
+               }
+               if ((LOCAL_CHASSIS(cfg)->c_cap_available & LLDP_CAP_STATION) &&
+                   (LOCAL_CHASSIS(cfg)->c_cap_enabled == 0))
+                       LOCAL_CHASSIS(cfg)->c_cap_enabled = LLDP_CAP_STATION;
        }
-       if ((LOCAL_CHASSIS(cfg)->c_cap_available & LLDP_CAP_STATION) &&
-               (LOCAL_CHASSIS(cfg)->c_cap_enabled == 0))
-           LOCAL_CHASSIS(cfg)->c_cap_enabled = LLDP_CAP_STATION;
 
        /* Do not modify the chassis if it's already set to a MAC address or if
         * it's set to a local address equal to the user-provided
index 6d8853474ffe8c17cdfabe1202c4bfe9246bbbc2..2d53fbada575237469f1573f3d6126e253e4fe21 100644 (file)
@@ -1241,23 +1241,25 @@ lldpd_update_localchassis(struct lldpd *cfg)
        if (cfg->g_config.c_platform == NULL)
                cfg->g_config.c_platform = strdup(un.sysname);
 
-       /* Check routing */
-       if (lldpd_routing_enabled(cfg)) {
-               log_debug("localchassis", "routing is enabled, enable router capability");
-               LOCAL_CHASSIS(cfg)->c_cap_enabled |= LLDP_CAP_ROUTER;
-       } else
-               LOCAL_CHASSIS(cfg)->c_cap_enabled &= ~LLDP_CAP_ROUTER;
+       if (!cfg->g_config.c_cap_override) {
+               /* Check routing */
+               if (lldpd_routing_enabled(cfg)) {
+                       log_debug("localchassis", "routing is enabled, enable router capability");
+                       LOCAL_CHASSIS(cfg)->c_cap_enabled |= LLDP_CAP_ROUTER;
+               } else
+                       LOCAL_CHASSIS(cfg)->c_cap_enabled &= ~LLDP_CAP_ROUTER;
 
 #ifdef ENABLE_LLDPMED
-       if (LOCAL_CHASSIS(cfg)->c_cap_available & LLDP_CAP_TELEPHONE)
-               LOCAL_CHASSIS(cfg)->c_cap_enabled |= LLDP_CAP_TELEPHONE;
-       lldpd_med(cfg, &un);
+               if (LOCAL_CHASSIS(cfg)->c_cap_available & LLDP_CAP_TELEPHONE)
+                       LOCAL_CHASSIS(cfg)->c_cap_enabled |= LLDP_CAP_TELEPHONE;
+               lldpd_med(cfg, &un);
 #endif
-       if ((LOCAL_CHASSIS(cfg)->c_cap_available & LLDP_CAP_STATION) &&
-               (LOCAL_CHASSIS(cfg)->c_cap_enabled == 0))
-               LOCAL_CHASSIS(cfg)->c_cap_enabled = LLDP_CAP_STATION;
-       else if (LOCAL_CHASSIS(cfg)->c_cap_enabled != LLDP_CAP_STATION)
-               LOCAL_CHASSIS(cfg)->c_cap_enabled &= ~LLDP_CAP_STATION;
+               if ((LOCAL_CHASSIS(cfg)->c_cap_available & LLDP_CAP_STATION) &&
+                   (LOCAL_CHASSIS(cfg)->c_cap_enabled == 0))
+                       LOCAL_CHASSIS(cfg)->c_cap_enabled = LLDP_CAP_STATION;
+               else if (LOCAL_CHASSIS(cfg)->c_cap_enabled != LLDP_CAP_STATION)
+                       LOCAL_CHASSIS(cfg)->c_cap_enabled &= ~LLDP_CAP_STATION;
+       }
 
        /* Set chassis ID if needed. This is only done if chassis ID
           has not been set previously (with the MAC address of an
@@ -1307,7 +1309,8 @@ lldpd_loop(struct lldpd *cfg)
           2. Update local chassis information
        */
        log_debug("loop", "start new loop");
-       LOCAL_CHASSIS(cfg)->c_cap_enabled = 0;
+       if(!cfg->g_config.c_cap_override)
+               LOCAL_CHASSIS(cfg)->c_cap_enabled = 0;
        /* Information for local ports is triggered even when it is possible to
         * update them on some other event because we want to refresh them if we
         * missed something. */
@@ -1941,6 +1944,7 @@ lldpd_main(int argc, char *argv[], char *envp[])
                calloc(1, sizeof(struct lldpd_chassis))) == NULL)
                fatal("localchassis", NULL);
        cfg->g_config.c_cap_advertise = 1;
+       cfg->g_config.c_cap_override = 0;
        lchassis->c_cap_available = LLDP_CAP_BRIDGE | LLDP_CAP_WLAN |
            LLDP_CAP_ROUTER | LLDP_CAP_STATION;
        cfg->g_config.c_mgmt_advertise = 1;
index 1d2ed27bcd94a3254d394fd4b064299070362aa3..4ef72a511f5e6c0334ce90c455641603b4831073 100644 (file)
@@ -234,6 +234,42 @@ _lldpctl_atom_get_str_chassis(lldpctl_atom_t *atom, lldpctl_key_t key)
        }
 }
 
+static lldpctl_atom_t*
+_lldpctl_atom_set_int_chassis(lldpctl_atom_t *atom, lldpctl_key_t key,
+    long int value)
+{
+       int rc;
+       char *canary = NULL;
+       struct _lldpctl_atom_chassis_t *c =
+           (struct _lldpctl_atom_chassis_t *) atom;
+       struct lldpd_chassis chassis;
+       memcpy(&chassis, c->chassis, sizeof(struct lldpd_chassis));
+
+       switch (key) {
+       case lldpctl_k_chassis_cap_enabled:
+               chassis.c_cap_enabled = c->chassis->c_cap_enabled = chassis.c_cap_available & value;
+               break;
+       default:
+               SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
+               return NULL;
+       }
+
+       if (asprintf(&canary, "%d%ld", key, value) == -1) {
+               SET_ERROR(atom->conn, LLDPCTL_ERR_NOMEM);
+               return NULL;
+       }
+
+       rc = _lldpctl_do_something(atom->conn,
+           CONN_STATE_SET_CHASSIS_SEND, CONN_STATE_SET_CHASSIS_RECV,
+           canary,
+           SET_CHASSIS, &chassis, &MARSHAL_INFO(lldpd_chassis),
+           NULL, NULL);
+
+       free(canary);
+       if (rc == 0) return atom;
+       return NULL;
+}
+
 static long int
 _lldpctl_atom_get_int_chassis(lldpctl_atom_t *atom, lldpctl_key_t key)
 {
@@ -287,6 +323,7 @@ static struct atom_builder chassis =
          .get  = _lldpctl_atom_get_atom_chassis,
          .get_str = _lldpctl_atom_get_str_chassis,
          .get_int = _lldpctl_atom_get_int_chassis,
+         .set_int = _lldpctl_atom_set_int_chassis,
          .get_buffer = _lldpctl_atom_get_buf_chassis,
 #ifdef ENABLE_LLDPMED
          .set_str = _lldpctl_atom_set_str_chassis,
index ebe8a36a630164c87b510928d977ec4f0203bd5b..675e6f6205b2874cf1add7fa487f4a82f9e39d6f 100644 (file)
@@ -234,6 +234,8 @@ _lldpctl_atom_get_int_config(lldpctl_atom_t *atom, lldpctl_key_t key)
                return c->config->c_promisc;
        case lldpctl_k_config_chassis_cap_advertise:
                return c->config->c_cap_advertise;
+       case lldpctl_k_config_chassis_cap_override:
+               return c->config->c_cap_override;
        case lldpctl_k_config_chassis_mgmt_advertise:
                return c->config->c_mgmt_advertise;
 #ifdef ENABLE_LLDPMED
@@ -285,6 +287,9 @@ _lldpctl_atom_set_int_config(lldpctl_atom_t *atom, lldpctl_key_t key,
        case lldpctl_k_config_chassis_cap_advertise:
                config.c_cap_advertise = c->config->c_cap_advertise = value;
                break;
+       case lldpctl_k_config_chassis_cap_override:
+               config.c_cap_override = c->config->c_cap_override = value;
+               break;
        case lldpctl_k_config_chassis_mgmt_advertise:
                config.c_mgmt_advertise = c->config->c_mgmt_advertise = value;
                break;
index 56b3bf489648d59a6e5c6537f79934b9c0df7ffc..6774ed1eec140899de88b151c345b12118c5fc6e 100644 (file)
@@ -718,6 +718,7 @@ typedef enum {
        lldpctl_k_config_cid_string,    /**< `(S,WON)` User defined string for the chassis ID */
        lldpctl_k_config_perm_iface_pattern, /**< `(S,WON)` Pattern of permanent interfaces */
        lldpctl_k_config_tx_interval_ms, /**< `(I,WO)` Transmit interval in milliseconds. Set to -1 to transmit now. */
+       lldpctl_k_config_chassis_cap_override, /**< `(I,WO)` Override chassis capabilities */
 
        lldpctl_k_interface_name = 1000, /**< `(S)` The interface name. */
 
@@ -793,13 +794,13 @@ typedef enum {
        lldpctl_k_chassis_id,         /**< `(BS)` The ID of this chassis. */
        lldpctl_k_chassis_name,       /**< `(S)` The name of this chassis. */
        lldpctl_k_chassis_descr,      /**< `(S)` The description of this chassis. */
-       lldpctl_k_chassis_cap_available, /**< `(I)` Available capabalities (see `LLDP_CAP_*`) */
+       lldpctl_k_chassis_cap_available, /**< `(I)` Available capabilities (see `LLDP_CAP_*`) */
        lldpctl_k_chassis_cap_enabled,   /**< `(I)` Enabled capabilities (see `LLDP_CAP_*`) */
        lldpctl_k_chassis_mgmt,          /**< `(AL)` List of management addresses */
        lldpctl_k_chassis_ttl,           /**< Deprecated */
 
        lldpctl_k_chassis_med_type = 1900, /**< `(IS)` Chassis MED type. See `LLDP_MED_CLASS_*` */
-       lldpctl_k_chassis_med_cap,  /**< `(I)` Available MED capabilitied. See `LLDP_MED_CAP_*` */
+       lldpctl_k_chassis_med_cap,  /**< `(I)` Available MED capabilities. See `LLDP_MED_CAP_*` */
        lldpctl_k_chassis_med_inventory_hw, /**< `(S,W)` LLDP MED inventory "Hardware Revision" */
        lldpctl_k_chassis_med_inventory_sw, /**< `(S,W)` LLDP MED inventory "Software Revision" */
        lldpctl_k_chassis_med_inventory_fw, /**< `(S,W)` LLDP MED inventory "Firmware Revision" */
index e98a05513379e059d0041bb9cdbf8d04fd2e1c87..5a7d4538a6f075a148dc7fc7a6d5adff996ecfe0 100644 (file)
@@ -411,6 +411,7 @@ struct lldpd_config {
        int c_set_ifdescr;       /* Set interface description */
        int c_promisc;           /* Interfaces should be in promiscuous mode */
        int c_cap_advertise;     /* Chassis capabilities advertisement */
+       int c_cap_override;      /* Override chassis capabilities enabled */
        int c_mgmt_advertise;    /* Management addresses advertisement */
 
 #ifdef ENABLE_LLDPMED
index 6cef96a1a6ca6e5469c807cbcf51182c73ff365e..098d2d265e3ed852c3923f950c9a3ad4b07327eb 100644 (file)
@@ -625,3 +625,44 @@ def test_config_change(lldpd1, lldpcli, namespaces, command, name, expected):
         assert result.returncode == 0
         out = lldpcli("-f", "keyvalue", "show", "configuration")
         assert out['configuration.config.{}'.format(name)] == str(expected)
+
+
+def test_config_capabilities(lldpd1, lldpcli, namespaces):
+    with namespaces(1):
+        out = lldpcli("-f", "keyvalue", "show", "chassis")
+
+        # Save values to check after unconfigure
+        bridge = out['local-chassis.chassis.Bridge.enabled']
+        router = out['local-chassis.chassis.Router.enabled']
+        wlan = out['local-chassis.chassis.Wlan.enabled']
+        station = out['local-chassis.chassis.Station.enabled']
+
+        # Configure only bridge capability
+        lldpcli("configure", "system", "capabilities", "enabled", "bridge")
+
+        # Check only bridge capability on
+        out = lldpcli("-f", "keyvalue", "show", "chassis")
+        assert out['local-chassis.chassis.Bridge.enabled'] == "on"
+        assert out['local-chassis.chassis.Router.enabled'] == "off"
+        assert out['local-chassis.chassis.Wlan.enabled'] == "off"
+        assert out['local-chassis.chassis.Station.enabled'] == "off"
+
+        # Configure router and wlan capabilities.
+        lldpcli("configure", "system", "capabilities", "enabled", "router,wlan")
+
+        # This shoud enable only router and wlan and set to off the bridge capability again
+        out = lldpcli("-f", "keyvalue", "show", "chassis")
+        assert out['local-chassis.chassis.Bridge.enabled'] == "off"
+        assert out['local-chassis.chassis.Router.enabled'] == "on"
+        assert out['local-chassis.chassis.Wlan.enabled'] == "on"
+        assert out['local-chassis.chassis.Station.enabled'] == "off"
+
+        # Unconfigure system capabilities and use again the kernel information to enable capabilities
+        lldpcli("unconfigure", "system", "capabilities", "enabled")
+
+        # Check if the capabilities have the same values as before start the configurations
+        out = lldpcli("-f", "keyvalue", "show", "chassis")
+        assert out['local-chassis.chassis.Bridge.enabled'] == bridge
+        assert out['local-chassis.chassis.Router.enabled'] == router
+        assert out['local-chassis.chassis.Wlan.enabled'] == wlan
+        assert out['local-chassis.chassis.Station.enabled'] == station