aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge/br_input.c')
-rw-r--r--net/bridge/br_input.c76
1 files changed, 50 insertions, 26 deletions
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 5ee1a3682bf2..826cd5221536 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -11,6 +11,7 @@
11 * 2 of the License, or (at your option) any later version. 11 * 2 of the License, or (at your option) any later version.
12 */ 12 */
13 13
14#include <linux/slab.h>
14#include <linux/kernel.h> 15#include <linux/kernel.h>
15#include <linux/netdevice.h> 16#include <linux/netdevice.h>
16#include <linux/etherdevice.h> 17#include <linux/etherdevice.h>
@@ -20,27 +21,32 @@
20/* Bridge group multicast address 802.1d (pg 51). */ 21/* Bridge group multicast address 802.1d (pg 51). */
21const u8 br_group_address[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; 22const u8 br_group_address[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
22 23
23static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb) 24static int br_pass_frame_up(struct sk_buff *skb)
24{ 25{
25 struct net_device *indev, *brdev = br->dev; 26 struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev;
27 struct net_bridge *br = netdev_priv(brdev);
28 struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats);
26 29
27 brdev->stats.rx_packets++; 30 u64_stats_update_begin(&brstats->syncp);
28 brdev->stats.rx_bytes += skb->len; 31 brstats->rx_packets++;
32 brstats->rx_bytes += skb->len;
33 u64_stats_update_end(&brstats->syncp);
29 34
30 indev = skb->dev; 35 indev = skb->dev;
31 skb->dev = brdev; 36 skb->dev = brdev;
32 37
33 NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL, 38 return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL,
34 netif_receive_skb); 39 netif_receive_skb);
35} 40}
36 41
37/* note: already called with rcu_read_lock (preempt_disabled) */ 42/* note: already called with rcu_read_lock */
38int br_handle_frame_finish(struct sk_buff *skb) 43int br_handle_frame_finish(struct sk_buff *skb)
39{ 44{
40 const unsigned char *dest = eth_hdr(skb)->h_dest; 45 const unsigned char *dest = eth_hdr(skb)->h_dest;
41 struct net_bridge_port *p = rcu_dereference(skb->dev->br_port); 46 struct net_bridge_port *p = br_port_get_rcu(skb->dev);
42 struct net_bridge *br; 47 struct net_bridge *br;
43 struct net_bridge_fdb_entry *dst; 48 struct net_bridge_fdb_entry *dst;
49 struct net_bridge_mdb_entry *mdst;
44 struct sk_buff *skb2; 50 struct sk_buff *skb2;
45 51
46 if (!p || p->state == BR_STATE_DISABLED) 52 if (!p || p->state == BR_STATE_DISABLED)
@@ -50,9 +56,15 @@ int br_handle_frame_finish(struct sk_buff *skb)
50 br = p->br; 56 br = p->br;
51 br_fdb_update(br, p, eth_hdr(skb)->h_source); 57 br_fdb_update(br, p, eth_hdr(skb)->h_source);
52 58
59 if (is_multicast_ether_addr(dest) &&
60 br_multicast_rcv(br, p, skb))
61 goto drop;
62
53 if (p->state == BR_STATE_LEARNING) 63 if (p->state == BR_STATE_LEARNING)
54 goto drop; 64 goto drop;
55 65
66 BR_INPUT_SKB_CB(skb)->brdev = br->dev;
67
56 /* The packet skb2 goes to the local host (NULL to skip). */ 68 /* The packet skb2 goes to the local host (NULL to skip). */
57 skb2 = NULL; 69 skb2 = NULL;
58 70
@@ -62,27 +74,35 @@ int br_handle_frame_finish(struct sk_buff *skb)
62 dst = NULL; 74 dst = NULL;
63 75
64 if (is_multicast_ether_addr(dest)) { 76 if (is_multicast_ether_addr(dest)) {
77 mdst = br_mdb_get(br, skb);
78 if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) {
79 if ((mdst && !hlist_unhashed(&mdst->mglist)) ||
80 br_multicast_is_router(br))
81 skb2 = skb;
82 br_multicast_forward(mdst, skb, skb2);
83 skb = NULL;
84 if (!skb2)
85 goto out;
86 } else
87 skb2 = skb;
88
65 br->dev->stats.multicast++; 89 br->dev->stats.multicast++;
66 skb2 = skb;
67 } else if ((dst = __br_fdb_get(br, dest)) && dst->is_local) { 90 } else if ((dst = __br_fdb_get(br, dest)) && dst->is_local) {
68 skb2 = skb; 91 skb2 = skb;
69 /* Do not forward the packet since it's local. */ 92 /* Do not forward the packet since it's local. */
70 skb = NULL; 93 skb = NULL;
71 } 94 }
72 95
73 if (skb2 == skb)
74 skb2 = skb_clone(skb, GFP_ATOMIC);
75
76 if (skb2)
77 br_pass_frame_up(br, skb2);
78
79 if (skb) { 96 if (skb) {
80 if (dst) 97 if (dst)
81 br_forward(dst->dst, skb); 98 br_forward(dst->dst, skb, skb2);
82 else 99 else
83 br_flood_forward(br, skb); 100 br_flood_forward(br, skb, skb2);
84 } 101 }
85 102
103 if (skb2)
104 return br_pass_frame_up(skb2);
105
86out: 106out:
87 return 0; 107 return 0;
88drop: 108drop:
@@ -90,13 +110,12 @@ drop:
90 goto out; 110 goto out;
91} 111}
92 112
93/* note: already called with rcu_read_lock (preempt_disabled) */ 113/* note: already called with rcu_read_lock */
94static int br_handle_local_finish(struct sk_buff *skb) 114static int br_handle_local_finish(struct sk_buff *skb)
95{ 115{
96 struct net_bridge_port *p = rcu_dereference(skb->dev->br_port); 116 struct net_bridge_port *p = br_port_get_rcu(skb->dev);
97 117
98 if (p) 118 br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
99 br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
100 return 0; /* process further */ 119 return 0; /* process further */
101} 120}
102 121
@@ -113,15 +132,18 @@ static inline int is_link_local(const unsigned char *dest)
113} 132}
114 133
115/* 134/*
116 * Called via br_handle_frame_hook.
117 * Return NULL if skb is handled 135 * Return NULL if skb is handled
118 * note: already called with rcu_read_lock (preempt_disabled) 136 * note: already called with rcu_read_lock
119 */ 137 */
120struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb) 138struct sk_buff *br_handle_frame(struct sk_buff *skb)
121{ 139{
140 struct net_bridge_port *p;
122 const unsigned char *dest = eth_hdr(skb)->h_dest; 141 const unsigned char *dest = eth_hdr(skb)->h_dest;
123 int (*rhook)(struct sk_buff *skb); 142 int (*rhook)(struct sk_buff *skb);
124 143
144 if (skb->pkt_type == PACKET_LOOPBACK)
145 return skb;
146
125 if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) 147 if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
126 goto drop; 148 goto drop;
127 149
@@ -129,6 +151,8 @@ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb)
129 if (!skb) 151 if (!skb)
130 return NULL; 152 return NULL;
131 153
154 p = br_port_get_rcu(skb->dev);
155
132 if (unlikely(is_link_local(dest))) { 156 if (unlikely(is_link_local(dest))) {
133 /* Pause frames shouldn't be passed up by driver anyway */ 157 /* Pause frames shouldn't be passed up by driver anyway */
134 if (skb->protocol == htons(ETH_P_PAUSE)) 158 if (skb->protocol == htons(ETH_P_PAUSE))
@@ -138,7 +162,7 @@ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb)
138 if (p->br->stp_enabled == BR_NO_STP && dest[5] == 0) 162 if (p->br->stp_enabled == BR_NO_STP && dest[5] == 0)
139 goto forward; 163 goto forward;
140 164
141 if (NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, 165 if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
142 NULL, br_handle_local_finish)) 166 NULL, br_handle_local_finish))
143 return NULL; /* frame consumed by filter */ 167 return NULL; /* frame consumed by filter */
144 else 168 else
@@ -159,7 +183,7 @@ forward:
159 if (!compare_ether_addr(p->br->dev->dev_addr, dest)) 183 if (!compare_ether_addr(p->br->dev->dev_addr, dest))
160 skb->pkt_type = PACKET_HOST; 184 skb->pkt_type = PACKET_HOST;
161 185
162 NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, 186 NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
163 br_handle_frame_finish); 187 br_handle_frame_finish);
164 break; 188 break;
165 default: 189 default: