br_forward.c 7.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 *	Forwarding decision
 *	Linux ethernet bridge
 *
 *	Authors:
 *	Lennert Buytenhek		<buytenh@gnu.org>
 *
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License
 *	as published by the Free Software Foundation; either version
 *	2 of the License, or (at your option) any later version.
 */

14
#include <linux/err.h>
15
#include <linux/slab.h>
L
Linus Torvalds 已提交
16 17
#include <linux/kernel.h>
#include <linux/netdevice.h>
W
WANG Cong 已提交
18
#include <linux/netpoll.h>
L
Linus Torvalds 已提交
19
#include <linux/skbuff.h>
20
#include <linux/if_vlan.h>
L
Linus Torvalds 已提交
21 22 23
#include <linux/netfilter_bridge.h>
#include "br_private.h"

24 25
static int deliver_clone(const struct net_bridge_port *prev,
			 struct sk_buff *skb,
26 27 28
			 void (*__packet_hook)(const struct net_bridge_port *p,
					       struct sk_buff *skb));

T
tanxiaojun 已提交
29
/* Don't forward packets to originating port or forwarding disabled */
30
static inline int should_deliver(const struct net_bridge_port *p,
L
Linus Torvalds 已提交
31 32
				 const struct sk_buff *skb)
{
33 34 35
	struct net_bridge_vlan_group *vg;

	vg = nbp_vlan_group(p);
36
	return ((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) &&
37
		br_allowed_egress(vg, skb) && p->state == BR_STATE_FORWARDING;
L
Linus Torvalds 已提交
38 39
}

40
int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb)
L
Linus Torvalds 已提交
41
{
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
	if (!is_skb_forwardable(skb->dev, skb))
		goto drop;

	skb_push(skb, ETH_HLEN);
	br_drop_fake_rtable(skb);
	skb_sender_cpu_clear(skb);

	if (skb->ip_summed == CHECKSUM_PARTIAL &&
	    (skb->protocol == htons(ETH_P_8021Q) ||
	     skb->protocol == htons(ETH_P_8021AD))) {
		int depth;

		if (!__vlan_get_protocol(skb, skb->protocol, &depth))
			goto drop;

		skb_set_network_header(skb, depth);
L
Linus Torvalds 已提交
58 59
	}

60 61 62 63 64 65
	dev_queue_xmit(skb);

	return 0;

drop:
	kfree_skb(skb);
L
Linus Torvalds 已提交
66 67
	return 0;
}
68
EXPORT_SYMBOL_GPL(br_dev_queue_push_xmit);
L
Linus Torvalds 已提交
69

70
int br_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
L
Linus Torvalds 已提交
71
{
72 73
	return NF_HOOK(NFPROTO_BRIDGE, NF_BR_POST_ROUTING,
		       net, sk, skb, NULL, skb->dev,
74
		       br_dev_queue_push_xmit);
L
Linus Torvalds 已提交
75 76

}
77
EXPORT_SYMBOL_GPL(br_forward_finish);
L
Linus Torvalds 已提交
78 79 80

static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
{
81 82 83 84
	struct net_bridge_vlan_group *vg;

	vg = nbp_vlan_group(to);
	skb = br_handle_vlan(to->br, vg, skb);
85 86 87
	if (!skb)
		return;

L
Linus Torvalds 已提交
88
	skb->dev = to->dev;
H
Herbert Xu 已提交
89

90
	if (unlikely(netpoll_tx_running(to->br->dev))) {
91
		if (!is_skb_forwardable(skb->dev, skb))
H
Herbert Xu 已提交
92 93 94 95 96 97 98 99
			kfree_skb(skb);
		else {
			skb_push(skb, ETH_HLEN);
			br_netpoll_send_skb(to, skb);
		}
		return;
	}

100 101
	NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT,
		dev_net(skb->dev), NULL, skb,NULL, skb->dev,
102
		br_forward_finish);
L
Linus Torvalds 已提交
103 104 105 106
}

static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
{
107
	struct net_bridge_vlan_group *vg;
L
Linus Torvalds 已提交
108 109
	struct net_device *indev;

H
Herbert Xu 已提交
110 111 112 113 114
	if (skb_warn_if_lro(skb)) {
		kfree_skb(skb);
		return;
	}

115 116
	vg = nbp_vlan_group(to);
	skb = br_handle_vlan(to->br, vg, skb);
117 118 119
	if (!skb)
		return;

L
Linus Torvalds 已提交
120 121
	indev = skb->dev;
	skb->dev = to->dev;
122
	skb_forward_csum(skb);
L
Linus Torvalds 已提交
123

124 125
	NF_HOOK(NFPROTO_BRIDGE, NF_BR_FORWARD,
		dev_net(indev), NULL, skb, indev, skb->dev,
126
		br_forward_finish);
L
Linus Torvalds 已提交
127 128 129 130 131
}

/* called with rcu_read_lock */
void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
{
132
	if (to && should_deliver(to, skb)) {
L
Linus Torvalds 已提交
133 134 135 136 137 138
		__br_deliver(to, skb);
		return;
	}

	kfree_skb(skb);
}
139
EXPORT_SYMBOL_GPL(br_deliver);
L
Linus Torvalds 已提交
140 141

/* called with rcu_read_lock */
142
void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, struct sk_buff *skb0)
L
Linus Torvalds 已提交
143
{
H
Herbert Xu 已提交
144
	if (should_deliver(to, skb)) {
145 146 147 148
		if (skb0)
			deliver_clone(to, skb, __br_forward);
		else
			__br_forward(to, skb);
L
Linus Torvalds 已提交
149 150 151
		return;
	}

152 153
	if (!skb0)
		kfree_skb(skb);
L
Linus Torvalds 已提交
154 155
}

