blob: 8347916efe88544b50f27a440ca975065a189e0e [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Forwarding decision
3 * Linux ethernet bridge
4 *
5 * Authors:
6 * Lennert Buytenhek <buytenh@gnu.org>
7 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13
Herbert Xu025d89c2010-02-27 19:41:43 +000014#include <linux/err.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include <linux/kernel.h>
16#include <linux/netdevice.h>
17#include <linux/skbuff.h>
Stephen Hemminger85ca7192006-04-26 02:39:19 -070018#include <linux/if_vlan.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include <linux/netfilter_bridge.h>
20#include "br_private.h"
21
Michael Braun7f7708f2010-03-16 00:26:22 -070022static int deliver_clone(struct net_bridge_port *prev, struct sk_buff *skb,
23 void (*__packet_hook)(const struct net_bridge_port *p,
24 struct sk_buff *skb));
25
Stephen Hemminger9ef513b2006-05-25 15:58:54 -070026/* Don't forward packets to originating port or forwarding diasabled */
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +090027static inline int should_deliver(const struct net_bridge_port *p,
Linus Torvalds1da177e2005-04-16 15:20:36 -070028 const struct sk_buff *skb)
29{
Fischer, Anna3982d3d2009-08-13 06:55:16 +000030 return (((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) &&
31 p->state == BR_STATE_FORWARDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -070032}
33
Stephen Hemminger85ca7192006-04-26 02:39:19 -070034static inline unsigned packet_length(const struct sk_buff *skb)
35{
36 return skb->len - (skb->protocol == htons(ETH_P_8021Q) ? VLAN_HLEN : 0);
37}
38
Linus Torvalds1da177e2005-04-16 15:20:36 -070039int br_dev_queue_push_xmit(struct sk_buff *skb)
40{
Herbert Xu79671682006-06-22 02:40:14 -070041 /* drop mtu oversized packets except gso */
Herbert Xu89114af2006-07-08 13:34:32 -070042 if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -070043 kfree_skb(skb);
44 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -070045 /* ip_refrag calls ip_fragment, doesn't copy the MAC header. */
Stephen Hemminger3a138132006-08-26 20:28:30 -070046 if (nf_bridge_maybe_copy_header(skb))
47 kfree_skb(skb);
Stephen Hemminger07317622006-08-29 17:48:17 -070048 else {
Stephen Hemminger3a138132006-08-26 20:28:30 -070049 skb_push(skb, ETH_HLEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
Stephen Hemminger3a138132006-08-26 20:28:30 -070051 dev_queue_xmit(skb);
52 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070053 }
54
55 return 0;
56}
57
58int br_forward_finish(struct sk_buff *skb)
59{
Stephen Hemminger9ef513b2006-05-25 15:58:54 -070060 return NF_HOOK(PF_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev,
61 br_dev_queue_push_xmit);
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Linus Torvalds1da177e2005-04-16 15:20:36 -070063}
64
65static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
66{
67 skb->dev = to->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -070068 NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
69 br_forward_finish);
70}
71
72static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
73{
74 struct net_device *indev;
75
Herbert Xu4906f992009-02-09 15:07:18 -080076 if (skb_warn_if_lro(skb)) {
77 kfree_skb(skb);
78 return;
79 }
80
Linus Torvalds1da177e2005-04-16 15:20:36 -070081 indev = skb->dev;
82 skb->dev = to->dev;
Herbert Xu35fc92a2007-03-26 23:22:20 -070083 skb_forward_csum(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -070084
85 NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev,
86 br_forward_finish);
87}
88
89/* called with rcu_read_lock */
90void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
91{
92 if (should_deliver(to, skb)) {
93 __br_deliver(to, skb);
94 return;
95 }
96
97 kfree_skb(skb);
98}
99
100/* called with rcu_read_lock */
Michael Braun7f7708f2010-03-16 00:26:22 -0700101void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, struct sk_buff *skb0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102{
Herbert Xu4906f992009-02-09 15:07:18 -0800103 if (should_deliver(to, skb)) {
Michael Braun7f7708f2010-03-16 00:26:22 -0700104 if (skb0)
105 deliver_clone(to, skb, __br_forward);
106 else
107 __br_forward(to, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 return;
109 }
110
Michael Braun7f7708f2010-03-16 00:26:22 -0700111 if (!skb0)
112 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113}
114
Herbert Xu025d89c2010-02-27 19:41:43 +0000115static int deliver_clone(struct net_bridge_port *prev, struct sk_buff *skb,
116 void (*__packet_hook)(const struct net_bridge_port *p,
117 struct sk_buff *skb))
118{
119 skb = skb_clone(skb, GFP_ATOMIC);
120 if (!skb) {
121 struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
122
123 dev->stats.tx_dropped++;
124 return -ENOMEM;
125 }
126
127 __packet_hook(prev, skb);
128 return 0;
129}
130
131static struct net_bridge_port *maybe_deliver(
132 struct net_bridge_port *prev, struct net_bridge_port *p,
133 struct sk_buff *skb,
134 void (*__packet_hook)(const struct net_bridge_port *p,
135 struct sk_buff *skb))
136{
137 int err;
138
139 if (!should_deliver(p, skb))
140 return prev;
141
142 if (!prev)
143 goto out;
144
145 err = deliver_clone(prev, skb, __packet_hook);
146 if (err)
147 return ERR_PTR(err);
148
149out:
150 return p;
151}
152
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153/* called under bridge lock */
Herbert Xue081e1e2007-09-16 16:20:48 -0700154static void br_flood(struct net_bridge *br, struct sk_buff *skb,
Herbert Xub33084b2010-02-27 19:41:41 +0000155 struct sk_buff *skb0,
156 void (*__packet_hook)(const struct net_bridge_port *p,
157 struct sk_buff *skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158{
159 struct net_bridge_port *p;
160 struct net_bridge_port *prev;
161
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 prev = NULL;
163
164 list_for_each_entry_rcu(p, &br->port_list, list) {
Herbert Xu025d89c2010-02-27 19:41:43 +0000165 prev = maybe_deliver(prev, p, skb, __packet_hook);
166 if (IS_ERR(prev))
167 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 }
169
Herbert Xub33084b2010-02-27 19:41:41 +0000170 if (!prev)
171 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172
Herbert Xu025d89c2010-02-27 19:41:43 +0000173 if (skb0)
174 deliver_clone(prev, skb, __packet_hook);
175 else
176 __packet_hook(prev, skb);
Herbert Xub33084b2010-02-27 19:41:41 +0000177 return;
178
179out:
180 if (!skb0)
181 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182}
183
184
185/* called with rcu_read_lock */
Herbert Xue081e1e2007-09-16 16:20:48 -0700186void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187{
Herbert Xub33084b2010-02-27 19:41:41 +0000188 br_flood(br, skb, NULL, __br_deliver);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189}
190
191/* called under bridge lock */
Herbert Xub33084b2010-02-27 19:41:41 +0000192void br_flood_forward(struct net_bridge *br, struct sk_buff *skb,
193 struct sk_buff *skb2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194{
Herbert Xub33084b2010-02-27 19:41:41 +0000195 br_flood(br, skb, skb2, __br_forward);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196}
Herbert Xu5cb5e942010-02-27 19:41:46 +0000197
198#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
199/* called with rcu_read_lock */
200static void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
201 struct sk_buff *skb, struct sk_buff *skb0,
202 void (*__packet_hook)(
203 const struct net_bridge_port *p,
204 struct sk_buff *skb))
205{
206 struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
207 struct net_bridge *br = netdev_priv(dev);
208 struct net_bridge_port *port;
209 struct net_bridge_port *lport, *rport;
210 struct net_bridge_port *prev;
211 struct net_bridge_port_group *p;
212 struct hlist_node *rp;
213
214 prev = NULL;
215
216 rp = br->router_list.first;
217 p = mdst ? mdst->ports : NULL;
218 while (p || rp) {
219 lport = p ? p->port : NULL;
220 rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) :
221 NULL;
222
223 port = (unsigned long)lport > (unsigned long)rport ?
224 lport : rport;
225
226 prev = maybe_deliver(prev, port, skb, __packet_hook);
227 if (IS_ERR(prev))
228 goto out;
229
230 if ((unsigned long)lport >= (unsigned long)port)
231 p = p->next;
232 if ((unsigned long)rport >= (unsigned long)port)
233 rp = rp->next;
234 }
235
236 if (!prev)
237 goto out;
238
239 if (skb0)
240 deliver_clone(prev, skb, __packet_hook);
241 else
242 __packet_hook(prev, skb);
243 return;
244
245out:
246 if (!skb0)
247 kfree_skb(skb);
248}
249
250/* called with rcu_read_lock */
251void br_multicast_deliver(struct net_bridge_mdb_entry *mdst,
252 struct sk_buff *skb)
253{
254 br_multicast_flood(mdst, skb, NULL, __br_deliver);
255}
256
257/* called with rcu_read_lock */
258void br_multicast_forward(struct net_bridge_mdb_entry *mdst,
259 struct sk_buff *skb, struct sk_buff *skb2)
260{
261 br_multicast_flood(mdst, skb, skb2, __br_forward);
262}
263#endif