diff options
Diffstat (limited to 'net/core/dev.c')
-rw-r--r-- | net/core/dev.c | 85 |
1 files changed, 75 insertions, 10 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 56b46579ff4..472676dd550 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -90,6 +90,7 @@ | |||
90 | #include <linux/if_ether.h> | 90 | #include <linux/if_ether.h> |
91 | #include <linux/netdevice.h> | 91 | #include <linux/netdevice.h> |
92 | #include <linux/etherdevice.h> | 92 | #include <linux/etherdevice.h> |
93 | #include <linux/ethtool.h> | ||
93 | #include <linux/notifier.h> | 94 | #include <linux/notifier.h> |
94 | #include <linux/skbuff.h> | 95 | #include <linux/skbuff.h> |
95 | #include <net/net_namespace.h> | 96 | #include <net/net_namespace.h> |
@@ -961,6 +962,12 @@ void netdev_state_change(struct net_device *dev) | |||
961 | } | 962 | } |
962 | } | 963 | } |
963 | 964 | ||
965 | void netdev_bonding_change(struct net_device *dev) | ||
966 | { | ||
967 | call_netdevice_notifiers(NETDEV_BONDING_FAILOVER, dev); | ||
968 | } | ||
969 | EXPORT_SYMBOL(netdev_bonding_change); | ||
970 | |||
964 | /** | 971 | /** |
965 | * dev_load - load a network module | 972 | * dev_load - load a network module |
966 | * @net: the applicable net namespace | 973 | * @net: the applicable net namespace |
@@ -1117,6 +1124,29 @@ int dev_close(struct net_device *dev) | |||
1117 | } | 1124 | } |
1118 | 1125 | ||
1119 | 1126 | ||
1127 | /** | ||
1128 | * dev_disable_lro - disable Large Receive Offload on a device | ||
1129 | * @dev: device | ||
1130 | * | ||
1131 | * Disable Large Receive Offload (LRO) on a net device. Must be | ||
1132 | * called under RTNL. This is needed if received packets may be | ||
1133 | * forwarded to another interface. | ||
1134 | */ | ||
1135 | void dev_disable_lro(struct net_device *dev) | ||
1136 | { | ||
1137 | if (dev->ethtool_ops && dev->ethtool_ops->get_flags && | ||
1138 | dev->ethtool_ops->set_flags) { | ||
1139 | u32 flags = dev->ethtool_ops->get_flags(dev); | ||
1140 | if (flags & ETH_FLAG_LRO) { | ||
1141 | flags &= ~ETH_FLAG_LRO; | ||
1142 | dev->ethtool_ops->set_flags(dev, flags); | ||
1143 | } | ||
1144 | } | ||
1145 | WARN_ON(dev->features & NETIF_F_LRO); | ||
1146 | } | ||
1147 | EXPORT_SYMBOL(dev_disable_lro); | ||
1148 | |||
1149 | |||
1120 | static int dev_boot_phase = 1; | 1150 | static int dev_boot_phase = 1; |
1121 | 1151 | ||
1122 | /* | 1152 | /* |
@@ -2769,16 +2799,29 @@ int netdev_set_master(struct net_device *slave, struct net_device *master) | |||
2769 | return 0; | 2799 | return 0; |
2770 | } | 2800 | } |
2771 | 2801 | ||
2772 | static void __dev_set_promiscuity(struct net_device *dev, int inc) | 2802 | static int __dev_set_promiscuity(struct net_device *dev, int inc) |
2773 | { | 2803 | { |
2774 | unsigned short old_flags = dev->flags; | 2804 | unsigned short old_flags = dev->flags; |
2775 | 2805 | ||
2776 | ASSERT_RTNL(); | 2806 | ASSERT_RTNL(); |
2777 | 2807 | ||
2778 | if ((dev->promiscuity += inc) == 0) | 2808 | dev->flags |= IFF_PROMISC; |
2779 | dev->flags &= ~IFF_PROMISC; | 2809 | dev->promiscuity += inc; |
2780 | else | 2810 | if (dev->promiscuity == 0) { |
2781 | dev->flags |= IFF_PROMISC; | 2811 | /* |
2812 | * Avoid overflow. | ||
2813 | * If inc causes overflow, untouch promisc and return error. | ||
2814 | */ | ||
2815 | if (inc < 0) | ||
2816 | dev->flags &= ~IFF_PROMISC; | ||
2817 | else { | ||
2818 | dev->promiscuity -= inc; | ||
2819 | printk(KERN_WARNING "%s: promiscuity touches roof, " | ||
2820 | "set promiscuity failed, promiscuity feature " | ||
2821 | "of device might be broken.\n", dev->name); | ||
2822 | return -EOVERFLOW; | ||
2823 | } | ||
2824 | } | ||
2782 | if (dev->flags != old_flags) { | 2825 | if (dev->flags != old_flags) { |
2783 | printk(KERN_INFO "device %s %s promiscuous mode\n", | 2826 | printk(KERN_INFO "device %s %s promiscuous mode\n", |
2784 | dev->name, (dev->flags & IFF_PROMISC) ? "entered" : | 2827 | dev->name, (dev->flags & IFF_PROMISC) ? "entered" : |
@@ -2796,6 +2839,7 @@ static void __dev_set_promiscuity(struct net_device *dev, int inc) | |||
2796 | if (dev->change_rx_flags) | 2839 | if (dev->change_rx_flags) |
2797 | dev->change_rx_flags(dev, IFF_PROMISC); | 2840 | dev->change_rx_flags(dev, IFF_PROMISC); |
2798 | } | 2841 | } |
2842 | return 0; | ||
2799 | } | 2843 | } |
2800 | 2844 | ||
2801 | /** | 2845 | /** |
@@ -2807,14 +2851,19 @@ static void __dev_set_promiscuity(struct net_device *dev, int inc) | |||
2807 | * remains above zero the interface remains promiscuous. Once it hits zero | 2851 | * remains above zero the interface remains promiscuous. Once it hits zero |
2808 | * the device reverts back to normal filtering operation. A negative inc | 2852 | * the device reverts back to normal filtering operation. A negative inc |
2809 | * value is used to drop promiscuity on the device. | 2853 | * value is used to drop promiscuity on the device. |
2854 | * Return 0 if successful or a negative errno code on error. | ||
2810 | */ | 2855 | */ |
2811 | void dev_set_promiscuity(struct net_device *dev, int inc) | 2856 | int dev_set_promiscuity(struct net_device *dev, int inc) |
2812 | { | 2857 | { |
2813 | unsigned short old_flags = dev->flags; | 2858 | unsigned short old_flags = dev->flags; |
2859 | int err; | ||
2814 | 2860 | ||
2815 | __dev_set_promiscuity(dev, inc); | 2861 | err = __dev_set_promiscuity(dev, inc); |
2862 | if (!err) | ||
2863 | return err; | ||
2816 | if (dev->flags != old_flags) | 2864 | if (dev->flags != old_flags) |
2817 | dev_set_rx_mode(dev); | 2865 | dev_set_rx_mode(dev); |
2866 | return err; | ||
2818 | } | 2867 | } |
2819 | 2868 | ||
2820 | /** | 2869 | /** |
@@ -2827,22 +2876,38 @@ void dev_set_promiscuity(struct net_device *dev, int inc) | |||
2827 | * to all interfaces. Once it hits zero the device reverts back to normal | 2876 | * to all interfaces. Once it hits zero the device reverts back to normal |
2828 | * filtering operation. A negative @inc value is used to drop the counter | 2877 | * filtering operation. A negative @inc value is used to drop the counter |
2829 | * when releasing a resource needing all multicasts. | 2878 | * when releasing a resource needing all multicasts. |
2879 | * Return 0 if successful or a negative errno code on error. | ||
2830 | */ | 2880 | */ |
2831 | 2881 | ||
2832 | void dev_set_allmulti(struct net_device *dev, int inc) | 2882 | int dev_set_allmulti(struct net_device *dev, int inc) |
2833 | { | 2883 | { |
2834 | unsigned short old_flags = dev->flags; | 2884 | unsigned short old_flags = dev->flags; |
2835 | 2885 | ||
2836 | ASSERT_RTNL(); | 2886 | ASSERT_RTNL(); |
2837 | 2887 | ||
2838 | dev->flags |= IFF_ALLMULTI; | 2888 | dev->flags |= IFF_ALLMULTI; |
2839 | if ((dev->allmulti += inc) == 0) | 2889 | dev->allmulti += inc; |
2840 | dev->flags &= ~IFF_ALLMULTI; | 2890 | if (dev->allmulti == 0) { |
2891 | /* | ||
2892 | * Avoid overflow. | ||
2893 | * If inc causes overflow, untouch allmulti and return error. | ||
2894 | */ | ||
2895 | if (inc < 0) | ||
2896 | dev->flags &= ~IFF_ALLMULTI; | ||
2897 | else { | ||
2898 | dev->allmulti -= inc; | ||
2899 | printk(KERN_WARNING "%s: allmulti touches roof, " | ||
2900 | "set allmulti failed, allmulti feature of " | ||
2901 | "device might be broken.\n", dev->name); | ||
2902 | return -EOVERFLOW; | ||
2903 | } | ||
2904 | } | ||
2841 | if (dev->flags ^ old_flags) { | 2905 | if (dev->flags ^ old_flags) { |
2842 | if (dev->change_rx_flags) | 2906 | if (dev->change_rx_flags) |
2843 | dev->change_rx_flags(dev, IFF_ALLMULTI); | 2907 | dev->change_rx_flags(dev, IFF_ALLMULTI); |
2844 | dev_set_rx_mode(dev); | 2908 | dev_set_rx_mode(dev); |
2845 | } | 2909 | } |
2910 | return 0; | ||
2846 | } | 2911 | } |
2847 | 2912 | ||
2848 | /* | 2913 | /* |