Branch data Line data Source code
1 : : /*
2 : : * net/core/dev_addr_lists.c - Functions for handling net device lists
3 : : * Copyright (c) 2010 Jiri Pirko <jpirko@redhat.com>
4 : : *
5 : : * This file contains functions for working with unicast, multicast and device
6 : : * addresses lists.
7 : : *
8 : : * This program is free software; you can redistribute it and/or modify
9 : : * it under the terms of the GNU General Public License as published by
10 : : * the Free Software Foundation; either version 2 of the License, or
11 : : * (at your option) any later version.
12 : : */
13 : :
14 : : #include <linux/netdevice.h>
15 : : #include <linux/rtnetlink.h>
16 : : #include <linux/export.h>
17 : : #include <linux/list.h>
18 : :
19 : : /*
20 : : * General list handling functions
21 : : */
22 : :
23 : 0 : static int __hw_addr_create_ex(struct netdev_hw_addr_list *list,
24 : : const unsigned char *addr, int addr_len,
25 : : unsigned char addr_type, bool global,
26 : : bool sync)
27 : : {
28 : : struct netdev_hw_addr *ha;
29 : : int alloc_size;
30 : :
31 : : alloc_size = sizeof(*ha);
32 : : if (alloc_size < L1_CACHE_BYTES)
33 : : alloc_size = L1_CACHE_BYTES;
34 : : ha = kmalloc(alloc_size, GFP_ATOMIC);
35 [ # # ]: 0 : if (!ha)
36 : : return -ENOMEM;
37 : 0 : memcpy(ha->addr, addr, addr_len);
38 : 0 : ha->type = addr_type;
39 : 0 : ha->refcount = 1;
40 : 0 : ha->global_use = global;
41 : 0 : ha->synced = sync;
42 : 0 : ha->sync_cnt = 0;
43 : 0 : list_add_tail_rcu(&ha->list, &list->list);
44 : 0 : list->count++;
45 : :
46 : 0 : return 0;
47 : : }
48 : :
49 : 0 : static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
50 : : const unsigned char *addr, int addr_len,
51 : : unsigned char addr_type, bool global, bool sync)
52 : : {
53 : : struct netdev_hw_addr *ha;
54 : :
55 [ # # ]: 0 : if (addr_len > MAX_ADDR_LEN)
56 : : return -EINVAL;
57 : :
58 [ # # ]: 0 : list_for_each_entry(ha, &list->list, list) {
59 [ # # ][ # # ]: 0 : if (!memcmp(ha->addr, addr, addr_len) &&
60 : 0 : ha->type == addr_type) {
61 [ # # ]: 0 : if (global) {
62 : : /* check if addr is already used as global */
63 [ # # ]: 0 : if (ha->global_use)
64 : : return 0;
65 : : else
66 : 0 : ha->global_use = true;
67 : : }
68 [ # # ]: 0 : if (sync) {
69 [ # # ]: 0 : if (ha->synced)
70 : : return -EEXIST;
71 : : else
72 : 0 : ha->synced = true;
73 : : }
74 : 0 : ha->refcount++;
75 : 0 : return 0;
76 : : }
77 : : }
78 : :
79 : 0 : return __hw_addr_create_ex(list, addr, addr_len, addr_type, global,
80 : : sync);
81 : : }
82 : :
83 : : static int __hw_addr_add(struct netdev_hw_addr_list *list,
84 : : const unsigned char *addr, int addr_len,
85 : : unsigned char addr_type)
86 : : {
87 : 0 : return __hw_addr_add_ex(list, addr, addr_len, addr_type, false, false);
88 : : }
89 : :
90 : 0 : static int __hw_addr_del_entry(struct netdev_hw_addr_list *list,
91 : : struct netdev_hw_addr *ha, bool global,
92 : : bool sync)
93 : : {
94 [ # # ][ # # ]: 0 : if (global && !ha->global_use)
95 : : return -ENOENT;
96 : :
97 [ # # ][ # # ]: 0 : if (sync && !ha->synced)
98 : : return -ENOENT;
99 : :
100 [ # # ]: 0 : if (global)
101 : 0 : ha->global_use = false;
102 : :
103 [ # # ]: 0 : if (sync)
104 : 0 : ha->synced = false;
105 : :
106 [ # # ]: 0 : if (--ha->refcount)
107 : : return 0;
108 : : list_del_rcu(&ha->list);
109 : 0 : kfree_rcu(ha, rcu_head);
110 : 0 : list->count--;
111 : : return 0;
112 : : }
113 : :
114 : 0 : static int __hw_addr_del_ex(struct netdev_hw_addr_list *list,
115 : : const unsigned char *addr, int addr_len,
116 : : unsigned char addr_type, bool global, bool sync)
117 : : {
118 : : struct netdev_hw_addr *ha;
119 : :
120 [ # # ]: 0 : list_for_each_entry(ha, &list->list, list) {
121 [ # # ][ # # ]: 0 : if (!memcmp(ha->addr, addr, addr_len) &&
122 [ # # ]: 0 : (ha->type == addr_type || !addr_type))
123 : 0 : return __hw_addr_del_entry(list, ha, global, sync);
124 : : }
125 : : return -ENOENT;
126 : : }
127 : :
128 : : static int __hw_addr_del(struct netdev_hw_addr_list *list,
129 : : const unsigned char *addr, int addr_len,
130 : : unsigned char addr_type)
131 : : {
132 : 0 : return __hw_addr_del_ex(list, addr, addr_len, addr_type, false, false);
133 : : }
134 : :
135 : 0 : static int __hw_addr_sync_one(struct netdev_hw_addr_list *to_list,
136 : : struct netdev_hw_addr *ha,
137 : : int addr_len)
138 : : {
139 : : int err;
140 : :
141 : 0 : err = __hw_addr_add_ex(to_list, ha->addr, addr_len, ha->type,
142 : : false, true);
143 [ # # ]: 0 : if (err && err != -EEXIST)
144 : : return err;
145 : :
146 [ # # ]: 0 : if (!err) {
147 : 0 : ha->sync_cnt++;
148 : 0 : ha->refcount++;
149 : : }
150 : :
151 : : return 0;
152 : : }
153 : :
154 : 0 : static void __hw_addr_unsync_one(struct netdev_hw_addr_list *to_list,
155 : : struct netdev_hw_addr_list *from_list,
156 : : struct netdev_hw_addr *ha,
157 : : int addr_len)
158 : : {
159 : : int err;
160 : :
161 : 0 : err = __hw_addr_del_ex(to_list, ha->addr, addr_len, ha->type,
162 : : false, true);
163 [ # # ]: 0 : if (err)
164 : 0 : return;
165 : 0 : ha->sync_cnt--;
166 : : /* address on from list is not marked synced */
167 : 0 : __hw_addr_del_entry(from_list, ha, false, false);
168 : : }
169 : :
170 : 0 : static int __hw_addr_sync_multiple(struct netdev_hw_addr_list *to_list,
171 : : struct netdev_hw_addr_list *from_list,
172 : : int addr_len)
173 : : {
174 : : int err = 0;
175 : : struct netdev_hw_addr *ha, *tmp;
176 : :
177 [ # # ]: 0 : list_for_each_entry_safe(ha, tmp, &from_list->list, list) {
178 [ # # ]: 0 : if (ha->sync_cnt == ha->refcount) {
179 : 0 : __hw_addr_unsync_one(to_list, from_list, ha, addr_len);
180 : : } else {
181 : 0 : err = __hw_addr_sync_one(to_list, ha, addr_len);
182 [ # # ]: 0 : if (err)
183 : : break;
184 : : }
185 : : }
186 : 0 : return err;
187 : : }
188 : :
189 : 0 : int __hw_addr_add_multiple(struct netdev_hw_addr_list *to_list,
190 : : struct netdev_hw_addr_list *from_list,
191 : : int addr_len, unsigned char addr_type)
192 : : {
193 : : int err;
194 : : struct netdev_hw_addr *ha, *ha2;
195 : : unsigned char type;
196 : :
197 [ # # ]: 0 : list_for_each_entry(ha, &from_list->list, list) {
198 [ # # ]: 0 : type = addr_type ? addr_type : ha->type;
199 : 0 : err = __hw_addr_add(to_list, ha->addr, addr_len, type);
200 [ # # ]: 0 : if (err)
201 : : goto unroll;
202 : : }
203 : : return 0;
204 : :
205 : : unroll:
206 [ # # ]: 0 : list_for_each_entry(ha2, &from_list->list, list) {
207 [ # # ]: 0 : if (ha2 == ha)
208 : : break;
209 [ # # ]: 0 : type = addr_type ? addr_type : ha2->type;
210 : 0 : __hw_addr_del(to_list, ha2->addr, addr_len, type);
211 : : }
212 : : return err;
213 : : }
214 : : EXPORT_SYMBOL(__hw_addr_add_multiple);
215 : :
216 : 0 : void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list,
217 : : struct netdev_hw_addr_list *from_list,
218 : : int addr_len, unsigned char addr_type)
219 : : {
220 : : struct netdev_hw_addr *ha;
221 : : unsigned char type;
222 : :
223 [ # # ]: 0 : list_for_each_entry(ha, &from_list->list, list) {
224 [ # # ]: 0 : type = addr_type ? addr_type : ha->type;
225 : 0 : __hw_addr_del(to_list, ha->addr, addr_len, type);
226 : : }
227 : 0 : }
228 : : EXPORT_SYMBOL(__hw_addr_del_multiple);
229 : :
230 : : /* This function only works where there is a strict 1-1 relationship
231 : : * between source and destionation of they synch. If you ever need to
232 : : * sync addresses to more then 1 destination, you need to use
233 : : * __hw_addr_sync_multiple().
234 : : */
235 : 0 : int __hw_addr_sync(struct netdev_hw_addr_list *to_list,
236 : : struct netdev_hw_addr_list *from_list,
237 : : int addr_len)
238 : : {
239 : : int err = 0;
240 : : struct netdev_hw_addr *ha, *tmp;
241 : :
242 [ # # ]: 0 : list_for_each_entry_safe(ha, tmp, &from_list->list, list) {
243 [ # # ]: 0 : if (!ha->sync_cnt) {
244 : 0 : err = __hw_addr_sync_one(to_list, ha, addr_len);
245 [ # # ]: 0 : if (err)
246 : : break;
247 [ # # ]: 0 : } else if (ha->refcount == 1)
248 : 0 : __hw_addr_unsync_one(to_list, from_list, ha, addr_len);
249 : : }
250 : 0 : return err;
251 : : }
252 : : EXPORT_SYMBOL(__hw_addr_sync);
253 : :
254 : 0 : void __hw_addr_unsync(struct netdev_hw_addr_list *to_list,
255 : : struct netdev_hw_addr_list *from_list,
256 : : int addr_len)
257 : : {
258 : : struct netdev_hw_addr *ha, *tmp;
259 : :
260 [ # # ]: 0 : list_for_each_entry_safe(ha, tmp, &from_list->list, list) {
261 [ # # ]: 0 : if (ha->sync_cnt)
262 : 0 : __hw_addr_unsync_one(to_list, from_list, ha, addr_len);
263 : : }
264 : 0 : }
265 : : EXPORT_SYMBOL(__hw_addr_unsync);
266 : :
267 : 0 : void __hw_addr_flush(struct netdev_hw_addr_list *list)
268 : : {
269 : : struct netdev_hw_addr *ha, *tmp;
270 : :
271 [ # # ]: 0 : list_for_each_entry_safe(ha, tmp, &list->list, list) {
272 : : list_del_rcu(&ha->list);
273 : 0 : kfree_rcu(ha, rcu_head);
274 : : }
275 : 0 : list->count = 0;
276 : 0 : }
277 : : EXPORT_SYMBOL(__hw_addr_flush);
278 : :
279 : 0 : void __hw_addr_init(struct netdev_hw_addr_list *list)
280 : : {
281 : 0 : INIT_LIST_HEAD(&list->list);
282 : 0 : list->count = 0;
283 : 0 : }
284 : : EXPORT_SYMBOL(__hw_addr_init);
285 : :
286 : : /*
287 : : * Device addresses handling functions
288 : : */
289 : :
290 : : /**
291 : : * dev_addr_flush - Flush device address list
292 : : * @dev: device
293 : : *
294 : : * Flush device address list and reset ->dev_addr.
295 : : *
296 : : * The caller must hold the rtnl_mutex.
297 : : */
298 : 0 : void dev_addr_flush(struct net_device *dev)
299 : : {
300 : : /* rtnl_mutex must be held here */
301 : :
302 : 0 : __hw_addr_flush(&dev->dev_addrs);
303 : 0 : dev->dev_addr = NULL;
304 : 0 : }
305 : : EXPORT_SYMBOL(dev_addr_flush);
306 : :
307 : : /**
308 : : * dev_addr_init - Init device address list
309 : : * @dev: device
310 : : *
311 : : * Init device address list and create the first element,
312 : : * used by ->dev_addr.
313 : : *
314 : : * The caller must hold the rtnl_mutex.
315 : : */
316 : 0 : int dev_addr_init(struct net_device *dev)
317 : : {
318 : : unsigned char addr[MAX_ADDR_LEN];
319 : : struct netdev_hw_addr *ha;
320 : : int err;
321 : :
322 : : /* rtnl_mutex must be held here */
323 : :
324 : : __hw_addr_init(&dev->dev_addrs);
325 : 0 : memset(addr, 0, sizeof(addr));
326 : 0 : err = __hw_addr_add(&dev->dev_addrs, addr, sizeof(addr),
327 : : NETDEV_HW_ADDR_T_LAN);
328 [ # # ]: 0 : if (!err) {
329 : : /*
330 : : * Get the first (previously created) address from the list
331 : : * and set dev_addr pointer to this location.
332 : : */
333 : 0 : ha = list_first_entry(&dev->dev_addrs.list,
334 : : struct netdev_hw_addr, list);
335 : 0 : dev->dev_addr = ha->addr;
336 : : }
337 : 0 : return err;
338 : : }
339 : : EXPORT_SYMBOL(dev_addr_init);
340 : :
341 : : /**
342 : : * dev_addr_add - Add a device address
343 : : * @dev: device
344 : : * @addr: address to add
345 : : * @addr_type: address type
346 : : *
347 : : * Add a device address to the device or increase the reference count if
348 : : * it already exists.
349 : : *
350 : : * The caller must hold the rtnl_mutex.
351 : : */
352 : 0 : int dev_addr_add(struct net_device *dev, const unsigned char *addr,
353 : : unsigned char addr_type)
354 : : {
355 : : int err;
356 : :
357 [ # # ]: 0 : ASSERT_RTNL();
358 : :
359 : 0 : err = __hw_addr_add(&dev->dev_addrs, addr, dev->addr_len, addr_type);
360 [ # # ]: 0 : if (!err)
361 : 0 : call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
362 : 0 : return err;
363 : : }
364 : : EXPORT_SYMBOL(dev_addr_add);
365 : :
366 : : /**
367 : : * dev_addr_del - Release a device address.
368 : : * @dev: device
369 : : * @addr: address to delete
370 : : * @addr_type: address type
371 : : *
372 : : * Release reference to a device address and remove it from the device
373 : : * if the reference count drops to zero.
374 : : *
375 : : * The caller must hold the rtnl_mutex.
376 : : */
377 : 0 : int dev_addr_del(struct net_device *dev, const unsigned char *addr,
378 : : unsigned char addr_type)
379 : : {
380 : : int err;
381 : : struct netdev_hw_addr *ha;
382 : :
383 [ # # ]: 0 : ASSERT_RTNL();
384 : :
385 : : /*
386 : : * We can not remove the first address from the list because
387 : : * dev->dev_addr points to that.
388 : : */
389 : 0 : ha = list_first_entry(&dev->dev_addrs.list,
390 : : struct netdev_hw_addr, list);
391 [ # # ][ # # ]: 0 : if (!memcmp(ha->addr, addr, dev->addr_len) &&
392 [ # # ]: 0 : ha->type == addr_type && ha->refcount == 1)
393 : : return -ENOENT;
394 : :
395 : 0 : err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len,
396 : : addr_type);
397 [ # # ]: 0 : if (!err)
398 : 0 : call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
399 : 0 : return err;
400 : : }
401 : : EXPORT_SYMBOL(dev_addr_del);
402 : :
403 : : /**
404 : : * dev_addr_add_multiple - Add device addresses from another device
405 : : * @to_dev: device to which addresses will be added
406 : : * @from_dev: device from which addresses will be added
407 : : * @addr_type: address type - 0 means type will be used from from_dev
408 : : *
409 : : * Add device addresses of the one device to another.
410 : : **
411 : : * The caller must hold the rtnl_mutex.
412 : : */
413 : 0 : int dev_addr_add_multiple(struct net_device *to_dev,
414 : : struct net_device *from_dev,
415 : : unsigned char addr_type)
416 : : {
417 : : int err;
418 : :
419 [ # # ]: 0 : ASSERT_RTNL();
420 : :
421 [ # # ]: 0 : if (from_dev->addr_len != to_dev->addr_len)
422 : : return -EINVAL;
423 : 0 : err = __hw_addr_add_multiple(&to_dev->dev_addrs, &from_dev->dev_addrs,
424 : : to_dev->addr_len, addr_type);
425 [ # # ]: 0 : if (!err)
426 : 0 : call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev);
427 : 0 : return err;
428 : : }
429 : : EXPORT_SYMBOL(dev_addr_add_multiple);
430 : :
431 : : /**
432 : : * dev_addr_del_multiple - Delete device addresses by another device
433 : : * @to_dev: device where the addresses will be deleted
434 : : * @from_dev: device supplying the addresses to be deleted
435 : : * @addr_type: address type - 0 means type will be used from from_dev
436 : : *
437 : : * Deletes addresses in to device by the list of addresses in from device.
438 : : *
439 : : * The caller must hold the rtnl_mutex.
440 : : */
441 : 0 : int dev_addr_del_multiple(struct net_device *to_dev,
442 : : struct net_device *from_dev,
443 : : unsigned char addr_type)
444 : : {
445 [ # # ]: 0 : ASSERT_RTNL();
446 : :
447 [ # # ]: 0 : if (from_dev->addr_len != to_dev->addr_len)
448 : : return -EINVAL;
449 : 0 : __hw_addr_del_multiple(&to_dev->dev_addrs, &from_dev->dev_addrs,
450 : : to_dev->addr_len, addr_type);
451 : 0 : call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev);
452 : 0 : return 0;
453 : : }
454 : : EXPORT_SYMBOL(dev_addr_del_multiple);
455 : :
456 : : /*
457 : : * Unicast list handling functions
458 : : */
459 : :
460 : : /**
461 : : * dev_uc_add_excl - Add a global secondary unicast address
462 : : * @dev: device
463 : : * @addr: address to add
464 : : */
465 : 0 : int dev_uc_add_excl(struct net_device *dev, const unsigned char *addr)
466 : : {
467 : : struct netdev_hw_addr *ha;
468 : : int err;
469 : :
470 : : netif_addr_lock_bh(dev);
471 [ # # ]: 0 : list_for_each_entry(ha, &dev->uc.list, list) {
472 [ # # ][ # # ]: 0 : if (!memcmp(ha->addr, addr, dev->addr_len) &&
473 : 0 : ha->type == NETDEV_HW_ADDR_T_UNICAST) {
474 : : err = -EEXIST;
475 : : goto out;
476 : : }
477 : : }
478 : 0 : err = __hw_addr_create_ex(&dev->uc, addr, dev->addr_len,
479 : : NETDEV_HW_ADDR_T_UNICAST, true, false);
480 [ # # ]: 0 : if (!err)
481 : 0 : __dev_set_rx_mode(dev);
482 : : out:
483 : : netif_addr_unlock_bh(dev);
484 : 0 : return err;
485 : : }
486 : : EXPORT_SYMBOL(dev_uc_add_excl);
487 : :
488 : : /**
489 : : * dev_uc_add - Add a secondary unicast address
490 : : * @dev: device
491 : : * @addr: address to add
492 : : *
493 : : * Add a secondary unicast address to the device or increase
494 : : * the reference count if it already exists.
495 : : */
496 : 0 : int dev_uc_add(struct net_device *dev, const unsigned char *addr)
497 : : {
498 : : int err;
499 : :
500 : : netif_addr_lock_bh(dev);
501 : 0 : err = __hw_addr_add(&dev->uc, addr, dev->addr_len,
502 : : NETDEV_HW_ADDR_T_UNICAST);
503 [ # # ]: 0 : if (!err)
504 : 0 : __dev_set_rx_mode(dev);
505 : : netif_addr_unlock_bh(dev);
506 : 0 : return err;
507 : : }
508 : : EXPORT_SYMBOL(dev_uc_add);
509 : :
510 : : /**
511 : : * dev_uc_del - Release secondary unicast address.
512 : : * @dev: device
513 : : * @addr: address to delete
514 : : *
515 : : * Release reference to a secondary unicast address and remove it
516 : : * from the device if the reference count drops to zero.
517 : : */
518 : 0 : int dev_uc_del(struct net_device *dev, const unsigned char *addr)
519 : : {
520 : : int err;
521 : :
522 : : netif_addr_lock_bh(dev);
523 : 0 : err = __hw_addr_del(&dev->uc, addr, dev->addr_len,
524 : : NETDEV_HW_ADDR_T_UNICAST);
525 [ # # ]: 0 : if (!err)
526 : 0 : __dev_set_rx_mode(dev);
527 : : netif_addr_unlock_bh(dev);
528 : 0 : return err;
529 : : }
530 : : EXPORT_SYMBOL(dev_uc_del);
531 : :
532 : : /**
533 : : * dev_uc_sync - Synchronize device's unicast list to another device
534 : : * @to: destination device
535 : : * @from: source device
536 : : *
537 : : * Add newly added addresses to the destination device and release
538 : : * addresses that have no users left. The source device must be
539 : : * locked by netif_addr_lock_bh.
540 : : *
541 : : * This function is intended to be called from the dev->set_rx_mode
542 : : * function of layered software devices. This function assumes that
543 : : * addresses will only ever be synced to the @to devices and no other.
544 : : */
545 : 0 : int dev_uc_sync(struct net_device *to, struct net_device *from)
546 : : {
547 : : int err = 0;
548 : :
549 [ # # ]: 0 : if (to->addr_len != from->addr_len)
550 : : return -EINVAL;
551 : :
552 : : netif_addr_lock_nested(to);
553 : 0 : err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len);
554 [ # # ]: 0 : if (!err)
555 : 0 : __dev_set_rx_mode(to);
556 : : netif_addr_unlock(to);
557 : 0 : return err;
558 : : }
559 : : EXPORT_SYMBOL(dev_uc_sync);
560 : :
561 : : /**
562 : : * dev_uc_sync_multiple - Synchronize device's unicast list to another
563 : : * device, but allow for multiple calls to sync to multiple devices.
564 : : * @to: destination device
565 : : * @from: source device
566 : : *
567 : : * Add newly added addresses to the destination device and release
568 : : * addresses that have been deleted from the source. The source device
569 : : * must be locked by netif_addr_lock_bh.
570 : : *
571 : : * This function is intended to be called from the dev->set_rx_mode
572 : : * function of layered software devices. It allows for a single source
573 : : * device to be synced to multiple destination devices.
574 : : */
575 : 0 : int dev_uc_sync_multiple(struct net_device *to, struct net_device *from)
576 : : {
577 : : int err = 0;
578 : :
579 [ # # ]: 0 : if (to->addr_len != from->addr_len)
580 : : return -EINVAL;
581 : :
582 : : netif_addr_lock_nested(to);
583 : 0 : err = __hw_addr_sync_multiple(&to->uc, &from->uc, to->addr_len);
584 [ # # ]: 0 : if (!err)
585 : 0 : __dev_set_rx_mode(to);
586 : : netif_addr_unlock(to);
587 : 0 : return err;
588 : : }
589 : : EXPORT_SYMBOL(dev_uc_sync_multiple);
590 : :
591 : : /**
592 : : * dev_uc_unsync - Remove synchronized addresses from the destination device
593 : : * @to: destination device
594 : : * @from: source device
595 : : *
596 : : * Remove all addresses that were added to the destination device by
597 : : * dev_uc_sync(). This function is intended to be called from the
598 : : * dev->stop function of layered software devices.
599 : : */
600 : 0 : void dev_uc_unsync(struct net_device *to, struct net_device *from)
601 : : {
602 [ # # ]: 0 : if (to->addr_len != from->addr_len)
603 : 0 : return;
604 : :
605 : : netif_addr_lock_bh(from);
606 : : netif_addr_lock_nested(to);
607 : 0 : __hw_addr_unsync(&to->uc, &from->uc, to->addr_len);
608 : 0 : __dev_set_rx_mode(to);
609 : : netif_addr_unlock(to);
610 : : netif_addr_unlock_bh(from);
611 : : }
612 : : EXPORT_SYMBOL(dev_uc_unsync);
613 : :
614 : : /**
615 : : * dev_uc_flush - Flush unicast addresses
616 : : * @dev: device
617 : : *
618 : : * Flush unicast addresses.
619 : : */
620 : 0 : void dev_uc_flush(struct net_device *dev)
621 : : {
622 : : netif_addr_lock_bh(dev);
623 : 0 : __hw_addr_flush(&dev->uc);
624 : : netif_addr_unlock_bh(dev);
625 : 0 : }
626 : : EXPORT_SYMBOL(dev_uc_flush);
627 : :
628 : : /**
629 : : * dev_uc_flush - Init unicast address list
630 : : * @dev: device
631 : : *
632 : : * Init unicast address list.
633 : : */
634 : 0 : void dev_uc_init(struct net_device *dev)
635 : : {
636 : : __hw_addr_init(&dev->uc);
637 : 0 : }
638 : : EXPORT_SYMBOL(dev_uc_init);
639 : :
640 : : /*
641 : : * Multicast list handling functions
642 : : */
643 : :
644 : : /**
645 : : * dev_mc_add_excl - Add a global secondary multicast address
646 : : * @dev: device
647 : : * @addr: address to add
648 : : */
649 : 0 : int dev_mc_add_excl(struct net_device *dev, const unsigned char *addr)
650 : : {
651 : : struct netdev_hw_addr *ha;
652 : : int err;
653 : :
654 : : netif_addr_lock_bh(dev);
655 [ # # ]: 0 : list_for_each_entry(ha, &dev->mc.list, list) {
656 [ # # ][ # # ]: 0 : if (!memcmp(ha->addr, addr, dev->addr_len) &&
657 : 0 : ha->type == NETDEV_HW_ADDR_T_MULTICAST) {
658 : : err = -EEXIST;
659 : : goto out;
660 : : }
661 : : }
662 : 0 : err = __hw_addr_create_ex(&dev->mc, addr, dev->addr_len,
663 : : NETDEV_HW_ADDR_T_MULTICAST, true, false);
664 [ # # ]: 0 : if (!err)
665 : 0 : __dev_set_rx_mode(dev);
666 : : out:
667 : : netif_addr_unlock_bh(dev);
668 : 0 : return err;
669 : : }
670 : : EXPORT_SYMBOL(dev_mc_add_excl);
671 : :
672 : 0 : static int __dev_mc_add(struct net_device *dev, const unsigned char *addr,
673 : : bool global)
674 : : {
675 : : int err;
676 : :
677 : : netif_addr_lock_bh(dev);
678 : 0 : err = __hw_addr_add_ex(&dev->mc, addr, dev->addr_len,
679 : : NETDEV_HW_ADDR_T_MULTICAST, global, false);
680 [ # # ]: 0 : if (!err)
681 : 0 : __dev_set_rx_mode(dev);
682 : : netif_addr_unlock_bh(dev);
683 : 0 : return err;
684 : : }
685 : : /**
686 : : * dev_mc_add - Add a multicast address
687 : : * @dev: device
688 : : * @addr: address to add
689 : : *
690 : : * Add a multicast address to the device or increase
691 : : * the reference count if it already exists.
692 : : */
693 : 0 : int dev_mc_add(struct net_device *dev, const unsigned char *addr)
694 : : {
695 : 0 : return __dev_mc_add(dev, addr, false);
696 : : }
697 : : EXPORT_SYMBOL(dev_mc_add);
698 : :
699 : : /**
700 : : * dev_mc_add_global - Add a global multicast address
701 : : * @dev: device
702 : : * @addr: address to add
703 : : *
704 : : * Add a global multicast address to the device.
705 : : */
706 : 0 : int dev_mc_add_global(struct net_device *dev, const unsigned char *addr)
707 : : {
708 : 0 : return __dev_mc_add(dev, addr, true);
709 : : }
710 : : EXPORT_SYMBOL(dev_mc_add_global);
711 : :
712 : 0 : static int __dev_mc_del(struct net_device *dev, const unsigned char *addr,
713 : : bool global)
714 : : {
715 : : int err;
716 : :
717 : : netif_addr_lock_bh(dev);
718 : 0 : err = __hw_addr_del_ex(&dev->mc, addr, dev->addr_len,
719 : : NETDEV_HW_ADDR_T_MULTICAST, global, false);
720 [ # # ]: 0 : if (!err)
721 : 0 : __dev_set_rx_mode(dev);
722 : : netif_addr_unlock_bh(dev);
723 : 0 : return err;
724 : : }
725 : :
726 : : /**
727 : : * dev_mc_del - Delete a multicast address.
728 : : * @dev: device
729 : : * @addr: address to delete
730 : : *
731 : : * Release reference to a multicast address and remove it
732 : : * from the device if the reference count drops to zero.
733 : : */
734 : 0 : int dev_mc_del(struct net_device *dev, const unsigned char *addr)
735 : : {
736 : 0 : return __dev_mc_del(dev, addr, false);
737 : : }
738 : : EXPORT_SYMBOL(dev_mc_del);
739 : :
740 : : /**
741 : : * dev_mc_del_global - Delete a global multicast address.
742 : : * @dev: device
743 : : * @addr: address to delete
744 : : *
745 : : * Release reference to a multicast address and remove it
746 : : * from the device if the reference count drops to zero.
747 : : */
748 : 0 : int dev_mc_del_global(struct net_device *dev, const unsigned char *addr)
749 : : {
750 : 0 : return __dev_mc_del(dev, addr, true);
751 : : }
752 : : EXPORT_SYMBOL(dev_mc_del_global);
753 : :
754 : : /**
755 : : * dev_mc_sync - Synchronize device's multicast list to another device
756 : : * @to: destination device
757 : : * @from: source device
758 : : *
759 : : * Add newly added addresses to the destination device and release
760 : : * addresses that have no users left. The source device must be
761 : : * locked by netif_addr_lock_bh.
762 : : *
763 : : * This function is intended to be called from the ndo_set_rx_mode
764 : : * function of layered software devices.
765 : : */
766 : 0 : int dev_mc_sync(struct net_device *to, struct net_device *from)
767 : : {
768 : : int err = 0;
769 : :
770 [ # # ]: 0 : if (to->addr_len != from->addr_len)
771 : : return -EINVAL;
772 : :
773 : : netif_addr_lock_nested(to);
774 : 0 : err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len);
775 [ # # ]: 0 : if (!err)
776 : 0 : __dev_set_rx_mode(to);
777 : : netif_addr_unlock(to);
778 : 0 : return err;
779 : : }
780 : : EXPORT_SYMBOL(dev_mc_sync);
781 : :
782 : : /**
783 : : * dev_mc_sync_multiple - Synchronize device's multicast list to another
784 : : * device, but allow for multiple calls to sync to multiple devices.
785 : : * @to: destination device
786 : : * @from: source device
787 : : *
788 : : * Add newly added addresses to the destination device and release
789 : : * addresses that have no users left. The source device must be
790 : : * locked by netif_addr_lock_bh.
791 : : *
792 : : * This function is intended to be called from the ndo_set_rx_mode
793 : : * function of layered software devices. It allows for a single
794 : : * source device to be synced to multiple destination devices.
795 : : */
796 : 0 : int dev_mc_sync_multiple(struct net_device *to, struct net_device *from)
797 : : {
798 : : int err = 0;
799 : :
800 [ # # ]: 0 : if (to->addr_len != from->addr_len)
801 : : return -EINVAL;
802 : :
803 : : netif_addr_lock_nested(to);
804 : 0 : err = __hw_addr_sync_multiple(&to->mc, &from->mc, to->addr_len);
805 [ # # ]: 0 : if (!err)
806 : 0 : __dev_set_rx_mode(to);
807 : : netif_addr_unlock(to);
808 : 0 : return err;
809 : : }
810 : : EXPORT_SYMBOL(dev_mc_sync_multiple);
811 : :
812 : : /**
813 : : * dev_mc_unsync - Remove synchronized addresses from the destination device
814 : : * @to: destination device
815 : : * @from: source device
816 : : *
817 : : * Remove all addresses that were added to the destination device by
818 : : * dev_mc_sync(). This function is intended to be called from the
819 : : * dev->stop function of layered software devices.
820 : : */
821 : 0 : void dev_mc_unsync(struct net_device *to, struct net_device *from)
822 : : {
823 [ # # ]: 0 : if (to->addr_len != from->addr_len)
824 : 0 : return;
825 : :
826 : : netif_addr_lock_bh(from);
827 : : netif_addr_lock_nested(to);
828 : 0 : __hw_addr_unsync(&to->mc, &from->mc, to->addr_len);
829 : 0 : __dev_set_rx_mode(to);
830 : : netif_addr_unlock(to);
831 : : netif_addr_unlock_bh(from);
832 : : }
833 : : EXPORT_SYMBOL(dev_mc_unsync);
834 : :
835 : : /**
836 : : * dev_mc_flush - Flush multicast addresses
837 : : * @dev: device
838 : : *
839 : : * Flush multicast addresses.
840 : : */
841 : 0 : void dev_mc_flush(struct net_device *dev)
842 : : {
843 : : netif_addr_lock_bh(dev);
844 : 0 : __hw_addr_flush(&dev->mc);
845 : : netif_addr_unlock_bh(dev);
846 : 0 : }
847 : : EXPORT_SYMBOL(dev_mc_flush);
848 : :
849 : : /**
850 : : * dev_mc_flush - Init multicast address list
851 : : * @dev: device
852 : : *
853 : : * Init multicast address list.
854 : : */
855 : 0 : void dev_mc_init(struct net_device *dev)
856 : : {
857 : : __hw_addr_init(&dev->mc);
858 : 0 : }
859 : : EXPORT_SYMBOL(dev_mc_init);
|