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]
21 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22 * Use is subject to license terms.
23 * Copyright (c) 2016 by Delphix. All rights reserved.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * gld - Generic LAN Driver
30 * media dependent routines
33 #include <sys/types.h>
34 #include <sys/errno.h>
35 #include <sys/stropts.h>
36 #include <sys/stream.h>
39 #include <sys/modctl.h>
40 #include <sys/kstat.h>
41 #include <sys/debug.h>
43 #include <sys/byteorder.h>
44 #include <sys/strsun.h>
46 #include <sys/ethernet.h>
47 #include <sys/multidata.h>
49 #include <sys/gldpriv.h>
51 #include <sys/sunddi.h>
52 #include <sys/sysmacros.h>
53 #include <sys/ib/clients/ibd/ibd.h>
54 #include <sys/pattr.h>
56 #define DLSAPLENGTH(macinfo) \
57 ((macinfo)->gldm_addrlen + ABS((macinfo)->gldm_saplen))
63 extern void gld_bitrevcopy(caddr_t src
, caddr_t target
, size_t n
);
64 extern char *gld_macaddr_sprintf(char *, unsigned char *, int);
65 extern gld_vlan_t
*gld_find_vlan(gld_mac_info_t
*, uint32_t);
66 extern uint32_t gld_global_options
;
68 static struct llc_snap_hdr llc_snap_def
= {
69 LSAP_SNAP
, /* DLSAP 0xaa */
70 LSAP_SNAP
, /* SLSAP 0xaa */
71 CNTL_LLC_UI
, /* Control 0x03 */
72 0x00, 0x00, 0x00, /* Org[3] */
76 #define ISETHERTYPE(snaphdr) \
77 (snaphdr->d_lsap == LSAP_SNAP && \
78 snaphdr->s_lsap == LSAP_SNAP && \
79 snaphdr->control == CNTL_LLC_UI && \
80 snaphdr->org[0] == 0 && \
81 snaphdr->org[1] == 0 && \
88 static mac_addr_t ether_broadcast
= {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
91 gld_init_ether(gld_mac_info_t
*macinfo
)
93 struct gldkstats
*sp
=
94 ((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->kstatp
->ks_data
;
96 /* Assumptions we make for this medium */
97 ASSERT(macinfo
->gldm_type
== DL_ETHER
);
98 ASSERT(macinfo
->gldm_addrlen
== 6);
99 ASSERT(macinfo
->gldm_saplen
== -2);
100 ASSERT(sizeof (struct ether_header
) == 14);
101 ASSERT(sizeof (mac_addr_t
) == 6);
103 kstat_named_init(&sp
->glds_frame
, "align_errors", KSTAT_DATA_ULONG
);
104 kstat_named_init(&sp
->glds_crc
, "fcs_errors", KSTAT_DATA_ULONG
);
105 kstat_named_init(&sp
->glds_collisions
, "collisions", KSTAT_DATA_ULONG
);
106 kstat_named_init(&sp
->glds_nocarrier
, "carrier_errors",
108 kstat_named_init(&sp
->glds_defer
, "defer_xmts", KSTAT_DATA_ULONG
);
109 kstat_named_init(&sp
->glds_xmtlatecoll
, "tx_late_collisions",
111 kstat_named_init(&sp
->glds_short
, "runt_errors", KSTAT_DATA_ULONG
);
112 kstat_named_init(&sp
->glds_excoll
, "ex_collisions", KSTAT_DATA_ULONG
);
115 * only initialize the new statistics if the driver
118 if (macinfo
->gldm_driver_version
!= GLD_VERSION_200
)
121 kstat_named_init(&sp
->glds_dot3_first_coll
,
122 "first_collisions", KSTAT_DATA_UINT32
);
123 kstat_named_init(&sp
->glds_dot3_multi_coll
,
124 "multi_collisions", KSTAT_DATA_UINT32
);
125 kstat_named_init(&sp
->glds_dot3_sqe_error
,
126 "sqe_errors", KSTAT_DATA_UINT32
);
127 kstat_named_init(&sp
->glds_dot3_mac_xmt_error
,
128 "macxmt_errors", KSTAT_DATA_UINT32
);
129 kstat_named_init(&sp
->glds_dot3_mac_rcv_error
,
130 "macrcv_errors", KSTAT_DATA_UINT32
);
131 kstat_named_init(&sp
->glds_dot3_frame_too_long
,
132 "toolong_errors", KSTAT_DATA_UINT32
);
133 kstat_named_init(&sp
->glds_duplex
, "duplex", KSTAT_DATA_CHAR
);
138 gld_uninit_ether(gld_mac_info_t
*macinfo
)
143 gld_interpret_ether(gld_mac_info_t
*macinfo
, mblk_t
*mp
, pktinfo_t
*pktinfo
,
146 struct ether_header
*mh
;
147 gld_mac_pvt_t
*mac_pvt
= (gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
;
148 struct llc_snap_hdr
*snaphdr
;
149 mblk_t
*pmp
= NULL
, *savemp
= mp
;
150 unsigned short typelen
;
154 * Quickly handle receive fastpath for IPQ hack.
156 if (flags
== GLD_RXQUICK
) {
157 pktinfo
->pktLen
= msgdsize(mp
);
159 * Check whether the header is contiguous, which
160 * also implicitly makes sure the packet is big enough.
162 if (MBLKL(mp
) < sizeof (struct ether_header
))
164 mh
= (struct ether_header
*)mp
->b_rptr
;
165 pktinfo
->ethertype
= REF_NET_USHORT(mh
->ether_type
);
166 pktinfo
->isForMe
= mac_eq(&mh
->ether_dhost
,
167 mac_pvt
->curr_macaddr
, macinfo
->gldm_addrlen
);
168 pktinfo
->macLen
= sizeof (struct ether_header
);
173 bzero((void *)pktinfo
, sizeof (*pktinfo
));
175 pktinfo
->pktLen
= msgdsize(mp
);
177 /* make sure packet has at least a whole mac header */
178 if (pktinfo
->pktLen
< sizeof (struct ether_header
))
181 /* make sure the mac header falls into contiguous memory */
182 if (MBLKL(mp
) < sizeof (struct ether_header
)) {
183 if ((pmp
= msgpullup(mp
, -1)) == NULL
) {
185 if (gld_debug
& GLDERRS
)
187 "GLD: interpret_ether cannot msgpullup");
191 mp
= pmp
; /* this mblk contains the whole mac header */
194 mh
= (struct ether_header
*)mp
->b_rptr
;
196 /* Check to see if the mac is a broadcast or multicast address. */
197 if (mac_eq(&mh
->ether_dhost
, ether_broadcast
, macinfo
->gldm_addrlen
))
198 pktinfo
->isBroadcast
= 1;
199 else if (mh
->ether_dhost
.ether_addr_octet
[0] & 1)
200 pktinfo
->isMulticast
= 1;
202 typelen
= REF_NET_USHORT(mh
->ether_type
);
204 * If the hardware is capable of VLAN tag insertion
205 * strip out the VLAN tag info. Knowing hardware is
206 * capable of VLAN can be established by the presance
207 * of non null 'macinfo->gldm_send_tagged'.
209 if (flags
== GLD_TX
) {
210 if ((typelen
== ETHERTYPE_VLAN
) &&
211 (macinfo
->gldm_send_tagged
!= NULL
)) {
212 struct ether_vlan_header
*evhp
;
215 if ((MBLKL(mp
) < sizeof (struct ether_vlan_header
)) &&
216 (pullupmsg(mp
, sizeof (struct ether_vlan_header
))
221 evhp
= (struct ether_vlan_header
*)mp
->b_rptr
;
222 tci
= REF_NET_USHORT(evhp
->ether_tci
);
225 * We don't allow the VID and priority are both zero.
227 if ((GLD_VTAG_PRI((int32_t)tci
) == 0 &&
228 GLD_VTAG_VID((int32_t)tci
) == VLAN_VID_NONE
) ||
229 (GLD_VTAG_CFI((uint32_t)tci
)) != VLAN_CFI_ETHER
) {
235 * Remember the VTAG info in order to reinsert it,
236 * Then strip the tag. This is required because some
237 * drivers do not allow the size of message (passed
238 * by the gldm_send_tagged() function) to be greater
241 GLD_SAVE_MBLK_VTAG(savemp
, GLD_TCI2VTAG(tci
));
242 ovbcopy(mp
->b_rptr
, mp
->b_rptr
+ VTAG_SIZE
,
244 mp
->b_rptr
+= VTAG_SIZE
;
246 goto out
; /* Got all info we need for xmit case */
249 ASSERT(GLDM_LOCK_HELD(macinfo
));
252 * Deal with the mac header
255 mac_copy(&mh
->ether_dhost
, pktinfo
->dhost
, macinfo
->gldm_addrlen
);
256 mac_copy(&mh
->ether_shost
, pktinfo
->shost
, macinfo
->gldm_addrlen
);
258 pktinfo
->isLooped
= mac_eq(pktinfo
->shost
,
259 mac_pvt
->curr_macaddr
, macinfo
->gldm_addrlen
);
260 pktinfo
->isForMe
= mac_eq(pktinfo
->dhost
,
261 mac_pvt
->curr_macaddr
, macinfo
->gldm_addrlen
);
263 pktinfo
->macLen
= sizeof (struct ether_header
);
265 if (typelen
> ETHERMTU
) {
266 pktinfo
->ethertype
= typelen
; /* use type interpretation */
271 * Packet is 802.3 so the ether type/length field
272 * specifies the number of bytes that should be present
273 * in the data field. Additional bytes are padding, and
277 int delta
= pktinfo
->pktLen
-
278 (sizeof (struct ether_header
) + typelen
);
280 if (delta
> 0 && adjmsg(mp
, -delta
))
281 pktinfo
->pktLen
-= delta
;
285 * Before trying to look beyond the MAC header, make sure the LLC
286 * header exists, and that both it and any SNAP header are contiguous.
288 if (pktinfo
->pktLen
< pktinfo
->macLen
+ LLC_HDR1_LEN
)
289 goto out
; /* LLC hdr should have been there! */
293 if (gld_global_options
& GLD_OPT_NO_ETHRXSNAP
||
294 pktinfo
->pktLen
< pktinfo
->macLen
+ LLC_SNAP_HDR_LEN
)
297 if (MBLKL(mp
) < sizeof (struct ether_header
) + LLC_SNAP_HDR_LEN
&&
298 MBLKL(mp
) < pktinfo
->pktLen
) {
300 * we don't have the entire packet within the first mblk (and
301 * therefore we didn't do the msgpullup above), AND the first
302 * mblk may not contain all the data we need to look at.
304 ASSERT(pmp
== NULL
); /* couldn't have done msgpullup above */
305 if ((pmp
= msgpullup(mp
, -1)) == NULL
) {
307 if (gld_debug
& GLDERRS
)
309 "GLD: interpret_ether cannot msgpullup2");
311 goto out
; /* can't interpret this pkt further */
313 mp
= pmp
; /* this mblk should contain everything needed */
317 * Check SAP/SNAP information for EtherType.
320 snaphdr
= (struct llc_snap_hdr
*)(mp
->b_rptr
+ pktinfo
->macLen
);
321 if (ISETHERTYPE(snaphdr
)) {
322 pktinfo
->ethertype
= REF_NET_USHORT(snaphdr
->type
);
323 pktinfo
->hdrLen
= LLC_SNAP_HDR_LEN
;
333 gld_unitdata_ether(gld_t
*gld
, mblk_t
*mp
)
335 gld_mac_info_t
*macinfo
= gld
->gld_mac_info
;
336 dl_unitdata_req_t
*dlp
= (dl_unitdata_req_t
*)mp
->b_rptr
;
337 struct gld_dlsap
*gldp
= DLSAP(dlp
, dlp
->dl_dest_addr_offset
);
339 unsigned short typelen
;
341 struct ether_header
*mh
;
344 gld_vlan_t
*gld_vlan
;
348 /* extract needed info from the mblk before we maybe reuse it */
349 mac_copy(gldp
->glda_addr
, dhost
, macinfo
->gldm_addrlen
);
351 /* look in the unitdata request for a sap, else use bound one */
352 if (dlp
->dl_dest_addr_length
>= DLSAPLENGTH(macinfo
) &&
353 REF_HOST_USHORT(gldp
->glda_sap
) != 0)
354 typelen
= REF_HOST_USHORT(gldp
->glda_sap
);
356 typelen
= gld
->gld_sap
;
359 * We take values less than or equal to ETHERMTU to mean that the
360 * packet should not have an encoded EtherType and so we use the
361 * IEEE 802.3 length interpretation of the type/length field.
363 if (typelen
<= ETHERMTU
)
364 typelen
= msgdsize(mp
);
366 hdrlen
= sizeof (struct ether_header
);
369 * Check to see if VLAN is enabled on this stream
370 * if so then make the header bigger to hold a clone
373 gld_vlan
= (gld_vlan_t
*)gld
->gld_vlan
;
374 if (gld_vlan
&& (gld_vlan
->gldv_id
!= VLAN_VID_NONE
)) {
376 vptag
= gld_vlan
->gldv_ptag
;
379 /* need a buffer big enough for the headers */
380 nmp
= mp
->b_cont
; /* where the packet payload M_DATA is */
381 if (DB_REF(nmp
) == 1 && MBLKHEAD(nmp
) >= hdrlen
) {
382 /* it fits at the beginning of the first M_DATA block */
383 freeb(mp
); /* don't need the M_PROTO anymore */
384 } else if (DB_REF(mp
) == 1 && MBLKSIZE(mp
) >= hdrlen
) {
385 /* we can reuse the dl_unitdata_req M_PROTO mblk */
387 DB_TYPE(nmp
) = M_DATA
;
388 nmp
->b_rptr
= nmp
->b_wptr
= DB_LIM(nmp
);
390 /* we need to allocate one */
391 if ((nmp
= allocb(hdrlen
, BPRI_MED
)) == NULL
)
393 nmp
->b_rptr
= nmp
->b_wptr
= DB_LIM(nmp
);
394 linkb(nmp
, mp
->b_cont
);
398 /* Got the space, now copy in the header components */
400 nmp
->b_rptr
-= sizeof (typelen
);
401 SET_NET_USHORT(*(uint16_t *)nmp
->b_rptr
, typelen
);
402 if (hdrlen
> sizeof (struct ether_header
)) {
403 nmp
->b_rptr
-= sizeof (uint16_t);
404 SET_NET_USHORT(*(uint16_t *)nmp
->b_rptr
, vptag
);
406 nmp
->b_rptr
-= sizeof (uint16_t);
407 SET_NET_USHORT(*(uint16_t *)nmp
->b_rptr
, vptag
);
409 nmp
->b_rptr
-= (ETHERADDRL
* 2);
410 mh
= (struct ether_header
*)nmp
->b_rptr
;
411 mac_copy(dhost
, &mh
->ether_dhost
, macinfo
->gldm_addrlen
);
414 * We access the mac address without the mutex to prevent
415 * mutex contention (BUG 4211361)
417 mac_copy(((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->curr_macaddr
,
418 &mh
->ether_shost
, macinfo
->gldm_addrlen
);
424 * Insert the VLAN tag into the packet. The packet now is an Ethernet header
425 * without VLAN tag information.
428 gld_insert_vtag_ether(mblk_t
*mp
, uint32_t vtag
)
430 struct ether_vlan_header
*evhp
;
431 struct ether_header
*ehp
;
434 if (vtag
== VLAN_VID_NONE
)
437 if (DB_REF(mp
) == 1 && MBLKHEAD(mp
) >= VTAG_SIZE
) {
438 /* it fits at the beginning of the message block */
440 ovbcopy(nmp
->b_rptr
, nmp
->b_rptr
- VTAG_SIZE
, 2 * ETHERADDRL
);
441 nmp
->b_rptr
-= VTAG_SIZE
;
442 evhp
= (struct ether_vlan_header
*)nmp
->b_rptr
;
444 /* we need to allocate one */
445 if ((nmp
= allocb(sizeof (struct ether_vlan_header
),
446 BPRI_MED
)) == NULL
) {
449 nmp
->b_wptr
+= sizeof (struct ether_vlan_header
);
451 /* transfer the ether_header fields */
452 evhp
= (struct ether_vlan_header
*)nmp
->b_rptr
;
453 ehp
= (struct ether_header
*)mp
->b_rptr
;
454 mac_copy(&ehp
->ether_dhost
, &evhp
->ether_dhost
, ETHERADDRL
);
455 mac_copy(&ehp
->ether_shost
, &evhp
->ether_shost
, ETHERADDRL
);
456 bcopy(&ehp
->ether_type
, &evhp
->ether_type
, sizeof (uint16_t));
458 /* offset the mp of the MAC header length. */
459 mp
->b_rptr
+= sizeof (struct ether_header
);
460 if (MBLKL(mp
) == 0) {
461 nmp
->b_cont
= mp
->b_cont
;
468 SET_NET_USHORT(evhp
->ether_tci
, vtag
);
470 SET_NET_USHORT(evhp
->ether_tpid
, vtag
);
475 gld_fastpath_ether(gld_t
*gld
, mblk_t
*mp
)
477 gld_mac_info_t
*macinfo
= gld
->gld_mac_info
;
478 dl_unitdata_req_t
*dlp
= (dl_unitdata_req_t
*)mp
->b_cont
->b_rptr
;
479 struct gld_dlsap
*gldp
= DLSAP(dlp
, dlp
->dl_dest_addr_offset
);
480 unsigned short typelen
;
482 struct ether_header
*mh
;
485 gld_vlan_t
*gld_vlan
;
489 /* look in the unitdata request for a sap, else use bound one */
490 if (dlp
->dl_dest_addr_length
>= DLSAPLENGTH(macinfo
) &&
491 REF_HOST_USHORT(gldp
->glda_sap
) != 0)
492 typelen
= REF_HOST_USHORT(gldp
->glda_sap
);
494 typelen
= gld
->gld_sap
;
497 * We only do fast-path for EtherType encoding because this is the only
498 * case where the media header will be consistent from packet to packet.
500 if (typelen
<= ETHERMTU
)
504 * Initialize the fast path header to include the
505 * basic source address information and type field.
507 hdrlen
= sizeof (struct ether_header
);
510 * Check to see if VLAN is enabled on this stream
511 * if so then make the header bigger to hold a clone
514 gld_vlan
= (gld_vlan_t
*)gld
->gld_vlan
;
515 if (gld_vlan
&& (gld_vlan
->gldv_id
!= VLAN_VID_NONE
)) {
517 vptag
= gld_vlan
->gldv_ptag
;
520 if ((nmp
= allocb(hdrlen
, BPRI_MED
)) == NULL
)
523 nmp
->b_rptr
= nmp
->b_wptr
= DB_LIM(nmp
);
525 /* Got the space, now copy in the header components */
527 nmp
->b_rptr
-= sizeof (typelen
);
528 SET_NET_USHORT(*(uint16_t *)nmp
->b_rptr
, typelen
);
531 * If the header is for a VLAN stream, then add
532 * in the VLAN tag to the clone header.
534 if (hdrlen
> sizeof (struct ether_header
)) {
535 nmp
->b_rptr
-= sizeof (uint16_t);
536 SET_NET_USHORT(*(uint16_t *)nmp
->b_rptr
, vptag
);
538 nmp
->b_rptr
-= sizeof (uint16_t);
539 SET_NET_USHORT(*(uint16_t *)nmp
->b_rptr
, vptag
);
541 nmp
->b_rptr
-= (ETHERADDRL
* 2);
542 mh
= (struct ether_header
*)nmp
->b_rptr
;
543 mac_copy(gldp
->glda_addr
, &mh
->ether_dhost
, macinfo
->gldm_addrlen
);
545 GLDM_LOCK(macinfo
, RW_WRITER
);
546 mac_copy(((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->curr_macaddr
,
547 &mh
->ether_shost
, macinfo
->gldm_addrlen
);
548 GLDM_UNLOCK(macinfo
);
558 gld_init_ib(gld_mac_info_t
*macinfo
)
561 * Currently, the generic stats maintained by GLD is
562 * sufficient for IPoIB.
565 /* Assumptions we make for this medium */
566 ASSERT(macinfo
->gldm_type
== DL_IB
);
567 ASSERT(macinfo
->gldm_addrlen
== IPOIB_ADDRL
);
568 ASSERT(macinfo
->gldm_saplen
== -2);
573 gld_uninit_ib(gld_mac_info_t
*macinfo
)
578 * The packet format sent to the driver is:
579 * IPOIB_ADDRL bytes dest addr :: 2b sap :: 2b 0s :: data
580 * The packet format received from the driver is:
581 * IPOIB_GRH_SIZE bytes pseudo GRH :: 2b sap :: 2b 0s :: data.
584 gld_interpret_ib(gld_mac_info_t
*macinfo
, mblk_t
*mp
, pktinfo_t
*pktinfo
,
588 ipoib_ptxhdr_t
*gldp
;
590 gld_mac_pvt_t
*mac_pvt
= (gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
;
593 * Quickly handle receive fastpath for IPQ hack.
595 if (flags
== GLD_RXQUICK
) {
596 pktinfo
->pktLen
= msgdsize(mp
) - IPOIB_GRH_SIZE
;
599 * Check whether the header is contiguous, which
600 * also implicitly makes sure the packet is big enough.
602 if (MBLKL(mp
) < (IPOIB_GRH_SIZE
+ IPOIB_HDRSIZE
))
606 * Almost all times, unicast will not have
607 * a valid pgrh; quickly identify and ask for
608 * IPQ hack optimization only in that case.
610 grh
= (ipoib_pgrh_t
*)mp
->b_rptr
;
611 if (grh
->ipoib_vertcflow
== 0) {
612 struct ipoib_header
*ihp
= (struct ipoib_header
*)
613 (mp
->b_rptr
+ IPOIB_GRH_SIZE
);
615 pktinfo
->isForMe
= 1;
616 pktinfo
->ethertype
= REF_NET_USHORT(ihp
->ipoib_type
);
617 pktinfo
->macLen
= IPOIB_GRH_SIZE
+ IPOIB_HDRSIZE
;
625 * Handle the GLD_TX, GLD_RX, GLD_RXLOOP cases now.
627 ASSERT(flags
!= GLD_RXQUICK
);
628 bzero((void *)pktinfo
, sizeof (*pktinfo
));
630 if (flags
!= GLD_RX
) {
632 * GLD_TX and GLD_RXLOOP cases.
634 gldp
= (ipoib_ptxhdr_t
*)mp
->b_rptr
;
635 pktinfo
->pktLen
= msgdsize(mp
);
637 /* make sure packet has at least a pseudo header */
638 if (pktinfo
->pktLen
< sizeof (ipoib_ptxhdr_t
))
641 /* make sure the mac header falls into contiguous memory */
642 if (MBLKL(mp
) < sizeof (ipoib_ptxhdr_t
)) {
643 if ((pmp
= msgpullup(mp
, -1)) == NULL
) {
645 if (gld_debug
& GLDERRS
)
652 /* this mblk contains the whole mac header */
657 * Check if mac is broadcast or multicast address; all these
658 * types of address have the top 4 bytes as 0x00FFFFFF.
660 if (mac_eq(&gldp
->ipoib_dest
, macinfo
->gldm_broadcast_addr
,
661 sizeof (uint32_t))) {
662 if (mac_eq(&gldp
->ipoib_dest
,
663 macinfo
->gldm_broadcast_addr
, IPOIB_ADDRL
))
664 pktinfo
->isBroadcast
= 1;
666 pktinfo
->isMulticast
= 1;
670 * Only count bytes we will be sending over the wire
673 pktinfo
->pktLen
-= IPOIB_ADDRL
;
675 goto out
; /* Got all info we need for xmit case */
678 * Loopback case: this is a dup'ed message.
680 mp
->b_rptr
+= IPOIB_ADDRL
;
681 mac_copy(&gldp
->ipoib_dest
, pktinfo
->dhost
, IPOIB_ADDRL
);
682 mac_copy(mac_pvt
->curr_macaddr
, pktinfo
->shost
, IPOIB_ADDRL
);
685 * GLD_RX case; process packet sent from driver.
687 ipoib_mac_t
*mact
, *tact
;
690 pktinfo
->pktLen
= msgdsize(mp
);
691 /* make sure packet has at least pgrh and mac header */
692 if (pktinfo
->pktLen
< (IPOIB_GRH_SIZE
+ IPOIB_HDRSIZE
))
695 /* make sure the header falls into contiguous memory */
696 if (MBLKL(mp
) < (IPOIB_GRH_SIZE
+ IPOIB_HDRSIZE
)) {
697 if ((pmp
= msgpullup(mp
, -1)) == NULL
) {
699 if (gld_debug
& GLDERRS
)
702 "cannot msgpullup2");
706 /* this mblk contains the whole mac header */
710 grh
= (ipoib_pgrh_t
*)mp
->b_rptr
;
711 mp
->b_rptr
+= IPOIB_GRH_SIZE
;
712 pktinfo
->pktLen
-= IPOIB_GRH_SIZE
;
713 if (grh
->ipoib_vertcflow
) {
715 * First, copy source address from grh.
717 mact
= (ipoib_mac_t
*)pktinfo
->shost
;
718 mac_copy(&grh
->ipoib_sqpn
, &mact
->ipoib_qpn
,
722 * Then copy destination address from grh;
723 * first, the 16 bytes of GID.
725 mact
= (ipoib_mac_t
*)pktinfo
->dhost
;
726 mac_copy(&grh
->ipoib_dgid_pref
,
727 &mact
->ipoib_gidpref
, IPOIB_ADDRL
-
728 sizeof (mact
->ipoib_qpn
));
729 tact
= (ipoib_mac_t
*)mac_pvt
->curr_macaddr
;
731 /* Is this a multicast address */
732 if (*(uchar_t
*)(grh
->ipoib_dgid_pref
) == 0xFF) {
734 * Only check for hardware looping in
735 * multicast case. It is assumed higher
736 * layer code (IP) will stop unicast loops;
737 * ie will prevent a transmit to self.
739 if (bcmp(&grh
->ipoib_sqpn
, tact
,
741 pktinfo
->isLooped
= 1;
743 tact
= (ipoib_mac_t
*)macinfo
->
745 if (mac_eq(tact
->ipoib_gidpref
,
746 grh
->ipoib_dgid_pref
,
747 IPOIB_ADDRL
- sizeof (tact
->ipoib_qpn
)))
748 pktinfo
->isBroadcast
= 1;
750 pktinfo
->isMulticast
= 1;
752 * Now copy the 4 bytes QPN part of the
753 * destination address.
755 dqpn
= htonl(IB_MC_QPN
);
756 mac_copy(&dqpn
, &mact
->ipoib_qpn
,
757 sizeof (mact
->ipoib_qpn
));
760 * Now copy the 4 bytes QPN part of the
761 * destination address.
763 mac_copy(&tact
->ipoib_qpn
, &mact
->ipoib_qpn
,
764 sizeof (mact
->ipoib_qpn
));
766 * Any unicast packets received on IBA are
769 pktinfo
->isForMe
= 1;
773 * It can not be a IBA multicast packet.
774 * Must have been unicast to us. We do not
775 * have shost information, which is used in
776 * gld_addudind(); IP/ARP does not care.
778 pktinfo
->nosource
= 1;
779 mac_copy(mac_pvt
->curr_macaddr
, pktinfo
->dhost
,
782 * Any unicast packets received on IBA are
785 pktinfo
->isForMe
= 1;
789 ASSERT((flags
== GLD_RX
) || (flags
== GLD_RXLOOP
));
790 ASSERT(GLDM_LOCK_HELD(macinfo
));
791 pktinfo
->ethertype
= REF_NET_USHORT(((ipoib_hdr_t
*)
792 (mp
->b_rptr
))->ipoib_type
);
793 pktinfo
->macLen
= IPOIB_HDRSIZE
;
803 * The packet format sent to the driver is: 2b sap :: 2b 0s :: data
806 gld_interpret_mdt_ib(gld_mac_info_t
*macinfo
, mblk_t
*mp
, pdescinfo_t
*pinfo
,
807 pktinfo_t
*pktinfo
, mdt_packet_flag_t flags
)
809 gld_mac_pvt_t
*mac_pvt
;
811 pattrinfo_t attr_info
= { PATTR_DSTADDRSAP
, };
813 ipoib_ptxhdr_t
*dlap
= NULL
;
816 * Per packet formatting.
818 if (flags
== GLD_MDT_TXPKT
) {
822 if (PDESC_HDRL(pinfo
) == 0)
826 * Update packet's link header.
828 pinfo
->hdr_rptr
-= IPOIB_HDRSIZE
;
829 hptr
= (ipoib_hdr_t
*)pinfo
->hdr_rptr
;
830 hptr
->ipoib_mbz
= htons(0);
831 hptr
->ipoib_type
= pktinfo
->ethertype
;
834 * Total #bytes that will be put on wire.
836 pktinfo
->pktLen
= PDESC_HDRL(pinfo
);
837 for (seg
= 0; seg
< pinfo
->pld_cnt
; seg
++)
838 pktinfo
->pktLen
+= PDESC_PLDL(pinfo
, seg
);
844 * The following two cases of GLD_MDT_TX and GLD_MDT_RXLOOP are per
845 * MDT message processing.
847 dlmdp
= mmd_getmultidata(mp
);
848 patr
= mmd_getpattr(dlmdp
, NULL
, &attr_info
);
849 ASSERT(patr
!= NULL
);
850 ASSERT(macinfo
->gldm_saplen
== -2);
852 dlap
= (ipoib_ptxhdr_t
*)((pattr_addr_t
*)attr_info
.buf
)->addr
;
854 if (flags
== GLD_MDT_TX
) {
855 bzero((void *)pktinfo
, sizeof (*pktinfo
));
860 * Check if mac is broadcast or multicast address; all these
861 * types of address have the top 4 bytes as 0x00FFFFFF.
863 if (mac_eq(dlap
, macinfo
->gldm_broadcast_addr
,
864 sizeof (uint32_t))) {
865 if (mac_eq(dlap
, macinfo
->gldm_broadcast_addr
,
867 pktinfo
->isBroadcast
= 1;
869 pktinfo
->isMulticast
= 1;
871 pktinfo
->ethertype
= REF_NET_USHORT(dlap
->
872 ipoib_rhdr
.ipoib_type
);
874 ASSERT(flags
== GLD_MDT_RXLOOP
);
875 pktinfo
->macLen
= IPOIB_HDRSIZE
;
876 mac_pvt
= (gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
;
877 mac_copy(mac_pvt
->curr_macaddr
, pktinfo
->shost
, IPOIB_ADDRL
);
880 mac_copy(&dlap
->ipoib_dest
, pktinfo
->dhost
, IPOIB_ADDRL
);
885 gld_unitdata_ib(gld_t
*gld
, mblk_t
*mp
)
887 gld_mac_info_t
*macinfo
= gld
->gld_mac_info
;
888 dl_unitdata_req_t
*dlp
= (dl_unitdata_req_t
*)mp
->b_rptr
;
889 ipoib_ptxhdr_t
*gldp
= IPOIBDLSAP(dlp
, dlp
->dl_dest_addr_offset
);
895 ASSERT(macinfo
!= NULL
);
897 /* extract needed info from the mblk before we maybe reuse it */
898 mac_copy(&gldp
->ipoib_dest
, &dhost
, IPOIB_ADDRL
);
900 /* look in the unitdata request for a sap, else use bound one */
901 if (dlp
->dl_dest_addr_length
>= DLSAPLENGTH(macinfo
) &&
902 REF_HOST_USHORT(gldp
->ipoib_rhdr
.ipoib_type
) != 0)
903 type
= REF_HOST_USHORT(gldp
->ipoib_rhdr
.ipoib_type
);
907 hdrlen
= sizeof (ipoib_ptxhdr_t
);
909 /* need a buffer big enough for the headers */
910 nmp
= mp
->b_cont
; /* where the packet payload M_DATA is */
911 if (DB_REF(nmp
) == 1 && MBLKHEAD(nmp
) >= hdrlen
) {
912 /* it fits at the beginning of the first M_DATA block */
913 freeb(mp
); /* don't need the M_PROTO anymore */
914 } else if (DB_REF(mp
) == 1 && MBLKSIZE(mp
) >= hdrlen
) {
915 /* we can reuse the dl_unitdata_req M_PROTO mblk */
917 DB_TYPE(nmp
) = M_DATA
;
918 nmp
->b_rptr
= nmp
->b_wptr
= DB_LIM(nmp
);
920 /* we need to allocate one */
921 if ((nmp
= allocb(hdrlen
, BPRI_MED
)) == NULL
)
923 nmp
->b_rptr
= nmp
->b_wptr
= DB_LIM(nmp
);
924 linkb(nmp
, mp
->b_cont
);
928 /* Got the space, now copy in the header components */
930 nmp
->b_rptr
-= sizeof (ipoib_ptxhdr_t
);
931 gldp
= (ipoib_ptxhdr_t
*)nmp
->b_rptr
;
932 SET_NET_USHORT(gldp
->ipoib_rhdr
.ipoib_type
, type
);
933 gldp
->ipoib_rhdr
.ipoib_mbz
= 0;
934 mac_copy(&dhost
, &gldp
->ipoib_dest
, IPOIB_ADDRL
);
940 gld_fastpath_ib(gld_t
*gld
, mblk_t
*mp
)
942 gld_mac_info_t
*macinfo
= gld
->gld_mac_info
;
943 dl_unitdata_req_t
*dlp
= (dl_unitdata_req_t
*)mp
->b_cont
->b_rptr
;
944 ipoib_ptxhdr_t
*gldp
= IPOIBDLSAP(dlp
, dlp
->dl_dest_addr_offset
);
947 ipoib_ptxhdr_t
*tgldp
;
950 ASSERT(macinfo
!= NULL
);
952 /* look in the unitdata request for a sap, else use bound one */
953 if (dlp
->dl_dest_addr_length
>= DLSAPLENGTH(macinfo
) &&
954 REF_HOST_USHORT(gldp
->ipoib_rhdr
.ipoib_type
) != 0)
955 type
= REF_HOST_USHORT(gldp
->ipoib_rhdr
.ipoib_type
);
959 hdrlen
= sizeof (ipoib_ptxhdr_t
);
961 if ((nmp
= allocb(hdrlen
, BPRI_MED
)) == NULL
)
964 nmp
->b_rptr
= nmp
->b_wptr
= DB_LIM(nmp
);
966 /* Got the space, now copy in the header components */
968 nmp
->b_rptr
-= sizeof (ipoib_ptxhdr_t
);
969 tgldp
= (ipoib_ptxhdr_t
*)nmp
->b_rptr
;
970 tgldp
->ipoib_rhdr
.ipoib_type
= htons(type
);
971 tgldp
->ipoib_rhdr
.ipoib_mbz
= 0;
972 mac_copy(&gldp
->ipoib_dest
, &tgldp
->ipoib_dest
, IPOIB_ADDRL
);
982 gld_init_fddi(gld_mac_info_t
*macinfo
)
984 struct gldkstats
*sp
=
985 ((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->kstatp
->ks_data
;
987 /* Assumptions we make for this medium */
988 ASSERT(macinfo
->gldm_type
== DL_FDDI
);
989 ASSERT(macinfo
->gldm_addrlen
== 6);
990 ASSERT(macinfo
->gldm_saplen
== -2);
991 ASSERT(sizeof (struct fddi_mac_frm
) == 13);
992 ASSERT(sizeof (mac_addr_t
) == 6);
994 /* Wire address format is bit reversed from canonical format */
995 macinfo
->gldm_options
|= GLDOPT_CANONICAL_ADDR
;
997 kstat_named_init(&sp
->glds_fddi_mac_error
,
998 "mac_errors", KSTAT_DATA_UINT32
);
999 kstat_named_init(&sp
->glds_fddi_mac_lost
,
1000 "mac_lost_errors", KSTAT_DATA_UINT32
);
1001 kstat_named_init(&sp
->glds_fddi_mac_token
,
1002 "mac_tokens", KSTAT_DATA_UINT32
);
1003 kstat_named_init(&sp
->glds_fddi_mac_tvx_expired
,
1004 "mac_tvx_expired", KSTAT_DATA_UINT32
);
1005 kstat_named_init(&sp
->glds_fddi_mac_late
,
1006 "mac_late", KSTAT_DATA_UINT32
);
1007 kstat_named_init(&sp
->glds_fddi_mac_ring_op
,
1008 "mac_ring_ops", KSTAT_DATA_UINT32
);
1013 gld_uninit_fddi(gld_mac_info_t
*macinfo
)
1018 gld_interpret_fddi(gld_mac_info_t
*macinfo
, mblk_t
*mp
, pktinfo_t
*pktinfo
,
1019 packet_flag_t flags
)
1021 struct fddi_mac_frm
*mh
;
1022 gld_mac_pvt_t
*mac_pvt
;
1023 struct llc_snap_hdr
*snaphdr
;
1027 * Quickly handle receive fastpath; FDDI does not support IPQ hack.
1029 if (flags
== GLD_RXQUICK
) {
1030 pktinfo
->pktLen
= msgdsize(mp
);
1034 bzero((void *)pktinfo
, sizeof (*pktinfo
));
1036 pktinfo
->pktLen
= msgdsize(mp
);
1038 /* make sure packet has at least a whole mac header */
1039 if (pktinfo
->pktLen
< sizeof (struct fddi_mac_frm
))
1042 /* make sure the mac header falls into contiguous memory */
1043 if (MBLKL(mp
) < sizeof (struct fddi_mac_frm
)) {
1044 if ((pmp
= msgpullup(mp
, -1)) == NULL
) {
1046 if (gld_debug
& GLDERRS
)
1048 "GLD: interpret_fddi cannot msgpullup");
1052 mp
= pmp
; /* this mblk contains the whole mac header */
1055 mh
= (struct fddi_mac_frm
*)mp
->b_rptr
;
1057 /* Check to see if the mac is a broadcast or multicast address. */
1058 /* NB we are still in wire format (non canonical) */
1059 /* mac_eq works because ether_broadcast is the same either way */
1060 if (mac_eq(mh
->fddi_dhost
, ether_broadcast
, macinfo
->gldm_addrlen
))
1061 pktinfo
->isBroadcast
= 1;
1062 else if (mh
->fddi_dhost
[0] & 0x80)
1063 pktinfo
->isMulticast
= 1;
1065 if (flags
== GLD_TX
)
1066 goto out
; /* Got all info we need for xmit case */
1068 ASSERT(GLDM_LOCK_HELD(macinfo
));
1071 * Deal with the mac header
1074 cmac_copy(mh
->fddi_dhost
, pktinfo
->dhost
,
1075 macinfo
->gldm_addrlen
, macinfo
);
1076 cmac_copy(mh
->fddi_shost
, pktinfo
->shost
,
1077 macinfo
->gldm_addrlen
, macinfo
);
1079 mac_pvt
= (gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
;
1080 pktinfo
->isLooped
= mac_eq(pktinfo
->shost
,
1081 mac_pvt
->curr_macaddr
, macinfo
->gldm_addrlen
);
1082 pktinfo
->isForMe
= mac_eq(pktinfo
->dhost
,
1083 mac_pvt
->curr_macaddr
, macinfo
->gldm_addrlen
);
1085 pktinfo
->macLen
= sizeof (struct fddi_mac_frm
);
1088 * Before trying to look beyond the MAC header, make sure the LLC
1089 * header exists, and that both it and any SNAP header are contiguous.
1091 if (MBLKL(mp
) < sizeof (struct fddi_mac_frm
) + LLC_SNAP_HDR_LEN
&&
1092 MBLKL(mp
) < pktinfo
->pktLen
) {
1094 * we don't have the entire packet within the first mblk (and
1095 * therefore we didn't do the msgpullup above), AND the first
1096 * mblk may not contain all the data we need to look at.
1098 ASSERT(pmp
== NULL
); /* couldn't have done msgpullup above */
1099 if ((pmp
= msgpullup(mp
, -1)) == NULL
) {
1101 if (gld_debug
& GLDERRS
)
1103 "GLD: interpret_fddi cannot msgpullup2");
1105 goto out
; /* can't interpret this pkt further */
1107 mp
= pmp
; /* this mblk should contain everything needed */
1111 * Check SAP/SNAP information.
1113 if ((mh
->fddi_fc
& 0x70) == 0x50) {
1114 if (pktinfo
->pktLen
< pktinfo
->macLen
+ LLC_HDR1_LEN
)
1119 if (pktinfo
->pktLen
< pktinfo
->macLen
+ LLC_SNAP_HDR_LEN
)
1122 snaphdr
= (struct llc_snap_hdr
*)(mp
->b_rptr
+ pktinfo
->macLen
);
1123 if (ISETHERTYPE(snaphdr
)) {
1124 pktinfo
->ethertype
= REF_NET_USHORT(snaphdr
->type
);
1125 pktinfo
->hdrLen
= LLC_SNAP_HDR_LEN
;
1136 gld_unitdata_fddi(gld_t
*gld
, mblk_t
*mp
)
1138 gld_mac_info_t
*macinfo
= gld
->gld_mac_info
;
1139 dl_unitdata_req_t
*dlp
= (dl_unitdata_req_t
*)mp
->b_rptr
;
1140 struct gld_dlsap
*gldp
= DLSAP(dlp
, dlp
->dl_dest_addr_offset
);
1142 unsigned short type
;
1144 struct fddi_mac_frm
*mh
;
1149 /* extract needed info from the mblk before we maybe reuse it */
1150 mac_copy(gldp
->glda_addr
, dhost
, macinfo
->gldm_addrlen
);
1152 /* look in the unitdata request for a sap, else use bound one */
1153 if (dlp
->dl_dest_addr_length
>= DLSAPLENGTH(macinfo
) &&
1154 REF_HOST_USHORT(gldp
->glda_sap
) != 0)
1155 type
= REF_HOST_USHORT(gldp
->glda_sap
);
1157 type
= gld
->gld_sap
;
1160 hdrlen
= sizeof (struct fddi_mac_frm
);
1163 * Check whether we need to do EtherType encoding or whether the packet
1166 if (type
> GLD_MAX_802_SAP
)
1167 hdrlen
+= sizeof (struct llc_snap_hdr
);
1169 /* need a buffer big enough for the headers */
1170 nmp
= mp
->b_cont
; /* where the packet payload M_DATA is */
1171 if (DB_REF(nmp
) == 1 && MBLKHEAD(nmp
) >= hdrlen
) {
1172 /* it fits at the beginning of the first M_DATA block */
1173 freeb(mp
); /* don't need the M_PROTO anymore */
1174 } else if (DB_REF(mp
) == 1 && MBLKSIZE(mp
) >= hdrlen
) {
1175 /* we can reuse the dl_unitdata_req M_PROTO mblk */
1177 DB_TYPE(nmp
) = M_DATA
;
1178 nmp
->b_rptr
= nmp
->b_wptr
= DB_LIM(nmp
);
1180 /* we need to allocate one */
1181 if ((nmp
= allocb(hdrlen
, BPRI_MED
)) == NULL
)
1183 nmp
->b_rptr
= nmp
->b_wptr
= DB_LIM(nmp
);
1184 linkb(nmp
, mp
->b_cont
);
1189 /* Got the space, now copy in the header components */
1190 if (type
> GLD_MAX_802_SAP
) {
1191 /* create the snap header */
1192 struct llc_snap_hdr
*snap
;
1193 nmp
->b_rptr
-= sizeof (struct llc_snap_hdr
);
1194 snap
= (struct llc_snap_hdr
*)(nmp
->b_rptr
);
1195 *snap
= llc_snap_def
;
1196 SET_NET_USHORT(snap
->type
, type
);
1199 nmp
->b_rptr
-= sizeof (struct fddi_mac_frm
);
1201 mh
= (struct fddi_mac_frm
*)nmp
->b_rptr
;
1204 cmac_copy(dhost
, mh
->fddi_dhost
, macinfo
->gldm_addrlen
, macinfo
);
1207 * We access the mac address without the mutex to prevent
1208 * mutex contention (BUG 4211361)
1210 cmac_copy(((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->curr_macaddr
,
1211 mh
->fddi_shost
, macinfo
->gldm_addrlen
, macinfo
);
1216 gld_fastpath_fddi(gld_t
*gld
, mblk_t
*mp
)
1218 gld_mac_info_t
*macinfo
= gld
->gld_mac_info
;
1219 dl_unitdata_req_t
*dlp
= (dl_unitdata_req_t
*)mp
->b_cont
->b_rptr
;
1220 struct gld_dlsap
*gldp
= DLSAP(dlp
, dlp
->dl_dest_addr_offset
);
1221 unsigned short type
;
1223 struct fddi_mac_frm
*mh
;
1228 /* look in the unitdata request for a sap, else use bound one */
1229 if (dlp
->dl_dest_addr_length
>= DLSAPLENGTH(macinfo
) &&
1230 REF_HOST_USHORT(gldp
->glda_sap
) != 0)
1231 type
= REF_HOST_USHORT(gldp
->glda_sap
);
1233 type
= gld
->gld_sap
;
1235 hdrlen
= sizeof (struct fddi_mac_frm
);
1238 * Check whether we need to do EtherType encoding or whether the packet
1241 if (type
> GLD_MAX_802_SAP
)
1242 hdrlen
+= sizeof (struct llc_snap_hdr
);
1244 if ((nmp
= allocb(hdrlen
, BPRI_MED
)) == NULL
)
1247 nmp
->b_rptr
= nmp
->b_wptr
= DB_LIM(nmp
);
1249 /* Got the space, now copy in the header components */
1251 if (type
> GLD_MAX_802_SAP
) {
1252 /* create the snap header */
1253 struct llc_snap_hdr
*snap
;
1254 nmp
->b_rptr
-= sizeof (struct llc_snap_hdr
);
1255 snap
= (struct llc_snap_hdr
*)(nmp
->b_rptr
);
1256 *snap
= llc_snap_def
;
1257 snap
->type
= htons(type
); /* we know it's aligned */
1260 nmp
->b_rptr
-= sizeof (struct fddi_mac_frm
);
1262 mh
= (struct fddi_mac_frm
*)nmp
->b_rptr
;
1264 cmac_copy(gldp
->glda_addr
, mh
->fddi_dhost
,
1265 macinfo
->gldm_addrlen
, macinfo
);
1267 GLDM_LOCK(macinfo
, RW_WRITER
);
1268 cmac_copy(((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->curr_macaddr
,
1269 mh
->fddi_shost
, macinfo
->gldm_addrlen
, macinfo
);
1270 GLDM_UNLOCK(macinfo
);
1279 #define GLD_SR_VAR(macinfo) \
1280 (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->data)
1282 #define GLD_SR_HASH(macinfo) ((struct srtab **)GLD_SR_VAR(macinfo))
1284 #define GLD_SR_MUTEX(macinfo) \
1285 (&((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->datalock)
1287 static void gld_sr_clear(gld_mac_info_t
*);
1288 static void gld_rcc_receive(gld_mac_info_t
*, pktinfo_t
*, struct gld_ri
*,
1290 static void gld_rcc_send(gld_mac_info_t
*, queue_t
*, uchar_t
*,
1291 struct gld_ri
**, uchar_t
*);
1293 static mac_addr_t tokenbroadcastaddr2
= { 0xc0, 0x00, 0xff, 0xff, 0xff, 0xff };
1294 static struct gld_ri ri_ste_def
;
1297 gld_init_tr(gld_mac_info_t
*macinfo
)
1299 struct gldkstats
*sp
=
1300 ((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->kstatp
->ks_data
;
1302 /* avoid endian-dependent code by initializing here instead of static */
1304 ri_ste_def
.rt
= RT_STE
;
1305 ri_ste_def
.mtu
= RT_MTU_MAX
;
1309 /* Assumptions we make for this medium */
1310 ASSERT(macinfo
->gldm_type
== DL_TPR
);
1311 ASSERT(macinfo
->gldm_addrlen
== 6);
1312 ASSERT(macinfo
->gldm_saplen
== -2);
1313 ASSERT(sizeof (struct tr_mac_frm_nori
) == 14);
1314 ASSERT(sizeof (mac_addr_t
) == 6);
1316 mutex_init(GLD_SR_MUTEX(macinfo
), NULL
, MUTEX_DRIVER
, NULL
);
1318 GLD_SR_VAR(macinfo
) = kmem_zalloc(sizeof (struct srtab
*)*SR_HASH_SIZE
,
1321 /* Default is RDE enabled for this medium */
1322 ((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->rde_enabled
=
1323 ddi_getprop(DDI_DEV_T_NONE
, macinfo
->gldm_devinfo
, 0,
1324 "gld_rde_enable", 1);
1327 * Default is to use STE for unknown paths if RDE is enabled.
1328 * If RDE is disabled, default is to use NULL RIF fields.
1330 * It's possible to force use of STE for ALL packets:
1331 * disable RDE but enable STE. This may be useful for
1332 * non-transparent bridges, when it is not desired to run
1333 * the RDE algorithms.
1335 ((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->rde_str_indicator_ste
=
1336 ddi_getprop(DDI_DEV_T_NONE
, macinfo
->gldm_devinfo
, 0,
1337 "gld_rde_str_indicator_ste",
1338 ((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->rde_enabled
);
1340 /* Default 10 second route timeout on lack of activity */
1342 int t
= ddi_getprop(DDI_DEV_T_NONE
, macinfo
->gldm_devinfo
, 0,
1343 "gld_rde_timeout", 10);
1345 t
= 1; /* Let's be reasonable */
1347 t
= 600; /* Let's be reasonable */
1348 /* We're using ticks (lbolts) for our timeout -- convert from seconds */
1349 t
= drv_usectohz(1000000 * t
);
1350 ((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->rde_timeout
= t
;
1353 kstat_named_init(&sp
->glds_dot5_line_error
,
1354 "line_errors", KSTAT_DATA_UINT32
);
1355 kstat_named_init(&sp
->glds_dot5_burst_error
,
1356 "burst_errors", KSTAT_DATA_UINT32
);
1357 kstat_named_init(&sp
->glds_dot5_signal_loss
,
1358 "signal_losses", KSTAT_DATA_UINT32
);
1361 * only initialize the new statistics if the driver
1364 if (macinfo
->gldm_driver_version
!= GLD_VERSION_200
)
1367 kstat_named_init(&sp
->glds_dot5_ace_error
,
1368 "ace_errors", KSTAT_DATA_UINT32
);
1369 kstat_named_init(&sp
->glds_dot5_internal_error
,
1370 "internal_errors", KSTAT_DATA_UINT32
);
1371 kstat_named_init(&sp
->glds_dot5_lost_frame_error
,
1372 "lost_frame_errors", KSTAT_DATA_UINT32
);
1373 kstat_named_init(&sp
->glds_dot5_frame_copied_error
,
1374 "frame_copied_errors", KSTAT_DATA_UINT32
);
1375 kstat_named_init(&sp
->glds_dot5_token_error
,
1376 "token_errors", KSTAT_DATA_UINT32
);
1377 kstat_named_init(&sp
->glds_dot5_freq_error
,
1378 "freq_errors", KSTAT_DATA_UINT32
);
1382 gld_uninit_tr(gld_mac_info_t
*macinfo
)
1384 mutex_destroy(GLD_SR_MUTEX(macinfo
));
1385 gld_sr_clear(macinfo
);
1386 kmem_free(GLD_SR_VAR(macinfo
), sizeof (struct srtab
*) * SR_HASH_SIZE
);
1390 gld_interpret_tr(gld_mac_info_t
*macinfo
, mblk_t
*mp
, pktinfo_t
*pktinfo
,
1391 packet_flag_t flags
)
1393 struct tr_mac_frm
*mh
;
1394 gld_mac_pvt_t
*mac_pvt
;
1395 struct llc_snap_hdr
*snaphdr
;
1400 * Quickly handle receive fastpath; TR does not support IPQ hack.
1402 if (flags
== GLD_RXQUICK
) {
1403 pktinfo
->pktLen
= msgdsize(mp
);
1407 bzero((void *)pktinfo
, sizeof (*pktinfo
));
1409 pktinfo
->pktLen
= msgdsize(mp
);
1411 /* make sure packet has at least a whole mac header */
1412 if (pktinfo
->pktLen
< sizeof (struct tr_mac_frm_nori
))
1415 /* make sure the mac header falls into contiguous memory */
1416 if (MBLKL(mp
) < sizeof (struct tr_mac_frm_nori
)) {
1417 if ((pmp
= msgpullup(mp
, -1)) == NULL
) {
1419 if (gld_debug
& GLDERRS
)
1421 "GLD: interpret_tr cannot msgpullup");
1425 mp
= pmp
; /* this mblk contains the whole mac header */
1428 mh
= (struct tr_mac_frm
*)mp
->b_rptr
;
1430 /* Check to see if the mac is a broadcast or multicast address. */
1431 if (mac_eq(mh
->tr_dhost
, ether_broadcast
, macinfo
->gldm_addrlen
) ||
1432 mac_eq(mh
->tr_dhost
, tokenbroadcastaddr2
, macinfo
->gldm_addrlen
))
1433 pktinfo
->isBroadcast
= 1;
1434 else if (mh
->tr_dhost
[0] & 0x80)
1435 pktinfo
->isMulticast
= 1;
1437 if (flags
== GLD_TX
)
1438 goto out
; /* Got all info we need for xmit case */
1440 ASSERT(GLDM_LOCK_HELD(macinfo
));
1443 * Deal with the mac header
1446 mac_copy(mh
->tr_dhost
, pktinfo
->dhost
, macinfo
->gldm_addrlen
);
1447 mac_copy(mh
->tr_shost
, pktinfo
->shost
, macinfo
->gldm_addrlen
);
1448 pktinfo
->shost
[0] &= ~0x80; /* turn off RIF indicator */
1450 mac_pvt
= (gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
;
1451 pktinfo
->isLooped
= mac_eq(pktinfo
->shost
,
1452 mac_pvt
->curr_macaddr
, macinfo
->gldm_addrlen
);
1453 pktinfo
->isForMe
= mac_eq(pktinfo
->dhost
,
1454 mac_pvt
->curr_macaddr
, macinfo
->gldm_addrlen
);
1457 pktinfo
->macLen
= sizeof (struct tr_mac_frm_nori
);
1460 * Before trying to look beyond the MAC header, make sure the data
1461 * structures are all contiguously where we can conveniently look at
1462 * them. We'll use a worst-case estimate of how many bytes into the
1463 * packet data we'll be needing to look. Things will be more efficient
1464 * if the driver puts at least this much into the first mblk.
1466 * Even after this, we still will have to do checks against the total
1467 * length of the packet. A bad incoming packet may not hold all the
1468 * data structures it says it does.
1470 if (MBLKL(mp
) < sizeof (struct tr_mac_frm
) +
1471 LLC_HDR1_LEN
+ sizeof (struct rde_pdu
) &&
1472 MBLKL(mp
) < pktinfo
->pktLen
) {
1474 * we don't have the entire packet within the first mblk (and
1475 * therefore we didn't do the msgpullup above), AND the first
1476 * mblk may not contain all the data we need to look at.
1478 ASSERT(pmp
== NULL
); /* couldn't have done msgpullup above */
1479 if ((pmp
= msgpullup(mp
, -1)) == NULL
) {
1481 if (gld_debug
& GLDERRS
)
1483 "GLD: interpret_tr cannot msgpullup2");
1485 goto out
; /* can't interpret this pkt further */
1487 mp
= pmp
; /* this mblk should contain everything needed */
1488 mh
= (struct tr_mac_frm
*)mp
->b_rptr
; /* to look at RIF */
1491 if (mh
->tr_shost
[0] & 0x80) {
1492 /* Routing Information Field (RIF) is present */
1493 if (pktinfo
->pktLen
< sizeof (struct tr_mac_frm_nori
) + 2)
1494 goto out
; /* RIF should have been there! */
1495 rh
= (struct gld_ri
*)&mh
->tr_ri
;
1496 if ((rh
->len
& 1) || rh
->len
< 2) {
1497 /* Bogus RIF, don't handle this packet */
1499 if (gld_debug
& GLDERRS
)
1501 "GLD: received TR packet with "
1502 "bogus RIF length %d",
1507 if (pktinfo
->pktLen
< sizeof (struct tr_mac_frm_nori
) + rh
->len
)
1508 goto out
; /* RIF should have been there! */
1509 pktinfo
->macLen
+= rh
->len
;
1512 if ((mh
->tr_fc
& 0xc0) == 0x40) {
1513 if (pktinfo
->pktLen
< pktinfo
->macLen
+ LLC_HDR1_LEN
)
1518 if (pktinfo
->pktLen
< pktinfo
->macLen
+ LLC_SNAP_HDR_LEN
)
1521 snaphdr
= (struct llc_snap_hdr
*)(mp
->b_rptr
+ pktinfo
->macLen
);
1522 if (ISETHERTYPE(snaphdr
)) {
1523 pktinfo
->ethertype
= REF_NET_USHORT(snaphdr
->type
);
1524 pktinfo
->hdrLen
= LLC_SNAP_HDR_LEN
;
1527 /* Inform the Route Control Component of received LLC frame */
1528 gld_rcc_receive(macinfo
, pktinfo
, rh
,
1529 mp
->b_rptr
+ pktinfo
->macLen
,
1530 pktinfo
->pktLen
- pktinfo
->macLen
);
1540 gld_unitdata_tr(gld_t
*gld
, mblk_t
*mp
)
1542 gld_mac_info_t
*macinfo
= gld
->gld_mac_info
;
1543 dl_unitdata_req_t
*dlp
= (dl_unitdata_req_t
*)mp
->b_rptr
;
1544 struct gld_dlsap
*gldp
= DLSAP(dlp
, dlp
->dl_dest_addr_offset
);
1546 unsigned short type
;
1547 mblk_t
*nmp
, *llcmp
, *pmp
= NULL
;
1548 struct tr_mac_frm_nori
*mh
;
1554 /* extract needed info from the mblk before we maybe reuse it */
1555 mac_copy(gldp
->glda_addr
, dhost
, macinfo
->gldm_addrlen
);
1557 /* look in the unitdata request for a sap, else use bound one */
1558 if (dlp
->dl_dest_addr_length
>= DLSAPLENGTH(macinfo
) &&
1559 REF_HOST_USHORT(gldp
->glda_sap
) != 0)
1560 type
= REF_HOST_USHORT(gldp
->glda_sap
);
1562 type
= gld
->gld_sap
;
1564 /* includes maximum possible Routing Information Field (RIF) size */
1565 hdrlen
= sizeof (struct tr_mac_frm
);
1568 * Check whether we need to do EtherType encoding or whether the packet
1571 if (type
> GLD_MAX_802_SAP
)
1572 hdrlen
+= sizeof (struct llc_snap_hdr
);
1574 /* need a buffer big enough for the headers */
1575 llcmp
= nmp
= mp
->b_cont
; /* where the packet payload M_DATA is */
1578 * We are going to need to look at the LLC header, so make sure it
1579 * is contiguously in a single mblk. If we're the ones who create
1580 * the LLC header (below, in the case where sap > 0xff) then we don't
1581 * have to worry about it here.
1583 ASSERT(nmp
!= NULL
); /* gld_unitdata guarantees msgdsize > 0 */
1584 if (type
<= GLD_MAX_802_SAP
) {
1585 if (MBLKL(llcmp
) < LLC_HDR1_LEN
) {
1586 llcmp
= pmp
= msgpullup(nmp
, LLC_HDR1_LEN
);
1589 if (gld_debug
& GLDERRS
)
1592 "cannot msgpullup");
1599 if (DB_REF(nmp
) == 1 && MBLKHEAD(nmp
) >= hdrlen
) {
1600 /* it fits at the beginning of the first M_DATA block */
1601 freeb(mp
); /* don't need the M_PROTO anymore */
1602 } else if (DB_REF(mp
) == 1 && MBLKSIZE(mp
) >= hdrlen
) {
1603 /* we can reuse the dl_unitdata_req M_PROTO mblk */
1605 DB_TYPE(nmp
) = M_DATA
;
1606 nmp
->b_rptr
= nmp
->b_wptr
= DB_LIM(nmp
);
1608 /* we need to allocate one */
1609 if ((nmp
= allocb(hdrlen
, BPRI_MED
)) == NULL
) {
1614 nmp
->b_rptr
= nmp
->b_wptr
= DB_LIM(nmp
);
1615 linkb(nmp
, mp
->b_cont
);
1619 /* Got the space, now copy in the header components */
1620 if (type
> GLD_MAX_802_SAP
) {
1621 /* create the snap header */
1622 struct llc_snap_hdr
*snap
;
1623 llcmp
= nmp
; /* LLC header is going to be in this mblk */
1624 nmp
->b_rptr
-= sizeof (struct llc_snap_hdr
);
1625 snap
= (struct llc_snap_hdr
*)(nmp
->b_rptr
);
1626 *snap
= llc_snap_def
;
1627 SET_NET_USHORT(snap
->type
, type
);
1630 /* Hold SR tables still while we maybe point at an entry */
1631 mutex_enter(GLD_SR_MUTEX(macinfo
));
1633 gld_rcc_send(macinfo
, WR(gld
->gld_qptr
), dhost
, &rh
, llcmp
->b_rptr
);
1636 /* copy in the RIF */
1637 ASSERT(rh
->len
<= sizeof (struct gld_ri
));
1638 nmp
->b_rptr
-= rh
->len
;
1639 bcopy((caddr_t
)rh
, (caddr_t
)nmp
->b_rptr
, rh
->len
);
1642 mutex_exit(GLD_SR_MUTEX(macinfo
));
1644 /* no longer need the pulled-up mblk */
1649 * fill in token ring header
1651 nmp
->b_rptr
-= sizeof (struct tr_mac_frm_nori
);
1652 mh
= (struct tr_mac_frm_nori
*)nmp
->b_rptr
;
1655 mac_copy(dhost
, mh
->tr_dhost
, macinfo
->gldm_addrlen
);
1658 * We access the mac address without the mutex to prevent
1659 * mutex contention (BUG 4211361)
1661 mac_copy(((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->curr_macaddr
,
1662 mh
->tr_shost
, macinfo
->gldm_addrlen
);
1665 mh
->tr_shost
[0] |= 0x80;
1667 mh
->tr_shost
[0] &= ~0x80;
1673 * We cannot have our client sending us "fastpath" M_DATA messages,
1674 * because to do that we must provide a fixed MAC header to
1675 * be prepended to each outgoing packet. But with Source Routing
1676 * media, the length and content of the MAC header changes as the
1677 * routes change, so there is no fixed header we can provide. So
1678 * we decline to accept M_DATA messages if Source Routing is enabled.
1681 gld_fastpath_tr(gld_t
*gld
, mblk_t
*mp
)
1683 gld_mac_info_t
*macinfo
= gld
->gld_mac_info
;
1684 dl_unitdata_req_t
*dlp
= (dl_unitdata_req_t
*)mp
->b_cont
->b_rptr
;
1685 struct gld_dlsap
*gldp
= DLSAP(dlp
, dlp
->dl_dest_addr_offset
);
1686 unsigned short type
;
1688 struct tr_mac_frm_nori
*mh
;
1694 * If we are doing Source Routing, then we cannot provide a fixed
1695 * MAC header, so fail.
1697 if (((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->rde_enabled
)
1700 /* look in the unitdata request for a sap, else use bound one */
1701 if (dlp
->dl_dest_addr_length
>= DLSAPLENGTH(macinfo
) &&
1702 REF_HOST_USHORT(gldp
->glda_sap
) != 0)
1703 type
= REF_HOST_USHORT(gldp
->glda_sap
);
1705 type
= gld
->gld_sap
;
1707 hdrlen
= sizeof (struct tr_mac_frm_nori
);
1709 if (((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->rde_str_indicator_ste
)
1710 hdrlen
+= ri_ste_def
.len
;
1713 * Check whether we need to do EtherType encoding or whether the packet
1716 if (type
> GLD_MAX_802_SAP
)
1717 hdrlen
+= sizeof (struct llc_snap_hdr
);
1719 if ((nmp
= allocb(hdrlen
, BPRI_MED
)) == NULL
)
1722 nmp
->b_rptr
= nmp
->b_wptr
= DB_LIM(nmp
);
1724 /* Got the space, now copy in the header components */
1726 if (type
> GLD_MAX_802_SAP
) {
1727 /* create the snap header */
1728 struct llc_snap_hdr
*snap
;
1729 nmp
->b_rptr
-= sizeof (struct llc_snap_hdr
);
1730 snap
= (struct llc_snap_hdr
*)(nmp
->b_rptr
);
1731 *snap
= llc_snap_def
;
1732 snap
->type
= htons(type
); /* we know it's aligned */
1735 /* RDE is disabled, use NULL RIF, or STE RIF */
1736 if (((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->rde_str_indicator_ste
) {
1737 nmp
->b_rptr
-= ri_ste_def
.len
;
1738 bcopy((caddr_t
)&ri_ste_def
, (caddr_t
)nmp
->b_rptr
,
1743 * fill in token ring header
1745 nmp
->b_rptr
-= sizeof (struct tr_mac_frm_nori
);
1746 mh
= (struct tr_mac_frm_nori
*)nmp
->b_rptr
;
1749 mac_copy(gldp
->glda_addr
, mh
->tr_dhost
, macinfo
->gldm_addrlen
);
1751 GLDM_LOCK(macinfo
, RW_WRITER
);
1752 mac_copy(((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->curr_macaddr
,
1753 mh
->tr_shost
, macinfo
->gldm_addrlen
);
1754 GLDM_UNLOCK(macinfo
);
1756 if (((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->rde_str_indicator_ste
)
1757 mh
->tr_shost
[0] |= 0x80;
1759 mh
->tr_shost
[0] &= ~0x80;
1765 * Route Determination Entity (ISO 8802-2 / IEEE 802.2 : 1994, Section 9)
1767 * RDE is an LLC layer entity. GLD is a MAC layer entity. The proper
1768 * solution to this architectural anomaly is to move RDE support out of GLD
1769 * and into LLC where it belongs. In particular, only LLC has the knowledge
1770 * necessary to reply to XID and TEST packets. If and when it comes time to
1771 * move RDE out of GLD to LLC, the LLC-to-GLD interface should be modified
1772 * to use MA_UNITDATA structures rather than DL_UNITDATA structures. Of
1773 * course, GLD will still have to continue to also support the DL_ structures
1774 * as long as IP is not layered over LLC. Another, perhaps better, idea
1775 * would be to make RDE an autopush module on top of the token ring drivers:
1776 * RDE would sit between LLC and GLD. It would then also sit between IP and
1777 * GLD, providing services to all clients of GLD/tokenring. In that case,
1778 * GLD would still have to continue to support the DL_ interface for non-
1779 * Token Ring interfaces, using the MA_ interface only for media supporting
1780 * Source Routing media.
1782 * At present, Token Ring is the only source routing medium we support.
1783 * Since Token Ring is not at this time a strategic network medium for Sun,
1784 * rather than devote a large amount of resources to creating a proper
1785 * architecture and implementation of RDE, we do the minimum necessary to
1786 * get it to work. The interface between the above token ring code and the
1787 * below RDE code is designed to make it relatively easy to change to an
1788 * MA_UNITDATA model later should this ever become a priority.
1791 static void gld_send_rqr(gld_mac_info_t
*, uchar_t
*, struct gld_ri
*,
1792 struct rde_pdu
*, int);
1793 static void gld_rde_pdu_req(gld_mac_info_t
*, queue_t
*, uchar_t
*,
1794 struct gld_ri
*, uchar_t
, uchar_t
, uchar_t
);
1795 static void gld_get_route(gld_mac_info_t
*, queue_t
*, uchar_t
*,
1796 struct gld_ri
**, uchar_t
, uchar_t
);
1797 static void gld_reset_route(gld_mac_info_t
*, queue_t
*,
1798 uchar_t
*, uchar_t
, uchar_t
);
1799 static void gld_rde_pdu_ind(gld_mac_info_t
*, struct gld_ri
*, struct rde_pdu
*,
1801 static void gld_rif_ind(gld_mac_info_t
*, struct gld_ri
*, uchar_t
*,
1803 static struct srtab
**gld_sr_hash(struct srtab
**, uchar_t
*, int);
1804 static struct srtab
*gld_sr_lookup_entry(gld_mac_info_t
*, uchar_t
*);
1805 static struct srtab
*gld_sr_create_entry(gld_mac_info_t
*, uchar_t
*);
1808 * This routine implements a modified subset of the 802.2 RDE RCC receive
1810 * we implement RCC receive events 3 to 12 (ISO 8802-2:1994 9.6.3.4);
1811 * we omit special handling for the NULL SAP;
1812 * we omit XID/TEST handling;
1813 * we pass all packets (including RDE) upstream to LLC.
1816 gld_rcc_receive(gld_mac_info_t
*macinfo
, pktinfo_t
*pktinfo
, struct gld_ri
*rh
,
1817 uchar_t
*llcpkt
, int llcpktlen
)
1819 struct llc_snap_hdr
*snaphdr
= (struct llc_snap_hdr
*)(llcpkt
);
1821 if (!((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->rde_enabled
)
1825 * First, ensure this packet wasn't something we received just
1826 * because we were in promiscuous mode. Since none of the below
1827 * code wants to see group addressed packets anyway, we can do
1828 * this check up front. Since we're doing that, we can omit the
1829 * checks for group addressed packets below.
1831 if (!pktinfo
->isForMe
)
1832 return; /* Event 6 */
1834 /* Process a subset of Route Determination Entity (RDE) packets */
1835 if (snaphdr
->d_lsap
== LSAP_RDE
) {
1836 struct rde_pdu
*pdu
= (struct rde_pdu
*)(llcpkt
+ LLC_HDR1_LEN
);
1837 int pdulen
= llcpktlen
- LLC_HDR1_LEN
;
1839 /* sanity check the PDU */
1840 if ((pdulen
< sizeof (struct rde_pdu
)) ||
1841 (snaphdr
->s_lsap
!= LSAP_RDE
))
1844 /* we only handle route discovery PDUs, not XID/TEST/other */
1845 if (snaphdr
->control
!= CNTL_LLC_UI
)
1848 switch (pdu
->rde_ptype
) {
1849 case RDE_RQC
: /* Route Query Command; Events 8 - 11 */
1850 gld_send_rqr(macinfo
, pktinfo
->shost
, rh
, pdu
, pdulen
);
1852 case RDE_RQR
: /* Route Query Response; Event 12 */
1853 case RDE_RS
: /* Route Selected; Event 7 */
1854 gld_rde_pdu_ind(macinfo
, rh
, pdu
, pdulen
);
1856 default: /* ignore if unrecognized ptype */
1863 /* Consider routes seen in other IA SRF packets */
1866 return; /* no RIF; Event 3 */
1868 if ((rh
->rt
& 0x04) != 0)
1869 return; /* not SRF; Event 5 */
1871 gld_rif_ind(macinfo
, rh
, pktinfo
->shost
, snaphdr
->s_lsap
,
1872 snaphdr
->d_lsap
); /* Event 4 */
1876 * Send RQR: 802.2 9.6.3.4.2(9) RCC Receive Events 8-11
1878 * The routing processing really doesn't belong here; it should be handled in
1879 * the LLC layer above. If that were the case then RDE could just send down
1880 * an extra MA_UNITDATA_REQ with the info needed to construct the packet. But
1881 * at the time we get control here, it's not a particularly good time to be
1882 * constructing packets and trying to send them. Specifically, at this layer
1883 * we need to construct the full media packet, which means the below routine
1884 * knows that it is dealing with Token Ring media. If this were instead done
1885 * via a proper MA_UNITDATA interface, the RDE stuff could all be completely
1886 * media independent. But since TR is the only source routing medium we
1887 * support, this works even though it is not clean.
1889 * We "know" that the only time we can get here is from the "interpret"
1890 * routine, and only when it was called at receive time.
1893 gld_send_rqr(gld_mac_info_t
*macinfo
, uchar_t
*shost
, struct gld_ri
*rh
,
1894 struct rde_pdu
*pdu
, int pdulen
)
1898 struct tr_mac_frm_nori
*nmh
;
1900 struct llc_snap_hdr
*nsnaphdr
;
1901 struct rde_pdu
*npdu
;
1903 /* We know and assume we're on the receive path */
1904 ASSERT(GLDM_LOCK_HELD(macinfo
));
1906 if (pdulen
< sizeof (struct rde_pdu
))
1907 return; /* Bad incoming PDU */
1909 nlen
= sizeof (struct tr_mac_frm
) + LLC_HDR1_LEN
+
1910 sizeof (struct rde_pdu
);
1912 if ((nmp
= allocb(nlen
, BPRI_MED
)) == NULL
)
1915 nmp
->b_rptr
= nmp
->b_wptr
= DB_LIM(nmp
);
1917 nmp
->b_rptr
-= sizeof (struct rde_pdu
);
1918 npdu
= (struct rde_pdu
*)(nmp
->b_rptr
);
1919 *npdu
= *pdu
; /* copy orig/target macaddr/saps */
1921 npdu
->rde_ptype
= RDE_RQR
;
1922 mac_copy(((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->curr_macaddr
,
1923 npdu
->rde_target_mac
, macinfo
->gldm_addrlen
);
1925 nmp
->b_rptr
-= LLC_HDR1_LEN
;
1926 nsnaphdr
= (struct llc_snap_hdr
*)(nmp
->b_rptr
);
1927 nsnaphdr
->s_lsap
= nsnaphdr
->d_lsap
= LSAP_RDE
;
1928 nsnaphdr
->control
= CNTL_LLC_UI
;
1930 if (rh
== NULL
|| (rh
->rt
& 0x06) == 0x06 ||
1931 rh
->len
> sizeof (struct gld_ri
)) {
1932 /* no RIF (Event 8), or RIF type STE (Event 9): send ARE RQR */
1934 nrh
= (struct gld_ri
*)(nmp
->b_rptr
);
1939 nrh
->mtu
= RT_MTU_MAX
;
1942 * RIF must be ARE (Event 10) or SRF (Event 11):
1943 * send SRF (reverse) RQR
1945 ASSERT(rh
->len
<= sizeof (struct gld_ri
));
1946 nmp
->b_rptr
-= rh
->len
;
1947 nrh
= (struct gld_ri
*)(nmp
->b_rptr
);
1948 bcopy(rh
, nrh
, rh
->len
); /* copy incoming RIF */
1949 nrh
->rt
= RT_SRF
; /* make it SRF */
1950 nrh
->dir
^= 1; /* reverse direction */
1953 nmp
->b_rptr
-= sizeof (struct tr_mac_frm_nori
);
1954 nmh
= (struct tr_mac_frm_nori
*)(nmp
->b_rptr
);
1957 mac_copy(shost
, nmh
->tr_dhost
, macinfo
->gldm_addrlen
);
1958 mac_copy(((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->curr_macaddr
,
1959 nmh
->tr_shost
, macinfo
->gldm_addrlen
);
1960 nmh
->tr_shost
[0] |= 0x80; /* indicate RIF present */
1963 * Packet assembled; send it.
1965 * As noted before, this is not really a good time to be trying to
1966 * send out packets. We have no obvious queue to use if the packet
1967 * can't be sent right away. We pick one arbitrarily.
1973 if ((vlan
= gld_find_vlan(macinfo
, VLAN_VID_NONE
)) == NULL
) {
1974 /* oops, no vlan on the list for this macinfo! */
1975 /* this should not happen */
1979 q
= vlan
->gldv_str_next
->gld_qptr
;
1982 * Queue the packet and let gld_wsrv
1983 * handle it, thus preventing a panic
1984 * caused by v2 TR in promiscuous mode
1985 * where it attempts to get the mutex
1986 * in this thread while already holding
1989 (void) putbq(WR(q
), nmp
);
1995 * This routine implements a modified subset of the 802.2 RDE RCC send actions:
1996 * we implement RCC send events 5 to 10 (ISO 8802-2:1994 9.6.3.5);
1997 * we omit special handling for the NULL SAP;
1998 * events 11 to 12 are handled by gld_rde_pdu_req below;
1999 * we require an immediate response to our GET_ROUTE_REQUEST.
2002 gld_rcc_send(gld_mac_info_t
*macinfo
, queue_t
*q
, uchar_t
*dhost
,
2003 struct gld_ri
**rhp
, uchar_t
*llcpkt
)
2005 struct llc_snap_hdr
*snaphdr
= (struct llc_snap_hdr
*)(llcpkt
);
2008 * Our caller has to take the mutex because: to avoid an extra bcopy
2009 * of the RIF on every transmit, we pass back a pointer to our sr
2010 * table entry via rhp. The caller has to keep the mutex until it has a
2011 * chance to copy the RIF out into the outgoing packet, so that we
2012 * don't modify the entry while it's being copied. This is a
2013 * little ugly, but saves the extra bcopy.
2015 ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo
)));
2017 *rhp
= NULL
; /* start off clean (no RIF) */
2019 if (!((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->rde_enabled
) {
2020 /* RDE is disabled -- use NULL or STE always */
2021 if (((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->
2022 rde_str_indicator_ste
)
2023 *rhp
= &ri_ste_def
; /* STE option */
2027 if (!(dhost
[0] & 0x80)) {
2028 /* individual address; Events 7 - 10 */
2029 if ((snaphdr
->control
& 0xef) == 0xe3) {
2030 /* TEST command, reset the route */
2031 gld_reset_route(macinfo
, q
,
2032 dhost
, snaphdr
->d_lsap
, snaphdr
->s_lsap
);
2034 gld_get_route(macinfo
, q
,
2035 dhost
, rhp
, snaphdr
->d_lsap
, snaphdr
->s_lsap
);
2040 * group address (Events 5 - 6),
2041 * or no route available (Events 8 - 9):
2042 * Need to send NSR or STE, as configured.
2044 if (((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->
2045 rde_str_indicator_ste
)
2046 *rhp
= &ri_ste_def
; /* STE option */
2051 * RCC send events 11 - 12
2053 * At present we only handle the RQC ptype.
2055 * We "know" that the only time we can get here is from the "unitdata"
2056 * routine, called at wsrv time.
2058 * If we ever implement the RS ptype (Event 13), this may no longer be true!
2061 gld_rde_pdu_req(gld_mac_info_t
*macinfo
, queue_t
*q
, uchar_t
*dhost
,
2062 struct gld_ri
*rh
, uchar_t dsap
, uchar_t ssap
, uchar_t ptype
)
2066 struct tr_mac_frm_nori
*nmh
;
2068 struct llc_snap_hdr
*nsnaphdr
;
2069 struct rde_pdu
*npdu
;
2072 /* if you change this to process other types, review all code below */
2073 ASSERT(ptype
== RDE_RQC
);
2074 ASSERT(rh
== NULL
); /* RQC never uses SRF */
2076 nlen
= sizeof (struct tr_mac_frm
) + LLC_HDR1_LEN
+
2077 sizeof (struct rde_pdu
);
2079 if ((nmp
= allocb(nlen
, BPRI_MED
)) == NULL
)
2082 nmp
->b_rptr
= nmp
->b_wptr
= DB_LIM(nmp
);
2084 nmp
->b_rptr
-= sizeof (struct rde_pdu
);
2085 npdu
= (struct rde_pdu
*)(nmp
->b_rptr
);
2087 npdu
->rde_ptype
= ptype
;
2088 mac_copy(dhost
, &npdu
->rde_target_mac
, 6);
2091 * access the mac address without a mutex - take a risk -
2092 * to prevent mutex contention (BUG 4211361)
2094 mac_copy(((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->curr_macaddr
,
2095 &npdu
->rde_orig_mac
, 6);
2096 npdu
->rde_target_sap
= dsap
;
2097 npdu
->rde_orig_sap
= ssap
;
2099 nmp
->b_rptr
-= LLC_HDR1_LEN
;
2100 nsnaphdr
= (struct llc_snap_hdr
*)(nmp
->b_rptr
);
2101 nsnaphdr
->s_lsap
= nsnaphdr
->d_lsap
= LSAP_RDE
;
2102 nsnaphdr
->control
= CNTL_LLC_UI
;
2104 #if 0 /* we don't need this for now */
2106 /* send an SRF frame with specified RIF */
2107 ASSERT(rh
->len
<= sizeof (struct gld_ri
));
2108 nmp
->b_rptr
-= rh
->len
;
2109 nrh
= (struct gld_ri
*)(nmp
->b_rptr
);
2110 bcopy(rh
, nrh
, rh
->len
);
2111 ASSERT(nrh
->rt
== RT_SRF
);
2116 /* Need to send NSR or STE, as configured. */
2117 if (((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->rde_str_indicator_ste
) {
2118 /* send an STE frame */
2120 nrh
= (struct gld_ri
*)(nmp
->b_rptr
);
2125 nrh
->mtu
= RT_MTU_MAX
;
2127 } /* else send an NSR frame */
2129 nmp
->b_rptr
-= sizeof (struct tr_mac_frm_nori
);
2130 nmh
= (struct tr_mac_frm_nori
*)(nmp
->b_rptr
);
2133 mac_copy(dhost
, nmh
->tr_dhost
, macinfo
->gldm_addrlen
);
2135 * access the mac address without a mutex - take a risk -
2136 * to prevent mutex contention - BUG 4211361
2138 mac_copy(((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->curr_macaddr
,
2139 nmh
->tr_shost
, macinfo
->gldm_addrlen
);
2142 nmh
->tr_shost
[0] |= 0x80;
2144 nmh
->tr_shost
[0] &= ~0x80;
2147 * Packet assembled; send it.
2149 * Since we own the SR_MUTEX, we don't want to take the maclock
2150 * mutex (since they are acquired in the opposite order on the
2151 * receive path, so deadlock could occur). We could rearrange
2152 * the code in gld_get_route() and drop the SR_MUTEX around the
2153 * call to gld_rde_pdu_req(), but that's kind of ugly. Rather,
2154 * we just refrain from calling gld_start() from here, and
2155 * instead just queue the packet for wsrv to send next. Besides,
2156 * it's more important to get the packet we're working on out
2157 * quickly than this RQC.
2159 (void) putbq(WR(q
), nmp
);
2164 * Route Determination Component (RDC)
2166 * We do not implement separate routes for each SAP, as specified by
2167 * ISO 8802-2; instead we implement only one route per remote mac address.
2170 gld_get_route(gld_mac_info_t
*macinfo
, queue_t
*q
, uchar_t
*dhost
,
2171 struct gld_ri
**rhp
, uchar_t dsap
, uchar_t ssap
)
2174 clock_t t
= ddi_get_lbolt();
2176 ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo
)));
2178 sr
= gld_sr_lookup_entry(macinfo
, dhost
);
2182 * we have no entry -- never heard of this address:
2183 * create an empty entry and initiate RQC
2185 sr
= gld_sr_create_entry(macinfo
, dhost
);
2186 gld_rde_pdu_req(macinfo
, q
, dhost
, NULL
,
2187 dsap
, ssap
, RDE_RQC
);
2190 *rhp
= NULL
; /* we have no route yet */
2194 /* we have an entry; see if we know a route yet */
2196 if (sr
->sr_ri
.len
== 0) {
2197 /* Have asked RQC, but no reply (yet) */
2198 if (t
- sr
->sr_timer
>
2199 ((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->rde_timeout
) {
2200 /* RQR overdue, resend RQC */
2201 gld_rde_pdu_req(macinfo
, q
, dhost
,
2202 NULL
, dsap
, ssap
, RDE_RQC
);
2205 *rhp
= NULL
; /* we have no route yet */
2209 /* we know a route, or it's local */
2211 /* if it might be stale, reset and get a new one */
2212 if (t
- sr
->sr_timer
>
2213 ((gld_mac_pvt_t
*)macinfo
->gldm_mac_pvt
)->rde_timeout
) {
2214 gld_rde_pdu_req(macinfo
, q
, dhost
,
2215 NULL
, dsap
, ssap
, RDE_RQC
);
2218 *rhp
= NULL
; /* we have no route */
2222 if (sr
->sr_ri
.len
== 2) {
2223 /* the remote site is on our local ring -- no route needed */
2228 *rhp
= &sr
->sr_ri
; /* we have a route, return it */
2232 * zap the specified entry and reinitiate RQC
2235 gld_reset_route(gld_mac_info_t
*macinfo
, queue_t
*q
,
2236 uchar_t
*dhost
, uchar_t dsap
, uchar_t ssap
)
2240 ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo
)));
2242 sr
= gld_sr_create_entry(macinfo
, dhost
);
2243 gld_rde_pdu_req(macinfo
, q
, dhost
, NULL
,
2244 dsap
, ssap
, RDE_RQC
);
2249 sr
->sr_timer
= ddi_get_lbolt();
2253 * This routine is called when an RDE PDU is received from our peer.
2254 * If it is an RS (Route Selected) PDU, we adopt the specified route.
2255 * If it is an RQR (reply to our previous RQC), we evaluate the
2256 * specified route in comparison with our current known route, if any,
2257 * and we keep the "better" of the two routes.
2260 gld_rde_pdu_ind(gld_mac_info_t
*macinfo
, struct gld_ri
*rh
, struct rde_pdu
*pdu
,
2266 if (pdulen
< sizeof (struct rde_pdu
))
2267 return; /* Bad incoming PDU */
2269 if (pdu
->rde_ptype
== RDE_RQC
)
2270 return; /* ignore RQC */
2272 if (pdu
->rde_ptype
!= RDE_RQR
&& pdu
->rde_ptype
!= RDE_RS
) {
2274 if (gld_debug
& GLDERRS
)
2275 cmn_err(CE_WARN
, "gld: bogus RDE ptype 0x%x received",
2283 if (gld_debug
& GLDERRS
)
2285 "gld: bogus NULL RIF, ptype 0x%x received",
2291 ASSERT(rh
->len
>= 2);
2292 ASSERT(rh
->len
<= sizeof (struct gld_ri
));
2293 ASSERT((rh
->len
& 1) == 0);
2295 if (pdu
->rde_ptype
== RDE_RQR
) {
2296 /* A reply to our RQC has its address as target mac */
2297 otherhost
= pdu
->rde_target_mac
;
2299 ASSERT(pdu
->rde_ptype
== RDE_RS
);
2300 /* An RS has its address as orig mac */
2301 otherhost
= pdu
->rde_orig_mac
;
2304 mutex_enter(GLD_SR_MUTEX(macinfo
));
2306 if ((sr
= gld_sr_create_entry(macinfo
, otherhost
)) == NULL
) {
2307 mutex_exit(GLD_SR_MUTEX(macinfo
));
2308 return; /* oh well, out of memory */
2311 if (pdu
->rde_ptype
== RDE_RQR
) {
2312 /* see if new route is better than what we may already have */
2313 if (sr
->sr_ri
.len
!= 0 &&
2314 sr
->sr_ri
.len
<= rh
->len
) {
2315 mutex_exit(GLD_SR_MUTEX(macinfo
));
2316 return; /* we have one, and new one is no shorter */
2320 /* adopt the new route */
2321 bcopy((caddr_t
)rh
, (caddr_t
)&sr
->sr_ri
, rh
->len
); /* copy incom RIF */
2322 sr
->sr_ri
.rt
= RT_SRF
; /* make it a clean SRF */
2323 sr
->sr_ri
.dir
^= 1; /* reverse direction */
2324 sr
->sr_timer
= ddi_get_lbolt();
2326 mutex_exit(GLD_SR_MUTEX(macinfo
));
2330 * This routine is called when a packet with a RIF is received. Our
2331 * policy is to adopt the route.
2335 gld_rif_ind(gld_mac_info_t
*macinfo
, struct gld_ri
*rh
, uchar_t
*shost
,
2336 uchar_t ssap
, uchar_t dsap
)
2340 ASSERT(rh
!= NULL
); /* ensure RIF */
2341 ASSERT((rh
->rt
& 0x04) == 0); /* ensure SRF */
2342 ASSERT(rh
->len
>= 2);
2343 ASSERT(rh
->len
<= sizeof (struct gld_ri
));
2344 ASSERT((rh
->len
& 1) == 0);
2346 mutex_enter(GLD_SR_MUTEX(macinfo
));
2348 if ((sr
= gld_sr_create_entry(macinfo
, shost
)) == NULL
) {
2349 mutex_exit(GLD_SR_MUTEX(macinfo
));
2350 return; /* oh well, out of memory */
2353 /* we have an entry; fill it in */
2354 bcopy((caddr_t
)rh
, (caddr_t
)&sr
->sr_ri
, rh
->len
); /* copy incom RIF */
2355 sr
->sr_ri
.rt
= RT_SRF
; /* make it a clean SRF */
2356 sr
->sr_ri
.dir
^= 1; /* reverse direction */
2357 sr
->sr_timer
= ddi_get_lbolt();
2359 mutex_exit(GLD_SR_MUTEX(macinfo
));
2362 static struct srtab
**
2363 gld_sr_hash(struct srtab
**sr_hash_tbl
, uchar_t
*addr
, int addr_length
)
2367 while (--addr_length
>= 0)
2370 return (&sr_hash_tbl
[hashval
% SR_HASH_SIZE
]);
2373 static struct srtab
*
2374 gld_sr_lookup_entry(gld_mac_info_t
*macinfo
, uchar_t
*macaddr
)
2378 ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo
)));
2380 for (sr
= *gld_sr_hash(GLD_SR_HASH(macinfo
), macaddr
,
2381 macinfo
->gldm_addrlen
); sr
; sr
= sr
->sr_next
)
2382 if (mac_eq(macaddr
, sr
->sr_mac
, macinfo
->gldm_addrlen
))
2388 static struct srtab
*
2389 gld_sr_create_entry(gld_mac_info_t
*macinfo
, uchar_t
*macaddr
)
2394 ASSERT(!(macaddr
[0] & 0x80)); /* no group addresses here */
2395 ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo
)));
2397 srp
= gld_sr_hash(GLD_SR_HASH(macinfo
), macaddr
, macinfo
->gldm_addrlen
);
2399 for (sr
= *srp
; sr
; sr
= sr
->sr_next
)
2400 if (mac_eq(macaddr
, sr
->sr_mac
, macinfo
->gldm_addrlen
))
2403 if (!(sr
= kmem_zalloc(sizeof (struct srtab
), KM_NOSLEEP
))) {
2405 if (gld_debug
& GLDERRS
)
2407 "gld: gld_sr_create_entry kmem_alloc failed");
2412 bcopy((caddr_t
)macaddr
, (caddr_t
)sr
->sr_mac
, macinfo
->gldm_addrlen
);
2420 gld_sr_clear(gld_mac_info_t
*macinfo
)
2423 struct srtab
**sr_hash_tbl
= GLD_SR_HASH(macinfo
);
2424 struct srtab
**srp
, *sr
;
2427 * Walk through the table, deleting all entries.
2429 * Only called from uninit, so don't need the mutex.
2431 for (i
= 0; i
< SR_HASH_SIZE
; i
++) {
2432 for (srp
= &sr_hash_tbl
[i
]; (sr
= *srp
) != NULL
; ) {
2434 kmem_free((char *)sr
, sizeof (struct srtab
));
2441 gld_sr_dump(gld_mac_info_t
*macinfo
)
2444 struct srtab
**sr_hash_tbl
;
2447 sr_hash_tbl
= GLD_SR_HASH(macinfo
);
2448 if (sr_hash_tbl
== NULL
)
2451 mutex_enter(GLD_SR_MUTEX(macinfo
));
2454 * Walk through the table, printing all entries
2456 cmn_err(CE_NOTE
, "GLD Source Routing Table (0x%p):", (void *)macinfo
);
2457 cmn_err(CE_CONT
, "Addr len,rt,dir,mtu,res rng,brg0 rng,brg1...\n");
2458 for (i
= 0; i
< SR_HASH_SIZE
; i
++) {
2459 for (sr
= sr_hash_tbl
[i
]; sr
; sr
= sr
->sr_next
) {
2461 "%x:%x:%x:%x:%x:%x %d,%x,%x,%x,%x ",
2462 sr
->sr_mac
[0], sr
->sr_mac
[1], sr
->sr_mac
[2],
2463 sr
->sr_mac
[3], sr
->sr_mac
[4], sr
->sr_mac
[5],
2464 sr
->sr_ri
.len
, sr
->sr_ri
.rt
, sr
->sr_ri
.dir
,
2465 sr
->sr_ri
.mtu
, sr
->sr_ri
.res
);
2467 for (j
= 0; j
< (sr
->sr_ri
.len
- 2) / 2; j
++)
2468 cmn_err(CE_CONT
, "%x ",
2469 REF_NET_USHORT(*(unsigned short *)
2471 cmn_err(CE_CONT
, "\n");
2475 mutex_exit(GLD_SR_MUTEX(macinfo
));