]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
lldp: add reference counter to struct tlv_packet
authorBeniamino Galvani <bgalvani@redhat.com>
Sun, 21 Jun 2015 18:27:04 +0000 (20:27 +0200)
committerBeniamino Galvani <bgalvani@redhat.com>
Fri, 2 Oct 2015 15:11:40 +0000 (17:11 +0200)
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.

src/libsystemd-network/lldp-internal.c
src/libsystemd-network/lldp-tlv.c
src/libsystemd-network/lldp-tlv.h
src/libsystemd-network/sd-lldp.c

index 3c04898e92885f473f76b33732793b1ea1f5e23f..2906b5a4b65ba3bcc21e9533de4eb53057891f7c 100644 (file)
@@ -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);
index 0cea5b10a6ef791614fb361fc036e6365b8ddb05..1370d217f4cfe54a087d8228b22d038893a84008 100644 (file)
@@ -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) {
index ce3334e1157e4f007854ff936904ee3f6b82623d..f682997031f97a7fc8a872ccc49a1b62374e9cc7 100644 (file)
@@ -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);
index 17512884f555cfaa2deaaea0b74be276e75a94c8..53cd19a750ddfe96a848ca1a44f364734ca1e120 100644 (file)
@@ -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;
 }