1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * - General Introduction: 29 * 30 * This file contains the implementation of the MAC client kernel 31 * API and related code. The MAC client API allows a kernel module 32 * to gain access to a MAC instance (physical NIC, link aggregation, etc). 33 * It allows a MAC client to associate itself with a MAC address, 34 * VLANs, callback functions for data traffic and for promiscuous mode. 35 * The MAC client API is also used to specify the properties associated 36 * with a MAC client, such as bandwidth limits, priority, CPUS, etc. 37 * These properties are further used to determine the hardware resources 38 * to allocate to the various MAC clients. 39 * 40 * - Primary MAC clients: 41 * 42 * The MAC client API refers to "primary MAC clients". A primary MAC 43 * client is a client which "owns" the primary MAC address of 44 * the underlying MAC instance. The primary MAC address is called out 45 * since it is associated with specific semantics: the primary MAC 46 * address is the MAC address which is assigned to the IP interface 47 * when it is plumbed, and the primary MAC address is assigned 48 * to VLAN data-links. The primary address of a MAC instance can 49 * also change dynamically from under the MAC client, for example 50 * as a result of a change of state of a link aggregation. In that 51 * case the MAC layer automatically updates all data-structures which 52 * refer to the current value of the primary MAC address. Typical 53 * primary MAC clients are dls, aggr, and xnb. A typical non-primary 54 * MAC client is the vnic driver. 55 * 56 * - Virtual Switching: 57 * 58 * The MAC layer implements a virtual switch between the MAC clients 59 * (primary and non-primary) defined on top of the same underlying 60 * NIC (physical, link aggregation, etc). The virtual switch is 61 * VLAN-aware, i.e. it allows multiple MAC clients to be member 62 * of one or more VLANs, and the virtual switch will distribute 63 * multicast tagged packets only to the member of the corresponding 64 * VLANs. 65 * 66 * - Upper vs Lower MAC: 67 * 68 * Creating a VNIC on top of a MAC instance effectively causes 69 * two MAC instances to be layered on top of each other, one for 70 * the VNIC(s), one for the underlying MAC instance (physical NIC, 71 * link aggregation, etc). In the code below we refer to the 72 * underlying NIC as the "lower MAC", and we refer to VNICs as 73 * the "upper MAC". 74 * 75 * - Pass-through for VNICs: 76 * 77 * When VNICs are created on top of an underlying MAC, this causes 78 * a layering of two MAC instances. Since the lower MAC already 79 * does the switching and demultiplexing to its MAC clients, the 80 * upper MAC would simply have to pass packets to the layer below 81 * or above it, which would introduce overhead. In order to avoid 82 * this overhead, the MAC layer implements a pass-through mechanism 83 * for VNICs. When a VNIC opens the lower MAC instance, it saves 84 * the MAC client handle it optains from the MAC layer. When a MAC 85 * client opens a VNIC (upper MAC), the MAC layer detects that 86 * the MAC being opened is a VNIC, and gets the MAC client handle 87 * that the VNIC driver obtained from the lower MAC. This exchange 88 * is doing through a private capability between the MAC layer 89 * and the VNIC driver. The upper MAC then returns that handle 90 * directly to its MAC client. Any operation done by the upper 91 * MAC client is now done on the lower MAC client handle, which 92 * allows the VNIC driver to be completely bypassed for the 93 * performance sensitive data-path. 94 * 95 */ 96 97 #include <sys/types.h> 98 #include <sys/conf.h> 99 #include <sys/id_space.h> 100 #include <sys/esunddi.h> 101 #include <sys/stat.h> 102 #include <sys/mkdev.h> 103 #include <sys/stream.h> 104 #include <sys/strsun.h> 105 #include <sys/strsubr.h> 106 #include <sys/dlpi.h> 107 #include <sys/modhash.h> 108 #include <sys/mac_impl.h> 109 #include <sys/mac_client_impl.h> 110 #include <sys/mac_soft_ring.h> 111 #include <sys/dls.h> 112 #include <sys/dld.h> 113 #include <sys/modctl.h> 114 #include <sys/fs/dv_node.h> 115 #include <sys/thread.h> 116 #include <sys/proc.h> 117 #include <sys/callb.h> 118 #include <sys/cpuvar.h> 119 #include <sys/atomic.h> 120 #include <sys/sdt.h> 121 #include <sys/mac_flow.h> 122 #include <sys/ddi_intr_impl.h> 123 #include <sys/disp.h> 124 #include <sys/sdt.h> 125 #include <sys/vnic.h> 126 #include <sys/vnic_impl.h> 127 #include <sys/vlan.h> 128 #include <inet/ip.h> 129 #include <inet/ip6.h> 130 #include <sys/exacct.h> 131 #include <sys/exacct_impl.h> 132 #include <inet/nd.h> 133 #include <sys/ethernet.h> 134 135 kmem_cache_t *mac_client_impl_cache; 136 kmem_cache_t *mac_promisc_impl_cache; 137 138 static boolean_t mac_client_single_rcvr(mac_client_impl_t *); 139 static flow_entry_t *mac_client_swap_mciflent(mac_client_impl_t *); 140 static flow_entry_t *mac_client_get_flow(mac_client_impl_t *, 141 mac_unicast_impl_t *); 142 static void mac_client_remove_flow_from_list(mac_client_impl_t *, 143 flow_entry_t *); 144 static void mac_client_add_to_flow_list(mac_client_impl_t *, flow_entry_t *); 145 static void mac_rename_flow_names(mac_client_impl_t *, const char *); 146 static void mac_virtual_link_update(mac_impl_t *); 147 148 /* ARGSUSED */ 149 static int 150 i_mac_client_impl_ctor(void *buf, void *arg, int kmflag) 151 { 152 int i; 153 mac_client_impl_t *mcip = buf; 154 155 bzero(buf, MAC_CLIENT_IMPL_SIZE); 156 mutex_init(&mcip->mci_tx_cb_lock, NULL, MUTEX_DRIVER, NULL); 157 mcip->mci_tx_notify_cb_info.mcbi_lockp = &mcip->mci_tx_cb_lock; 158 159 ASSERT(mac_tx_percpu_cnt >= 0); 160 for (i = 0; i <= mac_tx_percpu_cnt; i++) { 161 mutex_init(&mcip->mci_tx_pcpu[i].pcpu_tx_lock, NULL, 162 MUTEX_DRIVER, NULL); 163 } 164 cv_init(&mcip->mci_tx_cv, NULL, CV_DRIVER, NULL); 165 166 return (0); 167 } 168 169 /* ARGSUSED */ 170 static void 171 i_mac_client_impl_dtor(void *buf, void *arg) 172 { 173 int i; 174 mac_client_impl_t *mcip = buf; 175 176 ASSERT(mcip->mci_promisc_list == NULL); 177 ASSERT(mcip->mci_unicast_list == NULL); 178 ASSERT(mcip->mci_state_flags == 0); 179 ASSERT(mcip->mci_tx_flag == 0); 180 181 mutex_destroy(&mcip->mci_tx_cb_lock); 182 183 ASSERT(mac_tx_percpu_cnt >= 0); 184 for (i = 0; i <= mac_tx_percpu_cnt; i++) { 185 ASSERT(mcip->mci_tx_pcpu[i].pcpu_tx_refcnt == 0); 186 mutex_destroy(&mcip->mci_tx_pcpu[i].pcpu_tx_lock); 187 } 188 cv_destroy(&mcip->mci_tx_cv); 189 } 190 191 /* ARGSUSED */ 192 static int 193 i_mac_promisc_impl_ctor(void *buf, void *arg, int kmflag) 194 { 195 mac_promisc_impl_t *mpip = buf; 196 197 bzero(buf, sizeof (mac_promisc_impl_t)); 198 mpip->mpi_mci_link.mcb_objp = buf; 199 mpip->mpi_mci_link.mcb_objsize = sizeof (mac_promisc_impl_t); 200 mpip->mpi_mi_link.mcb_objp = buf; 201 mpip->mpi_mi_link.mcb_objsize = sizeof (mac_promisc_impl_t); 202 return (0); 203 } 204 205 /* ARGSUSED */ 206 static void 207 i_mac_promisc_impl_dtor(void *buf, void *arg) 208 { 209 mac_promisc_impl_t *mpip = buf; 210 211 ASSERT(mpip->mpi_mci_link.mcb_objp != NULL); 212 ASSERT(mpip->mpi_mci_link.mcb_objsize == sizeof (mac_promisc_impl_t)); 213 ASSERT(mpip->mpi_mi_link.mcb_objp == mpip->mpi_mci_link.mcb_objp); 214 ASSERT(mpip->mpi_mi_link.mcb_objsize == sizeof (mac_promisc_impl_t)); 215 216 mpip->mpi_mci_link.mcb_objp = NULL; 217 mpip->mpi_mci_link.mcb_objsize = 0; 218 mpip->mpi_mi_link.mcb_objp = NULL; 219 mpip->mpi_mi_link.mcb_objsize = 0; 220 221 ASSERT(mpip->mpi_mci_link.mcb_flags == 0); 222 mpip->mpi_mci_link.mcb_objsize = 0; 223 } 224 225 void 226 mac_client_init(void) 227 { 228 ASSERT(mac_tx_percpu_cnt >= 0); 229 230 mac_client_impl_cache = kmem_cache_create("mac_client_impl_cache", 231 MAC_CLIENT_IMPL_SIZE, 0, i_mac_client_impl_ctor, 232 i_mac_client_impl_dtor, NULL, NULL, NULL, 0); 233 ASSERT(mac_client_impl_cache != NULL); 234 235 mac_promisc_impl_cache = kmem_cache_create("mac_promisc_impl_cache", 236 sizeof (mac_promisc_impl_t), 0, i_mac_promisc_impl_ctor, 237 i_mac_promisc_impl_dtor, NULL, NULL, NULL, 0); 238 ASSERT(mac_promisc_impl_cache != NULL); 239 } 240 241 void 242 mac_client_fini(void) 243 { 244 kmem_cache_destroy(mac_client_impl_cache); 245 kmem_cache_destroy(mac_promisc_impl_cache); 246 } 247 248 /* 249 * Return the lower MAC client handle from the VNIC driver for the 250 * specified VNIC MAC instance. 251 */ 252 mac_client_impl_t * 253 mac_vnic_lower(mac_impl_t *mip) 254 { 255 mac_capab_vnic_t cap; 256 mac_client_impl_t *mcip; 257 258 VERIFY(i_mac_capab_get((mac_handle_t)mip, MAC_CAPAB_VNIC, &cap)); 259 mcip = cap.mcv_mac_client_handle(cap.mcv_arg); 260 261 return (mcip); 262 } 263 264 /* 265 * Return the MAC client handle of the primary MAC client for the 266 * specified MAC instance, or NULL otherwise. 267 */ 268 mac_client_impl_t * 269 mac_primary_client_handle(mac_impl_t *mip) 270 { 271 mac_client_impl_t *mcip; 272 273 if (mip->mi_state_flags & MIS_IS_VNIC) 274 return (mac_vnic_lower(mip)); 275 276 ASSERT(MAC_PERIM_HELD((mac_handle_t)mip)); 277 278 for (mcip = mip->mi_clients_list; mcip != NULL; 279 mcip = mcip->mci_client_next) { 280 if (MCIP_DATAPATH_SETUP(mcip) && mac_is_primary_client(mcip)) 281 return (mcip); 282 } 283 return (NULL); 284 } 285 286 /* 287 * Open a MAC specified by its MAC name. 288 */ 289 int 290 mac_open(const char *macname, mac_handle_t *mhp) 291 { 292 mac_impl_t *mip; 293 int err; 294 295 /* 296 * Look up its entry in the global hash table. 297 */ 298 if ((err = mac_hold(macname, &mip)) != 0) 299 return (err); 300 301 /* 302 * Hold the dip associated to the MAC to prevent it from being 303 * detached. For a softmac, its underlying dip is held by the 304 * mi_open() callback. 305 * 306 * This is done to be more tolerant with some defective drivers, 307 * which incorrectly handle mac_unregister() failure in their 308 * xxx_detach() routine. For example, some drivers ignore the 309 * failure of mac_unregister() and free all resources that 310 * that are needed for data transmition. 311 */ 312 e_ddi_hold_devi(mip->mi_dip); 313 314 if (!(mip->mi_callbacks->mc_callbacks & MC_OPEN)) { 315 *mhp = (mac_handle_t)mip; 316 return (0); 317 } 318 319 /* 320 * The mac perimeter is used in both mac_open and mac_close by the 321 * framework to single thread the MC_OPEN/MC_CLOSE of drivers. 322 */ 323 i_mac_perim_enter(mip); 324 mip->mi_oref++; 325 if (mip->mi_oref != 1 || ((err = mip->mi_open(mip->mi_driver)) == 0)) { 326 *mhp = (mac_handle_t)mip; 327 i_mac_perim_exit(mip); 328 return (0); 329 } 330 mip->mi_oref--; 331 ddi_release_devi(mip->mi_dip); 332 mac_rele(mip); 333 i_mac_perim_exit(mip); 334 return (err); 335 } 336 337 /* 338 * Open a MAC specified by its linkid. 339 */ 340 int 341 mac_open_by_linkid(datalink_id_t linkid, mac_handle_t *mhp) 342 { 343 dls_dl_handle_t dlh; 344 int err; 345 346 if ((err = dls_devnet_hold_tmp(linkid, &dlh)) != 0) 347 return (err); 348 349 dls_devnet_prop_task_wait(dlh); 350 351 err = mac_open(dls_devnet_mac(dlh), mhp); 352 353 dls_devnet_rele_tmp(dlh); 354 return (err); 355 } 356 357 /* 358 * Open a MAC specified by its link name. 359 */ 360 int 361 mac_open_by_linkname(const char *link, mac_handle_t *mhp) 362 { 363 datalink_id_t linkid; 364 int err; 365 366 if ((err = dls_mgmt_get_linkid(link, &linkid)) != 0) 367 return (err); 368 return (mac_open_by_linkid(linkid, mhp)); 369 } 370 371 /* 372 * Close the specified MAC. 373 */ 374 void 375 mac_close(mac_handle_t mh) 376 { 377 mac_impl_t *mip = (mac_impl_t *)mh; 378 379 i_mac_perim_enter(mip); 380 /* 381 * The mac perimeter is used in both mac_open and mac_close by the 382 * framework to single thread the MC_OPEN/MC_CLOSE of drivers. 383 */ 384 if (mip->mi_callbacks->mc_callbacks & MC_OPEN) { 385 ASSERT(mip->mi_oref != 0); 386 if (--mip->mi_oref == 0) { 387 if ((mip->mi_callbacks->mc_callbacks & MC_CLOSE)) 388 mip->mi_close(mip->mi_driver); 389 } 390 } 391 i_mac_perim_exit(mip); 392 ddi_release_devi(mip->mi_dip); 393 mac_rele(mip); 394 } 395 396 /* 397 * Misc utility functions to retrieve various information about a MAC 398 * instance or a MAC client. 399 */ 400 401 const mac_info_t * 402 mac_info(mac_handle_t mh) 403 { 404 return (&((mac_impl_t *)mh)->mi_info); 405 } 406 407 dev_info_t * 408 mac_devinfo_get(mac_handle_t mh) 409 { 410 return (((mac_impl_t *)mh)->mi_dip); 411 } 412 413 void * 414 mac_driver(mac_handle_t mh) 415 { 416 return (((mac_impl_t *)mh)->mi_driver); 417 } 418 419 const char * 420 mac_name(mac_handle_t mh) 421 { 422 return (((mac_impl_t *)mh)->mi_name); 423 } 424 425 char * 426 mac_client_name(mac_client_handle_t mch) 427 { 428 return (((mac_client_impl_t *)mch)->mci_name); 429 } 430 431 minor_t 432 mac_minor(mac_handle_t mh) 433 { 434 return (((mac_impl_t *)mh)->mi_minor); 435 } 436 437 /* 438 * Return the VID associated with a MAC client. This function should 439 * be called for clients which are associated with only one VID. 440 */ 441 uint16_t 442 mac_client_vid(mac_client_handle_t mch) 443 { 444 uint16_t vid = VLAN_ID_NONE; 445 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 446 flow_desc_t flow_desc; 447 448 if (mcip->mci_nflents == 0) 449 return (vid); 450 451 ASSERT(MCIP_DATAPATH_SETUP(mcip) && mac_client_single_rcvr(mcip)); 452 453 mac_flow_get_desc(mcip->mci_flent, &flow_desc); 454 if ((flow_desc.fd_mask & FLOW_LINK_VID) != 0) 455 vid = flow_desc.fd_vid; 456 457 return (vid); 458 } 459 460 /* 461 * Return whether the specified MAC client corresponds to a VLAN VNIC. 462 */ 463 boolean_t 464 mac_client_is_vlan_vnic(mac_client_handle_t mch) 465 { 466 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 467 468 return (((mcip->mci_state_flags & MCIS_IS_VNIC) != 0) && 469 ((mcip->mci_flent->fe_type & FLOW_PRIMARY_MAC) != 0)); 470 } 471 472 /* 473 * Return the link speed associated with the specified MAC client. 474 * 475 * The link speed of a MAC client is equal to the smallest value of 476 * 1) the current link speed of the underlying NIC, or 477 * 2) the bandwidth limit set for the MAC client. 478 * 479 * Note that the bandwidth limit can be higher than the speed 480 * of the underlying NIC. This is allowed to avoid spurious 481 * administration action failures or artifically lowering the 482 * bandwidth limit of a link that may have temporarily lowered 483 * its link speed due to hardware problem or administrator action. 484 */ 485 static uint64_t 486 mac_client_ifspeed(mac_client_impl_t *mcip) 487 { 488 mac_impl_t *mip = mcip->mci_mip; 489 uint64_t nic_speed; 490 491 nic_speed = mac_stat_get((mac_handle_t)mip, MAC_STAT_IFSPEED); 492 493 if (nic_speed == 0) { 494 return (0); 495 } else { 496 uint64_t policy_limit = (uint64_t)-1; 497 498 if (MCIP_RESOURCE_PROPS_MASK(mcip) & MRP_MAXBW) 499 policy_limit = MCIP_RESOURCE_PROPS_MAXBW(mcip); 500 501 return (MIN(policy_limit, nic_speed)); 502 } 503 } 504 505 /* 506 * Return the link state of the specified client. If here are more 507 * than one clients of the underying mac_impl_t, the link state 508 * will always be UP regardless of the link state of the underlying 509 * mac_impl_t. This is needed to allow the MAC clients to continue 510 * to communicate with each other even when the physical link of 511 * their mac_impl_t is down. 512 */ 513 static uint64_t 514 mac_client_link_state(mac_client_impl_t *mcip) 515 { 516 mac_impl_t *mip = mcip->mci_mip; 517 uint16_t vid; 518 mac_client_impl_t *mci_list; 519 mac_unicast_impl_t *mui_list, *oth_mui_list; 520 521 /* 522 * Returns LINK_STATE_UP if there are other MAC clients defined on 523 * mac_impl_t which share same VLAN ID as that of mcip. Note that 524 * if 'mcip' has more than one VID's then we match ANY one of the 525 * VID's with other MAC client's VID's and return LINK_STATE_UP. 526 */ 527 rw_enter(&mcip->mci_rw_lock, RW_READER); 528 for (mui_list = mcip->mci_unicast_list; mui_list != NULL; 529 mui_list = mui_list->mui_next) { 530 vid = mui_list->mui_vid; 531 for (mci_list = mip->mi_clients_list; mci_list != NULL; 532 mci_list = mci_list->mci_client_next) { 533 if (mci_list == mcip) 534 continue; 535 for (oth_mui_list = mci_list->mci_unicast_list; 536 oth_mui_list != NULL; oth_mui_list = oth_mui_list-> 537 mui_next) { 538 if (vid == oth_mui_list->mui_vid) { 539 rw_exit(&mcip->mci_rw_lock); 540 return (LINK_STATE_UP); 541 } 542 } 543 } 544 } 545 rw_exit(&mcip->mci_rw_lock); 546 547 return (mac_stat_get((mac_handle_t)mip, MAC_STAT_LINK_STATE)); 548 } 549 550 /* 551 * Return the statistics of a MAC client. These statistics are different 552 * then the statistics of the underlying MAC which are returned by 553 * mac_stat_get(). 554 */ 555 uint64_t 556 mac_client_stat_get(mac_client_handle_t mch, uint_t stat) 557 { 558 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 559 mac_impl_t *mip = mcip->mci_mip; 560 uint64_t val; 561 562 switch (stat) { 563 case MAC_STAT_LINK_STATE: 564 val = mac_client_link_state(mcip); 565 break; 566 case MAC_STAT_LINK_UP: 567 val = (mac_client_link_state(mcip) == LINK_STATE_UP); 568 break; 569 case MAC_STAT_PROMISC: 570 val = mac_stat_get((mac_handle_t)mip, MAC_STAT_PROMISC); 571 break; 572 case MAC_STAT_LOWLINK_STATE: 573 val = mac_stat_get((mac_handle_t)mip, MAC_STAT_LOWLINK_STATE); 574 break; 575 case MAC_STAT_IFSPEED: 576 val = mac_client_ifspeed(mcip); 577 break; 578 case MAC_STAT_MULTIRCV: 579 val = mcip->mci_stat_multircv; 580 break; 581 case MAC_STAT_BRDCSTRCV: 582 val = mcip->mci_stat_brdcstrcv; 583 break; 584 case MAC_STAT_MULTIXMT: 585 val = mcip->mci_stat_multixmt; 586 break; 587 case MAC_STAT_BRDCSTXMT: 588 val = mcip->mci_stat_brdcstxmt; 589 break; 590 case MAC_STAT_OBYTES: 591 val = mcip->mci_stat_obytes; 592 break; 593 case MAC_STAT_OPACKETS: 594 val = mcip->mci_stat_opackets; 595 break; 596 case MAC_STAT_OERRORS: 597 val = mcip->mci_stat_oerrors; 598 break; 599 case MAC_STAT_IPACKETS: 600 val = mcip->mci_stat_ipackets; 601 break; 602 case MAC_STAT_RBYTES: 603 val = mcip->mci_stat_ibytes; 604 break; 605 case MAC_STAT_IERRORS: 606 val = mcip->mci_stat_ierrors; 607 break; 608 default: 609 val = mac_stat_default(mip, stat); 610 break; 611 } 612 613 return (val); 614 } 615 616 /* 617 * Return the statistics of the specified MAC instance. 618 */ 619 uint64_t 620 mac_stat_get(mac_handle_t mh, uint_t stat) 621 { 622 mac_impl_t *mip = (mac_impl_t *)mh; 623 uint64_t val; 624 int ret; 625 626 /* 627 * The range of stat determines where it is maintained. Stat 628 * values from 0 up to (but not including) MAC_STAT_MIN are 629 * mainteined by the mac module itself. Everything else is 630 * maintained by the driver. 631 * 632 * If the mac_impl_t being queried corresponds to a VNIC, 633 * the stats need to be queried from the lower MAC client 634 * corresponding to the VNIC. (The mac_link_update() 635 * invoked by the driver to the lower MAC causes the *lower 636 * MAC* to update its mi_linkstate, and send a notification 637 * to its MAC clients. Due to the VNIC passthrough, 638 * these notifications are sent to the upper MAC clients 639 * of the VNIC directly, and the upper mac_impl_t of the VNIC 640 * does not have a valid mi_linkstate. 641 */ 642 if (stat < MAC_STAT_MIN && !(mip->mi_state_flags & MIS_IS_VNIC)) { 643 /* these stats are maintained by the mac module itself */ 644 switch (stat) { 645 case MAC_STAT_LINK_STATE: 646 return (mip->mi_linkstate); 647 case MAC_STAT_LINK_UP: 648 return (mip->mi_linkstate == LINK_STATE_UP); 649 case MAC_STAT_PROMISC: 650 return (mip->mi_devpromisc != 0); 651 case MAC_STAT_LOWLINK_STATE: 652 return (mip->mi_lowlinkstate); 653 default: 654 ASSERT(B_FALSE); 655 } 656 } 657 658 /* 659 * Call the driver to get the given statistic. 660 */ 661 ret = mip->mi_getstat(mip->mi_driver, stat, &val); 662 if (ret != 0) { 663 /* 664 * The driver doesn't support this statistic. Get the 665 * statistic's default value. 666 */ 667 val = mac_stat_default(mip, stat); 668 } 669 return (val); 670 } 671 672 /* 673 * Utility function which returns the VID associated with a flow entry. 674 */ 675 uint16_t 676 i_mac_flow_vid(flow_entry_t *flent) 677 { 678 flow_desc_t flow_desc; 679 680 mac_flow_get_desc(flent, &flow_desc); 681 682 if ((flow_desc.fd_mask & FLOW_LINK_VID) != 0) 683 return (flow_desc.fd_vid); 684 return (VLAN_ID_NONE); 685 } 686 687 /* 688 * Verify the validity of the specified unicast MAC address. Returns B_TRUE 689 * if the address is valid, B_FALSE otherwise (multicast address, or incorrect 690 * length. 691 */ 692 boolean_t 693 mac_unicst_verify(mac_handle_t mh, const uint8_t *addr, uint_t len) 694 { 695 mac_impl_t *mip = (mac_impl_t *)mh; 696 697 /* 698 * Verify the address. No lock is needed since mi_type and plugin 699 * details don't change after mac_register(). 700 */ 701 if ((len != mip->mi_type->mt_addr_length) || 702 (mip->mi_type->mt_ops.mtops_unicst_verify(addr, 703 mip->mi_pdata)) != 0) { 704 return (B_FALSE); 705 } else { 706 return (B_TRUE); 707 } 708 } 709 710 void 711 mac_sdu_get(mac_handle_t mh, uint_t *min_sdu, uint_t *max_sdu) 712 { 713 mac_impl_t *mip = (mac_impl_t *)mh; 714 715 if (min_sdu != NULL) 716 *min_sdu = mip->mi_sdu_min; 717 if (max_sdu != NULL) 718 *max_sdu = mip->mi_sdu_max; 719 } 720 721 /* 722 * Update the MAC unicast address of the specified client's flows. Currently 723 * only one unicast MAC unicast address is allowed per client. 724 */ 725 static void 726 mac_unicast_update_client_flow(mac_client_impl_t *mcip) 727 { 728 mac_impl_t *mip = mcip->mci_mip; 729 flow_entry_t *flent = mcip->mci_flent; 730 mac_address_t *map = mcip->mci_unicast; 731 flow_desc_t flow_desc; 732 733 ASSERT(MAC_PERIM_HELD((mac_handle_t)mip)); 734 ASSERT(flent != NULL); 735 736 mac_flow_get_desc(flent, &flow_desc); 737 ASSERT(flow_desc.fd_mask & FLOW_LINK_DST); 738 739 bcopy(map->ma_addr, flow_desc.fd_dst_mac, map->ma_len); 740 mac_flow_set_desc(flent, &flow_desc); 741 742 /* 743 * A MAC client could have one MAC address but multiple 744 * VLANs. In that case update the flow entries corresponding 745 * to all VLANs of the MAC client. 746 */ 747 for (flent = mcip->mci_flent_list; flent != NULL; 748 flent = flent->fe_client_next) { 749 mac_flow_get_desc(flent, &flow_desc); 750 if (!(flent->fe_type & FLOW_PRIMARY_MAC || 751 flent->fe_type & FLOW_VNIC_MAC)) 752 continue; 753 754 bcopy(map->ma_addr, flow_desc.fd_dst_mac, map->ma_len); 755 mac_flow_set_desc(flent, &flow_desc); 756 } 757 } 758 759 /* 760 * Update all clients that share the same unicast address. 761 */ 762 void 763 mac_unicast_update_clients(mac_impl_t *mip, mac_address_t *map) 764 { 765 mac_client_impl_t *mcip; 766 767 ASSERT(MAC_PERIM_HELD((mac_handle_t)mip)); 768 769 /* 770 * Find all clients that share the same unicast MAC address and update 771 * them appropriately. 772 */ 773 for (mcip = mip->mi_clients_list; mcip != NULL; 774 mcip = mcip->mci_client_next) { 775 /* 776 * Ignore clients that don't share this MAC address. 777 */ 778 if (map != mcip->mci_unicast) 779 continue; 780 781 /* 782 * Update those clients with same old unicast MAC address. 783 */ 784 mac_unicast_update_client_flow(mcip); 785 } 786 } 787 788 /* 789 * Update the unicast MAC address of the specified VNIC MAC client. 790 * 791 * Check whether the operation is valid. Any of following cases should fail: 792 * 793 * 1. It's a VLAN type of VNIC. 794 * 2. The new value is current "primary" MAC address. 795 * 3. The current MAC address is shared with other clients. 796 * 4. The new MAC address has been used. This case will be valid when 797 * client migration is fully supported. 798 */ 799 int 800 mac_vnic_unicast_set(mac_client_handle_t mch, const uint8_t *addr) 801 { 802 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 803 mac_impl_t *mip = mcip->mci_mip; 804 mac_address_t *map = mcip->mci_unicast; 805 int err; 806 807 ASSERT(!(mip->mi_state_flags & MIS_IS_VNIC)); 808 ASSERT(mcip->mci_state_flags & MCIS_IS_VNIC); 809 ASSERT(mcip->mci_flags != MAC_CLIENT_FLAGS_PRIMARY); 810 811 i_mac_perim_enter(mip); 812 813 /* 814 * If this is a VLAN type of VNIC, it's using "primary" MAC address 815 * of the underlying interface. Must fail here. Refer to case 1 above. 816 */ 817 if (bcmp(map->ma_addr, mip->mi_addr, map->ma_len) == 0) { 818 i_mac_perim_exit(mip); 819 return (ENOTSUP); 820 } 821 822 /* 823 * If the new address is the "primary" one, must fail. Refer to 824 * case 2 above. 825 */ 826 if (bcmp(addr, mip->mi_addr, map->ma_len) == 0) { 827 i_mac_perim_exit(mip); 828 return (EACCES); 829 } 830 831 /* 832 * If the address is shared by multiple clients, must fail. Refer 833 * to case 3 above. 834 */ 835 if (mac_check_macaddr_shared(map)) { 836 i_mac_perim_exit(mip); 837 return (EBUSY); 838 } 839 840 /* 841 * If the new address has been used, must fail for now. Refer to 842 * case 4 above. 843 */ 844 if (mac_find_macaddr(mip, (uint8_t *)addr) != NULL) { 845 i_mac_perim_exit(mip); 846 return (ENOTSUP); 847 } 848 849 /* 850 * Update the MAC address. 851 */ 852 err = mac_update_macaddr(map, (uint8_t *)addr); 853 854 if (err != 0) { 855 i_mac_perim_exit(mip); 856 return (err); 857 } 858 859 /* 860 * Update all flows of this MAC client. 861 */ 862 mac_unicast_update_client_flow(mcip); 863 864 i_mac_perim_exit(mip); 865 return (0); 866 } 867 868 /* 869 * Program the new primary unicast address of the specified MAC. 870 * 871 * Function mac_update_macaddr() takes care different types of underlying 872 * MAC. If the underlying MAC is VNIC, the VNIC driver must have registerd 873 * mi_unicst() entry point, that indirectly calls mac_vnic_unicast_set() 874 * which will take care of updating the MAC address of the corresponding 875 * MAC client. 876 * 877 * This is the only interface that allow the client to update the "primary" 878 * MAC address of the underlying MAC. The new value must have not been 879 * used by other clients. 880 */ 881 int 882 mac_unicast_primary_set(mac_handle_t mh, const uint8_t *addr) 883 { 884 mac_impl_t *mip = (mac_impl_t *)mh; 885 mac_address_t *map; 886 int err; 887 888 /* verify the address validity */ 889 if (!mac_unicst_verify(mh, addr, mip->mi_type->mt_addr_length)) 890 return (EINVAL); 891 892 i_mac_perim_enter(mip); 893 894 /* 895 * If the new value is the same as the current primary address value, 896 * there's nothing to do. 897 */ 898 if (bcmp(addr, mip->mi_addr, mip->mi_type->mt_addr_length) == 0) { 899 i_mac_perim_exit(mip); 900 return (0); 901 } 902 903 if (mac_find_macaddr(mip, (uint8_t *)addr) != 0) { 904 i_mac_perim_exit(mip); 905 return (EBUSY); 906 } 907 908 map = mac_find_macaddr(mip, mip->mi_addr); 909 ASSERT(map != NULL); 910 911 /* 912 * Update the MAC address. 913 */ 914 if (mip->mi_state_flags & MIS_IS_AGGR) { 915 mac_capab_aggr_t aggr_cap; 916 917 /* 918 * If the mac is an aggregation, other than the unicast 919 * addresses programming, aggr must be informed about this 920 * primary unicst address change to change its mac address 921 * policy to be user-specified. 922 */ 923 ASSERT(map->ma_type == MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED); 924 VERIFY(i_mac_capab_get(mh, MAC_CAPAB_AGGR, &aggr_cap)); 925 err = aggr_cap.mca_unicst(mip->mi_driver, addr); 926 if (err == 0) 927 bcopy(addr, map->ma_addr, map->ma_len); 928 } else { 929 err = mac_update_macaddr(map, (uint8_t *)addr); 930 } 931 932 if (err != 0) { 933 i_mac_perim_exit(mip); 934 return (err); 935 } 936 937 mac_unicast_update_clients(mip, map); 938 939 /* 940 * Save the new primary MAC address in mac_impl_t. 941 */ 942 bcopy(addr, mip->mi_addr, mip->mi_type->mt_addr_length); 943 944 i_mac_perim_exit(mip); 945 946 if (err == 0) 947 i_mac_notify(mip, MAC_NOTE_UNICST); 948 949 return (err); 950 } 951 952 /* 953 * Return the current primary MAC address of the specified MAC. 954 */ 955 void 956 mac_unicast_primary_get(mac_handle_t mh, uint8_t *addr) 957 { 958 mac_impl_t *mip = (mac_impl_t *)mh; 959 960 rw_enter(&mip->mi_rw_lock, RW_READER); 961 bcopy(mip->mi_addr, addr, mip->mi_type->mt_addr_length); 962 rw_exit(&mip->mi_rw_lock); 963 } 964 965 /* 966 * Return information about the use of the primary MAC address of the 967 * specified MAC instance: 968 * 969 * - if client_name is non-NULL, it must point to a string of at 970 * least MAXNAMELEN bytes, and will be set to the name of the MAC 971 * client which uses the primary MAC address. 972 * 973 * - if in_use is non-NULL, used to return whether the primary MAC 974 * address is currently in use. 975 */ 976 void 977 mac_unicast_primary_info(mac_handle_t mh, char *client_name, boolean_t *in_use) 978 { 979 mac_impl_t *mip = (mac_impl_t *)mh; 980 mac_client_impl_t *cur_client; 981 982 if (in_use != NULL) 983 *in_use = B_FALSE; 984 if (client_name != NULL) 985 bzero(client_name, MAXNAMELEN); 986 987 /* 988 * The mi_rw_lock is used to protect threads that don't hold the 989 * mac perimeter to get a consistent view of the mi_clients_list. 990 * Threads that modify the list must hold both the mac perimeter and 991 * mi_rw_lock(RW_WRITER) 992 */ 993 rw_enter(&mip->mi_rw_lock, RW_READER); 994 for (cur_client = mip->mi_clients_list; cur_client != NULL; 995 cur_client = cur_client->mci_client_next) { 996 if (mac_is_primary_client(cur_client) || 997 (mip->mi_state_flags & MIS_IS_VNIC)) { 998 rw_exit(&mip->mi_rw_lock); 999 if (in_use != NULL) 1000 *in_use = B_TRUE; 1001 if (client_name != NULL) { 1002 bcopy(cur_client->mci_name, client_name, 1003 MAXNAMELEN); 1004 } 1005 return; 1006 } 1007 } 1008 rw_exit(&mip->mi_rw_lock); 1009 } 1010 1011 /* 1012 * Add the specified MAC client to the list of clients which opened 1013 * the specified MAC. 1014 */ 1015 static void 1016 mac_client_add(mac_client_impl_t *mcip) 1017 { 1018 mac_impl_t *mip = mcip->mci_mip; 1019 1020 ASSERT(MAC_PERIM_HELD((mac_handle_t)mip)); 1021 1022 /* add VNIC to the front of the list */ 1023 rw_enter(&mip->mi_rw_lock, RW_WRITER); 1024 mcip->mci_client_next = mip->mi_clients_list; 1025 mip->mi_clients_list = mcip; 1026 mip->mi_nclients++; 1027 rw_exit(&mip->mi_rw_lock); 1028 } 1029 1030 /* 1031 * Remove the specified MAC client from the list of clients which opened 1032 * the specified MAC. 1033 */ 1034 static void 1035 mac_client_remove(mac_client_impl_t *mcip) 1036 { 1037 mac_impl_t *mip = mcip->mci_mip; 1038 mac_client_impl_t **prev, *cclient; 1039 1040 ASSERT(MAC_PERIM_HELD((mac_handle_t)mip)); 1041 1042 rw_enter(&mip->mi_rw_lock, RW_WRITER); 1043 prev = &mip->mi_clients_list; 1044 cclient = *prev; 1045 while (cclient != NULL && cclient != mcip) { 1046 prev = &cclient->mci_client_next; 1047 cclient = *prev; 1048 } 1049 ASSERT(cclient != NULL); 1050 *prev = cclient->mci_client_next; 1051 mip->mi_nclients--; 1052 rw_exit(&mip->mi_rw_lock); 1053 } 1054 1055 static mac_unicast_impl_t * 1056 mac_client_find_vid(mac_client_impl_t *mcip, uint16_t vid) 1057 { 1058 mac_unicast_impl_t *muip = mcip->mci_unicast_list; 1059 1060 while ((muip != NULL) && (muip->mui_vid != vid)) 1061 muip = muip->mui_next; 1062 1063 return (muip); 1064 } 1065 1066 /* 1067 * Return whether the specified (MAC address, VID) tuple is already used by 1068 * one of the MAC clients associated with the specified MAC. 1069 */ 1070 static boolean_t 1071 mac_addr_in_use(mac_impl_t *mip, uint8_t *mac_addr, uint16_t vid) 1072 { 1073 mac_client_impl_t *client; 1074 mac_address_t *map; 1075 1076 ASSERT(MAC_PERIM_HELD((mac_handle_t)mip)); 1077 1078 for (client = mip->mi_clients_list; client != NULL; 1079 client = client->mci_client_next) { 1080 1081 /* 1082 * Ignore clients that don't have unicast address. 1083 */ 1084 if (client->mci_unicast_list == NULL) 1085 continue; 1086 1087 map = client->mci_unicast; 1088 1089 if ((bcmp(mac_addr, map->ma_addr, map->ma_len) == 0) && 1090 (mac_client_find_vid(client, vid) != NULL)) { 1091 return (B_TRUE); 1092 } 1093 } 1094 1095 return (B_FALSE); 1096 } 1097 1098 /* 1099 * Generate a random MAC address. The MAC address prefix is 1100 * stored in the array pointed to by mac_addr, and its length, in bytes, 1101 * is specified by prefix_len. The least significant bits 1102 * after prefix_len bytes are generated, and stored after the prefix 1103 * in the mac_addr array. 1104 */ 1105 int 1106 mac_addr_random(mac_client_handle_t mch, uint_t prefix_len, 1107 uint8_t *mac_addr, mac_diag_t *diag) 1108 { 1109 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 1110 mac_impl_t *mip = mcip->mci_mip; 1111 size_t addr_len = mip->mi_type->mt_addr_length; 1112 1113 if (prefix_len >= addr_len) { 1114 *diag = MAC_DIAG_MACPREFIXLEN_INVALID; 1115 return (EINVAL); 1116 } 1117 1118 /* check the prefix value */ 1119 if (prefix_len > 0) { 1120 bzero(mac_addr + prefix_len, addr_len - prefix_len); 1121 if (!mac_unicst_verify((mac_handle_t)mip, mac_addr, 1122 addr_len)) { 1123 *diag = MAC_DIAG_MACPREFIX_INVALID; 1124 return (EINVAL); 1125 } 1126 } 1127 1128 /* generate the MAC address */ 1129 if (prefix_len < addr_len) { 1130 (void) random_get_pseudo_bytes(mac_addr + 1131 prefix_len, addr_len - prefix_len); 1132 } 1133 1134 *diag = 0; 1135 return (0); 1136 } 1137 1138 /* 1139 * Set the priority range for this MAC client. This will be used to 1140 * determine the absolute priority for the threads created for this 1141 * MAC client using the specified "low", "medium" and "high" level. 1142 * This will also be used for any subflows on this MAC client. 1143 */ 1144 #define MAC_CLIENT_SET_PRIORITY_RANGE(mcip, pri) { \ 1145 (mcip)->mci_min_pri = FLOW_MIN_PRIORITY(MINCLSYSPRI, \ 1146 MAXCLSYSPRI, (pri)); \ 1147 (mcip)->mci_max_pri = FLOW_MAX_PRIORITY(MINCLSYSPRI, \ 1148 MAXCLSYSPRI, (mcip)->mci_min_pri); \ 1149 } 1150 1151 /* 1152 * MAC client open entry point. Return a new MAC client handle. Each 1153 * MAC client is associated with a name, specified through the 'name' 1154 * argument. 1155 */ 1156 int 1157 mac_client_open(mac_handle_t mh, mac_client_handle_t *mchp, char *name, 1158 uint16_t flags) 1159 { 1160 mac_impl_t *mip = (mac_impl_t *)mh; 1161 mac_client_impl_t *mcip; 1162 int err = 0; 1163 boolean_t share_desired = 1164 ((flags & MAC_OPEN_FLAGS_SHARES_DESIRED) != 0); 1165 boolean_t no_hwrings = ((flags & MAC_OPEN_FLAGS_NO_HWRINGS) != 0); 1166 boolean_t req_hwrings = ((flags & MAC_OPEN_FLAGS_REQ_HWRINGS) != 0); 1167 flow_entry_t *flent = NULL; 1168 1169 *mchp = NULL; 1170 if (share_desired && no_hwrings) { 1171 /* can't have shares but no hardware rings */ 1172 return (EINVAL); 1173 } 1174 1175 i_mac_perim_enter(mip); 1176 1177 if (mip->mi_state_flags & MIS_IS_VNIC) { 1178 /* 1179 * The underlying MAC is a VNIC. Return the MAC client 1180 * handle of the lower MAC which was obtained by 1181 * the VNIC driver when it did its mac_client_open(). 1182 */ 1183 1184 mcip = mac_vnic_lower(mip); 1185 1186 /* 1187 * Note that multiple mac clients share the same mcip in 1188 * this case. 1189 */ 1190 if (flags & MAC_OPEN_FLAGS_EXCLUSIVE) 1191 mcip->mci_state_flags |= MCIS_EXCLUSIVE; 1192 1193 if (flags & MAC_OPEN_FLAGS_MULTI_PRIMARY) 1194 mcip->mci_flags |= MAC_CLIENT_FLAGS_MULTI_PRIMARY; 1195 1196 mip->mi_clients_list = mcip; 1197 i_mac_perim_exit(mip); 1198 *mchp = (mac_client_handle_t)mcip; 1199 return (err); 1200 } 1201 1202 mcip = kmem_cache_alloc(mac_client_impl_cache, KM_SLEEP); 1203 1204 mcip->mci_mip = mip; 1205 mcip->mci_upper_mip = NULL; 1206 mcip->mci_rx_fn = mac_pkt_drop; 1207 mcip->mci_rx_arg = NULL; 1208 mcip->mci_rx_p_fn = NULL; 1209 mcip->mci_rx_p_arg = NULL; 1210 mcip->mci_p_unicast_list = NULL; 1211 mcip->mci_direct_rx_fn = NULL; 1212 mcip->mci_direct_rx_arg = NULL; 1213 1214 mcip->mci_unicast_list = NULL; 1215 1216 if ((flags & MAC_OPEN_FLAGS_IS_VNIC) != 0) 1217 mcip->mci_state_flags |= MCIS_IS_VNIC; 1218 1219 if ((flags & MAC_OPEN_FLAGS_EXCLUSIVE) != 0) 1220 mcip->mci_state_flags |= MCIS_EXCLUSIVE; 1221 1222 if ((flags & MAC_OPEN_FLAGS_IS_AGGR_PORT) != 0) 1223 mcip->mci_state_flags |= MCIS_IS_AGGR_PORT; 1224 1225 if ((flags & MAC_OPEN_FLAGS_USE_DATALINK_NAME) != 0) { 1226 datalink_id_t linkid; 1227 1228 ASSERT(name == NULL); 1229 if ((err = dls_devnet_macname2linkid(mip->mi_name, 1230 &linkid)) != 0) { 1231 goto done; 1232 } 1233 if ((err = dls_mgmt_get_linkinfo(linkid, mcip->mci_name, NULL, 1234 NULL, NULL)) != 0) { 1235 /* 1236 * Use mac name if dlmgmtd is not available. 1237 */ 1238 if (err == EBADF) { 1239 (void) strlcpy(mcip->mci_name, mip->mi_name, 1240 sizeof (mcip->mci_name)); 1241 err = 0; 1242 } else { 1243 goto done; 1244 } 1245 } 1246 mcip->mci_state_flags |= MCIS_USE_DATALINK_NAME; 1247 } else { 1248 ASSERT(name != NULL); 1249 if (strlen(name) > MAXNAMELEN) { 1250 err = EINVAL; 1251 goto done; 1252 } 1253 (void) strlcpy(mcip->mci_name, name, sizeof (mcip->mci_name)); 1254 } 1255 1256 if (flags & MAC_OPEN_FLAGS_MULTI_PRIMARY) 1257 mcip->mci_flags |= MAC_CLIENT_FLAGS_MULTI_PRIMARY; 1258 1259 /* the subflow table will be created dynamically */ 1260 mcip->mci_subflow_tab = NULL; 1261 mcip->mci_stat_multircv = 0; 1262 mcip->mci_stat_brdcstrcv = 0; 1263 mcip->mci_stat_multixmt = 0; 1264 mcip->mci_stat_brdcstxmt = 0; 1265 1266 mcip->mci_stat_obytes = 0; 1267 mcip->mci_stat_opackets = 0; 1268 mcip->mci_stat_oerrors = 0; 1269 mcip->mci_stat_ibytes = 0; 1270 mcip->mci_stat_ipackets = 0; 1271 mcip->mci_stat_ierrors = 0; 1272 1273 /* Create an initial flow */ 1274 1275 err = mac_flow_create(NULL, NULL, mcip->mci_name, NULL, 1276 mcip->mci_state_flags & MCIS_IS_VNIC ? FLOW_VNIC_MAC : 1277 FLOW_PRIMARY_MAC, &flent); 1278 if (err != 0) 1279 goto done; 1280 mcip->mci_flent = flent; 1281 FLOW_MARK(flent, FE_MC_NO_DATAPATH); 1282 flent->fe_mcip = mcip; 1283 /* 1284 * Place initial creation reference on the flow. This reference 1285 * is released in the corresponding delete action viz. 1286 * mac_unicast_remove after waiting for all transient refs to 1287 * to go away. The wait happens in mac_flow_wait. 1288 */ 1289 FLOW_REFHOLD(flent); 1290 1291 /* 1292 * Do this ahead of the mac_bcast_add() below so that the mi_nclients 1293 * will have the right value for mac_rx_srs_setup(). 1294 */ 1295 mac_client_add(mcip); 1296 1297 if (no_hwrings) 1298 mcip->mci_state_flags |= MCIS_NO_HWRINGS; 1299 if (req_hwrings) 1300 mcip->mci_state_flags |= MCIS_REQ_HWRINGS; 1301 mcip->mci_share = NULL; 1302 if (share_desired) { 1303 ASSERT(!no_hwrings); 1304 i_mac_share_alloc(mcip); 1305 } 1306 1307 DTRACE_PROBE2(mac__client__open__allocated, mac_impl_t *, 1308 mcip->mci_mip, mac_client_impl_t *, mcip); 1309 *mchp = (mac_client_handle_t)mcip; 1310 1311 i_mac_perim_exit(mip); 1312 return (0); 1313 1314 done: 1315 i_mac_perim_exit(mip); 1316 mcip->mci_state_flags = 0; 1317 mcip->mci_tx_flag = 0; 1318 kmem_cache_free(mac_client_impl_cache, mcip); 1319 return (err); 1320 } 1321 1322 /* 1323 * Close the specified MAC client handle. 1324 */ 1325 void 1326 mac_client_close(mac_client_handle_t mch, uint16_t flags) 1327 { 1328 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 1329 mac_impl_t *mip = mcip->mci_mip; 1330 flow_entry_t *flent; 1331 1332 i_mac_perim_enter(mip); 1333 1334 if (flags & MAC_CLOSE_FLAGS_EXCLUSIVE) 1335 mcip->mci_state_flags &= ~MCIS_EXCLUSIVE; 1336 1337 if ((mcip->mci_state_flags & MCIS_IS_VNIC) && 1338 !(flags & MAC_CLOSE_FLAGS_IS_VNIC)) { 1339 /* 1340 * This is an upper VNIC client initiated operation. 1341 * The lower MAC client will be closed by the VNIC driver 1342 * when the VNIC is deleted. 1343 */ 1344 1345 i_mac_perim_exit(mip); 1346 return; 1347 } 1348 1349 /* 1350 * Remove the flent associated with the MAC client 1351 */ 1352 flent = mcip->mci_flent; 1353 mcip->mci_flent = NULL; 1354 FLOW_FINAL_REFRELE(flent); 1355 1356 /* 1357 * MAC clients must remove the unicast addresses and promisc callbacks 1358 * they added before issuing a mac_client_close(). 1359 */ 1360 ASSERT(mcip->mci_unicast_list == NULL); 1361 ASSERT(mcip->mci_promisc_list == NULL); 1362 ASSERT(mcip->mci_tx_notify_cb_list == NULL); 1363 1364 i_mac_share_free(mcip); 1365 1366 mac_client_remove(mcip); 1367 1368 i_mac_perim_exit(mip); 1369 mcip->mci_subflow_tab = NULL; 1370 mcip->mci_state_flags = 0; 1371 mcip->mci_tx_flag = 0; 1372 kmem_cache_free(mac_client_impl_cache, mch); 1373 } 1374 1375 /* 1376 * Enable bypass for the specified MAC client. 1377 */ 1378 boolean_t 1379 mac_rx_bypass_set(mac_client_handle_t mch, mac_direct_rx_t rx_fn, void *arg1) 1380 { 1381 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 1382 mac_impl_t *mip = mcip->mci_mip; 1383 1384 ASSERT(MAC_PERIM_HELD((mac_handle_t)mip)); 1385 1386 /* 1387 * If the mac_client is a VLAN, we should not do DLS bypass and 1388 * instead let the packets come up via mac_rx_deliver so the vlan 1389 * header can be stripped. 1390 */ 1391 if (mcip->mci_nvids > 0) 1392 return (B_FALSE); 1393 1394 /* 1395 * These are not accessed directly in the data path, and hence 1396 * don't need any protection 1397 */ 1398 mcip->mci_direct_rx_fn = rx_fn; 1399 mcip->mci_direct_rx_arg = arg1; 1400 mcip->mci_state_flags |= MCIS_CLIENT_POLL_CAPABLE; 1401 return (B_TRUE); 1402 } 1403 1404 /* 1405 * Set the receive callback for the specified MAC client. There can be 1406 * at most one such callback per MAC client. 1407 */ 1408 void 1409 mac_rx_set(mac_client_handle_t mch, mac_rx_t rx_fn, void *arg) 1410 { 1411 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 1412 mac_impl_t *mip = mcip->mci_mip; 1413 1414 /* 1415 * Instead of adding an extra set of locks and refcnts in 1416 * the datapath at the mac client boundary, we temporarily quiesce 1417 * the SRS and related entities. We then change the receive function 1418 * without interference from any receive data thread and then reenable 1419 * the data flow subsequently. 1420 */ 1421 i_mac_perim_enter(mip); 1422 mac_rx_client_quiesce(mch); 1423 1424 mcip->mci_rx_fn = rx_fn; 1425 mcip->mci_rx_arg = arg; 1426 mac_rx_client_restart(mch); 1427 i_mac_perim_exit(mip); 1428 } 1429 1430 /* 1431 * Reset the receive callback for the specified MAC client. 1432 */ 1433 void 1434 mac_rx_clear(mac_client_handle_t mch) 1435 { 1436 mac_rx_set(mch, mac_pkt_drop, NULL); 1437 } 1438 1439 /* 1440 * Walk the MAC client subflow table and updates their priority values. 1441 */ 1442 static int 1443 mac_update_subflow_priority_cb(flow_entry_t *flent, void *arg) 1444 { 1445 mac_flow_update_priority(arg, flent); 1446 return (0); 1447 } 1448 1449 void 1450 mac_update_subflow_priority(mac_client_impl_t *mcip) 1451 { 1452 (void) mac_flow_walk(mcip->mci_subflow_tab, 1453 mac_update_subflow_priority_cb, mcip); 1454 } 1455 1456 /* 1457 * When the MAC client is being brought up (i.e. we do a unicast_add) we need 1458 * to initialize the cpu and resource control structure in the 1459 * mac_client_impl_t from the mac_impl_t (i.e if there are any cached 1460 * properties before the flow entry for the unicast address was created). 1461 */ 1462 int 1463 mac_resource_ctl_set(mac_client_handle_t mch, mac_resource_props_t *mrp) 1464 { 1465 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 1466 mac_impl_t *mip = (mac_impl_t *)mcip->mci_mip; 1467 int err = 0; 1468 1469 ASSERT(MAC_PERIM_HELD((mac_handle_t)mip)); 1470 1471 err = mac_validate_props(mrp); 1472 if (err != 0) 1473 return (err); 1474 1475 mac_update_resources(mrp, MCIP_RESOURCE_PROPS(mcip), B_FALSE); 1476 if (MCIP_DATAPATH_SETUP(mcip)) { 1477 /* 1478 * We have to set this prior to calling mac_flow_modify. 1479 */ 1480 if (mrp->mrp_mask & MRP_PRIORITY) { 1481 if (mrp->mrp_priority == MPL_RESET) { 1482 MAC_CLIENT_SET_PRIORITY_RANGE(mcip, 1483 MPL_LINK_DEFAULT); 1484 } else { 1485 MAC_CLIENT_SET_PRIORITY_RANGE(mcip, 1486 mrp->mrp_priority); 1487 } 1488 } 1489 1490 mac_flow_modify(mip->mi_flow_tab, mcip->mci_flent, mrp); 1491 if (mrp->mrp_mask & MRP_PRIORITY) 1492 mac_update_subflow_priority(mcip); 1493 return (0); 1494 } 1495 return (0); 1496 } 1497 1498 void 1499 mac_resource_ctl_get(mac_client_handle_t mch, mac_resource_props_t *mrp) 1500 { 1501 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 1502 mac_resource_props_t *mcip_mrp = MCIP_RESOURCE_PROPS(mcip); 1503 1504 bcopy(mcip_mrp, mrp, sizeof (mac_resource_props_t)); 1505 } 1506 1507 static int 1508 mac_unicast_flow_create(mac_client_impl_t *mcip, uint8_t *mac_addr, 1509 uint16_t vid, boolean_t is_primary, boolean_t first_flow, 1510 flow_entry_t **flent, mac_resource_props_t *mrp) 1511 { 1512 mac_impl_t *mip = (mac_impl_t *)mcip->mci_mip; 1513 flow_desc_t flow_desc; 1514 char flowname[MAXFLOWNAMELEN]; 1515 int err; 1516 uint_t flent_flags; 1517 1518 /* 1519 * First unicast address being added, create a new flow 1520 * for that MAC client. 1521 */ 1522 bzero(&flow_desc, sizeof (flow_desc)); 1523 1524 flow_desc.fd_mac_len = mip->mi_type->mt_addr_length; 1525 bcopy(mac_addr, flow_desc.fd_dst_mac, flow_desc.fd_mac_len); 1526 flow_desc.fd_mask = FLOW_LINK_DST; 1527 if (vid != 0) { 1528 flow_desc.fd_vid = vid; 1529 flow_desc.fd_mask |= FLOW_LINK_VID; 1530 } 1531 1532 /* 1533 * XXX-nicolas. For now I'm keeping the FLOW_PRIMARY_MAC 1534 * and FLOW_VNIC. Even though they're a hack inherited 1535 * from the SRS code, we'll keep them for now. They're currently 1536 * consumed by mac_datapath_setup() to create the SRS. 1537 * That code should be eventually moved out of 1538 * mac_datapath_setup() and moved to a mac_srs_create() 1539 * function of some sort to keep things clean. 1540 * 1541 * Also, there's no reason why the SRS for the primary MAC 1542 * client should be different than any other MAC client. Until 1543 * this is cleaned-up, we support only one MAC unicast address 1544 * per client. 1545 * 1546 * We set FLOW_PRIMARY_MAC for the primary MAC address, 1547 * FLOW_VNIC for everything else. 1548 */ 1549 if (is_primary) 1550 flent_flags = FLOW_PRIMARY_MAC; 1551 else 1552 flent_flags = FLOW_VNIC_MAC; 1553 1554 /* 1555 * For the first flow we use the mac client's name - mci_name, for 1556 * subsequent ones we just create a name with the vid. This is 1557 * so that we can add these flows to the same flow table. This is 1558 * fine as the flow name (except for the one with the mac client's 1559 * name) is not visible. When the first flow is removed, we just replace 1560 * its fdesc with another from the list, so we will still retain the 1561 * flent with the MAC client's flow name. 1562 */ 1563 if (first_flow) { 1564 bcopy(mcip->mci_name, flowname, MAXFLOWNAMELEN); 1565 } else { 1566 (void) sprintf(flowname, "%s%u", mcip->mci_name, vid); 1567 flent_flags = FLOW_NO_STATS; 1568 } 1569 1570 if ((err = mac_flow_create(&flow_desc, mrp, flowname, NULL, 1571 flent_flags, flent)) != 0) 1572 return (err); 1573 1574 FLOW_MARK(*flent, FE_INCIPIENT); 1575 (*flent)->fe_mcip = mcip; 1576 1577 /* 1578 * Place initial creation reference on the flow. This reference 1579 * is released in the corresponding delete action viz. 1580 * mac_unicast_remove after waiting for all transient refs to 1581 * to go away. The wait happens in mac_flow_wait. 1582 * We have already held the reference in mac_client_open(). 1583 */ 1584 if (!first_flow) 1585 FLOW_REFHOLD(*flent); 1586 return (0); 1587 } 1588 1589 /* Refresh the multicast grouping for this VID. */ 1590 int 1591 mac_client_update_mcast(void *arg, boolean_t add, const uint8_t *addrp) 1592 { 1593 flow_entry_t *flent = arg; 1594 mac_client_impl_t *mcip = flent->fe_mcip; 1595 uint16_t vid; 1596 flow_desc_t flow_desc; 1597 1598 mac_flow_get_desc(flent, &flow_desc); 1599 vid = (flow_desc.fd_mask & FLOW_LINK_VID) != 0 ? 1600 flow_desc.fd_vid : VLAN_ID_NONE; 1601 1602 /* 1603 * We don't call mac_multicast_add()/mac_multicast_remove() as 1604 * we want to add/remove for this specific vid. 1605 */ 1606 if (add) { 1607 return (mac_bcast_add(mcip, addrp, vid, 1608 MAC_ADDRTYPE_MULTICAST)); 1609 } else { 1610 mac_bcast_delete(mcip, addrp, vid); 1611 return (0); 1612 } 1613 } 1614 1615 static void 1616 mac_update_single_active_client(mac_impl_t *mip) 1617 { 1618 mac_client_impl_t *client = NULL; 1619 1620 ASSERT(MAC_PERIM_HELD((mac_handle_t)mip)); 1621 1622 rw_enter(&mip->mi_rw_lock, RW_WRITER); 1623 if (mip->mi_nactiveclients == 1) { 1624 /* 1625 * Find the one active MAC client from the list of MAC 1626 * clients. The active MAC client has at least one 1627 * unicast address. 1628 */ 1629 for (client = mip->mi_clients_list; client != NULL; 1630 client = client->mci_client_next) { 1631 if (client->mci_unicast_list != NULL) 1632 break; 1633 } 1634 ASSERT(client != NULL); 1635 } 1636 1637 /* 1638 * mi_single_active_client is protected by the MAC impl's read/writer 1639 * lock, which allows mac_rx() to check the value of that pointer 1640 * as a reader. 1641 */ 1642 mip->mi_single_active_client = client; 1643 rw_exit(&mip->mi_rw_lock); 1644 } 1645 1646 /* 1647 * Set up the data path. Called from i_mac_unicast_add after having 1648 * done all the validations including making sure this is an active 1649 * client (i.e that is ready to process packets.) 1650 */ 1651 static int 1652 mac_client_datapath_setup(mac_client_impl_t *mcip, uint16_t vid, 1653 uint8_t *mac_addr, mac_resource_props_t *mrp, boolean_t isprimary, 1654 mac_unicast_impl_t *muip) 1655 { 1656 mac_impl_t *mip = mcip->mci_mip; 1657 boolean_t mac_started = B_FALSE; 1658 boolean_t bcast_added = B_FALSE; 1659 boolean_t nactiveclients_added = B_FALSE; 1660 flow_entry_t *flent; 1661 int err = 0; 1662 1663 if ((err = mac_start((mac_handle_t)mip)) != 0) 1664 goto bail; 1665 1666 mac_started = B_TRUE; 1667 1668 /* add the MAC client to the broadcast address group by default */ 1669 if (mip->mi_type->mt_brdcst_addr != NULL) { 1670 err = mac_bcast_add(mcip, mip->mi_type->mt_brdcst_addr, vid, 1671 MAC_ADDRTYPE_BROADCAST); 1672 if (err != 0) 1673 goto bail; 1674 bcast_added = B_TRUE; 1675 } 1676 1677 /* 1678 * If this is the first unicast address addition for this 1679 * client, reuse the pre-allocated larval flow entry associated with 1680 * the MAC client. 1681 */ 1682 flent = (mcip->mci_nflents == 0) ? mcip->mci_flent : NULL; 1683 1684 /* We are configuring the unicast flow now */ 1685 if (!MCIP_DATAPATH_SETUP(mcip)) { 1686 1687 MAC_CLIENT_SET_PRIORITY_RANGE(mcip, 1688 (mrp->mrp_mask & MRP_PRIORITY) ? mrp->mrp_priority : 1689 MPL_LINK_DEFAULT); 1690 1691 if ((err = mac_unicast_flow_create(mcip, mac_addr, vid, 1692 isprimary, B_TRUE, &flent, mrp)) != 0) 1693 goto bail; 1694 1695 mip->mi_nactiveclients++; 1696 nactiveclients_added = B_TRUE; 1697 1698 /* 1699 * This will allocate the RX ring group if possible for the 1700 * flow and program the software classifier as needed. 1701 */ 1702 if ((err = mac_datapath_setup(mcip, flent, SRST_LINK)) != 0) 1703 goto bail; 1704 1705 /* 1706 * The unicast MAC address must have been added successfully. 1707 */ 1708 ASSERT(mcip->mci_unicast != NULL); 1709 /* 1710 * Push down the sub-flows that were defined on this link 1711 * hitherto. The flows are added to the active flow table 1712 * and SRS, softrings etc. are created as needed. 1713 */ 1714 mac_link_init_flows((mac_client_handle_t)mcip); 1715 } else { 1716 mac_address_t *map = mcip->mci_unicast; 1717 1718 /* 1719 * A unicast flow already exists for that MAC client, 1720 * this flow must be the same mac address but with 1721 * different VID. It has been checked by mac_addr_in_use(). 1722 * 1723 * We will use the SRS etc. from the mci_flent. Note that 1724 * We don't need to create kstat for this as except for 1725 * the fdesc, everything will be used from in the 1st flent. 1726 */ 1727 1728 if (bcmp(mac_addr, map->ma_addr, map->ma_len) != 0) { 1729 err = EINVAL; 1730 goto bail; 1731 } 1732 1733 if ((err = mac_unicast_flow_create(mcip, mac_addr, vid, 1734 isprimary, B_FALSE, &flent, NULL)) != 0) { 1735 goto bail; 1736 } 1737 if ((err = mac_flow_add(mip->mi_flow_tab, flent)) != 0) { 1738 FLOW_FINAL_REFRELE(flent); 1739 goto bail; 1740 } 1741 1742 /* update the multicast group for this vid */ 1743 mac_client_bcast_refresh(mcip, mac_client_update_mcast, 1744 (void *)flent, B_TRUE); 1745 1746 } 1747 1748 /* populate the shared MAC address */ 1749 muip->mui_map = mcip->mci_unicast; 1750 1751 rw_enter(&mcip->mci_rw_lock, RW_WRITER); 1752 muip->mui_next = mcip->mci_unicast_list; 1753 mcip->mci_unicast_list = muip; 1754 rw_exit(&mcip->mci_rw_lock); 1755 1756 1757 /* 1758 * First add the flent to the flow list of this mcip. Then set 1759 * the mip's mi_single_active_client if needed. The Rx path assumes 1760 * that mip->mi_single_active_client will always have an associated 1761 * flent. 1762 */ 1763 mac_client_add_to_flow_list(mcip, flent); 1764 1765 if (nactiveclients_added) 1766 mac_update_single_active_client(mip); 1767 /* 1768 * Trigger a renegotiation of the capabilities when the number of 1769 * active clients changes from 1 to 2, since some of the capabilities 1770 * might have to be disabled. Also send a MAC_NOTE_LINK notification 1771 * to all the MAC clients whenever physical link is DOWN. 1772 */ 1773 if (mip->mi_nactiveclients == 2) { 1774 mac_capab_update((mac_handle_t)mip); 1775 mac_virtual_link_update(mip); 1776 } 1777 /* 1778 * Now that the setup is complete, clear the INCIPIENT flag. 1779 * The flag was set to avoid incoming packets seeing inconsistent 1780 * structures while the setup was in progress. Clear the mci_tx_flag 1781 * by calling mac_tx_client_block. It is possible that 1782 * mac_unicast_remove was called prior to this mac_unicast_add which 1783 * could have set the MCI_TX_QUIESCE flag. 1784 */ 1785 if (flent->fe_rx_ring_group != NULL) 1786 mac_rx_group_unmark(flent->fe_rx_ring_group, MR_INCIPIENT); 1787 FLOW_UNMARK(flent, FE_INCIPIENT); 1788 FLOW_UNMARK(flent, FE_MC_NO_DATAPATH); 1789 mac_tx_client_unblock(mcip); 1790 return (0); 1791 bail: 1792 if (bcast_added) 1793 mac_bcast_delete(mcip, mip->mi_type->mt_brdcst_addr, vid); 1794 1795 if (nactiveclients_added) 1796 mip->mi_nactiveclients--; 1797 1798 if (mac_started) 1799 mac_stop((mac_handle_t)mip); 1800 1801 return (err); 1802 } 1803 1804 /* 1805 * Return the passive primary MAC client, if present. The passive client is 1806 * a stand-by client that has the same unicast address as another that is 1807 * currenly active. Once the active client goes away, the passive client 1808 * becomes active. 1809 */ 1810 static mac_client_impl_t * 1811 mac_get_passive_primary_client(mac_impl_t *mip) 1812 { 1813 mac_client_impl_t *mcip; 1814 1815 for (mcip = mip->mi_clients_list; mcip != NULL; 1816 mcip = mcip->mci_client_next) { 1817 if (mac_is_primary_client(mcip) && 1818 (mcip->mci_flags & MAC_CLIENT_FLAGS_PASSIVE_PRIMARY) != 0) { 1819 return (mcip); 1820 } 1821 } 1822 return (NULL); 1823 } 1824 1825 /* 1826 * Add a new unicast address to the MAC client. 1827 * 1828 * The MAC address can be specified either by value, or the MAC client 1829 * can specify that it wants to use the primary MAC address of the 1830 * underlying MAC. See the introductory comments at the beginning 1831 * of this file for more more information on primary MAC addresses. 1832 * 1833 * Note also the tuple (MAC address, VID) must be unique 1834 * for the MAC clients defined on top of the same underlying MAC 1835 * instance, unless the MAC_UNICAST_NODUPCHECK is specified. 1836 * 1837 * In no case can a client use the PVID for the MAC, if the MAC has one set. 1838 */ 1839 int 1840 i_mac_unicast_add(mac_client_handle_t mch, uint8_t *mac_addr, uint16_t flags, 1841 mac_unicast_handle_t *mah, uint16_t vid, mac_diag_t *diag) 1842 { 1843 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 1844 mac_impl_t *mip = mcip->mci_mip; 1845 int err; 1846 uint_t mac_len = mip->mi_type->mt_addr_length; 1847 boolean_t check_dups = !(flags & MAC_UNICAST_NODUPCHECK); 1848 boolean_t fastpath_disabled = B_FALSE; 1849 boolean_t is_primary = (flags & MAC_UNICAST_PRIMARY); 1850 boolean_t is_unicast_hw = (flags & MAC_UNICAST_HW); 1851 mac_resource_props_t mrp; 1852 boolean_t passive_client = B_FALSE; 1853 mac_unicast_impl_t *muip; 1854 boolean_t is_vnic_primary = 1855 (flags & MAC_UNICAST_VNIC_PRIMARY); 1856 1857 /* when VID is non-zero, the underlying MAC can not be VNIC */ 1858 ASSERT(!((mip->mi_state_flags & MIS_IS_VNIC) && (vid != 0))); 1859 1860 /* 1861 * Check for an attempted use of the current Port VLAN ID, if enabled. 1862 * No client may use it. 1863 */ 1864 if (mip->mi_pvid != 0 && vid == mip->mi_pvid) 1865 return (EBUSY); 1866 1867 /* 1868 * Check whether it's the primary client and flag it. 1869 */ 1870 if (!(mcip->mci_state_flags & MCIS_IS_VNIC) && is_primary && vid == 0) 1871 mcip->mci_flags |= MAC_CLIENT_FLAGS_PRIMARY; 1872 1873 /* 1874 * is_vnic_primary is true when we come here as a VLAN VNIC 1875 * which uses the primary mac client's address but with a non-zero 1876 * VID. In this case the MAC address is not specified by an upper 1877 * MAC client. 1878 */ 1879 if ((mcip->mci_state_flags & MCIS_IS_VNIC) && is_primary && 1880 !is_vnic_primary) { 1881 /* 1882 * The address is being set by the upper MAC client 1883 * of a VNIC. The MAC address was already set by the 1884 * VNIC driver during VNIC creation. 1885 * 1886 * Note: a VNIC has only one MAC address. We return 1887 * the MAC unicast address handle of the lower MAC client 1888 * corresponding to the VNIC. We allocate a new entry 1889 * which is flagged appropriately, so that mac_unicast_remove() 1890 * doesn't attempt to free the original entry that 1891 * was allocated by the VNIC driver. 1892 */ 1893 ASSERT(mcip->mci_unicast != NULL); 1894 1895 /* Check for VLAN flags, if present */ 1896 if ((flags & MAC_UNICAST_TAG_DISABLE) != 0) 1897 mcip->mci_state_flags |= MCIS_TAG_DISABLE; 1898 1899 if ((flags & MAC_UNICAST_STRIP_DISABLE) != 0) 1900 mcip->mci_state_flags |= MCIS_STRIP_DISABLE; 1901 1902 if ((flags & MAC_UNICAST_DISABLE_TX_VID_CHECK) != 0) 1903 mcip->mci_state_flags |= MCIS_DISABLE_TX_VID_CHECK; 1904 1905 /* 1906 * Ensure that the primary unicast address of the VNIC 1907 * is added only once unless we have the 1908 * MAC_CLIENT_FLAGS_MULTI_PRIMARY set (and this is not 1909 * a passive MAC client). 1910 */ 1911 if ((mcip->mci_flags & MAC_CLIENT_FLAGS_VNIC_PRIMARY) != 0) { 1912 if ((mcip->mci_flags & 1913 MAC_CLIENT_FLAGS_MULTI_PRIMARY) == 0 || 1914 (mcip->mci_flags & 1915 MAC_CLIENT_FLAGS_PASSIVE_PRIMARY) != 0) { 1916 return (EBUSY); 1917 } 1918 mcip->mci_flags |= MAC_CLIENT_FLAGS_PASSIVE_PRIMARY; 1919 passive_client = B_TRUE; 1920 } 1921 1922 mcip->mci_flags |= MAC_CLIENT_FLAGS_VNIC_PRIMARY; 1923 1924 /* 1925 * Create a handle for vid 0. 1926 */ 1927 ASSERT(vid == 0); 1928 muip = kmem_zalloc(sizeof (mac_unicast_impl_t), KM_SLEEP); 1929 muip->mui_vid = vid; 1930 *mah = (mac_unicast_handle_t)muip; 1931 /* 1932 * This will be used by the caller to defer setting the 1933 * rx functions. 1934 */ 1935 if (passive_client) 1936 return (EAGAIN); 1937 return (0); 1938 } 1939 1940 /* primary MAC clients cannot be opened on top of anchor VNICs */ 1941 if ((is_vnic_primary || is_primary) && 1942 i_mac_capab_get((mac_handle_t)mip, MAC_CAPAB_ANCHOR_VNIC, NULL)) { 1943 return (ENXIO); 1944 } 1945 1946 /* 1947 * If this is a VNIC/VLAN, disable softmac fast-path. 1948 */ 1949 if (mcip->mci_state_flags & MCIS_IS_VNIC) { 1950 err = mac_fastpath_disable((mac_handle_t)mip); 1951 if (err != 0) 1952 return (err); 1953 fastpath_disabled = B_TRUE; 1954 } 1955 1956 /* 1957 * Return EBUSY if: 1958 * - there is an exclusively active mac client exists. 1959 * - this is an exclusive active mac client but 1960 * a. there is already active mac clients exist, or 1961 * b. fastpath streams are already plumbed on this legacy device 1962 * - the mac creator has disallowed active mac clients. 1963 */ 1964 if (mip->mi_state_flags & (MIS_EXCLUSIVE|MIS_NO_ACTIVE)) { 1965 if (fastpath_disabled) 1966 mac_fastpath_enable((mac_handle_t)mip); 1967 return (EBUSY); 1968 } 1969 1970 if (mcip->mci_state_flags & MCIS_EXCLUSIVE) { 1971 ASSERT(!fastpath_disabled); 1972 if (mip->mi_nactiveclients != 0) 1973 return (EBUSY); 1974 1975 if ((mip->mi_state_flags & MIS_LEGACY) && 1976 !(mip->mi_capab_legacy.ml_active_set(mip->mi_driver))) { 1977 return (EBUSY); 1978 } 1979 mip->mi_state_flags |= MIS_EXCLUSIVE; 1980 } 1981 1982 bzero(&mrp, sizeof (mac_resource_props_t)); 1983 if (is_primary && !(mcip->mci_state_flags & (MCIS_IS_VNIC | 1984 MCIS_IS_AGGR_PORT))) { 1985 /* 1986 * Apply the property cached in the mac_impl_t to the primary 1987 * mac client. If the mac client is a VNIC or an aggregation 1988 * port, its property should be set in the mcip when the 1989 * VNIC/aggr was created. 1990 */ 1991 mac_get_resources((mac_handle_t)mip, &mrp); 1992 (void) mac_client_set_resources(mch, &mrp); 1993 } else if (mcip->mci_state_flags & MCIS_IS_VNIC) { 1994 bcopy(MCIP_RESOURCE_PROPS(mcip), &mrp, 1995 sizeof (mac_resource_props_t)); 1996 } 1997 1998 muip = kmem_zalloc(sizeof (mac_unicast_impl_t), KM_SLEEP); 1999 muip->mui_vid = vid; 2000 2001 if (is_primary || is_vnic_primary) { 2002 mac_addr = mip->mi_addr; 2003 } else { 2004 2005 /* 2006 * Verify the validity of the specified MAC addresses value. 2007 */ 2008 if (!mac_unicst_verify((mac_handle_t)mip, mac_addr, mac_len)) { 2009 *diag = MAC_DIAG_MACADDR_INVALID; 2010 err = EINVAL; 2011 goto bail_out; 2012 } 2013 2014 /* 2015 * Make sure that the specified MAC address is different 2016 * than the unicast MAC address of the underlying NIC. 2017 */ 2018 if (check_dups && bcmp(mip->mi_addr, mac_addr, mac_len) == 0) { 2019 *diag = MAC_DIAG_MACADDR_NIC; 2020 err = EINVAL; 2021 goto bail_out; 2022 } 2023 } 2024 2025 /* 2026 * Set the flags here so that if this is a passive client, we 2027 * can return and set it when we call mac_client_datapath_setup 2028 * when this becomes the active client. If we defer to using these 2029 * flags to mac_client_datapath_setup, then for a passive client, 2030 * we'd have to store the flags somewhere (probably fe_flags) 2031 * and then use it. 2032 */ 2033 if (!MCIP_DATAPATH_SETUP(mcip)) { 2034 if (is_unicast_hw) { 2035 /* 2036 * The client requires a hardware MAC address slot 2037 * for that unicast address. Since we support only 2038 * one unicast MAC address per client, flag the 2039 * MAC client itself. 2040 */ 2041 mcip->mci_state_flags |= MCIS_UNICAST_HW; 2042 } 2043 2044 /* Check for VLAN flags, if present */ 2045 if ((flags & MAC_UNICAST_TAG_DISABLE) != 0) 2046 mcip->mci_state_flags |= MCIS_TAG_DISABLE; 2047 2048 if ((flags & MAC_UNICAST_STRIP_DISABLE) != 0) 2049 mcip->mci_state_flags |= MCIS_STRIP_DISABLE; 2050 2051 if ((flags & MAC_UNICAST_DISABLE_TX_VID_CHECK) != 0) 2052 mcip->mci_state_flags |= MCIS_DISABLE_TX_VID_CHECK; 2053 } else { 2054 /* 2055 * Assert that the specified flags are consistent with the 2056 * flags specified by previous calls to mac_unicast_add(). 2057 */ 2058 ASSERT(((flags & MAC_UNICAST_TAG_DISABLE) != 0 && 2059 (mcip->mci_state_flags & MCIS_TAG_DISABLE) != 0) || 2060 ((flags & MAC_UNICAST_TAG_DISABLE) == 0 && 2061 (mcip->mci_state_flags & MCIS_TAG_DISABLE) == 0)); 2062 2063 ASSERT(((flags & MAC_UNICAST_STRIP_DISABLE) != 0 && 2064 (mcip->mci_state_flags & MCIS_STRIP_DISABLE) != 0) || 2065 ((flags & MAC_UNICAST_STRIP_DISABLE) == 0 && 2066 (mcip->mci_state_flags & MCIS_STRIP_DISABLE) == 0)); 2067 2068 ASSERT(((flags & MAC_UNICAST_DISABLE_TX_VID_CHECK) != 0 && 2069 (mcip->mci_state_flags & MCIS_DISABLE_TX_VID_CHECK) != 0) || 2070 ((flags & MAC_UNICAST_DISABLE_TX_VID_CHECK) == 0 && 2071 (mcip->mci_state_flags & MCIS_DISABLE_TX_VID_CHECK) == 0)); 2072 2073 /* 2074 * Make sure the client is consistent about its requests 2075 * for MAC addresses. I.e. all requests from the clients 2076 * must have the MAC_UNICAST_HW flag set or clear. 2077 */ 2078 if ((mcip->mci_state_flags & MCIS_UNICAST_HW) != 0 && 2079 !is_unicast_hw || 2080 (mcip->mci_state_flags & MCIS_UNICAST_HW) == 0 && 2081 is_unicast_hw) { 2082 err = EINVAL; 2083 goto bail_out; 2084 } 2085 } 2086 /* 2087 * Make sure the MAC address is not already used by 2088 * another MAC client defined on top of the same 2089 * underlying NIC. Unless we have MAC_CLIENT_FLAGS_MULTI_PRIMARY 2090 * set when we allow a passive client to be present which will 2091 * be activated when the currently active client goes away - this 2092 * works only with primary addresses. 2093 */ 2094 if ((check_dups || is_primary || is_vnic_primary) && 2095 mac_addr_in_use(mip, mac_addr, vid)) { 2096 /* 2097 * Must have set the multiple primary address flag when 2098 * we did a mac_client_open AND this should be a primary 2099 * MAC client AND there should not already be a passive 2100 * primary. If all is true then we let this succeed 2101 * even if the address is a dup. 2102 */ 2103 if ((mcip->mci_flags & MAC_CLIENT_FLAGS_MULTI_PRIMARY) == 0 || 2104 (mcip->mci_flags & MAC_CLIENT_FLAGS_PRIMARY) == 0 || 2105 mac_get_passive_primary_client(mip) != NULL) { 2106 *diag = MAC_DIAG_MACADDR_INUSE; 2107 err = EEXIST; 2108 goto bail_out; 2109 } 2110 ASSERT((mcip->mci_flags & 2111 MAC_CLIENT_FLAGS_PASSIVE_PRIMARY) == 0); 2112 mcip->mci_flags |= MAC_CLIENT_FLAGS_PASSIVE_PRIMARY; 2113 2114 /* 2115 * Stash the unicast address handle, we will use it when 2116 * we set up the passive client. 2117 */ 2118 mcip->mci_p_unicast_list = muip; 2119 *mah = (mac_unicast_handle_t)muip; 2120 return (0); 2121 } 2122 2123 err = mac_client_datapath_setup(mcip, vid, mac_addr, &mrp, 2124 is_primary || is_vnic_primary, muip); 2125 if (err != 0) 2126 goto bail_out; 2127 *mah = (mac_unicast_handle_t)muip; 2128 return (0); 2129 2130 bail_out: 2131 if (fastpath_disabled) 2132 mac_fastpath_enable((mac_handle_t)mip); 2133 if (mcip->mci_state_flags & MCIS_EXCLUSIVE) { 2134 mip->mi_state_flags &= ~MIS_EXCLUSIVE; 2135 if (mip->mi_state_flags & MIS_LEGACY) { 2136 mip->mi_capab_legacy.ml_active_clear( 2137 mip->mi_driver); 2138 } 2139 } 2140 kmem_free(muip, sizeof (mac_unicast_impl_t)); 2141 return (err); 2142 } 2143 2144 /* 2145 * Wrapper function to mac_unicast_add when we want to have the same mac 2146 * client open for two instances, one that is currently active and another 2147 * that will become active when the current one is removed. In this case 2148 * mac_unicast_add will return EGAIN and we will save the rx function and 2149 * arg which will be used when we activate the passive client in 2150 * mac_unicast_remove. 2151 */ 2152 int 2153 mac_unicast_add_set_rx(mac_client_handle_t mch, uint8_t *mac_addr, 2154 uint16_t flags, mac_unicast_handle_t *mah, uint16_t vid, mac_diag_t *diag, 2155 mac_rx_t rx_fn, void *arg) 2156 { 2157 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 2158 uint_t err; 2159 2160 err = mac_unicast_add(mch, mac_addr, flags, mah, vid, diag); 2161 if (err != 0 && err != EAGAIN) 2162 return (err); 2163 if (err == EAGAIN) { 2164 if (rx_fn != NULL) { 2165 mcip->mci_rx_p_fn = rx_fn; 2166 mcip->mci_rx_p_arg = arg; 2167 } 2168 return (0); 2169 } 2170 if (rx_fn != NULL) 2171 mac_rx_set(mch, rx_fn, arg); 2172 return (err); 2173 } 2174 2175 int 2176 mac_unicast_add(mac_client_handle_t mch, uint8_t *mac_addr, uint16_t flags, 2177 mac_unicast_handle_t *mah, uint16_t vid, mac_diag_t *diag) 2178 { 2179 mac_impl_t *mip = ((mac_client_impl_t *)mch)->mci_mip; 2180 uint_t err; 2181 2182 i_mac_perim_enter(mip); 2183 err = i_mac_unicast_add(mch, mac_addr, flags, mah, vid, diag); 2184 i_mac_perim_exit(mip); 2185 2186 return (err); 2187 } 2188 2189 void 2190 mac_client_datapath_teardown(mac_client_handle_t mch, mac_unicast_impl_t *muip, 2191 flow_entry_t *flent) 2192 { 2193 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 2194 mac_impl_t *mip = mcip->mci_mip; 2195 2196 /* 2197 * We would have initialized subflows etc. only if we brought up 2198 * the primary client and set the unicast unicast address etc. 2199 * Deactivate the flows. The flow entry will be removed from the 2200 * active flow tables, and the associated SRS, softrings etc will 2201 * be deleted. But the flow entry itself won't be destroyed, instead 2202 * it will continue to be archived off the the global flow hash 2203 * list, for a possible future activation when say IP is plumbed 2204 * again. 2205 */ 2206 mac_link_release_flows(mch); 2207 2208 mip->mi_nactiveclients--; 2209 mac_update_single_active_client(mip); 2210 2211 /* Tear down the data path */ 2212 mac_datapath_teardown(mcip, mcip->mci_flent, SRST_LINK); 2213 2214 /* 2215 * Prevent any future access to the flow entry through the mci_flent 2216 * pointer by setting the mci_flent to NULL. Access to mci_flent in 2217 * mac_bcast_send is also under mi_rw_lock. 2218 */ 2219 rw_enter(&mip->mi_rw_lock, RW_WRITER); 2220 flent = mcip->mci_flent; 2221 mac_client_remove_flow_from_list(mcip, flent); 2222 2223 if (mcip->mci_state_flags & MCIS_DESC_LOGGED) 2224 mcip->mci_state_flags &= ~MCIS_DESC_LOGGED; 2225 2226 /* 2227 * This is the last unicast address being removed and there shouldn't 2228 * be any outbound data threads at this point coming down from mac 2229 * clients. We have waited for the data threads to finish before 2230 * starting dld_str_detach. Non-data threads must access TX SRS 2231 * under mi_rw_lock. 2232 */ 2233 rw_exit(&mip->mi_rw_lock); 2234 2235 /* 2236 * Don't use FLOW_MARK with FE_MC_NO_DATAPATH, as the flow might 2237 * contain other flags, such as FE_CONDEMNED, which we need to 2238 * cleared. We don't call mac_flow_cleanup() for this unicast 2239 * flow as we have a already cleaned up SRSs etc. (via the teadown 2240 * path). We just clear the stats and reset the initial callback 2241 * function, the rest will be set when we call mac_flow_create, 2242 * if at all. 2243 */ 2244 mutex_enter(&flent->fe_lock); 2245 ASSERT(flent->fe_refcnt == 1 && flent->fe_mbg == NULL && 2246 flent->fe_tx_srs == NULL && flent->fe_rx_srs_cnt == 0); 2247 flent->fe_flags = FE_MC_NO_DATAPATH; 2248 flow_stat_destroy(flent); 2249 2250 /* Initialize the receiver function to a safe routine */ 2251 flent->fe_cb_fn = (flow_fn_t)mac_pkt_drop; 2252 flent->fe_cb_arg1 = NULL; 2253 flent->fe_cb_arg2 = NULL; 2254 2255 flent->fe_index = -1; 2256 mutex_exit(&flent->fe_lock); 2257 2258 if (mip->mi_type->mt_brdcst_addr != NULL) { 2259 mac_bcast_delete(mcip, mip->mi_type->mt_brdcst_addr, 2260 muip->mui_vid); 2261 } 2262 2263 if (mip->mi_nactiveclients == 1) { 2264 mac_capab_update((mac_handle_t)mip); 2265 mac_virtual_link_update(mip); 2266 } 2267 2268 if (mcip->mci_state_flags & MCIS_EXCLUSIVE) { 2269 mip->mi_state_flags &= ~MIS_EXCLUSIVE; 2270 2271 if (mip->mi_state_flags & MIS_LEGACY) 2272 mip->mi_capab_legacy.ml_active_clear(mip->mi_driver); 2273 } 2274 2275 mcip->mci_state_flags &= ~MCIS_UNICAST_HW; 2276 2277 if (mcip->mci_state_flags & MCIS_TAG_DISABLE) 2278 mcip->mci_state_flags &= ~MCIS_TAG_DISABLE; 2279 2280 if (mcip->mci_state_flags & MCIS_STRIP_DISABLE) 2281 mcip->mci_state_flags &= ~MCIS_STRIP_DISABLE; 2282 2283 if (mcip->mci_state_flags & MCIS_DISABLE_TX_VID_CHECK) 2284 mcip->mci_state_flags &= ~MCIS_DISABLE_TX_VID_CHECK; 2285 2286 kmem_free(muip, sizeof (mac_unicast_impl_t)); 2287 2288 /* 2289 * Disable fastpath if this is a VNIC or a VLAN. 2290 */ 2291 if (mcip->mci_state_flags & MCIS_IS_VNIC) 2292 mac_fastpath_enable((mac_handle_t)mip); 2293 mac_stop((mac_handle_t)mip); 2294 } 2295 2296 /* 2297 * Remove a MAC address which was previously added by mac_unicast_add(). 2298 */ 2299 int 2300 mac_unicast_remove(mac_client_handle_t mch, mac_unicast_handle_t mah) 2301 { 2302 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 2303 mac_unicast_impl_t *muip = (mac_unicast_impl_t *)mah; 2304 mac_unicast_impl_t *pre; 2305 mac_impl_t *mip = mcip->mci_mip; 2306 flow_entry_t *flent; 2307 boolean_t isprimary = B_FALSE; 2308 2309 i_mac_perim_enter(mip); 2310 if (mcip->mci_flags & MAC_CLIENT_FLAGS_VNIC_PRIMARY) { 2311 /* 2312 * Called made by the upper MAC client of a VNIC. 2313 * There's nothing much to do, the unicast address will 2314 * be removed by the VNIC driver when the VNIC is deleted, 2315 * but let's ensure that all our transmit is done before 2316 * the client does a mac_client_stop lest it trigger an 2317 * assert in the driver. 2318 */ 2319 ASSERT(muip->mui_vid == 0); 2320 2321 mac_tx_client_flush(mcip); 2322 2323 if ((mcip->mci_flags & MAC_CLIENT_FLAGS_PASSIVE_PRIMARY) != 0) { 2324 mcip->mci_flags &= ~MAC_CLIENT_FLAGS_PASSIVE_PRIMARY; 2325 if (mcip->mci_rx_p_fn != NULL) { 2326 mac_rx_set(mch, mcip->mci_rx_p_fn, 2327 mcip->mci_rx_p_arg); 2328 mcip->mci_rx_p_fn = NULL; 2329 mcip->mci_rx_p_arg = NULL; 2330 } 2331 kmem_free(muip, sizeof (mac_unicast_impl_t)); 2332 i_mac_perim_exit(mip); 2333 return (0); 2334 } 2335 mcip->mci_flags &= ~MAC_CLIENT_FLAGS_VNIC_PRIMARY; 2336 2337 if (mcip->mci_state_flags & MCIS_TAG_DISABLE) 2338 mcip->mci_state_flags &= ~MCIS_TAG_DISABLE; 2339 2340 if (mcip->mci_state_flags & MCIS_STRIP_DISABLE) 2341 mcip->mci_state_flags &= ~MCIS_STRIP_DISABLE; 2342 2343 if (mcip->mci_state_flags & MCIS_DISABLE_TX_VID_CHECK) 2344 mcip->mci_state_flags &= ~MCIS_DISABLE_TX_VID_CHECK; 2345 2346 kmem_free(muip, sizeof (mac_unicast_impl_t)); 2347 i_mac_perim_exit(mip); 2348 return (0); 2349 } 2350 2351 ASSERT(muip != NULL); 2352 2353 /* 2354 * We are removing a passive client, we haven't setup the datapath 2355 * for this yet, so nothing much to do. 2356 */ 2357 if ((mcip->mci_flags & MAC_CLIENT_FLAGS_PASSIVE_PRIMARY) != 0) { 2358 2359 ASSERT((mcip->mci_flent->fe_flags & FE_MC_NO_DATAPATH) != 0); 2360 ASSERT(mcip->mci_p_unicast_list == muip); 2361 2362 mcip->mci_flags &= ~MAC_CLIENT_FLAGS_PASSIVE_PRIMARY; 2363 2364 mcip->mci_p_unicast_list = NULL; 2365 mcip->mci_rx_p_fn = NULL; 2366 mcip->mci_rx_p_arg = NULL; 2367 2368 mcip->mci_state_flags &= ~MCIS_UNICAST_HW; 2369 2370 if (mcip->mci_state_flags & MCIS_TAG_DISABLE) 2371 mcip->mci_state_flags &= ~MCIS_TAG_DISABLE; 2372 2373 if (mcip->mci_state_flags & MCIS_STRIP_DISABLE) 2374 mcip->mci_state_flags &= ~MCIS_STRIP_DISABLE; 2375 2376 if (mcip->mci_state_flags & MCIS_DISABLE_TX_VID_CHECK) 2377 mcip->mci_state_flags &= ~MCIS_DISABLE_TX_VID_CHECK; 2378 2379 kmem_free(muip, sizeof (mac_unicast_impl_t)); 2380 i_mac_perim_exit(mip); 2381 return (0); 2382 } 2383 /* 2384 * Remove the VID from the list of client's VIDs. 2385 */ 2386 pre = mcip->mci_unicast_list; 2387 if (muip == pre) { 2388 mcip->mci_unicast_list = muip->mui_next; 2389 } else { 2390 while ((pre->mui_next != NULL) && (pre->mui_next != muip)) 2391 pre = pre->mui_next; 2392 ASSERT(pre->mui_next == muip); 2393 rw_enter(&mcip->mci_rw_lock, RW_WRITER); 2394 pre->mui_next = muip->mui_next; 2395 rw_exit(&mcip->mci_rw_lock); 2396 } 2397 2398 if ((mcip->mci_flags & MAC_CLIENT_FLAGS_PRIMARY) && 2399 muip->mui_vid == 0) { 2400 mcip->mci_flags &= ~MAC_CLIENT_FLAGS_PRIMARY; 2401 isprimary = B_TRUE; 2402 } 2403 if (!mac_client_single_rcvr(mcip)) { 2404 /* 2405 * This MAC client is shared by more than one unicast 2406 * addresses, so we will just remove the flent 2407 * corresponding to the address being removed. We don't invoke 2408 * mac_rx_classify_flow_rem() since the additional flow is 2409 * not associated with its own separate set of SRS and rings, 2410 * and these constructs are still needed for the remaining 2411 * flows. 2412 */ 2413 flent = mac_client_get_flow(mcip, muip); 2414 ASSERT(flent != NULL); 2415 2416 /* 2417 * The first one is disappearing, need to make sure 2418 * we replace it with another from the list of 2419 * shared clients. 2420 */ 2421 if (flent == mcip->mci_flent) 2422 flent = mac_client_swap_mciflent(mcip); 2423 mac_client_remove_flow_from_list(mcip, flent); 2424 mac_flow_remove(mip->mi_flow_tab, flent, B_FALSE); 2425 mac_flow_wait(flent, FLOW_DRIVER_UPCALL); 2426 2427 /* 2428 * The multicast groups that were added by the client so 2429 * far must be removed from the brodcast domain corresponding 2430 * to the VID being removed. 2431 */ 2432 mac_client_bcast_refresh(mcip, mac_client_update_mcast, 2433 (void *)flent, B_FALSE); 2434 2435 if (mip->mi_type->mt_brdcst_addr != NULL) { 2436 mac_bcast_delete(mcip, mip->mi_type->mt_brdcst_addr, 2437 muip->mui_vid); 2438 } 2439 2440 FLOW_FINAL_REFRELE(flent); 2441 ASSERT(!(mcip->mci_state_flags & MCIS_EXCLUSIVE)); 2442 /* 2443 * Enable fastpath if this is a VNIC or a VLAN. 2444 */ 2445 if (mcip->mci_state_flags & MCIS_IS_VNIC) 2446 mac_fastpath_enable((mac_handle_t)mip); 2447 mac_stop((mac_handle_t)mip); 2448 i_mac_perim_exit(mip); 2449 return (0); 2450 } 2451 2452 mac_client_datapath_teardown(mch, muip, flent); 2453 2454 /* 2455 * If we are removing the primary, check if we have a passive primary 2456 * client that we need to activate now. 2457 */ 2458 if (!isprimary) { 2459 i_mac_perim_exit(mip); 2460 return (0); 2461 } 2462 mcip = mac_get_passive_primary_client(mip); 2463 if (mcip != NULL) { 2464 mac_resource_props_t mrp; 2465 mac_unicast_impl_t *muip; 2466 2467 mcip->mci_flags &= ~MAC_CLIENT_FLAGS_PASSIVE_PRIMARY; 2468 bzero(&mrp, sizeof (mac_resource_props_t)); 2469 /* 2470 * Apply the property cached in the mac_impl_t to the 2471 * primary mac client. 2472 */ 2473 mac_get_resources((mac_handle_t)mip, &mrp); 2474 (void) mac_client_set_resources(mch, &mrp); 2475 ASSERT(mcip->mci_p_unicast_list != NULL); 2476 muip = mcip->mci_p_unicast_list; 2477 mcip->mci_p_unicast_list = NULL; 2478 if (mac_client_datapath_setup(mcip, VLAN_ID_NONE, 2479 mip->mi_addr, &mrp, B_TRUE, muip) == 0) { 2480 if (mcip->mci_rx_p_fn != NULL) { 2481 mac_rx_set(mch, mcip->mci_rx_p_fn, 2482 mcip->mci_rx_p_arg); 2483 mcip->mci_rx_p_fn = NULL; 2484 mcip->mci_rx_p_arg = NULL; 2485 } 2486 } else { 2487 kmem_free(muip, sizeof (mac_unicast_impl_t)); 2488 } 2489 } 2490 i_mac_perim_exit(mip); 2491 return (0); 2492 } 2493 2494 /* 2495 * Multicast add function invoked by MAC clients. 2496 */ 2497 int 2498 mac_multicast_add(mac_client_handle_t mch, const uint8_t *addr) 2499 { 2500 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 2501 mac_impl_t *mip = mcip->mci_mip; 2502 flow_entry_t *flent = mcip->mci_flent_list; 2503 flow_entry_t *prev_fe = NULL; 2504 uint16_t vid; 2505 int err = 0; 2506 2507 /* Verify the address is a valid multicast address */ 2508 if ((err = mip->mi_type->mt_ops.mtops_multicst_verify(addr, 2509 mip->mi_pdata)) != 0) 2510 return (err); 2511 2512 i_mac_perim_enter(mip); 2513 while (flent != NULL) { 2514 vid = i_mac_flow_vid(flent); 2515 2516 err = mac_bcast_add((mac_client_impl_t *)mch, addr, vid, 2517 MAC_ADDRTYPE_MULTICAST); 2518 if (err != 0) 2519 break; 2520 prev_fe = flent; 2521 flent = flent->fe_client_next; 2522 } 2523 2524 /* 2525 * If we failed adding, then undo all, rather than partial 2526 * success. 2527 */ 2528 if (flent != NULL && prev_fe != NULL) { 2529 flent = mcip->mci_flent_list; 2530 while (flent != prev_fe->fe_client_next) { 2531 vid = i_mac_flow_vid(flent); 2532 mac_bcast_delete((mac_client_impl_t *)mch, addr, vid); 2533 flent = flent->fe_client_next; 2534 } 2535 } 2536 i_mac_perim_exit(mip); 2537 return (err); 2538 } 2539 2540 /* 2541 * Multicast delete function invoked by MAC clients. 2542 */ 2543 void 2544 mac_multicast_remove(mac_client_handle_t mch, const uint8_t *addr) 2545 { 2546 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 2547 mac_impl_t *mip = mcip->mci_mip; 2548 flow_entry_t *flent; 2549 uint16_t vid; 2550 2551 i_mac_perim_enter(mip); 2552 for (flent = mcip->mci_flent_list; flent != NULL; 2553 flent = flent->fe_client_next) { 2554 vid = i_mac_flow_vid(flent); 2555 mac_bcast_delete((mac_client_impl_t *)mch, addr, vid); 2556 } 2557 i_mac_perim_exit(mip); 2558 } 2559 2560 /* 2561 * When a MAC client desires to capture packets on an interface, 2562 * it registers a promiscuous call back with mac_promisc_add(). 2563 * There are three types of promiscuous callbacks: 2564 * 2565 * * MAC_CLIENT_PROMISC_ALL 2566 * Captures all packets sent and received by the MAC client, 2567 * the physical interface, as well as all other MAC clients 2568 * defined on top of the same MAC. 2569 * 2570 * * MAC_CLIENT_PROMISC_FILTERED 2571 * Captures all packets sent and received by the MAC client, 2572 * plus all multicast traffic sent and received by the phyisical 2573 * interface and the other MAC clients. 2574 * 2575 * * MAC_CLIENT_PROMISC_MULTI 2576 * Captures all broadcast and multicast packets sent and 2577 * received by the MAC clients as well as the physical interface. 2578 * 2579 * In all cases, the underlying MAC is put in promiscuous mode. 2580 */ 2581 int 2582 mac_promisc_add(mac_client_handle_t mch, mac_client_promisc_type_t type, 2583 mac_rx_t fn, void *arg, mac_promisc_handle_t *mphp, uint16_t flags) 2584 { 2585 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 2586 mac_impl_t *mip = mcip->mci_mip; 2587 mac_promisc_impl_t *mpip; 2588 mac_cb_info_t *mcbi; 2589 int rc; 2590 2591 i_mac_perim_enter(mip); 2592 2593 if ((rc = mac_start((mac_handle_t)mip)) != 0) { 2594 i_mac_perim_exit(mip); 2595 return (rc); 2596 } 2597 2598 if ((mcip->mci_state_flags & MCIS_IS_VNIC) && 2599 type == MAC_CLIENT_PROMISC_ALL) { 2600 /* 2601 * The function is being invoked by the upper MAC client 2602 * of a VNIC. The VNIC should only see the traffic 2603 * it is entitled to. 2604 */ 2605 type = MAC_CLIENT_PROMISC_FILTERED; 2606 } 2607 2608 2609 /* 2610 * Turn on promiscuous mode for the underlying NIC. 2611 * This is needed even for filtered callbacks which 2612 * expect to receive all multicast traffic on the wire. 2613 * 2614 * Physical promiscuous mode should not be turned on if 2615 * MAC_PROMISC_FLAGS_NO_PHYS is set. 2616 */ 2617 if ((flags & MAC_PROMISC_FLAGS_NO_PHYS) == 0) { 2618 if ((rc = i_mac_promisc_set(mip, B_TRUE)) != 0) { 2619 mac_stop((mac_handle_t)mip); 2620 i_mac_perim_exit(mip); 2621 return (rc); 2622 } 2623 } 2624 2625 mpip = kmem_cache_alloc(mac_promisc_impl_cache, KM_SLEEP); 2626 2627 mpip->mpi_type = type; 2628 mpip->mpi_fn = fn; 2629 mpip->mpi_arg = arg; 2630 mpip->mpi_mcip = mcip; 2631 mpip->mpi_no_tx_loop = ((flags & MAC_PROMISC_FLAGS_NO_TX_LOOP) != 0); 2632 mpip->mpi_no_phys = ((flags & MAC_PROMISC_FLAGS_NO_PHYS) != 0); 2633 mpip->mpi_strip_vlan_tag = 2634 ((flags & MAC_PROMISC_FLAGS_VLAN_TAG_STRIP) != 0); 2635 2636 mcbi = &mip->mi_promisc_cb_info; 2637 mutex_enter(mcbi->mcbi_lockp); 2638 2639 mac_callback_add(&mip->mi_promisc_cb_info, &mcip->mci_promisc_list, 2640 &mpip->mpi_mci_link); 2641 mac_callback_add(&mip->mi_promisc_cb_info, &mip->mi_promisc_list, 2642 &mpip->mpi_mi_link); 2643 2644 mutex_exit(mcbi->mcbi_lockp); 2645 2646 *mphp = (mac_promisc_handle_t)mpip; 2647 i_mac_perim_exit(mip); 2648 return (0); 2649 } 2650 2651 /* 2652 * Remove a multicast address previously aded through mac_promisc_add(). 2653 */ 2654 void 2655 mac_promisc_remove(mac_promisc_handle_t mph) 2656 { 2657 mac_promisc_impl_t *mpip = (mac_promisc_impl_t *)mph; 2658 mac_client_impl_t *mcip = mpip->mpi_mcip; 2659 mac_impl_t *mip = mcip->mci_mip; 2660 mac_cb_info_t *mcbi; 2661 int rv; 2662 2663 i_mac_perim_enter(mip); 2664 2665 /* 2666 * Even if the device can't be reset into normal mode, we still 2667 * need to clear the client promisc callbacks. The client may want 2668 * to close the mac end point and we can't have stale callbacks. 2669 */ 2670 if (!(mpip->mpi_no_phys)) { 2671 if ((rv = i_mac_promisc_set(mip, B_FALSE)) != 0) { 2672 cmn_err(CE_WARN, "%s: failed to switch OFF promiscuous" 2673 " mode because of error 0x%x", mip->mi_name, rv); 2674 } 2675 } 2676 mcbi = &mip->mi_promisc_cb_info; 2677 mutex_enter(mcbi->mcbi_lockp); 2678 if (mac_callback_remove(mcbi, &mip->mi_promisc_list, 2679 &mpip->mpi_mi_link)) { 2680 VERIFY(mac_callback_remove(&mip->mi_promisc_cb_info, 2681 &mcip->mci_promisc_list, &mpip->mpi_mci_link)); 2682 kmem_cache_free(mac_promisc_impl_cache, mpip); 2683 } else { 2684 mac_callback_remove_wait(&mip->mi_promisc_cb_info); 2685 } 2686 mutex_exit(mcbi->mcbi_lockp); 2687 mac_stop((mac_handle_t)mip); 2688 2689 i_mac_perim_exit(mip); 2690 } 2691 2692 /* 2693 * Reference count the number of active Tx threads. MCI_TX_QUIESCE indicates 2694 * that a control operation wants to quiesce the Tx data flow in which case 2695 * we return an error. Holding any of the per cpu locks ensures that the 2696 * mci_tx_flag won't change. 2697 * 2698 * 'CPU' must be accessed just once and used to compute the index into the 2699 * percpu array, and that index must be used for the entire duration of the 2700 * packet send operation. Note that the thread may be preempted and run on 2701 * another cpu any time and so we can't use 'CPU' more than once for the 2702 * operation. 2703 */ 2704 #define MAC_TX_TRY_HOLD(mcip, mytx, error) \ 2705 { \ 2706 (error) = 0; \ 2707 (mytx) = &(mcip)->mci_tx_pcpu[CPU->cpu_seqid & mac_tx_percpu_cnt]; \ 2708 mutex_enter(&(mytx)->pcpu_tx_lock); \ 2709 if (!((mcip)->mci_tx_flag & MCI_TX_QUIESCE)) { \ 2710 (mytx)->pcpu_tx_refcnt++; \ 2711 } else { \ 2712 (error) = -1; \ 2713 } \ 2714 mutex_exit(&(mytx)->pcpu_tx_lock); \ 2715 } 2716 2717 /* 2718 * Release the reference. If needed, signal any control operation waiting 2719 * for Tx quiescence. The wait and signal are always done using the 2720 * mci_tx_pcpu[0]'s lock 2721 */ 2722 #define MAC_TX_RELE(mcip, mytx) { \ 2723 mutex_enter(&(mytx)->pcpu_tx_lock); \ 2724 if (--(mytx)->pcpu_tx_refcnt == 0 && \ 2725 (mcip)->mci_tx_flag & MCI_TX_QUIESCE) { \ 2726 mutex_exit(&(mytx)->pcpu_tx_lock); \ 2727 mutex_enter(&(mcip)->mci_tx_pcpu[0].pcpu_tx_lock); \ 2728 cv_signal(&(mcip)->mci_tx_cv); \ 2729 mutex_exit(&(mcip)->mci_tx_pcpu[0].pcpu_tx_lock); \ 2730 } else { \ 2731 mutex_exit(&(mytx)->pcpu_tx_lock); \ 2732 } \ 2733 } 2734 2735 /* 2736 * Bump the count of the number of active Tx threads. This is maintained as 2737 * a per CPU counter. On (CMT kind of) machines with large number of CPUs, 2738 * a single mci_tx_lock may become contended. However a count of the total 2739 * number of Tx threads per client is needed in order to quiesce the Tx side 2740 * prior to reassigning a Tx ring dynamically to another client. The thread 2741 * that needs to quiesce the Tx traffic grabs all the percpu locks and checks 2742 * the sum of the individual percpu refcnts. Each Tx data thread only grabs 2743 * its own percpu lock and increments its own refcnt. 2744 */ 2745 void * 2746 mac_tx_hold(mac_client_handle_t mch) 2747 { 2748 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 2749 mac_tx_percpu_t *mytx; 2750 int error; 2751 2752 MAC_TX_TRY_HOLD(mcip, mytx, error); 2753 return (error == 0 ? (void *)mytx : NULL); 2754 } 2755 2756 void 2757 mac_tx_rele(mac_client_handle_t mch, void *mytx_handle) 2758 { 2759 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 2760 mac_tx_percpu_t *mytx = mytx_handle; 2761 2762 MAC_TX_RELE(mcip, mytx) 2763 } 2764 2765 /* 2766 * Send function invoked by MAC clients. 2767 */ 2768 mac_tx_cookie_t 2769 mac_tx(mac_client_handle_t mch, mblk_t *mp_chain, uintptr_t hint, 2770 uint16_t flag, mblk_t **ret_mp) 2771 { 2772 mac_tx_cookie_t cookie; 2773 int error; 2774 mac_tx_percpu_t *mytx; 2775 mac_soft_ring_set_t *srs; 2776 flow_entry_t *flent; 2777 boolean_t is_subflow = B_FALSE; 2778 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 2779 mac_impl_t *mip = mcip->mci_mip; 2780 mac_srs_tx_t *srs_tx; 2781 2782 /* 2783 * Check whether the active Tx threads count is bumped already. 2784 */ 2785 if (!(flag & MAC_TX_NO_HOLD)) { 2786 MAC_TX_TRY_HOLD(mcip, mytx, error); 2787 if (error != 0) { 2788 freemsgchain(mp_chain); 2789 return (NULL); 2790 } 2791 } 2792 2793 if (mcip->mci_subflow_tab != NULL && 2794 mcip->mci_subflow_tab->ft_flow_count > 0 && 2795 mac_flow_lookup(mcip->mci_subflow_tab, mp_chain, 2796 FLOW_OUTBOUND, &flent) == 0) { 2797 /* 2798 * The main assumption here is that if in the event 2799 * we get a chain, all the packets will be classified 2800 * to the same Flow/SRS. If this changes for any 2801 * reason, the following logic should change as well. 2802 * I suppose the fanout_hint also assumes this . 2803 */ 2804 ASSERT(flent != NULL); 2805 is_subflow = B_TRUE; 2806 } else { 2807 flent = mcip->mci_flent; 2808 } 2809 2810 srs = flent->fe_tx_srs; 2811 srs_tx = &srs->srs_tx; 2812 if (srs_tx->st_mode == SRS_TX_DEFAULT && 2813 (srs->srs_state & SRS_ENQUEUED) == 0 && 2814 mip->mi_nactiveclients == 1 && mip->mi_promisc_list == NULL && 2815 mp_chain->b_next == NULL) { 2816 uint64_t obytes; 2817 2818 /* 2819 * Since dls always opens the underlying MAC, nclients equals 2820 * to 1 means that the only active client is dls itself acting 2821 * as a primary client of the MAC instance. Since dls will not 2822 * send tagged packets in that case, and dls is trusted to send 2823 * packets for its allowed VLAN(s), the VLAN tag insertion and 2824 * check is required only if nclients is greater than 1. 2825 */ 2826 if (mip->mi_nclients > 1) { 2827 if (MAC_VID_CHECK_NEEDED(mcip)) { 2828 int err = 0; 2829 2830 MAC_VID_CHECK(mcip, mp_chain, err); 2831 if (err != 0) { 2832 freemsg(mp_chain); 2833 mcip->mci_stat_oerrors++; 2834 goto done; 2835 } 2836 } 2837 if (MAC_TAG_NEEDED(mcip)) { 2838 mp_chain = mac_add_vlan_tag(mp_chain, 0, 2839 mac_client_vid(mch)); 2840 if (mp_chain == NULL) { 2841 mcip->mci_stat_oerrors++; 2842 goto done; 2843 } 2844 } 2845 } 2846 2847 obytes = (mp_chain->b_cont == NULL ? MBLKL(mp_chain) : 2848 msgdsize(mp_chain)); 2849 2850 MAC_TX(mip, srs_tx->st_arg2, mp_chain, 2851 ((mcip->mci_state_flags & MCIS_SHARE_BOUND) != 0)); 2852 2853 if (mp_chain == NULL) { 2854 cookie = NULL; 2855 mcip->mci_stat_obytes += obytes; 2856 mcip->mci_stat_opackets += 1; 2857 if ((srs->srs_type & SRST_FLOW) != 0) { 2858 FLOW_STAT_UPDATE(flent, obytes, obytes); 2859 FLOW_STAT_UPDATE(flent, opackets, 1); 2860 } 2861 } else { 2862 mutex_enter(&srs->srs_lock); 2863 cookie = mac_tx_srs_no_desc(srs, mp_chain, 2864 flag, ret_mp); 2865 mutex_exit(&srs->srs_lock); 2866 } 2867 } else { 2868 cookie = srs_tx->st_func(srs, mp_chain, hint, flag, ret_mp); 2869 } 2870 2871 done: 2872 if (is_subflow) 2873 FLOW_REFRELE(flent); 2874 2875 if (!(flag & MAC_TX_NO_HOLD)) 2876 MAC_TX_RELE(mcip, mytx); 2877 2878 return (cookie); 2879 } 2880 2881 /* 2882 * mac_tx_is_blocked 2883 * 2884 * Given a cookie, it returns if the ring identified by the cookie is 2885 * flow-controlled or not. If NULL is passed in place of a cookie, 2886 * then it finds out if any of the underlying rings belonging to the 2887 * SRS is flow controlled or not and returns that status. 2888 */ 2889 /* ARGSUSED */ 2890 boolean_t 2891 mac_tx_is_flow_blocked(mac_client_handle_t mch, mac_tx_cookie_t cookie) 2892 { 2893 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 2894 mac_soft_ring_set_t *mac_srs; 2895 mac_soft_ring_t *sringp; 2896 boolean_t blocked = B_FALSE; 2897 mac_tx_percpu_t *mytx; 2898 int err; 2899 int i; 2900 2901 /* 2902 * Bump the reference count so that mac_srs won't be deleted. 2903 * If the client is currently quiesced and we failed to bump 2904 * the reference, return B_TRUE so that flow control stays 2905 * as enabled. 2906 * 2907 * Flow control will then be disabled once the client is no 2908 * longer quiesced. 2909 */ 2910 MAC_TX_TRY_HOLD(mcip, mytx, err); 2911 if (err != 0) 2912 return (B_TRUE); 2913 2914 if ((mac_srs = MCIP_TX_SRS(mcip)) == NULL) { 2915 MAC_TX_RELE(mcip, mytx); 2916 return (B_FALSE); 2917 } 2918 2919 mutex_enter(&mac_srs->srs_lock); 2920 if (mac_srs->srs_tx.st_mode == SRS_TX_FANOUT) { 2921 if (cookie != NULL) { 2922 sringp = (mac_soft_ring_t *)cookie; 2923 mutex_enter(&sringp->s_ring_lock); 2924 if (sringp->s_ring_state & S_RING_TX_HIWAT) 2925 blocked = B_TRUE; 2926 mutex_exit(&sringp->s_ring_lock); 2927 } else { 2928 for (i = 0; i < mac_srs->srs_oth_ring_count; i++) { 2929 sringp = mac_srs->srs_oth_soft_rings[i]; 2930 mutex_enter(&sringp->s_ring_lock); 2931 if (sringp->s_ring_state & S_RING_TX_HIWAT) { 2932 blocked = B_TRUE; 2933 mutex_exit(&sringp->s_ring_lock); 2934 break; 2935 } 2936 mutex_exit(&sringp->s_ring_lock); 2937 } 2938 } 2939 } else { 2940 blocked = (mac_srs->srs_state & SRS_TX_HIWAT); 2941 } 2942 mutex_exit(&mac_srs->srs_lock); 2943 MAC_TX_RELE(mcip, mytx); 2944 return (blocked); 2945 } 2946 2947 /* 2948 * Check if the MAC client is the primary MAC client. 2949 */ 2950 boolean_t 2951 mac_is_primary_client(mac_client_impl_t *mcip) 2952 { 2953 return (mcip->mci_flags & MAC_CLIENT_FLAGS_PRIMARY); 2954 } 2955 2956 void 2957 mac_ioctl(mac_handle_t mh, queue_t *wq, mblk_t *bp) 2958 { 2959 mac_impl_t *mip = (mac_impl_t *)mh; 2960 int cmd = ((struct iocblk *)bp->b_rptr)->ioc_cmd; 2961 2962 if ((cmd == ND_GET && (mip->mi_callbacks->mc_callbacks & MC_GETPROP)) || 2963 (cmd == ND_SET && (mip->mi_callbacks->mc_callbacks & MC_SETPROP))) { 2964 /* 2965 * If ndd props were registered, call them. 2966 * Note that ndd ioctls are Obsolete 2967 */ 2968 mac_ndd_ioctl(mip, wq, bp); 2969 return; 2970 } 2971 2972 /* 2973 * Call the driver to handle the ioctl. The driver may not support 2974 * any ioctls, in which case we reply with a NAK on its behalf. 2975 */ 2976 if (mip->mi_callbacks->mc_callbacks & MC_IOCTL) 2977 mip->mi_ioctl(mip->mi_driver, wq, bp); 2978 else 2979 miocnak(wq, bp, 0, EINVAL); 2980 } 2981 2982 /* 2983 * Return the link state of the specified MAC instance. 2984 */ 2985 link_state_t 2986 mac_link_get(mac_handle_t mh) 2987 { 2988 return (((mac_impl_t *)mh)->mi_linkstate); 2989 } 2990 2991 /* 2992 * Add a mac client specified notification callback. Please see the comments 2993 * above mac_callback_add() for general information about mac callback 2994 * addition/deletion in the presence of mac callback list walkers 2995 */ 2996 mac_notify_handle_t 2997 mac_notify_add(mac_handle_t mh, mac_notify_t notify_fn, void *arg) 2998 { 2999 mac_impl_t *mip = (mac_impl_t *)mh; 3000 mac_notify_cb_t *mncb; 3001 mac_cb_info_t *mcbi; 3002 3003 /* 3004 * Allocate a notify callback structure, fill in the details and 3005 * use the mac callback list manipulation functions to chain into 3006 * the list of callbacks. 3007 */ 3008 mncb = kmem_zalloc(sizeof (mac_notify_cb_t), KM_SLEEP); 3009 mncb->mncb_fn = notify_fn; 3010 mncb->mncb_arg = arg; 3011 mncb->mncb_mip = mip; 3012 mncb->mncb_link.mcb_objp = mncb; 3013 mncb->mncb_link.mcb_objsize = sizeof (mac_notify_cb_t); 3014 mncb->mncb_link.mcb_flags = MCB_NOTIFY_CB_T; 3015 3016 mcbi = &mip->mi_notify_cb_info; 3017 3018 i_mac_perim_enter(mip); 3019 mutex_enter(mcbi->mcbi_lockp); 3020 3021 mac_callback_add(&mip->mi_notify_cb_info, &mip->mi_notify_cb_list, 3022 &mncb->mncb_link); 3023 3024 mutex_exit(mcbi->mcbi_lockp); 3025 i_mac_perim_exit(mip); 3026 return ((mac_notify_handle_t)mncb); 3027 } 3028 3029 void 3030 mac_notify_remove_wait(mac_handle_t mh) 3031 { 3032 mac_impl_t *mip = (mac_impl_t *)mh; 3033 mac_cb_info_t *mcbi = &mip->mi_notify_cb_info; 3034 3035 mutex_enter(mcbi->mcbi_lockp); 3036 mac_callback_remove_wait(&mip->mi_notify_cb_info); 3037 mutex_exit(mcbi->mcbi_lockp); 3038 } 3039 3040 /* 3041 * Remove a mac client specified notification callback 3042 */ 3043 int 3044 mac_notify_remove(mac_notify_handle_t mnh, boolean_t wait) 3045 { 3046 mac_notify_cb_t *mncb = (mac_notify_cb_t *)mnh; 3047 mac_impl_t *mip = mncb->mncb_mip; 3048 mac_cb_info_t *mcbi; 3049 int err = 0; 3050 3051 mcbi = &mip->mi_notify_cb_info; 3052 3053 i_mac_perim_enter(mip); 3054 mutex_enter(mcbi->mcbi_lockp); 3055 3056 ASSERT(mncb->mncb_link.mcb_objp == mncb); 3057 /* 3058 * If there aren't any list walkers, the remove would succeed 3059 * inline, else we wait for the deferred remove to complete 3060 */ 3061 if (mac_callback_remove(&mip->mi_notify_cb_info, 3062 &mip->mi_notify_cb_list, &mncb->mncb_link)) { 3063 kmem_free(mncb, sizeof (mac_notify_cb_t)); 3064 } else { 3065 err = EBUSY; 3066 } 3067 3068 mutex_exit(mcbi->mcbi_lockp); 3069 i_mac_perim_exit(mip); 3070 3071 /* 3072 * If we failed to remove the notification callback and "wait" is set 3073 * to be B_TRUE, wait for the callback to finish after we exit the 3074 * mac perimeter. 3075 */ 3076 if (err != 0 && wait) { 3077 mac_notify_remove_wait((mac_handle_t)mip); 3078 return (0); 3079 } 3080 3081 return (err); 3082 } 3083 3084 /* 3085 * Associate resource management callbacks with the specified MAC 3086 * clients. 3087 */ 3088 3089 void 3090 mac_resource_set_common(mac_client_handle_t mch, mac_resource_add_t add, 3091 mac_resource_remove_t remove, mac_resource_quiesce_t quiesce, 3092 mac_resource_restart_t restart, mac_resource_bind_t bind, 3093 void *arg) 3094 { 3095 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 3096 3097 mcip->mci_resource_add = add; 3098 mcip->mci_resource_remove = remove; 3099 mcip->mci_resource_quiesce = quiesce; 3100 mcip->mci_resource_restart = restart; 3101 mcip->mci_resource_bind = bind; 3102 mcip->mci_resource_arg = arg; 3103 3104 if (arg == NULL) 3105 mcip->mci_state_flags &= ~MCIS_CLIENT_POLL_CAPABLE; 3106 } 3107 3108 void 3109 mac_resource_set(mac_client_handle_t mch, mac_resource_add_t add, void *arg) 3110 { 3111 /* update the 'resource_add' callback */ 3112 mac_resource_set_common(mch, add, NULL, NULL, NULL, NULL, arg); 3113 } 3114 3115 /* 3116 * Sets up the client resources and enable the polling interface over all the 3117 * SRS's and the soft rings of the client 3118 */ 3119 void 3120 mac_client_poll_enable(mac_client_handle_t mch) 3121 { 3122 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 3123 mac_soft_ring_set_t *mac_srs; 3124 flow_entry_t *flent; 3125 int i; 3126 3127 flent = mcip->mci_flent; 3128 ASSERT(flent != NULL); 3129 3130 for (i = 0; i < flent->fe_rx_srs_cnt; i++) { 3131 mac_srs = (mac_soft_ring_set_t *)flent->fe_rx_srs[i]; 3132 ASSERT(mac_srs->srs_mcip == mcip); 3133 mac_srs_client_poll_enable(mcip, mac_srs); 3134 } 3135 } 3136 3137 /* 3138 * Tears down the client resources and disable the polling interface over all 3139 * the SRS's and the soft rings of the client 3140 */ 3141 void 3142 mac_client_poll_disable(mac_client_handle_t mch) 3143 { 3144 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 3145 mac_soft_ring_set_t *mac_srs; 3146 flow_entry_t *flent; 3147 int i; 3148 3149 flent = mcip->mci_flent; 3150 ASSERT(flent != NULL); 3151 3152 for (i = 0; i < flent->fe_rx_srs_cnt; i++) { 3153 mac_srs = (mac_soft_ring_set_t *)flent->fe_rx_srs[i]; 3154 ASSERT(mac_srs->srs_mcip == mcip); 3155 mac_srs_client_poll_disable(mcip, mac_srs); 3156 } 3157 } 3158 3159 /* 3160 * Associate the CPUs specified by the given property with a MAC client. 3161 */ 3162 int 3163 mac_cpu_set(mac_client_handle_t mch, mac_resource_props_t *mrp) 3164 { 3165 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 3166 mac_impl_t *mip = mcip->mci_mip; 3167 int err = 0; 3168 3169 ASSERT(MAC_PERIM_HELD((mac_handle_t)mip)); 3170 3171 if ((err = mac_validate_props(mrp)) != 0) 3172 return (err); 3173 3174 if (MCIP_DATAPATH_SETUP(mcip)) 3175 mac_flow_modify(mip->mi_flow_tab, mcip->mci_flent, mrp); 3176 3177 mac_update_resources(mrp, MCIP_RESOURCE_PROPS(mcip), B_FALSE); 3178 return (0); 3179 } 3180 3181 /* 3182 * Apply the specified properties to the specified MAC client. 3183 */ 3184 int 3185 mac_client_set_resources(mac_client_handle_t mch, mac_resource_props_t *mrp) 3186 { 3187 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 3188 mac_impl_t *mip = mcip->mci_mip; 3189 int err = 0; 3190 3191 i_mac_perim_enter(mip); 3192 3193 if ((mrp->mrp_mask & MRP_MAXBW) || (mrp->mrp_mask & MRP_PRIORITY)) { 3194 err = mac_resource_ctl_set(mch, mrp); 3195 if (err != 0) { 3196 i_mac_perim_exit(mip); 3197 return (err); 3198 } 3199 } 3200 3201 if (mrp->mrp_mask & MRP_CPUS) 3202 err = mac_cpu_set(mch, mrp); 3203 3204 i_mac_perim_exit(mip); 3205 return (err); 3206 } 3207 3208 /* 3209 * Return the properties currently associated with the specified MAC client. 3210 */ 3211 void 3212 mac_client_get_resources(mac_client_handle_t mch, mac_resource_props_t *mrp) 3213 { 3214 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 3215 mac_resource_props_t *mcip_mrp = MCIP_RESOURCE_PROPS(mcip); 3216 3217 bcopy(mcip_mrp, mrp, sizeof (mac_resource_props_t)); 3218 } 3219 3220 /* 3221 * Pass a copy of the specified packet to the promiscuous callbacks 3222 * of the specified MAC. 3223 * 3224 * If sender is NULL, the function is being invoked for a packet chain 3225 * received from the wire. If sender is non-NULL, it points to 3226 * the MAC client from which the packet is being sent. 3227 * 3228 * The packets are distributed to the promiscuous callbacks as follows: 3229 * 3230 * - all packets are sent to the MAC_CLIENT_PROMISC_ALL callbacks 3231 * - all broadcast and multicast packets are sent to the 3232 * MAC_CLIENT_PROMISC_FILTER and MAC_CLIENT_PROMISC_MULTI. 3233 * 3234 * The unicast packets of MAC_CLIENT_PROMISC_FILTER callbacks are dispatched 3235 * after classification by mac_rx_deliver(). 3236 */ 3237 3238 static void 3239 mac_promisc_dispatch_one(mac_promisc_impl_t *mpip, mblk_t *mp, 3240 boolean_t loopback) 3241 { 3242 mblk_t *mp_copy; 3243 3244 mp_copy = copymsg(mp); 3245 if (mp_copy == NULL) 3246 return; 3247 mp_copy->b_next = NULL; 3248 3249 if (mpip->mpi_strip_vlan_tag) { 3250 if ((mp_copy = mac_strip_vlan_tag_chain(mp_copy)) == NULL) 3251 return; 3252 } 3253 mpip->mpi_fn(mpip->mpi_arg, NULL, mp_copy, loopback); 3254 } 3255 3256 /* 3257 * Return the VID of a packet. Zero if the packet is not tagged. 3258 */ 3259 static uint16_t 3260 mac_ether_vid(mblk_t *mp) 3261 { 3262 struct ether_header *eth = (struct ether_header *)mp->b_rptr; 3263 3264 if (ntohs(eth->ether_type) == ETHERTYPE_VLAN) { 3265 struct ether_vlan_header *t_evhp = 3266 (struct ether_vlan_header *)mp->b_rptr; 3267 return (VLAN_ID(ntohs(t_evhp->ether_tci))); 3268 } 3269 3270 return (0); 3271 } 3272 3273 /* 3274 * Return whether the specified packet contains a multicast or broadcast 3275 * destination MAC address. 3276 */ 3277 static boolean_t 3278 mac_is_mcast(mac_impl_t *mip, mblk_t *mp) 3279 { 3280 mac_header_info_t hdr_info; 3281 3282 if (mac_header_info((mac_handle_t)mip, mp, &hdr_info) != 0) 3283 return (B_FALSE); 3284 return ((hdr_info.mhi_dsttype == MAC_ADDRTYPE_BROADCAST) || 3285 (hdr_info.mhi_dsttype == MAC_ADDRTYPE_MULTICAST)); 3286 } 3287 3288 /* 3289 * Send a copy of an mblk chain to the MAC clients of the specified MAC. 3290 * "sender" points to the sender MAC client for outbound packets, and 3291 * is set to NULL for inbound packets. 3292 */ 3293 void 3294 mac_promisc_dispatch(mac_impl_t *mip, mblk_t *mp_chain, 3295 mac_client_impl_t *sender) 3296 { 3297 mac_promisc_impl_t *mpip; 3298 mac_cb_t *mcb; 3299 mblk_t *mp; 3300 boolean_t is_mcast, is_sender; 3301 3302 MAC_PROMISC_WALKER_INC(mip); 3303 for (mp = mp_chain; mp != NULL; mp = mp->b_next) { 3304 is_mcast = mac_is_mcast(mip, mp); 3305 /* send packet to interested callbacks */ 3306 for (mcb = mip->mi_promisc_list; mcb != NULL; 3307 mcb = mcb->mcb_nextp) { 3308 mpip = (mac_promisc_impl_t *)mcb->mcb_objp; 3309 is_sender = (mpip->mpi_mcip == sender); 3310 3311 if (is_sender && mpip->mpi_no_tx_loop) 3312 /* 3313 * The sender doesn't want to receive 3314 * copies of the packets it sends. 3315 */ 3316 continue; 3317 3318 /* this client doesn't need any packets (bridge) */ 3319 if (mpip->mpi_fn == NULL) 3320 continue; 3321 3322 /* 3323 * For an ethernet MAC, don't displatch a multicast 3324 * packet to a non-PROMISC_ALL callbacks unless the VID 3325 * of the packet matches the VID of the client. 3326 */ 3327 if (is_mcast && 3328 mpip->mpi_type != MAC_CLIENT_PROMISC_ALL && 3329 !mac_client_check_flow_vid(mpip->mpi_mcip, 3330 mac_ether_vid(mp))) 3331 continue; 3332 3333 if (is_sender || 3334 mpip->mpi_type == MAC_CLIENT_PROMISC_ALL || 3335 is_mcast) 3336 mac_promisc_dispatch_one(mpip, mp, is_sender); 3337 } 3338 } 3339 MAC_PROMISC_WALKER_DCR(mip); 3340 } 3341 3342 void 3343 mac_promisc_client_dispatch(mac_client_impl_t *mcip, mblk_t *mp_chain) 3344 { 3345 mac_impl_t *mip = mcip->mci_mip; 3346 mac_promisc_impl_t *mpip; 3347 boolean_t is_mcast; 3348 mblk_t *mp; 3349 mac_cb_t *mcb; 3350 3351 /* 3352 * The unicast packets for the MAC client still 3353 * need to be delivered to the MAC_CLIENT_PROMISC_FILTERED 3354 * promiscuous callbacks. The broadcast and multicast 3355 * packets were delivered from mac_rx(). 3356 */ 3357 MAC_PROMISC_WALKER_INC(mip); 3358 for (mp = mp_chain; mp != NULL; mp = mp->b_next) { 3359 is_mcast = mac_is_mcast(mip, mp); 3360 for (mcb = mcip->mci_promisc_list; mcb != NULL; 3361 mcb = mcb->mcb_nextp) { 3362 mpip = (mac_promisc_impl_t *)mcb->mcb_objp; 3363 if (mpip->mpi_type == MAC_CLIENT_PROMISC_FILTERED && 3364 !is_mcast) { 3365 mac_promisc_dispatch_one(mpip, mp, B_FALSE); 3366 } 3367 } 3368 } 3369 MAC_PROMISC_WALKER_DCR(mip); 3370 } 3371 3372 /* 3373 * Return the margin value currently assigned to the specified MAC instance. 3374 */ 3375 void 3376 mac_margin_get(mac_handle_t mh, uint32_t *marginp) 3377 { 3378 mac_impl_t *mip = (mac_impl_t *)mh; 3379 3380 rw_enter(&(mip->mi_rw_lock), RW_READER); 3381 *marginp = mip->mi_margin; 3382 rw_exit(&(mip->mi_rw_lock)); 3383 } 3384 3385 /* 3386 * mac_info_get() is used for retrieving the mac_info when a DL_INFO_REQ is 3387 * issued before a DL_ATTACH_REQ. we walk the i_mac_impl_hash table and find 3388 * the first mac_impl_t with a matching driver name; then we copy its mac_info_t 3389 * to the caller. we do all this with i_mac_impl_lock held so the mac_impl_t 3390 * cannot disappear while we are accessing it. 3391 */ 3392 typedef struct i_mac_info_state_s { 3393 const char *mi_name; 3394 mac_info_t *mi_infop; 3395 } i_mac_info_state_t; 3396 3397 /*ARGSUSED*/ 3398 static uint_t 3399 i_mac_info_walker(mod_hash_key_t key, mod_hash_val_t *val, void *arg) 3400 { 3401 i_mac_info_state_t *statep = arg; 3402 mac_impl_t *mip = (mac_impl_t *)val; 3403 3404 if (mip->mi_state_flags & MIS_DISABLED) 3405 return (MH_WALK_CONTINUE); 3406 3407 if (strcmp(statep->mi_name, 3408 ddi_driver_name(mip->mi_dip)) != 0) 3409 return (MH_WALK_CONTINUE); 3410 3411 statep->mi_infop = &mip->mi_info; 3412 return (MH_WALK_TERMINATE); 3413 } 3414 3415 boolean_t 3416 mac_info_get(const char *name, mac_info_t *minfop) 3417 { 3418 i_mac_info_state_t state; 3419 3420 rw_enter(&i_mac_impl_lock, RW_READER); 3421 state.mi_name = name; 3422 state.mi_infop = NULL; 3423 mod_hash_walk(i_mac_impl_hash, i_mac_info_walker, &state); 3424 if (state.mi_infop == NULL) { 3425 rw_exit(&i_mac_impl_lock); 3426 return (B_FALSE); 3427 } 3428 *minfop = *state.mi_infop; 3429 rw_exit(&i_mac_impl_lock); 3430 return (B_TRUE); 3431 } 3432 3433 /* 3434 * To get the capabilities that MAC layer cares about, such as rings, factory 3435 * mac address, vnic or not, it should directly invoke this function. If the 3436 * link is part of a bridge, then the only "capability" it has is the inability 3437 * to do zero copy. 3438 */ 3439 boolean_t 3440 i_mac_capab_get(mac_handle_t mh, mac_capab_t cap, void *cap_data) 3441 { 3442 mac_impl_t *mip = (mac_impl_t *)mh; 3443 3444 if (mip->mi_bridge_link != NULL) 3445 return (cap == MAC_CAPAB_NO_ZCOPY); 3446 else if (mip->mi_callbacks->mc_callbacks & MC_GETCAPAB) 3447 return (mip->mi_getcapab(mip->mi_driver, cap, cap_data)); 3448 else 3449 return (B_FALSE); 3450 } 3451 3452 /* 3453 * Capability query function. If number of active mac clients is greater than 3454 * 1, only limited capabilities can be advertised to the caller no matter the 3455 * driver has certain capability or not. Else, we query the driver to get the 3456 * capability. 3457 */ 3458 boolean_t 3459 mac_capab_get(mac_handle_t mh, mac_capab_t cap, void *cap_data) 3460 { 3461 mac_impl_t *mip = (mac_impl_t *)mh; 3462 3463 /* 3464 * if mi_nactiveclients > 1, only MAC_CAPAB_LEGACY, MAC_CAPAB_HCKSUM, 3465 * MAC_CAPAB_NO_NATIVEVLAN and MAC_CAPAB_NO_ZCOPY can be advertised. 3466 */ 3467 if (mip->mi_nactiveclients > 1) { 3468 switch (cap) { 3469 case MAC_CAPAB_NO_NATIVEVLAN: 3470 case MAC_CAPAB_NO_ZCOPY: 3471 return (B_TRUE); 3472 case MAC_CAPAB_LEGACY: 3473 case MAC_CAPAB_HCKSUM: 3474 break; 3475 default: 3476 return (B_FALSE); 3477 } 3478 } 3479 3480 /* else get capab from driver */ 3481 return (i_mac_capab_get(mh, cap, cap_data)); 3482 } 3483 3484 boolean_t 3485 mac_sap_verify(mac_handle_t mh, uint32_t sap, uint32_t *bind_sap) 3486 { 3487 mac_impl_t *mip = (mac_impl_t *)mh; 3488 3489 return (mip->mi_type->mt_ops.mtops_sap_verify(sap, bind_sap, 3490 mip->mi_pdata)); 3491 } 3492 3493 mblk_t * 3494 mac_header(mac_handle_t mh, const uint8_t *daddr, uint32_t sap, mblk_t *payload, 3495 size_t extra_len) 3496 { 3497 mac_impl_t *mip = (mac_impl_t *)mh; 3498 3499 return (mip->mi_type->mt_ops.mtops_header(mip->mi_addr, daddr, sap, 3500 mip->mi_pdata, payload, extra_len)); 3501 } 3502 3503 int 3504 mac_header_info(mac_handle_t mh, mblk_t *mp, mac_header_info_t *mhip) 3505 { 3506 mac_impl_t *mip = (mac_impl_t *)mh; 3507 3508 return (mip->mi_type->mt_ops.mtops_header_info(mp, mip->mi_pdata, 3509 mhip)); 3510 } 3511 3512 mblk_t * 3513 mac_header_cook(mac_handle_t mh, mblk_t *mp) 3514 { 3515 mac_impl_t *mip = (mac_impl_t *)mh; 3516 3517 if (mip->mi_type->mt_ops.mtops_ops & MTOPS_HEADER_COOK) { 3518 if (DB_REF(mp) > 1) { 3519 mblk_t *newmp = copymsg(mp); 3520 if (newmp == NULL) 3521 return (NULL); 3522 freemsg(mp); 3523 mp = newmp; 3524 } 3525 return (mip->mi_type->mt_ops.mtops_header_cook(mp, 3526 mip->mi_pdata)); 3527 } 3528 return (mp); 3529 } 3530 3531 mblk_t * 3532 mac_header_uncook(mac_handle_t mh, mblk_t *mp) 3533 { 3534 mac_impl_t *mip = (mac_impl_t *)mh; 3535 3536 if (mip->mi_type->mt_ops.mtops_ops & MTOPS_HEADER_UNCOOK) { 3537 if (DB_REF(mp) > 1) { 3538 mblk_t *newmp = copymsg(mp); 3539 if (newmp == NULL) 3540 return (NULL); 3541 freemsg(mp); 3542 mp = newmp; 3543 } 3544 return (mip->mi_type->mt_ops.mtops_header_uncook(mp, 3545 mip->mi_pdata)); 3546 } 3547 return (mp); 3548 } 3549 3550 uint_t 3551 mac_addr_len(mac_handle_t mh) 3552 { 3553 mac_impl_t *mip = (mac_impl_t *)mh; 3554 3555 return (mip->mi_type->mt_addr_length); 3556 } 3557 3558 /* True if a MAC is a VNIC */ 3559 boolean_t 3560 mac_is_vnic(mac_handle_t mh) 3561 { 3562 return (((mac_impl_t *)mh)->mi_state_flags & MIS_IS_VNIC); 3563 } 3564 3565 mac_handle_t 3566 mac_get_lower_mac_handle(mac_handle_t mh) 3567 { 3568 mac_impl_t *mip = (mac_impl_t *)mh; 3569 3570 ASSERT(mac_is_vnic(mh)); 3571 return (((vnic_t *)mip->mi_driver)->vn_lower_mh); 3572 } 3573 3574 void 3575 mac_update_resources(mac_resource_props_t *nmrp, mac_resource_props_t *cmrp, 3576 boolean_t is_user_flow) 3577 { 3578 if (nmrp != NULL && cmrp != NULL) { 3579 if (nmrp->mrp_mask & MRP_PRIORITY) { 3580 if (nmrp->mrp_priority == MPL_RESET) { 3581 cmrp->mrp_mask &= ~MRP_PRIORITY; 3582 if (is_user_flow) { 3583 cmrp->mrp_priority = 3584 MPL_SUBFLOW_DEFAULT; 3585 } else { 3586 cmrp->mrp_priority = MPL_LINK_DEFAULT; 3587 } 3588 } else { 3589 cmrp->mrp_mask |= MRP_PRIORITY; 3590 cmrp->mrp_priority = nmrp->mrp_priority; 3591 } 3592 } 3593 if (nmrp->mrp_mask & MRP_MAXBW) { 3594 cmrp->mrp_maxbw = nmrp->mrp_maxbw; 3595 if (nmrp->mrp_maxbw == MRP_MAXBW_RESETVAL) 3596 cmrp->mrp_mask &= ~MRP_MAXBW; 3597 else 3598 cmrp->mrp_mask |= MRP_MAXBW; 3599 } 3600 if (nmrp->mrp_mask & MRP_CPUS) 3601 MAC_COPY_CPUS(nmrp, cmrp); 3602 } 3603 } 3604 3605 /* 3606 * i_mac_set_resources: 3607 * 3608 * This routine associates properties with the primary MAC client of 3609 * the specified MAC instance. 3610 * - Cache the properties in mac_impl_t 3611 * - Apply the properties to the primary MAC client if exists 3612 */ 3613 int 3614 i_mac_set_resources(mac_handle_t mh, mac_resource_props_t *mrp) 3615 { 3616 mac_impl_t *mip = (mac_impl_t *)mh; 3617 mac_client_impl_t *mcip; 3618 int err = 0; 3619 uint32_t resmask, newresmask; 3620 mac_resource_props_t tmrp, umrp; 3621 3622 ASSERT(MAC_PERIM_HELD((mac_handle_t)mip)); 3623 3624 err = mac_validate_props(mrp); 3625 if (err != 0) 3626 return (err); 3627 3628 bcopy(&mip->mi_resource_props, &umrp, sizeof (mac_resource_props_t)); 3629 resmask = umrp.mrp_mask; 3630 mac_update_resources(mrp, &umrp, B_FALSE); 3631 newresmask = umrp.mrp_mask; 3632 3633 if (resmask == 0 && newresmask != 0) { 3634 /* 3635 * Bandwidth, priority or cpu link properties configured, 3636 * must disable fastpath. 3637 */ 3638 if ((err = mac_fastpath_disable((mac_handle_t)mip)) != 0) 3639 return (err); 3640 } 3641 3642 /* 3643 * Since bind_cpu may be modified by mac_client_set_resources() 3644 * we use a copy of bind_cpu and finally cache bind_cpu in mip. 3645 * This allows us to cache only user edits in mip. 3646 */ 3647 bcopy(mrp, &tmrp, sizeof (mac_resource_props_t)); 3648 mcip = mac_primary_client_handle(mip); 3649 if (mcip != NULL && (mcip->mci_state_flags & MCIS_IS_AGGR_PORT) == 0) { 3650 err = 3651 mac_client_set_resources((mac_client_handle_t)mcip, &tmrp); 3652 } 3653 3654 /* Only update the values if mac_client_set_resources succeeded */ 3655 if (err == 0) { 3656 bcopy(&umrp, &mip->mi_resource_props, 3657 sizeof (mac_resource_props_t)); 3658 /* 3659 * If bankwidth, priority or cpu link properties cleared, 3660 * renable fastpath. 3661 */ 3662 if (resmask != 0 && newresmask == 0) 3663 mac_fastpath_enable((mac_handle_t)mip); 3664 } else if (resmask == 0 && newresmask != 0) { 3665 mac_fastpath_enable((mac_handle_t)mip); 3666 } 3667 return (err); 3668 } 3669 3670 int 3671 mac_set_resources(mac_handle_t mh, mac_resource_props_t *mrp) 3672 { 3673 int err; 3674 3675 i_mac_perim_enter((mac_impl_t *)mh); 3676 err = i_mac_set_resources(mh, mrp); 3677 i_mac_perim_exit((mac_impl_t *)mh); 3678 return (err); 3679 } 3680 3681 /* 3682 * Get the properties cached for the specified MAC instance. 3683 */ 3684 void 3685 mac_get_resources(mac_handle_t mh, mac_resource_props_t *mrp) 3686 { 3687 mac_impl_t *mip = (mac_impl_t *)mh; 3688 mac_client_impl_t *mcip; 3689 3690 if (mip->mi_state_flags & MIS_IS_VNIC) { 3691 mcip = mac_primary_client_handle(mip); 3692 if (mcip != NULL) { 3693 mac_client_get_resources((mac_client_handle_t)mcip, 3694 mrp); 3695 return; 3696 } 3697 } 3698 bcopy(&mip->mi_resource_props, mrp, sizeof (mac_resource_props_t)); 3699 } 3700 3701 int 3702 mac_set_pvid(mac_handle_t mh, uint16_t pvid) 3703 { 3704 mac_impl_t *mip = (mac_impl_t *)mh; 3705 mac_client_impl_t *mcip; 3706 mac_unicast_impl_t *muip; 3707 3708 i_mac_perim_enter(mip); 3709 if (pvid != 0) { 3710 for (mcip = mip->mi_clients_list; mcip != NULL; 3711 mcip = mcip->mci_client_next) { 3712 for (muip = mcip->mci_unicast_list; muip != NULL; 3713 muip = muip->mui_next) { 3714 if (muip->mui_vid == pvid) { 3715 i_mac_perim_exit(mip); 3716 return (EBUSY); 3717 } 3718 } 3719 } 3720 } 3721 mip->mi_pvid = pvid; 3722 i_mac_perim_exit(mip); 3723 return (0); 3724 } 3725 3726 uint16_t 3727 mac_get_pvid(mac_handle_t mh) 3728 { 3729 mac_impl_t *mip = (mac_impl_t *)mh; 3730 3731 return (mip->mi_pvid); 3732 } 3733 3734 uint32_t 3735 mac_get_llimit(mac_handle_t mh) 3736 { 3737 mac_impl_t *mip = (mac_impl_t *)mh; 3738 3739 return (mip->mi_llimit); 3740 } 3741 3742 uint32_t 3743 mac_get_ldecay(mac_handle_t mh) 3744 { 3745 mac_impl_t *mip = (mac_impl_t *)mh; 3746 3747 return (mip->mi_ldecay); 3748 } 3749 3750 /* 3751 * Rename a mac client, its flow, and the kstat. 3752 */ 3753 int 3754 mac_rename_primary(mac_handle_t mh, const char *new_name) 3755 { 3756 mac_impl_t *mip = (mac_impl_t *)mh; 3757 mac_client_impl_t *cur_clnt = NULL; 3758 flow_entry_t *fep; 3759 3760 i_mac_perim_enter(mip); 3761 3762 /* 3763 * VNICs: we need to change the sys flow name and 3764 * the associated flow kstat. 3765 */ 3766 if (mip->mi_state_flags & MIS_IS_VNIC) { 3767 ASSERT(new_name != NULL); 3768 mac_rename_flow_names(mac_vnic_lower(mip), new_name); 3769 goto done; 3770 } 3771 /* 3772 * This mac may itself be an aggr link, or it may have some client 3773 * which is an aggr port. For both cases, we need to change the 3774 * aggr port's mac client name, its flow name and the associated flow 3775 * kstat. 3776 */ 3777 if (mip->mi_state_flags & MIS_IS_AGGR) { 3778 mac_capab_aggr_t aggr_cap; 3779 mac_rename_fn_t rename_fn; 3780 boolean_t ret; 3781 3782 ASSERT(new_name != NULL); 3783 ret = i_mac_capab_get((mac_handle_t)mip, MAC_CAPAB_AGGR, 3784 (void *)(&aggr_cap)); 3785 ASSERT(ret == B_TRUE); 3786 rename_fn = aggr_cap.mca_rename_fn; 3787 rename_fn(new_name, mip->mi_driver); 3788 /* 3789 * The aggr's client name and kstat flow name will be 3790 * updated below, i.e. via mac_rename_flow_names. 3791 */ 3792 } 3793 3794 for (cur_clnt = mip->mi_clients_list; cur_clnt != NULL; 3795 cur_clnt = cur_clnt->mci_client_next) { 3796 if (cur_clnt->mci_state_flags & MCIS_IS_AGGR_PORT) { 3797 if (new_name != NULL) { 3798 char *str_st = cur_clnt->mci_name; 3799 char *str_del = strchr(str_st, '-'); 3800 3801 ASSERT(str_del != NULL); 3802 bzero(str_del + 1, MAXNAMELEN - 3803 (str_del - str_st + 1)); 3804 bcopy(new_name, str_del + 1, 3805 strlen(new_name)); 3806 } 3807 fep = cur_clnt->mci_flent; 3808 mac_rename_flow(fep, cur_clnt->mci_name); 3809 break; 3810 } else if (new_name != NULL && 3811 cur_clnt->mci_state_flags & MCIS_USE_DATALINK_NAME) { 3812 mac_rename_flow_names(cur_clnt, new_name); 3813 break; 3814 } 3815 } 3816 3817 done: 3818 i_mac_perim_exit(mip); 3819 return (0); 3820 } 3821 3822 /* 3823 * Rename the MAC client's flow names 3824 */ 3825 static void 3826 mac_rename_flow_names(mac_client_impl_t *mcip, const char *new_name) 3827 { 3828 flow_entry_t *flent; 3829 uint16_t vid; 3830 char flowname[MAXFLOWNAMELEN]; 3831 mac_impl_t *mip = mcip->mci_mip; 3832 3833 ASSERT(MAC_PERIM_HELD((mac_handle_t)mip)); 3834 3835 /* 3836 * Use mi_rw_lock to ensure that threads not in the mac perimeter 3837 * see a self-consistent value for mci_name 3838 */ 3839 rw_enter(&mip->mi_rw_lock, RW_WRITER); 3840 (void) strlcpy(mcip->mci_name, new_name, sizeof (mcip->mci_name)); 3841 rw_exit(&mip->mi_rw_lock); 3842 3843 mac_rename_flow(mcip->mci_flent, new_name); 3844 3845 if (mcip->mci_nflents == 1) 3846 return; 3847 3848 /* 3849 * We have to rename all the others too, no stats to destroy for 3850 * these. 3851 */ 3852 for (flent = mcip->mci_flent_list; flent != NULL; 3853 flent = flent->fe_client_next) { 3854 if (flent != mcip->mci_flent) { 3855 vid = i_mac_flow_vid(flent); 3856 (void) sprintf(flowname, "%s%u", new_name, vid); 3857 mac_flow_set_name(flent, flowname); 3858 } 3859 } 3860 } 3861 3862 3863 /* 3864 * Add a flow to the MAC client's flow list - i.e list of MAC/VID tuples 3865 * defined for the specified MAC client. 3866 */ 3867 static void 3868 mac_client_add_to_flow_list(mac_client_impl_t *mcip, flow_entry_t *flent) 3869 { 3870 ASSERT(MAC_PERIM_HELD((mac_handle_t)mcip->mci_mip)); 3871 /* 3872 * The promisc Rx data path walks the mci_flent_list. Protect by 3873 * using mi_rw_lock 3874 */ 3875 rw_enter(&mcip->mci_rw_lock, RW_WRITER); 3876 3877 /* Add it to the head */ 3878 flent->fe_client_next = mcip->mci_flent_list; 3879 mcip->mci_flent_list = flent; 3880 mcip->mci_nflents++; 3881 3882 /* 3883 * Keep track of the number of non-zero VIDs addresses per MAC 3884 * client to avoid figuring it out in the data-path. 3885 */ 3886 if (i_mac_flow_vid(flent) != VLAN_ID_NONE) 3887 mcip->mci_nvids++; 3888 3889 rw_exit(&mcip->mci_rw_lock); 3890 } 3891 3892 /* 3893 * Remove a flow entry from the MAC client's list. 3894 */ 3895 static void 3896 mac_client_remove_flow_from_list(mac_client_impl_t *mcip, flow_entry_t *flent) 3897 { 3898 flow_entry_t *fe = mcip->mci_flent_list; 3899 flow_entry_t *prev_fe = NULL; 3900 3901 ASSERT(MAC_PERIM_HELD((mac_handle_t)mcip->mci_mip)); 3902 /* 3903 * The promisc Rx data path walks the mci_flent_list. Protect by 3904 * using mci_rw_lock 3905 */ 3906 rw_enter(&mcip->mci_rw_lock, RW_WRITER); 3907 while ((fe != NULL) && (fe != flent)) { 3908 prev_fe = fe; 3909 fe = fe->fe_client_next; 3910 } 3911 3912 ASSERT(fe != NULL); 3913 if (prev_fe == NULL) { 3914 /* Deleting the first node */ 3915 mcip->mci_flent_list = fe->fe_client_next; 3916 } else { 3917 prev_fe->fe_client_next = fe->fe_client_next; 3918 } 3919 mcip->mci_nflents--; 3920 3921 if (i_mac_flow_vid(flent) != VLAN_ID_NONE) 3922 mcip->mci_nvids--; 3923 3924 rw_exit(&mcip->mci_rw_lock); 3925 } 3926 3927 /* 3928 * Check if the given VID belongs to this MAC client. 3929 */ 3930 boolean_t 3931 mac_client_check_flow_vid(mac_client_impl_t *mcip, uint16_t vid) 3932 { 3933 flow_entry_t *flent; 3934 uint16_t mci_vid; 3935 3936 /* The mci_flent_list is protected by mci_rw_lock */ 3937 rw_enter(&mcip->mci_rw_lock, RW_WRITER); 3938 for (flent = mcip->mci_flent_list; flent != NULL; 3939 flent = flent->fe_client_next) { 3940 mci_vid = i_mac_flow_vid(flent); 3941 if (vid == mci_vid) { 3942 rw_exit(&mcip->mci_rw_lock); 3943 return (B_TRUE); 3944 } 3945 } 3946 rw_exit(&mcip->mci_rw_lock); 3947 return (B_FALSE); 3948 } 3949 3950 /* 3951 * Get the flow entry for the specified <MAC addr, VID> tuple. 3952 */ 3953 static flow_entry_t * 3954 mac_client_get_flow(mac_client_impl_t *mcip, mac_unicast_impl_t *muip) 3955 { 3956 mac_address_t *map = mcip->mci_unicast; 3957 flow_entry_t *flent; 3958 uint16_t vid; 3959 flow_desc_t flow_desc; 3960 3961 ASSERT(MAC_PERIM_HELD((mac_handle_t)mcip->mci_mip)); 3962 3963 mac_flow_get_desc(mcip->mci_flent, &flow_desc); 3964 if (bcmp(flow_desc.fd_dst_mac, map->ma_addr, map->ma_len) != 0) 3965 return (NULL); 3966 3967 for (flent = mcip->mci_flent_list; flent != NULL; 3968 flent = flent->fe_client_next) { 3969 vid = i_mac_flow_vid(flent); 3970 if (vid == muip->mui_vid) { 3971 return (flent); 3972 } 3973 } 3974 3975 return (NULL); 3976 } 3977 3978 /* 3979 * Since mci_flent has the SRSs, when we want to remove it, we replace 3980 * the flow_desc_t in mci_flent with that of an existing flent and then 3981 * remove that flent instead of mci_flent. 3982 */ 3983 static flow_entry_t * 3984 mac_client_swap_mciflent(mac_client_impl_t *mcip) 3985 { 3986 flow_entry_t *flent = mcip->mci_flent; 3987 flow_tab_t *ft = flent->fe_flow_tab; 3988 flow_entry_t *flent1; 3989 flow_desc_t fl_desc; 3990 char fl_name[MAXFLOWNAMELEN]; 3991 int err; 3992 3993 ASSERT(MAC_PERIM_HELD((mac_handle_t)mcip->mci_mip)); 3994 ASSERT(mcip->mci_nflents > 1); 3995 3996 /* get the next flent following the primary flent */ 3997 flent1 = mcip->mci_flent_list->fe_client_next; 3998 ASSERT(flent1 != NULL && flent1->fe_flow_tab == ft); 3999 4000 /* 4001 * Remove the flent from the flow table before updating the 4002 * flow descriptor as the hash depends on the flow descriptor. 4003 * This also helps incoming packet classification avoid having 4004 * to grab fe_lock. Access to fe_flow_desc of a flent not in the 4005 * flow table is done under the fe_lock so that log or stat functions 4006 * see a self-consistent fe_flow_desc. The name and desc are specific 4007 * to a flow, the rest are shared by all the clients, including 4008 * resource control etc. 4009 */ 4010 mac_flow_remove(ft, flent, B_TRUE); 4011 mac_flow_remove(ft, flent1, B_TRUE); 4012 4013 bcopy(&flent->fe_flow_desc, &fl_desc, sizeof (flow_desc_t)); 4014 bcopy(flent->fe_flow_name, fl_name, MAXFLOWNAMELEN); 4015 4016 /* update the primary flow entry */ 4017 mutex_enter(&flent->fe_lock); 4018 bcopy(&flent1->fe_flow_desc, &flent->fe_flow_desc, 4019 sizeof (flow_desc_t)); 4020 bcopy(&flent1->fe_flow_name, &flent->fe_flow_name, MAXFLOWNAMELEN); 4021 mutex_exit(&flent->fe_lock); 4022 4023 /* update the flow entry that is to be freed */ 4024 mutex_enter(&flent1->fe_lock); 4025 bcopy(&fl_desc, &flent1->fe_flow_desc, sizeof (flow_desc_t)); 4026 bcopy(fl_name, &flent1->fe_flow_name, MAXFLOWNAMELEN); 4027 mutex_exit(&flent1->fe_lock); 4028 4029 /* now reinsert the flow entries in the table */ 4030 err = mac_flow_add(ft, flent); 4031 ASSERT(err == 0); 4032 4033 err = mac_flow_add(ft, flent1); 4034 ASSERT(err == 0); 4035 4036 return (flent1); 4037 } 4038 4039 /* 4040 * Return whether there is only one flow entry associated with this 4041 * MAC client. 4042 */ 4043 static boolean_t 4044 mac_client_single_rcvr(mac_client_impl_t *mcip) 4045 { 4046 return (mcip->mci_nflents == 1); 4047 } 4048 4049 int 4050 mac_validate_props(mac_resource_props_t *mrp) 4051 { 4052 if (mrp == NULL) 4053 return (0); 4054 4055 if (mrp->mrp_mask & MRP_PRIORITY) { 4056 mac_priority_level_t pri = mrp->mrp_priority; 4057 4058 if (pri < MPL_LOW || pri > MPL_RESET) 4059 return (EINVAL); 4060 } 4061 4062 if (mrp->mrp_mask & MRP_MAXBW) { 4063 uint64_t maxbw = mrp->mrp_maxbw; 4064 4065 if (maxbw < MRP_MAXBW_MINVAL && maxbw != 0) 4066 return (EINVAL); 4067 } 4068 if (mrp->mrp_mask & MRP_CPUS) { 4069 int i, j; 4070 mac_cpu_mode_t fanout; 4071 4072 if (mrp->mrp_ncpus > ncpus || mrp->mrp_ncpus > MAX_SR_FANOUT) 4073 return (EINVAL); 4074 4075 for (i = 0; i < mrp->mrp_ncpus; i++) { 4076 for (j = 0; j < mrp->mrp_ncpus; j++) { 4077 if (i != j && 4078 mrp->mrp_cpu[i] == mrp->mrp_cpu[j]) { 4079 return (EINVAL); 4080 } 4081 } 4082 } 4083 4084 for (i = 0; i < mrp->mrp_ncpus; i++) { 4085 cpu_t *cp; 4086 int rv; 4087 4088 mutex_enter(&cpu_lock); 4089 cp = cpu_get(mrp->mrp_cpu[i]); 4090 if (cp != NULL) 4091 rv = cpu_is_online(cp); 4092 else 4093 rv = 0; 4094 mutex_exit(&cpu_lock); 4095 if (rv == 0) 4096 return (EINVAL); 4097 } 4098 4099 fanout = mrp->mrp_fanout_mode; 4100 if (fanout < 0 || fanout > MCM_CPUS) 4101 return (EINVAL); 4102 } 4103 return (0); 4104 } 4105 4106 /* 4107 * Send a MAC_NOTE_LINK notification to all the MAC clients whenever the 4108 * underlying physical link is down. This is to allow MAC clients to 4109 * communicate with other clients. 4110 */ 4111 void 4112 mac_virtual_link_update(mac_impl_t *mip) 4113 { 4114 if (mip->mi_linkstate != LINK_STATE_UP) 4115 i_mac_notify(mip, MAC_NOTE_LINK); 4116 } 4117 4118 /* 4119 * For clients that have a pass-thru MAC, e.g. VNIC, we set the VNIC's 4120 * mac handle in the client. 4121 */ 4122 void 4123 mac_set_upper_mac(mac_client_handle_t mch, mac_handle_t mh) 4124 { 4125 mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 4126 4127 mcip->mci_upper_mip = (mac_impl_t *)mh; 4128 } 4129 4130 /* 4131 * Mark the mac as being used exclusively by the single mac client that is 4132 * doing some control operation on this mac. No further opens of this mac 4133 * will be allowed until this client calls mac_unmark_exclusive. The mac 4134 * client calling this function must already be in the mac perimeter 4135 */ 4136 int 4137 mac_mark_exclusive(mac_handle_t mh) 4138 { 4139 mac_impl_t *mip = (mac_impl_t *)mh; 4140 4141 ASSERT(MAC_PERIM_HELD(mh)); 4142 /* 4143 * Look up its entry in the global hash table. 4144 */ 4145 rw_enter(&i_mac_impl_lock, RW_WRITER); 4146 if (mip->mi_state_flags & MIS_DISABLED) { 4147 rw_exit(&i_mac_impl_lock); 4148 return (ENOENT); 4149 } 4150 4151 /* 4152 * A reference to mac is held even if the link is not plumbed. 4153 * In i_dls_link_create() we open the MAC interface and hold the 4154 * reference. There is an additional reference for the mac_open 4155 * done in acquiring the mac perimeter 4156 */ 4157 if (mip->mi_ref != 2) { 4158 rw_exit(&i_mac_impl_lock); 4159 return (EBUSY); 4160 } 4161 4162 ASSERT(!(mip->mi_state_flags & MIS_EXCLUSIVE_HELD)); 4163 mip->mi_state_flags |= MIS_EXCLUSIVE_HELD; 4164 rw_exit(&i_mac_impl_lock); 4165 return (0); 4166 } 4167 4168 void 4169 mac_unmark_exclusive(mac_handle_t mh) 4170 { 4171 mac_impl_t *mip = (mac_impl_t *)mh; 4172 4173 ASSERT(MAC_PERIM_HELD(mh)); 4174 4175 rw_enter(&i_mac_impl_lock, RW_WRITER); 4176 /* 1 for the creation and another for the perimeter */ 4177 ASSERT(mip->mi_ref == 2 && (mip->mi_state_flags & MIS_EXCLUSIVE_HELD)); 4178 mip->mi_state_flags &= ~MIS_EXCLUSIVE_HELD; 4179 rw_exit(&i_mac_impl_lock); 4180 } 4181 4182 /* 4183 * Set the MTU for the specified device. The function returns EBUSY if 4184 * another MAC client prevents the caller to become the exclusive client. 4185 * Returns EAGAIN if the client is started. 4186 */ 4187 int 4188 mac_set_mtu(mac_handle_t mh, uint_t new_mtu, uint_t *old_mtu_arg) 4189 { 4190 mac_impl_t *mip = (mac_impl_t *)mh; 4191 uint_t old_mtu; 4192 int rv; 4193 boolean_t exclusive = B_FALSE; 4194 4195 i_mac_perim_enter(mip); 4196 4197 if ((mip->mi_callbacks->mc_callbacks & MC_SETPROP) == 0 || 4198 (mip->mi_callbacks->mc_callbacks & MC_GETPROP) == 0) { 4199 rv = ENOTSUP; 4200 goto bail; 4201 } 4202 4203 if ((rv = mac_mark_exclusive(mh)) != 0) 4204 goto bail; 4205 exclusive = B_TRUE; 4206 4207 if (mip->mi_active > 0) { 4208 /* 4209 * The MAC instance is started, for example due to the 4210 * presence of a promiscuous clients. Fail the operation 4211 * since the MAC's MTU cannot be changed while the NIC 4212 * is started. 4213 */ 4214 rv = EAGAIN; 4215 goto bail; 4216 } 4217 4218 mac_sdu_get(mh, NULL, &old_mtu); 4219 4220 if (old_mtu != new_mtu) { 4221 rv = mip->mi_callbacks->mc_setprop(mip->mi_driver, 4222 "mtu", MAC_PROP_MTU, sizeof (uint_t), &new_mtu); 4223 } 4224 4225 bail: 4226 if (exclusive) 4227 mac_unmark_exclusive(mh); 4228 i_mac_perim_exit(mip); 4229 4230 if (rv == 0 && old_mtu_arg != NULL) 4231 *old_mtu_arg = old_mtu; 4232 return (rv); 4233 } 4234 4235 void 4236 mac_get_hwgrp_info(mac_handle_t mh, int grp_index, uint_t *grp_num, 4237 uint_t *n_rings, uint_t *type, uint_t *n_clnts, char *clnts_name) 4238 { 4239 mac_impl_t *mip = (mac_impl_t *)mh; 4240 mac_grp_client_t *mcip; 4241 uint_t i = 0, index = 0; 4242 4243 /* Revisit when we implement fully dynamic group allocation */ 4244 ASSERT(grp_index >= 0 && grp_index < mip->mi_rx_group_count); 4245 4246 rw_enter(&mip->mi_rw_lock, RW_READER); 4247 *grp_num = mip->mi_rx_groups[grp_index].mrg_index; 4248 *type = mip->mi_rx_groups[grp_index].mrg_type; 4249 *n_rings = mip->mi_rx_groups[grp_index].mrg_cur_count; 4250 for (mcip = mip->mi_rx_groups[grp_index].mrg_clients; mcip != NULL; 4251 mcip = mcip->mgc_next) { 4252 int name_len = strlen(mcip->mgc_client->mci_name); 4253 4254 /* 4255 * MAXCLIENTNAMELEN is the buffer size reserved for client 4256 * names. 4257 * XXXX Formating the client name string needs to be moved 4258 * to user land when fixing the size of dhi_clnts in 4259 * dld_hwgrpinfo_t. We should use n_clients * client_name for 4260 * dhi_clntsin instead of MAXCLIENTNAMELEN 4261 */ 4262 if (index + name_len >= MAXCLIENTNAMELEN) { 4263 index = MAXCLIENTNAMELEN; 4264 break; 4265 } 4266 bcopy(mcip->mgc_client->mci_name, &(clnts_name[index]), 4267 name_len); 4268 index += name_len; 4269 clnts_name[index++] = ','; 4270 i++; 4271 } 4272 4273 /* Get rid of the last , */ 4274 if (index > 0) 4275 clnts_name[index - 1] = '\0'; 4276 *n_clnts = i; 4277 rw_exit(&mip->mi_rw_lock); 4278 } 4279 4280 uint_t 4281 mac_hwgrp_num(mac_handle_t mh) 4282 { 4283 mac_impl_t *mip = (mac_impl_t *)mh; 4284 4285 return (mip->mi_rx_group_count); 4286 } 4287