From: Ben Pfaff Date: Wed, 19 Aug 2009 19:51:27 +0000 (-0700) Subject: datapath: Additional fixes for datapath device renaming. X-Git-Tag: v0.90.5~30 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=b78a7336a3318a3c348004760bac3e0057b9e9d1;p=sliver-openvswitch.git datapath: Additional fixes for datapath device renaming. 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. --- diff --git a/datapath/dp_dev.c b/datapath/dp_dev.c index d11e7f6f7..b0ba3017a 100644 --- a/datapath/dp_dev.c +++ b/datapath/dp_dev.c @@ -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; } diff --git a/datapath/dp_notify.c b/datapath/dp_notify.c index f22d8b342..d5a274981 100644 --- a/datapath/dp_notify.c +++ b/datapath/dp_notify.c @@ -11,7 +11,7 @@ #include #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;