]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
Free unused chassis.
authorVincent <bernat@luffy.cx>
Sat, 6 Mar 2010 08:41:53 +0000 (09:41 +0100)
committerVincent <bernat@luffy.cx>
Sat, 6 Mar 2010 09:24:20 +0000 (10:24 +0100)
When reference count for a chassis drops to 0, we free the chassis.
This cannot happen to the local chassis because a reference should be
held to it even without any local port.

src/cdp.c
src/edp.c
src/interfaces.c
src/lldp.c
src/lldpd.c
src/lldpd.h
src/sonmp.c

index 62d75ae289eb8dceddfc59a99a991d8cc2cbbdc6..0d7c9576547a884051c34e1e66e8e8fd1dbce3e4 100644 (file)
--- a/src/cdp.c
+++ b/src/cdp.c
@@ -465,7 +465,7 @@ cdp_decode(struct lldpd *cfg, char *frame, int s,
 
 malformed:
        lldpd_chassis_cleanup(chassis, 1);
-       lldpd_port_cleanup(port, 1);
+       lldpd_port_cleanup(cfg, port, 1);
        free(port);
        return -1;
 }
index 47f9d81b8d80fafd7df5a9e347ec40bd0b6175db..810cab673efa8a35006ffb7cb67c0e7300b2fc75 100644 (file)
--- a/src/edp.c
+++ b/src/edp.c
@@ -485,7 +485,7 @@ edp_decode(struct lldpd *cfg, char *frame, int s,
 
 malformed:
        lldpd_chassis_cleanup(chassis, 1);
-       lldpd_port_cleanup(port, 1);
+       lldpd_port_cleanup(cfg, port, 1);
        free(port);
        return -1;
 }
index 2ba50a20c5bca388257d5e62d09368845d85ff31..18a1e302bb4072c5295445bc9556d3ca1ac43f7a 100644 (file)
@@ -710,7 +710,7 @@ lldpd_ifh_eth(struct lldpd *cfg, struct ifaddrs *ifap)
                        TAILQ_INSERT_TAIL(&cfg->g_hardware, hardware, h_entries);
                } else {
                        if (hardware->h_flags) continue; /* Already seen this time */
-                       lldpd_port_cleanup(&hardware->h_lport, 0);
+                       lldpd_port_cleanup(cfg, &hardware->h_lport, 0);
                }
 
                port = &hardware->h_lport;
@@ -894,7 +894,7 @@ lldpd_ifh_bond(struct lldpd *cfg, struct ifaddrs *ifap)
                        if (hardware->h_flags) continue; /* Already seen this time */
                        memset(hardware->h_data, 0, IFNAMSIZ);
                        if_indextoname(master, hardware->h_data);
-                       lldpd_port_cleanup(&hardware->h_lport, 0);
+                       lldpd_port_cleanup(cfg, &hardware->h_lport, 0);
                }
                
                port = &hardware->h_lport;
index 1ac88e1ba65737a248f746cdb366260bbcb4e7e0..6fc74933a4cc55fb53284ed82db41b984dcfb9d8 100644 (file)
@@ -784,7 +784,7 @@ lldp_decode(struct lldpd *cfg, char *frame, int s,
        return 1;
 malformed:
        lldpd_chassis_cleanup(chassis, 1);
-       lldpd_port_cleanup(port, 1);
+       lldpd_port_cleanup(cfg, port, 1);
        free(port);
        return -1;
 }
index 03b793b290a902adb61d3c0af2757b39fbb74add..d65d519f1b1d0fd674ccdf69377f21ac4392806b 100644 (file)
@@ -158,7 +158,7 @@ lldpd_vlan_cleanup(struct lldpd_port *port)
 /* If `all' is true, clear all information, including information that
    are not refreshed periodically. Port should be freed manually. */
 void
