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 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * MAC Services Module 30 */ 31 32 #include <sys/types.h> 33 #include <sys/conf.h> 34 #include <sys/stat.h> 35 #include <sys/stream.h> 36 #include <sys/strsun.h> 37 #include <sys/strsubr.h> 38 #include <sys/dlpi.h> 39 #include <sys/modhash.h> 40 #include <sys/mac.h> 41 #include <sys/mac_impl.h> 42 #include <sys/dls.h> 43 #include <sys/dld.h> 44 #include <sys/modctl.h> 45 #include <sys/fs/dv_node.h> 46 #include <sys/thread.h> 47 #include <sys/proc.h> 48 #include <sys/callb.h> 49 #include <sys/cpuvar.h> 50 #include <sys/atomic.h> 51 #include <sys/sdt.h> 52 53 #define IMPL_HASHSZ 67 /* prime */ 54 55 static kmem_cache_t *i_mac_impl_cachep; 56 static mod_hash_t *i_mac_impl_hash; 57 krwlock_t i_mac_impl_lock; 58 uint_t i_mac_impl_count; 59 60 #define MACTYPE_KMODDIR "mac" 61 #define MACTYPE_HASHSZ 67 62 static mod_hash_t *i_mactype_hash; 63 /* 64 * i_mactype_lock synchronizes threads that obtain references to mactype_t 65 * structures through i_mactype_getplugin(). 66 */ 67 static kmutex_t i_mactype_lock; 68 69 static void i_mac_notify_thread(void *); 70 71 /* 72 * Private functions. 73 */ 74 75 /*ARGSUSED*/ 76 static int 77 i_mac_constructor(void *buf, void *arg, int kmflag) 78 { 79 mac_impl_t *mip = buf; 80 81 bzero(buf, sizeof (mac_impl_t)); 82 83 mip->mi_linkstate = LINK_STATE_UNKNOWN; 84 85 rw_init(&mip->mi_state_lock, NULL, RW_DRIVER, NULL); 86 rw_init(&mip->mi_data_lock, NULL, RW_DRIVER, NULL); 87 rw_init(&mip->mi_notify_lock, NULL, RW_DRIVER, NULL); 88 rw_init(&mip->mi_rx_lock, NULL, RW_DRIVER, NULL); 89 rw_init(&mip->mi_txloop_lock, NULL, RW_DRIVER, NULL); 90 rw_init(&mip->mi_resource_lock, NULL, RW_DRIVER, NULL); 91 mutex_init(&mip->mi_activelink_lock, NULL, MUTEX_DEFAULT, NULL); 92 mutex_init(&mip->mi_notify_bits_lock, NULL, MUTEX_DRIVER, NULL); 93 cv_init(&mip->mi_notify_cv, NULL, CV_DRIVER, NULL); 94 mutex_init(&mip->mi_lock, NULL, MUTEX_DRIVER, NULL); 95 cv_init(&mip->mi_rx_cv, NULL, CV_DRIVER, NULL); 96 return (0); 97 } 98 99 /*ARGSUSED*/ 100 static void 101 i_mac_destructor(void *buf, void *arg) 102 { 103 mac_impl_t *mip = buf; 104 105 ASSERT(mip->mi_ref == 0); 106 ASSERT(mip->mi_active == 0); 107 ASSERT(mip->mi_linkstate == LINK_STATE_UNKNOWN); 108 ASSERT(mip->mi_devpromisc == 0); 109 ASSERT(mip->mi_promisc == 0); 110 ASSERT(mip->mi_mmap == NULL); 111 ASSERT(mip->mi_mnfp == NULL); 112 ASSERT(mip->mi_resource_add == NULL); 113 ASSERT(mip->mi_ksp == NULL); 114 ASSERT(mip->mi_kstat_count == 0); 115 ASSERT(mip->mi_notify_bits == 0); 116 ASSERT(mip->mi_notify_thread == NULL); 117 118 rw_destroy(&mip->mi_state_lock); 119 rw_destroy(&mip->mi_data_lock); 120 rw_destroy(&mip->mi_notify_lock); 121 rw_destroy(&mip->mi_rx_lock); 122 rw_destroy(&mip->mi_txloop_lock); 123 rw_destroy(&mip->mi_resource_lock); 124 mutex_destroy(&mip->mi_activelink_lock); 125 mutex_destroy(&mip->mi_notify_bits_lock); 126 cv_destroy(&mip->mi_notify_cv); 127 mutex_destroy(&mip->mi_lock); 128 cv_destroy(&mip->mi_rx_cv); 129 } 130 131 static void 132 i_mac_notify(mac_impl_t *mip, mac_notify_type_t type) 133 { 134 rw_enter(&i_mac_impl_lock, RW_READER); 135 if (mip->mi_disabled) 136 goto exit; 137 138 /* 139 * Guard against incorrect notifications. (Running a newer 140 * mac client against an older implementation?) 141 */ 142 if (type >= MAC_NNOTE) 143 goto exit; 144 145 mutex_enter(&mip->mi_notify_bits_lock); 146 mip->mi_notify_bits |= (1 << type); 147 cv_broadcast(&mip->mi_notify_cv); 148 mutex_exit(&mip->mi_notify_bits_lock); 149 150 exit: 151 rw_exit(&i_mac_impl_lock); 152 } 153 154 static void 155 i_mac_log_link_state(mac_impl_t *mip) 156 { 157 /* 158 * If no change, then it is not interesting. 159 */ 160 if (mip->mi_lastlinkstate == mip->mi_linkstate) 161 return; 162 163 switch (mip->mi_linkstate) { 164 case LINK_STATE_UP: 165 if (mip->mi_type->mt_ops.mtops_ops & MTOPS_LINK_DETAILS) { 166 char det[200]; 167 168 mip->mi_type->mt_ops.mtops_link_details(det, 169 sizeof (det), (mac_handle_t)mip, mip->mi_pdata); 170 171 cmn_err(CE_NOTE, "!%s link up, %s", mip->mi_name, det); 172 } else { 173 cmn_err(CE_NOTE, "!%s link up", mip->mi_name); 174 } 175 break; 176 177 case LINK_STATE_DOWN: 178 /* 179 * Only transitions from UP to DOWN are interesting 180 */ 181 if (mip->mi_lastlinkstate != LINK_STATE_UNKNOWN) 182 cmn_err(CE_NOTE, "!%s link down", mip->mi_name); 183 break; 184 185 case LINK_STATE_UNKNOWN: 186 /* 187 * This case is normally not interesting. 188 */ 189 break; 190 } 191 mip->mi_lastlinkstate = mip->mi_linkstate; 192 } 193 194 static void 195 i_mac_notify_thread(void *arg) 196 { 197 mac_impl_t *mip = arg; 198 callb_cpr_t cprinfo; 199 200 CALLB_CPR_INIT(&cprinfo, &mip->mi_notify_bits_lock, callb_generic_cpr, 201 "i_mac_notify_thread"); 202 203 mutex_enter(&mip->mi_notify_bits_lock); 204 for (;;) { 205 uint32_t bits; 206 uint32_t type; 207 208 bits = mip->mi_notify_bits; 209 if (bits == 0) { 210 CALLB_CPR_SAFE_BEGIN(&cprinfo); 211 cv_wait(&mip->mi_notify_cv, &mip->mi_notify_bits_lock); 212 CALLB_CPR_SAFE_END(&cprinfo, &mip->mi_notify_bits_lock); 213 continue; 214 } 215 mip->mi_notify_bits = 0; 216 217 if ((bits & (1 << MAC_NNOTE)) != 0) { 218 /* request to quit */ 219 ASSERT(mip->mi_disabled); 220 break; 221 } 222 223 mutex_exit(&mip->mi_notify_bits_lock); 224 225 /* 226 * Log link changes. 227 */ 228 if ((bits & (1 << MAC_NOTE_LINK)) != 0) 229 i_mac_log_link_state(mip); 230 231 /* 232 * Do notification callbacks for each notification type. 233 */ 234 for (type = 0; type < MAC_NNOTE; type++) { 235 mac_notify_fn_t *mnfp; 236 237 if ((bits & (1 << type)) == 0) { 238 continue; 239 } 240 241 /* 242 * Walk the list of notifications. 243 */ 244 rw_enter(&mip->mi_notify_lock, RW_READER); 245 for (mnfp = mip->mi_mnfp; mnfp != NULL; 246 mnfp = mnfp->mnf_nextp) { 247 248 mnfp->mnf_fn(mnfp->mnf_arg, type); 249 } 250 rw_exit(&mip->mi_notify_lock); 251 } 252 253 mutex_enter(&mip->mi_notify_bits_lock); 254 } 255 256 mip->mi_notify_thread = NULL; 257 cv_broadcast(&mip->mi_notify_cv); 258 259 CALLB_CPR_EXIT(&cprinfo); 260 261 thread_exit(); 262 } 263 264 static mactype_t * 265 i_mactype_getplugin(const char *pname) 266 { 267 mactype_t *mtype = NULL; 268 boolean_t tried_modload = B_FALSE; 269 270 mutex_enter(&i_mactype_lock); 271 272 find_registered_mactype: 273 if (mod_hash_find(i_mactype_hash, (mod_hash_key_t)pname, 274 (mod_hash_val_t *)&mtype) != 0) { 275 if (!tried_modload) { 276 /* 277 * If the plugin has not yet been loaded, then 278 * attempt to load it now. If modload() succeeds, 279 * the plugin should have registered using 280 * mactype_register(), in which case we can go back 281 * and attempt to find it again. 282 */ 283 if (modload(MACTYPE_KMODDIR, (char *)pname) != -1) { 284 tried_modload = B_TRUE; 285 goto find_registered_mactype; 286 } 287 } 288 } else { 289 /* 290 * Note that there's no danger that the plugin we've loaded 291 * could be unloaded between the modload() step and the 292 * reference count bump here, as we're holding 293 * i_mactype_lock, which mactype_unregister() also holds. 294 */ 295 atomic_inc_32(&mtype->mt_ref); 296 } 297 298 mutex_exit(&i_mactype_lock); 299 return (mtype); 300 } 301 302 /* 303 * Module initialization functions. 304 */ 305 306 void 307 mac_init(void) 308 { 309 i_mac_impl_cachep = kmem_cache_create("mac_impl_cache", 310 sizeof (mac_impl_t), 0, i_mac_constructor, i_mac_destructor, 311 NULL, NULL, NULL, 0); 312 ASSERT(i_mac_impl_cachep != NULL); 313 314 i_mac_impl_hash = mod_hash_create_extended("mac_impl_hash", 315 IMPL_HASHSZ, mod_hash_null_keydtor, mod_hash_null_valdtor, 316 mod_hash_bystr, NULL, mod_hash_strkey_cmp, KM_SLEEP); 317 rw_init(&i_mac_impl_lock, NULL, RW_DEFAULT, NULL); 318 i_mac_impl_count = 0; 319 320 i_mactype_hash = mod_hash_create_extended("mactype_hash", 321 MACTYPE_HASHSZ, 322 mod_hash_null_keydtor, mod_hash_null_valdtor, 323 mod_hash_bystr, NULL, mod_hash_strkey_cmp, KM_SLEEP); 324 } 325 326 int 327 mac_fini(void) 328 { 329 if (i_mac_impl_count > 0) 330 return (EBUSY); 331 332 mod_hash_destroy_hash(i_mac_impl_hash); 333 rw_destroy(&i_mac_impl_lock); 334 335 kmem_cache_destroy(i_mac_impl_cachep); 336 337 mod_hash_destroy_hash(i_mactype_hash); 338 return (0); 339 } 340 341 /* 342 * Client functions. 343 */ 344 345 int 346 mac_open(const char *macname, uint_t ddi_instance, mac_handle_t *mhp) 347 { 348 char driver[MAXNAMELEN]; 349 uint_t instance; 350 major_t major; 351 dev_info_t *dip; 352 mac_impl_t *mip; 353 int err; 354 355 /* 356 * Check the device name length to make sure it won't overflow our 357 * buffer. 358 */ 359 if (strlen(macname) >= MAXNAMELEN) 360 return (EINVAL); 361 362 /* 363 * Split the device name into driver and instance components. 364 */ 365 if (ddi_parse(macname, driver, &instance) != DDI_SUCCESS) 366 return (EINVAL); 367 368 /* 369 * Get the major number of the driver. 370 */ 371 if ((major = ddi_name_to_major(driver)) == (major_t)-1) 372 return (EINVAL); 373 374 /* 375 * Hold the given instance to prevent it from being detached. 376 * This will also attach the instance if it is not currently attached. 377 * Currently we ensure that mac_register() (called by the driver's 378 * attach entry point) and all code paths under it cannot possibly 379 * call mac_open() because this would lead to a recursive attach 380 * panic. 381 */ 382 if ((dip = ddi_hold_devi_by_instance(major, ddi_instance, 0)) == NULL) 383 return (EINVAL); 384 385 /* 386 * Look up its entry in the global hash table. 387 */ 388 again: 389 rw_enter(&i_mac_impl_lock, RW_WRITER); 390 err = mod_hash_find(i_mac_impl_hash, (mod_hash_key_t)macname, 391 (mod_hash_val_t *)&mip); 392 if (err != 0) { 393 err = ENOENT; 394 goto failed; 395 } 396 397 if (mip->mi_disabled) { 398 rw_exit(&i_mac_impl_lock); 399 goto again; 400 } 401 402 mip->mi_ref++; 403 rw_exit(&i_mac_impl_lock); 404 405 *mhp = (mac_handle_t)mip; 406 return (0); 407 408 failed: 409 rw_exit(&i_mac_impl_lock); 410 ddi_release_devi(dip); 411 return (err); 412 } 413 414 void 415 mac_close(mac_handle_t mh) 416 { 417 mac_impl_t *mip = (mac_impl_t *)mh; 418 dev_info_t *dip = mip->mi_dip; 419 420 rw_enter(&i_mac_impl_lock, RW_WRITER); 421 422 ASSERT(mip->mi_ref != 0); 423 if (--mip->mi_ref == 0) { 424 ASSERT(!mip->mi_activelink); 425 } 426 ddi_release_devi(dip); 427 rw_exit(&i_mac_impl_lock); 428 } 429 430 const mac_info_t * 431 mac_info(mac_handle_t mh) 432 { 433 return (&((mac_impl_t *)mh)->mi_info); 434 } 435 436 dev_info_t * 437 mac_devinfo_get(mac_handle_t mh) 438 { 439 return (((mac_impl_t *)mh)->mi_dip); 440 } 441 442 uint64_t 443 mac_stat_get(mac_handle_t mh, uint_t stat) 444 { 445 mac_impl_t *mip = (mac_impl_t *)mh; 446 uint64_t val; 447 int ret; 448 449 /* 450 * The range of stat determines where it is maintained. Stat 451 * values from 0 up to (but not including) MAC_STAT_MIN are 452 * mainteined by the mac module itself. Everything else is 453 * maintained by the driver. 454 */ 455 if (stat < MAC_STAT_MIN) { 456 /* These stats are maintained by the mac module itself. */ 457 switch (stat) { 458 case MAC_STAT_LINK_STATE: 459 return (mip->mi_linkstate); 460 case MAC_STAT_LINK_UP: 461 return (mip->mi_linkstate == LINK_STATE_UP); 462 case MAC_STAT_PROMISC: 463 return (mip->mi_devpromisc != 0); 464 default: 465 ASSERT(B_FALSE); 466 } 467 } 468 469 /* 470 * Call the driver to get the given statistic. 471 */ 472 ret = mip->mi_getstat(mip->mi_driver, stat, &val); 473 if (ret != 0) { 474 /* 475 * The driver doesn't support this statistic. Get the 476 * statistic's default value. 477 */ 478 val = mac_stat_default(mip, stat); 479 } 480 return (val); 481 } 482 483 int 484 mac_start(mac_handle_t mh) 485 { 486 mac_impl_t *mip = (mac_impl_t *)mh; 487 int err; 488 489 ASSERT(mip->mi_start != NULL); 490 491 rw_enter(&(mip->mi_state_lock), RW_WRITER); 492 493 /* 494 * Check whether the device is already started. 495 */ 496 if (mip->mi_active++ != 0) { 497 /* 498 * It's already started so there's nothing more to do. 499 */ 500 err = 0; 501 goto done; 502 } 503 504 /* 505 * Start the device. 506 */ 507 if ((err = mip->mi_start(mip->mi_driver)) != 0) 508 --mip->mi_active; 509 510 done: 511 rw_exit(&(mip->mi_state_lock)); 512 return (err); 513 } 514 515 void 516 mac_stop(mac_handle_t mh) 517 { 518 mac_impl_t *mip = (mac_impl_t *)mh; 519 520 ASSERT(mip->mi_stop != NULL); 521 522 rw_enter(&(mip->mi_state_lock), RW_WRITER); 523 524 /* 525 * Check whether the device is still needed. 526 */ 527 ASSERT(mip->mi_active != 0); 528 if (--mip->mi_active != 0) { 529 /* 530 * It's still needed so there's nothing more to do. 531 */ 532 goto done; 533 } 534 535 /* 536 * Stop the device. 537 */ 538 mip->mi_stop(mip->mi_driver); 539 540 done: 541 rw_exit(&(mip->mi_state_lock)); 542 } 543 544 int 545 mac_multicst_add(mac_handle_t mh, const uint8_t *addr) 546 { 547 mac_impl_t *mip = (mac_impl_t *)mh; 548 mac_multicst_addr_t **pp; 549 mac_multicst_addr_t *p; 550 int err; 551 552 ASSERT(mip->mi_multicst != NULL); 553 554 /* 555 * Verify the address. 556 */ 557 if ((err = mip->mi_type->mt_ops.mtops_multicst_verify(addr, 558 mip->mi_pdata)) != 0) { 559 return (err); 560 } 561 562 /* 563 * Check whether the given address is already enabled. 564 */ 565 rw_enter(&(mip->mi_data_lock), RW_WRITER); 566 for (pp = &(mip->mi_mmap); (p = *pp) != NULL; pp = &(p->mma_nextp)) { 567 if (bcmp(p->mma_addr, addr, mip->mi_type->mt_addr_length) == 568 0) { 569 /* 570 * The address is already enabled so just bump the 571 * reference count. 572 */ 573 p->mma_ref++; 574 err = 0; 575 goto done; 576 } 577 } 578 579 /* 580 * Allocate a new list entry. 581 */ 582 if ((p = kmem_zalloc(sizeof (mac_multicst_addr_t), 583 KM_NOSLEEP)) == NULL) { 584 err = ENOMEM; 585 goto done; 586 } 587 588 /* 589 * Enable a new multicast address. 590 */ 591 if ((err = mip->mi_multicst(mip->mi_driver, B_TRUE, addr)) != 0) { 592 kmem_free(p, sizeof (mac_multicst_addr_t)); 593 goto done; 594 } 595 596 /* 597 * Add the address to the list of enabled addresses. 598 */ 599 bcopy(addr, p->mma_addr, mip->mi_type->mt_addr_length); 600 p->mma_ref++; 601 *pp = p; 602 603 done: 604 rw_exit(&(mip->mi_data_lock)); 605 return (err); 606 } 607 608 int 609 mac_multicst_remove(mac_handle_t mh, const uint8_t *addr) 610 { 611 mac_impl_t *mip = (mac_impl_t *)mh; 612 mac_multicst_addr_t **pp; 613 mac_multicst_addr_t *p; 614 int err; 615 616 ASSERT(mip->mi_multicst != NULL); 617 618 /* 619 * Find the entry in the list for the given address. 620 */ 621 rw_enter(&(mip->mi_data_lock), RW_WRITER); 622 for (pp = &(mip->mi_mmap); (p = *pp) != NULL; pp = &(p->mma_nextp)) { 623 if (bcmp(p->mma_addr, addr, mip->mi_type->mt_addr_length) == 624 0) { 625 if (--p->mma_ref == 0) 626 break; 627 628 /* 629 * There is still a reference to this address so 630 * there's nothing more to do. 631 */ 632 err = 0; 633 goto done; 634 } 635 } 636 637 /* 638 * We did not find an entry for the given address so it is not 639 * currently enabled. 640 */ 641 if (p == NULL) { 642 err = ENOENT; 643 goto done; 644 } 645 ASSERT(p->mma_ref == 0); 646 647 /* 648 * Disable the multicast address. 649 */ 650 if ((err = mip->mi_multicst(mip->mi_driver, B_FALSE, addr)) != 0) { 651 p->mma_ref++; 652 goto done; 653 } 654 655 /* 656 * Remove it from the list. 657 */ 658 *pp = p->mma_nextp; 659 kmem_free(p, sizeof (mac_multicst_addr_t)); 660 661 done: 662 rw_exit(&(mip->mi_data_lock)); 663 return (err); 664 } 665 666 /* 667 * mac_unicst_verify: Verifies the passed address. It fails 668 * if the passed address is a group address or has incorrect length. 669 */ 670 boolean_t 671 mac_unicst_verify(mac_handle_t mh, const uint8_t *addr, uint_t len) 672 { 673 mac_impl_t *mip = (mac_impl_t *)mh; 674 675 /* 676 * Verify the address. 677 */ 678 if ((len != mip->mi_type->mt_addr_length) || 679 (mip->mi_type->mt_ops.mtops_unicst_verify(addr, 680 mip->mi_pdata)) != 0) { 681 return (B_FALSE); 682 } else { 683 return (B_TRUE); 684 } 685 } 686 687 int 688 mac_unicst_set(mac_handle_t mh, const uint8_t *addr) 689 { 690 mac_impl_t *mip = (mac_impl_t *)mh; 691 int err; 692 boolean_t notify = B_FALSE; 693 694 ASSERT(mip->mi_unicst != NULL); 695 696 /* 697 * Verify the address. 698 */ 699 if ((err = mip->mi_type->mt_ops.mtops_unicst_verify(addr, 700 mip->mi_pdata)) != 0) { 701 return (err); 702 } 703 704 /* 705 * Program the new unicast address. 706 */ 707 rw_enter(&(mip->mi_data_lock), RW_WRITER); 708 709 /* 710 * If address doesn't change, do nothing. 711 * This check is necessary otherwise it may call into mac_unicst_set 712 * recursively. 713 */ 714 if (bcmp(addr, mip->mi_addr, mip->mi_type->mt_addr_length) == 0) { 715 err = 0; 716 goto done; 717 } 718 719 if ((err = mip->mi_unicst(mip->mi_driver, addr)) != 0) 720 goto done; 721 722 /* 723 * Save the address and flag that we need to send a notification. 724 */ 725 bcopy(addr, mip->mi_addr, mip->mi_type->mt_addr_length); 726 notify = B_TRUE; 727 728 done: 729 rw_exit(&(mip->mi_data_lock)); 730 731 if (notify) 732 i_mac_notify(mip, MAC_NOTE_UNICST); 733 734 return (err); 735 } 736 737 void 738 mac_unicst_get(mac_handle_t mh, uint8_t *addr) 739 { 740 mac_impl_t *mip = (mac_impl_t *)mh; 741 742 /* 743 * Copy out the current unicast source address. 744 */ 745 rw_enter(&(mip->mi_data_lock), RW_READER); 746 bcopy(mip->mi_addr, addr, mip->mi_type->mt_addr_length); 747 rw_exit(&(mip->mi_data_lock)); 748 } 749 750 void 751 mac_dest_get(mac_handle_t mh, uint8_t *addr) 752 { 753 mac_impl_t *mip = (mac_impl_t *)mh; 754 755 /* 756 * Copy out the current destination address. 757 */ 758 rw_enter(&(mip->mi_data_lock), RW_READER); 759 bcopy(mip->mi_dstaddr, addr, mip->mi_type->mt_addr_length); 760 rw_exit(&(mip->mi_data_lock)); 761 } 762 763 int 764 mac_promisc_set(mac_handle_t mh, boolean_t on, mac_promisc_type_t ptype) 765 { 766 mac_impl_t *mip = (mac_impl_t *)mh; 767 int err = 0; 768 769 ASSERT(mip->mi_setpromisc != NULL); 770 ASSERT(ptype == MAC_DEVPROMISC || ptype == MAC_PROMISC); 771 772 /* 773 * Determine whether we should enable or disable promiscuous mode. 774 * For details on the distinction between "device promiscuous mode" 775 * and "MAC promiscuous mode", see PSARC/2005/289. 776 */ 777 rw_enter(&(mip->mi_data_lock), RW_WRITER); 778 if (on) { 779 /* 780 * Enable promiscuous mode on the device if not yet enabled. 781 */ 782 if (mip->mi_devpromisc++ == 0) { 783 err = mip->mi_setpromisc(mip->mi_driver, B_TRUE); 784 if (err != 0) { 785 mip->mi_devpromisc--; 786 goto done; 787 } 788 i_mac_notify(mip, MAC_NOTE_DEVPROMISC); 789 } 790 791 /* 792 * Enable promiscuous mode on the MAC if not yet enabled. 793 */ 794 if (ptype == MAC_PROMISC && mip->mi_promisc++ == 0) 795 i_mac_notify(mip, MAC_NOTE_PROMISC); 796 } else { 797 if (mip->mi_devpromisc == 0) { 798 err = EPROTO; 799 goto done; 800 } 801 802 /* 803 * Disable promiscuous mode on the device if this is the last 804 * enabling. 805 */ 806 if (--mip->mi_devpromisc == 0) { 807 err = mip->mi_setpromisc(mip->mi_driver, B_FALSE); 808 if (err != 0) { 809 mip->mi_devpromisc++; 810 goto done; 811 } 812 i_mac_notify(mip, MAC_NOTE_DEVPROMISC); 813 } 814 815 /* 816 * Disable promiscuous mode on the MAC if this is the last 817 * enabling. 818 */ 819 if (ptype == MAC_PROMISC && --mip->mi_promisc == 0) 820 i_mac_notify(mip, MAC_NOTE_PROMISC); 821 } 822 823 done: 824 rw_exit(&(mip->mi_data_lock)); 825 return (err); 826 } 827 828 boolean_t 829 mac_promisc_get(mac_handle_t mh, mac_promisc_type_t ptype) 830 { 831 mac_impl_t *mip = (mac_impl_t *)mh; 832 833 ASSERT(ptype == MAC_DEVPROMISC || ptype == MAC_PROMISC); 834 835 /* 836 * Return the current promiscuity. 837 */ 838 if (ptype == MAC_DEVPROMISC) 839 return (mip->mi_devpromisc != 0); 840 else 841 return (mip->mi_promisc != 0); 842 } 843 844 void 845 mac_resources(mac_handle_t mh) 846 { 847 mac_impl_t *mip = (mac_impl_t *)mh; 848 849 /* 850 * If the driver supports resource registration, call the driver to 851 * ask it to register its resources. 852 */ 853 if (mip->mi_callbacks->mc_callbacks & MC_RESOURCES) 854 mip->mi_resources(mip->mi_driver); 855 } 856 857 void 858 mac_ioctl(mac_handle_t mh, queue_t *wq, mblk_t *bp) 859 { 860 mac_impl_t *mip = (mac_impl_t *)mh; 861 862 /* 863 * Call the driver to handle the ioctl. The driver may not support 864 * any ioctls, in which case we reply with a NAK on its behalf. 865 */ 866 if (mip->mi_callbacks->mc_callbacks & MC_IOCTL) 867 mip->mi_ioctl(mip->mi_driver, wq, bp); 868 else 869 miocnak(wq, bp, 0, EINVAL); 870 } 871 872 const mac_txinfo_t * 873 mac_tx_get(mac_handle_t mh) 874 { 875 mac_impl_t *mip = (mac_impl_t *)mh; 876 mac_txinfo_t *mtp; 877 878 /* 879 * Grab the lock to prevent us from racing with MAC_PROMISC being 880 * changed. This is sufficient since MAC clients are careful to always 881 * call mac_txloop_add() prior to enabling MAC_PROMISC, and to disable 882 * MAC_PROMISC prior to calling mac_txloop_remove(). 883 */ 884 rw_enter(&mip->mi_txloop_lock, RW_READER); 885 886 if (mac_promisc_get(mh, MAC_PROMISC)) { 887 ASSERT(mip->mi_mtfp != NULL); 888 mtp = &mip->mi_txloopinfo; 889 } else { 890 /* 891 * Note that we cannot ASSERT() that mip->mi_mtfp is NULL, 892 * because to satisfy the above ASSERT(), we have to disable 893 * MAC_PROMISC prior to calling mac_txloop_remove(). 894 */ 895 mtp = &mip->mi_txinfo; 896 } 897 898 rw_exit(&mip->mi_txloop_lock); 899 return (mtp); 900 } 901 902 link_state_t 903 mac_link_get(mac_handle_t mh) 904 { 905 return (((mac_impl_t *)mh)->mi_linkstate); 906 } 907 908 mac_notify_handle_t 909 mac_notify_add(mac_handle_t mh, mac_notify_t notify, void *arg) 910 { 911 mac_impl_t *mip = (mac_impl_t *)mh; 912 mac_notify_fn_t *mnfp; 913 914 mnfp = kmem_zalloc(sizeof (mac_notify_fn_t), KM_SLEEP); 915 mnfp->mnf_fn = notify; 916 mnfp->mnf_arg = arg; 917 918 /* 919 * Add it to the head of the 'notify' callback list. 920 */ 921 rw_enter(&mip->mi_notify_lock, RW_WRITER); 922 mnfp->mnf_nextp = mip->mi_mnfp; 923 mip->mi_mnfp = mnfp; 924 rw_exit(&mip->mi_notify_lock); 925 926 return ((mac_notify_handle_t)mnfp); 927 } 928 929 void 930 mac_notify_remove(mac_handle_t mh, mac_notify_handle_t mnh) 931 { 932 mac_impl_t *mip = (mac_impl_t *)mh; 933 mac_notify_fn_t *mnfp = (mac_notify_fn_t *)mnh; 934 mac_notify_fn_t **pp; 935 mac_notify_fn_t *p; 936 937 /* 938 * Search the 'notify' callback list for the function closure. 939 */ 940 rw_enter(&mip->mi_notify_lock, RW_WRITER); 941 for (pp = &(mip->mi_mnfp); (p = *pp) != NULL; 942 pp = &(p->mnf_nextp)) { 943 if (p == mnfp) 944 break; 945 } 946 ASSERT(p != NULL); 947 948 /* 949 * Remove it from the list. 950 */ 951 *pp = p->mnf_nextp; 952 rw_exit(&mip->mi_notify_lock); 953 954 /* 955 * Free it. 956 */ 957 kmem_free(mnfp, sizeof (mac_notify_fn_t)); 958 } 959 960 void 961 mac_notify(mac_handle_t mh) 962 { 963 mac_impl_t *mip = (mac_impl_t *)mh; 964 mac_notify_type_t type; 965 966 for (type = 0; type < MAC_NNOTE; type++) 967 i_mac_notify(mip, type); 968 } 969 970 /* 971 * Register a receive function for this mac. 972 * More information on this function's interaction with mac_rx() 973 * can be found atop mac_rx(). 974 */ 975 mac_rx_handle_t 976 mac_rx_add(mac_handle_t mh, mac_rx_t rx, void *arg) 977 { 978 mac_impl_t *mip = (mac_impl_t *)mh; 979 mac_rx_fn_t *mrfp; 980 981 mrfp = kmem_zalloc(sizeof (mac_rx_fn_t), KM_SLEEP); 982 mrfp->mrf_fn = rx; 983 mrfp->mrf_arg = arg; 984 985 /* 986 * Add it to the head of the 'rx' callback list. 987 */ 988 rw_enter(&(mip->mi_rx_lock), RW_WRITER); 989 990 /* 991 * mac_rx() will only call callbacks that are marked inuse. 992 */ 993 mrfp->mrf_inuse = B_TRUE; 994 mrfp->mrf_nextp = mip->mi_mrfp; 995 996 /* 997 * mac_rx() could be traversing the remainder of the list 998 * and miss the new callback we're adding here. This is not a problem 999 * because we do not guarantee the callback to take effect immediately 1000 * after mac_rx_add() returns. 1001 */ 1002 mip->mi_mrfp = mrfp; 1003 rw_exit(&(mip->mi_rx_lock)); 1004 1005 return ((mac_rx_handle_t)mrfp); 1006 } 1007 1008 /* 1009 * Unregister a receive function for this mac. 1010 * This function does not block if wait is B_FALSE. This is useful 1011 * for clients who call mac_rx_remove() from a non-blockable context. 1012 * More information on this function's interaction with mac_rx() 1013 * can be found atop mac_rx(). 1014 */ 1015 void 1016 mac_rx_remove(mac_handle_t mh, mac_rx_handle_t mrh, boolean_t wait) 1017 { 1018 mac_impl_t *mip = (mac_impl_t *)mh; 1019 mac_rx_fn_t *mrfp = (mac_rx_fn_t *)mrh; 1020 mac_rx_fn_t **pp; 1021 mac_rx_fn_t *p; 1022 1023 /* 1024 * Search the 'rx' callback list for the function closure. 1025 */ 1026 rw_enter(&mip->mi_rx_lock, RW_WRITER); 1027 for (pp = &(mip->mi_mrfp); (p = *pp) != NULL; pp = &(p->mrf_nextp)) { 1028 if (p == mrfp) 1029 break; 1030 } 1031 ASSERT(p != NULL); 1032 1033 /* 1034 * If mac_rx() is running, mark callback for deletion 1035 * and return (if wait is false), or wait until mac_rx() 1036 * exits (if wait is true). 1037 */ 1038 if (mip->mi_rx_ref > 0) { 1039 DTRACE_PROBE1(defer_delete, mac_impl_t *, mip); 1040 p->mrf_inuse = B_FALSE; 1041 mutex_enter(&mip->mi_lock); 1042 mip->mi_rx_removed++; 1043 mutex_exit(&mip->mi_lock); 1044 1045 rw_exit(&mip->mi_rx_lock); 1046 if (wait) 1047 mac_rx_remove_wait(mh); 1048 return; 1049 } 1050 1051 /* Remove it from the list. */ 1052 *pp = p->mrf_nextp; 1053 kmem_free(mrfp, sizeof (mac_rx_fn_t)); 1054 rw_exit(&mip->mi_rx_lock); 1055 } 1056 1057 /* 1058 * Wait for all pending callback removals to be completed by mac_rx(). 1059 * Note that if we call mac_rx_remove() immediately before this, there is no 1060 * guarantee we would wait *only* on the callback that we specified. 1061 * mac_rx_remove() could have been called by other threads and we would have 1062 * to wait for other marked callbacks to be removed as well. 1063 */ 1064 void 1065 mac_rx_remove_wait(mac_handle_t mh) 1066 { 1067 mac_impl_t *mip = (mac_impl_t *)mh; 1068 1069 mutex_enter(&mip->mi_lock); 1070 while (mip->mi_rx_removed > 0) { 1071 DTRACE_PROBE1(need_wait, mac_impl_t *, mip); 1072 cv_wait(&mip->mi_rx_cv, &mip->mi_lock); 1073 } 1074 mutex_exit(&mip->mi_lock); 1075 } 1076 1077 mac_txloop_handle_t 1078 mac_txloop_add(mac_handle_t mh, mac_txloop_t tx, void *arg) 1079 { 1080 mac_impl_t *mip = (mac_impl_t *)mh; 1081 mac_txloop_fn_t *mtfp; 1082 1083 mtfp = kmem_zalloc(sizeof (mac_txloop_fn_t), KM_SLEEP); 1084 mtfp->mtf_fn = tx; 1085 mtfp->mtf_arg = arg; 1086 1087 /* 1088 * Add it to the head of the 'tx' callback list. 1089 */ 1090 rw_enter(&(mip->mi_txloop_lock), RW_WRITER); 1091 mtfp->mtf_nextp = mip->mi_mtfp; 1092 mip->mi_mtfp = mtfp; 1093 rw_exit(&(mip->mi_txloop_lock)); 1094 1095 return ((mac_txloop_handle_t)mtfp); 1096 } 1097 1098 /* 1099 * Unregister a transmit function for this mac. This removes the function 1100 * from the list of transmit functions for this mac. 1101 */ 1102 void 1103 mac_txloop_remove(mac_handle_t mh, mac_txloop_handle_t mth) 1104 { 1105 mac_impl_t *mip = (mac_impl_t *)mh; 1106 mac_txloop_fn_t *mtfp = (mac_txloop_fn_t *)mth; 1107 mac_txloop_fn_t **pp; 1108 mac_txloop_fn_t *p; 1109 1110 /* 1111 * Search the 'tx' callback list for the function. 1112 */ 1113 rw_enter(&(mip->mi_txloop_lock), RW_WRITER); 1114 for (pp = &(mip->mi_mtfp); (p = *pp) != NULL; pp = &(p->mtf_nextp)) { 1115 if (p == mtfp) 1116 break; 1117 } 1118 ASSERT(p != NULL); 1119 1120 /* Remove it from the list. */ 1121 *pp = p->mtf_nextp; 1122 kmem_free(mtfp, sizeof (mac_txloop_fn_t)); 1123 rw_exit(&(mip->mi_txloop_lock)); 1124 } 1125 1126 void 1127 mac_resource_set(mac_handle_t mh, mac_resource_add_t add, void *arg) 1128 { 1129 mac_impl_t *mip = (mac_impl_t *)mh; 1130 1131 /* 1132 * Update the 'resource_add' callbacks. 1133 */ 1134 rw_enter(&(mip->mi_resource_lock), RW_WRITER); 1135 mip->mi_resource_add = add; 1136 mip->mi_resource_add_arg = arg; 1137 rw_exit(&(mip->mi_resource_lock)); 1138 } 1139 1140 /* 1141 * Driver support functions. 1142 */ 1143 1144 mac_register_t * 1145 mac_alloc(uint_t mac_version) 1146 { 1147 mac_register_t *mregp; 1148 1149 /* 1150 * Make sure there isn't a version mismatch between the driver and 1151 * the framework. In the future, if multiple versions are 1152 * supported, this check could become more sophisticated. 1153 */ 1154 if (mac_version != MAC_VERSION) 1155 return (NULL); 1156 1157 mregp = kmem_zalloc(sizeof (mac_register_t), KM_SLEEP); 1158 mregp->m_version = mac_version; 1159 return (mregp); 1160 } 1161 1162 void 1163 mac_free(mac_register_t *mregp) 1164 { 1165 kmem_free(mregp, sizeof (mac_register_t)); 1166 } 1167 1168 /* 1169 * mac_register() is how drivers register new MACs with the GLDv3 1170 * framework. The mregp argument is allocated by drivers using the 1171 * mac_alloc() function, and can be freed using mac_free() immediately upon 1172 * return from mac_register(). Upon success (0 return value), the mhp 1173 * opaque pointer becomes the driver's handle to its MAC interface, and is 1174 * the argument to all other mac module entry points. 1175 */ 1176 int 1177 mac_register(mac_register_t *mregp, mac_handle_t *mhp) 1178 { 1179 mac_impl_t *mip; 1180 mactype_t *mtype; 1181 int err = EINVAL; 1182 struct devnames *dnp; 1183 minor_t minor; 1184 boolean_t style1_created = B_FALSE, style2_created = B_FALSE; 1185 1186 /* Find the required MAC-Type plugin. */ 1187 if ((mtype = i_mactype_getplugin(mregp->m_type_ident)) == NULL) 1188 return (EINVAL); 1189 1190 /* Create a mac_impl_t to represent this MAC. */ 1191 mip = kmem_cache_alloc(i_mac_impl_cachep, KM_SLEEP); 1192 1193 /* 1194 * The mac is not ready for open yet. 1195 */ 1196 mip->mi_disabled = B_TRUE; 1197 1198 mip->mi_drvname = ddi_driver_name(mregp->m_dip); 1199 /* 1200 * Some drivers such as aggr need to register multiple MACs. Such 1201 * drivers must supply a non-zero "instance" argument so that each 1202 * MAC can be assigned a unique MAC name and can have unique 1203 * kstats. 1204 */ 1205 mip->mi_instance = ((mregp->m_instance == 0) ? 1206 ddi_get_instance(mregp->m_dip) : mregp->m_instance); 1207 1208 /* Construct the MAC name as <drvname><instance> */ 1209 (void) snprintf(mip->mi_name, sizeof (mip->mi_name), "%s%d", 1210 mip->mi_drvname, mip->mi_instance); 1211 1212 mip->mi_driver = mregp->m_driver; 1213 1214 mip->mi_type = mtype; 1215 mip->mi_info.mi_media = mtype->mt_type; 1216 mip->mi_info.mi_nativemedia = mtype->mt_nativetype; 1217 mip->mi_info.mi_sdu_min = mregp->m_min_sdu; 1218 if (mregp->m_max_sdu <= mregp->m_min_sdu) 1219 goto fail; 1220 mip->mi_info.mi_sdu_max = mregp->m_max_sdu; 1221 mip->mi_info.mi_addr_length = mip->mi_type->mt_addr_length; 1222 /* 1223 * If the media supports a broadcast address, cache a pointer to it 1224 * in the mac_info_t so that upper layers can use it. 1225 */ 1226 mip->mi_info.mi_brdcst_addr = mip->mi_type->mt_brdcst_addr; 1227 1228 /* 1229 * Copy the unicast source address into the mac_info_t, but only if 1230 * the MAC-Type defines a non-zero address length. We need to 1231 * handle MAC-Types that have an address length of 0 1232 * (point-to-point protocol MACs for example). 1233 */ 1234 if (mip->mi_type->mt_addr_length > 0) { 1235 if (mregp->m_src_addr == NULL) 1236 goto fail; 1237 mip->mi_info.mi_unicst_addr = 1238 kmem_alloc(mip->mi_type->mt_addr_length, KM_SLEEP); 1239 bcopy(mregp->m_src_addr, mip->mi_info.mi_unicst_addr, 1240 mip->mi_type->mt_addr_length); 1241 1242 /* 1243 * Copy the fixed 'factory' MAC address from the immutable 1244 * info. This is taken to be the MAC address currently in 1245 * use. 1246 */ 1247 bcopy(mip->mi_info.mi_unicst_addr, mip->mi_addr, 1248 mip->mi_type->mt_addr_length); 1249 /* Copy the destination address if one is provided. */ 1250 if (mregp->m_dst_addr != NULL) { 1251 bcopy(mregp->m_dst_addr, mip->mi_dstaddr, 1252 mip->mi_type->mt_addr_length); 1253 } 1254 } else if (mregp->m_src_addr != NULL) { 1255 goto fail; 1256 } 1257 1258 /* 1259 * The format of the m_pdata is specific to the plugin. It is 1260 * passed in as an argument to all of the plugin callbacks. The 1261 * driver can update this information by calling 1262 * mac_pdata_update(). 1263 */ 1264 if (mregp->m_pdata != NULL) { 1265 /* 1266 * Verify that the plugin supports MAC plugin data and that 1267 * the supplied data is valid. 1268 */ 1269 if (!(mip->mi_type->mt_ops.mtops_ops & MTOPS_PDATA_VERIFY)) 1270 goto fail; 1271 if (!mip->mi_type->mt_ops.mtops_pdata_verify(mregp->m_pdata, 1272 mregp->m_pdata_size)) { 1273 goto fail; 1274 } 1275 mip->mi_pdata = kmem_alloc(mregp->m_pdata_size, KM_SLEEP); 1276 bcopy(mregp->m_pdata, mip->mi_pdata, mregp->m_pdata_size); 1277 mip->mi_pdata_size = mregp->m_pdata_size; 1278 } 1279 1280 /* 1281 * Stash the driver callbacks into the mac_impl_t, but first sanity 1282 * check to make sure all mandatory callbacks are set. 1283 */ 1284 if (mregp->m_callbacks->mc_getstat == NULL || 1285 mregp->m_callbacks->mc_start == NULL || 1286 mregp->m_callbacks->mc_stop == NULL || 1287 mregp->m_callbacks->mc_setpromisc == NULL || 1288 mregp->m_callbacks->mc_multicst == NULL || 1289 mregp->m_callbacks->mc_unicst == NULL || 1290 mregp->m_callbacks->mc_tx == NULL) { 1291 goto fail; 1292 } 1293 mip->mi_callbacks = mregp->m_callbacks; 1294 1295 mip->mi_dip = mregp->m_dip; 1296 1297 /* 1298 * Set up the two possible transmit routines. 1299 */ 1300 mip->mi_txinfo.mt_fn = mip->mi_tx; 1301 mip->mi_txinfo.mt_arg = mip->mi_driver; 1302 mip->mi_txloopinfo.mt_fn = mac_txloop; 1303 mip->mi_txloopinfo.mt_arg = mip; 1304 1305 /* 1306 * Allocate a notification thread. 1307 */ 1308 mip->mi_notify_thread = thread_create(NULL, 0, i_mac_notify_thread, 1309 mip, 0, &p0, TS_RUN, minclsyspri); 1310 if (mip->mi_notify_thread == NULL) 1311 goto fail; 1312 1313 /* 1314 * Initialize the kstats for this device. 1315 */ 1316 mac_stat_create(mip); 1317 1318 err = EEXIST; 1319 /* Create a style-2 DLPI device */ 1320 if (ddi_create_minor_node(mip->mi_dip, (char *)mip->mi_drvname, 1321 S_IFCHR, 0, DDI_NT_NET, CLONE_DEV) != DDI_SUCCESS) 1322 goto fail; 1323 style2_created = B_TRUE; 1324 1325 /* Create a style-1 DLPI device */ 1326 minor = (minor_t)mip->mi_instance + 1; 1327 if (ddi_create_minor_node(mip->mi_dip, mip->mi_name, S_IFCHR, minor, 1328 DDI_NT_NET, 0) != DDI_SUCCESS) 1329 goto fail; 1330 style1_created = B_TRUE; 1331 1332 /* 1333 * Create a link for this MAC. The link name will be the same as 1334 * the MAC name. 1335 */ 1336 err = dls_create(mip->mi_name, mip->mi_name, 1337 ddi_get_instance(mip->mi_dip)); 1338 if (err != 0) 1339 goto fail; 1340 1341 /* set the gldv3 flag in dn_flags */ 1342 dnp = &devnamesp[ddi_driver_major(mip->mi_dip)]; 1343 LOCK_DEV_OPS(&dnp->dn_lock); 1344 dnp->dn_flags |= DN_GLDV3_DRIVER; 1345 UNLOCK_DEV_OPS(&dnp->dn_lock); 1346 1347 rw_enter(&i_mac_impl_lock, RW_WRITER); 1348 if (mod_hash_insert(i_mac_impl_hash, 1349 (mod_hash_key_t)mip->mi_name, (mod_hash_val_t)mip) != 0) { 1350 rw_exit(&i_mac_impl_lock); 1351 VERIFY(dls_destroy(mip->mi_name) == 0); 1352 err = EEXIST; 1353 goto fail; 1354 } 1355 1356 /* 1357 * Mark the MAC to be ready for open. 1358 */ 1359 mip->mi_disabled = B_FALSE; 1360 1361 cmn_err(CE_NOTE, "!%s registered", mip->mi_name); 1362 1363 rw_exit(&i_mac_impl_lock); 1364 1365 atomic_inc_32(&i_mac_impl_count); 1366 *mhp = (mac_handle_t)mip; 1367 return (0); 1368 1369 fail: 1370 /* clean up notification thread */ 1371 if (mip->mi_notify_thread != NULL) { 1372 mutex_enter(&mip->mi_notify_bits_lock); 1373 mip->mi_notify_bits = (1 << MAC_NNOTE); 1374 cv_broadcast(&mip->mi_notify_cv); 1375 while (mip->mi_notify_bits != 0) 1376 cv_wait(&mip->mi_notify_cv, &mip->mi_notify_bits_lock); 1377 mutex_exit(&mip->mi_notify_bits_lock); 1378 } 1379 1380 if (mip->mi_info.mi_unicst_addr != NULL) { 1381 kmem_free(mip->mi_info.mi_unicst_addr, 1382 mip->mi_type->mt_addr_length); 1383 mip->mi_info.mi_unicst_addr = NULL; 1384 } 1385 if (style1_created) 1386 ddi_remove_minor_node(mip->mi_dip, mip->mi_name); 1387 if (style2_created) 1388 ddi_remove_minor_node(mip->mi_dip, (char *)mip->mi_drvname); 1389 1390 mac_stat_destroy(mip); 1391 1392 if (mip->mi_type != NULL) { 1393 atomic_dec_32(&mip->mi_type->mt_ref); 1394 mip->mi_type = NULL; 1395 } 1396 1397 if (mip->mi_pdata != NULL) { 1398 kmem_free(mip->mi_pdata, mip->mi_pdata_size); 1399 mip->mi_pdata = NULL; 1400 mip->mi_pdata_size = 0; 1401 } 1402 1403 kmem_cache_free(i_mac_impl_cachep, mip); 1404 return (err); 1405 } 1406 1407 int 1408 mac_unregister(mac_handle_t mh) 1409 { 1410 int err; 1411 mac_impl_t *mip = (mac_impl_t *)mh; 1412 mod_hash_val_t val; 1413 mac_multicst_addr_t *p, *nextp; 1414 1415 /* 1416 * See if there are any other references to this mac_t (e.g., VLAN's). 1417 * If not, set mi_disabled to prevent any new VLAN's from being 1418 * created while we're destroying this mac. 1419 */ 1420 rw_enter(&i_mac_impl_lock, RW_WRITER); 1421 if (mip->mi_ref > 0) { 1422 rw_exit(&i_mac_impl_lock); 1423 return (EBUSY); 1424 } 1425 mip->mi_disabled = B_TRUE; 1426 rw_exit(&i_mac_impl_lock); 1427 1428 if ((err = dls_destroy(mip->mi_name)) != 0) { 1429 rw_enter(&i_mac_impl_lock, RW_WRITER); 1430 mip->mi_disabled = B_FALSE; 1431 rw_exit(&i_mac_impl_lock); 1432 return (err); 1433 } 1434 1435 /* 1436 * Clean up notification thread (wait for it to exit). 1437 */ 1438 mutex_enter(&mip->mi_notify_bits_lock); 1439 mip->mi_notify_bits = (1 << MAC_NNOTE); 1440 cv_broadcast(&mip->mi_notify_cv); 1441 while (mip->mi_notify_bits != 0) 1442 cv_wait(&mip->mi_notify_cv, &mip->mi_notify_bits_lock); 1443 mutex_exit(&mip->mi_notify_bits_lock); 1444 1445 /* 1446 * Remove both style 1 and style 2 minor nodes 1447 */ 1448 ddi_remove_minor_node(mip->mi_dip, (char *)mip->mi_drvname); 1449 ddi_remove_minor_node(mip->mi_dip, mip->mi_name); 1450 1451 ASSERT(!mip->mi_activelink); 1452 1453 mac_stat_destroy(mip); 1454 1455 (void) mod_hash_remove(i_mac_impl_hash, (mod_hash_key_t)mip->mi_name, 1456 &val); 1457 ASSERT(mip == (mac_impl_t *)val); 1458 1459 ASSERT(i_mac_impl_count > 0); 1460 atomic_dec_32(&i_mac_impl_count); 1461 1462 if (mip->mi_pdata != NULL) 1463 kmem_free(mip->mi_pdata, mip->mi_pdata_size); 1464 mip->mi_pdata = NULL; 1465 mip->mi_pdata_size = 0; 1466 1467 /* 1468 * Free the list of multicast addresses. 1469 */ 1470 for (p = mip->mi_mmap; p != NULL; p = nextp) { 1471 nextp = p->mma_nextp; 1472 kmem_free(p, sizeof (mac_multicst_addr_t)); 1473 } 1474 mip->mi_mmap = NULL; 1475 1476 mip->mi_linkstate = LINK_STATE_UNKNOWN; 1477 kmem_free(mip->mi_info.mi_unicst_addr, mip->mi_type->mt_addr_length); 1478 mip->mi_info.mi_unicst_addr = NULL; 1479 1480 atomic_dec_32(&mip->mi_type->mt_ref); 1481 mip->mi_type = NULL; 1482 1483 cmn_err(CE_NOTE, "!%s unregistered", mip->mi_name); 1484 1485 kmem_cache_free(i_mac_impl_cachep, mip); 1486 1487 return (0); 1488 } 1489 1490 /* 1491 * To avoid potential deadlocks, mac_rx() releases mi_rx_lock 1492 * before invoking its list of upcalls. This introduces races with 1493 * mac_rx_remove() and mac_rx_add(), who can potentially modify the 1494 * upcall list while mi_rx_lock is not being held. The race with 1495 * mac_rx_remove() is handled by incrementing mi_rx_ref upon entering 1496 * mac_rx(); a non-zero mi_rx_ref would tell mac_rx_remove() 1497 * to not modify the list but instead mark an upcall for deletion. 1498 * before mac_rx() exits, mi_rx_ref is decremented and if it 1499 * is 0, the marked upcalls will be removed from the list and freed. 1500 * The race with mac_rx_add() is harmless because mac_rx_add() only 1501 * prepends to the list and since mac_rx() saves the list head 1502 * before releasing mi_rx_lock, any prepended upcall won't be seen 1503 * until the next packet chain arrives. 1504 * 1505 * To minimize lock contention between multiple parallel invocations 1506 * of mac_rx(), mi_rx_lock is acquired as a READER lock. The 1507 * use of atomic operations ensures the sanity of mi_rx_ref. mi_rx_lock 1508 * will be upgraded to WRITER mode when there are marked upcalls to be 1509 * cleaned. 1510 */ 1511 void 1512 mac_rx(mac_handle_t mh, mac_resource_handle_t mrh, mblk_t *mp_chain) 1513 { 1514 mac_impl_t *mip = (mac_impl_t *)mh; 1515 mblk_t *bp = mp_chain; 1516 mac_rx_fn_t *mrfp; 1517 1518 /* 1519 * Call all registered receive functions. 1520 */ 1521 rw_enter(&mip->mi_rx_lock, RW_READER); 1522 if ((mrfp = mip->mi_mrfp) == NULL) { 1523 /* There are no registered receive functions. */ 1524 freemsgchain(bp); 1525 rw_exit(&mip->mi_rx_lock); 1526 return; 1527 } 1528 atomic_inc_32(&mip->mi_rx_ref); 1529 rw_exit(&mip->mi_rx_lock); 1530 1531 /* 1532 * Call registered receive functions. 1533 */ 1534 do { 1535 mblk_t *recv_bp; 1536 1537 recv_bp = (mrfp->mrf_nextp != NULL) ? copymsgchain(bp) : bp; 1538 if (recv_bp != NULL) { 1539 if (mrfp->mrf_inuse) { 1540 /* 1541 * Send bp itself and keep the copy. 1542 * If there's only one active receiver, 1543 * it should get the original message, 1544 * tagged with the hardware checksum flags. 1545 */ 1546 mrfp->mrf_fn(mrfp->mrf_arg, mrh, bp); 1547 bp = recv_bp; 1548 } else { 1549 freemsgchain(recv_bp); 1550 } 1551 } 1552 mrfp = mrfp->mrf_nextp; 1553 } while (mrfp != NULL); 1554 1555 rw_enter(&mip->mi_rx_lock, RW_READER); 1556 if (atomic_dec_32_nv(&mip->mi_rx_ref) == 0 && mip->mi_rx_removed > 0) { 1557 mac_rx_fn_t **pp, *p; 1558 uint32_t cnt = 0; 1559 1560 DTRACE_PROBE1(delete_callbacks, mac_impl_t *, mip); 1561 1562 /* 1563 * Need to become exclusive before doing cleanup 1564 */ 1565 if (rw_tryupgrade(&mip->mi_rx_lock) == 0) { 1566 rw_exit(&mip->mi_rx_lock); 1567 rw_enter(&mip->mi_rx_lock, RW_WRITER); 1568 } 1569 1570 /* 1571 * We return if another thread has already entered and cleaned 1572 * up the list. 1573 */ 1574 if (mip->mi_rx_ref > 0 || mip->mi_rx_removed == 0) { 1575 rw_exit(&mip->mi_rx_lock); 1576 return; 1577 } 1578 1579 /* 1580 * Free removed callbacks. 1581 */ 1582 pp = &mip->mi_mrfp; 1583 while (*pp != NULL) { 1584 if (!(*pp)->mrf_inuse) { 1585 p = *pp; 1586 *pp = (*pp)->mrf_nextp; 1587 kmem_free(p, sizeof (*p)); 1588 cnt++; 1589 continue; 1590 } 1591 pp = &(*pp)->mrf_nextp; 1592 } 1593 1594 /* 1595 * Wake up mac_rx_remove_wait() 1596 */ 1597 mutex_enter(&mip->mi_lock); 1598 ASSERT(mip->mi_rx_removed == cnt); 1599 mip->mi_rx_removed = 0; 1600 cv_broadcast(&mip->mi_rx_cv); 1601 mutex_exit(&mip->mi_lock); 1602 } 1603 rw_exit(&mip->mi_rx_lock); 1604 } 1605 1606 /* 1607 * Transmit function -- ONLY used when there are registered loopback listeners. 1608 */ 1609 mblk_t * 1610 mac_txloop(void *arg, mblk_t *bp) 1611 { 1612 mac_impl_t *mip = arg; 1613 mac_txloop_fn_t *mtfp; 1614 mblk_t *loop_bp, *resid_bp, *next_bp; 1615 1616 while (bp != NULL) { 1617 next_bp = bp->b_next; 1618 bp->b_next = NULL; 1619 1620 if ((loop_bp = copymsg(bp)) == NULL) 1621 goto noresources; 1622 1623 if ((resid_bp = mip->mi_tx(mip->mi_driver, bp)) != NULL) { 1624 ASSERT(resid_bp == bp); 1625 freemsg(loop_bp); 1626 goto noresources; 1627 } 1628 1629 rw_enter(&mip->mi_txloop_lock, RW_READER); 1630 mtfp = mip->mi_mtfp; 1631 while (mtfp != NULL && loop_bp != NULL) { 1632 bp = loop_bp; 1633 1634 /* XXX counter bump if copymsg() fails? */ 1635 if (mtfp->mtf_nextp != NULL) 1636 loop_bp = copymsg(bp); 1637 else 1638 loop_bp = NULL; 1639 1640 mtfp->mtf_fn(mtfp->mtf_arg, bp); 1641 mtfp = mtfp->mtf_nextp; 1642 } 1643 rw_exit(&mip->mi_txloop_lock); 1644 1645 /* 1646 * It's possible we've raced with the disabling of promiscuous 1647 * mode, in which case we can discard our copy. 1648 */ 1649 if (loop_bp != NULL) 1650 freemsg(loop_bp); 1651 1652 bp = next_bp; 1653 } 1654 1655 return (NULL); 1656 1657 noresources: 1658 bp->b_next = next_bp; 1659 return (bp); 1660 } 1661 1662 void 1663 mac_link_update(mac_handle_t mh, link_state_t link) 1664 { 1665 mac_impl_t *mip = (mac_impl_t *)mh; 1666 1667 /* 1668 * Save the link state. 1669 */ 1670 mip->mi_linkstate = link; 1671 1672 /* 1673 * Send a MAC_NOTE_LINK notification. 1674 */ 1675 i_mac_notify(mip, MAC_NOTE_LINK); 1676 } 1677 1678 void 1679 mac_unicst_update(mac_handle_t mh, const uint8_t *addr) 1680 { 1681 mac_impl_t *mip = (mac_impl_t *)mh; 1682 1683 if (mip->mi_type->mt_addr_length == 0) 1684 return; 1685 1686 /* 1687 * Save the address. 1688 */ 1689 bcopy(addr, mip->mi_addr, mip->mi_type->mt_addr_length); 1690 1691 /* 1692 * Send a MAC_NOTE_UNICST notification. 1693 */ 1694 i_mac_notify(mip, MAC_NOTE_UNICST); 1695 } 1696 1697 void 1698 mac_tx_update(mac_handle_t mh) 1699 { 1700 /* 1701 * Send a MAC_NOTE_TX notification. 1702 */ 1703 i_mac_notify((mac_impl_t *)mh, MAC_NOTE_TX); 1704 } 1705 1706 void 1707 mac_resource_update(mac_handle_t mh) 1708 { 1709 /* 1710 * Send a MAC_NOTE_RESOURCE notification. 1711 */ 1712 i_mac_notify((mac_impl_t *)mh, MAC_NOTE_RESOURCE); 1713 } 1714 1715 mac_resource_handle_t 1716 mac_resource_add(mac_handle_t mh, mac_resource_t *mrp) 1717 { 1718 mac_impl_t *mip = (mac_impl_t *)mh; 1719 mac_resource_handle_t mrh; 1720 mac_resource_add_t add; 1721 void *arg; 1722 1723 rw_enter(&mip->mi_resource_lock, RW_READER); 1724 add = mip->mi_resource_add; 1725 arg = mip->mi_resource_add_arg; 1726 1727 if (add != NULL) 1728 mrh = add(arg, mrp); 1729 else 1730 mrh = NULL; 1731 rw_exit(&mip->mi_resource_lock); 1732 1733 return (mrh); 1734 } 1735 1736 int 1737 mac_pdata_update(mac_handle_t mh, void *mac_pdata, size_t dsize) 1738 { 1739 mac_impl_t *mip = (mac_impl_t *)mh; 1740 1741 /* 1742 * Verify that the plugin supports MAC plugin data and that the 1743 * supplied data is valid. 1744 */ 1745 if (!(mip->mi_type->mt_ops.mtops_ops & MTOPS_PDATA_VERIFY)) 1746 return (EINVAL); 1747 if (!mip->mi_type->mt_ops.mtops_pdata_verify(mac_pdata, dsize)) 1748 return (EINVAL); 1749 1750 if (mip->mi_pdata != NULL) 1751 kmem_free(mip->mi_pdata, mip->mi_pdata_size); 1752 1753 mip->mi_pdata = kmem_alloc(dsize, KM_SLEEP); 1754 bcopy(mac_pdata, mip->mi_pdata, dsize); 1755 mip->mi_pdata_size = dsize; 1756 1757 /* 1758 * Since the MAC plugin data is used to construct MAC headers that 1759 * were cached in fast-path headers, we need to flush fast-path 1760 * information for links associated with this mac. 1761 */ 1762 i_mac_notify(mip, MAC_NOTE_FASTPATH_FLUSH); 1763 return (0); 1764 } 1765 1766 void 1767 mac_multicst_refresh(mac_handle_t mh, mac_multicst_t refresh, void *arg, 1768 boolean_t add) 1769 { 1770 mac_impl_t *mip = (mac_impl_t *)mh; 1771 mac_multicst_addr_t *p; 1772 1773 /* 1774 * If no specific refresh function was given then default to the 1775 * driver's m_multicst entry point. 1776 */ 1777 if (refresh == NULL) { 1778 refresh = mip->mi_multicst; 1779 arg = mip->mi_driver; 1780 } 1781 ASSERT(refresh != NULL); 1782 1783 /* 1784 * Walk the multicast address list and call the refresh function for 1785 * each address. 1786 */ 1787 rw_enter(&(mip->mi_data_lock), RW_READER); 1788 for (p = mip->mi_mmap; p != NULL; p = p->mma_nextp) 1789 refresh(arg, add, p->mma_addr); 1790 rw_exit(&(mip->mi_data_lock)); 1791 } 1792 1793 void 1794 mac_unicst_refresh(mac_handle_t mh, mac_unicst_t refresh, void *arg) 1795 { 1796 mac_impl_t *mip = (mac_impl_t *)mh; 1797 /* 1798 * If no specific refresh function was given then default to the 1799 * driver's mi_unicst entry point. 1800 */ 1801 if (refresh == NULL) { 1802 refresh = mip->mi_unicst; 1803 arg = mip->mi_driver; 1804 } 1805 ASSERT(refresh != NULL); 1806 1807 /* 1808 * Call the refresh function with the current unicast address. 1809 */ 1810 refresh(arg, mip->mi_addr); 1811 } 1812 1813 void 1814 mac_promisc_refresh(mac_handle_t mh, mac_setpromisc_t refresh, void *arg) 1815 { 1816 mac_impl_t *mip = (mac_impl_t *)mh; 1817 1818 /* 1819 * If no specific refresh function was given then default to the 1820 * driver's m_promisc entry point. 1821 */ 1822 if (refresh == NULL) { 1823 refresh = mip->mi_setpromisc; 1824 arg = mip->mi_driver; 1825 } 1826 ASSERT(refresh != NULL); 1827 1828 /* 1829 * Call the refresh function with the current promiscuity. 1830 */ 1831 refresh(arg, (mip->mi_devpromisc != 0)); 1832 } 1833 1834 boolean_t 1835 mac_active_set(mac_handle_t mh) 1836 { 1837 mac_impl_t *mip = (mac_impl_t *)mh; 1838 1839 mutex_enter(&mip->mi_activelink_lock); 1840 if (mip->mi_activelink) { 1841 mutex_exit(&mip->mi_activelink_lock); 1842 return (B_FALSE); 1843 } 1844 mip->mi_activelink = B_TRUE; 1845 mutex_exit(&mip->mi_activelink_lock); 1846 return (B_TRUE); 1847 } 1848 1849 void 1850 mac_active_clear(mac_handle_t mh) 1851 { 1852 mac_impl_t *mip = (mac_impl_t *)mh; 1853 1854 mutex_enter(&mip->mi_activelink_lock); 1855 ASSERT(mip->mi_activelink); 1856 mip->mi_activelink = B_FALSE; 1857 mutex_exit(&mip->mi_activelink_lock); 1858 } 1859 1860 /* 1861 * mac_info_get() is used for retrieving the mac_info when a DL_INFO_REQ is 1862 * issued before a DL_ATTACH_REQ. we walk the i_mac_impl_hash table and find 1863 * the first mac_impl_t with a matching driver name; then we copy its mac_info_t 1864 * to the caller. we do all this with i_mac_impl_lock held so the mac_impl_t 1865 * cannot disappear while we are accessing it. 1866 */ 1867 typedef struct i_mac_info_state_s { 1868 const char *mi_name; 1869 mac_info_t *mi_infop; 1870 } i_mac_info_state_t; 1871 1872 /*ARGSUSED*/ 1873 static uint_t 1874 i_mac_info_walker(mod_hash_key_t key, mod_hash_val_t *val, void *arg) 1875 { 1876 i_mac_info_state_t *statep = arg; 1877 mac_impl_t *mip = (mac_impl_t *)val; 1878 1879 if (mip->mi_disabled) 1880 return (MH_WALK_CONTINUE); 1881 1882 if (strcmp(statep->mi_name, 1883 ddi_driver_name(mip->mi_dip)) != 0) 1884 return (MH_WALK_CONTINUE); 1885 1886 statep->mi_infop = &mip->mi_info; 1887 return (MH_WALK_TERMINATE); 1888 } 1889 1890 boolean_t 1891 mac_info_get(const char *name, mac_info_t *minfop) 1892 { 1893 i_mac_info_state_t state; 1894 1895 rw_enter(&i_mac_impl_lock, RW_READER); 1896 state.mi_name = name; 1897 state.mi_infop = NULL; 1898 mod_hash_walk(i_mac_impl_hash, i_mac_info_walker, &state); 1899 if (state.mi_infop == NULL) { 1900 rw_exit(&i_mac_impl_lock); 1901 return (B_FALSE); 1902 } 1903 *minfop = *state.mi_infop; 1904 rw_exit(&i_mac_impl_lock); 1905 return (B_TRUE); 1906 } 1907 1908 boolean_t 1909 mac_capab_get(mac_handle_t mh, mac_capab_t cap, void *cap_data) 1910 { 1911 mac_impl_t *mip = (mac_impl_t *)mh; 1912 1913 if (mip->mi_callbacks->mc_callbacks & MC_GETCAPAB) 1914 return (mip->mi_getcapab(mip->mi_driver, cap, cap_data)); 1915 else 1916 return (B_FALSE); 1917 } 1918 1919 boolean_t 1920 mac_sap_verify(mac_handle_t mh, uint32_t sap, uint32_t *bind_sap) 1921 { 1922 mac_impl_t *mip = (mac_impl_t *)mh; 1923 return (mip->mi_type->mt_ops.mtops_sap_verify(sap, bind_sap, 1924 mip->mi_pdata)); 1925 } 1926 1927 mblk_t * 1928 mac_header(mac_handle_t mh, const uint8_t *daddr, uint32_t sap, mblk_t *payload, 1929 size_t extra_len) 1930 { 1931 mac_impl_t *mip = (mac_impl_t *)mh; 1932 return (mip->mi_type->mt_ops.mtops_header(mip->mi_addr, daddr, sap, 1933 mip->mi_pdata, payload, extra_len)); 1934 } 1935 1936 int 1937 mac_header_info(mac_handle_t mh, mblk_t *mp, mac_header_info_t *mhip) 1938 { 1939 mac_impl_t *mip = (mac_impl_t *)mh; 1940 return (mip->mi_type->mt_ops.mtops_header_info(mp, mip->mi_pdata, 1941 mhip)); 1942 } 1943 1944 mblk_t * 1945 mac_header_cook(mac_handle_t mh, mblk_t *mp) 1946 { 1947 mac_impl_t *mip = (mac_impl_t *)mh; 1948 if (mip->mi_type->mt_ops.mtops_ops & MTOPS_HEADER_COOK) { 1949 if (DB_REF(mp) > 1) { 1950 mblk_t *newmp = copymsg(mp); 1951 if (newmp == NULL) 1952 return (NULL); 1953 freemsg(mp); 1954 mp = newmp; 1955 } 1956 return (mip->mi_type->mt_ops.mtops_header_cook(mp, 1957 mip->mi_pdata)); 1958 } 1959 return (mp); 1960 } 1961 1962 mblk_t * 1963 mac_header_uncook(mac_handle_t mh, mblk_t *mp) 1964 { 1965 mac_impl_t *mip = (mac_impl_t *)mh; 1966 if (mip->mi_type->mt_ops.mtops_ops & MTOPS_HEADER_UNCOOK) { 1967 if (DB_REF(mp) > 1) { 1968 mblk_t *newmp = copymsg(mp); 1969 if (newmp == NULL) 1970 return (NULL); 1971 freemsg(mp); 1972 mp = newmp; 1973 } 1974 return (mip->mi_type->mt_ops.mtops_header_uncook(mp, 1975 mip->mi_pdata)); 1976 } 1977 return (mp); 1978 } 1979 1980 void 1981 mac_init_ops(struct dev_ops *ops, const char *name) 1982 { 1983 dld_init_ops(ops, name); 1984 } 1985 1986 void 1987 mac_fini_ops(struct dev_ops *ops) 1988 { 1989 dld_fini_ops(ops); 1990 } 1991 1992 /* 1993 * MAC Type Plugin functions. 1994 */ 1995 1996 mactype_register_t * 1997 mactype_alloc(uint_t mactype_version) 1998 { 1999 mactype_register_t *mtrp; 2000 2001 /* 2002 * Make sure there isn't a version mismatch between the plugin and 2003 * the framework. In the future, if multiple versions are 2004 * supported, this check could become more sophisticated. 2005 */ 2006 if (mactype_version != MACTYPE_VERSION) 2007 return (NULL); 2008 2009 mtrp = kmem_zalloc(sizeof (mactype_register_t), KM_SLEEP); 2010 mtrp->mtr_version = mactype_version; 2011 return (mtrp); 2012 } 2013 2014 void 2015 mactype_free(mactype_register_t *mtrp) 2016 { 2017 kmem_free(mtrp, sizeof (mactype_register_t)); 2018 } 2019 2020 int 2021 mactype_register(mactype_register_t *mtrp) 2022 { 2023 mactype_t *mtp; 2024 mactype_ops_t *ops = mtrp->mtr_ops; 2025 2026 /* Do some sanity checking before we register this MAC type. */ 2027 if (mtrp->mtr_ident == NULL || ops == NULL || mtrp->mtr_addrlen == 0) 2028 return (EINVAL); 2029 2030 /* 2031 * Verify that all mandatory callbacks are set in the ops 2032 * vector. 2033 */ 2034 if (ops->mtops_unicst_verify == NULL || 2035 ops->mtops_multicst_verify == NULL || 2036 ops->mtops_sap_verify == NULL || 2037 ops->mtops_header == NULL || 2038 ops->mtops_header_info == NULL) { 2039 return (EINVAL); 2040 } 2041 2042 mtp = kmem_zalloc(sizeof (*mtp), KM_SLEEP); 2043 mtp->mt_ident = mtrp->mtr_ident; 2044 mtp->mt_ops = *ops; 2045 mtp->mt_type = mtrp->mtr_mactype; 2046 mtp->mt_nativetype = mtrp->mtr_nativetype; 2047 mtp->mt_addr_length = mtrp->mtr_addrlen; 2048 if (mtrp->mtr_brdcst_addr != NULL) { 2049 mtp->mt_brdcst_addr = kmem_alloc(mtrp->mtr_addrlen, KM_SLEEP); 2050 bcopy(mtrp->mtr_brdcst_addr, mtp->mt_brdcst_addr, 2051 mtrp->mtr_addrlen); 2052 } 2053 2054 mtp->mt_stats = mtrp->mtr_stats; 2055 mtp->mt_statcount = mtrp->mtr_statcount; 2056 2057 if (mod_hash_insert(i_mactype_hash, 2058 (mod_hash_key_t)mtp->mt_ident, (mod_hash_val_t)mtp) != 0) { 2059 kmem_free(mtp->mt_brdcst_addr, mtp->mt_addr_length); 2060 kmem_free(mtp, sizeof (*mtp)); 2061 return (EEXIST); 2062 } 2063 return (0); 2064 } 2065 2066 int 2067 mactype_unregister(const char *ident) 2068 { 2069 mactype_t *mtp; 2070 mod_hash_val_t val; 2071 int err; 2072 2073 /* 2074 * Let's not allow MAC drivers to use this plugin while we're 2075 * trying to unregister it. Holding i_mactype_lock also prevents a 2076 * plugin from unregistering while a MAC driver is attempting to 2077 * hold a reference to it in i_mactype_getplugin(). 2078 */ 2079 mutex_enter(&i_mactype_lock); 2080 2081 if ((err = mod_hash_find(i_mactype_hash, (mod_hash_key_t)ident, 2082 (mod_hash_val_t *)&mtp)) != 0) { 2083 /* A plugin is trying to unregister, but it never registered. */ 2084 err = ENXIO; 2085 goto done; 2086 } 2087 2088 if (mtp->mt_ref != 0) { 2089 err = EBUSY; 2090 goto done; 2091 } 2092 2093 err = mod_hash_remove(i_mactype_hash, (mod_hash_key_t)ident, &val); 2094 ASSERT(err == 0); 2095 if (err != 0) { 2096 /* This should never happen, thus the ASSERT() above. */ 2097 err = EINVAL; 2098 goto done; 2099 } 2100 ASSERT(mtp == (mactype_t *)val); 2101 2102 kmem_free(mtp->mt_brdcst_addr, mtp->mt_addr_length); 2103 kmem_free(mtp, sizeof (mactype_t)); 2104 done: 2105 mutex_exit(&i_mactype_lock); 2106 return (err); 2107 } 2108 2109 int 2110 mac_vlan_create(mac_handle_t mh, const char *name, minor_t minor) 2111 { 2112 mac_impl_t *mip = (mac_impl_t *)mh; 2113 2114 /* Create a style-1 DLPI device */ 2115 if (ddi_create_minor_node(mip->mi_dip, (char *)name, S_IFCHR, minor, 2116 DDI_NT_NET, 0) != DDI_SUCCESS) { 2117 return (-1); 2118 } 2119 return (0); 2120 } 2121 2122 void 2123 mac_vlan_remove(mac_handle_t mh, const char *name) 2124 { 2125 mac_impl_t *mip = (mac_impl_t *)mh; 2126 dev_info_t *dipp; 2127 2128 ddi_remove_minor_node(mip->mi_dip, (char *)name); 2129 dipp = ddi_get_parent(mip->mi_dip); 2130 (void) devfs_clean(dipp, NULL, 0); 2131 } 2132