Blame view

net/bridge/br_fdb.c 19.4 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
  /*
   *	Forwarding database
   *	Linux ethernet bridge
   *
   *	Authors:
   *	Lennert Buytenhek		<buytenh@gnu.org>
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
11
12
13
14
15
   *	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.
   */
  
  #include <linux/kernel.h>
  #include <linux/init.h>
82524746c   Franck Bui-Huu   rcu: split list.h...
16
  #include <linux/rculist.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
18
19
20
21
  #include <linux/spinlock.h>
  #include <linux/times.h>
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
  #include <linux/jhash.h>
3f8909231   Stephen Hemminger   bridge: simpler h...
22
  #include <linux/random.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
23
  #include <linux/slab.h>
60063497a   Arun Sharma   atomic: use <linu...
24
  #include <linux/atomic.h>
3f8909231   Stephen Hemminger   bridge: simpler h...
25
  #include <asm/unaligned.h>
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
26
  #include <linux/if_vlan.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
  #include "br_private.h"
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
28
  static struct kmem_cache *br_fdb_cache __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
  static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
30
  		      const unsigned char *addr, u16 vid);
31e8a49c1   stephen hemminger   bridge: rearrange...
31
32
  static void fdb_notify(struct net_bridge *br,
  		       const struct net_bridge_fdb_entry *, int);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33

3f8909231   Stephen Hemminger   bridge: simpler h...
34
  static u32 fdb_salt __read_mostly;
87a596e0b   Akinobu Mita   bridge: check kme...
35
  int __init br_fdb_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
38
39
  {
  	br_fdb_cache = kmem_cache_create("bridge_fdb_cache",
  					 sizeof(struct net_bridge_fdb_entry),
  					 0,
20c2df83d   Paul Mundt   mm: Remove slab d...
40
  					 SLAB_HWCACHE_ALIGN, NULL);
87a596e0b   Akinobu Mita   bridge: check kme...
41
42
  	if (!br_fdb_cache)
  		return -ENOMEM;
3f8909231   Stephen Hemminger   bridge: simpler h...
43
  	get_random_bytes(&fdb_salt, sizeof(fdb_salt));
87a596e0b   Akinobu Mita   bridge: check kme...
44
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
  }
