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