aboutsummaryrefslogtreecommitdiff
path: root/datapath/vport-netdev.c
diff options
context:
space:
mode:
authorSimon Horman <horms@verge.net.au>2010-08-23 15:30:06 +0900
committerJesse Gross <jesse@nicira.com>2010-08-23 14:37:44 -0400
commit431585099e82a88a23d5dec28138b5a3a8bb11da (patch)
tree93c94bd57f212e2fea6bed9787f1ae00a1441d3d /datapath/vport-netdev.c
parent4b70d8583bd8b4fd328cae192be5c60a761e73b1 (diff)
datapath: dont use non-existent receive hooks
This adds compatibility with kernel changeset of changeset "net: add rx_handler data pointer" and thus "net: replace hooks in __netif_receive_skb V5", which were added between 2.6.35 and 2.6.36-rc1 Signed-off-by: Simon Horman <horms@verge.net.au> Signed-off-by: Jesse Gross <jesse@nicira.com>
Diffstat (limited to 'datapath/vport-netdev.c')
-rw-r--r--datapath/vport-netdev.c46
1 files changed, 38 insertions, 8 deletions
diff --git a/datapath/vport-netdev.c b/datapath/vport-netdev.c
index 1773a09b..a85a9b5f 100644
--- a/datapath/vport-netdev.c
+++ b/datapath/vport-netdev.c
@@ -25,31 +25,54 @@
/* 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))
-static void netdev_port_receive(struct net_bridge_port *, struct sk_buff *);
+static void netdev_port_receive(struct vport *vport, struct sk_buff *skb);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
+/* Called with rcu_read_lock and bottom-halves disabled. */
+static struct sk_buff *netdev_frame_hook(struct sk_buff *skb)
+{
+ struct vport *vport;
+
+ if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
+ return skb;
+
+ vport = (struct vport *)rcu_dereference(skb->dev->br_port);
+
+ netdev_port_receive(vport, skb);
+
+ return NULL;
+}
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
/*
* Used as br_handle_frame_hook. (Cannot run bridge at the same time, even on
* different set of devices!)
*/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
/* Called with rcu_read_lock and bottom-halves disabled. */
static struct sk_buff *netdev_frame_hook(struct net_bridge_port *p,
struct sk_buff *skb)
{
- netdev_port_receive(p, skb);
+ netdev_port_receive((struct vport *)p, skb);
return NULL;
}
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+/*
+ * Used as br_handle_frame_hook. (Cannot run bridge at the same time, even on
+ * different set of devices!)
+ */
/* Called with rcu_read_lock and bottom-halves disabled. */
static int netdev_frame_hook(struct net_bridge_port *p, struct sk_buff **pskb)
{
- netdev_port_receive(p, *pskb);
+ netdev_port_receive((struct vport *)p, *pskb);
return 1;
}
#else
#error
#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
+static int netdev_init(void) { return 0; }
+static void netdev_exit(void) { }
+#else
static int netdev_init(void)
{
/* Hook into callback used by the bridge to intercept packets.
@@ -63,6 +86,7 @@ static void netdev_exit(void)
{
br_handle_frame_hook = NULL;
}
+#endif
static struct vport *netdev_create(const char *name, const void __user *config)
{
@@ -129,10 +153,17 @@ static int netdev_destroy(struct vport *vport)
static int netdev_attach(struct vport *vport)
{
struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
+ int err;
+
+ rcu_assign_pointer(netdev_vport->dev->br_port,
+ (struct net_bridge_port *)vport);
+ err = netdev_rx_handler_register(netdev_vport->dev, netdev_frame_hook,
+ NULL);
+ if (err)
+ return err;
dev_set_promiscuity(netdev_vport->dev, 1);
dev_disable_lro(netdev_vport->dev);
- rcu_assign_pointer(netdev_vport->dev->br_port, (struct net_bridge_port *)vport);
return 0;
}
@@ -141,6 +172,7 @@ static int netdev_detach(struct vport *vport)
{
struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
+ netdev_rx_handler_unregister(netdev_vport->dev);
rcu_assign_pointer(netdev_vport->dev->br_port, NULL);
dev_set_promiscuity(netdev_vport->dev, -1);
@@ -242,10 +274,8 @@ int netdev_get_mtu(const struct vport *vport)
}
/* Must be called with rcu_read_lock. */
-static void netdev_port_receive(struct net_bridge_port *p, struct sk_buff *skb)
+static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)
{
- struct vport *vport = (struct vport *)p;
-
/* Make our own copy of the packet. Otherwise we will mangle the
* packet for anyone who came before us (e.g. tcpdump via AF_PACKET).
* (No one comes after us, since we tell handle_bridge() that we took