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 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Data-Link Driver 31 */ 32 33 #include <sys/types.h> 34 #include <sys/stream.h> 35 #include <sys/stropts.h> 36 #include <sys/strsun.h> 37 #include <sys/strsubr.h> 38 #include <sys/atomic.h> 39 #include <sys/sdt.h> 40 #include <sys/mac.h> 41 #include <sys/dls.h> 42 #include <sys/dld.h> 43 #include <sys/dld_impl.h> 44 #include <sys/taskq.h> 45 #include <sys/vlan.h> 46 47 static int str_constructor(void *, void *, int); 48 static void str_destructor(void *, void *); 49 static void str_m_put(dld_str_t *, mblk_t *); 50 static void str_m_srv(dld_str_t *, mblk_t *); 51 static void str_mdata_fastpath_put(dld_str_t *, mblk_t *); 52 static void str_mdata_raw_put(dld_str_t *, mblk_t *); 53 static void str_mdata_srv(dld_str_t *, mblk_t *); 54 static void str_mproto_put(dld_str_t *, mblk_t *); 55 static void str_mpcproto_put(dld_str_t *, mblk_t *); 56 static void str_mioctl_put(dld_str_t *, mblk_t *); 57 static void str_mflush_put(dld_str_t *, mblk_t *); 58 static mblk_t *str_unitdata_ind(dld_str_t *, mblk_t *); 59 static void str_notify_promisc_on_phys(dld_str_t *); 60 static void str_notify_promisc_off_phys(dld_str_t *); 61 static void str_notify_phys_addr(dld_str_t *, const uint8_t *); 62 static void str_notify_link_up(dld_str_t *); 63 static void str_notify_link_down(dld_str_t *); 64 static void str_notify_capab_reneg(dld_str_t *); 65 static void str_notify_speed(dld_str_t *, uint32_t); 66 static void str_notify(void *, mac_notify_type_t); 67 static void str_putbq(queue_t *q, mblk_t *mp); 68 69 static uint32_t str_count; 70 static kmem_cache_t *str_cachep; 71 72 typedef struct str_msg_info { 73 uint8_t smi_type; 74 const char *smi_txt; 75 void (*smi_put)(dld_str_t *, mblk_t *); 76 void (*smi_srv)(dld_str_t *, mblk_t *); 77 } str_msg_info_t; 78 79 /* 80 * Normal priority message jump table. 81 */ 82 str_msg_info_t str_mi[] = { 83 { M_DATA, "M_DATA", str_m_put, str_m_srv }, 84 { M_PROTO, "M_PROTO", str_mproto_put, str_m_srv }, 85 { 0x02, "undefined", str_m_put, str_m_srv }, 86 { 0x03, "undefined", str_m_put, str_m_srv }, 87 { 0x04, "undefined", str_m_put, str_m_srv }, 88 { 0x05, "undefined", str_m_put, str_m_srv }, 89 { 0x06, "undefined", str_m_put, str_m_srv }, 90 { 0x07, "undefined", str_m_put, str_m_srv }, 91 { M_BREAK, "M_BREAK", str_m_put, str_m_srv }, 92 { M_PASSFP, "M_PASSFP", str_m_put, str_m_srv }, 93 { M_EVENT, "M_EVENT", str_m_put, str_m_srv }, 94 { M_SIG, "M_SIG", str_m_put, str_m_srv }, 95 { M_DELAY, "M_DELAY", str_m_put, str_m_srv }, 96 { M_CTL, "M_CTL", str_m_put, str_m_srv }, 97 { M_IOCTL, "M_IOCTL", str_mioctl_put, str_m_srv }, 98 { M_SETOPTS, "M_SETOPTS", str_m_put, str_m_srv }, 99 { M_RSE, "M_RSE", str_m_put, str_m_srv } 100 }; 101 102 #define STR_MI_COUNT (sizeof (str_mi) / sizeof (str_mi[0])) 103 104 /* 105 * High priority message jump table. 106 */ 107 str_msg_info_t str_pmi[] = { 108 { 0x80, "undefined", str_m_put, str_m_srv }, 109 { M_IOCACK, "M_IOCACK", str_m_put, str_m_srv }, 110 { M_IOCNAK, "M_IOCNAK", str_m_put, str_m_srv }, 111 { M_PCPROTO, "M_PCPROTO", str_mpcproto_put, str_m_srv }, 112 { M_PCSIG, "M_PCSIG", str_m_put, str_m_srv }, 113 { M_READ, "M_READ", str_m_put, str_m_srv }, 114 { M_FLUSH, "M_FLUSH", str_mflush_put, str_m_srv }, 115 { M_STOP, "M_STOP", str_m_put, str_m_srv }, 116 { M_START, "M_START", str_m_put, str_m_srv }, 117 { M_HANGUP, "M_HANGUP", str_m_put, str_m_srv }, 118 { M_ERROR, "M_ERROR", str_m_put, str_m_srv }, 119 { M_COPYIN, "M_COPYIN", str_m_put, str_m_srv }, 120 { M_COPYOUT, "M_COPYOUT", str_m_put, str_m_srv }, 121 { M_IOCDATA, "M_IOCDATA", str_m_put, str_m_srv }, 122 { M_PCRSE, "M_PCRSE", str_m_put, str_m_srv }, 123 { M_STOPI, "M_STOPI", str_m_put, str_m_srv }, 124 { M_STARTI, "M_STARTI", str_m_put, str_m_srv }, 125 { M_PCEVENT, "M_PCEVENT", str_m_put, str_m_srv }, 126 { M_UNHANGUP, "M_UNHANGUP", str_m_put, str_m_srv } 127 }; 128 129 #define STR_PMI_COUNT (sizeof (str_pmi) / sizeof (str_pmi[0])) 130 131 /* 132 * Initialize this module's data structures. 133 */ 134 void 135 dld_str_init(void) 136 { 137 /* 138 * Create dld_str_t object cache. 139 */ 140 str_cachep = kmem_cache_create("dld_str_cache", sizeof (dld_str_t), 141 0, str_constructor, str_destructor, NULL, NULL, NULL, 0); 142 ASSERT(str_cachep != NULL); 143 } 144 145 /* 146 * Tear down this module's data structures. 147 */ 148 int 149 dld_str_fini(void) 150 { 151 /* 152 * Make sure that there are no objects in use. 153 */ 154 if (str_count != 0) 155 return (EBUSY); 156 157 /* 158 * Destroy object cache. 159 */ 160 kmem_cache_destroy(str_cachep); 161 162 return (0); 163 } 164 165 /* 166 * Create a new dld_str_t object. 167 */ 168 dld_str_t * 169 dld_str_create(queue_t *rq) 170 { 171 dld_str_t *dsp; 172 173 /* 174 * Allocate an object from the cache. 175 */ 176 dsp = kmem_cache_alloc(str_cachep, KM_SLEEP); 177 atomic_add_32(&str_count, 1); 178 179 /* 180 * Initialize the queue pointers. 181 */ 182 ASSERT(RD(rq) == rq); 183 dsp->ds_rq = rq; 184 dsp->ds_wq = WR(rq); 185 rq->q_ptr = WR(rq)->q_ptr = (void *)dsp; 186 187 return (dsp); 188 } 189 190 /* 191 * Destroy a dld_str_t object. 192 */ 193 void 194 dld_str_destroy(dld_str_t *dsp) 195 { 196 queue_t *rq; 197 queue_t *wq; 198 199 /* 200 * Clear the queue pointers. 201 */ 202 rq = dsp->ds_rq; 203 wq = dsp->ds_wq; 204 ASSERT(wq == WR(rq)); 205 206 rq->q_ptr = wq->q_ptr = NULL; 207 dsp->ds_rq = dsp->ds_wq = NULL; 208 209 /* 210 * Reinitialize all the flags. 211 */ 212 dsp->ds_notifications = 0; 213 dsp->ds_passivestate = DLD_UNINITIALIZED; 214 dsp->ds_mode = DLD_UNITDATA; 215 216 /* 217 * Free the object back to the cache. 218 */ 219 kmem_cache_free(str_cachep, dsp); 220 atomic_add_32(&str_count, -1); 221 } 222 223 /* 224 * kmem_cache contructor function: see kmem_cache_create(9f). 225 */ 226 /*ARGSUSED*/ 227 static int 228 str_constructor(void *buf, void *cdrarg, int kmflags) 229 { 230 dld_str_t *dsp = buf; 231 232 bzero(buf, sizeof (dld_str_t)); 233 234 /* 235 * Take a copy of the global message handler jump tables. 236 */ 237 ASSERT(dsp->ds_mi == NULL); 238 if ((dsp->ds_mi = kmem_zalloc(sizeof (str_mi), kmflags)) == NULL) 239 return (-1); 240 241 bcopy(str_mi, dsp->ds_mi, sizeof (str_mi)); 242 243 ASSERT(dsp->ds_pmi == NULL); 244 if ((dsp->ds_pmi = kmem_zalloc(sizeof (str_pmi), kmflags)) == NULL) { 245 kmem_free(dsp->ds_mi, sizeof (str_mi)); 246 dsp->ds_mi = NULL; 247 return (-1); 248 } 249 250 bcopy(str_pmi, dsp->ds_pmi, sizeof (str_pmi)); 251 252 /* 253 * Allocate a new minor number. 254 */ 255 if ((dsp->ds_minor = dld_minor_hold(kmflags == KM_SLEEP)) == 0) { 256 kmem_free(dsp->ds_mi, sizeof (str_mi)); 257 dsp->ds_mi = NULL; 258 kmem_free(dsp->ds_pmi, sizeof (str_pmi)); 259 dsp->ds_pmi = NULL; 260 return (-1); 261 } 262 263 /* 264 * Initialize the DLPI state machine. 265 */ 266 dsp->ds_dlstate = DL_UNATTACHED; 267 268 return (0); 269 } 270 271 /* 272 * kmem_cache destructor function. 273 */ 274 /*ARGSUSED*/ 275 static void 276 str_destructor(void *buf, void *cdrarg) 277 { 278 dld_str_t *dsp = buf; 279 280 /* 281 * Make sure the DLPI state machine was reset. 282 */ 283 ASSERT(dsp->ds_dlstate == DL_UNATTACHED); 284 285 /* 286 * Make sure the data-link interface was closed. 287 */ 288 ASSERT(dsp->ds_mh == NULL); 289 ASSERT(dsp->ds_dc == NULL); 290 291 /* 292 * Make sure enabled notifications are cleared. 293 */ 294 ASSERT(dsp->ds_notifications == 0); 295 296 /* 297 * Make sure polling is disabled. 298 */ 299 ASSERT(!dsp->ds_polling); 300 301 /* 302 * Make sure M_DATA message handling is disabled. 303 */ 304 ASSERT(dsp->ds_mi[M_DATA].smi_put == str_m_put); 305 ASSERT(dsp->ds_mi[M_DATA].smi_srv == str_m_srv); 306 307 /* 308 * Release the minor number. 309 */ 310 dld_minor_rele(dsp->ds_minor); 311 312 /* 313 * Clear down the jump tables. 314 */ 315 kmem_free(dsp->ds_mi, sizeof (str_mi)); 316 dsp->ds_mi = NULL; 317 318 kmem_free(dsp->ds_pmi, sizeof (str_pmi)); 319 dsp->ds_pmi = NULL; 320 } 321 322 /* 323 * Called from put(9e) to process a streams message. 324 */ 325 void 326 dld_str_put(dld_str_t *dsp, mblk_t *mp) 327 { 328 uint8_t type; 329 str_msg_info_t *smip; 330 331 /* 332 * Look up the message handler from the appropriate jump table. 333 */ 334 if ((type = DB_TYPE(mp)) & QPCTL) { 335 /* 336 * Clear the priority bit to index into the jump table. 337 */ 338 type &= ~QPCTL; 339 340 /* 341 * Check the message is not out of range for the jump table. 342 */ 343 if (type >= STR_PMI_COUNT) 344 goto unknown; 345 346 /* 347 * Get the handler from the jump table. 348 */ 349 smip = &(dsp->ds_pmi[type]); 350 351 /* 352 * OR the priorty bit back in to restore the original message 353 * type. 354 */ 355 type |= QPCTL; 356 } else { 357 /* 358 * Check the message is not out of range for the jump table. 359 */ 360 if (type >= STR_MI_COUNT) 361 goto unknown; 362 363 /* 364 * Get the handler from the jump table. 365 */ 366 smip = &(dsp->ds_mi[type]); 367 } 368 369 ASSERT(smip->smi_type == type); 370 smip->smi_put(dsp, mp); 371 return; 372 373 unknown: 374 str_m_put(dsp, mp); 375 } 376 377 /* 378 * Called from srv(9e) to process a streams message. 379 */ 380 void 381 dld_str_srv(dld_str_t *dsp, mblk_t *mp) 382 { 383 uint8_t type; 384 str_msg_info_t *smip; 385 386 /* 387 * Look up the message handler from the appropriate jump table. 388 */ 389 if ((type = DB_TYPE(mp)) & QPCTL) { 390 /* 391 * Clear the priority bit to index into the jump table. 392 */ 393 type &= ~QPCTL; 394 395 /* 396 * Check the message is not out of range for the jump table. 397 */ 398 if (type >= STR_PMI_COUNT) 399 goto unknown; 400 401 /* 402 * Get the handler from the jump table. 403 */ 404 smip = &(dsp->ds_pmi[type]); 405 406 /* 407 * OR the priorty bit back in to restore the original message 408 * type. 409 */ 410 type |= QPCTL; 411 } else { 412 /* 413 * Check the message is not out of range for the jump table. 414 */ 415 if (type >= STR_MI_COUNT) 416 goto unknown; 417 418 /* 419 * Get the handler from the jump table. 420 */ 421 ASSERT(type < STR_MI_COUNT); 422 smip = &(dsp->ds_mi[type]); 423 } 424 425 ASSERT(smip->smi_type == type); 426 smip->smi_srv(dsp, mp); 427 return; 428 429 unknown: 430 str_m_srv(dsp, mp); 431 } 432 433 /* 434 * M_DATA put (IP fast-path mode) 435 */ 436 static void 437 str_mdata_fastpath_put(dld_str_t *dsp, mblk_t *mp) 438 { 439 queue_t *q = dsp->ds_wq; 440 441 /* 442 * If something is already queued then we must queue to avoid 443 * re-ordering. 444 */ 445 if (q->q_first != NULL) { 446 (void) putq(q, mp); 447 return; 448 } 449 450 /* 451 * Attempt to transmit the packet. 452 */ 453 if ((mp = dls_tx(dsp->ds_dc, mp)) != NULL) { 454 (void) putbq(q, mp); 455 qenable(q); 456 } 457 } 458 459 /* 460 * M_DATA put (raw mode) 461 */ 462 static void 463 str_mdata_raw_put(dld_str_t *dsp, mblk_t *mp) 464 { 465 queue_t *q = dsp->ds_wq; 466 struct ether_header *ehp; 467 mblk_t *bp; 468 size_t size; 469 size_t hdrlen; 470 471 size = MBLKL(mp); 472 if (size < sizeof (struct ether_header)) 473 goto discard; 474 475 hdrlen = sizeof (struct ether_header); 476 477 ehp = (struct ether_header *)mp->b_rptr; 478 if (ntohs(ehp->ether_type) == VLAN_TPID) { 479 struct ether_vlan_header *evhp; 480 481 if (size < sizeof (struct ether_vlan_header)) 482 goto discard; 483 484 /* 485 * Replace vtag with our own 486 */ 487 evhp = (struct ether_vlan_header *)ehp; 488 evhp->ether_tci = htons(VLAN_TCI(dsp->ds_pri, 489 ETHER_CFI, dsp->ds_vid)); 490 hdrlen = sizeof (struct ether_vlan_header); 491 } 492 493 /* 494 * Check the packet is not too big and that any remaining 495 * fragment list is composed entirely of M_DATA messages. (We 496 * know the first fragment was M_DATA otherwise we could not 497 * have got here). 498 */ 499 for (bp = mp->b_next; bp != NULL; bp = bp->b_cont) { 500 if (DB_TYPE(bp) != M_DATA) 501 goto discard; 502 size += MBLKL(bp); 503 } 504 505 if (size > dsp->ds_mip->mi_sdu_max + hdrlen) 506 goto discard; 507 508 /* 509 * If something is already queued then we must queue to avoid 510 * re-ordering. 511 */ 512 if (q->q_first != NULL) { 513 (void) putq(q, bp); 514 return; 515 } 516 517 /* 518 * Attempt to transmit the packet. 519 */ 520 if ((mp = dls_tx(dsp->ds_dc, mp)) != NULL) { 521 (void) putbq(q, mp); 522 qenable(q); 523 } 524 return; 525 526 discard: 527 freemsg(mp); 528 } 529 530 /* 531 * M_DATA srv 532 */ 533 static void 534 str_mdata_srv(dld_str_t *dsp, mblk_t *mp) 535 { 536 queue_t *q = dsp->ds_wq; 537 538 /* 539 * Attempt to transmit the packet. 540 */ 541 if ((mp = dls_tx(dsp->ds_dc, mp)) == NULL) 542 return; 543 544 (void) str_putbq(q, mp); 545 qenable(q); 546 } 547 548 /* 549 * M_PROTO put 550 */ 551 static void 552 str_mproto_put(dld_str_t *dsp, mblk_t *mp) 553 { 554 dld_proto(dsp, mp); 555 } 556 557 /* 558 * M_PCPROTO put 559 */ 560 static void 561 str_mpcproto_put(dld_str_t *dsp, mblk_t *mp) 562 { 563 dld_proto(dsp, mp); 564 } 565 566 /* 567 * M_IOCTL put 568 */ 569 static void 570 str_mioctl_put(dld_str_t *dsp, mblk_t *mp) 571 { 572 dld_ioc(dsp, mp); 573 } 574 575 /* 576 * M_FLUSH put 577 */ 578 /*ARGSUSED*/ 579 static void 580 str_mflush_put(dld_str_t *dsp, mblk_t *mp) 581 { 582 queue_t *q = dsp->ds_wq; 583 584 if (*mp->b_rptr & FLUSHW) { 585 flushq(q, FLUSHALL); 586 *mp->b_rptr &= ~FLUSHW; 587 } 588 589 if (*mp->b_rptr & FLUSHR) 590 qreply(q, mp); 591 else 592 freemsg(mp); 593 } 594 595 /* 596 * M_* put. 597 */ 598 /*ARGSUSED*/ 599 static void 600 str_m_put(dld_str_t *dsp, mblk_t *mp) 601 { 602 freemsg(mp); 603 } 604 605 /* 606 * M_* put. 607 */ 608 /*ARGSUSED*/ 609 static void 610 str_m_srv(dld_str_t *dsp, mblk_t *mp) 611 { 612 freemsgchain(mp); 613 } 614 615 /* 616 * Process DL_ATTACH_REQ (style 2) or open(2) (style 1). 617 */ 618 int 619 dld_str_attach(dld_str_t *dsp, dld_ppa_t *dpp) 620 { 621 int err; 622 dls_channel_t dc; 623 uint_t addr_length; 624 625 ASSERT(dsp->ds_dc == NULL); 626 627 /* 628 * Open a channel. 629 */ 630 if ((err = dls_open(dpp->dp_name, &dc)) != 0) 631 return (err); 632 633 /* 634 * Cache the MAC interface handle, a pointer to the immutable MAC 635 * information and the current and 'factory' MAC address. 636 */ 637 dsp->ds_mh = dls_mac(dc); 638 dsp->ds_mip = mac_info(dsp->ds_mh); 639 640 mac_unicst_get(dsp->ds_mh, dsp->ds_curr_addr); 641 642 addr_length = dsp->ds_mip->mi_addr_length; 643 bcopy(dsp->ds_mip->mi_unicst_addr, dsp->ds_fact_addr, addr_length); 644 645 /* 646 * Cache the interface VLAN identifier. (This will be VLAN_ID_NONE for 647 * a non-VLAN interface). 648 */ 649 dsp->ds_vid = dls_vid(dc); 650 651 /* 652 * Set the default packet priority. 653 */ 654 dsp->ds_pri = 0; 655 656 /* 657 * Add a notify function so that the we get updates from the MAC. 658 */ 659 dsp->ds_mnh = mac_notify_add(dsp->ds_mh, str_notify, (void *)dsp); 660 661 dsp->ds_dc = dc; 662 return (0); 663 } 664 665 /* 666 * Process DL_DETACH_REQ (style 2) or close(2) (style 1). Can also be called 667 * from close(2) for style 2. 668 */ 669 void 670 dld_str_detach(dld_str_t *dsp) 671 { 672 /* 673 * Remove the notify function. 674 */ 675 mac_notify_remove(dsp->ds_mh, dsp->ds_mnh); 676 677 /* 678 * Make sure the M_DATA handler is reset. 679 */ 680 dld_str_tx_drop(dsp); 681 682 /* 683 * Clear the polling and promisc flags. 684 */ 685 dsp->ds_polling = B_FALSE; 686 dsp->ds_promisc = 0; 687 688 /* 689 * Close the channel. 690 */ 691 dls_close(dsp->ds_dc); 692 dsp->ds_dc = NULL; 693 dsp->ds_mh = NULL; 694 } 695 696 /* 697 * Enable raw mode for this stream. This mode is mutually exclusive with 698 * fast-path and/or polling. 699 */ 700 void 701 dld_str_tx_raw(dld_str_t *dsp) 702 { 703 /* 704 * Enable M_DATA message handling. 705 */ 706 dsp->ds_mi[M_DATA].smi_put = str_mdata_raw_put; 707 dsp->ds_mi[M_DATA].smi_srv = str_mdata_srv; 708 } 709 710 /* 711 * Enable fast-path for this stream. 712 */ 713 void 714 dld_str_tx_fastpath(dld_str_t *dsp) 715 { 716 /* 717 * Enable M_DATA message handling. 718 */ 719 dsp->ds_mi[M_DATA].smi_put = str_mdata_fastpath_put; 720 dsp->ds_mi[M_DATA].smi_srv = str_mdata_srv; 721 } 722 723 /* 724 * Disable fast-path or raw mode. 725 */ 726 void 727 dld_str_tx_drop(dld_str_t *dsp) 728 { 729 /* 730 * Disable M_DATA message handling. 731 */ 732 dsp->ds_mi[M_DATA].smi_put = str_m_put; 733 dsp->ds_mi[M_DATA].smi_srv = str_m_srv; 734 } 735 736 /* 737 * Raw mode receive function. 738 */ 739 /*ARGSUSED*/ 740 void 741 dld_str_rx_raw(void *arg, mac_resource_handle_t mrh, mblk_t *mp, 742 size_t header_length) 743 { 744 dld_str_t *dsp = (dld_str_t *)arg; 745 mblk_t *next; 746 747 ASSERT(mp != NULL); 748 do { 749 /* 750 * Get the pointer to the next packet in the chain and then 751 * clear b_next before the packet gets passed on. 752 */ 753 next = mp->b_next; 754 mp->b_next = NULL; 755 756 /* 757 * Wind back b_rptr to point at the MAC header. 758 */ 759 ASSERT(mp->b_rptr >= DB_BASE(mp) + header_length); 760 mp->b_rptr -= header_length; 761 if (header_length == sizeof (struct ether_vlan_header)) { 762 /* 763 * Strip off the vtag 764 */ 765 ovbcopy(mp->b_rptr, mp->b_rptr + VLAN_TAGSZ, 766 2 * ETHERADDRL); 767 mp->b_rptr += VLAN_TAGSZ; 768 } 769 770 /* 771 * Pass the packet on. 772 */ 773 putnext(dsp->ds_rq, mp); 774 775 /* 776 * Move on to the next packet in the chain. 777 */ 778 mp = next; 779 } while (mp != NULL); 780 } 781 782 /* 783 * Fast-path receive function. 784 */ 785 /*ARGSUSED*/ 786 void 787 dld_str_rx_fastpath(void *arg, mac_resource_handle_t mrh, mblk_t *mp, 788 size_t header_length) 789 { 790 dld_str_t *dsp = (dld_str_t *)arg; 791 mblk_t *next; 792 793 ASSERT(mp != NULL); 794 do { 795 /* 796 * Get the pointer to the next packet in the chain and then 797 * clear b_next before the packet gets passed on. 798 */ 799 next = mp->b_next; 800 mp->b_next = NULL; 801 802 /* 803 * Pass the packet on. 804 */ 805 putnext(dsp->ds_rq, mp); 806 807 /* 808 * Move on to the next packet in the chain. 809 */ 810 mp = next; 811 } while (mp != NULL); 812 } 813 814 /* 815 * Default receive function (send DL_UNITDATA_IND messages). 816 */ 817 /*ARGSUSED*/ 818 void 819 dld_str_rx_unitdata(void *arg, mac_resource_handle_t mrh, mblk_t *mp, 820 size_t header_length) 821 { 822 dld_str_t *dsp = (dld_str_t *)arg; 823 mblk_t *ud_mp; 824 mblk_t *next; 825 826 ASSERT(mp != NULL); 827 do { 828 /* 829 * Get the pointer to the next packet in the chain and then 830 * clear b_next before the packet gets passed on. 831 */ 832 next = mp->b_next; 833 mp->b_next = NULL; 834 835 /* 836 * Wind back b_rptr to point at the MAC header. 837 */ 838 ASSERT(mp->b_rptr >= DB_BASE(mp) + header_length); 839 mp->b_rptr -= header_length; 840 841 /* 842 * Create the DL_UNITDATA_IND M_PROTO. 843 */ 844 if ((ud_mp = str_unitdata_ind(dsp, mp)) == NULL) { 845 freemsgchain(mp); 846 return; 847 } 848 849 /* 850 * Advance b_rptr to point at the payload again. 851 */ 852 mp->b_rptr += header_length; 853 854 /* 855 * Prepend the DL_UNITDATA_IND. 856 */ 857 ud_mp->b_cont = mp; 858 859 /* 860 * Send the message. 861 */ 862 putnext(dsp->ds_rq, ud_mp); 863 864 /* 865 * Move on to the next packet in the chain. 866 */ 867 mp = next; 868 } while (mp != NULL); 869 } 870 871 /* 872 * Generate DL_NOTIFY_IND messages to notify the DLPI consumer of the 873 * current state of the interface. 874 */ 875 void 876 dld_str_notify_ind(dld_str_t *dsp) 877 { 878 mac_notify_type_t type; 879 880 for (type = 0; type < MAC_NNOTE; type++) 881 str_notify(dsp, type); 882 } 883 884 typedef struct dl_unitdata_ind_wrapper { 885 dl_unitdata_ind_t dl_unitdata; 886 uint8_t dl_dest_addr[MAXADDRLEN + sizeof (uint16_t)]; 887 uint8_t dl_src_addr[MAXADDRLEN + sizeof (uint16_t)]; 888 } dl_unitdata_ind_wrapper_t; 889 890 /* 891 * Create a DL_UNITDATA_IND M_PROTO message. 892 */ 893 static mblk_t * 894 str_unitdata_ind(dld_str_t *dsp, mblk_t *mp) 895 { 896 mblk_t *nmp; 897 dl_unitdata_ind_wrapper_t *dlwp; 898 dl_unitdata_ind_t *dlp; 899 dls_header_info_t dhi; 900 uint_t addr_length; 901 uint8_t *daddr; 902 uint8_t *saddr; 903 904 /* 905 * Get the packet header information. 906 */ 907 dls_header_info(dsp->ds_dc, mp, &dhi); 908 909 /* 910 * Allocate a message large enough to contain the wrapper structure 911 * defined above. 912 */ 913 if ((nmp = mexchange(dsp->ds_wq, NULL, 914 sizeof (dl_unitdata_ind_wrapper_t), M_PROTO, 915 DL_UNITDATA_IND)) == NULL) 916 return (NULL); 917 918 dlwp = (dl_unitdata_ind_wrapper_t *)nmp->b_rptr; 919 920 dlp = &(dlwp->dl_unitdata); 921 ASSERT(dlp == (dl_unitdata_ind_t *)nmp->b_rptr); 922 ASSERT(dlp->dl_primitive == DL_UNITDATA_IND); 923 924 /* 925 * Copy in the destination address. 926 */ 927 addr_length = dsp->ds_mip->mi_addr_length; 928 daddr = dlwp->dl_dest_addr; 929 dlp->dl_dest_addr_offset = (uintptr_t)daddr - (uintptr_t)dlp; 930 bcopy(dhi.dhi_daddr, daddr, addr_length); 931 932 /* 933 * Set the destination DLSAP to our bound DLSAP value. 934 */ 935 *(uint16_t *)(daddr + addr_length) = dsp->ds_sap; 936 dlp->dl_dest_addr_length = addr_length + sizeof (uint16_t); 937 938 /* 939 * If the destination address was a group address then 940 * dl_group_address field should be non-zero. 941 */ 942 dlp->dl_group_address = dhi.dhi_isgroup; 943 944 /* 945 * Copy in the source address. 946 */ 947 saddr = dlwp->dl_src_addr; 948 dlp->dl_src_addr_offset = (uintptr_t)saddr - (uintptr_t)dlp; 949 bcopy(dhi.dhi_saddr, saddr, addr_length); 950 951 /* 952 * Set the source DLSAP to the packet ethertype. 953 */ 954 *(uint16_t *)(saddr + addr_length) = dhi.dhi_ethertype; 955 dlp->dl_src_addr_length = addr_length + sizeof (uint16_t); 956 957 return (nmp); 958 } 959 960 /* 961 * DL_NOTIFY_IND: DL_NOTE_PROMISC_ON_PHYS 962 */ 963 static void 964 str_notify_promisc_on_phys(dld_str_t *dsp) 965 { 966 mblk_t *mp; 967 dl_notify_ind_t *dlip; 968 969 if (!(dsp->ds_notifications & DL_NOTE_PROMISC_ON_PHYS)) 970 return; 971 972 if ((mp = mexchange(dsp->ds_wq, NULL, sizeof (dl_notify_ind_t), 973 M_PROTO, 0)) == NULL) 974 return; 975 976 bzero(mp->b_rptr, sizeof (dl_notify_ind_t)); 977 dlip = (dl_notify_ind_t *)mp->b_rptr; 978 dlip->dl_primitive = DL_NOTIFY_IND; 979 dlip->dl_notification = DL_NOTE_PROMISC_ON_PHYS; 980 981 qreply(dsp->ds_wq, mp); 982 } 983 984 /* 985 * DL_NOTIFY_IND: DL_NOTE_PROMISC_OFF_PHYS 986 */ 987 static void 988 str_notify_promisc_off_phys(dld_str_t *dsp) 989 { 990 mblk_t *mp; 991 dl_notify_ind_t *dlip; 992 993 if (!(dsp->ds_notifications & DL_NOTE_PROMISC_OFF_PHYS)) 994 return; 995 996 if ((mp = mexchange(dsp->ds_wq, NULL, sizeof (dl_notify_ind_t), 997 M_PROTO, 0)) == NULL) 998 return; 999 1000 bzero(mp->b_rptr, sizeof (dl_notify_ind_t)); 1001 dlip = (dl_notify_ind_t *)mp->b_rptr; 1002 dlip->dl_primitive = DL_NOTIFY_IND; 1003 dlip->dl_notification = DL_NOTE_PROMISC_OFF_PHYS; 1004 1005 qreply(dsp->ds_wq, mp); 1006 } 1007 1008 /* 1009 * DL_NOTIFY_IND: DL_NOTE_PHYS_ADDR 1010 */ 1011 static void 1012 str_notify_phys_addr(dld_str_t *dsp, const uint8_t *addr) 1013 { 1014 mblk_t *mp; 1015 dl_notify_ind_t *dlip; 1016 uint_t addr_length; 1017 uint16_t ethertype; 1018 1019 if (!(dsp->ds_notifications & DL_NOTE_PHYS_ADDR)) 1020 return; 1021 1022 addr_length = dsp->ds_mip->mi_addr_length; 1023 if ((mp = mexchange(dsp->ds_wq, NULL, 1024 sizeof (dl_notify_ind_t) + addr_length + sizeof (uint16_t), 1025 M_PROTO, 0)) == NULL) 1026 return; 1027 1028 bzero(mp->b_rptr, sizeof (dl_notify_ind_t)); 1029 dlip = (dl_notify_ind_t *)mp->b_rptr; 1030 dlip->dl_primitive = DL_NOTIFY_IND; 1031 dlip->dl_notification = DL_NOTE_PHYS_ADDR; 1032 dlip->dl_data = DL_CURR_PHYS_ADDR; 1033 dlip->dl_addr_offset = sizeof (dl_notify_ind_t); 1034 dlip->dl_addr_length = addr_length + sizeof (uint16_t); 1035 1036 bcopy(addr, &dlip[1], addr_length); 1037 1038 ethertype = (dsp->ds_sap < ETHERTYPE_802_MIN) ? 0 : dsp->ds_sap; 1039 *(uint16_t *)((uchar_t *)(dlip + 1) + addr_length) = 1040 ethertype; 1041 1042 qreply(dsp->ds_wq, mp); 1043 } 1044 1045 /* 1046 * DL_NOTIFY_IND: DL_NOTE_LINK_UP 1047 */ 1048 static void 1049 str_notify_link_up(dld_str_t *dsp) 1050 { 1051 mblk_t *mp; 1052 dl_notify_ind_t *dlip; 1053 1054 if (!(dsp->ds_notifications & DL_NOTE_LINK_UP)) 1055 return; 1056 1057 if ((mp = mexchange(dsp->ds_wq, NULL, sizeof (dl_notify_ind_t), 1058 M_PROTO, 0)) == NULL) 1059 return; 1060 1061 bzero(mp->b_rptr, sizeof (dl_notify_ind_t)); 1062 dlip = (dl_notify_ind_t *)mp->b_rptr; 1063 dlip->dl_primitive = DL_NOTIFY_IND; 1064 dlip->dl_notification = DL_NOTE_LINK_UP; 1065 1066 qreply(dsp->ds_wq, mp); 1067 } 1068 1069 /* 1070 * DL_NOTIFY_IND: DL_NOTE_LINK_DOWN 1071 */ 1072 static void 1073 str_notify_link_down(dld_str_t *dsp) 1074 { 1075 mblk_t *mp; 1076 dl_notify_ind_t *dlip; 1077 1078 if (!(dsp->ds_notifications & DL_NOTE_LINK_DOWN)) 1079 return; 1080 1081 if ((mp = mexchange(dsp->ds_wq, NULL, sizeof (dl_notify_ind_t), 1082 M_PROTO, 0)) == NULL) 1083 return; 1084 1085 bzero(mp->b_rptr, sizeof (dl_notify_ind_t)); 1086 dlip = (dl_notify_ind_t *)mp->b_rptr; 1087 dlip->dl_primitive = DL_NOTIFY_IND; 1088 dlip->dl_notification = DL_NOTE_LINK_DOWN; 1089 1090 qreply(dsp->ds_wq, mp); 1091 } 1092 1093 /* 1094 * DL_NOTIFY_IND: DL_NOTE_SPEED 1095 */ 1096 static void 1097 str_notify_speed(dld_str_t *dsp, uint32_t speed) 1098 { 1099 mblk_t *mp; 1100 dl_notify_ind_t *dlip; 1101 1102 if (!(dsp->ds_notifications & DL_NOTE_SPEED)) 1103 return; 1104 1105 if ((mp = mexchange(dsp->ds_wq, NULL, sizeof (dl_notify_ind_t), 1106 M_PROTO, 0)) == NULL) 1107 return; 1108 1109 bzero(mp->b_rptr, sizeof (dl_notify_ind_t)); 1110 dlip = (dl_notify_ind_t *)mp->b_rptr; 1111 dlip->dl_primitive = DL_NOTIFY_IND; 1112 dlip->dl_notification = DL_NOTE_SPEED; 1113 dlip->dl_data = speed; 1114 1115 qreply(dsp->ds_wq, mp); 1116 } 1117 1118 /* 1119 * DL_NOTIFY_IND: DL_NOTE_CAPAB_RENEG 1120 */ 1121 static void 1122 str_notify_capab_reneg(dld_str_t *dsp) 1123 { 1124 mblk_t *mp; 1125 dl_notify_ind_t *dlip; 1126 1127 if (!(dsp->ds_notifications & DL_NOTE_CAPAB_RENEG)) 1128 return; 1129 1130 if ((mp = mexchange(dsp->ds_wq, NULL, sizeof (dl_notify_ind_t), 1131 M_PROTO, 0)) == NULL) 1132 return; 1133 1134 bzero(mp->b_rptr, sizeof (dl_notify_ind_t)); 1135 dlip = (dl_notify_ind_t *)mp->b_rptr; 1136 dlip->dl_primitive = DL_NOTIFY_IND; 1137 dlip->dl_notification = DL_NOTE_CAPAB_RENEG; 1138 1139 qreply(dsp->ds_wq, mp); 1140 } 1141 1142 /* 1143 * MAC notification callback. 1144 */ 1145 static void 1146 str_notify(void *arg, mac_notify_type_t type) 1147 { 1148 dld_str_t *dsp = (dld_str_t *)arg; 1149 queue_t *q = dsp->ds_wq; 1150 1151 switch (type) { 1152 case MAC_NOTE_TX: 1153 enableok(q); 1154 qenable(q); 1155 break; 1156 1157 case MAC_NOTE_DEVPROMISC: 1158 /* 1159 * Send the appropriate DL_NOTIFY_IND. 1160 */ 1161 if (mac_promisc_get(dsp->ds_mh, MAC_DEVPROMISC)) 1162 str_notify_promisc_on_phys(dsp); 1163 else 1164 str_notify_promisc_off_phys(dsp); 1165 break; 1166 1167 case MAC_NOTE_PROMISC: 1168 break; 1169 1170 case MAC_NOTE_UNICST: 1171 /* 1172 * This notification is sent whenever the MAC unicast address 1173 * changes. We need to re-cache the address. 1174 */ 1175 mac_unicst_get(dsp->ds_mh, dsp->ds_curr_addr); 1176 1177 /* 1178 * Send the appropriate DL_NOTIFY_IND. 1179 */ 1180 str_notify_phys_addr(dsp, dsp->ds_curr_addr); 1181 break; 1182 1183 case MAC_NOTE_LINK: 1184 /* 1185 * This notification is sent every time the MAC driver 1186 * updates the link state. 1187 */ 1188 switch (mac_link_get(dsp->ds_mh)) { 1189 case LINK_STATE_UP: 1190 /* 1191 * The link is up so send the appropriate 1192 * DL_NOTIFY_IND. 1193 */ 1194 str_notify_link_up(dsp); 1195 1196 /* 1197 * If we can find the link speed then send a 1198 * DL_NOTIFY_IND for that too. 1199 */ 1200 if (dsp->ds_mip->mi_stat[MAC_STAT_IFSPEED]) { 1201 uint64_t val; 1202 1203 val = mac_stat_get(dsp->ds_mh, 1204 MAC_STAT_IFSPEED); 1205 str_notify_speed(dsp, 1206 (uint32_t)(val / 1000ull)); 1207 } 1208 break; 1209 1210 case LINK_STATE_DOWN: 1211 /* 1212 * The link is down so send the appropriate 1213 * DL_NOTIFY_IND. 1214 */ 1215 str_notify_link_down(dsp); 1216 break; 1217 1218 default: 1219 break; 1220 } 1221 break; 1222 1223 case MAC_NOTE_RESOURCE: 1224 /* 1225 * This notification is sent whenever the MAC resources 1226 * change. We need to renegotiate the capabilities. 1227 * Send the appropriate DL_NOTIFY_IND. 1228 */ 1229 str_notify_capab_reneg(dsp); 1230 break; 1231 1232 default: 1233 ASSERT(B_FALSE); 1234 break; 1235 } 1236 } 1237 1238 /* 1239 * Put a chain of packets back on the queue. 1240 */ 1241 static void 1242 str_putbq(queue_t *q, mblk_t *mp) 1243 { 1244 mblk_t *bp = NULL; 1245 mblk_t *nextp; 1246 1247 /* 1248 * Reverse the order of the chain. 1249 */ 1250 while (mp != NULL) { 1251 nextp = mp->b_next; 1252 1253 mp->b_next = bp; 1254 bp = mp; 1255 1256 mp = nextp; 1257 } 1258 1259 /* 1260 * Walk the reversed chain and put each message back on the 1261 * queue. 1262 */ 1263 while (bp != NULL) { 1264 nextp = bp->b_next; 1265 bp->b_next = NULL; 1266 1267 (void) putbq(q, bp); 1268 1269 bp = nextp; 1270 } 1271 } 1272