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