156 157
static int deliver_clone(const struct net_bridge_port *prev,
			 struct sk_buff *skb,
158 159 160
			 void (*__packet_hook)(const struct net_bridge_port *p,
					       struct sk_buff *skb))
{
161 162
	struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;

163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
	skb = skb_clone(skb, GFP_ATOMIC);
	if (!skb) {
		dev->stats.tx_dropped++;
		return -ENOMEM;
	}

	__packet_hook(prev, skb);
	return 0;
}

static struct net_bridge_port *maybe_deliver(
	struct net_bridge_port *prev, struct net_bridge_port *p,
	struct sk_buff *skb,
	void (*__packet_hook)(const struct net_bridge_port *p,
			      struct sk_buff *skb))
{
	int err;

	if (!should_deliver(p, skb))
		return prev;

	if (!prev)
		goto out;

	err = deliver_clone(prev, skb, __packet_hook);
	if (err)
		return ERR_PTR(err);

out:
	return p;
}

L
Linus Torvalds 已提交
195
/* called under bridge lock */
196
static void br_flood(struct net_bridge *br, struct sk_buff *skb,
197 198
		     struct sk_buff *skb0,
		     void (*__packet_hook)(const struct net_bridge_port *p,
199 200
					   struct sk_buff *skb),
		     bool unicast)
L
Linus Torvalds 已提交
201 202 203 204 205 206 207
{
	struct net_bridge_port *p;
	struct net_bridge_port *prev;

	prev = NULL;

	list_for_each_entry_rcu(p, &br->port_list, list) {
208 209 210
		/* Do not flood unicast traffic to ports that turn it off */
		if (unicast && !(p->flags & BR_FLOOD))
			continue;
211 212 213 214

		/* Do not flood to ports that enable proxy ARP */
		if (p->flags & BR_PROXYARP)
			continue;
215 216 217
		if ((p->flags & BR_PROXYARP_WIFI) &&
		    BR_INPUT_SKB_CB(skb)->proxyarp_replied)
			continue;
218

219 220 221
		prev = maybe_deliver(prev, p, skb, __packet_hook);
		if (IS_ERR(prev))
			goto out;
L
Linus Torvalds 已提交
222 223
	}

224 225 226
	if (!prev)
		goto out;

227 228 229 230
	if (skb0)
		deliver_clone(prev, skb, __packet_hook);
	else
		__packet_hook(prev, skb);
231
	return;
L
Linus Torvalds 已提交
232

233 234 235
out:
	if (!skb0)
		kfree_skb(skb);
L
Linus Torvalds 已提交
236 237 238 239
}


/* called with rcu_read_lock */
240
void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb, bool unicast)
L
Linus Torvalds 已提交
241
{
242
	br_flood(br, skb, NULL, __br_deliver, unicast);
L
Linus Torvalds 已提交
243 244 245
}

/* called under bridge lock */
246
void br_flood_forward(struct net_bridge *br, struct sk_buff *skb,
247
		      struct sk_buff *skb2, bool unicast)
L
Linus Torvalds 已提交
248
{
249
	br_flood(br, skb, skb2, __br_forward, unicast);
L
Linus Torvalds 已提交
250
}
251 252 253 254 255 256 257 258 259 260 261

#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
/* called with rcu_read_lock */
static void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
			       struct sk_buff *skb, struct sk_buff *skb0,
			       void (*__packet_hook)(
					const struct net_bridge_port *p,
					struct sk_buff *skb))
{
	struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
	struct net_bridge *br = netdev_priv(dev);
262
	struct net_bridge_port *prev = NULL;
263 264 265
	struct net_bridge_port_group *p;
	struct hlist_node *rp;

266
	rp = rcu_dereference(hlist_first_rcu(&br->router_list));
267
	p = mdst ? rcu_dereference(mdst->ports) : NULL;
268
	while (p || rp) {
269 270
		struct net_bridge_port *port, *lport, *rport;

271 272 273 274 275 276 277 278 279 280 281 282
		lport = p ? p->port : NULL;
		rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) :
			     NULL;

		port = (unsigned long)lport > (unsigned long)rport ?
		       lport : rport;

		prev = maybe_deliver(prev, port, skb, __packet_hook);
		if (IS_ERR(prev))
			goto out;

		if ((unsigned long)lport >= (unsigned long)port)
283
			p = rcu_dereference(p->next);
284
		if ((unsigned long)rport >= (unsigned long)port)
285
			rp = rcu_dereference(hlist_next_rcu(rp));
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
	}

	if (!prev)
		goto out;

	if (skb0)
		deliver_clone(prev, skb, __packet_hook);
	else
		__packet_hook(prev, skb);
	return;

out:
	if (!skb0)
		kfree_skb(skb);
}

/* called with rcu_read_lock */
void br_multicast_deliver(struct net_bridge_mdb_entry *mdst,
			  struct sk_buff *skb)
{
	br_multicast_flood(mdst, skb, NULL, __br_deliver);
}

/* called with rcu_read_lock */
void br_multicast_forward(struct net_bridge_mdb_entry *mdst,
			  struct sk_buff *skb, struct sk_buff *skb2)
{
	br_multicast_flood(mdst, skb, skb2, __br_forward);
}
#endif