From: kanna Date: Sun, 21 Feb 2016 17:59:10 +0000 (-0800) Subject: enhance custom tlv with add/replace commands X-Git-Tag: 0.9.2~50^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7c26c8b4e44e991efd99053823c17ec01c6b70e5;p=thirdparty%2Flldpd.git enhance custom tlv with add/replace commands allow for specific custom tlv to be deleted --- diff --git a/src/client/conf-lldp.c b/src/client/conf-lldp.c index 275a4855..4998008c 100644 --- a/src/client/conf-lldp.c +++ b/src/client/conf-lldp.c @@ -238,8 +238,12 @@ cmd_custom_tlv_set(struct lldpctl_conn_t *conn, struct writer *w, 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; @@ -281,6 +285,10 @@ cmd_custom_tlv_set(struct lldpctl_conn_t *conn, struct writer *w, 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; @@ -298,6 +306,7 @@ set: 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); @@ -311,19 +320,57 @@ set: 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( @@ -335,14 +382,33 @@ register_commands_configure_lldp_custom_tlvs(struct cmd_node *configure_lldp) 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, @@ -500,13 +566,6 @@ register_commands_configure_lldp(struct cmd_node *configure, #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 } diff --git a/src/client/lldpcli.8.in b/src/client/lldpcli.8.in index 36bbd5d1..b318b8b1 100644 --- a/src/client/lldpcli.8.in +++ b/src/client/lldpcli.8.in @@ -426,7 +426,9 @@ flag), setting any transmit mode won't have any effect. .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 @@ -434,7 +436,7 @@ Emit a custom TLV for OUI .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 @@ -443,12 +445,30 @@ and 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 diff --git a/src/daemon/client.c b/src/daemon/client.c index f7961c72..5e05c2bf 100644 --- a/src/daemon/client.c +++ b/src/daemon/client.c @@ -411,19 +411,26 @@ _client_handle_set_port(struct lldpd *cfg, 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 diff --git a/src/lib/atom.h b/src/lib/atom.h index 2f3559ee..cf8b1679 100644 --- a/src/lib/atom.h +++ b/src/lib/atom.h @@ -277,6 +277,7 @@ struct _lldpctl_atom_custom_list_t { struct _lldpctl_atom_custom_t { lldpctl_atom_t base; struct _lldpctl_atom_port_t *parent; + int op; struct lldpd_custom *tlv; }; #endif diff --git a/src/lib/atoms/custom.c b/src/lib/atoms/custom.c index a888d988..71800d23 100644 --- a/src/lib/atoms/custom.c +++ b/src/lib/atoms/custom.c @@ -100,6 +100,40 @@ _lldpctl_atom_get_int_custom(lldpctl_atom_t *atom, lldpctl_key_t key) } } +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) @@ -197,6 +231,7 @@ static struct atom_builder custom = .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 }; diff --git a/src/lib/atoms/port.c b/src/lib/atoms/port.c index 046813aa..dda4d853 100644 --- a/src/lib/atoms/port.c +++ b/src/lib/atoms/port.c @@ -379,6 +379,7 @@ _lldpctl_atom_set_atom_port(lldpctl_atom_t *atom, lldpctl_key_t key, lldpctl_ato } custom = (struct _lldpctl_atom_custom_t *)value; set.custom = custom->tlv; + set.custom_tlv_op = custom->op; break; #endif default: diff --git a/src/lib/lldpctl.h b/src/lib/lldpctl.h index 00f8e067..fbb115cb 100644 --- a/src/lib/lldpctl.h +++ b/src/lib/lldpctl.h @@ -789,6 +789,7 @@ typedef enum { 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; diff --git a/src/lldpd-structs.c b/src/lldpd-structs.c index 6e85f9a7..d42ebfb5 100644 --- a/src/lldpd-structs.c +++ b/src/lldpd-structs.c @@ -104,7 +104,41 @@ lldpd_pi_cleanup(struct lldpd_port *port) #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; diff --git a/src/lldpd-structs.h b/src/lldpd-structs.h index afe9acde..707b7a22 100644 --- a/src/lldpd-structs.h +++ b/src/lldpd-structs.h @@ -215,6 +215,11 @@ MARSHAL_STR(lldpd_chassis, c_med_asset) 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 */ @@ -328,6 +333,7 @@ struct lldpd_port_set { #ifdef ENABLE_CUSTOM struct lldpd_custom *custom; int custom_list_clear; + int custom_tlv_op; #endif }; MARSHAL_BEGIN(lldpd_port_set) @@ -531,6 +537,8 @@ void lldpd_vlan_cleanup(struct lldpd_port *); 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 diff --git a/tests/lldpcli.conf b/tests/lldpcli.conf index 2246a47c..1e5e3353 100644 --- a/tests/lldpcli.conf +++ b/tests/lldpcli.conf @@ -33,6 +33,10 @@ configure lldp ports eth0 status txOnly 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