aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_input.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /net/bridge/br_input.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'net/bridge/br_input.c')
-rw-r--r--net/bridge/br_input.c48
1 files changed, 30 insertions, 18 deletions
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 826cd5221536..f06ee39c73fd 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -21,6 +21,10 @@
21/* Bridge group multicast address 802.1d (pg 51). */ 21/* Bridge group multicast address 802.1d (pg 51). */
22const 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 };
23 23
24/* Hook for brouter */
25br_should_route_hook_t __rcu *br_should_route_hook __read_mostly;
26EXPORT_SYMBOL(br_should_route_hook);
27
24static int br_pass_frame_up(struct sk_buff *skb) 28static int br_pass_frame_up(struct sk_buff *skb)
25{ 29{
26 struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev; 30 struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev;
@@ -56,7 +60,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
56 br = p->br; 60 br = p->br;
57 br_fdb_update(br, p, eth_hdr(skb)->h_source); 61 br_fdb_update(br, p, eth_hdr(skb)->h_source);
58 62
59 if (is_multicast_ether_addr(dest) && 63 if (!is_broadcast_ether_addr(dest) && is_multicast_ether_addr(dest) &&
60 br_multicast_rcv(br, p, skb)) 64 br_multicast_rcv(br, p, skb))
61 goto drop; 65 goto drop;
62 66
@@ -73,10 +77,12 @@ int br_handle_frame_finish(struct sk_buff *skb)
73 77
74 dst = NULL; 78 dst = NULL;
75 79
76 if (is_multicast_ether_addr(dest)) { 80 if (is_broadcast_ether_addr(dest))
81 skb2 = skb;
82 else if (is_multicast_ether_addr(dest)) {
77 mdst = br_mdb_get(br, skb); 83 mdst = br_mdb_get(br, skb);
78 if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) { 84 if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) {
79 if ((mdst && !hlist_unhashed(&mdst->mglist)) || 85 if ((mdst && mdst->mglist) ||
80 br_multicast_is_router(br)) 86 br_multicast_is_router(br))
81 skb2 = skb; 87 skb2 = skb;
82 br_multicast_forward(mdst, skb, skb2); 88 br_multicast_forward(mdst, skb, skb2);
@@ -94,9 +100,10 @@ int br_handle_frame_finish(struct sk_buff *skb)
94 } 100 }
95 101
96 if (skb) { 102 if (skb) {
97 if (dst) 103 if (dst) {
104 dst->used = jiffies;
98 br_forward(dst->dst, skb, skb2); 105 br_forward(dst->dst, skb, skb2);
99 else 106 } else
100 br_flood_forward(br, skb, skb2); 107 br_flood_forward(br, skb, skb2);
101 } 108 }
102 109
@@ -135,21 +142,22 @@ static inline int is_link_local(const unsigned char *dest)
135 * Return NULL if skb is handled 142 * Return NULL if skb is handled
136 * note: already called with rcu_read_lock 143 * note: already called with rcu_read_lock
137 */ 144 */
138struct sk_buff *br_handle_frame(struct sk_buff *skb) 145rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
139{ 146{
140 struct net_bridge_port *p; 147 struct net_bridge_port *p;
148 struct sk_buff *skb = *pskb;
141 const unsigned char *dest = eth_hdr(skb)->h_dest; 149 const unsigned char *dest = eth_hdr(skb)->h_dest;
142 int (*rhook)(struct sk_buff *skb); 150 br_should_route_hook_t *rhook;
143 151
144 if (skb->pkt_type == PACKET_LOOPBACK) 152 if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
145 return skb; 153 return RX_HANDLER_PASS;
146 154
147 if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) 155 if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
148 goto drop; 156 goto drop;
149 157
150 skb = skb_share_check(skb, GFP_ATOMIC); 158 skb = skb_share_check(skb, GFP_ATOMIC);
151 if (!skb) 159 if (!skb)
152 return NULL; 160 return RX_HANDLER_CONSUMED;
153 161
154 p = br_port_get_rcu(skb->dev); 162 p = br_port_get_rcu(skb->dev);
155 163
@@ -163,19 +171,23 @@ struct sk_buff *br_handle_frame(struct sk_buff *skb)
163 goto forward; 171 goto forward;
164 172
165 if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, 173 if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
166 NULL, br_handle_local_finish)) 174 NULL, br_handle_local_finish)) {
167 return NULL; /* frame consumed by filter */ 175 return RX_HANDLER_CONSUMED; /* consumed by filter */
168 else 176 } else {
169 return skb; /* continue processing */ 177 *pskb = skb;
178 return RX_HANDLER_PASS; /* continue processing */
179 }
170 } 180 }
171 181
172forward: 182forward:
173 switch (p->state) { 183 switch (p->state) {
174 case BR_STATE_FORWARDING: 184 case BR_STATE_FORWARDING:
175 rhook = rcu_dereference(br_should_route_hook); 185 rhook = rcu_dereference(br_should_route_hook);
176 if (rhook != NULL) { 186 if (rhook) {
177 if (rhook(skb)) 187 if ((*rhook)(skb)) {
178 return skb; 188 *pskb = skb;
189 return RX_HANDLER_PASS;
190 }
179 dest = eth_hdr(skb)->h_dest; 191 dest = eth_hdr(skb)->h_dest;
180 } 192 }
181 /* fall through */ 193 /* fall through */
@@ -190,5 +202,5 @@ forward:
190drop: 202drop:
191 kfree_skb(skb); 203 kfree_skb(skb);
192 } 204 }
193 return NULL; 205 return RX_HANDLER_CONSUMED;
194} 206}