return 1;
}
+static int
+cmd_portid_type(struct lldpctl_conn_t *conn, struct writer *w,
+ struct cmd_env *env, void *arg)
+{
+ char *value_str;
+ int m = 0, value = -1;
+
+ log_debug("lldpctl", "lldp PortID TLV Subtype");
+
+ lldpctl_atom_t *config = lldpctl_get_configuration(conn);
+ if (config == NULL) {
+ log_warnx("lldpctl",
+ "unable to get configuration from lldpd. %s",
+ lldpctl_last_strerror(conn));
+ return 0;
+ }
+
+ value_str = arg;
+ for (lldpctl_map_t *b_map =
+ lldpctl_key_get_map(lldpctl_k_config_lldp_portid_type);
+ b_map->string; b_map++) {
+ if (!strcmp(b_map->string, value_str)) {
+ value = b_map->value;
+ break;
+ }
+ }
+
+ if (value == -1) {
+ log_warnx("lldpctl", "invalid value");
+ lldpctl_atom_dec_ref(config);
+ return 0;
+ }
+
+ if (lldpctl_atom_set_int(config,
+ lldpctl_k_config_lldp_portid_type, value) == NULL) {
+ log_warnx("lldpctl", "unable to set LLDP PortID type."
+ " %s", lldpctl_last_strerror(conn));
+ lldpctl_atom_dec_ref(config);
+ return 0;
+ }
+
+ log_info("lldpctl", "LLDP PortID TLV type set to new value : %s", arg);
+ lldpctl_atom_dec_ref(config);
+
+ return 1;
+}
+
/**
* Register `configure lldp` commands.
*
NULL, cmd_store_env_value, "tx-hold"),
NEWLINE, "Set LLDP transmit hold",
NULL, cmd_txhold, NULL);
+
+ /* Now handle the various portid subtypes we can configure. */
+ struct cmd_node *configure_lldp_portid_type = commands_new(
+ configure_lldp,
+ "portidsubtype", "LLDP PortID TLV Subtype ",
+ NULL, NULL, NULL);
+
+ for (lldpctl_map_t *b_map =
+ lldpctl_key_get_map(lldpctl_k_config_lldp_portid_type);
+ b_map->string; b_map++) {
+ if (!strcmp(b_map->string, "ifname")) {
+ commands_new(
+ commands_new(configure_lldp_portid_type,
+ b_map->string, "Interface Name",
+ NULL, NULL, NULL),
+ NEWLINE, NULL,
+ NULL, cmd_portid_type,
+ b_map->string);
+ } else if (!strcmp(b_map->string, "macaddress")) {
+ commands_new(
+ commands_new(configure_lldp_portid_type,
+ b_map->string, "MAC Address",
+ NULL, NULL, NULL),
+ NEWLINE, NULL,
+ NULL, cmd_portid_type,
+ b_map->string);
+ }
+ }
}
"Source MAC for LLDP frames on bond slaves",
lldpctl_atom_get_str(configuration,
lldpctl_k_config_bond_slave_src_mac_type));
+ tag_datatag(w, "lldp_portid-type",
+ "Portid TLV Subtype for lldp frames",
+ lldpctl_atom_get_str(configuration,
+ lldpctl_k_config_lldp_portid_type));
tag_end(w);
tag_end(w);
return output_len;
}
+/* Change the PortID Subtype configuration for all interfaces */
+void
+portid_subtype_update(struct lldpd *cfg)
+{
+ struct lldpd_hardware *hardware;
+ struct interfaces_device_list *interfaces;
+ struct interfaces_address_list *addresses;
+ struct interfaces_device *iface;
+ interfaces = netlink_get_interfaces();
+ addresses = netlink_get_addresses();
+
+ if (interfaces == NULL || addresses == NULL) {
+ log_warnx("interfaces", "cannot update the list of local interfaces");
+ return;
+ }
+ log_debug("interfaces", "portid_subtype_update called....");
+ TAILQ_FOREACH(iface, interfaces, next) {
+ if ((hardware = lldpd_get_hardware(cfg, iface->name,
+ iface->index,NULL)) == NULL)
+ continue;
+
+ /* do some port->p_id and port->p_descr settings so we get updates */
+ interfaces_helper_port_name_desc(cfg, hardware, iface);
+ }
+}
+
/* Change the global configuration */
static int
client_handle_set_configuration(struct lldpd *cfg, enum hmsg_type *type,
log_debug("rpc", "client asked for immediate retransmission");
levent_send_now(cfg);
}
+ if (config->c_lldp_portid_type > LLDP_PORTID_SUBTYPE_UNKNOWN &&
+ config->c_lldp_portid_type <= LLDP_PORTID_SUBTYPE_MAX) {
+ log_debug("rpc", "change lldp portid tlv subtype to %d",
+ config->c_lldp_portid_type);
+ cfg->g_config.c_lldp_portid_type = config->c_lldp_portid_type;
+ /* update the interfaces since our portid type has changed */
+ portid_subtype_update(cfg);
+ }
/* Pause/resume */
if (config->c_paused != cfg->g_config.c_paused) {
log_debug("rpc", "client asked to %s lldpd",
memcpy(&hardware->h_lladdr, iface->address, ETHER_ADDR_LEN);
/* Fill information about port */
- interfaces_helper_port_name_desc(hardware, iface);
+ interfaces_helper_port_name_desc(cfg, hardware, iface);
/* Fill additional info */
#ifdef ENABLE_DOT3
/* Fill up port name and description */
void
-interfaces_helper_port_name_desc(struct lldpd_hardware *hardware,
+interfaces_helper_port_name_desc(struct lldpd *cfg,
+ struct lldpd_hardware *hardware,
struct interfaces_device *iface)
{
struct lldpd_port *port = &hardware->h_lport;
- /* There are two cases:
-
- 1. We have a kernel recent enough to support ifAlias
- _and_ a non empty ifAlias, then we will use it for
- description and use ifname for port ID.
-
- 2. Otherwise, we will use the MAC address as ID and the
- port name in description.
+ /* We need to set the portid to what the client configured.
+ This can be done from the CLI.
*/
-
- if (iface->alias == NULL || strlen(iface->alias) == 0) {
- /* Case 2: MAC address and port name */
- log_debug("interfaces", "use ifname and MAC address for %s",
- hardware->h_ifname);
+ switch (cfg->g_config.c_lldp_portid_type) {
+ case LLDP_PORTID_SUBTYPE_IFNAME:
+ log_debug("interfaces", "use ifname for %s",
+ hardware->h_ifname);
+ port->p_id_subtype = LLDP_PORTID_SUBTYPE_IFNAME;
+ port->p_id_len = strlen(hardware->h_ifname);
+ if (port->p_id != NULL) {
+ free(port->p_id);
+ }
+ if ((port->p_id = calloc(1, port->p_id_len)) == NULL)
+ fatal("interfaces", NULL);
+ memcpy(port->p_id, hardware->h_ifname, port->p_id_len);
+ break;
+ case LLDP_PORTID_SUBTYPE_LLADDR:
+ /* fall through so we use the mac address */
+ default:
+ log_debug("interfaces", "use MAC address for %s",
+ hardware->h_ifname);
port->p_id_subtype = LLDP_PORTID_SUBTYPE_LLADDR;
- if ((port->p_id =
- calloc(1, ETHER_ADDR_LEN)) == NULL)
+ if (port->p_id != NULL) {
+ free(port->p_id);
+ }
+ if ((port->p_id = calloc(1, ETHER_ADDR_LEN)) == NULL)
fatal("interfaces", NULL);
memcpy(port->p_id, hardware->h_lladdr, ETHER_ADDR_LEN);
port->p_id_len = ETHER_ADDR_LEN;
+ }
+
+ if (iface->alias != NULL && strlen(iface->alias) != 0) {
+ /* use the actual alias in the port description */
+ log_debug("interfaces", "using alias in description for %s",
+ hardware->h_ifname);
+ if (port->p_descr != NULL) {
+ free(port->p_descr);
+ }
+ port->p_descr = strdup(iface->alias);
+ } else {
+ /* use the ifname in the port description until alias is set */
+ log_debug("interfaces", "using ifname in description for %s",
+ hardware->h_ifname);
+ if (port->p_descr != NULL) {
+ free(port->p_descr);
+ }
port->p_descr = strdup(hardware->h_ifname);
- return;
}
- /* Case 1: port name and port description */
- log_debug("interfaces", "use ifname and ifalias for %s",
- hardware->h_ifname);
- port->p_id_subtype = LLDP_PORTID_SUBTYPE_IFNAME;
- port->p_id_len = strlen(hardware->h_ifname);
- if ((port->p_id =
- calloc(1, port->p_id_len)) == NULL)
- fatal("interfaces", NULL);
- memcpy(port->p_id, hardware->h_ifname, port->p_id_len);
- port->p_descr = strdup(iface->alias);
}
void
memcpy(&hardware->h_lladdr, iface->address, ETHER_ADDR_LEN);
/* Fill information about port */
- interfaces_helper_port_name_desc(hardware, iface);
+ interfaces_helper_port_name_desc(cfg, hardware, iface);
/* Fill additional info */
hardware->h_mtu = iface->mtu ? iface->mtu : 1500;
struct interfaces_device_list *,
struct lldpd_ops *,
int(*init)(struct lldpd *, struct lldpd_hardware *));
-void interfaces_helper_port_name_desc(struct lldpd_hardware *,
+void interfaces_helper_port_name_desc(struct lldpd *,
+ struct lldpd_hardware *,
struct interfaces_device *);
void interfaces_helper_mgmt(struct lldpd *,
struct interfaces_address_list *);
{ LLDP_BOND_SLAVE_SRC_MAC_TYPE_UNKNOWN, NULL},
};
+static lldpctl_map_t lldp_portid_map[] = {
+ { LLDP_PORTID_SUBTYPE_IFNAME, "ifname"},
+ { LLDP_PORTID_SUBTYPE_LLADDR, "macaddress"},
+ { LLDP_PORTID_SUBTYPE_UNKNOWN, NULL},
+};
+
static const char*
map_lookup(lldpctl_map_t *list, int n)
{
#endif
case lldpctl_k_config_bond_slave_src_mac_type:
return bond_slave_src_mac_map;
+ case lldpctl_k_config_lldp_portid_type:
+ return lldp_portid_map;
default: return empty_map;
}
}
case lldpctl_k_config_bond_slave_src_mac_type:
return map_lookup(bond_slave_src_mac_map,
c->config->c_bond_slave_src_mac_type);
+ case lldpctl_k_config_lldp_portid_type:
+ return map_lookup(lldp_portid_map,
+ c->config->c_lldp_portid_type);
default:
SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
return NULL;
config.c_bond_slave_src_mac_type = value;
c->config->c_bond_slave_src_mac_type = value;
break;
+ case lldpctl_k_config_lldp_portid_type:
+ config.c_lldp_portid_type = value;
+ c->config->c_lldp_portid_type = value;
+ break;
default:
SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
return NULL;
lldpctl_k_delete_cnt, /**< `(I)` delete cnt. Only works for a local port. */
lldpctl_k_config_tx_hold, /**< `(I,WO)` Transmit hold interval. */
lldpctl_k_config_bond_slave_src_mac_type, /**< `(I,WO)` bond slave src mac type. */
+ lldpctl_k_config_lldp_portid_type, /**< `(I,WO)` LLDP PortID TLV Subtype */
} lldpctl_key_t;
/**
#define LLDP_CHASSISID_SUBTYPE_LOCAL 7
/* Port ID subtype */
+#define LLDP_PORTID_SUBTYPE_UNKNOWN 0
#define LLDP_PORTID_SUBTYPE_IFALIAS 1
#define LLDP_PORTID_SUBTYPE_PORT 2
#define LLDP_PORTID_SUBTYPE_LLADDR 3
#define LLDP_PORTID_SUBTYPE_IFNAME 5
#define LLDP_PORTID_SUBTYPE_AGENTCID 6
#define LLDP_PORTID_SUBTYPE_LOCAL 7
+#define LLDP_PORTID_SUBTYPE_MAX LLDP_PORTID_SUBTYPE_LOCAL
/* Operational MAU Type field, from RFC 3636 */
#define LLDP_DOT3_MAU_AUI 1
lldpd_ppvid_cleanup(port);
lldpd_pi_cleanup(port);
#endif
+ /* will set these to NULL so we don't free wrong memory */
+
free(port->p_id);
+ port->p_id = NULL;
free(port->p_descr);
+ port->p_descr = NULL;
if (all) {
free(port->p_lastframe);
if (port->p_chassis) { /* chassis may not have been attributed, yet */
int c_tx_hold; /* Transmit hold */
int c_bond_slave_src_mac_type; /* Src mac type in lldp frames over bond
slaves */
+ int c_lldp_portid_type; /* The PortID type */
};
MARSHAL_BEGIN(lldpd_config)
MARSHAL_STR(lldpd_config, c_mgmt_pattern)