]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
Remove unused chassis in lldpd_cleanup() instead of lldpd_port_cleanup().
authorVincent Bernat <bernat@luffy.cx>
Fri, 12 Mar 2010 16:12:52 +0000 (17:12 +0100)
committerVincent Bernat <bernat@luffy.cx>
Fri, 12 Mar 2010 16:12:52 +0000 (17:12 +0100)
In some cases, lldpd_port_cleanup() is called when a reference to the
chassis that will be removed is hold for updating. This happens when
we need to update the information on a chassis known by only one port:
 1. we find that the chassis is still the same
 2. we remove the port and hence remove the chassis which becomes
    unused and freed
 3. with the previous reference to the chassis, we try to update it
    with new information while it has been freed.

Freeing in lldpd_cleanup() is more natural and less risky.

src/lldpd.c

index 98f2770800b6d90682e5aa31e26b2f5ff6ded379..02ff304a17371047b068ca8a2ab38a2aa9bdcdac 100644 (file)
@@ -180,11 +180,6 @@ lldpd_port_cleanup(struct lldpd *cfg, struct lldpd_port *port, int all)
                free(port->p_lastframe);
                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;
                }
        }
@@ -256,6 +251,7 @@ static void
 lldpd_cleanup(struct lldpd *cfg)
 {
        struct lldpd_hardware *hardware, *hardware_next;
+       struct lldpd_chassis *chassis, *chassis_next;
 
        for (hardware = TAILQ_FIRST(&cfg->g_hardware); hardware != NULL;
             hardware = hardware_next) {
@@ -267,6 +263,15 @@ lldpd_cleanup(struct lldpd *cfg)
                } else
                        lldpd_remote_cleanup(cfg, hardware, 0);
        }
+
+       for (chassis = TAILQ_FIRST(&cfg->g_chassis); chassis;
+            chassis = chassis_next) {
+               chassis_next = TAILQ_NEXT(chassis, c_entries);
+               if (chassis->c_refcount == 0) {
+                       TAILQ_REMOVE(&cfg->g_chassis, chassis, c_entries);
+                       lldpd_chassis_cleanup(chassis, 1);
+               }
+       }
 }
 
 static int