LCOV - code coverage report
Current view: top level - net/core - dev_addr_lists.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 53 333 15.9 %
Date: 2021-04-22 12:43:58 Functions: 7 39 17.9 %

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

Generated by: LCOV version 1.14