Merge branch 'master' into next
[sliver-openvswitch.git] / datapath / datapath.c
index e62eaea..6a3b9ec 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2008, 2009 Nicira Networks.
+ * Copyright (c) 2007, 2008, 2009, 2010 Nicira Networks.
  * Distributed under the terms of the GNU GPL version 2.
  *
  * Significant portions of this file may be copied from parts of the Linux
 int (*dp_ioctl_hook)(struct net_device *dev, struct ifreq *rq, int cmd);
 EXPORT_SYMBOL(dp_ioctl_hook);
 
-int (*dp_add_dp_hook)(struct datapath *dp);
-EXPORT_SYMBOL(dp_add_dp_hook);
-
-int (*dp_del_dp_hook)(struct datapath *dp);
-EXPORT_SYMBOL(dp_del_dp_hook);
-
-int (*dp_add_if_hook)(struct net_bridge_port *p);
-EXPORT_SYMBOL(dp_add_if_hook);
-
-int (*dp_del_if_hook)(struct net_bridge_port *p);
-EXPORT_SYMBOL(dp_del_if_hook);
-
 /* Datapaths.  Protected on the read side by rcu_read_lock, on the write side
- * by dp_mutex.  dp_mutex is almost completely redundant with genl_mutex
- * maintained by the Generic Netlink code, but the timeout path needs mutual
- * exclusion too.
+ * by dp_mutex.
  *
  * dp_mutex nests inside the RTNL lock: if you need both you must take the RTNL
  * lock first.
@@ -184,6 +170,16 @@ errout:
                rtnl_set_sk_err(net, RTNLGRP_LINK, err);
 }
 
+static void release_dp(struct kobject *kobj)
+{
+       struct datapath *dp = container_of(kobj, struct datapath, ifobj);
+       kfree(dp);
+}
+
+struct kobj_type dp_ktype = {
+       .release = release_dp
+};
+
 static int create_dp(int dp_idx, const char __user *devnamep)
 {
        struct net_device *dp_dev;
@@ -218,28 +214,35 @@ static int create_dp(int dp_idx, const char __user *devnamep)
        dp = kzalloc(sizeof *dp, GFP_KERNEL);
        if (dp == NULL)
                goto err_put_module;
-
+       INIT_LIST_HEAD(&dp->port_list);
        mutex_init(&dp->mutex);
        dp->dp_idx = dp_idx;
        for (i = 0; i < DP_N_QUEUES; i++)
                skb_queue_head_init(&dp->queues[i]);
        init_waitqueue_head(&dp->waitqueue);
 
-       /* Setup our datapath device */
-       dp_dev = dp_dev_create(dp, devname, ODPP_LOCAL);
-       err = PTR_ERR(dp_dev);
-       if (IS_ERR(dp_dev))
-               goto err_free_dp;
+       /* Initialize kobject for bridge.  This will be added as
+        * /sys/class/net/<devname>/brif later, if sysfs is enabled. */
+       dp->ifobj.kset = NULL;
+       kobject_init(&dp->ifobj, &dp_ktype);
 
+       /* Allocate table. */
        err = -ENOMEM;
        rcu_assign_pointer(dp->table, dp_table_create(DP_L1_SIZE));
        if (!dp->table)
-               goto err_destroy_dp_dev;
-       INIT_LIST_HEAD(&dp->port_list);
+               goto err_free_dp;
+
+       /* Set up our datapath device. */
+       dp_dev = dp_dev_create(dp, devname, ODPP_LOCAL);
+       err = PTR_ERR(dp_dev);
+       if (IS_ERR(dp_dev))
+               goto err_destroy_table;
 
        err = new_nbp(dp, dp_dev, ODPP_LOCAL);
-       if (err)
+       if (err) {
+               dp_dev_destroy(dp_dev);
                goto err_destroy_table;
+       }
 
        dp->drop_frags = 0;
        dp->stats_percpu = alloc_percpu(struct dp_stats_percpu);
@@ -250,17 +253,14 @@ static int create_dp(int dp_idx, const char __user *devnamep)
        mutex_unlock(&dp_mutex);
        rtnl_unlock();
 
-       if (dp_add_dp_hook)
-               dp_add_dp_hook(dp);
+       dp_sysfs_add_dp(dp);
 
        return 0;
 
 err_destroy_local_port:
-       dp_del_port(dp->ports[ODPP_LOCAL], NULL);
+       dp_del_port(dp->ports[ODPP_LOCAL]);
 err_destroy_table:
        dp_table_destroy(dp->table, 0);
-err_destroy_dp_dev:
-       dp_dev_destroy(dp_dev);
 err_free_dp:
        kfree(dp);
 err_put_module:
@@ -272,37 +272,35 @@ err:
        return err;
 }
 
-static void do_destroy_dp(struct datapath *dp, struct list_head *dp_devs)
+static void do_destroy_dp(struct datapath *dp)
 {
        struct net_bridge_port *p, *n;
        int i;
 
-       if (dp_del_dp_hook)
-               dp_del_dp_hook(dp);
-
-       /* Drop references to DP. */
        list_for_each_entry_safe (p, n, &dp->port_list, node)
-               dp_del_port(p, dp_devs);
+               if (p->port_no != ODPP_LOCAL)
+                       dp_del_port(p);
+
+       dp_sysfs_del_dp(dp);
 
        rcu_assign_pointer(dps[dp->dp_idx], NULL);
 
-       /* Wait until no longer in use, then destroy it. */
-       synchronize_rcu();
+       dp_del_port(dp->ports[ODPP_LOCAL]);
+
        dp_table_destroy(dp->table, 1);
+
        for (i = 0; i < DP_N_QUEUES; i++)
                skb_queue_purge(&dp->queues[i]);
        for (i = 0; i < DP_MAX_GROUPS; i++)
                kfree(dp->groups[i]);
        free_percpu(dp->stats_percpu);
-       kfree(dp);
+       kobject_put(&dp->ifobj);
        module_put(THIS_MODULE);
 }
 
 static int destroy_dp(int dp_idx)
 {
-       struct dp_dev *dp_dev, *next;
        struct datapath *dp;
-       LIST_HEAD(dp_devs);
        int err;
 
        rtnl_lock();
@@ -312,17 +310,28 @@ static int destroy_dp(int dp_idx)
        if (!dp)
                goto err_unlock;
 
-       do_destroy_dp(dp, &dp_devs);
+       do_destroy_dp(dp);
        err = 0;
 
 err_unlock:
        mutex_unlock(&dp_mutex);
        rtnl_unlock();
-       list_for_each_entry_safe (dp_dev, next, &dp_devs, list)
-               free_netdev(dp_dev->dev);
        return err;
 }
 
