uint8_t oui_info[LLDP_TLV_ORG_OUI_INFO_MAXLEN];
int oui_info_len = 0;
uint16_t subtype = 0;
+ char *op = "add";
- log_debug("lldpctl", "lldp custom-tlv(s) %s", arg?"set":"clear");
+ if (!arg || !strcmp(arg, "remove"))
+ op = "remove";
+
+ log_debug("lldpctl", "lldp custom-tlv(s) %s", op);
if (!arg)
goto set;
free(s_copy);
}
+ s = cmdenv_get(env, "replace");
+ /* This info is optional */
+ if (s) op = "replace";
+
set:
while ((port = cmd_iterate_on_ports(conn, env, &name))) {
lldpctl_atom_t *custom_tlvs;
lldpctl_atom_set_buffer(tlv, lldpctl_k_custom_tlv_oui, oui, sizeof(oui));
lldpctl_atom_set_int(tlv, lldpctl_k_custom_tlv_oui_subtype, subtype);
lldpctl_atom_set_buffer(tlv, lldpctl_k_custom_tlv_oui_info_string, oui_info, oui_info_len);
+ lldpctl_atom_set_str(tlv, lldpctl_k_custom_tlv_op, op);
/* Assign it to port */
lldpctl_atom_set(port, lldpctl_k_custom_tlv, tlv);
return 1;
}
+static int
+cmd_check_no_add_env(struct cmd_env *env, void *arg)
+{
+ const char *what = arg;
+ if (cmdenv_get(env, "add")) return 0;
+ if (cmdenv_get(env, what)) return 0;
+ return 1;
+}
+
+static int
+cmd_check_no_replace_env(struct cmd_env *env, void *arg)
+{
+ const char *what = arg;
+ if (cmdenv_get(env, "replace")) return 0;
+ if (cmdenv_get(env, what)) return 0;
+ return 1;
+}
+
void
-register_commands_configure_lldp_custom_tlvs(struct cmd_node *configure_lldp)
+register_commands_configure_lldp_custom_tlvs(struct cmd_node *configure_lldp,
+ struct cmd_node *unconfigure_lldp)
{
struct cmd_node *configure_custom_tlvs;
+ struct cmd_node *unconfigure_custom_tlvs;
struct cmd_node *configure_custom_tlvs_basic;
+ struct cmd_node *unconfigure_custom_tlvs_basic;
- configure_custom_tlvs =
+ configure_custom_tlvs =
commands_new(configure_lldp,
"custom-tlv",
"Add custom TLV(s) to be broadcast on ports",
NULL, NULL, NULL);
- /* Basic form: 'configure lldp oui 11,22,33 subtype 44' */
+ unconfigure_custom_tlvs =
+ commands_new(unconfigure_lldp,
+ "custom-tlv",
+ "Remove ALL custom TLV(s)",
+ NULL, NULL, NULL);
+
+ commands_new(unconfigure_custom_tlvs,
+ NEWLINE, "Remove ALL custom TLV",
+ NULL, cmd_custom_tlv_set, NULL);
+
+ commands_new(configure_custom_tlvs,
+ "add", "Add custom TLV",
+ cmd_check_no_replace_env, cmd_store_env_and_pop, "add");
+ commands_new(configure_custom_tlvs,
+ "replace", "Replace custom TLV",
+ cmd_check_no_add_env, cmd_store_env_and_pop, "replace");
+
+ /* Basic form: 'configure lldp custom-tlv oui 11,22,33 subtype 44' */
configure_custom_tlvs_basic =
commands_new(
commands_new(
NULL, cmd_store_env_value, "oui"),
"subtype", "Organizationally Defined Subtype",
NULL, NULL, NULL),
- NULL, "Organizationally Defined Subtype",
+ NULL, "Organizationally Defined Subtype",
NULL, cmd_store_env_value, "subtype");
commands_new(configure_custom_tlvs_basic,
NEWLINE, "Add custom TLV(s) to be broadcast on ports",
NULL, cmd_custom_tlv_set, "enable");
- /* Extended form: 'configure lldp oui 11,22,33 subtype 44 oui-info 55,66,77,...' */
+ /* Basic form: 'unconfigure lldp custom-tlv oui 11,22,33 subtype 44' */
+ unconfigure_custom_tlvs_basic =
+ commands_new(
+ commands_new(
+ commands_new(
+ commands_new(unconfigure_custom_tlvs,
+ "oui", "Organizationally Unique Identifier",
+ NULL, NULL, NULL),
+ NULL, "Organizationally Unique Identifier",
+ NULL, cmd_store_env_value, "oui"),
+ "subtype", "Organizationally Defined Subtype",
+ NULL, NULL, NULL),
+ NULL, "Organizationally Defined Subtype",
+ NULL, cmd_store_env_value, "subtype");
+
+ commands_new(unconfigure_custom_tlvs_basic,
+ NEWLINE, "Remove specific custom TLV",
+ NULL, cmd_custom_tlv_set, "remove");
+
+ /* Extended form: 'configure custom-tlv lldp oui 11,22,33 subtype 44 oui-info 55,66,77,...' */
commands_new(
commands_new(
commands_new(configure_custom_tlvs_basic,
#ifdef ENABLE_CUSTOM
- register_commands_configure_lldp_custom_tlvs(configure_lldp);
- commands_new(
- commands_new(unconfigure_lldp,
- "custom-tlv",
- "Clear all (previously set) custom TLVs",
- NULL, NULL, NULL),
- NEWLINE, "Clear all (previously set) custom TLVs",
- NULL, cmd_custom_tlv_set, NULL);
+ register_commands_configure_lldp_custom_tlvs(configure_lldp, unconfigure_lldp);
#endif
}
.Ed
.Cd configure
-.Cd lldp custom-tlv oui Ar oui
+.Cd lldp custom-tlv
+.Op Cd add | replace
+.Cd oui Ar oui
.Cd subtype Ar subtype
.Op Cd oui-info Ar content
.Bd -ragged -offset XXXXXX
.Ar oui ,
with subtype
.Ar subtype
-and optionnaly with the bytes specified in
+and optionally with the bytes specified in
.Ar content .
Both
.Ar oui
should be a comma-separated list of bytes.
.Ar oui
must be exactly 3-byte long.
+If
+.Ar add
+is specified then the TLV will be added. This is the default action.
+If
+.Ar Replace
+is specified then all TLVs with the same
+.Ar oui
+and
+.Ar subtype
+will be replaced.
+
.Ed
.Cd unconfigure
.Cd lldp custom-tlv
+.Op Cd oui Ar oui
+.Op Cd subtype Ar subtype
.Bd -ragged -offset XXXXXX
-Remove any previously configured custom TLV.
+When no oui is specified, remove all previously configured custom TLV.
+When OUI
+.Ar oui
+and subtype
+.Ar subtype
+is specified, remove specific instances of custom TLV.
.Ed
.Cd configure med fast-start
lldpd_custom_list_cleanup(port);
} else {
if (set->custom) {
- struct lldpd_custom *custom;
- log_debug("rpc", "requested custom TLV add");
- if ((custom = malloc(sizeof(struct lldpd_custom)))) {
- memcpy(custom, set->custom, sizeof(struct lldpd_custom));
- if ((custom->oui_info = malloc(custom->oui_info_len))) {
- memcpy(custom->oui_info, set->custom->oui_info, custom->oui_info_len);
- TAILQ_INSERT_TAIL(&port->p_custom_list, custom, next);
- } else {
- free(custom);
- log_warn("rpc", "could not allocate memory for custom TLV info");
- }
- } else
- log_warn("rpc", "could not allocate memory for custom TLV");
+ log_info("rpc", "custom TLV op %s oui %02x:%02x:%02x subtype %x",
+ (set->custom_tlv_op == CUSTOM_TLV_REMOVE)?"remove":
+ (set->custom_tlv_op == CUSTOM_TLV_ADD)?"add":"replace",
+ set->custom->oui[0],
+ set->custom->oui[1],
+ set->custom->oui[2],
+ set->custom->subtype);
+ switch (set->custom_tlv_op) {
+ case CUSTOM_TLV_REMOVE:
+ lldpd_custom_tlv_cleanup(port, set->custom);
+ break;
+ case CUSTOM_TLV_ADD:
+ lldpd_custom_tlv_add(port, set->custom);
+ break;
+ case CUSTOM_TLV_REPLACE:
+ default:
+ lldpd_custom_tlv_cleanup(port, set->custom);
+ lldpd_custom_tlv_add(port, set->custom);
+ break;
+ }
}
}
#endif
struct _lldpctl_atom_custom_t {
lldpctl_atom_t base;
struct _lldpctl_atom_port_t *parent;
+ int op;
struct lldpd_custom *tlv;
};
#endif
}
}
+static lldpctl_atom_t*
+_lldpctl_atom_set_str_custom(lldpctl_atom_t *atom, lldpctl_key_t key,
+ const char *value)
+{
+ struct _lldpctl_atom_custom_t *custom =
+ (struct _lldpctl_atom_custom_t *)atom;
+
+ if (!value || !strlen(value))
+ return NULL;
+
+ /* Only local port can be modified */
+ if (!custom->parent->local) {
+ SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
+ return NULL;
+ }
+
+ switch (key) {
+ case lldpctl_k_custom_tlv_op:
+ if (!strcmp(value, "replace"))
+ custom->op = CUSTOM_TLV_REPLACE;
+ else if (!strcmp(value, "remove"))
+ custom->op = CUSTOM_TLV_REMOVE;
+ else
+ custom->op = CUSTOM_TLV_ADD;
+ return atom;
+ default:
+ SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
+ return NULL;
+ }
+
+ SET_ERROR(atom->conn, LLDPCTL_ERR_BAD_VALUE);
+ return NULL;
+}
+
static lldpctl_atom_t*
_lldpctl_atom_set_int_custom(lldpctl_atom_t *atom, lldpctl_key_t key,
long int value)
.free = _lldpctl_atom_free_custom,
.get_int = _lldpctl_atom_get_int_custom,
.set_int = _lldpctl_atom_set_int_custom,
+ .set_str = _lldpctl_atom_set_str_custom,
.get_buffer = _lldpctl_atom_get_buffer_custom,
.set_buffer = _lldpctl_atom_set_buffer_custom };
}
custom = (struct _lldpctl_atom_custom_t *)value;
set.custom = custom->tlv;
+ set.custom_tlv_op = custom->op;
break;
#endif
default:
lldpctl_k_custom_tlv_oui, /**< `(I,WO)` custom TLV Organizationally Unique Identifier. Default is 0 (3 bytes) */
lldpctl_k_custom_tlv_oui_subtype, /**< `(I,WO)` custom TLV subtype. Default is 0 (1 byte) */
lldpctl_k_custom_tlv_oui_info_string, /**< `(I,WO)` custom TLV Organizationally Unique Identifier Information String (up to 507 bytes) */
+ lldpctl_k_custom_tlv_op, /**< `(I,WO)` custom TLV operation */
} lldpctl_key_t;
#endif
#ifdef ENABLE_CUSTOM
-void
+void
+lldpd_custom_tlv_add(struct lldpd_port *port, struct lldpd_custom *curr)
+{
+ struct lldpd_custom *custom;
+
+ if ((custom = malloc(sizeof(struct lldpd_custom)))) {
+ memcpy(custom, curr, sizeof(struct lldpd_custom));
+ if ((custom->oui_info = malloc(custom->oui_info_len))) {
+ memcpy(custom->oui_info, curr->oui_info, custom->oui_info_len);
+ TAILQ_INSERT_TAIL(&port->p_custom_list, custom, next);
+ } else {
+ free(custom);
+ log_warn("rpc", "could not allocate memory for custom TLV info");
+ }
+ }
+}
+
+void
+lldpd_custom_tlv_cleanup(struct lldpd_port *port, struct lldpd_custom *curr)
+{
+ struct lldpd_custom *custom, *custom_next;
+ for (custom = TAILQ_FIRST(&port->p_custom_list);
+ custom != NULL;
+ custom = custom_next) {
+ custom_next = TAILQ_NEXT(custom, next);
+ if (!memcmp(curr->oui, custom->oui, sizeof(curr->oui)) &&
+ curr->subtype == custom->subtype) {
+ TAILQ_REMOVE(&port->p_custom_list, custom, next);
+ free(custom->oui_info);
+ free(custom);
+ }
+ }
+}
+
+void
lldpd_custom_list_cleanup(struct lldpd_port *port)
{
struct lldpd_custom *custom, *custom_next;
MARSHAL_END(lldpd_chassis);
#ifdef ENABLE_CUSTOM
+
+#define CUSTOM_TLV_ADD 1
+#define CUSTOM_TLV_REPLACE 2
+#define CUSTOM_TLV_REMOVE 3
+
/* Custom TLV struct as defined on page 35 of IEEE 802.1AB-2005 */
struct lldpd_custom {
TAILQ_ENTRY(lldpd_custom) next; /* Pointer to next custom TLV */
#ifdef ENABLE_CUSTOM
struct lldpd_custom *custom;
int custom_list_clear;
+ int custom_tlv_op;
#endif
};
MARSHAL_BEGIN(lldpd_port_set)
void lldpd_pi_cleanup(struct lldpd_port *);
#endif
#ifdef ENABLE_CUSTOM
+void lldpd_custom_tlv_cleanup(struct lldpd_port *, struct lldpd_custom *);
+void lldpd_custom_tlv_add(struct lldpd_port *, struct lldpd_custom *);
void lldpd_custom_list_cleanup(struct lldpd_port *);
#endif
configure lldp status rxAndTx
configure lldp custom-tlv oui 33,44,55 subtype 44
configure lldp custom-tlv oui 33,44,55 subtype 44 oui-info 45,45,45,45,45
+configure lldp custom-tlv add oui 33,44,55 subtype 44 oui-info 55,55,55,55,55
+configure lldp custom-tlv add oui 33,44,55 subtype 55 oui-info 65,65,65,65,65
+configure lldp custom-tlv replace oui 33,44,55 subtype 44 oui-info 66,66,66,66,66
+unconfigure lldp custom-tlv oui 33,44,55 subtype 55
unconfigure lldp custom-tlv
configure system bond-slave-src-mac-type fixed
configure system bond-slave-src-mac-type local