datapath: Additional fixes for datapath device renaming.
authorBen Pfaff <blp@nicira.com>
Wed, 19 Aug 2009 19:51:27 +0000 (12:51 -0700)
committerBen Pfaff <blp@nicira.com>
Wed, 19 Aug 2009 20:44:05 +0000 (13:44 -0700)
Commit c874dc6d6b "secchan: Fix behavior when a network device is renamed."
fixed a crash in the datapath when network devices within a datapath were
renamed.  However, this missed the case where the device that was renamed
was a datapath's internal port: these devices have their br_port members
set to NULL, so we have to determine that they belong to a datapath another
way.  This commit does so.

This commit also changes the initialization order in dp_dev_create().
Otherwise, dp_device_event() will dereference null when it is called via
register_netdevice(), because the newly created device is a datapath device
but its members are not yet initialized.

datapath/dp_dev.c
datapath/dp_notify.c

index d11e7f6f756f4880e8dfbef9616c39ea006b028e..b0ba3017a2cdf35d5ec165e49ff63becf1c989c9 100644 (file)
@@ -211,16 +211,17 @@ struct net_device *dp_dev_create(struct datapath *dp, const char *dp_name, int p
        if (!netdev)
                return ERR_PTR(-ENOMEM);
 
+       dp_dev = dp_dev_priv(netdev);
+       dp_dev->dp = dp;
+       dp_dev->port_no = port_no;
+       dp_dev->dev = netdev;
+
        err = register_netdevice(netdev);
        if (err) {
                free_netdev(netdev);
                return ERR_PTR(err);
        }
 
-       dp_dev = dp_dev_priv(netdev);
-       dp_dev->dp = dp;
-       dp_dev->port_no = port_no;
-       dp_dev->dev = netdev;
        return netdev;
 }
 
index f22d8b342f1b1b3d88d19132a2ad88d83feaec56..d5a274981f9ea077ab91b570e3fe35b838bc4c5e 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/netdevice.h>
 
 #include "datapath.h"
-
+#include "dp_dev.h"
 
 static int dp_device_event(struct notifier_block *unused, unsigned long event, 
                void *ptr) 
@@ -20,7 +20,12 @@ static int dp_device_event(struct notifier_block *unused, unsigned long event,
        struct net_bridge_port *p;
        struct datapath *dp;
 
-       p = dev->br_port;
+       if (is_dp_dev(dev)) {
+               struct dp_dev *dp_dev = dp_dev_priv(dev);
+               p = dp_dev->dp->ports[dp_dev->port_no];
+       } else {
+               p = dev->br_port;
+       }
        if (!p)
                return NOTIFY_DONE;
        dp = p->dp;