]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
lib: add compatibility layer with chassis-related information
authorVincent Bernat <vincent@bernat.im>
Sat, 11 Jul 2015 20:29:12 +0000 (22:29 +0200)
committerVincent Bernat <vincent@bernat.im>
Sat, 11 Jul 2015 20:29:12 +0000 (22:29 +0200)
When querying a port, if we don't find the requested information,
check if the chassis has the information as well.

src/lib/atom.c
src/lib/atom.h
src/lib/atoms/chassis.c
src/lib/atoms/port.c
tests/lldpcli.conf

index 054c7bd3ec3c08225989512fbc8e46a5b100c708..ddf849ee893dcabe678126413e809e1fdfdae426 100644 (file)
@@ -452,7 +452,7 @@ lldpctl_get_local_chassis(lldpctl_conn_t *conn)
            &p, &MARSHAL_INFO(lldpd_chassis));
        if (rc == 0) {
                chassis = p;
-               return _lldpctl_new_atom(conn, atom_chassis, chassis, NULL);
+               return _lldpctl_new_atom(conn, atom_chassis, chassis, NULL, 0);
        }
        return NULL;
 }
index 613d8594b95f90e1742a4061c1320c501038e1dd..18abf6fac4af7314c2644d144faf4f002af551dd 100644 (file)
@@ -175,6 +175,7 @@ struct _lldpctl_atom_chassis_t {
        lldpctl_atom_t base;
        struct lldpd_chassis *chassis;
        struct _lldpctl_atom_port_t *parent; /* Optional: parent of this atom (owning our reference) */
+       int embedded;                        /* This atom is "embedded" (not refcounted) */
 };
 
 struct _lldpctl_atom_port_t {
@@ -182,6 +183,7 @@ struct _lldpctl_atom_port_t {
        struct lldpd_hardware *hardware; /* Local port only */
        struct lldpd_port     *port;     /* Local and remote */
        struct _lldpctl_atom_port_t *parent; /* Local port if we are a remote port */
+       lldpctl_atom_t *chassis; /* Internal atom for chassis */
 };
 
 /* Can represent any simple list holding just a reference to a port. */
index 4316103efdb0c66d9048aca73c804283dfda878d..006996fce68fc8c6ed77d814968e5bdb9862db4d 100644 (file)
@@ -55,7 +55,8 @@ _lldpctl_atom_new_chassis(lldpctl_atom_t *atom, va_list ap)
            (struct _lldpctl_atom_chassis_t *)atom;
        p->chassis = va_arg(ap, struct lldpd_chassis*);
        p->parent = va_arg(ap, struct _lldpctl_atom_port_t*);
-       if (p->parent)
+       p->embedded = va_arg(ap, int);
+       if (p->parent && !p->embedded)
                lldpctl_atom_inc_ref((lldpctl_atom_t*)p->parent);
        return 1;
 }
