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