linux/net/bridge/br_fdb.c
<<
>>
Prefs
   1/*
   2 *      Forwarding database
   3 *      Linux ethernet bridge
   4 *
   5 *      Authors:
   6 *      Lennert Buytenhek               <buytenh@gnu.org>
   7 *
   8 *      This program is free software; you can redistribute it and/or
   9 *      modify it under the terms of the GNU General Public License
  10 *      as published by the Free Software Foundation; either version
  11 *      2 of the License, or (at your option) any later version.
  12 */
  13
  14#include <linux/kernel.h>
  15#include <linux/init.h>
  16#include <linux/rculist.h>
  17#include <linux/spinlock.h>
  18#include <linux/times.h>
  19#include <linux/netdevice.h>
  20#include <linux/etherdevice.h>
  21#include <linux/jhash.h>
  22#include <linux/random.h>
  23#include <linux/slab.h>
  24#include <linux/atomic.h>
  25#include <asm/unaligned.h>
  26#include <linux/if_vlan.h>
  27#include "br_private.h"
  28
  29static struct kmem_cache *br_fdb_cache __read_mostly;
  30static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
  31                      const unsigned char *addr, u16 vid);
  32static void fdb_notify(struct net_bridge *br,
  33                       const struct net_bridge_fdb_entry *, int);
  34
  35static u32 fdb_salt __read_mostly;
  36
  37int __init br_fdb_init(void)
  38{
  39        br_fdb_cache = kmem_cache_create("bridge_fdb_cache",
  40                                         sizeof(struct net_bridge_fdb_entry),
  41                                         0,
  42                                         SLAB_HWCACHE_ALIGN, NULL);
  43        if (!br_fdb_cache)
  44                return -ENOMEM;
  45
  46        get_random_bytes(&fdb_salt, sizeof(fdb_salt));
  47        return 0;
  48}
  49
  50void br_fdb_fini(void)
  51{
  52        kmem_cache_destroy(br_fdb_cache);
  53}
  54
  55
  56/* if topology_changing then use forward_delay (default 15 sec)
  57 * otherwise keep longer (default 5 minutes)
  58 */
  59static inline unsigned long hold_time(const struct net_bridge *br)
  60{
  61        return br->topology_change ? br->forward_delay : br->ageing_time;
  62}
  63
  64static inline int has_expired(const struct net_bridge *br,
  65                                  const struct net_bridge_fdb_entry *fdb)
  66{
  67        return !fdb->is_static &&
  68                time_before_eq(fdb->updated + hold_time(br), jiffies);
  69}
  70
  71static inline int br_mac_hash(const unsigned char *mac, __u16 vid)
  72{
  73        /* use 1 byte of OUI and 3 bytes of NIC */
  74        u32 key = get_unaligned((u32 *)(mac + 2));
  75        return jhash_2words(key, vid, fdb_salt) & (BR_HASH_SIZE - 1);
  76}
  77
  78static void fdb_rcu_free(struct rcu_head *head)
  79{
  80        struct net_bridge_fdb_entry *ent
  81                = container_of(head, struct net_bridge_fdb_entry, rcu);
  82        kmem_cache_free(br_fdb_cache, ent);
  83}
  84
  85static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f)
  86{
  87        hlist_del_rcu(&f->hlist);
  88        fdb_notify(br, f, RTM_DELNEIGH);
  89        call_rcu(&f->rcu, fdb_rcu_free);
  90}
  91
  92void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr)
  93{
  94        struct net_bridge *br = p->br;
  95        bool no_vlan = (nbp_get_vlan_info(p) == NULL) ? true : false;
  96        int i;
  97
  98        spin_lock_bh(&br->hash_lock);
  99
 100        /* Search all chains since old address/hash is unknown */
 101        for (i = 0; i < BR_HASH_SIZE; i++) {
 102                struct hlist_node *h;
 103                hlist_for_each(h, &br->hash[i]) {
 104                        struct net_bridge_fdb_entry *f;
 105
 106                        f = hlist_entry(h, struct net_bridge_fdb_entry, hlist);
 107                        if (f->dst == p && f->is_local) {
 108                                /* maybe another port has same hw addr? */
 109                                struct net_bridge_port *op;
 110                                u16 vid = f->vlan_id;
 111                                list_for_each_entry(op, &br->port_list, list) {
 112                                        if (op != p &&
 113                                            ether_addr_equal(op->dev->dev_addr,
 114                                                             f->addr.addr) &&
 115                                            nbp_vlan_find(op, vid)) {
 116                                                f->dst = op;
 117                                                goto insert;
 118                                        }
 119                                }
 120
 121                                /* delete old one */
 122                                fdb_delete(br, f);
 123insert:
 124                                /* insert new address,  may fail if invalid
 125                                 * address or dup.
 126                                 */
 127                                fdb_insert(br, p, newaddr, vid);
 128
 129                                /* if this port has no vlan information
 130                                 * configured, we can safely be done at
 131                                 * this point.
 132                                 */
 133                                if (no_vlan)
 134                                        goto done;
 135                        }
 136                }
 137        }
 138
 139done:
 140        spin_unlock_bh(&br->hash_lock);
 141}
 142
 143void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
 144{
 145        struct net_bridge_fdb_entry *f;
 146        struct net_port_vlans *pv;
 147        u16 vid = 0;
 148
 149        /* If old entry was unassociated with any port, then delete it. */
 150        f = __br_fdb_get(br, br->dev->dev_addr, 0);
 151        if (f && f->is_local && !f->dst)
 152                fdb_delete(br, f);
 153
 154        fdb_insert(br, NULL, newaddr, 0);
 155
 156        /* Now remove and add entries for every VLAN configured on the
 157         * bridge.  This function runs under RTNL so the bitmap will not
 158         * change from under us.
 159         */
 160        pv = br_get_vlan_info(br);
 161        if (!pv)
 162                return;
 163
 164        for_each_set_bit_from(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
 165                f = __br_fdb_get(br, br->dev->dev_addr, vid);
 166                if (f && f->is_local && !f->dst)
 167                        fdb_delete(br, f);
 168                fdb_insert(br, NULL, newaddr, vid);
 169        }
 170}
 171
 172void br_fdb_cleanup(unsigned long _data)
 173{
 174        struct net_bridge *br = (struct net_bridge *)_data;
 175        unsigned long delay = hold_time(br);
 176        unsigned long next_timer = jiffies + br->ageing_time;
 177        int i;
 178
 179        spin_lock(&br->hash_lock);
 180        for (i = 0; i < BR_HASH_SIZE; i++) {
 181                struct net_bridge_fdb_entry *f;
 182                struct hlist_node *n;
 183
 184                hlist_for_each_entry_safe(f, n, &br->hash[i], hlist) {
 185                        unsigned long this_timer;
 186                        if (f->is_static)
 187                                continue;
 188                        this_timer = f->updated + delay;
 189                        if (time_before_eq(this_timer, jiffies))
 190                                fdb_delete(br, f);
 191                        else if (time_before(this_timer, next_timer))
 192                                next_timer = this_timer;
 193                }
 194        }
 195        spin_unlock(&br->hash_lock);
 196
 197        mod_timer(&br->gc_timer, round_jiffies_up(next_timer));
 198}
 199
 200/* Completely flush all dynamic entries in forwarding database.*/
 201void br_fdb_flush(struct net_bridge *br)
 202{
 203        int i;
 204
 205        spin_lock_bh(&br->hash_lock);
 206        for (i = 0; i < BR_HASH_SIZE; i++) {
 207                struct net_bridge_fdb_entry *f;
 208                struct hlist_node *n;
 209                hlist_for_each_entry_safe(f, n, &br->hash[i], hlist) {
 210                        if (!f->is_static)
 211                                fdb_delete(br, f);
 212                }
 213        }
 214        spin_unlock_bh(&br->hash_lock);
 215}
 216
 217/* Flush all entries referring to a specific port.
 218 * if do_all is set also flush static entries
 219 */
 220void br_fdb_delete_by_port(struct net_bridge *br,
 221                           const struct net_bridge_port *p,
 222                           int do_all)
 223{
 224        int i;
 225
 226        spin_lock_bh(&br->hash_lock);
 227        for (i = 0; i < BR_HASH_SIZE; i++) {
 228                struct hlist_node *h, *g;
 229
 230                hlist_for_each_safe(h, g, &br->hash[i]) {
 231                        struct net_bridge_fdb_entry *f
 232                                = hlist_entry(h, struct net_bridge_fdb_entry, hlist);
 233                        if (f->dst != p)
 234                                continue;
 235
 236                        if (f->is_static && !do_all)
 237                                continue;
 238                        /*
 239                         * if multiple ports all have the same device address
 240                         * then when one port is deleted, assign
 241                         * the local entry to other port
 242                         */
 243                        if (f->is_local) {
 244                                struct net_bridge_port *op;
 245                                list_for_each_entry(op, &br->port_list, list) {
 246                                        if (op != p &&
 247                                            ether_addr_equal(op->dev->dev_addr,
 248                                                             f->addr.addr)) {
 249                                                f->dst = op;
 250                                                goto skip_delete;
 251                                        }
 252                                }
 253                        }
 254
 255                        fdb_delete(br, f);
 256                skip_delete: ;
 257                }
 258        }
 259        spin_unlock_bh(&br->hash_lock);
 260}
 261
 262/* No locking or refcounting, assumes caller has rcu_read_lock */
 263struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br,
 264                                          const unsigned char *addr,
 265                                          __u16 vid)
 266{
 267        struct net_bridge_fdb_entry *fdb;
 268
 269        hlist_for_each_entry_rcu(fdb,
 270                                &br->hash[br_mac_hash(addr, vid)], hlist) {
 271                if (ether_addr_equal(fdb->addr.addr, addr) &&
 272                    fdb->vlan_id == vid) {
 273                        if (unlikely(has_expired(br, fdb)))
 274                                break;
 275                        return fdb;
 276                }
 277        }
 278
 279        return NULL;
 280}
 281
 282#if IS_ENABLED(CONFIG_ATM_LANE)
 283/* Interface used by ATM LANE hook to test
 284 * if an addr is on some other bridge port */
 285int br_fdb_test_addr(struct net_device *dev, unsigned char *addr)
 286{
 287        struct net_bridge_fdb_entry *fdb;
 288        struct net_bridge_port *port;
 289        int ret;
 290
 291        rcu_read_lock();
 292        port = br_port_get_rcu(dev);
 293        if (!port)
 294                ret = 0;
 295        else {
 296                fdb = __br_fdb_get(port->br, addr, 0);
 297                ret = fdb && fdb->dst && fdb->dst->dev != dev &&
 298                        fdb->dst->state == BR_STATE_FORWARDING;
 299        }
 300        rcu_read_unlock();
 301
 302        return ret;
 303}
 304#endif /* CONFIG_ATM_LANE */
 305
 306/*
 307 * Fill buffer with forwarding table records in
 308 * the API format.
 309 */
 310int br_fdb_fillbuf(struct net_bridge *br, void *buf,
 311                   unsigned long maxnum, unsigned long skip)
 312{
 313        struct __fdb_entry *fe = buf;
 314        int i, num = 0;
 315        struct net_bridge_fdb_entry *f;
 316
 317        memset(buf, 0, maxnum*sizeof(struct __fdb_entry));
 318
 319        rcu_read_lock();
 320        for (i = 0; i < BR_HASH_SIZE; i++) {
 321                hlist_for_each_entry_rcu(f, &br->hash[i], hlist) {
 322                        if (num >= maxnum)
 323                                goto out;
 324
 325                        if (has_expired(br, f))
 326                                continue;
 327
 328                        /* ignore pseudo entry for local MAC address */
 329                        if (!f->dst)
 330                                continue;
 331
 332                        if (skip) {
 333                                --skip;
 334                                continue;
 335                        }
 336
 337                        /* convert from internal format to API */
 338                        memcpy(fe->mac_addr, f->addr.addr, ETH_ALEN);
 339
 340                        /* due to ABI compat need to split into hi/lo */
 341                        fe->port_no = f->dst->port_no;
 342                        fe->port_hi = f->dst->port_no >> 8;
 343
 344                        fe->is_local = f->is_local;
 345                        if (!f->is_static)
 346                                fe->ageing_timer_value = jiffies_delta_to_clock_t(jiffies - f->updated);
 347                        ++fe;
 348                        ++num;
 349                }
 350        }
 351
 352 out:
 353        rcu_read_unlock();
 354
 355        return num;
 356}
 357
 358static struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head,
 359                                             const unsigned char *addr,
 360                                             __u16 vid)
 361{
 362        struct net_bridge_fdb_entry *fdb;
 363
 364        hlist_for_each_entry(fdb, head, hlist) {
 365                if (ether_addr_equal(fdb->addr.addr, addr) &&
 366                    fdb->vlan_id == vid)
 367                        return fdb;
 368        }
 369        return NULL;
 370}
 371
 372static struct net_bridge_fdb_entry *fdb_find_rcu(struct hlist_head *head,
 373                                                 const unsigned char *addr,
 374                                                 __u16 vid)
 375{
 376        struct net_bridge_fdb_entry *fdb;
 377
 378        hlist_for_each_entry_rcu(fdb, head, hlist) {
 379                if (ether_addr_equal(fdb->addr.addr, addr) &&
 380                    fdb->vlan_id == vid)
 381                        return fdb;
 382        }
 383        return NULL;
 384}
 385
 386static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head,
 387                                               struct net_bridge_port *source,
 388                                               const unsigned char *addr,
 389                                               __u16 vid)
 390{
 391        struct net_bridge_fdb_entry *fdb;
 392
 393        fdb = kmem_cache_alloc(br_fdb_cache, GFP_ATOMIC);
 394        if (fdb) {
 395                memcpy(fdb->addr.addr, addr, ETH_ALEN);
 396                fdb->dst = source;
 397                fdb->vlan_id = vid;
 398                fdb->is_local = 0;
 399                fdb->is_static = 0;
 400                fdb->updated = fdb->used = jiffies;
 401                hlist_add_head_rcu(&fdb->hlist, head);
 402        }
 403        return fdb;
 404}
 405
 406static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
 407                  const unsigned char *addr, u16 vid)
 408{
 409        struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
 410        struct net_bridge_fdb_entry *fdb;
 411
 412        if (!is_valid_ether_addr(addr))
 413                return -EINVAL;
 414
 415        fdb = fdb_find(head, addr, vid);
 416        if (fdb) {
 417                /* it is okay to have multiple ports with same
 418                 * address, just use the first one.
 419                 */
 420                if (fdb->is_local)
 421                        return 0;
 422                br_warn(br, "adding interface %s with same address "
 423                       "as a received packet\n",
 424                       source ? source->dev->name : br->dev->name);
 425                fdb_delete(br, fdb);
 426        }
 427
 428        fdb = fdb_create(head, source, addr, vid);
 429        if (!fdb)
 430                return -ENOMEM;
 431
 432        fdb->is_local = fdb->is_static = 1;
 433        fdb_notify(br, fdb, RTM_NEWNEIGH);
 434        return 0;
 435}
 436
 437/* Add entry for local address of interface */
 438int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
 439                  const unsigned char *addr, u16 vid)
 440{
 441        int ret;
 442
 443        spin_lock_bh(&br->hash_lock);
 444        ret = fdb_insert(br, source, addr, vid);
 445        spin_unlock_bh(&br->hash_lock);
 446        return ret;
 447}
 448
 449void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
 450                   const unsigned char *addr, u16 vid)
 451{
 452        struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
 453        struct net_bridge_fdb_entry *fdb;
 454
 455        /* some users want to always flood. */
 456        if (hold_time(br) == 0)
 457                return;
 458
 459        /* ignore packets unless we are using this port */
 460        if (!(source->state == BR_STATE_LEARNING ||
 461              source->state == BR_STATE_FORWARDING))
 462                return;
 463
 464        fdb = fdb_find_rcu(head, addr, vid);
 465        if (likely(fdb)) {
 466                /* attempt to update an entry for a local interface */
 467                if (unlikely(fdb->is_local)) {
 468                        if (net_ratelimit())
 469                                br_warn(br, "received packet on %s with "
 470                                        "own address as source address\n",
 471                                        source->dev->name);
 472                } else {
 473                        /* fastpath: update of existing entry */
 474                        fdb->dst = source;
 475                        fdb->updated = jiffies;
 476                }
 477        } else {
 478                spin_lock(&br->hash_lock);
 479                if (likely(!fdb_find(head, addr, vid))) {
 480                        fdb = fdb_create(head, source, addr, vid);
 481                        if (fdb)
 482                                fdb_notify(br, fdb, RTM_NEWNEIGH);
 483                }
 484                /* else  we lose race and someone else inserts
 485                 * it first, don't bother updating
 486                 */
 487                spin_unlock(&br->hash_lock);
 488        }
 489}
 490
 491static int fdb_to_nud(const struct net_bridge_fdb_entry *fdb)
 492{
 493        if (fdb->is_local)
 494                return NUD_PERMANENT;
 495        else if (fdb->is_static)
 496                return NUD_NOARP;
 497        else if (has_expired(fdb->dst->br, fdb))
 498                return NUD_STALE;
 499        else
 500                return NUD_REACHABLE;
 501}
 502
 503static int fdb_fill_info(struct sk_buff *skb, const struct net_bridge *br,
 504                         const struct net_bridge_fdb_entry *fdb,
 505                         u32 portid, u32 seq, int type, unsigned int flags)
 506{
 507        unsigned long now = jiffies;
 508        struct nda_cacheinfo ci;
 509        struct nlmsghdr *nlh;
 510        struct ndmsg *ndm;
 511
 512        nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags);
 513        if (nlh == NULL)
 514                return -EMSGSIZE;
 515
 516        ndm = nlmsg_data(nlh);
 517        ndm->ndm_family  = AF_BRIDGE;
 518        ndm->ndm_pad1    = 0;
 519        ndm->ndm_pad2    = 0;
 520        ndm->ndm_flags   = 0;
 521        ndm->ndm_type    = 0;
 522        ndm->ndm_ifindex = fdb->dst ? fdb->dst->dev->ifindex : br->dev->ifindex;
 523        ndm->ndm_state   = fdb_to_nud(fdb);
 524
 525        if (nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->addr))
 526                goto nla_put_failure;
 527        ci.ndm_used      = jiffies_to_clock_t(now - fdb->used);
 528        ci.ndm_confirmed = 0;
 529        ci.ndm_updated   = jiffies_to_clock_t(now - fdb->updated);
 530        ci.ndm_refcnt    = 0;
 531        if (nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
 532                goto nla_put_failure;
 533
 534        if (nla_put(skb, NDA_VLAN, sizeof(u16), &fdb->vlan_id))
 535                goto nla_put_failure;
 536
 537        return nlmsg_end(skb, nlh);
 538
 539nla_put_failure:
 540        nlmsg_cancel(skb, nlh);
 541        return -EMSGSIZE;
 542}
 543
 544static inline size_t fdb_nlmsg_size(void)
 545{
 546        return NLMSG_ALIGN(sizeof(struct ndmsg))
 547                + nla_total_size(ETH_ALEN) /* NDA_LLADDR */
 548                + nla_total_size(sizeof(u16)) /* NDA_VLAN */
 549                + nla_total_size(sizeof(struct nda_cacheinfo));
 550}
 551
 552static void fdb_notify(struct net_bridge *br,
 553                       const struct net_bridge_fdb_entry *fdb, int type)
 554{
 555        struct net *net = dev_net(br->dev);
 556        struct sk_buff *skb;
 557        int err = -ENOBUFS;
 558
 559        skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC);
 560        if (skb == NULL)
 561                goto errout;
 562
 563        err = fdb_fill_info(skb, br, fdb, 0, 0, type, 0);
 564        if (err < 0) {
 565                /* -EMSGSIZE implies BUG in fdb_nlmsg_size() */
 566                WARN_ON(err == -EMSGSIZE);
 567                kfree_skb(skb);
 568                goto errout;
 569        }
 570        rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
 571        return;
 572errout:
 573        if (err < 0)
 574                rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
 575}
 576
 577/* Dump information about entries, in response to GETNEIGH */
 578int br_fdb_dump(struct sk_buff *skb,
 579                struct netlink_callback *cb,
 580                struct net_device *dev,
 581                int idx)
 582{
 583        struct net_bridge *br = netdev_priv(dev);
 584        int i;
 585
 586        if (!(dev->priv_flags & IFF_EBRIDGE))
 587                goto out;
 588
 589        for (i = 0; i < BR_HASH_SIZE; i++) {
 590                struct net_bridge_fdb_entry *f;
 591
 592                hlist_for_each_entry_rcu(f, &br->hash[i], hlist) {
 593                        if (idx < cb->args[0])
 594                                goto skip;
 595
 596                        if (fdb_fill_info(skb, br, f,
 597                                          NETLINK_CB(cb->skb).portid,
 598                                          cb->nlh->nlmsg_seq,
 599                                          RTM_NEWNEIGH,
 600                                          NLM_F_MULTI) < 0)
 601                                break;
 602skip:
 603                        ++idx;
 604                }
 605        }
 606
 607out:
 608        return idx;
 609}
 610
 611/* Update (create or replace) forwarding database entry */
 612static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr,
 613                         __u16 state, __u16 flags, __u16 vid)
 614{
 615        struct net_bridge *br = source->br;
 616        struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
 617        struct net_bridge_fdb_entry *fdb;
 618        bool modified = false;
 619
 620        fdb = fdb_find(head, addr, vid);
 621        if (fdb == NULL) {
 622                if (!(flags & NLM_F_CREATE))
 623                        return -ENOENT;
 624
 625                fdb = fdb_create(head, source, addr, vid);
 626                if (!fdb)
 627                        return -ENOMEM;
 628
 629                modified = true;
 630        } else {
 631                if (flags & NLM_F_EXCL)
 632                        return -EEXIST;
 633
 634                if (fdb->dst != source) {
 635                        fdb->dst = source;
 636                        modified = true;
 637                }
 638        }
 639
 640        if (fdb_to_nud(fdb) != state) {
 641                if (state & NUD_PERMANENT)
 642                        fdb->is_local = fdb->is_static = 1;
 643                else if (state & NUD_NOARP) {
 644                        fdb->is_local = 0;
 645                        fdb->is_static = 1;
 646                } else
 647                        fdb->is_local = fdb->is_static = 0;
 648
 649                modified = true;
 650        }
 651
 652        fdb->used = jiffies;
 653        if (modified) {
 654                fdb->updated = jiffies;
 655                fdb_notify(br, fdb, RTM_NEWNEIGH);
 656        }
 657
 658        return 0;
 659}
 660
 661static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge_port *p,
 662               const unsigned char *addr, u16 nlh_flags, u16 vid)
 663{
 664        int err = 0;
 665
 666        if (ndm->ndm_flags & NTF_USE) {
 667                rcu_read_lock();
 668                br_fdb_update(p->br, p, addr, vid);
 669                rcu_read_unlock();
 670        } else {
 671                spin_lock_bh(&p->br->hash_lock);
 672                err = fdb_add_entry(p, addr, ndm->ndm_state,
 673                                    nlh_flags, vid);
 674                spin_unlock_bh(&p->br->hash_lock);
 675        }
 676
 677        return err;
 678}
 679
 680/* Add new permanent fdb entry with RTM_NEWNEIGH */
 681int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 682               struct net_device *dev,
 683               const unsigned char *addr, u16 nlh_flags)
 684{
 685        struct net_bridge_port *p;
 686        int err = 0;
 687        struct net_port_vlans *pv;
 688        unsigned short vid = VLAN_N_VID;
 689
 690        if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE))) {
 691                pr_info("bridge: RTM_NEWNEIGH with invalid state %#x\n", ndm->ndm_state);
 692                return -EINVAL;
 693        }
 694
 695        if (tb[NDA_VLAN]) {
 696                if (nla_len(tb[NDA_VLAN]) != sizeof(unsigned short)) {
 697                        pr_info("bridge: RTM_NEWNEIGH with invalid vlan\n");
 698                        return -EINVAL;
 699                }
 700
 701                vid = nla_get_u16(tb[NDA_VLAN]);
 702
 703                if (vid >= VLAN_N_VID) {
 704                        pr_info("bridge: RTM_NEWNEIGH with invalid vlan id %d\n",
 705                                vid);
 706                        return -EINVAL;
 707                }
 708        }
 709
 710        p = br_port_get_rtnl(dev);
 711        if (p == NULL) {
 712                pr_info("bridge: RTM_NEWNEIGH %s not a bridge port\n",
 713                        dev->name);
 714                return -EINVAL;
 715        }
 716
 717        pv = nbp_get_vlan_info(p);
 718        if (vid != VLAN_N_VID) {
 719                if (!pv || !test_bit(vid, pv->vlan_bitmap)) {
 720                        pr_info("bridge: RTM_NEWNEIGH with unconfigured "
 721                                "vlan %d on port %s\n", vid, dev->name);
 722                        return -EINVAL;
 723                }
 724
 725                /* VID was specified, so use it. */
 726                err = __br_fdb_add(ndm, p, addr, nlh_flags, vid);
 727        } else {
 728                if (!pv || bitmap_empty(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN)) {
 729                        err = __br_fdb_add(ndm, p, addr, nlh_flags, 0);
 730                        goto out;
 731                }
 732
 733                /* We have vlans configured on this port and user didn't
 734                 * specify a VLAN.  To be nice, add/update entry for every
 735                 * vlan on this port.
 736                 */
 737                for_each_set_bit(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
 738                        err = __br_fdb_add(ndm, p, addr, nlh_flags, vid);
 739                        if (err)
 740                                goto out;
 741                }
 742        }
 743
 744out:
 745        return err;
 746}
 747
 748int fdb_delete_by_addr(struct net_bridge *br, const u8 *addr,
 749                       u16 vlan)
 750{
 751        struct hlist_head *head = &br->hash[br_mac_hash(addr, vlan)];
 752        struct net_bridge_fdb_entry *fdb;
 753
 754        fdb = fdb_find(head, addr, vlan);
 755        if (!fdb)
 756                return -ENOENT;
 757
 758        fdb_delete(br, fdb);
 759        return 0;
 760}
 761
 762static int __br_fdb_delete(struct net_bridge_port *p,
 763                           const unsigned char *addr, u16 vid)
 764{
 765        int err;
 766
 767        spin_lock_bh(&p->br->hash_lock);
 768        err = fdb_delete_by_addr(p->br, addr, vid);
 769        spin_unlock_bh(&p->br->hash_lock);
 770
 771        return err;
 772}
 773
 774/* Remove neighbor entry with RTM_DELNEIGH */
 775int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
 776                  struct net_device *dev,
 777                  const unsigned char *addr)
 778{
 779        struct net_bridge_port *p;
 780        int err;
 781        struct net_port_vlans *pv;
 782        unsigned short vid = VLAN_N_VID;
 783
 784        if (tb[NDA_VLAN]) {
 785                if (nla_len(tb[NDA_VLAN]) != sizeof(unsigned short)) {
 786                        pr_info("bridge: RTM_NEWNEIGH with invalid vlan\n");
 787                        return -EINVAL;
 788                }
 789
 790                vid = nla_get_u16(tb[NDA_VLAN]);
 791
 792                if (vid >= VLAN_N_VID) {
 793                        pr_info("bridge: RTM_NEWNEIGH with invalid vlan id %d\n",
 794                                vid);
 795                        return -EINVAL;
 796                }
 797        }
 798        p = br_port_get_rtnl(dev);
 799        if (p == NULL) {
 800                pr_info("bridge: RTM_DELNEIGH %s not a bridge port\n",
 801                        dev->name);
 802                return -EINVAL;
 803        }
 804
 805        pv = nbp_get_vlan_info(p);
 806        if (vid != VLAN_N_VID) {
 807                if (!pv || !test_bit(vid, pv->vlan_bitmap)) {
 808                        pr_info("bridge: RTM_DELNEIGH with unconfigured "
 809                                "vlan %d on port %s\n", vid, dev->name);
 810                        return -EINVAL;
 811                }
 812
 813                err = __br_fdb_delete(p, addr, vid);
 814        } else {
 815                if (!pv || bitmap_empty(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN)) {
 816                        err = __br_fdb_delete(p, addr, 0);
 817                        goto out;
 818                }
 819
 820                /* We have vlans configured on this port and user didn't
 821                 * specify a VLAN.  To be nice, add/update entry for every
 822                 * vlan on this port.
 823                 */
 824                err = -ENOENT;
 825                for_each_set_bit(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
 826                        err &= __br_fdb_delete(p, addr, vid);
 827                }
 828        }
 829out:
 830        return err;
 831}
 832