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