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 /* 23 * Copyright 2008 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 * MAC Services Module 31 */ 32 33 #include <sys/types.h> 34 #include <sys/conf.h> 35 #include <sys/id_space.h> 36 #include <sys/stat.h> 37 #include <sys/mkdev.h> 38 #include <sys/stream.h> 39 #include <sys/strsun.h> 40 #include <sys/strsubr.h> 41 #include <sys/dlpi.h> 42 #include <sys/dls.h> 43 #include <sys/modhash.h> 44 #include <sys/vlan.h> 45 #include <sys/mac.h> 46 #include <sys/mac_impl.h> 47 #include <sys/dld.h> 48 #include <sys/modctl.h> 49 #include <sys/fs/dv_node.h> 50 #include <sys/thread.h> 51 #include <sys/proc.h> 52 #include <sys/callb.h> 53 #include <sys/cpuvar.h> 54 #include <sys/atomic.h> 55 #include <sys/sdt.h> 56 57 #define IMPL_HASHSZ 67 /* prime */ 58 59 static kmem_cache_t *i_mac_impl_cachep; 60 static mod_hash_t *i_mac_impl_hash; 61 krwlock_t i_mac_impl_lock; 62 uint_t i_mac_impl_count; 63 static kmem_cache_t *mac_vnic_tx_cache; 64 static id_space_t *minor_ids; 65 static uint32_t minor_count; 66 67 #define MACTYPE_KMODDIR "mac" 68 #define MACTYPE_HASHSZ 67 69 static mod_hash_t *i_mactype_hash; 70 /* 71 * i_mactype_lock synchronizes threads that obtain references to mactype_t 72 * structures through i_mactype_getplugin(). 73 */ 74 static kmutex_t i_mactype_lock; 75 76 static void i_mac_notify_thread(void *); 77 static mblk_t *mac_vnic_tx(void *, mblk_t *); 78 static mblk_t *mac_vnic_txloop(void *, mblk_t *); 79 80 /* 81 * Private functions. 82 */ 83 84 /*ARGSUSED*/ 85 static int 86 i_mac_constructor(void *buf, void *arg, int kmflag) 87 { 88 mac_impl_t *mip = buf; 89 90 bzero(buf, sizeof (mac_impl_t)); 91 92 mip->mi_linkstate = LINK_STATE_UNKNOWN; 93 94 rw_init(&mip->mi_state_lock, NULL, RW_DRIVER, NULL); 95 rw_init(&mip->mi_gen_lock, NULL, RW_DRIVER, NULL); 96 rw_init(&mip->mi_data_lock, NULL, RW_DRIVER, NULL); 97 rw_init(&mip->mi_notify_lock, NULL, RW_DRIVER, NULL); 98 rw_init(&mip->mi_rx_lock, NULL, RW_DRIVER, NULL); 99 rw_init(&mip->mi_tx_lock, NULL, RW_DRIVER, NULL); 100 rw_init(&mip->mi_resource_lock, NULL, RW_DRIVER, NULL); 101 mutex_init(&mip->mi_activelink_lock, NULL, MUTEX_DEFAULT, NULL); 102 mutex_init(&mip->mi_notify_bits_lock, NULL, MUTEX_DRIVER, NULL); 103 cv_init(&mip->mi_notify_cv, NULL, CV_DRIVER, NULL); 104 mutex_init(&mip->mi_lock, NULL, MUTEX_DRIVER, NULL); 105 cv_init(&mip->mi_rx_cv, NULL, CV_DRIVER, NULL); 106 return (0); 107 } 108 109 /*ARGSUSED*/ 110 static void 111 i_mac_destructor(void *buf, void *arg) 112 { 113 mac_impl_t *mip = buf; 114 115 ASSERT(mip->mi_ref == 0); 116 ASSERT(!mip->mi_exclusive); 117 ASSERT(mip->mi_active == 0); 118 ASSERT(mip->mi_linkstate == LINK_STATE_UNKNOWN); 119 ASSERT(mip->mi_devpromisc == 0); 120 ASSERT(mip->mi_promisc == 0); 121 ASSERT(mip->mi_mmap == NULL); 122 ASSERT(mip->mi_mmrp == NULL); 123 ASSERT(mip->mi_mnfp == NULL); 124 ASSERT(mip->mi_resource_add == NULL); 125 ASSERT(mip->mi_ksp == NULL); 126 ASSERT(mip->mi_kstat_count == 0); 127 ASSERT(mip->mi_notify_bits == 0); 128 ASSERT(mip->mi_notify_thread == NULL); 129 130 rw_destroy(&mip->mi_gen_lock); 131 rw_destroy(&mip->mi_state_lock); 132 rw_destroy(&mip->mi_data_lock); 133 rw_destroy(&mip->mi_notify_lock); 134 rw_destroy(&mip->mi_rx_lock); 135 rw_destroy(&mip->mi_tx_lock); 136 rw_destroy(&mip->mi_resource_lock); 137 mutex_destroy(&mip->mi_activelink_lock); 138 mutex_destroy(&mip->mi_notify_bits_lock); 139 cv_destroy(&mip->mi_notify_cv); 140 mutex_destroy(&mip->mi_lock); 141 cv_destroy(&mip->mi_rx_cv); 142 } 143 144 /* 145 * mac_vnic_tx_t kmem cache support functions. 146 */ 147 148 /* ARGSUSED */ 149 static int 150 i_mac_vnic_tx_ctor(void *buf, void *arg, int mkflag) 151 { 152 mac_vnic_tx_t *vnic_tx = buf; 153 154 bzero(buf, sizeof (mac_vnic_tx_t)); 155 mutex_init(&vnic_tx->mv_lock, NULL, MUTEX_DRIVER, NULL); 156 cv_init(&vnic_tx->mv_cv, NULL, CV_DRIVER, NULL); 157 return (0); 158 } 159 160 /* ARGSUSED */ 161 static void 162 i_mac_vnic_tx_dtor(void *buf, void *arg) 163 { 164 mac_vnic_tx_t *vnic_tx = buf; 165 166 ASSERT(vnic_tx->mv_refs == 0); 167 mutex_destroy(&vnic_tx->mv_lock); 168 cv_destroy(&vnic_tx->mv_cv); 169 } 170 171 static void 172 i_mac_notify(mac_impl_t *mip, mac_notify_type_t type) 173 { 174 rw_enter(&i_mac_impl_lock, RW_READER); 175 if (mip->mi_disabled) 176 goto exit; 177 178 /* 179 * Guard against incorrect notifications. (Running a newer 180 * mac client against an older implementation?) 181 */ 182 if (type >= MAC_NNOTE) 183 goto exit; 184 185 mutex_enter(&mip->mi_notify_bits_lock); 186 mip->mi_notify_bits |= (1 << type); 187 cv_broadcast(&mip->mi_notify_cv); 188 mutex_exit(&mip->mi_notify_bits_lock); 189 190 exit: 191 rw_exit(&i_mac_impl_lock); 192 } 193 194 static void 195 i_mac_log_link_state(mac_impl_t *mip) 196 { 197 /* 198 * If no change, then it is not interesting. 199 */ 200 if (mip->mi_lastlinkstate == mip->mi_linkstate) 201 return; 202 203 switch (mip->mi_linkstate) { 204 case LINK_STATE_UP: 205 if (mip->mi_type->mt_ops.mtops_ops & MTOPS_LINK_DETAILS) { 206 char det[200]; 207 208 mip->mi_type->mt_ops.mtops_link_details(det, 209 sizeof (det), (mac_handle_t)mip, mip->mi_pdata); 210 211 cmn_err(CE_NOTE, "!%s link up, %s", mip->mi_name, det); 212 } else { 213 cmn_err(CE_NOTE, "!%s link up", mip->mi_name); 214 } 215 break; 216 217 case LINK_STATE_DOWN: 218 /* 219 * Only transitions from UP to DOWN are interesting 220 */ 221 if (mip->mi_lastlinkstate != LINK_STATE_UNKNOWN) 222 cmn_err(CE_NOTE, "!%s link down", mip->mi_name); 223 break; 224 225 case LINK_STATE_UNKNOWN: 226 /* 227 * This case is normally not interesting. 228 */ 229 break; 230 } 231 mip->mi_lastlinkstate = mip->mi_linkstate; 232 } 233 234 static void 235 i_mac_notify_thread(void *arg) 236 { 237 mac_impl_t *mip = arg; 238 callb_cpr_t cprinfo; 239 240 CALLB_CPR_INIT(&cprinfo, &mip->mi_notify_bits_lock, callb_generic_cpr, 241 "i_mac_notify_thread"); 242 243 mutex_enter(&mip->mi_notify_bits_lock); 244 for (;;) { 245 uint32_t bits; 246 uint32_t type; 247 248 bits = mip->mi_notify_bits; 249 if (bits == 0) { 250 CALLB_CPR_SAFE_BEGIN(&cprinfo); 251 cv_wait(&mip->mi_notify_cv, &mip->mi_notify_bits_lock); 252 CALLB_CPR_SAFE_END(&cprinfo, &mip->mi_notify_bits_lock); 253 continue; 254 } 255 mip->mi_notify_bits = 0; 256 257 if ((bits & (1 << MAC_NNOTE)) != 0) { 258 /* request to quit */ 259 ASSERT(mip->mi_disabled); 260 break; 261 } 262 263 mutex_exit(&mip->mi_notify_bits_lock); 264 265 /* 266 * Log link changes. 267 */ 268 if ((bits & (1 << MAC_NOTE_LINK)) != 0) 269 i_mac_log_link_state(mip); 270 271 /* 272 * Do notification callbacks for each notification type. 273 */ 274 for (type = 0; type < MAC_NNOTE; type++) { 275 mac_notify_fn_t *mnfp; 276 277 if ((bits & (1 << type)) == 0) { 278 continue; 279 } 280 281 /* 282 * Walk the list of notifications. 283 */ 284 rw_enter(&mip->mi_notify_lock, RW_READER); 285 for (mnfp = mip->mi_mnfp; mnfp != NULL; 286 mnfp = mnfp->mnf_nextp) { 287 288 mnfp->mnf_fn(mnfp->mnf_arg, type); 289 } 290 rw_exit(&mip->mi_notify_lock); 291 } 292 293 mutex_enter(&mip->mi_notify_bits_lock); 294 } 295 296 mip->mi_notify_thread = NULL; 297 cv_broadcast(&mip->mi_notify_cv); 298 299 CALLB_CPR_EXIT(&cprinfo); 300 301 thread_exit(); 302 } 303 304 static mactype_t * 305 i_mactype_getplugin(const char *pname) 306 { 307 mactype_t *mtype = NULL; 308 boolean_t tried_modload = B_FALSE; 309 310 mutex_enter(&i_mactype_lock); 311 312 find_registered_mactype: 313 if (mod_hash_find(i_mactype_hash, (mod_hash_key_t)pname, 314 (mod_hash_val_t *)&mtype) != 0) { 315 if (!tried_modload) { 316 /* 317 * If the plugin has not yet been loaded, then 318 * attempt to load it now. If modload() succeeds, 319 * the plugin should have registered using 320 * mactype_register(), in which case we can go back 321 * and attempt to find it again. 322 */ 323 if (modload(MACTYPE_KMODDIR, (char *)pname) != -1) { 324 tried_modload = B_TRUE; 325 goto find_registered_mactype; 326 } 327 } 328 } else { 329 /* 330 * Note that there's no danger that the plugin we've loaded 331 * could be unloaded between the modload() step and the 332 * reference count bump here, as we're holding 333 * i_mactype_lock, which mactype_unregister() also holds. 334 */ 335 atomic_inc_32(&mtype->mt_ref); 336 } 337 338 mutex_exit(&i_mactype_lock); 339 return (mtype); 340 } 341 342 /* 343 * Module initialization functions. 344 */ 345 346 void 347 mac_init(void) 348 { 349 i_mac_impl_cachep = kmem_cache_create("mac_impl_cache", 350 sizeof (mac_impl_t), 0, i_mac_constructor, i_mac_destructor, 351 NULL, NULL, NULL, 0); 352 ASSERT(i_mac_impl_cachep != NULL); 353 354 mac_vnic_tx_cache = kmem_cache_create("mac_vnic_tx_cache", 355 sizeof (mac_vnic_tx_t), 0, i_mac_vnic_tx_ctor, i_mac_vnic_tx_dtor, 356 NULL, NULL, NULL, 0); 357 ASSERT(mac_vnic_tx_cache != NULL); 358 359 i_mac_impl_hash = mod_hash_create_extended("mac_impl_hash", 360 IMPL_HASHSZ, mod_hash_null_keydtor, mod_hash_null_valdtor, 361 mod_hash_bystr, NULL, mod_hash_strkey_cmp, KM_SLEEP); 362 rw_init(&i_mac_impl_lock, NULL, RW_DEFAULT, NULL); 363 i_mac_impl_count = 0; 364 365 i_mactype_hash = mod_hash_create_extended("mactype_hash", 366 MACTYPE_HASHSZ, 367 mod_hash_null_keydtor, mod_hash_null_valdtor, 368 mod_hash_bystr, NULL, mod_hash_strkey_cmp, KM_SLEEP); 369 370 /* 371 * Allocate an id space to manage minor numbers. The range of the 372 * space will be from MAC_MAX_MINOR+1 to MAXMIN32 (maximum legal 373 * minor number is MAXMIN, but id_t is type of integer and does not 374 * allow MAXMIN). 375 */ 376 minor_ids = id_space_create("mac_minor_ids", MAC_MAX_MINOR+1, MAXMIN32); 377 ASSERT(minor_ids != NULL); 378 minor_count = 0; 379 } 380 381 int 382 mac_fini(void) 383 { 384 if (i_mac_impl_count > 0 || minor_count > 0) 385 return (EBUSY); 386 387 id_space_destroy(minor_ids); 388 389 mod_hash_destroy_hash(i_mac_impl_hash); 390 rw_destroy(&i_mac_impl_lock); 391 392 kmem_cache_destroy(i_mac_impl_cachep); 393 kmem_cache_destroy(mac_vnic_tx_cache); 394 395 mod_hash_destroy_hash(i_mactype_hash); 396 return (0); 397 } 398 399 /* 400 * Client functions. 401 */ 402 403 static int 404 mac_hold(const char *macname, mac_impl_t **pmip) 405 { 406 mac_impl_t *mip; 407 int err; 408 409 /* 410 * Check the device name length to make sure it won't overflow our 411 * buffer. 412 */ 413 if (strlen(macname) >= MAXNAMELEN) 414 return (EINVAL); 415 416 /* 417 * Look up its entry in the global hash table. 418 */ 419 rw_enter(&i_mac_impl_lock, RW_WRITER); 420 err = mod_hash_find(i_mac_impl_hash, (mod_hash_key_t)macname, 421 (mod_hash_val_t *)&mip); 422 423 if (err != 0) { 424 rw_exit(&i_mac_impl_lock); 425 return (ENOENT); 426 } 427 428 if (mip->mi_disabled) { 429 rw_exit(&i_mac_impl_lock); 430 return (ENOENT); 431 } 432 433 if (mip->mi_exclusive) { 434 rw_exit(&i_mac_impl_lock); 435 return (EBUSY); 436 } 437 438 mip->mi_ref++; 439 rw_exit(&i_mac_impl_lock); 440 441 *pmip = mip; 442 return (0); 443 } 444 445 static void 446 mac_rele(mac_impl_t *mip) 447 { 448 rw_enter(&i_mac_impl_lock, RW_WRITER); 449 ASSERT(mip->mi_ref != 0); 450 if (--mip->mi_ref == 0) 451 ASSERT(!mip->mi_activelink); 452 rw_exit(&i_mac_impl_lock); 453 } 454 455 int 456 mac_hold_exclusive(mac_handle_t mh) 457 { 458 mac_impl_t *mip = (mac_impl_t *)mh; 459 460 /* 461 * Look up its entry in the global hash table. 462 */ 463 rw_enter(&i_mac_impl_lock, RW_WRITER); 464 if (mip->mi_disabled) { 465 rw_exit(&i_mac_impl_lock); 466 return (ENOENT); 467 } 468 469 if (mip->mi_ref != 0) { 470 rw_exit(&i_mac_impl_lock); 471 return (EBUSY); 472 } 473 474 ASSERT(!mip->mi_exclusive); 475 476 mip->mi_ref++; 477 mip->mi_exclusive = B_TRUE; 478 rw_exit(&i_mac_impl_lock); 479 return (0); 480 } 481 482 void 483 mac_rele_exclusive(mac_handle_t mh) 484 { 485 mac_impl_t *mip = (mac_impl_t *)mh; 486 487 /* 488 * Look up its entry in the global hash table. 489 */ 490 rw_enter(&i_mac_impl_lock, RW_WRITER); 491 ASSERT(mip->mi_ref == 1 && mip->mi_exclusive); 492 mip->mi_ref--; 493 mip->mi_exclusive = B_FALSE; 494 rw_exit(&i_mac_impl_lock); 495 } 496 497 int 498 mac_open(const char *macname, mac_handle_t *mhp) 499 { 500 mac_impl_t *mip; 501 int err; 502 503 /* 504 * Look up its entry in the global hash table. 505 */ 506 if ((err = mac_hold(macname, &mip)) != 0) 507 return (err); 508 509 rw_enter(&mip->mi_gen_lock, RW_WRITER); 510 511 if ((mip->mi_oref != 0) || 512 !(mip->mi_callbacks->mc_callbacks & MC_OPEN)) { 513 goto done; 514 } 515 516 /* 517 * Note that we do not hold i_mac_impl_lock when calling the 518 * mc_open() callback function to avoid deadlock with the 519 * i_mac_notify() function. 520 */ 521 if ((err = mip->mi_open(mip->mi_driver)) != 0) { 522 rw_exit(&mip->mi_gen_lock); 523 mac_rele(mip); 524 return (err); 525 } 526 527 done: 528 mip->mi_oref++; 529 rw_exit(&mip->mi_gen_lock); 530 *mhp = (mac_handle_t)mip; 531 return (0); 532 } 533 534 int 535 mac_open_by_linkid(datalink_id_t linkid, mac_handle_t *mhp) 536 { 537 dls_dl_handle_t dlh; 538 int err; 539 540 if ((err = dls_devnet_hold_tmp(linkid, &dlh)) != 0) 541 return (err); 542 543 if (dls_devnet_vid(dlh) != VLAN_ID_NONE) { 544 err = EINVAL; 545 goto done; 546 } 547 548 err = mac_open(dls_devnet_mac(dlh), mhp); 549 550 done: 551 dls_devnet_rele_tmp(dlh); 552 return (err); 553 } 554 555 int 556 mac_open_by_linkname(const char *link, mac_handle_t *mhp) 557 { 558 datalink_id_t linkid; 559 int err; 560 561 if ((err = dls_mgmt_get_linkid(link, &linkid)) != 0) 562 return (err); 563 return (mac_open_by_linkid(linkid, mhp)); 564 } 565 566 void 567 mac_close(mac_handle_t mh) 568 { 569 mac_impl_t *mip = (mac_impl_t *)mh; 570 571 rw_enter(&mip->mi_gen_lock, RW_WRITER); 572 573 ASSERT(mip->mi_oref != 0); 574 if (--mip->mi_oref == 0) { 575 if ((mip->mi_callbacks->mc_callbacks & MC_CLOSE)) 576 mip->mi_close(mip->mi_driver); 577 } 578 rw_exit(&mip->mi_gen_lock); 579 580 mac_rele(mip); 581 } 582 583 const mac_info_t * 584 mac_info(mac_handle_t mh) 585 { 586 return (&((mac_impl_t *)mh)->mi_info); 587 } 588 589 dev_info_t * 590 mac_devinfo_get(mac_handle_t mh) 591 { 592 return (((mac_impl_t *)mh)->mi_dip); 593 } 594 595 const char * 596 mac_name(mac_handle_t mh) 597 { 598 return (((mac_impl_t *)mh)->mi_name); 599 } 600 601 minor_t 602 mac_minor(mac_handle_t mh) 603 { 604 return (((mac_impl_t *)mh)->mi_minor); 605 } 606 607 uint64_t 608 mac_stat_get(mac_handle_t mh, uint_t stat) 609 { 610 mac_impl_t *mip = (mac_impl_t *)mh; 611 uint64_t val; 612 int ret; 613 614 /* 615 * The range of stat determines where it is maintained. Stat 616 * values from 0 up to (but not including) MAC_STAT_MIN are 617 * mainteined by the mac module itself. Everything else is 618 * maintained by the driver. 619 */ 620 if (stat < MAC_STAT_MIN) { 621 /* These stats are maintained by the mac module itself. */ 622 switch (stat) { 623 case MAC_STAT_LINK_STATE: 624 return (mip->mi_linkstate); 625 case MAC_STAT_LINK_UP: 626 return (mip->mi_linkstate == LINK_STATE_UP); 627 case MAC_STAT_PROMISC: 628 return (mip->mi_devpromisc != 0); 629 default: 630 ASSERT(B_FALSE); 631 } 632 } 633 634 /* 635 * Call the driver to get the given statistic. 636 */ 637 ret = mip->mi_getstat(mip->mi_driver, stat, &val); 638 if (ret != 0) { 639 /* 640 * The driver doesn't support this statistic. Get the 641 * statistic's default value. 642 */ 643 val = mac_stat_default(mip, stat); 644 } 645 return (val); 646 } 647 648 int 649 mac_start(mac_handle_t mh) 650 { 651 mac_impl_t *mip = (mac_impl_t *)mh; 652 int err; 653 654 ASSERT(mip->mi_start != NULL); 655 656 rw_enter(&(mip->mi_state_lock), RW_WRITER); 657 658 /* 659 * Check whether the device is already started. 660 */ 661 if (mip->mi_active++ != 0) { 662 /* 663 * It's already started so there's nothing more to do. 664 */ 665 err = 0; 666 goto done; 667 } 668 669 /* 670 * Start the device. 671 */ 672 if ((err = mip->mi_start(mip->mi_driver)) != 0) 673 --mip->mi_active; 674 675 done: 676 rw_exit(&(mip->mi_state_lock)); 677 return (err); 678 } 679 680 void 681 mac_stop(mac_handle_t mh) 682 { 683 mac_impl_t *mip = (mac_impl_t *)mh; 684 685 ASSERT(mip->mi_stop != NULL); 686 687 rw_enter(&(mip->mi_state_lock), RW_WRITER); 688 689 /* 690 * Check whether the device is still needed. 691 */ 692 ASSERT(mip->mi_active != 0); 693 if (--mip->mi_active != 0) { 694 /* 695 * It's still needed so there's nothing more to do. 696 */ 697 goto done; 698 } 699 700 /* 701 * Stop the device. 702 */ 703 mip->mi_stop(mip->mi_driver); 704 705 done: 706 rw_exit(&(mip->mi_state_lock)); 707 } 708 709 int 710 mac_multicst_add(mac_handle_t mh, const uint8_t *addr) 711 { 712 mac_impl_t *mip = (mac_impl_t *)mh; 713 mac_multicst_addr_t **pp; 714 mac_multicst_addr_t *p; 715 int err; 716 717 ASSERT(mip->mi_multicst != NULL); 718 719 /* 720 * Verify the address. 721 */ 722 if ((err = mip->mi_type->mt_ops.mtops_multicst_verify(addr, 723 mip->mi_pdata)) != 0) { 724 return (err); 725 } 726 727 /* 728 * Check whether the given address is already enabled. 729 */ 730 rw_enter(&(mip->mi_data_lock), RW_WRITER); 731 for (pp = &(mip->mi_mmap); (p = *pp) != NULL; pp = &(p->mma_nextp)) { 732 if (bcmp(p->mma_addr, addr, mip->mi_type->mt_addr_length) == 733 0) { 734 /* 735 * The address is already enabled so just bump the 736 * reference count. 737 */ 738 p->mma_ref++; 739 err = 0; 740 goto done; 741 } 742 } 743 744 /* 745 * Allocate a new list entry. 746 */ 747 if ((p = kmem_zalloc(sizeof (mac_multicst_addr_t), 748 KM_NOSLEEP)) == NULL) { 749 err = ENOMEM; 750 goto done; 751 } 752 753 /* 754 * Enable a new multicast address. 755 */ 756 if ((err = mip->mi_multicst(mip->mi_driver, B_TRUE, addr)) != 0) { 757 kmem_free(p, sizeof (mac_multicst_addr_t)); 758 goto done; 759 } 760 761 /* 762 * Add the address to the list of enabled addresses. 763 */ 764 bcopy(addr, p->mma_addr, mip->mi_type->mt_addr_length); 765 p->mma_ref++; 766 *pp = p; 767 768 done: 769 rw_exit(&(mip->mi_data_lock)); 770 return (err); 771 } 772 773 int 774 mac_multicst_remove(mac_handle_t mh, const uint8_t *addr) 775 { 776 mac_impl_t *mip = (mac_impl_t *)mh; 777 mac_multicst_addr_t **pp; 778 mac_multicst_addr_t *p; 779 int err; 780 781 ASSERT(mip->mi_multicst != NULL); 782 783 /* 784 * Find the entry in the list for the given address. 785 */ 786 rw_enter(&(mip->mi_data_lock), RW_WRITER); 787 for (pp = &(mip->mi_mmap); (p = *pp) != NULL; pp = &(p->mma_nextp)) { 788 if (bcmp(p->mma_addr, addr, mip->mi_type->mt_addr_length) == 789 0) { 790 if (--p->mma_ref == 0) 791 break; 792 793 /* 794 * There is still a reference to this address so 795 * there's nothing more to do. 796 */ 797 err = 0; 798 goto done; 799 } 800 } 801 802 /* 803 * We did not find an entry for the given address so it is not 804 * currently enabled. 805 */ 806 if (p == NULL) { 807 err = ENOENT; 808 goto done; 809 } 810 ASSERT(p->mma_ref == 0); 811 812 /* 813 * Disable the multicast address. 814 */ 815 if ((err = mip->mi_multicst(mip->mi_driver, B_FALSE, addr)) != 0) { 816 p->mma_ref++; 817 goto done; 818 } 819 820 /* 821 * Remove it from the list. 822 */ 823 *pp = p->mma_nextp; 824 kmem_free(p, sizeof (mac_multicst_addr_t)); 825 826 done: 827 rw_exit(&(mip->mi_data_lock)); 828 return (err); 829 } 830 831 /* 832 * mac_unicst_verify: Verifies the passed address. It fails 833 * if the passed address is a group address or has incorrect length. 834 */ 835 boolean_t 836 mac_unicst_verify(mac_handle_t mh, const uint8_t *addr, uint_t len) 837 { 838 mac_impl_t *mip = (mac_impl_t *)mh; 839 840 /* 841 * Verify the address. 842 */ 843 if ((len != mip->mi_type->mt_addr_length) || 844 (mip->mi_type->mt_ops.mtops_unicst_verify(addr, 845 mip->mi_pdata)) != 0) { 846 return (B_FALSE); 847 } else { 848 return (B_TRUE); 849 } 850 } 851 852 int 853 mac_unicst_set(mac_handle_t mh, const uint8_t *addr) 854 { 855 mac_impl_t *mip = (mac_impl_t *)mh; 856 int err; 857 boolean_t notify = B_FALSE; 858 859 ASSERT(mip->mi_unicst != NULL); 860 861 /* 862 * Verify the address. 863 */ 864 if ((err = mip->mi_type->mt_ops.mtops_unicst_verify(addr, 865 mip->mi_pdata)) != 0) { 866 return (err); 867 } 868 869 /* 870 * Program the new unicast address. 871 */ 872 rw_enter(&(mip->mi_data_lock), RW_WRITER); 873 874 /* 875 * If address doesn't change, do nothing. 876 * This check is necessary otherwise it may call into mac_unicst_set 877 * recursively. 878 */ 879 if (bcmp(addr, mip->mi_addr, mip->mi_type->mt_addr_length) == 0) 880 goto done; 881 882 if ((err = mip->mi_unicst(mip->mi_driver, addr)) != 0) 883 goto done; 884 885 /* 886 * Save the address and flag that we need to send a notification. 887 */ 888 bcopy(addr, mip->mi_addr, mip->mi_type->mt_addr_length); 889 notify = B_TRUE; 890 891 done: 892 rw_exit(&(mip->mi_data_lock)); 893 894 if (notify) 895 i_mac_notify(mip, MAC_NOTE_UNICST); 896 897 return (err); 898 } 899 900 void 901 mac_unicst_get(mac_handle_t mh, uint8_t *addr) 902 { 903 mac_impl_t *mip = (mac_impl_t *)mh; 904 905 /* 906 * Copy out the current unicast source address. 907 */ 908 rw_enter(&(mip->mi_data_lock), RW_READER); 909 bcopy(mip->mi_addr, addr, mip->mi_type->mt_addr_length); 910 rw_exit(&(mip->mi_data_lock)); 911 } 912 913 void 914 mac_dest_get(mac_handle_t mh, uint8_t *addr) 915 { 916 mac_impl_t *mip = (mac_impl_t *)mh; 917 918 /* 919 * Copy out the current destination address. 920 */ 921 rw_enter(&(mip->mi_data_lock), RW_READER); 922 bcopy(mip->mi_dstaddr, addr, mip->mi_type->mt_addr_length); 923 rw_exit(&(mip->mi_data_lock)); 924 } 925 926 int 927 mac_promisc_set(mac_handle_t mh, boolean_t on, mac_promisc_type_t ptype) 928 { 929 mac_impl_t *mip = (mac_impl_t *)mh; 930 int err = 0; 931 932 ASSERT(mip->mi_setpromisc != NULL); 933 ASSERT(ptype == MAC_DEVPROMISC || ptype == MAC_PROMISC); 934 935 /* 936 * Determine whether we should enable or disable promiscuous mode. 937 * For details on the distinction between "device promiscuous mode" 938 * and "MAC promiscuous mode", see PSARC/2005/289. 939 */ 940 rw_enter(&(mip->mi_data_lock), RW_WRITER); 941 if (on) { 942 /* 943 * Enable promiscuous mode on the device if not yet enabled. 944 */ 945 if (mip->mi_devpromisc++ == 0) { 946 err = mip->mi_setpromisc(mip->mi_driver, B_TRUE); 947 if (err != 0) { 948 mip->mi_devpromisc--; 949 goto done; 950 } 951 i_mac_notify(mip, MAC_NOTE_DEVPROMISC); 952 } 953 954 /* 955 * Enable promiscuous mode on the MAC if not yet enabled. 956 */ 957 if (ptype == MAC_PROMISC && mip->mi_promisc++ == 0) 958 i_mac_notify(mip, MAC_NOTE_PROMISC); 959 } else { 960 if (mip->mi_devpromisc == 0) { 961 err = EPROTO; 962 goto done; 963 } 964 /* 965 * Disable promiscuous mode on the device if this is the last 966 * enabling. 967 */ 968 if (--mip->mi_devpromisc == 0) { 969 err = mip->mi_setpromisc(mip->mi_driver, B_FALSE); 970 if (err != 0) { 971 mip->mi_devpromisc++; 972 goto done; 973 } 974 i_mac_notify(mip, MAC_NOTE_DEVPROMISC); 975 } 976 977 /* 978 * Disable promiscuous mode on the MAC if this is the last 979 * enabling. 980 */ 981 if (ptype == MAC_PROMISC && --mip->mi_promisc == 0) 982 i_mac_notify(mip, MAC_NOTE_PROMISC); 983 } 984 985 done: 986 rw_exit(&(mip->mi_data_lock)); 987 return (err); 988 } 989 990 boolean_t 991 mac_promisc_get(mac_handle_t mh, mac_promisc_type_t ptype) 992 { 993 mac_impl_t *mip = (mac_impl_t *)mh; 994 995 ASSERT(ptype == MAC_DEVPROMISC || ptype == MAC_PROMISC); 996 997 /* 998 * Return the current promiscuity. 999 */ 1000 if (ptype == MAC_DEVPROMISC) 1001 return (mip->mi_devpromisc != 0); 1002 else 1003 return (mip->mi_promisc != 0); 1004 } 1005 1006 void 1007 mac_resources(mac_handle_t mh) 1008 { 1009 mac_impl_t *mip = (mac_impl_t *)mh; 1010 1011 /* 1012 * If the driver supports resource registration, call the driver to 1013 * ask it to register its resources. 1014 */ 1015 if (mip->mi_callbacks->mc_callbacks & MC_RESOURCES) 1016 mip->mi_resources(mip->mi_driver); 1017 } 1018 1019 void 1020 mac_ioctl(mac_handle_t mh, queue_t *wq, mblk_t *bp) 1021 { 1022 mac_impl_t *mip = (mac_impl_t *)mh; 1023 1024 /* 1025 * Call the driver to handle the ioctl. The driver may not support 1026 * any ioctls, in which case we reply with a NAK on its behalf. 1027 */ 1028 if (mip->mi_callbacks->mc_callbacks & MC_IOCTL) 1029 mip->mi_ioctl(mip->mi_driver, wq, bp); 1030 else 1031 miocnak(wq, bp, 0, EINVAL); 1032 } 1033 1034 const mac_txinfo_t * 1035 mac_do_tx_get(mac_handle_t mh, boolean_t is_vnic) 1036 { 1037 mac_impl_t *mip = (mac_impl_t *)mh; 1038 mac_txinfo_t *mtp; 1039 1040 /* 1041 * Grab the lock to prevent us from racing with MAC_PROMISC being 1042 * changed. This is sufficient since MAC clients are careful to always 1043 * call mac_txloop_add() prior to enabling MAC_PROMISC, and to disable 1044 * MAC_PROMISC prior to calling mac_txloop_remove(). 1045 */ 1046 rw_enter(&mip->mi_tx_lock, RW_READER); 1047 1048 if (mac_promisc_get(mh, MAC_PROMISC)) { 1049 ASSERT(mip->mi_mtfp != NULL); 1050 if (mip->mi_vnic_present && !is_vnic) { 1051 mtp = &mip->mi_vnic_txloopinfo; 1052 } else { 1053 mtp = &mip->mi_txloopinfo; 1054 } 1055 } else { 1056 if (mip->mi_vnic_present && !is_vnic) { 1057 mtp = &mip->mi_vnic_txinfo; 1058 } else { 1059 /* 1060 * Note that we cannot ASSERT() that mip->mi_mtfp is 1061 * NULL, because to satisfy the above ASSERT(), we 1062 * have to disable MAC_PROMISC prior to calling 1063 * mac_txloop_remove(). 1064 */ 1065 mtp = &mip->mi_txinfo; 1066 } 1067 } 1068 1069 rw_exit(&mip->mi_tx_lock); 1070 return (mtp); 1071 } 1072 1073 /* 1074 * Invoked by VNIC to obtain the transmit entry point. 1075 */ 1076 const mac_txinfo_t * 1077 mac_vnic_tx_get(mac_handle_t mh) 1078 { 1079 return (mac_do_tx_get(mh, B_TRUE)); 1080 } 1081 1082 /* 1083 * Invoked by any non-VNIC client to obtain the transmit entry point. 1084 * If a VNIC is present, the VNIC transmit function provided by the VNIC 1085 * will be returned to the MAC client. 1086 */ 1087 const mac_txinfo_t * 1088 mac_tx_get(mac_handle_t mh) 1089 { 1090 return (mac_do_tx_get(mh, B_FALSE)); 1091 } 1092 1093 link_state_t 1094 mac_link_get(mac_handle_t mh) 1095 { 1096 return (((mac_impl_t *)mh)->mi_linkstate); 1097 } 1098 1099 mac_notify_handle_t 1100 mac_notify_add(mac_handle_t mh, mac_notify_t notify, void *arg) 1101 { 1102 mac_impl_t *mip = (mac_impl_t *)mh; 1103 mac_notify_fn_t *mnfp; 1104 1105 mnfp = kmem_zalloc(sizeof (mac_notify_fn_t), KM_SLEEP); 1106 mnfp->mnf_fn = notify; 1107 mnfp->mnf_arg = arg; 1108 1109 /* 1110 * Add it to the head of the 'notify' callback list. 1111 */ 1112 rw_enter(&mip->mi_notify_lock, RW_WRITER); 1113 mnfp->mnf_nextp = mip->mi_mnfp; 1114 mip->mi_mnfp = mnfp; 1115 rw_exit(&mip->mi_notify_lock); 1116 1117 return ((mac_notify_handle_t)mnfp); 1118 } 1119 1120 void 1121 mac_notify_remove(mac_handle_t mh, mac_notify_handle_t mnh) 1122 { 1123 mac_impl_t *mip = (mac_impl_t *)mh; 1124 mac_notify_fn_t *mnfp = (mac_notify_fn_t *)mnh; 1125 mac_notify_fn_t **pp; 1126 mac_notify_fn_t *p; 1127 1128 /* 1129 * Search the 'notify' callback list for the function closure. 1130 */ 1131 rw_enter(&mip->mi_notify_lock, RW_WRITER); 1132 for (pp = &(mip->mi_mnfp); (p = *pp) != NULL; 1133 pp = &(p->mnf_nextp)) { 1134 if (p == mnfp) 1135 break; 1136 } 1137 ASSERT(p != NULL); 1138 1139 /* 1140 * Remove it from the list. 1141 */ 1142 *pp = p->mnf_nextp; 1143 rw_exit(&mip->mi_notify_lock); 1144 1145 /* 1146 * Free it. 1147 */ 1148 kmem_free(mnfp, sizeof (mac_notify_fn_t)); 1149 } 1150 1151 void 1152 mac_notify(mac_handle_t mh) 1153 { 1154 mac_impl_t *mip = (mac_impl_t *)mh; 1155 mac_notify_type_t type; 1156 1157 for (type = 0; type < MAC_NNOTE; type++) 1158 i_mac_notify(mip, type); 1159 } 1160 1161 /* 1162 * Register a receive function for this mac. 1163 * More information on this function's interaction with mac_rx() 1164 * can be found atop mac_rx(). 1165 */ 1166 mac_rx_handle_t 1167 mac_do_rx_add(mac_handle_t mh, mac_rx_t rx, void *arg, boolean_t is_active) 1168 { 1169 mac_impl_t *mip = (mac_impl_t *)mh; 1170 mac_rx_fn_t *mrfp; 1171 1172 mrfp = kmem_zalloc(sizeof (mac_rx_fn_t), KM_SLEEP); 1173 mrfp->mrf_fn = rx; 1174 mrfp->mrf_arg = arg; 1175 mrfp->mrf_active = is_active; 1176 1177 /* 1178 * Add it to the head of the 'rx' callback list. 1179 */ 1180 rw_enter(&(mip->mi_rx_lock), RW_WRITER); 1181 1182 /* 1183 * mac_rx() will only call callbacks that are marked inuse. 1184 */ 1185 mrfp->mrf_inuse = B_TRUE; 1186 mrfp->mrf_nextp = mip->mi_mrfp; 1187 1188 /* 1189 * mac_rx() could be traversing the remainder of the list 1190 * and miss the new callback we're adding here. This is not a problem 1191 * because we do not guarantee the callback to take effect immediately 1192 * after mac_rx_add() returns. 1193 */ 1194 mip->mi_mrfp = mrfp; 1195 rw_exit(&(mip->mi_rx_lock)); 1196 1197 return ((mac_rx_handle_t)mrfp); 1198 } 1199 1200 mac_rx_handle_t 1201 mac_rx_add(mac_handle_t mh, mac_rx_t rx, void *arg) 1202 { 1203 return (mac_do_rx_add(mh, rx, arg, B_FALSE)); 1204 } 1205 1206 mac_rx_handle_t 1207 mac_active_rx_add(mac_handle_t mh, mac_rx_t rx, void *arg) 1208 { 1209 return (mac_do_rx_add(mh, rx, arg, B_TRUE)); 1210 } 1211 1212 /* 1213 * Unregister a receive function for this mac. 1214 * This function does not block if wait is B_FALSE. This is useful 1215 * for clients who call mac_rx_remove() from a non-blockable context. 1216 * More information on this function's interaction with mac_rx() 1217 * can be found atop mac_rx(). 1218 */ 1219 void 1220 mac_rx_remove(mac_handle_t mh, mac_rx_handle_t mrh, boolean_t wait) 1221 { 1222 mac_impl_t *mip = (mac_impl_t *)mh; 1223 mac_rx_fn_t *mrfp = (mac_rx_fn_t *)mrh; 1224 mac_rx_fn_t **pp; 1225 mac_rx_fn_t *p; 1226 1227 /* 1228 * Search the 'rx' callback list for the function closure. 1229 */ 1230 rw_enter(&mip->mi_rx_lock, RW_WRITER); 1231 for (pp = &(mip->mi_mrfp); (p = *pp) != NULL; pp = &(p->mrf_nextp)) { 1232 if (p == mrfp) 1233 break; 1234 } 1235 ASSERT(p != NULL); 1236 1237 /* 1238 * If mac_rx() is running, mark callback for deletion 1239 * and return (if wait is false), or wait until mac_rx() 1240 * exits (if wait is true). 1241 */ 1242 if (mip->mi_rx_ref > 0) { 1243 DTRACE_PROBE1(defer_delete, mac_impl_t *, mip); 1244 p->mrf_inuse = B_FALSE; 1245 mutex_enter(&mip->mi_lock); 1246 mip->mi_rx_removed++; 1247 mutex_exit(&mip->mi_lock); 1248 1249 rw_exit(&mip->mi_rx_lock); 1250 if (wait) 1251 mac_rx_remove_wait(mh); 1252 return; 1253 } 1254 1255 /* Remove it from the list. */ 1256 *pp = p->mrf_nextp; 1257 kmem_free(mrfp, sizeof (mac_rx_fn_t)); 1258 rw_exit(&mip->mi_rx_lock); 1259 } 1260 1261 /* 1262 * Wait for all pending callback removals to be completed by mac_rx(). 1263 * Note that if we call mac_rx_remove() immediately before this, there is no 1264 * guarantee we would wait *only* on the callback that we specified. 1265 * mac_rx_remove() could have been called by other threads and we would have 1266 * to wait for other marked callbacks to be removed as well. 1267 */ 1268 void 1269 mac_rx_remove_wait(mac_handle_t mh) 1270 { 1271 mac_impl_t *mip = (mac_impl_t *)mh; 1272 1273 mutex_enter(&mip->mi_lock); 1274 while (mip->mi_rx_removed > 0) { 1275 DTRACE_PROBE1(need_wait, mac_impl_t *, mip); 1276 cv_wait(&mip->mi_rx_cv, &mip->mi_lock); 1277 } 1278 mutex_exit(&mip->mi_lock); 1279 } 1280 1281 mac_txloop_handle_t 1282 mac_txloop_add(mac_handle_t mh, mac_txloop_t tx, void *arg) 1283 { 1284 mac_impl_t *mip = (mac_impl_t *)mh; 1285 mac_txloop_fn_t *mtfp; 1286 1287 mtfp = kmem_zalloc(sizeof (mac_txloop_fn_t), KM_SLEEP); 1288 mtfp->mtf_fn = tx; 1289 mtfp->mtf_arg = arg; 1290 1291 /* 1292 * Add it to the head of the 'tx' callback list. 1293 */ 1294 rw_enter(&(mip->mi_tx_lock), RW_WRITER); 1295 mtfp->mtf_nextp = mip->mi_mtfp; 1296 mip->mi_mtfp = mtfp; 1297 rw_exit(&(mip->mi_tx_lock)); 1298 1299 return ((mac_txloop_handle_t)mtfp); 1300 } 1301 1302 /* 1303 * Unregister a transmit function for this mac. This removes the function 1304 * from the list of transmit functions for this mac. 1305 */ 1306 void 1307 mac_txloop_remove(mac_handle_t mh, mac_txloop_handle_t mth) 1308 { 1309 mac_impl_t *mip = (mac_impl_t *)mh; 1310 mac_txloop_fn_t *mtfp = (mac_txloop_fn_t *)mth; 1311 mac_txloop_fn_t **pp; 1312 mac_txloop_fn_t *p; 1313 1314 /* 1315 * Search the 'tx' callback list for the function. 1316 */ 1317 rw_enter(&(mip->mi_tx_lock), RW_WRITER); 1318 for (pp = &(mip->mi_mtfp); (p = *pp) != NULL; pp = &(p->mtf_nextp)) { 1319 if (p == mtfp) 1320 break; 1321 } 1322 ASSERT(p != NULL); 1323 1324 /* Remove it from the list. */ 1325 *pp = p->mtf_nextp; 1326 kmem_free(mtfp, sizeof (mac_txloop_fn_t)); 1327 rw_exit(&(mip->mi_tx_lock)); 1328 } 1329 1330 void 1331 mac_resource_set(mac_handle_t mh, mac_resource_add_t add, void *arg) 1332 { 1333 mac_impl_t *mip = (mac_impl_t *)mh; 1334 1335 /* 1336 * Update the 'resource_add' callbacks. 1337 */ 1338 rw_enter(&(mip->mi_resource_lock), RW_WRITER); 1339 mip->mi_resource_add = add; 1340 mip->mi_resource_add_arg = arg; 1341 rw_exit(&(mip->mi_resource_lock)); 1342 } 1343 1344 /* 1345 * Driver support functions. 1346 */ 1347 1348 mac_register_t * 1349 mac_alloc(uint_t mac_version) 1350 { 1351 mac_register_t *mregp; 1352 1353 /* 1354 * Make sure there isn't a version mismatch between the driver and 1355 * the framework. In the future, if multiple versions are 1356 * supported, this check could become more sophisticated. 1357 */ 1358 if (mac_version != MAC_VERSION) 1359 return (NULL); 1360 1361 mregp = kmem_zalloc(sizeof (mac_register_t), KM_SLEEP); 1362 mregp->m_version = mac_version; 1363 return (mregp); 1364 } 1365 1366 void 1367 mac_free(mac_register_t *mregp) 1368 { 1369 kmem_free(mregp, sizeof (mac_register_t)); 1370 } 1371 1372 /* 1373 * Allocate a minor number. 1374 */ 1375 minor_t 1376 mac_minor_hold(boolean_t sleep) 1377 { 1378 minor_t minor; 1379 1380 /* 1381 * Grab a value from the arena. 1382 */ 1383 atomic_add_32(&minor_count, 1); 1384 1385 if (sleep) 1386 minor = (uint_t)id_alloc(minor_ids); 1387 else 1388 minor = (uint_t)id_alloc_nosleep(minor_ids); 1389 1390 if (minor == 0) { 1391 atomic_add_32(&minor_count, -1); 1392 return (0); 1393 } 1394 1395 return (minor); 1396 } 1397 1398 /* 1399 * Release a previously allocated minor number. 1400 */ 1401 void 1402 mac_minor_rele(minor_t minor) 1403 { 1404 /* 1405 * Return the value to the arena. 1406 */ 1407 id_free(minor_ids, minor); 1408 atomic_add_32(&minor_count, -1); 1409 } 1410 1411 uint32_t 1412 mac_no_notification(mac_handle_t mh) 1413 { 1414 mac_impl_t *mip = (mac_impl_t *)mh; 1415 return (mip->mi_unsup_note); 1416 } 1417 1418 boolean_t 1419 mac_is_legacy(mac_handle_t mh) 1420 { 1421 mac_impl_t *mip = (mac_impl_t *)mh; 1422 return (mip->mi_legacy); 1423 } 1424 1425 /* 1426 * mac_register() is how drivers register new MACs with the GLDv3 1427 * framework. The mregp argument is allocated by drivers using the 1428 * mac_alloc() function, and can be freed using mac_free() immediately upon 1429 * return from mac_register(). Upon success (0 return value), the mhp 1430 * opaque pointer becomes the driver's handle to its MAC interface, and is 1431 * the argument to all other mac module entry points. 1432 */ 1433 int 1434 mac_register(mac_register_t *mregp, mac_handle_t *mhp) 1435 { 1436 mac_impl_t *mip; 1437 mactype_t *mtype; 1438 int err = EINVAL; 1439 struct devnames *dnp = NULL; 1440 uint_t instance; 1441 boolean_t style1_created = B_FALSE; 1442 boolean_t style2_created = B_FALSE; 1443 mac_capab_legacy_t legacy; 1444 char *driver; 1445 minor_t minor = 0; 1446 1447 /* Find the required MAC-Type plugin. */ 1448 if ((mtype = i_mactype_getplugin(mregp->m_type_ident)) == NULL) 1449 return (EINVAL); 1450 1451 /* Create a mac_impl_t to represent this MAC. */ 1452 mip = kmem_cache_alloc(i_mac_impl_cachep, KM_SLEEP); 1453 1454 /* 1455 * The mac is not ready for open yet. 1456 */ 1457 mip->mi_disabled = B_TRUE; 1458 1459 /* 1460 * When a mac is registered, the m_instance field can be set to: 1461 * 1462 * 0: Get the mac's instance number from m_dip. 1463 * This is usually used for physical device dips. 1464 * 1465 * [1 .. MAC_MAX_MINOR-1]: Use the value as the mac's instance number. 1466 * For example, when an aggregation is created with the key option, 1467 * "key" will be used as the instance number. 1468 * 1469 * -1: Assign an instance number from [MAC_MAX_MINOR .. MAXMIN-1]. 1470 * This is often used when a MAC of a virtual link is registered 1471 * (e.g., aggregation when "key" is not specified, or vnic). 1472 * 1473 * Note that the instance number is used to derive the mi_minor field 1474 * of mac_impl_t, which will then be used to derive the name of kstats 1475 * and the devfs nodes. The first 2 cases are needed to preserve 1476 * backward compatibility. 1477 */ 1478 switch (mregp->m_instance) { 1479 case 0: 1480 instance = ddi_get_instance(mregp->m_dip); 1481 break; 1482 case ((uint_t)-1): 1483 minor = mac_minor_hold(B_TRUE); 1484 if (minor == 0) { 1485 err = ENOSPC; 1486 goto fail; 1487 } 1488 instance = minor - 1; 1489 break; 1490 default: 1491 instance = mregp->m_instance; 1492 if (instance >= MAC_MAX_MINOR) { 1493 err = EINVAL; 1494 goto fail; 1495 } 1496 break; 1497 } 1498 1499 mip->mi_minor = (minor_t)(instance + 1); 1500 mip->mi_dip = mregp->m_dip; 1501 1502 driver = (char *)ddi_driver_name(mip->mi_dip); 1503 1504 /* Construct the MAC name as <drvname><instance> */ 1505 (void) snprintf(mip->mi_name, sizeof (mip->mi_name), "%s%d", 1506 driver, instance); 1507 1508 mip->mi_driver = mregp->m_driver; 1509 1510 mip->mi_type = mtype; 1511 mip->mi_margin = mregp->m_margin; 1512 mip->mi_info.mi_media = mtype->mt_type; 1513 mip->mi_info.mi_nativemedia = mtype->mt_nativetype; 1514 mip->mi_info.mi_sdu_min = mregp->m_min_sdu; 1515 if (mregp->m_max_sdu <= mregp->m_min_sdu) 1516 goto fail; 1517 mip->mi_info.mi_sdu_max = mregp->m_max_sdu; 1518 mip->mi_info.mi_addr_length = mip->mi_type->mt_addr_length; 1519 /* 1520 * If the media supports a broadcast address, cache a pointer to it 1521 * in the mac_info_t so that upper layers can use it. 1522 */ 1523 mip->mi_info.mi_brdcst_addr = mip->mi_type->mt_brdcst_addr; 1524 1525 /* 1526 * Copy the unicast source address into the mac_info_t, but only if 1527 * the MAC-Type defines a non-zero address length. We need to 1528 * handle MAC-Types that have an address length of 0 1529 * (point-to-point protocol MACs for example). 1530 */ 1531 if (mip->mi_type->mt_addr_length > 0) { 1532 if (mregp->m_src_addr == NULL) 1533 goto fail; 1534 mip->mi_info.mi_unicst_addr = 1535 kmem_alloc(mip->mi_type->mt_addr_length, KM_SLEEP); 1536 bcopy(mregp->m_src_addr, mip->mi_info.mi_unicst_addr, 1537 mip->mi_type->mt_addr_length); 1538 1539 /* 1540 * Copy the fixed 'factory' MAC address from the immutable 1541 * info. This is taken to be the MAC address currently in 1542 * use. 1543 */ 1544 bcopy(mip->mi_info.mi_unicst_addr, mip->mi_addr, 1545 mip->mi_type->mt_addr_length); 1546 /* Copy the destination address if one is provided. */ 1547 if (mregp->m_dst_addr != NULL) { 1548 bcopy(mregp->m_dst_addr, mip->mi_dstaddr, 1549 mip->mi_type->mt_addr_length); 1550 } 1551 } else if (mregp->m_src_addr != NULL) { 1552 goto fail; 1553 } 1554 1555 /* 1556 * The format of the m_pdata is specific to the plugin. It is 1557 * passed in as an argument to all of the plugin callbacks. The 1558 * driver can update this information by calling 1559 * mac_pdata_update(). 1560 */ 1561 if (mregp->m_pdata != NULL) { 1562 /* 1563 * Verify that the plugin supports MAC plugin data and that 1564 * the supplied data is valid. 1565 */ 1566 if (!(mip->mi_type->mt_ops.mtops_ops & MTOPS_PDATA_VERIFY)) 1567 goto fail; 1568 if (!mip->mi_type->mt_ops.mtops_pdata_verify(mregp->m_pdata, 1569 mregp->m_pdata_size)) { 1570 goto fail; 1571 } 1572 mip->mi_pdata = kmem_alloc(mregp->m_pdata_size, KM_SLEEP); 1573 bcopy(mregp->m_pdata, mip->mi_pdata, mregp->m_pdata_size); 1574 mip->mi_pdata_size = mregp->m_pdata_size; 1575 } 1576 1577 /* 1578 * Stash the driver callbacks into the mac_impl_t, but first sanity 1579 * check to make sure all mandatory callbacks are set. 1580 */ 1581 if (mregp->m_callbacks->mc_getstat == NULL || 1582 mregp->m_callbacks->mc_start == NULL || 1583 mregp->m_callbacks->mc_stop == NULL || 1584 mregp->m_callbacks->mc_setpromisc == NULL || 1585 mregp->m_callbacks->mc_multicst == NULL || 1586 mregp->m_callbacks->mc_unicst == NULL || 1587 mregp->m_callbacks->mc_tx == NULL) { 1588 goto fail; 1589 } 1590 mip->mi_callbacks = mregp->m_callbacks; 1591 1592 /* 1593 * Set up the possible transmit routines. 1594 */ 1595 mip->mi_txinfo.mt_fn = mip->mi_tx; 1596 mip->mi_txinfo.mt_arg = mip->mi_driver; 1597 1598 mip->mi_legacy = mac_capab_get((mac_handle_t)mip, 1599 MAC_CAPAB_LEGACY, &legacy); 1600 1601 if (mip->mi_legacy) { 1602 /* 1603 * Legacy device. Messages being sent will be looped back 1604 * by the underlying driver. Therefore the txloop function 1605 * pointer is the same as the tx function pointer. 1606 */ 1607 mip->mi_txloopinfo.mt_fn = mip->mi_txinfo.mt_fn; 1608 mip->mi_txloopinfo.mt_arg = mip->mi_txinfo.mt_arg; 1609 mip->mi_unsup_note = legacy.ml_unsup_note; 1610 mip->mi_phy_dev = legacy.ml_dev; 1611 } else { 1612 /* 1613 * Normal device. The framework needs to do the loopback. 1614 */ 1615 mip->mi_txloopinfo.mt_fn = mac_txloop; 1616 mip->mi_txloopinfo.mt_arg = mip; 1617 mip->mi_unsup_note = 0; 1618 mip->mi_phy_dev = makedevice(ddi_driver_major(mip->mi_dip), 1619 ddi_get_instance(mip->mi_dip) + 1); 1620 } 1621 1622 mip->mi_vnic_txinfo.mt_fn = mac_vnic_tx; 1623 mip->mi_vnic_txinfo.mt_arg = mip; 1624 1625 mip->mi_vnic_txloopinfo.mt_fn = mac_vnic_txloop; 1626 mip->mi_vnic_txloopinfo.mt_arg = mip; 1627 1628 /* 1629 * Allocate a notification thread. 1630 */ 1631 mip->mi_notify_thread = thread_create(NULL, 0, i_mac_notify_thread, 1632 mip, 0, &p0, TS_RUN, minclsyspri); 1633 if (mip->mi_notify_thread == NULL) 1634 goto fail; 1635 1636 /* 1637 * Initialize the kstats for this device. 1638 */ 1639 mac_stat_create(mip); 1640 1641 /* set the gldv3 flag in dn_flags */ 1642 dnp = &devnamesp[ddi_driver_major(mip->mi_dip)]; 1643 LOCK_DEV_OPS(&dnp->dn_lock); 1644 dnp->dn_flags |= (DN_GLDV3_DRIVER | DN_NETWORK_DRIVER); 1645 UNLOCK_DEV_OPS(&dnp->dn_lock); 1646 1647 if (mip->mi_minor < MAC_MAX_MINOR + 1) { 1648 /* Create a style-2 DLPI device */ 1649 if (ddi_create_minor_node(mip->mi_dip, driver, S_IFCHR, 0, 1650 DDI_NT_NET, CLONE_DEV) != DDI_SUCCESS) 1651 goto fail; 1652 style2_created = B_TRUE; 1653 1654 /* Create a style-1 DLPI device */ 1655 if (ddi_create_minor_node(mip->mi_dip, mip->mi_name, S_IFCHR, 1656 mip->mi_minor, DDI_NT_NET, 0) != DDI_SUCCESS) 1657 goto fail; 1658 style1_created = B_TRUE; 1659 } 1660 1661 rw_enter(&i_mac_impl_lock, RW_WRITER); 1662 if (mod_hash_insert(i_mac_impl_hash, 1663 (mod_hash_key_t)mip->mi_name, (mod_hash_val_t)mip) != 0) { 1664 1665 rw_exit(&i_mac_impl_lock); 1666 err = EEXIST; 1667 goto fail; 1668 } 1669 1670 /* 1671 * Mark the MAC to be ready for open. 1672 */ 1673 mip->mi_disabled = B_FALSE; 1674 1675 rw_exit(&i_mac_impl_lock); 1676 1677 atomic_inc_32(&i_mac_impl_count); 1678 1679 cmn_err(CE_NOTE, "!%s registered", mip->mi_name); 1680 *mhp = (mac_handle_t)mip; 1681 return (0); 1682 1683 fail: 1684 if (style1_created) 1685 ddi_remove_minor_node(mip->mi_dip, mip->mi_name); 1686 1687 if (style2_created) 1688 ddi_remove_minor_node(mip->mi_dip, driver); 1689 1690 /* clean up notification thread */ 1691 if (mip->mi_notify_thread != NULL) { 1692 mutex_enter(&mip->mi_notify_bits_lock); 1693 mip->mi_notify_bits = (1 << MAC_NNOTE); 1694 cv_broadcast(&mip->mi_notify_cv); 1695 while (mip->mi_notify_bits != 0) 1696 cv_wait(&mip->mi_notify_cv, &mip->mi_notify_bits_lock); 1697 mutex_exit(&mip->mi_notify_bits_lock); 1698 } 1699 1700 if (mip->mi_info.mi_unicst_addr != NULL) { 1701 kmem_free(mip->mi_info.mi_unicst_addr, 1702 mip->mi_type->mt_addr_length); 1703 mip->mi_info.mi_unicst_addr = NULL; 1704 } 1705 1706 mac_stat_destroy(mip); 1707 1708 if (mip->mi_type != NULL) { 1709 atomic_dec_32(&mip->mi_type->mt_ref); 1710 mip->mi_type = NULL; 1711 } 1712 1713 if (mip->mi_pdata != NULL) { 1714 kmem_free(mip->mi_pdata, mip->mi_pdata_size); 1715 mip->mi_pdata = NULL; 1716 mip->mi_pdata_size = 0; 1717 } 1718 1719 if (minor != 0) { 1720 ASSERT(minor > MAC_MAX_MINOR); 1721 mac_minor_rele(minor); 1722 } 1723 1724 kmem_cache_free(i_mac_impl_cachep, mip); 1725 return (err); 1726 } 1727 1728 int 1729 mac_disable(mac_handle_t mh) 1730 { 1731 mac_impl_t *mip = (mac_impl_t *)mh; 1732 1733 /* 1734 * See if there are any other references to this mac_t (e.g., VLAN's). 1735 * If not, set mi_disabled to prevent any new VLAN's from being 1736 * created while we're destroying this mac. 1737 */ 1738 rw_enter(&i_mac_impl_lock, RW_WRITER); 1739 if (mip->mi_ref > 0) { 1740 rw_exit(&i_mac_impl_lock); 1741 return (EBUSY); 1742 } 1743 mip->mi_disabled = B_TRUE; 1744 rw_exit(&i_mac_impl_lock); 1745 return (0); 1746 } 1747 1748 int 1749 mac_unregister(mac_handle_t mh) 1750 { 1751 int err; 1752 mac_impl_t *mip = (mac_impl_t *)mh; 1753 mod_hash_val_t val; 1754 mac_multicst_addr_t *p, *nextp; 1755 mac_margin_req_t *mmr, *nextmmr; 1756 1757 /* 1758 * See if there are any other references to this mac_t (e.g., VLAN's). 1759 * If not, set mi_disabled to prevent any new VLAN's from being 1760 * created while we're destroying this mac. Once mac_disable() returns 1761 * 0, the rest of mac_unregister() stuff should continue without 1762 * returning an error. 1763 */ 1764 if (!mip->mi_disabled) { 1765 if ((err = mac_disable(mh)) != 0) 1766 return (err); 1767 } 1768 1769 /* 1770 * Clean up notification thread (wait for it to exit). 1771 */ 1772 mutex_enter(&mip->mi_notify_bits_lock); 1773 mip->mi_notify_bits = (1 << MAC_NNOTE); 1774 cv_broadcast(&mip->mi_notify_cv); 1775 while (mip->mi_notify_bits != 0) 1776 cv_wait(&mip->mi_notify_cv, &mip->mi_notify_bits_lock); 1777 mutex_exit(&mip->mi_notify_bits_lock); 1778 1779 if (mip->mi_minor < MAC_MAX_MINOR + 1) { 1780 ddi_remove_minor_node(mip->mi_dip, mip->mi_name); 1781 ddi_remove_minor_node(mip->mi_dip, 1782 (char *)ddi_driver_name(mip->mi_dip)); 1783 } 1784 1785 ASSERT(!mip->mi_activelink); 1786 1787 mac_stat_destroy(mip); 1788 1789 rw_enter(&i_mac_impl_lock, RW_WRITER); 1790 (void) mod_hash_remove(i_mac_impl_hash, 1791 (mod_hash_key_t)mip->mi_name, &val); 1792 ASSERT(mip == (mac_impl_t *)val); 1793 1794 ASSERT(i_mac_impl_count > 0); 1795 atomic_dec_32(&i_mac_impl_count); 1796 rw_exit(&i_mac_impl_lock); 1797 1798 if (mip->mi_pdata != NULL) 1799 kmem_free(mip->mi_pdata, mip->mi_pdata_size); 1800 mip->mi_pdata = NULL; 1801 mip->mi_pdata_size = 0; 1802 1803 /* 1804 * Free the list of multicast addresses. 1805 */ 1806 for (p = mip->mi_mmap; p != NULL; p = nextp) { 1807 nextp = p->mma_nextp; 1808 kmem_free(p, sizeof (mac_multicst_addr_t)); 1809 } 1810 mip->mi_mmap = NULL; 1811 1812 /* 1813 * Free the list of margin request. 1814 */ 1815 for (mmr = mip->mi_mmrp; mmr != NULL; mmr = nextmmr) { 1816 nextmmr = mmr->mmr_nextp; 1817 kmem_free(mmr, sizeof (mac_margin_req_t)); 1818 } 1819 mip->mi_mmrp = NULL; 1820 1821 mip->mi_linkstate = LINK_STATE_UNKNOWN; 1822 kmem_free(mip->mi_info.mi_unicst_addr, mip->mi_type->mt_addr_length); 1823 mip->mi_info.mi_unicst_addr = NULL; 1824 1825 atomic_dec_32(&mip->mi_type->mt_ref); 1826 mip->mi_type = NULL; 1827 1828 if (mip->mi_minor > MAC_MAX_MINOR) 1829 mac_minor_rele(mip->mi_minor); 1830 1831 cmn_err(CE_NOTE, "!%s unregistered", mip->mi_name); 1832 1833 kmem_cache_free(i_mac_impl_cachep, mip); 1834 1835 return (0); 1836 } 1837 1838 /* 1839 * To avoid potential deadlocks, mac_rx() releases mi_rx_lock 1840 * before invoking its list of upcalls. This introduces races with 1841 * mac_rx_remove() and mac_rx_add(), who can potentially modify the 1842 * upcall list while mi_rx_lock is not being held. The race with 1843 * mac_rx_remove() is handled by incrementing mi_rx_ref upon entering 1844 * mac_rx(); a non-zero mi_rx_ref would tell mac_rx_remove() 1845 * to not modify the list but instead mark an upcall for deletion. 1846 * before mac_rx() exits, mi_rx_ref is decremented and if it 1847 * is 0, the marked upcalls will be removed from the list and freed. 1848 * The race with mac_rx_add() is harmless because mac_rx_add() only 1849 * prepends to the list and since mac_rx() saves the list head 1850 * before releasing mi_rx_lock, any prepended upcall won't be seen 1851 * until the next packet chain arrives. 1852 * 1853 * To minimize lock contention between multiple parallel invocations 1854 * of mac_rx(), mi_rx_lock is acquired as a READER lock. The 1855 * use of atomic operations ensures the sanity of mi_rx_ref. mi_rx_lock 1856 * will be upgraded to WRITER mode when there are marked upcalls to be 1857 * cleaned. 1858 */ 1859 static void 1860 mac_do_rx(mac_handle_t mh, mac_resource_handle_t mrh, mblk_t *mp_chain, 1861 boolean_t active_only) 1862 { 1863 mac_impl_t *mip = (mac_impl_t *)mh; 1864 mblk_t *bp = mp_chain; 1865 mac_rx_fn_t *mrfp; 1866 1867 /* 1868 * Call all registered receive functions. 1869 */ 1870 rw_enter(&mip->mi_rx_lock, RW_READER); 1871 if ((mrfp = mip->mi_mrfp) == NULL) { 1872 /* There are no registered receive functions. */ 1873 freemsgchain(bp); 1874 rw_exit(&mip->mi_rx_lock); 1875 return; 1876 } 1877 atomic_inc_32(&mip->mi_rx_ref); 1878 rw_exit(&mip->mi_rx_lock); 1879 1880 /* 1881 * Call registered receive functions. 1882 */ 1883 do { 1884 mblk_t *recv_bp; 1885 1886 if (active_only && !mrfp->mrf_active) { 1887 mrfp = mrfp->mrf_nextp; 1888 if (mrfp == NULL) { 1889 /* 1890 * We hit the last receiver, but it's not 1891 * active. 1892 */ 1893 freemsgchain(bp); 1894 } 1895 continue; 1896 } 1897 1898 recv_bp = (mrfp->mrf_nextp != NULL) ? copymsgchain(bp) : bp; 1899 if (recv_bp != NULL) { 1900 if (mrfp->mrf_inuse) { 1901 /* 1902 * Send bp itself and keep the copy. 1903 * If there's only one active receiver, 1904 * it should get the original message, 1905 * tagged with the hardware checksum flags. 1906 */ 1907 mrfp->mrf_fn(mrfp->mrf_arg, mrh, bp); 1908 bp = recv_bp; 1909 } else { 1910 freemsgchain(recv_bp); 1911 } 1912 } 1913 1914 mrfp = mrfp->mrf_nextp; 1915 } while (mrfp != NULL); 1916 1917 rw_enter(&mip->mi_rx_lock, RW_READER); 1918 if (atomic_dec_32_nv(&mip->mi_rx_ref) == 0 && mip->mi_rx_removed > 0) { 1919 mac_rx_fn_t **pp, *p; 1920 uint32_t cnt = 0; 1921 1922 DTRACE_PROBE1(delete_callbacks, mac_impl_t *, mip); 1923 1924 /* 1925 * Need to become exclusive before doing cleanup 1926 */ 1927 if (rw_tryupgrade(&mip->mi_rx_lock) == 0) { 1928 rw_exit(&mip->mi_rx_lock); 1929 rw_enter(&mip->mi_rx_lock, RW_WRITER); 1930 } 1931 1932 /* 1933 * We return if another thread has already entered and cleaned 1934 * up the list. 1935 */ 1936 if (mip->mi_rx_ref > 0 || mip->mi_rx_removed == 0) { 1937 rw_exit(&mip->mi_rx_lock); 1938 return; 1939 } 1940 1941 /* 1942 * Free removed callbacks. 1943 */ 1944 pp = &mip->mi_mrfp; 1945 while (*pp != NULL) { 1946 if (!(*pp)->mrf_inuse) { 1947 p = *pp; 1948 *pp = (*pp)->mrf_nextp; 1949 kmem_free(p, sizeof (*p)); 1950 cnt++; 1951 continue; 1952 } 1953 pp = &(*pp)->mrf_nextp; 1954 } 1955 1956 /* 1957 * Wake up mac_rx_remove_wait() 1958 */ 1959 mutex_enter(&mip->mi_lock); 1960 ASSERT(mip->mi_rx_removed == cnt); 1961 mip->mi_rx_removed = 0; 1962 cv_broadcast(&mip->mi_rx_cv); 1963 mutex_exit(&mip->mi_lock); 1964 } 1965 rw_exit(&mip->mi_rx_lock); 1966 } 1967 1968 void 1969 mac_rx(mac_handle_t mh, mac_resource_handle_t mrh, mblk_t *mp_chain) 1970 { 1971 mac_do_rx(mh, mrh, mp_chain, B_FALSE); 1972 } 1973 1974 /* 1975 * Send a packet chain up to the receive callbacks which declared 1976 * themselves as being active. 1977 */ 1978 void 1979 mac_active_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp_chain) 1980 { 1981 mac_do_rx(arg, mrh, mp_chain, B_TRUE); 1982 } 1983 1984 /* 1985 * Function passed to the active client sharing a VNIC. This function 1986 * is returned by mac_tx_get() when a VNIC is present. It invokes 1987 * the VNIC transmit entry point which was specified by the VNIC when 1988 * it called mac_vnic_set(). The VNIC transmit entry point will 1989 * pass the packets to the local VNICs and/or to the underlying VNICs 1990 * if needed. 1991 */ 1992 static mblk_t * 1993 mac_vnic_tx(void *arg, mblk_t *mp) 1994 { 1995 mac_impl_t *mip = arg; 1996 mac_txinfo_t *mtfp; 1997 mac_vnic_tx_t *mvt; 1998 1999 /* 2000 * There is a race between the notification of the VNIC 2001 * addition and removal, and the processing of the VNIC notification 2002 * by the MAC client. During this window, it is possible for 2003 * an active MAC client to contine invoking mac_vnic_tx() while 2004 * the VNIC has already been removed. So we cannot assume 2005 * that mi_vnic_present will always be true when mac_vnic_tx() 2006 * is invoked. 2007 */ 2008 rw_enter(&mip->mi_tx_lock, RW_READER); 2009 if (!mip->mi_vnic_present) { 2010 rw_exit(&mip->mi_tx_lock); 2011 freemsgchain(mp); 2012 return (NULL); 2013 } 2014 2015 ASSERT(mip->mi_vnic_tx != NULL); 2016 mvt = mip->mi_vnic_tx; 2017 MAC_VNIC_TXINFO_REFHOLD(mvt); 2018 rw_exit(&mip->mi_tx_lock); 2019 2020 mtfp = &mvt->mv_txinfo; 2021 mtfp->mt_fn(mtfp->mt_arg, mp); 2022 2023 MAC_VNIC_TXINFO_REFRELE(mvt); 2024 return (NULL); 2025 } 2026 2027 /* 2028 * Transmit function -- ONLY used when there are registered loopback listeners. 2029 */ 2030 mblk_t * 2031 mac_do_txloop(void *arg, mblk_t *bp, boolean_t call_vnic) 2032 { 2033 mac_impl_t *mip = arg; 2034 mac_txloop_fn_t *mtfp; 2035 mblk_t *loop_bp, *resid_bp, *next_bp; 2036 2037 if (call_vnic) { 2038 /* 2039 * In promiscous mode, a copy of the sent packet will 2040 * be sent to the client's promiscous receive entry 2041 * points via mac_vnic_tx()-> 2042 * mac_active_rx_promisc()->mac_rx_default(). 2043 */ 2044 return (mac_vnic_tx(arg, bp)); 2045 } 2046 2047 while (bp != NULL) { 2048 next_bp = bp->b_next; 2049 bp->b_next = NULL; 2050 2051 if ((loop_bp = copymsg(bp)) == NULL) 2052 goto noresources; 2053 2054 if ((resid_bp = mip->mi_tx(mip->mi_driver, bp)) != NULL) { 2055 ASSERT(resid_bp == bp); 2056 freemsg(loop_bp); 2057 goto noresources; 2058 } 2059 2060 rw_enter(&mip->mi_tx_lock, RW_READER); 2061 mtfp = mip->mi_mtfp; 2062 while (mtfp != NULL && loop_bp != NULL) { 2063 bp = loop_bp; 2064 2065 /* XXX counter bump if copymsg() fails? */ 2066 if (mtfp->mtf_nextp != NULL) 2067 loop_bp = copymsg(bp); 2068 else 2069 loop_bp = NULL; 2070 2071 mtfp->mtf_fn(mtfp->mtf_arg, bp); 2072 mtfp = mtfp->mtf_nextp; 2073 } 2074 rw_exit(&mip->mi_tx_lock); 2075 2076 /* 2077 * It's possible we've raced with the disabling of promiscuous 2078 * mode, in which case we can discard our copy. 2079 */ 2080 if (loop_bp != NULL) 2081 freemsg(loop_bp); 2082 2083 bp = next_bp; 2084 } 2085 2086 return (NULL); 2087 2088 noresources: 2089 bp->b_next = next_bp; 2090 return (bp); 2091 } 2092 2093 mblk_t * 2094 mac_txloop(void *arg, mblk_t *bp) 2095 { 2096 return (mac_do_txloop(arg, bp, B_FALSE)); 2097 } 2098 2099 static mblk_t * 2100 mac_vnic_txloop(void *arg, mblk_t *bp) 2101 { 2102 return (mac_do_txloop(arg, bp, B_TRUE)); 2103 } 2104 2105 void 2106 mac_link_update(mac_handle_t mh, link_state_t link) 2107 { 2108 mac_impl_t *mip = (mac_impl_t *)mh; 2109 2110 /* 2111 * Save the link state. 2112 */ 2113 mip->mi_linkstate = link; 2114 2115 /* 2116 * Send a MAC_NOTE_LINK notification. 2117 */ 2118 i_mac_notify(mip, MAC_NOTE_LINK); 2119 } 2120 2121 void 2122 mac_unicst_update(mac_handle_t mh, const uint8_t *addr) 2123 { 2124 mac_impl_t *mip = (mac_impl_t *)mh; 2125 2126 if (mip->mi_type->mt_addr_length == 0) 2127 return; 2128 2129 /* 2130 * If the address has not changed, do nothing. 2131 */ 2132 if (bcmp(addr, mip->mi_addr, mip->mi_type->mt_addr_length) == 0) 2133 return; 2134 2135 /* 2136 * Save the address. 2137 */ 2138 bcopy(addr, mip->mi_addr, mip->mi_type->mt_addr_length); 2139 2140 /* 2141 * Send a MAC_NOTE_UNICST notification. 2142 */ 2143 i_mac_notify(mip, MAC_NOTE_UNICST); 2144 } 2145 2146 void 2147 mac_tx_update(mac_handle_t mh) 2148 { 2149 /* 2150 * Send a MAC_NOTE_TX notification. 2151 */ 2152 i_mac_notify((mac_impl_t *)mh, MAC_NOTE_TX); 2153 } 2154 2155 void 2156 mac_resource_update(mac_handle_t mh) 2157 { 2158 /* 2159 * Send a MAC_NOTE_RESOURCE notification. 2160 */ 2161 i_mac_notify((mac_impl_t *)mh, MAC_NOTE_RESOURCE); 2162 } 2163 2164 mac_resource_handle_t 2165 mac_resource_add(mac_handle_t mh, mac_resource_t *mrp) 2166 { 2167 mac_impl_t *mip = (mac_impl_t *)mh; 2168 mac_resource_handle_t mrh; 2169 mac_resource_add_t add; 2170 void *arg; 2171 2172 rw_enter(&mip->mi_resource_lock, RW_READER); 2173 add = mip->mi_resource_add; 2174 arg = mip->mi_resource_add_arg; 2175 2176 if (add != NULL) 2177 mrh = add(arg, mrp); 2178 else 2179 mrh = NULL; 2180 rw_exit(&mip->mi_resource_lock); 2181 2182 return (mrh); 2183 } 2184 2185 int 2186 mac_pdata_update(mac_handle_t mh, void *mac_pdata, size_t dsize) 2187 { 2188 mac_impl_t *mip = (mac_impl_t *)mh; 2189 2190 /* 2191 * Verify that the plugin supports MAC plugin data and that the 2192 * supplied data is valid. 2193 */ 2194 if (!(mip->mi_type->mt_ops.mtops_ops & MTOPS_PDATA_VERIFY)) 2195 return (EINVAL); 2196 if (!mip->mi_type->mt_ops.mtops_pdata_verify(mac_pdata, dsize)) 2197 return (EINVAL); 2198 2199 if (mip->mi_pdata != NULL) 2200 kmem_free(mip->mi_pdata, mip->mi_pdata_size); 2201 2202 mip->mi_pdata = kmem_alloc(dsize, KM_SLEEP); 2203 bcopy(mac_pdata, mip->mi_pdata, dsize); 2204 mip->mi_pdata_size = dsize; 2205 2206 /* 2207 * Since the MAC plugin data is used to construct MAC headers that 2208 * were cached in fast-path headers, we need to flush fast-path 2209 * information for links associated with this mac. 2210 */ 2211 i_mac_notify(mip, MAC_NOTE_FASTPATH_FLUSH); 2212 return (0); 2213 } 2214 2215 void 2216 mac_multicst_refresh(mac_handle_t mh, mac_multicst_t refresh, void *arg, 2217 boolean_t add) 2218 { 2219 mac_impl_t *mip = (mac_impl_t *)mh; 2220 mac_multicst_addr_t *p; 2221 2222 /* 2223 * If no specific refresh function was given then default to the 2224 * driver's m_multicst entry point. 2225 */ 2226 if (refresh == NULL) { 2227 refresh = mip->mi_multicst; 2228 arg = mip->mi_driver; 2229 } 2230 ASSERT(refresh != NULL); 2231 2232 /* 2233 * Walk the multicast address list and call the refresh function for 2234 * each address. 2235 */ 2236 rw_enter(&(mip->mi_data_lock), RW_READER); 2237 for (p = mip->mi_mmap; p != NULL; p = p->mma_nextp) 2238 refresh(arg, add, p->mma_addr); 2239 rw_exit(&(mip->mi_data_lock)); 2240 } 2241 2242 void 2243 mac_unicst_refresh(mac_handle_t mh, mac_unicst_t refresh, void *arg) 2244 { 2245 mac_impl_t *mip = (mac_impl_t *)mh; 2246 /* 2247 * If no specific refresh function was given then default to the 2248 * driver's mi_unicst entry point. 2249 */ 2250 if (refresh == NULL) { 2251 refresh = mip->mi_unicst; 2252 arg = mip->mi_driver; 2253 } 2254 ASSERT(refresh != NULL); 2255 2256 /* 2257 * Call the refresh function with the current unicast address. 2258 */ 2259 refresh(arg, mip->mi_addr); 2260 } 2261 2262 void 2263 mac_promisc_refresh(mac_handle_t mh, mac_setpromisc_t refresh, void *arg) 2264 { 2265 mac_impl_t *mip = (mac_impl_t *)mh; 2266 2267 /* 2268 * If no specific refresh function was given then default to the 2269 * driver's m_promisc entry point. 2270 */ 2271 if (refresh == NULL) { 2272 refresh = mip->mi_setpromisc; 2273 arg = mip->mi_driver; 2274 } 2275 ASSERT(refresh != NULL); 2276 2277 /* 2278 * Call the refresh function with the current promiscuity. 2279 */ 2280 refresh(arg, (mip->mi_devpromisc != 0)); 2281 } 2282 2283 /* 2284 * The mac client requests that the mac not to change its margin size to 2285 * be less than the specified value. If "current" is B_TRUE, then the client 2286 * requests the mac not to change its margin size to be smaller than the 2287 * current size. Further, return the current margin size value in this case. 2288 * 2289 * We keep every requested size in an ordered list from largest to smallest. 2290 */ 2291 int 2292 mac_margin_add(mac_handle_t mh, uint32_t *marginp, boolean_t current) 2293 { 2294 mac_impl_t *mip = (mac_impl_t *)mh; 2295 mac_margin_req_t **pp, *p; 2296 int err = 0; 2297 2298 rw_enter(&(mip->mi_data_lock), RW_WRITER); 2299 if (current) 2300 *marginp = mip->mi_margin; 2301 2302 /* 2303 * If the current margin value cannot satisfy the margin requested, 2304 * return ENOTSUP directly. 2305 */ 2306 if (*marginp > mip->mi_margin) { 2307 err = ENOTSUP; 2308 goto done; 2309 } 2310 2311 /* 2312 * Check whether the given margin is already in the list. If so, 2313 * bump the reference count. 2314 */ 2315 for (pp = &(mip->mi_mmrp); (p = *pp) != NULL; pp = &(p->mmr_nextp)) { 2316 if (p->mmr_margin == *marginp) { 2317 /* 2318 * The margin requested is already in the list, 2319 * so just bump the reference count. 2320 */ 2321 p->mmr_ref++; 2322 goto done; 2323 } 2324 if (p->mmr_margin < *marginp) 2325 break; 2326 } 2327 2328 2329 if ((p = kmem_zalloc(sizeof (mac_margin_req_t), KM_NOSLEEP)) == NULL) { 2330 err = ENOMEM; 2331 goto done; 2332 } 2333 2334 p->mmr_margin = *marginp; 2335 p->mmr_ref++; 2336 p->mmr_nextp = *pp; 2337 *pp = p; 2338 2339 done: 2340 rw_exit(&(mip->mi_data_lock)); 2341 return (err); 2342 } 2343 2344 /* 2345 * The mac client requests to cancel its previous mac_margin_add() request. 2346 * We remove the requested margin size from the list. 2347 */ 2348 int 2349 mac_margin_remove(mac_handle_t mh, uint32_t margin) 2350 { 2351 mac_impl_t *mip = (mac_impl_t *)mh; 2352 mac_margin_req_t **pp, *p; 2353 int err = 0; 2354 2355 rw_enter(&(mip->mi_data_lock), RW_WRITER); 2356 /* 2357 * Find the entry in the list for the given margin. 2358 */ 2359 for (pp = &(mip->mi_mmrp); (p = *pp) != NULL; pp = &(p->mmr_nextp)) { 2360 if (p->mmr_margin == margin) { 2361 if (--p->mmr_ref == 0) 2362 break; 2363 2364 /* 2365 * There is still a reference to this address so 2366 * there's nothing more to do. 2367 */ 2368 goto done; 2369 } 2370 } 2371 2372 /* 2373 * We did not find an entry for the given margin. 2374 */ 2375 if (p == NULL) { 2376 err = ENOENT; 2377 goto done; 2378 } 2379 2380 ASSERT(p->mmr_ref == 0); 2381 2382 /* 2383 * Remove it from the list. 2384 */ 2385 *pp = p->mmr_nextp; 2386 kmem_free(p, sizeof (mac_margin_req_t)); 2387 done: 2388 rw_exit(&(mip->mi_data_lock)); 2389 return (err); 2390 } 2391 2392 /* 2393 * The mac client requests to get the mac's current margin value. 2394 */ 2395 void 2396 mac_margin_get(mac_handle_t mh, uint32_t *marginp) 2397 { 2398 mac_impl_t *mip = (mac_impl_t *)mh; 2399 2400 rw_enter(&(mip->mi_data_lock), RW_READER); 2401 *marginp = mip->mi_margin; 2402 rw_exit(&(mip->mi_data_lock)); 2403 } 2404 2405 boolean_t 2406 mac_margin_update(mac_handle_t mh, uint32_t margin) 2407 { 2408 mac_impl_t *mip = (mac_impl_t *)mh; 2409 uint32_t margin_needed = 0; 2410 2411 rw_enter(&(mip->mi_data_lock), RW_WRITER); 2412 2413 if (mip->mi_mmrp != NULL) 2414 margin_needed = mip->mi_mmrp->mmr_margin; 2415 2416 if (margin_needed <= margin) 2417 mip->mi_margin = margin; 2418 2419 rw_exit(&(mip->mi_data_lock)); 2420 2421 if (margin_needed <= margin) 2422 i_mac_notify(mip, MAC_NOTE_MARGIN); 2423 2424 return (margin_needed <= margin); 2425 } 2426 2427 boolean_t 2428 mac_do_active_set(mac_handle_t mh, boolean_t shareable) 2429 { 2430 mac_impl_t *mip = (mac_impl_t *)mh; 2431 2432 mutex_enter(&mip->mi_activelink_lock); 2433 if (mip->mi_activelink) { 2434 mutex_exit(&mip->mi_activelink_lock); 2435 return (B_FALSE); 2436 } 2437 mip->mi_activelink = B_TRUE; 2438 mip->mi_shareable = shareable; 2439 mutex_exit(&mip->mi_activelink_lock); 2440 return (B_TRUE); 2441 } 2442 2443 /* 2444 * Called by MAC clients. By default, active MAC clients cannot 2445 * share the NIC with VNICs. 2446 */ 2447 boolean_t 2448 mac_active_set(mac_handle_t mh) 2449 { 2450 return (mac_do_active_set(mh, B_FALSE)); 2451 } 2452 2453 /* 2454 * Called by MAC clients which can share the NIC with VNICS, e.g. DLS. 2455 */ 2456 boolean_t 2457 mac_active_shareable_set(mac_handle_t mh) 2458 { 2459 return (mac_do_active_set(mh, B_TRUE)); 2460 } 2461 2462 void 2463 mac_active_clear(mac_handle_t mh) 2464 { 2465 mac_impl_t *mip = (mac_impl_t *)mh; 2466 2467 mutex_enter(&mip->mi_activelink_lock); 2468 ASSERT(mip->mi_activelink); 2469 mip->mi_activelink = B_FALSE; 2470 mutex_exit(&mip->mi_activelink_lock); 2471 } 2472 2473 boolean_t 2474 mac_vnic_set(mac_handle_t mh, mac_txinfo_t *tx_info, mac_getcapab_t getcapab_fn, 2475 void *getcapab_arg) 2476 { 2477 mac_impl_t *mip = (mac_impl_t *)mh; 2478 mac_vnic_tx_t *vnic_tx; 2479 2480 mutex_enter(&mip->mi_activelink_lock); 2481 rw_enter(&mip->mi_tx_lock, RW_WRITER); 2482 ASSERT(!mip->mi_vnic_present); 2483 2484 if (mip->mi_activelink && !mip->mi_shareable) { 2485 /* 2486 * The NIC is already used by an active client which cannot 2487 * share it with VNICs. 2488 */ 2489 rw_exit(&mip->mi_tx_lock); 2490 mutex_exit(&mip->mi_activelink_lock); 2491 return (B_FALSE); 2492 } 2493 2494 vnic_tx = kmem_cache_alloc(mac_vnic_tx_cache, KM_SLEEP); 2495 vnic_tx->mv_refs = 0; 2496 vnic_tx->mv_txinfo = *tx_info; 2497 vnic_tx->mv_clearing = B_FALSE; 2498 2499 mip->mi_vnic_present = B_TRUE; 2500 mip->mi_vnic_tx = vnic_tx; 2501 mip->mi_vnic_getcapab_fn = getcapab_fn; 2502 mip->mi_vnic_getcapab_arg = getcapab_arg; 2503 rw_exit(&mip->mi_tx_lock); 2504 mutex_exit(&mip->mi_activelink_lock); 2505 2506 i_mac_notify(mip, MAC_NOTE_VNIC); 2507 return (B_TRUE); 2508 } 2509 2510 void 2511 mac_vnic_clear(mac_handle_t mh) 2512 { 2513 mac_impl_t *mip = (mac_impl_t *)mh; 2514 mac_vnic_tx_t *vnic_tx; 2515 2516 rw_enter(&mip->mi_tx_lock, RW_WRITER); 2517 ASSERT(mip->mi_vnic_present); 2518 mip->mi_vnic_present = B_FALSE; 2519 /* 2520 * Setting mi_vnic_tx to NULL here under the lock guarantees 2521 * that no new references to the current VNIC transmit structure 2522 * will be taken by mac_vnic_tx(). This is a necessary condition 2523 * for safely waiting for the reference count to drop to 2524 * zero below. 2525 */ 2526 vnic_tx = mip->mi_vnic_tx; 2527 mip->mi_vnic_tx = NULL; 2528 mip->mi_vnic_getcapab_fn = NULL; 2529 mip->mi_vnic_getcapab_arg = NULL; 2530 rw_exit(&mip->mi_tx_lock); 2531 2532 i_mac_notify(mip, MAC_NOTE_VNIC); 2533 2534 /* 2535 * Wait for all TX calls referencing the VNIC transmit 2536 * entry point that was removed to complete. 2537 */ 2538 mutex_enter(&vnic_tx->mv_lock); 2539 vnic_tx->mv_clearing = B_TRUE; 2540 while (vnic_tx->mv_refs > 0) 2541 cv_wait(&vnic_tx->mv_cv, &vnic_tx->mv_lock); 2542 mutex_exit(&vnic_tx->mv_lock); 2543 kmem_cache_free(mac_vnic_tx_cache, vnic_tx); 2544 } 2545 2546 /* 2547 * mac_info_get() is used for retrieving the mac_info when a DL_INFO_REQ is 2548 * issued before a DL_ATTACH_REQ. we walk the i_mac_impl_hash table and find 2549 * the first mac_impl_t with a matching driver name; then we copy its mac_info_t 2550 * to the caller. we do all this with i_mac_impl_lock held so the mac_impl_t 2551 * cannot disappear while we are accessing it. 2552 */ 2553 typedef struct i_mac_info_state_s { 2554 const char *mi_name; 2555 mac_info_t *mi_infop; 2556 } i_mac_info_state_t; 2557 2558 /*ARGSUSED*/ 2559 static uint_t 2560 i_mac_info_walker(mod_hash_key_t key, mod_hash_val_t *val, void *arg) 2561 { 2562 i_mac_info_state_t *statep = arg; 2563 mac_impl_t *mip = (mac_impl_t *)val; 2564 2565 if (mip->mi_disabled) 2566 return (MH_WALK_CONTINUE); 2567 2568 if (strcmp(statep->mi_name, 2569 ddi_driver_name(mip->mi_dip)) != 0) 2570 return (MH_WALK_CONTINUE); 2571 2572 statep->mi_infop = &mip->mi_info; 2573 return (MH_WALK_TERMINATE); 2574 } 2575 2576 boolean_t 2577 mac_info_get(const char *name, mac_info_t *minfop) 2578 { 2579 i_mac_info_state_t state; 2580 2581 rw_enter(&i_mac_impl_lock, RW_READER); 2582 state.mi_name = name; 2583 state.mi_infop = NULL; 2584 mod_hash_walk(i_mac_impl_hash, i_mac_info_walker, &state); 2585 if (state.mi_infop == NULL) { 2586 rw_exit(&i_mac_impl_lock); 2587 return (B_FALSE); 2588 } 2589 *minfop = *state.mi_infop; 2590 rw_exit(&i_mac_impl_lock); 2591 return (B_TRUE); 2592 } 2593 2594 boolean_t 2595 mac_do_capab_get(mac_handle_t mh, mac_capab_t cap, void *cap_data, 2596 boolean_t is_vnic) 2597 { 2598 mac_impl_t *mip = (mac_impl_t *)mh; 2599 2600 if (!is_vnic) { 2601 rw_enter(&mip->mi_tx_lock, RW_READER); 2602 if (mip->mi_vnic_present) { 2603 boolean_t rv; 2604 2605 rv = mip->mi_vnic_getcapab_fn(mip->mi_vnic_getcapab_arg, 2606 cap, cap_data); 2607 rw_exit(&mip->mi_tx_lock); 2608 return (rv); 2609 } 2610 rw_exit(&mip->mi_tx_lock); 2611 } 2612 2613 if (mip->mi_callbacks->mc_callbacks & MC_GETCAPAB) 2614 return (mip->mi_getcapab(mip->mi_driver, cap, cap_data)); 2615 else 2616 return (B_FALSE); 2617 } 2618 2619 boolean_t 2620 mac_capab_get(mac_handle_t mh, mac_capab_t cap, void *cap_data) 2621 { 2622 return (mac_do_capab_get(mh, cap, cap_data, B_FALSE)); 2623 } 2624 2625 boolean_t 2626 mac_vnic_capab_get(mac_handle_t mh, mac_capab_t cap, void *cap_data) 2627 { 2628 return (mac_do_capab_get(mh, cap, cap_data, B_TRUE)); 2629 } 2630 2631 boolean_t 2632 mac_sap_verify(mac_handle_t mh, uint32_t sap, uint32_t *bind_sap) 2633 { 2634 mac_impl_t *mip = (mac_impl_t *)mh; 2635 return (mip->mi_type->mt_ops.mtops_sap_verify(sap, bind_sap, 2636 mip->mi_pdata)); 2637 } 2638 2639 mblk_t * 2640 mac_header(mac_handle_t mh, const uint8_t *daddr, uint32_t sap, mblk_t *payload, 2641 size_t extra_len) 2642 { 2643 mac_impl_t *mip = (mac_impl_t *)mh; 2644 return (mip->mi_type->mt_ops.mtops_header(mip->mi_addr, daddr, sap, 2645 mip->mi_pdata, payload, extra_len)); 2646 } 2647 2648 int 2649 mac_header_info(mac_handle_t mh, mblk_t *mp, mac_header_info_t *mhip) 2650 { 2651 mac_impl_t *mip = (mac_impl_t *)mh; 2652 return (mip->mi_type->mt_ops.mtops_header_info(mp, mip->mi_pdata, 2653 mhip)); 2654 } 2655 2656 mblk_t * 2657 mac_header_cook(mac_handle_t mh, mblk_t *mp) 2658 { 2659 mac_impl_t *mip = (mac_impl_t *)mh; 2660 if (mip->mi_type->mt_ops.mtops_ops & MTOPS_HEADER_COOK) { 2661 if (DB_REF(mp) > 1) { 2662 mblk_t *newmp = copymsg(mp); 2663 if (newmp == NULL) 2664 return (NULL); 2665 freemsg(mp); 2666 mp = newmp; 2667 } 2668 return (mip->mi_type->mt_ops.mtops_header_cook(mp, 2669 mip->mi_pdata)); 2670 } 2671 return (mp); 2672 } 2673 2674 mblk_t * 2675 mac_header_uncook(mac_handle_t mh, mblk_t *mp) 2676 { 2677 mac_impl_t *mip = (mac_impl_t *)mh; 2678 if (mip->mi_type->mt_ops.mtops_ops & MTOPS_HEADER_UNCOOK) { 2679 if (DB_REF(mp) > 1) { 2680 mblk_t *newmp = copymsg(mp); 2681 if (newmp == NULL) 2682 return (NULL); 2683 freemsg(mp); 2684 mp = newmp; 2685 } 2686 return (mip->mi_type->mt_ops.mtops_header_uncook(mp, 2687 mip->mi_pdata)); 2688 } 2689 return (mp); 2690 } 2691 2692 void 2693 mac_init_ops(struct dev_ops *ops, const char *name) 2694 { 2695 dld_init_ops(ops, name); 2696 } 2697 2698 void 2699 mac_fini_ops(struct dev_ops *ops) 2700 { 2701 dld_fini_ops(ops); 2702 } 2703 2704 /* 2705 * MAC Type Plugin functions. 2706 */ 2707 2708 mactype_register_t * 2709 mactype_alloc(uint_t mactype_version) 2710 { 2711 mactype_register_t *mtrp; 2712 2713 /* 2714 * Make sure there isn't a version mismatch between the plugin and 2715 * the framework. In the future, if multiple versions are 2716 * supported, this check could become more sophisticated. 2717 */ 2718 if (mactype_version != MACTYPE_VERSION) 2719 return (NULL); 2720 2721 mtrp = kmem_zalloc(sizeof (mactype_register_t), KM_SLEEP); 2722 mtrp->mtr_version = mactype_version; 2723 return (mtrp); 2724 } 2725 2726 void 2727 mactype_free(mactype_register_t *mtrp) 2728 { 2729 kmem_free(mtrp, sizeof (mactype_register_t)); 2730 } 2731 2732 int 2733 mactype_register(mactype_register_t *mtrp) 2734 { 2735 mactype_t *mtp; 2736 mactype_ops_t *ops = mtrp->mtr_ops; 2737 2738 /* Do some sanity checking before we register this MAC type. */ 2739 if (mtrp->mtr_ident == NULL || ops == NULL || mtrp->mtr_addrlen == 0) 2740 return (EINVAL); 2741 2742 /* 2743 * Verify that all mandatory callbacks are set in the ops 2744 * vector. 2745 */ 2746 if (ops->mtops_unicst_verify == NULL || 2747 ops->mtops_multicst_verify == NULL || 2748 ops->mtops_sap_verify == NULL || 2749 ops->mtops_header == NULL || 2750 ops->mtops_header_info == NULL) { 2751 return (EINVAL); 2752 } 2753 2754 mtp = kmem_zalloc(sizeof (*mtp), KM_SLEEP); 2755 mtp->mt_ident = mtrp->mtr_ident; 2756 mtp->mt_ops = *ops; 2757 mtp->mt_type = mtrp->mtr_mactype; 2758 mtp->mt_nativetype = mtrp->mtr_nativetype; 2759 mtp->mt_addr_length = mtrp->mtr_addrlen; 2760 if (mtrp->mtr_brdcst_addr != NULL) { 2761 mtp->mt_brdcst_addr = kmem_alloc(mtrp->mtr_addrlen, KM_SLEEP); 2762 bcopy(mtrp->mtr_brdcst_addr, mtp->mt_brdcst_addr, 2763 mtrp->mtr_addrlen); 2764 } 2765 2766 mtp->mt_stats = mtrp->mtr_stats; 2767 mtp->mt_statcount = mtrp->mtr_statcount; 2768 2769 if (mod_hash_insert(i_mactype_hash, 2770 (mod_hash_key_t)mtp->mt_ident, (mod_hash_val_t)mtp) != 0) { 2771 kmem_free(mtp->mt_brdcst_addr, mtp->mt_addr_length); 2772 kmem_free(mtp, sizeof (*mtp)); 2773 return (EEXIST); 2774 } 2775 return (0); 2776 } 2777 2778 int 2779 mactype_unregister(const char *ident) 2780 { 2781 mactype_t *mtp; 2782 mod_hash_val_t val; 2783 int err; 2784 2785 /* 2786 * Let's not allow MAC drivers to use this plugin while we're 2787 * trying to unregister it. Holding i_mactype_lock also prevents a 2788 * plugin from unregistering while a MAC driver is attempting to 2789 * hold a reference to it in i_mactype_getplugin(). 2790 */ 2791 mutex_enter(&i_mactype_lock); 2792 2793 if ((err = mod_hash_find(i_mactype_hash, (mod_hash_key_t)ident, 2794 (mod_hash_val_t *)&mtp)) != 0) { 2795 /* A plugin is trying to unregister, but it never registered. */ 2796 err = ENXIO; 2797 goto done; 2798 } 2799 2800 if (mtp->mt_ref != 0) { 2801 err = EBUSY; 2802 goto done; 2803 } 2804 2805 err = mod_hash_remove(i_mactype_hash, (mod_hash_key_t)ident, &val); 2806 ASSERT(err == 0); 2807 if (err != 0) { 2808 /* This should never happen, thus the ASSERT() above. */ 2809 err = EINVAL; 2810 goto done; 2811 } 2812 ASSERT(mtp == (mactype_t *)val); 2813 2814 kmem_free(mtp->mt_brdcst_addr, mtp->mt_addr_length); 2815 kmem_free(mtp, sizeof (mactype_t)); 2816 done: 2817 mutex_exit(&i_mactype_lock); 2818 return (err); 2819 } 2820