xref: /illumos-gate/usr/src/uts/common/io/mac/mac_client.c (revision 069e6b7e31ba5dcbc5441b98af272714d9a5455c)
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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright 2019 Joyent, Inc.
25  * Copyright 2017 RackTop Systems.
26  * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
27  */
28 
29 /*
30  * - General Introduction:
31  *
32  * This file contains the implementation of the MAC client kernel
33  * API and related code. The MAC client API allows a kernel module
34  * to gain access to a MAC instance (physical NIC, link aggregation, etc).
35  * It allows a MAC client to associate itself with a MAC address,
36  * VLANs, callback functions for data traffic and for promiscuous mode.
37  * The MAC client API is also used to specify the properties associated
38  * with a MAC client, such as bandwidth limits, priority, CPUS, etc.
39  * These properties are further used to determine the hardware resources
40  * to allocate to the various MAC clients.
41  *
42  * - Primary MAC clients:
43  *
44  * The MAC client API refers to "primary MAC clients". A primary MAC
45  * client is a client which "owns" the primary MAC address of
46  * the underlying MAC instance. The primary MAC address is called out
47  * since it is associated with specific semantics: the primary MAC
48  * address is the MAC address which is assigned to the IP interface
49  * when it is plumbed, and the primary MAC address is assigned
50  * to VLAN data-links. The primary address of a MAC instance can
51  * also change dynamically from under the MAC client, for example
52  * as a result of a change of state of a link aggregation. In that
53  * case the MAC layer automatically updates all data-structures which
54  * refer to the current value of the primary MAC address. Typical
55  * primary MAC clients are dls, aggr, and xnb. A typical non-primary
56  * MAC client is the vnic driver.
57  *
58  * - Virtual Switching:
59  *
60  * The MAC layer implements a virtual switch between the MAC clients
61  * (primary and non-primary) defined on top of the same underlying
62  * NIC (physical, link aggregation, etc). The virtual switch is
63  * VLAN-aware, i.e. it allows multiple MAC clients to be member
64  * of one or more VLANs, and the virtual switch will distribute
65  * multicast tagged packets only to the member of the corresponding
66  * VLANs.
67  *
68  * - Upper vs Lower MAC:
69  *
70  * Creating a VNIC on top of a MAC instance effectively causes
71  * two MAC instances to be layered on top of each other, one for
72  * the VNIC(s), one for the underlying MAC instance (physical NIC,
73  * link aggregation, etc). In the code below we refer to the
74  * underlying NIC as the "lower MAC", and we refer to VNICs as
75  * the "upper MAC".
76  *
77  * - Pass-through for VNICs:
78  *
79  * When VNICs are created on top of an underlying MAC, this causes
80  * a layering of two MAC instances. Since the lower MAC already
81  * does the switching and demultiplexing to its MAC clients, the
82  * upper MAC would simply have to pass packets to the layer below
83  * or above it, which would introduce overhead. In order to avoid
84  * this overhead, the MAC layer implements a pass-through mechanism
85  * for VNICs. When a VNIC opens the lower MAC instance, it saves
86  * the MAC client handle it optains from the MAC layer. When a MAC
87  * client opens a VNIC (upper MAC), the MAC layer detects that
88  * the MAC being opened is a VNIC, and gets the MAC client handle
89  * that the VNIC driver obtained from the lower MAC. This exchange
90  * is done through a private capability between the MAC layer
91  * and the VNIC driver. The upper MAC then returns that handle
92  * directly to its MAC client. Any operation done by the upper
93  * MAC client is now done on the lower MAC client handle, which
94  * allows the VNIC driver to be completely bypassed for the
95  * performance sensitive data-path.
96  *
97  * - Secondary MACs for VNICs:
98  *
99  * VNICs support multiple upper mac clients to enable support for
100  * multiple MAC addresses on the VNIC. When the VNIC is created the
101  * initial mac client is the primary upper mac. Any additional mac
102  * clients are secondary macs. These are kept in sync with the primary
103  * (for things such as the rx function and resource control settings)
104  * using the same private capability interface between the MAC layer
105  * and the VNIC layer.
106  *
107  */
108 
109 #include <sys/types.h>
110 #include <sys/conf.h>
111 #include <sys/id_space.h>
112 #include <sys/esunddi.h>
113 #include <sys/stat.h>
114 #include <sys/mkdev.h>
115 #include <sys/stream.h>
116 #include <sys/strsun.h>
117 #include <sys/strsubr.h>
118 #include <sys/pattr.h>
119 #include <sys/dlpi.h>
120 #include <sys/modhash.h>
121 #include <sys/mac_impl.h>
122 #include <sys/mac_client_impl.h>
123 #include <sys/mac_soft_ring.h>
124 #include <sys/mac_stat.h>
125 #include <sys/dls.h>
126 #include <sys/dld.h>
127 #include <sys/modctl.h>
128 #include <sys/fs/dv_node.h>
129 #include <sys/thread.h>
130 #include <sys/proc.h>
131 #include <sys/callb.h>
132 #include <sys/cpuvar.h>
133 #include <sys/atomic.h>
134 #include <sys/sdt.h>
135 #include <sys/mac_flow.h>
136 #include <sys/ddi_intr_impl.h>
137 #include <sys/disp.h>
138 #include <sys/sdt.h>
139 #include <sys/vnic.h>
140 #include <sys/vnic_impl.h>
141 #include <sys/vlan.h>
142 #include <inet/ip.h>
143 #include <inet/ip6.h>
144 #include <sys/exacct.h>
145 #include <sys/exacct_impl.h>
146 #include <inet/nd.h>
147 #include <sys/ethernet.h>
148 
149 kmem_cache_t	*mac_client_impl_cache;
150 kmem_cache_t	*mac_promisc_impl_cache;
151 
152 static boolean_t mac_client_single_rcvr(mac_client_impl_t *);
153 static flow_entry_t *mac_client_swap_mciflent(mac_client_impl_t *);
154 static flow_entry_t *mac_client_get_flow(mac_client_impl_t *,
155     mac_unicast_impl_t *);
156 static void mac_client_remove_flow_from_list(mac_client_impl_t *,
157     flow_entry_t *);
158 static void mac_client_add_to_flow_list(mac_client_impl_t *, flow_entry_t *);
159 static void mac_rename_flow_names(mac_client_impl_t *, const char *);
160 static void mac_virtual_link_update(mac_impl_t *);
161 static int mac_client_datapath_setup(mac_client_impl_t *, uint16_t,
162     uint8_t *, mac_resource_props_t *, boolean_t, mac_unicast_impl_t *);
163 static void mac_client_datapath_teardown(mac_client_handle_t,
164     mac_unicast_impl_t *, flow_entry_t *);
165 static int mac_resource_ctl_set(mac_client_handle_t, mac_resource_props_t *);
166 
167 /* ARGSUSED */
168 static int
169 i_mac_client_impl_ctor(void *buf, void *arg, int kmflag)
170 {
171 	int	i;
172 	mac_client_impl_t	*mcip = buf;
173 
174 	bzero(buf, MAC_CLIENT_IMPL_SIZE);
175 	mutex_init(&mcip->mci_tx_cb_lock, NULL, MUTEX_DRIVER, NULL);
176 	mcip->mci_tx_notify_cb_info.mcbi_lockp = &mcip->mci_tx_cb_lock;
177 
178 	ASSERT(mac_tx_percpu_cnt >= 0);
179 	for (i = 0; i <= mac_tx_percpu_cnt; i++) {
180 		mutex_init(&mcip->mci_tx_pcpu[i].pcpu_tx_lock, NULL,
181 		    MUTEX_DRIVER, NULL);
182 	}
183 	cv_init(&mcip->mci_tx_cv, NULL, CV_DRIVER, NULL);
184 
185 	return (0);
186 }
187 
188 /* ARGSUSED */
189 static void
190 i_mac_client_impl_dtor(void *buf, void *arg)
191 {
192 	int	i;
193 	mac_client_impl_t *mcip = buf;
194 
195 	ASSERT(mcip->mci_promisc_list == NULL);
196 	ASSERT(mcip->mci_unicast_list == NULL);
197 	ASSERT(mcip->mci_state_flags == 0);
198 	ASSERT(mcip->mci_tx_flag == 0);
199 
200 	mutex_destroy(&mcip->mci_tx_cb_lock);
201 
202 	ASSERT(mac_tx_percpu_cnt >= 0);
203 	for (i = 0; i <= mac_tx_percpu_cnt; i++) {
204 		ASSERT(mcip->mci_tx_pcpu[i].pcpu_tx_refcnt == 0);
205 		mutex_destroy(&mcip->mci_tx_pcpu[i].pcpu_tx_lock);
206 	}
207 	cv_destroy(&mcip->mci_tx_cv);
208 }
209 
210 /* ARGSUSED */
211 static int
212 i_mac_promisc_impl_ctor(void *buf, void *arg, int kmflag)
213 {
214 	mac_promisc_impl_t	*mpip = buf;
215 
216 	bzero(buf, sizeof (mac_promisc_impl_t));
217 	mpip->mpi_mci_link.mcb_objp = buf;
218 	mpip->mpi_mci_link.mcb_objsize = sizeof (mac_promisc_impl_t);
219 	mpip->mpi_mi_link.mcb_objp = buf;
220 	mpip->mpi_mi_link.mcb_objsize = sizeof (mac_promisc_impl_t);
221 	return (0);
222 }
223 
224 /* ARGSUSED */
225 static void
226 i_mac_promisc_impl_dtor(void *buf, void *arg)
227 {
228 	mac_promisc_impl_t	*mpip = buf;
229 
230 	ASSERT(mpip->mpi_mci_link.mcb_objp != NULL);
231 	ASSERT(mpip->mpi_mci_link.mcb_objsize == sizeof (mac_promisc_impl_t));
232 	ASSERT(mpip->mpi_mi_link.mcb_objp == mpip->mpi_mci_link.mcb_objp);
233 	ASSERT(mpip->mpi_mi_link.mcb_objsize == sizeof (mac_promisc_impl_t));
234 
235 	mpip->mpi_mci_link.mcb_objp = NULL;
236 	mpip->mpi_mci_link.mcb_objsize = 0;
237 	mpip->mpi_mi_link.mcb_objp = NULL;
238 	mpip->mpi_mi_link.mcb_objsize = 0;
239 
240 	ASSERT(mpip->mpi_mci_link.mcb_flags == 0);
241 	mpip->mpi_mci_link.mcb_objsize = 0;
242 }
243 
244 void
245 mac_client_init(void)
246 {
247 	ASSERT(mac_tx_percpu_cnt >= 0);
248 
249 	mac_client_impl_cache = kmem_cache_create("mac_client_impl_cache",
250 	    MAC_CLIENT_IMPL_SIZE, 0, i_mac_client_impl_ctor,
251 	    i_mac_client_impl_dtor, NULL, NULL, NULL, 0);
252 	ASSERT(mac_client_impl_cache != NULL);
253 
254 	mac_promisc_impl_cache = kmem_cache_create("mac_promisc_impl_cache",
255 	    sizeof (mac_promisc_impl_t), 0, i_mac_promisc_impl_ctor,
256 	    i_mac_promisc_impl_dtor, NULL, NULL, NULL, 0);
257 	ASSERT(mac_promisc_impl_cache != NULL);
258 }
259 
260 void
261 mac_client_fini(void)
262 {
263 	kmem_cache_destroy(mac_client_impl_cache);
264 	kmem_cache_destroy(mac_promisc_impl_cache);
265 }
266 
267 /*
268  * Return the lower MAC client handle from the VNIC driver for the
269  * specified VNIC MAC instance.
270  */
271 mac_client_impl_t *
272 mac_vnic_lower(mac_impl_t *mip)
273 {
274 	mac_capab_vnic_t cap;
275 	mac_client_impl_t *mcip;
276 
277 	VERIFY(i_mac_capab_get((mac_handle_t)mip, MAC_CAPAB_VNIC, &cap));
278 	mcip = cap.mcv_mac_client_handle(cap.mcv_arg);
279 
280 	return (mcip);
281 }
282 
283 /*
284  * Update the secondary macs
285  */
286 void
287 mac_vnic_secondary_update(mac_impl_t *mip)
288 {
289 	mac_capab_vnic_t cap;
290 
291 	VERIFY(i_mac_capab_get((mac_handle_t)mip, MAC_CAPAB_VNIC, &cap));
292 	cap.mcv_mac_secondary_update(cap.mcv_arg);
293 }
294 
295 /*
296  * Return the MAC client handle of the primary MAC client for the
297  * specified MAC instance, or NULL otherwise.
298  */
299 mac_client_impl_t *
300 mac_primary_client_handle(mac_impl_t *mip)
301 {
302 	mac_client_impl_t *mcip;
303 
304 	if (mip->mi_state_flags & MIS_IS_VNIC)
305 		return (mac_vnic_lower(mip));
306 
307 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
308 
309 	for (mcip = mip->mi_clients_list; mcip != NULL;
310 	    mcip = mcip->mci_client_next) {
311 		if (MCIP_DATAPATH_SETUP(mcip) && mac_is_primary_client(mcip))
312 			return (mcip);
313 	}
314 	return (NULL);
315 }
316 
317 /*
318  * Open a MAC specified by its MAC name.
319  */
320 int
321 mac_open(const char *macname, mac_handle_t *mhp)
322 {
323 	mac_impl_t	*mip;
324 	int		err;
325 
326 	/*
327 	 * Look up its entry in the global hash table.
328 	 */
329 	if ((err = mac_hold(macname, &mip)) != 0)
330 		return (err);
331 
332 	/*
333 	 * Hold the dip associated to the MAC to prevent it from being
334 	 * detached. For a softmac, its underlying dip is held by the
335 	 * mi_open() callback.
336 	 *
337 	 * This is done to be more tolerant with some defective drivers,
338 	 * which incorrectly handle mac_unregister() failure in their
339 	 * xxx_detach() routine. For example, some drivers ignore the
340 	 * failure of mac_unregister() and free all resources that
341 	 * that are needed for data transmition.
342 	 */
343 	e_ddi_hold_devi(mip->mi_dip);
344 
345 	if (!(mip->mi_callbacks->mc_callbacks & MC_OPEN)) {
346 		*mhp = (mac_handle_t)mip;
347 		return (0);
348 	}
349 
350 	/*
351 	 * The mac perimeter is used in both mac_open and mac_close by the
352 	 * framework to single thread the MC_OPEN/MC_CLOSE of drivers.
353 	 */
354 	i_mac_perim_enter(mip);
355 	mip->mi_oref++;
356 	if (mip->mi_oref != 1 || ((err = mip->mi_open(mip->mi_driver)) == 0)) {
357 		*mhp = (mac_handle_t)mip;
358 		i_mac_perim_exit(mip);
359 		return (0);
360 	}
361 	mip->mi_oref--;
362 	ddi_release_devi(mip->mi_dip);
363 	mac_rele(mip);
364 	i_mac_perim_exit(mip);
365 	return (err);
366 }
367 
368 /*
369  * Open a MAC specified by its linkid.
370  */
371 int
372 mac_open_by_linkid(datalink_id_t linkid, mac_handle_t *mhp)
373 {
374 	dls_dl_handle_t	dlh;
375 	int		err;
376 
377 	if ((err = dls_devnet_hold_tmp(linkid, &dlh)) != 0)
378 		return (err);
379 
380 	dls_devnet_prop_task_wait(dlh);
381 
382 	err = mac_open(dls_devnet_mac(dlh), mhp);
383 
384 	dls_devnet_rele_tmp(dlh);
385 	return (err);
386 }
387 
388 /*
389  * Open a MAC specified by its link name.
390  */
391 int
392 mac_open_by_linkname(const char *link, mac_handle_t *mhp)
393 {
394 	datalink_id_t	linkid;
395 	int		err;
396 
397 	if ((err = dls_mgmt_get_linkid(link, &linkid)) != 0)
398 		return (err);
399 	return (mac_open_by_linkid(linkid, mhp));
400 }
401 
402 /*
403  * Close the specified MAC.
404  */
405 void
406 mac_close(mac_handle_t mh)
407 {
408 	mac_impl_t	*mip = (mac_impl_t *)mh;
409 
410 	i_mac_perim_enter(mip);
411 	/*
412 	 * The mac perimeter is used in both mac_open and mac_close by the
413 	 * framework to single thread the MC_OPEN/MC_CLOSE of drivers.
414 	 */
415 	if (mip->mi_callbacks->mc_callbacks & MC_OPEN) {
416 		ASSERT(mip->mi_oref != 0);
417 		if (--mip->mi_oref == 0) {
418 			if ((mip->mi_callbacks->mc_callbacks & MC_CLOSE))
419 				mip->mi_close(mip->mi_driver);
420 		}
421 	}
422 	i_mac_perim_exit(mip);
423 	ddi_release_devi(mip->mi_dip);
424 	mac_rele(mip);
425 }
426 
427 /*
428  * Misc utility functions to retrieve various information about a MAC
429  * instance or a MAC client.
430  */
431 
432 const mac_info_t *
433 mac_info(mac_handle_t mh)
434 {
435 	return (&((mac_impl_t *)mh)->mi_info);
436 }
437 
438 dev_info_t *
439 mac_devinfo_get(mac_handle_t mh)
440 {
441 	return (((mac_impl_t *)mh)->mi_dip);
442 }
443 
444 void *
445 mac_driver(mac_handle_t mh)
446 {
447 	return (((mac_impl_t *)mh)->mi_driver);
448 }
449 
450 const char *
451 mac_name(mac_handle_t mh)
452 {
453 	return (((mac_impl_t *)mh)->mi_name);
454 }
455 
456 int
457 mac_type(mac_handle_t mh)
458 {
459 	return (((mac_impl_t *)mh)->mi_type->mt_type);
460 }
461 
462 int
463 mac_nativetype(mac_handle_t mh)
464 {
465 	return (((mac_impl_t *)mh)->mi_type->mt_nativetype);
466 }
467 
468 char *
469 mac_client_name(mac_client_handle_t mch)
470 {
471 	return (((mac_client_impl_t *)mch)->mci_name);
472 }
473 
474 minor_t
475 mac_minor(mac_handle_t mh)
476 {
477 	return (((mac_impl_t *)mh)->mi_minor);
478 }
479 
480 /*
481  * Return the VID associated with a MAC client. This function should
482  * be called for clients which are associated with only one VID.
483  */
484 uint16_t
485 mac_client_vid(mac_client_handle_t mch)
486 {
487 	uint16_t		vid = VLAN_ID_NONE;
488 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
489 	flow_desc_t		flow_desc;
490 
491 	if (mcip->mci_nflents == 0)
492 		return (vid);
493 
494 	ASSERT(MCIP_DATAPATH_SETUP(mcip) && mac_client_single_rcvr(mcip));
495 
496 	mac_flow_get_desc(mcip->mci_flent, &flow_desc);
497 	if ((flow_desc.fd_mask & FLOW_LINK_VID) != 0)
498 		vid = flow_desc.fd_vid;
499 
500 	return (vid);
501 }
502 
503 /*
504  * Return whether the specified MAC client corresponds to a VLAN VNIC.
505  */
506 boolean_t
507 mac_client_is_vlan_vnic(mac_client_handle_t mch)
508 {
509 	mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
510 
511 	return (((mcip->mci_state_flags & MCIS_IS_VNIC) != 0) &&
512 	    ((mcip->mci_flent->fe_type & FLOW_PRIMARY_MAC) != 0));
513 }
514 
515 /*
516  * Return the link speed associated with the specified MAC client.
517  *
518  * The link speed of a MAC client is equal to the smallest value of
519  * 1) the current link speed of the underlying NIC, or
520  * 2) the bandwidth limit set for the MAC client.
521  *
522  * Note that the bandwidth limit can be higher than the speed
523  * of the underlying NIC. This is allowed to avoid spurious
524  * administration action failures or artifically lowering the
525  * bandwidth limit of a link that may  have temporarily lowered
526  * its link speed due to hardware problem or administrator action.
527  */
528 static uint64_t
529 mac_client_ifspeed(mac_client_impl_t *mcip)
530 {
531 	mac_impl_t *mip = mcip->mci_mip;
532 	uint64_t nic_speed;
533 
534 	nic_speed = mac_stat_get((mac_handle_t)mip, MAC_STAT_IFSPEED);
535 
536 	if (nic_speed == 0) {
537 		return (0);
538 	} else {
539 		uint64_t policy_limit = (uint64_t)-1;
540 
541 		if (MCIP_RESOURCE_PROPS_MASK(mcip) & MRP_MAXBW)
542 			policy_limit = MCIP_RESOURCE_PROPS_MAXBW(mcip);
543 
544 		return (MIN(policy_limit, nic_speed));
545 	}
546 }
547 
548 /*
549  * Return the link state of the specified client. If here are more
550  * than one clients of the underying mac_impl_t, the link state
551  * will always be UP regardless of the link state of the underlying
552  * mac_impl_t. This is needed to allow the MAC clients to continue
553  * to communicate with each other even when the physical link of
554  * their mac_impl_t is down.
555  */
556 static uint64_t
557 mac_client_link_state(mac_client_impl_t *mcip)
558 {
559 	mac_impl_t *mip = mcip->mci_mip;
560 	uint16_t vid;
561 	mac_client_impl_t *mci_list;
562 	mac_unicast_impl_t *mui_list, *oth_mui_list;
563 
564 	/*
565 	 * Returns LINK_STATE_UP if there are other MAC clients defined on
566 	 * mac_impl_t which share same VLAN ID as that of mcip. Note that
567 	 * if 'mcip' has more than one VID's then we match ANY one of the
568 	 * VID's with other MAC client's VID's and return LINK_STATE_UP.
569 	 */
570 	rw_enter(&mcip->mci_rw_lock, RW_READER);
571 	for (mui_list = mcip->mci_unicast_list; mui_list != NULL;
572 	    mui_list = mui_list->mui_next) {
573 		vid = mui_list->mui_vid;
574 		for (mci_list = mip->mi_clients_list; mci_list != NULL;
575 		    mci_list = mci_list->mci_client_next) {
576 			if (mci_list == mcip)
577 				continue;
578 			for (oth_mui_list = mci_list->mci_unicast_list;
579 			    oth_mui_list != NULL; oth_mui_list = oth_mui_list->
580 			    mui_next) {
581 				if (vid == oth_mui_list->mui_vid) {
582 					rw_exit(&mcip->mci_rw_lock);
583 					return (LINK_STATE_UP);
584 				}
585 			}
586 		}
587 	}
588 	rw_exit(&mcip->mci_rw_lock);
589 
590 	return (mac_stat_get((mac_handle_t)mip, MAC_STAT_LINK_STATE));
591 }
592 
593 /*
594  * These statistics are consumed by dladm show-link -s <vnic>,
595  * dladm show-vnic -s and netstat. With the introduction of dlstat,
596  * dladm show-link -s and dladm show-vnic -s witll be EOL'ed while
597  * netstat will consume from kstats introduced for dlstat. This code
598  * will be removed at that time.
599  */
600 
601 /*
602  * Return the statistics of a MAC client. These statistics are different
603  * then the statistics of the underlying MAC which are returned by
604  * mac_stat_get().
605  *
606  * Note that for things based on the tx and rx stats, mac will end up clobbering
607  * those stats when the underlying set of rings in the srs changes. As such, we
608  * need to source not only the current set, but also the historical set when
609  * returning to the client, lest our counters appear to go backwards.
610  */
611 uint64_t
612 mac_client_stat_get(mac_client_handle_t mch, uint_t stat)
613 {
614 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
615 	mac_impl_t		*mip = mcip->mci_mip;
616 	flow_entry_t		*flent = mcip->mci_flent;
617 	mac_soft_ring_set_t	*mac_srs;
618 	mac_rx_stats_t		*mac_rx_stat, *old_rx_stat;
619 	mac_tx_stats_t		*mac_tx_stat, *old_tx_stat;
620 	int i;
621 	uint64_t val = 0;
622 
623 	mac_srs = (mac_soft_ring_set_t *)(flent->fe_tx_srs);
624 	mac_tx_stat = &mac_srs->srs_tx.st_stat;
625 	old_rx_stat = &mcip->mci_misc_stat.mms_defunctrxlanestats;
626 	old_tx_stat = &mcip->mci_misc_stat.mms_defuncttxlanestats;
627 
628 	switch (stat) {
629 	case MAC_STAT_LINK_STATE:
630 		val = mac_client_link_state(mcip);
631 		break;
632 	case MAC_STAT_LINK_UP:
633 		val = (mac_client_link_state(mcip) == LINK_STATE_UP);
634 		break;
635 	case MAC_STAT_PROMISC:
636 		val = mac_stat_get((mac_handle_t)mip, MAC_STAT_PROMISC);
637 		break;
638 	case MAC_STAT_LOWLINK_STATE:
639 		val = mac_stat_get((mac_handle_t)mip, MAC_STAT_LOWLINK_STATE);
640 		break;
641 	case MAC_STAT_IFSPEED:
642 		val = mac_client_ifspeed(mcip);
643 		break;
644 	case MAC_STAT_MULTIRCV:
645 		val = mcip->mci_misc_stat.mms_multircv;
646 		break;
647 	case MAC_STAT_BRDCSTRCV:
648 		val = mcip->mci_misc_stat.mms_brdcstrcv;
649 		break;
650 	case MAC_STAT_MULTIXMT:
651 		val = mcip->mci_misc_stat.mms_multixmt;
652 		break;
653 	case MAC_STAT_BRDCSTXMT:
654 		val = mcip->mci_misc_stat.mms_brdcstxmt;
655 		break;
656 	case MAC_STAT_OBYTES:
657 		val = mac_tx_stat->mts_obytes;
658 		val += old_tx_stat->mts_obytes;
659 		break;
660 	case MAC_STAT_OPACKETS:
661 		val = mac_tx_stat->mts_opackets;
662 		val += old_tx_stat->mts_opackets;
663 		break;
664 	case MAC_STAT_OERRORS:
665 		val = mac_tx_stat->mts_oerrors;
666 		val += old_tx_stat->mts_oerrors;
667 		break;
668 	case MAC_STAT_IPACKETS:
669 		for (i = 0; i < flent->fe_rx_srs_cnt; i++) {
670 			mac_srs = (mac_soft_ring_set_t *)flent->fe_rx_srs[i];
671 			mac_rx_stat = &mac_srs->srs_rx.sr_stat;
672 			val += mac_rx_stat->mrs_intrcnt +
673 			    mac_rx_stat->mrs_pollcnt + mac_rx_stat->mrs_lclcnt;
674 		}
675 		val += old_rx_stat->mrs_intrcnt + old_rx_stat->mrs_pollcnt +
676 		    old_rx_stat->mrs_lclcnt;
677 		break;
678 	case MAC_STAT_RBYTES:
679 		for (i = 0; i < flent->fe_rx_srs_cnt; i++) {
680 			mac_srs = (mac_soft_ring_set_t *)flent->fe_rx_srs[i];
681 			mac_rx_stat = &mac_srs->srs_rx.sr_stat;
682 			val += mac_rx_stat->mrs_intrbytes +
683 			    mac_rx_stat->mrs_pollbytes +
684 			    mac_rx_stat->mrs_lclbytes;
685 		}
686 		val += old_rx_stat->mrs_intrbytes + old_rx_stat->mrs_pollbytes +
687 		    old_rx_stat->mrs_lclbytes;
688 		break;
689 	case MAC_STAT_IERRORS:
690 		for (i = 0; i < flent->fe_rx_srs_cnt; i++) {
691 			mac_srs = (mac_soft_ring_set_t *)flent->fe_rx_srs[i];
692 			mac_rx_stat = &mac_srs->srs_rx.sr_stat;
693 			val += mac_rx_stat->mrs_ierrors;
694 		}
695 		val += old_rx_stat->mrs_ierrors;
696 		break;
697 	default:
698 		val = mac_driver_stat_default(mip, stat);
699 		break;
700 	}
701 
702 	return (val);
703 }
704 
705 /*
706  * Return the statistics of the specified MAC instance.
707  */
708 uint64_t
709 mac_stat_get(mac_handle_t mh, uint_t stat)
710 {
711 	mac_impl_t	*mip = (mac_impl_t *)mh;
712 	uint64_t	val;
713 	int		ret;
714 
715 	/*
716 	 * The range of stat determines where it is maintained.  Stat
717 	 * values from 0 up to (but not including) MAC_STAT_MIN are
718 	 * mainteined by the mac module itself.  Everything else is
719 	 * maintained by the driver.
720 	 *
721 	 * If the mac_impl_t being queried corresponds to a VNIC,
722 	 * the stats need to be queried from the lower MAC client
723 	 * corresponding to the VNIC. (The mac_link_update()
724 	 * invoked by the driver to the lower MAC causes the *lower
725 	 * MAC* to update its mi_linkstate, and send a notification
726 	 * to its MAC clients. Due to the VNIC passthrough,
727 	 * these notifications are sent to the upper MAC clients
728 	 * of the VNIC directly, and the upper mac_impl_t of the VNIC
729 	 * does not have a valid mi_linkstate.
730 	 */
731 	if (stat < MAC_STAT_MIN && !(mip->mi_state_flags & MIS_IS_VNIC)) {
732 		/* these stats are maintained by the mac module itself */
733 		switch (stat) {
734 		case MAC_STAT_LINK_STATE:
735 			return (mip->mi_linkstate);
736 		case MAC_STAT_LINK_UP:
737 			return (mip->mi_linkstate == LINK_STATE_UP);
738 		case MAC_STAT_PROMISC:
739 			return (mip->mi_devpromisc != 0);
740 		case MAC_STAT_LOWLINK_STATE:
741 			return (mip->mi_lowlinkstate);
742 		default:
743 			ASSERT(B_FALSE);
744 		}
745 	}
746 
747 	/*
748 	 * Call the driver to get the given statistic.
749 	 */
750 	ret = mip->mi_getstat(mip->mi_driver, stat, &val);
751 	if (ret != 0) {
752 		/*
753 		 * The driver doesn't support this statistic.  Get the
754 		 * statistic's default value.
755 		 */
756 		val = mac_driver_stat_default(mip, stat);
757 	}
758 	return (val);
759 }
760 
761 /*
762  * Query hardware rx ring corresponding to the pseudo ring.
763  */
764 uint64_t
765 mac_pseudo_rx_ring_stat_get(mac_ring_handle_t handle, uint_t stat)
766 {
767 	return (mac_rx_ring_stat_get(handle, stat));
768 }
769 
770 /*
771  * Query hardware tx ring corresponding to the pseudo ring.
772  */
773 uint64_t
774 mac_pseudo_tx_ring_stat_get(mac_ring_handle_t handle, uint_t stat)
775 {
776 	return (mac_tx_ring_stat_get(handle, stat));
777 }
778 
779 /*
780  * Utility function which returns the VID associated with a flow entry.
781  */
782 uint16_t
783 i_mac_flow_vid(flow_entry_t *flent)
784 {
785 	flow_desc_t	flow_desc;
786 
787 	mac_flow_get_desc(flent, &flow_desc);
788 
789 	if ((flow_desc.fd_mask & FLOW_LINK_VID) != 0)
790 		return (flow_desc.fd_vid);
791 	return (VLAN_ID_NONE);
792 }
793 
794 /*
795  * Verify the validity of the specified unicast MAC address. Returns B_TRUE
796  * if the address is valid, B_FALSE otherwise (multicast address, or incorrect
797  * length.
798  */
799 boolean_t
800 mac_unicst_verify(mac_handle_t mh, const uint8_t *addr, uint_t len)
801 {
802 	mac_impl_t	*mip = (mac_impl_t *)mh;
803 
804 	/*
805 	 * Verify the address. No lock is needed since mi_type and plugin
806 	 * details don't change after mac_register().
807 	 */
808 	if ((len != mip->mi_type->mt_addr_length) ||
809 	    (mip->mi_type->mt_ops.mtops_unicst_verify(addr,
810 	    mip->mi_pdata)) != 0) {
811 		return (B_FALSE);
812 	} else {
813 		return (B_TRUE);
814 	}
815 }
816 
817 void
818 mac_sdu_get(mac_handle_t mh, uint_t *min_sdu, uint_t *max_sdu)
819 {
820 	mac_impl_t	*mip = (mac_impl_t *)mh;
821 
822 	if (min_sdu != NULL)
823 		*min_sdu = mip->mi_sdu_min;
824 	if (max_sdu != NULL)
825 		*max_sdu = mip->mi_sdu_max;
826 }
827 
828 void
829 mac_sdu_get2(mac_handle_t mh, uint_t *min_sdu, uint_t *max_sdu,
830     uint_t *multicast_sdu)
831 {
832 	mac_impl_t	*mip = (mac_impl_t *)mh;
833 
834 	if (min_sdu != NULL)
835 		*min_sdu = mip->mi_sdu_min;
836 	if (max_sdu != NULL)
837 		*max_sdu = mip->mi_sdu_max;
838 	if (multicast_sdu != NULL)
839 		*multicast_sdu = mip->mi_sdu_multicast;
840 }
841 
842 /*
843  * Update the MAC unicast address of the specified client's flows. Currently
844  * only one unicast MAC unicast address is allowed per client.
845  */
846 static void
847 mac_unicast_update_client_flow(mac_client_impl_t *mcip)
848 {
849 	mac_impl_t *mip = mcip->mci_mip;
850 	flow_entry_t *flent = mcip->mci_flent;
851 	mac_address_t *map = mcip->mci_unicast;
852 	flow_desc_t flow_desc;
853 
854 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
855 	ASSERT(flent != NULL);
856 
857 	mac_flow_get_desc(flent, &flow_desc);
858 	ASSERT(flow_desc.fd_mask & FLOW_LINK_DST);
859 
860 	bcopy(map->ma_addr, flow_desc.fd_dst_mac, map->ma_len);
861 	mac_flow_set_desc(flent, &flow_desc);
862 
863 	/*
864 	 * The v6 local and SLAAC addrs (used by mac protection) need to be
865 	 * regenerated because our mac address has changed.
866 	 */
867 	mac_protect_update_mac_token(mcip);
868 
869 	/*
870 	 * When there are multiple VLANs sharing the same MAC address,
871 	 * each gets its own MAC client, except when running on sun4v
872 	 * vsw. In that case the mci_flent_list is used to place
873 	 * multiple VLAN flows on one MAC client. If we ever get rid
874 	 * of vsw then this code can go, but until then we need to
875 	 * update all flow entries.
876 	 */
877 	for (flent = mcip->mci_flent_list; flent != NULL;
878 	    flent = flent->fe_client_next) {
879 		mac_flow_get_desc(flent, &flow_desc);
880 		if (!(flent->fe_type & FLOW_PRIMARY_MAC ||
881 		    flent->fe_type & FLOW_VNIC_MAC))
882 			continue;
883 
884 		bcopy(map->ma_addr, flow_desc.fd_dst_mac, map->ma_len);
885 		mac_flow_set_desc(flent, &flow_desc);
886 	}
887 }
888 
889 /*
890  * Update all clients that share the same unicast address.
891  */
892 void
893 mac_unicast_update_clients(mac_impl_t *mip, mac_address_t *map)
894 {
895 	mac_client_impl_t *mcip;
896 
897 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
898 
899 	/*
900 	 * Find all clients that share the same unicast MAC address and update
901 	 * them appropriately.
902 	 */
903 	for (mcip = mip->mi_clients_list; mcip != NULL;
904 	    mcip = mcip->mci_client_next) {
905 		/*
906 		 * Ignore clients that don't share this MAC address.
907 		 */
908 		if (map != mcip->mci_unicast)
909 			continue;
910 
911 		/*
912 		 * Update those clients with same old unicast MAC address.
913 		 */
914 		mac_unicast_update_client_flow(mcip);
915 	}
916 }
917 
918 /*
919  * Update the unicast MAC address of the specified VNIC MAC client.
920  *
921  * Check whether the operation is valid. Any of following cases should fail:
922  *
923  * 1. It's a VLAN type of VNIC.
924  * 2. The new value is current "primary" MAC address.
925  * 3. The current MAC address is shared with other clients.
926  * 4. The new MAC address has been used. This case will be valid when
927  *    client migration is fully supported.
928  */
929 int
930 mac_vnic_unicast_set(mac_client_handle_t mch, const uint8_t *addr)
931 {
932 	mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
933 	mac_impl_t *mip = mcip->mci_mip;
934 	mac_address_t *map = mcip->mci_unicast;
935 	int err;
936 
937 	ASSERT(!(mip->mi_state_flags & MIS_IS_VNIC));
938 	ASSERT(mcip->mci_state_flags & MCIS_IS_VNIC);
939 	ASSERT(mcip->mci_flags != MAC_CLIENT_FLAGS_PRIMARY);
940 
941 	i_mac_perim_enter(mip);
942 
943 	/*
944 	 * If this is a VLAN type of VNIC, it's using "primary" MAC address
945 	 * of the underlying interface. Must fail here. Refer to case 1 above.
946 	 */
947 	if (bcmp(map->ma_addr, mip->mi_addr, map->ma_len) == 0) {
948 		i_mac_perim_exit(mip);
949 		return (ENOTSUP);
950 	}
951 
952 	/*
953 	 * If the new address is the "primary" one, must fail. Refer to
954 	 * case 2 above.
955 	 */
956 	if (bcmp(addr, mip->mi_addr, map->ma_len) == 0) {
957 		i_mac_perim_exit(mip);
958 		return (EACCES);
959 	}
960 
961 	/*
962 	 * If the address is shared by multiple clients, must fail. Refer
963 	 * to case 3 above.
964 	 */
965 	if (mac_check_macaddr_shared(map)) {
966 		i_mac_perim_exit(mip);
967 		return (EBUSY);
968 	}
969 
970 	/*
971 	 * If the new address has been used, must fail for now. Refer to
972 	 * case 4 above.
973 	 */
974 	if (mac_find_macaddr(mip, (uint8_t *)addr) != NULL) {
975 		i_mac_perim_exit(mip);
976 		return (ENOTSUP);
977 	}
978 
979 	/*
980 	 * Update the MAC address.
981 	 */
982 	err = mac_update_macaddr(map, (uint8_t *)addr);
983 
984 	if (err != 0) {
985 		i_mac_perim_exit(mip);
986 		return (err);
987 	}
988 
989 	/*
990 	 * Update all flows of this MAC client.
991 	 */
992 	mac_unicast_update_client_flow(mcip);
993 
994 	i_mac_perim_exit(mip);
995 	return (0);
996 }
997 
998 /*
999  * Program the new primary unicast address of the specified MAC.
1000  *
1001  * Function mac_update_macaddr() takes care different types of underlying
1002  * MAC. If the underlying MAC is VNIC, the VNIC driver must have registerd
1003  * mi_unicst() entry point, that indirectly calls mac_vnic_unicast_set()
1004  * which will take care of updating the MAC address of the corresponding
1005  * MAC client.
1006  *
1007  * This is the only interface that allow the client to update the "primary"
1008  * MAC address of the underlying MAC. The new value must have not been
1009  * used by other clients.
1010  */
1011 int
1012 mac_unicast_primary_set(mac_handle_t mh, const uint8_t *addr)
1013 {
1014 	mac_impl_t *mip = (mac_impl_t *)mh;
1015 	mac_address_t *map;
1016 	int err;
1017 
1018 	/* verify the address validity */
1019 	if (!mac_unicst_verify(mh, addr, mip->mi_type->mt_addr_length))
1020 		return (EINVAL);
1021 
1022 	i_mac_perim_enter(mip);
1023 
1024 	/*
1025 	 * If the new value is the same as the current primary address value,
1026 	 * there's nothing to do.
1027 	 */
1028 	if (bcmp(addr, mip->mi_addr, mip->mi_type->mt_addr_length) == 0) {
1029 		i_mac_perim_exit(mip);
1030 		return (0);
1031 	}
1032 
1033 	if (mac_find_macaddr(mip, (uint8_t *)addr) != NULL) {
1034 		i_mac_perim_exit(mip);
1035 		return (EBUSY);
1036 	}
1037 
1038 	map = mac_find_macaddr(mip, mip->mi_addr);
1039 	ASSERT(map != NULL);
1040 
1041 	/*
1042 	 * Update the MAC address.
1043 	 */
1044 	if (mip->mi_state_flags & MIS_IS_AGGR) {
1045 		mac_capab_aggr_t aggr_cap;
1046 
1047 		/*
1048 		 * If the MAC is an aggregation, other than the unicast
1049 		 * addresses programming, aggr must be informed about this
1050 		 * primary unicst address change to change its MAC address
1051 		 * policy to be user-specified.
1052 		 */
1053 		ASSERT(map->ma_type == MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED);
1054 		VERIFY(i_mac_capab_get(mh, MAC_CAPAB_AGGR, &aggr_cap));
1055 		err = aggr_cap.mca_unicst(mip->mi_driver, addr);
1056 		if (err == 0)
1057 			bcopy(addr, map->ma_addr, map->ma_len);
1058 	} else {
1059 		err = mac_update_macaddr(map, (uint8_t *)addr);
1060 	}
1061 
1062 	if (err != 0) {
1063 		i_mac_perim_exit(mip);
1064 		return (err);
1065 	}
1066 
1067 	mac_unicast_update_clients(mip, map);
1068 
1069 	/*
1070 	 * Save the new primary MAC address in mac_impl_t.
1071 	 */
1072 	bcopy(addr, mip->mi_addr, mip->mi_type->mt_addr_length);
1073 
1074 	i_mac_perim_exit(mip);
1075 
1076 	if (err == 0)
1077 		i_mac_notify(mip, MAC_NOTE_UNICST);
1078 
1079 	return (err);
1080 }
1081 
1082 /*
1083  * Return the current primary MAC address of the specified MAC.
1084  */
1085 void
1086 mac_unicast_primary_get(mac_handle_t mh, uint8_t *addr)
1087 {
1088 	mac_impl_t *mip = (mac_impl_t *)mh;
1089 
1090 	rw_enter(&mip->mi_rw_lock, RW_READER);
1091 	bcopy(mip->mi_addr, addr, mip->mi_type->mt_addr_length);
1092 	rw_exit(&mip->mi_rw_lock);
1093 }
1094 
1095 /*
1096  * Return the secondary MAC address for the specified handle
1097  */
1098 void
1099 mac_unicast_secondary_get(mac_client_handle_t mh, uint8_t *addr)
1100 {
1101 	mac_client_impl_t *mcip = (mac_client_impl_t *)mh;
1102 
1103 	ASSERT(mcip->mci_unicast != NULL);
1104 	bcopy(mcip->mci_unicast->ma_addr, addr, mcip->mci_unicast->ma_len);
1105 }
1106 
1107 /*
1108  * Return information about the use of the primary MAC address of the
1109  * specified MAC instance:
1110  *
1111  * - if client_name is non-NULL, it must point to a string of at
1112  *   least MAXNAMELEN bytes, and will be set to the name of the MAC
1113  *   client which uses the primary MAC address.
1114  *
1115  * - if in_use is non-NULL, used to return whether the primary MAC
1116  *   address is currently in use.
1117  */
1118 void
1119 mac_unicast_primary_info(mac_handle_t mh, char *client_name, boolean_t *in_use)
1120 {
1121 	mac_impl_t *mip = (mac_impl_t *)mh;
1122 	mac_client_impl_t *cur_client;
1123 
1124 	if (in_use != NULL)
1125 		*in_use = B_FALSE;
1126 	if (client_name != NULL)
1127 		bzero(client_name, MAXNAMELEN);
1128 
1129 	/*
1130 	 * The mi_rw_lock is used to protect threads that don't hold the
1131 	 * mac perimeter to get a consistent view of the mi_clients_list.
1132 	 * Threads that modify the list must hold both the mac perimeter and
1133 	 * mi_rw_lock(RW_WRITER)
1134 	 */
1135 	rw_enter(&mip->mi_rw_lock, RW_READER);
1136 	for (cur_client = mip->mi_clients_list; cur_client != NULL;
1137 	    cur_client = cur_client->mci_client_next) {
1138 		if (mac_is_primary_client(cur_client) ||
1139 		    (mip->mi_state_flags & MIS_IS_VNIC)) {
1140 			rw_exit(&mip->mi_rw_lock);
1141 			if (in_use != NULL)
1142 				*in_use = B_TRUE;
1143 			if (client_name != NULL) {
1144 				bcopy(cur_client->mci_name, client_name,
1145 				    MAXNAMELEN);
1146 			}
1147 			return;
1148 		}
1149 	}
1150 	rw_exit(&mip->mi_rw_lock);
1151 }
1152 
1153 /*
1154  * Return the current destination MAC address of the specified MAC.
1155  */
1156 boolean_t
1157 mac_dst_get(mac_handle_t mh, uint8_t *addr)
1158 {
1159 	mac_impl_t *mip = (mac_impl_t *)mh;
1160 
1161 	rw_enter(&mip->mi_rw_lock, RW_READER);
1162 	if (mip->mi_dstaddr_set)
1163 		bcopy(mip->mi_dstaddr, addr, mip->mi_type->mt_addr_length);
1164 	rw_exit(&mip->mi_rw_lock);
1165 	return (mip->mi_dstaddr_set);
1166 }
1167 
1168 /*
1169  * Add the specified MAC client to the list of clients which opened
1170  * the specified MAC.
1171  */
1172 static void
1173 mac_client_add(mac_client_impl_t *mcip)
1174 {
1175 	mac_impl_t *mip = mcip->mci_mip;
1176 
1177 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
1178 
1179 	/* add VNIC to the front of the list */
1180 	rw_enter(&mip->mi_rw_lock, RW_WRITER);
1181 	mcip->mci_client_next = mip->mi_clients_list;
1182 	mip->mi_clients_list = mcip;
1183 	mip->mi_nclients++;
1184 	rw_exit(&mip->mi_rw_lock);
1185 }
1186 
1187 /*
1188  * Remove the specified MAC client from the list of clients which opened
1189  * the specified MAC.
1190  */
1191 static void
1192 mac_client_remove(mac_client_impl_t *mcip)
1193 {
1194 	mac_impl_t *mip = mcip->mci_mip;
1195 	mac_client_impl_t **prev, *cclient;
1196 
1197 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
1198 
1199 	rw_enter(&mip->mi_rw_lock, RW_WRITER);
1200 	prev = &mip->mi_clients_list;
1201 	cclient = *prev;
1202 	while (cclient != NULL && cclient != mcip) {
1203 		prev = &cclient->mci_client_next;
1204 		cclient = *prev;
1205 	}
1206 	ASSERT(cclient != NULL);
1207 	*prev = cclient->mci_client_next;
1208 	mip->mi_nclients--;
1209 	rw_exit(&mip->mi_rw_lock);
1210 }
1211 
1212 static mac_unicast_impl_t *
1213 mac_client_find_vid(mac_client_impl_t *mcip, uint16_t vid)
1214 {
1215 	mac_unicast_impl_t *muip = mcip->mci_unicast_list;
1216 
1217 	while ((muip != NULL) && (muip->mui_vid != vid))
1218 		muip = muip->mui_next;
1219 
1220 	return (muip);
1221 }
1222 
1223 /*
1224  * Return whether the specified (MAC address, VID) tuple is already used by
1225  * one of the MAC clients associated with the specified MAC.
1226  */
1227 static boolean_t
1228 mac_addr_in_use(mac_impl_t *mip, uint8_t *mac_addr, uint16_t vid)
1229 {
1230 	mac_client_impl_t *client;
1231 	mac_address_t *map;
1232 
1233 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
1234 
1235 	for (client = mip->mi_clients_list; client != NULL;
1236 	    client = client->mci_client_next) {
1237 
1238 		/*
1239 		 * Ignore clients that don't have unicast address.
1240 		 */
1241 		if (client->mci_unicast_list == NULL)
1242 			continue;
1243 
1244 		map = client->mci_unicast;
1245 
1246 		if ((bcmp(mac_addr, map->ma_addr, map->ma_len) == 0) &&
1247 		    (mac_client_find_vid(client, vid) != NULL)) {
1248 			return (B_TRUE);
1249 		}
1250 	}
1251 
1252 	return (B_FALSE);
1253 }
1254 
1255 /*
1256  * Generate a random MAC address. The MAC address prefix is
1257  * stored in the array pointed to by mac_addr, and its length, in bytes,
1258  * is specified by prefix_len. The least significant bits
1259  * after prefix_len bytes are generated, and stored after the prefix
1260  * in the mac_addr array.
1261  */
1262 int
1263 mac_addr_random(mac_client_handle_t mch, uint_t prefix_len,
1264     uint8_t *mac_addr, mac_diag_t *diag)
1265 {
1266 	mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
1267 	mac_impl_t *mip = mcip->mci_mip;
1268 	size_t addr_len = mip->mi_type->mt_addr_length;
1269 
1270 	if (prefix_len >= addr_len) {
1271 		*diag = MAC_DIAG_MACPREFIXLEN_INVALID;
1272 		return (EINVAL);
1273 	}
1274 
1275 	/* check the prefix value */
1276 	if (prefix_len > 0) {
1277 		bzero(mac_addr + prefix_len, addr_len - prefix_len);
1278 		if (!mac_unicst_verify((mac_handle_t)mip, mac_addr,
1279 		    addr_len)) {
1280 			*diag = MAC_DIAG_MACPREFIX_INVALID;
1281 			return (EINVAL);
1282 		}
1283 	}
1284 
1285 	/* generate the MAC address */
1286 	if (prefix_len < addr_len) {
1287 		(void) random_get_pseudo_bytes(mac_addr +
1288 		    prefix_len, addr_len - prefix_len);
1289 	}
1290 
1291 	*diag = MAC_DIAG_NONE;
1292 	return (0);
1293 }
1294 
1295 /*
1296  * Set the priority range for this MAC client. This will be used to
1297  * determine the absolute priority for the threads created for this
1298  * MAC client using the specified "low", "medium" and "high" level.
1299  * This will also be used for any subflows on this MAC client.
1300  */
1301 #define	MAC_CLIENT_SET_PRIORITY_RANGE(mcip, pri) {			\
1302 	(mcip)->mci_min_pri = FLOW_MIN_PRIORITY(MINCLSYSPRI,	\
1303 	    MAXCLSYSPRI, (pri));					\
1304 	(mcip)->mci_max_pri = FLOW_MAX_PRIORITY(MINCLSYSPRI,	\
1305 	    MAXCLSYSPRI, (mcip)->mci_min_pri);				\
1306 	}
1307 
1308 /*
1309  * MAC client open entry point. Return a new MAC client handle. Each
1310  * MAC client is associated with a name, specified through the 'name'
1311  * argument.
1312  */
1313 int
1314 mac_client_open(mac_handle_t mh, mac_client_handle_t *mchp, char *name,
1315     uint16_t flags)
1316 {
1317 	mac_impl_t		*mip = (mac_impl_t *)mh;
1318 	mac_client_impl_t	*mcip;
1319 	int			err = 0;
1320 	boolean_t		share_desired;
1321 	flow_entry_t		*flent = NULL;
1322 
1323 	share_desired = (flags & MAC_OPEN_FLAGS_SHARES_DESIRED) != 0;
1324 	*mchp = NULL;
1325 
1326 	i_mac_perim_enter(mip);
1327 
1328 	if (mip->mi_state_flags & MIS_IS_VNIC) {
1329 		/*
1330 		 * The underlying MAC is a VNIC. Return the MAC client
1331 		 * handle of the lower MAC which was obtained by
1332 		 * the VNIC driver when it did its mac_client_open().
1333 		 */
1334 
1335 		mcip = mac_vnic_lower(mip);
1336 
1337 		/*
1338 		 * Note that multiple mac clients share the same mcip in
1339 		 * this case.
1340 		 */
1341 		if (flags & MAC_OPEN_FLAGS_EXCLUSIVE)
1342 			mcip->mci_state_flags |= MCIS_EXCLUSIVE;
1343 
1344 		if (flags & MAC_OPEN_FLAGS_MULTI_PRIMARY)
1345 			mcip->mci_flags |= MAC_CLIENT_FLAGS_MULTI_PRIMARY;
1346 
1347 		mip->mi_clients_list = mcip;
1348 		i_mac_perim_exit(mip);
1349 		*mchp = (mac_client_handle_t)mcip;
1350 
1351 		DTRACE_PROBE2(mac__client__open__nonallocated, mac_impl_t *,
1352 		    mcip->mci_mip, mac_client_impl_t *, mcip);
1353 
1354 		return (err);
1355 	}
1356 
1357 	mcip = kmem_cache_alloc(mac_client_impl_cache, KM_SLEEP);
1358 
1359 	mcip->mci_mip = mip;
1360 	mcip->mci_upper_mip = NULL;
1361 	mcip->mci_rx_fn = mac_rx_def;
1362 	mcip->mci_rx_arg = NULL;
1363 	mcip->mci_rx_p_fn = NULL;
1364 	mcip->mci_rx_p_arg = NULL;
1365 	mcip->mci_p_unicast_list = NULL;
1366 	mcip->mci_direct_rx_fn = NULL;
1367 	mcip->mci_direct_rx_arg = NULL;
1368 	mcip->mci_vidcache = MCIP_VIDCACHE_INVALID;
1369 
1370 	mcip->mci_unicast_list = NULL;
1371 
1372 	if ((flags & MAC_OPEN_FLAGS_IS_VNIC) != 0)
1373 		mcip->mci_state_flags |= MCIS_IS_VNIC;
1374 
1375 	if ((flags & MAC_OPEN_FLAGS_EXCLUSIVE) != 0)
1376 		mcip->mci_state_flags |= MCIS_EXCLUSIVE;
1377 
1378 	if ((flags & MAC_OPEN_FLAGS_IS_AGGR_PORT) != 0)
1379 		mcip->mci_state_flags |= MCIS_IS_AGGR_PORT;
1380 
1381 	if (mip->mi_state_flags & MIS_IS_AGGR)
1382 		mcip->mci_state_flags |= MCIS_IS_AGGR_CLIENT;
1383 
1384 	if ((flags & MAC_OPEN_FLAGS_USE_DATALINK_NAME) != 0) {
1385 		datalink_id_t	linkid;
1386 
1387 		ASSERT(name == NULL);
1388 		if ((err = dls_devnet_macname2linkid(mip->mi_name,
1389 		    &linkid)) != 0) {
1390 			goto done;
1391 		}
1392 		if ((err = dls_mgmt_get_linkinfo(linkid, mcip->mci_name, NULL,
1393 		    NULL, NULL)) != 0) {
1394 			/*
1395 			 * Use mac name if dlmgmtd is not available.
1396 			 */
1397 			if (err == EBADF) {
1398 				(void) strlcpy(mcip->mci_name, mip->mi_name,
1399 				    sizeof (mcip->mci_name));
1400 				err = 0;
1401 			} else {
1402 				goto done;
1403 			}
1404 		}
1405 		mcip->mci_state_flags |= MCIS_USE_DATALINK_NAME;
1406 	} else {
1407 		ASSERT(name != NULL);
1408 		if (strlen(name) > MAXNAMELEN) {
1409 			err = EINVAL;
1410 			goto done;
1411 		}
1412 		(void) strlcpy(mcip->mci_name, name, sizeof (mcip->mci_name));
1413 	}
1414 
1415 	if (flags & MAC_OPEN_FLAGS_MULTI_PRIMARY)
1416 		mcip->mci_flags |= MAC_CLIENT_FLAGS_MULTI_PRIMARY;
1417 
1418 	if (flags & MAC_OPEN_FLAGS_NO_UNICAST_ADDR)
1419 		mcip->mci_state_flags |= MCIS_NO_UNICAST_ADDR;
1420 
1421 	mac_protect_init(mcip);
1422 
1423 	/* the subflow table will be created dynamically */
1424 	mcip->mci_subflow_tab = NULL;
1425 
1426 	mcip->mci_misc_stat.mms_multircv = 0;
1427 	mcip->mci_misc_stat.mms_brdcstrcv = 0;
1428 	mcip->mci_misc_stat.mms_multixmt = 0;
1429 	mcip->mci_misc_stat.mms_brdcstxmt = 0;
1430 
1431 	/* Create an initial flow */
1432 
1433 	err = mac_flow_create(NULL, NULL, mcip->mci_name, NULL,
1434 	    mcip->mci_state_flags & MCIS_IS_VNIC ? FLOW_VNIC_MAC :
1435 	    FLOW_PRIMARY_MAC, &flent);
1436 	if (err != 0)
1437 		goto done;
1438 	mcip->mci_flent = flent;
1439 	FLOW_MARK(flent, FE_MC_NO_DATAPATH);
1440 	flent->fe_mcip = mcip;
1441 
1442 	/*
1443 	 * Place initial creation reference on the flow. This reference
1444 	 * is released in the corresponding delete action viz.
1445 	 * mac_unicast_remove after waiting for all transient refs to
1446 	 * to go away. The wait happens in mac_flow_wait.
1447 	 */
1448 	FLOW_REFHOLD(flent);
1449 
1450 	/*
1451 	 * Do this ahead of the mac_bcast_add() below so that the mi_nclients
1452 	 * will have the right value for mac_rx_srs_setup().
1453 	 */
1454 	mac_client_add(mcip);
1455 
1456 	mcip->mci_share = 0;
1457 	if (share_desired)
1458 		i_mac_share_alloc(mcip);
1459 
1460 	/*
1461 	 * We will do mimimal datapath setup to allow a MAC client to
1462 	 * transmit or receive non-unicast packets without waiting
1463 	 * for mac_unicast_add.
1464 	 */
1465 	if (mcip->mci_state_flags & MCIS_NO_UNICAST_ADDR) {
1466 		if ((err = mac_client_datapath_setup(mcip, VLAN_ID_NONE,
1467 		    NULL, NULL, B_TRUE, NULL)) != 0) {
1468 			goto done;
1469 		}
1470 	}
1471 
1472 	DTRACE_PROBE2(mac__client__open__allocated, mac_impl_t *,
1473 	    mcip->mci_mip, mac_client_impl_t *, mcip);
1474 
1475 	*mchp = (mac_client_handle_t)mcip;
1476 	i_mac_perim_exit(mip);
1477 	return (0);
1478 
1479 done:
1480 	i_mac_perim_exit(mip);
1481 	mcip->mci_state_flags = 0;
1482 	mcip->mci_tx_flag = 0;
1483 	kmem_cache_free(mac_client_impl_cache, mcip);
1484 	return (err);
1485 }
1486 
1487 /*
1488  * Close the specified MAC client handle.
1489  */
1490 void
1491 mac_client_close(mac_client_handle_t mch, uint16_t flags)
1492 {
1493 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
1494 	mac_impl_t		*mip = mcip->mci_mip;
1495 	flow_entry_t		*flent;
1496 
1497 	i_mac_perim_enter(mip);
1498 
1499 	if (flags & MAC_CLOSE_FLAGS_EXCLUSIVE)
1500 		mcip->mci_state_flags &= ~MCIS_EXCLUSIVE;
1501 
1502 	if ((mcip->mci_state_flags & MCIS_IS_VNIC) &&
1503 	    !(flags & MAC_CLOSE_FLAGS_IS_VNIC)) {
1504 		/*
1505 		 * This is an upper VNIC client initiated operation.
1506 		 * The lower MAC client will be closed by the VNIC driver
1507 		 * when the VNIC is deleted.
1508 		 */
1509 
1510 		i_mac_perim_exit(mip);
1511 		return;
1512 	}
1513 
1514 	/* If we have only setup up minimal datapth setup, tear it down */
1515 	if (mcip->mci_state_flags & MCIS_NO_UNICAST_ADDR) {
1516 		mac_client_datapath_teardown((mac_client_handle_t)mcip, NULL,
1517 		    mcip->mci_flent);
1518 		mcip->mci_state_flags &= ~MCIS_NO_UNICAST_ADDR;
1519 	}
1520 
1521 	/*
1522 	 * Remove the flent associated with the MAC client
1523 	 */
1524 	flent = mcip->mci_flent;
1525 	mcip->mci_flent = NULL;
1526 	FLOW_FINAL_REFRELE(flent);
1527 
1528 	/*
1529 	 * MAC clients must remove the unicast addresses and promisc callbacks
1530 	 * they added before issuing a mac_client_close().
1531 	 */
1532 	ASSERT(mcip->mci_unicast_list == NULL);
1533 	ASSERT(mcip->mci_promisc_list == NULL);
1534 	ASSERT(mcip->mci_tx_notify_cb_list == NULL);
1535 
1536 	i_mac_share_free(mcip);
1537 	mac_protect_fini(mcip);
1538 	mac_client_remove(mcip);
1539 
1540 	i_mac_perim_exit(mip);
1541 	mcip->mci_subflow_tab = NULL;
1542 	mcip->mci_state_flags = 0;
1543 	mcip->mci_tx_flag = 0;
1544 	kmem_cache_free(mac_client_impl_cache, mch);
1545 }
1546 
1547 /*
1548  * Set the Rx bypass receive callback and return B_TRUE. Return
1549  * B_FALSE if it's not possible to enable bypass.
1550  */
1551 boolean_t
1552 mac_rx_bypass_set(mac_client_handle_t mch, mac_direct_rx_t rx_fn, void *arg1)
1553 {
1554 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
1555 	mac_impl_t		*mip = mcip->mci_mip;
1556 
1557 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
1558 
1559 	/*
1560 	 * If the client has more than one VLAN then process packets
1561 	 * through DLS. This should happen only when sun4v vsw is on
1562 	 * the scene.
1563 	 */
1564 	if (mcip->mci_nvids > 1)
1565 		return (B_FALSE);
1566 
1567 	/*
1568 	 * These are not accessed directly in the data path, and hence
1569 	 * don't need any protection
1570 	 */
1571 	mcip->mci_direct_rx_fn = rx_fn;
1572 	mcip->mci_direct_rx_arg = arg1;
1573 	return (B_TRUE);
1574 }
1575 
1576 /*
1577  * Enable/Disable rx bypass. By default, bypass is assumed to be enabled.
1578  */
1579 void
1580 mac_rx_bypass_enable(mac_client_handle_t mch)
1581 {
1582 	((mac_client_impl_t *)mch)->mci_state_flags &= ~MCIS_RX_BYPASS_DISABLE;
1583 }
1584 
1585 void
1586 mac_rx_bypass_disable(mac_client_handle_t mch)
1587 {
1588 	((mac_client_impl_t *)mch)->mci_state_flags |= MCIS_RX_BYPASS_DISABLE;
1589 }
1590 
1591 /*
1592  * Set the receive callback for the specified MAC client. There can be
1593  * at most one such callback per MAC client.
1594  */
1595 void
1596 mac_rx_set(mac_client_handle_t mch, mac_rx_t rx_fn, void *arg)
1597 {
1598 	mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
1599 	mac_impl_t	*mip = mcip->mci_mip;
1600 	mac_impl_t	*umip = mcip->mci_upper_mip;
1601 
1602 	/*
1603 	 * Instead of adding an extra set of locks and refcnts in
1604 	 * the datapath at the mac client boundary, we temporarily quiesce
1605 	 * the SRS and related entities. We then change the receive function
1606 	 * without interference from any receive data thread and then reenable
1607 	 * the data flow subsequently.
1608 	 */
1609 	i_mac_perim_enter(mip);
1610 	mac_rx_client_quiesce(mch);
1611 
1612 	mcip->mci_rx_fn = rx_fn;
1613 	mcip->mci_rx_arg = arg;
1614 	mac_rx_client_restart(mch);
1615 	i_mac_perim_exit(mip);
1616 
1617 	/*
1618 	 * If we're changing the Rx function on the primary MAC of a VNIC,
1619 	 * make sure any secondary addresses on the VNIC are updated as well.
1620 	 */
1621 	if (umip != NULL) {
1622 		ASSERT((umip->mi_state_flags & MIS_IS_VNIC) != 0);
1623 		mac_vnic_secondary_update(umip);
1624 	}
1625 }
1626 
1627 /*
1628  * Reset the receive callback for the specified MAC client.
1629  */
1630 void
1631 mac_rx_clear(mac_client_handle_t mch)
1632 {
1633 	mac_rx_set(mch, mac_rx_def, NULL);
1634 }
1635 
1636 void
1637 mac_rx_barrier(mac_client_handle_t mch)
1638 {
1639 	mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
1640 	mac_impl_t *mip = mcip->mci_mip;
1641 
1642 	i_mac_perim_enter(mip);
1643 
1644 	/* If a RX callback is set, quiesce and restart that datapath */
1645 	if (mcip->mci_rx_fn != mac_rx_def) {
1646 		mac_rx_client_quiesce(mch);
1647 		mac_rx_client_restart(mch);
1648 	}
1649 
1650 	/* If any promisc callbacks are registered, perform a barrier there */
1651 	if (mcip->mci_promisc_list != NULL || mip->mi_promisc_list != NULL) {
1652 		mac_cb_info_t *mcbi =  &mip->mi_promisc_cb_info;
1653 
1654 		mutex_enter(mcbi->mcbi_lockp);
1655 		mac_callback_barrier(mcbi);
1656 		mutex_exit(mcbi->mcbi_lockp);
1657 	}
1658 
1659 	i_mac_perim_exit(mip);
1660 }
1661 
1662 void
1663 mac_secondary_dup(mac_client_handle_t smch, mac_client_handle_t dmch)
1664 {
1665 	mac_client_impl_t *smcip = (mac_client_impl_t *)smch;
1666 	mac_client_impl_t *dmcip = (mac_client_impl_t *)dmch;
1667 	flow_entry_t *flent = dmcip->mci_flent;
1668 
1669 	/* This should only be called to setup secondary macs */
1670 	ASSERT((flent->fe_type & FLOW_PRIMARY_MAC) == 0);
1671 
1672 	mac_rx_set(dmch, smcip->mci_rx_fn, smcip->mci_rx_arg);
1673 	dmcip->mci_promisc_list = smcip->mci_promisc_list;
1674 
1675 	/*
1676 	 * Duplicate the primary mac resources to the secondary.
1677 	 * Since we already validated the resource controls when setting
1678 	 * them on the primary, we can ignore errors here.
1679 	 */
1680 	(void) mac_resource_ctl_set(dmch, MCIP_RESOURCE_PROPS(smcip));
1681 }
1682 
1683 /*
1684  * Called when removing a secondary MAC. Currently only clears the promisc_list
1685  * since we share the primary mac's promisc_list.
1686  */
1687 void
1688 mac_secondary_cleanup(mac_client_handle_t mch)
1689 {
1690 	mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
1691 	flow_entry_t *flent = mcip->mci_flent;
1692 
1693 	/* This should only be called for secondary macs */
1694 	ASSERT((flent->fe_type & FLOW_PRIMARY_MAC) == 0);
1695 	mcip->mci_promisc_list = NULL;
1696 }
1697 
1698 /*
1699  * Walk the MAC client subflow table and updates their priority values.
1700  */
1701 static int
1702 mac_update_subflow_priority_cb(flow_entry_t *flent, void *arg)
1703 {
1704 	mac_flow_update_priority(arg, flent);
1705 	return (0);
1706 }
1707 
1708 void
1709 mac_update_subflow_priority(mac_client_impl_t *mcip)
1710 {
1711 	(void) mac_flow_walk(mcip->mci_subflow_tab,
1712 	    mac_update_subflow_priority_cb, mcip);
1713 }
1714 
1715 /*
1716  * Modify the TX or RX ring properties. We could either just move around
1717  * rings, i.e add/remove rings given to a client. Or this might cause the
1718  * client to move from hardware based to software or the other way around.
1719  * If we want to reset this property, then we clear the mask, additionally
1720  * if the client was given a non-default group we remove all rings except
1721  * for 1 and give it back to the default group.
1722  */
1723 int
1724 mac_client_set_rings_prop(mac_client_impl_t *mcip, mac_resource_props_t *mrp,
1725     mac_resource_props_t *tmrp)
1726 {
1727 	mac_impl_t		*mip = mcip->mci_mip;
1728 	flow_entry_t		*flent = mcip->mci_flent;
1729 	uint8_t			*mac_addr;
1730 	int			err = 0;
1731 	mac_group_t		*defgrp;
1732 	mac_group_t		*group;
1733 	mac_group_t		*ngrp;
1734 	mac_resource_props_t	*cmrp = MCIP_RESOURCE_PROPS(mcip);
1735 	uint_t			ringcnt;
1736 	boolean_t		unspec;
1737 
1738 	if (mcip->mci_share != 0)
1739 		return (EINVAL);
1740 
1741 	if (mrp->mrp_mask & MRP_RX_RINGS) {
1742 		unspec = mrp->mrp_mask & MRP_RXRINGS_UNSPEC;
1743 		group = flent->fe_rx_ring_group;
1744 		defgrp = MAC_DEFAULT_RX_GROUP(mip);
1745 		mac_addr = flent->fe_flow_desc.fd_dst_mac;
1746 
1747 		/*
1748 		 * No resulting change. If we are resetting on a client on
1749 		 * which there was no rx rings property. For dynamic group
1750 		 * if we are setting the same number of rings already set.
1751 		 * For static group if we are requesting a group again.
1752 		 */
1753 		if (mrp->mrp_mask & MRP_RINGS_RESET) {
1754 			if (!(tmrp->mrp_mask & MRP_RX_RINGS))
1755 				return (0);
1756 		} else {
1757 			if (unspec) {
1758 				if (tmrp->mrp_mask & MRP_RXRINGS_UNSPEC)
1759 					return (0);
1760 			} else if (mip->mi_rx_group_type ==
1761 			    MAC_GROUP_TYPE_DYNAMIC) {
1762 				if ((tmrp->mrp_mask & MRP_RX_RINGS) &&
1763 				    !(tmrp->mrp_mask & MRP_RXRINGS_UNSPEC) &&
1764 				    mrp->mrp_nrxrings == tmrp->mrp_nrxrings) {
1765 					return (0);
1766 				}
1767 			}
1768 		}
1769 		/* Resetting the prop */
1770 		if (mrp->mrp_mask & MRP_RINGS_RESET) {
1771 			/*
1772 			 * We will just keep one ring and give others back if
1773 			 * we are not the primary. For the primary we give
1774 			 * all the rings in the default group except the
1775 			 * default ring. If it is a static group, then
1776 			 * we don't do anything, but clear the MRP_RX_RINGS
1777 			 * flag.
1778 			 */
1779 			if (group != defgrp) {
1780 				if (mip->mi_rx_group_type ==
1781 				    MAC_GROUP_TYPE_DYNAMIC) {
1782 					/*
1783 					 * This group has reserved rings
1784 					 * that need to be released now,
1785 					 * so does the group.
1786 					 */
1787 					MAC_RX_RING_RELEASED(mip,
1788 					    group->mrg_cur_count);
1789 					MAC_RX_GRP_RELEASED(mip);
1790 					if ((flent->fe_type &
1791 					    FLOW_PRIMARY_MAC) != 0) {
1792 						if (mip->mi_nactiveclients ==
1793 						    1) {
1794 							(void)
1795 							    mac_rx_switch_group(
1796 							    mcip, group,
1797 							    defgrp);
1798 							return (0);
1799 						} else {
1800 							cmrp->mrp_nrxrings =
1801 							    group->
1802 							    mrg_cur_count +
1803 							    defgrp->
1804 							    mrg_cur_count - 1;
1805 						}
1806 					} else {
1807 						cmrp->mrp_nrxrings = 1;
1808 					}
1809 					(void) mac_group_ring_modify(mcip,
1810 					    group, defgrp);
1811 				} else {
1812 					/*
1813 					 * If this is a static group, we
1814 					 * need to release the group. The
1815 					 * client will remain in the same
1816 					 * group till some other client
1817 					 * needs this group.
1818 					 */
1819 					MAC_RX_GRP_RELEASED(mip);
1820 				}
1821 			/* Let check if we can give this an excl group */
1822 			} else if (group == defgrp) {
1823 				/*
1824 				 * If multiple clients share an
1825 				 * address then they must stay on the
1826 				 * default group.
1827 				 */
1828 				if (mac_check_macaddr_shared(mcip->mci_unicast))
1829 					return (0);
1830 
1831 				ngrp = mac_reserve_rx_group(mcip, mac_addr,
1832 				    B_TRUE);
1833 				/* Couldn't give it a group, that's fine */
1834 				if (ngrp == NULL)
1835 					return (0);
1836 				/* Switch to H/W */
1837 				if (mac_rx_switch_group(mcip, defgrp, ngrp) !=
1838 				    0) {
1839 					mac_stop_group(ngrp);
1840 					return (0);
1841 				}
1842 			}
1843 			/*
1844 			 * If the client is in the default group, we will
1845 			 * just clear the MRP_RX_RINGS and leave it as
1846 			 * it rather than look for an exclusive group
1847 			 * for it.
1848 			 */
1849 			return (0);
1850 		}
1851 
1852 		if (group == defgrp && ((mrp->mrp_nrxrings > 0) || unspec)) {
1853 			/*
1854 			 * We are requesting Rx rings. Try to reserve
1855 			 * a non-default group.
1856 			 *
1857 			 * If multiple clients share an address then
1858 			 * they must stay on the default group.
1859 			 */
1860 			if (mac_check_macaddr_shared(mcip->mci_unicast))
1861 				return (EINVAL);
1862 
1863 			ngrp = mac_reserve_rx_group(mcip, mac_addr, B_TRUE);
1864 			if (ngrp == NULL)
1865 				return (ENOSPC);
1866 
1867 			/* Switch to H/W */
1868 			if (mac_rx_switch_group(mcip, defgrp, ngrp) != 0) {
1869 				mac_release_rx_group(mcip, ngrp);
1870 				return (ENOSPC);
1871 			}
1872 			MAC_RX_GRP_RESERVED(mip);
1873 			if (mip->mi_rx_group_type == MAC_GROUP_TYPE_DYNAMIC)
1874 				MAC_RX_RING_RESERVED(mip, ngrp->mrg_cur_count);
1875 		} else if (group != defgrp && !unspec &&
1876 		    mrp->mrp_nrxrings == 0) {
1877 			/* Switch to S/W */
1878 			ringcnt = group->mrg_cur_count;
1879 			if (mac_rx_switch_group(mcip, group, defgrp) != 0)
1880 				return (ENOSPC);
1881 			if (tmrp->mrp_mask & MRP_RX_RINGS) {
1882 				MAC_RX_GRP_RELEASED(mip);
1883 				if (mip->mi_rx_group_type ==
1884 				    MAC_GROUP_TYPE_DYNAMIC) {
1885 					MAC_RX_RING_RELEASED(mip, ringcnt);
1886 				}
1887 			}
1888 		} else if (group != defgrp && mip->mi_rx_group_type ==
1889 		    MAC_GROUP_TYPE_DYNAMIC) {
1890 			ringcnt = group->mrg_cur_count;
1891 			err = mac_group_ring_modify(mcip, group, defgrp);
1892 			if (err != 0)
1893 				return (err);
1894 			/*
1895 			 * Update the accounting. If this group
1896 			 * already had explicitly reserved rings,
1897 			 * we need to update the rings based on
1898 			 * the new ring count. If this group
1899 			 * had not explicitly reserved rings,
1900 			 * then we just reserve the rings asked for
1901 			 * and reserve the group.
1902 			 */
1903 			if (tmrp->mrp_mask & MRP_RX_RINGS) {
1904 				if (ringcnt > group->mrg_cur_count) {
1905 					MAC_RX_RING_RELEASED(mip,
1906 					    ringcnt - group->mrg_cur_count);
1907 				} else {
1908 					MAC_RX_RING_RESERVED(mip,
1909 					    group->mrg_cur_count - ringcnt);
1910 				}
1911 			} else {
1912 				MAC_RX_RING_RESERVED(mip, group->mrg_cur_count);
1913 				MAC_RX_GRP_RESERVED(mip);
1914 			}
1915 		}
1916 	}
1917 	if (mrp->mrp_mask & MRP_TX_RINGS) {
1918 		unspec = mrp->mrp_mask & MRP_TXRINGS_UNSPEC;
1919 		group = flent->fe_tx_ring_group;
1920 		defgrp = MAC_DEFAULT_TX_GROUP(mip);
1921 
1922 		/*
1923 		 * For static groups we only allow rings=0 or resetting the
1924 		 * rings property.
1925 		 */
1926 		if (mrp->mrp_ntxrings > 0 &&
1927 		    mip->mi_tx_group_type != MAC_GROUP_TYPE_DYNAMIC) {
1928 			return (ENOTSUP);
1929 		}
1930 		if (mrp->mrp_mask & MRP_RINGS_RESET) {
1931 			if (!(tmrp->mrp_mask & MRP_TX_RINGS))
1932 				return (0);
1933 		} else {
1934 			if (unspec) {
1935 				if (tmrp->mrp_mask & MRP_TXRINGS_UNSPEC)
1936 					return (0);
1937 			} else if (mip->mi_tx_group_type ==
1938 			    MAC_GROUP_TYPE_DYNAMIC) {
1939 				if ((tmrp->mrp_mask & MRP_TX_RINGS) &&
1940 				    !(tmrp->mrp_mask & MRP_TXRINGS_UNSPEC) &&
1941 				    mrp->mrp_ntxrings == tmrp->mrp_ntxrings) {
1942 					return (0);
1943 				}
1944 			}
1945 		}
1946 		/* Resetting the prop */
1947 		if (mrp->mrp_mask & MRP_RINGS_RESET) {
1948 			if (group != defgrp) {
1949 				if (mip->mi_tx_group_type ==
1950 				    MAC_GROUP_TYPE_DYNAMIC) {
1951 					ringcnt = group->mrg_cur_count;
1952 					if ((flent->fe_type &
1953 					    FLOW_PRIMARY_MAC) != 0) {
1954 						mac_tx_client_quiesce(
1955 						    (mac_client_handle_t)
1956 						    mcip);
1957 						mac_tx_switch_group(mcip,
1958 						    group, defgrp);
1959 						mac_tx_client_restart(
1960 						    (mac_client_handle_t)
1961 						    mcip);
1962 						MAC_TX_GRP_RELEASED(mip);
1963 						MAC_TX_RING_RELEASED(mip,
1964 						    ringcnt);
1965 						return (0);
1966 					}
1967 					cmrp->mrp_ntxrings = 1;
1968 					(void) mac_group_ring_modify(mcip,
1969 					    group, defgrp);
1970 					/*
1971 					 * This group has reserved rings
1972 					 * that need to be released now.
1973 					 */
1974 					MAC_TX_RING_RELEASED(mip, ringcnt);
1975 				}
1976 				/*
1977 				 * If this is a static group, we
1978 				 * need to release the group. The
1979 				 * client will remain in the same
1980 				 * group till some other client
1981 				 * needs this group.
1982 				 */
1983 				MAC_TX_GRP_RELEASED(mip);
1984 			} else if (group == defgrp &&
1985 			    (flent->fe_type & FLOW_PRIMARY_MAC) == 0) {
1986 				ngrp = mac_reserve_tx_group(mcip, B_TRUE);
1987 				if (ngrp == NULL)
1988 					return (0);
1989 				mac_tx_client_quiesce(
1990 				    (mac_client_handle_t)mcip);
1991 				mac_tx_switch_group(mcip, defgrp, ngrp);
1992 				mac_tx_client_restart(
1993 				    (mac_client_handle_t)mcip);
1994 			}
1995 			/*
1996 			 * If the client is in the default group, we will
1997 			 * just clear the MRP_TX_RINGS and leave it as
1998 			 * it rather than look for an exclusive group
1999 			 * for it.
2000 			 */
2001 			return (0);
2002 		}
2003 
2004 		/* Switch to H/W */
2005 		if (group == defgrp && ((mrp->mrp_ntxrings > 0) || unspec)) {
2006 			ngrp = mac_reserve_tx_group(mcip, B_TRUE);
2007 			if (ngrp == NULL)
2008 				return (ENOSPC);
2009 			mac_tx_client_quiesce((mac_client_handle_t)mcip);
2010 			mac_tx_switch_group(mcip, defgrp, ngrp);
2011 			mac_tx_client_restart((mac_client_handle_t)mcip);
2012 			MAC_TX_GRP_RESERVED(mip);
2013 			if (mip->mi_tx_group_type == MAC_GROUP_TYPE_DYNAMIC)
2014 				MAC_TX_RING_RESERVED(mip, ngrp->mrg_cur_count);
2015 		/* Switch to S/W */
2016 		} else if (group != defgrp && !unspec &&
2017 		    mrp->mrp_ntxrings == 0) {
2018 			/* Switch to S/W */
2019 			ringcnt = group->mrg_cur_count;
2020 			mac_tx_client_quiesce((mac_client_handle_t)mcip);
2021 			mac_tx_switch_group(mcip, group, defgrp);
2022 			mac_tx_client_restart((mac_client_handle_t)mcip);
2023 			if (tmrp->mrp_mask & MRP_TX_RINGS) {
2024 				MAC_TX_GRP_RELEASED(mip);
2025 				if (mip->mi_tx_group_type ==
2026 				    MAC_GROUP_TYPE_DYNAMIC) {
2027 					MAC_TX_RING_RELEASED(mip, ringcnt);
2028 				}
2029 			}
2030 		} else if (group != defgrp && mip->mi_tx_group_type ==
2031 		    MAC_GROUP_TYPE_DYNAMIC) {
2032 			ringcnt = group->mrg_cur_count;
2033 			err = mac_group_ring_modify(mcip, group, defgrp);
2034 			if (err != 0)
2035 				return (err);
2036 			/*
2037 			 * Update the accounting. If this group
2038 			 * already had explicitly reserved rings,
2039 			 * we need to update the rings based on
2040 			 * the new ring count. If this group
2041 			 * had not explicitly reserved rings,
2042 			 * then we just reserve the rings asked for
2043 			 * and reserve the group.
2044 			 */
2045 			if (tmrp->mrp_mask & MRP_TX_RINGS) {
2046 				if (ringcnt > group->mrg_cur_count) {
2047 					MAC_TX_RING_RELEASED(mip,
2048 					    ringcnt - group->mrg_cur_count);
2049 				} else {
2050 					MAC_TX_RING_RESERVED(mip,
2051 					    group->mrg_cur_count - ringcnt);
2052 				}
2053 			} else {
2054 				MAC_TX_RING_RESERVED(mip, group->mrg_cur_count);
2055 				MAC_TX_GRP_RESERVED(mip);
2056 			}
2057 		}
2058 	}
2059 	return (0);
2060 }
2061 
2062 /*
2063  * When the MAC client is being brought up (i.e. we do a unicast_add) we need
2064  * to initialize the cpu and resource control structure in the
2065  * mac_client_impl_t from the mac_impl_t (i.e if there are any cached
2066  * properties before the flow entry for the unicast address was created).
2067  */
2068 static int
2069 mac_resource_ctl_set(mac_client_handle_t mch, mac_resource_props_t *mrp)
2070 {
2071 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
2072 	mac_impl_t		*mip = (mac_impl_t *)mcip->mci_mip;
2073 	mac_impl_t		*umip = mcip->mci_upper_mip;
2074 	int			err = 0;
2075 	flow_entry_t		*flent = mcip->mci_flent;
2076 	mac_resource_props_t	*omrp, *nmrp = MCIP_RESOURCE_PROPS(mcip);
2077 
2078 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
2079 
2080 	err = mac_validate_props(mcip->mci_state_flags & MCIS_IS_VNIC ?
2081 	    mcip->mci_upper_mip : mip, mrp);
2082 	if (err != 0)
2083 		return (err);
2084 
2085 	/*
2086 	 * Copy over the existing properties since mac_update_resources
2087 	 * will modify the client's mrp. Currently, the saved property
2088 	 * is used to determine the difference between existing and
2089 	 * modified rings property.
2090 	 */
2091 	omrp = kmem_zalloc(sizeof (*omrp), KM_SLEEP);
2092 	bcopy(nmrp, omrp, sizeof (*omrp));
2093 	mac_update_resources(mrp, MCIP_RESOURCE_PROPS(mcip), B_FALSE);
2094 	if (MCIP_DATAPATH_SETUP(mcip)) {
2095 		/*
2096 		 * We support rings only for primary client when there are
2097 		 * multiple clients sharing the same MAC address (e.g. VLAN).
2098 		 */
2099 		if (mrp->mrp_mask & MRP_RX_RINGS ||
2100 		    mrp->mrp_mask & MRP_TX_RINGS) {
2101 
2102 			if ((err = mac_client_set_rings_prop(mcip, mrp,
2103 			    omrp)) != 0) {
2104 				if (omrp->mrp_mask & MRP_RX_RINGS) {
2105 					nmrp->mrp_mask |= MRP_RX_RINGS;
2106 					nmrp->mrp_nrxrings = omrp->mrp_nrxrings;
2107 				} else {
2108 					nmrp->mrp_mask &= ~MRP_RX_RINGS;
2109 					nmrp->mrp_nrxrings = 0;
2110 				}
2111 				if (omrp->mrp_mask & MRP_TX_RINGS) {
2112 					nmrp->mrp_mask |= MRP_TX_RINGS;
2113 					nmrp->mrp_ntxrings = omrp->mrp_ntxrings;
2114 				} else {
2115 					nmrp->mrp_mask &= ~MRP_TX_RINGS;
2116 					nmrp->mrp_ntxrings = 0;
2117 				}
2118 				if (omrp->mrp_mask & MRP_RXRINGS_UNSPEC)
2119 					omrp->mrp_mask |= MRP_RXRINGS_UNSPEC;
2120 				else
2121 					omrp->mrp_mask &= ~MRP_RXRINGS_UNSPEC;
2122 
2123 				if (omrp->mrp_mask & MRP_TXRINGS_UNSPEC)
2124 					omrp->mrp_mask |= MRP_TXRINGS_UNSPEC;
2125 				else
2126 					omrp->mrp_mask &= ~MRP_TXRINGS_UNSPEC;
2127 				kmem_free(omrp, sizeof (*omrp));
2128 				return (err);
2129 			}
2130 
2131 			/*
2132 			 * If we modified the rings property of the primary
2133 			 * we need to update the property fields of its
2134 			 * VLANs as they inherit the primary's properites.
2135 			 */
2136 			if (mac_is_primary_client(mcip)) {
2137 				mac_set_prim_vlan_rings(mip,
2138 				    MCIP_RESOURCE_PROPS(mcip));
2139 			}
2140 		}
2141 		/*
2142 		 * We have to set this prior to calling mac_flow_modify.
2143 		 */
2144 		if (mrp->mrp_mask & MRP_PRIORITY) {
2145 			if (mrp->mrp_priority == MPL_RESET) {
2146 				MAC_CLIENT_SET_PRIORITY_RANGE(mcip,
2147 				    MPL_LINK_DEFAULT);
2148 			} else {
2149 				MAC_CLIENT_SET_PRIORITY_RANGE(mcip,
2150 				    mrp->mrp_priority);
2151 			}
2152 		}
2153 
2154 		mac_flow_modify(mip->mi_flow_tab, flent, mrp);
2155 		if (mrp->mrp_mask & MRP_PRIORITY)
2156 			mac_update_subflow_priority(mcip);
2157 
2158 		/* Apply these resource settings to any secondary macs */
2159 		if (umip != NULL) {
2160 			ASSERT((umip->mi_state_flags & MIS_IS_VNIC) != 0);
2161 			mac_vnic_secondary_update(umip);
2162 		}
2163 	}
2164 	kmem_free(omrp, sizeof (*omrp));
2165 	return (0);
2166 }
2167 
2168 static int
2169 mac_unicast_flow_create(mac_client_impl_t *mcip, uint8_t *mac_addr,
2170     uint16_t vid, boolean_t is_primary, boolean_t first_flow,
2171     flow_entry_t **flent, mac_resource_props_t *mrp)
2172 {
2173 	mac_impl_t	*mip = (mac_impl_t *)mcip->mci_mip;
2174 	flow_desc_t	flow_desc;
2175 	char		flowname[MAXFLOWNAMELEN];
2176 	int		err;
2177 	uint_t		flent_flags;
2178 
2179 	/*
2180 	 * First unicast address being added, create a new flow
2181 	 * for that MAC client.
2182 	 */
2183 	bzero(&flow_desc, sizeof (flow_desc));
2184 
2185 	ASSERT(mac_addr != NULL ||
2186 	    (mcip->mci_state_flags & MCIS_NO_UNICAST_ADDR));
2187 	if (mac_addr != NULL) {
2188 		flow_desc.fd_mac_len = mip->mi_type->mt_addr_length;
2189 		bcopy(mac_addr, flow_desc.fd_dst_mac, flow_desc.fd_mac_len);
2190 	}
2191 	flow_desc.fd_mask = FLOW_LINK_DST;
2192 	if (vid != 0) {
2193 		flow_desc.fd_vid = vid;
2194 		flow_desc.fd_mask |= FLOW_LINK_VID;
2195 	}
2196 
2197 	/*
2198 	 * XXX-nicolas. For now I'm keeping the FLOW_PRIMARY_MAC
2199 	 * and FLOW_VNIC. Even though they're a hack inherited
2200 	 * from the SRS code, we'll keep them for now. They're currently
2201 	 * consumed by mac_datapath_setup() to create the SRS.
2202 	 * That code should be eventually moved out of
2203 	 * mac_datapath_setup() and moved to a mac_srs_create()
2204 	 * function of some sort to keep things clean.
2205 	 *
2206 	 * Also, there's no reason why the SRS for the primary MAC
2207 	 * client should be different than any other MAC client. Until
2208 	 * this is cleaned-up, we support only one MAC unicast address
2209 	 * per client.
2210 	 *
2211 	 * We set FLOW_PRIMARY_MAC for the primary MAC address,
2212 	 * FLOW_VNIC for everything else.
2213 	 */
2214 	if (is_primary)
2215 		flent_flags = FLOW_PRIMARY_MAC;
2216 	else
2217 		flent_flags = FLOW_VNIC_MAC;
2218 
2219 	/*
2220 	 * For the first flow we use the MAC client's name - mci_name, for
2221 	 * subsequent ones we just create a name with the VID. This is
2222 	 * so that we can add these flows to the same flow table. This is
2223 	 * fine as the flow name (except for the one with the MAC client's
2224 	 * name) is not visible. When the first flow is removed, we just replace
2225 	 * its fdesc with another from the list, so we will still retain the
2226 	 * flent with the MAC client's flow name.
2227 	 */
2228 	if (first_flow) {
2229 		bcopy(mcip->mci_name, flowname, MAXFLOWNAMELEN);
2230 	} else {
2231 		(void) sprintf(flowname, "%s%u", mcip->mci_name, vid);
2232 		flent_flags = FLOW_NO_STATS;
2233 	}
2234 
2235 	if ((err = mac_flow_create(&flow_desc, mrp, flowname, NULL,
2236 	    flent_flags, flent)) != 0)
2237 		return (err);
2238 
2239 	mac_misc_stat_create(*flent);
2240 	FLOW_MARK(*flent, FE_INCIPIENT);
2241 	(*flent)->fe_mcip = mcip;
2242 
2243 	/*
2244 	 * Place initial creation reference on the flow. This reference
2245 	 * is released in the corresponding delete action viz.
2246 	 * mac_unicast_remove after waiting for all transient refs to
2247 	 * to go away. The wait happens in mac_flow_wait.
2248 	 * We have already held the reference in mac_client_open().
2249 	 */
2250 	if (!first_flow)
2251 		FLOW_REFHOLD(*flent);
2252 	return (0);
2253 }
2254 
2255 /* Refresh the multicast grouping for this VID. */
2256 int
2257 mac_client_update_mcast(void *arg, boolean_t add, const uint8_t *addrp)
2258 {
2259 	flow_entry_t		*flent = arg;
2260 	mac_client_impl_t	*mcip = flent->fe_mcip;
2261 	uint16_t		vid;
2262 	flow_desc_t		flow_desc;
2263 
2264 	mac_flow_get_desc(flent, &flow_desc);
2265 	vid = (flow_desc.fd_mask & FLOW_LINK_VID) != 0 ?
2266 	    flow_desc.fd_vid : VLAN_ID_NONE;
2267 
2268 	/*
2269 	 * We don't call mac_multicast_add()/mac_multicast_remove() as
2270 	 * we want to add/remove for this specific vid.
2271 	 */
2272 	if (add) {
2273 		return (mac_bcast_add(mcip, addrp, vid,
2274 		    MAC_ADDRTYPE_MULTICAST));
2275 	} else {
2276 		mac_bcast_delete(mcip, addrp, vid);
2277 		return (0);
2278 	}
2279 }
2280 
2281 static void
2282 mac_update_single_active_client(mac_impl_t *mip)
2283 {
2284 	mac_client_impl_t *client = NULL;
2285 
2286 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
2287 
2288 	rw_enter(&mip->mi_rw_lock, RW_WRITER);
2289 	if (mip->mi_nactiveclients == 1) {
2290 		/*
2291 		 * Find the one active MAC client from the list of MAC
2292 		 * clients. The active MAC client has at least one
2293 		 * unicast address.
2294 		 */
2295 		for (client = mip->mi_clients_list; client != NULL;
2296 		    client = client->mci_client_next) {
2297 			if (client->mci_unicast_list != NULL)
2298 				break;
2299 		}
2300 		ASSERT(client != NULL);
2301 	}
2302 
2303 	/*
2304 	 * mi_single_active_client is protected by the MAC impl's read/writer
2305 	 * lock, which allows mac_rx() to check the value of that pointer
2306 	 * as a reader.
2307 	 */
2308 	mip->mi_single_active_client = client;
2309 	rw_exit(&mip->mi_rw_lock);
2310 }
2311 
2312 /*
2313  * Set up the data path. Called from i_mac_unicast_add after having
2314  * done all the validations including making sure this is an active
2315  * client (i.e that is ready to process packets.)
2316  */
2317 static int
2318 mac_client_datapath_setup(mac_client_impl_t *mcip, uint16_t vid,
2319     uint8_t *mac_addr, mac_resource_props_t *mrp, boolean_t isprimary,
2320     mac_unicast_impl_t *muip)
2321 {
2322 	mac_impl_t	*mip = mcip->mci_mip;
2323 	boolean_t	mac_started = B_FALSE;
2324 	boolean_t	bcast_added = B_FALSE;
2325 	boolean_t	nactiveclients_added = B_FALSE;
2326 	flow_entry_t	*flent;
2327 	int		err = 0;
2328 	boolean_t	no_unicast;
2329 
2330 	no_unicast = mcip->mci_state_flags & MCIS_NO_UNICAST_ADDR;
2331 
2332 	if ((err = mac_start((mac_handle_t)mip)) != 0)
2333 		goto bail;
2334 
2335 	mac_started = B_TRUE;
2336 
2337 	/* add the MAC client to the broadcast address group by default */
2338 	if (mip->mi_type->mt_brdcst_addr != NULL) {
2339 		err = mac_bcast_add(mcip, mip->mi_type->mt_brdcst_addr, vid,
2340 		    MAC_ADDRTYPE_BROADCAST);
2341 		if (err != 0)
2342 			goto bail;
2343 		bcast_added = B_TRUE;
2344 	}
2345 
2346 	/*
2347 	 * If this is the first unicast address addition for this
2348 	 * client, reuse the pre-allocated larval flow entry associated with
2349 	 * the MAC client.
2350 	 */
2351 	flent = (mcip->mci_nflents == 0) ? mcip->mci_flent : NULL;
2352 
2353 	/* We are configuring the unicast flow now */
2354 	if (!MCIP_DATAPATH_SETUP(mcip)) {
2355 
2356 		if (mrp != NULL) {
2357 			MAC_CLIENT_SET_PRIORITY_RANGE(mcip,
2358 			    (mrp->mrp_mask & MRP_PRIORITY) ? mrp->mrp_priority :
2359 			    MPL_LINK_DEFAULT);
2360 		}
2361 		if ((err = mac_unicast_flow_create(mcip, mac_addr, vid,
2362 		    isprimary, B_TRUE, &flent, mrp)) != 0)
2363 			goto bail;
2364 
2365 		mip->mi_nactiveclients++;
2366 		nactiveclients_added = B_TRUE;
2367 
2368 		/*
2369 		 * This will allocate the RX ring group if possible for the
2370 		 * flow and program the software classifier as needed.
2371 		 */
2372 		if ((err = mac_datapath_setup(mcip, flent, SRST_LINK)) != 0)
2373 			goto bail;
2374 
2375 		if (no_unicast)
2376 			goto done_setup;
2377 		/*
2378 		 * The unicast MAC address must have been added successfully.
2379 		 */
2380 		ASSERT(mcip->mci_unicast != NULL);
2381 
2382 		/*
2383 		 * Push down the sub-flows that were defined on this link
2384 		 * hitherto. The flows are added to the active flow table
2385 		 * and SRS, softrings etc. are created as needed.
2386 		 */
2387 		mac_link_init_flows((mac_client_handle_t)mcip);
2388 	} else {
2389 		mac_address_t *map = mcip->mci_unicast;
2390 
2391 		ASSERT(!no_unicast);
2392 		/*
2393 		 * A unicast flow already exists for that MAC client
2394 		 * so this flow must be the same MAC address but with
2395 		 * a different VID. It has been checked by
2396 		 * mac_addr_in_use().
2397 		 *
2398 		 * We will use the SRS etc. from the initial
2399 		 * mci_flent. We don't need to create a kstat for
2400 		 * this, as except for the fdesc, everything will be
2401 		 * used from the first flent.
2402 		 *
2403 		 * The only time we should see multiple flents on the
2404 		 * same MAC client is on the sun4v vsw. If we removed
2405 		 * that code we should be able to remove the entire
2406 		 * notion of multiple flents on a MAC client (this
2407 		 * doesn't affect sub/user flows because they have
2408 		 * their own list unrelated to mci_flent_list).
2409 		 */
2410 		if (bcmp(mac_addr, map->ma_addr, map->ma_len) != 0) {
2411 			err = EINVAL;
2412 			goto bail;
2413 		}
2414 
2415 		if ((err = mac_unicast_flow_create(mcip, mac_addr, vid,
2416 		    isprimary, B_FALSE, &flent, NULL)) != 0) {
2417 			goto bail;
2418 		}
2419 		if ((err = mac_flow_add(mip->mi_flow_tab, flent)) != 0) {
2420 			FLOW_FINAL_REFRELE(flent);
2421 			goto bail;
2422 		}
2423 
2424 		/* update the multicast group for this vid */
2425 		mac_client_bcast_refresh(mcip, mac_client_update_mcast,
2426 		    (void *)flent, B_TRUE);
2427 
2428 	}
2429 
2430 	/* populate the shared MAC address */
2431 	muip->mui_map = mcip->mci_unicast;
2432 
2433 	rw_enter(&mcip->mci_rw_lock, RW_WRITER);
2434 	muip->mui_next = mcip->mci_unicast_list;
2435 	mcip->mci_unicast_list = muip;
2436 	rw_exit(&mcip->mci_rw_lock);
2437 
2438 done_setup:
2439 	/*
2440 	 * First add the flent to the flow list of this mcip. Then set
2441 	 * the mip's mi_single_active_client if needed. The Rx path assumes
2442 	 * that mip->mi_single_active_client will always have an associated
2443 	 * flent.
2444 	 */
2445 	mac_client_add_to_flow_list(mcip, flent);
2446 	if (nactiveclients_added)
2447 		mac_update_single_active_client(mip);
2448 	/*
2449 	 * Trigger a renegotiation of the capabilities when the number of
2450 	 * active clients changes from 1 to 2, since some of the capabilities
2451 	 * might have to be disabled. Also send a MAC_NOTE_LINK notification
2452 	 * to all the MAC clients whenever physical link is DOWN.
2453 	 */
2454 	if (mip->mi_nactiveclients == 2) {
2455 		mac_capab_update((mac_handle_t)mip);
2456 		mac_virtual_link_update(mip);
2457 	}
2458 	/*
2459 	 * Now that the setup is complete, clear the INCIPIENT flag.
2460 	 * The flag was set to avoid incoming packets seeing inconsistent
2461 	 * structures while the setup was in progress. Clear the mci_tx_flag
2462 	 * by calling mac_tx_client_block. It is possible that
2463 	 * mac_unicast_remove was called prior to this mac_unicast_add which
2464 	 * could have set the MCI_TX_QUIESCE flag.
2465 	 */
2466 	if (flent->fe_rx_ring_group != NULL)
2467 		mac_rx_group_unmark(flent->fe_rx_ring_group, MR_INCIPIENT);
2468 	FLOW_UNMARK(flent, FE_INCIPIENT);
2469 
2470 	/*
2471 	 * If this is an aggr port client, don't enable the flow's
2472 	 * datapath at this stage. Otherwise, bcast traffic could
2473 	 * arrive while the aggr port is in the process of
2474 	 * initializing. Instead, the flow's datapath is started later
2475 	 * when mac_client_set_flow_cb() is called.
2476 	 */
2477 	if ((mcip->mci_state_flags & MCIS_IS_AGGR_PORT) == 0)
2478 		FLOW_UNMARK(flent, FE_MC_NO_DATAPATH);
2479 
2480 	mac_tx_client_unblock(mcip);
2481 	return (0);
2482 bail:
2483 	if (bcast_added)
2484 		mac_bcast_delete(mcip, mip->mi_type->mt_brdcst_addr, vid);
2485 
2486 	if (nactiveclients_added)
2487 		mip->mi_nactiveclients--;
2488 
2489 	if (mac_started)
2490 		mac_stop((mac_handle_t)mip);
2491 
2492 	return (err);
2493 }
2494 
2495 /*
2496  * Return the passive primary MAC client, if present. The passive client is
2497  * a stand-by client that has the same unicast address as another that is
2498  * currenly active. Once the active client goes away, the passive client
2499  * becomes active.
2500  */
2501 static mac_client_impl_t *
2502 mac_get_passive_primary_client(mac_impl_t *mip)
2503 {
2504 	mac_client_impl_t	*mcip;
2505 
2506 	for (mcip = mip->mi_clients_list; mcip != NULL;
2507 	    mcip = mcip->mci_client_next) {
2508 		if (mac_is_primary_client(mcip) &&
2509 		    (mcip->mci_flags & MAC_CLIENT_FLAGS_PASSIVE_PRIMARY) != 0) {
2510 			return (mcip);
2511 		}
2512 	}
2513 	return (NULL);
2514 }
2515 
2516 /*
2517  * Add a new unicast address to the MAC client.
2518  *
2519  * The MAC address can be specified either by value, or the MAC client
2520  * can specify that it wants to use the primary MAC address of the
2521  * underlying MAC. See the introductory comments at the beginning
2522  * of this file for more more information on primary MAC addresses.
2523  *
2524  * Note also the tuple (MAC address, VID) must be unique
2525  * for the MAC clients defined on top of the same underlying MAC
2526  * instance, unless the MAC_UNICAST_NODUPCHECK is specified.
2527  *
2528  * In no case can a client use the PVID for the MAC, if the MAC has one set.
2529  */
2530 int
2531 i_mac_unicast_add(mac_client_handle_t mch, uint8_t *mac_addr, uint16_t flags,
2532     mac_unicast_handle_t *mah, uint16_t vid, mac_diag_t *diag)
2533 {
2534 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
2535 	mac_impl_t		*mip = mcip->mci_mip;
2536 	int			err;
2537 	uint_t			mac_len = mip->mi_type->mt_addr_length;
2538 	boolean_t		check_dups = !(flags & MAC_UNICAST_NODUPCHECK);
2539 	boolean_t		fastpath_disabled = B_FALSE;
2540 	boolean_t		is_primary = (flags & MAC_UNICAST_PRIMARY);
2541 	boolean_t		is_unicast_hw = (flags & MAC_UNICAST_HW);
2542 	mac_resource_props_t	*mrp;
2543 	boolean_t		passive_client = B_FALSE;
2544 	mac_unicast_impl_t	*muip;
2545 	boolean_t		is_vnic_primary =
2546 	    (flags & MAC_UNICAST_VNIC_PRIMARY);
2547 
2548 	/*
2549 	 * When the VID is non-zero the underlying MAC cannot be a
2550 	 * VNIC. I.e., dladm create-vlan cannot take a VNIC as
2551 	 * argument, only the primary MAC client.
2552 	 */
2553 	ASSERT(!((mip->mi_state_flags & MIS_IS_VNIC) && (vid != VLAN_ID_NONE)));
2554 
2555 	*diag = MAC_DIAG_NONE;
2556 
2557 	/*
2558 	 * Can't unicast add if the client asked only for minimal datapath
2559 	 * setup.
2560 	 */
2561 	if (mcip->mci_state_flags & MCIS_NO_UNICAST_ADDR)
2562 		return (ENOTSUP);
2563 
2564 	/*
2565 	 * Check for an attempted use of the current Port VLAN ID, if enabled.
2566 	 * No client may use it.
2567 	 */
2568 	if (mip->mi_pvid != VLAN_ID_NONE && vid == mip->mi_pvid)
2569 		return (EBUSY);
2570 
2571 	/*
2572 	 * Check whether it's the primary client and flag it.
2573 	 */
2574 	if (!(mcip->mci_state_flags & MCIS_IS_VNIC) && is_primary &&
2575 	    vid == VLAN_ID_NONE)
2576 		mcip->mci_flags |= MAC_CLIENT_FLAGS_PRIMARY;
2577 
2578 	/*
2579 	 * is_vnic_primary is true when we come here as a VLAN VNIC
2580 	 * which uses the primary MAC client's address but with a non-zero
2581 	 * VID. In this case the MAC address is not specified by an upper
2582 	 * MAC client.
2583 	 */
2584 	if ((mcip->mci_state_flags & MCIS_IS_VNIC) && is_primary &&
2585 	    !is_vnic_primary) {
2586 		/*
2587 		 * The address is being set by the upper MAC client
2588 		 * of a VNIC. The MAC address was already set by the
2589 		 * VNIC driver during VNIC creation.
2590 		 *
2591 		 * Note: a VNIC has only one MAC address. We return
2592 		 * the MAC unicast address handle of the lower MAC client
2593 		 * corresponding to the VNIC. We allocate a new entry
2594 		 * which is flagged appropriately, so that mac_unicast_remove()
2595 		 * doesn't attempt to free the original entry that
2596 		 * was allocated by the VNIC driver.
2597 		 */
2598 		ASSERT(mcip->mci_unicast != NULL);
2599 
2600 		/* Check for VLAN flags, if present */
2601 		if ((flags & MAC_UNICAST_TAG_DISABLE) != 0)
2602 			mcip->mci_state_flags |= MCIS_TAG_DISABLE;
2603 
2604 		if ((flags & MAC_UNICAST_STRIP_DISABLE) != 0)
2605 			mcip->mci_state_flags |= MCIS_STRIP_DISABLE;
2606 
2607 		if ((flags & MAC_UNICAST_DISABLE_TX_VID_CHECK) != 0)
2608 			mcip->mci_state_flags |= MCIS_DISABLE_TX_VID_CHECK;
2609 
2610 		/*
2611 		 * Ensure that the primary unicast address of the VNIC
2612 		 * is added only once unless we have the
2613 		 * MAC_CLIENT_FLAGS_MULTI_PRIMARY set (and this is not
2614 		 * a passive MAC client).
2615 		 */
2616 		if ((mcip->mci_flags & MAC_CLIENT_FLAGS_VNIC_PRIMARY) != 0) {
2617 			if ((mcip->mci_flags &
2618 			    MAC_CLIENT_FLAGS_MULTI_PRIMARY) == 0 ||
2619 			    (mcip->mci_flags &
2620 			    MAC_CLIENT_FLAGS_PASSIVE_PRIMARY) != 0) {
2621 				return (EBUSY);
2622 			}
2623 			mcip->mci_flags |= MAC_CLIENT_FLAGS_PASSIVE_PRIMARY;
2624 			passive_client = B_TRUE;
2625 		}
2626 
2627 		mcip->mci_flags |= MAC_CLIENT_FLAGS_VNIC_PRIMARY;
2628 
2629 		/*
2630 		 * Create a handle for vid 0.
2631 		 */
2632 		ASSERT(vid == VLAN_ID_NONE);
2633 		muip = kmem_zalloc(sizeof (mac_unicast_impl_t), KM_SLEEP);
2634 		muip->mui_vid = vid;
2635 		*mah = (mac_unicast_handle_t)muip;
2636 		/*
2637 		 * This will be used by the caller to defer setting the
2638 		 * rx functions.
2639 		 */
2640 		if (passive_client)
2641 			return (EAGAIN);
2642 		return (0);
2643 	}
2644 
2645 	/* primary MAC clients cannot be opened on top of anchor VNICs */
2646 	if ((is_vnic_primary || is_primary) &&
2647 	    i_mac_capab_get((mac_handle_t)mip, MAC_CAPAB_ANCHOR_VNIC, NULL)) {
2648 		return (ENXIO);
2649 	}
2650 
2651 	/*
2652 	 * If this is a VNIC/VLAN, disable softmac fast-path. This is
2653 	 * only relevant to legacy devices which use softmac to
2654 	 * interface with GLDv3.
2655 	 */
2656 	if (mcip->mci_state_flags & MCIS_IS_VNIC) {
2657 		err = mac_fastpath_disable((mac_handle_t)mip);
2658 		if (err != 0)
2659 			return (err);
2660 		fastpath_disabled = B_TRUE;
2661 	}
2662 
2663 	/*
2664 	 * Return EBUSY if:
2665 	 *  - there is an exclusively active mac client exists.
2666 	 *  - this is an exclusive active mac client but
2667 	 *	a. there is already active mac clients exist, or
2668 	 *	b. fastpath streams are already plumbed on this legacy device
2669 	 *  - the mac creator has disallowed active mac clients.
2670 	 */
2671 	if (mip->mi_state_flags & (MIS_EXCLUSIVE|MIS_NO_ACTIVE)) {
2672 		if (fastpath_disabled)
2673 			mac_fastpath_enable((mac_handle_t)mip);
2674 		return (EBUSY);
2675 	}
2676 
2677 	if (mcip->mci_state_flags & MCIS_EXCLUSIVE) {
2678 		ASSERT(!fastpath_disabled);
2679 		if (mip->mi_nactiveclients != 0)
2680 			return (EBUSY);
2681 
2682 		if ((mip->mi_state_flags & MIS_LEGACY) &&
2683 		    !(mip->mi_capab_legacy.ml_active_set(mip->mi_driver))) {
2684 			return (EBUSY);
2685 		}
2686 		mip->mi_state_flags |= MIS_EXCLUSIVE;
2687 	}
2688 
2689 	mrp = kmem_zalloc(sizeof (*mrp), KM_SLEEP);
2690 	if (is_primary && !(mcip->mci_state_flags & (MCIS_IS_VNIC |
2691 	    MCIS_IS_AGGR_PORT))) {
2692 		/*
2693 		 * Apply the property cached in the mac_impl_t to the primary
2694 		 * mac client. If the mac client is a VNIC or an aggregation
2695 		 * port, its property should be set in the mcip when the
2696 		 * VNIC/aggr was created.
2697 		 */
2698 		mac_get_resources((mac_handle_t)mip, mrp);
2699 		(void) mac_client_set_resources(mch, mrp);
2700 	} else if (mcip->mci_state_flags & MCIS_IS_VNIC) {
2701 		/*
2702 		 * This is a VLAN client sharing the address of the
2703 		 * primary MAC client; i.e., one created via dladm
2704 		 * create-vlan. We don't support specifying ring
2705 		 * properties for this type of client as it inherits
2706 		 * these from the primary MAC client.
2707 		 */
2708 		if (is_vnic_primary) {
2709 			mac_resource_props_t	*vmrp;
2710 
2711 			vmrp = MCIP_RESOURCE_PROPS(mcip);
2712 			if (vmrp->mrp_mask & MRP_RX_RINGS ||
2713 			    vmrp->mrp_mask & MRP_TX_RINGS) {
2714 				if (fastpath_disabled)
2715 					mac_fastpath_enable((mac_handle_t)mip);
2716 				kmem_free(mrp, sizeof (*mrp));
2717 				return (ENOTSUP);
2718 			}
2719 			/*
2720 			 * Additionally we also need to inherit any
2721 			 * rings property from the MAC.
2722 			 */
2723 			mac_get_resources((mac_handle_t)mip, mrp);
2724 			if (mrp->mrp_mask & MRP_RX_RINGS) {
2725 				vmrp->mrp_mask |= MRP_RX_RINGS;
2726 				vmrp->mrp_nrxrings = mrp->mrp_nrxrings;
2727 			}
2728 			if (mrp->mrp_mask & MRP_TX_RINGS) {
2729 				vmrp->mrp_mask |= MRP_TX_RINGS;
2730 				vmrp->mrp_ntxrings = mrp->mrp_ntxrings;
2731 			}
2732 		}
2733 		bcopy(MCIP_RESOURCE_PROPS(mcip), mrp, sizeof (*mrp));
2734 	}
2735 
2736 	muip = kmem_zalloc(sizeof (mac_unicast_impl_t), KM_SLEEP);
2737 	muip->mui_vid = vid;
2738 
2739 	if (is_primary || is_vnic_primary) {
2740 		mac_addr = mip->mi_addr;
2741 	} else {
2742 
2743 		/*
2744 		 * Verify the validity of the specified MAC addresses value.
2745 		 */
2746 		if (!mac_unicst_verify((mac_handle_t)mip, mac_addr, mac_len)) {
2747 			*diag = MAC_DIAG_MACADDR_INVALID;
2748 			err = EINVAL;
2749 			goto bail_out;
2750 		}
2751 
2752 		/*
2753 		 * Make sure that the specified MAC address is different
2754 		 * than the unicast MAC address of the underlying NIC.
2755 		 */
2756 		if (check_dups && bcmp(mip->mi_addr, mac_addr, mac_len) == 0) {
2757 			*diag = MAC_DIAG_MACADDR_NIC;
2758 			err = EINVAL;
2759 			goto bail_out;
2760 		}
2761 	}
2762 
2763 	/*
2764 	 * Set the flags here so that if this is a passive client, we
2765 	 * can return and set it when we call mac_client_datapath_setup
2766 	 * when this becomes the active client. If we defer to using these
2767 	 * flags to mac_client_datapath_setup, then for a passive client,
2768 	 * we'd have to store the flags somewhere (probably fe_flags)
2769 	 * and then use it.
2770 	 */
2771 	if (!MCIP_DATAPATH_SETUP(mcip)) {
2772 		if (is_unicast_hw) {
2773 			/*
2774 			 * The client requires a hardware MAC address slot
2775 			 * for that unicast address. Since we support only
2776 			 * one unicast MAC address per client, flag the
2777 			 * MAC client itself.
2778 			 */
2779 			mcip->mci_state_flags |= MCIS_UNICAST_HW;
2780 		}
2781 
2782 		/* Check for VLAN flags, if present */
2783 		if ((flags & MAC_UNICAST_TAG_DISABLE) != 0)
2784 			mcip->mci_state_flags |= MCIS_TAG_DISABLE;
2785 
2786 		if ((flags & MAC_UNICAST_STRIP_DISABLE) != 0)
2787 			mcip->mci_state_flags |= MCIS_STRIP_DISABLE;
2788 
2789 		if ((flags & MAC_UNICAST_DISABLE_TX_VID_CHECK) != 0)
2790 			mcip->mci_state_flags |= MCIS_DISABLE_TX_VID_CHECK;
2791 	} else {
2792 		/*
2793 		 * Assert that the specified flags are consistent with the
2794 		 * flags specified by previous calls to mac_unicast_add().
2795 		 */
2796 		ASSERT(((flags & MAC_UNICAST_TAG_DISABLE) != 0 &&
2797 		    (mcip->mci_state_flags & MCIS_TAG_DISABLE) != 0) ||
2798 		    ((flags & MAC_UNICAST_TAG_DISABLE) == 0 &&
2799 		    (mcip->mci_state_flags & MCIS_TAG_DISABLE) == 0));
2800 
2801 		ASSERT(((flags & MAC_UNICAST_STRIP_DISABLE) != 0 &&
2802 		    (mcip->mci_state_flags & MCIS_STRIP_DISABLE) != 0) ||
2803 		    ((flags & MAC_UNICAST_STRIP_DISABLE) == 0 &&
2804 		    (mcip->mci_state_flags & MCIS_STRIP_DISABLE) == 0));
2805 
2806 		ASSERT(((flags & MAC_UNICAST_DISABLE_TX_VID_CHECK) != 0 &&
2807 		    (mcip->mci_state_flags & MCIS_DISABLE_TX_VID_CHECK) != 0) ||
2808 		    ((flags & MAC_UNICAST_DISABLE_TX_VID_CHECK) == 0 &&
2809 		    (mcip->mci_state_flags & MCIS_DISABLE_TX_VID_CHECK) == 0));
2810 
2811 		/*
2812 		 * Make sure the client is consistent about its requests
2813 		 * for MAC addresses. I.e. all requests from the clients
2814 		 * must have the MAC_UNICAST_HW flag set or clear.
2815 		 */
2816 		if (((mcip->mci_state_flags & MCIS_UNICAST_HW) != 0 &&
2817 		    !is_unicast_hw) ||
2818 		    ((mcip->mci_state_flags & MCIS_UNICAST_HW) == 0 &&
2819 		    is_unicast_hw)) {
2820 			err = EINVAL;
2821 			goto bail_out;
2822 		}
2823 	}
2824 	/*
2825 	 * Make sure the MAC address is not already used by
2826 	 * another MAC client defined on top of the same
2827 	 * underlying NIC. Unless we have MAC_CLIENT_FLAGS_MULTI_PRIMARY
2828 	 * set when we allow a passive client to be present which will
2829 	 * be activated when the currently active client goes away - this
2830 	 * works only with primary addresses.
2831 	 */
2832 	if ((check_dups || is_primary || is_vnic_primary) &&
2833 	    mac_addr_in_use(mip, mac_addr, vid)) {
2834 		/*
2835 		 * Must have set the multiple primary address flag when
2836 		 * we did a mac_client_open AND this should be a primary
2837 		 * MAC client AND there should not already be a passive
2838 		 * primary. If all is true then we let this succeed
2839 		 * even if the address is a dup.
2840 		 */
2841 		if ((mcip->mci_flags & MAC_CLIENT_FLAGS_MULTI_PRIMARY) == 0 ||
2842 		    (mcip->mci_flags & MAC_CLIENT_FLAGS_PRIMARY) == 0 ||
2843 		    mac_get_passive_primary_client(mip) != NULL) {
2844 			*diag = MAC_DIAG_MACADDR_INUSE;
2845 			err = EEXIST;
2846 			goto bail_out;
2847 		}
2848 		ASSERT((mcip->mci_flags &
2849 		    MAC_CLIENT_FLAGS_PASSIVE_PRIMARY) == 0);
2850 		mcip->mci_flags |= MAC_CLIENT_FLAGS_PASSIVE_PRIMARY;
2851 		kmem_free(mrp, sizeof (*mrp));
2852 
2853 		/*
2854 		 * Stash the unicast address handle, we will use it when
2855 		 * we set up the passive client.
2856 		 */
2857 		mcip->mci_p_unicast_list = muip;
2858 		*mah = (mac_unicast_handle_t)muip;
2859 		return (0);
2860 	}
2861 
2862 	err = mac_client_datapath_setup(mcip, vid, mac_addr, mrp,
2863 	    is_primary || is_vnic_primary, muip);
2864 	if (err != 0)
2865 		goto bail_out;
2866 
2867 	kmem_free(mrp, sizeof (*mrp));
2868 	*mah = (mac_unicast_handle_t)muip;
2869 	return (0);
2870 
2871 bail_out:
2872 	if (fastpath_disabled)
2873 		mac_fastpath_enable((mac_handle_t)mip);
2874 	if (mcip->mci_state_flags & MCIS_EXCLUSIVE) {
2875 		mip->mi_state_flags &= ~MIS_EXCLUSIVE;
2876 		if (mip->mi_state_flags & MIS_LEGACY) {
2877 			mip->mi_capab_legacy.ml_active_clear(
2878 			    mip->mi_driver);
2879 		}
2880 	}
2881 	kmem_free(mrp, sizeof (*mrp));
2882 	kmem_free(muip, sizeof (mac_unicast_impl_t));
2883 	return (err);
2884 }
2885 
2886 /*
2887  * Wrapper function to mac_unicast_add when we want to have the same mac
2888  * client open for two instances, one that is currently active and another
2889  * that will become active when the current one is removed. In this case
2890  * mac_unicast_add will return EGAIN and we will save the rx function and
2891  * arg which will be used when we activate the passive client in
2892  * mac_unicast_remove.
2893  */
2894 int
2895 mac_unicast_add_set_rx(mac_client_handle_t mch, uint8_t *mac_addr,
2896     uint16_t flags, mac_unicast_handle_t *mah,  uint16_t vid, mac_diag_t *diag,
2897     mac_rx_t rx_fn, void *arg)
2898 {
2899 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
2900 	uint_t			err;
2901 
2902 	err = mac_unicast_add(mch, mac_addr, flags, mah, vid, diag);
2903 	if (err != 0 && err != EAGAIN)
2904 		return (err);
2905 	if (err == EAGAIN) {
2906 		if (rx_fn != NULL) {
2907 			mcip->mci_rx_p_fn = rx_fn;
2908 			mcip->mci_rx_p_arg = arg;
2909 		}
2910 		return (0);
2911 	}
2912 	if (rx_fn != NULL)
2913 		mac_rx_set(mch, rx_fn, arg);
2914 	return (err);
2915 }
2916 
2917 int
2918 mac_unicast_add(mac_client_handle_t mch, uint8_t *mac_addr, uint16_t flags,
2919     mac_unicast_handle_t *mah, uint16_t vid, mac_diag_t *diag)
2920 {
2921 	mac_impl_t *mip = ((mac_client_impl_t *)mch)->mci_mip;
2922 	uint_t err;
2923 
2924 	i_mac_perim_enter(mip);
2925 	err = i_mac_unicast_add(mch, mac_addr, flags, mah, vid, diag);
2926 	i_mac_perim_exit(mip);
2927 
2928 	return (err);
2929 }
2930 
2931 static void
2932 mac_client_datapath_teardown(mac_client_handle_t mch, mac_unicast_impl_t *muip,
2933     flow_entry_t *flent)
2934 {
2935 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
2936 	mac_impl_t		*mip = mcip->mci_mip;
2937 	boolean_t		no_unicast;
2938 
2939 	/*
2940 	 * If we have not added a unicast address for this MAC client, just
2941 	 * teardown the datapath.
2942 	 */
2943 	no_unicast = mcip->mci_state_flags & MCIS_NO_UNICAST_ADDR;
2944 
2945 	if (!no_unicast) {
2946 		/*
2947 		 * We would have initialized subflows etc. only if we brought
2948 		 * up the primary client and set the unicast unicast address
2949 		 * etc. Deactivate the flows. The flow entry will be removed
2950 		 * from the active flow tables, and the associated SRS,
2951 		 * softrings etc will be deleted. But the flow entry itself
2952 		 * won't be destroyed, instead it will continue to be archived
2953 		 * off the  the global flow hash list, for a possible future
2954 		 * activation when say IP is plumbed again.
2955 		 */
2956 		mac_link_release_flows(mch);
2957 	}
2958 	mip->mi_nactiveclients--;
2959 	mac_update_single_active_client(mip);
2960 
2961 	/* Tear down the data path */
2962 	mac_datapath_teardown(mcip, mcip->mci_flent, SRST_LINK);
2963 
2964 	/*
2965 	 * Prevent any future access to the flow entry through the mci_flent
2966 	 * pointer by setting the mci_flent to NULL. Access to mci_flent in
2967 	 * mac_bcast_send is also under mi_rw_lock.
2968 	 */
2969 	rw_enter(&mip->mi_rw_lock, RW_WRITER);
2970 	flent = mcip->mci_flent;
2971 	mac_client_remove_flow_from_list(mcip, flent);
2972 
2973 	if (mcip->mci_state_flags & MCIS_DESC_LOGGED)
2974 		mcip->mci_state_flags &= ~MCIS_DESC_LOGGED;
2975 
2976 	/*
2977 	 * This is the last unicast address being removed and there shouldn't
2978 	 * be any outbound data threads at this point coming down from mac
2979 	 * clients. We have waited for the data threads to finish before
2980 	 * starting dld_str_detach. Non-data threads must access TX SRS
2981 	 * under mi_rw_lock.
2982 	 */
2983 	rw_exit(&mip->mi_rw_lock);
2984 
2985 	/*
2986 	 * Don't use FLOW_MARK with FE_MC_NO_DATAPATH, as the flow might
2987 	 * contain other flags, such as FE_CONDEMNED, which we need to
2988 	 * cleared. We don't call mac_flow_cleanup() for this unicast
2989 	 * flow as we have a already cleaned up SRSs etc. (via the teadown
2990 	 * path). We just clear the stats and reset the initial callback
2991 	 * function, the rest will be set when we call mac_flow_create,
2992 	 * if at all.
2993 	 */
2994 	mutex_enter(&flent->fe_lock);
2995 	ASSERT(flent->fe_refcnt == 1 && flent->fe_mbg == NULL &&
2996 	    flent->fe_tx_srs == NULL && flent->fe_rx_srs_cnt == 0);
2997 	flent->fe_flags = FE_MC_NO_DATAPATH;
2998 	flow_stat_destroy(flent);
2999 	mac_misc_stat_delete(flent);
3000 
3001 	/* Initialize the receiver function to a safe routine */
3002 	flent->fe_cb_fn = (flow_fn_t)mac_rx_def;
3003 	flent->fe_cb_arg1 = NULL;
3004 	flent->fe_cb_arg2 = NULL;
3005 
3006 	flent->fe_index = -1;
3007 	mutex_exit(&flent->fe_lock);
3008 
3009 	if (mip->mi_type->mt_brdcst_addr != NULL) {
3010 		ASSERT(muip != NULL || no_unicast);
3011 		mac_bcast_delete(mcip, mip->mi_type->mt_brdcst_addr,
3012 		    muip != NULL ? muip->mui_vid : VLAN_ID_NONE);
3013 	}
3014 
3015 	if (mip->mi_nactiveclients == 1) {
3016 		mac_capab_update((mac_handle_t)mip);
3017 		mac_virtual_link_update(mip);
3018 	}
3019 
3020 	if (mcip->mci_state_flags & MCIS_EXCLUSIVE) {
3021 		mip->mi_state_flags &= ~MIS_EXCLUSIVE;
3022 
3023 		if (mip->mi_state_flags & MIS_LEGACY)
3024 			mip->mi_capab_legacy.ml_active_clear(mip->mi_driver);
3025 	}
3026 
3027 	mcip->mci_state_flags &= ~MCIS_UNICAST_HW;
3028 
3029 	if (mcip->mci_state_flags & MCIS_TAG_DISABLE)
3030 		mcip->mci_state_flags &= ~MCIS_TAG_DISABLE;
3031 
3032 	if (mcip->mci_state_flags & MCIS_STRIP_DISABLE)
3033 		mcip->mci_state_flags &= ~MCIS_STRIP_DISABLE;
3034 
3035 	if (mcip->mci_state_flags & MCIS_DISABLE_TX_VID_CHECK)
3036 		mcip->mci_state_flags &= ~MCIS_DISABLE_TX_VID_CHECK;
3037 
3038 	if (muip != NULL)
3039 		kmem_free(muip, sizeof (mac_unicast_impl_t));
3040 	mac_protect_cancel_timer(mcip);
3041 	mac_protect_flush_dynamic(mcip);
3042 
3043 	bzero(&mcip->mci_misc_stat, sizeof (mcip->mci_misc_stat));
3044 	/*
3045 	 * Disable fastpath if this is a VNIC or a VLAN.
3046 	 */
3047 	if (mcip->mci_state_flags & MCIS_IS_VNIC)
3048 		mac_fastpath_enable((mac_handle_t)mip);
3049 	mac_stop((mac_handle_t)mip);
3050 }
3051 
3052 /*
3053  * Remove a MAC address which was previously added by mac_unicast_add().
3054  */
3055 int
3056 mac_unicast_remove(mac_client_handle_t mch, mac_unicast_handle_t mah)
3057 {
3058 	mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
3059 	mac_unicast_impl_t *muip = (mac_unicast_impl_t *)mah;
3060 	mac_unicast_impl_t *pre;
3061 	mac_impl_t *mip = mcip->mci_mip;
3062 	flow_entry_t		*flent;
3063 	uint16_t mui_vid;
3064 
3065 	i_mac_perim_enter(mip);
3066 	if (mcip->mci_flags & MAC_CLIENT_FLAGS_VNIC_PRIMARY) {
3067 		/*
3068 		 * Call made by the upper MAC client of a VNIC.
3069 		 * There's nothing much to do, the unicast address will
3070 		 * be removed by the VNIC driver when the VNIC is deleted,
3071 		 * but let's ensure that all our transmit is done before
3072 		 * the client does a mac_client_stop lest it trigger an
3073 		 * assert in the driver.
3074 		 */
3075 		ASSERT(muip->mui_vid == VLAN_ID_NONE);
3076 
3077 		mac_tx_client_flush(mcip);
3078 
3079 		if ((mcip->mci_flags & MAC_CLIENT_FLAGS_PASSIVE_PRIMARY) != 0) {
3080 			mcip->mci_flags &= ~MAC_CLIENT_FLAGS_PASSIVE_PRIMARY;
3081 			if (mcip->mci_rx_p_fn != NULL) {
3082 				mac_rx_set(mch, mcip->mci_rx_p_fn,
3083 				    mcip->mci_rx_p_arg);
3084 				mcip->mci_rx_p_fn = NULL;
3085 				mcip->mci_rx_p_arg = NULL;
3086 			}
3087 			kmem_free(muip, sizeof (mac_unicast_impl_t));
3088 			i_mac_perim_exit(mip);
3089 			return (0);
3090 		}
3091 		mcip->mci_flags &= ~MAC_CLIENT_FLAGS_VNIC_PRIMARY;
3092 
3093 		if (mcip->mci_state_flags & MCIS_TAG_DISABLE)
3094 			mcip->mci_state_flags &= ~MCIS_TAG_DISABLE;
3095 
3096 		if (mcip->mci_state_flags & MCIS_STRIP_DISABLE)
3097 			mcip->mci_state_flags &= ~MCIS_STRIP_DISABLE;
3098 
3099 		if (mcip->mci_state_flags & MCIS_DISABLE_TX_VID_CHECK)
3100 			mcip->mci_state_flags &= ~MCIS_DISABLE_TX_VID_CHECK;
3101 
3102 		kmem_free(muip, sizeof (mac_unicast_impl_t));
3103 		i_mac_perim_exit(mip);
3104 		return (0);
3105 	}
3106 
3107 	ASSERT(muip != NULL);
3108 
3109 	/*
3110 	 * We are removing a passive client, we haven't setup the datapath
3111 	 * for this yet, so nothing much to do.
3112 	 */
3113 	if ((mcip->mci_flags & MAC_CLIENT_FLAGS_PASSIVE_PRIMARY) != 0) {
3114 
3115 		ASSERT((mcip->mci_flent->fe_flags & FE_MC_NO_DATAPATH) != 0);
3116 		ASSERT(mcip->mci_p_unicast_list == muip);
3117 
3118 		mcip->mci_flags &= ~MAC_CLIENT_FLAGS_PASSIVE_PRIMARY;
3119 
3120 		mcip->mci_p_unicast_list = NULL;
3121 		mcip->mci_rx_p_fn = NULL;
3122 		mcip->mci_rx_p_arg = NULL;
3123 
3124 		mcip->mci_state_flags &= ~MCIS_UNICAST_HW;
3125 
3126 		if (mcip->mci_state_flags & MCIS_TAG_DISABLE)
3127 			mcip->mci_state_flags &= ~MCIS_TAG_DISABLE;
3128 
3129 		if (mcip->mci_state_flags & MCIS_STRIP_DISABLE)
3130 			mcip->mci_state_flags &= ~MCIS_STRIP_DISABLE;
3131 
3132 		if (mcip->mci_state_flags & MCIS_DISABLE_TX_VID_CHECK)
3133 			mcip->mci_state_flags &= ~MCIS_DISABLE_TX_VID_CHECK;
3134 
3135 		kmem_free(muip, sizeof (mac_unicast_impl_t));
3136 		i_mac_perim_exit(mip);
3137 		return (0);
3138 	}
3139 
3140 	/*
3141 	 * Remove the VID from the list of client's VIDs.
3142 	 */
3143 	pre = mcip->mci_unicast_list;
3144 	if (muip == pre) {
3145 		mcip->mci_unicast_list = muip->mui_next;
3146 	} else {
3147 		while ((pre->mui_next != NULL) && (pre->mui_next != muip))
3148 			pre = pre->mui_next;
3149 		ASSERT(pre->mui_next == muip);
3150 		rw_enter(&mcip->mci_rw_lock, RW_WRITER);
3151 		pre->mui_next = muip->mui_next;
3152 		rw_exit(&mcip->mci_rw_lock);
3153 	}
3154 
3155 	if (!mac_client_single_rcvr(mcip)) {
3156 		/*
3157 		 * This MAC client is shared by more than one unicast
3158 		 * addresses, so we will just remove the flent
3159 		 * corresponding to the address being removed. We don't invoke
3160 		 * mac_rx_classify_flow_rem() since the additional flow is
3161 		 * not associated with its own separate set of SRS and rings,
3162 		 * and these constructs are still needed for the remaining
3163 		 * flows.
3164 		 */
3165 		flent = mac_client_get_flow(mcip, muip);
3166 		VERIFY3P(flent, !=, NULL);
3167 
3168 		/*
3169 		 * The first one is disappearing, need to make sure
3170 		 * we replace it with another from the list of
3171 		 * shared clients.
3172 		 */
3173 		if (flent == mcip->mci_flent)
3174 			flent = mac_client_swap_mciflent(mcip);
3175 		mac_client_remove_flow_from_list(mcip, flent);
3176 		mac_flow_remove(mip->mi_flow_tab, flent, B_FALSE);
3177 		mac_flow_wait(flent, FLOW_DRIVER_UPCALL);
3178 
3179 		/*
3180 		 * The multicast groups that were added by the client so
3181 		 * far must be removed from the brodcast domain corresponding
3182 		 * to the VID being removed.
3183 		 */
3184 		mac_client_bcast_refresh(mcip, mac_client_update_mcast,
3185 		    (void *)flent, B_FALSE);
3186 
3187 		if (mip->mi_type->mt_brdcst_addr != NULL) {
3188 			mac_bcast_delete(mcip, mip->mi_type->mt_brdcst_addr,
3189 			    muip->mui_vid);
3190 		}
3191 
3192 		FLOW_FINAL_REFRELE(flent);
3193 		ASSERT(!(mcip->mci_state_flags & MCIS_EXCLUSIVE));
3194 
3195 		/*
3196 		 * Enable fastpath if this is a VNIC or a VLAN.
3197 		 */
3198 		if (mcip->mci_state_flags & MCIS_IS_VNIC)
3199 			mac_fastpath_enable((mac_handle_t)mip);
3200 		mac_stop((mac_handle_t)mip);
3201 		i_mac_perim_exit(mip);
3202 		return (0);
3203 	}
3204 
3205 	mui_vid = muip->mui_vid;
3206 	mac_client_datapath_teardown(mch, muip, flent);
3207 
3208 	if ((mcip->mci_flags & MAC_CLIENT_FLAGS_PRIMARY) &&
3209 	    mui_vid == VLAN_ID_NONE) {
3210 		mcip->mci_flags &= ~MAC_CLIENT_FLAGS_PRIMARY;
3211 	} else {
3212 		i_mac_perim_exit(mip);
3213 		return (0);
3214 	}
3215 
3216 	/*
3217 	 * If we are removing the primary, check if we have a passive primary
3218 	 * client that we need to activate now.
3219 	 */
3220 	mcip = mac_get_passive_primary_client(mip);
3221 	if (mcip != NULL) {
3222 		mac_resource_props_t	*mrp;
3223 		mac_unicast_impl_t	*muip;
3224 
3225 		mcip->mci_flags &= ~MAC_CLIENT_FLAGS_PASSIVE_PRIMARY;
3226 		mrp = kmem_zalloc(sizeof (*mrp), KM_SLEEP);
3227 
3228 		/*
3229 		 * Apply the property cached in the mac_impl_t to the
3230 		 * primary mac client.
3231 		 */
3232 		mac_get_resources((mac_handle_t)mip, mrp);
3233 		(void) mac_client_set_resources(mch, mrp);
3234 		ASSERT(mcip->mci_p_unicast_list != NULL);
3235 		muip = mcip->mci_p_unicast_list;
3236 		mcip->mci_p_unicast_list = NULL;
3237 		if (mac_client_datapath_setup(mcip, VLAN_ID_NONE,
3238 		    mip->mi_addr, mrp, B_TRUE, muip) == 0) {
3239 			if (mcip->mci_rx_p_fn != NULL) {
3240 				mac_rx_set(mch, mcip->mci_rx_p_fn,
3241 				    mcip->mci_rx_p_arg);
3242 				mcip->mci_rx_p_fn = NULL;
3243 				mcip->mci_rx_p_arg = NULL;
3244 			}
3245 		} else {
3246 			kmem_free(muip, sizeof (mac_unicast_impl_t));
3247 		}
3248 		kmem_free(mrp, sizeof (*mrp));
3249 	}
3250 	i_mac_perim_exit(mip);
3251 	return (0);
3252 }
3253 
3254 /*
3255  * Multicast add function invoked by MAC clients.
3256  */
3257 int
3258 mac_multicast_add(mac_client_handle_t mch, const uint8_t *addr)
3259 {
3260 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
3261 	mac_impl_t		*mip = mcip->mci_mip;
3262 	flow_entry_t		*flent = mcip->mci_flent_list;
3263 	flow_entry_t		*prev_fe = NULL;
3264 	uint16_t		vid;
3265 	int			err = 0;
3266 
3267 	/* Verify the address is a valid multicast address */
3268 	if ((err = mip->mi_type->mt_ops.mtops_multicst_verify(addr,
3269 	    mip->mi_pdata)) != 0)
3270 		return (err);
3271 
3272 	i_mac_perim_enter(mip);
3273 	while (flent != NULL) {
3274 		vid = i_mac_flow_vid(flent);
3275 
3276 		err = mac_bcast_add((mac_client_impl_t *)mch, addr, vid,
3277 		    MAC_ADDRTYPE_MULTICAST);
3278 		if (err != 0)
3279 			break;
3280 		prev_fe = flent;
3281 		flent = flent->fe_client_next;
3282 	}
3283 
3284 	/*
3285 	 * If we failed adding, then undo all, rather than partial
3286 	 * success.
3287 	 */
3288 	if (flent != NULL && prev_fe != NULL) {
3289 		flent = mcip->mci_flent_list;
3290 		while (flent != prev_fe->fe_client_next) {
3291 			vid = i_mac_flow_vid(flent);
3292 			mac_bcast_delete((mac_client_impl_t *)mch, addr, vid);
3293 			flent = flent->fe_client_next;
3294 		}
3295 	}
3296 	i_mac_perim_exit(mip);
3297 	return (err);
3298 }
3299 
3300 /*
3301  * Multicast delete function invoked by MAC clients.
3302  */
3303 void
3304 mac_multicast_remove(mac_client_handle_t mch, const uint8_t *addr)
3305 {
3306 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
3307 	mac_impl_t		*mip = mcip->mci_mip;
3308 	flow_entry_t		*flent;
3309 	uint16_t		vid;
3310 
3311 	i_mac_perim_enter(mip);
3312 	for (flent = mcip->mci_flent_list; flent != NULL;
3313 	    flent = flent->fe_client_next) {
3314 		vid = i_mac_flow_vid(flent);
3315 		mac_bcast_delete((mac_client_impl_t *)mch, addr, vid);
3316 	}
3317 	i_mac_perim_exit(mip);
3318 }
3319 
3320 /*
3321  * When a MAC client desires to capture packets on an interface,
3322  * it registers a promiscuous call back with mac_promisc_add().
3323  * There are three types of promiscuous callbacks:
3324  *
3325  * * MAC_CLIENT_PROMISC_ALL
3326  *   Captures all packets sent and received by the MAC client,
3327  *   the physical interface, as well as all other MAC clients
3328  *   defined on top of the same MAC.
3329  *
3330  * * MAC_CLIENT_PROMISC_FILTERED
3331  *   Captures all packets sent and received by the MAC client,
3332  *   plus all multicast traffic sent and received by the phyisical
3333  *   interface and the other MAC clients.
3334  *
3335  * * MAC_CLIENT_PROMISC_MULTI
3336  *   Captures all broadcast and multicast packets sent and
3337  *   received by the MAC clients as well as the physical interface.
3338  *
3339  * In all cases, the underlying MAC is put in promiscuous mode.
3340  */
3341 int
3342 mac_promisc_add(mac_client_handle_t mch, mac_client_promisc_type_t type,
3343     mac_rx_t fn, void *arg, mac_promisc_handle_t *mphp, uint16_t flags)
3344 {
3345 	mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
3346 	mac_impl_t *mip = mcip->mci_mip;
3347 	mac_promisc_impl_t *mpip;
3348 	mac_cb_info_t	*mcbi;
3349 	int rc;
3350 
3351 	i_mac_perim_enter(mip);
3352 
3353 	if ((rc = mac_start((mac_handle_t)mip)) != 0) {
3354 		i_mac_perim_exit(mip);
3355 		return (rc);
3356 	}
3357 
3358 	if ((mcip->mci_state_flags & MCIS_IS_VNIC) &&
3359 	    type == MAC_CLIENT_PROMISC_ALL &&
3360 	    (mcip->mci_protect_flags & MPT_FLAG_PROMISC_FILTERED)) {
3361 		/*
3362 		 * The function is being invoked by the upper MAC client
3363 		 * of a VNIC. The VNIC should only see the traffic
3364 		 * it is entitled to.
3365 		 */
3366 		type = MAC_CLIENT_PROMISC_FILTERED;
3367 	}
3368 
3369 
3370 	/*
3371 	 * Turn on promiscuous mode for the underlying NIC.
3372 	 * This is needed even for filtered callbacks which
3373 	 * expect to receive all multicast traffic on the wire.
3374 	 *
3375 	 * Physical promiscuous mode should not be turned on if
3376 	 * MAC_PROMISC_FLAGS_NO_PHYS is set.
3377 	 */
3378 	if ((flags & MAC_PROMISC_FLAGS_NO_PHYS) == 0) {
3379 		if ((rc = i_mac_promisc_set(mip, B_TRUE)) != 0) {
3380 			mac_stop((mac_handle_t)mip);
3381 			i_mac_perim_exit(mip);
3382 			return (rc);
3383 		}
3384 	}
3385 
3386 	mpip = kmem_cache_alloc(mac_promisc_impl_cache, KM_SLEEP);
3387 
3388 	mpip->mpi_type = type;
3389 	mpip->mpi_fn = fn;
3390 	mpip->mpi_arg = arg;
3391 	mpip->mpi_mcip = mcip;
3392 	mpip->mpi_no_tx_loop = ((flags & MAC_PROMISC_FLAGS_NO_TX_LOOP) != 0);
3393 	mpip->mpi_no_phys = ((flags & MAC_PROMISC_FLAGS_NO_PHYS) != 0);
3394 	mpip->mpi_strip_vlan_tag =
3395 	    ((flags & MAC_PROMISC_FLAGS_VLAN_TAG_STRIP) != 0);
3396 	mpip->mpi_no_copy = ((flags & MAC_PROMISC_FLAGS_NO_COPY) != 0);
3397 
3398 	mcbi = &mip->mi_promisc_cb_info;
3399 	mutex_enter(mcbi->mcbi_lockp);
3400 
3401 	mac_callback_add(&mip->mi_promisc_cb_info, &mcip->mci_promisc_list,
3402 	    &mpip->mpi_mci_link);
3403 	mac_callback_add(&mip->mi_promisc_cb_info, &mip->mi_promisc_list,
3404 	    &mpip->mpi_mi_link);
3405 
3406 	mutex_exit(mcbi->mcbi_lockp);
3407 
3408 	*mphp = (mac_promisc_handle_t)mpip;
3409 
3410 	if (mcip->mci_state_flags & MCIS_IS_VNIC) {
3411 		mac_impl_t *umip = mcip->mci_upper_mip;
3412 
3413 		ASSERT(umip != NULL);
3414 		mac_vnic_secondary_update(umip);
3415 	}
3416 
3417 	i_mac_perim_exit(mip);
3418 
3419 	return (0);
3420 }
3421 
3422 /*
3423  * Remove a multicast address previously aded through mac_promisc_add().
3424  */
3425 void
3426 mac_promisc_remove(mac_promisc_handle_t mph)
3427 {
3428 	mac_promisc_impl_t *mpip = (mac_promisc_impl_t *)mph;
3429 	mac_client_impl_t *mcip = mpip->mpi_mcip;
3430 	mac_impl_t *mip = mcip->mci_mip;
3431 	mac_cb_info_t *mcbi;
3432 	int rv;
3433 
3434 	i_mac_perim_enter(mip);
3435 
3436 	/*
3437 	 * Even if the device can't be reset into normal mode, we still
3438 	 * need to clear the client promisc callbacks. The client may want
3439 	 * to close the mac end point and we can't have stale callbacks.
3440 	 */
3441 	if (!(mpip->mpi_no_phys)) {
3442 		if ((rv = i_mac_promisc_set(mip, B_FALSE)) != 0) {
3443 			cmn_err(CE_WARN, "%s: failed to switch OFF promiscuous"
3444 			    " mode because of error 0x%x", mip->mi_name, rv);
3445 		}
3446 	}
3447 	mcbi = &mip->mi_promisc_cb_info;
3448 	mutex_enter(mcbi->mcbi_lockp);
3449 	if (mac_callback_remove(mcbi, &mip->mi_promisc_list,
3450 	    &mpip->mpi_mi_link)) {
3451 		VERIFY(mac_callback_remove(&mip->mi_promisc_cb_info,
3452 		    &mcip->mci_promisc_list, &mpip->mpi_mci_link));
3453 		kmem_cache_free(mac_promisc_impl_cache, mpip);
3454 	} else {
3455 		mac_callback_remove_wait(&mip->mi_promisc_cb_info);
3456 	}
3457 
3458 	if (mcip->mci_state_flags & MCIS_IS_VNIC) {
3459 		mac_impl_t *umip = mcip->mci_upper_mip;
3460 
3461 		ASSERT(umip != NULL);
3462 		mac_vnic_secondary_update(umip);
3463 	}
3464 
3465 	mutex_exit(mcbi->mcbi_lockp);
3466 	mac_stop((mac_handle_t)mip);
3467 
3468 	i_mac_perim_exit(mip);
3469 }
3470 
3471 /*
3472  * Reference count the number of active Tx threads. MCI_TX_QUIESCE indicates
3473  * that a control operation wants to quiesce the Tx data flow in which case
3474  * we return an error. Holding any of the per cpu locks ensures that the
3475  * mci_tx_flag won't change.
3476  *
3477  * 'CPU' must be accessed just once and used to compute the index into the
3478  * percpu array, and that index must be used for the entire duration of the
3479  * packet send operation. Note that the thread may be preempted and run on
3480  * another cpu any time and so we can't use 'CPU' more than once for the
3481  * operation.
3482  */
3483 #define	MAC_TX_TRY_HOLD(mcip, mytx, error)				\
3484 {									\
3485 	(error) = 0;							\
3486 	(mytx) = &(mcip)->mci_tx_pcpu[CPU->cpu_seqid & mac_tx_percpu_cnt]; \
3487 	mutex_enter(&(mytx)->pcpu_tx_lock);				\
3488 	if (!((mcip)->mci_tx_flag & MCI_TX_QUIESCE)) {			\
3489 		(mytx)->pcpu_tx_refcnt++;				\
3490 	} else {							\
3491 		(error) = -1;						\
3492 	}								\
3493 	mutex_exit(&(mytx)->pcpu_tx_lock);				\
3494 }
3495 
3496 /*
3497  * Release the reference. If needed, signal any control operation waiting
3498  * for Tx quiescence. The wait and signal are always done using the
3499  * mci_tx_pcpu[0]'s lock
3500  */
3501 #define	MAC_TX_RELE(mcip, mytx) {					\
3502 	mutex_enter(&(mytx)->pcpu_tx_lock);				\
3503 	if (--(mytx)->pcpu_tx_refcnt == 0 &&				\
3504 	    (mcip)->mci_tx_flag & MCI_TX_QUIESCE) {			\
3505 		mutex_exit(&(mytx)->pcpu_tx_lock);			\
3506 		mutex_enter(&(mcip)->mci_tx_pcpu[0].pcpu_tx_lock);	\
3507 		cv_signal(&(mcip)->mci_tx_cv);				\
3508 		mutex_exit(&(mcip)->mci_tx_pcpu[0].pcpu_tx_lock);	\
3509 	} else {							\
3510 		mutex_exit(&(mytx)->pcpu_tx_lock);			\
3511 	}								\
3512 }
3513 
3514 /*
3515  * Send function invoked by MAC clients.
3516  */
3517 mac_tx_cookie_t
3518 mac_tx(mac_client_handle_t mch, mblk_t *mp_chain, uintptr_t hint,
3519     uint16_t flag, mblk_t **ret_mp)
3520 {
3521 	mac_tx_cookie_t		cookie = 0;
3522 	int			error;
3523 	mac_tx_percpu_t		*mytx;
3524 	mac_soft_ring_set_t	*srs;
3525 	flow_entry_t		*flent;
3526 	boolean_t		is_subflow = B_FALSE;
3527 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
3528 	mac_impl_t		*mip = mcip->mci_mip;
3529 	mac_srs_tx_t		*srs_tx;
3530 
3531 	/*
3532 	 * Check whether the active Tx threads count is bumped already.
3533 	 */
3534 	if (!(flag & MAC_TX_NO_HOLD)) {
3535 		MAC_TX_TRY_HOLD(mcip, mytx, error);
3536 		if (error != 0) {
3537 			freemsgchain(mp_chain);
3538 			return (0);
3539 		}
3540 	}
3541 
3542 	/*
3543 	 * If mac protection is enabled, only the permissible packets will be
3544 	 * returned by mac_protect_check().
3545 	 */
3546 	if ((mcip->mci_flent->
3547 	    fe_resource_props.mrp_mask & MRP_PROTECT) != 0 &&
3548 	    (mp_chain = mac_protect_check(mch, mp_chain)) == NULL)
3549 		goto done;
3550 
3551 	if (mcip->mci_subflow_tab != NULL &&
3552 	    mcip->mci_subflow_tab->ft_flow_count > 0 &&
3553 	    mac_flow_lookup(mcip->mci_subflow_tab, mp_chain,
3554 	    FLOW_OUTBOUND, &flent) == 0) {
3555 		/*
3556 		 * The main assumption here is that if in the event
3557 		 * we get a chain, all the packets will be classified
3558 		 * to the same Flow/SRS. If this changes for any
3559 		 * reason, the following logic should change as well.
3560 		 * I suppose the fanout_hint also assumes this .
3561 		 */
3562 		ASSERT(flent != NULL);
3563 		is_subflow = B_TRUE;
3564 	} else {
3565 		flent = mcip->mci_flent;
3566 	}
3567 
3568 	srs = flent->fe_tx_srs;
3569 	/*
3570 	 * This is to avoid panics with PF_PACKET that can call mac_tx()
3571 	 * against an interface that is not capable of sending. A rewrite
3572 	 * of the mac datapath is required to remove this limitation.
3573 	 */
3574 	if (srs == NULL) {
3575 		freemsgchain(mp_chain);
3576 		goto done;
3577 	}
3578 
3579 	srs_tx = &srs->srs_tx;
3580 	if (srs_tx->st_mode == SRS_TX_DEFAULT &&
3581 	    (srs->srs_state & SRS_ENQUEUED) == 0 &&
3582 	    mip->mi_nactiveclients == 1 &&
3583 	    mp_chain->b_next == NULL &&
3584 	    (DB_CKSUMFLAGS(mp_chain) & HW_LSO) == 0) {
3585 		uint64_t	obytes;
3586 
3587 		/*
3588 		 * Since dls always opens the underlying MAC, nclients equals
3589 		 * to 1 means that the only active client is dls itself acting
3590 		 * as a primary client of the MAC instance. Since dls will not
3591 		 * send tagged packets in that case, and dls is trusted to send
3592 		 * packets for its allowed VLAN(s), the VLAN tag insertion and
3593 		 * check is required only if nclients is greater than 1.
3594 		 */
3595 		if (mip->mi_nclients > 1) {
3596 			if (MAC_VID_CHECK_NEEDED(mcip)) {
3597 				int	err = 0;
3598 
3599 				MAC_VID_CHECK(mcip, mp_chain, err);
3600 				if (err != 0) {
3601 					freemsg(mp_chain);
3602 					mcip->mci_misc_stat.mms_txerrors++;
3603 					goto done;
3604 				}
3605 			}
3606 			if (MAC_TAG_NEEDED(mcip)) {
3607 				mp_chain = mac_add_vlan_tag(mp_chain, 0,
3608 				    mac_client_vid(mch));
3609 				if (mp_chain == NULL) {
3610 					mcip->mci_misc_stat.mms_txerrors++;
3611 					goto done;
3612 				}
3613 			}
3614 		}
3615 
3616 		obytes = (mp_chain->b_cont == NULL ? MBLKL(mp_chain) :
3617 		    msgdsize(mp_chain));
3618 
3619 		mp_chain = mac_provider_tx(mip, srs_tx->st_arg2, mp_chain,
3620 		    mcip);
3621 
3622 		if (mp_chain == NULL) {
3623 			cookie = 0;
3624 			SRS_TX_STAT_UPDATE(srs, opackets, 1);
3625 			SRS_TX_STAT_UPDATE(srs, obytes, obytes);
3626 		} else {
3627 			mutex_enter(&srs->srs_lock);
3628 			cookie = mac_tx_srs_no_desc(srs, mp_chain,
3629 			    flag, ret_mp);
3630 			mutex_exit(&srs->srs_lock);
3631 		}
3632 	} else {
3633 		mblk_t *mp = mp_chain;
3634 		mblk_t *new_head = NULL;
3635 		mblk_t *new_tail = NULL;
3636 
3637 		/*
3638 		 * There are occasions where the packets arriving here
3639 		 * may request hardware offloads that are not
3640 		 * available from the underlying MAC provider. This
3641 		 * currently only happens when a packet is sent across
3642 		 * the MAC-loopback path of one MAC and then forwarded
3643 		 * (via IP) to another MAC that lacks one or more of
3644 		 * the hardware offloads provided by the first one.
3645 		 * However, in the future, we may choose to pretend
3646 		 * all MAC providers support all offloads, performing
3647 		 * emulation on Tx as needed.
3648 		 *
3649 		 * We iterate each mblk in-turn, emulating hardware
3650 		 * offloads as required. From this process, we create
3651 		 * a new chain. The new chain may be the same as the
3652 		 * original chain (no hardware emulation needed), a
3653 		 * collection of new mblks (hardware emulation
3654 		 * needed), or a mix. At this point, the chain is safe
3655 		 * for consumption by the underlying MAC provider and
3656 		 * is passed down to the SRS.
3657 		 */
3658 		while (mp != NULL) {
3659 			mblk_t *next = mp->b_next;
3660 			mblk_t *tail = NULL;
3661 			const uint16_t needed =
3662 			    (DB_CKSUMFLAGS(mp) ^ mip->mi_tx_cksum_flags) &
3663 			    DB_CKSUMFLAGS(mp);
3664 
3665 			mp->b_next = NULL;
3666 
3667 			if ((needed & (HCK_TX_FLAGS | HW_LSO_FLAGS)) != 0) {
3668 				mac_emul_t emul = 0;
3669 
3670 				if (needed & HCK_IPV4_HDRCKSUM)
3671 					emul |= MAC_IPCKSUM_EMUL;
3672 				if (needed & (HCK_PARTIALCKSUM | HCK_FULLCKSUM))
3673 					emul |= MAC_HWCKSUM_EMUL;
3674 				if (needed & HW_LSO)
3675 					emul = MAC_LSO_EMUL;
3676 
3677 				mac_hw_emul(&mp, &tail, NULL, emul);
3678 
3679 				if (mp == NULL) {
3680 					mp = next;
3681 					continue;
3682 				}
3683 			}
3684 
3685 			if (new_head == NULL) {
3686 				new_head = mp;
3687 			} else {
3688 				new_tail->b_next = mp;
3689 			}
3690 
3691 			new_tail = (tail == NULL) ? mp : tail;
3692 			mp = next;
3693 		}
3694 
3695 		if (new_head == NULL) {
3696 			cookie = 0;
3697 			goto done;
3698 		}
3699 
3700 		cookie = srs_tx->st_func(srs, new_head, hint, flag, ret_mp);
3701 	}
3702 
3703 done:
3704 	if (is_subflow)
3705 		FLOW_REFRELE(flent);
3706 
3707 	if (!(flag & MAC_TX_NO_HOLD))
3708 		MAC_TX_RELE(mcip, mytx);
3709 
3710 	return (cookie);
3711 }
3712 
3713 /*
3714  * mac_tx_is_blocked
3715  *
3716  * Given a cookie, it returns if the ring identified by the cookie is
3717  * flow-controlled or not. If NULL is passed in place of a cookie,
3718  * then it finds out if any of the underlying rings belonging to the
3719  * SRS is flow controlled or not and returns that status.
3720  */
3721 /* ARGSUSED */
3722 boolean_t
3723 mac_tx_is_flow_blocked(mac_client_handle_t mch, mac_tx_cookie_t cookie)
3724 {
3725 	mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
3726 	mac_soft_ring_set_t *mac_srs;
3727 	mac_soft_ring_t *sringp;
3728 	boolean_t blocked = B_FALSE;
3729 	mac_tx_percpu_t *mytx;
3730 	int err;
3731 	int i;
3732 
3733 	/*
3734 	 * Bump the reference count so that mac_srs won't be deleted.
3735 	 * If the client is currently quiesced and we failed to bump
3736 	 * the reference, return B_TRUE so that flow control stays
3737 	 * as enabled.
3738 	 *
3739 	 * Flow control will then be disabled once the client is no
3740 	 * longer quiesced.
3741 	 */
3742 	MAC_TX_TRY_HOLD(mcip, mytx, err);
3743 	if (err != 0)
3744 		return (B_TRUE);
3745 
3746 	if ((mac_srs = MCIP_TX_SRS(mcip)) == NULL) {
3747 		MAC_TX_RELE(mcip, mytx);
3748 		return (B_FALSE);
3749 	}
3750 
3751 	mutex_enter(&mac_srs->srs_lock);
3752 	/*
3753 	 * Only in the case of TX_FANOUT and TX_AGGR, the underlying
3754 	 * softring (s_ring_state) will have the HIWAT set. This is
3755 	 * the multiple Tx ring flow control case. For all other
3756 	 * case, SRS (srs_state) will store the condition.
3757 	 */
3758 	if (mac_srs->srs_tx.st_mode == SRS_TX_FANOUT ||
3759 	    mac_srs->srs_tx.st_mode == SRS_TX_AGGR) {
3760 		if (cookie != 0) {
3761 			sringp = (mac_soft_ring_t *)cookie;
3762 			mutex_enter(&sringp->s_ring_lock);
3763 			if (sringp->s_ring_state & S_RING_TX_HIWAT)
3764 				blocked = B_TRUE;
3765 			mutex_exit(&sringp->s_ring_lock);
3766 		} else {
3767 			for (i = 0; i < mac_srs->srs_tx_ring_count; i++) {
3768 				sringp = mac_srs->srs_tx_soft_rings[i];
3769 				mutex_enter(&sringp->s_ring_lock);
3770 				if (sringp->s_ring_state & S_RING_TX_HIWAT) {
3771 					blocked = B_TRUE;
3772 					mutex_exit(&sringp->s_ring_lock);
3773 					break;
3774 				}
3775 				mutex_exit(&sringp->s_ring_lock);
3776 			}
3777 		}
3778 	} else {
3779 		blocked = (mac_srs->srs_state & SRS_TX_HIWAT);
3780 	}
3781 	mutex_exit(&mac_srs->srs_lock);
3782 	MAC_TX_RELE(mcip, mytx);
3783 	return (blocked);
3784 }
3785 
3786 /*
3787  * Check if the MAC client is the primary MAC client.
3788  */
3789 boolean_t
3790 mac_is_primary_client(mac_client_impl_t *mcip)
3791 {
3792 	return (mcip->mci_flags & MAC_CLIENT_FLAGS_PRIMARY);
3793 }
3794 
3795 void
3796 mac_ioctl(mac_handle_t mh, queue_t *wq, mblk_t *bp)
3797 {
3798 	mac_impl_t	*mip = (mac_impl_t *)mh;
3799 	int cmd = ((struct iocblk *)bp->b_rptr)->ioc_cmd;
3800 
3801 	if ((cmd == ND_GET && (mip->mi_callbacks->mc_callbacks & MC_GETPROP)) ||
3802 	    (cmd == ND_SET && (mip->mi_callbacks->mc_callbacks & MC_SETPROP))) {
3803 		/*
3804 		 * If ndd props were registered, call them.
3805 		 * Note that ndd ioctls are Obsolete
3806 		 */
3807 		mac_ndd_ioctl(mip, wq, bp);
3808 		return;
3809 	}
3810 
3811 	/*
3812 	 * Call the driver to handle the ioctl.  The driver may not support
3813 	 * any ioctls, in which case we reply with a NAK on its behalf.
3814 	 */
3815 	if (mip->mi_callbacks->mc_callbacks & MC_IOCTL)
3816 		mip->mi_ioctl(mip->mi_driver, wq, bp);
3817 	else
3818 		miocnak(wq, bp, 0, EINVAL);
3819 }
3820 
3821 /*
3822  * Return the link state of the specified MAC instance.
3823  */
3824 link_state_t
3825 mac_link_get(mac_handle_t mh)
3826 {
3827 	return (((mac_impl_t *)mh)->mi_linkstate);
3828 }
3829 
3830 /*
3831  * Add a mac client specified notification callback. Please see the comments
3832  * above mac_callback_add() for general information about mac callback
3833  * addition/deletion in the presence of mac callback list walkers
3834  */
3835 mac_notify_handle_t
3836 mac_notify_add(mac_handle_t mh, mac_notify_t notify_fn, void *arg)
3837 {
3838 	mac_impl_t		*mip = (mac_impl_t *)mh;
3839 	mac_notify_cb_t		*mncb;
3840 	mac_cb_info_t		*mcbi;
3841 
3842 	/*
3843 	 * Allocate a notify callback structure, fill in the details and
3844 	 * use the mac callback list manipulation functions to chain into
3845 	 * the list of callbacks.
3846 	 */
3847 	mncb = kmem_zalloc(sizeof (mac_notify_cb_t), KM_SLEEP);
3848 	mncb->mncb_fn = notify_fn;
3849 	mncb->mncb_arg = arg;
3850 	mncb->mncb_mip = mip;
3851 	mncb->mncb_link.mcb_objp = mncb;
3852 	mncb->mncb_link.mcb_objsize = sizeof (mac_notify_cb_t);
3853 	mncb->mncb_link.mcb_flags = MCB_NOTIFY_CB_T;
3854 
3855 	mcbi = &mip->mi_notify_cb_info;
3856 
3857 	i_mac_perim_enter(mip);
3858 	mutex_enter(mcbi->mcbi_lockp);
3859 
3860 	mac_callback_add(&mip->mi_notify_cb_info, &mip->mi_notify_cb_list,
3861 	    &mncb->mncb_link);
3862 
3863 	mutex_exit(mcbi->mcbi_lockp);
3864 	i_mac_perim_exit(mip);
3865 	return ((mac_notify_handle_t)mncb);
3866 }
3867 
3868 void
3869 mac_notify_remove_wait(mac_handle_t mh)
3870 {
3871 	mac_impl_t	*mip = (mac_impl_t *)mh;
3872 	mac_cb_info_t	*mcbi = &mip->mi_notify_cb_info;
3873 
3874 	mutex_enter(mcbi->mcbi_lockp);
3875 	mac_callback_remove_wait(&mip->mi_notify_cb_info);
3876 	mutex_exit(mcbi->mcbi_lockp);
3877 }
3878 
3879 /*
3880  * Remove a mac client specified notification callback
3881  */
3882 int
3883 mac_notify_remove(mac_notify_handle_t mnh, boolean_t wait)
3884 {
3885 	mac_notify_cb_t	*mncb = (mac_notify_cb_t *)mnh;
3886 	mac_impl_t	*mip = mncb->mncb_mip;
3887 	mac_cb_info_t	*mcbi;
3888 	int		err = 0;
3889 
3890 	mcbi = &mip->mi_notify_cb_info;
3891 
3892 	i_mac_perim_enter(mip);
3893 	mutex_enter(mcbi->mcbi_lockp);
3894 
3895 	ASSERT(mncb->mncb_link.mcb_objp == mncb);
3896 	/*
3897 	 * If there aren't any list walkers, the remove would succeed
3898 	 * inline, else we wait for the deferred remove to complete
3899 	 */
3900 	if (mac_callback_remove(&mip->mi_notify_cb_info,
3901 	    &mip->mi_notify_cb_list, &mncb->mncb_link)) {
3902 		kmem_free(mncb, sizeof (mac_notify_cb_t));
3903 	} else {
3904 		err = EBUSY;
3905 	}
3906 
3907 	mutex_exit(mcbi->mcbi_lockp);
3908 	i_mac_perim_exit(mip);
3909 
3910 	/*
3911 	 * If we failed to remove the notification callback and "wait" is set
3912 	 * to be B_TRUE, wait for the callback to finish after we exit the
3913 	 * mac perimeter.
3914 	 */
3915 	if (err != 0 && wait) {
3916 		mac_notify_remove_wait((mac_handle_t)mip);
3917 		return (0);
3918 	}
3919 
3920 	return (err);
3921 }
3922 
3923 /*
3924  * Associate resource management callbacks with the specified MAC
3925  * clients.
3926  */
3927 
3928 void
3929 mac_resource_set_common(mac_client_handle_t mch, mac_resource_add_t add,
3930     mac_resource_remove_t remove, mac_resource_quiesce_t quiesce,
3931     mac_resource_restart_t restart, mac_resource_bind_t bind,
3932     void *arg)
3933 {
3934 	mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
3935 
3936 	mcip->mci_resource_add = add;
3937 	mcip->mci_resource_remove = remove;
3938 	mcip->mci_resource_quiesce = quiesce;
3939 	mcip->mci_resource_restart = restart;
3940 	mcip->mci_resource_bind = bind;
3941 	mcip->mci_resource_arg = arg;
3942 }
3943 
3944 void
3945 mac_resource_set(mac_client_handle_t mch, mac_resource_add_t add, void *arg)
3946 {
3947 	/* update the 'resource_add' callback */
3948 	mac_resource_set_common(mch, add, NULL, NULL, NULL, NULL, arg);
3949 }
3950 
3951 /*
3952  * Sets up the client resources and enable the polling interface over all the
3953  * SRS's and the soft rings of the client
3954  */
3955 void
3956 mac_client_poll_enable(mac_client_handle_t mch)
3957 {
3958 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
3959 	mac_soft_ring_set_t	*mac_srs;
3960 	flow_entry_t		*flent;
3961 	int			i;
3962 
3963 	flent = mcip->mci_flent;
3964 	ASSERT(flent != NULL);
3965 
3966 	mcip->mci_state_flags |= MCIS_CLIENT_POLL_CAPABLE;
3967 	for (i = 0; i < flent->fe_rx_srs_cnt; i++) {
3968 		mac_srs = (mac_soft_ring_set_t *)flent->fe_rx_srs[i];
3969 		ASSERT(mac_srs->srs_mcip == mcip);
3970 		mac_srs_client_poll_enable(mcip, mac_srs);
3971 	}
3972 }
3973 
3974 /*
3975  * Tears down the client resources and disable the polling interface over all
3976  * the SRS's and the soft rings of the client
3977  */
3978 void
3979 mac_client_poll_disable(mac_client_handle_t mch)
3980 {
3981 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
3982 	mac_soft_ring_set_t	*mac_srs;
3983 	flow_entry_t		*flent;
3984 	int			i;
3985 
3986 	flent = mcip->mci_flent;
3987 	ASSERT(flent != NULL);
3988 
3989 	mcip->mci_state_flags &= ~MCIS_CLIENT_POLL_CAPABLE;
3990 	for (i = 0; i < flent->fe_rx_srs_cnt; i++) {
3991 		mac_srs = (mac_soft_ring_set_t *)flent->fe_rx_srs[i];
3992 		ASSERT(mac_srs->srs_mcip == mcip);
3993 		mac_srs_client_poll_disable(mcip, mac_srs);
3994 	}
3995 }
3996 
3997 /*
3998  * Associate the CPUs specified by the given property with a MAC client.
3999  */
4000 int
4001 mac_cpu_set(mac_client_handle_t mch, mac_resource_props_t *mrp)
4002 {
4003 	mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
4004 	mac_impl_t *mip = mcip->mci_mip;
4005 	int err = 0;
4006 
4007 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
4008 
4009 	if ((err = mac_validate_props(mcip->mci_state_flags & MCIS_IS_VNIC ?
4010 	    mcip->mci_upper_mip : mip, mrp)) != 0) {
4011 		return (err);
4012 	}
4013 	if (MCIP_DATAPATH_SETUP(mcip))
4014 		mac_flow_modify(mip->mi_flow_tab, mcip->mci_flent, mrp);
4015 
4016 	mac_update_resources(mrp, MCIP_RESOURCE_PROPS(mcip), B_FALSE);
4017 	return (0);
4018 }
4019 
4020 /*
4021  * Apply the specified properties to the specified MAC client.
4022  */
4023 int
4024 mac_client_set_resources(mac_client_handle_t mch, mac_resource_props_t *mrp)
4025 {
4026 	mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
4027 	mac_impl_t *mip = mcip->mci_mip;
4028 	int err = 0;
4029 
4030 	i_mac_perim_enter(mip);
4031 
4032 	if ((mrp->mrp_mask & MRP_MAXBW) || (mrp->mrp_mask & MRP_PRIORITY)) {
4033 		err = mac_resource_ctl_set(mch, mrp);
4034 		if (err != 0)
4035 			goto done;
4036 	}
4037 
4038 	if (mrp->mrp_mask & (MRP_CPUS|MRP_POOL)) {
4039 		err = mac_cpu_set(mch, mrp);
4040 		if (err != 0)
4041 			goto done;
4042 	}
4043 
4044 	if (mrp->mrp_mask & MRP_PROTECT) {
4045 		err = mac_protect_set(mch, mrp);
4046 		if (err != 0)
4047 			goto done;
4048 	}
4049 
4050 	if ((mrp->mrp_mask & MRP_RX_RINGS) || (mrp->mrp_mask & MRP_TX_RINGS))
4051 		err = mac_resource_ctl_set(mch, mrp);
4052 
4053 done:
4054 	i_mac_perim_exit(mip);
4055 	return (err);
4056 }
4057 
4058 /*
4059  * Return the properties currently associated with the specified MAC client.
4060  */
4061 void
4062 mac_client_get_resources(mac_client_handle_t mch, mac_resource_props_t *mrp)
4063 {
4064 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
4065 	mac_resource_props_t	*mcip_mrp = MCIP_RESOURCE_PROPS(mcip);
4066 
4067 	bcopy(mcip_mrp, mrp, sizeof (mac_resource_props_t));
4068 }
4069 
4070 /*
4071  * Return the effective properties currently associated with the specified
4072  * MAC client.
4073  */
4074 void
4075 mac_client_get_effective_resources(mac_client_handle_t mch,
4076     mac_resource_props_t *mrp)
4077 {
4078 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
4079 	mac_resource_props_t	*mcip_mrp = MCIP_EFFECTIVE_PROPS(mcip);
4080 
4081 	bcopy(mcip_mrp, mrp, sizeof (mac_resource_props_t));
4082 }
4083 
4084 /*
4085  * Pass a copy of the specified packet to the promiscuous callbacks
4086  * of the specified MAC.
4087  *
4088  * If sender is NULL, the function is being invoked for a packet chain
4089  * received from the wire. If sender is non-NULL, it points to
4090  * the MAC client from which the packet is being sent.
4091  *
4092  * The packets are distributed to the promiscuous callbacks as follows:
4093  *
4094  * - all packets are sent to the MAC_CLIENT_PROMISC_ALL callbacks
4095  * - all broadcast and multicast packets are sent to the
4096  *   MAC_CLIENT_PROMISC_FILTER and MAC_CLIENT_PROMISC_MULTI.
4097  *
4098  * The unicast packets of MAC_CLIENT_PROMISC_FILTER callbacks are dispatched
4099  * after classification by mac_rx_deliver().
4100  */
4101 static void
4102 mac_promisc_dispatch_one(mac_promisc_impl_t *mpip, mblk_t *mp,
4103     boolean_t loopback, boolean_t local)
4104 {
4105 	mblk_t *mp_next;
4106 
4107 	if (!mpip->mpi_no_copy || mpip->mpi_strip_vlan_tag) {
4108 		mblk_t *mp_copy;
4109 
4110 		mp_copy = copymsg(mp);
4111 		if (mp_copy == NULL)
4112 			return;
4113 
4114 		if (mpip->mpi_strip_vlan_tag) {
4115 			mp_copy = mac_strip_vlan_tag_chain(mp_copy);
4116 			if (mp_copy == NULL)
4117 				return;
4118 		}
4119 
4120 		/*
4121 		 * There is code upstack that can't deal with message
4122 		 * chains.
4123 		 */
4124 		for (mblk_t *tmp = mp_copy; tmp != NULL; tmp = mp_next) {
4125 			mp_next = tmp->b_next;
4126 			tmp->b_next = NULL;
4127 			mpip->mpi_fn(mpip->mpi_arg, NULL, tmp, loopback);
4128 		}
4129 
4130 		return;
4131 	}
4132 
4133 	mp_next = mp->b_next;
4134 	mp->b_next = NULL;
4135 	mpip->mpi_fn(mpip->mpi_arg, NULL, mp, loopback);
4136 	mp->b_next = mp_next;
4137 }
4138 
4139 /*
4140  * Return the VID of a packet. Zero if the packet is not tagged.
4141  */
4142 static uint16_t
4143 mac_ether_vid(mblk_t *mp)
4144 {
4145 	struct ether_header *eth = (struct ether_header *)mp->b_rptr;
4146 
4147 	if (ntohs(eth->ether_type) == ETHERTYPE_VLAN) {
4148 		struct ether_vlan_header *t_evhp =
4149 		    (struct ether_vlan_header *)mp->b_rptr;
4150 		return (VLAN_ID(ntohs(t_evhp->ether_tci)));
4151 	}
4152 
4153 	return (0);
4154 }
4155 
4156 /*
4157  * Return whether the specified packet contains a multicast or broadcast
4158  * destination MAC address.
4159  */
4160 static boolean_t
4161 mac_is_mcast(mac_impl_t *mip, mblk_t *mp)
4162 {
4163 	mac_header_info_t hdr_info;
4164 
4165 	if (mac_header_info((mac_handle_t)mip, mp, &hdr_info) != 0)
4166 		return (B_FALSE);
4167 	return ((hdr_info.mhi_dsttype == MAC_ADDRTYPE_BROADCAST) ||
4168 	    (hdr_info.mhi_dsttype == MAC_ADDRTYPE_MULTICAST));
4169 }
4170 
4171 /*
4172  * Send a copy of an mblk chain to the MAC clients of the specified MAC.
4173  * "sender" points to the sender MAC client for outbound packets, and
4174  * is set to NULL for inbound packets.
4175  */
4176 void
4177 mac_promisc_dispatch(mac_impl_t *mip, mblk_t *mp_chain,
4178     mac_client_impl_t *sender, boolean_t local)
4179 {
4180 	mac_promisc_impl_t *mpip;
4181 	mac_cb_t *mcb;
4182 	mblk_t *mp;
4183 	boolean_t is_mcast, is_sender;
4184 
4185 	MAC_PROMISC_WALKER_INC(mip);
4186 	for (mp = mp_chain; mp != NULL; mp = mp->b_next) {
4187 		is_mcast = mac_is_mcast(mip, mp);
4188 		/* send packet to interested callbacks */
4189 		for (mcb = mip->mi_promisc_list; mcb != NULL;
4190 		    mcb = mcb->mcb_nextp) {
4191 			mpip = (mac_promisc_impl_t *)mcb->mcb_objp;
4192 			is_sender = (mpip->mpi_mcip == sender);
4193 
4194 			if (is_sender && mpip->mpi_no_tx_loop)
4195 				/*
4196 				 * The sender doesn't want to receive
4197 				 * copies of the packets it sends.
4198 				 */
4199 				continue;
4200 
4201 			/* this client doesn't need any packets (bridge) */
4202 			if (mpip->mpi_fn == NULL)
4203 				continue;
4204 
4205 			/*
4206 			 * For an ethernet MAC, don't displatch a multicast
4207 			 * packet to a non-PROMISC_ALL callbacks unless the VID
4208 			 * of the packet matches the VID of the client.
4209 			 */
4210 			if (is_mcast &&
4211 			    mpip->mpi_type != MAC_CLIENT_PROMISC_ALL &&
4212 			    !mac_client_check_flow_vid(mpip->mpi_mcip,
4213 			    mac_ether_vid(mp)))
4214 				continue;
4215 
4216 			if (is_sender ||
4217 			    mpip->mpi_type == MAC_CLIENT_PROMISC_ALL ||
4218 			    is_mcast) {
4219 				mac_promisc_dispatch_one(mpip, mp, is_sender,
4220 				    local);
4221 			}
4222 		}
4223 	}
4224 	MAC_PROMISC_WALKER_DCR(mip);
4225 }
4226 
4227 void
4228 mac_promisc_client_dispatch(mac_client_impl_t *mcip, mblk_t *mp_chain)
4229 {
4230 	mac_impl_t		*mip = mcip->mci_mip;
4231 	mac_promisc_impl_t	*mpip;
4232 	boolean_t		is_mcast;
4233 	mblk_t			*mp;
4234 	mac_cb_t		*mcb;
4235 
4236 	/*
4237 	 * The unicast packets for the MAC client still
4238 	 * need to be delivered to the MAC_CLIENT_PROMISC_FILTERED
4239 	 * promiscuous callbacks. The broadcast and multicast
4240 	 * packets were delivered from mac_rx().
4241 	 */
4242 	MAC_PROMISC_WALKER_INC(mip);
4243 	for (mp = mp_chain; mp != NULL; mp = mp->b_next) {
4244 		is_mcast = mac_is_mcast(mip, mp);
4245 		for (mcb = mcip->mci_promisc_list; mcb != NULL;
4246 		    mcb = mcb->mcb_nextp) {
4247 			mpip = (mac_promisc_impl_t *)mcb->mcb_objp;
4248 			if (mpip->mpi_type == MAC_CLIENT_PROMISC_FILTERED &&
4249 			    !is_mcast) {
4250 				mac_promisc_dispatch_one(mpip, mp, B_FALSE,
4251 				    B_FALSE);
4252 			}
4253 		}
4254 	}
4255 	MAC_PROMISC_WALKER_DCR(mip);
4256 }
4257 
4258 /*
4259  * Return the margin value currently assigned to the specified MAC instance.
4260  */
4261 void
4262 mac_margin_get(mac_handle_t mh, uint32_t *marginp)
4263 {
4264 	mac_impl_t *mip = (mac_impl_t *)mh;
4265 
4266 	rw_enter(&(mip->mi_rw_lock), RW_READER);
4267 	*marginp = mip->mi_margin;
4268 	rw_exit(&(mip->mi_rw_lock));
4269 }
4270 
4271 /*
4272  * mac_info_get() is used for retrieving the mac_info when a DL_INFO_REQ is
4273  * issued before a DL_ATTACH_REQ. we walk the i_mac_impl_hash table and find
4274  * the first mac_impl_t with a matching driver name; then we copy its mac_info_t
4275  * to the caller. we do all this with i_mac_impl_lock held so the mac_impl_t
4276  * cannot disappear while we are accessing it.
4277  */
4278 typedef struct i_mac_info_state_s {
4279 	const char	*mi_name;
4280 	mac_info_t	*mi_infop;
4281 } i_mac_info_state_t;
4282 
4283 /*ARGSUSED*/
4284 static uint_t
4285 i_mac_info_walker(mod_hash_key_t key, mod_hash_val_t *val, void *arg)
4286 {
4287 	i_mac_info_state_t *statep = arg;
4288 	mac_impl_t *mip = (mac_impl_t *)val;
4289 
4290 	if (mip->mi_state_flags & MIS_DISABLED)
4291 		return (MH_WALK_CONTINUE);
4292 
4293 	if (strcmp(statep->mi_name,
4294 	    ddi_driver_name(mip->mi_dip)) != 0)
4295 		return (MH_WALK_CONTINUE);
4296 
4297 	statep->mi_infop = &mip->mi_info;
4298 	return (MH_WALK_TERMINATE);
4299 }
4300 
4301 boolean_t
4302 mac_info_get(const char *name, mac_info_t *minfop)
4303 {
4304 	i_mac_info_state_t state;
4305 
4306 	rw_enter(&i_mac_impl_lock, RW_READER);
4307 	state.mi_name = name;
4308 	state.mi_infop = NULL;
4309 	mod_hash_walk(i_mac_impl_hash, i_mac_info_walker, &state);
4310 	if (state.mi_infop == NULL) {
4311 		rw_exit(&i_mac_impl_lock);
4312 		return (B_FALSE);
4313 	}
4314 	*minfop = *state.mi_infop;
4315 	rw_exit(&i_mac_impl_lock);
4316 	return (B_TRUE);
4317 }
4318 
4319 /*
4320  * To get the capabilities that MAC layer cares about, such as rings, factory
4321  * mac address, vnic or not, it should directly invoke this function.  If the
4322  * link is part of a bridge, then the only "capability" it has is the inability
4323  * to do zero copy.
4324  */
4325 boolean_t
4326 i_mac_capab_get(mac_handle_t mh, mac_capab_t cap, void *cap_data)
4327 {
4328 	mac_impl_t *mip = (mac_impl_t *)mh;
4329 
4330 	if (mip->mi_bridge_link != NULL) {
4331 		return (cap == MAC_CAPAB_NO_ZCOPY);
4332 	} else if (mip->mi_callbacks->mc_callbacks & MC_GETCAPAB) {
4333 		boolean_t res;
4334 
4335 		res = mip->mi_getcapab(mip->mi_driver, cap, cap_data);
4336 		/*
4337 		 * Until we have suppport for TSOv6 emulation in the MAC
4338 		 * loopback path, do not allow the TSOv6 capability to be
4339 		 * advertised to consumers.
4340 		 */
4341 		if (res && cap == MAC_CAPAB_LSO) {
4342 			mac_capab_lso_t *cap_lso = cap_data;
4343 
4344 			cap_lso->lso_flags &= ~LSO_TX_BASIC_TCP_IPV6;
4345 			cap_lso->lso_basic_tcp_ipv6.lso_max = 0;
4346 		}
4347 		return (res);
4348 	} else {
4349 		return (B_FALSE);
4350 	}
4351 }
4352 
4353 /*
4354  * Capability query function. If number of active mac clients is greater than
4355  * 1, only limited capabilities can be advertised to the caller no matter the
4356  * driver has certain capability or not. Else, we query the driver to get the
4357  * capability.
4358  */
4359 boolean_t
4360 mac_capab_get(mac_handle_t mh, mac_capab_t cap, void *cap_data)
4361 {
4362 	mac_impl_t *mip = (mac_impl_t *)mh;
4363 
4364 	/*
4365 	 * Some capabilities are restricted when there are more than one active
4366 	 * clients on the MAC resource.  The ones noted below are safe,
4367 	 * independent of that count.
4368 	 */
4369 	if (mip->mi_nactiveclients > 1) {
4370 		switch (cap) {
4371 		case MAC_CAPAB_NO_ZCOPY:
4372 			return (B_TRUE);
4373 		case MAC_CAPAB_LEGACY:
4374 		case MAC_CAPAB_HCKSUM:
4375 		case MAC_CAPAB_LSO:
4376 		case MAC_CAPAB_NO_NATIVEVLAN:
4377 			break;
4378 		default:
4379 			return (B_FALSE);
4380 		}
4381 	}
4382 
4383 	/* else get capab from driver */
4384 	return (i_mac_capab_get(mh, cap, cap_data));
4385 }
4386 
4387 boolean_t
4388 mac_sap_verify(mac_handle_t mh, uint32_t sap, uint32_t *bind_sap)
4389 {
4390 	mac_impl_t *mip = (mac_impl_t *)mh;
4391 
4392 	return (mip->mi_type->mt_ops.mtops_sap_verify(sap, bind_sap,
4393 	    mip->mi_pdata));
4394 }
4395 
4396 mblk_t *
4397 mac_header(mac_handle_t mh, const uint8_t *daddr, uint32_t sap, mblk_t *payload,
4398     size_t extra_len)
4399 {
4400 	mac_impl_t	*mip = (mac_impl_t *)mh;
4401 	const uint8_t	*hdr_daddr;
4402 
4403 	/*
4404 	 * If the MAC is point-to-point with a fixed destination address, then
4405 	 * we must always use that destination in the MAC header.
4406 	 */
4407 	hdr_daddr = (mip->mi_dstaddr_set ? mip->mi_dstaddr : daddr);
4408 	return (mip->mi_type->mt_ops.mtops_header(mip->mi_addr, hdr_daddr, sap,
4409 	    mip->mi_pdata, payload, extra_len));
4410 }
4411 
4412 int
4413 mac_header_info(mac_handle_t mh, mblk_t *mp, mac_header_info_t *mhip)
4414 {
4415 	mac_impl_t *mip = (mac_impl_t *)mh;
4416 
4417 	return (mip->mi_type->mt_ops.mtops_header_info(mp, mip->mi_pdata,
4418 	    mhip));
4419 }
4420 
4421 int
4422 mac_vlan_header_info(mac_handle_t mh, mblk_t *mp, mac_header_info_t *mhip)
4423 {
4424 	mac_impl_t	*mip = (mac_impl_t *)mh;
4425 	boolean_t	is_ethernet = (mip->mi_info.mi_media == DL_ETHER);
4426 	int		err = 0;
4427 
4428 	/*
4429 	 * Packets should always be at least 16 bit aligned.
4430 	 */
4431 	ASSERT(IS_P2ALIGNED(mp->b_rptr, sizeof (uint16_t)));
4432 
4433 	if ((err = mac_header_info(mh, mp, mhip)) != 0)
4434 		return (err);
4435 
4436 	/*
4437 	 * If this is a VLAN-tagged Ethernet packet, then the SAP in the
4438 	 * mac_header_info_t as returned by mac_header_info() is
4439 	 * ETHERTYPE_VLAN. We need to grab the ethertype from the VLAN header.
4440 	 */
4441 	if (is_ethernet && (mhip->mhi_bindsap == ETHERTYPE_VLAN)) {
4442 		struct ether_vlan_header *evhp;
4443 		uint16_t sap;
4444 		mblk_t *tmp = NULL;
4445 		size_t size;
4446 
4447 		size = sizeof (struct ether_vlan_header);
4448 		if (MBLKL(mp) < size) {
4449 			/*
4450 			 * Pullup the message in order to get the MAC header
4451 			 * infomation. Note that this is a read-only function,
4452 			 * we keep the input packet intact.
4453 			 */
4454 			if ((tmp = msgpullup(mp, size)) == NULL)
4455 				return (EINVAL);
4456 
4457 			mp = tmp;
4458 		}
4459 		evhp = (struct ether_vlan_header *)mp->b_rptr;
4460 		sap = ntohs(evhp->ether_type);
4461 		(void) mac_sap_verify(mh, sap, &mhip->mhi_bindsap);
4462 		mhip->mhi_hdrsize = sizeof (struct ether_vlan_header);
4463 		mhip->mhi_tci = ntohs(evhp->ether_tci);
4464 		mhip->mhi_istagged = B_TRUE;
4465 		freemsg(tmp);
4466 
4467 		if (VLAN_CFI(mhip->mhi_tci) != ETHER_CFI)
4468 			return (EINVAL);
4469 	} else {
4470 		mhip->mhi_istagged = B_FALSE;
4471 		mhip->mhi_tci = 0;
4472 	}
4473 
4474 	return (0);
4475 }
4476 
4477 mblk_t *
4478 mac_header_cook(mac_handle_t mh, mblk_t *mp)
4479 {
4480 	mac_impl_t *mip = (mac_impl_t *)mh;
4481 
4482 	if (mip->mi_type->mt_ops.mtops_ops & MTOPS_HEADER_COOK) {
4483 		if (DB_REF(mp) > 1) {
4484 			mblk_t *newmp = copymsg(mp);
4485 			if (newmp == NULL)
4486 				return (NULL);
4487 			freemsg(mp);
4488 			mp = newmp;
4489 		}
4490 		return (mip->mi_type->mt_ops.mtops_header_cook(mp,
4491 		    mip->mi_pdata));
4492 	}
4493 	return (mp);
4494 }
4495 
4496 mblk_t *
4497 mac_header_uncook(mac_handle_t mh, mblk_t *mp)
4498 {
4499 	mac_impl_t *mip = (mac_impl_t *)mh;
4500 
4501 	if (mip->mi_type->mt_ops.mtops_ops & MTOPS_HEADER_UNCOOK) {
4502 		if (DB_REF(mp) > 1) {
4503 			mblk_t *newmp = copymsg(mp);
4504 			if (newmp == NULL)
4505 				return (NULL);
4506 			freemsg(mp);
4507 			mp = newmp;
4508 		}
4509 		return (mip->mi_type->mt_ops.mtops_header_uncook(mp,
4510 		    mip->mi_pdata));
4511 	}
4512 	return (mp);
4513 }
4514 
4515 uint_t
4516 mac_addr_len(mac_handle_t mh)
4517 {
4518 	mac_impl_t *mip = (mac_impl_t *)mh;
4519 
4520 	return (mip->mi_type->mt_addr_length);
4521 }
4522 
4523 /* True if a MAC is a VNIC */
4524 boolean_t
4525 mac_is_vnic(mac_handle_t mh)
4526 {
4527 	return (((mac_impl_t *)mh)->mi_state_flags & MIS_IS_VNIC);
4528 }
4529 
4530 mac_handle_t
4531 mac_get_lower_mac_handle(mac_handle_t mh)
4532 {
4533 	mac_impl_t *mip = (mac_impl_t *)mh;
4534 
4535 	ASSERT(mac_is_vnic(mh));
4536 	return (((vnic_t *)mip->mi_driver)->vn_lower_mh);
4537 }
4538 
4539 boolean_t
4540 mac_is_vnic_primary(mac_handle_t mh)
4541 {
4542 	mac_impl_t *mip = (mac_impl_t *)mh;
4543 
4544 	ASSERT(mac_is_vnic(mh));
4545 	return (((vnic_t *)mip->mi_driver)->vn_addr_type ==
4546 	    VNIC_MAC_ADDR_TYPE_PRIMARY);
4547 }
4548 
4549 void
4550 mac_update_resources(mac_resource_props_t *nmrp, mac_resource_props_t *cmrp,
4551     boolean_t is_user_flow)
4552 {
4553 	if (nmrp != NULL && cmrp != NULL) {
4554 		if (nmrp->mrp_mask & MRP_PRIORITY) {
4555 			if (nmrp->mrp_priority == MPL_RESET) {
4556 				cmrp->mrp_mask &= ~MRP_PRIORITY;
4557 				if (is_user_flow) {
4558 					cmrp->mrp_priority =
4559 					    MPL_SUBFLOW_DEFAULT;
4560 				} else {
4561 					cmrp->mrp_priority = MPL_LINK_DEFAULT;
4562 				}
4563 			} else {
4564 				cmrp->mrp_mask |= MRP_PRIORITY;
4565 				cmrp->mrp_priority = nmrp->mrp_priority;
4566 			}
4567 		}
4568 		if (nmrp->mrp_mask & MRP_MAXBW) {
4569 			if (nmrp->mrp_maxbw == MRP_MAXBW_RESETVAL) {
4570 				cmrp->mrp_mask &= ~MRP_MAXBW;
4571 				cmrp->mrp_maxbw = 0;
4572 			} else {
4573 				cmrp->mrp_mask |= MRP_MAXBW;
4574 				cmrp->mrp_maxbw = nmrp->mrp_maxbw;
4575 			}
4576 		}
4577 		if (nmrp->mrp_mask & MRP_CPUS)
4578 			MAC_COPY_CPUS(nmrp, cmrp);
4579 
4580 		if (nmrp->mrp_mask & MRP_POOL) {
4581 			if (strlen(nmrp->mrp_pool) == 0) {
4582 				cmrp->mrp_mask &= ~MRP_POOL;
4583 				bzero(cmrp->mrp_pool, sizeof (cmrp->mrp_pool));
4584 			} else {
4585 				cmrp->mrp_mask |= MRP_POOL;
4586 				(void) strncpy(cmrp->mrp_pool, nmrp->mrp_pool,
4587 				    sizeof (cmrp->mrp_pool));
4588 			}
4589 
4590 		}
4591 
4592 		if (nmrp->mrp_mask & MRP_PROTECT)
4593 			mac_protect_update(nmrp, cmrp);
4594 
4595 		/*
4596 		 * Update the rings specified.
4597 		 */
4598 		if (nmrp->mrp_mask & MRP_RX_RINGS) {
4599 			if (nmrp->mrp_mask & MRP_RINGS_RESET) {
4600 				cmrp->mrp_mask &= ~MRP_RX_RINGS;
4601 				if (cmrp->mrp_mask & MRP_RXRINGS_UNSPEC)
4602 					cmrp->mrp_mask &= ~MRP_RXRINGS_UNSPEC;
4603 				cmrp->mrp_nrxrings = 0;
4604 			} else {
4605 				cmrp->mrp_mask |= MRP_RX_RINGS;
4606 				cmrp->mrp_nrxrings = nmrp->mrp_nrxrings;
4607 			}
4608 		}
4609 		if (nmrp->mrp_mask & MRP_TX_RINGS) {
4610 			if (nmrp->mrp_mask & MRP_RINGS_RESET) {
4611 				cmrp->mrp_mask &= ~MRP_TX_RINGS;
4612 				if (cmrp->mrp_mask & MRP_TXRINGS_UNSPEC)
4613 					cmrp->mrp_mask &= ~MRP_TXRINGS_UNSPEC;
4614 				cmrp->mrp_ntxrings = 0;
4615 			} else {
4616 				cmrp->mrp_mask |= MRP_TX_RINGS;
4617 				cmrp->mrp_ntxrings = nmrp->mrp_ntxrings;
4618 			}
4619 		}
4620 		if (nmrp->mrp_mask & MRP_RXRINGS_UNSPEC)
4621 			cmrp->mrp_mask |= MRP_RXRINGS_UNSPEC;
4622 		else if (cmrp->mrp_mask & MRP_RXRINGS_UNSPEC)
4623 			cmrp->mrp_mask &= ~MRP_RXRINGS_UNSPEC;
4624 
4625 		if (nmrp->mrp_mask & MRP_TXRINGS_UNSPEC)
4626 			cmrp->mrp_mask |= MRP_TXRINGS_UNSPEC;
4627 		else if (cmrp->mrp_mask & MRP_TXRINGS_UNSPEC)
4628 			cmrp->mrp_mask &= ~MRP_TXRINGS_UNSPEC;
4629 	}
4630 }
4631 
4632 /*
4633  * i_mac_set_resources:
4634  *
4635  * This routine associates properties with the primary MAC client of
4636  * the specified MAC instance.
4637  * - Cache the properties in mac_impl_t
4638  * - Apply the properties to the primary MAC client if exists
4639  */
4640 int
4641 i_mac_set_resources(mac_handle_t mh, mac_resource_props_t *mrp)
4642 {
4643 	mac_impl_t		*mip = (mac_impl_t *)mh;
4644 	mac_client_impl_t	*mcip;
4645 	int			err = 0;
4646 	uint32_t		resmask, newresmask;
4647 	mac_resource_props_t	*tmrp, *umrp;
4648 
4649 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
4650 
4651 	err = mac_validate_props(mip, mrp);
4652 	if (err != 0)
4653 		return (err);
4654 
4655 	umrp = kmem_zalloc(sizeof (*umrp), KM_SLEEP);
4656 	bcopy(&mip->mi_resource_props, umrp, sizeof (*umrp));
4657 	resmask = umrp->mrp_mask;
4658 	mac_update_resources(mrp, umrp, B_FALSE);
4659 	newresmask = umrp->mrp_mask;
4660 
4661 	if (resmask == 0 && newresmask != 0) {
4662 		/*
4663 		 * Bandwidth, priority, cpu or pool link properties configured,
4664 		 * must disable fastpath.
4665 		 */
4666 		if ((err = mac_fastpath_disable((mac_handle_t)mip)) != 0) {
4667 			kmem_free(umrp, sizeof (*umrp));
4668 			return (err);
4669 		}
4670 	}
4671 
4672 	/*
4673 	 * Since bind_cpu may be modified by mac_client_set_resources()
4674 	 * we use a copy of bind_cpu and finally cache bind_cpu in mip.
4675 	 * This allows us to cache only user edits in mip.
4676 	 */
4677 	tmrp = kmem_zalloc(sizeof (*tmrp), KM_SLEEP);
4678 	bcopy(mrp, tmrp, sizeof (*tmrp));
4679 	mcip = mac_primary_client_handle(mip);
4680 	if (mcip != NULL && (mcip->mci_state_flags & MCIS_IS_AGGR_PORT) == 0) {
4681 		err = mac_client_set_resources((mac_client_handle_t)mcip, tmrp);
4682 	} else if ((mrp->mrp_mask & MRP_RX_RINGS ||
4683 	    mrp->mrp_mask & MRP_TX_RINGS)) {
4684 		mac_client_impl_t	*vmcip;
4685 
4686 		/*
4687 		 * If the primary is not up, we need to check if there
4688 		 * are any VLANs on this primary. If there are then
4689 		 * we need to set this property on the VLANs since
4690 		 * VLANs follow the primary they are based on. Just
4691 		 * look for the first VLAN and change its properties,
4692 		 * all the other VLANs should be in the same group.
4693 		 */
4694 		for (vmcip = mip->mi_clients_list; vmcip != NULL;
4695 		    vmcip = vmcip->mci_client_next) {
4696 			if ((vmcip->mci_flent->fe_type & FLOW_PRIMARY_MAC) &&
4697 			    mac_client_vid((mac_client_handle_t)vmcip) !=
4698 			    VLAN_ID_NONE) {
4699 				break;
4700 			}
4701 		}
4702 		if (vmcip != NULL) {
4703 			mac_resource_props_t	*omrp;
4704 			mac_resource_props_t	*vmrp;
4705 
4706 			omrp = kmem_zalloc(sizeof (*omrp), KM_SLEEP);
4707 			bcopy(MCIP_RESOURCE_PROPS(vmcip), omrp, sizeof (*omrp));
4708 			/*
4709 			 * We dont' call mac_update_resources since we
4710 			 * want to take only the ring properties and
4711 			 * not all the properties that may have changed.
4712 			 */
4713 			vmrp = MCIP_RESOURCE_PROPS(vmcip);
4714 			if (mrp->mrp_mask & MRP_RX_RINGS) {
4715 				if (mrp->mrp_mask & MRP_RINGS_RESET) {
4716 					vmrp->mrp_mask &= ~MRP_RX_RINGS;
4717 					if (vmrp->mrp_mask &
4718 					    MRP_RXRINGS_UNSPEC) {
4719 						vmrp->mrp_mask &=
4720 						    ~MRP_RXRINGS_UNSPEC;
4721 					}
4722 					vmrp->mrp_nrxrings = 0;
4723 				} else {
4724 					vmrp->mrp_mask |= MRP_RX_RINGS;
4725 					vmrp->mrp_nrxrings = mrp->mrp_nrxrings;
4726 				}
4727 			}
4728 			if (mrp->mrp_mask & MRP_TX_RINGS) {
4729 				if (mrp->mrp_mask & MRP_RINGS_RESET) {
4730 					vmrp->mrp_mask &= ~MRP_TX_RINGS;
4731 					if (vmrp->mrp_mask &
4732 					    MRP_TXRINGS_UNSPEC) {
4733 						vmrp->mrp_mask &=
4734 						    ~MRP_TXRINGS_UNSPEC;
4735 					}
4736 					vmrp->mrp_ntxrings = 0;
4737 				} else {
4738 					vmrp->mrp_mask |= MRP_TX_RINGS;
4739 					vmrp->mrp_ntxrings = mrp->mrp_ntxrings;
4740 				}
4741 			}
4742 			if (mrp->mrp_mask & MRP_RXRINGS_UNSPEC)
4743 				vmrp->mrp_mask |= MRP_RXRINGS_UNSPEC;
4744 
4745 			if (mrp->mrp_mask & MRP_TXRINGS_UNSPEC)
4746 				vmrp->mrp_mask |= MRP_TXRINGS_UNSPEC;
4747 
4748 			if ((err = mac_client_set_rings_prop(vmcip, mrp,
4749 			    omrp)) != 0) {
4750 				bcopy(omrp, MCIP_RESOURCE_PROPS(vmcip),
4751 				    sizeof (*omrp));
4752 			} else {
4753 				mac_set_prim_vlan_rings(mip, vmrp);
4754 			}
4755 			kmem_free(omrp, sizeof (*omrp));
4756 		}
4757 	}
4758 
4759 	/* Only update the values if mac_client_set_resources succeeded */
4760 	if (err == 0) {
4761 		bcopy(umrp, &mip->mi_resource_props, sizeof (*umrp));
4762 		/*
4763 		 * If bandwidth, priority or cpu link properties cleared,
4764 		 * renable fastpath.
4765 		 */
4766 		if (resmask != 0 && newresmask == 0)
4767 			mac_fastpath_enable((mac_handle_t)mip);
4768 	} else if (resmask == 0 && newresmask != 0) {
4769 		mac_fastpath_enable((mac_handle_t)mip);
4770 	}
4771 	kmem_free(tmrp, sizeof (*tmrp));
4772 	kmem_free(umrp, sizeof (*umrp));
4773 	return (err);
4774 }
4775 
4776 int
4777 mac_set_resources(mac_handle_t mh, mac_resource_props_t *mrp)
4778 {
4779 	int err;
4780 
4781 	i_mac_perim_enter((mac_impl_t *)mh);
4782 	err = i_mac_set_resources(mh, mrp);
4783 	i_mac_perim_exit((mac_impl_t *)mh);
4784 	return (err);
4785 }
4786 
4787 /*
4788  * Get the properties cached for the specified MAC instance.
4789  */
4790 void
4791 mac_get_resources(mac_handle_t mh, mac_resource_props_t *mrp)
4792 {
4793 	mac_impl_t		*mip = (mac_impl_t *)mh;
4794 	mac_client_impl_t	*mcip;
4795 
4796 	mcip = mac_primary_client_handle(mip);
4797 	if (mcip != NULL) {
4798 		mac_client_get_resources((mac_client_handle_t)mcip, mrp);
4799 		return;
4800 	}
4801 	bcopy(&mip->mi_resource_props, mrp, sizeof (mac_resource_props_t));
4802 }
4803 
4804 /*
4805  * Get the effective properties from the primary client of the
4806  * specified MAC instance.
4807  */
4808 void
4809 mac_get_effective_resources(mac_handle_t mh, mac_resource_props_t *mrp)
4810 {
4811 	mac_impl_t		*mip = (mac_impl_t *)mh;
4812 	mac_client_impl_t	*mcip;
4813 
4814 	mcip = mac_primary_client_handle(mip);
4815 	if (mcip != NULL) {
4816 		mac_client_get_effective_resources((mac_client_handle_t)mcip,
4817 		    mrp);
4818 		return;
4819 	}
4820 	bzero(mrp, sizeof (mac_resource_props_t));
4821 }
4822 
4823 int
4824 mac_set_pvid(mac_handle_t mh, uint16_t pvid)
4825 {
4826 	mac_impl_t *mip = (mac_impl_t *)mh;
4827 	mac_client_impl_t *mcip;
4828 	mac_unicast_impl_t *muip;
4829 
4830 	i_mac_perim_enter(mip);
4831 	if (pvid != 0) {
4832 		for (mcip = mip->mi_clients_list; mcip != NULL;
4833 		    mcip = mcip->mci_client_next) {
4834 			for (muip = mcip->mci_unicast_list; muip != NULL;
4835 			    muip = muip->mui_next) {
4836 				if (muip->mui_vid == pvid) {
4837 					i_mac_perim_exit(mip);
4838 					return (EBUSY);
4839 				}
4840 			}
4841 		}
4842 	}
4843 	mip->mi_pvid = pvid;
4844 	i_mac_perim_exit(mip);
4845 	return (0);
4846 }
4847 
4848 uint16_t
4849 mac_get_pvid(mac_handle_t mh)
4850 {
4851 	mac_impl_t *mip = (mac_impl_t *)mh;
4852 
4853 	return (mip->mi_pvid);
4854 }
4855 
4856 uint32_t
4857 mac_get_llimit(mac_handle_t mh)
4858 {
4859 	mac_impl_t *mip = (mac_impl_t *)mh;
4860 
4861 	return (mip->mi_llimit);
4862 }
4863 
4864 uint32_t
4865 mac_get_ldecay(mac_handle_t mh)
4866 {
4867 	mac_impl_t *mip = (mac_impl_t *)mh;
4868 
4869 	return (mip->mi_ldecay);
4870 }
4871 
4872 /*
4873  * Rename a mac client, its flow, and the kstat.
4874  */
4875 int
4876 mac_rename_primary(mac_handle_t mh, const char *new_name)
4877 {
4878 	mac_impl_t		*mip = (mac_impl_t *)mh;
4879 	mac_client_impl_t	*cur_clnt = NULL;
4880 	flow_entry_t		*fep;
4881 
4882 	i_mac_perim_enter(mip);
4883 
4884 	/*
4885 	 * VNICs: we need to change the sys flow name and
4886 	 * the associated flow kstat.
4887 	 */
4888 	if (mip->mi_state_flags & MIS_IS_VNIC) {
4889 		mac_client_impl_t *mcip = mac_vnic_lower(mip);
4890 		ASSERT(new_name != NULL);
4891 		mac_rename_flow_names(mcip, new_name);
4892 		mac_stat_rename(mcip);
4893 		goto done;
4894 	}
4895 	/*
4896 	 * This mac may itself be an aggr link, or it may have some client
4897 	 * which is an aggr port. For both cases, we need to change the
4898 	 * aggr port's mac client name, its flow name and the associated flow
4899 	 * kstat.
4900 	 */
4901 	if (mip->mi_state_flags & MIS_IS_AGGR) {
4902 		mac_capab_aggr_t aggr_cap;
4903 		mac_rename_fn_t rename_fn;
4904 		boolean_t ret;
4905 
4906 		ASSERT(new_name != NULL);
4907 		ret = i_mac_capab_get((mac_handle_t)mip, MAC_CAPAB_AGGR,
4908 		    (void *)(&aggr_cap));
4909 		ASSERT(ret == B_TRUE);
4910 		rename_fn = aggr_cap.mca_rename_fn;
4911 		rename_fn(new_name, mip->mi_driver);
4912 		/*
4913 		 * The aggr's client name and kstat flow name will be
4914 		 * updated below, i.e. via mac_rename_flow_names.
4915 		 */
4916 	}
4917 
4918 	for (cur_clnt = mip->mi_clients_list; cur_clnt != NULL;
4919 	    cur_clnt = cur_clnt->mci_client_next) {
4920 		if (cur_clnt->mci_state_flags & MCIS_IS_AGGR_PORT) {
4921 			if (new_name != NULL) {
4922 				char *str_st = cur_clnt->mci_name;
4923 				char *str_del = strchr(str_st, '-');
4924 
4925 				ASSERT(str_del != NULL);
4926 				bzero(str_del + 1, MAXNAMELEN -
4927 				    (str_del - str_st + 1));
4928 				bcopy(new_name, str_del + 1,
4929 				    strlen(new_name));
4930 			}
4931 			fep = cur_clnt->mci_flent;
4932 			mac_rename_flow(fep, cur_clnt->mci_name);
4933 			break;
4934 		} else if (new_name != NULL &&
4935 		    cur_clnt->mci_state_flags & MCIS_USE_DATALINK_NAME) {
4936 			mac_rename_flow_names(cur_clnt, new_name);
4937 			break;
4938 		}
4939 	}
4940 
4941 	/* Recreate kstats associated with aggr pseudo rings */
4942 	if (mip->mi_state_flags & MIS_IS_AGGR)
4943 		mac_pseudo_ring_stat_rename(mip);
4944 
4945 done:
4946 	i_mac_perim_exit(mip);
4947 	return (0);
4948 }
4949 
4950 /*
4951  * Rename the MAC client's flow names
4952  */
4953 static void
4954 mac_rename_flow_names(mac_client_impl_t *mcip, const char *new_name)
4955 {
4956 	flow_entry_t	*flent;
4957 	uint16_t	vid;
4958 	char		flowname[MAXFLOWNAMELEN];
4959 	mac_impl_t	*mip = mcip->mci_mip;
4960 
4961 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
4962 
4963 	/*
4964 	 * Use mi_rw_lock to ensure that threads not in the mac perimeter
4965 	 * see a self-consistent value for mci_name
4966 	 */
4967 	rw_enter(&mip->mi_rw_lock, RW_WRITER);
4968 	(void) strlcpy(mcip->mci_name, new_name, sizeof (mcip->mci_name));
4969 	rw_exit(&mip->mi_rw_lock);
4970 
4971 	mac_rename_flow(mcip->mci_flent, new_name);
4972 
4973 	if (mcip->mci_nflents == 1)
4974 		return;
4975 
4976 	/*
4977 	 * We have to rename all the others too, no stats to destroy for
4978 	 * these.
4979 	 */
4980 	for (flent = mcip->mci_flent_list; flent != NULL;
4981 	    flent = flent->fe_client_next) {
4982 		if (flent != mcip->mci_flent) {
4983 			vid = i_mac_flow_vid(flent);
4984 			(void) sprintf(flowname, "%s%u", new_name, vid);
4985 			mac_flow_set_name(flent, flowname);
4986 		}
4987 	}
4988 }
4989 
4990 
4991 /*
4992  * Add a flow to the MAC client's flow list - i.e list of MAC/VID tuples
4993  * defined for the specified MAC client.
4994  */
4995 static void
4996 mac_client_add_to_flow_list(mac_client_impl_t *mcip, flow_entry_t *flent)
4997 {
4998 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mcip->mci_mip));
4999 	/*
5000 	 * The promisc Rx data path walks the mci_flent_list. Protect by
5001 	 * using mi_rw_lock
5002 	 */
5003 	rw_enter(&mcip->mci_rw_lock, RW_WRITER);
5004 
5005 	mcip->mci_vidcache = MCIP_VIDCACHE_INVALID;
5006 
5007 	/* Add it to the head */
5008 	flent->fe_client_next = mcip->mci_flent_list;
5009 	mcip->mci_flent_list = flent;
5010 	mcip->mci_nflents++;
5011 
5012 	/*
5013 	 * Keep track of the number of non-zero VIDs addresses per MAC
5014 	 * client to avoid figuring it out in the data-path.
5015 	 */
5016 	if (i_mac_flow_vid(flent) != VLAN_ID_NONE)
5017 		mcip->mci_nvids++;
5018 
5019 	rw_exit(&mcip->mci_rw_lock);
5020 }
5021 
5022 /*
5023  * Remove a flow entry from the MAC client's list.
5024  */
5025 static void
5026 mac_client_remove_flow_from_list(mac_client_impl_t *mcip, flow_entry_t *flent)
5027 {
5028 	flow_entry_t	*fe = mcip->mci_flent_list;
5029 	flow_entry_t	*prev_fe = NULL;
5030 
5031 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mcip->mci_mip));
5032 	/*
5033 	 * The promisc Rx data path walks the mci_flent_list. Protect by
5034 	 * using mci_rw_lock
5035 	 */
5036 	rw_enter(&mcip->mci_rw_lock, RW_WRITER);
5037 	mcip->mci_vidcache = MCIP_VIDCACHE_INVALID;
5038 
5039 	while ((fe != NULL) && (fe != flent)) {
5040 		prev_fe = fe;
5041 		fe = fe->fe_client_next;
5042 	}
5043 
5044 	ASSERT(fe != NULL);
5045 	if (prev_fe == NULL) {
5046 		/* Deleting the first node */
5047 		mcip->mci_flent_list = fe->fe_client_next;
5048 	} else {
5049 		prev_fe->fe_client_next = fe->fe_client_next;
5050 	}
5051 	mcip->mci_nflents--;
5052 
5053 	if (i_mac_flow_vid(flent) != VLAN_ID_NONE)
5054 		mcip->mci_nvids--;
5055 
5056 	rw_exit(&mcip->mci_rw_lock);
5057 }
5058 
5059 /*
5060  * Check if the given VID belongs to this MAC client.
5061  */
5062 boolean_t
5063 mac_client_check_flow_vid(mac_client_impl_t *mcip, uint16_t vid)
5064 {
5065 	flow_entry_t	*flent;
5066 	uint16_t	mci_vid;
5067 	uint32_t	cache = mcip->mci_vidcache;
5068 
5069 	/*
5070 	 * In hopes of not having to touch the mci_rw_lock, check to see if
5071 	 * this vid matches our cached result.
5072 	 */
5073 	if (MCIP_VIDCACHE_ISVALID(cache) && MCIP_VIDCACHE_VID(cache) == vid)
5074 		return (MCIP_VIDCACHE_BOOL(cache) ? B_TRUE : B_FALSE);
5075 
5076 	/* The mci_flent_list is protected by mci_rw_lock */
5077 	rw_enter(&mcip->mci_rw_lock, RW_WRITER);
5078 	for (flent = mcip->mci_flent_list; flent != NULL;
5079 	    flent = flent->fe_client_next) {
5080 		mci_vid = i_mac_flow_vid(flent);
5081 		if (vid == mci_vid) {
5082 			mcip->mci_vidcache = MCIP_VIDCACHE_CACHE(vid, B_TRUE);
5083 			rw_exit(&mcip->mci_rw_lock);
5084 			return (B_TRUE);
5085 		}
5086 	}
5087 
5088 	mcip->mci_vidcache = MCIP_VIDCACHE_CACHE(vid, B_FALSE);
5089 	rw_exit(&mcip->mci_rw_lock);
5090 	return (B_FALSE);
5091 }
5092 
5093 /*
5094  * Get the flow entry for the specified <MAC addr, VID> tuple.
5095  */
5096 static flow_entry_t *
5097 mac_client_get_flow(mac_client_impl_t *mcip, mac_unicast_impl_t *muip)
5098 {
5099 	mac_address_t *map = mcip->mci_unicast;
5100 	flow_entry_t *flent;
5101 	uint16_t vid;
5102 	flow_desc_t flow_desc;
5103 
5104 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mcip->mci_mip));
5105 
5106 	mac_flow_get_desc(mcip->mci_flent, &flow_desc);
5107 	if (bcmp(flow_desc.fd_dst_mac, map->ma_addr, map->ma_len) != 0)
5108 		return (NULL);
5109 
5110 	for (flent = mcip->mci_flent_list; flent != NULL;
5111 	    flent = flent->fe_client_next) {
5112 		vid = i_mac_flow_vid(flent);
5113 		if (vid == muip->mui_vid) {
5114 			return (flent);
5115 		}
5116 	}
5117 
5118 	return (NULL);
5119 }
5120 
5121 /*
5122  * Since mci_flent has the SRSs, when we want to remove it, we replace
5123  * the flow_desc_t in mci_flent with that of an existing flent and then
5124  * remove that flent instead of mci_flent.
5125  */
5126 static flow_entry_t *
5127 mac_client_swap_mciflent(mac_client_impl_t *mcip)
5128 {
5129 	flow_entry_t	*flent = mcip->mci_flent;
5130 	flow_tab_t	*ft = flent->fe_flow_tab;
5131 	flow_entry_t	*flent1;
5132 	flow_desc_t	fl_desc;
5133 	char		fl_name[MAXFLOWNAMELEN];
5134 	int		err;
5135 
5136 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mcip->mci_mip));
5137 	ASSERT(mcip->mci_nflents > 1);
5138 
5139 	/* get the next flent following the primary flent  */
5140 	flent1 = mcip->mci_flent_list->fe_client_next;
5141 	ASSERT(flent1 != NULL && flent1->fe_flow_tab == ft);
5142 
5143 	/*
5144 	 * Remove the flent from the flow table before updating the
5145 	 * flow descriptor as the hash depends on the flow descriptor.
5146 	 * This also helps incoming packet classification avoid having
5147 	 * to grab fe_lock. Access to fe_flow_desc of a flent not in the
5148 	 * flow table is done under the fe_lock so that log or stat functions
5149 	 * see a self-consistent fe_flow_desc. The name and desc are specific
5150 	 * to a flow, the rest are shared by all the clients, including
5151 	 * resource control etc.
5152 	 */
5153 	mac_flow_remove(ft, flent, B_TRUE);
5154 	mac_flow_remove(ft, flent1, B_TRUE);
5155 
5156 	bcopy(&flent->fe_flow_desc, &fl_desc, sizeof (flow_desc_t));
5157 	bcopy(flent->fe_flow_name, fl_name, MAXFLOWNAMELEN);
5158 
5159 	/* update the primary flow entry */
5160 	mutex_enter(&flent->fe_lock);
5161 	bcopy(&flent1->fe_flow_desc, &flent->fe_flow_desc,
5162 	    sizeof (flow_desc_t));
5163 	bcopy(&flent1->fe_flow_name, &flent->fe_flow_name, MAXFLOWNAMELEN);
5164 	mutex_exit(&flent->fe_lock);
5165 
5166 	/* update the flow entry that is to be freed */
5167 	mutex_enter(&flent1->fe_lock);
5168 	bcopy(&fl_desc, &flent1->fe_flow_desc, sizeof (flow_desc_t));
5169 	bcopy(fl_name, &flent1->fe_flow_name, MAXFLOWNAMELEN);
5170 	mutex_exit(&flent1->fe_lock);
5171 
5172 	/* now reinsert the flow entries in the table */
5173 	err = mac_flow_add(ft, flent);
5174 	ASSERT(err == 0);
5175 
5176 	err = mac_flow_add(ft, flent1);
5177 	ASSERT(err == 0);
5178 
5179 	return (flent1);
5180 }
5181 
5182 /*
5183  * Return whether there is only one flow entry associated with this
5184  * MAC client.
5185  */
5186 static boolean_t
5187 mac_client_single_rcvr(mac_client_impl_t *mcip)
5188 {
5189 	return (mcip->mci_nflents == 1);
5190 }
5191 
5192 int
5193 mac_validate_props(mac_impl_t *mip, mac_resource_props_t *mrp)
5194 {
5195 	boolean_t		reset;
5196 	uint32_t		rings_needed;
5197 	uint32_t		rings_avail;
5198 	mac_group_type_t	gtype;
5199 	mac_resource_props_t	*mip_mrp;
5200 
5201 	if (mrp == NULL)
5202 		return (0);
5203 
5204 	if (mrp->mrp_mask & MRP_PRIORITY) {
5205 		mac_priority_level_t	pri = mrp->mrp_priority;
5206 
5207 		if (pri < MPL_LOW || pri > MPL_RESET)
5208 			return (EINVAL);
5209 	}
5210 
5211 	if (mrp->mrp_mask & MRP_MAXBW) {
5212 		uint64_t maxbw = mrp->mrp_maxbw;
5213 
5214 		if (maxbw < MRP_MAXBW_MINVAL && maxbw != 0)
5215 			return (EINVAL);
5216 	}
5217 	if (mrp->mrp_mask & MRP_CPUS) {
5218 		int i, j;
5219 		mac_cpu_mode_t	fanout;
5220 
5221 		if (mrp->mrp_ncpus > ncpus)
5222 			return (EINVAL);
5223 
5224 		for (i = 0; i < mrp->mrp_ncpus; i++) {
5225 			for (j = 0; j < mrp->mrp_ncpus; j++) {
5226 				if (i != j &&
5227 				    mrp->mrp_cpu[i] == mrp->mrp_cpu[j]) {
5228 					return (EINVAL);
5229 				}
5230 			}
5231 		}
5232 
5233 		for (i = 0; i < mrp->mrp_ncpus; i++) {
5234 			cpu_t *cp;
5235 			int rv;
5236 
5237 			mutex_enter(&cpu_lock);
5238 			cp = cpu_get(mrp->mrp_cpu[i]);
5239 			if (cp != NULL)
5240 				rv = cpu_is_online(cp);
5241 			else
5242 				rv = 0;
5243 			mutex_exit(&cpu_lock);
5244 			if (rv == 0)
5245 				return (EINVAL);
5246 		}
5247 
5248 		fanout = mrp->mrp_fanout_mode;
5249 		if (fanout < 0 || fanout > MCM_CPUS)
5250 			return (EINVAL);
5251 	}
5252 
5253 	if (mrp->mrp_mask & MRP_PROTECT) {
5254 		int err = mac_protect_validate(mrp);
5255 		if (err != 0)
5256 			return (err);
5257 	}
5258 
5259 	if (!(mrp->mrp_mask & MRP_RX_RINGS) &&
5260 	    !(mrp->mrp_mask & MRP_TX_RINGS)) {
5261 		return (0);
5262 	}
5263 
5264 	/*
5265 	 * mip will be null when we come from mac_flow_create or
5266 	 * mac_link_flow_modify. In the latter case it is a user flow,
5267 	 * for which we don't support rings. In the former we would
5268 	 * have validated the props beforehand (i_mac_unicast_add ->
5269 	 * mac_client_set_resources -> validate for the primary and
5270 	 * vnic_dev_create -> mac_client_set_resources -> validate for
5271 	 * a vnic.
5272 	 */
5273 	if (mip == NULL)
5274 		return (0);
5275 
5276 	/*
5277 	 * We don't support setting rings property for a VNIC that is using a
5278 	 * primary address (VLAN)
5279 	 */
5280 	if ((mip->mi_state_flags & MIS_IS_VNIC) &&
5281 	    mac_is_vnic_primary((mac_handle_t)mip)) {
5282 		return (ENOTSUP);
5283 	}
5284 
5285 	mip_mrp = &mip->mi_resource_props;
5286 	/*
5287 	 * The rings property should be validated against the NICs
5288 	 * resources
5289 	 */
5290 	if (mip->mi_state_flags & MIS_IS_VNIC)
5291 		mip = (mac_impl_t *)mac_get_lower_mac_handle((mac_handle_t)mip);
5292 
5293 	reset = mrp->mrp_mask & MRP_RINGS_RESET;
5294 	/*
5295 	 * If groups are not supported, return error.
5296 	 */
5297 	if (((mrp->mrp_mask & MRP_RX_RINGS) && mip->mi_rx_groups == NULL) ||
5298 	    ((mrp->mrp_mask & MRP_TX_RINGS) && mip->mi_tx_groups == NULL)) {
5299 		return (EINVAL);
5300 	}
5301 	/*
5302 	 * If we are just resetting, there is no validation needed.
5303 	 */
5304 	if (reset)
5305 		return (0);
5306 
5307 	if (mrp->mrp_mask & MRP_RX_RINGS) {
5308 		rings_needed = mrp->mrp_nrxrings;
5309 		/*
5310 		 * We just want to check if the number of additional
5311 		 * rings requested is available.
5312 		 */
5313 		if (mip_mrp->mrp_mask & MRP_RX_RINGS) {
5314 			if (mrp->mrp_nrxrings > mip_mrp->mrp_nrxrings)
5315 				/* Just check for the additional rings */
5316 				rings_needed -= mip_mrp->mrp_nrxrings;
5317 			else
5318 				/* We are not asking for additional rings */
5319 				rings_needed = 0;
5320 		}
5321 		rings_avail = mip->mi_rxrings_avail;
5322 		gtype = mip->mi_rx_group_type;
5323 	} else {
5324 		rings_needed = mrp->mrp_ntxrings;
5325 		/* Similarly for the TX rings */
5326 		if (mip_mrp->mrp_mask & MRP_TX_RINGS) {
5327 			if (mrp->mrp_ntxrings > mip_mrp->mrp_ntxrings)
5328 				/* Just check for the additional rings */
5329 				rings_needed -= mip_mrp->mrp_ntxrings;
5330 			else
5331 				/* We are not asking for additional rings */
5332 				rings_needed = 0;
5333 		}
5334 		rings_avail = mip->mi_txrings_avail;
5335 		gtype = mip->mi_tx_group_type;
5336 	}
5337 
5338 	/* Error if the group is dynamic .. */
5339 	if (gtype == MAC_GROUP_TYPE_DYNAMIC) {
5340 		/*
5341 		 * .. and rings specified are more than available.
5342 		 */
5343 		if (rings_needed > rings_avail)
5344 			return (EINVAL);
5345 	} else {
5346 		/*
5347 		 * OR group is static and we have specified some rings.
5348 		 */
5349 		if (rings_needed > 0)
5350 			return (EINVAL);
5351 	}
5352 	return (0);
5353 }
5354 
5355 /*
5356  * Send a MAC_NOTE_LINK notification to all the MAC clients whenever the
5357  * underlying physical link is down. This is to allow MAC clients to
5358  * communicate with other clients.
5359  */
5360 void
5361 mac_virtual_link_update(mac_impl_t *mip)
5362 {
5363 	if (mip->mi_linkstate != LINK_STATE_UP)
5364 		i_mac_notify(mip, MAC_NOTE_LINK);
5365 }
5366 
5367 /*
5368  * For clients that have a pass-thru MAC, e.g. VNIC, we set the VNIC's
5369  * mac handle in the client.
5370  */
5371 void
5372 mac_set_upper_mac(mac_client_handle_t mch, mac_handle_t mh,
5373     mac_resource_props_t *mrp)
5374 {
5375 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
5376 	mac_impl_t		*mip = (mac_impl_t *)mh;
5377 
5378 	mcip->mci_upper_mip = mip;
5379 	/* If there are any properties, copy it over too */
5380 	if (mrp != NULL) {
5381 		bcopy(mrp, &mip->mi_resource_props,
5382 		    sizeof (mac_resource_props_t));
5383 	}
5384 }
5385 
5386 /*
5387  * Mark the mac as being used exclusively by the single mac client that is
5388  * doing some control operation on this mac. No further opens of this mac
5389  * will be allowed until this client calls mac_unmark_exclusive. The mac
5390  * client calling this function must already be in the mac perimeter
5391  */
5392 int
5393 mac_mark_exclusive(mac_handle_t mh)
5394 {
5395 	mac_impl_t	*mip = (mac_impl_t *)mh;
5396 
5397 	ASSERT(MAC_PERIM_HELD(mh));
5398 	/*
5399 	 * Look up its entry in the global hash table.
5400 	 */
5401 	rw_enter(&i_mac_impl_lock, RW_WRITER);
5402 	if (mip->mi_state_flags & MIS_DISABLED) {
5403 		rw_exit(&i_mac_impl_lock);
5404 		return (ENOENT);
5405 	}
5406 
5407 	/*
5408 	 * A reference to mac is held even if the link is not plumbed.
5409 	 * In i_dls_link_create() we open the MAC interface and hold the
5410 	 * reference. There is an additional reference for the mac_open
5411 	 * done in acquiring the mac perimeter
5412 	 */
5413 	if (mip->mi_ref != 2) {
5414 		rw_exit(&i_mac_impl_lock);
5415 		return (EBUSY);
5416 	}
5417 
5418 	ASSERT(!(mip->mi_state_flags & MIS_EXCLUSIVE_HELD));
5419 	mip->mi_state_flags |= MIS_EXCLUSIVE_HELD;
5420 	rw_exit(&i_mac_impl_lock);
5421 	return (0);
5422 }
5423 
5424 void
5425 mac_unmark_exclusive(mac_handle_t mh)
5426 {
5427 	mac_impl_t	*mip = (mac_impl_t *)mh;
5428 
5429 	ASSERT(MAC_PERIM_HELD(mh));
5430 
5431 	rw_enter(&i_mac_impl_lock, RW_WRITER);
5432 	/* 1 for the creation and another for the perimeter */
5433 	ASSERT(mip->mi_ref == 2 && (mip->mi_state_flags & MIS_EXCLUSIVE_HELD));
5434 	mip->mi_state_flags &= ~MIS_EXCLUSIVE_HELD;
5435 	rw_exit(&i_mac_impl_lock);
5436 }
5437 
5438 /*
5439  * Set the MTU for the specified MAC.
5440  */
5441 int
5442 mac_set_mtu(mac_handle_t mh, uint_t new_mtu, uint_t *old_mtu_arg)
5443 {
5444 	mac_impl_t *mip = (mac_impl_t *)mh;
5445 	uint_t old_mtu;
5446 	int rv = 0;
5447 
5448 	i_mac_perim_enter(mip);
5449 
5450 	if (!(mip->mi_callbacks->mc_callbacks & (MC_SETPROP|MC_GETPROP))) {
5451 		rv = ENOTSUP;
5452 		goto bail;
5453 	}
5454 
5455 	old_mtu = mip->mi_sdu_max;
5456 
5457 	if (new_mtu == 0 || new_mtu < mip->mi_sdu_min) {
5458 		rv = EINVAL;
5459 		goto bail;
5460 	}
5461 
5462 	rw_enter(&mip->mi_rw_lock, RW_READER);
5463 	if (mip->mi_mtrp != NULL && new_mtu < mip->mi_mtrp->mtr_mtu) {
5464 		rv = EBUSY;
5465 		rw_exit(&mip->mi_rw_lock);
5466 		goto bail;
5467 	}
5468 	rw_exit(&mip->mi_rw_lock);
5469 
5470 	if (old_mtu != new_mtu) {
5471 		rv = mip->mi_callbacks->mc_setprop(mip->mi_driver,
5472 		    "mtu", MAC_PROP_MTU, sizeof (uint_t), &new_mtu);
5473 		if (rv != 0)
5474 			goto bail;
5475 		rv = mac_maxsdu_update(mh, new_mtu);
5476 		ASSERT(rv == 0);
5477 	}
5478 
5479 bail:
5480 	i_mac_perim_exit(mip);
5481 
5482 	if (rv == 0 && old_mtu_arg != NULL)
5483 		*old_mtu_arg = old_mtu;
5484 	return (rv);
5485 }
5486 
5487 /*
5488  * Return the RX h/w information for the group indexed by grp_num.
5489  */
5490 void
5491 mac_get_hwrxgrp_info(mac_handle_t mh, int grp_index, uint_t *grp_num,
5492     uint_t *n_rings, uint_t *rings, uint_t *type, uint_t *n_clnts,
5493     char *clnts_name)
5494 {
5495 	mac_impl_t *mip = (mac_impl_t *)mh;
5496 	mac_grp_client_t *mcip;
5497 	uint_t i = 0, index = 0;
5498 	mac_ring_t	*ring;
5499 
5500 	/* Revisit when we implement fully dynamic group allocation */
5501 	ASSERT(grp_index >= 0 && grp_index < mip->mi_rx_group_count);
5502 
5503 	rw_enter(&mip->mi_rw_lock, RW_READER);
5504 	*grp_num = mip->mi_rx_groups[grp_index].mrg_index;
5505 	*type = mip->mi_rx_groups[grp_index].mrg_type;
5506 	*n_rings = mip->mi_rx_groups[grp_index].mrg_cur_count;
5507 	ring = mip->mi_rx_groups[grp_index].mrg_rings;
5508 	for (index = 0; index < mip->mi_rx_groups[grp_index].mrg_cur_count;
5509 	    index++) {
5510 		rings[index] = ring->mr_index;
5511 		ring = ring->mr_next;
5512 	}
5513 	/* Assuming the 1st is the default group */
5514 	index = 0;
5515 	if (grp_index == 0) {
5516 		(void) strlcpy(clnts_name, "<default,mcast>,",
5517 		    MAXCLIENTNAMELEN);
5518 		index += strlen("<default,mcast>,");
5519 	}
5520 	for (mcip = mip->mi_rx_groups[grp_index].mrg_clients; mcip != NULL;
5521 	    mcip = mcip->mgc_next) {
5522 		int name_len = strlen(mcip->mgc_client->mci_name);
5523 
5524 		/*
5525 		 * MAXCLIENTNAMELEN is the buffer size reserved for client
5526 		 * names.
5527 		 * XXXX Formating the client name string needs to be moved
5528 		 * to user land when fixing the size of dhi_clnts in
5529 		 * dld_hwgrpinfo_t. We should use n_clients * client_name for
5530 		 * dhi_clntsin instead of MAXCLIENTNAMELEN
5531 		 */
5532 		if (index + name_len >= MAXCLIENTNAMELEN) {
5533 			index = MAXCLIENTNAMELEN;
5534 			break;
5535 		}
5536 		bcopy(mcip->mgc_client->mci_name, &(clnts_name[index]),
5537 		    name_len);
5538 		index += name_len;
5539 		clnts_name[index++] = ',';
5540 		i++;
5541 	}
5542 
5543 	/* Get rid of the last , */
5544 	if (index > 0)
5545 		clnts_name[index - 1] = '\0';
5546 	*n_clnts = i;
5547 	rw_exit(&mip->mi_rw_lock);
5548 }
5549 
5550 /*
5551  * Return the TX h/w information for the group indexed by grp_num.
5552  */
5553 void
5554 mac_get_hwtxgrp_info(mac_handle_t mh, int grp_index, uint_t *grp_num,
5555     uint_t *n_rings, uint_t *rings, uint_t *type, uint_t *n_clnts,
5556     char *clnts_name)
5557 {
5558 	mac_impl_t *mip = (mac_impl_t *)mh;
5559 	mac_grp_client_t *mcip;
5560 	uint_t i = 0, index = 0;
5561 	mac_ring_t	*ring;
5562 
5563 	/* Revisit when we implement fully dynamic group allocation */
5564 	ASSERT(grp_index >= 0 && grp_index <= mip->mi_tx_group_count);
5565 
5566 	rw_enter(&mip->mi_rw_lock, RW_READER);
5567 	*grp_num = mip->mi_tx_groups[grp_index].mrg_index > 0 ?
5568 	    mip->mi_tx_groups[grp_index].mrg_index : grp_index;
5569 	*type = mip->mi_tx_groups[grp_index].mrg_type;
5570 	*n_rings = mip->mi_tx_groups[grp_index].mrg_cur_count;
5571 	ring = mip->mi_tx_groups[grp_index].mrg_rings;
5572 	for (index = 0; index < mip->mi_tx_groups[grp_index].mrg_cur_count;
5573 	    index++) {
5574 		rings[index] = ring->mr_index;
5575 		ring = ring->mr_next;
5576 	}
5577 	index = 0;
5578 	/* Default group has an index of -1 */
5579 	if (mip->mi_tx_groups[grp_index].mrg_index < 0) {
5580 		(void) strlcpy(clnts_name, "<default>,",
5581 		    MAXCLIENTNAMELEN);
5582 		index += strlen("<default>,");
5583 	}
5584 	for (mcip = mip->mi_tx_groups[grp_index].mrg_clients; mcip != NULL;
5585 	    mcip = mcip->mgc_next) {
5586 		int name_len = strlen(mcip->mgc_client->mci_name);
5587 
5588 		/*
5589 		 * MAXCLIENTNAMELEN is the buffer size reserved for client
5590 		 * names.
5591 		 * XXXX Formating the client name string needs to be moved
5592 		 * to user land when fixing the size of dhi_clnts in
5593 		 * dld_hwgrpinfo_t. We should use n_clients * client_name for
5594 		 * dhi_clntsin instead of MAXCLIENTNAMELEN
5595 		 */
5596 		if (index + name_len >= MAXCLIENTNAMELEN) {
5597 			index = MAXCLIENTNAMELEN;
5598 			break;
5599 		}
5600 		bcopy(mcip->mgc_client->mci_name, &(clnts_name[index]),
5601 		    name_len);
5602 		index += name_len;
5603 		clnts_name[index++] = ',';
5604 		i++;
5605 	}
5606 
5607 	/* Get rid of the last , */
5608 	if (index > 0)
5609 		clnts_name[index - 1] = '\0';
5610 	*n_clnts = i;
5611 	rw_exit(&mip->mi_rw_lock);
5612 }
5613 
5614 /*
5615  * Return the group count for RX or TX.
5616  */
5617 uint_t
5618 mac_hwgrp_num(mac_handle_t mh, int type)
5619 {
5620 	mac_impl_t *mip = (mac_impl_t *)mh;
5621 
5622 	/*
5623 	 * Return the Rx and Tx group count; for the Tx we need to
5624 	 * include the default too.
5625 	 */
5626 	return (type == MAC_RING_TYPE_RX ? mip->mi_rx_group_count :
5627 	    mip->mi_tx_groups != NULL ? mip->mi_tx_group_count + 1 : 0);
5628 }
5629 
5630 /*
5631  * The total number of free TX rings for this MAC.
5632  */
5633 uint_t
5634 mac_txavail_get(mac_handle_t mh)
5635 {
5636 	mac_impl_t	*mip = (mac_impl_t *)mh;
5637 
5638 	return (mip->mi_txrings_avail);
5639 }
5640 
5641 /*
5642  * The total number of free RX rings for this MAC.
5643  */
5644 uint_t
5645 mac_rxavail_get(mac_handle_t mh)
5646 {
5647 	mac_impl_t	*mip = (mac_impl_t *)mh;
5648 
5649 	return (mip->mi_rxrings_avail);
5650 }
5651 
5652 /*
5653  * The total number of reserved RX rings on this MAC.
5654  */
5655 uint_t
5656 mac_rxrsvd_get(mac_handle_t mh)
5657 {
5658 	mac_impl_t	*mip = (mac_impl_t *)mh;
5659 
5660 	return (mip->mi_rxrings_rsvd);
5661 }
5662 
5663 /*
5664  * The total number of reserved TX rings on this MAC.
5665  */
5666 uint_t
5667 mac_txrsvd_get(mac_handle_t mh)
5668 {
5669 	mac_impl_t	*mip = (mac_impl_t *)mh;
5670 
5671 	return (mip->mi_txrings_rsvd);
5672 }
5673 
5674 /*
5675  * Total number of free RX groups on this MAC.
5676  */
5677 uint_t
5678 mac_rxhwlnksavail_get(mac_handle_t mh)
5679 {
5680 	mac_impl_t	*mip = (mac_impl_t *)mh;
5681 
5682 	return (mip->mi_rxhwclnt_avail);
5683 }
5684 
5685 /*
5686  * Total number of RX groups reserved on this MAC.
5687  */
5688 uint_t
5689 mac_rxhwlnksrsvd_get(mac_handle_t mh)
5690 {
5691 	mac_impl_t	*mip = (mac_impl_t *)mh;
5692 
5693 	return (mip->mi_rxhwclnt_used);
5694 }
5695 
5696 /*
5697  * Total number of free TX groups on this MAC.
5698  */
5699 uint_t
5700 mac_txhwlnksavail_get(mac_handle_t mh)
5701 {
5702 	mac_impl_t	*mip = (mac_impl_t *)mh;
5703 
5704 	return (mip->mi_txhwclnt_avail);
5705 }
5706 
5707 /*
5708  * Total number of TX groups reserved on this MAC.
5709  */
5710 uint_t
5711 mac_txhwlnksrsvd_get(mac_handle_t mh)
5712 {
5713 	mac_impl_t	*mip = (mac_impl_t *)mh;
5714 
5715 	return (mip->mi_txhwclnt_used);
5716 }
5717 
5718 /*
5719  * Initialize the rings property for a mac client. A non-0 value for
5720  * rxring or txring specifies the number of rings required, a value
5721  * of MAC_RXRINGS_NONE/MAC_TXRINGS_NONE specifies that it doesn't need
5722  * any RX/TX rings and a value of MAC_RXRINGS_DONTCARE/MAC_TXRINGS_DONTCARE
5723  * means the system can decide whether it can give any rings or not.
5724  */
5725 void
5726 mac_client_set_rings(mac_client_handle_t mch, int rxrings, int txrings)
5727 {
5728 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
5729 	mac_resource_props_t	*mrp = MCIP_RESOURCE_PROPS(mcip);
5730 
5731 	if (rxrings != MAC_RXRINGS_DONTCARE) {
5732 		mrp->mrp_mask |= MRP_RX_RINGS;
5733 		mrp->mrp_nrxrings = rxrings;
5734 	}
5735 
5736 	if (txrings != MAC_TXRINGS_DONTCARE) {
5737 		mrp->mrp_mask |= MRP_TX_RINGS;
5738 		mrp->mrp_ntxrings = txrings;
5739 	}
5740 }
5741 
5742 boolean_t
5743 mac_get_promisc_filtered(mac_client_handle_t mch)
5744 {
5745 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
5746 
5747 	return (mcip->mci_protect_flags & MPT_FLAG_PROMISC_FILTERED);
5748 }
5749 
5750 void
5751 mac_set_promisc_filtered(mac_client_handle_t mch, boolean_t enable)
5752 {
5753 	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
5754 
5755 	ASSERT(MAC_PERIM_HELD((mac_handle_t)mcip->mci_mip));
5756 	if (enable)
5757 		mcip->mci_protect_flags |= MPT_FLAG_PROMISC_FILTERED;
5758 	else
5759 		mcip->mci_protect_flags &= ~MPT_FLAG_PROMISC_FILTERED;
5760 }
5761