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