@@ -67,9 +68,15 @@ _lldpctl_atom_free_chassis(lldpctl_atom_t *atom)
            (struct _lldpctl_atom_chassis_t *)atom;
        /* When we have a parent, the chassis structure is in fact part of the
         * parent, just decrement the reference count of the parent. Otherwise,
-        * we need to free the whole chassis. */
-       if (p->parent) lldpctl_atom_dec_ref((lldpctl_atom_t*)p->parent);
-       else lldpd_chassis_cleanup(p->chassis, 1);
+        * we need to free the whole chassis. When embedded, we don't alter the
+        * reference count of the parent. Therefore, it's important to also not
+        * increase the reference count of this atom. See
+        * `_lldpctl_atom_get_atom_chassis' for how to handle that. */
+       if (p->parent) {
+               if (!p->embedded)
+                       lldpctl_atom_dec_ref((lldpctl_atom_t*)p->parent);
+       } else
+               lldpd_chassis_cleanup(p->chassis, 1);
 }
 
 static lldpctl_atom_t*
@@ -82,7 +89,10 @@ _lldpctl_atom_get_atom_chassis(lldpctl_atom_t *atom, lldpctl_key_t key)
        switch (key) {
        case lldpctl_k_chassis_mgmt:
                return _lldpctl_new_atom(atom->conn, atom_mgmts_list,
-                   p, chassis);
+                   (p->parent && p->embedded)?
+                   (lldpctl_atom_t *)p->parent:
+                   (lldpctl_atom_t *)p,
+                   chassis);
        default:
                SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
                return NULL;
index e419a8ed58b46d96872bd47cd8eaded17eee0161..7cab6959a617a56ae1c65fc3834b8ff1dc70b1bc 100644 (file)
@@ -141,6 +141,11 @@ _lldpctl_atom_new_port(lldpctl_atom_t *atom, va_list ap)
        port->parent = va_arg(ap, struct _lldpctl_atom_port_t*);
        if (port->parent)
                lldpctl_atom_inc_ref((lldpctl_atom_t*)port->parent);
+
+       /* Internal atom. We are the parent, but our reference count is not
+        * incremented. */
+       port->chassis = _lldpctl_new_atom(atom->conn, atom_chassis,
+                   port->port->p_chassis, port, 1);
        return 1;
 }
 
@@ -167,6 +172,10 @@ _lldpctl_atom_free_port(lldpctl_atom_t *atom)
        struct lldpd_chassis  *one_chassis, *one_chassis_next;
        struct lldpd_port     *one_port;
 
+       /* Free internal chassis atom. Should be freed immediately since we
+        * should have the only reference. */
+       lldpctl_atom_dec_ref((lldpctl_atom_t*)port->chassis);
+
        /* We need to free the whole struct lldpd_hardware: local port, local
         * chassis and remote ports... The same chassis may be present several
         * times. We build a list of chassis (we don't use reference count). */
@@ -223,7 +232,7 @@ _lldpctl_atom_get_atom_port(lldpctl_atom_t *atom, lldpctl_key_t key)
        switch (key) {
        case lldpctl_k_port_chassis:
                return _lldpctl_new_atom(atom->conn, atom_chassis,
-                   port->p_chassis, p);
+                   port->p_chassis, p, 0);
 #ifdef ENABLE_DOT3
        case lldpctl_k_port_dot3_power:
                return _lldpctl_new_atom(atom->conn, atom_dot3_power,
@@ -255,8 +264,8 @@ _lldpctl_atom_get_atom_port(lldpctl_atom_t *atom, lldpctl_key_t key)
                return _lldpctl_new_atom(atom->conn, atom_custom_list, p);
 #endif
        default:
-               SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
-               return NULL;
+               /* Compatibility: query the associated chassis too */
+               return lldpctl_atom_get(p->chassis, key);
        }
 }
 
@@ -430,8 +439,8 @@ _lldpctl_atom_get_str_port(lldpctl_atom_t *atom, lldpctl_key_t key)
 #endif
 
        default:
-               SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
-               return NULL;
+               /* Compatibility: query the associated chassis too */
+               return lldpctl_atom_get_str(p->chassis, key);
        }
 }
 
@@ -528,7 +537,8 @@ _lldpctl_atom_get_int_port(lldpctl_atom_t *atom, lldpctl_key_t key)
                return port->p_pvid;
 #endif
        default:
-               return SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
+               /* Compatibility: query the associated chassis too */
+               return lldpctl_atom_get_int(p->chassis, key);
        }
        return SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
 }
@@ -545,8 +555,8 @@ _lldpctl_atom_get_buf_port(lldpctl_atom_t *atom, lldpctl_key_t key, size_t *n)
                *n = port->p_id_len;
                return (uint8_t*)port->p_id;
        default:
-               SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
-               return NULL;
+               /* Compatibility: query the associated chassis too */
+               return lldpctl_atom_get_buffer(p->chassis, key, n);
        }
 }
 
index 9a5b9fec9ebd3d79fc414e6b99831f7780ad93af..94d2d41f6bac3358c9674e71006d273a1d6a4d25 100644 (file)
@@ -49,4 +49,4 @@ configure ports eth0 dot3 power pse supported enabled paircontrol powerpairs spa
 configure dot3 power pd supported enabled powerpairs spare class class-3 type 1 source pse priority low requested 10000 allocated 15000
 
 # A convenient way to "test" lldpcli and liblldpctl is to load those commands in lldpcli with valgrind:
-#  libtool execute valgrind --suppressions=../src/client/lldpcli.supp --leak-check=full src/client/lldpcli -c ../src/client/lldpcli.conf
+#  libtool execute valgrind --suppressions=../src/client/lldpcli.supp --leak-check=full src/client/lldpcli -c ../tests/lldpcli.conf