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