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 supports AF_TRILL sockets and TRILL layer-2 forwarding.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/strsubr.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/socket.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/socketvar.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/modctl.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/cmn_err.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/tihdr.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/strsun.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/policy.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/ethernet.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/vlan.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <net/trill.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <net/if_dl.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/mac.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/mac_client.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/mac_provider.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/mac_client_priv.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/sdt.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/dls.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/sunddi.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include "trill_impl.h"
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void trill_del_all(trill_inst_t *, boolean_t);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int trill_del_nick(trill_inst_t *, uint16_t, boolean_t);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void trill_stop_recv(trill_sock_t *);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void trill_ctrl_input(trill_sock_t *, mblk_t *, const uint8_t *,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic trill_node_t *trill_node_lookup(trill_inst_t *, uint16_t);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void trill_node_unref(trill_inst_t *, trill_node_t *);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void trill_sock_unref(trill_sock_t *);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void trill_kstats_init(trill_sock_t *, const char *);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic list_t trill_inst_list;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic krwlock_t trill_inst_rwlock;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic sock_lower_handle_t trill_create(int, int, int, sock_downcalls_t **,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint_t *, int *, int, cred_t *);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic smod_reg_t sinfo = {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai SOCKMOD_VERSION,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai "trill",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai SOCK_UC_VERSION,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai SOCK_DC_VERSION,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_create,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai};
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* modldrv structure */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic struct modlsockmod sockmod = {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai &mod_sockmodops, "AF_TRILL socket module", &sinfo
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai};
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* modlinkage structure */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic struct modlinkage ml = {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai MODREV_1,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai &sockmod,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai};
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#define VALID_NICK(n) ((n) != RBRIDGE_NICKNAME_NONE && \
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (n) != RBRIDGE_NICKNAME_UNUSED)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic mblk_t *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaicreate_trill_header(trill_sock_t *tsock, mblk_t *mp, const uint8_t *daddr,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai boolean_t trill_hdr_ok, boolean_t multidest, uint16_t tci,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai size_t msglen)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int extra_hdr_len;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct ether_vlan_header *ethvlanhdr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mblk_t *hdr_mp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t etype;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai etype = msglen > 0 ? (uint16_t)msglen : ETHERTYPE_TRILL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* When sending on the PVID, we must not give a VLAN ID */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tci == tsock->ts_link->bl_pvid)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tci = TRILL_NO_TCI;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Create new Ethernet header and include additional space
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * for writing TRILL header and/or VLAN tag.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai extra_hdr_len = (trill_hdr_ok ? 0 : sizeof (trill_header_t)) +
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (tci != TRILL_NO_TCI ? sizeof (struct ether_vlan_extinfo) : 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai hdr_mp = mac_header(tsock->ts_link->bl_mh, daddr,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tci != TRILL_NO_TCI ? ETHERTYPE_VLAN : etype, mp, extra_hdr_len);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (hdr_mp == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tci != TRILL_NO_TCI) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ethvlanhdr = (struct ether_vlan_header *)hdr_mp->b_rptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ethvlanhdr->ether_tci = htons(tci);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ethvlanhdr->ether_type = htons(etype);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai hdr_mp->b_wptr += sizeof (struct ether_vlan_extinfo);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!trill_hdr_ok) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_header_t *thp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai thp = (trill_header_t *)hdr_mp->b_wptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) memset(thp, 0, sizeof (trill_header_t));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai thp->th_hopcount = TRILL_DEFAULT_HOPS;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai thp->th_multidest = (multidest ? 1:0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai hdr_mp->b_wptr += sizeof (trill_header_t);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai hdr_mp->b_cont = mp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (hdr_mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * TRILL local recv function. TRILL data frames that should be received
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * by the local system are decapsulated here and passed to bridging for
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * learning and local system receive. Only called when we are the forwarder
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * on the link (multi-dest frames) or the frame was destined for us.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_recv_local(trill_sock_t *tsock, mblk_t *mp, uint16_t ingressnick)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct ether_header *inner_ethhdr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai inner_ethhdr = (struct ether_header *)mp->b_rptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DTRACE_PROBE1(trill__recv__local, struct ether_header *, inner_ethhdr);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DB_CKSUMFLAGS(mp) = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Transmit the decapsulated frame on the link via Bridging.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Bridging does source address learning and appropriate forwarding.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_trill_decaps(tsock->ts_link, mp, ingressnick);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSPINCR(tks_decap);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Determines the outgoing link to reach a RBridge having the given nick
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Assumes caller has acquired the trill instance rwlock.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic trill_sock_t *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaifind_trill_link(trill_inst_t *tip, datalink_id_t linkid)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_sock_t *tsp = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(RW_LOCK_HELD(&tip->ti_rwlock));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (tsp = list_head(&tip->ti_socklist); tsp != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsp = list_next(&tip->ti_socklist, tsp)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tsp->ts_link != NULL && tsp->ts_link->bl_linkid == linkid) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(tsp->ts_link->bl_mh != NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(!(tsp->ts_flags & TSF_SHUTDOWN));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai atomic_inc_uint(&tsp->ts_refs);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (tsp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * TRILL destination forwarding function. Transmits the TRILL data packet
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * to the next-hop, adjacent RBridge. Consumes passed mblk_t.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_dest_fwd(trill_inst_t *tip, mblk_t *fwd_mp, uint16_t adj_nick,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai boolean_t has_trill_hdr, boolean_t multidest, uint16_t dtnick)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_t *adj;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_sock_t *tsock = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_header_t *trillhdr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct ether_header *ethhdr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int ethtype;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int ethhdrlen;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai adj = trill_node_lookup(tip, adj_nick);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (adj == NULL || ((tsock = adj->tn_tsp) == NULL))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto dest_fwd_fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(tsock->ts_link != NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(!(tsock->ts_flags & TSF_SHUTDOWN));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(adj->tn_ni != NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DTRACE_PROBE3(trill__dest__fwd, uint16_t, adj_nick, trill_node_t,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai adj, trill_sock_t, tsock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * For broadcast links by using the dest address of
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * the RBridge to forward the frame should result in
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * savings. When the link is a bridged LAN or there are
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * many end stations the frame will not always be flooded.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_mp = create_trill_header(tsock, fwd_mp, adj->tn_ni->tni_adjsnpa,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai has_trill_hdr, multidest, tsock->ts_desigvlan, 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (fwd_mp == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto dest_fwd_fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ethhdr = (struct ether_header *)fwd_mp->b_rptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ethtype = ntohs(ethhdr->ether_type);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(ethtype == ETHERTYPE_VLAN || ethtype == ETHERTYPE_TRILL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Pullup Ethernet and TRILL header (w/o TRILL options) */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ethhdrlen = sizeof (struct ether_header) +
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (ethtype == ETHERTYPE_VLAN ? sizeof (struct ether_vlan_extinfo):0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!pullupmsg(fwd_mp, ethhdrlen + sizeof (trill_header_t)))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto dest_fwd_fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trillhdr = (struct trill_header *)(fwd_mp->b_rptr + ethhdrlen);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Update TRILL header with ingress and egress nicks for new frames */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!has_trill_hdr) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* We are creating a new TRILL frame */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trillhdr->th_egressnick = (multidest ? dtnick:adj_nick);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&tip->ti_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trillhdr->th_ingressnick = tip->ti_nick;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&tip->ti_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!VALID_NICK(trillhdr->th_ingressnick))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto dest_fwd_fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Set hop count and update header in packet */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(trillhdr->th_hopcount != 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trillhdr->th_hopcount--;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Clear checksum flag and transmit frame on the link */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DB_CKSUMFLAGS(fwd_mp) = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DTRACE_PROBE1(trill__dest__fwd__tx, trill_header_t *, &trillhdr);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_mp = bridge_trill_output(tsock->ts_link, fwd_mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (fwd_mp == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSPINCR(tks_sent);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSPINCR(tks_forward);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(fwd_mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSPINCR(tks_drops);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_unref(tip, adj);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaidest_fwd_fail:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (adj != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_unref(tip, adj);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tsock != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSPINCR(tks_drops);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(fwd_mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * TRILL multi-destination forwarding. Transmits the packet to the adjacencies
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * on the distribution tree determined by the egress nick. Source addr (saddr)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * is NULL for new TRILL packets originating from us.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_multidest_fwd(trill_inst_t *tip, mblk_t *mp, uint16_t egressnick,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t ingressnick, boolean_t is_trill_pkt, const uint8_t *saddr,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int inner_vlan, boolean_t free_mblk)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int idx;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t adjnick;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_t *dest;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_t *adj;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mblk_t *fwd_mp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai boolean_t nicksaved = B_FALSE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t adjnicksaved;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Lookup the egress nick info, this is the DT root */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((dest = trill_node_lookup(tip, egressnick)) == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail_multidest_fwd;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Send a copy to all our adjacencies on the DT root */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(dest->tn_ni);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (idx = 0; idx < dest->tn_ni->tni_adjcount; idx++) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Check for a valid adjacency node */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai adjnick = TNI_ADJNICK(dest->tn_ni, idx);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!VALID_NICK(adjnick) || ingressnick == adjnick ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ((adj = trill_node_lookup(tip, adjnick)) == NULL))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Do not forward back to adjacency that sent the pkt to us */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(adj->tn_ni != NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((saddr != NULL) &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (memcmp(adj->tn_ni->tni_adjsnpa, saddr,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ETHERADDRL) == 0)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_unref(tip, adj);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Check if adj is marked as reaching inner VLAN downstream */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((inner_vlan != VLAN_ID_NONE) &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai !TRILL_VLANISSET(TNI_VLANFILTERMAP(dest->tn_ni, idx),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai inner_vlan)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_unref(tip, adj);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DTRACE_PROBE4(trill__multi__dest__fwd__vlanfiltered,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t, adjnick, uint16_t, ingressnick,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t, egressnick, int, inner_vlan);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_unref(tip, adj);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Save the nick and look ahead to see if we should forward the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * frame to more adjacencies. We avoid doing a copy for this
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * nick and use the passed mblk when we can consume the passed
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * mblk.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (free_mblk && !nicksaved) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai adjnicksaved = adjnick;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai nicksaved = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fwd_mp = copymsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (fwd_mp == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DTRACE_PROBE2(trill__multi__dest__fwd, uint16_t,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai adjnick, uint16_t, ingressnick);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_dest_fwd(tip, fwd_mp, adjnick, is_trill_pkt,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai B_TRUE, egressnick);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_unref(tip, dest);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (nicksaved) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(free_mblk);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DTRACE_PROBE2(trill__multi__dest__fwd, uint16_t,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai adjnicksaved, uint16_t, ingressnick);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_dest_fwd(tip, mp, adjnicksaved, is_trill_pkt,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai B_TRUE, egressnick);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaifail_multidest_fwd:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DTRACE_PROBE2(trill__multi__dest__fwd__fail, uint16_t,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai egressnick, uint16_t, ingressnick);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (free_mblk) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * TRILL data receive function. Forwards the received frame if necessary
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * and also determines if the received frame should be consumed locally.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Consumes passed mblk.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_recv(trill_sock_t *tsock, mblk_t *mp, const uint8_t *mpsaddr)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_header_t *trillhdr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_t *dest = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_t *source = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_t *adj;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t ournick, adjnick, treeroot;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct ether_header *ethhdr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_inst_t *tip = tsock->ts_tip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint8_t srcaddr[ETHERADDRL];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai size_t trillhdrlen;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int inner_vlan = VLAN_ID_NONE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int tci;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int idx;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai size_t min_size;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Copy Ethernet source address before modifying packet */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) memcpy(srcaddr, mpsaddr, ETHERADDRL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Pull up TRILL header if necessary. */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai min_size = sizeof (trill_header_t);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((MBLKL(mp) < min_size ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai !IS_P2ALIGNED(mp->b_rptr, TRILL_HDR_ALIGN)) &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai !pullupmsg(mp, min_size))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trillhdr = (trill_header_t *)mp->b_rptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (trillhdr->th_version != TRILL_PROTOCOL_VERS) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DTRACE_PROBE1(trill__recv__wrongversion,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_header_t *, trillhdr);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Drop if unknown or invalid nickname */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!VALID_NICK(trillhdr->th_egressnick) ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai !VALID_NICK(trillhdr->th_ingressnick)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DTRACE_PROBE1(trill__recv__invalidnick,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_header_t *, trillhdr);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&tip->ti_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ournick = tip->ti_nick;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai treeroot = tip->ti_treeroot;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&tip->ti_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Drop if we received a packet with our nick as ingress */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (trillhdr->th_ingressnick == ournick)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Re-pull any TRILL options and inner Ethernet header */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai min_size += GET_TRILL_OPTS_LEN(trillhdr) * sizeof (uint32_t) +
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (struct ether_header);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (MBLKL(mp) < min_size) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!pullupmsg(mp, min_size))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trillhdr = (trill_header_t *)mp->b_rptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trillhdrlen = sizeof (trill_header_t) +
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (GET_TRILL_OPTS_LEN(trillhdr) * sizeof (uint32_t));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Get the inner Ethernet header, plus the inner VLAN header if there
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * is one.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ethhdr = (struct ether_header *)(mp->b_rptr + trillhdrlen);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (ethhdr->ether_type == htons(ETHERTYPE_VLAN)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai min_size += sizeof (struct ether_vlan_extinfo);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (MBLKL(mp) < min_size) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!pullupmsg(mp, min_size))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trillhdr = (trill_header_t *)mp->b_rptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ethhdr = (struct ether_header *)(mp->b_rptr +
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trillhdrlen);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tci = ntohs(((struct ether_vlan_header *)ethhdr)->ether_tci);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai inner_vlan = VLAN_ID(tci);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Known/single destination forwarding. */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!trillhdr->th_multidest) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Inner MacDA must be unicast */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (ethhdr->ether_dhost.ether_addr_octet[0] & 1)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Ingress and Egress nicks must be different */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (trillhdr->th_egressnick == trillhdr->th_ingressnick)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DTRACE_PROBE1(trill__recv__singledest,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_header_t *, trillhdr);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (trillhdr->th_egressnick == ournick) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_rptr += trillhdrlen;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_recv_local(tsock, mp, trillhdr->th_ingressnick);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else if (trillhdr->th_hopcount > 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_dest_fwd(tip, mp, trillhdr->th_egressnick,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai B_TRUE, B_FALSE, RBRIDGE_NICKNAME_NONE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Multi-destination frame: perform checks verifying we have
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * received a valid multi-destination frame before receiving the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * frame locally and forwarding the frame to other RBridges.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Check if we received this multi-destination frame on a
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * adjacency in the distribution tree indicated by the frame's
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * egress nickname.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((dest = trill_node_lookup(tip, trillhdr->th_egressnick)) == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (idx = 0; idx < dest->tn_ni->tni_adjcount; idx++) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai adjnick = TNI_ADJNICK(dest->tn_ni, idx);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((adj = trill_node_lookup(tip, adjnick)) == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai continue;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (memcmp(adj->tn_ni->tni_adjsnpa, srcaddr, ETHERADDRL) == 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_unref(tip, adj);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_unref(tip, adj);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (idx >= dest->tn_ni->tni_adjcount) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DTRACE_PROBE2(trill__recv__multidest__adjcheckfail,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_header_t *, trillhdr, trill_node_t *, dest);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Reverse path forwarding check. Check if the ingress RBridge
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * that has forwarded the frame advertised the use of the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * distribution tree specified in the egress nick.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((source = trill_node_lookup(tip, trillhdr->th_ingressnick)) == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (idx = 0; idx < source->tn_ni->tni_dtrootcount; idx++) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (TNI_DTROOTNICK(source->tn_ni, idx) ==
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trillhdr->th_egressnick)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (idx >= source->tn_ni->tni_dtrootcount) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Allow receipt of forwarded frame with the highest
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * tree root RBridge as the egress RBridge when the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * ingress RBridge has not advertised the use of any
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * distribution trees.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (source->tn_ni->tni_dtrootcount != 0 ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trillhdr->th_egressnick != treeroot) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DTRACE_PROBE3(
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill__recv__multidest__rpfcheckfail,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_header_t *, trillhdr, trill_node_t *,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai source, trill_inst_t *, tip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Check hop count before doing any forwarding */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (trillhdr->th_hopcount == 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto fail;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Forward frame using the distribution tree specified by egress nick */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DTRACE_PROBE2(trill__recv__multidest, trill_header_t *,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trillhdr, trill_node_t *, source);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_unref(tip, source);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_unref(tip, dest);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Tell forwarding not to free if we're the link forwarder. */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_multidest_fwd(tip, mp, trillhdr->th_egressnick,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trillhdr->th_ingressnick, B_TRUE, srcaddr, inner_vlan,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai B_FALSE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Send de-capsulated frame locally if we are the link forwarder (also
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * does bridge learning).
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_rptr += trillhdrlen;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_recv_local(tsock, mp, trillhdr->th_ingressnick);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSPINCR(tks_recv);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaifail:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DTRACE_PROBE2(trill__recv__multidest__fail, mblk_t *, mp,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_sock_t *, tsock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (dest != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_unref(tip, dest);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (source != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_unref(tip, source);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSPINCR(tks_drops);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_stop_recv(trill_sock_t *tsock)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&tsock->ts_socklock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistop_retry:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tsock->ts_state == TS_UNBND || tsock->ts_link == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&tsock->ts_socklock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If another thread is closing the socket then wait. Our callers
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * expect us to return only after the socket is closed.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tsock->ts_flags & TSF_CLOSEWAIT) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_wait(&tsock->ts_sockclosewait, &tsock->ts_socklock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto stop_retry;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Set state and flags to block new bind or close calls
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * while we close the socket.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock->ts_flags |= TSF_CLOSEWAIT;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Wait until all AF_TRILL socket transmit operations are done */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while (tsock->ts_sockthreadcount > 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_wait(&tsock->ts_sockthreadwait, &tsock->ts_socklock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * We are guaranteed to be the only thread closing on the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * socket while the TSF_CLOSEWAIT flag is set, all others cv_wait
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * for us to finish.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(tsock->ts_link != NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tsock->ts_ksp != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kstat_delete(tsock->ts_ksp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Release lock before bridge_trill_lnunref to prevent deadlock
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * between trill_ctrl_input thread waiting to acquire ts_socklock
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * and bridge_trill_lnunref waiting for the trill thread to finish.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&tsock->ts_socklock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Release TRILL link reference from Bridging. On return from
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridge_trill_lnunref we can be sure there are no active TRILL data
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * threads for this link.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_trill_lnunref(tsock->ts_link);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Set socket as unbound & wakeup threads waiting for socket to close */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&tsock->ts_socklock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(tsock->ts_link != NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock->ts_link = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock->ts_state = TS_UNBND;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock->ts_flags &= ~TSF_CLOSEWAIT;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_broadcast(&tsock->ts_sockclosewait);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&tsock->ts_socklock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_start_recv(trill_sock_t *tsock, const struct sockaddr *sa, socklen_t len)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct sockaddr_dl *lladdr = (struct sockaddr_dl *)sa;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai datalink_id_t linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int err = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (len != sizeof (*lladdr))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EINVAL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&tsock->ts_socklock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tsock->ts_tip == NULL || tsock->ts_state != TS_UNBND) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai err = EINVAL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto bind_error;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tsock->ts_flags & TSF_CLOSEWAIT || tsock->ts_link != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai err = EBUSY;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto bind_error;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) memcpy(&(tsock->ts_lladdr), lladdr,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (struct sockaddr_dl));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) memcpy(&linkid, tsock->ts_lladdr.sdl_data,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (datalink_id_t));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock->ts_link = bridge_trill_lnref(tsock->ts_tip->ti_binst,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai linkid, tsock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tsock->ts_link == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai err = EINVAL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto bind_error;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_kstats_init(tsock, tsock->ts_tip->ti_bridgename);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock->ts_state = TS_IDLE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibind_error:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&tsock->ts_socklock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (err);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_do_unbind(trill_sock_t *tsock)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* If a bind has not been done, we can't unbind. */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tsock->ts_state != TS_IDLE)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EINVAL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_stop_recv(tsock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_instance_unref(trill_inst_t *tip)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&trill_inst_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&tip->ti_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (atomic_dec_uint_nv(&tip->ti_refs) == 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai list_remove(&trill_inst_list, tip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&tip->ti_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&trill_inst_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tip->ti_binst != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_trill_brunref(tip->ti_binst);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai list_destroy(&tip->ti_socklist);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_destroy(&tip->ti_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kmem_free(tip, sizeof (*tip));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&tip->ti_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&trill_inst_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This is called when the bridge module receives a TRILL-encapsulated packet
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * on a given link or a packet identified as "TRILL control." We must verify
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * that it's for us (it almost certainly will be), and then either decapsulate
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * (if it's to our nickname), forward (if it's to someone else), or send up one
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * of the sockets (if it's control traffic).
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Sadly, on Ethernet, the control traffic is identified by Outer.MacDA, and
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * not by TRILL header information.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_recv_pkt_cb(void *lptr, bridge_link_t *blp, mac_resource_handle_t rsrc,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mblk_t *mp, mac_header_info_t *hdr_info)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_sock_t *tsock = lptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai _NOTE(ARGUNUSED(rsrc));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(tsock->ts_tip != NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(tsock->ts_link != NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(!(tsock->ts_flags & TSF_SHUTDOWN));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Only receive packet if the source address is not multicast (which is
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bogus).
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (hdr_info->mhi_saddr[0] & 1)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto discard;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Check if this is our own packet reflected back. It should not be.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (bcmp(hdr_info->mhi_saddr, blp->bl_local_mac, ETHERADDRL) == 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto discard;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Only receive unicast packet if addressed to us */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (hdr_info->mhi_dsttype == MAC_ADDRTYPE_UNICAST &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bcmp(hdr_info->mhi_daddr, blp->bl_local_mac, ETHERADDRL) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto discard;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (hdr_info->mhi_bindsap == ETHERTYPE_TRILL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* TRILL data packets */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_recv(tsock, mp, hdr_info->mhi_saddr);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Design constraint for cheap IS-IS/BPDU comparison */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(all_isis_rbridges[4] != bridge_group_address[4]);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Send received control packet upstream */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_ctrl_input(tsock, mp, hdr_info->mhi_saddr,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai hdr_info->mhi_daddr[4] == all_isis_rbridges[4] ?
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai hdr_info->mhi_tci : TRILL_TCI_BPDU);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaidiscard:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSPINCR(tks_drops);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This is called when the bridge module discovers that the destination address
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * for a packet is not local -- it's through some remote node. We must verify
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * that the remote node isn't our nickname (it shouldn't be), add a TRILL
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * header, and then use the IS-IS data to determine which link and which
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * next-hop RBridge should be used for output. We then transmit on that link.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * The egress_nick is RBRIDGE_NICKNAME_NONE for the "unknown destination" case.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_encap_pkt_cb(void *lptr, bridge_link_t *blp, mac_header_info_t *hdr_info,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mblk_t *mp, uint16_t egress_nick)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t ournick;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t dtnick;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_t *self = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_sock_t *tsock = lptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_inst_t *tip = tsock->ts_tip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int vlan = VLAN_ID_NONE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai _NOTE(ARGUNUSED(blp));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(hdr_info->mhi_bindsap != ETHERTYPE_TRILL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* egress_nick = RBRIDGE_NICKNAME_NONE is valid */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (egress_nick != RBRIDGE_NICKNAME_NONE && !VALID_NICK(egress_nick))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto discard;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Check if our own nick is valid before we do any forwarding */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&tip->ti_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ournick = tip->ti_nick;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dtnick = tip->ti_treeroot;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&tip->ti_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!VALID_NICK(ournick))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto discard;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * For Multi-Destination forwarding determine our choice of
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * root distribution tree. If we didn't choose a distribution
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * tree (dtroots_count=0) then we use the highest priority tree
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * root (t_treeroot) else we drop the packet without forwarding.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (egress_nick == RBRIDGE_NICKNAME_NONE) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((self = trill_node_lookup(tip, ournick)) == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto discard;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Use the first DT configured for now. In future we
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * should have DT selection code here.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (self->tn_ni->tni_dtrootcount > 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dtnick = TNI_DTROOTNICK(self->tn_ni, 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_unref(tip, self);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!VALID_NICK(dtnick)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DTRACE_PROBE(trill__fwd__packet__nodtroot);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto discard;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Retrieve VLAN ID of the native frame used for VLAN
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * pruning of multi-destination frames.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (hdr_info->mhi_istagged) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai vlan = VLAN_ID(hdr_info->mhi_tci);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DTRACE_PROBE2(trill__fwd__packet, mac_header_info_t *, hdr_info,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t, egress_nick);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (egress_nick == RBRIDGE_NICKNAME_NONE) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_multidest_fwd(tip, mp, dtnick,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ournick, B_FALSE, NULL, vlan, B_TRUE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_dest_fwd(tip, mp, egress_nick, B_FALSE, B_FALSE,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai RBRIDGE_NICKNAME_NONE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSPINCR(tks_encap);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaidiscard:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This is called when the bridge module has completely torn down a bridge
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * instance and all of the attached links. We need to make the TRILL instance
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * go away at this point.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_br_dstr_cb(void *bptr, bridge_inst_t *bip)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_inst_t *tip = bptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai _NOTE(ARGUNUSED(bip));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&tip->ti_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tip->ti_binst != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_trill_brunref(tip->ti_binst);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tip->ti_binst = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&tip->ti_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This is called when the bridge module is tearing down a link, but before the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * actual tear-down starts. When this function returns, we must make sure that
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * we will not initiate any new transmits on this link.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_ln_dstr_cb(void *lptr, bridge_link_t *blp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_sock_t *tsock = lptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai _NOTE(ARGUNUSED(blp));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_stop_recv(tsock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_init(void)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai list_create(&trill_inst_list, sizeof (trill_inst_t),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai offsetof(trill_inst_t, ti_instnode));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_init(&trill_inst_rwlock, NULL, RW_DRIVER, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_trill_register_cb(trill_recv_pkt_cb, trill_encap_pkt_cb,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_br_dstr_cb, trill_ln_dstr_cb);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_fini(void)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_trill_register_cb(NULL, NULL, NULL, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_destroy(&trill_inst_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai list_destroy(&trill_inst_list);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* Loadable module configuration entry points */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiint
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai_init(void)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int rc;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_init();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((rc = mod_install(&ml)) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_fini();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (rc);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiint
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai_info(struct modinfo *modinfop)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (mod_info(&ml, modinfop));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiint
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai_fini(void)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int rc;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&trill_inst_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = list_is_empty(&trill_inst_list) ? 0 : EBUSY;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&trill_inst_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (rc == 0 && ((rc = mod_remove(&ml)) == 0))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_fini();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (rc);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_kstats_init(trill_sock_t *tsock, const char *bname)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int i;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai char kstatname[KSTAT_STRLEN];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kstat_named_t *knt;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai static const char *sock_kstats_list[] = { TRILL_KSSOCK_NAMES };
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai char link_name[MAXNAMELEN];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int num;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int err;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bzero(link_name, sizeof (link_name));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((err = dls_mgmt_get_linkinfo(tsock->ts_link->bl_linkid, link_name,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, NULL, NULL)) != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cmn_err(CE_WARN, "%s: trill_kstats_init: error %d retrieving"
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai " linkinfo for linkid:%d", "trill", err,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock->ts_link->bl_linkid);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bzero(kstatname, sizeof (kstatname));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) snprintf(kstatname, sizeof (kstatname), "%s-%s",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bname, link_name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai num = sizeof (sock_kstats_list) / sizeof (*sock_kstats_list);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (i = 0; i < num; i++) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai knt = (kstat_named_t *)&(tsock->ts_kstats);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kstat_named_init(&knt[i], sock_kstats_list[i],
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSTAT_DATA_UINT64);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock->ts_ksp = kstat_create_zone("trill", 0, kstatname, "sock",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSTAT_TYPE_NAMED, num, KSTAT_FLAG_VIRTUAL, GLOBAL_ZONEID);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tsock->ts_ksp != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock->ts_ksp->ks_data = &tsock->ts_kstats;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kstat_install(tsock->ts_ksp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic trill_sock_t *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_do_open(int flags)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_sock_t *tsock;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int kmflag = ((flags & SOCKET_NOSLEEP)) ? KM_NOSLEEP:KM_SLEEP;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock = kmem_zalloc(sizeof (trill_sock_t), kmflag);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tsock != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock->ts_state = TS_UNBND;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock->ts_refs++;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_init(&tsock->ts_socklock, NULL, MUTEX_DRIVER, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_init(&tsock->ts_sockthreadwait, NULL, CV_DRIVER, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_init(&tsock->ts_sockclosewait, NULL, CV_DRIVER, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (tsock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_find_bridge(trill_sock_t *tsock, const char *bname, boolean_t can_create)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_inst_t *tip, *newtip = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Allocate some memory (speculatively) before taking locks */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (can_create)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai newtip = kmem_zalloc(sizeof (*tip), KM_NOSLEEP);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&trill_inst_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (tip = list_head(&trill_inst_list); tip != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tip = list_next(&trill_inst_list, tip)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (strcmp(tip->ti_bridgename, bname) == 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tip == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!can_create || newtip == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&trill_inst_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (can_create ? ENOMEM : ENOENT);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tip = newtip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai newtip = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) strcpy(tip->ti_bridgename, bname);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Register TRILL instance with bridging */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tip->ti_binst = bridge_trill_brref(bname, tip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tip->ti_binst == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&trill_inst_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kmem_free(tip, sizeof (*tip));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (ENOENT);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_init(&tip->ti_rwlock, NULL, RW_DRIVER, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai list_create(&tip->ti_socklist, sizeof (trill_sock_t),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai offsetof(trill_sock_t, ts_socklistnode));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai list_insert_tail(&trill_inst_list, tip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai atomic_inc_uint(&tip->ti_refs);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&trill_inst_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* If we didn't need the preallocated memory, then discard now. */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (newtip != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kmem_free(newtip, sizeof (*newtip));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&tip->ti_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai list_insert_tail(&(tip->ti_socklist), tsock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock->ts_tip = tip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&tip->ti_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_clear_bridge(trill_sock_t *tsock)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_inst_t *tip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((tip = tsock->ts_tip) == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&tip->ti_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai list_remove(&tip->ti_socklist, tsock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (list_is_empty(&tip->ti_socklist))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_del_all(tip, B_TRUE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&tip->ti_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_sock_unref(trill_sock_t *tsock)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (atomic_dec_uint_nv(&tsock->ts_refs) == 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_destroy(&tsock->ts_socklock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_destroy(&tsock->ts_sockthreadwait);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_destroy(&tsock->ts_sockclosewait);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kmem_free(tsock, sizeof (trill_sock_t));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_do_close(trill_sock_t *tsock)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_inst_t *tip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tip = tsock->ts_tip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_stop_recv(tsock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Remove socket from TRILL instance socket list */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_clear_bridge(tsock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock->ts_flags |= TSF_SHUTDOWN;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_sock_unref(tsock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tip != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_instance_unref(tip);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_del_all(trill_inst_t *tip, boolean_t lockheld)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int i;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!lockheld)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&tip->ti_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (i = RBRIDGE_NICKNAME_MIN; i < RBRIDGE_NICKNAME_MAX; i++) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tip->ti_nodes[i] != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) trill_del_nick(tip, i, B_TRUE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!lockheld)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&tip->ti_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_node_free(trill_node_t *nick_entry)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_nickinfo_t *tni;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tni = nick_entry->tn_ni;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kmem_free(tni, TNI_TOTALSIZE(tni));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kmem_free(nick_entry, sizeof (trill_node_t));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_node_unref(trill_inst_t *tip, trill_node_t *tnp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (atomic_dec_uint_nv(&tnp->tn_refs) == 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tnp->tn_tsp != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_sock_unref(tnp->tn_tsp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_free(tnp);
640c1670a105457bb0040e8e11037b53ab6ebcfaJosef 'Jeff' Sipek atomic_dec_uint(&tip->ti_nodecount);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic trill_node_t *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_node_lookup(trill_inst_t *tip, uint16_t nick)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_t *nick_entry;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!VALID_NICK(nick))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&tip->ti_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai nick_entry = tip->ti_nodes[nick];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (nick_entry != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai atomic_inc_uint(&nick_entry->tn_refs);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&tip->ti_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (nick_entry);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_del_nick(trill_inst_t *tip, uint16_t nick, boolean_t lockheld)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_t *nick_entry;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int rc = ENOENT;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!lockheld)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&tip->ti_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (VALID_NICK(nick)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai nick_entry = tip->ti_nodes[nick];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (nick_entry != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_unref(tip, nick_entry);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tip->ti_nodes[nick] = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!lockheld)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&tip->ti_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (rc);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_add_nick(trill_inst_t *tip, void *arg, boolean_t self, int mode)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t nick;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int size;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_t *tnode;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_nickinfo_t tnihdr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* First make sure we have at least the header available */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (ddi_copyin(arg, &tnihdr, sizeof (trill_nickinfo_t), mode) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EFAULT);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai nick = tnihdr.tni_nick;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!VALID_NICK(nick)) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DTRACE_PROBE1(trill__add__nick__bad, trill_nickinfo_t *,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai &tnihdr);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EINVAL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai size = TNI_TOTALSIZE(&tnihdr);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (size > TNI_MAXSIZE)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EINVAL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tnode = kmem_zalloc(sizeof (trill_node_t), KM_SLEEP);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tnode->tn_ni = kmem_zalloc(size, KM_SLEEP);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (ddi_copyin(arg, tnode->tn_ni, size, mode) != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kmem_free(tnode->tn_ni, size);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai kmem_free(tnode, sizeof (trill_node_t));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EFAULT);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tnode->tn_refs++;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&tip->ti_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tip->ti_nodes[nick] != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) trill_del_nick(tip, nick, B_TRUE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (self) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tip->ti_nick = nick;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tnode->tn_tsp = find_trill_link(tip,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tnode->tn_ni->tni_linkid);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DTRACE_PROBE2(trill__add__nick, trill_node_t *, tnode,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t, nick);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tip->ti_nodes[nick] = tnode;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tip->ti_nodecount++;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&tip->ti_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_do_ioctl(trill_sock_t *tsock, int cmd, void *arg, int mode)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int error = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_inst_t *tip = tsock->ts_tip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai switch (cmd) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRILL_DESIGVLAN: {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t desigvlan;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (ddi_copyin(arg, &desigvlan, sizeof (desigvlan), mode) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EFAULT);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock->ts_desigvlan = desigvlan;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRILL_VLANFWDER: {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint8_t vlans[TRILL_VLANS_ARRSIZE];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tsock->ts_link == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EINVAL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((ddi_copyin(arg, vlans, sizeof (vlans), mode)) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EFAULT);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_trill_setvlans(tsock->ts_link, vlans);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRILL_SETNICK:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tip == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EINVAL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai error = trill_add_nick(tip, arg, B_TRUE, mode);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRILL_GETNICK:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tip == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EINVAL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&tip->ti_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (ddi_copyout(&tip->ti_nick, arg, sizeof (tip->ti_nick),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mode) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai error = EFAULT;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&tip->ti_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRILL_ADDNICK:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tip == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai error = trill_add_nick(tip, arg, B_FALSE, mode);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRILL_DELNICK: {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t delnick;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tip == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (ddi_copyin(arg, &delnick, sizeof (delnick), mode) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EFAULT);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai error = trill_del_nick(tip, delnick, B_FALSE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRILL_DELALL:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tip == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_del_all(tip, B_FALSE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRILL_TREEROOT: {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t treeroot;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tip == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (ddi_copyin(arg, &treeroot, sizeof (treeroot), mode) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EFAULT);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!VALID_NICK(treeroot))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EINVAL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&tip->ti_rwlock, RW_WRITER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tip->ti_treeroot = treeroot;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&tip->ti_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRILL_HWADDR:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tsock->ts_link == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (ddi_copyout(tsock->ts_link->bl_local_mac, arg, ETHERADDRL,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mode) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EFAULT);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRILL_NEWBRIDGE: {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai char bname[MAXLINKNAMELEN];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tsock->ts_state != TS_UNBND)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (ENOTSUP);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* ts_tip can only be set once */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tip != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EEXIST);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (ddi_copyin(arg, bname, sizeof (bname), mode) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EFAULT);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bname[MAXLINKNAMELEN-1] = '\0';
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai error = trill_find_bridge(tsock, bname, B_TRUE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRILL_GETBRIDGE: {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai char bname[MAXLINKNAMELEN];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* ts_tip can only be set once */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tip != NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EEXIST);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (ddi_copyin(arg, bname, sizeof (bname), mode) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EFAULT);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bname[MAXLINKNAMELEN - 1] = '\0';
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai error = trill_find_bridge(tsock, bname, B_FALSE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRILL_LISTNICK: {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_listnick_t tln;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_node_t *tnp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_nickinfo_t *tnip;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t nick;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tip == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EINVAL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (ddi_copyin(arg, &tln, sizeof (tln), mode) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EFAULT);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai nick = tln.tln_nick;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (nick >= RBRIDGE_NICKNAME_MAX) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai error = EINVAL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_enter(&tip->ti_rwlock, RW_READER);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai while (++nick < RBRIDGE_NICKNAME_MAX) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((tnp = tip->ti_nodes[nick]) != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tnip = tnp->tn_ni;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(nick == tnip->tni_nick);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tln.tln_nick = nick;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bcopy(tnip->tni_adjsnpa, tln.tln_nexthop,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ETHERADDRL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tln.tln_ours = nick == tip->ti_nick;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tln.tln_ours || tnp->tn_tsp == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tln.tln_linkid =
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DATALINK_INVALID_LINKID;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tln.tln_linkid =
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tnp->tn_tsp->ts_link->bl_linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rw_exit(&tip->ti_rwlock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (nick >= RBRIDGE_NICKNAME_MAX)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bzero(&tln, sizeof (tln));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (ddi_copyout(&tln, arg, sizeof (tln), mode) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EFAULT);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Port flush: this is used when we lose AF on a port. We must discard
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * all regular bridge forwarding entries on this port with the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * indicated VLAN.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRILL_PORTFLUSH: {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t vlan = (uint16_t)(uintptr_t)arg;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tsock->ts_link == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EINVAL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_trill_flush(tsock->ts_link, vlan, B_FALSE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Nick flush: this is used when we lose AF on a port. We must discard
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * all bridge TRILL forwarding entries on this port with the indicated
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * VLAN.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRILL_NICKFLUSH: {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t vlan = (uint16_t)(uintptr_t)arg;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tsock->ts_link == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EINVAL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_trill_flush(tsock->ts_link, vlan, B_TRUE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRILL_GETMTU:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tsock->ts_link == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (ddi_copyout(&tsock->ts_link->bl_maxsdu, arg,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (uint_t), mode) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EFAULT);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai default:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai error = ENOTSUP;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (error);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Sends received packet back upstream on the TRILL socket.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Consumes passed mblk_t.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_ctrl_input(trill_sock_t *tsock, mblk_t *mp, const uint8_t *saddr,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t tci)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int udi_size;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mblk_t *mp1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct T_unitdata_ind *tudi;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct sockaddr_dl *sdl;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai char *lladdr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int error;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(!(tsock->ts_flags & TSF_SHUTDOWN));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tsock->ts_flow_ctrld) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSPINCR(tks_drops);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai udi_size = sizeof (struct T_unitdata_ind) +
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (struct sockaddr_dl);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp1 = allocb(udi_size, BPRI_MED);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mp1 == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSPINCR(tks_drops);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp1->b_cont = mp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp = mp1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_datap->db_type = M_PROTO;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tudi = (struct T_unitdata_ind *)mp->b_rptr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp->b_wptr = (uchar_t *)tudi + udi_size;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tudi->PRIM_type = T_UNITDATA_IND;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tudi->SRC_length = sizeof (struct sockaddr_dl);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tudi->SRC_offset = sizeof (struct T_unitdata_ind);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tudi->OPT_length = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tudi->OPT_offset = sizeof (struct T_unitdata_ind) +
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (struct sockaddr_dl);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Information of the link on which packet was received. */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sdl = (struct sockaddr_dl *)&tudi[1];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) memset(sdl, 0, sizeof (struct sockaddr_dl));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sdl->sdl_family = AF_TRILL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *(datalink_id_t *)sdl->sdl_data = tsock->ts_link->bl_linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sdl->sdl_nlen = sizeof (tsock->ts_link->bl_linkid);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai lladdr = LLADDR(sdl);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) memcpy(lladdr, saddr, ETHERADDRL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai lladdr += ETHERADDRL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sdl->sdl_alen = ETHERADDRL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *(uint16_t *)lladdr = tci;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sdl->sdl_slen = sizeof (uint16_t);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DTRACE_PROBE2(trill__ctrl__input, trill_sock_t *, tsock, mblk_t *, mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (*tsock->ts_conn_upcalls->su_recv)(tsock->ts_conn_upper_handle,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp, msgdsize(mp), 0, &error, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (error == ENOSPC) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&tsock->ts_socklock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (*tsock->ts_conn_upcalls->su_recv)(tsock->ts_conn_upper_handle,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, 0, 0, &error, NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (error == ENOSPC)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock->ts_flow_ctrld = B_TRUE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&tsock->ts_socklock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSPINCR(tks_drops);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else if (error != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSPINCR(tks_drops);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSPINCR(tks_recv);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DTRACE_PROBE2(trill__ctrl__input__done, trill_sock_t *,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock, int, error);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* ARGSUSED */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_activate(sock_lower_handle_t proto_handle,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sock_upper_handle_t sock_handle, sock_upcalls_t *sock_upcalls,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int flags, cred_t *cr)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_sock_t *tsock = (trill_sock_t *)proto_handle;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct sock_proto_props sopp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock->ts_conn_upcalls = sock_upcalls;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock->ts_conn_upper_handle = sock_handle;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sopp.sopp_flags = SOCKOPT_WROFF | SOCKOPT_RCVHIWAT |
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai SOCKOPT_RCVLOWAT | SOCKOPT_MAXADDRLEN | SOCKOPT_MAXPSZ |
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai SOCKOPT_MAXBLK | SOCKOPT_MINPSZ;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sopp.sopp_wroff = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sopp.sopp_rxhiwat = SOCKET_RECVHIWATER;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sopp.sopp_rxlowat = SOCKET_RECVLOWATER;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sopp.sopp_maxaddrlen = sizeof (struct sockaddr_dl);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sopp.sopp_maxpsz = INFPSZ;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sopp.sopp_maxblk = INFPSZ;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sopp.sopp_minpsz = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (*tsock->ts_conn_upcalls->su_set_proto_props)(
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock->ts_conn_upper_handle, &sopp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* ARGSUSED */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_close(sock_lower_handle_t proto_handle, int flags, cred_t *cr)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_sock_t *tsock = (trill_sock_t *)proto_handle;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_do_close(tsock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* ARGSUSED */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_bind(sock_lower_handle_t proto_handle, struct sockaddr *sa,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai socklen_t len, cred_t *cr)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int error;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_sock_t *tsock = (trill_sock_t *)proto_handle;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (sa == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai error = trill_do_unbind(tsock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai error = trill_start_recv(tsock, sa, len);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (error);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* ARGSUSED */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_send(sock_lower_handle_t proto_handle, mblk_t *mp, struct nmsghdr *msg,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cred_t *cr)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_sock_t *tsock = (trill_sock_t *)proto_handle;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct sockaddr_dl *laddr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t tci;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(DB_TYPE(mp) == M_DATA);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ASSERT(!(tsock->ts_flags & TSF_SHUTDOWN));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (msg->msg_name == NULL || msg->msg_namelen != sizeof (*laddr))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto eproto;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * The name is a datalink_id_t, the address is an Ethernet address, and
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * the selector value is the VLAN ID.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai laddr = (struct sockaddr_dl *)msg->msg_name;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (laddr->sdl_nlen != sizeof (datalink_id_t) ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai laddr->sdl_alen != ETHERADDRL ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (laddr->sdl_slen != sizeof (tci) && laddr->sdl_slen != 0))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto eproto;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&tsock->ts_socklock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (tsock->ts_state != TS_IDLE || tsock->ts_link == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&tsock->ts_socklock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai goto eproto;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai atomic_inc_uint(&tsock->ts_sockthreadcount);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&tsock->ts_socklock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Safe to dereference VLAN now, as we've checked the user's specified
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * values, and alignment is now guaranteed.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (laddr->sdl_slen == 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tci = TRILL_NO_TCI;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tci = *(uint16_t *)(LLADDR(laddr) + ETHERADDRL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp = create_trill_header(tsock, mp, (const uchar_t *)LLADDR(laddr),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai B_TRUE, B_FALSE, tci, msgdsize(mp));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mp != NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mp = bridge_trill_output(tsock->ts_link, mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (mp == NULL) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSPINCR(tks_sent);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSPINCR(tks_drops);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Wake up any threads blocking on us */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (atomic_dec_uint_nv(&tsock->ts_sockthreadcount) == 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai cv_broadcast(&tsock->ts_sockthreadwait);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaieproto:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai freemsg(mp);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai KSPINCR(tks_drops);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EPROTO);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* ARGSUSED */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_ioctl(sock_lower_handle_t proto_handle, int cmd, intptr_t arg,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int mode, int32_t *rvalp, cred_t *cr)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_sock_t *tsock = (trill_sock_t *)proto_handle;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int rc;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai switch (cmd) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* List of unprivileged TRILL ioctls */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRILL_GETNICK:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRILL_GETBRIDGE:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRILL_LISTNICK:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai default:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (secpolicy_dl_config(cr) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EPERM);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Lock ensures socket state is unchanged during ioctl handling */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&tsock->ts_socklock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rc = trill_do_ioctl(tsock, cmd, (void *)arg, mode);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&tsock->ts_socklock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (rc);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_clr_flowctrl(sock_lower_handle_t proto_handle)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_sock_t *tsock = (trill_sock_t *)proto_handle;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_enter(&tsock->ts_socklock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock->ts_flow_ctrld = B_FALSE;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai mutex_exit(&tsock->ts_socklock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic sock_downcalls_t sock_trill_downcalls = {
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai trill_activate, /* sd_activate */
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai sock_accept_notsupp, /* sd_accept */
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai trill_bind, /* sd_bind */
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai sock_listen_notsupp, /* sd_listen */
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai sock_connect_notsupp, /* sd_connect */
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai sock_getpeername_notsupp, /* sd_getpeername */
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai sock_getsockname_notsupp, /* sd_getsockname */
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai sock_getsockopt_notsupp, /* sd_getsockopt */
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai sock_setsockopt_notsupp, /* sd_setsockopt */
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai trill_send, /* sd_send */
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai NULL, /* sd_send_uio */
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai NULL, /* sd_recv_uio */
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai NULL, /* sd_poll */
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai sock_shutdown_notsupp, /* sd_shutdown */
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai trill_clr_flowctrl, /* sd_setflowctrl */
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai trill_ioctl, /* sd_ioctl */
6f40bf67422a6901bbfa4fb5f381ba19238f4763Rishi Srivatsavai trill_close /* sd_close */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai};
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* ARGSUSED */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic sock_lower_handle_t
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitrill_create(int family, int type, int proto, sock_downcalls_t **sock_downcalls,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint_t *smodep, int *errorp, int flags, cred_t *credp)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai trill_sock_t *tsock;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (family != AF_TRILL || type != SOCK_DGRAM || proto != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *errorp = EPROTONOSUPPORT;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (NULL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *sock_downcalls = &sock_trill_downcalls;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *smodep = SM_ATOMIC;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai tsock = trill_do_open(flags);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *errorp = (tsock != NULL) ? 0:ENOMEM;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return ((sock_lower_handle_t)tsock);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}