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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2012, Nexenta Systems, Inc. All rights reserved.
28 * Copyright (c) 2013 Joyent, Inc. All rights reserved.
32 * Data-Link Services Module
35 #include <sys/strsun.h>
37 #include <sys/dld_impl.h>
38 #include <sys/mac_client_priv.h>
41 dls_open(dls_link_t
*dlp
, dls_dl_handle_t ddh
, dld_str_t
*dsp
)
43 zoneid_t zid
= getzoneid();
48 * Check whether this client belongs to the zone of this dlp. Note that
49 * a global zone client is allowed to open a local zone dlp.
51 if (zid
!= GLOBAL_ZONEID
&& dlp
->dl_zid
!= zid
)
55 * mac_start() is required for non-legacy MACs to show accurate
56 * kstats even before the interface is brought up. For legacy
57 * drivers, this is not needed. Further, calling mac_start() for
58 * legacy drivers would make the shared-lower-stream to stay in
59 * the DL_IDLE state, which in turn causes performance regression.
61 if (!mac_capab_get(dlp
->dl_mh
, MAC_CAPAB_LEGACY
, NULL
) &&
62 ((err
= mac_start(dlp
->dl_mh
)) != 0)) {
66 local
= (zid
== dlp
->dl_zid
);
67 dlp
->dl_zone_ref
+= (local
? 1 : 0);
70 * Cache a copy of the MAC interface handle, a pointer to the
74 dsp
->ds_mh
= dlp
->dl_mh
;
75 dsp
->ds_mch
= dlp
->dl_mch
;
76 dsp
->ds_mip
= dlp
->dl_mip
;
78 dsp
->ds_local
= local
;
80 ASSERT(MAC_PERIM_HELD(dsp
->ds_mh
));
85 dls_close(dld_str_t
*dsp
)
87 dls_link_t
*dlp
= dsp
->ds_dlp
;
88 dls_multicst_addr_t
*p
;
89 dls_multicst_addr_t
*nextp
;
91 ASSERT(dsp
->ds_datathr_cnt
== 0);
92 ASSERT(MAC_PERIM_HELD(dsp
->ds_mh
));
96 dsp
->ds_local
= B_FALSE
;
99 * Walk the list of multicast addresses, disabling each at the MAC.
100 * Note that we must remove multicast address before
101 * mac_unicast_remove() (called by dls_active_clear()) because
102 * mac_multicast_remove() relies on the unicast flows on the mac
105 for (p
= dsp
->ds_dmap
; p
!= NULL
; p
= nextp
) {
106 (void) mac_multicast_remove(dsp
->ds_mch
, p
->dma_addr
);
107 nextp
= p
->dma_nextp
;
108 kmem_free(p
, sizeof (dls_multicst_addr_t
));
112 dls_active_clear(dsp
, B_TRUE
);
115 * If the dld_str_t is bound then unbind it.
117 if (dsp
->ds_dlstate
== DL_IDLE
) {
119 dsp
->ds_dlstate
= DL_UNBOUND
;
123 * If the MAC has been set in promiscuous mode then disable it.
124 * This needs to be done before resetting ds_rx.
126 (void) dls_promisc(dsp
, 0);
129 * At this point we have cutoff inbound packet flow from the mac
130 * for this 'dsp'. The dls_link_remove above cut off packets meant
131 * for us and waited for upcalls to finish. Similarly the dls_promisc
132 * reset above waited for promisc callbacks to finish. Now we can
133 * safely reset ds_rx to NULL
136 dsp
->ds_rx_arg
= NULL
;
140 if (!mac_capab_get(dsp
->ds_mh
, MAC_CAPAB_LEGACY
, NULL
))
141 mac_stop(dsp
->ds_mh
);
144 * Release our reference to the dls_link_t allowing that to be
145 * destroyed if there are no more dls_impl_t.
151 dls_bind(dld_str_t
*dsp
, uint32_t sap
)
155 ASSERT(MAC_PERIM_HELD(dsp
->ds_mh
));
158 * Check to see the value is legal for the media type.
160 if (!mac_sap_verify(dsp
->ds_mh
, sap
, &dls_sap
))
163 if (dsp
->ds_promisc
& DLS_PROMISC_SAP
)
164 dls_sap
= DLS_SAP_PROMISC
;
167 * Set up the dld_str_t to mark it as able to receive packets.
172 * The MAC layer does the VLAN demultiplexing and will only pass up
173 * untagged packets to non-promiscuous primary MAC clients. In order to
174 * support the binding to the VLAN SAP which is required by DLPI, dls
175 * needs to get a copy of all tagged packets when the client binds to
176 * the VLAN SAP. We do this by registering a separate promiscuous
177 * callback for each dls client binding to that SAP.
179 * Note: even though there are two promiscuous handles in dld_str_t,
180 * ds_mph is for the regular promiscuous mode, ds_vlan_mph is the handle
181 * to receive VLAN pkt when promiscuous mode is not on. Only one of
182 * them can be non-NULL at the same time, to avoid receiving dup copies
185 if (sap
== ETHERTYPE_VLAN
&& dsp
->ds_promisc
== 0) {
188 if (dsp
->ds_vlan_mph
!= NULL
)
190 err
= mac_promisc_add(dsp
->ds_mch
,
191 MAC_CLIENT_PROMISC_ALL
, dls_rx_vlan_promisc
, dsp
,
192 &dsp
->ds_vlan_mph
, MAC_PROMISC_FLAGS_NO_PHYS
);
194 if (err
== 0 && dsp
->ds_nonip
&&
195 dsp
->ds_dlp
->dl_nonip_cnt
++ == 0)
196 mac_rx_bypass_disable(dsp
->ds_mch
);
202 * Now bind the dld_str_t by adding it into the hash table in the
205 dls_link_add(dsp
->ds_dlp
, dls_sap
, dsp
);
206 if (dsp
->ds_nonip
&& dsp
->ds_dlp
->dl_nonip_cnt
++ == 0)
207 mac_rx_bypass_disable(dsp
->ds_mch
);
213 dls_unbind(dld_str_t
*dsp
)
215 ASSERT(MAC_PERIM_HELD(dsp
->ds_mh
));
217 if (dsp
->ds_nonip
&& --dsp
->ds_dlp
->dl_nonip_cnt
== 0)
218 mac_rx_bypass_enable(dsp
->ds_mch
);
221 * For VLAN SAP, there was a promisc handle registered when dls_bind.
222 * When unbind this dls link, we need to remove the promisc handle.
223 * See comments in dls_bind().
225 if (dsp
->ds_vlan_mph
!= NULL
) {
226 mac_promisc_remove(dsp
->ds_vlan_mph
);
227 dsp
->ds_vlan_mph
= NULL
;
232 * Unbind the dld_str_t by removing it from the hash table in the
235 dls_link_remove(dsp
->ds_dlp
, dsp
);
240 * In order to prevent promiscuous-mode processing with dsp->ds_promisc
241 * set to inaccurate values, this function sets dsp->ds_promisc with new
242 * flags. For enabling (mac_promisc_add), the flags are set prior to the
243 * actual enabling. For disabling (mac_promisc_remove), the flags are set
244 * after the actual disabling.
247 dls_promisc(dld_str_t
*dsp
, uint32_t new_flags
)
250 uint32_t old_flags
= dsp
->ds_promisc
;
251 mac_client_promisc_type_t mptype
= MAC_CLIENT_PROMISC_ALL
;
253 ASSERT(MAC_PERIM_HELD(dsp
->ds_mh
));
254 ASSERT(!(new_flags
& ~(DLS_PROMISC_SAP
| DLS_PROMISC_MULTI
|
258 * If the user has only requested DLS_PROMISC_MULTI then we need to make
259 * sure that they don't see all packets.
261 if (new_flags
== DLS_PROMISC_MULTI
)
262 mptype
= MAC_CLIENT_PROMISC_MULTI
;
264 if (dsp
->ds_promisc
== 0 && new_flags
!= 0) {
266 * If only DLS_PROMISC_SAP, we don't turn on the
267 * physical promisc mode
269 dsp
->ds_promisc
= new_flags
;
270 err
= mac_promisc_add(dsp
->ds_mch
, mptype
,
271 dls_rx_promisc
, dsp
, &dsp
->ds_mph
,
272 (new_flags
!= DLS_PROMISC_SAP
) ? 0 :
273 MAC_PROMISC_FLAGS_NO_PHYS
);
275 dsp
->ds_promisc
= old_flags
;
279 /* Remove vlan promisc handle to avoid sending dup copy up */
280 if (dsp
->ds_vlan_mph
!= NULL
) {
281 mac_promisc_remove(dsp
->ds_vlan_mph
);
282 dsp
->ds_vlan_mph
= NULL
;
284 } else if (dsp
->ds_promisc
!= 0 && new_flags
== 0) {
285 ASSERT(dsp
->ds_mph
!= NULL
);
287 mac_promisc_remove(dsp
->ds_mph
);
288 dsp
->ds_promisc
= new_flags
;
291 if (dsp
->ds_sap
== ETHERTYPE_VLAN
&&
292 dsp
->ds_dlstate
!= DL_UNBOUND
) {
293 if (dsp
->ds_vlan_mph
!= NULL
)
295 err
= mac_promisc_add(dsp
->ds_mch
,
296 MAC_CLIENT_PROMISC_ALL
, dls_rx_vlan_promisc
, dsp
,
297 &dsp
->ds_vlan_mph
, MAC_PROMISC_FLAGS_NO_PHYS
);
299 } else if (dsp
->ds_promisc
== DLS_PROMISC_SAP
&& new_flags
!= 0 &&
300 new_flags
!= dsp
->ds_promisc
) {
302 * If the old flag is PROMISC_SAP, but the current flag has
303 * changed to some new non-zero value, we need to turn the
304 * physical promiscuous mode.
306 ASSERT(dsp
->ds_mph
!= NULL
);
307 mac_promisc_remove(dsp
->ds_mph
);
308 /* Honors both after-remove and before-add semantics! */
309 dsp
->ds_promisc
= new_flags
;
310 err
= mac_promisc_add(dsp
->ds_mch
, mptype
,
311 dls_rx_promisc
, dsp
, &dsp
->ds_mph
, 0);
313 dsp
->ds_promisc
= old_flags
;
315 /* No adding or removing, but record the new flags anyway. */
316 dsp
->ds_promisc
= new_flags
;
323 dls_multicst_add(dld_str_t
*dsp
, const uint8_t *addr
)
326 dls_multicst_addr_t
**pp
;
327 dls_multicst_addr_t
*p
;
330 ASSERT(MAC_PERIM_HELD(dsp
->ds_mh
));
333 * Check whether the address is in the list of enabled addresses for
336 addr_length
= dsp
->ds_mip
->mi_addr_length
;
339 * Protect against concurrent access of ds_dmap by data threads using
340 * ds_rw_lock. The mac perimeter serializes the dls_multicst_add and
341 * remove operations. Dropping the ds_rw_lock across mac calls is thus
342 * ok and is also required by the locking protocol.
344 rw_enter(&dsp
->ds_rw_lock
, RW_WRITER
);
345 for (pp
= &(dsp
->ds_dmap
); (p
= *pp
) != NULL
; pp
= &(p
->dma_nextp
)) {
346 if (bcmp(addr
, p
->dma_addr
, addr_length
) == 0) {
348 * It is there so there's nothing to do.
356 * Allocate a new list item and add it to the list.
358 p
= kmem_zalloc(sizeof (dls_multicst_addr_t
), KM_SLEEP
);
359 bcopy(addr
, p
->dma_addr
, addr_length
);
361 rw_exit(&dsp
->ds_rw_lock
);
364 * Enable the address at the MAC.
366 err
= mac_multicast_add(dsp
->ds_mch
, addr
);
370 /* Undo the operation as it has failed */
371 rw_enter(&dsp
->ds_rw_lock
, RW_WRITER
);
372 ASSERT(*pp
== p
&& p
->dma_nextp
== NULL
);
374 kmem_free(p
, sizeof (dls_multicst_addr_t
));
376 rw_exit(&dsp
->ds_rw_lock
);
381 dls_multicst_remove(dld_str_t
*dsp
, const uint8_t *addr
)
383 dls_multicst_addr_t
**pp
;
384 dls_multicst_addr_t
*p
;
387 ASSERT(MAC_PERIM_HELD(dsp
->ds_mh
));
390 * Find the address in the list of enabled addresses for this
393 addr_length
= dsp
->ds_mip
->mi_addr_length
;
396 * Protect against concurrent access to ds_dmap by data threads using
397 * ds_rw_lock. The mac perimeter serializes the dls_multicst_add and
398 * remove operations. Dropping the ds_rw_lock across mac calls is thus
399 * ok and is also required by the locking protocol.
401 rw_enter(&dsp
->ds_rw_lock
, RW_WRITER
);
402 for (pp
= &(dsp
->ds_dmap
); (p
= *pp
) != NULL
; pp
= &(p
->dma_nextp
)) {
403 if (bcmp(addr
, p
->dma_addr
, addr_length
) == 0)
408 * If we walked to the end of the list then the given address is
409 * not currently enabled for this dld_str_t.
412 rw_exit(&dsp
->ds_rw_lock
);
417 * Remove the address from the list.
420 rw_exit(&dsp
->ds_rw_lock
);
423 * Disable the address at the MAC.
425 mac_multicast_remove(dsp
->ds_mch
, addr
);
426 kmem_free(p
, sizeof (dls_multicst_addr_t
));
431 dls_header(dld_str_t
*dsp
, const uint8_t *addr
, uint16_t sap
, uint_t pri
,
437 mblk_t
*mp
, *payload
;
438 boolean_t is_ethernet
= (dsp
->ds_mip
->mi_media
== DL_ETHER
);
439 struct ether_vlan_header
*evhp
;
441 vid
= mac_client_vid(dsp
->ds_mch
);
442 payload
= (payloadp
== NULL
) ? NULL
: (*payloadp
);
445 * In the case of Ethernet, we need to tell mac_header() if we need
446 * extra room beyond the Ethernet header for a VLAN header. We'll
447 * need to add a VLAN header if this isn't an ETHERTYPE_VLAN listener
448 * (because such streams will be handling VLAN headers on their own)
449 * and one of the following conditions is satisfied:
451 * - This is a VLAN stream
452 * - This is a physical stream, the priority is not 0, and user
453 * priority tagging is allowed.
455 if (is_ethernet
&& sap
!= ETHERTYPE_VLAN
&&
456 (vid
!= VLAN_ID_NONE
||
457 (pri
!= 0 && dsp
->ds_dlp
->dl_tagmode
!= LINK_TAGMODE_VLANONLY
))) {
458 extra_len
= sizeof (struct ether_vlan_header
) -
459 sizeof (struct ether_header
);
460 mac_sap
= ETHERTYPE_VLAN
;
466 mp
= mac_header(dsp
->ds_mh
, addr
, mac_sap
, payload
, extra_len
);
470 if ((vid
== VLAN_ID_NONE
&& (pri
== 0 ||
471 dsp
->ds_dlp
->dl_tagmode
== LINK_TAGMODE_VLANONLY
)) || !is_ethernet
)
475 * Fill in the tag information.
477 ASSERT(MBLKL(mp
) == sizeof (struct ether_header
));
478 if (extra_len
!= 0) {
479 mp
->b_wptr
+= extra_len
;
480 evhp
= (struct ether_vlan_header
*)mp
->b_rptr
;
481 evhp
->ether_tci
= htons(VLAN_TCI(pri
, ETHER_CFI
, vid
));
482 evhp
->ether_type
= htons(sap
);
485 * The stream is ETHERTYPE_VLAN listener, so its VLAN tag is
486 * in the payload. Update the priority.
488 struct ether_vlan_extinfo
*extinfo
;
489 size_t len
= sizeof (struct ether_vlan_extinfo
);
491 ASSERT(sap
== ETHERTYPE_VLAN
);
492 ASSERT(payload
!= NULL
);
494 if ((DB_REF(payload
) > 1) || (MBLKL(payload
) < len
)) {
498 * Because some DLS consumers only check the db_ref
499 * count of the first mblk, we pullup 'payload' into
502 newmp
= msgpullup(payload
, -1);
503 if ((newmp
== NULL
) || (MBLKL(newmp
) < len
)) {
509 *payloadp
= payload
= newmp
;
513 extinfo
= (struct ether_vlan_extinfo
*)payload
->b_rptr
;
514 extinfo
->ether_tci
= htons(VLAN_TCI(pri
, ETHER_CFI
,
515 VLAN_ID(ntohs(extinfo
->ether_tci
))));
521 dls_rx_set(dld_str_t
*dsp
, dls_rx_t rx
, void *arg
)
523 mutex_enter(&dsp
->ds_lock
);
525 dsp
->ds_rx_arg
= arg
;
526 mutex_exit(&dsp
->ds_lock
);
530 dls_accept_common(dld_str_t
*dsp
, mac_header_info_t
*mhip
, dls_rx_t
*ds_rx
,
531 void **ds_rx_arg
, boolean_t promisc
, boolean_t promisc_loopback
)
533 dls_multicst_addr_t
*dmap
;
534 size_t addr_length
= dsp
->ds_mip
->mi_addr_length
;
537 * We must not accept packets if the dld_str_t is not marked as bound
538 * or is being removed.
540 if (dsp
->ds_dlstate
!= DL_IDLE
)
543 if (dsp
->ds_promisc
!= 0) {
545 * Filter out packets that arrived from the data path
546 * (i_dls_link_rx) when promisc mode is on. We need to correlate
547 * the ds_promisc flags with the mac header destination type. If
548 * only DLS_PROMISC_MULTI is enabled, we need to only reject
549 * multicast packets as those are the only ones which filter up
550 * the promiscuous path. If we have DLS_PROMISC_PHYS or
551 * DLS_PROMISC_SAP set, then we know that we'll be seeing
552 * everything, so we should drop it now.
554 if (!promisc
&& !(dsp
->ds_promisc
== DLS_PROMISC_MULTI
&&
555 mhip
->mhi_dsttype
!= MAC_ADDRTYPE_MULTICAST
))
558 * If the dls_impl_t is in 'all physical' mode then
561 if (dsp
->ds_promisc
& DLS_PROMISC_PHYS
)
565 * Loopback packets i.e. packets sent out by DLS on a given
566 * mac end point, will be accepted back by DLS on loopback
567 * from the mac, only in the 'all physical' mode which has been
568 * covered by the previous check above
570 if (promisc_loopback
)
574 switch (mhip
->mhi_dsttype
) {
575 case MAC_ADDRTYPE_UNICAST
:
576 case MAC_ADDRTYPE_BROADCAST
:
578 * We can accept unicast and broadcast packets because
579 * filtering is already done by the mac layer.
582 case MAC_ADDRTYPE_MULTICAST
:
584 * Additional filtering is needed for multicast addresses
585 * because different streams may be interested in different
588 if (dsp
->ds_promisc
& DLS_PROMISC_MULTI
)
591 rw_enter(&dsp
->ds_rw_lock
, RW_READER
);
592 for (dmap
= dsp
->ds_dmap
; dmap
!= NULL
;
593 dmap
= dmap
->dma_nextp
) {
594 if (memcmp(mhip
->mhi_daddr
, dmap
->dma_addr
,
596 rw_exit(&dsp
->ds_rw_lock
);
600 rw_exit(&dsp
->ds_rw_lock
);
609 * the returned ds_rx and ds_rx_arg will always be in sync.
611 mutex_enter(&dsp
->ds_lock
);
613 *ds_rx_arg
= dsp
->ds_rx_arg
;
614 mutex_exit(&dsp
->ds_lock
);
621 dls_accept(dld_str_t
*dsp
, mac_header_info_t
*mhip
, dls_rx_t
*ds_rx
,
624 return (dls_accept_common(dsp
, mhip
, ds_rx
, ds_rx_arg
, B_FALSE
,
629 dls_accept_promisc(dld_str_t
*dsp
, mac_header_info_t
*mhip
, dls_rx_t
*ds_rx
,
630 void **ds_rx_arg
, boolean_t loopback
)
632 return (dls_accept_common(dsp
, mhip
, ds_rx
, ds_rx_arg
, B_TRUE
,
637 dls_mac_active_set(dls_link_t
*dlp
)
642 * First client; add the primary unicast address.
644 if (dlp
->dl_nactive
== 0) {
646 * First client; add the primary unicast address.
650 /* request the primary MAC address */
651 if ((err
= mac_unicast_add(dlp
->dl_mch
, NULL
,
652 MAC_UNICAST_PRIMARY
| MAC_UNICAST_TAG_DISABLE
|
653 MAC_UNICAST_DISABLE_TX_VID_CHECK
, &dlp
->dl_mah
, 0,
659 * Set the function to start receiving packets.
661 mac_rx_set(dlp
->dl_mch
, i_dls_link_rx
, dlp
);
668 dls_mac_active_clear(dls_link_t
*dlp
)
670 if (--dlp
->dl_nactive
== 0) {
671 ASSERT(dlp
->dl_mah
!= NULL
);
672 (void) mac_unicast_remove(dlp
->dl_mch
, dlp
->dl_mah
);
674 mac_rx_clear(dlp
->dl_mch
);
679 dls_active_set(dld_str_t
*dsp
)
683 ASSERT(MAC_PERIM_HELD(dsp
->ds_mh
));
685 if (dsp
->ds_passivestate
== DLD_PASSIVE
)
688 /* If we're already active, then there's nothing more to do. */
689 if ((dsp
->ds_nactive
== 0) &&
690 ((err
= dls_mac_active_set(dsp
->ds_dlp
)) != 0)) {
691 /* except for ENXIO all other errors are mapped to EBUSY */
697 dsp
->ds_passivestate
= DLD_ACTIVE
;
703 * Note that dls_active_set() is called whenever an active operation
704 * (DL_BIND_REQ, DL_ENABMULTI_REQ ...) is processed and
705 * dls_active_clear(dsp, B_FALSE) is called whenever the active operation
706 * is being undone (DL_UNBIND_REQ, DL_DISABMULTI_REQ ...). In some cases,
707 * a stream is closed without every active operation being undone and we
708 * need to clear all the "active" states by calling
709 * dls_active_clear(dsp, B_TRUE).
712 dls_active_clear(dld_str_t
*dsp
, boolean_t all
)
714 ASSERT(MAC_PERIM_HELD(dsp
->ds_mh
));
716 if (dsp
->ds_passivestate
== DLD_PASSIVE
)
719 if (all
&& dsp
->ds_nactive
== 0)
722 ASSERT(dsp
->ds_nactive
> 0);
724 dsp
->ds_nactive
-= (all
? dsp
->ds_nactive
: 1);
725 if (dsp
->ds_nactive
!= 0)
728 ASSERT(dsp
->ds_passivestate
== DLD_ACTIVE
);
729 dls_mac_active_clear(dsp
->ds_dlp
);
730 dsp
->ds_passivestate
= DLD_UNINITIALIZED
;