10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*2760Sdg199075 * Common Development and Distribution License (the "License").
6*2760Sdg199075 * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate *
21*2760Sdg199075 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
220Sstevel@tonic-gate * Use is subject to license terms.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
250Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
260Sstevel@tonic-gate
270Sstevel@tonic-gate /*
280Sstevel@tonic-gate * gld - Generic LAN Driver
290Sstevel@tonic-gate * media dependent routines
300Sstevel@tonic-gate */
310Sstevel@tonic-gate
320Sstevel@tonic-gate #include <sys/types.h>
330Sstevel@tonic-gate #include <sys/errno.h>
340Sstevel@tonic-gate #include <sys/stropts.h>
350Sstevel@tonic-gate #include <sys/stream.h>
360Sstevel@tonic-gate #include <sys/kmem.h>
370Sstevel@tonic-gate #include <sys/stat.h>
380Sstevel@tonic-gate #include <sys/modctl.h>
390Sstevel@tonic-gate #include <sys/kstat.h>
400Sstevel@tonic-gate #include <sys/debug.h>
410Sstevel@tonic-gate
420Sstevel@tonic-gate #include <sys/byteorder.h>
430Sstevel@tonic-gate #include <sys/strsun.h>
440Sstevel@tonic-gate #include <sys/dlpi.h>
450Sstevel@tonic-gate #include <sys/ethernet.h>
460Sstevel@tonic-gate #include <sys/multidata.h>
470Sstevel@tonic-gate #include <sys/gld.h>
480Sstevel@tonic-gate #include <sys/gldpriv.h>
490Sstevel@tonic-gate #include <sys/ddi.h>
500Sstevel@tonic-gate #include <sys/sunddi.h>
510Sstevel@tonic-gate #include <sys/sysmacros.h>
520Sstevel@tonic-gate #include <sys/ib/clients/ibd/ibd.h>
530Sstevel@tonic-gate #include <sys/pattr.h>
540Sstevel@tonic-gate
550Sstevel@tonic-gate #define DLSAPLENGTH(macinfo) \
560Sstevel@tonic-gate ((macinfo)->gldm_addrlen + ABS((macinfo)->gldm_saplen))
570Sstevel@tonic-gate
580Sstevel@tonic-gate #ifdef GLD_DEBUG
590Sstevel@tonic-gate extern int gld_debug;
600Sstevel@tonic-gate #endif
610Sstevel@tonic-gate
620Sstevel@tonic-gate extern void gld_bitrevcopy(caddr_t src, caddr_t target, size_t n);
630Sstevel@tonic-gate extern char *gld_macaddr_sprintf(char *, unsigned char *, int);
640Sstevel@tonic-gate extern gld_vlan_t *gld_find_vlan(gld_mac_info_t *, uint32_t);
650Sstevel@tonic-gate extern uint32_t gld_global_options;
660Sstevel@tonic-gate
670Sstevel@tonic-gate static struct llc_snap_hdr llc_snap_def = {
680Sstevel@tonic-gate LSAP_SNAP, /* DLSAP 0xaa */
690Sstevel@tonic-gate LSAP_SNAP, /* SLSAP 0xaa */
700Sstevel@tonic-gate CNTL_LLC_UI, /* Control 0x03 */
710Sstevel@tonic-gate 0x00, 0x00, 0x00, /* Org[3] */
720Sstevel@tonic-gate 0x00 /* Type */
730Sstevel@tonic-gate };
740Sstevel@tonic-gate
750Sstevel@tonic-gate #define ISETHERTYPE(snaphdr) \
760Sstevel@tonic-gate (snaphdr->d_lsap == LSAP_SNAP && \
770Sstevel@tonic-gate snaphdr->s_lsap == LSAP_SNAP && \
780Sstevel@tonic-gate snaphdr->control == CNTL_LLC_UI && \
790Sstevel@tonic-gate snaphdr->org[0] == 0 && \
800Sstevel@tonic-gate snaphdr->org[1] == 0 && \
810Sstevel@tonic-gate snaphdr->org[2] == 0)
820Sstevel@tonic-gate
830Sstevel@tonic-gate /* ======== */
840Sstevel@tonic-gate /* Ethernet */
850Sstevel@tonic-gate /* ======== */
860Sstevel@tonic-gate
870Sstevel@tonic-gate static mac_addr_t ether_broadcast = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
880Sstevel@tonic-gate
890Sstevel@tonic-gate void
gld_init_ether(gld_mac_info_t * macinfo)900Sstevel@tonic-gate gld_init_ether(gld_mac_info_t *macinfo)
910Sstevel@tonic-gate {
920Sstevel@tonic-gate struct gldkstats *sp =
930Sstevel@tonic-gate ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->kstatp->ks_data;
940Sstevel@tonic-gate
950Sstevel@tonic-gate /* Assumptions we make for this medium */
960Sstevel@tonic-gate ASSERT(macinfo->gldm_type == DL_ETHER);
970Sstevel@tonic-gate ASSERT(macinfo->gldm_addrlen == 6);
980Sstevel@tonic-gate ASSERT(macinfo->gldm_saplen == -2);
990Sstevel@tonic-gate #ifndef lint
100*2760Sdg199075 ASSERT(sizeof (struct ether_header) == 14);
1010Sstevel@tonic-gate ASSERT(sizeof (mac_addr_t) == 6);
1020Sstevel@tonic-gate #endif
1030Sstevel@tonic-gate
1040Sstevel@tonic-gate kstat_named_init(&sp->glds_frame, "align_errors", KSTAT_DATA_ULONG);
1050Sstevel@tonic-gate kstat_named_init(&sp->glds_crc, "fcs_errors", KSTAT_DATA_ULONG);
1060Sstevel@tonic-gate kstat_named_init(&sp->glds_collisions, "collisions", KSTAT_DATA_ULONG);
1070Sstevel@tonic-gate kstat_named_init(&sp->glds_nocarrier, "carrier_errors",
1080Sstevel@tonic-gate KSTAT_DATA_ULONG);
1090Sstevel@tonic-gate kstat_named_init(&sp->glds_defer, "defer_xmts", KSTAT_DATA_ULONG);
1100Sstevel@tonic-gate kstat_named_init(&sp->glds_xmtlatecoll, "tx_late_collisions",
1110Sstevel@tonic-gate KSTAT_DATA_ULONG);
1120Sstevel@tonic-gate kstat_named_init(&sp->glds_short, "runt_errors", KSTAT_DATA_ULONG);
1130Sstevel@tonic-gate kstat_named_init(&sp->glds_excoll, "ex_collisions", KSTAT_DATA_ULONG);
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate /*
1160Sstevel@tonic-gate * only initialize the new statistics if the driver
1170Sstevel@tonic-gate * knows about them.
1180Sstevel@tonic-gate */
1190Sstevel@tonic-gate if (macinfo->gldm_driver_version != GLD_VERSION_200)
1200Sstevel@tonic-gate return;
1210Sstevel@tonic-gate
1220Sstevel@tonic-gate kstat_named_init(&sp->glds_dot3_first_coll,
1230Sstevel@tonic-gate "first_collisions", KSTAT_DATA_UINT32);
1240Sstevel@tonic-gate kstat_named_init(&sp->glds_dot3_multi_coll,
1250Sstevel@tonic-gate "multi_collisions", KSTAT_DATA_UINT32);
1260Sstevel@tonic-gate kstat_named_init(&sp->glds_dot3_sqe_error,
1270Sstevel@tonic-gate "sqe_errors", KSTAT_DATA_UINT32);
1280Sstevel@tonic-gate kstat_named_init(&sp->glds_dot3_mac_xmt_error,
1290Sstevel@tonic-gate "macxmt_errors", KSTAT_DATA_UINT32);
1300Sstevel@tonic-gate kstat_named_init(&sp->glds_dot3_mac_rcv_error,
1310Sstevel@tonic-gate "macrcv_errors", KSTAT_DATA_UINT32);
1320Sstevel@tonic-gate kstat_named_init(&sp->glds_dot3_frame_too_long,
1330Sstevel@tonic-gate "toolong_errors", KSTAT_DATA_UINT32);
1340Sstevel@tonic-gate kstat_named_init(&sp->glds_duplex, "duplex", KSTAT_DATA_CHAR);
1350Sstevel@tonic-gate }
1360Sstevel@tonic-gate
1370Sstevel@tonic-gate /*ARGSUSED*/
1380Sstevel@tonic-gate void
gld_uninit_ether(gld_mac_info_t * macinfo)1390Sstevel@tonic-gate gld_uninit_ether(gld_mac_info_t *macinfo)
1400Sstevel@tonic-gate {
1410Sstevel@tonic-gate }
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate int
gld_interpret_ether(gld_mac_info_t * macinfo,mblk_t * mp,pktinfo_t * pktinfo,packet_flag_t flags)1440Sstevel@tonic-gate gld_interpret_ether(gld_mac_info_t *macinfo, mblk_t *mp, pktinfo_t *pktinfo,
1450Sstevel@tonic-gate packet_flag_t flags)
1460Sstevel@tonic-gate {
147*2760Sdg199075 struct ether_header *mh;
1480Sstevel@tonic-gate gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
1490Sstevel@tonic-gate struct llc_snap_hdr *snaphdr;
150*2760Sdg199075 mblk_t *pmp = NULL, *savemp = mp;
1510Sstevel@tonic-gate unsigned short typelen;
152*2760Sdg199075 int ret = 0;
1530Sstevel@tonic-gate
1540Sstevel@tonic-gate /*
1550Sstevel@tonic-gate * Quickly handle receive fastpath for IPQ hack.
1560Sstevel@tonic-gate */
1570Sstevel@tonic-gate if (flags == GLD_RXQUICK) {
1580Sstevel@tonic-gate pktinfo->pktLen = msgdsize(mp);
1590Sstevel@tonic-gate /*
1600Sstevel@tonic-gate * Check whether the header is contiguous, which
1610Sstevel@tonic-gate * also implicitly makes sure the packet is big enough.
1620Sstevel@tonic-gate */
163*2760Sdg199075 if (MBLKL(mp) < sizeof (struct ether_header))
1640Sstevel@tonic-gate return (-1);
165*2760Sdg199075 mh = (struct ether_header *)mp->b_rptr;
1660Sstevel@tonic-gate pktinfo->ethertype = REF_NET_USHORT(mh->ether_type);
167*2760Sdg199075 pktinfo->isForMe = mac_eq(&mh->ether_dhost,
1680Sstevel@tonic-gate mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
169*2760Sdg199075 pktinfo->macLen = sizeof (struct ether_header);
1700Sstevel@tonic-gate
1710Sstevel@tonic-gate return (0);
1720Sstevel@tonic-gate }
1730Sstevel@tonic-gate
1740Sstevel@tonic-gate bzero((void *)pktinfo, sizeof (*pktinfo));
1750Sstevel@tonic-gate
1760Sstevel@tonic-gate pktinfo->pktLen = msgdsize(mp);
1770Sstevel@tonic-gate
1780Sstevel@tonic-gate /* make sure packet has at least a whole mac header */
179*2760Sdg199075 if (pktinfo->pktLen < sizeof (struct ether_header))
1800Sstevel@tonic-gate return (-1);
1810Sstevel@tonic-gate
1820Sstevel@tonic-gate /* make sure the mac header falls into contiguous memory */
183*2760Sdg199075 if (MBLKL(mp) < sizeof (struct ether_header)) {
1840Sstevel@tonic-gate if ((pmp = msgpullup(mp, -1)) == NULL) {
1850Sstevel@tonic-gate #ifdef GLD_DEBUG
1860Sstevel@tonic-gate if (gld_debug & GLDERRS)
1870Sstevel@tonic-gate cmn_err(CE_WARN,
1880Sstevel@tonic-gate "GLD: interpret_ether cannot msgpullup");
1890Sstevel@tonic-gate #endif
1900Sstevel@tonic-gate return (-1);
1910Sstevel@tonic-gate }
1920Sstevel@tonic-gate mp = pmp; /* this mblk contains the whole mac header */
1930Sstevel@tonic-gate }
1940Sstevel@tonic-gate
195*2760Sdg199075 mh = (struct ether_header *)mp->b_rptr;
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate /* Check to see if the mac is a broadcast or multicast address. */
198*2760Sdg199075 if (mac_eq(&mh->ether_dhost, ether_broadcast, macinfo->gldm_addrlen))
1990Sstevel@tonic-gate pktinfo->isBroadcast = 1;
200*2760Sdg199075 else if (mh->ether_dhost.ether_addr_octet[0] & 1)
2010Sstevel@tonic-gate pktinfo->isMulticast = 1;
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate typelen = REF_NET_USHORT(mh->ether_type);
2040Sstevel@tonic-gate /*
2050Sstevel@tonic-gate * If the hardware is capable of VLAN tag insertion
2060Sstevel@tonic-gate * strip out the VLAN tag info. Knowing hardware is
2070Sstevel@tonic-gate * capable of VLAN can be established by the presance
2080Sstevel@tonic-gate * of non null 'macinfo->gldm_send_tagged'.
2090Sstevel@tonic-gate */
2100Sstevel@tonic-gate if (flags == GLD_TX) {
211*2760Sdg199075 if ((typelen == ETHERTYPE_VLAN) &&
212*2760Sdg199075 (macinfo->gldm_send_tagged != NULL)) {
213*2760Sdg199075 struct ether_vlan_header *evhp;
214*2760Sdg199075 uint16_t tci;
215*2760Sdg199075
216*2760Sdg199075 if ((MBLKL(mp) < sizeof (struct ether_vlan_header)) &&
217*2760Sdg199075 (pullupmsg(mp, sizeof (struct ether_vlan_header))
218*2760Sdg199075 == 0)) {
219*2760Sdg199075 ret = -1;
220*2760Sdg199075 goto out;
221*2760Sdg199075 }
222*2760Sdg199075 evhp = (struct ether_vlan_header *)mp->b_rptr;
223*2760Sdg199075 tci = REF_NET_USHORT(evhp->ether_tci);
224*2760Sdg199075
225*2760Sdg199075 /*
226*2760Sdg199075 * We don't allow the VID and priority are both zero.
227*2760Sdg199075 */
228*2760Sdg199075 if ((GLD_VTAG_PRI((int32_t)tci) == 0 &&
229*2760Sdg199075 GLD_VTAG_VID((int32_t)tci) == VLAN_VID_NONE) ||
230*2760Sdg199075 (GLD_VTAG_CFI((uint32_t)tci)) != VLAN_CFI_ETHER) {
231*2760Sdg199075 ret = -1;
232*2760Sdg199075 goto out;
233*2760Sdg199075 }
234*2760Sdg199075
235*2760Sdg199075 /*
236*2760Sdg199075 * Remember the VTAG info in order to reinsert it,
237*2760Sdg199075 * Then strip the tag. This is required because some
238*2760Sdg199075 * drivers do not allow the size of message (passed
239*2760Sdg199075 * by the gldm_send_tagged() function) to be greater
240*2760Sdg199075 * than ETHERMAX.
241*2760Sdg199075 */
242*2760Sdg199075 GLD_SAVE_MBLK_VTAG(savemp, GLD_TCI2VTAG(tci));
243*2760Sdg199075 ovbcopy(mp->b_rptr, mp->b_rptr + VTAG_SIZE,
244*2760Sdg199075 2 * ETHERADDRL);
2450Sstevel@tonic-gate mp->b_rptr += VTAG_SIZE;
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate goto out; /* Got all info we need for xmit case */
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate
2500Sstevel@tonic-gate ASSERT(GLDM_LOCK_HELD(macinfo));
2510Sstevel@tonic-gate
2520Sstevel@tonic-gate /*
2530Sstevel@tonic-gate * Deal with the mac header
2540Sstevel@tonic-gate */
2550Sstevel@tonic-gate
256*2760Sdg199075 mac_copy(&mh->ether_dhost, pktinfo->dhost, macinfo->gldm_addrlen);
257*2760Sdg199075 mac_copy(&mh->ether_shost, pktinfo->shost, macinfo->gldm_addrlen);
2580Sstevel@tonic-gate
2590Sstevel@tonic-gate pktinfo->isLooped = mac_eq(pktinfo->shost,
2600Sstevel@tonic-gate mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
2610Sstevel@tonic-gate pktinfo->isForMe = mac_eq(pktinfo->dhost,
2620Sstevel@tonic-gate mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
2630Sstevel@tonic-gate
264*2760Sdg199075 pktinfo->macLen = sizeof (struct ether_header);
2650Sstevel@tonic-gate
2660Sstevel@tonic-gate if (typelen > ETHERMTU) {
2670Sstevel@tonic-gate pktinfo->ethertype = typelen; /* use type interpretation */
2680Sstevel@tonic-gate goto out;
2690Sstevel@tonic-gate }
2700Sstevel@tonic-gate
2710Sstevel@tonic-gate /*
2720Sstevel@tonic-gate * Packet is 802.3 so the ether type/length field
2730Sstevel@tonic-gate * specifies the number of bytes that should be present
2740Sstevel@tonic-gate * in the data field. Additional bytes are padding, and
2750Sstevel@tonic-gate * should be removed
2760Sstevel@tonic-gate */
2770Sstevel@tonic-gate {
2780Sstevel@tonic-gate int delta = pktinfo->pktLen -
279*2760Sdg199075 (sizeof (struct ether_header) + typelen);
2800Sstevel@tonic-gate
2810Sstevel@tonic-gate if (delta > 0 && adjmsg(mp, -delta))
2820Sstevel@tonic-gate pktinfo->pktLen -= delta;
2830Sstevel@tonic-gate }
2840Sstevel@tonic-gate
2850Sstevel@tonic-gate /*
2860Sstevel@tonic-gate * Before trying to look beyond the MAC header, make sure the LLC
2870Sstevel@tonic-gate * header exists, and that both it and any SNAP header are contiguous.
2880Sstevel@tonic-gate */
2890Sstevel@tonic-gate if (pktinfo->pktLen < pktinfo->macLen + LLC_HDR1_LEN)
2900Sstevel@tonic-gate goto out; /* LLC hdr should have been there! */
2910Sstevel@tonic-gate
2920Sstevel@tonic-gate pktinfo->isLLC = 1;
2930Sstevel@tonic-gate
2940Sstevel@tonic-gate if (gld_global_options & GLD_OPT_NO_ETHRXSNAP ||
295*2760Sdg199075 pktinfo->pktLen < pktinfo->macLen + LLC_SNAP_HDR_LEN)
2960Sstevel@tonic-gate goto out;
2970Sstevel@tonic-gate
298*2760Sdg199075 if (MBLKL(mp) < sizeof (struct ether_header) + LLC_SNAP_HDR_LEN &&
2990Sstevel@tonic-gate MBLKL(mp) < pktinfo->pktLen) {
3000Sstevel@tonic-gate /*
3010Sstevel@tonic-gate * we don't have the entire packet within the first mblk (and
3020Sstevel@tonic-gate * therefore we didn't do the msgpullup above), AND the first
3030Sstevel@tonic-gate * mblk may not contain all the data we need to look at.
3040Sstevel@tonic-gate */
3050Sstevel@tonic-gate ASSERT(pmp == NULL); /* couldn't have done msgpullup above */
3060Sstevel@tonic-gate if ((pmp = msgpullup(mp, -1)) == NULL) {
3070Sstevel@tonic-gate #ifdef GLD_DEBUG
3080Sstevel@tonic-gate if (gld_debug & GLDERRS)
3090Sstevel@tonic-gate cmn_err(CE_WARN,
3100Sstevel@tonic-gate "GLD: interpret_ether cannot msgpullup2");
3110Sstevel@tonic-gate #endif
3120Sstevel@tonic-gate goto out; /* can't interpret this pkt further */
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate mp = pmp; /* this mblk should contain everything needed */
3150Sstevel@tonic-gate }
3160Sstevel@tonic-gate
3170Sstevel@tonic-gate /*
3180Sstevel@tonic-gate * Check SAP/SNAP information for EtherType.
3190Sstevel@tonic-gate */
3200Sstevel@tonic-gate
3210Sstevel@tonic-gate snaphdr = (struct llc_snap_hdr *)(mp->b_rptr + pktinfo->macLen);
3220Sstevel@tonic-gate if (ISETHERTYPE(snaphdr)) {
3230Sstevel@tonic-gate pktinfo->ethertype = REF_NET_USHORT(snaphdr->type);
3240Sstevel@tonic-gate pktinfo->hdrLen = LLC_SNAP_HDR_LEN;
3250Sstevel@tonic-gate }
3260Sstevel@tonic-gate out:
3270Sstevel@tonic-gate if (pmp != NULL)
3280Sstevel@tonic-gate freemsg(pmp);
3290Sstevel@tonic-gate
330*2760Sdg199075 return (ret);
3310Sstevel@tonic-gate }
3320Sstevel@tonic-gate
3330Sstevel@tonic-gate mblk_t *
gld_unitdata_ether(gld_t * gld,mblk_t * mp)3340Sstevel@tonic-gate gld_unitdata_ether(gld_t *gld, mblk_t *mp)
3350Sstevel@tonic-gate {
3360Sstevel@tonic-gate gld_mac_info_t *macinfo = gld->gld_mac_info;
3370Sstevel@tonic-gate dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_rptr;
3380Sstevel@tonic-gate struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
3390Sstevel@tonic-gate mac_addr_t dhost;
3400Sstevel@tonic-gate unsigned short typelen;
3410Sstevel@tonic-gate mblk_t *nmp;
342*2760Sdg199075 struct ether_header *mh;
3430Sstevel@tonic-gate int hdrlen;
3440Sstevel@tonic-gate uint32_t vptag;
3450Sstevel@tonic-gate gld_vlan_t *gld_vlan;
3460Sstevel@tonic-gate
3470Sstevel@tonic-gate ASSERT(macinfo);
3480Sstevel@tonic-gate
3490Sstevel@tonic-gate /* extract needed info from the mblk before we maybe reuse it */
3500Sstevel@tonic-gate mac_copy(gldp->glda_addr, dhost, macinfo->gldm_addrlen);
3510Sstevel@tonic-gate
3520Sstevel@tonic-gate /* look in the unitdata request for a sap, else use bound one */
3530Sstevel@tonic-gate if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
3540Sstevel@tonic-gate REF_HOST_USHORT(gldp->glda_sap) != 0)
3550Sstevel@tonic-gate typelen = REF_HOST_USHORT(gldp->glda_sap);
3560Sstevel@tonic-gate else
3570Sstevel@tonic-gate typelen = gld->gld_sap;
3580Sstevel@tonic-gate
3590Sstevel@tonic-gate /*
3600Sstevel@tonic-gate * We take values less than or equal to ETHERMTU to mean that the
3610Sstevel@tonic-gate * packet should not have an encoded EtherType and so we use the
3620Sstevel@tonic-gate * IEEE 802.3 length interpretation of the type/length field.
3630Sstevel@tonic-gate */
3640Sstevel@tonic-gate if (typelen <= ETHERMTU)
3650Sstevel@tonic-gate typelen = msgdsize(mp);
3660Sstevel@tonic-gate
367*2760Sdg199075 hdrlen = sizeof (struct ether_header);
3680Sstevel@tonic-gate
3690Sstevel@tonic-gate /*
3700Sstevel@tonic-gate * Check to see if VLAN is enabled on this stream
3710Sstevel@tonic-gate * if so then make the header bigger to hold a clone
3720Sstevel@tonic-gate * vlan tag.
3730Sstevel@tonic-gate */
3740Sstevel@tonic-gate gld_vlan = (gld_vlan_t *)gld->gld_vlan;
3750Sstevel@tonic-gate if (gld_vlan && (gld_vlan->gldv_id != VLAN_VID_NONE)) {
3760Sstevel@tonic-gate hdrlen += VTAG_SIZE;
3770Sstevel@tonic-gate vptag = gld_vlan->gldv_ptag;
3780Sstevel@tonic-gate }
3790Sstevel@tonic-gate
3800Sstevel@tonic-gate /* need a buffer big enough for the headers */
3810Sstevel@tonic-gate nmp = mp->b_cont; /* where the packet payload M_DATA is */
3820Sstevel@tonic-gate if (DB_REF(nmp) == 1 && MBLKHEAD(nmp) >= hdrlen) {
3830Sstevel@tonic-gate /* it fits at the beginning of the first M_DATA block */
3840Sstevel@tonic-gate freeb(mp); /* don't need the M_PROTO anymore */
3850Sstevel@tonic-gate } else if (DB_REF(mp) == 1 && MBLKSIZE(mp) >= hdrlen) {
3860Sstevel@tonic-gate /* we can reuse the dl_unitdata_req M_PROTO mblk */
3870Sstevel@tonic-gate nmp = mp;
3880Sstevel@tonic-gate DB_TYPE(nmp) = M_DATA;
3890Sstevel@tonic-gate nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
3900Sstevel@tonic-gate } else {
3910Sstevel@tonic-gate /* we need to allocate one */
3920Sstevel@tonic-gate if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
3930Sstevel@tonic-gate return (NULL);
3940Sstevel@tonic-gate nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
3950Sstevel@tonic-gate linkb(nmp, mp->b_cont);
3960Sstevel@tonic-gate freeb(mp);
3970Sstevel@tonic-gate }
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate /* Got the space, now copy in the header components */
4000Sstevel@tonic-gate
4010Sstevel@tonic-gate nmp->b_rptr -= sizeof (typelen);
4020Sstevel@tonic-gate SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, typelen);
403*2760Sdg199075 if (hdrlen > sizeof (struct ether_header)) {
4040Sstevel@tonic-gate nmp->b_rptr -= sizeof (uint16_t);
4050Sstevel@tonic-gate SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, vptag);
4060Sstevel@tonic-gate vptag >>= 16;
4070Sstevel@tonic-gate nmp->b_rptr -= sizeof (uint16_t);
4080Sstevel@tonic-gate SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, vptag);
4090Sstevel@tonic-gate }
4100Sstevel@tonic-gate nmp->b_rptr -= (ETHERADDRL * 2);
411*2760Sdg199075 mh = (struct ether_header *)nmp->b_rptr;
412*2760Sdg199075 mac_copy(dhost, &mh->ether_dhost, macinfo->gldm_addrlen);
4130Sstevel@tonic-gate
4140Sstevel@tonic-gate /*
4150Sstevel@tonic-gate * We access the mac address without the mutex to prevent
4160Sstevel@tonic-gate * mutex contention (BUG 4211361)
4170Sstevel@tonic-gate */
4180Sstevel@tonic-gate mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
419*2760Sdg199075 &mh->ether_shost, macinfo->gldm_addrlen);
420*2760Sdg199075
421*2760Sdg199075 return (nmp);
422*2760Sdg199075 }
423*2760Sdg199075
424*2760Sdg199075 /*
425*2760Sdg199075 * Insert the VLAN tag into the packet. The packet now is an Ethernet header
426*2760Sdg199075 * without VLAN tag information.
427*2760Sdg199075 */
428*2760Sdg199075 mblk_t *
gld_insert_vtag_ether(mblk_t * mp,uint32_t vtag)429*2760Sdg199075 gld_insert_vtag_ether(mblk_t *mp, uint32_t vtag)
430*2760Sdg199075 {
431*2760Sdg199075 struct ether_vlan_header *evhp;
432*2760Sdg199075 struct ether_header *ehp;
433*2760Sdg199075 mblk_t *nmp;
434*2760Sdg199075
435*2760Sdg199075 if (vtag == VLAN_VID_NONE)
436*2760Sdg199075 return (mp);
4370Sstevel@tonic-gate
438*2760Sdg199075 if (DB_REF(mp) == 1 && MBLKHEAD(mp) >= VTAG_SIZE) {
439*2760Sdg199075 /* it fits at the beginning of the message block */
440*2760Sdg199075 nmp = mp;
441*2760Sdg199075 ovbcopy(nmp->b_rptr, nmp->b_rptr - VTAG_SIZE, 2 * ETHERADDRL);
442*2760Sdg199075 nmp->b_rptr -= VTAG_SIZE;
443*2760Sdg199075 evhp = (struct ether_vlan_header *)nmp->b_rptr;
444*2760Sdg199075 } else {
445*2760Sdg199075 /* we need to allocate one */
446*2760Sdg199075 if ((nmp = allocb(sizeof (struct ether_vlan_header),
447*2760Sdg199075 BPRI_MED)) == NULL) {
448*2760Sdg199075 return (NULL);
449*2760Sdg199075 }
450*2760Sdg199075 nmp->b_wptr += sizeof (struct ether_vlan_header);
451*2760Sdg199075
452*2760Sdg199075 /* transfer the ether_header fields */
453*2760Sdg199075 evhp = (struct ether_vlan_header *)nmp->b_rptr;
454*2760Sdg199075 ehp = (struct ether_header *)mp->b_rptr;
455*2760Sdg199075 mac_copy(&ehp->ether_dhost, &evhp->ether_dhost, ETHERADDRL);
456*2760Sdg199075 mac_copy(&ehp->ether_shost, &evhp->ether_shost, ETHERADDRL);
457*2760Sdg199075 bcopy(&ehp->ether_type, &evhp->ether_type, sizeof (uint16_t));
458*2760Sdg199075
459*2760Sdg199075 /* offset the mp of the MAC header length. */
460*2760Sdg199075 mp->b_rptr += sizeof (struct ether_header);
461*2760Sdg199075 if (MBLKL(mp) == 0) {
462*2760Sdg199075 nmp->b_cont = mp->b_cont;
463*2760Sdg199075 freeb(mp);
464*2760Sdg199075 } else {
465*2760Sdg199075 nmp->b_cont = mp;
466*2760Sdg199075 }
467*2760Sdg199075 }
468*2760Sdg199075
469*2760Sdg199075 SET_NET_USHORT(evhp->ether_tci, vtag);
470*2760Sdg199075 vtag >>= 16;
471*2760Sdg199075 SET_NET_USHORT(evhp->ether_tpid, vtag);
4720Sstevel@tonic-gate return (nmp);
4730Sstevel@tonic-gate }
4740Sstevel@tonic-gate
4750Sstevel@tonic-gate mblk_t *
gld_fastpath_ether(gld_t * gld,mblk_t * mp)4760Sstevel@tonic-gate gld_fastpath_ether(gld_t *gld, mblk_t *mp)
4770Sstevel@tonic-gate {
4780Sstevel@tonic-gate gld_mac_info_t *macinfo = gld->gld_mac_info;
4790Sstevel@tonic-gate dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
4800Sstevel@tonic-gate struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
4810Sstevel@tonic-gate unsigned short typelen;
4820Sstevel@tonic-gate mblk_t *nmp;
483*2760Sdg199075 struct ether_header *mh;
4840Sstevel@tonic-gate int hdrlen;
4850Sstevel@tonic-gate uint32_t vptag;
4860Sstevel@tonic-gate gld_vlan_t *gld_vlan;
4870Sstevel@tonic-gate
4880Sstevel@tonic-gate ASSERT(macinfo);
4890Sstevel@tonic-gate
4900Sstevel@tonic-gate /* look in the unitdata request for a sap, else use bound one */
4910Sstevel@tonic-gate if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
4920Sstevel@tonic-gate REF_HOST_USHORT(gldp->glda_sap) != 0)
4930Sstevel@tonic-gate typelen = REF_HOST_USHORT(gldp->glda_sap);
4940Sstevel@tonic-gate else
4950Sstevel@tonic-gate typelen = gld->gld_sap;
4960Sstevel@tonic-gate
4970Sstevel@tonic-gate /*
4980Sstevel@tonic-gate * We only do fast-path for EtherType encoding because this is the only
4990Sstevel@tonic-gate * case where the media header will be consistent from packet to packet.
5000Sstevel@tonic-gate */
5010Sstevel@tonic-gate if (typelen <= ETHERMTU)
5020Sstevel@tonic-gate return (NULL);
5030Sstevel@tonic-gate
5040Sstevel@tonic-gate /*
5050Sstevel@tonic-gate * Initialize the fast path header to include the
5060Sstevel@tonic-gate * basic source address information and type field.
5070Sstevel@tonic-gate */
508*2760Sdg199075 hdrlen = sizeof (struct ether_header);
5090Sstevel@tonic-gate
5100Sstevel@tonic-gate /*
5110Sstevel@tonic-gate * Check to see if VLAN is enabled on this stream
5120Sstevel@tonic-gate * if so then make the header bigger to hold a clone
5130Sstevel@tonic-gate * vlan tag.
5140Sstevel@tonic-gate */
5150Sstevel@tonic-gate gld_vlan = (gld_vlan_t *)gld->gld_vlan;
5160Sstevel@tonic-gate if (gld_vlan && (gld_vlan->gldv_id != VLAN_VID_NONE)) {
5170Sstevel@tonic-gate hdrlen += VTAG_SIZE;
5180Sstevel@tonic-gate vptag = gld_vlan->gldv_ptag;
5190Sstevel@tonic-gate }
5200Sstevel@tonic-gate
5210Sstevel@tonic-gate if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
5220Sstevel@tonic-gate return (NULL);
5230Sstevel@tonic-gate
5240Sstevel@tonic-gate nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
5250Sstevel@tonic-gate
5260Sstevel@tonic-gate /* Got the space, now copy in the header components */
5270Sstevel@tonic-gate
5280Sstevel@tonic-gate nmp->b_rptr -= sizeof (typelen);
5290Sstevel@tonic-gate SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, typelen);
5300Sstevel@tonic-gate
5310Sstevel@tonic-gate /*
5320Sstevel@tonic-gate * If the header is for a VLAN stream, then add
5330Sstevel@tonic-gate * in the VLAN tag to the clone header.
5340Sstevel@tonic-gate */
535*2760Sdg199075 if (hdrlen > sizeof (struct ether_header)) {
5360Sstevel@tonic-gate nmp->b_rptr -= sizeof (uint16_t);
5370Sstevel@tonic-gate SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, vptag);
5380Sstevel@tonic-gate vptag >>= 16;
5390Sstevel@tonic-gate nmp->b_rptr -= sizeof (uint16_t);
5400Sstevel@tonic-gate SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, vptag);
5410Sstevel@tonic-gate }
5420Sstevel@tonic-gate nmp->b_rptr -= (ETHERADDRL * 2);
543*2760Sdg199075 mh = (struct ether_header *)nmp->b_rptr;
544*2760Sdg199075 mac_copy(gldp->glda_addr, &mh->ether_dhost, macinfo->gldm_addrlen);
5450Sstevel@tonic-gate
5460Sstevel@tonic-gate GLDM_LOCK(macinfo, RW_WRITER);
5470Sstevel@tonic-gate mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
548*2760Sdg199075 &mh->ether_shost, macinfo->gldm_addrlen);
5490Sstevel@tonic-gate GLDM_UNLOCK(macinfo);
5500Sstevel@tonic-gate
5510Sstevel@tonic-gate return (nmp);
5520Sstevel@tonic-gate }
5530Sstevel@tonic-gate
5540Sstevel@tonic-gate /* == */
5550Sstevel@tonic-gate /* IB */
5560Sstevel@tonic-gate /* == */
5570Sstevel@tonic-gate
5580Sstevel@tonic-gate void
gld_init_ib(gld_mac_info_t * macinfo)5590Sstevel@tonic-gate gld_init_ib(gld_mac_info_t *macinfo)
5600Sstevel@tonic-gate {
5610Sstevel@tonic-gate /*
5620Sstevel@tonic-gate * Currently, the generic stats maintained by GLD is
5630Sstevel@tonic-gate * sufficient for IPoIB.
5640Sstevel@tonic-gate */
5650Sstevel@tonic-gate
5660Sstevel@tonic-gate /* Assumptions we make for this medium */
5670Sstevel@tonic-gate ASSERT(macinfo->gldm_type == DL_IB);
5680Sstevel@tonic-gate ASSERT(macinfo->gldm_addrlen == IPOIB_ADDRL);
5690Sstevel@tonic-gate ASSERT(macinfo->gldm_saplen == -2);
5700Sstevel@tonic-gate }
5710Sstevel@tonic-gate
5720Sstevel@tonic-gate /* ARGSUSED */
5730Sstevel@tonic-gate void
gld_uninit_ib(gld_mac_info_t * macinfo)5740Sstevel@tonic-gate gld_uninit_ib(gld_mac_info_t *macinfo)
5750Sstevel@tonic-gate {
5760Sstevel@tonic-gate }
5770Sstevel@tonic-gate
5780Sstevel@tonic-gate /*
5790Sstevel@tonic-gate * The packet format sent to the driver is:
5800Sstevel@tonic-gate * IPOIB_ADDRL bytes dest addr :: 2b sap :: 2b 0s :: data
5810Sstevel@tonic-gate * The packet format received from the driver is:
5820Sstevel@tonic-gate * IPOIB_GRH_SIZE bytes pseudo GRH :: 2b sap :: 2b 0s :: data.
5830Sstevel@tonic-gate */
5840Sstevel@tonic-gate int
gld_interpret_ib(gld_mac_info_t * macinfo,mblk_t * mp,pktinfo_t * pktinfo,packet_flag_t flags)5850Sstevel@tonic-gate gld_interpret_ib(gld_mac_info_t *macinfo, mblk_t *mp, pktinfo_t *pktinfo,
5860Sstevel@tonic-gate packet_flag_t flags)
5870Sstevel@tonic-gate {
5880Sstevel@tonic-gate ipoib_pgrh_t *grh;
5890Sstevel@tonic-gate ipoib_ptxhdr_t *gldp;
5900Sstevel@tonic-gate mblk_t *pmp = NULL;
5910Sstevel@tonic-gate gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
5920Sstevel@tonic-gate
5930Sstevel@tonic-gate /*
5940Sstevel@tonic-gate * Quickly handle receive fastpath for IPQ hack.
5950Sstevel@tonic-gate */
5960Sstevel@tonic-gate if (flags == GLD_RXQUICK) {
5970Sstevel@tonic-gate pktinfo->pktLen = msgdsize(mp) - IPOIB_GRH_SIZE;
5980Sstevel@tonic-gate
5990Sstevel@tonic-gate /*
6000Sstevel@tonic-gate * Check whether the header is contiguous, which
6010Sstevel@tonic-gate * also implicitly makes sure the packet is big enough.
6020Sstevel@tonic-gate */
6030Sstevel@tonic-gate if (MBLKL(mp) < (IPOIB_GRH_SIZE + IPOIB_HDRSIZE))
6040Sstevel@tonic-gate return (-1);
6050Sstevel@tonic-gate
6060Sstevel@tonic-gate /*
6070Sstevel@tonic-gate * Almost all times, unicast will not have
6080Sstevel@tonic-gate * a valid pgrh; quickly identify and ask for
6090Sstevel@tonic-gate * IPQ hack optimization only in that case.
6100Sstevel@tonic-gate */
6110Sstevel@tonic-gate grh = (ipoib_pgrh_t *)mp->b_rptr;
6120Sstevel@tonic-gate if (grh->ipoib_vertcflow == 0) {
6130Sstevel@tonic-gate struct ipoib_header *ihp = (struct ipoib_header *)
6140Sstevel@tonic-gate (mp->b_rptr + IPOIB_GRH_SIZE);
6150Sstevel@tonic-gate
6160Sstevel@tonic-gate pktinfo->isForMe = 1;
6170Sstevel@tonic-gate pktinfo->ethertype = REF_NET_USHORT(ihp->ipoib_type);
6180Sstevel@tonic-gate pktinfo->macLen = IPOIB_GRH_SIZE + IPOIB_HDRSIZE;
6190Sstevel@tonic-gate return (0);
6200Sstevel@tonic-gate } else {
6210Sstevel@tonic-gate return (-1);
6220Sstevel@tonic-gate }
6230Sstevel@tonic-gate }
6240Sstevel@tonic-gate
6250Sstevel@tonic-gate /*
6260Sstevel@tonic-gate * Handle the GLD_TX, GLD_RX, GLD_RXLOOP cases now.
6270Sstevel@tonic-gate */
6280Sstevel@tonic-gate ASSERT(flags != GLD_RXQUICK);
6290Sstevel@tonic-gate bzero((void *)pktinfo, sizeof (*pktinfo));
6300Sstevel@tonic-gate
6310Sstevel@tonic-gate if (flags != GLD_RX) {
6320Sstevel@tonic-gate /*
6330Sstevel@tonic-gate * GLD_TX and GLD_RXLOOP cases.
6340Sstevel@tonic-gate */
6350Sstevel@tonic-gate gldp = (ipoib_ptxhdr_t *)mp->b_rptr;
6360Sstevel@tonic-gate pktinfo->pktLen = msgdsize(mp);
6370Sstevel@tonic-gate
6380Sstevel@tonic-gate /* make sure packet has at least a pseudo header */
6390Sstevel@tonic-gate if (pktinfo->pktLen < sizeof (ipoib_ptxhdr_t))
6400Sstevel@tonic-gate return (-1);
6410Sstevel@tonic-gate
6420Sstevel@tonic-gate /* make sure the mac header falls into contiguous memory */
6430Sstevel@tonic-gate if (MBLKL(mp) < sizeof (ipoib_ptxhdr_t)) {
6440Sstevel@tonic-gate if ((pmp = msgpullup(mp, -1)) == NULL) {
6450Sstevel@tonic-gate #ifdef GLD_DEBUG
6460Sstevel@tonic-gate if (gld_debug & GLDERRS)
6470Sstevel@tonic-gate cmn_err(CE_WARN,
6480Sstevel@tonic-gate "GLD: interpret_ib "
6490Sstevel@tonic-gate "cannot msgpullup");
6500Sstevel@tonic-gate #endif
6510Sstevel@tonic-gate return (-1);
6520Sstevel@tonic-gate }
6530Sstevel@tonic-gate /* this mblk contains the whole mac header */
6540Sstevel@tonic-gate mp = pmp;
6550Sstevel@tonic-gate }
6560Sstevel@tonic-gate
6570Sstevel@tonic-gate /*
6580Sstevel@tonic-gate * Check if mac is broadcast or multicast address; all these
6590Sstevel@tonic-gate * types of address have the top 4 bytes as 0x00FFFFFF.
6600Sstevel@tonic-gate */
6610Sstevel@tonic-gate if (mac_eq(&gldp->ipoib_dest, macinfo->gldm_broadcast_addr,
6620Sstevel@tonic-gate sizeof (uint32_t))) {
6630Sstevel@tonic-gate if (mac_eq(&gldp->ipoib_dest,
6640Sstevel@tonic-gate macinfo->gldm_broadcast_addr, IPOIB_ADDRL))
6650Sstevel@tonic-gate pktinfo->isBroadcast = 1;
6660Sstevel@tonic-gate else
6670Sstevel@tonic-gate pktinfo->isMulticast = 1;
6680Sstevel@tonic-gate }
6690Sstevel@tonic-gate
6700Sstevel@tonic-gate /*
6710Sstevel@tonic-gate * Only count bytes we will be sending over the wire
6720Sstevel@tonic-gate * or looping back.
6730Sstevel@tonic-gate */
6740Sstevel@tonic-gate pktinfo->pktLen -= IPOIB_ADDRL;
6750Sstevel@tonic-gate if (flags == GLD_TX)
6760Sstevel@tonic-gate goto out; /* Got all info we need for xmit case */
6770Sstevel@tonic-gate
6780Sstevel@tonic-gate /*
6790Sstevel@tonic-gate * Loopback case: this is a dup'ed message.
6800Sstevel@tonic-gate */
6810Sstevel@tonic-gate mp->b_rptr += IPOIB_ADDRL;
6820Sstevel@tonic-gate mac_copy(&gldp->ipoib_dest, pktinfo->dhost, IPOIB_ADDRL);
6830Sstevel@tonic-gate mac_copy(mac_pvt->curr_macaddr, pktinfo->shost, IPOIB_ADDRL);
6840Sstevel@tonic-gate } else {
6850Sstevel@tonic-gate /*
6860Sstevel@tonic-gate * GLD_RX case; process packet sent from driver.
6870Sstevel@tonic-gate */
6880Sstevel@tonic-gate ipoib_mac_t *mact, *tact;
6890Sstevel@tonic-gate ib_qpn_t dqpn;
6900Sstevel@tonic-gate
6910Sstevel@tonic-gate pktinfo->pktLen = msgdsize(mp);
6920Sstevel@tonic-gate /* make sure packet has at least pgrh and mac header */
6930Sstevel@tonic-gate if (pktinfo->pktLen < (IPOIB_GRH_SIZE + IPOIB_HDRSIZE))
6940Sstevel@tonic-gate return (-1);
6950Sstevel@tonic-gate
6960Sstevel@tonic-gate /* make sure the header falls into contiguous memory */
6970Sstevel@tonic-gate if (MBLKL(mp) < (IPOIB_GRH_SIZE + IPOIB_HDRSIZE)) {
6980Sstevel@tonic-gate if ((pmp = msgpullup(mp, -1)) == NULL) {
6990Sstevel@tonic-gate #ifdef GLD_DEBUG
7000Sstevel@tonic-gate if (gld_debug & GLDERRS)
7010Sstevel@tonic-gate cmn_err(CE_WARN,
7020Sstevel@tonic-gate "GLD: interpret_ib "
7030Sstevel@tonic-gate "cannot msgpullup2");
7040Sstevel@tonic-gate #endif
7050Sstevel@tonic-gate return (-1);
7060Sstevel@tonic-gate }
7070Sstevel@tonic-gate /* this mblk contains the whole mac header */
7080Sstevel@tonic-gate mp = pmp;
7090Sstevel@tonic-gate }
7100Sstevel@tonic-gate
7110Sstevel@tonic-gate grh = (ipoib_pgrh_t *)mp->b_rptr;
7120Sstevel@tonic-gate mp->b_rptr += IPOIB_GRH_SIZE;
7130Sstevel@tonic-gate pktinfo->pktLen -= IPOIB_GRH_SIZE;
7140Sstevel@tonic-gate if (grh->ipoib_vertcflow) {
7150Sstevel@tonic-gate /*
7160Sstevel@tonic-gate * First, copy source address from grh.
7170Sstevel@tonic-gate */
7180Sstevel@tonic-gate mact = (ipoib_mac_t *)pktinfo->shost;
7190Sstevel@tonic-gate mac_copy(&grh->ipoib_sqpn, &mact->ipoib_qpn,
7200Sstevel@tonic-gate IPOIB_ADDRL);
7210Sstevel@tonic-gate
7220Sstevel@tonic-gate /*
7230Sstevel@tonic-gate * Then copy destination address from grh;
7240Sstevel@tonic-gate * first, the 16 bytes of GID.
7250Sstevel@tonic-gate */
7260Sstevel@tonic-gate mact = (ipoib_mac_t *)pktinfo->dhost;
7270Sstevel@tonic-gate mac_copy(&grh->ipoib_dgid_pref,
7280Sstevel@tonic-gate &mact->ipoib_gidpref, IPOIB_ADDRL -
7290Sstevel@tonic-gate sizeof (mact->ipoib_qpn));
7300Sstevel@tonic-gate tact = (ipoib_mac_t *)mac_pvt->curr_macaddr;
7310Sstevel@tonic-gate
7320Sstevel@tonic-gate /* Is this a multicast address */
7330Sstevel@tonic-gate if (*(uchar_t *)(grh->ipoib_dgid_pref) == 0xFF) {
7340Sstevel@tonic-gate /*
7350Sstevel@tonic-gate * Only check for hardware looping in
7360Sstevel@tonic-gate * multicast case. It is assumed higher
7370Sstevel@tonic-gate * layer code (IP) will stop unicast loops;
7380Sstevel@tonic-gate * ie will prevent a transmit to self.
7390Sstevel@tonic-gate */
7400Sstevel@tonic-gate if (bcmp(&grh->ipoib_sqpn, tact,
7410Sstevel@tonic-gate IPOIB_ADDRL) == 0)
7420Sstevel@tonic-gate pktinfo->isLooped = 1;
7430Sstevel@tonic-gate
7440Sstevel@tonic-gate tact = (ipoib_mac_t *)macinfo->
7450Sstevel@tonic-gate gldm_broadcast_addr;
7460Sstevel@tonic-gate if (mac_eq(tact->ipoib_gidpref,
7470Sstevel@tonic-gate grh->ipoib_dgid_pref,
7480Sstevel@tonic-gate IPOIB_ADDRL - sizeof (tact->ipoib_qpn)))
7490Sstevel@tonic-gate pktinfo->isBroadcast = 1;
7500Sstevel@tonic-gate else
7510Sstevel@tonic-gate pktinfo->isMulticast = 1;
7520Sstevel@tonic-gate /*
7530Sstevel@tonic-gate * Now copy the 4 bytes QPN part of the
7540Sstevel@tonic-gate * destination address.
7550Sstevel@tonic-gate */
7560Sstevel@tonic-gate dqpn = htonl(IB_MC_QPN);
7570Sstevel@tonic-gate mac_copy(&dqpn, &mact->ipoib_qpn,
7580Sstevel@tonic-gate sizeof (mact->ipoib_qpn));
7590Sstevel@tonic-gate } else {
7600Sstevel@tonic-gate /*
7610Sstevel@tonic-gate * Now copy the 4 bytes QPN part of the
7620Sstevel@tonic-gate * destination address.
7630Sstevel@tonic-gate */
7640Sstevel@tonic-gate mac_copy(&tact->ipoib_qpn, &mact->ipoib_qpn,
7650Sstevel@tonic-gate sizeof (mact->ipoib_qpn));
7660Sstevel@tonic-gate /*
7670Sstevel@tonic-gate * Any unicast packets received on IBA are
7680Sstevel@tonic-gate * for the node.
7690Sstevel@tonic-gate */
7700Sstevel@tonic-gate pktinfo->isForMe = 1;
7710Sstevel@tonic-gate }
7720Sstevel@tonic-gate } else {
7730Sstevel@tonic-gate /*
7740Sstevel@tonic-gate * It can not be a IBA multicast packet.
7750Sstevel@tonic-gate * Must have been unicast to us. We do not
7760Sstevel@tonic-gate * have shost information, which is used in
7770Sstevel@tonic-gate * gld_addudind(); IP/ARP does not care.
7780Sstevel@tonic-gate */
7790Sstevel@tonic-gate pktinfo->nosource = 1;
7800Sstevel@tonic-gate mac_copy(mac_pvt->curr_macaddr, pktinfo->dhost,
7810Sstevel@tonic-gate IPOIB_ADDRL);
7820Sstevel@tonic-gate /*
7830Sstevel@tonic-gate * Any unicast packets received on IBA are
7840Sstevel@tonic-gate * for the node.
7850Sstevel@tonic-gate */
7860Sstevel@tonic-gate pktinfo->isForMe = 1;
7870Sstevel@tonic-gate }
7880Sstevel@tonic-gate }
7890Sstevel@tonic-gate
7900Sstevel@tonic-gate ASSERT((flags == GLD_RX) || (flags == GLD_RXLOOP));
7910Sstevel@tonic-gate ASSERT(GLDM_LOCK_HELD(macinfo));
7920Sstevel@tonic-gate pktinfo->ethertype = REF_NET_USHORT(((ipoib_hdr_t *)
7930Sstevel@tonic-gate (mp->b_rptr))->ipoib_type);
7940Sstevel@tonic-gate pktinfo->macLen = IPOIB_HDRSIZE;
7950Sstevel@tonic-gate
7960Sstevel@tonic-gate out:
7970Sstevel@tonic-gate if (pmp != NULL)
7980Sstevel@tonic-gate freemsg(pmp);
7990Sstevel@tonic-gate
8000Sstevel@tonic-gate return (0);
8010Sstevel@tonic-gate }
8020Sstevel@tonic-gate
8030Sstevel@tonic-gate /*
8040Sstevel@tonic-gate * The packet format sent to the driver is: 2b sap :: 2b 0s :: data
8050Sstevel@tonic-gate */
8060Sstevel@tonic-gate void
gld_interpret_mdt_ib(gld_mac_info_t * macinfo,mblk_t * mp,pdescinfo_t * pinfo,pktinfo_t * pktinfo,mdt_packet_flag_t flags)8070Sstevel@tonic-gate gld_interpret_mdt_ib(gld_mac_info_t *macinfo, mblk_t *mp, pdescinfo_t *pinfo,
8080Sstevel@tonic-gate pktinfo_t *pktinfo, mdt_packet_flag_t flags)
8090Sstevel@tonic-gate {
8100Sstevel@tonic-gate gld_mac_pvt_t *mac_pvt;
8110Sstevel@tonic-gate multidata_t *dlmdp;
8120Sstevel@tonic-gate pattrinfo_t attr_info = { PATTR_DSTADDRSAP, };
8130Sstevel@tonic-gate pattr_t *patr;
8140Sstevel@tonic-gate ipoib_ptxhdr_t *dlap = NULL;
8150Sstevel@tonic-gate
8160Sstevel@tonic-gate /*
8170Sstevel@tonic-gate * Per packet formatting.
8180Sstevel@tonic-gate */
8190Sstevel@tonic-gate if (flags == GLD_MDT_TXPKT) {
8200Sstevel@tonic-gate ipoib_hdr_t *hptr;
8210Sstevel@tonic-gate uint_t seg;
8220Sstevel@tonic-gate
8230Sstevel@tonic-gate if (PDESC_HDRL(pinfo) == 0)
8240Sstevel@tonic-gate return;
8250Sstevel@tonic-gate
8260Sstevel@tonic-gate /*
8270Sstevel@tonic-gate * Update packet's link header.
8280Sstevel@tonic-gate */
8290Sstevel@tonic-gate pinfo->hdr_rptr -= IPOIB_HDRSIZE;
8300Sstevel@tonic-gate hptr = (ipoib_hdr_t *)pinfo->hdr_rptr;
8310Sstevel@tonic-gate hptr->ipoib_mbz = htons(0);
8320Sstevel@tonic-gate hptr->ipoib_type = pktinfo->ethertype;
8330Sstevel@tonic-gate
8340Sstevel@tonic-gate /*
8350Sstevel@tonic-gate * Total #bytes that will be put on wire.
8360Sstevel@tonic-gate */
8370Sstevel@tonic-gate pktinfo->pktLen = PDESC_HDRL(pinfo);
8380Sstevel@tonic-gate for (seg = 0; seg < pinfo->pld_cnt; seg++)
8390Sstevel@tonic-gate pktinfo->pktLen += PDESC_PLDL(pinfo, seg);
8400Sstevel@tonic-gate
8410Sstevel@tonic-gate return;
8420Sstevel@tonic-gate }
8430Sstevel@tonic-gate
8440Sstevel@tonic-gate /*
8450Sstevel@tonic-gate * The following two cases of GLD_MDT_TX and GLD_MDT_RXLOOP are per
8460Sstevel@tonic-gate * MDT message processing.
8470Sstevel@tonic-gate */
8480Sstevel@tonic-gate dlmdp = mmd_getmultidata(mp);
8490Sstevel@tonic-gate patr = mmd_getpattr(dlmdp, NULL, &attr_info);
8500Sstevel@tonic-gate ASSERT(patr != NULL);
8510Sstevel@tonic-gate ASSERT(macinfo->gldm_saplen == -2);
8520Sstevel@tonic-gate if (patr != NULL)
8530Sstevel@tonic-gate dlap = (ipoib_ptxhdr_t *)((pattr_addr_t *)attr_info.buf)->addr;
8540Sstevel@tonic-gate
8550Sstevel@tonic-gate if (flags == GLD_MDT_TX) {
8560Sstevel@tonic-gate bzero((void *)pktinfo, sizeof (*pktinfo));
8570Sstevel@tonic-gate if (dlap == NULL)
8580Sstevel@tonic-gate return;
8590Sstevel@tonic-gate
8600Sstevel@tonic-gate /*
8610Sstevel@tonic-gate * Check if mac is broadcast or multicast address; all these
8620Sstevel@tonic-gate * types of address have the top 4 bytes as 0x00FFFFFF.
8630Sstevel@tonic-gate */
8640Sstevel@tonic-gate if (mac_eq(dlap, macinfo->gldm_broadcast_addr,
8650Sstevel@tonic-gate sizeof (uint32_t))) {
8660Sstevel@tonic-gate if (mac_eq(dlap, macinfo->gldm_broadcast_addr,
8670Sstevel@tonic-gate IPOIB_ADDRL))
8680Sstevel@tonic-gate pktinfo->isBroadcast = 1;
8690Sstevel@tonic-gate else
8700Sstevel@tonic-gate pktinfo->isMulticast = 1;
8710Sstevel@tonic-gate }
8720Sstevel@tonic-gate pktinfo->ethertype = REF_NET_USHORT(dlap->
8730Sstevel@tonic-gate ipoib_rhdr.ipoib_type);
8740Sstevel@tonic-gate } else {
8750Sstevel@tonic-gate ASSERT(flags == GLD_MDT_RXLOOP);
8760Sstevel@tonic-gate pktinfo->macLen = IPOIB_HDRSIZE;
8770Sstevel@tonic-gate mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
8780Sstevel@tonic-gate mac_copy(mac_pvt->curr_macaddr, pktinfo->shost, IPOIB_ADDRL);
8790Sstevel@tonic-gate if (dlap == NULL)
8800Sstevel@tonic-gate return;
8810Sstevel@tonic-gate mac_copy(&dlap->ipoib_dest, pktinfo->dhost, IPOIB_ADDRL);
8820Sstevel@tonic-gate }
8830Sstevel@tonic-gate }
8840Sstevel@tonic-gate
8850Sstevel@tonic-gate mblk_t *
gld_unitdata_ib(gld_t * gld,mblk_t * mp)8860Sstevel@tonic-gate gld_unitdata_ib(gld_t *gld, mblk_t *mp)
8870Sstevel@tonic-gate {
8880Sstevel@tonic-gate gld_mac_info_t *macinfo = gld->gld_mac_info;
8890Sstevel@tonic-gate dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_rptr;
8900Sstevel@tonic-gate ipoib_ptxhdr_t *gldp = IPOIBDLSAP(dlp, dlp->dl_dest_addr_offset);
8910Sstevel@tonic-gate ipoib_mac_t dhost;
8920Sstevel@tonic-gate unsigned short type;
8930Sstevel@tonic-gate mblk_t *nmp;
8940Sstevel@tonic-gate int hdrlen;
8950Sstevel@tonic-gate
8960Sstevel@tonic-gate ASSERT(macinfo != NULL);
8970Sstevel@tonic-gate
8980Sstevel@tonic-gate /* extract needed info from the mblk before we maybe reuse it */
8990Sstevel@tonic-gate mac_copy(&gldp->ipoib_dest, &dhost, IPOIB_ADDRL);
9000Sstevel@tonic-gate
9010Sstevel@tonic-gate /* look in the unitdata request for a sap, else use bound one */
9020Sstevel@tonic-gate if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
9030Sstevel@tonic-gate REF_HOST_USHORT(gldp->ipoib_rhdr.ipoib_type) != 0)
9040Sstevel@tonic-gate type = REF_HOST_USHORT(gldp->ipoib_rhdr.ipoib_type);
9050Sstevel@tonic-gate else
9060Sstevel@tonic-gate type = gld->gld_sap;
9070Sstevel@tonic-gate
9080Sstevel@tonic-gate hdrlen = sizeof (ipoib_ptxhdr_t);
9090Sstevel@tonic-gate
9100Sstevel@tonic-gate /* need a buffer big enough for the headers */
9110Sstevel@tonic-gate nmp = mp->b_cont; /* where the packet payload M_DATA is */
9120Sstevel@tonic-gate if (DB_REF(nmp) == 1 && MBLKHEAD(nmp) >= hdrlen) {
9130Sstevel@tonic-gate /* it fits at the beginning of the first M_DATA block */
9140Sstevel@tonic-gate freeb(mp); /* don't need the M_PROTO anymore */
9150Sstevel@tonic-gate } else if (DB_REF(mp) == 1 && MBLKSIZE(mp) >= hdrlen) {
9160Sstevel@tonic-gate /* we can reuse the dl_unitdata_req M_PROTO mblk */
9170Sstevel@tonic-gate nmp = mp;
9180Sstevel@tonic-gate DB_TYPE(nmp) = M_DATA;
9190Sstevel@tonic-gate nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
9200Sstevel@tonic-gate } else {
9210Sstevel@tonic-gate /* we need to allocate one */
9220Sstevel@tonic-gate if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
9230Sstevel@tonic-gate return (NULL);
9240Sstevel@tonic-gate nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
9250Sstevel@tonic-gate linkb(nmp, mp->b_cont);
9260Sstevel@tonic-gate freeb(mp);
9270Sstevel@tonic-gate }
9280Sstevel@tonic-gate
9290Sstevel@tonic-gate /* Got the space, now copy in the header components */
9300Sstevel@tonic-gate
9310Sstevel@tonic-gate nmp->b_rptr -= sizeof (ipoib_ptxhdr_t);
9320Sstevel@tonic-gate gldp = (ipoib_ptxhdr_t *)nmp->b_rptr;
9330Sstevel@tonic-gate SET_NET_USHORT(gldp->ipoib_rhdr.ipoib_type, type);
9340Sstevel@tonic-gate gldp->ipoib_rhdr.ipoib_mbz = 0;
9350Sstevel@tonic-gate mac_copy(&dhost, &gldp->ipoib_dest, IPOIB_ADDRL);
9360Sstevel@tonic-gate
9370Sstevel@tonic-gate return (nmp);
9380Sstevel@tonic-gate }
9390Sstevel@tonic-gate
9400Sstevel@tonic-gate mblk_t *
gld_fastpath_ib(gld_t * gld,mblk_t * mp)9410Sstevel@tonic-gate gld_fastpath_ib(gld_t *gld, mblk_t *mp)
9420Sstevel@tonic-gate {
9430Sstevel@tonic-gate gld_mac_info_t *macinfo = gld->gld_mac_info;
9440Sstevel@tonic-gate dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
9450Sstevel@tonic-gate ipoib_ptxhdr_t *gldp = IPOIBDLSAP(dlp, dlp->dl_dest_addr_offset);
9460Sstevel@tonic-gate unsigned short type;
9470Sstevel@tonic-gate mblk_t *nmp;
9480Sstevel@tonic-gate ipoib_ptxhdr_t *tgldp;
9490Sstevel@tonic-gate int hdrlen;
9500Sstevel@tonic-gate
9510Sstevel@tonic-gate ASSERT(macinfo != NULL);
9520Sstevel@tonic-gate
9530Sstevel@tonic-gate /* look in the unitdata request for a sap, else use bound one */
9540Sstevel@tonic-gate if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
9550Sstevel@tonic-gate REF_HOST_USHORT(gldp->ipoib_rhdr.ipoib_type) != 0)
9560Sstevel@tonic-gate type = REF_HOST_USHORT(gldp->ipoib_rhdr.ipoib_type);
9570Sstevel@tonic-gate else
9580Sstevel@tonic-gate type = gld->gld_sap;
9590Sstevel@tonic-gate
9600Sstevel@tonic-gate hdrlen = sizeof (ipoib_ptxhdr_t);
9610Sstevel@tonic-gate
9620Sstevel@tonic-gate if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
9630Sstevel@tonic-gate return (NULL);
9640Sstevel@tonic-gate
9650Sstevel@tonic-gate nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
9660Sstevel@tonic-gate
9670Sstevel@tonic-gate /* Got the space, now copy in the header components */
9680Sstevel@tonic-gate
9690Sstevel@tonic-gate nmp->b_rptr -= sizeof (ipoib_ptxhdr_t);
9700Sstevel@tonic-gate tgldp = (ipoib_ptxhdr_t *)nmp->b_rptr;
9710Sstevel@tonic-gate tgldp->ipoib_rhdr.ipoib_type = htons(type);
9720Sstevel@tonic-gate tgldp->ipoib_rhdr.ipoib_mbz = 0;
9730Sstevel@tonic-gate mac_copy(&gldp->ipoib_dest, &tgldp->ipoib_dest, IPOIB_ADDRL);
9740Sstevel@tonic-gate
9750Sstevel@tonic-gate return (nmp);
9760Sstevel@tonic-gate }
9770Sstevel@tonic-gate
9780Sstevel@tonic-gate /* ==== */
9790Sstevel@tonic-gate /* FDDI */
9800Sstevel@tonic-gate /* ==== */
9810Sstevel@tonic-gate
9820Sstevel@tonic-gate void
gld_init_fddi(gld_mac_info_t * macinfo)9830Sstevel@tonic-gate gld_init_fddi(gld_mac_info_t *macinfo)
9840Sstevel@tonic-gate {
9850Sstevel@tonic-gate struct gldkstats *sp =
9860Sstevel@tonic-gate ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->kstatp->ks_data;
9870Sstevel@tonic-gate
9880Sstevel@tonic-gate /* Assumptions we make for this medium */
9890Sstevel@tonic-gate ASSERT(macinfo->gldm_type == DL_FDDI);
9900Sstevel@tonic-gate ASSERT(macinfo->gldm_addrlen == 6);
9910Sstevel@tonic-gate ASSERT(macinfo->gldm_saplen == -2);
9920Sstevel@tonic-gate #ifndef lint
9930Sstevel@tonic-gate ASSERT(sizeof (struct fddi_mac_frm) == 13);
9940Sstevel@tonic-gate ASSERT(sizeof (mac_addr_t) == 6);
9950Sstevel@tonic-gate #endif
9960Sstevel@tonic-gate
9970Sstevel@tonic-gate /* Wire address format is bit reversed from canonical format */
9980Sstevel@tonic-gate macinfo->gldm_options |= GLDOPT_CANONICAL_ADDR;
9990Sstevel@tonic-gate
10000Sstevel@tonic-gate kstat_named_init(&sp->glds_fddi_mac_error,
10010Sstevel@tonic-gate "mac_errors", KSTAT_DATA_UINT32);
10020Sstevel@tonic-gate kstat_named_init(&sp->glds_fddi_mac_lost,
10030Sstevel@tonic-gate "mac_lost_errors", KSTAT_DATA_UINT32);
10040Sstevel@tonic-gate kstat_named_init(&sp->glds_fddi_mac_token,
10050Sstevel@tonic-gate "mac_tokens", KSTAT_DATA_UINT32);
10060Sstevel@tonic-gate kstat_named_init(&sp->glds_fddi_mac_tvx_expired,
10070Sstevel@tonic-gate "mac_tvx_expired", KSTAT_DATA_UINT32);
10080Sstevel@tonic-gate kstat_named_init(&sp->glds_fddi_mac_late,
10090Sstevel@tonic-gate "mac_late", KSTAT_DATA_UINT32);
10100Sstevel@tonic-gate kstat_named_init(&sp->glds_fddi_mac_ring_op,
10110Sstevel@tonic-gate "mac_ring_ops", KSTAT_DATA_UINT32);
10120Sstevel@tonic-gate }
10130Sstevel@tonic-gate
10140Sstevel@tonic-gate /*ARGSUSED*/
10150Sstevel@tonic-gate void
gld_uninit_fddi(gld_mac_info_t * macinfo)10160Sstevel@tonic-gate gld_uninit_fddi(gld_mac_info_t *macinfo)
10170Sstevel@tonic-gate {
10180Sstevel@tonic-gate }
10190Sstevel@tonic-gate
10200Sstevel@tonic-gate int
gld_interpret_fddi(gld_mac_info_t * macinfo,mblk_t * mp,pktinfo_t * pktinfo,packet_flag_t flags)10210Sstevel@tonic-gate gld_interpret_fddi(gld_mac_info_t *macinfo, mblk_t *mp, pktinfo_t *pktinfo,
10220Sstevel@tonic-gate packet_flag_t flags)
10230Sstevel@tonic-gate {
10240Sstevel@tonic-gate struct fddi_mac_frm *mh;
10250Sstevel@tonic-gate gld_mac_pvt_t *mac_pvt;
10260Sstevel@tonic-gate struct llc_snap_hdr *snaphdr;
10270Sstevel@tonic-gate mblk_t *pmp = NULL;
10280Sstevel@tonic-gate
10290Sstevel@tonic-gate /*
10300Sstevel@tonic-gate * Quickly handle receive fastpath; FDDI does not support IPQ hack.
10310Sstevel@tonic-gate */
10320Sstevel@tonic-gate if (flags == GLD_RXQUICK) {
10330Sstevel@tonic-gate pktinfo->pktLen = msgdsize(mp);
10340Sstevel@tonic-gate return (-1);
10350Sstevel@tonic-gate }
10360Sstevel@tonic-gate
10370Sstevel@tonic-gate bzero((void *)pktinfo, sizeof (*pktinfo));
10380Sstevel@tonic-gate
10390Sstevel@tonic-gate pktinfo->pktLen = msgdsize(mp);
10400Sstevel@tonic-gate
10410Sstevel@tonic-gate /* make sure packet has at least a whole mac header */
10420Sstevel@tonic-gate if (pktinfo->pktLen < sizeof (struct fddi_mac_frm))
10430Sstevel@tonic-gate return (-1);
10440Sstevel@tonic-gate
10450Sstevel@tonic-gate /* make sure the mac header falls into contiguous memory */
10460Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct fddi_mac_frm)) {
10470Sstevel@tonic-gate if ((pmp = msgpullup(mp, -1)) == NULL) {
10480Sstevel@tonic-gate #ifdef GLD_DEBUG
10490Sstevel@tonic-gate if (gld_debug & GLDERRS)
10500Sstevel@tonic-gate cmn_err(CE_WARN,
10510Sstevel@tonic-gate "GLD: interpret_fddi cannot msgpullup");
10520Sstevel@tonic-gate #endif
10530Sstevel@tonic-gate return (-1);
10540Sstevel@tonic-gate }
10550Sstevel@tonic-gate mp = pmp; /* this mblk contains the whole mac header */
10560Sstevel@tonic-gate }
10570Sstevel@tonic-gate
10580Sstevel@tonic-gate mh = (struct fddi_mac_frm *)mp->b_rptr;
10590Sstevel@tonic-gate
10600Sstevel@tonic-gate /* Check to see if the mac is a broadcast or multicast address. */
10610Sstevel@tonic-gate /* NB we are still in wire format (non canonical) */
10620Sstevel@tonic-gate /* mac_eq works because ether_broadcast is the same either way */
10630Sstevel@tonic-gate if (mac_eq(mh->fddi_dhost, ether_broadcast, macinfo->gldm_addrlen))
10640Sstevel@tonic-gate pktinfo->isBroadcast = 1;
10650Sstevel@tonic-gate else if (mh->fddi_dhost[0] & 0x80)
10660Sstevel@tonic-gate pktinfo->isMulticast = 1;
10670Sstevel@tonic-gate
10680Sstevel@tonic-gate if (flags == GLD_TX)
10690Sstevel@tonic-gate goto out; /* Got all info we need for xmit case */
10700Sstevel@tonic-gate
10710Sstevel@tonic-gate ASSERT(GLDM_LOCK_HELD(macinfo));
10720Sstevel@tonic-gate
10730Sstevel@tonic-gate /*
10740Sstevel@tonic-gate * Deal with the mac header
10750Sstevel@tonic-gate */
10760Sstevel@tonic-gate
10770Sstevel@tonic-gate cmac_copy(mh->fddi_dhost, pktinfo->dhost,
10780Sstevel@tonic-gate macinfo->gldm_addrlen, macinfo);
10790Sstevel@tonic-gate cmac_copy(mh->fddi_shost, pktinfo->shost,
10800Sstevel@tonic-gate macinfo->gldm_addrlen, macinfo);
10810Sstevel@tonic-gate
10820Sstevel@tonic-gate mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
10830Sstevel@tonic-gate pktinfo->isLooped = mac_eq(pktinfo->shost,
10840Sstevel@tonic-gate mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
10850Sstevel@tonic-gate pktinfo->isForMe = mac_eq(pktinfo->dhost,
10860Sstevel@tonic-gate mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
10870Sstevel@tonic-gate
10880Sstevel@tonic-gate pktinfo->macLen = sizeof (struct fddi_mac_frm);
10890Sstevel@tonic-gate
10900Sstevel@tonic-gate /*
10910Sstevel@tonic-gate * Before trying to look beyond the MAC header, make sure the LLC
10920Sstevel@tonic-gate * header exists, and that both it and any SNAP header are contiguous.
10930Sstevel@tonic-gate */
10940Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct fddi_mac_frm) + LLC_SNAP_HDR_LEN &&
10950Sstevel@tonic-gate MBLKL(mp) < pktinfo->pktLen) {
10960Sstevel@tonic-gate /*
10970Sstevel@tonic-gate * we don't have the entire packet within the first mblk (and
10980Sstevel@tonic-gate * therefore we didn't do the msgpullup above), AND the first
10990Sstevel@tonic-gate * mblk may not contain all the data we need to look at.
11000Sstevel@tonic-gate */
11010Sstevel@tonic-gate ASSERT(pmp == NULL); /* couldn't have done msgpullup above */
11020Sstevel@tonic-gate if ((pmp = msgpullup(mp, -1)) == NULL) {
11030Sstevel@tonic-gate #ifdef GLD_DEBUG
11040Sstevel@tonic-gate if (gld_debug & GLDERRS)
11050Sstevel@tonic-gate cmn_err(CE_WARN,
11060Sstevel@tonic-gate "GLD: interpret_fddi cannot msgpullup2");
11070Sstevel@tonic-gate #endif
11080Sstevel@tonic-gate goto out; /* can't interpret this pkt further */
11090Sstevel@tonic-gate }
11100Sstevel@tonic-gate mp = pmp; /* this mblk should contain everything needed */
11110Sstevel@tonic-gate }
11120Sstevel@tonic-gate
11130Sstevel@tonic-gate /*
11140Sstevel@tonic-gate * Check SAP/SNAP information.
11150Sstevel@tonic-gate */
11160Sstevel@tonic-gate if ((mh->fddi_fc & 0x70) == 0x50) {
11170Sstevel@tonic-gate if (pktinfo->pktLen < pktinfo->macLen + LLC_HDR1_LEN)
11180Sstevel@tonic-gate goto out;
11190Sstevel@tonic-gate
11200Sstevel@tonic-gate pktinfo->isLLC = 1;
11210Sstevel@tonic-gate
11220Sstevel@tonic-gate if (pktinfo->pktLen < pktinfo->macLen + LLC_SNAP_HDR_LEN)
11230Sstevel@tonic-gate goto out;
11240Sstevel@tonic-gate
11250Sstevel@tonic-gate snaphdr = (struct llc_snap_hdr *)(mp->b_rptr + pktinfo->macLen);
11260Sstevel@tonic-gate if (ISETHERTYPE(snaphdr)) {
11270Sstevel@tonic-gate pktinfo->ethertype = REF_NET_USHORT(snaphdr->type);
11280Sstevel@tonic-gate pktinfo->hdrLen = LLC_SNAP_HDR_LEN;
11290Sstevel@tonic-gate }
11300Sstevel@tonic-gate }
11310Sstevel@tonic-gate out:
11320Sstevel@tonic-gate if (pmp != NULL)
11330Sstevel@tonic-gate freemsg(pmp);
11340Sstevel@tonic-gate
11350Sstevel@tonic-gate return (0);
11360Sstevel@tonic-gate }
11370Sstevel@tonic-gate
11380Sstevel@tonic-gate mblk_t *
gld_unitdata_fddi(gld_t * gld,mblk_t * mp)11390Sstevel@tonic-gate gld_unitdata_fddi(gld_t *gld, mblk_t *mp)
11400Sstevel@tonic-gate {
11410Sstevel@tonic-gate gld_mac_info_t *macinfo = gld->gld_mac_info;
11420Sstevel@tonic-gate dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_rptr;
11430Sstevel@tonic-gate struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
11440Sstevel@tonic-gate mac_addr_t dhost;
11450Sstevel@tonic-gate unsigned short type;
11460Sstevel@tonic-gate mblk_t *nmp;
11470Sstevel@tonic-gate struct fddi_mac_frm *mh;
11480Sstevel@tonic-gate int hdrlen;
11490Sstevel@tonic-gate
11500Sstevel@tonic-gate ASSERT(macinfo);
11510Sstevel@tonic-gate
11520Sstevel@tonic-gate /* extract needed info from the mblk before we maybe reuse it */
11530Sstevel@tonic-gate mac_copy(gldp->glda_addr, dhost, macinfo->gldm_addrlen);
11540Sstevel@tonic-gate
11550Sstevel@tonic-gate /* look in the unitdata request for a sap, else use bound one */
11560Sstevel@tonic-gate if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
11570Sstevel@tonic-gate REF_HOST_USHORT(gldp->glda_sap) != 0)
11580Sstevel@tonic-gate type = REF_HOST_USHORT(gldp->glda_sap);
11590Sstevel@tonic-gate else
11600Sstevel@tonic-gate type = gld->gld_sap;
11610Sstevel@tonic-gate
11620Sstevel@tonic-gate
11630Sstevel@tonic-gate hdrlen = sizeof (struct fddi_mac_frm);
11640Sstevel@tonic-gate
11650Sstevel@tonic-gate /*
11660Sstevel@tonic-gate * Check whether we need to do EtherType encoding or whether the packet
11670Sstevel@tonic-gate * is LLC.
11680Sstevel@tonic-gate */
11690Sstevel@tonic-gate if (type > GLD_MAX_802_SAP)
11700Sstevel@tonic-gate hdrlen += sizeof (struct llc_snap_hdr);
11710Sstevel@tonic-gate
11720Sstevel@tonic-gate /* need a buffer big enough for the headers */
11730Sstevel@tonic-gate nmp = mp->b_cont; /* where the packet payload M_DATA is */
11740Sstevel@tonic-gate if (DB_REF(nmp) == 1 && MBLKHEAD(nmp) >= hdrlen) {
11750Sstevel@tonic-gate /* it fits at the beginning of the first M_DATA block */
11760Sstevel@tonic-gate freeb(mp); /* don't need the M_PROTO anymore */
11770Sstevel@tonic-gate } else if (DB_REF(mp) == 1 && MBLKSIZE(mp) >= hdrlen) {
11780Sstevel@tonic-gate /* we can reuse the dl_unitdata_req M_PROTO mblk */
11790Sstevel@tonic-gate nmp = mp;
11800Sstevel@tonic-gate DB_TYPE(nmp) = M_DATA;
11810Sstevel@tonic-gate nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
11820Sstevel@tonic-gate } else {
11830Sstevel@tonic-gate /* we need to allocate one */
11840Sstevel@tonic-gate if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
11850Sstevel@tonic-gate return (NULL);
11860Sstevel@tonic-gate nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
11870Sstevel@tonic-gate linkb(nmp, mp->b_cont);
11880Sstevel@tonic-gate freeb(mp);
11890Sstevel@tonic-gate }
11900Sstevel@tonic-gate
11910Sstevel@tonic-gate
11920Sstevel@tonic-gate /* Got the space, now copy in the header components */
11930Sstevel@tonic-gate if (type > GLD_MAX_802_SAP) {
11940Sstevel@tonic-gate /* create the snap header */
11950Sstevel@tonic-gate struct llc_snap_hdr *snap;
11960Sstevel@tonic-gate nmp->b_rptr -= sizeof (struct llc_snap_hdr);
11970Sstevel@tonic-gate snap = (struct llc_snap_hdr *)(nmp->b_rptr);
11980Sstevel@tonic-gate *snap = llc_snap_def;
11990Sstevel@tonic-gate SET_NET_USHORT(snap->type, type);
12000Sstevel@tonic-gate }
12010Sstevel@tonic-gate
12020Sstevel@tonic-gate nmp->b_rptr -= sizeof (struct fddi_mac_frm);
12030Sstevel@tonic-gate
12040Sstevel@tonic-gate mh = (struct fddi_mac_frm *)nmp->b_rptr;
12050Sstevel@tonic-gate
12060Sstevel@tonic-gate mh->fddi_fc = 0x50;
12070Sstevel@tonic-gate cmac_copy(dhost, mh->fddi_dhost, macinfo->gldm_addrlen, macinfo);
12080Sstevel@tonic-gate
12090Sstevel@tonic-gate /*
12100Sstevel@tonic-gate * We access the mac address without the mutex to prevent
12110Sstevel@tonic-gate * mutex contention (BUG 4211361)
12120Sstevel@tonic-gate */
12130Sstevel@tonic-gate cmac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
12140Sstevel@tonic-gate mh->fddi_shost, macinfo->gldm_addrlen, macinfo);
12150Sstevel@tonic-gate return (nmp);
12160Sstevel@tonic-gate }
12170Sstevel@tonic-gate
12180Sstevel@tonic-gate mblk_t *
gld_fastpath_fddi(gld_t * gld,mblk_t * mp)12190Sstevel@tonic-gate gld_fastpath_fddi(gld_t *gld, mblk_t *mp)
12200Sstevel@tonic-gate {
12210Sstevel@tonic-gate gld_mac_info_t *macinfo = gld->gld_mac_info;
12220Sstevel@tonic-gate dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
12230Sstevel@tonic-gate struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
12240Sstevel@tonic-gate unsigned short type;
12250Sstevel@tonic-gate mblk_t *nmp;
12260Sstevel@tonic-gate struct fddi_mac_frm *mh;
12270Sstevel@tonic-gate int hdrlen;
12280Sstevel@tonic-gate
12290Sstevel@tonic-gate ASSERT(macinfo);
12300Sstevel@tonic-gate
12310Sstevel@tonic-gate /* look in the unitdata request for a sap, else use bound one */
12320Sstevel@tonic-gate if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
12330Sstevel@tonic-gate REF_HOST_USHORT(gldp->glda_sap) != 0)
12340Sstevel@tonic-gate type = REF_HOST_USHORT(gldp->glda_sap);
12350Sstevel@tonic-gate else
12360Sstevel@tonic-gate type = gld->gld_sap;
12370Sstevel@tonic-gate
12380Sstevel@tonic-gate hdrlen = sizeof (struct fddi_mac_frm);
12390Sstevel@tonic-gate
12400Sstevel@tonic-gate /*
12410Sstevel@tonic-gate * Check whether we need to do EtherType encoding or whether the packet
12420Sstevel@tonic-gate * will be LLC.
12430Sstevel@tonic-gate */
12440Sstevel@tonic-gate if (type > GLD_MAX_802_SAP)
12450Sstevel@tonic-gate hdrlen += sizeof (struct llc_snap_hdr);
12460Sstevel@tonic-gate
12470Sstevel@tonic-gate if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
12480Sstevel@tonic-gate return (NULL);
12490Sstevel@tonic-gate
12500Sstevel@tonic-gate nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
12510Sstevel@tonic-gate
12520Sstevel@tonic-gate /* Got the space, now copy in the header components */
12530Sstevel@tonic-gate
12540Sstevel@tonic-gate if (type > GLD_MAX_802_SAP) {
12550Sstevel@tonic-gate /* create the snap header */
12560Sstevel@tonic-gate struct llc_snap_hdr *snap;
12570Sstevel@tonic-gate nmp->b_rptr -= sizeof (struct llc_snap_hdr);
12580Sstevel@tonic-gate snap = (struct llc_snap_hdr *)(nmp->b_rptr);
12590Sstevel@tonic-gate *snap = llc_snap_def;
12600Sstevel@tonic-gate snap->type = htons(type); /* we know it's aligned */
12610Sstevel@tonic-gate }
12620Sstevel@tonic-gate
12630Sstevel@tonic-gate nmp->b_rptr -= sizeof (struct fddi_mac_frm);
12640Sstevel@tonic-gate
12650Sstevel@tonic-gate mh = (struct fddi_mac_frm *)nmp->b_rptr;
12660Sstevel@tonic-gate mh->fddi_fc = 0x50;
12670Sstevel@tonic-gate cmac_copy(gldp->glda_addr, mh->fddi_dhost,
12680Sstevel@tonic-gate macinfo->gldm_addrlen, macinfo);
12690Sstevel@tonic-gate
12700Sstevel@tonic-gate GLDM_LOCK(macinfo, RW_WRITER);
12710Sstevel@tonic-gate cmac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
12720Sstevel@tonic-gate mh->fddi_shost, macinfo->gldm_addrlen, macinfo);
12730Sstevel@tonic-gate GLDM_UNLOCK(macinfo);
12740Sstevel@tonic-gate
12750Sstevel@tonic-gate return (nmp);
12760Sstevel@tonic-gate }
12770Sstevel@tonic-gate
12780Sstevel@tonic-gate /* ========== */
12790Sstevel@tonic-gate /* Token Ring */
12800Sstevel@tonic-gate /* ========== */
12810Sstevel@tonic-gate
12820Sstevel@tonic-gate #define GLD_SR_VAR(macinfo) \
12830Sstevel@tonic-gate (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->data)
12840Sstevel@tonic-gate
12850Sstevel@tonic-gate #define GLD_SR_HASH(macinfo) ((struct srtab **)GLD_SR_VAR(macinfo))
12860Sstevel@tonic-gate
12870Sstevel@tonic-gate #define GLD_SR_MUTEX(macinfo) \
12880Sstevel@tonic-gate (&((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->datalock)
12890Sstevel@tonic-gate
12900Sstevel@tonic-gate static void gld_sr_clear(gld_mac_info_t *);
12910Sstevel@tonic-gate static void gld_rcc_receive(gld_mac_info_t *, pktinfo_t *, struct gld_ri *,
12920Sstevel@tonic-gate uchar_t *, int);
12930Sstevel@tonic-gate static void gld_rcc_send(gld_mac_info_t *, queue_t *, uchar_t *,
12940Sstevel@tonic-gate struct gld_ri **, uchar_t *);
12950Sstevel@tonic-gate
12960Sstevel@tonic-gate static mac_addr_t tokenbroadcastaddr2 = { 0xc0, 0x00, 0xff, 0xff, 0xff, 0xff };
12970Sstevel@tonic-gate static struct gld_ri ri_ste_def;
12980Sstevel@tonic-gate
12990Sstevel@tonic-gate void
gld_init_tr(gld_mac_info_t * macinfo)13000Sstevel@tonic-gate gld_init_tr(gld_mac_info_t *macinfo)
13010Sstevel@tonic-gate {
13020Sstevel@tonic-gate struct gldkstats *sp =
13030Sstevel@tonic-gate ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->kstatp->ks_data;
13040Sstevel@tonic-gate
13050Sstevel@tonic-gate /* avoid endian-dependent code by initializing here instead of static */
13060Sstevel@tonic-gate ri_ste_def.len = 2;
13070Sstevel@tonic-gate ri_ste_def.rt = RT_STE;
13080Sstevel@tonic-gate ri_ste_def.mtu = RT_MTU_MAX;
13090Sstevel@tonic-gate ri_ste_def.dir = 0;
13100Sstevel@tonic-gate ri_ste_def.res = 0;
13110Sstevel@tonic-gate
13120Sstevel@tonic-gate /* Assumptions we make for this medium */
13130Sstevel@tonic-gate ASSERT(macinfo->gldm_type == DL_TPR);
13140Sstevel@tonic-gate ASSERT(macinfo->gldm_addrlen == 6);
13150Sstevel@tonic-gate ASSERT(macinfo->gldm_saplen == -2);
13160Sstevel@tonic-gate #ifndef lint
13170Sstevel@tonic-gate ASSERT(sizeof (struct tr_mac_frm_nori) == 14);
13180Sstevel@tonic-gate ASSERT(sizeof (mac_addr_t) == 6);
13190Sstevel@tonic-gate #endif
13200Sstevel@tonic-gate
13210Sstevel@tonic-gate mutex_init(GLD_SR_MUTEX(macinfo), NULL, MUTEX_DRIVER, NULL);
13220Sstevel@tonic-gate
13230Sstevel@tonic-gate GLD_SR_VAR(macinfo) = kmem_zalloc(sizeof (struct srtab *)*SR_HASH_SIZE,
13240Sstevel@tonic-gate KM_SLEEP);
13250Sstevel@tonic-gate
13260Sstevel@tonic-gate /* Default is RDE enabled for this medium */
13270Sstevel@tonic-gate ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_enabled =
13280Sstevel@tonic-gate ddi_getprop(DDI_DEV_T_NONE, macinfo->gldm_devinfo, 0,
13290Sstevel@tonic-gate "gld_rde_enable", 1);
13300Sstevel@tonic-gate
13310Sstevel@tonic-gate /*
13320Sstevel@tonic-gate * Default is to use STE for unknown paths if RDE is enabled.
13330Sstevel@tonic-gate * If RDE is disabled, default is to use NULL RIF fields.
13340Sstevel@tonic-gate *
13350Sstevel@tonic-gate * It's possible to force use of STE for ALL packets:
13360Sstevel@tonic-gate * disable RDE but enable STE. This may be useful for
13370Sstevel@tonic-gate * non-transparent bridges, when it is not desired to run
13380Sstevel@tonic-gate * the RDE algorithms.
13390Sstevel@tonic-gate */
13400Sstevel@tonic-gate ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_str_indicator_ste =
13410Sstevel@tonic-gate ddi_getprop(DDI_DEV_T_NONE, macinfo->gldm_devinfo, 0,
13420Sstevel@tonic-gate "gld_rde_str_indicator_ste",
13430Sstevel@tonic-gate ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_enabled);
13440Sstevel@tonic-gate
13450Sstevel@tonic-gate /* Default 10 second route timeout on lack of activity */
13460Sstevel@tonic-gate {
13470Sstevel@tonic-gate int t = ddi_getprop(DDI_DEV_T_NONE, macinfo->gldm_devinfo, 0,
13480Sstevel@tonic-gate "gld_rde_timeout", 10);
13490Sstevel@tonic-gate if (t < 1)
13500Sstevel@tonic-gate t = 1; /* Let's be reasonable */
13510Sstevel@tonic-gate if (t > 600)
13520Sstevel@tonic-gate t = 600; /* Let's be reasonable */
13530Sstevel@tonic-gate /* We're using ticks (lbolts) for our timeout -- convert from seconds */
13540Sstevel@tonic-gate t = drv_usectohz(1000000 * t);
13550Sstevel@tonic-gate ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_timeout = t;
13560Sstevel@tonic-gate }
13570Sstevel@tonic-gate
13580Sstevel@tonic-gate kstat_named_init(&sp->glds_dot5_line_error,
13590Sstevel@tonic-gate "line_errors", KSTAT_DATA_UINT32);
13600Sstevel@tonic-gate kstat_named_init(&sp->glds_dot5_burst_error,
13610Sstevel@tonic-gate "burst_errors", KSTAT_DATA_UINT32);
13620Sstevel@tonic-gate kstat_named_init(&sp->glds_dot5_signal_loss,
13630Sstevel@tonic-gate "signal_losses", KSTAT_DATA_UINT32);
13640Sstevel@tonic-gate
13650Sstevel@tonic-gate /*
13660Sstevel@tonic-gate * only initialize the new statistics if the driver
13670Sstevel@tonic-gate * knows about them.
13680Sstevel@tonic-gate */
13690Sstevel@tonic-gate if (macinfo->gldm_driver_version != GLD_VERSION_200)
13700Sstevel@tonic-gate return;
13710Sstevel@tonic-gate
13720Sstevel@tonic-gate kstat_named_init(&sp->glds_dot5_ace_error,
13730Sstevel@tonic-gate "ace_errors", KSTAT_DATA_UINT32);
13740Sstevel@tonic-gate kstat_named_init(&sp->glds_dot5_internal_error,
13750Sstevel@tonic-gate "internal_errors", KSTAT_DATA_UINT32);
13760Sstevel@tonic-gate kstat_named_init(&sp->glds_dot5_lost_frame_error,
13770Sstevel@tonic-gate "lost_frame_errors", KSTAT_DATA_UINT32);
13780Sstevel@tonic-gate kstat_named_init(&sp->glds_dot5_frame_copied_error,
13790Sstevel@tonic-gate "frame_copied_errors", KSTAT_DATA_UINT32);
13800Sstevel@tonic-gate kstat_named_init(&sp->glds_dot5_token_error,
13810Sstevel@tonic-gate "token_errors", KSTAT_DATA_UINT32);
13820Sstevel@tonic-gate kstat_named_init(&sp->glds_dot5_freq_error,
13830Sstevel@tonic-gate "freq_errors", KSTAT_DATA_UINT32);
13840Sstevel@tonic-gate }
13850Sstevel@tonic-gate
13860Sstevel@tonic-gate void
gld_uninit_tr(gld_mac_info_t * macinfo)13870Sstevel@tonic-gate gld_uninit_tr(gld_mac_info_t *macinfo)
13880Sstevel@tonic-gate {
13890Sstevel@tonic-gate mutex_destroy(GLD_SR_MUTEX(macinfo));
13900Sstevel@tonic-gate gld_sr_clear(macinfo);
13910Sstevel@tonic-gate kmem_free(GLD_SR_VAR(macinfo), sizeof (struct srtab *) * SR_HASH_SIZE);
13920Sstevel@tonic-gate }
13930Sstevel@tonic-gate
13940Sstevel@tonic-gate int
gld_interpret_tr(gld_mac_info_t * macinfo,mblk_t * mp,pktinfo_t * pktinfo,packet_flag_t flags)13950Sstevel@tonic-gate gld_interpret_tr(gld_mac_info_t *macinfo, mblk_t *mp, pktinfo_t *pktinfo,
13960Sstevel@tonic-gate packet_flag_t flags)
13970Sstevel@tonic-gate {
13980Sstevel@tonic-gate struct tr_mac_frm *mh;
13990Sstevel@tonic-gate gld_mac_pvt_t *mac_pvt;
14000Sstevel@tonic-gate struct llc_snap_hdr *snaphdr;
14010Sstevel@tonic-gate mblk_t *pmp = NULL;
14020Sstevel@tonic-gate struct gld_ri *rh;
14030Sstevel@tonic-gate
14040Sstevel@tonic-gate /*
14050Sstevel@tonic-gate * Quickly handle receive fastpath; TR does not support IPQ hack.
14060Sstevel@tonic-gate */
14070Sstevel@tonic-gate if (flags == GLD_RXQUICK) {
14080Sstevel@tonic-gate pktinfo->pktLen = msgdsize(mp);
14090Sstevel@tonic-gate return (-1);
14100Sstevel@tonic-gate }
14110Sstevel@tonic-gate
14120Sstevel@tonic-gate bzero((void *)pktinfo, sizeof (*pktinfo));
14130Sstevel@tonic-gate
14140Sstevel@tonic-gate pktinfo->pktLen = msgdsize(mp);
14150Sstevel@tonic-gate
14160Sstevel@tonic-gate /* make sure packet has at least a whole mac header */
14170Sstevel@tonic-gate if (pktinfo->pktLen < sizeof (struct tr_mac_frm_nori))
14180Sstevel@tonic-gate return (-1);
14190Sstevel@tonic-gate
14200Sstevel@tonic-gate /* make sure the mac header falls into contiguous memory */
14210Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct tr_mac_frm_nori)) {
14220Sstevel@tonic-gate if ((pmp = msgpullup(mp, -1)) == NULL) {
14230Sstevel@tonic-gate #ifdef GLD_DEBUG
14240Sstevel@tonic-gate if (gld_debug & GLDERRS)
14250Sstevel@tonic-gate cmn_err(CE_WARN,
14260Sstevel@tonic-gate "GLD: interpret_tr cannot msgpullup");
14270Sstevel@tonic-gate #endif
14280Sstevel@tonic-gate return (-1);
14290Sstevel@tonic-gate }
14300Sstevel@tonic-gate mp = pmp; /* this mblk contains the whole mac header */
14310Sstevel@tonic-gate }
14320Sstevel@tonic-gate
14330Sstevel@tonic-gate mh = (struct tr_mac_frm *)mp->b_rptr;
14340Sstevel@tonic-gate
14350Sstevel@tonic-gate /* Check to see if the mac is a broadcast or multicast address. */
14360Sstevel@tonic-gate if (mac_eq(mh->tr_dhost, ether_broadcast, macinfo->gldm_addrlen) ||
14370Sstevel@tonic-gate mac_eq(mh->tr_dhost, tokenbroadcastaddr2, macinfo->gldm_addrlen))
14380Sstevel@tonic-gate pktinfo->isBroadcast = 1;
14390Sstevel@tonic-gate else if (mh->tr_dhost[0] & 0x80)
14400Sstevel@tonic-gate pktinfo->isMulticast = 1;
14410Sstevel@tonic-gate
14420Sstevel@tonic-gate if (flags == GLD_TX)
14430Sstevel@tonic-gate goto out; /* Got all info we need for xmit case */
14440Sstevel@tonic-gate
14450Sstevel@tonic-gate ASSERT(GLDM_LOCK_HELD(macinfo));
14460Sstevel@tonic-gate
14470Sstevel@tonic-gate /*
14480Sstevel@tonic-gate * Deal with the mac header
14490Sstevel@tonic-gate */
14500Sstevel@tonic-gate
14510Sstevel@tonic-gate mac_copy(mh->tr_dhost, pktinfo->dhost, macinfo->gldm_addrlen);
14520Sstevel@tonic-gate mac_copy(mh->tr_shost, pktinfo->shost, macinfo->gldm_addrlen);
14530Sstevel@tonic-gate pktinfo->shost[0] &= ~0x80; /* turn off RIF indicator */
14540Sstevel@tonic-gate
14550Sstevel@tonic-gate mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
14560Sstevel@tonic-gate pktinfo->isLooped = mac_eq(pktinfo->shost,
14570Sstevel@tonic-gate mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
14580Sstevel@tonic-gate pktinfo->isForMe = mac_eq(pktinfo->dhost,
14590Sstevel@tonic-gate mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
14600Sstevel@tonic-gate
14610Sstevel@tonic-gate rh = (struct gld_ri *)NULL;
14620Sstevel@tonic-gate pktinfo->macLen = sizeof (struct tr_mac_frm_nori);
14630Sstevel@tonic-gate
14640Sstevel@tonic-gate /*
14650Sstevel@tonic-gate * Before trying to look beyond the MAC header, make sure the data
14660Sstevel@tonic-gate * structures are all contiguously where we can conveniently look at
14670Sstevel@tonic-gate * them. We'll use a worst-case estimate of how many bytes into the
14680Sstevel@tonic-gate * packet data we'll be needing to look. Things will be more efficient
14690Sstevel@tonic-gate * if the driver puts at least this much into the first mblk.
14700Sstevel@tonic-gate *
14710Sstevel@tonic-gate * Even after this, we still will have to do checks against the total
14720Sstevel@tonic-gate * length of the packet. A bad incoming packet may not hold all the
14730Sstevel@tonic-gate * data structures it says it does.
14740Sstevel@tonic-gate */
14750Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct tr_mac_frm) +
14760Sstevel@tonic-gate LLC_HDR1_LEN + sizeof (struct rde_pdu) &&
14770Sstevel@tonic-gate MBLKL(mp) < pktinfo->pktLen) {
14780Sstevel@tonic-gate /*
14790Sstevel@tonic-gate * we don't have the entire packet within the first mblk (and
14800Sstevel@tonic-gate * therefore we didn't do the msgpullup above), AND the first
14810Sstevel@tonic-gate * mblk may not contain all the data we need to look at.
14820Sstevel@tonic-gate */
14830Sstevel@tonic-gate ASSERT(pmp == NULL); /* couldn't have done msgpullup above */
14840Sstevel@tonic-gate if ((pmp = msgpullup(mp, -1)) == NULL) {
14850Sstevel@tonic-gate #ifdef GLD_DEBUG
14860Sstevel@tonic-gate if (gld_debug & GLDERRS)
14870Sstevel@tonic-gate cmn_err(CE_WARN,
14880Sstevel@tonic-gate "GLD: interpret_tr cannot msgpullup2");
14890Sstevel@tonic-gate #endif
14900Sstevel@tonic-gate goto out; /* can't interpret this pkt further */
14910Sstevel@tonic-gate }
14920Sstevel@tonic-gate mp = pmp; /* this mblk should contain everything needed */
14930Sstevel@tonic-gate mh = (struct tr_mac_frm *)mp->b_rptr; /* to look at RIF */
14940Sstevel@tonic-gate }
14950Sstevel@tonic-gate
14960Sstevel@tonic-gate if (mh->tr_shost[0] & 0x80) {
14970Sstevel@tonic-gate /* Routing Information Field (RIF) is present */
14980Sstevel@tonic-gate if (pktinfo->pktLen < sizeof (struct tr_mac_frm_nori) + 2)
14990Sstevel@tonic-gate goto out; /* RIF should have been there! */
15000Sstevel@tonic-gate rh = (struct gld_ri *)&mh->tr_ri;
15010Sstevel@tonic-gate if ((rh->len & 1) || rh->len < 2) {
15020Sstevel@tonic-gate /* Bogus RIF, don't handle this packet */
15030Sstevel@tonic-gate #ifdef GLD_DEBUG
15040Sstevel@tonic-gate if (gld_debug & GLDERRS)
15050Sstevel@tonic-gate cmn_err(CE_WARN,
15060Sstevel@tonic-gate "GLD: received TR packet with "
15070Sstevel@tonic-gate "bogus RIF length %d",
15080Sstevel@tonic-gate rh->len);
15090Sstevel@tonic-gate #endif
15100Sstevel@tonic-gate goto out;
15110Sstevel@tonic-gate }
15120Sstevel@tonic-gate if (pktinfo->pktLen < sizeof (struct tr_mac_frm_nori) + rh->len)
15130Sstevel@tonic-gate goto out; /* RIF should have been there! */
15140Sstevel@tonic-gate pktinfo->macLen += rh->len;
15150Sstevel@tonic-gate }
15160Sstevel@tonic-gate
15170Sstevel@tonic-gate if ((mh->tr_fc & 0xc0) == 0x40) {
15180Sstevel@tonic-gate if (pktinfo->pktLen < pktinfo->macLen + LLC_HDR1_LEN)
15190Sstevel@tonic-gate goto out;
15200Sstevel@tonic-gate
15210Sstevel@tonic-gate pktinfo->isLLC = 1;
15220Sstevel@tonic-gate
15230Sstevel@tonic-gate if (pktinfo->pktLen < pktinfo->macLen + LLC_SNAP_HDR_LEN)
15240Sstevel@tonic-gate goto out;
15250Sstevel@tonic-gate
15260Sstevel@tonic-gate snaphdr = (struct llc_snap_hdr *)(mp->b_rptr + pktinfo->macLen);
15270Sstevel@tonic-gate if (ISETHERTYPE(snaphdr)) {
15280Sstevel@tonic-gate pktinfo->ethertype = REF_NET_USHORT(snaphdr->type);
15290Sstevel@tonic-gate pktinfo->hdrLen = LLC_SNAP_HDR_LEN;
15300Sstevel@tonic-gate }
15310Sstevel@tonic-gate
15320Sstevel@tonic-gate /* Inform the Route Control Component of received LLC frame */
15330Sstevel@tonic-gate gld_rcc_receive(macinfo, pktinfo, rh,
15340Sstevel@tonic-gate mp->b_rptr + pktinfo->macLen,
15350Sstevel@tonic-gate pktinfo->pktLen - pktinfo->macLen);
15360Sstevel@tonic-gate }
15370Sstevel@tonic-gate out:
15380Sstevel@tonic-gate if (pmp != NULL)
15390Sstevel@tonic-gate freemsg(pmp);
15400Sstevel@tonic-gate
15410Sstevel@tonic-gate return (0);
15420Sstevel@tonic-gate }
15430Sstevel@tonic-gate
15440Sstevel@tonic-gate mblk_t *
gld_unitdata_tr(gld_t * gld,mblk_t * mp)15450Sstevel@tonic-gate gld_unitdata_tr(gld_t *gld, mblk_t *mp)
15460Sstevel@tonic-gate {
15470Sstevel@tonic-gate gld_mac_info_t *macinfo = gld->gld_mac_info;
15480Sstevel@tonic-gate dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_rptr;
15490Sstevel@tonic-gate struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
15500Sstevel@tonic-gate mac_addr_t dhost;
15510Sstevel@tonic-gate unsigned short type;
15520Sstevel@tonic-gate mblk_t *nmp, *llcmp, *pmp = NULL;
15530Sstevel@tonic-gate struct tr_mac_frm_nori *mh;
15540Sstevel@tonic-gate int hdrlen;
15550Sstevel@tonic-gate struct gld_ri *rh;
15560Sstevel@tonic-gate
15570Sstevel@tonic-gate ASSERT(macinfo);
15580Sstevel@tonic-gate
15590Sstevel@tonic-gate /* extract needed info from the mblk before we maybe reuse it */
15600Sstevel@tonic-gate mac_copy(gldp->glda_addr, dhost, macinfo->gldm_addrlen);
15610Sstevel@tonic-gate
15620Sstevel@tonic-gate /* look in the unitdata request for a sap, else use bound one */
15630Sstevel@tonic-gate if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
15640Sstevel@tonic-gate REF_HOST_USHORT(gldp->glda_sap) != 0)
15650Sstevel@tonic-gate type = REF_HOST_USHORT(gldp->glda_sap);
15660Sstevel@tonic-gate else
15670Sstevel@tonic-gate type = gld->gld_sap;
15680Sstevel@tonic-gate
15690Sstevel@tonic-gate /* includes maximum possible Routing Information Field (RIF) size */
15700Sstevel@tonic-gate hdrlen = sizeof (struct tr_mac_frm);
15710Sstevel@tonic-gate
15720Sstevel@tonic-gate /*
15730Sstevel@tonic-gate * Check whether we need to do EtherType encoding or whether the packet
15740Sstevel@tonic-gate * is LLC.
15750Sstevel@tonic-gate */
15760Sstevel@tonic-gate if (type > GLD_MAX_802_SAP)
15770Sstevel@tonic-gate hdrlen += sizeof (struct llc_snap_hdr);
15780Sstevel@tonic-gate
15790Sstevel@tonic-gate /* need a buffer big enough for the headers */
15800Sstevel@tonic-gate llcmp = nmp = mp->b_cont; /* where the packet payload M_DATA is */
15810Sstevel@tonic-gate
15820Sstevel@tonic-gate /*
15830Sstevel@tonic-gate * We are going to need to look at the LLC header, so make sure it
15840Sstevel@tonic-gate * is contiguously in a single mblk. If we're the ones who create
15850Sstevel@tonic-gate * the LLC header (below, in the case where sap > 0xff) then we don't
15860Sstevel@tonic-gate * have to worry about it here.
15870Sstevel@tonic-gate */
15880Sstevel@tonic-gate ASSERT(nmp != NULL); /* gld_unitdata guarantees msgdsize > 0 */
15890Sstevel@tonic-gate if (type <= GLD_MAX_802_SAP) {
15900Sstevel@tonic-gate if (MBLKL(llcmp) < LLC_HDR1_LEN) {
15910Sstevel@tonic-gate llcmp = pmp = msgpullup(nmp, LLC_HDR1_LEN);
15920Sstevel@tonic-gate if (pmp == NULL) {
15930Sstevel@tonic-gate #ifdef GLD_DEBUG
15940Sstevel@tonic-gate if (gld_debug & GLDERRS)
15950Sstevel@tonic-gate cmn_err(CE_WARN,
15960Sstevel@tonic-gate "GLD: unitdata_tr "
15970Sstevel@tonic-gate "cannot msgpullup");
15980Sstevel@tonic-gate #endif
15990Sstevel@tonic-gate return (NULL);
16000Sstevel@tonic-gate }
16010Sstevel@tonic-gate }
16020Sstevel@tonic-gate }
16030Sstevel@tonic-gate
16040Sstevel@tonic-gate if (DB_REF(nmp) == 1 && MBLKHEAD(nmp) >= hdrlen) {
16050Sstevel@tonic-gate /* it fits at the beginning of the first M_DATA block */
16060Sstevel@tonic-gate freeb(mp); /* don't need the M_PROTO anymore */
16070Sstevel@tonic-gate } else if (DB_REF(mp) == 1 && MBLKSIZE(mp) >= hdrlen) {
16080Sstevel@tonic-gate /* we can reuse the dl_unitdata_req M_PROTO mblk */
16090Sstevel@tonic-gate nmp = mp;
16100Sstevel@tonic-gate DB_TYPE(nmp) = M_DATA;
16110Sstevel@tonic-gate nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
16120Sstevel@tonic-gate } else {
16130Sstevel@tonic-gate /* we need to allocate one */
16140Sstevel@tonic-gate if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL) {
16150Sstevel@tonic-gate if (pmp != NULL)
16160Sstevel@tonic-gate freemsg(pmp);
16170Sstevel@tonic-gate return (NULL);
16180Sstevel@tonic-gate }
16190Sstevel@tonic-gate nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
16200Sstevel@tonic-gate linkb(nmp, mp->b_cont);
16210Sstevel@tonic-gate freeb(mp);
16220Sstevel@tonic-gate }
16230Sstevel@tonic-gate
16240Sstevel@tonic-gate /* Got the space, now copy in the header components */
16250Sstevel@tonic-gate if (type > GLD_MAX_802_SAP) {
16260Sstevel@tonic-gate /* create the snap header */
16270Sstevel@tonic-gate struct llc_snap_hdr *snap;
16280Sstevel@tonic-gate llcmp = nmp; /* LLC header is going to be in this mblk */
16290Sstevel@tonic-gate nmp->b_rptr -= sizeof (struct llc_snap_hdr);
16300Sstevel@tonic-gate snap = (struct llc_snap_hdr *)(nmp->b_rptr);
16310Sstevel@tonic-gate *snap = llc_snap_def;
16320Sstevel@tonic-gate SET_NET_USHORT(snap->type, type);
16330Sstevel@tonic-gate }
16340Sstevel@tonic-gate
16350Sstevel@tonic-gate /* Hold SR tables still while we maybe point at an entry */
16360Sstevel@tonic-gate mutex_enter(GLD_SR_MUTEX(macinfo));
16370Sstevel@tonic-gate
16380Sstevel@tonic-gate gld_rcc_send(macinfo, WR(gld->gld_qptr), dhost, &rh, llcmp->b_rptr);
16390Sstevel@tonic-gate
16400Sstevel@tonic-gate if (rh != NULL) {
16410Sstevel@tonic-gate /* copy in the RIF */
16420Sstevel@tonic-gate ASSERT(rh->len <= sizeof (struct gld_ri));
16430Sstevel@tonic-gate nmp->b_rptr -= rh->len;
16440Sstevel@tonic-gate bcopy((caddr_t)rh, (caddr_t)nmp->b_rptr, rh->len);
16450Sstevel@tonic-gate }
16460Sstevel@tonic-gate
16470Sstevel@tonic-gate mutex_exit(GLD_SR_MUTEX(macinfo));
16480Sstevel@tonic-gate
16490Sstevel@tonic-gate /* no longer need the pulled-up mblk */
16500Sstevel@tonic-gate if (pmp != NULL)
16510Sstevel@tonic-gate freemsg(pmp);
16520Sstevel@tonic-gate
16530Sstevel@tonic-gate /*
16540Sstevel@tonic-gate * fill in token ring header
16550Sstevel@tonic-gate */
16560Sstevel@tonic-gate nmp->b_rptr -= sizeof (struct tr_mac_frm_nori);
16570Sstevel@tonic-gate mh = (struct tr_mac_frm_nori *)nmp->b_rptr;
16580Sstevel@tonic-gate mh->tr_ac = 0x10;
16590Sstevel@tonic-gate mh->tr_fc = 0x40;
16600Sstevel@tonic-gate mac_copy(dhost, mh->tr_dhost, macinfo->gldm_addrlen);
16610Sstevel@tonic-gate
16620Sstevel@tonic-gate /*
16630Sstevel@tonic-gate * We access the mac address without the mutex to prevent
16640Sstevel@tonic-gate * mutex contention (BUG 4211361)
16650Sstevel@tonic-gate */
16660Sstevel@tonic-gate mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
16670Sstevel@tonic-gate mh->tr_shost, macinfo->gldm_addrlen);
16680Sstevel@tonic-gate
16690Sstevel@tonic-gate if (rh != NULL)
16700Sstevel@tonic-gate mh->tr_shost[0] |= 0x80;
16710Sstevel@tonic-gate else
16720Sstevel@tonic-gate mh->tr_shost[0] &= ~0x80;
16730Sstevel@tonic-gate
16740Sstevel@tonic-gate return (nmp);
16750Sstevel@tonic-gate }
16760Sstevel@tonic-gate
16770Sstevel@tonic-gate /*
16780Sstevel@tonic-gate * We cannot have our client sending us "fastpath" M_DATA messages,
16790Sstevel@tonic-gate * because to do that we must provide to him a fixed MAC header to
16800Sstevel@tonic-gate * be prepended to each outgoing packet. But with Source Routing
16810Sstevel@tonic-gate * media, the length and content of the MAC header changes as the
16820Sstevel@tonic-gate * routes change, so there is no fixed header we can provide. So
16830Sstevel@tonic-gate * we decline to accept M_DATA messages if Source Routing is enabled.
16840Sstevel@tonic-gate */
16850Sstevel@tonic-gate mblk_t *
gld_fastpath_tr(gld_t * gld,mblk_t * mp)16860Sstevel@tonic-gate gld_fastpath_tr(gld_t *gld, mblk_t *mp)
16870Sstevel@tonic-gate {
16880Sstevel@tonic-gate gld_mac_info_t *macinfo = gld->gld_mac_info;
16890Sstevel@tonic-gate dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
16900Sstevel@tonic-gate struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
16910Sstevel@tonic-gate unsigned short type;
16920Sstevel@tonic-gate mblk_t *nmp;
16930Sstevel@tonic-gate struct tr_mac_frm_nori *mh;
16940Sstevel@tonic-gate int hdrlen;
16950Sstevel@tonic-gate
16960Sstevel@tonic-gate ASSERT(macinfo);
16970Sstevel@tonic-gate
16980Sstevel@tonic-gate /*
16990Sstevel@tonic-gate * If we are doing Source Routing, then we cannot provide a fixed
17000Sstevel@tonic-gate * MAC header, so fail.
17010Sstevel@tonic-gate */
17020Sstevel@tonic-gate if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_enabled)
17030Sstevel@tonic-gate return (NULL);
17040Sstevel@tonic-gate
17050Sstevel@tonic-gate /* look in the unitdata request for a sap, else use bound one */
17060Sstevel@tonic-gate if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
17070Sstevel@tonic-gate REF_HOST_USHORT(gldp->glda_sap) != 0)
17080Sstevel@tonic-gate type = REF_HOST_USHORT(gldp->glda_sap);
17090Sstevel@tonic-gate else
17100Sstevel@tonic-gate type = gld->gld_sap;
17110Sstevel@tonic-gate
17120Sstevel@tonic-gate hdrlen = sizeof (struct tr_mac_frm_nori);
17130Sstevel@tonic-gate
17140Sstevel@tonic-gate if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_str_indicator_ste)
17150Sstevel@tonic-gate hdrlen += ri_ste_def.len;
17160Sstevel@tonic-gate
17170Sstevel@tonic-gate /*
17180Sstevel@tonic-gate * Check whether we need to do EtherType encoding or whether the packet
17190Sstevel@tonic-gate * will be LLC.
17200Sstevel@tonic-gate */
17210Sstevel@tonic-gate if (type > GLD_MAX_802_SAP)
17220Sstevel@tonic-gate hdrlen += sizeof (struct llc_snap_hdr);
17230Sstevel@tonic-gate
17240Sstevel@tonic-gate if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
17250Sstevel@tonic-gate return (NULL);
17260Sstevel@tonic-gate
17270Sstevel@tonic-gate nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
17280Sstevel@tonic-gate
17290Sstevel@tonic-gate /* Got the space, now copy in the header components */
17300Sstevel@tonic-gate
17310Sstevel@tonic-gate if (type > GLD_MAX_802_SAP) {
17320Sstevel@tonic-gate /* create the snap header */
17330Sstevel@tonic-gate struct llc_snap_hdr *snap;
17340Sstevel@tonic-gate nmp->b_rptr -= sizeof (struct llc_snap_hdr);
17350Sstevel@tonic-gate snap = (struct llc_snap_hdr *)(nmp->b_rptr);
17360Sstevel@tonic-gate *snap = llc_snap_def;
17370Sstevel@tonic-gate snap->type = htons(type); /* we know it's aligned */
17380Sstevel@tonic-gate }
17390Sstevel@tonic-gate
17400Sstevel@tonic-gate /* RDE is disabled, use NULL RIF, or STE RIF */
17410Sstevel@tonic-gate if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_str_indicator_ste) {
17420Sstevel@tonic-gate nmp->b_rptr -= ri_ste_def.len;
17430Sstevel@tonic-gate bcopy((caddr_t)&ri_ste_def, (caddr_t)nmp->b_rptr,
17440Sstevel@tonic-gate ri_ste_def.len);
17450Sstevel@tonic-gate }
17460Sstevel@tonic-gate
17470Sstevel@tonic-gate /*
17480Sstevel@tonic-gate * fill in token ring header
17490Sstevel@tonic-gate */
17500Sstevel@tonic-gate nmp->b_rptr -= sizeof (struct tr_mac_frm_nori);
17510Sstevel@tonic-gate mh = (struct tr_mac_frm_nori *)nmp->b_rptr;
17520Sstevel@tonic-gate mh->tr_ac = 0x10;
17530Sstevel@tonic-gate mh->tr_fc = 0x40;
17540Sstevel@tonic-gate mac_copy(gldp->glda_addr, mh->tr_dhost, macinfo->gldm_addrlen);
17550Sstevel@tonic-gate
17560Sstevel@tonic-gate GLDM_LOCK(macinfo, RW_WRITER);
17570Sstevel@tonic-gate mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
17580Sstevel@tonic-gate mh->tr_shost, macinfo->gldm_addrlen);
17590Sstevel@tonic-gate GLDM_UNLOCK(macinfo);
17600Sstevel@tonic-gate
17610Sstevel@tonic-gate if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_str_indicator_ste)
17620Sstevel@tonic-gate mh->tr_shost[0] |= 0x80;
17630Sstevel@tonic-gate else
17640Sstevel@tonic-gate mh->tr_shost[0] &= ~0x80;
17650Sstevel@tonic-gate
17660Sstevel@tonic-gate return (nmp);
17670Sstevel@tonic-gate }
17680Sstevel@tonic-gate
17690Sstevel@tonic-gate /*
17700Sstevel@tonic-gate * Route Determination Entity (ISO 8802-2 / IEEE 802.2 : 1994, Section 9)
17710Sstevel@tonic-gate *
17720Sstevel@tonic-gate * RDE is an LLC layer entity. GLD is a MAC layer entity. The proper
17730Sstevel@tonic-gate * solution to this architectural anomaly is to move RDE support out of GLD
17740Sstevel@tonic-gate * and into LLC where it belongs. In particular, only LLC has the knowledge
17750Sstevel@tonic-gate * necessary to reply to XID and TEST packets. If and when it comes time to
17760Sstevel@tonic-gate * move RDE out of GLD to LLC, the LLC-to-GLD interface should be modified
17770Sstevel@tonic-gate * to use MA_UNITDATA structures rather than DL_UNITDATA structures. Of
17780Sstevel@tonic-gate * course, GLD will still have to continue to also support the DL_ structures
17790Sstevel@tonic-gate * as long as IP is not layered over LLC. Another, perhaps better, idea
17800Sstevel@tonic-gate * would be to make RDE an autopush module on top of the token ring drivers:
17810Sstevel@tonic-gate * RDE would sit between LLC and GLD. It would then also sit between IP and
17820Sstevel@tonic-gate * GLD, providing services to all clients of GLD/tokenring. In that case,
17830Sstevel@tonic-gate * GLD would still have to continue to support the DL_ interface for non-
17840Sstevel@tonic-gate * Token Ring interfaces, using the MA_ interface only for media supporting
17850Sstevel@tonic-gate * Source Routing media.
17860Sstevel@tonic-gate *
17870Sstevel@tonic-gate * At present, Token Ring is the only source routing medium we support.
17880Sstevel@tonic-gate * Since Token Ring is not at this time a strategic network medium for Sun,
17890Sstevel@tonic-gate * rather than devote a large amount of resources to creating a proper
17900Sstevel@tonic-gate * architecture and implementation of RDE, we do the minimum necessary to
17910Sstevel@tonic-gate * get it to work. The interface between the above token ring code and the
17920Sstevel@tonic-gate * below RDE code is designed to make it relatively easy to change to an
17930Sstevel@tonic-gate * MA_UNITDATA model later should this ever become a priority.
17940Sstevel@tonic-gate */
17950Sstevel@tonic-gate
17960Sstevel@tonic-gate static void gld_send_rqr(gld_mac_info_t *, uchar_t *, struct gld_ri *,
17970Sstevel@tonic-gate struct rde_pdu *, int);
17980Sstevel@tonic-gate static void gld_rde_pdu_req(gld_mac_info_t *, queue_t *, uchar_t *,
17990Sstevel@tonic-gate struct gld_ri *, uchar_t, uchar_t, uchar_t);
18000Sstevel@tonic-gate static void gld_get_route(gld_mac_info_t *, queue_t *, uchar_t *,
18010Sstevel@tonic-gate struct gld_ri **, uchar_t, uchar_t);
18020Sstevel@tonic-gate static void gld_reset_route(gld_mac_info_t *, queue_t *,
18030Sstevel@tonic-gate uchar_t *, uchar_t, uchar_t);
18040Sstevel@tonic-gate static void gld_rde_pdu_ind(gld_mac_info_t *, struct gld_ri *, struct rde_pdu *,
18050Sstevel@tonic-gate int);
18060Sstevel@tonic-gate static void gld_rif_ind(gld_mac_info_t *, struct gld_ri *, uchar_t *,
18070Sstevel@tonic-gate uchar_t, uchar_t);
18080Sstevel@tonic-gate static struct srtab **gld_sr_hash(struct srtab **, uchar_t *, int);
18090Sstevel@tonic-gate static struct srtab *gld_sr_lookup_entry(gld_mac_info_t *, uchar_t *);
18100Sstevel@tonic-gate static struct srtab *gld_sr_create_entry(gld_mac_info_t *, uchar_t *);
18110Sstevel@tonic-gate
18120Sstevel@tonic-gate /*
18130Sstevel@tonic-gate * This routine implements a modified subset of the 802.2 RDE RCC receive
18140Sstevel@tonic-gate * actions:
18150Sstevel@tonic-gate * we implement RCC receive events 3 to 12 (ISO 8802-2:1994 9.6.3.4);
18160Sstevel@tonic-gate * we omit special handling for the NULL SAP;
18170Sstevel@tonic-gate * we omit XID/TEST handling;
18180Sstevel@tonic-gate * we pass all packets (including RDE) upstream to LLC.
18190Sstevel@tonic-gate */
18200Sstevel@tonic-gate static void
gld_rcc_receive(gld_mac_info_t * macinfo,pktinfo_t * pktinfo,struct gld_ri * rh,uchar_t * llcpkt,int llcpktlen)18210Sstevel@tonic-gate gld_rcc_receive(gld_mac_info_t *macinfo, pktinfo_t *pktinfo, struct gld_ri *rh,
18220Sstevel@tonic-gate uchar_t *llcpkt, int llcpktlen)
18230Sstevel@tonic-gate {
18240Sstevel@tonic-gate struct llc_snap_hdr *snaphdr = (struct llc_snap_hdr *)(llcpkt);
18250Sstevel@tonic-gate
18260Sstevel@tonic-gate if (!((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_enabled)
18270Sstevel@tonic-gate return;
18280Sstevel@tonic-gate
18290Sstevel@tonic-gate /*
18300Sstevel@tonic-gate * First, ensure this packet wasn't something we received just
18310Sstevel@tonic-gate * because we were in promiscuous mode. Since none of the below
18320Sstevel@tonic-gate * code wants to see group addressed packets anyway, we can do
18330Sstevel@tonic-gate * this check up front. Since we're doing that, we can omit the
18340Sstevel@tonic-gate * checks for group addressed packets below.
18350Sstevel@tonic-gate */
18360Sstevel@tonic-gate if (!pktinfo->isForMe)
18370Sstevel@tonic-gate return; /* Event 6 */
18380Sstevel@tonic-gate
18390Sstevel@tonic-gate /* Process a subset of Route Determination Entity (RDE) packets */
18400Sstevel@tonic-gate if (snaphdr->d_lsap == LSAP_RDE) {
18410Sstevel@tonic-gate struct rde_pdu *pdu = (struct rde_pdu *)(llcpkt + LLC_HDR1_LEN);
18420Sstevel@tonic-gate int pdulen = llcpktlen - LLC_HDR1_LEN;
18430Sstevel@tonic-gate
18440Sstevel@tonic-gate /* sanity check the PDU */
18450Sstevel@tonic-gate if ((pdulen < sizeof (struct rde_pdu)) ||
18460Sstevel@tonic-gate (snaphdr->s_lsap != LSAP_RDE))
18470Sstevel@tonic-gate return;
18480Sstevel@tonic-gate
18490Sstevel@tonic-gate /* we only handle route discovery PDUs, not XID/TEST/other */
18500Sstevel@tonic-gate if (snaphdr->control != CNTL_LLC_UI)
18510Sstevel@tonic-gate return;
18520Sstevel@tonic-gate
18530Sstevel@tonic-gate switch (pdu->rde_ptype) {
18540Sstevel@tonic-gate case RDE_RQC: /* Route Query Command; Events 8 - 11 */
18550Sstevel@tonic-gate gld_send_rqr(macinfo, pktinfo->shost, rh, pdu, pdulen);
18560Sstevel@tonic-gate /* FALLTHROUGH */
18570Sstevel@tonic-gate case RDE_RQR: /* Route Query Response; Event 12 */
18580Sstevel@tonic-gate case RDE_RS: /* Route Selected; Event 7 */
18590Sstevel@tonic-gate gld_rde_pdu_ind(macinfo, rh, pdu, pdulen);
18600Sstevel@tonic-gate break;
18610Sstevel@tonic-gate default: /* ignore if unrecognized ptype */
18620Sstevel@tonic-gate return;
18630Sstevel@tonic-gate }
18640Sstevel@tonic-gate
18650Sstevel@tonic-gate return;
18660Sstevel@tonic-gate }
18670Sstevel@tonic-gate
18680Sstevel@tonic-gate /* Consider routes seen in other IA SRF packets */
18690Sstevel@tonic-gate
18700Sstevel@tonic-gate if (rh == NULL)
18710Sstevel@tonic-gate return; /* no RIF; Event 3 */
18720Sstevel@tonic-gate
18730Sstevel@tonic-gate if ((rh->rt & 0x04) != 0)
18740Sstevel@tonic-gate return; /* not SRF; Event 5 */
18750Sstevel@tonic-gate
18760Sstevel@tonic-gate gld_rif_ind(macinfo, rh, pktinfo->shost, snaphdr->s_lsap,
18770Sstevel@tonic-gate snaphdr->d_lsap); /* Event 4 */
18780Sstevel@tonic-gate }
18790Sstevel@tonic-gate
18800Sstevel@tonic-gate /*
18810Sstevel@tonic-gate * Send RQR: 802.2 9.6.3.4.2(9) RCC Receive Events 8-11
18820Sstevel@tonic-gate *
18830Sstevel@tonic-gate * The routing processing really doesn't belong here; it should be handled in
18840Sstevel@tonic-gate * the LLC layer above. If that were the case then RDE could just send down
18850Sstevel@tonic-gate * an extra MA_UNITDATA_REQ with the info needed to construct the packet. But
18860Sstevel@tonic-gate * at the time we get control here, it's not a particularly good time to be
18870Sstevel@tonic-gate * constructing packets and trying to send them. Specifically, at this layer
18880Sstevel@tonic-gate * we need to construct the full media packet, which means the below routine
18890Sstevel@tonic-gate * knows that it is dealing with Token Ring media. If this were instead done
18900Sstevel@tonic-gate * via a proper MA_UNITDATA interface, the RDE stuff could all be completely
18910Sstevel@tonic-gate * media independent. But since TR is the only source routing medium we
18920Sstevel@tonic-gate * support, this works even though it is not clean.
18930Sstevel@tonic-gate *
18940Sstevel@tonic-gate * We "know" that the only time we can get here is from the "interpret"
18950Sstevel@tonic-gate * routine, and only when it was called at receive time.
18960Sstevel@tonic-gate */
18970Sstevel@tonic-gate static void
gld_send_rqr(gld_mac_info_t * macinfo,uchar_t * shost,struct gld_ri * rh,struct rde_pdu * pdu,int pdulen)18980Sstevel@tonic-gate gld_send_rqr(gld_mac_info_t *macinfo, uchar_t *shost, struct gld_ri *rh,
18990Sstevel@tonic-gate struct rde_pdu *pdu, int pdulen)
19000Sstevel@tonic-gate {
19010Sstevel@tonic-gate mblk_t *nmp;
19020Sstevel@tonic-gate int nlen;
19030Sstevel@tonic-gate struct tr_mac_frm_nori *nmh;
19040Sstevel@tonic-gate struct gld_ri *nrh;
19050Sstevel@tonic-gate struct llc_snap_hdr *nsnaphdr;
19060Sstevel@tonic-gate struct rde_pdu *npdu;
19070Sstevel@tonic-gate
19080Sstevel@tonic-gate /* We know and assume we're on the receive path */
19090Sstevel@tonic-gate ASSERT(GLDM_LOCK_HELD(macinfo));
19100Sstevel@tonic-gate
19110Sstevel@tonic-gate if (pdulen < sizeof (struct rde_pdu))
19120Sstevel@tonic-gate return; /* Bad incoming PDU */
19130Sstevel@tonic-gate
19140Sstevel@tonic-gate nlen = sizeof (struct tr_mac_frm) + LLC_HDR1_LEN +
19150Sstevel@tonic-gate sizeof (struct rde_pdu);
19160Sstevel@tonic-gate
19170Sstevel@tonic-gate if ((nmp = allocb(nlen, BPRI_MED)) == NULL)
19180Sstevel@tonic-gate return;
19190Sstevel@tonic-gate
19200Sstevel@tonic-gate nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
19210Sstevel@tonic-gate
19220Sstevel@tonic-gate nmp->b_rptr -= sizeof (struct rde_pdu);
19230Sstevel@tonic-gate npdu = (struct rde_pdu *)(nmp->b_rptr);
19240Sstevel@tonic-gate *npdu = *pdu; /* copy orig/target macaddr/saps */
19250Sstevel@tonic-gate npdu->rde_ver = 1;
19260Sstevel@tonic-gate npdu->rde_ptype = RDE_RQR;
19270Sstevel@tonic-gate mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
19280Sstevel@tonic-gate npdu->rde_target_mac, macinfo->gldm_addrlen);
19290Sstevel@tonic-gate
19300Sstevel@tonic-gate nmp->b_rptr -= LLC_HDR1_LEN;
19310Sstevel@tonic-gate nsnaphdr = (struct llc_snap_hdr *)(nmp->b_rptr);
19320Sstevel@tonic-gate nsnaphdr->s_lsap = nsnaphdr->d_lsap = LSAP_RDE;
19330Sstevel@tonic-gate nsnaphdr->control = CNTL_LLC_UI;
19340Sstevel@tonic-gate
19350Sstevel@tonic-gate if (rh == NULL || (rh->rt & 0x06) == 0x06 ||
19360Sstevel@tonic-gate rh->len > sizeof (struct gld_ri)) {
19370Sstevel@tonic-gate /* no RIF (Event 8), or RIF type STE (Event 9): send ARE RQR */
19380Sstevel@tonic-gate nmp->b_rptr -= 2;
19390Sstevel@tonic-gate nrh = (struct gld_ri *)(nmp->b_rptr);
19400Sstevel@tonic-gate nrh->len = 2;
19410Sstevel@tonic-gate nrh->rt = RT_ARE;
19420Sstevel@tonic-gate nrh->dir = 0;
19430Sstevel@tonic-gate nrh->res = 0;
19440Sstevel@tonic-gate nrh->mtu = RT_MTU_MAX;
19450Sstevel@tonic-gate } else {
19460Sstevel@tonic-gate /*
19470Sstevel@tonic-gate * RIF must be ARE (Event 10) or SRF (Event 11):
19480Sstevel@tonic-gate * send SRF (reverse) RQR
19490Sstevel@tonic-gate */
19500Sstevel@tonic-gate ASSERT(rh->len <= sizeof (struct gld_ri));
19510Sstevel@tonic-gate nmp->b_rptr -= rh->len;
19520Sstevel@tonic-gate nrh = (struct gld_ri *)(nmp->b_rptr);
19530Sstevel@tonic-gate bcopy(rh, nrh, rh->len); /* copy incoming RIF */
19540Sstevel@tonic-gate nrh->rt = RT_SRF; /* make it SRF */
19550Sstevel@tonic-gate nrh->dir ^= 1; /* reverse direction */
19560Sstevel@tonic-gate }
19570Sstevel@tonic-gate
19580Sstevel@tonic-gate nmp->b_rptr -= sizeof (struct tr_mac_frm_nori);
19590Sstevel@tonic-gate nmh = (struct tr_mac_frm_nori *)(nmp->b_rptr);
19600Sstevel@tonic-gate nmh->tr_ac = 0x10;
19610Sstevel@tonic-gate nmh->tr_fc = 0x40;
19620Sstevel@tonic-gate mac_copy(shost, nmh->tr_dhost, macinfo->gldm_addrlen);
19630Sstevel@tonic-gate mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
19640Sstevel@tonic-gate nmh->tr_shost, macinfo->gldm_addrlen);
19650Sstevel@tonic-gate nmh->tr_shost[0] |= 0x80; /* indicate RIF present */
19660Sstevel@tonic-gate
19670Sstevel@tonic-gate /*
19680Sstevel@tonic-gate * Packet assembled; send it.
19690Sstevel@tonic-gate *
19700Sstevel@tonic-gate * As noted before, this is not really a good time to be trying to
19710Sstevel@tonic-gate * send out packets. We have no obvious queue to use if the packet
19720Sstevel@tonic-gate * can't be sent right away. We pick one arbitrarily.
19730Sstevel@tonic-gate */
19740Sstevel@tonic-gate {
19750Sstevel@tonic-gate gld_vlan_t *vlan;
19760Sstevel@tonic-gate queue_t *q;
19770Sstevel@tonic-gate
19780Sstevel@tonic-gate if ((vlan = gld_find_vlan(macinfo, VLAN_VID_NONE)) == NULL) {
19790Sstevel@tonic-gate /* oops, no vlan on the list for this macinfo! */
19800Sstevel@tonic-gate /* this should not happen */
19810Sstevel@tonic-gate freeb(nmp);
19820Sstevel@tonic-gate return;
19830Sstevel@tonic-gate }
19840Sstevel@tonic-gate q = vlan->gldv_str_next->gld_qptr;
19850Sstevel@tonic-gate
19860Sstevel@tonic-gate /*
19870Sstevel@tonic-gate * Queue the packet and let gld_wsrv
19880Sstevel@tonic-gate * handle it, thus preventing a panic
19890Sstevel@tonic-gate * caused by v2 TR in promiscuous mode
19900Sstevel@tonic-gate * where it attempts to get the mutex
19910Sstevel@tonic-gate * in this thread while already holding
19920Sstevel@tonic-gate * it.
19930Sstevel@tonic-gate */
19940Sstevel@tonic-gate (void) putbq(WR(q), nmp);
19950Sstevel@tonic-gate qenable(WR(q));
19960Sstevel@tonic-gate }
19970Sstevel@tonic-gate }
19980Sstevel@tonic-gate
19990Sstevel@tonic-gate /*
20000Sstevel@tonic-gate * This routine implements a modified subset of the 802.2 RDE RCC send actions:
20010Sstevel@tonic-gate * we implement RCC send events 5 to 10 (ISO 8802-2:1994 9.6.3.5);
20020Sstevel@tonic-gate * we omit special handling for the NULL SAP;
20030Sstevel@tonic-gate * events 11 to 12 are handled by gld_rde_pdu_req below;
20040Sstevel@tonic-gate * we require an immediate response to our GET_ROUTE_REQUEST.
20050Sstevel@tonic-gate */
20060Sstevel@tonic-gate static void
gld_rcc_send(gld_mac_info_t * macinfo,queue_t * q,uchar_t * dhost,struct gld_ri ** rhp,uchar_t * llcpkt)20070Sstevel@tonic-gate gld_rcc_send(gld_mac_info_t *macinfo, queue_t *q, uchar_t *dhost,
20080Sstevel@tonic-gate struct gld_ri **rhp, uchar_t *llcpkt)
20090Sstevel@tonic-gate {
20100Sstevel@tonic-gate struct llc_snap_hdr *snaphdr = (struct llc_snap_hdr *)(llcpkt);
20110Sstevel@tonic-gate
20120Sstevel@tonic-gate /*
20130Sstevel@tonic-gate * Our caller has to take the mutex because: to avoid an extra bcopy
20140Sstevel@tonic-gate * of the RIF on every transmit, we pass back a pointer to our sr
20150Sstevel@tonic-gate * table entry via rhp. He has to keep the mutex until he has a
20160Sstevel@tonic-gate * chance to copy the RIF out into the outgoing packet, so that we
20170Sstevel@tonic-gate * don't modify the entry while he's trying to copy it. This is a
20180Sstevel@tonic-gate * little ugly, but saves the extra bcopy.
20190Sstevel@tonic-gate */
20200Sstevel@tonic-gate ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo)));
20210Sstevel@tonic-gate
20220Sstevel@tonic-gate *rhp = (struct gld_ri *)NULL; /* start off clean (no RIF) */
20230Sstevel@tonic-gate
20240Sstevel@tonic-gate if (!((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_enabled) {
20250Sstevel@tonic-gate /* RDE is disabled -- use NULL or STE always */
20260Sstevel@tonic-gate if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->
20270Sstevel@tonic-gate rde_str_indicator_ste)
20280Sstevel@tonic-gate *rhp = &ri_ste_def; /* STE option */
20290Sstevel@tonic-gate return;
20300Sstevel@tonic-gate }
20310Sstevel@tonic-gate
20320Sstevel@tonic-gate if (!(dhost[0] & 0x80)) {
20330Sstevel@tonic-gate /* individual address; Events 7 - 10 */
20340Sstevel@tonic-gate if ((snaphdr->control & 0xef) == 0xe3) {
20350Sstevel@tonic-gate /* TEST command, reset the route */
20360Sstevel@tonic-gate gld_reset_route(macinfo, q,
20370Sstevel@tonic-gate dhost, snaphdr->d_lsap, snaphdr->s_lsap);
20380Sstevel@tonic-gate }
20390Sstevel@tonic-gate gld_get_route(macinfo, q,
20400Sstevel@tonic-gate dhost, rhp, snaphdr->d_lsap, snaphdr->s_lsap);
20410Sstevel@tonic-gate }
20420Sstevel@tonic-gate
20430Sstevel@tonic-gate if (*rhp == NULL) {
20440Sstevel@tonic-gate /*
20450Sstevel@tonic-gate * group address (Events 5 - 6),
20460Sstevel@tonic-gate * or no route available (Events 8 - 9):
20470Sstevel@tonic-gate * Need to send NSR or STE, as configured.
20480Sstevel@tonic-gate */
20490Sstevel@tonic-gate if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->
20500Sstevel@tonic-gate rde_str_indicator_ste)
20510Sstevel@tonic-gate *rhp = &ri_ste_def; /* STE option */
20520Sstevel@tonic-gate }
20530Sstevel@tonic-gate }
20540Sstevel@tonic-gate
20550Sstevel@tonic-gate /*
20560Sstevel@tonic-gate * RCC send events 11 - 12
20570Sstevel@tonic-gate *
20580Sstevel@tonic-gate * At present we only handle the RQC ptype.
20590Sstevel@tonic-gate *
20600Sstevel@tonic-gate * We "know" that the only time we can get here is from the "unitdata"
20610Sstevel@tonic-gate * routine, called at wsrv time.
20620Sstevel@tonic-gate *
20630Sstevel@tonic-gate * If we ever implement the RS ptype (Event 13), this may no longer be true!
20640Sstevel@tonic-gate */
20650Sstevel@tonic-gate static void
gld_rde_pdu_req(gld_mac_info_t * macinfo,queue_t * q,uchar_t * dhost,struct gld_ri * rh,uchar_t dsap,uchar_t ssap,uchar_t ptype)20660Sstevel@tonic-gate gld_rde_pdu_req(gld_mac_info_t *macinfo, queue_t *q, uchar_t *dhost,
20670Sstevel@tonic-gate struct gld_ri *rh, uchar_t dsap, uchar_t ssap, uchar_t ptype)
20680Sstevel@tonic-gate {
20690Sstevel@tonic-gate mblk_t *nmp;
20700Sstevel@tonic-gate int nlen;
20710Sstevel@tonic-gate struct tr_mac_frm_nori *nmh;
20720Sstevel@tonic-gate struct gld_ri *nrh;
20730Sstevel@tonic-gate struct llc_snap_hdr *nsnaphdr;
20740Sstevel@tonic-gate struct rde_pdu *npdu;
20750Sstevel@tonic-gate int srpresent = 0;
20760Sstevel@tonic-gate
20770Sstevel@tonic-gate /* if you change this to process other types, review all code below */
20780Sstevel@tonic-gate ASSERT(ptype == RDE_RQC);
20790Sstevel@tonic-gate ASSERT(rh == NULL); /* RQC never uses SRF */
20800Sstevel@tonic-gate
20810Sstevel@tonic-gate nlen = sizeof (struct tr_mac_frm) + LLC_HDR1_LEN +
20820Sstevel@tonic-gate sizeof (struct rde_pdu);
20830Sstevel@tonic-gate
20840Sstevel@tonic-gate if ((nmp = allocb(nlen, BPRI_MED)) == NULL)
20850Sstevel@tonic-gate return;
20860Sstevel@tonic-gate
20870Sstevel@tonic-gate nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
20880Sstevel@tonic-gate
20890Sstevel@tonic-gate nmp->b_rptr -= sizeof (struct rde_pdu);
20900Sstevel@tonic-gate npdu = (struct rde_pdu *)(nmp->b_rptr);
20910Sstevel@tonic-gate npdu->rde_ver = 1;
20920Sstevel@tonic-gate npdu->rde_ptype = ptype;
20930Sstevel@tonic-gate mac_copy(dhost, &npdu->rde_target_mac, 6);
20940Sstevel@tonic-gate
20950Sstevel@tonic-gate /*
20960Sstevel@tonic-gate * access the mac address without a mutex - take a risk -
20970Sstevel@tonic-gate * to prevent mutex contention (BUG 4211361)
20980Sstevel@tonic-gate */
20990Sstevel@tonic-gate mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
21000Sstevel@tonic-gate &npdu->rde_orig_mac, 6);
21010Sstevel@tonic-gate npdu->rde_target_sap = dsap;
21020Sstevel@tonic-gate npdu->rde_orig_sap = ssap;
21030Sstevel@tonic-gate
21040Sstevel@tonic-gate nmp->b_rptr -= LLC_HDR1_LEN;
21050Sstevel@tonic-gate nsnaphdr = (struct llc_snap_hdr *)(nmp->b_rptr);
21060Sstevel@tonic-gate nsnaphdr->s_lsap = nsnaphdr->d_lsap = LSAP_RDE;
21070Sstevel@tonic-gate nsnaphdr->control = CNTL_LLC_UI;
21080Sstevel@tonic-gate
21090Sstevel@tonic-gate #if 0 /* we don't need this for now */
21100Sstevel@tonic-gate if (rh != NULL) {
21110Sstevel@tonic-gate /* send an SRF frame with specified RIF */
21120Sstevel@tonic-gate ASSERT(rh->len <= sizeof (struct gld_ri));
21130Sstevel@tonic-gate nmp->b_rptr -= rh->len;
21140Sstevel@tonic-gate nrh = (struct gld_ri *)(nmp->b_rptr);
21150Sstevel@tonic-gate bcopy(rh, nrh, rh->len);
21160Sstevel@tonic-gate ASSERT(nrh->rt == RT_SRF);
21170Sstevel@tonic-gate srpresent = 1;
21180Sstevel@tonic-gate } else
21190Sstevel@tonic-gate #endif
21200Sstevel@tonic-gate
21210Sstevel@tonic-gate /* Need to send NSR or STE, as configured. */
21220Sstevel@tonic-gate if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_str_indicator_ste) {
21230Sstevel@tonic-gate /* send an STE frame */
21240Sstevel@tonic-gate nmp->b_rptr -= 2;
21250Sstevel@tonic-gate nrh = (struct gld_ri *)(nmp->b_rptr);
21260Sstevel@tonic-gate nrh->len = 2;
21270Sstevel@tonic-gate nrh->rt = RT_STE;
21280Sstevel@tonic-gate nrh->dir = 0;
21290Sstevel@tonic-gate nrh->res = 0;
21300Sstevel@tonic-gate nrh->mtu = RT_MTU_MAX;
21310Sstevel@tonic-gate srpresent = 1;
21320Sstevel@tonic-gate } /* else send an NSR frame */
21330Sstevel@tonic-gate
21340Sstevel@tonic-gate nmp->b_rptr -= sizeof (struct tr_mac_frm_nori);
21350Sstevel@tonic-gate nmh = (struct tr_mac_frm_nori *)(nmp->b_rptr);
21360Sstevel@tonic-gate nmh->tr_ac = 0x10;
21370Sstevel@tonic-gate nmh->tr_fc = 0x40;
21380Sstevel@tonic-gate mac_copy(dhost, nmh->tr_dhost, macinfo->gldm_addrlen);
21390Sstevel@tonic-gate /*
21400Sstevel@tonic-gate * access the mac address without a mutex - take a risk -
21410Sstevel@tonic-gate * to prevent mutex contention - BUG 4211361
21420Sstevel@tonic-gate */
21430Sstevel@tonic-gate mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
21440Sstevel@tonic-gate nmh->tr_shost, macinfo->gldm_addrlen);
21450Sstevel@tonic-gate
21460Sstevel@tonic-gate if (srpresent)
21470Sstevel@tonic-gate nmh->tr_shost[0] |= 0x80;
21480Sstevel@tonic-gate else
21490Sstevel@tonic-gate nmh->tr_shost[0] &= ~0x80;
21500Sstevel@tonic-gate
21510Sstevel@tonic-gate /*
21520Sstevel@tonic-gate * Packet assembled; send it.
21530Sstevel@tonic-gate *
21540Sstevel@tonic-gate * Since we own the SR_MUTEX, we don't want to take the maclock
21550Sstevel@tonic-gate * mutex (since they are acquired in the opposite order on the
21560Sstevel@tonic-gate * receive path, so deadlock could occur). We could rearrange
21570Sstevel@tonic-gate * the code in gld_get_route() and drop the SR_MUTEX around the
21580Sstevel@tonic-gate * call to gld_rde_pdu_req(), but that's kind of ugly. Rather,
21590Sstevel@tonic-gate * we just refrain from calling gld_start() from here, and
21600Sstevel@tonic-gate * instead just queue the packet for wsrv to send next. Besides,
21610Sstevel@tonic-gate * it's more important to get the packet we're working on out
21620Sstevel@tonic-gate * quickly than this RQC.
21630Sstevel@tonic-gate */
21640Sstevel@tonic-gate (void) putbq(WR(q), nmp);
21650Sstevel@tonic-gate qenable(WR(q));
21660Sstevel@tonic-gate }
21670Sstevel@tonic-gate
21680Sstevel@tonic-gate /*
21690Sstevel@tonic-gate * Route Determination Component (RDC)
21700Sstevel@tonic-gate *
21710Sstevel@tonic-gate * We do not implement separate routes for each SAP, as specified by
21720Sstevel@tonic-gate * ISO 8802-2; instead we implement only one route per remote mac address.
21730Sstevel@tonic-gate */
21740Sstevel@tonic-gate static void
gld_get_route(gld_mac_info_t * macinfo,queue_t * q,uchar_t * dhost,struct gld_ri ** rhp,uchar_t dsap,uchar_t ssap)21750Sstevel@tonic-gate gld_get_route(gld_mac_info_t *macinfo, queue_t *q, uchar_t *dhost,
21760Sstevel@tonic-gate struct gld_ri **rhp, uchar_t dsap, uchar_t ssap)
21770Sstevel@tonic-gate {
21780Sstevel@tonic-gate struct srtab *sr;
21790Sstevel@tonic-gate clock_t t = ddi_get_lbolt();
21800Sstevel@tonic-gate
21810Sstevel@tonic-gate ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo)));
21820Sstevel@tonic-gate
21830Sstevel@tonic-gate sr = gld_sr_lookup_entry(macinfo, dhost);
21840Sstevel@tonic-gate
21850Sstevel@tonic-gate if (sr == NULL) {
21860Sstevel@tonic-gate /*
21870Sstevel@tonic-gate * we have no entry -- never heard of this address:
21880Sstevel@tonic-gate * create an empty entry and initiate RQC
21890Sstevel@tonic-gate */
21900Sstevel@tonic-gate sr = gld_sr_create_entry(macinfo, dhost);
21910Sstevel@tonic-gate gld_rde_pdu_req(macinfo, q, dhost, (struct gld_ri *)NULL,
21920Sstevel@tonic-gate dsap, ssap, RDE_RQC);
21930Sstevel@tonic-gate if (sr)
21940Sstevel@tonic-gate sr->sr_timer = t;
21950Sstevel@tonic-gate *rhp = NULL; /* we have no route yet */
21960Sstevel@tonic-gate return;
21970Sstevel@tonic-gate }
21980Sstevel@tonic-gate
21990Sstevel@tonic-gate /* we have an entry; see if we know a route yet */
22000Sstevel@tonic-gate
22010Sstevel@tonic-gate if (sr->sr_ri.len == 0) {
22020Sstevel@tonic-gate /* Have asked RQC, but no reply (yet) */
22030Sstevel@tonic-gate if (t - sr->sr_timer >
22040Sstevel@tonic-gate ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_timeout) {
22050Sstevel@tonic-gate /* RQR overdue, resend RQC */
22060Sstevel@tonic-gate gld_rde_pdu_req(macinfo, q, dhost,
22070Sstevel@tonic-gate (struct gld_ri *)NULL, dsap, ssap, RDE_RQC);
22080Sstevel@tonic-gate sr->sr_timer = t;
22090Sstevel@tonic-gate }
22100Sstevel@tonic-gate *rhp = NULL; /* we have no route yet */
22110Sstevel@tonic-gate return;
22120Sstevel@tonic-gate }
22130Sstevel@tonic-gate
22140Sstevel@tonic-gate /* we know a route, or it's local */
22150Sstevel@tonic-gate
22160Sstevel@tonic-gate /* if it might be stale, reset and get a new one */
22170Sstevel@tonic-gate if (t - sr->sr_timer >
22180Sstevel@tonic-gate ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_timeout) {
22190Sstevel@tonic-gate gld_rde_pdu_req(macinfo, q, dhost,
22200Sstevel@tonic-gate (struct gld_ri *)NULL, dsap, ssap, RDE_RQC);
22210Sstevel@tonic-gate sr->sr_ri.len = 0;
22220Sstevel@tonic-gate sr->sr_timer = t;
22230Sstevel@tonic-gate *rhp = NULL; /* we have no route */
22240Sstevel@tonic-gate return;
22250Sstevel@tonic-gate }
22260Sstevel@tonic-gate
22270Sstevel@tonic-gate if (sr->sr_ri.len == 2) {
22280Sstevel@tonic-gate /* the remote site is on our local ring -- no route needed */
22290Sstevel@tonic-gate *rhp = NULL;
22300Sstevel@tonic-gate return;
22310Sstevel@tonic-gate }
22320Sstevel@tonic-gate
22330Sstevel@tonic-gate *rhp = &sr->sr_ri; /* we have a route, return it */
22340Sstevel@tonic-gate }
22350Sstevel@tonic-gate
22360Sstevel@tonic-gate /*
22370Sstevel@tonic-gate * zap the specified entry and reinitiate RQC
22380Sstevel@tonic-gate */
22390Sstevel@tonic-gate static void
gld_reset_route(gld_mac_info_t * macinfo,queue_t * q,uchar_t * dhost,uchar_t dsap,uchar_t ssap)22400Sstevel@tonic-gate gld_reset_route(gld_mac_info_t *macinfo, queue_t *q,
22410Sstevel@tonic-gate uchar_t *dhost, uchar_t dsap, uchar_t ssap)
22420Sstevel@tonic-gate {
22430Sstevel@tonic-gate struct srtab *sr;
22440Sstevel@tonic-gate
22450Sstevel@tonic-gate ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo)));
22460Sstevel@tonic-gate
22470Sstevel@tonic-gate sr = gld_sr_create_entry(macinfo, dhost);
22480Sstevel@tonic-gate gld_rde_pdu_req(macinfo, q, dhost, (struct gld_ri *)NULL,
22490Sstevel@tonic-gate dsap, ssap, RDE_RQC);
22500Sstevel@tonic-gate if (sr == NULL)
22510Sstevel@tonic-gate return;
22520Sstevel@tonic-gate
22530Sstevel@tonic-gate sr->sr_ri.len = 0;
22540Sstevel@tonic-gate sr->sr_timer = ddi_get_lbolt();
22550Sstevel@tonic-gate }
22560Sstevel@tonic-gate
22570Sstevel@tonic-gate /*
22580Sstevel@tonic-gate * This routine is called when an RDE PDU is received from our peer.
22590Sstevel@tonic-gate * If it is an RS (Route Selected) PDU, we adopt the specified route.
22600Sstevel@tonic-gate * If it is an RQR (reply to our previous RQC), we evaluate the
22610Sstevel@tonic-gate * specified route in comparison with our current known route, if any,
22620Sstevel@tonic-gate * and we keep the "better" of the two routes.
22630Sstevel@tonic-gate */
22640Sstevel@tonic-gate static void
gld_rde_pdu_ind(gld_mac_info_t * macinfo,struct gld_ri * rh,struct rde_pdu * pdu,int pdulen)22650Sstevel@tonic-gate gld_rde_pdu_ind(gld_mac_info_t *macinfo, struct gld_ri *rh, struct rde_pdu *pdu,
22660Sstevel@tonic-gate int pdulen)
22670Sstevel@tonic-gate {
22680Sstevel@tonic-gate struct srtab *sr;
22690Sstevel@tonic-gate uchar_t *otherhost;
22700Sstevel@tonic-gate
22710Sstevel@tonic-gate if (pdulen < sizeof (struct rde_pdu))
22720Sstevel@tonic-gate return; /* Bad incoming PDU */
22730Sstevel@tonic-gate
22740Sstevel@tonic-gate if (pdu->rde_ptype == RDE_RQC)
22750Sstevel@tonic-gate return; /* ignore RQC */
22760Sstevel@tonic-gate
22770Sstevel@tonic-gate if (pdu->rde_ptype != RDE_RQR && pdu->rde_ptype != RDE_RS) {
22780Sstevel@tonic-gate #ifdef GLD_DEBUG
22790Sstevel@tonic-gate if (gld_debug & GLDERRS)
22800Sstevel@tonic-gate cmn_err(CE_WARN, "gld: bogus RDE ptype 0x%x received",
22810Sstevel@tonic-gate pdu->rde_ptype);
22820Sstevel@tonic-gate #endif
22830Sstevel@tonic-gate return;
22840Sstevel@tonic-gate }
22850Sstevel@tonic-gate
22860Sstevel@tonic-gate if (rh == NULL) {
22870Sstevel@tonic-gate #ifdef GLD_DEBUG
22880Sstevel@tonic-gate if (gld_debug & GLDERRS)
22890Sstevel@tonic-gate cmn_err(CE_WARN,
22900Sstevel@tonic-gate "gld: bogus NULL RIF, ptype 0x%x received",
22910Sstevel@tonic-gate pdu->rde_ptype);
22920Sstevel@tonic-gate #endif
22930Sstevel@tonic-gate return;
22940Sstevel@tonic-gate }
22950Sstevel@tonic-gate
22960Sstevel@tonic-gate ASSERT(rh->len >= 2);
22970Sstevel@tonic-gate ASSERT(rh->len <= sizeof (struct gld_ri));
22980Sstevel@tonic-gate ASSERT((rh->len & 1) == 0);
22990Sstevel@tonic-gate
23000Sstevel@tonic-gate if (pdu->rde_ptype == RDE_RQR) {
23010Sstevel@tonic-gate /* A reply to our RQC has his address as target mac */
23020Sstevel@tonic-gate otherhost = pdu->rde_target_mac;
23030Sstevel@tonic-gate } else {
23040Sstevel@tonic-gate ASSERT(pdu->rde_ptype == RDE_RS);
23050Sstevel@tonic-gate /* An RS has his address as orig mac */
23060Sstevel@tonic-gate otherhost = pdu->rde_orig_mac;
23070Sstevel@tonic-gate }
23080Sstevel@tonic-gate
23090Sstevel@tonic-gate mutex_enter(GLD_SR_MUTEX(macinfo));
23100Sstevel@tonic-gate
23110Sstevel@tonic-gate if ((sr = gld_sr_create_entry(macinfo, otherhost)) == NULL) {
23120Sstevel@tonic-gate mutex_exit(GLD_SR_MUTEX(macinfo));
23130Sstevel@tonic-gate return; /* oh well, out of memory */
23140Sstevel@tonic-gate }
23150Sstevel@tonic-gate
23160Sstevel@tonic-gate if (pdu->rde_ptype == RDE_RQR) {
23170Sstevel@tonic-gate /* see if new route is better than what we may already have */
23180Sstevel@tonic-gate if (sr->sr_ri.len != 0 &&
23190Sstevel@tonic-gate sr->sr_ri.len <= rh->len) {
23200Sstevel@tonic-gate mutex_exit(GLD_SR_MUTEX(macinfo));
23210Sstevel@tonic-gate return; /* we have one, and new one is no shorter */
23220Sstevel@tonic-gate }
23230Sstevel@tonic-gate }
23240Sstevel@tonic-gate
23250Sstevel@tonic-gate /* adopt the new route */
23260Sstevel@tonic-gate bcopy((caddr_t)rh, (caddr_t)&sr->sr_ri, rh->len); /* copy incom RIF */
23270Sstevel@tonic-gate sr->sr_ri.rt = RT_SRF; /* make it a clean SRF */
23280Sstevel@tonic-gate sr->sr_ri.dir ^= 1; /* reverse direction */
23290Sstevel@tonic-gate sr->sr_timer = ddi_get_lbolt();
23300Sstevel@tonic-gate
23310Sstevel@tonic-gate mutex_exit(GLD_SR_MUTEX(macinfo));
23320Sstevel@tonic-gate }
23330Sstevel@tonic-gate
23340Sstevel@tonic-gate /*
23350Sstevel@tonic-gate * This routine is called when a packet with a RIF is received. Our
23360Sstevel@tonic-gate * policy is to adopt the route.
23370Sstevel@tonic-gate */
23380Sstevel@tonic-gate /* ARGSUSED3 */
23390Sstevel@tonic-gate static void
gld_rif_ind(gld_mac_info_t * macinfo,struct gld_ri * rh,uchar_t * shost,uchar_t ssap,uchar_t dsap)23400Sstevel@tonic-gate gld_rif_ind(gld_mac_info_t *macinfo, struct gld_ri *rh, uchar_t *shost,
23410Sstevel@tonic-gate uchar_t ssap, uchar_t dsap)
23420Sstevel@tonic-gate {
23430Sstevel@tonic-gate struct srtab *sr;
23440Sstevel@tonic-gate
23450Sstevel@tonic-gate ASSERT(rh != NULL); /* ensure RIF */
23460Sstevel@tonic-gate ASSERT((rh->rt & 0x04) == 0); /* ensure SRF */
23470Sstevel@tonic-gate ASSERT(rh->len >= 2);
23480Sstevel@tonic-gate ASSERT(rh->len <= sizeof (struct gld_ri));
23490Sstevel@tonic-gate ASSERT((rh->len & 1) == 0);
23500Sstevel@tonic-gate
23510Sstevel@tonic-gate mutex_enter(GLD_SR_MUTEX(macinfo));
23520Sstevel@tonic-gate
23530Sstevel@tonic-gate if ((sr = gld_sr_create_entry(macinfo, shost)) == NULL) {
23540Sstevel@tonic-gate mutex_exit(GLD_SR_MUTEX(macinfo));
23550Sstevel@tonic-gate return; /* oh well, out of memory */
23560Sstevel@tonic-gate }
23570Sstevel@tonic-gate
23580Sstevel@tonic-gate /* we have an entry; fill it in */
23590Sstevel@tonic-gate bcopy((caddr_t)rh, (caddr_t)&sr->sr_ri, rh->len); /* copy incom RIF */
23600Sstevel@tonic-gate sr->sr_ri.rt = RT_SRF; /* make it a clean SRF */
23610Sstevel@tonic-gate sr->sr_ri.dir ^= 1; /* reverse direction */
23620Sstevel@tonic-gate sr->sr_timer = ddi_get_lbolt();
23630Sstevel@tonic-gate
23640Sstevel@tonic-gate mutex_exit(GLD_SR_MUTEX(macinfo));
23650Sstevel@tonic-gate }
23660Sstevel@tonic-gate
23670Sstevel@tonic-gate static struct srtab **
gld_sr_hash(struct srtab ** sr_hash_tbl,uchar_t * addr,int addr_length)23680Sstevel@tonic-gate gld_sr_hash(struct srtab **sr_hash_tbl, uchar_t *addr, int addr_length)
23690Sstevel@tonic-gate {
23700Sstevel@tonic-gate uint_t hashval = 0;
23710Sstevel@tonic-gate
23720Sstevel@tonic-gate while (--addr_length >= 0)
23730Sstevel@tonic-gate hashval ^= *addr++;
23740Sstevel@tonic-gate
23750Sstevel@tonic-gate return (&sr_hash_tbl[hashval % SR_HASH_SIZE]);
23760Sstevel@tonic-gate }
23770Sstevel@tonic-gate
23780Sstevel@tonic-gate static struct srtab *
gld_sr_lookup_entry(gld_mac_info_t * macinfo,uchar_t * macaddr)23790Sstevel@tonic-gate gld_sr_lookup_entry(gld_mac_info_t *macinfo, uchar_t *macaddr)
23800Sstevel@tonic-gate {
23810Sstevel@tonic-gate struct srtab *sr;
23820Sstevel@tonic-gate
23830Sstevel@tonic-gate ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo)));
23840Sstevel@tonic-gate
23850Sstevel@tonic-gate for (sr = *gld_sr_hash(GLD_SR_HASH(macinfo), macaddr,
23860Sstevel@tonic-gate macinfo->gldm_addrlen); sr; sr = sr->sr_next)
23870Sstevel@tonic-gate if (mac_eq(macaddr, sr->sr_mac, macinfo->gldm_addrlen))
23880Sstevel@tonic-gate return (sr);
23890Sstevel@tonic-gate
23900Sstevel@tonic-gate return ((struct srtab *)0);
23910Sstevel@tonic-gate }
23920Sstevel@tonic-gate
23930Sstevel@tonic-gate static struct srtab *
gld_sr_create_entry(gld_mac_info_t * macinfo,uchar_t * macaddr)23940Sstevel@tonic-gate gld_sr_create_entry(gld_mac_info_t *macinfo, uchar_t *macaddr)
23950Sstevel@tonic-gate {
23960Sstevel@tonic-gate struct srtab *sr;
23970Sstevel@tonic-gate struct srtab **srp;
23980Sstevel@tonic-gate
23990Sstevel@tonic-gate ASSERT(!(macaddr[0] & 0x80)); /* no group addresses here */
24000Sstevel@tonic-gate ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo)));
24010Sstevel@tonic-gate
24020Sstevel@tonic-gate srp = gld_sr_hash(GLD_SR_HASH(macinfo), macaddr, macinfo->gldm_addrlen);
24030Sstevel@tonic-gate
24040Sstevel@tonic-gate for (sr = *srp; sr; sr = sr->sr_next)
24050Sstevel@tonic-gate if (mac_eq(macaddr, sr->sr_mac, macinfo->gldm_addrlen))
24060Sstevel@tonic-gate return (sr);
24070Sstevel@tonic-gate
24080Sstevel@tonic-gate if (!(sr = kmem_zalloc(sizeof (struct srtab), KM_NOSLEEP))) {
24090Sstevel@tonic-gate #ifdef GLD_DEBUG
24100Sstevel@tonic-gate if (gld_debug & GLDERRS)
24110Sstevel@tonic-gate cmn_err(CE_WARN,
24120Sstevel@tonic-gate "gld: gld_sr_create_entry kmem_alloc failed");
24130Sstevel@tonic-gate #endif
24140Sstevel@tonic-gate return ((struct srtab *)0);
24150Sstevel@tonic-gate }
24160Sstevel@tonic-gate
24170Sstevel@tonic-gate bcopy((caddr_t)macaddr, (caddr_t)sr->sr_mac, macinfo->gldm_addrlen);
24180Sstevel@tonic-gate
24190Sstevel@tonic-gate sr->sr_next = *srp;
24200Sstevel@tonic-gate *srp = sr;
24210Sstevel@tonic-gate return (sr);
24220Sstevel@tonic-gate }
24230Sstevel@tonic-gate
24240Sstevel@tonic-gate static void
gld_sr_clear(gld_mac_info_t * macinfo)24250Sstevel@tonic-gate gld_sr_clear(gld_mac_info_t *macinfo)
24260Sstevel@tonic-gate {
24270Sstevel@tonic-gate int i;
24280Sstevel@tonic-gate struct srtab **sr_hash_tbl = GLD_SR_HASH(macinfo);
24290Sstevel@tonic-gate struct srtab **srp, *sr;
24300Sstevel@tonic-gate
24310Sstevel@tonic-gate /*
24320Sstevel@tonic-gate * Walk through the table, deleting all entries.
24330Sstevel@tonic-gate *
24340Sstevel@tonic-gate * Only called from uninit, so don't need the mutex.
24350Sstevel@tonic-gate */
24360Sstevel@tonic-gate for (i = 0; i < SR_HASH_SIZE; i++) {
24370Sstevel@tonic-gate for (srp = &sr_hash_tbl[i]; (sr = *srp) != NULL; ) {
24380Sstevel@tonic-gate *srp = sr->sr_next;
24390Sstevel@tonic-gate kmem_free((char *)sr, sizeof (struct srtab));
24400Sstevel@tonic-gate }
24410Sstevel@tonic-gate }
24420Sstevel@tonic-gate }
24430Sstevel@tonic-gate
24440Sstevel@tonic-gate #ifdef DEBUG
24450Sstevel@tonic-gate void
gld_sr_dump(gld_mac_info_t * macinfo)24460Sstevel@tonic-gate gld_sr_dump(gld_mac_info_t *macinfo)
24470Sstevel@tonic-gate {
24480Sstevel@tonic-gate int i, j;
24490Sstevel@tonic-gate struct srtab **sr_hash_tbl;
24500Sstevel@tonic-gate struct srtab *sr;
24510Sstevel@tonic-gate
24520Sstevel@tonic-gate sr_hash_tbl = GLD_SR_HASH(macinfo);
24530Sstevel@tonic-gate if (sr_hash_tbl == NULL)
24540Sstevel@tonic-gate return;
24550Sstevel@tonic-gate
24560Sstevel@tonic-gate mutex_enter(GLD_SR_MUTEX(macinfo));
24570Sstevel@tonic-gate
24580Sstevel@tonic-gate /*
24590Sstevel@tonic-gate * Walk through the table, printing all entries
24600Sstevel@tonic-gate */
24610Sstevel@tonic-gate cmn_err(CE_NOTE, "GLD Source Routing Table (0x%p):", (void *)macinfo);
24620Sstevel@tonic-gate cmn_err(CE_CONT, "Addr len,rt,dir,mtu,res rng,brg0 rng,brg1...\n");
24630Sstevel@tonic-gate for (i = 0; i < SR_HASH_SIZE; i++) {
24640Sstevel@tonic-gate for (sr = sr_hash_tbl[i]; sr; sr = sr->sr_next) {
24650Sstevel@tonic-gate cmn_err(CE_CONT,
24660Sstevel@tonic-gate "%x:%x:%x:%x:%x:%x %d,%x,%x,%x,%x ",
24670Sstevel@tonic-gate sr->sr_mac[0], sr->sr_mac[1], sr->sr_mac[2],
24680Sstevel@tonic-gate sr->sr_mac[3], sr->sr_mac[4], sr->sr_mac[5],
24690Sstevel@tonic-gate sr->sr_ri.len, sr->sr_ri.rt, sr->sr_ri.dir,
24700Sstevel@tonic-gate sr->sr_ri.mtu, sr->sr_ri.res);
24710Sstevel@tonic-gate if (sr->sr_ri.len)
24720Sstevel@tonic-gate for (j = 0; j < (sr->sr_ri.len - 2) / 2; j++)
24730Sstevel@tonic-gate cmn_err(CE_CONT, "%x ",
24740Sstevel@tonic-gate REF_NET_USHORT(*(unsigned short *)
24750Sstevel@tonic-gate &sr->sr_ri.rd[j]));
24760Sstevel@tonic-gate cmn_err(CE_CONT, "\n");
24770Sstevel@tonic-gate }
24780Sstevel@tonic-gate }
24790Sstevel@tonic-gate
24800Sstevel@tonic-gate mutex_exit(GLD_SR_MUTEX(macinfo));
24810Sstevel@tonic-gate }
24820Sstevel@tonic-gate #endif
2483