Skip to content

Commit

Permalink
med: Add configure inventory commands
Browse files Browse the repository at this point in the history
Default inventory information is fetched from dmi table.
Most of embedded devices do not run EFI bootloader hence dmi information
will not be available in /sys/class/dmi

- Add `configure inventory` commands
- Add `unconfigure inventory` commands
- New code is dependent on enable-lldpmed
- Add write support on lldpctl atoms
- Add support for setting inventory configuration in daemon
- Refactor `lldp_med` to assign `c_med_sw` only once.
  We have the configurability of inventory information, So
  it is not required for daemon to keep assigning `c_med_sw`
  • Loading branch information
harshalgohel authored and vincentbernat committed May 15, 2022
1 parent 12e81bd commit 8ef9c76
Show file tree
Hide file tree
Showing 12 changed files with 409 additions and 23 deletions.
2 changes: 1 addition & 1 deletion src/client/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ uninstall-local:
cd $(DESTDIR)$(sbindir) && rm -f lldpctl

lldpcli_SOURCES = client.h lldpcli.c display.c \
conf.c conf-med.c conf-dot3.c conf-power.c \
conf.c conf-med.c conf-inv.c conf-dot3.c conf-power.c \
conf-lldp.c conf-system.c \
commands.c show.c \
misc.c tokenizer.c \
Expand Down
1 change: 1 addition & 0 deletions src/client/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ void register_commands_configure(struct cmd_node *);
void register_commands_configure_system(struct cmd_node *, struct cmd_node *);
void register_commands_configure_lldp(struct cmd_node *, struct cmd_node *);
void register_commands_configure_med(struct cmd_node *, struct cmd_node *);
void register_commands_configure_inventory(struct cmd_node *, struct cmd_node *);
void register_commands_configure_dot3(struct cmd_node *);
void register_commands_medpow(struct cmd_node *);
void register_commands_dot3pow(struct cmd_node *);
Expand Down
215 changes: 215 additions & 0 deletions src/client/conf-inv.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
/* -*- mode: c; c-file-style: "openbsd" -*- */
/*
* SPDX-FileCopyrightText: 2022 Koninklijke Philips N.V.
* SPDX-License-Identifier: ISC
*/

#include <unistd.h>
#include <string.h>

#include "client.h"
#include "../log.h"

static int
cmd_inventory(struct lldpctl_conn_t *conn, struct writer *w,
struct cmd_env *env, void *arg)
{
log_debug("lldpctl", "configure inventory information");

lldpctl_atom_t *chassis = lldpctl_get_local_chassis(conn);

if (chassis == NULL) {
log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
lldpctl_last_strerror(conn));
return 0;
}

char *action = arg;
if ((!strcmp(action, "hardware-revision") &&
(lldpctl_atom_set_str(chassis,
lldpctl_k_chassis_med_inventory_hw,
cmdenv_get(env, "hardware-revision")) == NULL)) ||
(!strcmp(action, "software-revision") &&
(lldpctl_atom_set_str(chassis,
lldpctl_k_chassis_med_inventory_sw,
cmdenv_get(env, "software-revision")) == NULL)) ||
(!strcmp(action, "firmware-revision") &&
(lldpctl_atom_set_str(chassis,
lldpctl_k_chassis_med_inventory_fw,
cmdenv_get(env, "firmware-revision")) == NULL)) ||
(!strcmp(action, "serial-number") &&
(lldpctl_atom_set_str(chassis,
lldpctl_k_chassis_med_inventory_sn,
cmdenv_get(env, "serial-number")) == NULL)) ||
(!strcmp(action, "manufacturer") &&
(lldpctl_atom_set_str(chassis,
lldpctl_k_chassis_med_inventory_manuf,
cmdenv_get(env, "manufacturer")) == NULL)) ||
(!strcmp(action, "model") &&
(lldpctl_atom_set_str(chassis,
lldpctl_k_chassis_med_inventory_model,
cmdenv_get(env, "model")) == NULL)) ||
(!strcmp(action, "asset") &&
(lldpctl_atom_set_str(chassis,
lldpctl_k_chassis_med_inventory_asset,
cmdenv_get(env, "asset")) == NULL))) {
log_warnx("lldpctl", "Unable to setup inventory. %s",
lldpctl_last_strerror(conn));
lldpctl_atom_dec_ref(chassis);
return 0;
}

