From 9898ac078defbeb73285b90a23bcf5ac344130c0 Mon Sep 17 00:00:00 2001 From: Vincent Date: Sat, 6 Mar 2010 09:41:53 +0100 Subject: [PATCH] Free unused chassis. 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 | 2 +- src/edp.c | 2 +- src/interfaces.c | 4 ++-- src/lldp.c | 2 +- src/lldpd.c | 19 +++++++++++++------ src/lldpd.h | 2 +- src/sonmp.c | 2 +- 7 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/cdp.c b/src/cdp.c index 62d75ae2..0d7c9576 100644 --- 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; } diff --git a/src/edp.c b/src/edp.c index 47f9d81b..810cab67 100644 --- 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; } diff --git a/src/interfaces.c b/src/interfaces.c index 2ba50a20..18a1e302 100644 --- a/src/interfaces.c +++ b/src/interfaces.c @@ -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; diff --git a/src/lldp.c b/src/lldp.c index 1ac88e1b..6fc74933 100644 --- a/src/lldp.c +++ b/src/lldp.c @@ -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; } diff --git a/src/lldpd.c b/src/lldpd.c index 03b793b2..d65d519f 100644 --- a/src/lldpd.c +++ b/src/lldpd.c @@ -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); diff --git a/src/lldpd.h b/src/lldpd.h index aa26938f..96ef8d6f 100644 --- a/src/lldpd.h +++ b/src/lldpd.h @@ -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)); diff --git a/src/sonmp.c b/src/sonmp.c index ed09c77d..c2a9a378 100644 --- a/src/sonmp.c +++ b/src/sonmp.c @@ -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; } -- 2.39.5