diff options
Diffstat (limited to 'net/core/dev.c')
-rw-r--r-- | net/core/dev.c | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 96443055324e..13a0d9f6da54 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -98,6 +98,7 @@ | |||
98 | #include <linux/seq_file.h> | 98 | #include <linux/seq_file.h> |
99 | #include <linux/stat.h> | 99 | #include <linux/stat.h> |
100 | #include <linux/if_bridge.h> | 100 | #include <linux/if_bridge.h> |
101 | #include <linux/if_macvlan.h> | ||
101 | #include <net/dst.h> | 102 | #include <net/dst.h> |
102 | #include <net/pkt_sched.h> | 103 | #include <net/pkt_sched.h> |
103 | #include <net/checksum.h> | 104 | #include <net/checksum.h> |
@@ -1813,6 +1814,28 @@ static inline struct sk_buff *handle_bridge(struct sk_buff *skb, | |||
1813 | #define handle_bridge(skb, pt_prev, ret, orig_dev) (skb) | 1814 | #define handle_bridge(skb, pt_prev, ret, orig_dev) (skb) |
1814 | #endif | 1815 | #endif |
1815 | 1816 | ||
1817 | #if defined(CONFIG_MACVLAN) || defined(CONFIG_MACVLAN_MODULE) | ||
1818 | struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *skb) __read_mostly; | ||
1819 | EXPORT_SYMBOL_GPL(macvlan_handle_frame_hook); | ||
1820 | |||
1821 | static inline struct sk_buff *handle_macvlan(struct sk_buff *skb, | ||
1822 | struct packet_type **pt_prev, | ||
1823 | int *ret, | ||
1824 | struct net_device *orig_dev) | ||
1825 | { | ||
1826 | if (skb->dev->macvlan_port == NULL) | ||
1827 | return skb; | ||
1828 | |||
1829 | if (*pt_prev) { | ||
1830 | *ret = deliver_skb(skb, *pt_prev, orig_dev); | ||
1831 | *pt_prev = NULL; | ||
1832 | } | ||
1833 | return macvlan_handle_frame_hook(skb); | ||
1834 | } | ||
1835 | #else | ||
1836 | #define handle_macvlan(skb, pt_prev, ret, orig_dev) (skb) | ||
1837 | #endif | ||
1838 | |||
1816 | #ifdef CONFIG_NET_CLS_ACT | 1839 | #ifdef CONFIG_NET_CLS_ACT |
1817 | /* TODO: Maybe we should just force sch_ingress to be compiled in | 1840 | /* TODO: Maybe we should just force sch_ingress to be compiled in |
1818 | * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions | 1841 | * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions |
@@ -1920,6 +1943,9 @@ ncls: | |||
1920 | skb = handle_bridge(skb, &pt_prev, &ret, orig_dev); | 1943 | skb = handle_bridge(skb, &pt_prev, &ret, orig_dev); |
1921 | if (!skb) | 1944 | if (!skb) |
1922 | goto out; | 1945 | goto out; |
1946 | skb = handle_macvlan(skb, &pt_prev, &ret, orig_dev); | ||
1947 | if (!skb) | ||
1948 | goto out; | ||
1923 | 1949 | ||
1924 | type = skb->protocol; | 1950 | type = skb->protocol; |
1925 | list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) { | 1951 | list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) { |
@@ -2521,6 +2547,8 @@ static void __dev_set_promiscuity(struct net_device *dev, int inc) | |||
2521 | { | 2547 | { |
2522 | unsigned short old_flags = dev->flags; | 2548 | unsigned short old_flags = dev->flags; |
2523 | 2549 | ||
2550 | ASSERT_RTNL(); | ||
2551 | |||
2524 | if ((dev->promiscuity += inc) == 0) | 2552 | if ((dev->promiscuity += inc) == 0) |
2525 | dev->flags &= ~IFF_PROMISC; | 2553 | dev->flags &= ~IFF_PROMISC; |
2526 | else | 2554 | else |
@@ -2535,6 +2563,9 @@ static void __dev_set_promiscuity(struct net_device *dev, int inc) | |||
2535 | dev->name, (dev->flags & IFF_PROMISC), | 2563 | dev->name, (dev->flags & IFF_PROMISC), |
2536 | (old_flags & IFF_PROMISC), | 2564 | (old_flags & IFF_PROMISC), |
2537 | audit_get_loginuid(current->audit_context)); | 2565 | audit_get_loginuid(current->audit_context)); |
2566 | |||
2567 | if (dev->change_rx_flags) | ||
2568 | dev->change_rx_flags(dev, IFF_PROMISC); | ||
2538 | } | 2569 | } |
2539 | } | 2570 | } |
2540 | 2571 | ||
@@ -2573,11 +2604,16 @@ void dev_set_allmulti(struct net_device *dev, int inc) | |||
2573 | { | 2604 | { |
2574 | unsigned short old_flags = dev->flags; | 2605 | unsigned short old_flags = dev->flags; |
2575 | 2606 | ||
2607 | ASSERT_RTNL(); | ||
2608 | |||
2576 | dev->flags |= IFF_ALLMULTI; | 2609 | dev->flags |= IFF_ALLMULTI; |
2577 | if ((dev->allmulti += inc) == 0) | 2610 | if ((dev->allmulti += inc) == 0) |
2578 | dev->flags &= ~IFF_ALLMULTI; | 2611 | dev->flags &= ~IFF_ALLMULTI; |
2579 | if (dev->flags ^ old_flags) | 2612 | if (dev->flags ^ old_flags) { |
2613 | if (dev->change_rx_flags) | ||
2614 | dev->change_rx_flags(dev, IFF_ALLMULTI); | ||
2580 | dev_set_rx_mode(dev); | 2615 | dev_set_rx_mode(dev); |
2616 | } | ||
2581 | } | 2617 | } |
2582 | 2618 | ||
2583 | /* | 2619 | /* |
@@ -2778,6 +2814,8 @@ int dev_change_flags(struct net_device *dev, unsigned flags) | |||
2778 | int ret, changes; | 2814 | int ret, changes; |
2779 | int old_flags = dev->flags; | 2815 | int old_flags = dev->flags; |
2780 | 2816 | ||
2817 | ASSERT_RTNL(); | ||
2818 | |||
2781 | /* | 2819 | /* |
2782 | * Set the flags on our device. | 2820 | * Set the flags on our device. |
2783 | */ | 2821 | */ |
@@ -2792,6 +2830,9 @@ int dev_change_flags(struct net_device *dev, unsigned flags) | |||
2792 | * Load in the correct multicast list now the flags have changed. | 2830 | * Load in the correct multicast list now the flags have changed. |
2793 | */ | 2831 | */ |
2794 | 2832 | ||
2833 | if (dev->change_rx_flags && (dev->flags ^ flags) & IFF_MULTICAST) | ||
2834 | dev->change_rx_flags(dev, IFF_MULTICAST); | ||
2835 | |||
2795 | dev_set_rx_mode(dev); | 2836 | dev_set_rx_mode(dev); |
2796 | 2837 | ||
2797 | /* | 2838 | /* |