log_info("lldpctl", "Configuration for inventory is applied");
lldpctl_atom_dec_ref(chassis);
return 1;
}

/**
* Register `configure inventory *` commands
*
*/
static void
register_commands_inv(struct cmd_node *configure_inv, struct cmd_node *unconfigure_inv)
{
commands_new(
commands_new(
commands_new(configure_inv,
"hardware-revision", "Set hardware-revision string",
NULL, NULL, NULL),
NULL, "Inventory hardware-revision string",
NULL, cmd_store_env_value, "hardware-revision"),
NEWLINE, "Set hardware-revision string",
NULL, cmd_inventory, "hardware-revision");

commands_new(
commands_new(unconfigure_inv,
"hardware-revision", "Unset hardware-revision string",
NULL, NULL, NULL),
NEWLINE, "Unset hardware-revision string",
NULL, cmd_inventory, "hardware-revision");

commands_new(
commands_new(
commands_new(configure_inv,
"software-revision", "Set software-revision string",
NULL, NULL, NULL),
NULL, "Inventory software-revision string",
NULL, cmd_store_env_value, "software-revision"),
NEWLINE, "Set software-revision string",
NULL, cmd_inventory, "software-revision");

commands_new(
commands_new(unconfigure_inv,
"software-revision", "Unset software-revision string",
NULL, NULL, NULL),
NEWLINE, "Unset software-revision string",
NULL, cmd_inventory, "software-revision");

commands_new(
commands_new(
commands_new(configure_inv,
"firmware-revision", "Set firmware-revision string",
NULL, NULL, NULL),
NULL, "Inventory firmware-revision string",
NULL, cmd_store_env_value, "firmware-revision"),
NEWLINE, "Set firmware-revision string",
NULL, cmd_inventory, "firmware-revision");

commands_new(
commands_new(unconfigure_inv,
"firmware-revision", "Unset firmware-revision string",
NULL, NULL, NULL),
NEWLINE, "Unset firmware-revision string",
NULL, cmd_inventory, "firmware-revision");

commands_new(
commands_new(
commands_new(configure_inv,
"serial-number", "Set serial-number string",
NULL, NULL, NULL),
NULL, "Inventory serial-number string",
NULL, cmd_store_env_value, "serial-number"),
NEWLINE, "Set serial-number string",
NULL, cmd_inventory, "serial-number");

commands_new(
commands_new(unconfigure_inv,
"serial-number", "Unset serial-number string",
NULL, NULL, NULL),
NEWLINE, "Unset serial-number string",
NULL, cmd_inventory, "serial-number");

commands_new(
commands_new(
commands_new(configure_inv,
"manufacturer", "Set manufacturer string",
NULL, NULL, NULL),
NULL, "Inventory manufacturer string",
NULL, cmd_store_env_value, "manufacturer"),
NEWLINE, "Set manufacturer string",
NULL, cmd_inventory, "manufacturer");

commands_new(
commands_new(unconfigure_inv,
"manufacturer", "Unset manufacturer string",
NULL, NULL, NULL),
NEWLINE, "Unset manufacturer string",
NULL, cmd_inventory, "manufacturer");

commands_new(
commands_new(
commands_new(configure_inv,
"model", "Set model string",
NULL, NULL, NULL),
NULL, "Inventory model string",
NULL, cmd_store_env_value, "model"),
NEWLINE, "Set model string",
NULL, cmd_inventory, "model");

commands_new(
commands_new(unconfigure_inv,
"model", "Unset model string",
NULL, NULL, NULL),
NEWLINE, "Unset model string",
NULL, cmd_inventory, "model");

commands_new(
commands_new(
commands_new(configure_inv,
"asset", "Set asset string",
NULL, NULL, NULL),
NULL, "Inventory asset string",
NULL, cmd_store_env_value, "asset"),
NEWLINE, "Set asset string",
NULL, cmd_inventory, "asset");

commands_new(
commands_new(unconfigure_inv,
"asset", "Unset asset string",
NULL, NULL, NULL),
NEWLINE, "Unset asset string",
NULL, cmd_inventory, "asset");
}

