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