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

Generated by: LCOV version 1.9