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