-lldpd_port_cleanup(struct lldpd_port *port, int all)
+lldpd_port_cleanup(struct lldpd *cfg, struct lldpd_port *port, int all)
 {
 #ifdef ENABLE_LLDPMED
        int i;
@@ -173,8 +173,15 @@ lldpd_port_cleanup(struct lldpd_port *port, int all)
        free(port->p_descr);
        if (all) {
                free(port->p_lastframe);
-               if (port->p_chassis) /* chassis may not have been attributed, yet */
+               if (port->p_chassis) /* chassis may not have been attributed, yet */
                        port->p_chassis->c_refcount--;
+                       if (port->p_chassis->c_refcount == 0) {
+                               /* This is the last port referencing this chassis */
+                               TAILQ_REMOVE(&cfg->g_chassis, port->p_chassis, c_entries);
+                               lldpd_chassis_cleanup(port->p_chassis, 1);
+                       }
+                       port->p_chassis = NULL;
+               }
        }
 }
 
@@ -214,7 +221,7 @@ lldpd_remote_cleanup(struct lldpd *cfg, struct lldpd_hardware *hardware, int all
                }
                if (del) {
                        TAILQ_REMOVE(&hardware->h_rports, port, p_entries);
-                       lldpd_port_cleanup(port, 1);
+                       lldpd_port_cleanup(cfg, port, 1);
                        free(port);
                }
        }
@@ -224,7 +231,7 @@ void
 lldpd_hardware_cleanup(struct lldpd *cfg, struct lldpd_hardware *hardware)
 {
        int i;
-       lldpd_port_cleanup(&hardware->h_lport, 1);
+       lldpd_port_cleanup(cfg, &hardware->h_lport, 1);
        /* If we have a dedicated cleanup function, use it. Otherwise,
           we just free the hardware-dependent data and close all FD
           in h_recvfds and h_sendfd. */
@@ -348,7 +355,7 @@ lldpd_decode(struct lldpd *cfg, char *frame, int s,
        if (oport) {
                /* The port is known, remove it before adding it back */
                TAILQ_REMOVE(&hardware->h_rports, oport, p_entries);
-               lldpd_port_cleanup(oport, 1);
+               lldpd_port_cleanup(cfg, oport, 1);
                free(oport);
        }
        if (ochassis) {
@@ -902,7 +909,7 @@ lldpd_main(int argc, char *argv[])
        TAILQ_INIT(&cfg->g_hardware);
        TAILQ_INIT(&cfg->g_chassis);
        TAILQ_INSERT_TAIL(&cfg->g_chassis, lchassis, c_entries);
-       lchassis->c_refcount++;
+       lchassis->c_refcount++; /* We should always keep a reference to local chassis */
 
        TAILQ_INIT(&cfg->g_callbacks);
 
index aa26938f520ab85acc21377c39bb5d226a8587fb..96ef8d6fb1c1a2d919fef12fb126efbec9f25274 100644 (file)
@@ -345,7 +345,7 @@ void         lldpd_hardware_cleanup(struct lldpd*, struct lldpd_hardware *);
 void    lldpd_vlan_cleanup(struct lldpd_port *);
 #endif
 void    lldpd_remote_cleanup(struct lldpd *, struct lldpd_hardware *, int);
-void    lldpd_port_cleanup(struct lldpd_port *, int);
+void    lldpd_port_cleanup(struct lldpd*, struct lldpd_port *, int);
 void    lldpd_chassis_cleanup(struct lldpd_chassis *, int);
 int     lldpd_callback_add(struct lldpd *, int, void(*fn)(CALLBACK_SIG), void *);
 void    lldpd_callback_del(struct lldpd *, int, void(*fn)(CALLBACK_SIG));
index ed09c77d9c875edf910f6ebe0a07d5883f7717ea..c2a9a3784941ad3239a3b161c05ac38366711b3a 100644 (file)
@@ -377,7 +377,7 @@ sonmp_decode(struct lldpd *cfg, char *frame, int s,
 
 malformed:
        lldpd_chassis_cleanup(chassis, 1);
-       lldpd_port_cleanup(port, 1);
+       lldpd_port_cleanup(cfg, port, 1);
        free(port);
        return -1;
 }