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 (!memcmp(ha->addr, addr, dev->addr_len) &&
 321            ha->type == addr_type && ha->refcount == 1)
 322                return -ENOENT;
 323
 324        err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len,
 325                            addr_type);
 326        if (!err)
 327                call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
 328        return err;
 329}
 330EXPORT_SYMBOL(dev_addr_del);
 331
 332/**
 333 *      dev_addr_add_multiple - Add device addresses from another device
 334 *      @to_dev: device to which addresses will be added
 335 *      @from_dev: device from which addresses will be added
 336 *      @addr_type: address type - 0 means type will be used from from_dev
 337 *
 338 *      Add device addresses of the one device to another.
 339 **
 340 *      The caller must hold the rtnl_mutex.
 341 */
 342int dev_addr_add_multiple(struct net_device *to_dev,
 343                          struct net_device *from_dev,
 344                          unsigned char addr_type)
 345{
 346        int err;
 347
 348        ASSERT_RTNL();
 349
 350        if (from_dev->addr_len != to_dev->addr_len)
 351                return -EINVAL;
 352        err = __hw_addr_add_multiple(&to_dev->dev_addrs, &from_dev->dev_addrs,
 353                                     to_dev->addr_len, addr_type);
 354        if (!err)
 355                call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev);
 356        return err;
 357}
 358EXPORT_SYMBOL(dev_addr_add_multiple);
 359
 360/**
 361 *      dev_addr_del_multiple - Delete device addresses by another device
 362 *      @to_dev: device where the addresses will be deleted
 363 *      @from_dev: device supplying the addresses to be deleted
 364 *      @addr_type: address type - 0 means type will be used from from_dev
 365 *
 366 *      Deletes addresses in to device by the list of addresses in from device.
 367 *
 368 *      The caller must hold the rtnl_mutex.
 369 */
 370int dev_addr_del_multiple(struct net_device *to_dev,
 371                          struct net_device *from_dev,
 372                          unsigned char addr_type)
 373{
 374        ASSERT_RTNL();
 375
 376        if (from_dev->addr_len != to_dev->addr_len)
 377                return -EINVAL;
 378        __hw_addr_del_multiple(&to_dev->dev_addrs, &from_dev->dev_addrs,
 379                               to_dev->addr_len, addr_type);
 380        call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev);
 381        return 0;
 382}
 383EXPORT_SYMBOL(dev_addr_del_multiple);
 384
 385/*
 386 * Unicast list handling functions
 387 */
 388
 389/**
 390 *      dev_uc_add_excl - Add a global secondary unicast address
 391 *      @dev: device
 392 *      @addr: address to add
 393 */
 394int dev_uc_add_excl(struct net_device *dev, unsigned char *addr)
 395{
 396        struct netdev_hw_addr *ha;
 397        int err;
 398
 399        netif_addr_lock_bh(dev);
 400        list_for_each_entry(ha, &dev->uc.list, list) {
 401                if (!memcmp(ha->addr, addr, dev->addr_len) &&
 402                    ha->type == NETDEV_HW_ADDR_T_UNICAST) {
 403                        err = -EEXIST;
 404                        goto out;
 405                }
 406        }
 407        err = __hw_addr_create_ex(&dev->uc, addr, dev->addr_len,
 408                                  NETDEV_HW_ADDR_T_UNICAST, true);
 409        if (!err)
 410                __dev_set_rx_mode(dev);
 411out:
 412        netif_addr_unlock_bh(dev);
 413        return err;
 414}
 415EXPORT_SYMBOL(dev_uc_add_excl);
 416
 417/**
 418 *      dev_uc_add - Add a secondary unicast address
 419 *      @dev: device
 420 *      @addr: address to add
 421 *
 422 *      Add a secondary unicast address to the device or increase
 423 *      the reference count if it already exists.
 424 */
 425int dev_uc_add(struct net_device *dev, unsigned char *addr)
 426{
 427        int err;
 428
 429        netif_addr_lock_bh(dev);
 430        err = __hw_addr_add(&dev->uc, addr, dev->addr_len,
 431                            NETDEV_HW_ADDR_T_UNICAST);
 432        if (!err)
 433                __dev_set_rx_mode(dev);
 434        netif_addr_unlock_bh(dev);
 435        return err;
 436}
 437EXPORT_SYMBOL(dev_uc_add);
 438
 439/**
 440 *      dev_uc_del - Release secondary unicast address.
 441 *      @dev: device
 442 *      @addr: address to delete
 443 *
 444 *      Release reference to a secondary unicast address and remove it
 445 *      from the device if the reference count drops to zero.
 446 */
 447int dev_uc_del(struct net_device *dev, unsigned char *addr)
 448{
 449        int err;
 450
 451        netif_addr_lock_bh(dev);
 452        err = __hw_addr_del(&dev->uc, addr, dev->addr_len,
 453                            NETDEV_HW_ADDR_T_UNICAST);
 454        if (!err)
 455                __dev_set_rx_mode(dev);
 456        netif_addr_unlock_bh(dev);
 457        return err;
 458}
 459EXPORT_SYMBOL(dev_uc_del);
 460
 461/**
 462 *      dev_uc_sync - Synchronize device's unicast list to another device
 463 *      @to: destination device
 464 *      @from: source device
 465 *
 466 *      Add newly added addresses to the destination device and release
 467 *      addresses that have no users left. The source device must be
 468 *      locked by netif_addr_lock_bh.
 469 *
 470 *      This function is intended to be called from the dev->set_rx_mode
 471 *      function of layered software devices.
 472 */
 473int dev_uc_sync(struct net_device *to, struct net_device *from)
 474{
 475        int err = 0;
 476
 477        if (to->addr_len != from->addr_len)
 478                return -EINVAL;
 479
 480        netif_addr_lock_nested(to);
 481        err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len);
 482        if (!err)
 483                __dev_set_rx_mode(to);
 484        netif_addr_unlock(to);
 485        return err;
 486}
 487EXPORT_SYMBOL(dev_uc_sync);
 488
 489/**
 490 *      dev_uc_unsync - Remove synchronized addresses from the destination device
 491 *      @to: destination device
 492 *      @from: source device
 493 *
 494 *      Remove all addresses that were added to the destination device by
 495 *      dev_uc_sync(). This function is intended to be called from the
 496 *      dev->stop function of layered software devices.
 497 */
 498void dev_uc_unsync(struct net_device *to, struct net_device *from)
 499{
 500        if (to->addr_len != from->addr_len)
 501                return;
 502
 503        netif_addr_lock_bh(from);
 504        netif_addr_lock_nested(to);
 505        __hw_addr_unsync(&to->uc, &from->uc, to->addr_len);
 506        __dev_set_rx_mode(to);
 507        netif_addr_unlock(to);
 508        netif_addr_unlock_bh(from);
 509}
 510EXPORT_SYMBOL(dev_uc_unsync);
 511
 512/**
 513 *      dev_uc_flush - Flush unicast addresses
 514 *      @dev: device
 515 *
 516 *      Flush unicast addresses.
 517 */
 518void dev_uc_flush(struct net_device *dev)
 519{
 520        netif_addr_lock_bh(dev);
 521        __hw_addr_flush(&dev->uc);
 522        netif_addr_unlock_bh(dev);
 523}
 524EXPORT_SYMBOL(dev_uc_flush);
 525
 526/**
 527 *      dev_uc_flush - Init unicast address list
 528 *      @dev: device
 529 *
 530 *      Init unicast address list.
 531 */
 532void dev_uc_init(struct net_device *dev)
 533{
 534        __hw_addr_init(&dev->uc);
 535}
 536EXPORT_SYMBOL(dev_uc_init);
 537
 538/*
 539 * Multicast list handling functions
 540 */
 541
 542/**
 543 *      dev_mc_add_excl - Add a global secondary multicast address
 544 *      @dev: device
 545 *      @addr: address to add
 546 */
 547int dev_mc_add_excl(struct net_device *dev, unsigned char *addr)
 548{
 549        struct netdev_hw_addr *ha;
 550        int err;
 551
 552        netif_addr_lock_bh(dev);
 553        list_for_each_entry(ha, &dev->mc.list, list) {
 554                if (!memcmp(ha->addr, addr, dev->addr_len) &&
 555                    ha->type == NETDEV_HW_ADDR_T_MULTICAST) {
 556                        err = -EEXIST;
 557                        goto out;
 558                }
 559        }
 560        err = __hw_addr_create_ex(&dev->mc, addr, dev->addr_len,
 561                                  NETDEV_HW_ADDR_T_MULTICAST, true);
 562        if (!err)
 563                __dev_set_rx_mode(dev);
 564out:
 565        netif_addr_unlock_bh(dev);
 566        return err;
 567}
 568EXPORT_SYMBOL(dev_mc_add_excl);
 569
 570static int __dev_mc_add(struct net_device *dev, unsigned char *addr,
 571                        bool global)
 572{
 573        int err;
 574
 575        netif_addr_lock_bh(dev);
 576        err = __hw_addr_add_ex(&dev->mc, addr, dev->addr_len,
 577                               NETDEV_HW_ADDR_T_MULTICAST, global);
 578        if (!err)
 579                __dev_set_rx_mode(dev);
 580        netif_addr_unlock_bh(dev);
 581        return err;
 582}
 583/**
 584 *      dev_mc_add - Add a multicast address
 585 *      @dev: device
 586 *      @addr: address to add
 587 *
 588 *      Add a multicast address to the device or increase
 589 *      the reference count if it already exists.
 590 */
 591int dev_mc_add(struct net_device *dev, unsigned char *addr)
 592{
 593        return __dev_mc_add(dev, addr, false);
 594}
 595EXPORT_SYMBOL(dev_mc_add);
 596
 597/**
 598 *      dev_mc_add_global - Add a global multicast address
 599 *      @dev: device
 600 *      @addr: address to add
 601 *
 602 *      Add a global multicast address to the device.
 603 */
 604int dev_mc_add_global(struct net_device *dev, unsigned char *addr)
 605{
 606        return __dev_mc_add(dev, addr, true);
 607}
 608EXPORT_SYMBOL(dev_mc_add_global);
 609
 610static int __dev_mc_del(struct net_device *dev, unsigned char *addr,
 611                        bool global)
 612{
 613        int err;
 614
 615        netif_addr_lock_bh(dev);
 616        err = __hw_addr_del_ex(&dev->mc, addr, dev->addr_len,
 617                               NETDEV_HW_ADDR_T_MULTICAST, global);
 618        if (!err)
 619                __dev_set_rx_mode(dev);
 620        netif_addr_unlock_bh(dev);
 621        return err;
 622}
 623
 624/**
 625 *      dev_mc_del - Delete a multicast address.
 626 *      @dev: device
 627 *      @addr: address to delete
 628 *
 629 *      Release reference to a multicast address and remove it
 630 *      from the device if the reference count drops to zero.
 631 */
 632int dev_mc_del(struct net_device *dev, unsigned char *addr)
 633{
 634        return __dev_mc_del(dev, addr, false);
 635}
 636EXPORT_SYMBOL(dev_mc_del);
 637
 638/**
 639 *      dev_mc_del_global - Delete a global multicast address.
 640 *      @dev: device
 641 *      @addr: address to delete
 642 *
 643 *      Release reference to a multicast address and remove it
 644 *      from the device if the reference count drops to zero.
 645 */
 646int dev_mc_del_global(struct net_device *dev, unsigned char *addr)
 647{
 648        return __dev_mc_del(dev, addr, true);
 649}
 650EXPORT_SYMBOL(dev_mc_del_global);
 651
 652/**
 653 *      dev_mc_sync - Synchronize device's unicast list to another device
 654 *      @to: destination device
 655 *      @from: source device
 656 *
 657 *      Add newly added addresses to the destination device and release
 658 *      addresses that have no users left. The source device must be
 659 *      locked by netif_addr_lock_bh.
 660 *
 661 *      This function is intended to be called from the ndo_set_rx_mode
 662 *      function of layered software devices.
 663 */
 664int dev_mc_sync(struct net_device *to, struct net_device *from)
 665{
 666        int err = 0;
 667
 668        if (to->addr_len != from->addr_len)
 669                return -EINVAL;
 670
 671        netif_addr_lock_nested(to);
 672        err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len);
 673        if (!err)
 674                __dev_set_rx_mode(to);
 675        netif_addr_unlock(to);
 676        return err;
 677}
 678EXPORT_SYMBOL(dev_mc_sync);
 679
 680/**
 681 *      dev_mc_unsync - Remove synchronized addresses from the destination device
 682 *      @to: destination device
 683 *      @from: source device
 684 *
 685 *      Remove all addresses that were added to the destination device by
 686 *      dev_mc_sync(). This function is intended to be called from the
 687 *      dev->stop function of layered software devices.
 688 */
 689void dev_mc_unsync(struct net_device *to, struct net_device *from)
 690{
 691        if (to->addr_len != from->addr_len)
 692                return;
 693
 694        netif_addr_lock_bh(from);
 695        netif_addr_lock_nested(to);
 696        __hw_addr_unsync(&to->mc, &from->mc, to->addr_len);
 697        __dev_set_rx_mode(to);
 698        netif_addr_unlock(to);
 699        netif_addr_unlock_bh(from);
 700}
 701EXPORT_SYMBOL(dev_mc_unsync);
 702
 703/**
 704 *      dev_mc_flush - Flush multicast addresses
 705 *      @dev: device
 706 *
 707 *      Flush multicast addresses.
 708 */
 709void dev_mc_flush(struct net_device *dev)
 710{
 711        netif_addr_lock_bh(dev);
 712        __hw_addr_flush(&dev->mc);
 713        netif_addr_unlock_bh(dev);
 714}
 715EXPORT_SYMBOL(dev_mc_flush);
 716
 717/**
 718 *      dev_mc_flush - Init multicast address list
 719 *      @dev: device
 720 *
 721 *      Init multicast address list.
 722 */
 723void dev_mc_init(struct net_device *dev)
 724{
 725        __hw_addr_init(&dev->mc);
 726}
 727EXPORT_SYMBOL(dev_mc_init);
 728
 729#ifdef CONFIG_PROC_FS
 730#include <linux/seq_file.h>
 731
 732static int dev_mc_seq_show(struct seq_file *seq, void *v)
 733{
 734        struct netdev_hw_addr *ha;
 735        struct net_device *dev = v;
 736
 737        if (v == SEQ_START_TOKEN)
 738                return 0;
 739
 740        netif_addr_lock_bh(dev);
 741        netdev_for_each_mc_addr(ha, dev) {
 742                int i;
 743
 744                seq_printf(seq, "%-4d %-15s %-5d %-5d ", dev->ifindex,
 745                           dev->name, ha->refcount, ha->global_use);
 746
 747                for (i = 0; i < dev->addr_len; i++)
 748                        seq_printf(seq, "%02x", ha->addr[i]);
 749
 750                seq_putc(seq, '\n');
 751        }
 752        netif_addr_unlock_bh(dev);
 753        return 0;
 754}
 755
 756static const struct seq_operations dev_mc_seq_ops = {
 757        .start = dev_seq_start,
 758        .next  = dev_seq_next,
 759        .stop  = dev_seq_stop,
 760        .show  = dev_mc_seq_show,
 761};
 762
 763static int dev_mc_seq_open(struct inode *inode, struct file *file)
 764{
 765        return seq_open_net(inode, file, &dev_mc_seq_ops,
 766                            sizeof(struct seq_net_private));
 767}
 768
 769static const struct file_operations dev_mc_seq_fops = {
 770        .owner   = THIS_MODULE,
 771        .open    = dev_mc_seq_open,
 772        .read    = seq_read,
 773        .llseek  = seq_lseek,
 774        .release = seq_release_net,
 775};
 776
 777#endif
 778
 779static int __net_init dev_mc_net_init(struct net *net)
 780{
 781        if (!proc_net_fops_create(net, "dev_mcast", 0, &dev_mc_seq_fops))
 782                return -ENOMEM;
 783        return 0;
 784}
 785
 786static void __net_exit dev_mc_net_exit(struct net *net)
 787{
 788        proc_net_remove(net, "dev_mcast");
 789}
 790
 791static struct pernet_operations __net_initdata dev_mc_net_ops = {
 792        .init = dev_mc_net_init,
 793        .exit = dev_mc_net_exit,
 794};
 795
 796void __init dev_mcast_init(void)
 797{
 798        register_pernet_subsys(&dev_mc_net_ops);
 799}
 800
 801
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.