Blame view

net/bridge/br_fdb.c 27.1 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>
b4ad7baa0   Scott Feldman   bridge: del exter...
27
  #include <net/switchdev.h>
b74fd306e   Roopa Prabhu   bridge: fdb add a...
28
  #include <trace/events/bridge.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
  #include "br_private.h"
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
30
  static struct kmem_cache *br_fdb_cache __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
  static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
32
  		      const unsigned char *addr, u16 vid);
31e8a49c1   stephen hemminger   bridge: rearrange...
33
34
  static void fdb_notify(struct net_bridge *br,
  		       const struct net_bridge_fdb_entry *, int);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35

3f8909231   Stephen Hemminger   bridge: simpler h...
36
  static u32 fdb_salt __read_mostly;
87a596e0b   Akinobu Mita   bridge: check kme...
37
  int __init br_fdb_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
39
40
41
  {
  	br_fdb_cache = kmem_cache_create("bridge_fdb_cache",
  					 sizeof(struct net_bridge_fdb_entry),
  					 0,
20c2df83d   Paul Mundt   mm: Remove slab d...
42
  					 SLAB_HWCACHE_ALIGN, NULL);
87a596e0b   Akinobu Mita   bridge: check kme...
43
44
  	if (!br_fdb_cache)
  		return -ENOMEM;
3f8909231   Stephen Hemminger   bridge: simpler h...
45
  	get_random_bytes(&fdb_salt, sizeof(fdb_salt));
87a596e0b   Akinobu Mita   bridge: check kme...
46
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
  }
