summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSurya Rudra <rudrasurya.r@altencalsoftlabs.com>2019-10-21 12:42:02 +0530
committerBen Pfaff <blp@ovn.org>2019-10-24 12:58:18 -0700
commit6791d2a23e2bd4d301f6a31d0140626e430778f6 (patch)
treef44bf0e222665bb0e6ba7d035e3cc892f2105472
parent4eb9b83971f77df3b46c72f495567ac7233f1dff (diff)
downloadopenvswitch-6791d2a23e2bd4d301f6a31d0140626e430778f6.tar.gz
lldp: Fix for OVS crashes when a LLDP-enabled port is deleted
Issue: When LLDP is enabled on a port, a structure to hold LLDP related state is created and that structure has a reference to the port. The ofproto monitor thread accesses the LLDP structure to periodically send packets over the associated port. When the port is deleted, the LLDP structure is not cleaned up and it continues to refer to the deleted port. When the monitor thread attempts to access the deleted port OVS crashes. Crash can happen with bridge delete and bond delete also. Fix: Remove all references to the LLDP structure and free it when the port is deleted. Signed-off-by: Surya Rudra <rudrasurya.r@altencalsoftlabs.com> Signed-off-by: Ben Pfaff <blp@ovn.org>
-rw-r--r--ofproto/ofproto-dpif.c10
-rw-r--r--ofproto/ofproto.c3
2 files changed, 8 insertions, 5 deletions
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 4c37fbb7c..0a1714d02 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -1974,24 +1974,24 @@ set_lldp(struct ofport *ofport_,
const struct smap *cfg)
{
struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
+ struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
int error = 0;
if (cfg) {
if (!ofport->lldp) {
- struct ofproto_dpif *ofproto;
-
- ofproto = ofproto_dpif_cast(ofport->up.ofproto);
ofproto->backer->need_revalidate = REV_RECONFIGURE;
ofport->lldp = lldp_create(ofport->up.netdev, ofport_->mtu, cfg);
}
if (!lldp_configure(ofport->lldp, cfg)) {
+ lldp_unref(ofport->lldp);
+ ofport->lldp = NULL;
error = EINVAL;
}
- }
- if (error) {
+ } else if (ofport->lldp) {
lldp_unref(ofport->lldp);
ofport->lldp = NULL;
+ ofproto->backer->need_revalidate = REV_RECONFIGURE;
}
ofproto_dpif_monitor_port_update(ofport,
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 00afaf7e8..c3e22742c 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -2486,6 +2486,9 @@ ofproto_port_unregister(struct ofproto *ofproto, ofp_port_t ofp_port)
{
struct ofport *port = ofproto_get_port(ofproto, ofp_port);
if (port) {
+ if (port->ofproto->ofproto_class->set_lldp) {
+ port->ofproto->ofproto_class->set_lldp(port, NULL);
+ }
if (port->ofproto->ofproto_class->set_stp_port) {
port->ofproto->ofproto_class->set_stp_port(port, NULL);
}