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