This adds compatibility with kernel changeset
of changeset "net: replace hooks in __netif_receive_skb V5",
which was also added between 2.6.35 and 2.6.35-rc1

Signed-off-by: Simon Horman <horms@verge.net.au>

--- 

Compile tested only.

The code still conflicts with the bridging module due to its
use of dev->br_port. I would like to handle the conflict
with bridging module after this code is merged into the kernel tree.

Index: openvswitch/datapath/vport-netdev.c
===================================================================
--- openvswitch.orig/datapath/vport-netdev.c	2010-08-06 22:31:46.000000000 +0900
+++ openvswitch/datapath/vport-netdev.c	2010-08-06 22:32:02.000000000 +0900
@@ -25,25 +25,26 @@
 /* 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);
 
 /*
  * Used as br_handle_frame_hook.  (Cannot run bridge at the same time, even on
  * different set of devices!)
  */
+#ifdef HAVE_BR_HANDLE_FRAME_HOOK
 #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)
 /* 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
@@ -64,6 +65,27 @@ static void netdev_exit(void)
 	br_handle_frame_hook = NULL;
 }
 
+#else
+
+/* Called with rcu_read_lock and bottom-halves disabled. */
+static struct sk_buff *netdev_frame_hook(struct sk_buff *skb)
+{
+	struct vport *vport;
+
+	if (skb->pkt_type == PACKET_LOOPBACK)
+		return skb;
+
+	vport = (struct vport *)rcu_dereference(skb->dev->br_port);
+
+	netdev_port_receive(vport, skb);
+
+	return NULL;
+}
+
+static int netdev_init(void) { return 0; }
+static void netdev_exit(void) { ; }
+#endif
+
 static struct vport *netdev_create(const char *name, const void __user *config)
 {
 	struct vport *vport;
@@ -129,18 +151,25 @@ static int netdev_destroy(struct vport *
 static int netdev_attach(struct vport *vport)
 {
 	struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
+	int err = 0;
 
 	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;
+	rcu_assign_pointer(netdev_vport->dev->br_port,
+			   (struct net_bridge_port *)vport);
+#ifndef HAVE_BR_HANDLE_FRAME_HOOK
+	err = netdev_rx_handler_register(netdev_vport->dev, netdev_frame_hook);
+#endif
+	return err;
 }
 
 static int netdev_detach(struct vport *vport)
 {
 	struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
 
+#ifndef HAVE_BR_HANDLE_FRAME_HOOK
+	netdev_rx_handler_unregister(netdev_vport->dev);
+#endif
 	rcu_assign_pointer(netdev_vport->dev->br_port, NULL);
 	dev_set_promiscuity(netdev_vport->dev, -1);
 
@@ -242,10 +271,8 @@ int netdev_get_mtu(const struct vport *v
 }
 
 /* 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
Index: openvswitch/acinclude.m4
===================================================================
--- openvswitch.orig/acinclude.m4	2010-08-06 22:31:46.000000000 +0900
+++ openvswitch/acinclude.m4	2010-08-06 22:31:52.000000000 +0900
@@ -154,6 +154,10 @@ AC_DEFUN([OVS_CHECK_LINUX26_COMPAT], [
   OVS_GREP_IFELSE([$KSRC26/include/linux/err.h], [ERR_CAST],
                   [OVS_DEFINE([HAVE_ERR_CAST])])
 
+  OVS_GREP_IFELSE([$KSRC26/include/linux/if_bridge.h],
+                  [br_handle_frame_hook],
+                  [OVS_DEFINE([HAVE_BR_HANDLE_FRAME_HOOK])])
+
   OVS_GREP_IFELSE([$KSRC26/include/linux/in.h], [ipv4_is_multicast],
                   [OVS_DEFINE([HAVE_IPV4_IS_MULTICAST])])
 



