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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Data-Link Driver 31 */ 32 33 #include <sys/types.h> 34 #include <sys/debug.h> 35 #include <sys/sysmacros.h> 36 #include <sys/stream.h> 37 #include <sys/ddi.h> 38 #include <sys/sunddi.h> 39 #include <sys/strsun.h> 40 #include <sys/dlpi.h> 41 #include <netinet/in.h> 42 #include <sys/sdt.h> 43 #include <sys/strsubr.h> 44 #include <sys/vlan.h> 45 #include <sys/mac.h> 46 #include <sys/dls.h> 47 #include <sys/dld.h> 48 #include <sys/dld_impl.h> 49 50 typedef boolean_t proto_reqfunc_t(dld_str_t *, union DL_primitives *, mblk_t *); 51 52 static proto_reqfunc_t proto_info_req, proto_attach_req, proto_detach_req, 53 proto_bind_req, proto_unbind_req, proto_promiscon_req, proto_promiscoff_req, 54 proto_enabmulti_req, proto_disabmulti_req, proto_physaddr_req, 55 proto_setphysaddr_req, proto_udqos_req, proto_req, proto_capability_req, 56 proto_notify_req, proto_unitdata_req, proto_passive_req; 57 58 static void proto_poll_disable(dld_str_t *); 59 static boolean_t proto_poll_enable(dld_str_t *, dl_capab_poll_t *); 60 static boolean_t proto_capability_advertise(dld_str_t *, mblk_t *); 61 62 #define DL_ACK_PENDING(state) \ 63 ((state) == DL_ATTACH_PENDING || \ 64 (state) == DL_DETACH_PENDING || \ 65 (state) == DL_BIND_PENDING || \ 66 (state) == DL_UNBIND_PENDING) 67 68 /* 69 * Process a DLPI protocol message. 70 * The primitives DL_BIND_REQ, DL_ENABMULTI_REQ, DL_PROMISCON_REQ, 71 * DL_SET_PHYS_ADDR_REQ put the data link below our dld_str_t into an 72 * 'active' state. The primitive DL_PASSIVE_REQ marks our dld_str_t 73 * as 'passive' and forbids it from being subsequently made 'active' 74 * by the above primitives. 75 */ 76 void 77 dld_proto(dld_str_t *dsp, mblk_t *mp) 78 { 79 union DL_primitives *udlp; 80 t_uscalar_t prim; 81 82 if (MBLKL(mp) < sizeof (t_uscalar_t)) { 83 freemsg(mp); 84 return; 85 } 86 87 udlp = (union DL_primitives *)mp->b_rptr; 88 prim = udlp->dl_primitive; 89 90 switch (prim) { 91 case DL_INFO_REQ: 92 (void) proto_info_req(dsp, udlp, mp); 93 break; 94 case DL_BIND_REQ: 95 (void) proto_bind_req(dsp, udlp, mp); 96 break; 97 case DL_UNBIND_REQ: 98 (void) proto_unbind_req(dsp, udlp, mp); 99 break; 100 case DL_UNITDATA_REQ: 101 (void) proto_unitdata_req(dsp, udlp, mp); 102 break; 103 case DL_UDQOS_REQ: 104 (void) proto_udqos_req(dsp, udlp, mp); 105 break; 106 case DL_ATTACH_REQ: 107 (void) proto_attach_req(dsp, udlp, mp); 108 break; 109 case DL_DETACH_REQ: 110 (void) proto_detach_req(dsp, udlp, mp); 111 break; 112 case DL_ENABMULTI_REQ: 113 (void) proto_enabmulti_req(dsp, udlp, mp); 114 break; 115 case DL_DISABMULTI_REQ: 116 (void) proto_disabmulti_req(dsp, udlp, mp); 117 break; 118 case DL_PROMISCON_REQ: 119 (void) proto_promiscon_req(dsp, udlp, mp); 120 break; 121 case DL_PROMISCOFF_REQ: 122 (void) proto_promiscoff_req(dsp, udlp, mp); 123 break; 124 case DL_PHYS_ADDR_REQ: 125 (void) proto_physaddr_req(dsp, udlp, mp); 126 break; 127 case DL_SET_PHYS_ADDR_REQ: 128 (void) proto_setphysaddr_req(dsp, udlp, mp); 129 break; 130 case DL_NOTIFY_REQ: 131 (void) proto_notify_req(dsp, udlp, mp); 132 break; 133 case DL_CAPABILITY_REQ: 134 (void) proto_capability_req(dsp, udlp, mp); 135 break; 136 case DL_PASSIVE_REQ: 137 (void) proto_passive_req(dsp, udlp, mp); 138 break; 139 default: 140 (void) proto_req(dsp, udlp, mp); 141 break; 142 } 143 } 144 145 /* 146 * Finish any pending operations. At this moment we are single-threaded, 147 * hence there is no need to hold ds_lock as writer because we're already 148 * exclusive. 149 */ 150 void 151 dld_finish_pending_ops(dld_str_t *dsp) 152 { 153 ASSERT(MUTEX_HELD(&dsp->ds_thr_lock)); 154 ASSERT(dsp->ds_thr == 0); 155 156 /* Pending DL_DETACH_REQ? */ 157 if (dsp->ds_detach_req != NULL) { 158 mblk_t *mp; 159 160 ASSERT(dsp->ds_dlstate == DL_DETACH_PENDING); 161 dld_str_detach(dsp); 162 163 mp = dsp->ds_detach_req; 164 dsp->ds_detach_req = NULL; 165 166 mutex_exit(&dsp->ds_thr_lock); 167 dlokack(dsp->ds_wq, mp, DL_DETACH_REQ); 168 } else { 169 mutex_exit(&dsp->ds_thr_lock); 170 } 171 } 172 173 #define NEG(x) -(x) 174 175 typedef struct dl_info_ack_wrapper { 176 dl_info_ack_t dl_info; 177 uint8_t dl_addr[MAXADDRLEN + sizeof (uint16_t)]; 178 uint8_t dl_brdcst_addr[MAXADDRLEN]; 179 dl_qos_cl_range1_t dl_qos_range1; 180 dl_qos_cl_sel1_t dl_qos_sel1; 181 } dl_info_ack_wrapper_t; 182 183 /* 184 * DL_INFO_REQ 185 */ 186 /*ARGSUSED*/ 187 static boolean_t 188 proto_info_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 189 { 190 dl_info_ack_wrapper_t *dlwp; 191 dl_info_ack_t *dlp; 192 dl_qos_cl_sel1_t *selp; 193 dl_qos_cl_range1_t *rangep; 194 uint8_t *addr; 195 uint8_t *brdcst_addr; 196 uint_t addr_length; 197 uint_t sap_length; 198 mac_info_t minfo; 199 mac_info_t *minfop; 200 queue_t *q = dsp->ds_wq; 201 202 /* 203 * Swap the request message for one large enough to contain the 204 * wrapper structure defined above. 205 */ 206 if ((mp = mexchange(q, mp, sizeof (dl_info_ack_wrapper_t), 207 M_PCPROTO, 0)) == NULL) 208 return (B_FALSE); 209 210 rw_enter(&dsp->ds_lock, RW_READER); 211 212 bzero(mp->b_rptr, sizeof (dl_info_ack_wrapper_t)); 213 dlwp = (dl_info_ack_wrapper_t *)mp->b_rptr; 214 215 dlp = &(dlwp->dl_info); 216 ASSERT(dlp == (dl_info_ack_t *)mp->b_rptr); 217 218 dlp->dl_primitive = DL_INFO_ACK; 219 220 /* 221 * Set up the sub-structure pointers. 222 */ 223 addr = dlwp->dl_addr; 224 brdcst_addr = dlwp->dl_brdcst_addr; 225 rangep = &(dlwp->dl_qos_range1); 226 selp = &(dlwp->dl_qos_sel1); 227 228 /* 229 * This driver supports only version 2 connectionless DLPI provider 230 * nodes. 231 */ 232 dlp->dl_service_mode = DL_CLDLS; 233 dlp->dl_version = DL_VERSION_2; 234 235 /* 236 * Set the style of the provider 237 */ 238 dlp->dl_provider_style = dsp->ds_style; 239 ASSERT(dlp->dl_provider_style == DL_STYLE1 || 240 dlp->dl_provider_style == DL_STYLE2); 241 242 /* 243 * Set the current DLPI state. 244 */ 245 dlp->dl_current_state = dsp->ds_dlstate; 246 247 /* 248 * Gratuitously set the media type. This is to deal with modules 249 * that assume the media type is known prior to DL_ATTACH_REQ 250 * being completed. 251 */ 252 dlp->dl_mac_type = DL_ETHER; 253 254 /* 255 * If the stream is not at least attached we try to retrieve the 256 * mac_info using mac_info_get() 257 */ 258 if (dsp->ds_dlstate == DL_UNATTACHED || 259 dsp->ds_dlstate == DL_ATTACH_PENDING || 260 dsp->ds_dlstate == DL_DETACH_PENDING) { 261 if (!mac_info_get(ddi_major_to_name(dsp->ds_major), &minfo)) { 262 /* 263 * Cannot find mac_info. giving up. 264 */ 265 goto done; 266 } 267 minfop = &minfo; 268 } else { 269 minfop = (mac_info_t *)dsp->ds_mip; 270 } 271 272 /* 273 * Set the media type (properly this time). 274 */ 275 dlp->dl_mac_type = minfop->mi_media; 276 277 /* 278 * Set the DLSAP length. We only support 16 bit values and they 279 * appear after the MAC address portion of DLSAP addresses. 280 */ 281 sap_length = sizeof (uint16_t); 282 dlp->dl_sap_length = NEG(sap_length); 283 284 /* 285 * Set the minimum and maximum payload sizes. 286 */ 287 dlp->dl_min_sdu = minfop->mi_sdu_min; 288 dlp->dl_max_sdu = minfop->mi_sdu_max; 289 290 addr_length = minfop->mi_addr_length; 291 ASSERT(addr_length != 0); 292 293 /* 294 * Copy in the media broadcast address. 295 */ 296 dlp->dl_brdcst_addr_offset = (uintptr_t)brdcst_addr - (uintptr_t)dlp; 297 bcopy(minfop->mi_brdcst_addr, brdcst_addr, addr_length); 298 dlp->dl_brdcst_addr_length = addr_length; 299 300 /* 301 * We only support QoS information for VLAN interfaces. 302 */ 303 if (dsp->ds_vid != VLAN_ID_NONE) { 304 dlp->dl_qos_range_offset = (uintptr_t)rangep - (uintptr_t)dlp; 305 dlp->dl_qos_range_length = sizeof (dl_qos_cl_range1_t); 306 307 rangep->dl_qos_type = DL_QOS_CL_RANGE1; 308 rangep->dl_trans_delay.dl_target_value = DL_UNKNOWN; 309 rangep->dl_trans_delay.dl_accept_value = DL_UNKNOWN; 310 rangep->dl_protection.dl_min = DL_UNKNOWN; 311 rangep->dl_protection.dl_max = DL_UNKNOWN; 312 rangep->dl_residual_error = DL_UNKNOWN; 313 314 /* 315 * Specify the supported range of priorities. 316 */ 317 rangep->dl_priority.dl_min = 0; 318 rangep->dl_priority.dl_max = (1 << VLAN_PRI_SIZE) - 1; 319 320 dlp->dl_qos_offset = (uintptr_t)selp - (uintptr_t)dlp; 321 dlp->dl_qos_length = sizeof (dl_qos_cl_sel1_t); 322 323 selp->dl_qos_type = DL_QOS_CL_SEL1; 324 selp->dl_trans_delay = DL_UNKNOWN; 325 selp->dl_protection = DL_UNKNOWN; 326 selp->dl_residual_error = DL_UNKNOWN; 327 328 /* 329 * Specify the current priority (which can be changed by 330 * the DL_UDQOS_REQ primitive). 331 */ 332 selp->dl_priority = dsp->ds_pri; 333 } else { 334 /* 335 * Shorten the buffer to lose the unused QoS information 336 * structures. 337 */ 338 mp->b_wptr = (uint8_t *)rangep; 339 } 340 341 dlp->dl_addr_length = addr_length + sizeof (uint16_t); 342 if (dsp->ds_dlstate == DL_IDLE) { 343 /* 344 * The stream is bound. Therefore we can formulate a valid 345 * DLSAP address. 346 */ 347 dlp->dl_addr_offset = (uintptr_t)addr - (uintptr_t)dlp; 348 bcopy(dsp->ds_curr_addr, addr, addr_length); 349 *(uint16_t *)(addr + addr_length) = dsp->ds_sap; 350 } 351 352 done: 353 ASSERT(IMPLY(dlp->dl_qos_offset != 0, dlp->dl_qos_length != 0)); 354 ASSERT(IMPLY(dlp->dl_qos_range_offset != 0, 355 dlp->dl_qos_range_length != 0)); 356 ASSERT(IMPLY(dlp->dl_addr_offset != 0, dlp->dl_addr_length != 0)); 357 ASSERT(IMPLY(dlp->dl_brdcst_addr_offset != 0, 358 dlp->dl_brdcst_addr_length != 0)); 359 360 rw_exit(&dsp->ds_lock); 361 362 qreply(q, mp); 363 return (B_TRUE); 364 } 365 366 /* 367 * DL_ATTACH_REQ 368 */ 369 static boolean_t 370 proto_attach_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 371 { 372 dl_attach_req_t *dlp = (dl_attach_req_t *)udlp; 373 int err = 0; 374 t_uscalar_t dl_err; 375 queue_t *q = dsp->ds_wq; 376 377 rw_enter(&dsp->ds_lock, RW_WRITER); 378 379 if (MBLKL(mp) < sizeof (dl_attach_req_t) || 380 dlp->dl_ppa < 0 || dsp->ds_style == DL_STYLE1) { 381 dl_err = DL_BADPRIM; 382 goto failed; 383 } 384 385 if (dsp->ds_dlstate != DL_UNATTACHED) { 386 dl_err = DL_OUTSTATE; 387 goto failed; 388 } 389 390 dsp->ds_dlstate = DL_ATTACH_PENDING; 391 392 err = dld_str_attach(dsp, dlp->dl_ppa); 393 if (err != 0) { 394 switch (err) { 395 case ENOENT: 396 dl_err = DL_BADPPA; 397 err = 0; 398 break; 399 default: 400 dl_err = DL_SYSERR; 401 break; 402 } 403 dsp->ds_dlstate = DL_UNATTACHED; 404 goto failed; 405 } 406 ASSERT(dsp->ds_dlstate == DL_UNBOUND); 407 rw_exit(&dsp->ds_lock); 408 409 dlokack(q, mp, DL_ATTACH_REQ); 410 return (B_TRUE); 411 failed: 412 rw_exit(&dsp->ds_lock); 413 dlerrorack(q, mp, DL_ATTACH_REQ, dl_err, (t_uscalar_t)err); 414 return (B_FALSE); 415 } 416 417 /* 418 * DL_DETACH_REQ 419 */ 420 /*ARGSUSED*/ 421 static boolean_t 422 proto_detach_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 423 { 424 queue_t *q = dsp->ds_wq; 425 t_uscalar_t dl_err; 426 427 rw_enter(&dsp->ds_lock, RW_WRITER); 428 429 if (MBLKL(mp) < sizeof (dl_detach_req_t)) { 430 dl_err = DL_BADPRIM; 431 goto failed; 432 } 433 434 if (dsp->ds_dlstate != DL_UNBOUND) { 435 dl_err = DL_OUTSTATE; 436 goto failed; 437 } 438 439 if (dsp->ds_style == DL_STYLE1) { 440 dl_err = DL_BADPRIM; 441 goto failed; 442 } 443 444 dsp->ds_dlstate = DL_DETACH_PENDING; 445 446 /* 447 * Complete the detach when the driver is single-threaded. 448 */ 449 mutex_enter(&dsp->ds_thr_lock); 450 ASSERT(dsp->ds_detach_req == NULL); 451 dsp->ds_detach_req = mp; 452 mutex_exit(&dsp->ds_thr_lock); 453 rw_exit(&dsp->ds_lock); 454 455 return (B_TRUE); 456 failed: 457 rw_exit(&dsp->ds_lock); 458 dlerrorack(q, mp, DL_DETACH_REQ, dl_err, 0); 459 return (B_FALSE); 460 } 461 462 /* 463 * DL_BIND_REQ 464 */ 465 static boolean_t 466 proto_bind_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 467 { 468 dl_bind_req_t *dlp = (dl_bind_req_t *)udlp; 469 int err = 0; 470 uint8_t addr[MAXADDRLEN]; 471 uint_t addr_length; 472 t_uscalar_t dl_err; 473 t_scalar_t sap; 474 queue_t *q = dsp->ds_wq; 475 476 if (MBLKL(mp) < sizeof (dl_bind_req_t)) { 477 dl_err = DL_BADPRIM; 478 goto failed; 479 } 480 481 if (dlp->dl_xidtest_flg != 0) { 482 dl_err = DL_NOAUTO; 483 goto failed; 484 } 485 486 if (dlp->dl_service_mode != DL_CLDLS) { 487 dl_err = DL_UNSUPPORTED; 488 goto failed; 489 } 490 491 rw_enter(&dsp->ds_lock, RW_WRITER); 492 493 if (dsp->ds_dlstate != DL_UNBOUND) { 494 dl_err = DL_OUTSTATE; 495 goto failed; 496 } 497 498 if (dsp->ds_passivestate == DLD_UNINITIALIZED && 499 !dls_active_set(dsp->ds_dc)) { 500 dl_err = DL_SYSERR; 501 err = EBUSY; 502 goto failed; 503 } 504 505 dsp->ds_dlstate = DL_BIND_PENDING; 506 /* 507 * Set the receive callback. 508 */ 509 dls_rx_set(dsp->ds_dc, (dsp->ds_mode == DLD_RAW) ? 510 dld_str_rx_raw : dld_str_rx_unitdata, dsp); 511 512 /* 513 * Bind the channel such that it can receive packets. 514 */ 515 sap = dsp->ds_sap = dlp->dl_sap; 516 err = dls_bind(dsp->ds_dc, dlp->dl_sap); 517 if (err != 0) { 518 switch (err) { 519 case EINVAL: 520 dl_err = DL_BADADDR; 521 err = 0; 522 break; 523 default: 524 dl_err = DL_SYSERR; 525 break; 526 } 527 dsp->ds_dlstate = DL_UNBOUND; 528 if (dsp->ds_passivestate == DLD_UNINITIALIZED) 529 dls_active_clear(dsp->ds_dc); 530 531 goto failed; 532 } 533 534 /* 535 * Copy in MAC address. 536 */ 537 addr_length = dsp->ds_mip->mi_addr_length; 538 bcopy(dsp->ds_curr_addr, addr, addr_length); 539 540 /* 541 * Copy in the DLSAP. 542 */ 543 *(uint16_t *)(addr + addr_length) = dsp->ds_sap; 544 addr_length += sizeof (uint16_t); 545 546 dsp->ds_dlstate = DL_IDLE; 547 if (dsp->ds_passivestate == DLD_UNINITIALIZED) 548 dsp->ds_passivestate = DLD_ACTIVE; 549 550 rw_exit(&dsp->ds_lock); 551 552 dlbindack(q, mp, sap, (void *)addr, addr_length, 0, 0); 553 return (B_TRUE); 554 failed: 555 rw_exit(&dsp->ds_lock); 556 dlerrorack(q, mp, DL_BIND_REQ, dl_err, (t_uscalar_t)err); 557 return (B_FALSE); 558 } 559 560 /* 561 * DL_UNBIND_REQ 562 */ 563 /*ARGSUSED*/ 564 static boolean_t 565 proto_unbind_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 566 { 567 queue_t *q = dsp->ds_wq; 568 t_uscalar_t dl_err; 569 570 rw_enter(&dsp->ds_lock, RW_WRITER); 571 572 if (MBLKL(mp) < sizeof (dl_unbind_req_t)) { 573 dl_err = DL_BADPRIM; 574 goto failed; 575 } 576 577 if (dsp->ds_dlstate != DL_IDLE) { 578 dl_err = DL_OUTSTATE; 579 goto failed; 580 } 581 582 dsp->ds_dlstate = DL_UNBIND_PENDING; 583 584 /* 585 * Flush any remaining packets scheduled for transmission. 586 */ 587 dld_tx_flush(dsp); 588 589 /* 590 * Unbind the channel to stop packets being received. 591 */ 592 dls_unbind(dsp->ds_dc); 593 594 /* 595 * Disable polling mode, if it is enabled. 596 */ 597 proto_poll_disable(dsp); 598 599 /* 600 * Clear the receive callback. 601 */ 602 dls_rx_set(dsp->ds_dc, NULL, NULL); 603 604 /* 605 * Set the mode back to the default (unitdata). 606 */ 607 dsp->ds_mode = DLD_UNITDATA; 608 609 dsp->ds_dlstate = DL_UNBOUND; 610 rw_exit(&dsp->ds_lock); 611 612 dlokack(q, mp, DL_UNBIND_REQ); 613 return (B_TRUE); 614 failed: 615 rw_exit(&dsp->ds_lock); 616 dlerrorack(q, mp, DL_UNBIND_REQ, dl_err, 0); 617 return (B_FALSE); 618 } 619 620 /* 621 * DL_PROMISCON_REQ 622 */ 623 static boolean_t 624 proto_promiscon_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 625 { 626 dl_promiscon_req_t *dlp = (dl_promiscon_req_t *)udlp; 627 int err = 0; 628 t_uscalar_t dl_err; 629 uint32_t promisc_saved; 630 queue_t *q = dsp->ds_wq; 631 632 if (MBLKL(mp) < sizeof (dl_promiscon_req_t)) { 633 dl_err = DL_BADPRIM; 634 goto failed; 635 } 636 637 rw_enter(&dsp->ds_lock, RW_WRITER); 638 639 if (dsp->ds_dlstate == DL_UNATTACHED || 640 DL_ACK_PENDING(dsp->ds_dlstate)) { 641 dl_err = DL_OUTSTATE; 642 goto failed; 643 } 644 645 promisc_saved = dsp->ds_promisc; 646 switch (dlp->dl_level) { 647 case DL_PROMISC_SAP: 648 dsp->ds_promisc |= DLS_PROMISC_SAP; 649 break; 650 651 case DL_PROMISC_MULTI: 652 dsp->ds_promisc |= DLS_PROMISC_MULTI; 653 break; 654 655 case DL_PROMISC_PHYS: 656 dsp->ds_promisc |= DLS_PROMISC_PHYS; 657 break; 658 659 default: 660 dl_err = DL_NOTSUPPORTED; 661 goto failed; 662 } 663 664 if (dsp->ds_passivestate == DLD_UNINITIALIZED && 665 !dls_active_set(dsp->ds_dc)) { 666 dsp->ds_promisc = promisc_saved; 667 dl_err = DL_SYSERR; 668 err = EBUSY; 669 goto failed; 670 } 671 672 /* 673 * Adjust channel promiscuity. 674 */ 675 err = dls_promisc(dsp->ds_dc, dsp->ds_promisc); 676 if (err != 0) { 677 dl_err = DL_SYSERR; 678 dsp->ds_promisc = promisc_saved; 679 if (dsp->ds_passivestate == DLD_UNINITIALIZED) 680 dls_active_clear(dsp->ds_dc); 681 682 goto failed; 683 } 684 685 if (dsp->ds_passivestate == DLD_UNINITIALIZED) 686 dsp->ds_passivestate = DLD_ACTIVE; 687 688 rw_exit(&dsp->ds_lock); 689 dlokack(q, mp, DL_PROMISCON_REQ); 690 return (B_TRUE); 691 failed: 692 rw_exit(&dsp->ds_lock); 693 dlerrorack(q, mp, DL_PROMISCON_REQ, dl_err, (t_uscalar_t)err); 694 return (B_FALSE); 695 } 696 697 /* 698 * DL_PROMISCOFF_REQ 699 */ 700 static boolean_t 701 proto_promiscoff_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 702 { 703 dl_promiscoff_req_t *dlp = (dl_promiscoff_req_t *)udlp; 704 int err = 0; 705 t_uscalar_t dl_err; 706 uint32_t promisc_saved; 707 queue_t *q = dsp->ds_wq; 708 709 710 if (MBLKL(mp) < sizeof (dl_promiscoff_req_t)) { 711 dl_err = DL_BADPRIM; 712 goto failed; 713 } 714 715 rw_enter(&dsp->ds_lock, RW_WRITER); 716 717 if (dsp->ds_dlstate == DL_UNATTACHED || 718 DL_ACK_PENDING(dsp->ds_dlstate)) { 719 dl_err = DL_OUTSTATE; 720 goto failed; 721 } 722 723 promisc_saved = dsp->ds_promisc; 724 switch (dlp->dl_level) { 725 case DL_PROMISC_SAP: 726 if (!(dsp->ds_promisc & DLS_PROMISC_SAP)) { 727 dl_err = DL_NOTENAB; 728 goto failed; 729 } 730 dsp->ds_promisc &= ~DLS_PROMISC_SAP; 731 break; 732 733 case DL_PROMISC_MULTI: 734 if (!(dsp->ds_promisc & DLS_PROMISC_MULTI)) { 735 dl_err = DL_NOTENAB; 736 goto failed; 737 } 738 dsp->ds_promisc &= ~DLS_PROMISC_MULTI; 739 break; 740 741 case DL_PROMISC_PHYS: 742 if (!(dsp->ds_promisc & DLS_PROMISC_PHYS)) { 743 dl_err = DL_NOTENAB; 744 goto failed; 745 } 746 dsp->ds_promisc &= ~DLS_PROMISC_PHYS; 747 break; 748 749 default: 750 dl_err = DL_NOTSUPPORTED; 751 goto failed; 752 } 753 754 /* 755 * Adjust channel promiscuity. 756 */ 757 err = dls_promisc(dsp->ds_dc, dsp->ds_promisc); 758 if (err != 0) { 759 dsp->ds_promisc = promisc_saved; 760 dl_err = DL_SYSERR; 761 goto failed; 762 } 763 764 rw_exit(&dsp->ds_lock); 765 dlokack(q, mp, DL_PROMISCOFF_REQ); 766 return (B_TRUE); 767 failed: 768 rw_exit(&dsp->ds_lock); 769 dlerrorack(q, mp, DL_PROMISCOFF_REQ, dl_err, (t_uscalar_t)err); 770 return (B_FALSE); 771 } 772 773 /* 774 * DL_ENABMULTI_REQ 775 */ 776 static boolean_t 777 proto_enabmulti_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 778 { 779 dl_enabmulti_req_t *dlp = (dl_enabmulti_req_t *)udlp; 780 int err = 0; 781 t_uscalar_t dl_err; 782 queue_t *q = dsp->ds_wq; 783 784 rw_enter(&dsp->ds_lock, RW_WRITER); 785 786 if (dsp->ds_dlstate == DL_UNATTACHED || 787 DL_ACK_PENDING(dsp->ds_dlstate)) { 788 dl_err = DL_OUTSTATE; 789 goto failed; 790 } 791 792 if (MBLKL(mp) < sizeof (dl_enabmulti_req_t) || 793 !MBLKIN(mp, dlp->dl_addr_offset, dlp->dl_addr_length) || 794 dlp->dl_addr_length != dsp->ds_mip->mi_addr_length) { 795 dl_err = DL_BADPRIM; 796 goto failed; 797 } 798 799 if (dsp->ds_passivestate == DLD_UNINITIALIZED && 800 !dls_active_set(dsp->ds_dc)) { 801 dl_err = DL_SYSERR; 802 err = EBUSY; 803 goto failed; 804 } 805 806 err = dls_multicst_add(dsp->ds_dc, mp->b_rptr + dlp->dl_addr_offset); 807 if (err != 0) { 808 switch (err) { 809 case EINVAL: 810 dl_err = DL_BADADDR; 811 err = 0; 812 break; 813 case ENOSPC: 814 dl_err = DL_TOOMANY; 815 err = 0; 816 break; 817 default: 818 dl_err = DL_SYSERR; 819 break; 820 } 821 if (dsp->ds_passivestate == DLD_UNINITIALIZED) 822 dls_active_clear(dsp->ds_dc); 823 824 goto failed; 825 } 826 827 if (dsp->ds_passivestate == DLD_UNINITIALIZED) 828 dsp->ds_passivestate = DLD_ACTIVE; 829 830 rw_exit(&dsp->ds_lock); 831 dlokack(q, mp, DL_ENABMULTI_REQ); 832 return (B_TRUE); 833 failed: 834 rw_exit(&dsp->ds_lock); 835 dlerrorack(q, mp, DL_ENABMULTI_REQ, dl_err, (t_uscalar_t)err); 836 return (B_FALSE); 837 } 838 839 /* 840 * DL_DISABMULTI_REQ 841 */ 842 static boolean_t 843 proto_disabmulti_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 844 { 845 dl_disabmulti_req_t *dlp = (dl_disabmulti_req_t *)udlp; 846 int err = 0; 847 t_uscalar_t dl_err; 848 queue_t *q = dsp->ds_wq; 849 850 rw_enter(&dsp->ds_lock, RW_READER); 851 852 if (dsp->ds_dlstate == DL_UNATTACHED || 853 DL_ACK_PENDING(dsp->ds_dlstate)) { 854 dl_err = DL_OUTSTATE; 855 goto failed; 856 } 857 858 if (MBLKL(mp) < sizeof (dl_disabmulti_req_t) || 859 !MBLKIN(mp, dlp->dl_addr_offset, dlp->dl_addr_length) || 860 dlp->dl_addr_length != dsp->ds_mip->mi_addr_length) { 861 dl_err = DL_BADPRIM; 862 goto failed; 863 } 864 865 err = dls_multicst_remove(dsp->ds_dc, mp->b_rptr + dlp->dl_addr_offset); 866 if (err != 0) { 867 switch (err) { 868 case EINVAL: 869 dl_err = DL_BADADDR; 870 err = 0; 871 break; 872 873 case ENOENT: 874 dl_err = DL_NOTENAB; 875 err = 0; 876 break; 877 878 default: 879 dl_err = DL_SYSERR; 880 break; 881 } 882 goto failed; 883 } 884 885 rw_exit(&dsp->ds_lock); 886 dlokack(q, mp, DL_DISABMULTI_REQ); 887 return (B_TRUE); 888 failed: 889 rw_exit(&dsp->ds_lock); 890 dlerrorack(q, mp, DL_DISABMULTI_REQ, dl_err, (t_uscalar_t)err); 891 return (B_FALSE); 892 } 893 894 /* 895 * DL_PHYS_ADDR_REQ 896 */ 897 static boolean_t 898 proto_physaddr_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 899 { 900 dl_phys_addr_req_t *dlp = (dl_phys_addr_req_t *)udlp; 901 queue_t *q = dsp->ds_wq; 902 t_uscalar_t dl_err; 903 char *addr; 904 uint_t addr_length; 905 906 rw_enter(&dsp->ds_lock, RW_READER); 907 908 if (MBLKL(mp) < sizeof (dl_phys_addr_req_t)) { 909 dl_err = DL_BADPRIM; 910 goto failed; 911 } 912 913 if (dsp->ds_dlstate == DL_UNATTACHED || 914 DL_ACK_PENDING(dsp->ds_dlstate)) { 915 dl_err = DL_OUTSTATE; 916 goto failed; 917 } 918 919 if (dlp->dl_addr_type != DL_CURR_PHYS_ADDR && 920 dlp->dl_addr_type != DL_FACT_PHYS_ADDR) { 921 dl_err = DL_UNSUPPORTED; 922 goto failed; 923 } 924 925 addr_length = dsp->ds_mip->mi_addr_length; 926 addr = kmem_alloc(addr_length, KM_NOSLEEP); 927 if (addr == NULL) { 928 rw_exit(&dsp->ds_lock); 929 merror(q, mp, ENOSR); 930 return (B_FALSE); 931 } 932 933 /* 934 * Copy out the address before we drop the lock; we don't 935 * want to call dlphysaddrack() while holding ds_lock. 936 */ 937 bcopy((dlp->dl_addr_type == DL_CURR_PHYS_ADDR) ? 938 dsp->ds_curr_addr : dsp->ds_fact_addr, addr, addr_length); 939 940 rw_exit(&dsp->ds_lock); 941 dlphysaddrack(q, mp, addr, (t_uscalar_t)addr_length); 942 kmem_free(addr, addr_length); 943 return (B_TRUE); 944 failed: 945 rw_exit(&dsp->ds_lock); 946 dlerrorack(q, mp, DL_PHYS_ADDR_REQ, dl_err, 0); 947 return (B_FALSE); 948 } 949 950 /* 951 * DL_SET_PHYS_ADDR_REQ 952 */ 953 static boolean_t 954 proto_setphysaddr_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 955 { 956 dl_set_phys_addr_req_t *dlp = (dl_set_phys_addr_req_t *)udlp; 957 int err = 0; 958 t_uscalar_t dl_err; 959 queue_t *q = dsp->ds_wq; 960 961 rw_enter(&dsp->ds_lock, RW_WRITER); 962 963 if (dsp->ds_dlstate == DL_UNATTACHED || 964 DL_ACK_PENDING(dsp->ds_dlstate)) { 965 dl_err = DL_OUTSTATE; 966 goto failed; 967 } 968 969 if (MBLKL(mp) < sizeof (dl_set_phys_addr_req_t) || 970 !MBLKIN(mp, dlp->dl_addr_offset, dlp->dl_addr_length) || 971 dlp->dl_addr_length != dsp->ds_mip->mi_addr_length) { 972 dl_err = DL_BADPRIM; 973 goto failed; 974 } 975 976 if (dsp->ds_passivestate == DLD_UNINITIALIZED && 977 !dls_active_set(dsp->ds_dc)) { 978 dl_err = DL_SYSERR; 979 err = EBUSY; 980 goto failed; 981 } 982 983 err = mac_unicst_set(dsp->ds_mh, mp->b_rptr + dlp->dl_addr_offset); 984 if (err != 0) { 985 switch (err) { 986 case EINVAL: 987 dl_err = DL_BADADDR; 988 err = 0; 989 break; 990 991 default: 992 dl_err = DL_SYSERR; 993 break; 994 } 995 if (dsp->ds_passivestate == DLD_UNINITIALIZED) 996 dls_active_clear(dsp->ds_dc); 997 998 goto failed; 999 } 1000 if (dsp->ds_passivestate == DLD_UNINITIALIZED) 1001 dsp->ds_passivestate = DLD_ACTIVE; 1002 1003 rw_exit(&dsp->ds_lock); 1004 dlokack(q, mp, DL_SET_PHYS_ADDR_REQ); 1005 return (B_TRUE); 1006 failed: 1007 rw_exit(&dsp->ds_lock); 1008 dlerrorack(q, mp, DL_SET_PHYS_ADDR_REQ, dl_err, (t_uscalar_t)err); 1009 return (B_FALSE); 1010 } 1011 1012 /* 1013 * DL_UDQOS_REQ 1014 */ 1015 static boolean_t 1016 proto_udqos_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 1017 { 1018 dl_udqos_req_t *dlp = (dl_udqos_req_t *)udlp; 1019 dl_qos_cl_sel1_t *selp; 1020 int off, len; 1021 t_uscalar_t dl_err; 1022 queue_t *q = dsp->ds_wq; 1023 1024 off = dlp->dl_qos_offset; 1025 len = dlp->dl_qos_length; 1026 1027 if (MBLKL(mp) < sizeof (dl_udqos_req_t) || !MBLKIN(mp, off, len)) { 1028 dl_err = DL_BADPRIM; 1029 goto failed; 1030 } 1031 1032 selp = (dl_qos_cl_sel1_t *)(mp->b_rptr + off); 1033 if (selp->dl_qos_type != DL_QOS_CL_SEL1) { 1034 dl_err = DL_BADQOSTYPE; 1035 goto failed; 1036 } 1037 1038 rw_enter(&dsp->ds_lock, RW_WRITER); 1039 1040 if (dsp->ds_vid == VLAN_ID_NONE || 1041 selp->dl_priority > (1 << VLAN_PRI_SIZE) - 1 || 1042 selp->dl_priority < 0) { 1043 dl_err = DL_BADQOSPARAM; 1044 goto failed; 1045 } 1046 1047 dsp->ds_pri = selp->dl_priority; 1048 1049 rw_exit(&dsp->ds_lock); 1050 dlokack(q, mp, DL_UDQOS_REQ); 1051 return (B_TRUE); 1052 failed: 1053 rw_exit(&dsp->ds_lock); 1054 dlerrorack(q, mp, DL_UDQOS_REQ, dl_err, 0); 1055 return (B_FALSE); 1056 } 1057 1058 /* 1059 * DL_CAPABILITY_REQ 1060 */ 1061 /*ARGSUSED*/ 1062 static boolean_t 1063 proto_capability_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 1064 { 1065 dl_capability_req_t *dlp = (dl_capability_req_t *)udlp; 1066 dl_capability_sub_t *sp; 1067 size_t size, len; 1068 offset_t off, end; 1069 t_uscalar_t dl_err; 1070 queue_t *q = dsp->ds_wq; 1071 boolean_t upgraded; 1072 1073 rw_enter(&dsp->ds_lock, RW_READER); 1074 1075 if (MBLKL(mp) < sizeof (dl_capability_req_t)) { 1076 dl_err = DL_BADPRIM; 1077 goto failed; 1078 } 1079 1080 if (dsp->ds_dlstate == DL_UNATTACHED || 1081 DL_ACK_PENDING(dsp->ds_dlstate)) { 1082 dl_err = DL_OUTSTATE; 1083 goto failed; 1084 } 1085 1086 /* 1087 * This request is overloaded. If there are no requested capabilities 1088 * then we just want to acknowledge with all the capabilities we 1089 * support. Otherwise we enable the set of capabilities requested. 1090 */ 1091 if (dlp->dl_sub_length == 0) { 1092 /* callee drops lock */ 1093 return (proto_capability_advertise(dsp, mp)); 1094 } 1095 1096 if (!MBLKIN(mp, dlp->dl_sub_offset, dlp->dl_sub_length)) { 1097 dl_err = DL_BADPRIM; 1098 goto failed; 1099 } 1100 1101 dlp->dl_primitive = DL_CAPABILITY_ACK; 1102 1103 off = dlp->dl_sub_offset; 1104 len = dlp->dl_sub_length; 1105 1106 /* 1107 * Walk the list of capabilities to be enabled. 1108 */ 1109 upgraded = B_FALSE; 1110 for (end = off + len; off < end; ) { 1111 sp = (dl_capability_sub_t *)(mp->b_rptr + off); 1112 size = sizeof (dl_capability_sub_t) + sp->dl_length; 1113 1114 if (off + size > end || 1115 !IS_P2ALIGNED(off, sizeof (uint32_t))) { 1116 dl_err = DL_BADPRIM; 1117 goto failed; 1118 } 1119 1120 switch (sp->dl_cap) { 1121 /* 1122 * TCP/IP checksum offload to hardware. 1123 */ 1124 case DL_CAPAB_HCKSUM: { 1125 dl_capab_hcksum_t *hcksump; 1126 dl_capab_hcksum_t hcksum; 1127 1128 ASSERT(dsp->ds_mip->mi_cksum != 0); 1129 1130 hcksump = (dl_capab_hcksum_t *)&sp[1]; 1131 /* 1132 * Copy for alignment. 1133 */ 1134 bcopy(hcksump, &hcksum, sizeof (dl_capab_hcksum_t)); 1135 dlcapabsetqid(&(hcksum.hcksum_mid), dsp->ds_rq); 1136 bcopy(&hcksum, hcksump, sizeof (dl_capab_hcksum_t)); 1137 break; 1138 } 1139 1140 /* 1141 * IP polling interface. 1142 */ 1143 case DL_CAPAB_POLL: { 1144 dl_capab_poll_t *pollp; 1145 dl_capab_poll_t poll; 1146 1147 pollp = (dl_capab_poll_t *)&sp[1]; 1148 /* 1149 * Copy for alignment. 1150 */ 1151 bcopy(pollp, &poll, sizeof (dl_capab_poll_t)); 1152 1153 /* 1154 * We need to become writer before enabling and/or 1155 * disabling the polling interface. If we couldn' 1156 * upgrade, check state again after re-acquiring the 1157 * lock to make sure we can proceed. 1158 */ 1159 if (!upgraded && !rw_tryupgrade(&dsp->ds_lock)) { 1160 rw_exit(&dsp->ds_lock); 1161 rw_enter(&dsp->ds_lock, RW_WRITER); 1162 1163 if (dsp->ds_dlstate == DL_UNATTACHED || 1164 DL_ACK_PENDING(dsp->ds_dlstate)) { 1165 dl_err = DL_OUTSTATE; 1166 goto failed; 1167 } 1168 } 1169 upgraded = B_TRUE; 1170 1171 switch (poll.poll_flags) { 1172 default: 1173 /*FALLTHRU*/ 1174 case POLL_DISABLE: 1175 proto_poll_disable(dsp); 1176 break; 1177 1178 case POLL_ENABLE: 1179 ASSERT(!(dld_opt & DLD_OPT_NO_POLL)); 1180 1181 /* 1182 * Make sure polling is disabled. 1183 */ 1184 proto_poll_disable(dsp); 1185 1186 /* 1187 * Now attempt enable it. 1188 */ 1189 if (!proto_poll_enable(dsp, &poll)) 1190 break; 1191 1192 bzero(&poll, sizeof (dl_capab_poll_t)); 1193 poll.poll_flags = POLL_ENABLE; 1194 break; 1195 } 1196 1197 dlcapabsetqid(&(poll.poll_mid), dsp->ds_rq); 1198 bcopy(&poll, pollp, sizeof (dl_capab_poll_t)); 1199 break; 1200 } 1201 default: 1202 break; 1203 } 1204 1205 off += size; 1206 } 1207 rw_exit(&dsp->ds_lock); 1208 qreply(q, mp); 1209 return (B_TRUE); 1210 failed: 1211 rw_exit(&dsp->ds_lock); 1212 dlerrorack(q, mp, DL_CAPABILITY_REQ, dl_err, 0); 1213 return (B_FALSE); 1214 } 1215 1216 /* 1217 * DL_NOTIFY_REQ 1218 */ 1219 static boolean_t 1220 proto_notify_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 1221 { 1222 dl_notify_req_t *dlp = (dl_notify_req_t *)udlp; 1223 t_uscalar_t dl_err; 1224 queue_t *q = dsp->ds_wq; 1225 uint_t note = 1226 DL_NOTE_PROMISC_ON_PHYS | 1227 DL_NOTE_PROMISC_OFF_PHYS | 1228 DL_NOTE_PHYS_ADDR | 1229 DL_NOTE_LINK_UP | 1230 DL_NOTE_LINK_DOWN | 1231 DL_NOTE_CAPAB_RENEG; 1232 1233 if (MBLKL(mp) < sizeof (dl_notify_req_t)) { 1234 dl_err = DL_BADPRIM; 1235 goto failed; 1236 } 1237 1238 rw_enter(&dsp->ds_lock, RW_WRITER); 1239 if (dsp->ds_dlstate == DL_UNATTACHED || 1240 DL_ACK_PENDING(dsp->ds_dlstate)) { 1241 dl_err = DL_OUTSTATE; 1242 goto failed; 1243 } 1244 1245 if (dsp->ds_mip->mi_stat[MAC_STAT_IFSPEED]) 1246 note |= DL_NOTE_SPEED; 1247 1248 /* 1249 * Cache the notifications that are being enabled. 1250 */ 1251 dsp->ds_notifications = dlp->dl_notifications & note; 1252 rw_exit(&dsp->ds_lock); 1253 /* 1254 * The ACK carries all notifications regardless of which set is 1255 * being enabled. 1256 */ 1257 dlnotifyack(q, mp, note); 1258 1259 /* 1260 * Solicit DL_NOTIFY_IND messages for each enabled notification. 1261 */ 1262 rw_enter(&dsp->ds_lock, RW_READER); 1263 if (dsp->ds_notifications != 0) { 1264 rw_exit(&dsp->ds_lock); 1265 dld_str_notify_ind(dsp); 1266 } else { 1267 rw_exit(&dsp->ds_lock); 1268 } 1269 return (B_TRUE); 1270 failed: 1271 rw_exit(&dsp->ds_lock); 1272 dlerrorack(q, mp, DL_NOTIFY_REQ, dl_err, 0); 1273 return (B_FALSE); 1274 } 1275 1276 /* 1277 * DL_UINTDATA_REQ 1278 */ 1279 static boolean_t 1280 proto_unitdata_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 1281 { 1282 queue_t *q = dsp->ds_wq; 1283 dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)udlp; 1284 off_t off; 1285 size_t len, size; 1286 const uint8_t *addr; 1287 uint16_t sap; 1288 uint_t addr_length; 1289 mblk_t *bp, *cont; 1290 uint32_t start, stuff, end, value, flags; 1291 t_uscalar_t dl_err; 1292 1293 rw_enter(&dsp->ds_lock, RW_READER); 1294 1295 if (MBLKL(mp) < sizeof (dl_unitdata_req_t) || mp->b_cont == NULL) { 1296 dl_err = DL_BADPRIM; 1297 goto failed; 1298 } 1299 1300 if (dsp->ds_dlstate != DL_IDLE) { 1301 dl_err = DL_OUTSTATE; 1302 goto failed; 1303 } 1304 addr_length = dsp->ds_mip->mi_addr_length; 1305 1306 off = dlp->dl_dest_addr_offset; 1307 len = dlp->dl_dest_addr_length; 1308 1309 if (!MBLKIN(mp, off, len) || !IS_P2ALIGNED(off, sizeof (uint16_t))) { 1310 dl_err = DL_BADPRIM; 1311 goto failed; 1312 } 1313 1314 if (len != addr_length + sizeof (uint16_t)) { 1315 dl_err = DL_BADADDR; 1316 goto failed; 1317 } 1318 1319 addr = mp->b_rptr + off; 1320 sap = *(uint16_t *)(mp->b_rptr + off + addr_length); 1321 1322 /* 1323 * Check the length of the packet and the block types. 1324 */ 1325 size = 0; 1326 cont = mp->b_cont; 1327 for (bp = cont; bp != NULL; bp = bp->b_cont) { 1328 if (DB_TYPE(bp) != M_DATA) 1329 goto baddata; 1330 1331 size += MBLKL(bp); 1332 } 1333 1334 if (size > dsp->ds_mip->mi_sdu_max) 1335 goto baddata; 1336 1337 /* 1338 * Build a packet header. 1339 */ 1340 if ((bp = dls_header(dsp->ds_dc, addr, sap, dsp->ds_pri)) == NULL) { 1341 dl_err = DL_BADADDR; 1342 goto failed; 1343 } 1344 1345 /* 1346 * We no longer need the M_PROTO header, so free it. 1347 */ 1348 freeb(mp); 1349 1350 /* 1351 * Transfer the checksum offload information if it is present. 1352 */ 1353 hcksum_retrieve(cont, NULL, NULL, &start, &stuff, &end, &value, 1354 &flags); 1355 (void) hcksum_assoc(bp, NULL, NULL, start, stuff, end, value, flags, 1356 0); 1357 1358 /* 1359 * Link the payload onto the new header. 1360 */ 1361 ASSERT(bp->b_cont == NULL); 1362 bp->b_cont = cont; 1363 1364 str_mdata_fastpath_put(dsp, bp); 1365 rw_exit(&dsp->ds_lock); 1366 return (B_TRUE); 1367 failed: 1368 rw_exit(&dsp->ds_lock); 1369 dlerrorack(q, mp, DL_UNITDATA_REQ, dl_err, 0); 1370 return (B_FALSE); 1371 1372 baddata: 1373 rw_exit(&dsp->ds_lock); 1374 dluderrorind(q, mp, (void *)addr, len, DL_BADDATA, 0); 1375 return (B_FALSE); 1376 } 1377 1378 /* 1379 * DL_PASSIVE_REQ 1380 */ 1381 /* ARGSUSED */ 1382 static boolean_t 1383 proto_passive_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 1384 { 1385 t_uscalar_t dl_err; 1386 1387 rw_enter(&dsp->ds_lock, RW_WRITER); 1388 /* 1389 * If we've already become active by issuing an active primitive, 1390 * then it's too late to try to become passive. 1391 */ 1392 if (dsp->ds_passivestate == DLD_ACTIVE) { 1393 dl_err = DL_OUTSTATE; 1394 goto failed; 1395 } 1396 1397 if (MBLKL(mp) < sizeof (dl_passive_req_t)) { 1398 dl_err = DL_BADPRIM; 1399 goto failed; 1400 } 1401 1402 dsp->ds_passivestate = DLD_PASSIVE; 1403 rw_exit(&dsp->ds_lock); 1404 dlokack(dsp->ds_wq, mp, DL_PASSIVE_REQ); 1405 return (B_TRUE); 1406 failed: 1407 rw_exit(&dsp->ds_lock); 1408 dlerrorack(dsp->ds_wq, mp, DL_PASSIVE_REQ, dl_err, 0); 1409 return (B_FALSE); 1410 } 1411 1412 1413 /* 1414 * Catch-all handler. 1415 */ 1416 static boolean_t 1417 proto_req(dld_str_t *dsp, union DL_primitives *dlp, mblk_t *mp) 1418 { 1419 dlerrorack(dsp->ds_wq, mp, dlp->dl_primitive, DL_UNSUPPORTED, 0); 1420 return (B_FALSE); 1421 } 1422 1423 static void 1424 proto_poll_disable(dld_str_t *dsp) 1425 { 1426 mac_handle_t mh; 1427 1428 ASSERT(RW_WRITE_HELD(&dsp->ds_lock)); 1429 1430 if (!dsp->ds_polling) 1431 return; 1432 1433 /* 1434 * It should be impossible to enable raw mode if polling is turned on. 1435 */ 1436 ASSERT(dsp->ds_mode != DLD_RAW); 1437 1438 /* 1439 * Reset the resource_add callback. 1440 */ 1441 mh = dls_mac(dsp->ds_dc); 1442 mac_resource_set(mh, NULL, NULL); 1443 1444 /* 1445 * Set receive function back to default. 1446 */ 1447 dls_rx_set(dsp->ds_dc, (dsp->ds_mode == DLD_FASTPATH) ? 1448 dld_str_rx_fastpath : dld_str_rx_unitdata, (void *)dsp); 1449 1450 /* 1451 * Note that polling is disabled. 1452 */ 1453 dsp->ds_polling = B_FALSE; 1454 } 1455 1456 static boolean_t 1457 proto_poll_enable(dld_str_t *dsp, dl_capab_poll_t *pollp) 1458 { 1459 mac_handle_t mh; 1460 1461 ASSERT(RW_WRITE_HELD(&dsp->ds_lock)); 1462 ASSERT(!dsp->ds_polling); 1463 1464 /* 1465 * We cannot enable polling if raw mode 1466 * has been enabled. 1467 */ 1468 if (dsp->ds_mode == DLD_RAW) 1469 return (B_FALSE); 1470 1471 mh = dls_mac(dsp->ds_dc); 1472 1473 /* 1474 * Register resources. 1475 */ 1476 mac_resource_set(mh, (mac_resource_add_t)pollp->poll_ring_add, 1477 (void *)pollp->poll_rx_handle); 1478 mac_resources(mh); 1479 1480 /* 1481 * Set the receive function. 1482 */ 1483 dls_rx_set(dsp->ds_dc, (dls_rx_t)pollp->poll_rx, 1484 (void *)pollp->poll_rx_handle); 1485 1486 /* 1487 * Note that polling is enabled. This prevents further DLIOCHDRINFO 1488 * ioctls from overwriting the receive function pointer. 1489 */ 1490 dsp->ds_polling = B_TRUE; 1491 return (B_TRUE); 1492 } 1493 1494 /* 1495 * DL_CAPABILITY_ACK/DL_ERROR_ACK 1496 */ 1497 static boolean_t 1498 proto_capability_advertise(dld_str_t *dsp, mblk_t *mp) 1499 { 1500 dl_capability_ack_t *dlap; 1501 dl_capability_sub_t *dlsp; 1502 size_t subsize; 1503 dl_capab_poll_t poll; 1504 dl_capab_hcksum_t hcksum; 1505 dl_capab_zerocopy_t zcopy; 1506 uint8_t *ptr; 1507 uint32_t cksum; 1508 boolean_t poll_cap; 1509 queue_t *q = dsp->ds_wq; 1510 mblk_t *mp1; 1511 1512 ASSERT(RW_READ_HELD(&dsp->ds_lock)); 1513 1514 /* 1515 * Initially assume no capabilities. 1516 */ 1517 subsize = 0; 1518 1519 /* 1520 * Check if polling can be enabled on this interface. 1521 * If advertising DL_CAPAB_POLL has not been explicitly disabled 1522 * then reserve space for that capability. 1523 */ 1524 poll_cap = ((dsp->ds_mip->mi_poll & DL_CAPAB_POLL) && 1525 !(dld_opt & DLD_OPT_NO_POLL) && (dsp->ds_vid == VLAN_ID_NONE)); 1526 if (poll_cap) { 1527 subsize += sizeof (dl_capability_sub_t) + 1528 sizeof (dl_capab_poll_t); 1529 } 1530 1531 /* 1532 * If the MAC interface supports checksum offload then reserve 1533 * space for the DL_CAPAB_HCKSUM capability. 1534 */ 1535 if ((cksum = dsp->ds_mip->mi_cksum) != 0) { 1536 subsize += sizeof (dl_capability_sub_t) + 1537 sizeof (dl_capab_hcksum_t); 1538 } 1539 1540 /* 1541 * If DL_CAPAB_ZEROCOPY has not be explicitly disabled then 1542 * reserve space for it. 1543 */ 1544 if (!(dld_opt & DLD_OPT_NO_ZEROCOPY)) { 1545 subsize += sizeof (dl_capability_sub_t) + 1546 sizeof (dl_capab_zerocopy_t); 1547 } 1548 1549 /* 1550 * If there are no capabilities to advertise or if we 1551 * can't allocate a response, send a DL_ERROR_ACK. 1552 */ 1553 if (subsize == 0 || (mp1 = reallocb(mp, 1554 sizeof (dl_capability_ack_t) + subsize, 0)) == NULL) { 1555 rw_exit(&dsp->ds_lock); 1556 dlerrorack(q, mp, DL_CAPABILITY_REQ, DL_NOTSUPPORTED, 0); 1557 return (B_FALSE); 1558 } 1559 1560 mp = mp1; 1561 DB_TYPE(mp) = M_PROTO; 1562 mp->b_wptr = mp->b_rptr + sizeof (dl_capability_ack_t) + subsize; 1563 bzero(mp->b_rptr, MBLKL(mp)); 1564 dlap = (dl_capability_ack_t *)mp->b_rptr; 1565 dlap->dl_primitive = DL_CAPABILITY_ACK; 1566 dlap->dl_sub_offset = sizeof (dl_capability_ack_t); 1567 dlap->dl_sub_length = subsize; 1568 ptr = (uint8_t *)&dlap[1]; 1569 1570 /* 1571 * IP polling interface. 1572 */ 1573 if (poll_cap) { 1574 /* 1575 * Attempt to disable just in case this is a re-negotiation; 1576 * we need to become writer before doing so. 1577 */ 1578 if (!rw_tryupgrade(&dsp->ds_lock)) { 1579 rw_exit(&dsp->ds_lock); 1580 rw_enter(&dsp->ds_lock, RW_WRITER); 1581 } 1582 1583 /* 1584 * Check if polling state has changed after we re-acquired 1585 * the lock above, so that we don't mis-advertise it. 1586 */ 1587 poll_cap = ((dsp->ds_mip->mi_poll & DL_CAPAB_POLL) && 1588 !(dld_opt & DLD_OPT_NO_POLL) && 1589 (dsp->ds_vid == VLAN_ID_NONE)); 1590 1591 if (!poll_cap) { 1592 int poll_capab_size; 1593 1594 rw_downgrade(&dsp->ds_lock); 1595 1596 poll_capab_size = sizeof (dl_capability_sub_t) + 1597 sizeof (dl_capab_poll_t); 1598 1599 mp->b_wptr -= poll_capab_size; 1600 subsize -= poll_capab_size; 1601 dlap->dl_sub_length = subsize; 1602 } else { 1603 proto_poll_disable(dsp); 1604 1605 rw_downgrade(&dsp->ds_lock); 1606 1607 dlsp = (dl_capability_sub_t *)ptr; 1608 1609 dlsp->dl_cap = DL_CAPAB_POLL; 1610 dlsp->dl_length = sizeof (dl_capab_poll_t); 1611 ptr += sizeof (dl_capability_sub_t); 1612 1613 bzero(&poll, sizeof (dl_capab_poll_t)); 1614 poll.poll_version = POLL_VERSION_1; 1615 poll.poll_flags = POLL_CAPABLE; 1616 poll.poll_tx_handle = (uintptr_t)dsp; 1617 poll.poll_tx = (uintptr_t)str_mdata_fastpath_put; 1618 1619 dlcapabsetqid(&(poll.poll_mid), dsp->ds_rq); 1620 bcopy(&poll, ptr, sizeof (dl_capab_poll_t)); 1621 ptr += sizeof (dl_capab_poll_t); 1622 } 1623 } 1624 1625 ASSERT(RW_READ_HELD(&dsp->ds_lock)); 1626 1627 /* 1628 * TCP/IP checksum offload. 1629 */ 1630 if (cksum != 0) { 1631 dlsp = (dl_capability_sub_t *)ptr; 1632 1633 dlsp->dl_cap = DL_CAPAB_HCKSUM; 1634 dlsp->dl_length = sizeof (dl_capab_hcksum_t); 1635 ptr += sizeof (dl_capability_sub_t); 1636 1637 bzero(&hcksum, sizeof (dl_capab_hcksum_t)); 1638 hcksum.hcksum_version = HCKSUM_VERSION_1; 1639 hcksum.hcksum_txflags = cksum; 1640 1641 dlcapabsetqid(&(hcksum.hcksum_mid), dsp->ds_rq); 1642 bcopy(&hcksum, ptr, sizeof (dl_capab_hcksum_t)); 1643 ptr += sizeof (dl_capab_hcksum_t); 1644 } 1645 1646 /* 1647 * Zero copy 1648 */ 1649 if (!(dld_opt & DLD_OPT_NO_ZEROCOPY)) { 1650 dlsp = (dl_capability_sub_t *)ptr; 1651 1652 dlsp->dl_cap = DL_CAPAB_ZEROCOPY; 1653 dlsp->dl_length = sizeof (dl_capab_zerocopy_t); 1654 ptr += sizeof (dl_capability_sub_t); 1655 1656 bzero(&zcopy, sizeof (dl_capab_zerocopy_t)); 1657 zcopy.zerocopy_version = ZEROCOPY_VERSION_1; 1658 zcopy.zerocopy_flags = DL_CAPAB_VMSAFE_MEM; 1659 1660 dlcapabsetqid(&(zcopy.zerocopy_mid), dsp->ds_rq); 1661 bcopy(&zcopy, ptr, sizeof (dl_capab_zerocopy_t)); 1662 ptr += sizeof (dl_capab_zerocopy_t); 1663 } 1664 1665 ASSERT(ptr == mp->b_rptr + sizeof (dl_capability_ack_t) + subsize); 1666 1667 rw_exit(&dsp->ds_lock); 1668 qreply(q, mp); 1669 return (B_TRUE); 1670 } 1671