&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;
}
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 {
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. */
(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;
}
(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*
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;
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;
}
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). */
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,
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);
}
}
#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);
}
}
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);
}
*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);
}
}
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