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>
#define skb_checksum_help(skb) skb_checksum_help((skb), 0)
#endif
#define skb_checksum_help(skb) skb_checksum_help((skb), 0)
#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
+static inline int netdev_rx_handler_register(struct net_device *dev,
+ void *rx_handler,
+ void *rx_handler_data)
+{
+ return 0;
+}
+static inline void netdev_rx_handler_unregister(struct net_device *dev) { }
+#endif
+
/* 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))
/* 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!)
*/
/*
* 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)
{
/* 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)
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)
{
/* 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
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.
static int netdev_init(void)
{
/* Hook into callback used by the bridge to intercept packets.
{
br_handle_frame_hook = NULL;
}
{
br_handle_frame_hook = NULL;
}
static struct vport *netdev_create(const char *name, const void __user *config)
{
static struct vport *netdev_create(const char *name, const void __user *config)
{
static int netdev_attach(struct vport *vport)
{
struct netdev_vport *netdev_vport = netdev_vport_priv(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);
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);
{
struct netdev_vport *netdev_vport = netdev_vport_priv(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);
rcu_assign_pointer(netdev_vport->dev->br_port, NULL);
dev_set_promiscuity(netdev_vport->dev, -1);
}
/* Must be called with rcu_read_lock. */
}
/* 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
/* 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