datapath: Add support for kernel 3.14.
[sliver-openvswitch.git] / datapath / linux / compat / dev-openvswitch.c
1 #include <linux/if_bridge.h>
2 #include <linux/netdevice.h>
3 #include <linux/version.h>
4
5 #ifndef HAVE_DEV_DISABLE_LRO
6
7 #ifdef NETIF_F_LRO
8 #include <linux/ethtool.h>
9
10 /**
11  *      dev_disable_lro - disable Large Receive Offload on a device
12  *      @dev: device
13  *
14  *      Disable Large Receive Offload (LRO) on a net device.  Must be
15  *      called under RTNL.  This is needed if received packets may be
16  *      forwarded to another interface.
17  */
18 void dev_disable_lro(struct net_device *dev)
19 {
20         if (dev->ethtool_ops && dev->ethtool_ops->get_flags &&
21             dev->ethtool_ops->set_flags) {
22                 u32 flags = dev->ethtool_ops->get_flags(dev);
23                 if (flags & ETH_FLAG_LRO) {
24                         flags &= ~ETH_FLAG_LRO;
25                         dev->ethtool_ops->set_flags(dev, flags);
26                 }
27         }
28         WARN_ON(dev->features & NETIF_F_LRO);
29 }
30 #else
31 void dev_disable_lro(struct net_device *dev) { }
32 #endif /* NETIF_F_LRO */
33
34 #endif /* HAVE_DEV_DISABLE_LRO */
35
36 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) || \
37     defined HAVE_RHEL_OVS_HOOK
38
39 static int nr_bridges;
40
41 #ifdef HAVE_RHEL_OVS_HOOK
42 int netdev_rx_handler_register(struct net_device *dev,
43                                openvswitch_handle_frame_hook_t *hook,
44                                void *rx_handler_data)
45 {
46         nr_bridges++;
47         rcu_assign_pointer(dev->ax25_ptr, rx_handler_data);
48
49         if (nr_bridges == 1)
50                 rcu_assign_pointer(openvswitch_handle_frame_hook, hook);
51         return 0;
52 }
53 #else
54
55 int netdev_rx_handler_register(struct net_device *dev,
56                                struct sk_buff *(*hook)(struct net_bridge_port *p,
57                                                        struct sk_buff *skb),
58                                void *rx_handler_data)
59 {
60         nr_bridges++;
61         if (dev->br_port)
62                 return -EBUSY;
63
64         rcu_assign_pointer(dev->br_port, rx_handler_data);
65
66         if (nr_bridges == 1)
67                 br_handle_frame_hook = hook;
68         return 0;
69 }
70 #endif
71
72 void netdev_rx_handler_unregister(struct net_device *dev)
73 {
74         nr_bridges--;
75 #ifdef HAVE_RHEL_OVS_HOOK
76         rcu_assign_pointer(dev->ax25_ptr, NULL);
77
78         if (nr_bridges)
79                 return;
80
81         rcu_assign_pointer(openvswitch_handle_frame_hook, NULL);
82 #else
83         rcu_assign_pointer(dev->br_port, NULL);
84
85         if (nr_bridges)
86                 return;
87
88         br_handle_frame_hook = NULL;
89 #endif
90 }
91 #endif