ofproto: Call port_modified before closing old netdev in update_port().
authorBen Pfaff <blp@nicira.com>
Fri, 13 May 2011 16:14:18 +0000 (09:14 -0700)
committerBen Pfaff <blp@nicira.com>
Fri, 13 May 2011 16:14:18 +0000 (09:14 -0700)
Fixes a segmentation fault due to update_port() -> port_modified() ->
bond_slave_set_netdev() -> netdev_monitor_remove() -> netdev_get_name().

Reported-by: Michael MAO <mmao@nicira.com>
ofproto/ofproto.c

index f21731011c58cedfdde37f2719d0ba58f07202ad..46e7c1fd70d2ded9b8e0eb796c2bf3bcec6ad14f 100644 (file)
@@ -1169,21 +1169,25 @@ update_port(struct ofproto *ofproto, const char *name)
     if (netdev) {
         port = ofproto_get_port(ofproto, ofproto_port.ofp_port);
         if (port && !strcmp(netdev_get_name(port->netdev), name)) {
+            struct netdev *old_netdev = port->netdev;
+
             /* 'name' hasn't changed location.  Any properties changed? */
             if (!ofport_equal(&port->opp, &opp)) {
                 ofport_modified(port, &opp);
             }
 
-            /* Install the newly opened netdev in case it has changed. */
+            /* Install the newly opened netdev in case it has changed.
+             * Don't close the old netdev yet in case port_modified has to
+             * remove a retained reference to it.*/
             netdev_monitor_remove(ofproto->netdev_monitor, port->netdev);
             netdev_monitor_add(ofproto->netdev_monitor, netdev);
-
-            netdev_close(port->netdev);
             port->netdev = netdev;
 
             if (port->ofproto->ofproto_class->port_modified) {
                 port->ofproto->ofproto_class->port_modified(port);
             }
+
+            netdev_close(old_netdev);
         } else {
             /* If 'port' is nonnull then its name differs from 'name' and thus
              * we should delete it.  If we think there's a port named 'name'