73afc9069   Andrew Morton   [BRIDGE]: Section...
48
  void br_fdb_fini(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
51
52
53
54
55
56
  {
  	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...
57
  static inline unsigned long hold_time(const struct net_bridge *br)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
60
  {
  	return br->topology_change ? br->forward_delay : br->ageing_time;
  }
3f8909231   Stephen Hemminger   bridge: simpler h...
61
  static inline int has_expired(const struct net_bridge *br,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
63
  				  const struct net_bridge_fdb_entry *fdb)
  {
eda7a5e88   Roopa Prabhu   bridge: don't ind...
64
  	return !fdb->is_static && !fdb->added_by_external_learn &&
7cd8861ab   stephen hemminger   bridge: track las...
65
  		time_before_eq(fdb->updated + hold_time(br), jiffies);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
  }
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
67
  static inline int br_mac_hash(const unsigned char *mac, __u16 vid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
  {
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
69
  	/* use 1 byte of OUI and 3 bytes of NIC */
3f8909231   Stephen Hemminger   bridge: simpler h...
70
  	u32 key = get_unaligned((u32 *)(mac + 2));
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
71
  	return jhash_2words(key, vid, fdb_salt) & (BR_HASH_SIZE - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
  }
da6782927   Michał Mirosław   bridge: Simplify ...
73
74
75
76
77
78
  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);
  }
bfd0aeac5   Nikolay Aleksandrov   bridge: fdb: conv...
79
80
81
82
83
  static struct net_bridge_fdb_entry *fdb_find_rcu(struct hlist_head *head,
  						 const unsigned char *addr,
  						 __u16 vid)
  {
  	struct net_bridge_fdb_entry *f;
410b3d48f   Nikolay Aleksandrov   bridge: fdb: add ...
84
  	WARN_ON_ONCE(!rcu_read_lock_held());
bfd0aeac5   Nikolay Aleksandrov   bridge: fdb: conv...
85
86
87
88
89
90
91
92
93
94
95
96
97
98
  	hlist_for_each_entry_rcu(f, head, hlist)
  		if (ether_addr_equal(f->addr.addr, addr) && f->vlan_id == vid)
  			break;
  
  	return f;
  }
  
  /* requires bridge hash_lock */
  static struct net_bridge_fdb_entry *br_fdb_find(struct net_bridge *br,
  						const unsigned char *addr,
  						__u16 vid)
  {
  	struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
  	struct net_bridge_fdb_entry *fdb;
d12c91769   WANG Cong   bridge: resolve a...
99
  	lockdep_assert_held_once(&br->hash_lock);
410b3d48f   Nikolay Aleksandrov   bridge: fdb: add ...
100

bfd0aeac5   Nikolay Aleksandrov   bridge: fdb: conv...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
  	rcu_read_lock();
  	fdb = fdb_find_rcu(head, addr, vid);
  	rcu_read_unlock();
  
  	return fdb;
  }
  
  struct net_bridge_fdb_entry *br_fdb_find_rcu(struct net_bridge *br,
  					     const unsigned char *addr,
  					     __u16 vid)
  {
  	struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
  
  	return fdb_find_rcu(head, addr, vid);
  }
145beee8d   Vlad Yasevich   bridge: Add addre...
116
117
118
119
120
  /* When a static FDB entry is added, the mac address from the entry is
   * added to the bridge private HW address list and all required ports
   * are then updated with the new information.
   * Called under RTNL.
   */
020ec6ba2   Jiri Pirko   bridge: rename fd...
121
  static void fdb_add_hw_addr(struct net_bridge *br, const unsigned char *addr)
145beee8d   Vlad Yasevich   bridge: Add addre...
122
123
  {
  	int err;
a3f5ee71c   Li RongQing   bridge: use list_...
124
  	struct net_bridge_port *p;
145beee8d   Vlad Yasevich   bridge: Add addre...
125
126
127
128
129
130
131
132
133
134
135
136
137
  
  	ASSERT_RTNL();
  
  	list_for_each_entry(p, &br->port_list, list) {
  		if (!br_promisc_port(p)) {
  			err = dev_uc_add(p->dev, addr);
  			if (err)
  				goto undo;
  		}
  	}
  
  	return;
  undo:
a3f5ee71c   Li RongQing   bridge: use list_...
138
139
140
  	list_for_each_entry_continue_reverse(p, &br->port_list, list) {
  		if (!br_promisc_port(p))
  			dev_uc_del(p->dev, addr);
145beee8d   Vlad Yasevich   bridge: Add addre...
141
142
143
144
145
146
147
148
  	}
  }
  
  /* When a static FDB entry is deleted, the HW address from that entry is
   * also removed from the bridge private HW address list and updates all
   * the ports with needed information.
   * Called under RTNL.
   */
020ec6ba2   Jiri Pirko   bridge: rename fd...
149
  static void fdb_del_hw_addr(struct net_bridge *br, const unsigned char *addr)
145beee8d   Vlad Yasevich   bridge: Add addre...
150
151
152
153
154
155
156
157
158
159
  {
  	struct net_bridge_port *p;
  
  	ASSERT_RTNL();
  
  	list_for_each_entry(p, &br->port_list, list) {
  		if (!br_promisc_port(p))
  			dev_uc_del(p->dev, addr);
  	}
  }
31e8a49c1   stephen hemminger   bridge: rearrange...
160
  static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
  {
b74fd306e   Roopa Prabhu   bridge: fdb add a...
162
  	trace_fdb_delete(br, f);
145beee8d   Vlad Yasevich   bridge: Add addre...
163
  	if (f->is_static)
020ec6ba2   Jiri Pirko   bridge: rename fd...
164
  		fdb_del_hw_addr(br, f->addr.addr);
145beee8d   Vlad Yasevich   bridge: Add addre...
165

f7cdee8a7   Nikolay Aleksandrov   bridge: move to w...
166
  	hlist_del_init_rcu(&f->hlist);
31e8a49c1   stephen hemminger   bridge: rearrange...
167
  	fdb_notify(br, f, RTM_DELNEIGH);
da6782927   Michał Mirosław   bridge: Simplify ...
168
  	call_rcu(&f->rcu, fdb_rcu_free);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
  }
960b589f8   Toshiaki Makita   bridge: Properly ...
170
171
172
173
174
175
  /* Delete a local entry if no other port had the same address. */
  static void fdb_delete_local(struct net_bridge *br,
  			     const struct net_bridge_port *p,
  			     struct net_bridge_fdb_entry *f)
  {
  	const unsigned char *addr = f->addr.addr;
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
176
177
  	struct net_bridge_vlan_group *vg;
  	const struct net_bridge_vlan *v;
960b589f8   Toshiaki Makita   bridge: Properly ...
178
  	struct net_bridge_port *op;
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
179
  	u16 vid = f->vlan_id;
960b589f8   Toshiaki Makita   bridge: Properly ...
180
181
182
  
  	/* Maybe another port has same hw addr? */
  	list_for_each_entry(op, &br->port_list, list) {
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
183
  		vg = nbp_vlan_group(op);
960b589f8   Toshiaki Makita   bridge: Properly ...
184
  		if (op != p && ether_addr_equal(op->dev->dev_addr, addr) &&
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
185
  		    (!vid || br_vlan_find(vg, vid))) {
960b589f8   Toshiaki Makita   bridge: Properly ...
186
  			f->dst = op;
a778e6d1a   Toshiaki Makita   bridge: Properly ...
187
  			f->added_by_user = 0;
960b589f8   Toshiaki Makita   bridge: Properly ...
188
189
190
  			return;
  		}
  	}
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
191
192
  	vg = br_vlan_group(br);
  	v = br_vlan_find(vg, vid);
960b589f8   Toshiaki Makita   bridge: Properly ...
193
194
  	/* Maybe bridge device has same hw addr? */
  	if (p && ether_addr_equal(br->dev->dev_addr, addr) &&
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
195
  	    (!vid || (v && br_vlan_should_use(v)))) {
960b589f8   Toshiaki Makita   bridge: Properly ...
196
  		f->dst = NULL;
a778e6d1a   Toshiaki Makita   bridge: Properly ...
197
  		f->added_by_user = 0;
960b589f8   Toshiaki Makita   bridge: Properly ...
198
199
200
201
202
  		return;
  	}
  
  	fdb_delete(br, f);
  }
424bb9c97   Toshiaki Makita   bridge: Properly ...
203
204
205
206
  void br_fdb_find_delete_local(struct net_bridge *br,
  			      const struct net_bridge_port *p,
  			      const unsigned char *addr, u16 vid)
  {
424bb9c97   Toshiaki Makita   bridge: Properly ...
207
208
209
  	struct net_bridge_fdb_entry *f;
  
  	spin_lock_bh(&br->hash_lock);
bfd0aeac5   Nikolay Aleksandrov   bridge: fdb: conv...
210
  	f = br_fdb_find(br, addr, vid);
424bb9c97   Toshiaki Makita   bridge: Properly ...
211
212
213
214
  	if (f && f->is_local && !f->added_by_user && f->dst == p)
  		fdb_delete_local(br, p, f);
  	spin_unlock_bh(&br->hash_lock);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
216
  void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr)
  {
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
217
  	struct net_bridge_vlan_group *vg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
  	struct net_bridge *br = p->br;
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
219
  	struct net_bridge_vlan *v;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
  	int i;
9d6f229fc   YOSHIFUJI Hideaki   [NET] BRIDGE: Fix...
221

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
  	spin_lock_bh(&br->hash_lock);
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
223
  	vg = nbp_vlan_group(p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
225
226
227
228
229
230
  	/* 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);
a5642ab47   Toshiaki Makita   bridge: Fix the w...
231
  			if (f->dst == p && f->is_local && !f->added_by_user) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
  				/* delete old one */
960b589f8   Toshiaki Makita   bridge: Properly ...
233
  				fdb_delete_local(br, p, f);
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
234
235
236
237
  				/* if this port has no vlan information
  				 * configured, we can safely be done at
  				 * this point.
  				 */
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
238
  				if (!vg || !vg->num_vlans)
2836882fe   Toshiaki Makita   bridge: Fix the w...
239
  					goto insert;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
241
242
  			}
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243

2836882fe   Toshiaki Makita   bridge: Fix the w...
244
245
246
  insert:
  	/* insert new address,  may fail if invalid address or dup. */
  	fdb_insert(br, p, newaddr, 0);
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
247
  	if (!vg || !vg->num_vlans)
2836882fe   Toshiaki Makita   bridge: Fix the w...
248
249
250
251
252
253
  		goto done;
  
  	/* Now add entries for every VLAN configured on the port.
  	 * This function runs under RTNL so the bitmap will not change
  	 * from under us.
  	 */
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
254
255
  	list_for_each_entry(v, &vg->vlan_list, vlist)
  		fdb_insert(br, p, newaddr, v->vid);
2836882fe   Toshiaki Makita   bridge: Fix the w...
256

bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
257
  done:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
259
  	spin_unlock_bh(&br->hash_lock);
  }
435988133   stephen hemminger   bridge: add local...
260
261
  void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
  {
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
262
  	struct net_bridge_vlan_group *vg;
435988133   stephen hemminger   bridge: add local...
263
  	struct net_bridge_fdb_entry *f;
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
264
  	struct net_bridge_vlan *v;
435988133   stephen hemminger   bridge: add local...
265

ac4c88688   Toshiaki Makita   bridge: Prevent p...
266
  	spin_lock_bh(&br->hash_lock);
435988133   stephen hemminger   bridge: add local...
267
  	/* If old entry was unassociated with any port, then delete it. */
bfd0aeac5   Nikolay Aleksandrov   bridge: fdb: conv...
268
  	f = br_fdb_find(br, br->dev->dev_addr, 0);
7bb90c371   Toshiaki Makita   bridge: Fix probl...
269
  	if (f && f->is_local && !f->dst && !f->added_by_user)
960b589f8   Toshiaki Makita   bridge: Properly ...
270
  		fdb_delete_local(br, NULL, f);
435988133   stephen hemminger   bridge: add local...
271

bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
272
  	fdb_insert(br, NULL, newaddr, 0);
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
273
274
275
  	vg = br_vlan_group(br);
  	if (!vg || !vg->num_vlans)
  		goto out;
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
276
277
278
279
  	/* 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.
  	 */
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
280
  	list_for_each_entry(v, &vg->vlan_list, vlist) {
0b148def4   Toshiaki Makita   bridge: Don't ins...
281
282
  		if (!br_vlan_should_use(v))
  			continue;
bfd0aeac5   Nikolay Aleksandrov   bridge: fdb: conv...
283
  		f = br_fdb_find(br, br->dev->dev_addr, v->vid);
7bb90c371   Toshiaki Makita   bridge: Fix probl...
284
  		if (f && f->is_local && !f->dst && !f->added_by_user)
960b589f8   Toshiaki Makita   bridge: Properly ...
285
  			fdb_delete_local(br, NULL, f);
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
286
  		fdb_insert(br, NULL, newaddr, v->vid);
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
287
  	}
ac4c88688   Toshiaki Makita   bridge: Prevent p...
288
289
  out:
  	spin_unlock_bh(&br->hash_lock);
435988133   stephen hemminger   bridge: add local...
290
  }
f7cdee8a7   Nikolay Aleksandrov   bridge: move to w...
291
  void br_fdb_cleanup(struct work_struct *work)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
  {
f7cdee8a7   Nikolay Aleksandrov   bridge: move to w...
293
294
  	struct net_bridge *br = container_of(work, struct net_bridge,
  					     gc_work.work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
  	unsigned long delay = hold_time(br);
f7cdee8a7   Nikolay Aleksandrov   bridge: move to w...
296
297
  	unsigned long work_delay = delay;
  	unsigned long now = jiffies;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
298
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
300
  	for (i = 0; i < BR_HASH_SIZE; i++) {
  		struct net_bridge_fdb_entry *f;
b67bfe0d4   Sasha Levin   hlist: drop the n...
301
  		struct hlist_node *n;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302

f7cdee8a7   Nikolay Aleksandrov   bridge: move to w...
303
304
305
306
  		if (!br->hash[i].first)
  			continue;
  
  		spin_lock_bh(&br->hash_lock);
b67bfe0d4   Sasha Levin   hlist: drop the n...
307
  		hlist_for_each_entry_safe(f, n, &br->hash[i], hlist) {
071f77226   Baruch Even   [BRIDGE]: Reduce ...
308
  			unsigned long this_timer;
f7cdee8a7   Nikolay Aleksandrov   bridge: move to w...
309

3fcf90111   David S. Miller   Revert "bridge: L...
310
  			if (f->is_static)
071f77226   Baruch Even   [BRIDGE]: Reduce ...
311
  				continue;
dcd45e064   Siva Mannem   bridge: don't age...
312
313
  			if (f->added_by_external_learn)
  				continue;
7cd8861ab   stephen hemminger   bridge: track las...
314
  			this_timer = f->updated + delay;
f7cdee8a7   Nikolay Aleksandrov   bridge: move to w...
315
316
317
  			if (time_after(this_timer, now))
  				work_delay = min(work_delay, this_timer - now);
  			else
31e8a49c1   stephen hemminger   bridge: rearrange...
318
  				fdb_delete(br, f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319
  		}
f7cdee8a7   Nikolay Aleksandrov   bridge: move to w...
320
321
  		spin_unlock_bh(&br->hash_lock);
  		cond_resched();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323

f7cdee8a7   Nikolay Aleksandrov   bridge: move to w...
324
325
326
  	/* Cleanup minimum 10 milliseconds apart */
  	work_delay = max_t(unsigned long, work_delay, msecs_to_jiffies(10));
  	mod_delayed_work(system_long_wq, &br->gc_work, work_delay);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
  }
9cf637473   Stephen Hemminger   bridge: add sysfs...
328
329
330
331
332
333
334
335
  /* 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...
336
337
  		struct hlist_node *n;
  		hlist_for_each_entry_safe(f, n, &br->hash[i], hlist) {
9cf637473   Stephen Hemminger   bridge: add sysfs...
338
  			if (!f->is_static)
31e8a49c1   stephen hemminger   bridge: rearrange...
339
  				fdb_delete(br, f);
9cf637473   Stephen Hemminger   bridge: add sysfs...
340
341
342
343
  		}
  	}
  	spin_unlock_bh(&br->hash_lock);
  }
1a620698c   Stephen Hemminger   [BRIDGE]: flush f...
344

25985edce   Lucas De Marchi   Fix common misspe...
345
  /* Flush all entries referring to a specific port.
9cf637473   Stephen Hemminger   bridge: add sysfs...
346
   * if do_all is set also flush static entries
1ea2d020b   Nikolay Aleksandrov   bridge: vlan: flu...
347
   * if vid is set delete all entries that match the vlan_id
9cf637473   Stephen Hemminger   bridge: add sysfs...
348
   */
1a620698c   Stephen Hemminger   [BRIDGE]: flush f...
349
350
  void br_fdb_delete_by_port(struct net_bridge *br,
  			   const struct net_bridge_port *p,
1ea2d020b   Nikolay Aleksandrov   bridge: vlan: flu...
351
  			   u16 vid,
1a620698c   Stephen Hemminger   [BRIDGE]: flush f...
352
  			   int do_all)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353
354
355
356
357
358
  {
  	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...
359

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360
361
362
  		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...
363
  			if (f->dst != p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364
  				continue;
1ea2d020b   Nikolay Aleksandrov   bridge: vlan: flu...
365
366
367
  			if (!do_all)
  				if (f->is_static || (vid && f->vlan_id != vid))
  					continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368

a778e6d1a   Toshiaki Makita   bridge: Properly ...
369
370
371
372
  			if (f->is_local)
  				fdb_delete_local(br, p, f);
  			else
  				fdb_delete(br, f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
374
375
376
  		}
  	}
  	spin_unlock_bh(&br->hash_lock);
  }
e6373c4c0   Igor Maravić   net:bridge: use I...
377
  #if IS_ENABLED(CONFIG_ATM_LANE)
da6782927   Michał Mirosław   bridge: Simplify ...
378
379
380
  /* 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
381
382
  {
  	struct net_bridge_fdb_entry *fdb;
b5ed54e94   stephen hemminger   bridge: fix RCU r...
383
  	struct net_bridge_port *port;
da6782927   Michał Mirosław   bridge: Simplify ...
384
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
385
  	rcu_read_lock();
b5ed54e94   stephen hemminger   bridge: fix RCU r...
386
387
388
389
  	port = br_port_get_rcu(dev);
  	if (!port)
  		ret = 0;
  	else {
bfd0aeac5   Nikolay Aleksandrov   bridge: fdb: conv...
390
  		fdb = br_fdb_find_rcu(port->br, addr, 0);
435988133   stephen hemminger   bridge: add local...
391
  		ret = fdb && fdb->dst && fdb->dst->dev != dev &&
b5ed54e94   stephen hemminger   bridge: fix RCU r...
392
393
  			fdb->dst->state == BR_STATE_FORWARDING;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
394
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395

da6782927   Michał Mirosław   bridge: Simplify ...
396
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
  }
da6782927   Michał Mirosław   bridge: Simplify ...
398
  #endif /* CONFIG_ATM_LANE */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399
400
  
  /*
9d6f229fc   YOSHIFUJI Hideaki   [NET] BRIDGE: Fix...
401
   * Fill buffer with forwarding table records in
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402
403
404
405
406
407
408
   * 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
409
410
411
412
413
414
  	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...
415
  		hlist_for_each_entry_rcu(f, &br->hash[i], hlist) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416
417
  			if (num >= maxnum)
  				goto out;
9d6f229fc   YOSHIFUJI Hideaki   [NET] BRIDGE: Fix...
418
  			if (has_expired(br, f))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
  				continue;
435988133   stephen hemminger   bridge: add local...
420
421
422
  			/* ignore pseudo entry for local MAC address */
  			if (!f->dst)
  				continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423
424
425
426
427
428
429
  			if (skip) {
  				--skip;
  				continue;
  			}
  
  			/* convert from internal format to API */
  			memcpy(fe->mac_addr, f->addr.addr, ETH_ALEN);
ae4f8fca4   Stephen Hemminger   bridge: forwardin...
430
431
  
  			/* due to ABI compat need to split into hi/lo */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
  			fe->port_no = f->dst->port_no;
ae4f8fca4   Stephen Hemminger   bridge: forwardin...
433
  			fe->port_hi = f->dst->port_no >> 8;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
435
  			fe->is_local = f->is_local;
  			if (!f->is_static)
a399a8053   Eric Dumazet   time: jiffies_del...
436
  				fe->ageing_timer_value = jiffies_delta_to_clock_t(jiffies - f->updated);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
438
439
440
441
442
443
444
445
446
  			++fe;
  			++num;
  		}
  	}
  
   out:
  	rcu_read_unlock();
  
  	return num;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
448
  static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head,
  					       struct net_bridge_port *source,
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
449
  					       const unsigned char *addr,
b7af1472a   Roopa Prabhu   bridge: set is_lo...
450
451
452
  					       __u16 vid,
  					       unsigned char is_local,
  					       unsigned char is_static)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
454
455
456
457
458
  {
  	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
459
  		fdb->dst = source;
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
460
  		fdb->vlan_id = vid;
b7af1472a   Roopa Prabhu   bridge: set is_lo...
461
462
  		fdb->is_local = is_local;
  		fdb->is_static = is_static;
a5642ab47   Toshiaki Makita   bridge: Fix the w...
463
  		fdb->added_by_user = 0;
cf6b8e1ee   Scott Feldman   bridge: add API t...
464
  		fdb->added_by_external_learn = 0;
9fe8bcec0   Arkadi Sharshevsky   net: bridge: Rece...
465
  		fdb->offloaded = 0;
7cd8861ab   stephen hemminger   bridge: track las...
466
  		fdb->updated = fdb->used = jiffies;
1158f762e   Pavel Emelyanov   bridge: Don't put...
467
  		hlist_add_head_rcu(&fdb->hlist, head);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
469
470
471
472
  	}
  	return fdb;
  }
  
  static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
473
  		  const unsigned char *addr, u16 vid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
  {
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
475
  	struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
477
478
479
  	struct net_bridge_fdb_entry *fdb;
  
  	if (!is_valid_ether_addr(addr))
  		return -EINVAL;
bfd0aeac5   Nikolay Aleksandrov   bridge: fdb: conv...
480
  	fdb = br_fdb_find(br, addr, vid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
  	if (fdb) {
9d6f229fc   YOSHIFUJI Hideaki   [NET] BRIDGE: Fix...
482
  		/* it is okay to have multiple ports with same
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483
484
  		 * address, just use the first one.
  		 */
9d6f229fc   YOSHIFUJI Hideaki   [NET] BRIDGE: Fix...
485
  		if (fdb->is_local)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
  			return 0;
de1dfeefe   Roopa Prabhu   bridge: add addre...
487
488
489
  		br_warn(br, "adding interface %s with same address as a received packet (addr:%pM, vlan:%u)
  ",
  		       source ? source->dev->name : br->dev->name, addr, vid);
31e8a49c1   stephen hemminger   bridge: rearrange...
490
  		fdb_delete(br, fdb);
9d6f229fc   YOSHIFUJI Hideaki   [NET] BRIDGE: Fix...
491
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492

b7af1472a   Roopa Prabhu   bridge: set is_lo...
493
  	fdb = fdb_create(head, source, addr, vid, 1, 1);
03e9b64b8   stephen hemminger   bridge: change ar...
494
  	if (!fdb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495
  		return -ENOMEM;
020ec6ba2   Jiri Pirko   bridge: rename fd...
496
  	fdb_add_hw_addr(br, addr);
31e8a49c1   stephen hemminger   bridge: rearrange...
497
  	fdb_notify(br, fdb, RTM_NEWNEIGH);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
498
499
  	return 0;
  }
03e9b64b8   stephen hemminger   bridge: change ar...
500
  /* Add entry for local address of interface */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501
  int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
502
  		  const unsigned char *addr, u16 vid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
503
504
505
506
  {
  	int ret;
  
  	spin_lock_bh(&br->hash_lock);
bc9a25d21   Vlad Yasevich   bridge: Add vlan ...
507
  	ret = fdb_insert(br, source, addr, vid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508
509
510
511
512
  	spin_unlock_bh(&br->hash_lock);
  	return ret;
  }
  
  void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
a5642ab47   Toshiaki Makita   bridge: Fix the w...
513
  		   const unsigned char *addr, u16 vid, bool added_by_user)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
514
  {
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
515
  	struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
  	struct net_bridge_fdb_entry *fdb;
c65c7a306   Jon Maxwell   bridge: notify us...
517
  	bool fdb_modified = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
519
520
521
  
  	/* some users want to always flood. */
  	if (hold_time(br) == 0)
  		return;
df1c0b846   Stephen Hemminger   [BRIDGE]: Packets...
522
523
524
525
  	/* 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 ...
526
  	fdb = fdb_find_rcu(head, addr, vid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
528
529
  	if (likely(fdb)) {
  		/* attempt to update an entry for a local interface */
  		if (unlikely(fdb->is_local)) {
9d6f229fc   YOSHIFUJI Hideaki   [NET] BRIDGE: Fix...
530
  			if (net_ratelimit())
de1dfeefe   Roopa Prabhu   bridge: add addre...
531
532
533
  				br_warn(br, "received packet on %s with own address as source address (addr:%pM, vlan:%u)
  ",
  					source->dev->name, addr, vid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
  		} else {
ca6d4480f   stephen hemminger   bridge: avoid unn...
535
  			unsigned long now = jiffies;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
  			/* fastpath: update of existing entry */
c65c7a306   Jon Maxwell   bridge: notify us...
537
538
539
  			if (unlikely(source != fdb->dst)) {
  				fdb->dst = source;
  				fdb_modified = true;
58073b32b   Arkadi Sharshevsky   net: bridge: Fix ...
540
541
542
  				/* Take over HW learned entry */
  				if (unlikely(fdb->added_by_external_learn))
  					fdb->added_by_external_learn = 0;
c65c7a306   Jon Maxwell   bridge: notify us...
543
  			}
ca6d4480f   stephen hemminger   bridge: avoid unn...
544
545
  			if (now != fdb->updated)
  				fdb->updated = now;
a5642ab47   Toshiaki Makita   bridge: Fix the w...
546
547
  			if (unlikely(added_by_user))
  				fdb->added_by_user = 1;
e3cfddd57   Roopa Prabhu   bridge: add trace...
548
549
  			if (unlikely(fdb_modified)) {
  				trace_br_fdb_update(br, source, addr, vid, added_by_user);
c65c7a306   Jon Maxwell   bridge: notify us...
550
  				fdb_notify(br, fdb, RTM_NEWNEIGH);
e3cfddd57   Roopa Prabhu   bridge: add trace...
551
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552
553
  		}
  	} else {
f8ae737de   Stephen Hemminger   [BRIDGE]: forward...
554
  		spin_lock(&br->hash_lock);
bfd0aeac5   Nikolay Aleksandrov   bridge: fdb: conv...
555
  		if (likely(!fdb_find_rcu(head, addr, vid))) {
b7af1472a   Roopa Prabhu   bridge: set is_lo...
556
  			fdb = fdb_create(head, source, addr, vid, 0, 0);
a5642ab47   Toshiaki Makita   bridge: Fix the w...
557
558
559
  			if (fdb) {
  				if (unlikely(added_by_user))
  					fdb->added_by_user = 1;
e3cfddd57   Roopa Prabhu   bridge: add trace...
560
  				trace_br_fdb_update(br, source, addr, vid, added_by_user);
31e8a49c1   stephen hemminger   bridge: rearrange...
561
  				fdb_notify(br, fdb, RTM_NEWNEIGH);
a5642ab47   Toshiaki Makita   bridge: Fix the w...
562
  			}
f58ee4e1a   stephen hemminger   bridge: refactor ...
563
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564
565
566
  		/* else  we lose race and someone else inserts
  		 * it first, don't bother updating
  		 */
f8ae737de   Stephen Hemminger   [BRIDGE]: forward...
567
  		spin_unlock(&br->hash_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
569
  }
b078f0df6   stephen hemminger   bridge: add netli...
570

3741873b4   Roopa Prabhu   bridge: allow add...
571
572
  static int fdb_to_nud(const struct net_bridge *br,
  		      const struct net_bridge_fdb_entry *fdb)
b078f0df6   stephen hemminger   bridge: add netli...
573
574
575
576
577
  {
  	if (fdb->is_local)
  		return NUD_PERMANENT;
  	else if (fdb->is_static)
  		return NUD_NOARP;
3741873b4   Roopa Prabhu   bridge: allow add...
578
  	else if (has_expired(br, fdb))
b078f0df6   stephen hemminger   bridge: add netli...
579
580
581
582
  		return NUD_STALE;
  	else
  		return NUD_REACHABLE;
  }
31e8a49c1   stephen hemminger   bridge: rearrange...
583
  static int fdb_fill_info(struct sk_buff *skb, const struct net_bridge *br,
b078f0df6   stephen hemminger   bridge: add netli...
584
  			 const struct net_bridge_fdb_entry *fdb,
15e473046   Eric W. Biederman   netlink: Rename p...
585
  			 u32 portid, u32 seq, int type, unsigned int flags)
b078f0df6   stephen hemminger   bridge: add netli...
586
587
588
589
590
  {
  	unsigned long now = jiffies;
  	struct nda_cacheinfo ci;
  	struct nlmsghdr *nlh;
  	struct ndmsg *ndm;
15e473046   Eric W. Biederman   netlink: Rename p...
591
  	nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags);
b078f0df6   stephen hemminger   bridge: add netli...
592
593
  	if (nlh == NULL)
  		return -EMSGSIZE;
b078f0df6   stephen hemminger   bridge: add netli...
594
595
596
597
  	ndm = nlmsg_data(nlh);
  	ndm->ndm_family	 = AF_BRIDGE;
  	ndm->ndm_pad1    = 0;
  	ndm->ndm_pad2    = 0;
9fe8bcec0   Arkadi Sharshevsky   net: bridge: Rece...
598
  	ndm->ndm_flags	 = 0;
b078f0df6   stephen hemminger   bridge: add netli...
599
  	ndm->ndm_type	 = 0;
435988133   stephen hemminger   bridge: add local...
600
  	ndm->ndm_ifindex = fdb->dst ? fdb->dst->dev->ifindex : br->dev->ifindex;
3741873b4   Roopa Prabhu   bridge: allow add...
601
  	ndm->ndm_state   = fdb_to_nud(br, fdb);
b078f0df6   stephen hemminger   bridge: add netli...
602

9fe8bcec0   Arkadi Sharshevsky   net: bridge: Rece...
603
604
605
606
  	if (fdb->offloaded)
  		ndm->ndm_flags |= NTF_OFFLOADED;
  	if (fdb->added_by_external_learn)
  		ndm->ndm_flags |= NTF_EXT_LEARNED;
2eb812e65   David S. Miller   bridge: Stop usin...
607
608
  	if (nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->addr))
  		goto nla_put_failure;
41c389d72   Roopa Prabhu   bridge: Add bridg...
609
610
  	if (nla_put_u32(skb, NDA_MASTER, br->dev->ifindex))
  		goto nla_put_failure;
b078f0df6   stephen hemminger   bridge: add netli...
611
612
613
614
  	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...
615
616
  	if (nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
  		goto nla_put_failure;
1690be63a   Vlad Yasevich   bridge: Add vlan ...
617

47fab41ab   Toshiaki Makita   bridge: Don't inc...
618
  	if (fdb->vlan_id && nla_put(skb, NDA_VLAN, sizeof(u16), &fdb->vlan_id))
1690be63a   Vlad Yasevich   bridge: Add vlan ...
619
  		goto nla_put_failure;
053c095a8   Johannes Berg   netlink: make nlm...
620
621
  	nlmsg_end(skb, nlh);
  	return 0;
b078f0df6   stephen hemminger   bridge: add netli...
622
623
624
625
626
627
628
629
630
631
  
  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 */
41c389d72   Roopa Prabhu   bridge: Add bridg...
632
  		+ nla_total_size(sizeof(u32)) /* NDA_MASTER */
1690be63a   Vlad Yasevich   bridge: Add vlan ...
633
  		+ nla_total_size(sizeof(u16)) /* NDA_VLAN */
b078f0df6   stephen hemminger   bridge: add netli...
634
635
  		+ nla_total_size(sizeof(struct nda_cacheinfo));
  }
31e8a49c1   stephen hemminger   bridge: rearrange...
636
637
  static void fdb_notify(struct net_bridge *br,
  		       const struct net_bridge_fdb_entry *fdb, int type)
b078f0df6   stephen hemminger   bridge: add netli...
638
  {
31e8a49c1   stephen hemminger   bridge: rearrange...
639
  	struct net *net = dev_net(br->dev);
b078f0df6   stephen hemminger   bridge: add netli...
640
641
  	struct sk_buff *skb;
  	int err = -ENOBUFS;
6b26b51b1   Arkadi Sharshevsky   net: bridge: Add ...
642
  	br_switchdev_fdb_notify(fdb, type);
b078f0df6   stephen hemminger   bridge: add netli...
643
644
645
  	skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC);
  	if (skb == NULL)
  		goto errout;
31e8a49c1   stephen hemminger   bridge: rearrange...
646
  	err = fdb_fill_info(skb, br, fdb, 0, 0, type, 0);
b078f0df6   stephen hemminger   bridge: add netli...
647
648
649
650
651
652
653
654
655
  	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:
87e823b3d   tanxiaojun   bridge: remove un...
656
  	rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
b078f0df6   stephen hemminger   bridge: add netli...
657
658
659
  }
  
  /* Dump information about entries, in response to GETNEIGH */
77162022a   John Fastabend   net: add generic ...
660
661
662
  int br_fdb_dump(struct sk_buff *skb,
  		struct netlink_callback *cb,
  		struct net_device *dev,
5d5eacb34   Jamal Hadi Salim   bridge: fdb dumpi...
663
  		struct net_device *filter_dev,
d297653dd   Roopa Prabhu   rtnetlink: fdb du...
664
  		int *idx)
b078f0df6   stephen hemminger   bridge: add netli...
665
  {
77162022a   John Fastabend   net: add generic ...
666
  	struct net_bridge *br = netdev_priv(dev);
d297653dd   Roopa Prabhu   rtnetlink: fdb du...
667
  	int err = 0;
77162022a   John Fastabend   net: add generic ...
668
  	int i;
b078f0df6   stephen hemminger   bridge: add netli...
669

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

d297653dd   Roopa Prabhu   rtnetlink: fdb du...
673
674
675
676
677
  	if (!filter_dev) {
  		err = ndo_dflt_fdb_dump(skb, cb, dev, NULL, idx);
  		if (err < 0)
  			goto out;
  	}
6cb69742d   Hubert Sokolowski   net: Do not call ...
678

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

b67bfe0d4   Sasha Levin   hlist: drop the n...
682
  		hlist_for_each_entry_rcu(f, &br->hash[i], hlist) {
472681d57   MINOURA Makoto / 箕浦 真   net: ndo_fdb_dump...
683

d297653dd   Roopa Prabhu   rtnetlink: fdb du...
684
  			if (*idx < cb->args[2])
77162022a   John Fastabend   net: add generic ...
685
  				goto skip;
5e6d24358   Jamal Hadi Salim   bridge: netlink d...
686
687
688
689
  			if (filter_dev &&
  			    (!f->dst || f->dst->dev != filter_dev)) {
  				if (filter_dev != dev)
  					goto skip;
6cb69742d   Hubert Sokolowski   net: Do not call ...
690
  				/* !f->dst is a special case for bridge
5e6d24358   Jamal Hadi Salim   bridge: netlink d...
691
692
693
694
695
696
697
  				 * It means the MAC belongs to the bridge
  				 * Therefore need a little more filtering
  				 * we only want to dump the !f->dst case
  				 */
  				if (f->dst)
  					goto skip;
  			}
6cb69742d   Hubert Sokolowski   net: Do not call ...
698
699
  			if (!filter_dev && f->dst)
  				goto skip;
5d5eacb34   Jamal Hadi Salim   bridge: fdb dumpi...
700

472681d57   MINOURA Makoto / 箕浦 真   net: ndo_fdb_dump...
701
702
703
704
705
  			err = fdb_fill_info(skb, br, f,
  					    NETLINK_CB(cb->skb).portid,
  					    cb->nlh->nlmsg_seq,
  					    RTM_NEWNEIGH,
  					    NLM_F_MULTI);
d297653dd   Roopa Prabhu   rtnetlink: fdb du...
706
707
  			if (err < 0)
  				goto out;
b078f0df6   stephen hemminger   bridge: add netli...
708
  skip:
d297653dd   Roopa Prabhu   rtnetlink: fdb du...
709
  			*idx += 1;
b078f0df6   stephen hemminger   bridge: add netli...
710
711
  		}
  	}
b078f0df6   stephen hemminger   bridge: add netli...
712

77162022a   John Fastabend   net: add generic ...
713
  out:
d297653dd   Roopa Prabhu   rtnetlink: fdb du...
714
  	return err;
b078f0df6   stephen hemminger   bridge: add netli...
715
  }
36fd2b63e   stephen hemminger   bridge: allow cre...
716

292d13989   stephen hemminger   bridge: add NTF_U...
717
  /* Update (create or replace) forwarding database entry */
7bb90c371   Toshiaki Makita   bridge: Fix probl...
718
719
  static int fdb_add_entry(struct net_bridge *br, struct net_bridge_port *source,
  			 const __u8 *addr, __u16 state, __u16 flags, __u16 vid)
36fd2b63e   stephen hemminger   bridge: allow cre...
720
  {
2ba071ecb   Vlad Yasevich   bridge: Add vlan ...
721
  	struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
36fd2b63e   stephen hemminger   bridge: allow cre...
722
  	struct net_bridge_fdb_entry *fdb;
b0a397fb3   roopa   bridge: Add fdb d...
723
  	bool modified = false;
36fd2b63e   stephen hemminger   bridge: allow cre...
724

eb8d7baae   Wilson Kok   bridge: skip fdb ...
725
  	/* If the port cannot learn allow only local and static entries */
7bb90c371   Toshiaki Makita   bridge: Fix probl...
726
  	if (source && !(state & NUD_PERMANENT) && !(state & NUD_NOARP) &&
eb8d7baae   Wilson Kok   bridge: skip fdb ...
727
728
729
  	    !(source->state == BR_STATE_LEARNING ||
  	      source->state == BR_STATE_FORWARDING))
  		return -EPERM;
7bb90c371   Toshiaki Makita   bridge: Fix probl...
730
731
732
733
734
735
  	if (!source && !(state & NUD_PERMANENT)) {
  		pr_info("bridge: RTM_NEWNEIGH %s without NUD_PERMANENT
  ",
  			br->dev->name);
  		return -EINVAL;
  	}
bfd0aeac5   Nikolay Aleksandrov   bridge: fdb: conv...
736
  	fdb = br_fdb_find(br, addr, vid);
64af1bac9   stephen hemminger   bridge: allow upd...
737
738
739
  	if (fdb == NULL) {
  		if (!(flags & NLM_F_CREATE))
  			return -ENOENT;
36fd2b63e   stephen hemminger   bridge: allow cre...
740

b7af1472a   Roopa Prabhu   bridge: set is_lo...
741
  		fdb = fdb_create(head, source, addr, vid, 0, 0);
64af1bac9   stephen hemminger   bridge: allow upd...
742
743
  		if (!fdb)
  			return -ENOMEM;
b0a397fb3   roopa   bridge: Add fdb d...
744
745
  
  		modified = true;
64af1bac9   stephen hemminger   bridge: allow upd...
746
747
748
  	} else {
  		if (flags & NLM_F_EXCL)
  			return -EEXIST;
b0a397fb3   roopa   bridge: Add fdb d...
749
750
751
752
753
  
  		if (fdb->dst != source) {
  			fdb->dst = source;
  			modified = true;
  		}
292d13989   stephen hemminger   bridge: add NTF_U...
754
  	}
3741873b4   Roopa Prabhu   bridge: allow add...
755
  	if (fdb_to_nud(br, fdb) != state) {
145beee8d   Vlad Yasevich   bridge: Add addre...
756
757
758
759
  		if (state & NUD_PERMANENT) {
  			fdb->is_local = 1;
  			if (!fdb->is_static) {
  				fdb->is_static = 1;
020ec6ba2   Jiri Pirko   bridge: rename fd...
760
  				fdb_add_hw_addr(br, addr);
145beee8d   Vlad Yasevich   bridge: Add addre...
761
762
763
764
765
  			}
  		} else if (state & NUD_NOARP) {
  			fdb->is_local = 0;
  			if (!fdb->is_static) {
  				fdb->is_static = 1;
020ec6ba2   Jiri Pirko   bridge: rename fd...
766
  				fdb_add_hw_addr(br, addr);
145beee8d   Vlad Yasevich   bridge: Add addre...
767
768
  			}
  		} else {
292d13989   stephen hemminger   bridge: add NTF_U...
769
  			fdb->is_local = 0;
145beee8d   Vlad Yasevich   bridge: Add addre...
770
771
  			if (fdb->is_static) {
  				fdb->is_static = 0;
020ec6ba2   Jiri Pirko   bridge: rename fd...
772
  				fdb_del_hw_addr(br, addr);
145beee8d   Vlad Yasevich   bridge: Add addre...
773
774
  			}
  		}
64af1bac9   stephen hemminger   bridge: allow upd...
775

b0a397fb3   roopa   bridge: Add fdb d...
776
777
  		modified = true;
  	}
a5642ab47   Toshiaki Makita   bridge: Fix the w...
778
  	fdb->added_by_user = 1;
b0a397fb3   roopa   bridge: Add fdb d...
779
780
781
782
  
  	fdb->used = jiffies;
  	if (modified) {
  		fdb->updated = jiffies;
31e8a49c1   stephen hemminger   bridge: rearrange...
783
  		fdb_notify(br, fdb, RTM_NEWNEIGH);
64af1bac9   stephen hemminger   bridge: allow upd...
784
  	}
36fd2b63e   stephen hemminger   bridge: allow cre...
785

36fd2b63e   stephen hemminger   bridge: allow cre...
786
787
  	return 0;
  }
7bb90c371   Toshiaki Makita   bridge: Fix probl...
788
789
790
  static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge *br,
  			struct net_bridge_port *p, const unsigned char *addr,
  			u16 nlh_flags, u16 vid)
1690be63a   Vlad Yasevich   bridge: Add vlan ...
791
792
793
794
  {
  	int err = 0;
  
  	if (ndm->ndm_flags & NTF_USE) {
7bb90c371   Toshiaki Makita   bridge: Fix probl...
795
796
797
798
799
800
  		if (!p) {
  			pr_info("bridge: RTM_NEWNEIGH %s with NTF_USE is not supported
  ",
  				br->dev->name);
  			return -EINVAL;
  		}
c4c832f89   Nikolay Aleksandrov   bridge: disable s...
801
  		local_bh_disable();
1690be63a   Vlad Yasevich   bridge: Add vlan ...
802
  		rcu_read_lock();
7bb90c371   Toshiaki Makita   bridge: Fix probl...
803
  		br_fdb_update(br, p, addr, vid, true);
1690be63a   Vlad Yasevich   bridge: Add vlan ...
804
  		rcu_read_unlock();
c4c832f89   Nikolay Aleksandrov   bridge: disable s...
805
  		local_bh_enable();
eb100e0e2   Nikolay Aleksandrov   net: bridge: allo...
806
807
  	} else if (ndm->ndm_flags & NTF_EXT_LEARNED) {
  		err = br_fdb_external_learn_add(br, p, addr, vid);
1690be63a   Vlad Yasevich   bridge: Add vlan ...
808
  	} else {
7bb90c371   Toshiaki Makita   bridge: Fix probl...
809
810
  		spin_lock_bh(&br->hash_lock);
  		err = fdb_add_entry(br, p, addr, ndm->ndm_state,
1690be63a   Vlad Yasevich   bridge: Add vlan ...
811
  				    nlh_flags, vid);
7bb90c371   Toshiaki Makita   bridge: Fix probl...
812
  		spin_unlock_bh(&br->hash_lock);
1690be63a   Vlad Yasevich   bridge: Add vlan ...
813
814
815
816
  	}
  
  	return err;
  }
36fd2b63e   stephen hemminger   bridge: allow cre...
817
  /* Add new permanent fdb entry with RTM_NEWNEIGH */
edc7d5732   stephen hemminger   netlink: add attr...
818
819
  int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
  	       struct net_device *dev,
f6f6424ba   Jiri Pirko   net: make vid as ...
820
  	       const unsigned char *addr, u16 vid, u16 nlh_flags)
36fd2b63e   stephen hemminger   bridge: allow cre...
821
  {
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
822
  	struct net_bridge_vlan_group *vg;
3741873b4   Roopa Prabhu   bridge: allow add...
823
  	struct net_bridge_port *p = NULL;
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
824
  	struct net_bridge_vlan *v;
3741873b4   Roopa Prabhu   bridge: allow add...
825
  	struct net_bridge *br = NULL;
77162022a   John Fastabend   net: add generic ...
826
  	int err = 0;
36fd2b63e   stephen hemminger   bridge: allow cre...
827

b74fd306e   Roopa Prabhu   bridge: fdb add a...
828
  	trace_br_fdb_add(ndm, dev, addr, vid, nlh_flags);
292d13989   stephen hemminger   bridge: add NTF_U...
829
830
831
832
833
  	if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE))) {
  		pr_info("bridge: RTM_NEWNEIGH with invalid state %#x
  ", ndm->ndm_state);
  		return -EINVAL;
  	}
537f7f849   Stephen Hemminger   bridge: check for...
834
835
836
837
838
  	if (is_zero_ether_addr(addr)) {
  		pr_info("bridge: RTM_NEWNEIGH with invalid ether address
  ");
  		return -EINVAL;
  	}
3741873b4   Roopa Prabhu   bridge: allow add...
839
840
841
842
843
844
845
846
847
848
849
  	if (dev->priv_flags & IFF_EBRIDGE) {
  		br = netdev_priv(dev);
  		vg = br_vlan_group(br);
  	} else {
  		p = br_port_get_rtnl(dev);
  		if (!p) {
  			pr_info("bridge: RTM_NEWNEIGH %s not a bridge port
  ",
  				dev->name);
  			return -EINVAL;
  		}
7bb90c371   Toshiaki Makita   bridge: Fix probl...
850
  		br = p->br;
3741873b4   Roopa Prabhu   bridge: allow add...
851
  		vg = nbp_vlan_group(p);
36fd2b63e   stephen hemminger   bridge: allow cre...
852
  	}
f6f6424ba   Jiri Pirko   net: make vid as ...
853
  	if (vid) {
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
854
  		v = br_vlan_find(vg, vid);
3741873b4   Roopa Prabhu   bridge: allow add...
855
856
857
  		if (!v || !br_vlan_should_use(v)) {
  			pr_info("bridge: RTM_NEWNEIGH with unconfigured vlan %d on %s
  ", vid, dev->name);
1690be63a   Vlad Yasevich   bridge: Add vlan ...
858
859
860
861
  			return -EINVAL;
  		}
  
  		/* VID was specified, so use it. */
7bb90c371   Toshiaki Makita   bridge: Fix probl...
862
  		err = __br_fdb_add(ndm, br, p, addr, nlh_flags, vid);
292d13989   stephen hemminger   bridge: add NTF_U...
863
  	} else {
7bb90c371   Toshiaki Makita   bridge: Fix probl...
864
  		err = __br_fdb_add(ndm, br, p, addr, nlh_flags, 0);
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
865
  		if (err || !vg || !vg->num_vlans)
1690be63a   Vlad Yasevich   bridge: Add vlan ...
866
  			goto out;
1690be63a   Vlad Yasevich   bridge: Add vlan ...
867
868
869
870
871
  
  		/* 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.
  		 */
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
872
  		list_for_each_entry(v, &vg->vlan_list, vlist) {
3741873b4   Roopa Prabhu   bridge: allow add...
873
874
  			if (!br_vlan_should_use(v))
  				continue;
7bb90c371   Toshiaki Makita   bridge: Fix probl...
875
  			err = __br_fdb_add(ndm, br, p, addr, nlh_flags, v->vid);
1690be63a   Vlad Yasevich   bridge: Add vlan ...
876
877
  			if (err)
  				goto out;
1690be63a   Vlad Yasevich   bridge: Add vlan ...
878
  		}
292d13989   stephen hemminger   bridge: add NTF_U...
879
  	}
36fd2b63e   stephen hemminger   bridge: allow cre...
880

1690be63a   Vlad Yasevich   bridge: Add vlan ...
881
  out:
36fd2b63e   stephen hemminger   bridge: allow cre...
882
883
  	return err;
  }
5019ab50f   Nikolay Aleksandrov   bridge: fdb: conv...
884
885
  static int fdb_delete_by_addr_and_port(struct net_bridge *br,
  				       const struct net_bridge_port *p,
8c86f967d   Nikolay Aleksandrov   bridge: make br_f...
886
  				       const u8 *addr, u16 vlan)
36fd2b63e   stephen hemminger   bridge: allow cre...
887
  {
36fd2b63e   stephen hemminger   bridge: allow cre...
888
  	struct net_bridge_fdb_entry *fdb;
bfd0aeac5   Nikolay Aleksandrov   bridge: fdb: conv...
889
  	fdb = br_fdb_find(br, addr, vlan);
8c86f967d   Nikolay Aleksandrov   bridge: make br_f...
890
  	if (!fdb || fdb->dst != p)
36fd2b63e   stephen hemminger   bridge: allow cre...
891
  		return -ENOENT;
1690be63a   Vlad Yasevich   bridge: Add vlan ...
892
  	fdb_delete(br, fdb);
5019ab50f   Nikolay Aleksandrov   bridge: fdb: conv...
893

36fd2b63e   stephen hemminger   bridge: allow cre...
894
895
  	return 0;
  }
5019ab50f   Nikolay Aleksandrov   bridge: fdb: conv...
896
897
  static int __br_fdb_delete(struct net_bridge *br,
  			   const struct net_bridge_port *p,
1690be63a   Vlad Yasevich   bridge: Add vlan ...
898
899
900
  			   const unsigned char *addr, u16 vid)
  {
  	int err;
5019ab50f   Nikolay Aleksandrov   bridge: fdb: conv...
901
902
903
  	spin_lock_bh(&br->hash_lock);
  	err = fdb_delete_by_addr_and_port(br, p, addr, vid);
  	spin_unlock_bh(&br->hash_lock);
1690be63a   Vlad Yasevich   bridge: Add vlan ...
904
905
906
  
  	return err;
  }
36fd2b63e   stephen hemminger   bridge: allow cre...
907
  /* Remove neighbor entry with RTM_DELNEIGH */
1690be63a   Vlad Yasevich   bridge: Add vlan ...
908
909
  int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
  		  struct net_device *dev,
f6f6424ba   Jiri Pirko   net: make vid as ...
910
  		  const unsigned char *addr, u16 vid)
36fd2b63e   stephen hemminger   bridge: allow cre...
911
  {
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
912
  	struct net_bridge_vlan_group *vg;
3741873b4   Roopa Prabhu   bridge: allow add...
913
  	struct net_bridge_port *p = NULL;
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
914
  	struct net_bridge_vlan *v;
5019ab50f   Nikolay Aleksandrov   bridge: fdb: conv...
915
  	struct net_bridge *br;
36fd2b63e   stephen hemminger   bridge: allow cre...
916
  	int err;
1690be63a   Vlad Yasevich   bridge: Add vlan ...
917

3741873b4   Roopa Prabhu   bridge: allow add...
918
919
920
921
922
923
924
925
926
927
928
929
  	if (dev->priv_flags & IFF_EBRIDGE) {
  		br = netdev_priv(dev);
  		vg = br_vlan_group(br);
  	} else {
  		p = br_port_get_rtnl(dev);
  		if (!p) {
  			pr_info("bridge: RTM_DELNEIGH %s not a bridge port
  ",
  				dev->name);
  			return -EINVAL;
  		}
  		vg = nbp_vlan_group(p);
5019ab50f   Nikolay Aleksandrov   bridge: fdb: conv...
930
  		br = p->br;
36fd2b63e   stephen hemminger   bridge: allow cre...
931
  	}
f6f6424ba   Jiri Pirko   net: make vid as ...
932
  	if (vid) {
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
933
934
  		v = br_vlan_find(vg, vid);
  		if (!v) {
3741873b4   Roopa Prabhu   bridge: allow add...
935
936
  			pr_info("bridge: RTM_DELNEIGH with unconfigured vlan %d on %s
  ", vid, dev->name);
1690be63a   Vlad Yasevich   bridge: Add vlan ...
937
938
  			return -EINVAL;
  		}
36fd2b63e   stephen hemminger   bridge: allow cre...
939

5019ab50f   Nikolay Aleksandrov   bridge: fdb: conv...
940
  		err = __br_fdb_delete(br, p, addr, vid);
1690be63a   Vlad Yasevich   bridge: Add vlan ...
941
  	} else {
25d3b493a   Toshiaki Makita   bridge: Fix inabi...
942
  		err = -ENOENT;
5019ab50f   Nikolay Aleksandrov   bridge: fdb: conv...
943
  		err &= __br_fdb_delete(br, p, addr, 0);
2594e9064   Nikolay Aleksandrov   bridge: vlan: add...
944
  		if (!vg || !vg->num_vlans)
5019ab50f   Nikolay Aleksandrov   bridge: fdb: conv...
945
  			return err;
1690be63a   Vlad Yasevich   bridge: Add vlan ...
946

3741873b4   Roopa Prabhu   bridge: allow add...
947
948
949
  		list_for_each_entry(v, &vg->vlan_list, vlist) {
  			if (!br_vlan_should_use(v))
  				continue;
5019ab50f   Nikolay Aleksandrov   bridge: fdb: conv...
950
  			err &= __br_fdb_delete(br, p, addr, v->vid);
3741873b4   Roopa Prabhu   bridge: allow add...
951
  		}
1690be63a   Vlad Yasevich   bridge: Add vlan ...
952
  	}
5019ab50f   Nikolay Aleksandrov   bridge: fdb: conv...
953

36fd2b63e   stephen hemminger   bridge: allow cre...
954
955
  	return err;
  }
8db24af71   Vlad Yasevich   bridge: Add funct...
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
  
  int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p)
  {
  	struct net_bridge_fdb_entry *fdb, *tmp;
  	int i;
  	int err;
  
  	ASSERT_RTNL();
  
  	for (i = 0; i < BR_HASH_SIZE; i++) {
  		hlist_for_each_entry(fdb, &br->hash[i], hlist) {
  			/* We only care for static entries */
  			if (!fdb->is_static)
  				continue;
  
  			err = dev_uc_add(p->dev, fdb->addr.addr);
  			if (err)
  				goto rollback;
  		}
  	}
  	return 0;
  
  rollback:
  	for (i = 0; i < BR_HASH_SIZE; i++) {
  		hlist_for_each_entry(tmp, &br->hash[i], hlist) {
  			/* If we reached the fdb that failed, we can stop */
  			if (tmp == fdb)
  				break;
  
  			/* We only care for static entries */
  			if (!tmp->is_static)
  				continue;
  
  			dev_uc_del(p->dev, tmp->addr.addr);
  		}
  	}
  	return err;
  }
  
  void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p)
  {
  	struct net_bridge_fdb_entry *fdb;
  	int i;
  
  	ASSERT_RTNL();
  
  	for (i = 0; i < BR_HASH_SIZE; i++) {
  		hlist_for_each_entry_rcu(fdb, &br->hash[i], hlist) {
  			/* We only care for static entries */
  			if (!fdb->is_static)
  				continue;
  
  			dev_uc_del(p->dev, fdb->addr.addr);
  		}
  	}
  }
cf6b8e1ee   Scott Feldman   bridge: add API t...
1012

3aeb66176   Jiri Pirko   net: replace br_f...
1013
  int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
cf6b8e1ee   Scott Feldman   bridge: add API t...
1014
1015
  			      const unsigned char *addr, u16 vid)
  {
cf6b8e1ee   Scott Feldman   bridge: add API t...
1016
  	struct net_bridge_fdb_entry *fdb;
7597b266c   Nikolay Aleksandrov   bridge: allow ext...
1017
1018
  	struct hlist_head *head;
  	bool modified = false;
cf6b8e1ee   Scott Feldman   bridge: add API t...
1019
  	int err = 0;
b74fd306e   Roopa Prabhu   bridge: fdb add a...
1020
  	trace_br_fdb_external_learn_add(br, p, addr, vid);
cf6b8e1ee   Scott Feldman   bridge: add API t...
1021
1022
1023
  	spin_lock_bh(&br->hash_lock);
  
  	head = &br->hash[br_mac_hash(addr, vid)];
bfd0aeac5   Nikolay Aleksandrov   bridge: fdb: conv...
1024
  	fdb = br_fdb_find(br, addr, vid);
cf6b8e1ee   Scott Feldman   bridge: add API t...
1025
  	if (!fdb) {
b7af1472a   Roopa Prabhu   bridge: set is_lo...
1026
  		fdb = fdb_create(head, p, addr, vid, 0, 0);
cf6b8e1ee   Scott Feldman   bridge: add API t...
1027
1028
1029
1030
1031
1032
  		if (!fdb) {
  			err = -ENOMEM;
  			goto err_unlock;
  		}
  		fdb->added_by_external_learn = 1;
  		fdb_notify(br, fdb, RTM_NEWNEIGH);
7597b266c   Nikolay Aleksandrov   bridge: allow ext...
1033
  	} else {
cf6b8e1ee   Scott Feldman   bridge: add API t...
1034
  		fdb->updated = jiffies;
7597b266c   Nikolay Aleksandrov   bridge: allow ext...
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
  
  		if (fdb->dst != p) {
  			fdb->dst = p;
  			modified = true;
  		}
  
  		if (fdb->added_by_external_learn) {
  			/* Refresh entry */
  			fdb->used = jiffies;
  		} else if (!fdb->added_by_user) {
  			/* Take over SW learned entry */
  			fdb->added_by_external_learn = 1;
  			modified = true;
  		}
  
  		if (modified)
  			fdb_notify(br, fdb, RTM_NEWNEIGH);
cf6b8e1ee   Scott Feldman   bridge: add API t...
1052
1053
1054
1055
  	}
  
  err_unlock:
  	spin_unlock_bh(&br->hash_lock);
cf6b8e1ee   Scott Feldman   bridge: add API t...
1056
1057
1058
  
  	return err;
  }
