]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
enhance custom tlv with add/replace commands 163/head
authorkanna <kanna@cumulusnetworks.com>
Sun, 21 Feb 2016 17:59:10 +0000 (09:59 -0800)
committerkanna <kanna@cumulusnetworks.com>
Sun, 28 Feb 2016 13:20:48 +0000 (05:20 -0800)
allow for specific custom tlv to be deleted

src/client/conf-lldp.c
src/client/lldpcli.8.in
src/daemon/client.c
src/lib/atom.h
src/lib/atoms/custom.c
src/lib/atoms/port.c
src/lib/lldpctl.h
src/lldpd-structs.c
src/lldpd-structs.h
tests/lldpcli.conf

index 275a485518b38d8478521a15f977f6ee5e2c4a85..4998008c075f1f2bcc86e638bdff9a12bb8ec2f6 100644 (file)
@@ -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
 }
index 36bbd5d1c0d5e50388dd957cac5fb199b304877f..b318b8b1e489fc6ee286d11db081271222e1fca5 100644 (file)
@@ -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
index f7961c72ce523394d97d305826a2fda3993ec7da..5e05c2bf73a5107cd84202f2ce3f9eb25edff9d0 100644 (file)
@@ -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
index 2f3559eef3c7fe6f222b482b6b152c814209da1b..cf8b1679538bef7f97e87ce358fa43aa4f279d29 100644 (file)
@@ -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
index a888d98871e0ecff24584690302f328be32d0018..71800d237c56502b8be915ce62fbaacdbc4b1f4c 100644 (file)
@@ -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 };
 
index 046813aa380113fe929442e90ef2700efde17e1f..dda4d8536a865ddb2a5348d0d4a0523f0e25a220 100644 (file)
@@ -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:
index 00f8e06730e55dea46f3583062cfd7d47c1700fd..fbb115cbe862750376d3fdf9d52c5770152580cc 100644 (file)
@@ -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;
 
index 6e85f9a70d81a5598c73247e7db32211142dfccf..d42ebfb585b84d9439edc2c0dbdf373ed7be953b 100644 (file)
@@ -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;
index afe9acdebceb0a8f270e2b6ea06fdc7403eaefe8..707b7a22a36a4f2e20f4fa5f33f09e0a8fdb4a25 100644 (file)
@@ -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
 
index 2246a47c09e486395de9645915fbc8a83a6e524e..1e5e33536df26cc476fb34c1de40d261c38a15aa 100644 (file)
@@ -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