0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/netdevice.h>
0011 #include <linux/rtnetlink.h>
0012 #include <linux/export.h>
0013 #include <linux/list.h>
0014
0015 #include "dev.h"
0016
0017
0018
0019
0020
0021 static int __hw_addr_insert(struct netdev_hw_addr_list *list,
0022 struct netdev_hw_addr *new, int addr_len)
0023 {
0024 struct rb_node **ins_point = &list->tree.rb_node, *parent = NULL;
0025 struct netdev_hw_addr *ha;
0026
0027 while (*ins_point) {
0028 int diff;
0029
0030 ha = rb_entry(*ins_point, struct netdev_hw_addr, node);
0031 diff = memcmp(new->addr, ha->addr, addr_len);
0032 if (diff == 0)
0033 diff = memcmp(&new->type, &ha->type, sizeof(new->type));
0034
0035 parent = *ins_point;
0036 if (diff < 0)
0037 ins_point = &parent->rb_left;
0038 else if (diff > 0)
0039 ins_point = &parent->rb_right;
0040 else
0041 return -EEXIST;
0042 }
0043
0044 rb_link_node_rcu(&new->node, parent, ins_point);
0045 rb_insert_color(&new->node, &list->tree);
0046
0047 return 0;
0048 }
0049
0050 static struct netdev_hw_addr*
0051 __hw_addr_create(const unsigned char *addr, int addr_len,
0052 unsigned char addr_type, bool global, bool sync)
0053 {
0054 struct netdev_hw_addr *ha;
0055 int alloc_size;
0056
0057 alloc_size = sizeof(*ha);
0058 if (alloc_size < L1_CACHE_BYTES)
0059 alloc_size = L1_CACHE_BYTES;
0060 ha = kmalloc(alloc_size, GFP_ATOMIC);
0061 if (!ha)
0062 return NULL;
0063 memcpy(ha->addr, addr, addr_len);
0064 ha->type = addr_type;
0065 ha->refcount = 1;
0066 ha->global_use = global;
0067 ha->synced = sync ? 1 : 0;
0068 ha->sync_cnt = 0;
0069
0070 return ha;
0071 }
0072
0073 static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
0074 const unsigned char *addr, int addr_len,
0075 unsigned char addr_type, bool global, bool sync,
0076 int sync_count, bool exclusive)
0077 {
0078 struct rb_node **ins_point = &list->tree.rb_node, *parent = NULL;
0079 struct netdev_hw_addr *ha;
0080
0081 if (addr_len > MAX_ADDR_LEN)
0082 return -EINVAL;
0083
0084 while (*ins_point) {
0085 int diff;
0086
0087 ha = rb_entry(*ins_point, struct netdev_hw_addr, node);
0088 diff = memcmp(addr, ha->addr, addr_len);
0089 if (diff == 0)
0090 diff = memcmp(&addr_type, &ha->type, sizeof(addr_type));
0091
0092 parent = *ins_point;
0093 if (diff < 0) {
0094 ins_point = &parent->rb_left;
0095 } else if (diff > 0) {
0096 ins_point = &parent->rb_right;
0097 } else {
0098 if (exclusive)
0099 return -EEXIST;
0100 if (global) {
0101
0102 if (ha->global_use)
0103 return 0;
0104 else
0105 ha->global_use = true;
0106 }
0107 if (sync) {
0108 if (ha->synced && sync_count)
0109 return -EEXIST;
0110 else
0111 ha->synced++;
0112 }
0113 ha->refcount++;
0114 return 0;
0115 }
0116 }
0117
0118 ha = __hw_addr_create(addr, addr_len, addr_type, global, sync);
0119 if (!ha)
0120 return -ENOMEM;
0121
0122 rb_link_node(&ha->node, parent, ins_point);
0123 rb_insert_color(&ha->node, &list->tree);
0124
0125 list_add_tail_rcu(&ha->list, &list->list);
0126 list->count++;
0127
0128 return 0;
0129 }
0130
0131 static int __hw_addr_add(struct netdev_hw_addr_list *list,
0132 const unsigned char *addr, int addr_len,
0133 unsigned char addr_type)
0134 {
0135 return __hw_addr_add_ex(list, addr, addr_len, addr_type, false, false,
0136 0, false);
0137 }
0138
0139 static int __hw_addr_del_entry(struct netdev_hw_addr_list *list,
0140 struct netdev_hw_addr *ha, bool global,
0141 bool sync)
0142 {
0143 if (global && !ha->global_use)
0144 return -ENOENT;
0145
0146 if (sync && !ha->synced)
0147 return -ENOENT;
0148
0149 if (global)
0150 ha->global_use = false;
0151
0152 if (sync)
0153 ha->synced--;
0154
0155 if (--ha->refcount)
0156 return 0;
0157
0158 rb_erase(&ha->node, &list->tree);
0159
0160 list_del_rcu(&ha->list);
0161 kfree_rcu(ha, rcu_head);
0162 list->count--;
0163 return 0;
0164 }
0165
0166 static struct netdev_hw_addr *__hw_addr_lookup(struct netdev_hw_addr_list *list,
0167 const unsigned char *addr, int addr_len,
0168 unsigned char addr_type)
0169 {
0170 struct rb_node *node;
0171
0172 node = list->tree.rb_node;
0173
0174 while (node) {
0175 struct netdev_hw_addr *ha = rb_entry(node, struct netdev_hw_addr, node);
0176 int diff = memcmp(addr, ha->addr, addr_len);
0177
0178 if (diff == 0 && addr_type)
0179 diff = memcmp(&addr_type, &ha->type, sizeof(addr_type));
0180
0181 if (diff < 0)
0182 node = node->rb_left;
0183 else if (diff > 0)
0184 node = node->rb_right;
0185 else
0186 return ha;
0187 }
0188
0189 return NULL;
0190 }
0191
0192 static int __hw_addr_del_ex(struct netdev_hw_addr_list *list,
0193 const unsigned char *addr, int addr_len,
0194 unsigned char addr_type, bool global, bool sync)
0195 {
0196 struct netdev_hw_addr *ha = __hw_addr_lookup(list, addr, addr_len, addr_type);
0197
0198 if (!ha)
0199 return -ENOENT;
0200 return __hw_addr_del_entry(list, ha, global, sync);
0201 }
0202
0203 static int __hw_addr_del(struct netdev_hw_addr_list *list,
0204 const unsigned char *addr, int addr_len,
0205 unsigned char addr_type)
0206 {
0207 return __hw_addr_del_ex(list, addr, addr_len, addr_type, false, false);
0208 }
0209
0210 static int __hw_addr_sync_one(struct netdev_hw_addr_list *to_list,
0211 struct netdev_hw_addr *ha,
0212 int addr_len)
0213 {
0214 int err;
0215
0216 err = __hw_addr_add_ex(to_list, ha->addr, addr_len, ha->type,
0217 false, true, ha->sync_cnt, false);
0218 if (err && err != -EEXIST)
0219 return err;
0220
0221 if (!err) {
0222 ha->sync_cnt++;
0223 ha->refcount++;
0224 }
0225
0226 return 0;
0227 }
0228
0229 static void __hw_addr_unsync_one(struct netdev_hw_addr_list *to_list,
0230 struct netdev_hw_addr_list *from_list,
0231 struct netdev_hw_addr *ha,
0232 int addr_len)
0233 {
0234 int err;
0235
0236 err = __hw_addr_del_ex(to_list, ha->addr, addr_len, ha->type,
0237 false, true);
0238 if (err)
0239 return;
0240 ha->sync_cnt--;
0241
0242 __hw_addr_del_entry(from_list, ha, false, false);
0243 }
0244
0245 static int __hw_addr_sync_multiple(struct netdev_hw_addr_list *to_list,
0246 struct netdev_hw_addr_list *from_list,
0247 int addr_len)
0248 {
0249 int err = 0;
0250 struct netdev_hw_addr *ha, *tmp;
0251
0252 list_for_each_entry_safe(ha, tmp, &from_list->list, list) {
0253 if (ha->sync_cnt == ha->refcount) {
0254 __hw_addr_unsync_one(to_list, from_list, ha, addr_len);
0255 } else {
0256 err = __hw_addr_sync_one(to_list, ha, addr_len);
0257 if (err)
0258 break;
0259 }
0260 }
0261 return err;
0262 }
0263
0264
0265
0266
0267
0268
0269 int __hw_addr_sync(struct netdev_hw_addr_list *to_list,
0270 struct netdev_hw_addr_list *from_list,
0271 int addr_len)
0272 {
0273 int err = 0;
0274 struct netdev_hw_addr *ha, *tmp;
0275
0276 list_for_each_entry_safe(ha, tmp, &from_list->list, list) {
0277 if (!ha->sync_cnt) {
0278 err = __hw_addr_sync_one(to_list, ha, addr_len);
0279 if (err)
0280 break;
0281 } else if (ha->refcount == 1)
0282 __hw_addr_unsync_one(to_list, from_list, ha, addr_len);
0283 }
0284 return err;
0285 }
0286 EXPORT_SYMBOL(__hw_addr_sync);
0287
0288 void __hw_addr_unsync(struct netdev_hw_addr_list *to_list,
0289 struct netdev_hw_addr_list *from_list,
0290 int addr_len)
0291 {
0292 struct netdev_hw_addr *ha, *tmp;
0293
0294 list_for_each_entry_safe(ha, tmp, &from_list->list, list) {
0295 if (ha->sync_cnt)
0296 __hw_addr_unsync_one(to_list, from_list, ha, addr_len);
0297 }
0298 }
0299 EXPORT_SYMBOL(__hw_addr_unsync);
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314 int __hw_addr_sync_dev(struct netdev_hw_addr_list *list,
0315 struct net_device *dev,
0316 int (*sync)(struct net_device *, const unsigned char *),
0317 int (*unsync)(struct net_device *,
0318 const unsigned char *))
0319 {
0320 struct netdev_hw_addr *ha, *tmp;
0321 int err;
0322
0323
0324 list_for_each_entry_safe(ha, tmp, &list->list, list) {
0325 if (!ha->sync_cnt || ha->refcount != 1)
0326 continue;
0327
0328
0329 if (unsync && unsync(dev, ha->addr))
0330 continue;
0331
0332 ha->sync_cnt--;
0333 __hw_addr_del_entry(list, ha, false, false);
0334 }
0335
0336
0337 list_for_each_entry_safe(ha, tmp, &list->list, list) {
0338 if (ha->sync_cnt)
0339 continue;
0340
0341 err = sync(dev, ha->addr);
0342 if (err)
0343 return err;
0344
0345 ha->sync_cnt++;
0346 ha->refcount++;
0347 }
0348
0349 return 0;
0350 }
0351 EXPORT_SYMBOL(__hw_addr_sync_dev);
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369 int __hw_addr_ref_sync_dev(struct netdev_hw_addr_list *list,
0370 struct net_device *dev,
0371 int (*sync)(struct net_device *,
0372 const unsigned char *, int),
0373 int (*unsync)(struct net_device *,
0374 const unsigned char *, int))
0375 {
0376 struct netdev_hw_addr *ha, *tmp;
0377 int err, ref_cnt;
0378
0379
0380 list_for_each_entry_safe(ha, tmp, &list->list, list) {
0381
0382 if ((ha->sync_cnt << 1) <= ha->refcount)
0383 continue;
0384
0385
0386 ref_cnt = ha->refcount - ha->sync_cnt;
0387 if (unsync && unsync(dev, ha->addr, ref_cnt))
0388 continue;
0389
0390 ha->refcount = (ref_cnt << 1) + 1;
0391 ha->sync_cnt = ref_cnt;
0392 __hw_addr_del_entry(list, ha, false, false);
0393 }
0394
0395
0396 list_for_each_entry_safe(ha, tmp, &list->list, list) {
0397
0398 if ((ha->sync_cnt << 1) >= ha->refcount)
0399 continue;
0400
0401 ref_cnt = ha->refcount - ha->sync_cnt;
0402 err = sync(dev, ha->addr, ref_cnt);
0403 if (err)
0404 return err;
0405
0406 ha->refcount = ref_cnt << 1;
0407 ha->sync_cnt = ref_cnt;
0408 }
0409
0410 return 0;
0411 }
0412 EXPORT_SYMBOL(__hw_addr_ref_sync_dev);
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428 void __hw_addr_ref_unsync_dev(struct netdev_hw_addr_list *list,
0429 struct net_device *dev,
0430 int (*unsync)(struct net_device *,
0431 const unsigned char *, int))
0432 {
0433 struct netdev_hw_addr *ha, *tmp;
0434
0435 list_for_each_entry_safe(ha, tmp, &list->list, list) {
0436 if (!ha->sync_cnt)
0437 continue;
0438
0439
0440 if (unsync && unsync(dev, ha->addr, ha->sync_cnt))
0441 continue;
0442
0443 ha->refcount -= ha->sync_cnt - 1;
0444 ha->sync_cnt = 0;
0445 __hw_addr_del_entry(list, ha, false, false);
0446 }
0447 }
0448 EXPORT_SYMBOL(__hw_addr_ref_unsync_dev);
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462 void __hw_addr_unsync_dev(struct netdev_hw_addr_list *list,
0463 struct net_device *dev,
0464 int (*unsync)(struct net_device *,
0465 const unsigned char *))
0466 {
0467 struct netdev_hw_addr *ha, *tmp;
0468
0469 list_for_each_entry_safe(ha, tmp, &list->list, list) {
0470 if (!ha->sync_cnt)
0471 continue;
0472
0473
0474 if (unsync && unsync(dev, ha->addr))
0475 continue;
0476
0477 ha->sync_cnt--;
0478 __hw_addr_del_entry(list, ha, false, false);
0479 }
0480 }
0481 EXPORT_SYMBOL(__hw_addr_unsync_dev);
0482
0483 static void __hw_addr_flush(struct netdev_hw_addr_list *list)
0484 {
0485 struct netdev_hw_addr *ha, *tmp;
0486
0487 list->tree = RB_ROOT;
0488 list_for_each_entry_safe(ha, tmp, &list->list, list) {
0489 list_del_rcu(&ha->list);
0490 kfree_rcu(ha, rcu_head);
0491 }
0492 list->count = 0;
0493 }
0494
0495 void __hw_addr_init(struct netdev_hw_addr_list *list)
0496 {
0497 INIT_LIST_HEAD(&list->list);
0498 list->count = 0;
0499 list->tree = RB_ROOT;
0500 }
0501 EXPORT_SYMBOL(__hw_addr_init);
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511 void dev_addr_check(struct net_device *dev)
0512 {
0513 if (!memcmp(dev->dev_addr, dev->dev_addr_shadow, MAX_ADDR_LEN))
0514 return;
0515
0516 netdev_warn(dev, "Current addr: %*ph\n", MAX_ADDR_LEN, dev->dev_addr);
0517 netdev_warn(dev, "Expected addr: %*ph\n",
0518 MAX_ADDR_LEN, dev->dev_addr_shadow);
0519 netdev_WARN(dev, "Incorrect netdev->dev_addr\n");
0520 }
0521
0522
0523
0524
0525
0526
0527
0528
0529
0530 void dev_addr_flush(struct net_device *dev)
0531 {
0532
0533 dev_addr_check(dev);
0534
0535 __hw_addr_flush(&dev->dev_addrs);
0536 dev->dev_addr = NULL;
0537 }
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548 int dev_addr_init(struct net_device *dev)
0549 {
0550 unsigned char addr[MAX_ADDR_LEN];
0551 struct netdev_hw_addr *ha;
0552 int err;
0553
0554
0555
0556 __hw_addr_init(&dev->dev_addrs);
0557 memset(addr, 0, sizeof(addr));
0558 err = __hw_addr_add(&dev->dev_addrs, addr, sizeof(addr),
0559 NETDEV_HW_ADDR_T_LAN);
0560 if (!err) {
0561
0562
0563
0564
0565 ha = list_first_entry(&dev->dev_addrs.list,
0566 struct netdev_hw_addr, list);
0567 dev->dev_addr = ha->addr;
0568 }
0569 return err;
0570 }
0571
0572 void dev_addr_mod(struct net_device *dev, unsigned int offset,
0573 const void *addr, size_t len)
0574 {
0575 struct netdev_hw_addr *ha;
0576
0577 dev_addr_check(dev);
0578
0579 ha = container_of(dev->dev_addr, struct netdev_hw_addr, addr[0]);
0580 rb_erase(&ha->node, &dev->dev_addrs.tree);
0581 memcpy(&ha->addr[offset], addr, len);
0582 memcpy(&dev->dev_addr_shadow[offset], addr, len);
0583 WARN_ON(__hw_addr_insert(&dev->dev_addrs, ha, dev->addr_len));
0584 }
0585 EXPORT_SYMBOL(dev_addr_mod);
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598 int dev_addr_add(struct net_device *dev, const unsigned char *addr,
0599 unsigned char addr_type)
0600 {
0601 int err;
0602
0603 ASSERT_RTNL();
0604
0605 err = dev_pre_changeaddr_notify(dev, addr, NULL);
0606 if (err)
0607 return err;
0608 err = __hw_addr_add(&dev->dev_addrs, addr, dev->addr_len, addr_type);
0609 if (!err)
0610 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
0611 return err;
0612 }
0613 EXPORT_SYMBOL(dev_addr_add);
0614
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626 int dev_addr_del(struct net_device *dev, const unsigned char *addr,
0627 unsigned char addr_type)
0628 {
0629 int err;
0630 struct netdev_hw_addr *ha;
0631
0632 ASSERT_RTNL();
0633
0634
0635
0636
0637
0638 ha = list_first_entry(&dev->dev_addrs.list,
0639 struct netdev_hw_addr, list);
0640 if (!memcmp(ha->addr, addr, dev->addr_len) &&
0641 ha->type == addr_type && ha->refcount == 1)
0642 return -ENOENT;
0643
0644 err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len,
0645 addr_type);
0646 if (!err)
0647 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
0648 return err;
0649 }
0650 EXPORT_SYMBOL(dev_addr_del);
0651
0652
0653
0654
0655
0656
0657
0658
0659
0660
0661 int dev_uc_add_excl(struct net_device *dev, const unsigned char *addr)
0662 {
0663 int err;
0664
0665 netif_addr_lock_bh(dev);
0666 err = __hw_addr_add_ex(&dev->uc, addr, dev->addr_len,
0667 NETDEV_HW_ADDR_T_UNICAST, true, false,
0668 0, true);
0669 if (!err)
0670 __dev_set_rx_mode(dev);
0671 netif_addr_unlock_bh(dev);
0672 return err;
0673 }
0674 EXPORT_SYMBOL(dev_uc_add_excl);
0675
0676
0677
0678
0679
0680
0681
0682
0683
0684 int dev_uc_add(struct net_device *dev, const unsigned char *addr)
0685 {
0686 int err;
0687
0688 netif_addr_lock_bh(dev);
0689 err = __hw_addr_add(&dev->uc, addr, dev->addr_len,
0690 NETDEV_HW_ADDR_T_UNICAST);
0691 if (!err)
0692 __dev_set_rx_mode(dev);
0693 netif_addr_unlock_bh(dev);
0694 return err;
0695 }
0696 EXPORT_SYMBOL(dev_uc_add);
0697
0698
0699
0700
0701
0702
0703
0704
0705
0706 int dev_uc_del(struct net_device *dev, const unsigned char *addr)
0707 {
0708 int err;
0709
0710 netif_addr_lock_bh(dev);
0711 err = __hw_addr_del(&dev->uc, addr, dev->addr_len,
0712 NETDEV_HW_ADDR_T_UNICAST);
0713 if (!err)
0714 __dev_set_rx_mode(dev);
0715 netif_addr_unlock_bh(dev);
0716 return err;
0717 }
0718 EXPORT_SYMBOL(dev_uc_del);
0719
0720
0721
0722
0723
0724
0725
0726
0727
0728
0729
0730
0731
0732
0733 int dev_uc_sync(struct net_device *to, struct net_device *from)
0734 {
0735 int err = 0;
0736
0737 if (to->addr_len != from->addr_len)
0738 return -EINVAL;
0739
0740 netif_addr_lock(to);
0741 err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len);
0742 if (!err)
0743 __dev_set_rx_mode(to);
0744 netif_addr_unlock(to);
0745 return err;
0746 }
0747 EXPORT_SYMBOL(dev_uc_sync);
0748
0749
0750
0751
0752
0753
0754
0755
0756
0757
0758
0759
0760
0761
0762
0763 int dev_uc_sync_multiple(struct net_device *to, struct net_device *from)
0764 {
0765 int err = 0;
0766
0767 if (to->addr_len != from->addr_len)
0768 return -EINVAL;
0769
0770 netif_addr_lock(to);
0771 err = __hw_addr_sync_multiple(&to->uc, &from->uc, to->addr_len);
0772 if (!err)
0773 __dev_set_rx_mode(to);
0774 netif_addr_unlock(to);
0775 return err;
0776 }
0777 EXPORT_SYMBOL(dev_uc_sync_multiple);
0778
0779
0780
0781
0782
0783
0784
0785
0786
0787
0788 void dev_uc_unsync(struct net_device *to, struct net_device *from)
0789 {
0790 if (to->addr_len != from->addr_len)
0791 return;
0792
0793
0794
0795
0796
0797
0798
0799
0800
0801
0802 netif_addr_lock_bh(from);
0803 netif_addr_lock(to);
0804 __hw_addr_unsync(&to->uc, &from->uc, to->addr_len);
0805 __dev_set_rx_mode(to);
0806 netif_addr_unlock(to);
0807 netif_addr_unlock_bh(from);
0808 }
0809 EXPORT_SYMBOL(dev_uc_unsync);
0810
0811
0812
0813
0814
0815
0816
0817 void dev_uc_flush(struct net_device *dev)
0818 {
0819 netif_addr_lock_bh(dev);
0820 __hw_addr_flush(&dev->uc);
0821 netif_addr_unlock_bh(dev);
0822 }
0823 EXPORT_SYMBOL(dev_uc_flush);
0824
0825
0826
0827
0828
0829
0830
0831 void dev_uc_init(struct net_device *dev)
0832 {
0833 __hw_addr_init(&dev->uc);
0834 }
0835 EXPORT_SYMBOL(dev_uc_init);
0836
0837
0838
0839
0840
0841
0842
0843
0844
0845
0846 int dev_mc_add_excl(struct net_device *dev, const unsigned char *addr)
0847 {
0848 int err;
0849
0850 netif_addr_lock_bh(dev);
0851 err = __hw_addr_add_ex(&dev->mc, addr, dev->addr_len,
0852 NETDEV_HW_ADDR_T_MULTICAST, true, false,
0853 0, true);
0854 if (!err)
0855 __dev_set_rx_mode(dev);
0856 netif_addr_unlock_bh(dev);
0857 return err;
0858 }
0859 EXPORT_SYMBOL(dev_mc_add_excl);
0860
0861 static int __dev_mc_add(struct net_device *dev, const unsigned char *addr,
0862 bool global)
0863 {
0864 int err;
0865
0866 netif_addr_lock_bh(dev);
0867 err = __hw_addr_add_ex(&dev->mc, addr, dev->addr_len,
0868 NETDEV_HW_ADDR_T_MULTICAST, global, false,
0869 0, false);
0870 if (!err)
0871 __dev_set_rx_mode(dev);
0872 netif_addr_unlock_bh(dev);
0873 return err;
0874 }
0875
0876
0877
0878
0879
0880
0881
0882
0883 int dev_mc_add(struct net_device *dev, const unsigned char *addr)
0884 {
0885 return __dev_mc_add(dev, addr, false);
0886 }
0887 EXPORT_SYMBOL(dev_mc_add);
0888
0889
0890
0891
0892
0893
0894
0895
0896 int dev_mc_add_global(struct net_device *dev, const unsigned char *addr)
0897 {
0898 return __dev_mc_add(dev, addr, true);
0899 }
0900 EXPORT_SYMBOL(dev_mc_add_global);
0901
0902 static int __dev_mc_del(struct net_device *dev, const unsigned char *addr,
0903 bool global)
0904 {
0905 int err;
0906
0907 netif_addr_lock_bh(dev);
0908 err = __hw_addr_del_ex(&dev->mc, addr, dev->addr_len,
0909 NETDEV_HW_ADDR_T_MULTICAST, global, false);
0910 if (!err)
0911 __dev_set_rx_mode(dev);
0912 netif_addr_unlock_bh(dev);
0913 return err;
0914 }
0915
0916
0917
0918
0919
0920
0921
0922
0923
0924 int dev_mc_del(struct net_device *dev, const unsigned char *addr)
0925 {
0926 return __dev_mc_del(dev, addr, false);
0927 }
0928 EXPORT_SYMBOL(dev_mc_del);
0929
0930
0931
0932
0933
0934
0935
0936
0937
0938 int dev_mc_del_global(struct net_device *dev, const unsigned char *addr)
0939 {
0940 return __dev_mc_del(dev, addr, true);
0941 }
0942 EXPORT_SYMBOL(dev_mc_del_global);
0943
0944
0945
0946
0947
0948
0949
0950
0951
0952
0953
0954
0955
0956 int dev_mc_sync(struct net_device *to, struct net_device *from)
0957 {
0958 int err = 0;
0959
0960 if (to->addr_len != from->addr_len)
0961 return -EINVAL;
0962
0963 netif_addr_lock(to);
0964 err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len);
0965 if (!err)
0966 __dev_set_rx_mode(to);
0967 netif_addr_unlock(to);
0968 return err;
0969 }
0970 EXPORT_SYMBOL(dev_mc_sync);
0971
0972
0973
0974
0975
0976
0977
0978
0979
0980
0981
0982
0983
0984
0985
0986 int dev_mc_sync_multiple(struct net_device *to, struct net_device *from)
0987 {
0988 int err = 0;
0989
0990 if (to->addr_len != from->addr_len)
0991 return -EINVAL;
0992
0993 netif_addr_lock(to);
0994 err = __hw_addr_sync_multiple(&to->mc, &from->mc, to->addr_len);
0995 if (!err)
0996 __dev_set_rx_mode(to);
0997 netif_addr_unlock(to);
0998 return err;
0999 }
1000 EXPORT_SYMBOL(dev_mc_sync_multiple);
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011 void dev_mc_unsync(struct net_device *to, struct net_device *from)
1012 {
1013 if (to->addr_len != from->addr_len)
1014 return;
1015
1016
1017 netif_addr_lock_bh(from);
1018 netif_addr_lock(to);
1019 __hw_addr_unsync(&to->mc, &from->mc, to->addr_len);
1020 __dev_set_rx_mode(to);
1021 netif_addr_unlock(to);
1022 netif_addr_unlock_bh(from);
1023 }
1024 EXPORT_SYMBOL(dev_mc_unsync);
1025
1026
1027
1028
1029
1030
1031
1032 void dev_mc_flush(struct net_device *dev)
1033 {
1034 netif_addr_lock_bh(dev);
1035 __hw_addr_flush(&dev->mc);
1036 netif_addr_unlock_bh(dev);
1037 }
1038 EXPORT_SYMBOL(dev_mc_flush);
1039
1040
1041
1042
1043
1044
1045
1046 void dev_mc_init(struct net_device *dev)
1047 {
1048 __hw_addr_init(&dev->mc);
1049 }
1050 EXPORT_SYMBOL(dev_mc_init);