38ec8fe9ee1cd0b7f17e40386c4225cc5a0b9d2d
[cascardo/ovs.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 !defined HAVE_NETDEV_RX_HANDLER_REGISTER || \
37     defined HAVE_RHEL_OVS_HOOK
38
39 static int nr_bridges;
40
41 #ifdef HAVE_RHEL_OVS_HOOK
42 int rpl_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 EXPORT_SYMBOL_GPL(rpl_netdev_rx_handler_register);
54 #else
55
56 int rpl_netdev_rx_handler_register(struct net_device *dev,
57                                    struct sk_buff *(*hook)(struct net_bridge_port *p,
58                                                            struct sk_buff *skb),
59                                    void *rx_handler_data)
60 {
61         nr_bridges++;
62         if (dev->br_port)
63                 return -EBUSY;
64
65         rcu_assign_pointer(dev->br_port, rx_handler_data);
66
67         if (nr_bridges == 1)
68                 br_handle_frame_hook = hook;
69         return 0;
70 }
71 EXPORT_SYMBOL_GPL(rpl_netdev_rx_handler_register);
72 #endif
73
74 void rpl_netdev_rx_handler_unregister(struct net_device *dev)
75 {
76         nr_bridges--;
77 #ifdef HAVE_RHEL_OVS_HOOK
78         rcu_assign_pointer(dev->ax25_ptr, NULL);
79
80         if (nr_bridges)
81                 return;
82
83         rcu_assign_pointer(openvswitch_handle_frame_hook, NULL);
84 #else
85         rcu_assign_pointer(dev->br_port, NULL);
86
87         if (nr_bridges)
88                 return;
89
90         br_handle_frame_hook = NULL;
91 #endif
92 }
93 EXPORT_SYMBOL_GPL(rpl_netdev_rx_handler_unregister);
94
95 #endif