From 3642294da976cf090755e9df823fd67d0ff86e4d Mon Sep 17 00:00:00 2001 From: Surya Rudra Date: Mon, 21 Oct 2019 12:42:02 +0530 Subject: 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 Signed-off-by: Ben Pfaff --- ofproto/ofproto-dpif.c | 10 +++++----- ofproto/ofproto.c | 3 +++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 7bb0f7bdb..a8c7369d0 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -2280,24 +2280,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 1d6fc0069..6ffaced18 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -2511,6 +2511,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); } -- 2.14.1