79 lines
2.7 KiB
Diff
79 lines
2.7 KiB
Diff
|
|
From 3642294da976cf090755e9df823fd67d0ff86e4d Mon Sep 17 00:00:00 2001
|
||
|
|
From: Surya Rudra <rudrasurya.r@altencalsoftlabs.com>
|
||
|
|
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 <rudrasurya.r@altencalsoftlabs.com>
|
||
|
|
Signed-off-by: Ben Pfaff <blp@ovn.org>
|
||
|
|
---
|
||
|
|
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
|
||
|
|
|
||
|
|
|