]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
lldp: add proper ref counting to sd_lldp object and a separate call for setting the...
authorLennart Poettering <lennart@poettering.net>
Thu, 2 Jun 2016 15:45:08 +0000 (17:45 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 6 Jun 2016 17:59:07 +0000 (19:59 +0200)
Let's make sd-lldp a bit more like sd-ndisc ant the other APIs, and add proper
ref counting and a separate call for setting the ifindex.

This also adds a new lldp_reset() call we can use at various places to close
all fds. This is also similar to how sd-ndisc already does it.

src/libsystemd-network/lldp-internal.h
src/libsystemd-network/sd-lldp.c
src/libsystemd-network/test-lldp.c
src/network/networkd-link.c
src/systemd/sd-lldp.h

index 7592bc4305c52fba8cfd27b384d2be26642b7948..becc162fab99bc1daf8db02f6cf586b2fd260ab5 100644 (file)
@@ -28,6 +28,8 @@
 #include "prioq.h"
 
 struct sd_lldp {
+        unsigned n_ref;
+
         int ifindex;
         int fd;
 
index 223a5ac02f0b4a82a3c5c2054d909db3a718b47e..9e9907ca379466cbfb22da0226ba227432837e73 100644 (file)
@@ -234,10 +234,20 @@ static int lldp_receive_datagram(sd_event_source *s, int fd, uint32_t revents, v
         return lldp_handle_datagram(lldp, n);
 }
 
+static void lldp_reset(sd_lldp *lldp) {
+        assert(lldp);
+
+        lldp->timer_event_source = sd_event_source_unref(lldp->timer_event_source);
+        lldp->io_event_source = sd_event_source_unref(lldp->io_event_source);
+        lldp->fd = safe_close(lldp->fd);
+}
+
 _public_ int sd_lldp_start(sd_lldp *lldp) {
         int r;
 
         assert_return(lldp, -EINVAL);
+        assert_return(lldp->event, -EINVAL);
+        assert_return(lldp->ifindex > 0, -EINVAL);
 
         if (lldp->fd >= 0)
                 return 0;
@@ -248,24 +258,21 @@ _public_ int sd_lldp_start(sd_lldp *lldp) {
         if (lldp->fd < 0)
                 return lldp->fd;
 
-        if (lldp->event) {
-                r = sd_event_add_io(lldp->event, &lldp->io_event_source, lldp->fd, EPOLLIN, lldp_receive_datagram, lldp);
-                if (r < 0)
-                        goto fail;
+        r = sd_event_add_io(lldp->event, &lldp->io_event_source, lldp->fd, EPOLLIN, lldp_receive_datagram, lldp);
+        if (r < 0)
+                goto fail;
 
-                r = sd_event_source_set_priority(lldp->io_event_source, lldp->event_priority);
-                if (r < 0)
-                        goto fail;
+        r = sd_event_source_set_priority(lldp->io_event_source, lldp->event_priority);
+        if (r < 0)
+                goto fail;
 
-                (void) sd_event_source_set_description(lldp->io_event_source, "lldp-io");
-        }
+        (void) sd_event_source_set_description(lldp->io_event_source, "lldp-io");
 
+        log_lldp("Started LLDP client");
         return 1;
 
 fail:
-        lldp->io_event_source = sd_event_source_unref(lldp->io_event_source);
-        lldp->fd = safe_close(lldp->fd);
-
+        lldp_reset(lldp);
         return r;
 }
 
@@ -275,10 +282,9 @@ _public_ int sd_lldp_stop(sd_lldp *lldp) {
         if (lldp->fd < 0)
                 return 0;
 
-        lldp->timer_event_source = sd_event_source_unref(lldp->timer_event_source);
-        lldp->io_event_source = sd_event_source_unref(lldp->io_event_source);
-        lldp->fd = safe_close(lldp->fd);
+        log_lldp("Stopping LLDP client");
 
+        lldp_reset(lldp);
         lldp_flush_neighbors(lldp);
 
         return 1;
@@ -322,39 +328,60 @@ _public_ int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *us
         return 0;
 }
 
+_public_ int sd_lldp_set_ifindex(sd_lldp *lldp, int ifindex) {
+        assert_return(lldp, -EINVAL);
+        assert_return(ifindex > 0, -EINVAL);
+        assert_return(lldp->fd < 0, -EBUSY);
+
+        lldp->ifindex = ifindex;
+        return 0;
+}
+
+_public_ sd_lldp* sd_lldp_ref(sd_lldp *lldp) {
+
+        if (!lldp)
+                return NULL;
+
+        assert(lldp->n_ref > 0);
+        lldp->n_ref++;
+
+        return lldp;
+}
+
 _public_ sd_lldp* sd_lldp_unref(sd_lldp *lldp) {
 
         if (!lldp)
                 return NULL;
 
+        assert(lldp->n_ref > 0);
+        lldp->n_ref --;
+
+        if (lldp->n_ref > 0)
+                return NULL;
+
+        lldp_reset(lldp);
+        sd_lldp_detach_event(lldp);
         lldp_flush_neighbors(lldp);
 
         hashmap_free(lldp->neighbor_by_id);
         prioq_free(lldp->neighbor_by_expiry);
-
-        sd_event_source_unref(lldp->io_event_source);
-        sd_event_source_unref(lldp->timer_event_source);
-        sd_event_unref(lldp->event);
-        safe_close(lldp->fd);
-
         free(lldp);
 
         return NULL;
 }
 
-_public_ int sd_lldp_new(sd_lldp **ret, int ifindex) {
+_public_ int sd_lldp_new(sd_lldp **ret) {
         _cleanup_(sd_lldp_unrefp) sd_lldp *lldp = NULL;
         int r;
 
         assert_return(ret, -EINVAL);
-        assert_return(ifindex > 0, -EINVAL);
 
         lldp = new0(sd_lldp, 1);
         if (!lldp)
                 return -ENOMEM;
 
+        lldp->n_ref = 1;
         lldp->fd = -1;
-        lldp->ifindex = ifindex;
         lldp->neighbors_max = LLDP_DEFAULT_NEIGHBORS_MAX;
         lldp->capability_mask = (uint16_t) -1;
 
index 1aae2253c071b2ee5e97af184032f6f6d0b0f25f..6bcd65de0afe243ae0830fffbd80b08566604c4b 100644 (file)
@@ -54,11 +54,11 @@ static void lldp_handler(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n
 static int start_lldp(sd_lldp **lldp, sd_event *e, sd_lldp_callback_t cb, void *cb_data) {
         int r;
 
-        r = sd_lldp_new(lldp, 42);
+        r = sd_lldp_new(lldp);
         if (r < 0)
                 return r;
 
-        r = sd_lldp_attach_event(*lldp, e, 0);
+        r = sd_lldp_set_ifindex(*lldp, 42);
         if (r < 0)
                 return r;
 
@@ -66,6 +66,10 @@ static int start_lldp(sd_lldp **lldp, sd_event *e, sd_lldp_callback_t cb, void *
         if (r < 0)
                 return r;
 
+        r = sd_lldp_attach_event(*lldp, e, 0);
+        if (r < 0)
+                return r;
+
         r = sd_lldp_start(*lldp);
         if (r < 0)
                 return r;
index ee52b1ce1e1fce827b3a6857fea7548cb8b6bde5..90ed55d42ca68ea71847bc9826488fcbcd83f566 100644 (file)
@@ -2364,7 +2364,11 @@ static int link_configure(Link *link) {
         }
 
         if (link_lldp_rx_enabled(link)) {
-                r = sd_lldp_new(&link->lldp, link->ifindex);
+                r = sd_lldp_new(&link->lldp);
+                if (r < 0)
+                        return r;
+
+                r = sd_lldp_set_ifindex(link->lldp, link->ifindex);
                 if (r < 0)
                         return r;
 
index 617e0f1e17becda86f4dbc493473d62efdea8f92..8f096c1b99aa3886bcf4ff0a65e9543e0c5d057c 100644 (file)
@@ -30,9 +30,6 @@
 
 _SD_BEGIN_DECLARATIONS;
 
-typedef struct sd_lldp sd_lldp;
-typedef struct sd_lldp_neighbor sd_lldp_neighbor;
-
 /* IEEE 802.3AB Clause 9: TLV Types */
 enum {
         SD_LLDP_TYPE_END                 = 0,
@@ -111,6 +108,9 @@ enum {
         SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION      = 7,
 };
 
+typedef struct sd_lldp sd_lldp;
+typedef struct sd_lldp_neighbor sd_lldp_neighbor;
+
 typedef enum sd_lldp_event {
         SD_LLDP_EVENT_ADDED     = 'a',
         SD_LLDP_EVENT_REMOVED   = 'r',
@@ -120,7 +120,8 @@ typedef enum sd_lldp_event {
 
 typedef void (*sd_lldp_callback_t)(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata);
 
-int sd_lldp_new(sd_lldp **ret, int ifindex);
+int sd_lldp_new(sd_lldp **ret);
+sd_lldp* sd_lldp_ref(sd_lldp *lldp);
 sd_lldp* sd_lldp_unref(sd_lldp *lldp);
 
 int sd_lldp_start(sd_lldp *lldp);
@@ -130,6 +131,7 @@ int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int64_t priority);
 int sd_lldp_detach_event(sd_lldp *lldp);
 
 int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *userdata);
+int sd_lldp_set_ifindex(sd_lldp *lldp, int ifindex);
 
 /* Controls how much and what to store in the neighbors database */
 int sd_lldp_set_neighbors_max(sd_lldp *lldp, uint64_t n);