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