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