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