bmake-ify mega_sas
[unleashed.git] / usr / src / uts / common / io / gldutil.c
blob7193c6ffa2985dc4386fdfc995d9e11d14b9a154
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
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.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * gld - Generic LAN Driver
30 * media dependent routines
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>
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>
56 #define DLSAPLENGTH(macinfo) \
57 ((macinfo)->gldm_addrlen + ABS((macinfo)->gldm_saplen))
59 #ifdef GLD_DEBUG
60 extern int gld_debug;
61 #endif
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;
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 */
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)
84 /* ======== */
85 /* Ethernet */
86 /* ======== */
88 static mac_addr_t ether_broadcast = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
90 void
91 gld_init_ether(gld_mac_info_t *macinfo)
93 struct gldkstats *sp =
94 ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->kstatp->ks_data;
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 ASSERT(sizeof (struct ether_header) == 14);
101 ASSERT(sizeof (mac_addr_t) == 6);
103 kstat_named_init(&sp->glds_frame, "align_errors", KSTAT_DATA_ULONG);
104 kstat_named_init(&sp->glds_crc, "fcs_errors", KSTAT_DATA_ULONG);
105 kstat_named_init(&sp->glds_collisions, "collisions", KSTAT_DATA_ULONG);
106 kstat_named_init(&sp->glds_nocarrier, "carrier_errors",
107 KSTAT_DATA_ULONG);
108 kstat_named_init(&sp->glds_defer, "defer_xmts", KSTAT_DATA_ULONG);
109 kstat_named_init(&sp->glds_xmtlatecoll, "tx_late_collisions",
110 KSTAT_DATA_ULONG);
111 kstat_named_init(&sp->glds_short, "runt_errors", KSTAT_DATA_ULONG);
112 kstat_named_init(&sp->glds_excoll, "ex_collisions", KSTAT_DATA_ULONG);
115 * only initialize the new statistics if the driver
116 * knows about them.
118 if (macinfo->gldm_driver_version != GLD_VERSION_200)
119 return;
121 kstat_named_init(&sp->glds_dot3_first_coll,
122 "first_collisions", KSTAT_DATA_UINT32);
123 kstat_named_init(&sp->glds_dot3_multi_coll,
124 "multi_collisions", KSTAT_DATA_UINT32);
125 kstat_named_init(&sp->glds_dot3_sqe_error,
126 "sqe_errors", KSTAT_DATA_UINT32);
127 kstat_named_init(&sp->glds_dot3_mac_xmt_error,
128 "macxmt_errors", KSTAT_DATA_UINT32);
129 kstat_named_init(&sp->glds_dot3_mac_rcv_error,
130 "macrcv_errors", KSTAT_DATA_UINT32);
131 kstat_named_init(&sp->glds_dot3_frame_too_long,
132 "toolong_errors", KSTAT_DATA_UINT32);
133 kstat_named_init(&sp->glds_duplex, "duplex", KSTAT_DATA_CHAR);
136 /*ARGSUSED*/
137 void
138 gld_uninit_ether(gld_mac_info_t *macinfo)
143 gld_interpret_ether(gld_mac_info_t *macinfo, mblk_t *mp, pktinfo_t *pktinfo,
144 packet_flag_t flags)
146 struct ether_header *mh;
147 gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
148 struct llc_snap_hdr *snaphdr;
149 mblk_t *pmp = NULL, *savemp = mp;
150 unsigned short typelen;
151 int ret = 0;
154 * Quickly handle receive fastpath for IPQ hack.
156 if (flags == GLD_RXQUICK) {
157 pktinfo->pktLen = msgdsize(mp);
159 * Check whether the header is contiguous, which
160 * also implicitly makes sure the packet is big enough.
162 if (MBLKL(mp) < sizeof (struct ether_header))
163 return (-1);
164 mh = (struct ether_header *)mp->b_rptr;
165 pktinfo->ethertype = REF_NET_USHORT(mh->ether_type);
166 pktinfo->isForMe = mac_eq(&mh->ether_dhost,
167 mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
168 pktinfo->macLen = sizeof (struct ether_header);
170 return (0);
173 bzero((void *)pktinfo, sizeof (*pktinfo));
175 pktinfo->pktLen = msgdsize(mp);
177 /* make sure packet has at least a whole mac header */
178 if (pktinfo->pktLen < sizeof (struct ether_header))
179 return (-1);
181 /* make sure the mac header falls into contiguous memory */
182 if (MBLKL(mp) < sizeof (struct ether_header)) {
183 if ((pmp = msgpullup(mp, -1)) == NULL) {
184 #ifdef GLD_DEBUG
185 if (gld_debug & GLDERRS)
186 cmn_err(CE_WARN,
187 "GLD: interpret_ether cannot msgpullup");
188 #endif
189 return (-1);
191 mp = pmp; /* this mblk contains the whole mac header */
194 mh = (struct ether_header *)mp->b_rptr;
196 /* Check to see if the mac is a broadcast or multicast address. */
197 if (mac_eq(&mh->ether_dhost, ether_broadcast, macinfo->gldm_addrlen))
198 pktinfo->isBroadcast = 1;
199 else if (mh->ether_dhost.ether_addr_octet[0] & 1)
200 pktinfo->isMulticast = 1;
202 typelen = REF_NET_USHORT(mh->ether_type);
204 * If the hardware is capable of VLAN tag insertion
205 * strip out the VLAN tag info. Knowing hardware is
206 * capable of VLAN can be established by the presance
207 * of non null 'macinfo->gldm_send_tagged'.
209 if (flags == GLD_TX) {
210 if ((typelen == ETHERTYPE_VLAN) &&
211 (macinfo->gldm_send_tagged != NULL)) {
212 struct ether_vlan_header *evhp;
213 uint16_t tci;
215 if ((MBLKL(mp) < sizeof (struct ether_vlan_header)) &&
216 (pullupmsg(mp, sizeof (struct ether_vlan_header))
217 == 0)) {
218 ret = -1;
219 goto out;
221 evhp = (struct ether_vlan_header *)mp->b_rptr;
222 tci = REF_NET_USHORT(evhp->ether_tci);
225 * We don't allow the VID and priority are both zero.
227 if ((GLD_VTAG_PRI((int32_t)tci) == 0 &&
228 GLD_VTAG_VID((int32_t)tci) == VLAN_VID_NONE) ||
229 (GLD_VTAG_CFI((uint32_t)tci)) != VLAN_CFI_ETHER) {
230 ret = -1;
231 goto out;
235 * Remember the VTAG info in order to reinsert it,
236 * Then strip the tag. This is required because some
237 * drivers do not allow the size of message (passed
238 * by the gldm_send_tagged() function) to be greater
239 * than ETHERMAX.
241 GLD_SAVE_MBLK_VTAG(savemp, GLD_TCI2VTAG(tci));
242 ovbcopy(mp->b_rptr, mp->b_rptr + VTAG_SIZE,
243 2 * ETHERADDRL);
244 mp->b_rptr += VTAG_SIZE;
246 goto out; /* Got all info we need for xmit case */
249 ASSERT(GLDM_LOCK_HELD(macinfo));
252 * Deal with the mac header
255 mac_copy(&mh->ether_dhost, pktinfo->dhost, macinfo->gldm_addrlen);
256 mac_copy(&mh->ether_shost, pktinfo->shost, macinfo->gldm_addrlen);
258 pktinfo->isLooped = mac_eq(pktinfo->shost,
259 mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
260 pktinfo->isForMe = mac_eq(pktinfo->dhost,
261 mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
263 pktinfo->macLen = sizeof (struct ether_header);
265 if (typelen > ETHERMTU) {
266 pktinfo->ethertype = typelen; /* use type interpretation */
267 goto out;
271 * Packet is 802.3 so the ether type/length field
272 * specifies the number of bytes that should be present
273 * in the data field. Additional bytes are padding, and
274 * should be removed
277 int delta = pktinfo->pktLen -
278 (sizeof (struct ether_header) + typelen);
280 if (delta > 0 && adjmsg(mp, -delta))
281 pktinfo->pktLen -= delta;
285 * Before trying to look beyond the MAC header, make sure the LLC
286 * header exists, and that both it and any SNAP header are contiguous.
288 if (pktinfo->pktLen < pktinfo->macLen + LLC_HDR1_LEN)
289 goto out; /* LLC hdr should have been there! */
291 pktinfo->isLLC = 1;
293 if (gld_global_options & GLD_OPT_NO_ETHRXSNAP ||
294 pktinfo->pktLen < pktinfo->macLen + LLC_SNAP_HDR_LEN)
295 goto out;
297 if (MBLKL(mp) < sizeof (struct ether_header) + LLC_SNAP_HDR_LEN &&
298 MBLKL(mp) < pktinfo->pktLen) {
300 * we don't have the entire packet within the first mblk (and
301 * therefore we didn't do the msgpullup above), AND the first
302 * mblk may not contain all the data we need to look at.
304 ASSERT(pmp == NULL); /* couldn't have done msgpullup above */
305 if ((pmp = msgpullup(mp, -1)) == NULL) {
306 #ifdef GLD_DEBUG
307 if (gld_debug & GLDERRS)
308 cmn_err(CE_WARN,
309 "GLD: interpret_ether cannot msgpullup2");
310 #endif
311 goto out; /* can't interpret this pkt further */
313 mp = pmp; /* this mblk should contain everything needed */
317 * Check SAP/SNAP information for EtherType.
320 snaphdr = (struct llc_snap_hdr *)(mp->b_rptr + pktinfo->macLen);
321 if (ISETHERTYPE(snaphdr)) {
322 pktinfo->ethertype = REF_NET_USHORT(snaphdr->type);
323 pktinfo->hdrLen = LLC_SNAP_HDR_LEN;
325 out:
326 if (pmp != NULL)
327 freemsg(pmp);
329 return (ret);
332 mblk_t *
333 gld_unitdata_ether(gld_t *gld, mblk_t *mp)
335 gld_mac_info_t *macinfo = gld->gld_mac_info;
336 dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_rptr;
337 struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
338 mac_addr_t dhost;
339 unsigned short typelen;
340 mblk_t *nmp;
341 struct ether_header *mh;
342 int hdrlen;
343 uint32_t vptag;
344 gld_vlan_t *gld_vlan;
346 ASSERT(macinfo);
348 /* extract needed info from the mblk before we maybe reuse it */
349 mac_copy(gldp->glda_addr, dhost, macinfo->gldm_addrlen);
351 /* look in the unitdata request for a sap, else use bound one */
352 if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
353 REF_HOST_USHORT(gldp->glda_sap) != 0)
354 typelen = REF_HOST_USHORT(gldp->glda_sap);
355 else
356 typelen = gld->gld_sap;
359 * We take values less than or equal to ETHERMTU to mean that the
360 * packet should not have an encoded EtherType and so we use the
361 * IEEE 802.3 length interpretation of the type/length field.
363 if (typelen <= ETHERMTU)
364 typelen = msgdsize(mp);
366 hdrlen = sizeof (struct ether_header);
369 * Check to see if VLAN is enabled on this stream
370 * if so then make the header bigger to hold a clone
371 * vlan tag.
373 gld_vlan = (gld_vlan_t *)gld->gld_vlan;
374 if (gld_vlan && (gld_vlan->gldv_id != VLAN_VID_NONE)) {
375 hdrlen += VTAG_SIZE;
376 vptag = gld_vlan->gldv_ptag;
379 /* need a buffer big enough for the headers */
380 nmp = mp->b_cont; /* where the packet payload M_DATA is */
381 if (DB_REF(nmp) == 1 && MBLKHEAD(nmp) >= hdrlen) {
382 /* it fits at the beginning of the first M_DATA block */
383 freeb(mp); /* don't need the M_PROTO anymore */
384 } else if (DB_REF(mp) == 1 && MBLKSIZE(mp) >= hdrlen) {
385 /* we can reuse the dl_unitdata_req M_PROTO mblk */
386 nmp = mp;
387 DB_TYPE(nmp) = M_DATA;
388 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
389 } else {
390 /* we need to allocate one */
391 if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
392 return (NULL);
393 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
394 linkb(nmp, mp->b_cont);
395 freeb(mp);
398 /* Got the space, now copy in the header components */
400 nmp->b_rptr -= sizeof (typelen);
401 SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, typelen);
402 if (hdrlen > sizeof (struct ether_header)) {
403 nmp->b_rptr -= sizeof (uint16_t);
404 SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, vptag);
405 vptag >>= 16;
406 nmp->b_rptr -= sizeof (uint16_t);
407 SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, vptag);
409 nmp->b_rptr -= (ETHERADDRL * 2);
410 mh = (struct ether_header *)nmp->b_rptr;
411 mac_copy(dhost, &mh->ether_dhost, macinfo->gldm_addrlen);
414 * We access the mac address without the mutex to prevent
415 * mutex contention (BUG 4211361)
417 mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
418 &mh->ether_shost, macinfo->gldm_addrlen);
420 return (nmp);
424 * Insert the VLAN tag into the packet. The packet now is an Ethernet header
425 * without VLAN tag information.
427 mblk_t *
428 gld_insert_vtag_ether(mblk_t *mp, uint32_t vtag)
430 struct ether_vlan_header *evhp;
431 struct ether_header *ehp;
432 mblk_t *nmp;
434 if (vtag == VLAN_VID_NONE)
435 return (mp);
437 if (DB_REF(mp) == 1 && MBLKHEAD(mp) >= VTAG_SIZE) {
438 /* it fits at the beginning of the message block */
439 nmp = mp;
440 ovbcopy(nmp->b_rptr, nmp->b_rptr - VTAG_SIZE, 2 * ETHERADDRL);
441 nmp->b_rptr -= VTAG_SIZE;
442 evhp = (struct ether_vlan_header *)nmp->b_rptr;
443 } else {
444 /* we need to allocate one */
445 if ((nmp = allocb(sizeof (struct ether_vlan_header),
446 BPRI_MED)) == NULL) {
447 return (NULL);
449 nmp->b_wptr += sizeof (struct ether_vlan_header);
451 /* transfer the ether_header fields */
452 evhp = (struct ether_vlan_header *)nmp->b_rptr;
453 ehp = (struct ether_header *)mp->b_rptr;
454 mac_copy(&ehp->ether_dhost, &evhp->ether_dhost, ETHERADDRL);
455 mac_copy(&ehp->ether_shost, &evhp->ether_shost, ETHERADDRL);
456 bcopy(&ehp->ether_type, &evhp->ether_type, sizeof (uint16_t));
458 /* offset the mp of the MAC header length. */
459 mp->b_rptr += sizeof (struct ether_header);
460 if (MBLKL(mp) == 0) {
461 nmp->b_cont = mp->b_cont;
462 freeb(mp);
463 } else {
464 nmp->b_cont = mp;
468 SET_NET_USHORT(evhp->ether_tci, vtag);
469 vtag >>= 16;
470 SET_NET_USHORT(evhp->ether_tpid, vtag);
471 return (nmp);
474 mblk_t *
475 gld_fastpath_ether(gld_t *gld, mblk_t *mp)
477 gld_mac_info_t *macinfo = gld->gld_mac_info;
478 dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
479 struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
480 unsigned short typelen;
481 mblk_t *nmp;
482 struct ether_header *mh;
483 int hdrlen;
484 uint32_t vptag;
485 gld_vlan_t *gld_vlan;
487 ASSERT(macinfo);
489 /* look in the unitdata request for a sap, else use bound one */
490 if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
491 REF_HOST_USHORT(gldp->glda_sap) != 0)
492 typelen = REF_HOST_USHORT(gldp->glda_sap);
493 else
494 typelen = gld->gld_sap;
497 * We only do fast-path for EtherType encoding because this is the only
498 * case where the media header will be consistent from packet to packet.
500 if (typelen <= ETHERMTU)
501 return (NULL);
504 * Initialize the fast path header to include the
505 * basic source address information and type field.
507 hdrlen = sizeof (struct ether_header);
510 * Check to see if VLAN is enabled on this stream
511 * if so then make the header bigger to hold a clone
512 * vlan tag.
514 gld_vlan = (gld_vlan_t *)gld->gld_vlan;
515 if (gld_vlan && (gld_vlan->gldv_id != VLAN_VID_NONE)) {
516 hdrlen += VTAG_SIZE;
517 vptag = gld_vlan->gldv_ptag;
520 if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
521 return (NULL);
523 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
525 /* Got the space, now copy in the header components */
527 nmp->b_rptr -= sizeof (typelen);
528 SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, typelen);
531 * If the header is for a VLAN stream, then add
532 * in the VLAN tag to the clone header.
534 if (hdrlen > sizeof (struct ether_header)) {
535 nmp->b_rptr -= sizeof (uint16_t);
536 SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, vptag);
537 vptag >>= 16;
538 nmp->b_rptr -= sizeof (uint16_t);
539 SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, vptag);
541 nmp->b_rptr -= (ETHERADDRL * 2);
542 mh = (struct ether_header *)nmp->b_rptr;
543 mac_copy(gldp->glda_addr, &mh->ether_dhost, macinfo->gldm_addrlen);
545 GLDM_LOCK(macinfo, RW_WRITER);
546 mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
547 &mh->ether_shost, macinfo->gldm_addrlen);
548 GLDM_UNLOCK(macinfo);
550 return (nmp);
553 /* == */
554 /* IB */
555 /* == */
557 void
558 gld_init_ib(gld_mac_info_t *macinfo)
561 * Currently, the generic stats maintained by GLD is
562 * sufficient for IPoIB.
565 /* Assumptions we make for this medium */
566 ASSERT(macinfo->gldm_type == DL_IB);
567 ASSERT(macinfo->gldm_addrlen == IPOIB_ADDRL);
568 ASSERT(macinfo->gldm_saplen == -2);
571 /* ARGSUSED */
572 void
573 gld_uninit_ib(gld_mac_info_t *macinfo)
578 * The packet format sent to the driver is:
579 * IPOIB_ADDRL bytes dest addr :: 2b sap :: 2b 0s :: data
580 * The packet format received from the driver is:
581 * IPOIB_GRH_SIZE bytes pseudo GRH :: 2b sap :: 2b 0s :: data.
584 gld_interpret_ib(gld_mac_info_t *macinfo, mblk_t *mp, pktinfo_t *pktinfo,
585 packet_flag_t flags)
587 ipoib_pgrh_t *grh;
588 ipoib_ptxhdr_t *gldp;
589 mblk_t *pmp = NULL;
590 gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
593 * Quickly handle receive fastpath for IPQ hack.
595 if (flags == GLD_RXQUICK) {
596 pktinfo->pktLen = msgdsize(mp) - IPOIB_GRH_SIZE;
599 * Check whether the header is contiguous, which
600 * also implicitly makes sure the packet is big enough.
602 if (MBLKL(mp) < (IPOIB_GRH_SIZE + IPOIB_HDRSIZE))
603 return (-1);
606 * Almost all times, unicast will not have
607 * a valid pgrh; quickly identify and ask for
608 * IPQ hack optimization only in that case.
610 grh = (ipoib_pgrh_t *)mp->b_rptr;
611 if (grh->ipoib_vertcflow == 0) {
612 struct ipoib_header *ihp = (struct ipoib_header *)
613 (mp->b_rptr + IPOIB_GRH_SIZE);
615 pktinfo->isForMe = 1;
616 pktinfo->ethertype = REF_NET_USHORT(ihp->ipoib_type);
617 pktinfo->macLen = IPOIB_GRH_SIZE + IPOIB_HDRSIZE;
618 return (0);
619 } else {
620 return (-1);
625 * Handle the GLD_TX, GLD_RX, GLD_RXLOOP cases now.
627 ASSERT(flags != GLD_RXQUICK);
628 bzero((void *)pktinfo, sizeof (*pktinfo));
630 if (flags != GLD_RX) {
632 * GLD_TX and GLD_RXLOOP cases.
634 gldp = (ipoib_ptxhdr_t *)mp->b_rptr;
635 pktinfo->pktLen = msgdsize(mp);
637 /* make sure packet has at least a pseudo header */
638 if (pktinfo->pktLen < sizeof (ipoib_ptxhdr_t))
639 return (-1);
641 /* make sure the mac header falls into contiguous memory */
642 if (MBLKL(mp) < sizeof (ipoib_ptxhdr_t)) {
643 if ((pmp = msgpullup(mp, -1)) == NULL) {
644 #ifdef GLD_DEBUG
645 if (gld_debug & GLDERRS)
646 cmn_err(CE_WARN,
647 "GLD: interpret_ib "
648 "cannot msgpullup");
649 #endif
650 return (-1);
652 /* this mblk contains the whole mac header */
653 mp = pmp;
657 * Check if mac is broadcast or multicast address; all these
658 * types of address have the top 4 bytes as 0x00FFFFFF.
660 if (mac_eq(&gldp->ipoib_dest, macinfo->gldm_broadcast_addr,
661 sizeof (uint32_t))) {
662 if (mac_eq(&gldp->ipoib_dest,
663 macinfo->gldm_broadcast_addr, IPOIB_ADDRL))
664 pktinfo->isBroadcast = 1;
665 else
666 pktinfo->isMulticast = 1;
670 * Only count bytes we will be sending over the wire
671 * or looping back.
673 pktinfo->pktLen -= IPOIB_ADDRL;
674 if (flags == GLD_TX)
675 goto out; /* Got all info we need for xmit case */
678 * Loopback case: this is a dup'ed message.
680 mp->b_rptr += IPOIB_ADDRL;
681 mac_copy(&gldp->ipoib_dest, pktinfo->dhost, IPOIB_ADDRL);
682 mac_copy(mac_pvt->curr_macaddr, pktinfo->shost, IPOIB_ADDRL);
683 } else {
685 * GLD_RX case; process packet sent from driver.
687 ipoib_mac_t *mact, *tact;
688 ib_qpn_t dqpn;
690 pktinfo->pktLen = msgdsize(mp);
691 /* make sure packet has at least pgrh and mac header */
692 if (pktinfo->pktLen < (IPOIB_GRH_SIZE + IPOIB_HDRSIZE))
693 return (-1);
695 /* make sure the header falls into contiguous memory */
696 if (MBLKL(mp) < (IPOIB_GRH_SIZE + IPOIB_HDRSIZE)) {
697 if ((pmp = msgpullup(mp, -1)) == NULL) {
698 #ifdef GLD_DEBUG
699 if (gld_debug & GLDERRS)
700 cmn_err(CE_WARN,
701 "GLD: interpret_ib "
702 "cannot msgpullup2");
703 #endif
704 return (-1);
706 /* this mblk contains the whole mac header */
707 mp = pmp;
710 grh = (ipoib_pgrh_t *)mp->b_rptr;
711 mp->b_rptr += IPOIB_GRH_SIZE;
712 pktinfo->pktLen -= IPOIB_GRH_SIZE;
713 if (grh->ipoib_vertcflow) {
715 * First, copy source address from grh.
717 mact = (ipoib_mac_t *)pktinfo->shost;
718 mac_copy(&grh->ipoib_sqpn, &mact->ipoib_qpn,
719 IPOIB_ADDRL);
722 * Then copy destination address from grh;
723 * first, the 16 bytes of GID.
725 mact = (ipoib_mac_t *)pktinfo->dhost;
726 mac_copy(&grh->ipoib_dgid_pref,
727 &mact->ipoib_gidpref, IPOIB_ADDRL -
728 sizeof (mact->ipoib_qpn));
729 tact = (ipoib_mac_t *)mac_pvt->curr_macaddr;
731 /* Is this a multicast address */
732 if (*(uchar_t *)(grh->ipoib_dgid_pref) == 0xFF) {
734 * Only check for hardware looping in
735 * multicast case. It is assumed higher
736 * layer code (IP) will stop unicast loops;
737 * ie will prevent a transmit to self.
739 if (bcmp(&grh->ipoib_sqpn, tact,
740 IPOIB_ADDRL) == 0)
741 pktinfo->isLooped = 1;
743 tact = (ipoib_mac_t *)macinfo->
744 gldm_broadcast_addr;
745 if (mac_eq(tact->ipoib_gidpref,
746 grh->ipoib_dgid_pref,
747 IPOIB_ADDRL - sizeof (tact->ipoib_qpn)))
748 pktinfo->isBroadcast = 1;
749 else
750 pktinfo->isMulticast = 1;
752 * Now copy the 4 bytes QPN part of the
753 * destination address.
755 dqpn = htonl(IB_MC_QPN);
756 mac_copy(&dqpn, &mact->ipoib_qpn,
757 sizeof (mact->ipoib_qpn));
758 } else {
760 * Now copy the 4 bytes QPN part of the
761 * destination address.
763 mac_copy(&tact->ipoib_qpn, &mact->ipoib_qpn,
764 sizeof (mact->ipoib_qpn));
766 * Any unicast packets received on IBA are
767 * for the node.
769 pktinfo->isForMe = 1;
771 } else {
773 * It can not be a IBA multicast packet.
774 * Must have been unicast to us. We do not
775 * have shost information, which is used in
776 * gld_addudind(); IP/ARP does not care.
778 pktinfo->nosource = 1;
779 mac_copy(mac_pvt->curr_macaddr, pktinfo->dhost,
780 IPOIB_ADDRL);
782 * Any unicast packets received on IBA are
783 * for the node.
785 pktinfo->isForMe = 1;
789 ASSERT((flags == GLD_RX) || (flags == GLD_RXLOOP));
790 ASSERT(GLDM_LOCK_HELD(macinfo));
791 pktinfo->ethertype = REF_NET_USHORT(((ipoib_hdr_t *)
792 (mp->b_rptr))->ipoib_type);
793 pktinfo->macLen = IPOIB_HDRSIZE;
795 out:
796 if (pmp != NULL)
797 freemsg(pmp);
799 return (0);
803 * The packet format sent to the driver is: 2b sap :: 2b 0s :: data
805 void
806 gld_interpret_mdt_ib(gld_mac_info_t *macinfo, mblk_t *mp, pdescinfo_t *pinfo,
807 pktinfo_t *pktinfo, mdt_packet_flag_t flags)
809 gld_mac_pvt_t *mac_pvt;
810 multidata_t *dlmdp;
811 pattrinfo_t attr_info = { PATTR_DSTADDRSAP, };
812 pattr_t *patr;
813 ipoib_ptxhdr_t *dlap = NULL;
816 * Per packet formatting.
818 if (flags == GLD_MDT_TXPKT) {
819 ipoib_hdr_t *hptr;
820 uint_t seg;
822 if (PDESC_HDRL(pinfo) == 0)
823 return;
826 * Update packet's link header.
828 pinfo->hdr_rptr -= IPOIB_HDRSIZE;
829 hptr = (ipoib_hdr_t *)pinfo->hdr_rptr;
830 hptr->ipoib_mbz = htons(0);
831 hptr->ipoib_type = pktinfo->ethertype;
834 * Total #bytes that will be put on wire.
836 pktinfo->pktLen = PDESC_HDRL(pinfo);
837 for (seg = 0; seg < pinfo->pld_cnt; seg++)
838 pktinfo->pktLen += PDESC_PLDL(pinfo, seg);
840 return;
844 * The following two cases of GLD_MDT_TX and GLD_MDT_RXLOOP are per
845 * MDT message processing.
847 dlmdp = mmd_getmultidata(mp);
848 patr = mmd_getpattr(dlmdp, NULL, &attr_info);
849 ASSERT(patr != NULL);
850 ASSERT(macinfo->gldm_saplen == -2);
851 if (patr != NULL)
852 dlap = (ipoib_ptxhdr_t *)((pattr_addr_t *)attr_info.buf)->addr;
854 if (flags == GLD_MDT_TX) {
855 bzero((void *)pktinfo, sizeof (*pktinfo));
856 if (dlap == NULL)
857 return;
860 * Check if mac is broadcast or multicast address; all these
861 * types of address have the top 4 bytes as 0x00FFFFFF.
863 if (mac_eq(dlap, macinfo->gldm_broadcast_addr,
864 sizeof (uint32_t))) {
865 if (mac_eq(dlap, macinfo->gldm_broadcast_addr,
866 IPOIB_ADDRL))
867 pktinfo->isBroadcast = 1;
868 else
869 pktinfo->isMulticast = 1;
871 pktinfo->ethertype = REF_NET_USHORT(dlap->
872 ipoib_rhdr.ipoib_type);
873 } else {
874 ASSERT(flags == GLD_MDT_RXLOOP);
875 pktinfo->macLen = IPOIB_HDRSIZE;
876 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
877 mac_copy(mac_pvt->curr_macaddr, pktinfo->shost, IPOIB_ADDRL);
878 if (dlap == NULL)
879 return;
880 mac_copy(&dlap->ipoib_dest, pktinfo->dhost, IPOIB_ADDRL);
884 mblk_t *
885 gld_unitdata_ib(gld_t *gld, mblk_t *mp)
887 gld_mac_info_t *macinfo = gld->gld_mac_info;
888 dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_rptr;
889 ipoib_ptxhdr_t *gldp = IPOIBDLSAP(dlp, dlp->dl_dest_addr_offset);
890 ipoib_mac_t dhost;
891 unsigned short type;
892 mblk_t *nmp;
893 int hdrlen;
895 ASSERT(macinfo != NULL);
897 /* extract needed info from the mblk before we maybe reuse it */
898 mac_copy(&gldp->ipoib_dest, &dhost, IPOIB_ADDRL);
900 /* look in the unitdata request for a sap, else use bound one */
901 if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
902 REF_HOST_USHORT(gldp->ipoib_rhdr.ipoib_type) != 0)
903 type = REF_HOST_USHORT(gldp->ipoib_rhdr.ipoib_type);
904 else
905 type = gld->gld_sap;
907 hdrlen = sizeof (ipoib_ptxhdr_t);
909 /* need a buffer big enough for the headers */
910 nmp = mp->b_cont; /* where the packet payload M_DATA is */
911 if (DB_REF(nmp) == 1 && MBLKHEAD(nmp) >= hdrlen) {
912 /* it fits at the beginning of the first M_DATA block */
913 freeb(mp); /* don't need the M_PROTO anymore */
914 } else if (DB_REF(mp) == 1 && MBLKSIZE(mp) >= hdrlen) {
915 /* we can reuse the dl_unitdata_req M_PROTO mblk */
916 nmp = mp;
917 DB_TYPE(nmp) = M_DATA;
918 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
919 } else {
920 /* we need to allocate one */
921 if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
922 return (NULL);
923 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
924 linkb(nmp, mp->b_cont);
925 freeb(mp);
928 /* Got the space, now copy in the header components */
930 nmp->b_rptr -= sizeof (ipoib_ptxhdr_t);
931 gldp = (ipoib_ptxhdr_t *)nmp->b_rptr;
932 SET_NET_USHORT(gldp->ipoib_rhdr.ipoib_type, type);
933 gldp->ipoib_rhdr.ipoib_mbz = 0;
934 mac_copy(&dhost, &gldp->ipoib_dest, IPOIB_ADDRL);
936 return (nmp);
939 mblk_t *
940 gld_fastpath_ib(gld_t *gld, mblk_t *mp)
942 gld_mac_info_t *macinfo = gld->gld_mac_info;
943 dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
944 ipoib_ptxhdr_t *gldp = IPOIBDLSAP(dlp, dlp->dl_dest_addr_offset);
945 unsigned short type;
946 mblk_t *nmp;
947 ipoib_ptxhdr_t *tgldp;
948 int hdrlen;
950 ASSERT(macinfo != NULL);
952 /* look in the unitdata request for a sap, else use bound one */
953 if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
954 REF_HOST_USHORT(gldp->ipoib_rhdr.ipoib_type) != 0)
955 type = REF_HOST_USHORT(gldp->ipoib_rhdr.ipoib_type);
956 else
957 type = gld->gld_sap;
959 hdrlen = sizeof (ipoib_ptxhdr_t);
961 if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
962 return (NULL);
964 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
966 /* Got the space, now copy in the header components */
968 nmp->b_rptr -= sizeof (ipoib_ptxhdr_t);
969 tgldp = (ipoib_ptxhdr_t *)nmp->b_rptr;
970 tgldp->ipoib_rhdr.ipoib_type = htons(type);
971 tgldp->ipoib_rhdr.ipoib_mbz = 0;
972 mac_copy(&gldp->ipoib_dest, &tgldp->ipoib_dest, IPOIB_ADDRL);
974 return (nmp);
977 /* ==== */
978 /* FDDI */
979 /* ==== */
981 void
982 gld_init_fddi(gld_mac_info_t *macinfo)
984 struct gldkstats *sp =
985 ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->kstatp->ks_data;
987 /* Assumptions we make for this medium */
988 ASSERT(macinfo->gldm_type == DL_FDDI);
989 ASSERT(macinfo->gldm_addrlen == 6);
990 ASSERT(macinfo->gldm_saplen == -2);
991 ASSERT(sizeof (struct fddi_mac_frm) == 13);
992 ASSERT(sizeof (mac_addr_t) == 6);
994 /* Wire address format is bit reversed from canonical format */
995 macinfo->gldm_options |= GLDOPT_CANONICAL_ADDR;
997 kstat_named_init(&sp->glds_fddi_mac_error,
998 "mac_errors", KSTAT_DATA_UINT32);
999 kstat_named_init(&sp->glds_fddi_mac_lost,
1000 "mac_lost_errors", KSTAT_DATA_UINT32);
1001 kstat_named_init(&sp->glds_fddi_mac_token,
1002 "mac_tokens", KSTAT_DATA_UINT32);
1003 kstat_named_init(&sp->glds_fddi_mac_tvx_expired,
1004 "mac_tvx_expired", KSTAT_DATA_UINT32);
1005 kstat_named_init(&sp->glds_fddi_mac_late,
1006 "mac_late", KSTAT_DATA_UINT32);
1007 kstat_named_init(&sp->glds_fddi_mac_ring_op,
1008 "mac_ring_ops", KSTAT_DATA_UINT32);
1011 /*ARGSUSED*/
1012 void
1013 gld_uninit_fddi(gld_mac_info_t *macinfo)
1018 gld_interpret_fddi(gld_mac_info_t *macinfo, mblk_t *mp, pktinfo_t *pktinfo,
1019 packet_flag_t flags)
1021 struct fddi_mac_frm *mh;
1022 gld_mac_pvt_t *mac_pvt;
1023 struct llc_snap_hdr *snaphdr;
1024 mblk_t *pmp = NULL;
1027 * Quickly handle receive fastpath; FDDI does not support IPQ hack.
1029 if (flags == GLD_RXQUICK) {
1030 pktinfo->pktLen = msgdsize(mp);
1031 return (-1);
1034 bzero((void *)pktinfo, sizeof (*pktinfo));
1036 pktinfo->pktLen = msgdsize(mp);
1038 /* make sure packet has at least a whole mac header */
1039 if (pktinfo->pktLen < sizeof (struct fddi_mac_frm))
1040 return (-1);
1042 /* make sure the mac header falls into contiguous memory */
1043 if (MBLKL(mp) < sizeof (struct fddi_mac_frm)) {
1044 if ((pmp = msgpullup(mp, -1)) == NULL) {
1045 #ifdef GLD_DEBUG
1046 if (gld_debug & GLDERRS)
1047 cmn_err(CE_WARN,
1048 "GLD: interpret_fddi cannot msgpullup");
1049 #endif
1050 return (-1);
1052 mp = pmp; /* this mblk contains the whole mac header */
1055 mh = (struct fddi_mac_frm *)mp->b_rptr;
1057 /* Check to see if the mac is a broadcast or multicast address. */
1058 /* NB we are still in wire format (non canonical) */
1059 /* mac_eq works because ether_broadcast is the same either way */
1060 if (mac_eq(mh->fddi_dhost, ether_broadcast, macinfo->gldm_addrlen))
1061 pktinfo->isBroadcast = 1;
1062 else if (mh->fddi_dhost[0] & 0x80)
1063 pktinfo->isMulticast = 1;
1065 if (flags == GLD_TX)
1066 goto out; /* Got all info we need for xmit case */
1068 ASSERT(GLDM_LOCK_HELD(macinfo));
1071 * Deal with the mac header
1074 cmac_copy(mh->fddi_dhost, pktinfo->dhost,
1075 macinfo->gldm_addrlen, macinfo);
1076 cmac_copy(mh->fddi_shost, pktinfo->shost,
1077 macinfo->gldm_addrlen, macinfo);
1079 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
1080 pktinfo->isLooped = mac_eq(pktinfo->shost,
1081 mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
1082 pktinfo->isForMe = mac_eq(pktinfo->dhost,
1083 mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
1085 pktinfo->macLen = sizeof (struct fddi_mac_frm);
1088 * Before trying to look beyond the MAC header, make sure the LLC
1089 * header exists, and that both it and any SNAP header are contiguous.
1091 if (MBLKL(mp) < sizeof (struct fddi_mac_frm) + LLC_SNAP_HDR_LEN &&
1092 MBLKL(mp) < pktinfo->pktLen) {
1094 * we don't have the entire packet within the first mblk (and
1095 * therefore we didn't do the msgpullup above), AND the first
1096 * mblk may not contain all the data we need to look at.
1098 ASSERT(pmp == NULL); /* couldn't have done msgpullup above */
1099 if ((pmp = msgpullup(mp, -1)) == NULL) {
1100 #ifdef GLD_DEBUG
1101 if (gld_debug & GLDERRS)
1102 cmn_err(CE_WARN,
1103 "GLD: interpret_fddi cannot msgpullup2");
1104 #endif
1105 goto out; /* can't interpret this pkt further */
1107 mp = pmp; /* this mblk should contain everything needed */
1111 * Check SAP/SNAP information.
1113 if ((mh->fddi_fc & 0x70) == 0x50) {
1114 if (pktinfo->pktLen < pktinfo->macLen + LLC_HDR1_LEN)
1115 goto out;
1117 pktinfo->isLLC = 1;
1119 if (pktinfo->pktLen < pktinfo->macLen + LLC_SNAP_HDR_LEN)
1120 goto out;
1122 snaphdr = (struct llc_snap_hdr *)(mp->b_rptr + pktinfo->macLen);
1123 if (ISETHERTYPE(snaphdr)) {
1124 pktinfo->ethertype = REF_NET_USHORT(snaphdr->type);
1125 pktinfo->hdrLen = LLC_SNAP_HDR_LEN;
1128 out:
1129 if (pmp != NULL)
1130 freemsg(pmp);
1132 return (0);
1135 mblk_t *
1136 gld_unitdata_fddi(gld_t *gld, mblk_t *mp)
1138 gld_mac_info_t *macinfo = gld->gld_mac_info;
1139 dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_rptr;
1140 struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
1141 mac_addr_t dhost;
1142 unsigned short type;
1143 mblk_t *nmp;
1144 struct fddi_mac_frm *mh;
1145 int hdrlen;
1147 ASSERT(macinfo);
1149 /* extract needed info from the mblk before we maybe reuse it */
1150 mac_copy(gldp->glda_addr, dhost, macinfo->gldm_addrlen);
1152 /* look in the unitdata request for a sap, else use bound one */
1153 if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
1154 REF_HOST_USHORT(gldp->glda_sap) != 0)
1155 type = REF_HOST_USHORT(gldp->glda_sap);
1156 else
1157 type = gld->gld_sap;
1160 hdrlen = sizeof (struct fddi_mac_frm);
1163 * Check whether we need to do EtherType encoding or whether the packet
1164 * is LLC.
1166 if (type > GLD_MAX_802_SAP)
1167 hdrlen += sizeof (struct llc_snap_hdr);
1169 /* need a buffer big enough for the headers */
1170 nmp = mp->b_cont; /* where the packet payload M_DATA is */
1171 if (DB_REF(nmp) == 1 && MBLKHEAD(nmp) >= hdrlen) {
1172 /* it fits at the beginning of the first M_DATA block */
1173 freeb(mp); /* don't need the M_PROTO anymore */
1174 } else if (DB_REF(mp) == 1 && MBLKSIZE(mp) >= hdrlen) {
1175 /* we can reuse the dl_unitdata_req M_PROTO mblk */
1176 nmp = mp;
1177 DB_TYPE(nmp) = M_DATA;
1178 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
1179 } else {
1180 /* we need to allocate one */
1181 if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
1182 return (NULL);
1183 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
1184 linkb(nmp, mp->b_cont);
1185 freeb(mp);
1189 /* Got the space, now copy in the header components */
1190 if (type > GLD_MAX_802_SAP) {
1191 /* create the snap header */
1192 struct llc_snap_hdr *snap;
1193 nmp->b_rptr -= sizeof (struct llc_snap_hdr);
1194 snap = (struct llc_snap_hdr *)(nmp->b_rptr);
1195 *snap = llc_snap_def;
1196 SET_NET_USHORT(snap->type, type);
1199 nmp->b_rptr -= sizeof (struct fddi_mac_frm);
1201 mh = (struct fddi_mac_frm *)nmp->b_rptr;
1203 mh->fddi_fc = 0x50;
1204 cmac_copy(dhost, mh->fddi_dhost, macinfo->gldm_addrlen, macinfo);
1207 * We access the mac address without the mutex to prevent
1208 * mutex contention (BUG 4211361)
1210 cmac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
1211 mh->fddi_shost, macinfo->gldm_addrlen, macinfo);
1212 return (nmp);
1215 mblk_t *
1216 gld_fastpath_fddi(gld_t *gld, mblk_t *mp)
1218 gld_mac_info_t *macinfo = gld->gld_mac_info;
1219 dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
1220 struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
1221 unsigned short type;
1222 mblk_t *nmp;
1223 struct fddi_mac_frm *mh;
1224 int hdrlen;
1226 ASSERT(macinfo);
1228 /* look in the unitdata request for a sap, else use bound one */
1229 if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
1230 REF_HOST_USHORT(gldp->glda_sap) != 0)
1231 type = REF_HOST_USHORT(gldp->glda_sap);
1232 else
1233 type = gld->gld_sap;
1235 hdrlen = sizeof (struct fddi_mac_frm);
1238 * Check whether we need to do EtherType encoding or whether the packet
1239 * will be LLC.
1241 if (type > GLD_MAX_802_SAP)
1242 hdrlen += sizeof (struct llc_snap_hdr);
1244 if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
1245 return (NULL);
1247 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
1249 /* Got the space, now copy in the header components */
1251 if (type > GLD_MAX_802_SAP) {
1252 /* create the snap header */
1253 struct llc_snap_hdr *snap;
1254 nmp->b_rptr -= sizeof (struct llc_snap_hdr);
1255 snap = (struct llc_snap_hdr *)(nmp->b_rptr);
1256 *snap = llc_snap_def;
1257 snap->type = htons(type); /* we know it's aligned */
1260 nmp->b_rptr -= sizeof (struct fddi_mac_frm);
1262 mh = (struct fddi_mac_frm *)nmp->b_rptr;
1263 mh->fddi_fc = 0x50;
1264 cmac_copy(gldp->glda_addr, mh->fddi_dhost,
1265 macinfo->gldm_addrlen, macinfo);
1267 GLDM_LOCK(macinfo, RW_WRITER);
1268 cmac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
1269 mh->fddi_shost, macinfo->gldm_addrlen, macinfo);
1270 GLDM_UNLOCK(macinfo);
1272 return (nmp);
1275 /* ========== */
1276 /* Token Ring */
1277 /* ========== */
1279 #define GLD_SR_VAR(macinfo) \
1280 (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->data)
1282 #define GLD_SR_HASH(macinfo) ((struct srtab **)GLD_SR_VAR(macinfo))
1284 #define GLD_SR_MUTEX(macinfo) \
1285 (&((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->datalock)
1287 static void gld_sr_clear(gld_mac_info_t *);
1288 static void gld_rcc_receive(gld_mac_info_t *, pktinfo_t *, struct gld_ri *,
1289 uchar_t *, int);
1290 static void gld_rcc_send(gld_mac_info_t *, queue_t *, uchar_t *,
1291 struct gld_ri **, uchar_t *);
1293 static mac_addr_t tokenbroadcastaddr2 = { 0xc0, 0x00, 0xff, 0xff, 0xff, 0xff };
1294 static struct gld_ri ri_ste_def;
1296 void
1297 gld_init_tr(gld_mac_info_t *macinfo)
1299 struct gldkstats *sp =
1300 ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->kstatp->ks_data;
1302 /* avoid endian-dependent code by initializing here instead of static */
1303 ri_ste_def.len = 2;
1304 ri_ste_def.rt = RT_STE;
1305 ri_ste_def.mtu = RT_MTU_MAX;
1306 ri_ste_def.dir = 0;
1307 ri_ste_def.res = 0;
1309 /* Assumptions we make for this medium */
1310 ASSERT(macinfo->gldm_type == DL_TPR);
1311 ASSERT(macinfo->gldm_addrlen == 6);
1312 ASSERT(macinfo->gldm_saplen == -2);
1313 ASSERT(sizeof (struct tr_mac_frm_nori) == 14);
1314 ASSERT(sizeof (mac_addr_t) == 6);
1316 mutex_init(GLD_SR_MUTEX(macinfo), NULL, MUTEX_DRIVER, NULL);
1318 GLD_SR_VAR(macinfo) = kmem_zalloc(sizeof (struct srtab *)*SR_HASH_SIZE,
1319 KM_SLEEP);
1321 /* Default is RDE enabled for this medium */
1322 ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_enabled =
1323 ddi_getprop(DDI_DEV_T_NONE, macinfo->gldm_devinfo, 0,
1324 "gld_rde_enable", 1);
1327 * Default is to use STE for unknown paths if RDE is enabled.
1328 * If RDE is disabled, default is to use NULL RIF fields.
1330 * It's possible to force use of STE for ALL packets:
1331 * disable RDE but enable STE. This may be useful for
1332 * non-transparent bridges, when it is not desired to run
1333 * the RDE algorithms.
1335 ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_str_indicator_ste =
1336 ddi_getprop(DDI_DEV_T_NONE, macinfo->gldm_devinfo, 0,
1337 "gld_rde_str_indicator_ste",
1338 ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_enabled);
1340 /* Default 10 second route timeout on lack of activity */
1342 int t = ddi_getprop(DDI_DEV_T_NONE, macinfo->gldm_devinfo, 0,
1343 "gld_rde_timeout", 10);
1344 if (t < 1)
1345 t = 1; /* Let's be reasonable */
1346 if (t > 600)
1347 t = 600; /* Let's be reasonable */
1348 /* We're using ticks (lbolts) for our timeout -- convert from seconds */
1349 t = drv_usectohz(1000000 * t);
1350 ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_timeout = t;
1353 kstat_named_init(&sp->glds_dot5_line_error,
1354 "line_errors", KSTAT_DATA_UINT32);
1355 kstat_named_init(&sp->glds_dot5_burst_error,
1356 "burst_errors", KSTAT_DATA_UINT32);
1357 kstat_named_init(&sp->glds_dot5_signal_loss,
1358 "signal_losses", KSTAT_DATA_UINT32);
1361 * only initialize the new statistics if the driver
1362 * knows about them.
1364 if (macinfo->gldm_driver_version != GLD_VERSION_200)
1365 return;
1367 kstat_named_init(&sp->glds_dot5_ace_error,
1368 "ace_errors", KSTAT_DATA_UINT32);
1369 kstat_named_init(&sp->glds_dot5_internal_error,
1370 "internal_errors", KSTAT_DATA_UINT32);
1371 kstat_named_init(&sp->glds_dot5_lost_frame_error,
1372 "lost_frame_errors", KSTAT_DATA_UINT32);
1373 kstat_named_init(&sp->glds_dot5_frame_copied_error,
1374 "frame_copied_errors", KSTAT_DATA_UINT32);
1375 kstat_named_init(&sp->glds_dot5_token_error,
1376 "token_errors", KSTAT_DATA_UINT32);
1377 kstat_named_init(&sp->glds_dot5_freq_error,
1378 "freq_errors", KSTAT_DATA_UINT32);
1381 void
1382 gld_uninit_tr(gld_mac_info_t *macinfo)
1384 mutex_destroy(GLD_SR_MUTEX(macinfo));
1385 gld_sr_clear(macinfo);
1386 kmem_free(GLD_SR_VAR(macinfo), sizeof (struct srtab *) * SR_HASH_SIZE);
1390 gld_interpret_tr(gld_mac_info_t *macinfo, mblk_t *mp, pktinfo_t *pktinfo,
1391 packet_flag_t flags)
1393 struct tr_mac_frm *mh;
1394 gld_mac_pvt_t *mac_pvt;
1395 struct llc_snap_hdr *snaphdr;
1396 mblk_t *pmp = NULL;
1397 struct gld_ri *rh;
1400 * Quickly handle receive fastpath; TR does not support IPQ hack.
1402 if (flags == GLD_RXQUICK) {
1403 pktinfo->pktLen = msgdsize(mp);
1404 return (-1);
1407 bzero((void *)pktinfo, sizeof (*pktinfo));
1409 pktinfo->pktLen = msgdsize(mp);
1411 /* make sure packet has at least a whole mac header */
1412 if (pktinfo->pktLen < sizeof (struct tr_mac_frm_nori))
1413 return (-1);
1415 /* make sure the mac header falls into contiguous memory */
1416 if (MBLKL(mp) < sizeof (struct tr_mac_frm_nori)) {
1417 if ((pmp = msgpullup(mp, -1)) == NULL) {
1418 #ifdef GLD_DEBUG
1419 if (gld_debug & GLDERRS)
1420 cmn_err(CE_WARN,
1421 "GLD: interpret_tr cannot msgpullup");
1422 #endif
1423 return (-1);
1425 mp = pmp; /* this mblk contains the whole mac header */
1428 mh = (struct tr_mac_frm *)mp->b_rptr;
1430 /* Check to see if the mac is a broadcast or multicast address. */
1431 if (mac_eq(mh->tr_dhost, ether_broadcast, macinfo->gldm_addrlen) ||
1432 mac_eq(mh->tr_dhost, tokenbroadcastaddr2, macinfo->gldm_addrlen))
1433 pktinfo->isBroadcast = 1;
1434 else if (mh->tr_dhost[0] & 0x80)
1435 pktinfo->isMulticast = 1;
1437 if (flags == GLD_TX)
1438 goto out; /* Got all info we need for xmit case */
1440 ASSERT(GLDM_LOCK_HELD(macinfo));
1443 * Deal with the mac header
1446 mac_copy(mh->tr_dhost, pktinfo->dhost, macinfo->gldm_addrlen);
1447 mac_copy(mh->tr_shost, pktinfo->shost, macinfo->gldm_addrlen);
1448 pktinfo->shost[0] &= ~0x80; /* turn off RIF indicator */
1450 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
1451 pktinfo->isLooped = mac_eq(pktinfo->shost,
1452 mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
1453 pktinfo->isForMe = mac_eq(pktinfo->dhost,
1454 mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
1456 rh = NULL;
1457 pktinfo->macLen = sizeof (struct tr_mac_frm_nori);
1460 * Before trying to look beyond the MAC header, make sure the data
1461 * structures are all contiguously where we can conveniently look at
1462 * them. We'll use a worst-case estimate of how many bytes into the
1463 * packet data we'll be needing to look. Things will be more efficient
1464 * if the driver puts at least this much into the first mblk.
1466 * Even after this, we still will have to do checks against the total
1467 * length of the packet. A bad incoming packet may not hold all the
1468 * data structures it says it does.
1470 if (MBLKL(mp) < sizeof (struct tr_mac_frm) +
1471 LLC_HDR1_LEN + sizeof (struct rde_pdu) &&
1472 MBLKL(mp) < pktinfo->pktLen) {
1474 * we don't have the entire packet within the first mblk (and
1475 * therefore we didn't do the msgpullup above), AND the first
1476 * mblk may not contain all the data we need to look at.
1478 ASSERT(pmp == NULL); /* couldn't have done msgpullup above */
1479 if ((pmp = msgpullup(mp, -1)) == NULL) {
1480 #ifdef GLD_DEBUG
1481 if (gld_debug & GLDERRS)
1482 cmn_err(CE_WARN,
1483 "GLD: interpret_tr cannot msgpullup2");
1484 #endif
1485 goto out; /* can't interpret this pkt further */
1487 mp = pmp; /* this mblk should contain everything needed */
1488 mh = (struct tr_mac_frm *)mp->b_rptr; /* to look at RIF */
1491 if (mh->tr_shost[0] & 0x80) {
1492 /* Routing Information Field (RIF) is present */
1493 if (pktinfo->pktLen < sizeof (struct tr_mac_frm_nori) + 2)
1494 goto out; /* RIF should have been there! */
1495 rh = (struct gld_ri *)&mh->tr_ri;
1496 if ((rh->len & 1) || rh->len < 2) {
1497 /* Bogus RIF, don't handle this packet */
1498 #ifdef GLD_DEBUG
1499 if (gld_debug & GLDERRS)
1500 cmn_err(CE_WARN,
1501 "GLD: received TR packet with "
1502 "bogus RIF length %d",
1503 rh->len);
1504 #endif
1505 goto out;
1507 if (pktinfo->pktLen < sizeof (struct tr_mac_frm_nori) + rh->len)
1508 goto out; /* RIF should have been there! */
1509 pktinfo->macLen += rh->len;
1512 if ((mh->tr_fc & 0xc0) == 0x40) {
1513 if (pktinfo->pktLen < pktinfo->macLen + LLC_HDR1_LEN)
1514 goto out;
1516 pktinfo->isLLC = 1;
1518 if (pktinfo->pktLen < pktinfo->macLen + LLC_SNAP_HDR_LEN)
1519 goto out;
1521 snaphdr = (struct llc_snap_hdr *)(mp->b_rptr + pktinfo->macLen);
1522 if (ISETHERTYPE(snaphdr)) {
1523 pktinfo->ethertype = REF_NET_USHORT(snaphdr->type);
1524 pktinfo->hdrLen = LLC_SNAP_HDR_LEN;
1527 /* Inform the Route Control Component of received LLC frame */
1528 gld_rcc_receive(macinfo, pktinfo, rh,
1529 mp->b_rptr + pktinfo->macLen,
1530 pktinfo->pktLen - pktinfo->macLen);
1532 out:
1533 if (pmp != NULL)
1534 freemsg(pmp);
1536 return (0);
1539 mblk_t *
1540 gld_unitdata_tr(gld_t *gld, mblk_t *mp)
1542 gld_mac_info_t *macinfo = gld->gld_mac_info;
1543 dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_rptr;
1544 struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
1545 mac_addr_t dhost;
1546 unsigned short type;
1547 mblk_t *nmp, *llcmp, *pmp = NULL;
1548 struct tr_mac_frm_nori *mh;
1549 int hdrlen;
1550 struct gld_ri *rh;
1552 ASSERT(macinfo);
1554 /* extract needed info from the mblk before we maybe reuse it */
1555 mac_copy(gldp->glda_addr, dhost, macinfo->gldm_addrlen);
1557 /* look in the unitdata request for a sap, else use bound one */
1558 if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
1559 REF_HOST_USHORT(gldp->glda_sap) != 0)
1560 type = REF_HOST_USHORT(gldp->glda_sap);
1561 else
1562 type = gld->gld_sap;
1564 /* includes maximum possible Routing Information Field (RIF) size */
1565 hdrlen = sizeof (struct tr_mac_frm);
1568 * Check whether we need to do EtherType encoding or whether the packet
1569 * is LLC.
1571 if (type > GLD_MAX_802_SAP)
1572 hdrlen += sizeof (struct llc_snap_hdr);
1574 /* need a buffer big enough for the headers */
1575 llcmp = nmp = mp->b_cont; /* where the packet payload M_DATA is */
1578 * We are going to need to look at the LLC header, so make sure it
1579 * is contiguously in a single mblk. If we're the ones who create
1580 * the LLC header (below, in the case where sap > 0xff) then we don't
1581 * have to worry about it here.
1583 ASSERT(nmp != NULL); /* gld_unitdata guarantees msgdsize > 0 */
1584 if (type <= GLD_MAX_802_SAP) {
1585 if (MBLKL(llcmp) < LLC_HDR1_LEN) {
1586 llcmp = pmp = msgpullup(nmp, LLC_HDR1_LEN);
1587 if (pmp == NULL) {
1588 #ifdef GLD_DEBUG
1589 if (gld_debug & GLDERRS)
1590 cmn_err(CE_WARN,
1591 "GLD: unitdata_tr "
1592 "cannot msgpullup");
1593 #endif
1594 return (NULL);
1599 if (DB_REF(nmp) == 1 && MBLKHEAD(nmp) >= hdrlen) {
1600 /* it fits at the beginning of the first M_DATA block */
1601 freeb(mp); /* don't need the M_PROTO anymore */
1602 } else if (DB_REF(mp) == 1 && MBLKSIZE(mp) >= hdrlen) {
1603 /* we can reuse the dl_unitdata_req M_PROTO mblk */
1604 nmp = mp;
1605 DB_TYPE(nmp) = M_DATA;
1606 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
1607 } else {
1608 /* we need to allocate one */
1609 if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL) {
1610 if (pmp != NULL)
1611 freemsg(pmp);
1612 return (NULL);
1614 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
1615 linkb(nmp, mp->b_cont);
1616 freeb(mp);
1619 /* Got the space, now copy in the header components */
1620 if (type > GLD_MAX_802_SAP) {
1621 /* create the snap header */
1622 struct llc_snap_hdr *snap;
1623 llcmp = nmp; /* LLC header is going to be in this mblk */
1624 nmp->b_rptr -= sizeof (struct llc_snap_hdr);
1625 snap = (struct llc_snap_hdr *)(nmp->b_rptr);
1626 *snap = llc_snap_def;
1627 SET_NET_USHORT(snap->type, type);
1630 /* Hold SR tables still while we maybe point at an entry */
1631 mutex_enter(GLD_SR_MUTEX(macinfo));
1633 gld_rcc_send(macinfo, WR(gld->gld_qptr), dhost, &rh, llcmp->b_rptr);
1635 if (rh != NULL) {
1636 /* copy in the RIF */
1637 ASSERT(rh->len <= sizeof (struct gld_ri));
1638 nmp->b_rptr -= rh->len;
1639 bcopy((caddr_t)rh, (caddr_t)nmp->b_rptr, rh->len);
1642 mutex_exit(GLD_SR_MUTEX(macinfo));
1644 /* no longer need the pulled-up mblk */
1645 if (pmp != NULL)
1646 freemsg(pmp);
1649 * fill in token ring header
1651 nmp->b_rptr -= sizeof (struct tr_mac_frm_nori);
1652 mh = (struct tr_mac_frm_nori *)nmp->b_rptr;
1653 mh->tr_ac = 0x10;
1654 mh->tr_fc = 0x40;
1655 mac_copy(dhost, mh->tr_dhost, macinfo->gldm_addrlen);
1658 * We access the mac address without the mutex to prevent
1659 * mutex contention (BUG 4211361)
1661 mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
1662 mh->tr_shost, macinfo->gldm_addrlen);
1664 if (rh != NULL)
1665 mh->tr_shost[0] |= 0x80;
1666 else
1667 mh->tr_shost[0] &= ~0x80;
1669 return (nmp);
1673 * We cannot have our client sending us "fastpath" M_DATA messages,
1674 * because to do that we must provide a fixed MAC header to
1675 * be prepended to each outgoing packet. But with Source Routing
1676 * media, the length and content of the MAC header changes as the
1677 * routes change, so there is no fixed header we can provide. So
1678 * we decline to accept M_DATA messages if Source Routing is enabled.
1680 mblk_t *
1681 gld_fastpath_tr(gld_t *gld, mblk_t *mp)
1683 gld_mac_info_t *macinfo = gld->gld_mac_info;
1684 dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
1685 struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
1686 unsigned short type;
1687 mblk_t *nmp;
1688 struct tr_mac_frm_nori *mh;
1689 int hdrlen;
1691 ASSERT(macinfo);
1694 * If we are doing Source Routing, then we cannot provide a fixed
1695 * MAC header, so fail.
1697 if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_enabled)
1698 return (NULL);
1700 /* look in the unitdata request for a sap, else use bound one */
1701 if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
1702 REF_HOST_USHORT(gldp->glda_sap) != 0)
1703 type = REF_HOST_USHORT(gldp->glda_sap);
1704 else
1705 type = gld->gld_sap;
1707 hdrlen = sizeof (struct tr_mac_frm_nori);
1709 if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_str_indicator_ste)
1710 hdrlen += ri_ste_def.len;
1713 * Check whether we need to do EtherType encoding or whether the packet
1714 * will be LLC.
1716 if (type > GLD_MAX_802_SAP)
1717 hdrlen += sizeof (struct llc_snap_hdr);
1719 if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
1720 return (NULL);
1722 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
1724 /* Got the space, now copy in the header components */
1726 if (type > GLD_MAX_802_SAP) {
1727 /* create the snap header */
1728 struct llc_snap_hdr *snap;
1729 nmp->b_rptr -= sizeof (struct llc_snap_hdr);
1730 snap = (struct llc_snap_hdr *)(nmp->b_rptr);
1731 *snap = llc_snap_def;
1732 snap->type = htons(type); /* we know it's aligned */
1735 /* RDE is disabled, use NULL RIF, or STE RIF */
1736 if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_str_indicator_ste) {
1737 nmp->b_rptr -= ri_ste_def.len;
1738 bcopy((caddr_t)&ri_ste_def, (caddr_t)nmp->b_rptr,
1739 ri_ste_def.len);
1743 * fill in token ring header
1745 nmp->b_rptr -= sizeof (struct tr_mac_frm_nori);
1746 mh = (struct tr_mac_frm_nori *)nmp->b_rptr;
1747 mh->tr_ac = 0x10;
1748 mh->tr_fc = 0x40;
1749 mac_copy(gldp->glda_addr, mh->tr_dhost, macinfo->gldm_addrlen);
1751 GLDM_LOCK(macinfo, RW_WRITER);
1752 mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
1753 mh->tr_shost, macinfo->gldm_addrlen);
1754 GLDM_UNLOCK(macinfo);
1756 if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_str_indicator_ste)
1757 mh->tr_shost[0] |= 0x80;
1758 else
1759 mh->tr_shost[0] &= ~0x80;
1761 return (nmp);
1765 * Route Determination Entity (ISO 8802-2 / IEEE 802.2 : 1994, Section 9)
1767 * RDE is an LLC layer entity. GLD is a MAC layer entity. The proper
1768 * solution to this architectural anomaly is to move RDE support out of GLD
1769 * and into LLC where it belongs. In particular, only LLC has the knowledge
1770 * necessary to reply to XID and TEST packets. If and when it comes time to
1771 * move RDE out of GLD to LLC, the LLC-to-GLD interface should be modified
1772 * to use MA_UNITDATA structures rather than DL_UNITDATA structures. Of
1773 * course, GLD will still have to continue to also support the DL_ structures
1774 * as long as IP is not layered over LLC. Another, perhaps better, idea
1775 * would be to make RDE an autopush module on top of the token ring drivers:
1776 * RDE would sit between LLC and GLD. It would then also sit between IP and
1777 * GLD, providing services to all clients of GLD/tokenring. In that case,
1778 * GLD would still have to continue to support the DL_ interface for non-
1779 * Token Ring interfaces, using the MA_ interface only for media supporting
1780 * Source Routing media.
1782 * At present, Token Ring is the only source routing medium we support.
1783 * Since Token Ring is not at this time a strategic network medium for Sun,
1784 * rather than devote a large amount of resources to creating a proper
1785 * architecture and implementation of RDE, we do the minimum necessary to
1786 * get it to work. The interface between the above token ring code and the
1787 * below RDE code is designed to make it relatively easy to change to an
1788 * MA_UNITDATA model later should this ever become a priority.
1791 static void gld_send_rqr(gld_mac_info_t *, uchar_t *, struct gld_ri *,
1792 struct rde_pdu *, int);
1793 static void gld_rde_pdu_req(gld_mac_info_t *, queue_t *, uchar_t *,
1794 struct gld_ri *, uchar_t, uchar_t, uchar_t);
1795 static void gld_get_route(gld_mac_info_t *, queue_t *, uchar_t *,
1796 struct gld_ri **, uchar_t, uchar_t);
1797 static void gld_reset_route(gld_mac_info_t *, queue_t *,
1798 uchar_t *, uchar_t, uchar_t);
1799 static void gld_rde_pdu_ind(gld_mac_info_t *, struct gld_ri *, struct rde_pdu *,
1800 int);
1801 static void gld_rif_ind(gld_mac_info_t *, struct gld_ri *, uchar_t *,
1802 uchar_t, uchar_t);
1803 static struct srtab **gld_sr_hash(struct srtab **, uchar_t *, int);
1804 static struct srtab *gld_sr_lookup_entry(gld_mac_info_t *, uchar_t *);
1805 static struct srtab *gld_sr_create_entry(gld_mac_info_t *, uchar_t *);
1808 * This routine implements a modified subset of the 802.2 RDE RCC receive
1809 * actions:
1810 * we implement RCC receive events 3 to 12 (ISO 8802-2:1994 9.6.3.4);
1811 * we omit special handling for the NULL SAP;
1812 * we omit XID/TEST handling;
1813 * we pass all packets (including RDE) upstream to LLC.
1815 static void
1816 gld_rcc_receive(gld_mac_info_t *macinfo, pktinfo_t *pktinfo, struct gld_ri *rh,
1817 uchar_t *llcpkt, int llcpktlen)
1819 struct llc_snap_hdr *snaphdr = (struct llc_snap_hdr *)(llcpkt);
1821 if (!((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_enabled)
1822 return;
1825 * First, ensure this packet wasn't something we received just
1826 * because we were in promiscuous mode. Since none of the below
1827 * code wants to see group addressed packets anyway, we can do
1828 * this check up front. Since we're doing that, we can omit the
1829 * checks for group addressed packets below.
1831 if (!pktinfo->isForMe)
1832 return; /* Event 6 */
1834 /* Process a subset of Route Determination Entity (RDE) packets */
1835 if (snaphdr->d_lsap == LSAP_RDE) {
1836 struct rde_pdu *pdu = (struct rde_pdu *)(llcpkt + LLC_HDR1_LEN);
1837 int pdulen = llcpktlen - LLC_HDR1_LEN;
1839 /* sanity check the PDU */
1840 if ((pdulen < sizeof (struct rde_pdu)) ||
1841 (snaphdr->s_lsap != LSAP_RDE))
1842 return;
1844 /* we only handle route discovery PDUs, not XID/TEST/other */
1845 if (snaphdr->control != CNTL_LLC_UI)
1846 return;
1848 switch (pdu->rde_ptype) {
1849 case RDE_RQC: /* Route Query Command; Events 8 - 11 */
1850 gld_send_rqr(macinfo, pktinfo->shost, rh, pdu, pdulen);
1851 /* FALLTHROUGH */
1852 case RDE_RQR: /* Route Query Response; Event 12 */
1853 case RDE_RS: /* Route Selected; Event 7 */
1854 gld_rde_pdu_ind(macinfo, rh, pdu, pdulen);
1855 break;
1856 default: /* ignore if unrecognized ptype */
1857 return;
1860 return;
1863 /* Consider routes seen in other IA SRF packets */
1865 if (rh == NULL)
1866 return; /* no RIF; Event 3 */
1868 if ((rh->rt & 0x04) != 0)
1869 return; /* not SRF; Event 5 */
1871 gld_rif_ind(macinfo, rh, pktinfo->shost, snaphdr->s_lsap,
1872 snaphdr->d_lsap); /* Event 4 */
1876 * Send RQR: 802.2 9.6.3.4.2(9) RCC Receive Events 8-11
1878 * The routing processing really doesn't belong here; it should be handled in
1879 * the LLC layer above. If that were the case then RDE could just send down
1880 * an extra MA_UNITDATA_REQ with the info needed to construct the packet. But
1881 * at the time we get control here, it's not a particularly good time to be
1882 * constructing packets and trying to send them. Specifically, at this layer
1883 * we need to construct the full media packet, which means the below routine
1884 * knows that it is dealing with Token Ring media. If this were instead done
1885 * via a proper MA_UNITDATA interface, the RDE stuff could all be completely
1886 * media independent. But since TR is the only source routing medium we
1887 * support, this works even though it is not clean.
1889 * We "know" that the only time we can get here is from the "interpret"
1890 * routine, and only when it was called at receive time.
1892 static void
1893 gld_send_rqr(gld_mac_info_t *macinfo, uchar_t *shost, struct gld_ri *rh,
1894 struct rde_pdu *pdu, int pdulen)
1896 mblk_t *nmp;
1897 int nlen;
1898 struct tr_mac_frm_nori *nmh;
1899 struct gld_ri *nrh;
1900 struct llc_snap_hdr *nsnaphdr;
1901 struct rde_pdu *npdu;
1903 /* We know and assume we're on the receive path */
1904 ASSERT(GLDM_LOCK_HELD(macinfo));
1906 if (pdulen < sizeof (struct rde_pdu))
1907 return; /* Bad incoming PDU */
1909 nlen = sizeof (struct tr_mac_frm) + LLC_HDR1_LEN +
1910 sizeof (struct rde_pdu);
1912 if ((nmp = allocb(nlen, BPRI_MED)) == NULL)
1913 return;
1915 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
1917 nmp->b_rptr -= sizeof (struct rde_pdu);
1918 npdu = (struct rde_pdu *)(nmp->b_rptr);
1919 *npdu = *pdu; /* copy orig/target macaddr/saps */
1920 npdu->rde_ver = 1;
1921 npdu->rde_ptype = RDE_RQR;
1922 mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
1923 npdu->rde_target_mac, macinfo->gldm_addrlen);
1925 nmp->b_rptr -= LLC_HDR1_LEN;
1926 nsnaphdr = (struct llc_snap_hdr *)(nmp->b_rptr);
1927 nsnaphdr->s_lsap = nsnaphdr->d_lsap = LSAP_RDE;
1928 nsnaphdr->control = CNTL_LLC_UI;
1930 if (rh == NULL || (rh->rt & 0x06) == 0x06 ||
1931 rh->len > sizeof (struct gld_ri)) {
1932 /* no RIF (Event 8), or RIF type STE (Event 9): send ARE RQR */
1933 nmp->b_rptr -= 2;
1934 nrh = (struct gld_ri *)(nmp->b_rptr);
1935 nrh->len = 2;
1936 nrh->rt = RT_ARE;
1937 nrh->dir = 0;
1938 nrh->res = 0;
1939 nrh->mtu = RT_MTU_MAX;
1940 } else {
1942 * RIF must be ARE (Event 10) or SRF (Event 11):
1943 * send SRF (reverse) RQR
1945 ASSERT(rh->len <= sizeof (struct gld_ri));
1946 nmp->b_rptr -= rh->len;
1947 nrh = (struct gld_ri *)(nmp->b_rptr);
1948 bcopy(rh, nrh, rh->len); /* copy incoming RIF */
1949 nrh->rt = RT_SRF; /* make it SRF */
1950 nrh->dir ^= 1; /* reverse direction */
1953 nmp->b_rptr -= sizeof (struct tr_mac_frm_nori);
1954 nmh = (struct tr_mac_frm_nori *)(nmp->b_rptr);
1955 nmh->tr_ac = 0x10;
1956 nmh->tr_fc = 0x40;
1957 mac_copy(shost, nmh->tr_dhost, macinfo->gldm_addrlen);
1958 mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
1959 nmh->tr_shost, macinfo->gldm_addrlen);
1960 nmh->tr_shost[0] |= 0x80; /* indicate RIF present */
1963 * Packet assembled; send it.
1965 * As noted before, this is not really a good time to be trying to
1966 * send out packets. We have no obvious queue to use if the packet
1967 * can't be sent right away. We pick one arbitrarily.
1970 gld_vlan_t *vlan;
1971 queue_t *q;
1973 if ((vlan = gld_find_vlan(macinfo, VLAN_VID_NONE)) == NULL) {
1974 /* oops, no vlan on the list for this macinfo! */
1975 /* this should not happen */
1976 freeb(nmp);
1977 return;
1979 q = vlan->gldv_str_next->gld_qptr;
1982 * Queue the packet and let gld_wsrv
1983 * handle it, thus preventing a panic
1984 * caused by v2 TR in promiscuous mode
1985 * where it attempts to get the mutex
1986 * in this thread while already holding
1987 * it.
1989 (void) putbq(WR(q), nmp);
1990 qenable(WR(q));
1995 * This routine implements a modified subset of the 802.2 RDE RCC send actions:
1996 * we implement RCC send events 5 to 10 (ISO 8802-2:1994 9.6.3.5);
1997 * we omit special handling for the NULL SAP;
1998 * events 11 to 12 are handled by gld_rde_pdu_req below;
1999 * we require an immediate response to our GET_ROUTE_REQUEST.
2001 static void
2002 gld_rcc_send(gld_mac_info_t *macinfo, queue_t *q, uchar_t *dhost,
2003 struct gld_ri **rhp, uchar_t *llcpkt)
2005 struct llc_snap_hdr *snaphdr = (struct llc_snap_hdr *)(llcpkt);
2008 * Our caller has to take the mutex because: to avoid an extra bcopy
2009 * of the RIF on every transmit, we pass back a pointer to our sr
2010 * table entry via rhp. The caller has to keep the mutex until it has a
2011 * chance to copy the RIF out into the outgoing packet, so that we
2012 * don't modify the entry while it's being copied. This is a
2013 * little ugly, but saves the extra bcopy.
2015 ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo)));
2017 *rhp = NULL; /* start off clean (no RIF) */
2019 if (!((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_enabled) {
2020 /* RDE is disabled -- use NULL or STE always */
2021 if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->
2022 rde_str_indicator_ste)
2023 *rhp = &ri_ste_def; /* STE option */
2024 return;
2027 if (!(dhost[0] & 0x80)) {
2028 /* individual address; Events 7 - 10 */
2029 if ((snaphdr->control & 0xef) == 0xe3) {
2030 /* TEST command, reset the route */
2031 gld_reset_route(macinfo, q,
2032 dhost, snaphdr->d_lsap, snaphdr->s_lsap);
2034 gld_get_route(macinfo, q,
2035 dhost, rhp, snaphdr->d_lsap, snaphdr->s_lsap);
2038 if (*rhp == NULL) {
2040 * group address (Events 5 - 6),
2041 * or no route available (Events 8 - 9):
2042 * Need to send NSR or STE, as configured.
2044 if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->
2045 rde_str_indicator_ste)
2046 *rhp = &ri_ste_def; /* STE option */
2051 * RCC send events 11 - 12
2053 * At present we only handle the RQC ptype.
2055 * We "know" that the only time we can get here is from the "unitdata"
2056 * routine, called at wsrv time.
2058 * If we ever implement the RS ptype (Event 13), this may no longer be true!
2060 static void
2061 gld_rde_pdu_req(gld_mac_info_t *macinfo, queue_t *q, uchar_t *dhost,
2062 struct gld_ri *rh, uchar_t dsap, uchar_t ssap, uchar_t ptype)
2064 mblk_t *nmp;
2065 int nlen;
2066 struct tr_mac_frm_nori *nmh;
2067 struct gld_ri *nrh;
2068 struct llc_snap_hdr *nsnaphdr;
2069 struct rde_pdu *npdu;
2070 int srpresent = 0;
2072 /* if you change this to process other types, review all code below */
2073 ASSERT(ptype == RDE_RQC);
2074 ASSERT(rh == NULL); /* RQC never uses SRF */
2076 nlen = sizeof (struct tr_mac_frm) + LLC_HDR1_LEN +
2077 sizeof (struct rde_pdu);
2079 if ((nmp = allocb(nlen, BPRI_MED)) == NULL)
2080 return;
2082 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
2084 nmp->b_rptr -= sizeof (struct rde_pdu);
2085 npdu = (struct rde_pdu *)(nmp->b_rptr);
2086 npdu->rde_ver = 1;
2087 npdu->rde_ptype = ptype;
2088 mac_copy(dhost, &npdu->rde_target_mac, 6);
2091 * access the mac address without a mutex - take a risk -
2092 * to prevent mutex contention (BUG 4211361)
2094 mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
2095 &npdu->rde_orig_mac, 6);
2096 npdu->rde_target_sap = dsap;
2097 npdu->rde_orig_sap = ssap;
2099 nmp->b_rptr -= LLC_HDR1_LEN;
2100 nsnaphdr = (struct llc_snap_hdr *)(nmp->b_rptr);
2101 nsnaphdr->s_lsap = nsnaphdr->d_lsap = LSAP_RDE;
2102 nsnaphdr->control = CNTL_LLC_UI;
2104 #if 0 /* we don't need this for now */
2105 if (rh != NULL) {
2106 /* send an SRF frame with specified RIF */
2107 ASSERT(rh->len <= sizeof (struct gld_ri));
2108 nmp->b_rptr -= rh->len;
2109 nrh = (struct gld_ri *)(nmp->b_rptr);
2110 bcopy(rh, nrh, rh->len);
2111 ASSERT(nrh->rt == RT_SRF);
2112 srpresent = 1;
2113 } else
2114 #endif
2116 /* Need to send NSR or STE, as configured. */
2117 if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_str_indicator_ste) {
2118 /* send an STE frame */
2119 nmp->b_rptr -= 2;
2120 nrh = (struct gld_ri *)(nmp->b_rptr);
2121 nrh->len = 2;
2122 nrh->rt = RT_STE;
2123 nrh->dir = 0;
2124 nrh->res = 0;
2125 nrh->mtu = RT_MTU_MAX;
2126 srpresent = 1;
2127 } /* else send an NSR frame */
2129 nmp->b_rptr -= sizeof (struct tr_mac_frm_nori);
2130 nmh = (struct tr_mac_frm_nori *)(nmp->b_rptr);
2131 nmh->tr_ac = 0x10;
2132 nmh->tr_fc = 0x40;
2133 mac_copy(dhost, nmh->tr_dhost, macinfo->gldm_addrlen);
2135 * access the mac address without a mutex - take a risk -
2136 * to prevent mutex contention - BUG 4211361
2138 mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
2139 nmh->tr_shost, macinfo->gldm_addrlen);
2141 if (srpresent)
2142 nmh->tr_shost[0] |= 0x80;
2143 else
2144 nmh->tr_shost[0] &= ~0x80;
2147 * Packet assembled; send it.
2149 * Since we own the SR_MUTEX, we don't want to take the maclock
2150 * mutex (since they are acquired in the opposite order on the
2151 * receive path, so deadlock could occur). We could rearrange
2152 * the code in gld_get_route() and drop the SR_MUTEX around the
2153 * call to gld_rde_pdu_req(), but that's kind of ugly. Rather,
2154 * we just refrain from calling gld_start() from here, and
2155 * instead just queue the packet for wsrv to send next. Besides,
2156 * it's more important to get the packet we're working on out
2157 * quickly than this RQC.
2159 (void) putbq(WR(q), nmp);
2160 qenable(WR(q));
2164 * Route Determination Component (RDC)
2166 * We do not implement separate routes for each SAP, as specified by
2167 * ISO 8802-2; instead we implement only one route per remote mac address.
2169 static void
2170 gld_get_route(gld_mac_info_t *macinfo, queue_t *q, uchar_t *dhost,
2171 struct gld_ri **rhp, uchar_t dsap, uchar_t ssap)
2173 struct srtab *sr;
2174 clock_t t = ddi_get_lbolt();
2176 ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo)));
2178 sr = gld_sr_lookup_entry(macinfo, dhost);
2180 if (sr == NULL) {
2182 * we have no entry -- never heard of this address:
2183 * create an empty entry and initiate RQC
2185 sr = gld_sr_create_entry(macinfo, dhost);
2186 gld_rde_pdu_req(macinfo, q, dhost, NULL,
2187 dsap, ssap, RDE_RQC);
2188 if (sr)
2189 sr->sr_timer = t;
2190 *rhp = NULL; /* we have no route yet */
2191 return;
2194 /* we have an entry; see if we know a route yet */
2196 if (sr->sr_ri.len == 0) {
2197 /* Have asked RQC, but no reply (yet) */
2198 if (t - sr->sr_timer >
2199 ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_timeout) {
2200 /* RQR overdue, resend RQC */
2201 gld_rde_pdu_req(macinfo, q, dhost,
2202 NULL, dsap, ssap, RDE_RQC);
2203 sr->sr_timer = t;
2205 *rhp = NULL; /* we have no route yet */
2206 return;
2209 /* we know a route, or it's local */
2211 /* if it might be stale, reset and get a new one */
2212 if (t - sr->sr_timer >
2213 ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_timeout) {
2214 gld_rde_pdu_req(macinfo, q, dhost,
2215 NULL, dsap, ssap, RDE_RQC);
2216 sr->sr_ri.len = 0;
2217 sr->sr_timer = t;
2218 *rhp = NULL; /* we have no route */
2219 return;
2222 if (sr->sr_ri.len == 2) {
2223 /* the remote site is on our local ring -- no route needed */
2224 *rhp = NULL;
2225 return;
2228 *rhp = &sr->sr_ri; /* we have a route, return it */
2232 * zap the specified entry and reinitiate RQC
2234 static void
2235 gld_reset_route(gld_mac_info_t *macinfo, queue_t *q,
2236 uchar_t *dhost, uchar_t dsap, uchar_t ssap)
2238 struct srtab *sr;
2240 ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo)));
2242 sr = gld_sr_create_entry(macinfo, dhost);
2243 gld_rde_pdu_req(macinfo, q, dhost, NULL,
2244 dsap, ssap, RDE_RQC);
2245 if (sr == NULL)
2246 return;
2248 sr->sr_ri.len = 0;
2249 sr->sr_timer = ddi_get_lbolt();
2253 * This routine is called when an RDE PDU is received from our peer.
2254 * If it is an RS (Route Selected) PDU, we adopt the specified route.
2255 * If it is an RQR (reply to our previous RQC), we evaluate the
2256 * specified route in comparison with our current known route, if any,
2257 * and we keep the "better" of the two routes.
2259 static void
2260 gld_rde_pdu_ind(gld_mac_info_t *macinfo, struct gld_ri *rh, struct rde_pdu *pdu,
2261 int pdulen)
2263 struct srtab *sr;
2264 uchar_t *otherhost;
2266 if (pdulen < sizeof (struct rde_pdu))
2267 return; /* Bad incoming PDU */
2269 if (pdu->rde_ptype == RDE_RQC)
2270 return; /* ignore RQC */
2272 if (pdu->rde_ptype != RDE_RQR && pdu->rde_ptype != RDE_RS) {
2273 #ifdef GLD_DEBUG
2274 if (gld_debug & GLDERRS)
2275 cmn_err(CE_WARN, "gld: bogus RDE ptype 0x%x received",
2276 pdu->rde_ptype);
2277 #endif
2278 return;
2281 if (rh == NULL) {
2282 #ifdef GLD_DEBUG
2283 if (gld_debug & GLDERRS)
2284 cmn_err(CE_WARN,
2285 "gld: bogus NULL RIF, ptype 0x%x received",
2286 pdu->rde_ptype);
2287 #endif
2288 return;
2291 ASSERT(rh->len >= 2);
2292 ASSERT(rh->len <= sizeof (struct gld_ri));
2293 ASSERT((rh->len & 1) == 0);
2295 if (pdu->rde_ptype == RDE_RQR) {
2296 /* A reply to our RQC has its address as target mac */
2297 otherhost = pdu->rde_target_mac;
2298 } else {
2299 ASSERT(pdu->rde_ptype == RDE_RS);
2300 /* An RS has its address as orig mac */
2301 otherhost = pdu->rde_orig_mac;
2304 mutex_enter(GLD_SR_MUTEX(macinfo));
2306 if ((sr = gld_sr_create_entry(macinfo, otherhost)) == NULL) {
2307 mutex_exit(GLD_SR_MUTEX(macinfo));
2308 return; /* oh well, out of memory */
2311 if (pdu->rde_ptype == RDE_RQR) {
2312 /* see if new route is better than what we may already have */
2313 if (sr->sr_ri.len != 0 &&
2314 sr->sr_ri.len <= rh->len) {
2315 mutex_exit(GLD_SR_MUTEX(macinfo));
2316 return; /* we have one, and new one is no shorter */
2320 /* adopt the new route */
2321 bcopy((caddr_t)rh, (caddr_t)&sr->sr_ri, rh->len); /* copy incom RIF */
2322 sr->sr_ri.rt = RT_SRF; /* make it a clean SRF */
2323 sr->sr_ri.dir ^= 1; /* reverse direction */
2324 sr->sr_timer = ddi_get_lbolt();
2326 mutex_exit(GLD_SR_MUTEX(macinfo));
2330 * This routine is called when a packet with a RIF is received. Our
2331 * policy is to adopt the route.
2333 /* ARGSUSED3 */
2334 static void
2335 gld_rif_ind(gld_mac_info_t *macinfo, struct gld_ri *rh, uchar_t *shost,
2336 uchar_t ssap, uchar_t dsap)
2338 struct srtab *sr;
2340 ASSERT(rh != NULL); /* ensure RIF */
2341 ASSERT((rh->rt & 0x04) == 0); /* ensure SRF */
2342 ASSERT(rh->len >= 2);
2343 ASSERT(rh->len <= sizeof (struct gld_ri));
2344 ASSERT((rh->len & 1) == 0);
2346 mutex_enter(GLD_SR_MUTEX(macinfo));
2348 if ((sr = gld_sr_create_entry(macinfo, shost)) == NULL) {
2349 mutex_exit(GLD_SR_MUTEX(macinfo));
2350 return; /* oh well, out of memory */
2353 /* we have an entry; fill it in */
2354 bcopy((caddr_t)rh, (caddr_t)&sr->sr_ri, rh->len); /* copy incom RIF */
2355 sr->sr_ri.rt = RT_SRF; /* make it a clean SRF */
2356 sr->sr_ri.dir ^= 1; /* reverse direction */
2357 sr->sr_timer = ddi_get_lbolt();
2359 mutex_exit(GLD_SR_MUTEX(macinfo));
2362 static struct srtab **
2363 gld_sr_hash(struct srtab **sr_hash_tbl, uchar_t *addr, int addr_length)
2365 uint_t hashval = 0;
2367 while (--addr_length >= 0)
2368 hashval ^= *addr++;
2370 return (&sr_hash_tbl[hashval % SR_HASH_SIZE]);
2373 static struct srtab *
2374 gld_sr_lookup_entry(gld_mac_info_t *macinfo, uchar_t *macaddr)
2376 struct srtab *sr;
2378 ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo)));
2380 for (sr = *gld_sr_hash(GLD_SR_HASH(macinfo), macaddr,
2381 macinfo->gldm_addrlen); sr; sr = sr->sr_next)
2382 if (mac_eq(macaddr, sr->sr_mac, macinfo->gldm_addrlen))
2383 return (sr);
2385 return (NULL);
2388 static struct srtab *
2389 gld_sr_create_entry(gld_mac_info_t *macinfo, uchar_t *macaddr)
2391 struct srtab *sr;
2392 struct srtab **srp;
2394 ASSERT(!(macaddr[0] & 0x80)); /* no group addresses here */
2395 ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo)));
2397 srp = gld_sr_hash(GLD_SR_HASH(macinfo), macaddr, macinfo->gldm_addrlen);
2399 for (sr = *srp; sr; sr = sr->sr_next)
2400 if (mac_eq(macaddr, sr->sr_mac, macinfo->gldm_addrlen))
2401 return (sr);
2403 if (!(sr = kmem_zalloc(sizeof (struct srtab), KM_NOSLEEP))) {
2404 #ifdef GLD_DEBUG
2405 if (gld_debug & GLDERRS)
2406 cmn_err(CE_WARN,
2407 "gld: gld_sr_create_entry kmem_alloc failed");
2408 #endif
2409 return (NULL);
2412 bcopy((caddr_t)macaddr, (caddr_t)sr->sr_mac, macinfo->gldm_addrlen);
2414 sr->sr_next = *srp;
2415 *srp = sr;
2416 return (sr);
2419 static void
2420 gld_sr_clear(gld_mac_info_t *macinfo)
2422 int i;
2423 struct srtab **sr_hash_tbl = GLD_SR_HASH(macinfo);
2424 struct srtab **srp, *sr;
2427 * Walk through the table, deleting all entries.
2429 * Only called from uninit, so don't need the mutex.
2431 for (i = 0; i < SR_HASH_SIZE; i++) {
2432 for (srp = &sr_hash_tbl[i]; (sr = *srp) != NULL; ) {
2433 *srp = sr->sr_next;
2434 kmem_free((char *)sr, sizeof (struct srtab));
2439 #ifdef DEBUG
2440 void
2441 gld_sr_dump(gld_mac_info_t *macinfo)
2443 int i, j;
2444 struct srtab **sr_hash_tbl;
2445 struct srtab *sr;
2447 sr_hash_tbl = GLD_SR_HASH(macinfo);
2448 if (sr_hash_tbl == NULL)
2449 return;
2451 mutex_enter(GLD_SR_MUTEX(macinfo));
2454 * Walk through the table, printing all entries
2456 cmn_err(CE_NOTE, "GLD Source Routing Table (0x%p):", (void *)macinfo);
2457 cmn_err(CE_CONT, "Addr len,rt,dir,mtu,res rng,brg0 rng,brg1...\n");
2458 for (i = 0; i < SR_HASH_SIZE; i++) {
2459 for (sr = sr_hash_tbl[i]; sr; sr = sr->sr_next) {
2460 cmn_err(CE_CONT,
2461 "%x:%x:%x:%x:%x:%x %d,%x,%x,%x,%x ",
2462 sr->sr_mac[0], sr->sr_mac[1], sr->sr_mac[2],
2463 sr->sr_mac[3], sr->sr_mac[4], sr->sr_mac[5],
2464 sr->sr_ri.len, sr->sr_ri.rt, sr->sr_ri.dir,
2465 sr->sr_ri.mtu, sr->sr_ri.res);
2466 if (sr->sr_ri.len)
2467 for (j = 0; j < (sr->sr_ri.len - 2) / 2; j++)
2468 cmn_err(CE_CONT, "%x ",
2469 REF_NET_USHORT(*(unsigned short *)
2470 &sr->sr_ri.rd[j]));
2471 cmn_err(CE_CONT, "\n");
2475 mutex_exit(GLD_SR_MUTEX(macinfo));
2477 #endif