LCOV - code coverage report
Current view: top level - net/core - dev_addr_lists.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 59 254 23.2 %
Date: 2020-09-30 20:25:40 Functions: 11 39 28.2 %
Branches: 19 184 10.3 %

           Branch data     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                 :       2070 : 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                 :            :         struct netdev_hw_addr *ha;
      25                 :            :         int alloc_size;
      26                 :            : 
      27                 :            :         alloc_size = sizeof(*ha);
      28                 :            :         if (alloc_size < L1_CACHE_BYTES)
      29                 :            :                 alloc_size = L1_CACHE_BYTES;
      30                 :            :         ha = kmalloc(alloc_size, GFP_ATOMIC);
      31         [ +  - ]:       2070 :         if (!ha)
      32                 :            :                 return -ENOMEM;
      33                 :       2070 :         memcpy(ha->addr, addr, addr_len);
      34                 :       2070 :         ha->type = addr_type;
      35                 :       2070 :         ha->refcount = 1;
      36                 :       2070 :         ha->global_use = global;
      37                 :       2070 :         ha->synced = sync ? 1 : 0;
      38                 :       2070 :         ha->sync_cnt = 0;
      39                 :       2070 :         list_add_tail_rcu(&ha->list, &list->list);
      40                 :       2070 :         list->count++;
      41                 :            : 
      42                 :       2070 :         return 0;
      43                 :            : }
      44                 :            : 
      45                 :       2070 : 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                 :            :         struct netdev_hw_addr *ha;
      51                 :            : 
      52         [ +  - ]:       2070 :         if (addr_len > MAX_ADDR_LEN)
      53                 :            :                 return -EINVAL;
      54                 :            : 
      55         [ +  + ]:       5175 :         list_for_each_entry(ha, &list->list, list) {
      56   [ +  -  -  + ]:       6210 :                 if (ha->type == addr_type &&
      57                 :       3105 :                     !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                 :       2070 :         return __hw_addr_create_ex(list, addr, addr_len, addr_type, global,
      77                 :            :                                    sync);
      78                 :            : }
      79                 :            : 
      80                 :            : 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                 :        621 :         return __hw_addr_add_ex(list, addr, addr_len, addr_type, false, false,
      85                 :            :                                 0);
      86                 :            : }
      87                 :            : 
      88                 :        414 : 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   [ -  +  #  # ]:        414 :         if (global && !ha->global_use)
      93                 :            :                 return -ENOENT;
      94                 :            : 
      95   [ -  +  #  # ]:        414 :         if (sync && !ha->synced)
      96                 :            :                 return -ENOENT;
      97                 :            : 
      98         [ -  + ]:        414 :         if (global)
      99                 :          0 :                 ha->global_use = false;
     100                 :            : 
     101         [ -  + ]:        414 :         if (sync)
     102                 :          0 :                 ha->synced--;
     103                 :            : 
     104         [ +  - ]:        414 :         if (--ha->refcount)
     105                 :            :                 return 0;
     106                 :            :         list_del_rcu(&ha->list);
     107         [ +  - ]:        414 :         kfree_rcu(ha, rcu_head);
     108                 :        414 :         list->count--;
     109                 :        414 :         return 0;
     110                 :            : }
     111                 :            : 
     112                 :        414 : 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                 :            :         struct netdev_hw_addr *ha;
     117                 :            : 
     118         [ +  - ]:       1325 :         list_for_each_entry(ha, &list->list, list) {
     119   [ +  +  -  + ]:       1739 :                 if (!memcmp(ha->addr, addr, addr_len) &&
     120         [ #  # ]:        414 :                     (ha->type == addr_type || !addr_type))
     121                 :        414 :                         return __hw_addr_del_entry(list, ha, global, sync);
     122                 :            :         }
     123                 :            :         return -ENOENT;
     124                 :            : }
     125                 :            : 
     126                 :            : 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                 :            :         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                 :            :         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                 :          0 :                 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                 :            :         int err = 0;
     173                 :            :         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                 :            :         int err = 0;
     197                 :            :         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                 :            :         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                 :            :         struct netdev_hw_addr *ha, *tmp;
     244                 :            :         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                 :            :         struct netdev_hw_addr *ha, *tmp;
     300                 :            :         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                 :            :         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                 :            :         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                 :            :         struct netdev_hw_addr *ha, *tmp;
     409                 :            : 
     410         [ #  # ]:          0 :         list_for_each_entry_safe(ha, tmp, &list->list, list) {
     411                 :            :                 list_del_rcu(&ha->list);
     412         [ #  # ]:          0 :                 kfree_rcu(ha, rcu_head);
     413                 :            :         }
     414                 :          0 :         list->count = 0;
     415                 :          0 : }
     416                 :            : 
     417                 :          0 : void __hw_addr_init(struct netdev_hw_addr_list *list)
     418                 :            : {
     419                 :       1863 :         INIT_LIST_HEAD(&list->list);
     420                 :       1863 :         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                 :        621 : int dev_addr_init(struct net_device *dev)
     455                 :            : {
     456                 :            :         unsigned char addr[MAX_ADDR_LEN];
     457                 :            :         struct netdev_hw_addr *ha;
     458                 :            :         int err;
     459                 :            : 
     460                 :            :         /* rtnl_mutex must be held here */
     461                 :            : 
     462                 :            :         __hw_addr_init(&dev->dev_addrs);
     463                 :        621 :         memset(addr, 0, sizeof(addr));
     464                 :        621 :         err = __hw_addr_add(&dev->dev_addrs, addr, sizeof(addr),
     465                 :            :                             NETDEV_HW_ADDR_T_LAN);
     466         [ +  - ]:        621 :         if (!err) {
     467                 :            :                 /*
     468                 :            :                  * Get the first (previously created) address from the list
     469                 :            :                  * and set dev_addr pointer to this location.
     470                 :            :                  */
     471                 :        621 :                 ha = list_first_entry(&dev->dev_addrs.list,
     472                 :            :                                       struct netdev_hw_addr, list);
     473                 :        621 :                 dev->dev_addr = ha->addr;
     474                 :            :         }
     475                 :        621 :         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                 :            :         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                 :          0 :         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                 :            :         int err;
     522                 :            :         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                 :          0 :         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                 :            :         struct netdev_hw_addr *ha;
     556                 :            :         int err;
     557                 :            : 
     558                 :            :         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                 :            :                         err = -EEXIST;
     563                 :            :                         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                 :            : out:
     571                 :            :         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                 :            :         int err;
     587                 :            : 
     588                 :            :         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                 :            :         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                 :            :         int err;
     609                 :            : 
     610                 :            :         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                 :            :         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                 :            :         int err = 0;
     636                 :            : 
     637         [ #  # ]:          0 :         if (to->addr_len != from->addr_len)
     638                 :            :                 return -EINVAL;
     639                 :            : 
     640                 :            :         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                 :            :         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                 :            :         int err = 0;
     666                 :            : 
     667         [ #  # ]:          0 :         if (to->addr_len != from->addr_len)
     668                 :            :                 return -EINVAL;
     669                 :            : 
     670                 :            :         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                 :            :         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                 :          0 :                 return;
     692                 :            : 
     693                 :            :         netif_addr_lock_bh(from);
     694                 :            :         netif_addr_lock(to);
     695                 :          0 :         __hw_addr_unsync(&to->uc, &from->uc, to->addr_len);
     696                 :          0 :         __dev_set_rx_mode(to);
     697                 :            :         netif_addr_unlock(to);
     698                 :            :         netif_addr_unlock_bh(from);
     699                 :            : }
     700                 :            : EXPORT_SYMBOL(dev_uc_unsync);
     701                 :            : 
     702                 :            : /**
     703                 :            :  *      dev_uc_flush - Flush unicast addresses
     704                 :            :  *      @dev: device
     705                 :            :  *
     706                 :            :  *      Flush unicast addresses.
     707                 :            :  */
     708                 :          0 : void dev_uc_flush(struct net_device *dev)
     709                 :            : {
     710                 :            :         netif_addr_lock_bh(dev);
     711                 :          0 :         __hw_addr_flush(&dev->uc);
     712                 :            :         netif_addr_unlock_bh(dev);
     713                 :          0 : }
     714                 :            : EXPORT_SYMBOL(dev_uc_flush);
     715                 :            : 
     716                 :            : /**
     717                 :            :  *      dev_uc_flush - Init unicast address list
     718                 :            :  *      @dev: device
     719                 :            :  *
     720                 :            :  *      Init unicast address list.
     721                 :            :  */
     722                 :        621 : void dev_uc_init(struct net_device *dev)
     723                 :            : {
     724                 :            :         __hw_addr_init(&dev->uc);
     725                 :        621 : }
     726                 :            : EXPORT_SYMBOL(dev_uc_init);
     727                 :            : 
     728                 :            : /*
     729                 :            :  * Multicast list handling functions
     730                 :            :  */
     731                 :            : 
     732                 :            : /**
     733                 :            :  *      dev_mc_add_excl - Add a global secondary multicast address
     734                 :            :  *      @dev: device
     735                 :            :  *      @addr: address to add
     736                 :            :  */
     737                 :          0 : int dev_mc_add_excl(struct net_device *dev, const unsigned char *addr)
     738                 :            : {
     739                 :            :         struct netdev_hw_addr *ha;
     740                 :            :         int err;
     741                 :            : 
     742                 :            :         netif_addr_lock_bh(dev);
     743         [ #  # ]:          0 :         list_for_each_entry(ha, &dev->mc.list, list) {
     744   [ #  #  #  # ]:          0 :                 if (!memcmp(ha->addr, addr, dev->addr_len) &&
     745                 :          0 :                     ha->type == NETDEV_HW_ADDR_T_MULTICAST) {
     746                 :            :                         err = -EEXIST;
     747                 :            :                         goto out;
     748                 :            :                 }
     749                 :            :         }
     750                 :          0 :         err = __hw_addr_create_ex(&dev->mc, addr, dev->addr_len,
     751                 :            :                                   NETDEV_HW_ADDR_T_MULTICAST, true, false);
     752         [ #  # ]:          0 :         if (!err)
     753                 :          0 :                 __dev_set_rx_mode(dev);
     754                 :            : out:
     755                 :            :         netif_addr_unlock_bh(dev);
     756                 :          0 :         return err;
     757                 :            : }
     758                 :            : EXPORT_SYMBOL(dev_mc_add_excl);
     759                 :            : 
     760                 :       1449 : static int __dev_mc_add(struct net_device *dev, const unsigned char *addr,
     761                 :            :                         bool global)
     762                 :            : {
     763                 :            :         int err;
     764                 :            : 
     765                 :            :         netif_addr_lock_bh(dev);
     766                 :       1449 :         err = __hw_addr_add_ex(&dev->mc, addr, dev->addr_len,
     767                 :            :                                NETDEV_HW_ADDR_T_MULTICAST, global, false, 0);
     768         [ +  - ]:       1449 :         if (!err)
     769                 :       1449 :                 __dev_set_rx_mode(dev);
     770                 :            :         netif_addr_unlock_bh(dev);
     771                 :       1449 :         return err;
     772                 :            : }
     773                 :            : /**
     774                 :            :  *      dev_mc_add - Add a multicast address
     775                 :            :  *      @dev: device
     776                 :            :  *      @addr: address to add
     777                 :            :  *
     778                 :            :  *      Add a multicast address to the device or increase
     779                 :            :  *      the reference count if it already exists.
     780                 :            :  */
     781                 :       1449 : int dev_mc_add(struct net_device *dev, const unsigned char *addr)
     782                 :            : {
     783                 :       1449 :         return __dev_mc_add(dev, addr, false);
     784                 :            : }
     785                 :            : EXPORT_SYMBOL(dev_mc_add);
     786                 :            : 
     787                 :            : /**
     788                 :            :  *      dev_mc_add_global - Add a global multicast address
     789                 :            :  *      @dev: device
     790                 :            :  *      @addr: address to add
     791                 :            :  *
     792                 :            :  *      Add a global multicast address to the device.
     793                 :            :  */
     794                 :          0 : int dev_mc_add_global(struct net_device *dev, const unsigned char *addr)
     795                 :            : {
     796                 :          0 :         return __dev_mc_add(dev, addr, true);
     797                 :            : }
     798                 :            : EXPORT_SYMBOL(dev_mc_add_global);
     799                 :            : 
     800                 :        414 : static int __dev_mc_del(struct net_device *dev, const unsigned char *addr,
     801                 :            :                         bool global)
     802                 :            : {
     803                 :            :         int err;
     804                 :            : 
     805                 :            :         netif_addr_lock_bh(dev);
     806                 :        414 :         err = __hw_addr_del_ex(&dev->mc, addr, dev->addr_len,
     807                 :            :                                NETDEV_HW_ADDR_T_MULTICAST, global, false);
     808         [ +  - ]:        414 :         if (!err)
     809                 :        414 :                 __dev_set_rx_mode(dev);
     810                 :            :         netif_addr_unlock_bh(dev);
     811                 :        414 :         return err;
     812                 :            : }
     813                 :            : 
     814                 :            : /**
     815                 :            :  *      dev_mc_del - Delete a multicast address.
     816                 :            :  *      @dev: device
     817                 :            :  *      @addr: address to delete
     818                 :            :  *
     819                 :            :  *      Release reference to a multicast address and remove it
     820                 :            :  *      from the device if the reference count drops to zero.
     821                 :            :  */
     822                 :        414 : int dev_mc_del(struct net_device *dev, const unsigned char *addr)
     823                 :            : {
     824                 :        414 :         return __dev_mc_del(dev, addr, false);
     825                 :            : }
     826                 :            : EXPORT_SYMBOL(dev_mc_del);
     827                 :            : 
     828                 :            : /**
     829                 :            :  *      dev_mc_del_global - Delete a global multicast address.
     830                 :            :  *      @dev: device
     831                 :            :  *      @addr: address to delete
     832                 :            :  *
     833                 :            :  *      Release reference to a multicast address and remove it
     834                 :            :  *      from the device if the reference count drops to zero.
     835                 :            :  */
     836                 :          0 : int dev_mc_del_global(struct net_device *dev, const unsigned char *addr)
     837                 :            : {
     838                 :          0 :         return __dev_mc_del(dev, addr, true);
     839                 :            : }
     840                 :            : EXPORT_SYMBOL(dev_mc_del_global);
     841                 :            : 
     842                 :            : /**
     843                 :            :  *      dev_mc_sync - Synchronize device's multicast list to another device
     844                 :            :  *      @to: destination device
     845                 :            :  *      @from: source device
     846                 :            :  *
     847                 :            :  *      Add newly added addresses to the destination device and release
     848                 :            :  *      addresses that have no users left. The source device must be
     849                 :            :  *      locked by netif_addr_lock_bh.
     850                 :            :  *
     851                 :            :  *      This function is intended to be called from the ndo_set_rx_mode
     852                 :            :  *      function of layered software devices.
     853                 :            :  */
     854                 :          0 : int dev_mc_sync(struct net_device *to, struct net_device *from)
     855                 :            : {
     856                 :            :         int err = 0;
     857                 :            : 
     858         [ #  # ]:          0 :         if (to->addr_len != from->addr_len)
     859                 :            :                 return -EINVAL;
     860                 :            : 
     861                 :            :         netif_addr_lock(to);
     862                 :          0 :         err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len);
     863         [ #  # ]:          0 :         if (!err)
     864                 :          0 :                 __dev_set_rx_mode(to);
     865                 :            :         netif_addr_unlock(to);
     866                 :          0 :         return err;
     867                 :            : }
     868                 :            : EXPORT_SYMBOL(dev_mc_sync);
     869                 :            : 
     870                 :            : /**
     871                 :            :  *      dev_mc_sync_multiple - Synchronize device's multicast list to another
     872                 :            :  *      device, but allow for multiple calls to sync to multiple devices.
     873                 :            :  *      @to: destination device
     874                 :            :  *      @from: source device
     875                 :            :  *
     876                 :            :  *      Add newly added addresses to the destination device and release
     877                 :            :  *      addresses that have no users left. The source device must be
     878                 :            :  *      locked by netif_addr_lock_bh.
     879                 :            :  *
     880                 :            :  *      This function is intended to be called from the ndo_set_rx_mode
     881                 :            :  *      function of layered software devices.  It allows for a single
     882                 :            :  *      source device to be synced to multiple destination devices.
     883                 :            :  */
     884                 :          0 : int dev_mc_sync_multiple(struct net_device *to, struct net_device *from)
     885                 :            : {
     886                 :            :         int err = 0;
     887                 :            : 
     888         [ #  # ]:          0 :         if (to->addr_len != from->addr_len)
     889                 :            :                 return -EINVAL;
     890                 :            : 
     891                 :            :         netif_addr_lock(to);
     892                 :          0 :         err = __hw_addr_sync_multiple(&to->mc, &from->mc, to->addr_len);
     893         [ #  # ]:          0 :         if (!err)
     894                 :          0 :                 __dev_set_rx_mode(to);
     895                 :            :         netif_addr_unlock(to);
     896                 :          0 :         return err;
     897                 :            : }
     898                 :            : EXPORT_SYMBOL(dev_mc_sync_multiple);
     899                 :            : 
     900                 :            : /**
     901                 :            :  *      dev_mc_unsync - Remove synchronized addresses from the destination device
     902                 :            :  *      @to: destination device
     903                 :            :  *      @from: source device
     904                 :            :  *
     905                 :            :  *      Remove all addresses that were added to the destination device by
     906                 :            :  *      dev_mc_sync(). This function is intended to be called from the
     907                 :            :  *      dev->stop function of layered software devices.
     908                 :            :  */
     909                 :          0 : void dev_mc_unsync(struct net_device *to, struct net_device *from)
     910                 :            : {
     911         [ #  # ]:          0 :         if (to->addr_len != from->addr_len)
     912                 :          0 :                 return;
     913                 :            : 
     914                 :            :         netif_addr_lock_bh(from);
     915                 :            :         netif_addr_lock(to);
     916                 :          0 :         __hw_addr_unsync(&to->mc, &from->mc, to->addr_len);
     917                 :          0 :         __dev_set_rx_mode(to);
     918                 :            :         netif_addr_unlock(to);
     919                 :            :         netif_addr_unlock_bh(from);
     920                 :            : }
     921                 :            : EXPORT_SYMBOL(dev_mc_unsync);
     922                 :            : 
     923                 :            : /**
     924                 :            :  *      dev_mc_flush - Flush multicast addresses
     925                 :            :  *      @dev: device
     926                 :            :  *
     927                 :            :  *      Flush multicast addresses.
     928                 :            :  */
     929                 :          0 : void dev_mc_flush(struct net_device *dev)
     930                 :            : {
     931                 :            :         netif_addr_lock_bh(dev);
     932                 :          0 :         __hw_addr_flush(&dev->mc);
     933                 :            :         netif_addr_unlock_bh(dev);
     934                 :          0 : }
     935                 :            : EXPORT_SYMBOL(dev_mc_flush);
     936                 :            : 
     937                 :            : /**
     938                 :            :  *      dev_mc_init - Init multicast address list
     939                 :            :  *      @dev: device
     940                 :            :  *
     941                 :            :  *      Init multicast address list.
     942                 :            :  */
     943                 :        621 : void dev_mc_init(struct net_device *dev)
     944                 :            : {
     945                 :            :         __hw_addr_init(&dev->mc);
     946                 :        621 : }
     947                 :            : EXPORT_SYMBOL(dev_mc_init);

Generated by: LCOV version 1.14