/*
- * Copyright (c) 2010 Nicira Networks.
+ * Copyright (c) 2010, 2011 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
#include <net/llc.h>
+#include "checksum.h"
#include "datapath.h"
#include "vport-internal_dev.h"
#include "vport-netdev.h"
-#include "compat.h"
-
/* If the native device stats aren't 64 bit use the vport stats tracking instead. */
#define USE_VPORT_STATS (sizeof(((struct net_device_stats *)0)->rx_bytes) < sizeof(u64))
struct netdev_vport *netdev_vport;
int err;
- vport = vport_alloc(sizeof(struct netdev_vport), &netdev_vport_ops);
+ vport = vport_alloc(sizeof(struct netdev_vport), &netdev_vport_ops, parms);
if (IS_ERR(vport)) {
err = PTR_ERR(vport);
goto error;
vport_set_stats(vport, &stats);
}
+ err = netdev_rx_handler_register(netdev_vport->dev, netdev_frame_hook,
+ vport);
+ if (err)
+ goto error_put;
+
+ dev_set_promiscuity(netdev_vport->dev, 1);
+ dev_disable_lro(netdev_vport->dev);
+ netdev_vport->dev->priv_flags |= IFF_OVS_DATAPATH;
+
return vport;
error_put:
{
struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
- dev_put(netdev_vport->dev);
- vport_free(vport);
-
- return 0;
-}
-
-static int netdev_attach(struct vport *vport)
-{
- struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
- int err;
-
- err = netdev_rx_handler_register(netdev_vport->dev, netdev_frame_hook,
- vport);
- if (err)
- return err;
-
- dev_set_promiscuity(netdev_vport->dev, 1);
- dev_disable_lro(netdev_vport->dev);
- netdev_vport->dev->priv_flags |= IFF_OVS_DATAPATH;
-
- return 0;
-}
-
-static int netdev_detach(struct vport *vport)
-{
- struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
-
netdev_vport->dev->priv_flags &= ~IFF_OVS_DATAPATH;
netdev_rx_handler_unregister(netdev_vport->dev);
dev_set_promiscuity(netdev_vport->dev, -1);
+ synchronize_rcu();
+
+ dev_put(netdev_vport->dev);
+ vport_free(vport);
+
return 0;
}
/* Returns null if this device is not attached to a datapath. */
struct vport *netdev_get_vport(struct net_device *dev)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
- /* XXX: The bridge code may have registered the data.
- * So check that the handler pointer is the datapath's.
- * Once the merge is done and IFF_OVS_DATAPATH stops
- * being the same value as IFF_BRIDGE_PORT the check can
- * simply be netdev_vport->dev->priv_flags & IFF_OVS_DATAPATH. */
- if (rcu_dereference(dev->rx_handler) != netdev_frame_hook)
+#ifdef IFF_BRIDGE_PORT
+#if IFF_BRIDGE_PORT != IFF_OVS_DATAPATH
+ if (likely(dev->priv_flags & IFF_OVS_DATAPATH))
+#else
+ if (likely(rcu_access_pointer(dev->rx_handler) == netdev_frame_hook))
+#endif
+ return (struct vport *)rcu_dereference_rtnl(dev->rx_handler_data);
+ else
return NULL;
- return (struct vport *)rcu_dereference(dev->rx_handler_data);
#else
- return (struct vport *)rcu_dereference(dev->br_port);
+ return (struct vport *)rcu_dereference_rtnl(dev->br_port);
#endif
}
const struct vport_ops netdev_vport_ops = {
- .type = "netdev",
+ .type = ODP_VPORT_TYPE_NETDEV,
.flags = (VPORT_F_REQUIRED |
(USE_VPORT_STATS ? VPORT_F_GEN_STATS : 0)),
.init = netdev_init,
.exit = netdev_exit,
.create = netdev_create,
.destroy = netdev_destroy,
- .attach = netdev_attach,
- .detach = netdev_detach,
.set_mtu = netdev_set_mtu,
.set_addr = netdev_set_addr,
.get_name = netdev_get_name,