datapath: Fix querying the local port by name.
authorBen Pfaff <blp@nicira.com>
Thu, 5 Mar 2009 21:13:30 +0000 (13:13 -0800)
committerBen Pfaff <blp@nicira.com>
Thu, 5 Mar 2009 21:13:30 +0000 (13:13 -0800)
Before, this would return an ENOENT error.

datapath/datapath.c

index 9581e792a176af52b2e094e4cede8cd3c181ea01..85f5a6a62079c07f69c3470988fdfd5ae696cd7b 100644 (file)
@@ -354,6 +354,16 @@ static int new_nbp(struct datapath *dp, struct net_device *dev, int port_no)
        p->dev = dev;
        if (port_no != ODPP_LOCAL)
                rcu_assign_pointer(dev->br_port, p);
+       else {
+               /* For consistency it would make sense to assign dev->br_port
+                * here too, but we can't because that would cause packets
+                * received on the local port to get caught in
+                * dp_frame_hook().  On modern Linux kernels that's not a big
+                * deal--we would just return an appropriate value--but on
+                * Linux 2.4 there's no way for the frame hook to pass along
+                * the skbuff to the rest of the network stack.  So we're
+                * stuck with the status quo. */
+       }
        rcu_assign_pointer(dp->ports[port_no], p);
        list_add_rcu(&p->node, &dp->port_list);
        dp->n_ports++;
@@ -1140,7 +1150,6 @@ query_port(struct datapath *dp, struct odp_port __user *uport)
        if (copy_from_user(&port, uport, sizeof port))
                return -EFAULT;
        if (port.devname[0]) {
-               struct net_bridge_port *p;
                struct net_device *dev;
                int err;
 
@@ -1150,8 +1159,12 @@ query_port(struct datapath *dp, struct odp_port __user *uport)
                if (!dev)
                        return -ENODEV;
 
-               p = dev->br_port;
-               err = p && p->dp == dp ? put_port(p, uport) : -ENOENT;
+               if (dev == dp->ports[ODPP_LOCAL]->dev) {
+                       err = put_port(dp->ports[ODPP_LOCAL], uport);
+               } else {
+                       struct net_bridge_port *p = dev->br_port;
+                       err = p && p->dp == dp ? put_port(p, uport) : -ENOENT;
+               }
                dev_put(dev);
 
                return err;