LCOV - code coverage report
Current view: top level - net/core - dev_addr_lists.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 224 0.0 %
Date: 2014-04-07 Functions: 0 39 0.0 %
Branches: 0 152 0.0 %

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

Generated by: LCOV version 1.9