73afc9069   Andrew Morton   [BRIDGE]: Section...
46
  void br_fdb_fini(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
48
49
50
51
52
53
54
  {
  	kmem_cache_destroy(br_fdb_cache);
  }
  
  
  /* if topology_changing then use forward_delay (default 15 sec)
   * otherwise keep longer (default 5 minutes)
   */
3f8909231   Stephen Hemminger   bridge: simpler h...
55
  static inline unsigned long hold_time(const struct net_bridge *br)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
58
  {
  	return br->topology_change ? br->forward_delay : br->ageing_time;
  }
3f8909231   Stephen Hemminger   bridge: simpler h...
59
  static inline int has_expired(const struct net_bridge *br,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
  				  const struct net_bridge_fdb_entry *fdb)
  {
f64f9e719   Joe Perches   net: Move && and ...
62
  	return !fdb->is_static &&
7cd8861ab   stephen hemminger   bridge: track las...
63
  		time_before_eq(fdb->updated + hold_time(br), jiffies);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
  }
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
65
  static inline int br_mac_hash(const unsigned char *mac, __u16 vid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
  {
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
67
  	/* use 1 byte of OUI and 3 bytes of NIC */
3f8909231   Stephen Hemminger   bridge: simpler h...
68
  	u32 key = get_unaligned((u32 *)(mac + 2));
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
69
  	return jhash_2words(key, vid, fdb_salt) & (BR_HASH_SIZE - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
  }
da6782927   Michał Mirosław   bridge: Simplify ...
71
72
73
74
75
76
  static void fdb_rcu_free(struct rcu_head *head)
  {
  	struct net_bridge_fdb_entry *ent
  		= container_of(head, struct net_bridge_fdb_entry, rcu);
  	kmem_cache_free(br_fdb_cache, ent);
  }
31e8a49c1   stephen hemminger   bridge: rearrange...
77
  static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
  {
  	hlist_del_rcu(&f->hlist);
31e8a49c1   stephen hemminger   bridge: rearrange...
80
  	fdb_notify(br, f, RTM_DELNEIGH);
da6782927   Michał Mirosław   bridge: Simplify ...
81
  	call_rcu(&f->rcu, fdb_rcu_free);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
83
84
85
86
  }
  
  void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr)
  {
  	struct net_bridge *br = p->br;
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
87
  	bool no_vlan = (nbp_get_vlan_info(p) == NULL) ? true : false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
  	int i;
9d6f229fc   YOSHIFUJI Hideaki   [NET] BRIDGE: Fix...
89

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
92
93
94
95
96
97
98
99
100
101
  	spin_lock_bh(&br->hash_lock);
  
  	/* Search all chains since old address/hash is unknown */
  	for (i = 0; i < BR_HASH_SIZE; i++) {
  		struct hlist_node *h;
  		hlist_for_each(h, &br->hash[i]) {
  			struct net_bridge_fdb_entry *f;
  
  			f = hlist_entry(h, struct net_bridge_fdb_entry, hlist);
  			if (f->dst == p && f->is_local) {
  				/* maybe another port has same hw addr? */
  				struct net_bridge_port *op;
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
102
  				u16 vid = f->vlan_id;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
  				list_for_each_entry(op, &br->port_list, list) {
9d6f229fc   YOSHIFUJI Hideaki   [NET] BRIDGE: Fix...
104
  					if (op != p &&
9a7b6ef9b   Joe Perches   bridge: Convert c...
105
  					    ether_addr_equal(op->dev->dev_addr,
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
106
107
  							     f->addr.addr) &&
  					    nbp_vlan_find(op, vid)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
109
110
111
112
113
  						f->dst = op;
  						goto insert;
  					}
  				}
  
  				/* delete old one */
31e8a49c1   stephen hemminger   bridge: rearrange...
114
  				fdb_delete(br, f);
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
115
116
117
118
119
120
121
122
123
124
125
126
  insert:
  				/* insert new address,  may fail if invalid
  				 * address or dup.
  				 */
  				fdb_insert(br, p, newaddr, vid);
  
  				/* if this port has no vlan information
  				 * configured, we can safely be done at
  				 * this point.
  				 */
  				if (no_vlan)
  					goto done;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
128
129
  			}
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130

bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
131
  done:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
133
  	spin_unlock_bh(&br->hash_lock);
  }
435988133   stephen hemminger   bridge: add local...
134
135
136
  void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
  {
  	struct net_bridge_fdb_entry *f;
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
137
138
  	struct net_port_vlans *pv;
  	u16 vid = 0;
435988133   stephen hemminger   bridge: add local...
139
140
  
  	/* If old entry was unassociated with any port, then delete it. */
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
141
  	f = __br_fdb_get(br, br->dev->dev_addr, 0);
435988133   stephen hemminger   bridge: add local...
142
143
  	if (f && f->is_local && !f->dst)
  		fdb_delete(br, f);
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
144
145
146
147
148
149
150
151
152
  	fdb_insert(br, NULL, newaddr, 0);
  
  	/* Now remove and add entries for every VLAN configured on the
  	 * bridge.  This function runs under RTNL so the bitmap will not
  	 * change from under us.
  	 */
  	pv = br_get_vlan_info(br);
  	if (!pv)
  		return;
9f0bd377e   Toshiaki Makita   bridge: Use the c...
153
  	for_each_set_bit_from(vid, pv->vlan_bitmap, VLAN_N_VID) {
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
154
155
156
157
158
  		f = __br_fdb_get(br, br->dev->dev_addr, vid);
  		if (f && f->is_local && !f->dst)
  			fdb_delete(br, f);
  		fdb_insert(br, NULL, newaddr, vid);
  	}
435988133   stephen hemminger   bridge: add local...
159
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
162
163
  void br_fdb_cleanup(unsigned long _data)
  {
  	struct net_bridge *br = (struct net_bridge *)_data;
  	unsigned long delay = hold_time(br);
25442e06d   stephen hemminger   bridge: fdb clean...
164
  	unsigned long next_timer = jiffies + br->ageing_time;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
  	int i;
27a429383   Eric Dumazet   bridge: BH alread...
166
  	spin_lock(&br->hash_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
168
  	for (i = 0; i < BR_HASH_SIZE; i++) {
  		struct net_bridge_fdb_entry *f;
b67bfe0d4   Sasha Levin   hlist: drop the n...
169
  		struct hlist_node *n;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170

b67bfe0d4   Sasha Levin   hlist: drop the n...
171
  		hlist_for_each_entry_safe(f, n, &br->hash[i], hlist) {
071f77226   Baruch Even   [BRIDGE]: Reduce ...
172
173
174
  			unsigned long this_timer;
  			if (f->is_static)
  				continue;
7cd8861ab   stephen hemminger   bridge: track las...
175
  			this_timer = f->updated + delay;
071f77226   Baruch Even   [BRIDGE]: Reduce ...
176
  			if (time_before_eq(this_timer, jiffies))
31e8a49c1   stephen hemminger   bridge: rearrange...
177
  				fdb_delete(br, f);
2bec008ca   Fabio Checconi   bridge: use time_...
178
  			else if (time_before(this_timer, next_timer))
071f77226   Baruch Even   [BRIDGE]: Reduce ...
179
  				next_timer = this_timer;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
181
  		}
  	}
27a429383   Eric Dumazet   bridge: BH alread...
182
  	spin_unlock(&br->hash_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183

25442e06d   stephen hemminger   bridge: fdb clean...
184
  	mod_timer(&br->gc_timer, round_jiffies_up(next_timer));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
  }
9cf637473   Stephen Hemminger   bridge: add sysfs...
186
187
188
189
190
191
192
193
  /* Completely flush all dynamic entries in forwarding database.*/
  void br_fdb_flush(struct net_bridge *br)
  {
  	int i;
  
  	spin_lock_bh(&br->hash_lock);
  	for (i = 0; i < BR_HASH_SIZE; i++) {
  		struct net_bridge_fdb_entry *f;
b67bfe0d4   Sasha Levin   hlist: drop the n...
194
195
  		struct hlist_node *n;
  		hlist_for_each_entry_safe(f, n, &br->hash[i], hlist) {
9cf637473   Stephen Hemminger   bridge: add sysfs...
196
  			if (!f->is_static)
31e8a49c1   stephen hemminger   bridge: rearrange...
197
  				fdb_delete(br, f);
9cf637473   Stephen Hemminger   bridge: add sysfs...
198
199
200
201
  		}
  	}
  	spin_unlock_bh(&br->hash_lock);
  }
1a620698c   Stephen Hemminger   [BRIDGE]: flush f...
202

25985edce   Lucas De Marchi   Fix common misspe...
203
  /* Flush all entries referring to a specific port.
9cf637473   Stephen Hemminger   bridge: add sysfs...
204
205
   * if do_all is set also flush static entries
   */
1a620698c   Stephen Hemminger   [BRIDGE]: flush f...
206
207
208
  void br_fdb_delete_by_port(struct net_bridge *br,
  			   const struct net_bridge_port *p,
  			   int do_all)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
210
211
212
213
214
  {
  	int i;
  
  	spin_lock_bh(&br->hash_lock);
  	for (i = 0; i < BR_HASH_SIZE; i++) {
  		struct hlist_node *h, *g;
9d6f229fc   YOSHIFUJI Hideaki   [NET] BRIDGE: Fix...
215

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
217
218
  		hlist_for_each_safe(h, g, &br->hash[i]) {
  			struct net_bridge_fdb_entry *f
  				= hlist_entry(h, struct net_bridge_fdb_entry, hlist);
9d6f229fc   YOSHIFUJI Hideaki   [NET] BRIDGE: Fix...
219
  			if (f->dst != p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
  				continue;
1a620698c   Stephen Hemminger   [BRIDGE]: flush f...
221
222
  			if (f->is_static && !do_all)
  				continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
224
225
226
227
228
229
230
  			/*
  			 * if multiple ports all have the same device address
  			 * then when one port is deleted, assign
  			 * the local entry to other port
  			 */
  			if (f->is_local) {
  				struct net_bridge_port *op;
  				list_for_each_entry(op, &br->port_list, list) {
9d6f229fc   YOSHIFUJI Hideaki   [NET] BRIDGE: Fix...
231
  					if (op != p &&
9a7b6ef9b   Joe Perches   bridge: Convert c...
232
233
  					    ether_addr_equal(op->dev->dev_addr,
  							     f->addr.addr)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
235
236
237
238
  						f->dst = op;
  						goto skip_delete;
  					}
  				}
  			}
31e8a49c1   stephen hemminger   bridge: rearrange...
239
  			fdb_delete(br, f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
241
242
243
244
  		skip_delete: ;
  		}
  	}
  	spin_unlock_bh(&br->hash_lock);
  }
eeaf61d88   stephen hemminger   bridge: add rcu_r...
245
  /* No locking or refcounting, assumes caller has rcu_read_lock */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
  struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br,
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
247
248
  					  const unsigned char *addr,
  					  __u16 vid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
  	struct net_bridge_fdb_entry *fdb;
b67bfe0d4   Sasha Levin   hlist: drop the n...
251
  	hlist_for_each_entry_rcu(fdb,
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
252
253
254
  				&br->hash[br_mac_hash(addr, vid)], hlist) {
  		if (ether_addr_equal(fdb->addr.addr, addr) &&
  		    fdb->vlan_id == vid) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
256
257
258
259
260
261
262
  			if (unlikely(has_expired(br, fdb)))
  				break;
  			return fdb;
  		}
  	}
  
  	return NULL;
  }
e6373c4c0   Igor Maravić   net:bridge: use I...
263
  #if IS_ENABLED(CONFIG_ATM_LANE)
da6782927   Michał Mirosław   bridge: Simplify ...
264
265
266
  /* Interface used by ATM LANE hook to test
   * if an addr is on some other bridge port */
  int br_fdb_test_addr(struct net_device *dev, unsigned char *addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
268
  {
  	struct net_bridge_fdb_entry *fdb;
b5ed54e94   stephen hemminger   bridge: fix RCU r...
269
  	struct net_bridge_port *port;
da6782927   Michał Mirosław   bridge: Simplify ...
270
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
  	rcu_read_lock();
b5ed54e94   stephen hemminger   bridge: fix RCU r...
272
273
274
275
  	port = br_port_get_rcu(dev);
  	if (!port)
  		ret = 0;
  	else {
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
276
  		fdb = __br_fdb_get(port->br, addr, 0);
435988133   stephen hemminger   bridge: add local...
277
  		ret = fdb && fdb->dst && fdb->dst->dev != dev &&
b5ed54e94   stephen hemminger   bridge: fix RCU r...
278
279
  			fdb->dst->state == BR_STATE_FORWARDING;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281

da6782927   Michał Mirosław   bridge: Simplify ...
282
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
  }
da6782927   Michał Mirosław   bridge: Simplify ...
284
  #endif /* CONFIG_ATM_LANE */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
286
  
  /*
9d6f229fc   YOSHIFUJI Hideaki   [NET] BRIDGE: Fix...
287
   * Fill buffer with forwarding table records in
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
289
290
291
292
293
294
   * the API format.
   */
  int br_fdb_fillbuf(struct net_bridge *br, void *buf,
  		   unsigned long maxnum, unsigned long skip)
  {
  	struct __fdb_entry *fe = buf;
  	int i, num = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
296
297
298
299
300
  	struct net_bridge_fdb_entry *f;
  
  	memset(buf, 0, maxnum*sizeof(struct __fdb_entry));
  
  	rcu_read_lock();
  	for (i = 0; i < BR_HASH_SIZE; i++) {
b67bfe0d4   Sasha Levin   hlist: drop the n...
301
  		hlist_for_each_entry_rcu(f, &br->hash[i], hlist) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
303
  			if (num >= maxnum)
  				goto out;
9d6f229fc   YOSHIFUJI Hideaki   [NET] BRIDGE: Fix...
304
  			if (has_expired(br, f))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
  				continue;
435988133   stephen hemminger   bridge: add local...
306
307
308
  			/* ignore pseudo entry for local MAC address */
  			if (!f->dst)
  				continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
310
311
312
313
314
315
  			if (skip) {
  				--skip;
  				continue;
  			}
  
  			/* convert from internal format to API */
  			memcpy(fe->mac_addr, f->addr.addr, ETH_ALEN);
ae4f8fca4   Stephen Hemminger   bridge: forwardin...
316
317
  
  			/* due to ABI compat need to split into hi/lo */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
  			fe->port_no = f->dst->port_no;
ae4f8fca4   Stephen Hemminger   bridge: forwardin...
319
  			fe->port_hi = f->dst->port_no >> 8;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
321
  			fe->is_local = f->is_local;
  			if (!f->is_static)
a399a8053   Eric Dumazet   time: jiffies_del...
322
  				fe->ageing_timer_value = jiffies_delta_to_clock_t(jiffies - f->updated);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
324
325
326
327
328
329
330
331
332
  			++fe;
  			++num;
  		}
  	}
  
   out:
  	rcu_read_unlock();
  
  	return num;
  }
664de48bb   stephen hemminger   bridge: split rcu...
333
  static struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head,
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
334
335
  					     const unsigned char *addr,
  					     __u16 vid)
664de48bb   stephen hemminger   bridge: split rcu...
336
  {
664de48bb   stephen hemminger   bridge: split rcu...
337
  	struct net_bridge_fdb_entry *fdb;
b67bfe0d4   Sasha Levin   hlist: drop the n...
338
  	hlist_for_each_entry(fdb, head, hlist) {
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
339
340
  		if (ether_addr_equal(fdb->addr.addr, addr) &&
  		    fdb->vlan_id == vid)
664de48bb   stephen hemminger   bridge: split rcu...
341
342
343
344
345
346
  			return fdb;
  	}
  	return NULL;
  }
  
  static struct net_bridge_fdb_entry *fdb_find_rcu(struct hlist_head *head,
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
347
348
  						 const unsigned char *addr,
  						 __u16 vid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
  	struct net_bridge_fdb_entry *fdb;
b67bfe0d4   Sasha Levin   hlist: drop the n...
351
  	hlist_for_each_entry_rcu(fdb, head, hlist) {
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
352
353
  		if (ether_addr_equal(fdb->addr.addr, addr) &&
  		    fdb->vlan_id == vid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354
355
356
357
358
359
360
  			return fdb;
  	}
  	return NULL;
  }
  
  static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head,
  					       struct net_bridge_port *source,
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
361
362
  					       const unsigned char *addr,
  					       __u16 vid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
364
365
366
367
368
  {
  	struct net_bridge_fdb_entry *fdb;
  
  	fdb = kmem_cache_alloc(br_fdb_cache, GFP_ATOMIC);
  	if (fdb) {
  		memcpy(fdb->addr.addr, addr, ETH_ALEN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
  		fdb->dst = source;
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
370
  		fdb->vlan_id = vid;
03e9b64b8   stephen hemminger   bridge: change ar...
371
372
  		fdb->is_local = 0;
  		fdb->is_static = 0;
7cd8861ab   stephen hemminger   bridge: track las...
373
  		fdb->updated = fdb->used = jiffies;
1158f762e   Pavel Emelyanov   bridge: Don't put...
374
  		hlist_add_head_rcu(&fdb->hlist, head);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
376
377
378
379
  	}
  	return fdb;
  }
  
  static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
380
  		  const unsigned char *addr, u16 vid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381
  {
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
382
  	struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383
384
385
386
  	struct net_bridge_fdb_entry *fdb;
  
  	if (!is_valid_ether_addr(addr))
  		return -EINVAL;
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
387
  	fdb = fdb_find(head, addr, vid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388
  	if (fdb) {
9d6f229fc   YOSHIFUJI Hideaki   [NET] BRIDGE: Fix...
389
  		/* it is okay to have multiple ports with same
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390
391
  		 * address, just use the first one.
  		 */
9d6f229fc   YOSHIFUJI Hideaki   [NET] BRIDGE: Fix...
392
  		if (fdb->is_local)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
  			return 0;
28a16c979   stephen hemminger   bridge: change co...
394
  		br_warn(br, "adding interface %s with same address "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
396
  		       "as a received packet
  ",
9b46922e1   Hong zhi guo   bridge: fix crash...
397
  		       source ? source->dev->name : br->dev->name);
31e8a49c1   stephen hemminger   bridge: rearrange...
398
  		fdb_delete(br, fdb);
9d6f229fc   YOSHIFUJI Hideaki   [NET] BRIDGE: Fix...
399
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
400

bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
401
  	fdb = fdb_create(head, source, addr, vid);
03e9b64b8   stephen hemminger   bridge: change ar...
402
  	if (!fdb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
  		return -ENOMEM;
03e9b64b8   stephen hemminger   bridge: change ar...
404
  	fdb->is_local = fdb->is_static = 1;
31e8a49c1   stephen hemminger   bridge: rearrange...
405
  	fdb_notify(br, fdb, RTM_NEWNEIGH);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
407
  	return 0;
  }
03e9b64b8   stephen hemminger   bridge: change ar...
408
  /* Add entry for local address of interface */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
  int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
410
  		  const unsigned char *addr, u16 vid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
412
413
414
  {
  	int ret;
  
  	spin_lock_bh(&br->hash_lock);
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
415
  	ret = fdb_insert(br, source, addr, vid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416
417
418
419
420
  	spin_unlock_bh(&br->hash_lock);
  	return ret;
  }
  
  void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
421
  		   const unsigned char *addr, u16 vid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
  {
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
423
  	struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
425
426
427
428
  	struct net_bridge_fdb_entry *fdb;
  
  	/* some users want to always flood. */
  	if (hold_time(br) == 0)
  		return;
df1c0b846   Stephen Hemminger   [BRIDGE]: Packets...
429
430
431
432
  	/* ignore packets unless we are using this port */
  	if (!(source->state == BR_STATE_LEARNING ||
  	      source->state == BR_STATE_FORWARDING))
  		return;
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
433
  	fdb = fdb_find_rcu(head, addr, vid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
435
436
  	if (likely(fdb)) {
  		/* attempt to update an entry for a local interface */
  		if (unlikely(fdb->is_local)) {
9d6f229fc   YOSHIFUJI Hideaki   [NET] BRIDGE: Fix...
437
  			if (net_ratelimit())
28a16c979   stephen hemminger   bridge: change co...
438
439
440
441
  				br_warn(br, "received packet on %s with "
  					"own address as source address
  ",
  					source->dev->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
442
443
444
  		} else {
  			/* fastpath: update of existing entry */
  			fdb->dst = source;
7cd8861ab   stephen hemminger   bridge: track las...
445
  			fdb->updated = jiffies;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446
447
  		}
  	} else {
f8ae737de   Stephen Hemminger   [BRIDGE]: forward...
448
  		spin_lock(&br->hash_lock);
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
449
450
  		if (likely(!fdb_find(head, addr, vid))) {
  			fdb = fdb_create(head, source, addr, vid);
f58ee4e1a   stephen hemminger   bridge: refactor ...
451
  			if (fdb)
31e8a49c1   stephen hemminger   bridge: rearrange...
452
  				fdb_notify(br, fdb, RTM_NEWNEIGH);
f58ee4e1a   stephen hemminger   bridge: refactor ...
453
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454
455
456
  		/* else  we lose race and someone else inserts
  		 * it first, don't bother updating
  		 */
f8ae737de   Stephen Hemminger   [BRIDGE]: forward...
457
  		spin_unlock(&br->hash_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
  }
b078f0df6   stephen hemminger   bridge: add netli...
460
461
462
463
464
465
466
467
468
469
470
471
  
  static int fdb_to_nud(const struct net_bridge_fdb_entry *fdb)
  {
  	if (fdb->is_local)
  		return NUD_PERMANENT;
  	else if (fdb->is_static)
  		return NUD_NOARP;
  	else if (has_expired(fdb->dst->br, fdb))
  		return NUD_STALE;
  	else
  		return NUD_REACHABLE;
  }
31e8a49c1   stephen hemminger   bridge: rearrange...
472
  static int fdb_fill_info(struct sk_buff *skb, const struct net_bridge *br,
b078f0df6   stephen hemminger   bridge: add netli...
473
  			 const struct net_bridge_fdb_entry *fdb,
15e473046   Eric W. Biederman   netlink: Rename p...
474
  			 u32 portid, u32 seq, int type, unsigned int flags)
b078f0df6   stephen hemminger   bridge: add netli...
475
476
477
478
479
  {
  	unsigned long now = jiffies;
  	struct nda_cacheinfo ci;
  	struct nlmsghdr *nlh;
  	struct ndmsg *ndm;
15e473046   Eric W. Biederman   netlink: Rename p...
480
  	nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags);
b078f0df6   stephen hemminger   bridge: add netli...
481
482
  	if (nlh == NULL)
  		return -EMSGSIZE;
b078f0df6   stephen hemminger   bridge: add netli...
483
484
485
486
487
488
  	ndm = nlmsg_data(nlh);
  	ndm->ndm_family	 = AF_BRIDGE;
  	ndm->ndm_pad1    = 0;
  	ndm->ndm_pad2    = 0;
  	ndm->ndm_flags	 = 0;
  	ndm->ndm_type	 = 0;
435988133   stephen hemminger   bridge: add local...
489
  	ndm->ndm_ifindex = fdb->dst ? fdb->dst->dev->ifindex : br->dev->ifindex;
b078f0df6   stephen hemminger   bridge: add netli...
490
  	ndm->ndm_state   = fdb_to_nud(fdb);
2eb812e65   David S. Miller   bridge: Stop usin...
491
492
  	if (nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->addr))
  		goto nla_put_failure;
b078f0df6   stephen hemminger   bridge: add netli...
493
494
495
496
  	ci.ndm_used	 = jiffies_to_clock_t(now - fdb->used);
  	ci.ndm_confirmed = 0;
  	ci.ndm_updated	 = jiffies_to_clock_t(now - fdb->updated);
  	ci.ndm_refcnt	 = 0;
2eb812e65   David S. Miller   bridge: Stop usin...
497
498
  	if (nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
  		goto nla_put_failure;
1690be63a   Vlad Yasevich   bridge: Add vlan ...
499
500
501
  
  	if (nla_put(skb, NDA_VLAN, sizeof(u16), &fdb->vlan_id))
  		goto nla_put_failure;
b078f0df6   stephen hemminger   bridge: add netli...
502
503
504
505
506
507
508
509
510
511
512
  	return nlmsg_end(skb, nlh);
  
  nla_put_failure:
  	nlmsg_cancel(skb, nlh);
  	return -EMSGSIZE;
  }
  
  static inline size_t fdb_nlmsg_size(void)
  {
  	return NLMSG_ALIGN(sizeof(struct ndmsg))
  		+ nla_total_size(ETH_ALEN) /* NDA_LLADDR */
1690be63a   Vlad Yasevich   bridge: Add vlan ...
513
  		+ nla_total_size(sizeof(u16)) /* NDA_VLAN */
b078f0df6   stephen hemminger   bridge: add netli...
514
515
  		+ nla_total_size(sizeof(struct nda_cacheinfo));
  }
31e8a49c1   stephen hemminger   bridge: rearrange...
516
517
  static void fdb_notify(struct net_bridge *br,
  		       const struct net_bridge_fdb_entry *fdb, int type)
b078f0df6   stephen hemminger   bridge: add netli...
518
  {
31e8a49c1   stephen hemminger   bridge: rearrange...
519
  	struct net *net = dev_net(br->dev);
b078f0df6   stephen hemminger   bridge: add netli...
520
521
522
523
524
525
  	struct sk_buff *skb;
  	int err = -ENOBUFS;
  
  	skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC);
  	if (skb == NULL)
  		goto errout;
31e8a49c1   stephen hemminger   bridge: rearrange...
526
  	err = fdb_fill_info(skb, br, fdb, 0, 0, type, 0);
b078f0df6   stephen hemminger   bridge: add netli...
527
528
529
530
531
532
533
534
535
536
537
538
539
540
  	if (err < 0) {
  		/* -EMSGSIZE implies BUG in fdb_nlmsg_size() */
  		WARN_ON(err == -EMSGSIZE);
  		kfree_skb(skb);
  		goto errout;
  	}
  	rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
  	return;
  errout:
  	if (err < 0)
  		rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
  }
  
  /* Dump information about entries, in response to GETNEIGH */
77162022a   John Fastabend   net: add generic ...
541
542
543
544
  int br_fdb_dump(struct sk_buff *skb,
  		struct netlink_callback *cb,
  		struct net_device *dev,
  		int idx)
b078f0df6   stephen hemminger   bridge: add netli...
545
  {
77162022a   John Fastabend   net: add generic ...
546
547
  	struct net_bridge *br = netdev_priv(dev);
  	int i;
b078f0df6   stephen hemminger   bridge: add netli...
548

77162022a   John Fastabend   net: add generic ...
549
550
  	if (!(dev->priv_flags & IFF_EBRIDGE))
  		goto out;
b078f0df6   stephen hemminger   bridge: add netli...
551

77162022a   John Fastabend   net: add generic ...
552
  	for (i = 0; i < BR_HASH_SIZE; i++) {
77162022a   John Fastabend   net: add generic ...
553
  		struct net_bridge_fdb_entry *f;
b078f0df6   stephen hemminger   bridge: add netli...
554

b67bfe0d4   Sasha Levin   hlist: drop the n...
555
  		hlist_for_each_entry_rcu(f, &br->hash[i], hlist) {
77162022a   John Fastabend   net: add generic ...
556
557
558
559
  			if (idx < cb->args[0])
  				goto skip;
  
  			if (fdb_fill_info(skb, br, f,
15e473046   Eric W. Biederman   netlink: Rename p...
560
  					  NETLINK_CB(cb->skb).portid,
77162022a   John Fastabend   net: add generic ...
561
562
563
564
  					  cb->nlh->nlmsg_seq,
  					  RTM_NEWNEIGH,
  					  NLM_F_MULTI) < 0)
  				break;
b078f0df6   stephen hemminger   bridge: add netli...
565
  skip:
77162022a   John Fastabend   net: add generic ...
566
  			++idx;
b078f0df6   stephen hemminger   bridge: add netli...
567
568
  		}
  	}
b078f0df6   stephen hemminger   bridge: add netli...
569

77162022a   John Fastabend   net: add generic ...
570
571
  out:
  	return idx;
b078f0df6   stephen hemminger   bridge: add netli...
572
  }
36fd2b63e   stephen hemminger   bridge: allow cre...
573

292d13989   stephen hemminger   bridge: add NTF_U...
574
  /* Update (create or replace) forwarding database entry */
36fd2b63e   stephen hemminger   bridge: allow cre...
575
  static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr,
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
576
  			 __u16 state, __u16 flags, __u16 vid)
36fd2b63e   stephen hemminger   bridge: allow cre...
577
578
  {
  	struct net_bridge *br = source->br;
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
579
  	struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
36fd2b63e   stephen hemminger   bridge: allow cre...
580
  	struct net_bridge_fdb_entry *fdb;
b0a397fb3   roopa   bridge: Add fdb d...
581
  	bool modified = false;
36fd2b63e   stephen hemminger   bridge: allow cre...
582

2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
583
  	fdb = fdb_find(head, addr, vid);
64af1bac9   stephen hemminger   bridge: allow upd...
584
585
586
  	if (fdb == NULL) {
  		if (!(flags & NLM_F_CREATE))
  			return -ENOENT;
36fd2b63e   stephen hemminger   bridge: allow cre...
587

2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
588
  		fdb = fdb_create(head, source, addr, vid);
64af1bac9   stephen hemminger   bridge: allow upd...
589
590
  		if (!fdb)
  			return -ENOMEM;
b0a397fb3   roopa   bridge: Add fdb d...
591
592
  
  		modified = true;
64af1bac9   stephen hemminger   bridge: allow upd...
593
594
595
  	} else {
  		if (flags & NLM_F_EXCL)
  			return -EEXIST;
b0a397fb3   roopa   bridge: Add fdb d...
596
597
598
599
600
  
  		if (fdb->dst != source) {
  			fdb->dst = source;
  			modified = true;
  		}
292d13989   stephen hemminger   bridge: add NTF_U...
601
602
603
604
605
606
607
608
609
610
  	}
  
  	if (fdb_to_nud(fdb) != state) {
  		if (state & NUD_PERMANENT)
  			fdb->is_local = fdb->is_static = 1;
  		else if (state & NUD_NOARP) {
  			fdb->is_local = 0;
  			fdb->is_static = 1;
  		} else
  			fdb->is_local = fdb->is_static = 0;
64af1bac9   stephen hemminger   bridge: allow upd...
611

b0a397fb3   roopa   bridge: Add fdb d...
612
613
614
615
616
617
  		modified = true;
  	}
  
  	fdb->used = jiffies;
  	if (modified) {
  		fdb->updated = jiffies;
31e8a49c1   stephen hemminger   bridge: rearrange...
618
  		fdb_notify(br, fdb, RTM_NEWNEIGH);
64af1bac9   stephen hemminger   bridge: allow upd...
619
  	}
36fd2b63e   stephen hemminger   bridge: allow cre...
620

36fd2b63e   stephen hemminger   bridge: allow cre...
621
622
  	return 0;
  }
1690be63a   Vlad Yasevich   bridge: Add vlan ...
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
  static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge_port *p,
  	       const unsigned char *addr, u16 nlh_flags, u16 vid)
  {
  	int err = 0;
  
  	if (ndm->ndm_flags & NTF_USE) {
  		rcu_read_lock();
  		br_fdb_update(p->br, p, addr, vid);
  		rcu_read_unlock();
  	} else {
  		spin_lock_bh(&p->br->hash_lock);
  		err = fdb_add_entry(p, addr, ndm->ndm_state,
  				    nlh_flags, vid);
  		spin_unlock_bh(&p->br->hash_lock);
  	}
  
  	return err;
  }
36fd2b63e   stephen hemminger   bridge: allow cre...
641
  /* Add new permanent fdb entry with RTM_NEWNEIGH */
edc7d5732   stephen hemminger   netlink: add attr...
642
643
  int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
  	       struct net_device *dev,
6b6e27255   stephen hemminger   netdev: make addr...
644
  	       const unsigned char *addr, u16 nlh_flags)
36fd2b63e   stephen hemminger   bridge: allow cre...
645
  {
36fd2b63e   stephen hemminger   bridge: allow cre...
646
  	struct net_bridge_port *p;
77162022a   John Fastabend   net: add generic ...
647
  	int err = 0;
1690be63a   Vlad Yasevich   bridge: Add vlan ...
648
649
  	struct net_port_vlans *pv;
  	unsigned short vid = VLAN_N_VID;
36fd2b63e   stephen hemminger   bridge: allow cre...
650

292d13989   stephen hemminger   bridge: add NTF_U...
651
652
653
654
655
  	if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE))) {
  		pr_info("bridge: RTM_NEWNEIGH with invalid state %#x
  ", ndm->ndm_state);
  		return -EINVAL;
  	}
1690be63a   Vlad Yasevich   bridge: Add vlan ...
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
  	if (tb[NDA_VLAN]) {
  		if (nla_len(tb[NDA_VLAN]) != sizeof(unsigned short)) {
  			pr_info("bridge: RTM_NEWNEIGH with invalid vlan
  ");
  			return -EINVAL;
  		}
  
  		vid = nla_get_u16(tb[NDA_VLAN]);
  
  		if (vid >= VLAN_N_VID) {
  			pr_info("bridge: RTM_NEWNEIGH with invalid vlan id %d
  ",
  				vid);
  			return -EINVAL;
  		}
  	}
36fd2b63e   stephen hemminger   bridge: allow cre...
672
673
674
675
676
677
678
  	p = br_port_get_rtnl(dev);
  	if (p == NULL) {
  		pr_info("bridge: RTM_NEWNEIGH %s not a bridge port
  ",
  			dev->name);
  		return -EINVAL;
  	}
1690be63a   Vlad Yasevich   bridge: Add vlan ...
679
680
681
682
683
684
685
686
687
688
689
  	pv = nbp_get_vlan_info(p);
  	if (vid != VLAN_N_VID) {
  		if (!pv || !test_bit(vid, pv->vlan_bitmap)) {
  			pr_info("bridge: RTM_NEWNEIGH with unconfigured "
  				"vlan %d on port %s
  ", vid, dev->name);
  			return -EINVAL;
  		}
  
  		/* VID was specified, so use it. */
  		err = __br_fdb_add(ndm, p, addr, nlh_flags, vid);
292d13989   stephen hemminger   bridge: add NTF_U...
690
  	} else {
9f0bd377e   Toshiaki Makita   bridge: Use the c...
691
  		if (!pv || bitmap_empty(pv->vlan_bitmap, VLAN_N_VID)) {
1690be63a   Vlad Yasevich   bridge: Add vlan ...
692
693
694
695
696
697
698
699
  			err = __br_fdb_add(ndm, p, addr, nlh_flags, 0);
  			goto out;
  		}
  
  		/* We have vlans configured on this port and user didn't
  		 * specify a VLAN.  To be nice, add/update entry for every
  		 * vlan on this port.
  		 */
9f0bd377e   Toshiaki Makita   bridge: Use the c...
700
  		for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) {
1690be63a   Vlad Yasevich   bridge: Add vlan ...
701
702
703
  			err = __br_fdb_add(ndm, p, addr, nlh_flags, vid);
  			if (err)
  				goto out;
1690be63a   Vlad Yasevich   bridge: Add vlan ...
704
  		}
292d13989   stephen hemminger   bridge: add NTF_U...
705
  	}
36fd2b63e   stephen hemminger   bridge: allow cre...
706

1690be63a   Vlad Yasevich   bridge: Add vlan ...
707
  out:
36fd2b63e   stephen hemminger   bridge: allow cre...
708
709
  	return err;
  }
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
710
711
  int fdb_delete_by_addr(struct net_bridge *br, const u8 *addr,
  		       u16 vlan)
36fd2b63e   stephen hemminger   bridge: allow cre...
712
  {
1690be63a   Vlad Yasevich   bridge: Add vlan ...
713
  	struct hlist_head *head = &br->hash[br_mac_hash(addr, vlan)];
36fd2b63e   stephen hemminger   bridge: allow cre...
714
  	struct net_bridge_fdb_entry *fdb;
1690be63a   Vlad Yasevich   bridge: Add vlan ...
715
  	fdb = fdb_find(head, addr, vlan);
36fd2b63e   stephen hemminger   bridge: allow cre...
716
717
  	if (!fdb)
  		return -ENOENT;
1690be63a   Vlad Yasevich   bridge: Add vlan ...
718
  	fdb_delete(br, fdb);
36fd2b63e   stephen hemminger   bridge: allow cre...
719
720
  	return 0;
  }
1690be63a   Vlad Yasevich   bridge: Add vlan ...
721
722
723
724
725
726
727
728
729
730
731
  static int __br_fdb_delete(struct net_bridge_port *p,
  			   const unsigned char *addr, u16 vid)
  {
  	int err;
  
  	spin_lock_bh(&p->br->hash_lock);
  	err = fdb_delete_by_addr(p->br, addr, vid);
  	spin_unlock_bh(&p->br->hash_lock);
  
  	return err;
  }
36fd2b63e   stephen hemminger   bridge: allow cre...
732
  /* Remove neighbor entry with RTM_DELNEIGH */
1690be63a   Vlad Yasevich   bridge: Add vlan ...
733
734
  int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
  		  struct net_device *dev,
6b6e27255   stephen hemminger   netdev: make addr...
735
  		  const unsigned char *addr)
36fd2b63e   stephen hemminger   bridge: allow cre...
736
  {
36fd2b63e   stephen hemminger   bridge: allow cre...
737
  	struct net_bridge_port *p;
36fd2b63e   stephen hemminger   bridge: allow cre...
738
  	int err;
1690be63a   Vlad Yasevich   bridge: Add vlan ...
739
740
  	struct net_port_vlans *pv;
  	unsigned short vid = VLAN_N_VID;
36fd2b63e   stephen hemminger   bridge: allow cre...
741

1690be63a   Vlad Yasevich   bridge: Add vlan ...
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
  	if (tb[NDA_VLAN]) {
  		if (nla_len(tb[NDA_VLAN]) != sizeof(unsigned short)) {
  			pr_info("bridge: RTM_NEWNEIGH with invalid vlan
  ");
  			return -EINVAL;
  		}
  
  		vid = nla_get_u16(tb[NDA_VLAN]);
  
  		if (vid >= VLAN_N_VID) {
  			pr_info("bridge: RTM_NEWNEIGH with invalid vlan id %d
  ",
  				vid);
  			return -EINVAL;
  		}
  	}
36fd2b63e   stephen hemminger   bridge: allow cre...
758
759
760
761
762
763
764
  	p = br_port_get_rtnl(dev);
  	if (p == NULL) {
  		pr_info("bridge: RTM_DELNEIGH %s not a bridge port
  ",
  			dev->name);
  		return -EINVAL;
  	}
1690be63a   Vlad Yasevich   bridge: Add vlan ...
765
766
767
768
769
770
771
772
  	pv = nbp_get_vlan_info(p);
  	if (vid != VLAN_N_VID) {
  		if (!pv || !test_bit(vid, pv->vlan_bitmap)) {
  			pr_info("bridge: RTM_DELNEIGH with unconfigured "
  				"vlan %d on port %s
  ", vid, dev->name);
  			return -EINVAL;
  		}
36fd2b63e   stephen hemminger   bridge: allow cre...
773

1690be63a   Vlad Yasevich   bridge: Add vlan ...
774
775
  		err = __br_fdb_delete(p, addr, vid);
  	} else {
9f0bd377e   Toshiaki Makita   bridge: Use the c...
776
  		if (!pv || bitmap_empty(pv->vlan_bitmap, VLAN_N_VID)) {
1690be63a   Vlad Yasevich   bridge: Add vlan ...
777
778
779
780
781
782
783
784
785
  			err = __br_fdb_delete(p, addr, 0);
  			goto out;
  		}
  
  		/* We have vlans configured on this port and user didn't
  		 * specify a VLAN.  To be nice, add/update entry for every
  		 * vlan on this port.
  		 */
  		err = -ENOENT;
9f0bd377e   Toshiaki Makita   bridge: Use the c...
786
  		for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) {
1690be63a   Vlad Yasevich   bridge: Add vlan ...
787
  			err &= __br_fdb_delete(p, addr, vid);
1690be63a   Vlad Yasevich   bridge: Add vlan ...
788
789
790
  		}
  	}
  out:
36fd2b63e   stephen hemminger   bridge: allow cre...
791
792
  	return err;
  }