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