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 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22 * Use is subject to license terms.
23 */
24
25 /*
26 * gld - Generic LAN Driver
27 * media dependent routines
28 */
29
30 #include <sys/types.h>
31 #include <sys/errno.h>
32 #include <sys/stropts.h>
33 #include <sys/stream.h>
34 #include <sys/kmem.h>
35 #include <sys/stat.h>
36 #include <sys/modctl.h>
37 #include <sys/kstat.h>
38 #include <sys/debug.h>
39
40 #include <sys/byteorder.h>
41 #include <sys/strsun.h>
42 #include <sys/dlpi.h>
43 #include <sys/ethernet.h>
44 #include <sys/multidata.h>
45 #include <sys/gld.h>
46 #include <sys/gldpriv.h>
47 #include <sys/ddi.h>
48 #include <sys/sunddi.h>
49 #include <sys/sysmacros.h>
50 #include <sys/ib/clients/ibd/ibd.h>
51 #include <sys/pattr.h>
52
53 #define DLSAPLENGTH(macinfo) \
54 ((macinfo)->gldm_addrlen + ABS((macinfo)->gldm_saplen))
55
56 #ifdef GLD_DEBUG
57 extern int gld_debug;
58 #endif
59
60 extern void gld_bitrevcopy(caddr_t src, caddr_t target, size_t n);
61 extern char *gld_macaddr_sprintf(char *, unsigned char *, int);
62 extern gld_vlan_t *gld_find_vlan(gld_mac_info_t *, uint32_t);
63 extern uint32_t gld_global_options;
64
65 static struct llc_snap_hdr llc_snap_def = {
66 LSAP_SNAP, /* DLSAP 0xaa */
67 LSAP_SNAP, /* SLSAP 0xaa */
68 CNTL_LLC_UI, /* Control 0x03 */
69 { 0x00, 0x00, 0x00 }, /* Org[3] */
70 0x00 /* Type */
71 };
72
73 #define ISETHERTYPE(snaphdr) \
74 (snaphdr->d_lsap == LSAP_SNAP && \
75 snaphdr->s_lsap == LSAP_SNAP && \
76 snaphdr->control == CNTL_LLC_UI && \
77 snaphdr->org[0] == 0 && \
78 snaphdr->org[1] == 0 && \
79 snaphdr->org[2] == 0)
80
81 /* ======== */
82 /* Ethernet */
83 /* ======== */
84
85 static mac_addr_t ether_broadcast = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
86
87 void
88 gld_init_ether(gld_mac_info_t *macinfo)
89 {
90 struct gldkstats *sp =
91 ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->kstatp->ks_data;
92
93 /* Assumptions we make for this medium */
94 ASSERT(macinfo->gldm_type == DL_ETHER);
95 ASSERT(macinfo->gldm_addrlen == 6);
96 ASSERT(macinfo->gldm_saplen == -2);
97 #ifndef lint
98 ASSERT(sizeof (struct ether_header) == 14);
99 ASSERT(sizeof (mac_addr_t) == 6);
100 #endif
101
102 kstat_named_init(&sp->glds_frame, "align_errors", KSTAT_DATA_ULONG);
103 kstat_named_init(&sp->glds_crc, "fcs_errors", KSTAT_DATA_ULONG);
104 kstat_named_init(&sp->glds_collisions, "collisions", KSTAT_DATA_ULONG);
105 kstat_named_init(&sp->glds_nocarrier, "carrier_errors",
106 KSTAT_DATA_ULONG);
107 kstat_named_init(&sp->glds_defer, "defer_xmts", KSTAT_DATA_ULONG);
108 kstat_named_init(&sp->glds_xmtlatecoll, "tx_late_collisions",
109 KSTAT_DATA_ULONG);
110 kstat_named_init(&sp->glds_short, "runt_errors", KSTAT_DATA_ULONG);
111 kstat_named_init(&sp->glds_excoll, "ex_collisions", KSTAT_DATA_ULONG);
112
113 /*
114 * only initialize the new statistics if the driver
115 * knows about them.
116 */
117 if (macinfo->gldm_driver_version != GLD_VERSION_200)
118 return;
119
120 kstat_named_init(&sp->glds_dot3_first_coll,
121 "first_collisions", KSTAT_DATA_UINT32);
122 kstat_named_init(&sp->glds_dot3_multi_coll,
123 "multi_collisions", KSTAT_DATA_UINT32);
124 kstat_named_init(&sp->glds_dot3_sqe_error,
125 "sqe_errors", KSTAT_DATA_UINT32);
126 kstat_named_init(&sp->glds_dot3_mac_xmt_error,
127 "macxmt_errors", KSTAT_DATA_UINT32);
128 kstat_named_init(&sp->glds_dot3_mac_rcv_error,
129 "macrcv_errors", KSTAT_DATA_UINT32);
130 kstat_named_init(&sp->glds_dot3_frame_too_long,
131 "toolong_errors", KSTAT_DATA_UINT32);
132 kstat_named_init(&sp->glds_duplex, "duplex", KSTAT_DATA_CHAR);
133 }
134
135 /*ARGSUSED*/
136 void
137 gld_uninit_ether(gld_mac_info_t *macinfo)
138 {
139 }
140
141 int
142 gld_interpret_ether(gld_mac_info_t *macinfo, mblk_t *mp, pktinfo_t *pktinfo,
143 packet_flag_t flags)
144 {
145 struct ether_header *mh;
146 gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
147 struct llc_snap_hdr *snaphdr;
148 mblk_t *pmp = NULL, *savemp = mp;
149 unsigned short typelen;
150 int ret = 0;
151
152 /*
153 * Quickly handle receive fastpath for IPQ hack.
154 */
155 if (flags == GLD_RXQUICK) {
156 pktinfo->pktLen = msgdsize(mp);
157 /*
158 * Check whether the header is contiguous, which
159 * also implicitly makes sure the packet is big enough.
160 */
161 if (MBLKL(mp) < sizeof (struct ether_header))
162 return (-1);
163 mh = (struct ether_header *)mp->b_rptr;
164 pktinfo->ethertype = REF_NET_USHORT(mh->ether_type);
165 pktinfo->isForMe = mac_eq(&mh->ether_dhost,
166 mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
167 pktinfo->macLen = sizeof (struct ether_header);
168
169 return (0);
170 }
171
172 bzero((void *)pktinfo, sizeof (*pktinfo));
173
174 pktinfo->pktLen = msgdsize(mp);
175
176 /* make sure packet has at least a whole mac header */
177 if (pktinfo->pktLen < sizeof (struct ether_header))
178 return (-1);
179
180 /* make sure the mac header falls into contiguous memory */
181 if (MBLKL(mp) < sizeof (struct ether_header)) {
182 if ((pmp = msgpullup(mp, -1)) == NULL) {
183 #ifdef GLD_DEBUG
184 if (gld_debug & GLDERRS)
185 cmn_err(CE_WARN,
186 "GLD: interpret_ether cannot msgpullup");
187 #endif
188 return (-1);
189 }
190 mp = pmp; /* this mblk contains the whole mac header */
191 }
192
193 mh = (struct ether_header *)mp->b_rptr;
194
195 /* Check to see if the mac is a broadcast or multicast address. */
196 if (mac_eq(&mh->ether_dhost, ether_broadcast, macinfo->gldm_addrlen))
197 pktinfo->isBroadcast = 1;
198 else if (mh->ether_dhost.ether_addr_octet[0] & 1)
199 pktinfo->isMulticast = 1;
200
201 typelen = REF_NET_USHORT(mh->ether_type);
202 /*
203 * If the hardware is capable of VLAN tag insertion
204 * strip out the VLAN tag info. Knowing hardware is
205 * capable of VLAN can be established by the presance
206 * of non null 'macinfo->gldm_send_tagged'.
207 */
208 if (flags == GLD_TX) {
209 if ((typelen == ETHERTYPE_VLAN) &&
210 (macinfo->gldm_send_tagged != NULL)) {
211 struct ether_vlan_header *evhp;
212 uint16_t tci;
213
214 if ((MBLKL(mp) < sizeof (struct ether_vlan_header)) &&
215 (pullupmsg(mp, sizeof (struct ether_vlan_header))
216 == 0)) {
217 ret = -1;
218 goto out;
219 }
220 evhp = (struct ether_vlan_header *)mp->b_rptr;
221 tci = REF_NET_USHORT(evhp->ether_tci);
222
223 /*
224 * We don't allow the VID and priority are both zero.
225 */
226 if ((GLD_VTAG_PRI((int32_t)tci) == 0 &&
227 GLD_VTAG_VID((int32_t)tci) == VLAN_VID_NONE) ||
228 (GLD_VTAG_CFI((uint32_t)tci)) != VLAN_CFI_ETHER) {
229 ret = -1;
230 goto out;
231 }
232
233 /*
234 * Remember the VTAG info in order to reinsert it,
235 * Then strip the tag. This is required because some
236 * drivers do not allow the size of message (passed
237 * by the gldm_send_tagged() function) to be greater
238 * than ETHERMAX.
239 */
240 GLD_SAVE_MBLK_VTAG(savemp, GLD_TCI2VTAG(tci));
241 ovbcopy(mp->b_rptr, mp->b_rptr + VTAG_SIZE,
242 2 * ETHERADDRL);
243 mp->b_rptr += VTAG_SIZE;
244 }
245 goto out; /* Got all info we need for xmit case */
246 }
247
248 ASSERT(GLDM_LOCK_HELD(macinfo));
249
250 /*
251 * Deal with the mac header
252 */
253
254 mac_copy(&mh->ether_dhost, pktinfo->dhost, macinfo->gldm_addrlen);
255 mac_copy(&mh->ether_shost, pktinfo->shost, macinfo->gldm_addrlen);
256
257 pktinfo->isLooped = mac_eq(pktinfo->shost,
258 mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
259 pktinfo->isForMe = mac_eq(pktinfo->dhost,
260 mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
261
262 pktinfo->macLen = sizeof (struct ether_header);
263
264 if (typelen > ETHERMTU) {
265 pktinfo->ethertype = typelen; /* use type interpretation */
266 goto out;
267 }
268
269 /*
270 * Packet is 802.3 so the ether type/length field
271 * specifies the number of bytes that should be present
272 * in the data field. Additional bytes are padding, and
273 * should be removed
274 */
275 {
276 int delta = pktinfo->pktLen -
277 (sizeof (struct ether_header) + typelen);
278
279 if (delta > 0 && adjmsg(mp, -delta))
280 pktinfo->pktLen -= delta;
281 }
282
283 /*
284 * Before trying to look beyond the MAC header, make sure the LLC
285 * header exists, and that both it and any SNAP header are contiguous.
286 */
287 if (pktinfo->pktLen < pktinfo->macLen + LLC_HDR1_LEN)
288 goto out; /* LLC hdr should have been there! */
289
290 pktinfo->isLLC = 1;
291
292 if (gld_global_options & GLD_OPT_NO_ETHRXSNAP ||
293 pktinfo->pktLen < pktinfo->macLen + LLC_SNAP_HDR_LEN)
294 goto out;
295
296 if (MBLKL(mp) < sizeof (struct ether_header) + LLC_SNAP_HDR_LEN &&
297 MBLKL(mp) < pktinfo->pktLen) {
298 /*
299 * we don't have the entire packet within the first mblk (and
300 * therefore we didn't do the msgpullup above), AND the first
301 * mblk may not contain all the data we need to look at.
302 */
303 ASSERT(pmp == NULL); /* couldn't have done msgpullup above */
304 if ((pmp = msgpullup(mp, -1)) == NULL) {
305 #ifdef GLD_DEBUG
306 if (gld_debug & GLDERRS)
307 cmn_err(CE_WARN,
308 "GLD: interpret_ether cannot msgpullup2");
309 #endif
310 goto out; /* can't interpret this pkt further */
311 }
312 mp = pmp; /* this mblk should contain everything needed */
313 }
314
315 /*
316 * Check SAP/SNAP information for EtherType.
317 */
318
319 snaphdr = (struct llc_snap_hdr *)(mp->b_rptr + pktinfo->macLen);
320 if (ISETHERTYPE(snaphdr)) {
321 pktinfo->ethertype = REF_NET_USHORT(snaphdr->type);
322 pktinfo->hdrLen = LLC_SNAP_HDR_LEN;
323 }
324 out:
325 if (pmp != NULL)
326 freemsg(pmp);
327
328 return (ret);
329 }
330
331 mblk_t *
332 gld_unitdata_ether(gld_t *gld, mblk_t *mp)
333 {
334 gld_mac_info_t *macinfo = gld->gld_mac_info;
335 dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_rptr;
336 struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
337 mac_addr_t dhost;
338 unsigned short typelen;
339 mblk_t *nmp;
340 struct ether_header *mh;
341 int hdrlen;
342 uint32_t vptag;
343 gld_vlan_t *gld_vlan;
344
345 ASSERT(macinfo);
346
347 /* extract needed info from the mblk before we maybe reuse it */
348 mac_copy(gldp->glda_addr, dhost, macinfo->gldm_addrlen);
349
350 /* look in the unitdata request for a sap, else use bound one */
351 if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
352 REF_HOST_USHORT(gldp->glda_sap) != 0)
353 typelen = REF_HOST_USHORT(gldp->glda_sap);
354 else
355 typelen = gld->gld_sap;
356
357 /*
358 * We take values less than or equal to ETHERMTU to mean that the
359 * packet should not have an encoded EtherType and so we use the
360 * IEEE 802.3 length interpretation of the type/length field.
361 */
362 if (typelen <= ETHERMTU)
363 typelen = msgdsize(mp);
364
365 hdrlen = sizeof (struct ether_header);
366
367 /*
368 * Check to see if VLAN is enabled on this stream
369 * if so then make the header bigger to hold a clone
370 * vlan tag.
371 */
372 gld_vlan = (gld_vlan_t *)gld->gld_vlan;
373 if (gld_vlan && (gld_vlan->gldv_id != VLAN_VID_NONE)) {
374 hdrlen += VTAG_SIZE;
375 vptag = gld_vlan->gldv_ptag;
376 }
377
378 /* need a buffer big enough for the headers */
379 nmp = mp->b_cont; /* where the packet payload M_DATA is */
380 if (DB_REF(nmp) == 1 && MBLKHEAD(nmp) >= hdrlen) {
381 /* it fits at the beginning of the first M_DATA block */
382 freeb(mp); /* don't need the M_PROTO anymore */
383 } else if (DB_REF(mp) == 1 && MBLKSIZE(mp) >= hdrlen) {
384 /* we can reuse the dl_unitdata_req M_PROTO mblk */
385 nmp = mp;
386 DB_TYPE(nmp) = M_DATA;
387 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
388 } else {
389 /* we need to allocate one */
390 if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
391 return (NULL);
392 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
393 linkb(nmp, mp->b_cont);
394 freeb(mp);
395 }
396
397 /* Got the space, now copy in the header components */
398
399 nmp->b_rptr -= sizeof (typelen);
400 SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, typelen);
401 if (hdrlen > sizeof (struct ether_header)) {
402 nmp->b_rptr -= sizeof (uint16_t);
403 SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, vptag);
404 vptag >>= 16;
405 nmp->b_rptr -= sizeof (uint16_t);
406 SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, vptag);
407 }
408 nmp->b_rptr -= (ETHERADDRL * 2);
409 mh = (struct ether_header *)nmp->b_rptr;
410 mac_copy(dhost, &mh->ether_dhost, macinfo->gldm_addrlen);
411
412 /*
413 * We access the mac address without the mutex to prevent
414 * mutex contention (BUG 4211361)
415 */
416 mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
417 &mh->ether_shost, macinfo->gldm_addrlen);
418
419 return (nmp);
420 }
421
422 /*
423 * Insert the VLAN tag into the packet. The packet now is an Ethernet header
424 * without VLAN tag information.
425 */
426 mblk_t *
427 gld_insert_vtag_ether(mblk_t *mp, uint32_t vtag)
428 {
429 struct ether_vlan_header *evhp;
430 struct ether_header *ehp;
431 mblk_t *nmp;
432
433 if (vtag == VLAN_VID_NONE)
434 return (mp);
435
436 if (DB_REF(mp) == 1 && MBLKHEAD(mp) >= VTAG_SIZE) {
437 /* it fits at the beginning of the message block */
438 nmp = mp;
439 ovbcopy(nmp->b_rptr, nmp->b_rptr - VTAG_SIZE, 2 * ETHERADDRL);
440 nmp->b_rptr -= VTAG_SIZE;
441 evhp = (struct ether_vlan_header *)nmp->b_rptr;
442 } else {
443 /* we need to allocate one */
444 if ((nmp = allocb(sizeof (struct ether_vlan_header),
445 BPRI_MED)) == NULL) {
446 return (NULL);
447 }
448 nmp->b_wptr += sizeof (struct ether_vlan_header);
449
450 /* transfer the ether_header fields */
451 evhp = (struct ether_vlan_header *)nmp->b_rptr;
452 ehp = (struct ether_header *)mp->b_rptr;
453 mac_copy(&ehp->ether_dhost, &evhp->ether_dhost, ETHERADDRL);
454 mac_copy(&ehp->ether_shost, &evhp->ether_shost, ETHERADDRL);
455 bcopy(&ehp->ether_type, &evhp->ether_type, sizeof (uint16_t));
456
457 /* offset the mp of the MAC header length. */
458 mp->b_rptr += sizeof (struct ether_header);
459 if (MBLKL(mp) == 0) {
460 nmp->b_cont = mp->b_cont;
461 freeb(mp);
462 } else {
463 nmp->b_cont = mp;
464 }
465 }
466
467 SET_NET_USHORT(evhp->ether_tci, vtag);
468 vtag >>= 16;
469 SET_NET_USHORT(evhp->ether_tpid, vtag);
470 return (nmp);
471 }
472
473 mblk_t *
474 gld_fastpath_ether(gld_t *gld, mblk_t *mp)
475 {
476 gld_mac_info_t *macinfo = gld->gld_mac_info;
477 dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
478 struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
479 unsigned short typelen;
480 mblk_t *nmp;
481 struct ether_header *mh;
482 int hdrlen;
483 uint32_t vptag;
484 gld_vlan_t *gld_vlan;
485
486 ASSERT(macinfo);
487
488 /* look in the unitdata request for a sap, else use bound one */
489 if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
490 REF_HOST_USHORT(gldp->glda_sap) != 0)
491 typelen = REF_HOST_USHORT(gldp->glda_sap);
492 else
493 typelen = gld->gld_sap;
494
495 /*
496 * We only do fast-path for EtherType encoding because this is the only
497 * case where the media header will be consistent from packet to packet.
498 */
499 if (typelen <= ETHERMTU)
500 return (NULL);
501
502 /*
503 * Initialize the fast path header to include the
504 * basic source address information and type field.
505 */
506 hdrlen = sizeof (struct ether_header);
507
508 /*
509 * Check to see if VLAN is enabled on this stream
510 * if so then make the header bigger to hold a clone
511 * vlan tag.
512 */
513 gld_vlan = (gld_vlan_t *)gld->gld_vlan;
514 if (gld_vlan && (gld_vlan->gldv_id != VLAN_VID_NONE)) {
515 hdrlen += VTAG_SIZE;
516 vptag = gld_vlan->gldv_ptag;
517 }
518
519 if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
520 return (NULL);
521
522 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
523
524 /* Got the space, now copy in the header components */
525
526 nmp->b_rptr -= sizeof (typelen);
527 SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, typelen);
528
529 /*
530 * If the header is for a VLAN stream, then add
531 * in the VLAN tag to the clone header.
532 */
533 if (hdrlen > sizeof (struct ether_header)) {
534 nmp->b_rptr -= sizeof (uint16_t);
535 SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, vptag);
536 vptag >>= 16;
537 nmp->b_rptr -= sizeof (uint16_t);
538 SET_NET_USHORT(*(uint16_t *)nmp->b_rptr, vptag);
539 }
540 nmp->b_rptr -= (ETHERADDRL * 2);
541 mh = (struct ether_header *)nmp->b_rptr;
542 mac_copy(gldp->glda_addr, &mh->ether_dhost, macinfo->gldm_addrlen);
543
544 GLDM_LOCK(macinfo, RW_WRITER);
545 mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
546 &mh->ether_shost, macinfo->gldm_addrlen);
547 GLDM_UNLOCK(macinfo);
548
549 return (nmp);
550 }
551
552 /* == */
553 /* IB */
554 /* == */
555
556 void
557 gld_init_ib(gld_mac_info_t *macinfo)
558 {
559 /*
560 * Currently, the generic stats maintained by GLD is
561 * sufficient for IPoIB.
562 */
563
564 /* Assumptions we make for this medium */
565 ASSERT(macinfo->gldm_type == DL_IB);
566 ASSERT(macinfo->gldm_addrlen == IPOIB_ADDRL);
567 ASSERT(macinfo->gldm_saplen == -2);
568 }
569
570 /* ARGSUSED */
571 void
572 gld_uninit_ib(gld_mac_info_t *macinfo)
573 {
574 }
575
576 /*
577 * The packet format sent to the driver is:
578 * IPOIB_ADDRL bytes dest addr :: 2b sap :: 2b 0s :: data
579 * The packet format received from the driver is:
580 * IPOIB_GRH_SIZE bytes pseudo GRH :: 2b sap :: 2b 0s :: data.
581 */
582 int
583 gld_interpret_ib(gld_mac_info_t *macinfo, mblk_t *mp, pktinfo_t *pktinfo,
584 packet_flag_t flags)
585 {
586 ipoib_pgrh_t *grh;
587 ipoib_ptxhdr_t *gldp;
588 mblk_t *pmp = NULL;
589 gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
590
591 /*
592 * Quickly handle receive fastpath for IPQ hack.
593 */
594 if (flags == GLD_RXQUICK) {
595 pktinfo->pktLen = msgdsize(mp) - IPOIB_GRH_SIZE;
596
597 /*
598 * Check whether the header is contiguous, which
599 * also implicitly makes sure the packet is big enough.
600 */
601 if (MBLKL(mp) < (IPOIB_GRH_SIZE + IPOIB_HDRSIZE))
602 return (-1);
603
604 /*
605 * Almost all times, unicast will not have
606 * a valid pgrh; quickly identify and ask for
607 * IPQ hack optimization only in that case.
608 */
609 grh = (ipoib_pgrh_t *)mp->b_rptr;
610 if (grh->ipoib_vertcflow == 0) {
611 struct ipoib_header *ihp = (struct ipoib_header *)
612 (mp->b_rptr + IPOIB_GRH_SIZE);
613
614 pktinfo->isForMe = 1;
615 pktinfo->ethertype = REF_NET_USHORT(ihp->ipoib_type);
616 pktinfo->macLen = IPOIB_GRH_SIZE + IPOIB_HDRSIZE;
617 return (0);
618 } else {
619 return (-1);
620 }
621 }
622
623 /*
624 * Handle the GLD_TX, GLD_RX, GLD_RXLOOP cases now.
625 */
626 ASSERT(flags != GLD_RXQUICK);
627 bzero((void *)pktinfo, sizeof (*pktinfo));
628
629 if (flags != GLD_RX) {
630 /*
631 * GLD_TX and GLD_RXLOOP cases.
632 */
633 gldp = (ipoib_ptxhdr_t *)mp->b_rptr;
634 pktinfo->pktLen = msgdsize(mp);
635
636 /* make sure packet has at least a pseudo header */
637 if (pktinfo->pktLen < sizeof (ipoib_ptxhdr_t))
638 return (-1);
639
640 /* make sure the mac header falls into contiguous memory */
641 if (MBLKL(mp) < sizeof (ipoib_ptxhdr_t)) {
642 if ((pmp = msgpullup(mp, -1)) == NULL) {
643 #ifdef GLD_DEBUG
644 if (gld_debug & GLDERRS)
645 cmn_err(CE_WARN,
646 "GLD: interpret_ib "
647 "cannot msgpullup");
648 #endif
649 return (-1);
650 }
651 /* this mblk contains the whole mac header */
652 mp = pmp;
653 }
654
655 /*
656 * Check if mac is broadcast or multicast address; all these
657 * types of address have the top 4 bytes as 0x00FFFFFF.
658 */
659 if (mac_eq(&gldp->ipoib_dest, macinfo->gldm_broadcast_addr,
660 sizeof (uint32_t))) {
661 if (mac_eq(&gldp->ipoib_dest,
662 macinfo->gldm_broadcast_addr, IPOIB_ADDRL))
663 pktinfo->isBroadcast = 1;
664 else
665 pktinfo->isMulticast = 1;
666 }
667
668 /*
669 * Only count bytes we will be sending over the wire
670 * or looping back.
671 */
672 pktinfo->pktLen -= IPOIB_ADDRL;
673 if (flags == GLD_TX)
674 goto out; /* Got all info we need for xmit case */
675
676 /*
677 * Loopback case: this is a dup'ed message.
678 */
679 mp->b_rptr += IPOIB_ADDRL;
680 mac_copy(&gldp->ipoib_dest, pktinfo->dhost, IPOIB_ADDRL);
681 mac_copy(mac_pvt->curr_macaddr, pktinfo->shost, IPOIB_ADDRL);
682 } else {
683 /*
684 * GLD_RX case; process packet sent from driver.
685 */
686 ipoib_mac_t *mact, *tact;
687 ib_qpn_t dqpn;
688
689 pktinfo->pktLen = msgdsize(mp);
690 /* make sure packet has at least pgrh and mac header */
691 if (pktinfo->pktLen < (IPOIB_GRH_SIZE + IPOIB_HDRSIZE))
692 return (-1);
693
694 /* make sure the header falls into contiguous memory */
695 if (MBLKL(mp) < (IPOIB_GRH_SIZE + IPOIB_HDRSIZE)) {
696 if ((pmp = msgpullup(mp, -1)) == NULL) {
697 #ifdef GLD_DEBUG
698 if (gld_debug & GLDERRS)
699 cmn_err(CE_WARN,
700 "GLD: interpret_ib "
701 "cannot msgpullup2");
702 #endif
703 return (-1);
704 }
705 /* this mblk contains the whole mac header */
706 mp = pmp;
707 }
708
709 grh = (ipoib_pgrh_t *)mp->b_rptr;
710 mp->b_rptr += IPOIB_GRH_SIZE;
711 pktinfo->pktLen -= IPOIB_GRH_SIZE;
712 if (grh->ipoib_vertcflow) {
713 /*
714 * First, copy source address from grh.
715 */
716 mact = (ipoib_mac_t *)pktinfo->shost;
717 mac_copy(&grh->ipoib_sqpn, &mact->ipoib_qpn,
718 IPOIB_ADDRL);
719
720 /*
721 * Then copy destination address from grh;
722 * first, the 16 bytes of GID.
723 */
724 mact = (ipoib_mac_t *)pktinfo->dhost;
725 mac_copy(&grh->ipoib_dgid_pref,
726 &mact->ipoib_gidpref, IPOIB_ADDRL -
727 sizeof (mact->ipoib_qpn));
728 tact = (ipoib_mac_t *)mac_pvt->curr_macaddr;
729
730 /* Is this a multicast address */
731 if (*(uchar_t *)(grh->ipoib_dgid_pref) == 0xFF) {
732 /*
733 * Only check for hardware looping in
734 * multicast case. It is assumed higher
735 * layer code (IP) will stop unicast loops;
736 * ie will prevent a transmit to self.
737 */
738 if (bcmp(&grh->ipoib_sqpn, tact,
739 IPOIB_ADDRL) == 0)
740 pktinfo->isLooped = 1;
741
742 tact = (ipoib_mac_t *)macinfo->
743 gldm_broadcast_addr;
744 if (mac_eq(tact->ipoib_gidpref,
745 grh->ipoib_dgid_pref,
746 IPOIB_ADDRL - sizeof (tact->ipoib_qpn)))
747 pktinfo->isBroadcast = 1;
748 else
749 pktinfo->isMulticast = 1;
750 /*
751 * Now copy the 4 bytes QPN part of the
752 * destination address.
753 */
754 dqpn = htonl(IB_MC_QPN);
755 mac_copy(&dqpn, &mact->ipoib_qpn,
756 sizeof (mact->ipoib_qpn));
757 } else {
758 /*
759 * Now copy the 4 bytes QPN part of the
760 * destination address.
761 */
762 mac_copy(&tact->ipoib_qpn, &mact->ipoib_qpn,
763 sizeof (mact->ipoib_qpn));
764 /*
765 * Any unicast packets received on IBA are
766 * for the node.
767 */
768 pktinfo->isForMe = 1;
769 }
770 } else {
771 /*
772 * It can not be a IBA multicast packet.
773 * Must have been unicast to us. We do not
774 * have shost information, which is used in
775 * gld_addudind(); IP/ARP does not care.
776 */
777 pktinfo->nosource = 1;
778 mac_copy(mac_pvt->curr_macaddr, pktinfo->dhost,
779 IPOIB_ADDRL);
780 /*
781 * Any unicast packets received on IBA are
782 * for the node.
783 */
784 pktinfo->isForMe = 1;
785 }
786 }
787
788 ASSERT((flags == GLD_RX) || (flags == GLD_RXLOOP));
789 ASSERT(GLDM_LOCK_HELD(macinfo));
790 pktinfo->ethertype = REF_NET_USHORT(((ipoib_hdr_t *)
791 (mp->b_rptr))->ipoib_type);
792 pktinfo->macLen = IPOIB_HDRSIZE;
793
794 out:
795 if (pmp != NULL)
796 freemsg(pmp);
797
798 return (0);
799 }
800
801 /*
802 * The packet format sent to the driver is: 2b sap :: 2b 0s :: data
803 */
804 void
805 gld_interpret_mdt_ib(gld_mac_info_t *macinfo, mblk_t *mp, pdescinfo_t *pinfo,
806 pktinfo_t *pktinfo, mdt_packet_flag_t flags)
807 {
808 gld_mac_pvt_t *mac_pvt;
809 multidata_t *dlmdp;
810 pattrinfo_t attr_info = { PATTR_DSTADDRSAP, };
811 pattr_t *patr;
812 ipoib_ptxhdr_t *dlap = NULL;
813
814 /*
815 * Per packet formatting.
816 */
817 if (flags == GLD_MDT_TXPKT) {
818 ipoib_hdr_t *hptr;
819 uint_t seg;
820
821 if (PDESC_HDRL(pinfo) == 0)
822 return;
823
824 /*
825 * Update packet's link header.
826 */
827 pinfo->hdr_rptr -= IPOIB_HDRSIZE;
828 hptr = (ipoib_hdr_t *)pinfo->hdr_rptr;
829 hptr->ipoib_mbz = htons(0);
830 hptr->ipoib_type = pktinfo->ethertype;
831
832 /*
833 * Total #bytes that will be put on wire.
834 */
835 pktinfo->pktLen = PDESC_HDRL(pinfo);
836 for (seg = 0; seg < pinfo->pld_cnt; seg++)
837 pktinfo->pktLen += PDESC_PLDL(pinfo, seg);
838
839 return;
840 }
841
842 /*
843 * The following two cases of GLD_MDT_TX and GLD_MDT_RXLOOP are per
844 * MDT message processing.
845 */
846 dlmdp = mmd_getmultidata(mp);
847 patr = mmd_getpattr(dlmdp, NULL, &attr_info);
848 ASSERT(patr != NULL);
849 ASSERT(macinfo->gldm_saplen == -2);
850 if (patr != NULL)
851 dlap = (ipoib_ptxhdr_t *)((pattr_addr_t *)attr_info.buf)->addr;
852
853 if (flags == GLD_MDT_TX) {
854 bzero((void *)pktinfo, sizeof (*pktinfo));
855 if (dlap == NULL)
856 return;
857
858 /*
859 * Check if mac is broadcast or multicast address; all these
860 * types of address have the top 4 bytes as 0x00FFFFFF.
861 */
862 if (mac_eq(dlap, macinfo->gldm_broadcast_addr,
863 sizeof (uint32_t))) {
864 if (mac_eq(dlap, macinfo->gldm_broadcast_addr,
865 IPOIB_ADDRL))
866 pktinfo->isBroadcast = 1;
867 else
868 pktinfo->isMulticast = 1;
869 }
870 pktinfo->ethertype = REF_NET_USHORT(dlap->
871 ipoib_rhdr.ipoib_type);
872 } else {
873 ASSERT(flags == GLD_MDT_RXLOOP);
874 pktinfo->macLen = IPOIB_HDRSIZE;
875 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
876 mac_copy(mac_pvt->curr_macaddr, pktinfo->shost, IPOIB_ADDRL);
877 if (dlap == NULL)
878 return;
879 mac_copy(&dlap->ipoib_dest, pktinfo->dhost, IPOIB_ADDRL);
880 }
881 }
882
883 mblk_t *
884 gld_unitdata_ib(gld_t *gld, mblk_t *mp)
885 {
886 gld_mac_info_t *macinfo = gld->gld_mac_info;
887 dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_rptr;
888 ipoib_ptxhdr_t *gldp = IPOIBDLSAP(dlp, dlp->dl_dest_addr_offset);
889 ipoib_mac_t dhost;
890 unsigned short type;
891 mblk_t *nmp;
892 int hdrlen;
893
894 ASSERT(macinfo != NULL);
895
896 /* extract needed info from the mblk before we maybe reuse it */
897 mac_copy(&gldp->ipoib_dest, &dhost, IPOIB_ADDRL);
898
899 /* look in the unitdata request for a sap, else use bound one */
900 if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
901 REF_HOST_USHORT(gldp->ipoib_rhdr.ipoib_type) != 0)
902 type = REF_HOST_USHORT(gldp->ipoib_rhdr.ipoib_type);
903 else
904 type = gld->gld_sap;
905
906 hdrlen = sizeof (ipoib_ptxhdr_t);
907
908 /* need a buffer big enough for the headers */
909 nmp = mp->b_cont; /* where the packet payload M_DATA is */
910 if (DB_REF(nmp) == 1 && MBLKHEAD(nmp) >= hdrlen) {
911 /* it fits at the beginning of the first M_DATA block */
912 freeb(mp); /* don't need the M_PROTO anymore */
913 } else if (DB_REF(mp) == 1 && MBLKSIZE(mp) >= hdrlen) {
914 /* we can reuse the dl_unitdata_req M_PROTO mblk */
915 nmp = mp;
916 DB_TYPE(nmp) = M_DATA;
917 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
918 } else {
919 /* we need to allocate one */
920 if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
921 return (NULL);
922 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
923 linkb(nmp, mp->b_cont);
924 freeb(mp);
925 }
926
927 /* Got the space, now copy in the header components */
928
929 nmp->b_rptr -= sizeof (ipoib_ptxhdr_t);
930 gldp = (ipoib_ptxhdr_t *)nmp->b_rptr;
931 SET_NET_USHORT(gldp->ipoib_rhdr.ipoib_type, type);
932 gldp->ipoib_rhdr.ipoib_mbz = 0;
933 mac_copy(&dhost, &gldp->ipoib_dest, IPOIB_ADDRL);
934
935 return (nmp);
936 }
937
938 mblk_t *
939 gld_fastpath_ib(gld_t *gld, mblk_t *mp)
940 {
941 gld_mac_info_t *macinfo = gld->gld_mac_info;
942 dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
943 ipoib_ptxhdr_t *gldp = IPOIBDLSAP(dlp, dlp->dl_dest_addr_offset);
944 unsigned short type;
945 mblk_t *nmp;
946 ipoib_ptxhdr_t *tgldp;
947 int hdrlen;
948
949 ASSERT(macinfo != NULL);
950
951 /* look in the unitdata request for a sap, else use bound one */
952 if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
953 REF_HOST_USHORT(gldp->ipoib_rhdr.ipoib_type) != 0)
954 type = REF_HOST_USHORT(gldp->ipoib_rhdr.ipoib_type);
955 else
956 type = gld->gld_sap;
957
958 hdrlen = sizeof (ipoib_ptxhdr_t);
959
960 if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
961 return (NULL);
962
963 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
964
965 /* Got the space, now copy in the header components */
966
967 nmp->b_rptr -= sizeof (ipoib_ptxhdr_t);
968 tgldp = (ipoib_ptxhdr_t *)nmp->b_rptr;
969 tgldp->ipoib_rhdr.ipoib_type = htons(type);
970 tgldp->ipoib_rhdr.ipoib_mbz = 0;
971 mac_copy(&gldp->ipoib_dest, &tgldp->ipoib_dest, IPOIB_ADDRL);
972
973 return (nmp);
974 }
975
976 /* ==== */
977 /* FDDI */
978 /* ==== */
979
980 void
981 gld_init_fddi(gld_mac_info_t *macinfo)
982 {
983 struct gldkstats *sp =
984 ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->kstatp->ks_data;
985
986 /* Assumptions we make for this medium */
987 ASSERT(macinfo->gldm_type == DL_FDDI);
988 ASSERT(macinfo->gldm_addrlen == 6);
989 ASSERT(macinfo->gldm_saplen == -2);
990 #ifndef lint
991 ASSERT(sizeof (struct fddi_mac_frm) == 13);
992 ASSERT(sizeof (mac_addr_t) == 6);
993 #endif
994
995 /* Wire address format is bit reversed from canonical format */
996 macinfo->gldm_options |= GLDOPT_CANONICAL_ADDR;
997
998 kstat_named_init(&sp->glds_fddi_mac_error,
999 "mac_errors", KSTAT_DATA_UINT32);
1000 kstat_named_init(&sp->glds_fddi_mac_lost,
1001 "mac_lost_errors", KSTAT_DATA_UINT32);
1002 kstat_named_init(&sp->glds_fddi_mac_token,
1003 "mac_tokens", KSTAT_DATA_UINT32);
1004 kstat_named_init(&sp->glds_fddi_mac_tvx_expired,
1005 "mac_tvx_expired", KSTAT_DATA_UINT32);
1006 kstat_named_init(&sp->glds_fddi_mac_late,
1007 "mac_late", KSTAT_DATA_UINT32);
1008 kstat_named_init(&sp->glds_fddi_mac_ring_op,
1009 "mac_ring_ops", KSTAT_DATA_UINT32);
1010 }
1011
1012 /*ARGSUSED*/
1013 void
1014 gld_uninit_fddi(gld_mac_info_t *macinfo)
1015 {
1016 }
1017
1018 int
1019 gld_interpret_fddi(gld_mac_info_t *macinfo, mblk_t *mp, pktinfo_t *pktinfo,
1020 packet_flag_t flags)
1021 {
1022 struct fddi_mac_frm *mh;
1023 gld_mac_pvt_t *mac_pvt;
1024 struct llc_snap_hdr *snaphdr;
1025 mblk_t *pmp = NULL;
1026
1027 /*
1028 * Quickly handle receive fastpath; FDDI does not support IPQ hack.
1029 */
1030 if (flags == GLD_RXQUICK) {
1031 pktinfo->pktLen = msgdsize(mp);
1032 return (-1);
1033 }
1034
1035 bzero((void *)pktinfo, sizeof (*pktinfo));
1036
1037 pktinfo->pktLen = msgdsize(mp);
1038
1039 /* make sure packet has at least a whole mac header */
1040 if (pktinfo->pktLen < sizeof (struct fddi_mac_frm))
1041 return (-1);
1042
1043 /* make sure the mac header falls into contiguous memory */
1044 if (MBLKL(mp) < sizeof (struct fddi_mac_frm)) {
1045 if ((pmp = msgpullup(mp, -1)) == NULL) {
1046 #ifdef GLD_DEBUG
1047 if (gld_debug & GLDERRS)
1048 cmn_err(CE_WARN,
1049 "GLD: interpret_fddi cannot msgpullup");
1050 #endif
1051 return (-1);
1052 }
1053 mp = pmp; /* this mblk contains the whole mac header */
1054 }
1055
1056 mh = (struct fddi_mac_frm *)mp->b_rptr;
1057
1058 /* Check to see if the mac is a broadcast or multicast address. */
1059 /* NB we are still in wire format (non canonical) */
1060 /* mac_eq works because ether_broadcast is the same either way */
1061 if (mac_eq(mh->fddi_dhost, ether_broadcast, macinfo->gldm_addrlen))
1062 pktinfo->isBroadcast = 1;
1063 else if (mh->fddi_dhost[0] & 0x80)
1064 pktinfo->isMulticast = 1;
1065
1066 if (flags == GLD_TX)
1067 goto out; /* Got all info we need for xmit case */
1068
1069 ASSERT(GLDM_LOCK_HELD(macinfo));
1070
1071 /*
1072 * Deal with the mac header
1073 */
1074
1075 cmac_copy(mh->fddi_dhost, pktinfo->dhost,
1076 macinfo->gldm_addrlen, macinfo);
1077 cmac_copy(mh->fddi_shost, pktinfo->shost,
1078 macinfo->gldm_addrlen, macinfo);
1079
1080 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
1081 pktinfo->isLooped = mac_eq(pktinfo->shost,
1082 mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
1083 pktinfo->isForMe = mac_eq(pktinfo->dhost,
1084 mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
1085
1086 pktinfo->macLen = sizeof (struct fddi_mac_frm);
1087
1088 /*
1089 * Before trying to look beyond the MAC header, make sure the LLC
1090 * header exists, and that both it and any SNAP header are contiguous.
1091 */
1092 if (MBLKL(mp) < sizeof (struct fddi_mac_frm) + LLC_SNAP_HDR_LEN &&
1093 MBLKL(mp) < pktinfo->pktLen) {
1094 /*
1095 * we don't have the entire packet within the first mblk (and
1096 * therefore we didn't do the msgpullup above), AND the first
1097 * mblk may not contain all the data we need to look at.
1098 */
1099 ASSERT(pmp == NULL); /* couldn't have done msgpullup above */
1100 if ((pmp = msgpullup(mp, -1)) == NULL) {
1101 #ifdef GLD_DEBUG
1102 if (gld_debug & GLDERRS)
1103 cmn_err(CE_WARN,
1104 "GLD: interpret_fddi cannot msgpullup2");
1105 #endif
1106 goto out; /* can't interpret this pkt further */
1107 }
1108 mp = pmp; /* this mblk should contain everything needed */
1109 }
1110
1111 /*
1112 * Check SAP/SNAP information.
1113 */
1114 if ((mh->fddi_fc & 0x70) == 0x50) {
1115 if (pktinfo->pktLen < pktinfo->macLen + LLC_HDR1_LEN)
1116 goto out;
1117
1118 pktinfo->isLLC = 1;
1119
1120 if (pktinfo->pktLen < pktinfo->macLen + LLC_SNAP_HDR_LEN)
1121 goto out;
1122
1123 snaphdr = (struct llc_snap_hdr *)(mp->b_rptr + pktinfo->macLen);
1124 if (ISETHERTYPE(snaphdr)) {
1125 pktinfo->ethertype = REF_NET_USHORT(snaphdr->type);
1126 pktinfo->hdrLen = LLC_SNAP_HDR_LEN;
1127 }
1128 }
1129 out:
1130 if (pmp != NULL)
1131 freemsg(pmp);
1132
1133 return (0);
1134 }
1135
1136 mblk_t *
1137 gld_unitdata_fddi(gld_t *gld, mblk_t *mp)
1138 {
1139 gld_mac_info_t *macinfo = gld->gld_mac_info;
1140 dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_rptr;
1141 struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
1142 mac_addr_t dhost;
1143 unsigned short type;
1144 mblk_t *nmp;
1145 struct fddi_mac_frm *mh;
1146 int hdrlen;
1147
1148 ASSERT(macinfo);
1149
1150 /* extract needed info from the mblk before we maybe reuse it */
1151 mac_copy(gldp->glda_addr, dhost, macinfo->gldm_addrlen);
1152
1153 /* look in the unitdata request for a sap, else use bound one */
1154 if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
1155 REF_HOST_USHORT(gldp->glda_sap) != 0)
1156 type = REF_HOST_USHORT(gldp->glda_sap);
1157 else
1158 type = gld->gld_sap;
1159
1160
1161 hdrlen = sizeof (struct fddi_mac_frm);
1162
1163 /*
1164 * Check whether we need to do EtherType encoding or whether the packet
1165 * is LLC.
1166 */
1167 if (type > GLD_MAX_802_SAP)
1168 hdrlen += sizeof (struct llc_snap_hdr);
1169
1170 /* need a buffer big enough for the headers */
1171 nmp = mp->b_cont; /* where the packet payload M_DATA is */
1172 if (DB_REF(nmp) == 1 && MBLKHEAD(nmp) >= hdrlen) {
1173 /* it fits at the beginning of the first M_DATA block */
1174 freeb(mp); /* don't need the M_PROTO anymore */
1175 } else if (DB_REF(mp) == 1 && MBLKSIZE(mp) >= hdrlen) {
1176 /* we can reuse the dl_unitdata_req M_PROTO mblk */
1177 nmp = mp;
1178 DB_TYPE(nmp) = M_DATA;
1179 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
1180 } else {
1181 /* we need to allocate one */
1182 if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
1183 return (NULL);
1184 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
1185 linkb(nmp, mp->b_cont);
1186 freeb(mp);
1187 }
1188
1189
1190 /* Got the space, now copy in the header components */
1191 if (type > GLD_MAX_802_SAP) {
1192 /* create the snap header */
1193 struct llc_snap_hdr *snap;
1194 nmp->b_rptr -= sizeof (struct llc_snap_hdr);
1195 snap = (struct llc_snap_hdr *)(nmp->b_rptr);
1196 *snap = llc_snap_def;
1197 SET_NET_USHORT(snap->type, type);
1198 }
1199
1200 nmp->b_rptr -= sizeof (struct fddi_mac_frm);
1201
1202 mh = (struct fddi_mac_frm *)nmp->b_rptr;
1203
1204 mh->fddi_fc = 0x50;
1205 cmac_copy(dhost, mh->fddi_dhost, macinfo->gldm_addrlen, macinfo);
1206
1207 /*
1208 * We access the mac address without the mutex to prevent
1209 * mutex contention (BUG 4211361)
1210 */
1211 cmac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
1212 mh->fddi_shost, macinfo->gldm_addrlen, macinfo);
1213 return (nmp);
1214 }
1215
1216 mblk_t *
1217 gld_fastpath_fddi(gld_t *gld, mblk_t *mp)
1218 {
1219 gld_mac_info_t *macinfo = gld->gld_mac_info;
1220 dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
1221 struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
1222 unsigned short type;
1223 mblk_t *nmp;
1224 struct fddi_mac_frm *mh;
1225 int hdrlen;
1226
1227 ASSERT(macinfo);
1228
1229 /* look in the unitdata request for a sap, else use bound one */
1230 if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
1231 REF_HOST_USHORT(gldp->glda_sap) != 0)
1232 type = REF_HOST_USHORT(gldp->glda_sap);
1233 else
1234 type = gld->gld_sap;
1235
1236 hdrlen = sizeof (struct fddi_mac_frm);
1237
1238 /*
1239 * Check whether we need to do EtherType encoding or whether the packet
1240 * will be LLC.
1241 */
1242 if (type > GLD_MAX_802_SAP)
1243 hdrlen += sizeof (struct llc_snap_hdr);
1244
1245 if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
1246 return (NULL);
1247
1248 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
1249
1250 /* Got the space, now copy in the header components */
1251
1252 if (type > GLD_MAX_802_SAP) {
1253 /* create the snap header */
1254 struct llc_snap_hdr *snap;
1255 nmp->b_rptr -= sizeof (struct llc_snap_hdr);
1256 snap = (struct llc_snap_hdr *)(nmp->b_rptr);
1257 *snap = llc_snap_def;
1258 snap->type = htons(type); /* we know it's aligned */
1259 }
1260
1261 nmp->b_rptr -= sizeof (struct fddi_mac_frm);
1262
1263 mh = (struct fddi_mac_frm *)nmp->b_rptr;
1264 mh->fddi_fc = 0x50;
1265 cmac_copy(gldp->glda_addr, mh->fddi_dhost,
1266 macinfo->gldm_addrlen, macinfo);
1267
1268 GLDM_LOCK(macinfo, RW_WRITER);
1269 cmac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
1270 mh->fddi_shost, macinfo->gldm_addrlen, macinfo);
1271 GLDM_UNLOCK(macinfo);
1272
1273 return (nmp);
1274 }
1275
1276 /* ========== */
1277 /* Token Ring */
1278 /* ========== */
1279
1280 #define GLD_SR_VAR(macinfo) \
1281 (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->data)
1282
1283 #define GLD_SR_HASH(macinfo) ((struct srtab **)GLD_SR_VAR(macinfo))
1284
1285 #define GLD_SR_MUTEX(macinfo) \
1286 (&((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->datalock)
1287
1288 static void gld_sr_clear(gld_mac_info_t *);
1289 static void gld_rcc_receive(gld_mac_info_t *, pktinfo_t *, struct gld_ri *,
1290 uchar_t *, int);
1291 static void gld_rcc_send(gld_mac_info_t *, queue_t *, uchar_t *,
1292 struct gld_ri **, uchar_t *);
1293
1294 static mac_addr_t tokenbroadcastaddr2 = { 0xc0, 0x00, 0xff, 0xff, 0xff, 0xff };
1295 static struct gld_ri ri_ste_def;
1296
1297 void
1298 gld_init_tr(gld_mac_info_t *macinfo)
1299 {
1300 struct gldkstats *sp =
1301 ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->kstatp->ks_data;
1302
1303 /* avoid endian-dependent code by initializing here instead of static */
1304 ri_ste_def.len = 2;
1305 ri_ste_def.rt = RT_STE;
1306 ri_ste_def.mtu = RT_MTU_MAX;
1307 ri_ste_def.dir = 0;
1308 ri_ste_def.res = 0;
1309
1310 /* Assumptions we make for this medium */
1311 ASSERT(macinfo->gldm_type == DL_TPR);
1312 ASSERT(macinfo->gldm_addrlen == 6);
1313 ASSERT(macinfo->gldm_saplen == -2);
1314 #ifndef lint
1315 ASSERT(sizeof (struct tr_mac_frm_nori) == 14);
1316 ASSERT(sizeof (mac_addr_t) == 6);
1317 #endif
1318
1319 mutex_init(GLD_SR_MUTEX(macinfo), NULL, MUTEX_DRIVER, NULL);
1320
1321 GLD_SR_VAR(macinfo) = kmem_zalloc(sizeof (struct srtab *)*SR_HASH_SIZE,
1322 KM_SLEEP);
1323
1324 /* Default is RDE enabled for this medium */
1325 ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_enabled =
1326 ddi_getprop(DDI_DEV_T_NONE, macinfo->gldm_devinfo, 0,
1327 "gld_rde_enable", 1);
1328
1329 /*
1330 * Default is to use STE for unknown paths if RDE is enabled.
1331 * If RDE is disabled, default is to use NULL RIF fields.
1332 *
1333 * It's possible to force use of STE for ALL packets:
1334 * disable RDE but enable STE. This may be useful for
1335 * non-transparent bridges, when it is not desired to run
1336 * the RDE algorithms.
1337 */
1338 ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_str_indicator_ste =
1339 ddi_getprop(DDI_DEV_T_NONE, macinfo->gldm_devinfo, 0,
1340 "gld_rde_str_indicator_ste",
1341 ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_enabled);
1342
1343 /* Default 10 second route timeout on lack of activity */
1344 {
1345 int t = ddi_getprop(DDI_DEV_T_NONE, macinfo->gldm_devinfo, 0,
1346 "gld_rde_timeout", 10);
1347 if (t < 1)
1348 t = 1; /* Let's be reasonable */
1349 if (t > 600)
1350 t = 600; /* Let's be reasonable */
1351 /* We're using ticks (lbolts) for our timeout -- convert from seconds */
1352 t = drv_usectohz(1000000 * t);
1353 ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_timeout = t;
1354 }
1355
1356 kstat_named_init(&sp->glds_dot5_line_error,
1357 "line_errors", KSTAT_DATA_UINT32);
1358 kstat_named_init(&sp->glds_dot5_burst_error,
1359 "burst_errors", KSTAT_DATA_UINT32);
1360 kstat_named_init(&sp->glds_dot5_signal_loss,
1361 "signal_losses", KSTAT_DATA_UINT32);
1362
1363 /*
1364 * only initialize the new statistics if the driver
1365 * knows about them.
1366 */
1367 if (macinfo->gldm_driver_version != GLD_VERSION_200)
1368 return;
1369
1370 kstat_named_init(&sp->glds_dot5_ace_error,
1371 "ace_errors", KSTAT_DATA_UINT32);
1372 kstat_named_init(&sp->glds_dot5_internal_error,
1373 "internal_errors", KSTAT_DATA_UINT32);
1374 kstat_named_init(&sp->glds_dot5_lost_frame_error,
1375 "lost_frame_errors", KSTAT_DATA_UINT32);
1376 kstat_named_init(&sp->glds_dot5_frame_copied_error,
1377 "frame_copied_errors", KSTAT_DATA_UINT32);
1378 kstat_named_init(&sp->glds_dot5_token_error,
1379 "token_errors", KSTAT_DATA_UINT32);
1380 kstat_named_init(&sp->glds_dot5_freq_error,
1381 "freq_errors", KSTAT_DATA_UINT32);
1382 }
1383
1384 void
1385 gld_uninit_tr(gld_mac_info_t *macinfo)
1386 {
1387 mutex_destroy(GLD_SR_MUTEX(macinfo));
1388 gld_sr_clear(macinfo);
1389 kmem_free(GLD_SR_VAR(macinfo), sizeof (struct srtab *) * SR_HASH_SIZE);
1390 }
1391
1392 int
1393 gld_interpret_tr(gld_mac_info_t *macinfo, mblk_t *mp, pktinfo_t *pktinfo,
1394 packet_flag_t flags)
1395 {
1396 struct tr_mac_frm *mh;
1397 gld_mac_pvt_t *mac_pvt;
1398 struct llc_snap_hdr *snaphdr;
1399 mblk_t *pmp = NULL;
1400 struct gld_ri *rh;
1401
1402 /*
1403 * Quickly handle receive fastpath; TR does not support IPQ hack.
1404 */
1405 if (flags == GLD_RXQUICK) {
1406 pktinfo->pktLen = msgdsize(mp);
1407 return (-1);
1408 }
1409
1410 bzero((void *)pktinfo, sizeof (*pktinfo));
1411
1412 pktinfo->pktLen = msgdsize(mp);
1413
1414 /* make sure packet has at least a whole mac header */
1415 if (pktinfo->pktLen < sizeof (struct tr_mac_frm_nori))
1416 return (-1);
1417
1418 /* make sure the mac header falls into contiguous memory */
1419 if (MBLKL(mp) < sizeof (struct tr_mac_frm_nori)) {
1420 if ((pmp = msgpullup(mp, -1)) == NULL) {
1421 #ifdef GLD_DEBUG
1422 if (gld_debug & GLDERRS)
1423 cmn_err(CE_WARN,
1424 "GLD: interpret_tr cannot msgpullup");
1425 #endif
1426 return (-1);
1427 }
1428 mp = pmp; /* this mblk contains the whole mac header */
1429 }
1430
1431 mh = (struct tr_mac_frm *)mp->b_rptr;
1432
1433 /* Check to see if the mac is a broadcast or multicast address. */
1434 if (mac_eq(mh->tr_dhost, ether_broadcast, macinfo->gldm_addrlen) ||
1435 mac_eq(mh->tr_dhost, tokenbroadcastaddr2, macinfo->gldm_addrlen))
1436 pktinfo->isBroadcast = 1;
1437 else if (mh->tr_dhost[0] & 0x80)
1438 pktinfo->isMulticast = 1;
1439
1440 if (flags == GLD_TX)
1441 goto out; /* Got all info we need for xmit case */
1442
1443 ASSERT(GLDM_LOCK_HELD(macinfo));
1444
1445 /*
1446 * Deal with the mac header
1447 */
1448
1449 mac_copy(mh->tr_dhost, pktinfo->dhost, macinfo->gldm_addrlen);
1450 mac_copy(mh->tr_shost, pktinfo->shost, macinfo->gldm_addrlen);
1451 pktinfo->shost[0] &= ~0x80; /* turn off RIF indicator */
1452
1453 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
1454 pktinfo->isLooped = mac_eq(pktinfo->shost,
1455 mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
1456 pktinfo->isForMe = mac_eq(pktinfo->dhost,
1457 mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
1458
1459 rh = (struct gld_ri *)NULL;
1460 pktinfo->macLen = sizeof (struct tr_mac_frm_nori);
1461
1462 /*
1463 * Before trying to look beyond the MAC header, make sure the data
1464 * structures are all contiguously where we can conveniently look at
1465 * them. We'll use a worst-case estimate of how many bytes into the
1466 * packet data we'll be needing to look. Things will be more efficient
1467 * if the driver puts at least this much into the first mblk.
1468 *
1469 * Even after this, we still will have to do checks against the total
1470 * length of the packet. A bad incoming packet may not hold all the
1471 * data structures it says it does.
1472 */
1473 if (MBLKL(mp) < sizeof (struct tr_mac_frm) +
1474 LLC_HDR1_LEN + sizeof (struct rde_pdu) &&
1475 MBLKL(mp) < pktinfo->pktLen) {
1476 /*
1477 * we don't have the entire packet within the first mblk (and
1478 * therefore we didn't do the msgpullup above), AND the first
1479 * mblk may not contain all the data we need to look at.
1480 */
1481 ASSERT(pmp == NULL); /* couldn't have done msgpullup above */
1482 if ((pmp = msgpullup(mp, -1)) == NULL) {
1483 #ifdef GLD_DEBUG
1484 if (gld_debug & GLDERRS)
1485 cmn_err(CE_WARN,
1486 "GLD: interpret_tr cannot msgpullup2");
1487 #endif
1488 goto out; /* can't interpret this pkt further */
1489 }
1490 mp = pmp; /* this mblk should contain everything needed */
1491 mh = (struct tr_mac_frm *)mp->b_rptr; /* to look at RIF */
1492 }
1493
1494 if (mh->tr_shost[0] & 0x80) {
1495 /* Routing Information Field (RIF) is present */
1496 if (pktinfo->pktLen < sizeof (struct tr_mac_frm_nori) + 2)
1497 goto out; /* RIF should have been there! */
1498 rh = (struct gld_ri *)&mh->tr_ri;
1499 if ((rh->len & 1) || rh->len < 2) {
1500 /* Bogus RIF, don't handle this packet */
1501 #ifdef GLD_DEBUG
1502 if (gld_debug & GLDERRS)
1503 cmn_err(CE_WARN,
1504 "GLD: received TR packet with "
1505 "bogus RIF length %d",
1506 rh->len);
1507 #endif
1508 goto out;
1509 }
1510 if (pktinfo->pktLen < sizeof (struct tr_mac_frm_nori) + rh->len)
1511 goto out; /* RIF should have been there! */
1512 pktinfo->macLen += rh->len;
1513 }
1514
1515 if ((mh->tr_fc & 0xc0) == 0x40) {
1516 if (pktinfo->pktLen < pktinfo->macLen + LLC_HDR1_LEN)
1517 goto out;
1518
1519 pktinfo->isLLC = 1;
1520
1521 if (pktinfo->pktLen < pktinfo->macLen + LLC_SNAP_HDR_LEN)
1522 goto out;
1523
1524 snaphdr = (struct llc_snap_hdr *)(mp->b_rptr + pktinfo->macLen);
1525 if (ISETHERTYPE(snaphdr)) {
1526 pktinfo->ethertype = REF_NET_USHORT(snaphdr->type);
1527 pktinfo->hdrLen = LLC_SNAP_HDR_LEN;
1528 }
1529
1530 /* Inform the Route Control Component of received LLC frame */
1531 gld_rcc_receive(macinfo, pktinfo, rh,
1532 mp->b_rptr + pktinfo->macLen,
1533 pktinfo->pktLen - pktinfo->macLen);
1534 }
1535 out:
1536 if (pmp != NULL)
1537 freemsg(pmp);
1538
1539 return (0);
1540 }
1541
1542 mblk_t *
1543 gld_unitdata_tr(gld_t *gld, mblk_t *mp)
1544 {
1545 gld_mac_info_t *macinfo = gld->gld_mac_info;
1546 dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_rptr;
1547 struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
1548 mac_addr_t dhost;
1549 unsigned short type;
1550 mblk_t *nmp, *llcmp, *pmp = NULL;
1551 struct tr_mac_frm_nori *mh;
1552 int hdrlen;
1553 struct gld_ri *rh;
1554
1555 ASSERT(macinfo);
1556
1557 /* extract needed info from the mblk before we maybe reuse it */
1558 mac_copy(gldp->glda_addr, dhost, macinfo->gldm_addrlen);
1559
1560 /* look in the unitdata request for a sap, else use bound one */
1561 if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
1562 REF_HOST_USHORT(gldp->glda_sap) != 0)
1563 type = REF_HOST_USHORT(gldp->glda_sap);
1564 else
1565 type = gld->gld_sap;
1566
1567 /* includes maximum possible Routing Information Field (RIF) size */
1568 hdrlen = sizeof (struct tr_mac_frm);
1569
1570 /*
1571 * Check whether we need to do EtherType encoding or whether the packet
1572 * is LLC.
1573 */
1574 if (type > GLD_MAX_802_SAP)
1575 hdrlen += sizeof (struct llc_snap_hdr);
1576
1577 /* need a buffer big enough for the headers */
1578 llcmp = nmp = mp->b_cont; /* where the packet payload M_DATA is */
1579
1580 /*
1581 * We are going to need to look at the LLC header, so make sure it
1582 * is contiguously in a single mblk. If we're the ones who create
1583 * the LLC header (below, in the case where sap > 0xff) then we don't
1584 * have to worry about it here.
1585 */
1586 ASSERT(nmp != NULL); /* gld_unitdata guarantees msgdsize > 0 */
1587 if (type <= GLD_MAX_802_SAP) {
1588 if (MBLKL(llcmp) < LLC_HDR1_LEN) {
1589 llcmp = pmp = msgpullup(nmp, LLC_HDR1_LEN);
1590 if (pmp == NULL) {
1591 #ifdef GLD_DEBUG
1592 if (gld_debug & GLDERRS)
1593 cmn_err(CE_WARN,
1594 "GLD: unitdata_tr "
1595 "cannot msgpullup");
1596 #endif
1597 return (NULL);
1598 }
1599 }
1600 }
1601
1602 if (DB_REF(nmp) == 1 && MBLKHEAD(nmp) >= hdrlen) {
1603 /* it fits at the beginning of the first M_DATA block */
1604 freeb(mp); /* don't need the M_PROTO anymore */
1605 } else if (DB_REF(mp) == 1 && MBLKSIZE(mp) >= hdrlen) {
1606 /* we can reuse the dl_unitdata_req M_PROTO mblk */
1607 nmp = mp;
1608 DB_TYPE(nmp) = M_DATA;
1609 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
1610 } else {
1611 /* we need to allocate one */
1612 if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL) {
1613 if (pmp != NULL)
1614 freemsg(pmp);
1615 return (NULL);
1616 }
1617 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
1618 linkb(nmp, mp->b_cont);
1619 freeb(mp);
1620 }
1621
1622 /* Got the space, now copy in the header components */
1623 if (type > GLD_MAX_802_SAP) {
1624 /* create the snap header */
1625 struct llc_snap_hdr *snap;
1626 llcmp = nmp; /* LLC header is going to be in this mblk */
1627 nmp->b_rptr -= sizeof (struct llc_snap_hdr);
1628 snap = (struct llc_snap_hdr *)(nmp->b_rptr);
1629 *snap = llc_snap_def;
1630 SET_NET_USHORT(snap->type, type);
1631 }
1632
1633 /* Hold SR tables still while we maybe point at an entry */
1634 mutex_enter(GLD_SR_MUTEX(macinfo));
1635
1636 gld_rcc_send(macinfo, WR(gld->gld_qptr), dhost, &rh, llcmp->b_rptr);
1637
1638 if (rh != NULL) {
1639 /* copy in the RIF */
1640 ASSERT(rh->len <= sizeof (struct gld_ri));
1641 nmp->b_rptr -= rh->len;
1642 bcopy((caddr_t)rh, (caddr_t)nmp->b_rptr, rh->len);
1643 }
1644
1645 mutex_exit(GLD_SR_MUTEX(macinfo));
1646
1647 /* no longer need the pulled-up mblk */
1648 if (pmp != NULL)
1649 freemsg(pmp);
1650
1651 /*
1652 * fill in token ring header
1653 */
1654 nmp->b_rptr -= sizeof (struct tr_mac_frm_nori);
1655 mh = (struct tr_mac_frm_nori *)nmp->b_rptr;
1656 mh->tr_ac = 0x10;
1657 mh->tr_fc = 0x40;
1658 mac_copy(dhost, mh->tr_dhost, macinfo->gldm_addrlen);
1659
1660 /*
1661 * We access the mac address without the mutex to prevent
1662 * mutex contention (BUG 4211361)
1663 */
1664 mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
1665 mh->tr_shost, macinfo->gldm_addrlen);
1666
1667 if (rh != NULL)
1668 mh->tr_shost[0] |= 0x80;
1669 else
1670 mh->tr_shost[0] &= ~0x80;
1671
1672 return (nmp);
1673 }
1674
1675 /*
1676 * We cannot have our client sending us "fastpath" M_DATA messages,
1677 * because to do that we must provide to him a fixed MAC header to
1678 * be prepended to each outgoing packet. But with Source Routing
1679 * media, the length and content of the MAC header changes as the
1680 * routes change, so there is no fixed header we can provide. So
1681 * we decline to accept M_DATA messages if Source Routing is enabled.
1682 */
1683 mblk_t *
1684 gld_fastpath_tr(gld_t *gld, mblk_t *mp)
1685 {
1686 gld_mac_info_t *macinfo = gld->gld_mac_info;
1687 dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
1688 struct gld_dlsap *gldp = DLSAP(dlp, dlp->dl_dest_addr_offset);
1689 unsigned short type;
1690 mblk_t *nmp;
1691 struct tr_mac_frm_nori *mh;
1692 int hdrlen;
1693
1694 ASSERT(macinfo);
1695
1696 /*
1697 * If we are doing Source Routing, then we cannot provide a fixed
1698 * MAC header, so fail.
1699 */
1700 if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_enabled)
1701 return (NULL);
1702
1703 /* look in the unitdata request for a sap, else use bound one */
1704 if (dlp->dl_dest_addr_length >= DLSAPLENGTH(macinfo) &&
1705 REF_HOST_USHORT(gldp->glda_sap) != 0)
1706 type = REF_HOST_USHORT(gldp->glda_sap);
1707 else
1708 type = gld->gld_sap;
1709
1710 hdrlen = sizeof (struct tr_mac_frm_nori);
1711
1712 if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_str_indicator_ste)
1713 hdrlen += ri_ste_def.len;
1714
1715 /*
1716 * Check whether we need to do EtherType encoding or whether the packet
1717 * will be LLC.
1718 */
1719 if (type > GLD_MAX_802_SAP)
1720 hdrlen += sizeof (struct llc_snap_hdr);
1721
1722 if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL)
1723 return (NULL);
1724
1725 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
1726
1727 /* Got the space, now copy in the header components */
1728
1729 if (type > GLD_MAX_802_SAP) {
1730 /* create the snap header */
1731 struct llc_snap_hdr *snap;
1732 nmp->b_rptr -= sizeof (struct llc_snap_hdr);
1733 snap = (struct llc_snap_hdr *)(nmp->b_rptr);
1734 *snap = llc_snap_def;
1735 snap->type = htons(type); /* we know it's aligned */
1736 }
1737
1738 /* RDE is disabled, use NULL RIF, or STE RIF */
1739 if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_str_indicator_ste) {
1740 nmp->b_rptr -= ri_ste_def.len;
1741 bcopy((caddr_t)&ri_ste_def, (caddr_t)nmp->b_rptr,
1742 ri_ste_def.len);
1743 }
1744
1745 /*
1746 * fill in token ring header
1747 */
1748 nmp->b_rptr -= sizeof (struct tr_mac_frm_nori);
1749 mh = (struct tr_mac_frm_nori *)nmp->b_rptr;
1750 mh->tr_ac = 0x10;
1751 mh->tr_fc = 0x40;
1752 mac_copy(gldp->glda_addr, mh->tr_dhost, macinfo->gldm_addrlen);
1753
1754 GLDM_LOCK(macinfo, RW_WRITER);
1755 mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
1756 mh->tr_shost, macinfo->gldm_addrlen);
1757 GLDM_UNLOCK(macinfo);
1758
1759 if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_str_indicator_ste)
1760 mh->tr_shost[0] |= 0x80;
1761 else
1762 mh->tr_shost[0] &= ~0x80;
1763
1764 return (nmp);
1765 }
1766
1767 /*
1768 * Route Determination Entity (ISO 8802-2 / IEEE 802.2 : 1994, Section 9)
1769 *
1770 * RDE is an LLC layer entity. GLD is a MAC layer entity. The proper
1771 * solution to this architectural anomaly is to move RDE support out of GLD
1772 * and into LLC where it belongs. In particular, only LLC has the knowledge
1773 * necessary to reply to XID and TEST packets. If and when it comes time to
1774 * move RDE out of GLD to LLC, the LLC-to-GLD interface should be modified
1775 * to use MA_UNITDATA structures rather than DL_UNITDATA structures. Of
1776 * course, GLD will still have to continue to also support the DL_ structures
1777 * as long as IP is not layered over LLC. Another, perhaps better, idea
1778 * would be to make RDE an autopush module on top of the token ring drivers:
1779 * RDE would sit between LLC and GLD. It would then also sit between IP and
1780 * GLD, providing services to all clients of GLD/tokenring. In that case,
1781 * GLD would still have to continue to support the DL_ interface for non-
1782 * Token Ring interfaces, using the MA_ interface only for media supporting
1783 * Source Routing media.
1784 *
1785 * At present, Token Ring is the only source routing medium we support.
1786 * Since Token Ring is not at this time a strategic network medium for Sun,
1787 * rather than devote a large amount of resources to creating a proper
1788 * architecture and implementation of RDE, we do the minimum necessary to
1789 * get it to work. The interface between the above token ring code and the
1790 * below RDE code is designed to make it relatively easy to change to an
1791 * MA_UNITDATA model later should this ever become a priority.
1792 */
1793
1794 static void gld_send_rqr(gld_mac_info_t *, uchar_t *, struct gld_ri *,
1795 struct rde_pdu *, int);
1796 static void gld_rde_pdu_req(gld_mac_info_t *, queue_t *, uchar_t *,
1797 struct gld_ri *, uchar_t, uchar_t, uchar_t);
1798 static void gld_get_route(gld_mac_info_t *, queue_t *, uchar_t *,
1799 struct gld_ri **, uchar_t, uchar_t);
1800 static void gld_reset_route(gld_mac_info_t *, queue_t *,
1801 uchar_t *, uchar_t, uchar_t);
1802 static void gld_rde_pdu_ind(gld_mac_info_t *, struct gld_ri *, struct rde_pdu *,
1803 int);
1804 static void gld_rif_ind(gld_mac_info_t *, struct gld_ri *, uchar_t *,
1805 uchar_t, uchar_t);
1806 static struct srtab **gld_sr_hash(struct srtab **, uchar_t *, int);
1807 static struct srtab *gld_sr_lookup_entry(gld_mac_info_t *, uchar_t *);
1808 static struct srtab *gld_sr_create_entry(gld_mac_info_t *, uchar_t *);
1809
1810 /*
1811 * This routine implements a modified subset of the 802.2 RDE RCC receive
1812 * actions:
1813 * we implement RCC receive events 3 to 12 (ISO 8802-2:1994 9.6.3.4);
1814 * we omit special handling for the NULL SAP;
1815 * we omit XID/TEST handling;
1816 * we pass all packets (including RDE) upstream to LLC.
1817 */
1818 static void
1819 gld_rcc_receive(gld_mac_info_t *macinfo, pktinfo_t *pktinfo, struct gld_ri *rh,
1820 uchar_t *llcpkt, int llcpktlen)
1821 {
1822 struct llc_snap_hdr *snaphdr = (struct llc_snap_hdr *)(llcpkt);
1823
1824 if (!((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_enabled)
1825 return;
1826
1827 /*
1828 * First, ensure this packet wasn't something we received just
1829 * because we were in promiscuous mode. Since none of the below
1830 * code wants to see group addressed packets anyway, we can do
1831 * this check up front. Since we're doing that, we can omit the
1832 * checks for group addressed packets below.
1833 */
1834 if (!pktinfo->isForMe)
1835 return; /* Event 6 */
1836
1837 /* Process a subset of Route Determination Entity (RDE) packets */
1838 if (snaphdr->d_lsap == LSAP_RDE) {
1839 struct rde_pdu *pdu = (struct rde_pdu *)(llcpkt + LLC_HDR1_LEN);
1840 int pdulen = llcpktlen - LLC_HDR1_LEN;
1841
1842 /* sanity check the PDU */
1843 if ((pdulen < sizeof (struct rde_pdu)) ||
1844 (snaphdr->s_lsap != LSAP_RDE))
1845 return;
1846
1847 /* we only handle route discovery PDUs, not XID/TEST/other */
1848 if (snaphdr->control != CNTL_LLC_UI)
1849 return;
1850
1851 switch (pdu->rde_ptype) {
1852 case RDE_RQC: /* Route Query Command; Events 8 - 11 */
1853 gld_send_rqr(macinfo, pktinfo->shost, rh, pdu, pdulen);
1854 /* FALLTHROUGH */
1855 case RDE_RQR: /* Route Query Response; Event 12 */
1856 case RDE_RS: /* Route Selected; Event 7 */
1857 gld_rde_pdu_ind(macinfo, rh, pdu, pdulen);
1858 break;
1859 default: /* ignore if unrecognized ptype */
1860 return;
1861 }
1862
1863 return;
1864 }
1865
1866 /* Consider routes seen in other IA SRF packets */
1867
1868 if (rh == NULL)
1869 return; /* no RIF; Event 3 */
1870
1871 if ((rh->rt & 0x04) != 0)
1872 return; /* not SRF; Event 5 */
1873
1874 gld_rif_ind(macinfo, rh, pktinfo->shost, snaphdr->s_lsap,
1875 snaphdr->d_lsap); /* Event 4 */
1876 }
1877
1878 /*
1879 * Send RQR: 802.2 9.6.3.4.2(9) RCC Receive Events 8-11
1880 *
1881 * The routing processing really doesn't belong here; it should be handled in
1882 * the LLC layer above. If that were the case then RDE could just send down
1883 * an extra MA_UNITDATA_REQ with the info needed to construct the packet. But
1884 * at the time we get control here, it's not a particularly good time to be
1885 * constructing packets and trying to send them. Specifically, at this layer
1886 * we need to construct the full media packet, which means the below routine
1887 * knows that it is dealing with Token Ring media. If this were instead done
1888 * via a proper MA_UNITDATA interface, the RDE stuff could all be completely
1889 * media independent. But since TR is the only source routing medium we
1890 * support, this works even though it is not clean.
1891 *
1892 * We "know" that the only time we can get here is from the "interpret"
1893 * routine, and only when it was called at receive time.
1894 */
1895 static void
1896 gld_send_rqr(gld_mac_info_t *macinfo, uchar_t *shost, struct gld_ri *rh,
1897 struct rde_pdu *pdu, int pdulen)
1898 {
1899 mblk_t *nmp;
1900 int nlen;
1901 struct tr_mac_frm_nori *nmh;
1902 struct gld_ri *nrh;
1903 struct llc_snap_hdr *nsnaphdr;
1904 struct rde_pdu *npdu;
1905
1906 /* We know and assume we're on the receive path */
1907 ASSERT(GLDM_LOCK_HELD(macinfo));
1908
1909 if (pdulen < sizeof (struct rde_pdu))
1910 return; /* Bad incoming PDU */
1911
1912 nlen = sizeof (struct tr_mac_frm) + LLC_HDR1_LEN +
1913 sizeof (struct rde_pdu);
1914
1915 if ((nmp = allocb(nlen, BPRI_MED)) == NULL)
1916 return;
1917
1918 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
1919
1920 nmp->b_rptr -= sizeof (struct rde_pdu);
1921 npdu = (struct rde_pdu *)(nmp->b_rptr);
1922 *npdu = *pdu; /* copy orig/target macaddr/saps */
1923 npdu->rde_ver = 1;
1924 npdu->rde_ptype = RDE_RQR;
1925 mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
1926 npdu->rde_target_mac, macinfo->gldm_addrlen);
1927
1928 nmp->b_rptr -= LLC_HDR1_LEN;
1929 nsnaphdr = (struct llc_snap_hdr *)(nmp->b_rptr);
1930 nsnaphdr->s_lsap = nsnaphdr->d_lsap = LSAP_RDE;
1931 nsnaphdr->control = CNTL_LLC_UI;
1932
1933 if (rh == NULL || (rh->rt & 0x06) == 0x06 ||
1934 rh->len > sizeof (struct gld_ri)) {
1935 /* no RIF (Event 8), or RIF type STE (Event 9): send ARE RQR */
1936 nmp->b_rptr -= 2;
1937 nrh = (struct gld_ri *)(nmp->b_rptr);
1938 nrh->len = 2;
1939 nrh->rt = RT_ARE;
1940 nrh->dir = 0;
1941 nrh->res = 0;
1942 nrh->mtu = RT_MTU_MAX;
1943 } else {
1944 /*
1945 * RIF must be ARE (Event 10) or SRF (Event 11):
1946 * send SRF (reverse) RQR
1947 */
1948 ASSERT(rh->len <= sizeof (struct gld_ri));
1949 nmp->b_rptr -= rh->len;
1950 nrh = (struct gld_ri *)(nmp->b_rptr);
1951 bcopy(rh, nrh, rh->len); /* copy incoming RIF */
1952 nrh->rt = RT_SRF; /* make it SRF */
1953 nrh->dir ^= 1; /* reverse direction */
1954 }
1955
1956 nmp->b_rptr -= sizeof (struct tr_mac_frm_nori);
1957 nmh = (struct tr_mac_frm_nori *)(nmp->b_rptr);
1958 nmh->tr_ac = 0x10;
1959 nmh->tr_fc = 0x40;
1960 mac_copy(shost, nmh->tr_dhost, macinfo->gldm_addrlen);
1961 mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
1962 nmh->tr_shost, macinfo->gldm_addrlen);
1963 nmh->tr_shost[0] |= 0x80; /* indicate RIF present */
1964
1965 /*
1966 * Packet assembled; send it.
1967 *
1968 * As noted before, this is not really a good time to be trying to
1969 * send out packets. We have no obvious queue to use if the packet
1970 * can't be sent right away. We pick one arbitrarily.
1971 */
1972 {
1973 gld_vlan_t *vlan;
1974 queue_t *q;
1975
1976 if ((vlan = gld_find_vlan(macinfo, VLAN_VID_NONE)) == NULL) {
1977 /* oops, no vlan on the list for this macinfo! */
1978 /* this should not happen */
1979 freeb(nmp);
1980 return;
1981 }
1982 q = vlan->gldv_str_next->gld_qptr;
1983
1984 /*
1985 * Queue the packet and let gld_wsrv
1986 * handle it, thus preventing a panic
1987 * caused by v2 TR in promiscuous mode
1988 * where it attempts to get the mutex
1989 * in this thread while already holding
1990 * it.
1991 */
1992 (void) putbq(WR(q), nmp);
1993 qenable(WR(q));
1994 }
1995 }
1996
1997 /*
1998 * This routine implements a modified subset of the 802.2 RDE RCC send actions:
1999 * we implement RCC send events 5 to 10 (ISO 8802-2:1994 9.6.3.5);
2000 * we omit special handling for the NULL SAP;
2001 * events 11 to 12 are handled by gld_rde_pdu_req below;
2002 * we require an immediate response to our GET_ROUTE_REQUEST.
2003 */
2004 static void
2005 gld_rcc_send(gld_mac_info_t *macinfo, queue_t *q, uchar_t *dhost,
2006 struct gld_ri **rhp, uchar_t *llcpkt)
2007 {
2008 struct llc_snap_hdr *snaphdr = (struct llc_snap_hdr *)(llcpkt);
2009
2010 /*
2011 * Our caller has to take the mutex because: to avoid an extra bcopy
2012 * of the RIF on every transmit, we pass back a pointer to our sr
2013 * table entry via rhp. He has to keep the mutex until he has a
2014 * chance to copy the RIF out into the outgoing packet, so that we
2015 * don't modify the entry while he's trying to copy it. This is a
2016 * little ugly, but saves the extra bcopy.
2017 */
2018 ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo)));
2019
2020 *rhp = (struct gld_ri *)NULL; /* start off clean (no RIF) */
2021
2022 if (!((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_enabled) {
2023 /* RDE is disabled -- use NULL or STE always */
2024 if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->
2025 rde_str_indicator_ste)
2026 *rhp = &ri_ste_def; /* STE option */
2027 return;
2028 }
2029
2030 if (!(dhost[0] & 0x80)) {
2031 /* individual address; Events 7 - 10 */
2032 if ((snaphdr->control & 0xef) == 0xe3) {
2033 /* TEST command, reset the route */
2034 gld_reset_route(macinfo, q,
2035 dhost, snaphdr->d_lsap, snaphdr->s_lsap);
2036 }
2037 gld_get_route(macinfo, q,
2038 dhost, rhp, snaphdr->d_lsap, snaphdr->s_lsap);
2039 }
2040
2041 if (*rhp == NULL) {
2042 /*
2043 * group address (Events 5 - 6),
2044 * or no route available (Events 8 - 9):
2045 * Need to send NSR or STE, as configured.
2046 */
2047 if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->
2048 rde_str_indicator_ste)
2049 *rhp = &ri_ste_def; /* STE option */
2050 }
2051 }
2052
2053 /*
2054 * RCC send events 11 - 12
2055 *
2056 * At present we only handle the RQC ptype.
2057 *
2058 * We "know" that the only time we can get here is from the "unitdata"
2059 * routine, called at wsrv time.
2060 *
2061 * If we ever implement the RS ptype (Event 13), this may no longer be true!
2062 */
2063 static void
2064 gld_rde_pdu_req(gld_mac_info_t *macinfo, queue_t *q, uchar_t *dhost,
2065 struct gld_ri *rh, uchar_t dsap, uchar_t ssap, uchar_t ptype)
2066 {
2067 mblk_t *nmp;
2068 int nlen;
2069 struct tr_mac_frm_nori *nmh;
2070 struct gld_ri *nrh;
2071 struct llc_snap_hdr *nsnaphdr;
2072 struct rde_pdu *npdu;
2073 int srpresent = 0;
2074
2075 /* if you change this to process other types, review all code below */
2076 ASSERT(ptype == RDE_RQC);
2077 ASSERT(rh == NULL); /* RQC never uses SRF */
2078
2079 nlen = sizeof (struct tr_mac_frm) + LLC_HDR1_LEN +
2080 sizeof (struct rde_pdu);
2081
2082 if ((nmp = allocb(nlen, BPRI_MED)) == NULL)
2083 return;
2084
2085 nmp->b_rptr = nmp->b_wptr = DB_LIM(nmp);
2086
2087 nmp->b_rptr -= sizeof (struct rde_pdu);
2088 npdu = (struct rde_pdu *)(nmp->b_rptr);
2089 npdu->rde_ver = 1;
2090 npdu->rde_ptype = ptype;
2091 mac_copy(dhost, &npdu->rde_target_mac, 6);
2092
2093 /*
2094 * access the mac address without a mutex - take a risk -
2095 * to prevent mutex contention (BUG 4211361)
2096 */
2097 mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
2098 &npdu->rde_orig_mac, 6);
2099 npdu->rde_target_sap = dsap;
2100 npdu->rde_orig_sap = ssap;
2101
2102 nmp->b_rptr -= LLC_HDR1_LEN;
2103 nsnaphdr = (struct llc_snap_hdr *)(nmp->b_rptr);
2104 nsnaphdr->s_lsap = nsnaphdr->d_lsap = LSAP_RDE;
2105 nsnaphdr->control = CNTL_LLC_UI;
2106
2107 #if 0 /* we don't need this for now */
2108 if (rh != NULL) {
2109 /* send an SRF frame with specified RIF */
2110 ASSERT(rh->len <= sizeof (struct gld_ri));
2111 nmp->b_rptr -= rh->len;
2112 nrh = (struct gld_ri *)(nmp->b_rptr);
2113 bcopy(rh, nrh, rh->len);
2114 ASSERT(nrh->rt == RT_SRF);
2115 srpresent = 1;
2116 } else
2117 #endif
2118
2119 /* Need to send NSR or STE, as configured. */
2120 if (((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_str_indicator_ste) {
2121 /* send an STE frame */
2122 nmp->b_rptr -= 2;
2123 nrh = (struct gld_ri *)(nmp->b_rptr);
2124 nrh->len = 2;
2125 nrh->rt = RT_STE;
2126 nrh->dir = 0;
2127 nrh->res = 0;
2128 nrh->mtu = RT_MTU_MAX;
2129 srpresent = 1;
2130 } /* else send an NSR frame */
2131
2132 nmp->b_rptr -= sizeof (struct tr_mac_frm_nori);
2133 nmh = (struct tr_mac_frm_nori *)(nmp->b_rptr);
2134 nmh->tr_ac = 0x10;
2135 nmh->tr_fc = 0x40;
2136 mac_copy(dhost, nmh->tr_dhost, macinfo->gldm_addrlen);
2137 /*
2138 * access the mac address without a mutex - take a risk -
2139 * to prevent mutex contention - BUG 4211361
2140 */
2141 mac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
2142 nmh->tr_shost, macinfo->gldm_addrlen);
2143
2144 if (srpresent)
2145 nmh->tr_shost[0] |= 0x80;
2146 else
2147 nmh->tr_shost[0] &= ~0x80;
2148
2149 /*
2150 * Packet assembled; send it.
2151 *
2152 * Since we own the SR_MUTEX, we don't want to take the maclock
2153 * mutex (since they are acquired in the opposite order on the
2154 * receive path, so deadlock could occur). We could rearrange
2155 * the code in gld_get_route() and drop the SR_MUTEX around the
2156 * call to gld_rde_pdu_req(), but that's kind of ugly. Rather,
2157 * we just refrain from calling gld_start() from here, and
2158 * instead just queue the packet for wsrv to send next. Besides,
2159 * it's more important to get the packet we're working on out
2160 * quickly than this RQC.
2161 */
2162 (void) putbq(WR(q), nmp);
2163 qenable(WR(q));
2164 }
2165
2166 /*
2167 * Route Determination Component (RDC)
2168 *
2169 * We do not implement separate routes for each SAP, as specified by
2170 * ISO 8802-2; instead we implement only one route per remote mac address.
2171 */
2172 static void
2173 gld_get_route(gld_mac_info_t *macinfo, queue_t *q, uchar_t *dhost,
2174 struct gld_ri **rhp, uchar_t dsap, uchar_t ssap)
2175 {
2176 struct srtab *sr;
2177 clock_t t = ddi_get_lbolt();
2178
2179 ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo)));
2180
2181 sr = gld_sr_lookup_entry(macinfo, dhost);
2182
2183 if (sr == NULL) {
2184 /*
2185 * we have no entry -- never heard of this address:
2186 * create an empty entry and initiate RQC
2187 */
2188 sr = gld_sr_create_entry(macinfo, dhost);
2189 gld_rde_pdu_req(macinfo, q, dhost, (struct gld_ri *)NULL,
2190 dsap, ssap, RDE_RQC);
2191 if (sr)
2192 sr->sr_timer = t;
2193 *rhp = NULL; /* we have no route yet */
2194 return;
2195 }
2196
2197 /* we have an entry; see if we know a route yet */
2198
2199 if (sr->sr_ri.len == 0) {
2200 /* Have asked RQC, but no reply (yet) */
2201 if (t - sr->sr_timer >
2202 ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_timeout) {
2203 /* RQR overdue, resend RQC */
2204 gld_rde_pdu_req(macinfo, q, dhost,
2205 (struct gld_ri *)NULL, dsap, ssap, RDE_RQC);
2206 sr->sr_timer = t;
2207 }
2208 *rhp = NULL; /* we have no route yet */
2209 return;
2210 }
2211
2212 /* we know a route, or it's local */
2213
2214 /* if it might be stale, reset and get a new one */
2215 if (t - sr->sr_timer >
2216 ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->rde_timeout) {
2217 gld_rde_pdu_req(macinfo, q, dhost,
2218 (struct gld_ri *)NULL, dsap, ssap, RDE_RQC);
2219 sr->sr_ri.len = 0;
2220 sr->sr_timer = t;
2221 *rhp = NULL; /* we have no route */
2222 return;
2223 }
2224
2225 if (sr->sr_ri.len == 2) {
2226 /* the remote site is on our local ring -- no route needed */
2227 *rhp = NULL;
2228 return;
2229 }
2230
2231 *rhp = &sr->sr_ri; /* we have a route, return it */
2232 }
2233
2234 /*
2235 * zap the specified entry and reinitiate RQC
2236 */
2237 static void
2238 gld_reset_route(gld_mac_info_t *macinfo, queue_t *q,
2239 uchar_t *dhost, uchar_t dsap, uchar_t ssap)
2240 {
2241 struct srtab *sr;
2242
2243 ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo)));
2244
2245 sr = gld_sr_create_entry(macinfo, dhost);
2246 gld_rde_pdu_req(macinfo, q, dhost, (struct gld_ri *)NULL,
2247 dsap, ssap, RDE_RQC);
2248 if (sr == NULL)
2249 return;
2250
2251 sr->sr_ri.len = 0;
2252 sr->sr_timer = ddi_get_lbolt();
2253 }
2254
2255 /*
2256 * This routine is called when an RDE PDU is received from our peer.
2257 * If it is an RS (Route Selected) PDU, we adopt the specified route.
2258 * If it is an RQR (reply to our previous RQC), we evaluate the
2259 * specified route in comparison with our current known route, if any,
2260 * and we keep the "better" of the two routes.
2261 */
2262 static void
2263 gld_rde_pdu_ind(gld_mac_info_t *macinfo, struct gld_ri *rh, struct rde_pdu *pdu,
2264 int pdulen)
2265 {
2266 struct srtab *sr;
2267 uchar_t *otherhost;
2268
2269 if (pdulen < sizeof (struct rde_pdu))
2270 return; /* Bad incoming PDU */
2271
2272 if (pdu->rde_ptype == RDE_RQC)
2273 return; /* ignore RQC */
2274
2275 if (pdu->rde_ptype != RDE_RQR && pdu->rde_ptype != RDE_RS) {
2276 #ifdef GLD_DEBUG
2277 if (gld_debug & GLDERRS)
2278 cmn_err(CE_WARN, "gld: bogus RDE ptype 0x%x received",
2279 pdu->rde_ptype);
2280 #endif
2281 return;
2282 }
2283
2284 if (rh == NULL) {
2285 #ifdef GLD_DEBUG
2286 if (gld_debug & GLDERRS)
2287 cmn_err(CE_WARN,
2288 "gld: bogus NULL RIF, ptype 0x%x received",
2289 pdu->rde_ptype);
2290 #endif
2291 return;
2292 }
2293
2294 ASSERT(rh->len >= 2);
2295 ASSERT(rh->len <= sizeof (struct gld_ri));
2296 ASSERT((rh->len & 1) == 0);
2297
2298 if (pdu->rde_ptype == RDE_RQR) {
2299 /* A reply to our RQC has his address as target mac */
2300 otherhost = pdu->rde_target_mac;
2301 } else {
2302 ASSERT(pdu->rde_ptype == RDE_RS);
2303 /* An RS has his address as orig mac */
2304 otherhost = pdu->rde_orig_mac;
2305 }
2306
2307 mutex_enter(GLD_SR_MUTEX(macinfo));
2308
2309 if ((sr = gld_sr_create_entry(macinfo, otherhost)) == NULL) {
2310 mutex_exit(GLD_SR_MUTEX(macinfo));
2311 return; /* oh well, out of memory */
2312 }
2313
2314 if (pdu->rde_ptype == RDE_RQR) {
2315 /* see if new route is better than what we may already have */
2316 if (sr->sr_ri.len != 0 &&
2317 sr->sr_ri.len <= rh->len) {
2318 mutex_exit(GLD_SR_MUTEX(macinfo));
2319 return; /* we have one, and new one is no shorter */
2320 }
2321 }
2322
2323 /* adopt the new route */
2324 bcopy((caddr_t)rh, (caddr_t)&sr->sr_ri, rh->len); /* copy incom RIF */
2325 sr->sr_ri.rt = RT_SRF; /* make it a clean SRF */
2326 sr->sr_ri.dir ^= 1; /* reverse direction */
2327 sr->sr_timer = ddi_get_lbolt();
2328
2329 mutex_exit(GLD_SR_MUTEX(macinfo));
2330 }
2331
2332 /*
2333 * This routine is called when a packet with a RIF is received. Our
2334 * policy is to adopt the route.
2335 */
2336 /* ARGSUSED3 */
2337 static void
2338 gld_rif_ind(gld_mac_info_t *macinfo, struct gld_ri *rh, uchar_t *shost,
2339 uchar_t ssap, uchar_t dsap)
2340 {
2341 struct srtab *sr;
2342
2343 ASSERT(rh != NULL); /* ensure RIF */
2344 ASSERT((rh->rt & 0x04) == 0); /* ensure SRF */
2345 ASSERT(rh->len >= 2);
2346 ASSERT(rh->len <= sizeof (struct gld_ri));
2347 ASSERT((rh->len & 1) == 0);
2348
2349 mutex_enter(GLD_SR_MUTEX(macinfo));
2350
2351 if ((sr = gld_sr_create_entry(macinfo, shost)) == NULL) {
2352 mutex_exit(GLD_SR_MUTEX(macinfo));
2353 return; /* oh well, out of memory */
2354 }
2355
2356 /* we have an entry; fill it in */
2357 bcopy((caddr_t)rh, (caddr_t)&sr->sr_ri, rh->len); /* copy incom RIF */
2358 sr->sr_ri.rt = RT_SRF; /* make it a clean SRF */
2359 sr->sr_ri.dir ^= 1; /* reverse direction */
2360 sr->sr_timer = ddi_get_lbolt();
2361
2362 mutex_exit(GLD_SR_MUTEX(macinfo));
2363 }
2364
2365 static struct srtab **
2366 gld_sr_hash(struct srtab **sr_hash_tbl, uchar_t *addr, int addr_length)
2367 {
2368 uint_t hashval = 0;
2369
2370 while (--addr_length >= 0)
2371 hashval ^= *addr++;
2372
2373 return (&sr_hash_tbl[hashval % SR_HASH_SIZE]);
2374 }
2375
2376 static struct srtab *
2377 gld_sr_lookup_entry(gld_mac_info_t *macinfo, uchar_t *macaddr)
2378 {
2379 struct srtab *sr;
2380
2381 ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo)));
2382
2383 for (sr = *gld_sr_hash(GLD_SR_HASH(macinfo), macaddr,
2384 macinfo->gldm_addrlen); sr; sr = sr->sr_next)
2385 if (mac_eq(macaddr, sr->sr_mac, macinfo->gldm_addrlen))
2386 return (sr);
2387
2388 return ((struct srtab *)0);
2389 }
2390
2391 static struct srtab *
2392 gld_sr_create_entry(gld_mac_info_t *macinfo, uchar_t *macaddr)
2393 {
2394 struct srtab *sr;
2395 struct srtab **srp;
2396
2397 ASSERT(!(macaddr[0] & 0x80)); /* no group addresses here */
2398 ASSERT(mutex_owned(GLD_SR_MUTEX(macinfo)));
2399
2400 srp = gld_sr_hash(GLD_SR_HASH(macinfo), macaddr, macinfo->gldm_addrlen);
2401
2402 for (sr = *srp; sr; sr = sr->sr_next)
2403 if (mac_eq(macaddr, sr->sr_mac, macinfo->gldm_addrlen))
2404 return (sr);
2405
2406 if (!(sr = kmem_zalloc(sizeof (struct srtab), KM_NOSLEEP))) {
2407 #ifdef GLD_DEBUG
2408 if (gld_debug & GLDERRS)
2409 cmn_err(CE_WARN,
2410 "gld: gld_sr_create_entry kmem_alloc failed");
2411 #endif
2412 return ((struct srtab *)0);
2413 }
2414
2415 bcopy((caddr_t)macaddr, (caddr_t)sr->sr_mac, macinfo->gldm_addrlen);
2416
2417 sr->sr_next = *srp;
2418 *srp = sr;
2419 return (sr);
2420 }
2421
2422 static void
2423 gld_sr_clear(gld_mac_info_t *macinfo)
2424 {
2425 int i;
2426 struct srtab **sr_hash_tbl = GLD_SR_HASH(macinfo);
2427 struct srtab **srp, *sr;
2428
2429 /*
2430 * Walk through the table, deleting all entries.
2431 *
2432 * Only called from uninit, so don't need the mutex.
2433 */
2434 for (i = 0; i < SR_HASH_SIZE; i++) {
2435 for (srp = &sr_hash_tbl[i]; (sr = *srp) != NULL; ) {
2436 *srp = sr->sr_next;
2437 kmem_free((char *)sr, sizeof (struct srtab));
2438 }
2439 }
2440 }
2441
2442 #ifdef DEBUG
2443 void
2444 gld_sr_dump(gld_mac_info_t *macinfo)
2445 {
2446 int i, j;
2447 struct srtab **sr_hash_tbl;
2448 struct srtab *sr;
2449
2450 sr_hash_tbl = GLD_SR_HASH(macinfo);
2451 if (sr_hash_tbl == NULL)
2452 return;
2453
2454 mutex_enter(GLD_SR_MUTEX(macinfo));
2455
2456 /*
2457 * Walk through the table, printing all entries
2458 */
2459 cmn_err(CE_NOTE, "GLD Source Routing Table (0x%p):", (void *)macinfo);
2460 cmn_err(CE_CONT, "Addr len,rt,dir,mtu,res rng,brg0 rng,brg1...\n");
2461 for (i = 0; i < SR_HASH_SIZE; i++) {
2462 for (sr = sr_hash_tbl[i]; sr; sr = sr->sr_next) {
2463 cmn_err(CE_CONT,
2464 "%x:%x:%x:%x:%x:%x %d,%x,%x,%x,%x ",
2465 sr->sr_mac[0], sr->sr_mac[1], sr->sr_mac[2],
2466 sr->sr_mac[3], sr->sr_mac[4], sr->sr_mac[5],
2467 sr->sr_ri.len, sr->sr_ri.rt, sr->sr_ri.dir,
2468 sr->sr_ri.mtu, sr->sr_ri.res);
2469 if (sr->sr_ri.len)
2470 for (j = 0; j < (sr->sr_ri.len - 2) / 2; j++)
2471 cmn_err(CE_CONT, "%x ",
2472 REF_NET_USHORT(*(unsigned short *)
2473 &sr->sr_ri.rd[j]));
2474 cmn_err(CE_CONT, "\n");
2475 }
2476 }
2477
2478 mutex_exit(GLD_SR_MUTEX(macinfo));
2479 }
2480 #endif