summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2015-06-21 20:27:04 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2015-10-02 17:11:40 +0200
commit2212d76d08f3bc34c683aed1a6736325b841625c (patch)
tree15d61c2c8ad6f0eb807df35c7ee182dd859ee575
parent3c2f5a543de9cc3d958920b3bd18dc8657dc201f (diff)
lldp: add reference counter to struct tlv_packet
Add a reference counter to the tlv_packet structure so that it can be shared between multiple users and properly free'd when no longer in use.
-rw-r--r--src/libsystemd-network/lldp-internal.c6
-rw-r--r--src/libsystemd-network/lldp-tlv.c23
-rw-r--r--src/libsystemd-network/lldp-tlv.h9
-rw-r--r--src/libsystemd-network/sd-lldp.c2
4 files changed, 31 insertions, 9 deletions
diff --git a/src/libsystemd-network/lldp-internal.c b/src/libsystemd-network/lldp-internal.c
index 3c04898e92..2906b5a4b6 100644
--- a/src/libsystemd-network/lldp-internal.c
+++ b/src/libsystemd-network/lldp-internal.c
@@ -259,7 +259,7 @@ int lldp_mib_update_objects(lldp_chassis *c, tlv_packet *tlv) {
p->until = ttl * USEC_PER_SEC + now(clock_boottime_or_monotonic());
- tlv_packet_free(p->packet);
+ tlv_packet_unref(p->packet);
p->packet = tlv;
prioq_reshuffle(p->c->by_expiry, p, &p->prioq_idx);
@@ -401,7 +401,7 @@ int lldp_mib_add_objects(Prioq *by_expiry,
return 0;
drop:
- tlv_packet_free(tlv);
+ tlv_packet_unref(tlv);
if (new_chassis)
hashmap_remove(neighbour_mib, &c->chassis_id);
@@ -435,7 +435,7 @@ void lldp_neighbour_port_free(lldp_neighbour_port *p) {
if(!p)
return;
- tlv_packet_free(p->packet);
+ tlv_packet_unref(p->packet);
free(p->data);
free(p);
diff --git a/src/libsystemd-network/lldp-tlv.c b/src/libsystemd-network/lldp-tlv.c
index 0cea5b10a6..1370d217f4 100644
--- a/src/libsystemd-network/lldp-tlv.c
+++ b/src/libsystemd-network/lldp-tlv.c
@@ -54,22 +54,41 @@ int tlv_packet_new(tlv_packet **ret) {
return -ENOMEM;
LIST_HEAD_INIT(m->sections);
+ m->n_ref = 1;
*ret = m;
return 0;
}
-void tlv_packet_free(tlv_packet *m) {
+tlv_packet *tlv_packet_ref(tlv_packet *m) {
+
+ if (!m)
+ return NULL;
+
+ assert(m->n_ref > 0);
+ m->n_ref++;
+
+ return m;
+}
+
+tlv_packet *tlv_packet_unref(tlv_packet *m) {
tlv_section *s, *n;
if (!m)
- return;
+ return NULL;
+
+ assert(m->n_ref > 0);
+ m->n_ref--;
+
+ if (m->n_ref > 0)
+ return m;
LIST_FOREACH_SAFE(section, s, n, m->sections)
tlv_section_free(s);
free(m);
+ return NULL;
}
int tlv_packet_append_bytes(tlv_packet *m, const void *data, size_t data_length) {
diff --git a/src/libsystemd-network/lldp-tlv.h b/src/libsystemd-network/lldp-tlv.h
index ce3334e115..f682997031 100644
--- a/src/libsystemd-network/lldp-tlv.h
+++ b/src/libsystemd-network/lldp-tlv.h
@@ -45,6 +45,8 @@ int tlv_section_new(tlv_section **ret);
void tlv_section_free(tlv_section *ret);
struct tlv_packet {
+ unsigned n_ref;
+
uint16_t type;
uint16_t length;
usec_t ts;
@@ -61,10 +63,11 @@ struct tlv_packet {
};
int tlv_packet_new(tlv_packet **ret);
-void tlv_packet_free(tlv_packet *m);
+tlv_packet *tlv_packet_ref(tlv_packet *m);
+tlv_packet *tlv_packet_unref(tlv_packet *m);
-DEFINE_TRIVIAL_CLEANUP_FUNC(tlv_packet*, tlv_packet_free);
-#define _cleanup_tlv_packet_free_ _cleanup_(tlv_packet_freep)
+DEFINE_TRIVIAL_CLEANUP_FUNC(tlv_packet*, tlv_packet_unref);
+#define _cleanup_tlv_packet_free_ _cleanup_(tlv_packet_unrefp)
int lldp_tlv_packet_open_container(tlv_packet *m, uint16_t type);
int lldp_tlv_packet_close_container(tlv_packet *m);
diff --git a/src/libsystemd-network/sd-lldp.c b/src/libsystemd-network/sd-lldp.c
index 17512884f5..53cd19a750 100644
--- a/src/libsystemd-network/sd-lldp.c
+++ b/src/libsystemd-network/sd-lldp.c
@@ -338,7 +338,7 @@ int lldp_handle_packet(tlv_packet *tlv, uint16_t length) {
lldp->statistics.stats_frames_in_errors_total ++;
}
- tlv_packet_free(tlv);
+ tlv_packet_unref(tlv);
return 0;
}