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