+static void release_nbp(struct kobject *kobj)
+{
+       struct net_bridge_port *p = container_of(kobj, struct net_bridge_port, kobj);
+       kfree(p);
+}
+
+struct kobj_type brport_ktype = {
+#ifdef CONFIG_SYSFS
+       .sysfs_ops = &brport_sysfs_ops,
+#endif
+       .release = release_nbp
+};
+
 /* Called with RTNL lock and dp_mutex. */
 static int new_nbp(struct datapath *dp, struct net_device *dev, int port_no)
 {
@@ -340,6 +349,7 @@ static int new_nbp(struct datapath *dp, struct net_device *dev, int port_no)
        p->port_no = port_no;
        p->dp = dp;
        p->dev = dev;
+       atomic_set(&p->sflow_pool, 0);
        if (!is_dp_dev(dev))
                rcu_assign_pointer(dev->br_port, p);
        else {
@@ -352,6 +362,11 @@ static int new_nbp(struct datapath *dp, struct net_device *dev, int port_no)
        list_add_rcu(&p->node, &dp->port_list);
        dp->n_ports++;
 
+       /* Initialize kobject for bridge.  This will be added as
+        * /sys/class/net/<devname>/brport later, if sysfs is enabled. */
+       p->kobj.kset = NULL;
+       kobject_init(&p->kobj, &brport_ktype);
+
        dp_ifinfo_notify(RTM_NEWLINK, p);
 
        return 0;
@@ -369,11 +384,6 @@ static int add_port(int dp_idx, struct odp_port __user *portp)
        if (copy_from_user(&port, portp, sizeof port))
                goto out;
        port.devname[IFNAMSIZ - 1] = '\0';
-       port_no = port.port;
-
-       err = -EINVAL;
-       if (port_no < 0 || port_no >= DP_MAX_PORTS)
-               goto out;
 
        rtnl_lock();
        dp = get_dp_locked(dp_idx);
@@ -381,10 +391,13 @@ static int add_port(int dp_idx, struct odp_port __user *portp)
        if (!dp)
                goto out_unlock_rtnl;
 
-       err = -EEXIST;
-       if (dp->ports[port_no])
-               goto out_unlock_dp;
+       for (port_no = 1; port_no < DP_MAX_PORTS; port_no++)
+               if (!dp->ports[port_no])
+                       goto got_port_no;
+       err = -EFBIG;
+       goto out_unlock_dp;
 
+got_port_no:
        if (!(port.flags & ODP_PORT_INTERNAL)) {
                err = -ENODEV;
                dev = dev_get_by_name(&init_net, port.devname);
@@ -407,8 +420,10 @@ static int add_port(int dp_idx, struct odp_port __user *portp)
        if (err)
                goto out_put;
 
-       if (dp_add_if_hook)
-               dp_add_if_hook(dp->ports[port_no]);
+       set_dp_devs_mtu(dp, dev);
+       dp_sysfs_add_if(dp->ports[port_no]);
+
+       err = __put_user(port_no, &port.port);
 
 out_put:
        dev_put(dev);
@@ -420,17 +435,12 @@ out:
        return err;
 }
 
-int dp_del_port(struct net_bridge_port *p, struct list_head *dp_devs)
+int dp_del_port(struct net_bridge_port *p)
 {
        ASSERT_RTNL();
 
-       if (p->port_no != ODPP_LOCAL && dp_del_if_hook) {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
-               sysfs_remove_link(&p->dp->ifobj, p->dev->name);
-#else
-               sysfs_remove_link(p->dp->ifobj, p->dev->name);
-#endif
-       }
+       if (p->port_no != ODPP_LOCAL)
+               dp_sysfs_del_if(p);
        dp_ifinfo_notify(RTM_DELLINK, p);
 
        p->dp->n_ports--;
@@ -451,26 +461,16 @@ int dp_del_port(struct net_bridge_port *p, struct list_head *dp_devs)
        /* Then wait until no one is still using it, and destroy it. */
        synchronize_rcu();
 
-       if (is_dp_dev(p->dev)) {
+       if (is_dp_dev(p->dev))
                dp_dev_destroy(p->dev);
-               if (dp_devs) {
-                       struct dp_dev *dp_dev = dp_dev_priv(p->dev);
-                       list_add(&dp_dev->list, dp_devs);
-               }
-       }
-       if (p->port_no != ODPP_LOCAL && dp_del_if_hook) {
-               dp_del_if_hook(p);
-       } else {
-               dev_put(p->dev);
-               kfree(p);
-       }
+       dev_put(p->dev);
+       kobject_put(&p->kobj);
 
        return 0;
 }
 
 static int del_port(int dp_idx, int port_no)
 {
-       struct dp_dev *dp_dev, *next;
        struct net_bridge_port *p;
        struct datapath *dp;
        LIST_HEAD(dp_devs);
@@ -491,15 +491,13 @@ static int del_port(int dp_idx, int port_no)
        if (!p)
                goto out_unlock_dp;
 
-       err = dp_del_port(p, &dp_devs);
+       err = dp_del_port(p);
 
 out_unlock_dp:
        mutex_unlock(&dp->mutex);
 out_unlock_rtnl:
        rtnl_unlock();
 out:
-       list_for_each_entry_safe (dp_dev, next, &dp_devs, list)
-               free_netdev(dp_dev->dev);
        return err;
 }
 
@@ -530,7 +528,6 @@ void dp_process_received_packet(struct sk_buff *skb, struct net_bridge_port *p)
        struct sw_flow *flow;
 
        WARN_ON_ONCE(skb_shared(skb));
-       WARN_ON_ONCE(skb->destructor);
 
        /* BHs are off so we don't have to use get_cpu()/put_cpu() here. */
        stats = percpu_ptr(dp->stats_percpu, smp_processor_id());
@@ -579,11 +576,11 @@ static int dp_frame_hook(struct net_bridge_port *p, struct sk_buff **pskb)
 #error
 #endif
 
-#ifdef CONFIG_XEN
-#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,18)
-/* This code is copied verbatim from net/dev/core.c in Xen's
- * linux-2.6.18-92.1.10.el5.xs5.0.0.394.644.  We can't call those functions
- * directly because they aren't exported. */
+#if defined(CONFIG_XEN) && defined(HAVE_PROTO_DATA_VALID)
+/* This code is based on a skb_checksum_setup from net/dev/core.c from a
+ * combination of Lenny's 2.6.26 Xen kernel and Xen's
+ * linux-2.6.18-92.1.10.el5.xs5.0.0.394.644.  We can't call this function
+ * directly because it isn't exported in all versions. */
 static int skb_pull_up_to(struct sk_buff *skb, void *ptr)
 {
        if (ptr < (void *)skb->tail)
@@ -596,39 +593,198 @@ static int skb_pull_up_to(struct sk_buff *skb, void *ptr)
        }
 }
 
-int skb_checksum_setup(struct sk_buff *skb)
+int vswitch_skb_checksum_setup(struct sk_buff *skb)
 {
-       if (skb->proto_csum_blank) {
-               if (skb->protocol != htons(ETH_P_IP))
-                       goto out;
-               if (!skb_pull_up_to(skb, skb->nh.iph + 1))
-                       goto out;
-               skb->h.raw = (unsigned char *)skb->nh.iph + 4*skb->nh.iph->ihl;
-               switch (skb->nh.iph->protocol) {
-               case IPPROTO_TCP:
-                       skb->csum = offsetof(struct tcphdr, check);
-                       break;
-               case IPPROTO_UDP:
-                       skb->csum = offsetof(struct udphdr, check);
-                       break;
-               default:
-                       if (net_ratelimit())
-                               printk(KERN_ERR "Attempting to checksum a non-"
-                                      "TCP/UDP packet, dropping a protocol"
-                                      " %d packet", skb->nh.iph->protocol);
-                       goto out;
-               }
-               if (!skb_pull_up_to(skb, skb->h.raw + skb->csum + 2))
-                       goto out;
-               skb->ip_summed = CHECKSUM_HW;
-               skb->proto_csum_blank = 0;
+       struct iphdr *iph;
+       unsigned char *th;
+       int err = -EPROTO;
+       __u16 csum_start, csum_offset;
+
+       if (!skb->proto_csum_blank)
+               return 0;
+
+       if (skb->protocol != htons(ETH_P_IP))
+               goto out;
+
+       if (!skb_pull_up_to(skb, skb_network_header(skb) + 1))
+               goto out;
+
+       iph = ip_hdr(skb);
+       th = skb_network_header(skb) + 4 * iph->ihl;
+
+       csum_start = th - skb->head;
+       switch (iph->protocol) {
+       case IPPROTO_TCP:
+               csum_offset = offsetof(struct tcphdr, check);
+               break;
+       case IPPROTO_UDP:
+               csum_offset = offsetof(struct udphdr, check);
+               break;
+       default:
+               if (net_ratelimit())
+                       printk(KERN_ERR "Attempting to checksum a non-"
+                              "TCP/UDP packet, dropping a protocol"
+                              " %d packet", iph->protocol);
+               goto out;
        }
-       return 0;
+
+       if (!skb_pull_up_to(skb, th + csum_offset + 2))
+               goto out;
+
+       skb->ip_summed = CHECKSUM_PARTIAL;
+       skb->proto_csum_blank = 0;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+       skb->csum_start = csum_start;
+       skb->csum_offset = csum_offset;
+#else
+       skb_set_transport_header(skb, csum_start - skb_headroom(skb));
+       skb->csum = csum_offset;
+#endif
+
+       err = 0;
+
 out:
-       return -EPROTO;
+       return err;
+}
+#endif /* CONFIG_XEN && HAVE_PROTO_DATA_VALID */
+
+ /* Types of checksums that we can receive (these all refer to L4 checksums):
+ * 1. CHECKSUM_NONE: Device that did not compute checksum, contains full
+ *     (though not verified) checksum in packet but not in skb->csum.  Packets
+ *     from the bridge local port will also have this type.
+ * 2. CHECKSUM_COMPLETE (CHECKSUM_HW): Good device that computes checksums,
+ *     also the GRE module.  This is the same as CHECKSUM_NONE, except it has
+ *     a valid skb->csum.  Importantly, both contain a full checksum (not
+ *     verified) in the packet itself.  The only difference is that if the
+ *     packet gets to L4 processing on this machine (not in DomU) we won't
+ *     have to recompute the checksum to verify.  Most hardware devices do not
+ *     produce packets with this type, even if they support receive checksum
+ *     offloading (they produce type #5).
+ * 3. CHECKSUM_PARTIAL (CHECKSUM_HW): Packet without full checksum and needs to
+ *     be computed if it is sent off box.  Unfortunately on earlier kernels,
+ *     this case is impossible to distinguish from #2, despite having opposite
+ *     meanings.  Xen adds an extra field on earlier kernels (see #4) in order
+ *     to distinguish the different states.  The only real user of this type
+ *     with bridging is Xen (on later kernels).
+ * 4. CHECKSUM_UNNECESSARY (with proto_csum_blank true): This packet was
+ *     generated locally by a Xen DomU and has a partial checksum.  If it is
+ *     handled on this machine (Dom0 or DomU), then the checksum will not be
+ *     computed.  If it goes off box, the checksum in the packet needs to
+ *     completed.  Calling skb_checksum_setup converts this to CHECKSUM_HW
+ *     (CHECKSUM_PARTIAL) so that the checksum can be completed.  In later
+ *     kernels, this combination is replaced with CHECKSUM_PARTIAL.
+ * 5. CHECKSUM_UNNECESSARY (with proto_csum_blank false): Packet with a correct
+ *     full checksum or using a protocol without a checksum.  skb->csum is
+ *     undefined.  This is common from devices with receive checksum
+ *     offloading.  This is somewhat similar to CHECKSUM_NONE, except that
+ *     nobody will try to verify the checksum with CHECKSUM_UNNECESSARY.
+ *
+ * Note that on earlier kernels, CHECKSUM_COMPLETE and CHECKSUM_PARTIAL are
+ * both defined as CHECKSUM_HW.  Normally the meaning of CHECKSUM_HW is clear
+ * based on whether it is on the transmit or receive path.  After the datapath
+ * it will be intepreted as CHECKSUM_PARTIAL.  If the packet already has a
+ * checksum, we will panic.  Since we can receive packets with checksums, we
+ * assume that all CHECKSUM_HW packets have checksums and map them to
+ * CHECKSUM_NONE, which has a similar meaning (the it is only different if the
+ * packet is processed by the local IP stack, in which case it will need to
+ * be reverified).  If we receive a packet with CHECKSUM_HW that really means
+ * CHECKSUM_PARTIAL, it will be sent with the wrong checksum.  However, there
+ * shouldn't be any devices that do this with bridging.
+ *
+ * The bridge has similar behavior and this function closely resembles
+ * skb_forward_csum().  It is slightly different because we are only concerned
+ * with bridging and not other types of forwarding and can get away with
+ * slightly more optimal behavior.*/
+void
+forward_ip_summed(struct sk_buff *skb)
+{
+#ifdef CHECKSUM_HW
+       if (skb->ip_summed == CHECKSUM_HW)
+               skb->ip_summed = CHECKSUM_NONE;
+#endif
+}
+
+/* Append each packet in 'skb' list to 'queue'.  There will be only one packet
+ * unless we broke up a GSO packet. */
+static int
+queue_control_packets(struct sk_buff *skb, struct sk_buff_head *queue,
+                     int queue_no, u32 arg)
+{
+       struct sk_buff *nskb;
+       int port_no;
+       int err;
+
+       port_no = ODPP_LOCAL;
+       if (skb->dev) {
+               if (skb->dev->br_port)
+                       port_no = skb->dev->br_port->port_no;
+               else if (is_dp_dev(skb->dev))
+                       port_no = dp_dev_priv(skb->dev)->port_no;
+       }
+
+       do {
+               struct odp_msg *header;
+
+               nskb = skb->next;
+               skb->next = NULL;
+
+               /* If a checksum-deferred packet is forwarded to the
+                * controller, correct the pointers and checksum.  This happens
+                * on a regular basis only on Xen, on which VMs can pass up
+                * packets that do not have their checksum computed.
+                */
+               err = vswitch_skb_checksum_setup(skb);
+               if (err)
+                       goto err_kfree_skbs;
+#ifndef CHECKSUM_HW
+               if (skb->ip_summed == CHECKSUM_PARTIAL) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+                       /* Until 2.6.22, the start of the transport header was
+                        * also the start of data to be checksummed.  Linux
+                        * 2.6.22 introduced the csum_start field for this
+                        * purpose, but we should point the transport header to
+                        * it anyway for backward compatibility, as
+                        * dev_queue_xmit() does even in 2.6.28. */
+                       skb_set_transport_header(skb, skb->csum_start -
+                                                skb_headroom(skb));
+#endif
+                       err = skb_checksum_help(skb);
+                       if (err)
+                               goto err_kfree_skbs;
+               }
+#else
+               if (skb->ip_summed == CHECKSUM_HW) {
+                       err = skb_checksum_help(skb, 0);
+                       if (err)
+                               goto err_kfree_skbs;
+               }
+#endif
+
+               err = skb_cow(skb, sizeof *header);
+               if (err)
+                       goto err_kfree_skbs;
+
+               header = (struct odp_msg*)__skb_push(skb, sizeof *header);
+               header->type = queue_no;
+               header->length = skb->len;
+               header->port = port_no;
+               header->reserved = 0;
+               header->arg = arg;
+               skb_queue_tail(queue, skb);
+
+               skb = nskb;
+       } while (skb);
+       return 0;
+
+err_kfree_skbs:
+       kfree_skb(skb);
+       while ((skb = nskb) != NULL) {
+               nskb = skb->next;
+               kfree_skb(skb);
+       }
+       return err;
 }
-#endif /* linux == 2.6.18 */
-#endif /* CONFIG_XEN */
 
 int
 dp_output_control(struct datapath *dp, struct sk_buff *skb, int queue_no,
@@ -636,50 +792,16 @@ dp_output_control(struct datapath *dp, struct sk_buff *skb, int queue_no,
 {
        struct dp_stats_percpu *stats;
        struct sk_buff_head *queue;
-       int port_no;
        int err;
 
        WARN_ON_ONCE(skb_shared(skb));
-       BUG_ON(queue_no != _ODPL_MISS_NR && queue_no != _ODPL_ACTION_NR);
-
+       BUG_ON(queue_no != _ODPL_MISS_NR && queue_no != _ODPL_ACTION_NR && queue_no != _ODPL_SFLOW_NR);
        queue = &dp->queues[queue_no];
        err = -ENOBUFS;
        if (skb_queue_len(queue) >= DP_MAX_QUEUE_LEN)
                goto err_kfree_skb;
 
-       /* If a checksum-deferred packet is forwarded to the controller,
-        * correct the pointers and checksum.  This happens on a regular basis
-        * only on Xen (the CHECKSUM_HW case), on which VMs can pass up packets
-        * that do not have their checksum computed.  We also implement it for
-        * the non-Xen case, but it is difficult to trigger or test this case
-        * there, hence the WARN_ON_ONCE().
-        */
-       err = skb_checksum_setup(skb);
-       if (err)
-               goto err_kfree_skb;
-#ifndef CHECKSUM_HW
-       if (skb->ip_summed == CHECKSUM_PARTIAL) {
-               WARN_ON_ONCE(1);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
-               /* Until 2.6.22, the start of the transport header was also the
-                * start of data to be checksummed.  Linux 2.6.22 introduced
-                * the csum_start field for this purpose, but we should point
-                * the transport header to it anyway for backward
-                * compatibility, as dev_queue_xmit() does even in 2.6.28. */
-               skb_set_transport_header(skb, skb->csum_start -
-                                             skb_headroom(skb));
-#endif
-               err = skb_checksum_help(skb);
-               if (err)
-                       goto err_kfree_skb;
-       }
-#else
-       if (skb->ip_summed == CHECKSUM_HW) {
-               err = skb_checksum_help(skb, 0);
-               if (err)
-                       goto err_kfree_skb;
-       }
-#endif
+       forward_ip_summed(skb);
 
        /* Break apart GSO packets into their component pieces.  Otherwise
         * userspace may try to stuff a 64kB packet into a 1500-byte MTU. */
@@ -698,45 +820,9 @@ dp_output_control(struct datapath *dp, struct sk_buff *skb, int queue_no,
                }
        }
 
-       /* Figure out port number. */
-       port_no = ODPP_LOCAL;
-       if (skb->dev) {
-               if (skb->dev->br_port)
-                       port_no = skb->dev->br_port->port_no;
-               else if (is_dp_dev(skb->dev))
-                       port_no = dp_dev_priv(skb->dev)->port_no;
-       }
-
-       /* Append each packet to queue.  There will be only one packet unless
-        * we broke up a GSO packet above. */
-       do {
-               struct odp_msg *header;
-               struct sk_buff *nskb = skb->next;
-               skb->next = NULL;
-
-               err = skb_cow(skb, sizeof *header);
-               if (err) {
-                       while (nskb) {
-                               kfree_skb(skb);
-                               skb = nskb;
-                               nskb = skb->next;
-                       }
-                       goto err_kfree_skb;
-               }
-
-               header = (struct odp_msg*)__skb_push(skb, sizeof *header);
-               header->type = queue_no;
-               header->length = skb->len;
-               header->port = port_no;
-               header->reserved = 0;
-               header->arg = arg;
-               skb_queue_tail(queue, skb);
-
-               skb = nskb;
-       } while (skb);
-
+       err = queue_control_packets(skb, queue, queue_no, arg);
        wake_up_interruptible(&dp->waitqueue);
-       return 0;
+       return err;
 
 err_kfree_skb:
        kfree_skb(skb);
@@ -777,7 +863,8 @@ static int validate_actions(const struct sw_flow_actions *actions)
                        break;
 
                case ODPAT_SET_VLAN_PCP:
-                       if (a->vlan_pcp.vlan_pcp & ~VLAN_PCP_MASK)
+                       if (a->vlan_pcp.vlan_pcp
+                           & ~(VLAN_PCP_MASK >> VLAN_PCP_SHIFT))
                                return -EINVAL;
                        break;
 
@@ -830,6 +917,7 @@ static void get_stats(struct sw_flow *flow, struct odp_flow_stats *stats)
        stats->n_bytes = flow->byte_count;
        stats->ip_tos = flow->ip_tos;
        stats->tcp_flags = flow->tcp_flags;
+       stats->error = 0;
 }
 
 static void clear_stats(struct sw_flow *flow)
@@ -844,7 +932,7 @@ static void clear_stats(struct sw_flow *flow)
 static int put_flow(struct datapath *dp, struct odp_flow_put __user *ufp)
 {
        struct odp_flow_put uf;
-       struct sw_flow *flow, **bucket;
+       struct sw_flow *flow;
        struct dp_table *table;
        struct odp_flow_stats stats;
        int error;
@@ -854,15 +942,10 @@ static int put_flow(struct datapath *dp, struct odp_flow_put __user *ufp)
                goto error;
        uf.flow.key.reserved = 0;
 
-retry:
        table = rcu_dereference(dp->table);
-       bucket = dp_table_lookup_for_insert(table, &uf.flow.key);
-       if (!bucket) {
-               /* No such flow, and the slots where it could go are full. */
-               error = uf.flags & ODPPF_CREATE ? -EXFULL : -ENOENT;
-               goto error;
-       } else if (!*bucket) {
-               /* No such flow, but we found an available slot for it. */
+       flow = dp_table_lookup(table, &uf.flow.key);
+       if (!flow) {
+               /* No such flow. */
                struct sw_flow_actions *acts;
 
                error = -ENOENT;
@@ -870,14 +953,15 @@ retry:
                        goto error;
 
                /* Expand table, if necessary, to make room. */
-               if (dp->n_flows * 4 >= table->n_buckets &&
-                   table->n_buckets < DP_MAX_BUCKETS) {
+               if (dp->n_flows >= table->n_buckets) {
+                       error = -ENOSPC;
+                       if (table->n_buckets >= DP_MAX_BUCKETS)
+                               goto error;
+
                        error = dp_table_expand(dp);
                        if (error)
                                goto error;
-
-                       /* The bucket's location has changed.  Try again. */
-                       goto retry;
+                       table = rcu_dereference(dp->table);
                }
 
                /* Allocate flow. */
@@ -897,12 +981,13 @@ retry:
                rcu_assign_pointer(flow->sf_acts, acts);
 
                /* Put flow in bucket. */
-               rcu_assign_pointer(*bucket, flow);
+               error = dp_table_insert(table, flow);
+               if (error)
+                       goto error_free_flow_acts;
                dp->n_flows++;
                memset(&stats, 0, sizeof(struct odp_flow_stats));
        } else {
                /* We found a matching flow. */
-               struct sw_flow *flow = *rcu_dereference(bucket);
                struct sw_flow_actions *old_acts, *new_acts;
                unsigned long int flags;
 
@@ -940,6 +1025,8 @@ retry:
                return -EFAULT;
        return 0;
 
+error_free_flow_acts:
+       kfree(flow->sf_acts);
 error_free_flow:
        kmem_cache_free(flow_cache, flow);
 error:
@@ -958,8 +1045,6 @@ static int put_actions(const struct sw_flow *flow, struct odp_flow __user *ufp)
 
        if (!n_actions)
                return 0;
-       if (ufp->n_actions > INT_MAX / sizeof(union odp_action))
-               return -EINVAL;
 
        sf_acts = rcu_dereference(flow->sf_acts);
        if (__put_user(sf_acts->n_actions, &ufp->n_actions) ||
@@ -971,13 +1056,18 @@ static int put_actions(const struct sw_flow *flow, struct odp_flow __user *ufp)
        return 0;
 }
 
-static int answer_query(struct sw_flow *flow, struct odp_flow __user *ufp)
+static int answer_query(struct sw_flow *flow, u32 query_flags,
+                       struct odp_flow __user *ufp)
 {
        struct odp_flow_stats stats;
        unsigned long int flags;
 
        spin_lock_irqsave(&flow->lock, flags);
        get_stats(flow, &stats);
+
+       if (query_flags & ODPFF_ZERO_TCP_FLAGS) {
+               flow->tcp_flags = 0;
+       }
        spin_unlock_irqrestore(&flow->lock, flags);
 
        if (__copy_to_user(&ufp->stats, &stats, sizeof(struct odp_flow_stats)))
@@ -985,9 +1075,7 @@ static int answer_query(struct sw_flow *flow, struct odp_flow __user *ufp)
        return put_actions(flow, ufp);
 }
 
-static int del_or_query_flow(struct datapath *dp,
-                            struct odp_flow __user *ufp,
-                            unsigned int cmd)
+static int del_flow(struct datapath *dp, struct odp_flow __user *ufp)
 {
        struct dp_table *table = rcu_dereference(dp->table);
        struct odp_flow uf;
@@ -1004,29 +1092,24 @@ static int del_or_query_flow(struct datapath *dp,
        if (!flow)
                goto error;
 
-       if (cmd == ODP_FLOW_DEL) {
-               /* XXX redundant lookup */
-               error = dp_table_delete(table, flow);
-               if (error)
-                       goto error;
+       /* XXX redundant lookup */
+       error = dp_table_delete(table, flow);
+       if (error)
+               goto error;
 
-               /* XXX These statistics might lose a few packets, since other
-                * CPUs can be using this flow.  We used to synchronize_rcu()
-                * to make sure that we get completely accurate stats, but that
-                * blows our performance, badly. */
-               dp->n_flows--;
-               error = answer_query(flow, ufp);
-               flow_deferred_free(flow);
-       } else {
-               error = answer_query(flow, ufp);
-       }
+       /* XXX These statistics might lose a few packets, since other CPUs can
+        * be using this flow.  We used to synchronize_rcu() to make sure that
+        * we get completely accurate stats, but that blows our performance,
+        * badly. */
+       dp->n_flows--;
+       error = answer_query(flow, 0, ufp);
+       flow_deferred_free(flow);
 
 error:
        return error;
 }
 
-static int query_multiple_flows(struct datapath *dp,
-                               const struct odp_flowvec *flowvec)
+static int query_flows(struct datapath *dp, const struct odp_flowvec *flowvec)
 {
        struct dp_table *table = rcu_dereference(dp->table);
        int i;
@@ -1042,9 +1125,9 @@ static int query_multiple_flows(struct datapath *dp,
 
                flow = dp_table_lookup(table, &uf.key);
                if (!flow)
-                       error = __clear_user(&ufp->stats, sizeof ufp->stats);
+                       error = __put_user(ENOENT, &ufp->stats.error);
                else
-                       error = answer_query(flow, ufp);
+                       error = answer_query(flow, uf.flags, ufp);
                if (error)
                        return -EFAULT;
        }
@@ -1065,7 +1148,7 @@ static int list_flow(struct sw_flow *flow, void *cbdata_)
 
        if (__copy_to_user(&ufp->key, &flow->key, sizeof flow->key))
                return -EFAULT;
-       error = answer_query(flow, ufp);
+       error = answer_query(flow, 0, ufp);
        if (error)
                return error;
 
@@ -1122,6 +1205,7 @@ static int do_execute(struct datapath *dp, const struct odp_execute *executep)
        struct odp_flow_key key;
        struct sk_buff *skb;
        struct sw_flow_actions *actions;
+       struct ethhdr *eth;
        int err;
 
        err = -EFAULT;
@@ -1161,6 +1245,17 @@ static int do_execute(struct datapath *dp, const struct odp_execute *executep)
                           execute.length))
                goto error_free_skb;
 
+       skb_reset_mac_header(skb);
+       eth = eth_hdr(skb);
+
+       /* Normally, setting the skb 'protocol' field would be handled by a
+        * call to eth_type_trans(), but it assumes there's a sending
+        * device, which we may not have. */
+       if (ntohs(eth->h_proto) >= 1536)
+               skb->protocol = eth->h_proto;
+       else
+               skb->protocol = htons(ETH_P_802_2);
+
        flow_extract(skb, execute.in_port, &key);
        err = execute_actions(dp, skb, &key, actions->actions,
                              actions->n_actions, GFP_KERNEL);
@@ -1175,15 +1270,14 @@ error:
        return err;
 }
 
-static int
-get_dp_stats(struct datapath *dp, struct odp_stats __user *statsp)
+static int get_dp_stats(struct datapath *dp, struct odp_stats __user *statsp)
 {
        struct odp_stats stats;
        int i;
 
        stats.n_flows = dp->n_flows;
-       stats.cur_capacity = rcu_dereference(dp->table)->n_buckets * 2;
-       stats.max_capacity = DP_MAX_BUCKETS * 2;
+       stats.cur_capacity = rcu_dereference(dp->table)->n_buckets;
+       stats.max_capacity = DP_MAX_BUCKETS;
        stats.n_ports = dp->n_ports;
        stats.max_ports = DP_MAX_PORTS;
        stats.max_groups = DP_MAX_GROUPS;
@@ -1201,6 +1295,52 @@ get_dp_stats(struct datapath *dp, struct odp_stats __user *statsp)
        return copy_to_user(statsp, &stats, sizeof stats) ? -EFAULT : 0;
 }
 
+/* MTU of the dp pseudo-device: ETH_DATA_LEN or the minimum of the ports */
+int dp_min_mtu(const struct datapath *dp)
+{
+       struct net_bridge_port *p;
+       int mtu = 0;
+
+       ASSERT_RTNL();
+
+       list_for_each_entry_rcu (p, &dp->port_list, node) {
+               struct net_device *dev = p->dev;
+
+               /* Skip any internal ports, since that's what we're trying to
+                * set. */
+               if (is_dp_dev(dev))
+                       continue;
+
+               if (!mtu || dev->mtu < mtu)
+                       mtu = dev->mtu;
+       }
+
+       return mtu ? mtu : ETH_DATA_LEN;
+}
+
+/* Sets the MTU of all datapath devices to the minimum of the ports. 'dev'
+ * is the device whose MTU may have changed.  Must be called with RTNL lock
+ * and dp_mutex. */
+void set_dp_devs_mtu(const struct datapath *dp, struct net_device *dev)
+{
+       struct net_bridge_port *p;
+       int mtu;
+
+       ASSERT_RTNL();
+
+       if (is_dp_dev(dev))
+               return;
+
+       mtu = dp_min_mtu(dp);
+
+       list_for_each_entry_rcu (p, &dp->port_list, node) {
+               struct net_device *br_dev = p->dev;
+
+               if (is_dp_dev(br_dev))
+                       dev_set_mtu(br_dev, mtu);
+       }
+}
+
 static int
 put_port(const struct net_bridge_port *p, struct odp_port __user *uop)
 {
@@ -1268,7 +1408,7 @@ list_ports(struct datapath *dp, struct odp_portvec __user *pvp)
                                break;
                }
        }
-       return put_user(idx, &pvp->n_ports);
+       return put_user(dp->n_ports, &pvp->n_ports);
 }
 
 /* RCU callback for freeing a dp_port_group */
@@ -1341,35 +1481,50 @@ get_port_group(struct datapath *dp, struct odp_port_group *upg)
        return 0;
 }
 
+static int get_listen_mask(const struct file *f)
+{
+       return (long)f->private_data;
+}
+
+static void set_listen_mask(struct file *f, int listen_mask)
+{
+       f->private_data = (void*)(long)listen_mask;
+}
+
 static long openvswitch_ioctl(struct file *f, unsigned int cmd,
                           unsigned long argp)
 {
        int dp_idx = iminor(f->f_dentry->d_inode);
        struct datapath *dp;
        int drop_frags, listeners, port_no;
+       unsigned int sflow_probability;
        int err;
 
        /* Handle commands with special locking requirements up front. */
        switch (cmd) {
        case ODP_DP_CREATE:
-               return create_dp(dp_idx, (char __user *)argp);
+               err = create_dp(dp_idx, (char __user *)argp);
+               goto exit;
 
        case ODP_DP_DESTROY:
-               return destroy_dp(dp_idx);
+               err = destroy_dp(dp_idx);
+               goto exit;
 
        case ODP_PORT_ADD:
-               return add_port(dp_idx, (struct odp_port __user *)argp);
+               err = add_port(dp_idx, (struct odp_port __user *)argp);
+               goto exit;
 
        case ODP_PORT_DEL:
                err = get_user(port_no, (int __user *)argp);
-               if (err)
-                       break;
-               return del_port(dp_idx, port_no);
+               if (!err)
+                       err = del_port(dp_idx, port_no);
+               goto exit;
        }
 
        dp = get_dp_locked(dp_idx);
+       err = -ENODEV;
        if (!dp)
-               return -ENODEV;
+               goto exit;
 
        switch (cmd) {
        case ODP_DP_STATS:
@@ -1392,7 +1547,7 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd,
                break;
 
        case ODP_GET_LISTEN_MASK:
-               err = put_user((int)f->private_data, (int __user *)argp);
+               err = put_user(get_listen_mask(f), (int __user *)argp);
                break;
 
        case ODP_SET_LISTEN_MASK:
@@ -1403,7 +1558,17 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd,
                if (listeners & ~ODPL_ALL)
                        break;
                err = 0;
-               f->private_data = (void*)listeners;
+               set_listen_mask(f, listeners);
+               break;
+
+       case ODP_GET_SFLOW_PROBABILITY:
+               err = put_user(dp->sflow_probability, (unsigned int __user *)argp);
+               break;
+
+       case ODP_SET_SFLOW_PROBABILITY:
+               err = get_user(sflow_probability, (unsigned int __user *)argp);
+               if (!err)
+                       dp->sflow_probability = sflow_probability;
                break;
 
        case ODP_PORT_QUERY:
@@ -1431,13 +1596,11 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd,
                break;
 
        case ODP_FLOW_DEL:
-       case ODP_FLOW_GET:
-               err = del_or_query_flow(dp, (struct odp_flow __user *)argp,
-                                       cmd);
+               err = del_flow(dp, (struct odp_flow __user *)argp);
                break;
 
-       case ODP_FLOW_GET_MULTIPLE:
-               err = do_flowvec_ioctl(dp, argp, query_multiple_flows);
+       case ODP_FLOW_GET:
+               err = do_flowvec_ioctl(dp, argp, query_flows);
                break;
 
        case ODP_FLOW_LIST:
@@ -1453,6 +1616,7 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd,
                break;
        }
        mutex_unlock(&dp->mutex);
+exit:
        return err;
 }
 
@@ -1469,7 +1633,8 @@ static int dp_has_packet_of_interest(struct datapath *dp, int listeners)
 ssize_t openvswitch_read(struct file *f, char __user *buf, size_t nbytes,
                      loff_t *ppos)
 {
-       int listeners = (int) f->private_data;
+       /* XXX is there sufficient synchronization here? */
+       int listeners = get_listen_mask(f);
        int dp_idx = iminor(f->f_dentry->d_inode);
        struct datapath *dp = get_dp(dp_idx);
        struct sk_buff *skb;
@@ -1509,7 +1674,7 @@ ssize_t openvswitch_read(struct file *f, char __user *buf, size_t nbytes,
                }
        }
 success:
-       copy_bytes = min(skb->len, nbytes);
+       copy_bytes = min_t(size_t, skb->len, nbytes);
        iov.iov_base = buf;
        iov.iov_len = copy_bytes;
        retval = skb_copy_datagram_iovec(skb, 0, &iov, iov.iov_len);
@@ -1523,6 +1688,7 @@ error:
 
 static unsigned int openvswitch_poll(struct file *file, poll_table *wait)
 {
+       /* XXX is there sufficient synchronization here? */
        int dp_idx = iminor(file->f_dentry->d_inode);
        struct datapath *dp = get_dp(dp_idx);
        unsigned int mask;
@@ -1530,7 +1696,7 @@ static unsigned int openvswitch_poll(struct file *file, poll_table *wait)
        if (dp) {
                mask = 0;
                poll_wait(file, &dp->waitqueue, wait);
-               if (dp_has_packet_of_interest(dp, (int)file->private_data))
+               if (dp_has_packet_of_interest(dp, get_listen_mask(file)))
                        mask |= POLLIN | POLLRDNORM;
        } else {
                mask = POLLIN | POLLRDNORM | POLLHUP;
@@ -1547,6 +1713,8 @@ struct file_operations openvswitch_fops = {
 };
 
 static int major;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
 static struct llc_sap *dp_stp_sap;
 
 static int dp_stp_rcv(struct sk_buff *skb, struct net_device *dev,
@@ -1559,12 +1727,8 @@ static int dp_stp_rcv(struct sk_buff *skb, struct net_device *dev,
        return 0;
 }
 
-static int __init dp_init(void)
+static int dp_avoid_bridge_init(void)
 {
-       int err;
-
-       printk("Open vSwitch %s, built "__DATE__" "__TIME__"\n", VERSION BUILDNR);
-
        /* Register to receive STP packets because the bridge module also
         * attempts to do so.  Since there can only be a single listener for a
         * given protocol, this provides mutual exclusion against the bridge
@@ -1575,6 +1739,43 @@ static int __init dp_init(void)
                printk(KERN_ERR "openvswitch: can't register sap for STP (probably the bridge module is loaded)\n");
                return -EADDRINUSE;
        }
+       return 0;
+}
+
+static void dp_avoid_bridge_exit(void)
+{
+       llc_sap_put(dp_stp_sap);
+}
+#else  /* Linux 2.6.27 or later. */
+static int dp_avoid_bridge_init(void)
+{
+       /* Linux 2.6.27 introduces a way for multiple clients to register for
+        * STP packets, which interferes with what we try to do above.
+        * Instead, just check whether there's a bridge hook defined.  This is
+        * not as safe--the bridge module is willing to load over the top of
+        * us--but it provides a little bit of protection. */
+       if (br_handle_frame_hook) {
+               printk(KERN_ERR "openvswitch: bridge module is loaded, cannot load over it\n");
+               return -EADDRINUSE;
+       }
+       return 0;
+}
+
+static void dp_avoid_bridge_exit(void)
+{
+       /* Nothing to do. */
+}
+#endif /* Linux 2.6.27 or later */
+
+static int __init dp_init(void)
+{
+       int err;
+
+       printk("Open vSwitch %s, built "__DATE__" "__TIME__"\n", VERSION BUILDNR);
+
+       err = dp_avoid_bridge_init();
+       if (err)
+               return err;
 
        err = flow_init();
        if (err)
@@ -1609,7 +1810,7 @@ static void dp_cleanup(void)
        unregister_netdevice_notifier(&dp_device_notifier);
        flow_exit();
        br_handle_frame_hook = NULL;
-       llc_sap_put(dp_stp_sap);
+       dp_avoid_bridge_exit();
 }
 
 module_init(dp_init);