/**
* Register `configure inventory *`
*
*/
void
register_commands_configure_inventory(struct cmd_node *configure, struct cmd_node *unconfigure) {
if(lldpctl_key_get_map(
lldpctl_k_med_policy_type)[0].value <= 0)
return;

struct cmd_node *configure_inv = commands_new(
configure,
"inventory", "Inventory configuration",
NULL, NULL, NULL);
struct cmd_node *unconfigure_inv = commands_new(
unconfigure,
"inventory", "Inventory configuration",
NULL, NULL, NULL);

register_commands_inv(configure_inv, unconfigure_inv);
}

1 change: 1 addition & 0 deletions src/client/conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@ register_commands_configure(struct cmd_node *root)
register_commands_configure_system(configure, unconfigure);
register_commands_configure_lldp(configure, unconfigure);
register_commands_configure_med(configure, unconfigure);
register_commands_configure_inventory(configure, unconfigure);
register_commands_configure_dot3(configure);
}
1 change: 1 addition & 0 deletions src/ctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ enum hmsg_type {
GET_CONFIG, /* Get global configuration */
SET_CONFIG, /* Change global configuration */
GET_INTERFACES, /* Get list of interfaces */
SET_CHASSIS, /* Set local chassis */
GET_CHASSIS, /* Get local chassis */
GET_INTERFACE, /* Get all information related to an interface */
GET_DEFAULT_PORT, /* Get all information related to default port */
Expand Down
83 changes: 83 additions & 0 deletions src/daemon/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
#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,
void *input, int input_len, void **output, int *subscribed)
Expand Down Expand Up @@ -273,6 +277,82 @@ client_handle_get_interfaces(struct lldpd *cfg, enum hmsg_type *type,
return output_len;
}

#ifdef ENABLE_LLDPMED
/**
* Set local chassis inventory info
* Input: chassis object
* Output: updated chassis object
*/
static ssize_t
client_handle_set_local_chassis(struct lldpd *cfg, enum hmsg_type *type,
void *input, int input_len, void **output, int *subscribed)
{
struct lldpd_chassis *chassis = NULL;
struct lldpd_chassis *local_chassis = NULL;
struct utsname un;

log_debug("rpc", "client request a change in chassis configuration");
if (lldpd_chassis_unserialize(input, input_len, &chassis) <= 0) {
*type = NONE;
return 0;
}

local_chassis = LOCAL_CHASSIS(cfg);

free(local_chassis->c_med_hw);
local_chassis->c_med_hw = (!chassis->c_med_hw) ? dmi_hw() : strdup(chassis->c_med_hw);

// Follows lldpd.c - only set sw if advertising is enabled
if (cfg->g_config.c_advertise_version) {
free(local_chassis->c_med_sw);

if (!chassis->c_med_sw) {
if (uname(&un) < 0) {
log_warn("rpc", "Could not get default uname. Will continue anyway.");
local_chassis->c_med_sw = NULL;
} else {
local_chassis->c_med_sw = strdup(un.release);
}
} else {
local_chassis->c_med_sw = strdup(chassis->c_med_sw);
}
}

free(local_chassis->c_med_fw);
local_chassis->c_med_fw = (!chassis->c_med_fw) ? dmi_fw() : strdup(chassis->c_med_fw);

free(local_chassis->c_med_sn);
local_chassis->c_med_sn = (!chassis->c_med_sn) ? dmi_sn() : strdup(chassis->c_med_sn);

free(local_chassis->c_med_manuf);
local_chassis->c_med_manuf = (!chassis->c_med_manuf) ? dmi_manuf() : strdup(chassis->c_med_manuf);

free(local_chassis->c_med_model);
local_chassis->c_med_model = (!chassis->c_med_model) ? dmi_model() : strdup(chassis->c_med_model);

free(local_chassis->c_med_asset);
local_chassis->c_med_asset = (!chassis->c_med_asset) ? dmi_asset() : strdup(chassis->c_med_asset);

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);
log_debug("rpc", "change serial-number to: %s", local_chassis->c_med_sn);
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);

