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