4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * CDDL HEADER START
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * The contents of this file are subject to the terms of the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Common Development and Distribution License (the "License").
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * You may not use this file except in compliance with the License.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * or http://www.opensolaris.org/os/licensing.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * See the License for the specific language governing permissions
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * and limitations under the License.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * When distributing Covered Code, include this CDDL HEADER in each
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If applicable, add the following below this CDDL HEADER, with the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * fields enclosed by brackets "[]" replaced with your own identifying
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * information: Portions Copyright [yyyy] [name of copyright owner]
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * CDDL HEADER END
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Use is subject to license terms.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This module implements a STREAMS driver that provides layer-two (Ethernet)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridging functionality. The STREAMS interface is used to provide
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * observability (snoop/wireshark) and control, but not for interface plumbing.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/types.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/bitmap.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/cmn_err.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/conf.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/ddi.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/errno.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/kstat.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/modctl.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/note.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/param.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/policy.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/sdt.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/stat.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/stream.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/stropts.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/strsun.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/sunddi.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/sysmacros.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/systm.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/time.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/dlpi.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/dls.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/mac_ether.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/mac_provider.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/mac_client_priv.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/mac_impl.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/vlan.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <net/bridge.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <net/bridge_impl.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <net/trill.h>
56a3cd3dcb3f5ee44668549e9ca623a435558fcdRishi Srivatsavai#include <sys/dld_ioc.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Locks and reference counts: object lifetime and design.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridge_mac_t
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Bridge mac (snoop) instances are in bmac_list, which is protected by
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bmac_rwlock. They're allocated by bmac_alloc and freed by bridge_timer().
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Every bridge_inst_t has a single bridge_mac_t, but when bridge_inst_t goes
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * away, the bridge_mac_t remains until either all of the users go away
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * (detected by a timer) or until the instance is picked up again by the same
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridge starting back up.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridge_inst_t
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Bridge instances are in inst_list, which is protected by inst_lock.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * They're allocated by inst_alloc() and freed by inst_free(). After
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * allocation, an instance is placed in inst_list, and the reference count is
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * incremented to represent this. That reference is decremented when the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * BIF_SHUTDOWN flag is set, and no new increments may occur. When the last
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * reference is freed, the instance is removed from the list.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Bridge instances have lists of links and an AVL tree of forwarding
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * entries. Each of these structures holds one reference on the bridge
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * instance. These lists and tree are protected by bi_rwlock.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridge_stream_t
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Bridge streams are allocated by stream_alloc() and freed by stream_free().
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * These streams are created when "bridged" opens /dev/bridgectl, and are
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * used to create new bridge instances (via BRIOC_NEWBRIDGE) and control the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * links on the bridge. When a stream closes, the bridge instance created is
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * destroyed. There's at most one bridge instance for a given control
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * stream.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridge_link_t
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Links are allocated by bridge_add_link() and freed by link_free(). The
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bi_links list holds a reference to the link. When the BLF_DELETED flag is
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * set, that reference is dropped. The link isn't removed from the list
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * until the last reference drops. Each forwarding entry that uses a given
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * link holds a reference, as does each thread transmitting a packet via the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * link. The MAC layer calls in via bridge_ref_cb() to hold a reference on
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * a link when transmitting.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * It's important that once BLF_DELETED is set, there's no way for the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * reference count to increase again. If it can, then the link may be
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * double-freed. The BLF_FREED flag is intended for use with assertions to
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * guard against this in testing.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridge_fwd_t
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Bridge forwarding entries are allocated by bridge_recv_cb() and freed by
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * fwd_free(). The bi_fwd AVL tree holds one reference to the entry. Unlike
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * other data structures, the reference is dropped when the entry is removed
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * from the tree by fwd_delete(), and the BFF_INTREE flag is removed. Each
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * thread that's forwarding a packet to a known destination holds a reference
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * to a forwarding entry.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * TRILL notes:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * The TRILL module does all of its I/O through bridging. It uses references
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * on the bridge_inst_t and bridge_link_t structures, and has seven entry
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * points and four callbacks. One entry point is for setting the callbacks
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * (bridge_trill_register_cb). There are four entry points for taking bridge
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * and link references (bridge_trill_{br,ln}{ref,unref}). The final two
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * entry points are for decapsulated packets from TRILL (bridge_trill_decaps)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * that need to be bridged locally, and for TRILL-encapsulated output packets
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * (bridge_trill_output).
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * The four callbacks comprise two notification functions for bridges and
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * links being deleted, one function for raw received TRILL packets, and one
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * for bridge output to non-local TRILL destinations (tunnel entry).
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Ethernet reserved multicast addresses for TRILL; used also in TRILL module.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiconst uint8_t all_isis_rbridges[] = ALL_ISIS_RBRIDGES;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic const uint8_t all_esadi_rbridges[] = ALL_ESADI_RBRIDGES;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiconst uint8_t bridge_group_address[] = BRIDGE_GROUP_ADDRESS;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic const char *inst_kstats_list[] = { KSINST_NAMES };
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic const char *link_kstats_list[] = { KSLINK_NAMES };
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#define KREF(p, m, vn) p->m.vn.value.ui64
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#define KINCR(p, m, vn) ++KREF(p, m, vn)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#define KDECR(p, m, vn) --KREF(p, m, vn)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#define KIPINCR(p, vn) KINCR(p, bi_kstats, vn)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#define KIPDECR(p, vn) KDECR(p, bi_kstats, vn)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#define KLPINCR(p, vn) KINCR(p, bl_kstats, vn)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#define KIINCR(vn) KIPINCR(bip, vn)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#define KIDECR(vn) KIPDECR(bip, vn)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#define KLINCR(vn) KLPINCR(blp, vn)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#define Dim(x) (sizeof (x) / sizeof (*(x)))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* Amount of overhead added when encapsulating with VLAN headers */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#define VLAN_INCR (sizeof (struct ether_vlan_header) - \
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (struct ether_header))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic dev_info_t *bridge_dev_info;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic major_t bridge_major;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic ddi_taskq_t *bridge_taskq;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * These are the bridge instance management data structures. The mutex lock
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * protects the list of bridge instances. A reference count is then used on
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * each instance to determine when to free it. We use mac_minor_hold() to
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * allocate minor_t values, which are used both for self-cloning /dev/net/
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * device nodes as well as client streams. Minor node 0 is reserved for the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * allocation control node.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic list_t inst_list;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic kcondvar_t inst_cv; /* Allows us to wait for shutdown */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic kmutex_t inst_lock;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic krwlock_t bmac_rwlock;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic list_t bmac_list;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* Wait for taskq entries that use STREAMS */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic kcondvar_t stream_ref_cv;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic kmutex_t stream_ref_lock;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic timeout_id_t bridge_timerid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic clock_t bridge_scan_interval;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic clock_t bridge_fwd_age;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic bridge_inst_t *bridge_find_name(const char *);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void bridge_timer(void *);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void bridge_unref(bridge_inst_t *);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic const uint8_t zero_addr[ETHERADDRL] = { 0 };
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* Global TRILL linkage */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic trill_recv_pkt_t trill_recv_fn;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic trill_encap_pkt_t trill_encap_fn;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic trill_br_dstr_t trill_brdstr_fn;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic trill_ln_dstr_t trill_lndstr_fn;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* special settings to accommodate DLD flow control; see dld_str.c */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic struct module_info bridge_dld_modinfo = {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai 0, /* mi_idnum */
f2905fb789fa42069fdb0ba5bd1b61400e23f348Rishi Srivatsavai BRIDGE_DEV_NAME, /* mi_idname */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai 0, /* mi_minpsz */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai INFPSZ, /* mi_maxpsz */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai 1, /* mi_hiwat */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai 0 /* mi_lowat */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai};
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic struct qinit bridge_dld_rinit = {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, /* qi_putp */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, /* qi_srvp */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dld_open, /* qi_qopen */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dld_close, /* qi_qclose */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, /* qi_qadmin */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai &bridge_dld_modinfo, /* qi_minfo */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL /* qi_mstat */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai};
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic struct qinit bridge_dld_winit = {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (int (*)())dld_wput, /* qi_putp */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (int (*)())dld_wsrv, /* qi_srvp */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, /* qi_qopen */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, /* qi_qclose */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, /* qi_qadmin */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai &bridge_dld_modinfo, /* qi_minfo */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL /* qi_mstat */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai};
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int bridge_ioc_listfwd(void *, intptr_t, int, cred_t *, int *);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* GLDv3 control ioctls used by Bridging */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic dld_ioc_info_t bridge_ioc_list[] = {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai {BRIDGE_IOC_LISTFWD, DLDCOPYINOUT, sizeof (bridge_listfwd_t),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_ioc_listfwd, NULL},
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai};
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Given a bridge mac pointer, get a ref-held pointer to the corresponding
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridge instance, if any. We must hold the global bmac_rwlock so that
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bm_inst doesn't slide out from under us.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic bridge_inst_t *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaimac_to_inst(const bridge_mac_t *bmp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bmac_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((bip = bmp->bm_inst) != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai atomic_inc_uint(&bip->bi_refs);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bmac_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (bip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavailink_sdu_fail(bridge_link_t *blp, boolean_t failed, mblk_t **mlist)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mblk_t *mp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_ctl_t *bcp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_link_t *blcmp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_mac_t *bmp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (failed) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_flags & BLF_SDUFAIL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_flags |= BLF_SDUFAIL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!(blp->bl_flags & BLF_SDUFAIL))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_flags &= ~BLF_SDUFAIL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If this link is otherwise up, then check if there are any other
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * non-failed non-down links. If not, then we control the state of the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * whole bridge.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip = blp->bl_inst;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmp = bip->bi_mac;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_linkstate != LINK_STATE_DOWN) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (blcmp = list_head(&bip->bi_links); blcmp != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blcmp = list_next(&bip->bi_links, blcmp)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp != blcmp &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai !(blcmp->bl_flags & (BLF_DELETED|BLF_SDUFAIL)) &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blcmp->bl_linkstate != LINK_STATE_DOWN)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blcmp == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmp->bm_linkstate = failed ? LINK_STATE_DOWN :
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai LINK_STATE_UP;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_link_redo(bmp->bm_mh, bmp->bm_linkstate);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If we're becoming failed, then the link's current true state needs
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * to be reflected upwards to this link's clients. If we're becoming
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * unfailed, then we get the state of the bridge instead on all
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * clients.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (failed) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bmp->bm_linkstate != blp->bl_linkstate)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_link_redo(blp->bl_mh, blp->bl_linkstate);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_link_redo(blp->bl_mh, bmp->bm_linkstate);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* get the current mblk we're going to send up */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((mp = blp->bl_lfailmp) == NULL &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (mp = allocb(sizeof (bridge_ctl_t), BPRI_MED)) == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* get a new one for next time */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_lfailmp = allocb(sizeof (bridge_ctl_t), BPRI_MED);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* if none for next time, then report only failures */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_lfailmp == NULL && !failed) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_lfailmp = mp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bcp = (bridge_ctl_t *)mp->b_rptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bcp->bc_linkid = blp->bl_linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bcp->bc_failed = failed;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_wptr = (uchar_t *)(bcp + 1);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_next = *mlist;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *mlist = mp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Send control messages (link SDU changes) using the stream to the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridge instance daemon.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaisend_up_messages(bridge_inst_t *bip, mblk_t *mp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mblk_t *mnext;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai queue_t *rq;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rq = bip->bi_control->bs_wq;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rq = OTHERQ(rq);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while (mp != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mnext = mp->b_next;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_next = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai putnext(rq, mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp = mnext;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* ARGSUSED */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_m_getstat(void *arg, uint_t stat, uint64_t *val)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (ENOTSUP);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_m_start(void *arg)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_mac_t *bmp = arg;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmp->bm_flags |= BMF_STARTED;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_m_stop(void *arg)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_mac_t *bmp = arg;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmp->bm_flags &= ~BMF_STARTED;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* ARGSUSED */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_m_setpromisc(void *arg, boolean_t on)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* ARGSUSED */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* ARGSUSED */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_m_unicst(void *arg, const uint8_t *macaddr)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (ENOTSUP);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic mblk_t *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_m_tx(void *arg, mblk_t *mp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai _NOTE(ARGUNUSED(arg));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsgchain(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* ARGSUSED */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_ioc_listfwd(void *karg, intptr_t arg, int mode, cred_t *cred, int *rvalp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_listfwd_t *blf = karg;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_fwd_t *bfp, match;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_index_t where;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip = bridge_find_name(blf->blf_name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bip == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (ENOENT);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bcopy(blf->blf_dest, match.bf_dest, ETHERADDRL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai match.bf_flags |= BFF_VLANLOCAL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((bfp = avl_find(&bip->bi_fwd, &match, &where)) == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp = avl_nearest(&bip->bi_fwd, where, AVL_AFTER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp = AVL_NEXT(&bip->bi_fwd, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bzero(blf, sizeof (*blf));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bcopy(bfp->bf_dest, blf->blf_dest, ETHERADDRL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blf->blf_trill_nick = bfp->bf_trill_nick;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blf->blf_ms_age =
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drv_hztousec(ddi_get_lbolt() - bfp->bf_lastheard) / 1000;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blf->blf_is_local =
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (bfp->bf_flags & BFF_LOCALADDR) != 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blf->blf_linkid = bfp->bf_links[0]->bl_linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_unref(bip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint_t pr_valsize, const void *pr_val)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_mac_t *bmp = arg;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_link_t *blp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int err;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint_t maxsdu;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mblk_t *mlist;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai _NOTE(ARGUNUSED(pr_name));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai switch (pr_num) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case MAC_PROP_MTU:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (pr_valsize < sizeof (bmp->bm_maxsdu)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai err = EINVAL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) bcopy(pr_val, &maxsdu, sizeof (maxsdu));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (maxsdu == bmp->bm_maxsdu) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai err = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else if ((bip = mac_to_inst(bmp)) == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai err = ENXIO;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mlist = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (blp = list_head(&bip->bi_links); blp != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp = list_next(&bip->bi_links, blp)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_flags & BLF_DELETED)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_maxsdu == maxsdu)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai link_sdu_fail(blp, B_FALSE, &mlist);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else if (blp->bl_maxsdu == bmp->bm_maxsdu)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai link_sdu_fail(blp, B_TRUE, &mlist);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmp->bm_maxsdu = maxsdu;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) mac_maxsdu_update(bmp->bm_mh, maxsdu);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai send_up_messages(bip, mlist);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_unref(bip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai err = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai default:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai err = ENOTSUP;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (err);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer uint_t pr_valsize, void *pr_val)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_mac_t *bmp = arg;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int err = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai _NOTE(ARGUNUSED(pr_name));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai switch (pr_num) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case MAC_PROP_STATUS:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ASSERT(pr_valsize >= sizeof (bmp->bm_linkstate));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer bcopy(&bmp->bm_linkstate, pr_val, sizeof (&bmp->bm_linkstate));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai default:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai err = ENOTSUP;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (err);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerbridge_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_handle_t prh)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer bridge_mac_t *bmp = arg;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer _NOTE(ARGUNUSED(pr_name));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer switch (pr_num) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_MTU:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_set_range_uint32(prh, bmp->bm_maxsdu,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer bmp->bm_maxsdu);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_STATUS:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic mac_callbacks_t bridge_m_callbacks = {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MC_SETPROP | MC_GETPROP | MC_PROPINFO,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_m_getstat,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_m_start,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_m_stop,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_m_setpromisc,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_m_multicst,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_m_unicst,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_m_tx,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer NULL, /* reserved */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, /* ioctl */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, /* getcapab */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, /* open */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, /* close */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_m_setprop,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer bridge_m_getprop,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer bridge_m_propinfo
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai};
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Create kstats from a list.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic kstat_t *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaikstat_setup(kstat_named_t *knt, const char **names, int nstat,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai const char *unitname)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kstat_t *ksp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int i;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (i = 0; i < nstat; i++)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kstat_named_init(&knt[i], names[i], KSTAT_DATA_UINT64);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
f2905fb789fa42069fdb0ba5bd1b61400e23f348Rishi Srivatsavai ksp = kstat_create_zone(BRIDGE_DEV_NAME, 0, unitname, "net",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSTAT_TYPE_NAMED, nstat, KSTAT_FLAG_VIRTUAL, GLOBAL_ZONEID);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (ksp != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ksp->ks_data = knt;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kstat_install(ksp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (ksp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Find an existing bridge_mac_t structure or allocate a new one for the given
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridge instance. This creates the mac driver instance that snoop can use.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibmac_alloc(bridge_inst_t *bip, bridge_mac_t **bmacp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_mac_t *bmp, *bnew;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_register_t *mac;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int err;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *bmacp = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((mac = mac_alloc(MAC_VERSION)) == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EINVAL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bnew = kmem_zalloc(sizeof (*bnew), KM_SLEEP);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bmac_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (bmp = list_head(&bmac_list); bmp != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmp = list_next(&bmac_list, bmp)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (strcmp(bip->bi_name, bmp->bm_name) == 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(bmp->bm_inst == NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmp->bm_inst = bip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bmac_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kmem_free(bnew, sizeof (*bnew));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_free(mac);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *bmacp = bmp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac->m_driver = bnew;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac->m_dip = bridge_dev_info;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac->m_instance = (uint_t)-1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac->m_src_addr = (uint8_t *)zero_addr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac->m_callbacks = &bridge_m_callbacks;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Note that the SDU limits are irrelevant, as nobody transmits on the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridge node itself. It's mainly for monitoring but we allow
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * setting the bridge MTU for quick transition of all links part of the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridge to a new MTU.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac->m_min_sdu = 1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac->m_max_sdu = 1500;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai err = mac_register(mac, &bnew->bm_mh);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_free(mac);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (err != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bmac_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kmem_free(bnew, sizeof (*bnew));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (err);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bnew->bm_inst = bip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) strcpy(bnew->bm_name, bip->bi_name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (list_is_empty(&bmac_list)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_timerid = timeout(bridge_timer, NULL,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_scan_interval);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai list_insert_tail(&bmac_list, bnew);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bmac_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Mark the MAC as unable to go "active" so that only passive clients
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * (such as snoop) can bind to it.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_no_active(bnew->bm_mh);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *bmacp = bnew;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Disconnect the given bridge_mac_t from its bridge instance. The bridge
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * instance is going away. The mac instance can't go away until the clients
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * are gone (see bridge_timer).
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibmac_disconnect(bridge_mac_t *bmp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmp->bm_linkstate = LINK_STATE_DOWN;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_link_redo(bmp->bm_mh, LINK_STATE_DOWN);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bmac_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip = bmp->bm_inst;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip->bi_mac = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmp->bm_inst = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bmac_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* This is used by the avl trees to sort forwarding table entries */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaifwd_compare(const void *addr1, const void *addr2)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai const bridge_fwd_t *fwd1 = addr1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai const bridge_fwd_t *fwd2 = addr2;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int diff = memcmp(fwd1->bf_dest, fwd2->bf_dest, ETHERADDRL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (diff != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (diff > 0 ? 1 : -1);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((fwd1->bf_flags ^ fwd2->bf_flags) & BFF_VLANLOCAL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (fwd1->bf_vlanid > fwd2->bf_vlanid)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (1);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else if (fwd1->bf_vlanid < fwd2->bf_vlanid)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (-1);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiinst_free(bridge_inst_t *bip)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(bip->bi_mac == NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_destroy(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai list_destroy(&bip->bi_links);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_destroy(&bip->bi_linkwait);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_destroy(&bip->bi_fwd);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bip->bi_ksp != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kstat_delete(bip->bi_ksp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kmem_free(bip, sizeof (*bip));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic bridge_inst_t *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiinst_alloc(const char *bridge)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip = kmem_zalloc(sizeof (*bip), KM_SLEEP);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip->bi_refs = 1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) strcpy(bip->bi_name, bridge);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_init(&bip->bi_rwlock, NULL, RW_DRIVER, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai list_create(&bip->bi_links, sizeof (bridge_link_t),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai offsetof(bridge_link_t, bl_node));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_init(&bip->bi_linkwait, NULL, CV_DRIVER, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_create(&bip->bi_fwd, fwd_compare, sizeof (bridge_fwd_t),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai offsetof(bridge_fwd_t, bf_node));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (bip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic bridge_inst_t *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_find_name(const char *bridge)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&inst_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (bip = list_head(&inst_list); bip != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip = list_next(&inst_list, bip)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!(bip->bi_flags & BIF_SHUTDOWN) &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai strcmp(bridge, bip->bi_name) == 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai atomic_inc_uint(&bip->bi_refs);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&inst_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (bip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roybridge_create(datalink_id_t linkid, const char *bridge, bridge_inst_t **bipc,
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy cred_t *cred)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip, *bipnew;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_mac_t *bmp = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int err;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *bipc = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bipnew = inst_alloc(bridge);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&inst_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavailookup_retry:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (bip = list_head(&inst_list); bip != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip = list_next(&inst_list, bip)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (strcmp(bridge, bip->bi_name) == 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* This should not take long; if it does, we've got a design problem */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bip != NULL && (bip->bi_flags & BIF_SHUTDOWN)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_wait(&inst_cv, &inst_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto lookup_retry;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
f2905fb789fa42069fdb0ba5bd1b61400e23f348Rishi Srivatsavai if (bip == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip = bipnew;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bipnew = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai list_insert_tail(&inst_list, bip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&inst_lock);
f2905fb789fa42069fdb0ba5bd1b61400e23f348Rishi Srivatsavai if (bipnew != NULL) {
f2905fb789fa42069fdb0ba5bd1b61400e23f348Rishi Srivatsavai inst_free(bipnew);
f2905fb789fa42069fdb0ba5bd1b61400e23f348Rishi Srivatsavai return (EEXIST);
f2905fb789fa42069fdb0ba5bd1b61400e23f348Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip->bi_ksp = kstat_setup((kstat_named_t *)&bip->bi_kstats,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai inst_kstats_list, Dim(inst_kstats_list), bip->bi_name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai err = bmac_alloc(bip, &bmp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((bip->bi_mac = bmp) == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail_create;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bm_inst is set, so the timer cannot yank the DLS rug from under us.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * No extra locking is needed here.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!(bmp->bm_flags & BMF_DLS)) {
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy err = dls_devnet_create(bmp->bm_mh, linkid, crgetzoneid(cred));
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy if (err != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail_create;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmp->bm_flags |= BMF_DLS;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip->bi_dev = makedevice(bridge_major, mac_minor(bmp->bm_mh));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *bipc = bip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaifail_create:
f2905fb789fa42069fdb0ba5bd1b61400e23f348Rishi Srivatsavai ASSERT(bip->bi_trilldata == NULL);
f2905fb789fa42069fdb0ba5bd1b61400e23f348Rishi Srivatsavai bip->bi_flags |= BIF_SHUTDOWN;
f2905fb789fa42069fdb0ba5bd1b61400e23f348Rishi Srivatsavai bridge_unref(bip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (err);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_unref(bridge_inst_t *bip)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (atomic_dec_uint_nv(&bip->bi_refs) == 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(bip->bi_flags & BIF_SHUTDOWN);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* free up mac for reuse before leaving global list */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bip->bi_mac != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmac_disconnect(bip->bi_mac);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&inst_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai list_remove(&inst_list, bip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_broadcast(&inst_cv);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&inst_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai inst_free(bip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Stream instances are used only for allocating bridges and serving as a
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * control node. They serve no data-handling function.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic bridge_stream_t *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistream_alloc(void)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_stream_t *bsp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai minor_t mn;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((mn = mac_minor_hold(B_FALSE)) == 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bsp = kmem_zalloc(sizeof (*bsp), KM_SLEEP);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bsp->bs_minor = mn;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (bsp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistream_free(bridge_stream_t *bsp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_minor_rele(bsp->bs_minor);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kmem_free(bsp, sizeof (*bsp));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* Reference hold/release functions for STREAMS-related taskq */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistream_ref(bridge_stream_t *bsp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&stream_ref_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bsp->bs_taskq_cnt++;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&stream_ref_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistream_unref(bridge_stream_t *bsp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&stream_ref_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (--bsp->bs_taskq_cnt == 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_broadcast(&stream_ref_cv);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&stream_ref_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavailink_free(bridge_link_t *blp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip = blp->bl_inst;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(!(blp->bl_flags & BLF_FREED));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_flags |= BLF_FREED;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_ksp != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kstat_delete(blp->bl_ksp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_lfailmp != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freeb(blp->bl_lfailmp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_destroy(&blp->bl_trillwait);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_destroy(&blp->bl_trilllock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kmem_free(blp, sizeof (*blp));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Don't unreference the bridge until the MAC is closed */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_unref(bip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavailink_unref(bridge_link_t *blp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (atomic_dec_uint_nv(&blp->bl_refs) == 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip = blp->bl_inst;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(blp->bl_flags & BLF_DELETED);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_WRITER);
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai if (blp->bl_flags & BLF_LINK_ADDED)
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai list_remove(&bip->bi_links, blp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bip->bi_trilldata != NULL && list_is_empty(&bip->bi_links))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_broadcast(&bip->bi_linkwait);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai link_free(blp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic bridge_fwd_t *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaifwd_alloc(const uint8_t *addr, uint_t nlinks, uint16_t nick)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_fwd_t *bfp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp = kmem_zalloc(sizeof (*bfp) + (nlinks * sizeof (bridge_link_t *)),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KM_NOSLEEP);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bcopy(addr, bfp->bf_dest, ETHERADDRL);
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni bfp->bf_lastheard = ddi_get_lbolt();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp->bf_maxlinks = nlinks;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp->bf_links = (bridge_link_t **)(bfp + 1);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp->bf_trill_nick = nick;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic bridge_fwd_t *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaifwd_find(bridge_inst_t *bip, const uint8_t *addr, uint16_t vlanid)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_fwd_t *bfp, *vbfp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_fwd_t match;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bcopy(addr, match.bf_dest, ETHERADDRL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai match.bf_flags = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((bfp = avl_find(&bip->bi_fwd, &match, NULL)) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp->bf_vlanid != vlanid && bfp->bf_vcnt > 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai match.bf_vlanid = vlanid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai match.bf_flags = BFF_VLANLOCAL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai vbfp = avl_find(&bip->bi_fwd, &match, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (vbfp != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp = vbfp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai atomic_inc_uint(&bfp->bf_refs);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaifwd_free(bridge_fwd_t *bfp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint_t i;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip = bfp->bf_links[0]->bl_inst;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KIDECR(bki_count);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (i = 0; i < bfp->bf_nlinks; i++)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai link_unref(bfp->bf_links[i]);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kmem_free(bfp,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (*bfp) + bfp->bf_maxlinks * sizeof (bridge_link_t *));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaifwd_unref(bridge_fwd_t *bfp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (atomic_dec_uint_nv(&bfp->bf_refs) == 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(!(bfp->bf_flags & BFF_INTREE));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_free(bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaifwd_delete(bridge_fwd_t *bfp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_fwd_t *bfpzero;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp->bf_flags & BFF_INTREE) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(bfp->bf_nlinks > 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip = bfp->bf_links[0]->bl_inst;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Another thread could beat us to this */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp->bf_flags & BFF_INTREE) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_remove(&bip->bi_fwd, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp->bf_flags &= ~BFF_INTREE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp->bf_flags & BFF_VLANLOCAL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp->bf_flags &= ~BFF_VLANLOCAL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfpzero = avl_find(&bip->bi_fwd, bfp, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfpzero != NULL && bfpzero->bf_vcnt > 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfpzero->bf_vcnt--;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_unref(bfp); /* no longer in avl tree */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic boolean_t
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaifwd_insert(bridge_inst_t *bip, bridge_fwd_t *bfp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_index_t idx;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai boolean_t retv;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!(bip->bi_flags & BIF_SHUTDOWN) &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_numnodes(&bip->bi_fwd) < bip->bi_tablemax &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_find(&bip->bi_fwd, bfp, &idx) == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_insert(&bip->bi_fwd, bfp, idx);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp->bf_flags |= BFF_INTREE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai atomic_inc_uint(&bfp->bf_refs); /* avl entry */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai retv = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai retv = B_FALSE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (retv);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaifwd_update_local(bridge_link_t *blp, const uint8_t *oldaddr,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai const uint8_t *newaddr)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip = blp->bl_inst;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_fwd_t *bfp, *bfnew;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_fwd_t match;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_index_t idx;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai boolean_t drop_ref = B_FALSE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bcmp(oldaddr, newaddr, ETHERADDRL) == 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bcmp(oldaddr, zero_addr, ETHERADDRL) == 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto no_old_addr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Find the previous entry, and remove our link from it.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bcopy(oldaddr, match.bf_dest, ETHERADDRL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((bfp = avl_find(&bip->bi_fwd, &match, NULL)) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int i;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * See if we're in the list, and remove if so.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (i = 0; i < bfp->bf_nlinks; i++) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp->bf_links[i] == blp) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * We assume writes are atomic, so no special
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * MT handling is needed. The list length is
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * decremented first, and then we remove
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * entries.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp->bf_nlinks--;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (; i < bfp->bf_nlinks; i++)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp->bf_links[i] = bfp->bf_links[i + 1];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai drop_ref = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* If no more links, then remove and free up */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp->bf_nlinks == 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_remove(&bip->bi_fwd, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp->bf_flags &= ~BFF_INTREE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_unref(bfp); /* no longer in avl tree */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Now get the new link address and add this link to the list. The
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * list should be of length 1 unless the user has configured multiple
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * NICs with the same address. (That's an incorrect configuration, but
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * we support it anyway.)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaino_old_addr:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((bip->bi_flags & BIF_SHUTDOWN) ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bcmp(newaddr, zero_addr, ETHERADDRL) == 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto no_new_addr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bcopy(newaddr, match.bf_dest, ETHERADDRL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((bfp = avl_find(&bip->bi_fwd, &match, &idx)) == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnew = fwd_alloc(newaddr, 1, RBRIDGE_NICKNAME_NONE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfnew != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KIINCR(bki_count);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else if (bfp->bf_nlinks < bfp->bf_maxlinks) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* special case: link fits in existing entry */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnew = bfp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnew = fwd_alloc(newaddr, bfp->bf_nlinks + 1,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai RBRIDGE_NICKNAME_NONE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfnew != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KIINCR(bki_count);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_remove(&bip->bi_fwd, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp->bf_flags &= ~BFF_INTREE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnew->bf_nlinks = bfp->bf_nlinks;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bcopy(bfp->bf_links, bfnew->bf_links,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp->bf_nlinks * sizeof (bfp));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* reset the idx value due to removal above */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) avl_find(&bip->bi_fwd, &match, &idx);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfnew != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnew->bf_links[bfnew->bf_nlinks++] = blp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (drop_ref)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai drop_ref = B_FALSE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai atomic_inc_uint(&blp->bl_refs); /* bf_links entry */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfnew != bfp) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* local addresses are not subject to table limits */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_insert(&bip->bi_fwd, bfnew, idx);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnew->bf_flags |= (BFF_INTREE | BFF_LOCALADDR);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai atomic_inc_uint(&bfnew->bf_refs); /* avl entry */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaino_new_addr:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If we found an existing entry and we replaced it with a new one,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * then drop the table reference from the old one. We removed it from
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * the AVL tree above.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfnew != NULL && bfp != NULL && bfnew != bfp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_unref(bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Account for removed entry. */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (drop_ref)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai link_unref(blp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_new_unicst(bridge_link_t *blp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint8_t new_mac[ETHERADDRL];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_unicast_primary_get(blp->bl_mh, new_mac);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_update_local(blp, blp->bl_local_mac, new_mac);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bcopy(new_mac, blp->bl_local_mac, ETHERADDRL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * We must shut down a link prior to freeing it, and doing that requires
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * blocking to wait for running MAC threads while holding a reference. This is
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * run from a taskq to accomplish proper link shutdown followed by reference
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * drop.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavailink_shutdown(void *arg)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_link_t *blp = arg;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_handle_t mh = blp->bl_mh;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_fwd_t *bfp, *bfnext;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_tree_t fwd_scavenge;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int i;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This link is being destroyed. Notify TRILL now that it's no longer
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * possible to send packets. Data packets may still arrive until TRILL
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * calls bridge_trill_lnunref.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_trilldata != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_lndstr_fn(blp->bl_trilldata, blp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_flags & BLF_PROM_ADDED)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) mac_promisc_remove(blp->bl_mphp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_flags & BLF_SET_BRIDGE)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_bridge_clear(mh, (mac_handle_t)blp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_flags & BLF_MARGIN_ADDED) {
4249d844b6c24a328b579c3d5ebc44595a61e046Rishi Srivatsavai (void) mac_notify_remove(blp->bl_mnh, B_TRUE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) mac_margin_remove(mh, blp->bl_margin);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Tell the clients the real link state when we leave */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_link_redo(blp->bl_mh,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_stat_get(blp->bl_mh, MAC_STAT_LOWLINK_STATE));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Destroy all of the forwarding entries related to this link */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_create(&fwd_scavenge, fwd_compare, sizeof (bridge_fwd_t),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai offsetof(bridge_fwd_t, bf_node));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip = blp->bl_inst;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnext = avl_first(&bip->bi_fwd);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while ((bfp = bfnext) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnext = AVL_NEXT(&bip->bi_fwd, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (i = 0; i < bfp->bf_nlinks; i++) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp->bf_links[i] == blp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (i >= bfp->bf_nlinks)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp->bf_nlinks > 1) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* note that this can't be the last reference */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai link_unref(blp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp->bf_nlinks--;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (; i < bfp->bf_nlinks; i++)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp->bf_links[i] = bfp->bf_links[i + 1];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(bfp->bf_flags & BFF_INTREE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_remove(&bip->bi_fwd, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp->bf_flags &= ~BFF_INTREE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_add(&fwd_scavenge, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnext = avl_first(&fwd_scavenge);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while ((bfp = bfnext) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnext = AVL_NEXT(&fwd_scavenge, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_remove(&fwd_scavenge, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_unref(bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_destroy(&fwd_scavenge);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_flags & BLF_CLIENT_OPEN)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_client_close(blp->bl_mch, 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_close(mh);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * We are now completely removed from the active list, so drop the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * reference (see bridge_add_link).
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai link_unref(blp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaishutdown_inst(bridge_inst_t *bip)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_link_t *blp, *blnext;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_fwd_t *bfp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&inst_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bip->bi_flags & BIF_SHUTDOWN) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&inst_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Once on the inst_list, the bridge instance must not leave that list
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * without having the shutdown flag set first. When the shutdown flag
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * is set, we own the list reference, so we must drop it before
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * returning.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip->bi_flags |= BIF_SHUTDOWN;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&inst_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip->bi_control = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blnext = list_head(&bip->bi_links);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while ((blp = blnext) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blnext = list_next(&bip->bi_links, blp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!(blp->bl_flags & BLF_DELETED)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_flags |= BLF_DELETED;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) ddi_taskq_dispatch(bridge_taskq, link_shutdown,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp, DDI_SLEEP);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while ((bfp = avl_first(&bip->bi_fwd)) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai atomic_inc_uint(&bfp->bf_refs);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_delete(bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_unref(bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This bridge is being destroyed. Notify TRILL once all of the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * links are all gone.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&inst_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while (bip->bi_trilldata != NULL && !list_is_empty(&bip->bi_links))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_wait(&bip->bi_linkwait, &inst_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&inst_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bip->bi_trilldata != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_brdstr_fn(bip->bi_trilldata, bip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_unref(bip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This is called once by the TRILL module when it starts up. It just sets the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * global TRILL callback function pointers -- data transmit/receive and bridge
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * and link destroy notification. There's only one TRILL module, so only one
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * registration is needed.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * TRILL should call this function with NULL pointers before unloading. It
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * must not do so before dropping all references to bridges and links. We
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * assert that this is true on debug builds.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaivoid
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_trill_register_cb(trill_recv_pkt_t recv_fn, trill_encap_pkt_t encap_fn,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_br_dstr_t brdstr_fn, trill_ln_dstr_t lndstr_fn)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#ifdef DEBUG
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (recv_fn == NULL && trill_recv_fn != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_link_t *blp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&inst_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (bip = list_head(&inst_list); bip != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip = list_next(&inst_list, bip)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(bip->bi_trilldata == NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (blp = list_head(&bip->bi_links); blp != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp = list_next(&bip->bi_links, blp)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(blp->bl_trilldata == NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&inst_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#endif
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_recv_fn = recv_fn;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_encap_fn = encap_fn;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_brdstr_fn = brdstr_fn;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_lndstr_fn = lndstr_fn;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This registers the TRILL instance pointer with a bridge. Before this
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * pointer is set, the forwarding, TRILL receive, and bridge destructor
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * functions won't be called.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * TRILL holds a reference on a bridge with this call. It must free the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * reference by calling the unregister function below.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_inst_t *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_trill_brref(const char *bname, void *ptr)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai char bridge[MAXLINKNAMELEN];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) snprintf(bridge, MAXLINKNAMELEN, "%s0", bname);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip = bridge_find_name(bridge);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bip != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(bip->bi_trilldata == NULL && ptr != NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip->bi_trilldata = ptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (bip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaivoid
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_trill_brunref(bridge_inst_t *bip)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(bip->bi_trilldata != NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip->bi_trilldata = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_unref(bip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * TRILL calls this function when referencing a particular link on a bridge.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * It holds a reference on the link, so TRILL must clear out the reference when
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * it's done with the link (on unbinding).
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_link_t *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_trill_lnref(bridge_inst_t *bip, datalink_id_t linkid, void *ptr)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_link_t *blp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(ptr != NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (blp = list_head(&bip->bi_links); blp != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp = list_next(&bip->bi_links, blp)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!(blp->bl_flags & BLF_DELETED) &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_linkid == linkid && blp->bl_trilldata == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_trilldata = ptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_flags &= ~BLF_TRILLACTIVE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) memset(blp->bl_afs, 0, sizeof (blp->bl_afs));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai atomic_inc_uint(&blp->bl_refs);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (blp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaivoid
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_trill_lnunref(bridge_link_t *blp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&blp->bl_trilllock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(blp->bl_trilldata != NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_trilldata = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_flags &= ~BLF_TRILLACTIVE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while (blp->bl_trillthreads > 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_wait(&blp->bl_trillwait, &blp->bl_trilllock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&blp->bl_trilllock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) memset(blp->bl_afs, 0xff, sizeof (blp->bl_afs));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai link_unref(blp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This periodic timer performs three functions:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * 1. It scans the list of learned forwarding entries, and removes ones that
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * haven't been heard from in a while. The time limit is backed down if
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * we're above the configured table limit.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * 2. It walks the links and decays away the bl_learns counter.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * 3. It scans the observability node entries looking for ones that can be
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * freed up.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* ARGSUSED */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_timer(void *arg)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_fwd_t *bfp, *bfnext;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_mac_t *bmp, *bmnext;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_link_t *blp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int err;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai datalink_id_t tmpid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_tree_t fwd_scavenge;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai clock_t age_limit;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint32_t ldecay;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_create(&fwd_scavenge, fwd_compare, sizeof (bridge_fwd_t),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai offsetof(bridge_fwd_t, bf_node));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&inst_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (bip = list_head(&inst_list); bip != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip = list_next(&inst_list, bip)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bip->bi_flags & BIF_SHUTDOWN)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* compute scaled maximum age based on table limit */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (avl_numnodes(&bip->bi_fwd) > bip->bi_tablemax)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip->bi_tshift++;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip->bi_tshift = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((age_limit = bridge_fwd_age >> bip->bi_tshift) == 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bip->bi_tshift != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip->bi_tshift--;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai age_limit = 1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnext = avl_first(&bip->bi_fwd);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while ((bfp = bfnext) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnext = AVL_NEXT(&bip->bi_fwd, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!(bfp->bf_flags & BFF_LOCALADDR) &&
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (ddi_get_lbolt() - bfp->bf_lastheard) > age_limit) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(bfp->bf_flags & BFF_INTREE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_remove(&bip->bi_fwd, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp->bf_flags &= ~BFF_INTREE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_add(&fwd_scavenge, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (blp = list_head(&bip->bi_links); blp != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp = list_next(&bip->bi_links, blp)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ldecay = mac_get_ldecay(blp->bl_mh);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (ldecay >= blp->bl_learns)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_learns = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai atomic_add_int(&blp->bl_learns, -(int)ldecay);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnext = avl_first(&fwd_scavenge);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while ((bfp = bfnext) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnext = AVL_NEXT(&fwd_scavenge, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_remove(&fwd_scavenge, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KIINCR(bki_expire);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_unref(bfp); /* drop tree reference */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&inst_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_destroy(&fwd_scavenge);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Scan the bridge_mac_t entries and try to free up the ones that are
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * no longer active. This must be done by polling, as neither DLS nor
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * MAC provides a driver any sort of positive control over clients.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bmac_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmnext = list_head(&bmac_list);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while ((bmp = bmnext) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmnext = list_next(&bmac_list, bmp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* ignore active bridges */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bmp->bm_inst != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bmp->bm_flags & BMF_DLS) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai err = dls_devnet_destroy(bmp->bm_mh, &tmpid, B_FALSE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(err == 0 || err == EBUSY);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (err == 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmp->bm_flags &= ~BMF_DLS;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!(bmp->bm_flags & BMF_DLS)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai err = mac_unregister(bmp->bm_mh);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(err == 0 || err == EBUSY);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (err == 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai list_remove(&bmac_list, bmp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kmem_free(bmp, sizeof (*bmp));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (list_is_empty(&bmac_list)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_timerid = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_timerid = timeout(bridge_timer, NULL,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_scan_interval);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bmac_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_open(queue_t *rq, dev_t *devp, int oflag, int sflag, cred_t *credp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_stream_t *bsp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (rq->q_ptr != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (sflag & MODOPEN)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EINVAL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Check the minor node number being opened. This tells us which
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridge instance the user wants.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (getminor(*devp) != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This is a regular DLPI stream for snoop or the like.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Redirect it through DLD.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rq->q_qinfo = &bridge_dld_rinit;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai OTHERQ(rq)->q_qinfo = &bridge_dld_winit;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (dld_open(rq, devp, oflag, sflag, credp));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Allocate the bridge control stream structure.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((bsp = stream_alloc()) == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (ENOSR);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rq->q_ptr = WR(rq)->q_ptr = (caddr_t)bsp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bsp->bs_wq = WR(rq);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *devp = makedevice(getmajor(*devp), bsp->bs_minor);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai qprocson(rq);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This is used only for bridge control streams. DLPI goes through dld
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * instead.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_close(queue_t *rq)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_stream_t *bsp = rq->q_ptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Wait for any stray taskq (add/delete link) entries related to this
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * stream to leave the system.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&stream_ref_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while (bsp->bs_taskq_cnt != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_wait(&stream_ref_cv, &stream_ref_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&stream_ref_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai qprocsoff(rq);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((bip = bsp->bs_inst) != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai shutdown_inst(bip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rq->q_ptr = WR(rq)->q_ptr = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai stream_free(bsp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bip != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_unref(bip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_learn(bridge_link_t *blp, const uint8_t *saddr, uint16_t ingress_nick,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t vlanid)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip = blp->bl_inst;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_fwd_t *bfp, *bfpnew;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int i;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai boolean_t replaced = B_FALSE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Ignore multi-destination address used as source; it's nonsense. */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (*saddr & 1)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If the source is known, then check whether it belongs on this link.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If not, and this isn't a fixed local address, then we've detected a
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * move. If it's not known, learn it.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((bfp = fwd_find(bip, saddr, vlanid)) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If the packet has a fixed local source address, then there's
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * nothing we can learn. We must quit. If this was a received
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * packet, then the sender has stolen our address, but there's
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * nothing we can do. If it's a transmitted packet, then
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * that's the normal case.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp->bf_flags & BFF_LOCALADDR) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_unref(bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Check if the link (and TRILL sender, if any) being used is
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * among the ones registered for this address. If so, then
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * this is information that we already know.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp->bf_trill_nick == ingress_nick) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (i = 0; i < bfp->bf_nlinks; i++) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp->bf_links[i] == blp) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni bfp->bf_lastheard = ddi_get_lbolt();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_unref(bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Note that we intentionally "unlearn" things that appear to be under
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * attack on this link. The forwarding cache is a negative thing for
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * security -- it disables reachability as a performance optimization
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * -- so leaving out entries optimizes for success and defends against
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * the attack. Thus, the bare increment without a check in the delete
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * code above is right. (And it's ok if we skid over the limit a
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * little, so there's no syncronization needed on the test.)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_learns >= mac_get_llimit(blp->bl_mh)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp->bf_vcnt == 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_delete(bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_unref(bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai atomic_inc_uint(&blp->bl_learns);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((bfpnew = fwd_alloc(saddr, 1, ingress_nick)) == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_unref(bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KIINCR(bki_count);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If this is a new destination for the same VLAN, then delete
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * so that we can update. If it's a different VLAN, then we're
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * not going to delete the original. Split off instead into an
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * IVL entry.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp->bf_vlanid == vlanid) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* save the count of IVL duplicates */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfpnew->bf_vcnt = bfp->bf_vcnt;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* entry deletes count as learning events */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai atomic_inc_uint(&blp->bl_learns);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* destroy and create anew; node moved */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_delete(bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai replaced = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KIINCR(bki_moved);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp->bf_vcnt++;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfpnew->bf_flags |= BFF_VLANLOCAL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_unref(bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfpnew->bf_links[0] = blp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfpnew->bf_nlinks = 1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai atomic_inc_uint(&blp->bl_refs); /* bf_links entry */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!fwd_insert(bip, bfpnew))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_free(bfpnew);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else if (!replaced)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KIINCR(bki_source);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Process the VLAN headers for output on a given link. There are several
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * cases (noting that we don't map VLANs):
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * 1. The input packet is good as it is; either
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * a. It has no tag, and output has same PVID
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * b. It has a non-zero priority-only tag for PVID, and b_band is same
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * c. It has a tag with VLAN different from PVID, and b_band is same
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * 2. The tag must change: non-zero b_band is different from tag priority
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * 3. The packet has a tag and should not (VLAN same as PVID, b_band zero)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * 4. The packet has no tag and needs one:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * a. VLAN ID same as PVID, but b_band is non-zero
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * b. VLAN ID different from PVID
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * We exclude case 1 first, then modify the packet. Note that output packets
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * get a priority set by the mblk, not by the header, because QoS in bridging
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * requires priority recalculation at each node.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * The passed-in tci is the "impossible" value 0xFFFF when no tag is present.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic mblk_t *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaireform_vlan_header(mblk_t *mp, uint16_t vlanid, uint16_t tci, uint16_t pvid)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai boolean_t source_has_tag = (tci != 0xFFFF);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mblk_t *mpcopy;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai size_t mlen, minlen;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct ether_vlan_header *evh;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int pri;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* This helps centralize error handling in the caller. */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mp == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* No forwarded packet can have hardware checksum enabled */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DB_CKSUMFLAGS(mp) = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Get the no-modification cases out of the way first */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!source_has_tag && vlanid == pvid) /* 1a */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pri = VLAN_PRI(tci);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (source_has_tag && mp->b_band == pri) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (vlanid != pvid) /* 1c */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (pri != 0 && VLAN_ID(tci) == 0) /* 1b */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * We now know that we must modify the packet. Prepare for that. Note
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * that if a tag is present, the caller has already done a pullup for
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * the VLAN header, so we're good to go.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (MBLKL(mp) < sizeof (struct ether_header)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mpcopy = msgpullup(mp, sizeof (struct ether_header));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mpcopy == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp = mpcopy;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (DB_REF(mp) > 1 || !IS_P2ALIGNED(mp->b_rptr, sizeof (uint16_t)) ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (!source_has_tag && MBLKTAIL(mp) < VLAN_INCR)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai minlen = mlen = MBLKL(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!source_has_tag)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai minlen += VLAN_INCR;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(minlen >= sizeof (struct ether_vlan_header));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * We're willing to copy some data to avoid fragmentation, but
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * not a lot.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (minlen > 256)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai minlen = sizeof (struct ether_vlan_header);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mpcopy = allocb(minlen, BPRI_MED);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mpcopy == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mlen <= minlen) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* We toss the first mblk when we can. */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bcopy(mp->b_rptr, mpcopy->b_rptr, mlen);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mpcopy->b_wptr += mlen;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mpcopy->b_cont = mp->b_cont;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freeb(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* If not, then just copy what we need */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!source_has_tag)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai minlen = sizeof (struct ether_header);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bcopy(mp->b_rptr, mpcopy->b_rptr, minlen);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mpcopy->b_wptr += minlen;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mpcopy->b_cont = mp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_rptr += minlen;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp = mpcopy;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: pointer alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai evh = (struct ether_vlan_header *)mp->b_rptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (source_has_tag) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mp->b_band == 0 && vlanid == pvid) { /* 3 */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai evh->ether_tpid = evh->ether_type;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mlen = MBLKL(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mlen > sizeof (struct ether_vlan_header))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ovbcopy(mp->b_rptr +
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (struct ether_vlan_header),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_rptr + sizeof (struct ether_header),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mlen - sizeof (struct ether_vlan_header));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_wptr -= VLAN_INCR;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else { /* 2 */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (vlanid == pvid)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai vlanid = VLAN_ID_NONE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tci = VLAN_TCI(mp->b_band, ETHER_CFI, vlanid);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai evh->ether_tci = htons(tci);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* case 4: no header present, but one is needed */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mlen = MBLKL(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mlen > sizeof (struct ether_header))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ovbcopy(mp->b_rptr + sizeof (struct ether_header),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_rptr + sizeof (struct ether_vlan_header),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mlen - sizeof (struct ether_header));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_wptr += VLAN_INCR;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(mp->b_wptr <= DB_LIM(mp));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (vlanid == pvid)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai vlanid = VLAN_ID_NONE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tci = VLAN_TCI(mp->b_band, ETHER_CFI, vlanid);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai evh->ether_type = evh->ether_tpid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai evh->ether_tpid = htons(ETHERTYPE_VLAN);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai evh->ether_tci = htons(tci);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* Record VLAN information and strip header if requested . */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiupdate_header(mblk_t *mp, mac_header_info_t *hdr_info, boolean_t striphdr)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (hdr_info->mhi_bindsap == ETHERTYPE_VLAN) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct ether_vlan_header *evhp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t ether_type;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai evhp = (struct ether_vlan_header *)mp->b_rptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai hdr_info->mhi_istagged = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai hdr_info->mhi_tci = ntohs(evhp->ether_tci);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (striphdr) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * For VLAN tagged frames update the ether_type
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * in hdr_info before stripping the header.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ether_type = ntohs(evhp->ether_type);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai hdr_info->mhi_origsap = ether_type;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai hdr_info->mhi_bindsap = (ether_type > ETHERMTU) ?
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ether_type : DLS_SAP_LLC;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_rptr = (uchar_t *)(evhp + 1);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai hdr_info->mhi_istagged = B_FALSE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai hdr_info->mhi_tci = VLAN_ID_NONE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (striphdr)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_rptr += sizeof (struct ether_header);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Return B_TRUE if we're allowed to send on this link with the given VLAN ID.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic boolean_t
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_can_send(bridge_link_t *blp, uint16_t vlanid)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(vlanid != VLAN_ID_NONE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_flags & BLF_DELETED)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (B_FALSE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_trilldata == NULL && blp->bl_state != BLS_FORWARDING)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (B_FALSE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (BRIDGE_VLAN_ISSET(blp, vlanid) && BRIDGE_AF_ISSET(blp, vlanid));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This function scans the bridge forwarding tables in order to forward a given
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * packet. If the packet either doesn't need forwarding (the current link is
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * correct) or the current link needs a copy as well, then the packet is
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * returned to the caller.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If a packet has been decapsulated from TRILL, then it must *NOT* reenter a
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * TRILL tunnel. If the destination points there, then drop instead.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic mblk_t *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_forward(bridge_link_t *blp, mac_header_info_t *hdr_info, mblk_t *mp,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t vlanid, uint16_t tci, boolean_t from_trill, boolean_t is_xmit)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mblk_t *mpsend, *mpcopy;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip = blp->bl_inst;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_link_t *blpsend, *blpnext;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_fwd_t *bfp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint_t i;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai boolean_t selfseen = B_FALSE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai void *tdp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai const uint8_t *daddr = hdr_info->mhi_daddr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Check for the IEEE "reserved" multicast addresses. Messages sent to
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * these addresses are used for link-local control (STP and pause), and
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * are never forwarded or redirected.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (daddr[0] == 1 && daddr[1] == 0x80 && daddr[2] == 0xc2 &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai daddr[3] == 0 && daddr[4] == 0 && (daddr[5] & 0xf0) == 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (from_trill) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((bfp = fwd_find(bip, daddr, vlanid)) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If trill indicates a destination for this node, then it's
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * clearly not intended for local delivery. We must tell TRILL
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * to encapsulate, as long as we didn't just decapsulate it.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp->bf_trill_nick != RBRIDGE_NICKNAME_NONE) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Error case: can't reencapsulate if the protocols are
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * working correctly.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (from_trill) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&blp->bl_trilllock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((tdp = blp->bl_trilldata) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_trillthreads++;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&blp->bl_trilllock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai update_header(mp, hdr_info, B_FALSE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (is_xmit)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp = mac_fix_cksum(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* all trill data frames have Inner.VLAN */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp = reform_vlan_header(mp, vlanid, tci, 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mp == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KIINCR(bki_drops);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_unref(bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_encap_fn(tdp, blp, hdr_info, mp,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp->bf_trill_nick);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&blp->bl_trilllock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (--blp->bl_trillthreads == 0 &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_trilldata == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_broadcast(&blp->bl_trillwait);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&blp->bl_trilllock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* if TRILL has been disabled, then kill this stray */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tdp == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_delete(bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_unref(bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* find first link we can send on */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (i = 0; i < bfp->bf_nlinks; i++) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blpsend = bfp->bf_links[i];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blpsend == blp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai selfseen = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else if (bridge_can_send(blpsend, vlanid))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while (i < bfp->bf_nlinks) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blpsend = bfp->bf_links[i];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (i++; i < bfp->bf_nlinks; i++) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blpnext = bfp->bf_links[i];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blpnext == blp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai selfseen = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else if (bridge_can_send(blpnext, vlanid))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (i == bfp->bf_nlinks && !selfseen) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mpsend = mp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mpsend = copymsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!from_trill && is_xmit)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mpsend = mac_fix_cksum(mpsend);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mpsend = reform_vlan_header(mpsend, vlanid, tci,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blpsend->bl_pvid);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mpsend == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KIINCR(bki_drops);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KIINCR(bki_forwards);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * No need to bump up the link reference count, as
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * the forwarding entry itself holds a reference to
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * the link.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp->bf_flags & BFF_LOCALADDR) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_rx_common(blpsend->bl_mh, NULL, mpsend);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KLPINCR(blpsend, bkl_xmit);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai MAC_RING_TX(blpsend->bl_mh, NULL, mpsend,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mpsend);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mpsend);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Handle a special case: if we're transmitting to the original
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * link, then check whether the localaddr flag is set. If it
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * is, then receive instead. This doesn't happen with ordinary
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridging, but does happen often with TRILL decapsulation.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mp != NULL && is_xmit && (bfp->bf_flags & BFF_LOCALADDR)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_rx_common(blp->bl_mh, NULL, mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_unref(bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * TRILL has two cases to handle. If the packet is off the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * wire (not from TRILL), then we need to send up into the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * TRILL module to have the distribution tree computed. If the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * packet is from TRILL (decapsulated), then we're part of the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * distribution tree, and we need to copy the packet on member
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * interfaces.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Thus, the from TRILL case is identical to the STP case.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!from_trill && blp->bl_trilldata != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&blp->bl_trilllock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((tdp = blp->bl_trilldata) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_trillthreads++;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&blp->bl_trilllock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((mpsend = copymsg(mp)) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai update_header(mpsend,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai hdr_info, B_FALSE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * all trill data frames have
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Inner.VLAN
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mpsend = reform_vlan_header(mpsend,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai vlanid, tci, 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mpsend == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KIINCR(bki_drops);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_encap_fn(tdp, blp,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai hdr_info, mpsend,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai RBRIDGE_NICKNAME_NONE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&blp->bl_trilllock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (--blp->bl_trillthreads == 0 &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_trilldata == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_broadcast(&blp->bl_trillwait);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&blp->bl_trilllock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This is an unknown destination, so flood.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (blpnext = list_head(&bip->bi_links); blpnext != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blpnext = list_next(&bip->bi_links, blpnext)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blpnext == blp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai selfseen = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else if (bridge_can_send(blpnext, vlanid))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blpnext != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai atomic_inc_uint(&blpnext->bl_refs);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while ((blpsend = blpnext) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (blpnext = list_next(&bip->bi_links, blpsend);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blpnext != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blpnext = list_next(&bip->bi_links, blpnext)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blpnext == blp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai selfseen = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else if (bridge_can_send(blpnext, vlanid))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blpnext != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai atomic_inc_uint(&blpnext->bl_refs);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blpnext == NULL && !selfseen) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mpsend = mp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mpsend = copymsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!from_trill && is_xmit)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mpsend = mac_fix_cksum(mpsend);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mpsend = reform_vlan_header(mpsend, vlanid, tci,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blpsend->bl_pvid);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mpsend == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KIINCR(bki_drops);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (hdr_info->mhi_dsttype == MAC_ADDRTYPE_UNICAST)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KIINCR(bki_unknown);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KIINCR(bki_mbcast);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KLPINCR(blpsend, bkl_xmit);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((mpcopy = copymsg(mpsend)) != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_rx_common(blpsend->bl_mh, NULL, mpcopy);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai MAC_RING_TX(blpsend->bl_mh, NULL, mpsend, mpsend);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mpsend);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai link_unref(blpsend);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * At this point, if np is non-NULL, it means that the caller needs to
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * continue on the selected link.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Extract and validate the VLAN information for a given packet. This checks
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * conformance with the rules for use of the PVID on the link, and for the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * allowed (configured) VLAN set.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Returns B_TRUE if the packet passes, B_FALSE if it fails.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic boolean_t
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_get_vlan(bridge_link_t *blp, mac_header_info_t *hdr_info, mblk_t *mp,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t *vlanidp, uint16_t *tcip)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t tci, vlanid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (hdr_info->mhi_bindsap == ETHERTYPE_VLAN) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ptrdiff_t tpos = offsetof(struct ether_vlan_header, ether_tci);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ptrdiff_t mlen;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Extract the VLAN ID information, regardless of alignment,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * and without a pullup. This isn't attractive, but we do this
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * to avoid having to deal with the pointers stashed in
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * hdr_info moving around or having the caller deal with a new
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * mblk_t pointer.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while (mp != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mlen = MBLKL(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mlen > tpos && mlen > 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tpos -= mlen;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp = mp->b_cont;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mp == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (B_FALSE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tci = mp->b_rptr[tpos] << 8;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (++tpos >= mlen) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai do {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp = mp->b_cont;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } while (mp != NULL && MBLKL(mp) == 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mp == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (B_FALSE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tpos = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tci |= mp->b_rptr[tpos];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai vlanid = VLAN_ID(tci);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (VLAN_CFI(tci) != ETHER_CFI || vlanid > VLAN_ID_MAX)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (B_FALSE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (vlanid == VLAN_ID_NONE || vlanid == blp->bl_pvid)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto input_no_vlan;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!BRIDGE_VLAN_ISSET(blp, vlanid))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (B_FALSE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tci = 0xFFFF;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiinput_no_vlan:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If PVID is set to zero, then untagged traffic is not
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * supported here. Do not learn or forward.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((vlanid = blp->bl_pvid) == VLAN_ID_NONE)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (B_FALSE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *tcip = tci;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *vlanidp = vlanid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (B_TRUE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Handle MAC notifications.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_notify_cb(void *arg, mac_notify_type_t note_type)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_link_t *blp = arg;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai switch (note_type) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case MAC_NOTE_UNICST:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_new_unicst(blp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case MAC_NOTE_SDU_SIZE: {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint_t maxsdu;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip = blp->bl_inst;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_mac_t *bmp = bip->bi_mac;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai boolean_t notify = B_FALSE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mblk_t *mlist = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_sdu_get(blp->bl_mh, NULL, &maxsdu);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (list_prev(&bip->bi_links, blp) == NULL &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai list_next(&bip->bi_links, blp) == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai notify = (maxsdu != bmp->bm_maxsdu);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmp->bm_maxsdu = maxsdu;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_maxsdu = maxsdu;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (maxsdu != bmp->bm_maxsdu)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai link_sdu_fail(blp, B_TRUE, &mlist);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else if (notify)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) mac_maxsdu_update(bmp->bm_mh, maxsdu);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai send_up_messages(bip, mlist);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This is called by the MAC layer. As with the transmit side, we're right in
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * the data path for all I/O on this port, so if we don't need to forward this
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * packet anywhere, we have to send it upwards via mac_rx_common.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_recv_cb(mac_handle_t mh, mac_resource_handle_t rsrc, mblk_t *mpnext)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mblk_t *mp, *mpcopy;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_link_t *blp = (bridge_link_t *)mh;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip = blp->bl_inst;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_mac_t *bmp = bip->bi_mac;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_header_info_t hdr_info;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t vlanid, tci;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai boolean_t trillmode = B_FALSE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KIINCR(bki_recv);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KLINCR(bkl_recv);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Regardless of state, check for inbound TRILL packets when TRILL is
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * active. These are pulled out of band and sent for TRILL handling.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_trilldata != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai void *tdp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mblk_t *newhead;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mblk_t *tail = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&blp->bl_trilllock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((tdp = blp->bl_trilldata) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_trillthreads++;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&blp->bl_trilllock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trillmode = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai newhead = mpnext;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while ((mp = mpnext) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai boolean_t raw_isis, bridge_group;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mpnext = mp->b_next;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If the header isn't readable, then leave on
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * the list and continue.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mac_header_info(blp->bl_mh, mp,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai &hdr_info) != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tail = mp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * The TRILL document specifies that, on
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Ethernet alone, IS-IS packets arrive with
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * LLC rather than Ethertype, and using a
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * specific destination address. We must check
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * for that here. Also, we need to give BPDUs
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * to TRILL for processing.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai raw_isis = bridge_group = B_FALSE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (hdr_info.mhi_dsttype ==
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai MAC_ADDRTYPE_MULTICAST) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (memcmp(hdr_info.mhi_daddr,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai all_isis_rbridges, ETHERADDRL) == 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai raw_isis = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else if (memcmp(hdr_info.mhi_daddr,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_group_address, ETHERADDRL) ==
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_group = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!raw_isis && !bridge_group &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai hdr_info.mhi_bindsap != ETHERTYPE_TRILL &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (hdr_info.mhi_bindsap != ETHERTYPE_VLAN ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ((struct ether_vlan_header *)mp->b_rptr)->
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ether_type != htons(ETHERTYPE_TRILL))) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tail = mp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * We've got TRILL input. Remove from the list
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * and send up through the TRILL module. (Send
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * a copy through promiscuous receive just to
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * support snooping on TRILL. Order isn't
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * preserved strictly, but that doesn't matter
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * here.)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tail != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tail->b_next = mpnext;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_next = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mp == newhead)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai newhead = mpnext;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_trill_snoop(blp->bl_mh, mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai update_header(mp, &hdr_info, B_TRUE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * On raw IS-IS and BPDU frames, we have to
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * make sure that the length is trimmed
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * properly. We use origsap in order to cope
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * with jumbograms for IS-IS. (Regular mac
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * can't.)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (raw_isis || bridge_group) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai size_t msglen = msgdsize(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (msglen > hdr_info.mhi_origsap) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) adjmsg(mp,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai hdr_info.mhi_origsap -
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai msglen);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else if (msglen <
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai hdr_info.mhi_origsap) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_recv_fn(tdp, blp, rsrc, mp, &hdr_info);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mpnext = newhead;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&blp->bl_trilllock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (--blp->bl_trillthreads == 0 &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_trilldata == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_broadcast(&blp->bl_trillwait);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&blp->bl_trilllock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mpnext == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If this is a TRILL RBridge, then just check whether this link is
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * used at all for forwarding. If not, then we're done.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (trillmode) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!(blp->bl_flags & BLF_TRILLACTIVE) ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (blp->bl_flags & BLF_SDUFAIL)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_rx_common(blp->bl_mh, rsrc, mpnext);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * For regular (STP) bridges, if we're in blocking or listening
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * state, then do nothing. We don't learn or forward until
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * told to do so.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_state == BLS_BLOCKLISTEN) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_rx_common(blp->bl_mh, rsrc, mpnext);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Send a copy of the message chain up to the observability node users.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * For TRILL, we must obey the VLAN AF rules, so we go packet-by-
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * packet.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!trillmode && blp->bl_state == BLS_FORWARDING &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (bmp->bm_flags & BMF_STARTED) &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (mp = copymsgchain(mpnext)) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_rx(bmp->bm_mh, NULL, mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * We must be in learning or forwarding state, or using TRILL on a link
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * with one or more VLANs active. For each packet in the list, process
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * the source address, and then attempt to forward.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while ((mp = mpnext) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mpnext = mp->b_next;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_next = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If we can't decode the header or if the header specifies a
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * multicast source address (impossible!), then don't bother
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * learning or forwarding, but go ahead and forward up the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * stack for subsequent processing.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mac_header_info(blp->bl_mh, mp, &hdr_info) != 0 ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (hdr_info.mhi_saddr[0] & 1) != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KIINCR(bki_drops);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KLINCR(bkl_drops);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_rx_common(blp->bl_mh, rsrc, mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Extract and validate the VLAN ID for this packet.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!bridge_get_vlan(blp, &hdr_info, mp, &vlanid, &tci) ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai !BRIDGE_AF_ISSET(blp, vlanid)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_rx_common(blp->bl_mh, rsrc, mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (trillmode) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Special test required by TRILL document: must
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * discard frames with outer address set to ESADI.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (memcmp(hdr_info.mhi_daddr, all_esadi_rbridges,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ETHERADDRL) == 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_rx_common(blp->bl_mh, rsrc, mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If we're in TRILL mode, then the call above to get
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * the VLAN ID has also checked that we're the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * appointed forwarder, so report that we're handling
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * this packet to any observability node users.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((bmp->bm_flags & BMF_STARTED) &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (mpcopy = copymsg(mp)) != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_rx(bmp->bm_mh, NULL, mpcopy);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * First process the source address and learn from it. For
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * TRILL, we learn only if we're the appointed forwarder.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_learn(blp, hdr_info.mhi_saddr, RBRIDGE_NICKNAME_NONE,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai vlanid);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Now check whether we're forwarding and look up the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * destination. If we can forward, do so.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (trillmode || blp->bl_state == BLS_FORWARDING) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp = bridge_forward(blp, &hdr_info, mp, vlanid, tci,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai B_FALSE, B_FALSE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mp != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_rx_common(blp->bl_mh, rsrc, mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* ARGSUSED */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic mblk_t *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_xmit_cb(mac_handle_t mh, mac_ring_handle_t rh, mblk_t *mpnext)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_link_t *blp = (bridge_link_t *)mh;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip = blp->bl_inst;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_mac_t *bmp = bip->bi_mac;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_header_info_t hdr_info;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t vlanid, tci;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mblk_t *mp, *mpcopy;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai boolean_t trillmode;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trillmode = blp->bl_trilldata != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If we're using STP and we're in blocking or listening state, or if
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * we're using TRILL and no VLANs are active, then behave as though the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridge isn't here at all, and send on the local link alone.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((!trillmode && blp->bl_state == BLS_BLOCKLISTEN) ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (trillmode &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (!(blp->bl_flags & BLF_TRILLACTIVE) ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (blp->bl_flags & BLF_SDUFAIL)))) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KIINCR(bki_sent);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KLINCR(bkl_xmit);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai MAC_RING_TX(blp->bl_mh, rh, mpnext, mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Send a copy of the message up to the observability node users.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * TRILL needs to check on a packet-by-packet basis.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!trillmode && blp->bl_state == BLS_FORWARDING &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (bmp->bm_flags & BMF_STARTED) &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (mp = copymsgchain(mpnext)) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_rx(bmp->bm_mh, NULL, mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while ((mp = mpnext) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mpnext = mp->b_next;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_next = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mac_header_info(blp->bl_mh, mp, &hdr_info) != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Extract and validate the VLAN ID for this packet.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!bridge_get_vlan(blp, &hdr_info, mp, &vlanid, &tci) ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai !BRIDGE_AF_ISSET(blp, vlanid)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If we're using TRILL, then we've now validated that we're
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * the forwarder for this VLAN, so go ahead and let
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * observability node users know about the packet.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (trillmode && (bmp->bm_flags & BMF_STARTED) &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (mpcopy = copymsg(mp)) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_rx(bmp->bm_mh, NULL, mpcopy);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * We have to learn from our own transmitted packets, because
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * there may be a Solaris DLPI raw sender (who can specify his
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * own source address) using promiscuous mode for receive. The
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * mac layer information won't (and can't) tell us everything
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * we need to know.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_learn(blp, hdr_info.mhi_saddr, RBRIDGE_NICKNAME_NONE,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai vlanid);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* attempt forwarding */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (trillmode || blp->bl_state == BLS_FORWARDING) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp = bridge_forward(blp, &hdr_info, mp, vlanid, tci,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai B_FALSE, B_TRUE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mp != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai MAC_RING_TX(blp->bl_mh, rh, mp, mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mp == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KIINCR(bki_sent);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KLINCR(bkl_xmit);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If we get stuck, then stop. Don't let the user's output
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * packets get out of order. (More importantly: don't try to
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridge the same packet multiple times if flow control is
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * asserted.)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mp != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_next = mpnext;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This is called by TRILL when it decapsulates an packet, and we must forward
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * locally. On failure, we just drop.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Note that the ingress_nick reported by TRILL must not represent this local
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * node.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaivoid
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_trill_decaps(bridge_link_t *blp, mblk_t *mp, uint16_t ingress_nick)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_header_info_t hdr_info;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t vlanid, tci;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip = blp->bl_inst; /* used by macros */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mblk_t *mpcopy;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mac_header_info(blp->bl_mh, mp, &hdr_info) != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Extract VLAN ID for this packet. */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (hdr_info.mhi_bindsap == ETHERTYPE_VLAN) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct ether_vlan_header *evhp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai evhp = (struct ether_vlan_header *)mp->b_rptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tci = ntohs(evhp->ether_tci);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai vlanid = VLAN_ID(tci);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Inner VLAN headers are required in TRILL data packets */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DTRACE_PROBE3(bridge__trill__decaps__novlan, bridge_link_t *,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp, mblk_t *, mp, uint16_t, ingress_nick);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Learn the location of this sender in the RBridge network */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_learn(blp, hdr_info.mhi_saddr, ingress_nick, vlanid);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* attempt forwarding */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp = bridge_forward(blp, &hdr_info, mp, vlanid, tci, B_TRUE, B_TRUE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mp != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bridge_can_send(blp, vlanid)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Deliver a copy locally as well */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((mpcopy = copymsg(mp)) != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_rx_common(blp->bl_mh, NULL, mpcopy);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai MAC_RING_TX(blp->bl_mh, NULL, mp, mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mp == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KIINCR(bki_sent);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KLINCR(bkl_xmit);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This function is used by TRILL _only_ to transmit TRILL-encapsulated
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * packets. It sends on a single underlying link and does not bridge.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaimblk_t *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_trill_output(bridge_link_t *blp, mblk_t *mp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip = blp->bl_inst; /* used by macros */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_trill_snoop(blp->bl_mh, mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai MAC_RING_TX(blp->bl_mh, NULL, mp, mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mp == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KIINCR(bki_sent);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KLINCR(bkl_xmit);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Set the "appointed forwarder" flag array for this link. TRILL controls
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * forwarding on a VLAN basis. The "trillactive" flag is an optimization for
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * the forwarder.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaivoid
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_trill_setvlans(bridge_link_t *blp, const uint8_t *arr)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int i;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint_t newflags = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (i = 0; i < BRIDGE_VLAN_ARR_SIZE; i++) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((blp->bl_afs[i] = arr[i]) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai newflags = BLF_TRILLACTIVE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_flags = (blp->bl_flags & ~BLF_TRILLACTIVE) | newflags;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaivoid
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_trill_flush(bridge_link_t *blp, uint16_t vlan, boolean_t dotrill)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip = blp->bl_inst;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_fwd_t *bfp, *bfnext;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_tree_t fwd_scavenge;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int i;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai _NOTE(ARGUNUSED(vlan));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_create(&fwd_scavenge, fwd_compare, sizeof (bridge_fwd_t),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai offsetof(bridge_fwd_t, bf_node));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnext = avl_first(&bip->bi_fwd);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while ((bfp = bfnext) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnext = AVL_NEXT(&bip->bi_fwd, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp->bf_flags & BFF_LOCALADDR)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (dotrill) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* port doesn't matter if we're flushing TRILL */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp->bf_trill_nick == RBRIDGE_NICKNAME_NONE)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp->bf_trill_nick != RBRIDGE_NICKNAME_NONE)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (i = 0; i < bfp->bf_nlinks; i++) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp->bf_links[i] == blp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (i >= bfp->bf_nlinks)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(bfp->bf_flags & BFF_INTREE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_remove(&bip->bi_fwd, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp->bf_flags &= ~BFF_INTREE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_add(&fwd_scavenge, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnext = avl_first(&fwd_scavenge);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while ((bfp = bfnext) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnext = AVL_NEXT(&fwd_scavenge, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_remove(&fwd_scavenge, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_unref(bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_destroy(&fwd_scavenge);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Let the mac module take or drop a reference to a bridge link. When this is
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * called, the mac module is holding the mi_bridge_lock, so the link cannot be
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * in the process of entering or leaving a bridge.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_ref_cb(mac_handle_t mh, boolean_t hold)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_link_t *blp = (bridge_link_t *)mh;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (hold)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai atomic_inc_uint(&blp->bl_refs);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai link_unref(blp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Handle link state changes reported by the mac layer. This acts as a filter
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * for link state changes: if a link is reporting down, but there are other
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * links still up on the bridge, then the state is changed to "up." When the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * last link goes down, all are marked down, and when the first link goes up,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * all are marked up. (Recursion is avoided by the use of the "redo" function.)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * We treat unknown as equivalent to "up."
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic link_state_t
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_ls_cb(mac_handle_t mh, link_state_t newls)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_link_t *blp = (bridge_link_t *)mh;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_link_t *blcmp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_mac_t *bmp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (newls != LINK_STATE_DOWN && blp->bl_linkstate != LINK_STATE_DOWN ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (blp->bl_flags & (BLF_DELETED|BLF_SDUFAIL))) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_linkstate = newls;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (newls);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Scan first to see if there are any other non-down links. If there
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * are, then we're done. Otherwise, if all others are down, then the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * state of this link is the state of the bridge.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip = blp->bl_inst;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (blcmp = list_head(&bip->bi_links); blcmp != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blcmp = list_next(&bip->bi_links, blcmp)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blcmp != blp &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai !(blcmp->bl_flags & (BLF_DELETED|BLF_SDUFAIL)) &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blcmp->bl_linkstate != LINK_STATE_DOWN)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blcmp != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If there are other links that are considered up, then tell
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * the caller that the link is actually still up, regardless of
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * this link's underlying state.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_linkstate = newls;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai newls = LINK_STATE_UP;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else if (blp->bl_linkstate != newls) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If we've found no other 'up' links, and this link has
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * changed state, then report the new state of the bridge to
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * all other clients.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_linkstate = newls;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (blcmp = list_head(&bip->bi_links); blcmp != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blcmp = list_next(&bip->bi_links, blcmp)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blcmp != blp && !(blcmp->bl_flags & BLF_DELETED))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_link_redo(blcmp->bl_mh, newls);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmp = bip->bi_mac;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((bmp->bm_linkstate = newls) != LINK_STATE_DOWN)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmp->bm_linkstate = LINK_STATE_UP;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_link_redo(bmp->bm_mh, bmp->bm_linkstate);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (newls);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_add_link(void *arg)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mblk_t *mp = arg;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_stream_t *bsp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip, *bipt;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_mac_t *bmp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai datalink_id_t linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int err;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_handle_t mh;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint_t maxsdu;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_link_t *blp = NULL, *blpt;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai const mac_info_t *mip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai boolean_t macopen = B_FALSE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai char linkname[MAXLINKNAMELEN];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai char kstatname[KSTAT_STRLEN];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int i;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai link_state_t linkstate;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mblk_t *mlist;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bsp = (bridge_stream_t *)mp->b_next;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_next = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip = bsp->bs_inst;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai linkid = *(datalink_id_t *)mp->b_cont->b_rptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * First make sure that there is no other bridge that has this link.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * We don't want to overlap operations from two bridges; the MAC layer
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * supports only one bridge on a given MAC at a time.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * We rely on the fact that there's just one taskq thread for the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridging module: once we've checked for a duplicate, we can drop the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * lock, because no other thread could possibly be adding another link
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * until we're done.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&inst_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (bipt = list_head(&inst_list); bipt != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bipt = list_next(&inst_list, bipt)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bipt->bi_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (blpt = list_head(&bipt->bi_links); blpt != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blpt = list_next(&bipt->bi_links, blpt)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (linkid == blpt->bl_linkid)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bipt->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blpt != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&inst_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bipt != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai err = EBUSY;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((err = mac_open_by_linkid(linkid, &mh)) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai macopen = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* we bridge only Ethernet */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mip = mac_info(mh);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mip->mi_media != DL_ETHER) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai err = ENOTSUP;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Get the current maximum SDU on this interface. If there are other
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * links on the bridge, then this one must match, or it errors out.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Otherwise, the first link becomes the standard for the new bridge.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_sdu_get(mh, NULL, &maxsdu);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmp = bip->bi_mac;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (list_is_empty(&bip->bi_links)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmp->bm_maxsdu = maxsdu;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) mac_maxsdu_update(bmp->bm_mh, maxsdu);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* figure the kstat name; also used as the mac client name */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai i = MBLKL(mp->b_cont) - sizeof (datalink_id_t);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (i < 0 || i >= MAXLINKNAMELEN)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai i = MAXLINKNAMELEN - 1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bcopy(mp->b_cont->b_rptr + sizeof (datalink_id_t), linkname, i);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai linkname[i] = '\0';
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) snprintf(kstatname, sizeof (kstatname), "%s-%s", bip->bi_name,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai linkname);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((blp = kmem_zalloc(sizeof (*blp), KM_NOSLEEP)) == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai err = ENOMEM;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_lfailmp = allocb(sizeof (bridge_ctl_t), BPRI_MED);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_lfailmp == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kmem_free(blp, sizeof (*blp));
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai blp = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai err = ENOMEM;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai blp->bl_refs = 1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai atomic_inc_uint(&bip->bi_refs);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_inst = bip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_mh = mh;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_linkid = linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_maxsdu = maxsdu;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_init(&blp->bl_trillwait, NULL, CV_DRIVER, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_init(&blp->bl_trilllock, NULL, MUTEX_DRIVER, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) memset(blp->bl_afs, 0xff, sizeof (blp->bl_afs));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai err = mac_client_open(mh, &blp->bl_mch, kstatname, 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (err != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_flags |= BLF_CLIENT_OPEN;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai err = mac_margin_add(mh, &blp->bl_margin, B_TRUE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (err != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_flags |= BLF_MARGIN_ADDED;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_mnh = mac_notify_add(mh, bridge_notify_cb, blp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai /* Enable Bridging on the link */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai err = mac_bridge_set(mh, (mac_handle_t)blp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (err != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_flags |= BLF_SET_BRIDGE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai err = mac_promisc_add(blp->bl_mch, MAC_CLIENT_PROMISC_ALL, NULL,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp, &blp->bl_mphp, MAC_PROMISC_FLAGS_NO_TX_LOOP);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (err != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_flags |= BLF_PROM_ADDED;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_new_unicst(blp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_ksp = kstat_setup((kstat_named_t *)&blp->bl_kstats,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai link_kstats_list, Dim(link_kstats_list), kstatname);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * The link holds a reference to the bridge instance, so that the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * instance can't go away before the link is freed. The insertion into
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai * bi_links holds a reference on the link (reference set to 1 above).
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai * When marking as removed from bi_links (BLF_DELETED), drop the
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai * reference on the link. When freeing the link, drop the reference on
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai * the instance. BLF_LINK_ADDED tracks link insertion in bi_links list.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai list_insert_tail(&bip->bi_links, blp);
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai blp->bl_flags |= BLF_LINK_ADDED;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If the new link is no good on this bridge, then let the daemon know
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * about the problem.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mlist = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (maxsdu != bmp->bm_maxsdu)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai link_sdu_fail(blp, B_TRUE, &mlist);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai send_up_messages(bip, mlist);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Trigger a link state update so that if this link is the first one
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * "up" in the bridge, then we notify everyone. This triggers a trip
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * through bridge_ls_cb.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai linkstate = mac_stat_get(mh, MAC_STAT_LOWLINK_STATE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_linkstate = LINK_STATE_DOWN;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_link_update(mh, linkstate);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * We now need to report back to the stream that invoked us, and then
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * drop the reference on the stream that we're holding.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai miocack(bsp->bs_wq, mp, 0, 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai stream_unref(bsp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaifail:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (macopen)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_close(mh);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai link_shutdown(blp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai miocnak(bsp->bs_wq, mp, 0, err);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai stream_unref(bsp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_rem_link(void *arg)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mblk_t *mp = arg;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_stream_t *bsp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_mac_t *bmp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai datalink_id_t linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_link_t *blp, *blsave;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai boolean_t found;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mblk_t *mlist;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bsp = (bridge_stream_t *)mp->b_next;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_next = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip = bsp->bs_inst;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai linkid = *(datalink_id_t *)mp->b_cont->b_rptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * We become reader here so that we can loop over the other links and
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * deliver link up/down notification.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai found = B_FALSE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (blp = list_head(&bip->bi_links); blp != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp = list_next(&bip->bi_links, blp)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_linkid == linkid &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai !(blp->bl_flags & BLF_DELETED)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_flags |= BLF_DELETED;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) ddi_taskq_dispatch(bridge_taskq, link_shutdown,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp, DDI_SLEEP);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai found = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Check if this link is up and the remainder of the links are all
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * down.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp != NULL && blp->bl_linkstate != LINK_STATE_DOWN) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (blp = list_head(&bip->bi_links); blp != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp = list_next(&bip->bi_links, blp)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_linkstate != LINK_STATE_DOWN &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai !(blp->bl_flags & (BLF_DELETED|BLF_SDUFAIL)))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (blp = list_head(&bip->bi_links); blp != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp = list_next(&bip->bi_links, blp)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!(blp->bl_flags & BLF_DELETED))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_link_redo(blp->bl_mh,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai LINK_STATE_DOWN);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmp = bip->bi_mac;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmp->bm_linkstate = LINK_STATE_DOWN;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_link_redo(bmp->bm_mh, LINK_STATE_DOWN);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Check if there's just one working link left on the bridge. If so,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * then that link is now authoritative for bridge MTU.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blsave = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (blp = list_head(&bip->bi_links); blp != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp = list_next(&bip->bi_links, blp)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!(blp->bl_flags & BLF_DELETED)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blsave == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blsave = blp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mlist = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmp = bip->bi_mac;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blsave != NULL && blp == NULL &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blsave->bl_maxsdu != bmp->bm_maxsdu) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bmp->bm_maxsdu = blsave->bl_maxsdu;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) mac_maxsdu_update(bmp->bm_mh, blsave->bl_maxsdu);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai link_sdu_fail(blsave, B_FALSE, &mlist);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai send_up_messages(bip, mlist);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (found)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai miocack(bsp->bs_wq, mp, 0, 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai miocnak(bsp->bs_wq, mp, 0, ENOENT);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai stream_unref(bsp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This function intentionally returns with bi_rwlock held; it is intended for
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * quick checks and updates.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic bridge_link_t *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaienter_link(bridge_inst_t *bip, datalink_id_t linkid)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_link_t *blp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (blp = list_head(&bip->bi_links); blp != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp = list_next(&bip->bi_links, blp)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_linkid == linkid && !(blp->bl_flags & BLF_DELETED))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (blp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_ioctl(queue_t *wq, mblk_t *mp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_stream_t *bsp = wq->q_ptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_t *bip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct iocblk *iop;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int rc = EINVAL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int len = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_link_t *blp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cred_t *cr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai iop = (struct iocblk *)mp->b_rptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * For now, all of the bridge ioctls are privileged.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((cr = msg_getcred(mp, NULL)) == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cr = iop->ioc_cr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (cr != NULL && secpolicy_net_config(cr, B_FALSE) != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai miocnak(wq, mp, 0, EPERM);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai switch (iop->ioc_cmd) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case BRIOC_NEWBRIDGE: {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_newbridge_t *bnb;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bsp->bs_inst != NULL ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (rc = miocpullup(mp, sizeof (bridge_newbridge_t))) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bnb = (bridge_newbridge_t *)mp->b_cont->b_rptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bnb->bnb_name[MAXNAMELEN-1] = '\0';
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy rc = bridge_create(bnb->bnb_linkid, bnb->bnb_name, &bip, cr);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy if (rc != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bip->bi_control != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_unref(bip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = EBUSY;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai atomic_inc_uint(&bip->bi_refs);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bsp->bs_inst = bip; /* stream holds reference */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip->bi_control = bsp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case BRIOC_ADDLINK:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((bip = bsp->bs_inst) == NULL ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (rc = miocpullup(mp, sizeof (datalink_id_t))) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * We cannot perform the action in this thread, because we're
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * not in process context, and we may already be holding
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * MAC-related locks. Place the request on taskq.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_next = (mblk_t *)bsp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai stream_ref(bsp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) ddi_taskq_dispatch(bridge_taskq, bridge_add_link, mp,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DDI_SLEEP);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case BRIOC_REMLINK:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((bip = bsp->bs_inst) == NULL ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (rc = miocpullup(mp, sizeof (datalink_id_t))) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * We cannot perform the action in this thread, because we're
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * not in process context, and we may already be holding
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * MAC-related locks. Place the request on taskq.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_next = (mblk_t *)bsp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai stream_ref(bsp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) ddi_taskq_dispatch(bridge_taskq, bridge_rem_link, mp,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DDI_SLEEP);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case BRIOC_SETSTATE: {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_setstate_t *bss;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((bip = bsp->bs_inst) == NULL ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (rc = miocpullup(mp, sizeof (*bss))) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bss = (bridge_setstate_t *)mp->b_cont->b_rptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((blp = enter_link(bip, bss->bss_linkid)) == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = ENOENT;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_state = bss->bss_state;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case BRIOC_SETPVID: {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_setpvid_t *bsv;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((bip = bsp->bs_inst) == NULL ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (rc = miocpullup(mp, sizeof (*bsv))) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bsv = (bridge_setpvid_t *)mp->b_cont->b_rptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bsv->bsv_vlan > VLAN_ID_MAX)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((blp = enter_link(bip, bsv->bsv_linkid)) == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = ENOENT;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else if (blp->bl_pvid == bsv->bsv_vlan) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai BRIDGE_VLAN_CLR(blp, blp->bl_pvid);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp->bl_pvid = bsv->bsv_vlan;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_pvid != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai BRIDGE_VLAN_SET(blp, blp->bl_pvid);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case BRIOC_VLANENAB: {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_vlanenab_t *bve;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((bip = bsp->bs_inst) == NULL ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (rc = miocpullup(mp, sizeof (*bve))) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bve = (bridge_vlanenab_t *)mp->b_cont->b_rptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bve->bve_vlan > VLAN_ID_MAX)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((blp = enter_link(bip, bve->bve_linkid)) == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = ENOENT;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* special case: vlan 0 means "all" */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bve->bve_vlan == 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) memset(blp->bl_vlans,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bve->bve_onoff ? ~0 : 0,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (blp->bl_vlans));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai BRIDGE_VLAN_CLR(blp, 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_pvid != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai BRIDGE_VLAN_SET(blp, blp->bl_pvid);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else if (bve->bve_vlan == blp->bl_pvid) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = EINVAL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else if (bve->bve_onoff) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai BRIDGE_VLAN_SET(blp, bve->bve_vlan);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai BRIDGE_VLAN_CLR(blp, bve->bve_vlan);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case BRIOC_FLUSHFWD: {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_flushfwd_t *bff;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_fwd_t *bfp, *bfnext;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_tree_t fwd_scavenge;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int i;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((bip = bsp->bs_inst) == NULL ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (rc = miocpullup(mp, sizeof (*bff))) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bff = (bridge_flushfwd_t *)mp->b_cont->b_rptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bip->bi_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* This case means "all" */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bff->bff_linkid == DATALINK_INVALID_LINKID) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (blp = list_head(&bip->bi_links); blp != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai blp = list_next(&bip->bi_links, blp)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp->bl_linkid == bff->bff_linkid &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai !(blp->bl_flags & BLF_DELETED))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = ENOENT;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_create(&fwd_scavenge, fwd_compare, sizeof (bridge_fwd_t),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai offsetof(bridge_fwd_t, bf_node));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnext = avl_first(&bip->bi_fwd);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while ((bfp = bfnext) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnext = AVL_NEXT(&bip->bi_fwd, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp->bf_flags & BFF_LOCALADDR)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (blp != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (i = 0; i < bfp->bf_maxlinks; i++) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bfp->bf_links[i] == blp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If the link is there and we're excluding,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * then skip. If the link is not there and
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * we're doing only that link, then skip.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((i < bfp->bf_maxlinks) == bff->bff_exclude)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(bfp->bf_flags & BFF_INTREE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_remove(&bip->bi_fwd, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfp->bf_flags &= ~BFF_INTREE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_add(&fwd_scavenge, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bip->bi_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnext = avl_first(&fwd_scavenge);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while ((bfp = bfnext) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bfnext = AVL_NEXT(&fwd_scavenge, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_remove(&fwd_scavenge, bfp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_unref(bfp); /* drop tree reference */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai avl_destroy(&fwd_scavenge);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case BRIOC_TABLEMAX:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((bip = bsp->bs_inst) == NULL ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (rc = miocpullup(mp, sizeof (uint32_t))) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bip->bi_tablemax = *(uint32_t *)mp->b_cont->b_rptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (rc == 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai miocack(wq, mp, len, 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai miocnak(wq, mp, 0, rc);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_wput(queue_t *wq, mblk_t *mp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai switch (DB_TYPE(mp)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case M_IOCTL:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_ioctl(wq, mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case M_FLUSH:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (*mp->b_rptr & FLUSHW)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *mp->b_rptr &= ~FLUSHW;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (*mp->b_rptr & FLUSHR)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai qreply(wq, mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai default:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This function allocates the main data structures for the bridge driver and
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * connects us into devfs.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_inst_init(void)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_scan_interval = 5 * drv_usectohz(1000000);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_fwd_age = 25 * drv_usectohz(1000000);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_init(&bmac_rwlock, NULL, RW_DRIVER, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai list_create(&bmac_list, sizeof (bridge_mac_t),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai offsetof(bridge_mac_t, bm_node));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai list_create(&inst_list, sizeof (bridge_inst_t),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai offsetof(bridge_inst_t, bi_node));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_init(&inst_cv, NULL, CV_DRIVER, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_init(&inst_lock, NULL, MUTEX_DRIVER, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_init(&stream_ref_cv, NULL, CV_DRIVER, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_init(&stream_ref_lock, NULL, MUTEX_DRIVER, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_bridge_vectors(bridge_xmit_cb, bridge_recv_cb, bridge_ref_cb,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_ls_cb);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This function disconnects from devfs and destroys all data structures in
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * preparation for unload. It's assumed that there are no active bridge
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * references left at this point.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_inst_fini(void)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mac_bridge_vectors(NULL, NULL, NULL, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bridge_timerid != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) untimeout(bridge_timerid);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_destroy(&bmac_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai list_destroy(&bmac_list);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai list_destroy(&inst_list);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_destroy(&inst_cv);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_destroy(&inst_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_destroy(&stream_ref_cv);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_destroy(&stream_ref_lock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridge_attach()
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Description:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Attach bridge driver to the system.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (cmd != DDI_ATTACH)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (DDI_FAILURE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (ddi_create_minor_node(dip, BRIDGE_CTL, S_IFCHR, 0, DDI_PSEUDO,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai CLONE_DEV) == DDI_FAILURE) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (DDI_FAILURE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (dld_ioc_register(BRIDGE_IOC, bridge_ioc_list,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DLDIOCCNT(bridge_ioc_list)) != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ddi_remove_minor_node(dip, BRIDGE_CTL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (DDI_FAILURE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_dev_info = dip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_major = ddi_driver_major(dip);
f2905fb789fa42069fdb0ba5bd1b61400e23f348Rishi Srivatsavai bridge_taskq = ddi_taskq_create(dip, BRIDGE_DEV_NAME, 1,
f2905fb789fa42069fdb0ba5bd1b61400e23f348Rishi Srivatsavai TASKQ_DEFAULTPRI, 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (DDI_SUCCESS);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridge_detach()
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Description:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Detach an interface to the system.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (cmd != DDI_DETACH)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (DDI_FAILURE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ddi_remove_minor_node(dip, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ddi_taskq_destroy(bridge_taskq);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_dev_info = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (DDI_SUCCESS);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridge_info()
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Description:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Translate "dev_t" to a pointer to the associated "dev_info_t".
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* ARGSUSED */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai void **result)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int rc;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai switch (infocmd) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case DDI_INFO_DEVT2DEVINFO:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bridge_dev_info == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = DDI_FAILURE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *result = (void *)bridge_dev_info;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = DDI_SUCCESS;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case DDI_INFO_DEVT2INSTANCE:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *result = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = DDI_SUCCESS;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai default:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = DDI_FAILURE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (rc);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic struct module_info bridge_modinfo = {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai 2105, /* mi_idnum */
f2905fb789fa42069fdb0ba5bd1b61400e23f348Rishi Srivatsavai BRIDGE_DEV_NAME, /* mi_idname */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai 0, /* mi_minpsz */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai 16384, /* mi_maxpsz */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai 65536, /* mi_hiwat */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai 128 /* mi_lowat */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai};
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic struct qinit bridge_rinit = {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, /* qi_putp */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, /* qi_srvp */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_open, /* qi_qopen */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_close, /* qi_qclose */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, /* qi_qadmin */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai &bridge_modinfo, /* qi_minfo */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL /* qi_mstat */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai};
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic struct qinit bridge_winit = {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (int (*)())bridge_wput, /* qi_putp */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, /* qi_srvp */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, /* qi_qopen */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, /* qi_qclose */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, /* qi_qadmin */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai &bridge_modinfo, /* qi_minfo */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL /* qi_mstat */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai};
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic struct streamtab bridge_tab = {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai &bridge_rinit, /* st_rdinit */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai &bridge_winit /* st_wrinit */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai};
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* No STREAMS perimeters; we do all our own locking */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi SrivatsavaiDDI_DEFINE_STREAM_OPS(bridge_ops, nulldev, nulldev, bridge_attach,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_detach, nodev, bridge_info, D_NEW | D_MP, &bridge_tab,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ddi_quiesce_not_supported);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic struct modldrv modldrv = {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai &mod_driverops,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai "bridging driver",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai &bridge_ops
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai};
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic struct modlinkage modlinkage = {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai MODREV_1,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void *)&modldrv,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai};
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiint
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai_init(void)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int retv;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
f2905fb789fa42069fdb0ba5bd1b61400e23f348Rishi Srivatsavai mac_init_ops(NULL, BRIDGE_DEV_NAME);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_init();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((retv = mod_install(&modlinkage)) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_fini();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (retv);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiint
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai_fini(void)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int retv;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&bmac_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai retv = list_is_empty(&bmac_list) ? 0 : EBUSY;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&bmac_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (retv == 0 &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (retv = mod_remove(&modlinkage)) == 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_inst_fini();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (retv);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiint
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai_info(struct modinfo *modinfop)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (mod_info(&modlinkage, modinfop));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}