Home | History | Annotate | Download | only in io
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  *
     21  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
     22  * Use is subject to license terms.
     23  */
     24 
     25 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     26 
     27 /*
     28  * gld - Generic LAN Driver
     29  * media dependent routines
     30  */
     31 
     32 #include <sys/types.h>
     33 #include <sys/errno.h>
     34 #include <sys/stropts.h>
     35 #include <sys/stream.h>
     36 #include <sys/kmem.h>
     37 #include <sys/stat.h>
     38 #include <sys/modctl.h>
     39 #include <sys/kstat.h>
     40 #include <sys/debug.h>
     41 
     42 #include <sys/byteorder.h>
     43 #include <sys/strsun.h>
     44 #include <sys/dlpi.h>
     45 #include <sys/ethernet.h>
     46 #include <sys/multidata.h>
     47 #include <sys/gld.h>
     48 #include <sys/gldpriv.h>
     49 #include <sys/ddi.h>
     50 #include <sys/sunddi.h>
     51 #include <sys/sysmacros.h>
     52 #include <sys/ib/clients/ibd/ibd.h>
     53 #include <sys/pattr.h>
     54 
     55 #define	DLSAPLENGTH(macinfo) \
     56 	((macinfo)->gldm_addrlen + ABS((macinfo)->gldm_saplen))
     57 
     58 #ifdef GLD_DEBUG
     59 extern int gld_debug;
     60 #endif
     61 
     62 extern void gld_bitrevcopy(caddr_t src, caddr_t target, size_t n);
     63 extern char *gld_macaddr_sprintf(char *, unsigned char *, int);
     64 extern gld_vlan_t *gld_find_vlan(gld_mac_info_t *, uint32_t);
     65 extern uint32_t gld_global_options;
     66 
     67 static struct	llc_snap_hdr llc_snap_def = {
     68 	LSAP_SNAP,		/* DLSAP 0xaa */
     69 	LSAP_SNAP,		/* SLSAP 0xaa */
     70 	CNTL_LLC_UI,		/* Control 0x03 */
     71 	0x00, 0x00, 0x00,	/* Org[3] */
     72 	0x00			/* Type */
     73 };
     74 
     75 #define	ISETHERTYPE(snaphdr) \
     76 	(snaphdr->d_lsap == LSAP_SNAP && \
     77 	snaphdr->s_lsap == LSAP_SNAP && \
     78 	snaphdr->control == CNTL_LLC_UI && \
     79 	snaphdr->org[0] == 0 && \
     80 	snaphdr->org[1] == 0 && \
     81 	snaphdr->org[2] == 0)
     82 
     83 /* ======== */
     84 /* Ethernet */
     85 /* ======== */
     86 
     87 static mac_addr_t ether_broadcast = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
     88 
     89 void
     90 gld_init_ether(gld_mac_info_t *macinfo)
     91 {
     92 	struct gldkstats *sp =
     93 	    ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->kstatp->ks_data;
     94 
     95 	/* Assumptions we make for this medium */
     96 	ASSERT(macinfo->gldm_type == DL_ETHER);
     97 	ASSERT(macinfo->gldm_addrlen == 6);
     98 	ASSERT(macinfo->gldm_saplen == -2);
     99 #ifndef	lint
    100 	ASSERT(sizeof (struct ether_header) == 14);
    101 	ASSERT(sizeof (mac_addr_t) == 6);
    102 #endif
    103 
    104 	kstat_named_init(&sp->glds_frame, "align_errors", KSTAT_DATA_ULONG);
    105 	kstat_named_init(&sp->glds_crc, "fcs_errors", KSTAT_DATA_ULONG);
    106 	kstat_named_init(&sp->glds_collisions, "collisions", KSTAT_DATA_ULONG);
    107 	kstat_named_init(&sp->glds_nocarrier, "carrier_errors",
    108 	    KSTAT_DATA_ULONG);
    109 	kstat_named_init(&sp->glds_defer, "defer_xmts", KSTAT_DATA_ULONG);
    110 	kstat_named_init(&sp->glds_xmtlatecoll, "tx_late_collisions",
    111 					KSTAT_DATA_ULONG);
    112 	kstat_named_init(&sp->glds_short, "runt_errors", KSTAT_DATA_ULONG);
    113 	kstat_named_init(&sp->glds_excoll, "ex_collisions", KSTAT_DATA_ULONG);
    114 
    115 	/*
    116 	 * only initialize the new statistics if the driver
    117 	 * knows about them.
    118 	 */
    119 	if (macinfo->gldm_driver_version != GLD_VERSION_200)
    120 		return;
    121 
    122 	kstat_named_init(&sp->glds_dot3_first_coll,
    123 	    "first_collisions", KSTAT_DATA_UINT32);
    124 	kstat_named_init(&sp->glds_dot3_multi_coll,
    125 	    "multi_collisions", KSTAT_DATA_UINT32);
    126 	kstat_named_init(&sp->glds_dot3_sqe_error,
    127 	    "sqe_errors", KSTAT_DATA_UINT32);
    128 	kstat_named_init(&sp->glds_dot3_mac_xmt_error,
    129 	    "macxmt_errors", KSTAT_DATA_UINT32);
    130 	kstat_named_init(&sp->glds_dot3_mac_rcv_error,
    131 	    "macrcv_errors", KSTAT_DATA_UINT32);
    132 	kstat_named_init(&sp->glds_dot3_frame_too_long,
    133 	    "toolong_errors", KSTAT_DATA_UINT32);
    134 	kstat_named_init(&sp->glds_duplex, "duplex", KSTAT_DATA_CHAR);
    135 }
    136 
    137 /*ARGSUSED*/
    138 void
    139 gld_uninit_ether(gld_mac_info_t *macinfo)
    140 {
    141 }
    142 
    143 int
    144 gld_interpret_ether(gld_mac_info_t *macinfo, mblk_t *mp, pktinfo_t *pktinfo,
    145     packet_flag_t flags)
    146 {
    147 	struct ether_header *mh;
    148 	gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
    149 	struct llc_snap_hdr *snaphdr;
    150 	mblk_t *pmp = NULL, *savemp = mp;
    151 	unsigned short typelen;
    152 	int ret = 0;
    153 
    154 	/*
    155 	 * Quickly handle receive fastpath for IPQ hack.
    156 	 */
    157 	if (flags == GLD_RXQUICK) {
    158 		pktinfo->pktLen = msgdsize(mp);
    159 		/*
    160 		 * Check whether the header is contiguous, which
    161 		 * also implicitly makes sure the packet is big enough.
    162 		 */
    163 		if (MBLKL(mp) < sizeof (struct ether_header))
    164 			return (-1);
    165 		mh = (struct ether_header *)mp->b_rptr;
    166 		pktinfo->ethertype = REF_NET_USHORT(mh->ether_type);
    167 		pktinfo->isForMe = mac_eq(&mh->ether_dhost,
    168 		    mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
    169 		pktinfo->macLen = sizeof (struct ether_header);
    170 
    171 		return (0);
    172 	}
    173 
    174 	bzero((void *)pktinfo, sizeof (*pktinfo));
    175 
    176 	pktinfo->pktLen = msgdsize(mp);
    177 
    178 	/* make sure packet has at least a whole mac header */
    179 	if (pktinfo->pktLen < sizeof (struct ether_header))
    180 		return (-1);
    181 
    182 	/* make sure the mac header falls into contiguous memory */
    183 	if (MBLKL(mp) < sizeof (struct ether_header)) {
    184 		if ((pmp = msgpullup(mp, -1)) == NULL) {
    185 #ifdef GLD_DEBUG
    186 			if (gld_debug & GLDERRS)
    187 				cmn_err(CE_WARN,
    188 				    "GLD: interpret_ether cannot msgpullup");
    189 #endif
    190 			return (-1);
    191 		}
    192 		mp = pmp;	/* this mblk contains the whole mac header */
    193 	}
    194 
    195 	mh = (struct ether_header *)mp->b_rptr;
    196 
    197 	/* Check to see if the mac is a broadcast or multicast address. */
    198 	if (mac_eq(&mh->ether_dhost, ether_broadcast, macinfo->gldm_addrlen))
    199 		pktinfo->isBroadcast = 1;
    200 	else if (mh->ether_dhost.ether_addr_octet[0] & 1)
    201 		pktinfo->isMulticast = 1;
    202 
    203 	typelen = REF_NET_USHORT(mh->ether_type);
    204 	/*
    205 	 * If the hardware is capable of VLAN tag insertion
    206 	 * strip out the VLAN tag info. Knowing hardware is
    207 	 * capable of VLAN can be established by the presance
    208 	 * of non null 'macinfo->gldm_send_tagged'.
    209 	 */
    210 	if (flags == GLD_TX) {
    211 		if ((typelen == ETHERTYPE_VLAN) &&
    212 		    (macinfo->gldm_send_tagged != NULL)) {
    213 			struct ether_vlan_header *evhp;
    214 			uint16_t tci;
    215 
    216 			if ((MBLKL(mp) < sizeof (struct ether_vlan_header)) &&
    217 			    (pullupmsg(mp, sizeof (struct ether_vlan_header))
    218 			    == 0)) {
    219 				ret = -1;
    220 				goto out;
    221 			}
    222 			evhp = (struct ether_vlan_header *)mp->b_rptr;
    223 			tci = REF_NET_USHORT(evhp->ether_tci);
    224 
    225 			/*
    226 			 * We don't allow the VID and priority are both zero.
    227 			 */
    228 			if ((GLD_VTAG_PRI((int32_t)tci) == 0 &&
    229 			    GLD_VTAG_VID((int32_t)tci) == VLAN_VID_NONE) ||
    230 			    (GLD_VTAG_CFI((uint32_t)tci)) != VLAN_CFI_ETHER) {
    231 				ret = -1;
    232 				goto out;
    233 			}
    234 
    235 			/*
    236 			 * Remember the VTAG info in order to reinsert it,
    237 			 * Then strip the tag. This is required because some
    238 			 * drivers do not allow the size of message (passed
    239 			 * by the gldm_send_tagged() function) to be greater
    240 			 * than ETHERMAX.
    241 			 */
    242 			GLD_SAVE_MBLK_VTAG(savemp, GLD_TCI2VTAG(tci));
    243 			ovbcopy(mp->b_rptr, mp->b_rptr + VTAG_SIZE,
    244 			    2 * ETHERADDRL);
    245 			mp->b_rptr += VTAG_SIZE;
    246 		}
    247 		goto out;	/* Got all info we need for xmit case */
    248 	}
    249 
    250 	ASSERT(GLDM_LOCK_HELD(macinfo));
    251 
    252 	/*
    253 	 * Deal with the mac header
    254 	 */
    255 
    256 	mac_copy(&mh->ether_dhost, pktinfo->dhost, macinfo->gldm_addrlen);
    257 	mac_copy(&mh->ether_shost, pktinfo->shost, macinfo->gldm_addrlen);
    258 
    259 	pktinfo->isLooped = mac_eq(pktinfo->shost,
    260 	    mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
    261 	pktinfo->isForMe = mac_eq(pktinfo->dhost,
    262 	    mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
    263 
    264 	pktinfo->macLen = sizeof (struct ether_header);
    265 
    266 	if (typelen > ETHERMTU) {
    267 		pktinfo->ethertype = typelen; /* use type interpretation */
    268 		goto out;
    269 	}
    270 
    271 	/*
    272 	 * Packet is 802.3 so the ether type/length field
    273 	 * specifies the number of bytes that should be present
    274 	 * in the data field.  Additional bytes are padding, and
    275 	 * should be removed
    276 	 */
    277 	{
    278 	int delta = pktinfo->pktLen -
    279 	    (sizeof (struct ether_header) + typelen);
    280 
    281 	if (delta > 0 && adjmsg(mp, -delta))
    282 		pktinfo->pktLen -= delta;
    283 	}
    284 
    285 	/*
    286 	 * Before trying to look beyond the MAC header, make sure the LLC
    287 	 * header exists, and that both it and any SNAP header are contiguous.
    288 	 */
    289 	if (pktinfo->pktLen < pktinfo->macLen + LLC_HDR1_LEN)
    290 		goto out;	/* LLC hdr should have been there! */
    291 
    292 	pktinfo->isLLC = 1;
    293 
    294 	if (gld_global_options & GLD_OPT_NO_ETHRXSNAP ||
    295 	    pktinfo->pktLen <  pktinfo->macLen + LLC_SNAP_HDR_LEN)
    296 		goto out;
    297 
    298 	if (MBLKL(mp) < sizeof (struct ether_header) + LLC_SNAP_HDR_LEN &&
    299 	    MBLKL(mp) < pktinfo->pktLen) {
    300 		/*
    301 		 * we don't have the entire packet within the first mblk (and
    302 		 * therefore we didn't do the msgpullup above), AND the first
    303 		 * mblk may not contain all the data we need to look at.
    304 		 */
    305 		ASSERT(pmp == NULL);	/* couldn't have done msgpullup above */
    306 		if ((pmp = msgpullup(mp, -1)) == NULL) {
    307 #ifdef GLD_DEBUG
    308 			if (gld_debug & GLDERRS)
    309 				cmn_err(CE_WARN,
    310 				    "GLD: interpret_ether cannot msgpullup2");
    311 #endif
    312 			goto out;	/* can't interpret this pkt further */
    313 		}
    314 		mp = pmp;	/* this mblk should contain everything needed */
    315 	}
    316 
    317 	/*
    318 	 * Check SAP/SNAP information for EtherType.
    319 	 */
    320 
    321 	snaphdr = (struct llc_snap_hdr *)(mp->b_rptr + pktinfo->macLen);
    322 	if (ISETHERTYPE(snaphdr)) {
    323 		pktinfo->ethertype = REF_NET_USHORT(snaphdr->type);
    324 		pktinfo->hdrLen = LLC_SNAP_HDR_LEN;
    325 	}
    326 out:
    327 	if (pmp != NULL)
    328 		freemsg(pmp);
    329 
    330 	return (ret);
    331 }
    332 
    333 mblk_t *
    334 gld_unitdata_ether(gld_t *gld, mblk_t *mp)
    335 {
    336 	gld_mac_info_t *macinfo = gld->gld_mac_info;
    337 	dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_rptr;
    338 	struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
    339 	mac_addr_t dhost;
    340 	unsigned short typelen;
    341 	mblk_t *nmp;
    342 	struct ether_header *mh;
    343 	int hdrlen;
    344 	uint32_t vptag;
    345 	gld_vlan_t *gld_vlan;
    346 
    347 	ASSERT(macinfo);
    348 
    349 	/* extract needed info from the mblk before we maybe reuse it */
    350 	mac_copy(gldp->glda_addr, dhost, macinfo->gldm_addrlen);
    351 
    352 	/* look in the unitdata request for a sap, else use bound one */
    353 	if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
    354 	    REF_HOST_USHORT(gldp->glda_sap) != 0)
    355 		typelen = REF_HOST_USHORT(gldp->glda_sap);
    356 	else
    357 		typelen = gld->gld_sap;
    358 
    359 	/*
    360 	 * We take values less than or equal to ETHERMTU to mean that the
    361 	 * packet should not have an encoded EtherType and so we use the
    362 	 * IEEE 802.3 length interpretation of the type/length field.
    363 	 */
    364 	if (typelen <= ETHERMTU)
    365 		typelen = msgdsize(mp);
    366 
    367 	hdrlen = sizeof (struct ether_header);
    368 
    369 	/*
    370 	 * Check to see if VLAN is enabled on this stream
    371 	 * if so then make the header bigger to hold a clone
    372 	 * vlan tag.
    373 	 */
    374 	gld_vlan = (gld_vlan_t *)gld->gld_vlan;
    375 	if (gld_vlan && (gld_vlan->gldv_id != VLAN_VID_NONE)) {
    376 		hdrlen += VTAG_SIZE;
    377 		vptag = gld_vlan->gldv_ptag;
    378 	}
    379 
    380 	/* need a buffer big enough for the headers */
    381 	nmp = mp->b_cont;	/* where the packet payload M_DATA is */
    382 	if (DB_REF(nmp) == 1 && MBLKHEAD(nmp) >= hdrlen) {
    383 		/* it fits at the beginning of the first M_DATA block */
    384 		freeb(mp);	/* don't need the M_PROTO anymore */
    385 	} else if (DB_REF(mp) == 1 && MBLKSIZE(mp) >= hdrlen) {
    386 		/* we can reuse the dl_unitdata_req M_PROTO mblk */
    387 		nmp = mp;
    388 		DB_TYPE(nmp) = M_DATA;
    389 		nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
    390 	} else {
    391 		/* we need to allocate one */
    392 		if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
    393 			return (NULL);
    394 		nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
    395 		linkb(nmp, mp->b_cont);
    396 		freeb(mp);
    397 	}
    398 
    399 	/* Got the space, now copy in the header components */
    400 
    401 	nmp->b_rptr -= sizeof (typelen);
    402 	SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, typelen);
    403 	if (hdrlen > sizeof (struct ether_header)) {
    404 		nmp->b_rptr -= sizeof (uint16_t);
    405 		SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, vptag);
    406 		vptag >>= 16;
    407 		nmp->b_rptr -= sizeof (uint16_t);
    408 		SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, vptag);
    409 	}
    410 	nmp->b_rptr -= (ETHERADDRL * 2);
    411 	mh = (struct ether_header *)nmp->b_rptr;
    412 	mac_copy(dhost, &mh->ether_dhost, macinfo->gldm_addrlen);
    413 
    414 	/*
    415 	 * We access the mac address without the mutex to prevent
    416 	 * mutex contention (BUG 4211361)
    417 	 */
    418 	mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
    419 	    &mh->ether_shost, macinfo->gldm_addrlen);
    420 
    421 	return (nmp);
    422 }
    423 
    424 /*
    425  * Insert the VLAN tag into the packet. The packet now is an Ethernet header
    426  * without VLAN tag information.
    427  */
    428 mblk_t *
    429 gld_insert_vtag_ether(mblk_t *mp, uint32_t vtag)
    430 {
    431 	struct ether_vlan_header *evhp;
    432 	struct ether_header *ehp;
    433 	mblk_t *nmp;
    434 
    435 	if (vtag == VLAN_VID_NONE)
    436 		return (mp);
    437 
    438 	if (DB_REF(mp) == 1 && MBLKHEAD(mp) >= VTAG_SIZE) {
    439 		/* it fits at the beginning of the message block */
    440 		nmp = mp;
    441 		ovbcopy(nmp->b_rptr, nmp->b_rptr - VTAG_SIZE, 2 * ETHERADDRL);
    442 		nmp->b_rptr -= VTAG_SIZE;
    443 		evhp = (struct ether_vlan_header *)nmp->b_rptr;
    444 	} else {
    445 		/* we need to allocate one */
    446 		if ((nmp = allocb(sizeof (struct ether_vlan_header),
    447 		    BPRI_MED)) == NULL) {
    448 			return (NULL);
    449 		}
    450 		nmp->b_wptr += sizeof (struct ether_vlan_header);
    451 
    452 		/* transfer the ether_header fields */
    453 		evhp = (struct ether_vlan_header *)nmp->b_rptr;
    454 		ehp = (struct ether_header *)mp->b_rptr;
    455 		mac_copy(&ehp->ether_dhost, &evhp->ether_dhost, ETHERADDRL);
    456 		mac_copy(&ehp->ether_shost, &evhp->ether_shost, ETHERADDRL);
    457 		bcopy(&ehp->ether_type, &evhp->ether_type, sizeof (uint16_t));
    458 
    459 		/* offset the mp of the MAC header length. */
    460 		mp->b_rptr += sizeof (struct ether_header);
    461 		if (MBLKL(mp) == 0) {
    462 			nmp->b_cont = mp->b_cont;
    463 			freeb(mp);
    464 		} else {
    465 			nmp->b_cont = mp;
    466 		}
    467 	}
    468 
    469 	SET_NET_USHORT(evhp->ether_tci, vtag);
    470 	vtag >>= 16;
    471 	SET_NET_USHORT(evhp->ether_tpid, vtag);
    472 	return (nmp);
    473 }
    474 
    475 mblk_t *
    476 gld_fastpath_ether(gld_t *gld, mblk_t *mp)
    477 {
    478 	gld_mac_info_t *macinfo = gld->gld_mac_info;
    479 	dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
    480 	struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
    481 	unsigned short typelen;
    482 	mblk_t *nmp;
    483 	struct ether_header *mh;
    484 	int hdrlen;
    485 	uint32_t vptag;
    486 	gld_vlan_t *gld_vlan;
    487 
    488 	ASSERT(macinfo);
    489 
    490 	/* look in the unitdata request for a sap, else use bound one */
    491 	if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
    492 	    REF_HOST_USHORT(gldp->glda_sap) != 0)
    493 		typelen = REF_HOST_USHORT(gldp->glda_sap);
    494 	else
    495 		typelen = gld->gld_sap;
    496 
    497 	/*
    498 	 * We only do fast-path for EtherType encoding because this is the only
    499 	 * case where the media header will be consistent from packet to packet.
    500 	 */
    501 	if (typelen <= ETHERMTU)
    502 		return (NULL);
    503 
    504 	/*
    505 	 * Initialize the fast path header to include the
    506 	 * basic source address information and type field.
    507 	 */
    508 	hdrlen = sizeof (struct ether_header);
    509 
    510 	/*
    511 	 * Check to see if VLAN is enabled on this stream
    512 	 * if so then make the header bigger to hold a clone
    513 	 * vlan tag.
    514 	 */
    515 	gld_vlan = (gld_vlan_t *)gld->gld_vlan;
    516 	if (gld_vlan && (gld_vlan->gldv_id != VLAN_VID_NONE)) {
    517 		hdrlen += VTAG_SIZE;
    518 		vptag = gld_vlan->gldv_ptag;
    519 	}
    520 
    521 	if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
    522 		return (NULL);
    523 
    524 	nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
    525 
    526 	/* Got the space, now copy in the header components */
    527 
    528 	nmp->b_rptr -= sizeof (typelen);
    529 	SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, typelen);
    530 
    531 	/*
    532 	 * If the header is for a VLAN stream, then add
    533 	 * in the VLAN tag to the clone header.
    534 	 */
    535 	if (hdrlen > sizeof (struct ether_header)) {
    536 		nmp->b_rptr -= sizeof (uint16_t);
    537 		SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, vptag);
    538 		vptag >>= 16;
    539 		nmp->b_rptr -= sizeof (uint16_t);
    540 		SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, vptag);
    541 	}
    542 	nmp->b_rptr -= (ETHERADDRL * 2);
    543 	mh = (struct ether_header *)nmp->b_rptr;
    544 	mac_copy(gldp->glda_addr, &mh->ether_dhost, macinfo->gldm_addrlen);
    545 
    546 	GLDM_LOCK(macinfo, RW_WRITER);
    547 	mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
    548 	    &mh->ether_shost, macinfo->gldm_addrlen);
    549 	GLDM_UNLOCK(macinfo);
    550 
    551 	return (nmp);
    552 }
    553 
    554 /* == */
    555 /* IB */
    556 /* == */
    557 
    558 void
    559 gld_init_ib(gld_mac_info_t *macinfo)
    560 {
    561 	/*
    562 	 * Currently, the generic stats maintained by GLD is
    563 	 * sufficient for IPoIB.
    564 	 */
    565 
    566 	/* Assumptions we make for this medium */
    567 	ASSERT(macinfo->gldm_type == DL_IB);
    568 	ASSERT(macinfo->gldm_addrlen == IPOIB_ADDRL);
    569 	ASSERT(macinfo->gldm_saplen == -2);
    570 }
    571 
    572 /* ARGSUSED */
    573 void
    574 gld_uninit_ib(gld_mac_info_t *macinfo)
    575 {
    576 }
    577 
    578 /*
    579  * The packet format sent to the driver is:
    580  * IPOIB_ADDRL bytes dest addr :: 2b sap :: 2b 0s :: data
    581  * The packet format received from the driver is:
    582  * IPOIB_GRH_SIZE bytes pseudo GRH :: 2b sap :: 2b 0s :: data.
    583  */
    584 int
    585 gld_interpret_ib(gld_mac_info_t *macinfo, mblk_t *mp, pktinfo_t *pktinfo,
    586     packet_flag_t flags)
    587 {
    588 	ipoib_pgrh_t *grh;
    589 	ipoib_ptxhdr_t *gldp;
    590 	mblk_t *pmp = NULL;
    591 	gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
    592 
    593 	/*
    594 	 * Quickly handle receive fastpath for IPQ hack.
    595 	 */
    596 	if (flags == GLD_RXQUICK) {
    597 		pktinfo->pktLen = msgdsize(mp) - IPOIB_GRH_SIZE;
    598 
    599 		/*
    600 		 * Check whether the header is contiguous, which
    601 		 * also implicitly makes sure the packet is big enough.
    602 		 */
    603 		if (MBLKL(mp) < (IPOIB_GRH_SIZE + IPOIB_HDRSIZE))
    604 			return (-1);
    605 
    606 		/*
    607 		 * Almost all times, unicast will not have
    608 		 * a valid pgrh; quickly identify and ask for
    609 		 * IPQ hack optimization only in that case.
    610 		 */
    611 		grh = (ipoib_pgrh_t *)mp->b_rptr;
    612 		if (grh->ipoib_vertcflow == 0) {
    613 			struct ipoib_header *ihp = (struct ipoib_header *)
    614 			    (mp->b_rptr + IPOIB_GRH_SIZE);
    615 
    616 			pktinfo->isForMe = 1;
    617 			pktinfo->ethertype = REF_NET_USHORT(ihp->ipoib_type);
    618 			pktinfo->macLen = IPOIB_GRH_SIZE + IPOIB_HDRSIZE;
    619 			return (0);
    620 		} else {
    621 			return (-1);
    622 		}
    623 	}
    624 
    625 	/*
    626 	 * Handle the GLD_TX, GLD_RX, GLD_RXLOOP cases now.
    627 	 */
    628 	ASSERT(flags != GLD_RXQUICK);
    629 	bzero((void *)pktinfo, sizeof (*pktinfo));
    630 
    631 	if (flags != GLD_RX) {
    632 		/*
    633 		 * GLD_TX and GLD_RXLOOP cases.
    634 		 */
    635 		gldp = (ipoib_ptxhdr_t *)mp->b_rptr;
    636 		pktinfo->pktLen = msgdsize(mp);
    637 
    638 		/* make sure packet has at least a pseudo header */
    639 		if (pktinfo->pktLen < sizeof (ipoib_ptxhdr_t))
    640 			return (-1);
    641 
    642 		/* make sure the mac header falls into contiguous memory */
    643 		if (MBLKL(mp) < sizeof (ipoib_ptxhdr_t)) {
    644 			if ((pmp = msgpullup(mp, -1)) == NULL) {
    645 #ifdef GLD_DEBUG
    646 				if (gld_debug & GLDERRS)
    647 					cmn_err(CE_WARN,
    648 					    "GLD: interpret_ib "
    649 					    "cannot msgpullup");
    650 #endif
    651 				return (-1);
    652 			}
    653 			/* this mblk contains the whole mac header */
    654 			mp = pmp;
    655 		}
    656 
    657 		/*
    658 		 * Check if mac is broadcast or multicast address; all these
    659 		 * types of address have the top 4 bytes as 0x00FFFFFF.
    660 		 */
    661 		if (mac_eq(&gldp->ipoib_dest, macinfo->gldm_broadcast_addr,
    662 		    sizeof (uint32_t))) {
    663 			if (mac_eq(&gldp->ipoib_dest,
    664 			    macinfo->gldm_broadcast_addr, IPOIB_ADDRL))
    665 				pktinfo->isBroadcast = 1;
    666 			else
    667 				pktinfo->isMulticast = 1;
    668 		}
    669 
    670 		/*
    671 		 * Only count bytes we will be sending over the wire
    672 		 * or looping back.
    673 		 */
    674 		pktinfo->pktLen -= IPOIB_ADDRL;
    675 		if (flags == GLD_TX)
    676 			goto out;	/* Got all info we need for xmit case */
    677 
    678 		/*
    679 		 * Loopback case: this is a dup'ed message.
    680 		 */
    681 		mp->b_rptr += IPOIB_ADDRL;
    682 		mac_copy(&gldp->ipoib_dest, pktinfo->dhost, IPOIB_ADDRL);
    683 		mac_copy(mac_pvt->curr_macaddr, pktinfo->shost, IPOIB_ADDRL);
    684 	} else {
    685 		/*
    686 		 * GLD_RX case; process packet sent from driver.
    687 		 */
    688 		ipoib_mac_t *mact, *tact;
    689 		ib_qpn_t dqpn;
    690 
    691 		pktinfo->pktLen = msgdsize(mp);
    692 		/* make sure packet has at least pgrh and mac header */
    693 		if (pktinfo->pktLen < (IPOIB_GRH_SIZE + IPOIB_HDRSIZE))
    694 			return (-1);
    695 
    696 		/* make sure the header falls into contiguous memory */
    697 		if (MBLKL(mp) < (IPOIB_GRH_SIZE + IPOIB_HDRSIZE)) {
    698 			if ((pmp = msgpullup(mp, -1)) == NULL) {
    699 #ifdef GLD_DEBUG
    700 				if (gld_debug & GLDERRS)
    701 					cmn_err(CE_WARN,
    702 					    "GLD: interpret_ib "
    703 					    "cannot msgpullup2");
    704 #endif
    705 				return (-1);
    706 			}
    707 			/* this mblk contains the whole mac header */
    708 			mp = pmp;
    709 		}
    710 
    711 		grh = (ipoib_pgrh_t *)mp->b_rptr;
    712 		mp->b_rptr += IPOIB_GRH_SIZE;
    713 		pktinfo->pktLen -= IPOIB_GRH_SIZE;
    714 		if (grh->ipoib_vertcflow) {
    715 			/*
    716 			 * First, copy source address from grh.
    717 			 */
    718 			mact = (ipoib_mac_t *)pktinfo->shost;
    719 			mac_copy(&grh->ipoib_sqpn, &mact->ipoib_qpn,
    720 			    IPOIB_ADDRL);
    721 
    722 			/*
    723 			 * Then copy destination address from grh;
    724 			 * first, the 16 bytes of GID.
    725 			 */
    726 			mact = (ipoib_mac_t *)pktinfo->dhost;
    727 			mac_copy(&grh->ipoib_dgid_pref,
    728 			    &mact->ipoib_gidpref, IPOIB_ADDRL -
    729 			    sizeof (mact->ipoib_qpn));
    730 			tact = (ipoib_mac_t *)mac_pvt->curr_macaddr;
    731 
    732 			/* Is this a multicast address */
    733 			if (*(uchar_t *)(grh->ipoib_dgid_pref) == 0xFF) {
    734 				/*
    735 				 * Only check for hardware looping in
    736 				 * multicast case. It is assumed higher
    737 				 * layer code (IP) will stop unicast loops;
    738 				 * ie will prevent a transmit to self.
    739 				 */
    740 				if (bcmp(&grh->ipoib_sqpn, tact,
    741 				    IPOIB_ADDRL) == 0)
    742 					pktinfo->isLooped = 1;
    743 
    744 				tact = (ipoib_mac_t *)macinfo->
    745 				    gldm_broadcast_addr;
    746 				if (mac_eq(tact->ipoib_gidpref,
    747 				    grh->ipoib_dgid_pref,
    748 				    IPOIB_ADDRL - sizeof (tact->ipoib_qpn)))
    749 					pktinfo->isBroadcast = 1;
    750 				else
    751 					pktinfo->isMulticast = 1;
    752 				/*
    753 				 * Now copy the 4 bytes QPN part of the
    754 				 * destination address.
    755 				 */
    756 				dqpn = htonl(IB_MC_QPN);
    757 				mac_copy(&dqpn, &mact->ipoib_qpn,
    758 				    sizeof (mact->ipoib_qpn));
    759 			} else {
    760 				/*
    761 				 * Now copy the 4 bytes QPN part of the
    762 				 * destination address.
    763 				 */
    764 				mac_copy(&tact->ipoib_qpn, &mact->ipoib_qpn,
    765 				    sizeof (mact->ipoib_qpn));
    766 				/*
    767 				 * Any unicast packets received on IBA are
    768 				 * for the node.
    769 				 */
    770 				pktinfo->isForMe = 1;
    771 			}
    772 		} else {
    773 			/*
    774 			 * It can not be a IBA multicast packet.
    775 			 * Must have been unicast to us. We do not
    776 			 * have shost information, which is used in
    777 			 * gld_addudind(); IP/ARP does not care.
    778 			 */
    779 			pktinfo->nosource = 1;
    780 			mac_copy(mac_pvt->curr_macaddr, pktinfo->dhost,
    781 			    IPOIB_ADDRL);
    782 			/*
    783 			 * Any unicast packets received on IBA are
    784 			 * for the node.
    785 			 */
    786 			pktinfo->isForMe = 1;
    787 		}
    788 	}
    789 
    790 	ASSERT((flags == GLD_RX) || (flags == GLD_RXLOOP));
    791 	ASSERT(GLDM_LOCK_HELD(macinfo));
    792 	pktinfo->ethertype = REF_NET_USHORT(((ipoib_hdr_t *)
    793 	    (mp->b_rptr))->ipoib_type);
    794 	pktinfo->macLen = IPOIB_HDRSIZE;
    795 
    796 out:
    797 	if (pmp != NULL)
    798 		freemsg(pmp);
    799 
    800 	return (0);
    801 }
    802 
    803 /*
    804  * The packet format sent to the driver is: 2b sap :: 2b 0s :: data
    805  */
    806 void
    807 gld_interpret_mdt_ib(gld_mac_info_t *macinfo, mblk_t *mp, pdescinfo_t *pinfo,
    808     pktinfo_t *pktinfo, mdt_packet_flag_t flags)
    809 {
    810 	gld_mac_pvt_t *mac_pvt;
    811 	multidata_t *dlmdp;
    812 	pattrinfo_t attr_info = { PATTR_DSTADDRSAP, };
    813 	pattr_t *patr;
    814 	ipoib_ptxhdr_t *dlap = NULL;
    815 
    816 	/*
    817 	 * Per packet formatting.
    818 	 */
    819 	if (flags == GLD_MDT_TXPKT) {
    820 		ipoib_hdr_t *hptr;
    821 		uint_t seg;
    822 
    823 		if (PDESC_HDRL(pinfo) == 0)
    824 			return;
    825 
    826 		/*
    827 		 * Update packet's link header.
    828 		 */
    829 		pinfo->hdr_rptr -= IPOIB_HDRSIZE;
    830 		hptr = (ipoib_hdr_t *)pinfo->hdr_rptr;
    831 		hptr->ipoib_mbz = htons(0);
    832 		hptr->ipoib_type = pktinfo->ethertype;
    833 
    834 		/*
    835 		 * Total #bytes that will be put on wire.
    836 		 */
    837 		pktinfo->pktLen = PDESC_HDRL(pinfo);
    838 		for (seg = 0; seg < pinfo->pld_cnt; seg++)
    839 			pktinfo->pktLen += PDESC_PLDL(pinfo, seg);
    840 
    841 		return;
    842 	}
    843 
    844 	/*
    845 	 * The following two cases of GLD_MDT_TX and GLD_MDT_RXLOOP are per
    846 	 * MDT message processing.
    847 	 */
    848 	dlmdp = mmd_getmultidata(mp);
    849 	patr = mmd_getpattr(dlmdp, NULL, &attr_info);
    850 	ASSERT(patr != NULL);
    851 	ASSERT(macinfo->gldm_saplen == -2);
    852 	if (patr != NULL)
    853 		dlap = (ipoib_ptxhdr_t *)((pattr_addr_t *)attr_info.buf)->addr;
    854 
    855 	if (flags == GLD_MDT_TX) {
    856 		bzero((void *)pktinfo, sizeof (*pktinfo));
    857 		if (dlap == NULL)
    858 			return;
    859 
    860 		/*
    861 		 * Check if mac is broadcast or multicast address; all these
    862 		 * types of address have the top 4 bytes as 0x00FFFFFF.
    863 		 */
    864 		if (mac_eq(dlap, macinfo->gldm_broadcast_addr,
    865 		    sizeof (uint32_t))) {
    866 			if (mac_eq(dlap, macinfo->gldm_broadcast_addr,
    867 			    IPOIB_ADDRL))
    868 				pktinfo->isBroadcast = 1;
    869 			else
    870 				pktinfo->isMulticast = 1;
    871 		}
    872 		pktinfo->ethertype = REF_NET_USHORT(dlap->
    873 		    ipoib_rhdr.ipoib_type);
    874 	} else {
    875 		ASSERT(flags == GLD_MDT_RXLOOP);
    876 		pktinfo->macLen = IPOIB_HDRSIZE;
    877 		mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
    878 		mac_copy(mac_pvt->curr_macaddr, pktinfo->shost, IPOIB_ADDRL);
    879 		if (dlap == NULL)
    880 			return;
    881 		mac_copy(&dlap->ipoib_dest, pktinfo->dhost, IPOIB_ADDRL);
    882 	}
    883 }
    884 
    885 mblk_t *
    886 gld_unitdata_ib(gld_t *gld, mblk_t *mp)
    887 {
    888 	gld_mac_info_t *macinfo = gld->gld_mac_info;
    889 	dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_rptr;
    890 	ipoib_ptxhdr_t *gldp = IPOIBDLSAP(dlp, dlp->dl_dest_addr_offset);
    891 	ipoib_mac_t dhost;
    892 	unsigned short type;
    893 	mblk_t *nmp;
    894 	int hdrlen;
    895 
    896 	ASSERT(macinfo != NULL);
    897 
    898 	/* extract needed info from the mblk before we maybe reuse it */
    899 	mac_copy(&gldp->ipoib_dest, &dhost, IPOIB_ADDRL);
    900 
    901 	/* look in the unitdata request for a sap, else use bound one */
    902 	if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
    903 	    REF_HOST_USHORT(gldp->ipoib_rhdr.ipoib_type) != 0)
    904 		type = REF_HOST_USHORT(gldp->ipoib_rhdr.ipoib_type);
    905 	else
    906 		type = gld->gld_sap;
    907 
    908 	hdrlen = sizeof (ipoib_ptxhdr_t);
    909 
    910 	/* need a buffer big enough for the headers */
    911 	nmp = mp->b_cont;	/* where the packet payload M_DATA is */
    912 	if (DB_REF(nmp) == 1 && MBLKHEAD(nmp) >= hdrlen) {
    913 		/* it fits at the beginning of the first M_DATA block */
    914 		freeb(mp);	/* don't need the M_PROTO anymore */
    915 	} else if (DB_REF(mp) == 1 && MBLKSIZE(mp) >= hdrlen) {
    916 		/* we can reuse the dl_unitdata_req M_PROTO mblk */
    917 		nmp = mp;
    918 		DB_TYPE(nmp) = M_DATA;
    919 		nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
    920 	} else {
    921 		/* we need to allocate one */
    922 		if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
    923 			return (NULL);
    924 		nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
    925 		linkb(nmp, mp->b_cont);
    926 		freeb(mp);
    927 	}
    928 
    929 	/* Got the space, now copy in the header components */
    930 
    931 	nmp->b_rptr -= sizeof (ipoib_ptxhdr_t);
    932 	gldp = (ipoib_ptxhdr_t *)nmp->b_rptr;
    933 	SET_NET_USHORT(gldp->ipoib_rhdr.ipoib_type, type);
    934 	gldp->ipoib_rhdr.ipoib_mbz = 0;
    935 	mac_copy(&dhost, &gldp->ipoib_dest, IPOIB_ADDRL);
    936 
    937 	return (nmp);
    938 }
    939 
    940 mblk_t *
    941 gld_fastpath_ib(gld_t *gld, mblk_t *mp)
    942 {
    943 	gld_mac_info_t *macinfo = gld->gld_mac_info;
    944 	dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
    945 	ipoib_ptxhdr_t *gldp = IPOIBDLSAP(dlp, dlp->dl_dest_addr_offset);
    946 	unsigned short type;
    947 	mblk_t *nmp;
    948 	ipoib_ptxhdr_t *tgldp;
    949 	int hdrlen;
    950 
    951 	ASSERT(macinfo != NULL);
    952 
    953 	/* look in the unitdata request for a sap, else use bound one */
    954 	if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
    955 	    REF_HOST_USHORT(gldp->ipoib_rhdr.ipoib_type) != 0)
    956 		type = REF_HOST_USHORT(gldp->ipoib_rhdr.ipoib_type);
    957 	else
    958 		type = gld->gld_sap;
    959 
    960 	hdrlen = sizeof (ipoib_ptxhdr_t);
    961 
    962 	if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
    963 		return (NULL);
    964 
    965 	nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
    966 
    967 	/* Got the space, now copy in the header components */
    968 
    969 	nmp->b_rptr -= sizeof (ipoib_ptxhdr_t);
    970 	tgldp = (ipoib_ptxhdr_t *)nmp->b_rptr;
    971 	tgldp->ipoib_rhdr.ipoib_type = htons(type);
    972 	tgldp->ipoib_rhdr.ipoib_mbz = 0;
    973 	mac_copy(&gldp->ipoib_dest, &tgldp->ipoib_dest, IPOIB_ADDRL);
    974 
    975 	return (nmp);
    976 }
    977 
    978 /* ==== */
    979 /* FDDI */
    980 /* ==== */
    981 
    982 void
    983 gld_init_fddi(gld_mac_info_t *macinfo)
    984 {
    985 	struct gldkstats *sp =
    986 	    ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->kstatp->ks_data;
    987 
    988 	/* Assumptions we make for this medium */
    989 	ASSERT(macinfo->gldm_type == DL_FDDI);
    990 	ASSERT(macinfo->gldm_addrlen == 6);
    991 	ASSERT(macinfo->gldm_saplen == -2);
    992 #ifndef	lint
    993 	ASSERT(sizeof (struct fddi_mac_frm) == 13);
    994 	ASSERT(sizeof (mac_addr_t) == 6);
    995 #endif
    996 
    997 	/* Wire address format is bit reversed from canonical format */
    998 	macinfo->gldm_options |= GLDOPT_CANONICAL_ADDR;
    999 
   1000 	kstat_named_init(&sp->glds_fddi_mac_error,
   1001 	    "mac_errors", KSTAT_DATA_UINT32);
   1002 	kstat_named_init(&sp->glds_fddi_mac_lost,
   1003 	    "mac_lost_errors", KSTAT_DATA_UINT32);
   1004 	kstat_named_init(&sp->glds_fddi_mac_token,
   1005 	    "mac_tokens", KSTAT_DATA_UINT32);
   1006 	kstat_named_init(&sp->glds_fddi_mac_tvx_expired,
   1007 	    "mac_tvx_expired", KSTAT_DATA_UINT32);
   1008 	kstat_named_init(&sp->glds_fddi_mac_late,
   1009 	    "mac_late", KSTAT_DATA_UINT32);
   1010 	kstat_named_init(&sp->glds_fddi_mac_ring_op,
   1011 	    "mac_ring_ops", KSTAT_DATA_UINT32);
   1012 }
   1013 
   1014 /*ARGSUSED*/
   1015 void
   1016 gld_uninit_fddi(gld_mac_info_t *macinfo)
   1017 {
   1018 }
   1019 
   1020 int
   1021 gld_interpret_fddi(gld_mac_info_t *macinfo, mblk_t *mp, pktinfo_t *pktinfo,
   1022     packet_flag_t flags)
   1023 {
   1024 	struct fddi_mac_frm *mh;
   1025 	gld_mac_pvt_t *mac_pvt;
   1026 	struct llc_snap_hdr *snaphdr;
   1027 	mblk_t *pmp = NULL;
   1028 
   1029 	/*
   1030 	 * Quickly handle receive fastpath; FDDI does not support IPQ hack.
   1031 	 */
   1032 	if (flags == GLD_RXQUICK) {
   1033 		pktinfo->pktLen = msgdsize(mp);
   1034 		return (-1);
   1035 	}
   1036 
   1037 	bzero((void *)pktinfo, sizeof (*pktinfo));
   1038 
   1039 	pktinfo->pktLen = msgdsize(mp);
   1040 
   1041 	/* make sure packet has at least a whole mac header */
   1042 	if (pktinfo->pktLen < sizeof (struct fddi_mac_frm))
   1043 		return (-1);
   1044 
   1045 	/* make sure the mac header falls into contiguous memory */
   1046 	if (MBLKL(mp) < sizeof (struct fddi_mac_frm)) {
   1047 		if ((pmp = msgpullup(mp, -1)) == NULL) {
   1048 #ifdef GLD_DEBUG
   1049 			if (gld_debug & GLDERRS)
   1050 				cmn_err(CE_WARN,
   1051 				    "GLD: interpret_fddi cannot msgpullup");
   1052 #endif
   1053 			return (-1);
   1054 		}
   1055 		mp = pmp;	/* this mblk contains the whole mac header */
   1056 	}
   1057 
   1058 	mh = (struct fddi_mac_frm *)mp->b_rptr;
   1059 
   1060 	/* Check to see if the mac is a broadcast or multicast address. */
   1061 	/* NB we are still in wire format (non canonical) */
   1062 	/* mac_eq works because ether_broadcast is the same either way */
   1063 	if (mac_eq(mh->fddi_dhost, ether_broadcast, macinfo->gldm_addrlen))
   1064 		pktinfo->isBroadcast = 1;
   1065 	else if (mh->fddi_dhost[0] & 0x80)
   1066 		pktinfo->isMulticast = 1;
   1067 
   1068 	if (flags == GLD_TX)
   1069 		goto out;	/* Got all info we need for xmit case */
   1070 
   1071 	ASSERT(GLDM_LOCK_HELD(macinfo));
   1072 
   1073 	/*
   1074 	 * Deal with the mac header
   1075 	 */
   1076 
   1077 	cmac_copy(mh->fddi_dhost, pktinfo->dhost,
   1078 	    macinfo->gldm_addrlen, macinfo);
   1079 	cmac_copy(mh->fddi_shost, pktinfo->shost,
   1080 	    macinfo->gldm_addrlen, macinfo);
   1081 
   1082 	mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
   1083 	pktinfo->isLooped = mac_eq(pktinfo->shost,
   1084 	    mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
   1085 	pktinfo->isForMe = mac_eq(pktinfo->dhost,
   1086 	    mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
   1087 
   1088 	pktinfo->macLen = sizeof (struct fddi_mac_frm);
   1089 
   1090 	/*
   1091 	 * Before trying to look beyond the MAC header, make sure the LLC
   1092 	 * header exists, and that both it and any SNAP header are contiguous.
   1093 	 */
   1094 	if (MBLKL(mp) < sizeof (struct fddi_mac_frm) + LLC_SNAP_HDR_LEN &&
   1095 	    MBLKL(mp) < pktinfo->pktLen) {
   1096 		/*
   1097 		 * we don't have the entire packet within the first mblk (and
   1098 		 * therefore we didn't do the msgpullup above), AND the first
   1099 		 * mblk may not contain all the data we need to look at.
   1100 		 */
   1101 		ASSERT(pmp == NULL);	/* couldn't have done msgpullup above */
   1102 		if ((pmp = msgpullup(mp, -1)) == NULL) {
   1103 #ifdef GLD_DEBUG
   1104 			if (gld_debug & GLDERRS)
   1105 				cmn_err(CE_WARN,
   1106 				    "GLD: interpret_fddi cannot msgpullup2");
   1107 #endif
   1108 			goto out;	/* can't interpret this pkt further */
   1109 		}
   1110 		mp = pmp;	/* this mblk should contain everything needed */
   1111 	}
   1112 
   1113 	/*
   1114 	 * Check SAP/SNAP information.
   1115 	 */
   1116 	if ((mh->fddi_fc & 0x70) == 0x50) {
   1117 		if (pktinfo->pktLen < pktinfo->macLen + LLC_HDR1_LEN)
   1118 			goto out;
   1119 
   1120 		pktinfo->isLLC = 1;
   1121 
   1122 		if (pktinfo->pktLen < pktinfo->macLen + LLC_SNAP_HDR_LEN)
   1123 			goto out;
   1124 
   1125 		snaphdr = (struct llc_snap_hdr *)(mp->b_rptr + pktinfo->macLen);
   1126 		if (ISETHERTYPE(snaphdr)) {
   1127 			pktinfo->ethertype = REF_NET_USHORT(snaphdr->type);
   1128 			pktinfo->hdrLen = LLC_SNAP_HDR_LEN;
   1129 		}
   1130 	}
   1131 out:
   1132 	if (pmp != NULL)
   1133 		freemsg(pmp);
   1134 
   1135 	return (0);
   1136 }
   1137 
   1138 mblk_t *
   1139 gld_unitdata_fddi(gld_t *gld, mblk_t *mp)
   1140 {
   1141 	gld_mac_info_t *macinfo = gld->gld_mac_info;
   1142 	dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_rptr;
   1143 	struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
   1144 	mac_addr_t dhost;
   1145 	unsigned short type;
   1146 	mblk_t *nmp;
   1147 	struct fddi_mac_frm *mh;
   1148 	int hdrlen;
   1149 
   1150 	ASSERT(macinfo);
   1151 
   1152 	/* extract needed info from the mblk before we maybe reuse it */
   1153 	mac_copy(gldp->glda_addr, dhost, macinfo->gldm_addrlen);
   1154 
   1155 	/* look in the unitdata request for a sap, else use bound one */
   1156 	if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
   1157 	    REF_HOST_USHORT(gldp->glda_sap) != 0)
   1158 		type = REF_HOST_USHORT(gldp->glda_sap);
   1159 	else
   1160 		type = gld->gld_sap;
   1161 
   1162 
   1163 	hdrlen = sizeof (struct fddi_mac_frm);
   1164 
   1165 	/*
   1166 	 * Check whether we need to do EtherType encoding or whether the packet
   1167 	 * is LLC.
   1168 	 */
   1169 	if (type > GLD_MAX_802_SAP)
   1170 		hdrlen += sizeof (struct llc_snap_hdr);
   1171 
   1172 	/* need a buffer big enough for the headers */
   1173 	nmp = mp->b_cont;	/* where the packet payload M_DATA is */
   1174 	if (DB_REF(nmp) == 1 && MBLKHEAD(nmp) >= hdrlen) {
   1175 		/* it fits at the beginning of the first M_DATA block */
   1176 		freeb(mp);	/* don't need the M_PROTO anymore */
   1177 	} else if (DB_REF(mp) == 1 && MBLKSIZE(mp) >= hdrlen) {
   1178 		/* we can reuse the dl_unitdata_req M_PROTO mblk */
   1179 		nmp = mp;
   1180 		DB_TYPE(nmp) = M_DATA;
   1181 		nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
   1182 	} else {
   1183 		/* we need to allocate one */
   1184 		if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
   1185 			return (NULL);
   1186 		nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
   1187 		linkb(nmp, mp->b_cont);
   1188 		freeb(mp);
   1189 	}
   1190 
   1191 
   1192 	/* Got the space, now copy in the header components */
   1193 	if (type > GLD_MAX_802_SAP) {
   1194 		/* create the snap header */
   1195 		struct llc_snap_hdr *snap;
   1196 		nmp->b_rptr -= sizeof (struct llc_snap_hdr);
   1197 		snap  = (struct llc_snap_hdr *)(nmp->b_rptr);
   1198 		*snap = llc_snap_def;
   1199 		SET_NET_USHORT(snap->type, type);
   1200 	}
   1201 
   1202 	nmp->b_rptr -= sizeof (struct fddi_mac_frm);
   1203 
   1204 	mh = (struct fddi_mac_frm *)nmp->b_rptr;
   1205 
   1206 	mh->fddi_fc = 0x50;
   1207 	cmac_copy(dhost, mh->fddi_dhost, macinfo->gldm_addrlen, macinfo);
   1208 
   1209 	/*
   1210 	 * We access the mac address without the mutex to prevent
   1211 	 * mutex contention (BUG 4211361)
   1212 	 */
   1213 	cmac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
   1214 	    mh->fddi_shost, macinfo->gldm_addrlen, macinfo);
   1215 	return (nmp);
   1216 }
   1217 
   1218 mblk_t *
   1219 gld_fastpath_fddi(gld_t *gld, mblk_t *mp)
   1220 {
   1221 	gld_mac_info_t *macinfo = gld->gld_mac_info;
   1222 	dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
   1223 	struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
   1224 	unsigned short type;
   1225 	mblk_t *nmp;
   1226 	struct fddi_mac_frm *mh;
   1227 	int hdrlen;
   1228 
   1229 	ASSERT(macinfo);
   1230 
   1231 	/* look in the unitdata request for a sap, else use bound one */
   1232 	if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
   1233 	    REF_HOST_USHORT(gldp->glda_sap) != 0)
   1234 		type = REF_HOST_USHORT(gldp->glda_sap);
   1235 	else
   1236 		type = gld->gld_sap;
   1237 
   1238 	hdrlen = sizeof (struct fddi_mac_frm);
   1239 
   1240 	/*
   1241 	 * Check whether we need to do EtherType encoding or whether the packet
   1242 	 * will be LLC.
   1243 	 */
   1244 	if (type > GLD_MAX_802_SAP)
   1245 		hdrlen += sizeof (struct llc_snap_hdr);
   1246 
   1247 	if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
   1248 		return (NULL);
   1249 
   1250 	nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
   1251 
   1252 	/* Got the space, now copy in the header components */
   1253 
   1254 	if (type > GLD_MAX_802_SAP) {
   1255 		/* create the snap header */
   1256 		struct llc_snap_hdr *snap;
   1257 		nmp->b_rptr -= sizeof (struct llc_snap_hdr);
   1258 		snap  = (struct llc_snap_hdr *)(nmp->b_rptr);
   1259 		*snap = llc_snap_def;
   1260 		snap->type = htons(type);	/* we know it's aligned */
   1261 	}
   1262 
   1263 	nmp->b_rptr -= sizeof (struct fddi_mac_frm);
   1264 
   1265 	mh = (struct fddi_mac_frm *)nmp->b_rptr;
   1266 	mh->fddi_fc = 0x50;
   1267 	cmac_copy(gldp->glda_addr, mh->fddi_dhost,
   1268 	    macinfo->gldm_addrlen, macinfo);
   1269 
   1270 	GLDM_LOCK(macinfo, RW_WRITER);
   1271 	cmac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
   1272 	    mh->fddi_shost, macinfo->gldm_addrlen, macinfo);
   1273 	GLDM_UNLOCK(macinfo);
   1274 
   1275 	return (nmp);
   1276 }
   1277 
   1278 /* ========== */
   1279 /* Token Ring */
   1280 /* ========== */
   1281 
   1282 #define	GLD_SR_VAR(macinfo)	\
   1283 	(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->data)
   1284 
   1285 #define	GLD_SR_HASH(macinfo)	((struct srtab **)GLD_SR_VAR(macinfo))
   1286 
   1287 #define	GLD_SR_MUTEX(macinfo)	\
   1288 	(&((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->datalock)
   1289 
   1290 static void gld_sr_clear(gld_mac_info_t *);
   1291 static void gld_rcc_receive(gld_mac_info_t *, pktinfo_t *, struct gld_ri *,
   1292     uchar_t *, int);
   1293 static void gld_rcc_send(gld_mac_info_t *, queue_t *, uchar_t *,
   1294     struct gld_ri **, uchar_t *);
   1295 
   1296 static mac_addr_t tokenbroadcastaddr2 = { 0xc0, 0x00, 0xff, 0xff, 0xff, 0xff };
   1297 static struct gld_ri ri_ste_def;
   1298 
   1299 void
   1300 gld_init_tr(gld_mac_info_t *macinfo)
   1301 {
   1302 	struct gldkstats *sp =
   1303 	    ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->kstatp->ks_data;
   1304 
   1305 	/* avoid endian-dependent code by initializing here instead of static */
   1306 	ri_ste_def.len = 2;
   1307 	ri_ste_def.rt = RT_STE;
   1308 	ri_ste_def.mtu = RT_MTU_MAX;
   1309 	ri_ste_def.dir = 0;
   1310 	ri_ste_def.res = 0;
   1311 
   1312 	/* Assumptions we make for this medium */
   1313 	ASSERT(macinfo->gldm_type == DL_TPR);
   1314 	ASSERT(macinfo->gldm_addrlen == 6);
   1315 	ASSERT(macinfo->gldm_saplen == -2);
   1316 #ifndef	lint
   1317 	ASSERT(sizeof (struct tr_mac_frm_nori) == 14);
   1318 	ASSERT(sizeof (mac_addr_t) == 6);
   1319 #endif
   1320 
   1321 	mutex_init(GLD_SR_MUTEX(macinfo), NULL, MUTEX_DRIVER, NULL);
   1322 
   1323 	GLD_SR_VAR(macinfo) = kmem_zalloc(sizeof (struct srtab *)*SR_HASH_SIZE,
   1324 				KM_SLEEP);
   1325 
   1326 	/* Default is RDE enabled for this medium */
   1327 	((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_enabled =
   1328 	    ddi_getprop(DDI_DEV_T_NONE, macinfo->gldm_devinfo, 0,
   1329 	    "gld_rde_enable", 1);
   1330 
   1331 	/*
   1332 	 * Default is to use STE for unknown paths if RDE is enabled.
   1333 	 * If RDE is disabled, default is to use NULL RIF fields.
   1334 	 *
   1335 	 * It's possible to force use of STE for ALL packets:
   1336 	 * disable RDE but enable STE.  This may be useful for
   1337 	 * non-transparent bridges, when it is not desired to run
   1338 	 * the RDE algorithms.
   1339 	 */
   1340 	((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_str_indicator_ste =
   1341 	    ddi_getprop(DDI_DEV_T_NONE, macinfo->gldm_devinfo, 0,
   1342 	    "gld_rde_str_indicator_ste",
   1343 	    ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_enabled);
   1344 
   1345 	/* Default 10 second route timeout on lack of activity */
   1346 	{
   1347 	int t = ddi_getprop(DDI_DEV_T_NONE, macinfo->gldm_devinfo, 0,
   1348 	    "gld_rde_timeout", 10);
   1349 	if (t < 1)
   1350 		t = 1;		/* Let's be reasonable */
   1351 	if (t > 600)
   1352 		t = 600;	/* Let's be reasonable */
   1353 	/* We're using ticks (lbolts) for our timeout -- convert from seconds */
   1354 	t = drv_usectohz(1000000 * t);
   1355 	((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_timeout = t;
   1356 	}
   1357 
   1358 	kstat_named_init(&sp->glds_dot5_line_error,
   1359 	    "line_errors", KSTAT_DATA_UINT32);
   1360 	kstat_named_init(&sp->glds_dot5_burst_error,
   1361 	    "burst_errors", KSTAT_DATA_UINT32);
   1362 	kstat_named_init(&sp->glds_dot5_signal_loss,
   1363 	    "signal_losses", KSTAT_DATA_UINT32);
   1364 
   1365 	/*
   1366 	 * only initialize the new statistics if the driver
   1367 	 * knows about them.
   1368 	 */
   1369 	if (macinfo->gldm_driver_version != GLD_VERSION_200)
   1370 		return;
   1371 
   1372 	kstat_named_init(&sp->glds_dot5_ace_error,
   1373 	    "ace_errors", KSTAT_DATA_UINT32);
   1374 	kstat_named_init(&sp->glds_dot5_internal_error,
   1375 	    "internal_errors", KSTAT_DATA_UINT32);
   1376 	kstat_named_init(&sp->glds_dot5_lost_frame_error,
   1377 	    "lost_frame_errors", KSTAT_DATA_UINT32);
   1378 	kstat_named_init(&sp->glds_dot5_frame_copied_error,
   1379 	    "frame_copied_errors", KSTAT_DATA_UINT32);
   1380 	kstat_named_init(&sp->glds_dot5_token_error,
   1381 	    "token_errors", KSTAT_DATA_UINT32);
   1382 	kstat_named_init(&sp->glds_dot5_freq_error,
   1383 	    "freq_errors", KSTAT_DATA_UINT32);
   1384 }
   1385 
   1386 void
   1387 gld_uninit_tr(gld_mac_info_t *macinfo)
   1388 {
   1389 	mutex_destroy(GLD_SR_MUTEX(macinfo));
   1390 	gld_sr_clear(macinfo);
   1391 	kmem_free(GLD_SR_VAR(macinfo), sizeof (struct srtab *) * SR_HASH_SIZE);
   1392 }
   1393 
   1394 int
   1395 gld_interpret_tr(gld_mac_info_t *macinfo, mblk_t *mp, pktinfo_t *pktinfo,
   1396     packet_flag_t flags)
   1397 {
   1398 	struct tr_mac_frm *mh;
   1399 	gld_mac_pvt_t *mac_pvt;
   1400 	struct llc_snap_hdr *snaphdr;
   1401 	mblk_t *pmp = NULL;
   1402 	struct gld_ri *rh;
   1403 
   1404 	/*
   1405 	 * Quickly handle receive fastpath; TR does not support IPQ hack.
   1406 	 */
   1407 	if (flags == GLD_RXQUICK) {
   1408 		pktinfo->pktLen = msgdsize(mp);
   1409 		return (-1);
   1410 	}
   1411 
   1412 	bzero((void *)pktinfo, sizeof (*pktinfo));
   1413 
   1414 	pktinfo->pktLen = msgdsize(mp);
   1415 
   1416 	/* make sure packet has at least a whole mac header */
   1417 	if (pktinfo->pktLen < sizeof (struct tr_mac_frm_nori))
   1418 		return (-1);
   1419 
   1420 	/* make sure the mac header falls into contiguous memory */
   1421 	if (MBLKL(mp) < sizeof (struct tr_mac_frm_nori)) {
   1422 		if ((pmp = msgpullup(mp, -1)) == NULL) {
   1423 #ifdef GLD_DEBUG
   1424 			if (gld_debug & GLDERRS)
   1425 				cmn_err(CE_WARN,
   1426 				    "GLD: interpret_tr cannot msgpullup");
   1427 #endif
   1428 			return (-1);
   1429 		}
   1430 		mp = pmp;	/* this mblk contains the whole mac header */
   1431 	}
   1432 
   1433 	mh = (struct tr_mac_frm *)mp->b_rptr;
   1434 
   1435 	/* Check to see if the mac is a broadcast or multicast address. */
   1436 	if (mac_eq(mh->tr_dhost, ether_broadcast, macinfo->gldm_addrlen) ||
   1437 	    mac_eq(mh->tr_dhost, tokenbroadcastaddr2, macinfo->gldm_addrlen))
   1438 		pktinfo->isBroadcast = 1;
   1439 	else if (mh->tr_dhost[0] & 0x80)
   1440 		pktinfo->isMulticast = 1;
   1441 
   1442 	if (flags == GLD_TX)
   1443 		goto out;	/* Got all info we need for xmit case */
   1444 
   1445 	ASSERT(GLDM_LOCK_HELD(macinfo));
   1446 
   1447 	/*
   1448 	 * Deal with the mac header
   1449 	 */
   1450 
   1451 	mac_copy(mh->tr_dhost, pktinfo->dhost, macinfo->gldm_addrlen);
   1452 	mac_copy(mh->tr_shost, pktinfo->shost, macinfo->gldm_addrlen);
   1453 	pktinfo->shost[0] &= ~0x80;	/* turn off RIF indicator */
   1454 
   1455 	mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
   1456 	pktinfo->isLooped = mac_eq(pktinfo->shost,
   1457 	    mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
   1458 	pktinfo->isForMe = mac_eq(pktinfo->dhost,
   1459 	    mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
   1460 
   1461 	rh = (struct gld_ri *)NULL;
   1462 	pktinfo->macLen = sizeof (struct tr_mac_frm_nori);
   1463 
   1464 	/*
   1465 	 * Before trying to look beyond the MAC header, make sure the data
   1466 	 * structures are all contiguously where we can conveniently look at
   1467 	 * them.  We'll use a worst-case estimate of how many bytes into the
   1468 	 * packet data we'll be needing to look.  Things will be more efficient
   1469 	 * if the driver puts at least this much into the first mblk.
   1470 	 *
   1471 	 * Even after this, we still will have to do checks against the total
   1472 	 * length of the packet.  A bad incoming packet may not hold all the
   1473 	 * data structures it says it does.
   1474 	 */
   1475 	if (MBLKL(mp) < sizeof (struct tr_mac_frm) +
   1476 	    LLC_HDR1_LEN + sizeof (struct rde_pdu) &&
   1477 	    MBLKL(mp) < pktinfo->pktLen) {
   1478 		/*
   1479 		 * we don't have the entire packet within the first mblk (and
   1480 		 * therefore we didn't do the msgpullup above), AND the first
   1481 		 * mblk may not contain all the data we need to look at.
   1482 		 */
   1483 		ASSERT(pmp == NULL);	/* couldn't have done msgpullup above */
   1484 		if ((pmp = msgpullup(mp, -1)) == NULL) {
   1485 #ifdef GLD_DEBUG
   1486 			if (gld_debug & GLDERRS)
   1487 				cmn_err(CE_WARN,
   1488 				    "GLD: interpret_tr cannot msgpullup2");
   1489 #endif
   1490 			goto out;	/* can't interpret this pkt further */
   1491 		}
   1492 		mp = pmp;	/* this mblk should contain everything needed */
   1493 		mh = (struct tr_mac_frm *)mp->b_rptr;	/* to look at RIF */
   1494 	}
   1495 
   1496 	if (mh->tr_shost[0] & 0x80) {
   1497 		/* Routing Information Field (RIF) is present */
   1498 		if (pktinfo->pktLen < sizeof (struct tr_mac_frm_nori) + 2)
   1499 			goto out;	/* RIF should have been there! */
   1500 		rh = (struct gld_ri *)&mh->tr_ri;
   1501 		if ((rh->len & 1) || rh->len < 2) {
   1502 			/* Bogus RIF, don't handle this packet */
   1503 #ifdef GLD_DEBUG
   1504 			if (gld_debug & GLDERRS)
   1505 				cmn_err(CE_WARN,
   1506 				    "GLD: received TR packet with "
   1507 				    "bogus RIF length %d",
   1508 				    rh->len);
   1509 #endif
   1510 			goto out;
   1511 		}
   1512 		if (pktinfo->pktLen < sizeof (struct tr_mac_frm_nori) + rh->len)
   1513 			goto out;	/* RIF should have been there! */
   1514 		pktinfo->macLen += rh->len;
   1515 	}
   1516 
   1517 	if ((mh->tr_fc & 0xc0) == 0x40) {
   1518 		if (pktinfo->pktLen < pktinfo->macLen + LLC_HDR1_LEN)
   1519 			goto out;
   1520 
   1521 		pktinfo->isLLC = 1;
   1522 
   1523 		if (pktinfo->pktLen < pktinfo->macLen + LLC_SNAP_HDR_LEN)
   1524 			goto out;
   1525 
   1526 		snaphdr = (struct llc_snap_hdr *)(mp->b_rptr + pktinfo->macLen);
   1527 		if (ISETHERTYPE(snaphdr)) {
   1528 			pktinfo->ethertype = REF_NET_USHORT(snaphdr->type);
   1529 			pktinfo->hdrLen = LLC_SNAP_HDR_LEN;
   1530 		}
   1531 
   1532 		/* Inform the Route Control Component of received LLC frame */
   1533 		gld_rcc_receive(macinfo, pktinfo, rh,
   1534 		    mp->b_rptr + pktinfo->macLen,
   1535 		    pktinfo->pktLen - pktinfo->macLen);
   1536 	}
   1537 out:
   1538 	if (pmp != NULL)
   1539 		freemsg(pmp);
   1540 
   1541 	return (0);
   1542 }
   1543 
   1544 mblk_t *
   1545 gld_unitdata_tr(gld_t *gld, mblk_t *mp)
   1546 {
   1547 	gld_mac_info_t *macinfo = gld->gld_mac_info;
   1548 	dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_rptr;
   1549 	struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
   1550 	mac_addr_t dhost;
   1551 	unsigned short type;
   1552 	mblk_t *nmp, *llcmp, *pmp = NULL;
   1553 	struct tr_mac_frm_nori *mh;
   1554 	int hdrlen;
   1555 	struct gld_ri *rh;
   1556 
   1557 	ASSERT(macinfo);
   1558 
   1559 	/* extract needed info from the mblk before we maybe reuse it */
   1560 	mac_copy(gldp->glda_addr, dhost, macinfo->gldm_addrlen);
   1561 
   1562 	/* look in the unitdata request for a sap, else use bound one */
   1563 	if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
   1564 	    REF_HOST_USHORT(gldp->glda_sap) != 0)
   1565 		type = REF_HOST_USHORT(gldp->glda_sap);
   1566 	else
   1567 		type = gld->gld_sap;
   1568 
   1569 	/* includes maximum possible Routing Information Field (RIF) size */
   1570 	hdrlen = sizeof (struct tr_mac_frm);
   1571 
   1572 	/*
   1573 	 * Check whether we need to do EtherType encoding or whether the packet
   1574 	 * is LLC.
   1575 	 */
   1576 	if (type > GLD_MAX_802_SAP)
   1577 		hdrlen += sizeof (struct llc_snap_hdr);
   1578 
   1579 	/* need a buffer big enough for the headers */
   1580 	llcmp = nmp = mp->b_cont; /* where the packet payload M_DATA is */
   1581 
   1582 	/*
   1583 	 * We are going to need to look at the LLC header, so make sure it
   1584 	 * is contiguously in a single mblk.  If we're the ones who create
   1585 	 * the LLC header (below, in the case where sap > 0xff) then we don't
   1586 	 * have to worry about it here.
   1587 	 */
   1588 	ASSERT(nmp != NULL);	/* gld_unitdata guarantees msgdsize > 0 */
   1589 	if (type <= GLD_MAX_802_SAP) {
   1590 		if (MBLKL(llcmp) < LLC_HDR1_LEN) {
   1591 			llcmp = pmp = msgpullup(nmp, LLC_HDR1_LEN);
   1592 			if (pmp == NULL) {
   1593 #ifdef GLD_DEBUG
   1594 				if (gld_debug & GLDERRS)
   1595 					cmn_err(CE_WARN,
   1596 					    "GLD: unitdata_tr "
   1597 					    "cannot msgpullup");
   1598 #endif
   1599 				return (NULL);
   1600 			}
   1601 		}
   1602 	}
   1603 
   1604 	if (DB_REF(nmp) == 1 && MBLKHEAD(nmp) >= hdrlen) {
   1605 		/* it fits at the beginning of the first M_DATA block */
   1606 		freeb(mp);	/* don't need the M_PROTO anymore */
   1607 	} else if (DB_REF(mp) == 1 && MBLKSIZE(mp) >= hdrlen) {
   1608 		/* we can reuse the dl_unitdata_req M_PROTO mblk */
   1609 		nmp = mp;
   1610 		DB_TYPE(nmp) = M_DATA;
   1611 		nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
   1612 	} else {
   1613 		/* we need to allocate one */
   1614 		if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL) {
   1615 			if (pmp != NULL)
   1616 				freemsg(pmp);
   1617 			return (NULL);
   1618 		}
   1619 		nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
   1620 		linkb(nmp, mp->b_cont);
   1621 		freeb(mp);
   1622 	}
   1623 
   1624 	/* Got the space, now copy in the header components */
   1625 	if (type > GLD_MAX_802_SAP) {
   1626 		/* create the snap header */
   1627 		struct llc_snap_hdr *snap;
   1628 		llcmp = nmp;	/* LLC header is going to be in this mblk */
   1629 		nmp->b_rptr -= sizeof (struct llc_snap_hdr);
   1630 		snap  = (struct llc_snap_hdr *)(nmp->b_rptr);
   1631 		*snap = llc_snap_def;
   1632 		SET_NET_USHORT(snap->type, type);
   1633 	}
   1634 
   1635 	/* Hold SR tables still while we maybe point at an entry */
   1636 	mutex_enter(GLD_SR_MUTEX(macinfo));
   1637 
   1638 	gld_rcc_send(macinfo, WR(gld->gld_qptr), dhost, &rh, llcmp->b_rptr);
   1639 
   1640 	if (rh != NULL) {
   1641 		/* copy in the RIF */
   1642 		ASSERT(rh->len <= sizeof (struct gld_ri));
   1643 		nmp->b_rptr -= rh->len;
   1644 		bcopy((caddr_t)rh, (caddr_t)nmp->b_rptr, rh->len);
   1645 	}
   1646 
   1647 	mutex_exit(GLD_SR_MUTEX(macinfo));
   1648 
   1649 	/* no longer need the pulled-up mblk */
   1650 	if (pmp != NULL)
   1651 		freemsg(pmp);
   1652 
   1653 	/*
   1654 	 * fill in token ring header
   1655 	 */
   1656 	nmp->b_rptr -= sizeof (struct tr_mac_frm_nori);
   1657 	mh = (struct tr_mac_frm_nori *)nmp->b_rptr;
   1658 	mh->tr_ac = 0x10;
   1659 	mh->tr_fc = 0x40;
   1660 	mac_copy(dhost, mh->tr_dhost, macinfo->gldm_addrlen);
   1661 
   1662 	/*
   1663 	 * We access the mac address without the mutex to prevent
   1664 	 * mutex contention (BUG 4211361)
   1665 	 */
   1666 	mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
   1667 	    mh->tr_shost, macinfo->gldm_addrlen);
   1668 
   1669 	if (rh != NULL)
   1670 		mh->tr_shost[0] |= 0x80;
   1671 	else
   1672 		mh->tr_shost[0] &= ~0x80;
   1673 
   1674 	return (nmp);
   1675 }
   1676 
   1677 /*
   1678  * We cannot have our client sending us "fastpath" M_DATA messages,
   1679  * because to do that we must provide to him a fixed MAC header to
   1680  * be prepended to each outgoing packet.  But with Source Routing
   1681  * media, the length and content of the MAC header changes as the
   1682  * routes change, so there is no fixed header we can provide.  So
   1683  * we decline to accept M_DATA messages if Source Routing is enabled.
   1684  */
   1685 mblk_t *
   1686 gld_fastpath_tr(gld_t *gld, mblk_t *mp)
   1687 {
   1688 	gld_mac_info_t *macinfo = gld->gld_mac_info;
   1689 	dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
   1690 	struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
   1691 	unsigned short type;
   1692 	mblk_t *nmp;
   1693 	struct tr_mac_frm_nori *mh;
   1694 	int hdrlen;
   1695 
   1696 	ASSERT(macinfo);
   1697 
   1698 	/*
   1699 	 * If we are doing Source Routing, then we cannot provide a fixed
   1700 	 * MAC header, so fail.
   1701 	 */
   1702 	if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_enabled)
   1703 		return (NULL);
   1704 
   1705 	/* look in the unitdata request for a sap, else use bound one */
   1706 	if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
   1707 	    REF_HOST_USHORT(gldp->glda_sap) != 0)
   1708 		type = REF_HOST_USHORT(gldp->glda_sap);
   1709 	else
   1710 		type = gld->gld_sap;
   1711 
   1712 	hdrlen = sizeof (struct tr_mac_frm_nori);
   1713 
   1714 	if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_str_indicator_ste)
   1715 		hdrlen += ri_ste_def.len;
   1716 
   1717 	/*
   1718 	 * Check whether we need to do EtherType encoding or whether the packet
   1719 	 * will be LLC.
   1720 	 */
   1721 	if (type > GLD_MAX_802_SAP)
   1722 		hdrlen += sizeof (struct llc_snap_hdr);
   1723 
   1724 	if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
   1725 		return (NULL);
   1726 
   1727 	nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
   1728 
   1729 	/* Got the space, now copy in the header components */
   1730 
   1731 	if (type > GLD_MAX_802_SAP) {
   1732 		/* create the snap header */
   1733 		struct llc_snap_hdr *snap;
   1734 		nmp->b_rptr -= sizeof (struct llc_snap_hdr);
   1735 		snap  = (struct llc_snap_hdr *)(nmp->b_rptr);
   1736 		*snap = llc_snap_def;
   1737 		snap->type = htons(type);	/* we know it's aligned */
   1738 	}
   1739 
   1740 	/* RDE is disabled, use NULL RIF, or STE RIF */
   1741 	if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_str_indicator_ste) {
   1742 		nmp->b_rptr -= ri_ste_def.len;
   1743 		bcopy((caddr_t)&ri_ste_def, (caddr_t)nmp->b_rptr,
   1744 		    ri_ste_def.len);
   1745 	}
   1746 
   1747 	/*
   1748 	 * fill in token ring header
   1749 	 */
   1750 	nmp->b_rptr -= sizeof (struct tr_mac_frm_nori);
   1751 	mh = (struct tr_mac_frm_nori *)nmp->b_rptr;
   1752 	mh->tr_ac = 0x10;
   1753 	mh->tr_fc = 0x40;
   1754 	mac_copy(gldp->glda_addr, mh->tr_dhost, macinfo->gldm_addrlen);
   1755 
   1756 	GLDM_LOCK(macinfo, RW_WRITER);
   1757 	mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
   1758 	    mh->tr_shost, macinfo->gldm_addrlen);
   1759 	GLDM_UNLOCK(macinfo);
   1760 
   1761 	if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_str_indicator_ste)
   1762 		mh->tr_shost[0] |= 0x80;
   1763 	else
   1764 		mh->tr_shost[0] &= ~0x80;
   1765 
   1766 	return (nmp);
   1767 }
   1768 
   1769 /*
   1770  * Route Determination Entity (ISO 8802-2 / IEEE 802.2 : 1994, Section 9)
   1771  *
   1772  * RDE is an LLC layer entity.  GLD is a MAC layer entity.  The proper
   1773  * solution to this architectural anomaly is to move RDE support out of GLD
   1774  * and into LLC where it belongs.  In particular, only LLC has the knowledge
   1775  * necessary to reply to XID and TEST packets.  If and when it comes time to
   1776  * move RDE out of GLD to LLC, the LLC-to-GLD interface should be modified
   1777  * to use MA_UNITDATA structures rather than DL_UNITDATA structures.  Of
   1778  * course, GLD will still have to continue to also support the DL_ structures
   1779  * as long as IP is not layered over LLC.  Another, perhaps better, idea
   1780  * would be to make RDE an autopush module on top of the token ring drivers:
   1781  * RDE would sit between LLC and GLD.  It would then also sit between IP and
   1782  * GLD, providing services to all clients of GLD/tokenring.  In that case,
   1783  * GLD would still have to continue to support the DL_ interface for non-
   1784  * Token Ring interfaces, using the MA_ interface only for media supporting
   1785  * Source Routing media.
   1786  *
   1787  * At present, Token Ring is the only source routing medium we support.
   1788  * Since Token Ring is not at this time a strategic network medium for Sun,
   1789  * rather than devote a large amount of resources to creating a proper
   1790  * architecture and implementation of RDE, we do the minimum necessary to
   1791  * get it to work.  The interface between the above token ring code and the
   1792  * below RDE code is designed to make it relatively easy to change to an
   1793  * MA_UNITDATA model later should this ever become a priority.
   1794  */
   1795 
   1796 static void gld_send_rqr(gld_mac_info_t *, uchar_t *, struct gld_ri *,
   1797     struct rde_pdu *, int);
   1798 static void gld_rde_pdu_req(gld_mac_info_t *, queue_t *, uchar_t *,
   1799     struct gld_ri *, uchar_t, uchar_t, uchar_t);
   1800 static void gld_get_route(gld_mac_info_t *, queue_t *, uchar_t *,
   1801     struct gld_ri **, uchar_t, uchar_t);
   1802 static void gld_reset_route(gld_mac_info_t *, queue_t *,
   1803     uchar_t *, uchar_t, uchar_t);
   1804 static void gld_rde_pdu_ind(gld_mac_info_t *, struct gld_ri *, struct rde_pdu *,
   1805     int);
   1806 static void gld_rif_ind(gld_mac_info_t *, struct gld_ri *, uchar_t *,
   1807     uchar_t, uchar_t);
   1808 static struct srtab **gld_sr_hash(struct srtab **, uchar_t *, int);
   1809 static struct srtab *gld_sr_lookup_entry(gld_mac_info_t *, uchar_t *);
   1810 static struct srtab *gld_sr_create_entry(gld_mac_info_t *, uchar_t *);
   1811 
   1812 /*
   1813  * This routine implements a modified subset of the 802.2 RDE RCC receive
   1814  * actions:
   1815  *   we implement RCC receive events 3 to 12 (ISO 8802-2:1994 9.6.3.4);
   1816  *   we omit special handling for the NULL SAP;
   1817  *   we omit XID/TEST handling;
   1818  *   we pass all packets (including RDE) upstream to LLC.
   1819  */
   1820 static void
   1821 gld_rcc_receive(gld_mac_info_t *macinfo, pktinfo_t *pktinfo, struct gld_ri *rh,
   1822     uchar_t *llcpkt, int llcpktlen)
   1823 {
   1824 	struct llc_snap_hdr *snaphdr = (struct llc_snap_hdr *)(llcpkt);
   1825 
   1826 	if (!((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_enabled)
   1827 		return;
   1828 
   1829 	/*
   1830 	 * First, ensure this packet wasn't something we received just
   1831 	 * because we were in promiscuous mode.  Since none of the below
   1832 	 * code wants to see group addressed packets anyway, we can do
   1833 	 * this check up front.  Since we're doing that, we can omit the
   1834 	 * checks for group addressed packets below.
   1835 	 */
   1836 	if (!pktinfo->isForMe)
   1837 		return;		/* Event 6 */
   1838 
   1839 	/* Process a subset of Route Determination Entity (RDE) packets */
   1840 	if (snaphdr->d_lsap == LSAP_RDE) {
   1841 		struct rde_pdu *pdu = (struct rde_pdu *)(llcpkt + LLC_HDR1_LEN);
   1842 		int pdulen = llcpktlen - LLC_HDR1_LEN;
   1843 
   1844 		/* sanity check the PDU */
   1845 		if ((pdulen < sizeof (struct rde_pdu)) ||
   1846 		    (snaphdr->s_lsap != LSAP_RDE))
   1847 			return;
   1848 
   1849 		/* we only handle route discovery PDUs, not XID/TEST/other */
   1850 		if (snaphdr->control != CNTL_LLC_UI)
   1851 			return;
   1852 
   1853 		switch (pdu->rde_ptype) {
   1854 		case RDE_RQC:	/* Route Query Command; Events 8 - 11 */
   1855 			gld_send_rqr(macinfo, pktinfo->shost, rh, pdu, pdulen);
   1856 			/* FALLTHROUGH */
   1857 		case RDE_RQR:	/* Route Query Response; Event 12 */
   1858 		case RDE_RS:	/* Route Selected; Event 7 */
   1859 			gld_rde_pdu_ind(macinfo, rh, pdu, pdulen);
   1860 			break;
   1861 		default:	/* ignore if unrecognized ptype */
   1862 			return;
   1863 		}
   1864 
   1865 		return;
   1866 	}
   1867 
   1868 	/* Consider routes seen in other IA SRF packets */
   1869 
   1870 	if (rh == NULL)
   1871 		return;		/* no RIF; Event 3 */
   1872 
   1873 	if ((rh->rt & 0x04) != 0)
   1874 		return;		/* not SRF; Event 5 */
   1875 
   1876 	gld_rif_ind(macinfo, rh, pktinfo->shost, snaphdr->s_lsap,
   1877 	    snaphdr->d_lsap);	/* Event 4 */
   1878 }
   1879 
   1880 /*
   1881  * Send RQR: 802.2 9.6.3.4.2(9) RCC Receive Events 8-11
   1882  *
   1883  * The routing processing really doesn't belong here; it should be handled in
   1884  * the LLC layer above.  If that were the case then RDE could just send down
   1885  * an extra MA_UNITDATA_REQ with the info needed to construct the packet.  But
   1886  * at the time we get control here, it's not a particularly good time to be
   1887  * constructing packets and trying to send them.  Specifically, at this layer
   1888  * we need to construct the full media packet, which means the below routine
   1889  * knows that it is dealing with Token Ring media.  If this were instead done
   1890  * via a proper MA_UNITDATA interface, the RDE stuff could all be completely
   1891  * media independent.  But since TR is the only source routing medium we
   1892  * support, this works even though it is not clean.
   1893  *
   1894  * We "know" that the only time we can get here is from the "interpret"
   1895  * routine, and only when it was called at receive time.
   1896  */
   1897 static void
   1898 gld_send_rqr(gld_mac_info_t *macinfo, uchar_t *shost, struct gld_ri *rh,
   1899     struct rde_pdu *pdu, int pdulen)
   1900 {
   1901 	mblk_t *nmp;
   1902 	int nlen;
   1903 	struct tr_mac_frm_nori *nmh;
   1904 	struct gld_ri *nrh;
   1905 	struct llc_snap_hdr *nsnaphdr;
   1906 	struct rde_pdu *npdu;
   1907 
   1908 	/* We know and assume we're on the receive path */
   1909 	ASSERT(GLDM_LOCK_HELD(macinfo));
   1910 
   1911 	if (pdulen < sizeof (struct rde_pdu))
   1912 		return;		/* Bad incoming PDU */
   1913 
   1914 	nlen = sizeof (struct tr_mac_frm) + LLC_HDR1_LEN +
   1915 	    sizeof (struct rde_pdu);
   1916 
   1917 	if ((nmp = allocb(nlen, BPRI_MED)) == NULL)
   1918 		return;
   1919 
   1920 	nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
   1921 
   1922 	nmp->b_rptr -= sizeof (struct rde_pdu);
   1923 	npdu = (struct rde_pdu *)(nmp->b_rptr);
   1924 	*npdu = *pdu;	/* copy orig/target macaddr/saps */
   1925 	npdu->rde_ver = 1;
   1926 	npdu->rde_ptype = RDE_RQR;
   1927 	mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
   1928 	    npdu->rde_target_mac, macinfo->gldm_addrlen);
   1929 
   1930 	nmp->b_rptr -= LLC_HDR1_LEN;
   1931 	nsnaphdr = (struct llc_snap_hdr *)(nmp->b_rptr);
   1932 	nsnaphdr->s_lsap = nsnaphdr->d_lsap = LSAP_RDE;
   1933 	nsnaphdr->control = CNTL_LLC_UI;
   1934 
   1935 	if (rh == NULL || (rh->rt & 0x06) == 0x06 ||
   1936 	    rh->len > sizeof (struct gld_ri)) {
   1937 		/* no RIF (Event 8), or RIF type STE (Event 9): send ARE RQR */
   1938 		nmp->b_rptr -= 2;
   1939 		nrh = (struct gld_ri *)(nmp->b_rptr);
   1940 		nrh->len = 2;
   1941 		nrh->rt = RT_ARE;
   1942 		nrh->dir = 0;
   1943 		nrh->res = 0;
   1944 		nrh->mtu = RT_MTU_MAX;
   1945 	} else {
   1946 		/*
   1947 		 * RIF must be ARE (Event 10) or SRF (Event 11):
   1948 		 * send SRF (reverse) RQR
   1949 		 */
   1950 		ASSERT(rh->len <= sizeof (struct gld_ri));
   1951 		nmp->b_rptr -= rh->len;
   1952 		nrh = (struct gld_ri *)(nmp->b_rptr);
   1953 		bcopy(rh, nrh, rh->len);	/* copy incoming RIF */
   1954 		nrh->rt = RT_SRF;		/* make it SRF */
   1955 		nrh->dir ^= 1;			/* reverse direction */
   1956 	}
   1957 
   1958 	nmp->b_rptr -= sizeof (struct tr_mac_frm_nori);
   1959 	nmh = (struct tr_mac_frm_nori *)(nmp->b_rptr);
   1960 	nmh->tr_ac = 0x10;
   1961 	nmh->tr_fc = 0x40;
   1962 	mac_copy(shost, nmh->tr_dhost, macinfo->gldm_addrlen);
   1963 	mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
   1964 	    nmh->tr_shost, macinfo->gldm_addrlen);
   1965 	nmh->tr_shost[0] |= 0x80;		/* indicate RIF present */
   1966 
   1967 	/*
   1968 	 * Packet assembled; send it.
   1969 	 *
   1970 	 * As noted before, this is not really a good time to be trying to
   1971 	 * send out packets.  We have no obvious queue to use if the packet
   1972 	 * can't be sent right away.  We pick one arbitrarily.
   1973 	 */
   1974 	{
   1975 	gld_vlan_t *vlan;
   1976 	queue_t *q;
   1977 
   1978 	if ((vlan = gld_find_vlan(macinfo, VLAN_VID_NONE)) == NULL) {
   1979 		/* oops, no vlan on the list for this macinfo! */
   1980 		/* this should not happen */
   1981 		freeb(nmp);
   1982 		return;
   1983 	}
   1984 	q = vlan->gldv_str_next->gld_qptr;
   1985 
   1986 	/*
   1987 	 * Queue the packet and let gld_wsrv
   1988 	 * handle it, thus preventing a panic
   1989 	 * caused by v2 TR in promiscuous mode
   1990 	 * where it attempts to get the mutex
   1991 	 * in this thread while already holding
   1992 	 * it.
   1993 	 */
   1994 	(void) putbq(WR(q), nmp);
   1995 	qenable(WR(q));
   1996 	}
   1997 }
   1998 
   1999 /*
   2000  * This routine implements a modified subset of the 802.2 RDE RCC send actions:
   2001  *   we implement RCC send events 5 to 10 (ISO 8802-2:1994 9.6.3.5);
   2002  *   we omit special handling for the NULL SAP;
   2003  *   events 11 to 12 are handled by gld_rde_pdu_req below;
   2004  *   we require an immediate response to our GET_ROUTE_REQUEST.
   2005  */
   2006 static void
   2007 gld_rcc_send(gld_mac_info_t *macinfo, queue_t *q, uchar_t *dhost,
   2008     struct gld_ri **rhp, uchar_t *llcpkt)
   2009 {
   2010 	struct llc_snap_hdr *snaphdr = (struct llc_snap_hdr *)(llcpkt);
   2011 
   2012 	/*
   2013 	 * Our caller has to take the mutex because: to avoid an extra bcopy
   2014 	 * of the RIF on every transmit, we pass back a pointer to our sr
   2015 	 * table entry via rhp.  He has to keep the mutex until he has a
   2016 	 * chance to copy the RIF out into the outgoing packet, so that we
   2017 	 * don't modify the entry while he's trying to copy it.  This is a
   2018 	 * little ugly, but saves the extra bcopy.
   2019 	 */
   2020 	ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo)));
   2021 
   2022 	*rhp = (struct gld_ri *)NULL;	/* start off clean (no RIF) */
   2023 
   2024 	if (!((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_enabled) {
   2025 		/* RDE is disabled -- use NULL or STE always */
   2026 		if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->
   2027 		    rde_str_indicator_ste)
   2028 			*rhp = &ri_ste_def;	/* STE option */
   2029 		return;
   2030 	}
   2031 
   2032 	if (!(dhost[0] & 0x80)) {
   2033 		/* individual address; Events 7 - 10 */
   2034 		if ((snaphdr->control & 0xef) == 0xe3) {
   2035 			/* TEST command, reset the route */
   2036 			gld_reset_route(macinfo, q,
   2037 			    dhost, snaphdr->d_lsap, snaphdr->s_lsap);
   2038 		}
   2039 		gld_get_route(macinfo, q,
   2040 		    dhost, rhp, snaphdr->d_lsap, snaphdr->s_lsap);
   2041 	}
   2042 
   2043 	if (*rhp == NULL) {
   2044 		/*
   2045 		 * group address (Events 5 - 6),
   2046 		 * or no route available (Events 8 - 9):
   2047 		 * Need to send NSR or STE, as configured.
   2048 		 */
   2049 		if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->
   2050 		    rde_str_indicator_ste)
   2051 			*rhp = &ri_ste_def;	/* STE option */
   2052 	}
   2053 }
   2054 
   2055 /*
   2056  * RCC send events 11 - 12
   2057  *
   2058  * At present we only handle the RQC ptype.
   2059  *
   2060  * We "know" that the only time we can get here is from the "unitdata"
   2061  * routine, called at wsrv time.
   2062  *
   2063  * If we ever implement the RS ptype (Event 13), this may no longer be true!
   2064  */
   2065 static void
   2066 gld_rde_pdu_req(gld_mac_info_t *macinfo, queue_t *q, uchar_t *dhost,
   2067     struct gld_ri *rh, uchar_t dsap, uchar_t ssap, uchar_t ptype)
   2068 {
   2069 	mblk_t *nmp;
   2070 	int nlen;
   2071 	struct tr_mac_frm_nori *nmh;
   2072 	struct gld_ri *nrh;
   2073 	struct llc_snap_hdr *nsnaphdr;
   2074 	struct rde_pdu *npdu;
   2075 	int srpresent = 0;
   2076 
   2077 	/* if you change this to process other types, review all code below */
   2078 	ASSERT(ptype == RDE_RQC);
   2079 	ASSERT(rh == NULL);	/* RQC never uses SRF */
   2080 
   2081 	nlen = sizeof (struct tr_mac_frm) + LLC_HDR1_LEN +
   2082 	    sizeof (struct rde_pdu);
   2083 
   2084 	if ((nmp = allocb(nlen, BPRI_MED)) == NULL)
   2085 		return;
   2086 
   2087 	nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
   2088 
   2089 	nmp->b_rptr -= sizeof (struct rde_pdu);
   2090 	npdu = (struct rde_pdu *)(nmp->b_rptr);
   2091 	npdu->rde_ver = 1;
   2092 	npdu->rde_ptype = ptype;
   2093 	mac_copy(dhost, &npdu->rde_target_mac, 6);
   2094 
   2095 	/*
   2096 	 * access the mac address without a mutex - take a risk -
   2097 	 * to prevent mutex contention (BUG 4211361)
   2098 	 */
   2099 	mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
   2100 	    &npdu->rde_orig_mac, 6);
   2101 	npdu->rde_target_sap = dsap;
   2102 	npdu->rde_orig_sap = ssap;
   2103 
   2104 	nmp->b_rptr -= LLC_HDR1_LEN;
   2105 	nsnaphdr = (struct llc_snap_hdr *)(nmp->b_rptr);
   2106 	nsnaphdr->s_lsap = nsnaphdr->d_lsap = LSAP_RDE;
   2107 	nsnaphdr->control = CNTL_LLC_UI;
   2108 
   2109 #if 0	/* we don't need this for now */
   2110 	if (rh != NULL) {
   2111 		/* send an SRF frame with specified RIF */
   2112 		ASSERT(rh->len <= sizeof (struct gld_ri));
   2113 		nmp->b_rptr -= rh->len;
   2114 		nrh = (struct gld_ri *)(nmp->b_rptr);
   2115 		bcopy(rh, nrh, rh->len);
   2116 		ASSERT(nrh->rt == RT_SRF);
   2117 		srpresent = 1;
   2118 	} else
   2119 #endif
   2120 
   2121 	/* Need to send NSR or STE, as configured.  */
   2122 	if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_str_indicator_ste) {
   2123 		/* send an STE frame */
   2124 		nmp->b_rptr -= 2;
   2125 		nrh = (struct gld_ri *)(nmp->b_rptr);
   2126 		nrh->len = 2;
   2127 		nrh->rt = RT_STE;
   2128 		nrh->dir = 0;
   2129 		nrh->res = 0;
   2130 		nrh->mtu = RT_MTU_MAX;
   2131 		srpresent = 1;
   2132 	} /* else send an NSR frame */
   2133 
   2134 	nmp->b_rptr -= sizeof (struct tr_mac_frm_nori);
   2135 	nmh = (struct tr_mac_frm_nori *)(nmp->b_rptr);
   2136 	nmh->tr_ac = 0x10;
   2137 	nmh->tr_fc = 0x40;
   2138 	mac_copy(dhost, nmh->tr_dhost, macinfo->gldm_addrlen);
   2139 	/*
   2140 	 * access the mac address without a mutex - take a risk -
   2141 	 * to prevent mutex contention  - BUG 4211361
   2142 	 */
   2143 	mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
   2144 	    nmh->tr_shost, macinfo->gldm_addrlen);
   2145 
   2146 	if (srpresent)
   2147 		nmh->tr_shost[0] |= 0x80;
   2148 	else
   2149 		nmh->tr_shost[0] &= ~0x80;
   2150 
   2151 	/*
   2152 	 * Packet assembled; send it.
   2153 	 *
   2154 	 * Since we own the SR_MUTEX, we don't want to take the maclock
   2155 	 * mutex (since they are acquired in the opposite order on the
   2156 	 * receive path, so deadlock could occur).  We could rearrange
   2157 	 * the code in gld_get_route() and drop the SR_MUTEX around the
   2158 	 * call to gld_rde_pdu_req(), but that's kind of ugly.  Rather,
   2159 	 * we just refrain from calling gld_start() from here, and
   2160 	 * instead just queue the packet for wsrv to send next.  Besides,
   2161 	 * it's more important to get the packet we're working on out
   2162 	 * quickly than this RQC.
   2163 	 */
   2164 	(void) putbq(WR(q), nmp);
   2165 	qenable(WR(q));
   2166 }
   2167 
   2168 /*
   2169  * Route Determination Component (RDC)
   2170  *
   2171  * We do not implement separate routes for each SAP, as specified by
   2172  * ISO 8802-2; instead we implement only one route per remote mac address.
   2173  */
   2174 static void
   2175 gld_get_route(gld_mac_info_t *macinfo, queue_t *q, uchar_t *dhost,
   2176     struct gld_ri **rhp, uchar_t dsap, uchar_t ssap)
   2177 {
   2178 	struct srtab *sr;
   2179 	clock_t t = ddi_get_lbolt();
   2180 
   2181 	ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo)));
   2182 
   2183 	sr = gld_sr_lookup_entry(macinfo, dhost);
   2184 
   2185 	if (sr == NULL) {
   2186 		/*
   2187 		 * we have no entry -- never heard of this address:
   2188 		 * create an empty entry and initiate RQC
   2189 		 */
   2190 		sr = gld_sr_create_entry(macinfo, dhost);
   2191 		gld_rde_pdu_req(macinfo, q, dhost, (struct gld_ri *)NULL,
   2192 		    dsap, ssap, RDE_RQC);
   2193 		if (sr)
   2194 			sr->sr_timer = t;
   2195 		*rhp = NULL;		/* we have no route yet */
   2196 		return;
   2197 	}
   2198 
   2199 	/* we have an entry; see if we know a route yet */
   2200 
   2201 	if (sr->sr_ri.len == 0) {
   2202 		/* Have asked RQC, but no reply (yet) */
   2203 		if (t - sr->sr_timer >
   2204 		    ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_timeout) {
   2205 			/* RQR overdue, resend RQC */
   2206 			gld_rde_pdu_req(macinfo, q, dhost,
   2207 			    (struct gld_ri *)NULL, dsap, ssap, RDE_RQC);
   2208 			sr->sr_timer = t;
   2209 		}
   2210 		*rhp = NULL;		/* we have no route yet */
   2211 		return;
   2212 	}
   2213 
   2214 	/* we know a route, or it's local */
   2215 
   2216 	/* if it might be stale, reset and get a new one */
   2217 	if (t - sr->sr_timer >
   2218 	    ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_timeout) {
   2219 		gld_rde_pdu_req(macinfo, q, dhost,
   2220 		    (struct gld_ri *)NULL, dsap, ssap, RDE_RQC);
   2221 		sr->sr_ri.len = 0;
   2222 		sr->sr_timer = t;
   2223 		*rhp = NULL;		/* we have no route */
   2224 		return;
   2225 	}
   2226 
   2227 	if (sr->sr_ri.len == 2) {
   2228 		/* the remote site is on our local ring -- no route needed */
   2229 		*rhp = NULL;
   2230 		return;
   2231 	}
   2232 
   2233 	*rhp = &sr->sr_ri;	/* we have a route, return it */
   2234 }
   2235 
   2236 /*
   2237  * zap the specified entry and reinitiate RQC
   2238  */
   2239 static void
   2240 gld_reset_route(gld_mac_info_t *macinfo, queue_t *q,
   2241     uchar_t *dhost, uchar_t dsap, uchar_t ssap)
   2242 {
   2243 	struct srtab *sr;
   2244 
   2245 	ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo)));
   2246 
   2247 	sr = gld_sr_create_entry(macinfo, dhost);
   2248 	gld_rde_pdu_req(macinfo, q, dhost, (struct gld_ri *)NULL,
   2249 	    dsap, ssap, RDE_RQC);
   2250 	if (sr == NULL)
   2251 		return;
   2252 
   2253 	sr->sr_ri.len = 0;
   2254 	sr->sr_timer = ddi_get_lbolt();
   2255 }
   2256 
   2257 /*
   2258  * This routine is called when an RDE PDU is received from our peer.
   2259  * If it is an RS (Route Selected) PDU, we adopt the specified route.
   2260  * If it is an RQR (reply to our previous RQC), we evaluate the
   2261  * specified route in comparison with our current known route, if any,
   2262  * and we keep the "better" of the two routes.
   2263  */
   2264 static void
   2265 gld_rde_pdu_ind(gld_mac_info_t *macinfo, struct gld_ri *rh, struct rde_pdu *pdu,
   2266     int pdulen)
   2267 {
   2268 	struct srtab *sr;
   2269 	uchar_t *otherhost;
   2270 
   2271 	if (pdulen < sizeof (struct rde_pdu))
   2272 		return;		/* Bad incoming PDU */
   2273 
   2274 	if (pdu->rde_ptype == RDE_RQC)
   2275 		return;			/* ignore RQC */
   2276 
   2277 	if (pdu->rde_ptype != RDE_RQR && pdu->rde_ptype != RDE_RS) {
   2278 #ifdef GLD_DEBUG
   2279 		if (gld_debug & GLDERRS)
   2280 			cmn_err(CE_WARN, "gld: bogus RDE ptype 0x%x received",
   2281 			    pdu->rde_ptype);
   2282 #endif
   2283 		return;
   2284 	}
   2285 
   2286 	if (rh == NULL) {
   2287 #ifdef GLD_DEBUG
   2288 		if (gld_debug & GLDERRS)
   2289 			cmn_err(CE_WARN,
   2290 			    "gld: bogus NULL RIF, ptype 0x%x received",
   2291 			    pdu->rde_ptype);
   2292 #endif
   2293 		return;
   2294 	}
   2295 
   2296 	ASSERT(rh->len >= 2);
   2297 	ASSERT(rh->len <= sizeof (struct gld_ri));
   2298 	ASSERT((rh->len & 1) == 0);
   2299 
   2300 	if (pdu->rde_ptype == RDE_RQR) {
   2301 		/* A reply to our RQC has his address as target mac */
   2302 		otherhost = pdu->rde_target_mac;
   2303 	} else {
   2304 		ASSERT(pdu->rde_ptype == RDE_RS);
   2305 		/* An RS has his address as orig mac */
   2306 		otherhost = pdu->rde_orig_mac;
   2307 	}
   2308 
   2309 	mutex_enter(GLD_SR_MUTEX(macinfo));
   2310 
   2311 	if ((sr = gld_sr_create_entry(macinfo, otherhost)) == NULL) {
   2312 		mutex_exit(GLD_SR_MUTEX(macinfo));
   2313 		return;		/* oh well, out of memory */
   2314 	}
   2315 
   2316 	if (pdu->rde_ptype == RDE_RQR) {
   2317 		/* see if new route is better than what we may already have */
   2318 		if (sr->sr_ri.len != 0 &&
   2319 		    sr->sr_ri.len <= rh->len) {
   2320 			mutex_exit(GLD_SR_MUTEX(macinfo));
   2321 			return;	/* we have one, and new one is no shorter */
   2322 		}
   2323 	}
   2324 
   2325 	/* adopt the new route */
   2326 	bcopy((caddr_t)rh, (caddr_t)&sr->sr_ri, rh->len); /* copy incom RIF */
   2327 	sr->sr_ri.rt = RT_SRF;	/* make it a clean SRF */
   2328 	sr->sr_ri.dir ^= 1;	/* reverse direction */
   2329 	sr->sr_timer = ddi_get_lbolt();
   2330 
   2331 	mutex_exit(GLD_SR_MUTEX(macinfo));
   2332 }
   2333 
   2334 /*
   2335  * This routine is called when a packet with a RIF is received.  Our
   2336  * policy is to adopt the route.
   2337  */
   2338 /* ARGSUSED3 */
   2339 static void
   2340 gld_rif_ind(gld_mac_info_t *macinfo, struct gld_ri *rh, uchar_t *shost,
   2341     uchar_t ssap, uchar_t dsap)
   2342 {
   2343 	struct srtab *sr;
   2344 
   2345 	ASSERT(rh != NULL);		/* ensure RIF */
   2346 	ASSERT((rh->rt & 0x04) == 0);	/* ensure SRF */
   2347 	ASSERT(rh->len >= 2);
   2348 	ASSERT(rh->len <= sizeof (struct gld_ri));
   2349 	ASSERT((rh->len & 1) == 0);
   2350 
   2351 	mutex_enter(GLD_SR_MUTEX(macinfo));
   2352 
   2353 	if ((sr = gld_sr_create_entry(macinfo, shost)) == NULL) {
   2354 		mutex_exit(GLD_SR_MUTEX(macinfo));
   2355 		return;		/* oh well, out of memory */
   2356 	}
   2357 
   2358 	/* we have an entry; fill it in */
   2359 	bcopy((caddr_t)rh, (caddr_t)&sr->sr_ri, rh->len); /* copy incom RIF */
   2360 	sr->sr_ri.rt = RT_SRF;	/* make it a clean SRF */
   2361 	sr->sr_ri.dir ^= 1;	/* reverse direction */
   2362 	sr->sr_timer = ddi_get_lbolt();
   2363 
   2364 	mutex_exit(GLD_SR_MUTEX(macinfo));
   2365 }
   2366 
   2367 static struct srtab **
   2368 gld_sr_hash(struct srtab **sr_hash_tbl, uchar_t *addr, int addr_length)
   2369 {
   2370 	uint_t hashval = 0;
   2371 
   2372 	while (--addr_length >= 0)
   2373 		hashval ^= *addr++;
   2374 
   2375 	return (&sr_hash_tbl[hashval % SR_HASH_SIZE]);
   2376 }
   2377 
   2378 static struct srtab *
   2379 gld_sr_lookup_entry(gld_mac_info_t *macinfo, uchar_t *macaddr)
   2380 {
   2381 	struct srtab *sr;
   2382 
   2383 	ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo)));
   2384 
   2385 	for (sr = *gld_sr_hash(GLD_SR_HASH(macinfo), macaddr,
   2386 	    macinfo->gldm_addrlen); sr; sr = sr->sr_next)
   2387 		if (mac_eq(macaddr, sr->sr_mac, macinfo->gldm_addrlen))
   2388 			return (sr);
   2389 
   2390 	return ((struct srtab *)0);
   2391 }
   2392 
   2393 static struct srtab *
   2394 gld_sr_create_entry(gld_mac_info_t *macinfo, uchar_t *macaddr)
   2395 {
   2396 	struct srtab *sr;
   2397 	struct srtab **srp;
   2398 
   2399 	ASSERT(!(macaddr[0] & 0x80));	/* no group addresses here */
   2400 	ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo)));
   2401 
   2402 	srp = gld_sr_hash(GLD_SR_HASH(macinfo), macaddr, macinfo->gldm_addrlen);
   2403 
   2404 	for (sr = *srp; sr; sr = sr->sr_next)
   2405 		if (mac_eq(macaddr, sr->sr_mac, macinfo->gldm_addrlen))
   2406 			return (sr);
   2407 
   2408 	if (!(sr = kmem_zalloc(sizeof (struct srtab), KM_NOSLEEP))) {
   2409 #ifdef GLD_DEBUG
   2410 		if (gld_debug & GLDERRS)
   2411 			cmn_err(CE_WARN,
   2412 			    "gld: gld_sr_create_entry kmem_alloc failed");
   2413 #endif
   2414 		return ((struct srtab *)0);
   2415 	}
   2416 
   2417 	bcopy((caddr_t)macaddr, (caddr_t)sr->sr_mac, macinfo->gldm_addrlen);
   2418 
   2419 	sr->sr_next = *srp;
   2420 	*srp = sr;
   2421 	return (sr);
   2422 }
   2423 
   2424 static void
   2425 gld_sr_clear(gld_mac_info_t *macinfo)
   2426 {
   2427 	int i;
   2428 	struct srtab **sr_hash_tbl = GLD_SR_HASH(macinfo);
   2429 	struct srtab **srp, *sr;
   2430 
   2431 	/*
   2432 	 * Walk through the table, deleting all entries.
   2433 	 *
   2434 	 * Only called from uninit, so don't need the mutex.
   2435 	 */
   2436 	for (i = 0; i < SR_HASH_SIZE; i++) {
   2437 		for (srp = &sr_hash_tbl[i]; (sr = *srp) != NULL; ) {
   2438 			*srp = sr->sr_next;
   2439 			kmem_free((char *)sr, sizeof (struct srtab));
   2440 		}
   2441 	}
   2442 }
   2443 
   2444 #ifdef	DEBUG
   2445 void
   2446 gld_sr_dump(gld_mac_info_t *macinfo)
   2447 {
   2448 	int i, j;
   2449 	struct srtab **sr_hash_tbl;
   2450 	struct srtab *sr;
   2451 
   2452 	sr_hash_tbl = GLD_SR_HASH(macinfo);
   2453 	if (sr_hash_tbl == NULL)
   2454 		return;
   2455 
   2456 	mutex_enter(GLD_SR_MUTEX(macinfo));
   2457 
   2458 	/*
   2459 	 * Walk through the table, printing all entries
   2460 	 */
   2461 	cmn_err(CE_NOTE, "GLD Source Routing Table (0x%p):", (void *)macinfo);
   2462 	cmn_err(CE_CONT, "Addr len,rt,dir,mtu,res rng,brg0 rng,brg1...\n");
   2463 	for (i = 0; i < SR_HASH_SIZE; i++) {
   2464 		for (sr = sr_hash_tbl[i]; sr; sr = sr->sr_next) {
   2465 			cmn_err(CE_CONT,
   2466 			    "%x:%x:%x:%x:%x:%x %d,%x,%x,%x,%x ",
   2467 			    sr->sr_mac[0], sr->sr_mac[1], sr->sr_mac[2],
   2468 			    sr->sr_mac[3], sr->sr_mac[4], sr->sr_mac[5],
   2469 			    sr->sr_ri.len, sr->sr_ri.rt, sr->sr_ri.dir,
   2470 			    sr->sr_ri.mtu, sr->sr_ri.res);
   2471 			if (sr->sr_ri.len)
   2472 				for (j = 0; j < (sr->sr_ri.len - 2) / 2; j++)
   2473 					cmn_err(CE_CONT, "%x ",
   2474 					    REF_NET_USHORT(*(unsigned short *)
   2475 					    &sr->sr_ri.rd[j]));
   2476 			cmn_err(CE_CONT, "\n");
   2477 		}
   2478 	}
   2479 
   2480 	mutex_exit(GLD_SR_MUTEX(macinfo));
   2481 }
   2482 #endif
   2483