Merge commit 'origin/citrix'
[sliver-openvswitch.git] / datapath / datapath.c
index 015edc4..14d83cd 100644 (file)
@@ -1,6 +1,9 @@
 /*
- * Distributed under the terms of the GNU GPL version 2.
  * Copyright (c) 2007, 2008, 2009 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
+ * kernel, by Linus Torvalds and others.
  */
 
 /* Functions for managing the dp interface/device. */
@@ -174,7 +177,8 @@ static void dp_ifinfo_notify(int event, struct net_bridge_port *port)
                kfree_skb(skb);
                goto errout;
        }
-       err = rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
+       rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
+       return;
 errout:
        if (err < 0)
                rtnl_set_sk_err(net, RTNLGRP_LINK, err);
@@ -273,19 +277,19 @@ static void do_destroy_dp(struct datapath *dp, struct list_head *dp_devs)
        struct net_bridge_port *p, *n;
        int i;
 
+       list_for_each_entry_safe (p, n, &dp->port_list, node)
+               if (p->port_no != ODPP_LOCAL)
+                       dp_del_port(p, dp_devs);
+
        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);
-
        rcu_assign_pointer(dps[dp->dp_idx], NULL);
-       synchronize_rcu();
 
-       /* Wait until no longer in use, then destroy it. */
-       synchronize_rcu();
+       dp_del_port(dp->ports[ODPP_LOCAL], dp_devs);
+
        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++)
@@ -421,10 +425,13 @@ int dp_del_port(struct net_bridge_port *p, struct list_head *dp_devs)
 {
        ASSERT_RTNL();
 
-#ifdef SUPPORT_SYSFS
-       if (p->port_no != ODPP_LOCAL && dp_del_if_hook)
+       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
+       }
        dp_ifinfo_notify(RTM_DELLINK, p);
 
        p->dp->n_ports--;
@@ -574,6 +581,7 @@ static int dp_frame_hook(struct net_bridge_port *p, struct sk_buff **pskb)
 #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. */
@@ -620,7 +628,8 @@ int skb_checksum_setup(struct sk_buff *skb)
 out:
        return -EPROTO;
 }
-#endif
+#endif /* linux == 2.6.18 */
+#endif /* CONFIG_XEN */
 
 int
 dp_output_control(struct datapath *dp, struct sk_buff *skb, int queue_no,
@@ -1461,6 +1470,7 @@ 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)
 {
+       /* XXX is there sufficient synchronization here? */
        int listeners = (int) f->private_data;
        int dp_idx = iminor(f->f_dentry->d_inode);
        struct datapath *dp = get_dp(dp_idx);
@@ -1515,6 +1525,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;