On Wed, Dec 11, 2013 at 05:55:35PM -0800, Ben Pfaff wrote:
> On Wed, Dec 11, 2013 at 04:09:57PM -0800, Jarno Rajahalme wrote:
> > 
> > On Dec 11, 2013, at 3:14 PM, Ben Pfaff <b...@nicira.com> wrote:
> > 
> > > On Wed, Dec 11, 2013 at 02:17:13PM -0800, Jarno Rajahalme wrote:
> > >> While testing the code I accidentally requested a change in the 
> > >> interface type (to dummy), like this:
> > >> 
> > >> # ovs-vsctl add-br br0
> > >> # ovs-vsctl add-port br0 p1 -- set Interface p1 type=internal
> > >> # ovs-vsctl -- set Interface p1 type=dummy
> > >> 
> > >> Running OVS without dummy enabled seg faults:
> > > 
> > > I couldn't reproduce this, can you try to get me a backtrace or run
> > > under valgrind?
> > 
> 
> [...]
> 
> > ==33664== Invalid read of size 2
> > ==33664==    at 0x40A1C2: bridge_reconfigure (bridge.c:1568)
> > ==33664==    by 0x406BAC: bridge_run (bridge.c:2289)
> > ==33664==    by 0x40E498: main (ovs-vswitchd.c:118)
> > ==33664==  Address 0x48 is not stack'd, malloc'd or (recently) free'd
> 
> [...]
> 
> > The offending line is:
> > 
> >             if (iface->ofp_port == OFPP_LOCAL) {
> > 
> > Seems like iface is NULL (if offset of odp_port == 0x48) in this case.
> 
> Thanks.
> 
> I figured out how to reproduce it.
> 
> I folded this in and it fixes the problem for me.  For you too?
> 
> diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
> index ed16860..5dd7752 100644
> --- a/vswitchd/bridge.c
> +++ b/vswitchd/bridge.c
> @@ -653,6 +653,7 @@ bridge_delete_or_reconfigure_ports(struct bridge *br)
>  
>      OFPROTO_PORT_FOR_EACH (&ofproto_port, &dump, br->ofproto) {
>          struct iface *iface;
> +        struct port *port;
>  
>          iface = iface_lookup(br, ofproto_port.name);
>          if (!iface) {
> @@ -679,7 +680,11 @@ bridge_delete_or_reconfigure_ports(struct bridge *br)
>          continue;
>  
>      delete:
> +        port = iface->port;
>          iface_destroy(iface);
> +        if (list_is_empty(&port->ifaces)) {
> +            port_destroy(port);
> +        }
>          del = add_ofp_port(ofproto_port.ofp_port, del, &n, &allocated);
>      }
>  
> @@ -3102,7 +3107,12 @@ port_del_ifaces(struct port *port)
>      /* Get rid of deleted interfaces. */
>      LIST_FOR_EACH_SAFE (iface, next, port_elem, &port->ifaces) {
>          if (!sset_contains(&new_ifaces, iface->name)) {
> +            struct port *port = iface->port;
> +
>              iface_destroy(iface);
> +            if (list_is_empty(&port->ifaces)) {
> +                port_destroy(port);
> +            }
>          }
>      }
>  

But introduced a new segfault because 'iface' could be null in the first
case.  I folded in the following additional patch as a combined fix and
cleanup.

diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index 8267636..37f5812 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -657,7 +657,6 @@ bridge_delete_or_reconfigure_ports(struct bridge *br)
     OFPROTO_PORT_FOR_EACH (&ofproto_port, &dump, br->ofproto) {
         ofp_port_t requested_ofp_port;
         struct iface *iface;
-        struct port *port;
 
         iface = iface_lookup(br, ofproto_port.name);
         if (!iface) {
@@ -721,11 +720,7 @@ bridge_delete_or_reconfigure_ports(struct bridge *br)
         continue;
 
     delete:
-        port = iface->port;
         iface_destroy(iface);
-        if (list_is_empty(&port->ifaces)) {
-            port_destroy(port);
-        }
         del = add_ofp_port(ofproto_port.ofp_port, del, &n, &allocated);
     }
 
@@ -3131,6 +3126,8 @@ bridge_configure_dp_desc(struct bridge *br)
 
 /* Port functions. */
 
+static void iface_destroy__(struct iface *);
+
 static struct port *
 port_create(struct bridge *br, const struct ovsrec_port *cfg)
 {
@@ -3167,12 +3164,7 @@ port_del_ifaces(struct port *port)
     /* Get rid of deleted interfaces. */
     LIST_FOR_EACH_SAFE (iface, next, port_elem, &port->ifaces) {
         if (!sset_contains(&new_ifaces, iface->name)) {
-            struct port *port = iface->port;
-
             iface_destroy(iface);
-            if (list_is_empty(&port->ifaces)) {
-                port_destroy(port);
-            }
         }
     }
 
@@ -3191,7 +3183,7 @@ port_destroy(struct port *port)
         }
 
         LIST_FOR_EACH_SAFE (iface, next, port_elem, &port->ifaces) {
-            iface_destroy(iface);
+            iface_destroy__(iface);
         }
 
         hmap_remove(&br->ports, &port->hmap_node);
@@ -3413,7 +3405,7 @@ iface_get_type(const struct ovsrec_interface *iface,
 }
 
 static void
-iface_destroy(struct iface *iface)
+iface_destroy__(struct iface *iface)
 {
     if (iface) {
         struct port *port = iface->port;
@@ -3437,6 +3429,19 @@ iface_destroy(struct iface *iface)
     }
 }
 
+static void
+iface_destroy(struct iface *iface)
+{
+    if (iface) {
+        struct port *port = iface->port;
+
+        iface_destroy__(iface);
+        if (list_is_empty(&port->ifaces)) {
+            port_destroy(port);
+        }
+    }
+}
+
 static struct iface *
 iface_lookup(const struct bridge *br, const char *name)
 {
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to