cf6b8e1ee   Scott Feldman   bridge: add API t...
1059

3aeb66176   Jiri Pirko   net: replace br_f...
1060
  int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
cf6b8e1ee   Scott Feldman   bridge: add API t...
1061
1062
  			      const unsigned char *addr, u16 vid)
  {
cf6b8e1ee   Scott Feldman   bridge: add API t...
1063
1064
  	struct net_bridge_fdb_entry *fdb;
  	int err = 0;
cf6b8e1ee   Scott Feldman   bridge: add API t...
1065
  	spin_lock_bh(&br->hash_lock);
bfd0aeac5   Nikolay Aleksandrov   bridge: fdb: conv...
1066
  	fdb = br_fdb_find(br, addr, vid);
cf6b8e1ee   Scott Feldman   bridge: add API t...
1067
1068
1069
1070
1071
1072
  	if (fdb && fdb->added_by_external_learn)
  		fdb_delete(br, fdb);
  	else
  		err = -ENOENT;
  
  	spin_unlock_bh(&br->hash_lock);
cf6b8e1ee   Scott Feldman   bridge: add API t...
1073
1074
1075
  
  	return err;
  }
9fe8bcec0   Arkadi Sharshevsky   net: bridge: Rece...
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
  
  void br_fdb_offloaded_set(struct net_bridge *br, struct net_bridge_port *p,
  			  const unsigned char *addr, u16 vid)
  {
  	struct net_bridge_fdb_entry *fdb;
  
  	spin_lock_bh(&br->hash_lock);
  
  	fdb = br_fdb_find(br, addr, vid);
  	if (fdb)
  		fdb->offloaded = 1;
  
  	spin_unlock_bh(&br->hash_lock);
  }