return 1;
}
+static int
+cmd_agent_type(struct lldpctl_conn_t *conn, struct writer *w,
+ struct cmd_env *env, void *arg)
+{
+ const char *str = arg;
+ int value = -1;
+
+ log_debug("lldpctl", "set agent type to '%s'", str);
+
+ 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;
+ }
+
+ for (lldpctl_map_t *b_map =
+ lldpctl_key_get_map(lldpctl_k_config_lldp_agent_type);
+ b_map->string; b_map++) {
+ if (!strcmp(b_map->string, 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_agent_type, value) == NULL) {
+ log_warnx("lldpctl", "unable to set LLDP agent type."
+ " %s", lldpctl_last_strerror(conn));
+ lldpctl_atom_dec_ref(config);
+ return 0;
+ }
+
+ log_info("lldpctl", "agent type set to new value : %s", str);
+ lldpctl_atom_dec_ref(config);
+
+ return 1;
+}
+
static int
cmd_portid_type_local(struct lldpctl_conn_t *conn, struct writer *w,
struct cmd_env *env, void *arg)
NULL, cmd_status, NULL);
}
+ /* Configure the various agent type we can configure. */
+ struct cmd_node *configure_lldp_agent_type = commands_new(
+ configure_lldp,
+ "agent-type",
+ "LLDP agent type",
+ NULL, NULL, NULL);
+ for (lldpctl_map_t *b_map =
+ lldpctl_key_get_map(lldpctl_k_config_lldp_agent_type);
+ b_map->string; b_map++) {
+ const char *tag = strdup(totag(b_map->string));
+ SUPPRESS_LEAK(tag);
+ commands_new(
+ commands_new(configure_lldp_agent_type,
+ tag,
+ b_map->string,
+ NULL, NULL, NULL),
+ NEWLINE, "Set LLDP agent type",
+ NULL, cmd_agent_type, b_map->string);
+ }
+
/* 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 ",
+ "portidsubtype", "LLDP PortID TLV Subtype",
NULL, NULL, NULL);
for (lldpctl_map_t *b_map =
"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",
+ tag_datatag(w, "lldp-portid-type",
+ "Port ID TLV subtype for LLDP frames",
lldpctl_atom_get_str(configuration,
lldpctl_k_config_lldp_portid_type));
+ tag_datatag(w, "lldp-agent-type",
+ "Agent type",
+ lldpctl_atom_get_str(configuration,
+ lldpctl_k_config_lldp_agent_type));
tag_end(w);
tag_end(w);
Enable promiscuous mode on managed interfaces.
.Pp
When the interface is not managed any more (or when quitting
-.Nm ) ,
+.Nm lldpd ) ,
the interface is left in promiscuous mode as it is difficult to know
if someone else also put the interface in promiscuous mode.
.Pp
quite unlikely).
.Ed
+.Cd configure
+.Cd lldp agent-type
+.Cd nearest-bridge | nearest-non-tpmr-bridge | nearest-customer-bridge
+.Bd -ragged -offset XXXXXX
+The destination MAC address used to send LLDPDU allows an agent to
+control the propagation of LLDPDUs. By default, the
+.Li 01:80:c2:00:00:0e
+MAC address is used and limit the propagation of the LLDPDU to the
+nearest bridge
+.Cd ( nearest-bridge ) .
+To instruct
+.Nm lldpd
+to use the
+.Li 01:80:c2:00:00:03
+MAC address instead, use
+.Cd nearest-nontpmr-bridge
+instead.
+To use the
+.Li 01:80:c2:00:00:00
+MAC address instead, use
+.Cd nearest-customer-bridge
+instead.
+.Ed
+
.Cd configure
.Cd lldp portidsubtype
.Cd ifname | macaddress
.Cd local Ar value Op Cd description Ar description
.Bd -ragged -offset XXXXXX
Force port ID subtype. By default,
-.Nm
+.Nm lldpd
will use the MAC address as port identifier and the interface name as
port description, unless the interface has an alias. In this case, the
interface name will be used as port identifier and the description
cfg->g_config.c_lldp_portid_type = config->c_lldp_portid_type;
levent_update_now(cfg);
}
+ if (CHANGED(c_lldp_agent_type) &&
+ config->c_lldp_agent_type > LLDP_AGENT_TYPE_UNKNOWN &&
+ config->c_lldp_agent_type <= LLDP_AGENT_TYPE_MAX) {
+ log_debug("rpc", "change lldp agent type to %d",
+ config->c_lldp_agent_type);
+ cfg->g_config.c_lldp_agent_type = config->c_lldp_agent_type;
+ levent_update_now(cfg);
+ }
/* Pause/resume */
if (CHANGED(c_paused)) {
log_debug("rpc", "client asked to %s lldpd",
struct lldpd_mgmt *mgmt;
int proto;
- u_int8_t mcastaddr[] = LLDP_ADDR_NEAREST_BRIDGE;
+ u_int8_t mcastaddr_regular[] = LLDP_ADDR_NEAREST_BRIDGE;
+ u_int8_t mcastaddr_nontpmr[] = LLDP_ADDR_NEAREST_NONTPMR_BRIDGE;
+ u_int8_t mcastaddr_customer[] = LLDP_ADDR_NEAREST_CUSTOMER_BRIDGE;
+ u_int8_t *mcastaddr;
#ifdef ENABLE_DOT1
const u_int8_t dot1[] = LLDP_TLV_ORG_DOT1;
struct lldpd_vlan *vlan;
pos = packet;
/* Ethernet header */
+ switch (global->g_config.c_lldp_agent_type) {
+ case LLDP_AGENT_TYPE_NEAREST_NONTPMR_BRIDGE: mcastaddr = mcastaddr_nontpmr; break;
+ case LLDP_AGENT_TYPE_NEAREST_CUSTOMER_BRIDGE: mcastaddr = mcastaddr_customer; break;
+ case LLDP_AGENT_TYPE_NEAREST_BRIDGE:
+ default: mcastaddr = mcastaddr_regular; break;
+ }
if (!(
/* LLDP multicast address */
- POKE_BYTES(mcastaddr, sizeof(mcastaddr)) &&
+ POKE_BYTES(mcastaddr, ETHER_ADDR_LEN) &&
/* Source MAC address */
POKE_BYTES(&hardware->h_lladdr, ETHER_ADDR_LEN) &&
/* LLDP frame */
},
};
+static struct atom_map lldp_agent_map = {
+ .key = lldpctl_k_config_lldp_agent_type,
+ .map = {
+ { LLDP_AGENT_TYPE_NEAREST_BRIDGE, "nearest bridge"},
+ { LLDP_AGENT_TYPE_NEAREST_NONTPMR_BRIDGE, "nearest non-TPMR bridge"},
+ { LLDP_AGENT_TYPE_NEAREST_CUSTOMER_BRIDGE, "nearest customer bridge"},
+ { LLDP_AGENT_TYPE_UNKNOWN, NULL},
+ },
+};
+
ATOM_MAP_REGISTER(bond_slave_src_mac_map, 1);
ATOM_MAP_REGISTER(lldp_portid_map, 2);
+ATOM_MAP_REGISTER(lldp_agent_map, 3);
static int
_lldpctl_atom_new_config(lldpctl_atom_t *atom, va_list ap)
case lldpctl_k_config_lldp_portid_type:
return map_lookup(lldp_portid_map.map,
c->config->c_lldp_portid_type);
+ case lldpctl_k_config_lldp_agent_type:
+ return map_lookup(lldp_agent_map.map,
+ c->config->c_lldp_agent_type);
default:
SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
return NULL;
config.c_lldp_portid_type = value;
c->config->c_lldp_portid_type = value;
break;
+ case lldpctl_k_config_lldp_agent_type:
+ config.c_lldp_agent_type = value;
+ c->config->c_lldp_agent_type = value;
+ break;
default:
SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
return NULL;
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_k_config_lldp_agent_type, /**< `(I,WO)` LLDP agent type */
lldpctl_k_custom_tlvs = 5000, /**< `(AL)` custom TLVs */
lldpctl_k_custom_tlvs_clear, /** `(I,WO)` clear list of custom TLVs */
#define LLDP_BOND_SLAVE_SRC_MAC_TYPE_LOCALLY_ADMINISTERED 4
#define LLDP_BOND_SLAVE_SRC_MAC_TYPE_MAX LLDP_BOND_SLAVE_SRC_MAC_TYPE_LOCALLY_ADMINISTERED
+/* Agent types */
+#define LLDP_AGENT_TYPE_UNKNOWN 0
+#define LLDP_AGENT_TYPE_NEAREST_BRIDGE 1
+#define LLDP_AGENT_TYPE_NEAREST_NONTPMR_BRIDGE 2
+#define LLDP_AGENT_TYPE_NEAREST_CUSTOMER_BRIDGE 3
+#define LLDP_AGENT_TYPE_MAX LLDP_AGENT_TYPE_NEAREST_CUSTOMER_BRIDGE
+
#endif /* _LLDP_H */
int c_bond_slave_src_mac_type; /* Src mac type in lldp frames over bond
slaves */
int c_lldp_portid_type; /* The PortID type */
+ int c_lldp_agent_type; /* The agent type */
};
MARSHAL_BEGIN(lldpd_config)
MARSHAL_STR(lldpd_config, c_mgmt_pattern)