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