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