/*
- * 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. */
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);
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++)
{
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--;
#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. */
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,
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);
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;