xref: /illumos-gate/usr/src/uts/common/io/gldutil.c (revision f967d548b23673f68e7356c6c741329b7698269c)
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