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