aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJiri Pirko <jpirko@redhat.com>2009-06-16 21:12:19 -0400
committerDavid S. Miller <davem@davemloft.net>2009-06-18 03:29:08 -0400
commit31278e71471399beaff9280737e52b47db4dc345 (patch)
tree25fe2ff8e48a75b7f569dccc463f3bd2561c6c66 /net
parent7b85576d15bf2574b0a451108f59f9ad4170dd3f (diff)
net: group address list and its count
This patch is inspired by patch recently posted by Johannes Berg. Basically what my patch does is to group list and a count of addresses into newly introduced structure netdev_hw_addr_list. This brings us two benefits: 1) struct net_device becames a bit nicer. 2) in the future there will be a possibility to operate with lists independently on netdevices (with exporting right functions). I wanted to introduce this patch before I'll post a multicast lists conversion. Signed-off-by: Jiri Pirko <jpirko@redhat.com> drivers/net/bnx2.c | 4 +- drivers/net/e1000/e1000_main.c | 4 +- drivers/net/ixgbe/ixgbe_main.c | 6 +- drivers/net/mv643xx_eth.c | 2 +- drivers/net/niu.c | 4 +- drivers/net/virtio_net.c | 10 ++-- drivers/s390/net/qeth_l2_main.c | 2 +- include/linux/netdevice.h | 17 +++-- net/core/dev.c | 130 ++++++++++++++++++-------------------- 9 files changed, 89 insertions(+), 90 deletions(-) Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/dev.c130
1 files changed, 62 insertions, 68 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 576a61574a93..baf2dc13a34a 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3461,10 +3461,10 @@ void __dev_set_rx_mode(struct net_device *dev)
3461 /* Unicast addresses changes may only happen under the rtnl, 3461 /* Unicast addresses changes may only happen under the rtnl,
3462 * therefore calling __dev_set_promiscuity here is safe. 3462 * therefore calling __dev_set_promiscuity here is safe.
3463 */ 3463 */
3464 if (dev->uc_count > 0 && !dev->uc_promisc) { 3464 if (dev->uc.count > 0 && !dev->uc_promisc) {
3465 __dev_set_promiscuity(dev, 1); 3465 __dev_set_promiscuity(dev, 1);
3466 dev->uc_promisc = 1; 3466 dev->uc_promisc = 1;
3467 } else if (dev->uc_count == 0 && dev->uc_promisc) { 3467 } else if (dev->uc.count == 0 && dev->uc_promisc) {
3468 __dev_set_promiscuity(dev, -1); 3468 __dev_set_promiscuity(dev, -1);
3469 dev->uc_promisc = 0; 3469 dev->uc_promisc = 0;
3470 } 3470 }
@@ -3483,9 +3483,8 @@ void dev_set_rx_mode(struct net_device *dev)
3483 3483
3484/* hw addresses list handling functions */ 3484/* hw addresses list handling functions */
3485 3485
3486static int __hw_addr_add(struct list_head *list, int *delta, 3486static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr,
3487 unsigned char *addr, int addr_len, 3487 int addr_len, unsigned char addr_type)
3488 unsigned char addr_type)
3489{ 3488{
3490 struct netdev_hw_addr *ha; 3489 struct netdev_hw_addr *ha;
3491 int alloc_size; 3490 int alloc_size;
@@ -3493,7 +3492,7 @@ static int __hw_addr_add(struct list_head *list, int *delta,
3493 if (addr_len > MAX_ADDR_LEN) 3492 if (addr_len > MAX_ADDR_LEN)
3494 return -EINVAL; 3493 return -EINVAL;
3495 3494
3496 list_for_each_entry(ha, list, list) { 3495 list_for_each_entry(ha, &list->list, list) {
3497 if (!memcmp(ha->addr, addr, addr_len) && 3496 if (!memcmp(ha->addr, addr, addr_len) &&
3498 ha->type == addr_type) { 3497 ha->type == addr_type) {
3499 ha->refcount++; 3498 ha->refcount++;
@@ -3512,9 +3511,8 @@ static int __hw_addr_add(struct list_head *list, int *delta,
3512 ha->type = addr_type; 3511 ha->type = addr_type;
3513 ha->refcount = 1; 3512 ha->refcount = 1;
3514 ha->synced = false; 3513 ha->synced = false;
3515 list_add_tail_rcu(&ha->list, list); 3514 list_add_tail_rcu(&ha->list, &list->list);
3516 if (delta) 3515 list->count++;
3517 (*delta)++;
3518 return 0; 3516 return 0;
3519} 3517}
3520 3518
@@ -3526,120 +3524,121 @@ static void ha_rcu_free(struct rcu_head *head)
3526 kfree(ha); 3524 kfree(ha);
3527} 3525}
3528 3526
3529static int __hw_addr_del(struct list_head *list, int *delta, 3527static int __hw_addr_del(struct netdev_hw_addr_list *list, unsigned char *addr,
3530 unsigned char *addr, int addr_len, 3528 int addr_len, unsigned char addr_type)
3531 unsigned char addr_type)
3532{ 3529{
3533 struct netdev_hw_addr *ha; 3530 struct netdev_hw_addr *ha;
3534 3531
3535 list_for_each_entry(ha, list, list) { 3532 list_for_each_entry(ha, &list->list, list) {
3536 if (!memcmp(ha->addr, addr, addr_len) && 3533 if (!memcmp(ha->addr, addr, addr_len) &&
3537 (ha->type == addr_type || !addr_type)) { 3534 (ha->type == addr_type || !addr_type)) {
3538 if (--ha->refcount) 3535 if (--ha->refcount)
3539 return 0; 3536 return 0;
3540 list_del_rcu(&ha->list); 3537 list_del_rcu(&ha->list);
3541 call_rcu(&ha->rcu_head, ha_rcu_free); 3538 call_rcu(&ha->rcu_head, ha_rcu_free);
3542 if (delta) 3539 list->count--;
3543 (*delta)--;
3544 return 0; 3540 return 0;
3545 } 3541 }
3546 } 3542 }
3547 return -ENOENT; 3543 return -ENOENT;
3548} 3544}
3549 3545
3550static int __hw_addr_add_multiple(struct list_head *to_list, int *to_delta, 3546static int __hw_addr_add_multiple(struct netdev_hw_addr_list *to_list,
3551 struct list_head *from_list, int addr_len, 3547 struct netdev_hw_addr_list *from_list,
3548 int addr_len,
3552 unsigned char addr_type) 3549 unsigned char addr_type)
3553{ 3550{
3554 int err; 3551 int err;
3555 struct netdev_hw_addr *ha, *ha2; 3552 struct netdev_hw_addr *ha, *ha2;
3556 unsigned char type; 3553 unsigned char type;
3557 3554
3558 list_for_each_entry(ha, from_list, list) { 3555 list_for_each_entry(ha, &from_list->list, list) {
3559 type = addr_type ? addr_type : ha->type; 3556 type = addr_type ? addr_type : ha->type;
3560 err = __hw_addr_add(to_list, to_delta, ha->addr, 3557 err = __hw_addr_add(to_list, ha->addr, addr_len, type);
3561 addr_len, type);
3562 if (err) 3558 if (err)
3563 goto unroll; 3559 goto unroll;
3564 } 3560 }
3565 return 0; 3561 return 0;
3566 3562
3567unroll: 3563unroll:
3568 list_for_each_entry(ha2, from_list, list) { 3564 list_for_each_entry(ha2, &from_list->list, list) {
3569 if (ha2 == ha) 3565 if (ha2 == ha)
3570 break; 3566 break;
3571 type = addr_type ? addr_type : ha2->type; 3567 type = addr_type ? addr_type : ha2->type;
3572 __hw_addr_del(to_list, to_delta, ha2->addr, 3568 __hw_addr_del(to_list, ha2->addr, addr_len, type);
3573 addr_len, type);
3574 } 3569 }
3575 return err; 3570 return err;
3576} 3571}
3577 3572
3578static void __hw_addr_del_multiple(struct list_head *to_list, int *to_delta, 3573static void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list,
3579 struct list_head *from_list, int addr_len, 3574 struct netdev_hw_addr_list *from_list,
3575 int addr_len,
3580 unsigned char addr_type) 3576 unsigned char addr_type)
3581{ 3577{
3582 struct netdev_hw_addr *ha; 3578 struct netdev_hw_addr *ha;
3583 unsigned char type; 3579 unsigned char type;
3584 3580
3585 list_for_each_entry(ha, from_list, list) { 3581 list_for_each_entry(ha, &from_list->list, list) {
3586 type = addr_type ? addr_type : ha->type; 3582 type = addr_type ? addr_type : ha->type;
3587 __hw_addr_del(to_list, to_delta, ha->addr, 3583 __hw_addr_del(to_list, ha->addr, addr_len, addr_type);
3588 addr_len, addr_type);
3589 } 3584 }
3590} 3585}
3591 3586
3592static int __hw_addr_sync(struct list_head *to_list, int *to_delta, 3587static int __hw_addr_sync(struct netdev_hw_addr_list *to_list,
3593 struct list_head *from_list, int *from_delta, 3588 struct netdev_hw_addr_list *from_list,
3594 int addr_len) 3589 int addr_len)
3595{ 3590{
3596 int err = 0; 3591 int err = 0;
3597 struct netdev_hw_addr *ha, *tmp; 3592 struct netdev_hw_addr *ha, *tmp;
3598 3593
3599 list_for_each_entry_safe(ha, tmp, from_list, list) { 3594 list_for_each_entry_safe(ha, tmp, &from_list->list, list) {
3600 if (!ha->synced) { 3595 if (!ha->synced) {
3601 err = __hw_addr_add(to_list, to_delta, ha->addr, 3596 err = __hw_addr_add(to_list, ha->addr,
3602 addr_len, ha->type); 3597 addr_len, ha->type);
3603 if (err) 3598 if (err)
3604 break; 3599 break;
3605 ha->synced = true; 3600 ha->synced = true;
3606 ha->refcount++; 3601 ha->refcount++;
3607 } else if (ha->refcount == 1) { 3602 } else if (ha->refcount == 1) {
3608 __hw_addr_del(to_list, to_delta, ha->addr, 3603 __hw_addr_del(to_list, ha->addr, addr_len, ha->type);
3609 addr_len, ha->type); 3604 __hw_addr_del(from_list, ha->addr, addr_len, ha->type);
3610 __hw_addr_del(from_list, from_delta, ha->addr,
3611 addr_len, ha->type);
3612 } 3605 }
3613 } 3606 }
3614 return err; 3607 return err;
3615} 3608}
3616 3609
3617static void __hw_addr_unsync(struct list_head *to_list, int *to_delta, 3610static void __hw_addr_unsync(struct netdev_hw_addr_list *to_list,
3618 struct list_head *from_list, int *from_delta, 3611 struct netdev_hw_addr_list *from_list,
3619 int addr_len) 3612 int addr_len)
3620{ 3613{
3621 struct netdev_hw_addr *ha, *tmp; 3614 struct netdev_hw_addr *ha, *tmp;
3622 3615
3623 list_for_each_entry_safe(ha, tmp, from_list, list) { 3616 list_for_each_entry_safe(ha, tmp, &from_list->list, list) {
3624 if (ha->synced) { 3617 if (ha->synced) {
3625 __hw_addr_del(to_list, to_delta, ha->addr, 3618 __hw_addr_del(to_list, ha->addr,
3626 addr_len, ha->type); 3619 addr_len, ha->type);
3627 ha->synced = false; 3620 ha->synced = false;
3628 __hw_addr_del(from_list, from_delta, ha->addr, 3621 __hw_addr_del(from_list, ha->addr,
3629 addr_len, ha->type); 3622 addr_len, ha->type);
3630 } 3623 }
3631 } 3624 }
3632} 3625}
3633 3626
3634 3627static void __hw_addr_flush(struct netdev_hw_addr_list *list)
3635static void __hw_addr_flush(struct list_head *list)
3636{ 3628{
3637 struct netdev_hw_addr *ha, *tmp; 3629 struct netdev_hw_addr *ha, *tmp;
3638 3630
3639 list_for_each_entry_safe(ha, tmp, list, list) { 3631 list_for_each_entry_safe(ha, tmp, &list->list, list) {
3640 list_del_rcu(&ha->list); 3632 list_del_rcu(&ha->list);
3641 call_rcu(&ha->rcu_head, ha_rcu_free); 3633 call_rcu(&ha->rcu_head, ha_rcu_free);
3642 } 3634 }
3635 list->count = 0;
3636}
3637
3638static void __hw_addr_init(struct netdev_hw_addr_list *list)
3639{
3640 INIT_LIST_HEAD(&list->list);
3641 list->count = 0;
3643} 3642}
3644 3643
3645/* Device addresses handling functions */ 3644/* Device addresses handling functions */
@@ -3648,7 +3647,7 @@ static void dev_addr_flush(struct net_device *dev)
3648{ 3647{
3649 /* rtnl_mutex must be held here */ 3648 /* rtnl_mutex must be held here */
3650 3649
3651 __hw_addr_flush(&dev->dev_addr_list); 3650 __hw_addr_flush(&dev->dev_addrs);
3652 dev->dev_addr = NULL; 3651 dev->dev_addr = NULL;
3653} 3652}
3654 3653
@@ -3660,16 +3659,16 @@ static int dev_addr_init(struct net_device *dev)
3660 3659
3661 /* rtnl_mutex must be held here */ 3660 /* rtnl_mutex must be held here */
3662 3661
3663 INIT_LIST_HEAD(&dev->dev_addr_list); 3662 __hw_addr_init(&dev->dev_addrs);
3664 memset(addr, 0, sizeof(addr)); 3663 memset(addr, 0, sizeof(addr));
3665 err = __hw_addr_add(&dev->dev_addr_list, NULL, addr, sizeof(addr), 3664 err = __hw_addr_add(&dev->dev_addrs, addr, sizeof(addr),
3666 NETDEV_HW_ADDR_T_LAN); 3665 NETDEV_HW_ADDR_T_LAN);
3667 if (!err) { 3666 if (!err) {
3668 /* 3667 /*
3669 * Get the first (previously created) address from the list 3668 * Get the first (previously created) address from the list
3670 * and set dev_addr pointer to this location. 3669 * and set dev_addr pointer to this location.
3671 */ 3670 */
3672 ha = list_first_entry(&dev->dev_addr_list, 3671 ha = list_first_entry(&dev->dev_addrs.list,
3673 struct netdev_hw_addr, list); 3672 struct netdev_hw_addr, list);
3674 dev->dev_addr = ha->addr; 3673 dev->dev_addr = ha->addr;
3675 } 3674 }
@@ -3694,8 +3693,7 @@ int dev_addr_add(struct net_device *dev, unsigned char *addr,
3694 3693
3695 ASSERT_RTNL(); 3694 ASSERT_RTNL();
3696 3695
3697 err = __hw_addr_add(&dev->dev_addr_list, NULL, addr, dev->addr_len, 3696 err = __hw_addr_add(&dev->dev_addrs, addr, dev->addr_len, addr_type);
3698 addr_type);
3699 if (!err) 3697 if (!err)
3700 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); 3698 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
3701 return err; 3699 return err;
@@ -3725,11 +3723,12 @@ int dev_addr_del(struct net_device *dev, unsigned char *addr,
3725 * We can not remove the first address from the list because 3723 * We can not remove the first address from the list because
3726 * dev->dev_addr points to that. 3724 * dev->dev_addr points to that.
3727 */ 3725 */
3728 ha = list_first_entry(&dev->dev_addr_list, struct netdev_hw_addr, list); 3726 ha = list_first_entry(&dev->dev_addrs.list,
3727 struct netdev_hw_addr, list);
3729 if (ha->addr == dev->dev_addr && ha->refcount == 1) 3728 if (ha->addr == dev->dev_addr && ha->refcount == 1)
3730 return -ENOENT; 3729 return -ENOENT;
3731 3730
3732 err = __hw_addr_del(&dev->dev_addr_list, NULL, addr, dev->addr_len, 3731 err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len,
3733 addr_type); 3732 addr_type);
3734 if (!err) 3733 if (!err)
3735 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); 3734 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
@@ -3757,8 +3756,7 @@ int dev_addr_add_multiple(struct net_device *to_dev,
3757 3756
3758 if (from_dev->addr_len != to_dev->addr_len) 3757 if (from_dev->addr_len != to_dev->addr_len)
3759 return -EINVAL; 3758 return -EINVAL;
3760 err = __hw_addr_add_multiple(&to_dev->dev_addr_list, NULL, 3759 err = __hw_addr_add_multiple(&to_dev->dev_addrs, &from_dev->dev_addrs,
3761 &from_dev->dev_addr_list,
3762 to_dev->addr_len, addr_type); 3760 to_dev->addr_len, addr_type);
3763 if (!err) 3761 if (!err)
3764 call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); 3762 call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev);
@@ -3784,15 +3782,14 @@ int dev_addr_del_multiple(struct net_device *to_dev,
3784 3782
3785 if (from_dev->addr_len != to_dev->addr_len) 3783 if (from_dev->addr_len != to_dev->addr_len)
3786 return -EINVAL; 3784 return -EINVAL;
3787 __hw_addr_del_multiple(&to_dev->dev_addr_list, NULL, 3785 __hw_addr_del_multiple(&to_dev->dev_addrs, &from_dev->dev_addrs,
3788 &from_dev->dev_addr_list,
3789 to_dev->addr_len, addr_type); 3786 to_dev->addr_len, addr_type);
3790 call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); 3787 call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev);
3791 return 0; 3788 return 0;
3792} 3789}
3793EXPORT_SYMBOL(dev_addr_del_multiple); 3790EXPORT_SYMBOL(dev_addr_del_multiple);
3794 3791
3795/* unicast and multicast addresses handling functions */ 3792/* multicast addresses handling functions */
3796 3793
3797int __dev_addr_delete(struct dev_addr_list **list, int *count, 3794int __dev_addr_delete(struct dev_addr_list **list, int *count,
3798 void *addr, int alen, int glbl) 3795 void *addr, int alen, int glbl)
@@ -3868,8 +3865,8 @@ int dev_unicast_delete(struct net_device *dev, void *addr)
3868 3865
3869 ASSERT_RTNL(); 3866 ASSERT_RTNL();
3870 3867
3871 err = __hw_addr_del(&dev->uc_list, &dev->uc_count, addr, 3868 err = __hw_addr_del(&dev->uc, addr, dev->addr_len,
3872 dev->addr_len, NETDEV_HW_ADDR_T_UNICAST); 3869 NETDEV_HW_ADDR_T_UNICAST);
3873 if (!err) 3870 if (!err)
3874 __dev_set_rx_mode(dev); 3871 __dev_set_rx_mode(dev);
3875 return err; 3872 return err;
@@ -3892,8 +3889,8 @@ int dev_unicast_add(struct net_device *dev, void *addr)
3892 3889
3893 ASSERT_RTNL(); 3890 ASSERT_RTNL();
3894 3891
3895 err = __hw_addr_add(&dev->uc_list, &dev->uc_count, addr, 3892 err = __hw_addr_add(&dev->uc, addr, dev->addr_len,
3896 dev->addr_len, NETDEV_HW_ADDR_T_UNICAST); 3893 NETDEV_HW_ADDR_T_UNICAST);
3897 if (!err) 3894 if (!err)
3898 __dev_set_rx_mode(dev); 3895 __dev_set_rx_mode(dev);
3899 return err; 3896 return err;
@@ -3966,8 +3963,7 @@ int dev_unicast_sync(struct net_device *to, struct net_device *from)
3966 if (to->addr_len != from->addr_len) 3963 if (to->addr_len != from->addr_len)
3967 return -EINVAL; 3964 return -EINVAL;
3968 3965
3969 err = __hw_addr_sync(&to->uc_list, &to->uc_count, 3966 err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len);
3970 &from->uc_list, &from->uc_count, to->addr_len);
3971 if (!err) 3967 if (!err)
3972 __dev_set_rx_mode(to); 3968 __dev_set_rx_mode(to);
3973 return err; 3969 return err;
@@ -3990,8 +3986,7 @@ void dev_unicast_unsync(struct net_device *to, struct net_device *from)
3990 if (to->addr_len != from->addr_len) 3986 if (to->addr_len != from->addr_len)
3991 return; 3987 return;
3992 3988
3993 __hw_addr_unsync(&to->uc_list, &to->uc_count, 3989 __hw_addr_unsync(&to->uc, &from->uc, to->addr_len);
3994 &from->uc_list, &from->uc_count, to->addr_len);
3995 __dev_set_rx_mode(to); 3990 __dev_set_rx_mode(to);
3996} 3991}
3997EXPORT_SYMBOL(dev_unicast_unsync); 3992EXPORT_SYMBOL(dev_unicast_unsync);
@@ -4000,15 +3995,14 @@ static void dev_unicast_flush(struct net_device *dev)
4000{ 3995{
4001 /* rtnl_mutex must be held here */ 3996 /* rtnl_mutex must be held here */
4002 3997
4003 __hw_addr_flush(&dev->uc_list); 3998 __hw_addr_flush(&dev->uc);
4004 dev->uc_count = 0;
4005} 3999}
4006 4000
4007static void dev_unicast_init(struct net_device *dev) 4001static void dev_unicast_init(struct net_device *dev)
4008{ 4002{
4009 /* rtnl_mutex must be held here */ 4003 /* rtnl_mutex must be held here */
4010 4004
4011 INIT_LIST_HEAD(&dev->uc_list); 4005 __hw_addr_init(&dev->uc);
4012} 4006}
4013 4007
4014 4008