lldpd_chassis_cleanup(chassis, 1);

ssize_t output_len = lldpd_chassis_serialize(local_chassis, output);
if (output_len <= 0) {
*type = NONE;
return 0;
}

return output_len;
}
#endif /* ENABLE_LLDPMED */

/* Return the local chassis.
Input: nothing.
Output: local chassis (lldpd_chassis)
Expand Down Expand Up @@ -572,6 +652,9 @@ 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 },
Expand Down
32 changes: 18 additions & 14 deletions src/daemon/lldpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1156,16 +1156,25 @@ lldpd_send(struct lldpd_hardware *hardware)

#ifdef ENABLE_LLDPMED
static void
lldpd_med(struct lldpd_chassis *chassis)
lldpd_med(struct lldpd *cfg, struct utsname *un)
{
static short int once = 0;
if (!once) {
chassis->c_med_hw = dmi_hw();
chassis->c_med_fw = dmi_fw();
chassis->c_med_sn = dmi_sn();
chassis->c_med_manuf = dmi_manuf();
chassis->c_med_model = dmi_model();
chassis->c_med_asset = dmi_asset();
if (!once && cfg) {
LOCAL_CHASSIS(cfg)->c_med_hw = dmi_hw();
LOCAL_CHASSIS(cfg)->c_med_fw = dmi_fw();
LOCAL_CHASSIS(cfg)->c_med_sn = dmi_sn();
LOCAL_CHASSIS(cfg)->c_med_manuf = dmi_manuf();
LOCAL_CHASSIS(cfg)->c_med_model = dmi_model();
LOCAL_CHASSIS(cfg)->c_med_asset = dmi_asset();
if (un) {
if (LOCAL_CHASSIS(cfg)->c_med_sw)
free(LOCAL_CHASSIS(cfg)->c_med_sw);

if (cfg->g_config.c_advertise_version)
LOCAL_CHASSIS(cfg)->c_med_sw = strdup(un->release);
else
LOCAL_CHASSIS(cfg)->c_med_sw = strdup("Unknown");
}
once = 1;
}
}
Expand Down Expand Up @@ -1242,12 +1251,7 @@ lldpd_update_localchassis(struct lldpd *cfg)
#ifdef ENABLE_LLDPMED
if (LOCAL_CHASSIS(cfg)->c_cap_available & LLDP_CAP_TELEPHONE)
LOCAL_CHASSIS(cfg)->c_cap_enabled |= LLDP_CAP_TELEPHONE;
lldpd_med(LOCAL_CHASSIS(cfg));
free(LOCAL_CHASSIS(cfg)->c_med_sw);
if (cfg->g_config.c_advertise_version)
LOCAL_CHASSIS(cfg)->c_med_sw = strdup(un.release);
else
LOCAL_CHASSIS(cfg)->c_med_sw = strdup("Unknown");
lldpd_med(cfg, &un);
#endif
if ((LOCAL_CHASSIS(cfg)->c_cap_available & LLDP_CAP_STATION) &&
(LOCAL_CHASSIS(cfg)->c_cap_enabled == 0))
Expand Down
Loading

0 comments on commit 8ef9c76

Please sign in to comment.